Skip to content

Commit 1dbc09c

Browse files
author
Artem Gindinson
authored
Accept intrinsic namings into -spirv-allow-unknown-intrinsics (#912)
Previously, enabling the option would let all intrinsics through the translator. From now on, the option can be configured so that only specific intrinsic calls with the given prefix are allowed, while those not matching the prefix will result in an error as if no option was given. The allowed intrinsic prefixes are fed into the option as a comma-separated list, akin to `--spirv-ext`. The list can also be left unspecified, which, as before, will accept all intrinsic calls into SPIR-V. One of the relevant use cases involves llvm.genx.* intrinsics, which stem from SYCL ESIMD code, but can also mix with common LLVM intrinsics that stem from regular SYCL code. It would be desirable to allow ESIMD-specific intrinsics, but still error out on other unknown ones, To better highlight this case, all ESIMD-specific tests have been switched to passing an explicit prefix to the CLI option.
1 parent b89b25f commit 1dbc09c

File tree

12 files changed

+141
-25
lines changed

12 files changed

+141
-25
lines changed

include/LLVMSPIRVOpts.h

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,19 @@
3939
#ifndef SPIRV_LLVMSPIRVOPTS_H
4040
#define SPIRV_LLVMSPIRVOPTS_H
4141

42+
#include <llvm/ADT/Optional.h>
43+
#include <llvm/ADT/SmallVector.h>
44+
#include <llvm/ADT/StringRef.h>
45+
4246
#include <cassert>
4347
#include <cstdint>
4448
#include <map>
4549
#include <unordered_map>
4650

51+
namespace llvm {
52+
class IntrinsicInst;
53+
} // namespace llvm
54+
4755
namespace SPIRV {
4856

4957
enum class VersionNumber : uint32_t {
@@ -77,6 +85,7 @@ enum class DebugInfoEIS : uint32_t { SPIRV_Debug, OpenCL_DebugInfo_100 };
7785
class TranslatorOpts {
7886
public:
7987
using ExtensionsStatusMap = std::map<ExtensionID, bool>;
88+
using ArgList = llvm::SmallVector<llvm::StringRef, 4>;
8089

8190
TranslatorOpts() = default;
8291

@@ -139,14 +148,9 @@ class TranslatorOpts {
139148

140149
FPContractMode getFPContractMode() const { return FPCMode; }
141150

142-
bool isSPIRVAllowUnknownIntrinsicsEnabled() const noexcept {
143-
return SPIRVAllowUnknownIntrinsics;
144-
}
145-
146-
void
147-
setSPIRVAllowUnknownIntrinsicsEnabled(bool AllowUnknownIntrinsics) noexcept {
148-
SPIRVAllowUnknownIntrinsics = AllowUnknownIntrinsics;
149-
}
151+
bool isUnknownIntrinsicAllowed(llvm::IntrinsicInst *II) const noexcept;
152+
bool isSPIRVAllowUnknownIntrinsicsEnabled() const noexcept;
153+
void setSPIRVAllowUnknownIntrinsics(ArgList IntrinsicPrefixList) noexcept;
150154

151155
bool allowExtraDIExpressions() const noexcept {
152156
return AllowExtraDIExpressions;
@@ -193,7 +197,7 @@ class TranslatorOpts {
193197

194198
// Unknown LLVM intrinsics will be translated as external function calls in
195199
// SPIR-V
196-
bool SPIRVAllowUnknownIntrinsics = false;
200+
llvm::Optional<ArgList> SPIRVAllowUnknownIntrinsics{};
197201

198202
// Enable support for extra DIExpression opcodes not listed in the SPIR-V
199203
// DebugInfo specification.

lib/SPIRV/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
add_llvm_library(LLVMSPIRVLib
2+
LLVMSPIRVOpts.cpp
23
LLVMToSPIRVDbgTran.cpp
34
Mangler/FunctionDescriptor.cpp
45
Mangler/Mangler.cpp

lib/SPIRV/LLVMSPIRVOpts.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
//===- LLVMSPIRVOpts.cpp - Defines LLVM/SPIR-V options ----------*- C++ -*-===//
2+
//
3+
// The LLVM/SPIR-V Translator
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
// Copyright (c) 2021 Intel Corporation. All rights reserved.
9+
//
10+
// Permission is hereby granted, free of charge, to any person obtaining a
11+
// copy of this software and associated documentation files (the "Software"),
12+
// to deal with the Software without restriction, including without limitation
13+
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
14+
// and/or sell copies of the Software, and to permit persons to whom the
15+
// Software is furnished to do so, subject to the following conditions:
16+
//
17+
// Redistributions of source code must retain the above copyright notice,
18+
// this list of conditions and the following disclaimers.
19+
// Redistributions in binary form must reproduce the above copyright notice,
20+
// this list of conditions and the following disclaimers in the documentation
21+
// and/or other materials provided with the distribution.
22+
// Neither the names of Advanced Micro Devices, Inc., nor the names of its
23+
// contributors may be used to endorse or promote products derived from this
24+
// Software without specific prior written permission.
25+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28+
// CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
31+
// THE SOFTWARE.
32+
//
33+
//===----------------------------------------------------------------------===//
34+
/// \file
35+
///
36+
/// This file provides definitions for LLVM/SPIR-V Translator's CLI
37+
/// functionality.
38+
///
39+
//===----------------------------------------------------------------------===//
40+
41+
#include "LLVMSPIRVOpts.h"
42+
43+
#include <llvm/ADT/Optional.h>
44+
#include <llvm/ADT/SmallVector.h>
45+
#include <llvm/ADT/StringRef.h>
46+
#include <llvm/IR/IntrinsicInst.h>
47+
48+
using namespace llvm;
49+
using namespace SPIRV;
50+
51+
bool TranslatorOpts::isUnknownIntrinsicAllowed(IntrinsicInst *II) const
52+
noexcept {
53+
if (!SPIRVAllowUnknownIntrinsics.hasValue())
54+
return false;
55+
const auto &IntrinsicPrefixList = SPIRVAllowUnknownIntrinsics.getValue();
56+
StringRef IntrinsicName = II->getCalledOperand()->getName();
57+
for (const auto Prefix : IntrinsicPrefixList) {
58+
if (IntrinsicName.startswith(Prefix)) // Also true if `Prefix` is empty
59+
return true;
60+
}
61+
return false;
62+
}
63+
64+
bool TranslatorOpts::isSPIRVAllowUnknownIntrinsicsEnabled() const noexcept {
65+
return SPIRVAllowUnknownIntrinsics.hasValue();
66+
}
67+
68+
void TranslatorOpts::setSPIRVAllowUnknownIntrinsics(
69+
TranslatorOpts::ArgList IntrinsicPrefixList) noexcept {
70+
SPIRVAllowUnknownIntrinsics = IntrinsicPrefixList;
71+
}

lib/SPIRV/SPIRVWriter.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2716,7 +2716,7 @@ SPIRVValue *LLVMToSPIRV::transIntrinsicInst(IntrinsicInst *II,
27162716
return BM->addInstTemplate(OpSaveMemoryINTEL, BB, Ty);
27172717
}
27182718
BM->getErrorLog().checkError(
2719-
BM->isSPIRVAllowUnknownIntrinsicsEnabled(), SPIRVEC_InvalidFunctionCall,
2719+
BM->isUnknownIntrinsicAllowed(II), SPIRVEC_InvalidFunctionCall,
27202720
toString(II) + "\nTranslation of llvm.stacksave intrinsic requires "
27212721
"SPV_INTEL_variable_length_array extension or "
27222722
"-spirv-allow-unknown-intrinsics option.");
@@ -2730,7 +2730,7 @@ SPIRVValue *LLVMToSPIRV::transIntrinsicInst(IntrinsicInst *II,
27302730
nullptr);
27312731
}
27322732
BM->getErrorLog().checkError(
2733-
BM->isSPIRVAllowUnknownIntrinsicsEnabled(), SPIRVEC_InvalidFunctionCall,
2733+
BM->isUnknownIntrinsicAllowed(II), SPIRVEC_InvalidFunctionCall,
27342734
toString(II) + "\nTranslation of llvm.restore intrinsic requires "
27352735
"SPV_INTEL_variable_length_array extension or "
27362736
"-spirv-allow-unknown-intrinsics option.");
@@ -2753,7 +2753,7 @@ SPIRVValue *LLVMToSPIRV::transIntrinsicInst(IntrinsicInst *II,
27532753
return transValue(ConstantInt::getFalse(II->getType()), BB, false);
27542754
}
27552755
default:
2756-
if (BM->isSPIRVAllowUnknownIntrinsicsEnabled())
2756+
if (BM->isUnknownIntrinsicAllowed(II))
27572757
return BM->addCallInst(
27582758
transFunctionDecl(II->getCalledFunction()),
27592759
transArguments(II, BB,

lib/SPIRV/libSPIRV/SPIRVModule.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,10 @@ class SPIRVModule {
486486
return TranslationOpts.getFPContractMode();
487487
}
488488

489+
bool isUnknownIntrinsicAllowed(llvm::IntrinsicInst *II) const noexcept {
490+
return TranslationOpts.isUnknownIntrinsicAllowed(II);
491+
}
492+
489493
bool isSPIRVAllowUnknownIntrinsicsEnabled() const noexcept {
490494
return TranslationOpts.isSPIRVAllowUnknownIntrinsicsEnabled();
491495
}

test/transcoding/AllowIntrinsics.ll

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,52 @@
1-
; The test checks command-line option for the translator
2-
; which will allow to represent unknown llvm intrinsics as external function call in SPIR-V.
1+
; The test checks command-line option for the translator which allows to represent
2+
; unknown intrinsics as external function calls in SPIR-V.
33
; RUN: llvm-as %s -o %t.bc
44
; RUN: llvm-spirv -spirv-allow-unknown-intrinsics %t.bc -o %t.spv
55
; RUN: spirv-val %t.spv
66
; RUN: llvm-spirv %t.spv -to-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV
77
; RUN: llvm-spirv -r %t.spv -o %t.rev.bc
88
; RUN: llvm-dis < %t.rev.bc | FileCheck %s --check-prefix=CHECK-LLVM
99

10+
; Check that passing a prefix list into the option works/fails as expected.
11+
;
12+
; Positive cases:
13+
; RUN: llvm-spirv -spirv-allow-unknown-intrinsics=llvm. %t.bc
14+
; RUN: llvm-spirv -spirv-allow-unknown-intrinsics=llvm.,random.prefix %t.bc
15+
;
16+
; Positive cases (identical to "no setting at all"):
17+
; RUN: llvm-spirv -spirv-allow-unknown-intrinsics= %t.bc
18+
; RUN: llvm-spirv -spirv-allow-unknown-intrinsics="" %t.bc
19+
; RUN: llvm-spirv -spirv-allow-unknown-intrinsics=random.prefix, %t.bc
20+
;
21+
; Negative cases:
22+
; RUN: not llvm-spirv -spirv-allow-unknown-intrinsics=llvm.some.custom %t.bc 2>&1 \
23+
; RUN: | FileCheck %s --check-prefix=CHECK-FAIL-READCYCLE
24+
; CHECK-FAIL-READCYCLE: InvalidFunctionCall: Unexpected llvm intrinsic:
25+
; CHECK-FAIL-READCYCLE-NEXT: llvm.readcyclecounter
26+
; RUN: not llvm-spirv -spirv-allow-unknown-intrinsics=llvm.readcyclecounter %t.bc 2>&1 \
27+
; RUN: | FileCheck %s --check-prefix=CHECK-FAIL-CUSTOM
28+
; CHECK-FAIL-CUSTOM: InvalidFunctionCall: Unexpected llvm intrinsic:
29+
; CHECK-FAIL-CUSTOM-NEXT: llvm.some.custom.intrinsic
30+
; RUN: not llvm-spirv -spirv-allow-unknown-intrinsics=non.llvm.1,non,llvm.2 %t.bc
31+
1032
; Note: This test used to call llvm.fma, but that is now traslated correctly.
1133

1234
; CHECK-LLVM: declare i64 @llvm.readcyclecounter()
1335
; CHECK-SPIRV: LinkageAttributes "llvm.readcyclecounter" Import
36+
; CHECK-LLVM: declare i64 @llvm.some.custom.intrinsic()
1437
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64"
1538
target triple = "spir64"
1639

1740
; Function Attrs: nounwind
1841
define spir_func void @foo() #0 {
1942
entry:
2043
%0 = call i64 @llvm.readcyclecounter()
44+
%1 = call i64 @llvm.some.custom.intrinsic()
2145
ret void
2246
}
2347

2448
declare i64 @llvm.readcyclecounter()
49+
declare i64 @llvm.some.custom.intrinsic()
2550

2651
attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
2752

test/transcoding/SPV_INTEL_vector_compute/decoration_byte_offset.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; RUN: llvm-as %s -o %t.bc
2-
; RUN: llvm-spirv %t.bc -o %t.spv --spirv-ext=+SPV_INTEL_vector_compute --spirv-allow-unknown-intrinsics
2+
; RUN: llvm-spirv %t.bc -o %t.spv --spirv-ext=+SPV_INTEL_vector_compute --spirv-allow-unknown-intrinsics=llvm.genx
33
; RUN: llvm-spirv %t.spv -o %t.spt --to-text
44
; RUN: llvm-spirv -r %t.spv -o %t.bc
55
; RUN: llvm-dis %t.bc -o %t.ll

test/transcoding/SPV_INTEL_vector_compute/decoration_simt_call.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; RUN: llvm-as %s -o %t.bc
2-
; RUN: llvm-spirv %t.bc -o %t.spv --spirv-ext=+SPV_INTEL_vector_compute --spirv-allow-unknown-intrinsics
2+
; RUN: llvm-spirv %t.bc -o %t.spv --spirv-ext=+SPV_INTEL_vector_compute --spirv-allow-unknown-intrinsics=llvm.genx
33
; RUN: llvm-spirv %t.spv -o %t.spt --to-text
44
; RUN: llvm-spirv -r %t.spv -o %t.bc
55
; RUN: llvm-dis %t.bc -o %t.ll

test/transcoding/SPV_INTEL_vector_compute/decoration_single_element_vector.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; RUN: llvm-as %s -o %t.bc
2-
; RUN: llvm-spirv %t.bc -o %t.spv --spirv-ext=+SPV_INTEL_vector_compute --spirv-allow-unknown-intrinsics
2+
; RUN: llvm-spirv %t.bc -o %t.spv --spirv-ext=+SPV_INTEL_vector_compute --spirv-allow-unknown-intrinsics=llvm.genx
33
; RUN: llvm-spirv %t.spv -o %t.spt --to-text
44
; RUN: llvm-spirv -r %t.spv -o %t.bc
55
; RUN: llvm-dis %t.bc -o %t.ll

test/transcoding/SPV_INTEL_vector_compute/decoration_volatile.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; RUN: llvm-as %s -o %t.bc
2-
; RUN: llvm-spirv %t.bc -o %t.spv --spirv-ext=+SPV_INTEL_vector_compute --spirv-allow-unknown-intrinsics
2+
; RUN: llvm-spirv %t.bc -o %t.spv --spirv-ext=+SPV_INTEL_vector_compute --spirv-allow-unknown-intrinsics=llvm.genx
33
; RUN: llvm-spirv %t.spv -o %t.spt --to-text
44
; RUN: llvm-spirv -r %t.spv -o %t.bc
55
; RUN: llvm-dis %t.bc -o %t.ll

test/transcoding/SPV_INTEL_vector_compute/extension_vector_compute_stability.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; RUN: llvm-as %s -o %t.bc
2-
; RUN: llvm-spirv %t.bc -o %t.spv --spirv-ext=+SPV_INTEL_vector_compute,+SPV_KHR_float_controls,+SPV_INTEL_float_controls2 --spirv-allow-unknown-intrinsics
2+
; RUN: llvm-spirv %t.bc -o %t.spv --spirv-ext=+SPV_INTEL_vector_compute,+SPV_KHR_float_controls,+SPV_INTEL_float_controls2 --spirv-allow-unknown-intrinsics=llvm.genx
33
; RUN: llvm-spirv -r %t.spv -o %t.bc
44
; RUN: llvm-spirv %t.bc -o %t.spv --spirv-ext=+SPV_INTEL_vector_compute,+SPV_KHR_float_controls,+SPV_INTEL_float_controls2 --spirv-allow-unknown-intrinsics
55
; RUN: llvm-spirv -r %t.spv -o %t.bc

tools/llvm-spirv/llvm-spirv.cpp

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,14 @@ static cl::list<std::string>
113113
cl::value_desc("+SPV_extenstion1_name,-SPV_extension2_name"),
114114
cl::ValueRequired);
115115

116+
static cl::list<std::string> SPIRVAllowUnknownIntrinsics(
117+
"spirv-allow-unknown-intrinsics", cl::CommaSeparated,
118+
cl::desc("Unknown intrinsics that begin with any prefix from the "
119+
"comma-separated input list will be translated as external "
120+
"function calls in SPIR-V.\nLeaving any prefix unspecified "
121+
"(default) would naturally allow all unknown intrinsics"),
122+
cl::value_desc("intrinsic_prefix_1,intrinsic_prefix_2"), cl::ValueOptional);
123+
116124
static cl::opt<bool> SPIRVGenKernelArgNameMD(
117125
"spirv-gen-kernel-arg-name-md", cl::init(false),
118126
cl::desc("Enable generating OpenCL kernel argument name "
@@ -178,11 +186,6 @@ static cl::opt<SPIRV::FPContractMode> FPCMode(
178186
SPIRV::FPContractMode::Fast, "fast",
179187
"allow all operations to be contracted for all entry points")));
180188

181-
cl::opt<bool> SPIRVAllowUnknownIntrinsics(
182-
"spirv-allow-unknown-intrinsics", cl::init(false),
183-
cl::desc("Unknown LLVM intrinsics will be translated as external function "
184-
"calls in SPIR-V"));
185-
186189
static cl::opt<bool> SPIRVAllowExtraDIExpressions(
187190
"spirv-allow-extra-diexpressions", cl::init(false),
188191
cl::desc("Allow DWARF operations not listed in the OpenCL.DebugInfo.100 "
@@ -543,6 +546,14 @@ bool parseSpecConstOpt(llvm::StringRef SpecConstStr,
543546
return false;
544547
}
545548

549+
static void parseAllowUnknownIntrinsicsOpt(SPIRV::TranslatorOpts &Opts) {
550+
SPIRV::TranslatorOpts::ArgList PrefixList;
551+
for (const auto &Prefix : SPIRVAllowUnknownIntrinsics) {
552+
PrefixList.push_back(Prefix);
553+
}
554+
Opts.setSPIRVAllowUnknownIntrinsics(PrefixList);
555+
}
556+
546557
int main(int Ac, char **Av) {
547558
EnablePrettyStackTrace();
548559
sys::PrintStackTraceOnErrorSignal(Av[0]);
@@ -589,7 +600,7 @@ int main(int Ac, char **Av) {
589600
<< "Note: --spirv-allow-unknown-intrinsics option ignored as it only "
590601
"affects translation from LLVM IR to SPIR-V";
591602
} else {
592-
Opts.setSPIRVAllowUnknownIntrinsicsEnabled(SPIRVAllowUnknownIntrinsics);
603+
parseAllowUnknownIntrinsicsOpt(Opts);
593604
}
594605
}
595606

0 commit comments

Comments
 (0)