[Mesa-dev] [PATCH 06/11] i965/fs: Refactor code generation for nir_op_fsign to its own function
Ian Romanick
idr at freedesktop.org
Mon Sep 10 23:29:09 UTC 2018
From: Ian Romanick <ian.d.romanick at intel.com>
Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>
---
src/intel/compiler/brw_fs.h | 1 +
src/intel/compiler/brw_fs_nir.cpp | 154 +++++++++++++++++++++++++-------------
2 files changed, 103 insertions(+), 52 deletions(-)
diff --git a/src/intel/compiler/brw_fs.h b/src/intel/compiler/brw_fs.h
index aba19d5ab2c..c45f0f608fc 100644
--- a/src/intel/compiler/brw_fs.h
+++ b/src/intel/compiler/brw_fs.h
@@ -186,6 +186,7 @@ public:
void emit_gen6_gather_wa(uint8_t wa, fs_reg dst);
fs_reg resolve_source_modifiers(const fs_reg &src);
void emit_discard_jump();
+ void emit_fsign(const class brw::fs_builder &, const nir_alu_instr *instr);
bool opt_peephole_sel();
bool opt_peephole_csel();
bool opt_peephole_predicated_break();
diff --git a/src/intel/compiler/brw_fs_nir.cpp b/src/intel/compiler/brw_fs_nir.cpp
index 12b087a5ec0..d0f25e96c3e 100644
--- a/src/intel/compiler/brw_fs_nir.cpp
+++ b/src/intel/compiler/brw_fs_nir.cpp
@@ -669,9 +669,109 @@ brw_rnd_mode_from_nir_op (const nir_op op) {
}
}
+/**
+ * Emit code for nir_op_fsign
+ */
+void
+fs_visitor::emit_fsign(const fs_builder &bld, const nir_alu_instr *instr)
+{
+ fs_inst *inst;
+
+ assert(instr->op == nir_op_fsign);
+
+ fs_reg result = get_nir_dest(instr->dest.dest);
+ result.type = brw_type_for_nir_type(devinfo,
+ (nir_alu_type)(nir_op_infos[instr->op].output_type |
+ nir_dest_bit_size(instr->dest.dest)));
+
+ const nir_alu_src *sources[2] = { &instr->src[0], NULL };
+ const unsigned num_sources = 1;
+ fs_reg op[2];
+
+ for (unsigned i = 0; i < num_sources; i++) {
+ op[i] = get_nir_src(sources[i]->src);
+
+ const nir_alu_type t =
+ (nir_alu_type)(nir_op_infos[instr->op].input_types[i] |
+ nir_src_bit_size(sources[i]->src));
+
+ op[i].type = brw_type_for_nir_type(devinfo, t);
+ op[i].abs = sources[i]->abs;
+ op[i].negate = sources[i]->negate;
+ }
+
+ unsigned channel = 0;
+ if (nir_op_infos[instr->op].output_size == 0) {
+ /* Since NIR is doing the scalarizing for us, we should only ever see
+ * vectorized operations with a single channel.
+ */
+ assert(util_bitcount(instr->dest.write_mask) == 1);
+ channel = ffs(instr->dest.write_mask) - 1;
+
+ result = offset(result, bld, channel);
+ }
+
+ for (unsigned i = 0; i < num_sources; i++)
+ op[i] = offset(op[i], bld, sources[i]->swizzle[channel]);
+
+ assert(!instr->dest.saturate);
+ if (op[0].abs) {
+ /* Straightforward since the source can be assumed to be either strictly
+ * >= 0 or strictly <= 0 depending on the setting of the negate flag.
+ */
+ set_condmod(BRW_CONDITIONAL_NZ, bld.MOV(result, op[0]));
+
+ inst = (op[0].negate)
+ ? bld.MOV(result, brw_imm_f(-1.0f))
+ : bld.MOV(result, brw_imm_f(1.0f));
+
+ set_predicate(BRW_PREDICATE_NORMAL, inst);
+ } else if (type_sz(op[0].type) < 8) {
+ /* AND(val, 0x80000000) gives the sign bit.
+ *
+ * Predicated OR ORs 1.0 (0x3f800000) with the sign bit if val is not
+ * zero.
+ */
+ bld.CMP(bld.null_reg_f(), op[0], brw_imm_f(0.0f), BRW_CONDITIONAL_NZ);
+
+ fs_reg result_int = retype(result, BRW_REGISTER_TYPE_UD);
+ op[0].type = BRW_REGISTER_TYPE_UD;
+ result.type = BRW_REGISTER_TYPE_UD;
+ bld.AND(result_int, op[0], brw_imm_ud(0x80000000u));
+
+ inst = bld.OR(result_int, result_int, brw_imm_ud(0x3f800000u));
+ inst->predicate = BRW_PREDICATE_NORMAL;
+ } else {
+ /* For doubles we do the same but we need to consider:
+ *
+ * - 2-src instructions can't operate with 64-bit immediates
+ * - The sign is encoded in the high 32-bit of each DF
+ * - We need to produce a DF result.
+ */
+
+ fs_reg zero = vgrf(glsl_type::double_type);
+ bld.MOV(zero, setup_imm_df(bld, 0.0));
+ bld.CMP(bld.null_reg_df(), op[0], zero, BRW_CONDITIONAL_NZ);
+
+ bld.MOV(result, zero);
+
+ fs_reg r = subscript(result, BRW_REGISTER_TYPE_UD, 1);
+ bld.AND(r, subscript(op[0], BRW_REGISTER_TYPE_UD, 1),
+ brw_imm_ud(0x80000000u));
+
+ set_predicate(BRW_PREDICATE_NORMAL,
+ bld.OR(r, r, brw_imm_ud(0x3ff00000u)));
+ }
+}
+
void
fs_visitor::nir_emit_alu(const fs_builder &bld, nir_alu_instr *instr)
{
+ if (instr->op == nir_op_fsign) {
+ emit_fsign(bld, instr);
+ return;
+ }
+
struct brw_wm_prog_key *fs_key = (struct brw_wm_prog_key *) this->key;
fs_inst *inst;
@@ -841,58 +941,8 @@ fs_visitor::nir_emit_alu(const fs_builder &bld, nir_alu_instr *instr)
inst->saturate = instr->dest.saturate;
break;
- case nir_op_fsign: {
- assert(!instr->dest.saturate);
- if (op[0].abs) {
- /* Straightforward since the source can be assumed to be either
- * strictly >= 0 or strictly <= 0 depending on the setting of the
- * negate flag.
- */
- set_condmod(BRW_CONDITIONAL_NZ, bld.MOV(result, op[0]));
-
- inst = (op[0].negate)
- ? bld.MOV(result, brw_imm_f(-1.0f))
- : bld.MOV(result, brw_imm_f(1.0f));
-
- set_predicate(BRW_PREDICATE_NORMAL, inst);
- } else if (type_sz(op[0].type) < 8) {
- /* AND(val, 0x80000000) gives the sign bit.
- *
- * Predicated OR ORs 1.0 (0x3f800000) with the sign bit if val is not
- * zero.
- */
- bld.CMP(bld.null_reg_f(), op[0], brw_imm_f(0.0f), BRW_CONDITIONAL_NZ);
-
- fs_reg result_int = retype(result, BRW_REGISTER_TYPE_UD);
- op[0].type = BRW_REGISTER_TYPE_UD;
- result.type = BRW_REGISTER_TYPE_UD;
- bld.AND(result_int, op[0], brw_imm_ud(0x80000000u));
-
- inst = bld.OR(result_int, result_int, brw_imm_ud(0x3f800000u));
- inst->predicate = BRW_PREDICATE_NORMAL;
- } else {
- /* For doubles we do the same but we need to consider:
- *
- * - 2-src instructions can't operate with 64-bit immediates
- * - The sign is encoded in the high 32-bit of each DF
- * - We need to produce a DF result.
- */
-
- fs_reg zero = vgrf(glsl_type::double_type);
- bld.MOV(zero, setup_imm_df(bld, 0.0));
- bld.CMP(bld.null_reg_df(), op[0], zero, BRW_CONDITIONAL_NZ);
-
- bld.MOV(result, zero);
-
- fs_reg r = subscript(result, BRW_REGISTER_TYPE_UD, 1);
- bld.AND(r, subscript(op[0], BRW_REGISTER_TYPE_UD, 1),
- brw_imm_ud(0x80000000u));
-
- set_predicate(BRW_PREDICATE_NORMAL,
- bld.OR(r, r, brw_imm_ud(0x3ff00000u)));
- }
- break;
- }
+ case nir_op_fsign:
+ unreachable("Opcode already handled.");
case nir_op_isign: {
/* ASR(val, 31) -> negative val generates 0xffffffff (signed -1).
--
2.14.4
More information about the mesa-dev
mailing list