HSA: implement DIVMOD internal function call
authorMartin Liska <mliska@suse.cz>
Thu, 5 Jan 2017 14:25:06 +0000 (15:25 +0100)
committerMartin Liska <marxin@gcc.gnu.org>
Thu, 5 Jan 2017 14:25:06 +0000 (14:25 +0000)
2017-01-05  Martin Liska  <mliska@suse.cz>

* hsa-gen.c (gen_hsa_divmod): New function.
(gen_hsa_insn_for_internal_fn_call): Use the function
for IFN_DIVMOD.

From-SVN: r244104

gcc/ChangeLog
gcc/hsa-gen.c

index 28b46e49db02a9bd7b3ed564647c6f2f93e498c5..62884e82ebe8ae578a461ec62286e41c9443ab4e 100644 (file)
@@ -1,3 +1,9 @@
+2017-01-05  Martin Liska  <mliska@suse.cz>
+
+       * hsa-gen.c (gen_hsa_divmod): New function.
+       (gen_hsa_insn_for_internal_fn_call): Use the function
+       for IFN_DIVMOD.
+
 2017-01-05  Martin Liska  <mliska@suse.cz>
 
        PR pch/78970
index f2843b3ed386368597d60454ba0ad9536ba323da..632561d5e45df6d2456c57feb1bb38820f20659e 100644 (file)
@@ -4345,6 +4345,40 @@ gen_hsa_popcount (gcall *call, hsa_bb *hbb)
   gen_hsa_popcount_to_dest (dest, arg, hbb);
 }
 
+/* Emit instructions that implement DIVMOD builtin STMT.
+   Instructions are appended to basic block HBB.  */
+
+static void
+gen_hsa_divmod (gcall *call, hsa_bb *hbb)
+{
+  tree lhs = gimple_call_lhs (call);
+  if (lhs == NULL_TREE)
+    return;
+
+  tree rhs0 = gimple_call_arg (call, 0);
+  tree rhs1 = gimple_call_arg (call, 1);
+
+  hsa_op_with_type *arg0 = hsa_reg_or_immed_for_gimple_op (rhs0, hbb);
+  hsa_op_with_type *arg1 = hsa_reg_or_immed_for_gimple_op (rhs1, hbb);
+
+  hsa_op_reg *dest0 = new hsa_op_reg (arg0->m_type);
+  hsa_op_reg *dest1 = new hsa_op_reg (arg1->m_type);
+
+  hsa_insn_basic *insn = new hsa_insn_basic (3, BRIG_OPCODE_DIV, dest0->m_type,
+                                            dest0, arg0, arg1);
+  hbb->append_insn (insn);
+  insn = new hsa_insn_basic (3, BRIG_OPCODE_REM, dest1->m_type, dest1, arg0,
+                            arg1);
+  hbb->append_insn (insn);
+
+  hsa_op_reg *dest = hsa_cfun->reg_for_gimple_ssa (lhs);
+  BrigType16_t src_type = hsa_bittype_for_type (dest0->m_type);
+
+  insn = new hsa_insn_packed (3, BRIG_OPCODE_COMBINE, dest->m_type,
+                             src_type, dest, dest0, dest1);
+  hbb->append_insn (insn);
+}
+
 /* Set VALUE to a shadow kernel debug argument and append a new instruction
    to HBB basic block.  */
 
@@ -5050,6 +5084,10 @@ gen_hsa_insn_for_internal_fn_call (gcall *stmt, hsa_bb *hbb)
       gen_hsa_popcount (stmt, hbb);
       break;
 
+    case IFN_DIVMOD:
+      gen_hsa_divmod (stmt, hbb);
+      break;
+
     case IFN_ACOS:
     case IFN_ASIN:
     case IFN_ATAN: