bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) { auto It = Functions.find(MF.getName()); if (It == Functions.end()) return error(Twine("no machine function information for function '") + MF.getName() + "' in the MIR file"); // TODO: Recreate the machine function. const yaml::MachineFunction &YamlMF = *It->getValue(); if (YamlMF.Alignment) MF.setAlignment(YamlMF.Alignment); MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice); MF.setHasInlineAsm(YamlMF.HasInlineAsm); PerFunctionMIParsingState PFS; if (initializeRegisterInfo(MF, MF.getRegInfo(), YamlMF, PFS.VirtualRegisterSlots)) return true; if (initializeFrameInfo(*MF.getFunction(), *MF.getFrameInfo(), YamlMF, PFS.StackObjectSlots, PFS.FixedStackObjectSlots)) return true; const auto &F = *MF.getFunction(); for (const auto &YamlMBB : YamlMF.BasicBlocks) { const BasicBlock *BB = nullptr; const yaml::StringValue &Name = YamlMBB.Name; if (!Name.Value.empty()) { BB = dyn_cast_or_null<BasicBlock>( F.getValueSymbolTable().lookup(Name.Value)); if (!BB) return error(Name.SourceRange.Start, Twine("basic block '") + Name.Value + "' is not defined in the function '" + MF.getName() + "'"); } auto *MBB = MF.CreateMachineBasicBlock(BB); MF.insert(MF.end(), MBB); bool WasInserted = PFS.MBBSlots.insert(std::make_pair(YamlMBB.ID, MBB)).second; if (!WasInserted) return error(Twine("redefinition of machine basic block with id #") + Twine(YamlMBB.ID)); } if (YamlMF.BasicBlocks.empty()) return error(Twine("machine function '") + Twine(MF.getName()) + "' requires at least one machine basic block in its body"); // Initialize the jump table after creating all the MBBs so that the MBB // references can be resolved. if (!YamlMF.JumpTableInfo.Entries.empty() && initializeJumpTableInfo(MF, YamlMF.JumpTableInfo, PFS)) return true; // Initialize the machine basic blocks after creating them all so that the // machine instructions parser can resolve the MBB references. unsigned I = 0; for (const auto &YamlMBB : YamlMF.BasicBlocks) { if (initializeMachineBasicBlock(MF, *MF.getBlockNumbered(I++), YamlMBB, PFS)) return true; } return false; }
bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) { auto It = Functions.find(MF.getName()); if (It == Functions.end()) return error(Twine("no machine function information for function '") + MF.getName() + "' in the MIR file"); // TODO: Recreate the machine function. const yaml::MachineFunction &YamlMF = *It->getValue(); if (YamlMF.Alignment) MF.setAlignment(YamlMF.Alignment); MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice); MF.setHasInlineAsm(YamlMF.HasInlineAsm); if (initializeRegisterInfo(MF.getRegInfo(), YamlMF)) return true; const auto &F = *MF.getFunction(); DenseMap<unsigned, MachineBasicBlock *> MBBSlots; for (const auto &YamlMBB : YamlMF.BasicBlocks) { const BasicBlock *BB = nullptr; if (!YamlMBB.Name.empty()) { BB = dyn_cast_or_null<BasicBlock>( F.getValueSymbolTable().lookup(YamlMBB.Name)); if (!BB) return error(Twine("basic block '") + YamlMBB.Name + "' is not defined in the function '" + MF.getName() + "'"); } auto *MBB = MF.CreateMachineBasicBlock(BB); MF.insert(MF.end(), MBB); bool WasInserted = MBBSlots.insert(std::make_pair(YamlMBB.ID, MBB)).second; if (!WasInserted) return error(Twine("redefinition of machine basic block with id #") + Twine(YamlMBB.ID)); } // Initialize the machine basic blocks after creating them all so that the // machine instructions parser can resolve the MBB references. unsigned I = 0; for (const auto &YamlMBB : YamlMF.BasicBlocks) { if (initializeMachineBasicBlock(MF, *MF.getBlockNumbered(I++), YamlMBB, MBBSlots)) return true; } return false; }
static void analyzeFrameIndexes(MachineFunction &MF) { if (MBDisableStackAdjust) return; MachineFrameInfo *MFI = MF.getFrameInfo(); MBlazeFunctionInfo *MBlazeFI = MF.getInfo<MBlazeFunctionInfo>(); const MachineRegisterInfo &MRI = MF.getRegInfo(); MachineRegisterInfo::livein_iterator LII = MRI.livein_begin(); MachineRegisterInfo::livein_iterator LIE = MRI.livein_end(); const SmallVector<int, 16> &LiveInFI = MBlazeFI->getLiveIn(); SmallVector<MachineInstr*, 16> EraseInstr; SmallVector<std::pair<int,int64_t>, 16> FrameRelocate; MachineBasicBlock *MBB = MF.getBlockNumbered(0); MachineBasicBlock::iterator MIB = MBB->begin(); MachineBasicBlock::iterator MIE = MBB->end(); int StackAdjust = 0; int StackOffset = -28; // In this loop we are searching frame indexes that corrospond to incoming // arguments that are already in the stack. We look for instruction sequences // like the following: // // LWI REG, FI1, 0 // ... // SWI REG, FI2, 0 // // As long as there are no defs of REG in the ... part, we can eliminate // the SWI instruction because the value has already been stored to the // stack by the caller. All we need to do is locate FI at the correct // stack location according to the calling convensions. // // Additionally, if the SWI operation kills the def of REG then we don't // need the LWI operation so we can erase it as well. for (unsigned i = 0, e = LiveInFI.size(); i < e; ++i) { for (MachineBasicBlock::iterator I=MIB; I != MIE; ++I) { if (I->getOpcode() != MBlaze::LWI || I->getNumOperands() != 3 || !I->getOperand(1).isFI() || !I->getOperand(0).isReg() || I->getOperand(1).getIndex() != LiveInFI[i]) continue; unsigned FIReg = I->getOperand(0).getReg(); MachineBasicBlock::iterator SI = I; for (SI++; SI != MIE; ++SI) { if (!SI->getOperand(0).isReg() || !SI->getOperand(1).isFI() || SI->getOpcode() != MBlaze::SWI) continue; int FI = SI->getOperand(1).getIndex(); if (SI->getOperand(0).getReg() != FIReg || MFI->isFixedObjectIndex(FI) || MFI->getObjectSize(FI) != 4) continue; if (SI->getOperand(0).isDef()) break; if (SI->getOperand(0).isKill()) { DEBUG(dbgs() << "LWI for FI#" << I->getOperand(1).getIndex() << " removed\n"); EraseInstr.push_back(I); } EraseInstr.push_back(SI); DEBUG(dbgs() << "SWI for FI#" << FI << " removed\n"); FrameRelocate.push_back(std::make_pair(FI,StackOffset)); DEBUG(dbgs() << "FI#" << FI << " relocated to " << StackOffset << "\n"); StackOffset -= 4; StackAdjust += 4; break; } } } // In this loop we are searching for frame indexes that corrospond to // incoming arguments that are in registers. We look for instruction // sequences like the following: // // ... SWI REG, FI, 0 // // As long as the ... part does not define REG and if REG is an incoming // parameter register then we know that, according to ABI convensions, the // caller has allocated stack space for it already. Instead of allocating // stack space on our frame, we record the correct location in the callers // frame. for (MachineRegisterInfo::livein_iterator LI = LII; LI != LIE; ++LI) { for (MachineBasicBlock::iterator I=MIB; I != MIE; ++I) { if (I->definesRegister(LI->first)) break; if (I->getOpcode() != MBlaze::SWI || I->getNumOperands() != 3 || !I->getOperand(1).isFI() || !I->getOperand(0).isReg() || I->getOperand(1).getIndex() < 0) continue; if (I->getOperand(0).getReg() == LI->first) { int FI = I->getOperand(1).getIndex(); MBlazeFI->recordLiveIn(FI); int FILoc = 0; switch (LI->first) { default: llvm_unreachable("invalid incoming parameter!"); case MBlaze::R5: FILoc = -4; break; case MBlaze::R6: FILoc = -8; break; case MBlaze::R7: FILoc = -12; break; case MBlaze::R8: FILoc = -16; break; case MBlaze::R9: FILoc = -20; break; case MBlaze::R10: FILoc = -24; break; } StackAdjust += 4; FrameRelocate.push_back(std::make_pair(FI,FILoc)); DEBUG(dbgs() << "FI#" << FI << " relocated to " << FILoc << "\n"); break; } } } // Go ahead and erase all of the instructions that we determined were // no longer needed. for (int i = 0, e = EraseInstr.size(); i < e; ++i) MBB->erase(EraseInstr[i]); // Replace all of the frame indexes that we have relocated with new // fixed object frame indexes. replaceFrameIndexes(MF, FrameRelocate); }
bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) { auto It = Functions.find(MF.getName()); if (It == Functions.end()) return error(Twine("no machine function information for function '") + MF.getName() + "' in the MIR file"); // TODO: Recreate the machine function. const yaml::MachineFunction &YamlMF = *It->getValue(); if (YamlMF.Alignment) MF.setAlignment(YamlMF.Alignment); MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice); MF.setHasInlineAsm(YamlMF.HasInlineAsm); PerFunctionMIParsingState PFS; if (initializeRegisterInfo(MF, YamlMF, PFS)) return true; if (!YamlMF.Constants.empty()) { auto *ConstantPool = MF.getConstantPool(); assert(ConstantPool && "Constant pool must be created"); if (initializeConstantPool(*ConstantPool, YamlMF, MF, PFS.ConstantPoolSlots)) return true; } const auto &F = *MF.getFunction(); for (const auto &YamlMBB : YamlMF.BasicBlocks) { const BasicBlock *BB = nullptr; const yaml::StringValue &Name = YamlMBB.Name; const yaml::StringValue &IRBlock = YamlMBB.IRBlock; if (!Name.Value.empty()) { BB = dyn_cast_or_null<BasicBlock>( F.getValueSymbolTable().lookup(Name.Value)); if (!BB) return error(Name.SourceRange.Start, Twine("basic block '") + Name.Value + "' is not defined in the function '" + MF.getName() + "'"); } if (!IRBlock.Value.empty()) { // TODO: Report an error when both name and ir block are specified. SMDiagnostic Error; if (parseIRBlockReference(BB, SM, MF, IRBlock.Value, PFS, IRSlots, Error)) return error(Error, IRBlock.SourceRange); } auto *MBB = MF.CreateMachineBasicBlock(BB); MF.insert(MF.end(), MBB); bool WasInserted = PFS.MBBSlots.insert(std::make_pair(YamlMBB.ID, MBB)).second; if (!WasInserted) return error(Twine("redefinition of machine basic block with id #") + Twine(YamlMBB.ID)); } if (YamlMF.BasicBlocks.empty()) return error(Twine("machine function '") + Twine(MF.getName()) + "' requires at least one machine basic block in its body"); // Initialize the frame information after creating all the MBBs so that the // MBB references in the frame information can be resolved. if (initializeFrameInfo(MF, YamlMF, PFS)) return true; // Initialize the jump table after creating all the MBBs so that the MBB // references can be resolved. if (!YamlMF.JumpTableInfo.Entries.empty() && initializeJumpTableInfo(MF, YamlMF.JumpTableInfo, PFS)) return true; // Initialize the machine basic blocks after creating them all so that the // machine instructions parser can resolve the MBB references. unsigned I = 0; for (const auto &YamlMBB : YamlMF.BasicBlocks) { if (initializeMachineBasicBlock(MF, *MF.getBlockNumbered(I++), YamlMBB, PFS)) return true; } // FIXME: This is a temporary workaround until the reserved registers can be // serialized. MF.getRegInfo().freezeReservedRegs(MF); MF.verify(); return false; }