[llvm] 7de492f - [InstCombine] Preserve nuw flag in indexed compare fold
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 2 07:03:56 PDT 2024
Author: Nikita Popov
Date: 2024-10-02T16:03:47+02:00
New Revision: 7de492f90dd733859f5f0dd582860ccc5899dc22
URL: https://github.com/llvm/llvm-project/commit/7de492f90dd733859f5f0dd582860ccc5899dc22
DIFF: https://github.com/llvm/llvm-project/commit/7de492f90dd733859f5f0dd582860ccc5899dc22.diff
LOG: [InstCombine] Preserve nuw flag in indexed compare fold
If all the involved GEPs have the nuw flag, also preserve it on
the resulting adds and GEPs.
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
llvm/test/Transforms/InstCombine/indexed-gep-compares.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index d4d45384ec90e3..b0771ffcc38a83 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -423,7 +423,7 @@ Instruction *InstCombinerImpl::foldCmpLoadFromIndexedGlobal(
/// Returns true if we can rewrite Start as a GEP with pointer Base
/// and some integer offset. The nodes that need to be re-written
/// for this transformation will be added to Explored.
-static bool canRewriteGEPAsOffset(Value *Start, Value *Base,
+static bool canRewriteGEPAsOffset(Value *Start, Value *Base, GEPNoWrapFlags &NW,
const DataLayout &DL,
SetVector<Value *> &Explored) {
SmallVector<Value *, 16> WorkList(1, Start);
@@ -462,6 +462,7 @@ static bool canRewriteGEPAsOffset(Value *Start, Value *Base,
if (!GEP->isInBounds() || count_if(GEP->indices(), IsNonConst) > 1)
return false;
+ NW = NW.intersectForOffsetAdd(GEP->getNoWrapFlags());
if (!Explored.contains(GEP->getOperand(0)))
WorkList.push_back(GEP->getOperand(0));
}
@@ -536,7 +537,7 @@ static void setInsertionPoint(IRBuilder<> &Builder, Value *V,
/// Returns a re-written value of Start as an indexed GEP using Base as a
/// pointer.
-static Value *rewriteGEPAsOffset(Value *Start, Value *Base,
+static Value *rewriteGEPAsOffset(Value *Start, Value *Base, GEPNoWrapFlags NW,
const DataLayout &DL,
SetVector<Value *> &Explored,
InstCombiner &IC) {
@@ -578,8 +579,10 @@ static Value *rewriteGEPAsOffset(Value *Start, Value *Base,
if (isa<ConstantInt>(Op) && cast<ConstantInt>(Op)->isZero())
NewInsts[GEP] = OffsetV;
else
- NewInsts[GEP] = Builder.CreateNSWAdd(
- Op, OffsetV, GEP->getOperand(0)->getName() + ".add");
+ NewInsts[GEP] = Builder.CreateAdd(
+ Op, OffsetV, GEP->getOperand(0)->getName() + ".add",
+ /*NUW=*/NW.hasNoUnsignedWrap(),
+ /*NSW=*/NW.hasNoUnsignedSignedWrap());
continue;
}
if (isa<PHINode>(Val))
@@ -613,8 +616,8 @@ static Value *rewriteGEPAsOffset(Value *Start, Value *Base,
setInsertionPoint(Builder, Val, false);
// Create GEP for external users.
- Value *NewVal = Builder.CreateInBoundsGEP(
- Builder.getInt8Ty(), Base, NewInsts[Val], Val->getName() + ".ptr");
+ Value *NewVal = Builder.CreateGEP(Builder.getInt8Ty(), Base, NewInsts[Val],
+ Val->getName() + ".ptr", NW);
IC.replaceInstUsesWith(*cast<Instruction>(Val), NewVal);
// Add old instruction to worklist for DCE. We don't directly remove it
// here because the original compare is one of the users.
@@ -649,8 +652,8 @@ static Instruction *transformToIndexedCompare(GEPOperator *GEPLHS, Value *RHS,
// The set of nodes that will take part in this transformation.
SetVector<Value *> Nodes;
-
- if (!canRewriteGEPAsOffset(RHS, PtrBase, DL, Nodes))
+ GEPNoWrapFlags NW = GEPLHS->getNoWrapFlags();
+ if (!canRewriteGEPAsOffset(RHS, PtrBase, NW, DL, Nodes))
return nullptr;
// We know we can re-write this as
@@ -659,7 +662,7 @@ static Instruction *transformToIndexedCompare(GEPOperator *GEPLHS, Value *RHS,
// can't have overflow on either side. We can therefore re-write
// this as:
// OFFSET1 cmp OFFSET2
- Value *NewRHS = rewriteGEPAsOffset(RHS, PtrBase, DL, Nodes, IC);
+ Value *NewRHS = rewriteGEPAsOffset(RHS, PtrBase, NW, DL, Nodes, IC);
// RewriteGEPAsOffset has replaced RHS and all of its uses with a re-written
// GEP having PtrBase as the pointer base, and has returned in NewRHS the
diff --git a/llvm/test/Transforms/InstCombine/indexed-gep-compares.ll b/llvm/test/Transforms/InstCombine/indexed-gep-compares.ll
index ef8f5fea4ff7c1..79511cf9e666ff 100644
--- a/llvm/test/Transforms/InstCombine/indexed-gep-compares.ll
+++ b/llvm/test/Transforms/InstCombine/indexed-gep-compares.ll
@@ -32,6 +32,64 @@ bb2:
ret ptr %RHS
}
+define ptr @test1_nuw(ptr %A, i32 %Offset) {
+; CHECK-LABEL: @test1_nuw(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP_IDX:%.*]] = shl nuw nsw i32 [[OFFSET:%.*]], 2
+; CHECK-NEXT: br label [[BB:%.*]]
+; CHECK: bb:
+; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[RHS_ADD]] = add nuw nsw i32 [[RHS_IDX]], 4
+; CHECK-NEXT: [[COND:%.*]] = icmp ugt i32 [[RHS_IDX]], 400
+; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
+; CHECK: bb2:
+; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds nuw i8, ptr [[A:%.*]], i32 [[RHS_IDX]]
+; CHECK-NEXT: ret ptr [[RHS_PTR]]
+;
+entry:
+ %tmp = getelementptr inbounds nuw i32, ptr %A, i32 %Offset
+ br label %bb
+
+bb:
+ %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]
+ %LHS = getelementptr inbounds nuw i32, ptr %A, i32 100
+ %RHS.next = getelementptr inbounds nuw i32, ptr %RHS, i64 1
+ %cond = icmp ult ptr %LHS, %RHS
+ br i1 %cond, label %bb2, label %bb
+
+bb2:
+ ret ptr %RHS
+}
+
+define ptr @test1_not_all_nuw(ptr %A, i32 %Offset) {
+; CHECK-LABEL: @test1_not_all_nuw(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 2
+; CHECK-NEXT: br label [[BB:%.*]]
+; CHECK: bb:
+; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[ENTRY:%.*]] ]
+; CHECK-NEXT: [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 4
+; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 400
+; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
+; CHECK: bb2:
+; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i32 [[RHS_IDX]]
+; CHECK-NEXT: ret ptr [[RHS_PTR]]
+;
+entry:
+ %tmp = getelementptr inbounds i32, ptr %A, i32 %Offset
+ br label %bb
+
+bb:
+ %RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]
+ %LHS = getelementptr inbounds nuw i32, ptr %A, i32 100
+ %RHS.next = getelementptr inbounds nuw i32, ptr %RHS, i64 1
+ %cond = icmp ult ptr %LHS, %RHS
+ br i1 %cond, label %bb2, label %bb
+
+bb2:
+ ret ptr %RHS
+}
+
define ptr at test2(i32 %A, i32 %Offset) {
; CHECK-LABEL: @test2(
; CHECK-NEXT: entry:
More information about the llvm-commits
mailing list