summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIan Romanick <ian.d.romanick@intel.com>2019-02-19 20:11:06 -0800
committerIan Romanick <ian.d.romanick@intel.com>2019-03-26 10:29:22 -0700
commit63e9b863613fc1c03018410122b2f57f45320ab1 (patch)
treee77556d56ca12719683fb2c4ab52b3c761d842b0 /src
parentbd46de24404c851415d12577a7caf18b4e2df40e (diff)
WIP: intel/compiler: Add a code builder that consumes a bytecode
Diffstat (limited to 'src')
-rw-r--r--src/intel/compiler/codegen_builder.cpp203
-rw-r--r--src/intel/compiler/codegen_builder.h222
-rw-r--r--src/intel/compiler/meson.build2
3 files changed, 427 insertions, 0 deletions
diff --git a/src/intel/compiler/codegen_builder.cpp b/src/intel/compiler/codegen_builder.cpp
new file mode 100644
index 000000000000..3f052a17cd86
--- /dev/null
+++ b/src/intel/compiler/codegen_builder.cpp
@@ -0,0 +1,203 @@
+/*
+ * Copyright © 2019 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "codegen_builder.h"
+
+void
+emit_instructions_from_bytecode(const brw::fs_builder &bld,
+ const struct bytecode_instruction *bi,
+ const fs_reg &result,
+ const fs_reg *inputs,
+ const union immediate_value *imm,
+ bool implicit_saturate)
+{
+ fs_reg operands[16];
+ unsigned num_operands = 0;
+ fs_reg temporaries[16];
+ unsigned num_temps = 0;
+ fs_inst *inst = NULL;
+
+ while (bi->op != end_of_stream) {
+ switch (bi->op) {
+ case append_output:
+ assert(num_operands < ARRAY_SIZE(operands));
+ operands[num_operands++] = result;
+ break;
+
+ case append_input:
+ assert(num_operands < ARRAY_SIZE(operands));
+ operands[num_operands++] = inputs[bi->index];
+ break;
+
+ case append_constant:
+ assert(num_operands < ARRAY_SIZE(operands));
+
+ switch (bi->reg_type) {
+ case BRW_REGISTER_TYPE_DF:
+ operands[num_operands++] = brw_imm_df(imm[bi->index].df);
+ break;
+ case BRW_REGISTER_TYPE_F:
+ operands[num_operands++] = brw_imm_f(imm[bi->index].f);
+ break;
+
+ case BRW_REGISTER_TYPE_Q:
+ operands[num_operands++] = brw_imm_q(imm[bi->index].q);
+ break;
+ case BRW_REGISTER_TYPE_UQ:
+ operands[num_operands++] = brw_imm_uq(imm[bi->index].uq);
+ break;
+ case BRW_REGISTER_TYPE_D:
+ operands[num_operands++] = brw_imm_d(imm[bi->index].d);
+ break;
+ case BRW_REGISTER_TYPE_UD:
+ operands[num_operands++] = brw_imm_ud(imm[bi->index].ud);
+ break;
+ case BRW_REGISTER_TYPE_W:
+ operands[num_operands++] = brw_imm_w(imm[bi->index].w);
+ break;
+ case BRW_REGISTER_TYPE_UW:
+ operands[num_operands++] = brw_imm_uw(imm[bi->index].uw);
+ break;
+
+ case BRW_REGISTER_TYPE_NF:
+ case BRW_REGISTER_TYPE_HF:
+ case BRW_REGISTER_TYPE_VF:
+ case BRW_REGISTER_TYPE_B:
+ case BRW_REGISTER_TYPE_UB:
+ case BRW_REGISTER_TYPE_V:
+ case BRW_REGISTER_TYPE_UV:
+ unreachable("Unsupported type");
+ };
+ break;
+
+ case append_temporary:
+ assert(num_operands < ARRAY_SIZE(operands));
+ assert(bi->index < num_temps);
+ operands[num_operands++] = temporaries[bi->index];
+ break;
+
+ case append_null_reg:
+ assert(num_operands < ARRAY_SIZE(operands));
+ operands[num_operands++] = retype(bld.null_reg_ud(),
+ bi->reg_type);
+ break;
+
+ case append_vec1_grf:
+ assert(num_operands < ARRAY_SIZE(operands));
+ operands[num_operands++] = brw_vec1_grf(bi->index, bi->blob);
+ break;
+
+ case append_vec2_grf:
+ assert(num_operands < ARRAY_SIZE(operands));
+ operands[num_operands++] = brw_vec2_grf(bi->index, bi->blob);
+ break;
+
+ case append_vec4_grf:
+ assert(num_operands < ARRAY_SIZE(operands));
+ operands[num_operands++] = brw_vec4_grf(bi->index, bi->blob);
+ break;
+
+ case append_vec8_grf:
+ assert(num_operands < ARRAY_SIZE(operands));
+ operands[num_operands++] = brw_vec8_grf(bi->index, bi->blob);
+ break;
+
+ case append_vec16_grf:
+ assert(num_operands < ARRAY_SIZE(operands));
+ operands[num_operands++] = brw_vec16_grf(bi->index, bi->blob);
+ break;
+
+ case declare_temporary:
+ assert(num_temps < ARRAY_SIZE(temporaries));
+
+ if (bi->reg_type == BRW_REGISTER_TYPE_VF)
+ temporaries[num_temps++] = bld.vgrf(result.type, 1);
+ else
+ temporaries[num_temps++] = bld.vgrf(bi->reg_type, 1);
+ break;
+
+ case neg_operand:
+ assert(num_operands > 0);
+ operands[num_operands - 1].negate = !operands[num_operands - 1].negate;
+ break;
+
+ case abs_operand:
+ assert(num_operands > 0);
+ operands[num_operands - 1].negate = false;
+ operands[num_operands - 1].abs = true;
+ break;
+
+ case retype_operand:
+ assert(num_operands > 0);
+ operands[num_operands - 1] = retype(operands[num_operands - 1],
+ bi->reg_type);
+ break;
+
+ case subscript_operand:
+ assert(num_operands > 0);
+ operands[num_operands - 1] = subscript(operands[num_operands - 1],
+ bi->reg_type,
+ bi->index);
+ break;
+
+ case emit_instruction:
+ if (num_operands == 0) {
+ inst = bld.emit(bi->gen_opcode);
+ } else {
+ inst = bld.emit(bi->gen_opcode,
+ operands[0],
+ &operands[1],
+ num_operands - 1);
+ num_operands = 0;
+ }
+
+ break;
+
+ case saturate_instruction:
+ assert(inst != NULL);
+ inst->saturate = true;
+ break;
+
+ case conditional_mod:
+ assert(inst != NULL);
+ inst->conditional_mod = bi->cmod;
+ break;
+
+ case predicate_instruction:
+ assert(inst != NULL);
+ inst->predicate = bi->pred;
+ break;
+
+ case end_of_stream:
+ unreachable("Should have already exited loop.");
+ }
+
+ bi++;
+ }
+
+ if (implicit_saturate)
+ inst->saturate = true;
+
+ /* There should be no operands hanging around. */
+ assert(num_operands == 0);
+}
diff --git a/src/intel/compiler/codegen_builder.h b/src/intel/compiler/codegen_builder.h
new file mode 100644
index 000000000000..b7cf5f504b0c
--- /dev/null
+++ b/src/intel/compiler/codegen_builder.h
@@ -0,0 +1,222 @@
+/* -*- c++ -*- */
+/*
+ * Copyright © 2019 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef CODEGEN_BUILDER_H
+#define CODEGEN_BUILDER_H
+
+#include "brw_fs.h"
+
+enum PACKED operation {
+ append_output,
+
+ /**
+ * Appends a new operand from the input in the operand list.
+ *
+ * The input to be appended is selected by \c ::index.
+ */
+ append_input,
+
+ /**
+ * Appends a new operand from a constant in the imm list.
+ *
+ * The constant to be appended is selected by \c ::index, and its type is
+ * specified in \c ::reg_type.
+ */
+ append_constant,
+
+ /**
+ * Appends a new operand from a temporary in the operand list.
+ *
+ * The temporary to be appended is selected by \c ::index.
+ */
+ append_temporary,
+
+ /**
+ * Appends a new null register in the operand list.
+ *
+ * The type of the null register is specified in \c ::reg_type.
+ */
+ append_null_reg,
+
+ append_vec1_grf,
+ append_vec2_grf,
+ append_vec4_grf,
+ append_vec8_grf,
+ append_vec16_grf,
+
+ /**
+ * Allocate a register for the next temporary slot
+ *
+ * The type of the temporary is specified in \c ::reg_type. Registers
+ * cannot have type \c BRW_REGISTER_TYPE_VF, \c BRW_REGISTER_TYPE_V, or
+ * \c BRW_REGISTER_TYPE_VU. If the type \c BRW_REGISTER_TYPE_VF is used to
+ * declare a temporary, it has the special meaning to copy the result type.
+ */
+ declare_temporary,
+
+ /**
+ * Toggles the negate flag of the last added operand.
+ */
+ neg_operand,
+
+ /**
+ * Sets the absolute value flag of the last added operand.
+ *
+ * Also clears the negate flag.
+ */
+ abs_operand,
+
+ /**
+ * Changes the type of the last added operand.
+ *
+ * The new type of the operand is specified in \c ::reg_type.
+ */
+ retype_operand,
+
+ subscript_operand,
+
+ /**
+ * Emit an instruction
+ *
+ * The opcode of the instruction is specified in \c ::gen_opcode. All
+ * operands are consumed by the new instruction.
+ */
+ emit_instruction,
+
+ /**
+ * Sets the saturate flag for the most recently emitted instruction.
+ */
+ saturate_instruction,
+
+ /**
+ * Sets the conditional modifier for the most recently emitted instruction.
+ */
+ conditional_mod,
+
+ predicate_instruction,
+
+ /**
+ * Denotes the end of the byte code stream.
+ */
+ end_of_stream
+};
+
+struct bytecode_instruction {
+ enum operation op;
+
+ union {
+ enum PACKED opcode gen_opcode;
+ enum brw_reg_type reg_type;
+ enum brw_conditional_mod cmod;
+ enum brw_predicate pred;
+ uint8_t blob;
+ };
+
+ uint16_t index;
+
+ bytecode_instruction(enum operation _op, enum opcode _gen_opcode)
+ : op(_op), gen_opcode(_gen_opcode), index(0)
+ {
+ assert(op == emit_instruction);
+ }
+
+ bytecode_instruction(enum operation _op, enum brw_reg_type _reg_type)
+ : op(_op), reg_type(_reg_type), index(0)
+ {
+ assert(op == retype_operand ||
+ op == declare_temporary ||
+ op == append_null_reg);
+ }
+
+ bytecode_instruction(enum operation _op, enum brw_reg_type _reg_type,
+ uint16_t _index)
+ : op(_op), reg_type(_reg_type), index(_index)
+ {
+ assert(op == subscript_operand ||
+ op == append_constant);
+ }
+
+ bytecode_instruction(enum operation _op, enum brw_predicate _pred)
+ : op(_op), pred(_pred), index(0)
+ {
+ assert(op == predicate_instruction);
+ }
+
+ bytecode_instruction(enum operation _op, enum brw_conditional_mod _cmod)
+ : op(_op), cmod(_cmod), index(0)
+ {
+ assert(op == conditional_mod);
+ }
+
+ bytecode_instruction(enum operation _op, uint16_t _index)
+ : op(_op), blob(0), index(_index)
+ {
+ assert(op == append_input ||
+ op == append_temporary);
+ }
+
+ bytecode_instruction(enum operation _op, uint8_t subnr, uint16_t nr)
+ : op(_op), blob(subnr), index(nr)
+ {
+ assert(op == append_vec1_grf ||
+ op == append_vec2_grf ||
+ op == append_vec4_grf ||
+ op == append_vec8_grf ||
+ op == append_vec16_grf);
+ }
+
+ bytecode_instruction(enum operation _op)
+ : op(_op), blob(0), index(0)
+ {
+ assert(op == abs_operand ||
+ op == neg_operand ||
+ op == saturate_instruction ||
+ op == append_output ||
+ op == end_of_stream);
+ }
+};
+
+union immediate_value {
+ uint64_t uq;
+ int64_t q;
+ double df;
+ float f;
+ int d;
+ unsigned ud;
+ int16_t w;
+ uint16_t uw;
+ int8_t b;
+ uint8_t ub;
+};
+
+//STATIC_ASSERT(sizeof(struct bytecode_instruction) <= 4);
+
+void emit_instructions_from_bytecode(const brw::fs_builder &bld,
+ const struct bytecode_instruction *bi,
+ const fs_reg &result,
+ const fs_reg *inputs,
+ const union immediate_value *imm,
+ bool implicit_saturate);
+
+#endif /* CODEGEN_BUILDER_H */
diff --git a/src/intel/compiler/meson.build b/src/intel/compiler/meson.build
index 21614c5baf99..d0bec0fccf28 100644
--- a/src/intel/compiler/meson.build
+++ b/src/intel/compiler/meson.build
@@ -19,6 +19,8 @@
# SOFTWARE.
libintel_compiler_files = files(
+ 'codegen_builder.cpp',
+ 'codegen_builder.h',
'brw_cfg.cpp',
'brw_cfg.h',
'brw_clip.h',