From 15d2c3fb00757119263b8ad39a29af26c056f228 Mon Sep 17 00:00:00 2001 From: Andrea Di Biagio Date: Sat, 7 Mar 2015 12:24:55 +0000 Subject: [PATCH] [DAGCombiner] Fix wrong folding of AND dag nodes. This patch fixes the logic in the DAGCombiner that folds an AND node according to rule: (and (X (load V)), C) -> (X (load V)) An AND between a vector load 'X' and a constant build_vector 'C' can be folded into the load itself only if we can prove that the AND operation is redundant. The algorithm implemented by 'visitAND' firstly computes the splat value 'S' from C, and then checks if S has the lower 'B' bits set (where B is the size in bits of the vector element type). The algorithm takes into account also the 'undef' bits in the splat mask. Unfortunately, the algorithm only worked under the assumption that the size of S is a multiple of the vector element type. With this patch, we conservatively avoid folding the AND if the splat bits are not compatible with the vector element type. Added X86 test and-load-fold.ll Differential Revision: http://reviews.llvm.org/D8085 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@231563 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 10 +++++++--- test/CodeGen/X86/and-load-fold.ll | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 test/CodeGen/X86/and-load-fold.ll diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index c141d63236e..444ea2319e7 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/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/test/CodeGen/X86/and-load-fold.ll b/test/CodeGen/X86/and-load-fold.ll new file mode 100644 index 00000000000..29ab3242ce2 --- /dev/null +++ b/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, + %1 = extractelement <3 x i8> %0, i64 2 + ret i8 %1 +}