[llvm] [SPIR-V] Allow intrinsics with aggregate return type to reach GlobalISel (PR #108893)
Vyacheslav Levytskyy via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 16 15:17:55 PDT 2024
https://github.com/VyacheslavLevytskyy created https://github.com/llvm/llvm-project/pull/108893
Two main goals of this PR are:
* to support "Arithmetic with Overflow" intrinsics, including the special case when those intrinsics are being generated by the CodeGenPrepare pass during translations with optimization;
* to redirect intrinsics with aggregate return type to be lowered via GlobalISel operations instead of SPIRV-specific unfolding/lowering (see https://github.com/llvm/llvm-project/pull/95012).
This PR continues a series of PRs aimed to identify and fix flaws in code emission, to improve pass rates for the mode with expensive checks set on (see https://github.com/llvm/llvm-project/pull/101732, https://github.com/llvm/llvm-project/pull/104104, https://github.com/llvm/llvm-project/pull/106966), having in mind the ultimate goal of proceeding towards the non-experimental status of SPIR-V Backend.
>From bb1ad757c940f3d5194bbd9fd32bcd54aa5f6374 Mon Sep 17 00:00:00 2001
From: "Levytskyy, Vyacheslav" <vyacheslav.levytskyy at intel.com>
Date: Mon, 16 Sep 2024 15:00:55 -0700
Subject: [PATCH] allow intrinsics with aggregate return type to reach
GlobalISel
---
llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 48 ++++++++++++++++++-
llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp | 3 +-
llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp | 8 +++-
.../Target/SPIRV/SPIRVPrepareFunctions.cpp | 19 ++++++++
4 files changed, 74 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 4175f766ac69ad..0af656729c946f 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -188,6 +188,40 @@ bool isConvergenceIntrinsic(const Instruction *I) {
II->getIntrinsicID() == Intrinsic::experimental_convergence_loop ||
II->getIntrinsicID() == Intrinsic::experimental_convergence_anchor;
}
+
+bool isInternalNonVoidIntrinsic(const Value *I) {
+ if (const auto *II = dyn_cast<IntrinsicInst>(I))
+ switch (II->getIntrinsicID()) {
+ case Intrinsic::spv_cmpxchg:
+ case Intrinsic::spv_const_composite:
+ case Intrinsic::spv_track_constant:
+ case Intrinsic::spv_load:
+ case Intrinsic::spv_extractv:
+ case Intrinsic::spv_insertv:
+ case Intrinsic::spv_extractelt:
+ case Intrinsic::spv_insertelt:
+ case Intrinsic::spv_bitcast:
+ case Intrinsic::spv_ptrcast:
+ case Intrinsic::spv_alloca:
+ case Intrinsic::spv_alloca_array:
+ case Intrinsic::spv_undef:
+ return true;
+ }
+ return false;
+}
+
+bool allowEmitFakeUse(const Value *Arg) {
+ if (isInternalNonVoidIntrinsic(Arg))
+ return false;
+ if (dyn_cast<AtomicCmpXchgInst>(Arg) || dyn_cast<InsertValueInst>(Arg) ||
+ dyn_cast<UndefValue>(Arg))
+ return false;
+ if (const auto *LI = dyn_cast<LoadInst>(Arg))
+ if (LI->getType()->isAggregateType())
+ return false;
+ return true;
+}
+
} // namespace
char SPIRVEmitIntrinsics::ID = 0;
@@ -283,8 +317,16 @@ static inline Type *reconstructType(SPIRVGlobalRegistry *GR, Value *Op) {
void SPIRVEmitIntrinsics::buildAssignType(IRBuilder<> &B, Type *Ty,
Value *Arg) {
Value *OfType = PoisonValue::get(Ty);
- CallInst *AssignCI = buildIntrWithMD(Intrinsic::spv_assign_type,
- {Arg->getType()}, OfType, Arg, {}, B);
+ CallInst *AssignCI = nullptr;
+ if (Ty->isAggregateType() && allowEmitFakeUse(Arg)) {
+ AssignCI = B.CreateIntrinsic(Intrinsic::fake_use, {}, {Arg});
+ AssignCI->setMetadata(
+ "spirv.__BE.assign_type",
+ MDNode::get(Arg->getContext(), ValueAsMetadata::getConstant(OfType)));
+ } else {
+ AssignCI = buildIntrWithMD(Intrinsic::spv_assign_type, {Arg->getType()},
+ OfType, Arg, {}, B);
+ }
GR->addAssignPtrTypeInstr(Arg, AssignCI);
}
@@ -1270,6 +1312,8 @@ Instruction *SPIRVEmitIntrinsics::visitInsertValueInst(InsertValueInst &I) {
}
Instruction *SPIRVEmitIntrinsics::visitExtractValueInst(ExtractValueInst &I) {
+ if (I.getAggregateOperand()->getType()->isAggregateType())
+ return &I;
IRBuilder<> B(I.getParent());
B.SetInsertPoint(&I);
SmallVector<Value *> Args;
diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
index 9fe4d8a16bc32a..189b84369d1c33 100644
--- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
@@ -287,7 +287,8 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
// TODO: add proper legalization rules.
getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG).alwaysLegal();
- getActionDefinitionsBuilder({G_UADDO, G_USUBO, G_SMULO, G_UMULO})
+ getActionDefinitionsBuilder(
+ {G_UADDO, G_SADDO, G_USUBO, G_SSUBO, G_SMULO, G_UMULO})
.alwaysLegal();
// FP conversions.
diff --git a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
index df1b75bc1cb9eb..53a266722da21d 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
@@ -376,7 +376,13 @@ Register insertAssignInstr(Register Reg, Type *Ty, SPIRVType *SpvType,
.addUse(NewReg)
.addUse(GR->getSPIRVTypeID(SpvType))
.setMIFlags(Flags);
- Def->getOperand(0).setReg(NewReg);
+ for (unsigned I = 0, E = Def->getNumExplicitDefs(); I != E; ++I) {
+ MachineOperand &MO = Def->getOperand(I);
+ if (MO.isReg() && MO.isDef() && MO.getReg() == Reg) {
+ MO.setReg(NewReg);
+ break;
+ }
+ }
return NewReg;
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp b/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
index 29b8f8fac98e82..e755af2ff20158 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
@@ -478,6 +478,24 @@ bool SPIRVPrepareFunctions::substituteIntrinsicCalls(Function *F) {
// noted in 'spv.cloned_funcs' metadata for later restoration.
Function *
SPIRVPrepareFunctions::removeAggregateTypesFromSignature(Function *F) {
+ if (F->isIntrinsic())
+ // Allow intrinsics with aggregate return type to reach GlobalISel
+ switch (F->getIntrinsicID()) {
+ // Standard C/C++ Library Intrinsics
+ case Intrinsic::frexp:
+ // Vector Reduction Intrinsics
+ case Intrinsic::vector_interleave2:
+ case Intrinsic::vector_deinterleave2:
+ // Arithmetic with Overflow Intrinsics
+ case Intrinsic::smul_with_overflow:
+ case Intrinsic::umul_with_overflow:
+ case Intrinsic::sadd_with_overflow:
+ case Intrinsic::uadd_with_overflow:
+ case Intrinsic::ssub_with_overflow:
+ case Intrinsic::usub_with_overflow:
+ return F;
+ }
+
IRBuilder<> B(F->getContext());
bool IsRetAggr = F->getReturnType()->isAggregateType();
@@ -561,6 +579,7 @@ bool SPIRVPrepareFunctions::runOnModule(Module &M) {
Changed = true;
}
}
+
return Changed;
}
More information about the llvm-commits
mailing list