Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions llvm/docs/SPIRVUsage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ list of supported SPIR-V extensions, sorted alphabetically by their extension na
- Adds decorations that can be applied to global (module scope) variables to help code generation for FPGA devices.
* - ``SPV_INTEL_media_block_io``
- Adds additional subgroup block read and write functionality that allow applications to flexibly specify the width and height of the block to read from or write to a 2D image.
* - ``SPV_INTEL_memory_access_aliasing``
- Adds instructions and decorations to specify memory access aliasing, similar to alias.scope and noalias LLVM metadata.
* - ``SPV_INTEL_optnone``
- Adds OptNoneINTEL value for Function Control mask that indicates a request to not optimize the function.
* - ``SPV_INTEL_split_barrier``
Expand Down Expand Up @@ -301,6 +303,10 @@ SPIR-V backend, along with their descriptions and argument details.
- None
- `[Type, Metadata]`
- Assigns decoration to values by associating them with metadatas. Not emitted directly but used to support SPIR-V representation in LLVM IR.
* - `int_spv_assign_aliasing_decoration`
- None
- `[Type, 32-bit Integer, Metadata]`
- Assigns one of two memory aliasing decorations (specified by the second argument) to instructions using original alasing list metadata node. Not emitted directly but used to support SPIR-V representation in LLVM IR.
* - `int_spv_track_constant`
- Type
- `[Type, Metadata]`
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/IR/IntrinsicsSPIRV.td
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,7 @@ let TargetPrefix = "spv" in {
def int_spv_resource_store_typedbuffer
: DefaultAttrsIntrinsic<[], [llvm_any_ty, llvm_i32_ty, llvm_anyvector_ty]>;

// Memory aliasing intrinsics
def int_spv_assign_aliasing_decoration : Intrinsic<[], [llvm_any_ty, llvm_i32_ty, llvm_metadata_ty], [ImmArg<ArgIndex<1>>]>;

}
3 changes: 3 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,9 @@ void SPIRVAsmPrinter::outputModuleSections() {
outputModuleSection(SPIRV::MB_DebugNames);
// 7c. Debug: all OpModuleProcessed instructions.
outputModuleSection(SPIRV::MB_DebugModuleProcessed);
// xxx. SPV_INTEL_memory_access_aliasing instructions go before 8.
// "All annotation instructions"
outputModuleSection(SPIRV::MB_AliasingInsts);
// 8. All annotation instructions (all decorations).
outputAnnotations(*M);
// 9. All type declarations (OpTypeXXX instructions), all constant
Expand Down
14 changes: 14 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,20 @@ bool SPIRVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
return false;
MIB.addUse(Arg.Regs[0]);
}

if (ST->canUseExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing)) {
// Process aliasing metadata.
const CallBase *CI = Info.CB;
if (CI && CI->hasMetadata()) {
if (MDNode *MD = CI->getMetadata(LLVMContext::MD_alias_scope))
buildMemAliasingOpDecorate(ResVReg, MIRBuilder,
SPIRV::Decoration::AliasScopeINTEL, MD);
if (MDNode *MD = CI->getMetadata(LLVMContext::MD_noalias))
buildMemAliasingOpDecorate(ResVReg, MIRBuilder,
SPIRV::Decoration::NoAliasINTEL, MD);
}
}

return MIB.constrainAllUses(MIRBuilder.getTII(), *ST->getRegisterInfo(),
*ST->getRegBankInfo());
}
2 changes: 2 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVCommandLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ static const std::map<std::string, SPIRV::Extension::Extension, std::less<>>
SPIRV::Extension::Extension::SPV_INTEL_subgroups},
{"SPV_INTEL_media_block_io",
SPIRV::Extension::Extension::SPV_INTEL_media_block_io},
{"SPV_INTEL_memory_access_aliasing",
SPIRV::Extension::Extension::SPV_INTEL_memory_access_aliasing},
{"SPV_INTEL_joint_matrix",
SPIRV::Extension::Extension::SPV_INTEL_joint_matrix},
{"SPV_KHR_uniform_group_instructions",
Expand Down
54 changes: 54 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ class SPIRVEmitIntrinsics
unsigned OperandToReplace,
IRBuilder<> &B);
void insertPtrCastOrAssignTypeInstr(Instruction *I, IRBuilder<> &B);
bool shouldTryToAddMemAliasingDecoration(Instruction *Inst);
void insertSpirvDecorations(Instruction *I, IRBuilder<> &B);
void processGlobalValue(GlobalVariable &GV, IRBuilder<> &B);
void processParamTypes(Function *F, IRBuilder<> &B);
Expand Down Expand Up @@ -1249,6 +1250,7 @@ void SPIRVEmitIntrinsics::replaceMemInstrUses(Instruction *Old,
llvm_unreachable("illegal aggregate intrinsic user");
}
}
New->copyMetadata(*Old);
Old->eraseFromParent();
}

