-
Notifications
You must be signed in to change notification settings - Fork 13.2k
release/18.x: [InstCombine] Fold gep of exact unsigned division (#82334) #82347
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
(cherry picked from commit ec2c770)
Extend the transform added in llvm#76458 to also handle unsigned division. X exact/ Y * Y == X holds independently of whether the division is signed or unsigned. Proofs: https://alive2.llvm.org/ce/z/wFd5Ec (cherry picked from commit 26d4afc)
@dtcxzyw What do you think about merging this PR to the release branch? |
@llvm/pr-subscribers-llvm-transforms Author: None (llvmbot) ChangesRequested by: @nikic Full diff: https://github.com/llvm/llvm-project/pull/82347.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 249f4a7710e046..5d207dcfd18dd4 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -2594,10 +2594,10 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
Value *V;
if ((has_single_bit(TyAllocSize) &&
match(GEP.getOperand(1),
- m_Exact(m_AShr(m_Value(V),
- m_SpecificInt(countr_zero(TyAllocSize)))))) ||
+ m_Exact(m_Shr(m_Value(V),
+ m_SpecificInt(countr_zero(TyAllocSize)))))) ||
match(GEP.getOperand(1),
- m_Exact(m_SDiv(m_Value(V), m_SpecificInt(TyAllocSize))))) {
+ m_Exact(m_IDiv(m_Value(V), m_SpecificInt(TyAllocSize))))) {
GetElementPtrInst *NewGEP = GetElementPtrInst::Create(
Builder.getInt8Ty(), GEP.getPointerOperand(), V);
NewGEP->setIsInBounds(GEP.isInBounds());
diff --git a/llvm/test/Transforms/InstCombine/getelementptr.ll b/llvm/test/Transforms/InstCombine/getelementptr.ll
index 642c3eb2a0e41b..c90b6c9fb29592 100644
--- a/llvm/test/Transforms/InstCombine/getelementptr.ll
+++ b/llvm/test/Transforms/InstCombine/getelementptr.ll
@@ -116,6 +116,7 @@ define void @test_overaligned_vec(i8 %B) {
; CHECK-LABEL: @test_overaligned_vec(
; CHECK-NEXT: store i8 [[B:%.*]], ptr getelementptr inbounds ([10 x i8], ptr @Global, i64 0, i64 2), align 1
; CHECK-NEXT: ret void
+;
%A = getelementptr <2 x half>, ptr @Global, i64 0, i64 1
store i8 %B, ptr %A
ret void
@@ -1473,6 +1474,16 @@ define ptr @gep_sdiv(ptr %p, i64 %off) {
ret ptr %ptr
}
+define ptr @gep_udiv(ptr %p, i64 %off) {
+; CHECK-LABEL: @gep_udiv(
+; CHECK-NEXT: [[PTR:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[OFF:%.*]]
+; CHECK-NEXT: ret ptr [[PTR]]
+;
+ %index = udiv exact i64 %off, 7
+ %ptr = getelementptr %struct.C, ptr %p, i64 %index
+ ret ptr %ptr
+}
+
define <2 x ptr> @gep_sdiv_vec(<2 x ptr> %p, <2 x i64> %off) {
; CHECK-LABEL: @gep_sdiv_vec(
; CHECK-NEXT: [[PTR:%.*]] = getelementptr i8, <2 x ptr> [[P:%.*]], <2 x i64> [[OFF:%.*]]
@@ -1503,6 +1514,16 @@ define ptr @gep_ashr(ptr %p, i64 %off) {
ret ptr %ptr
}
+define ptr @gep_lshr(ptr %p, i64 %off) {
+; CHECK-LABEL: @gep_lshr(
+; CHECK-NEXT: [[PTR:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 [[OFF:%.*]]
+; CHECK-NEXT: ret ptr [[PTR]]
+;
+ %index = lshr exact i64 %off, 2
+ %ptr = getelementptr i32, ptr %p, i64 %index
+ ret ptr %ptr
+}
+
; Negative tests
define ptr @gep_i8(ptr %p, i64 %off) {
@@ -1525,6 +1546,17 @@ define ptr @gep_sdiv_mismatched_size(ptr %p, i64 %off) {
ret ptr %ptr
}
+define ptr @gep_udiv_mismatched_size(ptr %p, i64 %off) {
+; CHECK-LABEL: @gep_udiv_mismatched_size(
+; CHECK-NEXT: [[INDEX:%.*]] = udiv exact i64 [[OFF:%.*]], 20
+; CHECK-NEXT: [[PTR:%.*]] = getelementptr [[STRUCT_C:%.*]], ptr [[P:%.*]], i64 [[INDEX]]
+; CHECK-NEXT: ret ptr [[PTR]]
+;
+ %index = udiv exact i64 %off, 20
+ %ptr = getelementptr %struct.C, ptr %p, i64 %index
+ ret ptr %ptr
+}
+
define ptr @gep_sdiv_without_exact(ptr %p, i64 %off) {
; CHECK-LABEL: @gep_sdiv_without_exact(
; CHECK-NEXT: [[INDEX:%.*]] = sdiv i64 [[OFF:%.*]], 7
@@ -1536,6 +1568,17 @@ define ptr @gep_sdiv_without_exact(ptr %p, i64 %off) {
ret ptr %ptr
}
+define ptr @gep_udiv_without_exact(ptr %p, i64 %off) {
+; CHECK-LABEL: @gep_udiv_without_exact(
+; CHECK-NEXT: [[INDEX:%.*]] = udiv i64 [[OFF:%.*]], 7
+; CHECK-NEXT: [[PTR:%.*]] = getelementptr [[STRUCT_C:%.*]], ptr [[P:%.*]], i64 [[INDEX]]
+; CHECK-NEXT: ret ptr [[PTR]]
+;
+ %index = udiv i64 %off, 7
+ %ptr = getelementptr %struct.C, ptr %p, i64 %index
+ ret ptr %ptr
+}
+
define ptr @gep_ashr_without_exact(ptr %p, i64 %off) {
; CHECK-LABEL: @gep_ashr_without_exact(
; CHECK-NEXT: [[INDEX:%.*]] = ashr i64 [[OFF:%.*]], 2
@@ -1547,6 +1590,17 @@ define ptr @gep_ashr_without_exact(ptr %p, i64 %off) {
ret ptr %ptr
}
+define ptr @gep_lshr_without_exact(ptr %p, i64 %off) {
+; CHECK-LABEL: @gep_lshr_without_exact(
+; CHECK-NEXT: [[INDEX:%.*]] = lshr i64 [[OFF:%.*]], 2
+; CHECK-NEXT: [[PTR:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[INDEX]]
+; CHECK-NEXT: ret ptr [[PTR]]
+;
+ %index = lshr i64 %off, 2
+ %ptr = getelementptr i32, ptr %p, i64 %index
+ ret ptr %ptr
+}
+
define i1 @test_only_used_by_icmp(ptr %a, ptr %b, ptr %c) {
; CHECK-LABEL: @test_only_used_by_icmp(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[B:%.*]], [[C:%.*]]
|
Submitting this for backport, because it mitigates an LLVM 18 optimization regression encountered in Rust. The regression is really in a different area, but I think this is the least intrusive way to mitigate it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM if CI is happy.
Backport ec2c770 26d4afc
Requested by: @nikic