diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2022-07-27 19:50:45 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2022-07-27 19:50:54 +0000 |
| commit | 08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (patch) | |
| tree | 041e72e32710b1e742516d8c9f1575bf0116d3e3 /llvm/lib/CodeGen | |
| parent | 4b4fe385e49bd883fd183b5f21c1ea486c722e61 (diff) | |
vendor/llvm-project/llvmorg-15-init-17827-gd77882e66779vendor/llvm-project/llvmorg-15-init-17826-g1f8ae9d7e7e4
Diffstat (limited to 'llvm/lib/CodeGen')
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 7 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/WasmException.h | 2 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/AtomicExpandPass.cpp | 7 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/CodeGenPrepare.cpp | 4 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp | 3 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 10 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp | 5 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/LiveRangeEdit.cpp | 16 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/MachineFunctionPass.cpp | 29 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp | 7 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/ProcessImplicitDefs.cpp | 2 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/RegAllocGreedy.cpp | 19 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/RegAllocGreedy.h | 2 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 90 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 41 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h | 2 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp | 17 |
17 files changed, 195 insertions, 68 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index e0050a47a6f6..32a10ad41d1f 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -2795,12 +2795,7 @@ const MCExpr *AsmPrinter::lowerConstant(const Constant *CV) { DL.getTypeAllocSize(Op->getType()).getFixedSize()) return OpExpr; - // Otherwise the pointer is smaller than the resultant integer, mask off - // the high bits so we are sure to get a proper truncation if the input is - // a constant expr. - unsigned InBits = DL.getTypeAllocSizeInBits(Op->getType()); - const MCExpr *MaskExpr = MCConstantExpr::create(~0ULL >> (64-InBits), Ctx); - return MCBinaryExpr::createAnd(OpExpr, MaskExpr, Ctx); + break; // Error } case Instruction::Sub: { diff --git a/llvm/lib/CodeGen/AsmPrinter/WasmException.h b/llvm/lib/CodeGen/AsmPrinter/WasmException.h index 2abbe37cb6d9..419b569d123c 100644 --- a/llvm/lib/CodeGen/AsmPrinter/WasmException.h +++ b/llvm/lib/CodeGen/AsmPrinter/WasmException.h @@ -28,7 +28,7 @@ public: void endModule() override; void beginFunction(const MachineFunction *MF) override {} - virtual void markFunctionEnd() override; + void markFunctionEnd() override; void endFunction(const MachineFunction *MF) override; protected: diff --git a/llvm/lib/CodeGen/AtomicExpandPass.cpp b/llvm/lib/CodeGen/AtomicExpandPass.cpp index f21c1bf4e914..ad51bab8f30b 100644 --- a/llvm/lib/CodeGen/AtomicExpandPass.cpp +++ b/llvm/lib/CodeGen/AtomicExpandPass.cpp @@ -515,9 +515,14 @@ void AtomicExpand::expandAtomicStore(StoreInst *SI) { // It is the responsibility of the target to only signal expansion via // shouldExpandAtomicRMW in cases where this is required and possible. IRBuilder<> Builder(SI); + AtomicOrdering Ordering = SI->getOrdering(); + assert(Ordering != AtomicOrdering::NotAtomic); + AtomicOrdering RMWOrdering = Ordering == AtomicOrdering::Unordered + ? AtomicOrdering::Monotonic + : Ordering; AtomicRMWInst *AI = Builder.CreateAtomicRMW( AtomicRMWInst::Xchg, SI->getPointerOperand(), SI->getValueOperand(), - SI->getAlign(), SI->getOrdering()); + SI->getAlign(), RMWOrdering); SI->eraseFromParent(); // Now we have an appropriate swap instruction, lower it as usual. diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index b6c762b93ca5..b8f6fc9bbcde 100644 --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -2568,8 +2568,6 @@ struct ExtAddrMode : public TargetLowering::AddrMode { } }; -} // end anonymous namespace - #ifndef NDEBUG static inline raw_ostream &operator<<(raw_ostream &OS, const ExtAddrMode &AM) { AM.print(OS); @@ -2617,6 +2615,8 @@ LLVM_DUMP_METHOD void ExtAddrMode::dump() const { } #endif +} // end anonymous namespace + namespace { /// This class provides transaction based operation on the IR. diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp index da054b9c14fb..05a25bc3078e 100644 --- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp @@ -1142,7 +1142,8 @@ bool CombinerHelper::matchCombineDivRem(MachineInstr &MI, if (MI.getParent() == UseMI.getParent() && ((IsDiv && UseMI.getOpcode() == RemOpcode) || (!IsDiv && UseMI.getOpcode() == DivOpcode)) && - matchEqualDefs(MI.getOperand(2), UseMI.getOperand(2))) { + matchEqualDefs(MI.getOperand(2), UseMI.getOperand(2)) && + matchEqualDefs(MI.getOperand(1), UseMI.getOperand(1))) { OtherMI = &UseMI; return true; } diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index dbdcfe0b6f0b..2f9187bbf2ad 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -151,11 +151,11 @@ public: LLVM_DEBUG(dbgs() << "Checking DILocation from " << *CurrInst << " was copied to " << MI); #endif - // We allow insts in the entry block to have a debug loc line of 0 because + // We allow insts in the entry block to have no debug loc because // they could have originated from constants, and we don't want a jumpy // debug experience. assert((CurrInst->getDebugLoc() == MI.getDebugLoc() || - MI.getDebugLoc().getLine() == 0) && + (MI.getParent()->isEntryBlock() && !MI.getDebugLoc())) && "Line info was not transferred to all instructions"); } }; @@ -3020,11 +3020,9 @@ bool IRTranslator::translate(const Instruction &Inst) { bool IRTranslator::translate(const Constant &C, Register Reg) { // We only emit constants into the entry block from here. To prevent jumpy - // debug behaviour set the line to 0. + // debug behaviour remove debug line. if (auto CurrInstDL = CurBuilder->getDL()) - EntryBuilder->setDebugLoc(DILocation::get(C.getContext(), 0, 0, - CurrInstDL.getScope(), - CurrInstDL.getInlinedAt())); + EntryBuilder->setDebugLoc(DebugLoc()); if (auto CI = dyn_cast<ConstantInt>(&C)) EntryBuilder->buildConstant(Reg, *CI); diff --git a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp index ef49d3888f2b..191596dbf53e 100644 --- a/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp +++ b/llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp @@ -1330,7 +1330,7 @@ bool InstrRefBasedLDV::transferDebugPHI(MachineInstr &MI) { const MachineOperand &MO = MI.getOperand(0); unsigned InstrNum = MI.getOperand(1).getImm(); - auto EmitBadPHI = [this, &MI, InstrNum](void) -> bool { + auto EmitBadPHI = [this, &MI, InstrNum]() -> bool { // Helper lambda to do any accounting when we fail to find a location for // a DBG_PHI. This can happen if DBG_PHIs are malformed, or refer to a // dead stack slot, for example. @@ -3136,8 +3136,7 @@ bool InstrRefBasedLDV::emitTransfers( MI->getDebugLoc()->getInlinedAt()); Insts.emplace_back(AllVarsNumbering.find(Var)->second, MI); } - llvm::sort(Insts, - [](const auto &A, const auto &B) { return A.first < B.first; }); + llvm::sort(Insts, llvm::less_first()); // Insert either before or after the designated point... if (P.MBB) { diff --git a/llvm/lib/CodeGen/LiveRangeEdit.cpp b/llvm/lib/CodeGen/LiveRangeEdit.cpp index 2aafb746aa2c..abf36b3f4c67 100644 --- a/llvm/lib/CodeGen/LiveRangeEdit.cpp +++ b/llvm/lib/CodeGen/LiveRangeEdit.cpp @@ -300,13 +300,15 @@ void LiveRangeEdit::eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink) { SmallVector<unsigned, 8> RegsToErase; bool ReadsPhysRegs = false; bool isOrigDef = false; - unsigned Dest; + Register Dest; + unsigned DestSubReg; // Only optimize rematerialize case when the instruction has one def, since // otherwise we could leave some dead defs in the code. This case is // extremely rare. if (VRM && MI->getOperand(0).isReg() && MI->getOperand(0).isDef() && MI->getDesc().getNumDefs() == 1) { Dest = MI->getOperand(0).getReg(); + DestSubReg = MI->getOperand(0).getSubReg(); unsigned Original = VRM->getOriginal(Dest); LiveInterval &OrigLI = LIS.getInterval(Original); VNInfo *OrigVNI = OrigLI.getVNInfoAt(Idx); @@ -384,8 +386,18 @@ void LiveRangeEdit::eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink) { if (isOrigDef && DeadRemats && !HasLiveVRegUses && TII.isTriviallyReMaterializable(*MI)) { LiveInterval &NewLI = createEmptyIntervalFrom(Dest, false); - VNInfo *VNI = NewLI.getNextValue(Idx, LIS.getVNInfoAllocator()); + VNInfo::Allocator &Alloc = LIS.getVNInfoAllocator(); + VNInfo *VNI = NewLI.getNextValue(Idx, Alloc); NewLI.addSegment(LiveInterval::Segment(Idx, Idx.getDeadSlot(), VNI)); + + if (DestSubReg) { + const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo(); + auto *SR = NewLI.createSubRange( + Alloc, TRI->getSubRegIndexLaneMask(DestSubReg)); + SR->addSegment(LiveInterval::Segment(Idx, Idx.getDeadSlot(), + SR->getNextValue(Idx, Alloc))); + } + pop_back(); DeadRemats->insert(MI); const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo(); diff --git a/llvm/lib/CodeGen/MachineFunctionPass.cpp b/llvm/lib/CodeGen/MachineFunctionPass.cpp index 99494122d608..477310f59112 100644 --- a/llvm/lib/CodeGen/MachineFunctionPass.cpp +++ b/llvm/lib/CodeGen/MachineFunctionPass.cpp @@ -26,6 +26,7 @@ #include "llvm/CodeGen/Passes.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" +#include "llvm/IR/PrintPasses.h" using namespace llvm; using namespace ore; @@ -70,6 +71,17 @@ bool MachineFunctionPass::runOnFunction(Function &F) { if (ShouldEmitSizeRemarks) CountBefore = MF.getInstructionCount(); + // For --print-changed, if the function name is a candidate, save the + // serialized MF to be compared later. + // TODO Implement --filter-passes. + SmallString<0> BeforeStr, AfterStr; + bool ShouldPrintChanged = PrintChanged != ChangePrinter::None && + isFunctionInPrintList(MF.getName()); + if (ShouldPrintChanged) { + raw_svector_ostream OS(BeforeStr); + MF.print(OS); + } + bool RV = runOnMachineFunction(MF); if (ShouldEmitSizeRemarks) { @@ -97,6 +109,23 @@ bool MachineFunctionPass::runOnFunction(Function &F) { MFProps.set(SetProperties); MFProps.reset(ClearedProperties); + + // For --print-changed, print if the serialized MF has changed. Modes other + // than quiet/verbose are unimplemented and treated the same as 'quiet'. + if (ShouldPrintChanged) { + raw_svector_ostream OS(AfterStr); + MF.print(OS); + if (BeforeStr != AfterStr) { + StringRef Arg; + if (const PassInfo *PI = Pass::lookupPassInfo(getPassID())) + Arg = PI->getPassArgument(); + errs() << ("*** IR Dump After " + getPassName() + " (" + Arg + ") on " + + MF.getName() + " ***\n" + AfterStr); + } else if (PrintChanged == ChangePrinter::Verbose) { + errs() << ("*** IR Dump After " + getPassName() + " on " + MF.getName() + + " omitted because no change ***\n"); + } + } return RV; } diff --git a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp index 1115c2a27956..87e2f9f20021 100644 --- a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp +++ b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp @@ -18,6 +18,7 @@ #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" #include "llvm/IR/Type.h" #include "llvm/InitializePasses.h" @@ -69,6 +70,8 @@ static CallInst::TailCallKind getOverridingTailCallKind(const Function &F) { static bool lowerObjCCall(Function &F, const char *NewFn, bool setNonLazyBind = false) { + assert(IntrinsicInst::mayLowerToFunctionCall(F.getIntrinsicID()) && + "Pre-ISel intrinsics do lower into regular function calls"); if (F.use_empty()) return false; @@ -107,7 +110,9 @@ static bool lowerObjCCall(Function &F, const char *NewFn, IRBuilder<> Builder(CI->getParent(), CI->getIterator()); SmallVector<Value *, 8> Args(CI->args()); - CallInst *NewCI = Builder.CreateCall(FCache, Args); + SmallVector<llvm::OperandBundleDef, 1> BundleList; + CI->getOperandBundlesAsDefs(BundleList); + CallInst *NewCI = Builder.CreateCall(FCache, Args, BundleList); NewCI->setName(CI->getName()); // Try to set the most appropriate TailCallKind based on both the current diff --git a/llvm/lib/CodeGen/ProcessImplicitDefs.cpp b/llvm/lib/CodeGen/ProcessImplicitDefs.cpp index 7327f9e52efc..54bb4a31ef49 100644 --- a/llvm/lib/CodeGen/ProcessImplicitDefs.cpp +++ b/llvm/lib/CodeGen/ProcessImplicitDefs.cpp @@ -47,7 +47,7 @@ public: bool runOnMachineFunction(MachineFunction &MF) override; - virtual MachineFunctionProperties getRequiredProperties() const override { + MachineFunctionProperties getRequiredProperties() const override { return MachineFunctionProperties().set( MachineFunctionProperties::Property::IsSSA); } diff --git a/llvm/lib/CodeGen/RegAllocGreedy.cpp b/llvm/lib/CodeGen/RegAllocGreedy.cpp index 4a54d7ebf8a9..9c6cb7c3a4e2 100644 --- a/llvm/lib/CodeGen/RegAllocGreedy.cpp +++ b/llvm/lib/CodeGen/RegAllocGreedy.cpp @@ -135,6 +135,12 @@ static cl::opt<bool> GreedyRegClassPriorityTrumpsGlobalness( "more important then whether the range is global"), cl::Hidden); +static cl::opt<bool> GreedyReverseLocalAssignment( + "greedy-reverse-local-assignment", + cl::desc("Reverse allocation order of local live ranges, such that " + "shorter local live ranges will tend to be allocated first"), + cl::Hidden); + static RegisterRegAlloc greedyRegAlloc("greedy", "greedy register allocator", createGreedyRegisterAllocator); @@ -297,11 +303,10 @@ void RAGreedy::enqueue(PQueue &CurQueue, const LiveInterval *LI) { } else { // Giant live ranges fall back to the global assignment heuristic, which // prevents excessive spilling in pathological cases. - bool ReverseLocal = TRI->reverseLocalAssignment(); const TargetRegisterClass &RC = *MRI->getRegClass(Reg); - bool ForceGlobal = - !ReverseLocal && (Size / SlotIndex::InstrDist) > - (2 * RegClassInfo.getNumAllocatableRegs(&RC)); + bool ForceGlobal = !ReverseLocalAssignment && + (Size / SlotIndex::InstrDist) > + (2 * RegClassInfo.getNumAllocatableRegs(&RC)); unsigned GlobalBit = 0; if (Stage == RS_Assign && !ForceGlobal && !LI->empty() && @@ -309,7 +314,7 @@ void RAGreedy::enqueue(PQueue &CurQueue, const LiveInterval *LI) { // Allocate original local ranges in linear instruction order. Since they // are singly defined, this produces optimal coloring in the absence of // global interference and other constraints. - if (!ReverseLocal) + if (!ReverseLocalAssignment) Prio = LI->beginIndex().getInstrDistance(Indexes->getLastIndex()); else { // Allocating bottom up may allow many short LRGs to be assigned first @@ -2528,6 +2533,10 @@ bool RAGreedy::runOnMachineFunction(MachineFunction &mf) { ? GreedyRegClassPriorityTrumpsGlobalness : TRI->regClassPriorityTrumpsGlobalness(*MF); + ReverseLocalAssignment = GreedyReverseLocalAssignment.getNumOccurrences() + ? GreedyReverseLocalAssignment + : TRI->reverseLocalAssignment(); + ExtraInfo.emplace(); EvictAdvisor = getAnalysis<RegAllocEvictionAdvisorAnalysis>().getAdvisor(*MF, *this); diff --git a/llvm/lib/CodeGen/RegAllocGreedy.h b/llvm/lib/CodeGen/RegAllocGreedy.h index 316b12d0213b..483f59ed8e8e 100644 --- a/llvm/lib/CodeGen/RegAllocGreedy.h +++ b/llvm/lib/CodeGen/RegAllocGreedy.h @@ -270,6 +270,8 @@ private: /// machine function. bool RegClassPriorityTrumpsGlobalness; + bool ReverseLocalAssignment; + public: RAGreedy(const RegClassFilterFunc F = allocateAllRegClasses); diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index edb0756e8c3b..654879115ff9 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -4877,9 +4877,16 @@ SDValue DAGCombiner::visitSMUL_LOHI(SDNode *N) { if (SDValue Res = SimplifyNodeWithTwoResults(N, ISD::MUL, ISD::MULHS)) return Res; + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); EVT VT = N->getValueType(0); SDLoc DL(N); + // canonicalize constant to RHS (vector doesn't have to splat) + if (DAG.isConstantIntBuildVectorOrConstantInt(N0) && + !DAG.isConstantIntBuildVectorOrConstantInt(N1)) + return DAG.getNode(ISD::SMUL_LOHI, DL, N->getVTList(), N1, N0); + // If the type is twice as wide is legal, transform the mulhu to a wider // multiply plus a shift. if (VT.isSimple() && !VT.isVector()) { @@ -4887,8 +4894,8 @@ SDValue DAGCombiner::visitSMUL_LOHI(SDNode *N) { unsigned SimpleSize = Simple.getSizeInBits(); EVT NewVT = EVT::getIntegerVT(*DAG.getContext(), SimpleSize*2); if (TLI.isOperationLegal(ISD::MUL, NewVT)) { - SDValue Lo = DAG.getNode(ISD::SIGN_EXTEND, DL, NewVT, N->getOperand(0)); - SDValue Hi = DAG.getNode(ISD::SIGN_EXTEND, DL, NewVT, N->getOperand(1)); + SDValue Lo = DAG.getNode(ISD::SIGN_EXTEND, DL, NewVT, N0); + SDValue Hi = DAG.getNode(ISD::SIGN_EXTEND, DL, NewVT, N1); Lo = DAG.getNode(ISD::MUL, DL, NewVT, Lo, Hi); // Compute the high part as N1. Hi = DAG.getNode(ISD::SRL, DL, NewVT, Lo, @@ -4908,19 +4915,26 @@ SDValue DAGCombiner::visitUMUL_LOHI(SDNode *N) { if (SDValue Res = SimplifyNodeWithTwoResults(N, ISD::MUL, ISD::MULHU)) return Res; + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); EVT VT = N->getValueType(0); SDLoc DL(N); + // canonicalize constant to RHS (vector doesn't have to splat) + if (DAG.isConstantIntBuildVectorOrConstantInt(N0) && + !DAG.isConstantIntBuildVectorOrConstantInt(N1)) + return DAG.getNode(ISD::UMUL_LOHI, DL, N->getVTList(), N1, N0); + // (umul_lohi N0, 0) -> (0, 0) - if (isNullConstant(N->getOperand(1))) { + if (isNullConstant(N1)) { SDValue Zero = DAG.getConstant(0, DL, VT); return CombineTo(N, Zero, Zero); } // (umul_lohi N0, 1) -> (N0, 0) - if (isOneConstant(N->getOperand(1))) { + if (isOneConstant(N1)) { SDValue Zero = DAG.getConstant(0, DL, VT); - return CombineTo(N, N->getOperand(0), Zero); + return CombineTo(N, N0, Zero); } // If the type is twice as wide is legal, transform the mulhu to a wider @@ -4930,8 +4944,8 @@ SDValue DAGCombiner::visitUMUL_LOHI(SDNode *N) { unsigned SimpleSize = Simple.getSizeInBits(); EVT NewVT = EVT::getIntegerVT(*DAG.getContext(), SimpleSize*2); if (TLI.isOperationLegal(ISD::MUL, NewVT)) { - SDValue Lo = DAG.getNode(ISD::ZERO_EXTEND, DL, NewVT, N->getOperand(0)); - SDValue Hi = DAG.getNode(ISD::ZERO_EXTEND, DL, NewVT, N->getOperand(1)); + SDValue Lo = DAG.getNode(ISD::ZERO_EXTEND, DL, NewVT, N0); + SDValue Hi = DAG.getNode(ISD::ZERO_EXTEND, DL, NewVT, N1); Lo = DAG.getNode(ISD::MUL, DL, NewVT, Lo, Hi); // Compute the high part as N1. Hi = DAG.getNode(ISD::SRL, DL, NewVT, Lo, @@ -7247,6 +7261,7 @@ static SDValue extractShiftForRotate(SelectionDAG &DAG, SDValue OppShift, // Otherwise if matching a general funnel shift, it should be clear. static bool matchRotateSub(SDValue Pos, SDValue Neg, unsigned EltSize, SelectionDAG &DAG, bool IsRotate) { + const auto &TLI = DAG.getTargetLoweringInfo(); // If EltSize is a power of 2 then: // // (a) (Pos == 0 ? 0 : EltSize - Pos) == (EltSize - Pos) & (EltSize - 1) @@ -7278,19 +7293,20 @@ static bool matchRotateSub(SDValue Pos, SDValue Neg, unsigned EltSize, // always invokes undefined behavior for 32-bit X. // // Below, Mask == EltSize - 1 when using [A] and is all-ones otherwise. + // This allows us to peek through any operations that only affect Mask's + // un-demanded bits. // - // NOTE: We can only do this when matching an AND and not a general - // funnel shift. + // NOTE: We can only do this when matching operations which won't modify the + // least Log2(EltSize) significant bits and not a general funnel shift. unsigned MaskLoBits = 0; - if (IsRotate && Neg.getOpcode() == ISD::AND && isPowerOf2_64(EltSize)) { - if (ConstantSDNode *NegC = isConstOrConstSplat(Neg.getOperand(1))) { - KnownBits Known = DAG.computeKnownBits(Neg.getOperand(0)); - unsigned Bits = Log2_64(EltSize); - if (NegC->getAPIntValue().getActiveBits() <= Bits && - ((NegC->getAPIntValue() | Known.Zero).countTrailingOnes() >= Bits)) { - Neg = Neg.getOperand(0); - MaskLoBits = Bits; - } + if (IsRotate && isPowerOf2_64(EltSize)) { + unsigned Bits = Log2_64(EltSize); + APInt DemandedBits = + APInt::getLowBitsSet(Neg.getScalarValueSizeInBits(), Bits); + if (SDValue Inner = + TLI.SimplifyMultipleUseDemandedBits(Neg, DemandedBits, DAG)) { + Neg = Inner; + MaskLoBits = Bits; } } @@ -7302,15 +7318,15 @@ static bool matchRotateSub(SDValue Pos, SDValue Neg, unsigned EltSize, return false; SDValue NegOp1 = Neg.getOperand(1); - // On the RHS of [A], if Pos is Pos' & (EltSize - 1), just replace Pos with - // Pos'. The truncation is redundant for the purpose of the equality. - if (MaskLoBits && Pos.getOpcode() == ISD::AND) { - if (ConstantSDNode *PosC = isConstOrConstSplat(Pos.getOperand(1))) { - KnownBits Known = DAG.computeKnownBits(Pos.getOperand(0)); - if (PosC->getAPIntValue().getActiveBits() <= MaskLoBits && - ((PosC->getAPIntValue() | Known.Zero).countTrailingOnes() >= - MaskLoBits)) - Pos = Pos.getOperand(0); + // On the RHS of [A], if Pos is the result of operation on Pos' that won't + // affect Mask's demanded bits, just replace Pos with Pos'. These operations + // are redundant for the purpose of the equality. + if (MaskLoBits) { + APInt DemandedBits = + APInt::getLowBitsSet(Pos.getScalarValueSizeInBits(), MaskLoBits); + if (SDValue Inner = + TLI.SimplifyMultipleUseDemandedBits(Pos, DemandedBits, DAG)) { + Pos = Inner; } } @@ -14988,7 +15004,7 @@ SDValue DAGCombiner::visitFMA(SDNode *N) { // FMA nodes have flags that propagate to the created nodes. SelectionDAG::FlagInserter FlagsInserter(DAG, N); - bool UnsafeFPMath = + bool CanReassociate = Options.UnsafeFPMath || N->getFlags().hasAllowReassociation(); // Constant fold FMA. @@ -15012,7 +15028,8 @@ SDValue DAGCombiner::visitFMA(SDNode *N) { CostN1 == TargetLowering::NegatibleCost::Cheaper)) return DAG.getNode(ISD::FMA, DL, VT, NegN0, NegN1, N2); - if (UnsafeFPMath) { + // FIXME: use fast math flags instead of Options.UnsafeFPMath + if (Options.UnsafeFPMath) { if (N0CFP && N0CFP->isZero()) return N2; if (N1CFP && N1CFP->isZero()) @@ -15029,7 +15046,7 @@ SDValue DAGCombiner::visitFMA(SDNode *N) { !DAG.isConstantFPBuildVectorOrConstantFP(N1)) return DAG.getNode(ISD::FMA, SDLoc(N), VT, N1, N0, N2); - if (UnsafeFPMath) { + if (CanReassociate) { // (fma x, c1, (fmul x, c2)) -> (fmul x, c1+c2) if (N2.getOpcode() == ISD::FMUL && N0 == N2.getOperand(0) && DAG.isConstantFPBuildVectorOrConstantFP(N1) && @@ -15070,7 +15087,7 @@ SDValue DAGCombiner::visitFMA(SDNode *N) { } } - if (UnsafeFPMath) { + if (CanReassociate) { // (fma x, c, x) -> (fmul x, (c+1)) if (N1CFP && N0 == N2) { return DAG.getNode( @@ -19697,8 +19714,11 @@ static SDValue scalarizeExtractedBinop(SDNode *ExtElt, SelectionDAG &DAG, // extract. SDValue Op0 = Vec.getOperand(0); SDValue Op1 = Vec.getOperand(1); + APInt SplatVal; if (isAnyConstantBuildVector(Op0, true) || - isAnyConstantBuildVector(Op1, true)) { + ISD::isConstantSplatVector(Op0.getNode(), SplatVal) || + isAnyConstantBuildVector(Op1, true) || + ISD::isConstantSplatVector(Op1.getNode(), SplatVal)) { // extractelt (binop X, C), IndexC --> binop (extractelt X, IndexC), C' // extractelt (binop C, X), IndexC --> binop C', (extractelt X, IndexC) SDLoc DL(ExtElt); @@ -19775,6 +19795,9 @@ SDValue DAGCombiner::visitEXTRACT_VECTOR_ELT(SDNode *N) { // converts. } + if (SDValue BO = scalarizeExtractedBinop(N, DAG, LegalOperations)) + return BO; + if (VecVT.isScalableVector()) return SDValue(); @@ -19820,9 +19843,6 @@ SDValue DAGCombiner::visitEXTRACT_VECTOR_ELT(SDNode *N) { } } - if (SDValue BO = scalarizeExtractedBinop(N, DAG, LegalOperations)) - return BO; - // Transform: (EXTRACT_VECTOR_ELT( VECTOR_SHUFFLE )) -> EXTRACT_VECTOR_ELT. // We only perform this optimization before the op legalization phase because // we may introduce new vector instructions which are not backed by TD diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 441437351852..195c0e6a836f 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -2529,8 +2529,7 @@ bool SelectionDAG::MaskedValueIsZero(SDValue V, const APInt &Mask, /// DemandedElts. We use this predicate to simplify operations downstream. bool SelectionDAG::MaskedVectorIsZero(SDValue V, const APInt &DemandedElts, unsigned Depth /* = 0 */) const { - APInt Mask = APInt::getAllOnes(V.getScalarValueSizeInBits()); - return Mask.isSubsetOf(computeKnownBits(V, DemandedElts, Depth).Zero); + return computeKnownBits(V, DemandedElts, Depth).isZero(); } /// MaskedValueIsAllOnes - Return true if '(Op & Mask) == Mask'. @@ -9089,6 +9088,15 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList, } break; } + case ISD::SMUL_LOHI: + case ISD::UMUL_LOHI: { + assert(VTList.NumVTs == 2 && Ops.size() == 2 && "Invalid mul lo/hi op!"); + assert(VTList.VTs[0].isInteger() && VTList.VTs[0] == VTList.VTs[1] && + VTList.VTs[0] == Ops[0].getValueType() && + VTList.VTs[0] == Ops[1].getValueType() && + "Binary operator types must match!"); + break; + } case ISD::STRICT_FP_EXTEND: assert(VTList.NumVTs == 2 && Ops.size() == 2 && "Invalid STRICT_FP_EXTEND!"); @@ -11682,6 +11690,35 @@ bool BuildVectorSDNode::isConstant() const { return true; } +Optional<std::pair<APInt, APInt>> +BuildVectorSDNode::isConstantSequence() const { + unsigned NumOps = getNumOperands(); + if (NumOps < 2) + return None; + + if (!isa<ConstantSDNode>(getOperand(0)) || + !isa<ConstantSDNode>(getOperand(1))) + return None; + + unsigned EltSize = getValueType(0).getScalarSizeInBits(); + APInt Start = getConstantOperandAPInt(0).trunc(EltSize); + APInt Stride = getConstantOperandAPInt(1).trunc(EltSize) - Start; + + if (Stride.isZero()) + return None; + + for (unsigned i = 2; i < NumOps; ++i) { + if (!isa<ConstantSDNode>(getOperand(i))) + return None; + + APInt Val = getConstantOperandAPInt(i).trunc(EltSize); + if (Val != (Start + (Stride * i))) + return None; + } + + return std::make_pair(Start, Stride); +} + bool ShuffleVectorSDNode::isSplatMask(const int *Mask, EVT VT) { // Find the first non-undef value in the shuffle mask. unsigned i, e; diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h index 4a3ab00614b3..d1915fd4e7ae 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -198,7 +198,7 @@ public: SDAGSwitchLowering(SelectionDAGBuilder *sdb, FunctionLoweringInfo &funcinfo) : SwitchCG::SwitchLowering(funcinfo), SDB(sdb) {} - virtual void addSuccessorWithProb( + void addSuccessorWithProb( MachineBasicBlock *Src, MachineBasicBlock *Dst, BranchProbability Prob = BranchProbability::getUnknown()) override { SDB->addSuccessorWithProb(Src, Dst, Prob); diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index cd4f0ae42bcd..6205e74837c0 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -654,6 +654,14 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, SDValue TargetLowering::SimplifyMultipleUseDemandedBits( SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, SelectionDAG &DAG, unsigned Depth) const { + EVT VT = Op.getValueType(); + + // Pretend we don't know anything about scalable vectors for now. + // TODO: We can probably do more work on simplifying the operations for + // scalable vectors, but for now we just bail out. + if (VT.isScalableVector()) + return SDValue(); + // Limit search depth. if (Depth >= SelectionDAG::MaxRecursionDepth) return SDValue(); @@ -664,7 +672,7 @@ SDValue TargetLowering::SimplifyMultipleUseDemandedBits( // Not demanding any bits/elts from Op. if (DemandedBits == 0 || DemandedElts == 0) - return DAG.getUNDEF(Op.getValueType()); + return DAG.getUNDEF(VT); bool IsLE = DAG.getDataLayout().isLittleEndian(); unsigned NumElts = DemandedElts.getBitWidth(); @@ -894,6 +902,13 @@ SDValue TargetLowering::SimplifyMultipleUseDemandedBits( SDValue Op, const APInt &DemandedBits, SelectionDAG &DAG, unsigned Depth) const { EVT VT = Op.getValueType(); + + // Pretend we don't know anything about scalable vectors for now. + // TODO: We can probably do more work on simplifying the operations for + // scalable vectors, but for now we just bail out. + if (VT.isScalableVector()) + return SDValue(); + APInt DemandedElts = VT.isVector() ? APInt::getAllOnes(VT.getVectorNumElements()) : APInt(1, 1); |
