MachineFunction* Disassembler::disassemble(unsigned Address) { MachineFunction *MF = getOrCreateFunction(Address); if (MF->size() == 0) { // Decode basic blocks until end of function unsigned Size = 0; MachineBasicBlock *MBB; do { unsigned MBBSize = 0; MBB = decodeBasicBlock(Address+Size, MF, MBBSize); Size += MBBSize; } while (Address+Size < CurSectionEnd && MBB->size() > 0 && !(MBB->instr_rbegin()->isReturn())); if (Address+Size < CurSectionEnd && MBB->size() > 0) { // FIXME: This can be shoved into the loop above to improve performance MachineFunction *NextMF = getNearestFunction(getDebugOffset(MBB->instr_rbegin()->getDebugLoc())); if (NextMF != NULL) { Functions.erase( getDebugOffset(NextMF->begin()->instr_begin()->getDebugLoc())); } } } Functions[Address] = MF; return MF; }
void MIRPrinter::convert(ModuleSlotTracker &MST, yaml::MachineBasicBlock &YamlMBB, const MachineBasicBlock &MBB) { assert(MBB.getNumber() >= 0 && "Invalid MBB number"); YamlMBB.ID = (unsigned)MBB.getNumber(); // TODO: Serialize unnamed BB references. if (const auto *BB = MBB.getBasicBlock()) YamlMBB.Name.Value = BB->hasName() ? BB->getName() : "<unnamed bb>"; else YamlMBB.Name.Value = ""; YamlMBB.Alignment = MBB.getAlignment(); YamlMBB.AddressTaken = MBB.hasAddressTaken(); YamlMBB.IsLandingPad = MBB.isLandingPad(); for (const auto *SuccMBB : MBB.successors()) { std::string Str; raw_string_ostream StrOS(Str); MIPrinter(StrOS, MST, RegisterMaskIds).printMBBReference(*SuccMBB); YamlMBB.Successors.push_back(StrOS.str()); } // Print the machine instructions. YamlMBB.Instructions.reserve(MBB.size()); std::string Str; for (const auto &MI : MBB) { raw_string_ostream StrOS(Str); MIPrinter(StrOS, MST, RegisterMaskIds).print(MI); YamlMBB.Instructions.push_back(StrOS.str()); Str.clear(); } }
MachineBasicBlock* Disassembler::decodeBasicBlock(unsigned Address, MachineFunction* MF, unsigned &Size) { assert(MF && "Unable to decode basic block without Machine Function!"); uint64_t MFLoc = MF->getFunctionNumber(); // FIXME: Horrible, horrible hack uint64_t Off = Address-MFLoc; std::stringstream MBBName; MBBName << MF->getName().str() << "+" << Off; // Dummy holds the name. BasicBlock *Dummy = BasicBlock::Create(*MC->getContext(), MBBName.str()); MachineBasicBlock *MBB = MF->CreateMachineBasicBlock(Dummy); MF->push_back(MBB); // NOTE: Might also need SectAddr... Size = 0; while (Address+Size < (unsigned) CurSectionEnd) { unsigned CurAddr = Address+Size; Size += std::max(unsigned(1), decodeInstruction(CurAddr, MBB)); MachineInstr* MI = NULL; if (MBB->size() != 0) { MI = &(*MBB->instr_rbegin()); MachineInstructions[CurAddr] = MI; } if (MI != NULL && MI->isTerminator()) { break; } } if (Address >= CurSectionEnd) { printInfo("Reached end of current section!"); } return MBB; }
/// runOnMachineFunction - Loop over all of the basic blocks, inserting /// NOOP instructions before early exits. bool PadShortFunc::runOnMachineFunction(MachineFunction &MF) { const AttributeSet &FnAttrs = MF.getFunction()->getAttributes(); if (FnAttrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::OptimizeForSize) || FnAttrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::MinSize)) { return false; } TM = &MF.getTarget(); if (!TM->getSubtarget<X86Subtarget>().padShortFunctions()) return false; TII = TM->getInstrInfo(); // Search through basic blocks and mark the ones that have early returns ReturnBBs.clear(); VisitedBBs.clear(); findReturns(MF.begin()); bool MadeChange = false; MachineBasicBlock *MBB; unsigned int Cycles = 0; // Pad the identified basic blocks with NOOPs for (DenseMap<MachineBasicBlock*, unsigned int>::iterator I = ReturnBBs.begin(); I != ReturnBBs.end(); ++I) { MBB = I->first; Cycles = I->second; if (Cycles < Threshold) { // BB ends in a return. Skip over any DBG_VALUE instructions // trailing the terminator. assert(MBB->size() > 0 && "Basic block should contain at least a RET but is empty"); MachineBasicBlock::iterator ReturnLoc = --MBB->end(); while (ReturnLoc->isDebugValue()) --ReturnLoc; assert(ReturnLoc->isReturn() && !ReturnLoc->isCall() && "Basic block does not end with RET"); addPadding(MBB, ReturnLoc, Threshold - Cycles); NumBBsPadded++; MadeChange = true; } } return MadeChange; }
void MIRPrinter::convert(ModuleSlotTracker &MST, yaml::MachineBasicBlock &YamlMBB, const MachineBasicBlock &MBB) { assert(MBB.getNumber() >= 0 && "Invalid MBB number"); YamlMBB.ID = (unsigned)MBB.getNumber(); if (const auto *BB = MBB.getBasicBlock()) { if (BB->hasName()) { YamlMBB.Name.Value = BB->getName(); } else { int Slot = MST.getLocalSlot(BB); if (Slot == -1) YamlMBB.IRBlock.Value = "<badref>"; else YamlMBB.IRBlock.Value = (Twine("%ir-block.") + Twine(Slot)).str(); } } YamlMBB.Alignment = MBB.getAlignment(); YamlMBB.AddressTaken = MBB.hasAddressTaken(); YamlMBB.IsLandingPad = MBB.isLandingPad(); for (const auto *SuccMBB : MBB.successors()) { std::string Str; raw_string_ostream StrOS(Str); MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping) .printMBBReference(*SuccMBB); YamlMBB.Successors.push_back(StrOS.str()); } if (MBB.hasSuccessorWeights()) { for (auto I = MBB.succ_begin(), E = MBB.succ_end(); I != E; ++I) YamlMBB.SuccessorWeights.push_back( yaml::UnsignedValue(MBB.getSuccWeight(I))); } // Print the live in registers. const auto *TRI = MBB.getParent()->getSubtarget().getRegisterInfo(); assert(TRI && "Expected target register info"); for (auto I = MBB.livein_begin(), E = MBB.livein_end(); I != E; ++I) { std::string Str; raw_string_ostream StrOS(Str); printReg(*I, StrOS, TRI); YamlMBB.LiveIns.push_back(StrOS.str()); } // Print the machine instructions. YamlMBB.Instructions.reserve(MBB.size()); std::string Str; for (const auto &MI : MBB) { raw_string_ostream StrOS(Str); MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping).print(MI); YamlMBB.Instructions.push_back(StrOS.str()); Str.clear(); } }
void MIRPrinter::convert(yaml::MachineBasicBlock &YamlMBB, const MachineBasicBlock &MBB) { // TODO: Serialize unnamed BB references. if (const auto *BB = MBB.getBasicBlock()) YamlMBB.Name = BB->hasName() ? BB->getName() : "<unnamed bb>"; else YamlMBB.Name = ""; YamlMBB.Alignment = MBB.getAlignment(); YamlMBB.AddressTaken = MBB.hasAddressTaken(); YamlMBB.IsLandingPad = MBB.isLandingPad(); // Print the machine instructions. YamlMBB.Instructions.reserve(MBB.size()); std::string Str; for (const auto &MI : MBB) { raw_string_ostream StrOS(Str); MIPrinter(StrOS).print(MI); YamlMBB.Instructions.push_back(StrOS.str()); Str.clear(); } }
void MipsAsmPrinter::EmitBasicBlockEnd(const MachineBasicBlock &MBB) { MipsTargetStreamer &TS = getTargetStreamer(); if (MBB.size() == 0) TS.emitDirectiveInsn(); }
/// TailDuplicateBlocks - Look for small blocks that are unconditionally /// branched to and do not fall through. Tail-duplicate their instructions /// into their predecessors to eliminate (dynamic) branches. bool TailDuplicatePass::TailDuplicateBlocks(MachineFunction &MF) { bool MadeChange = false; if (PreRegAlloc && TailDupVerify) { DEBUG(dbgs() << "\n*** Before tail-duplicating\n"); VerifyPHIs(MF, true); } SmallVector<MachineInstr*, 8> NewPHIs; MachineSSAUpdater SSAUpdate(MF, &NewPHIs); for (MachineFunction::iterator I = ++MF.begin(), E = MF.end(); I != E; ) { MachineBasicBlock *MBB = I++; if (NumTails == TailDupLimit) break; // Save the successors list. SmallSetVector<MachineBasicBlock*, 8> Succs(MBB->succ_begin(), MBB->succ_end()); SmallVector<MachineBasicBlock*, 8> TDBBs; SmallVector<MachineInstr*, 16> Copies; if (TailDuplicate(MBB, MF, TDBBs, Copies)) { ++NumTails; // TailBB's immediate successors are now successors of those predecessors // which duplicated TailBB. Add the predecessors as sources to the PHI // instructions. bool isDead = MBB->pred_empty(); if (PreRegAlloc) UpdateSuccessorsPHIs(MBB, isDead, TDBBs, Succs); // If it is dead, remove it. if (isDead) { NumInstrDups -= MBB->size(); RemoveDeadBlock(MBB); ++NumDeadBlocks; } // Update SSA form. if (!SSAUpdateVRs.empty()) { for (unsigned i = 0, e = SSAUpdateVRs.size(); i != e; ++i) { unsigned VReg = SSAUpdateVRs[i]; SSAUpdate.Initialize(VReg); // If the original definition is still around, add it as an available // value. MachineInstr *DefMI = MRI->getVRegDef(VReg); MachineBasicBlock *DefBB = 0; if (DefMI) { DefBB = DefMI->getParent(); SSAUpdate.AddAvailableValue(DefBB, VReg); } // Add the new vregs as available values. DenseMap<unsigned, AvailableValsTy>::iterator LI = SSAUpdateVals.find(VReg); for (unsigned j = 0, ee = LI->second.size(); j != ee; ++j) { MachineBasicBlock *SrcBB = LI->second[j].first; unsigned SrcReg = LI->second[j].second; SSAUpdate.AddAvailableValue(SrcBB, SrcReg); } // Rewrite uses that are outside of the original def's block. MachineRegisterInfo::use_iterator UI = MRI->use_begin(VReg); while (UI != MRI->use_end()) { MachineOperand &UseMO = UI.getOperand(); MachineInstr *UseMI = &*UI; ++UI; if (UseMI->isDebugValue()) { // SSAUpdate can replace the use with an undef. That creates // a debug instruction that is a kill. // FIXME: Should it SSAUpdate job to delete debug instructions // instead of replacing the use with undef? UseMI->eraseFromParent(); continue; } if (UseMI->getParent() == DefBB && !UseMI->isPHI()) continue; SSAUpdate.RewriteUse(UseMO); } } SSAUpdateVRs.clear(); SSAUpdateVals.clear(); } // Eliminate some of the copies inserted by tail duplication to maintain // SSA form. for (unsigned i = 0, e = Copies.size(); i != e; ++i) { MachineInstr *Copy = Copies[i]; if (!Copy->isCopy()) continue; unsigned Dst = Copy->getOperand(0).getReg(); unsigned Src = Copy->getOperand(1).getReg(); MachineRegisterInfo::use_iterator UI = MRI->use_begin(Src); if (++UI == MRI->use_end()) { // Copy is the only use. Do trivial copy propagation here. MRI->replaceRegWith(Dst, Src); Copy->eraseFromParent(); } } if (PreRegAlloc && TailDupVerify) VerifyPHIs(MF, false); MadeChange = true; } } NumAddedPHIs += NewPHIs.size(); return MadeChange; }
// Expand branch instructions to long branches. // TODO: This function has to be fixed for beqz16 and bnez16, because it // currently assumes that all branches have 16-bit offsets, and will produce // wrong code if branches whose allowed offsets are [-128, -126, ..., 126] // are present. void MipsLongBranch::expandToLongBranch(MBBInfo &I) { MachineBasicBlock::iterator Pos; MachineBasicBlock *MBB = I.Br->getParent(), *TgtMBB = getTargetMBB(*I.Br); DebugLoc DL = I.Br->getDebugLoc(); const BasicBlock *BB = MBB->getBasicBlock(); MachineFunction::iterator FallThroughMBB = ++MachineFunction::iterator(MBB); MachineBasicBlock *LongBrMBB = MF->CreateMachineBasicBlock(BB); const MipsSubtarget &Subtarget = static_cast<const MipsSubtarget &>(MF->getSubtarget()); const MipsInstrInfo *TII = static_cast<const MipsInstrInfo *>(Subtarget.getInstrInfo()); MF->insert(FallThroughMBB, LongBrMBB); MBB->replaceSuccessor(TgtMBB, LongBrMBB); if (IsPIC) { MachineBasicBlock *BalTgtMBB = MF->CreateMachineBasicBlock(BB); MF->insert(FallThroughMBB, BalTgtMBB); LongBrMBB->addSuccessor(BalTgtMBB); BalTgtMBB->addSuccessor(TgtMBB); // We must select between the MIPS32r6/MIPS64r6 BAL (which is a normal // instruction) and the pre-MIPS32r6/MIPS64r6 definition (which is an // pseudo-instruction wrapping BGEZAL). unsigned BalOp = Subtarget.hasMips32r6() ? Mips::BAL : Mips::BAL_BR; if (!ABI.IsN64()) { // $longbr: // addiu $sp, $sp, -8 // sw $ra, 0($sp) // lui $at, %hi($tgt - $baltgt) // bal $baltgt // addiu $at, $at, %lo($tgt - $baltgt) // $baltgt: // addu $at, $ra, $at // lw $ra, 0($sp) // jr $at // addiu $sp, $sp, 8 // $fallthrough: // Pos = LongBrMBB->begin(); BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::SP) .addReg(Mips::SP).addImm(-8); BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::SW)).addReg(Mips::RA) .addReg(Mips::SP).addImm(0); // LUi and ADDiu instructions create 32-bit offset of the target basic // block from the target of BAL instruction. We cannot use immediate // value for this offset because it cannot be determined accurately when // the program has inline assembly statements. We therefore use the // relocation expressions %hi($tgt-$baltgt) and %lo($tgt-$baltgt) which // are resolved during the fixup, so the values will always be correct. // // Since we cannot create %hi($tgt-$baltgt) and %lo($tgt-$baltgt) // expressions at this point (it is possible only at the MC layer), // we replace LUi and ADDiu with pseudo instructions // LONG_BRANCH_LUi and LONG_BRANCH_ADDiu, and add both basic // blocks as operands to these instructions. When lowering these pseudo // instructions to LUi and ADDiu in the MC layer, we will create // %hi($tgt-$baltgt) and %lo($tgt-$baltgt) expressions and add them as // operands to lowered instructions. BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_LUi), Mips::AT) .addMBB(TgtMBB).addMBB(BalTgtMBB); MIBundleBuilder(*LongBrMBB, Pos) .append(BuildMI(*MF, DL, TII->get(BalOp)).addMBB(BalTgtMBB)) .append(BuildMI(*MF, DL, TII->get(Mips::LONG_BRANCH_ADDiu), Mips::AT) .addReg(Mips::AT) .addMBB(TgtMBB) .addMBB(BalTgtMBB)); Pos = BalTgtMBB->begin(); BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDu), Mips::AT) .addReg(Mips::RA).addReg(Mips::AT); BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LW), Mips::RA) .addReg(Mips::SP).addImm(0); if (!Subtarget.isTargetNaCl()) { MIBundleBuilder(*BalTgtMBB, Pos) .append(BuildMI(*MF, DL, TII->get(Mips::JR)).addReg(Mips::AT)) .append(BuildMI(*MF, DL, TII->get(Mips::ADDiu), Mips::SP) .addReg(Mips::SP).addImm(8)); } else { // In NaCl, modifying the sp is not allowed in branch delay slot. BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::SP) .addReg(Mips::SP).addImm(8); MIBundleBuilder(*BalTgtMBB, Pos) .append(BuildMI(*MF, DL, TII->get(Mips::JR)).addReg(Mips::AT)) .append(BuildMI(*MF, DL, TII->get(Mips::NOP))); // Bundle-align the target of indirect branch JR. TgtMBB->setAlignment(MIPS_NACL_BUNDLE_ALIGN); } } else { // $longbr: // daddiu $sp, $sp, -16 // sd $ra, 0($sp) // daddiu $at, $zero, %hi($tgt - $baltgt) // dsll $at, $at, 16 // bal $baltgt // daddiu $at, $at, %lo($tgt - $baltgt) // $baltgt: // daddu $at, $ra, $at // ld $ra, 0($sp) // jr64 $at // daddiu $sp, $sp, 16 // $fallthrough: // // We assume the branch is within-function, and that offset is within // +/- 2GB. High 32 bits will therefore always be zero. // Note that this will work even if the offset is negative, because // of the +1 modification that's added in that case. For example, if the // offset is -1MB (0xFFFFFFFFFFF00000), the computation for %higher is // // 0xFFFFFFFFFFF00000 + 0x80008000 = 0x000000007FF08000 // // and the bits [47:32] are zero. For %highest // // 0xFFFFFFFFFFF00000 + 0x800080008000 = 0x000080007FF08000 // // and the bits [63:48] are zero. Pos = LongBrMBB->begin(); BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::DADDiu), Mips::SP_64) .addReg(Mips::SP_64).addImm(-16); BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::SD)).addReg(Mips::RA_64) .addReg(Mips::SP_64).addImm(0); BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_DADDiu), Mips::AT_64).addReg(Mips::ZERO_64) .addMBB(TgtMBB, MipsII::MO_ABS_HI).addMBB(BalTgtMBB); BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::DSLL), Mips::AT_64) .addReg(Mips::AT_64).addImm(16); MIBundleBuilder(*LongBrMBB, Pos) .append(BuildMI(*MF, DL, TII->get(BalOp)).addMBB(BalTgtMBB)) .append( BuildMI(*MF, DL, TII->get(Mips::LONG_BRANCH_DADDiu), Mips::AT_64) .addReg(Mips::AT_64) .addMBB(TgtMBB, MipsII::MO_ABS_LO) .addMBB(BalTgtMBB)); Pos = BalTgtMBB->begin(); BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DADDu), Mips::AT_64) .addReg(Mips::RA_64).addReg(Mips::AT_64); BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LD), Mips::RA_64) .addReg(Mips::SP_64).addImm(0); MIBundleBuilder(*BalTgtMBB, Pos) .append(BuildMI(*MF, DL, TII->get(Mips::JR64)).addReg(Mips::AT_64)) .append(BuildMI(*MF, DL, TII->get(Mips::DADDiu), Mips::SP_64) .addReg(Mips::SP_64).addImm(16)); } assert(LongBrMBB->size() + BalTgtMBB->size() == LongBranchSeqSize); } else { // $longbr: // j $tgt // nop // $fallthrough: // Pos = LongBrMBB->begin(); LongBrMBB->addSuccessor(TgtMBB); MIBundleBuilder(*LongBrMBB, Pos) .append(BuildMI(*MF, DL, TII->get(Mips::J)).addMBB(TgtMBB)) .append(BuildMI(*MF, DL, TII->get(Mips::NOP))); assert(LongBrMBB->size() == LongBranchSeqSize); } if (I.Br->isUnconditionalBranch()) { // Change branch destination. assert(I.Br->getDesc().getNumOperands() == 1); I.Br->RemoveOperand(0); I.Br->addOperand(MachineOperand::CreateMBB(LongBrMBB)); } else // Change branch destination and reverse condition. replaceBranch(*MBB, I.Br, DL, &*FallThroughMBB); }
unsigned SPUInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, const SmallVectorImpl<MachineOperand> &Cond, DebugLoc DL) const { // Shouldn't be a fall through. assert(TBB && "InsertBranch must not be told to insert a fallthrough"); assert((Cond.size() == 2 || Cond.size() == 0) && "SPU branch conditions have two components!"); MachineInstrBuilder MIB; //TODO: make a more accurate algorithm. bool haveHBR = MBB.size()>8; removeHBR(MBB); MCSymbol *branchLabel = MBB.getParent()->getContext().CreateTempSymbol(); // Add a label just before the branch if (haveHBR) MIB = BuildMI(&MBB, DL, get(SPU::HBR_LABEL)).addSym(branchLabel); // One-way branch. if (FBB == 0) { if (Cond.empty()) { // Unconditional branch MIB = BuildMI(&MBB, DL, get(SPU::BR)); MIB.addMBB(TBB); DEBUG(errs() << "Inserted one-way uncond branch: "); DEBUG((*MIB).dump()); // basic blocks have just one branch so it is safe to add the hint a its if (haveHBR) { MIB = BuildMI( MBB, findHBRPosition(MBB), DL, get(SPU::HBRA)); MIB.addSym(branchLabel); MIB.addMBB(TBB); } } else { // Conditional branch MIB = BuildMI(&MBB, DL, get(Cond[0].getImm())); MIB.addReg(Cond[1].getReg()).addMBB(TBB); if (haveHBR) { MIB = BuildMI(MBB, findHBRPosition(MBB), DL, get(SPU::HBRA)); MIB.addSym(branchLabel); MIB.addMBB(TBB); } DEBUG(errs() << "Inserted one-way cond branch: "); DEBUG((*MIB).dump()); } return 1; } else { MIB = BuildMI(&MBB, DL, get(Cond[0].getImm())); MachineInstrBuilder MIB2 = BuildMI(&MBB, DL, get(SPU::BR)); // Two-way Conditional Branch. MIB.addReg(Cond[1].getReg()).addMBB(TBB); MIB2.addMBB(FBB); if (haveHBR) { MIB = BuildMI( MBB, findHBRPosition(MBB), DL, get(SPU::HBRA)); MIB.addSym(branchLabel); MIB.addMBB(FBB); } DEBUG(errs() << "Inserted conditional branch: "); DEBUG((*MIB).dump()); DEBUG(errs() << "part 2: "); DEBUG((*MIB2).dump()); return 2; } }
// Expand branch instructions to long branches. void MipsLongBranch::expandToLongBranch(MBBInfo &I) { MachineBasicBlock::iterator Pos; MachineBasicBlock *MBB = I.Br->getParent(), *TgtMBB = getTargetMBB(*I.Br); DebugLoc DL = I.Br->getDebugLoc(); const BasicBlock *BB = MBB->getBasicBlock(); MachineFunction::iterator FallThroughMBB = ++MachineFunction::iterator(MBB); MachineBasicBlock *LongBrMBB = MF->CreateMachineBasicBlock(BB); const MipsInstrInfo *TII = static_cast<const MipsInstrInfo*>(TM.getInstrInfo()); MF->insert(FallThroughMBB, LongBrMBB); MBB->removeSuccessor(TgtMBB); MBB->addSuccessor(LongBrMBB); if (IsPIC) { MachineBasicBlock *BalTgtMBB = MF->CreateMachineBasicBlock(BB); MF->insert(FallThroughMBB, BalTgtMBB); LongBrMBB->addSuccessor(BalTgtMBB); BalTgtMBB->addSuccessor(TgtMBB); int64_t TgtAddress = MBBInfos[TgtMBB->getNumber()].Address; unsigned BalTgtMBBSize = 5; int64_t Offset = TgtAddress - (I.Address + I.Size - BalTgtMBBSize * 4); int64_t Lo = SignExtend64<16>(Offset & 0xffff); int64_t Hi = SignExtend64<16>(((Offset + 0x8000) >> 16) & 0xffff); if (ABI != MipsSubtarget::N64) { // $longbr: // addiu $sp, $sp, -8 // sw $ra, 0($sp) // bal $baltgt // lui $at, %hi($tgt - $baltgt) // $baltgt: // addiu $at, $at, %lo($tgt - $baltgt) // addu $at, $ra, $at // lw $ra, 0($sp) // jr $at // addiu $sp, $sp, 8 // $fallthrough: // Pos = LongBrMBB->begin(); BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::SP) .addReg(Mips::SP).addImm(-8); BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::SW)).addReg(Mips::RA) .addReg(Mips::SP).addImm(0); MIBundleBuilder(*LongBrMBB, Pos) .append(BuildMI(*MF, DL, TII->get(Mips::BAL_BR)).addMBB(BalTgtMBB)) .append(BuildMI(*MF, DL, TII->get(Mips::LUi), Mips::AT).addImm(Hi)); Pos = BalTgtMBB->begin(); BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::AT) .addReg(Mips::AT).addImm(Lo); BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDu), Mips::AT) .addReg(Mips::RA).addReg(Mips::AT); BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LW), Mips::RA) .addReg(Mips::SP).addImm(0); MIBundleBuilder(*BalTgtMBB, Pos) .append(BuildMI(*MF, DL, TII->get(Mips::JR)).addReg(Mips::AT)) .append(BuildMI(*MF, DL, TII->get(Mips::ADDiu), Mips::SP) .addReg(Mips::SP).addImm(8)); } else { // $longbr: // daddiu $sp, $sp, -16 // sd $ra, 0($sp) // lui64 $at, %highest($tgt - $baltgt) // daddiu $at, $at, %higher($tgt - $baltgt) // dsll $at, $at, 16 // daddiu $at, $at, %hi($tgt - $baltgt) // bal $baltgt // dsll $at, $at, 16 // $baltgt: // daddiu $at, $at, %lo($tgt - $baltgt) // daddu $at, $ra, $at // ld $ra, 0($sp) // jr64 $at // daddiu $sp, $sp, 16 // $fallthrough: // int64_t Higher = SignExtend64<16>(((Offset + 0x80008000) >> 32) & 0xffff); int64_t Highest = SignExtend64<16>(((Offset + 0x800080008000LL) >> 48) & 0xffff); Pos = LongBrMBB->begin(); BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::DADDiu), Mips::SP_64) .addReg(Mips::SP_64).addImm(-16); BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::SD)).addReg(Mips::RA_64) .addReg(Mips::SP_64).addImm(0); BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LUi64), Mips::AT_64) .addImm(Highest); BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::DADDiu), Mips::AT_64) .addReg(Mips::AT_64).addImm(Higher); BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::DSLL), Mips::AT_64) .addReg(Mips::AT_64).addImm(16); BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::DADDiu), Mips::AT_64) .addReg(Mips::AT_64).addImm(Hi); MIBundleBuilder(*LongBrMBB, Pos) .append(BuildMI(*MF, DL, TII->get(Mips::BAL_BR)).addMBB(BalTgtMBB)) .append(BuildMI(*MF, DL, TII->get(Mips::DSLL), Mips::AT_64) .addReg(Mips::AT_64).addImm(16)); Pos = BalTgtMBB->begin(); BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DADDiu), Mips::AT_64) .addReg(Mips::AT_64).addImm(Lo); BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DADDu), Mips::AT_64) .addReg(Mips::RA_64).addReg(Mips::AT_64); BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LD), Mips::RA_64) .addReg(Mips::SP_64).addImm(0); MIBundleBuilder(*BalTgtMBB, Pos) .append(BuildMI(*MF, DL, TII->get(Mips::JR64)).addReg(Mips::AT_64)) .append(BuildMI(*MF, DL, TII->get(Mips::DADDiu), Mips::SP_64) .addReg(Mips::SP_64).addImm(16)); } assert(BalTgtMBBSize == BalTgtMBB->size()); assert(LongBrMBB->size() + BalTgtMBBSize == LongBranchSeqSize); } else {
bool PTXInstrInfo:: AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl<MachineOperand> &Cond, bool AllowModify) const { // TODO implement cases when AllowModify is true if (MBB.empty()) return true; MachineBasicBlock::const_iterator iter = MBB.end(); const MachineInstr& instLast1 = *--iter; const MCInstrDesc &desc1 = instLast1.getDesc(); // for special case that MBB has only 1 instruction const bool IsSizeOne = MBB.size() == 1; // if IsSizeOne is true, *--iter and instLast2 are invalid // we put a dummy value in instLast2 and desc2 since they are used const MachineInstr& instLast2 = IsSizeOne ? instLast1 : *--iter; const MCInstrDesc &desc2 = IsSizeOne ? desc1 : instLast2.getDesc(); DEBUG(dbgs() << "\n"); DEBUG(dbgs() << "AnalyzeBranch: opcode: " << instLast1.getOpcode() << "\n"); DEBUG(dbgs() << "AnalyzeBranch: MBB: " << MBB.getName().str() << "\n"); DEBUG(dbgs() << "AnalyzeBranch: TBB: " << TBB << "\n"); DEBUG(dbgs() << "AnalyzeBranch: FBB: " << FBB << "\n"); // this block ends with no branches if (!IsAnyKindOfBranch(instLast1)) { DEBUG(dbgs() << "AnalyzeBranch: ends with no branch\n"); return false; } // this block ends with only an unconditional branch if (desc1.isUnconditionalBranch() && // when IsSizeOne is true, it "absorbs" the evaluation of instLast2 (IsSizeOne || !IsAnyKindOfBranch(instLast2))) { DEBUG(dbgs() << "AnalyzeBranch: ends with only uncond branch\n"); TBB = GetBranchTarget(instLast1); return false; } // this block ends with a conditional branch and // it falls through to a successor block if (desc1.isConditionalBranch() && IsAnySuccessorAlsoLayoutSuccessor(MBB)) { DEBUG(dbgs() << "AnalyzeBranch: ends with cond branch and fall through\n"); TBB = GetBranchTarget(instLast1); int i = instLast1.findFirstPredOperandIdx(); Cond.push_back(instLast1.getOperand(i)); Cond.push_back(instLast1.getOperand(i+1)); return false; } // when IsSizeOne is true, we are done if (IsSizeOne) return true; // this block ends with a conditional branch // followed by an unconditional branch if (desc2.isConditionalBranch() && desc1.isUnconditionalBranch()) { DEBUG(dbgs() << "AnalyzeBranch: ends with cond and uncond branch\n"); TBB = GetBranchTarget(instLast2); FBB = GetBranchTarget(instLast1); int i = instLast2.findFirstPredOperandIdx(); Cond.push_back(instLast2.getOperand(i)); Cond.push_back(instLast2.getOperand(i+1)); return false; } // branch cannot be understood DEBUG(dbgs() << "AnalyzeBranch: cannot be understood\n"); return true; }
// Expand branch instructions to long branches. // TODO: This function has to be fixed for beqz16 and bnez16, because it // currently assumes that all branches have 16-bit offsets, and will produce // wrong code if branches whose allowed offsets are [-128, -126, ..., 126] // are present. void Cpu0LongBranch::expandToLongBranch(MBBInfo &I) { MachineBasicBlock::iterator Pos; MachineBasicBlock *MBB = I.Br->getParent(), *TgtMBB = getTargetMBB(*I.Br); DebugLoc DL = I.Br->getDebugLoc(); const BasicBlock *BB = MBB->getBasicBlock(); MachineFunction::iterator FallThroughMBB = ++MachineFunction::iterator(MBB); MachineBasicBlock *LongBrMBB = MF->CreateMachineBasicBlock(BB); const Cpu0Subtarget &Subtarget = static_cast<const Cpu0Subtarget &>(MF->getSubtarget()); const Cpu0InstrInfo *TII = static_cast<const Cpu0InstrInfo *>(Subtarget.getInstrInfo()); MF->insert(FallThroughMBB, LongBrMBB); MBB->replaceSuccessor(TgtMBB, LongBrMBB); if (IsPIC) { MachineBasicBlock *BalTgtMBB = MF->CreateMachineBasicBlock(BB); MF->insert(FallThroughMBB, BalTgtMBB); LongBrMBB->addSuccessor(BalTgtMBB); BalTgtMBB->addSuccessor(TgtMBB); unsigned BalOp = Cpu0::BAL; // $longbr: // addiu $sp, $sp, -8 // st $lr, 0($sp) // lui $at, %hi($tgt - $baltgt) // addiu $lr, $lr, %lo($tgt - $baltgt) // bal $baltgt // nop // $baltgt: // addu $at, $lr, $at // addiu $sp, $sp, 8 // ld $lr, 0($sp) // jr $at // nop // $fallthrough: // Pos = LongBrMBB->begin(); BuildMI(*LongBrMBB, Pos, DL, TII->get(Cpu0::ADDiu), Cpu0::SP) .addReg(Cpu0::SP).addImm(-8); BuildMI(*LongBrMBB, Pos, DL, TII->get(Cpu0::ST)).addReg(Cpu0::LR) .addReg(Cpu0::SP).addImm(0); // LUi and ADDiu instructions create 32-bit offset of the target basic // block from the target of BAL instruction. We cannot use immediate // value for this offset because it cannot be determined accurately when // the program has inline assembly statements. We therefore use the // relocation expressions %hi($tgt-$baltgt) and %lo($tgt-$baltgt) which // are resolved during the fixup, so the values will always be correct. // // Since we cannot create %hi($tgt-$baltgt) and %lo($tgt-$baltgt) // expressions at this point (it is possible only at the MC layer), // we replace LUi and ADDiu with pseudo instructions // LONG_BRANCH_LUi and LONG_BRANCH_ADDiu, and add both basic // blocks as operands to these instructions. When lowering these pseudo // instructions to LUi and ADDiu in the MC layer, we will create // %hi($tgt-$baltgt) and %lo($tgt-$baltgt) expressions and add them as // operands to lowered instructions. BuildMI(*LongBrMBB, Pos, DL, TII->get(Cpu0::LONG_BRANCH_LUi), Cpu0::AT) .addMBB(TgtMBB).addMBB(BalTgtMBB); BuildMI(*LongBrMBB, Pos, DL, TII->get(Cpu0::LONG_BRANCH_ADDiu), Cpu0::AT) .addReg(Cpu0::AT).addMBB(TgtMBB).addMBB(BalTgtMBB); MIBundleBuilder(*LongBrMBB, Pos) .append(BuildMI(*MF, DL, TII->get(BalOp)).addMBB(BalTgtMBB)); Pos = BalTgtMBB->begin(); BuildMI(*BalTgtMBB, Pos, DL, TII->get(Cpu0::ADDu), Cpu0::AT) .addReg(Cpu0::LR).addReg(Cpu0::AT); BuildMI(*BalTgtMBB, Pos, DL, TII->get(Cpu0::LD), Cpu0::LR) .addReg(Cpu0::SP).addImm(0); BuildMI(*BalTgtMBB, Pos, DL, TII->get(Cpu0::ADDiu), Cpu0::SP) .addReg(Cpu0::SP).addImm(8); MIBundleBuilder(*BalTgtMBB, Pos) .append(BuildMI(*MF, DL, TII->get(Cpu0::JR)).addReg(Cpu0::AT)) .append(BuildMI(*MF, DL, TII->get(Cpu0::NOP))); assert(LongBrMBB->size() + BalTgtMBB->size() == LongBranchSeqSize); } else { // $longbr: // jmp $tgt // nop // $fallthrough: // Pos = LongBrMBB->begin(); LongBrMBB->addSuccessor(TgtMBB); MIBundleBuilder(*LongBrMBB, Pos) .append(BuildMI(*MF, DL, TII->get(Cpu0::JMP)).addMBB(TgtMBB)) .append(BuildMI(*MF, DL, TII->get(Cpu0::NOP))); assert(LongBrMBB->size() == LongBranchSeqSize); } if (I.Br->isUnconditionalBranch()) { // Change branch destination. assert(I.Br->getDesc().getNumOperands() == 1); I.Br->RemoveOperand(0); I.Br->addOperand(MachineOperand::CreateMBB(LongBrMBB)); } else // Change branch destination and reverse condition. replaceBranch(*MBB, I.Br, DL, &*FallThroughMBB); }