mirror of
https://github.com/kmc7468/cs420.git
synced 2025-12-16 23:48:48 +00:00
HW8 (7)
This commit is contained in:
@@ -40,8 +40,8 @@ impl Translate<ir::TranslationUnit> for Asmgen {
|
|||||||
struct InferenceGraph {
|
struct InferenceGraph {
|
||||||
edges: HashSet<(ir::RegisterId, ir::RegisterId)>,
|
edges: HashSet<(ir::RegisterId, ir::RegisterId)>,
|
||||||
vertices: HashMap<ir::RegisterId, (ir::Dtype, asm::Register)>,
|
vertices: HashMap<ir::RegisterId, (ir::Dtype, asm::Register)>,
|
||||||
has_call: bool,
|
analysis: Analysis,
|
||||||
is_a0_return_pointer: bool,
|
lives: HashMap<ir::RegisterId, HashSet<ir::RegisterId>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InferenceGraph {
|
impl InferenceGraph {
|
||||||
@@ -192,6 +192,16 @@ impl InferenceGraph {
|
|||||||
.or_insert_with(HashSet::new),
|
.or_insert_with(HashSet::new),
|
||||||
uses,
|
uses,
|
||||||
) || changed;
|
) || changed;
|
||||||
|
|
||||||
|
let phinodes = (0..block.phinodes.len())
|
||||||
|
.map(|i| ir::RegisterId::arg(*bid, i))
|
||||||
|
.collect();
|
||||||
|
changed = extend_set(
|
||||||
|
lives
|
||||||
|
.entry(ir::RegisterId::temp(*bid, 0))
|
||||||
|
.or_insert_with(HashSet::new),
|
||||||
|
phinodes,
|
||||||
|
) || changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !changed {
|
if !changed {
|
||||||
@@ -212,95 +222,57 @@ impl InferenceGraph {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (bid, block) in &code.blocks {
|
// for (bid, block) in &code.blocks {
|
||||||
for (i, _) in block.phinodes.iter().enumerate() {
|
// for (i, _) in block.phinodes.iter().enumerate() {
|
||||||
let rid1 = ir::RegisterId::arg(*bid, i);
|
// let rid1 = ir::RegisterId::arg(*bid, i);
|
||||||
for (j, _) in block.phinodes.iter().enumerate() {
|
// for (j, _) in block.phinodes.iter().enumerate() {
|
||||||
if i != j {
|
// if i != j {
|
||||||
let rid2 = ir::RegisterId::arg(*bid, j);
|
// let rid2 = ir::RegisterId::arg(*bid, j);
|
||||||
let _ = edges.insert((rid1, rid2));
|
// let _ = edges.insert((rid1, rid2));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
for (j, _) in block.instructions.iter().enumerate() {
|
// for (j, _) in block.instructions.iter().enumerate() {
|
||||||
let rid2 = ir::RegisterId::temp(*bid, j);
|
// let rid2 = ir::RegisterId::temp(*bid, j);
|
||||||
let _ = edges.insert((rid1, rid2));
|
// let _ = edges.insert((rid1, rid2));
|
||||||
let _ = edges.insert((rid2, rid1));
|
// let _ = edges.insert((rid2, rid1));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
let mut num_of_edges = HashMap::new();
|
let mut num_of_edges = HashMap::new();
|
||||||
for (rid1, _) in &edges {
|
for (rid1, _) in &edges {
|
||||||
*num_of_edges.entry(*rid1).or_insert(0) += 1;
|
*num_of_edges.entry(*rid1).or_insert(0) += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (mut num_int_args, mut num_float_args, primitive_arg_reg_index) =
|
let analysis = analyze_function(code, signature, structs);
|
||||||
get_number_of_register_arguments(&signature.ret, &signature.params, structs);
|
|
||||||
let mut has_call = false;
|
|
||||||
let mut is_a0_return_pointer = false;
|
|
||||||
|
|
||||||
'outer: for block in code.blocks.values() {
|
if !analysis.has_memcpy_in_prologue {
|
||||||
for inst in &block.instructions {
|
for (aid, dtype) in code.blocks[&code.bid_init].phinodes.iter().enumerate() {
|
||||||
if let ir::Instruction::Call {
|
let rid = ir::RegisterId::arg(code.bid_init, aid);
|
||||||
callee,
|
if analysis.is_temporary2(&rid, &lives) {
|
||||||
args,
|
if is_integer(dtype) {
|
||||||
return_type,
|
let (_, asm_reg) = vertices.get_mut(&rid).unwrap();
|
||||||
} = inst.deref()
|
*asm_reg = asm::Register::arg(
|
||||||
{
|
asm::RegisterType::Integer,
|
||||||
// let (new_num_int_args, new_num_float_args) = get_number_of_register_arguments(
|
analysis.primitive_arg_reg_index[&aid] as usize,
|
||||||
// return_type,
|
);
|
||||||
// &args.iter().map(|operand| operand.dtype()).collect(),
|
} else if is_float(dtype) {
|
||||||
// structs,
|
let (_, asm_reg) = vertices.get_mut(&rid).unwrap();
|
||||||
// );
|
*asm_reg = asm::Register::arg(
|
||||||
// num_int_args = std::cmp::max(num_int_args, new_num_int_args);
|
asm::RegisterType::FloatingPoint,
|
||||||
// num_float_args = std::cmp::max(num_float_args, new_num_float_args);
|
analysis.primitive_arg_reg_index[&aid] as usize,
|
||||||
|
);
|
||||||
num_int_args = 8;
|
|
||||||
num_float_args = 8; // call이 있는 경우 a는 사용 x
|
|
||||||
has_call = true;
|
|
||||||
break 'outer;
|
|
||||||
} else if let ir::Instruction::Store { value, .. } = inst.deref() {
|
|
||||||
if is_struct(&value.dtype(), structs).is_some() {
|
|
||||||
num_int_args = 8;
|
|
||||||
num_float_args = 8;
|
|
||||||
has_call = true; // memcpy
|
|
||||||
break 'outer;
|
|
||||||
}
|
|
||||||
} else if let ir::Instruction::Load { ptr } = inst.deref() {
|
|
||||||
if is_struct(ptr.dtype().get_pointer_inner().unwrap(), structs).is_some() {
|
|
||||||
num_int_args = 8;
|
|
||||||
num_float_args = 8;
|
|
||||||
has_call = true; // memcpy
|
|
||||||
break 'outer;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(size) = is_struct(&signature.ret, structs) {
|
for (bid, iid, _, reg) in &analysis.calls {
|
||||||
if size > 16 {
|
let rid = ir::RegisterId::temp(*bid, *iid);
|
||||||
num_int_args = 8;
|
if analysis.is_temporary2(&rid, &lives) {
|
||||||
num_float_args = 8;
|
if let Some(reg) = reg {
|
||||||
has_call = true; // memcpy
|
|
||||||
is_a0_return_pointer = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !has_call {
|
|
||||||
for (aid, dtype) in code.blocks[&code.bid_init].phinodes.iter().enumerate() {
|
|
||||||
let rid = ir::RegisterId::arg(code.bid_init, aid);
|
|
||||||
if is_integer(dtype) {
|
|
||||||
let (_, asm_reg) = vertices.get_mut(&rid).unwrap();
|
let (_, asm_reg) = vertices.get_mut(&rid).unwrap();
|
||||||
*asm_reg = asm::Register::arg(
|
*asm_reg = *reg;
|
||||||
asm::RegisterType::Integer,
|
|
||||||
primitive_arg_reg_index[&aid] as usize,
|
|
||||||
);
|
|
||||||
} else if is_float(dtype) {
|
|
||||||
let (_, asm_reg) = vertices.get_mut(&rid).unwrap();
|
|
||||||
*asm_reg = asm::Register::arg(
|
|
||||||
asm::RegisterType::FloatingPoint,
|
|
||||||
primitive_arg_reg_index[&aid] as usize,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -363,7 +335,7 @@ impl InferenceGraph {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
num_int_args as usize,
|
0,
|
||||||
);
|
);
|
||||||
let smallest_saved_reg = smallest_missing_integer(
|
let smallest_saved_reg = smallest_missing_integer(
|
||||||
&neighbor_registers
|
&neighbor_registers
|
||||||
@@ -378,7 +350,7 @@ impl InferenceGraph {
|
|||||||
.collect(),
|
.collect(),
|
||||||
1,
|
1,
|
||||||
); // s0는 못 씀
|
); // s0는 못 씀
|
||||||
if smallest_arg_reg <= 7 {
|
if smallest_arg_reg <= 7 && analysis.is_temporary2(&rid, &lives) {
|
||||||
let _unused = vertices.insert(
|
let _unused = vertices.insert(
|
||||||
rid,
|
rid,
|
||||||
(
|
(
|
||||||
@@ -409,7 +381,7 @@ impl InferenceGraph {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
num_float_args as usize,
|
0,
|
||||||
);
|
);
|
||||||
let smallest_saved_reg = smallest_missing_integer(
|
let smallest_saved_reg = smallest_missing_integer(
|
||||||
&neighbor_registers
|
&neighbor_registers
|
||||||
@@ -424,7 +396,7 @@ impl InferenceGraph {
|
|||||||
.collect(),
|
.collect(),
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
if smallest_arg_reg <= 7 {
|
if smallest_arg_reg <= 7 && analysis.is_temporary2(&rid, &lives) {
|
||||||
let _unused = vertices.insert(
|
let _unused = vertices.insert(
|
||||||
rid,
|
rid,
|
||||||
(
|
(
|
||||||
@@ -454,8 +426,8 @@ impl InferenceGraph {
|
|||||||
InferenceGraph {
|
InferenceGraph {
|
||||||
edges,
|
edges,
|
||||||
vertices,
|
vertices,
|
||||||
has_call,
|
analysis,
|
||||||
is_a0_return_pointer,
|
lives,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,6 +473,117 @@ fn smallest_missing_integer(set: &HashSet<usize>, start: usize) -> usize {
|
|||||||
i
|
i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Analysis {
|
||||||
|
num_int_args: i32,
|
||||||
|
num_float_args: i32,
|
||||||
|
primitive_arg_reg_index: HashMap<usize, i32>,
|
||||||
|
is_a0_return_pointer: bool,
|
||||||
|
has_memcpy_in_prologue: bool,
|
||||||
|
calls: Vec<(
|
||||||
|
ir::BlockId,
|
||||||
|
usize,
|
||||||
|
HashSet<ir::RegisterId>,
|
||||||
|
Option<asm::Register>,
|
||||||
|
)>,
|
||||||
|
has_call: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Analysis {
|
||||||
|
fn is_temporary2(
|
||||||
|
&self,
|
||||||
|
reg: &ir::RegisterId,
|
||||||
|
lives: &HashMap<ir::RegisterId, HashSet<ir::RegisterId>>,
|
||||||
|
) -> bool {
|
||||||
|
for (call_bid, call_iid, call_args, _) in &self.calls {
|
||||||
|
let lives_before = lives
|
||||||
|
.get(&ir::RegisterId::temp(*call_bid, *call_iid))
|
||||||
|
.unwrap();
|
||||||
|
let lives_after = lives
|
||||||
|
.get(&ir::RegisterId::temp(*call_bid, call_iid + 1))
|
||||||
|
.unwrap();
|
||||||
|
if lives_before.contains(reg) && (call_args.contains(reg) || lives_after.contains(reg))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn analyze_function(
|
||||||
|
code: &ir::FunctionDefinition,
|
||||||
|
signature: &ir::FunctionSignature,
|
||||||
|
structs: &HashMap<String, Option<ir::Dtype>>,
|
||||||
|
) -> Analysis {
|
||||||
|
let (num_int_args, num_float_args, primitive_arg_reg_index) =
|
||||||
|
get_number_of_register_arguments(&signature.ret, &signature.params, structs);
|
||||||
|
let is_a0_return_pointer = is_struct(&signature.ret, structs).is_some_and(|size| size > 16);
|
||||||
|
let mut calls = Vec::new();
|
||||||
|
|
||||||
|
for (bid, block) in &code.blocks {
|
||||||
|
for (iid, inst) in block.instructions.iter().enumerate() {
|
||||||
|
match inst.deref() {
|
||||||
|
ir::Instruction::Call { callee, args, .. } => {
|
||||||
|
let mut used = HashSet::new();
|
||||||
|
mark_as_used(callee, &mut used);
|
||||||
|
for arg in args {
|
||||||
|
mark_as_used(arg, &mut used);
|
||||||
|
}
|
||||||
|
|
||||||
|
let return_type = callee
|
||||||
|
.dtype()
|
||||||
|
.get_pointer_inner()
|
||||||
|
.unwrap()
|
||||||
|
.get_function_inner()
|
||||||
|
.unwrap()
|
||||||
|
.0
|
||||||
|
.clone();
|
||||||
|
let ret_asm_reg = if is_integer(&return_type) {
|
||||||
|
Some(asm::Register::A0)
|
||||||
|
} else if is_float(&return_type) {
|
||||||
|
Some(asm::Register::FA0)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
calls.push((*bid, iid, used, ret_asm_reg));
|
||||||
|
}
|
||||||
|
ir::Instruction::Store { value, .. } => {
|
||||||
|
if is_struct(&value.dtype(), structs).is_some() {
|
||||||
|
calls.push((*bid, iid, HashSet::new(), None)); // memcpy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ir::Instruction::Load { ptr } => {
|
||||||
|
if is_struct(ptr.dtype().get_pointer_inner().unwrap(), structs).is_some() {
|
||||||
|
calls.push((*bid, iid, HashSet::new(), None)); // memcpy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let has_memcpy_in_prologue = signature.params.iter().any(|param| {
|
||||||
|
if let Some(size) = is_struct(param, structs) {
|
||||||
|
size > 16
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let has_call = has_memcpy_in_prologue || !calls.is_empty();
|
||||||
|
|
||||||
|
Analysis {
|
||||||
|
num_int_args,
|
||||||
|
num_float_args,
|
||||||
|
primitive_arg_reg_index,
|
||||||
|
is_a0_return_pointer,
|
||||||
|
has_memcpy_in_prologue,
|
||||||
|
calls,
|
||||||
|
has_call,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct Context {
|
struct Context {
|
||||||
insts: Vec<asm::Instruction>,
|
insts: Vec<asm::Instruction>,
|
||||||
stack_offsets: HashMap<ir::RegisterId, u64>,
|
stack_offsets: HashMap<ir::RegisterId, u64>,
|
||||||
@@ -649,11 +732,11 @@ impl Asmgen {
|
|||||||
stack_allocation += 8; // s0
|
stack_allocation += 8; // s0
|
||||||
let mut saved_reg_offset = 8;
|
let mut saved_reg_offset = 8;
|
||||||
|
|
||||||
if inference_graph.has_call {
|
if inference_graph.analysis.has_call {
|
||||||
stack_allocation += 8; // ra
|
stack_allocation += 8; // ra
|
||||||
saved_reg_offset += 8;
|
saved_reg_offset += 8;
|
||||||
}
|
}
|
||||||
if inference_graph.is_a0_return_pointer {
|
if inference_graph.analysis.is_a0_return_pointer {
|
||||||
stack_allocation += 8; // a0
|
stack_allocation += 8; // a0
|
||||||
saved_reg_offset += 8;
|
saved_reg_offset += 8;
|
||||||
}
|
}
|
||||||
@@ -718,7 +801,7 @@ impl Asmgen {
|
|||||||
stack_allocation,
|
stack_allocation,
|
||||||
&mut insts,
|
&mut insts,
|
||||||
);
|
);
|
||||||
if inference_graph.has_call {
|
if inference_graph.analysis.has_call {
|
||||||
insts.push(asm::Instruction::SType {
|
insts.push(asm::Instruction::SType {
|
||||||
instr: asm::SType::SD,
|
instr: asm::SType::SD,
|
||||||
rs1: asm::Register::S0,
|
rs1: asm::Register::S0,
|
||||||
@@ -726,7 +809,7 @@ impl Asmgen {
|
|||||||
imm: asm::Immediate::Value(!16 + 1),
|
imm: asm::Immediate::Value(!16 + 1),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if inference_graph.is_a0_return_pointer {
|
if inference_graph.analysis.is_a0_return_pointer {
|
||||||
insts.push(asm::Instruction::SType {
|
insts.push(asm::Instruction::SType {
|
||||||
instr: asm::SType::SD,
|
instr: asm::SType::SD,
|
||||||
rs1: asm::Register::S0,
|
rs1: asm::Register::S0,
|
||||||
@@ -1053,7 +1136,7 @@ impl Asmgen {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if context.inference_graph.has_call {
|
if context.inference_graph.analysis.has_call {
|
||||||
context.insts.push(asm::Instruction::IType {
|
context.insts.push(asm::Instruction::IType {
|
||||||
instr: asm::IType::LD,
|
instr: asm::IType::LD,
|
||||||
rd: asm::Register::Ra,
|
rd: asm::Register::Ra,
|
||||||
@@ -1960,12 +2043,14 @@ impl Asmgen {
|
|||||||
// TODO
|
// TODO
|
||||||
if is_integer(return_type) {
|
if is_integer(return_type) {
|
||||||
if let Some(rd) = context.inference_graph.get_register(&rid) {
|
if let Some(rd) = context.inference_graph.get_register(&rid) {
|
||||||
context
|
if rd != asm::Register::A0 {
|
||||||
.insts
|
context
|
||||||
.push(asm::Instruction::Pseudo(asm::Pseudo::Mv {
|
.insts
|
||||||
rd,
|
.push(asm::Instruction::Pseudo(asm::Pseudo::Mv {
|
||||||
rs: asm::Register::A0,
|
rd,
|
||||||
}));
|
rs: asm::Register::A0,
|
||||||
|
}));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self.translate_store_result(
|
self.translate_store_result(
|
||||||
&rid,
|
&rid,
|
||||||
@@ -1976,14 +2061,16 @@ impl Asmgen {
|
|||||||
}
|
}
|
||||||
} else if is_float(return_type) {
|
} else if is_float(return_type) {
|
||||||
if let Some(rd) = context.inference_graph.get_register(&rid) {
|
if let Some(rd) = context.inference_graph.get_register(&rid) {
|
||||||
context
|
if rd != asm::Register::FA0 {
|
||||||
.insts
|
context
|
||||||
.push(asm::Instruction::Pseudo(asm::Pseudo::Fmv {
|
.insts
|
||||||
data_size: asm::DataSize::try_from(return_type.clone())
|
.push(asm::Instruction::Pseudo(asm::Pseudo::Fmv {
|
||||||
.unwrap(),
|
data_size: asm::DataSize::try_from(return_type.clone())
|
||||||
rd,
|
.unwrap(),
|
||||||
rs: asm::Register::FA0,
|
rd,
|
||||||
}));
|
rs: asm::Register::FA0,
|
||||||
|
}));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self.translate_store_result(
|
self.translate_store_result(
|
||||||
&rid,
|
&rid,
|
||||||
@@ -2153,9 +2240,14 @@ impl Asmgen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if is_signed == target_is_signed {
|
} else if is_signed == target_is_signed {
|
||||||
context
|
if rd != rs1 {
|
||||||
.insts
|
context
|
||||||
.push(asm::Instruction::Pseudo(asm::Pseudo::Mv { rd, rs: rs1 }))
|
.insts
|
||||||
|
.push(asm::Instruction::Pseudo(asm::Pseudo::Mv {
|
||||||
|
rd,
|
||||||
|
rs: rs1,
|
||||||
|
}));
|
||||||
|
}
|
||||||
} else if *target_is_signed {
|
} else if *target_is_signed {
|
||||||
let rs2 = get_rhs_register(&value_dtype);
|
let rs2 = get_rhs_register(&value_dtype);
|
||||||
context
|
context
|
||||||
@@ -2216,7 +2308,7 @@ impl Asmgen {
|
|||||||
rs1,
|
rs1,
|
||||||
context,
|
context,
|
||||||
);
|
);
|
||||||
} else {
|
} else if rd != rs1 {
|
||||||
context
|
context
|
||||||
.insts
|
.insts
|
||||||
.push(asm::Instruction::Pseudo(asm::Pseudo::Mv {
|
.push(asm::Instruction::Pseudo(asm::Pseudo::Mv {
|
||||||
@@ -2447,7 +2539,7 @@ impl Asmgen {
|
|||||||
let default_label = self.translate_label(name, default, context, structs);
|
let default_label = self.translate_label(name, default, context, structs);
|
||||||
|
|
||||||
for (case, arg) in cases {
|
for (case, arg) in cases {
|
||||||
let _ = self.translate_load_operand(
|
let rs2 = self.translate_load_operand(
|
||||||
&ir::Operand::constant(case.clone()),
|
&ir::Operand::constant(case.clone()),
|
||||||
rs2,
|
rs2,
|
||||||
context,
|
context,
|
||||||
@@ -2611,6 +2703,7 @@ impl Asmgen {
|
|||||||
ir::Operand::Constant(constant) => {
|
ir::Operand::Constant(constant) => {
|
||||||
match constant {
|
match constant {
|
||||||
ir::Constant::Undef { .. } => (), // Do nothing
|
ir::Constant::Undef { .. } => (), // Do nothing
|
||||||
|
ir::Constant::Int { value: 0, .. } => return asm::Register::Zero,
|
||||||
&ir::Constant::Int { value, .. } => {
|
&ir::Constant::Int { value, .. } => {
|
||||||
context
|
context
|
||||||
.insts
|
.insts
|
||||||
@@ -2703,7 +2796,14 @@ impl Asmgen {
|
|||||||
structs: &HashMap<String, Option<ir::Dtype>>,
|
structs: &HashMap<String, Option<ir::Dtype>>,
|
||||||
) -> Vec<asm::Instruction> {
|
) -> Vec<asm::Instruction> {
|
||||||
let bid = arg.bid;
|
let bid = arg.bid;
|
||||||
|
let mut lives = context
|
||||||
|
.inference_graph
|
||||||
|
.lives
|
||||||
|
.get(&ir::RegisterId::temp(bid, 0))
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or_default();
|
||||||
let mut referenced_org_phinodes = HashSet::new();
|
let mut referenced_org_phinodes = HashSet::new();
|
||||||
|
|
||||||
for arg in &arg.args {
|
for arg in &arg.args {
|
||||||
if let ir::Operand::Register {
|
if let ir::Operand::Register {
|
||||||
rid: ir::RegisterId::Arg { bid: arg_bid, aid },
|
rid: ir::RegisterId::Arg { bid: arg_bid, aid },
|
||||||
@@ -2714,13 +2814,67 @@ impl Asmgen {
|
|||||||
let _ = referenced_org_phinodes.insert(aid);
|
let _ = referenced_org_phinodes.insert(aid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let ir::Operand::Register { rid, .. } = arg {
|
||||||
|
let _ = lives.insert(*rid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut used_asm_registers = lives
|
||||||
|
.iter()
|
||||||
|
.filter_map(|rid| context.inference_graph.get_register(rid))
|
||||||
|
.collect::<HashSet<_>>();
|
||||||
|
|
||||||
|
let mut phinode_temp_registers = HashMap::new();
|
||||||
let mut phinode_stack_offsets = HashMap::new();
|
let mut phinode_stack_offsets = HashMap::new();
|
||||||
let mut phinode_stack_allocations = 0;
|
let mut phinode_stack_allocations = 0;
|
||||||
|
|
||||||
for (aid, arg) in arg.args.iter().enumerate() {
|
for (aid, arg) in arg.args.iter().enumerate() {
|
||||||
if referenced_org_phinodes.contains(&aid) {
|
if referenced_org_phinodes.contains(&aid) {
|
||||||
|
let dtype = arg.dtype();
|
||||||
|
// 자리가 있으면 기존 phinode 값을 레지스터에 백업
|
||||||
|
if is_integer(&dtype) {
|
||||||
|
let used_asm_a_registers = used_asm_registers
|
||||||
|
.iter()
|
||||||
|
.filter_map(|asm_reg| {
|
||||||
|
if let asm::Register::Arg(asm::RegisterType::Integer, i) = asm_reg {
|
||||||
|
Some(*i)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let smallest_a = smallest_missing_integer(&used_asm_a_registers, 0);
|
||||||
|
if smallest_a <= 7 {
|
||||||
|
let asm_reg = asm::Register::arg(asm::RegisterType::Integer, smallest_a);
|
||||||
|
let _ = phinode_temp_registers.insert(aid, asm_reg);
|
||||||
|
let _ = used_asm_registers.insert(asm_reg);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if is_float(&dtype) {
|
||||||
|
let used_asm_a_registers = used_asm_registers
|
||||||
|
.iter()
|
||||||
|
.filter_map(|asm_reg| {
|
||||||
|
if let asm::Register::Arg(asm::RegisterType::FloatingPoint, i) = asm_reg
|
||||||
|
{
|
||||||
|
Some(*i)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let smallest_a = smallest_missing_integer(&used_asm_a_registers, 0);
|
||||||
|
if smallest_a <= 7 {
|
||||||
|
let asm_reg =
|
||||||
|
asm::Register::arg(asm::RegisterType::FloatingPoint, smallest_a);
|
||||||
|
let _ = phinode_temp_registers.insert(aid, asm_reg);
|
||||||
|
let _ = used_asm_registers.insert(asm_reg);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 자리가 없으면 스택에
|
||||||
let _ = phinode_stack_offsets.insert(aid, phinode_stack_allocations);
|
let _ = phinode_stack_offsets.insert(aid, phinode_stack_allocations);
|
||||||
phinode_stack_allocations +=
|
phinode_stack_allocations +=
|
||||||
ceil_to_multiple_of_16(get_dtype_size(&arg.dtype(), structs));
|
ceil_to_multiple_of_16(get_dtype_size(&arg.dtype(), structs));
|
||||||
@@ -2737,32 +2891,50 @@ impl Asmgen {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Swap Issue를 해결하기 위해 스택에 기존 phinode값 저장 (필요한 것만)
|
// Swap Issue를 해결하기 위해 스택/레지스터에 기존 phinode값 저장 (필요한 것만)
|
||||||
let bid = arg.bid;
|
let bid = arg.bid;
|
||||||
for (aid, arg) in arg.args.iter().enumerate() {
|
for (aid, arg) in arg.args.iter().enumerate() {
|
||||||
if referenced_org_phinodes.contains(&aid) {
|
if referenced_org_phinodes.contains(&aid) {
|
||||||
let rid = ir::RegisterId::arg(bid, aid);
|
let rid = ir::RegisterId::arg(bid, aid);
|
||||||
let arg_dtype = arg.dtype();
|
let arg_dtype = arg.dtype();
|
||||||
let rs1 = if let Some(rs1) = context.inference_graph.get_register(&rid) {
|
let rs1: asm::Register =
|
||||||
rs1
|
if let Some(rs1) = context.inference_graph.get_register(&rid) {
|
||||||
|
rs1
|
||||||
|
} else {
|
||||||
|
let rs1 = get_lhs_register(&arg_dtype);
|
||||||
|
self.translate_load(
|
||||||
|
asm::IType::load(arg_dtype.clone()),
|
||||||
|
rs1,
|
||||||
|
asm::Register::S0,
|
||||||
|
context.stack_offsets[&rid],
|
||||||
|
&mut phinode_insts,
|
||||||
|
);
|
||||||
|
rs1
|
||||||
|
};
|
||||||
|
if let Some(asm_reg) = phinode_temp_registers.get(&aid) {
|
||||||
|
if is_integer(&arg_dtype) {
|
||||||
|
phinode_insts.push(asm::Instruction::Pseudo(asm::Pseudo::Mv {
|
||||||
|
rd: *asm_reg,
|
||||||
|
rs: rs1,
|
||||||
|
}));
|
||||||
|
} else if is_float(&arg_dtype) {
|
||||||
|
phinode_insts.push(asm::Instruction::Pseudo(asm::Pseudo::Fmv {
|
||||||
|
data_size: asm::DataSize::try_from(arg_dtype).unwrap(),
|
||||||
|
rd: *asm_reg,
|
||||||
|
rs: rs1,
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let rs1 = get_lhs_register(&arg_dtype);
|
self.translate_store(
|
||||||
self.translate_load(
|
asm::SType::store(arg_dtype),
|
||||||
asm::IType::load(arg_dtype.clone()),
|
asm::Register::Sp,
|
||||||
rs1,
|
rs1,
|
||||||
asm::Register::S0,
|
phinode_stack_offsets[&aid],
|
||||||
context.stack_offsets[&rid],
|
|
||||||
&mut phinode_insts,
|
&mut phinode_insts,
|
||||||
);
|
);
|
||||||
rs1
|
}
|
||||||
};
|
|
||||||
self.translate_store(
|
|
||||||
asm::SType::store(arg_dtype),
|
|
||||||
asm::Register::Sp,
|
|
||||||
rs1,
|
|
||||||
phinode_stack_offsets[&aid],
|
|
||||||
&mut phinode_insts,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2776,6 +2948,23 @@ impl Asmgen {
|
|||||||
match arg {
|
match arg {
|
||||||
ir::Operand::Constant(constant) => match constant {
|
ir::Operand::Constant(constant) => match constant {
|
||||||
ir::Constant::Undef { .. } => continue, // Do nothing
|
ir::Constant::Undef { .. } => continue, // Do nothing
|
||||||
|
ir::Constant::Int { value: 0, .. } => {
|
||||||
|
if is_spilled {
|
||||||
|
self.translate_store(
|
||||||
|
asm::SType::store(arg.dtype()),
|
||||||
|
asm::Register::S0,
|
||||||
|
asm::Register::Zero,
|
||||||
|
context.stack_offsets[&ir::RegisterId::arg(bid, aid)],
|
||||||
|
&mut phinode_insts,
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
phinode_insts.push(asm::Instruction::Pseudo(asm::Pseudo::Mv {
|
||||||
|
rd,
|
||||||
|
rs: asm::Register::Zero,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
ir::Constant::Int {
|
ir::Constant::Int {
|
||||||
value,
|
value,
|
||||||
width,
|
width,
|
||||||
@@ -2793,13 +2982,32 @@ impl Asmgen {
|
|||||||
} = arg_rid
|
} = arg_rid
|
||||||
{
|
{
|
||||||
if *arg_bid == bid {
|
if *arg_bid == bid {
|
||||||
self.translate_load(
|
if let Some(asm_reg) = phinode_temp_registers.get(arg_aid) {
|
||||||
asm::IType::load(arg_dtype),
|
if is_integer(&arg_dtype) {
|
||||||
rd,
|
phinode_insts.push(asm::Instruction::Pseudo(asm::Pseudo::Mv {
|
||||||
asm::Register::Sp,
|
rd,
|
||||||
phinode_stack_offsets[arg_aid],
|
rs: *asm_reg,
|
||||||
&mut phinode_insts,
|
}));
|
||||||
);
|
} else if is_float(&arg_dtype) {
|
||||||
|
phinode_insts.push(asm::Instruction::Pseudo(
|
||||||
|
asm::Pseudo::Fmv {
|
||||||
|
data_size: asm::DataSize::try_from(arg_dtype).unwrap(),
|
||||||
|
rd,
|
||||||
|
rs: *asm_reg,
|
||||||
|
},
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.translate_load(
|
||||||
|
asm::IType::load(arg_dtype),
|
||||||
|
rd,
|
||||||
|
asm::Register::Sp,
|
||||||
|
phinode_stack_offsets[arg_aid],
|
||||||
|
&mut phinode_insts,
|
||||||
|
);
|
||||||
|
}
|
||||||
} else if let Some(rs1) = context.inference_graph.get_register(arg_rid) {
|
} else if let Some(rs1) = context.inference_graph.get_register(arg_rid) {
|
||||||
if is_integer(&arg_dtype) {
|
if is_integer(&arg_dtype) {
|
||||||
phinode_insts.push(asm::Instruction::Pseudo(asm::Pseudo::Mv {
|
phinode_insts.push(asm::Instruction::Pseudo(asm::Pseudo::Mv {
|
||||||
|
|||||||
Reference in New Issue
Block a user