[llvm] [InstCombine] Preserve nuw in canonicalizeGEPOfConstGEPI8() (PR #151533)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 31 08:01:57 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Nikita Popov (nikic)
<details>
<summary>Changes</summary>
Proof: https://alive2.llvm.org/ce/z/vC239S
---
Full diff: https://github.com/llvm/llvm-project/pull/151533.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/InstCombine/InstructionCombining.cpp (+8-2)
- (modified) llvm/test/Transforms/InstCombine/gepofconstgepi8.ll (+75)
``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 9e333202fb2e7..d5896a3041ff6 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -2652,9 +2652,15 @@ static Instruction *canonicalizeGEPOfConstGEPI8(GetElementPtrInst &GEP,
APInt NewOffset = TypeSize * *C2 + *C1;
if (NewOffset.isZero() ||
(Src->hasOneUse() && GEP.getOperand(1)->hasOneUse())) {
+ GEPNoWrapFlags Flags = GEPNoWrapFlags::none();
+ if (GEP.hasNoUnsignedWrap() &&
+ cast<GEPOperator>(Src)->hasNoUnsignedWrap() &&
+ match(GEP.getOperand(1), m_NUWAddLike(m_Value(), m_Value())))
+ Flags |= GEPNoWrapFlags::noUnsignedWrap();
+
Value *GEPConst =
- IC.Builder.CreatePtrAdd(Base, IC.Builder.getInt(NewOffset));
- return GetElementPtrInst::Create(BaseType, GEPConst, VarIndex);
+ IC.Builder.CreatePtrAdd(Base, IC.Builder.getInt(NewOffset), "", Flags);
+ return GetElementPtrInst::Create(BaseType, GEPConst, VarIndex, Flags);
}
return nullptr;
diff --git a/llvm/test/Transforms/InstCombine/gepofconstgepi8.ll b/llvm/test/Transforms/InstCombine/gepofconstgepi8.ll
index a92e0c263d357..63553189cca11 100644
--- a/llvm/test/Transforms/InstCombine/gepofconstgepi8.ll
+++ b/llvm/test/Transforms/InstCombine/gepofconstgepi8.ll
@@ -293,3 +293,78 @@ entry:
%p2 = getelementptr <vscale x 4 x i32>, ptr %p1, i64 %index
ret ptr %p2
}
+
+define ptr @test_all_nuw(ptr %base, i64 %a) {
+; CHECK-LABEL: define ptr @test_all_nuw(
+; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP0:%.*]] = getelementptr nuw i8, ptr [[BASE]], i64 9
+; CHECK-NEXT: [[P2:%.*]] = getelementptr nuw i32, ptr [[TMP0]], i64 [[A]]
+; CHECK-NEXT: ret ptr [[P2]]
+;
+entry:
+ %p1 = getelementptr nuw i8, ptr %base, i64 1
+ %index = add nuw i64 %a, 2
+ %p2 = getelementptr nuw i32, ptr %p1, i64 %index
+ ret ptr %p2
+}
+
+define ptr @test_all_partial_nuw1(ptr %base, i64 %a) {
+; CHECK-LABEL: define ptr @test_all_partial_nuw1(
+; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[BASE]], i64 9
+; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[TMP0]], i64 [[A]]
+; CHECK-NEXT: ret ptr [[P2]]
+;
+entry:
+ %p1 = getelementptr i8, ptr %base, i64 1
+ %index = add nuw i64 %a, 2
+ %p2 = getelementptr nuw i32, ptr %p1, i64 %index
+ ret ptr %p2
+}
+
+define ptr @test_all_partial_nuw2(ptr %base, i64 %a) {
+; CHECK-LABEL: define ptr @test_all_partial_nuw2(
+; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[BASE]], i64 9
+; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[TMP0]], i64 [[A]]
+; CHECK-NEXT: ret ptr [[P2]]
+;
+entry:
+ %p1 = getelementptr nuw i8, ptr %base, i64 1
+ %index = add i64 %a, 2
+ %p2 = getelementptr nuw i32, ptr %p1, i64 %index
+ ret ptr %p2
+}
+
+define ptr @test_all_partial_nuw3(ptr %base, i64 %a) {
+; CHECK-LABEL: define ptr @test_all_partial_nuw3(
+; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[BASE]], i64 9
+; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[TMP0]], i64 [[A]]
+; CHECK-NEXT: ret ptr [[P2]]
+;
+entry:
+ %p1 = getelementptr nuw i8, ptr %base, i64 1
+ %index = add nuw i64 %a, 2
+ %p2 = getelementptr i32, ptr %p1, i64 %index
+ ret ptr %p2
+}
+
+define ptr @test_all_nuw_disjoint(ptr %base, i64 %a) {
+; CHECK-LABEL: define ptr @test_all_nuw_disjoint(
+; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP0:%.*]] = getelementptr nuw i8, ptr [[BASE]], i64 9
+; CHECK-NEXT: [[P2:%.*]] = getelementptr nuw i32, ptr [[TMP0]], i64 [[A]]
+; CHECK-NEXT: ret ptr [[P2]]
+;
+entry:
+ %p1 = getelementptr nuw i8, ptr %base, i64 1
+ %index = or disjoint i64 %a, 2
+ %p2 = getelementptr nuw i32, ptr %p1, i64 %index
+ ret ptr %p2
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/151533
More information about the llvm-commits
mailing list