Skip to content

Commit

Permalink
Implementation of SPIRV -> LLVM IR translation for
Browse files Browse the repository at this point in the history
SPV_INTEL__device_side_avc_motion_estimation extension.

Corresponding OpenCL extension is 'cl_intel_device_side_avc_motion_estimation'
https://www.khronos.org/registry/OpenCL/extensions/intel/cl_intel_device_side_avc_motion_estimation.txt
  • Loading branch information
aratajew authored and AlexeySotkin committed Jun 26, 2019
1 parent 218d450 commit 564c8d1
Show file tree
Hide file tree
Showing 11 changed files with 785 additions and 9 deletions.
31 changes: 28 additions & 3 deletions lib/SPIRV/Mangler/ManglingUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,20 @@ static const char *PrimitiveNames[PRIMITIVE_NUM] = {
"kernel_enqueue_flags_t",
"clk_profiling_info",
"memory_order",
"memory_scope"};
"memory_scope",
"intel_sub_group_avc_mce_payload_t",
"intel_sub_group_avc_ime_payload_t",
"intel_sub_group_avc_ref_payload_t",
"intel_sub_group_avc_sic_payload_t",
"intel_sub_group_avc_mce_result_t",
"intel_sub_group_avc_ime_result_t",
"intel_sub_group_avc_ref_result_t",
"intel_sub_group_avc_sic_result_t",
"intel_sub_group_avc_ime_result_single_reference_streamout_t",
"intel_sub_group_avc_ime_result_dual_reference_streamout_t",
"intel_sub_group_avc_ime_result_single_reference_streamin_t",
"intel_sub_group_avc_ime_result_dual_reference_streamin_t"
};

