diff options
Diffstat (limited to 'llvm/lib/CodeGen/GlobalISel')
| -rw-r--r-- | llvm/lib/CodeGen/GlobalISel/CallLowering.cpp | 4 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp | 87 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp | 11 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 102 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp | 67 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp | 15 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/GlobalISel/LegalityPredicates.cpp | 20 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/GlobalISel/Legalizer.cpp | 4 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp | 53 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp | 6 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp | 9 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/GlobalISel/Utils.cpp | 27 |
12 files changed, 316 insertions, 89 deletions
diff --git a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp index 7be7468..e2ed45e 100644 --- a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp @@ -196,6 +196,10 @@ bool CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, const CallBase &CB, assert(Info.CFIType->getType()->isIntegerTy(32) && "Invalid CFI type"); } + if (auto Bundle = CB.getOperandBundle(LLVMContext::OB_deactivation_symbol)) { + Info.DeactivationSymbol = cast<GlobalValue>(Bundle->Inputs[0]); + } + Info.CB = &CB; Info.KnownCallees = CB.getMetadata(LLVMContext::MD_callees); Info.CallConv = CallConv; diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp index ec4d13f..f0fbe01 100644 --- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp @@ -3463,6 +3463,91 @@ static bool isConstValidTrue(const TargetLowering &TLI, unsigned ScalarSizeBits, isConstTrueVal(TLI, Cst, IsVector, IsFP); } +// This pattern aims to match the following shape to avoid extra mov +// instructions +// G_BUILD_VECTOR( +// G_UNMERGE_VALUES(src, 0) +// G_UNMERGE_VALUES(src, 1) +// G_IMPLICIT_DEF +// G_IMPLICIT_DEF +// ) +// -> +// G_CONCAT_VECTORS( +// src, +// undef +// ) +bool CombinerHelper::matchCombineBuildUnmerge(MachineInstr &MI, + MachineRegisterInfo &MRI, + Register &UnmergeSrc) const { + auto &BV = cast<GBuildVector>(MI); + + unsigned BuildUseCount = BV.getNumSources(); + if (BuildUseCount % 2 != 0) + return false; + + unsigned NumUnmerge = BuildUseCount / 2; + + auto *Unmerge = getOpcodeDef<GUnmerge>(BV.getSourceReg(0), MRI); + + // Check the first operand is an unmerge and has the correct number of + // operands + if (!Unmerge || Unmerge->getNumDefs() != NumUnmerge) + return false; + + UnmergeSrc = Unmerge->getSourceReg(); + + LLT DstTy = MRI.getType(MI.getOperand(0).getReg()); + LLT UnmergeSrcTy = MRI.getType(UnmergeSrc); + + if (!UnmergeSrcTy.isVector()) + return false; + + // Ensure we only generate legal instructions post-legalizer + if (!IsPreLegalize && + !isLegal({TargetOpcode::G_CONCAT_VECTORS, {DstTy, UnmergeSrcTy}})) + return false; + + // Check that all of the operands before the midpoint come from the same + // unmerge and are in the same order as they are used in the build_vector + for (unsigned I = 0; I < NumUnmerge; ++I) { + auto MaybeUnmergeReg = BV.getSourceReg(I); + auto *LoopUnmerge = getOpcodeDef<GUnmerge>(MaybeUnmergeReg, MRI); + + if (!LoopUnmerge || LoopUnmerge != Unmerge) + return false; + + if (LoopUnmerge->getOperand(I).getReg() != MaybeUnmergeReg) + return false; + } + + // Check that all of the unmerged values are used + if (Unmerge->getNumDefs() != NumUnmerge) + return false; + + // Check that all of the operands after the mid point are undefs. + for (unsigned I = NumUnmerge; I < BuildUseCount; ++I) { + auto *Undef = getDefIgnoringCopies(BV.getSourceReg(I), MRI); + + if (Undef->getOpcode() != TargetOpcode::G_IMPLICIT_DEF) + return false; + } + + return true; +} + +void CombinerHelper::applyCombineBuildUnmerge(MachineInstr &MI, + MachineRegisterInfo &MRI, + MachineIRBuilder &B, + Register &UnmergeSrc) const { + assert(UnmergeSrc && "Expected there to be one matching G_UNMERGE_VALUES"); + B.setInstrAndDebugLoc(MI); + + Register UndefVec = B.buildUndef(MRI.getType(UnmergeSrc)).getReg(0); + B.buildConcatVectors(MI.getOperand(0), {UnmergeSrc, UndefVec}); + + MI.eraseFromParent(); +} + // This combine tries to reduce the number of scalarised G_TRUNC instructions by // using vector truncates instead // @@ -8426,4 +8511,4 @@ bool CombinerHelper::matchSuboCarryOut(const MachineInstr &MI, } return false; -} +}
\ No newline at end of file diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp index c1fb8b6..ecba323 100644 --- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp +++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp @@ -247,6 +247,7 @@ void GISelValueTracking::computeKnownBitsImpl(Register R, KnownBits &Known, for (unsigned Idx = 1; Idx < MI.getNumOperands(); Idx += 2) { const MachineOperand &Src = MI.getOperand(Idx); Register SrcReg = Src.getReg(); + LLT SrcTy = MRI.getType(SrcReg); // Look through trivial copies and phis but don't look through trivial // copies or phis of the form `%1:(s32) = OP %0:gpr32`, known-bits // analysis is currently unable to determine the bit width of a @@ -255,9 +256,15 @@ void GISelValueTracking::computeKnownBitsImpl(Register R, KnownBits &Known, // We can't use NoSubRegister by name as it's defined by each target but // it's always defined to be 0 by tablegen. if (SrcReg.isVirtual() && Src.getSubReg() == 0 /*NoSubRegister*/ && - MRI.getType(SrcReg).isValid()) { + SrcTy.isValid()) { + // In case we're forwarding from a vector register to a non-vector + // register we need to update the demanded elements to reflect this + // before recursing. + APInt NowDemandedElts = SrcTy.isFixedVector() && !DstTy.isFixedVector() + ? APInt::getAllOnes(SrcTy.getNumElements()) + : DemandedElts; // Known to be APInt(1, 1) // For COPYs we don't do anything, don't increase the depth. - computeKnownBitsImpl(SrcReg, Known2, DemandedElts, + computeKnownBitsImpl(SrcReg, Known2, NowDemandedElts, Depth + (Opcode != TargetOpcode::COPY)); Known2 = Known2.anyextOrTrunc(BitWidth); Known = Known.intersectWith(Known2); diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index d656f10..d87a231 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -111,17 +111,18 @@ INITIALIZE_PASS_END(IRTranslator, DEBUG_TYPE, "IRTranslator LLVM IR -> MI", false, false) static void reportTranslationError(MachineFunction &MF, - const TargetPassConfig &TPC, OptimizationRemarkEmitter &ORE, OptimizationRemarkMissed &R) { MF.getProperties().setFailedISel(); + bool IsGlobalISelAbortEnabled = + MF.getTarget().Options.GlobalISelAbort == GlobalISelAbortMode::Enable; // Print the function name explicitly if we don't have a debug location (which // makes the diagnostic less useful) or if we're going to emit a raw error. - if (!R.getLocation().isValid() || TPC.isGlobalISelAbortEnabled()) + if (!R.getLocation().isValid() || IsGlobalISelAbortEnabled) R << (" (in function: " + MF.getName() + ")").str(); - if (TPC.isGlobalISelAbortEnabled()) + if (IsGlobalISelAbortEnabled) report_fatal_error(Twine(R.getMsg())); else ORE.emit(R); @@ -242,7 +243,7 @@ ArrayRef<Register> IRTranslator::getOrCreateVRegs(const Value &Val) { MF->getFunction().getSubprogram(), &MF->getFunction().getEntryBlock()); R << "unable to translate constant: " << ore::NV("Type", Val.getType()); - reportTranslationError(*MF, *TPC, *ORE, R); + reportTranslationError(*MF, *ORE, R); return *VRegs; } } @@ -279,7 +280,7 @@ Align IRTranslator::getMemOpAlign(const Instruction &I) { OptimizationRemarkMissed R("gisel-irtranslator", "", &I); R << "unable to translate memop: " << ore::NV("Opcode", &I); - reportTranslationError(*MF, *TPC, *ORE, R); + reportTranslationError(*MF, *ORE, R); return Align(1); } @@ -1412,14 +1413,14 @@ bool IRTranslator::translateLoad(const User &U, MachineIRBuilder &MIRBuilder) { Regs.size() == 1 ? LI.getMetadata(LLVMContext::MD_range) : nullptr; for (unsigned i = 0; i < Regs.size(); ++i) { Register Addr; - MIRBuilder.materializeObjectPtrOffset(Addr, Base, OffsetTy, Offsets[i] / 8); + MIRBuilder.materializeObjectPtrOffset(Addr, Base, OffsetTy, Offsets[i]); - MachinePointerInfo Ptr(LI.getPointerOperand(), Offsets[i] / 8); + MachinePointerInfo Ptr(LI.getPointerOperand(), Offsets[i]); Align BaseAlign = getMemOpAlign(LI); - auto MMO = MF->getMachineMemOperand( - Ptr, Flags, MRI->getType(Regs[i]), - commonAlignment(BaseAlign, Offsets[i] / 8), AAInfo, Ranges, - LI.getSyncScopeID(), LI.getOrdering()); + auto MMO = + MF->getMachineMemOperand(Ptr, Flags, MRI->getType(Regs[i]), + commonAlignment(BaseAlign, Offsets[i]), AAInfo, + Ranges, LI.getSyncScopeID(), LI.getOrdering()); MIRBuilder.buildLoad(Regs[i], Addr, *MMO); } @@ -1451,14 +1452,14 @@ bool IRTranslator::translateStore(const User &U, MachineIRBuilder &MIRBuilder) { for (unsigned i = 0; i < Vals.size(); ++i) { Register Addr; - MIRBuilder.materializeObjectPtrOffset(Addr, Base, OffsetTy, Offsets[i] / 8); + MIRBuilder.materializeObjectPtrOffset(Addr, Base, OffsetTy, Offsets[i]); - MachinePointerInfo Ptr(SI.getPointerOperand(), Offsets[i] / 8); + MachinePointerInfo Ptr(SI.getPointerOperand(), Offsets[i]); Align BaseAlign = getMemOpAlign(SI); - auto MMO = MF->getMachineMemOperand( - Ptr, Flags, MRI->getType(Vals[i]), - commonAlignment(BaseAlign, Offsets[i] / 8), SI.getAAMetadata(), nullptr, - SI.getSyncScopeID(), SI.getOrdering()); + auto MMO = MF->getMachineMemOperand(Ptr, Flags, MRI->getType(Vals[i]), + commonAlignment(BaseAlign, Offsets[i]), + SI.getAAMetadata(), nullptr, + SI.getSyncScopeID(), SI.getOrdering()); MIRBuilder.buildStore(Vals[i], Addr, *MMO); } return true; @@ -1483,8 +1484,8 @@ static uint64_t getOffsetFromIndices(const User &U, const DataLayout &DL) { llvm::append_range(Indices, drop_begin(U.operands())); } - return 8 * static_cast<uint64_t>( - DL.getIndexedOffsetInType(Src->getType(), Indices)); + return static_cast<uint64_t>( + DL.getIndexedOffsetInType(Src->getType(), Indices)); } bool IRTranslator::translateExtractValue(const User &U, @@ -2835,7 +2836,7 @@ bool IRTranslator::translateCall(const User &U, MachineIRBuilder &MIRBuilder) { IsTgtMemIntrinsic ? &Info : nullptr); } -/// Translate a call to an intrinsic. +/// Translate a call or callbr to an intrinsic. /// Depending on whether TLI->getTgtMemIntrinsic() is true, TgtMemIntrinsicInfo /// is a pointer to the correspondingly populated IntrinsicInfo object. /// Otherwise, this pointer is null. @@ -2917,6 +2918,9 @@ bool IRTranslator::translateIntrinsic( } } + if (auto Bundle = CB.getOperandBundle(LLVMContext::OB_deactivation_symbol)) + MIB->setDeactivationSymbol(*MF, Bundle->Inputs[0].get()); + return true; } @@ -3063,10 +3067,52 @@ bool IRTranslator::translateInvoke(const User &U, return true; } +/// The intrinsics currently supported by callbr are implicit control flow +/// intrinsics such as amdgcn.kill. bool IRTranslator::translateCallBr(const User &U, MachineIRBuilder &MIRBuilder) { - // FIXME: Implement this. - return false; + if (containsBF16Type(U)) + return false; // see translateCall + + const CallBrInst &I = cast<CallBrInst>(U); + MachineBasicBlock *CallBrMBB = &MIRBuilder.getMBB(); + + Intrinsic::ID IID = I.getIntrinsicID(); + if (I.isInlineAsm()) { + // FIXME: inline asm is not yet supported for callbr in GlobalISel. As soon + // as we add support, we need to handle the indirect asm targets, see + // SelectionDAGBuilder::visitCallBr(). + return false; + } + if (!translateIntrinsic(I, IID, MIRBuilder)) + return false; + + // Retrieve successors. + SmallPtrSet<BasicBlock *, 8> Dests = {I.getDefaultDest()}; + MachineBasicBlock *Return = &getMBB(*I.getDefaultDest()); + + // Update successor info. + addSuccessorWithProb(CallBrMBB, Return, BranchProbability::getOne()); + + // Add indirect targets as successors. For intrinsic callbr, these represent + // implicit control flow (e.g., the "kill" path for amdgcn.kill). We mark them + // with setIsInlineAsmBrIndirectTarget so the machine verifier accepts them as + // valid successors, even though they're not from inline asm. + for (BasicBlock *Dest : I.getIndirectDests()) { + MachineBasicBlock &Target = getMBB(*Dest); + Target.setIsInlineAsmBrIndirectTarget(); + Target.setLabelMustBeEmitted(); + // Don't add duplicate machine successors. + if (Dests.insert(Dest).second) + addSuccessorWithProb(CallBrMBB, &Target, BranchProbability::getZero()); + } + + CallBrMBB->normalizeSuccProbs(); + + // Drop into default successor. + MIRBuilder.buildBr(*Return); + + return true; } bool IRTranslator::translateLandingPad(const User &U, @@ -3482,7 +3528,7 @@ bool IRTranslator::translateAtomicCmpXchg(const User &U, bool IRTranslator::translateAtomicRMW(const User &U, MachineIRBuilder &MIRBuilder) { - if (!MF->getTarget().getTargetTriple().isSPIRV() && containsBF16Type(U)) + if (containsBF16Type(U) && !targetSupportsBF16Type(MF)) return false; const AtomicRMWInst &I = cast<AtomicRMWInst>(U); @@ -4144,7 +4190,7 @@ bool IRTranslator::runOnMachineFunction(MachineFunction &CurMF) { OptimizationRemarkMissed R("gisel-irtranslator", "GISelFailure", F.getSubprogram(), &F.getEntryBlock()); R << "unable to translate in big endian mode"; - reportTranslationError(*MF, *TPC, *ORE, R); + reportTranslationError(*MF, *ORE, R); return false; } @@ -4188,7 +4234,7 @@ bool IRTranslator::runOnMachineFunction(MachineFunction &CurMF) { F.getSubprogram(), &F.getEntryBlock()); R << "unable to lower function: " << ore::NV("Prototype", F.getFunctionType()); - reportTranslationError(*MF, *TPC, *ORE, R); + reportTranslationError(*MF, *ORE, R); return false; } @@ -4211,7 +4257,7 @@ bool IRTranslator::runOnMachineFunction(MachineFunction &CurMF) { F.getSubprogram(), &F.getEntryBlock()); R << "unable to lower arguments: " << ore::NV("Prototype", F.getFunctionType()); - reportTranslationError(*MF, *TPC, *ORE, R); + reportTranslationError(*MF, *ORE, R); return false; } @@ -4262,7 +4308,7 @@ bool IRTranslator::runOnMachineFunction(MachineFunction &CurMF) { R << ": '" << InstStrStorage << "'"; } - reportTranslationError(*MF, *TPC, *ORE, R); + reportTranslationError(*MF, *ORE, R); return false; } @@ -4270,7 +4316,7 @@ bool IRTranslator::runOnMachineFunction(MachineFunction &CurMF) { OptimizationRemarkMissed R("gisel-irtranslator", "GISelFailure", BB->getTerminator()->getDebugLoc(), BB); R << "unable to translate basic block"; - reportTranslationError(*MF, *TPC, *ORE, R); + reportTranslationError(*MF, *ORE, R); return false; } } diff --git a/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp b/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp index b4e64d7..f695a2d 100644 --- a/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp +++ b/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp @@ -13,6 +13,7 @@ #include "llvm/CodeGen/GlobalISel/InlineAsmLowering.h" #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" +#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/TargetLowering.h" @@ -454,26 +455,52 @@ bool InlineAsmLowering::lowerInlineAsm( } if (OpInfo.ConstraintType == TargetLowering::C_Memory) { - - if (!OpInfo.isIndirect) { - LLVM_DEBUG(dbgs() - << "Cannot indirectify memory input operands yet\n"); - return false; - } - - assert(OpInfo.isIndirect && "Operand must be indirect to be a mem!"); - const InlineAsm::ConstraintCode ConstraintID = TLI->getInlineAsmMemConstraint(OpInfo.ConstraintCode); InlineAsm::Flag OpFlags(InlineAsm::Kind::Mem, 1); OpFlags.setMemConstraint(ConstraintID); Inst.addImm(OpFlags); + + if (OpInfo.isIndirect) { + // already indirect + ArrayRef<Register> SourceRegs = + GetOrCreateVRegs(*OpInfo.CallOperandVal); + if (SourceRegs.size() != 1) { + LLVM_DEBUG(dbgs() << "Expected the memory input to fit into a " + "single virtual register " + "for constraint '" + << OpInfo.ConstraintCode << "'\n"); + return false; + } + Inst.addReg(SourceRegs[0]); + break; + } + + // Needs to be made indirect. Store the value on the stack and use + // a pointer to it. + Value *OpVal = OpInfo.CallOperandVal; + TypeSize Bytes = DL.getTypeStoreSize(OpVal->getType()); + Align Alignment = DL.getPrefTypeAlign(OpVal->getType()); + int FrameIdx = + MF.getFrameInfo().CreateStackObject(Bytes, Alignment, false); + + unsigned AddrSpace = DL.getAllocaAddrSpace(); + LLT FramePtrTy = + LLT::pointer(AddrSpace, DL.getPointerSizeInBits(AddrSpace)); + auto Ptr = MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx).getReg(0); ArrayRef<Register> SourceRegs = GetOrCreateVRegs(*OpInfo.CallOperandVal); - assert( - SourceRegs.size() == 1 && - "Expected the memory input to fit into a single virtual register"); - Inst.addReg(SourceRegs[0]); + if (SourceRegs.size() != 1) { + LLVM_DEBUG(dbgs() << "Expected the memory input to fit into a single " + "virtual register " + "for constraint '" + << OpInfo.ConstraintCode << "'\n"); + return false; + } + MIRBuilder.buildStore(SourceRegs[0], Ptr, + MachinePointerInfo::getFixedStack(MF, FrameIdx), + Alignment); + Inst.addReg(Ptr); break; } @@ -538,13 +565,6 @@ bool InlineAsmLowering::lowerInlineAsm( } } - // Add rounding control registers as implicit def for inline asm. - if (MF.getFunction().hasFnAttribute(Attribute::StrictFP)) { - ArrayRef<MCPhysReg> RCRegs = TLI->getRoundingControlRegisters(); - for (MCPhysReg Reg : RCRegs) - Inst.addReg(Reg, RegState::ImplicitDefine); - } - if (auto Bundle = Call.getOperandBundle(LLVMContext::OB_convergencectrl)) { auto *Token = Bundle->Inputs[0].get(); ArrayRef<Register> SourceRegs = GetOrCreateVRegs(*Token); @@ -556,6 +576,13 @@ bool InlineAsmLowering::lowerInlineAsm( if (const MDNode *SrcLoc = Call.getMetadata("srcloc")) Inst.addMetadata(SrcLoc); + // Add rounding control registers as implicit def for inline asm. + if (MF.getFunction().hasFnAttribute(Attribute::StrictFP)) { + ArrayRef<MCPhysReg> RCRegs = TLI->getRoundingControlRegisters(); + for (MCPhysReg Reg : RCRegs) + Inst.addReg(Reg, RegState::ImplicitDefine); + } + // All inputs are handled, insert the instruction now MIRBuilder.insertInstr(Inst); diff --git a/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp b/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp index 2dd22c8a..1d281ab 100644 --- a/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp +++ b/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp @@ -137,7 +137,6 @@ bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) { return false; ISel = MF.getSubtarget().getInstructionSelector(); - ISel->TPC = &getAnalysis<TargetPassConfig>(); // FIXME: Properly override OptLevel in TargetMachine. See OptLevelChanger CodeGenOptLevel OldOptLevel = OptLevel; @@ -159,7 +158,6 @@ bool InstructionSelect::selectMachineFunction(MachineFunction &MF) { LLVM_DEBUG(dbgs() << "Selecting function: " << MF.getName() << '\n'); assert(ISel && "Cannot work without InstructionSelector"); - const TargetPassConfig &TPC = *ISel->TPC; CodeGenCoverage CoverageInfo; ISel->setupMF(MF, VT, &CoverageInfo, PSI, BFI); @@ -177,8 +175,8 @@ bool InstructionSelect::selectMachineFunction(MachineFunction &MF) { // property check already is. if (!DisableGISelLegalityCheck) if (const MachineInstr *MI = machineFunctionIsIllegal(MF)) { - reportGISelFailure(MF, TPC, MORE, "gisel-select", - "instruction is not legal", *MI); + reportGISelFailure(MF, MORE, "gisel-select", "instruction is not legal", + *MI); return false; } // FIXME: We could introduce new blocks and will need to fix the outer loop. @@ -215,8 +213,7 @@ bool InstructionSelect::selectMachineFunction(MachineFunction &MF) { if (!selectInstr(MI)) { LLVM_DEBUG(dbgs() << "Selection failed!\n"; MIIMaintainer.reportFullyCreatedInstrs()); - reportGISelFailure(MF, TPC, MORE, "gisel-select", "cannot select", - MI); + reportGISelFailure(MF, MORE, "gisel-select", "cannot select", MI); return false; } LLVM_DEBUG(MIIMaintainer.reportFullyCreatedInstrs()); @@ -279,7 +276,7 @@ bool InstructionSelect::selectMachineFunction(MachineFunction &MF) { const TargetRegisterClass *RC = MRI.getRegClassOrNull(VReg); if (!RC) { - reportGISelFailure(MF, TPC, MORE, "gisel-select", + reportGISelFailure(MF, MORE, "gisel-select", "VReg has no regclass after selection", *MI); return false; } @@ -288,7 +285,7 @@ bool InstructionSelect::selectMachineFunction(MachineFunction &MF) { if (Ty.isValid() && TypeSize::isKnownGT(Ty.getSizeInBits(), TRI.getRegSizeInBits(*RC))) { reportGISelFailure( - MF, TPC, MORE, "gisel-select", + MF, MORE, "gisel-select", "VReg's low-level type and register class have different sizes", *MI); return false; } @@ -299,7 +296,7 @@ bool InstructionSelect::selectMachineFunction(MachineFunction &MF) { MF.getFunction().getSubprogram(), /*MBB=*/nullptr); R << "inserting blocks is not supported yet"; - reportGISelFailure(MF, TPC, MORE, R); + reportGISelFailure(MF, MORE, R); return false; } #endif diff --git a/llvm/lib/CodeGen/GlobalISel/LegalityPredicates.cpp b/llvm/lib/CodeGen/GlobalISel/LegalityPredicates.cpp index 30c2d08..5e7cd5f 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegalityPredicates.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalityPredicates.cpp @@ -155,6 +155,26 @@ LegalityPredicate LegalityPredicates::scalarOrEltNarrowerThan(unsigned TypeIdx, }; } +LegalityPredicate +LegalityPredicates::vectorElementCountIsGreaterThan(unsigned TypeIdx, + unsigned Size) { + + return [=](const LegalityQuery &Query) { + const LLT QueryTy = Query.Types[TypeIdx]; + return QueryTy.isFixedVector() && QueryTy.getNumElements() > Size; + }; +} + +LegalityPredicate +LegalityPredicates::vectorElementCountIsLessThanOrEqualTo(unsigned TypeIdx, + unsigned Size) { + + return [=](const LegalityQuery &Query) { + const LLT QueryTy = Query.Types[TypeIdx]; + return QueryTy.isFixedVector() && QueryTy.getNumElements() <= Size; + }; +} + LegalityPredicate LegalityPredicates::scalarOrEltWiderThan(unsigned TypeIdx, unsigned Size) { return [=](const LegalityQuery &Query) { diff --git a/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp b/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp index aef16b5..0f0656a 100644 --- a/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp +++ b/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp @@ -348,7 +348,7 @@ bool Legalizer::runOnMachineFunction(MachineFunction &MF) { *MIRBuilder, VT); if (Result.FailedOn) { - reportGISelFailure(MF, TPC, MORE, "gisel-legalize", + reportGISelFailure(MF, MORE, "gisel-legalize", "unable to legalize instruction", *Result.FailedOn); return false; } @@ -360,7 +360,7 @@ bool Legalizer::runOnMachineFunction(MachineFunction &MF) { R << "lost " << ore::NV("NumLostDebugLocs", LocObserver.getNumLostDebugLocs()) << " debug locations during pass"; - reportGISelWarning(MF, TPC, MORE, R); + reportGISelWarning(MF, MORE, R); // Example remark: // --- !Missed // Pass: gisel-legalize diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index d02f097..251ea4b 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -1930,7 +1930,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI, Register CmpOut; CmpInst::Predicate PartPred; - if (I == E - 1 && LHSLeftoverRegs.empty()) { + if (I == E - 1) { PartPred = Pred; CmpOut = Dst; } else { @@ -3065,6 +3065,14 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) { Observer.changedInstr(MI); return Legalized; + case TargetOpcode::G_FPEXT: + if (TypeIdx != 1) + return UnableToLegalize; + + Observer.changingInstr(MI); + widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_FPEXT); + Observer.changedInstr(MI); + return Legalized; case TargetOpcode::G_FPTOSI: case TargetOpcode::G_FPTOUI: case TargetOpcode::G_INTRINSIC_LRINT: @@ -3431,6 +3439,18 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) { Observer.changedInstr(MI); return Legalized; } + case TargetOpcode::G_LROUND: + case TargetOpcode::G_LLROUND: + Observer.changingInstr(MI); + + if (TypeIdx == 0) + widenScalarDst(MI, WideTy); + else + widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_FPEXT); + + Observer.changedInstr(MI); + return Legalized; + case TargetOpcode::G_INTTOPTR: if (TypeIdx != 1) return UnableToLegalize; @@ -6664,13 +6684,24 @@ LegalizerHelper::moreElementsVector(MachineInstr &MI, unsigned TypeIdx, case TargetOpcode::G_FMAXIMUMNUM: case TargetOpcode::G_STRICT_FADD: case TargetOpcode::G_STRICT_FSUB: - case TargetOpcode::G_STRICT_FMUL: + case TargetOpcode::G_STRICT_FMUL: { + Observer.changingInstr(MI); + moreElementsVectorSrc(MI, MoreTy, 1); + moreElementsVectorSrc(MI, MoreTy, 2); + moreElementsVectorDst(MI, MoreTy, 0); + Observer.changedInstr(MI); + return Legalized; + } case TargetOpcode::G_SHL: case TargetOpcode::G_ASHR: case TargetOpcode::G_LSHR: { Observer.changingInstr(MI); moreElementsVectorSrc(MI, MoreTy, 1); - moreElementsVectorSrc(MI, MoreTy, 2); + // The shift operand may have a different scalar type from the source and + // destination operands. + LLT ShiftMoreTy = MoreTy.changeElementType( + MRI.getType(MI.getOperand(2).getReg()).getElementType()); + moreElementsVectorSrc(MI, ShiftMoreTy, 2); moreElementsVectorDst(MI, MoreTy, 0); Observer.changedInstr(MI); return Legalized; @@ -6786,12 +6817,10 @@ LegalizerHelper::moreElementsVector(MachineInstr &MI, unsigned TypeIdx, LLT DstExtTy; if (TypeIdx == 0) { DstExtTy = MoreTy; - SrcExtTy = LLT::fixed_vector( - MoreTy.getNumElements(), + SrcExtTy = MoreTy.changeElementType( MRI.getType(MI.getOperand(1).getReg()).getElementType()); } else { - DstExtTy = LLT::fixed_vector( - MoreTy.getNumElements(), + DstExtTy = MoreTy.changeElementType( MRI.getType(MI.getOperand(0).getReg()).getElementType()); SrcExtTy = MoreTy; } @@ -7589,7 +7618,7 @@ LegalizerHelper::lowerBitCount(MachineInstr &MI) { } case TargetOpcode::G_CTLZ: { auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs(); - unsigned Len = SrcTy.getSizeInBits(); + unsigned Len = SrcTy.getScalarSizeInBits(); if (isSupported({TargetOpcode::G_CTLZ_ZERO_UNDEF, {DstTy, SrcTy}})) { // If CTLZ_ZERO_UNDEF is supported, emit that and a select for zero. @@ -7637,7 +7666,7 @@ LegalizerHelper::lowerBitCount(MachineInstr &MI) { case TargetOpcode::G_CTTZ: { auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs(); - unsigned Len = SrcTy.getSizeInBits(); + unsigned Len = SrcTy.getScalarSizeInBits(); if (isSupported({TargetOpcode::G_CTTZ_ZERO_UNDEF, {DstTy, SrcTy}})) { // If CTTZ_ZERO_UNDEF is legal or custom, emit that and a select with // zero. @@ -7675,9 +7704,13 @@ LegalizerHelper::lowerBitCount(MachineInstr &MI) { case TargetOpcode::G_CTPOP: { Register SrcReg = MI.getOperand(1).getReg(); LLT Ty = MRI.getType(SrcReg); - unsigned Size = Ty.getSizeInBits(); + unsigned Size = Ty.getScalarSizeInBits(); MachineIRBuilder &B = MIRBuilder; + // Bail out on irregular type lengths. + if (Size > 128 || Size % 8 != 0) + return UnableToLegalize; + // Count set bits in blocks of 2 bits. Default approach would be // B2Count = { val & 0x55555555 } + { (val >> 1) & 0x55555555 } // We use following formula instead: diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp index 637acd6..3906b31 100644 --- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp +++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp @@ -38,8 +38,10 @@ void MachineIRBuilder::setMF(MachineFunction &MF) { //------------------------------------------------------------------------------ MachineInstrBuilder MachineIRBuilder::buildInstrNoInsert(unsigned Opcode) { - return BuildMI(getMF(), {getDL(), getPCSections(), getMMRAMetadata()}, - getTII().get(Opcode)); + return BuildMI( + getMF(), + {getDL(), getPCSections(), getMMRAMetadata(), getDeactivationSymbol()}, + getTII().get(Opcode)); } MachineInstrBuilder MachineIRBuilder::insertInstr(MachineInstrBuilder MIB) { diff --git a/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp b/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp index bcb4f1c..5db631b 100644 --- a/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp +++ b/llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp @@ -39,6 +39,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" #include <algorithm> #include <cassert> #include <cstdint> @@ -83,7 +84,6 @@ void RegBankSelect::init(MachineFunction &MF) { assert(RBI && "Cannot work without RegisterBankInfo"); MRI = &MF.getRegInfo(); TRI = MF.getSubtarget().getRegisterInfo(); - TPC = &getAnalysis<TargetPassConfig>(); if (OptMode != Mode::Fast) { MBFI = &getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI(); MBPI = &getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI(); @@ -308,7 +308,8 @@ const RegisterBankInfo::InstructionMapping &RegBankSelect::findBestMapping( RepairPts.emplace_back(std::move(RepairPt)); } } - if (!BestMapping && !TPC->isGlobalISelAbortEnabled()) { + if (!BestMapping && MI.getMF()->getTarget().Options.GlobalISelAbort != + GlobalISelAbortMode::Enable) { // If none of the mapping worked that means they are all impossible. // Thus, pick the first one and set an impossible repairing point. // It will trigger the failed isel mode. @@ -708,7 +709,7 @@ bool RegBankSelect::assignRegisterBanks(MachineFunction &MF) { continue; if (!assignInstr(MI)) { - reportGISelFailure(MF, *TPC, *MORE, "gisel-regbankselect", + reportGISelFailure(MF, *MORE, "gisel-regbankselect", "unable to map instruction", MI); return false; } @@ -722,7 +723,7 @@ bool RegBankSelect::checkFunctionIsLegal(MachineFunction &MF) const { #ifndef NDEBUG if (!DisableGISelLegalityCheck) { if (const MachineInstr *MI = machineFunctionIsIllegal(MF)) { - reportGISelFailure(MF, *TPC, *MORE, "gisel-regbankselect", + reportGISelFailure(MF, *MORE, "gisel-regbankselect", "instruction is not legal", *MI); return false; } diff --git a/llvm/lib/CodeGen/GlobalISel/Utils.cpp b/llvm/lib/CodeGen/GlobalISel/Utils.cpp index 5fab6ec..15e81f5 100644 --- a/llvm/lib/CodeGen/GlobalISel/Utils.cpp +++ b/llvm/lib/CodeGen/GlobalISel/Utils.cpp @@ -114,7 +114,7 @@ Register llvm::constrainOperandRegClass( // Assume physical registers are properly constrained. assert(Reg.isVirtual() && "PhysReg not implemented"); - const TargetRegisterClass *OpRC = TII.getRegClass(II, OpIdx, &TRI); + const TargetRegisterClass *OpRC = TII.getRegClass(II, OpIdx); // Some of the target independent instructions, like COPY, may not impose any // register class constraints on some of their operands: If it's a use, we can // skip constraining as the instruction defining the register would constrain @@ -234,11 +234,11 @@ bool llvm::isTriviallyDead(const MachineInstr &MI, static void reportGISelDiagnostic(DiagnosticSeverity Severity, MachineFunction &MF, - const TargetPassConfig &TPC, MachineOptimizationRemarkEmitter &MORE, MachineOptimizationRemarkMissed &R) { - bool IsFatal = Severity == DS_Error && - TPC.isGlobalISelAbortEnabled(); + bool IsGlobalISelAbortEnabled = + MF.getTarget().Options.GlobalISelAbort == GlobalISelAbortMode::Enable; + bool IsFatal = Severity == DS_Error && IsGlobalISelAbortEnabled; // Print the function name explicitly if we don't have a debug location (which // makes the diagnostic less useful) or if we're going to emit a raw error. if (!R.getLocation().isValid() || IsFatal) @@ -250,20 +250,20 @@ static void reportGISelDiagnostic(DiagnosticSeverity Severity, MORE.emit(R); } -void llvm::reportGISelWarning(MachineFunction &MF, const TargetPassConfig &TPC, +void llvm::reportGISelWarning(MachineFunction &MF, MachineOptimizationRemarkEmitter &MORE, MachineOptimizationRemarkMissed &R) { - reportGISelDiagnostic(DS_Warning, MF, TPC, MORE, R); + reportGISelDiagnostic(DS_Warning, MF, MORE, R); } -void llvm::reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC, +void llvm::reportGISelFailure(MachineFunction &MF, MachineOptimizationRemarkEmitter &MORE, MachineOptimizationRemarkMissed &R) { MF.getProperties().setFailedISel(); - reportGISelDiagnostic(DS_Error, MF, TPC, MORE, R); + reportGISelDiagnostic(DS_Error, MF, MORE, R); } -void llvm::reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC, +void llvm::reportGISelFailure(MachineFunction &MF, MachineOptimizationRemarkEmitter &MORE, const char *PassName, StringRef Msg, const MachineInstr &MI) { @@ -271,9 +271,10 @@ void llvm::reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC, MI.getDebugLoc(), MI.getParent()); R << Msg; // Printing MI is expensive; only do it if expensive remarks are enabled. - if (TPC.isGlobalISelAbortEnabled() || MORE.allowExtraAnalysis(PassName)) + if (MF.getTarget().Options.GlobalISelAbort == GlobalISelAbortMode::Enable || + MORE.allowExtraAnalysis(PassName)) R << ": " << ore::MNV("Inst", MI); - reportGISelFailure(MF, TPC, MORE, R); + reportGISelFailure(MF, MORE, R); } unsigned llvm::getInverseGMinMaxOpcode(unsigned MinMaxOpc) { @@ -768,8 +769,12 @@ llvm::ConstantFoldFPBinOp(unsigned Opcode, const Register Op1, C1.copySign(C2); return C1; case TargetOpcode::G_FMINNUM: + if (C1.isSignaling() || C2.isSignaling()) + return std::nullopt; return minnum(C1, C2); case TargetOpcode::G_FMAXNUM: + if (C1.isSignaling() || C2.isSignaling()) + return std::nullopt; return maxnum(C1, C2); case TargetOpcode::G_FMINIMUM: return minimum(C1, C2); |
