-
Notifications
You must be signed in to change notification settings - Fork 216
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SPV_KHR_untyped_pointers - implement OpUntypedPrefetchKHR #2752
base: main
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5329,6 +5329,12 @@ SPIRVValue *LLVMToSPIRVBase::transDirectCallInst(CallInst *CI, | |
BM->addExtension( | ||
ExtensionID::SPV_EXT_relaxed_printf_string_address_space); | ||
} | ||
} else if (DemangledName.find("__spirv_ocl_prefetch") != StringRef::npos) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please also add translation from prefetch llvm intrinsic. |
||
if (BM->isAllowedToUseExtension(ExtensionID::SPV_KHR_untyped_pointers)) { | ||
return BM->addUntypedPrefetchKHRInst( | ||
transScavengedType(CI), | ||
BM->getIds(transValue(getArguments(CI), BB)), BB); | ||
} | ||
} | ||
|
||
return addDecorations( | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4225,5 +4225,82 @@ _SPIRV_OP(ConvertHandleToSamplerINTEL) | |
_SPIRV_OP(ConvertHandleToSampledImageINTEL) | ||
#undef _SPIRV_OP | ||
|
||
class SPIRVUntypedPrefetchKHR : public SPIRVInstruction { | ||
public: | ||
static const Op OC = OpUntypedPrefetchKHR; | ||
static const SPIRVWord FixedWordCount = 3; | ||
|
||
SPIRVUntypedPrefetchKHR(SPIRVType *Ty, std::vector<SPIRVWord> &TheArgs, | ||
SPIRVBasicBlock *BB) | ||
: SPIRVInstruction(FixedWordCount, OC, BB) { | ||
setHasNoId(); | ||
setHasNoType(); | ||
PtrTy = TheArgs[0]; | ||
NumBytes = TheArgs[1]; | ||
if (TheArgs.size() > 2) | ||
RW.push_back(TheArgs[2]); | ||
if (TheArgs.size() > 3) | ||
Locality.push_back(TheArgs[3]); | ||
if (TheArgs.size() > 4) | ||
CacheTy.push_back(TheArgs[4]); | ||
assert(BB && "Invalid BB"); | ||
validate(); | ||
} | ||
|
||
SPIRVUntypedPrefetchKHR() : SPIRVInstruction(OC) { | ||
setHasNoId(); | ||
setHasNoType(); | ||
} | ||
|
||
void validate() const override { | ||
SPIRVInstruction::validate(); | ||
assert(getValueType(PtrTy)->isTypePointer()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lets use
|
||
assert(getValueType(PtrTy)->getPointerStorageClass() == | ||
StorageClassCrossWorkgroup); | ||
assert(getValueType(NumBytes)->isTypeInt()); | ||
assert(RW.empty() || (RW.size() == 1 && getValueType(RW[0])->isTypeInt())); | ||
assert(Locality.empty() || | ||
(Locality.size() == 1 && getValueType(Locality[0])->isTypeInt())); | ||
assert(CacheTy.empty() || | ||
(CacheTy.size() == 1 && getValueType(CacheTy[0])->isTypeInt())); | ||
} | ||
|
||
void setWordCount(SPIRVWord TheWordCount) override { | ||
SPIRVEntry::setWordCount(TheWordCount); | ||
if (TheWordCount > 3) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I might be missing something, but why do we need these checks? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the way to handle optional arguments that is used through the translator's codebase. For the current test case without optional parameters these checks are not used, but need to verify if they are in case we have optional operands. |
||
RW.resize(1); | ||
if (TheWordCount > 4) | ||
Locality.resize(1); | ||
if (TheWordCount > 5) | ||
CacheTy.resize(1); | ||
} | ||
const std::vector<SPIRVWord> getArguments() const { | ||
std::vector<SPIRVWord> Args; | ||
Args.push_back(PtrTy); | ||
Args.push_back(NumBytes); | ||
if (!RW.empty()) | ||
Args.push_back(RW[0]); | ||
if (!Locality.empty()) | ||
Args.push_back(Locality[0]); | ||
if (!CacheTy.empty()) | ||
Args.push_back(CacheTy[0]); | ||
return Args; | ||
} | ||
|
||
SPIRVCapVec getRequiredCapability() const override { | ||
return getVec(CapabilityUntypedPointersKHR); | ||
} | ||
std::optional<ExtensionID> getRequiredExtension() const override { | ||
return ExtensionID::SPV_KHR_untyped_pointers; | ||
} | ||
_SPIRV_DEF_ENCDEC5(PtrTy, NumBytes, RW, Locality, CacheTy) | ||
protected: | ||
SPIRVId PtrTy; | ||
SPIRVId NumBytes; | ||
std::vector<SPIRVId> RW; | ||
std::vector<SPIRVId> Locality; | ||
std::vector<SPIRVId> CacheTy; | ||
}; | ||
|
||
} // namespace SPIRV | ||
#endif // SPIRV_LIBSPIRV_SPIRVINSTRUCTION_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
db5a00f8cebe81146cafabf89019674a3c4bf03d | ||
efb6b4099ddb8fa60f62956dee592c4b94ec6a49 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I started to remember (missed it in our chat). We need to map the instruction to llvm.prefetch intrinsic. So probably the logic should be:
Note, No.2 is discussible, we may want to still emit llvm intrinsic but with some default values set. In the case No.2 RW will always be set, which is good as we won't need to guess a default value, locality can be defaulted to '0'. Not sure though what to use for Cache Type, '1' seems reasonable to me. Would be nice to hear from @alan-baker @bashbaug and @svenvh about that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could add that restriction in the future if that is the only practical use case. I left it vague because I am not familiar with generating the equivalent LLVM intrinsic.
As for defaults I simply tried to provide the same arguments as the LLVM intrinsics, though I can't imagine how instruction cache fetching could be done via OpenCL C. So for Cache Type I'd expect it's always safe to default to data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
About p.1, I'm not sure we should use
llvm.prefetch
intrinsic for now because it does not contain the number of bytes to prefetch field.The similar concern is for forward translation. Although
llvm.prefetch
containsRW
,Locality
andCache Type
fields, it does not have a number of bytes to prefetch, which is a mandatory field inOpUntypedPrefetchKHR
instruction.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed. Probably it can go to another PR, but we can add the following logic: