static bool selectUnmergeValues(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI) { assert(TII.getSubtarget().hasVFP2() && "Can't select unmerge without VFP"); // We only support G_UNMERGE_VALUES as a way to break up one DPR into two // GPRs. unsigned VReg0 = MIB->getOperand(0).getReg(); (void)VReg0; assert(MRI.getType(VReg0).getSizeInBits() == 32 && RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::GPRRegBankID && "Unsupported operand for G_UNMERGE_VALUES"); unsigned VReg1 = MIB->getOperand(1).getReg(); (void)VReg1; assert(MRI.getType(VReg1).getSizeInBits() == 32 && RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID && "Unsupported operand for G_UNMERGE_VALUES"); unsigned VReg2 = MIB->getOperand(2).getReg(); (void)VReg2; assert(MRI.getType(VReg2).getSizeInBits() == 64 && RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::FPRRegBankID && "Unsupported operand for G_UNMERGE_VALUES"); MIB->setDesc(TII.get(ARM::VMOVRRD)); MIB.add(predOps(ARMCC::AL)); return true; }
void MipsSEInstrInfo::expandDPLoadStore(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned OpcD, unsigned OpcS) const { // If NoDPLoadStore is false, just change the opcode. if (!NoDPLoadStore) { genInstrWithNewOpc(OpcD, I); return; } // Expand a double precision FP load or store to two single precision // instructions. const TargetRegisterInfo &TRI = getRegisterInfo(); const MachineOperand &ValReg = I->getOperand(0); unsigned LoReg = TRI.getSubReg(ValReg.getReg(), Mips::sub_fpeven); unsigned HiReg = TRI.getSubReg(ValReg.getReg(), Mips::sub_fpodd); if (!TM.getSubtarget<MipsSubtarget>().isLittle()) std::swap(LoReg, HiReg); // Create an instruction which loads from or stores to the lower memory // address. MachineInstrBuilder MIB = genInstrWithNewOpc(OpcS, I); MIB->getOperand(0).setReg(LoReg); // Create an instruction which loads from or stores to the higher memory // address. MIB = genInstrWithNewOpc(OpcS, I); MIB->getOperand(0).setReg(HiReg); fixDisp(MIB->getOperand(2)); }
/// AddRegisterOperand - Add the specified register as an operand to the /// specified machine instr. Insert register copies if the register is /// not in the required register class. void InstrEmitter::AddRegisterOperand(MachineInstrBuilder &MIB, SDValue Op, unsigned IIOpNum, const MCInstrDesc *II, DenseMap<SDValue, unsigned> &VRBaseMap, bool IsDebug, bool IsClone, bool IsCloned) { assert(Op.getValueType() != MVT::Other && Op.getValueType() != MVT::Glue && "Chain and glue operands should occur at end of operand list!"); // Get/emit the operand. unsigned VReg = getVR(Op, VRBaseMap); assert(TargetRegisterInfo::isVirtualRegister(VReg) && "Not a vreg?"); const MCInstrDesc &MCID = MIB->getDesc(); bool isOptDef = IIOpNum < MCID.getNumOperands() && MCID.OpInfo[IIOpNum].isOptionalDef(); // If the instruction requires a register in a different class, create // a new virtual register and copy the value into it, but first attempt to // shrink VReg's register class within reason. For example, if VReg == GR32 // and II requires a GR32_NOSP, just constrain VReg to GR32_NOSP. if (II) { const TargetRegisterClass *DstRC = nullptr; if (IIOpNum < II->getNumOperands()) DstRC = TRI->getAllocatableClass(TII->getRegClass(*II,IIOpNum,TRI,*MF)); if (DstRC && !MRI->constrainRegClass(VReg, DstRC, MinRCSize)) { unsigned NewVReg = MRI->createVirtualRegister(DstRC); BuildMI(*MBB, InsertPos, Op.getNode()->getDebugLoc(), TII->get(TargetOpcode::COPY), NewVReg).addReg(VReg); VReg = NewVReg; } } // If this value has only one use, that use is a kill. This is a // conservative approximation. InstrEmitter does trivial coalescing // with CopyFromReg nodes, so don't emit kill flags for them. // Avoid kill flags on Schedule cloned nodes, since there will be // multiple uses. // Tied operands are never killed, so we need to check that. And that // means we need to determine the index of the operand. bool isKill = Op.hasOneUse() && Op.getNode()->getOpcode() != ISD::CopyFromReg && !IsDebug && !(IsClone || IsCloned); if (isKill) { unsigned Idx = MIB->getNumOperands(); while (Idx > 0 && MIB->getOperand(Idx-1).isReg() && MIB->getOperand(Idx-1).isImplicit()) --Idx; bool isTied = MCID.getOperandConstraint(Idx, MCOI::TIED_TO) != -1; if (isTied) isKill = false; } MIB.addReg(VReg, getDefRegState(isOptDef) | getKillRegState(isKill) | getDebugRegState(IsDebug)); }
bool ARMInstructionSelector::selectCmp(CmpConstants Helper, MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const { const InsertInfo I(MIB); auto ResReg = MIB->getOperand(0).getReg(); if (!validReg(MRI, ResReg, 1, ARM::GPRRegBankID)) return false; auto Cond = static_cast<CmpInst::Predicate>(MIB->getOperand(1).getPredicate()); if (Cond == CmpInst::FCMP_TRUE || Cond == CmpInst::FCMP_FALSE) { putConstant(I, ResReg, Cond == CmpInst::FCMP_TRUE ? 1 : 0); MIB->eraseFromParent(); return true; } auto LHSReg = MIB->getOperand(2).getReg(); auto RHSReg = MIB->getOperand(3).getReg(); if (!validOpRegPair(MRI, LHSReg, RHSReg, Helper.OperandSize, Helper.OperandRegBankID)) return false; auto ARMConds = getComparePreds(Cond); auto ZeroReg = MRI.createVirtualRegister(&ARM::GPRRegClass); putConstant(I, ZeroReg, 0); if (ARMConds.second == ARMCC::AL) { // Simple case, we only need one comparison and we're done. if (!insertComparison(Helper, I, ResReg, ARMConds.first, LHSReg, RHSReg, ZeroReg)) return false; } else { // Not so simple, we need two successive comparisons. auto IntermediateRes = MRI.createVirtualRegister(&ARM::GPRRegClass); if (!insertComparison(Helper, I, IntermediateRes, ARMConds.first, LHSReg, RHSReg, ZeroReg)) return false; if (!insertComparison(Helper, I, ResReg, ARMConds.second, LHSReg, RHSReg, IntermediateRes)) return false; } MIB->eraseFromParent(); return true; }
bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const { if (TII.getSubtarget().isROPI() || TII.getSubtarget().isRWPI()) { DEBUG(dbgs() << "ROPI and RWPI not supported yet\n"); return false; } if (TM.isPositionIndependent()) { DEBUG(dbgs() << "PIC not supported yet\n"); return false; } auto GV = MIB->getOperand(1).getGlobal(); if (GV->isThreadLocal()) { DEBUG(dbgs() << "TLS variables not supported yet\n"); return false; } auto &MBB = *MIB->getParent(); auto &MF = *MBB.getParent(); auto ObjectFormat = TII.getSubtarget().getTargetTriple().getObjectFormat(); bool UseMovt = TII.getSubtarget().useMovt(MF); if (ObjectFormat == Triple::ELF) { if (UseMovt) { MIB->setDesc(TII.get(ARM::MOVi32imm)); } else { // Load the global's address from the constant pool. MIB->setDesc(TII.get(ARM::LDRi12)); MIB->RemoveOperand(1); unsigned Alignment = 4; MIB.addConstantPoolIndex( MF.getConstantPool()->getConstantPoolIndex(GV, Alignment), /* Offset */ 0, /* TargetFlags */ 0) .addMemOperand(MF.getMachineMemOperand( MachinePointerInfo::getConstantPool(MF), MachineMemOperand::MOLoad, TM.getPointerSize(), Alignment)) .addImm(0) .add(predOps(ARMCC::AL)); } } else if (ObjectFormat == Triple::MachO) { if (UseMovt) MIB->setDesc(TII.get(ARM::MOVi32imm)); else MIB->setDesc(TII.get(ARM::LDRLIT_ga_abs)); } else { DEBUG(dbgs() << "Object format not supported yet\n"); return false; } return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI); }
bool ARMInstructionSelector::selectSelect(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const { auto &MBB = *MIB->getParent(); auto InsertBefore = std::next(MIB->getIterator()); auto &DbgLoc = MIB->getDebugLoc(); // Compare the condition to 0. auto CondReg = MIB->getOperand(1).getReg(); assert(validReg(MRI, CondReg, 1, ARM::GPRRegBankID) && "Unsupported types for select operation"); auto CmpI = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(ARM::CMPri)) .addUse(CondReg) .addImm(0) .add(predOps(ARMCC::AL)); if (!constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI)) return false; // Move a value into the result register based on the result of the // comparison. auto ResReg = MIB->getOperand(0).getReg(); auto TrueReg = MIB->getOperand(2).getReg(); auto FalseReg = MIB->getOperand(3).getReg(); assert(validOpRegPair(MRI, ResReg, TrueReg, 32, ARM::GPRRegBankID) && validOpRegPair(MRI, TrueReg, FalseReg, 32, ARM::GPRRegBankID) && "Unsupported types for select operation"); auto Mov1I = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(ARM::MOVCCr)) .addDef(ResReg) .addUse(TrueReg) .addUse(FalseReg) .add(predOps(ARMCC::EQ, ARM::CPSR)); if (!constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI)) return false; MIB->eraseFromParent(); return true; }
bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const { if ((STI.isROPI() || STI.isRWPI()) && !STI.isTargetELF()) { LLVM_DEBUG(dbgs() << "ROPI and RWPI only supported for ELF\n"); return false; } auto GV = MIB->getOperand(1).getGlobal(); if (GV->isThreadLocal()) { LLVM_DEBUG(dbgs() << "TLS variables not supported yet\n"); return false; } auto &MBB = *MIB->getParent(); auto &MF = *MBB.getParent(); bool UseMovt = STI.useMovt(MF); unsigned Size = TM.getPointerSize(0); unsigned Alignment = 4; auto addOpsForConstantPoolLoad = [&MF, Alignment, Size](MachineInstrBuilder &MIB, const GlobalValue *GV, bool IsSBREL) { assert(MIB->getOpcode() == ARM::LDRi12 && "Unsupported instruction"); auto ConstPool = MF.getConstantPool(); auto CPIndex = // For SB relative entries we need a target-specific constant pool. // Otherwise, just use a regular constant pool entry. IsSBREL ? ConstPool->getConstantPoolIndex( ARMConstantPoolConstant::Create(GV, ARMCP::SBREL), Alignment) : ConstPool->getConstantPoolIndex(GV, Alignment); MIB.addConstantPoolIndex(CPIndex, /*Offset*/ 0, /*TargetFlags*/ 0) .addMemOperand( MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF), MachineMemOperand::MOLoad, Size, Alignment)) .addImm(0) .add(predOps(ARMCC::AL)); }; if (TM.isPositionIndependent()) { bool Indirect = STI.isGVIndirectSymbol(GV); // FIXME: Taking advantage of MOVT for ELF is pretty involved, so we don't // support it yet. See PR28229. unsigned Opc = UseMovt && !STI.isTargetELF() ? (Indirect ? ARM::MOV_ga_pcrel_ldr : ARM::MOV_ga_pcrel) : (Indirect ? ARM::LDRLIT_ga_pcrel_ldr : ARM::LDRLIT_ga_pcrel); MIB->setDesc(TII.get(Opc)); int TargetFlags = ARMII::MO_NO_FLAG; if (STI.isTargetDarwin()) TargetFlags |= ARMII::MO_NONLAZY; if (STI.isGVInGOT(GV)) TargetFlags |= ARMII::MO_GOT; MIB->getOperand(1).setTargetFlags(TargetFlags); if (Indirect) MIB.addMemOperand(MF.getMachineMemOperand( MachinePointerInfo::getGOT(MF), MachineMemOperand::MOLoad, TM.getProgramPointerSize(), Alignment)); return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI); } bool isReadOnly = STI.getTargetLowering()->isReadOnly(GV); if (STI.isROPI() && isReadOnly) { unsigned Opc = UseMovt ? ARM::MOV_ga_pcrel : ARM::LDRLIT_ga_pcrel; MIB->setDesc(TII.get(Opc)); return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI); } if (STI.isRWPI() && !isReadOnly) { auto Offset = MRI.createVirtualRegister(&ARM::GPRRegClass); MachineInstrBuilder OffsetMIB; if (UseMovt) { OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(), TII.get(ARM::MOVi32imm), Offset); OffsetMIB.addGlobalAddress(GV, /*Offset*/ 0, ARMII::MO_SBREL); } else { // Load the offset from the constant pool. OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(), TII.get(ARM::LDRi12), Offset); addOpsForConstantPoolLoad(OffsetMIB, GV, /*IsSBREL*/ true); } if (!constrainSelectedInstRegOperands(*OffsetMIB, TII, TRI, RBI)) return false; // Add the offset to the SB register. MIB->setDesc(TII.get(ARM::ADDrr)); MIB->RemoveOperand(1); MIB.addReg(ARM::R9) // FIXME: don't hardcode R9 .addReg(Offset) .add(predOps(ARMCC::AL)) .add(condCodeOp()); return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI); } if (STI.isTargetELF()) { if (UseMovt) { MIB->setDesc(TII.get(ARM::MOVi32imm)); } else { // Load the global's address from the constant pool. MIB->setDesc(TII.get(ARM::LDRi12)); MIB->RemoveOperand(1); addOpsForConstantPoolLoad(MIB, GV, /*IsSBREL*/ false); } } else if (STI.isTargetMachO()) { if (UseMovt) MIB->setDesc(TII.get(ARM::MOVi32imm)); else MIB->setDesc(TII.get(ARM::LDRLIT_ga_abs)); } else { LLVM_DEBUG(dbgs() << "Object format not supported yet\n"); return false; } return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI); }
MachineBasicBlock::iterator AArch64LoadStoreOpt::mergePairedInsns(MachineBasicBlock::iterator I, MachineBasicBlock::iterator Paired, const LdStPairFlags &Flags) { MachineBasicBlock::iterator NextI = I; ++NextI; // If NextI is the second of the two instructions to be merged, we need // to skip one further. Either way we merge will invalidate the iterator, // and we don't need to scan the new instruction, as it's a pairwise // instruction, which we're not considering for further action anyway. if (NextI == Paired) ++NextI; int SExtIdx = Flags.getSExtIdx(); unsigned Opc = SExtIdx == -1 ? I->getOpcode() : getMatchingNonSExtOpcode(I->getOpcode()); bool IsUnscaled = isUnscaledLdst(Opc); int OffsetStride = IsUnscaled && EnableAArch64UnscaledMemOp ? getMemSize(I) : 1; bool MergeForward = Flags.getMergeForward(); unsigned NewOpc = getMatchingPairOpcode(Opc); // Insert our new paired instruction after whichever of the paired // instructions MergeForward indicates. MachineBasicBlock::iterator InsertionPoint = MergeForward ? Paired : I; // Also based on MergeForward is from where we copy the base register operand // so we get the flags compatible with the input code. MachineOperand &BaseRegOp = MergeForward ? Paired->getOperand(1) : I->getOperand(1); // Which register is Rt and which is Rt2 depends on the offset order. MachineInstr *RtMI, *Rt2MI; if (I->getOperand(2).getImm() == Paired->getOperand(2).getImm() + OffsetStride) { RtMI = Paired; Rt2MI = I; // Here we swapped the assumption made for SExtIdx. // I.e., we turn ldp I, Paired into ldp Paired, I. // Update the index accordingly. if (SExtIdx != -1) SExtIdx = (SExtIdx + 1) % 2; } else { RtMI = I; Rt2MI = Paired; } // Handle Unscaled int OffsetImm = RtMI->getOperand(2).getImm(); if (IsUnscaled && EnableAArch64UnscaledMemOp) OffsetImm /= OffsetStride; // Construct the new instruction. MachineInstrBuilder MIB = BuildMI(*I->getParent(), InsertionPoint, I->getDebugLoc(), TII->get(NewOpc)) .addOperand(RtMI->getOperand(0)) .addOperand(Rt2MI->getOperand(0)) .addOperand(BaseRegOp) .addImm(OffsetImm); (void)MIB; // FIXME: Do we need/want to copy the mem operands from the source // instructions? Probably. What uses them after this? DEBUG(dbgs() << "Creating pair load/store. Replacing instructions:\n "); DEBUG(I->print(dbgs())); DEBUG(dbgs() << " "); DEBUG(Paired->print(dbgs())); DEBUG(dbgs() << " with instruction:\n "); if (SExtIdx != -1) { // Generate the sign extension for the proper result of the ldp. // I.e., with X1, that would be: // %W1<def> = KILL %W1, %X1<imp-def> // %X1<def> = SBFMXri %X1<kill>, 0, 31 MachineOperand &DstMO = MIB->getOperand(SExtIdx); // Right now, DstMO has the extended register, since it comes from an // extended opcode. unsigned DstRegX = DstMO.getReg(); // Get the W variant of that register. unsigned DstRegW = TRI->getSubReg(DstRegX, AArch64::sub_32); // Update the result of LDP to use the W instead of the X variant. DstMO.setReg(DstRegW); DEBUG(((MachineInstr *)MIB)->print(dbgs())); DEBUG(dbgs() << "\n"); // Make the machine verifier happy by providing a definition for // the X register. // Insert this definition right after the generated LDP, i.e., before // InsertionPoint. MachineInstrBuilder MIBKill = BuildMI(*I->getParent(), InsertionPoint, I->getDebugLoc(), TII->get(TargetOpcode::KILL), DstRegW) .addReg(DstRegW) .addReg(DstRegX, RegState::Define); MIBKill->getOperand(2).setImplicit(); // Create the sign extension. MachineInstrBuilder MIBSXTW = BuildMI(*I->getParent(), InsertionPoint, I->getDebugLoc(), TII->get(AArch64::SBFMXri), DstRegX) .addReg(DstRegX) .addImm(0) .addImm(31); (void)MIBSXTW; DEBUG(dbgs() << " Extend operand:\n "); DEBUG(((MachineInstr *)MIBSXTW)->print(dbgs())); DEBUG(dbgs() << "\n"); } else { DEBUG(((MachineInstr *)MIB)->print(dbgs())); DEBUG(dbgs() << "\n"); } // Erase the old instructions. I->eraseFromParent(); Paired->eraseFromParent(); return NextI; }
/// GetValueInMiddleOfBlock - Construct SSA form, materializing a value that /// is live in the middle of the specified block. /// /// GetValueInMiddleOfBlock is the same as GetValueAtEndOfBlock except in one /// important case: if there is a definition of the rewritten value after the /// 'use' in BB. Consider code like this: /// /// X1 = ... /// SomeBB: /// use(X) /// X2 = ... /// br Cond, SomeBB, OutBB /// /// In this case, there are two values (X1 and X2) added to the AvailableVals /// set by the client of the rewriter, and those values are both live out of /// their respective blocks. However, the use of X happens in the *middle* of /// a block. Because of this, we need to insert a new PHI node in SomeBB to /// merge the appropriate values, and this value isn't live out of the block. /// unsigned MachineSSAUpdater::GetValueInMiddleOfBlock(MachineBasicBlock *BB) { // If there is no definition of the renamed variable in this block, just use // GetValueAtEndOfBlock to do our work. if (!HasValueForBlock(BB)) return GetValueAtEndOfBlockInternal(BB); // If there are no predecessors, just return undef. if (BB->pred_empty()) { // Insert an implicit_def to represent an undef value. MachineInstr *NewDef = InsertNewDef(TargetOpcode::IMPLICIT_DEF, BB, BB->getFirstTerminator(), VRC, MRI, TII); return NewDef->getOperand(0).getReg(); } // Otherwise, we have the hard case. Get the live-in values for each // predecessor. SmallVector<std::pair<MachineBasicBlock*, unsigned>, 8> PredValues; unsigned SingularValue = 0; bool isFirstPred = true; for (MachineBasicBlock::pred_iterator PI = BB->pred_begin(), E = BB->pred_end(); PI != E; ++PI) { MachineBasicBlock *PredBB = *PI; unsigned PredVal = GetValueAtEndOfBlockInternal(PredBB); PredValues.push_back(std::make_pair(PredBB, PredVal)); // Compute SingularValue. if (isFirstPred) { SingularValue = PredVal; isFirstPred = false; } else if (PredVal != SingularValue) SingularValue = 0; } // Otherwise, if all the merged values are the same, just use it. if (SingularValue != 0) return SingularValue; // If an identical PHI is already in BB, just reuse it. unsigned DupPHI = LookForIdenticalPHI(BB, PredValues); if (DupPHI) return DupPHI; // Otherwise, we do need a PHI: insert one now. MachineBasicBlock::iterator Loc = BB->empty() ? BB->end() : BB->begin(); MachineInstrBuilder InsertedPHI = InsertNewDef(TargetOpcode::PHI, BB, Loc, VRC, MRI, TII); // Fill in all the predecessors of the PHI. for (unsigned i = 0, e = PredValues.size(); i != e; ++i) InsertedPHI.addReg(PredValues[i].second).addMBB(PredValues[i].first); // See if the PHI node can be merged to a single value. This can happen in // loop cases when we get a PHI of itself and one other value. if (unsigned ConstVal = InsertedPHI->isConstantValuePHI()) { InsertedPHI->eraseFromParent(); return ConstVal; } // If the client wants to know about all new instructions, tell it. if (InsertedPHIs) InsertedPHIs->push_back(InsertedPHI); DEBUG(dbgs() << " Inserted PHI: " << *InsertedPHI << "\n"); return InsertedPHI->getOperand(0).getReg(); }