#include "brw_cfg.h"
#include "brw_nir.h"
#include "brw_vec4_builder.h"
-#include "brw_vec4_live_variables.h"
#include "brw_vec4_vs.h"
#include "brw_dead_control_flow.h"
-#include "common/gen_debug.h"
+#include "dev/gen_debug.h"
#include "program/prog_parameter.h"
+#include "util/u_math.h"
#define MAX_INSTRUCTION (1 << 30)
void
src_reg::init()
{
- memset(this, 0, sizeof(*this));
+ memset((void*)this, 0, sizeof(*this));
this->file = BAD_FILE;
this->type = BRW_REGISTER_TYPE_UD;
}
void
dst_reg::init()
{
- memset(this, 0, sizeof(*this));
+ memset((void*)this, 0, sizeof(*this));
this->file = BAD_FILE;
this->type = BRW_REGISTER_TYPE_UD;
this->writemask = WRITEMASK_XYZW;
}
bool
-vec4_instruction::is_send_from_grf()
+vec4_instruction::is_send_from_grf() const
{
switch (opcode) {
case SHADER_OPCODE_SHADER_TIME_ADD:
case VS_OPCODE_PULL_CONSTANT_LOAD_GEN7:
- case SHADER_OPCODE_UNTYPED_ATOMIC:
- case SHADER_OPCODE_UNTYPED_SURFACE_READ:
- case SHADER_OPCODE_UNTYPED_SURFACE_WRITE:
- case SHADER_OPCODE_TYPED_ATOMIC:
- case SHADER_OPCODE_TYPED_SURFACE_READ:
- case SHADER_OPCODE_TYPED_SURFACE_WRITE:
+ case VEC4_OPCODE_UNTYPED_ATOMIC:
+ case VEC4_OPCODE_UNTYPED_SURFACE_READ:
+ case VEC4_OPCODE_UNTYPED_SURFACE_WRITE:
case VEC4_OPCODE_URB_READ:
case TCS_OPCODE_URB_WRITE:
case TCS_OPCODE_RELEASE_INPUT:
{
switch (opcode) {
case SHADER_OPCODE_SHADER_TIME_ADD:
- case SHADER_OPCODE_UNTYPED_ATOMIC:
- case SHADER_OPCODE_UNTYPED_SURFACE_READ:
- case SHADER_OPCODE_UNTYPED_SURFACE_WRITE:
- case SHADER_OPCODE_TYPED_ATOMIC:
- case SHADER_OPCODE_TYPED_SURFACE_READ:
- case SHADER_OPCODE_TYPED_SURFACE_WRITE:
+ case VEC4_OPCODE_UNTYPED_ATOMIC:
+ case VEC4_OPCODE_UNTYPED_SURFACE_READ:
+ case VEC4_OPCODE_UNTYPED_SURFACE_WRITE:
case TCS_OPCODE_URB_WRITE:
if (arg == 0)
return mlen * REG_SIZE;
return true;
}
+bool
+vec4_instruction::can_do_cmod()
+{
+ if (!backend_instruction::can_do_cmod())
+ return false;
+
+ /* The accumulator result appears to get used for the conditional modifier
+ * generation. When negating a UD value, there is a 33rd bit generated for
+ * the sign in the accumulator value, so now you can't check, for example,
+ * equality with a 32-bit value. See piglit fs-op-neg-uvec4.
+ */
+ for (unsigned i = 0; i < 3; i++) {
+ if (src[i].file != BAD_FILE &&
+ type_is_unsigned_int(src[i].type) && src[i].negate)
+ return false;
+ }
+
+ return true;
+}
+
bool
vec4_instruction::can_do_writemask(const struct gen_device_info *devinfo)
{
* instruction -- the generate_* functions generate additional MOVs
* for setup.
*/
-int
-vec4_visitor::implied_mrf_writes(vec4_instruction *inst)
+unsigned
+vec4_instruction::implied_mrf_writes() const
{
- if (inst->mlen == 0 || inst->is_send_from_grf())
+ if (mlen == 0 || is_send_from_grf())
return 0;
- switch (inst->opcode) {
+ switch (opcode) {
case SHADER_OPCODE_RCP:
case SHADER_OPCODE_RSQ:
case SHADER_OPCODE_SQRT:
case SHADER_OPCODE_TG4_OFFSET:
case SHADER_OPCODE_SAMPLEINFO:
case SHADER_OPCODE_GET_BUFFER_SIZE:
- return inst->header_size;
+ return header_size;
default:
unreachable("not reached");
}
bool progress = false;
foreach_block(block, cfg) {
- int last_reg = -1, last_offset = -1;
+ unsigned last_reg = ~0u, last_offset = ~0u;
enum brw_reg_file last_reg_file = BAD_FILE;
uint8_t imm[4] = { 0 };
foreach_inst_in_block_safe(vec4_instruction, inst, block) {
int vf = -1;
- enum brw_reg_type need_type;
+ enum brw_reg_type need_type = BRW_REGISTER_TYPE_LAST;
/* Look for unconditional MOVs from an immediate with a partial
* writemask. Skip type-conversion MOVs other than integer 0,
need_type = BRW_REGISTER_TYPE_F;
}
} else {
- last_reg = -1;
+ last_reg = ~0u;
}
/* If this wasn't a MOV, or the destination register doesn't match,
}
inst_count = 0;
- last_reg = -1;
+ last_reg = ~0u;;
writemask = 0;
dest_type = BRW_REGISTER_TYPE_F;
}
if (progress)
- invalidate_live_intervals();
+ invalidate_analysis(DEPENDENCY_INSTRUCTIONS);
return progress;
}
}
if (progress)
- invalidate_live_intervals();
+ invalidate_analysis(DEPENDENCY_INSTRUCTION_DETAIL);
return progress;
}
void
vec4_visitor::pack_uniform_registers()
{
+ if (!compiler->compact_params)
+ return;
+
uint8_t chans_used[this->uniforms];
int new_loc[this->uniforms];
int new_chan[this->uniforms];
break;
if (inst->saturate) {
- if (inst->dst.type != inst->src[0].type)
+ /* Full mixed-type saturates don't happen. However, we can end up
+ * with things like:
+ *
+ * mov.sat(8) g21<1>DF -1F
+ *
+ * Other mixed-size-but-same-base-type cases may also be possible.
+ */
+ if (inst->dst.type != inst->src[0].type &&
+ inst->dst.type != BRW_REGISTER_TYPE_DF &&
+ inst->src[0].type != BRW_REGISTER_TYPE_F)
assert(!"unimplemented: saturate mixed types");
- if (brw_saturate_immediate(inst->dst.type,
+ if (brw_saturate_immediate(inst->src[0].type,
&inst->src[0].as_brw_reg())) {
inst->saturate = false;
progress = true;
progress = true;
}
break;
- case BRW_OPCODE_CMP:
- if (inst->conditional_mod == BRW_CONDITIONAL_GE &&
- inst->src[0].abs &&
- inst->src[0].negate &&
- inst->src[1].is_zero()) {
- inst->src[0].abs = false;
- inst->src[0].negate = false;
- inst->conditional_mod = BRW_CONDITIONAL_Z;
- progress = true;
- break;
- }
- break;
case SHADER_OPCODE_BROADCAST:
if (is_uniform(inst->src[0]) ||
inst->src[1].is_zero()) {
}
if (progress)
- invalidate_live_intervals();
+ invalidate_analysis(DEPENDENCY_INSTRUCTION_DATA_FLOW |
+ DEPENDENCY_INSTRUCTION_DETAIL);
return progress;
}
if (devinfo->gen == 6 && is_math() && swizzle != BRW_SWIZZLE_XYZW)
return false;
+ /* If we write to the flag register changing the swizzle would change
+ * what channels are written to the flag register.
+ */
+ if (writes_flag())
+ return false;
+
/* We can't swizzle implicit accumulator access. We'd have to
* reswizzle the producer of the accumulator value in addition
* to the consumer (i.e. both MUL and MACH). Just skip this.
opcode != BRW_OPCODE_DP3 && opcode != BRW_OPCODE_DP2 &&
opcode != VEC4_OPCODE_PACK_BYTES) {
for (int i = 0; i < 3; i++) {
- if (src[i].file == BAD_FILE || src[i].file == IMM)
+ if (src[i].file == BAD_FILE)
continue;
+ if (src[i].file == IMM) {
+ assert(src[i].type != BRW_REGISTER_TYPE_V &&
+ src[i].type != BRW_REGISTER_TYPE_UV);
+
+ /* Vector immediate types need to be reswizzled. */
+ if (src[i].type == BRW_REGISTER_TYPE_VF) {
+ const unsigned imm[] = {
+ (src[i].ud >> 0) & 0x0ff,
+ (src[i].ud >> 8) & 0x0ff,
+ (src[i].ud >> 16) & 0x0ff,
+ (src[i].ud >> 24) & 0x0ff,
+ };
+
+ src[i] = brw_imm_vf4(imm[BRW_GET_SWZ(swizzle, 0)],
+ imm[BRW_GET_SWZ(swizzle, 1)],
+ imm[BRW_GET_SWZ(swizzle, 2)],
+ imm[BRW_GET_SWZ(swizzle, 3)]);
+ }
+
+ continue;
+ }
+
src[i].swizzle = brw_compose_swizzle(swizzle, src[i].swizzle);
}
}
{
bool progress = false;
int next_ip = 0;
-
- calculate_live_intervals();
+ const vec4_live_variables &live = live_analysis.require();
foreach_block_and_inst_safe (block, vec4_instruction, inst, cfg) {
int ip = next_ip;
/* Can't coalesce this GRF if someone else was going to
* read it later.
*/
- if (var_range_end(var_from_reg(alloc, dst_reg(inst->src[0])), 8) > ip)
+ if (live.var_range_end(var_from_reg(alloc, dst_reg(inst->src[0])), 8) > ip)
continue;
/* We need to check interference with the final destination between this
* in the register instead.
*/
if (to_mrf && scan_inst->mlen > 0) {
- if (inst->dst.nr >= scan_inst->base_mrf &&
- inst->dst.nr < scan_inst->base_mrf + scan_inst->mlen) {
+ unsigned start = scan_inst->base_mrf;
+ unsigned end = scan_inst->base_mrf + scan_inst->mlen;
+
+ if (inst->dst.nr >= start && inst->dst.nr < end) {
break;
}
} else {
}
if (progress)
- invalidate_live_intervals();
+ invalidate_analysis(DEPENDENCY_INSTRUCTIONS);
return progress;
}
}
}
+ if (progress)
+ invalidate_analysis(DEPENDENCY_INSTRUCTION_DETAIL);
+
return progress;
}
}
}
}
- invalidate_live_intervals();
+ invalidate_analysis(DEPENDENCY_INSTRUCTION_DETAIL | DEPENDENCY_VARIABLES);
}
void
-vec4_visitor::dump_instruction(backend_instruction *be_inst)
+vec4_visitor::dump_instruction(const backend_instruction *be_inst) const
{
dump_instruction(be_inst, stderr);
}
void
-vec4_visitor::dump_instruction(backend_instruction *be_inst, FILE *file)
+vec4_visitor::dump_instruction(const backend_instruction *be_inst, FILE *file) const
{
- vec4_instruction *inst = (vec4_instruction *)be_inst;
+ const vec4_instruction *inst = (const vec4_instruction *)be_inst;
if (inst->predicate) {
fprintf(file, "(%cf%d.%d%s) ",
}
if (progress)
- invalidate_live_intervals();
+ invalidate_analysis(DEPENDENCY_INSTRUCTIONS);
return progress;
}
}
if (progress)
- invalidate_live_intervals();
+ invalidate_analysis(DEPENDENCY_INSTRUCTION_DETAIL |
+ DEPENDENCY_VARIABLES);
}
void
}
if (progress)
- invalidate_live_intervals();
+ invalidate_analysis(DEPENDENCY_INSTRUCTIONS | DEPENDENCY_VARIABLES);
return progress;
}
}
if (progress)
- invalidate_live_intervals();
+ invalidate_analysis(DEPENDENCY_INSTRUCTIONS);
return progress;
}
}
if (progress)
- invalidate_live_intervals();
+ invalidate_analysis(DEPENDENCY_INSTRUCTIONS | DEPENDENCY_VARIABLES);
return progress;
}
}
}
+void
+vec4_visitor::invalidate_analysis(brw::analysis_dependency_class c)
+{
+ backend_shader::invalidate_analysis(c);
+ live_analysis.invalidate(c);
+}
+
bool
vec4_visitor::run()
{
void *mem_ctx,
const struct brw_vs_prog_key *key,
struct brw_vs_prog_data *prog_data,
- const nir_shader *src_shader,
+ nir_shader *shader,
int shader_time_index,
+ struct brw_compile_stats *stats,
char **error_str)
{
const bool is_scalar = compiler->scalar_stage[MESA_SHADER_VERTEX];
- nir_shader *shader = nir_shader_clone(mem_ctx, src_shader);
- shader = brw_nir_apply_sampler_key(shader, compiler, &key->tex, is_scalar);
+ brw_nir_apply_key(shader, compiler, &key->base, 8, is_scalar);
const unsigned *assembly = NULL;
brw_nir_lower_vs_inputs(shader, key->gl_attrib_wa_flags);
brw_nir_lower_vue_outputs(shader);
- shader = brw_postprocess_nir(shader, compiler, is_scalar);
+ brw_postprocess_nir(shader, compiler, is_scalar);
prog_data->base.clip_distance_mask =
((1 << shader->info.clip_distance_array_size) - 1);
((1 << shader->info.cull_distance_array_size) - 1) <<
shader->info.clip_distance_array_size;
- unsigned nr_attribute_slots = _mesa_bitcount_64(prog_data->inputs_read);
+ unsigned nr_attribute_slots = util_bitcount64(prog_data->inputs_read);
/* gl_VertexID and gl_InstanceID are system values, but arrive via an
* incoming vertex attribute. So, add an extra slot.
if (is_scalar) {
prog_data->base.dispatch_mode = DISPATCH_MODE_SIMD8;
- fs_visitor v(compiler, log_data, mem_ctx, key, &prog_data->base.base,
- NULL, /* prog; Only used for TEXTURE_RECTANGLE on gen < 8 */
+ fs_visitor v(compiler, log_data, mem_ctx, &key->base,
+ &prog_data->base.base,
shader, 8, shader_time_index);
if (!v.run_vs()) {
if (error_str)
prog_data->base.base.dispatch_grf_start_reg = v.payload.num_regs;
fs_generator g(compiler, log_data, mem_ctx,
- &prog_data->base.base, v.promoted_constants,
- v.runtime_check_aads_emit, MESA_SHADER_VERTEX);
+ &prog_data->base.base, v.runtime_check_aads_emit,
+ MESA_SHADER_VERTEX);
if (INTEL_DEBUG & DEBUG_VS) {
const char *debug_name =
ralloc_asprintf(mem_ctx, "%s vertex shader %s",
g.enable_debug(debug_name);
}
- g.generate_code(v.cfg, 8);
+ g.generate_code(v.cfg, 8, v.shader_stats, stats);
assembly = g.get_assembly();
}
}
assembly = brw_vec4_generate_assembly(compiler, log_data, mem_ctx,
- shader, &prog_data->base, v.cfg);
+ shader, &prog_data->base,
+ v.cfg, stats);
}
return assembly;