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