Skip to main content

luaur_code_gen/functions/
const_prop_in_inst.rs

1use crate::enums::ir_cmd::IrCmd;
2use crate::enums::ir_const_kind::IrConstKind;
3use crate::enums::ir_op_kind::IrOpKind;
4use crate::functions::compare_ir_utils::compare_f64_f64_ir_condition;
5use crate::functions::compare_ir_utils_alt_b::compare_i32_i32_ir_condition;
6use crate::functions::condition_op::condition_op;
7use crate::functions::fold_constants::fold_constants;
8use crate::functions::handle_builtin_effects::handle_builtin_effects;
9use crate::functions::is_gco::is_gco;
10use crate::functions::produces_dirty_high_register_bits::produces_dirty_high_register_bits;
11use crate::functions::replace_ir_utils::replace_ir_function_ir_op_ir_op;
12use crate::functions::replace_ir_utils_alt_b::replace_ir_function_ir_block_u32_ir_inst;
13use crate::functions::safe_integer_constant::safe_integer_constant;
14use crate::functions::substitute::substitute;
15use crate::functions::substitute_with_truncated_uint::substitute_with_truncated_uint;
16use crate::functions::try_get_operand_tag::try_get_operand_tag;
17use crate::functions::try_get_tag_for_typename::try_get_tag_for_typename;
18use crate::functions::vm_const_op::vm_const_op;
19use crate::macros::has_op_c::HAS_OP_C;
20use crate::macros::op_a::op_a;
21use crate::macros::op_b::op_b;
22use crate::macros::op_c::op_c;
23use crate::macros::op_d::op_d;
24use crate::macros::op_e::op_e;
25use crate::macros::op_f::op_f;
26use crate::macros::op_g::op_g;
27use crate::macros::opt_op_b::OPT_OP_B;
28use crate::macros::opt_op_c::OPT_OP_C;
29use crate::macros::opt_op_d::OPT_OP_D;
30use crate::records::array_value_entry::ArrayValueEntry;
31use crate::records::const_prop_state::ConstPropState;
32use crate::records::ir_block::IrBlock;
33use crate::records::ir_builder::IrBuilder;
34use crate::records::ir_function::IrFunction;
35use crate::records::ir_inst::IrInst;
36use crate::records::ir_op::IrOp;
37use crate::records::node_slot_state::NodeSlotState;
38use crate::records::numbered_instruction::NumberedInstruction;
39use crate::type_aliases::ir_ops::IrOps;
40use luaur_common::enums::luau_builtin_function::LuauBuiltinFunction;
41use luaur_vm::enums::lua_type::lua_Type;
42use luaur_vm::macros::getstr::getstr;
43use luaur_vm::macros::tsvalue::tsvalue;
44use luaur_vm::macros::ttisvector::ttisvector;
45use luaur_vm::macros::vvalue::vvalue;
46use luaur_vm::type_aliases::t_value::TValue;
47
48fn const_prop_make_inst(cmd: IrCmd, ops: &[IrOp]) -> IrInst {
49    let mut ir_ops = IrOps::new();
50    for &op in ops {
51        ir_ops.push(op);
52    }
53
54    IrInst {
55        cmd,
56        ops: ir_ops,
57        ..IrInst::default()
58    }
59}
60
61fn tag_for_vm_const_typename(function: &IrFunction, source: IrOp, for_typeof: bool) -> Option<u8> {
62    if source.kind() != IrOpKind::VmConst || function.proto.is_null() {
63        return None;
64    }
65
66    unsafe {
67        let constants = (*function.proto).k;
68        if constants.is_null() {
69            return None;
70        }
71
72        let value = constants.add(vm_const_op(source) as usize);
73        if (*value).tt != lua_Type::LUA_TSTRING as core::ffi::c_int {
74            return None;
75        }
76
77        let string = tsvalue!(value as *const TValue);
78        let name = core::ffi::CStr::from_ptr(getstr(string)).to_str().ok()?;
79        let tag = try_get_tag_for_typename(name, for_typeof);
80
81        if tag == 0xff {
82            None
83        } else {
84            Some(tag)
85        }
86    }
87}
88
89fn type_name_tag_comparison(
90    function: &IrFunction,
91    lhs_op: IrOp,
92    rhs_op: IrOp,
93) -> Option<(IrOp, u8)> {
94    if lhs_op.kind() != IrOpKind::Inst || rhs_op.kind() != IrOpKind::Inst {
95        return None;
96    }
97
98    let mut lhs = function.instructions.get(lhs_op.index() as usize)?.clone();
99    let mut rhs = function.instructions.get(rhs_op.index() as usize)?.clone();
100
101    if lhs.cmd != IrCmd::GET_TYPE && lhs.cmd != IrCmd::GET_TYPEOF {
102        return None;
103    }
104
105    if rhs.cmd != IrCmd::LOAD_POINTER {
106        return None;
107    }
108
109    let source = op_a(&mut lhs);
110    let tag = tag_for_vm_const_typename(function, op_a(&mut rhs), lhs.cmd == IrCmd::GET_TYPEOF)?;
111
112    Some((source, tag))
113}
114
115pub fn const_prop_in_inst(
116    state: &mut ConstPropState,
117    build: &mut IrBuilder,
118    function: &mut IrFunction,
119    block: &mut IrBlock,
120    inst: &mut IrInst,
121    index: u32,
122) {
123    match inst.cmd {
124        IrCmd::LOAD_TAG => {
125            let source = op_a(inst);
126            let tag = state.try_get_tag(source);
127            if tag != 0xff {
128                let tag_op = build.const_tag(tag);
129                substitute(function, inst, tag_op);
130            } else if source.kind() == IrOpKind::VmReg {
131                if state.substitute_tag_load_with_t_value_data(build, inst) {
132                    return;
133                }
134
135                if luaur_common::FFlag::LuauCodegenLoadPropagateOrigin.get() {
136                    state.try_redirect_vm_reg_load_to_t_value_origin(inst);
137                }
138
139                state.substitute_or_record_vm_reg_load(inst);
140            }
141        }
142        IrCmd::LOAD_POINTER => {
143            let source = op_a(inst);
144            if source.kind() == IrOpKind::VmReg {
145                if state.substitute_or_record_value_load_with_t_value_data(build, inst) {
146                    return;
147                }
148
149                if luaur_common::FFlag::LuauCodegenLoadPropagateOrigin.get() {
150                    state.try_redirect_vm_reg_load_to_t_value_origin(inst);
151                }
152
153                state.substitute_or_record_vm_reg_load(inst);
154            }
155        }
156        IrCmd::LOAD_DOUBLE => {
157            let source = op_a(inst);
158            let value = state.try_get_value(source);
159
160            if function.as_double_op(value).is_some() {
161                substitute(function, inst, value);
162            } else if source.kind() == IrOpKind::VmReg {
163                if state.substitute_or_record_value_load_with_t_value_data(build, inst) {
164                    return;
165                }
166
167                if luaur_common::FFlag::LuauCodegenLoadPropagateOrigin.get() {
168                    state.try_redirect_vm_reg_load_to_t_value_origin(inst);
169                }
170
171                state.substitute_or_record_vm_reg_load(inst);
172            } else {
173                state.substitute_or_record(inst, index);
174            }
175        }
176        IrCmd::LOAD_INT => {
177            let source = op_a(inst);
178            let value = state.try_get_value(source);
179
180            if function.as_int_op(value).is_some() {
181                substitute(function, inst, value);
182            } else if source.kind() == IrOpKind::VmReg {
183                if state.substitute_or_record_value_load_with_t_value_data(build, inst) {
184                    return;
185                }
186
187                if luaur_common::FFlag::LuauCodegenLoadPropagateOrigin.get() {
188                    state.try_redirect_vm_reg_load_to_t_value_origin(inst);
189                }
190
191                state.substitute_or_record_vm_reg_load(inst);
192            } else {
193                state.substitute_or_record(inst, index);
194            }
195        }
196        IrCmd::LOAD_INT64 => {
197            let source = op_a(inst);
198            let value = state.try_get_value(source);
199
200            if function.as_int_64_op(value).is_some() {
201                substitute(function, inst, value);
202            } else if source.kind() == IrOpKind::VmReg {
203                if state.substitute_or_record_value_load_with_t_value_data(build, inst) {
204                    return;
205                }
206
207                if luaur_common::FFlag::LuauCodegenLoadPropagateOrigin.get() {
208                    state.try_redirect_vm_reg_load_to_t_value_origin(inst);
209                }
210
211                state.substitute_or_record_vm_reg_load(inst);
212            } else {
213                state.substitute_or_record(inst, index);
214            }
215        }
216        IrCmd::LOAD_TVALUE => {
217            let source = op_a(inst);
218            if source.kind() == IrOpKind::VmReg {
219                if !state.substitute_or_record_vm_reg_load(inst) && !HAS_OP_C!(inst) {
220                    let tag = state.try_get_tag(source);
221                    if tag != 0xff {
222                        let offset = build.const_int(0);
223                        let tag_op = build.const_tag(tag);
224                        let mut ops = crate::type_aliases::ir_ops::IrOps::new();
225                        ops.push(source);
226                        ops.push(offset);
227                        ops.push(tag_op);
228                        replace_ir_function_ir_block_u32_ir_inst(
229                            function,
230                            block,
231                            index,
232                            IrInst {
233                                cmd: IrCmd::LOAD_TVALUE,
234                                ops,
235                                ..IrInst::default()
236                            },
237                        );
238                    }
239                }
240            } else if source.kind() == IrOpKind::Inst {
241                let source_inst = function.instructions[source.index() as usize].clone();
242
243                if source_inst.cmd == IrCmd::GET_SLOT_NODE_ADDR {
244                    if let Some(prev_idx) = state.hash_value_cache.find(&source.index()).copied() {
245                        if prev_idx != crate::records::ir_data::k_invalid_inst_idx {
246                            let prev = function.instructions[prev_idx as usize].clone();
247
248                            if prev.cmd == IrCmd::LOAD_TVALUE {
249                                if prev.use_count != 0 {
250                                    substitute(
251                                        function,
252                                        inst,
253                                        IrOp::ir_op_ir_op_kind_u32(IrOpKind::Inst, prev_idx),
254                                    );
255                                }
256                            } else if prev.cmd == IrCmd::STORE_SPLIT_TVALUE {
257                                state
258                                    .inst_tag
259                                    .try_insert(index, function.tag_op(op_b(prev.clone())));
260                                state.inst_value.try_insert(index, op_c(prev));
261                            } else if luaur_common::FFlag::LuauCodegenExtraTableOpts.get()
262                                && prev.cmd == IrCmd::STORE_TVALUE
263                            {
264                                let arg = function.as_inst_op(op_b(prev.clone()));
265                                if !arg.is_null() && unsafe { (*arg).use_count } != 0 {
266                                    substitute(function, inst, op_b(prev));
267                                }
268                            }
269
270                            return;
271                        }
272                    }
273
274                    *state.hash_value_cache.get_or_insert(source.index()) = index;
275                } else if source_inst.cmd == IrCmd::GET_ARR_ADDR {
276                    let mut source_addr = source_inst;
277                    let offset_op = state.get_combined_array_load_offset_op(
278                        &mut source_addr,
279                        OPT_OP_B(inst.clone()),
280                    );
281
282                    if let Some(entry) = state
283                        .array_value_cache
284                        .iter()
285                        .find(|entry| entry.pointer == source.index() && entry.offset == offset_op)
286                        .copied()
287                    {
288                        if entry.value != crate::records::ir_data::k_invalid_inst_idx {
289                            let prev = function.instructions[entry.value as usize].clone();
290
291                            if prev.cmd == IrCmd::LOAD_TVALUE {
292                                if prev.use_count != 0 {
293                                    substitute(
294                                        function,
295                                        inst,
296                                        IrOp::ir_op_ir_op_kind_u32(IrOpKind::Inst, entry.value),
297                                    );
298                                }
299                            } else if prev.cmd == IrCmd::STORE_SPLIT_TVALUE {
300                                state
301                                    .inst_tag
302                                    .try_insert(index, function.tag_op(op_b(prev.clone())));
303                                state.inst_value.try_insert(index, op_c(prev));
304                            } else if luaur_common::FFlag::LuauCodegenExtraTableOpts.get()
305                                && prev.cmd == IrCmd::STORE_TVALUE
306                            {
307                                let arg = function.as_inst_op(op_b(prev.clone()));
308                                if !arg.is_null() && unsafe { (*arg).use_count } != 0 {
309                                    substitute(function, inst, op_b(prev));
310                                }
311                            }
312
313                            return;
314                        }
315                    }
316
317                    state.array_value_cache.push(ArrayValueEntry {
318                        pointer: source.index(),
319                        offset: offset_op,
320                        value: index,
321                    });
322                } else {
323                    state.substitute_or_record(inst, index);
324                }
325            }
326        }
327        IrCmd::LOAD_FLOAT => {
328            let source = op_a(inst);
329            if source.kind() == IrOpKind::VmReg {
330                let offset = function.int_op(op_b(inst.clone()));
331
332                if let Some(subst) =
333                    state.find_substitute_component_load_from_store_vector(build, source, offset)
334                {
335                    substitute(function, inst, subst);
336                    return;
337                }
338
339                if let Some(prev_idx_ptr) =
340                    state.get_previous_versioned_load_index(IrCmd::LOAD_TVALUE, source)
341                {
342                    let mut prev_idx = unsafe { *prev_idx_ptr };
343                    let prev = function.instructions[prev_idx as usize].clone();
344
345                    if prev.cmd == IrCmd::TAG_VECTOR {
346                        let mut prev_for_arg = prev.clone();
347                        let prev_arg = op_a(&mut prev_for_arg);
348                        if !function.as_inst_op(prev_arg).is_null() {
349                            prev_idx = prev_arg.index();
350                        }
351                    }
352
353                    let value = function.instructions[prev_idx as usize].clone();
354                    let byte_offset = offset as u32;
355                    crate::macros::codegen_assert::CODEGEN_ASSERT!(byte_offset % 4 == 0);
356
357                    let component = byte_offset / 4;
358                    crate::macros::codegen_assert::CODEGEN_ASSERT!(component <= 3);
359
360                    if value.cmd == IrCmd::LOAD_TVALUE {
361                        let mut value_for_source = value.clone();
362                        let value_source = op_a(&mut value_for_source);
363
364                        if value_source.kind() == IrOpKind::VmConst && !function.proto.is_null() {
365                            let tv = unsafe {
366                                (*function.proto).k.add(vm_const_op(value_source) as usize)
367                            };
368
369                            if ttisvector!(tv as *const TValue) {
370                                let v = unsafe { vvalue!(tv as *const TValue) };
371                                let subst = build.const_double(v[component as usize] as f64);
372                                substitute(function, inst, subst);
373                                return;
374                            }
375                        } else if value_source.kind() == IrOpKind::VmReg {
376                            let prev_op = IrOp::ir_op_ir_op_kind_u32(IrOpKind::Inst, prev_idx);
377                            if state.try_get_reg_link(prev_op).is_some() {
378                                if let Some(subst) = state
379                                    .find_substitute_component_load_from_store_vector(
380                                        build,
381                                        value_source,
382                                        offset,
383                                    )
384                                {
385                                    substitute(function, inst, subst);
386                                    return;
387                                }
388                            }
389                        }
390                    }
391
392                    let mut ops = crate::type_aliases::ir_ops::IrOps::new();
393                    ops.push(IrOp::ir_op_ir_op_kind_u32(IrOpKind::Inst, prev_idx));
394                    ops.push(build.const_int(component as i32));
395
396                    replace_ir_function_ir_block_u32_ir_inst(
397                        function,
398                        block,
399                        index,
400                        IrInst {
401                            cmd: IrCmd::EXTRACT_VEC,
402                            ops,
403                            ..IrInst::default()
404                        },
405                    );
406
407                    state.substitute_or_record(&mut function.instructions[index as usize], index);
408                    return;
409                }
410
411                state.substitute_or_record_vm_reg_load(inst);
412            } else {
413                state.substitute_or_record(inst, index);
414            }
415        }
416        IrCmd::STORE_TAG => {
417            let target = op_a(inst);
418            if target.kind() == IrOpKind::VmReg {
419                let mut active_load_cmd = IrCmd::NOP;
420                let mut active_load_value = !0u32;
421                let value = op_b(inst.clone());
422                if value.kind() == IrOpKind::Constant {
423                    let tag = function.tag_op(value);
424                    (active_load_cmd, active_load_value) =
425                        state.get_previous_versioned_load_for_tag(tag, target);
426
427                    if state.try_get_tag(target) == tag {
428                        crate::functions::kill_ir_utils::kill_ir_function_ir_inst(function, inst);
429                    } else {
430                        state.save_tag(target, tag);
431                        if tag == lua_Type::LUA_TNIL as u8 {
432                            state.invalidate_value(target);
433                        }
434                    }
435                } else {
436                    state.invalidate_tag(target);
437                }
438
439                if active_load_value != !0u32 {
440                    let key = state.versioned_vm_reg_load_ir_cmd_ir_op(active_load_cmd, target);
441                    *state.value_map.get_or_insert(key) = active_load_value;
442                }
443            }
444        }
445        IrCmd::STORE_POINTER => {
446            let target = op_a(inst);
447            if target.kind() == IrOpKind::VmReg {
448                let value = op_b(inst.clone());
449                if value.kind() == IrOpKind::Inst {
450                    if let Some(prev_idx) =
451                        state.get_previous_versioned_load_index(IrCmd::LOAD_POINTER, target)
452                    {
453                        if unsafe { *prev_idx } == value.index() {
454                            crate::functions::kill_ir_utils::kill_ir_function_ir_inst(
455                                function, inst,
456                            );
457                            return;
458                        }
459                    }
460                }
461
462                state.invalidate_value(target);
463                if value.kind() == IrOpKind::Inst {
464                    state.forward_vm_reg_store_to_load(inst, IrCmd::LOAD_POINTER);
465
466                    let value_ptr = function.as_inst_op(value);
467                    if !luaur_common::FFlag::LuauCodegenExtraTableOpts.get()
468                        && !value_ptr.is_null()
469                        && unsafe { (*value_ptr).cmd } == IrCmd::NEW_TABLE
470                    {
471                        if let Some(info) = state.try_get_register_info(target) {
472                            unsafe {
473                                let array_size_op = (&(*value_ptr).ops)[0];
474                                (*info).known_not_readonly_deprecated = true;
475                                (*info).known_no_metatable_deprecated = true;
476                                (*info).known_table_array_size_deprecated =
477                                    function.uint_op(array_size_op) as i32;
478                            }
479                        }
480                    }
481                }
482            }
483        }
484        IrCmd::STORE_DOUBLE => {
485            let target = op_a(inst);
486            if target.kind() == IrOpKind::VmReg {
487                let value = op_b(inst.clone());
488                if value.kind() == IrOpKind::Constant {
489                    if state.try_get_value(target) == value {
490                        crate::functions::kill_ir_utils::kill_ir_function_ir_inst(function, inst);
491                    } else {
492                        state.save_value(target, value);
493                    }
494                } else {
495                    if value.kind() == IrOpKind::Inst {
496                        if let Some(prev_idx) =
497                            state.get_previous_versioned_load_index(IrCmd::LOAD_DOUBLE, target)
498                        {
499                            if unsafe { *prev_idx } == value.index() {
500                                crate::functions::kill_ir_utils::kill_ir_function_ir_inst(
501                                    function, inst,
502                                );
503                                return;
504                            }
505                        }
506                    }
507
508                    state.invalidate_value(target);
509                    state.forward_vm_reg_store_to_load(inst, IrCmd::LOAD_DOUBLE);
510                }
511            }
512        }
513        IrCmd::STORE_INT => {
514            let stored = op_b(inst.clone());
515            let stored_inst = function.as_inst_op(stored);
516            if !stored_inst.is_null() && unsafe { (*stored_inst).cmd } == IrCmd::TRUNCATE_UINT {
517                let mut stored_inst_clone = unsafe { (*stored_inst).clone() };
518                let replacement = op_a(&mut stored_inst_clone);
519                replace_ir_function_ir_op_ir_op(function, &mut inst.ops[1], replacement);
520            }
521
522            let target = op_a(inst);
523            if target.kind() == IrOpKind::VmReg {
524                let value = op_b(inst.clone());
525                if value.kind() == IrOpKind::Constant {
526                    if state.try_get_value(target) == value {
527                        crate::functions::kill_ir_utils::kill_ir_function_ir_inst(function, inst);
528                    } else {
529                        state.save_value(target, value);
530                    }
531                } else {
532                    if value.kind() == IrOpKind::Inst {
533                        if let Some(prev_idx) =
534                            state.get_previous_versioned_load_index(IrCmd::LOAD_INT, target)
535                        {
536                            if unsafe { *prev_idx } == value.index() {
537                                crate::functions::kill_ir_utils::kill_ir_function_ir_inst(
538                                    function, inst,
539                                );
540                                return;
541                            }
542                        }
543                    }
544
545                    state.invalidate_value(target);
546                    state.forward_vm_reg_store_to_load(inst, IrCmd::LOAD_INT);
547                }
548            }
549        }
550        IrCmd::STORE_INT64 => {
551            let target = op_a(inst);
552            if target.kind() == IrOpKind::VmReg {
553                let value = op_b(inst.clone());
554                if value.kind() == IrOpKind::Constant {
555                    if state.try_get_value(target) == value {
556                        crate::functions::kill_ir_utils::kill_ir_function_ir_inst(function, inst);
557                    } else {
558                        state.save_value(target, value);
559                    }
560                } else {
561                    if value.kind() == IrOpKind::Inst {
562                        if let Some(prev_idx) =
563                            state.get_previous_versioned_load_index(IrCmd::LOAD_INT64, target)
564                        {
565                            if unsafe { *prev_idx } == value.index() {
566                                crate::functions::kill_ir_utils::kill_ir_function_ir_inst(
567                                    function, inst,
568                                );
569                                return;
570                            }
571                        }
572                    }
573
574                    state.invalidate_value(target);
575                    state.forward_vm_reg_store_to_load(inst, IrCmd::LOAD_INT64);
576                }
577            }
578        }
579        IrCmd::STORE_VECTOR => {
580            let target = op_a(inst);
581            if target.kind() == IrOpKind::VmReg {
582                state.invalidate_value(target);
583
584                let reg = crate::functions::vm_reg_op::vm_reg_op(target) as usize;
585                let captured_regs = unsafe { &(*state.function).cfg.captured.regs };
586                if (captured_regs[reg / 64] & (1u64 << (reg % 64))) == 0 {
587                    let key = state.versioned_vm_reg_load_ir_cmd_ir_op(IrCmd::LOAD_FLOAT, target);
588                    *state.value_map.get_or_insert(key) = index;
589                }
590            }
591        }
592        IrCmd::STORE_TVALUE => {
593            let target = op_a(inst);
594            if target.kind() == IrOpKind::VmReg || target.kind() == IrOpKind::Inst {
595                let stored = op_b(inst.clone());
596
597                if target.kind() == IrOpKind::VmReg {
598                    if stored.kind() == IrOpKind::Inst {
599                        if let Some(prev_idx) =
600                            state.get_previous_versioned_load_index(IrCmd::LOAD_TVALUE, target)
601                        {
602                            if unsafe { *prev_idx } == stored.index() {
603                                crate::functions::kill_ir_utils::kill_ir_function_ir_inst(
604                                    function, inst,
605                                );
606                                return;
607                            }
608                        }
609                    }
610
611                    state.invalidate_ir_op(target);
612                }
613
614                let mut tag = state.try_get_tag(stored);
615                if tag == 0xff {
616                    tag = try_get_operand_tag(function, stored).unwrap_or(0xff);
617                }
618
619                let mut value = state.try_get_value(stored);
620
621                if target.kind() == IrOpKind::VmReg {
622                    if tag != 0xff {
623                        state.save_tag(target, tag);
624                    }
625
626                    if value.kind() != IrOpKind::None {
627                        state.save_value(target, value);
628                    }
629                }
630
631                if target.kind() == IrOpKind::Inst {
632                    let target_inst = function.instructions[target.index() as usize].clone();
633                    state.invalidate_table_store_location(target_inst, OPT_OP_C(inst.clone()), tag);
634                }
635
636                let mut active_load_cmd = IrCmd::NOP;
637                let mut active_load_value = !0u32;
638
639                if tag != 0xff
640                    && value.kind() == IrOpKind::None
641                    && state.try_get_reg_link(stored).is_some()
642                {
643                    let arg_ptr = function.as_inst_op(stored);
644                    if !arg_ptr.is_null() {
645                        let mut arg = unsafe { (*arg_ptr).clone() };
646                        let arg_source = op_a(&mut arg);
647                        if arg.cmd == IrCmd::LOAD_TVALUE && arg_source.kind() == IrOpKind::VmReg {
648                            let (cmd, idx) =
649                                state.get_previous_versioned_load_for_tag(tag, arg_source);
650                            if idx != !0u32 {
651                                active_load_cmd = cmd;
652                                active_load_value = idx;
653                                value = crate::records::ir_op::IrOp::ir_op_ir_op_kind_u32(
654                                    IrOpKind::Inst,
655                                    idx,
656                                );
657                            }
658                        }
659                    }
660                }
661
662                let can_split_tvalue_store = if tag == lua_Type::LUA_TBOOLEAN as u8 {
663                    value.kind() == IrOpKind::Inst || function.as_int_op(value).is_some()
664                } else if tag == lua_Type::LUA_TNUMBER as u8 {
665                    value.kind() == IrOpKind::Inst || function.as_double_op(value).is_some()
666                } else if tag == lua_Type::LUA_TINTEGER as u8 {
667                    value.kind() == IrOpKind::Inst || function.as_int_64_op(value).is_some()
668                } else {
669                    tag != 0xff && is_gco(tag) && value.kind() == IrOpKind::Inst
670                };
671
672                if can_split_tvalue_store {
673                    let tag_op = build.const_tag(tag);
674                    let mut ops = crate::type_aliases::ir_ops::IrOps::new();
675                    ops.push(target);
676                    ops.push(tag_op);
677                    ops.push(value);
678                    if HAS_OP_C!(inst) {
679                        ops.push(op_c(inst.clone()));
680                    }
681
682                    let replacement = IrInst {
683                        cmd: IrCmd::STORE_SPLIT_TVALUE,
684                        ops,
685                        ..IrInst::default()
686                    };
687                    let replacement_offset = OPT_OP_D(replacement.clone());
688
689                    replace_ir_function_ir_block_u32_ir_inst(function, block, index, replacement);
690
691                    if target.kind() == IrOpKind::VmReg && active_load_value != !0u32 {
692                        let reg = crate::functions::vm_reg_op::vm_reg_op(target) as usize;
693                        let versioned_reg = crate::records::ir_op::IrOp::ir_op_ir_op_kind_u32(
694                            IrOpKind::VmReg,
695                            (reg as u32) | (state.regs[reg].version << 8),
696                        );
697                        let mut ops = crate::type_aliases::ir_ops::IrOps::new();
698                        ops.push(versioned_reg);
699                        let key = IrInst {
700                            cmd: active_load_cmd,
701                            ops,
702                            ..IrInst::default()
703                        };
704                        *state.value_map.get_or_insert(key) = active_load_value;
705                    }
706
707                    if target.kind() == IrOpKind::Inst {
708                        let target_ptr =
709                            &mut function.instructions[target.index() as usize] as *mut IrInst;
710                        unsafe {
711                            state.forward_table_store_to_load(
712                                &mut *target_ptr,
713                                replacement_offset,
714                                index,
715                            );
716                        }
717                    }
718                } else if target.kind() == IrOpKind::VmReg {
719                    state.forward_vm_reg_store_to_load(inst, IrCmd::LOAD_TVALUE);
720                } else if luaur_common::FFlag::LuauCodegenExtraTableOpts.get()
721                    && target.kind() == IrOpKind::Inst
722                {
723                    let offset = OPT_OP_C(inst.clone());
724                    let target_ptr =
725                        &mut function.instructions[target.index() as usize] as *mut IrInst;
726                    unsafe {
727                        state.forward_table_store_to_load(&mut *target_ptr, offset, index);
728                    }
729                }
730            }
731        }
732        IrCmd::STORE_SPLIT_TVALUE => {
733            let target = op_a(inst);
734            if target.kind() == IrOpKind::VmReg {
735                state.invalidate_ir_op(target);
736
737                let tag = function.tag_op(op_b(inst.clone()));
738                state.save_tag(target, tag);
739
740                let value = op_c(inst.clone());
741                if value.kind() == IrOpKind::Constant {
742                    state.save_value(target, value);
743                }
744            } else if target.kind() == IrOpKind::Inst {
745                let tag = function.tag_op(op_b(inst.clone()));
746                let offset = OPT_OP_D(inst.clone());
747                let target_inst = function.instructions[target.index() as usize].clone();
748                state.invalidate_table_store_location(target_inst, offset, tag);
749
750                let target_ptr = &mut function.instructions[target.index() as usize] as *mut IrInst;
751                unsafe {
752                    state.forward_table_store_to_load(&mut *target_ptr, offset, index);
753                }
754            }
755        }
756        IrCmd::GET_UPVALUE => {
757            state.substitute_or_record_vm_upvalue_load(inst);
758        }
759        IrCmd::SET_UPVALUE => {
760            state.forward_vm_upvalue_store_to_load(inst);
761
762            let source = op_b(inst.clone());
763            let tag = state.try_get_tag(source);
764            if tag != 0xff {
765                let tag_op = build.const_tag(tag);
766                replace_ir_function_ir_op_ir_op(function, &mut inst.ops[2], tag_op);
767            }
768        }
769        IrCmd::INT64_TO_NUM | IrCmd::INT_TO_NUM => {
770            state.substitute_or_record(inst, index);
771        }
772        IrCmd::ADD_NUM | IrCmd::SUB_NUM => {
773            let rhs = op_b(inst.clone());
774            let rhs = if rhs.kind() == IrOpKind::Constant {
775                rhs
776            } else {
777                state.try_get_value(rhs)
778            };
779
780            if let Some(k) = function.as_double_op(rhs) {
781                if k == 0.0 && k.is_sign_negative() == (inst.cmd == IrCmd::ADD_NUM) {
782                    let lhs = op_a(inst);
783                    substitute(function, inst, lhs);
784                } else {
785                    state.substitute_or_record(inst, index);
786                }
787            } else {
788                state.substitute_or_record(inst, index);
789            }
790        }
791        IrCmd::MUL_NUM => {
792            let rhs = op_b(inst.clone());
793            let rhs = if rhs.kind() == IrOpKind::Constant {
794                rhs
795            } else {
796                state.try_get_value(rhs)
797            };
798
799            if let Some(k) = function.as_double_op(rhs) {
800                if k == 1.0 {
801                    let lhs = op_a(inst);
802                    substitute(function, inst, lhs);
803                } else if k == 2.0 {
804                    let lhs = op_a(inst);
805                    let mut ops = crate::type_aliases::ir_ops::IrOps::new();
806                    ops.push(lhs);
807                    ops.push(lhs);
808                    replace_ir_function_ir_block_u32_ir_inst(
809                        function,
810                        block,
811                        index,
812                        IrInst {
813                            cmd: IrCmd::ADD_NUM,
814                            ops,
815                            ..IrInst::default()
816                        },
817                    );
818                } else if k == -1.0 {
819                    let lhs = op_a(inst);
820                    let mut ops = crate::type_aliases::ir_ops::IrOps::new();
821                    ops.push(lhs);
822                    replace_ir_function_ir_block_u32_ir_inst(
823                        function,
824                        block,
825                        index,
826                        IrInst {
827                            cmd: IrCmd::UNM_NUM,
828                            ops,
829                            ..IrInst::default()
830                        },
831                    );
832                } else {
833                    state.substitute_or_record(inst, index);
834                }
835            } else {
836                state.substitute_or_record(inst, index);
837            }
838        }
839        IrCmd::DIV_NUM => {
840            let rhs = op_b(inst.clone());
841            let rhs = if rhs.kind() == IrOpKind::Constant {
842                rhs
843            } else {
844                state.try_get_value(rhs)
845            };
846
847            if let Some(k) = function.as_double_op(rhs) {
848                if k == 1.0 {
849                    let lhs = op_a(inst);
850                    substitute(function, inst, lhs);
851                } else if k == -1.0 {
852                    let lhs = op_a(inst);
853                    let mut ops = crate::type_aliases::ir_ops::IrOps::new();
854                    ops.push(lhs);
855                    replace_ir_function_ir_block_u32_ir_inst(
856                        function,
857                        block,
858                        index,
859                        IrInst {
860                            cmd: IrCmd::UNM_NUM,
861                            ops,
862                            ..IrInst::default()
863                        },
864                    );
865                } else {
866                    let exp = k.log2();
867                    if k > 0.0
868                        && k.is_finite()
869                        && exp.fract() == 0.0
870                        && (-1000.0..=1000.0).contains(&exp)
871                    {
872                        let lhs = op_a(inst);
873                        let reciprocal = build.const_double(1.0 / k);
874                        let mut ops = crate::type_aliases::ir_ops::IrOps::new();
875                        ops.push(lhs);
876                        ops.push(reciprocal);
877                        replace_ir_function_ir_block_u32_ir_inst(
878                            function,
879                            block,
880                            index,
881                            IrInst {
882                                cmd: IrCmd::MUL_NUM,
883                                ops,
884                                ..IrInst::default()
885                            },
886                        );
887                    } else {
888                        state.substitute_or_record(inst, index);
889                    }
890                }
891            } else {
892                state.substitute_or_record(inst, index);
893            }
894        }
895        IrCmd::ADD_FLOAT | IrCmd::SUB_FLOAT => {
896            let rhs = op_b(inst.clone());
897            let rhs = if rhs.kind() == IrOpKind::Constant {
898                rhs
899            } else {
900                state.try_get_value(rhs)
901            };
902
903            if let Some(k) = function.as_double_op(rhs) {
904                let kf = k as f32;
905                if kf == 0.0 && kf.is_sign_negative() == (inst.cmd == IrCmd::ADD_FLOAT) {
906                    let lhs = op_a(inst);
907                    substitute(function, inst, lhs);
908                } else {
909                    state.substitute_or_record(inst, index);
910                }
911            } else {
912                state.substitute_or_record(inst, index);
913            }
914        }
915        IrCmd::MUL_FLOAT => {
916            let rhs = op_b(inst.clone());
917            let rhs = if rhs.kind() == IrOpKind::Constant {
918                rhs
919            } else {
920                state.try_get_value(rhs)
921            };
922
923            if let Some(k) = function.as_double_op(rhs) {
924                let kf = k as f32;
925                if kf == 1.0 {
926                    let lhs = op_a(inst);
927                    substitute(function, inst, lhs);
928                } else if kf == 2.0 {
929                    let lhs = op_a(inst);
930                    let mut ops = IrOps::new();
931                    ops.push(lhs);
932                    ops.push(lhs);
933                    replace_ir_function_ir_block_u32_ir_inst(
934                        function,
935                        block,
936                        index,
937                        IrInst {
938                            cmd: IrCmd::ADD_FLOAT,
939                            ops,
940                            ..IrInst::default()
941                        },
942                    );
943                } else if kf == -1.0 {
944                    let lhs = op_a(inst);
945                    let mut ops = IrOps::new();
946                    ops.push(lhs);
947                    replace_ir_function_ir_block_u32_ir_inst(
948                        function,
949                        block,
950                        index,
951                        IrInst {
952                            cmd: IrCmd::UNM_FLOAT,
953                            ops,
954                            ..IrInst::default()
955                        },
956                    );
957                } else {
958                    state.substitute_or_record(inst, index);
959                }
960            } else {
961                state.substitute_or_record(inst, index);
962            }
963        }
964        IrCmd::DIV_FLOAT => {
965            let rhs = op_b(inst.clone());
966            let rhs = if rhs.kind() == IrOpKind::Constant {
967                rhs
968            } else {
969                state.try_get_value(rhs)
970            };
971
972            if let Some(k) = function.as_double_op(rhs) {
973                let kf = k as f32;
974                if kf == 1.0 {
975                    let lhs = op_a(inst);
976                    substitute(function, inst, lhs);
977                } else if kf == -1.0 {
978                    let lhs = op_a(inst);
979                    let mut ops = IrOps::new();
980                    ops.push(lhs);
981                    replace_ir_function_ir_block_u32_ir_inst(
982                        function,
983                        block,
984                        index,
985                        IrInst {
986                            cmd: IrCmd::UNM_FLOAT,
987                            ops,
988                            ..IrInst::default()
989                        },
990                    );
991                } else {
992                    let exp = kf.log2();
993                    if kf > 0.0
994                        && kf.is_finite()
995                        && exp.fract() == 0.0
996                        && (-1000.0..=1000.0).contains(&exp)
997                    {
998                        let lhs = op_a(inst);
999                        let reciprocal = build.const_double((1.0f32 / kf) as f64);
1000                        let mut ops = IrOps::new();
1001                        ops.push(lhs);
1002                        ops.push(reciprocal);
1003                        replace_ir_function_ir_block_u32_ir_inst(
1004                            function,
1005                            block,
1006                            index,
1007                            IrInst {
1008                                cmd: IrCmd::MUL_FLOAT,
1009                                ops,
1010                                ..IrInst::default()
1011                            },
1012                        );
1013                    } else {
1014                        state.substitute_or_record(inst, index);
1015                    }
1016                }
1017            } else {
1018                state.substitute_or_record(inst, index);
1019            }
1020        }
1021        IrCmd::MIN_FLOAT
1022        | IrCmd::MAX_FLOAT
1023        | IrCmd::UNM_FLOAT
1024        | IrCmd::FLOOR_FLOAT
1025        | IrCmd::CEIL_FLOAT
1026        | IrCmd::SQRT_FLOAT
1027        | IrCmd::ABS_FLOAT
1028        | IrCmd::SIGN_FLOAT => {
1029            state.substitute_or_record(inst, index);
1030        }
1031        IrCmd::IDIV_NUM
1032        | IrCmd::MULADD_NUM
1033        | IrCmd::MOD_NUM
1034        | IrCmd::MIN_NUM
1035        | IrCmd::MAX_NUM
1036        | IrCmd::UNM_NUM
1037        | IrCmd::FLOOR_NUM
1038        | IrCmd::CEIL_NUM
1039        | IrCmd::ROUND_NUM
1040        | IrCmd::SQRT_NUM
1041        | IrCmd::ABS_NUM
1042        | IrCmd::SIGN_NUM
1043        | IrCmd::SELECT_NUM
1044        | IrCmd::SELECT_INT64
1045        | IrCmd::SELECT_VEC
1046        | IrCmd::MULADD_VEC
1047        | IrCmd::EXTRACT_VEC
1048        | IrCmd::NOT_ANY => {
1049            state.substitute_or_record(inst, index);
1050        }
1051        IrCmd::SELECT_IF_TRUTHY => {
1052            let tag = state.try_get_tag(op_a(inst));
1053
1054            if tag == lua_Type::LUA_TNIL as u8 {
1055                let replacement = op_c(inst.clone());
1056                substitute(function, inst, replacement);
1057            } else if tag != 0xff && tag != lua_Type::LUA_TBOOLEAN as u8 {
1058                let replacement = op_b(inst.clone());
1059                substitute(function, inst, replacement);
1060            }
1061        }
1062        IrCmd::UINT_TO_NUM | IrCmd::UINT_TO_FLOAT => {
1063            let src = function.as_inst_op(op_a(inst));
1064            if !src.is_null() {
1065                let mut src_clone = unsafe { (*src).clone() };
1066                if src_clone.cmd == IrCmd::TRUNCATE_UINT {
1067                    let src_source = op_a(&mut src_clone);
1068                    let src_of_src = function.as_inst_op(src_source);
1069                    if !src_of_src.is_null() && unsafe { (*src_of_src).cmd } == IrCmd::NUM_TO_UINT {
1070                        replace_ir_function_ir_op_ir_op(function, &mut inst.ops[0], src_source);
1071                    }
1072                }
1073            }
1074
1075            state.substitute_or_record(inst, index);
1076        }
1077        IrCmd::NUM_TO_INT => {
1078            let src = function.as_inst_op(op_a(inst));
1079            if !src.is_null() {
1080                let src_clone = unsafe { (*src).clone() };
1081
1082                if src_clone.cmd == IrCmd::INT_TO_NUM {
1083                    let mut src_clone = src_clone;
1084                    substitute(function, inst, op_a(&mut src_clone));
1085                    return;
1086                }
1087
1088                if src_clone.cmd == IrCmd::ADD_NUM {
1089                    if let Some(arg) = function.as_double_op(op_b(src_clone.clone())) {
1090                        if arg == 0.0 {
1091                            let mut src_clone = src_clone.clone();
1092                            replace_ir_function_ir_op_ir_op(
1093                                function,
1094                                &mut inst.ops[0],
1095                                op_a(&mut src_clone),
1096                            );
1097                            state.substitute_or_record(inst, index);
1098                            return;
1099                        }
1100                    }
1101
1102                    let mut src_clone_for_a = src_clone.clone();
1103                    let src_op_a = op_a(&mut src_clone_for_a);
1104                    if let Some(arg) = function.as_double_op(src_op_a) {
1105                        if arg == 0.0 {
1106                            replace_ir_function_ir_op_ir_op(
1107                                function,
1108                                &mut inst.ops[0],
1109                                op_b(src_clone),
1110                            );
1111                            state.substitute_or_record(inst, index);
1112                            return;
1113                        }
1114                    }
1115                }
1116
1117                if src_clone.cmd == IrCmd::UINT_TO_NUM {
1118                    let mut src_clone = src_clone;
1119                    let src_source = op_a(&mut src_clone);
1120                    if src_source.kind() != IrOpKind::Constant {
1121                        substitute_with_truncated_uint(function, block, inst, src_source);
1122                        return;
1123                    }
1124                }
1125            }
1126
1127            state.substitute_or_record(inst, index);
1128        }
1129        IrCmd::NUM_TO_UINT => {
1130            let src = function.as_inst_op(op_a(inst));
1131            if !src.is_null() {
1132                let src_clone = unsafe { (*src).clone() };
1133
1134                if src_clone.cmd == IrCmd::UINT_TO_NUM {
1135                    let mut src_clone = src_clone;
1136                    substitute_with_truncated_uint(function, block, inst, op_a(&mut src_clone));
1137                    return;
1138                }
1139
1140                if src_clone.cmd == IrCmd::INT_TO_NUM {
1141                    let mut src_clone = src_clone.clone();
1142                    let src_source = op_a(&mut src_clone);
1143                    if src_source.kind() != IrOpKind::Constant {
1144                        substitute(function, inst, src_source);
1145                        return;
1146                    }
1147                }
1148
1149                if src_clone.cmd == IrCmd::ADD_NUM || src_clone.cmd == IrCmd::SUB_NUM {
1150                    let mut src_clone_a = src_clone.clone();
1151                    let src_a = op_a(&mut src_clone_a);
1152                    let src_b = op_b(src_clone.clone());
1153                    let add_src_1 = function.as_inst_op(src_a);
1154                    let add_num_1 = function.as_double_op(src_a);
1155                    let add_src_2 = function.as_inst_op(src_b);
1156                    let add_num_2 = function.as_double_op(src_b);
1157
1158                    let replacement_cmd = if src_clone.cmd == IrCmd::ADD_NUM {
1159                        IrCmd::ADD_INT
1160                    } else {
1161                        IrCmd::SUB_INT
1162                    };
1163
1164                    if !add_src_1.is_null()
1165                        && unsafe { (*add_src_1).cmd } == IrCmd::UINT_TO_NUM
1166                        && !add_src_2.is_null()
1167                        && unsafe { (*add_src_2).cmd } == IrCmd::UINT_TO_NUM
1168                    {
1169                        let mut add_src_1_clone = unsafe { (*add_src_1).clone() };
1170                        let mut add_src_2_clone = unsafe { (*add_src_2).clone() };
1171                        let mut ops = crate::type_aliases::ir_ops::IrOps::new();
1172                        ops.push(op_a(&mut add_src_1_clone));
1173                        ops.push(op_a(&mut add_src_2_clone));
1174                        replace_ir_function_ir_block_u32_ir_inst(
1175                            function,
1176                            block,
1177                            index,
1178                            IrInst {
1179                                cmd: replacement_cmd,
1180                                ops,
1181                                ..IrInst::default()
1182                            },
1183                        );
1184                        return;
1185                    } else if let Some(add_num_1) = add_num_1 {
1186                        if safe_integer_constant(add_num_1)
1187                            && !add_src_2.is_null()
1188                            && unsafe { (*add_src_2).cmd } == IrCmd::UINT_TO_NUM
1189                        {
1190                            let mut add_src_2_clone = unsafe { (*add_src_2).clone() };
1191                            let mut ops = crate::type_aliases::ir_ops::IrOps::new();
1192                            ops.push(build.const_int((add_num_1 as i64 as u32) as i32));
1193                            ops.push(op_a(&mut add_src_2_clone));
1194                            replace_ir_function_ir_block_u32_ir_inst(
1195                                function,
1196                                block,
1197                                index,
1198                                IrInst {
1199                                    cmd: replacement_cmd,
1200                                    ops,
1201                                    ..IrInst::default()
1202                                },
1203                            );
1204                            return;
1205                        }
1206                    } else if !add_src_1.is_null()
1207                        && unsafe { (*add_src_1).cmd } == IrCmd::UINT_TO_NUM
1208                    {
1209                        if let Some(add_num_2) = add_num_2 {
1210                            if safe_integer_constant(add_num_2) {
1211                                let mut add_src_1_clone = unsafe { (*add_src_1).clone() };
1212                                let mut ops = crate::type_aliases::ir_ops::IrOps::new();
1213                                ops.push(op_a(&mut add_src_1_clone));
1214                                ops.push(build.const_int((add_num_2 as i64 as u32) as i32));
1215                                replace_ir_function_ir_block_u32_ir_inst(
1216                                    function,
1217                                    block,
1218                                    index,
1219                                    IrInst {
1220                                        cmd: replacement_cmd,
1221                                        ops,
1222                                        ..IrInst::default()
1223                                    },
1224                                );
1225                                return;
1226                            }
1227                        }
1228                    }
1229                }
1230            }
1231
1232            state.substitute_or_record(inst, index);
1233        }
1234        IrCmd::TRUNCATE_UINT => {
1235            let src = function.as_inst_op(op_a(inst));
1236            if !src.is_null() && !produces_dirty_high_register_bits(unsafe { (*src).cmd }) {
1237                let source = op_a(inst);
1238                substitute(function, inst, source);
1239            } else {
1240                state.substitute_or_record(inst, index);
1241            }
1242        }
1243        IrCmd::FLOAT_TO_NUM => {
1244            state.substitute_or_record(inst, index);
1245        }
1246        IrCmd::NUM_TO_FLOAT => {
1247            let src = function.as_inst_op(op_a(inst));
1248            if !src.is_null() {
1249                let src_clone = unsafe { (*src).clone() };
1250                if src_clone.cmd == IrCmd::FLOAT_TO_NUM {
1251                    let mut src_clone = src_clone;
1252                    substitute(function, inst, op_a(&mut src_clone));
1253                } else if src_clone.cmd == IrCmd::UINT_TO_NUM {
1254                    let mut src_clone = src_clone;
1255                    let mut ops = IrOps::new();
1256                    ops.push(op_a(&mut src_clone));
1257                    replace_ir_function_ir_block_u32_ir_inst(
1258                        function,
1259                        block,
1260                        index,
1261                        IrInst {
1262                            cmd: IrCmd::UINT_TO_FLOAT,
1263                            ops,
1264                            ..IrInst::default()
1265                        },
1266                    );
1267                } else {
1268                    state.substitute_or_record(inst, index);
1269                }
1270            } else {
1271                state.substitute_or_record(inst, index);
1272            }
1273        }
1274        IrCmd::JUMP_IF_TRUTHY => {
1275            let tag = state.try_get_tag(op_a(inst));
1276            if tag != 0xff {
1277                if tag == lua_Type::LUA_TNIL as u8 {
1278                    let mut ops = crate::type_aliases::ir_ops::IrOps::new();
1279                    ops.push(op_c(inst.clone()));
1280                    replace_ir_function_ir_block_u32_ir_inst(
1281                        function,
1282                        block,
1283                        index,
1284                        IrInst {
1285                            cmd: IrCmd::JUMP,
1286                            ops,
1287                            ..IrInst::default()
1288                        },
1289                    );
1290                } else if tag != lua_Type::LUA_TBOOLEAN as u8 {
1291                    let mut ops = crate::type_aliases::ir_ops::IrOps::new();
1292                    ops.push(op_b(inst.clone()));
1293                    replace_ir_function_ir_block_u32_ir_inst(
1294                        function,
1295                        block,
1296                        index,
1297                        IrInst {
1298                            cmd: IrCmd::JUMP,
1299                            ops,
1300                            ..IrInst::default()
1301                        },
1302                    );
1303                }
1304            }
1305        }
1306        IrCmd::JUMP_IF_FALSY => {
1307            let tag = state.try_get_tag(op_a(inst));
1308            if tag != 0xff {
1309                if tag == lua_Type::LUA_TNIL as u8 {
1310                    let mut ops = crate::type_aliases::ir_ops::IrOps::new();
1311                    ops.push(op_b(inst.clone()));
1312                    replace_ir_function_ir_block_u32_ir_inst(
1313                        function,
1314                        block,
1315                        index,
1316                        IrInst {
1317                            cmd: IrCmd::JUMP,
1318                            ops,
1319                            ..IrInst::default()
1320                        },
1321                    );
1322                } else if tag != lua_Type::LUA_TBOOLEAN as u8 {
1323                    let mut ops = crate::type_aliases::ir_ops::IrOps::new();
1324                    ops.push(op_c(inst.clone()));
1325                    replace_ir_function_ir_block_u32_ir_inst(
1326                        function,
1327                        block,
1328                        index,
1329                        IrInst {
1330                            cmd: IrCmd::JUMP,
1331                            ops,
1332                            ..IrInst::default()
1333                        },
1334                    );
1335                }
1336            }
1337        }
1338        IrCmd::CMP_ANY => {
1339            state.invalidate_user_call();
1340        }
1341        IrCmd::CMP_SPLIT_TVALUE => {
1342            let tag_a_op = op_a(inst);
1343            let tag_b_op = op_b(inst.clone());
1344            let tag_a = if tag_a_op.kind() == IrOpKind::Constant {
1345                function.tag_op(tag_a_op)
1346            } else {
1347                state.try_get_tag(tag_a_op)
1348            };
1349            let tag_b = if tag_b_op.kind() == IrOpKind::Constant {
1350                function.tag_op(tag_b_op)
1351            } else {
1352                state.try_get_tag(tag_b_op)
1353            };
1354
1355            if tag_a == lua_Type::LUA_TSTRING as u8 && tag_b == lua_Type::LUA_TSTRING as u8 {
1356                if let Some((source, tag)) =
1357                    type_name_tag_comparison(function, op_c(inst.clone()), op_d(inst.clone()))
1358                {
1359                    let tag_op = build.const_tag(tag);
1360                    let replacement =
1361                        const_prop_make_inst(IrCmd::CMP_TAG, &[source, tag_op, op_e(inst.clone())]);
1362
1363                    replace_ir_function_ir_block_u32_ir_inst(function, block, index, replacement);
1364                    fold_constants(build, function, block, index);
1365                    return;
1366                }
1367            }
1368        }
1369        IrCmd::JUMP_EQ_POINTER => {
1370            if let Some((source, tag)) =
1371                type_name_tag_comparison(function, op_a(inst), op_b(inst.clone()))
1372            {
1373                let tag_op = build.const_tag(tag);
1374                let replacement = const_prop_make_inst(
1375                    IrCmd::JUMP_EQ_TAG,
1376                    &[source, tag_op, op_c(inst.clone()), op_d(inst.clone())],
1377                );
1378
1379                replace_ir_function_ir_block_u32_ir_inst(function, block, index, replacement);
1380                fold_constants(build, function, block, index);
1381                return;
1382            }
1383        }
1384        IrCmd::JUMP_EQ_TAG => {
1385            let a = op_a(inst);
1386            let b = op_b(inst.clone());
1387            let tag_a = if a.kind() == IrOpKind::Constant {
1388                function.tag_op(a)
1389            } else {
1390                state.try_get_tag(a)
1391            };
1392            let tag_b = if b.kind() == IrOpKind::Constant {
1393                function.tag_op(b)
1394            } else {
1395                state.try_get_tag(b)
1396            };
1397
1398            if tag_a != 0xff && tag_b != 0xff {
1399                let target = if tag_a == tag_b {
1400                    op_c(inst.clone())
1401                } else {
1402                    op_d(inst.clone())
1403                };
1404                let mut ops = crate::type_aliases::ir_ops::IrOps::new();
1405                ops.push(target);
1406                replace_ir_function_ir_block_u32_ir_inst(
1407                    function,
1408                    block,
1409                    index,
1410                    IrInst {
1411                        cmd: IrCmd::JUMP,
1412                        ops,
1413                        ..IrInst::default()
1414                    },
1415                );
1416            } else if a == b {
1417                let mut ops = crate::type_aliases::ir_ops::IrOps::new();
1418                ops.push(op_c(inst.clone()));
1419                replace_ir_function_ir_block_u32_ir_inst(
1420                    function,
1421                    block,
1422                    index,
1423                    IrInst {
1424                        cmd: IrCmd::JUMP,
1425                        ops,
1426                        ..IrInst::default()
1427                    },
1428                );
1429            }
1430        }
1431        IrCmd::JUMP_CMP_INT => {
1432            let a = op_a(inst);
1433            let b = op_b(inst.clone());
1434            let value_a = function.as_int_op(if a.kind() == IrOpKind::Constant {
1435                a
1436            } else {
1437                state.try_get_value(a)
1438            });
1439            let value_b = function.as_int_op(if b.kind() == IrOpKind::Constant {
1440                b
1441            } else {
1442                state.try_get_value(b)
1443            });
1444
1445            if let (Some(value_a), Some(value_b)) = (value_a, value_b) {
1446                let target = if compare_i32_i32_ir_condition(
1447                    value_a,
1448                    value_b,
1449                    condition_op(op_c(inst.clone())),
1450                ) {
1451                    op_d(inst.clone())
1452                } else {
1453                    op_e(inst.clone())
1454                };
1455                let mut ops = crate::type_aliases::ir_ops::IrOps::new();
1456                ops.push(target);
1457                replace_ir_function_ir_block_u32_ir_inst(
1458                    function,
1459                    block,
1460                    index,
1461                    IrInst {
1462                        cmd: IrCmd::JUMP,
1463                        ops,
1464                        ..IrInst::default()
1465                    },
1466                );
1467            }
1468        }
1469        IrCmd::JUMP_CMP_NUM => {
1470            let a = op_a(inst);
1471            let b = op_b(inst.clone());
1472            let value_a = function.as_double_op(if a.kind() == IrOpKind::Constant {
1473                a
1474            } else {
1475                state.try_get_value(a)
1476            });
1477            let value_b = function.as_double_op(if b.kind() == IrOpKind::Constant {
1478                b
1479            } else {
1480                state.try_get_value(b)
1481            });
1482
1483            if let (Some(value_a), Some(value_b)) = (value_a, value_b) {
1484                let target = if compare_f64_f64_ir_condition(
1485                    value_a,
1486                    value_b,
1487                    condition_op(op_c(inst.clone())),
1488                ) {
1489                    op_d(inst.clone())
1490                } else {
1491                    op_e(inst.clone())
1492                };
1493                let mut ops = crate::type_aliases::ir_ops::IrOps::new();
1494                ops.push(target);
1495                replace_ir_function_ir_block_u32_ir_inst(
1496                    function,
1497                    block,
1498                    index,
1499                    IrInst {
1500                        cmd: IrCmd::JUMP,
1501                        ops,
1502                        ..IrInst::default()
1503                    },
1504                );
1505            }
1506        }
1507        IrCmd::CHECK_TAG => {
1508            let target = op_a(inst);
1509            let expected = function.tag_op(op_b(inst.clone()));
1510            let mut tag = state.try_get_tag(target);
1511
1512            if tag == 0xff {
1513                let value = state.try_get_value(target);
1514                if value.kind() == IrOpKind::Constant {
1515                    let constant = function.const_op(value);
1516                    if constant.kind == IrConstKind::Double {
1517                        tag = lua_Type::LUA_TNUMBER as u8;
1518                    } else if constant.kind == IrConstKind::Int64 {
1519                        tag = lua_Type::LUA_TINTEGER as u8;
1520                    }
1521                }
1522            }
1523
1524            if tag != 0xff {
1525                if tag == expected {
1526                    crate::functions::kill_ir_utils::kill_ir_function_ir_inst(function, inst);
1527                } else {
1528                    let mut ops = crate::type_aliases::ir_ops::IrOps::new();
1529                    ops.push(op_c(inst.clone()));
1530                    replace_ir_function_ir_block_u32_ir_inst(
1531                        function,
1532                        block,
1533                        index,
1534                        IrInst {
1535                            cmd: IrCmd::JUMP,
1536                            ops,
1537                            ..IrInst::default()
1538                        },
1539                    );
1540                }
1541            } else {
1542                let lhs = function.as_inst_op(target);
1543                if !lhs.is_null() {
1544                    let mut lhs_inst = unsafe { (*lhs).clone() };
1545                    let lhs_source = op_a(&mut lhs_inst);
1546                    if lhs_inst.cmd == IrCmd::LOAD_TAG && lhs_source.kind() == IrOpKind::VmReg {
1547                        if let Some(prev_idx) =
1548                            state.get_previous_versioned_load_index(IrCmd::LOAD_TVALUE, lhs_source)
1549                        {
1550                            state.inst_tag.try_insert(unsafe { *prev_idx }, expected);
1551                        }
1552                    }
1553                }
1554
1555                state.update_tag(target, expected);
1556            }
1557        }
1558        IrCmd::NUM_TO_INT64 => {
1559            // INT64_TO_NUM followed by NUM_TO_INT64 of the same source is the identity.
1560            let src = function.as_inst_op(op_a(inst));
1561            if !src.is_null() {
1562                let src_clone = unsafe { (*src).clone() };
1563                let src_cmd = src_clone.cmd;
1564                if src_cmd == IrCmd::INT64_TO_NUM {
1565                    let src_op_a = op_a(&mut { src_clone });
1566                    substitute(function, inst, src_op_a);
1567                    return;
1568                }
1569                if src_cmd == IrCmd::ADD_NUM {
1570                    let src_op_b = op_b(src_clone.clone());
1571                    if let Some(arg) = function.as_double_op(src_op_b) {
1572                        if arg == 0.0 {
1573                            let src_op_a = op_a(&mut { src_clone.clone() });
1574                            inst.ops[0] = src_op_a;
1575                            state.substitute_or_record(inst, index);
1576                            return;
1577                        }
1578                    }
1579                    let src_op_a = op_a(&mut { src_clone.clone() });
1580                    if let Some(arg) = function.as_double_op(src_op_a) {
1581                        if arg == 0.0 {
1582                            let src_op_b = op_b(src_clone);
1583                            inst.ops[0] = src_op_b;
1584                            state.substitute_or_record(inst, index);
1585                            return;
1586                        }
1587                    }
1588                }
1589            }
1590            state.substitute_or_record(inst, index);
1591        }
1592        IrCmd::LOAD_ENV => {
1593            if luaur_common::FFlag::LuauCodegenExtraTableOpts.get() {
1594                if state.load_env_idx != crate::records::ir_data::k_invalid_inst_idx {
1595                    substitute(
1596                        function,
1597                        inst,
1598                        IrOp::ir_op_ir_op_kind_u32(IrOpKind::Inst, state.load_env_idx),
1599                    );
1600                } else {
1601                    state.load_env_idx = index;
1602                }
1603            }
1604        }
1605        IrCmd::GET_SLOT_NODE_ADDR => {
1606            for i in 0..state.get_slot_node_cache.len() {
1607                let prev_idx = state.get_slot_node_cache[i].inst_idx;
1608                let mut prev = function.instructions[prev_idx as usize].clone();
1609
1610                if op_a(&mut prev) == op_a(inst) && op_c(prev.clone()) == op_c(inst.clone()) {
1611                    let limit = luaur_common::FInt::LuauCodeGenLiveSlotReuseLimit.get();
1612
1613                    if state.get_slot_node_cache.len() as i32 > limit {
1614                        let mut cache = state.get_slot_node_cache.clone();
1615                        if state.get_max_internal_overlap(&mut cache, i) > limit {
1616                            return;
1617                        }
1618                    }
1619
1620                    state.get_slot_node_cache[i].finish_pos = state.inst_pos;
1621
1622                    substitute(
1623                        function,
1624                        inst,
1625                        IrOp::ir_op_ir_op_kind_u32(IrOpKind::Inst, prev_idx),
1626                    );
1627                    return;
1628                }
1629            }
1630
1631            if (state.get_slot_node_cache.len() as i32)
1632                < luaur_common::FInt::LuauCodeGenReuseSlotLimit.get()
1633            {
1634                state.get_slot_node_cache.push(NumberedInstruction {
1635                    inst_idx: index,
1636                    start_pos: state.inst_pos,
1637                    finish_pos: state.inst_pos,
1638                });
1639            }
1640        }
1641        IrCmd::GET_ARR_ADDR => {
1642            for prev_idx in state.get_arr_addr_cache.iter().copied() {
1643                let mut prev = function.instructions[prev_idx as usize].clone();
1644
1645                if op_a(&mut prev) == op_a(inst) && op_b(prev.clone()) == op_b(inst.clone()) {
1646                    substitute(
1647                        function,
1648                        inst,
1649                        IrOp::ir_op_ir_op_kind_u32(IrOpKind::Inst, prev_idx),
1650                    );
1651                    return;
1652                }
1653            }
1654
1655            if (state.get_arr_addr_cache.len() as i32)
1656                < luaur_common::FInt::LuauCodeGenReuseSlotLimit.get()
1657            {
1658                state.get_arr_addr_cache.push(index);
1659            }
1660        }
1661        IrCmd::ADD_INT
1662        | IrCmd::SUB_INT
1663        | IrCmd::ADD_INT64
1664        | IrCmd::SUB_INT64
1665        | IrCmd::MUL_INT64
1666        | IrCmd::DIV_INT64
1667        | IrCmd::IDIV_INT64
1668        | IrCmd::CHECK_DIV_INT64
1669        | IrCmd::UDIV_INT64
1670        | IrCmd::REM_INT64
1671        | IrCmd::UREM_INT64
1672        | IrCmd::MOD_INT64
1673        | IrCmd::SEXTI8_INT
1674        | IrCmd::SEXTI16_INT => {
1675            state.substitute_or_record(inst, index);
1676        }
1677        IrCmd::TRY_NUM_TO_INDEX => {
1678            for prev_idx in state.try_num_to_index_cache.iter().copied() {
1679                let mut prev = function.instructions[prev_idx as usize].clone();
1680
1681                if op_a(&mut prev) == op_a(inst) {
1682                    substitute(
1683                        function,
1684                        inst,
1685                        IrOp::ir_op_ir_op_kind_u32(IrOpKind::Inst, prev_idx),
1686                    );
1687                    return;
1688                }
1689            }
1690
1691            if (state.try_num_to_index_cache.len() as i32)
1692                < luaur_common::FInt::LuauCodeGenReuseSlotLimit.get()
1693            {
1694                state.try_num_to_index_cache.push(index);
1695            }
1696        }
1697        IrCmd::CHECK_SLOT_MATCH => {
1698            for el in &mut state.check_slot_match_cache {
1699                let mut prev = function.instructions[el.pointer as usize].clone();
1700
1701                if op_a(&mut prev) == op_a(inst) && op_b(prev.clone()) == op_b(inst.clone()) {
1702                    if let Some(info) = state.inst_tag.find(&op_a(inst).index()) {
1703                        if *info != lua_Type::LUA_TNIL as u8 {
1704                            el.knownToNotBeNil = true;
1705                        }
1706                    }
1707
1708                    if el.knownToNotBeNil {
1709                        crate::functions::kill_ir_utils::kill_ir_function_ir_inst(function, inst);
1710                    } else {
1711                        let mut ops = crate::type_aliases::ir_ops::IrOps::new();
1712                        ops.push(op_a(inst));
1713                        ops.push(op_c(inst.clone()));
1714                        replace_ir_function_ir_block_u32_ir_inst(
1715                            function,
1716                            block,
1717                            index,
1718                            IrInst {
1719                                cmd: IrCmd::CHECK_NODE_VALUE,
1720                                ops,
1721                                ..IrInst::default()
1722                            },
1723                        );
1724                    }
1725
1726                    el.knownToNotBeNil = true;
1727                    return;
1728                }
1729            }
1730
1731            if (state.check_slot_match_cache.len() as i32)
1732                < luaur_common::FInt::LuauCodeGenReuseSlotLimit.get()
1733            {
1734                state.check_slot_match_cache.push(NodeSlotState {
1735                    pointer: index,
1736                    knownToNotBeNil: true,
1737                });
1738            }
1739        }
1740        IrCmd::CHECK_SAFE_ENV => {
1741            if state.in_safe_env {
1742                crate::functions::kill_ir_utils::kill_ir_function_ir_inst(function, inst);
1743            } else {
1744                state.in_safe_env = true;
1745            }
1746        }
1747        IrCmd::CHECK_READONLY => {
1748            let target = op_a(inst);
1749            if luaur_common::FFlag::LuauCodegenExtraTableOpts.get()
1750                && target.kind() == IrOpKind::Inst
1751            {
1752                let target_idx = target.index();
1753                if state.inst_not_readonly.find(&target_idx).is_some() {
1754                    crate::functions::kill_ir_utils::kill_ir_function_ir_inst(function, inst);
1755                    return;
1756                }
1757                state.inst_not_readonly.insert(target_idx);
1758            } else if !luaur_common::FFlag::LuauCodegenExtraTableOpts.get() {
1759                if let Some(info) = state.try_get_register_info(target) {
1760                    unsafe {
1761                        if (*info).known_not_readonly_deprecated {
1762                            crate::functions::kill_ir_utils::kill_ir_function_ir_inst(
1763                                function, inst,
1764                            );
1765                        } else {
1766                            (*info).known_not_readonly_deprecated = true;
1767                        }
1768                    }
1769                }
1770            }
1771        }
1772        IrCmd::CHECK_NO_METATABLE => {
1773            let target = op_a(inst);
1774            if luaur_common::FFlag::LuauCodegenExtraTableOpts.get()
1775                && target.kind() == IrOpKind::Inst
1776            {
1777                let target_idx = target.index();
1778                if state.inst_no_metatable.find(&target_idx).is_some() {
1779                    crate::functions::kill_ir_utils::kill_ir_function_ir_inst(function, inst);
1780                    return;
1781                }
1782                state.inst_no_metatable.insert(target_idx);
1783            } else if !luaur_common::FFlag::LuauCodegenExtraTableOpts.get() {
1784                if let Some(info) = state.try_get_register_info(target) {
1785                    unsafe {
1786                        if (*info).known_no_metatable_deprecated {
1787                            crate::functions::kill_ir_utils::kill_ir_function_ir_inst(
1788                                function, inst,
1789                            );
1790                        } else {
1791                            (*info).known_no_metatable_deprecated = true;
1792                        }
1793                    }
1794                }
1795            }
1796        }
1797        IrCmd::BUFFER_READI8 => {
1798            state.substitute_or_record_buffer_load(block, index, inst, 1);
1799        }
1800        IrCmd::BUFFER_READU8 => {
1801            state.substitute_or_record_buffer_load(block, index, inst, 1);
1802        }
1803        IrCmd::BUFFER_WRITEI8 => {
1804            let src = function.as_inst_op(op_c(inst.clone()));
1805            if !src.is_null() {
1806                let src_inst = unsafe { (*src).clone() };
1807                let int_src_b = function.as_int_op(OPT_OP_B(src_inst.clone()));
1808
1809                if src_inst.cmd == IrCmd::SEXTI8_INT {
1810                    let replacement = op_a(&mut src_inst.clone());
1811                    replace_ir_function_ir_op_ir_op(function, &mut inst.ops[2], replacement);
1812                } else if src_inst.cmd == IrCmd::BITAND_UINT && int_src_b == Some(0xff) {
1813                    let replacement = op_a(&mut src_inst.clone());
1814                    replace_ir_function_ir_op_ir_op(function, &mut inst.ops[2], replacement);
1815                }
1816            }
1817
1818            state.forward_buffer_store_to_load(inst, IrCmd::BUFFER_READI8, 1);
1819        }
1820        IrCmd::BUFFER_READI16 => {
1821            state.substitute_or_record_buffer_load(block, index, inst, 2);
1822        }
1823        IrCmd::BUFFER_READU16 => {
1824            state.substitute_or_record_buffer_load(block, index, inst, 2);
1825        }
1826        IrCmd::BUFFER_WRITEI16 => {
1827            let src = function.as_inst_op(op_c(inst.clone()));
1828            if !src.is_null() {
1829                let src_inst = unsafe { (*src).clone() };
1830                let int_src_b = function.as_int_op(OPT_OP_B(src_inst.clone()));
1831
1832                if src_inst.cmd == IrCmd::SEXTI16_INT {
1833                    let replacement = op_a(&mut src_inst.clone());
1834                    replace_ir_function_ir_op_ir_op(function, &mut inst.ops[2], replacement);
1835                } else if src_inst.cmd == IrCmd::BITAND_UINT && int_src_b == Some(0xffff) {
1836                    let replacement = op_a(&mut src_inst.clone());
1837                    replace_ir_function_ir_op_ir_op(function, &mut inst.ops[2], replacement);
1838                }
1839            }
1840
1841            state.forward_buffer_store_to_load(inst, IrCmd::BUFFER_READI16, 2);
1842        }
1843        IrCmd::BUFFER_READI32 => {
1844            state.substitute_or_record_buffer_load(block, index, inst, 4);
1845        }
1846        IrCmd::BUFFER_WRITEI32 => {
1847            let src = function.as_inst_op(op_c(inst.clone()));
1848            if !src.is_null() {
1849                let src_inst = unsafe { (*src).clone() };
1850
1851                if src_inst.cmd == IrCmd::TRUNCATE_UINT {
1852                    let replacement = op_a(&mut src_inst.clone());
1853                    replace_ir_function_ir_op_ir_op(function, &mut inst.ops[2], replacement);
1854                }
1855            }
1856
1857            state.forward_buffer_store_to_load(inst, IrCmd::BUFFER_READI32, 4);
1858        }
1859        IrCmd::BUFFER_READF32 => {
1860            state.substitute_or_record_buffer_load(block, index, inst, 4);
1861        }
1862        IrCmd::BUFFER_WRITEF32 => {
1863            state.forward_buffer_store_to_load(inst, IrCmd::BUFFER_READF32, 4);
1864        }
1865        IrCmd::BUFFER_READF64 => {
1866            state.substitute_or_record_buffer_load(block, index, inst, 8);
1867        }
1868        IrCmd::BUFFER_WRITEF64 => {
1869            state.forward_buffer_store_to_load(inst, IrCmd::BUFFER_READF64, 8);
1870        }
1871        IrCmd::BUFFER_READI64 => {
1872            state.substitute_or_record_buffer_load(block, index, inst, 8);
1873        }
1874        IrCmd::BUFFER_WRITEI64 => {
1875            state.forward_buffer_store_to_load(inst, IrCmd::BUFFER_READI64, 8);
1876        }
1877        IrCmd::CHECK_GC => {
1878            if state.checked_gc {
1879                crate::functions::kill_ir_utils::kill_ir_function_ir_inst(function, inst);
1880            } else {
1881                state.checked_gc = true;
1882                state.invalidate_heap_table_data();
1883            }
1884        }
1885        IrCmd::BARRIER_OBJ | IrCmd::BARRIER_TABLE_FORWARD => {
1886            let value = op_b(inst.clone());
1887            if value.kind() == IrOpKind::VmReg {
1888                let tag = state.try_get_tag(value);
1889                if tag != 0xff && !is_gco(tag) {
1890                    crate::functions::kill_ir_utils::kill_ir_function_ir_inst(function, inst);
1891                }
1892            }
1893        }
1894        IrCmd::NEW_TABLE => {
1895            if luaur_common::FFlag::LuauCodegenExtraTableOpts.get() {
1896                let array_size = function.uint_op(op_a(inst)) as i32;
1897                state.inst_not_readonly.insert(index);
1898                state.inst_no_metatable.insert(index);
1899                state.inst_array_size.try_insert(index, array_size);
1900            }
1901        }
1902        IrCmd::CHECK_ARRAY_SIZE => {
1903            let target = op_a(inst);
1904            let boundary = op_b(inst.clone());
1905            let boundary_value = if boundary.kind() == IrOpKind::Constant {
1906                function.as_int_op(boundary)
1907            } else {
1908                function.as_int_op(state.try_get_value(boundary))
1909            };
1910
1911            if let Some(array_index) = boundary_value {
1912                if array_index < 0 {
1913                    let mut ops = crate::type_aliases::ir_ops::IrOps::new();
1914                    ops.push(op_c(inst.clone()));
1915                    replace_ir_function_ir_block_u32_ir_inst(
1916                        function,
1917                        block,
1918                        index,
1919                        IrInst {
1920                            cmd: IrCmd::JUMP,
1921                            ops,
1922                            ..IrInst::default()
1923                        },
1924                    );
1925                    return;
1926                }
1927
1928                if luaur_common::FFlag::LuauCodegenExtraTableOpts.get()
1929                    && target.kind() == IrOpKind::Inst
1930                {
1931                    if let Some(known_array_size) = state.inst_array_size.find(&target.index()) {
1932                        if *known_array_size >= 0 {
1933                            if (array_index as u32) < (*known_array_size as u32) {
1934                                crate::functions::kill_ir_utils::kill_ir_function_ir_inst(
1935                                    function, inst,
1936                                );
1937                            } else {
1938                                let mut ops = crate::type_aliases::ir_ops::IrOps::new();
1939                                ops.push(op_c(inst.clone()));
1940                                replace_ir_function_ir_block_u32_ir_inst(
1941                                    function,
1942                                    block,
1943                                    index,
1944                                    IrInst {
1945                                        cmd: IrCmd::JUMP,
1946                                        ops,
1947                                        ..IrInst::default()
1948                                    },
1949                                );
1950                            }
1951                            return;
1952                        }
1953                    }
1954                }
1955
1956                if let Some(info) = state.try_get_register_info(target) {
1957                    unsafe {
1958                        if (*info).known_table_array_size_deprecated >= 0 {
1959                            if (array_index as u32)
1960                                < ((*info).known_table_array_size_deprecated as u32)
1961                            {
1962                                crate::functions::kill_ir_utils::kill_ir_function_ir_inst(
1963                                    function, inst,
1964                                );
1965                            } else {
1966                                let mut ops = crate::type_aliases::ir_ops::IrOps::new();
1967                                ops.push(op_c(inst.clone()));
1968                                replace_ir_function_ir_block_u32_ir_inst(
1969                                    function,
1970                                    block,
1971                                    index,
1972                                    IrInst {
1973                                        cmd: IrCmd::JUMP,
1974                                        ops,
1975                                        ..IrInst::default()
1976                                    },
1977                                );
1978                            }
1979                            return;
1980                        }
1981                    }
1982                }
1983            }
1984
1985            for prev_idx in state.check_array_size_cache.iter().copied() {
1986                let mut prev = function.instructions[prev_idx as usize].clone();
1987
1988                if op_a(&mut prev) != op_a(inst) {
1989                    continue;
1990                }
1991
1992                let prev_boundary = op_b(prev.clone());
1993                let boundary = op_b(inst.clone());
1994                let mut same_boundary = prev_boundary == boundary;
1995
1996                if !same_boundary
1997                    && boundary.kind() == IrOpKind::Constant
1998                    && prev_boundary.kind() == IrOpKind::Constant
1999                    && (function.int_op(boundary) as u32) < (function.int_op(prev_boundary) as u32)
2000                {
2001                    same_boundary = true;
2002                }
2003
2004                if same_boundary {
2005                    crate::functions::kill_ir_utils::kill_ir_function_ir_inst(function, inst);
2006                    return;
2007                }
2008            }
2009
2010            if (state.check_array_size_cache.len() as i32)
2011                < luaur_common::FInt::LuauCodeGenReuseSlotLimit.get()
2012            {
2013                state.check_array_size_cache.push(index);
2014            }
2015        }
2016        IrCmd::CHECK_BUFFER_LEN => {
2017            let buffer_offset_op = op_b(inst.clone());
2018            let buffer_offset = if buffer_offset_op.kind() == IrOpKind::Constant {
2019                function.as_int_op(buffer_offset_op)
2020            } else {
2021                function.as_int_op(state.try_get_value(buffer_offset_op))
2022            };
2023
2024            let min_offset = function.int_op(op_c(inst.clone()));
2025            let max_offset = function.int_op(op_d(inst.clone()));
2026            crate::macros::codegen_assert::CODEGEN_ASSERT!(min_offset < max_offset);
2027            let access_size = max_offset - min_offset;
2028            crate::macros::codegen_assert::CODEGEN_ASSERT!(access_size > 0);
2029
2030            if let Some(buffer_offset) = buffer_offset {
2031                if buffer_offset < 0
2032                    || (buffer_offset as u32).wrapping_add(access_size as u32) >= i32::MAX as u32
2033                {
2034                    let mut ops = crate::type_aliases::ir_ops::IrOps::new();
2035                    ops.push(op_f(inst.clone()));
2036                    replace_ir_function_ir_block_u32_ir_inst(
2037                        function,
2038                        block,
2039                        index,
2040                        IrInst {
2041                            cmd: IrCmd::JUMP,
2042                            ops,
2043                            ..IrInst::default()
2044                        },
2045                    );
2046                    return;
2047                }
2048            }
2049
2050            for prev_idx in state.check_buffer_len_cache.clone() {
2051                let prev_ptr = &mut function.instructions[prev_idx as usize] as *mut IrInst;
2052                let prev = unsafe { &mut *prev_ptr };
2053
2054                if prev.cmd != IrCmd::CHECK_BUFFER_LEN {
2055                    continue;
2056                }
2057
2058                if op_a(prev) == op_a(inst)
2059                    && op_b(prev.clone()) == op_b(inst.clone())
2060                    && op_c(prev.clone()) == op_c(inst.clone())
2061                    && op_d(prev.clone()) == op_d(inst.clone())
2062                {
2063                    if luaur_common::FFlag::DebugLuauAbortingChecks.get() {
2064                        let replacement = build.undef();
2065                        replace_ir_function_ir_op_ir_op(function, &mut inst.ops[5], replacement);
2066                    } else {
2067                        crate::functions::kill_ir_utils::kill_ir_function_ir_inst(function, inst);
2068                    }
2069                    return;
2070                }
2071
2072                if op_a(prev) == op_a(inst)
2073                    && op_b(inst.clone()).kind() == IrOpKind::Constant
2074                    && op_b(prev.clone()).kind() == IrOpKind::Constant
2075                {
2076                    let curr_bound = function.int_op(op_b(inst.clone()));
2077                    let prev_bound = function.int_op(op_b(prev.clone()));
2078                    crate::macros::codegen_assert::CODEGEN_ASSERT!(curr_bound >= 0);
2079                    crate::macros::codegen_assert::CODEGEN_ASSERT!(prev_bound >= 0);
2080
2081                    let extra_offset = curr_bound - prev_bound;
2082                    if state.try_merge_and_kill_buffer_length_check(
2083                        build,
2084                        block,
2085                        inst,
2086                        prev,
2087                        extra_offset,
2088                    ) {
2089                        return;
2090                    }
2091
2092                    continue;
2093                }
2094
2095                if state.try_merge_buffer_range_check(build, block, inst, prev) {
2096                    return;
2097                }
2098            }
2099
2100            if (state.check_buffer_len_cache.len() as i32)
2101                < luaur_common::FInt::LuauCodeGenReuseSlotLimit.get()
2102            {
2103                state.check_buffer_len_cache.push(index);
2104            }
2105        }
2106        IrCmd::ADD_VEC
2107        | IrCmd::SUB_VEC
2108        | IrCmd::MUL_VEC
2109        | IrCmd::DIV_VEC
2110        | IrCmd::IDIV_VEC
2111        | IrCmd::DOT_VEC
2112        | IrCmd::MIN_VEC
2113        | IrCmd::MAX_VEC => {
2114            let a = op_a(inst);
2115            let a_ptr = function.as_inst_op(a);
2116            if !a_ptr.is_null() {
2117                let a_inst = unsafe { (*a_ptr).clone() };
2118                if a_inst.cmd == IrCmd::TAG_VECTOR {
2119                    let replacement = op_a(&mut a_inst.clone());
2120                    replace_ir_function_ir_op_ir_op(function, &mut inst.ops[0], replacement);
2121                }
2122            }
2123
2124            let b = op_b(inst.clone());
2125            let b_ptr = function.as_inst_op(b);
2126            if !b_ptr.is_null() {
2127                let b_inst = unsafe { (*b_ptr).clone() };
2128                if b_inst.cmd == IrCmd::TAG_VECTOR {
2129                    let replacement = op_a(&mut b_inst.clone());
2130                    replace_ir_function_ir_op_ir_op(function, &mut inst.ops[1], replacement);
2131                }
2132            }
2133
2134            state.substitute_or_record(inst, index);
2135        }
2136        IrCmd::UNM_VEC | IrCmd::FLOOR_VEC | IrCmd::CEIL_VEC | IrCmd::ABS_VEC => {
2137            let a = op_a(inst);
2138            let a_ptr = function.as_inst_op(a);
2139            if !a_ptr.is_null() {
2140                let a_inst = unsafe { (*a_ptr).clone() };
2141                if a_inst.cmd == IrCmd::TAG_VECTOR {
2142                    let replacement = op_a(&mut a_inst.clone());
2143                    replace_ir_function_ir_op_ir_op(function, &mut inst.ops[0], replacement);
2144                }
2145            }
2146
2147            state.substitute_or_record(inst, index);
2148        }
2149        IrCmd::FLOAT_TO_VEC | IrCmd::TAG_VECTOR => {
2150            state.substitute_or_record(inst, index);
2151        }
2152        IrCmd::INVOKE_LIBM => {
2153            state.substitute_or_record(inst, index);
2154        }
2155        IrCmd::DO_ARITH => {
2156            let target = op_a(inst);
2157            state.invalidate_ir_op(target);
2158            state.invalidate_user_call();
2159        }
2160        IrCmd::DO_LEN => {
2161            let target = op_a(inst);
2162            state.invalidate_ir_op(target);
2163            state.invalidate_user_call();
2164            state.save_tag(target, lua_Type::LUA_TNUMBER as u8);
2165        }
2166        IrCmd::GET_TABLE => {
2167            let target = op_a(inst);
2168            state.invalidate_ir_op(target);
2169            state.invalidate_user_call();
2170        }
2171        IrCmd::SET_TABLE => {
2172            state.invalidate_user_call();
2173        }
2174        IrCmd::GET_CACHED_IMPORT => {
2175            let target = op_a(inst);
2176            state.invalidate_ir_op(target);
2177
2178            if state.in_safe_env {
2179                state.invalidate_value_propagation();
2180            } else {
2181                state.invalidate_user_call();
2182            }
2183        }
2184        IrCmd::SETLIST => {
2185            if luaur_common::FFlag::LuauCodegenExtraTableOpts.get() {
2186                if let Some(load_idx) =
2187                    state.get_previous_versioned_load_index(IrCmd::LOAD_POINTER, op_b(inst.clone()))
2188                {
2189                    let load_idx = unsafe { *load_idx };
2190                    if let Some(known_array_size) = state.inst_array_size.find(&load_idx) {
2191                        if *known_array_size >= 0 {
2192                            let replacement = build.const_uint(*known_array_size as u32);
2193                            replace_ir_function_ir_op_ir_op(
2194                                function,
2195                                &mut inst.ops[5],
2196                                replacement,
2197                            );
2198                        }
2199                    }
2200                }
2201            } else if let Some(info) = state.try_get_register_info(op_b(inst.clone())) {
2202                unsafe {
2203                    if (*info).known_table_array_size_deprecated >= 0 {
2204                        let replacement =
2205                            build.const_uint((*info).known_table_array_size_deprecated as u32);
2206                        replace_ir_function_ir_op_ir_op(function, &mut inst.ops[5], replacement);
2207                    }
2208                }
2209            }
2210
2211            state.invalidate_value_propagation();
2212            state.invalidate_heap_table_data();
2213            state.invalidate_heap_buffer_data();
2214        }
2215        IrCmd::TABLE_SETNUM => {
2216            state.invalidate_table_array_size();
2217        }
2218        IrCmd::CONCAT => {
2219            let first_reg = crate::functions::vm_reg_op::vm_reg_op(op_a(inst));
2220            let count = function.uint_op(op_b(inst.clone())) as i32;
2221            state.invalidate_register_range(first_reg, count);
2222            state.invalidate_user_call();
2223        }
2224        IrCmd::FALLBACK_GETVARARGS => {
2225            let first_reg = crate::functions::vm_reg_op::vm_reg_op(op_b(inst.clone()));
2226            let count = function.int_op(op_c(inst.clone()));
2227            state.invalidate_register_range(first_reg, count);
2228        }
2229        IrCmd::FASTCALL => {
2230            let bfid = unsafe {
2231                core::mem::transmute::<u8, LuauBuiltinFunction>(function.uint_op(op_a(inst)) as u8)
2232            };
2233            let first_return_reg = crate::functions::vm_reg_op::vm_reg_op(op_b(inst.clone()));
2234            let nresults = function.int_op(op_d(inst.clone()));
2235
2236            handle_builtin_effects(state, bfid, first_return_reg as u32, nresults);
2237
2238            match bfid {
2239                LuauBuiltinFunction::LBF_MATH_MODF | LuauBuiltinFunction::LBF_MATH_FREXP => {
2240                    let target =
2241                        IrOp::ir_op_ir_op_kind_u32(IrOpKind::VmReg, first_return_reg as u32);
2242                    state.update_tag(target, lua_Type::LUA_TNUMBER as u8);
2243
2244                    if nresults > 1 {
2245                        let target = IrOp::ir_op_ir_op_kind_u32(
2246                            IrOpKind::VmReg,
2247                            (first_return_reg + 1) as u32,
2248                        );
2249                        state.update_tag(target, lua_Type::LUA_TNUMBER as u8);
2250                    }
2251                }
2252                _ => {}
2253            }
2254        }
2255        IrCmd::INVOKE_FASTCALL => {
2256            let bfid = unsafe {
2257                core::mem::transmute::<u8, LuauBuiltinFunction>(function.uint_op(op_a(inst)) as u8)
2258            };
2259            let first_return_reg =
2260                crate::functions::vm_reg_op::vm_reg_op(op_b(inst.clone())) as u32;
2261            let nresults = function.int_op(op_g(inst.clone()));
2262            handle_builtin_effects(state, bfid, first_return_reg, nresults);
2263        }
2264        IrCmd::CALL => {
2265            let first_reg = crate::functions::vm_reg_op::vm_reg_op(op_a(inst));
2266            state.invalidate_registers_from(first_reg);
2267            state.invalidate_user_call();
2268        }
2269        IrCmd::FALLBACK_GETGLOBAL => {
2270            state.invalidate_ir_op(op_b(inst.clone()));
2271            state.invalidate_user_call();
2272        }
2273        IrCmd::FALLBACK_SETGLOBAL | IrCmd::FALLBACK_SETTABLEKS => {
2274            state.invalidate_user_call();
2275        }
2276        IrCmd::FALLBACK_GETTABLEKS => {
2277            state.invalidate_ir_op(op_b(inst.clone()));
2278            state.invalidate_user_call();
2279        }
2280        IrCmd::FALLBACK_NAMECALL => {
2281            let target = op_b(inst.clone());
2282            state.invalidate_ir_op(target);
2283            state.invalidate_ir_op(IrOp::ir_op_ir_op_kind_u32(
2284                target.kind(),
2285                target.index() + 1,
2286            ));
2287            state.invalidate_user_call();
2288        }
2289        IrCmd::FALLBACK_PREPVARARGS => {}
2290        IrCmd::FALLBACK_DUPCLOSURE => {
2291            state.invalidate_ir_op(op_b(inst.clone()));
2292            state.invalidate_heap_table_data();
2293        }
2294        IrCmd::FALLBACK_FORGPREP => {
2295            let target = op_b(inst.clone());
2296            state.invalidate_ir_op(target);
2297            state.invalidate_ir_op(IrOp::ir_op_ir_op_kind_u32(
2298                target.kind(),
2299                target.index() + 1,
2300            ));
2301            state.invalidate_ir_op(IrOp::ir_op_ir_op_kind_u32(
2302                target.kind(),
2303                target.index() + 2,
2304            ));
2305            state.invalidate_user_call();
2306        }
2307        _ => {}
2308    }
2309}