[llvm] [InstCombine] Handle mul in `maintainNoSignedWrap` (PR #123299)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 17 00:01:00 PST 2025
https://github.com/dtcxzyw created https://github.com/llvm/llvm-project/pull/123299
Alive2: https://alive2.llvm.org/ce/z/Kgamks
Closes https://github.com/llvm/llvm-project/issues/123175.
For `@foo1`, the nsw flag is propagated because we first convert it into `mul nsw nuw (shl nsw nuw X, 1), 3`.
>From b15f4827bfe503b00448c0684c544984a14193c7 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Fri, 17 Jan 2025 15:37:42 +0800
Subject: [PATCH 1/2] [InstCombine] Add pre-commit tests. NFC.
---
llvm/test/Transforms/InstCombine/nsw.ll | 60 +++++++++++++++++++++++++
1 file changed, 60 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/nsw.ll b/llvm/test/Transforms/InstCombine/nsw.ll
index 329a47324f8623..6383bc0236522d 100644
--- a/llvm/test/Transforms/InstCombine/nsw.ll
+++ b/llvm/test/Transforms/InstCombine/nsw.ll
@@ -415,3 +415,63 @@ define i8 @neg_nsw_mul_missing_nsw_on_mul(i8 %a1, i8 %a2, i8 %b) {
%neg = sub nsw i8 0, %shl
ret i8 %neg
}
+
+; This could propagate nsw.
+
+define i16 @mul_nsw_reassoc_prop(i16 %x) {
+; CHECK-LABEL: @mul_nsw_reassoc_prop(
+; CHECK-NEXT: [[B:%.*]] = mul i16 [[X:%.*]], 6
+; CHECK-NEXT: ret i16 [[B]]
+;
+ %a = mul nsw i16 %x, 3
+ %b = mul nsw i16 %a, 2
+ ret i16 %b
+}
+
+; This could propagate nsw.
+
+define i16 @mul_nsw_reassoc_prop_neg(i16 %x) {
+; CHECK-LABEL: @mul_nsw_reassoc_prop_neg(
+; CHECK-NEXT: [[B:%.*]] = mul i16 [[X:%.*]], -2201
+; CHECK-NEXT: ret i16 [[B]]
+;
+ %a = mul nsw i16 %x, -71
+ %b = mul nsw i16 %a, 31
+ ret i16 %b
+}
+
+; Must not propagate nsw.
+
+define i16 @mul_nsw_reassoc_prop_no_nsw1(i16 %x) {
+; CHECK-LABEL: @mul_nsw_reassoc_prop_no_nsw1(
+; CHECK-NEXT: [[B:%.*]] = mul i16 [[X:%.*]], 6
+; CHECK-NEXT: ret i16 [[B]]
+;
+ %a = mul i16 %x, 3
+ %b = mul nsw i16 %a, 2
+ ret i16 %b
+}
+
+; Must not propagate nsw.
+
+define i16 @mul_nsw_reassoc_prop_no_nsw2(i16 %x) {
+; CHECK-LABEL: @mul_nsw_reassoc_prop_no_nsw2(
+; CHECK-NEXT: [[B:%.*]] = mul i16 [[X:%.*]], 6
+; CHECK-NEXT: ret i16 [[B]]
+;
+ %a = mul nsw i16 %x, 3
+ %b = mul i16 %a, 2
+ ret i16 %b
+}
+
+; Must not propagate nsw.
+
+define i16 @mul_nsw_reassoc_prop_overflow(i16 %x) {
+; CHECK-LABEL: @mul_nsw_reassoc_prop_overflow(
+; CHECK-NEXT: [[B:%.*]] = mul i16 [[X:%.*]], -31777
+; CHECK-NEXT: ret i16 [[B]]
+;
+ %a = mul nsw i16 %x, 1023
+ %b = mul nsw i16 %a, 33
+ ret i16 %b
+}
>From e8c3b8b35d3c0e79c09dec4d4910c87b88924717 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Fri, 17 Jan 2025 15:56:27 +0800
Subject: [PATCH 2/2] [InstCombine] Handle mul in `maintainNoSignedWrap`
---
.../InstCombine/InstructionCombining.cpp | 23 +++++++++++--------
llvm/test/Transforms/InstCombine/nsw.ll | 4 ++--
2 files changed, 16 insertions(+), 11 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 2fb60ef11499c7..fb21576722461e 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -281,28 +281,33 @@ bool InstCombinerImpl::shouldChangeType(Type *From, Type *To) const {
// Return true, if No Signed Wrap should be maintained for I.
// The No Signed Wrap flag can be kept if the operation "B (I.getOpcode) C",
// where both B and C should be ConstantInts, results in a constant that does
-// not overflow. This function only handles the Add and Sub opcodes. For
+// not overflow. This function only handles the Add/Sub/Mul opcodes. For
// all other opcodes, the function conservatively returns false.
static bool maintainNoSignedWrap(BinaryOperator &I, Value *B, Value *C) {
auto *OBO = dyn_cast<OverflowingBinaryOperator>(&I);
if (!OBO || !OBO->hasNoSignedWrap())
return false;
- // We reason about Add and Sub Only.
- Instruction::BinaryOps Opcode = I.getOpcode();
- if (Opcode != Instruction::Add && Opcode != Instruction::Sub)
- return false;
-
const APInt *BVal, *CVal;
if (!match(B, m_APInt(BVal)) || !match(C, m_APInt(CVal)))
return false;
+ // We reason about Add/Sub/Mul Only.
bool Overflow = false;
- if (Opcode == Instruction::Add)
+ switch (I.getOpcode()) {
+ case Instruction::Add:
(void)BVal->sadd_ov(*CVal, Overflow);
- else
+ break;
+ case Instruction::Sub:
(void)BVal->ssub_ov(*CVal, Overflow);
-
+ break;
+ case Instruction::Mul:
+ (void)BVal->smul_ov(*CVal, Overflow);
+ break;
+ default:
+ // Conservatively return false for other opcodes.
+ return false;
+ }
return !Overflow;
}
diff --git a/llvm/test/Transforms/InstCombine/nsw.ll b/llvm/test/Transforms/InstCombine/nsw.ll
index 6383bc0236522d..b00f2e58add783 100644
--- a/llvm/test/Transforms/InstCombine/nsw.ll
+++ b/llvm/test/Transforms/InstCombine/nsw.ll
@@ -420,7 +420,7 @@ define i8 @neg_nsw_mul_missing_nsw_on_mul(i8 %a1, i8 %a2, i8 %b) {
define i16 @mul_nsw_reassoc_prop(i16 %x) {
; CHECK-LABEL: @mul_nsw_reassoc_prop(
-; CHECK-NEXT: [[B:%.*]] = mul i16 [[X:%.*]], 6
+; CHECK-NEXT: [[B:%.*]] = mul nsw i16 [[X:%.*]], 6
; CHECK-NEXT: ret i16 [[B]]
;
%a = mul nsw i16 %x, 3
@@ -432,7 +432,7 @@ define i16 @mul_nsw_reassoc_prop(i16 %x) {
define i16 @mul_nsw_reassoc_prop_neg(i16 %x) {
; CHECK-LABEL: @mul_nsw_reassoc_prop_neg(
-; CHECK-NEXT: [[B:%.*]] = mul i16 [[X:%.*]], -2201
+; CHECK-NEXT: [[B:%.*]] = mul nsw i16 [[X:%.*]], -2201
; CHECK-NEXT: ret i16 [[B]]
;
%a = mul nsw i16 %x, -71
More information about the llvm-commits
mailing list