// Adjust SP by FrameSize bytes. Save RA, S0, S1 void Mips16InstrInfo::makeFrame(unsigned SP, int64_t FrameSize, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { DebugLoc DL; MachineFunction &MF = *MBB.getParent(); MachineFrameInfo &MFI = MF.getFrameInfo(); const BitVector Reserved = RI.getReservedRegs(MF); bool SaveS2 = Reserved[Mips::S2]; MachineInstrBuilder MIB; unsigned Opc = ((FrameSize <= 128) && !SaveS2)? Mips::Save16:Mips::SaveX16; MIB = BuildMI(MBB, I, DL, get(Opc)); const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); addSaveRestoreRegs(MIB, CSI); if (SaveS2) MIB.addReg(Mips::S2); if (isUInt<11>(FrameSize)) MIB.addImm(FrameSize); else { int Base = 2040; // should create template function like isUInt that // returns largest possible n bit unsigned integer int64_t Remainder = FrameSize - Base; MIB.addImm(Base); if (isInt<16>(-Remainder)) BuildAddiuSpImm(MBB, I, -Remainder); else adjustStackPtrBig(SP, -Remainder, MBB, I, Mips::V0, Mips::V1); } }
MachineInstr * LanaiInstrInfo::optimizeSelect(MachineInstr &MI, SmallPtrSetImpl<MachineInstr *> &SeenMIs, bool PreferFalse) const { assert(MI.getOpcode() == Lanai::SELECT && "unknown select instruction"); MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo(); MachineInstr *DefMI = canFoldIntoSelect(MI.getOperand(1).getReg(), MRI, this); bool Invert = !DefMI; if (!DefMI) DefMI = canFoldIntoSelect(MI.getOperand(2).getReg(), MRI, this); if (!DefMI) return nullptr; // Find new register class to use. MachineOperand FalseReg = MI.getOperand(Invert ? 1 : 2); unsigned DestReg = MI.getOperand(0).getReg(); const TargetRegisterClass *PreviousClass = MRI.getRegClass(FalseReg.getReg()); if (!MRI.constrainRegClass(DestReg, PreviousClass)) return nullptr; // Create a new predicated version of DefMI. MachineInstrBuilder NewMI = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), DefMI->getDesc(), DestReg); // Copy all the DefMI operands, excluding its (null) predicate. const MCInstrDesc &DefDesc = DefMI->getDesc(); for (unsigned i = 1, e = DefDesc.getNumOperands(); i != e && !DefDesc.OpInfo[i].isPredicate(); ++i) NewMI.addOperand(DefMI->getOperand(i)); unsigned CondCode = MI.getOperand(3).getImm(); if (Invert) NewMI.addImm(getOppositeCondition(LPCC::CondCode(CondCode))); else NewMI.addImm(CondCode); NewMI.copyImplicitOps(MI); // The output register value when the predicate is false is an implicit // register operand tied to the first def. The tie makes the register // allocator ensure the FalseReg is allocated the same register as operand 0. FalseReg.setImplicit(); NewMI.addOperand(FalseReg); NewMI->tieOperands(0, NewMI->getNumOperands() - 1); // Update SeenMIs set: register newly created MI and erase removed DefMI. SeenMIs.insert(NewMI); SeenMIs.erase(DefMI); // If MI is inside a loop, and DefMI is outside the loop, then kill flags on // DefMI would be invalid when transferred inside the loop. Checking for a // loop is expensive, but at least remove kill flags if they are in different // BBs. if (DefMI->getParent() != MI.getParent()) NewMI->clearKillInfo(); // The caller will erase MI, but not DefMI. DefMI->eraseFromParent(); return NewMI; }
/// EmitDbgValue - Generate machine instruction for a dbg_value node. /// MachineInstr * InstrEmitter::EmitDbgValue(SDDbgValue *SD, DenseMap<SDValue, unsigned> &VRBaseMap) { uint64_t Offset = SD->getOffset(); MDNode* MDPtr = SD->getMDPtr(); DebugLoc DL = SD->getDebugLoc(); if (SD->getKind() == SDDbgValue::FRAMEIX) { // Stack address; this needs to be lowered in target-dependent fashion. // EmitTargetCodeForFrameDebugValue is responsible for allocation. return BuildMI(*MF, DL, TII->get(TargetOpcode::DBG_VALUE)) .addFrameIndex(SD->getFrameIx()).addImm(Offset).addMetadata(MDPtr); } // Otherwise, we're going to create an instruction here. const MCInstrDesc &II = TII->get(TargetOpcode::DBG_VALUE); MachineInstrBuilder MIB = BuildMI(*MF, DL, II); if (SD->getKind() == SDDbgValue::SDNODE) { SDNode *Node = SD->getSDNode(); SDValue Op = SDValue(Node, SD->getResNo()); // It's possible we replaced this SDNode with other(s) and therefore // didn't generate code for it. It's better to catch these cases where // they happen and transfer the debug info, but trying to guarantee that // in all cases would be very fragile; this is a safeguard for any // that were missed. DenseMap<SDValue, unsigned>::iterator I = VRBaseMap.find(Op); if (I==VRBaseMap.end()) MIB.addReg(0U); // undef else AddOperand(MIB, Op, (*MIB).getNumOperands(), &II, VRBaseMap, /*IsDebug=*/true, /*IsClone=*/false, /*IsCloned=*/false); } else if (SD->getKind() == SDDbgValue::CONST) { const Value *V = SD->getConst(); if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) { if (CI->getBitWidth() > 64) MIB.addCImm(CI); else MIB.addImm(CI->getSExtValue()); } else if (const ConstantFP *CF = dyn_cast<ConstantFP>(V)) { MIB.addFPImm(CF); } else { // Could be an Undef. In any case insert an Undef so we can see what we // dropped. MIB.addReg(0U); } } else { // Insert an Undef so we can see what we dropped. MIB.addReg(0U); } if (Offset != 0) // Indirect addressing. MIB.addImm(Offset); else MIB.addReg(0U, RegState::Debug); MIB.addMetadata(MDPtr); return &*MIB; }
/// EmitDbgValue - Generate machine instruction for a dbg_value node. /// MachineInstr * InstrEmitter::EmitDbgValue(SDDbgValue *SD, DenseMap<SDValue, unsigned> &VRBaseMap) { uint64_t Offset = SD->getOffset(); MDNode* MDPtr = SD->getMDPtr(); DebugLoc DL = SD->getDebugLoc(); if (SD->getKind() == SDDbgValue::FRAMEIX) { // Stack address; this needs to be lowered in target-dependent fashion. // EmitTargetCodeForFrameDebugValue is responsible for allocation. unsigned FrameIx = SD->getFrameIx(); return TII->emitFrameIndexDebugValue(*MF, FrameIx, Offset, MDPtr, DL); } // Otherwise, we're going to create an instruction here. const TargetInstrDesc &II = TII->get(TargetOpcode::DBG_VALUE); MachineInstrBuilder MIB = BuildMI(*MF, DL, II); if (SD->getKind() == SDDbgValue::SDNODE) { SDNode *Node = SD->getSDNode(); SDValue Op = SDValue(Node, SD->getResNo()); // It's possible we replaced this SDNode with other(s) and therefore // didn't generate code for it. It's better to catch these cases where // they happen and transfer the debug info, but trying to guarantee that // in all cases would be very fragile; this is a safeguard for any // that were missed. DenseMap<SDValue, unsigned>::iterator I = VRBaseMap.find(Op); if (I==VRBaseMap.end()) MIB.addReg(0U); // undef else AddOperand(&*MIB, Op, (*MIB).getNumOperands(), &II, VRBaseMap, /*IsDebug=*/true, /*IsClone=*/false, /*IsCloned=*/false); } else if (SD->getKind() == SDDbgValue::CONST) { const Value *V = SD->getConst(); if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) { // FIXME: SDDbgValue constants aren't updated with legalization, so it's // possible to have i128 constants in them at this point. Dwarf writer // does not handle i128 constants at the moment so, as a crude workaround, // just drop the debug info if this happens. if (!CI->getValue().isSignedIntN(64)) MIB.addReg(0U); else MIB.addImm(CI->getSExtValue()); } else if (const ConstantFP *CF = dyn_cast<ConstantFP>(V)) { MIB.addFPImm(CF); } else { // Could be an Undef. In any case insert an Undef so we can see what we // dropped. MIB.addReg(0U); } } else { // Insert an Undef so we can see what we dropped. MIB.addReg(0U); } MIB.addImm(Offset).addMetadata(MDPtr); return &*MIB; }
/// ExpandFPMLxInstructions - Expand a MLA / MLS instruction into a pair /// of MUL + ADD / SUB instructions. void MLxExpansion::ExpandFPMLxInstruction(MachineBasicBlock &MBB, MachineInstr *MI, unsigned MulOpc, unsigned AddSubOpc, bool NegAcc, bool HasLane) { unsigned DstReg = MI->getOperand(0).getReg(); bool DstDead = MI->getOperand(0).isDead(); unsigned AccReg = MI->getOperand(1).getReg(); unsigned Src1Reg = MI->getOperand(2).getReg(); unsigned Src2Reg = MI->getOperand(3).getReg(); bool Src1Kill = MI->getOperand(2).isKill(); bool Src2Kill = MI->getOperand(3).isKill(); unsigned LaneImm = HasLane ? MI->getOperand(4).getImm() : 0; unsigned NextOp = HasLane ? 5 : 4; ARMCC::CondCodes Pred = (ARMCC::CondCodes)MI->getOperand(NextOp).getImm(); unsigned PredReg = MI->getOperand(++NextOp).getReg(); const MCInstrDesc &MCID1 = TII->get(MulOpc); const MCInstrDesc &MCID2 = TII->get(AddSubOpc); const MachineFunction &MF = *MI->getParent()->getParent(); unsigned TmpReg = MRI->createVirtualRegister( TII->getRegClass(MCID1, 0, TRI, MF)); MachineInstrBuilder MIB = BuildMI(MBB, MI, MI->getDebugLoc(), MCID1, TmpReg) .addReg(Src1Reg, getKillRegState(Src1Kill)) .addReg(Src2Reg, getKillRegState(Src2Kill)); if (HasLane) MIB.addImm(LaneImm); MIB.addImm(Pred).addReg(PredReg); MIB = BuildMI(MBB, MI, MI->getDebugLoc(), MCID2) .addReg(DstReg, getDefRegState(true) | getDeadRegState(DstDead)); if (NegAcc) { bool AccKill = MRI->hasOneNonDBGUse(AccReg); MIB.addReg(TmpReg, getKillRegState(true)) .addReg(AccReg, getKillRegState(AccKill)); } else { MIB.addReg(AccReg).addReg(TmpReg, getKillRegState(true)); } MIB.addImm(Pred).addReg(PredReg); DEBUG({ dbgs() << "Expanding: " << *MI; dbgs() << " to:\n"; MachineBasicBlock::iterator MII = MI; MII = std::prev(MII); MachineInstr &MI2 = *MII; MII = std::prev(MII); MachineInstr &MI1 = *MII; dbgs() << " " << MI1; dbgs() << " " << MI2; });
bool IRTranslator::translateCall(const CallInst &CI) { auto TII = MIRBuilder.getMF().getTarget().getIntrinsicInfo(); const Function &F = *CI.getCalledFunction(); Intrinsic::ID ID = F.getIntrinsicID(); if (TII && ID == Intrinsic::not_intrinsic) ID = static_cast<Intrinsic::ID>(TII->getIntrinsicID(&F)); assert(ID != Intrinsic::not_intrinsic && "FIXME: support real calls"); // Need types (starting with return) & args. SmallVector<LLT, 4> Tys; Tys.emplace_back(*CI.getType()); for (auto &Arg : CI.arg_operands()) Tys.emplace_back(*Arg->getType()); unsigned Res = CI.getType()->isVoidTy() ? 0 : getOrCreateVReg(CI); MachineInstrBuilder MIB = MIRBuilder.buildIntrinsic(Tys, ID, Res, !CI.doesNotAccessMemory()); for (auto &Arg : CI.arg_operands()) { if (ConstantInt *CI = dyn_cast<ConstantInt>(Arg)) MIB.addImm(CI->getSExtValue()); else MIB.addUse(getOrCreateVReg(*Arg)); } return true; }
void MipsInstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg, SmallVectorImpl<MachineOperand> &Addr, const TargetRegisterClass *RC, SmallVectorImpl<MachineInstr*> &NewMIs) const { unsigned Opc; if (RC == Mips::CPURegsRegisterClass) Opc = Mips::LW; else if (RC == Mips::FGR32RegisterClass) Opc = Mips::LWC1; else if (RC == Mips::AFGR32RegisterClass) Opc = Mips::LWC1A; else if (RC == Mips::AFGR64RegisterClass) Opc = Mips::LDC1; else assert(0 && "Can't load this register"); MachineInstrBuilder MIB = BuildMI(MF, get(Opc), DestReg); for (unsigned i = 0, e = Addr.size(); i != e; ++i) { MachineOperand &MO = Addr[i]; if (MO.isReg()) MIB.addReg(MO.getReg()); else if (MO.isImm()) MIB.addImm(MO.getImm()); else MIB.addFrameIndex(MO.getIndex()); } NewMIs.push_back(MIB); return; }
void SparcInstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg, SmallVectorImpl<MachineOperand> &Addr, const TargetRegisterClass *RC, SmallVectorImpl<MachineInstr*> &NewMIs) const { unsigned Opc = 0; if (RC == SP::IntRegsRegisterClass) Opc = SP::LDri; else if (RC == SP::FPRegsRegisterClass) Opc = SP::LDFri; else if (RC == SP::DFPRegsRegisterClass) Opc = SP::LDDFri; else assert(0 && "Can't load this register"); MachineInstrBuilder MIB = BuildMI(MF, get(Opc), DestReg); for (unsigned i = 0, e = Addr.size(); i != e; ++i) { MachineOperand &MO = Addr[i]; if (MO.isReg()) MIB.addReg(MO.getReg()); else if (MO.isImm()) MIB.addImm(MO.getImm()); else { assert(MO.isFI()); MIB.addFrameIndex(MO.getIndex()); } } NewMIs.push_back(MIB); return; }
void IA64InstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg, SmallVectorImpl<MachineOperand> &Addr, const TargetRegisterClass *RC, SmallVectorImpl<MachineInstr*> &NewMIs) const { unsigned Opc = 0; if (RC == IA64::FPRegisterClass) { Opc = IA64::LDF8; } else if (RC == IA64::GRRegisterClass) { Opc = IA64::LD8; } else if (RC == IA64::PRRegisterClass) { Opc = IA64::LD1; } else { assert(0 && "sorry, I don't know how to store this sort of reg\n"); } MachineInstrBuilder MIB = BuildMI(MF, get(Opc), DestReg); for (unsigned i = 0, e = Addr.size(); i != e; ++i) { MachineOperand &MO = Addr[i]; if (MO.isReg()) MIB.addReg(MO.getReg()); else if (MO.isImm()) MIB.addImm(MO.getImm()); else MIB.addFrameIndex(MO.getIndex()); } NewMIs.push_back(MIB); return; }
bool ARMInstructionSelector::selectShift(unsigned ShiftOpc, MachineInstrBuilder &MIB) const { MIB->setDesc(TII.get(ARM::MOVsr)); MIB.addImm(ShiftOpc); MIB.add(predOps(ARMCC::AL)).add(condCodeOp()); return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI); }
// Adjust SP by FrameSize bytes. Restore RA, S0, S1 void Mips16InstrInfo::restoreFrame(unsigned SP, int64_t FrameSize, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); MachineFunction *MF = MBB.getParent(); MachineFrameInfo &MFI = MF->getFrameInfo(); const BitVector Reserved = RI.getReservedRegs(*MF); bool SaveS2 = Reserved[Mips::S2]; MachineInstrBuilder MIB; unsigned Opc = ((FrameSize <= 128) && !SaveS2)? Mips::Restore16:Mips::RestoreX16; if (!isUInt<11>(FrameSize)) { unsigned Base = 2040; int64_t Remainder = FrameSize - Base; FrameSize = Base; // should create template function like isUInt that // returns largest possible n bit unsigned integer if (isInt<16>(Remainder)) BuildAddiuSpImm(MBB, I, Remainder); else adjustStackPtrBig(SP, Remainder, MBB, I, Mips::A0, Mips::A1); } MIB = BuildMI(MBB, I, DL, get(Opc)); const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); addSaveRestoreRegs(MIB, CSI, RegState::Define); if (SaveS2) MIB.addReg(Mips::S2, RegState::Define); MIB.addImm(FrameSize); }
void AlphaInstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg, bool isKill, SmallVectorImpl<MachineOperand> &Addr, const TargetRegisterClass *RC, SmallVectorImpl<MachineInstr*> &NewMIs) const { unsigned Opc = 0; if (RC == Alpha::F4RCRegisterClass) Opc = Alpha::STS; else if (RC == Alpha::F8RCRegisterClass) Opc = Alpha::STT; else if (RC == Alpha::GPRCRegisterClass) Opc = Alpha::STQ; else abort(); MachineInstrBuilder MIB = BuildMI(MF, get(Opc)).addReg(SrcReg, false, false, isKill); for (unsigned i = 0, e = Addr.size(); i != e; ++i) { MachineOperand &MO = Addr[i]; if (MO.isReg()) MIB.addReg(MO.getReg(), MO.isDef(), MO.isImplicit()); else MIB.addImm(MO.getImm()); } NewMIs.push_back(MIB); }
void WebAssemblyFastISel::addLoadStoreOperands(const Address &Addr, const MachineInstrBuilder &MIB, MachineMemOperand *MMO) { if (const GlobalValue *GV = Addr.getGlobalValue()) MIB.addGlobalAddress(GV, Addr.getOffset()); else MIB.addImm(Addr.getOffset()); if (Addr.isRegBase()) MIB.addReg(Addr.getReg()); else MIB.addFrameIndex(Addr.getFI()); // Set the alignment operand (this is rewritten in SetP2AlignOperands). // TODO: Disable SetP2AlignOperands for FastISel and just do it here. MIB.addImm(0); MIB.addMemOperand(MMO); }
bool SystemZFrameLowering:: restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const std::vector<CalleeSavedInfo> &CSI, const TargetRegisterInfo *TRI) const { if (CSI.empty()) return false; MachineFunction &MF = *MBB.getParent(); const TargetInstrInfo *TII = MF.getTarget().getInstrInfo(); SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); bool HasFP = hasFP(MF); DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); // Restore FPRs in the normal TargetInstrInfo way. for (unsigned I = 0, E = CSI.size(); I != E; ++I) { unsigned Reg = CSI[I].getReg(); if (SystemZ::FP64BitRegClass.contains(Reg)) TII->loadRegFromStackSlot(MBB, MBBI, Reg, CSI[I].getFrameIdx(), &SystemZ::FP64BitRegClass, TRI); } // Restore call-saved GPRs (but not call-clobbered varargs, which at // this point might hold return values). unsigned LowGPR = ZFI->getLowSavedGPR(); unsigned HighGPR = ZFI->getHighSavedGPR(); unsigned StartOffset = RegSpillOffsets[LowGPR]; if (LowGPR) { // If we saved any of %r2-%r5 as varargs, we should also be saving // and restoring %r6. If we're saving %r6 or above, we should be // restoring it too. assert(LowGPR != HighGPR && "Should be loading %r15 and something else"); // Build an LMG instruction. MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(SystemZ::LMG)); // Add the explicit register operands. MIB.addReg(LowGPR, RegState::Define); MIB.addReg(HighGPR, RegState::Define); // Add the address. MIB.addReg(HasFP ? SystemZ::R11D : SystemZ::R15D); MIB.addImm(StartOffset); // Do a second scan adding regs as being defined by instruction for (unsigned I = 0, E = CSI.size(); I != E; ++I) { unsigned Reg = CSI[I].getReg(); if (Reg != LowGPR && Reg != HighGPR) MIB.addReg(Reg, RegState::ImplicitDefine); } } return true; }
bool SystemZInstrInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector<CalleeSavedInfo> &CSI) const { if (CSI.empty()) return false; DebugLoc DL = DebugLoc::getUnknownLoc(); if (MI != MBB.end()) DL = MI->getDebugLoc(); MachineFunction &MF = *MBB.getParent(); const TargetRegisterInfo *RegInfo= MF.getTarget().getRegisterInfo(); SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>(); // Restore FP registers for (unsigned i = 0, e = CSI.size(); i != e; ++i) { unsigned Reg = CSI[i].getReg(); const TargetRegisterClass *RegClass = CSI[i].getRegClass(); if (RegClass == &SystemZ::FP64RegClass) loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), RegClass); } // Restore GP registers unsigned LowReg = MFI->getLowReg(), HighReg = MFI->getHighReg(); unsigned StartOffset = RegSpillOffsets[LowReg]; if (StartOffset) { // Build a load instruction. Use LOAD MULTIPLE instruction if there are many // registers to load, otherwise - just LOAD. MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, get((LowReg == HighReg ? SystemZ::MOV64rm : SystemZ::MOV64rmm))); // Add store operands. MIB.addReg(LowReg, RegState::Define); if (LowReg != HighReg) MIB.addReg(HighReg, RegState::Define); MIB.addReg((RegInfo->hasFP(MF) ? SystemZ::R11D : SystemZ::R15D)); MIB.addImm(StartOffset); if (LowReg == HighReg) MIB.addReg(0); // Do a second scan adding regs as being defined by instruction for (unsigned i = 0, e = CSI.size(); i != e; ++i) { unsigned Reg = CSI[i].getReg(); if (Reg != LowReg && Reg != HighReg) MIB.addReg(Reg, RegState::ImplicitDefine); } } return true; }
MachineInstrBuilder R600InstrInfo::buildDefaultInstruction(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned Opcode, unsigned DstReg, unsigned Src0Reg, unsigned Src1Reg) const { MachineInstrBuilder MIB = BuildMI(MBB, I, MBB.findDebugLoc(I), get(Opcode), DstReg); // $dst if (Src1Reg) { MIB.addImm(0) // $update_exec_mask .addImm(0); // $update_predicate } MIB.addImm(1) // $write .addImm(0) // $omod .addImm(0) // $dst_rel .addImm(0) // $dst_clamp .addReg(Src0Reg) // $src0 .addImm(0) // $src0_neg .addImm(0) // $src0_rel .addImm(0); // $src0_abs if (Src1Reg) { MIB.addReg(Src1Reg) // $src1 .addImm(0) // $src1_neg .addImm(0) // $src1_rel .addImm(0); // $src1_abs } //XXX: The r600g finalizer expects this to be 1, once we've moved the //scheduling to the backend, we can change the default to 0. MIB.addImm(1) // $last .addReg(AMDGPU::PRED_SEL_OFF) // $pred_sel .addImm(0); // $literal return MIB; }
void MipsInstrInfo::BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB, const DebugLoc &DL, ArrayRef<MachineOperand> Cond) const { unsigned Opc = Cond[0].getImm(); const MCInstrDesc &MCID = get(Opc); MachineInstrBuilder MIB = BuildMI(&MBB, DL, MCID); for (unsigned i = 1; i < Cond.size(); ++i) { if (Cond[i].isReg()) MIB.addReg(Cond[i].getReg()); else if (Cond[i].isImm()) MIB.addImm(Cond[i].getImm()); else assert(false && "Cannot copy operand"); } MIB.addMBB(TBB); }
void CoffeeInstrInfo::BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB, DebugLoc DL, const SmallVectorImpl<MachineOperand>& Cond) const { unsigned Opc = Cond[0].getImm(); const MCInstrDesc &MCID = get(Opc); MachineInstrBuilder MIB = BuildMI(&MBB, DL, MCID); for (unsigned i = 1; i < Cond.size(); ++i) { if (Cond[i].isReg()) MIB.addReg(Cond[i].getReg()); else if (Cond[i].isImm()) MIB.addImm(Cond[i].getImm()); else assert(true && "Cannot copy operand"); } MIB.addMBB(TBB); }
MachineInstrBuilder MachineIRBuilder::buildSequence(unsigned Res, ArrayRef<unsigned> Ops, ArrayRef<uint64_t> Indices) { #ifndef NDEBUG assert(Ops.size() == Indices.size() && "incompatible args"); assert(!Ops.empty() && "invalid trivial sequence"); assert(std::is_sorted(Indices.begin(), Indices.end()) && "sequence offsets must be in ascending order"); assert(MRI->getType(Res).isValid() && "invalid operand type"); for (auto Op : Ops) assert(MRI->getType(Op).isValid() && "invalid operand type"); #endif MachineInstrBuilder MIB = buildInstr(TargetOpcode::G_SEQUENCE); MIB.addDef(Res); for (unsigned i = 0; i < Ops.size(); ++i) { MIB.addUse(Ops[i]); MIB.addImm(Indices[i]); } return MIB; }
bool IRTranslator::translateCall(const User &U) { const CallInst &CI = cast<CallInst>(U); auto TII = MIRBuilder.getMF().getTarget().getIntrinsicInfo(); const Function *F = CI.getCalledFunction(); if (!F || !F->isIntrinsic()) { unsigned Res = CI.getType()->isVoidTy() ? 0 : getOrCreateVReg(CI); SmallVector<unsigned, 8> Args; for (auto &Arg: CI.arg_operands()) Args.push_back(getOrCreateVReg(*Arg)); return CLI->lowerCall(MIRBuilder, CI, Res, Args, [&]() { return getOrCreateVReg(*CI.getCalledValue()); }); } Intrinsic::ID ID = F->getIntrinsicID(); if (TII && ID == Intrinsic::not_intrinsic) ID = static_cast<Intrinsic::ID>(TII->getIntrinsicID(F)); assert(ID != Intrinsic::not_intrinsic && "unknown intrinsic"); if (translateKnownIntrinsic(CI, ID)) return true; unsigned Res = CI.getType()->isVoidTy() ? 0 : getOrCreateVReg(CI); MachineInstrBuilder MIB = MIRBuilder.buildIntrinsic(ID, Res, !CI.doesNotAccessMemory()); for (auto &Arg : CI.arg_operands()) { if (ConstantInt *CI = dyn_cast<ConstantInt>(Arg)) MIB.addImm(CI->getSExtValue()); else MIB.addUse(getOrCreateVReg(*Arg)); } return true; }
void AlphaInstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg, SmallVectorImpl<MachineOperand> &Addr, const TargetRegisterClass *RC, SmallVectorImpl<MachineInstr*> &NewMIs) const { unsigned Opc = 0; if (RC == Alpha::F4RCRegisterClass) Opc = Alpha::LDS; else if (RC == Alpha::F8RCRegisterClass) Opc = Alpha::LDT; else if (RC == Alpha::GPRCRegisterClass) Opc = Alpha::LDQ; else abort(); MachineInstrBuilder MIB = BuildMI(MF, get(Opc), DestReg); for (unsigned i = 0, e = Addr.size(); i != e; ++i) { MachineOperand &MO = Addr[i]; if (MO.isReg()) MIB.addReg(MO.getReg(), MO.isDef(), MO.isImplicit()); else MIB.addImm(MO.getImm()); } NewMIs.push_back(MIB); }
/// EmitSpecialNode - Generate machine code for a target-independent node and /// needed dependencies. void InstrEmitter:: EmitSpecialNode(SDNode *Node, bool IsClone, bool IsCloned, DenseMap<SDValue, unsigned> &VRBaseMap) { switch (Node->getOpcode()) { default: #ifndef NDEBUG Node->dump(); #endif llvm_unreachable("This target-independent node should have been selected!"); case ISD::EntryToken: llvm_unreachable("EntryToken should have been excluded from the schedule!"); case ISD::MERGE_VALUES: case ISD::TokenFactor: // fall thru break; case ISD::CopyToReg: { unsigned SrcReg; SDValue SrcVal = Node->getOperand(2); if (RegisterSDNode *R = dyn_cast<RegisterSDNode>(SrcVal)) SrcReg = R->getReg(); else SrcReg = getVR(SrcVal, VRBaseMap); unsigned DestReg = cast<RegisterSDNode>(Node->getOperand(1))->getReg(); if (SrcReg == DestReg) // Coalesced away the copy? Ignore. break; BuildMI(*MBB, InsertPos, Node->getDebugLoc(), TII->get(TargetOpcode::COPY), DestReg).addReg(SrcReg); break; } case ISD::CopyFromReg: { unsigned SrcReg = cast<RegisterSDNode>(Node->getOperand(1))->getReg(); EmitCopyFromReg(Node, 0, IsClone, IsCloned, SrcReg, VRBaseMap); break; } case ISD::EH_LABEL: case ISD::ANNOTATION_LABEL: { unsigned Opc = (Node->getOpcode() == ISD::EH_LABEL) ? TargetOpcode::EH_LABEL : TargetOpcode::ANNOTATION_LABEL; MCSymbol *S = cast<LabelSDNode>(Node)->getLabel(); BuildMI(*MBB, InsertPos, Node->getDebugLoc(), TII->get(Opc)).addSym(S); break; } case ISD::LIFETIME_START: case ISD::LIFETIME_END: { unsigned TarOp = (Node->getOpcode() == ISD::LIFETIME_START) ? TargetOpcode::LIFETIME_START : TargetOpcode::LIFETIME_END; FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Node->getOperand(1)); BuildMI(*MBB, InsertPos, Node->getDebugLoc(), TII->get(TarOp)) .addFrameIndex(FI->getIndex()); break; } case ISD::INLINEASM: { unsigned NumOps = Node->getNumOperands(); if (Node->getOperand(NumOps-1).getValueType() == MVT::Glue) --NumOps; // Ignore the glue operand. // Create the inline asm machine instruction. MachineInstrBuilder MIB = BuildMI(*MF, Node->getDebugLoc(), TII->get(TargetOpcode::INLINEASM)); // Add the asm string as an external symbol operand. SDValue AsmStrV = Node->getOperand(InlineAsm::Op_AsmString); const char *AsmStr = cast<ExternalSymbolSDNode>(AsmStrV)->getSymbol(); MIB.addExternalSymbol(AsmStr); // Add the HasSideEffect, isAlignStack, AsmDialect, MayLoad and MayStore // bits. int64_t ExtraInfo = cast<ConstantSDNode>(Node->getOperand(InlineAsm::Op_ExtraInfo))-> getZExtValue(); MIB.addImm(ExtraInfo); // Remember to operand index of the group flags. SmallVector<unsigned, 8> GroupIdx; // Remember registers that are part of early-clobber defs. SmallVector<unsigned, 8> ECRegs; // Add all of the operand registers to the instruction. for (unsigned i = InlineAsm::Op_FirstOperand; i != NumOps;) { unsigned Flags = cast<ConstantSDNode>(Node->getOperand(i))->getZExtValue(); const unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags); GroupIdx.push_back(MIB->getNumOperands()); MIB.addImm(Flags); ++i; // Skip the ID value. switch (InlineAsm::getKind(Flags)) { default: llvm_unreachable("Bad flags!"); case InlineAsm::Kind_RegDef: for (unsigned j = 0; j != NumVals; ++j, ++i) { unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg(); // FIXME: Add dead flags for physical and virtual registers defined. // For now, mark physical register defs as implicit to help fast // regalloc. This makes inline asm look a lot like calls. MIB.addReg(Reg, RegState::Define | getImplRegState(TargetRegisterInfo::isPhysicalRegister(Reg))); } break; case InlineAsm::Kind_RegDefEarlyClobber: case InlineAsm::Kind_Clobber: for (unsigned j = 0; j != NumVals; ++j, ++i) { unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg(); MIB.addReg(Reg, RegState::Define | RegState::EarlyClobber | getImplRegState(TargetRegisterInfo::isPhysicalRegister(Reg))); ECRegs.push_back(Reg); } break; case InlineAsm::Kind_RegUse: // Use of register. case InlineAsm::Kind_Imm: // Immediate. case InlineAsm::Kind_Mem: // Addressing mode. // The addressing mode has been selected, just add all of the // operands to the machine instruction. for (unsigned j = 0; j != NumVals; ++j, ++i) AddOperand(MIB, Node->getOperand(i), 0, nullptr, VRBaseMap, /*IsDebug=*/false, IsClone, IsCloned); // Manually set isTied bits. if (InlineAsm::getKind(Flags) == InlineAsm::Kind_RegUse) { unsigned DefGroup = 0; if (InlineAsm::isUseOperandTiedToDef(Flags, DefGroup)) { unsigned DefIdx = GroupIdx[DefGroup] + 1; unsigned UseIdx = GroupIdx.back() + 1; for (unsigned j = 0; j != NumVals; ++j) MIB->tieOperands(DefIdx + j, UseIdx + j); } } break; } } // GCC inline assembly allows input operands to also be early-clobber // output operands (so long as the operand is written only after it's // used), but this does not match the semantics of our early-clobber flag. // If an early-clobber operand register is also an input operand register, // then remove the early-clobber flag. for (unsigned Reg : ECRegs) { if (MIB->readsRegister(Reg, TRI)) { MachineOperand *MO = MIB->findRegisterDefOperand(Reg, false, TRI); assert(MO && "No def operand for clobbered register?"); MO->setIsEarlyClobber(false); } } // Get the mdnode from the asm if it exists and add it to the instruction. SDValue MDV = Node->getOperand(InlineAsm::Op_MDNode); const MDNode *MD = cast<MDNodeSDNode>(MDV)->getMD(); if (MD) MIB.addMetadata(MD); MBB->insert(InsertPos, MIB); break; } } }
void SSACCmpConv::convert(SmallVectorImpl<MachineBasicBlock *> &RemovedBlocks) { DEBUG(dbgs() << "Merging BB#" << CmpBB->getNumber() << " into BB#" << Head->getNumber() << ":\n" << *CmpBB); // All CmpBB instructions are moved into Head, and CmpBB is deleted. // Update the CFG first. updateTailPHIs(); Head->removeSuccessor(CmpBB); CmpBB->removeSuccessor(Tail); Head->transferSuccessorsAndUpdatePHIs(CmpBB); DebugLoc TermDL = Head->getFirstTerminator()->getDebugLoc(); TII->RemoveBranch(*Head); // If the Head terminator was one of the cbz / tbz branches with built-in // compare, we need to insert an explicit compare instruction in its place. if (HeadCond[0].getImm() == -1) { ++NumCompBranches; unsigned Opc = 0; switch (HeadCond[1].getImm()) { case AArch64::CBZW: case AArch64::CBNZW: Opc = AArch64::SUBSWri; break; case AArch64::CBZX: case AArch64::CBNZX: Opc = AArch64::SUBSXri; break; default: llvm_unreachable("Cannot convert Head branch"); } const MCInstrDesc &MCID = TII->get(Opc); // Create a dummy virtual register for the SUBS def. unsigned DestReg = MRI->createVirtualRegister(TII->getRegClass(MCID, 0, TRI, *MF)); // Insert a SUBS Rn, #0 instruction instead of the cbz / cbnz. BuildMI(*Head, Head->end(), TermDL, MCID) .addReg(DestReg, RegState::Define | RegState::Dead) .addOperand(HeadCond[2]) .addImm(0) .addImm(0); // SUBS uses the GPR*sp register classes. MRI->constrainRegClass(HeadCond[2].getReg(), TII->getRegClass(MCID, 1, TRI, *MF)); } Head->splice(Head->end(), CmpBB, CmpBB->begin(), CmpBB->end()); // Now replace CmpMI with a ccmp instruction that also considers the incoming // flags. unsigned Opc = 0; unsigned FirstOp = 1; // First CmpMI operand to copy. bool isZBranch = false; // CmpMI is a cbz/cbnz instruction. switch (CmpMI->getOpcode()) { default: llvm_unreachable("Unknown compare opcode"); case AArch64::SUBSWri: Opc = AArch64::CCMPWi; break; case AArch64::SUBSWrr: Opc = AArch64::CCMPWr; break; case AArch64::SUBSXri: Opc = AArch64::CCMPXi; break; case AArch64::SUBSXrr: Opc = AArch64::CCMPXr; break; case AArch64::ADDSWri: Opc = AArch64::CCMNWi; break; case AArch64::ADDSWrr: Opc = AArch64::CCMNWr; break; case AArch64::ADDSXri: Opc = AArch64::CCMNXi; break; case AArch64::ADDSXrr: Opc = AArch64::CCMNXr; break; case AArch64::FCMPSrr: Opc = AArch64::FCCMPSrr; FirstOp = 0; break; case AArch64::FCMPDrr: Opc = AArch64::FCCMPDrr; FirstOp = 0; break; case AArch64::FCMPESrr: Opc = AArch64::FCCMPESrr; FirstOp = 0; break; case AArch64::FCMPEDrr: Opc = AArch64::FCCMPEDrr; FirstOp = 0; break; case AArch64::CBZW: case AArch64::CBNZW: Opc = AArch64::CCMPWi; FirstOp = 0; isZBranch = true; break; case AArch64::CBZX: case AArch64::CBNZX: Opc = AArch64::CCMPXi; FirstOp = 0; isZBranch = true; break; } // The ccmp instruction should set the flags according to the comparison when // Head would have branched to CmpBB. // The NZCV immediate operand should provide flags for the case where Head // would have branched to Tail. These flags should cause the new Head // terminator to branch to tail. unsigned NZCV = AArch64CC::getNZCVToSatisfyCondCode(CmpBBTailCC); const MCInstrDesc &MCID = TII->get(Opc); MRI->constrainRegClass(CmpMI->getOperand(FirstOp).getReg(), TII->getRegClass(MCID, 0, TRI, *MF)); if (CmpMI->getOperand(FirstOp + 1).isReg()) MRI->constrainRegClass(CmpMI->getOperand(FirstOp + 1).getReg(), TII->getRegClass(MCID, 1, TRI, *MF)); MachineInstrBuilder MIB = BuildMI(*Head, CmpMI, CmpMI->getDebugLoc(), MCID) .addOperand(CmpMI->getOperand(FirstOp)); // Register Rn if (isZBranch) MIB.addImm(0); // cbz/cbnz Rn -> ccmp Rn, #0 else MIB.addOperand(CmpMI->getOperand(FirstOp + 1)); // Register Rm / Immediate MIB.addImm(NZCV).addImm(HeadCmpBBCC); // If CmpMI was a terminator, we need a new conditional branch to replace it. // This now becomes a Head terminator. if (isZBranch) { bool isNZ = CmpMI->getOpcode() == AArch64::CBNZW || CmpMI->getOpcode() == AArch64::CBNZX; BuildMI(*Head, CmpMI, CmpMI->getDebugLoc(), TII->get(AArch64::Bcc)) .addImm(isNZ ? AArch64CC::NE : AArch64CC::EQ) .addOperand(CmpMI->getOperand(1)); // Branch target. } CmpMI->eraseFromParent(); Head->updateTerminator(); RemovedBlocks.push_back(CmpBB); CmpBB->eraseFromParent(); DEBUG(dbgs() << "Result:\n" << *Head); ++NumConverted; }
bool Thumb2ITBlockPass::InsertITInstructions(MachineBasicBlock &MBB) { bool Modified = false; SmallSet<unsigned, 4> Defs; SmallSet<unsigned, 4> Uses; MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); while (MBBI != E) { MachineInstr *MI = &*MBBI; DebugLoc dl = MI->getDebugLoc(); unsigned PredReg = 0; ARMCC::CondCodes CC = llvm::getITInstrPredicate(MI, PredReg); if (CC == ARMCC::AL) { ++MBBI; continue; } Defs.clear(); Uses.clear(); TrackDefUses(MI, Defs, Uses, TRI); // Insert an IT instruction. MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(ARM::t2IT)) .addImm(CC); // Add implicit use of ITSTATE to IT block instructions. MI->addOperand(MachineOperand::CreateReg(ARM::ITSTATE, false/*ifDef*/, true/*isImp*/, false/*isKill*/)); MachineInstr *LastITMI = MI; MachineBasicBlock::iterator InsertPos = MIB; ++MBBI; // Form IT block. ARMCC::CondCodes OCC = ARMCC::getOppositeCondition(CC); unsigned Mask = 0, Pos = 3; // Branches, including tricky ones like LDM_RET, need to end an IT // block so check the instruction we just put in the block. for (; MBBI != E && Pos && (!MI->isBranch() && !MI->isReturn()) ; ++MBBI) { if (MBBI->isDebugValue()) continue; MachineInstr *NMI = &*MBBI; MI = NMI; unsigned NPredReg = 0; ARMCC::CondCodes NCC = llvm::getITInstrPredicate(NMI, NPredReg); if (NCC == CC || NCC == OCC) { Mask |= (NCC & 1) << Pos; // Add implicit use of ITSTATE. NMI->addOperand(MachineOperand::CreateReg(ARM::ITSTATE, false/*ifDef*/, true/*isImp*/, false/*isKill*/)); LastITMI = NMI; } else { if (NCC == ARMCC::AL && MoveCopyOutOfITBlock(NMI, CC, OCC, Defs, Uses)) { --MBBI; MBB.remove(NMI); MBB.insert(InsertPos, NMI); ++NumMovedInsts; continue; } break; } TrackDefUses(NMI, Defs, Uses, TRI); --Pos; } // Finalize IT mask. Mask |= (1 << Pos); // Tag along (firstcond[0] << 4) with the mask. Mask |= (CC & 1) << 4; MIB.addImm(Mask); // Last instruction in IT block kills ITSTATE. LastITMI->findRegisterUseOperand(ARM::ITSTATE)->setIsKill(); Modified = true; ++NumITs; } return Modified; }
bool AMDGPUIndirectAddressingPass::runOnMachineFunction(MachineFunction &MF) { MachineRegisterInfo &MRI = MF.getRegInfo(); int IndirectBegin = TII->getIndirectIndexBegin(MF); int IndirectEnd = TII->getIndirectIndexEnd(MF); if (IndirectBegin == -1) { // No indirect addressing, we can skip this pass assert(IndirectEnd == -1); return false; } // The map keeps track of the indirect address that is represented by // each virtual register. The key is the register and the value is the // indirect address it uses. std::map<unsigned, unsigned> RegisterAddressMap; // First pass - Lower all of the RegisterStore instructions and track which // registers are live. for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end(); BB != BB_E; ++BB) { // This map keeps track of the current live indirect registers. // The key is the address and the value is the register std::map<unsigned, unsigned> LiveAddressRegisterMap; MachineBasicBlock &MBB = *BB; for (MachineBasicBlock::iterator I = MBB.begin(), Next = llvm::next(I); I != MBB.end(); I = Next) { Next = llvm::next(I); MachineInstr &MI = *I; if (!TII->isRegisterStore(MI)) { continue; } // Lower RegisterStore unsigned RegIndex = MI.getOperand(2).getImm(); unsigned Channel = MI.getOperand(3).getImm(); unsigned Address = TII->calculateIndirectAddress(RegIndex, Channel); const TargetRegisterClass *IndirectStoreRegClass = TII->getIndirectAddrStoreRegClass(MI.getOperand(0).getReg()); if (MI.getOperand(1).getReg() == AMDGPU::INDIRECT_BASE_ADDR) { // Direct register access. unsigned DstReg = MRI.createVirtualRegister(IndirectStoreRegClass); BuildMI(MBB, I, MBB.findDebugLoc(I), TII->get(AMDGPU::COPY), DstReg) .addOperand(MI.getOperand(0)); RegisterAddressMap[DstReg] = Address; LiveAddressRegisterMap[Address] = DstReg; } else { // Indirect register access. MachineInstrBuilder MOV = TII->buildIndirectWrite(BB, I, MI.getOperand(0).getReg(), // Value Address, MI.getOperand(1).getReg()); // Offset for (int i = IndirectBegin; i <= IndirectEnd; ++i) { unsigned Addr = TII->calculateIndirectAddress(i, Channel); unsigned DstReg = MRI.createVirtualRegister(IndirectStoreRegClass); MOV.addReg(DstReg, RegState::Define | RegState::Implicit); RegisterAddressMap[DstReg] = Addr; LiveAddressRegisterMap[Addr] = DstReg; } } MI.eraseFromParent(); } // Update the live-ins of the succesor blocks for (MachineBasicBlock::succ_iterator Succ = MBB.succ_begin(), SuccEnd = MBB.succ_end(); SuccEnd != Succ; ++Succ) { std::map<unsigned, unsigned>::const_iterator Key, KeyEnd; for (Key = LiveAddressRegisterMap.begin(), KeyEnd = LiveAddressRegisterMap.end(); KeyEnd != Key; ++Key) { (*Succ)->addLiveIn(Key->second); } } } // Second pass - Lower the RegisterLoad instructions for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end(); BB != BB_E; ++BB) { // Key is the address and the value is the register std::map<unsigned, unsigned> LiveAddressRegisterMap; MachineBasicBlock &MBB = *BB; MachineBasicBlock::livein_iterator LI = MBB.livein_begin(); while (LI != MBB.livein_end()) { std::vector<unsigned> PhiRegisters; // Make sure this live in is used for indirect addressing if (RegisterAddressMap.find(*LI) == RegisterAddressMap.end()) { ++LI; continue; } unsigned Address = RegisterAddressMap[*LI]; LiveAddressRegisterMap[Address] = *LI; PhiRegisters.push_back(*LI); // Check if there are other live in registers which map to the same // indirect address. for (MachineBasicBlock::livein_iterator LJ = llvm::next(LI), LE = MBB.livein_end(); LJ != LE; ++LJ) { unsigned Reg = *LJ; if (RegisterAddressMap.find(Reg) == RegisterAddressMap.end()) { continue; } if (RegisterAddressMap[Reg] == Address) { PhiRegisters.push_back(Reg); } } if (PhiRegisters.size() == 1) { // We don't need to insert a Phi instruction, so we can just add the // registers to the live list for the block. LiveAddressRegisterMap[Address] = *LI; MBB.removeLiveIn(*LI); } else { // We need to insert a PHI, because we have the same address being // written in multiple predecessor blocks. const TargetRegisterClass *PhiDstClass = TII->getIndirectAddrStoreRegClass(*(PhiRegisters.begin())); unsigned PhiDstReg = MRI.createVirtualRegister(PhiDstClass); MachineInstrBuilder Phi = BuildMI(MBB, MBB.begin(), MBB.findDebugLoc(MBB.begin()), TII->get(AMDGPU::PHI), PhiDstReg); for (std::vector<unsigned>::const_iterator RI = PhiRegisters.begin(), RE = PhiRegisters.end(); RI != RE; ++RI) { unsigned Reg = *RI; MachineInstr *DefInst = MRI.getVRegDef(Reg); assert(DefInst); MachineBasicBlock *RegBlock = DefInst->getParent(); Phi.addReg(Reg); Phi.addMBB(RegBlock); MBB.removeLiveIn(Reg); } RegisterAddressMap[PhiDstReg] = Address; LiveAddressRegisterMap[Address] = PhiDstReg; } LI = MBB.livein_begin(); } for (MachineBasicBlock::iterator I = MBB.begin(), Next = llvm::next(I); I != MBB.end(); I = Next) { Next = llvm::next(I); MachineInstr &MI = *I; if (!TII->isRegisterLoad(MI)) { if (MI.getOpcode() == AMDGPU::PHI) { continue; } // Check for indirect register defs for (unsigned OpIdx = 0, NumOperands = MI.getNumOperands(); OpIdx < NumOperands; ++OpIdx) { MachineOperand &MO = MI.getOperand(OpIdx); if (MO.isReg() && MO.isDef() && RegisterAddressMap.find(MO.getReg()) != RegisterAddressMap.end()) { unsigned Reg = MO.getReg(); unsigned LiveAddress = RegisterAddressMap[Reg]; // Chain the live-ins if (LiveAddressRegisterMap.find(LiveAddress) != RegisterAddressMap.end()) { MI.addOperand(MachineOperand::CreateReg( LiveAddressRegisterMap[LiveAddress], false, // isDef true, // isImp true)); // isKill } LiveAddressRegisterMap[LiveAddress] = Reg; } } continue; } const TargetRegisterClass *SuperIndirectRegClass = TII->getSuperIndirectRegClass(); const TargetRegisterClass *IndirectLoadRegClass = TII->getIndirectAddrLoadRegClass(); unsigned IndirectReg = MRI.createVirtualRegister(SuperIndirectRegClass); unsigned RegIndex = MI.getOperand(2).getImm(); unsigned Channel = MI.getOperand(3).getImm(); unsigned Address = TII->calculateIndirectAddress(RegIndex, Channel); if (MI.getOperand(1).getReg() == AMDGPU::INDIRECT_BASE_ADDR) { // Direct register access unsigned Reg = LiveAddressRegisterMap[Address]; unsigned AddrReg = IndirectLoadRegClass->getRegister(Address); if (regHasExplicitDef(MRI, Reg)) { // If the register we are reading from has an explicit def, then that // means it was written via a direct register access (i.e. COPY // or other instruction that doesn't use indirect addressing). In // this case we know where the value has been stored, so we can just // issue a copy. BuildMI(MBB, I, MBB.findDebugLoc(I), TII->get(AMDGPU::COPY), MI.getOperand(0).getReg()) .addReg(Reg); } else { // If the register we are reading has an implicit def, then that // means it was written by an indirect register access (i.e. An // instruction that uses indirect addressing. BuildMI(MBB, I, MBB.findDebugLoc(I), TII->get(AMDGPU::COPY), MI.getOperand(0).getReg()) .addReg(AddrReg) .addReg(Reg, RegState::Implicit); } } else { // Indirect register access // Note on REQ_SEQUENCE instructons: You can't actually use the register // it defines unless you have an instruction that takes the defined // register class as an operand. MachineInstrBuilder Sequence = BuildMI(MBB, I, MBB.findDebugLoc(I), TII->get(AMDGPU::REG_SEQUENCE), IndirectReg); for (int i = IndirectBegin; i <= IndirectEnd; ++i) { unsigned Addr = TII->calculateIndirectAddress(i, Channel); if (LiveAddressRegisterMap.find(Addr) == LiveAddressRegisterMap.end()) { continue; } unsigned Reg = LiveAddressRegisterMap[Addr]; // We only need to use REG_SEQUENCE for explicit defs, since the // register coalescer won't do anything with the implicit defs. if (!regHasExplicitDef(MRI, Reg)) { continue; } // Insert a REQ_SEQUENCE instruction to force the register allocator // to allocate the virtual register to the correct physical register. Sequence.addReg(LiveAddressRegisterMap[Addr]); Sequence.addImm(TII->getRegisterInfo().getIndirectSubReg(Addr)); } MachineInstrBuilder Mov = TII->buildIndirectRead(BB, I, MI.getOperand(0).getReg(), // Value Address, MI.getOperand(1).getReg()); // Offset Mov.addReg(IndirectReg, RegState::Implicit | RegState::Kill); Mov.addReg(LiveAddressRegisterMap[Address], RegState::Implicit); } MI.eraseFromParent(); } } return false; }
bool Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI, const ReduceEntry &Entry) { if (ReduceLimitLdSt != -1 && ((int)NumLdSts >= ReduceLimitLdSt)) return false; unsigned Scale = 1; bool HasImmOffset = false; bool HasShift = false; bool HasOffReg = true; bool isLdStMul = false; unsigned Opc = Entry.NarrowOpc1; unsigned OpNum = 3; // First 'rest' of operands. uint8_t ImmLimit = Entry.Imm1Limit; switch (Entry.WideOpc) { default: llvm_unreachable("Unexpected Thumb2 load / store opcode!"); case ARM::t2LDRi12: case ARM::t2STRi12: if (MI->getOperand(1).getReg() == ARM::SP) { Opc = Entry.NarrowOpc2; ImmLimit = Entry.Imm2Limit; HasOffReg = false; } Scale = 4; HasImmOffset = true; HasOffReg = false; break; case ARM::t2LDRBi12: case ARM::t2STRBi12: HasImmOffset = true; HasOffReg = false; break; case ARM::t2LDRHi12: case ARM::t2STRHi12: Scale = 2; HasImmOffset = true; HasOffReg = false; break; case ARM::t2LDRs: case ARM::t2LDRBs: case ARM::t2LDRHs: case ARM::t2LDRSBs: case ARM::t2LDRSHs: case ARM::t2STRs: case ARM::t2STRBs: case ARM::t2STRHs: HasShift = true; OpNum = 4; break; case ARM::t2LDMIA: case ARM::t2LDMDB: { unsigned BaseReg = MI->getOperand(0).getReg(); if (!isARMLowRegister(BaseReg) || Entry.WideOpc != ARM::t2LDMIA) return false; // For the non-writeback version (this one), the base register must be // one of the registers being loaded. bool isOK = false; for (unsigned i = 4; i < MI->getNumOperands(); ++i) { if (MI->getOperand(i).getReg() == BaseReg) { isOK = true; break; } } if (!isOK) return false; OpNum = 0; isLdStMul = true; break; } case ARM::t2LDMIA_RET: { unsigned BaseReg = MI->getOperand(1).getReg(); if (BaseReg != ARM::SP) return false; Opc = Entry.NarrowOpc2; // tPOP_RET OpNum = 2; isLdStMul = true; break; } case ARM::t2LDMIA_UPD: case ARM::t2LDMDB_UPD: case ARM::t2STMIA_UPD: case ARM::t2STMDB_UPD: { OpNum = 0; unsigned BaseReg = MI->getOperand(1).getReg(); if (BaseReg == ARM::SP && (Entry.WideOpc == ARM::t2LDMIA_UPD || Entry.WideOpc == ARM::t2STMDB_UPD)) { Opc = Entry.NarrowOpc2; // tPOP or tPUSH OpNum = 2; } else if (!isARMLowRegister(BaseReg) || (Entry.WideOpc != ARM::t2LDMIA_UPD && Entry.WideOpc != ARM::t2STMIA_UPD)) { return false; } isLdStMul = true; break; } } unsigned OffsetReg = 0; bool OffsetKill = false; if (HasShift) { OffsetReg = MI->getOperand(2).getReg(); OffsetKill = MI->getOperand(2).isKill(); if (MI->getOperand(3).getImm()) // Thumb1 addressing mode doesn't support shift. return false; } unsigned OffsetImm = 0; if (HasImmOffset) { OffsetImm = MI->getOperand(2).getImm(); unsigned MaxOffset = ((1 << ImmLimit) - 1) * Scale; if ((OffsetImm & (Scale - 1)) || OffsetImm > MaxOffset) // Make sure the immediate field fits. return false; } // Add the 16-bit load / store instruction. DebugLoc dl = MI->getDebugLoc(); MachineInstrBuilder MIB = BuildMI(MBB, MI, dl, TII->get(Opc)); if (!isLdStMul) { MIB.addOperand(MI->getOperand(0)); MIB.addOperand(MI->getOperand(1)); if (HasImmOffset) MIB.addImm(OffsetImm / Scale); assert((!HasShift || OffsetReg) && "Invalid so_reg load / store address!"); if (HasOffReg) MIB.addReg(OffsetReg, getKillRegState(OffsetKill)); } // Transfer the rest of operands. for (unsigned e = MI->getNumOperands(); OpNum != e; ++OpNum) MIB.addOperand(MI->getOperand(OpNum)); // Transfer memoperands. MIB->setMemRefs(MI->memoperands_begin(), MI->memoperands_end()); // Transfer MI flags. MIB.setMIFlags(MI->getFlags()); DEBUG(errs() << "Converted 32-bit: " << *MI << " to 16-bit: " << *MIB); MBB.erase_instr(MI); ++NumLdSts; return true; }
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; }
/// AddOperand - Add the specified operand to the specified machine instr. II /// specifies the instruction information for the node, and IIOpNum is the /// operand number (in the II) that we are adding. void InstrEmitter::AddOperand(MachineInstrBuilder &MIB, SDValue Op, unsigned IIOpNum, const MCInstrDesc *II, DenseMap<SDValue, unsigned> &VRBaseMap, bool IsDebug, bool IsClone, bool IsCloned) { if (Op.isMachineOpcode()) { AddRegisterOperand(MIB, Op, IIOpNum, II, VRBaseMap, IsDebug, IsClone, IsCloned); } else if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) { MIB.addImm(C->getSExtValue()); } else if (ConstantFPSDNode *F = dyn_cast<ConstantFPSDNode>(Op)) { MIB.addFPImm(F->getConstantFPValue()); } else if (RegisterSDNode *R = dyn_cast<RegisterSDNode>(Op)) { unsigned VReg = R->getReg(); MVT OpVT = Op.getSimpleValueType(); const TargetRegisterClass *OpRC = TLI->isTypeLegal(OpVT) ? TLI->getRegClassFor(OpVT) : nullptr; const TargetRegisterClass *IIRC = II ? TRI->getAllocatableClass(TII->getRegClass(*II, IIOpNum, TRI, *MF)) : nullptr; if (OpRC && IIRC && OpRC != IIRC && TargetRegisterInfo::isVirtualRegister(VReg)) { unsigned NewVReg = MRI->createVirtualRegister(IIRC); BuildMI(*MBB, InsertPos, Op.getNode()->getDebugLoc(), TII->get(TargetOpcode::COPY), NewVReg).addReg(VReg); VReg = NewVReg; } // Turn additional physreg operands into implicit uses on non-variadic // instructions. This is used by call and return instructions passing // arguments in registers. bool Imp = II && (IIOpNum >= II->getNumOperands() && !II->isVariadic()); MIB.addReg(VReg, getImplRegState(Imp)); } else if (RegisterMaskSDNode *RM = dyn_cast<RegisterMaskSDNode>(Op)) { MIB.addRegMask(RM->getRegMask()); } else if (GlobalAddressSDNode *TGA = dyn_cast<GlobalAddressSDNode>(Op)) { MIB.addGlobalAddress(TGA->getGlobal(), TGA->getOffset(), TGA->getTargetFlags()); } else if (BasicBlockSDNode *BBNode = dyn_cast<BasicBlockSDNode>(Op)) { MIB.addMBB(BBNode->getBasicBlock()); } else if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Op)) { MIB.addFrameIndex(FI->getIndex()); } else if (JumpTableSDNode *JT = dyn_cast<JumpTableSDNode>(Op)) { MIB.addJumpTableIndex(JT->getIndex(), JT->getTargetFlags()); } else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Op)) { int Offset = CP->getOffset(); unsigned Align = CP->getAlignment(); Type *Type = CP->getType(); // MachineConstantPool wants an explicit alignment. if (Align == 0) { Align = MF->getDataLayout().getPrefTypeAlignment(Type); if (Align == 0) { // Alignment of vector types. FIXME! Align = MF->getDataLayout().getTypeAllocSize(Type); } } unsigned Idx; MachineConstantPool *MCP = MF->getConstantPool(); if (CP->isMachineConstantPoolEntry()) Idx = MCP->getConstantPoolIndex(CP->getMachineCPVal(), Align); else Idx = MCP->getConstantPoolIndex(CP->getConstVal(), Align); MIB.addConstantPoolIndex(Idx, Offset, CP->getTargetFlags()); } else if (ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Op)) { MIB.addExternalSymbol(ES->getSymbol(), ES->getTargetFlags()); } else if (auto *SymNode = dyn_cast<MCSymbolSDNode>(Op)) { MIB.addSym(SymNode->getMCSymbol()); } else if (BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(Op)) { MIB.addBlockAddress(BA->getBlockAddress(), BA->getOffset(), BA->getTargetFlags()); } else if (TargetIndexSDNode *TI = dyn_cast<TargetIndexSDNode>(Op)) { MIB.addTargetIndex(TI->getIndex(), TI->getOffset(), TI->getTargetFlags()); } else { assert(Op.getValueType() != MVT::Other && Op.getValueType() != MVT::Glue && "Chain and glue operands should occur at end of operand list!"); AddRegisterOperand(MIB, Op, IIOpNum, II, VRBaseMap, IsDebug, IsClone, IsCloned); } }
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; }
/// EmitSubregNode - Generate machine code for subreg nodes. /// void InstrEmitter::EmitSubregNode(SDNode *Node, DenseMap<SDValue, unsigned> &VRBaseMap, bool IsClone, bool IsCloned) { unsigned VRBase = 0; unsigned Opc = Node->getMachineOpcode(); // If the node is only used by a CopyToReg and the dest reg is a vreg, use // the CopyToReg'd destination register instead of creating a new vreg. for (SDNode *User : Node->uses()) { if (User->getOpcode() == ISD::CopyToReg && User->getOperand(2).getNode() == Node) { unsigned DestReg = cast<RegisterSDNode>(User->getOperand(1))->getReg(); if (TargetRegisterInfo::isVirtualRegister(DestReg)) { VRBase = DestReg; break; } } } if (Opc == TargetOpcode::EXTRACT_SUBREG) { // EXTRACT_SUBREG is lowered as %dst = COPY %src:sub. There are no // constraints on the %dst register, COPY can target all legal register // classes. unsigned SubIdx = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue(); const TargetRegisterClass *TRC = TLI->getRegClassFor(Node->getSimpleValueType(0)); unsigned Reg; MachineInstr *DefMI; RegisterSDNode *R = dyn_cast<RegisterSDNode>(Node->getOperand(0)); if (R && TargetRegisterInfo::isPhysicalRegister(R->getReg())) { Reg = R->getReg(); DefMI = nullptr; } else { Reg = getVR(Node->getOperand(0), VRBaseMap); DefMI = MRI->getVRegDef(Reg); } unsigned SrcReg, DstReg, DefSubIdx; if (DefMI && TII->isCoalescableExtInstr(*DefMI, SrcReg, DstReg, DefSubIdx) && SubIdx == DefSubIdx && TRC == MRI->getRegClass(SrcReg)) { // Optimize these: // r1025 = s/zext r1024, 4 // r1026 = extract_subreg r1025, 4 // to a copy // r1026 = copy r1024 VRBase = MRI->createVirtualRegister(TRC); BuildMI(*MBB, InsertPos, Node->getDebugLoc(), TII->get(TargetOpcode::COPY), VRBase).addReg(SrcReg); MRI->clearKillFlags(SrcReg); } else { // Reg may not support a SubIdx sub-register, and we may need to // constrain its register class or issue a COPY to a compatible register // class. if (TargetRegisterInfo::isVirtualRegister(Reg)) Reg = ConstrainForSubReg(Reg, SubIdx, Node->getOperand(0).getSimpleValueType(), Node->getDebugLoc()); // Create the destreg if it is missing. if (VRBase == 0) VRBase = MRI->createVirtualRegister(TRC); // Create the extract_subreg machine instruction. MachineInstrBuilder CopyMI = BuildMI(*MBB, InsertPos, Node->getDebugLoc(), TII->get(TargetOpcode::COPY), VRBase); if (TargetRegisterInfo::isVirtualRegister(Reg)) CopyMI.addReg(Reg, 0, SubIdx); else CopyMI.addReg(TRI->getSubReg(Reg, SubIdx)); } } else if (Opc == TargetOpcode::INSERT_SUBREG || Opc == TargetOpcode::SUBREG_TO_REG) { SDValue N0 = Node->getOperand(0); SDValue N1 = Node->getOperand(1); SDValue N2 = Node->getOperand(2); unsigned SubIdx = cast<ConstantSDNode>(N2)->getZExtValue(); // Figure out the register class to create for the destreg. It should be // the largest legal register class supporting SubIdx sub-registers. // RegisterCoalescer will constrain it further if it decides to eliminate // the INSERT_SUBREG instruction. // // %dst = INSERT_SUBREG %src, %sub, SubIdx // // is lowered by TwoAddressInstructionPass to: // // %dst = COPY %src // %dst:SubIdx = COPY %sub // // There is no constraint on the %src register class. // const TargetRegisterClass *SRC = TLI->getRegClassFor(Node->getSimpleValueType(0)); SRC = TRI->getSubClassWithSubReg(SRC, SubIdx); assert(SRC && "No register class supports VT and SubIdx for INSERT_SUBREG"); if (VRBase == 0 || !SRC->hasSubClassEq(MRI->getRegClass(VRBase))) VRBase = MRI->createVirtualRegister(SRC); // Create the insert_subreg or subreg_to_reg machine instruction. MachineInstrBuilder MIB = BuildMI(*MF, Node->getDebugLoc(), TII->get(Opc), VRBase); // If creating a subreg_to_reg, then the first input operand // is an implicit value immediate, otherwise it's a register if (Opc == TargetOpcode::SUBREG_TO_REG) { const ConstantSDNode *SD = cast<ConstantSDNode>(N0); MIB.addImm(SD->getZExtValue()); } else AddOperand(MIB, N0, 0, nullptr, VRBaseMap, /*IsDebug=*/false, IsClone, IsCloned); // Add the subregister being inserted AddOperand(MIB, N1, 0, nullptr, VRBaseMap, /*IsDebug=*/false, IsClone, IsCloned); MIB.addImm(SubIdx); MBB->insert(InsertPos, MIB); } else llvm_unreachable("Node is not insert_subreg, extract_subreg, or subreg_to_reg"); SDValue Op(Node, 0); bool isNew = VRBaseMap.insert(std::make_pair(Op, VRBase)).second; (void)isNew; // Silence compiler warning. assert(isNew && "Node emitted out of order - early"); }