Skip to content

Commit e802518

Browse files
committed
[SPIR-V] Enable SPIR-V format emitter in clang.
Signed-off-by: Vladimir Lazarev <[email protected]>
1 parent fa1ff0a commit e802518

File tree

382 files changed

+62334
-0
lines changed

Some content is hidden

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

382 files changed

+62334
-0
lines changed

clang/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,9 +375,12 @@ include(AddClang)
375375

376376
set(CMAKE_INCLUDE_CURRENT_DIR ON)
377377

378+
set(LLVM_SPIRV_INCLUDE_DIRS "${LLVM_MAIN_SRC_DIR}/../llvm-spirv/include")
379+
378380
include_directories(BEFORE
379381
${CMAKE_CURRENT_BINARY_DIR}/include
380382
${CMAKE_CURRENT_SOURCE_DIR}/include
383+
${LLVM_SPIRV_INCLUDE_DIRS}
381384
)
382385

383386
if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)

clang/include/clang/CodeGen/BackendUtil.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ namespace clang {
3131
enum BackendAction {
3232
Backend_EmitAssembly, ///< Emit native assembly files
3333
Backend_EmitBC, ///< Emit LLVM bitcode files
34+
Backend_EmitSPIRV, ///< Emit SPIR-V bitcode files
3435
Backend_EmitLL, ///< Emit human-readable LLVM assembly
3536
Backend_EmitNothing, ///< Don't emit anything (benchmarking mode)
3637
Backend_EmitMCNull, ///< Run CodeGen, but don't emit anything

clang/include/clang/CodeGen/CodeGenAction.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@ class EmitBCAction : public CodeGenAction {
9393
EmitBCAction(llvm::LLVMContext *_VMContext = nullptr);
9494
};
9595

96+
class EmitSPIRVAction : public CodeGenAction {
97+
virtual void anchor();
98+
public:
99+
EmitSPIRVAction(llvm::LLVMContext *_VMContext = nullptr);
100+
};
101+
96102
class EmitLLVMAction : public CodeGenAction {
97103
virtual void anchor();
98104
public:

clang/include/clang/Driver/CC1Options.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,8 @@ def emit_llvm_bc : Flag<["-"], "emit-llvm-bc">,
572572
HelpText<"Build ASTs then convert to LLVM, emit .bc file">;
573573
def emit_llvm_only : Flag<["-"], "emit-llvm-only">,
574574
HelpText<"Build ASTs and convert to LLVM, discarding output">;
575+
def emit_spirv : Flag<["-"], "emit-spirv">,
576+
HelpText<"Build ASTs then convert to LLVM then convert to SPIR-V, emit .spv file">;
575577
def emit_codegen_only : Flag<["-"], "emit-codegen-only">,
576578
HelpText<"Generate machine code, but discard output">;
577579
def emit_obj : Flag<["-"], "emit-obj">,

clang/include/clang/Frontend/FrontendOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ enum ActionKind {
5858
/// Emit a .bc file.
5959
EmitBC,
6060

61+
/// Emit a .spv file.
62+
EmitSPIRV,
63+
6164
/// Translate input source into HTML.
6265
EmitHTML,
6366

clang/lib/CodeGen/BackendUtil.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
#include "llvm/Transforms/Utils.h"
6262
#include "llvm/Transforms/Utils/NameAnonGlobals.h"
6363
#include "llvm/Transforms/Utils/SymbolRewriter.h"
64+
#include "LLVMSPIRVLib.h"
6465
#include <memory>
6566
using namespace clang;
6667
using namespace llvm;
@@ -777,6 +778,7 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
777778

778779
bool UsesCodeGen = (Action != Backend_EmitNothing &&
779780
Action != Backend_EmitBC &&
781+
Action != Backend_EmitSPIRV &&
780782
Action != Backend_EmitLL);
781783
CreateTargetMachine(UsesCodeGen);
782784

@@ -831,6 +833,13 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
831833
}
832834
break;
833835

836+
837+
case Backend_EmitSPIRV:
838+
839+
PerModulePasses.add(createSPIRVWriterPass(*OS));
840+
841+
break;
842+
834843
case Backend_EmitLL:
835844
PerModulePasses.add(
836845
createPrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists));
@@ -1066,6 +1075,10 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
10661075
}
10671076
break;
10681077

1078+
case Backend_EmitSPIRV:
1079+
CodeGenPasses.add(createSPIRVWriterPass(*OS));
1080+
break;
1081+
10691082
case Backend_EmitLL:
10701083
MPM.addPass(PrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists));
10711084
break;

