[llvm] [InstCombine] Fix a cycle when folding fneg(select) with scalable vector types (PR #112465)

via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 15 20:26:25 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: None (ssijaric-nv)

<details>
<summary>Changes</summary>

The two folding operations are causing a cycle for the following case with
scalable vector types:

define <vscale x 2 x double> @<!-- -->test_fneg_select_abs(<vscale x 2 x i1> %cond, <vscale x 2 x double> %b) {
  %1 = select <vscale x 2 x i1> %cond, <vscale x 2 x double> zeroinitializer, <vscale x 2 x double> %b
  %2 = fneg fast <vscale x 2 x double> %1
  ret <vscale x 2 x double> %2
}

1) fold fneg:  -(Cond ? C : Y) -> Cond ? -C : -Y

2) fold select: (Cond ? -X : -Y) -> -(Cond ? X : Y)

1) results in the following since '<vscale x 2 x double> zeroinitializer' passes
the check for the immediate constant:

%.neg = fneg fast <vscale x 2 x double> zeroinitializer
%b.neg = fneg fast <vscale x 2 x double> %b
%1 = select fast <vscale x 2 x i1> %cond, <vscale x 2 x double> %.neg, <vscale x 2 x double> %b.neg

and so we end up going back and forth between 1) and 2).

Don't perform 1) if we are dealing with scalable vector constants as there is no
immediate representation for a negative scalable zeroinitializer.


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


2 Files Affected:

- (modified) llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp (+2-1) 
- (modified) llvm/test/Transforms/InstCombine/fneg.ll (+12) 


``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 21588aca512758..645fad14c1999c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2878,7 +2878,8 @@ Instruction *InstCombinerImpl::visitFNeg(UnaryOperator &I) {
 
     // -(Cond ? X : C) --> Cond ? -X : -C
     // -(Cond ? C : Y) --> Cond ? -C : -Y
-    if (match(X, m_ImmConstant()) || match(Y, m_ImmConstant())) {
+    if ((match(X, m_ImmConstant()) && !isa<ScalableVectorType>(X->getType())) ||
+        (match(Y, m_ImmConstant()) && !isa<ScalableVectorType>(Y->getType()))) {
       Value *NegX = Builder.CreateFNegFMF(X, &I, X->getName() + ".neg");
       Value *NegY = Builder.CreateFNegFMF(Y, &I, Y->getName() + ".neg");
       SelectInst *NewSel = SelectInst::Create(Cond, NegX, NegY);
diff --git a/llvm/test/Transforms/InstCombine/fneg.ll b/llvm/test/Transforms/InstCombine/fneg.ll
index 3c4088832feaaa..643c8fd8d8a742 100644
--- a/llvm/test/Transforms/InstCombine/fneg.ll
+++ b/llvm/test/Transforms/InstCombine/fneg.ll
@@ -1109,4 +1109,16 @@ define float @test_fneg_select_maxnum(float %x) {
   ret float %neg
 }
 
+; Check that there's no infinite loop.
+define <vscale x 2 x double> @test_fneg_select_svec(<vscale x 2 x i1> %cond, <vscale x 2 x double> %b) {
+; CHECK-LABEL: @test_fneg_select_svec(
+; CHECK-NEXT:    [[TMP1:%.*]] = select <vscale x 2 x i1> [[COND:%.*]], <vscale x 2 x double> zeroinitializer, <vscale x 2 x double> [[B:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = fneg fast <vscale x 2 x double> [[TMP1]]
+; CHECK-NEXT:    ret <vscale x 2 x double> [[TMP2]]
+;
+  %1 = select <vscale x 2 x i1> %cond, <vscale x 2 x double> zeroinitializer, <vscale x 2 x double> %b
+  %2 = fneg fast <vscale x 2 x double> %1
+  ret <vscale x 2 x double> %2
+}
+
 !0 = !{}

``````````

</details>


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


More information about the llvm-commits mailing list