[llvm] [InstCombine] foldFPSignBitOps - fabs(X) * fabs(X) -> freeze(X) * freeze(X) (PR #120072)

Simon Pilgrim via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 16 04:22:59 PST 2024


https://github.com/RKSimon created https://github.com/llvm/llvm-project/pull/120072

Ensure we freeze the repeated X operand as we are increasing its number of uses.

Reported on Project Zero: https://web.ist.utl.pt/nuno.lopes/alive2/index.php?hash=de3d864b2cd8f709&test=Transforms%2FInstCombine%2Ffmul.ll

>From 2ab035342fb97b470a0db5acf23b205a092c7efb Mon Sep 17 00:00:00 2001
From: Simon Pilgrim <llvm-dev at redking.me.uk>
Date: Mon, 16 Dec 2024 12:21:19 +0000
Subject: [PATCH] [InstCombine] foldFPSignBitOps - fabs(X) * fabs(X) ->
 freeze(X) * freeze(X)

Ensure we freeze the repeated X operand as we are increasing its number of uses.

Reported on Project Zero: https://web.ist.utl.pt/nuno.lopes/alive2/index.php?hash=de3d864b2cd8f709&test=Transforms%2FInstCombine%2Ffmul.ll
---
 llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp | 9 +++++++--
 llvm/test/Transforms/InstCombine/fdiv.ll                 | 6 ++++--
 llvm/test/Transforms/InstCombine/fmul.ll                 | 6 ++++--
 3 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index f85a3c93651353..519e7968a5e1d5 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -583,8 +583,13 @@ Instruction *InstCombinerImpl::foldFPSignBitOps(BinaryOperator &I) {
 
   // fabs(X) * fabs(X) -> X * X
   // fabs(X) / fabs(X) -> X / X
-  if (Op0 == Op1 && match(Op0, m_FAbs(m_Value(X))))
-    return BinaryOperator::CreateWithCopiedFlags(Opcode, X, X, &I);
+  // X must be frozen because we are increasing its number of uses.
+  if (Op0 == Op1 && match(Op0, m_FAbs(m_Value(X)))) {
+    Value *FX = X;
+    if (!isGuaranteedNotToBeUndef(X))
+      FX = Builder.CreateFreeze(X, X->getName() + ".fr");
+    return BinaryOperator::CreateWithCopiedFlags(Opcode, FX, FX, &I);
+  }
 
   // fabs(X) * fabs(Y) --> fabs(X * Y)
   // fabs(X) / fabs(Y) --> fabs(X / Y)
diff --git a/llvm/test/Transforms/InstCombine/fdiv.ll b/llvm/test/Transforms/InstCombine/fdiv.ll
index 54b0bf8c50ac70..f7f0ad5f468cb1 100644
--- a/llvm/test/Transforms/InstCombine/fdiv.ll
+++ b/llvm/test/Transforms/InstCombine/fdiv.ll
@@ -593,7 +593,8 @@ define float @fdiv_fneg1_extra_use(float %x, float %y) {
 
 define float @fabs_same_op(float %x) {
 ; CHECK-LABEL: @fabs_same_op(
-; CHECK-NEXT:    [[R:%.*]] = fdiv float [[X:%.*]], [[X]]
+; CHECK-NEXT:    [[X:%.*]] = freeze float [[X1:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fdiv float [[X]], [[X]]
 ; CHECK-NEXT:    ret float [[R]]
 ;
   %a = call float @llvm.fabs.f32(float %x)
@@ -603,7 +604,8 @@ define float @fabs_same_op(float %x) {
 
 define float @fabs_same_op_extra_use(float %x) {
 ; CHECK-LABEL: @fabs_same_op_extra_use(
-; CHECK-NEXT:    [[A:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
+; CHECK-NEXT:    [[X:%.*]] = freeze float [[X1:%.*]]
+; CHECK-NEXT:    [[A:%.*]] = call float @llvm.fabs.f32(float [[X]])
 ; CHECK-NEXT:    call void @use_f32(float [[A]])
 ; CHECK-NEXT:    [[R:%.*]] = fdiv reassoc ninf float [[X]], [[X]]
 ; CHECK-NEXT:    ret float [[R]]
diff --git a/llvm/test/Transforms/InstCombine/fmul.ll b/llvm/test/Transforms/InstCombine/fmul.ll
index cd4a8e36c6e239..bd91f32e195d56 100644
--- a/llvm/test/Transforms/InstCombine/fmul.ll
+++ b/llvm/test/Transforms/InstCombine/fmul.ll
@@ -463,7 +463,8 @@ declare float @llvm.fabs.f32(float) nounwind readnone
 
 define float @fabs_squared(float %x) {
 ; CHECK-LABEL: @fabs_squared(
-; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X:%.*]], [[X]]
+; CHECK-NEXT:    [[X:%.*]] = freeze float [[X1:%.*]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[X]], [[X]]
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %x.fabs = call float @llvm.fabs.f32(float %x)
@@ -473,7 +474,8 @@ define float @fabs_squared(float %x) {
 
 define float @fabs_squared_fast(float %x) {
 ; CHECK-LABEL: @fabs_squared_fast(
-; CHECK-NEXT:    [[MUL:%.*]] = fmul fast float [[X:%.*]], [[X]]
+; CHECK-NEXT:    [[X:%.*]] = freeze float [[X1:%.*]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul fast float [[X]], [[X]]
 ; CHECK-NEXT:    ret float [[MUL]]
 ;
   %x.fabs = call float @llvm.fabs.f32(float %x)



More information about the llvm-commits mailing list