Commit c61bf363 authored by Zack Rusin's avatar Zack Rusin
Browse files

llvmpipe: export the tgsi translation code to a common layer

the llvmpipe tgsi translation is a lot more complete than what was in
gallivm so replacing the latter with the former. this is needed since
the draw llvm paths will use the same code. effectively the proven
llvmpipe code becomes gallivm.
parent 74d23546
......@@ -79,9 +79,10 @@ Help(opts.GenerateHelpText(env))
# replicate options values in local variables
debug = env['debug']
dri = env['dri']
llvm = env['llvm']
machine = env['machine']
platform = env['platform']
drawllvm = 'llvmpipe' in env['drivers']
# derived options
x86 = machine == 'x86'
......@@ -94,7 +95,7 @@ Export([
'x86',
'ppc',
'dri',
'llvm',
'drawllvm',
'platform',
'gcc',
'msvc',
......@@ -165,13 +166,12 @@ if dri:
'GLX_INDIRECT_RENDERING',
])
# LLVM
if llvm:
# LLVM support in the Draw module
if drawllvm:
# See also http://www.scons.org/wiki/UsingPkgConfig
env.ParseConfig('llvm-config --cflags --ldflags --libs backend bitreader engine instrumentation interpreter ipo')
env.Append(CPPDEFINES = ['MESA_LLVM'])
# Force C++ linkage
env['LINK'] = env['CXX']
# currently --ldflags --libsdisabled since the driver will force the correct linkage
env.ParseConfig('llvm-config --cflags backend bitreader engine instrumentation interpreter ipo')
env.Append(CPPDEFINES = ['DRAW_LLVM'])
# libGL
if platform in ('linux', 'freebsd', 'darwin'):
......
......@@ -12,7 +12,7 @@ GALLIUM_DRIVERS_DIRS += llvmpipe
OPT_FLAGS = -O3 -ansi -pedantic
ARCH_FLAGS = -m32 -mmmx -msse -msse2 -mstackrealign
DEFINES += -DNDEBUG -DGALLIUM_LLVMPIPE -DHAVE_UDIS86
DEFINES += -DNDEBUG -DGALLIUM_LLVMPIPE -DDRAW_LLVM -DHAVE_UDIS86
# override -std=c99
CFLAGS += -std=gnu99
......
......@@ -130,41 +130,40 @@ C_SOURCES = \
vl/vl_shader_build.c
GALLIVM_SOURCES = \
gallivm/gallivm.cpp \
gallivm/gallivm_cpu.cpp \
gallivm/instructions.cpp \
gallivm/loweringpass.cpp \
gallivm/tgsitollvm.cpp \
gallivm/storage.cpp \
gallivm/storagesoa.cpp \
gallivm/instructionssoa.cpp
gallivm/lp_bld_alpha.c \
gallivm/lp_bld_arit.c \
gallivm/lp_bld_blend_aos.c \
gallivm/lp_bld_blend_logicop.c \
gallivm/lp_bld_blend_soa.c \
gallivm/lp_bld_const.c \
gallivm/lp_bld_conv.c \
gallivm/lp_bld_debug.c \
gallivm/lp_bld_depth.c \
gallivm/lp_bld_flow.c \
gallivm/lp_bld_format_aos.c \
gallivm/lp_bld_format_query.c \
gallivm/lp_bld_format_soa.c \
gallivm/lp_bld_interp.c \
gallivm/lp_bld_intr.c \
gallivm/lp_bld_logic.c \
gallivm/lp_bld_pack.c \
gallivm/lp_bld_sample.c \
gallivm/lp_bld_sample_soa.c \
gallivm/lp_bld_struct.c \
gallivm/lp_bld_swizzle.c \
gallivm/lp_bld_tgsi_soa.c \
gallivm/lp_bld_type.c
INC_SOURCES = \
gallivm/gallivm_builtins.cpp \
gallivm/gallivmsoabuiltins.cpp
# XXX: gallivm doesn't build correctly so disable for now
#ifeq ($(MESA_LLVM),1)
#DEFINES += -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS
#CPP_SOURCES += \
# $(GALLIVM_SOURCES)
#endif
ifeq ($(MESA_LLVM),1)
C_SOURCES += \
$(GALLIVM_SOURCES)
endif
include ../Makefile.template
gallivm/gallivm_builtins.cpp: gallivm/llvm_builtins.c
clang --emit-llvm < $< |llvm-as|opt -std-compile-opts > temp1.bin
(echo "static const unsigned char llvm_builtins_data[] = {"; od -txC temp1.bin | sed -e "s/^[0-9]*//" -e s"/ \([0-9a-f][0-9a-f]\)/0x\1,/g" -e"\$$d" | sed -e"\$$s/,$$/,0x00};/") >$@
rm temp1.bin
gallivm/gallivmsoabuiltins.cpp: gallivm/soabuiltins.c
clang --emit-llvm < $< |llvm-as|opt -std-compile-opts > temp2.bin
(echo "static const unsigned char soabuiltins_data[] = {"; od -txC temp2.bin | sed -e "s/^[0-9]*//" -e s"/ \([0-9a-f][0-9a-f]\)/0x\1,/g" -e"\$$d" | sed -e"\$$s/,$$/,0x00};/") >$@
rm temp2.bin
indices/u_indices_gen.c: indices/u_indices_gen.py
python $< > $@
......
......@@ -166,16 +166,31 @@ source = [
'vl/vl_shader_build.c',
]
if env['llvm']:
if drawllvm:
source += [
'gallivm/gallivm.cpp',
'gallivm/gallivm_cpu.cpp',
'gallivm/instructions.cpp',
'gallivm/loweringpass.cpp',
'gallivm/tgsitollvm.cpp',
'gallivm/storage.cpp',
'gallivm/storagesoa.cpp',
'gallivm/instructionssoa.cpp',
'gallivm/lp_bld_alpha.c',
'gallivm/lp_bld_arit.c',
'gallivm/lp_bld_blend_aos.c',
'gallivm/lp_bld_blend_logicop.c',
'gallivm/lp_bld_blend_soa.c',
'gallivm/lp_bld_const.c',
'gallivm/lp_bld_conv.c',
'gallivm/lp_bld_debug.c',
'gallivm/lp_bld_depth.c',
'gallivm/lp_bld_flow.c',
'gallivm/lp_bld_format_aos.c',
'gallivm/lp_bld_format_query.c',
'gallivm/lp_bld_format_soa.c',
'gallivm/lp_bld_interp.c',
'gallivm/lp_bld_intr.c',
'gallivm/lp_bld_logic.c',
'gallivm/lp_bld_pack.c',
'gallivm/lp_bld_sample.c',
'gallivm/lp_bld_sample_soa.c',
'gallivm/lp_bld_struct.c',
'gallivm/lp_bld_swizzle.c',
'gallivm/lp_bld_tgsi_soa.c',
'gallivm/lp_bld_type.c',
]
gallium = env.ConvenienceLibrary(
......
......@@ -48,8 +48,6 @@
struct pipe_context;
struct gallivm_prog;
struct gallivm_cpu_engine;
struct draw_vertex_shader;
struct draw_context;
struct draw_stage;
......@@ -193,10 +191,6 @@ struct draw_context
uint num_samplers;
struct tgsi_sampler **samplers;
/* This (and the tgsi_exec_machine struct) probably need to be moved somewhere private.
*/
struct gallivm_cpu_engine *engine;
/* Here's another one:
*/
struct aos_machine *aos_machine;
......
......@@ -42,11 +42,8 @@
#ifdef MESA_LLVM
#include "gallivm/gallivm.h"
struct draw_llvm_vertex_shader {
struct draw_vertex_shader base;
struct gallivm_prog *llvm_prog;
struct tgsi_exec_machine *machine;
};
......@@ -58,8 +55,6 @@ vs_llvm_prepare( struct draw_vertex_shader *base,
}
static void
vs_llvm_run_linear( struct draw_vertex_shader *base,
const float (*input)[4],
......@@ -71,11 +66,6 @@ vs_llvm_run_linear( struct draw_vertex_shader *base,
{
struct draw_llvm_vertex_shader *shader =
(struct draw_llvm_vertex_shader *)base;
gallivm_cpu_vs_exec(shader->llvm_prog, shader->machine,
input, base->info.num_inputs, output, base->info.num_outputs,
(const float (*)[4])constants[0],
count, input_stride, output_stride);
}
......@@ -122,27 +112,6 @@ draw_create_vs_llvm(struct draw_context *draw,
vs->base.delete = vs_llvm_delete;
vs->machine = draw->vs.machine;
{
struct gallivm_ir *ir = gallivm_ir_new(GALLIVM_VS);
gallivm_ir_set_layout(ir, GALLIVM_SOA);
gallivm_ir_set_components(ir, 4);
gallivm_ir_fill_from_tgsi(ir, vs->base.state.tokens);
vs->llvm_prog = gallivm_ir_compile(ir);
gallivm_ir_delete(ir);
}
draw->vs.engine = gallivm_global_cpu_engine();
/* XXX: Why are there two versions of this? Shouldn't creating the
* engine be a separate operation to compiling a shader?
*/
if (!draw->vs.engine) {
draw->vs.engine = gallivm_cpu_engine_create(vs->llvm_prog);
}
else {
gallivm_cpu_jit_compile(draw->vs.engine, vs->llvm_prog);
}
return &vs->base;
}
......
/**************************************************************************
*
* 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 "gallivm.h"
#include "gallivm_p.h"
#include "instructions.h"
#include "loweringpass.h"
#include "storage.h"
#include "tgsitollvm.h"
#include "pipe/p_context.h"
#include "pipe/p_shader_tokens.h"
#include "tgsi/tgsi_exec.h"
#include "tgsi/tgsi_dump.h"
#include <llvm/Module.h>
#include <llvm/CallingConv.h>
#include <llvm/Constants.h>
#include <llvm/DerivedTypes.h>
#include <llvm/Instructions.h>
#include <llvm/ModuleProvider.h>
#include <llvm/Pass.h>
#include <llvm/PassManager.h>
#include <llvm/Attributes.h>
#include <llvm/Support/PatternMatch.h>
#include <llvm/ExecutionEngine/JIT.h>
#include <llvm/ExecutionEngine/Interpreter.h>
#include <llvm/ExecutionEngine/GenericValue.h>
#include <llvm/Support/MemoryBuffer.h>
#include <llvm/LinkAllPasses.h>
#include <llvm/Analysis/Verifier.h>
#include <llvm/Analysis/LoopPass.h>
#include <llvm/Target/TargetData.h>
#include <llvm/Bitcode/ReaderWriter.h>
#include <llvm/Transforms/Utils/Cloning.h>
#include <sstream>
#include <fstream>
#include <iostream>
static int GLOBAL_ID = 0;
using namespace llvm;
static inline
void AddStandardCompilePasses(PassManager &PM)
{
PM.add(new LoweringPass());
PM.add(createVerifierPass()); // Verify that input is correct
PM.add(createLowerSetJmpPass()); // Lower llvm.setjmp/.longjmp
//PM.add(createStripSymbolsPass(true));
PM.add(createRaiseAllocationsPass()); // call %malloc -> malloc inst
PM.add(createCFGSimplificationPass()); // Clean up disgusting code
PM.add(createPromoteMemoryToRegisterPass());// Kill useless allocas
PM.add(createGlobalOptimizerPass()); // Optimize out global vars
PM.add(createGlobalDCEPass()); // Remove unused fns and globs
PM.add(createIPConstantPropagationPass());// IP Constant Propagation
PM.add(createDeadArgEliminationPass()); // Dead argument elimination
PM.add(createInstructionCombiningPass()); // Clean up after IPCP & DAE
PM.add(createCFGSimplificationPass()); // Clean up after IPCP & DAE
PM.add(createPruneEHPass()); // Remove dead EH info
PM.add(createFunctionInliningPass()); // Inline small functions
PM.add(createArgumentPromotionPass()); // Scalarize uninlined fn args
PM.add(createTailDuplicationPass()); // Simplify cfg by copying code
PM.add(createInstructionCombiningPass()); // Cleanup for scalarrepl.
PM.add(createCFGSimplificationPass()); // Merge & remove BBs
PM.add(createScalarReplAggregatesPass()); // Break up aggregate allocas
PM.add(createInstructionCombiningPass()); // Combine silly seq's
PM.add(createCondPropagationPass()); // Propagate conditionals
PM.add(createTailCallEliminationPass()); // Eliminate tail calls
PM.add(createCFGSimplificationPass()); // Merge & remove BBs
PM.add(createReassociatePass()); // Reassociate expressions
PM.add(createLoopRotatePass());
PM.add(createLICMPass()); // Hoist loop invariants
PM.add(createLoopUnswitchPass()); // Unswitch loops.
PM.add(createLoopIndexSplitPass()); // Index split loops.
PM.add(createInstructionCombiningPass()); // Clean up after LICM/reassoc
PM.add(createIndVarSimplifyPass()); // Canonicalize indvars
PM.add(createLoopUnrollPass()); // Unroll small loops
PM.add(createInstructionCombiningPass()); // Clean up after the unroller
PM.add(createGVNPass()); // Remove redundancies
PM.add(createSCCPPass()); // Constant prop with SCCP
// Run instcombine after redundancy elimination to exploit opportunities
// opened up by them.
PM.add(createInstructionCombiningPass());
PM.add(createCondPropagationPass()); // Propagate conditionals
PM.add(createDeadStoreEliminationPass()); // Delete dead stores
PM.add(createAggressiveDCEPass()); // SSA based 'Aggressive DCE'
PM.add(createCFGSimplificationPass()); // Merge & remove BBs
PM.add(createSimplifyLibCallsPass()); // Library Call Optimizations
PM.add(createDeadTypeEliminationPass()); // Eliminate dead types
PM.add(createConstantMergePass()); // Merge dup global constants
}
void gallivm_prog_delete(struct gallivm_prog *prog)
{
delete prog->module;
prog->module = 0;
prog->function = 0;
free(prog);
}
static inline void
constant_interpolation(float (*inputs)[16][4],
const struct tgsi_interp_coef *coefs,
unsigned attrib,
unsigned chan)
{
unsigned i;
for (i = 0; i < QUAD_SIZE; ++i) {
inputs[i][attrib][chan] = coefs[attrib].a0[chan];
}
}
static inline void
linear_interpolation(float (*inputs)[16][4],
const struct tgsi_interp_coef *coefs,
unsigned attrib,
unsigned chan)
{
unsigned i;
for( i = 0; i < QUAD_SIZE; i++ ) {
const float x = inputs[i][0][0];
const float y = inputs[i][0][1];
inputs[i][attrib][chan] =
coefs[attrib].a0[chan] +
coefs[attrib].dadx[chan] * x +
coefs[attrib].dady[chan] * y;
}
}
static inline void
perspective_interpolation(float (*inputs)[16][4],
const struct tgsi_interp_coef *coefs,
unsigned attrib,
unsigned chan )
{
unsigned i;
for( i = 0; i < QUAD_SIZE; i++ ) {
const float x = inputs[i][0][0];
const float y = inputs[i][0][1];
/* WPOS.w here is really 1/w */
const float w = 1.0f / inputs[i][0][3];
assert(inputs[i][0][3] != 0.0);
inputs[i][attrib][chan] =
(coefs[attrib].a0[chan] +
coefs[attrib].dadx[chan] * x +
coefs[attrib].dady[chan] * y) * w;
}
}
void gallivm_ir_dump(struct gallivm_ir *ir, const char *file_prefix)
{
if (!ir || !ir->module)
return;
if (file_prefix) {
std::ostringstream stream;
stream << file_prefix;
stream << ir->id;
stream << ".ll";
std::string name = stream.str();
std::ofstream out(name.c_str());
if (!out) {
std::cerr<<"Can't open file : "<<stream.str()<<std::endl;;
return;
}
out << (*ir->module);
out.close();
} else {
const llvm::Module::FunctionListType &funcs = ir->module->getFunctionList();
llvm::Module::FunctionListType::const_iterator itr;
std::cout<<"; ---------- Start shader "<<ir->id<<std::endl;
for (itr = funcs.begin(); itr != funcs.end(); ++itr) {
const llvm::Function &func = (*itr);
std::string name = func.getName();
const llvm::Function *found = 0;
if (name.find("vs_shader") != std::string::npos ||
name.find("fs_shader") != std::string::npos ||
name.find("function") != std::string::npos)
found = &func;
if (found) {
std::cout<<*found<<std::endl;
}
}
std::cout<<"; ---------- End shader "<<ir->id<<std::endl;
}
}
void gallivm_prog_inputs_interpolate(struct gallivm_prog *prog,
float (*inputs)[16][4],
const struct tgsi_interp_coef *coef)
{
for (int i = 0; i < prog->num_interp; ++i) {
const gallivm_interpolate &interp = prog->interpolators[i];
switch (interp.type) {
case TGSI_INTERPOLATE_CONSTANT:
constant_interpolation(inputs, coef, interp.attrib, interp.chan);
break;
case TGSI_INTERPOLATE_LINEAR:
linear_interpolation(inputs, coef, interp.attrib, interp.chan);
break;
case TGSI_INTERPOLATE_PERSPECTIVE:
perspective_interpolation(inputs, coef, interp.attrib, interp.chan);
break;
default:
assert( 0 );
}
}
}
struct gallivm_ir * gallivm_ir_new(enum gallivm_shader_type type)
{
struct gallivm_ir *ir =
(struct gallivm_ir *)calloc(1, sizeof(struct gallivm_ir));
++GLOBAL_ID;
ir->id = GLOBAL_ID;
ir->type = type;
return ir;
}
void gallivm_ir_set_layout(struct gallivm_ir *ir,
enum gallivm_vector_layout layout)
{
ir->layout = layout;
}
void gallivm_ir_set_components(struct gallivm_ir *ir, int num)
{
ir->num_components = num;
}
void gallivm_ir_fill_from_tgsi(struct gallivm_ir *ir,
const struct tgsi_token *tokens)
{
std::cout << "Creating llvm from: " <<std::endl;
tgsi_dump(tokens, 0);
llvm::Module *mod = tgsi_to_llvmir(ir, tokens);
ir->module = mod;
gallivm_ir_dump(ir, 0);
}
void gallivm_ir_delete(struct gallivm_ir *ir)
{
delete ir->module;
free(ir);
}
struct gallivm_prog * gallivm_ir_compile(struct gallivm_ir *ir)
{
struct gallivm_prog *prog =
(struct gallivm_prog *)calloc(1, sizeof(struct gallivm_prog));
std::cout << "Before optimizations:"<<std::endl;
ir->module->dump();
std::cout<<"-------------------------------"<<std::endl;
PassManager veri;
veri.add(createVerifierPass());
veri.run(*ir->module);
llvm::Module *mod = llvm::CloneModule(ir->module);
prog->num_consts = ir->num_consts;
memcpy(prog->interpolators, ir->interpolators, sizeof(prog->interpolators));
prog->num_interp = ir->num_interp;
/* Run optimization passes over it */
PassManager passes;
passes.add(new TargetData(mod));
AddStandardCompilePasses(passes);
passes.run(*mod);
prog->module = mod;
std::cout << "After optimizations:"<<std::endl;
mod->dump();
return prog;
}
#endif /* MESA_LLVM */
/**************************************************************************
*
* 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.
*
**************************************************************************/
/*