From: Zack Rusin Date: Tue, 9 Apr 2013 10:28:48 +0000 (-0700) Subject: gallivm: fix unsigned divide and remainder opcodes X-Git-Tag: android-x86-4.4-r1~454 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=7466e0b6c84ce0c6029e60739daac8baeccb8b0b;p=android-x86%2Fexternal-mesa.git gallivm: fix unsigned divide and remainder opcodes We want to both make sure we never divide by zero to not generate sigfpe and that divide by zero is guaranteed to return 0xffffffff. Based on José idea. Signed-off-by: Zack Rusin Reviewed-by: Jose Fonseca Reviewed-by: Roland Scheidegger --- diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c index f3ae7b6b6d8..c71c1f111bd 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c @@ -1543,8 +1543,23 @@ udiv_emit_cpu( struct lp_build_tgsi_context * bld_base, struct lp_build_emit_data * emit_data) { - emit_data->output[emit_data->chan] = lp_build_div(&bld_base->uint_bld, - emit_data->args[0], emit_data->args[1]); + + LLVMBuilderRef builder = bld_base->base.gallivm->builder; + LLVMValueRef div_mask = lp_build_cmp(&bld_base->uint_bld, + PIPE_FUNC_EQUAL, emit_data->args[1], + bld_base->uint_bld.zero); + /* We want to make sure that we never divide/mod by zero to not + * generate sigfpe. We don't want to crash just because the + * shader is doing something weird. */ + LLVMValueRef divisor = LLVMBuildOr(builder, + div_mask, + emit_data->args[1], ""); + LLVMValueRef result = lp_build_div(&bld_base->uint_bld, + emit_data->args[0], divisor); + /* udiv by zero is guaranteed to return 0xffffffff */ + emit_data->output[emit_data->chan] = LLVMBuildOr(builder, + div_mask, + result, ""); } /* TGSI_OPCODE_UMAX (CPU Only) */ @@ -1576,8 +1591,22 @@ umod_emit_cpu( struct lp_build_tgsi_context * bld_base, struct lp_build_emit_data * emit_data) { - emit_data->output[emit_data->chan] = lp_build_mod(&bld_base->uint_bld, - emit_data->args[0], emit_data->args[1]); + LLVMBuilderRef builder = bld_base->base.gallivm->builder; + LLVMValueRef div_mask = lp_build_cmp(&bld_base->uint_bld, + PIPE_FUNC_EQUAL, emit_data->args[1], + bld_base->uint_bld.zero); + /* We want to make sure that we never divide/mod by zero to not + * generate sigfpe. We don't want to crash just because the + * shader is doing something weird. */ + LLVMValueRef divisor = LLVMBuildOr(builder, + div_mask, + emit_data->args[1], ""); + LLVMValueRef result = lp_build_mod(&bld_base->uint_bld, + emit_data->args[0], divisor); + /* umod by zero is guaranteed to return 0xffffffff */ + emit_data->output[emit_data->chan] = LLVMBuildOr(builder, + div_mask, + result, ""); } /* TGSI_OPCODE_USET Helper (CPU Only) */