/// Find an insertion point in Head for the speculated instructions. The /// insertion point must be: /// /// 1. Before any terminators. /// 2. After any instructions in InsertAfter. /// 3. Not have any clobbered regunits live. /// /// This function sets InsertionPoint and returns true when successful, it /// returns false if no valid insertion point could be found. /// bool SSAIfConv::findInsertionPoint() { // Keep track of live regunits before the current position. // Only track RegUnits that are also in ClobberedRegUnits. LiveRegUnits.clear(); SmallVector<unsigned, 8> Reads; MachineBasicBlock::iterator FirstTerm = Head->getFirstTerminator(); MachineBasicBlock::iterator I = Head->end(); MachineBasicBlock::iterator B = Head->begin(); while (I != B) { --I; // Some of the conditional code depends in I. if (InsertAfter.count(I)) { DEBUG(dbgs() << "Can't insert code after " << *I); return false; } // Update live regunits. for (MIOperands MO(I); MO.isValid(); ++MO) { // We're ignoring regmask operands. That is conservatively correct. if (!MO->isReg()) continue; unsigned Reg = MO->getReg(); if (!TargetRegisterInfo::isPhysicalRegister(Reg)) continue; // I clobbers Reg, so it isn't live before I. if (MO->isDef()) for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) LiveRegUnits.erase(*Units); // Unless I reads Reg. if (MO->readsReg()) Reads.push_back(Reg); } // Anything read by I is live before I. while (!Reads.empty()) for (MCRegUnitIterator Units(Reads.pop_back_val(), TRI); Units.isValid(); ++Units) if (ClobberedRegUnits.test(*Units)) LiveRegUnits.insert(*Units); // We can't insert before a terminator. if (I != FirstTerm && I->isTerminator()) continue; // Some of the clobbered registers are live before I, not a valid insertion // point. if (!LiveRegUnits.empty()) { DEBUG({ dbgs() << "Would clobber"; for (SparseSet<unsigned>::const_iterator i = LiveRegUnits.begin(), e = LiveRegUnits.end(); i != e; ++i) dbgs() << ' ' << PrintRegUnit(*i, TRI); dbgs() << " live before " << *I; }); continue; }
// Fill MBBs and Terminators, setting the addresses on the assumption // that no branches need relaxation. Return the size of the function under // this assumption. uint64_t SystemZLongBranch::initMBBInfo() { MF->RenumberBlocks(); unsigned NumBlocks = MF->size(); MBBs.clear(); MBBs.resize(NumBlocks); Terminators.clear(); Terminators.reserve(NumBlocks); BlockPosition Position(MF->getAlignment()); for (unsigned I = 0; I < NumBlocks; ++I) { MachineBasicBlock *MBB = MF->getBlockNumbered(I); MBBInfo &Block = MBBs[I]; // Record the alignment, for quick access. Block.Alignment = MBB->getAlignment(); // Calculate the size of the fixed part of the block. MachineBasicBlock::iterator MI = MBB->begin(); MachineBasicBlock::iterator End = MBB->end(); while (MI != End && !MI->isTerminator()) { Block.Size += TII->getInstSizeInBytes(*MI); ++MI; } skipNonTerminators(Position, Block); // Add the terminators. while (MI != End) { if (!MI->isDebugValue()) { assert(MI->isTerminator() && "Terminator followed by non-terminator"); Terminators.push_back(describeTerminator(*MI)); skipTerminator(Position, Terminators.back(), false); ++Block.NumTerminators; } ++MI; } } return Position.Address; }
// Finds compare instruction that corresponds to supported types of branching. // Returns the instruction or nullptr on failures or detecting unsupported // instructions. MachineInstr *AArch64ConditionOptimizer::findSuitableCompare( MachineBasicBlock *MBB) { MachineBasicBlock::iterator I = MBB->getFirstTerminator(); if (I == MBB->end()) return nullptr; if (I->getOpcode() != AArch64::Bcc) return nullptr; // Now find the instruction controlling the terminator. for (MachineBasicBlock::iterator B = MBB->begin(); I != B;) { --I; assert(!I->isTerminator() && "Spurious terminator"); switch (I->getOpcode()) { // cmp is an alias for subs with a dead destination register. case AArch64::SUBSWri: case AArch64::SUBSXri: // cmn is an alias for adds with a dead destination register. case AArch64::ADDSWri: case AArch64::ADDSXri: if (MRI->use_empty(I->getOperand(0).getReg())) return I; DEBUG(dbgs() << "Destination of cmp is not dead, " << *I << '\n'); return nullptr; // Prevent false positive case like: // cmp w19, #0 // cinc w0, w19, gt // ... // fcmp d8, #0.0 // b.gt .LBB0_5 case AArch64::FCMPDri: case AArch64::FCMPSri: case AArch64::FCMPESri: case AArch64::FCMPEDri: case AArch64::SUBSWrr: case AArch64::SUBSXrr: case AArch64::ADDSWrr: case AArch64::ADDSXrr: case AArch64::FCMPSrr: case AArch64::FCMPDrr: case AArch64::FCMPESrr: case AArch64::FCMPEDrr: // Skip comparison instructions without immediate operands. return nullptr; } } DEBUG(dbgs() << "Flags not defined in BB#" << MBB->getNumber() << '\n'); return nullptr; }
void GCMachineCodeAnalysis::FindSafePoints(MachineFunction &MF) { for (MachineFunction::iterator BBI = MF.begin(), BBE = MF.end(); BBI != BBE; ++BBI) for (MachineBasicBlock::iterator MI = BBI->begin(), ME = BBI->end(); MI != ME; ++MI) if (MI->isCall()) { // Do not treat tail or sibling call sites as safe points. This is // legal since any arguments passed to the callee which live in the // remnants of the callers frame will be owned and updated by the // callee if required. if (MI->isTerminator()) continue; VisitCallPoint(MI); } }
MachineInstr *SSACCmpConv::findConvertibleCompare(MachineBasicBlock *MBB) { MachineBasicBlock::iterator I = MBB->getFirstTerminator(); if (I == MBB->end()) return nullptr; // The terminator must be controlled by the flags. if (!I->readsRegister(AArch64::NZCV)) { switch (I->getOpcode()) { case AArch64::CBZW: case AArch64::CBZX: case AArch64::CBNZW: case AArch64::CBNZX: // These can be converted into a ccmp against #0. return I; } ++NumCmpTermRejs; DEBUG(dbgs() << "Flags not used by terminator: " << *I); return nullptr; } // Now find the instruction controlling the terminator. for (MachineBasicBlock::iterator B = MBB->begin(); I != B;) { --I; assert(!I->isTerminator() && "Spurious terminator"); switch (I->getOpcode()) { // cmp is an alias for subs with a dead destination register. case AArch64::SUBSWri: case AArch64::SUBSXri: // cmn is an alias for adds with a dead destination register. case AArch64::ADDSWri: case AArch64::ADDSXri: // Check that the immediate operand is within range, ccmp wants a uimm5. // Rd = SUBSri Rn, imm, shift if (I->getOperand(3).getImm() || !isUInt<5>(I->getOperand(2).getImm())) { DEBUG(dbgs() << "Immediate out of range for ccmp: " << *I); ++NumImmRangeRejs; return nullptr; } // Fall through. case AArch64::SUBSWrr: case AArch64::SUBSXrr: case AArch64::ADDSWrr: case AArch64::ADDSXrr: if (isDeadDef(I->getOperand(0).getReg())) return I; DEBUG(dbgs() << "Can't convert compare with live destination: " << *I); ++NumLiveDstRejs; return nullptr; case AArch64::FCMPSrr: case AArch64::FCMPDrr: case AArch64::FCMPESrr: case AArch64::FCMPEDrr: return I; } // Check for flag reads and clobbers. MIOperands::PhysRegInfo PRI = MIOperands(I).analyzePhysReg(AArch64::NZCV, TRI); if (PRI.Reads) { // The ccmp doesn't produce exactly the same flags as the original // compare, so reject the transform if there are uses of the flags // besides the terminators. DEBUG(dbgs() << "Can't create ccmp with multiple uses: " << *I); ++NumMultNZCVUses; return nullptr; } if (PRI.Clobbers) { DEBUG(dbgs() << "Not convertible compare: " << *I); ++NumUnknNZCVDefs; return nullptr; } } DEBUG(dbgs() << "Flags not defined in BB#" << MBB->getNumber() << '\n'); return nullptr; }
// Finds compare instruction that corresponds to supported types of branching. // Returns the instruction or nullptr on failures or detecting unsupported // instructions. MachineInstr *AArch64ConditionOptimizer::findSuitableCompare( MachineBasicBlock *MBB) { MachineBasicBlock::iterator I = MBB->getFirstTerminator(); if (I == MBB->end()) return nullptr; if (I->getOpcode() != AArch64::Bcc) return nullptr; // Since we may modify cmp of this MBB, make sure NZCV does not live out. for (auto SuccBB : MBB->successors()) if (SuccBB->isLiveIn(AArch64::NZCV)) return nullptr; // Now find the instruction controlling the terminator. for (MachineBasicBlock::iterator B = MBB->begin(); I != B;) { --I; assert(!I->isTerminator() && "Spurious terminator"); // Check if there is any use of NZCV between CMP and Bcc. if (I->readsRegister(AArch64::NZCV)) return nullptr; switch (I->getOpcode()) { // cmp is an alias for subs with a dead destination register. case AArch64::SUBSWri: case AArch64::SUBSXri: // cmn is an alias for adds with a dead destination register. case AArch64::ADDSWri: case AArch64::ADDSXri: { unsigned ShiftAmt = AArch64_AM::getShiftValue(I->getOperand(3).getImm()); if (!I->getOperand(2).isImm()) { DEBUG(dbgs() << "Immediate of cmp is symbolic, " << *I << '\n'); return nullptr; } else if (I->getOperand(2).getImm() << ShiftAmt >= 0xfff) { DEBUG(dbgs() << "Immediate of cmp may be out of range, " << *I << '\n'); return nullptr; } else if (!MRI->use_empty(I->getOperand(0).getReg())) { DEBUG(dbgs() << "Destination of cmp is not dead, " << *I << '\n'); return nullptr; } return I; } // Prevent false positive case like: // cmp w19, #0 // cinc w0, w19, gt // ... // fcmp d8, #0.0 // b.gt .LBB0_5 case AArch64::FCMPDri: case AArch64::FCMPSri: case AArch64::FCMPESri: case AArch64::FCMPEDri: case AArch64::SUBSWrr: case AArch64::SUBSXrr: case AArch64::ADDSWrr: case AArch64::ADDSXrr: case AArch64::FCMPSrr: case AArch64::FCMPDrr: case AArch64::FCMPESrr: case AArch64::FCMPEDrr: // Skip comparison instructions without immediate operands. return nullptr; } } DEBUG(dbgs() << "Flags not defined in BB#" << MBB->getNumber() << '\n'); return nullptr; }
bool AArch64RedundantCopyElimination::optimizeBlock(MachineBasicBlock *MBB) { // Check if the current basic block has a single predecessor. if (MBB->pred_size() != 1) return false; // Check if the predecessor has two successors, implying the block ends in a // conditional branch. MachineBasicBlock *PredMBB = *MBB->pred_begin(); if (PredMBB->succ_size() != 2) return false; MachineBasicBlock::iterator CondBr = PredMBB->getLastNonDebugInstr(); if (CondBr == PredMBB->end()) return false; // Keep track of the earliest point in the PredMBB block where kill markers // need to be removed if a COPY is removed. MachineBasicBlock::iterator FirstUse; // After calling knownRegValInBlock, FirstUse will either point to a CBZ/CBNZ // or a compare (i.e., SUBS). In the latter case, we must take care when // updating FirstUse when scanning for COPY instructions. In particular, if // there's a COPY in between the compare and branch the COPY should not // update FirstUse. bool SeenFirstUse = false; // Registers that contain a known value at the start of MBB. SmallVector<RegImm, 4> KnownRegs; MachineBasicBlock::iterator Itr = std::next(CondBr); do { --Itr; if (!knownRegValInBlock(*Itr, MBB, KnownRegs, FirstUse)) continue; // Reset the clobber list. OptBBClobberedRegs.reset(); // Look backward in PredMBB for COPYs from the known reg to find other // registers that are known to be a constant value. for (auto PredI = Itr;; --PredI) { if (FirstUse == PredI) SeenFirstUse = true; if (PredI->isCopy()) { MCPhysReg CopyDstReg = PredI->getOperand(0).getReg(); MCPhysReg CopySrcReg = PredI->getOperand(1).getReg(); for (auto &KnownReg : KnownRegs) { if (OptBBClobberedRegs[KnownReg.Reg]) continue; // If we have X = COPY Y, and Y is known to be zero, then now X is // known to be zero. if (CopySrcReg == KnownReg.Reg && !OptBBClobberedRegs[CopyDstReg]) { KnownRegs.push_back(RegImm(CopyDstReg, KnownReg.Imm)); if (SeenFirstUse) FirstUse = PredI; break; } // If we have X = COPY Y, and X is known to be zero, then now Y is // known to be zero. if (CopyDstReg == KnownReg.Reg && !OptBBClobberedRegs[CopySrcReg]) { KnownRegs.push_back(RegImm(CopySrcReg, KnownReg.Imm)); if (SeenFirstUse) FirstUse = PredI; break; } } } // Stop if we get to the beginning of PredMBB. if (PredI == PredMBB->begin()) break; trackRegDefs(*PredI, OptBBClobberedRegs, TRI); // Stop if all of the known-zero regs have been clobbered. if (all_of(KnownRegs, [&](RegImm KnownReg) { return OptBBClobberedRegs[KnownReg.Reg]; })) break; } break; } while (Itr != PredMBB->begin() && Itr->isTerminator()); // We've not found a registers with a known value, time to bail out. if (KnownRegs.empty()) return false; bool Changed = false; // UsedKnownRegs is the set of KnownRegs that have had uses added to MBB. SmallSetVector<unsigned, 4> UsedKnownRegs; MachineBasicBlock::iterator LastChange = MBB->begin(); // Remove redundant copy/move instructions unless KnownReg is modified. for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E;) { MachineInstr *MI = &*I; ++I; bool RemovedMI = false; bool IsCopy = MI->isCopy(); bool IsMoveImm = MI->isMoveImmediate(); if (IsCopy || IsMoveImm) { MCPhysReg DefReg = MI->getOperand(0).getReg(); MCPhysReg SrcReg = IsCopy ? MI->getOperand(1).getReg() : 0; int64_t SrcImm = IsMoveImm ? MI->getOperand(1).getImm() : 0; if (!MRI->isReserved(DefReg) && ((IsCopy && (SrcReg == AArch64::XZR || SrcReg == AArch64::WZR)) || IsMoveImm)) { for (RegImm &KnownReg : KnownRegs) { if (KnownReg.Reg != DefReg && !TRI->isSuperRegister(DefReg, KnownReg.Reg)) continue; // For a copy, the known value must be a zero. if (IsCopy && KnownReg.Imm != 0) continue; if (IsMoveImm) { // For a move immediate, the known immediate must match the source // immediate. if (KnownReg.Imm != SrcImm) continue; // Don't remove a move immediate that implicitly defines the upper // bits when only the lower 32 bits are known. MCPhysReg CmpReg = KnownReg.Reg; if (any_of(MI->implicit_operands(), [CmpReg](MachineOperand &O) { return !O.isDead() && O.isReg() && O.isDef() && O.getReg() != CmpReg; })) continue; } if (IsCopy) DEBUG(dbgs() << "Remove redundant Copy : " << *MI); else DEBUG(dbgs() << "Remove redundant Move : " << *MI); MI->eraseFromParent(); Changed = true; LastChange = I; NumCopiesRemoved++; UsedKnownRegs.insert(KnownReg.Reg); RemovedMI = true; break; } } } // Skip to the next instruction if we removed the COPY/MovImm. if (RemovedMI) continue; // Remove any regs the MI clobbers from the KnownConstRegs set. for (unsigned RI = 0; RI < KnownRegs.size();) if (MI->modifiesRegister(KnownRegs[RI].Reg, TRI)) { std::swap(KnownRegs[RI], KnownRegs[KnownRegs.size() - 1]); KnownRegs.pop_back(); // Don't increment RI since we need to now check the swapped-in // KnownRegs[RI]. } else { ++RI; } // Continue until the KnownRegs set is empty. if (KnownRegs.empty()) break; } if (!Changed) return false; // Add newly used regs to the block's live-in list if they aren't there // already. for (MCPhysReg KnownReg : UsedKnownRegs) if (!MBB->isLiveIn(KnownReg)) MBB->addLiveIn(KnownReg); // Clear kills in the range where changes were made. This is conservative, // but should be okay since kill markers are being phased out. DEBUG(dbgs() << "Clearing kill flags.\n\tFirstUse: " << *FirstUse << "\tLastChange: " << *LastChange); for (MachineInstr &MMI : make_range(FirstUse, PredMBB->end())) MMI.clearKillInfo(); for (MachineInstr &MMI : make_range(MBB->begin(), LastChange)) MMI.clearKillInfo(); return true; }
void AVRFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { CallingConv::ID CallConv = MF.getFunction()->getCallingConv(); bool isHandler = (CallConv == CallingConv::AVR_INTR || CallConv == CallingConv::AVR_SIGNAL); // Early exit if the frame pointer is not needed in this function except for // signal/interrupt handlers where special code generation is required. if (!hasFP(MF) && !isHandler) { return; } MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); assert(MBBI->getDesc().isReturn() && "Can only insert epilog into returning blocks"); DebugLoc DL = MBBI->getDebugLoc(); const MachineFrameInfo &MFI = MF.getFrameInfo(); const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>(); unsigned FrameSize = MFI.getStackSize() - AFI->getCalleeSavedFrameSize(); const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>(); const AVRInstrInfo &TII = *STI.getInstrInfo(); // Emit special epilogue code to restore R1, R0 and SREG in interrupt/signal // handlers at the very end of the function, just before reti. if (isHandler) { BuildMI(MBB, MBBI, DL, TII.get(AVR::POPRd), AVR::R0); BuildMI(MBB, MBBI, DL, TII.get(AVR::OUTARr)) .addImm(0x3f) .addReg(AVR::R0, RegState::Kill); BuildMI(MBB, MBBI, DL, TII.get(AVR::POPWRd), AVR::R1R0); } if (hasFP(MF)) BuildMI(MBB, MBBI, DL, TII.get(AVR::POPWRd), AVR::R29R28); // Early exit if there is no need to restore the frame pointer. if (!FrameSize) { return; } // Skip the callee-saved pop instructions. while (MBBI != MBB.begin()) { MachineBasicBlock::iterator PI = std::prev(MBBI); int Opc = PI->getOpcode(); if (Opc != AVR::POPRd && Opc != AVR::POPWRd && !PI->isTerminator()) { break; } --MBBI; } unsigned Opcode; // Select the optimal opcode depending on how big it is. if (isUInt<6>(FrameSize)) { Opcode = AVR::ADIWRdK; } else { Opcode = AVR::SUBIWRdK; FrameSize = -FrameSize; } // Restore the frame pointer by doing FP += <size>. MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII.get(Opcode), AVR::R29R28) .addReg(AVR::R29R28, RegState::Kill) .addImm(FrameSize); // The SREG implicit def is dead. MI->getOperand(3).setIsDead(); // Write back R29R28 to SP and temporarily disable interrupts. BuildMI(MBB, MBBI, DL, TII.get(AVR::SPWRITE), AVR::SP) .addReg(AVR::R29R28, RegState::Kill); }
/// insertCSRSpillsAndRestores - Insert spill and restore code for /// callee saved registers used in the function, handling shrink wrapping. /// void PEI::insertCSRSpillsAndRestores(MachineFunction &Fn) { // Get callee saved register information. MachineFrameInfo *MFI = Fn.getFrameInfo(); const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); MFI->setCalleeSavedInfoValid(true); // Early exit if no callee saved registers are modified! if (CSI.empty()) return; const TargetInstrInfo &TII = *Fn.getTarget().getInstrInfo(); const TargetFrameLowering *TFI = Fn.getTarget().getFrameLowering(); const TargetRegisterInfo *TRI = Fn.getTarget().getRegisterInfo(); MachineBasicBlock::iterator I; if (!ShrinkWrapThisFunction) { // Spill using target interface. I = EntryBlock->begin(); if (!TFI->spillCalleeSavedRegisters(*EntryBlock, I, CSI, TRI)) { for (unsigned i = 0, e = CSI.size(); i != e; ++i) { // Add the callee-saved register as live-in. // It's killed at the spill. EntryBlock->addLiveIn(CSI[i].getReg()); // Insert the spill to the stack frame. unsigned Reg = CSI[i].getReg(); const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); TII.storeRegToStackSlot(*EntryBlock, I, Reg, true, CSI[i].getFrameIdx(), RC, TRI); } } // Restore using target interface. for (unsigned ri = 0, re = ReturnBlocks.size(); ri != re; ++ri) { MachineBasicBlock* MBB = ReturnBlocks[ri]; I = MBB->end(); --I; // Skip over all terminator instructions, which are part of the return // sequence. MachineBasicBlock::iterator I2 = I; while (I2 != MBB->begin() && (--I2)->isTerminator()) I = I2; bool AtStart = I == MBB->begin(); MachineBasicBlock::iterator BeforeI = I; if (!AtStart) --BeforeI; // Restore all registers immediately before the return and any // terminators that precede it. if (!TFI->restoreCalleeSavedRegisters(*MBB, I, CSI, TRI)) { for (unsigned i = 0, e = CSI.size(); i != e; ++i) { unsigned Reg = CSI[i].getReg(); const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); TII.loadRegFromStackSlot(*MBB, I, Reg, CSI[i].getFrameIdx(), RC, TRI); assert(I != MBB->begin() && "loadRegFromStackSlot didn't insert any code!"); // Insert in reverse order. loadRegFromStackSlot can insert // multiple instructions. if (AtStart) I = MBB->begin(); else { I = BeforeI; ++I; } } } } return; } // Insert spills. std::vector<CalleeSavedInfo> blockCSI; for (CSRegBlockMap::iterator BI = CSRSave.begin(), BE = CSRSave.end(); BI != BE; ++BI) { MachineBasicBlock* MBB = BI->first; CSRegSet save = BI->second; if (save.empty()) continue; blockCSI.clear(); for (CSRegSet::iterator RI = save.begin(), RE = save.end(); RI != RE; ++RI) { blockCSI.push_back(CSI[*RI]); } assert(blockCSI.size() > 0 && "Could not collect callee saved register info"); I = MBB->begin(); // When shrink wrapping, use stack slot stores/loads. for (unsigned i = 0, e = blockCSI.size(); i != e; ++i) { // Add the callee-saved register as live-in. // It's killed at the spill. MBB->addLiveIn(blockCSI[i].getReg()); // Insert the spill to the stack frame. unsigned Reg = blockCSI[i].getReg(); const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); TII.storeRegToStackSlot(*MBB, I, Reg, true, blockCSI[i].getFrameIdx(), RC, TRI); } } for (CSRegBlockMap::iterator BI = CSRRestore.begin(), BE = CSRRestore.end(); BI != BE; ++BI) { MachineBasicBlock* MBB = BI->first; CSRegSet restore = BI->second; if (restore.empty()) continue; blockCSI.clear(); for (CSRegSet::iterator RI = restore.begin(), RE = restore.end(); RI != RE; ++RI) { blockCSI.push_back(CSI[*RI]); } assert(blockCSI.size() > 0 && "Could not find callee saved register info"); // If MBB is empty and needs restores, insert at the _beginning_. if (MBB->empty()) { I = MBB->begin(); } else { I = MBB->end(); --I; // Skip over all terminator instructions, which are part of the // return sequence. if (! I->isTerminator()) { ++I; } else { MachineBasicBlock::iterator I2 = I; while (I2 != MBB->begin() && (--I2)->isTerminator()) I = I2; } } bool AtStart = I == MBB->begin(); MachineBasicBlock::iterator BeforeI = I; if (!AtStart) --BeforeI; // Restore all registers immediately before the return and any // terminators that precede it. for (unsigned i = 0, e = blockCSI.size(); i != e; ++i) { unsigned Reg = blockCSI[i].getReg(); const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); TII.loadRegFromStackSlot(*MBB, I, Reg, blockCSI[i].getFrameIdx(), RC, TRI); assert(I != MBB->begin() && "loadRegFromStackSlot didn't insert any code!"); // Insert in reverse order. loadRegFromStackSlot can insert // multiple instructions. if (AtStart) I = MBB->begin(); else { I = BeforeI; ++I; } } } }
bool AArch64RedundantCopyElimination::optimizeCopy(MachineBasicBlock *MBB) { // Check if the current basic block has a single predecessor. if (MBB->pred_size() != 1) return false; MachineBasicBlock *PredMBB = *MBB->pred_begin(); MachineBasicBlock::iterator CompBr = PredMBB->getLastNonDebugInstr(); if (CompBr == PredMBB->end() || PredMBB->succ_size() != 2) return false; ++CompBr; do { --CompBr; if (guaranteesZeroRegInBlock(*CompBr, MBB)) break; } while (CompBr != PredMBB->begin() && CompBr->isTerminator()); // We've not found a CBZ/CBNZ, time to bail out. if (!guaranteesZeroRegInBlock(*CompBr, MBB)) return false; unsigned TargetReg = CompBr->getOperand(0).getReg(); if (!TargetReg) return false; assert(TargetRegisterInfo::isPhysicalRegister(TargetReg) && "Expect physical register"); // Remember all registers aliasing with TargetReg. SmallSetVector<unsigned, 8> TargetRegs; for (MCRegAliasIterator AI(TargetReg, TRI, true); AI.isValid(); ++AI) TargetRegs.insert(*AI); bool Changed = false; MachineBasicBlock::iterator LastChange = MBB->begin(); unsigned SmallestDef = TargetReg; // Remove redundant Copy instructions unless TargetReg is modified. for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E;) { MachineInstr *MI = &*I; ++I; if (MI->isCopy() && MI->getOperand(0).isReg() && MI->getOperand(1).isReg()) { unsigned DefReg = MI->getOperand(0).getReg(); unsigned SrcReg = MI->getOperand(1).getReg(); if ((SrcReg == AArch64::XZR || SrcReg == AArch64::WZR) && !MRI->isReserved(DefReg) && (TargetReg == DefReg || TRI->isSuperRegister(DefReg, TargetReg))) { DEBUG(dbgs() << "Remove redundant Copy : "); DEBUG((MI)->print(dbgs())); MI->eraseFromParent(); Changed = true; LastChange = I; NumCopiesRemoved++; SmallestDef = TRI->isSubRegister(SmallestDef, DefReg) ? DefReg : SmallestDef; continue; } } if (MI->modifiesRegister(TargetReg, TRI)) break; } if (!Changed) return false; // Otherwise, we have to fixup the use-def chain, starting with the // CBZ/CBNZ. Conservatively mark as much as we can live. CompBr->clearRegisterKills(SmallestDef, TRI); if (std::none_of(TargetRegs.begin(), TargetRegs.end(), [&](unsigned Reg) { return MBB->isLiveIn(Reg); })) MBB->addLiveIn(TargetReg); // Clear any kills of TargetReg between CompBr and the last removed COPY. for (MachineInstr &MMI : make_range(MBB->begin()->getIterator(), LastChange->getIterator())) MMI.clearRegisterKills(SmallestDef, TRI); return true; }
void MSP430FrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { const MachineFrameInfo *MFI = MF.getFrameInfo(); MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>(); const MSP430InstrInfo &TII = *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo()); MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); unsigned RetOpcode = MBBI->getOpcode(); DebugLoc DL = MBBI->getDebugLoc(); switch (RetOpcode) { case MSP430::RET: case MSP430::RETI: break; // These are ok default: llvm_unreachable("Can only insert epilog into returning blocks"); } // Get the number of bytes to allocate from the FrameInfo uint64_t StackSize = MFI->getStackSize(); unsigned CSSize = MSP430FI->getCalleeSavedFrameSize(); uint64_t NumBytes = 0; if (hasFP(MF)) { // Calculate required stack adjustment uint64_t FrameSize = StackSize - 2; NumBytes = FrameSize - CSSize; // pop FP. BuildMI(MBB, MBBI, DL, TII.get(MSP430::POP16r), MSP430::FP); } else NumBytes = StackSize - CSSize; // Skip the callee-saved pop instructions. while (MBBI != MBB.begin()) { MachineBasicBlock::iterator PI = std::prev(MBBI); unsigned Opc = PI->getOpcode(); if (Opc != MSP430::POP16r && !PI->isTerminator()) break; --MBBI; } DL = MBBI->getDebugLoc(); // If there is an ADD16ri or SUB16ri of SP immediately before this // instruction, merge the two instructions. //if (NumBytes || MFI->hasVarSizedObjects()) // mergeSPUpdatesUp(MBB, MBBI, StackPtr, &NumBytes); if (MFI->hasVarSizedObjects()) { BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::SP).addReg(MSP430::FP); if (CSSize) { MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP) .addReg(MSP430::SP).addImm(CSSize); // The SRW implicit def is dead. MI->getOperand(3).setIsDead(); } } else { // adjust stack pointer back: SP += numbytes if (NumBytes) { MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII.get(MSP430::ADD16ri), MSP430::SP) .addReg(MSP430::SP).addImm(NumBytes); // The SRW implicit def is dead. MI->getOperand(3).setIsDead(); } } }
bool ARCInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl<MachineOperand> &Cond, bool AllowModify) const { TBB = FBB = nullptr; MachineBasicBlock::iterator I = MBB.end(); if (I == MBB.begin()) return false; --I; while (isPredicated(*I) || I->isTerminator() || I->isDebugValue()) { // Flag to be raised on unanalyzeable instructions. This is useful in cases // where we want to clean up on the end of the basic block before we bail // out. bool CantAnalyze = false; // Skip over DEBUG values and predicated nonterminators. while (I->isDebugValue() || !I->isTerminator()) { if (I == MBB.begin()) return false; --I; } if (isJumpOpcode(I->getOpcode())) { // Indirect branches and jump tables can't be analyzed, but we still want // to clean up any instructions at the tail of the basic block. CantAnalyze = true; } else if (isUncondBranchOpcode(I->getOpcode())) { TBB = I->getOperand(0).getMBB(); } else if (isCondBranchOpcode(I->getOpcode())) { // Bail out if we encounter multiple conditional branches. if (!Cond.empty()) return true; assert(!FBB && "FBB should have been null."); FBB = TBB; TBB = I->getOperand(0).getMBB(); Cond.push_back(I->getOperand(1)); Cond.push_back(I->getOperand(2)); Cond.push_back(I->getOperand(3)); } else if (I->isReturn()) { // Returns can't be analyzed, but we should run cleanup. CantAnalyze = !isPredicated(*I); } else { // We encountered other unrecognized terminator. Bail out immediately. return true; } // Cleanup code - to be run for unpredicated unconditional branches and // returns. if (!isPredicated(*I) && (isUncondBranchOpcode(I->getOpcode()) || isJumpOpcode(I->getOpcode()) || I->isReturn())) { // Forget any previous condition branch information - it no longer // applies. Cond.clear(); FBB = nullptr; // If we can modify the function, delete everything below this // unconditional branch. if (AllowModify) { MachineBasicBlock::iterator DI = std::next(I); while (DI != MBB.end()) { MachineInstr &InstToDelete = *DI; ++DI; InstToDelete.eraseFromParent(); } } } if (CantAnalyze) return true; if (I == MBB.begin()) return false; --I; } // We made it past the terminators without bailing out - we must have // analyzed this branch successfully. return false; }