const char *MangledTypes[PRIMITIVE_NUM] = {
"b", // BOOL
Expand Down Expand Up @@ -144,9 +157,21 @@ const char *MangledTypes[PRIMITIVE_NUM] = {
"i", // PRIMITIVE_MEMORY_ORDER
"i", // PRIMITIVE_MEMORY_SCOPE
#else
"12memory_order", // PRIMITIVE_MEMORY_ORDER
"12memory_scope" // PRIMITIVE_MEMORY_SCOPE
"12memory_order", // PRIMITIVE_MEMORY_ORDER
"12memory_scope", // PRIMITIVE_MEMORY_SCOPE
#endif
"37ocl_intel_sub_group_avc_mce_payload_t", // PRIMITIVE_SUB_GROUP_AVC_MCE_PAYLOAD_T
"37ocl_intel_sub_group_avc_ime_payload_t", // PRIMITIVE_SUB_GROUP_AVC_IME_PAYLOAD_T
"37ocl_intel_sub_group_avc_ref_payload_t", // PRIMITIVE_SUB_GROUP_AVC_REF_PAYLOAD_T
"37ocl_intel_sub_group_avc_sic_payload_t", // PRIMITIVE_SUB_GROUP_AVC_SIC_PAYLOAD_T
"36ocl_intel_sub_group_avc_mce_result_t", // PRIMITIVE_SUB_GROUP_AVC_MCE_RESULT_T
"36ocl_intel_sub_group_avc_ime_result_t", // PRIMITIVE_SUB_GROUP_AVC_IME_RESULT_T
"36ocl_intel_sub_group_avc_ref_result_t", // PRIMITIVE_SUB_GROUP_AVC_REF_RESULT_T
"36ocl_intel_sub_group_avc_sic_result_t", // PRIMITIVE_SUB_GROUP_AVC_REF_RESULT_T
"63ocl_intel_sub_group_avc_ime_result_single_reference_streamout_t", // PRIMITIVE_SUB_GROUP_AVC_IME_SINGLE_REF_STREAMOUT_T
"61ocl_intel_sub_group_avc_ime_result_dual_reference_streamout_t", // PRIMITIVE_SUB_GROUP_AVC_IME_DUAL_REF_STREAMOUT_T
"55ocl_intel_sub_group_avc_ime_single_reference_streamin_t", // PRIMITIVE_SUB_GROUP_AVC_IME_SINGLE_REF_STREAMIN_T
"53ocl_intel_sub_group_avc_ime_dual_reference_streamin_t" // PRIMITIVE_SUB_GROUP_AVC_IME_DUAL_REF_STREAMIN_T
};

const char *ReadableAttribute[ATTR_NUM] = {
Expand Down
14 changes: 13 additions & 1 deletion lib/SPIRV/Mangler/ParameterType.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,19 @@ enum TypePrimitiveEnum {
PRIMITIVE_CLK_PROFILING_INFO,
PRIMITIVE_MEMORY_ORDER,
PRIMITIVE_MEMORY_SCOPE,
PRIMITIVE_LAST = PRIMITIVE_MEMORY_SCOPE,
PRIMITIVE_SUB_GROUP_AVC_MCE_PAYLOAD_T,
PRIMITIVE_SUB_GROUP_AVC_IME_PAYLOAD_T,
PRIMITIVE_SUB_GROUP_AVC_REF_PAYLOAD_T,
PRIMITIVE_SUB_GROUP_AVC_SIC_PAYLOAD_T,
PRIMITIVE_SUB_GROUP_AVC_MCE_RESULT_T,
PRIMITIVE_SUB_GROUP_AVC_IME_RESULT_T,
PRIMITIVE_SUB_GROUP_AVC_REF_RESULT_T,
PRIMITIVE_SUB_GROUP_AVC_SIC_RESULT_T,
PRIMITIVE_SUB_GROUP_AVC_IME_SINGLE_REF_STREAMOUT_T,
PRIMITIVE_SUB_GROUP_AVC_IME_DUAL_REF_STREAMOUT_T,
PRIMITIVE_SUB_GROUP_AVC_IME_SINGLE_REF_STREAMIN_T,
PRIMITIVE_SUB_GROUP_AVC_IME_DUAL_REF_STREAMIN_T,
PRIMITIVE_LAST = PRIMITIVE_SUB_GROUP_AVC_IME_DUAL_REF_STREAMIN_T,
PRIMITIVE_NONE,
// Keep this at the end.
PRIMITIVE_NUM = PRIMITIVE_NONE
Expand Down
81 changes: 79 additions & 2 deletions lib/SPIRV/OCLUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ namespace OCLUtil {
#define SPIRV_EVENT_T_ADDR_SPACE SPIRV_OCL_SPECIAL_TYPES_DEFAULT_ADDR_SPACE
#endif

#ifndef SPIRV_AVC_INTEL_T_ADDR_SPACE
#define SPIRV_AVC_INTEL_T_ADDR_SPACE SPIRV_OCL_SPECIAL_TYPES_DEFAULT_ADDR_SPACE
#endif

#ifndef SPIRV_CLK_EVENT_T_ADDR_SPACE
#define SPIRV_CLK_EVENT_T_ADDR_SPACE SPIRV_OCL_SPECIAL_TYPES_DEFAULT_ADDR_SPACE
#endif
Expand Down Expand Up @@ -321,6 +325,8 @@ SPIRAddressSpace getOCLOpaqueTypeAddrSpace(Op OpCode) {
case OpTypeSampler:
return SPIRV_SAMPLER_T_ADDR_SPACE;
default:
if (isSubgroupAvcINTELTypeOpCode(OpCode))
return SPIRV_AVC_INTEL_T_ADDR_SPACE;
assert(false && "No address space is determined for some OCL type");
return SPIRV_OCL_SPECIAL_TYPES_DEFAULT_ADDR_SPACE;
}
Expand Down Expand Up @@ -415,6 +421,13 @@ class OCLBuiltinFuncMangleInfo : public SPIRV::BuiltinFuncMangleInfo {
UnmangledName = UniqName;
size_t Pos = std::string::npos;

auto EraseSubstring = [](std::string &Str, std::string ToErase) {
size_t Pos = Str.find(ToErase);
if (Pos != std::string::npos) {
Str.erase(Pos, ToErase.length());
}
};

if (UnmangledName.find("async_work_group") == 0) {
addUnsignedArg(-1);
setArgAttr(1, SPIR::ATTR_CONST);
Expand Down Expand Up @@ -573,11 +586,75 @@ class OCLBuiltinFuncMangleInfo : public SPIRV::BuiltinFuncMangleInfo {
(Pos = UnmangledName.find("umin")) != std::string::npos) {
addUnsignedArg(-1);
UnmangledName.erase(Pos, 1);
} else if (UnmangledName.find("broadcast") != std::string::npos)
} else if (UnmangledName.find("broadcast") != std::string::npos) {
addUnsignedArg(-1);
else if (UnmangledName.find(kOCLBuiltinName::SampledReadImage) == 0) {
} else if (UnmangledName.find(kOCLBuiltinName::SampledReadImage) == 0) {
UnmangledName.erase(0, strlen(kOCLBuiltinName::Sampled));
addSamplerArg(1);
} else if (UnmangledName.find(kOCLSubgroupsAVCIntel::Prefix) !=
std::string::npos) {
if (UnmangledName.find("evaluate_with_single_reference") !=
std::string::npos)
addSamplerArg(2);
else if (UnmangledName.find("evaluate_with_multi_reference") !=
std::string::npos) {
addUnsignedArg(1);
std::string PostFix = "_interlaced";
if (UnmangledName.find(PostFix) != std::string::npos) {
addUnsignedArg(2);
addSamplerArg(3);
size_t Pos = UnmangledName.find(PostFix);
if (Pos != std::string::npos)
UnmangledName.erase(Pos, PostFix.length());
} else
addSamplerArg(2);
} else if (UnmangledName.find("evaluate_with_dual_reference") !=
std::string::npos)
addSamplerArg(3);
else if (UnmangledName.find("fme_initialize") != std::string::npos)
addUnsignedArgs(0, 6);
else if (UnmangledName.find("bme_initialize") != std::string::npos)
addUnsignedArgs(0, 7);
else if (UnmangledName.find("set_inter_base_multi_reference_penalty") !=
std::string::npos ||
UnmangledName.find("set_inter_shape_penalty") !=
std::string::npos)
addUnsignedArg(0);
else if (UnmangledName.find("set_motion_vector_cost_function") !=
std::string::npos)
addUnsignedArgs(0, 2);
else if (UnmangledName.find(kOCLSubgroupsAVCIntel::MCEPrefix) !=
std::string::npos) {
if (UnmangledName.find("get_default") != std::string::npos)
addUnsignedArgs(0, 1);
} else if (UnmangledName.find(kOCLSubgroupsAVCIntel::IMEPrefix) !=
std::string::npos) {
if (UnmangledName.find("initialize") != std::string::npos)
addUnsignedArgs(0, 2);
else if (UnmangledName.find("set_single_reference") !=
std::string::npos)
addUnsignedArg(1);
else if (UnmangledName.find("adjust_ref_offset") != std::string::npos)
addUnsignedArgs(1, 3);
else if (UnmangledName.find("set_max_motion_vector_count") !=
std::string::npos ||
UnmangledName.find("get_border_reached") != std::string::npos)
addUnsignedArg(0);
} else if (UnmangledName.find(kOCLSubgroupsAVCIntel::SICPrefix) !=
std::string::npos) {
if (UnmangledName.find("initialize") != std::string::npos)
addUnsignedArg(0);
else if (UnmangledName.find("configure_ipe") != std::string::npos) {
if (UnmangledName.find("_luma") != std::string::npos) {
addUnsignedArgs(0, 6);
EraseSubstring(UnmangledName, "_luma");
}
if (UnmangledName.find("_chroma") != std::string::npos) {
addUnsignedArgs(7, 9);
EraseSubstring(UnmangledName, "_chroma");
}
}
}
}
}
// Auxiliarry information, it is expected what it is relevant at the moment
Expand Down
5 changes: 5 additions & 0 deletions lib/SPIRV/SPIRVInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,11 @@ class BuiltinFuncMangleInfo {
virtual ~BuiltinFuncMangleInfo() {}
const std::string &getUnmangledName() const { return UnmangledName; }
void addUnsignedArg(int Ndx) { UnsignedArgs.insert(Ndx); }
void addUnsignedArgs(int StartNdx, int StopNdx) {
assert(StartNdx < StopNdx && "wrong parameters");
for (size_t I = StartNdx; I <= StopNdx; ++I)
addUnsignedArg(I);
}
void addVoidPtrArg(int Ndx) { VoidPtrArgs.insert(Ndx); }
void addSamplerArg(int Ndx) { SamplerArgs.insert(Ndx); }
void addAtomicArg(int Ndx) { AtomicArgs.insert(Ndx); }
Expand Down
65 changes: 62 additions & 3 deletions lib/SPIRV/SPIRVReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -445,12 +445,18 @@ Type *SPIRVToLLVM::transType(SPIRVType *T, bool IsClassMember) {
T, getOrCreateOpaquePtrType(M, transOCLPipeStorageTypeName(PST),
getOCLOpaqueTypeAddrSpace(T->getOpCode())));
}
// OpenCL Compiler does not use this instruction
case OpTypeVmeImageINTEL:
return nullptr;
default: {
auto OC = T->getOpCode();
if (isOpaqueGenericTypeOpCode(OC))
if (isOpaqueGenericTypeOpCode(OC) || isSubgroupAvcINTELTypeOpCode(OC)) {
auto Name = isSubgroupAvcINTELTypeOpCode(OC)
? OCLSubgroupINTELTypeOpCodeMap::rmap(OC)
: OCLOpaqueTypeOpCodeMap::rmap(OC);
return mapType(
T, getOrCreateOpaquePtrType(M, OCLOpaqueTypeOpCodeMap::rmap(OC),
getOCLOpaqueTypeAddrSpace(OC)));
T, getOrCreateOpaquePtrType(M, Name, getOCLOpaqueTypeAddrSpace(OC)));
}
llvm_unreachable("Not implemented");
}
}
Expand Down Expand Up @@ -1490,6 +1496,7 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
BV->getName(), BB));
}

