aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2022-07-27 19:50:45 +0000
committerDimitry Andric <dim@FreeBSD.org>2022-07-27 19:50:54 +0000
commit08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (patch)
tree041e72e32710b1e742516d8c9f1575bf0116d3e3 /llvm/lib/CodeGen
parent4b4fe385e49bd883fd183b5f21c1ea486c722e61 (diff)
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp7
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/WasmException.h2
-rw-r--r--llvm/lib/CodeGen/AtomicExpandPass.cpp7
-rw-r--r--llvm/lib/CodeGen/CodeGenPrepare.cpp4
-rw-r--r--llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp3
-rw-r--r--llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp10
-rw-r--r--llvm/lib/CodeGen/LiveDebugValues/InstrRefBasedImpl.cpp5
-rw-r--r--llvm/lib/CodeGen/LiveRangeEdit.cpp16
-rw-r--r--llvm/lib/CodeGen/MachineFunctionPass.cpp29
-rw-r--r--llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp7
-rw-r--r--llvm/lib/CodeGen/ProcessImplicitDefs.cpp2
-rw-r--r--llvm/lib/CodeGen/RegAllocGreedy.cpp19
-rw-r--r--llvm/lib/CodeGen/RegAllocGreedy.h2
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp90
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp41
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h2
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp17
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);