Skip to content

Commit 0681d12

Browse files
author
iclsrc
committed
Merge from 'sycl' to 'sycl-web' (#1)
2 parents 0417fd6 + ab467f7 commit 0681d12

File tree

12 files changed

+802
-118
lines changed

12 files changed

+802
-118
lines changed

llvm-spirv/lib/SPIRV/SPIRVInternal.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,9 @@ int getMDOperandAsInt(MDNode *N, unsigned I);
777777
/// Get metadata operand as string.
778778
std::string getMDOperandAsString(MDNode *N, unsigned I);
779779

780+
/// Get metadata operand as another metadata node
781+
MDNode *getMDOperandAsMDNode(MDNode *N, unsigned I);
782+
780783
/// Get metadata operand as type.
781784
Type *getMDOperandAsType(MDNode *N, unsigned I);
782785

@@ -935,10 +938,6 @@ template <> inline void SPIRVMap<std::string, Op, SPIRVOpaqueType>::init() {
935938
// Check if the module contains llvm.loop.* metadata
936939
bool hasLoopMetadata(const Module *M);
937940

938-
// If the branch instruction has !llvm.loop metadata, go through its operands
939-
// and find Loop Control mask and possible parameters.
940-
spv::LoopControlMask getLoopControl(const BranchInst *Branch,
941-
std::vector<SPIRVWord> &Parameters);
942941
} // namespace SPIRV
943942

944943
#endif // SPIRV_SPIRVINTERNAL_H

llvm-spirv/lib/SPIRV/SPIRVReader.cpp

Lines changed: 120 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,11 @@
5151
#include "SPIRVValue.h"
5252

5353
#include "llvm/ADT/DenseMap.h"
54-
#include "llvm/Analysis/CFG.h"
54+
#include "llvm/Analysis/LoopInfo.h"
5555
#include "llvm/BinaryFormat/Dwarf.h"
5656
#include "llvm/IR/Constants.h"
5757
#include "llvm/IR/DerivedTypes.h"
58+
#include "llvm/IR/Dominators.h"
5859
#include "llvm/IR/IRBuilder.h"
5960
#include "llvm/IR/Instructions.h"
6061
#include "llvm/IR/IntrinsicInst.h"
@@ -590,18 +591,17 @@ SPIRVToLLVM::getMetadataFromNameAndParameter(std::string Name,
590591
}
591592

592593
template <typename LoopInstType>
593-
void SPIRVToLLVM::setLLVMLoopMetadata(const LoopInstType *LM, Instruction *BI) {
594+
void SPIRVToLLVM::setLLVMLoopMetadata(const LoopInstType *LM,
595+
const Loop *LoopObj) {
594596
if (!LM)
595597
return;
596598

597-
assert(BI && isa<BranchInst>(BI));
598-
599599
auto Temp = MDNode::getTemporary(*Context, None);
600600
auto Self = MDNode::get(*Context, Temp.get());
601601
Self->replaceOperandWith(0, Self);
602602
SPIRVWord LC = LM->getLoopControl();
603603
if (LC == LoopControlMaskNone) {
604-
BI->setMetadata("llvm.loop", Self);
604+
LoopObj->setLoopID(Self);
605605
return;
606606
}
607607

@@ -685,49 +685,137 @@ void SPIRVToLLVM::setLLVMLoopMetadata(const LoopInstType *LM, Instruction *BI) {
685685
LoopControlParameters[++NumParam])));
686686
break;
687687
}
688-
default:
688+
case DependencyArrayINTEL: {
689+
// Collect array variable <-> safelen information
690+
std::map<Value *, unsigned> ArraySflnMap;
691+
unsigned NumOperandPairs = LoopControlParameters[++NumParam];
692+
unsigned OperandsEndIndex = NumParam + NumOperandPairs * 2;
693+
assert(OperandsEndIndex <= LoopControlParameters.size() &&
694+
"Missing loop control parameter!");
695+
SPIRVModule *M = LM->getModule();
696+
while (NumParam < OperandsEndIndex) {
697+
SPIRVId ArraySPIRVId = LoopControlParameters[++NumParam];
698+
Value *ArrayVar = ValueMap[M->getValue(ArraySPIRVId)];
699+
unsigned Safelen = LoopControlParameters[++NumParam];
700+
ArraySflnMap.emplace(ArrayVar, Safelen);
701+
}
702+
703+
// A single run over the loop to retrieve all GetElementPtr instructions
704+
// that access relevant array variables
705+
std::map<Value *, std::vector<GetElementPtrInst *>> ArrayGEPMap;
706+
for (auto &BB : LoopObj->blocks()) {
707+
for (Instruction &I : *BB) {
708+
auto *GEP = dyn_cast<GetElementPtrInst>(&I);
709+
if (!GEP)
710+
continue;
711+
712+
Value *AccessedArray = GEP->getPointerOperand();
713+
auto ArraySflnIt = ArraySflnMap.find(AccessedArray);
714+
if (ArraySflnIt != ArraySflnMap.end())
715+
ArrayGEPMap[AccessedArray].push_back(GEP);
716+
}
717+
}
718+
719+
// Create index group metadata nodes specific - one per each array
720+
// variables. Mark each GEP accessing a particular array variable
721+
// into a corresponding index group
722+
std::map<unsigned, std::vector<MDNode *>> SafelenIdxGroupMap;
723+
for (auto &ArrayGEPIt : ArrayGEPMap) {
724+
// Emit a distinct index group that will be referenced from
725+
// llvm.loop.parallel_access_indices metadata
726+
auto *CurrentDepthIdxGroup =
727+
llvm::MDNode::getDistinct(*Context, None);
728+
unsigned Safelen = ArraySflnMap.find(ArrayGEPIt.first)->second;
729+
SafelenIdxGroupMap[Safelen].push_back(CurrentDepthIdxGroup);
730+
731+
for (auto *GEP : ArrayGEPIt.second) {
732+
StringRef IdxGroupMDName("llvm.index.group");
733+
llvm::MDNode *PreviousIdxGroup = GEP->getMetadata(IdxGroupMDName);
734+
if (!PreviousIdxGroup) {
735+
GEP->setMetadata(IdxGroupMDName, CurrentDepthIdxGroup);
736+
continue;
737+
}
738+
739+
// If we're dealing with an embedded loop, it may be the case
740+
// that GEP instructions for some of the arrays were already
741+
// marked by the algorithm when it went over the outer level loops.
742+
// In order to retain the IVDep information for each "loop
743+
// dimension", we will mark such GEP's into a separate joined node
744+
// that will refer to the previous levels' index groups AND to the
745+
// index group specific to the current loop.
746+
std::vector<llvm::Metadata *> CurrentDepthOperands;
747+
for (auto &Op : PreviousIdxGroup->operands())
748+
CurrentDepthOperands.push_back(Op);
749+
if (CurrentDepthOperands.size() == 0)
750+
CurrentDepthOperands.push_back(PreviousIdxGroup);
751+
CurrentDepthOperands.push_back(CurrentDepthIdxGroup);
752+
auto *JointIdxGroup =
753+
llvm::MDNode::get(*Context, CurrentDepthOperands);
754+
GEP->setMetadata(IdxGroupMDName, JointIdxGroup);
755+
}
756+
}
757+
758+
for (auto &SflnIdxGroupIt : SafelenIdxGroupMap) {
759+
auto *Name =
760+
MDString::get(*Context, "llvm.loop.parallel_access_indices");
761+
unsigned SflnValue = SflnIdxGroupIt.first;
762+
llvm::Metadata *SafelenMDOp =
763+
SflnValue ? ConstantAsMetadata::get(ConstantInt::get(
764+
Type::getInt32Ty(*Context), SflnValue))
765+
: nullptr;
766+
std::vector<llvm::Metadata *> Parameters{Name};
767+
for (auto *Node : SflnIdxGroupIt.second)
768+
Parameters.push_back(Node);
769+
if (SafelenMDOp)
770+
Parameters.push_back(SafelenMDOp);
771+
Metadata.push_back(llvm::MDNode::get(*Context, Parameters));
772+
}
689773
break;
690774
}
775+
default:
776+
llvm_unreachable(
777+
"Unexpected token in LoopControlExtendedConstrolsMask");
778+
}
691779
++NumParam;
692780
}
693781
}
694782
llvm::MDNode *Node = llvm::MDNode::get(*Context, Metadata);
695783