case OpVmeImageINTEL:
case OpLine:
case OpSelectionMerge: // OpenCL Compiler does not use this instruction
case OpLoopMerge: // Should be translated at OpBranch or OpBranchConditional
Expand Down Expand Up @@ -1758,6 +1765,7 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
if (isSPIRVCmpInstTransToLLVMInst(static_cast<SPIRVInstruction *>(BV))) {
return mapValue(BV, transCmpInst(BV, BB, F));
} else if ((OCLSPIRVBuiltinMap::rfind(OC, nullptr) ||
isSubgroupAvcINTELInstructionOpCode(OC) ||
isIntelSubgroupOpCode(OC)) &&
!isAtomicOpCode(OC) && !isGroupOpCode(OC) && !isPipeOpCode(OC)) {
return mapValue(
Expand Down Expand Up @@ -1882,6 +1890,54 @@ void SPIRVToLLVM::transOCLBuiltinFromInstPreproc(
else if (OC == OpImageRead && Args.size() > 2) {
// Drop "Image operands" argument
Args.erase(Args.begin() + 2);
} else if (isSubgroupAvcINTELEvaluateOpcode(OC)) {
// There are three types of AVC Intel Evaluate opcodes:
// 1. With multi reference images - does not use OpVmeImageINTEL opcode for
// reference images
// 2. With dual reference images - uses two OpVmeImageINTEL opcodes for
// reference image
// 3. With single reference image - uses one OpVmeImageINTEL opcode for
// reference image
int NumImages =
std::count_if(Args.begin(), Args.end(), [](SPIRVValue *Arg) {
return static_cast<SPIRVInstruction *>(Arg)->getOpCode() ==
OpVmeImageINTEL;
});
if (NumImages) {
SPIRVInstruction *SrcImage = static_cast<SPIRVInstruction *>(Args[0]);
assert(SrcImage &&
"Src image operand not found in avc evaluate instruction");
if (NumImages == 1) {
// Multi reference opcode - remove src image OpVmeImageINTEL opcode
// and replace it with corresponding OpImage and OpSampler arguments
bool IsInterlaced = (Args.size() == 4) ? true : false;
size_t SamplerPos = IsInterlaced ? 3 : 2;
Args.erase(Args.begin(), Args.begin() + 1);
Args.insert(Args.begin(), SrcImage->getOperands()[0]);
Args.insert(Args.begin() + SamplerPos, SrcImage->getOperands()[1]);
} else {
SPIRVInstruction *FwdRefImage =
static_cast<SPIRVInstruction *>(Args[1]);
SPIRVInstruction *BwdRefImage =
static_cast<SPIRVInstruction *>(Args[2]);
assert(FwdRefImage && "invalid avc evaluate instruction");
// Single reference opcode - remove src and ref image OpVmeImageINTEL
// opcodes and replace them with src and ref OpImage opcodes and
// OpSampler
Args.erase(Args.begin(), Args.begin() + NumImages);
// insert source OpImage and OpSampler
auto SrcOps = SrcImage->getOperands();
Args.insert(Args.begin(), SrcOps.begin(), SrcOps.end());
// insert reference OpImage
Args.insert(Args.begin() + 1, FwdRefImage->getOperands()[0]);
if (NumImages == 3) {
// Dual reference opcode - insert second reference OpImage argument
assert(BwdRefImage && "invalid avc evaluate instruction");
Args.insert(Args.begin() + 2, BwdRefImage->getOperands()[0]);
}
}
} else
llvm_unreachable("invalid avc instruction");
}
}

Expand Down Expand Up @@ -2155,6 +2211,9 @@ std::string SPIRVToLLVM::getOCLBuiltinName(SPIRVInstruction *BI) {
}
return Name.str();
}
if (isSubgroupAvcINTELInstructionOpCode(OC))
return OCLSPIRVSubgroupAVCIntelBuiltinMap::rmap(OC);

auto Name = OCLSPIRVBuiltinMap::rmap(OC);

SPIRVType *T = nullptr;
Expand Down
25 changes: 25 additions & 0 deletions lib/SPIRV/SPIRVUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,31 @@ SPIR::TypePrimitiveEnum getOCLTypePrimitiveEnum(StringRef TyName) {
.Case("opencl.clk_event_t", SPIR::PRIMITIVE_CLK_EVENT_T)
.Case("opencl.sampler_t", SPIR::PRIMITIVE_SAMPLER_T)
.Case("struct.ndrange_t", SPIR::PRIMITIVE_NDRANGE_T)
.Case("opencl.intel_sub_group_avc_mce_payload_t",
SPIR::PRIMITIVE_SUB_GROUP_AVC_MCE_PAYLOAD_T)
.Case("opencl.intel_sub_group_avc_ime_payload_t",
SPIR::PRIMITIVE_SUB_GROUP_AVC_IME_PAYLOAD_T)
.Case("opencl.intel_sub_group_avc_ref_payload_t",
SPIR::PRIMITIVE_SUB_GROUP_AVC_REF_PAYLOAD_T)
.Case("opencl.intel_sub_group_avc_sic_payload_t",
SPIR::PRIMITIVE_SUB_GROUP_AVC_SIC_PAYLOAD_T)
.Case("opencl.intel_sub_group_avc_mce_result_t",
SPIR::PRIMITIVE_SUB_GROUP_AVC_MCE_RESULT_T)
.Case("opencl.intel_sub_group_avc_ime_result_t",
SPIR::PRIMITIVE_SUB_GROUP_AVC_IME_RESULT_T)
.Case("opencl.intel_sub_group_avc_ref_result_t",
SPIR::PRIMITIVE_SUB_GROUP_AVC_REF_RESULT_T)
.Case("opencl.intel_sub_group_avc_sic_result_t",
SPIR::PRIMITIVE_SUB_GROUP_AVC_SIC_RESULT_T)
.Case(
"opencl.intel_sub_group_avc_ime_result_single_reference_streamout_t",
SPIR::PRIMITIVE_SUB_GROUP_AVC_IME_SINGLE_REF_STREAMOUT_T)
.Case("opencl.intel_sub_group_avc_ime_result_dual_reference_streamout_t",
SPIR::PRIMITIVE_SUB_GROUP_AVC_IME_DUAL_REF_STREAMOUT_T)
.Case("opencl.intel_sub_group_avc_ime_single_reference_streamin_t",
SPIR::PRIMITIVE_SUB_GROUP_AVC_IME_SINGLE_REF_STREAMIN_T)
.Case("opencl.intel_sub_group_avc_ime_dual_reference_streamin_t",
SPIR::PRIMITIVE_SUB_GROUP_AVC_IME_DUAL_REF_STREAMIN_T)
.Default(SPIR::PRIMITIVE_NONE);
}
/// Translates LLVM type to descriptor for mangler.
Expand Down
16 changes: 16 additions & 0 deletions lib/SPIRV/libSPIRV/SPIRVOpCode.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,22 @@ inline bool isSubgroupAvcINTELTypeOpCode(Op OpCode) {
return OpTypeAvcImePayloadINTEL <= OC && OC <= OpTypeAvcSicResultINTEL;
}

inline bool isSubgroupAvcINTELInstructionOpCode(Op OpCode) {
unsigned OC = OpCode;
return OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL <= OC &&
OC <= OpSubgroupAvcSicGetInterRawSadsINTEL;
}

inline bool isSubgroupAvcINTELEvaluateOpcode(Op OpCode) {
unsigned OC = OpCode;
return (OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL <= OC &&
OC <= OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL) ||
(OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL <= OC &&
OC <= OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL) ||
(OpSubgroupAvcSicEvaluateIpeINTEL <= OC &&
OC <= OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL);
}

inline bool isTypeOpCode(Op OpCode) {
unsigned OC = OpCode;
return (OpTypeVoid <= OC && OC <= OpTypePipe) || OC == OpTypePipeStorage ||
Expand Down
Loading

0 comments on commit 564c8d1

Please sign in to comment.