[InstSimplify] Allow gep inbounds x, 0 -> x in non-refining op replacement
authorNikita Popov <npopov@redhat.com>
Fri, 14 Jul 2023 14:14:50 +0000 (16:14 +0200)
committerNikita Popov <npopov@redhat.com>
Fri, 14 Jul 2023 14:14:50 +0000 (16:14 +0200)
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
    }

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

index d65bb51..c7a5f15 100644 (file)
@@ -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) {
index e91c468..fb65d4f 100644 (file)
@@ -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