luaur_code_gen/functions/
try_replace_value_with_full_store.rs1use crate::enums::ir_cmd::IrCmd;
2use crate::enums::ir_op_kind::IrOpKind;
3use crate::functions::replace_ir_utils_alt_b::replace_ir_function_ir_block_u32_ir_inst;
4use crate::macros::codegen_assert::CODEGEN_ASSERT;
5use crate::macros::has_op_d::HAS_OP_D;
6use crate::records::ir_block::IrBlock;
7use crate::records::ir_builder::IrBuilder;
8use crate::records::ir_function::IrFunction;
9use crate::records::ir_inst::IrInst;
10use crate::records::ir_op::IrOp;
11use crate::records::remove_dead_store_state::RemoveDeadStoreState;
12use crate::records::store_reg_info::StoreRegInfo;
13use crate::type_aliases::ir_ops::IrOps;
14
15fn make_split(target_op: IrOp, tag_op: IrOp, value_op: IrOp) -> IrInst {
16 let mut ops = IrOps::new();
17 ops.push_back(target_op);
18 ops.push_back(tag_op);
19 ops.push_back(value_op);
20 IrInst {
21 cmd: IrCmd::STORE_SPLIT_TVALUE,
22 ops,
23 ..IrInst::default()
24 }
25}
26
27pub fn try_replace_value_with_full_store(
28 state: &mut RemoveDeadStoreState,
29 build: &mut IrBuilder,
30 function: &mut IrFunction,
31 block: &mut IrBlock,
32 inst_index: u32,
33 target_op: IrOp,
34 value_op: IrOp,
35 reg_info: &mut StoreRegInfo,
36) -> bool {
37 if reg_info.tag_inst_idx != !0u32 && reg_info.value_inst_idx != !0u32 {
39 let prev_tag_op = function.instructions[reg_info.tag_inst_idx as usize].ops[1];
40 let prev_tag = function.tag_op(prev_tag_op);
41
42 CODEGEN_ASSERT!(reg_info.known_tag == prev_tag);
43 let repl = make_split(target_op, prev_tag_op, value_op);
44 replace_ir_function_ir_block_u32_ir_inst(function, block, inst_index, repl);
45
46 state.kill_tag_store(reg_info);
47 state.kill_value_store(reg_info);
48
49 reg_info.tvalue_inst_idx = inst_index;
50 return true;
51 }
52
53 if reg_info.tvalue_inst_idx != !0u32 {
55 let prev_cmd = function.instructions[reg_info.tvalue_inst_idx as usize].cmd;
56
57 if prev_cmd == IrCmd::STORE_SPLIT_TVALUE {
58 let prev_tag_op = function.instructions[reg_info.tvalue_inst_idx as usize].ops[1];
59 let prev_tag = function.tag_op(prev_tag_op);
60
61 CODEGEN_ASSERT!(reg_info.known_tag == prev_tag);
62 CODEGEN_ASSERT!(!HAS_OP_D!(
63 function.instructions[reg_info.tvalue_inst_idx as usize]
64 ));
65 let repl = make_split(target_op, prev_tag_op, value_op);
66 replace_ir_function_ir_block_u32_ir_inst(function, block, inst_index, repl);
67
68 CODEGEN_ASSERT!(reg_info.tag_inst_idx == !0u32 && reg_info.value_inst_idx == !0u32);
69 state.kill_t_value_store(reg_info);
70
71 reg_info.tvalue_inst_idx = inst_index;
72 return true;
73 } else if prev_cmd == IrCmd::STORE_VECTOR {
74 let prev_tag_op = function.instructions[reg_info.tvalue_inst_idx as usize].ops[4];
75 CODEGEN_ASSERT!(prev_tag_op.kind() != IrOpKind::None);
76 let prev_tag = function.tag_op(prev_tag_op);
77
78 CODEGEN_ASSERT!(reg_info.known_tag == prev_tag);
79 let repl = make_split(target_op, prev_tag_op, value_op);
80 replace_ir_function_ir_block_u32_ir_inst(function, block, inst_index, repl);
81
82 CODEGEN_ASSERT!(reg_info.tag_inst_idx == !0u32 && reg_info.value_inst_idx == !0u32);
83 state.kill_t_value_store(reg_info);
84
85 reg_info.tvalue_inst_idx = inst_index;
86 return true;
87 } else if prev_cmd == IrCmd::STORE_TVALUE
88 && reg_info.known_tag != 0xff
89 && reg_info.tag_inst_idx == !0u32
90 {
91 let prev_tag_op = build.const_tag(reg_info.known_tag);
92 let repl = make_split(target_op, prev_tag_op, value_op);
93 replace_ir_function_ir_block_u32_ir_inst(function, block, inst_index, repl);
94
95 CODEGEN_ASSERT!(reg_info.tag_inst_idx == !0u32 && reg_info.value_inst_idx == !0u32);
96 state.kill_t_value_store(reg_info);
97
98 reg_info.tvalue_inst_idx = inst_index;
99 return true;
100 }
101 }
102
103 false
104}