903 lines
31 KiB
C++
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
|
|
|
|
|