[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
Thu Jan 25 11:37:45 PST 2024


https://github.com/topperc created https://github.com/llvm/llvm-project/pull/79490

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

>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] [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 54490c46dfaefcd..03668f59dfdfb2c 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 6ea2718abb2bbc5..5b8f0c44bde8e56 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) {



More information about the llvm-commits mailing list