Skip to content

Commit

Permalink
Implementation of SPV_INTEL_inline_assembly extension
Browse files Browse the repository at this point in the history
Extension is published as intel/llvm#1290

Co-Authored-By: Nikita Rudenko <nikita.rudenko@intel.com>
Co-Authored-By: Anton Sidorenko <anton.sidorenko@intel.com>
Co-Authored-By: Alexey Sachkov <alexey.sachkov@intel.com>
  • Loading branch information
4 people authored and AlexeySotkin committed Mar 19, 2020
1 parent 2c4b84c commit 7a0767f
Show file tree
Hide file tree
Showing 17 changed files with 568 additions and 69 deletions.
1 change: 1 addition & 0 deletions include/LLVMSPIRVExtensions.inc
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ EXT(SPV_INTEL_blocking_pipes)
EXT(SPV_INTEL_function_pointers)
EXT(SPV_INTEL_kernel_attributes)
EXT(SPV_INTEL_io_pipes)
EXT(SPV_INTEL_inline_assembly)
27 changes: 27 additions & 0 deletions lib/SPIRV/SPIRVReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
//===----------------------------------------------------------------------===//
#include "SPIRVReader.h"
#include "OCLUtil.h"
#include "SPIRVAsm.h"
#include "SPIRVBasicBlock.h"
#include "SPIRVExtInst.h"
#include "SPIRVFunction.h"
Expand All @@ -57,6 +58,7 @@
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LegacyPassManager.h"
Expand Down Expand Up @@ -1516,6 +1518,9 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
case OpFunction:
return mapValue(BV, transFunction(static_cast<SPIRVFunction *>(BV)));

case OpAsmINTEL:
return mapValue(BV, transAsmINTEL(static_cast<SPIRVAsmINTEL *>(BV)));

case OpLabel:
return mapValue(BV, BasicBlock::Create(*Context, BV->getName(), F));

Expand Down Expand Up @@ -2112,6 +2117,10 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
return mapValue(BV, Call);
}

case OpAsmCallINTEL:
return mapValue(
BV, transAsmCallINTEL(static_cast<SPIRVAsmCallINTEL *>(BV), F, BB));

