ALU2(SHR)
ALU2(ASR)
+/** Gen4 predicated IF. */
+fs_inst *
+fs_visitor::IF(uint32_t predicate)
+{
+ fs_inst *inst = new(mem_ctx) fs_inst(BRW_OPCODE_IF);
+ inst->predicate = predicate;
+ return inst;
+}
+
+/** Gen6+ IF with embedded comparison. */
+fs_inst *
+fs_visitor::IF(fs_reg src0, fs_reg src1, uint32_t condition)
+{
+ assert(intel->gen >= 6);
+ fs_inst *inst = new(mem_ctx) fs_inst(BRW_OPCODE_IF,
+ reg_null_d, src0, src1);
+ inst->conditional_mod = condition;
+ return inst;
+}
+
+/**
+ * CMP: Sets the low bit of the destination channels with the result
+ * of the comparison, while the upper bits are undefined, and updates
+ * the flag register with the packed 16 bits of the result.
+ */
+fs_inst *
+fs_visitor::CMP(fs_reg dst, fs_reg src0, fs_reg src1, uint32_t condition)
+{
+ fs_inst *inst;
+
+ /* Take the instruction:
+ *
+ * CMP null<d> src0<f> src1<f>
+ *
+ * Original gen4 does type conversion to the destination type before
+ * comparison, producing garbage results for floating point comparisons.
+ * gen5 does the comparison on the execution type (resolved source types),
+ * so dst type doesn't matter. gen6 does comparison and then uses the
+ * result as if it was the dst type with no conversion, which happens to
+ * mostly work out for float-interpreted-as-int since our comparisons are
+ * for >0, =0, <0.
+ */
+ if (intel->gen == 4) {
+ dst.type = src0.type;
+ if (dst.file == FIXED_HW_REG)
+ dst.fixed_hw_reg.type = dst.type;
+ }
+
+ resolve_ud_negate(&src0);
+ resolve_ud_negate(&src1);
+
+ inst = new(mem_ctx) fs_inst(BRW_OPCODE_CMP, dst, src0, src1);
+ inst->conditional_mod = condition;
+
+ return inst;
+}
+
bool
fs_inst::equals(fs_inst *inst)
{
/* bit 31 is "primitive is back face", so checking < (1 << 31) gives
* us front face
*/
- fs_inst *inst = emit(BRW_OPCODE_CMP, *reg,
- fs_reg(r1_6ud),
- fs_reg(1u << 31));
- inst->conditional_mod = BRW_CONDITIONAL_L;
+ emit(CMP(*reg, fs_reg(r1_6ud), fs_reg(1u << 31), BRW_CONDITIONAL_L));
emit(BRW_OPCODE_AND, *reg, *reg, fs_reg(1u));
}
if (fpi->DstReg.WriteMask & (1 << i)) {
fs_inst *inst;
- inst = emit(BRW_OPCODE_CMP, fs_reg(brw_null_reg()),
- regoffset(src0, i), regoffset(src1, i));
- inst->conditional_mod = conditional_mod;
+ emit(CMP(reg_null_d, regoffset(src0, i), regoffset(src1, i),
+ conditional_mod));
inst = emit(BRW_OPCODE_SEL, regoffset(dst, i), one, fs_reg(0.0f));
inst->predicate = BRW_PREDICATE_NORMAL;
if (fpi->DstReg.WriteMask & (1 << i)) {
fs_inst *inst;
- inst = emit(BRW_OPCODE_CMP, null,
- regoffset(src[0], i), fs_reg(0.0f));
- inst->conditional_mod = BRW_CONDITIONAL_L;
+ emit(CMP(null, regoffset(src[0], i), fs_reg(0.0f),
+ BRW_CONDITIONAL_L));
inst = emit(BRW_OPCODE_SEL, regoffset(dst, i),
regoffset(src[1], i), regoffset(src[2], i));
continue;
}
- fs_inst *inst = emit(BRW_OPCODE_CMP, null,
- regoffset(src[0], i), 0.0f);
- inst->conditional_mod = BRW_CONDITIONAL_L;
+ emit(CMP(null, regoffset(src[0], i), fs_reg(0.0f),
+ BRW_CONDITIONAL_L));
- inst = emit(BRW_OPCODE_IF);
- inst->predicate = BRW_PREDICATE_NORMAL;
+ emit(IF(BRW_PREDICATE_NORMAL));
emit(FS_OPCODE_DISCARD);
emit(BRW_OPCODE_ENDIF);
}
if (fpi->DstReg.WriteMask & WRITEMASK_YZ) {
fs_inst *inst;
- inst = emit(BRW_OPCODE_CMP, null,
- regoffset(src[0], 0), fs_reg(0.0f));
- inst->conditional_mod = BRW_CONDITIONAL_LE;
+ emit(CMP(null, regoffset(src[0], 0), fs_reg(0.0f),
+ BRW_CONDITIONAL_LE));
if (fpi->DstReg.WriteMask & WRITEMASK_Y) {
emit(MOV(regoffset(dst, 1), regoffset(src[0], 0)));
inst = emit(BRW_OPCODE_SEL, dst, src0, src1);
inst->conditional_mod = conditionalmod;
} else {
- inst = emit(BRW_OPCODE_CMP, reg_null_cmp, src0, src1);
- inst->conditional_mod = conditionalmod;
+ emit(CMP(reg_null_d, src0, src1, conditionalmod));
inst = emit(BRW_OPCODE_SEL, dst, src0, src1);
inst->predicate = BRW_PREDICATE_NORMAL;
emit(MOV(this->result, fs_reg(0.0f)));
- inst = emit(BRW_OPCODE_CMP, reg_null_f, op[0], fs_reg(0.0f));
- inst->conditional_mod = BRW_CONDITIONAL_G;
+ emit(CMP(reg_null_f, op[0], fs_reg(0.0f), BRW_CONDITIONAL_G));
inst = emit(MOV(this->result, fs_reg(1.0f)));
inst->predicate = BRW_PREDICATE_NORMAL;
- inst = emit(BRW_OPCODE_CMP, reg_null_f, op[0], fs_reg(0.0f));
- inst->conditional_mod = BRW_CONDITIONAL_L;
+ emit(CMP(reg_null_f, op[0], fs_reg(0.0f), BRW_CONDITIONAL_L));
inst = emit(MOV(this->result, fs_reg(-1.0f)));
inst->predicate = BRW_PREDICATE_NORMAL;
case ir_binop_all_equal:
case ir_binop_nequal:
case ir_binop_any_nequal:
- temp = this->result;
- /* original gen4 does implicit conversion before comparison. */
- if (intel->gen < 5)
- temp.type = op[0].type;
-
- resolve_ud_negate(&op[0]);
- resolve_ud_negate(&op[1]);
-
resolve_bool_comparison(ir->operands[0], &op[0]);
resolve_bool_comparison(ir->operands[1], &op[1]);
- inst = emit(BRW_OPCODE_CMP, temp, op[0], op[1]);
- inst->conditional_mod = brw_conditional_for_comparison(ir->operation);
+ emit(CMP(this->result, op[0], op[1],
+ brw_conditional_for_comparison(ir->operation)));
break;
case ir_binop_logic_xor:
case ir_unop_f2b:
case ir_unop_i2b:
- temp = this->result;
- /* original gen4 does implicit conversion before comparison. */
- if (intel->gen < 5)
- temp.type = op[0].type;
-
- resolve_ud_negate(&op[0]);
-
- inst = emit(BRW_OPCODE_CMP, temp, op[0], fs_reg(0.0f));
- inst->conditional_mod = BRW_CONDITIONAL_NZ;
+ emit(CMP(this->result, op[0], fs_reg(0.0f), BRW_CONDITIONAL_NZ));
break;
case ir_unop_trunc:
* values with the low bit set to 1. Convert them using CMP.
*/
if (ir->type->base_type == GLSL_TYPE_BOOL) {
- fs_inst *inst = emit(fs_inst(BRW_OPCODE_CMP, result,
- packed_consts, fs_reg(0u)));
- inst->conditional_mod = BRW_CONDITIONAL_NZ;
+ emit(CMP(result, packed_consts, fs_reg(0u), BRW_CONDITIONAL_NZ));
} else {
emit(MOV(result, packed_consts));
}
case ir_unop_f2b:
if (intel->gen >= 6) {
- inst = emit(BRW_OPCODE_CMP, reg_null_d, op[0], fs_reg(0.0f));
+ emit(CMP(reg_null_d, op[0], fs_reg(0.0f), BRW_CONDITIONAL_NZ));
} else {
inst = emit(MOV(reg_null_f, op[0]));
+ inst->conditional_mod = BRW_CONDITIONAL_NZ;
}
- inst->conditional_mod = BRW_CONDITIONAL_NZ;
break;
case ir_unop_i2b:
if (intel->gen >= 6) {
- inst = emit(BRW_OPCODE_CMP, reg_null_d, op[0], fs_reg(0));
+ emit(CMP(reg_null_d, op[0], fs_reg(0), BRW_CONDITIONAL_NZ));
} else {
inst = emit(MOV(reg_null_d, op[0]));
+ inst->conditional_mod = BRW_CONDITIONAL_NZ;
}
- inst->conditional_mod = BRW_CONDITIONAL_NZ;
break;
case ir_binop_greater:
resolve_bool_comparison(expr->operands[0], &op[0]);
resolve_bool_comparison(expr->operands[1], &op[1]);
- inst = emit(BRW_OPCODE_CMP, reg_null_cmp, op[0], op[1]);
- inst->conditional_mod =
- brw_conditional_for_comparison(expr->operation);
+ emit(CMP(reg_null_d, op[0], op[1],
+ brw_conditional_for_comparison(expr->operation)));
break;
default:
return;
case ir_unop_i2b:
- inst = emit(BRW_OPCODE_IF, reg_null_d, op[0], fs_reg(0));
- inst->conditional_mod = BRW_CONDITIONAL_NZ;
+ emit(IF(op[0], fs_reg(0), BRW_CONDITIONAL_NZ));
return;
case ir_binop_greater:
resolve_bool_comparison(expr->operands[0], &op[0]);
resolve_bool_comparison(expr->operands[1], &op[1]);
- inst = emit(BRW_OPCODE_IF, reg_null_d, op[0], op[1]);
- inst->conditional_mod =
- brw_conditional_for_comparison(expr->operation);
+ emit(IF(op[0], op[1],
+ brw_conditional_for_comparison(expr->operation)));
return;
default:
assert(!"not reached");
- inst = emit(BRW_OPCODE_IF, reg_null_d, op[0], fs_reg(0));
- inst->conditional_mod = BRW_CONDITIONAL_NZ;
+ emit(IF(op[0], fs_reg(0), BRW_CONDITIONAL_NZ));
fail("bad condition\n");
return;
}
void
fs_visitor::visit(ir_if *ir)
{
- fs_inst *inst;
-
if (intel->gen < 6 && c->dispatch_width == 16) {
fail("Can't support (non-uniform) control flow on 16-wide\n");
}
} else {
emit_bool_to_cond_code(ir->condition);
- inst = emit(BRW_OPCODE_IF);
- inst->predicate = BRW_PREDICATE_NORMAL;
+ emit(IF(BRW_PREDICATE_NORMAL));
}
foreach_list(node, &ir->then_instructions) {
this->base_ir = ir->to;
ir->to->accept(this);
- fs_inst *inst = emit(BRW_OPCODE_CMP, reg_null_cmp, counter, this->result);
- inst->conditional_mod = brw_conditional_for_comparison(ir->cmp);
+ emit(CMP(reg_null_d, counter, this->result,
+ brw_conditional_for_comparison(ir->cmp)));
- inst = emit(BRW_OPCODE_BREAK);
+ fs_inst *inst = emit(BRW_OPCODE_BREAK);
inst->predicate = BRW_PREDICATE_NORMAL;
}
hash_table_pointer_hash,
hash_table_pointer_compare);
- /* There's a question that appears to be left open in the spec:
- * How do implicit dst conversions interact with the CMP
- * instruction or conditional mods? On gen6, the instruction:
- *
- * CMP null<d> src0<f> src1<f>
- *
- * will do src1 - src0 and compare that result as if it was an
- * integer. On gen4, it will do src1 - src0 as float, convert
- * the result to int, and compare as int. In between, it
- * appears that it does src1 - src0 and does the compare in the
- * execution type so dst type doesn't matter.
- */
- if (this->intel->gen > 4)
- this->reg_null_cmp = reg_null_d;
- else
- this->reg_null_cmp = reg_null_f;
-
memset(this->outputs, 0, sizeof(this->outputs));
memset(this->output_components, 0, sizeof(this->output_components));
this->first_non_payload_grf = 0;