blob: ee8162efce5319328685f549cf4b364f656cd567 [file] [log] [blame]
/**************************************************************************
*
* 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 "util/u_memory.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/Attributes.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_llvmFexp = 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::BasicBlock * Instructions::currentBlock() const
{
return m_builder.GetInsertBlock();
}
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);
}
llvm::Value * Instructions::add(llvm::Value *in1, llvm::Value *in2)
{
return m_builder.CreateAdd(in1, in2, name("add"));
}
llvm::Value * Instructions::arl(llvm::Value *in)
{
return floor(in);
}
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::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::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);
}
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::Value * Instructions::ceil(llvm::Value *in)
{
std::vector<llvm::Value*> vec = extractVector(in);
return vectorFromVals(callCeil(vec[0]), callCeil(vec[1]),
callCeil(vec[2]), callCeil(vec[3]));
}
llvm::Value * Instructions::clamp(llvm::Value *in1)
{
llvm::Value *zero = constVector(0.0f, 0.0f, 0.0f, 0.0f);
llvm::Value *one = constVector(1.0f, 1.0f, 1.0f, 1.0f);
return min( max(zero, in1), one);
}
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::cnd(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3)
{
std::vector<llvm::Value*> vec1 = extractVector(in1);
std::vector<llvm::Value*> vec2 = extractVector(in2);
std::vector<llvm::Value*> vec3 = extractVector(in3);
Constant *half = ConstantFP::get(APFloat(0.5f));
Value *xcmp = m_builder.CreateFCmpOGT(vec1[0], half, name("xcmp"));
Value *selx = m_builder.CreateSelect(xcmp, vec2[0], vec3[0],
name("selx"));
Value *ycmp = m_builder.CreateFCmpOGT(vec1[1], half, name("ycmp"));
Value *sely = m_builder.CreateSelect(ycmp, vec2[1], vec3[1],
name("sely"));
Value *zcmp = m_builder.CreateFCmpOGT(vec1[2], half, name("zcmp"));
Value *selz = m_builder.CreateSelect(zcmp, vec2[2], vec3[2],
name("selz"));
Value *wcmp = m_builder.CreateFCmpOGT(vec1[3], half, name("wcmp"));
Value *selw = m_builder.CreateSelect(wcmp, vec2[3], vec3[3],
name("selw"));
return vectorFromVals(selx, sely, selz, selw);
}
llvm::Value * Instructions::cnd0(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3)
{
std::vector<llvm::Value*> vec1 = extractVector(in1);
std::vector<llvm::Value*> vec2 = extractVector(in2);
std::vector<llvm::Value*> vec3 = extractVector(in3);
Constant *zero = Constant::getNullValue(Type::FloatTy);
Value *xcmp = m_builder.CreateFCmpOGE(vec1[0], zero, name("xcmp"));
Value *selx = m_builder.CreateSelect(xcmp, vec2[0], vec3[0],
name("selx"));
Value *ycmp = m_builder.CreateFCmpOGE(vec1[1], zero, name("ycmp"));
Value *sely = m_builder.CreateSelect(ycmp, vec2[1], vec3[1],
name("sely"));
Value *zcmp = m_builder.CreateFCmpOGE(vec1[2], zero, name("zcmp"));
Value *selz = m_builder.CreateSelect(zcmp, vec2[2], vec3[2],
name("selz"));
Value *wcmp = m_builder.CreateFCmpOGE(vec1[3], zero, name("wcmp"));
Value *selw = m_builder.CreateSelect(wcmp, vec2[3], vec3[3],
name("selw"));
return vectorFromVals(selx, sely, selz, selw);
}
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::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::ddx(llvm::Value *in)
{
// FIXME
assert(0);
}
llvm::Value * Instructions::ddy(llvm::Value *in)
{
// FIXME
assert(0);
}
llvm::Value * Instructions::div(llvm::Value *in1, llvm::Value *in2)
{
return m_builder.CreateFDiv(in1, in2, name("div"));
}
llvm::Value * Instructions::dot2add(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3)
{
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(in3,
m_storage->constantInt(2),
name("extractz"));
Value *xy = m_builder.CreateAdd(x, y,name("xy"));
Value *dot2add = m_builder.CreateAdd(xy, z, name("dot2add"));
return vectorFromVals(dot2add, dot2add, dot2add, dot2add);
}
llvm::Value * Instructions::dp2(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 *xy = m_builder.CreateAdd(x, y,name("xy"));
return vectorFromVals(xy, xy, xy, xy);
}
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::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);
}
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();
}
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::end()
{
m_builder.CreateRetVoid();
}
void Instructions::endSub()
{
m_func = 0;
m_builder.SetInsertPoint(0);
}
llvm::Value * Instructions::exp(llvm::Value *in)
{
std::vector<llvm::Value*> vec = extractVector(in);
return vectorFromVals(callFExp(vec[0]), callFExp(vec[1]),
callFExp(vec[2]), callFExp(vec[3]));
}
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::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::frc(llvm::Value *in)
{
llvm::Value *flr = floor(in);
return sub(in, flr);
}
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::Value * Instructions::kil(llvm::Value *in)
{
llvm::Function *func = m_mod->getFunction("kil");
assert(func);
CallInst *call = m_builder.CreateCall(func, in, name("kilpres"));
call->setTailCall(false);
return call;
}
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));
}
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::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::log(llvm::Value *in)
{
std::vector<llvm::Value*> vec = extractVector(in);
return vectorFromVals(callFLog(vec[0]), callFLog(vec[1]),
callFLog(vec[2]), callFLog(vec[3]));
}
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::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);
}
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::mul(llvm::Value *in1, llvm::Value *in2)
{
return m_builder.CreateMul(in1, in2, name("mul"));
}
llvm::Value * Instructions::neg(llvm::Value *in)
{
Value *neg = m_builder.CreateNeg(in, name("neg"));
return neg;
}
llvm::Value * Instructions::nrm(llvm::Value *in)
{
llvm::Value *v = rsq(in);
return mul(v, in);
}
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::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::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::seq(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.CreateFCmpOEQ(vec1[0], vec2[0], name("xcmp"));
Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
Value *ycmp = m_builder.CreateFCmpOEQ(vec1[1], vec2[1], name("ycmp"));
Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
Value *zcmp = m_builder.CreateFCmpOEQ(vec1[2], vec2[2], name("zcmp"));
Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
Value *wcmp = m_builder.CreateFCmpOEQ(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::sfl(llvm::Value *in1, llvm::Value *in2)
{
Constant *const0f = Constant::getNullValue(Type::FloatTy);
return vectorFromVals(const0f, const0f, const0f, const0f);
}
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::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::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;
}
llvm::Value * Instructions::sle(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.CreateFCmpOLE(vec1[0], vec2[0], name("xcmp"));
Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
Value *ycmp = m_builder.CreateFCmpOLE(vec1[1], vec2[1], name("ycmp"));
Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
Value *zcmp = m_builder.CreateFCmpOLE(vec1[2], vec2[2], name("zcmp"));
Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
Value *wcmp = m_builder.CreateFCmpOLE(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::sne(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.CreateFCmpONE(vec1[0], vec2[0], name("xcmp"));
Value *x = m_builder.CreateSelect(xcmp, const1f, const0f, name("xsel"));
Value *ycmp = m_builder.CreateFCmpONE(vec1[1], vec2[1], name("ycmp"));
Value *y = m_builder.CreateSelect(ycmp, const1f, const0f, name("ysel"));
Value *zcmp = m_builder.CreateFCmpONE(vec1[2], vec2[2], name("zcmp"));
Value *z = m_builder.CreateSelect(zcmp, const1f, const0f, name("zsel"));
Value *wcmp = m_builder.CreateFCmpONE(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::str(llvm::Value *in1, llvm::Value *in2)
{
Constant *const1f = ConstantFP::get(APFloat(1.000000e+00f));
return vectorFromVals(const1f, const1f, const1f, const1f);
}
llvm::Value * Instructions::sub(llvm::Value *in1, llvm::Value *in2)
{
Value *res = m_builder.CreateSub(in1, in2, name("sub"));
return res;
}
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);
}
llvm::Value * Instructions::x2d(llvm::Value *in1, llvm::Value *in2, llvm::Value *in3)
{
std::vector<llvm::Value*> vec1 = extractVector(in1);
std::vector<llvm::Value*> vec2 = extractVector(in2);
std::vector<llvm::Value*> vec3 = extractVector(in3);
Value *x2x3 = m_builder.CreateMul( vec2[0], vec3[0], name("x2x3"));
Value *y2y3 = m_builder.CreateMul( vec2[1], vec3[1], name("y2y3"));
Value *x1px2x3 = m_builder.CreateAdd (vec1[0], x2x3, name("x1 + x2x3"));
Value *x1px2x3py2y3 = m_builder.CreateAdd (x1px2x3, y2y3, name("x1 + x2x3 + y2y3"));
Value *x2z3 = m_builder.CreateMul( vec2[0], vec3[2], name("x2z3"));
Value *y2w3 = m_builder.CreateMul( vec2[1], vec3[3], name("y2w3"));
Value *y1px2z3 = m_builder.CreateAdd (vec1[1], x2z3, name("y1 + x2z3"));
Value *y1px2z3py2w3 = m_builder.CreateAdd (y1px2z3, y2w3, name("y1 + x2z3 + y2w3"));
return vectorFromVals(x1px2x3py2y3, y1px2z3py2w3, x1px2x3py2y3, y1px2z3py2w3);
}
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);
}
const char * Instructions::name(const char *prefix)
{
++m_idx;
snprintf(m_name, 32, "%s%d", prefix, m_idx);
return m_name;
}
llvm::Value * Instructions::callCeil(llvm::Value *val)
{
if (!m_llvmCeil) {
// predeclare the intrinsic
std::vector<const Type*> ceilArgs;
ceilArgs.push_back(Type::FloatTy);
AttrListPtr ceilPal;
FunctionType* ceilType = FunctionType::get(
/*Result=*/Type::FloatTy,
/*Params=*/ceilArgs,
/*isVarArg=*/false);
m_llvmCeil = Function::Create(
/*Type=*/ceilType,
/*Linkage=*/GlobalValue::ExternalLinkage,
/*Name=*/"ceilf", m_mod);
m_llvmCeil->setCallingConv(CallingConv::C);
m_llvmCeil->setAttributes(ceilPal);
}
CallInst *call = m_builder.CreateCall(m_llvmCeil, val,
name("ceilf"));
call->setCallingConv(CallingConv::C);
call->setTailCall(false);
return call;
}
llvm::Value *Instructions::callFAbs(llvm::Value *val)
{
if (!m_llvmFAbs) {
// predeclare the intrinsic
std::vector<const Type*> fabsArgs;
fabsArgs.push_back(Type::FloatTy);
AttrListPtr 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->setAttributes(fabsPal);
}
CallInst *call = m_builder.CreateCall(m_llvmFAbs, val,
name("fabs"));
call->setCallingConv(CallingConv::C);
call->setTailCall(false);
return call;
}
llvm::Value * Instructions::callFExp(llvm::Value *val)
{
if (!m_llvmFexp) {
// predeclare the intrinsic
std::vector<const Type*> fexpArgs;
fexpArgs.push_back(Type::FloatTy);
AttrListPtr fexpPal;
FunctionType* fexpType = FunctionType::get(
/*Result=*/Type::FloatTy,
/*Params=*/fexpArgs,
/*isVarArg=*/false);
m_llvmFexp = Function::Create(
/*Type=*/fexpType,
/*Linkage=*/GlobalValue::ExternalLinkage,
/*Name=*/"expf", m_mod);
m_llvmFexp->setCallingConv(CallingConv::C);
m_llvmFexp->setAttributes(fexpPal);
}
CallInst *call = m_builder.CreateCall(m_llvmFexp, val,
name("expf"));
call->setCallingConv(CallingConv::C);
call->setTailCall(false);
return call;
}
llvm::Value * Instructions::callFLog(llvm::Value *val)
{
if (!m_llvmFlog) {
// predeclare the intrinsic
std::vector<const Type*> flogArgs;
flogArgs.push_back(Type::FloatTy);
AttrListPtr 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->setAttributes(flogPal);
}
CallInst *call = m_builder.CreateCall(m_llvmFlog, val,
name("logf"));
call->setCallingConv(CallingConv::C);
call->setTailCall(false);
return call;
}
llvm::Value * Instructions::callFloor(llvm::Value *val)
{
if (!m_llvmFloor) {
// predeclare the intrinsic
std::vector<const Type*> floorArgs;
floorArgs.push_back(Type::FloatTy);
AttrListPtr 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->setAttributes(floorPal);
}
CallInst *call = m_builder.CreateCall(m_llvmFloor, val,
name("floorf"));
call->setCallingConv(CallingConv::C);
call->setTailCall(false);
return call;
}
llvm::Value *Instructions::callFSqrt(llvm::Value *val)
{
if (!m_llvmFSqrt) {
// predeclare the intrinsic
std::vector<const Type*> fsqrtArgs;
fsqrtArgs.push_back(Type::FloatTy);
AttrListPtr 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->setAttributes(fsqrtPal);
}
CallInst *call = m_builder.CreateCall(m_llvmFSqrt, val,
name("sqrt"));
call->setCallingConv(CallingConv::C);
call->setTailCall(false);
return call;
}
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);
AttrListPtr 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->setAttributes(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::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::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);
}
llvm::Function * Instructions::declarePrintf()
{
std::vector<const Type*> args;
AttrListPtr 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->setAttributes(params);
return func_printf;
}
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);
AttrListPtr 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->setAttributes(params);
return func;
}
llvm::Function * Instructions::findFunction(int label)
{
llvm::Function *func = m_functions[label];
if (!func) {
func = declareFunc(label);
m_functions[label] = func;
}
return func;
}
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;
}
#endif //MESA_LLVM