This commit is contained in:
static
2025-06-17 07:53:11 +00:00
parent 4c91663320
commit 982cd19af0

View File

@@ -234,7 +234,7 @@ impl InferenceGraph {
*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) = let (mut num_int_args, mut num_float_args, primitive_arg_reg_index) =
get_number_of_register_arguments(&signature.ret, &signature.params, structs); get_number_of_register_arguments(&signature.ret, &signature.params, structs);
let mut has_call = false; let mut has_call = false;
let mut is_a0_return_pointer = false; let mut is_a0_return_pointer = false;
@@ -286,13 +286,32 @@ impl InferenceGraph {
} }
} }
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();
*asm_reg = asm::Register::arg(
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,
);
}
}
}
let mut vertices_order = vertices let mut vertices_order = vertices
.keys() .keys()
.map(|rid| (*rid, num_of_edges.get(rid).cloned().unwrap_or_default())) .map(|rid| (*rid, num_of_edges.get(rid).cloned().unwrap_or_default()))
.sorted_by(|(_, v1), (_, v2)| v2.cmp(v1)); .sorted_by(|(_, v1), (_, v2)| v2.cmp(v1));
for (rid, count) in vertices_order { for (rid, count) in vertices_order {
if count == 0 { if count == 0 || vertices[&rid].1 != asm::Register::Zero {
continue; continue;
} }
@@ -546,7 +565,7 @@ impl Asmgen {
if let Some(definition) = definition { if let Some(definition) = definition {
let graph = InferenceGraph::new(definition, signature, structs); let graph = InferenceGraph::new(definition, signature, structs);
// println!("asdf: {:?}", graph.vertices); // println!("{name} asdf: {:?}", graph.vertices);
let mut context = let mut context =
self.translate_prologue(signature, definition, structs, graph); self.translate_prologue(signature, definition, structs, graph);
@@ -758,7 +777,9 @@ impl Asmgen {
let rs = asm::Register::arg(asm::RegisterType::Integer, num_int_args); let rs = asm::Register::arg(asm::RegisterType::Integer, num_int_args);
num_int_args += 1; num_int_args += 1;
if let Some(rd) = rd { if let Some(rd) = rd {
insts.push(asm::Instruction::Pseudo(asm::Pseudo::Mv { rd, rs })); if rd != rs {
insts.push(asm::Instruction::Pseudo(asm::Pseudo::Mv { rd, rs }));
}
} else { } else {
self.translate_store( self.translate_store(
asm::SType::store(dtype.clone()), asm::SType::store(dtype.clone()),
@@ -772,11 +793,13 @@ impl Asmgen {
let rs = asm::Register::arg(asm::RegisterType::FloatingPoint, num_float_args); let rs = asm::Register::arg(asm::RegisterType::FloatingPoint, num_float_args);
num_float_args += 1; num_float_args += 1;
if let Some(rd) = rd { if let Some(rd) = rd {
insts.push(asm::Instruction::Pseudo(asm::Pseudo::Fmv { if rd != rs {
data_size: asm::DataSize::try_from(dtype.clone()).unwrap(), insts.push(asm::Instruction::Pseudo(asm::Pseudo::Fmv {
rd, data_size: asm::DataSize::try_from(dtype.clone()).unwrap(),
rs, rd,
})); rs,
}));
}
} else { } else {
self.translate_store( self.translate_store(
asm::SType::store(dtype.clone()), asm::SType::store(dtype.clone()),
@@ -2265,48 +2288,76 @@ impl Asmgen {
ir::Instruction::GetElementPtr { ptr, offset, .. } => { ir::Instruction::GetElementPtr { ptr, offset, .. } => {
let ptr_dtype = ptr.dtype(); let ptr_dtype = ptr.dtype();
let offset_dtype = offset.dtype(); let offset_dtype = offset.dtype();
let rs2 = self.translate_load_operand( let rd = rd.unwrap_or(get_res_register(&ptr_dtype));
offset,
get_rhs_register(&offset_dtype),
context,
);
match ptr { match ptr {
ir::Operand::Constant(ir::Constant::GlobalVariable { ir::Operand::Constant(ir::Constant::GlobalVariable {
name: ptr_name, name: ptr_name,
.. ..
}) => { }) => {
let rd = rd.unwrap_or(get_res_register(&ptr_dtype));
context context
.insts .insts
.push(asm::Instruction::Pseudo(asm::Pseudo::La { .push(asm::Instruction::Pseudo(asm::Pseudo::La {
rd: asm::Register::T0, rd: asm::Register::T0,
symbol: asm::Label(ptr_name.clone()), symbol: asm::Label(ptr_name.clone()),
})); }));
context.insts.push(asm::Instruction::RType { let mut imm_mode = false;
instr: asm::RType::add(ptr_dtype.clone()), if let Some(ir::Constant::Int { value, .. }) = offset.get_constant() {
rd, if (-2048..=2047).contains(&(*value as i128)) {
rs1: asm::Register::T0, context.insts.push(asm::Instruction::IType {
rs2: Some(rs2), instr: asm::IType::ADDI,
}); rd,
rs1: asm::Register::T0,
imm: asm::Immediate::Value(*value as u64),
});
imm_mode = true;
}
}
if !imm_mode {
let rs2 = self.translate_load_operand(
offset,
get_rhs_register(&offset_dtype),
context,
);
context.insts.push(asm::Instruction::RType {
instr: asm::RType::add(ptr_dtype.clone()),
rd,
rs1: asm::Register::T0,
rs2: Some(rs2),
});
}
if is_spilled { if is_spilled {
self.translate_store_result(&rid, ptr_dtype, rd, context); self.translate_store_result(&rid, ptr_dtype, rd, context);
} }
} }
ir::Operand::Register { rid: ptr_rid, .. } => match ptr_rid { ir::Operand::Register { rid: ptr_rid, .. } => match ptr_rid {
ir::RegisterId::Local { aid } => { ir::RegisterId::Local { aid } => {
let rd = rd.unwrap_or(get_res_register(&ptr_dtype)); if let Some(ir::Constant::Int { value, .. }) = offset.get_constant()
self.translate_addi( {
rd, self.translate_addi(
asm::Register::S0, rd,
context.stack_offsets[ptr_rid], asm::Register::S0,
&mut context.insts, context.stack_offsets[ptr_rid] + (*value as u64),
); &mut context.insts,
context.insts.push(asm::Instruction::RType { );
instr: asm::RType::add(ptr_dtype.clone()), } else {
rd, let rs2 = self.translate_load_operand(
rs1: rd, offset,
rs2: Some(rs2), get_rhs_register(&offset_dtype),
}); context,
);
self.translate_addi(
rd,
asm::Register::S0,
context.stack_offsets[ptr_rid],
&mut context.insts,
);
context.insts.push(asm::Instruction::RType {
instr: asm::RType::add(ptr_dtype.clone()),
rd,
rs1: rd,
rs2: Some(rs2),
});
}
if is_spilled { if is_spilled {
self.translate_store_result(&rid, ptr_dtype, rd, context); self.translate_store_result(&rid, ptr_dtype, rd, context);
} }
@@ -2317,13 +2368,32 @@ impl Asmgen {
get_lhs_register(&ptr_dtype), get_lhs_register(&ptr_dtype),
context, context,
); );
let rd = rd.unwrap_or(get_res_register(&ptr_dtype)); let mut imm_mode = false;
context.insts.push(asm::Instruction::RType { if let Some(ir::Constant::Int { value, .. }) = offset.get_constant()
instr: asm::RType::add(ptr_dtype.clone()), {
rd, if (-2048..=2047).contains(&(*value as i128)) {
rs1, context.insts.push(asm::Instruction::IType {
rs2: Some(rs2), instr: asm::IType::ADDI,
}); rd,
rs1,
imm: asm::Immediate::Value(*value as u64),
});
imm_mode = true;
}
}
if !imm_mode {
let rs2 = self.translate_load_operand(
offset,
get_rhs_register(&offset_dtype),
context,
);
context.insts.push(asm::Instruction::RType {
instr: asm::RType::add(ptr_dtype.clone()),
rd,
rs1,
rs2: Some(rs2),
});
}
if is_spilled { if is_spilled {
self.translate_store_result(&rid, ptr_dtype, rd, context); self.translate_store_result(&rid, ptr_dtype, rd, context);
} }
@@ -2632,13 +2702,29 @@ impl Asmgen {
context: &Context, context: &Context,
structs: &HashMap<String, Option<ir::Dtype>>, structs: &HashMap<String, Option<ir::Dtype>>,
) -> Vec<asm::Instruction> { ) -> Vec<asm::Instruction> {
let bid = arg.bid;
let mut referenced_org_phinodes = HashSet::new();
for arg in &arg.args {
if let ir::Operand::Register {
rid: ir::RegisterId::Arg { bid: arg_bid, aid },
..
} = arg
{
if *arg_bid == bid {
let _ = referenced_org_phinodes.insert(aid);
}
}
}
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() {
let _ = phinode_stack_offsets.insert(aid, phinode_stack_allocations); if referenced_org_phinodes.contains(&aid) {
phinode_stack_allocations += let _ = phinode_stack_offsets.insert(aid, phinode_stack_allocations);
ceil_to_multiple_of_16(get_dtype_size(&arg.dtype(), structs)); phinode_stack_allocations +=
ceil_to_multiple_of_16(get_dtype_size(&arg.dtype(), structs));
}
} }
let mut phinode_insts = Vec::new(); let mut phinode_insts = Vec::new();
@@ -2651,31 +2737,33 @@ 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() {
let rid = ir::RegisterId::arg(bid, aid); if referenced_org_phinodes.contains(&aid) {
let arg_dtype = arg.dtype(); let rid = ir::RegisterId::arg(bid, aid);
let rs1 = if let Some(rs1) = context.inference_graph.get_register(&rid) { let arg_dtype = arg.dtype();
rs1 let rs1 = if let Some(rs1) = context.inference_graph.get_register(&rid) {
} else { rs1
let rs1 = get_lhs_register(&arg_dtype); } else {
self.translate_load( let rs1 = get_lhs_register(&arg_dtype);
asm::IType::load(arg_dtype.clone()), self.translate_load(
asm::IType::load(arg_dtype.clone()),
rs1,
asm::Register::S0,
context.stack_offsets[&rid],
&mut phinode_insts,
);
rs1
};
self.translate_store(
asm::SType::store(arg_dtype),
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,
);
} }
for (aid, arg) in arg.args.iter().enumerate() { for (aid, arg) in arg.args.iter().enumerate() {
@@ -3069,20 +3157,23 @@ fn get_struct_dtype<'a>(
fn get_number_of_register_arguments( fn get_number_of_register_arguments(
return_type: &ir::Dtype, return_type: &ir::Dtype,
params: &Vec<ir::Dtype>, params: &[ir::Dtype],
structs: &HashMap<String, Option<ir::Dtype>>, structs: &HashMap<String, Option<ir::Dtype>>,
) -> (i32, i32) { ) -> (i32, i32, HashMap<usize, i32>) {
let mut num_int_args = 0; let mut num_int_args = 0;
let mut num_float_args = 0; let mut num_float_args = 0;
let mut primitive_arg_reg_index = HashMap::new();
if is_struct(return_type, structs).is_some_and(|size| size > 16) { if is_struct(return_type, structs).is_some_and(|size| size > 16) {
num_int_args += 1; num_int_args += 1;
} }
for dtype in params { for (i, dtype) in params.iter().enumerate() {
if is_integer(dtype) { if is_integer(dtype) {
let _ = primitive_arg_reg_index.insert(i, num_int_args);
num_int_args += 1; num_int_args += 1;
} else if is_float(dtype) { } else if is_float(dtype) {
let _ = primitive_arg_reg_index.insert(i, num_float_args);
num_float_args += 1; num_float_args += 1;
} else if let Some(size) = is_struct(dtype, structs) { } else if let Some(size) = is_struct(dtype, structs) {
if size > 16 { if size > 16 {
@@ -3137,5 +3228,5 @@ fn get_number_of_register_arguments(
num_float_args = 1; num_float_args = 1;
} }
(num_int_args, num_float_args) (num_int_args, num_float_args, primitive_arg_reg_index)
} }