|  | 
|  | 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