1 /**************************************************************************
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
30 * Zack Rusin zack@tungstengraphics.com
34 #include "instructions.h"
38 #include "util/u_memory.h"
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/Attributes.h>
47 #include <llvm/Support/MemoryBuffer.h>
48 #include <llvm/Bitcode/ReaderWriter.h>
56 #include "gallivm_builtins.cpp"
59 llvm::Value
*arrayFromChannels(std::vector
<llvm::Value
*> &vals
)
61 VectorType
*vectorType
= VectorType::get(Type::FloatTy
, 4);
62 ArrayType
*vectorArray
= ArrayType::get(vectorType
, 4);
66 static inline std::string
createFuncName(int label
)
68 std::ostringstream stream
;
74 Instructions::Instructions(llvm::Module
*mod
, llvm::Function
*func
, llvm::BasicBlock
*block
,
76 : m_mod(mod
), m_func(func
), m_builder(block
), m_idx(0),
79 m_floatVecType
= VectorType::get(Type::FloatTy
, 4);
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
);
96 llvm::BasicBlock
* Instructions::currentBlock() const
98 return m_builder
.GetInsertBlock();
101 llvm::Value
* Instructions::abs(llvm::Value
*in
)
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
);
111 llvm::Value
* Instructions::add(llvm::Value
*in1
, llvm::Value
*in2
)
113 return m_builder
.CreateAdd(in1
, in2
, name("add"));
116 llvm::Value
* Instructions::arl(llvm::Value
*in
)
121 void Instructions::beginLoop()
123 BasicBlock
*begin
= BasicBlock::Create(name("loop"), m_func
,0);
124 BasicBlock
*end
= BasicBlock::Create(name("endloop"), m_func
,0);
126 m_builder
.CreateBr(begin
);
130 m_builder
.SetInsertPoint(begin
);
131 m_loopStack
.push(loop
);
134 void Instructions::bgnSub(unsigned label
)
136 llvm::Function
*func
= findFunction(label
);
138 Function::arg_iterator args
= func
->arg_begin();
139 Value
*ptr_INPUT
= args
++;
140 ptr_INPUT
->setName("INPUT");
141 m_storage
->pushArguments(ptr_INPUT
);
143 llvm::BasicBlock
*entry
= BasicBlock::Create("entry", func
, 0);
146 m_builder
.SetInsertPoint(entry
);
149 void Instructions::brk()
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
);
157 void Instructions::cal(int label
, llvm::Value
*input
)
159 std::vector
<Value
*> params
;
160 params
.push_back(input
);
161 llvm::Function
*func
= findFunction(label
);
163 m_builder
.CreateCall(func
, params
.begin(), params
.end());
166 llvm::Value
* Instructions::ceil(llvm::Value
*in
)
168 std::vector
<llvm::Value
*> vec
= extractVector(in
);
169 return vectorFromVals(callCeil(vec
[0]), callCeil(vec
[1]),
170 callCeil(vec
[2]), callCeil(vec
[3]));
173 llvm::Value
* Instructions::clamp(llvm::Value
*in1
)
175 llvm::Value
*zero
= constVector(0.0f
, 0.0f
, 0.0f
, 0.0f
);
176 llvm::Value
*one
= constVector(1.0f
, 1.0f
, 1.0f
, 1.0f
);
177 return min( max(zero
, in1
), one
);
180 llvm::Value
* Instructions::cmp(llvm::Value
*in1
, llvm::Value
*in2
, llvm::Value
*in3
)
182 llvm::Function
*func
= m_mod
->getFunction("cmp");
185 std::vector
<Value
*> params
;
186 params
.push_back(in1
);
187 params
.push_back(in2
);
188 params
.push_back(in3
);
189 CallInst
*call
= m_builder
.CreateCall(func
, params
.begin(), params
.end(), name("cmpres"));
190 call
->setTailCall(false);
194 llvm::Value
* Instructions::cnd(llvm::Value
*in1
, llvm::Value
*in2
, llvm::Value
*in3
)
196 std::vector
<llvm::Value
*> vec1
= extractVector(in1
);
197 std::vector
<llvm::Value
*> vec2
= extractVector(in2
);
198 std::vector
<llvm::Value
*> vec3
= extractVector(in3
);
199 Constant
*half
= ConstantFP::get(APFloat(0.5f
));
201 Value
*xcmp
= m_builder
.CreateFCmpOGT(vec1
[0], half
, name("xcmp"));
202 Value
*selx
= m_builder
.CreateSelect(xcmp
, vec2
[0], vec3
[0],
205 Value
*ycmp
= m_builder
.CreateFCmpOGT(vec1
[1], half
, name("ycmp"));
206 Value
*sely
= m_builder
.CreateSelect(ycmp
, vec2
[1], vec3
[1],
209 Value
*zcmp
= m_builder
.CreateFCmpOGT(vec1
[2], half
, name("zcmp"));
210 Value
*selz
= m_builder
.CreateSelect(zcmp
, vec2
[2], vec3
[2],
213 Value
*wcmp
= m_builder
.CreateFCmpOGT(vec1
[3], half
, name("wcmp"));
214 Value
*selw
= m_builder
.CreateSelect(wcmp
, vec2
[3], vec3
[3],
217 return vectorFromVals(selx
, sely
, selz
, selw
);
220 llvm::Value
* Instructions::cnd0(llvm::Value
*in1
, llvm::Value
*in2
, llvm::Value
*in3
)
222 std::vector
<llvm::Value
*> vec1
= extractVector(in1
);
223 std::vector
<llvm::Value
*> vec2
= extractVector(in2
);
224 std::vector
<llvm::Value
*> vec3
= extractVector(in3
);
225 Constant
*zero
= Constant::getNullValue(Type::FloatTy
);
227 Value
*xcmp
= m_builder
.CreateFCmpOGE(vec1
[0], zero
, name("xcmp"));
228 Value
*selx
= m_builder
.CreateSelect(xcmp
, vec2
[0], vec3
[0],
231 Value
*ycmp
= m_builder
.CreateFCmpOGE(vec1
[1], zero
, name("ycmp"));
232 Value
*sely
= m_builder
.CreateSelect(ycmp
, vec2
[1], vec3
[1],
235 Value
*zcmp
= m_builder
.CreateFCmpOGE(vec1
[2], zero
, name("zcmp"));
236 Value
*selz
= m_builder
.CreateSelect(zcmp
, vec2
[2], vec3
[2],
239 Value
*wcmp
= m_builder
.CreateFCmpOGE(vec1
[3], zero
, name("wcmp"));
240 Value
*selw
= m_builder
.CreateSelect(wcmp
, vec2
[3], vec3
[3],
243 return vectorFromVals(selx
, sely
, selz
, selw
);
246 llvm::Value
* Instructions::cos(llvm::Value
*in
)
249 llvm::Function
*func
= m_mod
->getFunction("vcos");
252 CallInst
*call
= m_builder
.CreateCall(func
, in
, name("cosres"));
253 call
->setTailCall(false);
256 std::vector
<llvm::Value
*> elems
= extractVector(in
);
257 Function
*func
= m_mod
->getFunction("cosf");
259 CallInst
*cos
= m_builder
.CreateCall(func
, elems
[0], name("cosres"));
260 cos
->setCallingConv(CallingConv::C
);
261 cos
->setTailCall(true);
262 return vectorFromVals(cos
, cos
, cos
, cos
);
266 llvm::Value
* Instructions::cross(llvm::Value
*in1
, llvm::Value
*in2
)
268 Value
*x1
= m_builder
.CreateExtractElement(in1
,
269 m_storage
->constantInt(0),
271 Value
*y1
= m_builder
.CreateExtractElement(in1
,
272 m_storage
->constantInt(1),
274 Value
*z1
= m_builder
.CreateExtractElement(in1
,
275 m_storage
->constantInt(2),
278 Value
*x2
= m_builder
.CreateExtractElement(in2
,
279 m_storage
->constantInt(0),
281 Value
*y2
= m_builder
.CreateExtractElement(in2
,
282 m_storage
->constantInt(1),
284 Value
*z2
= m_builder
.CreateExtractElement(in2
,
285 m_storage
->constantInt(2),
287 Value
*y1z2
= mul(y1
, z2
);
288 Value
*z1y2
= mul(z1
, y2
);
290 Value
*z1x2
= mul(z1
, x2
);
291 Value
*x1z2
= mul(x1
, z2
);
293 Value
*x1y2
= mul(x1
, y2
);
294 Value
*y1x2
= mul(y1
, x2
);
296 return vectorFromVals(sub(y1z2
, z1y2
), sub(z1x2
, x1z2
), sub(x1y2
, y1x2
));
299 llvm::Value
* Instructions::ddx(llvm::Value
*in
)
305 llvm::Value
* Instructions::ddy(llvm::Value
*in
)
311 llvm::Value
* Instructions::div(llvm::Value
*in1
, llvm::Value
*in2
)
313 return m_builder
.CreateFDiv(in1
, in2
, name("div"));
316 llvm::Value
* Instructions::dot2add(llvm::Value
*in1
, llvm::Value
*in2
, llvm::Value
*in3
)
318 Value
*mulRes
= mul(in1
, in2
);
319 Value
*x
= m_builder
.CreateExtractElement(mulRes
,
320 m_storage
->constantInt(0),
322 Value
*y
= m_builder
.CreateExtractElement(mulRes
,
323 m_storage
->constantInt(1),
325 Value
*z
= m_builder
.CreateExtractElement(in3
,
326 m_storage
->constantInt(2),
328 Value
*xy
= m_builder
.CreateAdd(x
, y
,name("xy"));
329 Value
*dot2add
= m_builder
.CreateAdd(xy
, z
, name("dot2add"));
330 return vectorFromVals(dot2add
, dot2add
, dot2add
, dot2add
);
333 llvm::Value
* Instructions::dp2(llvm::Value
*in1
, llvm::Value
*in2
)
335 Value
*mulRes
= mul(in1
, in2
);
336 Value
*x
= m_builder
.CreateExtractElement(mulRes
,
337 m_storage
->constantInt(0),
339 Value
*y
= m_builder
.CreateExtractElement(mulRes
,
340 m_storage
->constantInt(1),
342 Value
*xy
= m_builder
.CreateAdd(x
, y
,name("xy"));
343 return vectorFromVals(xy
, xy
, xy
, xy
);
346 llvm::Value
* Instructions::dp3(llvm::Value
*in1
, llvm::Value
*in2
)
348 Value
*mulRes
= mul(in1
, in2
);
349 Value
*x
= m_builder
.CreateExtractElement(mulRes
,
350 m_storage
->constantInt(0),
352 Value
*y
= m_builder
.CreateExtractElement(mulRes
,
353 m_storage
->constantInt(1),
355 Value
*z
= m_builder
.CreateExtractElement(mulRes
,
356 m_storage
->constantInt(2),
358 Value
*xy
= m_builder
.CreateAdd(x
, y
,name("xy"));
359 Value
*dot3
= m_builder
.CreateAdd(xy
, z
, name("dot3"));
360 return vectorFromVals(dot3
, dot3
, dot3
, dot3
);
363 llvm::Value
* Instructions::dp4(llvm::Value
*in1
, llvm::Value
*in2
)
365 Value
*mulRes
= mul(in1
, in2
);
366 std::vector
<llvm::Value
*> vec
= extractVector(mulRes
);
367 Value
*xy
= m_builder
.CreateAdd(vec
[0], vec
[1], name("xy"));
368 Value
*xyz
= m_builder
.CreateAdd(xy
, vec
[2], name("xyz"));
369 Value
*dot4
= m_builder
.CreateAdd(xyz
, vec
[3], name("dot4"));
370 return vectorFromVals(dot4
, dot4
, dot4
, dot4
);
373 llvm::Value
* Instructions::dph(llvm::Value
*in1
, llvm::Value
*in2
)
375 Value
*mulRes
= mul(in1
, in2
);
376 std::vector
<llvm::Value
*> vec1
= extractVector(mulRes
);
377 Value
*xy
= m_builder
.CreateAdd(vec1
[0], vec1
[1], name("xy"));
378 Value
*xyz
= m_builder
.CreateAdd(xy
, vec1
[2], name("xyz"));
379 Value
*dph
= m_builder
.CreateAdd(xyz
, vec1
[3], name("dph"));
380 return vectorFromVals(dph
, dph
, dph
, dph
);
383 llvm::Value
* Instructions::dst(llvm::Value
*in1
, llvm::Value
*in2
)
385 Value
*y1
= m_builder
.CreateExtractElement(in1
,
386 m_storage
->constantInt(1),
388 Value
*z
= m_builder
.CreateExtractElement(in1
,
389 m_storage
->constantInt(2),
391 Value
*y2
= m_builder
.CreateExtractElement(in2
,
392 m_storage
->constantInt(1),
394 Value
*w
= m_builder
.CreateExtractElement(in2
,
395 m_storage
->constantInt(3),
397 Value
*ry
= m_builder
.CreateMul(y1
, y2
, name("tyuy"));
398 return vectorFromVals(ConstantFP::get(APFloat(1.f
)),
402 void Instructions::elseop()
404 assert(!m_ifStack
.empty());
405 BasicBlock
*ifend
= BasicBlock::Create(name("ifend"), m_func
,0);
406 m_builder
.CreateBr(ifend
);
407 m_builder
.SetInsertPoint(m_ifStack
.top());
408 currentBlock()->setName(name("ifelse"));
410 m_ifStack
.push(ifend
);
413 void Instructions::endif()
415 assert(!m_ifStack
.empty());
416 m_builder
.CreateBr(m_ifStack
.top());
417 m_builder
.SetInsertPoint(m_ifStack
.top());
421 void Instructions::endLoop()
423 assert(!m_loopStack
.empty());
424 Loop loop
= m_loopStack
.top();
425 m_builder
.CreateBr(loop
.begin
);
426 loop
.end
->moveAfter(currentBlock());
427 m_builder
.SetInsertPoint(loop
.end
);
431 void Instructions::end()
433 m_builder
.CreateRetVoid();
436 void Instructions::endSub()
439 m_builder
.SetInsertPoint(0);
442 llvm::Value
* Instructions::exp(llvm::Value
*in
)
444 std::vector
<llvm::Value
*> vec
= extractVector(in
);
445 return vectorFromVals(callFExp(vec
[0]), callFExp(vec
[1]),
446 callFExp(vec
[2]), callFExp(vec
[3]));
449 llvm::Value
* Instructions::ex2(llvm::Value
*in
)
451 llvm::Value
*val
= callPow(ConstantFP::get(APFloat(2.f
)),
452 m_builder
.CreateExtractElement(
453 in
, m_storage
->constantInt(0),
455 return vectorFromVals(val
, val
, val
, val
);
458 llvm::Value
* Instructions::floor(llvm::Value
*in
)
460 std::vector
<llvm::Value
*> vec
= extractVector(in
);
461 return vectorFromVals(callFloor(vec
[0]), callFloor(vec
[1]),
462 callFloor(vec
[2]), callFloor(vec
[3]));
465 llvm::Value
* Instructions::frc(llvm::Value
*in
)
467 llvm::Value
*flr
= floor(in
);
471 void Instructions::ifop(llvm::Value
*in
)
473 BasicBlock
*ifthen
= BasicBlock::Create(name("ifthen"), m_func
,0);
474 BasicBlock
*ifend
= BasicBlock::Create(name("ifthenend"), m_func
,0);
476 //BasicBlock *yblock = new BasicBlock(name("yblock"), m_func,0);
477 //BasicBlock *zblock = new BasicBlock(name("zblock"), m_func,0);
478 //BasicBlock *wblock = new BasicBlock(name("wblock"), m_func,0);
480 Constant
*float0
= Constant::getNullValue(Type::FloatTy
);
482 Value
*x
= m_builder
.CreateExtractElement(in
, m_storage
->constantInt(0),
484 Value
*xcmp
= m_builder
.CreateFCmpUNE(x
, float0
, name("xcmp"));
485 m_builder
.CreateCondBr(xcmp
, ifthen
, ifend
);
486 //m_builder.SetInsertPoint(yblock);
488 m_builder
.SetInsertPoint(ifthen
);
489 m_ifStack
.push(ifend
);
492 llvm::Value
* Instructions::kil(llvm::Value
*in
)
494 llvm::Function
*func
= m_mod
->getFunction("kil");
497 CallInst
*call
= m_builder
.CreateCall(func
, in
, name("kilpres"));
498 call
->setTailCall(false);
502 llvm::Value
* Instructions::lerp(llvm::Value
*in1
, llvm::Value
*in2
,
505 llvm::Value
*m
= mul(in1
, in2
);
506 llvm::Value
*vec1
= constVector(1.f
, 1.f
, 1.f
, 1.f
);
507 llvm::Value
*s
= sub(vec1
, in1
);
508 return add(m
, mul(s
, in3
));
511 llvm::Value
* Instructions::lg2(llvm::Value
*in
)
513 std::vector
<llvm::Value
*> vec
= extractVector(in
);
514 llvm::Value
*const_vec
= constVector(1.442695f
, 1.442695f
,
515 1.442695f
, 1.442695f
);
516 return mul(vectorFromVals(callFLog(vec
[0]), callFLog(vec
[1]),
517 callFLog(vec
[2]), callFLog(vec
[3])), const_vec
);
520 llvm::Value
* Instructions::lit(llvm::Value
*in
)
523 m_llvmLit
= m_mod
->getFunction("lit");
525 CallInst
*call
= m_builder
.CreateCall(m_llvmLit
, in
, name("litres"));
526 call
->setCallingConv(CallingConv::C
);
527 call
->setTailCall(false);
531 llvm::Value
* Instructions::log(llvm::Value
*in
)
533 std::vector
<llvm::Value
*> vec
= extractVector(in
);
534 return vectorFromVals(callFLog(vec
[0]), callFLog(vec
[1]),
535 callFLog(vec
[2]), callFLog(vec
[3]));
538 llvm::Value
* Instructions::madd(llvm::Value
*in1
, llvm::Value
*in2
,
541 Value
*mulRes
= mul(in1
, in2
);
542 return add(mulRes
, in3
);
545 llvm::Value
* Instructions::max(llvm::Value
*in1
, llvm::Value
*in2
)
547 std::vector
<llvm::Value
*> vec1
= extractVector(in1
);
548 std::vector
<llvm::Value
*> vec2
= extractVector(in2
);
550 Value
*xcmp
= m_builder
.CreateFCmpOGT(vec1
[0], vec2
[0],
552 Value
*selx
= m_builder
.CreateSelect(xcmp
, vec1
[0], vec2
[0],
555 Value
*ycmp
= m_builder
.CreateFCmpOGT(vec1
[1], vec2
[1],
557 Value
*sely
= m_builder
.CreateSelect(ycmp
, vec1
[1], vec2
[1],
560 Value
*zcmp
= m_builder
.CreateFCmpOGT(vec1
[2], vec2
[2],
562 Value
*selz
= m_builder
.CreateSelect(zcmp
, vec1
[2], vec2
[2],
565 Value
*wcmp
= m_builder
.CreateFCmpOGT(vec1
[3], vec2
[3],
567 Value
*selw
= m_builder
.CreateSelect(wcmp
, vec1
[3], vec2
[3],
570 return vectorFromVals(selx
, sely
, selz
, selw
);
573 llvm::Value
* Instructions::min(llvm::Value
*in1
, llvm::Value
*in2
)
575 std::vector
<llvm::Value
*> vec1
= extractVector(in1
);
576 std::vector
<llvm::Value
*> vec2
= extractVector(in2
);
578 Value
*xcmp
= m_builder
.CreateFCmpOLT(vec1
[0], vec2
[0], name("xcmp"));
579 Value
*selx
= m_builder
.CreateSelect(xcmp
, vec1
[0], vec2
[0],
582 Value
*ycmp
= m_builder
.CreateFCmpOLT(vec1
[1], vec2
[1], name("ycmp"));
583 Value
*sely
= m_builder
.CreateSelect(ycmp
, vec1
[1], vec2
[1],
586 Value
*zcmp
= m_builder
.CreateFCmpOLT(vec1
[2], vec2
[2], name("zcmp"));
587 Value
*selz
= m_builder
.CreateSelect(zcmp
, vec1
[2], vec2
[2],
590 Value
*wcmp
= m_builder
.CreateFCmpOLT(vec1
[3], vec2
[3], name("wcmp"));
591 Value
*selw
= m_builder
.CreateSelect(wcmp
, vec1
[3], vec2
[3],
594 return vectorFromVals(selx
, sely
, selz
, selw
);
597 llvm::Value
* Instructions::mul(llvm::Value
*in1
, llvm::Value
*in2
)
599 return m_builder
.CreateMul(in1
, in2
, name("mul"));
602 llvm::Value
* Instructions::neg(llvm::Value
*in
)
604 Value
*neg
= m_builder
.CreateNeg(in
, name("neg"));
608 llvm::Value
* Instructions::nrm(llvm::Value
*in
)
610 llvm::Value
*v
= rsq(in
);
614 llvm::Value
* Instructions::pow(llvm::Value
*in1
, llvm::Value
*in2
)
616 Value
*x1
= m_builder
.CreateExtractElement(in1
,
617 m_storage
->constantInt(0),
619 Value
*x2
= m_builder
.CreateExtractElement(in2
,
620 m_storage
->constantInt(0),
622 llvm::Value
*val
= callPow(x1
, x2
);
623 return vectorFromVals(val
, val
, val
, val
);
626 llvm::Value
* Instructions::rcp(llvm::Value
*in1
)
628 Value
*x1
= m_builder
.CreateExtractElement(in1
,
629 m_storage
->constantInt(0),
631 Value
*res
= m_builder
.CreateFDiv(ConstantFP::get(APFloat(1.f
)),
633 return vectorFromVals(res
, res
, res
, res
);
636 llvm::Value
* Instructions::rsq(llvm::Value
*in1
)
638 Value
*x
= m_builder
.CreateExtractElement(in1
,
639 m_storage
->constantInt(0),
641 Value
*abs
= callFAbs(x
);
642 Value
*sqrt
= callFSqrt(abs
);
644 Value
*rsqrt
= m_builder
.CreateFDiv(ConstantFP::get(APFloat(1.f
)),
647 return vectorFromVals(rsqrt
, rsqrt
, rsqrt
, rsqrt
);
650 llvm::Value
* Instructions::scs(llvm::Value
*in
)
652 llvm::Function
*func
= m_mod
->getFunction("scs");
655 CallInst
*call
= m_builder
.CreateCall(func
, in
, name("scsres"));
656 call
->setTailCall(false);
660 llvm::Value
* Instructions::seq(llvm::Value
*in1
, llvm::Value
*in2
)
662 Constant
*const1f
= ConstantFP::get(APFloat(1.000000e+00f
));
663 Constant
*const0f
= Constant::getNullValue(Type::FloatTy
);
665 std::vector
<llvm::Value
*> vec1
= extractVector(in1
);
666 std::vector
<llvm::Value
*> vec2
= extractVector(in2
);
668 Value
*xcmp
= m_builder
.CreateFCmpOEQ(vec1
[0], vec2
[0], name("xcmp"));
669 Value
*x
= m_builder
.CreateSelect(xcmp
, const1f
, const0f
, name("xsel"));
671 Value
*ycmp
= m_builder
.CreateFCmpOEQ(vec1
[1], vec2
[1], name("ycmp"));
672 Value
*y
= m_builder
.CreateSelect(ycmp
, const1f
, const0f
, name("ysel"));
674 Value
*zcmp
= m_builder
.CreateFCmpOEQ(vec1
[2], vec2
[2], name("zcmp"));
675 Value
*z
= m_builder
.CreateSelect(zcmp
, const1f
, const0f
, name("zsel"));
677 Value
*wcmp
= m_builder
.CreateFCmpOEQ(vec1
[3], vec2
[3], name("wcmp"));
678 Value
*w
= m_builder
.CreateSelect(wcmp
, const1f
, const0f
, name("wsel"));
680 return vectorFromVals(x
, y
, z
, w
);
683 llvm::Value
* Instructions::sfl(llvm::Value
*in1
, llvm::Value
*in2
)
685 Constant
*const0f
= Constant::getNullValue(Type::FloatTy
);
687 return vectorFromVals(const0f
, const0f
, const0f
, const0f
);
690 llvm::Value
* Instructions::sge(llvm::Value
*in1
, llvm::Value
*in2
)
692 Constant
*const1f
= ConstantFP::get(APFloat(1.000000e+00f
));
693 Constant
*const0f
= Constant::getNullValue(Type::FloatTy
);
695 std::vector
<llvm::Value
*> vec1
= extractVector(in1
);
696 std::vector
<llvm::Value
*> vec2
= extractVector(in2
);
698 Value
*xcmp
= m_builder
.CreateFCmpOGE(vec1
[0], vec2
[0], name("xcmp"));
699 Value
*x
= m_builder
.CreateSelect(xcmp
, const1f
, const0f
, name("xsel"));
701 Value
*ycmp
= m_builder
.CreateFCmpOGE(vec1
[1], vec2
[1], name("ycmp"));
702 Value
*y
= m_builder
.CreateSelect(ycmp
, const1f
, const0f
, name("ysel"));
704 Value
*zcmp
= m_builder
.CreateFCmpOGE(vec1
[2], vec2
[2], name("zcmp"));
705 Value
*z
= m_builder
.CreateSelect(zcmp
, const1f
, const0f
, name("zsel"));
707 Value
*wcmp
= m_builder
.CreateFCmpOGE(vec1
[3], vec2
[3], name("wcmp"));
708 Value
*w
= m_builder
.CreateSelect(wcmp
, const1f
, const0f
, name("wsel"));
710 return vectorFromVals(x
, y
, z
, w
);
713 llvm::Value
* Instructions::sgt(llvm::Value
*in1
, llvm::Value
*in2
)
715 Constant
*const1f
= ConstantFP::get(APFloat(1.000000e+00f
));
716 Constant
*const0f
= Constant::getNullValue(Type::FloatTy
);
718 std::vector
<llvm::Value
*> vec1
= extractVector(in1
);
719 std::vector
<llvm::Value
*> vec2
= extractVector(in2
);
720 Value
*xcmp
= m_builder
.CreateFCmpOGT(vec1
[0], vec2
[0], name("xcmp"));
721 Value
*x
= m_builder
.CreateSelect(xcmp
, const1f
, const0f
, name("xsel"));
723 Value
*ycmp
= m_builder
.CreateFCmpOGT(vec1
[1], vec2
[1], name("ycmp"));
724 Value
*y
= m_builder
.CreateSelect(ycmp
, const1f
, const0f
, name("ysel"));
726 Value
*zcmp
= m_builder
.CreateFCmpOGT(vec1
[2], vec2
[2], name("zcmp"));
727 Value
*z
= m_builder
.CreateSelect(zcmp
, const1f
, const0f
, name("zsel"));
729 Value
*wcmp
= m_builder
.CreateFCmpOGT(vec1
[3], vec2
[3], name("wcmp"));
730 Value
*w
= m_builder
.CreateSelect(wcmp
, const1f
, const0f
, name("wsel"));
732 return vectorFromVals(x
, y
, z
, w
);
735 llvm::Value
* Instructions::sin(llvm::Value
*in
)
737 llvm::Function
*func
= m_mod
->getFunction("vsin");
740 CallInst
*call
= m_builder
.CreateCall(func
, in
, name("sinres"));
741 call
->setTailCall(false);
745 llvm::Value
* Instructions::sle(llvm::Value
*in1
, llvm::Value
*in2
)
747 Constant
*const1f
= ConstantFP::get(APFloat(1.000000e+00f
));
748 Constant
*const0f
= Constant::getNullValue(Type::FloatTy
);
750 std::vector
<llvm::Value
*> vec1
= extractVector(in1
);
751 std::vector
<llvm::Value
*> vec2
= extractVector(in2
);
753 Value
*xcmp
= m_builder
.CreateFCmpOLE(vec1
[0], vec2
[0], name("xcmp"));
754 Value
*x
= m_builder
.CreateSelect(xcmp
, const1f
, const0f
, name("xsel"));
756 Value
*ycmp
= m_builder
.CreateFCmpOLE(vec1
[1], vec2
[1], name("ycmp"));
757 Value
*y
= m_builder
.CreateSelect(ycmp
, const1f
, const0f
, name("ysel"));
759 Value
*zcmp
= m_builder
.CreateFCmpOLE(vec1
[2], vec2
[2], name("zcmp"));
760 Value
*z
= m_builder
.CreateSelect(zcmp
, const1f
, const0f
, name("zsel"));
762 Value
*wcmp
= m_builder
.CreateFCmpOLE(vec1
[3], vec2
[3], name("wcmp"));
763 Value
*w
= m_builder
.CreateSelect(wcmp
, const1f
, const0f
, name("wsel"));
765 return vectorFromVals(x
, y
, z
, w
);
768 llvm::Value
* Instructions::slt(llvm::Value
*in1
, llvm::Value
*in2
)
770 Constant
*const1f
= ConstantFP::get(APFloat(1.000000e+00f
));
771 Constant
*const0f
= Constant::getNullValue(Type::FloatTy
);
773 std::vector
<llvm::Value
*> vec1
= extractVector(in1
);
774 std::vector
<llvm::Value
*> vec2
= extractVector(in2
);
776 Value
*xcmp
= m_builder
.CreateFCmpOLT(vec1
[0], vec2
[0], name("xcmp"));
777 Value
*x
= m_builder
.CreateSelect(xcmp
, const1f
, const0f
, name("xsel"));
779 Value
*ycmp
= m_builder
.CreateFCmpOLT(vec1
[1], vec2
[1], name("ycmp"));
780 Value
*y
= m_builder
.CreateSelect(ycmp
, const1f
, const0f
, name("ysel"));
782 Value
*zcmp
= m_builder
.CreateFCmpOLT(vec1
[2], vec2
[2], name("zcmp"));
783 Value
*z
= m_builder
.CreateSelect(zcmp
, const1f
, const0f
, name("zsel"));
785 Value
*wcmp
= m_builder
.CreateFCmpOLT(vec1
[3], vec2
[3], name("wcmp"));
786 Value
*w
= m_builder
.CreateSelect(wcmp
, const1f
, const0f
, name("wsel"));
788 return vectorFromVals(x
, y
, z
, w
);
791 llvm::Value
* Instructions::sne(llvm::Value
*in1
, llvm::Value
*in2
)
793 Constant
*const1f
= ConstantFP::get(APFloat(1.000000e+00f
));
794 Constant
*const0f
= Constant::getNullValue(Type::FloatTy
);
796 std::vector
<llvm::Value
*> vec1
= extractVector(in1
);
797 std::vector
<llvm::Value
*> vec2
= extractVector(in2
);
799 Value
*xcmp
= m_builder
.CreateFCmpONE(vec1
[0], vec2
[0], name("xcmp"));
800 Value
*x
= m_builder
.CreateSelect(xcmp
, const1f
, const0f
, name("xsel"));
802 Value
*ycmp
= m_builder
.CreateFCmpONE(vec1
[1], vec2
[1], name("ycmp"));
803 Value
*y
= m_builder
.CreateSelect(ycmp
, const1f
, const0f
, name("ysel"));
805 Value
*zcmp
= m_builder
.CreateFCmpONE(vec1
[2], vec2
[2], name("zcmp"));
806 Value
*z
= m_builder
.CreateSelect(zcmp
, const1f
, const0f
, name("zsel"));
808 Value
*wcmp
= m_builder
.CreateFCmpONE(vec1
[3], vec2
[3], name("wcmp"));
809 Value
*w
= m_builder
.CreateSelect(wcmp
, const1f
, const0f
, name("wsel"));
811 return vectorFromVals(x
, y
, z
, w
);
814 llvm::Value
* Instructions::str(llvm::Value
*in1
, llvm::Value
*in2
)
816 Constant
*const1f
= ConstantFP::get(APFloat(1.000000e+00f
));
818 return vectorFromVals(const1f
, const1f
, const1f
, const1f
);
821 llvm::Value
* Instructions::sub(llvm::Value
*in1
, llvm::Value
*in2
)
823 Value
*res
= m_builder
.CreateSub(in1
, in2
, name("sub"));
827 llvm::Value
* Instructions::trunc(llvm::Value
*in
)
829 std::vector
<llvm::Value
*> vec
= extractVector(in
);
830 Value
*icastx
= m_builder
.CreateFPToSI(vec
[0], IntegerType::get(32),
832 Value
*icasty
= m_builder
.CreateFPToSI(vec
[1], IntegerType::get(32),
834 Value
*icastz
= m_builder
.CreateFPToSI(vec
[2], IntegerType::get(32),
836 Value
*icastw
= m_builder
.CreateFPToSI(vec
[3], IntegerType::get(32),
838 Value
*fx
= m_builder
.CreateSIToFP(icastx
, Type::FloatTy
,
840 Value
*fy
= m_builder
.CreateSIToFP(icasty
, Type::FloatTy
,
842 Value
*fz
= m_builder
.CreateSIToFP(icastz
, Type::FloatTy
,
844 Value
*fw
= m_builder
.CreateSIToFP(icastw
, Type::FloatTy
,
846 return vectorFromVals(fx
, fy
, fz
, fw
);
849 llvm::Value
* Instructions::x2d(llvm::Value
*in1
, llvm::Value
*in2
, llvm::Value
*in3
)
851 std::vector
<llvm::Value
*> vec1
= extractVector(in1
);
852 std::vector
<llvm::Value
*> vec2
= extractVector(in2
);
853 std::vector
<llvm::Value
*> vec3
= extractVector(in3
);
855 Value
*x2x3
= m_builder
.CreateMul( vec2
[0], vec3
[0], name("x2x3"));
856 Value
*y2y3
= m_builder
.CreateMul( vec2
[1], vec3
[1], name("y2y3"));
857 Value
*x1px2x3
= m_builder
.CreateAdd (vec1
[0], x2x3
, name("x1 + x2x3"));
858 Value
*x1px2x3py2y3
= m_builder
.CreateAdd (x1px2x3
, y2y3
, name("x1 + x2x3 + y2y3"));
860 Value
*x2z3
= m_builder
.CreateMul( vec2
[0], vec3
[2], name("x2z3"));
861 Value
*y2w3
= m_builder
.CreateMul( vec2
[1], vec3
[3], name("y2w3"));
862 Value
*y1px2z3
= m_builder
.CreateAdd (vec1
[1], x2z3
, name("y1 + x2z3"));
863 Value
*y1px2z3py2w3
= m_builder
.CreateAdd (y1px2z3
, y2w3
, name("y1 + x2z3 + y2w3"));
865 return vectorFromVals(x1px2x3py2y3
, y1px2z3py2w3
, x1px2x3py2y3
, y1px2z3py2w3
);
868 void Instructions::printVector(llvm::Value
*val
)
870 static const char *frmt
= "Vector is [%f, %f, %f, %f]\x0A";
873 Constant
*format
= ConstantArray::get(frmt
, true);
874 ArrayType
*arrayTy
= ArrayType::get(IntegerType::get(8), strlen(frmt
) + 1);
875 GlobalVariable
* globalFormat
= new GlobalVariable(
878 /*Linkage=*/GlobalValue::InternalLinkage
,
879 /*Initializer=*/0, // has initializer, specified below
880 /*Name=*/name(".str"),
882 globalFormat
->setInitializer(format
);
884 Constant
* const_int0
= Constant::getNullValue(IntegerType::get(32));
885 std::vector
<Constant
*> const_ptr_21_indices
;
886 const_ptr_21_indices
.push_back(const_int0
);
887 const_ptr_21_indices
.push_back(const_int0
);
888 m_fmtPtr
= ConstantExpr::getGetElementPtr(globalFormat
,
889 &const_ptr_21_indices
[0], const_ptr_21_indices
.size());
892 Function
*func_printf
= m_mod
->getFunction("printf");
894 func_printf
= declarePrintf();
896 std::vector
<llvm::Value
*> vec
= extractVector(val
);
897 Value
*dx
= m_builder
.CreateFPExt(vec
[0], Type::DoubleTy
, name("dx"));
898 Value
*dy
= m_builder
.CreateFPExt(vec
[1], Type::DoubleTy
, name("dy"));
899 Value
*dz
= m_builder
.CreateFPExt(vec
[2], Type::DoubleTy
, name("dz"));
900 Value
*dw
= m_builder
.CreateFPExt(vec
[3], Type::DoubleTy
, name("dw"));
901 std::vector
<Value
*> params
;
902 params
.push_back(m_fmtPtr
);
903 params
.push_back(dx
);
904 params
.push_back(dy
);
905 params
.push_back(dz
);
906 params
.push_back(dw
);
907 CallInst
*call
= m_builder
.CreateCall(func_printf
, params
.begin(), params
.end(),
909 call
->setCallingConv(CallingConv::C
);
910 call
->setTailCall(true);
913 const char * Instructions::name(const char *prefix
)
916 snprintf(m_name
, 32, "%s%d", prefix
, m_idx
);
920 llvm::Value
* Instructions::callCeil(llvm::Value
*val
)
923 // predeclare the intrinsic
924 std::vector
<const Type
*> ceilArgs
;
925 ceilArgs
.push_back(Type::FloatTy
);
927 FunctionType
* ceilType
= FunctionType::get(
928 /*Result=*/Type::FloatTy
,
931 m_llvmCeil
= Function::Create(
933 /*Linkage=*/GlobalValue::ExternalLinkage
,
934 /*Name=*/"ceilf", m_mod
);
935 m_llvmCeil
->setCallingConv(CallingConv::C
);
936 m_llvmCeil
->setAttributes(ceilPal
);
938 CallInst
*call
= m_builder
.CreateCall(m_llvmCeil
, val
,
940 call
->setCallingConv(CallingConv::C
);
941 call
->setTailCall(false);
945 llvm::Value
*Instructions::callFAbs(llvm::Value
*val
)
948 // predeclare the intrinsic
949 std::vector
<const Type
*> fabsArgs
;
950 fabsArgs
.push_back(Type::FloatTy
);
952 FunctionType
* fabsType
= FunctionType::get(
953 /*Result=*/Type::FloatTy
,
956 m_llvmFAbs
= Function::Create(
958 /*Linkage=*/GlobalValue::ExternalLinkage
,
959 /*Name=*/"fabs", m_mod
);
960 m_llvmFAbs
->setCallingConv(CallingConv::C
);
961 m_llvmFAbs
->setAttributes(fabsPal
);
963 CallInst
*call
= m_builder
.CreateCall(m_llvmFAbs
, val
,
965 call
->setCallingConv(CallingConv::C
);
966 call
->setTailCall(false);
970 llvm::Value
* Instructions::callFExp(llvm::Value
*val
)
973 // predeclare the intrinsic
974 std::vector
<const Type
*> fexpArgs
;
975 fexpArgs
.push_back(Type::FloatTy
);
977 FunctionType
* fexpType
= FunctionType::get(
978 /*Result=*/Type::FloatTy
,
981 m_llvmFexp
= Function::Create(
983 /*Linkage=*/GlobalValue::ExternalLinkage
,
984 /*Name=*/"expf", m_mod
);
985 m_llvmFexp
->setCallingConv(CallingConv::C
);
986 m_llvmFexp
->setAttributes(fexpPal
);
988 CallInst
*call
= m_builder
.CreateCall(m_llvmFexp
, val
,
990 call
->setCallingConv(CallingConv::C
);
991 call
->setTailCall(false);
995 llvm::Value
* Instructions::callFLog(llvm::Value
*val
)
998 // predeclare the intrinsic
999 std::vector
<const Type
*> flogArgs
;
1000 flogArgs
.push_back(Type::FloatTy
);
1001 AttrListPtr flogPal
;
1002 FunctionType
* flogType
= FunctionType::get(
1003 /*Result=*/Type::FloatTy
,
1004 /*Params=*/flogArgs
,
1005 /*isVarArg=*/false);
1006 m_llvmFlog
= Function::Create(
1008 /*Linkage=*/GlobalValue::ExternalLinkage
,
1009 /*Name=*/"logf", m_mod
);
1010 m_llvmFlog
->setCallingConv(CallingConv::C
);
1011 m_llvmFlog
->setAttributes(flogPal
);
1013 CallInst
*call
= m_builder
.CreateCall(m_llvmFlog
, val
,
1015 call
->setCallingConv(CallingConv::C
);
1016 call
->setTailCall(false);
1020 llvm::Value
* Instructions::callFloor(llvm::Value
*val
)
1023 // predeclare the intrinsic
1024 std::vector
<const Type
*> floorArgs
;
1025 floorArgs
.push_back(Type::FloatTy
);
1026 AttrListPtr floorPal
;
1027 FunctionType
* floorType
= FunctionType::get(
1028 /*Result=*/Type::FloatTy
,
1029 /*Params=*/floorArgs
,
1030 /*isVarArg=*/false);
1031 m_llvmFloor
= Function::Create(
1033 /*Linkage=*/GlobalValue::ExternalLinkage
,
1034 /*Name=*/"floorf", m_mod
);
1035 m_llvmFloor
->setCallingConv(CallingConv::C
);
1036 m_llvmFloor
->setAttributes(floorPal
);
1038 CallInst
*call
= m_builder
.CreateCall(m_llvmFloor
, val
,
1040 call
->setCallingConv(CallingConv::C
);
1041 call
->setTailCall(false);
1045 llvm::Value
*Instructions::callFSqrt(llvm::Value
*val
)
1048 // predeclare the intrinsic
1049 std::vector
<const Type
*> fsqrtArgs
;
1050 fsqrtArgs
.push_back(Type::FloatTy
);
1051 AttrListPtr fsqrtPal
;
1052 FunctionType
* fsqrtType
= FunctionType::get(
1053 /*Result=*/Type::FloatTy
,
1054 /*Params=*/fsqrtArgs
,
1055 /*isVarArg=*/false);
1056 m_llvmFSqrt
= Function::Create(
1058 /*Linkage=*/GlobalValue::ExternalLinkage
,
1059 /*Name=*/"llvm.sqrt.f32", m_mod
);
1060 m_llvmFSqrt
->setCallingConv(CallingConv::C
);
1061 m_llvmFSqrt
->setAttributes(fsqrtPal
);
1063 CallInst
*call
= m_builder
.CreateCall(m_llvmFSqrt
, val
,
1065 call
->setCallingConv(CallingConv::C
);
1066 call
->setTailCall(false);
1070 llvm::Value
* Instructions::callPow(llvm::Value
*val1
, llvm::Value
*val2
)
1073 // predeclare the intrinsic
1074 std::vector
<const Type
*> powArgs
;
1075 powArgs
.push_back(Type::FloatTy
);
1076 powArgs
.push_back(Type::FloatTy
);
1078 FunctionType
* powType
= FunctionType::get(
1079 /*Result=*/Type::FloatTy
,
1081 /*isVarArg=*/false);
1082 m_llvmPow
= Function::Create(
1084 /*Linkage=*/GlobalValue::ExternalLinkage
,
1085 /*Name=*/"llvm.pow.f32", m_mod
);
1086 m_llvmPow
->setCallingConv(CallingConv::C
);
1087 m_llvmPow
->setAttributes(powPal
);
1089 std::vector
<Value
*> params
;
1090 params
.push_back(val1
);
1091 params
.push_back(val2
);
1092 CallInst
*call
= m_builder
.CreateCall(m_llvmPow
, params
.begin(), params
.end(),
1094 call
->setCallingConv(CallingConv::C
);
1095 call
->setTailCall(false);
1099 llvm::Value
* Instructions::vectorFromVals(llvm::Value
*x
, llvm::Value
*y
,
1100 llvm::Value
*z
, llvm::Value
*w
)
1102 Constant
*const_vec
= Constant::getNullValue(m_floatVecType
);
1103 Value
*res
= m_builder
.CreateInsertElement(const_vec
, x
,
1104 m_storage
->constantInt(0),
1106 res
= m_builder
.CreateInsertElement(res
, y
, m_storage
->constantInt(1),
1108 res
= m_builder
.CreateInsertElement(res
, z
, m_storage
->constantInt(2),
1111 res
= m_builder
.CreateInsertElement(res
, w
, m_storage
->constantInt(3),
1116 llvm::Value
* Instructions::constVector(float x
, float y
, float z
, float w
)
1118 std::vector
<Constant
*> vec(4);
1119 vec
[0] = ConstantFP::get(APFloat(x
));
1120 vec
[1] = ConstantFP::get(APFloat(y
));
1121 vec
[2] = ConstantFP::get(APFloat(z
));
1122 vec
[3] = ConstantFP::get(APFloat(w
));
1123 return ConstantVector::get(m_floatVecType
, vec
);
1126 llvm::Function
* Instructions::declarePrintf()
1128 std::vector
<const Type
*> args
;
1130 FunctionType
* funcTy
= FunctionType::get(
1131 /*Result=*/IntegerType::get(32),
1134 Function
* func_printf
= Function::Create(
1136 /*Linkage=*/GlobalValue::ExternalLinkage
,
1137 /*Name=*/"printf", m_mod
);
1138 func_printf
->setCallingConv(CallingConv::C
);
1139 func_printf
->setAttributes(params
);
1143 llvm::Function
* Instructions::declareFunc(int label
)
1145 PointerType
*vecPtr
= PointerType::getUnqual(m_floatVecType
);
1146 std::vector
<const Type
*> args
;
1147 args
.push_back(vecPtr
);
1148 args
.push_back(vecPtr
);
1149 args
.push_back(vecPtr
);
1150 args
.push_back(vecPtr
);
1152 FunctionType
*funcType
= FunctionType::get(
1153 /*Result=*/Type::VoidTy
,
1155 /*isVarArg=*/false);
1156 std::string name
= createFuncName(label
);
1157 Function
*func
= Function::Create(
1159 /*Linkage=*/GlobalValue::ExternalLinkage
,
1160 /*Name=*/name
.c_str(), m_mod
);
1161 func
->setCallingConv(CallingConv::C
);
1162 func
->setAttributes(params
);
1166 llvm::Function
* Instructions::findFunction(int label
)
1168 llvm::Function
*func
= m_functions
[label
];
1170 func
= declareFunc(label
);
1171 m_functions
[label
] = func
;
1176 std::vector
<llvm::Value
*> Instructions::extractVector(llvm::Value
*vec
)
1178 std::vector
<llvm::Value
*> elems(4);
1179 elems
[0] = m_builder
.CreateExtractElement(vec
, m_storage
->constantInt(0),
1181 elems
[1] = m_builder
.CreateExtractElement(vec
, m_storage
->constantInt(1),
1183 elems
[2] = m_builder
.CreateExtractElement(vec
, m_storage
->constantInt(2),
1185 elems
[3] = m_builder
.CreateExtractElement(vec
, m_storage
->constantInt(3),