diff options
author | José Fonseca <[email protected]> | 2009-08-20 20:17:55 +0100 |
---|---|---|
committer | José Fonseca <[email protected]> | 2009-08-29 09:21:37 +0100 |
commit | d07b0383660cd318ba43abad11bb80de4a124951 (patch) | |
tree | bfaf13e65c6fa3158da634a71363b0db0747da3b /src/gallium | |
parent | 89146cd48d37aed0e710d7d935be90b342309f0e (diff) |
llvmpipe: Generate instrinsics for integer comparisons.
It is a little messy, given the available instrucions form SIMD
integer comparisons is rather limited.
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_bld_logic.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_logic.c b/src/gallium/drivers/llvmpipe/lp_bld_logic.c index 95d7f8c5ba4..5b8efb05778 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_logic.c +++ b/src/gallium/drivers/llvmpipe/lp_bld_logic.c @@ -107,6 +107,77 @@ lp_build_cmp(struct lp_build_context *bld, res = LLVMBuildBitCast(bld->builder, res, int_vec_type, ""); return res; } + else { + static const struct { + unsigned swap:1; + unsigned eq:1; + unsigned gt:1; + unsigned not:1; + } table[] = { + {0, 0, 0, 1}, /* PIPE_FUNC_NEVER */ + {1, 0, 1, 0}, /* PIPE_FUNC_LESS */ + {0, 1, 0, 0}, /* PIPE_FUNC_EQUAL */ + {0, 0, 1, 1}, /* PIPE_FUNC_LEQUAL */ + {0, 0, 1, 0}, /* PIPE_FUNC_GREATER */ + {0, 1, 0, 1}, /* PIPE_FUNC_NOTEQUAL */ + {1, 0, 1, 1}, /* PIPE_FUNC_GEQUAL */ + {0, 0, 0, 0} /* PIPE_FUNC_ALWAYS */ + }; + const char *pcmpeq; + const char *pcmpgt; + LLVMValueRef args[2]; + LLVMValueRef res; + + switch (type.width) { + case 8: + pcmpeq = "llvm.x86.sse2.pcmpeq.b"; + pcmpgt = "llvm.x86.sse2.pcmpgt.b"; + break; + case 16: + pcmpeq = "llvm.x86.sse2.pcmpeq.w"; + pcmpgt = "llvm.x86.sse2.pcmpgt.w"; + break; + case 32: + pcmpeq = "llvm.x86.sse2.pcmpeq.d"; + pcmpgt = "llvm.x86.sse2.pcmpgt.d"; + break; + default: + assert(0); + return bld->undef; + } + + /* There are no signed byte and unsigned word/dword comparison + * instructions. So flip the sign bit so that the results match. + */ + if(table[func].gt && + ((type.width == 8 && type.sign) || + (type.width != 8 && !type.sign))) { + LLVMValueRef msb = lp_build_int_const_uni(type, (unsigned long long)1 << (type.width - 1)); + a = LLVMBuildXor(bld->builder, a, msb, ""); + b = LLVMBuildXor(bld->builder, b, msb, ""); + } + + if(table[func].swap) { + args[0] = b; + args[1] = a; + } + else { + args[0] = a; + args[1] = b; + } + + if(table[func].eq) + res = lp_build_intrinsic(bld->builder, pcmpeq, vec_type, args, 2); + else if (table[func].gt) + res = lp_build_intrinsic(bld->builder, pcmpgt, vec_type, args, 2); + else + res = LLVMConstNull(vec_type); + + if(table[func].not) + res = LLVMBuildNot(bld->builder, res, ""); + + return res; + } } #endif |