clang/lib/CodeGen/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ set(LLVM_LINK_COMPONENTS
2121
Support
2222
Target
2323
TransformUtils
24+
SPIRVLib
2425
)
2526

2627
# In a standard Clang+LLVM build, we need to generate intrinsics before

clang/lib/CodeGen/CodeGenAction.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -837,6 +837,8 @@ GetOutputStream(CompilerInstance &CI, StringRef InFile, BackendAction Action) {
837837
return CI.createDefaultOutputFile(false, InFile, "ll");
838838
case Backend_EmitBC:
839839
return CI.createDefaultOutputFile(true, InFile, "bc");
840+
case Backend_EmitSPIRV:
841+
return CI.createDefaultOutputFile(true, InFile, "spv");
840842
case Backend_EmitNothing:
841843
return nullptr;
842844
case Backend_EmitMCNull:
@@ -1058,6 +1060,10 @@ void EmitBCAction::anchor() { }
10581060
EmitBCAction::EmitBCAction(llvm::LLVMContext *_VMContext)
10591061
: CodeGenAction(Backend_EmitBC, _VMContext) {}
10601062

1063+
void EmitSPIRVAction::anchor() { }
1064+
EmitSPIRVAction::EmitSPIRVAction(llvm::LLVMContext *_VMContext)
1065+
: CodeGenAction(Backend_EmitSPIRV, _VMContext) {}
1066+
10611067
void EmitLLVMAction::anchor() { }
10621068
EmitLLVMAction::EmitLLVMAction(llvm::LLVMContext *_VMContext)
10631069
: CodeGenAction(Backend_EmitLL, _VMContext) {}

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ static unsigned getOptimizationLevel(ArgList &Args, InputKind IK,
124124
if (IK.getLanguage() == InputKind::OpenCL && !Args.hasArg(OPT_cl_opt_disable))
125125
DefaultOpt = llvm::CodeGenOpt::Default;
126126

127+
if (Args.hasArg(OPT_emit_spirv))
128+
return 0; // LLVM-SPIRV translator expects not optimized IR
129+
127130
if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
128131
if (A->getOption().matches(options::OPT_O0))
129132
return llvm::CodeGenOpt::None;
@@ -1183,6 +1186,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
11831186
}
11841187
}
11851188

