int PatmosInstrInfo::findPrevDelaySlotEnd(MachineBasicBlock &MBB, MachineBasicBlock::iterator &II, int Cycles) const { int cnt = 0; int maxDelaySlotSize = PST.getCFLDelaySlotCycles(false); while (II != MBB.begin()) { --II; if (isPseudo(&*II)) continue; // This code assumes that delay slots can not be completely inside other // delay slots, i.e., we only need to scan up to the first CFL instruction. if (II->isInlineAsm()) { break; } if (II->isBranch() || II->isCall() || II->isReturn()) { cnt -= PST.getDelaySlotCycles(&*II); break; } if (Cycles >= 0 && cnt >= Cycles + maxDelaySlotSize) break; cnt++; } return Cycles >= 0 && cnt > Cycles ? Cycles : cnt; }
bool OR1KInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl<MachineOperand> &Cond, bool AllowModify) const { // Start from the bottom of the block and work up, examining the // terminator instructions. MachineBasicBlock::iterator I = MBB.end(); while (I != MBB.begin()) { --I; if (I->isDebugValue()) continue; // Working from the bottom, when we see a non-terminator // instruction, we're done. if (!isUnpredicatedTerminator(*I)) break; // A terminator that isn't a branch can't easily be handled // by this analysis. if (!I->isBranch()) return true; // Cannot handle indirect branches. if (I->getOpcode() == OR1K::JR) return true; // Handle unconditional branches. if (I->getOpcode() == OR1K::J) { if (!AllowModify) { TBB = I->getOperand(0).getMBB(); continue; } // If the block has any instructions after a J, delete them. while (std::next(I) != MBB.end()) std::next(I)->eraseFromParent(); Cond.clear(); FBB = 0; // Delete the J if it's equivalent to a fall-through. if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) { TBB = 0; I->eraseFromParent(); I = MBB.end(); continue; } // TBB is used to indicate the unconditinal destination. TBB = I->getOperand(0).getMBB(); continue; } // Cannot handle conditional branches return true; } return false; }
void Thumb2InstrInfo::ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail, MachineBasicBlock *NewDest) const { MachineBasicBlock *MBB = Tail->getParent(); ARMFunctionInfo *AFI = MBB->getParent()->getInfo<ARMFunctionInfo>(); if (!AFI->hasITBlocks() || Tail->isBranch()) { TargetInstrInfo::ReplaceTailWithBranchTo(Tail, NewDest); return; } // If the first instruction of Tail is predicated, we may have to update // the IT instruction. unsigned PredReg = 0; ARMCC::CondCodes CC = getInstrPredicate(*Tail, PredReg); MachineBasicBlock::iterator MBBI = Tail; if (CC != ARMCC::AL) // Expecting at least the t2IT instruction before it. --MBBI; // Actually replace the tail. TargetInstrInfo::ReplaceTailWithBranchTo(Tail, NewDest); // Fix up IT. if (CC != ARMCC::AL) { MachineBasicBlock::iterator E = MBB->begin(); unsigned Count = 4; // At most 4 instructions in an IT block. while (Count && MBBI != E) { if (MBBI->isDebugValue()) { --MBBI; continue; } if (MBBI->getOpcode() == ARM::t2IT) { unsigned Mask = MBBI->getOperand(1).getImm(); if (Count == 4) MBBI->eraseFromParent(); else { unsigned MaskOn = 1 << Count; unsigned MaskOff = ~(MaskOn - 1); MBBI->getOperand(1).setImm((Mask & MaskOff) | MaskOn); } return; } --MBBI; --Count; } // Ctrl flow can reach here if branch folding is run before IT block // formation pass. } }
unsigned PatmosInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { MachineBasicBlock::iterator I = MBB.end(); unsigned Count = 0; while (I != MBB.begin()) { --I; if (I->isDebugValue()) continue; if (!I->isBranch()) break; // Not a branch // Remove the branch. I->eraseFromParent(); I = MBB.end(); ++Count; } return Count; }
// The AnalyzeBranch function is used to examine conditional instructions and // remove unnecessary instructions. This method is used by BranchFolder and // IfConverter machine function passes to improve the CFG. // - TrueBlock is set to the destination if condition evaluates true (it is the // nullptr if the destination is the fall-through branch); // - FalseBlock is set to the destination if condition evaluates to false (it // is the nullptr if the branch is unconditional); // - condition is populated with machine operands needed to generate the branch // to insert in InsertBranch; // Returns: false if branch could successfully be analyzed. bool LanaiInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TrueBlock, MachineBasicBlock *&FalseBlock, SmallVectorImpl<MachineOperand> &Condition, bool AllowModify) const { // Iterator to current instruction being considered. MachineBasicBlock::iterator Instruction = MBB.end(); // Start from the bottom of the block and work up, examining the // terminator instructions. while (Instruction != MBB.begin()) { --Instruction; // Skip over debug values. if (Instruction->isDebugValue()) continue; // Working from the bottom, when we see a non-terminator // instruction, we're done. if (!isUnpredicatedTerminator(*Instruction)) break; // A terminator that isn't a branch can't easily be handled // by this analysis. if (!Instruction->isBranch()) return true; // Handle unconditional branches. if (Instruction->getOpcode() == Lanai::BT) { if (!AllowModify) { TrueBlock = Instruction->getOperand(0).getMBB(); continue; } // If the block has any instructions after a branch, delete them. while (std::next(Instruction) != MBB.end()) { std::next(Instruction)->eraseFromParent(); } Condition.clear(); FalseBlock = nullptr; // Delete the jump if it's equivalent to a fall-through. if (MBB.isLayoutSuccessor(Instruction->getOperand(0).getMBB())) { TrueBlock = nullptr; Instruction->eraseFromParent(); Instruction = MBB.end(); continue; } // TrueBlock is used to indicate the unconditional destination. TrueBlock = Instruction->getOperand(0).getMBB(); continue; } // Handle conditional branches unsigned Opcode = Instruction->getOpcode(); if (Opcode != Lanai::BRCC) return true; // Unknown opcode. // Multiple conditional branches are not handled here so only proceed if // there are no conditions enqueued. if (Condition.empty()) { LPCC::CondCode BranchCond = static_cast<LPCC::CondCode>(Instruction->getOperand(1).getImm()); // TrueBlock is the target of the previously seen unconditional branch. FalseBlock = TrueBlock; TrueBlock = Instruction->getOperand(0).getMBB(); Condition.push_back(MachineOperand::CreateImm(BranchCond)); continue; } // Multiple conditional branches are not handled. return true; } // Return false indicating branch successfully analyzed. return false; }
bool MSP430InstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl<MachineOperand> &Cond, bool AllowModify) const { // Start from the bottom of the block and work up, examining the // terminator instructions. MachineBasicBlock::iterator I = MBB.end(); while (I != MBB.begin()) { --I; if (I->isDebugValue()) continue; // Working from the bottom, when we see a non-terminator // instruction, we're done. if (!isUnpredicatedTerminator(I)) break; // A terminator that isn't a branch can't easily be handled // by this analysis. if (!I->isBranch()) return true; // Cannot handle indirect branches. if (I->getOpcode() == MSP430::Br || I->getOpcode() == MSP430::Bm) return true; // Handle unconditional branches. if (I->getOpcode() == MSP430::JMP) { if (!AllowModify) { TBB = I->getOperand(0).getMBB(); continue; } // If the block has any instructions after a JMP, delete them. while (std::next(I) != MBB.end()) std::next(I)->eraseFromParent(); Cond.clear(); FBB = nullptr; // Delete the JMP if it's equivalent to a fall-through. if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) { TBB = nullptr; I->eraseFromParent(); I = MBB.end(); continue; } // TBB is used to indicate the unconditinal destination. TBB = I->getOperand(0).getMBB(); continue; } // Handle conditional branches. assert(I->getOpcode() == MSP430::JCC && "Invalid conditional branch"); MSP430CC::CondCodes BranchCode = static_cast<MSP430CC::CondCodes>(I->getOperand(1).getImm()); if (BranchCode == MSP430CC::COND_INVALID) return true; // Can't handle weird stuff. // Working from the bottom, handle the first conditional branch. if (Cond.empty()) { FBB = TBB; TBB = I->getOperand(0).getMBB(); Cond.push_back(MachineOperand::CreateImm(BranchCode)); continue; } // Handle subsequent conditional branches. Only handle the case where all // conditional branches branch to the same destination. assert(Cond.size() == 1); assert(TBB); // Only handle the case where all conditional branches branch to // the same destination. if (TBB != I->getOperand(0).getMBB()) return true; MSP430CC::CondCodes OldBranchCode = (MSP430CC::CondCodes)Cond[0].getImm(); // If the conditions are the same, we can leave them alone. if (OldBranchCode == BranchCode) continue; return true; } return false; }
MachineInstrBuilder MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc, MachineBasicBlock::iterator I) const { MachineInstrBuilder MIB; // Certain branches have two forms: e.g beq $1, $zero, dst vs beqz $1, dest // Pick the zero form of the branch for readable assembly and for greater // branch distance in non-microMIPS mode. // FIXME: Certain atomic sequences on mips64 generate 32bit references to // Mips::ZERO, which is incorrect. This test should be updated to use // Subtarget.getABI().GetZeroReg() when those atomic sequences and others // are fixed. bool BranchWithZeroOperand = (I->isBranch() && !I->isPseudo() && I->getOperand(1).isReg() && (I->getOperand(1).getReg() == Mips::ZERO || I->getOperand(1).getReg() == Mips::ZERO_64)); if (BranchWithZeroOperand) { switch (NewOpc) { case Mips::BEQC: NewOpc = Mips::BEQZC; break; case Mips::BNEC: NewOpc = Mips::BNEZC; break; case Mips::BGEC: NewOpc = Mips::BGEZC; break; case Mips::BLTC: NewOpc = Mips::BLTZC; break; } } MIB = BuildMI(*I->getParent(), I, I->getDebugLoc(), get(NewOpc)); // For MIPSR6 JI*C requires an immediate 0 as an operand, JIALC(64) an // immediate 0 as an operand and requires the removal of it's %RA<imp-def> // implicit operand as copying the implicit operations of the instructio we're // looking at will give us the correct flags. if (NewOpc == Mips::JIC || NewOpc == Mips::JIALC || NewOpc == Mips::JIC64 || NewOpc == Mips::JIALC64) { if (NewOpc == Mips::JIALC || NewOpc == Mips::JIALC64) MIB->RemoveOperand(0); for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) { MIB.addOperand(I->getOperand(J)); } MIB.addImm(0); } else if (BranchWithZeroOperand) { // For MIPSR6 and microMIPS branches with an explicit zero operand, copy // everything after the zero. MIB.addOperand(I->getOperand(0)); for (unsigned J = 2, E = I->getDesc().getNumOperands(); J < E; ++J) { MIB.addOperand(I->getOperand(J)); } } else { // All other cases copy all other operands. for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) { MIB.addOperand(I->getOperand(J)); } } MIB.copyImplicitOps(*I); MIB.setMemRefs(I->memoperands_begin(), I->memoperands_end()); return MIB; }
MachineInstrBuilder MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc, MachineBasicBlock::iterator I) const { MachineInstrBuilder MIB; // Certain branches have two forms: e.g beq $1, $zero, dest vs beqz $1, dest // Pick the zero form of the branch for readable assembly and for greater // branch distance in non-microMIPS mode. // Additional MIPSR6 does not permit the use of register $zero for compact // branches. // FIXME: Certain atomic sequences on mips64 generate 32bit references to // Mips::ZERO, which is incorrect. This test should be updated to use // Subtarget.getABI().GetZeroReg() when those atomic sequences and others // are fixed. int ZeroOperandPosition = -1; bool BranchWithZeroOperand = false; if (I->isBranch() && !I->isPseudo()) { auto TRI = I->getParent()->getParent()->getSubtarget().getRegisterInfo(); ZeroOperandPosition = I->findRegisterUseOperandIdx(Mips::ZERO, false, TRI); BranchWithZeroOperand = ZeroOperandPosition != -1; } if (BranchWithZeroOperand) { switch (NewOpc) { case Mips::BEQC: NewOpc = Mips::BEQZC; break; case Mips::BNEC: NewOpc = Mips::BNEZC; break; case Mips::BGEC: NewOpc = Mips::BGEZC; break; case Mips::BLTC: NewOpc = Mips::BLTZC; break; case Mips::BEQC64: NewOpc = Mips::BEQZC64; break; case Mips::BNEC64: NewOpc = Mips::BNEZC64; break; } } MIB = BuildMI(*I->getParent(), I, I->getDebugLoc(), get(NewOpc)); // For MIPSR6 JI*C requires an immediate 0 as an operand, JIALC(64) an // immediate 0 as an operand and requires the removal of it's %RA<imp-def> // implicit operand as copying the implicit operations of the instructio we're // looking at will give us the correct flags. if (NewOpc == Mips::JIC || NewOpc == Mips::JIALC || NewOpc == Mips::JIC64 || NewOpc == Mips::JIALC64) { if (NewOpc == Mips::JIALC || NewOpc == Mips::JIALC64) MIB->RemoveOperand(0); for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) { MIB.add(I->getOperand(J)); } MIB.addImm(0); } else { for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) { if (BranchWithZeroOperand && (unsigned)ZeroOperandPosition == J) continue; MIB.add(I->getOperand(J)); } } MIB.copyImplicitOps(*I); MIB.setMemRefs(I->memoperands_begin(), I->memoperands_end()); return MIB; }
bool Mos6502InstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl<MachineOperand> &Cond, bool AllowModify) const { MachineBasicBlock::iterator I = MBB.end(); MachineBasicBlock::iterator UnCondBrIter = MBB.end(); while (I != MBB.begin()) { --I; if (I->isDebugValue()) continue; // When we see a non-terminator, we are done. if (!isUnpredicatedTerminator(I)) break; // Terminator is not a branch. if (!I->isBranch()) return true; // Handle Unconditional branches. if (I->getOpcode() == M6502::BA) { UnCondBrIter = I; if (!AllowModify) { TBB = I->getOperand(0).getMBB(); continue; } while (std::next(I) != MBB.end()) std::next(I)->eraseFromParent(); Cond.clear(); FBB = nullptr; if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) { TBB = nullptr; I->eraseFromParent(); I = MBB.end(); UnCondBrIter = MBB.end(); continue; } TBB = I->getOperand(0).getMBB(); continue; } unsigned Opcode = I->getOpcode(); if (Opcode != M6502::BCOND && Opcode != M6502::FBCOND) return true; // Unknown Opcode. SPCC::CondCodes BranchCode = (SPCC::CondCodes)I->getOperand(1).getImm(); if (Cond.empty()) { MachineBasicBlock *TargetBB = I->getOperand(0).getMBB(); if (AllowModify && UnCondBrIter != MBB.end() && MBB.isLayoutSuccessor(TargetBB)) { // Transform the code // // brCC L1 // ba L2 // L1: // .. // L2: // // into // // brnCC L2 // L1: // ... // L2: // BranchCode = GetOppositeBranchCondition(BranchCode); MachineBasicBlock::iterator OldInst = I; BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(Opcode)) .addMBB(UnCondBrIter->getOperand(0).getMBB()).addImm(BranchCode); BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(M6502::BA)) .addMBB(TargetBB); OldInst->eraseFromParent(); UnCondBrIter->eraseFromParent(); UnCondBrIter = MBB.end(); I = MBB.end(); continue; } FBB = TBB; TBB = I->getOperand(0).getMBB(); Cond.push_back(MachineOperand::CreateImm(BranchCode)); continue; } // FIXME: Handle subsequent conditional branches. // For now, we can't handle multiple conditional branches. return true; } return false; }
bool PatmosDelaySlotKiller::killDelaySlots(MachineBasicBlock &MBB) { bool Changed = false; DEBUG( dbgs() << "Killing slots in BB#" << MBB.getNumber() << " (" << MBB.getFullName() << ")\n" ); // consider the basic block from top to bottom for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) { // Control-flow instructions ("proper" delay slots) if (I->hasDelaySlot()) { assert( ( I->isCall() || I->isReturn() || I->isBranch() ) && "Unexpected instruction with delay slot."); MachineBasicBlock::instr_iterator MI = *I; if (I->isBundle()) { ++MI; } unsigned Opcode = MI->getOpcode(); if (Opcode == Patmos::BR || Opcode == Patmos::BRu || Opcode == Patmos::BRR || Opcode == Patmos::BRRu || Opcode == Patmos::BRT || Opcode == Patmos::BRTu || Opcode == Patmos::BRCF || Opcode == Patmos::BRCFu || Opcode == Patmos::BRCFR || Opcode == Patmos::BRCFRu || Opcode == Patmos::BRCFT || Opcode == Patmos::BRCFTu || Opcode == Patmos::CALL || Opcode == Patmos::CALLR || Opcode == Patmos::RET || Opcode == Patmos::XRET) { bool onlyNops = true; unsigned maxCount = TM.getSubtargetImpl()->getDelaySlotCycles(&*I); unsigned count = 0; for (MachineBasicBlock::iterator K = llvm::next(I), E = MBB.end(); K != E && count < maxCount; ++K, ++count) { TII->skipPseudos(MBB, K); if (K->getOpcode() != Patmos::NOP) { onlyNops = false; } } if (onlyNops) { unsigned NewOpcode = 0; switch(Opcode) { case Patmos::BR: NewOpcode = Patmos::BRND; break; case Patmos::BRu: NewOpcode = Patmos::BRNDu; break; case Patmos::BRR: NewOpcode = Patmos::BRRND; break; case Patmos::BRRu: NewOpcode = Patmos::BRRNDu; break; case Patmos::BRT: NewOpcode = Patmos::BRTND; break; case Patmos::BRTu: NewOpcode = Patmos::BRTNDu; break; case Patmos::BRCF: NewOpcode = Patmos::BRCFND; break; case Patmos::BRCFu: NewOpcode = Patmos::BRCFNDu; break; case Patmos::BRCFR: NewOpcode = Patmos::BRCFRND; break; case Patmos::BRCFRu: NewOpcode = Patmos::BRCFRNDu; break; case Patmos::BRCFT: NewOpcode = Patmos::BRCFTND; break; case Patmos::BRCFTu: NewOpcode = Patmos::BRCFTNDu; break; case Patmos::CALL: NewOpcode = Patmos::CALLND; break; case Patmos::CALLR: NewOpcode = Patmos::CALLRND; break; case Patmos::RET: NewOpcode = Patmos::RETND; break; case Patmos::XRET: NewOpcode = Patmos::XRETND; break; } const MCInstrDesc &nonDelayed = TII->get(NewOpcode); MI->setDesc(nonDelayed); unsigned killCount = 0; MachineBasicBlock::iterator K = llvm::next(I); for (MachineBasicBlock::iterator E = MBB.end(); K != E && killCount < count; ++K, ++killCount) { TII->skipPseudos(MBB, K); KilledSlots++; } MBB.erase(llvm::next(I), K); } } Changed = true; // pass result } } return Changed; }
unsigned PatmosInstrInfo::moveUp(MachineBasicBlock &MBB, MachineBasicBlock::iterator &II, unsigned Cycles) const { // TODO We assume here that we do not have instructions which must be scheduled // *within* a certain amount of cycles, except for branches (i.e., we // do not emit overlapping pipelined MULs). Otherwise we would need to // check if we violate any latency constraints when inserting an instruction // Note: We assume that the instruction has no dependencies on previous // instructions within the given number of cycles. If we would check for this, // this would become a complete scheduler. // We might move an instruction // 1) outside of delay slots -> always possible // 2) into a delay slot -> optional, must add predicate and replace NOP or // be bundled; we do not move other instructions around // 3) over a branch -> always possible if not predicated, but only until next // delay slot and if not moved into a delay slot if (II->isBundled()) { // TODO moving bundled instructions is not yet supported. return Cycles; } MachineBasicBlock::iterator J = II; // determine start of first delay slot above the instruction int nonDelayed = findPrevDelaySlotEnd(MBB, J, Cycles); // Check if the instruction is inside a delay slot if (nonDelayed < 0) { // do not move it out of the delay slot // TODO we could move it, and insert a NOP instead.. return Cycles; } bool isBranch = II->isBranch(); bool isCFLInstr = isBranch || II->isCall() || II->isReturn(); if (nonDelayed < (int)Cycles && J->isBranch() && !isPredicated(&*II) && isPredicated(&*J) && (!isCFLInstr || (isBranch && PST.allowBranchInsideCFLDelaySots()) )) { // J points to the branch instruction unsigned delayed = nonDelayed + PST.getDelaySlotCycles(&*J) + 1; // Load the predicate of the branch // We assume here that a bundle only contains at most one branch, // that this instruction is the first instruction in the bundle, and // that the branch is actually predicated. // TODO add a check for this! SmallVector<MachineOperand,4> Pred; const MachineInstr *BR = getFirstMI(&*J); assert(BR->isBranch() && "Branch is not in the first slot"); getPredicateOperands(BR, Pred); assert(Pred.size() >= 2 && "Branch instruction not predicated"); // determine if instruction might be moved over the delay slot if (delayed <= Cycles) { // TODO We only move the instruction at most one cycle above the branch. // We could move it further up, but then we need to check where the // predicate is defined. MachineBasicBlock::iterator JJ = J; if (findPrevDelaySlotEnd(MBB, JJ, 0) >= 0) { // Move the instruction up and predicate it II = MBB.insert(J, MBB.remove(II)); PredicateInstruction(&*II, Pred); NegatePredicate(&*II); return Cycles - delayed; } } // if not, check if we can move it into the delay slot MachineBasicBlock::iterator dst = J; // Going down from the branch until the first possible slot, checking // that the predicate is not redefined. // Note that we are not inserting the instruction, but replacing an // instruction, i.e., we move one instruction less over II than in the // other cases. while ((int)delayed > nonDelayed) { delayed--; if (delayed <= Cycles && moveTo(MBB, dst, II, &Pred, true)) { return Cycles - delayed; } // TODO check if this also finds a MTS $S0 !! if (dst->definesRegister(Pred[0].getReg(), &getRegisterInfo())) { break; } dst = nextNonPseudo(MBB, dst); } } if (nonDelayed > 0) { // we are staying below a delay slot, just move the instruction up J = II; recedeCycles(MBB, J, nonDelayed); II = MBB.insert(J, MBB.remove(II)); return Cycles - nonDelayed; } return Cycles; }
bool PatmosInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl<MachineOperand> &Cond, bool AllowModify) const { // If the client does not want to only simplify the branch, // the output arguments must be initialized. assert(AllowModify || (TBB==0 && FBB==0 && Cond.size()==0)); // Start from the bottom of the block and work up, examining the // terminator instructions. MachineBasicBlock::iterator I = MBB.end(); while (I != MBB.begin()) { --I; if (I->isDebugValue() || I->isPseudo()) continue; // Working from the bottom, when we see a non-terminator inst, we're done. if (!isUnpredicatedTerminator(I)) break; // A terminator that isn't a (direct) branch can't easily be handled // by this analysis. if (!I->isBranch() || I->isIndirectBranch()) return true; // Handle Unconditional branches if (!isPredicated(I)) { // fix instruction, if necessary if (!I->isUnconditionalBranch()) fixOpcodeForGuard(I); // TBB is used to indicate the unconditional destination. TBB = getBranchTarget(I); if (AllowModify) { // If the block has any instructions after an uncond branch, delete them. while (llvm::next(I) != MBB.end()) llvm::next(I)->eraseFromParent(); } continue; } // Handle conditional branches if (isPredicated(I)) { // fix instruction, if necessary if (!I->isConditionalBranch()) fixOpcodeForGuard(I); // we only treat the first conditional branch in a row if (Cond.size() > 0) return true; // Get branch condition int i = I->findFirstPredOperandIdx(); assert(i != -1 ); Cond.push_back(I->getOperand(i)); // reg Cond.push_back(I->getOperand(i+1)); // flag // We've processed an unconditional branch before, // the unconditional target goes to FBB now if (TBB) FBB = TBB; // target of conditional branch goes to TBB TBB = getBranchTarget(I); continue; } // we explicitly leave or continue. llvm_unreachable("AnalyzeBranch error."); } // left the loop? then we're done return false; }
bool DCPU16InstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl<MachineOperand> &Cond, bool AllowModify) const { // Start from the bottom of the block and work up, examining the // terminator instructions. MachineBasicBlock::iterator I = MBB.end(); while (I != MBB.begin()) { --I; if (I->isDebugValue()) continue; // Working from the bottom, when we see a non-terminator // instruction, we're done. if (!isUnpredicatedTerminator(I)) break; // A terminator that isn't a branch can't easily be handled // by this analysis. if (!I->isBranch()) return true; // Cannot handle indirect branches. if (I->getOpcode() == DCPU16::Br || I->getOpcode() == DCPU16::Bm) return true; // Handle unconditional branches. if (I->getOpcode() == DCPU16::JMP) { if (!AllowModify) { TBB = I->getOperand(0).getMBB(); continue; } // If the block has any instructions after a JMP, delete them. while (llvm::next(I) != MBB.end()) llvm::next(I)->eraseFromParent(); Cond.clear(); FBB = 0; // Delete the JMP if it's equivalent to a fall-through. if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) { TBB = 0; I->eraseFromParent(); I = MBB.end(); continue; } // TBB is used to indicate the unconditinal destination. TBB = I->getOperand(0).getMBB(); continue; } // Handle conditional branches. assert(isBR_CC(I->getOpcode()) && "Invalid conditional branch"); DCPU16CC::CondCodes BranchCode = static_cast<DCPU16CC::CondCodes>(I->getOperand(0).getImm()); if (BranchCode == DCPU16CC::COND_INVALID) return true; // Can't handle weird stuff. MachineOperand LHS = I->getOperand(1); MachineOperand RHS = I->getOperand(2); // Working from the bottom, handle the first conditional branch. if (Cond.empty()) { FBB = TBB; TBB = I->getOperand(3).getMBB(); Cond.push_back(MachineOperand::CreateImm(I->getOpcode())); Cond.push_back(MachineOperand::CreateImm(BranchCode)); Cond.push_back(LHS); Cond.push_back(RHS); continue; } assert(Cond.size() == 4); assert(TBB); // Is it a complex CC? DCPU16CC::CondCodes complexCC; if ((BranchCode == DCPU16CC::COND_E) && AcceptsAdditionalEqualityCheck((DCPU16CC::CondCodes) Cond[1].getImm(), &complexCC) && (TBB == I->getOperand(3).getMBB()) // This should actually check for equality but that's just too much code... && (((Cond[2].getType() == LHS.getType()) && (Cond[3].getType() == RHS.getType())) || ((Cond[2].getType() == RHS.getType()) && (Cond[3].getType() == LHS.getType())))) { Cond[1] = MachineOperand::CreateImm(complexCC); } break; } return false; }