[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