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