return repl;
}
+/* DISCARD.b32(FCMP.f(x, y)) --> DISCARD.f(x, y) */
+
+static inline void
+bi_fuse_discard_fcmp(bi_instr *I, bi_instr *mod, unsigned arch)
+{
+ if (I->op != BI_OPCODE_DISCARD_B32) return;
+ if (mod->op != BI_OPCODE_FCMP_F32 && mod->op != BI_OPCODE_FCMP_V2F16) return;
+ if (mod->cmpf >= BI_CMPF_GTLT) return;
+
+ /* .abs and .neg modifiers allowed on Valhall DISCARD but not Bifrost */
+ bool absneg = mod->src[0].neg || mod->src[0].abs;
+ absneg |= mod->src[1].neg || mod->src[1].abs;
+
+ if (arch <= 8 && absneg) return;
+
+ enum bi_swizzle r = I->src[0].swizzle;
+
+ /* result_type doesn't matter */
+ I->op = BI_OPCODE_DISCARD_F32;
+ I->cmpf = mod->cmpf;
+ I->src[0] = mod->src[0];
+ I->src[1] = mod->src[1];
+
+ if (mod->op == BI_OPCODE_FCMP_V2F16) {
+ I->src[0].swizzle = bi_compose_swizzle_16(r, I->src[0].swizzle);
+ I->src[1].swizzle = bi_compose_swizzle_16(r, I->src[1].swizzle);
+ }
+}
+
void
bi_opt_mod_prop_forward(bi_context *ctx)
{
unsigned size = bi_opcode_props[I->op].size;
+ bi_fuse_discard_fcmp(I, mod, ctx->arch);
+
if (bi_is_fabsneg(mod->op, size)) {
if (mod->src[0].abs && !bi_takes_fabs(ctx->arch, I, mod->src[0], s))
continue;
I->src[1] = bi_negzero();
break;
+ case BI_OPCODE_DISCARD_B32:
+ I->op = BI_OPCODE_DISCARD_F32;
+ I->src[1] = bi_imm_u16(0);
+ I->cmpf = BI_CMPF_NE;
+ break;
+
default:
break;
}
case nir_intrinsic_discard_if: {
bi_index src = bi_src_index(&instr->src[0]);
assert(nir_src_bit_size(instr->src[0]) == 1);
- bi_discard_f32(b, bi_half(src, false), bi_imm_u16(0), BI_CMPF_NE);
+ bi_discard_b32(b, bi_half(src, false));
break;
}
bool
bi_side_effects(enum bi_opcode op)
{
- if (bi_opcode_props[op].last || op == BI_OPCODE_DISCARD_F32)
+ if (bi_opcode_props[op].last)
return true;
+ switch (op) {
+ case BI_OPCODE_DISCARD_F32:
+ case BI_OPCODE_DISCARD_B32:
+ return true;
+ default:
+ break;
+ }
+
switch (bi_opcode_props[op].message) {
case BIFROST_MESSAGE_NONE:
case BIFROST_MESSAGE_VARYING: