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