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 (YamlMF.AllVRegsAllocated) MF.getProperties().set(MachineFunctionProperties::Property::AllVRegsAllocated); 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; } SMDiagnostic Error; if (parseMachineBasicBlockDefinitions(MF, YamlMF.Body.Value.Value, PFS, IRSlots, Error)) { reportDiagnostic( diagFromBlockStringDiag(Error, YamlMF.Body.Value.SourceRange)); return true; } if (MF.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; // Parse the machine instructions after creating all of the MBBs so that the // parser can resolve the MBB references. if (parseMachineInstructions(MF, YamlMF.Body.Value.Value, PFS, IRSlots, Error)) { reportDiagnostic( diagFromBlockStringDiag(Error, YamlMF.Body.Value.SourceRange)); return true; } inferRegisterInfo(MF, YamlMF); // FIXME: This is a temporary workaround until the reserved registers can be // serialized. MF.getRegInfo().freezeReservedRegs(MF); MF.verify(); return false; }
bool ShrinkWrap::runOnMachineFunction(MachineFunction &MF) { if (skipFunction(MF.getFunction()) || MF.empty() || !isShrinkWrapEnabled(MF)) return false; LLVM_DEBUG(dbgs() << "**** Analysing " << MF.getName() << '\n'); init(MF); ReversePostOrderTraversal<MachineBasicBlock *> RPOT(&*MF.begin()); if (containsIrreducibleCFG<MachineBasicBlock *>(RPOT, *MLI)) { // If MF is irreducible, a block may be in a loop without // MachineLoopInfo reporting it. I.e., we may use the // post-dominance property in loops, which lead to incorrect // results. Moreover, we may miss that the prologue and // epilogue are not in the same loop, leading to unbalanced // construction/deconstruction of the stack frame. LLVM_DEBUG(dbgs() << "Irreducible CFGs are not supported yet\n"); return false; } const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); std::unique_ptr<RegScavenger> RS( TRI->requiresRegisterScavenging(MF) ? new RegScavenger() : nullptr); for (MachineBasicBlock &MBB : MF) { LLVM_DEBUG(dbgs() << "Look into: " << MBB.getNumber() << ' ' << MBB.getName() << '\n'); if (MBB.isEHFuncletEntry()) { LLVM_DEBUG(dbgs() << "EH Funclets are not supported yet.\n"); return false; } if (MBB.isEHPad()) { // Push the prologue and epilogue outside of // the region that may throw by making sure // that all the landing pads are at least at the // boundary of the save and restore points. // The problem with exceptions is that the throw // is not properly modeled and in particular, a // basic block can jump out from the middle. updateSaveRestorePoints(MBB, RS.get()); if (!ArePointsInteresting()) { LLVM_DEBUG(dbgs() << "EHPad prevents shrink-wrapping\n"); return false; } continue; } for (const MachineInstr &MI : MBB) { if (!useOrDefCSROrFI(MI, RS.get())) continue; // Save (resp. restore) point must dominate (resp. post dominate) // MI. Look for the proper basic block for those. updateSaveRestorePoints(MBB, RS.get()); // If we are at a point where we cannot improve the placement of // save/restore instructions, just give up. if (!ArePointsInteresting()) { LLVM_DEBUG(dbgs() << "No Shrink wrap candidate found\n"); return false; } // No need to look for other instructions, this basic block // will already be part of the handled region. break; } } if (!ArePointsInteresting()) { // If the points are not interesting at this point, then they must be null // because it means we did not encounter any frame/CSR related code. // Otherwise, we would have returned from the previous loop. assert(!Save && !Restore && "We miss a shrink-wrap opportunity?!"); LLVM_DEBUG(dbgs() << "Nothing to shrink-wrap\n"); return false; } LLVM_DEBUG(dbgs() << "\n ** Results **\nFrequency of the Entry: " << EntryFreq << '\n'); const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); do { LLVM_DEBUG(dbgs() << "Shrink wrap candidates (#, Name, Freq):\nSave: " << Save->getNumber() << ' ' << Save->getName() << ' ' << MBFI->getBlockFreq(Save).getFrequency() << "\nRestore: " << Restore->getNumber() << ' ' << Restore->getName() << ' ' << MBFI->getBlockFreq(Restore).getFrequency() << '\n'); bool IsSaveCheap, TargetCanUseSaveAsPrologue = false; if (((IsSaveCheap = EntryFreq >= MBFI->getBlockFreq(Save).getFrequency()) && EntryFreq >= MBFI->getBlockFreq(Restore).getFrequency()) && ((TargetCanUseSaveAsPrologue = TFI->canUseAsPrologue(*Save)) && TFI->canUseAsEpilogue(*Restore))) break; LLVM_DEBUG( dbgs() << "New points are too expensive or invalid for the target\n"); MachineBasicBlock *NewBB; if (!IsSaveCheap || !TargetCanUseSaveAsPrologue) { Save = FindIDom<>(*Save, Save->predecessors(), *MDT); if (!Save) break; NewBB = Save; } else { // Restore is expensive. Restore = FindIDom<>(*Restore, Restore->successors(), *MPDT); if (!Restore) break; NewBB = Restore; } updateSaveRestorePoints(*NewBB, RS.get()); } while (Save && Restore); if (!ArePointsInteresting()) { ++NumCandidatesDropped; return false; } LLVM_DEBUG(dbgs() << "Final shrink wrap candidates:\nSave: " << Save->getNumber() << ' ' << Save->getName() << "\nRestore: " << Restore->getNumber() << ' ' << Restore->getName() << '\n'); MachineFrameInfo &MFI = MF.getFrameInfo(); MFI.setSavePoint(Save); MFI.setRestorePoint(Restore); ++NumCandidates; return false; }
bool PPCBranchCoalescing::runOnMachineFunction(MachineFunction &MF) { if (skipFunction(MF.getFunction()) || MF.empty()) return false; bool didSomething = false; DEBUG(dbgs() << "******** Branch Coalescing ********\n"); initialize(MF); DEBUG(dbgs() << "Function: "; MF.dump(); dbgs() << "\n"); CoalescingCandidateInfo Cand1, Cand2; // Walk over blocks and find candidates to merge // Continue trying to merge with the first candidate found, as long as merging // is successfull. for (MachineBasicBlock &MBB : MF) { bool MergedCandidates = false; do { MergedCandidates = false; Cand1.clear(); Cand2.clear(); Cand1.BranchBlock = &MBB; // If unable to coalesce the branch, then continue to next block if (!canCoalesceBranch(Cand1)) break; Cand2.BranchBlock = Cand1.BranchTargetBlock; if (!canCoalesceBranch(Cand2)) break; // Sanity check // The branch-taken block of the second candidate should post-dominate the // first candidate assert(MPDT->dominates(Cand2.BranchTargetBlock, Cand1.BranchBlock) && "Branch-taken block should post-dominate first candidate"); if (!identicalOperands(Cand1.Cond, Cand2.Cond)) { DEBUG(dbgs() << "Blocks " << Cand1.BranchBlock->getNumber() << " and " << Cand2.BranchBlock->getNumber() << " have different branches\n"); break; } if (!canMerge(Cand2, Cand1)) { DEBUG(dbgs() << "Cannot merge blocks " << Cand1.BranchBlock->getNumber() << " and " << Cand2.BranchBlock->getNumber() << "\n"); NumBlocksNotCoalesced++; continue; } DEBUG(dbgs() << "Merging blocks " << Cand1.BranchBlock->getNumber() << " and " << Cand1.BranchTargetBlock->getNumber() << "\n"); MergedCandidates = mergeCandidates(Cand2, Cand1); if (MergedCandidates) didSomething = true; DEBUG(dbgs() << "Function after merging: "; MF.dump(); dbgs() << "\n"); } while (MergedCandidates); } #ifndef NDEBUG // Verify MF is still valid after branch coalescing if (didSomething) MF.verify(nullptr, "Error in code produced by branch coalescing"); #endif // NDEBUG DEBUG(dbgs() << "Finished Branch Coalescing\n"); return didSomething; }
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); if (YamlMF.Legalized) MF.getProperties().set(MachineFunctionProperties::Property::Legalized); if (YamlMF.RegBankSelected) MF.getProperties().set( MachineFunctionProperties::Property::RegBankSelected); if (YamlMF.Selected) MF.getProperties().set(MachineFunctionProperties::Property::Selected); PerFunctionMIParsingState PFS(MF, SM, IRSlots); if (initializeRegisterInfo(PFS, YamlMF)) return true; if (!YamlMF.Constants.empty()) { auto *ConstantPool = MF.getConstantPool(); assert(ConstantPool && "Constant pool must be created"); if (initializeConstantPool(PFS, *ConstantPool, YamlMF)) return true; } StringRef BlockStr = YamlMF.Body.Value.Value; SMDiagnostic Error; SourceMgr BlockSM; BlockSM.AddNewSourceBuffer( MemoryBuffer::getMemBuffer(BlockStr, "",/*RequiresNullTerminator=*/false), SMLoc()); PFS.SM = &BlockSM; if (parseMachineBasicBlockDefinitions(PFS, BlockStr, Error)) { reportDiagnostic( diagFromBlockStringDiag(Error, YamlMF.Body.Value.SourceRange)); return true; } PFS.SM = &SM; if (MF.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(PFS, YamlMF)) 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(PFS, YamlMF.JumpTableInfo)) return true; // Parse the machine instructions after creating all of the MBBs so that the // parser can resolve the MBB references. StringRef InsnStr = YamlMF.Body.Value.Value; SourceMgr InsnSM; InsnSM.AddNewSourceBuffer( MemoryBuffer::getMemBuffer(InsnStr, "", /*RequiresNullTerminator=*/false), SMLoc()); PFS.SM = &InsnSM; if (parseMachineInstructions(PFS, InsnStr, Error)) { reportDiagnostic( diagFromBlockStringDiag(Error, YamlMF.Body.Value.SourceRange)); return true; } PFS.SM = &SM; inferRegisterInfo(PFS, YamlMF); computeFunctionProperties(MF); // FIXME: This is a temporary workaround until the reserved registers can be // serialized. MF.getRegInfo().freezeReservedRegs(MF); MF.verify(); return false; }
bool ShadowCallStack::runOnMachineFunction(MachineFunction &Fn) { if (!Fn.getFunction().hasFnAttribute(Attribute::ShadowCallStack) || Fn.getFunction().hasFnAttribute(Attribute::Naked)) return false; if (Fn.empty() || !Fn.getRegInfo().tracksLiveness()) return false; // FIXME: Skip functions that have r10 or r11 live on entry (r10 can be live // on entry for parameters with the nest attribute.) if (Fn.front().isLiveIn(X86::R10) || Fn.front().isLiveIn(X86::R11)) return false; // FIXME: Skip functions with conditional and r10 tail calls for now. bool HasReturn = false; for (auto &MBB : Fn) { if (MBB.empty()) continue; const MachineInstr &MI = MBB.instr_back(); if (MI.isReturn()) HasReturn = true; if (MI.isReturn() && MI.isCall()) { if (MI.findRegisterUseOperand(X86::EFLAGS)) return false; // This should only be possible on Windows 64 (see GR64_TC versus // GR64_TCW64.) if (MI.findRegisterUseOperand(X86::R10) || MI.hasRegisterImplicitUseOperand(X86::R10)) return false; } } if (!HasReturn) return false; // For leaf functions: // 1. Do not instrument very short functions where it would not improve that // function's security. // 2. Detect if there is an unused caller-saved register we can reserve to // hold the return address instead of writing/reading it from the shadow // call stack. MCPhysReg LeafFuncRegister = X86::NoRegister; if (!Fn.getFrameInfo().adjustsStack()) { size_t InstructionCount = 0; std::bitset<X86::NUM_TARGET_REGS> UsedRegs; for (auto &MBB : Fn) { for (auto &LiveIn : MBB.liveins()) UsedRegs.set(LiveIn.PhysReg); for (auto &MI : MBB) { if (!MI.isDebugValue() && !MI.isCFIInstruction() && !MI.isLabel()) InstructionCount++; for (auto &Op : MI.operands()) if (Op.isReg() && Op.isDef()) UsedRegs.set(Op.getReg()); } } if (InstructionCount <= SkipLeafInstructions) return false; std::bitset<X86::NUM_TARGET_REGS> CalleeSavedRegs; const MCPhysReg *CSRegs = Fn.getRegInfo().getCalleeSavedRegs(); for (size_t i = 0; CSRegs[i]; i++) CalleeSavedRegs.set(CSRegs[i]); const TargetRegisterInfo *TRI = Fn.getSubtarget().getRegisterInfo(); for (auto &Reg : X86::GR64_NOSPRegClass.getRegisters()) { // FIXME: Optimization opportunity: spill/restore a callee-saved register // if a caller-saved register is unavailable. if (CalleeSavedRegs.test(Reg)) continue; bool Used = false; for (MCSubRegIterator SR(Reg, TRI, true); SR.isValid(); ++SR) if ((Used = UsedRegs.test(*SR))) break; if (!Used) { LeafFuncRegister = Reg; break; } } } const bool LeafFuncOptimization = LeafFuncRegister != X86::NoRegister; if (LeafFuncOptimization) // Mark the leaf function register live-in for all MBBs except the entry MBB for (auto I = ++Fn.begin(), E = Fn.end(); I != E; ++I) I->addLiveIn(LeafFuncRegister); MachineBasicBlock &MBB = Fn.front(); const MachineBasicBlock *NonEmpty = MBB.empty() ? MBB.getFallThrough() : &MBB; const DebugLoc &DL = NonEmpty->front().getDebugLoc(); const TargetInstrInfo *TII = Fn.getSubtarget().getInstrInfo(); if (LeafFuncOptimization) addPrologLeaf(Fn, TII, MBB, DL, LeafFuncRegister); else addProlog(Fn, TII, MBB, DL); MachineBasicBlock *Trap = nullptr; for (auto &MBB : Fn) { if (MBB.empty()) continue; MachineInstr &MI = MBB.instr_back(); if (MI.isReturn()) { if (!Trap) { Trap = Fn.CreateMachineBasicBlock(); BuildMI(Trap, MI.getDebugLoc(), TII->get(X86::TRAP)); Fn.push_back(Trap); } if (LeafFuncOptimization) addEpilogLeaf(TII, MBB, MI, *Trap, LeafFuncRegister); else if (MI.findRegisterUseOperand(X86::R11)) addEpilogOnlyR10(TII, MBB, MI, *Trap); else addEpilog(TII, MBB, MI, *Trap); } } return true; }
bool ShrinkWrap::runOnMachineFunction(MachineFunction &MF) { if (MF.empty()) return false; DEBUG(dbgs() << "**** Analysing " << MF.getName() << '\n'); init(MF); for (MachineBasicBlock &MBB : MF) { DEBUG(dbgs() << "Look into: " << MBB.getNumber() << ' ' << MBB.getName() << '\n'); for (const MachineInstr &MI : MBB) { if (!useOrDefCSROrFI(MI)) continue; // Save (resp. restore) point must dominate (resp. post dominate) // MI. Look for the proper basic block for those. updateSaveRestorePoints(MBB); // If we are at a point where we cannot improve the placement of // save/restore instructions, just give up. if (!ArePointsInteresting()) { DEBUG(dbgs() << "No Shrink wrap candidate found\n"); return false; } // No need to look for other instructions, this basic block // will already be part of the handled region. break; } } if (!ArePointsInteresting()) { // If the points are not interesting at this point, then they must be null // because it means we did not encounter any frame/CSR related code. // Otherwise, we would have returned from the previous loop. assert(!Save && !Restore && "We miss a shrink-wrap opportunity?!"); DEBUG(dbgs() << "Nothing to shrink-wrap\n"); return false; } DEBUG(dbgs() << "\n ** Results **\nFrequency of the Entry: " << EntryFreq << '\n'); do { DEBUG(dbgs() << "Shrink wrap candidates (#, Name, Freq):\nSave: " << Save->getNumber() << ' ' << Save->getName() << ' ' << MBFI->getBlockFreq(Save).getFrequency() << "\nRestore: " << Restore->getNumber() << ' ' << Restore->getName() << ' ' << MBFI->getBlockFreq(Restore).getFrequency() << '\n'); bool IsSaveCheap; if ((IsSaveCheap = EntryFreq >= MBFI->getBlockFreq(Save).getFrequency()) && EntryFreq >= MBFI->getBlockFreq(Restore).getFrequency()) break; DEBUG(dbgs() << "New points are too expensive\n"); MachineBasicBlock *NewBB; if (!IsSaveCheap) { Save = FindIDom<>(*Save, Save->predecessors(), *MDT); if (!Save) break; NewBB = Save; } else { // Restore is expensive. Restore = FindIDom<>(*Restore, Restore->successors(), *MPDT); if (!Restore) break; NewBB = Restore; } updateSaveRestorePoints(*NewBB); } while (Save && Restore); if (!ArePointsInteresting()) { ++NumCandidatesDropped; return false; } DEBUG(dbgs() << "Final shrink wrap candidates:\nSave: " << Save->getNumber() << ' ' << Save->getName() << "\nRestore: " << Restore->getNumber() << ' ' << Restore->getName() << '\n'); MachineFrameInfo *MFI = MF.getFrameInfo(); MFI->setSavePoint(Save); MFI->setRestorePoint(Restore); ++NumCandidates; return false; }