@@ -7511,6 +7511,132 @@ nvptx_goacc_expand_var_decl (tree var)
return NULL_RTX;
}
+/* Helper function of nvptx_rtx_costs.
+ Assume each ptxas instruction has the same size. */
+
+static bool
+nvptx_rtx_size_costs (rtx x, machine_mode mode, int outer_code, int *total)
+{
+ int code = GET_CODE (x);
+
+ switch (code)
+ {
+ case PLUS:
+ case MINUS:
+ case MULT:
+ case DIV:
+ case MOD:
+ case FMA:
+ if (mode == SImode || mode == DImode
+ || mode == HImode || mode == QImode
+ || mode == SFmode || mode == DFmode)
+ *total = COSTS_N_INSNS (1);
+ break;
+ case ASHIFT:
+ case ASHIFTRT:
+ case LSHIFTRT:
+ case ZERO_EXTEND:
+ case UDIV:
+ case UMOD:
+ case ABS:
+ case POPCOUNT:
+ if (mode == SImode || mode == DImode
+ || mode == HImode || mode == QImode)
+ *total = COSTS_N_INSNS (1);
+ break;
+ case SUBREG:
+ case TRUNCATE:
+ *total = COSTS_N_INSNS (1);
+ break;
+ case REG:
+ case CONST_INT:
+ case CONST_DOUBLE:
+ if (outer_code == SET)
+ *total = COSTS_N_INSNS (1);
+ break;
+ }
+ return false;
+}
+
+/* Implement TARGET_RTX_COSTS. */
+
+static bool
+nvptx_rtx_costs (rtx x, machine_mode mode, int outer_code,
+ int opno ATTRIBUTE_UNUSED, int *total, bool speed_p)
+{
+ if (! speed_p)
+ return nvptx_rtx_size_costs (x, mode, outer_code, total);
+
+ int code = GET_CODE (x);
+
+ switch (code)
+ {
+ case PLUS:
+ case MINUS:
+ case NEG:
+ case ASHIFT:
+ case ASHIFTRT:
+ case LSHIFTRT:
+ case ZERO_EXTEND:
+ if (mode == SImode || mode == DImode
+ || mode == HImode || mode == QImode
+ || mode == SFmode || mode == DFmode)
+ *total = COSTS_N_INSNS (1);
+ break;
+ case MULT:
+ case FMA:
+ case UMUL_HIGHPART:
+ if (mode == SImode || mode == DImode
+ || mode == HImode || mode == QImode
+ || mode == SFmode || mode == DFmode)
+ *total = COSTS_N_INSNS (2);
+ break;
+ case DIV:
+ case MOD:
+ if (mode == SImode || mode == DImode
+ || mode == HImode || mode == QImode)
+ *total = COSTS_N_INSNS (25);
+ else if (mode == SFmode)
+ *total = COSTS_N_INSNS (64);
+ else if (mode == DFmode)
+ *total = COSTS_N_INSNS (90);
+ break;
+ case UDIV:
+ case UMOD:
+ if (mode == SImode || mode == DImode
+ || mode == HImode || mode == QImode)
+ *total = COSTS_N_INSNS (24);
+ break;
+ case ABS:
+ if (mode == SImode || mode == DImode
+ || mode == HImode || mode == QImode)
+ *total = COSTS_N_INSNS (2);
+ break;
+ case POPCOUNT:
+ if (mode == SImode || mode == DImode
+ || mode == HImode || mode == QImode)
+ *total = COSTS_N_INSNS (4);
+ break;
+ case SUBREG:
+ case TRUNCATE:
+ *total = COSTS_N_INSNS (1);
+ break;
+ case REG:
+ case CONST_INT:
+ case CONST_DOUBLE:
+ *total = (outer_code == SET) ? COSTS_N_INSNS (1) : 0;
+ return true;
+ case UNSPEC:
+ if (XINT (x, 1) == UNSPEC_ARG_REG)
+ {
+ *total = (outer_code == SET) ? COSTS_N_INSNS (1) : 0;
+ return true;
+ }
+ break;
+ }
+ return false;
+}
+
static GTY(()) tree nvptx_previous_fndecl;
static void
@@ -7786,6 +7912,9 @@ nvptx_asm_output_def_from_decls (FILE *stream, tree name, tree value)
#undef TARGET_GOACC_EXPAND_VAR_DECL
#define TARGET_GOACC_EXPAND_VAR_DECL nvptx_goacc_expand_var_decl
+#undef TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS nvptx_rtx_costs
+
#undef TARGET_SET_CURRENT_FUNCTION
#define TARGET_SET_CURRENT_FUNCTION nvptx_set_current_function
new file mode 100644
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+int foo(unsigned int x)
+{
+ return x/10;
+}
+
+/* { dg-final { scan-assembler "mul.hi.u32" } } */
+/* { dg-final { scan-assembler "shr.u32" } } */
+/* { dg-final { scan-assembler-not "div.u32" } } */