mirror of
https://github.com/kmc7468/cs420.git
synced 2025-12-15 06:58:50 +00:00
Fix ir equiv
This commit is contained in:
132
src/ir/equiv.rs
132
src/ir/equiv.rs
@@ -110,13 +110,143 @@ fn is_equiv_block(lhs: &Block, rhs: &Block, map: &HashMap<BlockId, BlockId>) ->
|
||||
return false;
|
||||
}
|
||||
|
||||
if lhs.instructions != rhs.instructions {
|
||||
if lhs.instructions.len() != rhs.instructions.len() {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (l, r) in izip!(&lhs.instructions, &rhs.instructions) {
|
||||
if !is_equiv_instruction(l, r, map) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
is_equiv_block_exit(&lhs.exit, &rhs.exit, map)
|
||||
}
|
||||
|
||||
fn is_equiv_instruction(
|
||||
lhs: &Instruction,
|
||||
rhs: &Instruction,
|
||||
map: &HashMap<BlockId, BlockId>,
|
||||
) -> bool {
|
||||
match (lhs, rhs) {
|
||||
(Instruction::Nop, Instruction::Nop) => true,
|
||||
(
|
||||
Instruction::BinOp {
|
||||
op,
|
||||
lhs,
|
||||
rhs,
|
||||
dtype,
|
||||
},
|
||||
Instruction::BinOp {
|
||||
op: op_other,
|
||||
lhs: lhs_other,
|
||||
rhs: rhs_other,
|
||||
dtype: dtype_other,
|
||||
},
|
||||
) => {
|
||||
op == op_other
|
||||
&& is_equiv_operand(lhs, lhs_other, map)
|
||||
&& is_equiv_operand(rhs, rhs_other, map)
|
||||
&& dtype == dtype_other
|
||||
}
|
||||
(
|
||||
Instruction::UnaryOp { op, operand, dtype },
|
||||
Instruction::UnaryOp {
|
||||
op: op_other,
|
||||
operand: operand_other,
|
||||
dtype: dtype_other,
|
||||
},
|
||||
) => {
|
||||
op == op_other && is_equiv_operand(operand, operand_other, map) && dtype == dtype_other
|
||||
}
|
||||
(
|
||||
Instruction::Store { ptr, value },
|
||||
Instruction::Store {
|
||||
ptr: ptr_other,
|
||||
value: value_other,
|
||||
},
|
||||
) => is_equiv_operand(ptr, ptr_other, map) && is_equiv_operand(value, value_other, map),
|
||||
(Instruction::Load { ptr }, Instruction::Load { ptr: ptr_other }) => {
|
||||
is_equiv_operand(ptr, ptr_other, map)
|
||||
}
|
||||
(
|
||||
Instruction::Call {
|
||||
callee,
|
||||
args,
|
||||
return_type,
|
||||
},
|
||||
Instruction::Call {
|
||||
callee: callee_other,
|
||||
args: args_other,
|
||||
return_type: return_type_other,
|
||||
},
|
||||
) => {
|
||||
is_equiv_operand(callee, callee_other, map)
|
||||
&& args.len() == args_other.len()
|
||||
&& izip!(args, args_other).all(|(l, r)| is_equiv_operand(l, r, map))
|
||||
&& return_type == return_type_other
|
||||
}
|
||||
(
|
||||
Instruction::TypeCast {
|
||||
value,
|
||||
target_dtype,
|
||||
},
|
||||
Instruction::TypeCast {
|
||||
value: value_other,
|
||||
target_dtype: target_dtype_other,
|
||||
},
|
||||
) => is_equiv_operand(value, value_other, map) && target_dtype == target_dtype_other,
|
||||
(
|
||||
Instruction::GetElementPtr { ptr, offset, dtype },
|
||||
Instruction::GetElementPtr {
|
||||
ptr: ptr_other,
|
||||
offset: offset_other,
|
||||
dtype: dtype_other,
|
||||
},
|
||||
) => {
|
||||
is_equiv_operand(ptr, ptr_other, map)
|
||||
&& is_equiv_operand(offset, offset_other, map)
|
||||
&& dtype == dtype_other
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_equiv_operand(lhs: &Operand, rhs: &Operand, map: &HashMap<BlockId, BlockId>) -> bool {
|
||||
match (lhs, rhs) {
|
||||
(Operand::Constant(_), Operand::Constant(_)) => lhs == rhs,
|
||||
(
|
||||
Operand::Register { rid, dtype },
|
||||
Operand::Register {
|
||||
rid: rid_other,
|
||||
dtype: dtype_other,
|
||||
},
|
||||
) => is_equiv_rid(rid, rid_other, map) && dtype == dtype_other,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_equiv_rid(lhs: &RegisterId, rhs: &RegisterId, map: &HashMap<BlockId, BlockId>) -> bool {
|
||||
match (lhs, rhs) {
|
||||
(RegisterId::Local { .. }, RegisterId::Local { .. }) => lhs == rhs,
|
||||
(
|
||||
RegisterId::Arg { bid, aid },
|
||||
RegisterId::Arg {
|
||||
bid: bid_other,
|
||||
aid: aid_other,
|
||||
},
|
||||
) => map.get(bid) == Some(bid_other) && aid == aid_other,
|
||||
(
|
||||
RegisterId::Temp { bid, iid },
|
||||
RegisterId::Temp {
|
||||
bid: bid_other,
|
||||
iid: iid_other,
|
||||
},
|
||||
) => map.get(bid) == Some(bid_other) && iid == iid_other,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_equiv_block_exit(lhs: &BlockExit, rhs: &BlockExit, map: &HashMap<BlockId, BlockId>) -> bool {
|
||||
match (lhs, rhs) {
|
||||
(BlockExit::Jump { arg }, BlockExit::Jump { arg: arg_other }) => {
|
||||
|
||||
Reference in New Issue
Block a user