Skip to content

Commit 7bf3a0b

Browse files
authored
Merge pull request #230 from haonanya/haonanya/branch-80/lower-llvm.fmuladd
Add possibility to lower llvm.fmuladd into mad from OpenCL extinst
2 parents 6bd68cf + 12b76cf commit 7bf3a0b

File tree

1 file changed

+170
-0
lines changed

1 file changed

+170
-0
lines changed
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
From 18038368f25cd2b06a55083a8b7030134bd75350 Mon Sep 17 00:00:00 2001
2+
From: Alexey Sachkov <[email protected]>
3+
Date: Thu, 17 Dec 2020 11:47:07 +0300
4+
Subject: [PATCH] Add possibility to lower llvm.fmuladd into mad from OpenCL
5+
extinst (#858)
6+
7+
---
8+
include/LLVMSPIRVOpts.h | 12 ++++++++++++
9+
lib/SPIRV/SPIRVWriter.cpp | 13 +++++++++++++
10+
lib/SPIRV/libSPIRV/SPIRVModule.h | 4 ++++
11+
test/llvm.fmuladd.ll | 33 ++++++++++++++++++++------------
12+
tools/llvm-spirv/llvm-spirv.cpp | 16 ++++++++++++++++
13+
5 files changed, 66 insertions(+), 12 deletions(-)
14+
15+
diff --git a/include/LLVMSPIRVOpts.h b/include/LLVMSPIRVOpts.h
16+
index 3e36375..4d7d5f0 100644
17+
--- a/include/LLVMSPIRVOpts.h
18+
+++ b/include/LLVMSPIRVOpts.h
19+
@@ -107,6 +107,14 @@ public:
20+
21+
void setDebugInfoEIS(DebugInfoEIS EIS) { DebugInfoVersion = EIS; }
22+
23+
+ bool shouldReplaceLLVMFmulAddWithOpenCLMad() const noexcept {
24+
+ return ReplaceLLVMFmulAddWithOpenCLMad;
25+
+ }
26+
+
27+
+ void setReplaceLLVMFmulAddWithOpenCLMad(bool Value) noexcept {
28+
+ ReplaceLLVMFmulAddWithOpenCLMad = Value;
29+
+ }
30+
+
31+
private:
32+
// Common translation options
33+
VersionNumber MaxVersion = VersionNumber::MaximumVersion;
34+
@@ -124,6 +132,10 @@ private:
35+
bool SPIRVAllowUnknownIntrinsics = false;
36+
37+
DebugInfoEIS DebugInfoVersion = DebugInfoEIS::SPIRV_Debug;
38+
+
39+
+ // Controls whether llvm.fmuladd.* should be replaced with mad from OpenCL
40+
+ // extended instruction set or with a simple fmul + fadd
41+
+ bool ReplaceLLVMFmulAddWithOpenCLMad = true;
42+
};
43+
44+
} // namespace SPIRV
45+
diff --git a/lib/SPIRV/SPIRVWriter.cpp b/lib/SPIRV/SPIRVWriter.cpp
46+
index 810ba1f..332dbdb 100644
47+
--- a/lib/SPIRV/SPIRVWriter.cpp
48+
+++ b/lib/SPIRV/SPIRVWriter.cpp
49+
@@ -1260,6 +1260,19 @@ SPIRVValue *LLVMToSPIRV::transIntrinsicInst(IntrinsicInst *II,
50+
// For llvm.fmuladd.* fusion is not guaranteed. If a fused multiply-add
51+
// is required the corresponding llvm.fma.* intrinsic function should be
52+
// used instead.
53+
+ // If allowed, let's replace llvm.fmuladd.* with mad from OpenCL extended
54+
+ // instruction set, as it has the same semantic for FULL_PROFILE OpenCL
55+
+ // devices (implementation-defined for EMBEDDED_PROFILE).
56+
+ if (BM->shouldReplaceLLVMFmulAddWithOpenCLMad()) {
57+
+ std::vector<SPIRVValue *> Ops{transValue(II->getArgOperand(0), BB),
58+
+ transValue(II->getArgOperand(1), BB),
59+
+ transValue(II->getArgOperand(2), BB)};
60+
+ return BM->addExtInst(transType(II->getType()),
61+
+ BM->getExtInstSetId(SPIRVEIS_OpenCL),
62+
+ OpenCLLIB::Mad, Ops, BB);
63+
+ }
64+
+
65+
+ // Otherwise, just break llvm.fmuladd.* into a pair of fmul + fadd
66+
SPIRVType *Ty = transType(II->getType());
67+
SPIRVValue *Mul =
68+
BM->addBinaryInst(OpFMul, Ty, transValue(II->getArgOperand(0), BB),
69+
diff --git a/lib/SPIRV/libSPIRV/SPIRVModule.h b/lib/SPIRV/libSPIRV/SPIRVModule.h
70+
index 4460821..c3ea082 100644
71+
--- a/lib/SPIRV/libSPIRV/SPIRVModule.h
72+
+++ b/lib/SPIRV/libSPIRV/SPIRVModule.h
73+
@@ -416,6 +416,10 @@ public:
74+
return TranslationOpts.isSPIRVAllowUnknownIntrinsicsEnabled();
75+
}
76+
77+
+ bool shouldReplaceLLVMFmulAddWithOpenCLMad() const noexcept {
78+
+ return TranslationOpts.shouldReplaceLLVMFmulAddWithOpenCLMad();
79+
+ }
80+
+
81+
SPIRVExtInstSetKind getDebugInfoEIS() const {
82+
switch (TranslationOpts.getDebugInfoEIS()) {
83+
case DebugInfoEIS::SPIRV_Debug:
84+
diff --git a/test/llvm.fmuladd.ll b/test/llvm.fmuladd.ll
85+
index aab9b86..5f63454 100644
86+
--- a/test/llvm.fmuladd.ll
87+
+++ b/test/llvm.fmuladd.ll
88+
@@ -1,12 +1,25 @@
89+
; RUN: llvm-as %s -o %t.bc
90+
-; RUN: llvm-spirv %t.bc -spirv-text -o - | FileCheck %s
91+
-; RUN: llvm-spirv %t.bc -o %t.spv
92+
-; RUN: spirv-val %t.spv
93+
-
94+
-; CHECK-NOT: llvm.fmuladd
95+
-
96+
-; CHECK: TypeFloat [[f32:[0-9]+]] 32
97+
-; CHECK: TypeFloat [[f64:[0-9]+]] 64
98+
+; RUN: llvm-spirv %t.bc -o %default.spv
99+
+; RUN: llvm-spirv %t.bc --spirv-replace-fmuladd-with-ocl-mad=true -o %replace.spv
100+
+; RUN: llvm-spirv %t.bc --spirv-replace-fmuladd-with-ocl-mad=false -o %break.spv
101+
+; RUN: spirv-val %replace.spv
102+
+; RUN: spirv-val %break.spv
103+
+; RUN: llvm-spirv %default.spv -to-text -o - | FileCheck %s --check-prefixes=COMMON,REPLACE
104+
+; RUN: llvm-spirv %replace.spv -to-text -o - | FileCheck %s --check-prefixes=COMMON,REPLACE
105+
+; RUN: llvm-spirv %break.spv -to-text -o - | FileCheck %s --check-prefixes=COMMON,BREAK
106+
+
107+
+; COMMON-NOT: llvm.fmuladd
108+
+
109+
+; COMMON: TypeFloat [[f32:[0-9]+]] 32
110+
+; COMMON: TypeFloat [[f64:[0-9]+]] 64
111+
+;
112+
+; REPLACE: ExtInst [[f32]] {{[0-9]+}} {{[0-9]+}} mad
113+
+; REPLACE: ExtInst [[f64]] {{[0-9]+}} {{[0-9]+}} mad
114+
+;
115+
+; BREAK: FMul [[f32]] [[mul32:[0-9]+]] {{[0-9]+}} {{[0-9]+}}
116+
+; BREAK-NEXT: FAdd [[f32]] {{[0-9]+}} [[mul32]] {{[0-9]+}}
117+
+; BREAK: FMul [[f64]] [[mul64:[0-9]+]] {{[0-9]+}} {{[0-9]+}}
118+
+; BREAK-NEXT: FAdd [[f64]] {{[0-9]+}} [[mul64]] {{[0-9]+}}
119+
120+
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"
121+
target triple = "spir64"
122+
@@ -15,11 +28,7 @@ target triple = "spir64"
123+
define spir_func void @foo(float %a, float %b, float %c, double %x, double %y, double %z) #0 {
124+
entry:
125+
%0 = call float @llvm.fmuladd.f32(float %a, float %b, float %c)
126+
-; CHECK: FMul [[f32]] [[mul32:[0-9]+]] {{[0-9]+}} {{[0-9]+}}
127+
-; CHECK-NEXT: FAdd [[f32]] {{[0-9]+}} [[mul32]] {{[0-9]+}}
128+
%1 = call double @llvm.fmuladd.f64(double %x, double %y, double %z)
129+
-; CHECK: FMul [[f64]] [[mul64:[0-9]+]] {{[0-9]+}} {{[0-9]+}}
130+
-; CHECK-NEXT: FAdd [[f64]] {{[0-9]+}} [[mul64]] {{[0-9]+}}
131+
ret void
132+
}
133+
134+
diff --git a/tools/llvm-spirv/llvm-spirv.cpp b/tools/llvm-spirv/llvm-spirv.cpp
135+
index b6f1fe4..1ca8acc 100644
136+
--- a/tools/llvm-spirv/llvm-spirv.cpp
137+
+++ b/tools/llvm-spirv/llvm-spirv.cpp
138+
@@ -156,6 +156,12 @@ static cl::opt<SPIRV::DebugInfoEIS> DebugEIS(
139+
"extended instruction set. This version of SPIR-V debug "
140+
"info format is compatible with the SPIRV-Tools")));
141+
142+
+static cl::opt<bool> SPIRVReplaceLLVMFmulAddWithOpenCLMad(
143+
+ "spirv-replace-fmuladd-with-ocl-mad",
144+
+ cl::desc("Allow replacement of llvm.fmuladd.* intrinsic with OpenCL mad "
145+
+ "instruction from OpenCL extended instruction set"),
146+
+ cl::init(true));
147+
+
148+
static std::string removeExt(const std::string &FileName) {
149+
size_t Pos = FileName.find_last_of(".");
150+
if (Pos != std::string::npos)
151+
@@ -339,6 +345,16 @@ int main(int Ac, char **Av) {
152+
}
153+
}
154+
155+
+ if (SPIRVReplaceLLVMFmulAddWithOpenCLMad.getNumOccurrences() != 0) {
156+
+ if (IsReverse) {
157+
+ errs() << "Note: --spirv-replace-fmuladd-with-ocl-mad option ignored as "
158+
+ "it only affects translation from LLVM IR to SPIR-V";
159+
+ } else {
160+
+ Opts.setReplaceLLVMFmulAddWithOpenCLMad(
161+
+ SPIRVReplaceLLVMFmulAddWithOpenCLMad);
162+
+ }
163+
+ }
164+
+
165+
if (DebugEIS.getNumOccurrences() != 0) {
166+
if (IsReverse) {
167+
errs() << "Note: --spirv-debug-info-version option ignored as it only "
168+
--
169+
2.17.1
170+

0 commit comments

Comments
 (0)