[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
Tue Sep 17 06:03:54 PDT 2024
https://github.com/VyacheslavLevytskyy updated https://github.com/llvm/llvm-project/pull/108893
>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 1/4] 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;
}
>From 80fc31f1e62a094ab542ac893850631ad78a789b Mon Sep 17 00:00:00 2001
From: "Levytskyy, Vyacheslav" <vyacheslav.levytskyy at intel.com>
Date: Tue, 17 Sep 2024 04:58:06 -0700
Subject: [PATCH 2/4] implement keeping and referencing aggregate result
attributes between passes; implement selection of Arithmetic with Overflow
Intrinsics
---
llvm/include/llvm/IR/IntrinsicsSPIRV.td | 1 +
llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 11 +--
llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h | 17 +++++
.../Target/SPIRV/SPIRVInstructionSelector.cpp | 70 +++++++++++++++++++
llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp | 2 +-
llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp | 22 +++++-
.../Target/SPIRV/SPIRVPrepareFunctions.cpp | 17 +++--
7 files changed, 126 insertions(+), 14 deletions(-)
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index a4c01952927175..e3a875ae0b1b3e 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -15,6 +15,7 @@ let TargetPrefix = "spv" in {
def int_spv_assign_ptr_type : Intrinsic<[], [llvm_any_ty, llvm_metadata_ty, llvm_i32_ty], [ImmArg<ArgIndex<2>>]>;
def int_spv_assign_name : Intrinsic<[], [llvm_any_ty, llvm_vararg_ty]>;
def int_spv_assign_decoration : Intrinsic<[], [llvm_any_ty, llvm_metadata_ty]>;
+ def int_spv_value_md : Intrinsic<[], [llvm_metadata_ty]>;
def int_spv_track_constant : Intrinsic<[llvm_any_ty], [llvm_any_ty, llvm_metadata_ty]>;
def int_spv_init_global : Intrinsic<[], [llvm_any_ty, llvm_any_ty]>;
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 0af656729c946f..e4fcfd21d5e691 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -319,10 +319,13 @@ void SPIRVEmitIntrinsics::buildAssignType(IRBuilder<> &B, Type *Ty,
Value *OfType = PoisonValue::get(Ty);
CallInst *AssignCI = nullptr;
if (Ty->isAggregateType() && allowEmitFakeUse(Arg)) {
+ LLVMContext &Ctx = Arg->getContext();
+ SmallVector<Metadata *, 2> ArgMDs{
+ MDNode::get(Ctx, ValueAsMetadata::getConstant(OfType)),
+ MDString::get(Ctx, Arg->getName())};
+ B.CreateIntrinsic(Intrinsic::spv_value_md, {},
+ {MetadataAsValue::get(Ctx, MDTuple::get(Ctx, ArgMDs))});
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);
@@ -1579,7 +1582,7 @@ void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I,
I->setOperand(OpNo, NewOp);
}
}
- if (I->hasName()) {
+ if (I->hasName() && !I->getType()->isAggregateType()) {
reportFatalOnTokenType(I);
setInsertPointAfterDef(B, I);
std::vector<Value *> Args = {I};
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
index a5cb86f4f1c638..1637fa8b84f132 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
@@ -55,6 +55,8 @@ class SPIRVGlobalRegistry {
// created during substitution of aggregate arguments
// (see `SPIRVPrepareFunctions::removeAggregateTypesFromSignature()`)
DenseMap<Value *, Type *> MutatedAggRet;
+ // map an instruction to its value's attributes (type, name)
+ DenseMap<MachineInstr *, std::pair<Type *, StringRef>> ValueAttrs;
// Look for an equivalent of the newType in the map. Return the equivalent
// if it's found, otherwise insert newType to the map and return the type.
@@ -177,6 +179,21 @@ class SPIRVGlobalRegistry {
return It == MutatedAggRet.end() ? nullptr : It->second;
}
+ // A registry of value's attributes (type, name)
+ // - Add a record.
+ void addValueAttrs(MachineInstr *Key, std::pair<Type *, StringRef> Val) {
+ ValueAttrs[Key] = Val;
+ }
+ // - Find a record.
+ bool findValueAttrs(const MachineInstr *Key, Type *&Ty, StringRef &Name) {
+ auto It = ValueAttrs.find(Key);
+ if (It == ValueAttrs.end())
+ return false;
+ Ty = It->second.first;
+ Name = It->second.second;
+ return true;
+ }
+
// Deduced element types of untyped pointers and composites:
// - Add a record to the map of deduced element types.
void addDeducedElementType(Value *Val, Type *Ty) { DeducedElTys[Val] = Ty; }
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index b526c9f29f1e6a..2e1dd1eeb6d729 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -191,6 +191,9 @@ class SPIRVInstructionSelector : public InstructionSelector {
bool selectFloatDot(Register ResVReg, const SPIRVType *ResType,
MachineInstr &I) const;
+ bool selectOverflowArith(Register ResVReg, const SPIRVType *ResType,
+ MachineInstr &I, unsigned Opcode) const;
+
bool selectIntegerDot(Register ResVReg, const SPIRVType *ResType,
MachineInstr &I) const;
@@ -590,6 +593,23 @@ bool SPIRVInstructionSelector::spvSelect(Register ResVReg,
case TargetOpcode::G_USUBSAT:
return selectExtInst(ResVReg, ResType, I, CL::u_sub_sat);
+ case TargetOpcode::G_SADDO:
+ report_fatal_error(
+ "Selection of a signed addition with overflow is not implemented",
+ false);
+ case TargetOpcode::G_UADDO:
+ return selectOverflowArith(ResVReg, ResType, I, SPIRV::OpIAddCarry);
+ case TargetOpcode::G_SSUBO:
+ report_fatal_error(
+ "Selection of a signed subtraction with overflow is not implemented",
+ false);
+ case TargetOpcode::G_USUBO:
+ return selectOverflowArith(ResVReg, ResType, I, SPIRV::OpISubBorrow);
+ case TargetOpcode::G_UMULO:
+ return selectOverflowArith(ResVReg, ResType, I, SPIRV::OpUMulExtended);
+ case TargetOpcode::G_SMULO:
+ return selectOverflowArith(ResVReg, ResType, I, SPIRV::OpSMulExtended);
+
case TargetOpcode::G_SEXT:
return selectExt(ResVReg, ResType, I, true);
case TargetOpcode::G_ANYEXT:
@@ -1101,6 +1121,53 @@ bool SPIRVInstructionSelector::selectFence(MachineInstr &I) const {
.constrainAllUses(TII, TRI, RBI);
}
+bool SPIRVInstructionSelector::selectOverflowArith(Register ResVReg,
+ const SPIRVType *ResType,
+ MachineInstr &I,
+ unsigned Opcode) const {
+ Type *ResTy = nullptr;
+ StringRef ResName;
+ if (!GR.findValueAttrs(&I, ResTy, ResName))
+ report_fatal_error(
+ "Not enough info to select the arithmetic with overflow instruction");
+ if (!ResTy->isStructTy())
+ report_fatal_error("Expect struct type result for the arithmetic "
+ "with overflow instruction");
+ // "Result Type must be from OpTypeStruct. The struct must have two members,
+ // and the two members must be the same type."
+ Type *ResElemTy = cast<StructType>(ResTy)->getElementType(0);
+ ResTy = StructType::create(SmallVector<Type *, 2>{ResElemTy, ResElemTy});
+ // Build SPIR-V type if needed.
+ MachineIRBuilder MIRBuilder(I);
+ SPIRVType *StructType = GR.getOrCreateSPIRVType(
+ ResTy, MIRBuilder, SPIRV::AccessQualifier::ReadWrite, false);
+ // A new virtual register to store the result struct.
+ Register StructVReg = MRI->createGenericVirtualRegister(LLT::scalar(64));
+ MRI->setRegClass(StructVReg, &SPIRV::IDRegClass);
+ // Build the result name of needed.
+ if (ResName.size() > 0)
+ buildOpName(StructVReg, ResName, MIRBuilder);
+ // Build the arithmetic with overflow instruction.
+ MachineBasicBlock &BB = *I.getParent();
+ auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode))
+ .addDef(StructVReg)
+ .addUse(GR.getSPIRVTypeID(StructType));
+ for (unsigned i = I.getNumDefs(); i < I.getNumOperands(); ++i)
+ MIB.addUse(I.getOperand(i).getReg());
+ bool Status = MIB.constrainAllUses(TII, TRI, RBI);
+ // Build instructions to extract fields of the instruction's result.
+ for (unsigned i = 0; i < I.getNumDefs(); ++i) {
+ auto MIB =
+ BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpCompositeExtract))
+ .addDef(I.getOperand(i).getReg())
+ .addUse(GR.getSPIRVTypeID(ResType))
+ .addUse(StructVReg)
+ .addImm(i);
+ Status &= MIB.constrainAllUses(TII, TRI, RBI);
+ }
+ return Status;
+}
+
bool SPIRVInstructionSelector::selectAtomicCmpXchg(Register ResVReg,
const SPIRVType *ResType,
MachineInstr &I) const {
@@ -2492,6 +2559,9 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
}
case Intrinsic::spv_step:
return selectStep(ResVReg, ResType, I);
+ case Intrinsic::spv_value_md:
+ // ignore the intrinsic
+ break;
default: {
std::string DiagMsg;
raw_string_ostream OS(DiagMsg);
diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
index 189b84369d1c33..de9c495d4cbacc 100644
--- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
@@ -288,7 +288,7 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG).alwaysLegal();
getActionDefinitionsBuilder(
- {G_UADDO, G_SADDO, G_USUBO, G_SSUBO, G_SMULO, G_UMULO})
+ {G_UADDO, G_SADDO, G_USUBO, G_SSUBO, G_UMULO, G_SMULO})
.alwaysLegal();
// FP conversions.
diff --git a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
index 53a266722da21d..49830745ddd996 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
@@ -376,9 +376,9 @@ Register insertAssignInstr(Register Reg, Type *Ty, SPIRVType *SpvType,
.addUse(NewReg)
.addUse(GR->getSPIRVTypeID(SpvType))
.setMIFlags(Flags);
- for (unsigned I = 0, E = Def->getNumExplicitDefs(); I != E; ++I) {
+ for (unsigned I = 0, E = Def->getNumDefs(); I != E; ++I) {
MachineOperand &MO = Def->getOperand(I);
- if (MO.isReg() && MO.isDef() && MO.getReg() == Reg) {
+ if (MO.getReg() == Reg) {
MO.setReg(NewReg);
break;
}
@@ -468,6 +468,24 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
Def->getOpcode() != SPIRV::ASSIGN_TYPE)
insertAssignInstr(Reg, Ty, nullptr, GR, MIB, MF.getRegInfo());
ToErase.push_back(&MI);
+ } else if (MIOp == TargetOpcode::FAKE_USE && MI.getNumOperands() > 0) {
+ MachineInstr *MdMI = MI.getPrevNode();
+ if (MdMI && isSpvIntrinsic(*MdMI, Intrinsic::spv_value_md)) {
+ // It's an internal service info from before IRTranslator passes.
+ MachineInstr *Def = MRI.getVRegDef(MI.getOperand(0).getReg());
+ for (unsigned I = 1, E = MI.getNumOperands(); I != E && Def; ++I)
+ if (MRI.getVRegDef(MI.getOperand(I).getReg()) != Def)
+ Def = nullptr;
+ if (Def) {
+ const MDNode *MD = MdMI->getOperand(1).getMetadata();
+ Type *ValueTy = cast<ValueAsMetadata>(MD->getOperand(0))->getType();
+ StringRef ValueName =
+ cast<MDString>(MD->getOperand(1))->getString();
+ GR->addValueAttrs(Def, std::make_pair(ValueTy, ValueName));
+ }
+ }
+ ToErase.push_back(&MI);
+ ToErase.push_back(MdMI);
} else if (MIOp == TargetOpcode::G_CONSTANT ||
MIOp == TargetOpcode::G_FCONSTANT ||
MIOp == TargetOpcode::G_BUILD_VECTOR) {
diff --git a/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp b/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
index e755af2ff20158..78371485e0c669 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp
@@ -444,10 +444,10 @@ bool SPIRVPrepareFunctions::substituteIntrinsicCalls(Function *F) {
lowerFunnelShifts(II);
Changed = true;
break;
- case Intrinsic::umul_with_overflow:
- lowerUMulWithOverflow(II);
- Changed = true;
- break;
+// case Intrinsic::umul_with_overflow:
+// lowerUMulWithOverflow(II);
+// Changed = true;
+// break;
case Intrinsic::assume:
case Intrinsic::expect: {
const SPIRVSubtarget &STI = TM.getSubtarget<SPIRVSubtarget>(*F);
@@ -478,7 +478,11 @@ bool SPIRVPrepareFunctions::substituteIntrinsicCalls(Function *F) {
// noted in 'spv.cloned_funcs' metadata for later restoration.
Function *
SPIRVPrepareFunctions::removeAggregateTypesFromSignature(Function *F) {
- if (F->isIntrinsic())
+ bool IsRetAggr = F->getReturnType()->isAggregateType();
+ // Allow intrinsics with aggregate return type to reach GlobalISel
+ if (F->isIntrinsic() && IsRetAggr)
+ return F;
+ /*
// Allow intrinsics with aggregate return type to reach GlobalISel
switch (F->getIntrinsicID()) {
// Standard C/C++ Library Intrinsics
@@ -495,10 +499,10 @@ SPIRVPrepareFunctions::removeAggregateTypesFromSignature(Function *F) {
case Intrinsic::usub_with_overflow:
return F;
}
+*/
IRBuilder<> B(F->getContext());
- bool IsRetAggr = F->getReturnType()->isAggregateType();
bool HasAggrArg =
std::any_of(F->arg_begin(), F->arg_end(), [](Argument &Arg) {
return Arg.getType()->isAggregateType();
@@ -579,7 +583,6 @@ bool SPIRVPrepareFunctions::runOnModule(Module &M) {
Changed = true;
}
}
-
return Changed;
}
>From b9d75d06af2d98c5b229e535e40bd111233615ae Mon Sep 17 00:00:00 2001
From: "Levytskyy, Vyacheslav" <vyacheslav.levytskyy at intel.com>
Date: Tue, 17 Sep 2024 05:36:01 -0700
Subject: [PATCH 3/4] fix passing info and access to metadata
---
llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 3 ++-
llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp | 11 ++++++++---
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index e4fcfd21d5e691..9c292e253650f4 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -318,7 +318,8 @@ void SPIRVEmitIntrinsics::buildAssignType(IRBuilder<> &B, Type *Ty,
Value *Arg) {
Value *OfType = PoisonValue::get(Ty);
CallInst *AssignCI = nullptr;
- if (Ty->isAggregateType() && allowEmitFakeUse(Arg)) {
+ if (Arg->getType()->isAggregateType() && Ty->isAggregateType() &&
+ allowEmitFakeUse(Arg)) {
LLVMContext &Ctx = Arg->getContext();
SmallVector<Metadata *, 2> ArgMDs{
MDNode::get(Ctx, ValueAsMetadata::getConstant(OfType)),
diff --git a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
index 49830745ddd996..4ed448b4fe4e20 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
@@ -473,14 +473,19 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
if (MdMI && isSpvIntrinsic(*MdMI, Intrinsic::spv_value_md)) {
// It's an internal service info from before IRTranslator passes.
MachineInstr *Def = MRI.getVRegDef(MI.getOperand(0).getReg());
- for (unsigned I = 1, E = MI.getNumOperands(); I != E && Def; ++I)
- if (MRI.getVRegDef(MI.getOperand(I).getReg()) != Def)
+ for (unsigned I = 1, E = MI.getNumOperands(); I != E && Def; ++I) {
+ MachineInstr *MaybeDef = MRI.getVRegDef(MI.getOperand(I).getReg());
+ if (MaybeDef && MaybeDef->getOpcode() == SPIRV::ASSIGN_TYPE)
+ MaybeDef = MRI.getVRegDef(MaybeDef->getOperand(1).getReg());
+ if (MaybeDef != Def)
Def = nullptr;
+ }
if (Def) {
const MDNode *MD = MdMI->getOperand(1).getMetadata();
- Type *ValueTy = cast<ValueAsMetadata>(MD->getOperand(0))->getType();
StringRef ValueName =
cast<MDString>(MD->getOperand(1))->getString();
+ const MDNode *TypeMD = cast<MDNode>(MD->getOperand(0));
+ Type *ValueTy = getMDOperandAsType(TypeMD, 0);
GR->addValueAttrs(Def, std::make_pair(ValueTy, ValueName));
}
}
>From e1cc84c73a4544b4153012b4fd24781aa62e9161 Mon Sep 17 00:00:00 2001
From: "Levytskyy, Vyacheslav" <vyacheslav.levytskyy at intel.com>
Date: Tue, 17 Sep 2024 06:03:39 -0700
Subject: [PATCH 4/4] fixes
---
llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp | 10 +++-------
llvm/lib/Target/SPIRV/SPIRVUtils.cpp | 7 +++++++
llvm/lib/Target/SPIRV/SPIRVUtils.h | 2 ++
3 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
index 4ed448b4fe4e20..74e309185e8067 100644
--- a/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
@@ -472,14 +472,10 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
MachineInstr *MdMI = MI.getPrevNode();
if (MdMI && isSpvIntrinsic(*MdMI, Intrinsic::spv_value_md)) {
// It's an internal service info from before IRTranslator passes.
- MachineInstr *Def = MRI.getVRegDef(MI.getOperand(0).getReg());
- for (unsigned I = 1, E = MI.getNumOperands(); I != E && Def; ++I) {
- MachineInstr *MaybeDef = MRI.getVRegDef(MI.getOperand(I).getReg());
- if (MaybeDef && MaybeDef->getOpcode() == SPIRV::ASSIGN_TYPE)
- MaybeDef = MRI.getVRegDef(MaybeDef->getOperand(1).getReg());
- if (MaybeDef != Def)
+ MachineInstr *Def = getVRegDef(MRI, MI.getOperand(0).getReg());
+ for (unsigned I = 1, E = MI.getNumOperands(); I != E && Def; ++I)
+ if (getVRegDef(MRI, MI.getOperand(I).getReg()) != Def)
Def = nullptr;
- }
if (Def) {
const MDNode *MD = MdMI->getOperand(1).getMetadata();
StringRef ValueName =
diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
index 927683ad7e32be..9e715dac0677e0 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
@@ -434,4 +434,11 @@ Type *parseBasicTypeName(StringRef &TypeName, LLVMContext &Ctx) {
return nullptr;
}
+MachineInstr *getVRegDef(MachineRegisterInfo &MRI, Register Reg) {
+ MachineInstr *MaybeDef = MRI.getVRegDef(Reg);
+ if (MaybeDef && MaybeDef->getOpcode() == SPIRV::ASSIGN_TYPE)
+ MaybeDef = MRI.getVRegDef(MaybeDef->getOperand(1).getReg());
+ return MaybeDef;
+}
+
} // namespace llvm
diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.h b/llvm/lib/Target/SPIRV/SPIRVUtils.h
index c757af6b8aa72c..eadc4ce48930f8 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.h
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.h
@@ -238,5 +238,7 @@ inline const Type *unifyPtrType(const Type *Ty) {
return toTypedPointer(const_cast<Type *>(Ty));
}
+MachineInstr *getVRegDef(MachineRegisterInfo &MRI, Register Reg);
+
} // namespace llvm
#endif // LLVM_LIB_TARGET_SPIRV_SPIRVUTILS_H
More information about the llvm-commits
mailing list