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 <llvm/CallingConv.h>
39 #include <llvm/Constants.h>
40 #include <llvm/DerivedTypes.h>
41 #include <llvm/Function.h>
42 #include <llvm/InstrTypes.h>
43 #include <llvm/Instructions.h>
44 #include <llvm/ParameterAttributes.h>
52 #include "gallivm_builtins.cpp"
54 static inline std::string
createFuncName(int label
)
56 std::ostringstream stream
;
62 Instructions::Instructions(llvm::Module
*mod
, llvm::Function
*func
, llvm::BasicBlock
*block
,
64 : m_mod(mod
), m_func(func
), m_builder(block
), m_idx(0),
67 m_floatVecType
= VectorType::get(Type::FloatTy
, 4);
77 createGallivmBuiltins(m_mod
);
80 llvm::Value
* Instructions::add(llvm::Value
*in1
, llvm::Value
*in2
)
82 return m_builder
.CreateAdd(in1
, in2
, name("add"));
85 llvm::Value
* Instructions::madd(llvm::Value
*in1
, llvm::Value
*in2
,
88 Value
*mulRes
= mul(in1
, in2
);
89 return add(mulRes
, in3
);
92 llvm::Value
* Instructions::mul(llvm::Value
*in1
, llvm::Value
*in2
)
94 return m_builder
.CreateMul(in1
, in2
, name("mul"));
97 const char * Instructions::name(const char *prefix
)
100 snprintf(m_name
, 32, "%s%d", prefix
, m_idx
);
104 llvm::Value
* Instructions::dp3(llvm::Value
*in1
, llvm::Value
*in2
)
106 Value
*mulRes
= mul(in1
, in2
);
107 Value
*x
= m_builder
.CreateExtractElement(mulRes
,
108 m_storage
->constantInt(0),
110 Value
*y
= m_builder
.CreateExtractElement(mulRes
,
111 m_storage
->constantInt(1),
113 Value
*z
= m_builder
.CreateExtractElement(mulRes
,
114 m_storage
->constantInt(2),
116 Value
*xy
= m_builder
.CreateAdd(x
, y
,name("xy"));
117 Value
*dot3
= m_builder
.CreateAdd(xy
, z
, name("dot3"));
118 return vectorFromVals(dot3
, dot3
, dot3
, dot3
);
121 llvm::Value
*Instructions::callFSqrt(llvm::Value
*val
)
124 // predeclare the intrinsic
125 std::vector
<const Type
*> fsqrtArgs
;
126 fsqrtArgs
.push_back(Type::FloatTy
);
127 ParamAttrsList
*fsqrtPal
= 0;
128 FunctionType
* fsqrtType
= FunctionType::get(
129 /*Result=*/Type::FloatTy
,
130 /*Params=*/fsqrtArgs
,
132 m_llvmFSqrt
= new Function(
134 /*Linkage=*/GlobalValue::ExternalLinkage
,
135 /*Name=*/"llvm.sqrt.f32", m_mod
);
136 m_llvmFSqrt
->setCallingConv(CallingConv::C
);
137 m_llvmFSqrt
->setParamAttrs(fsqrtPal
);
139 CallInst
*call
= m_builder
.CreateCall(m_llvmFSqrt
, val
,
141 call
->setCallingConv(CallingConv::C
);
142 call
->setTailCall(false);
146 llvm::Value
* Instructions::rsq(llvm::Value
*in1
)
148 Value
*x
= m_builder
.CreateExtractElement(in1
,
149 m_storage
->constantInt(0),
151 Value
*abs
= callFAbs(x
);
152 Value
*sqrt
= callFSqrt(abs
);
154 Value
*rsqrt
= m_builder
.CreateFDiv(ConstantFP::get(Type::FloatTy
,
158 return vectorFromVals(rsqrt
, rsqrt
, rsqrt
, rsqrt
);
161 llvm::Value
* Instructions::vectorFromVals(llvm::Value
*x
, llvm::Value
*y
,
162 llvm::Value
*z
, llvm::Value
*w
)
164 Constant
*const_vec
= Constant::getNullValue(m_floatVecType
);
165 Value
*res
= m_builder
.CreateInsertElement(const_vec
, x
,
166 m_storage
->constantInt(0),
168 res
= m_builder
.CreateInsertElement(res
, y
, m_storage
->constantInt(1),
170 res
= m_builder
.CreateInsertElement(res
, z
, m_storage
->constantInt(2),
173 res
= m_builder
.CreateInsertElement(res
, w
, m_storage
->constantInt(3),
178 llvm::Value
*Instructions::callFAbs(llvm::Value
*val
)
181 // predeclare the intrinsic
182 std::vector
<const Type
*> fabsArgs
;
183 fabsArgs
.push_back(Type::FloatTy
);
184 ParamAttrsList
*fabsPal
= 0;
185 FunctionType
* fabsType
= FunctionType::get(
186 /*Result=*/Type::FloatTy
,
189 m_llvmFAbs
= new Function(
191 /*Linkage=*/GlobalValue::ExternalLinkage
,
192 /*Name=*/"fabs", m_mod
);
193 m_llvmFAbs
->setCallingConv(CallingConv::C
);
194 m_llvmFAbs
->setParamAttrs(fabsPal
);
196 CallInst
*call
= m_builder
.CreateCall(m_llvmFAbs
, val
,
198 call
->setCallingConv(CallingConv::C
);
199 call
->setTailCall(false);
203 llvm::Value
* Instructions::lit(llvm::Value
*in
)
206 m_llvmLit
= m_mod
->getFunction("lit");
208 CallInst
*call
= m_builder
.CreateCall(m_llvmLit
, in
, name("litres"));
209 call
->setCallingConv(CallingConv::C
);
210 call
->setTailCall(false);
214 llvm::Value
* Instructions::sub(llvm::Value
*in1
, llvm::Value
*in2
)
216 Value
*res
= m_builder
.CreateSub(in1
, in2
, name("sub"));
220 llvm::Value
* Instructions::callPow(llvm::Value
*val1
, llvm::Value
*val2
)
223 // predeclare the intrinsic
224 std::vector
<const Type
*> powArgs
;
225 powArgs
.push_back(Type::FloatTy
);
226 powArgs
.push_back(Type::FloatTy
);
227 ParamAttrsList
*powPal
= 0;
228 FunctionType
* powType
= FunctionType::get(
229 /*Result=*/Type::FloatTy
,
232 m_llvmPow
= new Function(
234 /*Linkage=*/GlobalValue::ExternalLinkage
,
235 /*Name=*/"llvm.pow.f32", m_mod
);
236 m_llvmPow
->setCallingConv(CallingConv::C
);
237 m_llvmPow
->setParamAttrs(powPal
);
239 std::vector
<Value
*> params
;
240 params
.push_back(val1
);
241 params
.push_back(val2
);
242 CallInst
*call
= m_builder
.CreateCall(m_llvmPow
, params
.begin(), params
.end(),
244 call
->setCallingConv(CallingConv::C
);
245 call
->setTailCall(false);
249 llvm::Value
* Instructions::pow(llvm::Value
*in1
, llvm::Value
*in2
)
251 Value
*x1
= m_builder
.CreateExtractElement(in1
,
252 m_storage
->constantInt(0),
254 Value
*x2
= m_builder
.CreateExtractElement(in2
,
255 m_storage
->constantInt(0),
257 llvm::Value
*val
= callPow(x1
, x2
);
258 return vectorFromVals(val
, val
, val
, val
);
261 llvm::Value
* Instructions::rcp(llvm::Value
*in1
)
263 Value
*x1
= m_builder
.CreateExtractElement(in1
,
264 m_storage
->constantInt(0),
266 Value
*res
= m_builder
.CreateFDiv(ConstantFP::get(Type::FloatTy
,
269 return vectorFromVals(res
, res
, res
, res
);
272 llvm::Value
* Instructions::dp4(llvm::Value
*in1
, llvm::Value
*in2
)
274 Value
*mulRes
= mul(in1
, in2
);
275 std::vector
<llvm::Value
*> vec
= extractVector(mulRes
);
276 Value
*xy
= m_builder
.CreateAdd(vec
[0], vec
[1], name("xy"));
277 Value
*xyz
= m_builder
.CreateAdd(xy
, vec
[2], name("xyz"));
278 Value
*dot4
= m_builder
.CreateAdd(xyz
, vec
[3], name("dot4"));
279 return vectorFromVals(dot4
, dot4
, dot4
, dot4
);
282 llvm::Value
* Instructions::dph(llvm::Value
*in1
, llvm::Value
*in2
)
284 Value
*mulRes
= mul(in1
, in2
);
285 std::vector
<llvm::Value
*> vec1
= extractVector(mulRes
);
286 Value
*xy
= m_builder
.CreateAdd(vec1
[0], vec1
[1], name("xy"));
287 Value
*xyz
= m_builder
.CreateAdd(xy
, vec1
[2], name("xyz"));
288 Value
*dph
= m_builder
.CreateAdd(xyz
, vec1
[3], name("dph"));
289 return vectorFromVals(dph
, dph
, dph
, dph
);
292 llvm::Value
* Instructions::dst(llvm::Value
*in1
, llvm::Value
*in2
)
294 Value
*y1
= m_builder
.CreateExtractElement(in1
,
295 m_storage
->constantInt(1),
297 Value
*z
= m_builder
.CreateExtractElement(in1
,
298 m_storage
->constantInt(2),
300 Value
*y2
= m_builder
.CreateExtractElement(in2
,
301 m_storage
->constantInt(1),
303 Value
*w
= m_builder
.CreateExtractElement(in2
,
304 m_storage
->constantInt(3),
306 Value
*ry
= m_builder
.CreateMul(y1
, y2
, name("tyuy"));
307 return vectorFromVals(ConstantFP::get(Type::FloatTy
, APFloat(1.f
)),
311 llvm::Value
* Instructions::ex2(llvm::Value
*in
)
313 llvm::Value
*val
= callPow(ConstantFP::get(Type::FloatTy
, APFloat(2.f
)),
314 m_builder
.CreateExtractElement(
315 in
, m_storage
->constantInt(0),
317 return vectorFromVals(val
, val
, val
, val
);
320 llvm::Value
* Instructions::callFloor(llvm::Value
*val
)
323 // predeclare the intrinsic
324 std::vector
<const Type
*> floorArgs
;
325 floorArgs
.push_back(Type::FloatTy
);
326 ParamAttrsList
*floorPal
= 0;
327 FunctionType
* floorType
= FunctionType::get(
328 /*Result=*/Type::FloatTy
,
329 /*Params=*/floorArgs
,
331 m_llvmFloor
= new Function(
333 /*Linkage=*/GlobalValue::ExternalLinkage
,
334 /*Name=*/"floorf", m_mod
);
335 m_llvmFloor
->setCallingConv(CallingConv::C
);
336 m_llvmFloor
->setParamAttrs(floorPal
);
338 CallInst
*call
= m_builder
.CreateCall(m_llvmFloor
, val
,
340 call
->setCallingConv(CallingConv::C
);
341 call
->setTailCall(false);
345 llvm::Value
* Instructions::floor(llvm::Value
*in
)
347 std::vector
<llvm::Value
*> vec
= extractVector(in
);
348 return vectorFromVals(callFloor(vec
[0]), callFloor(vec
[1]),
349 callFloor(vec
[2]), callFloor(vec
[3]));
352 llvm::Value
* Instructions::arl(llvm::Value
*in
)
357 llvm::Value
* Instructions::frc(llvm::Value
*in
)
359 llvm::Value
*flr
= floor(in
);
363 llvm::Value
* Instructions::callFLog(llvm::Value
*val
)
366 // predeclare the intrinsic
367 std::vector
<const Type
*> flogArgs
;
368 flogArgs
.push_back(Type::FloatTy
);
369 ParamAttrsList
*flogPal
= 0;
370 FunctionType
* flogType
= FunctionType::get(
371 /*Result=*/Type::FloatTy
,
374 m_llvmFlog
= new Function(
376 /*Linkage=*/GlobalValue::ExternalLinkage
,
377 /*Name=*/"logf", m_mod
);
378 m_llvmFlog
->setCallingConv(CallingConv::C
);
379 m_llvmFlog
->setParamAttrs(flogPal
);
381 CallInst
*call
= m_builder
.CreateCall(m_llvmFlog
, val
,
383 call
->setCallingConv(CallingConv::C
);
384 call
->setTailCall(false);
388 llvm::Value
* Instructions::lg2(llvm::Value
*in
)
390 std::vector
<llvm::Value
*> vec
= extractVector(in
);
391 llvm::Value
*const_vec
= constVector(1.442695f
, 1.442695f
,
392 1.442695f
, 1.442695f
);
393 return mul(vectorFromVals(callFLog(vec
[0]), callFLog(vec
[1]),
394 callFLog(vec
[2]), callFLog(vec
[3])), const_vec
);
397 llvm::Value
* Instructions::min(llvm::Value
*in1
, llvm::Value
*in2
)
399 std::vector
<llvm::Value
*> vec1
= extractVector(in1
);
400 std::vector
<llvm::Value
*> vec2
= extractVector(in2
);
402 Value
*xcmp
= m_builder
.CreateFCmpOLT(vec1
[0], vec2
[0], name("xcmp"));
403 Value
*selx
= m_builder
.CreateSelect(xcmp
, vec1
[0], vec2
[0],
406 Value
*ycmp
= m_builder
.CreateFCmpOLT(vec1
[1], vec2
[1], name("ycmp"));
407 Value
*sely
= m_builder
.CreateSelect(ycmp
, vec1
[1], vec2
[1],
410 Value
*zcmp
= m_builder
.CreateFCmpOLT(vec1
[2], vec2
[2], name("zcmp"));
411 Value
*selz
= m_builder
.CreateSelect(zcmp
, vec1
[2], vec2
[2],
414 Value
*wcmp
= m_builder
.CreateFCmpOLT(vec1
[3], vec2
[3], name("wcmp"));
415 Value
*selw
= m_builder
.CreateSelect(wcmp
, vec1
[3], vec2
[3],
418 return vectorFromVals(selx
, sely
, selz
, selw
);
421 llvm::Value
* Instructions::max(llvm::Value
*in1
, llvm::Value
*in2
)
423 std::vector
<llvm::Value
*> vec1
= extractVector(in1
);
424 std::vector
<llvm::Value
*> vec2
= extractVector(in2
);
426 Value
*xcmp
= m_builder
.CreateFCmpOGT(vec1
[0], vec2
[0],
428 Value
*selx
= m_builder
.CreateSelect(xcmp
, vec1
[0], vec2
[0],
431 Value
*ycmp
= m_builder
.CreateFCmpOGT(vec1
[1], vec2
[1],
433 Value
*sely
= m_builder
.CreateSelect(ycmp
, vec1
[1], vec2
[1],
436 Value
*zcmp
= m_builder
.CreateFCmpOGT(vec1
[2], vec2
[2],
438 Value
*selz
= m_builder
.CreateSelect(zcmp
, vec1
[2], vec2
[2],
441 Value
*wcmp
= m_builder
.CreateFCmpOGT(vec1
[3], vec2
[3],
443 Value
*selw
= m_builder
.CreateSelect(wcmp
, vec1
[3], vec2
[3],
446 return vectorFromVals(selx
, sely
, selz
, selw
);
449 void Instructions::printVector(llvm::Value
*val
)
451 static const char *frmt
= "Vector is [%f, %f, %f, %f]\x0A";
454 Constant
*format
= ConstantArray::get(frmt
, true);
455 ArrayType
*arrayTy
= ArrayType::get(IntegerType::get(8), strlen(frmt
) + 1);
456 GlobalVariable
* globalFormat
= new GlobalVariable(
459 /*Linkage=*/GlobalValue::InternalLinkage
,
460 /*Initializer=*/0, // has initializer, specified below
461 /*Name=*/name(".str"),
463 globalFormat
->setInitializer(format
);
465 Constant
* const_int0
= Constant::getNullValue(IntegerType::get(32));
466 std::vector
<Constant
*> const_ptr_21_indices
;
467 const_ptr_21_indices
.push_back(const_int0
);
468 const_ptr_21_indices
.push_back(const_int0
);
469 m_fmtPtr
= ConstantExpr::getGetElementPtr(globalFormat
,
470 &const_ptr_21_indices
[0], const_ptr_21_indices
.size());
473 Function
*func_printf
= m_mod
->getFunction("printf");
475 func_printf
= declarePrintf();
477 std::vector
<llvm::Value
*> vec
= extractVector(val
);
478 Value
*dx
= m_builder
.CreateFPExt(vec
[0], Type::DoubleTy
, name("dx"));
479 Value
*dy
= m_builder
.CreateFPExt(vec
[1], Type::DoubleTy
, name("dy"));
480 Value
*dz
= m_builder
.CreateFPExt(vec
[2], Type::DoubleTy
, name("dz"));
481 Value
*dw
= m_builder
.CreateFPExt(vec
[3], Type::DoubleTy
, name("dw"));
482 std::vector
<Value
*> params
;
483 params
.push_back(m_fmtPtr
);
484 params
.push_back(dx
);
485 params
.push_back(dy
);
486 params
.push_back(dz
);
487 params
.push_back(dw
);
488 CallInst
*call
= m_builder
.CreateCall(func_printf
, params
.begin(), params
.end(),
490 call
->setCallingConv(CallingConv::C
);
491 call
->setTailCall(true);
494 llvm::Function
* Instructions::declarePrintf()
496 std::vector
<const Type
*> args
;
497 ParamAttrsList
*params
= 0;
498 FunctionType
* funcTy
= FunctionType::get(
499 /*Result=*/IntegerType::get(32),
502 Function
* func_printf
= new Function(
504 /*Linkage=*/GlobalValue::ExternalLinkage
,
505 /*Name=*/"printf", m_mod
);
506 func_printf
->setCallingConv(CallingConv::C
);
507 func_printf
->setParamAttrs(params
);
512 llvm::Value
* Instructions::sgt(llvm::Value
*in1
, llvm::Value
*in2
)
514 Constant
*const1f
= ConstantFP::get(Type::FloatTy
, APFloat(1.000000e+00f
));
515 Constant
*const0f
= Constant::getNullValue(Type::FloatTy
);
517 std::vector
<llvm::Value
*> vec1
= extractVector(in1
);
518 std::vector
<llvm::Value
*> vec2
= extractVector(in2
);
519 Value
*xcmp
= m_builder
.CreateFCmpOGT(vec1
[0], vec2
[0], name("xcmp"));
520 Value
*x
= m_builder
.CreateSelect(xcmp
, const1f
, const0f
, name("xsel"));
522 Value
*ycmp
= m_builder
.CreateFCmpOGT(vec1
[1], vec2
[1], name("ycmp"));
523 Value
*y
= m_builder
.CreateSelect(ycmp
, const1f
, const0f
, name("ysel"));
525 Value
*zcmp
= m_builder
.CreateFCmpOGT(vec1
[2], vec2
[2], name("zcmp"));
526 Value
*z
= m_builder
.CreateSelect(zcmp
, const1f
, const0f
, name("zsel"));
528 Value
*wcmp
= m_builder
.CreateFCmpOGT(vec1
[3], vec2
[3], name("wcmp"));
529 Value
*w
= m_builder
.CreateSelect(wcmp
, const1f
, const0f
, name("wsel"));
531 return vectorFromVals(x
, y
, z
, w
);
533 llvm::Value
* Instructions::sge(llvm::Value
*in1
, llvm::Value
*in2
)
535 Constant
*const1f
= ConstantFP::get(Type::FloatTy
, APFloat(1.000000e+00f
));
536 Constant
*const0f
= Constant::getNullValue(Type::FloatTy
);
538 std::vector
<llvm::Value
*> vec1
= extractVector(in1
);
539 std::vector
<llvm::Value
*> vec2
= extractVector(in2
);
541 Value
*xcmp
= m_builder
.CreateFCmpOGE(vec1
[0], vec2
[0], name("xcmp"));
542 Value
*x
= m_builder
.CreateSelect(xcmp
, const1f
, const0f
, name("xsel"));
544 Value
*ycmp
= m_builder
.CreateFCmpOGE(vec1
[1], vec2
[1], name("ycmp"));
545 Value
*y
= m_builder
.CreateSelect(ycmp
, const1f
, const0f
, name("ysel"));
547 Value
*zcmp
= m_builder
.CreateFCmpOGE(vec1
[2], vec2
[2], name("zcmp"));
548 Value
*z
= m_builder
.CreateSelect(zcmp
, const1f
, const0f
, name("zsel"));
550 Value
*wcmp
= m_builder
.CreateFCmpOGE(vec1
[3], vec2
[3], name("wcmp"));
551 Value
*w
= m_builder
.CreateSelect(wcmp
, const1f
, const0f
, name("wsel"));
553 return vectorFromVals(x
, y
, z
, w
);
557 llvm::Value
* Instructions::slt(llvm::Value
*in1
, llvm::Value
*in2
)
559 Constant
*const1f
= ConstantFP::get(Type::FloatTy
, APFloat(1.000000e+00f
));
560 Constant
*const0f
= Constant::getNullValue(Type::FloatTy
);
562 std::vector
<llvm::Value
*> vec1
= extractVector(in1
);
563 std::vector
<llvm::Value
*> vec2
= extractVector(in2
);
565 Value
*xcmp
= m_builder
.CreateFCmpOLT(vec1
[0], vec2
[0], name("xcmp"));
566 Value
*x
= m_builder
.CreateSelect(xcmp
, const1f
, const0f
, name("xsel"));
568 Value
*ycmp
= m_builder
.CreateFCmpOLT(vec1
[1], vec2
[1], name("ycmp"));
569 Value
*y
= m_builder
.CreateSelect(ycmp
, const1f
, const0f
, name("ysel"));
571 Value
*zcmp
= m_builder
.CreateFCmpOLT(vec1
[2], vec2
[2], name("zcmp"));
572 Value
*z
= m_builder
.CreateSelect(zcmp
, const1f
, const0f
, name("zsel"));
574 Value
*wcmp
= m_builder
.CreateFCmpOLT(vec1
[3], vec2
[3], name("wcmp"));
575 Value
*w
= m_builder
.CreateSelect(wcmp
, const1f
, const0f
, name("wsel"));
577 return vectorFromVals(x
, y
, z
, w
);
580 llvm::Value
* Instructions::cross(llvm::Value
*in1
, llvm::Value
*in2
)
582 Value
*x1
= m_builder
.CreateExtractElement(in1
,
583 m_storage
->constantInt(0),
585 Value
*y1
= m_builder
.CreateExtractElement(in1
,
586 m_storage
->constantInt(1),
588 Value
*z1
= m_builder
.CreateExtractElement(in1
,
589 m_storage
->constantInt(2),
592 Value
*x2
= m_builder
.CreateExtractElement(in2
,
593 m_storage
->constantInt(0),
595 Value
*y2
= m_builder
.CreateExtractElement(in2
,
596 m_storage
->constantInt(1),
598 Value
*z2
= m_builder
.CreateExtractElement(in2
,
599 m_storage
->constantInt(2),
601 Value
*y1z2
= mul(y1
, z2
);
602 Value
*z1y2
= mul(z1
, y2
);
604 Value
*z1x2
= mul(z1
, x2
);
605 Value
*x1z2
= mul(x1
, z2
);
607 Value
*x1y2
= mul(x1
, y2
);
608 Value
*y1x2
= mul(y1
, x2
);
610 return vectorFromVals(sub(y1z2
, z1y2
), sub(z1x2
, x1z2
), sub(x1y2
, y1x2
));
614 llvm::Value
* Instructions::abs(llvm::Value
*in
)
616 std::vector
<llvm::Value
*> vec
= extractVector(in
);
617 Value
*xabs
= callFAbs(vec
[0]);
618 Value
*yabs
= callFAbs(vec
[1]);
619 Value
*zabs
= callFAbs(vec
[2]);
620 Value
*wabs
= callFAbs(vec
[3]);
621 return vectorFromVals(xabs
, yabs
, zabs
, wabs
);
624 void Instructions::ifop(llvm::Value
*in
)
626 BasicBlock
*ifthen
= new BasicBlock(name("ifthen"), m_func
,0);
627 BasicBlock
*ifend
= new BasicBlock(name("ifthenend"), m_func
,0);
629 //BasicBlock *yblock = new BasicBlock(name("yblock"), m_func,0);
630 //BasicBlock *zblock = new BasicBlock(name("zblock"), m_func,0);
631 //BasicBlock *wblock = new BasicBlock(name("wblock"), m_func,0);
633 Constant
*float0
= Constant::getNullValue(Type::FloatTy
);
635 Value
*x
= m_builder
.CreateExtractElement(in
, m_storage
->constantInt(0),
637 Value
*xcmp
= m_builder
.CreateFCmpUNE(x
, float0
, name("xcmp"));
638 m_builder
.CreateCondBr(xcmp
, ifthen
, ifend
);
639 //m_builder.SetInsertPoint(yblock);
641 m_builder
.SetInsertPoint(ifthen
);
642 m_ifStack
.push(ifend
);
645 llvm::BasicBlock
* Instructions::currentBlock() const
647 return m_builder
.GetInsertBlock();
650 void Instructions::elseop()
652 assert(!m_ifStack
.empty());
653 BasicBlock
*ifend
= new BasicBlock(name("ifend"), m_func
,0);
654 m_builder
.CreateBr(ifend
);
655 m_builder
.SetInsertPoint(m_ifStack
.top());
656 currentBlock()->setName(name("ifelse"));
658 m_ifStack
.push(ifend
);
661 void Instructions::endif()
663 assert(!m_ifStack
.empty());
664 m_builder
.CreateBr(m_ifStack
.top());
665 m_builder
.SetInsertPoint(m_ifStack
.top());
669 llvm::Value
* Instructions::lerp(llvm::Value
*in1
, llvm::Value
*in2
,
672 llvm::Value
*m
= mul(in1
, in2
);
673 llvm::Value
*vec1
= constVector(1.f
, 1.f
, 1.f
, 1.f
);
674 llvm::Value
*s
= sub(vec1
, in1
);
675 return add(m
, mul(s
, in3
));
678 void Instructions::beginLoop()
680 BasicBlock
*begin
= new BasicBlock(name("loop"), m_func
,0);
681 BasicBlock
*end
= new BasicBlock(name("endloop"), m_func
,0);
683 m_builder
.CreateBr(begin
);
687 m_builder
.SetInsertPoint(begin
);
688 m_loopStack
.push(loop
);
691 void Instructions::endLoop()
693 assert(!m_loopStack
.empty());
694 Loop loop
= m_loopStack
.top();
695 m_builder
.CreateBr(loop
.begin
);
696 loop
.end
->moveAfter(currentBlock());
697 m_builder
.SetInsertPoint(loop
.end
);
701 void Instructions::brk()
703 assert(!m_loopStack
.empty());
704 BasicBlock
*unr
= new BasicBlock(name("unreachable"), m_func
,0);
705 m_builder
.CreateBr(m_loopStack
.top().end
);
706 m_builder
.SetInsertPoint(unr
);
709 llvm::Value
* Instructions::trunc(llvm::Value
*in
)
711 std::vector
<llvm::Value
*> vec
= extractVector(in
);
712 Value
*icastx
= m_builder
.CreateFPToSI(vec
[0], IntegerType::get(32),
714 Value
*icasty
= m_builder
.CreateFPToSI(vec
[1], IntegerType::get(32),
716 Value
*icastz
= m_builder
.CreateFPToSI(vec
[2], IntegerType::get(32),
718 Value
*icastw
= m_builder
.CreateFPToSI(vec
[3], IntegerType::get(32),
720 Value
*fx
= m_builder
.CreateSIToFP(icastx
, Type::FloatTy
,
722 Value
*fy
= m_builder
.CreateSIToFP(icasty
, Type::FloatTy
,
724 Value
*fz
= m_builder
.CreateSIToFP(icastz
, Type::FloatTy
,
726 Value
*fw
= m_builder
.CreateSIToFP(icastw
, Type::FloatTy
,
728 return vectorFromVals(fx
, fy
, fz
, fw
);
731 void Instructions::end()
733 m_builder
.CreateRetVoid();
736 void Instructions::cal(int label
, llvm::Value
*input
)
738 std::vector
<Value
*> params
;
739 params
.push_back(input
);
740 llvm::Function
*func
= findFunction(label
);
742 m_builder
.CreateCall(func
, params
.begin(), params
.end());
745 llvm::Function
* Instructions::declareFunc(int label
)
747 PointerType
*vecPtr
= PointerType::getUnqual(m_floatVecType
);
748 std::vector
<const Type
*> args
;
749 args
.push_back(vecPtr
);
750 args
.push_back(vecPtr
);
751 args
.push_back(vecPtr
);
752 args
.push_back(vecPtr
);
753 ParamAttrsList
*params
= 0;
754 FunctionType
*funcType
= FunctionType::get(
755 /*Result=*/Type::VoidTy
,
758 std::string name
= createFuncName(label
);
759 Function
*func
= new Function(
761 /*Linkage=*/GlobalValue::ExternalLinkage
,
762 /*Name=*/name
.c_str(), m_mod
);
763 func
->setCallingConv(CallingConv::C
);
764 func
->setParamAttrs(params
);
768 void Instructions::bgnSub(unsigned label
)
770 llvm::Function
*func
= findFunction(label
);
772 Function::arg_iterator args
= func
->arg_begin();
773 Value
*ptr_INPUT
= args
++;
774 ptr_INPUT
->setName("INPUT");
775 m_storage
->pushArguments(ptr_INPUT
);
777 llvm::BasicBlock
*entry
= new BasicBlock("entry", func
, 0);
780 m_builder
.SetInsertPoint(entry
);
783 void Instructions::endSub()
786 m_builder
.SetInsertPoint(0);
789 llvm::Function
* Instructions::findFunction(int label
)
791 llvm::Function
*func
= m_functions
[label
];
793 func
= declareFunc(label
);
794 m_functions
[label
] = func
;
799 llvm::Value
* Instructions::constVector(float x
, float y
, float z
, float w
)
801 std::vector
<Constant
*> vec(4);
802 vec
[0] = ConstantFP::get(Type::FloatTy
, APFloat(x
));
803 vec
[1] = ConstantFP::get(Type::FloatTy
, APFloat(y
));
804 vec
[2] = ConstantFP::get(Type::FloatTy
, APFloat(z
));
805 vec
[3] = ConstantFP::get(Type::FloatTy
, APFloat(w
));
806 return ConstantVector::get(m_floatVecType
, vec
);
810 std::vector
<llvm::Value
*> Instructions::extractVector(llvm::Value
*vec
)
812 std::vector
<llvm::Value
*> elems(4);
813 elems
[0] = m_builder
.CreateExtractElement(vec
, m_storage
->constantInt(0),
815 elems
[1] = m_builder
.CreateExtractElement(vec
, m_storage
->constantInt(1),
817 elems
[2] = m_builder
.CreateExtractElement(vec
, m_storage
->constantInt(2),
819 elems
[3] = m_builder
.CreateExtractElement(vec
, m_storage
->constantInt(3),
824 llvm::Value
* Instructions::cmp(llvm::Value
*in1
, llvm::Value
*in2
, llvm::Value
*in3
)
826 llvm::Function
*func
= m_mod
->getFunction("cmp");
829 std::vector
<Value
*> params
;
830 params
.push_back(in1
);
831 params
.push_back(in2
);
832 params
.push_back(in3
);
833 CallInst
*call
= m_builder
.CreateCall(func
, params
.begin(), params
.end(), name("cmpres"));
834 call
->setTailCall(false);
838 llvm::Value
* Instructions::cos(llvm::Value
*in
)
841 llvm::Function
*func
= m_mod
->getFunction("vcos");
844 CallInst
*call
= m_builder
.CreateCall(func
, in
, name("cosres"));
845 call
->setTailCall(false);
848 std::vector
<llvm::Value
*> elems
= extractVector(in
);
849 Function
*func
= m_mod
->getFunction("cosf");
851 CallInst
*cos
= m_builder
.CreateCall(func
, elems
[0], name("cosres"));
852 cos
->setCallingConv(CallingConv::C
);
853 cos
->setTailCall(true);
854 return vectorFromVals(cos
, cos
, cos
, cos
);
858 llvm::Value
* Instructions::scs(llvm::Value
*in
)
860 llvm::Function
*func
= m_mod
->getFunction("scs");
863 CallInst
*call
= m_builder
.CreateCall(func
, in
, name("scsres"));
864 call
->setTailCall(false);
868 llvm::Value
* Instructions::kilp(llvm::Value
*in
)
870 llvm::Function
*func
= m_mod
->getFunction("kilp");
873 CallInst
*call
= m_builder
.CreateCall(func
, in
, name("kilpres"));
874 call
->setTailCall(false);
878 llvm::Value
* Instructions::sin(llvm::Value
*in
)
880 llvm::Function
*func
= m_mod
->getFunction("vsin");
883 CallInst
*call
= m_builder
.CreateCall(func
, in
, name("sinres"));
884 call
->setTailCall(false);