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 Dec 8, 2024
2 parents cb97d6e + 50af2c7 commit b322dd4
Show file tree
Hide file tree
Showing 37 changed files with 807 additions and 130 deletions.
2 changes: 2 additions & 0 deletions lib/SPIRV/LLVMToSPIRVDbgTran.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,8 @@ SPIRVWord LLVMToSPIRVDbgTran::mapDebugFlags(DINode::DIFlags DFlags) {
if (BM->getDebugInfoEIS() == SPIRVEIS_NonSemantic_Shader_DebugInfo_200)
if (DFlags & DINode::FlagBitField)
Flags |= SPIRVDebug::FlagBitField;
if (DFlags & DINode::FlagEnumClass)
Flags |= SPIRVDebug::FlagIsEnumClass;
return Flags;
}

Expand Down
3 changes: 2 additions & 1 deletion lib/SPIRV/SPIRVBuiltinHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ BuiltinCallMutator::BuiltinCallMutator(BuiltinCallMutator &&Other)
Value *BuiltinCallMutator::doConversion() {
assert(CI && "Need to have a call instruction to do the conversion");
auto Mangler = makeMangler(CI, Rules);
for (unsigned I = 0; I < Args.size(); I++) {
for (unsigned I = 0, E = std::min(Args.size(), PointerTypes.size()); I < E;
I++) {
Mangler->getTypeMangleInfo(I).PointerTy =
dyn_cast<TypedPointerType>(PointerTypes[I]);
}
Expand Down
171 changes: 145 additions & 26 deletions lib/SPIRV/SPIRVReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,29 @@ Value *SPIRVToLLVM::mapFunction(SPIRVFunction *BF, Function *F) {
return F;
}

std::optional<uint64_t> SPIRVToLLVM::transIdAsConstant(SPIRVId Id) {
auto *V = BM->get<SPIRVValue>(Id);
const auto *ConstValue =
dyn_cast<ConstantInt>(transValue(V, nullptr, nullptr));
if (!ConstValue)
return {};
return ConstValue->getZExtValue();
}

std::optional<uint64_t> SPIRVToLLVM::getAlignment(SPIRVValue *V) {
SPIRVWord AlignmentBytes = 0;
if (V->hasAlignment(&AlignmentBytes)) {
return AlignmentBytes;
}

// If there was no Alignment decoration, look for AlignmentId instead.
SPIRVId AlignId;
if (V->hasDecorateId(DecorationAlignmentId, 0, &AlignId)) {
return transIdAsConstant(AlignId);
}
return {};
}

Type *SPIRVToLLVM::transFPType(SPIRVType *T) {
switch (T->getFloatBitWidth()) {
case 16:
Expand Down Expand Up @@ -2266,8 +2289,10 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
auto *AC = static_cast<SPIRVAccessChainBase *>(BV);
auto *Base = transValue(AC->getBase(), F, BB);
SPIRVType *BaseSPVTy = AC->getBaseType();
if (BaseSPVTy->isTypePointer() &&
BaseSPVTy->getPointerElementType()->isTypeCooperativeMatrixKHR()) {
if ((BaseSPVTy->isTypePointer() &&
BaseSPVTy->getPointerElementType()->isTypeCooperativeMatrixKHR()) ||
(isUntypedAccessChainOpCode(OC) &&
BaseSPVTy->isTypeCooperativeMatrixKHR())) {
return mapValue(BV, transSPIRVBuiltinFromInst(AC, BB));
}
Type *BaseTy =
Expand Down Expand Up @@ -2336,10 +2361,17 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,

case OpPtrDiff: {
auto *BC = static_cast<SPIRVBinary *>(BV);
auto Ops = transValue(BC->getOperands(), F, BB);
auto SPVOps = BC->getOperands();
auto Ops = transValue(SPVOps, F, BB);
IRBuilder<> Builder(BB);
Type *ElemTy =
transType(BC->getOperands()[0]->getType()->getPointerElementType());

Type *ElemTy = nullptr;
if (SPVOps[0]->isUntypedVariable())
ElemTy = transType(
static_cast<SPIRVUntypedVariableKHR *>(SPVOps[0])->getDataType());
else
ElemTy = transType(SPVOps[0]->getType()->getPointerElementType());

Value *V = Builder.CreatePtrDiff(ElemTy, Ops[0], Ops[1]);
return mapValue(BV, V);
}
Expand Down Expand Up @@ -2745,13 +2777,37 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
case OpSignBitSet:
return mapValue(BV,
transRelational(static_cast<SPIRVInstruction *>(BV), BB));
case OpIAddCarry: {
auto *BC = static_cast<SPIRVBinary *>(BV);
return mapValue(BV, transBuiltinFromInst("__spirv_IAddCarry", BC, BB));
}
case OpIAddCarry:
case OpISubBorrow: {
IRBuilder Builder(BB);
auto *BC = static_cast<SPIRVBinary *>(BV);
return mapValue(BV, transBuiltinFromInst("__spirv_ISubBorrow", BC, BB));
Intrinsic::ID ID = OC == OpIAddCarry ? Intrinsic::uadd_with_overflow
: Intrinsic::usub_with_overflow;
auto *Inst =
Builder.CreateBinaryIntrinsic(ID, transValue(BC->getOperand(0), F, BB),
transValue(BC->getOperand(1), F, BB));

// Extract components of the result.
auto *Result = Builder.CreateExtractValue(Inst, 0); // iN result
auto *Carry = Builder.CreateExtractValue(Inst, 1); // i1 overflow

// Convert {iN, i1} into {iN, iN} for SPIR-V compatibility.
Value *CarryInt;
if (Carry->getType()->isVectorTy()) {
CarryInt = Builder.CreateZExt(
Carry, VectorType::get(
cast<VectorType>(Result->getType())->getElementType(),
cast<VectorType>(Carry->getType())->getElementCount()));
} else {
CarryInt = Builder.CreateZExt(Carry, Result->getType());
}
auto *ResultStruct =
Builder.CreateInsertValue(UndefValue::get(StructType::get(
Result->getType(), CarryInt->getType())),
Result, 0);
ResultStruct = Builder.CreateInsertValue(ResultStruct, CarryInt, 1);

return mapValue(BV, ResultStruct);
}
case OpSMulExtended: {
auto *BC = static_cast<SPIRVBinary *>(BV);
Expand Down Expand Up @@ -3225,9 +3281,17 @@ void SPIRVToLLVM::transFunctionAttrs(SPIRVFunction *BF, Function *F) {
SPIRVWord MaxOffset = 0;
if (BA->hasDecorate(DecorationMaxByteOffset, 0, &MaxOffset))
Builder.addDereferenceableAttr(MaxOffset);
SPIRVWord AlignmentBytes = 0;
if (BA->hasAlignment(&AlignmentBytes))
Builder.addAlignmentAttr(AlignmentBytes);
else {
SPIRVId MaxOffsetId;
if (BA->hasDecorateId(DecorationMaxByteOffsetId, 0, &MaxOffsetId)) {
if (auto MaxOffsetVal = transIdAsConstant(MaxOffsetId)) {
Builder.addDereferenceableAttr(*MaxOffsetVal);
}
}
}
if (auto Alignment = getAlignment(BA)) {
Builder.addAlignmentAttr(*Alignment);
}
I->addAttrs(Builder);
}
BF->foreachReturnValueAttr([&](SPIRVFuncParamAttrKind Kind) {
Expand Down Expand Up @@ -3537,18 +3601,24 @@ Instruction *SPIRVToLLVM::transBuiltinFromInst(const std::string &FuncName,
M->getTargetTriple() == "amdgcn-amd-amdhsa")
Ops.insert(Ops.end(),
BM->getValue(*BI->getDecorate(DecorationMaxByteOffsetId).cbegin()));
Op OC = BI->getOpCode();
if (isUntypedAccessChainOpCode(OC)) {
auto *AC = static_cast<SPIRVAccessChainBase *>(BI);
if (AC->getBaseType()->isTypeCooperativeMatrixKHR())
Ops.erase(Ops.begin());
}
Type *RetTy =
BI->hasType() ? transType(BI->getType()) : Type::getVoidTy(*Context);
transOCLBuiltinFromInstPreproc(BI, RetTy, Ops);
std::vector<Type *> ArgTys =
transTypeVector(SPIRVInstruction::getOperandTypes(Ops), true);

// Special handling for "truly" untyped pointers to preserve correct
// builtin mangling of atomic operations.
auto Ptr = findFirstPtrType(ArgTys);
if (Ptr < ArgTys.size() &&
BI->getValueType(Ops[Ptr]->getId())->isTypeUntypedPointerKHR()) {
if (isAtomicOpCodeUntypedPtrSupported(BI->getOpCode())) {
// Special handling for "truly" untyped pointers to preserve correct
// builtin mangling of atomic and matrix operations.
if (isAtomicOpCodeUntypedPtrSupported(OC)) {
auto *AI = static_cast<SPIRVAtomicInstBase *>(BI);
ArgTys[Ptr] = TypedPointerType::get(
transType(AI->getSemanticType()),
Expand All @@ -3557,6 +3627,41 @@ Instruction *SPIRVToLLVM::transBuiltinFromInst(const std::string &FuncName,
BI->getValueType(Ops[Ptr]->getId())->getPointerStorageClass())
: SPIRSPIRVAddrSpaceMap::rmap(
BI->getValueType(Ops[Ptr]->getId())->getPointerStorageClass()));
} else if (OC == spv::OpCooperativeMatrixStoreKHR ||
OC == spv::internal::OpJointMatrixStoreINTEL ||
OC == spv::internal::OpCooperativeMatrixStoreCheckedINTEL ||
OC == spv::internal::OpJointMatrixLoadINTEL ||
OC == spv::OpCompositeConstruct ||
OC == spv::internal::OpCooperativeMatrixApplyFunctionINTEL) {
auto *Val = transValue(Ops[Ptr], BB->getParent(), BB);
Val = Val->stripPointerCasts();
if (auto *GEP = dyn_cast<GetElementPtrInst>(Val))
ArgTys[Ptr] = TypedPointerType::get(
GEP->getSourceElementType(),
SPIRSPIRVAddrSpaceMap::rmap(
BI->getValueType(Ops[Ptr]->getId())->getPointerStorageClass()));
else if (auto *AI = dyn_cast<AllocaInst>(Val))
ArgTys[Ptr] = TypedPointerType::get(
AI->getAllocatedType(),
SPIRSPIRVAddrSpaceMap::rmap(
BI->getValueType(Ops[Ptr]->getId())->getPointerStorageClass()));
else if (isa<Argument>(Val) && !RetTy->isVoidTy()) {
// Pointer could be a function parameter. Assume that the type of the
// pointer is the same as the return type.
Type *Ty = nullptr;
// it return type is array type, assign its element type to Ty
if (RetTy->isArrayTy())
Ty = RetTy->getArrayElementType();
else if (RetTy->isVectorTy())
Ty = cast<VectorType>(RetTy)->getElementType();
else
Ty = RetTy;

ArgTys[Ptr] = TypedPointerType::get(
Ty,
SPIRSPIRVAddrSpaceMap::rmap(
BI->getValueType(Ops[Ptr]->getId())->getPointerStorageClass()));
}
}
}

Expand Down Expand Up @@ -3585,8 +3690,7 @@ Instruction *SPIRVToLLVM::transBuiltinFromInst(const std::string &FuncName,
mangleOpenClBuiltin(FuncName, ArgTys, MangledName);
}
else
MangledName =
getSPIRVFriendlyIRFunctionName(FuncName, BI->getOpCode(), ArgTys, Ops);
MangledName = getSPIRVFriendlyIRFunctionName(FuncName, OC, ArgTys, Ops);

opaquifyTypedPointers(ArgTys);

Expand All @@ -3611,14 +3715,13 @@ Instruction *SPIRVToLLVM::transBuiltinFromInst(const std::string &FuncName,
CallingConv::SPIR_FUNC);
if (isFuncNoUnwind())
Func->addFnAttr(Attribute::NoUnwind);
auto OC = BI->getOpCode();
if (isGroupOpCode(OC) || isGroupNonUniformOpcode(OC) ||
isIntelSubgroupOpCode(OC) || isSplitBarrierINTELOpCode(OC) ||
OC == OpControlBarrier)
Func->addFnAttr(Attribute::Convergent);
}
CallInst *Call;
if (BI->getOpCode() == OpCooperativeMatrixLengthKHR &&
if (OC == OpCooperativeMatrixLengthKHR &&
Ops[0]->getOpCode() == OpTypeCooperativeMatrixKHR) {
// OpCooperativeMatrixLengthKHR needs special handling as its operand is
// a Type instead of a Value.
Expand Down Expand Up @@ -4638,11 +4741,29 @@ bool SPIRVToLLVM::transMetadata() {
if (auto *EM = BF->getExecutionMode(ExecutionModeLocalSize)) {
F->setMetadata(kSPIR2MD::WGSize,
getMDNodeStringIntVec(Context, EM->getLiterals()));
} else if (auto *EM = BF->getExecutionModeId(ExecutionModeLocalSizeId)) {
std::vector<SPIRVWord> Values;
for (const auto Id : EM->getLiterals()) {
if (auto Val = transIdAsConstant(Id)) {
Values.emplace_back(static_cast<SPIRVWord>(*Val));
}
}
F->setMetadata(kSPIR2MD::WGSize, getMDNodeStringIntVec(Context, Values));
}
// Generate metadata for work_group_size_hint
if (auto *EM = BF->getExecutionMode(ExecutionModeLocalSizeHint)) {
F->setMetadata(kSPIR2MD::WGSizeHint,
getMDNodeStringIntVec(Context, EM->getLiterals()));
} else if (auto *EM =
BF->getExecutionModeId(ExecutionModeLocalSizeHintId)) {
std::vector<SPIRVWord> Values;
for (const auto Id : EM->getLiterals()) {
if (auto Val = transIdAsConstant(Id)) {
Values.emplace_back(static_cast<SPIRVWord>(*Val));
}
}
F->setMetadata(kSPIR2MD::WGSizeHint,
getMDNodeStringIntVec(Context, Values));
}
// Generate metadata for vec_type_hint
if (auto *EM = BF->getExecutionMode(ExecutionModeVecTypeHint)) {
Expand Down Expand Up @@ -5120,15 +5241,13 @@ bool SPIRVToLLVM::transFPGAFunctionMetadata(SPIRVFunction *BF, Function *F) {

bool SPIRVToLLVM::transAlign(SPIRVValue *BV, Value *V) {
if (auto *AL = dyn_cast<AllocaInst>(V)) {
SPIRVWord Align = 0;
if (BV->hasAlignment(&Align))
AL->setAlignment(llvm::Align(Align));
if (auto Align = getAlignment(BV))
AL->setAlignment(llvm::Align(*Align));
return true;
}
if (auto *GV = dyn_cast<GlobalVariable>(V)) {
SPIRVWord Align = 0;
if (BV->hasAlignment(&Align))
GV->setAlignment(MaybeAlign(Align));
if (auto Align = getAlignment(BV))
GV->setAlignment(MaybeAlign(*Align));
return true;
}
return true;
Expand Down
7 changes: 7 additions & 0 deletions lib/SPIRV/SPIRVReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,13 @@ class SPIRVToLLVM : private BuiltinCallHelper {

bool isDirectlyTranslatedToOCL(Op OpCode) const;
MDString *transOCLKernelArgTypeName(SPIRVFunctionParameter *);

// Attempt to translate Id as a (specialization) constant.
std::optional<uint64_t> transIdAsConstant(SPIRVId Id);

// Return the value of an Alignment or AlignmentId decoration for V.
std::optional<uint64_t> getAlignment(SPIRVValue *V);

Value *mapFunction(SPIRVFunction *BF, Function *F);
Value *getTranslatedValue(SPIRVValue *BV);
IntrinsicInst *getLifetimeStartIntrinsic(Instruction *I);
Expand Down
2 changes: 1 addition & 1 deletion lib/SPIRV/SPIRVToLLVMDbgTran.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -811,7 +811,7 @@ DINode *SPIRVToLLVMDbgTran::transTypeEnum(const SPIRVExtInst *DebugInst) {
UnderlyingType = transDebugInst<DIType>(static_cast<SPIRVExtInst *>(E));
return getDIBuilder(DebugInst).createEnumerationType(
Scope, Name, File, LineNo, SizeInBits, AlignInBits, Enumerators,
UnderlyingType, 0, "", UnderlyingType);
UnderlyingType, 0, "", Flags & SPIRVDebug::FlagIsEnumClass);
}
}

Expand Down
28 changes: 28 additions & 0 deletions lib/SPIRV/SPIRVWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4262,6 +4262,14 @@ SPIRVValue *LLVMToSPIRVBase::transIntrinsicInst(IntrinsicInst *II,
return BM->addExtInst(STy, BM->getExtInstSetId(SPIRVEIS_OpenCL), ExtOp, Ops,
BB);
}
case Intrinsic::lround: {
SPIRVType *SourceTy = transType(II->getArgOperand(0)->getType());
SPIRVType *DestTy = transType(II->getType());
SPIRVValue *Rounded = BM->addExtInst(
SourceTy, BM->getExtInstSetId(SPIRVEIS_OpenCL), OpenCLLIB::Round,
{transValue(II->getArgOperand(0), BB)}, BB);
return BM->addUnaryInst(OpConvertFToS, DestTy, Rounded, BB);
}
case Intrinsic::frexp: {
if (!checkTypeForSPIRVExtendedInstLowering(II, BM))
break;
Expand Down Expand Up @@ -6876,8 +6884,28 @@ LLVMToSPIRVBase::transBuiltinToInstWithoutDecoration(Op OC, CallInst *CI,
SPRetTy = transType(F->getParamStructRetType(0));
Args.erase(Args.begin());
}
if (RetTy->isPointerTy() &&
BM->isAllowedToUseExtension(ExtensionID::SPV_KHR_untyped_pointers)) {
if (OC == OpAccessChain)
OC = OpUntypedAccessChainKHR;
else if (OC == OpInBoundsAccessChain)
OC = OpUntypedInBoundsAccessChainKHR;
else if (OC == OpPtrAccessChain)
OC = OpUntypedPtrAccessChainKHR;
else if (OC == OpInBoundsPtrAccessChain)
OC = OpUntypedInBoundsPtrAccessChainKHR;
}
auto *SPI = SPIRVInstTemplateBase::create(OC);
std::vector<SPIRVWord> SPArgs;
if (isUntypedAccessChainOpCode(OC)) {
// Untyped access chain instructions have an additional argument BaseTy.
Type *Ty = Scavenger->getScavengedType(Args[0]);
SPIRVType *PtrTy = nullptr;
if (auto *TPT = dyn_cast<TypedPointerType>(Ty)) {
PtrTy = transType(TPT->getElementType());
SPArgs.push_back(PtrTy->getId());
}
}
for (size_t I = 0, E = Args.size(); I != E; ++I) {
if (Args[I]->getType()->isPointerTy()) {
Value *Pointee = Args[I]->stripPointerCasts();
Expand Down
2 changes: 2 additions & 0 deletions lib/SPIRV/libSPIRV/SPIRVEntry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,9 @@ void SPIRVExecutionMode::decode(std::istream &I) {
getDecoder(I) >> Target >> ExecMode;
switch (static_cast<uint32_t>(ExecMode)) {
case ExecutionModeLocalSize:
case ExecutionModeLocalSizeId:
case ExecutionModeLocalSizeHint:
case ExecutionModeLocalSizeHintId:
case ExecutionModeMaxWorkgroupSizeINTEL:
WordLiterals.resize(3);
break;
Expand Down
6 changes: 6 additions & 0 deletions lib/SPIRV/libSPIRV/SPIRVEntry.h
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,12 @@ class SPIRVComponentExecutionModes {
return nullptr;
return Loc->second;
}
SPIRVExecutionModeId *getExecutionModeId(SPIRVExecutionModeKind EMK) const {
auto Loc = ExecModes.find(EMK);
if (Loc == ExecModes.end())
return nullptr;
return static_cast<SPIRVExecutionModeId *>(Loc->second);
}
SPIRVExecutionModeRange
getExecutionModeRange(SPIRVExecutionModeKind EMK) const {
return ExecModes.equal_range(EMK);
Expand Down
Loading

0 comments on commit b322dd4

Please sign in to comment.