[PATCH] D60600: [InstCombine] Fix a vector-of-pointers instcombine undef bug.

Neil Henning via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 12 01:59:34 PDT 2019


sheredom created this revision.
sheredom added reviewers: majnemer, uabelho.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

This commit fixes a really fun bug with inst combine where you have a
vector-of-pointers and only one element of this vector is used.
InstCombine correctly notes that an element is not used, and then will
go back through a gep into that vector-of-pointers and set all vector
elements to undef. This is fine in all cases except that the langref
(and a ton of places in the optimizer) requires that indexing into a
struct has the same index for each element of the vector-of-pointers.

To fix the bug I've just made the gep/undef propagation check that the
current type being indexed into is not a struct when doing the undef
propagation.


Repository:
  rL LLVM

https://reviews.llvm.org/D60600

Files:
  lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
  test/Transforms/InstCombine/vector-of-pointers.ll


Index: test/Transforms/InstCombine/vector-of-pointers.ll
===================================================================
--- /dev/null
+++ test/Transforms/InstCombine/vector-of-pointers.ll
@@ -0,0 +1,17 @@
+; RUN: opt -instcombine -S < %s | FileCheck %s
+
+%foo = type { float, i8 }
+
+define void @func(float* %out, [2 x %foo]* %in) {
+  %a = insertelement <2 x [2 x %foo]*> undef, [2 x %foo]* %in, i32 0
+  %b = insertelement <2 x [2 x %foo]*> %a, [2 x %foo]* %in, i32 1
+
+; CHECK: %gep = getelementptr [2 x %foo], <2 x [2 x %foo]*> %b, <2 x i64> <i64 undef, i64 0>, <2 x i64> <i64 undef, i64 1>, <2 x i32> zeroinitializer
+  %gep = getelementptr [2 x %foo], <2 x [2 x %foo]*> %b, <2 x i32> zeroinitializer, <2 x i32> <i32 0, i32 1>, <2 x i32> zeroinitializer
+
+  %extract = extractelement <2 x float*> %gep, i64 1
+
+  %load = load float, float* %extract, align 4
+  store float %load, float* %out
+  ret void
+}
Index: lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
===================================================================
--- lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -1173,17 +1173,38 @@
     // operands we may have.  We know there must be at least one, or we
     // wouldn't have a vector result to get here. Note that we intentionally
     // merge the undef bits here since gepping with either an undef base or
-    // index results in undef. 
-    for (unsigned i = 0; i < I->getNumOperands(); i++) {
+    // index results in undef.
+
+    auto simplifyGEPOperand = [&](unsigned i, bool isIndexStruct) -> bool {
       if (isa<UndefValue>(I->getOperand(i))) {
         // If the entire vector is undefined, just return this info.
         UndefElts = EltMask;
-        return nullptr;
+        return true;
       }
+
       if (I->getOperand(i)->getType()->isVectorTy()) {
-        APInt UndefEltsOp(VWidth, 0);
-        simplifyAndSetOp(I, i, DemandedElts, UndefEltsOp);
-        UndefElts |= UndefEltsOp;
+        // If we have a vector of indices into a struct element of the GEP, and
+        // change a single element this into an undef while preserving the
+        // others, that breaks the guarantee that each index of a
+        // vector-of-pointers into a struct will have the same index.
+        if (!isIndexStruct) {
+          APInt UndefEltsOp(VWidth, 0);
+          simplifyAndSetOp(I, i, DemandedElts, UndefEltsOp);
+          UndefElts |= UndefEltsOp;
+        }
+      }
+
+      return false;
+    };
+
+    if (simplifyGEPOperand(0, false)) {
+      return nullptr;
+    }
+
+    gep_type_iterator GTI = gep_type_begin(cast<GetElementPtrInst>(I));
+    for (unsigned i = 1; i < I->getNumOperands(); i++, GTI++) {
+      if (simplifyGEPOperand(i, GTI.isStruct())) {
+        return nullptr;
       }
     }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D60600.194814.patch
Type: text/x-patch
Size: 2857 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190412/a93e5be1/attachment.bin>


More information about the llvm-commits mailing list