bool PPCCTRLoops::runOnMachineFunction(MachineFunction &MF) { DEBUG(dbgs() << "********* PPC CTR Loops *********\n"); bool Changed = false; // get the loop information MLI = &getAnalysis<MachineLoopInfo>(); // get the register information MRI = &MF.getRegInfo(); // the target specific instructio info. TII = MF.getTarget().getInstrInfo(); for (MachineLoopInfo::iterator I = MLI->begin(), E = MLI->end(); I != E; ++I) { MachineLoop *L = *I; if (!L->getParentLoop()) { Changed |= convertToCTRLoop(L); } } return Changed; }
void WebAssemblyFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { auto &MFI = MF.getFrameInfo(); uint64_t StackSize = MFI.getStackSize(); if (!needsSP(MF, MFI) || !needsSPWriteback(MF, MFI)) return; const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); auto &MRI = MF.getRegInfo(); auto InsertPt = MBB.getFirstTerminator(); DebugLoc DL; if (InsertPt != MBB.end()) DL = InsertPt->getDebugLoc(); // Restore the stack pointer. If we had fixed-size locals, add the offset // subtracted in the prolog. unsigned SPReg = 0; MachineBasicBlock::iterator InsertAddr = InsertPt; if (hasBP(MF)) { auto FI = MF.getInfo<WebAssemblyFunctionInfo>(); SPReg = FI->getBasePointerVreg(); } else if (StackSize) { const TargetRegisterClass *PtrRC = MRI.getTargetRegisterInfo()->getPointerRegClass(MF); unsigned OffsetReg = MRI.createVirtualRegister(PtrRC); InsertAddr = BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), OffsetReg) .addImm(StackSize); // In the epilog we don't need to write the result back to the SP32 physreg // because it won't be used again. We can use a stackified register instead. SPReg = MRI.createVirtualRegister(PtrRC); BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::ADD_I32), SPReg) .addReg(hasFP(MF) ? WebAssembly::FP32 : WebAssembly::SP32) .addReg(OffsetReg); } else { SPReg = hasFP(MF) ? WebAssembly::FP32 : WebAssembly::SP32; } writeSPToMemory(SPReg, MF, MBB, InsertAddr, InsertPt, DL); }
bool SIFixWWMLiveness::runOnMachineFunction(MachineFunction &MF) { bool Modified = false; // This doesn't actually need LiveIntervals, but we can preserve them. LIS = getAnalysisIfAvailable<LiveIntervals>(); const SISubtarget &ST = MF.getSubtarget<SISubtarget>(); const SIInstrInfo *TII = ST.getInstrInfo(); TRI = &TII->getRegisterInfo(); MRI = &MF.getRegInfo(); for (MachineBasicBlock &MBB : MF) { for (MachineInstr &MI : MBB) { if (MI.getOpcode() == AMDGPU::EXIT_WWM) { Modified |= runOnWWMInstruction(MI); } } } return Modified; }
bool HexagonGenPredicate::runOnMachineFunction(MachineFunction &MF) { TII = MF.getSubtarget<HexagonSubtarget>().getInstrInfo(); TRI = MF.getSubtarget<HexagonSubtarget>().getRegisterInfo(); MRI = &MF.getRegInfo(); PredGPRs.clear(); PUsers.clear(); G2P.clear(); bool Changed = false; collectPredicateGPR(MF); for (SetOfReg::iterator I = PredGPRs.begin(), E = PredGPRs.end(); I != E; ++I) processPredicateGPR(*I); bool Again; do { Again = false; VectOfInst Processed, Copy; typedef VectOfInst::iterator iterator; Copy = PUsers; for (iterator I = Copy.begin(), E = Copy.end(); I != E; ++I) { MachineInstr *MI = *I; bool Done = convertToPredForm(MI); if (Done) { Processed.insert(MI); Again = true; } } Changed |= Again; auto Done = [Processed] (MachineInstr *MI) -> bool { return Processed.count(MI); }; PUsers.remove_if(Done); } while (Again); Changed |= eliminatePredCopies(MF); return Changed; }
void MIRPrinter::print(const MachineFunction &MF) { initRegisterMaskIds(MF); yaml::MachineFunction YamlMF; YamlMF.Name = MF.getName(); YamlMF.Alignment = MF.getAlignment(); YamlMF.ExposesReturnsTwice = MF.exposesReturnsTwice(); YamlMF.Legalized = MF.getProperties().hasProperty( MachineFunctionProperties::Property::Legalized); YamlMF.RegBankSelected = MF.getProperties().hasProperty( MachineFunctionProperties::Property::RegBankSelected); YamlMF.Selected = MF.getProperties().hasProperty( MachineFunctionProperties::Property::Selected); convert(YamlMF, MF.getRegInfo(), MF.getSubtarget().getRegisterInfo()); ModuleSlotTracker MST(MF.getFunction()->getParent()); MST.incorporateFunction(*MF.getFunction()); convert(MST, YamlMF.FrameInfo, MF.getFrameInfo()); convertStackObjects(YamlMF, MF, MST); if (const auto *ConstantPool = MF.getConstantPool()) convert(YamlMF, *ConstantPool); if (const auto *JumpTableInfo = MF.getJumpTableInfo()) convert(MST, YamlMF.JumpTableInfo, *JumpTableInfo); raw_string_ostream StrOS(YamlMF.Body.Value.Value); bool IsNewlineNeeded = false; for (const auto &MBB : MF) { if (IsNewlineNeeded) StrOS << "\n"; MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping) .print(MBB); IsNewlineNeeded = true; } StrOS.flush(); yaml::Output Out(OS); if (!SimplifyMIR) Out.setWriteDefaultValues(true); Out << YamlMF; }
bool llvm::PHIElimination::runOnMachineFunction(MachineFunction &MF) { MRI = &MF.getRegInfo(); bool Changed = false; // Split critical edges to help the coalescer if (LiveVariables *LV = getAnalysisIfAvailable<LiveVariables>()) { MachineLoopInfo *MLI = getAnalysisIfAvailable<MachineLoopInfo>(); for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) Changed |= SplitPHIEdges(MF, *I, *LV, MLI); } // Populate VRegPHIUseCount analyzePHINodes(MF); // Eliminate PHI instructions by inserting copies into predecessor blocks. for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) Changed |= EliminatePHINodes(MF, *I); // Remove dead IMPLICIT_DEF instructions. for (SmallPtrSet<MachineInstr*, 4>::iterator I = ImpDefs.begin(), E = ImpDefs.end(); I != E; ++I) { MachineInstr *DefMI = *I; unsigned DefReg = DefMI->getOperand(0).getReg(); if (MRI->use_nodbg_empty(DefReg)) DefMI->eraseFromParent(); } // Clean up the lowered PHI instructions. for (LoweredPHIMap::iterator I = LoweredPHIs.begin(), E = LoweredPHIs.end(); I != E; ++I) MF.DeleteMachineInstr(I->first); LoweredPHIs.clear(); ImpDefs.clear(); VRegPHIUseCount.clear(); return Changed; }
bool IRTranslator::runOnMachineFunction(MachineFunction &MF) { const Function &F = *MF.getFunction(); if (F.empty()) return false; CLI = MF.getSubtarget().getCallLowering(); MIRBuilder.setMF(MF); MRI = &MF.getRegInfo(); // Setup the arguments. MachineBasicBlock &MBB = getOrCreateBB(F.front()); MIRBuilder.setMBB(MBB); SmallVector<unsigned, 8> VRegArgs; for (const Argument &Arg: F.args()) VRegArgs.push_back(getOrCreateVReg(Arg)); bool Succeeded = CLI->lowerFormalArguments(MIRBuilder, F.getArgumentList(), VRegArgs); if (!Succeeded) report_fatal_error("Unable to lower arguments"); for (const BasicBlock &BB: F) { MachineBasicBlock &MBB = getOrCreateBB(BB); // Set the insertion point of all the following translations to // the end of this basic block. MIRBuilder.setMBB(MBB); for (const Instruction &Inst: BB) { bool Succeeded = translate(Inst); if (!Succeeded) { DEBUG(dbgs() << "Cannot translate: " << Inst << '\n'); report_fatal_error("Unable to translate instruction"); } } } // Now that the MachineFrameInfo has been configured, no further changes to // the reserved registers are possible. MRI->freezeReservedRegs(MF); return false; }
bool X86CallFrameOptimization::runOnMachineFunction(MachineFunction &MF) { STI = &MF.getSubtarget<X86Subtarget>(); TII = STI->getInstrInfo(); TFL = STI->getFrameLowering(); MRI = &MF.getRegInfo(); const X86RegisterInfo &RegInfo = *static_cast<const X86RegisterInfo *>(STI->getRegisterInfo()); SlotSize = RegInfo.getSlotSize(); assert(isPowerOf2_32(SlotSize) && "Expect power of 2 stack slot size"); Log2SlotSize = Log2_32(SlotSize); if (!isLegal(MF)) return false; unsigned FrameSetupOpcode = TII->getCallFrameSetupOpcode(); bool Changed = false; ContextVector CallSeqVector; for (auto &MBB : MF) for (auto &MI : MBB) if (MI.getOpcode() == FrameSetupOpcode) { CallContext Context; collectCallInfo(MF, MBB, MI, Context); CallSeqVector.push_back(Context); } if (!isProfitable(MF, CallSeqVector)) return false; for (auto CC : CallSeqVector) if (CC.UsePush) Changed |= adjustCallSequence(MF, CC); return Changed; }
bool HexagonEarlyIfConversion::runOnMachineFunction(MachineFunction &MF) { if (skipFunction(*MF.getFunction())) return false; auto &ST = MF.getSubtarget<HexagonSubtarget>(); HII = ST.getInstrInfo(); TRI = ST.getRegisterInfo(); MFN = &MF; MRI = &MF.getRegInfo(); MDT = &getAnalysis<MachineDominatorTree>(); MLI = &getAnalysis<MachineLoopInfo>(); MBPI = EnableHexagonBP ? &getAnalysis<MachineBranchProbabilityInfo>() : nullptr; Deleted.clear(); bool Changed = false; for (MachineLoopInfo::iterator I = MLI->begin(), E = MLI->end(); I != E; ++I) Changed |= visitLoop(*I); Changed |= visitLoop(nullptr); return Changed; }
static void writeSPToMemory(unsigned SrcReg, MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator &InsertAddr, MachineBasicBlock::iterator &InsertStore, DebugLoc DL) { auto *SPSymbol = MF.createExternalSymbolName("__stack_pointer"); unsigned SPAddr = MF.getRegInfo().createVirtualRegister(&WebAssembly::I32RegClass); const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo(); BuildMI(MBB, InsertAddr, DL, TII->get(WebAssembly::CONST_I32), SPAddr) .addExternalSymbol(SPSymbol); auto *MMO = new MachineMemOperand(MachinePointerInfo(), MachineMemOperand::MOStore, 4, 4); BuildMI(MBB, InsertStore, DL, TII->get(WebAssembly::STORE_I32), SrcReg) .addImm(0) .addReg(SPAddr) .addImm(2) // p2align .addReg(SrcReg) .addMemOperand(MMO); MF.getInfo<WebAssemblyFunctionInfo>()->stackifyVReg(SPAddr); }
bool ARMBaseRegisterInfo::canRealignStack(const MachineFunction &MF) const { const MachineRegisterInfo *MRI = &MF.getRegInfo(); const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); // We can't realign the stack if: // 1. Dynamic stack realignment is explicitly disabled, // 2. This is a Thumb1 function (it's not useful, so we don't bother), or // 3. There are VLAs in the function and the base pointer is disabled. if (!MF.getTarget().Options.RealignStack) return false; if (AFI->isThumb1OnlyFunction()) return false; // Stack realignment requires a frame pointer. If we already started // register allocation with frame pointer elimination, it is too late now. if (!MRI->canReserveReg(FramePtr)) return false; // We may also need a base pointer if there are dynamic allocas or stack // pointer adjustments around calls. if (MF.getTarget().getFrameLowering()->hasReservedCallFrame(MF)) return true; // A base pointer is required and allowed. Check that it isn't too late to // reserve it. return MRI->canReserveReg(BasePtr); }
bool SILoadStoreOptimizer::runOnMachineFunction(MachineFunction &MF) { if (skipFunction(*MF.getFunction())) return false; const SISubtarget &STM = MF.getSubtarget<SISubtarget>(); if (!STM.loadStoreOptEnabled()) return false; TII = STM.getInstrInfo(); TRI = &TII->getRegisterInfo(); MRI = &MF.getRegInfo(); AA = &getAnalysis<AAResultsWrapperPass>().getAAResults(); DEBUG(dbgs() << "Running SILoadStoreOptimizer\n"); bool Modified = false; for (MachineBasicBlock &MBB : MF) Modified |= optimizeBlock(MBB); return Modified; }
bool SIFixSGPRLiveRanges::runOnMachineFunction(MachineFunction &MF) { MachineRegisterInfo &MRI = MF.getRegInfo(); const SIRegisterInfo *TRI = static_cast<const SIRegisterInfo *>( MF.getTarget().getRegisterInfo()); LiveIntervals *LIS = &getAnalysis<LiveIntervals>(); for (MachineFunction::iterator BI = MF.begin(), BE = MF.end(); BI != BE; ++BI) { MachineBasicBlock &MBB = *BI; for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I) { MachineInstr &MI = *I; MachineOperand *ExecUse = MI.findRegisterUseOperand(AMDGPU::EXEC); if (ExecUse) continue; for (const MachineOperand &Def : MI.operands()) { if (!Def.isReg() || !Def.isDef() ||!TargetRegisterInfo::isVirtualRegister(Def.getReg())) continue; const TargetRegisterClass *RC = MRI.getRegClass(Def.getReg()); if (!TRI->isSGPRClass(RC)) continue; LiveInterval &LI = LIS->getInterval(Def.getReg()); for (unsigned i = 0, e = LI.size() - 1; i != e; ++i) { LiveRange::Segment &Seg = LI.segments[i]; LiveRange::Segment &Next = LI.segments[i + 1]; Seg.end = Next.start; } } } } return false; }
bool A15SDOptimizer::runOnMachineFunction(MachineFunction &Fn) { if (skipFunction(*Fn.getFunction())) return false; const ARMSubtarget &STI = Fn.getSubtarget<ARMSubtarget>(); // Since the A15SDOptimizer pass can insert VDUP instructions, it can only be // enabled when NEON is available. if (!(STI.isCortexA15() && STI.hasNEON())) return false; TII = STI.getInstrInfo(); TRI = STI.getRegisterInfo(); MRI = &Fn.getRegInfo(); bool Modified = false; DEBUG(dbgs() << "Running on function " << Fn.getName()<< "\n"); DeadInstr.clear(); Replacements.clear(); for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; ++MFI) { for (MachineBasicBlock::iterator MI = MFI->begin(), ME = MFI->end(); MI != ME;) { Modified |= runOnInstruction(MI++); } } for (std::set<MachineInstr *>::iterator I = DeadInstr.begin(), E = DeadInstr.end(); I != E; ++I) { (*I)->eraseFromParent(); } return Modified; }
// FIXME: Insert waits listed in Table 4.2 "Required User-Inserted Wait States" // around other non-memory instructions. bool SIInsertWaits::runOnMachineFunction(MachineFunction &MF) { bool Changes = false; TII = static_cast<const SIInstrInfo *>(MF.getSubtarget().getInstrInfo()); TRI = static_cast<const SIRegisterInfo *>(MF.getSubtarget().getRegisterInfo()); MRI = &MF.getRegInfo(); WaitedOn = ZeroCounts; LastIssued = ZeroCounts; LastOpcodeType = OTHER; memset(&UsedRegs, 0, sizeof(UsedRegs)); memset(&DefinedRegs, 0, sizeof(DefinedRegs)); for (MachineFunction::iterator BI = MF.begin(), BE = MF.end(); BI != BE; ++BI) { MachineBasicBlock &MBB = *BI; for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I) { // Wait for everything before a barrier. if (I->getOpcode() == AMDGPU::S_BARRIER) Changes |= insertWait(MBB, I, LastIssued); else Changes |= insertWait(MBB, I, handleOperands(*I)); pushInstruction(MBB, I); } // Wait for everything at the end of the MBB Changes |= insertWait(MBB, MBB.getFirstTerminator(), LastIssued); } return Changes; }
bool WebAssemblyPeephole::runOnMachineFunction(MachineFunction &MF) { bool Changed = false; MachineRegisterInfo &MRI = MF.getRegInfo(); WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>(); for (auto &MBB : MF) for (auto &MI : MBB) switch (MI.getOpcode()) { default: break; case WebAssembly::STORE8_I32: case WebAssembly::STORE16_I32: case WebAssembly::STORE8_I64: case WebAssembly::STORE16_I64: case WebAssembly::STORE32_I64: case WebAssembly::STORE_F32: case WebAssembly::STORE_F64: case WebAssembly::STORE_I32: case WebAssembly::STORE_I64: { // Store instructions return their value operand. If we ended up using // the same register for both, replace it with a dead def so that it // can use $discard instead. MachineOperand &MO = MI.getOperand(0); unsigned OldReg = MO.getReg(); if (OldReg == MI.getOperand(2).getReg()) { unsigned NewReg = MRI.createVirtualRegister(MRI.getRegClass(OldReg)); MO.setReg(NewReg); MO.setIsDead(); MFI.stackifyVReg(NewReg); MFI.addWAReg(NewReg, WebAssemblyFunctionInfo::UnusedReg); } } } return Changed; }
void ARMBaseRegisterInfo::updateRegAllocHint(unsigned Reg, unsigned NewReg, MachineFunction &MF) const { MachineRegisterInfo *MRI = &MF.getRegInfo(); std::pair<unsigned, unsigned> Hint = MRI->getRegAllocationHint(Reg); if ((Hint.first == (unsigned)ARMRI::RegPairOdd || Hint.first == (unsigned)ARMRI::RegPairEven) && TargetRegisterInfo::isVirtualRegister(Hint.second)) { // If 'Reg' is one of the even / odd register pair and it's now changed // (e.g. coalesced) into a different register. The other register of the // pair allocation hint must be updated to reflect the relationship // change. unsigned OtherReg = Hint.second; Hint = MRI->getRegAllocationHint(OtherReg); // Make sure the pair has not already divorced. if (Hint.second == Reg) { MRI->setRegAllocationHint(OtherReg, Hint.first, NewReg); if (TargetRegisterInfo::isVirtualRegister(NewReg)) MRI->setRegAllocationHint(NewReg, Hint.first == (unsigned)ARMRI::RegPairOdd ? ARMRI::RegPairEven : ARMRI::RegPairOdd, OtherReg); } } }
void MipsFrameLowering:: processFunctionBeforeCalleeSavedScan(MachineFunction &MF, RegScavenger *RS) const { MachineRegisterInfo& MRI = MF.getRegInfo(); unsigned RA = STI.isABI_N64() ? Mips::RA_64 : Mips::RA; unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP; // FIXME: remove this code if register allocator can correctly mark // $fp and $ra used or unused. // Mark $fp and $ra as used or unused. if (hasFP(MF)) MRI.setPhysRegUsed(FP); // The register allocator might determine $ra is used after seeing // instruction "jr $ra", but we do not want PrologEpilogInserter to insert // instructions to save/restore $ra unless there is a function call. // To correct this, $ra is explicitly marked unused if there is no // function call. if (MF.getFrameInfo()->hasCalls()) MRI.setPhysRegUsed(RA); else MRI.setPhysRegUnused(RA); }
void SIRegisterInfo::materializeFrameBaseRegister(MachineBasicBlock *MBB, unsigned BaseReg, int FrameIdx, int64_t Offset) const { MachineBasicBlock::iterator Ins = MBB->begin(); DebugLoc DL; // Defaults to "unknown" if (Ins != MBB->end()) DL = Ins->getDebugLoc(); MachineFunction *MF = MBB->getParent(); const SISubtarget &Subtarget = MF->getSubtarget<SISubtarget>(); const SIInstrInfo *TII = Subtarget.getInstrInfo(); if (Offset == 0) { BuildMI(*MBB, Ins, DL, TII->get(AMDGPU::V_MOV_B32_e32), BaseReg) .addFrameIndex(FrameIdx); return; } MachineRegisterInfo &MRI = MF->getRegInfo(); unsigned UnusedCarry = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass); unsigned OffsetReg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass); unsigned FIReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass); BuildMI(*MBB, Ins, DL, TII->get(AMDGPU::S_MOV_B32), OffsetReg) .addImm(Offset); BuildMI(*MBB, Ins, DL, TII->get(AMDGPU::V_MOV_B32_e32), FIReg) .addFrameIndex(FrameIdx); BuildMI(*MBB, Ins, DL, TII->get(AMDGPU::V_ADD_I32_e64), BaseReg) .addReg(UnusedCarry, RegState::Define | RegState::Dead) .addReg(OffsetReg, RegState::Kill) .addReg(FIReg); }
bool VirtRegMap::runOnMachineFunction(MachineFunction &mf) { MRI = &mf.getRegInfo(); TII = mf.getTarget().getInstrInfo(); TRI = mf.getTarget().getRegisterInfo(); MF = &mf; ReMatId = MAX_STACK_SLOT+1; LowSpillSlot = HighSpillSlot = NO_STACK_SLOT; Virt2PhysMap.clear(); Virt2StackSlotMap.clear(); Virt2ReMatIdMap.clear(); Virt2SplitMap.clear(); Virt2SplitKillMap.clear(); ReMatMap.clear(); ImplicitDefed.clear(); SpillSlotToUsesMap.clear(); MI2VirtMap.clear(); SpillPt2VirtMap.clear(); RestorePt2VirtMap.clear(); EmergencySpillMap.clear(); EmergencySpillSlots.clear(); SpillSlotToUsesMap.resize(8); ImplicitDefed.resize(MF->getRegInfo().getNumVirtRegs()); allocatableRCRegs.clear(); for (TargetRegisterInfo::regclass_iterator I = TRI->regclass_begin(), E = TRI->regclass_end(); I != E; ++I) allocatableRCRegs.insert(std::make_pair(*I, TRI->getAllocatableSet(mf, *I))); grow(); return false; }
bool AArch64ConditionOptimizer::runOnMachineFunction(MachineFunction &MF) { DEBUG(dbgs() << "********** AArch64 Conditional Compares **********\n" << "********** Function: " << MF.getName() << '\n'); TII = MF.getSubtarget().getInstrInfo(); DomTree = &getAnalysis<MachineDominatorTree>(); MRI = &MF.getRegInfo(); bool Changed = false; // Visit blocks in dominator tree pre-order. The pre-order enables multiple // cmp-conversions from the same head block. // Note that updateDomTree() modifies the children of the DomTree node // currently being visited. The df_iterator supports that; it doesn't look at // child_begin() / child_end() until after a node has been visited. for (MachineDomTreeNode *I : depth_first(DomTree)) { MachineBasicBlock *HBB = I->getBlock(); SmallVector<MachineOperand, 4> HeadCond; MachineBasicBlock *TBB = nullptr, *FBB = nullptr; if (TII->AnalyzeBranch(*HBB, TBB, FBB, HeadCond)) { continue; } // Equivalence check is to skip loops. if (!TBB || TBB == HBB) { continue; } SmallVector<MachineOperand, 4> TrueCond; MachineBasicBlock *TBB_TBB = nullptr, *TBB_FBB = nullptr; if (TII->AnalyzeBranch(*TBB, TBB_TBB, TBB_FBB, TrueCond)) { continue; } MachineInstr *HeadCmpMI = findSuitableCompare(HBB); if (!HeadCmpMI) { continue; } MachineInstr *TrueCmpMI = findSuitableCompare(TBB); if (!TrueCmpMI) { continue; } AArch64CC::CondCode HeadCmp; if (HeadCond.empty() || !parseCond(HeadCond, HeadCmp)) { continue; } AArch64CC::CondCode TrueCmp; if (TrueCond.empty() || !parseCond(TrueCond, TrueCmp)) { continue; } const int HeadImm = (int)HeadCmpMI->getOperand(2).getImm(); const int TrueImm = (int)TrueCmpMI->getOperand(2).getImm(); DEBUG(dbgs() << "Head branch:\n"); DEBUG(dbgs() << "\tcondition: " << AArch64CC::getCondCodeName(HeadCmp) << '\n'); DEBUG(dbgs() << "\timmediate: " << HeadImm << '\n'); DEBUG(dbgs() << "True branch:\n"); DEBUG(dbgs() << "\tcondition: " << AArch64CC::getCondCodeName(TrueCmp) << '\n'); DEBUG(dbgs() << "\timmediate: " << TrueImm << '\n'); if (((HeadCmp == AArch64CC::GT && TrueCmp == AArch64CC::LT) || (HeadCmp == AArch64CC::LT && TrueCmp == AArch64CC::GT)) && std::abs(TrueImm - HeadImm) == 2) { // This branch transforms machine instructions that correspond to // // 1) (a > {TrueImm} && ...) || (a < {HeadImm} && ...) // 2) (a < {TrueImm} && ...) || (a > {HeadImm} && ...) // // into // // 1) (a >= {NewImm} && ...) || (a <= {NewImm} && ...) // 2) (a <= {NewImm} && ...) || (a >= {NewImm} && ...) CmpInfo HeadCmpInfo = adjustCmp(HeadCmpMI, HeadCmp); CmpInfo TrueCmpInfo = adjustCmp(TrueCmpMI, TrueCmp); if (std::get<0>(HeadCmpInfo) == std::get<0>(TrueCmpInfo) && std::get<1>(HeadCmpInfo) == std::get<1>(TrueCmpInfo)) { modifyCmp(HeadCmpMI, HeadCmpInfo); modifyCmp(TrueCmpMI, TrueCmpInfo); Changed = true; } } else if (((HeadCmp == AArch64CC::GT && TrueCmp == AArch64CC::GT) || (HeadCmp == AArch64CC::LT && TrueCmp == AArch64CC::LT)) && std::abs(TrueImm - HeadImm) == 1) { // This branch transforms machine instructions that correspond to // // 1) (a > {TrueImm} && ...) || (a > {HeadImm} && ...) // 2) (a < {TrueImm} && ...) || (a < {HeadImm} && ...) // // into // // 1) (a <= {NewImm} && ...) || (a > {NewImm} && ...) // 2) (a < {NewImm} && ...) || (a >= {NewImm} && ...) // GT -> GE transformation increases immediate value, so picking the // smaller one; LT -> LE decreases immediate value so invert the choice. bool adjustHeadCond = (HeadImm < TrueImm); if (HeadCmp == AArch64CC::LT) { adjustHeadCond = !adjustHeadCond; } if (adjustHeadCond) { Changed |= adjustTo(HeadCmpMI, HeadCmp, TrueCmpMI, TrueImm); } else { Changed |= adjustTo(TrueCmpMI, TrueCmp, HeadCmpMI, HeadImm); } } // Other transformation cases almost never occur due to generation of < or > // comparisons instead of <= and >=. } return Changed; }
MachineBasicBlock* MSP430TargetLowering::EmitShiftInstr(MachineInstr *MI, MachineBasicBlock *BB) const { MachineFunction *F = BB->getParent(); MachineRegisterInfo &RI = F->getRegInfo(); DebugLoc dl = MI->getDebugLoc(); const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo(); unsigned Opc; const TargetRegisterClass * RC; switch (MI->getOpcode()) { default: assert(0 && "Invalid shift opcode!"); case MSP430::Shl8: Opc = MSP430::SHL8r1; RC = MSP430::GR8RegisterClass; break; case MSP430::Shl16: Opc = MSP430::SHL16r1; RC = MSP430::GR16RegisterClass; break; case MSP430::Sra8: Opc = MSP430::SAR8r1; RC = MSP430::GR8RegisterClass; break; case MSP430::Sra16: Opc = MSP430::SAR16r1; RC = MSP430::GR16RegisterClass; break; case MSP430::Srl8: Opc = MSP430::SAR8r1c; RC = MSP430::GR8RegisterClass; break; case MSP430::Srl16: Opc = MSP430::SAR16r1c; RC = MSP430::GR16RegisterClass; break; } const BasicBlock *LLVM_BB = BB->getBasicBlock(); MachineFunction::iterator I = BB; ++I; // Create loop block MachineBasicBlock *LoopBB = F->CreateMachineBasicBlock(LLVM_BB); MachineBasicBlock *RemBB = F->CreateMachineBasicBlock(LLVM_BB); F->insert(I, LoopBB); F->insert(I, RemBB); // Update machine-CFG edges by transferring all successors of the current // block to the block containing instructions after shift. RemBB->splice(RemBB->begin(), BB, llvm::next(MachineBasicBlock::iterator(MI)), BB->end()); RemBB->transferSuccessorsAndUpdatePHIs(BB); // Add adges BB => LoopBB => RemBB, BB => RemBB, LoopBB => LoopBB BB->addSuccessor(LoopBB); BB->addSuccessor(RemBB); LoopBB->addSuccessor(RemBB); LoopBB->addSuccessor(LoopBB); unsigned ShiftAmtReg = RI.createVirtualRegister(MSP430::GR8RegisterClass); unsigned ShiftAmtReg2 = RI.createVirtualRegister(MSP430::GR8RegisterClass); unsigned ShiftReg = RI.createVirtualRegister(RC); unsigned ShiftReg2 = RI.createVirtualRegister(RC); unsigned ShiftAmtSrcReg = MI->getOperand(2).getReg(); unsigned SrcReg = MI->getOperand(1).getReg(); unsigned DstReg = MI->getOperand(0).getReg(); // BB: // cmp 0, N // je RemBB BuildMI(BB, dl, TII.get(MSP430::CMP8ri)) .addReg(ShiftAmtSrcReg).addImm(0); BuildMI(BB, dl, TII.get(MSP430::JCC)) .addMBB(RemBB) .addImm(MSP430CC::COND_E); // LoopBB: // ShiftReg = phi [%SrcReg, BB], [%ShiftReg2, LoopBB] // ShiftAmt = phi [%N, BB], [%ShiftAmt2, LoopBB] // ShiftReg2 = shift ShiftReg // ShiftAmt2 = ShiftAmt - 1; BuildMI(LoopBB, dl, TII.get(MSP430::PHI), ShiftReg) .addReg(SrcReg).addMBB(BB) .addReg(ShiftReg2).addMBB(LoopBB); BuildMI(LoopBB, dl, TII.get(MSP430::PHI), ShiftAmtReg) .addReg(ShiftAmtSrcReg).addMBB(BB) .addReg(ShiftAmtReg2).addMBB(LoopBB); BuildMI(LoopBB, dl, TII.get(Opc), ShiftReg2) .addReg(ShiftReg); BuildMI(LoopBB, dl, TII.get(MSP430::SUB8ri), ShiftAmtReg2) .addReg(ShiftAmtReg).addImm(1); BuildMI(LoopBB, dl, TII.get(MSP430::JCC)) .addMBB(LoopBB) .addImm(MSP430CC::COND_NE); // RemBB: // DestReg = phi [%SrcReg, BB], [%ShiftReg, LoopBB] BuildMI(*RemBB, RemBB->begin(), dl, TII.get(MSP430::PHI), DstReg) .addReg(SrcReg).addMBB(BB) .addReg(ShiftReg2).addMBB(LoopBB); MI->eraseFromParent(); // The pseudo instruction is gone now. return RemBB; }
static void assignCalleeSavedSpillSlots(MachineFunction &F, const BitVector &SavedRegs, unsigned &MinCSFrameIndex, unsigned &MaxCSFrameIndex) { if (SavedRegs.empty()) return; const TargetRegisterInfo *RegInfo = F.getSubtarget().getRegisterInfo(); const MCPhysReg *CSRegs = F.getRegInfo().getCalleeSavedRegs(); std::vector<CalleeSavedInfo> CSI; for (unsigned i = 0; CSRegs[i]; ++i) { unsigned Reg = CSRegs[i]; if (SavedRegs.test(Reg)) CSI.push_back(CalleeSavedInfo(Reg)); } const TargetFrameLowering *TFI = F.getSubtarget().getFrameLowering(); MachineFrameInfo &MFI = F.getFrameInfo(); if (!TFI->assignCalleeSavedSpillSlots(F, RegInfo, CSI)) { // If target doesn't implement this, use generic code. if (CSI.empty()) return; // Early exit if no callee saved registers are modified! unsigned NumFixedSpillSlots; const TargetFrameLowering::SpillSlot *FixedSpillSlots = TFI->getCalleeSavedSpillSlots(NumFixedSpillSlots); // Now that we know which registers need to be saved and restored, allocate // stack slots for them. for (auto &CS : CSI) { unsigned Reg = CS.getReg(); const TargetRegisterClass *RC = RegInfo->getMinimalPhysRegClass(Reg); int FrameIdx; if (RegInfo->hasReservedSpillSlot(F, Reg, FrameIdx)) { CS.setFrameIdx(FrameIdx); continue; } // Check to see if this physreg must be spilled to a particular stack slot // on this target. const TargetFrameLowering::SpillSlot *FixedSlot = FixedSpillSlots; while (FixedSlot != FixedSpillSlots + NumFixedSpillSlots && FixedSlot->Reg != Reg) ++FixedSlot; unsigned Size = RegInfo->getSpillSize(*RC); if (FixedSlot == FixedSpillSlots + NumFixedSpillSlots) { // Nope, just spill it anywhere convenient. unsigned Align = RegInfo->getSpillAlignment(*RC); unsigned StackAlign = TFI->getStackAlignment(); // We may not be able to satisfy the desired alignment specification of // the TargetRegisterClass if the stack alignment is smaller. Use the // min. Align = std::min(Align, StackAlign); FrameIdx = MFI.CreateStackObject(Size, Align, true); if ((unsigned)FrameIdx < MinCSFrameIndex) MinCSFrameIndex = FrameIdx; if ((unsigned)FrameIdx > MaxCSFrameIndex) MaxCSFrameIndex = FrameIdx; } else { // Spill it to the stack where we must. FrameIdx = MFI.CreateFixedSpillStackObject(Size, FixedSlot->Offset); } CS.setFrameIdx(FrameIdx); } } MFI.setCalleeSavedInfo(CSI); }
/// runOnMachineFunction - Insert prolog/epilog code and replace abstract /// frame indexes with appropriate references. /// bool PEI::runOnMachineFunction(MachineFunction &Fn) { if (!SpillCalleeSavedRegisters) { const TargetMachine &TM = Fn.getTarget(); if (!TM.usesPhysRegsForPEI()) { SpillCalleeSavedRegisters = [](MachineFunction &, RegScavenger *, unsigned &, unsigned &, const MBBVector &, const MBBVector &) {}; ScavengeFrameVirtualRegs = [](MachineFunction &, RegScavenger &) {}; } else { SpillCalleeSavedRegisters = doSpillCalleeSavedRegs; ScavengeFrameVirtualRegs = scavengeFrameVirtualRegs; UsesCalleeSaves = true; } } const Function* F = Fn.getFunction(); const TargetRegisterInfo *TRI = Fn.getSubtarget().getRegisterInfo(); const TargetFrameLowering *TFI = Fn.getSubtarget().getFrameLowering(); RS = TRI->requiresRegisterScavenging(Fn) ? new RegScavenger() : nullptr; FrameIndexVirtualScavenging = TRI->requiresFrameIndexScavenging(Fn); FrameIndexEliminationScavenging = (RS && !FrameIndexVirtualScavenging) || TRI->requiresFrameIndexReplacementScavenging(Fn); ORE = &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE(); // Calculate the MaxCallFrameSize and AdjustsStack variables for the // function's frame information. Also eliminates call frame pseudo // instructions. calculateCallFrameInfo(Fn); // Determine placement of CSR spill/restore code and prolog/epilog code: // place all spills in the entry block, all restores in return blocks. calculateSaveRestoreBlocks(Fn); // Handle CSR spilling and restoring, for targets that need it. SpillCalleeSavedRegisters(Fn, RS, MinCSFrameIndex, MaxCSFrameIndex, SaveBlocks, RestoreBlocks); // Allow the target machine to make final modifications to the function // before the frame layout is finalized. TFI->processFunctionBeforeFrameFinalized(Fn, RS); // Calculate actual frame offsets for all abstract stack objects... calculateFrameObjectOffsets(Fn); // Add prolog and epilog code to the function. This function is required // to align the stack frame as necessary for any stack variables or // called functions. Because of this, calculateCalleeSavedRegisters() // must be called before this function in order to set the AdjustsStack // and MaxCallFrameSize variables. if (!F->hasFnAttribute(Attribute::Naked)) insertPrologEpilogCode(Fn); // Replace all MO_FrameIndex operands with physical register references // and actual offsets. // replaceFrameIndices(Fn); // If register scavenging is needed, as we've enabled doing it as a // post-pass, scavenge the virtual registers that frame index elimination // inserted. if (TRI->requiresRegisterScavenging(Fn) && FrameIndexVirtualScavenging) { ScavengeFrameVirtualRegs(Fn, *RS); // Clear any vregs created by virtual scavenging. Fn.getRegInfo().clearVirtRegs(); } // Warn on stack size when we exceeds the given limit. MachineFrameInfo &MFI = Fn.getFrameInfo(); uint64_t StackSize = MFI.getStackSize(); if (WarnStackSize.getNumOccurrences() > 0 && WarnStackSize < StackSize) { DiagnosticInfoStackSize DiagStackSize(*F, StackSize); F->getContext().diagnose(DiagStackSize); } delete RS; SaveBlocks.clear(); RestoreBlocks.clear(); MFI.setSavePoint(nullptr); MFI.setRestorePoint(nullptr); return true; }
void MipsSEDAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) { MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); if (!MipsFI->globalBaseRegSet()) return; MachineBasicBlock &MBB = MF.front(); MachineBasicBlock::iterator I = MBB.begin(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); unsigned V0, V1, GlobalBaseReg = MipsFI->getGlobalBaseReg(); const TargetRegisterClass *RC; if (Subtarget.isABI_N64()) RC = (const TargetRegisterClass*)&Mips::GPR64RegClass; else RC = (const TargetRegisterClass*)&Mips::GPR32RegClass; V0 = RegInfo.createVirtualRegister(RC); V1 = RegInfo.createVirtualRegister(RC); if (Subtarget.isABI_N64()) { MF.getRegInfo().addLiveIn(Mips::T9_64); MBB.addLiveIn(Mips::T9_64); // lui $v0, %hi(%neg(%gp_rel(fname))) // daddu $v1, $v0, $t9 // daddiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname))) const GlobalValue *FName = MF.getFunction(); BuildMI(MBB, I, DL, TII.get(Mips::LUi64), V0) .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI); BuildMI(MBB, I, DL, TII.get(Mips::DADDu), V1).addReg(V0) .addReg(Mips::T9_64); BuildMI(MBB, I, DL, TII.get(Mips::DADDiu), GlobalBaseReg).addReg(V1) .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO); return; } if (MF.getTarget().getRelocationModel() == Reloc::Static) { // Set global register to __gnu_local_gp. // // lui $v0, %hi(__gnu_local_gp) // addiu $globalbasereg, $v0, %lo(__gnu_local_gp) BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0) .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_HI); BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V0) .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_LO); return; } MF.getRegInfo().addLiveIn(Mips::T9); MBB.addLiveIn(Mips::T9); if (Subtarget.isABI_N32()) { // lui $v0, %hi(%neg(%gp_rel(fname))) // addu $v1, $v0, $t9 // addiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname))) const GlobalValue *FName = MF.getFunction(); BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0) .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI); BuildMI(MBB, I, DL, TII.get(Mips::ADDu), V1).addReg(V0).addReg(Mips::T9); BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V1) .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO); return; } assert(Subtarget.isABI_O32()); // For O32 ABI, the following instruction sequence is emitted to initialize // the global base register: // // 0. lui $2, %hi(_gp_disp) // 1. addiu $2, $2, %lo(_gp_disp) // 2. addu $globalbasereg, $2, $t9 // // We emit only the last instruction here. // // GNU linker requires that the first two instructions appear at the beginning // of a function and no instructions be inserted before or between them. // The two instructions are emitted during lowering to MC layer in order to // avoid any reordering. // // Register $2 (Mips::V0) is added to the list of live-in registers to ensure // the value instruction 1 (addiu) defines is valid when instruction 2 (addu) // reads it. MF.getRegInfo().addLiveIn(Mips::V0); MBB.addLiveIn(Mips::V0); BuildMI(MBB, I, DL, TII.get(Mips::ADDu), GlobalBaseReg) .addReg(Mips::V0).addReg(Mips::T9); }
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(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); // FIXME: This is a temporary workaround until the reserved registers can be // serialized. MF.getRegInfo().freezeReservedRegs(MF); MF.verify(); return false; }
bool AMDGPUInstructionSelector::selectSMRD(MachineInstr &I, ArrayRef<GEPInfo> AddrInfo) const { if (!I.hasOneMemOperand()) return false; if ((*I.memoperands_begin())->getAddrSpace() != AMDGPUAS::CONSTANT_ADDRESS && (*I.memoperands_begin())->getAddrSpace() != AMDGPUAS::CONSTANT_ADDRESS_32BIT) return false; if (!isInstrUniform(I)) return false; if (hasVgprParts(AddrInfo)) return false; MachineBasicBlock *BB = I.getParent(); MachineFunction *MF = BB->getParent(); const GCNSubtarget &Subtarget = MF->getSubtarget<GCNSubtarget>(); MachineRegisterInfo &MRI = MF->getRegInfo(); unsigned DstReg = I.getOperand(0).getReg(); const DebugLoc &DL = I.getDebugLoc(); unsigned Opcode; unsigned LoadSize = RBI.getSizeInBits(DstReg, MRI, TRI); if (!AddrInfo.empty() && AddrInfo[0].SgprParts.size() == 1) { const GEPInfo &GEPInfo = AddrInfo[0]; unsigned PtrReg = GEPInfo.SgprParts[0]; int64_t EncodedImm = AMDGPU::getSMRDEncodedOffset(Subtarget, GEPInfo.Imm); if (AMDGPU::isLegalSMRDImmOffset(Subtarget, GEPInfo.Imm)) { Opcode = getSmrdOpcode(AMDGPU::S_LOAD_DWORD_IMM, LoadSize); MachineInstr *SMRD = BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg) .addReg(PtrReg) .addImm(EncodedImm) .addImm(0); // glc return constrainSelectedInstRegOperands(*SMRD, TII, TRI, RBI); } if (Subtarget.getGeneration() == AMDGPUSubtarget::SEA_ISLANDS && isUInt<32>(EncodedImm)) { Opcode = getSmrdOpcode(AMDGPU::S_LOAD_DWORD_IMM_ci, LoadSize); MachineInstr *SMRD = BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg) .addReg(PtrReg) .addImm(EncodedImm) .addImm(0); // glc return constrainSelectedInstRegOperands(*SMRD, TII, TRI, RBI); } if (isUInt<32>(GEPInfo.Imm)) { Opcode = getSmrdOpcode(AMDGPU::S_LOAD_DWORD_SGPR, LoadSize); unsigned OffsetReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass); BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_MOV_B32), OffsetReg) .addImm(GEPInfo.Imm); MachineInstr *SMRD = BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg) .addReg(PtrReg) .addReg(OffsetReg) .addImm(0); // glc return constrainSelectedInstRegOperands(*SMRD, TII, TRI, RBI); } } unsigned PtrReg = I.getOperand(1).getReg(); Opcode = getSmrdOpcode(AMDGPU::S_LOAD_DWORD_IMM, LoadSize); MachineInstr *SMRD = BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg) .addReg(PtrReg) .addImm(0) .addImm(0); // glc return constrainSelectedInstRegOperands(*SMRD, TII, TRI, RBI); }
bool AMDGPUInstructionSelector::selectG_CONSTANT(MachineInstr &I) const { MachineBasicBlock *BB = I.getParent(); MachineFunction *MF = BB->getParent(); MachineRegisterInfo &MRI = MF->getRegInfo(); MachineOperand &ImmOp = I.getOperand(1); // The AMDGPU backend only supports Imm operands and not CImm or FPImm. if (ImmOp.isFPImm()) { const APInt &Imm = ImmOp.getFPImm()->getValueAPF().bitcastToAPInt(); ImmOp.ChangeToImmediate(Imm.getZExtValue()); } else if (ImmOp.isCImm()) { ImmOp.ChangeToImmediate(ImmOp.getCImm()->getZExtValue()); } unsigned DstReg = I.getOperand(0).getReg(); unsigned Size; bool IsSgpr; const RegisterBank *RB = MRI.getRegBankOrNull(I.getOperand(0).getReg()); if (RB) { IsSgpr = RB->getID() == AMDGPU::SGPRRegBankID; Size = MRI.getType(DstReg).getSizeInBits(); } else { const TargetRegisterClass *RC = TRI.getRegClassForReg(MRI, DstReg); IsSgpr = TRI.isSGPRClass(RC); Size = TRI.getRegSizeInBits(*RC); } if (Size != 32 && Size != 64) return false; unsigned Opcode = IsSgpr ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32; if (Size == 32) { I.setDesc(TII.get(Opcode)); I.addImplicitDefUseOperands(*MF); return constrainSelectedInstRegOperands(I, TII, TRI, RBI); } DebugLoc DL = I.getDebugLoc(); const TargetRegisterClass *RC = IsSgpr ? &AMDGPU::SReg_32_XM0RegClass : &AMDGPU::VGPR_32RegClass; unsigned LoReg = MRI.createVirtualRegister(RC); unsigned HiReg = MRI.createVirtualRegister(RC); const APInt &Imm = APInt(Size, I.getOperand(1).getImm()); BuildMI(*BB, &I, DL, TII.get(Opcode), LoReg) .addImm(Imm.trunc(32).getZExtValue()); BuildMI(*BB, &I, DL, TII.get(Opcode), HiReg) .addImm(Imm.ashr(32).getZExtValue()); const MachineInstr *RS = BuildMI(*BB, &I, DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg) .addReg(LoReg) .addImm(AMDGPU::sub0) .addReg(HiReg) .addImm(AMDGPU::sub1); // We can't call constrainSelectedInstRegOperands here, because it doesn't // work for target independent opcodes I.eraseFromParent(); const TargetRegisterClass *DstRC = TRI.getConstrainedRegClassForOperand(RS->getOperand(0), MRI); if (!DstRC) return true; return RBI.constrainGenericRegister(DstReg, *DstRC, MRI); }
LegalizerHelper::LegalizerHelper(MachineFunction &MF) : MRI(MF.getRegInfo()), LI(*MF.getSubtarget().getLegalizerInfo()) { MIRBuilder.setMF(MF); }
/// calculateCalleeSavedRegisters - Scan the function for modified callee saved /// registers. void PEI::calculateCalleeSavedRegisters(MachineFunction &Fn) { const TargetRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo(); const TargetFrameLowering *TFI = Fn.getTarget().getFrameLowering(); MachineFrameInfo *MFI = Fn.getFrameInfo(); // Get the callee saved register list... const unsigned *CSRegs = RegInfo->getCalleeSavedRegs(&Fn); // These are used to keep track the callee-save area. Initialize them. MinCSFrameIndex = INT_MAX; MaxCSFrameIndex = 0; // Early exit for targets which have no callee saved registers. if (CSRegs == 0 || CSRegs[0] == 0) return; // In Naked functions we aren't going to save any registers. if (Fn.getFunction()->hasFnAttr(Attribute::Naked)) return; std::vector<CalleeSavedInfo> CSI; for (unsigned i = 0; CSRegs[i]; ++i) { unsigned Reg = CSRegs[i]; if (Fn.getRegInfo().isPhysRegUsed(Reg)) { // If the reg is modified, save it! CSI.push_back(CalleeSavedInfo(Reg)); } else { for (const unsigned *AliasSet = RegInfo->getAliasSet(Reg); *AliasSet; ++AliasSet) { // Check alias registers too. if (Fn.getRegInfo().isPhysRegUsed(*AliasSet)) { CSI.push_back(CalleeSavedInfo(Reg)); break; } } } } if (CSI.empty()) return; // Early exit if no callee saved registers are modified! unsigned NumFixedSpillSlots; const TargetFrameLowering::SpillSlot *FixedSpillSlots = TFI->getCalleeSavedSpillSlots(NumFixedSpillSlots); // Now that we know which registers need to be saved and restored, allocate // stack slots for them. for (std::vector<CalleeSavedInfo>::iterator I = CSI.begin(), E = CSI.end(); I != E; ++I) { unsigned Reg = I->getReg(); const TargetRegisterClass *RC = RegInfo->getMinimalPhysRegClass(Reg); int FrameIdx; if (RegInfo->hasReservedSpillSlot(Fn, Reg, FrameIdx)) { I->setFrameIdx(FrameIdx); continue; } // Check to see if this physreg must be spilled to a particular stack slot // on this target. const TargetFrameLowering::SpillSlot *FixedSlot = FixedSpillSlots; while (FixedSlot != FixedSpillSlots+NumFixedSpillSlots && FixedSlot->Reg != Reg) ++FixedSlot; if (FixedSlot == FixedSpillSlots + NumFixedSpillSlots) { // Nope, just spill it anywhere convenient. unsigned Align = RC->getAlignment(); unsigned StackAlign = TFI->getStackAlignment(); // We may not be able to satisfy the desired alignment specification of // the TargetRegisterClass if the stack alignment is smaller. Use the // min. Align = std::min(Align, StackAlign); FrameIdx = MFI->CreateStackObject(RC->getSize(), Align, true); if ((unsigned)FrameIdx < MinCSFrameIndex) MinCSFrameIndex = FrameIdx; if ((unsigned)FrameIdx > MaxCSFrameIndex) MaxCSFrameIndex = FrameIdx; } else { // Spill it to the stack where we must. FrameIdx = MFI->CreateFixedObject(RC->getSize(), FixedSlot->Offset, true); } I->setFrameIdx(FrameIdx); } MFI->setCalleeSavedInfo(CSI); }