Skip to content

Commit 22fe285

Browse files
authored
Translate saturation addition and substraction LLVM intrinsics into OpenCL instructions (#1797)
1 parent e06e46d commit 22fe285

10 files changed

+297
-307
lines changed

include/LLVMSPIRVLib.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ void initializeSPIRVLowerBoolLegacyPass(PassRegistry &);
5757
void initializeSPIRVLowerConstExprLegacyPass(PassRegistry &);
5858
void initializeSPIRVLowerOCLBlocksLegacyPass(PassRegistry &);
5959
void initializeSPIRVLowerMemmoveLegacyPass(PassRegistry &);
60-
void initializeSPIRVLowerSaddIntrinsicsLegacyPass(PassRegistry &);
60+
void initializeSPIRVLowerSaddWithOverflowLegacyPass(PassRegistry &);
6161
void initializeSPIRVRegularizeLLVMLegacyPass(PassRegistry &);
6262
void initializeSPIRVToOCL12LegacyPass(PassRegistry &);
6363
void initializeSPIRVToOCL20LegacyPass(PassRegistry &);
@@ -190,7 +190,7 @@ ModulePass *createSPIRVLowerOCLBlocksLegacy();
190190
ModulePass *createSPIRVLowerMemmoveLegacy();
191191

192192
/// Create a pass for lowering llvm.sadd.with.overflow
193-
ModulePass *createSPIRVLowerSaddIntrinsicsLegacy();
193+
ModulePass *createSPIRVLowerSaddWithOverflowLegacy();
194194

195195
/// Create a pass for regularize LLVM module to be translated to SPIR-V.
196196
ModulePass *createSPIRVRegularizeLLVMLegacy();

lib/SPIRV/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ set(SRC_LIST
1515
SPIRVLowerConstExpr.cpp
1616
SPIRVLowerMemmove.cpp
1717
SPIRVLowerOCLBlocks.cpp
18-
SPIRVLowerSaddIntrinsics.cpp
18+
SPIRVLowerSaddWithOverflow.cpp
1919
SPIRVReader.cpp
2020
SPIRVRegularizeLLVM.cpp
2121
SPIRVToLLVMDbgTran.cpp

lib/SPIRV/SPIRVLowerSaddIntrinsics.cpp

-192
This file was deleted.
+149
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
//===- SPIRVLowerSaddWithOverflow.cpp - Lower llvm.sadd.with.overflow -----===//
2+
//
3+
// The LLVM/SPIRV 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) 2022 The Khronos Group Inc.
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 The Khronos Group, 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+
//
35+
// This file implements lowering of llvm.sadd.with.overflow.* into basic LLVM
36+
// operations. Probably, in the future this pass can be generalized for other
37+
// function calls
38+
//
39+
//===----------------------------------------------------------------------===//
40+
#define DEBUG_TYPE "spv-lower-llvm_sadd_with_overflow"
41+
42+
#include "SPIRVLowerSaddWithOverflow.h"
43+
#include "LLVMSaddWithOverflow.h"
44+
45+
#include "LLVMSPIRVLib.h"
46+
#include "SPIRVError.h"
47+
#include "libSPIRV/SPIRVDebug.h"
48+
49+
#include "llvm/IR/InstVisitor.h"
50+
#include "llvm/IR/IntrinsicInst.h"
51+
#include "llvm/IR/Module.h"
52+
#include "llvm/IRReader/IRReader.h"
53+
#include "llvm/Linker/Linker.h"
54+
#include "llvm/Support/SourceMgr.h"
55+
56+
using namespace llvm;
57+
using namespace SPIRV;
58+
59+
namespace SPIRV {
60+
61+
void SPIRVLowerSaddWithOverflowBase::visitIntrinsicInst(CallInst &I) {
62+
IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I);
63+
if (!II || II->getIntrinsicID() != Intrinsic::sadd_with_overflow)
64+
return;
65+
66+
Function *IntrinsicFunc = I.getCalledFunction();
67+
assert(IntrinsicFunc && "Missing function");
68+
StringRef IntrinsicName = IntrinsicFunc->getName();
69+
std::string FuncName = "llvm_sadd_with_overflow_i";
70+
if (IntrinsicName.endswith(".i16"))
71+
FuncName += "16";
72+
else if (IntrinsicName.endswith(".i32"))
73+
FuncName += "32";
74+
else if (IntrinsicName.endswith(".i64"))
75+
FuncName += "64";
76+
else {
77+
assert(false &&
78+
"Unsupported overloading of llvm.sadd.with.overflow intrinsic");
79+
return;
80+
}
81+
82+
// Redirect @llvm.sadd.with.overflow.* call to the function we have in
83+
// the loaded module @llvm_sadd_with_overflow_*
84+
Function *F = Mod->getFunction(FuncName);
85+
if (F) { // This function is already linked in.
86+
I.setCalledFunction(F);
87+
return;
88+
}
89+
FunctionCallee FC = Mod->getOrInsertFunction(FuncName, I.getFunctionType());
90+
I.setCalledFunction(FC);
91+
92+
// Read LLVM IR with the intrinsic's implementation
93+
SMDiagnostic Err;
94+
auto MB = MemoryBuffer::getMemBuffer(LLVMSaddWithOverflow);
95+
auto SaddWithOverflowModule =
96+
parseIR(MB->getMemBufferRef(), Err, *Context,
97+
[&](StringRef) { return Mod->getDataLayoutStr(); });
98+
if (!SaddWithOverflowModule) {
99+
std::string ErrMsg;
100+
raw_string_ostream ErrStream(ErrMsg);
101+
Err.print("", ErrStream);
102+
SPIRVErrorLog EL;
103+
EL.checkError(false, SPIRVEC_InvalidLlvmModule, ErrMsg);
104+
return;
105+
}
106+
107+
// Link in the intrinsic's implementation.
108+
if (!Linker::linkModules(*Mod, std::move(SaddWithOverflowModule),
109+
Linker::LinkOnlyNeeded))
110+
TheModuleIsModified = true;
111+
}
112+
113+
bool SPIRVLowerSaddWithOverflowBase::runLowerSaddWithOverflow(Module &M) {
114+
Context = &M.getContext();
115+
Mod = &M;
116+
visit(M);
117+
118+
verifyRegularizationPass(M, "SPIRVLowerSaddWithOverflow");
119+
return TheModuleIsModified;
120+
}
121+
122+
llvm::PreservedAnalyses
123+
SPIRVLowerSaddWithOverflowPass::run(llvm::Module &M,
124+
llvm::ModuleAnalysisManager &MAM) {
125+
return runLowerSaddWithOverflow(M) ? llvm::PreservedAnalyses::none()
126+
: llvm::PreservedAnalyses::all();
127+
}
128+
129+
SPIRVLowerSaddWithOverflowLegacy::SPIRVLowerSaddWithOverflowLegacy()
130+
: ModulePass(ID) {
131+
initializeSPIRVLowerSaddWithOverflowLegacyPass(
132+
*PassRegistry::getPassRegistry());
133+
}
134+
135+
bool SPIRVLowerSaddWithOverflowLegacy::runOnModule(Module &M) {
136+
return runLowerSaddWithOverflow(M);
137+
}
138+
139+
char SPIRVLowerSaddWithOverflowLegacy::ID = 0;
140+
141+
} // namespace SPIRV
142+
143+
INITIALIZE_PASS(SPIRVLowerSaddWithOverflowLegacy,
144+
"spv-lower-llvm_sadd_with_overflow",
145+
"Lower llvm.sadd.with.overflow.* intrinsics", false, false)
146+
147+
ModulePass *llvm::createSPIRVLowerSaddWithOverflowLegacy() {
148+
return new SPIRVLowerSaddWithOverflowLegacy();
149+
}

0 commit comments

Comments
 (0)