From 982cd19af0f16d449394d068428461676e1a17ac Mon Sep 17 00:00:00 2001 From: static Date: Tue, 17 Jun 2025 07:53:11 +0000 Subject: [PATCH] HW8 (6) --- src/asmgen/mod.rs | 227 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 159 insertions(+), 68 deletions(-) diff --git a/src/asmgen/mod.rs b/src/asmgen/mod.rs index a4416b0..ad2b686 100644 --- a/src/asmgen/mod.rs +++ b/src/asmgen/mod.rs @@ -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>, ) -> Vec { + 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, + params: &[ir::Dtype], structs: &HashMap>, -) -> (i32, i32) { +) -> (i32, i32, HashMap) { 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) }