Code reorganization: s/aux/auxiliary/.
[mesa.git] / src / gallium / auxiliary / llvm / instructions.cpp
1 /**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /*
29 * Authors:
30 * Zack Rusin zack@tungstengraphics.com
31 */
32 #ifdef MESA_LLVM
33
34 #include "instructions.h"
35
36 #include "storage.h"
37
38 #include <llvm/CallingConv.h>
39 #include <llvm/Constants.h>
40 #include <llvm/DerivedTypes.h>
41 #include <llvm/Function.h>
42 #include <llvm/InstrTypes.h>
43 #include <llvm/Instructions.h>
44 #include <llvm/ParameterAttributes.h>
45
46 #include <sstream>
47 #include <fstream>
48 #include <iostream>
49
50 using namespace llvm;
51
52 #include "gallivm_builtins.cpp"
53
54 static inline std::string createFuncName(int label)
55 {
56 std::ostringstream stream;
57 stream << "function";
58 stream << label;
59 return stream.str();
60 }
61
62 Instructions::Instructions(llvm::Module *mod, llvm::Function *func, llvm::BasicBlock *block,
63 Storage *storage)
64 : m_mod(mod), m_func(func), m_builder(block), m_idx(0),
65 m_storage(storage)
66 {
67 m_floatVecType = VectorType::get(Type::FloatTy, 4);
68
69 m_llvmFSqrt = 0;
70 m_llvmFAbs = 0;
71 m_llvmPow = 0;
72 m_llvmFloor = 0;
73 m_llvmFlog = 0;
74 m_llvmLit = 0;
75 m_fmtPtr = 0;
76
77 createGallivmBuiltins(m_mod);
78 }
79
80 llvm::Value * Instructions::add(llvm::Value *in1, llvm::Value *in2)
81 {
82 return m_builder.CreateAdd(in1, in2, name("add"));
83 }
84
85 llvm::Value * Instructions::madd(llvm::Value *in1, llvm::Value *in2,
86 llvm::Value *in3)
87 {
88 Value *mulRes = mul(in1, in2);
89 return add(mulRes, in3);
90 }
91
92 llvm::Value * Instructions::mul(llvm::Value *in1, llvm::Value *in2)
93 {
94 return m_builder.CreateMul(in1, in2, name("mul"));
95 }
96
97 const char * Instructions::name(const char *prefix)
98 {
99 ++m_idx;
100 snprintf(m_name, 32, "%s%d", prefix, m_idx);
101 return m_name;
102 }
103
104 llvm::Value * Instructions::dp3(llvm::Value *in1, llvm::Value *in2)
105 {
106 Value *mulRes = mul(in1, in2);
107 Value *x = m_builder.CreateExtractElement(mulRes,
108 m_storage->constantInt(0),
109 name("extractx"));
110 Value *y = m_builder.CreateExtractElement(mulRes,
111 m_storage->constantInt(1),
112 name("extracty"));
113 Value *z = m_builder.CreateExtractElement(mulRes,
114 m_storage->constantInt(2),
115 name("extractz"));
116 Value *xy = m_builder.CreateAdd(x, y,name("xy"));
117 Value *dot3 = m_builder.CreateAdd(xy, z, name("dot3"));
118 return vectorFromVals(dot3, dot3, dot3, dot3);
119 }
120
121 llvm::Value *Instructions::callFSqrt(llvm::Value *val)
122 {
123 if (!m_llvmFSqrt) {
124 // predeclare the intrinsic
125 std::vector<const Type*> fsqrtArgs;
126 fsqrtArgs.push_back(Type::FloatTy);
127 ParamAttrsList *fsqrtPal = 0;
128 FunctionType* fsqrtType = FunctionType::get(
129 /*Result=*/Type::FloatTy,
130 /*Params=*/fsqrtArgs,
131 /*isVarArg=*/false);
132 m_llvmFSqrt = new Function(
133 /*Type=*/fsqrtType,
134 /*Linkage=*/GlobalValue::ExternalLinkage,
135 /*Name=*/"llvm.sqrt.f32", m_mod);
136 m_llvmFSqrt->setCallingConv(CallingConv::C);
137 m_llvmFSqrt->setParamAttrs(fsqrtPal);
138 }
139 CallInst *call = m_builder.CreateCall(m_llvmFSqrt, val,
140 name("sqrt"));
141 call->setCallingConv(CallingConv::C);
142 call->setTailCall(false);
143 return call;
144 }
145
146 llvm::Value * Instructions::rsq(llvm::Value *in1)
147 {
148 Value *x = m_builder.CreateExtractElement(in1,
149 m_storage->constantInt(0),
150 name("extractx"));
151 Value *abs = callFAbs(x);
152 Value *sqrt = callFSqrt(abs);
153
154 Value *rsqrt = m_builder.CreateFDiv(ConstantFP::get(Type::FloatTy,
155 APFloat(1.f)),
156 sqrt,
157 name("rsqrt"));
158 return vectorFromVals(rsqrt, rsqrt, rsqrt, rsqrt);
159 }
160
161 llvm::Value * Instructions::vectorFromVals(llvm::Value *x, llvm::Value *y,
162 llvm::Value *z, llvm::Value *w)
163 {
164 Constant *const_vec = Constant::getNullValue(m_floatVecType);
165 Value *res = m_builder.CreateInsertElement(const_vec, x,
166 m_storage->constantInt(0),
167 name("vecx"));
168 res = m_builder.CreateInsertElement(res, y, m_storage->constantInt(1),
169 name("vecxy"));
170 res = m_builder.CreateInsertElement(res, z, m_storage->constantInt(2),
171 name("vecxyz"));
172 if (w)
173 res = m_builder.CreateInsertElement(res, w, m_storage->constantInt(3),
174 name("vecxyzw"));
175 return res;
176 }
177
178 llvm::Value *Instructions::callFAbs(llvm::Value *val)
179 {
180 if (!m_llvmFAbs) {
181 // predeclare the intrinsic
182 std::vector<const Type*> fabsArgs;
183 fabsArgs.push_back(Type::FloatTy);
184 ParamAttrsList *fabsPal = 0;
185 FunctionType* fabsType = FunctionType::get(
186 /*Result=*/Type::FloatTy,
187 /*Params=*/fabsArgs,
188 /*isVarArg=*/false);
189 m_llvmFAbs = new Function(
190 /*Type=*/fabsType,
191 /*Linkage=*/GlobalValue::ExternalLinkage,
192 /*Name=*/"fabs", m_mod);
193 m_llvmFAbs->setCallingConv(CallingConv::C);
194 m_llvmFAbs->setParamAttrs(fabsPal);
195 }
196 CallInst *call = m_builder.CreateCall(m_llvmFAbs, val,
197 name("fabs"));
198 call->setCallingConv(CallingConv::C);
199 call->setTailCall(false);
200 return call;
201 }
202
203 llvm::Value * Instructions::lit(llvm::Value *in)
204 {
205 if (!m_llvmLit) {
206 m_llvmLit = m_mod->getFunction("lit");
207 }
208 CallInst *call = m_builder.CreateCall(m_llvmLit, in, name("litres"));
209 call->setCallingConv(CallingConv::C);
210 call->setTailCall(false);
211 return call;
212 }
213
214 llvm::Value * Instructions::sub(llvm::Value *in1, llvm::Value *in2)
215 {
216 Value *res = m_builder.CreateSub(in1, in2, name("sub"));
217 return res;
218 }
219
220 llvm::Value * Instructions::callPow(llvm::Value *val1, llvm::Value *val2)
221 {
222 if (!m_llvmPow) {
223 // predeclare the intrinsic
224 std::vector<const Type*> powArgs;
225 powArgs.push_back(Type::FloatTy);
226 powArgs.push_back(Type::FloatTy);
227 ParamAttrsList *powPal = 0;
228 FunctionType* powType = FunctionType::get(
229 /*Result=*/Type::FloatTy,
230 /*Params=*/powArgs,
231 /*isVarArg=*/false);
232 m_llvmPow = new Function(
233 /*Type=*/powType,
234 /*Linkage=*/GlobalValue::ExternalLinkage,
235 /*Name=*/"llvm.pow.f32", m_mod);
236 m_llvmPow->setCallingConv(CallingConv::C);
237 m_llvmPow->setParamAttrs(powPal);
238 }
239 std::vector<Value*> params;
240 params.push_back(val1);
241 params.push_back(val2);
242 CallInst *call = m_builder.CreateCall(m_llvmPow, params.begin(), params.end(),
243 name("pow"));
244 call->setCallingConv(CallingConv::C);
245 call->setTailCall(false);
246 return call;
247 }
248
249 llvm::Value * Instructions::pow(llvm::Value *in1, llvm::Value *in2)
250 {
251 Value *x1 = m_builder.CreateExtractElement(in1,
252 m_storage->constantInt(0),
253 name("x1"));
254 Value *x2 = m_builder.CreateExtractElement(in2,
255 m_storage->constantInt(0),
256 name("x2"));
257 llvm::Value *val = callPow(x1, x2);
258 return vectorFromVals(val, val, val, val);
259 }
260
261 llvm::Value * Instructions::rcp(llvm::Value *in1)
262 {
263 Value *x1 = m_builder.CreateExtractElement(in1,
264 m_storage->constantInt(0),
265 name("x1"));
266 Value *res = m_builder.CreateFDiv(ConstantFP::get(Type::FloatTy,
267 APFloat(1.f)),
268 x1, name("rcp"));
269 return vectorFromVals(res, res, res, res);
270 }
271
272 llvm::Value * Instructions::dp4(llvm::Value *in1, llvm::Value *in2)
273 {
274 Value *mulRes = mul(in1, in2);
275 std::vector<llvm::Value*> vec = extractVector(mulRes);
276 Value *xy = m_builder.CreateAdd(vec[0], vec[1], name("xy"));
277 Value *xyz = m_builder.CreateAdd(xy, vec[2], name("xyz"));
278 Value *dot4 = m_builder.CreateAdd(xyz, vec[3], name("dot4"));
279 return vectorFromVals(dot4, dot4, dot4, dot4);
280 }
281
282 llvm::Value * Instructions::dph(llvm::Value *in1, llvm::Value *in2)
283 {
284 Value *mulRes = mul(in1, in2);
285 std::vector<llvm::Value*> vec1 = extractVector(mulRes);
286 Value *xy = m_builder.CreateAdd(vec1[0], vec1[1], name("xy"));
287 Value *xyz = m_builder.CreateAdd(xy, vec1[2], name("xyz"));
288 Value *dph = m_builder.CreateAdd(xyz, vec1[3], name("dph"));
289 return vectorFromVals(dph, dph, dph, dph);
290 }
291
292 llvm::Value * Instructions::dst(llvm::Value *in1, llvm::Value *in2)
293 {
294 Value *y1 = m_builder.CreateExtractElement(in1,
295 m_storage->constantInt(1),
296 name("y1"));
297 Value *z = m_builder.CreateExtractElement(in1,
298 m_storage->constantInt(2),
299 name("z"));
300 Value *y2 = m_builder.CreateExtractElement(in2,
301 m_storage->constantInt(1),
302 name("y2"));
303 Value *w = m_builder.CreateExtractElement(in2,
304 m_storage->constantInt(3),
305 name("w"));
306 Value *ry = m_builder.CreateMul(y1, y2, name("tyuy"));
307 return vectorFromVals(ConstantFP::get(Type::FloatTy, APFloat(1.f)),
308 ry, z, w);
309 }
310
311 llvm::Value * Instructions::ex2(llvm::Value *in)
312 {
313 llvm::Value *val = callPow(ConstantFP::get(Type::FloatTy, APFloat(2.f)),
314 m_builder.CreateExtractElement(
315 in, m_storage->constantInt(0),
316 name("x1")));
317 return vectorFromVals(val, val, val, val);
318 }
319
320 llvm::Value * Instructions::callFloor(llvm::Value *val)
321 {
322 if (!m_llvmFloor) {
323 // predeclare the intrinsic
324 std::vector<const Type*> floorArgs;
325 floorArgs.push_back(Type::FloatTy);
326 ParamAttrsList *floorPal = 0;
327 FunctionType* floorType = FunctionType::get(
328 /*Result=*/Type::FloatTy,
329 /*Params=*/floorArgs,
330 /*isVarArg=*/false);
331 m_llvmFloor = new Function(
332 /*Type=*/floorType,
333 /*Linkage=*/GlobalValue::ExternalLinkage,
334 /*Name=*/"floorf", m_mod);
335 m_llvmFloor->setCallingConv(CallingConv::C);
336 m_llvmFloor->setParamAttrs(floorPal);
337 }
338 CallInst *call = m_builder.CreateCall(m_llvmFloor, val,
339 name("floorf"));
340 call->setCallingConv(CallingConv::C);
341 call->setTailCall(false);
342 return call;
343 }
344
345 llvm::Value * Instructions::floor(llvm::Value *in)
346 {
347 std::vector<llvm::Value*> vec = extractVector(in);
348 return vectorFromVals(callFloor(vec[0]), callFloor(vec[1]),
349 callFloor(vec[2]), callFloor(vec[3]));
350 }
351
352 llvm::Value * Instructions::arl(llvm::Value *in)
353 {
354 return floor(in);
355 }
356
357 llvm::Value * Instructions::frc(llvm::Value *in)
358 {
359 llvm::Value *flr = floor(in);
360 return sub(in, flr);
361 }
362
363 llvm::Value * Instructions::callFLog(llvm::Value *val)
364 {
365 if (!m_llvmFlog) {
366 // predeclare the intrinsic
367 std::vector<const Type*> flogArgs;
368 flogArgs.push_back(Type::FloatTy);
369 ParamAttrsList *flogPal = 0;
370 FunctionType* flogType = FunctionType::get(
371 /*Result=*/Type::FloatTy,
372 /*Params=*/flogArgs,
373 /*isVarArg=*/false);
374 m_llvmFlog = new Function(
375 /*Type=*/flogType,
376 /*Linkage=*/GlobalValue::ExternalLinkage,
377 /*Name=*/"logf", m_mod);
378 m_llvmFlog->setCallingConv(CallingConv::C);
379 m_llvmFlog->setParamAttrs(flogPal);
380 }
381 CallInst *call = m_builder.CreateCall(m_llvmFlog, val,
382 name("logf"));
383 call->setCallingConv(CallingConv::C);
384 call->setTailCall(false);
385 return call;
386 }
387
388 llvm::Value * Instructions::lg2(llvm::Value *in)
389 {
390 std::vector<llvm::Value*> vec = extractVector(in);
391 llvm::Value *const_vec = constVector(1.442695f, 1.442695f,
392 1.442695f, 1.442695f);
393 return mul(vectorFromVals(callFLog(vec[0]), callFLog(vec[1]),
394 callFLog(vec[2]), callFLog(vec[3])), const_vec);
395 }
396
397 llvm::Value * Instructions::min(llvm::Value *in1, llvm::Value *in2)
398 {
399 std::vector<llvm::Value*> vec1 = extractVector(in1);
400 std::vector<llvm::Value*> vec2 = extractVector(in2);
401
402 Value *xcmp = m_builder.CreateFCmpOLT(vec1[0], vec2[0], name("xcmp"));
403 Value *selx = m_builder.CreateSelect(xcmp, vec1[0], vec2[0],
404 name("selx"));
405
406 Value *ycmp = m_builder.CreateFCmpOLT(vec1[1], vec2[1], name("ycmp"));
407 Value *sely = m_builder.CreateSelect(ycmp, vec1[1], vec2[1],
408 name("sely"));
409
410 Value *zcmp = m_builder.CreateFCmpOLT(vec1[2], vec2[2], name("zcmp"));
411 Value *selz = m_builder.CreateSelect(zcmp, vec1[2], vec2[2],
412 name("selz"));
413
414 Value *wcmp = m_builder.CreateFCmpOLT(vec1[3], vec2[3], name("wcmp"));
415 Value *selw = m_builder.CreateSelect(wcmp, vec1[3], vec2[3],
416 name("selw"));
417
418 return vectorFromVals(selx, sely, selz, selw);
419 }
420
421 llvm::Value * Instructions::max(llvm::Value *in1, llvm::Value *in2)
422 {
423 std::vector<llvm::Value*> vec1 = extractVector(in1);
424 std::vector<llvm::Value*> vec2 = extractVector(in2);
425
426 Value *xcmp = m_builder.CreateFCmpOGT(vec1[0], vec2[0],
427 name("xcmp"));
428 Value *selx = m_builder.CreateSelect(xcmp, vec1[0], vec2[0],
429 name("selx"));
430
431 Value *ycmp = m_builder.CreateFCmpOGT(vec1[1], vec2[1],
432 name("ycmp"));
433 Value *sely = m_builder.CreateSelect(ycmp, vec1[1], vec2[1],
434 name("sely"));
435
436 Value *zcmp = m_builder.CreateFCmpOGT(vec1[2], vec2[2],
437 name("zcmp"));
438 Value *selz = m_builder.CreateSelect(zcmp, vec1[2], vec2[2],
439 name("selz"));
440
441 Value *wcmp = m_builder.CreateFCmpOGT(vec1[3], vec2[3],
442 name("wcmp"));
443 Value *selw = m_builder.CreateSelect(wcmp, vec1[3], vec2[3],
444 name("selw"));
445
446 return vectorFromVals(selx, sely, selz, selw);
447 }
448
449 void Instructions::printVector(llvm::Value *val)
450 {
451 static const char *frmt = "Vector is [%f, %f, %f, %f]\x0A";
452
453 if (!m_fmtPtr) {
454 Constant *format = ConstantArray::get(frmt, true);
455 ArrayType *arrayTy = ArrayType::get(IntegerType::get(8), strlen(frmt) + 1);
456 GlobalVariable* globalFormat = new GlobalVariable(
457 /*Type=*/arrayTy,
458 /*isConstant=*/true,
459 /*Linkage=*/GlobalValue::InternalLinkage,
460 /*Initializer=*/0, // has initializer, specified below
461 /*Name=*/name(".str"),
462 m_mod);
463 globalFormat->setInitializer(format);
464
465 Constant* const_int0 = Constant::getNullValue(IntegerType::get(32));
466 std::vector<Constant*> const_ptr_21_indices;
467 const_ptr_21_indices.push_back(const_int0);
468 const_ptr_21_indices.push_back(const_int0);
469 m_fmtPtr = ConstantExpr::getGetElementPtr(globalFormat,
470 &const_ptr_21_indices[0], const_ptr_21_indices.size());
471 }
472
473 Function *func_printf = m_mod->getFunction("printf");
474 if (!func_printf)
475 func_printf = declarePrintf();
476 assert(func_printf);
477 std::vector<llvm::Value*> vec = extractVector(val);
478 Value *dx = m_builder.CreateFPExt(vec[0], Type::DoubleTy, name("dx"));
479 Value *dy = m_builder.CreateFPExt(vec[1], Type::DoubleTy, name("dy"));
480 Value *dz = m_builder.CreateFPExt(vec[2], Type::DoubleTy, name("dz"));
481 Value *dw = m_builder.CreateFPExt(vec[3], Type::DoubleTy, name("dw"));
482 std::vector<Value*> params;
483 params.push_back(m_fmtPtr);
484 params.push_back(dx);
485 params.push_back(dy);
486 params.push_back(dz);
487 params.push_back(dw);
488 CallInst *call = m_builder.CreateCall(func_printf, params.begin(), params.end(),
489 name("printf"));
490 call->setCallingConv(CallingConv::C);
491 call->setTailCall(true);
492 }
493
494 llvm::Function * Instructions::declarePrintf()
495 {
496 std::vector<const Type*> args;
497 ParamAttrsList *params = 0;
498 FunctionType* funcTy = FunctionType::get(
499 /*Result=*/IntegerType::get(32),
500 /*Params=*/args,
501 /*isVarArg=*/true);
502 Function* func_printf = new Function(
503 /*Type=*/funcTy,
504 /*Linkage=*/GlobalValue::ExternalLinkage,
505 /*Name=*/"printf", m_mod);
506 func_printf->setCallingConv(CallingConv::C);
507 func_printf->setParamAttrs(params);
508 return func_printf;
509 }
510
511
512 llvm::Value * Instructions::sgt(llvm::Value *in1, llvm::Value *in2)
513 {
514 Constant *const1f = ConstantFP::get(Type::FloatTy, APFloat(1.000000e+00f));
515 Constant *const0f = Constant::getNullValue(Type::FloatTy);
516
517 std::vector<llvm::Value*> vec1 = extractVector(in1);
518 std::vector<llvm::Value*> vec2 = extractVector(in2);
519 Value *xcmp = m_builder.CreateFCmpOGT(vec1[0], vec2[0], name("xcmp"));
520 Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
521
522 Value *ycmp = m_builder.CreateFCmpOGT(vec1[1], vec2[1], name("ycmp"));
523 Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
524
525 Value *zcmp = m_builder.CreateFCmpOGT(vec1[2], vec2[2], name("zcmp"));
526 Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
527
528 Value *wcmp = m_builder.CreateFCmpOGT(vec1[3], vec2[3], name("wcmp"));
529 Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel"));
530
531 return vectorFromVals(x, y, z, w);
532 }
533 llvm::Value * Instructions::sge(llvm::Value *in1, llvm::Value *in2)
534 {
535 Constant *const1f = ConstantFP::get(Type::FloatTy, APFloat(1.000000e+00f));
536 Constant *const0f = Constant::getNullValue(Type::FloatTy);
537
538 std::vector<llvm::Value*> vec1 = extractVector(in1);
539 std::vector<llvm::Value*> vec2 = extractVector(in2);
540
541 Value *xcmp = m_builder.CreateFCmpOGE(vec1[0], vec2[0], name("xcmp"));
542 Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
543
544 Value *ycmp = m_builder.CreateFCmpOGE(vec1[1], vec2[1], name("ycmp"));
545 Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
546
547 Value *zcmp = m_builder.CreateFCmpOGE(vec1[2], vec2[2], name("zcmp"));
548 Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
549
550 Value *wcmp = m_builder.CreateFCmpOGE(vec1[3], vec2[3], name("wcmp"));
551 Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel"));
552
553 return vectorFromVals(x, y, z, w);
554 }
555
556
557 llvm::Value * Instructions::slt(llvm::Value *in1, llvm::Value *in2)
558 {
559 Constant *const1f = ConstantFP::get(Type::FloatTy, APFloat(1.000000e+00f));
560 Constant *const0f = Constant::getNullValue(Type::FloatTy);
561
562 std::vector<llvm::Value*> vec1 = extractVector(in1);
563 std::vector<llvm::Value*> vec2 = extractVector(in2);
564
565 Value *xcmp = m_builder.CreateFCmpOLT(vec1[0], vec2[0], name("xcmp"));
566 Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
567
568 Value *ycmp = m_builder.CreateFCmpOLT(vec1[1], vec2[1], name("ycmp"));
569 Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
570
571 Value *zcmp = m_builder.CreateFCmpOLT(vec1[2], vec2[2], name("zcmp"));
572 Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
573
574 Value *wcmp = m_builder.CreateFCmpOLT(vec1[3], vec2[3], name("wcmp"));
575 Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel"));
576
577 return vectorFromVals(x, y, z, w);
578 }
579
580 llvm::Value * Instructions::cross(llvm::Value *in1, llvm::Value *in2)
581 {
582 Value *x1 = m_builder.CreateExtractElement(in1,
583 m_storage->constantInt(0),
584 name("x1"));
585 Value *y1 = m_builder.CreateExtractElement(in1,
586 m_storage->constantInt(1),
587 name("y1"));
588 Value *z1 = m_builder.CreateExtractElement(in1,
589 m_storage->constantInt(2),
590 name("z1"));
591
592 Value *x2 = m_builder.CreateExtractElement(in2,
593 m_storage->constantInt(0),
594 name("x2"));
595 Value *y2 = m_builder.CreateExtractElement(in2,
596 m_storage->constantInt(1),
597 name("y2"));
598 Value *z2 = m_builder.CreateExtractElement(in2,
599 m_storage->constantInt(2),
600 name("z2"));
601 Value *y1z2 = mul(y1, z2);
602 Value *z1y2 = mul(z1, y2);
603
604 Value *z1x2 = mul(z1, x2);
605 Value *x1z2 = mul(x1, z2);
606
607 Value *x1y2 = mul(x1, y2);
608 Value *y1x2 = mul(y1, x2);
609
610 return vectorFromVals(sub(y1z2, z1y2), sub(z1x2, x1z2), sub(x1y2, y1x2));
611 }
612
613
614 llvm::Value * Instructions::abs(llvm::Value *in)
615 {
616 std::vector<llvm::Value*> vec = extractVector(in);
617 Value *xabs = callFAbs(vec[0]);
618 Value *yabs = callFAbs(vec[1]);
619 Value *zabs = callFAbs(vec[2]);
620 Value *wabs = callFAbs(vec[3]);
621 return vectorFromVals(xabs, yabs, zabs, wabs);
622 }
623
624 void Instructions::ifop(llvm::Value *in)
625 {
626 BasicBlock *ifthen = new BasicBlock(name("ifthen"), m_func,0);
627 BasicBlock *ifend = new BasicBlock(name("ifthenend"), m_func,0);
628
629 //BasicBlock *yblock = new BasicBlock(name("yblock"), m_func,0);
630 //BasicBlock *zblock = new BasicBlock(name("zblock"), m_func,0);
631 //BasicBlock *wblock = new BasicBlock(name("wblock"), m_func,0);
632
633 Constant *float0 = Constant::getNullValue(Type::FloatTy);
634
635 Value *x = m_builder.CreateExtractElement(in, m_storage->constantInt(0),
636 name("extractx"));
637 Value *xcmp = m_builder.CreateFCmpUNE(x, float0, name("xcmp"));
638 m_builder.CreateCondBr(xcmp, ifthen, ifend);
639 //m_builder.SetInsertPoint(yblock);
640
641 m_builder.SetInsertPoint(ifthen);
642 m_ifStack.push(ifend);
643 }
644
645 llvm::BasicBlock * Instructions::currentBlock() const
646 {
647 return m_builder.GetInsertBlock();
648 }
649
650 void Instructions::elseop()
651 {
652 assert(!m_ifStack.empty());
653 BasicBlock *ifend = new BasicBlock(name("ifend"), m_func,0);
654 m_builder.CreateBr(ifend);
655 m_builder.SetInsertPoint(m_ifStack.top());
656 currentBlock()->setName(name("ifelse"));
657 m_ifStack.pop();
658 m_ifStack.push(ifend);
659 }
660
661 void Instructions::endif()
662 {
663 assert(!m_ifStack.empty());
664 m_builder.CreateBr(m_ifStack.top());
665 m_builder.SetInsertPoint(m_ifStack.top());
666 m_ifStack.pop();
667 }
668
669 llvm::Value * Instructions::lerp(llvm::Value *in1, llvm::Value *in2,
670 llvm::Value *in3)
671 {
672 llvm::Value *m = mul(in1, in2);
673 llvm::Value *vec1 = constVector(1.f, 1.f, 1.f, 1.f);
674 llvm::Value *s = sub(vec1, in1);
675 return add(m, mul(s, in3));
676 }
677
678 void Instructions::beginLoop()
679 {
680 BasicBlock *begin = new BasicBlock(name("loop"), m_func,0);
681 BasicBlock *end = new BasicBlock(name("endloop"), m_func,0);
682
683 m_builder.CreateBr(begin);
684 Loop loop;
685 loop.begin = begin;
686 loop.end = end;
687 m_builder.SetInsertPoint(begin);
688 m_loopStack.push(loop);
689 }
690
691 void Instructions::endLoop()
692 {
693 assert(!m_loopStack.empty());
694 Loop loop = m_loopStack.top();
695 m_builder.CreateBr(loop.begin);
696 loop.end->moveAfter(currentBlock());
697 m_builder.SetInsertPoint(loop.end);
698 m_loopStack.pop();
699 }
700
701 void Instructions::brk()
702 {
703 assert(!m_loopStack.empty());
704 BasicBlock *unr = new BasicBlock(name("unreachable"), m_func,0);
705 m_builder.CreateBr(m_loopStack.top().end);
706 m_builder.SetInsertPoint(unr);
707 }
708
709 llvm::Value * Instructions::trunc(llvm::Value *in)
710 {
711 std::vector<llvm::Value*> vec = extractVector(in);
712 Value *icastx = m_builder.CreateFPToSI(vec[0], IntegerType::get(32),
713 name("ftoix"));
714 Value *icasty = m_builder.CreateFPToSI(vec[1], IntegerType::get(32),
715 name("ftoiy"));
716 Value *icastz = m_builder.CreateFPToSI(vec[2], IntegerType::get(32),
717 name("ftoiz"));
718 Value *icastw = m_builder.CreateFPToSI(vec[3], IntegerType::get(32),
719 name("ftoiw"));
720 Value *fx = m_builder.CreateSIToFP(icastx, Type::FloatTy,
721 name("fx"));
722 Value *fy = m_builder.CreateSIToFP(icasty, Type::FloatTy,
723 name("fy"));
724 Value *fz = m_builder.CreateSIToFP(icastz, Type::FloatTy,
725 name("fz"));
726 Value *fw = m_builder.CreateSIToFP(icastw, Type::FloatTy,
727 name("fw"));
728 return vectorFromVals(fx, fy, fz, fw);
729 }
730
731 void Instructions::end()
732 {
733 m_builder.CreateRetVoid();
734 }
735
736 void Instructions::cal(int label, llvm::Value *input)
737 {
738 std::vector<Value*> params;
739 params.push_back(input);
740 llvm::Function *func = findFunction(label);
741
742 m_builder.CreateCall(func, params.begin(), params.end());
743 }
744
745 llvm::Function * Instructions::declareFunc(int label)
746 {
747 PointerType *vecPtr = PointerType::getUnqual(m_floatVecType);
748 std::vector<const Type*> args;
749 args.push_back(vecPtr);
750 args.push_back(vecPtr);
751 args.push_back(vecPtr);
752 args.push_back(vecPtr);
753 ParamAttrsList *params = 0;
754 FunctionType *funcType = FunctionType::get(
755 /*Result=*/Type::VoidTy,
756 /*Params=*/args,
757 /*isVarArg=*/false);
758 std::string name = createFuncName(label);
759 Function *func = new Function(
760 /*Type=*/funcType,
761 /*Linkage=*/GlobalValue::ExternalLinkage,
762 /*Name=*/name.c_str(), m_mod);
763 func->setCallingConv(CallingConv::C);
764 func->setParamAttrs(params);
765 return func;
766 }
767
768 void Instructions::bgnSub(unsigned label)
769 {
770 llvm::Function *func = findFunction(label);
771
772 Function::arg_iterator args = func->arg_begin();
773 Value *ptr_INPUT = args++;
774 ptr_INPUT->setName("INPUT");
775 m_storage->pushArguments(ptr_INPUT);
776
777 llvm::BasicBlock *entry = new BasicBlock("entry", func, 0);
778
779 m_func = func;
780 m_builder.SetInsertPoint(entry);
781 }
782
783 void Instructions::endSub()
784 {
785 m_func = 0;
786 m_builder.SetInsertPoint(0);
787 }
788
789 llvm::Function * Instructions::findFunction(int label)
790 {
791 llvm::Function *func = m_functions[label];
792 if (!func) {
793 func = declareFunc(label);
794 m_functions[label] = func;
795 }
796 return func;
797 }
798
799 llvm::Value * Instructions::constVector(float x, float y, float z, float w)
800 {
801 std::vector<Constant*> vec(4);
802 vec[0] = ConstantFP::get(Type::FloatTy, APFloat(x));
803 vec[1] = ConstantFP::get(Type::FloatTy, APFloat(y));
804 vec[2] = ConstantFP::get(Type::FloatTy, APFloat(z));
805 vec[3] = ConstantFP::get(Type::FloatTy, APFloat(w));
806 return ConstantVector::get(m_floatVecType, vec);
807 }
808
809
810 std::vector<llvm::Value*> Instructions::extractVector(llvm::Value *vec)
811 {
812 std::vector<llvm::Value*> elems(4);
813 elems[0] = m_builder.CreateExtractElement(vec, m_storage->constantInt(0),
814 name("x"));
815 elems[1] = m_builder.CreateExtractElement(vec, m_storage->constantInt(1),
816 name("y"));
817 elems[2] = m_builder.CreateExtractElement(vec, m_storage->constantInt(2),
818 name("z"));
819 elems[3] = m_builder.CreateExtractElement(vec, m_storage->constantInt(3),
820 name("w"));
821 return elems;
822 }
823
824 llvm::Value * Instructions::cmp(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3)
825 {
826 llvm::Function *func = m_mod->getFunction("cmp");
827 assert(func);
828
829 std::vector<Value*> params;
830 params.push_back(in1);
831 params.push_back(in2);
832 params.push_back(in3);
833 CallInst *call = m_builder.CreateCall(func, params.begin(), params.end(), name("cmpres"));
834 call->setTailCall(false);
835 return call;
836 }
837
838 llvm::Value * Instructions::cos(llvm::Value *in)
839 {
840 #if 0
841 llvm::Function *func = m_mod->getFunction("vcos");
842 assert(func);
843
844 CallInst *call = m_builder.CreateCall(func, in, name("cosres"));
845 call->setTailCall(false);
846 return call;
847 #else
848 std::vector<llvm::Value*> elems = extractVector(in);
849 Function *func = m_mod->getFunction("cosf");
850 assert(func);
851 CallInst *cos = m_builder.CreateCall(func, elems[0], name("cosres"));
852 cos->setCallingConv(CallingConv::C);
853 cos->setTailCall(true);
854 return vectorFromVals(cos, cos, cos, cos);
855 #endif
856 }
857
858 llvm::Value * Instructions::scs(llvm::Value *in)
859 {
860 llvm::Function *func = m_mod->getFunction("scs");
861 assert(func);
862
863 CallInst *call = m_builder.CreateCall(func, in, name("scsres"));
864 call->setTailCall(false);
865 return call;
866 }
867
868 llvm::Value * Instructions::kilp(llvm::Value *in)
869 {
870 llvm::Function *func = m_mod->getFunction("kilp");
871 assert(func);
872
873 CallInst *call = m_builder.CreateCall(func, in, name("kilpres"));
874 call->setTailCall(false);
875 return call;
876 }
877
878 llvm::Value * Instructions::sin(llvm::Value *in)
879 {
880 llvm::Function *func = m_mod->getFunction("vsin");
881 assert(func);
882
883 CallInst *call = m_builder.CreateCall(func, in, name("sinres"));
884 call->setTailCall(false);
885 return call;
886 }
887 #endif //MESA_LLVM
888
889