Lab4: Implement basic scalar optimizations and lower Phi nodes to assembly
This commit is contained in:
@@ -31,6 +31,26 @@ uint32_t GetTypeSize(const ir::Type* type) {
|
||||
uint32_t GetAllocaSize(const ir::Instruction& inst) {
|
||||
auto type = inst.GetType();
|
||||
if (type->IsPtrInt32() || type->IsPtrFloat()) {
|
||||
// Check if any StoreInst in the parent function stores a pointer to this alloca
|
||||
auto* parent_bb = inst.GetParent();
|
||||
if (parent_bb) {
|
||||
auto* parent_func = parent_bb->GetParent();
|
||||
if (parent_func) {
|
||||
for (const auto& bbPtr : parent_func->GetBlocks()) {
|
||||
for (const auto& other_inst : bbPtr->GetInstructions()) {
|
||||
if (other_inst->GetOpcode() == ir::Opcode::Store) {
|
||||
auto* store = static_cast<const ir::StoreInst*>(other_inst.get());
|
||||
if (store->GetPtr() == &inst) {
|
||||
auto val_ty = store->GetValue()->GetType();
|
||||
if (val_ty->IsPtrInt32() || val_ty->IsPtrFloat()) {
|
||||
return 8; // Stores a 64-bit pointer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
return GetTypeSize(type.get());
|
||||
@@ -120,7 +140,8 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
||||
if (alloca->GetOpcode() == ir::Opcode::Alloca) {
|
||||
auto it = slots.find(alloca);
|
||||
if (it != slots.end()) {
|
||||
PhysReg val_reg = store.GetValue()->GetType()->IsFloat() ? PhysReg::S8 : PhysReg::W8;
|
||||
PhysReg val_reg = store.GetValue()->GetType()->IsFloat() ? PhysReg::S8 :
|
||||
(store.GetValue()->GetType()->IsPtrInt32() || store.GetValue()->GetType()->IsPtrFloat()) ? PhysReg::X8 : PhysReg::W8;
|
||||
EmitValueToReg(store.GetValue(), val_reg, slots, block);
|
||||
block.Append(Opcode::StoreStack, {Operand::Reg(val_reg), Operand::FrameIndex(it->second)});
|
||||
return;
|
||||
@@ -129,7 +150,8 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
||||
}
|
||||
|
||||
// Dynamic store
|
||||
PhysReg val_reg = store.GetValue()->GetType()->IsFloat() ? PhysReg::S8 : PhysReg::W8;
|
||||
PhysReg val_reg = store.GetValue()->GetType()->IsFloat() ? PhysReg::S8 :
|
||||
(store.GetValue()->GetType()->IsPtrInt32() || store.GetValue()->GetType()->IsPtrFloat()) ? PhysReg::X8 : PhysReg::W8;
|
||||
EmitValueToReg(store.GetValue(), val_reg, slots, block);
|
||||
EmitAddressToReg(store.GetPtr(), PhysReg::X9, slots, block);
|
||||
block.Append(Opcode::StrRegReg, {Operand::Reg(val_reg), Operand::Reg(PhysReg::X9)});
|
||||
@@ -144,7 +166,8 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
||||
if (alloca->GetOpcode() == ir::Opcode::Alloca) {
|
||||
auto it = slots.find(alloca);
|
||||
if (it != slots.end()) {
|
||||
PhysReg val_reg = load.GetType()->IsFloat() ? PhysReg::S8 : PhysReg::W8;
|
||||
PhysReg val_reg = load.GetType()->IsFloat() ? PhysReg::S8 :
|
||||
(load.GetType()->IsPtrInt32() || load.GetType()->IsPtrFloat()) ? PhysReg::X8 : PhysReg::W8;
|
||||
block.Append(Opcode::LoadStack, {Operand::Reg(val_reg), Operand::FrameIndex(it->second)});
|
||||
block.Append(Opcode::StoreStack, {Operand::Reg(val_reg), Operand::FrameIndex(dst_slot)});
|
||||
return;
|
||||
@@ -153,7 +176,8 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
||||
}
|
||||
|
||||
// Dynamic load
|
||||
PhysReg val_reg = load.GetType()->IsFloat() ? PhysReg::S8 : PhysReg::W8;
|
||||
PhysReg val_reg = load.GetType()->IsFloat() ? PhysReg::S8 :
|
||||
(load.GetType()->IsPtrInt32() || load.GetType()->IsPtrFloat()) ? PhysReg::X8 : PhysReg::W8;
|
||||
EmitAddressToReg(load.GetPtr(), PhysReg::X9, slots, block);
|
||||
block.Append(Opcode::LdrRegReg, {Operand::Reg(val_reg), Operand::Reg(PhysReg::X9)});
|
||||
block.Append(Opcode::StoreStack, {Operand::Reg(val_reg), Operand::FrameIndex(dst_slot)});
|
||||
@@ -301,22 +325,50 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
||||
}
|
||||
case ir::Opcode::Br: {
|
||||
auto& br = static_cast<const ir::BranchInst&>(inst);
|
||||
std::cerr << "DEBUG: Br is_conditional=" << br.IsConditional() << std::endl;
|
||||
|
||||
auto emit_phi_copies = [&](const ir::BasicBlock* succ) {
|
||||
if (!succ) return;
|
||||
for (const auto& succ_inst : succ->GetInstructions()) {
|
||||
if (succ_inst->GetOpcode() == ir::Opcode::Phi) {
|
||||
auto* phi = static_cast<const ir::PhiInst*>(succ_inst.get());
|
||||
const ir::Value* incoming_val = nullptr;
|
||||
for (size_t i = 0; i < phi->GetNumIncoming(); ++i) {
|
||||
if (phi->GetIncomingBlock(i) == inst.GetParent()) {
|
||||
incoming_val = phi->GetIncomingValue(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (incoming_val) {
|
||||
auto slot_it = slots.find(phi);
|
||||
if (slot_it != slots.end()) {
|
||||
int phi_slot = slot_it->second;
|
||||
PhysReg val_reg = phi->GetType()->IsFloat() ? PhysReg::S8 :
|
||||
(phi->GetType()->IsPtrInt32() || phi->GetType()->IsPtrFloat()) ? PhysReg::X8 : PhysReg::W8;
|
||||
EmitValueToReg(incoming_val, val_reg, slots, block);
|
||||
block.Append(Opcode::StoreStack, {Operand::Reg(val_reg), Operand::FrameIndex(phi_slot)});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (br.IsConditional()) {
|
||||
std::cerr << "DEBUG: Cond pointer=" << br.GetCondition() << std::endl;
|
||||
std::cerr << "DEBUG: True pointer=" << br.GetIfTrue() << " name=" << (br.GetIfTrue() ? br.GetIfTrue()->GetName() : "<null>") << std::endl;
|
||||
std::cerr << "DEBUG: False pointer=" << br.GetIfFalse() << " name=" << (br.GetIfFalse() ? br.GetIfFalse()->GetName() : "<null>") << std::endl;
|
||||
emit_phi_copies(br.GetIfTrue());
|
||||
emit_phi_copies(br.GetIfFalse());
|
||||
EmitValueToReg(br.GetCondition(), PhysReg::W8, slots, block);
|
||||
block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W9), Operand::Imm(0)});
|
||||
block.Append(Opcode::CmpRR, {Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::W9)});
|
||||
block.Append(Opcode::BCond, {Operand::Cond("ne"), Operand::Label(br.GetIfTrue()->GetName())});
|
||||
block.Append(Opcode::B, {Operand::Label(br.GetIfFalse()->GetName())});
|
||||
} else {
|
||||
std::cerr << "DEBUG: Dest pointer=" << br.GetDest() << " name=" << (br.GetDest() ? br.GetDest()->GetName() : "<null>") << std::endl;
|
||||
emit_phi_copies(br.GetDest());
|
||||
block.Append(Opcode::B, {Operand::Label(br.GetDest()->GetName())});
|
||||
}
|
||||
return;
|
||||
}
|
||||
case ir::Opcode::Phi: {
|
||||
return;
|
||||
}
|
||||
case ir::Opcode::Ret: {
|
||||
auto& ret = static_cast<const ir::ReturnInst&>(inst);
|
||||
if (ret.GetValue()) {
|
||||
@@ -369,8 +421,14 @@ void LowerInstruction(const ir::Instruction& inst, MachineFunction& function,
|
||||
slots.emplace(&inst, dst_slot);
|
||||
|
||||
// Load base pointer address into X8
|
||||
if (dynamic_cast<const ir::AllocaInst*>(gep.GetPtr()) || gep.GetPtr()->IsGlobalValue()) {
|
||||
if (gep.GetPtr()->IsGlobalValue()) {
|
||||
EmitAddressToReg(gep.GetPtr(), PhysReg::X8, slots, block);
|
||||
} else if (auto* alloca = dynamic_cast<const ir::AllocaInst*>(gep.GetPtr())) {
|
||||
if (alloca->GetType()->IsArray()) {
|
||||
EmitAddressToReg(gep.GetPtr(), PhysReg::X8, slots, block);
|
||||
} else {
|
||||
EmitValueToReg(gep.GetPtr(), PhysReg::X8, slots, block);
|
||||
}
|
||||
} else {
|
||||
EmitValueToReg(gep.GetPtr(), PhysReg::X8, slots, block);
|
||||
}
|
||||
@@ -428,6 +486,16 @@ std::vector<std::unique_ptr<MachineFunction>> LowerToMIR(const ir::Module& modul
|
||||
bb_map[bbPtr.get()] = &mbb;
|
||||
}
|
||||
|
||||
// Pre-allocate stack slots for all Phi instructions in the function
|
||||
for (const auto& bbPtr : func.GetBlocks()) {
|
||||
for (const auto& inst : bbPtr->GetInstructions()) {
|
||||
if (inst->GetOpcode() == ir::Opcode::Phi) {
|
||||
int slot = machine_func->CreateFrameIndex(GetTypeSize(inst->GetType().get()));
|
||||
slots.emplace(inst.get(), slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto& entry_block = *bb_map.at(func.GetEntry());
|
||||
|
||||
// Lower function arguments at the start of the entry block
|
||||
|
||||
Reference in New Issue
Block a user