summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/CodeGen/SelectionDAGNodes.h8
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp13
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp28
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp34
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp151
-rw-r--r--llvm/test/CodeGen/X86/vector-gep.ll2
-rw-r--r--llvm/test/CodeGen/X86/widen_cast-4.ll25
7 files changed, 113 insertions, 148 deletions
diff --git a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
index 0943fa1aff4..5df40671b52 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -1584,10 +1584,10 @@ public:
bool isBigEndian = false) const;
/// getConstantSplatValue - Check if this is a constant splat, and if so,
- /// return the splatted value. Otherwise return a null SDValue. This is
- /// a simpler form of isConstantSplat. Get the constant splat only if you
- /// care about the splat value.
- SDValue getConstantSplatValue() const;
+ /// return the splat value only if it is a ConstantSDNode. Otherwise
+ /// return nullptr. This is a simpler form of isConstantSplat.
+ /// Get the constant splat only if you care about the splat value.
+ ConstantSDNode *getConstantSplatValue() const;
bool isConstant() const;
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 9a91dcc341b..7198203036b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -654,12 +654,13 @@ static ConstantSDNode *isConstOrConstSplat(SDValue N) {
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N))
return CN;
- if (BuildVectorSDNode *BV = dyn_cast<BuildVectorSDNode>(N))
- if (SDValue Splat = BV->getConstantSplatValue())
- if (auto *CN = dyn_cast<ConstantSDNode>(Splat))
- // BuildVectors can truncate their operands. Ignore that case here.
- if (CN->getValueType(0) == N.getValueType().getScalarType())
- return CN;
+ if (BuildVectorSDNode *BV = dyn_cast<BuildVectorSDNode>(N)) {
+ ConstantSDNode *CN = BV->getConstantSplatValue();
+
+ // BuildVectors can truncate their operands. Ignore that case here.
+ if (CN && CN->getValueType(0) == N.getValueType().getScalarType())
+ return CN;
+ }
return nullptr;
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index fb7d1b18d8b..3a8a5f9601f 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -6603,28 +6603,16 @@ bool BuildVectorSDNode::isConstantSplat(APInt &SplatValue,
return true;
}
-SDValue BuildVectorSDNode::getConstantSplatValue() const {
- SDValue Splatted;
- for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
- SDValue Op = getOperand(i);
- if (Op.getOpcode() == ISD::UNDEF)
- continue;
- if (Op.getOpcode() != ISD::Constant && Op.getOpcode() != ISD::ConstantFP)
- return SDValue();
-
- if (!Splatted)
- Splatted = Op;
- else if (Splatted != Op)
- return SDValue();
- }
+ConstantSDNode *BuildVectorSDNode::getConstantSplatValue() const {
+ SDValue Op0 = getOperand(0);
+ if (Op0.getOpcode() != ISD::Constant)
+ return nullptr;
- if (!Splatted) {
- assert(getOperand(0).getOpcode() == ISD::UNDEF &&
- "Can only have a splat without a constant for all undefs.");
- return getOperand(0);
- }
+ for (unsigned i = 1, e = getNumOperands(); i != e; ++i)
+ if (getOperand(i) != Op0)
+ return nullptr;
- return Splatted;
+ return cast<ConstantSDNode>(Op0);
}
bool BuildVectorSDNode::isConstant() const {
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 1b3e42848bf..ad91d4a87c1 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -1152,15 +1152,14 @@ bool TargetLowering::isConstTrueVal(const SDNode *N) const {
bool IsVec = false;
const ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N);
- if (!CN)
- if (auto *BV = dyn_cast<BuildVectorSDNode>(N))
- if (SDValue Splat = BV->getConstantSplatValue())
- if (auto *SplatCN = dyn_cast<ConstantSDNode>(Splat)) {
- IsVec = true;
- CN = SplatCN;
- }
- if (!CN)
- return false;
+ if (!CN) {
+ const BuildVectorSDNode *BV = dyn_cast<BuildVectorSDNode>(N);
+ if (!BV)
+ return false;
+
+ IsVec = true;
+ CN = BV->getConstantSplatValue();
+ }
switch (getBooleanContents(IsVec)) {
case UndefinedBooleanContent:
@@ -1180,15 +1179,14 @@ bool TargetLowering::isConstFalseVal(const SDNode *N) const {
bool IsVec = false;
const ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N);
- if (!CN)
- if (auto *BV = dyn_cast<BuildVectorSDNode>(N))
- if (SDValue Splat = BV->getConstantSplatValue())
- if (auto *SplatCN = dyn_cast<ConstantSDNode>(Splat)) {
- IsVec = true;
- CN = SplatCN;
- }
- if (!CN)
- return false;
+ if (!CN) {
+ const BuildVectorSDNode *BV = dyn_cast<BuildVectorSDNode>(N);
+ if (!BV)
+ return false;
+
+ IsVec = true;
+ CN = BV->getConstantSplatValue();
+ }
if (getBooleanContents(IsVec) == UndefinedBooleanContent)
return !CN->getAPIntValue()[0];
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 61accea84d1..4748daae49c 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -4858,6 +4858,19 @@ static bool ShouldXformToMOVLP(SDNode *V1, SDNode *V2,
return true;
}
+/// isSplatVector - Returns true if N is a BUILD_VECTOR node whose elements are
+/// all the same.
+static bool isSplatVector(SDNode *N) {
+ if (N->getOpcode() != ISD::BUILD_VECTOR)
+ return false;
+
+ SDValue SplatValue = N->getOperand(0);
+ for (unsigned i = 1, e = N->getNumOperands(); i != e; ++i)
+ if (N->getOperand(i) != SplatValue)
+ return false;
+ return true;
+}
+
/// isZeroShuffle - Returns true if N is a VECTOR_SHUFFLE that can be resolved
/// to an zero vector.
/// FIXME: move to dag combiner / method on ShuffleVectorSDNode
@@ -5766,20 +5779,17 @@ static SDValue LowerVectorBroadcast(SDValue Op, const X86Subtarget* Subtarget,
return SDValue();
case ISD::BUILD_VECTOR: {
- auto *BVOp = cast<BuildVectorSDNode>(Op.getNode());
// The BUILD_VECTOR node must be a splat.
- SDValue Splat = BVOp->getConstantSplatValue();
- if (!Splat)
+ if (!isSplatVector(Op.getNode()))
return SDValue();
- Ld = Splat;
+ Ld = Op.getOperand(0);
ConstSplatVal = (Ld.getOpcode() == ISD::Constant ||
Ld.getOpcode() == ISD::ConstantFP);
// The suspected load node has several users. Make sure that all
// of its users are from the BUILD_VECTOR node.
// Constants may have multiple users.
- // FIXME: This doesn't make sense if the build vector contains undefs.
if (!ConstSplatVal && !Ld->hasNUsesOfValue(VT.getVectorNumElements(), 0))
return SDValue();
break;
@@ -9406,12 +9416,8 @@ X86TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const {
bool Commuted = false;
// FIXME: This should also accept a bitcast of a splat? Be careful, not
// 1,1,1,1 -> v8i16 though.
- if (auto *BVOp = dyn_cast<BuildVectorSDNode>(V1.getNode()))
- if (BVOp->getConstantSplatValue())
- V1IsSplat = true;
- if (auto *BVOp = dyn_cast<BuildVectorSDNode>(V2.getNode()))
- if (BVOp->getConstantSplatValue())
- V2IsSplat = true;
+ V1IsSplat = isSplatVector(V1.getNode());
+ V2IsSplat = isSplatVector(V2.getNode());
// Canonicalize the splat or undef, if present, to be on the RHS.
if (!V2IsUndef && V1IsSplat && !V2IsSplat) {
@@ -15206,11 +15212,10 @@ static SDValue LowerScalarImmediateShift(SDValue Op, SelectionDAG &DAG,
SDValue Amt = Op.getOperand(1);
// Optimize shl/srl/sra with constant shift amount.
- if (auto *BVAmt = dyn_cast<BuildVectorSDNode>(Amt)) {
- if (SDValue Splat = BVAmt->getConstantSplatValue()) {
- uint64_t ShiftAmt = Splat.getOpcode() == ISD::UNDEF
- ? 0
- : cast<ConstantSDNode>(Splat)->getZExtValue();
+ if (isSplatVector(Amt.getNode())) {
+ SDValue SclrAmt = Amt->getOperand(0);
+ if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(SclrAmt)) {
+ uint64_t ShiftAmt = C->getZExtValue();
if (VT == MVT::v2i64 || VT == MVT::v4i32 || VT == MVT::v8i16 ||
(Subtarget->hasInt256() &&
@@ -19459,35 +19464,27 @@ static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG &DAG,
Other->getOpcode() == ISD::SUB && DAG.isEqualTo(OpRHS, CondRHS))
return DAG.getNode(X86ISD::SUBUS, DL, VT, OpLHS, OpRHS);
- if (auto *OpRHSBV = dyn_cast<BuildVectorSDNode>(OpRHS)) {
- SDValue OpRHSSplat = OpRHSBV->getConstantSplatValue();
- auto *OpRHSSplatConst = dyn_cast<ConstantSDNode>(OpRHSSplat);
- if (auto *CondRHSBV = dyn_cast<BuildVectorSDNode>(CondRHS)) {
- // If the RHS is a constant we have to reverse the const
- // canonicalization.
- // x > C-1 ? x+-C : 0 --> subus x, C
- SDValue CondRHSSplat = CondRHSBV->getConstantSplatValue();
- auto *CondRHSSplatConst = dyn_cast<ConstantSDNode>(CondRHSSplat);
- if (CC == ISD::SETUGT && Other->getOpcode() == ISD::ADD &&
- CondRHSSplatConst && OpRHSSplatConst) {
- APInt A = OpRHSSplatConst->getAPIntValue();
- if (CondRHSSplatConst->getAPIntValue() == -A - 1)
- return DAG.getNode(X86ISD::SUBUS, DL, VT, OpLHS,
- DAG.getConstant(-A, VT));
- }
- }
+ // If the RHS is a constant we have to reverse the const canonicalization.
+ // x > C-1 ? x+-C : 0 --> subus x, C
+ if (CC == ISD::SETUGT && Other->getOpcode() == ISD::ADD &&
+ isSplatVector(CondRHS.getNode()) && isSplatVector(OpRHS.getNode())) {
+ APInt A = cast<ConstantSDNode>(OpRHS.getOperand(0))->getAPIntValue();
+ if (CondRHS.getConstantOperandVal(0) == -A-1)
+ return DAG.getNode(X86ISD::SUBUS, DL, VT, OpLHS,
+ DAG.getConstant(-A, VT));
+ }
- // Another special case: If C was a sign bit, the sub has been
- // canonicalized into a xor.
- // FIXME: Would it be better to use computeKnownBits to determine
- // whether it's safe to decanonicalize the xor?
- // x s< 0 ? x^C : 0 --> subus x, C
- if (CC == ISD::SETLT && Other->getOpcode() == ISD::XOR &&
- ISD::isBuildVectorAllZeros(CondRHS.getNode()) && OpRHSSplatConst) {
- APInt A = OpRHSSplatConst->getAPIntValue();
- if (A.isSignBit())
- return DAG.getNode(X86ISD::SUBUS, DL, VT, OpLHS, OpRHS);
- }
+ // Another special case: If C was a sign bit, the sub has been
+ // canonicalized into a xor.
+ // FIXME: Would it be better to use computeKnownBits to determine whether
+ // it's safe to decanonicalize the xor?
+ // x s< 0 ? x^C : 0 --> subus x, C
+ if (CC == ISD::SETLT && Other->getOpcode() == ISD::XOR &&
+ ISD::isBuildVectorAllZeros(CondRHS.getNode()) &&
+ isSplatVector(OpRHS.getNode())) {
+ APInt A = cast<ConstantSDNode>(OpRHS.getOperand(0))->getAPIntValue();
+ if (A.isSignBit())
+ return DAG.getNode(X86ISD::SUBUS, DL, VT, OpLHS, OpRHS);
}
}
}
@@ -20196,16 +20193,16 @@ static SDValue PerformSHLCombine(SDNode *N, SelectionDAG &DAG) {
// vector operations in many cases. Also, on sandybridge ADD is faster than
// shl.
// (shl V, 1) -> add V,V
- if (auto *N1BV = dyn_cast<BuildVectorSDNode>(N1))
- if (SDValue N1Splat = N1BV->getConstantSplatValue()) {
- assert(N0.getValueType().isVector() && "Invalid vector shift type");
- // We shift all of the values by one. In many cases we do not have
- // hardware support for this operation. This is better expressed as an ADD
- // of two values.
- if (N1Splat.getOpcode() == ISD::Constant &&
- cast<ConstantSDNode>(N1Splat)->getZExtValue() == 1)
- return DAG.getNode(ISD::ADD, SDLoc(N), VT, N0, N0);
+ if (isSplatVector(N1.getNode())) {
+ assert(N0.getValueType().isVector() && "Invalid vector shift type");
+ ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1->getOperand(0));
+ // We shift all of the values by one. In many cases we do not have
+ // hardware support for this operation. This is better expressed as an ADD
+ // of two values.
+ if (N1C && (1 == N1C->getZExtValue())) {
+ return DAG.getNode(ISD::ADD, SDLoc(N), VT, N0, N0);
}
+ }
return SDValue();
}
@@ -20224,19 +20221,20 @@ static SDValue performShiftToAllZeros(SDNode *N, SelectionDAG &DAG,
SDValue Amt = N->getOperand(1);
SDLoc DL(N);
- if (auto *AmtBV = dyn_cast<BuildVectorSDNode>(Amt))
- if (SDValue AmtSplat = AmtBV->getConstantSplatValue())
- if (auto *AmtConst = dyn_cast<ConstantSDNode>(AmtSplat)) {
- APInt ShiftAmt = AmtConst->getAPIntValue();
- unsigned MaxAmount = VT.getVectorElementType().getSizeInBits();
-
- // SSE2/AVX2 logical shifts always return a vector of 0s
- // if the shift amount is bigger than or equal to
- // the element size. The constant shift amount will be
- // encoded as a 8-bit immediate.
- if (ShiftAmt.trunc(8).uge(MaxAmount))
- return getZeroVector(VT, Subtarget, DAG, DL);
- }
+ if (isSplatVector(Amt.getNode())) {
+ SDValue SclrAmt = Amt->getOperand(0);
+ if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(SclrAmt)) {
+ APInt ShiftAmt = C->getAPIntValue();
+ unsigned MaxAmount = VT.getVectorElementType().getSizeInBits();
+
+ // SSE2/AVX2 logical shifts always return a vector of 0s
+ // if the shift amount is bigger than or equal to
+ // the element size. The constant shift amount will be
+ // encoded as a 8-bit immediate.
+ if (ShiftAmt.trunc(8).uge(MaxAmount))
+ return getZeroVector(VT, Subtarget, DAG, DL);
+ }
+ }
return SDValue();
}
@@ -20430,10 +20428,9 @@ static SDValue WidenMaskArithmetic(SDNode *N, SelectionDAG &DAG,
// The right side has to be a 'trunc' or a constant vector.
bool RHSTrunc = N1.getOpcode() == ISD::TRUNCATE;
- SDValue RHSConstSplat;
- if (auto *RHSBV = dyn_cast<BuildVectorSDNode>(N1))
- RHSConstSplat = RHSBV->getConstantSplatValue();
- if (!RHSTrunc && !RHSConstSplat)
+ bool RHSConst = (isSplatVector(N1.getNode()) &&
+ isa<ConstantSDNode>(N1->getOperand(0)));
+ if (!RHSTrunc && !RHSConst)
return SDValue();
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
@@ -20443,9 +20440,9 @@ static SDValue WidenMaskArithmetic(SDNode *N, SelectionDAG &DAG,
// Set N0 and N1 to hold the inputs to the new wide operation.
N0 = N0->getOperand(0);
- if (RHSConstSplat) {
+ if (RHSConst) {
N1 = DAG.getNode(ISD::ZERO_EXTEND, DL, WideVT.getScalarType(),
- RHSConstSplat);
+ N1->getOperand(0));
SmallVector<SDValue, 8> C(WideVT.getVectorNumElements(), N1);
N1 = DAG.getNode(ISD::BUILD_VECTOR, DL, WideVT, C);
} else if (RHSTrunc) {
@@ -20591,10 +20588,12 @@ static SDValue PerformOrCombine(SDNode *N, SelectionDAG &DAG,
unsigned EltBits = MaskVT.getVectorElementType().getSizeInBits();
unsigned SraAmt = ~0;
if (Mask.getOpcode() == ISD::SRA) {
- if (auto *AmtBV = dyn_cast<BuildVectorSDNode>(Mask.getOperand(1)))
- if (SDValue AmtSplat = AmtBV->getConstantSplatValue())
- if (auto *AmtConst = dyn_cast<ConstantSDNode>(AmtSplat))
- SraAmt = AmtConst->getZExtValue();
+ SDValue Amt = Mask.getOperand(1);
+ if (isSplatVector(Amt.getNode())) {
+ SDValue SclrAmt = Amt->getOperand(0);
+ if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(SclrAmt))
+ SraAmt = C->getZExtValue();
+ }
} else if (Mask.getOpcode() == X86ISD::VSRAI) {
SDValue SraC = Mask.getOperand(1);
SraAmt = cast<ConstantSDNode>(SraC)->getZExtValue();
diff --git a/llvm/test/CodeGen/X86/vector-gep.ll b/llvm/test/CodeGen/X86/vector-gep.ll
index 291cc11f55b..3f7ee3aa3e4 100644
--- a/llvm/test/CodeGen/X86/vector-gep.ll
+++ b/llvm/test/CodeGen/X86/vector-gep.ll
@@ -5,7 +5,7 @@
define <4 x i32*> @AGEP0(i32* %ptr) nounwind {
entry:
;CHECK-LABEL: AGEP0
-;CHECK: vpshufd {{.*}} xmm0 = mem[0,0,0,0]
+;CHECK: vbroadcast
;CHECK-NEXT: vpaddd
;CHECK-NEXT: ret
%vecinit.i = insertelement <4 x i32*> undef, i32* %ptr, i32 0
diff --git a/llvm/test/CodeGen/X86/widen_cast-4.ll b/llvm/test/CodeGen/X86/widen_cast-4.ll
index 19b84f19a4f..1bc06a77cbf 100644
--- a/llvm/test/CodeGen/X86/widen_cast-4.ll
+++ b/llvm/test/CodeGen/X86/widen_cast-4.ll
@@ -1,9 +1,8 @@
; RUN: llc < %s -march=x86 -mattr=+sse4.2 | FileCheck %s
-; RUN: llc < %s -march=x86 -mattr=+sse4.2 -x86-experimental-vector-widening-legalization | FileCheck %s --check-prefix=CHECK-WIDE
+; CHECK: psraw
+; CHECK: psraw
define void @update(i64* %dst_i, i64* %src_i, i32 %n) nounwind {
-; CHECK-LABEL: update:
-; CHECK-WIDE-LABEL: update:
entry:
%dst_i.addr = alloca i64* ; <i64**> [#uses=2]
%src_i.addr = alloca i64* ; <i64**> [#uses=2]
@@ -45,26 +44,6 @@ forbody: ; preds = %forcond
%shr = ashr <8 x i8> %add, < i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2, i8 2 > ; <<8 x i8>> [#uses=1]
store <8 x i8> %shr, <8 x i8>* %arrayidx10
br label %forinc
-; CHECK: %forbody
-; CHECK: pmovzxbw
-; CHECK-NEXT: paddw
-; CHECK-NEXT: psllw $8
-; CHECK-NEXT: psraw $8
-; CHECK-NEXT: psraw $2
-; CHECK-NEXT: pshufb
-; CHECK-NEXT: movlpd
-;
-; FIXME: We shouldn't require both a movd and an insert.
-; CHECK-WIDE: %forbody
-; CHECK-WIDE: movd
-; CHECK-WIDE-NEXT: pinsrd
-; CHECK-WIDE-NEXT: paddb
-; CHECK-WIDE-NEXT: psrlw $2
-; CHECK-WIDE-NEXT: pand
-; CHECK-WIDE-NEXT: pxor
-; CHECK-WIDE-NEXT: psubb
-; CHECK-WIDE-NEXT: pextrd
-; CHECK-WIDE-NEXT: movd
forinc: ; preds = %forbody
%tmp15 = load i32* %i ; <i32> [#uses=1]
OpenPOWER on IntegriCloud