1189+
Opts.EmitOpenCLArgMetadata |= Args.hasArg(OPT_emit_spirv);
1190+
11861191
if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_EQ)) {
11871192
StringRef Val = A->getValue();
11881193
if (Val == "ieee")
@@ -1606,6 +1611,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
16061611
Opts.ProgramAction = frontend::EmitAssembly; break;
16071612
case OPT_emit_llvm_bc:
16081613
Opts.ProgramAction = frontend::EmitBC; break;
1614+
case OPT_emit_spirv:
1615+
Opts.ProgramAction = frontend::EmitSPIRV; break;
16091616
case OPT_emit_html:
16101617
Opts.ProgramAction = frontend::EmitHTML; break;
16111618
case OPT_emit_llvm:
@@ -3033,6 +3040,7 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
30333040
case frontend::ASTView:
30343041
case frontend::EmitAssembly:
30353042
case frontend::EmitBC:
3043+
case frontend::EmitSPIRV:
30363044
case frontend::EmitHTML:
30373045
case frontend::EmitLLVM:
30383046
case frontend::EmitLLVMOnly:

clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
5252
case DumpTokens: return llvm::make_unique<DumpTokensAction>();
5353
case EmitAssembly: return llvm::make_unique<EmitAssemblyAction>();
5454
case EmitBC: return llvm::make_unique<EmitBCAction>();
55+
case EmitSPIRV: return llvm::make_unique<EmitSPIRVAction>();
5556
case EmitHTML: return llvm::make_unique<HTMLPrintAction>();
5657
case EmitLLVM: return llvm::make_unique<EmitLLVMAction>();
5758
case EmitLLVMOnly: return llvm::make_unique<EmitLLVMOnlyAction>();
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Make sure that OpenCL builtins declared in opencl.h are translated
2+
// to corresponding SPIR-V instructions, not a function calls.
3+
// Builtins must be declared as overloadable, so Clang mangles their names,
4+
// and LLVM-SPIRV translator can recognize them.
5+
6+
// RUN: %clang_cc1 %s -emit-spirv -triple spir-unknown-unknown -O0 -cl-std=CL2.0 -include opencl-c.h -o %t.spv
7+
// RUN: llvm-spirv -to-text %t.spv -o - | FileCheck %s
8+
9+
// CHECK: CreateUserEvent
10+
// CHECK: IsValidEvent
11+
// CHECK-NOT: FunctionCall
12+
13+
bool test() {
14+
clk_event_t e = create_user_event();
15+
return is_valid_event(e);
16+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %clang_cc1 %s -triple spir-unknown-unknown -O0 -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-LLVM
2+
// RUN: %clang_cc1 %s -triple spir-unknown-unknown -O0 -emit-spirv -o %t.spv
3+
// RUN: llvm-spirv %t.spv -to-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV
4+
5+
// CHECK-LLVM: @__const.test.arr = private unnamed_addr addrspace(2) constant [3 x i32] [i32 1, i32 2, i32 3], align 4
6+
7+
// CHECK-SPIRV-DAG: TypeInt [[i32:[0-9]+]] 32 0
8+
// CHECK-SPIRV-DAG: TypeInt [[i8:[0-9]+]] 8 0
9+
// CHECK-SPIRV-DAG: Constant [[i32]] [[one:[0-9]+]] 1
10+
// CHECK-SPIRV-DAG: Constant [[i32]] [[two:[0-9]+]] 2
11+
// CHECK-SPIRV-DAG: Constant [[i32]] [[three:[0-9]+]] 3
12+
// CHECK-SPIRV-DAG: Constant [[i32]] [[twelve:[0-9]+]] 12
13+
// CHECK-SPIRV-DAG: TypeArray [[i32x3:[0-9]+]] [[i32]] [[three]]
14+
// CHECK-SPIRV-DAG: TypePointer [[i32x3_ptr:[0-9]+]] 7 [[i32x3]]
15+
// CHECK-SPIRV-DAG: TypePointer [[const_i32x3_ptr:[0-9]+]] 0 [[i32x3]]
16+
// CHECK-SPIRV-DAG: TypePointer [[i8_ptr:[0-9]+]] 7 [[i8]]
17+
// CHECK-SPIRV-DAG: TypePointer [[const_i8_ptr:[0-9]+]] 0 [[i8]]
18+
// CHECK-SPIRV: ConstantComposite [[i32x3]] [[test_arr_init:[0-9]+]] [[one]] [[two]] [[three]]
19+
// CHECK-SPIRV: Variable [[const_i32x3_ptr]] [[test_arr:[0-9]+]] 0 [[test_arr_init]]
20+
// CHECK-SPIRV: Variable [[const_i32x3_ptr]] [[test_arr2:[0-9]+]] 0 [[test_arr_init]]
21+
22+
void test() {
23+
__private int arr[] = {1,2,3};
24+
__private const int arr2[] = {1,2,3};
25+
// CHECK-LLVM: %arr = alloca [3 x i32], align 4
26+
// CHECK-LLVM: %[[arr_i8_ptr:[0-9]+]] = bitcast [3 x i32]* %arr to i8*
27+
// CHECK-LLVM: call void @llvm.memcpy.p0i8.p2i8.i32(i8* align 4 %0, i8 addrspace(2)* align 4 bitcast ([3 x i32] addrspace(2)* @__const.test.arr to i8 addrspace(2)*), i32 12, i1 false)
28+
29+
// CHECK-SPIRV: Variable [[i32x3_ptr]] [[arr:[0-9]+]] 7
30+
// CHECK-SPIRV: Variable [[i32x3_ptr]] [[arr2:[0-9]+]] 7
31+
32+
// CHECK-SPIRV: Bitcast [[i8_ptr]] [[arr_i8_ptr:[0-9]+]] [[arr]]
33+
// CHECK-SPIRV: Bitcast [[const_i8_ptr]] [[test_arr_const_i8_ptr:[0-9]+]] [[test_arr]]
34+
// CHECK-SPIRV: CopyMemorySized [[arr_i8_ptr]] [[test_arr_const_i8_ptr]] [[twelve]] 2 4
35+
36+
// CHECK-SPIRV: Bitcast [[i8_ptr]] [[arr2_i8_ptr:[0-9]+]] [[arr2]]
37+
// CHECK-SPIRV: Bitcast [[const_i8_ptr]] [[test_arr2_const_i8_ptr:[0-9]+]] [[test_arr2]]
38+
// CHECK-SPIRV: CopyMemorySized [[arr2_i8_ptr]] [[test_arr2_const_i8_ptr]] [[twelve]] 2 4
39+
}

llvm-spirv/.clang-format

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
BasedOnStyle: LLVM
2+

llvm-spirv/.clang-tidy

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Checks: '-*,clang-diagnostic-*,llvm-*,misc-*,-misc-unused-parameters,readability-identifier-naming,-llvm-header-guard'
2+
CheckOptions:
3+
- key: readability-identifier-naming.ClassCase
4+
value: CamelCase
5+
- key: readability-identifier-naming.EnumCase
6+
value: CamelCase
7+
- key: readability-identifier-naming.FunctionCase
8+
value: camelBack
9+
- key: readability-identifier-naming.MemberCase
10+
value: CamelCase
11+
- key: readability-identifier-naming.ParameterCase
12+
value: CamelCase
13+
- key: readability-identifier-naming.UnionCase
14+
value: CamelCase
15+
- key: readability-identifier-naming.VariableCase
16+
value: CamelCase
17+
- key: llvm-namespace-comment.ShortNamespaceLines
18+
value: '25'
19+

llvm-spirv/.gitignore

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#==============================================================================#
2+
# This file specifies intentionally untracked files that git should ignore.
3+
# See: http://www.kernel.org/pub/software/scm/git/docs/gitignore.html
4+
#
5+
# This file is intentionally different from the output of `git svn show-ignore`,
6+
# as most of those are useless.
7+
#==============================================================================#
8+
9+
#==============================================================================#
10+
# File extensions to be ignored anywhere in the tree.
11+
#==============================================================================#
12+
# Temp files created by most text editors.
13+
*~
14+
# Merge files created by git.
15+
*.orig
16+
# Byte compiled python modules.
17+
*.pyc
18+
# vim swap files
19+
.*.swp
20+
.sw?
21+
#OS X specific files.
22+
.DS_store
23+
24+
#==============================================================================#
25+
# Explicit files to ignore (only matches one).
26+
#==============================================================================#
27+
# Various tag programs
28+
/tags
29+
/TAGS
30+
/GPATH
31+
/GRTAGS
32+
/GSYMS
33+
/GTAGS
34+
.gitusers
35+
autom4te.cache
36+
cscope.files
37+
cscope.out
38+
autoconf/aclocal.m4
39+
autoconf/autom4te.cache
40+
compile_commands.json
41+
42+
#==============================================================================#
43+
# Directories to ignore (do not add trailing '/'s, they skip symlinks).
44+
#==============================================================================#
45+
# External projects that are tracked independently.
46+
projects/*
47+
!projects/CMakeLists.txt
48+
!projects/Makefile
49+
# Clang, which is tracked independently.
50+
tools/clang
51+
# LLDB, which is tracked independently.
52+
tools/lldb
53+
# lld, which is tracked independently.
54+
tools/lld
55+
# llgo, which is tracked independently.
56+
tools/llgo
57+
# Polly, which is tracked independently.
58+
tools/polly
59+
# Sphinx build tree, if building in-source dir.
60+
docs/_build
61+
62+
#==============================================================================#
63+
# Files created in tree by the Go bindings.
64+
#==============================================================================#
65+
bindings/go/llvm/llvm_config.go
66+
bindings/go/llvm/workdir

0 commit comments

Comments
 (0)