Skip to content

Commit fac165c

Browse files
Andrew Savonichevvladimirlaz
authored andcommitted
Add --spirv-fp-contract={on|off|fast} option (#509)
Add --spirv-fp-contract={on|off|fast} option In SPIR-V, floating point contraction (fused multiply add) can only be controlled per entry point using ContractionOFF execution mode: it can either allow any floating point operation to contract across a call graph (with an entry point as a root), or disallow contraction for a call graph. SPIR-V translator currently have an algorithm to determine if ContractionOFF should be set, but this algorithm is supposed to be very pessimistic. A single non-contracted fmul + fadd or a single undefined function must force ContractionOFF for the entire call graph. This behavior is used by default, or when --spirv-fp-contract=on is set. Two more modes are added: - `off' disables contraction for all entry points - `fast' unconditionally enables contraction for all entry points
1 parent d76d83c commit fac165c

File tree

5 files changed

+82
-10
lines changed

5 files changed

+82
-10
lines changed

llvm-spirv/include/LLVMSPIRVOpts.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ enum class ExtensionID : uint32_t {
6767

6868
enum class BIsRepresentation : uint32_t { OpenCL12, OpenCL20, SPIRVFriendlyIR };
6969

70+
enum class FPContractMode : uint32_t { On, Off, Fast };
71+
7072
/// \brief Helper class to manage SPIR-V translation
7173
class TranslatorOpts {
7274
public:
@@ -129,6 +131,10 @@ class TranslatorOpts {
129131
return DesiredRepresentationOfBIs;
130132
}
131133

134+
void setFPContractMode(FPContractMode Mode) { FPCMode = Mode; }
135+
136+
FPContractMode getFPContractMode() const { return FPCMode; }
137+
132138
private:
133139
// Common translation options
134140
VersionNumber MaxVersion = VersionNumber::MaximumVersion;
@@ -141,6 +147,16 @@ class TranslatorOpts {
141147
// Representation of built-ins, which should be used while translating from
142148
// SPIR-V to back to LLVM IR
143149
BIsRepresentation DesiredRepresentationOfBIs = BIsRepresentation::OpenCL12;
150+
// Controls floating point contraction.
151+
//
152+
// - FPContractMode::On allows to choose a mode according to
153+
// presence of fused LLVM intrinsics
154+
//
155+
// - FPContractMode::Off disables contratction for all entry points
156+
//
157+
// - FPContractMode::Fast allows *all* operations to be contracted
158+
// for all entry points
159+
FPContractMode FPCMode = FPContractMode::On;
144160
};
145161

146162
} // namespace SPIRV

llvm-spirv/lib/SPIRV/SPIRVWriter.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2194,12 +2194,26 @@ void LLVMToSPIRV::transFunction(Function *I) {
21942194
}
21952195
}
21962196

2197-
if (BF->getModule()->isEntryPoint(spv::ExecutionModelKernel, BF->getId()) &&
2198-
BF->shouldFPContractBeDisabled()) {
2197+
bool IsKernelEntryPoint =
2198+
BF->getModule()->isEntryPoint(spv::ExecutionModelKernel, BF->getId());
2199+
bool DisableContraction = false;
2200+
switch (BM->getFPContractMode()) {
2201+
case FPContractMode::Fast:
2202+
DisableContraction = false;
2203+
break;
2204+
case FPContractMode::On:
2205+
DisableContraction = IsKernelEntryPoint && BF->shouldFPContractBeDisabled();
2206+
break;
2207+
case FPContractMode::Off:
2208+
DisableContraction = IsKernelEntryPoint;
2209+
break;
2210+
}
2211+
2212+
if (DisableContraction) {
21992213
BF->addExecutionMode(BF->getModule()->add(
22002214
new SPIRVExecutionMode(BF, spv::ExecutionModeContractionOff)));
22012215
}
2202-
if (BF->getModule()->isEntryPoint(spv::ExecutionModelKernel, BF->getId())) {
2216+
if (IsKernelEntryPoint) {
22032217
collectInputOutputVariables(BF, I);
22042218
}
22052219
}

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,10 @@ class SPIRVModule {
472472
return TranslationOpts.getSpecializationConstant(SpecId, ConstValue);
473473
}
474474

475+
FPContractMode getFPContractMode() const {
476+
return TranslationOpts.getFPContractMode();
477+
}
478+
475479
// I/O functions
476480
friend spv_ostream &operator<<(spv_ostream &O, SPIRVModule &M);
477481
friend std::istream &operator>>(std::istream &I, SPIRVModule &M);

llvm-spirv/test/ContractionOff.ll

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,40 @@
1818
; opt -mem2reg 1.ll -S -o 1.o.ll
1919

2020
; RUN: llvm-as %s -o %t.bc
21-
; RUN: llvm-spirv %t.bc -spirv-text -o %t
22-
; RUN: FileCheck < %t %s
23-
; RUN: llvm-spirv %t.bc -o %t.spv
24-
; RUN: spirv-val %t.spv
21+
; RUN: llvm-spirv %t.bc -o %t.spv.default
22+
; RUN: llvm-spirv %t.spv.default -to-text -o - | FileCheck %s --check-prefixes CHECK,CHECK-ON
23+
; RUN: spirv-val %t.spv.default
24+
25+
; RUN: llvm-as %s -o %t.bc
26+
; RUN: llvm-spirv %t.bc -o %t.spv.off --spirv-fp-contract=off
27+
; RUN: llvm-spirv %t.spv.off -to-text -o - | FileCheck %s --check-prefixes CHECK,CHECK-OFF
28+
; RUN: spirv-val %t.spv.off
29+
30+
; RUN: llvm-as %s -o %t.bc
31+
; RUN: llvm-spirv %t.bc -o %t.spv.fast --spirv-fp-contract=fast
32+
; RUN: llvm-spirv %t.spv.fast -to-text -o - | FileCheck %s --check-prefixes CHECK,CHECK-FAST
33+
; RUN: spirv-val %t.spv.fast
34+
35+
; RUN: llvm-as %s -o %t.bc
36+
; RUN: llvm-spirv %t.bc -o %t.spv.on --spirv-fp-contract=on
37+
; RUN: llvm-spirv %t.spv.on -to-text -o - | FileCheck %s --check-prefixes CHECK,CHECK-ON
38+
; RUN: spirv-val %t.spv.on
2539

2640
; CHECK: EntryPoint 6 [[K1:[0-9]+]] "k1"
2741
; CHECK: EntryPoint 6 [[K2:[0-9]+]] "k2"
2842
; CHECK: EntryPoint 6 [[K3:[0-9]+]] "k3"
29-
; CHECK: ExecutionMode [[K1]] 31
30-
; CHECK-NOT: ExecutionMode [[K2]] 31
31-
; CHECK-NOT: ExecutionMode [[K3]] 31
43+
44+
; CHECK-OFF: ExecutionMode [[K1]] 31
45+
; CHECK-OFF: ExecutionMode [[K2]] 31
46+
; CHECK-OFF: ExecutionMode [[K3]] 31
47+
48+
; CHECK-FAST-NOT: ExecutionMode [[K1]] 31
49+
; CHECK-FAST-NOT: ExecutionMode [[K2]] 31
50+
; CHECK-FAST-NOT: ExecutionMode [[K3]] 31
51+
52+
; CHECK-ON: ExecutionMode [[K1]] 31
53+
; CHECK-ON-NOT: ExecutionMode [[K2]] 31
54+
; CHECK-ON-NOT: ExecutionMode [[K3]] 31
3255

3356
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
3457
target triple = "spir64"

llvm-spirv/tools/llvm-spirv/llvm-spirv.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,19 @@ static cl::opt<bool> SpecConstInfo(
163163
cl::desc("Display id of constants available for specializaion and their "
164164
"size in bytes"));
165165

166+
static cl::opt<SPIRV::FPContractMode> FPCMode(
167+
"spirv-fp-contract", cl::desc("Set FP Contraction mode:"),
168+
cl::init(SPIRV::FPContractMode::On),
169+
cl::values(
170+
clEnumValN(SPIRV::FPContractMode::On, "on",
171+
"choose a mode according to presence of llvm.fmuladd "
172+
"intrinsic or `contract' flag on fp operations"),
173+
clEnumValN(SPIRV::FPContractMode::Off, "off",
174+
"disable FP contraction for all entry points"),
175+
clEnumValN(
176+
SPIRV::FPContractMode::Fast, "fast",
177+
"allow all operations to be contracted for all entry points")));
178+
166179
static std::string removeExt(const std::string &FileName) {
167180
size_t Pos = FileName.find_last_of(".");
168181
if (Pos != std::string::npos)
@@ -527,6 +540,8 @@ int main(int Ac, char **Av) {
527540
}
528541
}
529542

543+
Opts.setFPContractMode(FPCMode);
544+
530545
if (SPIRVMemToReg)
531546
Opts.setMemToRegEnabled(SPIRVMemToReg);
532547
if (SPIRVGenKernelArgNameMD)

0 commit comments

Comments
 (0)