Expand Down Expand Up @@ -1832,6 +1834,7 @@ Instruction *SPIRVEmitIntrinsics::visitStoreInst(StoreInst &I) {
Intrinsic::spv_store, {I.getValueOperand()->getType(), PtrOp->getType()},
{I.getValueOperand(), PtrOp, B.getInt16(Flags),
B.getInt8(I.getAlign().value())});
NewI->copyMetadata(I);
I.eraseFromParent();
return NewI;
}
Expand Down Expand Up @@ -2034,13 +2037,64 @@ void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I,
}
}

bool SPIRVEmitIntrinsics::shouldTryToAddMemAliasingDecoration(
Instruction *Inst) {
const SPIRVSubtarget *STI = TM->getSubtargetImpl(*Inst->getFunction());
if (!STI->canUseExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing))
return false;
// Add aliasing decorations to internal load and store intrinsics
// and atomic instructions, skipping atomic store as it won't have ID to
// attach the decoration.
CallInst *CI = dyn_cast<CallInst>(Inst);
if (!CI)
return false;
if (Function *Fun = CI->getCalledFunction()) {
if (Fun->isIntrinsic()) {
switch (Fun->getIntrinsicID()) {
case Intrinsic::spv_load:
case Intrinsic::spv_store:
return true;
default:
return false;
}
}
std::string Name = getOclOrSpirvBuiltinDemangledName(Fun->getName());
const std::string Prefix = "__spirv_Atomic";
const bool IsAtomic = Name.find(Prefix) == 0;

if (!Fun->getReturnType()->isVoidTy() && IsAtomic)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: I have considered moving it to lowerBuiltin, but here (imho) it looks nicer. If/when in the future we allow more instructions to be decorated - then it can be done.

return true;
}
return false;
}

void SPIRVEmitIntrinsics::insertSpirvDecorations(Instruction *I,
IRBuilder<> &B) {
if (MDNode *MD = I->getMetadata("spirv.Decorations")) {
setInsertPointAfterDef(B, I);
B.CreateIntrinsic(Intrinsic::spv_assign_decoration, {I->getType()},
{I, MetadataAsValue::get(I->getContext(), MD)});
}
// Lower alias.scope/noalias metadata
{
auto processMemAliasingDecoration = [&](unsigned Kind) {
if (MDNode *AliasListMD = I->getMetadata(Kind)) {
if (shouldTryToAddMemAliasingDecoration(I)) {
uint32_t Dec = Kind == LLVMContext::MD_alias_scope
? SPIRV::Decoration::AliasScopeINTEL
: SPIRV::Decoration::NoAliasINTEL;
SmallVector<Value *, 3> Args = {
I, ConstantInt::get(B.getInt32Ty(), Dec),
MetadataAsValue::get(I->getContext(), AliasListMD)};
setInsertPointAfterDef(B, I);
B.CreateIntrinsic(Intrinsic::spv_assign_aliasing_decoration,
{I->getType()}, {Args});
}
}
};
processMemAliasingDecoration(LLVMContext::MD_alias_scope);
processMemAliasingDecoration(LLVMContext::MD_noalias);
}
}

void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I,
Expand Down
14 changes: 13 additions & 1 deletion llvm/lib/Target/SPIRV/SPIRVInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,17 @@ bool SPIRVInstrInfo::isDecorationInstr(const MachineInstr &MI) const {
}
}

bool SPIRVInstrInfo::isAliasingInstr(const MachineInstr &MI) const {
switch (MI.getOpcode()) {
case SPIRV::OpAliasDomainDeclINTEL:
case SPIRV::OpAliasScopeDeclINTEL:
case SPIRV::OpAliasScopeListDeclINTEL:
return true;
default:
return false;
}
}

