aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp131
1 files changed, 98 insertions, 33 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index c8d0f5faf647..441437351852 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -24,6 +24,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/MemoryLocation.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/CodeGen/Analysis.h"
@@ -602,7 +603,7 @@ static void AddNodeIDValueTypes(FoldingSetNodeID &ID, SDVTList VTList) {
/// AddNodeIDOperands - Various routines for adding operands to the NodeID data.
static void AddNodeIDOperands(FoldingSetNodeID &ID,
ArrayRef<SDValue> Ops) {
- for (auto& Op : Ops) {
+ for (const auto &Op : Ops) {
ID.AddPointer(Op.getNode());
ID.AddInteger(Op.getResNo());
}
@@ -611,7 +612,7 @@ static void AddNodeIDOperands(FoldingSetNodeID &ID,
/// AddNodeIDOperands - Various routines for adding operands to the NodeID data.
static void AddNodeIDOperands(FoldingSetNodeID &ID,
ArrayRef<SDUse> Ops) {
- for (auto& Op : Ops) {
+ for (const auto &Op : Ops) {
ID.AddPointer(Op.getNode());
ID.AddInteger(Op.getResNo());
}
@@ -2711,16 +2712,9 @@ bool SelectionDAG::isSplatValue(SDValue V, const APInt &DemandedElts,
SubDemandedElts &= ScaledDemandedElts;
if (!isSplatValue(Src, SubDemandedElts, SubUndefElts, Depth + 1))
return false;
-
- // Here we can't do "MatchAnyBits" operation merge for undef bits.
- // Because some operation only use part value of the source.
- // Take llvm.fshl.* for example:
- // t1: v4i32 = Constant:i32<12>, undef:i32, Constant:i32<12>, undef:i32
- // t2: v2i64 = bitcast t1
- // t5: v2i64 = fshl t3, t4, t2
- // We can not convert t2 to {i64 undef, i64 undef}
- UndefElts |= APIntOps::ScaleBitMask(SubUndefElts, NumElts,
- /*MatchAllBits=*/true);
+ // TODO: Add support for merging sub undef elements.
+ if (!SubUndefElts.isZero())
+ return false;
}
return true;
}
@@ -2947,6 +2941,9 @@ KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts,
unsigned Opcode = Op.getOpcode();
switch (Opcode) {
+ case ISD::MERGE_VALUES:
+ return computeKnownBits(Op.getOperand(Op.getResNo()), DemandedElts,
+ Depth + 1);
case ISD::BUILD_VECTOR:
// Collect the known bits that are shared by every demanded vector element.
Known.Zero.setAllBits(); Known.One.setAllBits();
@@ -3219,12 +3216,6 @@ KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts,
Known = KnownBits::mulhs(Known, Known2);
break;
}
- case ISD::UDIV: {
- Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
- Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
- Known = KnownBits::udiv(Known, Known2);
- break;
- }
case ISD::AVGCEILU: {
Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
@@ -3339,6 +3330,38 @@ KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts,
Known.Zero |= Known2.Zero;
}
break;
+ case ISD::SHL_PARTS:
+ case ISD::SRA_PARTS:
+ case ISD::SRL_PARTS: {
+ assert((Op.getResNo() == 0 || Op.getResNo() == 1) && "Unknown result");
+
+ // Collect lo/hi source values and concatenate.
+ // TODO: Would a KnownBits::concatBits helper be useful?
+ unsigned LoBits = Op.getOperand(0).getScalarValueSizeInBits();
+ unsigned HiBits = Op.getOperand(1).getScalarValueSizeInBits();
+ Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
+ Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
+ Known = Known.anyext(LoBits + HiBits);
+ Known.insertBits(Known2, LoBits);
+
+ // Collect shift amount.
+ Known2 = computeKnownBits(Op.getOperand(2), DemandedElts, Depth + 1);
+
+ if (Opcode == ISD::SHL_PARTS)
+ Known = KnownBits::shl(Known, Known2);
+ else if (Opcode == ISD::SRA_PARTS)
+ Known = KnownBits::ashr(Known, Known2);
+ else // if (Opcode == ISD::SRL_PARTS)
+ Known = KnownBits::lshr(Known, Known2);
+
+ // TODO: Minimum shift low/high bits are known zero.
+
+ if (Op.getResNo() == 0)
+ Known = Known.extractBits(LoBits, 0);
+ else
+ Known = Known.extractBits(HiBits, LoBits);
+ break;
+ }
case ISD::SIGN_EXTEND_INREG: {
Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
EVT EVT = cast<VTSDNode>(Op.getOperand(1))->getVT();
@@ -3570,6 +3593,12 @@ KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts,
Known = KnownBits::computeForAddCarry(Known, Known2, Carry);
break;
}
+ case ISD::UDIV: {
+ Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
+ Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
+ Known = KnownBits::udiv(Known, Known2);
+ break;
+ }
case ISD::SREM: {
Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
@@ -3925,7 +3954,9 @@ unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, const APInt &DemandedElts,
case ISD::AssertZext:
Tmp = cast<VTSDNode>(Op.getOperand(1))->getVT().getSizeInBits();
return VTBits-Tmp;
-
+ case ISD::MERGE_VALUES:
+ return ComputeNumSignBits(Op.getOperand(Op.getResNo()), DemandedElts,
+ Depth + 1);
case ISD::BUILD_VECTOR:
Tmp = VTBits;
for (unsigned i = 0, e = Op.getNumOperands(); (i < e) && (Tmp > 1); ++i) {
@@ -6105,8 +6136,8 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
assert(N1.getValueType().isVector() == VT.isVector() &&
"FP_TO_*INT_SAT type should be vector iff the operand type is "
"vector!");
- assert((!VT.isVector() || VT.getVectorNumElements() ==
- N1.getValueType().getVectorNumElements()) &&
+ assert((!VT.isVector() || VT.getVectorElementCount() ==
+ N1.getValueType().getVectorElementCount()) &&
"Vector element counts must match in FP_TO_*INT_SAT");
assert(!cast<VTSDNode>(N2)->getVT().isVector() &&
"Type to saturate to must be a scalar.");
@@ -6719,7 +6750,7 @@ static SDValue getMemcpyLoadsAndStores(SelectionDAG &DAG, const SDLoc &dl,
bool isVol, bool AlwaysInline,
MachinePointerInfo DstPtrInfo,
MachinePointerInfo SrcPtrInfo,
- const AAMDNodes &AAInfo) {
+ const AAMDNodes &AAInfo, AAResults *AA) {
// Turn a memcpy of undef to nop.
// FIXME: We need to honor volatile even is Src is undef.
if (Src.isUndef())
@@ -6782,6 +6813,11 @@ static SDValue getMemcpyLoadsAndStores(SelectionDAG &DAG, const SDLoc &dl,
AAMDNodes NewAAInfo = AAInfo;
NewAAInfo.TBAA = NewAAInfo.TBAAStruct = nullptr;
+ const Value *SrcVal = SrcPtrInfo.V.dyn_cast<const Value *>();
+ bool isConstant =
+ AA && SrcVal &&
+ AA->pointsToConstantMemory(MemoryLocation(SrcVal, Size, AAInfo));
+
MachineMemOperand::Flags MMOFlags =
isVol ? MachineMemOperand::MOVolatile : MachineMemOperand::MONone;
SmallVector<SDValue, 16> OutLoadChains;
@@ -6843,6 +6879,8 @@ static SDValue getMemcpyLoadsAndStores(SelectionDAG &DAG, const SDLoc &dl,
MachineMemOperand::Flags SrcMMOFlags = MMOFlags;
if (isDereferenceable)
SrcMMOFlags |= MachineMemOperand::MODereferenceable;
+ if (isConstant)
+ SrcMMOFlags |= MachineMemOperand::MOInvariant;
Value = DAG.getExtLoad(
ISD::EXTLOAD, dl, NVT, Chain,
@@ -7131,7 +7169,7 @@ SDValue SelectionDAG::getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst,
bool isVol, bool AlwaysInline, bool isTailCall,
MachinePointerInfo DstPtrInfo,
MachinePointerInfo SrcPtrInfo,
- const AAMDNodes &AAInfo) {
+ const AAMDNodes &AAInfo, AAResults *AA) {
// Check to see if we should lower the memcpy to loads and stores first.
// For cases within the target-specified limits, this is the best choice.
ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
@@ -7142,7 +7180,7 @@ SDValue SelectionDAG::getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst,
SDValue Result = getMemcpyLoadsAndStores(
*this, dl, Chain, Dst, Src, ConstantSize->getZExtValue(), Alignment,
- isVol, false, DstPtrInfo, SrcPtrInfo, AAInfo);
+ isVol, false, DstPtrInfo, SrcPtrInfo, AAInfo, AA);
if (Result.getNode())
return Result;
}
@@ -7161,9 +7199,9 @@ SDValue SelectionDAG::getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst,
// use a (potentially long) sequence of loads and stores.
if (AlwaysInline) {
assert(ConstantSize && "AlwaysInline requires a constant size!");
- return getMemcpyLoadsAndStores(*this, dl, Chain, Dst, Src,
- ConstantSize->getZExtValue(), Alignment,
- isVol, true, DstPtrInfo, SrcPtrInfo, AAInfo);
+ return getMemcpyLoadsAndStores(
+ *this, dl, Chain, Dst, Src, ConstantSize->getZExtValue(), Alignment,
+ isVol, true, DstPtrInfo, SrcPtrInfo, AAInfo, AA);
}
checkAddrSpaceIsValidForLibcall(TLI, DstPtrInfo.getAddrSpace());
@@ -7245,7 +7283,7 @@ SDValue SelectionDAG::getMemmove(SDValue Chain, const SDLoc &dl, SDValue Dst,
bool isVol, bool isTailCall,
MachinePointerInfo DstPtrInfo,
MachinePointerInfo SrcPtrInfo,
- const AAMDNodes &AAInfo) {
+ const AAMDNodes &AAInfo, AAResults *AA) {
// Check to see if we should lower the memmove to loads and stores first.
// For cases within the target-specified limits, this is the best choice.
ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
@@ -8904,7 +8942,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
}
#ifndef NDEBUG
- for (auto &Op : Ops)
+ for (const auto &Op : Ops)
assert(Op.getOpcode() != ISD::DELETED_NODE &&
"Operand is DELETED_NODE!");
#endif
@@ -8928,6 +8966,11 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
"True and False arms of SelectCC must have same type!");
assert(Ops[2].getValueType() == VT &&
"select_cc node must be of same type as true and false value!");
+ assert((!Ops[0].getValueType().isVector() ||
+ Ops[0].getValueType().getVectorElementCount() ==
+ VT.getVectorElementCount()) &&
+ "Expected select_cc with vector result to have the same sized "
+ "comparison type!");
break;
case ISD::BR_CC:
assert(NumOps == 5 && "BR_CC takes 5 operands!");
@@ -9018,12 +9061,34 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList,
return getNode(Opcode, DL, VTList.VTs[0], Ops, Flags);
#ifndef NDEBUG
- for (auto &Op : Ops)
+ for (const auto &Op : Ops)
assert(Op.getOpcode() != ISD::DELETED_NODE &&
"Operand is DELETED_NODE!");
#endif
switch (Opcode) {
+ case ISD::SADDO:
+ case ISD::UADDO:
+ case ISD::SSUBO:
+ case ISD::USUBO: {
+ assert(VTList.NumVTs == 2 && Ops.size() == 2 &&
+ "Invalid add/sub overflow op!");
+ assert(VTList.VTs[0].isInteger() && VTList.VTs[1].isInteger() &&
+ Ops[0].getValueType() == Ops[1].getValueType() &&
+ Ops[0].getValueType() == VTList.VTs[0] &&
+ "Binary operator types must match!");
+ SDValue N1 = Ops[0], N2 = Ops[1];
+ canonicalizeCommutativeBinop(Opcode, N1, N2);
+
+ // (X +- 0) -> X with zero-overflow.
+ ConstantSDNode *N2CV = isConstOrConstSplat(N2, /*AllowUndefs*/ false,
+ /*AllowTruncation*/ true);
+ if (N2CV && N2CV->isZero()) {
+ SDValue ZeroOverFlow = getConstant(0, DL, VTList.VTs[1]);
+ return getNode(ISD::MERGE_VALUES, DL, VTList, {N1, ZeroOverFlow}, Flags);
+ }
+ break;
+ }
case ISD::STRICT_FP_EXTEND:
assert(VTList.NumVTs == 2 && Ops.size() == 2 &&
"Invalid STRICT_FP_EXTEND!");
@@ -9914,7 +9979,7 @@ void SelectionDAG::salvageDebugInfo(SDNode &N) {
return;
SmallVector<SDDbgValue *, 2> ClonedDVs;
- for (auto DV : GetDbgValues(&N)) {
+ for (auto *DV : GetDbgValues(&N)) {
if (DV->isInvalidated())
continue;
switch (N.getOpcode()) {
@@ -10268,7 +10333,7 @@ bool SelectionDAG::calculateDivergence(SDNode *N) {
}
if (TLI->isSDNodeSourceOfDivergence(N, FLI, DA))
return true;
- for (auto &Op : N->ops()) {
+ for (const auto &Op : N->ops()) {
if (Op.Val.getValueType() != MVT::Other && Op.getNode()->isDivergent())
return true;
}
@@ -10298,7 +10363,7 @@ void SelectionDAG::CreateTopologicalOrder(std::vector<SDNode *> &Order) {
}
for (size_t I = 0; I != Order.size(); ++I) {
SDNode *N = Order[I];
- for (auto U : N->uses()) {
+ for (auto *U : N->uses()) {
unsigned &UnsortedOps = Degree[U];
if (0 == --UnsortedOps)
Order.push_back(U);