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