Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…nslator into amd-staging
  • Loading branch information
AlexVlx committed Jan 10, 2025
2 parents 2e9c07b + f2d913c commit fe5af73
Show file tree
Hide file tree
Showing 29 changed files with 507 additions and 78 deletions.
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,9 @@ if (NOT SPIRV_TOOLS_FOUND)
endif()
endif()

if (NOT SPIRV_TOOLS_FOUND)
option(LLVM_SPIRV_ENABLE_LIBSPIRV_DIS "Enable --spirv-tools-dis support.")

if (NOT SPIRV_TOOLS_FOUND AND LLVM_SPIRV_ENABLE_LIBSPIRV_DIS)
message(STATUS "SPIRV-Tools not found; project will be built without "
"--spirv-tools-dis support.")
endif()
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ Building clang from sources takes time and resources and it can be avoided:
### Build with SPIRV-Tools

The translator can use [SPIRV-Tools](https://github.com/KhronosGroup/SPIRV-Tools) to generate assembly with widely adopted syntax.
This feature can be enabled by passing `-DLLVM_SPIRV_ENABLE_LIBSPIRV_DIS=ON` option.
If SPIRV-Tools have been installed prior to the build it will be detected and
used automatically. However it is also possible to enable use of SPIRV-Tools
from a custom location using the following instructions:
Expand Down
1 change: 1 addition & 0 deletions include/LLVMSPIRVExtensions.inc
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ EXT(SPV_INTEL_fpga_cluster_attributes)
EXT(SPV_INTEL_loop_fuse)
EXT(SPV_INTEL_long_constant_composite) // TODO: rename to
// SPV_INTEL_long_composites later
EXT(SPV_EXT_optnone)
EXT(SPV_INTEL_optnone)
EXT(SPV_INTEL_fpga_dsp_control)
EXT(SPV_INTEL_memory_access_aliasing)
Expand Down
2 changes: 1 addition & 1 deletion lib/SPIRV/SPIRVInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ inline void
SPIRVMap<Attribute::AttrKind, SPIRVFunctionControlMaskKind>::init() {
add(Attribute::AlwaysInline, FunctionControlInlineMask);
add(Attribute::NoInline, FunctionControlDontInlineMask);
add(Attribute::OptimizeNone, internal::FunctionControlOptNoneINTELMask);
add(Attribute::OptimizeNone, FunctionControlOptNoneEXTMask);
}
typedef SPIRVMap<Attribute::AttrKind, SPIRVFunctionControlMaskKind>
SPIRSPIRVFuncCtlMaskMap;
Expand Down
93 changes: 73 additions & 20 deletions lib/SPIRV/SPIRVReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1099,8 +1099,43 @@ Value *SPIRVToLLVM::transConvertInst(SPIRVValue *BV, Function *F,
case OpBitcast:
if (Src->getType()->isPointerTy() && Dst->isPointerTy() &&
Src->getType()->getPointerAddressSpace() != Dst->getPointerAddressSpace() &&
M->getTargetTriple() == "amdgcn-amd-amdhsa")
M->getTargetTriple() == "amdgcn-amd-amdhsa") {
CO = Instruction::AddrSpaceCast;
} else {
// OpBitcast need to be handled as a special-case when the source is a
// pointer and the destination is not a pointer, and where the source is not
// a pointer and the destination is a pointer. This is supported by the
// SPIR-V bitcast, but not by the LLVM bitcast.
CO = Instruction::BitCast;
if (Src->getType()->isPointerTy() && !Dst->isPointerTy()) {
if (auto *DstVecTy = dyn_cast<FixedVectorType>(Dst)) {
unsigned TotalBitWidth =
DstVecTy->getElementType()->getIntegerBitWidth() *
DstVecTy->getNumElements();
auto *IntTy = Type::getIntNTy(BB->getContext(), TotalBitWidth);
if (BB) {
Src = CastInst::CreatePointerCast(Src, IntTy, "", BB);
} else {
Src = ConstantExpr::getPointerCast(dyn_cast<Constant>(Src), IntTy);
}
} else {
CO = Instruction::PtrToInt;
}
} else if (!Src->getType()->isPointerTy() && Dst->isPointerTy()) {
if (auto *SrcVecTy = dyn_cast<FixedVectorType>(Src->getType())) {
unsigned TotalBitWidth =
SrcVecTy->getElementType()->getIntegerBitWidth() *
SrcVecTy->getNumElements();
auto *IntTy = Type::getIntNTy(BB->getContext(), TotalBitWidth);
if (BB) {
Src = CastInst::Create(Instruction::BitCast, Src, IntTy, "", BB);
} else {
Src = ConstantExpr::getBitCast(dyn_cast<Constant>(Src), IntTy);
}
}
CO = Instruction::IntToPtr;
}
}
break;
default:
CO = static_cast<CastInst::CastOps>(OpCodeMap::rmap(BC->getOpCode()));
Expand Down Expand Up @@ -3838,6 +3873,7 @@ Instruction *SPIRVToLLVM::transSPIRVBuiltinFromInst(SPIRVInstruction *BI,
case internal::OpJointMatrixLoadINTEL:
case OpCooperativeMatrixLoadKHR:
case internal::OpCooperativeMatrixLoadCheckedINTEL:
case internal::OpCooperativeMatrixLoadOffsetINTEL:
case internal::OpTaskSequenceCreateINTEL:
case internal::OpConvertHandleToImageINTEL:
case internal::OpConvertHandleToSampledImageINTEL:
Expand Down Expand Up @@ -5545,36 +5581,53 @@ void SPIRVToLLVM::transAuxDataInst(SPIRVExtInst *BC) {
return;
auto Args = BC->getArguments();
// Args 0 and 1 are common between attributes and metadata.
// 0 is the function, 1 is the name of the attribute/metadata as a string
auto *SpvFcn = BC->getModule()->getValue(Args[0]);
auto *F = static_cast<Function *>(getTranslatedValue(SpvFcn));
assert(F && "Function should already have been translated!");
// 0 is the global object, 1 is the name of the attribute/metadata as a string
auto *Arg0 = BC->getModule()->getValue(Args[0]);
auto *GO = cast<GlobalObject>(getTranslatedValue(Arg0));
auto *F = dyn_cast<Function>(GO);
auto *GV = dyn_cast<GlobalVariable>(GO);
assert((F || GV) && "Value should already have been translated!");
auto AttrOrMDName = BC->getModule()->get<SPIRVString>(Args[1])->getStr();
switch (BC->getExtOp()) {
case NonSemanticAuxData::FunctionAttribute: {
case NonSemanticAuxData::FunctionAttribute:
case NonSemanticAuxData::GlobalVariableAttribute: {
assert(Args.size() < 4 && "Unexpected FunctionAttribute Args");
// If this attr was specially handled and added elsewhere, skip it.
Attribute::AttrKind AsKind = Attribute::getAttrKindFromName(AttrOrMDName);
if (AsKind != Attribute::None && F->hasFnAttribute(AsKind))
return;
if (AsKind == Attribute::None && F->hasFnAttribute(AttrOrMDName))
return;
if (AsKind != Attribute::None)
if ((F && F->hasFnAttribute(AsKind)) || (GV && GV->hasAttribute(AsKind)))
return;
if (AsKind == Attribute::None)
if ((F && F->hasFnAttribute(AttrOrMDName)) ||
(GV && GV->hasAttribute(AttrOrMDName)))
return;
// For attributes, arg 2 is the attribute value as a string, which may not
// exist.
if (Args.size() == 3) {
auto AttrValue = BC->getModule()->get<SPIRVString>(Args[2])->getStr();
F->addFnAttr(AttrOrMDName, AttrValue);
} else {
if (AsKind != Attribute::None)
F->addFnAttr(AsKind);
if (F)
F->addFnAttr(AttrOrMDName, AttrValue);
else
F->addFnAttr(AttrOrMDName);
GV->addAttribute(AttrOrMDName, AttrValue);
} else {
if (AsKind != Attribute::None) {
if (F)
F->addFnAttr(AsKind);
else
GV->addAttribute(AsKind);
} else {
if (F)
F->addFnAttr(AttrOrMDName);
else
GV->addAttribute(AttrOrMDName);
}
}
break;
}
case NonSemanticAuxData::FunctionMetadata: {
case NonSemanticAuxData::FunctionMetadata:
case NonSemanticAuxData::GlobalVariableMetadata: {
// If this metadata was specially handled and added elsewhere, skip it.
if (F->hasMetadata(AttrOrMDName))
if (GO->hasMetadata(AttrOrMDName))
return;
SmallVector<Metadata *> MetadataArgs;
// Process the metadata values.
Expand All @@ -5584,14 +5637,14 @@ void SPIRVToLLVM::transAuxDataInst(SPIRVExtInst *BC) {
if (Arg->getOpCode() == OpString) {
auto *ArgAsStr = static_cast<SPIRVString *>(Arg);
MetadataArgs.push_back(
MDString::get(F->getContext(), ArgAsStr->getStr()));
MDString::get(GO->getContext(), ArgAsStr->getStr()));
} else {
auto *ArgAsVal = static_cast<SPIRVValue *>(Arg);
auto *TranslatedMD = transValue(ArgAsVal, F, nullptr);
auto *TranslatedMD = transValue(ArgAsVal, nullptr, nullptr);
MetadataArgs.push_back(ValueAsMetadata::get(TranslatedMD));
}
}
F->setMetadata(AttrOrMDName, MDNode::get(*Context, MetadataArgs));
GO->setMetadata(AttrOrMDName, MDNode::get(*Context, MetadataArgs));
break;
}
default:
Expand Down
55 changes: 35 additions & 20 deletions lib/SPIRV/SPIRVWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1239,23 +1239,27 @@ void LLVMToSPIRVBase::transFunctionMetadataAsUserSemanticDecoration(
}
}

void LLVMToSPIRVBase::transAuxDataInst(SPIRVFunction *BF, Function *F) {
auto *BM = BF->getModule();
void LLVMToSPIRVBase::transAuxDataInst(SPIRVValue *BV, Value *V) {
auto *GO = cast<GlobalObject>(V);
auto *F = dyn_cast<Function>(GO);
auto *GV = dyn_cast<GlobalVariable>(GO);
assert((F || GV) && "Invalid value type");
auto *BM = BV->getModule();
if (!BM->preserveAuxData())
return;
if (!BM->isAllowedToUseVersion(VersionNumber::SPIRV_1_6))
BM->addExtension(SPIRV::ExtensionID::SPV_KHR_non_semantic_info);
else
BM->setMinSPIRVVersion(VersionNumber::SPIRV_1_6);
const auto &FnAttrs = F->getAttributes().getFnAttrs();
for (const auto &Attr : FnAttrs) {
const auto &Attrs = F ? F->getAttributes().getFnAttrs() : GV->getAttributes();
for (const auto &Attr : Attrs) {
std::vector<SPIRVWord> Ops;
Ops.push_back(BF->getId());
Ops.push_back(BV->getId());
if (Attr.isStringAttribute()) {
// Format for String attributes is:
// NonSemanticAuxDataFunctionAttribute Fcn AttrName AttrValue
// NonSemanticAuxData*Attribute ValueName AttrName AttrValue
// or, if no value:
// NonSemanticAuxDataFunctionAttribute Fcn AttrName
// NonSemanticAuxData*Attribute ValueName AttrName
//
// AttrName and AttrValue are always Strings
StringRef AttrKind = Attr.getKindAsString();
Expand All @@ -1268,19 +1272,20 @@ void LLVMToSPIRVBase::transAuxDataInst(SPIRVFunction *BF, Function *F) {
}
} else {
// Format for other types is:
// NonSemanticAuxDataFunctionAttribute Fcn AttrStr
// NonSemanticAuxData*Attribute ValueName AttrStr
// AttrStr is always a String.
std::string AttrStr = Attr.getAsString();
auto *AttrSpvString = BM->getString(AttrStr);
Ops.push_back(AttrSpvString->getId());
}
BM->addAuxData(NonSemanticAuxData::FunctionAttribute,
transType(Type::getVoidTy(F->getContext())), Ops);
BM->addAuxData(F ? NonSemanticAuxData::FunctionAttribute
: NonSemanticAuxData::GlobalVariableAttribute,
transType(Type::getVoidTy(V->getContext())), Ops);
}
SmallVector<std::pair<unsigned, MDNode *>> AllMD;
SmallVector<StringRef> MDNames;
F->getContext().getMDKindNames(MDNames);
F->getAllMetadata(AllMD);
V->getContext().getMDKindNames(MDNames);
GO->getAllMetadata(AllMD);
for (const auto &MD : AllMD) {
std::string MDName = MDNames[MD.first].str();

Expand All @@ -1293,11 +1298,11 @@ void LLVMToSPIRVBase::transAuxDataInst(SPIRVFunction *BF, Function *F) {
continue;

// Format for metadata is:
// NonSemanticAuxDataFunctionMetadata Fcn MDName MDVals...
// NonSemanticAuxData*Metadata ValueName MDName MDVals...
// MDName is always a String, MDVals have different types as explained
// below. Also note this instruction has a variable number of operands
std::vector<SPIRVWord> Ops;
Ops.push_back(BF->getId());
Ops.push_back(BV->getId());
Ops.push_back(BM->getString(MDName)->getId());
for (unsigned int OpIdx = 0; OpIdx < MD.second->getNumOperands(); OpIdx++) {
const auto &CurOp = MD.second->getOperand(OpIdx);
Expand All @@ -1313,8 +1318,9 @@ void LLVMToSPIRVBase::transAuxDataInst(SPIRVFunction *BF, Function *F) {
assert(false && "Unsupported metadata type");
}
}
BM->addAuxData(NonSemanticAuxData::FunctionMetadata,
transType(Type::getVoidTy(F->getContext())), Ops);
BM->addAuxData(F ? NonSemanticAuxData::FunctionMetadata
: NonSemanticAuxData::GlobalVariableMetadata,
transType(Type::getVoidTy(V->getContext())), Ops);
}
}

Expand Down Expand Up @@ -2045,6 +2051,7 @@ LLVMToSPIRVBase::transValueWithoutDecoration(Value *V, SPIRVBasicBlock *BB,
if (ST && ST->hasName() && isSPIRVConstantName(ST->getName())) {
auto *BV = transConstant(Init);
assert(BV);
transAuxDataInst(BV, V);
return mapValue(V, BV);
}
if (isa_and_nonnull<ConstantExpr>(Init)) {
Expand Down Expand Up @@ -2148,6 +2155,8 @@ LLVMToSPIRVBase::transValueWithoutDecoration(Value *V, SPIRVBasicBlock *BB,
GV->getAttribute(kVCMetadata::VCSingleElementVector), BVar);
}

transAuxDataInst(BVar, V);

mapValue(V, BVar);
spv::BuiltIn Builtin = spv::BuiltInPosition;
if (!GV->hasName() || !getSPIRVBuiltin(GV->getName().str(), Builtin))
Expand Down Expand Up @@ -4356,7 +4365,7 @@ SPIRVValue *LLVMToSPIRVBase::transIntrinsicInst(IntrinsicInst *II,
static_cast<std::vector<SPIRVValue *>::size_type>(VecSize);
auto *ElemOne = BM->addConstant(ElemTy, 1);
auto *ElemZero = BM->addConstant(ElemTy, 0);
auto *ElemMinusOne = BM->addConstant(ElemTy, MinusOneValue);
auto *ElemMinusOne = BM->addConstant(ElemTy, std::move(MinusOneValue));
std::vector<SPIRVValue *> ElemsOne(ElemCount, ElemOne);
std::vector<SPIRVValue *> ElemsZero(ElemCount, ElemZero);
std::vector<SPIRVValue *> ElemsMinusOne(ElemCount, ElemMinusOne);
Expand Down Expand Up @@ -5575,10 +5584,15 @@ SPIRVWord LLVMToSPIRVBase::transFunctionControlMask(Function *F) {
[&](Attribute::AttrKind Attr, SPIRVFunctionControlMaskKind Mask) {
if (F->hasFnAttribute(Attr)) {
if (Attr == Attribute::OptimizeNone) {
if (!BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_optnone))
if (BM->isAllowedToUseExtension(ExtensionID::SPV_EXT_optnone)) {
BM->addExtension(ExtensionID::SPV_EXT_optnone);
BM->addCapability(CapabilityOptNoneEXT);
} else if (BM->isAllowedToUseExtension(
ExtensionID::SPV_INTEL_optnone)) {
BM->addExtension(ExtensionID::SPV_INTEL_optnone);
BM->addCapability(CapabilityOptNoneINTEL);
} else
return;
BM->addExtension(ExtensionID::SPV_INTEL_optnone);
BM->addCapability(internal::CapabilityOptNoneINTEL);
}
FCM |= Mask;
}
Expand Down Expand Up @@ -7071,6 +7085,7 @@ bool runSpirvBackend(Module *M, std::string &Result, std::string &ErrMsg,
SPIRV::ExtensionID::SPV_INTEL_cache_controls,
SPIRV::ExtensionID::SPV_INTEL_global_variable_fpga_decorations,
SPIRV::ExtensionID::SPV_INTEL_global_variable_host_access,
SPIRV::ExtensionID::SPV_EXT_optnone,
SPIRV::ExtensionID::SPV_INTEL_optnone,
SPIRV::ExtensionID::SPV_INTEL_usm_storage_classes,
SPIRV::ExtensionID::SPV_INTEL_subgroups,
Expand Down
2 changes: 1 addition & 1 deletion lib/SPIRV/SPIRVWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ class LLVMToSPIRVBase : protected BuiltinCallHelper {
void transFunctionMetadataAsExecutionMode(SPIRVFunction *BF, Function *F);
void transFunctionMetadataAsUserSemanticDecoration(SPIRVFunction *BF,
Function *F);
void transAuxDataInst(SPIRVFunction *BF, Function *F);
void transAuxDataInst(SPIRVValue *BV, Value *V);

bool transGlobalVariables();

Expand Down
3 changes: 2 additions & 1 deletion lib/SPIRV/libSPIRV/NonSemantic.AuxData.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ namespace NonSemanticAuxData {
enum Instruction {
FunctionMetadata = 0,
FunctionAttribute = 1,
PreserveCount = 2
GlobalVariableMetadata = 2,
GlobalVariableAttribute = 3
};
} // namespace NonSemanticAuxData
2 changes: 2 additions & 0 deletions lib/SPIRV/libSPIRV/SPIRVEnum.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@ template <> inline void SPIRVMap<SPIRVCapabilityKind, SPIRVCapVec>::init() {
{CapabilityCooperativeMatrixKHR});
ADD_VEC_INIT(internal::CapabilityCooperativeMatrixCheckedInstructionsINTEL,
{CapabilityCooperativeMatrixKHR});
ADD_VEC_INIT(internal::CapabilityCooperativeMatrixOffsetInstructionsINTEL,
{CapabilityCooperativeMatrixKHR});
}

template <> inline void SPIRVMap<SPIRVExecutionModelKind, SPIRVCapVec>::init() {
Expand Down
4 changes: 4 additions & 0 deletions lib/SPIRV/libSPIRV/SPIRVExtInst.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,10 @@ inline void SPIRVMap<NonSemanticAuxDataOpKind, std::string>::init() {
"NonSemanticAuxDataFunctionMetadata");
add(NonSemanticAuxData::FunctionAttribute,
"NonSemanticAuxDataFunctionAttribute");
add(NonSemanticAuxData::GlobalVariableMetadata,
"NonSemanticAuxDataGlobalVariableMetadata");
add(NonSemanticAuxData::GlobalVariableAttribute,
"NonSemanticAuxDataGlobalVariableAttribute");
}
SPIRV_DEF_NAMEMAP(NonSemanticAuxDataOpKind, NonSemanticAuxDataOpMap)

Expand Down
20 changes: 20 additions & 0 deletions lib/SPIRV/libSPIRV/SPIRVInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -3740,6 +3740,26 @@ _SPIRV_OP(CooperativeMatrixStoreChecked, false, 8, true, 8)
_SPIRV_OP(CooperativeMatrixConstructChecked, true, 8)
#undef _SPIRV_OP

class SPIRVCooperativeMatrixOffsetInstructionsINTELInstBase
: public SPIRVInstTemplateBase {
protected:
std::optional<ExtensionID> getRequiredExtension() const override {
return ExtensionID::SPV_INTEL_joint_matrix;
}
SPIRVCapVec getRequiredCapability() const override {
return getVec(internal::CapabilityCooperativeMatrixOffsetInstructionsINTEL);
}
};

#define _SPIRV_OP(x, ...) \
typedef SPIRVInstTemplate< \
SPIRVCooperativeMatrixOffsetInstructionsINTELInstBase, \
internal::Op##x##INTEL, __VA_ARGS__> \
SPIRV##x##INTEL;
_SPIRV_OP(CooperativeMatrixLoadOffset, true, 8, true, 5)
_SPIRV_OP(CooperativeMatrixStoreOffset, false, 7, true, 6)
#undef _SPIRV_OP

class SPIRVCooperativeMatrixInvocationInstructionsINTELInstBase
: public SPIRVInstTemplateBase {
protected:
Expand Down
2 changes: 1 addition & 1 deletion lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ inline bool isValidFunctionControlMask(SPIRVWord Mask) {
ValidMask |= FunctionControlDontInlineMask;
ValidMask |= FunctionControlPureMask;
ValidMask |= FunctionControlConstMask;
ValidMask |= internal::FunctionControlOptNoneINTELMask;
ValidMask |= FunctionControlOptNoneEXTMask;

return (Mask & ~ValidMask) == 0;
}
Expand Down
Loading

0 comments on commit fe5af73

Please sign in to comment.