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/ParameterAttributes.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);
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
);
95 llvm::Value
* Instructions::add(llvm::Value
*in1
, llvm::Value
*in2
)
97 return m_builder
.CreateAdd(in1
, in2
, name("add"));
100 llvm::Value
* Instructions::madd(llvm::Value
*in1
, llvm::Value
*in2
,
103 Value
*mulRes
= mul(in1
, in2
);
104 return add(mulRes
, in3
);
107 llvm::Value
* Instructions::mul(llvm::Value
*in1
, llvm::Value
*in2
)
109 return m_builder
.CreateMul(in1
, in2
, name("mul"));
112 const char * Instructions::name(const char *prefix
)
115 snprintf(m_name
, 32, "%s%d", prefix
, m_idx
);
119 llvm::Value
* Instructions::dp3(llvm::Value
*in1
, llvm::Value
*in2
)
121 Value
*mulRes
= mul(in1
, in2
);
122 Value
*x
= m_builder
.CreateExtractElement(mulRes
,
123 m_storage
->constantInt(0),
125 Value
*y
= m_builder
.CreateExtractElement(mulRes
,
126 m_storage
->constantInt(1),
128 Value
*z
= m_builder
.CreateExtractElement(mulRes
,
129 m_storage
->constantInt(2),
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
);
136 llvm::Value
*Instructions::callFSqrt(llvm::Value
*val
)
139 // predeclare the intrinsic
140 std::vector
<const Type
*> fsqrtArgs
;
141 fsqrtArgs
.push_back(Type::FloatTy
);
143 FunctionType
* fsqrtType
= FunctionType::get(
144 /*Result=*/Type::FloatTy
,
145 /*Params=*/fsqrtArgs
,
147 m_llvmFSqrt
= Function::Create(
149 /*Linkage=*/GlobalValue::ExternalLinkage
,
150 /*Name=*/"llvm.sqrt.f32", m_mod
);
151 m_llvmFSqrt
->setCallingConv(CallingConv::C
);
152 m_llvmFSqrt
->setParamAttrs(fsqrtPal
);
154 CallInst
*call
= m_builder
.CreateCall(m_llvmFSqrt
, val
,
156 call
->setCallingConv(CallingConv::C
);
157 call
->setTailCall(false);
161 llvm::Value
* Instructions::rsq(llvm::Value
*in1
)
163 Value
*x
= m_builder
.CreateExtractElement(in1
,
164 m_storage
->constantInt(0),
166 Value
*abs
= callFAbs(x
);
167 Value
*sqrt
= callFSqrt(abs
);
169 Value
*rsqrt
= m_builder
.CreateFDiv(ConstantFP::get(APFloat(1.f
)),
172 return vectorFromVals(rsqrt
, rsqrt
, rsqrt
, rsqrt
);
175 llvm::Value
* Instructions::vectorFromVals(llvm::Value
*x
, llvm::Value
*y
,
176 llvm::Value
*z
, llvm::Value
*w
)
178 Constant
*const_vec
= Constant::getNullValue(m_floatVecType
);
179 Value
*res
= m_builder
.CreateInsertElement(const_vec
, x
,
180 m_storage
->constantInt(0),
182 res
= m_builder
.CreateInsertElement(res
, y
, m_storage
->constantInt(1),
184 res
= m_builder
.CreateInsertElement(res
, z
, m_storage
->constantInt(2),
187 res
= m_builder
.CreateInsertElement(res
, w
, m_storage
->constantInt(3),
192 llvm::Value
*Instructions::callFAbs(llvm::Value
*val
)
195 // predeclare the intrinsic
196 std::vector
<const Type
*> fabsArgs
;
197 fabsArgs
.push_back(Type::FloatTy
);
199 FunctionType
* fabsType
= FunctionType::get(
200 /*Result=*/Type::FloatTy
,
203 m_llvmFAbs
= Function::Create(
205 /*Linkage=*/GlobalValue::ExternalLinkage
,
206 /*Name=*/"fabs", m_mod
);
207 m_llvmFAbs
->setCallingConv(CallingConv::C
);
208 m_llvmFAbs
->setParamAttrs(fabsPal
);
210 CallInst
*call
= m_builder
.CreateCall(m_llvmFAbs
, val
,
212 call
->setCallingConv(CallingConv::C
);
213 call
->setTailCall(false);
217 llvm::Value
* Instructions::lit(llvm::Value
*in
)
220 m_llvmLit
= m_mod
->getFunction("lit");
222 CallInst
*call
= m_builder
.CreateCall(m_llvmLit
, in
, name("litres"));
223 call
->setCallingConv(CallingConv::C
);
224 call
->setTailCall(false);
228 llvm::Value
* Instructions::sub(llvm::Value
*in1
, llvm::Value
*in2
)
230 Value
*res
= m_builder
.CreateSub(in1
, in2
, name("sub"));
234 llvm::Value
* Instructions::callPow(llvm::Value
*val1
, llvm::Value
*val2
)
237 // predeclare the intrinsic
238 std::vector
<const Type
*> powArgs
;
239 powArgs
.push_back(Type::FloatTy
);
240 powArgs
.push_back(Type::FloatTy
);
242 FunctionType
* powType
= FunctionType::get(
243 /*Result=*/Type::FloatTy
,
246 m_llvmPow
= Function::Create(
248 /*Linkage=*/GlobalValue::ExternalLinkage
,
249 /*Name=*/"llvm.pow.f32", m_mod
);
250 m_llvmPow
->setCallingConv(CallingConv::C
);
251 m_llvmPow
->setParamAttrs(powPal
);
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(),
258 call
->setCallingConv(CallingConv::C
);
259 call
->setTailCall(false);
263 llvm::Value
* Instructions::pow(llvm::Value
*in1
, llvm::Value
*in2
)
265 Value
*x1
= m_builder
.CreateExtractElement(in1
,
266 m_storage
->constantInt(0),
268 Value
*x2
= m_builder
.CreateExtractElement(in2
,
269 m_storage
->constantInt(0),
271 llvm::Value
*val
= callPow(x1
, x2
);
272 return vectorFromVals(val
, val
, val
, val
);
275 llvm::Value
* Instructions::rcp(llvm::Value
*in1
)
277 Value
*x1
= m_builder
.CreateExtractElement(in1
,
278 m_storage
->constantInt(0),
280 Value
*res
= m_builder
.CreateFDiv(ConstantFP::get(APFloat(1.f
)),
282 return vectorFromVals(res
, res
, res
, res
);
285 llvm::Value
* Instructions::dp4(llvm::Value
*in1
, llvm::Value
*in2
)
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
);
295 llvm::Value
* Instructions::dph(llvm::Value
*in1
, llvm::Value
*in2
)
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
);
305 llvm::Value
* Instructions::dst(llvm::Value
*in1
, llvm::Value
*in2
)
307 Value
*y1
= m_builder
.CreateExtractElement(in1
,
308 m_storage
->constantInt(1),
310 Value
*z
= m_builder
.CreateExtractElement(in1
,
311 m_storage
->constantInt(2),
313 Value
*y2
= m_builder
.CreateExtractElement(in2
,
314 m_storage
->constantInt(1),
316 Value
*w
= m_builder
.CreateExtractElement(in2
,
317 m_storage
->constantInt(3),
319 Value
*ry
= m_builder
.CreateMul(y1
, y2
, name("tyuy"));
320 return vectorFromVals(ConstantFP::get(APFloat(1.f
)),
324 llvm::Value
* Instructions::ex2(llvm::Value
*in
)
326 llvm::Value
*val
= callPow(ConstantFP::get(APFloat(2.f
)),
327 m_builder
.CreateExtractElement(
328 in
, m_storage
->constantInt(0),
330 return vectorFromVals(val
, val
, val
, val
);
333 llvm::Value
* Instructions::callFloor(llvm::Value
*val
)
336 // predeclare the intrinsic
337 std::vector
<const Type
*> floorArgs
;
338 floorArgs
.push_back(Type::FloatTy
);
340 FunctionType
* floorType
= FunctionType::get(
341 /*Result=*/Type::FloatTy
,
342 /*Params=*/floorArgs
,
344 m_llvmFloor
= Function::Create(
346 /*Linkage=*/GlobalValue::ExternalLinkage
,
347 /*Name=*/"floorf", m_mod
);
348 m_llvmFloor
->setCallingConv(CallingConv::C
);
349 m_llvmFloor
->setParamAttrs(floorPal
);
351 CallInst
*call
= m_builder
.CreateCall(m_llvmFloor
, val
,
353 call
->setCallingConv(CallingConv::C
);
354 call
->setTailCall(false);
358 llvm::Value
* Instructions::floor(llvm::Value
*in
)
360 std::vector
<llvm::Value
*> vec
= extractVector(in
);
361 return vectorFromVals(callFloor(vec
[0]), callFloor(vec
[1]),
362 callFloor(vec
[2]), callFloor(vec
[3]));
365 llvm::Value
* Instructions::arl(llvm::Value
*in
)
370 llvm::Value
* Instructions::frc(llvm::Value
*in
)
372 llvm::Value
*flr
= floor(in
);
376 llvm::Value
* Instructions::callFLog(llvm::Value
*val
)
379 // predeclare the intrinsic
380 std::vector
<const Type
*> flogArgs
;
381 flogArgs
.push_back(Type::FloatTy
);
383 FunctionType
* flogType
= FunctionType::get(
384 /*Result=*/Type::FloatTy
,
387 m_llvmFlog
= Function::Create(
389 /*Linkage=*/GlobalValue::ExternalLinkage
,
390 /*Name=*/"logf", m_mod
);
391 m_llvmFlog
->setCallingConv(CallingConv::C
);
392 m_llvmFlog
->setParamAttrs(flogPal
);
394 CallInst
*call
= m_builder
.CreateCall(m_llvmFlog
, val
,
396 call
->setCallingConv(CallingConv::C
);
397 call
->setTailCall(false);
401 llvm::Value
* Instructions::lg2(llvm::Value
*in
)
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
);
410 llvm::Value
* Instructions::min(llvm::Value
*in1
, llvm::Value
*in2
)
412 std::vector
<llvm::Value
*> vec1
= extractVector(in1
);
413 std::vector
<llvm::Value
*> vec2
= extractVector(in2
);
415 Value
*xcmp
= m_builder
.CreateFCmpOLT(vec1
[0], vec2
[0], name("xcmp"));
416 Value
*selx
= m_builder
.CreateSelect(xcmp
, vec1
[0], vec2
[0],
419 Value
*ycmp
= m_builder
.CreateFCmpOLT(vec1
[1], vec2
[1], name("ycmp"));
420 Value
*sely
= m_builder
.CreateSelect(ycmp
, vec1
[1], vec2
[1],
423 Value
*zcmp
= m_builder
.CreateFCmpOLT(vec1
[2], vec2
[2], name("zcmp"));
424 Value
*selz
= m_builder
.CreateSelect(zcmp
, vec1
[2], vec2
[2],
427 Value
*wcmp
= m_builder
.CreateFCmpOLT(vec1
[3], vec2
[3], name("wcmp"));
428 Value
*selw
= m_builder
.CreateSelect(wcmp
, vec1
[3], vec2
[3],
431 return vectorFromVals(selx
, sely
, selz
, selw
);
434 llvm::Value
* Instructions::max(llvm::Value
*in1
, llvm::Value
*in2
)
436 std::vector
<llvm::Value
*> vec1
= extractVector(in1
);
437 std::vector
<llvm::Value
*> vec2
= extractVector(in2
);
439 Value
*xcmp
= m_builder
.CreateFCmpOGT(vec1
[0], vec2
[0],
441 Value
*selx
= m_builder
.CreateSelect(xcmp
, vec1
[0], vec2
[0],
444 Value
*ycmp
= m_builder
.CreateFCmpOGT(vec1
[1], vec2
[1],
446 Value
*sely
= m_builder
.CreateSelect(ycmp
, vec1
[1], vec2
[1],
449 Value
*zcmp
= m_builder
.CreateFCmpOGT(vec1
[2], vec2
[2],
451 Value
*selz
= m_builder
.CreateSelect(zcmp
, vec1
[2], vec2
[2],
454 Value
*wcmp
= m_builder
.CreateFCmpOGT(vec1
[3], vec2
[3],
456 Value
*selw
= m_builder
.CreateSelect(wcmp
, vec1
[3], vec2
[3],
459 return vectorFromVals(selx
, sely
, selz
, selw
);
462 void Instructions::printVector(llvm::Value
*val
)
464 static const char *frmt
= "Vector is [%f, %f, %f, %f]\x0A";
467 Constant
*format
= ConstantArray::get(frmt
, true);
468 ArrayType
*arrayTy
= ArrayType::get(IntegerType::get(8), strlen(frmt
) + 1);
469 GlobalVariable
* globalFormat
= new GlobalVariable(
472 /*Linkage=*/GlobalValue::InternalLinkage
,
473 /*Initializer=*/0, // has initializer, specified below
474 /*Name=*/name(".str"),
476 globalFormat
->setInitializer(format
);
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());
486 Function
*func_printf
= m_mod
->getFunction("printf");
488 func_printf
= declarePrintf();
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(),
503 call
->setCallingConv(CallingConv::C
);
504 call
->setTailCall(true);
507 llvm::Function
* Instructions::declarePrintf()
509 std::vector
<const Type
*> args
;
511 FunctionType
* funcTy
= FunctionType::get(
512 /*Result=*/IntegerType::get(32),
515 Function
* func_printf
= Function::Create(
517 /*Linkage=*/GlobalValue::ExternalLinkage
,
518 /*Name=*/"printf", m_mod
);
519 func_printf
->setCallingConv(CallingConv::C
);
520 func_printf
->setParamAttrs(params
);
525 llvm::Value
* Instructions::sgt(llvm::Value
*in1
, llvm::Value
*in2
)
527 Constant
*const1f
= ConstantFP::get(APFloat(1.000000e+00f
));
528 Constant
*const0f
= Constant::getNullValue(Type::FloatTy
);
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"));
535 Value
*ycmp
= m_builder
.CreateFCmpOGT(vec1
[1], vec2
[1], name("ycmp"));
536 Value
*y
= m_builder
.CreateSelect(ycmp
, const1f
, const0f
, name("ysel"));
538 Value
*zcmp
= m_builder
.CreateFCmpOGT(vec1
[2], vec2
[2], name("zcmp"));
539 Value
*z
= m_builder
.CreateSelect(zcmp
, const1f
, const0f
, name("zsel"));
541 Value
*wcmp
= m_builder
.CreateFCmpOGT(vec1
[3], vec2
[3], name("wcmp"));
542 Value
*w
= m_builder
.CreateSelect(wcmp
, const1f
, const0f
, name("wsel"));
544 return vectorFromVals(x
, y
, z
, w
);
546 llvm::Value
* Instructions::sge(llvm::Value
*in1
, llvm::Value
*in2
)
548 Constant
*const1f
= ConstantFP::get(APFloat(1.000000e+00f
));
549 Constant
*const0f
= Constant::getNullValue(Type::FloatTy
);
551 std::vector
<llvm::Value
*> vec1
= extractVector(in1
);
552 std::vector
<llvm::Value
*> vec2
= extractVector(in2
);
554 Value
*xcmp
= m_builder
.CreateFCmpOGE(vec1
[0], vec2
[0], name("xcmp"));
555 Value
*x
= m_builder
.CreateSelect(xcmp
, const1f
, const0f
, name("xsel"));
557 Value
*ycmp
= m_builder
.CreateFCmpOGE(vec1
[1], vec2
[1], name("ycmp"));
558 Value
*y
= m_builder
.CreateSelect(ycmp
, const1f
, const0f
, name("ysel"));
560 Value
*zcmp
= m_builder
.CreateFCmpOGE(vec1
[2], vec2
[2], name("zcmp"));
561 Value
*z
= m_builder
.CreateSelect(zcmp
, const1f
, const0f
, name("zsel"));
563 Value
*wcmp
= m_builder
.CreateFCmpOGE(vec1
[3], vec2
[3], name("wcmp"));
564 Value
*w
= m_builder
.CreateSelect(wcmp
, const1f
, const0f
, name("wsel"));
566 return vectorFromVals(x
, y
, z
, w
);
570 llvm::Value
* Instructions::slt(llvm::Value
*in1
, llvm::Value
*in2
)
572 Constant
*const1f
= ConstantFP::get(APFloat(1.000000e+00f
));
573 Constant
*const0f
= Constant::getNullValue(Type::FloatTy
);
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
*x
= m_builder
.CreateSelect(xcmp
, const1f
, const0f
, name("xsel"));
581 Value
*ycmp
= m_builder
.CreateFCmpOLT(vec1
[1], vec2
[1], name("ycmp"));
582 Value
*y
= m_builder
.CreateSelect(ycmp
, const1f
, const0f
, name("ysel"));
584 Value
*zcmp
= m_builder
.CreateFCmpOLT(vec1
[2], vec2
[2], name("zcmp"));
585 Value
*z
= m_builder
.CreateSelect(zcmp
, const1f
, const0f
, name("zsel"));
587 Value
*wcmp
= m_builder
.CreateFCmpOLT(vec1
[3], vec2
[3], name("wcmp"));
588 Value
*w
= m_builder
.CreateSelect(wcmp
, const1f
, const0f
, name("wsel"));
590 return vectorFromVals(x
, y
, z
, w
);
593 llvm::Value
* Instructions::cross(llvm::Value
*in1
, llvm::Value
*in2
)
595 Value
*x1
= m_builder
.CreateExtractElement(in1
,
596 m_storage
->constantInt(0),
598 Value
*y1
= m_builder
.CreateExtractElement(in1
,
599 m_storage
->constantInt(1),
601 Value
*z1
= m_builder
.CreateExtractElement(in1
,
602 m_storage
->constantInt(2),
605 Value
*x2
= m_builder
.CreateExtractElement(in2
,
606 m_storage
->constantInt(0),
608 Value
*y2
= m_builder
.CreateExtractElement(in2
,
609 m_storage
->constantInt(1),
611 Value
*z2
= m_builder
.CreateExtractElement(in2
,
612 m_storage
->constantInt(2),
614 Value
*y1z2
= mul(y1
, z2
);
615 Value
*z1y2
= mul(z1
, y2
);
617 Value
*z1x2
= mul(z1
, x2
);
618 Value
*x1z2
= mul(x1
, z2
);
620 Value
*x1y2
= mul(x1
, y2
);
621 Value
*y1x2
= mul(y1
, x2
);
623 return vectorFromVals(sub(y1z2
, z1y2
), sub(z1x2
, x1z2
), sub(x1y2
, y1x2
));
627 llvm::Value
* Instructions::abs(llvm::Value
*in
)
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
);
637 void Instructions::ifop(llvm::Value
*in
)
639 BasicBlock
*ifthen
= BasicBlock::Create(name("ifthen"), m_func
,0);
640 BasicBlock
*ifend
= BasicBlock::Create(name("ifthenend"), m_func
,0);
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);
646 Constant
*float0
= Constant::getNullValue(Type::FloatTy
);
648 Value
*x
= m_builder
.CreateExtractElement(in
, m_storage
->constantInt(0),
650 Value
*xcmp
= m_builder
.CreateFCmpUNE(x
, float0
, name("xcmp"));
651 m_builder
.CreateCondBr(xcmp
, ifthen
, ifend
);
652 //m_builder.SetInsertPoint(yblock);
654 m_builder
.SetInsertPoint(ifthen
);
655 m_ifStack
.push(ifend
);
658 llvm::BasicBlock
* Instructions::currentBlock() const
660 return m_builder
.GetInsertBlock();
663 void Instructions::elseop()
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"));
671 m_ifStack
.push(ifend
);
674 void Instructions::endif()
676 assert(!m_ifStack
.empty());
677 m_builder
.CreateBr(m_ifStack
.top());
678 m_builder
.SetInsertPoint(m_ifStack
.top());
682 llvm::Value
* Instructions::lerp(llvm::Value
*in1
, llvm::Value
*in2
,
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
));
691 void Instructions::beginLoop()
693 BasicBlock
*begin
= BasicBlock::Create(name("loop"), m_func
,0);
694 BasicBlock
*end
= BasicBlock::Create(name("endloop"), m_func
,0);
696 m_builder
.CreateBr(begin
);
700 m_builder
.SetInsertPoint(begin
);
701 m_loopStack
.push(loop
);
704 void Instructions::endLoop()
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
);
714 void Instructions::brk()
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
);
722 llvm::Value
* Instructions::trunc(llvm::Value
*in
)
724 std::vector
<llvm::Value
*> vec
= extractVector(in
);
725 Value
*icastx
= m_builder
.CreateFPToSI(vec
[0], IntegerType::get(32),
727 Value
*icasty
= m_builder
.CreateFPToSI(vec
[1], IntegerType::get(32),
729 Value
*icastz
= m_builder
.CreateFPToSI(vec
[2], IntegerType::get(32),
731 Value
*icastw
= m_builder
.CreateFPToSI(vec
[3], IntegerType::get(32),
733 Value
*fx
= m_builder
.CreateSIToFP(icastx
, Type::FloatTy
,
735 Value
*fy
= m_builder
.CreateSIToFP(icasty
, Type::FloatTy
,
737 Value
*fz
= m_builder
.CreateSIToFP(icastz
, Type::FloatTy
,
739 Value
*fw
= m_builder
.CreateSIToFP(icastw
, Type::FloatTy
,
741 return vectorFromVals(fx
, fy
, fz
, fw
);
744 void Instructions::end()
746 m_builder
.CreateRetVoid();
749 void Instructions::cal(int label
, llvm::Value
*input
)
751 std::vector
<Value
*> params
;
752 params
.push_back(input
);
753 llvm::Function
*func
= findFunction(label
);
755 m_builder
.CreateCall(func
, params
.begin(), params
.end());
758 llvm::Function
* Instructions::declareFunc(int label
)
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
);
767 FunctionType
*funcType
= FunctionType::get(
768 /*Result=*/Type::VoidTy
,
771 std::string name
= createFuncName(label
);
772 Function
*func
= Function::Create(
774 /*Linkage=*/GlobalValue::ExternalLinkage
,
775 /*Name=*/name
.c_str(), m_mod
);
776 func
->setCallingConv(CallingConv::C
);
777 func
->setParamAttrs(params
);
781 void Instructions::bgnSub(unsigned label
)
783 llvm::Function
*func
= findFunction(label
);
785 Function::arg_iterator args
= func
->arg_begin();
786 Value
*ptr_INPUT
= args
++;
787 ptr_INPUT
->setName("INPUT");
788 m_storage
->pushArguments(ptr_INPUT
);
790 llvm::BasicBlock
*entry
= BasicBlock::Create("entry", func
, 0);
793 m_builder
.SetInsertPoint(entry
);
796 void Instructions::endSub()
799 m_builder
.SetInsertPoint(0);
802 llvm::Function
* Instructions::findFunction(int label
)
804 llvm::Function
*func
= m_functions
[label
];
806 func
= declareFunc(label
);
807 m_functions
[label
] = func
;
812 llvm::Value
* Instructions::constVector(float x
, float y
, float z
, float w
)
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
);
823 std::vector
<llvm::Value
*> Instructions::extractVector(llvm::Value
*vec
)
825 std::vector
<llvm::Value
*> elems(4);
826 elems
[0] = m_builder
.CreateExtractElement(vec
, m_storage
->constantInt(0),
828 elems
[1] = m_builder
.CreateExtractElement(vec
, m_storage
->constantInt(1),
830 elems
[2] = m_builder
.CreateExtractElement(vec
, m_storage
->constantInt(2),
832 elems
[3] = m_builder
.CreateExtractElement(vec
, m_storage
->constantInt(3),
837 llvm::Value
* Instructions::cmp(llvm::Value
*in1
, llvm::Value
*in2
, llvm::Value
*in3
)
839 llvm::Function
*func
= m_mod
->getFunction("cmp");
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);
851 llvm::Value
* Instructions::cos(llvm::Value
*in
)
854 llvm::Function
*func
= m_mod
->getFunction("vcos");
857 CallInst
*call
= m_builder
.CreateCall(func
, in
, name("cosres"));
858 call
->setTailCall(false);
861 std::vector
<llvm::Value
*> elems
= extractVector(in
);
862 Function
*func
= m_mod
->getFunction("cosf");
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
);
871 llvm::Value
* Instructions::scs(llvm::Value
*in
)
873 llvm::Function
*func
= m_mod
->getFunction("scs");
876 CallInst
*call
= m_builder
.CreateCall(func
, in
, name("scsres"));
877 call
->setTailCall(false);
881 llvm::Value
* Instructions::kil(llvm::Value
*in
)
883 llvm::Function
*func
= m_mod
->getFunction("kil");
886 CallInst
*call
= m_builder
.CreateCall(func
, in
, name("kilpres"));
887 call
->setTailCall(false);
891 llvm::Value
* Instructions::sin(llvm::Value
*in
)
893 llvm::Function
*func
= m_mod
->getFunction("vsin");
896 CallInst
*call
= m_builder
.CreateCall(func
, in
, name("sinres"));
897 call
->setTailCall(false);