[PATCH] D92364: [MergeICmps] Disable if a GEP does not reference an Argument

Fangrui Song via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 30 22:09:45 PST 2020


MaskRay created this revision.
MaskRay added reviewers: courbet, jyknight.
Herald added subscribers: llvm-commits, hiraditya.
Herald added a project: LLVM.
MaskRay requested review of this revision.

If the pointer operand of a GEP references an instruction defined in a
deleted basic block, after cloning of the GEP and the removal of the
basic block, the GEP will reference undef.

This caused a miscompile which motivated my D92297 <https://reviews.llvm.org/D92297> (before D17993 <https://reviews.llvm.org/D17993>,
nonnull and dereferenceable attributed were not added so MergeICmps were
not triggered.) The new test gep-references-bb.ll demonstrate the issue.

Note: in LLVM 8.0, opt does not delete basic blocks (thus %gep is retained) and
insert new basic blocks. opt can actually optimize gep-references-bb.ll to use a
memcmp. We should try making the test profitable again.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D92364

Files:
  llvm/lib/Transforms/Scalar/MergeICmps.cpp
  llvm/test/Transforms/MergeICmps/X86/gep-references-bb.ll


Index: llvm/test/Transforms/MergeICmps/X86/gep-references-bb.ll
===================================================================
--- /dev/null
+++ llvm/test/Transforms/MergeICmps/X86/gep-references-bb.ll
@@ -0,0 +1,51 @@
+; RUN: opt < %s -S -mergeicmps -verify-dom-info | FileCheck %s
+target triple = "x86_64"
+
+%Triple = type { %Elem0, %Elem1, %Elem2 }
+%Elem0 = type { i32 }
+%Elem1 = type { i32 }
+%Elem2 = type { i32 }
+
+;; %gep does not reference an argument. Disable the optimization because
+;; otherwise the newly created gep may reference undef (after the basic block
+;; defining the pointer operand is deleted).
+;; TODO Optimize with a memcmp.
+; CHECK-LABEL: bb0:
+; CHECK:         load i32, i32* %l0_addr, align 4
+; CHECK:         load i32, i32* %r0_addr, align 4
+; CHECK-LABEL: bb1:
+; CHECK:         load i32, i32* %l1_addr, align 4
+; CHECK:         load i32, i32* %r1_addr, align 4
+; CHECK-LABEL: bb2:
+; CHECK:         load i32, i32* %l2_addr, align 4
+; CHECK:         load i32, i32* %r2_addr, align 4
+define i1 @bug(%Triple* nonnull dereferenceable(12) %lhs, %Triple* nonnull dereferenceable(12) %rhs) {
+bb0:
+  %gep = getelementptr %Triple, %Triple* %rhs, i64 0, i32 0
+  %l0_addr = getelementptr inbounds %Triple, %Triple* %lhs, i64 0, i32 0, i32 0
+  %l0 = load i32, i32* %l0_addr, align 4
+  %r0_addr = getelementptr inbounds %Triple, %Triple* %rhs, i64 0, i32 0, i32 0
+  %r0 = load i32, i32* %r0_addr, align 4
+  %cmp0 = icmp eq i32 %l0, %r0
+  br i1 %cmp0, label %bb1, label %final
+
+bb1:                                           ; preds = %bb0
+  %l1_addr = getelementptr inbounds %Triple, %Triple* %lhs, i64 0, i32 1, i32 0
+  %l1 = load i32, i32* %l1_addr, align 4
+  %r1_addr = getelementptr inbounds %Elem0, %Elem0* %gep, i64 1, i32 0
+  %r1 = load i32, i32* %r1_addr, align 4
+  %cmp1 = icmp eq i32 %l1, %r1
+  br i1 %cmp1, label %bb2, label %final
+
+bb2:                                           ; preds = %bb1
+  %l2_addr = getelementptr inbounds %Triple, %Triple* %lhs, i64 0, i32 2, i32 0
+  %l2 = load i32, i32* %l2_addr, align 4
+  %r2_addr = getelementptr inbounds %Elem0, %Elem0* %gep, i64 2, i32 0
+  %r2 = load i32, i32* %r2_addr, align 4
+  %cmp2 = icmp eq i32 %l2, %r2
+  br label %final
+
+final:                                            ; preds = %bb2, %bb1, %bb0
+  %ret = phi i1 [ false, %bb0 ], [ false, %bb1 ], [ %cmp2, %bb2 ]
+  ret i1 %ret
+}
Index: llvm/lib/Transforms/Scalar/MergeICmps.cpp
===================================================================
--- llvm/lib/Transforms/Scalar/MergeICmps.cpp
+++ llvm/lib/Transforms/Scalar/MergeICmps.cpp
@@ -158,6 +158,8 @@
   if (!GEP)
     return {};
   LLVM_DEBUG(dbgs() << "GEP\n");
+  if (!isa<Argument>(GEP->getPointerOperand()))
+    return {};
   if (GEP->isUsedOutsideOfBlock(LoadI->getParent())) {
     LLVM_DEBUG(dbgs() << "used outside of block\n");
     return {};


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D92364.308540.patch
Type: text/x-patch
Size: 2897 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20201201/1d236785/attachment.bin>


More information about the llvm-commits mailing list