blob: e33da9eb0a4e487e9522332460a174ff28f31a03 [file] [log] [blame]
David Neto22f144c2017-06-12 14:26:21 -04001// Copyright 2017 The Clspv Authors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
David Neto118188e2018-08-24 11:27:54 -040015#include "llvm/IR/IRBuilder.h"
Diego Novillo3cc8d7a2019-04-10 13:30:34 -040016#include "llvm/IR/Instructions.h"
David Neto118188e2018-08-24 11:27:54 -040017#include "llvm/IR/Module.h"
18#include "llvm/Pass.h"
19#include "llvm/Support/raw_ostream.h"
David Neto22f144c2017-06-12 14:26:21 -040020
Diego Novilloa4c44fa2019-04-11 10:56:15 -040021#include "Passes.h"
22
David Neto22f144c2017-06-12 14:26:21 -040023using namespace llvm;
24
25#define DEBUG_TYPE "splatarg"
26
27namespace {
28struct SplatArgPass : public ModulePass {
29 static char ID;
30 SplatArgPass() : ModulePass(ID) {}
31
Diego Novillo3cc8d7a2019-04-10 13:30:34 -040032 const char *getSplatName(StringRef Name);
David Neto22f144c2017-06-12 14:26:21 -040033 bool runOnModule(Module &M) override;
34};
Diego Novillo3cc8d7a2019-04-10 13:30:34 -040035} // namespace
David Neto22f144c2017-06-12 14:26:21 -040036
37char SplatArgPass::ID = 0;
Diego Novilloa4c44fa2019-04-11 10:56:15 -040038INITIALIZE_PASS(SplatArgPass, "SplatArg", "Splat Argument Pass", false, false)
David Neto22f144c2017-06-12 14:26:21 -040039
40namespace clspv {
41llvm::ModulePass *createSplatArgPass() { return new SplatArgPass(); }
Diego Novillo3cc8d7a2019-04-10 13:30:34 -040042} // namespace clspv
David Neto22f144c2017-06-12 14:26:21 -040043
Diego Novillo3cc8d7a2019-04-10 13:30:34 -040044const char *SplatArgPass::getSplatName(StringRef Name) {
David Neto22f144c2017-06-12 14:26:21 -040045 if (Name.equals("_Z5clampDv2_iii")) {
46 return "_Z5clampDv2_iS_S_";
47 } else if (Name.equals("_Z5clampDv3_iii")) {
48 return "_Z5clampDv3_iS_S_";
49 } else if (Name.equals("_Z5clampDv4_iii")) {
50 return "_Z5clampDv4_iS_S_";
51 } else if (Name.equals("_Z5clampDv2_jjj")) {
52 return "_Z5clampDv2_jS_S_";
53 } else if (Name.equals("_Z5clampDv3_jjj")) {
54 return "_Z5clampDv3_jS_S_";
55 } else if (Name.equals("_Z5clampDv4_jjj")) {
56 return "_Z5clampDv4_jS_S_";
57 } else if (Name.equals("_Z5clampDv2_fff")) {
58 return "_Z5clampDv2_fS_S_";
59 } else if (Name.equals("_Z5clampDv3_fff")) {
60 return "_Z5clampDv3_fS_S_";
61 } else if (Name.equals("_Z5clampDv4_fff")) {
62 return "_Z5clampDv4_fS_S_";
alan-baker49bb5fb2020-01-15 08:22:13 -050063 } else if (Name.equals("_Z5clampDv2_DhDhDh")) {
64 return "_Z5clampDv2_DhS_S_";
65 } else if (Name.equals("_Z5clampDv3_DhDhDh")) {
66 return "_Z5clampDv3_DhS_S_";
67 } else if (Name.equals("_Z5clampDv4_DhDhDh")) {
68 return "_Z5clampDv4_DhS_S_";
David Neto22f144c2017-06-12 14:26:21 -040069
70 } else if (Name.equals("_Z3maxDv2_ii")) {
71 return "_Z3maxDv2_iS_";
72 } else if (Name.equals("_Z3maxDv3_ii")) {
73 return "_Z3maxDv3_iS_";
74 } else if (Name.equals("_Z3maxDv4_ii")) {
75 return "_Z3maxDv4_iS_";
76 } else if (Name.equals("_Z3maxDv2_jj")) {
77 return "_Z3maxDv2_jS_";
78 } else if (Name.equals("_Z3maxDv3_jj")) {
79 return "_Z3maxDv3_jS_";
80 } else if (Name.equals("_Z3maxDv4_jj")) {
81 return "_Z3maxDv4_jS_";
82 } else if (Name.equals("_Z3maxDv2_ff")) {
83 return "_Z3maxDv2_fS_";
84 } else if (Name.equals("_Z3maxDv3_ff")) {
85 return "_Z3maxDv3_fS_";
86 } else if (Name.equals("_Z3maxDv4_ff")) {
87 return "_Z3maxDv4_fS_";
alan-baker49bb5fb2020-01-15 08:22:13 -050088 } else if (Name.equals("_Z3maxDv2_DhDh")) {
89 return "_Z3maxDv2_DhS_";
90 } else if (Name.equals("_Z3maxDv3_DhDh")) {
91 return "_Z3maxDv3_DhS_";
92 } else if (Name.equals("_Z3maxDv4_DhDh")) {
93 return "_Z3maxDv4_DhS_";
David Neto22f144c2017-06-12 14:26:21 -040094 } else if (Name.equals("_Z4fmaxDv2_ff")) {
95 return "_Z4fmaxDv2_fS_";
96 } else if (Name.equals("_Z4fmaxDv3_ff")) {
97 return "_Z4fmaxDv3_fS_";
98 } else if (Name.equals("_Z4fmaxDv4_ff")) {
99 return "_Z4fmaxDv4_fS_";
alan-baker49bb5fb2020-01-15 08:22:13 -0500100 } else if (Name.equals("_Z4fmaxDv2_DhDh")) {
101 return "_Z4fmaxDv2_DhS_";
102 } else if (Name.equals("_Z4fmaxDv3_DhDh")) {
103 return "_Z4fmaxDv3_DhS_";
104 } else if (Name.equals("_Z4fmaxDv4_DhDh")) {
105 return "_Z4fmaxDv4_DhS_";
David Neto22f144c2017-06-12 14:26:21 -0400106
107 } else if (Name.equals("_Z3minDv2_ii")) {
108 return "_Z3minDv2_iS_";
109 } else if (Name.equals("_Z3minDv3_ii")) {
110 return "_Z3minDv3_iS_";
Diego Novillo3cc8d7a2019-04-10 13:30:34 -0400111 } else if (Name.equals("_Z3minDv4_ii")) {
David Neto22f144c2017-06-12 14:26:21 -0400112 return "_Z3minDv4_iS_";
113 } else if (Name.equals("_Z3minDv2_jj")) {
114 return "_Z3minDv2_jS_";
115 } else if (Name.equals("_Z3minDv3_jj")) {
116 return "_Z3minDv3_jS_";
117 } else if (Name.equals("_Z3minDv4_jj")) {
118 return "_Z3minDv4_jS_";
119 } else if (Name.equals("_Z3minDv2_ff")) {
120 return "_Z3minDv2_fS_";
121 } else if (Name.equals("_Z3minDv3_ff")) {
122 return "_Z3minDv3_fS_";
123 } else if (Name.equals("_Z3minDv4_ff")) {
124 return "_Z3minDv4_fS_";
alan-baker49bb5fb2020-01-15 08:22:13 -0500125 } else if (Name.equals("_Z3minDv2_DhDh")) {
126 return "_Z3minDv2_DhS_";
127 } else if (Name.equals("_Z3minDv3_DhDh")) {
128 return "_Z3minDv3_DhS_";
129 } else if (Name.equals("_Z3minDv4_DhDh")) {
130 return "_Z3minDv4_DhS_";
David Neto22f144c2017-06-12 14:26:21 -0400131 } else if (Name.equals("_Z4fminDv2_ff")) {
132 return "_Z4fminDv2_fS_";
133 } else if (Name.equals("_Z4fminDv3_ff")) {
134 return "_Z4fminDv3_fS_";
135 } else if (Name.equals("_Z4fminDv4_ff")) {
136 return "_Z4fminDv4_fS_";
alan-baker49bb5fb2020-01-15 08:22:13 -0500137 } else if (Name.equals("_Z4fminDv2_DhDh")) {
138 return "_Z4fminDv2_DhS_";
139 } else if (Name.equals("_Z4fminDv3_DhDh")) {
140 return "_Z4fminDv3_DhS_";
141 } else if (Name.equals("_Z4fminDv4_DhDh")) {
142 return "_Z4fminDv4_DhS_";
David Neto22f144c2017-06-12 14:26:21 -0400143
144 } else if (Name.equals("_Z3mixDv2_fS_f")) {
145 return "_Z3mixDv2_fS_S_";
146 } else if (Name.equals("_Z3mixDv3_fS_f")) {
147 return "_Z3mixDv3_fS_S_";
148 } else if (Name.equals("_Z3mixDv4_fS_f")) {
149 return "_Z3mixDv4_fS_S_";
alan-baker49bb5fb2020-01-15 08:22:13 -0500150 } else if (Name.equals("_Z3mixDv2_DhS_Dh")) {
151 return "_Z3mixDv2_DhS_S_";
152 } else if (Name.equals("_Z3mixDv3_DhS_Dh")) {
153 return "_Z3mixDv3_DhS_S_";
154 } else if (Name.equals("_Z3mixDv4_DhS_Dh")) {
155 return "_Z3mixDv4_DhS_S_";
David Neto22f144c2017-06-12 14:26:21 -0400156 }
157
158 return nullptr;
159}
160
161bool SplatArgPass::runOnModule(Module &M) {
162 bool Changed = false;
163
164 SmallVector<CallInst *, 16> WorkList;
165 for (Function &F : M) {
166 for (BasicBlock &BB : F) {
167 for (Instruction &I : BB) {
168 if (CallInst *Call = dyn_cast<CallInst>(&I)) {
169 Function *Callee = Call->getCalledFunction();
170 if (Callee) {
171 // If min/max/mix/clamp function call has scalar type argument, we
172 // need to splat the scalar type one to vector type.
173 if (getSplatName(Callee->getName())) {
174 WorkList.push_back(Call);
175 Changed = true;
176 }
177 }
178 }
179 }
180 }
181 }
182
183 for (CallInst *Call : WorkList) {
184 Function *Callee = Call->getCalledFunction();
185 FunctionType *CalleeTy = Callee->getFunctionType();
186
187 // Create new callee function type with vector type.
188 SmallVector<Type *, 4> NewCalleeParamTys;
189 for (const auto &Arg : Callee->args()) {
190 if (Arg.getType()->isVectorTy()) {
191 NewCalleeParamTys.push_back(Arg.getType());
192 } else {
193 NewCalleeParamTys.push_back(Call->getType());
194 }
195 }
196
197 FunctionType *NewCalleeTy =
198 FunctionType::get(Call->getType(), NewCalleeParamTys, false);
199
200 // Create new callee function declaration with new function type.
201 StringRef NewCallName(getSplatName(Callee->getName()));
alan-bakerbccf62c2019-03-29 10:32:41 -0400202 Function *NewCallee = cast<Function>(
203 M.getOrInsertFunction(NewCallName, NewCalleeTy).getCallee());
David Neto22f144c2017-06-12 14:26:21 -0400204 NewCallee->setCallingConv(CallingConv::SPIR_FUNC);
205
206 // Change target of call instruction.
207 Call->setCalledFunction(NewCalleeTy, NewCallee);
208
209 // Change operands of call instruction.
210 IRBuilder<> Builder(Call);
211 for (unsigned i = 0; i < CalleeTy->getNumParams(); i++) {
212 if (!CalleeTy->getParamType(i)->isVectorTy()) {
213 VectorType *VTy = cast<VectorType>(Call->getType());
214 Value *NewArg = Builder.CreateVectorSplat(
215 VTy->getNumElements(), Call->getArgOperand(i), "arg_splat");
216 Call->setArgOperand(i, NewArg);
217 }
218 }
219
220 Call->setCallingConv(CallingConv::SPIR_FUNC);
221 }
222
223 return Changed;
224}