[llvm] [AggressiveInstCombine] Extend MulHigh fold for `or disjoint` (PR #228897)

via llvm-commits llvm-commits at lists.llvm.org
Sun Oct 4 07:52:10 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: 伍浩宇 (suogesi)

<details>
<summary>Changes</summary>

`foldMulHigh` is excecuted after another fold, which folds `add` into `or disjoint`. This can make `foldMulHigh` miss chances to fold.

Replacing `m_Add` into `m_AddLike` extends `foldMulHigh` so it can fold more cases in `-O3` mode.

Notice that there are more cases in `foldMulHigh`. They may need to replace `m_Add` too.

Fixes #<!-- -->221257.

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


2 Files Affected:

- (modified) llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp (+2-2) 
- (added) llvm/test/Transforms/AggressiveInstCombine/umulh_carry_o3.ll (+33) 


``````````diff
diff --git a/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp b/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
index c5548eb107a11..7b90bc76626d0 100644
--- a/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
+++ b/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
@@ -2524,8 +2524,8 @@ static bool foldMulHigh(Instruction &I) {
   Instruction *A, *B, *C;
   auto HiHi = m_OneUse(m_Mul(m_LShr(m_Value(X), m_SpecificInt(BitWidth / 2)),
                              m_LShr(m_Value(Y), m_SpecificInt(BitWidth / 2))));
-  if ((match(&I, m_c_Add(HiHi, m_OneUse(m_Add(m_Instruction(A),
-                                              m_Instruction(B))))) ||
+  if ((match(&I, m_c_Add(HiHi, m_OneUse(m_AddLike(m_Instruction(A),
+                                                  m_Instruction(B))))) ||
        match(&I, m_c_Add(m_Instruction(A),
                          m_OneUse(m_c_Add(HiHi, m_Instruction(B)))))) &&
       A->hasOneUse() && B->hasOneUse())
diff --git a/llvm/test/Transforms/AggressiveInstCombine/umulh_carry_o3.ll b/llvm/test/Transforms/AggressiveInstCombine/umulh_carry_o3.ll
new file mode 100644
index 0000000000000..7c6562959f09c
--- /dev/null
+++ b/llvm/test/Transforms/AggressiveInstCombine/umulh_carry_o3.ll
@@ -0,0 +1,33 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -O3 -S | FileCheck %s
+
+define i32 @mul_carry_add_carry_to_crosssum(i32 %x, i32 %y) {
+; CHECK-LABEL: define range(i32 0, -1) i32 @mul_carry_add_carry_to_crosssum(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[X]] to i64
+; CHECK-NEXT:    [[TMP1:%.*]] = zext i32 [[Y]] to i64
+; CHECK-NEXT:    [[TMP2:%.*]] = mul nuw i64 [[TMP1]], [[TMP0]]
+; CHECK-NEXT:    [[TMP3:%.*]] = lshr i64 [[TMP2]], 32
+; CHECK-NEXT:    [[ADD11:%.*]] = trunc nuw i64 [[TMP3]] to i32
+; CHECK-NEXT:    ret i32 [[ADD11]]
+;
+entry:
+  %shr = lshr i32 %x, 16
+  %and = and i32 %x, 65535
+  %shr1 = lshr i32 %y, 16
+  %and2 = and i32 %y, 65535
+  %mul = mul nuw i32 %and2, %shr
+  %mul3 = mul nuw i32 %shr1, %and
+  %add = add i32 %mul3, %mul
+  %mul4 = mul nuw i32 %and, %and2
+  %shr5 = lshr i32 %mul4, 16
+  %add6 = add i32 %shr5, %add
+  %cmp = icmp ult i32 %add6, %mul
+  %cond = select i1 %cmp, i32 65536, i32 0
+  %mul8 = mul nuw i32 %shr, %shr1
+  %shr10 = lshr i32 %add6, 16
+  %add9 = add nuw i32 %cond, %shr10
+  %add11 = add i32 %add9, %mul8
+  ret i32 %add11
+}

``````````

</details>


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


More information about the llvm-commits mailing list