[llvm] [InstCombine] Propagate exact flags in shift-combines (PR #88340)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 11 07:05:35 PDT 2024
https://github.com/AtariDreams updated https://github.com/llvm/llvm-project/pull/88340
>From a2fc0c24fd5275a72083d7d8438c3de6ae325d81 Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Wed, 10 Apr 2024 22:38:40 -0400
Subject: [PATCH 1/2] [InstCombine] Pre-commit tests (NFC)
---
llvm/test/Transforms/InstCombine/lshr.ll | 28 ++++++++++++
llvm/test/Transforms/InstCombine/shift.ll | 56 +++++++++++++++++++++++
2 files changed, 84 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/lshr.ll b/llvm/test/Transforms/InstCombine/lshr.ll
index 7d611ba188d6b4..802747607ef3c3 100644
--- a/llvm/test/Transforms/InstCombine/lshr.ll
+++ b/llvm/test/Transforms/InstCombine/lshr.ll
@@ -191,6 +191,34 @@ define <2 x i8> @shl_add_commute_vec(<2 x i8> %x, <2 x i8> %py) {
ret <2 x i8> %r
}
+define i8 @shl_add2(i8 %x, i8 %y) {
+; CHECK-LABEL: @shl_add2(
+; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 [[Y:%.*]], 2
+; CHECK-NEXT: [[TMP2:%.*]] = add i8 [[TMP1]], [[X:%.*]]
+; CHECK-NEXT: [[R:%.*]] = and i8 [[TMP2]], 63
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %l = shl i8 %x, 2
+ %a = add i8 %l, %y
+ %r = lshr exact i8 %a, 2
+ ret i8 %r
+}
+
+define <2 x i8> @shl_add_commute_vec2(<2 x i8> %x, <2 x i8> %py) {
+; CHECK-LABEL: @shl_add_commute_vec2(
+; CHECK-NEXT: [[Y:%.*]] = mul <2 x i8> [[PY:%.*]], [[PY]]
+; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i8> [[Y]], <i8 3, i8 3>
+; CHECK-NEXT: [[TMP2:%.*]] = add <2 x i8> [[TMP1]], [[X:%.*]]
+; CHECK-NEXT: [[R:%.*]] = and <2 x i8> [[TMP2]], <i8 31, i8 31>
+; CHECK-NEXT: ret <2 x i8> [[R]]
+;
+ %y = mul <2 x i8> %py, %py ; thwart complexity-based canonicalization
+ %l = shl <2 x i8> %x, <i8 3, i8 3>
+ %a = add <2 x i8> %y, %l
+ %r = lshr exact <2 x i8> %a, <i8 3, i8 3>
+ ret <2 x i8> %r
+}
+
define i32 @shl_add_use1(i32 %x, i32 %y) {
; CHECK-LABEL: @shl_add_use1(
; CHECK-NEXT: [[L:%.*]] = shl i32 [[X:%.*]], 2
diff --git a/llvm/test/Transforms/InstCombine/shift.ll b/llvm/test/Transforms/InstCombine/shift.ll
index bb8661919c89f5..eecb3ba3870c23 100644
--- a/llvm/test/Transforms/InstCombine/shift.ll
+++ b/llvm/test/Transforms/InstCombine/shift.ll
@@ -433,6 +433,34 @@ entry:
ret i32 %i10
}
+define i32 @test29_exact(i64 %d18) {
+; CHECK-LABEL: @test29_exact(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i64 [[D18:%.*]], 63
+; CHECK-NEXT: [[I101:%.*]] = trunc i64 [[SUM_SHIFT]] to i32
+; CHECK-NEXT: ret i32 [[I101]]
+;
+entry:
+ %i916 = lshr exact i64 %d18, 32
+ %i917 = trunc i64 %i916 to i32
+ %i10 = lshr exact i32 %i917, 31
+ ret i32 %i10
+}
+
+define i32 @test29_exact_fail(i64 %d18) {
+; CHECK-LABEL: @test29_exact_fail(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i64 [[D18:%.*]], 63
+; CHECK-NEXT: [[I101:%.*]] = trunc i64 [[SUM_SHIFT]] to i32
+; CHECK-NEXT: ret i32 [[I101]]
+;
+entry:
+ %i916 = lshr exact i64 %d18, 32
+ %i917 = trunc i64 %i916 to i32
+ %i10 = lshr i32 %i917, 31
+ ret i32 %i10
+}
+
define <2 x i32> @test29_uniform(<2 x i64> %d18) {
; CHECK-LABEL: @test29_uniform(
; CHECK-NEXT: entry:
@@ -447,6 +475,34 @@ entry:
ret <2 x i32> %i10
}
+define <2 x i32> @test29_uniform_exact(<2 x i64> %d18) {
+; CHECK-LABEL: @test29_uniform_exact(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr <2 x i64> [[D18:%.*]], <i64 63, i64 63>
+; CHECK-NEXT: [[I101:%.*]] = trunc <2 x i64> [[SUM_SHIFT]] to <2 x i32>
+; CHECK-NEXT: ret <2 x i32> [[I101]]
+;
+entry:
+ %i916 = lshr exact <2 x i64> %d18, <i64 32, i64 32>
+ %i917 = trunc <2 x i64> %i916 to <2 x i32>
+ %i10 = lshr exact <2 x i32> %i917, <i32 31, i32 31>
+ ret <2 x i32> %i10
+}
+
+define <2 x i32> @test29_uniform_exact_fail(<2 x i64> %d18) {
+; CHECK-LABEL: @test29_uniform_exact_fail(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr <2 x i64> [[D18:%.*]], <i64 63, i64 63>
+; CHECK-NEXT: [[I101:%.*]] = trunc <2 x i64> [[SUM_SHIFT]] to <2 x i32>
+; CHECK-NEXT: ret <2 x i32> [[I101]]
+;
+entry:
+ %i916 = lshr <2 x i64> %d18, <i64 32, i64 32>
+ %i917 = trunc <2 x i64> %i916 to <2 x i32>
+ %i10 = lshr exact <2 x i32> %i917, <i32 31, i32 31>
+ ret <2 x i32> %i10
+}
+
define <2 x i32> @test29_nonuniform(<2 x i64> %d18) {
; CHECK-LABEL: @test29_nonuniform(
; CHECK-NEXT: entry:
>From 19add43efed5ec72a8e4c865e4266acb63b240d5 Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Wed, 10 Apr 2024 21:56:13 -0400
Subject: [PATCH 2/2] [InstCombine] Propagate exact flags in shift-combines
There were a couple of places where we could propagate exact flags but did not.
This patch addresses some of those places.
Alive 2 Proofs:
https://alive2.llvm.org/ce/z/vmoZrX
https://alive2.llvm.org/ce/z/kspgi5
https://alive2.llvm.org/ce/z/9zxKKA
---
.../Transforms/InstCombine/InstCombineShifts.cpp | 13 +++++++++----
llvm/test/Transforms/InstCombine/lshr.ll | 4 ++--
llvm/test/Transforms/InstCombine/shift.ll | 4 ++--
3 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
index 95aa2119e2d88b..59daaa47322c24 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -1332,7 +1332,7 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) {
if (match(Op0,
m_OneUse(m_c_Add(m_OneUse(m_Shl(m_Value(X), m_Specific(Op1))),
m_Value(Y))))) {
- Value *NewLshr = Builder.CreateLShr(Y, Op1);
+ Value *NewLshr = Builder.CreateLShr(Y, Op1, "", I.isExact());
Value *NewAdd = Builder.CreateAdd(NewLshr, X);
unsigned Op1Val = C->getLimitedValue(BitWidth);
APInt Bits = APInt::getLowBitsSet(BitWidth, BitWidth - Op1Val);
@@ -1398,8 +1398,12 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) {
if (match(Op0, m_LShr(m_Value(X), m_APInt(C1)))) {
// Oversized shifts are simplified to zero in InstSimplify.
unsigned AmtSum = ShAmtC + C1->getZExtValue();
- if (AmtSum < BitWidth)
- return BinaryOperator::CreateLShr(X, ConstantInt::get(Ty, AmtSum));
+ if (AmtSum < BitWidth) {
+ auto *NewLShr =
+ BinaryOperator::CreateLShr(X, ConstantInt::get(Ty, AmtSum));
+ NewLShr->setIsExact(I.isExact() && cast<Instruction>(Op0)->isExact());
+ return NewLShr;
+ }
}
Instruction *TruncSrc;
@@ -1415,7 +1419,8 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) {
// mask instruction is eliminated (and so the use check is relaxed).
if (AmtSum < SrcWidth &&
(TruncSrc->hasOneUse() || C1->uge(SrcWidth - BitWidth))) {
- Value *SumShift = Builder.CreateLShr(X, AmtSum, "sum.shift");
+ Value *SumShift = Builder.CreateLShr(
+ X, AmtSum, "sum.shift", TruncSrc->isExact() && I.isExact());
Value *Trunc = Builder.CreateTrunc(SumShift, Ty, I.getName());
// If the first shift does not cover the number of bits truncated, then
diff --git a/llvm/test/Transforms/InstCombine/lshr.ll b/llvm/test/Transforms/InstCombine/lshr.ll
index 802747607ef3c3..ea35233cb41764 100644
--- a/llvm/test/Transforms/InstCombine/lshr.ll
+++ b/llvm/test/Transforms/InstCombine/lshr.ll
@@ -193,7 +193,7 @@ define <2 x i8> @shl_add_commute_vec(<2 x i8> %x, <2 x i8> %py) {
define i8 @shl_add2(i8 %x, i8 %y) {
; CHECK-LABEL: @shl_add2(
-; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 [[Y:%.*]], 2
+; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i8 [[Y:%.*]], 2
; CHECK-NEXT: [[TMP2:%.*]] = add i8 [[TMP1]], [[X:%.*]]
; CHECK-NEXT: [[R:%.*]] = and i8 [[TMP2]], 63
; CHECK-NEXT: ret i8 [[R]]
@@ -207,7 +207,7 @@ define i8 @shl_add2(i8 %x, i8 %y) {
define <2 x i8> @shl_add_commute_vec2(<2 x i8> %x, <2 x i8> %py) {
; CHECK-LABEL: @shl_add_commute_vec2(
; CHECK-NEXT: [[Y:%.*]] = mul <2 x i8> [[PY:%.*]], [[PY]]
-; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i8> [[Y]], <i8 3, i8 3>
+; CHECK-NEXT: [[TMP1:%.*]] = lshr exact <2 x i8> [[Y]], <i8 3, i8 3>
; CHECK-NEXT: [[TMP2:%.*]] = add <2 x i8> [[TMP1]], [[X:%.*]]
; CHECK-NEXT: [[R:%.*]] = and <2 x i8> [[TMP2]], <i8 31, i8 31>
; CHECK-NEXT: ret <2 x i8> [[R]]
diff --git a/llvm/test/Transforms/InstCombine/shift.ll b/llvm/test/Transforms/InstCombine/shift.ll
index eecb3ba3870c23..5506cd20d42f07 100644
--- a/llvm/test/Transforms/InstCombine/shift.ll
+++ b/llvm/test/Transforms/InstCombine/shift.ll
@@ -436,7 +436,7 @@ entry:
define i32 @test29_exact(i64 %d18) {
; CHECK-LABEL: @test29_exact(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr i64 [[D18:%.*]], 63
+; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr exact i64 [[D18:%.*]], 63
; CHECK-NEXT: [[I101:%.*]] = trunc i64 [[SUM_SHIFT]] to i32
; CHECK-NEXT: ret i32 [[I101]]
;
@@ -478,7 +478,7 @@ entry:
define <2 x i32> @test29_uniform_exact(<2 x i64> %d18) {
; CHECK-LABEL: @test29_uniform_exact(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr <2 x i64> [[D18:%.*]], <i64 63, i64 63>
+; CHECK-NEXT: [[SUM_SHIFT:%.*]] = lshr exact <2 x i64> [[D18:%.*]], <i64 63, i64 63>
; CHECK-NEXT: [[I101:%.*]] = trunc <2 x i64> [[SUM_SHIFT]] to <2 x i32>
; CHECK-NEXT: ret <2 x i32> [[I101]]
;
More information about the llvm-commits
mailing list