[llvm] [DAGCombiner][RISCV] Don't propagate the exact flag from udiv/sdiv to urem/srem. (PR #145387)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 23 11:53:44 PDT 2025
https://github.com/topperc created https://github.com/llvm/llvm-project/pull/145387
If we simplify a udiv/sdiv using the exact flag we shouldn't
propagate that simplifaction to any urem/srem that happens to
use the same operands. If the exact flag is wrong, the udiv/sdiv
will produce poison, but that doesn't mean we can make the urem/srem
simplify to 0.
Fixes #145360.
>From 52e10b2611e6082ba390e654010626fdc90eb2c3 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Mon, 23 Jun 2025 11:36:14 -0700
Subject: [PATCH 1/2] Pre-commit tests
---
llvm/test/CodeGen/RISCV/pr145360.ll | 69 +++++++++++++++++++++++++++++
1 file changed, 69 insertions(+)
create mode 100644 llvm/test/CodeGen/RISCV/pr145360.ll
diff --git a/llvm/test/CodeGen/RISCV/pr145360.ll b/llvm/test/CodeGen/RISCV/pr145360.ll
new file mode 100644
index 0000000000000..08c7592d37288
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/pr145360.ll
@@ -0,0 +1,69 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=riscv64 -mattr=+m | FileCheck %s
+
+define i32 @signed(i32 %0, ptr %1) {
+; CHECK-LABEL: signed:
+; CHECK: # %bb.0:
+; CHECK-NEXT: sraiw a0, a0, 8
+; CHECK-NEXT: sw zero, 0(a1)
+; CHECK-NEXT: ret
+ %rem = srem i32 %0, 256
+ store i32 %rem, ptr %1, align 4
+ %div = sdiv exact i32 %0, 256
+ ret i32 %div
+}
+
+define i32 @unsigned(i32 %0, ptr %1) {
+; CHECK-LABEL: unsigned:
+; CHECK: # %bb.0:
+; CHECK-NEXT: srliw a0, a0, 3
+; CHECK-NEXT: lui a2, 699051
+; CHECK-NEXT: addi a2, a2, -1365
+; CHECK-NEXT: mulw a0, a0, a2
+; CHECK-NEXT: sw zero, 0(a1)
+; CHECK-NEXT: ret
+ %rem = urem i32 %0, 24
+ store i32 %rem, ptr %1, align 4
+ %div = udiv exact i32 %0, 24
+ ret i32 %div
+}
+
+define i32 @signed_div_first(i32 %0, ptr %1) {
+; CHECK-LABEL: signed_div_first:
+; CHECK: # %bb.0:
+; CHECK-NEXT: sraiw a2, a0, 31
+; CHECK-NEXT: srliw a2, a2, 24
+; CHECK-NEXT: add a3, a0, a2
+; CHECK-NEXT: sraiw a2, a3, 8
+; CHECK-NEXT: andi a3, a3, -256
+; CHECK-NEXT: subw a0, a0, a3
+; CHECK-NEXT: sw a0, 0(a1)
+; CHECK-NEXT: mv a0, a2
+; CHECK-NEXT: ret
+ %div = sdiv exact i32 %0, 256
+ %rem = srem i32 %0, 256
+ store i32 %rem, ptr %1, align 4
+ ret i32 %div
+}
+
+define i32 @unsigned_div_first(i32 %0, ptr %1) {
+; CHECK-LABEL: unsigned_div_first:
+; CHECK: # %bb.0:
+; CHECK-NEXT: slli a2, a0, 32
+; CHECK-NEXT: lui a3, 699051
+; CHECK-NEXT: addi a3, a3, -1365
+; CHECK-NEXT: slli a3, a3, 32
+; CHECK-NEXT: mulhu a2, a2, a3
+; CHECK-NEXT: srli a2, a2, 36
+; CHECK-NEXT: slli a3, a2, 5
+; CHECK-NEXT: slli a4, a2, 3
+; CHECK-NEXT: subw a4, a4, a3
+; CHECK-NEXT: add a0, a0, a4
+; CHECK-NEXT: sw a0, 0(a1)
+; CHECK-NEXT: mv a0, a2
+; CHECK-NEXT: ret
+ %div = udiv exact i32 %0, 24
+ %rem = urem i32 %0, 24
+ store i32 %rem, ptr %1, align 4
+ ret i32 %div
+}
>From 1e4d03942c4035202b900499246b71e33c131ff0 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Mon, 23 Jun 2025 11:47:06 -0700
Subject: [PATCH 2/2] [DAGCombiner][RISCV] Don't propagate the exact flag from
udiv/sdiv to urem/srem.
If we simplify a udiv/sdiv using the exact flag we shouldn't
propagate that simplifaction to any urem/srem that happens to
use the same operands. If the exact flag is wrong, the udiv/sdiv
will produce poison, but that doesn't mean we can make the urem/srem
simplify to 0.
Fixes #145360.
---
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 28 ++++++++++++-------
llvm/test/CodeGen/RISCV/pr145360.ll | 25 +++++++++++++----
2 files changed, 37 insertions(+), 16 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 56a5643e13442..74a31e7a1fe7a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -4961,11 +4961,15 @@ SDValue DAGCombiner::visitSDIV(SDNode *N) {
// (Dividend - (Quotient * Divisor).
if (SDNode *RemNode = DAG.getNodeIfExists(ISD::SREM, N->getVTList(),
{ N0, N1 })) {
- SDValue Mul = DAG.getNode(ISD::MUL, DL, VT, V, N1);
- SDValue Sub = DAG.getNode(ISD::SUB, DL, VT, N0, Mul);
- AddToWorklist(Mul.getNode());
- AddToWorklist(Sub.getNode());
- CombineTo(RemNode, Sub);
+ // If the udiv has the exact flag we shouldn't propagate it to the
+ // remainder node.
+ if (!N->getFlags().hasExact()) {
+ SDValue Mul = DAG.getNode(ISD::MUL, DL, VT, V, N1);
+ SDValue Sub = DAG.getNode(ISD::SUB, DL, VT, N0, Mul);
+ AddToWorklist(Mul.getNode());
+ AddToWorklist(Sub.getNode());
+ CombineTo(RemNode, Sub);
+ }
}
return V;
}
@@ -5101,11 +5105,15 @@ SDValue DAGCombiner::visitUDIV(SDNode *N) {
// (Dividend - (Quotient * Divisor).
if (SDNode *RemNode = DAG.getNodeIfExists(ISD::UREM, N->getVTList(),
{ N0, N1 })) {
- SDValue Mul = DAG.getNode(ISD::MUL, DL, VT, V, N1);
- SDValue Sub = DAG.getNode(ISD::SUB, DL, VT, N0, Mul);
- AddToWorklist(Mul.getNode());
- AddToWorklist(Sub.getNode());
- CombineTo(RemNode, Sub);
+ // If the udiv has the exact flag we shouldn't propagate it to the
+ // remainder node.
+ if (!N->getFlags().hasExact()) {
+ SDValue Mul = DAG.getNode(ISD::MUL, DL, VT, V, N1);
+ SDValue Sub = DAG.getNode(ISD::SUB, DL, VT, N0, Mul);
+ AddToWorklist(Mul.getNode());
+ AddToWorklist(Sub.getNode());
+ CombineTo(RemNode, Sub);
+ }
}
return V;
}
diff --git a/llvm/test/CodeGen/RISCV/pr145360.ll b/llvm/test/CodeGen/RISCV/pr145360.ll
index 08c7592d37288..4251ac60c8bf6 100644
--- a/llvm/test/CodeGen/RISCV/pr145360.ll
+++ b/llvm/test/CodeGen/RISCV/pr145360.ll
@@ -4,8 +4,13 @@
define i32 @signed(i32 %0, ptr %1) {
; CHECK-LABEL: signed:
; CHECK: # %bb.0:
+; CHECK-NEXT: sraiw a2, a0, 31
+; CHECK-NEXT: srliw a2, a2, 24
+; CHECK-NEXT: add a2, a0, a2
+; CHECK-NEXT: andi a2, a2, -256
+; CHECK-NEXT: subw a2, a0, a2
; CHECK-NEXT: sraiw a0, a0, 8
-; CHECK-NEXT: sw zero, 0(a1)
+; CHECK-NEXT: sw a2, 0(a1)
; CHECK-NEXT: ret
%rem = srem i32 %0, 256
store i32 %rem, ptr %1, align 4
@@ -16,11 +21,19 @@ define i32 @signed(i32 %0, ptr %1) {
define i32 @unsigned(i32 %0, ptr %1) {
; CHECK-LABEL: unsigned:
; CHECK: # %bb.0:
-; CHECK-NEXT: srliw a0, a0, 3
-; CHECK-NEXT: lui a2, 699051
-; CHECK-NEXT: addi a2, a2, -1365
-; CHECK-NEXT: mulw a0, a0, a2
-; CHECK-NEXT: sw zero, 0(a1)
+; CHECK-NEXT: slli a2, a0, 32
+; CHECK-NEXT: lui a3, 699051
+; CHECK-NEXT: addi a3, a3, -1365
+; CHECK-NEXT: slli a4, a3, 32
+; CHECK-NEXT: mulhu a2, a2, a4
+; CHECK-NEXT: srli a2, a2, 36
+; CHECK-NEXT: slli a4, a2, 5
+; CHECK-NEXT: slli a2, a2, 3
+; CHECK-NEXT: subw a2, a2, a4
+; CHECK-NEXT: srliw a4, a0, 3
+; CHECK-NEXT: add a2, a0, a2
+; CHECK-NEXT: mulw a0, a4, a3
+; CHECK-NEXT: sw a2, 0(a1)
; CHECK-NEXT: ret
%rem = urem i32 %0, 24
store i32 %rem, ptr %1, align 4
More information about the llvm-commits
mailing list