The length of an insn can be used to calculate its cost, when optimizing for
size. When optimizing for speed, this is a good estimate, since the cycle cost
of an MSP430 instruction increases with its length.

>From e4c5f9c3f567489f89b41a0d96e321acb5d18152 Mon Sep 17 00:00:00 2001
From: Jozef Lawrynowicz <joze...@mittosystems.com>
Date: Thu, 16 Jul 2020 11:34:50 +0100
Subject: [PATCH 4/5] MSP430: Implement TARGET_INSN_COST

The length of an insn can be used to calculate its cost, when optimizing for
size. When optimizing for speed, this is a good estimate, since the cycle cost
of an MSP430 instruction increases with its length.

gcc/ChangeLog:

        * config/msp430/msp430.c (TARGET_INSN_COST): Define.
        (msp430_insn_cost): New function.
        * config/msp430/msp430.opt: Add -mdebug-insn-costs option.

gcc/testsuite/ChangeLog:

        * gcc.target/msp430/rtx-cost-O3-default.c: New test.
        * gcc.target/msp430/rtx-cost-O3-f5series.c: New test.
        * gcc.target/msp430/rtx-cost-Os-default.c: New test.
        * gcc.target/msp430/rtx-cost-Os-f5series.c: New test.
---
 gcc/config/msp430/msp430.c                    | 29 +++++++++++++
 gcc/config/msp430/msp430.opt                  |  4 ++
 .../gcc.target/msp430/rtx-cost-O3-default.c   | 42 ++++++++++++++++++
 .../gcc.target/msp430/rtx-cost-O3-f5series.c  | 38 ++++++++++++++++
 .../gcc.target/msp430/rtx-cost-Os-default.c   | 43 +++++++++++++++++++
 .../gcc.target/msp430/rtx-cost-Os-f5series.c  | 38 ++++++++++++++++
 6 files changed, 194 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/msp430/rtx-cost-O3-default.c
 create mode 100644 gcc/testsuite/gcc.target/msp430/rtx-cost-O3-f5series.c
 create mode 100644 gcc/testsuite/gcc.target/msp430/rtx-cost-Os-default.c
 create mode 100644 gcc/testsuite/gcc.target/msp430/rtx-cost-Os-f5series.c

diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c
index b7daafcc11a..7ef651fb324 100644
--- a/gcc/config/msp430/msp430.c
+++ b/gcc/config/msp430/msp430.c
@@ -1711,6 +1711,35 @@ msp430_rtx_costs (rtx x,
       return false;
     }
 }
+
+#undef TARGET_INSN_COST
+#define TARGET_INSN_COST msp430_insn_cost
+
+static int
+msp430_insn_cost (rtx_insn *insn, bool speed ATTRIBUTE_UNUSED)
+{
+  int cost;
+
+  if (recog_memoized (insn) < 0)
+    return 0;
+
+  cost = get_attr_length (insn);
+  if (TARGET_DEBUG_INSN_COSTS)
+    {
+      fprintf (stderr, "cost %d for insn:\n", cost);
+      debug_rtx (insn);
+    }
+
+  /* The returned cost must be relative to COSTS_N_INSNS (1). An insn with a
+     length of 2 bytes is the smallest possible size and so must be equivalent
+     to COSTS_N_INSNS (1).  */
+  return COSTS_N_INSNS (cost) / (2 * COSTS_N_INSNS (1));
+
+  /* FIXME Add more detailed costs when optimizing for speed.
+     For now the length of the instruction is a good approximiation and roughly
+     correlates with cycle cost.  */
+}
+
 
 /* Function Entry and Exit */
 