bool SPIRVInstrInfo::isHeaderInstr(const MachineInstr &MI) const {
switch (MI.getOpcode()) {
case SPIRV::OpCapability:
Expand All @@ -114,7 +125,8 @@ bool SPIRVInstrInfo::isHeaderInstr(const MachineInstr &MI) const {
case SPIRV::OpModuleProcessed:
return true;
default:
return isTypeDeclInstr(MI) || isConstantInstr(MI) || isDecorationInstr(MI);
return isTypeDeclInstr(MI) || isConstantInstr(MI) ||
isDecorationInstr(MI) || isAliasingInstr(MI);
}
}

Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/SPIRV/SPIRVInstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class SPIRVInstrInfo : public SPIRVGenInstrInfo {
bool isInlineAsmDefInstr(const MachineInstr &MI) const;
bool isTypeDeclInstr(const MachineInstr &MI) const;
bool isDecorationInstr(const MachineInstr &MI) const;
bool isAliasingInstr(const MachineInstr &MI) const;
bool canUseFastMathFlags(const MachineInstr &MI) const;
bool canUseNSW(const MachineInstr &MI) const;
bool canUseNUW(const MachineInstr &MI) const;
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -948,3 +948,11 @@ def OpConvertHandleToSamplerINTEL: Op<6530, (outs ID:$res), (ins TYPE:$type, ID:
"$res = OpConvertHandleToSamplerINTEL $type $operand">;
def OpConvertHandleToSampledImageINTEL: Op<6531, (outs ID:$res), (ins TYPE:$type, ID:$operand),
"$res = OpConvertHandleToSampledImageINTEL $type $operand">;

// SPV_INTEL_memory_access_aliasing
def OpAliasDomainDeclINTEL: Op<5911, (outs ID:$res), (ins variable_ops),
"$res = OpAliasDomainDeclINTEL">;
def OpAliasScopeDeclINTEL: Op<5912, (outs ID:$res), (ins ID:$AliasDomain, variable_ops),
"$res = OpAliasScopeDeclINTEL $AliasDomain">;
def OpAliasScopeListDeclINTEL: Op<5913, (outs ID:$res), (ins variable_ops),
"$res = OpAliasScopeListDeclINTEL">;
38 changes: 33 additions & 5 deletions llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1020,7 +1020,8 @@ bool SPIRVInstructionSelector::selectBitcast(Register ResVReg,
}

static void addMemoryOperands(MachineMemOperand *MemOp,
MachineInstrBuilder &MIB) {
MachineInstrBuilder &MIB,
MachineIRBuilder &MIRBuilder) {
uint32_t SpvMemOp = static_cast<uint32_t>(SPIRV::MemoryOperand::None);
if (MemOp->isVolatile())
SpvMemOp |= static_cast<uint32_t>(SPIRV::MemoryOperand::Volatile);
Expand All @@ -1029,10 +1030,33 @@ static void addMemoryOperands(MachineMemOperand *MemOp,
if (MemOp->getAlign().value())
SpvMemOp |= static_cast<uint32_t>(SPIRV::MemoryOperand::Aligned);

[[maybe_unused]] MachineInstr *AliasList = nullptr;
[[maybe_unused]] MachineInstr *NoAliasList = nullptr;
const SPIRVSubtarget *ST =
static_cast<const SPIRVSubtarget *>(&MIRBuilder.getMF().getSubtarget());
if (ST->canUseExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing)) {
if (auto *MD = MemOp->getAAInfo().Scope) {
AliasList = getOrAddMemAliasingINTELInst(MIRBuilder, MD);
if (AliasList)
SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::AliasScopeINTELMask);
}
if (auto *MD = MemOp->getAAInfo().NoAlias) {
NoAliasList = getOrAddMemAliasingINTELInst(MIRBuilder, MD);
if (NoAliasList)
SpvMemOp |=
static_cast<uint32_t>(SPIRV::MemoryOperand::NoAliasINTELMask);
}
}

if (SpvMemOp != static_cast<uint32_t>(SPIRV::MemoryOperand::None)) {
MIB.addImm(SpvMemOp);
if (SpvMemOp & static_cast<uint32_t>(SPIRV::MemoryOperand::Aligned))
MIB.addImm(MemOp->getAlign().value());
if (AliasList)
MIB.addUse(AliasList->getOperand(0).getReg());
if (NoAliasList)
MIB.addUse(NoAliasList->getOperand(0).getReg());
}
}

Expand Down Expand Up @@ -1081,7 +1105,8 @@ bool SPIRVInstructionSelector::selectLoad(Register ResVReg,
TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS);
addMemoryOperands(I.getOperand(2 + OpOffset).getImm(), MIB);
} else {
addMemoryOperands(*I.memoperands_begin(), MIB);
MachineIRBuilder MIRBuilder(I);
addMemoryOperands(*I.memoperands_begin(), MIB, MIRBuilder);
}
return MIB.constrainAllUses(TII, TRI, RBI);
}
Expand Down Expand Up @@ -1123,7 +1148,8 @@ bool SPIRVInstructionSelector::selectStore(MachineInstr &I) const {
TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS);
addMemoryOperands(I.getOperand(2 + OpOffset).getImm(), MIB);
} else {
addMemoryOperands(*I.memoperands_begin(), MIB);
MachineIRBuilder MIRBuilder(I);
addMemoryOperands(*I.memoperands_begin(), MIB, MIRBuilder);
}
return MIB.constrainAllUses(TII, TRI, RBI);
}
Expand Down Expand Up @@ -1200,8 +1226,10 @@ bool SPIRVInstructionSelector::selectMemOperation(Register ResVReg,
.addUse(I.getOperand(0).getReg())
.addUse(SrcReg)
.addUse(I.getOperand(2).getReg());
if (I.getNumMemOperands())
addMemoryOperands(*I.memoperands_begin(), MIB);
if (I.getNumMemOperands()) {
MachineIRBuilder MIRBuilder(I);
addMemoryOperands(*I.memoperands_begin(), MIB, MIRBuilder);
}
Result &= MIB.constrainAllUses(TII, TRI, RBI);
if (ResVReg.isValid() && ResVReg != MIB->getOperand(0).getReg())
Result &= BuildCOPY(ResVReg, MIB->getOperand(0).getReg(), I);
Expand Down
9 changes: 9 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,8 @@ void SPIRVModuleAnalysis::processOtherInstrs(const Module &M) {
collectOtherInstr(MI, MAI, SPIRV::MB_DebugNames, IS);
} else if (OpCode == SPIRV::OpEntryPoint) {
collectOtherInstr(MI, MAI, SPIRV::MB_EntryPoints, IS);
} else if (TII->isAliasingInstr(MI)) {
collectOtherInstr(MI, MAI, SPIRV::MB_AliasingInsts, IS);
} else if (TII->isDecorationInstr(MI)) {
collectOtherInstr(MI, MAI, SPIRV::MB_Annotations, IS);
collectFuncNames(MI, &*F);
Expand Down Expand Up @@ -1251,6 +1253,13 @@ void addInstrRequirements(const MachineInstr &MI,
}
break;
}
case SPIRV::OpAliasDomainDeclINTEL:
case SPIRV::OpAliasScopeDeclINTEL:
case SPIRV::OpAliasScopeListDeclINTEL: {
Reqs.addExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing);
Reqs.addCapability(SPIRV::Capability::MemoryAccessAliasingINTEL);
break;
}
case SPIRV::OpBitReverse:
case SPIRV::OpBitFieldInsert:
case SPIRV::OpBitFieldSExtract:
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ enum ModuleSectionType {
MB_DebugNames, // All OpName and OpMemberName intrs.
MB_DebugStrings, // All OpString intrs.
MB_DebugModuleProcessed, // All OpModuleProcessed instructions.
MB_AliasingInsts, // SPV_INTEL_memory_access_aliasing instructions.
MB_Annotations, // OpDecorate, OpMemberDecorate etc.
MB_TypeConstVars, // OpTypeXXX, OpConstantXXX, and global OpVariables.
MB_NonSemanticGlobalDI, // OpExtInst with e.g. DebugSource, DebugTypeBasic.
Expand Down
14 changes: 11 additions & 3 deletions llvm/lib/Target/SPIRV/SPIRVPreLegalizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -813,11 +813,19 @@ static void insertSpirvDecorations(MachineFunction &MF, MachineIRBuilder MIB) {
SmallVector<MachineInstr *, 10> ToErase;
for (MachineBasicBlock &MBB : MF) {
for (MachineInstr &MI : MBB) {
if (!isSpvIntrinsic(MI, Intrinsic::spv_assign_decoration))
if (!isSpvIntrinsic(MI, Intrinsic::spv_assign_decoration) &&
!isSpvIntrinsic(MI, Intrinsic::spv_assign_aliasing_decoration))
continue;
MIB.setInsertPt(*MI.getParent(), MI.getNextNode());
buildOpSpirvDecorations(MI.getOperand(1).getReg(), MIB,
MI.getOperand(2).getMetadata());
if (isSpvIntrinsic(MI, Intrinsic::spv_assign_decoration)) {
buildOpSpirvDecorations(MI.getOperand(1).getReg(), MIB,
MI.getOperand(2).getMetadata());
} else {
buildMemAliasingOpDecorate(MI.getOperand(1).getReg(), MIB,
MI.getOperand(2).getImm(),
MI.getOperand(3).getMetadata());
}

ToErase.push_back(&MI);
}
}
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ defm SPV_INTEL_joint_matrix : ExtensionOperand<114>;
defm SPV_INTEL_float_controls2 : ExtensionOperand<115>;
defm SPV_INTEL_bindless_images : ExtensionOperand<116>;
defm SPV_INTEL_long_composites : ExtensionOperand<117>;
defm SPV_INTEL_memory_access_aliasing : ExtensionOperand<118>;

//===----------------------------------------------------------------------===//
// Multiclass used to define Capabilities enum values and at the same time
Expand Down Expand Up @@ -509,6 +510,7 @@ defm FloatingPointModeINTEL : CapabilityOperand<5583, 0, 0, [SPV_INTEL_float_con
defm FunctionFloatControlINTEL : CapabilityOperand<5821, 0, 0, [SPV_INTEL_float_controls2], []>;
defm LongCompositesINTEL : CapabilityOperand<6089, 0, 0, [SPV_INTEL_long_composites], []>;
defm BindlessImagesINTEL : CapabilityOperand<6528, 0, 0, [SPV_INTEL_bindless_images], []>;
defm MemoryAccessAliasingINTEL : CapabilityOperand<5910, 0, 0, [SPV_INTEL_memory_access_aliasing], []>;

//===----------------------------------------------------------------------===//
// Multiclass used to define SourceLanguage enum values and at the same time
Expand Down Expand Up @@ -1257,6 +1259,8 @@ defm ImplementInRegisterMapINTEL : DecorationOperand<6191, 0, 0, [], [GlobalVari
defm FunctionRoundingModeINTEL : DecorationOperand<5822, 0, 0, [], [FunctionFloatControlINTEL]>;
defm FunctionDenormModeINTEL : DecorationOperand<5823, 0, 0, [], [FunctionFloatControlINTEL]>;
defm FunctionFloatingPointModeINTEL : DecorationOperand<6080, 0, 0, [], [FunctionFloatControlINTEL]>;
defm AliasScopeINTEL : DecorationOperand<5914, 0, 0, [], [MemoryAccessAliasingINTEL]>;
defm NoAliasINTEL : DecorationOperand<5915, 0, 0, [], [MemoryAccessAliasingINTEL]>;

//===----------------------------------------------------------------------===//
// Multiclass used to define BuiltIn enum values and at the same time
Expand Down Expand Up @@ -1529,6 +1533,8 @@ defm Nontemporal : MemoryOperandOperand<0x4, 0, 0, [], []>;
defm MakePointerAvailableKHR : MemoryOperandOperand<0x8, 0, 0, [], [VulkanMemoryModelKHR]>;
defm MakePointerVisibleKHR : MemoryOperandOperand<0x10, 0, 0, [], [VulkanMemoryModelKHR]>;
defm NonPrivatePointerKHR : MemoryOperandOperand<0x20, 0, 0, [], [VulkanMemoryModelKHR]>;
defm AliasScopeINTELMask : MemoryOperandOperand<0x10000, 0, 0, [], [MemoryAccessAliasingINTEL]>;
defm NoAliasINTELMask : MemoryOperandOperand<0x20000, 0, 0, [], [MemoryAccessAliasingINTEL]>;

//===----------------------------------------------------------------------===//
// Multiclass used to define Scope enum values and at the same time
Expand Down
Loading
Loading