i965: Generate code for ir_binop_carry and ir_binop_borrow.
authorMatt Turner <mattst88@gmail.com>
Thu, 19 Sep 2013 20:01:08 +0000 (13:01 -0700)
committerMatt Turner <mattst88@gmail.com>
Mon, 7 Oct 2013 17:41:17 +0000 (10:41 -0700)
Using the ADDC and SUBB instructions on Gen7.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
14 files changed:
src/mesa/drivers/dri/i965/brw_defines.h
src/mesa/drivers/dri/i965/brw_disasm.c
src/mesa/drivers/dri/i965/brw_eu.h
src/mesa/drivers/dri/i965/brw_eu_emit.c
src/mesa/drivers/dri/i965/brw_fs.cpp
src/mesa/drivers/dri/i965/brw_fs.h
src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp
src/mesa/drivers/dri/i965/brw_fs_copy_propagation.cpp
src/mesa/drivers/dri/i965/brw_fs_generator.cpp
src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
src/mesa/drivers/dri/i965/brw_vec4.h
src/mesa/drivers/dri/i965/brw_vec4_copy_propagation.cpp
src/mesa/drivers/dri/i965/brw_vec4_generator.cpp
src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp

index 7dfb2b9136ad29bfdcb19fd326f7a82195283a3d..c1e7f31fe8b14faed5483ba74c6c50421cf310c0 100644 (file)
@@ -733,6 +733,8 @@ enum opcode {
    BRW_OPCODE_FBH =    75,
    BRW_OPCODE_FBL =    76,
    BRW_OPCODE_CBIT =   77,
+   BRW_OPCODE_ADDC =   78,
+   BRW_OPCODE_SUBB =   79,
    BRW_OPCODE_SAD2 =   80,
    BRW_OPCODE_SADA2 =  81,
    BRW_OPCODE_DP4 =    84,
index 18e6c9d78fc0ecf481aa4489ddf9ab23e942ea9e..22b37d797bf48eb81e6f323c722f625b1d573fdb 100644 (file)
@@ -77,6 +77,8 @@ const struct opcode_desc opcode_descs[128] = {
     [BRW_OPCODE_BFE] = { .name = "bfe", .nsrc = 3, .ndst = 1},
     [BRW_OPCODE_BFI1] = { .name = "bfe1", .nsrc = 2, .ndst = 1},
     [BRW_OPCODE_BFI2] = { .name = "bfe2", .nsrc = 3, .ndst = 1},
+    [BRW_OPCODE_ADDC] = { .name = "addc", .nsrc = 2, .ndst = 1},
+    [BRW_OPCODE_SUBB] = { .name = "subb", .nsrc = 2, .ndst = 1},
 
     [BRW_OPCODE_SEND] = { .name = "send", .nsrc = 1, .ndst = 1 },
     [BRW_OPCODE_SENDC] = { .name = "sendc", .nsrc = 1, .ndst = 1 },
index 720bc74591adf83c03e02f4689a662c764ea6a05..072310d5544713648d4edea4789ad5fc12d620db 100644 (file)
@@ -181,6 +181,8 @@ ALU3(BFI2)
 ALU1(FBH)
 ALU1(FBL)
 ALU1(CBIT)
+ALU2(ADDC)
+ALU2(SUBB)
 
 ROUND(RNDZ)
 ROUND(RNDE)
index 7ed3df0e5f8f6117904fa476bdcb0702cc18552c..d9ba110f27ff53a36a7ac8b53c44c345813f3402 100644 (file)
@@ -968,6 +968,8 @@ ALU3(BFI2)
 ALU1(FBH)
 ALU1(FBL)
 ALU1(CBIT)
+ALU2(ADDC)
+ALU2(SUBB)
 
 ROUND(RNDZ)
 ROUND(RNDE)
index 89eb33e480d4069bdfab7febb9c0834d4ba51d85..b2c9f5a8e326ec986aa37975f5bea84603bf4153 100644 (file)
@@ -180,6 +180,8 @@ ALU1(FBH)
 ALU1(FBL)
 ALU1(CBIT)
 ALU3(MAD)
+ALU2(ADDC)
+ALU2(SUBB)
 
 /** Gen4 predicated IF. */
 fs_inst *
index 679a4b0dc1b25746d4b0afaa1da81c4cdb176144..c59ca51a1f9f90a9a7feb2b632f0676fc180a6e3 100644 (file)
@@ -260,6 +260,8 @@ public:
    fs_inst *FBL(fs_reg dst, fs_reg value);
    fs_inst *CBIT(fs_reg dst, fs_reg value);
    fs_inst *MAD(fs_reg dst, fs_reg c, fs_reg b, fs_reg a);
+   fs_inst *ADDC(fs_reg dst, fs_reg src0, fs_reg src1);
+   fs_inst *SUBB(fs_reg dst, fs_reg src0, fs_reg src1);
 
    int type_size(const struct glsl_type *type);
    fs_inst *get_instruction_generating_reg(fs_inst *start,
index fb932d8c2178bee17c77b2bfc33224cfb925d726..8cbe1c9bc99f83c3aca70e88bb19020b187be699 100644 (file)
@@ -234,6 +234,8 @@ ir_channel_expressions_visitor::visit_leave(ir_assignment *ir)
    case ir_binop_sub:
    case ir_binop_mul:
    case ir_binop_div:
+   case ir_binop_carry:
+   case ir_binop_borrow:
    case ir_binop_mod:
    case ir_binop_min:
    case ir_binop_max:
index 034ebef9917e9c4f5a8ed0e5f1cb45a9f9551f7d..5acef207af394388b6d2e68071d84a88966fe408 100644 (file)
@@ -343,6 +343,8 @@ fs_visitor::try_constant_propagate(fs_inst *inst, acp_entry *entry)
 
       case BRW_OPCODE_SHL:
       case BRW_OPCODE_SHR:
+      case BRW_OPCODE_ADDC:
+      case BRW_OPCODE_SUBB:
          if (i == 1) {
             inst->src[i] = entry->src;
             progress = true;
index 1e27152a67d418d3699004ae1756b665b8d14f53..8fe4203348122440b3b9fb0502871ce394ce8817 100644 (file)
@@ -1334,6 +1334,18 @@ fs_generator::generate_code(exec_list *instructions)
          /* CBIT only supports UD type for dst. */
          brw_CBIT(p, retype(dst, BRW_REGISTER_TYPE_UD), src[0]);
          break;
+      case BRW_OPCODE_ADDC:
+         assert(brw->gen >= 7);
+         brw_set_acc_write_control(p, 1);
+         brw_ADDC(p, dst, src[0], src[1]);
+         brw_set_acc_write_control(p, 0);
+         break;
+      case BRW_OPCODE_SUBB:
+         assert(brw->gen >= 7);
+         brw_set_acc_write_control(p, 1);
+         brw_SUBB(p, dst, src[0], src[1]);
+         brw_set_acc_write_control(p, 0);
+         break;
 
       case BRW_OPCODE_BFE:
          brw_set_access_mode(p, BRW_ALIGN_16);
index 62d2042a59876b762de3cd0bb436f035d18f309f..f35e112764672b3eef6a6a1ddd76530ae4efbe53 100644 (file)
@@ -447,6 +447,26 @@ fs_visitor::visit(ir_expression *ir)
       assert(ir->type->is_integer());
       emit_math(SHADER_OPCODE_INT_QUOTIENT, this->result, op[0], op[1]);
       break;
+   case ir_binop_carry: {
+      if (brw->gen >= 7 && dispatch_width == 16)
+         fail("16-wide explicit accumulator operands unsupported\n");
+
+      struct brw_reg acc = retype(brw_acc_reg(), BRW_REGISTER_TYPE_UD);
+
+      emit(ADDC(reg_null_ud, op[0], op[1]));
+      emit(MOV(this->result, fs_reg(acc)));
+      break;
+   }
+   case ir_binop_borrow: {
+      if (brw->gen >= 7 && dispatch_width == 16)
+         fail("16-wide explicit accumulator operands unsupported\n");
+
+      struct brw_reg acc = retype(brw_acc_reg(), BRW_REGISTER_TYPE_UD);
+
+      emit(SUBB(reg_null_ud, op[0], op[1]));
+      emit(MOV(this->result, fs_reg(acc)));
+      break;
+   }
    case ir_binop_mod:
       /* Floating point should be lowered by MOD_TO_FRACT in the compiler. */
       assert(ir->type->is_integer());
index 9683f1c06cd30b6b078e305abfd8ff7c6555e9f8..290363e416b85e50226d68a5bc9845779a38a454 100644 (file)
@@ -419,6 +419,8 @@ public:
    vec4_instruction *FBL(dst_reg dst, src_reg value);
    vec4_instruction *CBIT(dst_reg dst, src_reg value);
    vec4_instruction *MAD(dst_reg dst, src_reg c, src_reg b, src_reg a);
+   vec4_instruction *ADDC(dst_reg dst, src_reg src0, src_reg src1);
+   vec4_instruction *SUBB(dst_reg dst, src_reg src0, src_reg src1);
 
    int implied_mrf_writes(vec4_instruction *inst);
 
index cd2b11831aea0b1d14c71b853fc07048b69abdef..d009a08e8bd9fe37e68b077d1edb82d2187822fd 100644 (file)
@@ -97,6 +97,8 @@ try_constant_propagation(vec4_instruction *inst, int arg, src_reg *values[4])
 
    case BRW_OPCODE_SHL:
    case BRW_OPCODE_SHR:
+   case BRW_OPCODE_ADDC:
+   case BRW_OPCODE_SUBB:
       if (arg == 1) {
          inst->src[arg] = value;
          return true;
index 00efb10f38b82aa1b65c1b30714b7faa3daeccd1..ae6e43ca34a57383779d5452966a5803fec65c41 100644 (file)
@@ -963,6 +963,18 @@ vec4_generator::generate_vec4_instruction(vec4_instruction *instruction,
       /* CBIT only supports UD type for dst. */
       brw_CBIT(p, retype(dst, BRW_REGISTER_TYPE_UD), src[0]);
       break;
+   case BRW_OPCODE_ADDC:
+      assert(brw->gen >= 7);
+      brw_set_acc_write_control(p, 1);
+      brw_ADDC(p, dst, src[0], src[1]);
+      brw_set_acc_write_control(p, 0);
+      break;
+   case BRW_OPCODE_SUBB:
+      assert(brw->gen >= 7);
+      brw_set_acc_write_control(p, 1);
+      brw_SUBB(p, dst, src[0], src[1]);
+      brw_set_acc_write_control(p, 0);
+      break;
 
    case BRW_OPCODE_BFE:
       brw_BFE(p, dst, src[0], src[1], src[2]);
index 09f0236c682e373c576c7cc4b4913682507ad4ad..856312f4dd939326abc42f8bf21d1afc5e05e0c2 100644 (file)
@@ -162,6 +162,8 @@ ALU1(FBH)
 ALU1(FBL)
 ALU1(CBIT)
 ALU3(MAD)
+ALU2(ADDC)
+ALU2(SUBB)
 
 /** Gen4 predicated IF. */
 vec4_instruction *
@@ -1371,6 +1373,20 @@ vec4_visitor::visit(ir_expression *ir)
       assert(ir->type->is_integer());
       emit_math(SHADER_OPCODE_INT_QUOTIENT, result_dst, op[0], op[1]);
       break;
+   case ir_binop_carry: {
+      struct brw_reg acc = retype(brw_acc_reg(), BRW_REGISTER_TYPE_UD);
+
+      emit(ADDC(dst_null_ud(), op[0], op[1]));
+      emit(MOV(result_dst, src_reg(acc)));
+      break;
+   }
+   case ir_binop_borrow: {
+      struct brw_reg acc = retype(brw_acc_reg(), BRW_REGISTER_TYPE_UD);
+
+      emit(SUBB(dst_null_ud(), op[0], op[1]));
+      emit(MOV(result_dst, src_reg(acc)));
+      break;
+   }
    case ir_binop_mod:
       /* Floating point should be lowered by MOD_TO_FRACT in the compiler. */
       assert(ir->type->is_integer());