[llvm] 5475441 - [InstSimplify] Allow gep inbounds x, 0 -> x in non-refining op replacement

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 14 07:17:44 PDT 2023


Author: Nikita Popov
Date: 2023-07-14T16:14:50+02:00
New Revision: 547544112b60da4c6a75210ca4fc6e3bd05914ec

URL: https://github.com/llvm/llvm-project/commit/547544112b60da4c6a75210ca4fc6e3bd05914ec
DIFF: https://github.com/llvm/llvm-project/commit/547544112b60da4c6a75210ca4fc6e3bd05914ec.diff

LOG: [InstSimplify] Allow gep inbounds x, 0 -> x in non-refining op replacement

After the semantics change from https://reviews.llvm.org/D154051,
gep inbounds x, 0 can no longer produce poison. As such, we can
also perform this fold during non-refining operand replacement
and avoid unnecessary drops of the inbounds flag.

The online alive2 version has not been update to the new
semantics yet, but we can use the following proof locally:

    define ptr @src(ptr %base, i64 %offset) {
      %cmp = icmp eq i64 %offset, 0
      %gep = getelementptr inbounds i8, ptr %base, i64 %offset
      %sel = select i1 %cmp, ptr %base, ptr %gep
      ret ptr %sel
    }

    define ptr @tgt(ptr %base, i64 %offset) {
      %gep = getelementptr inbounds i8, ptr %base, i64 %offset
      ret ptr %gep
    }

Added: 
    

Modified: 
    llvm/lib/Analysis/InstructionSimplify.cpp
    llvm/test/Transforms/InstCombine/select.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index d65bb51f7e2f3b..c7a5f1548585c2 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4320,10 +4320,10 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
         return RepOp;
     }
 
-    if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) {
-      // getelementptr x, 0 -> x
-      if (NewOps.size() == 2 && match(NewOps[1], m_Zero()) &&
-          !GEP->isInBounds())
+    if (isa<GetElementPtrInst>(I)) {
+      // getelementptr x, 0 -> x.
+      // This never returns poison, even if inbounds is set.
+      if (NewOps.size() == 2 && match(NewOps[1], m_Zero()))
         return NewOps[0];
     }
   } else if (MaxRecurse) {

diff  --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll
index e91c468fb67841..fb65d4f3acae4f 100644
--- a/llvm/test/Transforms/InstCombine/select.ll
+++ b/llvm/test/Transforms/InstCombine/select.ll
@@ -2892,10 +2892,9 @@ define i32 @select_replacement_loop2(i32 %arg, i32 %arg2) {
   ret i32 %sel
 }
 
-; TODO: Dropping the inbounds flag should not be necessary for this fold.
 define ptr @select_replacement_gep_inbounds(ptr %base, i64 %offset) {
 ; CHECK-LABEL: @select_replacement_gep_inbounds(
-; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr [[BASE:%.*]], i64 [[OFFSET:%.*]]
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i8, ptr [[BASE:%.*]], i64 [[OFFSET:%.*]]
 ; CHECK-NEXT:    ret ptr [[GEP]]
 ;
   %cmp = icmp eq i64 %offset, 0


        


More information about the llvm-commits mailing list