Am 08.10.2013 21:22, schrieb Zack Rusin: > Both the imul_hi and umul_hi are working with this patch. > > Signed-off-by: Zack Rusin <za...@vmware.com> > --- > src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c | 60 > ++++++++++++++++++++++ > 1 file changed, 60 insertions(+) > > diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c > b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c > index 1cfaf78..8caaf83 100644 > --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c > +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c > @@ -763,6 +763,64 @@ umul_emit( > emit_data->args[0], emit_data->args[1]); > } > > +/* TGSI_OPCODE_IMUL_HI */ > +static void > +imul_hi_emit( > + 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; > + struct lp_build_context *int_bld = &bld_base->int_bld; > + struct lp_type type = int_bld->type; > + LLVMValueRef src0, src1; > + LLVMValueRef dst64; > + LLVMTypeRef typeRef; > + > + assert(type.width == 32); > + type.width = 64; > + typeRef = lp_build_vec_type(bld_base->base.gallivm, type); > + src0 = LLVMBuildSExt(builder, emit_data->args[0], typeRef, ""); > + src1 = LLVMBuildSExt(builder, emit_data->args[1], typeRef, ""); > + dst64 = LLVMBuildMul(builder, src0, src1, ""); > + dst64 = LLVMBuildAShr( > + builder, dst64, > + lp_build_const_vec(bld_base->base.gallivm, type, 32), ""); > + type.width = 32; > + typeRef = lp_build_vec_type(bld_base->base.gallivm, type); > + emit_data->output[emit_data->chan] = > + LLVMBuildTrunc(builder, dst64, typeRef, ""); > +} > + > +/* TGSI_OPCODE_UMUL_HI */ > +static void > +umul_hi_emit( > + 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; > + struct lp_build_context *uint_bld = &bld_base->uint_bld; > + struct lp_type type = uint_bld->type; > + LLVMValueRef src0, src1; > + LLVMValueRef dst64; > + LLVMTypeRef typeRef; > + > + assert(type.width == 32); > + type.width = 64; > + typeRef = lp_build_vec_type(bld_base->base.gallivm, type); > + src0 = LLVMBuildZExt(builder, emit_data->args[0], typeRef, ""); > + src1 = LLVMBuildZExt(builder, emit_data->args[1], typeRef, ""); > + dst64 = LLVMBuildMul(builder, src0, src1, ""); > + dst64 = LLVMBuildLShr( > + builder, dst64, > + lp_build_const_vec(bld_base->base.gallivm, type, 32), ""); > + type.width = 32; > + typeRef = lp_build_vec_type(bld_base->base.gallivm, type); > + emit_data->output[emit_data->chan] = > + LLVMBuildTrunc(builder, dst64, typeRef, ""); > +} > + > /* TGSI_OPCODE_MAX */ > static void fmax_emit( > const struct lp_build_tgsi_action * action, > @@ -894,6 +952,8 @@ lp_set_default_actions(struct lp_build_tgsi_context * > bld_base) > bld_base->op_actions[TGSI_OPCODE_U2F].emit = u2f_emit; > bld_base->op_actions[TGSI_OPCODE_UMAD].emit = umad_emit; > bld_base->op_actions[TGSI_OPCODE_UMUL].emit = umul_emit; > + bld_base->op_actions[TGSI_OPCODE_IMUL_HI].emit = imul_hi_emit; > + bld_base->op_actions[TGSI_OPCODE_UMUL_HI].emit = umul_hi_emit; > > bld_base->op_actions[TGSI_OPCODE_MAX].emit = fmax_emit; > bld_base->op_actions[TGSI_OPCODE_MIN].emit = fmin_emit; >
Series looks good to me. (Though I'm wondering if llvm generates the "right" code, what it should do is just use the pmuludq/pmuldq opcodes (though the latter requires sse41) together with some shuffles, and I sort of fear it will do something crazy instead like scalar extraction but as long as it isn't really performance critical we don't need to optimize that manually in any case.) Roland _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev