Skip to content

Commit c9af821

Browse files
author
iclsrc
committed
Merge from 'sycl' to 'sycl-web'
2 parents 4b7b5f9 + ebc3ddb commit c9af821

File tree

230 files changed

+3887
-7676
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

230 files changed

+3887
-7676
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ guidelines.
8181

8282
## Late-outline OpenMP\* and OpenMP\* Offload
8383

84-
See [openmp](/tree/openmp) branch.
84+
See [openmp](/openmp) branch.
8585

8686
# License
8787

clang/test/SemaSYCL/lb_sm_90.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// RUN: %clang_cc1 -internal-isystem %S/Inputs %s -triple nvptx64-nvidia-cuda -target-cpu sm_90 -fsycl-is-device -fsyntax-only -Wno-c++23-extensions -verify -S
22

33
// Maximum work groups per multi-processor, mapped to maxclusterrank PTX
4-
// directive, is an SM_90 feature, make sure that no warnings/errors are issued.
4+
// directive, is an SM_90 feature. Attributes need to be used in sequence:
5+
// max_work_group_size, min_work_groups_per_cu, max_work_groups_per_mp, warn on
6+
// missing attributes in sequences.
57

68
#include "sycl.hpp"
79

llvm/lib/SYCLLowerIR/CompileTimeProperties.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,8 @@ SYCL_COMPILE_TIME_PROPERTY("sycl-bi-directional-ports-true", 5885,
6060
// SPIR-V Spec: https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/INTEL/SPV_INTEL_cache_controls.asciidoc
6161
SYCL_COMPILE_TIME_PROPERTY("sycl-prefetch-hint", 6442, DecorValueTy::uint32)
6262
SYCL_COMPILE_TIME_PROPERTY("sycl-prefetch-hint-nt", 6442, DecorValueTy::uint32)
63+
64+
// The corresponding SPIR-V OpCodes for cache control properties
65+
SYCL_COMPILE_TIME_PROPERTY("sycl-cache-read-hint", 6442, DecorValueTy::uint32)
66+
SYCL_COMPILE_TIME_PROPERTY("sycl-cache-read-assertion", 6442, DecorValueTy::uint32)
67+
SYCL_COMPILE_TIME_PROPERTY("sycl-cache-write-hint", 6443, DecorValueTy::uint32)

llvm/lib/SYCLLowerIR/CompileTimePropertiesPass.cpp

Lines changed: 176 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ constexpr uint32_t SPIRV_HOST_ACCESS_DEFAULT_VALUE = 2; // Read/Write
4242
constexpr uint32_t SPIRV_INITIATION_INTERVAL_DECOR = 5917;
4343
constexpr uint32_t SPIRV_PIPELINE_ENABLE_DECOR = 5919;
4444

45+
constexpr uint32_t SPIRV_CACHE_CONTROL_READ_DECOR = 6442;
46+
constexpr uint32_t SPIRV_CACHE_CONTROL_WRITE_DECOR = 6443;
47+
4548
enum class DecorValueTy {
4649
uint32,
4750
boolean,
@@ -97,6 +100,72 @@ MDNode *buildSpirvDecorMetadata(LLVMContext &Ctx, uint32_t OpCode,
97100
return MDNode::get(Ctx, MD);
98101
}
99102

103+
/// Builds a metadata node for a SPIR-V decoration for cache controls
104+
/// where decoration code and value are both uint32_t integers.
105+
/// The value encodes a cache level and a cache control type.
106+
///
107+
/// @param Ctx [in] the LLVM Context.
108+
/// @param Name [in] the SPIR-V property string name.
109+
/// @param OpCode [in] the SPIR-V opcode.
110+
/// @param CacheMode [in] whether read or write.
111+
/// @param CacheLevel [in] the cache level.
112+
///
113+
/// @returns a pointer to the metadata node created for the required decoration
114+
/// and its values.
115+
MDNode *buildSpirvDecorCacheProp(LLVMContext &Ctx, StringRef Name,
116+
uint32_t OpCode, uint32_t CacheMode,
117+
uint32_t CacheLevel) {
118+
// SPIR-V encodings of read control
119+
enum cache_control_read_type {
120+
read_uncached = 0,
121+
read_cached = 1,
122+
read_streaming = 2,
123+
read_invalidate = 3,
124+
read_const_cached = 4
125+
};
126+
// SPIR-V encodings of write control
127+
enum cache_control_write_type {
128+
write_uncached = 0,
129+
write_through = 1,
130+
write_back = 2,
131+
write_streaming = 3
132+
};
133+
// SYCL encodings of read/write control. Definition of cache_mode should match
134+
// definition in SYCL header file cache_control_properties.hpp.
135+
enum class cache_mode {
136+
uncached,
137+
cached,
138+
streaming,
139+
invalidate,
140+
constant,
141+
write_through,
142+
write_back
143+
};
144+
static uint32_t SPIRVReadControl[] = {read_uncached, read_cached,
145+
read_streaming, read_invalidate,
146+
read_const_cached};
147+
static uint32_t SPIRVWriteControl[] = {
148+
write_uncached, write_uncached, write_streaming, write_uncached,
149+
write_uncached, write_through, write_back};
150+
151+
// Map SYCL encoding to SPIR-V
152+
uint32_t CacheProp;
153+
if (Name.starts_with("sycl-cache-read"))
154+
CacheProp = SPIRVReadControl[CacheMode];
155+
else
156+
CacheProp = SPIRVWriteControl[CacheMode];
157+
158+
auto *Ty = Type::getInt32Ty(Ctx);
159+
SmallVector<Metadata *, 3> MD;
160+
MD.push_back(ConstantAsMetadata::get(
161+
Constant::getIntegerValue(Ty, APInt(32, OpCode))));
162+
MD.push_back(ConstantAsMetadata::get(
163+
Constant::getIntegerValue(Ty, APInt(32, CacheLevel))));
164+
MD.push_back(ConstantAsMetadata::get(
165+
Constant::getIntegerValue(Ty, APInt(32, CacheProp))));
166+
return MDNode::get(Ctx, MD);
167+
}
168+
100169
/// Builds a metadata node for a SPIR-V decoration (decoration code
101170
/// is \c uint32_t integer and value is a string).
102171
///
@@ -625,9 +694,12 @@ bool CompileTimePropertiesPass::transformSYCLPropertiesAnnotation(
625694
// check alignment annotation and apply it to load/store
626695
parseAlignmentAndApply(M, IntrInst);
627696

628-
// Read the annotation values and create the new annotation string.
697+
// Read the annotation values and create new annotation strings.
629698
std::string NewAnnotString = "";
630699
auto Properties = parseSYCLPropertiesString(M, IntrInst);
700+
SmallVector<Metadata *, 8> MDOpsCacheProp;
701+
bool CacheProp = false;
702+
bool FPGAProp = false;
631703
for (const auto &[PropName, PropVal] : Properties) {
632704
// sycl-alignment is converted to align on
633705
// previous parseAlignmentAndApply(), dropping here
@@ -639,59 +711,118 @@ bool CompileTimePropertiesPass::transformSYCLPropertiesAnnotation(
639711
continue;
640712
uint32_t DecorCode = DecorIt->second.Code;
641713

642-
// Expected format is '{X}' or '{X:Y}' where X is decoration ID and
643-
// Y is the value if present. It encloses Y in " to ensure that
644-
// string values are handled correctly. Note that " around values are
645-
// always valid, even if the decoration parameters are not strings.
646-
NewAnnotString += "{" + std::to_string(DecorCode);
647-
if (PropVal)
648-
NewAnnotString += ":\"" + PropVal->str();
649-
650-
if (PropName == "sycl-prefetch-hint")
651-
NewAnnotString += ",1"; // CachedINTEL
652-
if (PropName == "sycl-prefetch-hint-nt")
653-
NewAnnotString += ",3"; // InvalidateAfterReadINTEL
654-
655-
if (PropVal)
656-
NewAnnotString += "\"";
657-
NewAnnotString += "}";
714+
// Handle cache control properties
715+
if ((*PropName).starts_with("sycl-cache-")) {
716+
CacheProp = true;
717+
auto DecorValue = PropVal;
718+
uint32_t AttrVal;
719+
DecorValue->getAsInteger(0, AttrVal);
720+
// Format is:
721+
// !Annot = !{!CC1, !CC2, ...}
722+
// !CC1 = !{i32 Load/Store, i32 Level, i32 Control}
723+
// !CC2 = !{i32 Load/Store, i32 Level, i32 Control}
724+
// ...
725+
LLVMContext &Ctx = M.getContext();
726+
uint32_t CacheMode = 0;
727+
while (AttrVal) {
728+
// The attribute value encodes cache control and levels.
729+
// Low-order to high-order nibbles hold cache levels specified for the
730+
// enumerated SYCL cache modes. Lowest order nibble for uncached, next
731+
// for cached, and so on.
732+
// In each nibble cache levels are encoded as L1=1, L2=2, L3=4 and L4=8.
733+
// The SPIR-V encoding of cache levels L1..L4 uses values 0..3.
734+
uint32_t CacheLevel = 0;
735+
uint32_t LevelMask = AttrVal & 0xf;
736+
while (LevelMask) {
737+
if (LevelMask & 1)
738+
MDOpsCacheProp.push_back(buildSpirvDecorCacheProp(
739+
Ctx, *PropName, DecorCode, CacheMode, CacheLevel));
740+
++CacheLevel;
741+
LevelMask >>= 1;
742+
}
743+
++CacheMode;
744+
AttrVal >>= 4;
745+
}
746+
} else {
747+
FPGAProp = true;
748+
// Expected format is '{X}' or '{X:Y}' where X is decoration ID and
749+
// Y is the value if present. It encloses Y in " to ensure that
750+
// string values are handled correctly. Note that " around values are
751+
// always valid, even if the decoration parameters are not strings.
752+
NewAnnotString += "{" + std::to_string(DecorCode);
753+
if (PropVal)
754+
NewAnnotString += ":\"" + PropVal->str();
755+
756+
if (PropName == "sycl-prefetch-hint")
757+
NewAnnotString += ",1"; // CachedINTEL
758+
if (PropName == "sycl-prefetch-hint-nt")
759+
NewAnnotString += ",3"; // InvalidateAfterReadINTEL
760+
761+
if (PropVal)
762+
NewAnnotString += "\"";
763+
NewAnnotString += "}";
764+
}
658765
}
659766

660-
// If the new annotation string is empty there is no reason to keep it, so
661-
// replace it with the first operand and mark it for removal.
662-
if (NewAnnotString.empty()) {
767+
// If there are no other annotations (except "alignment") then there is no
768+
// reason to keep the original intrinsic, so replace it with the first operand
769+
// and mark it for removal.
770+
if (!CacheProp && !FPGAProp) {
663771
IntrInst->replaceAllUsesWith(IntrInst->getOperand(0));
664772
RemovableAnnotations.push_back(IntrInst);
665773
return true;
666774
}
667775

668-
// Either reuse a previously generated one or create a new global variable
669-
// with the new annotation string.
670-
GlobalVariable *NewAnnotStringGV = nullptr;
671-
auto ExistingNewAnnotStringIt = ReusableAnnotStrings.find(NewAnnotString);
672-
if (ExistingNewAnnotStringIt != ReusableAnnotStrings.end()) {
673-
NewAnnotStringGV = ExistingNewAnnotStringIt->second;
674-
} else {
675-
Constant *NewAnnotStringData =
676-
ConstantDataArray::getString(M.getContext(), NewAnnotString);
677-
NewAnnotStringGV = new GlobalVariable(
678-
M, NewAnnotStringData->getType(), true, GlobalValue::PrivateLinkage,
679-
NewAnnotStringData, ".str", nullptr, llvm::GlobalValue::NotThreadLocal,
680-
IntrAnnotStringArg->getType()->getPointerAddressSpace());
681-
NewAnnotStringGV->setSection(AnnotStrArgGV->getSection());
682-
NewAnnotStringGV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
683-
ReusableAnnotStrings.insert({NewAnnotString, NewAnnotStringGV});
776+
if (FPGAProp) {
777+
// Either reuse a previously generated one or create a new global variable
778+
// with the new annotation string.
779+
GlobalVariable *NewAnnotStringGV = nullptr;
780+
auto ExistingNewAnnotStringIt = ReusableAnnotStrings.find(NewAnnotString);
781+
if (ExistingNewAnnotStringIt != ReusableAnnotStrings.end()) {
782+
NewAnnotStringGV = ExistingNewAnnotStringIt->second;
783+
} else {
784+
Constant *NewAnnotStringData =
785+
ConstantDataArray::getString(M.getContext(), NewAnnotString);
786+
NewAnnotStringGV = new GlobalVariable(
787+
M, NewAnnotStringData->getType(), true, GlobalValue::PrivateLinkage,
788+
NewAnnotStringData, ".str", nullptr,
789+
llvm::GlobalValue::NotThreadLocal,
790+
IntrAnnotStringArg->getType()->getPointerAddressSpace());
791+
NewAnnotStringGV->setSection(AnnotStrArgGV->getSection());
792+
NewAnnotStringGV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
793+
ReusableAnnotStrings.insert({NewAnnotString, NewAnnotStringGV});
794+
}
795+
796+
// Replace the annotation string with a bitcast of the new global variable.
797+
IntrInst->setArgOperand(
798+
1, ConstantExpr::getBitCast(NewAnnotStringGV,
799+
IntrAnnotStringArg->getType()));
800+
801+
// The values are now in the annotation string, so we can remove the
802+
// original annotation value.
803+
PointerType *Arg4PtrTy =
804+
cast<PointerType>(IntrInst->getArgOperand(4)->getType());
805+
IntrInst->setArgOperand(4, ConstantPointerNull::get(Arg4PtrTy));
684806
}
685807

686-
// Replace the annotation string with a bitcast of the new global variable.
687-
IntrInst->setArgOperand(
688-
1, ConstantExpr::getBitCast(NewAnnotStringGV,
689-
IntrAnnotStringArg->getType()));
808+
if (CacheProp) {
809+
LLVMContext &Ctx = M.getContext();
810+
unsigned MDKindID = Ctx.getMDKindID(SPIRV_DECOR_MD_KIND);
811+
if (!FPGAProp) {
812+
// If there are no annotations other than cache controls we can apply the
813+
// controls to the pointer and remove the intrinsic.
814+
auto PtrInstr = cast<Instruction>(IntrInst->getArgOperand(0));
815+
PtrInstr->setMetadata(MDKindID, MDTuple::get(Ctx, MDOpsCacheProp));
816+
// Replace all uses of IntrInst with first operand
817+
IntrInst->replaceAllUsesWith(PtrInstr);
818+
// Delete the original IntrInst
819+
RemovableAnnotations.push_back(IntrInst);
820+
} else {
821+
// If there were FPGA annotations then we retain the original intrinsic
822+
// and apply the cache control properties to its result.
823+
IntrInst->setMetadata(MDKindID, MDTuple::get(Ctx, MDOpsCacheProp));
824+
}
825+
}
690826

691-
// The values are not in the annotation string, so we can remove the original
692-
// annotation value.
693-
PointerType *Arg4PtrTy =
694-
cast<PointerType>(IntrInst->getArgOperand(4)->getType());
695-
IntrInst->setArgOperand(4, ConstantPointerNull::get(Arg4PtrTy));
696827
return true;
697828
}

0 commit comments

Comments
 (0)