case OpFunctionPointerCallINTEL: {
SPIRVFunctionPointerCallINTEL *BC =
static_cast<SPIRVFunctionPointerCallINTEL *>(BV);
Expand Down Expand Up @@ -2380,6 +2389,24 @@ Function *SPIRVToLLVM::transFunction(SPIRVFunction *BF) {
return F;
}

Value *SPIRVToLLVM::transAsmINTEL(SPIRVAsmINTEL *BA) {
assert(BA);
bool HasSideEffect = BA->hasDecorate(DecorationSideEffectsINTEL);
return InlineAsm::get(
cast<FunctionType>(transType(BA->getFunctionType())),
BA->getInstructions(), BA->getConstraints(), HasSideEffect,
/* IsAlignStack */ false, InlineAsm::AsmDialect::AD_ATT);
}

CallInst *SPIRVToLLVM::transAsmCallINTEL(SPIRVAsmCallINTEL *BI, Function *F,
BasicBlock *BB) {
assert(BI);
auto *IA = cast<InlineAsm>(transValue(BI->getAsm(), F, BB));
auto Args = transValue(BM->getValues(BI->getArguments()), F, BB);
return CallInst::Create(cast<FunctionType>(IA->getFunctionType()), IA, Args,
BI->getName(), BB);
}

/// LLVM convert builtin functions is translated to two instructions:
/// y = i32 islessgreater(float x, float z) ->
/// y = i32 ZExt(bool LessOrGreater(float x, float z))
Expand Down
3 changes: 3 additions & 0 deletions lib/SPIRV/SPIRVReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ class SPIRVToLLVM {
Instruction *transSGSizeQueryBI(SPIRVInstruction *BI, BasicBlock *BB);
bool transFPContractMetadata();
bool transKernelMetadata();
Value *transAsmINTEL(SPIRVAsmINTEL *BA);
CallInst *transAsmCallINTEL(SPIRVAsmCallINTEL *BI, Function *F,
BasicBlock *BB);
bool transNonTemporalMetadata(Instruction *I);
bool transSourceLanguage();
bool transSourceExtension();
Expand Down
37 changes: 37 additions & 0 deletions lib/SPIRV/SPIRVWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

#include "SPIRVWriter.h"
#include "LLVMToSPIRVDbgTran.h"
#include "SPIRVAsm.h"
#include "SPIRVBasicBlock.h"
#include "SPIRVEntry.h"
#include "SPIRVEnum.h"
Expand All @@ -60,6 +61,7 @@
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
Expand Down Expand Up @@ -1265,6 +1267,10 @@ SPIRVValue *LLVMToSPIRV::transValueWithoutDecoration(Value *V,
return BV ? mapValue(V, BV) : nullptr;
}

if (InlineAsm *IA = dyn_cast<InlineAsm>(V))
if (BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_inline_assembly))
return mapValue(V, transAsmINTEL(IA));

if (CallInst *CI = dyn_cast<CallInst>(V))
return mapValue(V, transCallInst(CI, BB));

Expand Down Expand Up @@ -1774,6 +1780,11 @@ SPIRVValue *LLVMToSPIRV::transIntrinsicInst(IntrinsicInst *II,
}

SPIRVValue *LLVMToSPIRV::transCallInst(CallInst *CI, SPIRVBasicBlock *BB) {
assert(CI);
if (isa<InlineAsm>(CI->getCalledOperand()) &&
BM->isAllowedToUseExtension(ExtensionID::SPV_INTEL_inline_assembly))
return transAsmCallINTEL(CI, BB);

if (CI->isIndirectCall())
return transIndirectCallInst(CI, BB);
return transDirectCallInst(CI, BB);
Expand Down Expand Up @@ -1827,6 +1838,32 @@ SPIRVValue *LLVMToSPIRV::transIndirectCallInst(CallInst *CI,
BB);
}

SPIRVValue *LLVMToSPIRV::transAsmINTEL(InlineAsm *IA) {
assert(IA);

// TODO: intention here is to provide information about actual target
// but in fact spir-64 is substituted as triple when translator works
// eventually we need to fix it (not urgent)
StringRef TripleStr(M->getTargetTriple());
auto AsmTarget = static_cast<SPIRVAsmTargetINTEL *>(
BM->getOrAddAsmTargetINTEL(TripleStr.str()));
auto SIA = BM->addAsmINTEL(
static_cast<SPIRVTypeFunction *>(transType(IA->getFunctionType())),
AsmTarget, IA->getAsmString(), IA->getConstraintString());
if (IA->hasSideEffects())
SIA->addDecorate(DecorationSideEffectsINTEL);
return SIA;
}

SPIRVValue *LLVMToSPIRV::transAsmCallINTEL(CallInst *CI, SPIRVBasicBlock *BB) {
assert(CI);
auto IA = cast<InlineAsm>(CI->getCalledOperand());
return BM->addAsmCallINTELInst(
static_cast<SPIRVAsmINTEL *>(transValue(IA, BB, false)),
transArguments(CI, BB, SPIRVEntry::createUnique(OpAsmCallINTEL).get()),
BB);
}

bool LLVMToSPIRV::transAddressingMode() {
Triple TargetTriple(M->getTargetTriple());

Expand Down
2 changes: 2 additions & 0 deletions lib/SPIRV/SPIRVWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ class LLVMToSPIRV : public ModulePass {
SPIRVValue *transCallInst(CallInst *Call, SPIRVBasicBlock *BB);
SPIRVValue *transDirectCallInst(CallInst *Call, SPIRVBasicBlock *BB);
SPIRVValue *transIndirectCallInst(CallInst *Call, SPIRVBasicBlock *BB);
SPIRVValue *transAsmINTEL(InlineAsm *Asm);
SPIRVValue *transAsmCallINTEL(CallInst *Call, SPIRVBasicBlock *BB);
bool transDecoration(Value *V, SPIRVValue *BV);
SPIRVWord transFunctionControlMask(Function *);
SPIRVFunction *transFunctionDecl(Function *F);
Expand Down
142 changes: 142 additions & 0 deletions lib/SPIRV/libSPIRV/SPIRVAsm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
//===- SPIRVAsm.h - --*- C++ -*-===//
//
// The LLVM/SPIRV Translator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
///
/// This file defines the inline assembler entries defined in SPIRV spec with op
/// codes.
///
//===----------------------------------------------------------------------===//

#ifndef SPIRV_LIBSPIRV_SPIRVASM_H
#define SPIRV_LIBSPIRV_SPIRVASM_H

#include "SPIRVEntry.h"
#include "SPIRVInstruction.h"
#include "SPIRVValue.h"

namespace SPIRV {

class SPIRVAsmTargetINTEL : public SPIRVEntry {
public:
static const SPIRVWord FixedWC = 2;
static const Op OC = OpAsmTargetINTEL;
// Complete constructor
SPIRVAsmTargetINTEL(SPIRVModule *M, SPIRVId TheId,
const std::string &TheTarget)
: SPIRVEntry(M, FixedWC + getSizeInWords(TheTarget), OC, TheId),
Target(TheTarget) {
validate();
}
// Incomplete constructor
SPIRVAsmTargetINTEL() : SPIRVEntry(OC) {}
SPIRVCapVec getRequiredCapability() const override {
return getVec(CapabilityAsmINTEL);
}
SPIRVExtSet getRequiredExtensions() const override {
return getSet(ExtensionID::SPV_INTEL_inline_assembly);
}
const std::string &getTarget() const { return Target; }

protected:
void validate() const override {
SPIRVEntry::validate();
assert(WordCount > FixedWC);
assert(OpCode == OC);
}
_SPIRV_DEF_ENCDEC2(Id, Target)
std::string Target;
};

class SPIRVAsmINTEL : public SPIRVValue {
public:
static const SPIRVWord FixedWC = 5;
static const Op OC = OpAsmINTEL;
// Complete constructor
SPIRVAsmINTEL(SPIRVModule *M, SPIRVTypeFunction *TheFunctionType,
SPIRVId TheId, SPIRVAsmTargetINTEL *TheTarget,
const std::string &TheInstructions,
const std::string &TheConstraints)
: SPIRVValue(M,
FixedWC + getSizeInWords(TheInstructions) +
getSizeInWords(TheConstraints),
OC, TheFunctionType->getReturnType(), TheId),
Target(TheTarget), FunctionType(TheFunctionType),
Instructions(TheInstructions), Constraints(TheConstraints) {
validate();
}
// Incomplete constructor
SPIRVAsmINTEL() : SPIRVValue(OC) {}
SPIRVCapVec getRequiredCapability() const override {
return getVec(CapabilityAsmINTEL);
}
SPIRVExtSet getRequiredExtensions() const override {
return getSet(ExtensionID::SPV_INTEL_inline_assembly);
}
const std::string &getInstructions() const { return Instructions; }
const std::string &getConstraints() const { return Constraints; }
SPIRVTypeFunction *getFunctionType() const { return FunctionType; }

protected:
_SPIRV_DEF_ENCDEC6(Type, Id, FunctionType, Target, Instructions, Constraints)
void validate() const override {
SPIRVValue::validate();
assert(WordCount > FixedWC);
assert(OpCode == OC);
}
SPIRVAsmTargetINTEL *Target;
SPIRVTypeFunction *FunctionType;
std::string Instructions;
std::string Constraints;
};

class SPIRVAsmCallINTEL : public SPIRVInstruction {
public:
static const SPIRVWord FixedWC = 4;
static const Op OC = OpAsmCallINTEL;
// Complete constructor
SPIRVAsmCallINTEL(SPIRVId TheId, SPIRVAsmINTEL *TheAsm,
const std::vector<SPIRVWord> &TheArgs,
SPIRVBasicBlock *TheBB)
: SPIRVInstruction(FixedWC + TheArgs.size(), OC, TheAsm->getType(), TheId,
TheBB),
Asm(TheAsm), Args(TheArgs) {
validate();
}
// Incomplete constructor
SPIRVAsmCallINTEL() : SPIRVInstruction(OC) {}
SPIRVCapVec getRequiredCapability() const override {
return getVec(CapabilityAsmINTEL);
}
SPIRVExtSet getRequiredExtensions() const override {
return getSet(ExtensionID::SPV_INTEL_inline_assembly);
}
bool isOperandLiteral(unsigned int Index) const override { return false; }
void setWordCount(SPIRVWord TheWordCount) override {
SPIRVEntry::setWordCount(TheWordCount);
Args.resize(TheWordCount - FixedWC);
}
const std::vector<SPIRVWord> &getArguments() const { return Args; }

SPIRVAsmINTEL *getAsm() const { return Asm; }

protected:
_SPIRV_DEF_ENCDEC4(Type, Id, Asm, Args)
void validate() const override {
SPIRVInstruction::validate();
assert(WordCount >= FixedWC);
assert(OpCode == OC);
assert(getBasicBlock() && "Invalid BB");
assert(getBasicBlock()->getModule() == Asm->getModule());
}
SPIRVAsmINTEL *Asm;
std::vector<SPIRVWord> Args;
};

} // namespace SPIRV
#endif // SPIRV_LIBSPIRV_SPIRVASM_H
1 change: 1 addition & 0 deletions lib/SPIRV/libSPIRV/SPIRVEntry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
//===----------------------------------------------------------------------===//

#include "SPIRVEntry.h"
#include "SPIRVAsm.h"
#include "SPIRVBasicBlock.h"
#include "SPIRVDebug.h"
#include "SPIRVDecorate.h"
Expand Down
1 change: 1 addition & 0 deletions lib/SPIRV/libSPIRV/SPIRVEnum.h
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ template <> inline void SPIRVMap<Decoration, SPIRVCapVec>::init() {
ADD_VEC_INIT(DecorationReferencedIndirectlyINTEL,
{CapabilityIndirectReferencesINTEL});
ADD_VEC_INIT(DecorationIOPipeStorageINTEL, {CapabilityIOPipeINTEL});
ADD_VEC_INIT(DecorationSideEffectsINTEL, {CapabilityAsmINTEL});
}

template <> inline void SPIRVMap<BuiltIn, SPIRVCapVec>::init() {
Expand Down
3 changes: 3 additions & 0 deletions lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,9 @@ inline bool isValid(spv::Op V) {
case OpSubgroupImageBlockWriteINTEL:
case OpSubgroupImageMediaBlockReadINTEL:
case OpSubgroupImageMediaBlockWriteINTEL:
case OpAsmTargetINTEL:
case OpAsmINTEL:
case OpAsmCallINTEL:
case OpVmeImageINTEL:
case OpTypeVmeImageINTEL:
case OpTypeAvcImePayloadINTEL:
Expand Down
Loading

0 comments on commit 7a0767f

Please sign in to comment.