[llvm] [DAGCombiner][RISCV] Don't propagate the exact flag from udiv/sdiv to urem/srem. (PR #145387)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 23 11:54:14 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-selectiondag

Author: Craig Topper (topperc)

<details>
<summary>Changes</summary>

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.

---
Full diff: https://github.com/llvm/llvm-project/pull/145387.diff


2 Files Affected:

- (modified) llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (+18-10) 
- (added) llvm/test/CodeGen/RISCV/pr145360.ll (+82) 


``````````diff
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
new file mode 100644
index 0000000000000..4251ac60c8bf6
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/pr145360.ll
@@ -0,0 +1,82 @@
+; 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 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 a2, 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:    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
+  %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
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/145387


More information about the llvm-commits mailing list