llvmpipe: add test program for round(), trunc(), floor(), ceil()

This commit is contained in:
Brian Paul 2010-07-06 11:36:01 -06:00
parent e834c48100
commit 7743791da0
2 changed files with 278 additions and 0 deletions

View File

@ -54,6 +54,7 @@ PROGS := lp_test_format \
lp_test_blend \
lp_test_conv \
lp_test_printf \
lp_test_round \
lp_test_sincos
lp_test_sincos.o : sse_mathfun.h

View File

@ -0,0 +1,277 @@
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include "util/u_pointer.h"
#include "gallivm/lp_bld.h"
#include "gallivm/lp_bld_printf.h"
#include "gallivm/lp_bld_arit.h"
#include <llvm-c/Analysis.h>
#include <llvm-c/ExecutionEngine.h>
#include <llvm-c/Target.h>
#include <llvm-c/Transforms/Scalar.h>
#include "lp_test.h"
void
write_tsv_header(FILE *fp)
{
fprintf(fp,
"result\t"
"format\n");
fflush(fp);
}
#ifdef PIPE_ARCH_SSE
#define USE_SSE2
#include "sse_mathfun.h"
typedef __m128 (*test_round_t)(__m128);
typedef LLVMValueRef (*lp_func_t)(struct lp_build_context *, LLVMValueRef);
static LLVMValueRef
add_test(LLVMModuleRef module, const char *name, lp_func_t lp_func)
{
LLVMTypeRef v4sf = LLVMVectorType(LLVMFloatType(), 4);
LLVMTypeRef args[1] = { v4sf };
LLVMValueRef func = LLVMAddFunction(module, name, LLVMFunctionType(v4sf, args, 1, 0));
LLVMValueRef arg1 = LLVMGetParam(func, 0);
LLVMBuilderRef builder = LLVMCreateBuilder();
LLVMBasicBlockRef block = LLVMAppendBasicBlock(func, "entry");
LLVMValueRef ret;
struct lp_build_context bld;
bld.builder = builder;
bld.type.floating = 1;
bld.type.width = 32;
bld.type.length = 4;
LLVMSetFunctionCallConv(func, LLVMCCallConv);
LLVMPositionBuilderAtEnd(builder, block);
ret = lp_func(&bld, arg1);
LLVMBuildRet(builder, ret);
LLVMDisposeBuilder(builder);
return func;
}
static void
printv(char* string, v4sf value)
{
v4sf v = value;
float *f = (float *)&v;
printf("%s: %10f %10f %10f %10f\n", string,
f[0], f[1], f[2], f[3]);
}
static void
compare(v4sf x, v4sf y)
{
float *xp = (float *) &x;
float *yp = (float *) &y;
if (xp[0] != yp[0] ||
xp[1] != yp[1] ||
xp[2] != yp[2] ||
xp[3] != yp[3]) {
printf(" Incorrect result! ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ \n");
}
}
PIPE_ALIGN_STACK
static boolean
test_round(unsigned verbose, FILE *fp)
{
LLVMModuleRef module = NULL;
LLVMValueRef test_round = NULL, test_trunc, test_floor, test_ceil;
LLVMExecutionEngineRef engine = NULL;
LLVMModuleProviderRef provider = NULL;
LLVMPassManagerRef pass = NULL;
char *error = NULL;
test_round_t round_func, trunc_func, floor_func, ceil_func;
float unpacked[4];
unsigned packed;
boolean success = TRUE;
int i;
module = LLVMModuleCreateWithName("test");
test_round = add_test(module, "round", lp_build_round);
test_trunc = add_test(module, "trunc", lp_build_trunc);
test_floor = add_test(module, "floor", lp_build_floor);
test_ceil = add_test(module, "ceil", lp_build_ceil);
if(LLVMVerifyModule(module, LLVMPrintMessageAction, &error)) {
printf("LLVMVerifyModule: %s\n", error);
LLVMDumpModule(module);
abort();
}
LLVMDisposeMessage(error);
provider = LLVMCreateModuleProviderForExistingModule(module);
if (LLVMCreateJITCompiler(&engine, provider, 1, &error)) {
fprintf(stderr, "%s\n", error);
LLVMDisposeMessage(error);
abort();
}
#if 0
pass = LLVMCreatePassManager();
LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), pass);
/* These are the passes currently listed in llvm-c/Transforms/Scalar.h,
* but there are more on SVN. */
LLVMAddConstantPropagationPass(pass);
LLVMAddInstructionCombiningPass(pass);
LLVMAddPromoteMemoryToRegisterPass(pass);
LLVMAddGVNPass(pass);
LLVMAddCFGSimplificationPass(pass);
LLVMRunPassManager(pass, module);
#else
(void)pass;
#endif
round_func = (test_round_t) pointer_to_func(LLVMGetPointerToGlobal(engine, test_round));
trunc_func = (test_round_t) pointer_to_func(LLVMGetPointerToGlobal(engine, test_trunc));
floor_func = (test_round_t) pointer_to_func(LLVMGetPointerToGlobal(engine, test_floor));
ceil_func = (test_round_t) pointer_to_func(LLVMGetPointerToGlobal(engine, test_ceil));
memset(unpacked, 0, sizeof unpacked);
packed = 0;
if (0)
LLVMDumpModule(module);
for (i = 0; i < 3; i++) {
v4sf xvals[3] = {
{-10.0, -1, 0, 12.0},
{-1.5, -0.25, 1.25, 2.5},
{-0.99, -0.01, 0.01, 0.99}
};
v4sf x = xvals[i];
v4sf y, ref;
float *xp = (float *) &x;
float *refp = (float *) &ref;
printf("\n");
printv("x ", x);
refp[0] = round(xp[0]);
refp[1] = round(xp[1]);
refp[2] = round(xp[2]);
refp[3] = round(xp[3]);
y = round_func(x);
printv("C round(x) ", ref);
printv("LLVM round(x)", y);
compare(ref, y);
refp[0] = trunc(xp[0]);
refp[1] = trunc(xp[1]);
refp[2] = trunc(xp[2]);
refp[3] = trunc(xp[3]);
y = trunc_func(x);
printv("C trunc(x) ", ref);
printv("LLVM trunc(x)", y);
compare(ref, y);
refp[0] = floor(xp[0]);
refp[1] = floor(xp[1]);
refp[2] = floor(xp[2]);
refp[3] = floor(xp[3]);
y = floor_func(x);
printv("C floor(x) ", ref);
printv("LLVM floor(x)", y);
compare(ref, y);
refp[0] = ceil(xp[0]);
refp[1] = ceil(xp[1]);
refp[2] = ceil(xp[2]);
refp[3] = ceil(xp[3]);
y = ceil_func(x);
printv("C ceil(x) ", ref);
printv("LLVM ceil(x) ", y);
compare(ref, y);
}
LLVMFreeMachineCodeForFunction(engine, test_round);
LLVMFreeMachineCodeForFunction(engine, test_trunc);
LLVMFreeMachineCodeForFunction(engine, test_floor);
LLVMFreeMachineCodeForFunction(engine, test_ceil);
LLVMDisposeExecutionEngine(engine);
if(pass)
LLVMDisposePassManager(pass);
return success;
}
#else /* !PIPE_ARCH_SSE */
static boolean
test_round(unsigned verbose, FILE *fp)
{
return TRUE;
}
#endif /* !PIPE_ARCH_SSE */
boolean
test_all(unsigned verbose, FILE *fp)
{
boolean success = TRUE;
test_round(verbose, fp);
return success;
}
boolean
test_some(unsigned verbose, FILE *fp, unsigned long n)
{
return test_all(verbose, fp);
}
boolean
test_single(unsigned verbose, FILE *fp)
{
printf("no test_single()");
return TRUE;
}