[llvm] [VPlan] Fold unary intrinsics with live-in operands (PR #202944)

Ramkumar Ramachandra via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 10 04:50:44 PDT 2026


https://github.com/artagnon created https://github.com/llvm/llvm-project/pull/202944

The InstSimplifyFolder is not strictly more powerful than the TargetFolder for intrinsics, and we have hence added a fallback.

>From b7f492db98cd4272ee299983f21ec0fbd31e2013 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <artagnon at tenstorrent.com>
Date: Wed, 10 Jun 2026 12:26:52 +0100
Subject: [PATCH] [VPlan] Fold unary intrinsics with live-in operands

The InstSimplifyFolder is not strictly more powerful than the
TargetFolder for intrinsics, and we have hence added a fallback.
---
 .../include/llvm/Analysis/InstSimplifyFolder.h |  4 ++++
 .../Transforms/Vectorize/VPlanTransforms.cpp   | 18 ++++++++++++------
 .../Transforms/LoopVectorize/X86/funclet.ll    |  3 +--
 3 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/llvm/include/llvm/Analysis/InstSimplifyFolder.h b/llvm/include/llvm/Analysis/InstSimplifyFolder.h
index a8dff839de214..ce9a819255899 100644
--- a/llvm/include/llvm/Analysis/InstSimplifyFolder.h
+++ b/llvm/include/llvm/Analysis/InstSimplifyFolder.h
@@ -123,12 +123,16 @@ class LLVM_ABI InstSimplifyFolder final : public IRBuilderFolder {
   Value *
   FoldUnaryIntrinsic(Intrinsic::ID ID, Value *Op, Type *Ty,
                      FastMathFlags FMF = FastMathFlags()) const override {
+    if (Value *V = ConstFolder.FoldUnaryIntrinsic(ID, Op, Ty, FMF))
+      return V;
     return simplifyUnaryIntrinsic(ID, Op, FMF, SQ);
   }
 
   Value *
   FoldBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, Type *Ty,
                       FastMathFlags FMF = FastMathFlags()) const override {
+    if (Value *V = ConstFolder.FoldBinaryIntrinsic(ID, LHS, RHS, Ty, FMF))
+      return V;
     return simplifyBinaryIntrinsic(ID, Ty, LHS, RHS, FMF, SQ);
   }
 
diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
index cc19c1c1faa2d..6ce27d50c4400 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
@@ -1241,14 +1241,14 @@ static void recursivelyDeleteDeadRecipes(VPValue *V) {
 /// an intrinsic ID.
 static std::optional<std::pair<bool, unsigned>>
 getOpcodeOrIntrinsicID(const VPSingleDefRecipe *R) {
+  Intrinsic::ID IID = vputils::getIntrinsicID(R);
+  if (IID != Intrinsic::not_intrinsic)
+    return std::make_pair(true, IID);
   return TypeSwitch<const VPSingleDefRecipe *,
                     std::optional<std::pair<bool, unsigned>>>(R)
       .Case<VPInstruction, VPWidenRecipe, VPWidenCastRecipe, VPWidenGEPRecipe,
             VPReplicateRecipe>(
           [](auto *I) { return std::make_pair(false, I->getOpcode()); })
-      .Case([](const VPWidenIntrinsicRecipe *I) {
-        return std::make_pair(true, I->getVectorIntrinsicID());
-      })
       .Case<VPVectorPointerRecipe, VPPredInstPHIRecipe, VPScalarIVStepsRecipe>(
           [](auto *I) {
             // For recipes that do not directly map to LLVM IR instructions,
@@ -1286,10 +1286,16 @@ static VPIRValue *tryToFoldLiveIns(VPSingleDefRecipe &R,
   auto FoldToIRValue = [&]() -> Value * {
     InstSimplifyFolder Folder(DL);
     if (OpcodeOrIID->first) {
-      if (R.getNumOperands() != 2)
-        return nullptr;
       unsigned ID = OpcodeOrIID->second;
-      return Folder.FoldBinaryIntrinsic(ID, Ops[0], Ops[1], R.getScalarType());
+      if (R.getNumOperands() == 2)
+        return Folder.FoldBinaryIntrinsic(
+            ID, Ops[0], Ops[1], R.getScalarType(),
+            cast<VPRecipeWithIRFlags>(R).getFastMathFlagsOrNone());
+      if (R.getNumOperands() == 1)
+        return Folder.FoldUnaryIntrinsic(
+            ID, Ops[0], R.getScalarType(),
+            cast<VPRecipeWithIRFlags>(R).getFastMathFlagsOrNone());
+      return nullptr;
     }
     unsigned Opcode = OpcodeOrIID->second;
     if (Instruction::isBinaryOp(Opcode))
diff --git a/llvm/test/Transforms/LoopVectorize/X86/funclet.ll b/llvm/test/Transforms/LoopVectorize/X86/funclet.ll
index 58812b5e2309d..fa858d6d6fbbc 100644
--- a/llvm/test/Transforms/LoopVectorize/X86/funclet.ll
+++ b/llvm/test/Transforms/LoopVectorize/X86/funclet.ll
@@ -26,10 +26,9 @@ define void @test1() #0 personality ptr @__CxxFrameHandler3 {
 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1024
 ; CHECK-NEXT:    br i1 [[EXITCOND]], label %[[TRY_CONT:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
 ; CHECK:       [[TRY_CONT]]:
-; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <16 x double> [[TMP2]], i64 15
 ; CHECK-NEXT:    br label %[[EXIT:.*]]
 ; CHECK:       [[EXIT]]:
-; CHECK-NEXT:    store double [[TMP4]], ptr @sink, align 8
+; CHECK-NEXT:    store double 1.000000e+00, ptr @sink, align 8
 ; CHECK-NEXT:    catchret from [[TMP1]] to label %[[TRY_CONT1:.*]]
 ; CHECK:       [[TRY_CONT1]]:
 ; CHECK-NEXT:    ret void



More information about the llvm-commits mailing list