[Mesa-dev] [PATCH 3/4] r600/radeonsi: implement new float comparison instructions
Tom Stellard
tom at stellard.net
Tue Aug 13 19:39:17 PDT 2013
On Tue, Aug 13, 2013 at 07:04:56PM +0200, sroland at vmware.com wrote:
> From: Roland Scheidegger <sroland at vmware.com>
>
> Also use ordered comparisons for old cmp instructions. Untested.
This patch looks good to me, but I would like to do a piglit run on
radeonsi before you commit. I will try to do this tomorrow.
-Tom
> ---
> src/gallium/drivers/r600/r600_shader.c | 18 ++++---
> .../drivers/radeon/radeon_setup_tgsi_llvm.c | 49 ++++++++++++++++----
> 2 files changed, 48 insertions(+), 19 deletions(-)
>
> diff --git a/src/gallium/drivers/r600/r600_shader.c b/src/gallium/drivers/r600/r600_shader.c
> index 37298cc..fb766c4 100644
> --- a/src/gallium/drivers/r600/r600_shader.c
> +++ b/src/gallium/drivers/r600/r600_shader.c
> @@ -5743,11 +5743,10 @@ static struct r600_shader_tgsi_instruction r600_shader_tgsi_instruction[] = {
> {105, 0, ALU_OP0_NOP, tgsi_unsupported},
> {106, 0, ALU_OP0_NOP, tgsi_unsupported},
> {TGSI_OPCODE_NOP, 0, ALU_OP0_NOP, tgsi_unsupported},
> - /* gap */
> - {108, 0, ALU_OP0_NOP, tgsi_unsupported},
> - {109, 0, ALU_OP0_NOP, tgsi_unsupported},
> - {110, 0, ALU_OP0_NOP, tgsi_unsupported},
> - {111, 0, ALU_OP0_NOP, tgsi_unsupported},
> + {TGSI_OPCODE_FSEQ, 0, ALU_OP2_SETE_DX10, tgsi_op2},
> + {TGSI_OPCODE_FSGE, 0, ALU_OP2_SETGE_DX10, tgsi_op2},
> + {TGSI_OPCODE_FSLT, 0, ALU_OP2_SETGT_DX10, tgsi_op2_swap},
> + {TGSI_OPCODE_FSNE, 0, ALU_OP2_SETNE_DX10, tgsi_op2_swap},
> {TGSI_OPCODE_NRM4, 0, ALU_OP0_NOP, tgsi_unsupported},
> {TGSI_OPCODE_CALLNZ, 0, ALU_OP0_NOP, tgsi_unsupported},
> /* gap */
> @@ -5936,11 +5935,10 @@ static struct r600_shader_tgsi_instruction eg_shader_tgsi_instruction[] = {
> {105, 0, ALU_OP0_NOP, tgsi_unsupported},
> {106, 0, ALU_OP0_NOP, tgsi_unsupported},
> {TGSI_OPCODE_NOP, 0, ALU_OP0_NOP, tgsi_unsupported},
> - /* gap */
> - {108, 0, ALU_OP0_NOP, tgsi_unsupported},
> - {109, 0, ALU_OP0_NOP, tgsi_unsupported},
> - {110, 0, ALU_OP0_NOP, tgsi_unsupported},
> - {111, 0, ALU_OP0_NOP, tgsi_unsupported},
> + {TGSI_OPCODE_FSEQ, 0, ALU_OP2_SETE_DX10, tgsi_op2},
> + {TGSI_OPCODE_FSGE, 0, ALU_OP2_SETGE_DX10, tgsi_op2},
> + {TGSI_OPCODE_FSLT, 0, ALU_OP2_SETGT_DX10, tgsi_op2_swap},
> + {TGSI_OPCODE_FSNE, 0, ALU_OP2_SETNE_DX10, tgsi_op2_swap},
> {TGSI_OPCODE_NRM4, 0, ALU_OP0_NOP, tgsi_unsupported},
> {TGSI_OPCODE_CALLNZ, 0, ALU_OP0_NOP, tgsi_unsupported},
> /* gap */
> diff --git a/src/gallium/drivers/radeon/radeon_setup_tgsi_llvm.c b/src/gallium/drivers/radeon/radeon_setup_tgsi_llvm.c
> index 7a47746..8ff9abd 100644
> --- a/src/gallium/drivers/radeon/radeon_setup_tgsi_llvm.c
> +++ b/src/gallium/drivers/radeon/radeon_setup_tgsi_llvm.c
> @@ -850,18 +850,16 @@ static void emit_cmp(
> LLVMRealPredicate pred;
> LLVMValueRef cond;
>
> - /* XXX I'm not sure whether to do unordered or ordered comparisons,
> - * but llvmpipe uses unordered comparisons, so for consistency we use
> - * unordered. (The authors of llvmpipe aren't sure about using
> - * unordered vs ordered comparisons either.
> + /* Use ordered for everything but NE (which is usual for
> + * float comparisons)
> */
> switch (emit_data->inst->Instruction.Opcode) {
> - case TGSI_OPCODE_SGE: pred = LLVMRealUGE; break;
> - case TGSI_OPCODE_SEQ: pred = LLVMRealUEQ; break;
> - case TGSI_OPCODE_SLE: pred = LLVMRealULE; break;
> - case TGSI_OPCODE_SLT: pred = LLVMRealULT; break;
> + case TGSI_OPCODE_SGE: pred = LLVMRealOGE; break;
> + case TGSI_OPCODE_SEQ: pred = LLVMRealOEQ; break;
> + case TGSI_OPCODE_SLE: pred = LLVMRealOLE; break;
> + case TGSI_OPCODE_SLT: pred = LLVMRealOLT; break;
> case TGSI_OPCODE_SNE: pred = LLVMRealUNE; break;
> - case TGSI_OPCODE_SGT: pred = LLVMRealUGT; break;
> + case TGSI_OPCODE_SGT: pred = LLVMRealOGT; break;
> default: assert(!"unknown instruction"); pred = 0; break;
> }
>
> @@ -872,6 +870,35 @@ static void emit_cmp(
> cond, bld_base->base.one, bld_base->base.zero, "");
> }
>
> +static void emit_fcmp(
> + const struct lp_build_tgsi_action *action,
> + struct lp_build_tgsi_context * bld_base,
> + struct lp_build_emit_data * emit_data)
> +{
> + LLVMBuilderRef builder = bld_base->base.gallivm->builder;
> + LLVMContextRef context = bld_base->base.gallivm->context;
> + LLVMRealPredicate pred;
> +
> + /* Use ordered for everything but NE (which is usual for
> + * float comparisons)
> + */
> + switch (emit_data->inst->Instruction.Opcode) {
> + case TGSI_OPCODE_FSEQ: pred = LLVMRealOEQ; break;
> + case TGSI_OPCODE_FSGE: pred = LLVMRealOGE; break;
> + case TGSI_OPCODE_FSLT: pred = LLVMRealOLT; break;
> + case TGSI_OPCODE_FSNE: pred = LLVMRealUNE; break;
> + default: assert(!"unknown instruction"); pred = 0; break;
> + }
> +
> + LLVMValueRef v = LLVMBuildFCmp(builder, pred,
> + emit_data->args[0], emit_data->args[1],"");
> +
> + v = LLVMBuildSExtOrBitCast(builder, v,
> + LLVMInt32TypeInContext(context), "");
> +
> + emit_data->output[emit_data->chan] = v;
> +}
> +
> static void emit_not(
> const struct lp_build_tgsi_action * action,
> struct lp_build_tgsi_context * bld_base,
> @@ -1236,6 +1263,10 @@ void radeon_llvm_context_init(struct radeon_llvm_context * ctx)
> bld_base->op_actions[TGSI_OPCODE_FRC].intr_name = "llvm.AMDIL.fraction.";
> bld_base->op_actions[TGSI_OPCODE_F2I].emit = emit_f2i;
> bld_base->op_actions[TGSI_OPCODE_F2U].emit = emit_f2u;
> + bld_base->op_actions[TGSI_OPCODE_FSEQ].emit = emit_fcmp;
> + bld_base->op_actions[TGSI_OPCODE_FSGE].emit = emit_fcmp;
> + bld_base->op_actions[TGSI_OPCODE_FSLT].emit = emit_fcmp;
> + bld_base->op_actions[TGSI_OPCODE_FSNE].emit = emit_fcmp;
> bld_base->op_actions[TGSI_OPCODE_IABS].emit = build_tgsi_intrinsic_nomem;
> bld_base->op_actions[TGSI_OPCODE_IABS].intr_name = "llvm.AMDIL.abs.";
> bld_base->op_actions[TGSI_OPCODE_IDIV].emit = emit_idiv;
> --
> 1.7.9.5
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
More information about the mesa-dev
mailing list