summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp10
-rw-r--r--llvm/test/CodeGen/X86/and-load-fold.ll15
2 files changed, 22 insertions, 3 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index c141d63236e..444ea2319e7 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -2912,9 +2912,13 @@ SDValue DAGCombiner::visitAND(SDNode *N) {
SplatBitSize = SplatBitSize * 2)
SplatValue |= SplatValue.shl(SplatBitSize);
- Constant = APInt::getAllOnesValue(BitWidth);
- for (unsigned i = 0, n = SplatBitSize/BitWidth; i < n; ++i)
- Constant &= SplatValue.lshr(i*BitWidth).zextOrTrunc(BitWidth);
+ // Make sure that variable 'Constant' is only set if 'SplatBitSize' is a
+ // multiple of 'BitWidth'. Otherwise, we could propagate a wrong value.
+ if (SplatBitSize % BitWidth == 0) {
+ Constant = APInt::getAllOnesValue(BitWidth);
+ for (unsigned i = 0, n = SplatBitSize/BitWidth; i < n; ++i)
+ Constant &= SplatValue.lshr(i*BitWidth).zextOrTrunc(BitWidth);
+ }
}
}
diff --git a/llvm/test/CodeGen/X86/and-load-fold.ll b/llvm/test/CodeGen/X86/and-load-fold.ll
new file mode 100644
index 00000000000..29ab3242ce2
--- /dev/null
+++ b/llvm/test/CodeGen/X86/and-load-fold.ll
@@ -0,0 +1,15 @@
+; RUN: llc -mtriple=x86_64-unknown-unknown -mcpu=generic < %s | FileCheck %s
+
+; Verify that the DAGCombiner doesn't wrongly remove the 'and' from the dag.
+
+define i8 @foo(<4 x i8>* %V) {
+; CHECK-LABEL: foo:
+; CHECK: pand
+; CHECK: ret
+entry:
+ %Vp = bitcast <4 x i8>* %V to <3 x i8>*
+ %V3i8 = load <3 x i8>, <3 x i8>* %Vp, align 4
+ %0 = and <3 x i8> %V3i8, <i8 undef, i8 undef, i8 95>
+ %1 = extractelement <3 x i8> %0, i64 2
+ ret i8 %1
+}
OpenPOWER on IntegriCloud