Skip to content

Commit 1364bee

Browse files
aratajewigcbot
authored andcommitted
[SPIRVReader] Fix loop metadata generation
In accordance with the SPIR-V spec loop metadata should be attached to the header block of the loop (via OpLoopMerge or OpLoopControlINTEL) whilst in LLVM IR it should be attached to latch block of the loop (via llvm.loop metadata). Fix attachment place of loop metadata in reverse translation. This is a port of the following change from Khronos SPIRV-LLVM Translator: KhronosGroup/SPIRV-LLVM-Translator@abee6f9
1 parent aa417d1 commit 1364bee

File tree

2 files changed

+71
-46
lines changed

2 files changed

+71
-46
lines changed

IGC/AdaptorOCL/SPIRV/SPIRVReader.cpp

Lines changed: 66 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ THE SOFTWARE.
5555

5656
#include <llvm/Support/ScaledNumber.h>
5757
#include <llvm/IR/IntrinsicInst.h>
58+
#include <llvm/Analysis/CFG.h>
5859
#include "libSPIRV/SPIRVDebugInfoExt.h"
5960
#include "llvm/Transforms/Utils/Cloning.h"
6061
#include "common/LLVMWarningsPop.hpp"
@@ -1433,6 +1434,9 @@ class SPIRVToLLVM {
14331434
// which are supposed to be replaced by the real values later.
14341435
typedef std::map<SPIRVValue *, LoadInst*> SPIRVToLLVMPlaceholderMap;
14351436

1437+
typedef std::map<const BasicBlock*, const SPIRVValue*>
1438+
SPIRVToLLVMLoopMetadataMap;
1439+
14361440
Value *getTranslatedValue(SPIRVValue *BV);
14371441

14381442
private:
@@ -1455,6 +1459,11 @@ class SPIRVToLLVM {
14551459
SPIRVToLLVMMDAliasInstMap MDAliasScopeMap;
14561460
SPIRVToLLVMMDAliasInstMap MDAliasListMap;
14571461

1462+
// Loops metadata is translated in the end of a function translation.
1463+
// This storage contains pairs of translated loop header basic block and loop
1464+
// metadata SPIR-V instruction in SPIR-V representation of this basic block.
1465+
SPIRVToLLVMLoopMetadataMap FuncLoopMetadataMap;
1466+
14581467
Type *mapType(SPIRVType *BT, Type *T) {
14591468
TypeMap[BT] = T;
14601469
return T;
@@ -1534,7 +1543,8 @@ class SPIRVToLLVM {
15341543
bool foreachFuncCtlMask(Source, Func);
15351544

15361545
template <typename LoopInstType>
1537-
void setLLVMLoopMetadata(LoopInstType* LM, BranchInst* BI);
1546+
void setLLVMLoopMetadata(const LoopInstType* LM, Instruction* BI);
1547+
void transLLVMLoopMetadata(const Function* F);
15381548
inline llvm::Metadata *getMetadataFromName(std::string Name);
15391549
inline std::vector<llvm::Metadata *>
15401550
getMetadataFromNameAndParameter(std::string Name, SPIRVWord Parameter);
@@ -1823,9 +1833,12 @@ SPIRVToLLVM::getMetadataFromNameAndParameter(std::string Name,
18231833

18241834

18251835
template <typename LoopInstType>
1826-
void SPIRVToLLVM::setLLVMLoopMetadata(LoopInstType* LM, BranchInst* BI) {
1836+
void SPIRVToLLVM::setLLVMLoopMetadata(const LoopInstType* LM, Instruction* BI) {
18271837
if (!LM)
18281838
return;
1839+
1840+
IGC_ASSERT(BI && isa<BranchInst>(BI));
1841+
18291842
auto Temp = MDNode::getTemporary(*Context, None);
18301843
auto Self = MDNode::get(*Context, Temp.get());
18311844
Self->replaceOperandWith(0, Self);
@@ -1898,6 +1911,40 @@ void SPIRVToLLVM::setLLVMLoopMetadata(LoopInstType* LM, BranchInst* BI) {
18981911
BI->setMetadata("llvm.loop", Node);
18991912
}
19001913

1914+
void SPIRVToLLVM::transLLVMLoopMetadata(const Function *F) {
1915+
assert(F);
1916+
1917+
if (!FuncLoopMetadataMap.empty()) {
1918+
// In SPIRV loop metadata is linked to a header basic block of a loop
1919+
// whilst in LLVM IR it is linked to a latch basic block (the one
1920+
// whose back edge goes to a header basic block) of the loop.
1921+
1922+
using Edge = std::pair<const BasicBlock *, const BasicBlock *>;
1923+
SmallVector<Edge, 32> Edges;
1924+
FindFunctionBackedges(*F, Edges);
1925+
1926+
for (const auto &BkEdge : Edges) {
1927+
// Check that loop header BB contains loop metadata.
1928+
const auto LMDItr = FuncLoopMetadataMap.find(BkEdge.second);
1929+
if (LMDItr == FuncLoopMetadataMap.end())
1930+
continue;
1931+
1932+
auto *BI = const_cast<Instruction *>(BkEdge.first->getTerminator());
1933+
const auto *LMD = LMDItr->second;
1934+
if (LMD->getOpCode() == OpLoopMerge) {
1935+
const auto *LM = static_cast<const SPIRVLoopMerge *>(LMD);
1936+
setLLVMLoopMetadata<SPIRVLoopMerge>(LM, BI);
1937+
} else if (LMD->getOpCode() == OpLoopControlINTEL) {
1938+
const auto *LCI = static_cast<const SPIRVLoopControlINTEL *>(LMD);
1939+
setLLVMLoopMetadata<SPIRVLoopControlINTEL>(LCI, BI);
1940+
}
1941+
}
1942+
1943+
// Loop metadata map should be re-filled during each function translation.
1944+
FuncLoopMetadataMap.clear();
1945+
}
1946+
}
1947+
19011948
GlobalValue::LinkageTypes
19021949
SPIRVToLLVM::transLinkageType(const SPIRVValue* V) {
19031950
if (V->getLinkageType() == LinkageTypeInternal) {
@@ -2997,46 +3044,22 @@ SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
29973044
// Translation of instructions
29983045
switch (BV->getOpCode()) {
29993046
case OpBranch: {
3000-
auto BR = static_cast<SPIRVBranch *>(BV);
3001-
IGC_ASSERT_MESSAGE(BB, "Invalid BB");
3002-
3003-
auto BI = BranchInst::Create(
3004-
dyn_cast<BasicBlock>(transValue(BR->getTargetLabel(), F, BB)), BB);
3005-
3006-
SPIRVInstruction *Prev = BR->getPrevious();
3007-
if(Prev && Prev->getOpCode() == OpLoopMerge) {
3008-
auto LM = static_cast<SPIRVLoopMerge*>(Prev);
3009-
setLLVMLoopMetadata<SPIRVLoopMerge>(LM, BI);
3010-
}
3011-
else if (Prev && Prev->getOpCode() == OpLoopControlINTEL) {
3012-
auto LCI = static_cast<SPIRVLoopControlINTEL*>(Prev);
3013-
setLLVMLoopMetadata<SPIRVLoopControlINTEL>(LCI, BI);
3014-
}
3015-
3047+
auto *BR = static_cast<SPIRVBranch *>(BV);
3048+
auto *BI = BranchInst::Create(
3049+
cast<BasicBlock>(transValue(BR->getTargetLabel(), F, BB)), BB);
3050+
// Loop metadata will be translated in the end of function translation.
30163051
return mapValue(BV, BI);
30173052
}
30183053
break;
30193054

30203055
case OpBranchConditional: {
3021-
auto BR = static_cast<SPIRVBranchConditional *>(BV);
3022-
IGC_ASSERT_MESSAGE(BB, "Invalid BB");
3023-
auto BC = BranchInst::Create(
3024-
dyn_cast<BasicBlock>(transValue(BR->getTrueLabel(), F, BB)),
3025-
dyn_cast<BasicBlock>(transValue(BR->getFalseLabel(), F, BB)),
3026-
// cond must be an i1, truncate bool to i1 if it was an i8.
3027-
transValue(BR->getCondition(), F, BB, true, BoolAction::Truncate),
3028-
BB);
3029-
3030-
SPIRVInstruction *Prev = BR->getPrevious();
3031-
if (Prev && Prev->getOpCode() == OpLoopMerge) {
3032-
if (auto LM = static_cast<SPIRVLoopMerge *>(Prev))
3033-
setLLVMLoopMetadata<SPIRVLoopMerge>(LM, BC);
3034-
}
3035-
else if (Prev && Prev->getOpCode() == OpLoopControlINTEL) {
3036-
if (auto LCI = static_cast<SPIRVLoopControlINTEL *>(Prev))
3037-
setLLVMLoopMetadata<SPIRVLoopControlINTEL>(LCI, BC);
3038-
}
3039-
3056+
auto *BR = static_cast<SPIRVBranchConditional *>(BV);
3057+
auto *BC = BranchInst::Create(
3058+
cast<BasicBlock>(transValue(BR->getTrueLabel(), F, BB)),
3059+
cast<BasicBlock>(transValue(BR->getFalseLabel(), F, BB)),
3060+
// cond must be an i1, truncate bool to i1 if it was an i8.
3061+
transValue(BR->getCondition(), F, BB, true, BoolAction::Truncate), BB);
3062+
// Loop metadata will be translated in the end of function translation.
30403063
return mapValue(BV, BC);
30413064
}
30423065
break;
@@ -3217,11 +3240,10 @@ SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
32173240
BV->getName(), BB));
32183241
}
32193242
break;
3220-
// OpenCL Compiler does not use this instruction
3221-
// Should be translated at OpBranch or OpBranchConditional cases
3222-
case OpLoopMerge:
3223-
case OpLoopControlINTEL:
3243+
case OpLoopMerge: // Will be translated after all other function's
3244+
case OpLoopControlINTEL: // instructions are translated.
32243245
{
3246+
FuncLoopMetadataMap[BB] = BV;
32253247
return nullptr;
32263248
}
32273249
break;
@@ -3655,6 +3677,9 @@ SPIRVToLLVM::transFunction(SPIRVFunction *BF) {
36553677
transValue(BInst, F, BB, false, BoolAction::Noop);
36563678
}
36573679
}
3680+
3681+
transLLVMLoopMetadata(F);
3682+
36583683
return F;
36593684
}
36603685

IGC/AdaptorOCL/SPIRV/libSPIRV/SPIRVInstruction.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -923,8 +923,8 @@ class SPIRVLoopMerge : public SPIRVInstruction {
923923

924924
SPIRVId getMergeBlock() { return MergeBlock; }
925925
SPIRVId getContinueTarget() { return ContinueTarget; }
926-
SPIRVWord getLoopControl() { return LoopControl; }
927-
std::vector<SPIRVWord> getLoopControlParameters() {
926+
SPIRVWord getLoopControl() const { return LoopControl; }
927+
std::vector<SPIRVWord> getLoopControlParameters() const {
928928
return LoopControlParameters;
929929
}
930930

@@ -954,7 +954,7 @@ class SPIRVSwitch: public SPIRVInstruction {
954954
setHasNoId();
955955
setHasNoType();
956956
}
957-
std::vector<SPIRVValue *> getPairs() {
957+
std::vector<SPIRVValue *> getPairs() const {
958958
return getValues(Pairs);
959959
}
960960
SPIRVValue *getSelect() const { return getValue(Select);}
@@ -1107,9 +1107,9 @@ class SPIRVLoopControlINTEL : public SPIRVInstruction {
11071107
setHasNoType();
11081108
}
11091109

1110-
SPIRVWord getLoopControl() { return LoopControl; }
1110+
SPIRVWord getLoopControl() const { return LoopControl; }
11111111

1112-
std::vector<SPIRVWord> getLoopControlParameters() {
1112+
std::vector<SPIRVWord> getLoopControlParameters() const {
11131113
return LoopControlParameters;
11141114
}
11151115

0 commit comments

Comments
 (0)