696784
// Set the first operand to refer itself
697785
Node->replaceOperandWith(0, Node);
698-
BI->setMetadata("llvm.loop", Node);
786+
LoopObj->setLoopID(Node);
699787
}
700788

701789
void SPIRVToLLVM::transLLVMLoopMetadata(const Function *F) {
702790
assert(F);
703791

704-
if (!FuncLoopMetadataMap.empty()) {
705-
// In SPIRV loop metadata is linked to a header basic block of a loop
706-
// whilst in LLVM IR it is linked to a latch basic block (the one
707-
// whose back edge goes to a header basic block) of the loop.
708-
709-
using Edge = std::pair<const BasicBlock *, const BasicBlock *>;
710-
SmallVector<Edge, 32> Edges;
711-
FindFunctionBackedges(*F, Edges);
712-
713-
for (const auto &BkEdge : Edges) {
714-
// Check that loop header BB contains loop metadata.
715-
const auto LMDItr = FuncLoopMetadataMap.find(BkEdge.second);
716-
if (LMDItr == FuncLoopMetadataMap.end())
717-
continue;
718-
719-
auto *BI = const_cast<Instruction *>(BkEdge.first->getTerminator());
720-
const auto *LMD = LMDItr->second;
721-
if (LMD->getOpCode() == OpLoopMerge) {
722-
const auto *LM = static_cast<const SPIRVLoopMerge *>(LMD);
723-
setLLVMLoopMetadata<SPIRVLoopMerge>(LM, BI);
724-
} else if (LMD->getOpCode() == OpLoopControlINTEL) {
725-
const auto *LCI = static_cast<const SPIRVLoopControlINTEL *>(LMD);
726-
setLLVMLoopMetadata<SPIRVLoopControlINTEL>(LCI, BI);
727-
}
792+
if (FuncLoopMetadataMap.empty())
793+
return;
728794

729-
FuncLoopMetadataMap.erase(LMDItr);
795+
DominatorTree DomTree(*(const_cast<Function *>(F)));
796+
LoopInfo LI(DomTree);
797+
798+
// In SPIRV loop metadata is linked to a header basic block of a loop
799+
// whilst in LLVM IR it is linked to a latch basic block (the one
800+
// whose back edge goes to a header basic block) of the loop.
801+
// To ensure consistent behaviour, we can rely on the `llvm::Loop`
802+
// class to handle the metadata placement
803+
for (const auto *LoopObj : LI.getLoopsInPreorder()) {
804+
// Check that loop header BB contains loop metadata.
805+
const auto LMDItr = FuncLoopMetadataMap.find(LoopObj->getHeader());
806+
if (LMDItr == FuncLoopMetadataMap.end())
807+
continue;
808+
809+
const auto *LMD = LMDItr->second;
810+
if (LMD->getOpCode() == OpLoopMerge) {
811+
const auto *LM = static_cast<const SPIRVLoopMerge *>(LMD);
812+
setLLVMLoopMetadata<SPIRVLoopMerge>(LM, LoopObj);
813+
} else if (LMD->getOpCode() == OpLoopControlINTEL) {
814+
const auto *LCI = static_cast<const SPIRVLoopControlINTEL *>(LMD);
815+
setLLVMLoopMetadata<SPIRVLoopControlINTEL>(LCI, LoopObj);
730816
}
817+
818+
FuncLoopMetadataMap.erase(LMDItr);
731819
}
732820
}
733821

llvm-spirv/lib/SPIRV/SPIRVReader.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,10 @@
5050
namespace llvm {
5151
class Module;
5252
class Type;
53-
class Value;
5453
class Instruction;
5554
class CallInst;
5655
class BasicBlock;
56+
class Loop;
5757
class Function;
5858
class GlobalVariable;
5959
class LLVMContext;
@@ -255,7 +255,7 @@ class SPIRVToLLVM {
255255
Value *oclTransConstantPipeStorage(SPIRV::SPIRVConstantPipeStorage *BCPS);
256256
void setName(llvm::Value *V, SPIRVValue *BV);
257257
template <typename LoopInstType>
258-
void setLLVMLoopMetadata(const LoopInstType *LM, Instruction *BI);
258+
void setLLVMLoopMetadata(const LoopInstType *LM, const Loop *LoopObj);
259259
void transLLVMLoopMetadata(const Function *F);
260260
inline llvm::Metadata *getMetadataFromName(std::string Name);
261261
inline std::vector<llvm::Metadata *>

llvm-spirv/lib/SPIRV/SPIRVUtil.cpp

Lines changed: 11 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -851,20 +851,23 @@ int getMDOperandAsInt(MDNode *N, unsigned I) {
851851
return mdconst::dyn_extract<ConstantInt>(N->getOperand(I))->getZExtValue();
852852
}
853853

854-
std::string getMDOperandAsString(MDNode *N, unsigned I) {
854+
// Additional helper function to be reused by getMDOperandAs* helpers
855+
Metadata *getMDOperandOrNull(MDNode *N, unsigned I) {
855856
if (!N)
856-
return "";
857-
858-
Metadata *Op = N->getOperand(I);
859-
if (!Op)
860-
return "";
857+
return nullptr;
858+
return N->getOperand(I);
859+
}
861860

862-
if (MDString *Str = dyn_cast<MDString>(Op)) {
861+
std::string getMDOperandAsString(MDNode *N, unsigned I) {
862+
if (auto *Str = dyn_cast_or_null<MDString>(getMDOperandOrNull(N, I)))
863863
return Str->getString().str();
864-
}
865864
return "";
866865
}
867866

867+
MDNode *getMDOperandAsMDNode(MDNode *N, unsigned I) {
868+
return dyn_cast_or_null<MDNode>(getMDOperandOrNull(N, I));
869+
}
870+
868871
Type *getMDOperandAsType(MDNode *N, unsigned I) {
869872
return cast<ValueAsMetadata>(N->getOperand(I))->getType();
870873
}
@@ -1511,57 +1514,4 @@ bool hasLoopMetadata(const Module *M) {
15111514
return false;
15121515
}
15131516

1514-
spv::LoopControlMask getLoopControl(const BranchInst *Branch,
1515-
std::vector<SPIRVWord> &Parameters) {
1516-
if (!Branch)
1517-
return spv::LoopControlMaskNone;
1518-
MDNode *LoopMD = Branch->getMetadata("llvm.loop");
1519-
if (!LoopMD)
1520-
return spv::LoopControlMaskNone;
1521-
1522-
size_t LoopControl = spv::LoopControlMaskNone;
1523-
for (const MDOperand &MDOp : LoopMD->operands()) {
1524-
if (MDNode *Node = dyn_cast<MDNode>(MDOp)) {
1525-
std::string S = getMDOperandAsString(Node, 0);
1526-
// Set the loop control bits. Parameters are set in the order described
1527-
// in 3.23 SPIR-V Spec. rev. 1.4:
1528-
// Bits that are set can indicate whether an additional operand follows,
1529-
// as described by the table. If there are multiple following operands
1530-
// indicated, they are ordered: Those indicated by smaller-numbered bits
1531-
// appear first.
1532-
if (S == "llvm.loop.unroll.disable")
1533-
LoopControl |= spv::LoopControlDontUnrollMask;
1534-
else if (S == "llvm.loop.unroll.full" || S == "llvm.loop.unroll.enable")
1535-
LoopControl |= spv::LoopControlUnrollMask;
1536-
if (S == "llvm.loop.ivdep.enable")
1537-
LoopControl |= spv::LoopControlDependencyInfiniteMask;
1538-
if (S == "llvm.loop.ivdep.safelen") {
1539-
size_t I = getMDOperandAsInt(Node, 1);
1540-
Parameters.push_back(I);
1541-
LoopControl |= spv::LoopControlDependencyLengthMask;
1542-
}
1543-
// PartialCount must not be used with the DontUnroll bit
1544-
if (S == "llvm.loop.unroll.count" &&
1545-
!(LoopControl & LoopControlDontUnrollMask)) {
1546-
size_t I = getMDOperandAsInt(Node, 1);
1547-
Parameters.push_back(I);
1548-
LoopControl |= spv::LoopControlPartialCountMask;
1549-
}
1550-
if (S == "llvm.loop.ii.count") {
1551-
Parameters.push_back(InitiationIntervalINTEL);
1552-
size_t I = getMDOperandAsInt(Node, 1);
1553-
Parameters.push_back(I);
1554-
LoopControl |= spv::LoopControlExtendedControlsMask;
1555-
}
1556-
if (S == "llvm.loop.max_concurrency.count") {
1557-
Parameters.push_back(MaxConcurrencyINTEL);
1558-
size_t I = getMDOperandAsInt(Node, 1);
1559-
Parameters.push_back(I);
1560-
LoopControl |= spv::LoopControlExtendedControlsMask;
1561-
}
1562-
}
1563-
}
1564-
return static_cast<spv::LoopControlMask>(LoopControl);
1565-
}
1566-
15671517
} // namespace SPIRV

0 commit comments

Comments
 (0)