i965/fs: Add support for translating ir_triop_fma into MAD.
[mesa.git] / src / mesa / drivers / dri / i965 / brw_fs_visitor.cpp
index a36c248550d52f40eecf1b1c26a984958a274442..b0494364a1ddd93cbf384f0ebc51fec52898680d 100644 (file)
@@ -336,6 +336,7 @@ fs_visitor::visit(ir_expression *ir)
         ir->operands[operand]->print();
          printf("\n");
       }
+      assert(this->result.is_valid_3src());
       op[operand] = this->result;
 
       /* Matrix expression operands should have been broken down to vector
@@ -361,12 +362,12 @@ fs_visitor::visit(ir_expression *ir)
       break;
    case ir_unop_neg:
       op[0].negate = !op[0].negate;
-      this->result = op[0];
+      emit(MOV(this->result, op[0]));
       break;
    case ir_unop_abs:
       op[0].abs = true;
       op[0].negate = false;
-      this->result = op[0];
+      emit(MOV(this->result, op[0]));
       break;
    case ir_unop_sign:
       temp = fs_reg(this, ir->type);
@@ -717,6 +718,13 @@ fs_visitor::visit(ir_expression *ir)
       break;
    }
 
+   case ir_triop_fma:
+      /* Note that the instruction's argument order is reversed from GLSL
+       * and the IR.
+       */
+      emit(MAD(this->result, op[2], op[1], op[0]));
+      break;
+
    case ir_triop_lrp:
       emit_lrp(this->result, op[0], op[1], op[2]);
       break;
@@ -1911,10 +1919,19 @@ fs_visitor::try_replace_with_sel()
          emit(MOV(src0, then_mov->src[0]));
       }
 
-      fs_inst *sel = emit(BRW_OPCODE_SEL, then_mov->dst, src0, else_mov->src[0]);
-      sel->predicate = if_inst->predicate;
-      sel->predicate_inverse = if_inst->predicate_inverse;
-      sel->conditional_mod = if_inst->conditional_mod;
+      fs_inst *sel;
+      if (if_inst->conditional_mod) {
+         /* Sandybridge-specific IF with embedded comparison */
+         emit(CMP(reg_null_d, if_inst->src[0], if_inst->src[1],
+                  if_inst->conditional_mod));
+         sel = emit(BRW_OPCODE_SEL, then_mov->dst, src0, else_mov->src[0]);
+         sel->predicate = BRW_PREDICATE_NORMAL;
+      } else {
+         /* Separate CMP and IF instructions */
+         sel = emit(BRW_OPCODE_SEL, then_mov->dst, src0, else_mov->src[0]);
+         sel->predicate = if_inst->predicate;
+         sel->predicate_inverse = if_inst->predicate_inverse;
+      }
    }
 }