[llvm] [InstCombine] Preserve nuw/exact flags when transforming (C shift (A add nuw C1)) --> ((C shift C1) shift A). (PR #79490)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 26 09:49:27 PST 2024
https://github.com/topperc updated https://github.com/llvm/llvm-project/pull/79490
>From 4d94a55c8f69bf85de56a6f5863ee8801e0b0860 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Thu, 25 Jan 2024 11:32:40 -0800
Subject: [PATCH 1/2] [InstCombine] Preserve nuw/exact flags when transforming
(C shift (A add nuw C1)) --> ((C shift C1) shift A).
If we weren't shifting out any non-zero bits before the transform,
we shouldn't be after.
Example alive2 proofs
https://alive2.llvm.org/ce/z/grqsED
https://alive2.llvm.org/ce/z/wja3g3
https://alive2.llvm.org/ce/z/sfiAUn
---
.../InstCombine/InstCombineShifts.cpp | 7 +++-
llvm/test/Transforms/InstCombine/shift-add.ll | 32 +++++++++++++++++++
2 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
index 54490c46dfaefc..03668f59dfdfb2 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -439,7 +439,12 @@ Instruction *InstCombinerImpl::commonShiftTransforms(BinaryOperator &I) {
if (match(Op0, m_Constant(C)) &&
match(Op1, m_NUWAdd(m_Value(A), m_Constant(C1)))) {
Value *NewC = Builder.CreateBinOp(I.getOpcode(), C, C1);
- return BinaryOperator::Create(I.getOpcode(), NewC, A);
+ BinaryOperator *NewShiftOp = BinaryOperator::Create(I.getOpcode(), NewC, A);
+ if (I.getOpcode() == Instruction::Shl)
+ NewShiftOp->setHasNoUnsignedWrap(I.hasNoUnsignedWrap());
+ else
+ NewShiftOp->setIsExact(I.isExact());
+ return NewShiftOp;
}
unsigned BitWidth = Ty->getScalarSizeInBits();
diff --git a/llvm/test/Transforms/InstCombine/shift-add.ll b/llvm/test/Transforms/InstCombine/shift-add.ll
index 6ea2718abb2bbc..5b8f0c44bde8e5 100644
--- a/llvm/test/Transforms/InstCombine/shift-add.ll
+++ b/llvm/test/Transforms/InstCombine/shift-add.ll
@@ -159,6 +159,38 @@ define i32 @ashr_add_nuw(i32 %x, ptr %p) {
ret i32 %r
}
+; Preserve nuw and exact flags.
+
+define i32 @shl_nuw_add_nuw(i32 %x) {
+; CHECK-LABEL: @shl_nuw_add_nuw(
+; CHECK-NEXT: [[R:%.*]] = shl nuw i32 2, [[X:%.*]]
+; CHECK-NEXT: ret i32 [[R]]
+;
+ %a = add nuw i32 %x, 1
+ %r = shl nuw i32 1, %a
+ ret i32 %r
+}
+
+define i32 @lshr_exact_add_nuw(i32 %x) {
+; CHECK-LABEL: @lshr_exact_add_nuw(
+; CHECK-NEXT: [[R:%.*]] = lshr exact i32 2, [[X:%.*]]
+; CHECK-NEXT: ret i32 [[R]]
+;
+ %a = add nuw i32 %x, 1
+ %r = lshr exact i32 4, %a
+ ret i32 %r
+}
+
+define i32 @ashr_exact_add_nuw(i32 %x) {
+; CHECK-LABEL: @ashr_exact_add_nuw(
+; CHECK-NEXT: [[R:%.*]] = ashr exact i32 -2, [[X:%.*]]
+; CHECK-NEXT: ret i32 [[R]]
+;
+ %a = add nuw i32 %x, 1
+ %r = ashr exact i32 -4, %a
+ ret i32 %r
+}
+
; negative test - must have 'nuw'
define i32 @shl_add_nsw(i32 %x) {
>From ed1919c0aef799e8031eaa2046a86cd34859d9a6 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Fri, 26 Jan 2024 09:48:42 -0800
Subject: [PATCH 2/2] fixup! Preserve nsw
---
llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp | 6 ++++--
llvm/test/Transforms/InstCombine/shift-add.ll | 10 ++++++++++
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
index 03668f59dfdfb2..3fbe98fae0b61b 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -440,10 +440,12 @@ Instruction *InstCombinerImpl::commonShiftTransforms(BinaryOperator &I) {
match(Op1, m_NUWAdd(m_Value(A), m_Constant(C1)))) {
Value *NewC = Builder.CreateBinOp(I.getOpcode(), C, C1);
BinaryOperator *NewShiftOp = BinaryOperator::Create(I.getOpcode(), NewC, A);
- if (I.getOpcode() == Instruction::Shl)
+ if (I.getOpcode() == Instruction::Shl) {
+ NewShiftOp->setHasNoSignedWrap(I.hasNoSignedWrap());
NewShiftOp->setHasNoUnsignedWrap(I.hasNoUnsignedWrap());
- else
+ } else {
NewShiftOp->setIsExact(I.isExact());
+ }
return NewShiftOp;
}
diff --git a/llvm/test/Transforms/InstCombine/shift-add.ll b/llvm/test/Transforms/InstCombine/shift-add.ll
index 5b8f0c44bde8e5..1b25675059930b 100644
--- a/llvm/test/Transforms/InstCombine/shift-add.ll
+++ b/llvm/test/Transforms/InstCombine/shift-add.ll
@@ -171,6 +171,16 @@ define i32 @shl_nuw_add_nuw(i32 %x) {
ret i32 %r
}
+define i32 @shl_nsw_add_nuw(i32 %x) {
+; CHECK-LABEL: @shl_nsw_add_nuw(
+; CHECK-NEXT: [[R:%.*]] = shl nsw i32 -2, [[X:%.*]]
+; CHECK-NEXT: ret i32 [[R]]
+;
+ %a = add nuw i32 %x, 1
+ %r = shl nsw i32 -1, %a
+ ret i32 %r
+}
+
define i32 @lshr_exact_add_nuw(i32 %x) {
; CHECK-LABEL: @lshr_exact_add_nuw(
; CHECK-NEXT: [[R:%.*]] = lshr exact i32 2, [[X:%.*]]
More information about the llvm-commits
mailing list