Gallivm: make it compile again, add some opcodes.
[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_llvmFexp = 0;
87 m_llvmLit = 0;
88 m_fmtPtr = 0;
89
90 MemoryBuffer *buffer = MemoryBuffer::getMemBuffer(
91 (const char*)&llvm_builtins_data[0],
92 (const char*)&llvm_builtins_data[Elements(llvm_builtins_data)-1]);
93 m_mod = ParseBitcodeFile(buffer);
94 }
95
96 llvm::BasicBlock * Instructions::currentBlock() const
97 {
98 return m_builder.GetInsertBlock();
99 }
100
101 llvm::Value * Instructions::abs(llvm::Value *in)
102 {
103 std::vector<llvm::Value*> vec = extractVector(in);
104 Value *xabs = callFAbs(vec[0]);
105 Value *yabs = callFAbs(vec[1]);
106 Value *zabs = callFAbs(vec[2]);
107 Value *wabs = callFAbs(vec[3]);
108 return vectorFromVals(xabs, yabs, zabs, wabs);
109 }
110
111 llvm::Value * Instructions::add(llvm::Value *in1, llvm::Value *in2)
112 {
113 return m_builder.CreateAdd(in1, in2, name("add"));
114 }
115
116 llvm::Value * Instructions::arl(llvm::Value *in)
117 {
118 return floor(in);
119 }
120
121 void Instructions::beginLoop()
122 {
123 BasicBlock *begin = BasicBlock::Create(name("loop"), m_func,0);
124 BasicBlock *end = BasicBlock::Create(name("endloop"), m_func,0);
125
126 m_builder.CreateBr(begin);
127 Loop loop;
128 loop.begin = begin;
129 loop.end = end;
130 m_builder.SetInsertPoint(begin);
131 m_loopStack.push(loop);
132 }
133
134 void Instructions::bgnSub(unsigned label)
135 {
136 llvm::Function *func = findFunction(label);
137
138 Function::arg_iterator args = func->arg_begin();
139 Value *ptr_INPUT = args++;
140 ptr_INPUT->setName("INPUT");
141 m_storage->pushArguments(ptr_INPUT);
142
143 llvm::BasicBlock *entry = BasicBlock::Create("entry", func, 0);
144
145 m_func = func;
146 m_builder.SetInsertPoint(entry);
147 }
148
149 void Instructions::brk()
150 {
151 assert(!m_loopStack.empty());
152 BasicBlock *unr = BasicBlock::Create(name("unreachable"), m_func,0);
153 m_builder.CreateBr(m_loopStack.top().end);
154 m_builder.SetInsertPoint(unr);
155 }
156
157 void Instructions::cal(int label, llvm::Value *input)
158 {
159 std::vector<Value*> params;
160 params.push_back(input);
161 llvm::Function *func = findFunction(label);
162
163 m_builder.CreateCall(func, params.begin(), params.end());
164 }
165
166 llvm::Value * Instructions::clamp(llvm::Value *in1)
167 {
168 // FIXME
169 }
170
171 llvm::Value * Instructions::cmp(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3)
172 {
173 llvm::Function *func = m_mod->getFunction("cmp");
174 assert(func);
175
176 std::vector<Value*> params;
177 params.push_back(in1);
178 params.push_back(in2);
179 params.push_back(in3);
180 CallInst *call = m_builder.CreateCall(func, params.begin(), params.end(), name("cmpres"));
181 call->setTailCall(false);
182 return call;
183 }
184
185 llvm::Value * Instructions::cnd(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3)
186 {
187 std::vector<llvm::Value*> vec1 = extractVector(in1);
188 std::vector<llvm::Value*> vec2 = extractVector(in2);
189 std::vector<llvm::Value*> vec3 = extractVector(in3);
190 Constant *half = ConstantFP::get(APFloat(0.5f));
191
192 Value *xcmp = m_builder.CreateFCmpOGT(vec1[0], half, name("xcmp"));
193 Value *selx = m_builder.CreateSelect(xcmp, vec2[0], vec3[0],
194 name("selx"));
195
196 Value *ycmp = m_builder.CreateFCmpOGT(vec1[1], half, name("ycmp"));
197 Value *sely = m_builder.CreateSelect(ycmp, vec2[1], vec3[1],
198 name("sely"));
199
200 Value *zcmp = m_builder.CreateFCmpOGT(vec1[2], half, name("zcmp"));
201 Value *selz = m_builder.CreateSelect(zcmp, vec2[2], vec3[2],
202 name("selz"));
203
204 Value *wcmp = m_builder.CreateFCmpOGT(vec1[3], half, name("wcmp"));
205 Value *selw = m_builder.CreateSelect(wcmp, vec2[3], vec3[3],
206 name("selw"));
207
208 return vectorFromVals(selx, sely, selz, selw);
209 }
210
211 llvm::Value * Instructions::cnd0(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3)
212 {
213 std::vector<llvm::Value*> vec1 = extractVector(in1);
214 std::vector<llvm::Value*> vec2 = extractVector(in2);
215 std::vector<llvm::Value*> vec3 = extractVector(in3);
216 Constant *zero = Constant::getNullValue(Type::FloatTy);
217
218 Value *xcmp = m_builder.CreateFCmpOGE(vec1[0], zero, name("xcmp"));
219 Value *selx = m_builder.CreateSelect(xcmp, vec2[0], vec3[0],
220 name("selx"));
221
222 Value *ycmp = m_builder.CreateFCmpOGE(vec1[1], zero, name("ycmp"));
223 Value *sely = m_builder.CreateSelect(ycmp, vec2[1], vec3[1],
224 name("sely"));
225
226 Value *zcmp = m_builder.CreateFCmpOGE(vec1[2], zero, name("zcmp"));
227 Value *selz = m_builder.CreateSelect(zcmp, vec2[2], vec3[2],
228 name("selz"));
229
230 Value *wcmp = m_builder.CreateFCmpOGE(vec1[3], zero, name("wcmp"));
231 Value *selw = m_builder.CreateSelect(wcmp, vec2[3], vec3[3],
232 name("selw"));
233
234 return vectorFromVals(selx, sely, selz, selw);
235 }
236
237 llvm::Value * Instructions::cos(llvm::Value *in)
238 {
239 #if 0
240 llvm::Function *func = m_mod->getFunction("vcos");
241 assert(func);
242
243 CallInst *call = m_builder.CreateCall(func, in, name("cosres"));
244 call->setTailCall(false);
245 return call;
246 #else
247 std::vector<llvm::Value*> elems = extractVector(in);
248 Function *func = m_mod->getFunction("cosf");
249 assert(func);
250 CallInst *cos = m_builder.CreateCall(func, elems[0], name("cosres"));
251 cos->setCallingConv(CallingConv::C);
252 cos->setTailCall(true);
253 return vectorFromVals(cos, cos, cos, cos);
254 #endif
255 }
256
257 llvm::Value * Instructions::cross(llvm::Value *in1, llvm::Value *in2)
258 {
259 Value *x1 = m_builder.CreateExtractElement(in1,
260 m_storage->constantInt(0),
261 name("x1"));
262 Value *y1 = m_builder.CreateExtractElement(in1,
263 m_storage->constantInt(1),
264 name("y1"));
265 Value *z1 = m_builder.CreateExtractElement(in1,
266 m_storage->constantInt(2),
267 name("z1"));
268
269 Value *x2 = m_builder.CreateExtractElement(in2,
270 m_storage->constantInt(0),
271 name("x2"));
272 Value *y2 = m_builder.CreateExtractElement(in2,
273 m_storage->constantInt(1),
274 name("y2"));
275 Value *z2 = m_builder.CreateExtractElement(in2,
276 m_storage->constantInt(2),
277 name("z2"));
278 Value *y1z2 = mul(y1, z2);
279 Value *z1y2 = mul(z1, y2);
280
281 Value *z1x2 = mul(z1, x2);
282 Value *x1z2 = mul(x1, z2);
283
284 Value *x1y2 = mul(x1, y2);
285 Value *y1x2 = mul(y1, x2);
286
287 return vectorFromVals(sub(y1z2, z1y2), sub(z1x2, x1z2), sub(x1y2, y1x2));
288 }
289
290 llvm::Value * Instructions::ddx(llvm::Value *in)
291 {
292 // FIXME
293 }
294
295 llvm::Value * Instructions::ddy(llvm::Value *in)
296 {
297 // FIXME
298 }
299
300 llvm::Value * Instructions::div(llvm::Value *in1, llvm::Value *in2)
301 {
302 return m_builder.CreateFDiv(in1, in2, name("div"));
303 }
304
305 llvm::Value * Instructions::dot2add(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3)
306 {
307 Value *mulRes = mul(in1, in2);
308 Value *x = m_builder.CreateExtractElement(mulRes,
309 m_storage->constantInt(0),
310 name("extractx"));
311 Value *y = m_builder.CreateExtractElement(mulRes,
312 m_storage->constantInt(1),
313 name("extracty"));
314 Value *z = m_builder.CreateExtractElement(in3,
315 m_storage->constantInt(2),
316 name("extractz"));
317 Value *xy = m_builder.CreateAdd(x, y,name("xy"));
318 Value *dot2add = m_builder.CreateAdd(xy, z, name("dot2add"));
319 return vectorFromVals(dot2add, dot2add, dot2add, dot2add);
320 }
321
322 llvm::Value * Instructions::dp3(llvm::Value *in1, llvm::Value *in2)
323 {
324 Value *mulRes = mul(in1, in2);
325 Value *x = m_builder.CreateExtractElement(mulRes,
326 m_storage->constantInt(0),
327 name("extractx"));
328 Value *y = m_builder.CreateExtractElement(mulRes,
329 m_storage->constantInt(1),
330 name("extracty"));
331 Value *z = m_builder.CreateExtractElement(mulRes,
332 m_storage->constantInt(2),
333 name("extractz"));
334 Value *xy = m_builder.CreateAdd(x, y,name("xy"));
335 Value *dot3 = m_builder.CreateAdd(xy, z, name("dot3"));
336 return vectorFromVals(dot3, dot3, dot3, dot3);
337 }
338
339 llvm::Value * Instructions::dp4(llvm::Value *in1, llvm::Value *in2)
340 {
341 Value *mulRes = mul(in1, in2);
342 std::vector<llvm::Value*> vec = extractVector(mulRes);
343 Value *xy = m_builder.CreateAdd(vec[0], vec[1], name("xy"));
344 Value *xyz = m_builder.CreateAdd(xy, vec[2], name("xyz"));
345 Value *dot4 = m_builder.CreateAdd(xyz, vec[3], name("dot4"));
346 return vectorFromVals(dot4, dot4, dot4, dot4);
347 }
348
349 llvm::Value * Instructions::dph(llvm::Value *in1, llvm::Value *in2)
350 {
351 Value *mulRes = mul(in1, in2);
352 std::vector<llvm::Value*> vec1 = extractVector(mulRes);
353 Value *xy = m_builder.CreateAdd(vec1[0], vec1[1], name("xy"));
354 Value *xyz = m_builder.CreateAdd(xy, vec1[2], name("xyz"));
355 Value *dph = m_builder.CreateAdd(xyz, vec1[3], name("dph"));
356 return vectorFromVals(dph, dph, dph, dph);
357 }
358
359 llvm::Value * Instructions::dst(llvm::Value *in1, llvm::Value *in2)
360 {
361 Value *y1 = m_builder.CreateExtractElement(in1,
362 m_storage->constantInt(1),
363 name("y1"));
364 Value *z = m_builder.CreateExtractElement(in1,
365 m_storage->constantInt(2),
366 name("z"));
367 Value *y2 = m_builder.CreateExtractElement(in2,
368 m_storage->constantInt(1),
369 name("y2"));
370 Value *w = m_builder.CreateExtractElement(in2,
371 m_storage->constantInt(3),
372 name("w"));
373 Value *ry = m_builder.CreateMul(y1, y2, name("tyuy"));
374 return vectorFromVals(ConstantFP::get(APFloat(1.f)),
375 ry, z, w);
376 }
377
378 void Instructions::elseop()
379 {
380 assert(!m_ifStack.empty());
381 BasicBlock *ifend = BasicBlock::Create(name("ifend"), m_func,0);
382 m_builder.CreateBr(ifend);
383 m_builder.SetInsertPoint(m_ifStack.top());
384 currentBlock()->setName(name("ifelse"));
385 m_ifStack.pop();
386 m_ifStack.push(ifend);
387 }
388
389 void Instructions::endif()
390 {
391 assert(!m_ifStack.empty());
392 m_builder.CreateBr(m_ifStack.top());
393 m_builder.SetInsertPoint(m_ifStack.top());
394 m_ifStack.pop();
395 }
396
397 void Instructions::endLoop()
398 {
399 assert(!m_loopStack.empty());
400 Loop loop = m_loopStack.top();
401 m_builder.CreateBr(loop.begin);
402 loop.end->moveAfter(currentBlock());
403 m_builder.SetInsertPoint(loop.end);
404 m_loopStack.pop();
405 }
406
407 void Instructions::end()
408 {
409 m_builder.CreateRetVoid();
410 }
411
412 void Instructions::endSub()
413 {
414 m_func = 0;
415 m_builder.SetInsertPoint(0);
416 }
417
418 llvm::Value * Instructions::exp(llvm::Value *in)
419 {
420 std::vector<llvm::Value*> vec = extractVector(in);
421 return vectorFromVals(callFExp(vec[0]), callFExp(vec[1]),
422 callFExp(vec[2]), callFExp(vec[3]));
423 }
424
425 llvm::Value * Instructions::ex2(llvm::Value *in)
426 {
427 llvm::Value *val = callPow(ConstantFP::get(APFloat(2.f)),
428 m_builder.CreateExtractElement(
429 in, m_storage->constantInt(0),
430 name("x1")));
431 return vectorFromVals(val, val, val, val);
432 }
433
434 llvm::Value * Instructions::floor(llvm::Value *in)
435 {
436 std::vector<llvm::Value*> vec = extractVector(in);
437 return vectorFromVals(callFloor(vec[0]), callFloor(vec[1]),
438 callFloor(vec[2]), callFloor(vec[3]));
439 }
440
441 llvm::Value * Instructions::frc(llvm::Value *in)
442 {
443 llvm::Value *flr = floor(in);
444 return sub(in, flr);
445 }
446
447 void Instructions::ifop(llvm::Value *in)
448 {
449 BasicBlock *ifthen = BasicBlock::Create(name("ifthen"), m_func,0);
450 BasicBlock *ifend = BasicBlock::Create(name("ifthenend"), m_func,0);
451
452 //BasicBlock *yblock = new BasicBlock(name("yblock"), m_func,0);
453 //BasicBlock *zblock = new BasicBlock(name("zblock"), m_func,0);
454 //BasicBlock *wblock = new BasicBlock(name("wblock"), m_func,0);
455
456 Constant *float0 = Constant::getNullValue(Type::FloatTy);
457
458 Value *x = m_builder.CreateExtractElement(in, m_storage->constantInt(0),
459 name("extractx"));
460 Value *xcmp = m_builder.CreateFCmpUNE(x, float0, name("xcmp"));
461 m_builder.CreateCondBr(xcmp, ifthen, ifend);
462 //m_builder.SetInsertPoint(yblock);
463
464 m_builder.SetInsertPoint(ifthen);
465 m_ifStack.push(ifend);
466 }
467
468 llvm::Value * Instructions::kil(llvm::Value *in)
469 {
470 llvm::Function *func = m_mod->getFunction("kil");
471 assert(func);
472
473 CallInst *call = m_builder.CreateCall(func, in, name("kilpres"));
474 call->setTailCall(false);
475 return call;
476 }
477
478 llvm::Value * Instructions::lerp(llvm::Value *in1, llvm::Value *in2,
479 llvm::Value *in3)
480 {
481 llvm::Value *m = mul(in1, in2);
482 llvm::Value *vec1 = constVector(1.f, 1.f, 1.f, 1.f);
483 llvm::Value *s = sub(vec1, in1);
484 return add(m, mul(s, in3));
485 }
486
487 llvm::Value * Instructions::lg2(llvm::Value *in)
488 {
489 std::vector<llvm::Value*> vec = extractVector(in);
490 llvm::Value *const_vec = constVector(1.442695f, 1.442695f,
491 1.442695f, 1.442695f);
492 return mul(vectorFromVals(callFLog(vec[0]), callFLog(vec[1]),
493 callFLog(vec[2]), callFLog(vec[3])), const_vec);
494 }
495
496 llvm::Value * Instructions::lit(llvm::Value *in)
497 {
498 if (!m_llvmLit) {
499 m_llvmLit = m_mod->getFunction("lit");
500 }
501 CallInst *call = m_builder.CreateCall(m_llvmLit, in, name("litres"));
502 call->setCallingConv(CallingConv::C);
503 call->setTailCall(false);
504 return call;
505 }
506
507 llvm::Value * Instructions::log(llvm::Value *in)
508 {
509 std::vector<llvm::Value*> vec = extractVector(in);
510 return vectorFromVals(callFLog(vec[0]), callFLog(vec[1]),
511 callFLog(vec[2]), callFLog(vec[3]));
512 }
513
514 llvm::Value * Instructions::madd(llvm::Value *in1, llvm::Value *in2,
515 llvm::Value *in3)
516 {
517 Value *mulRes = mul(in1, in2);
518 return add(mulRes, in3);
519 }
520
521 llvm::Value * Instructions::max(llvm::Value *in1, llvm::Value *in2)
522 {
523 std::vector<llvm::Value*> vec1 = extractVector(in1);
524 std::vector<llvm::Value*> vec2 = extractVector(in2);
525
526 Value *xcmp = m_builder.CreateFCmpOGT(vec1[0], vec2[0],
527 name("xcmp"));
528 Value *selx = m_builder.CreateSelect(xcmp, vec1[0], vec2[0],
529 name("selx"));
530
531 Value *ycmp = m_builder.CreateFCmpOGT(vec1[1], vec2[1],
532 name("ycmp"));
533 Value *sely = m_builder.CreateSelect(ycmp, vec1[1], vec2[1],
534 name("sely"));
535
536 Value *zcmp = m_builder.CreateFCmpOGT(vec1[2], vec2[2],
537 name("zcmp"));
538 Value *selz = m_builder.CreateSelect(zcmp, vec1[2], vec2[2],
539 name("selz"));
540
541 Value *wcmp = m_builder.CreateFCmpOGT(vec1[3], vec2[3],
542 name("wcmp"));
543 Value *selw = m_builder.CreateSelect(wcmp, vec1[3], vec2[3],
544 name("selw"));
545
546 return vectorFromVals(selx, sely, selz, selw);
547 }
548
549 llvm::Value * Instructions::min(llvm::Value *in1, llvm::Value *in2)
550 {
551 std::vector<llvm::Value*> vec1 = extractVector(in1);
552 std::vector<llvm::Value*> vec2 = extractVector(in2);
553
554 Value *xcmp = m_builder.CreateFCmpOLT(vec1[0], vec2[0], name("xcmp"));
555 Value *selx = m_builder.CreateSelect(xcmp, vec1[0], vec2[0],
556 name("selx"));
557
558 Value *ycmp = m_builder.CreateFCmpOLT(vec1[1], vec2[1], name("ycmp"));
559 Value *sely = m_builder.CreateSelect(ycmp, vec1[1], vec2[1],
560 name("sely"));
561
562 Value *zcmp = m_builder.CreateFCmpOLT(vec1[2], vec2[2], name("zcmp"));
563 Value *selz = m_builder.CreateSelect(zcmp, vec1[2], vec2[2],
564 name("selz"));
565
566 Value *wcmp = m_builder.CreateFCmpOLT(vec1[3], vec2[3], name("wcmp"));
567 Value *selw = m_builder.CreateSelect(wcmp, vec1[3], vec2[3],
568 name("selw"));
569
570 return vectorFromVals(selx, sely, selz, selw);
571 }
572
573 llvm::Value * Instructions::mul(llvm::Value *in1, llvm::Value *in2)
574 {
575 return m_builder.CreateMul(in1, in2, name("mul"));
576 }
577
578 llvm::Value * Instructions::neg(llvm::Value *in)
579 {
580 Value *neg = m_builder.CreateNeg(in, name("neg"));
581 return neg;
582 }
583
584 llvm::Value * Instructions::pow(llvm::Value *in1, llvm::Value *in2)
585 {
586 Value *x1 = m_builder.CreateExtractElement(in1,
587 m_storage->constantInt(0),
588 name("x1"));
589 Value *x2 = m_builder.CreateExtractElement(in2,
590 m_storage->constantInt(0),
591 name("x2"));
592 llvm::Value *val = callPow(x1, x2);
593 return vectorFromVals(val, val, val, val);
594 }
595
596 llvm::Value * Instructions::rcp(llvm::Value *in1)
597 {
598 Value *x1 = m_builder.CreateExtractElement(in1,
599 m_storage->constantInt(0),
600 name("x1"));
601 Value *res = m_builder.CreateFDiv(ConstantFP::get(APFloat(1.f)),
602 x1, name("rcp"));
603 return vectorFromVals(res, res, res, res);
604 }
605
606 llvm::Value * Instructions::rsq(llvm::Value *in1)
607 {
608 Value *x = m_builder.CreateExtractElement(in1,
609 m_storage->constantInt(0),
610 name("extractx"));
611 Value *abs = callFAbs(x);
612 Value *sqrt = callFSqrt(abs);
613
614 Value *rsqrt = m_builder.CreateFDiv(ConstantFP::get(APFloat(1.f)),
615 sqrt,
616 name("rsqrt"));
617 return vectorFromVals(rsqrt, rsqrt, rsqrt, rsqrt);
618 }
619
620 llvm::Value * Instructions::scs(llvm::Value *in)
621 {
622 llvm::Function *func = m_mod->getFunction("scs");
623 assert(func);
624
625 CallInst *call = m_builder.CreateCall(func, in, name("scsres"));
626 call->setTailCall(false);
627 return call;
628 }
629
630 llvm::Value * Instructions::seq(llvm::Value *in1, llvm::Value *in2)
631 {
632 Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f));
633 Constant *const0f = Constant::getNullValue(Type::FloatTy);
634
635 std::vector<llvm::Value*> vec1 = extractVector(in1);
636 std::vector<llvm::Value*> vec2 = extractVector(in2);
637
638 Value *xcmp = m_builder.CreateFCmpOEQ(vec1[0], vec2[0], name("xcmp"));
639 Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
640
641 Value *ycmp = m_builder.CreateFCmpOEQ(vec1[1], vec2[1], name("ycmp"));
642 Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
643
644 Value *zcmp = m_builder.CreateFCmpOEQ(vec1[2], vec2[2], name("zcmp"));
645 Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
646
647 Value *wcmp = m_builder.CreateFCmpOEQ(vec1[3], vec2[3], name("wcmp"));
648 Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel"));
649
650 return vectorFromVals(x, y, z, w);
651 }
652
653 llvm::Value * Instructions::sfl(llvm::Value *in1, llvm::Value *in2)
654 {
655 Constant *const0f = Constant::getNullValue(Type::FloatTy);
656
657 return vectorFromVals(const0f, const0f, const0f, const0f);
658 }
659
660 llvm::Value * Instructions::sge(llvm::Value *in1, llvm::Value *in2)
661 {
662 Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f));
663 Constant *const0f = Constant::getNullValue(Type::FloatTy);
664
665 std::vector<llvm::Value*> vec1 = extractVector(in1);
666 std::vector<llvm::Value*> vec2 = extractVector(in2);
667
668 Value *xcmp = m_builder.CreateFCmpOGE(vec1[0], vec2[0], name("xcmp"));
669 Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
670
671 Value *ycmp = m_builder.CreateFCmpOGE(vec1[1], vec2[1], name("ycmp"));
672 Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
673
674 Value *zcmp = m_builder.CreateFCmpOGE(vec1[2], vec2[2], name("zcmp"));
675 Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
676
677 Value *wcmp = m_builder.CreateFCmpOGE(vec1[3], vec2[3], name("wcmp"));
678 Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel"));
679
680 return vectorFromVals(x, y, z, w);
681 }
682
683 llvm::Value * Instructions::sgt(llvm::Value *in1, llvm::Value *in2)
684 {
685 Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f));
686 Constant *const0f = Constant::getNullValue(Type::FloatTy);
687
688 std::vector<llvm::Value*> vec1 = extractVector(in1);
689 std::vector<llvm::Value*> vec2 = extractVector(in2);
690 Value *xcmp = m_builder.CreateFCmpOGT(vec1[0], vec2[0], name("xcmp"));
691 Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
692
693 Value *ycmp = m_builder.CreateFCmpOGT(vec1[1], vec2[1], name("ycmp"));
694 Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
695
696 Value *zcmp = m_builder.CreateFCmpOGT(vec1[2], vec2[2], name("zcmp"));
697 Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
698
699 Value *wcmp = m_builder.CreateFCmpOGT(vec1[3], vec2[3], name("wcmp"));
700 Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel"));
701
702 return vectorFromVals(x, y, z, w);
703 }
704
705 llvm::Value * Instructions::sin(llvm::Value *in)
706 {
707 llvm::Function *func = m_mod->getFunction("vsin");
708 assert(func);
709
710 CallInst *call = m_builder.CreateCall(func, in, name("sinres"));
711 call->setTailCall(false);
712 return call;
713 }
714
715 llvm::Value * Instructions::sle(llvm::Value *in1, llvm::Value *in2)
716 {
717 Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f));
718 Constant *const0f = Constant::getNullValue(Type::FloatTy);
719
720 std::vector<llvm::Value*> vec1 = extractVector(in1);
721 std::vector<llvm::Value*> vec2 = extractVector(in2);
722
723 Value *xcmp = m_builder.CreateFCmpOLE(vec1[0], vec2[0], name("xcmp"));
724 Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
725
726 Value *ycmp = m_builder.CreateFCmpOLE(vec1[1], vec2[1], name("ycmp"));
727 Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
728
729 Value *zcmp = m_builder.CreateFCmpOLE(vec1[2], vec2[2], name("zcmp"));
730 Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
731
732 Value *wcmp = m_builder.CreateFCmpOLE(vec1[3], vec2[3], name("wcmp"));
733 Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel"));
734
735 return vectorFromVals(x, y, z, w);
736 }
737
738 llvm::Value * Instructions::slt(llvm::Value *in1, llvm::Value *in2)
739 {
740 Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f));
741 Constant *const0f = Constant::getNullValue(Type::FloatTy);
742
743 std::vector<llvm::Value*> vec1 = extractVector(in1);
744 std::vector<llvm::Value*> vec2 = extractVector(in2);
745
746 Value *xcmp = m_builder.CreateFCmpOLT(vec1[0], vec2[0], name("xcmp"));
747 Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
748
749 Value *ycmp = m_builder.CreateFCmpOLT(vec1[1], vec2[1], name("ycmp"));
750 Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
751
752 Value *zcmp = m_builder.CreateFCmpOLT(vec1[2], vec2[2], name("zcmp"));
753 Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
754
755 Value *wcmp = m_builder.CreateFCmpOLT(vec1[3], vec2[3], name("wcmp"));
756 Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel"));
757
758 return vectorFromVals(x, y, z, w);
759 }
760
761 llvm::Value * Instructions::sne(llvm::Value *in1, llvm::Value *in2)
762 {
763 Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f));
764 Constant *const0f = Constant::getNullValue(Type::FloatTy);
765
766 std::vector<llvm::Value*> vec1 = extractVector(in1);
767 std::vector<llvm::Value*> vec2 = extractVector(in2);
768
769 Value *xcmp = m_builder.CreateFCmpONE(vec1[0], vec2[0], name("xcmp"));
770 Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
771
772 Value *ycmp = m_builder.CreateFCmpONE(vec1[1], vec2[1], name("ycmp"));
773 Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
774
775 Value *zcmp = m_builder.CreateFCmpONE(vec1[2], vec2[2], name("zcmp"));
776 Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
777
778 Value *wcmp = m_builder.CreateFCmpONE(vec1[3], vec2[3], name("wcmp"));
779 Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel"));
780
781 return vectorFromVals(x, y, z, w);
782 }
783
784 llvm::Value * Instructions::str(llvm::Value *in1, llvm::Value *in2)
785 {
786 Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f));
787
788 return vectorFromVals(const1f, const1f, const1f, const1f);
789 }
790
791 llvm::Value * Instructions::sub(llvm::Value *in1, llvm::Value *in2)
792 {
793 Value *res = m_builder.CreateSub(in1, in2, name("sub"));
794 return res;
795 }
796
797 llvm::Value * Instructions::trunc(llvm::Value *in)
798 {
799 std::vector<llvm::Value*> vec = extractVector(in);
800 Value *icastx = m_builder.CreateFPToSI(vec[0], IntegerType::get(32),
801 name("ftoix"));
802 Value *icasty = m_builder.CreateFPToSI(vec[1], IntegerType::get(32),
803 name("ftoiy"));
804 Value *icastz = m_builder.CreateFPToSI(vec[2], IntegerType::get(32),
805 name("ftoiz"));
806 Value *icastw = m_builder.CreateFPToSI(vec[3], IntegerType::get(32),
807 name("ftoiw"));
808 Value *fx = m_builder.CreateSIToFP(icastx, Type::FloatTy,
809 name("fx"));
810 Value *fy = m_builder.CreateSIToFP(icasty, Type::FloatTy,
811 name("fy"));
812 Value *fz = m_builder.CreateSIToFP(icastz, Type::FloatTy,
813 name("fz"));
814 Value *fw = m_builder.CreateSIToFP(icastw, Type::FloatTy,
815 name("fw"));
816 return vectorFromVals(fx, fy, fz, fw);
817 }
818
819 llvm::Value * Instructions::x2d(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3)
820 {
821 std::vector<llvm::Value*> vec1 = extractVector(in1);
822 std::vector<llvm::Value*> vec2 = extractVector(in2);
823 std::vector<llvm::Value*> vec3 = extractVector(in3);
824
825 Value *x2x3 = m_builder.CreateMul( vec2[0], vec3[0], name("x2x3"));
826 Value *y2y3 = m_builder.CreateMul( vec2[1], vec3[1], name("y2y3"));
827 Value *x1px2x3 = m_builder.CreateAdd (vec1[0], x2x3, name("x1 + x2x3"));
828 Value *x1px2x3py2y3 = m_builder.CreateAdd (x1px2x3, y2y3, name("x1 + x2x3 + y2y3"));
829
830 Value *x2z3 = m_builder.CreateMul( vec2[0], vec3[2], name("x2z3"));
831 Value *y2w3 = m_builder.CreateMul( vec2[1], vec3[3], name("y2w3"));
832 Value *y1px2z3 = m_builder.CreateAdd (vec1[1], x2z3, name("y1 + x2z3"));
833 Value *y1px2z3py2w3 = m_builder.CreateAdd (y1px2z3, y2w3, name("y1 + x2z3 + y2w3"));
834
835 return vectorFromVals(x1px2x3py2y3, y1px2z3py2w3, x1px2x3py2y3, y1px2z3py2w3);
836 }
837
838 void Instructions::printVector(llvm::Value *val)
839 {
840 static const char *frmt = "Vector is [%f, %f, %f, %f]\x0A";
841
842 if (!m_fmtPtr) {
843 Constant *format = ConstantArray::get(frmt, true);
844 ArrayType *arrayTy = ArrayType::get(IntegerType::get(8), strlen(frmt) + 1);
845 GlobalVariable* globalFormat = new GlobalVariable(
846 /*Type=*/arrayTy,
847 /*isConstant=*/true,
848 /*Linkage=*/GlobalValue::InternalLinkage,
849 /*Initializer=*/0, // has initializer, specified below
850 /*Name=*/name(".str"),
851 m_mod);
852 globalFormat->setInitializer(format);
853
854 Constant* const_int0 = Constant::getNullValue(IntegerType::get(32));
855 std::vector<Constant*> const_ptr_21_indices;
856 const_ptr_21_indices.push_back(const_int0);
857 const_ptr_21_indices.push_back(const_int0);
858 m_fmtPtr = ConstantExpr::getGetElementPtr(globalFormat,
859 &const_ptr_21_indices[0], const_ptr_21_indices.size());
860 }
861
862 Function *func_printf = m_mod->getFunction("printf");
863 if (!func_printf)
864 func_printf = declarePrintf();
865 assert(func_printf);
866 std::vector<llvm::Value*> vec = extractVector(val);
867 Value *dx = m_builder.CreateFPExt(vec[0], Type::DoubleTy, name("dx"));
868 Value *dy = m_builder.CreateFPExt(vec[1], Type::DoubleTy, name("dy"));
869 Value *dz = m_builder.CreateFPExt(vec[2], Type::DoubleTy, name("dz"));
870 Value *dw = m_builder.CreateFPExt(vec[3], Type::DoubleTy, name("dw"));
871 std::vector<Value*> params;
872 params.push_back(m_fmtPtr);
873 params.push_back(dx);
874 params.push_back(dy);
875 params.push_back(dz);
876 params.push_back(dw);
877 CallInst *call = m_builder.CreateCall(func_printf, params.begin(), params.end(),
878 name("printf"));
879 call->setCallingConv(CallingConv::C);
880 call->setTailCall(true);
881 }
882
883 const char * Instructions::name(const char *prefix)
884 {
885 ++m_idx;
886 snprintf(m_name, 32, "%s%d", prefix, m_idx);
887 return m_name;
888 }
889
890 llvm::Value *Instructions::callFAbs(llvm::Value *val)
891 {
892 if (!m_llvmFAbs) {
893 // predeclare the intrinsic
894 std::vector<const Type*> fabsArgs;
895 fabsArgs.push_back(Type::FloatTy);
896 PAListPtr fabsPal;
897 FunctionType* fabsType = FunctionType::get(
898 /*Result=*/Type::FloatTy,
899 /*Params=*/fabsArgs,
900 /*isVarArg=*/false);
901 m_llvmFAbs = Function::Create(
902 /*Type=*/fabsType,
903 /*Linkage=*/GlobalValue::ExternalLinkage,
904 /*Name=*/"fabs", m_mod);
905 m_llvmFAbs->setCallingConv(CallingConv::C);
906 m_llvmFAbs->setParamAttrs(fabsPal);
907 }
908 CallInst *call = m_builder.CreateCall(m_llvmFAbs, val,
909 name("fabs"));
910 call->setCallingConv(CallingConv::C);
911 call->setTailCall(false);
912 return call;
913 }
914
915 llvm::Value * Instructions::callFExp(llvm::Value *val)
916 {
917 if (!m_llvmFexp) {
918 // predeclare the intrinsic
919 std::vector<const Type*> fexpArgs;
920 fexpArgs.push_back(Type::FloatTy);
921 PAListPtr fexpPal;
922 FunctionType* fexpType = FunctionType::get(
923 /*Result=*/Type::FloatTy,
924 /*Params=*/fexpArgs,
925 /*isVarArg=*/false);
926 m_llvmFexp = Function::Create(
927 /*Type=*/fexpType,
928 /*Linkage=*/GlobalValue::ExternalLinkage,
929 /*Name=*/"expf", m_mod);
930 m_llvmFexp->setCallingConv(CallingConv::C);
931 m_llvmFexp->setParamAttrs(fexpPal);
932 }
933 CallInst *call = m_builder.CreateCall(m_llvmFexp, val,
934 name("expf"));
935 call->setCallingConv(CallingConv::C);
936 call->setTailCall(false);
937 return call;
938 }
939
940 llvm::Value * Instructions::callFLog(llvm::Value *val)
941 {
942 if (!m_llvmFlog) {
943 // predeclare the intrinsic
944 std::vector<const Type*> flogArgs;
945 flogArgs.push_back(Type::FloatTy);
946 PAListPtr flogPal;
947 FunctionType* flogType = FunctionType::get(
948 /*Result=*/Type::FloatTy,
949 /*Params=*/flogArgs,
950 /*isVarArg=*/false);
951 m_llvmFlog = Function::Create(
952 /*Type=*/flogType,
953 /*Linkage=*/GlobalValue::ExternalLinkage,
954 /*Name=*/"logf", m_mod);
955 m_llvmFlog->setCallingConv(CallingConv::C);
956 m_llvmFlog->setParamAttrs(flogPal);
957 }
958 CallInst *call = m_builder.CreateCall(m_llvmFlog, val,
959 name("logf"));
960 call->setCallingConv(CallingConv::C);
961 call->setTailCall(false);
962 return call;
963 }
964
965 llvm::Value * Instructions::callFloor(llvm::Value *val)
966 {
967 if (!m_llvmFloor) {
968 // predeclare the intrinsic
969 std::vector<const Type*> floorArgs;
970 floorArgs.push_back(Type::FloatTy);
971 PAListPtr floorPal;
972 FunctionType* floorType = FunctionType::get(
973 /*Result=*/Type::FloatTy,
974 /*Params=*/floorArgs,
975 /*isVarArg=*/false);
976 m_llvmFloor = Function::Create(
977 /*Type=*/floorType,
978 /*Linkage=*/GlobalValue::ExternalLinkage,
979 /*Name=*/"floorf", m_mod);
980 m_llvmFloor->setCallingConv(CallingConv::C);
981 m_llvmFloor->setParamAttrs(floorPal);
982 }
983 CallInst *call = m_builder.CreateCall(m_llvmFloor, val,
984 name("floorf"));
985 call->setCallingConv(CallingConv::C);
986 call->setTailCall(false);
987 return call;
988 }
989
990 llvm::Value *Instructions::callFSqrt(llvm::Value *val)
991 {
992 if (!m_llvmFSqrt) {
993 // predeclare the intrinsic
994 std::vector<const Type*> fsqrtArgs;
995 fsqrtArgs.push_back(Type::FloatTy);
996 PAListPtr fsqrtPal;
997 FunctionType* fsqrtType = FunctionType::get(
998 /*Result=*/Type::FloatTy,
999 /*Params=*/fsqrtArgs,
1000 /*isVarArg=*/false);
1001 m_llvmFSqrt = Function::Create(
1002 /*Type=*/fsqrtType,
1003 /*Linkage=*/GlobalValue::ExternalLinkage,
1004 /*Name=*/"llvm.sqrt.f32", m_mod);
1005 m_llvmFSqrt->setCallingConv(CallingConv::C);
1006 m_llvmFSqrt->setParamAttrs(fsqrtPal);
1007 }
1008 CallInst *call = m_builder.CreateCall(m_llvmFSqrt, val,
1009 name("sqrt"));
1010 call->setCallingConv(CallingConv::C);
1011 call->setTailCall(false);
1012 return call;
1013 }
1014
1015 llvm::Value * Instructions::callPow(llvm::Value *val1, llvm::Value *val2)
1016 {
1017 if (!m_llvmPow) {
1018 // predeclare the intrinsic
1019 std::vector<const Type*> powArgs;
1020 powArgs.push_back(Type::FloatTy);
1021 powArgs.push_back(Type::FloatTy);
1022 PAListPtr powPal;
1023 FunctionType* powType = FunctionType::get(
1024 /*Result=*/Type::FloatTy,
1025 /*Params=*/powArgs,
1026 /*isVarArg=*/false);
1027 m_llvmPow = Function::Create(
1028 /*Type=*/powType,
1029 /*Linkage=*/GlobalValue::ExternalLinkage,
1030 /*Name=*/"llvm.pow.f32", m_mod);
1031 m_llvmPow->setCallingConv(CallingConv::C);
1032 m_llvmPow->setParamAttrs(powPal);
1033 }
1034 std::vector<Value*> params;
1035 params.push_back(val1);
1036 params.push_back(val2);
1037 CallInst *call = m_builder.CreateCall(m_llvmPow, params.begin(), params.end(),
1038 name("pow"));
1039 call->setCallingConv(CallingConv::C);
1040 call->setTailCall(false);
1041 return call;
1042 }
1043
1044 llvm::Value * Instructions::vectorFromVals(llvm::Value *x, llvm::Value *y,
1045 llvm::Value *z, llvm::Value *w)
1046 {
1047 Constant *const_vec = Constant::getNullValue(m_floatVecType);
1048 Value *res = m_builder.CreateInsertElement(const_vec, x,
1049 m_storage->constantInt(0),
1050 name("vecx"));
1051 res = m_builder.CreateInsertElement(res, y, m_storage->constantInt(1),
1052 name("vecxy"));
1053 res = m_builder.CreateInsertElement(res, z, m_storage->constantInt(2),
1054 name("vecxyz"));
1055 if (w)
1056 res = m_builder.CreateInsertElement(res, w, m_storage->constantInt(3),
1057 name("vecxyzw"));
1058 return res;
1059 }
1060
1061 llvm::Value * Instructions::constVector(float x, float y, float z, float w)
1062 {
1063 std::vector<Constant*> vec(4);
1064 vec[0] = ConstantFP::get(APFloat(x));
1065 vec[1] = ConstantFP::get(APFloat(y));
1066 vec[2] = ConstantFP::get(APFloat(z));
1067 vec[3] = ConstantFP::get(APFloat(w));
1068 return ConstantVector::get(m_floatVecType, vec);
1069 }
1070
1071 llvm::Function * Instructions::declarePrintf()
1072 {
1073 std::vector<const Type*> args;
1074 PAListPtr params;
1075 FunctionType* funcTy = FunctionType::get(
1076 /*Result=*/IntegerType::get(32),
1077 /*Params=*/args,
1078 /*isVarArg=*/true);
1079 Function* func_printf = Function::Create(
1080 /*Type=*/funcTy,
1081 /*Linkage=*/GlobalValue::ExternalLinkage,
1082 /*Name=*/"printf", m_mod);
1083 func_printf->setCallingConv(CallingConv::C);
1084 func_printf->setParamAttrs(params);
1085 return func_printf;
1086 }
1087
1088 llvm::Function * Instructions::declareFunc(int label)
1089 {
1090 PointerType *vecPtr = PointerType::getUnqual(m_floatVecType);
1091 std::vector<const Type*> args;
1092 args.push_back(vecPtr);
1093 args.push_back(vecPtr);
1094 args.push_back(vecPtr);
1095 args.push_back(vecPtr);
1096 PAListPtr params;
1097 FunctionType *funcType = FunctionType::get(
1098 /*Result=*/Type::VoidTy,
1099 /*Params=*/args,
1100 /*isVarArg=*/false);
1101 std::string name = createFuncName(label);
1102 Function *func = Function::Create(
1103 /*Type=*/funcType,
1104 /*Linkage=*/GlobalValue::ExternalLinkage,
1105 /*Name=*/name.c_str(), m_mod);
1106 func->setCallingConv(CallingConv::C);
1107 func->setParamAttrs(params);
1108 return func;
1109 }
1110
1111 llvm::Function * Instructions::findFunction(int label)
1112 {
1113 llvm::Function *func = m_functions[label];
1114 if (!func) {
1115 func = declareFunc(label);
1116 m_functions[label] = func;
1117 }
1118 return func;
1119 }
1120
1121 std::vector<llvm::Value*> Instructions::extractVector(llvm::Value *vec)
1122 {
1123 std::vector<llvm::Value*> elems(4);
1124 elems[0] = m_builder.CreateExtractElement(vec, m_storage->constantInt(0),
1125 name("x"));
1126 elems[1] = m_builder.CreateExtractElement(vec, m_storage->constantInt(1),
1127 name("y"));
1128 elems[2] = m_builder.CreateExtractElement(vec, m_storage->constantInt(2),
1129 name("z"));
1130 elems[3] = m_builder.CreateExtractElement(vec, m_storage->constantInt(3),
1131 name("w"));
1132 return elems;
1133 }
1134
1135
1136 #endif //MESA_LLVM
1137
1138