diff --git a/gcc/config/msp430/msp430.opt b/gcc/config/msp430/msp430.opt
index 8134ca7ac95..448c41aa81c 100644
--- a/gcc/config/msp430/msp430.opt
+++ b/gcc/config/msp430/msp430.opt
@@ -115,3 +115,7 @@ Target RejectNegative Joined UInteger IntegerRange(0,65) 
Var(msp430_max_inline_s
 For shift operations by a constant amount, which require an individual 
instruction to shift by one
 position, set the maximum number of inline shift instructions (maximum value 
64) to emit instead of using the corresponding __mspabi helper function.
 The default value is 4.
+
+mdebug-insn-costs
+Target Report Mask(DEBUG_INSN_COSTS)
+Print insns and their costs as calculated by TARGET_INSN_COSTS.
diff --git a/gcc/testsuite/gcc.target/msp430/rtx-cost-O3-default.c 
b/gcc/testsuite/gcc.target/msp430/rtx-cost-O3-default.c
new file mode 100644
index 00000000000..1bd6a142002
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/rtx-cost-O3-default.c
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/* Verify the MSP430 cost model is working as expected for the default ISA
+   (msp430x) and hwmult (none), when compiling at -O3.  */
+
+char arr[2];
+char a;
+char *ptr;
+
+/*
+** foo:
+** ...
+**     MOV.B   \&a, \&arr\+1
+**     MOV.*   #arr\+2, \&ptr
+** ...
+*/
+
+void
+foo (void)
+{
+  arr[1] = a;
+  ptr = arr + 2;
+}
+
+extern void ext (void);
+
+/*
+** bar:
+** ...
+**     CALL.*  #ext
+**     CALL.*  #ext
+** ...
+*/
+
+void
+bar (void)
+{
+  ext ();
+  ext ();
+}
diff --git a/gcc/testsuite/gcc.target/msp430/rtx-cost-O3-f5series.c 
b/gcc/testsuite/gcc.target/msp430/rtx-cost-O3-f5series.c
new file mode 100644
index 00000000000..1e48625f2e5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/rtx-cost-O3-f5series.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mhwmult=f5series" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/* Verify the MSP430 cost model is working as expected for the default ISA
+   (msp430x) and f5series hwmult, when compiling at -O3.  */
+
+volatile unsigned long a;
+volatile unsigned int b;
+volatile unsigned long c;
+unsigned long res1;
+unsigned long res2;
+unsigned long res3;
+
+/*
+** foo:
+** ...
+**     MOV.B   #16, R14
+**     CALL.*  #__mspabi_slll
+** ...
+**     MOV.*   \&res2.*
+** ...
+**     RLA.*RLC.*
+** ...
+**     MOV.*   \&res3.*
+** ...
+**     RLA.*RLC.*
+** ...
+*/
+void foo (void)
+{
+  /* Use the shift library function for this.  */
+  res1 = (a << 16) | b;
+  /* Emit 7 inline shifts for this.  */
+  res2 *= 128;
+  /* Perform this multiplication inline, using addition and shifts.  */
+  res3 *= 100;
+}
diff --git a/gcc/testsuite/gcc.target/msp430/rtx-cost-Os-default.c 
b/gcc/testsuite/gcc.target/msp430/rtx-cost-Os-default.c
new file mode 100644
index 00000000000..8f3d1b28049
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/rtx-cost-Os-default.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-Os" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/* Verify the MSP430 cost model is working as expected for the default ISA
+   (msp430x) and hwmult (none), when compiling at -Os.  */
+
+char arr[2];
+char a;
+char *ptr;
+
+/*
+** foo:
+** ...
+**     MOV.B   \&a, \&arr\+1
+**     MOV.*   #arr\+2, \&ptr
+** ...
+*/
+
+void
+foo (void)
+{
+  arr[1] = a;
+  ptr = arr + 2;
+}
+
+extern void ext (void);
+
+/*
+** bar:
+** ...
+**     MOV.*   #ext, R10
+**     CALL.*  R10
+**     CALL.*  R10
+** ...
+*/
+
+void
+bar (void)
+{
+  ext ();
+  ext ();
+}
diff --git a/gcc/testsuite/gcc.target/msp430/rtx-cost-Os-f5series.c 
b/gcc/testsuite/gcc.target/msp430/rtx-cost-Os-f5series.c
new file mode 100644
index 00000000000..bb37f9083d9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/rtx-cost-Os-f5series.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-Os -mhwmult=f5series" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/* Verify the MSP430 cost model is working as expected for the default ISA
+   (msp430x) and f5series hwmult, when compiling at -Os.  */
+
+volatile unsigned long a;
+volatile unsigned int b;
+volatile unsigned long c;
+unsigned long res1;
+unsigned long res2;
+unsigned long res3;
+
+/*
+** foo:
+** ...
+**     MOV.B   #16, R14
+**     CALL.*  #__mspabi_slll
+** ...
+**     MOV.B   #7, R14
+**     CALL.*  #__mspabi_slll
+** ...
+**     MOV.B   #100, R14
+**     MOV.B   #0, R15
+** ...
+**     CALL.*  #__mulsi2_f5
+** ...
+*/
+void foo (void)
+{
+  /* Use the shift library function for this.  */
+  res1 = (a << 16) | b;
+  /* Likewise.  */
+  res2 *= 128;
+  /* Use the hardware multiply library function for this.  */
+  res3 *= 100;
+}
-- 
2.27.0

Reply via email to