Files
mesa/src/gallium/auxiliary/gallivm/instructions.cpp
T
2008-05-12 17:17:18 -04:00

903 lines
31 KiB
C++

/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/*
* Authors:
* Zack Rusin zack@tungstengraphics.com
*/
#ifdef MESA_LLVM
#include "instructions.h"
#include "storage.h"
#include "pipe/p_util.h"
#include <llvm/CallingConv.h>
#include <llvm/Constants.h>
#include <llvm/DerivedTypes.h>
#include <llvm/Function.h>
#include <llvm/InstrTypes.h>
#include <llvm/Instructions.h>
#include <llvm/ParameterAttributes.h>
#include <llvm/Support/MemoryBuffer.h>
#include <llvm/Bitcode/ReaderWriter.h>
#include <sstream>
#include <fstream>
#include <iostream>
using namespace llvm;
#include "gallivm_builtins.cpp"
#if 0
llvm::Value *arrayFromChannels(std::vector<llvm::Value*> &vals)
{
VectorType *vectorType = VectorType::get(Type::FloatTy, 4);
ArrayType *vectorArray = ArrayType::get(vectorType, 4);
}
#endif
static inline std::string createFuncName(int label)
{
std::ostringstream stream;
stream << "function";
stream << label;
return stream.str();
}
Instructions::Instructions(llvm::Module *mod, llvm::Function *func, llvm::BasicBlock *block,
Storage *storage)
: m_mod(mod), m_func(func), m_builder(block), m_idx(0),
m_storage(storage)
{
m_floatVecType = VectorType::get(Type::FloatTy, 4);
m_llvmFSqrt = 0;
m_llvmFAbs = 0;
m_llvmPow = 0;
m_llvmFloor = 0;
m_llvmFlog = 0;
m_llvmLit = 0;
m_fmtPtr = 0;
MemoryBuffer *buffer = MemoryBuffer::getMemBuffer(
(const char*)&llvm_builtins_data[0],
(const char*)&llvm_builtins_data[Elements(llvm_builtins_data)-1]);
m_mod = ParseBitcodeFile(buffer);
}
llvm::Value * Instructions::add(llvm::Value *in1, llvm::Value *in2)
{
return m_builder.CreateAdd(in1, in2, name("add"));
}
llvm::Value * Instructions::madd(llvm::Value *in1, llvm::Value *in2,
llvm::Value *in3)
{
Value *mulRes = mul(in1, in2);
return add(mulRes, in3);
}
llvm::Value * Instructions::mul(llvm::Value *in1, llvm::Value *in2)
{
return m_builder.CreateMul(in1, in2, name("mul"));
}
const char * Instructions::name(const char *prefix)
{
++m_idx;
snprintf(m_name, 32, "%s%d", prefix, m_idx);
return m_name;
}
llvm::Value * Instructions::dp3(llvm::Value *in1, llvm::Value *in2)
{
Value *mulRes = mul(in1, in2);
Value *x = m_builder.CreateExtractElement(mulRes,
m_storage->constantInt(0),
name("extractx"));
Value *y = m_builder.CreateExtractElement(mulRes,
m_storage->constantInt(1),
name("extracty"));
Value *z = m_builder.CreateExtractElement(mulRes,
m_storage->constantInt(2),
name("extractz"));
Value *xy = m_builder.CreateAdd(x, y,name("xy"));
Value *dot3 = m_builder.CreateAdd(xy, z, name("dot3"));
return vectorFromVals(dot3, dot3, dot3, dot3);
}
llvm::Value *Instructions::callFSqrt(llvm::Value *val)
{
if (!m_llvmFSqrt) {
// predeclare the intrinsic
std::vector<const Type*> fsqrtArgs;
fsqrtArgs.push_back(Type::FloatTy);
PAListPtr fsqrtPal;
FunctionType* fsqrtType = FunctionType::get(
/*Result=*/Type::FloatTy,
/*Params=*/fsqrtArgs,
/*isVarArg=*/false);
m_llvmFSqrt = Function::Create(
/*Type=*/fsqrtType,
/*Linkage=*/GlobalValue::ExternalLinkage,
/*Name=*/"llvm.sqrt.f32", m_mod);
m_llvmFSqrt->setCallingConv(CallingConv::C);
m_llvmFSqrt->setParamAttrs(fsqrtPal);
}
CallInst *call = m_builder.CreateCall(m_llvmFSqrt, val,
name("sqrt"));
call->setCallingConv(CallingConv::C);
call->setTailCall(false);
return call;
}
llvm::Value * Instructions::rsq(llvm::Value *in1)
{
Value *x = m_builder.CreateExtractElement(in1,
m_storage->constantInt(0),
name("extractx"));
Value *abs = callFAbs(x);
Value *sqrt = callFSqrt(abs);
Value *rsqrt = m_builder.CreateFDiv(ConstantFP::get(APFloat(1.f)),
sqrt,
name("rsqrt"));
return vectorFromVals(rsqrt, rsqrt, rsqrt, rsqrt);
}
llvm::Value * Instructions::vectorFromVals(llvm::Value *x, llvm::Value *y,
llvm::Value *z, llvm::Value *w)
{
Constant *const_vec = Constant::getNullValue(m_floatVecType);
Value *res = m_builder.CreateInsertElement(const_vec, x,
m_storage->constantInt(0),
name("vecx"));
res = m_builder.CreateInsertElement(res, y, m_storage->constantInt(1),
name("vecxy"));
res = m_builder.CreateInsertElement(res, z, m_storage->constantInt(2),
name("vecxyz"));
if (w)
res = m_builder.CreateInsertElement(res, w, m_storage->constantInt(3),
name("vecxyzw"));
return res;
}
llvm::Value *Instructions::callFAbs(llvm::Value *val)
{
if (!m_llvmFAbs) {
// predeclare the intrinsic
std::vector<const Type*> fabsArgs;
fabsArgs.push_back(Type::FloatTy);
PAListPtr fabsPal;
FunctionType* fabsType = FunctionType::get(
/*Result=*/Type::FloatTy,
/*Params=*/fabsArgs,
/*isVarArg=*/false);
m_llvmFAbs = Function::Create(
/*Type=*/fabsType,
/*Linkage=*/GlobalValue::ExternalLinkage,
/*Name=*/"fabs", m_mod);
m_llvmFAbs->setCallingConv(CallingConv::C);
m_llvmFAbs->setParamAttrs(fabsPal);
}
CallInst *call = m_builder.CreateCall(m_llvmFAbs, val,
name("fabs"));
call->setCallingConv(CallingConv::C);
call->setTailCall(false);
return call;
}
llvm::Value * Instructions::lit(llvm::Value *in)
{
if (!m_llvmLit) {
m_llvmLit = m_mod->getFunction("lit");
}
CallInst *call = m_builder.CreateCall(m_llvmLit, in, name("litres"));
call->setCallingConv(CallingConv::C);
call->setTailCall(false);
return call;
}
llvm::Value * Instructions::sub(llvm::Value *in1, llvm::Value *in2)
{
Value *res = m_builder.CreateSub(in1, in2, name("sub"));
return res;
}
llvm::Value * Instructions::callPow(llvm::Value *val1, llvm::Value *val2)
{
if (!m_llvmPow) {
// predeclare the intrinsic
std::vector<const Type*> powArgs;
powArgs.push_back(Type::FloatTy);
powArgs.push_back(Type::FloatTy);
PAListPtr powPal;
FunctionType* powType = FunctionType::get(
/*Result=*/Type::FloatTy,
/*Params=*/powArgs,
/*isVarArg=*/false);
m_llvmPow = Function::Create(
/*Type=*/powType,
/*Linkage=*/GlobalValue::ExternalLinkage,
/*Name=*/"llvm.pow.f32", m_mod);
m_llvmPow->setCallingConv(CallingConv::C);
m_llvmPow->setParamAttrs(powPal);
}
std::vector<Value*> params;
params.push_back(val1);
params.push_back(val2);
CallInst *call = m_builder.CreateCall(m_llvmPow, params.begin(), params.end(),
name("pow"));
call->setCallingConv(CallingConv::C);
call->setTailCall(false);
return call;
}
llvm::Value * Instructions::pow(llvm::Value *in1, llvm::Value *in2)
{
Value *x1 = m_builder.CreateExtractElement(in1,
m_storage->constantInt(0),
name("x1"));
Value *x2 = m_builder.CreateExtractElement(in2,
m_storage->constantInt(0),
name("x2"));
llvm::Value *val = callPow(x1, x2);
return vectorFromVals(val, val, val, val);
}
llvm::Value * Instructions::rcp(llvm::Value *in1)
{
Value *x1 = m_builder.CreateExtractElement(in1,
m_storage->constantInt(0),
name("x1"));
Value *res = m_builder.CreateFDiv(ConstantFP::get(APFloat(1.f)),
x1, name("rcp"));
return vectorFromVals(res, res, res, res);
}
llvm::Value * Instructions::dp4(llvm::Value *in1, llvm::Value *in2)
{
Value *mulRes = mul(in1, in2);
std::vector<llvm::Value*> vec = extractVector(mulRes);
Value *xy = m_builder.CreateAdd(vec[0], vec[1], name("xy"));
Value *xyz = m_builder.CreateAdd(xy, vec[2], name("xyz"));
Value *dot4 = m_builder.CreateAdd(xyz, vec[3], name("dot4"));
return vectorFromVals(dot4, dot4, dot4, dot4);
}
llvm::Value * Instructions::dph(llvm::Value *in1, llvm::Value *in2)
{
Value *mulRes = mul(in1, in2);
std::vector<llvm::Value*> vec1 = extractVector(mulRes);
Value *xy = m_builder.CreateAdd(vec1[0], vec1[1], name("xy"));
Value *xyz = m_builder.CreateAdd(xy, vec1[2], name("xyz"));
Value *dph = m_builder.CreateAdd(xyz, vec1[3], name("dph"));
return vectorFromVals(dph, dph, dph, dph);
}
llvm::Value * Instructions::dst(llvm::Value *in1, llvm::Value *in2)
{
Value *y1 = m_builder.CreateExtractElement(in1,
m_storage->constantInt(1),
name("y1"));
Value *z = m_builder.CreateExtractElement(in1,
m_storage->constantInt(2),
name("z"));
Value *y2 = m_builder.CreateExtractElement(in2,
m_storage->constantInt(1),
name("y2"));
Value *w = m_builder.CreateExtractElement(in2,
m_storage->constantInt(3),
name("w"));
Value *ry = m_builder.CreateMul(y1, y2, name("tyuy"));
return vectorFromVals(ConstantFP::get(APFloat(1.f)),
ry, z, w);
}
llvm::Value * Instructions::ex2(llvm::Value *in)
{
llvm::Value *val = callPow(ConstantFP::get(APFloat(2.f)),
m_builder.CreateExtractElement(
in, m_storage->constantInt(0),
name("x1")));
return vectorFromVals(val, val, val, val);
}
llvm::Value * Instructions::callFloor(llvm::Value *val)
{
if (!m_llvmFloor) {
// predeclare the intrinsic
std::vector<const Type*> floorArgs;
floorArgs.push_back(Type::FloatTy);
PAListPtr floorPal;
FunctionType* floorType = FunctionType::get(
/*Result=*/Type::FloatTy,
/*Params=*/floorArgs,
/*isVarArg=*/false);
m_llvmFloor = Function::Create(
/*Type=*/floorType,
/*Linkage=*/GlobalValue::ExternalLinkage,
/*Name=*/"floorf", m_mod);
m_llvmFloor->setCallingConv(CallingConv::C);
m_llvmFloor->setParamAttrs(floorPal);
}
CallInst *call = m_builder.CreateCall(m_llvmFloor, val,
name("floorf"));
call->setCallingConv(CallingConv::C);
call->setTailCall(false);
return call;
}
llvm::Value * Instructions::floor(llvm::Value *in)
{
std::vector<llvm::Value*> vec = extractVector(in);
return vectorFromVals(callFloor(vec[0]), callFloor(vec[1]),
callFloor(vec[2]), callFloor(vec[3]));
}
llvm::Value * Instructions::arl(llvm::Value *in)
{
return floor(in);
}
llvm::Value * Instructions::frc(llvm::Value *in)
{
llvm::Value *flr = floor(in);
return sub(in, flr);
}
llvm::Value * Instructions::callFLog(llvm::Value *val)
{
if (!m_llvmFlog) {
// predeclare the intrinsic
std::vector<const Type*> flogArgs;
flogArgs.push_back(Type::FloatTy);
PAListPtr flogPal;
FunctionType* flogType = FunctionType::get(
/*Result=*/Type::FloatTy,
/*Params=*/flogArgs,
/*isVarArg=*/false);
m_llvmFlog = Function::Create(
/*Type=*/flogType,
/*Linkage=*/GlobalValue::ExternalLinkage,
/*Name=*/"logf", m_mod);
m_llvmFlog->setCallingConv(CallingConv::C);
m_llvmFlog->setParamAttrs(flogPal);
}
CallInst *call = m_builder.CreateCall(m_llvmFlog, val,
name("logf"));
call->setCallingConv(CallingConv::C);
call->setTailCall(false);
return call;
}
llvm::Value * Instructions::lg2(llvm::Value *in)
{
std::vector<llvm::Value*> vec = extractVector(in);
llvm::Value *const_vec = constVector(1.442695f, 1.442695f,
1.442695f, 1.442695f);
return mul(vectorFromVals(callFLog(vec[0]), callFLog(vec[1]),
callFLog(vec[2]), callFLog(vec[3])), const_vec);
}
llvm::Value * Instructions::min(llvm::Value *in1, llvm::Value *in2)
{
std::vector<llvm::Value*> vec1 = extractVector(in1);
std::vector<llvm::Value*> vec2 = extractVector(in2);
Value *xcmp = m_builder.CreateFCmpOLT(vec1[0], vec2[0], name("xcmp"));
Value *selx = m_builder.CreateSelect(xcmp, vec1[0], vec2[0],
name("selx"));
Value *ycmp = m_builder.CreateFCmpOLT(vec1[1], vec2[1], name("ycmp"));
Value *sely = m_builder.CreateSelect(ycmp, vec1[1], vec2[1],
name("sely"));
Value *zcmp = m_builder.CreateFCmpOLT(vec1[2], vec2[2], name("zcmp"));
Value *selz = m_builder.CreateSelect(zcmp, vec1[2], vec2[2],
name("selz"));
Value *wcmp = m_builder.CreateFCmpOLT(vec1[3], vec2[3], name("wcmp"));
Value *selw = m_builder.CreateSelect(wcmp, vec1[3], vec2[3],
name("selw"));
return vectorFromVals(selx, sely, selz, selw);
}
llvm::Value * Instructions::max(llvm::Value *in1, llvm::Value *in2)
{
std::vector<llvm::Value*> vec1 = extractVector(in1);
std::vector<llvm::Value*> vec2 = extractVector(in2);
Value *xcmp = m_builder.CreateFCmpOGT(vec1[0], vec2[0],
name("xcmp"));
Value *selx = m_builder.CreateSelect(xcmp, vec1[0], vec2[0],
name("selx"));
Value *ycmp = m_builder.CreateFCmpOGT(vec1[1], vec2[1],
name("ycmp"));
Value *sely = m_builder.CreateSelect(ycmp, vec1[1], vec2[1],
name("sely"));
Value *zcmp = m_builder.CreateFCmpOGT(vec1[2], vec2[2],
name("zcmp"));
Value *selz = m_builder.CreateSelect(zcmp, vec1[2], vec2[2],
name("selz"));
Value *wcmp = m_builder.CreateFCmpOGT(vec1[3], vec2[3],
name("wcmp"));
Value *selw = m_builder.CreateSelect(wcmp, vec1[3], vec2[3],
name("selw"));
return vectorFromVals(selx, sely, selz, selw);
}
void Instructions::printVector(llvm::Value *val)
{
static const char *frmt = "Vector is [%f, %f, %f, %f]\x0A";
if (!m_fmtPtr) {
Constant *format = ConstantArray::get(frmt, true);
ArrayType *arrayTy = ArrayType::get(IntegerType::get(8), strlen(frmt) + 1);
GlobalVariable* globalFormat = new GlobalVariable(
/*Type=*/arrayTy,
/*isConstant=*/true,
/*Linkage=*/GlobalValue::InternalLinkage,
/*Initializer=*/0, // has initializer, specified below
/*Name=*/name(".str"),
m_mod);
globalFormat->setInitializer(format);
Constant* const_int0 = Constant::getNullValue(IntegerType::get(32));
std::vector<Constant*> const_ptr_21_indices;
const_ptr_21_indices.push_back(const_int0);
const_ptr_21_indices.push_back(const_int0);
m_fmtPtr = ConstantExpr::getGetElementPtr(globalFormat,
&const_ptr_21_indices[0], const_ptr_21_indices.size());
}
Function *func_printf = m_mod->getFunction("printf");
if (!func_printf)
func_printf = declarePrintf();
assert(func_printf);
std::vector<llvm::Value*> vec = extractVector(val);
Value *dx = m_builder.CreateFPExt(vec[0], Type::DoubleTy, name("dx"));
Value *dy = m_builder.CreateFPExt(vec[1], Type::DoubleTy, name("dy"));
Value *dz = m_builder.CreateFPExt(vec[2], Type::DoubleTy, name("dz"));
Value *dw = m_builder.CreateFPExt(vec[3], Type::DoubleTy, name("dw"));
std::vector<Value*> params;
params.push_back(m_fmtPtr);
params.push_back(dx);
params.push_back(dy);
params.push_back(dz);
params.push_back(dw);
CallInst *call = m_builder.CreateCall(func_printf, params.begin(), params.end(),
name("printf"));
call->setCallingConv(CallingConv::C);
call->setTailCall(true);
}
llvm::Function * Instructions::declarePrintf()
{
std::vector<const Type*> args;
PAListPtr params;
FunctionType* funcTy = FunctionType::get(
/*Result=*/IntegerType::get(32),
/*Params=*/args,
/*isVarArg=*/true);
Function* func_printf = Function::Create(
/*Type=*/funcTy,
/*Linkage=*/GlobalValue::ExternalLinkage,
/*Name=*/"printf", m_mod);
func_printf->setCallingConv(CallingConv::C);
func_printf->setParamAttrs(params);
return func_printf;
}
llvm::Value * Instructions::sgt(llvm::Value *in1, llvm::Value *in2)
{
Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f));
Constant *const0f = Constant::getNullValue(Type::FloatTy);
std::vector<llvm::Value*> vec1 = extractVector(in1);
std::vector<llvm::Value*> vec2 = extractVector(in2);
Value *xcmp = m_builder.CreateFCmpOGT(vec1[0], vec2[0], name("xcmp"));
Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
Value *ycmp = m_builder.CreateFCmpOGT(vec1[1], vec2[1], name("ycmp"));
Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
Value *zcmp = m_builder.CreateFCmpOGT(vec1[2], vec2[2], name("zcmp"));
Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
Value *wcmp = m_builder.CreateFCmpOGT(vec1[3], vec2[3], name("wcmp"));
Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel"));
return vectorFromVals(x, y, z, w);
}
llvm::Value * Instructions::sge(llvm::Value *in1, llvm::Value *in2)
{
Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f));
Constant *const0f = Constant::getNullValue(Type::FloatTy);
std::vector<llvm::Value*> vec1 = extractVector(in1);
std::vector<llvm::Value*> vec2 = extractVector(in2);
Value *xcmp = m_builder.CreateFCmpOGE(vec1[0], vec2[0], name("xcmp"));
Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
Value *ycmp = m_builder.CreateFCmpOGE(vec1[1], vec2[1], name("ycmp"));
Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
Value *zcmp = m_builder.CreateFCmpOGE(vec1[2], vec2[2], name("zcmp"));
Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
Value *wcmp = m_builder.CreateFCmpOGE(vec1[3], vec2[3], name("wcmp"));
Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel"));
return vectorFromVals(x, y, z, w);
}
llvm::Value * Instructions::slt(llvm::Value *in1, llvm::Value *in2)
{
Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f));
Constant *const0f = Constant::getNullValue(Type::FloatTy);
std::vector<llvm::Value*> vec1 = extractVector(in1);
std::vector<llvm::Value*> vec2 = extractVector(in2);
Value *xcmp = m_builder.CreateFCmpOLT(vec1[0], vec2[0], name("xcmp"));
Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
Value *ycmp = m_builder.CreateFCmpOLT(vec1[1], vec2[1], name("ycmp"));
Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
Value *zcmp = m_builder.CreateFCmpOLT(vec1[2], vec2[2], name("zcmp"));
Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
Value *wcmp = m_builder.CreateFCmpOLT(vec1[3], vec2[3], name("wcmp"));
Value *w = m_builder.CreateSelect(wcmp, const1f, const0f, name("wsel"));
return vectorFromVals(x, y, z, w);
}
llvm::Value * Instructions::cross(llvm::Value *in1, llvm::Value *in2)
{
Value *x1 = m_builder.CreateExtractElement(in1,
m_storage->constantInt(0),
name("x1"));
Value *y1 = m_builder.CreateExtractElement(in1,
m_storage->constantInt(1),
name("y1"));
Value *z1 = m_builder.CreateExtractElement(in1,
m_storage->constantInt(2),
name("z1"));
Value *x2 = m_builder.CreateExtractElement(in2,
m_storage->constantInt(0),
name("x2"));
Value *y2 = m_builder.CreateExtractElement(in2,
m_storage->constantInt(1),
name("y2"));
Value *z2 = m_builder.CreateExtractElement(in2,
m_storage->constantInt(2),
name("z2"));
Value *y1z2 = mul(y1, z2);
Value *z1y2 = mul(z1, y2);
Value *z1x2 = mul(z1, x2);
Value *x1z2 = mul(x1, z2);
Value *x1y2 = mul(x1, y2);
Value *y1x2 = mul(y1, x2);
return vectorFromVals(sub(y1z2, z1y2), sub(z1x2, x1z2), sub(x1y2, y1x2));
}
llvm::Value * Instructions::abs(llvm::Value *in)
{
std::vector<llvm::Value*> vec = extractVector(in);
Value *xabs = callFAbs(vec[0]);
Value *yabs = callFAbs(vec[1]);
Value *zabs = callFAbs(vec[2]);
Value *wabs = callFAbs(vec[3]);
return vectorFromVals(xabs, yabs, zabs, wabs);
}
void Instructions::ifop(llvm::Value *in)
{
BasicBlock *ifthen = BasicBlock::Create(name("ifthen"), m_func,0);
BasicBlock *ifend = BasicBlock::Create(name("ifthenend"), m_func,0);
//BasicBlock *yblock = new BasicBlock(name("yblock"), m_func,0);
//BasicBlock *zblock = new BasicBlock(name("zblock"), m_func,0);
//BasicBlock *wblock = new BasicBlock(name("wblock"), m_func,0);
Constant *float0 = Constant::getNullValue(Type::FloatTy);
Value *x = m_builder.CreateExtractElement(in, m_storage->constantInt(0),
name("extractx"));
Value *xcmp = m_builder.CreateFCmpUNE(x, float0, name("xcmp"));
m_builder.CreateCondBr(xcmp, ifthen, ifend);
//m_builder.SetInsertPoint(yblock);
m_builder.SetInsertPoint(ifthen);
m_ifStack.push(ifend);
}
llvm::BasicBlock * Instructions::currentBlock() const
{
return m_builder.GetInsertBlock();
}
void Instructions::elseop()
{
assert(!m_ifStack.empty());
BasicBlock *ifend = BasicBlock::Create(name("ifend"), m_func,0);
m_builder.CreateBr(ifend);
m_builder.SetInsertPoint(m_ifStack.top());
currentBlock()->setName(name("ifelse"));
m_ifStack.pop();
m_ifStack.push(ifend);
}
void Instructions::endif()
{
assert(!m_ifStack.empty());
m_builder.CreateBr(m_ifStack.top());
m_builder.SetInsertPoint(m_ifStack.top());
m_ifStack.pop();
}
llvm::Value * Instructions::lerp(llvm::Value *in1, llvm::Value *in2,
llvm::Value *in3)
{
llvm::Value *m = mul(in1, in2);
llvm::Value *vec1 = constVector(1.f, 1.f, 1.f, 1.f);
llvm::Value *s = sub(vec1, in1);
return add(m, mul(s, in3));
}
void Instructions::beginLoop()
{
BasicBlock *begin = BasicBlock::Create(name("loop"), m_func,0);
BasicBlock *end = BasicBlock::Create(name("endloop"), m_func,0);
m_builder.CreateBr(begin);
Loop loop;
loop.begin = begin;
loop.end = end;
m_builder.SetInsertPoint(begin);
m_loopStack.push(loop);
}
void Instructions::endLoop()
{
assert(!m_loopStack.empty());
Loop loop = m_loopStack.top();
m_builder.CreateBr(loop.begin);
loop.end->moveAfter(currentBlock());
m_builder.SetInsertPoint(loop.end);
m_loopStack.pop();
}
void Instructions::brk()
{
assert(!m_loopStack.empty());
BasicBlock *unr = BasicBlock::Create(name("unreachable"), m_func,0);
m_builder.CreateBr(m_loopStack.top().end);
m_builder.SetInsertPoint(unr);
}
llvm::Value * Instructions::trunc(llvm::Value *in)
{
std::vector<llvm::Value*> vec = extractVector(in);
Value *icastx = m_builder.CreateFPToSI(vec[0], IntegerType::get(32),
name("ftoix"));
Value *icasty = m_builder.CreateFPToSI(vec[1], IntegerType::get(32),
name("ftoiy"));
Value *icastz = m_builder.CreateFPToSI(vec[2], IntegerType::get(32),
name("ftoiz"));
Value *icastw = m_builder.CreateFPToSI(vec[3], IntegerType::get(32),
name("ftoiw"));
Value *fx = m_builder.CreateSIToFP(icastx, Type::FloatTy,
name("fx"));
Value *fy = m_builder.CreateSIToFP(icasty, Type::FloatTy,
name("fy"));
Value *fz = m_builder.CreateSIToFP(icastz, Type::FloatTy,
name("fz"));
Value *fw = m_builder.CreateSIToFP(icastw, Type::FloatTy,
name("fw"));
return vectorFromVals(fx, fy, fz, fw);
}
void Instructions::end()
{
m_builder.CreateRetVoid();
}
void Instructions::cal(int label, llvm::Value *input)
{
std::vector<Value*> params;
params.push_back(input);
llvm::Function *func = findFunction(label);
m_builder.CreateCall(func, params.begin(), params.end());
}
llvm::Function * Instructions::declareFunc(int label)
{
PointerType *vecPtr = PointerType::getUnqual(m_floatVecType);
std::vector<const Type*> args;
args.push_back(vecPtr);
args.push_back(vecPtr);
args.push_back(vecPtr);
args.push_back(vecPtr);
PAListPtr params;
FunctionType *funcType = FunctionType::get(
/*Result=*/Type::VoidTy,
/*Params=*/args,
/*isVarArg=*/false);
std::string name = createFuncName(label);
Function *func = Function::Create(
/*Type=*/funcType,
/*Linkage=*/GlobalValue::ExternalLinkage,
/*Name=*/name.c_str(), m_mod);
func->setCallingConv(CallingConv::C);
func->setParamAttrs(params);
return func;
}
void Instructions::bgnSub(unsigned label)
{
llvm::Function *func = findFunction(label);
Function::arg_iterator args = func->arg_begin();
Value *ptr_INPUT = args++;
ptr_INPUT->setName("INPUT");
m_storage->pushArguments(ptr_INPUT);
llvm::BasicBlock *entry = BasicBlock::Create("entry", func, 0);
m_func = func;
m_builder.SetInsertPoint(entry);
}
void Instructions::endSub()
{
m_func = 0;
m_builder.SetInsertPoint(0);
}
llvm::Function * Instructions::findFunction(int label)
{
llvm::Function *func = m_functions[label];
if (!func) {
func = declareFunc(label);
m_functions[label] = func;
}
return func;
}
llvm::Value * Instructions::constVector(float x, float y, float z, float w)
{
std::vector<Constant*> vec(4);
vec[0] = ConstantFP::get(APFloat(x));
vec[1] = ConstantFP::get(APFloat(y));
vec[2] = ConstantFP::get(APFloat(z));
vec[3] = ConstantFP::get(APFloat(w));
return ConstantVector::get(m_floatVecType, vec);
}
std::vector<llvm::Value*> Instructions::extractVector(llvm::Value *vec)
{
std::vector<llvm::Value*> elems(4);
elems[0] = m_builder.CreateExtractElement(vec, m_storage->constantInt(0),
name("x"));
elems[1] = m_builder.CreateExtractElement(vec, m_storage->constantInt(1),
name("y"));
elems[2] = m_builder.CreateExtractElement(vec, m_storage->constantInt(2),
name("z"));
elems[3] = m_builder.CreateExtractElement(vec, m_storage->constantInt(3),
name("w"));
return elems;
}
llvm::Value * Instructions::cmp(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3)
{
llvm::Function *func = m_mod->getFunction("cmp");
assert(func);
std::vector<Value*> params;
params.push_back(in1);
params.push_back(in2);
params.push_back(in3);
CallInst *call = m_builder.CreateCall(func, params.begin(), params.end(), name("cmpres"));
call->setTailCall(false);
return call;
}
llvm::Value * Instructions::cos(llvm::Value *in)
{
#if 0
llvm::Function *func = m_mod->getFunction("vcos");
assert(func);
CallInst *call = m_builder.CreateCall(func, in, name("cosres"));
call->setTailCall(false);
return call;
#else
std::vector<llvm::Value*> elems = extractVector(in);
Function *func = m_mod->getFunction("cosf");
assert(func);
CallInst *cos = m_builder.CreateCall(func, elems[0], name("cosres"));
cos->setCallingConv(CallingConv::C);
cos->setTailCall(true);
return vectorFromVals(cos, cos, cos, cos);
#endif
}
llvm::Value * Instructions::scs(llvm::Value *in)
{
llvm::Function *func = m_mod->getFunction("scs");
assert(func);
CallInst *call = m_builder.CreateCall(func, in, name("scsres"));
call->setTailCall(false);
return call;
}
llvm::Value * Instructions::kilp(llvm::Value *in)
{
llvm::Function *func = m_mod->getFunction("kilp");
assert(func);
CallInst *call = m_builder.CreateCall(func, in, name("kilpres"));
call->setTailCall(false);
return call;
}
llvm::Value * Instructions::sin(llvm::Value *in)
{
llvm::Function *func = m_mod->getFunction("vsin");
assert(func);
CallInst *call = m_builder.CreateCall(func, in, name("sinres"));
call->setTailCall(false);
return call;
}
#endif //MESA_LLVM