[llvm] [InstCombine] Drop one-use check in matchesSquareSum for (a*a) (PR #228020)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 1 03:14:51 PDT 2026
https://github.com/konoongg created https://github.com/llvm/llvm-project/pull/228020
The pattern `(a * a) + (((a * 2) + b) * b)` is equivalent to `(a + b) * (a + b)`. The current implementation requires the `a * a` subexpression to have a single use, which prevents the fold when `a * a` is used elsewhere. This check is unnecessary: we can still perform the fold and keep the original `a * a` instruction for other uses.
For example, with an extra use of `a * a`:
%1 = mul i32 %a, %a
%2 = mul i32 %a, 2
%3 = add i32 %2, %b
%4 = mul i32 %3, %b
%5 = add i32 %4, %1
%6 = mul i32 %1, %1
After this change, InstCombine produces:
%1 = add i32 %a, %b
%2 = mul i32 %1, %1
%3 = mul i32 %a, %a
%4 = mul i32 %3, %3
This reduces the instruction count from 6 to 4, even though `a * a` is now computed both explicitly (for the extra use) and implicitly as part of `(a + b) * (a + b)`.
The same applies to the floating-point (fadd) variant. Both are
updated together.
Tests: llvm/test/Transforms/InstCombine/add.ll llvm/test/Transforms/InstCombine/fadd.ll
>From 9af4a51a78c24c273d8e633add8576ff1ced7cbd Mon Sep 17 00:00:00 2001
From: "v.akhmedov" <v.akhmedov at postgrespro.ru>
Date: Thu, 1 Oct 2026 16:01:32 +0700
Subject: [PATCH] [InstCombine] Drop one-use check in matchesSquareSum for
(a*a)
The pattern `(a * a) + (((a * 2) + b) * b)` is equivalent to
`(a + b) * (a + b)`. The current implementation requires the `a * a`
subexpression to have a single use, which prevents the fold when `a * a`
is used elsewhere. This check is unnecessary: we can still perform the
fold and keep the original `a * a` instruction for other uses.
For example, with an extra use of `a * a`:
%1 = mul i32 %a, %a
%2 = mul i32 %a, 2
%3 = add i32 %2, %b
%4 = mul i32 %3, %b
%5 = add i32 %4, %1
%6 = mul i32 %1, %1
After this change, InstCombine produces:
%1 = add i32 %a, %b
%2 = mul i32 %1, %1
%3 = mul i32 %a, %a
%4 = mul i32 %3, %3
This reduces the instruction count from 6 to 4, even though `a * a`
is now computed both explicitly (for the extra use) and implicitly as
part of `(a + b) * (a + b)`.
---
.../InstCombine/InstCombineAddSub.cpp | 2 +-
llvm/test/Transforms/InstCombine/add.ll | 24 ++++++++-----------
llvm/test/Transforms/InstCombine/fadd.ll | 12 ++++------
3 files changed, 16 insertions(+), 22 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 317d587ddedd662..bff47f010391469 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -1052,7 +1052,7 @@ static bool matchesSquareSum(BinaryOperator &I, Mul2Rhs M2Rhs, Value *&A,
// (a * a) + (((a * 2) + b) * b)
if (match(&I, m_c_BinOp(
- AddOp, m_OneUse(m_BinOp(MulOp, m_Value(A), m_Deferred(A))),
+ AddOp, m_BinOp(MulOp, m_Value(A), m_Deferred(A)),
m_OneUse(m_c_BinOp(
MulOp,
m_c_BinOp(AddOp, m_BinOp(Mul2Op, m_Deferred(A), M2Rhs),
diff --git a/llvm/test/Transforms/InstCombine/add.ll b/llvm/test/Transforms/InstCombine/add.ll
index 22472b0114fd7c7..992cf69f3cba304 100644
--- a/llvm/test/Transforms/InstCombine/add.ll
+++ b/llvm/test/Transforms/InstCombine/add.ll
@@ -4445,13 +4445,11 @@ define i32 @add_reduce_sqr_sum_not_one_use(i32 %a, i32 %b) {
define i32 @add_reduce_sqr_sum_not_one_use2(i32 %a, i32 %b) {
; CHECK-LABEL: @add_reduce_sqr_sum_not_one_use2(
-; CHECK-NEXT: [[A_SQ:%.*]] = mul nsw i32 [[A:%.*]], [[A]]
-; CHECK-NEXT: [[TWO_A:%.*]] = shl i32 [[A]], 1
-; CHECK-NEXT: [[TWO_A_PLUS_B:%.*]] = add i32 [[TWO_A]], [[B:%.*]]
-; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[TWO_A_PLUS_B]], [[B]]
-; CHECK-NEXT: tail call void @fake_func(i32 [[A_SQ]])
-; CHECK-NEXT: [[ADD:%.*]] = add i32 [[MUL]], [[A_SQ]]
-; CHECK-NEXT: ret i32 [[ADD]]
+; CHECK-NEXT: [[A_SQ:%.*]] = mul nsw i32 [[A:%.*]], [[A:%.*]]
+; CHECK-NEXT: tail call void @fake_func(i32 [[A_SQ:%.*]])
+; CHECK-NEXT: [[AB:%.*]] = add i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[AB_SQ:%.*]] = mul i32 [[AB:%.*]], [[AB:%.*]]
+; CHECK-NEXT: ret i32 [[AB_SQ:%.*]]
;
%a_sq = mul nsw i32 %a, %a
%two_a = shl i32 %a, 1
@@ -4484,13 +4482,11 @@ define i32 @add_reduce_sqr_sum_order2_not_one_use(i32 %a, i32 %b) {
define i32 @add_reduce_sqr_sum_order2_not_one_use2(i32 %a, i32 %b) {
; CHECK-LABEL: @add_reduce_sqr_sum_order2_not_one_use2(
-; CHECK-NEXT: [[A_SQ:%.*]] = mul nsw i32 [[A:%.*]], [[A]]
-; CHECK-NEXT: [[TWOA:%.*]] = shl i32 [[A]], 1
-; CHECK-NEXT: [[TWOAB1:%.*]] = add i32 [[TWOA]], [[B:%.*]]
-; CHECK-NEXT: [[TWOAB_B2:%.*]] = mul i32 [[TWOAB1]], [[B]]
-; CHECK-NEXT: tail call void @fake_func(i32 [[A_SQ]])
-; CHECK-NEXT: [[AB2:%.*]] = add i32 [[A_SQ]], [[TWOAB_B2]]
-; CHECK-NEXT: ret i32 [[AB2]]
+; CHECK-NEXT: [[A_SQ:%.*]] = mul nsw i32 [[A:%.*]], [[A:%.*]]
+; CHECK-NEXT: tail call void @fake_func(i32 [[A_SQ:%.*]])
+; CHECK-NEXT: [[AB:%.*]] = add i32 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[AB_SQ:%.*]] = mul i32 [[AB:%.*]], [[AB:%.*]]
+; CHECK-NEXT: ret i32 [[AB_SQ:%.*]]
;
%a_sq = mul nsw i32 %a, %a
%twoa = mul i32 %a, 2
diff --git a/llvm/test/Transforms/InstCombine/fadd.ll b/llvm/test/Transforms/InstCombine/fadd.ll
index 2311685db410d7d..c3f5cc742dd2811 100644
--- a/llvm/test/Transforms/InstCombine/fadd.ll
+++ b/llvm/test/Transforms/InstCombine/fadd.ll
@@ -829,13 +829,11 @@ define float @fadd_reduce_sqr_sum_varA_not_one_use1(float %a, float %b) {
define float @fadd_reduce_sqr_sum_varA_not_one_use2(float %a, float %b) {
; CHECK-LABEL: @fadd_reduce_sqr_sum_varA_not_one_use2(
-; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A:%.*]], [[A]]
-; CHECK-NEXT: [[TWO_A:%.*]] = fmul float [[A]], 2.000000e+00
-; CHECK-NEXT: [[TWO_A_PLUS_B:%.*]] = fadd float [[TWO_A]], [[B:%.*]]
-; CHECK-NEXT: [[MUL:%.*]] = fmul float [[TWO_A_PLUS_B]], [[B]]
-; CHECK-NEXT: [[ADD:%.*]] = fadd reassoc nsz float [[MUL]], [[A_SQ]]
-; CHECK-NEXT: tail call void @fake_func(float [[A_SQ]])
-; CHECK-NEXT: ret float [[ADD]]
+; CHECK-NEXT: [[A_SQ:%.*]] = fmul float [[A:%.*]], [[A:%.*]]
+; CHECK-NEXT: [[AB:%.*]] = fadd reassoc nsz float [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: [[AB_SQ:%.*]] = fmul reassoc nsz float [[AB:%.*]], [[AB:%.*]]
+; CHECK-NEXT: tail call void @fake_func(float [[A_SQ:%.*]])
+; CHECK-NEXT: ret float [[AB_SQ:%.*]]
;
%a_sq = fmul float %a, %a
%two_a = fmul float %a, 2.0
More information about the llvm-commits
mailing list