From 88304e3d5507787a5453c9745c42c4c5f4093975 Mon Sep 17 00:00:00 2001
From: Andre Simoes Dias Vieira <andre.simoesdiasvieira@arm.com>
Date: Tue, 30 Aug 2016 13:26:49 +0100
Subject: [PATCH 1/2] gcc32rm-709

Fix disabling of literal pool

mend
---
 gcc/config/arm/arm.c                               | 30 ++-------
 gcc/config/arm/arm.md                              | 13 ++--
 gcc/config/arm/thumb2.md                           | 11 ++++
 gcc/config/arm/vfp.md                              | 34 ++++++++++
 .../gcc.target/arm/thumb2-slow-flash-data-1.c      | 73 ++++++++++++++++++++++
 .../gcc.target/arm/thumb2-slow-flash-data-2.c      | 27 ++++++++
 .../gcc.target/arm/thumb2-slow-flash-data-3.c      | 24 +++++++
 .../gcc.target/arm/thumb2-slow-flash-data.c        | 73 ----------------------
 8 files changed, 179 insertions(+), 106 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data-1.c
 create mode 100644 gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data-2.c
 create mode 100644 gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data-3.c
 delete mode 100644 gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data.c

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 946f308ca84e232af8af6eca4813464914cbd59c..dce2569a2c3867464039e6a57e11acee2b28c423 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -7380,25 +7380,6 @@ thumb2_legitimate_address_p (machine_mode mode, rtx x, int strict_p)
 		  && thumb2_legitimate_index_p (mode, xop0, strict_p)));
     }
 
-  /* Normally we can assign constant values to target registers without
-     the help of constant pool.  But there are cases we have to use constant
-     pool like:
-     1) assign a label to register.
-     2) sign-extend a 8bit value to 32bit and then assign to register.
-
-     Constant pool access in format:
-     (set (reg r0) (mem (symbol_ref (".LC0"))))
-     will cause the use of literal pool (later in function arm_reorg).
-     So here we mark such format as an invalid format, then the compiler
-     will adjust it into:
-     (set (reg r0) (symbol_ref (".LC0")))
-     (set (reg r0) (mem (reg r0))).
-     No extra register is required, and (mem (reg r0)) won't cause the use
-     of literal pools.  */
-  else if (arm_disable_literal_pool && code == SYMBOL_REF
-	   && CONSTANT_POOL_ADDRESS_P (x))
-    return 0;
-
   else if (GET_MODE_CLASS (mode) != MODE_FLOAT
 	   && code == SYMBOL_REF
 	   && CONSTANT_POOL_ADDRESS_P (x)
@@ -8295,7 +8276,7 @@ thumb_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
 static bool
 arm_legitimate_constant_p (machine_mode mode, rtx x)
 {
-  return (!arm_cannot_force_const_mem (mode, x)
+  return (!(arm_cannot_force_const_mem (mode, x) && !arm_disable_literal_pool)
 	  && (TARGET_32BIT
 	      ? arm_legitimate_constant_p_1 (mode, x)
 	      : thumb_legitimate_constant_p (mode, x)));
@@ -8308,6 +8289,9 @@ arm_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
 {
   rtx base, offset;
 
+  if (arm_disable_literal_pool)
+    return true;
+
   if (ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P)
     {
       split_const (x, &base, &offset);
@@ -17173,10 +17157,6 @@ push_minipool_fix (rtx_insn *insn, HOST_WIDE_INT address, rtx *loc,
 int
 arm_max_const_double_inline_cost ()
 {
-  /* Let the value get synthesized to avoid the use of literal pools.  */
-  if (arm_disable_literal_pool)
-    return 99;
-
   return ((optimize_size || arm_ld_sched) ? 3 : 4);
 }
 
@@ -17746,7 +17726,7 @@ arm_reorg (void)
 	  ftmp = last_barrier;
 	}
       else
-        {
+	{
 	  /* ftmp is first fix that we can't fit into this pool and
 	     there no natural barriers that we could use.  Insert a
 	     new barrier in the code somewhere between the previous
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 318db75ece9615412b48943ba197aae364a78a54..80a9fe7c700e46abd5a4d9baade0c18e0d3cbe5a 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -233,10 +233,6 @@
 	       (match_test "arm_restrict_it"))
 	  (const_string "no")
 
-	  (and (eq_attr "use_literal_pool" "yes")
-	       (match_test "arm_disable_literal_pool"))
-	  (const_string "no")
-
 	  (eq_attr "arch_enabled" "no")
 	  (const_string "no")]
 	 (const_string "yes")))
@@ -5853,8 +5849,9 @@
 	(match_operand:ANY64 1 "immediate_operand" ""))]
   "TARGET_32BIT
    && reload_completed
-   && (arm_const_double_inline_cost (operands[1])
-       <= arm_max_const_double_inline_cost ())"
+   && (arm_disable_literal_pool
+       || (arm_const_double_inline_cost (operands[1])
+	   <= arm_max_const_double_inline_cost ()))"
   [(const_int 0)]
   "
   arm_split_constant (SET, SImode, curr_insn,
@@ -6070,7 +6067,7 @@
 
 (define_split
   [(set (match_operand:SI 0 "arm_general_register_operand" "")
-	(match_operand:SI 1 "const_int_operand" ""))]
+	(match_operand 1 "const_int_operand" ""))]
   "TARGET_32BIT
   && (!(const_ok_for_arm (INTVAL (operands[1]))
         || const_ok_for_arm (~INTVAL (operands[1]))))"
@@ -6099,7 +6096,7 @@
 (define_split
   [(set (match_operand:SI 0 "arm_general_register_operand" "")
 	(const:SI (plus:SI (match_operand:SI 1 "general_operand" "")
-			   (match_operand:SI 2 "const_int_operand" ""))))]
+			   (match_operand 2 "const_int_operand" ""))))]
   "TARGET_THUMB
    && TARGET_HAVE_MOVT
    && arm_disable_literal_pool
diff --git a/gcc/config/arm/thumb2.md b/gcc/config/arm/thumb2.md
index ab08288413c3e64911e8d7a8199b9809e0282d8e..217ca36f53130f89e0e0c893035d35505cd150f3 100644
--- a/gcc/config/arm/thumb2.md
+++ b/gcc/config/arm/thumb2.md
@@ -300,6 +300,17 @@
    (set_attr "neg_pool_range" "*,*,*,*,*,0,0,*,*")]
 )
 
+(define_insn "*thumb2_movsi_labelref_insn"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=l")
+    (label_ref (match_operand 1 "" "")))]
+    "TARGET_HAVE_MOVT && arm_disable_literal_pool"
+    "movt%?\\t%0, #:upper16:%l1\;movw%?\\t%0, #:lower16:%l1"
+    [(set_attr "type" "multiple")
+     (set_attr "length" "8")
+     (set_attr "ce_count" "2")
+     (set_attr "predicable" "yes")
+     (set_attr "predicable_short_it" "no")])
+
 (define_insn "tls_load_dot_plus_four"
   [(set (match_operand:SI 0 "register_operand" "=l,l,r,r")
 	(mem:SI (unspec:SI [(match_operand:SI 2 "register_operand" "0,1,0,1")
diff --git a/gcc/config/arm/vfp.md b/gcc/config/arm/vfp.md
index 9750ba16260af5a10defc7cfcecd5e8f78039205..62f7e348e253f8608a9bdb41a42e2997d5a1f24e 100644
--- a/gcc/config/arm/vfp.md
+++ b/gcc/config/arm/vfp.md
@@ -1410,3 +1410,37 @@
 ;; fmdhr et al (VFPv1)
 ;; Support for xD (single precision only) variants.
 ;; fmrrs, fmsrr
+
+;; Split an immediate DF move to two immediate SI moves.
+(define_insn_and_split "no_literal_pool_df_immediate"
+  [(set (match_operand 0 "s_register_operand" "")
+	(match_operand:DF 1 "const_double_operand" ""))]
+  "TARGET_THUMB2 && arm_disable_literal_pool"
+  "#"
+  "&& !reload_completed"
+  [(set (subreg:SI (match_dup 1) 0) (match_dup 2))
+   (set (subreg:SI (match_dup 1) 4) (match_dup 3))
+   (set (match_dup 0) (match_dup 1))]
+  "
+  long buf[2];
+  real_to_target (buf, CONST_DOUBLE_REAL_VALUE (operands[1]), DFmode);
+  operands[2] = GEN_INT (buf[0]);
+  operands[3] = GEN_INT (buf[1]);
+  operands[1] = gen_reg_rtx (DFmode);
+  ")
+
+;; Split an immediate SF move to one immediate SI move.
+(define_insn_and_split "no_literal_pool_sf_immediate"
+  [(set (match_operand 0 "s_register_operand" "")
+	(match_operand:SF 1 "const_double_operand" ""))]
+  "TARGET_THUMB2 && arm_disable_literal_pool"
+  "#"
+  "&& !reload_completed"
+  [(set (subreg:SI (match_dup 1) 0) (match_dup 2))
+   (set (match_dup 0) (match_dup 1))]
+  "
+  long buf;
+  real_to_target (&buf, CONST_DOUBLE_REAL_VALUE (operands[1]), SFmode);
+  operands[2] = GEN_INT (buf);
+  operands[1] = gen_reg_rtx (SFmode);
+  ")
diff --git a/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data-1.c b/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data-1.c
new file mode 100644
index 0000000000000000000000000000000000000000..089a72b67f3af570dbbed248a64a18b8b4e89ba4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data-1.c
@@ -0,0 +1,73 @@
+/* The option -mslow-flash-data is just for performance tuning, it
+   doesn't totally disable the use of literal pools.  But for below
+   simple cases, the use of literal pool should be replaced by
+   movw/movt or read-only constant pool.  */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_cortex_m } */
+/* { dg-require-effective-target arm_thumb2_ok } */
+/* { dg-options "-O2 -mthumb -mslow-flash-data" } */
+
+float sf;
+double df;
+long long l;
+static char *p = "Hello World";
+
+float
+testsf (float *p)
+{
+  if (*p > 1.1234f)
+    return 2.1234f;
+  else
+    return 3.1234f;
+}
+
+double
+testdf (double *p)
+{
+  if (*p > 4.1234)
+    return 2.1234;
+  else
+    return 3.1234;
+}
+
+long long
+testll (long long *p)
+{
+  if (*p > 0x123456789ABCDEFll)
+    return 0x111111111ll;
+  else
+    return 0x222222222ll;
+}
+
+char *
+testchar ()
+{
+  return p + 4;
+}
+
+int
+foo (int a, int b)
+{
+  int i;
+  volatile int *labelref = &&label1;
+
+  if (a > b)
+    {
+      while (i < b)
+	{
+	  a += *labelref;
+	  i += 1;
+	}
+      goto *labelref;
+    }
+  else
+    b = b + 3;
+
+  a = a * b;
+
+label1:
+  return a + b;
+}
+
+/* { dg-final { scan-assembler-not "\\.(float|l\\?double|\d?byte|short|int|long|quad|word)\\s+\[^.\]" } } */
diff --git a/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data-2.c b/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data-2.c
new file mode 100644
index 0000000000000000000000000000000000000000..c52de113809b63986a4621524d68686fc795f7ee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data-2.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_cortex_m } */
+/* { dg-require-effective-target arm_thumb2_ok } */
+/* { dg-skip-if "do not override -mfloat-abi" { *-*-* } { "-mfloat-abi=*" } { "-mfloat-abi=hard" } } */
+/* { dg-options "-O2 -mthumb -mfloat-abi=hard -mslow-flash-data" } */
+
+float f (float);
+
+const float max = 0.01f;
+
+int
+g (float in)
+{
+  if (f (in) + f (in) < max)
+    return 0;
+  return 1;
+}
+
+double foo (void)
+{
+  return 0xF1EC7A5239123AF;
+}
+
+double bar (void)
+{
+  return 0.0f;
+}
diff --git a/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data-3.c b/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data-3.c
new file mode 100644
index 0000000000000000000000000000000000000000..d25ba87413cb949e5e2162dbf4e695e205b01a34
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data-3.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_cortex_m } */
+/* { dg-require-effective-target arm_thumb2_ok } */
+/* { dg-skip-if "do not override -mfloat-abi" { *-*-* } { "-mfloat-abi=*" } { "-mfloat-abi=hard" } } */
+/* { dg-options "-mthumb -mfloat-abi=hard -mslow-flash-data" } */
+
+/* From PR71607 */
+
+float b;
+void fn1 ();
+
+float
+fn2 ()
+{
+  return 1.1f;
+}
+
+void
+fn3 ()
+{
+  float a[2];
+  a[1] = b;
+  fn1 (a);
+}
diff --git a/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data.c b/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data.c
deleted file mode 100644
index 089a72b67f3af570dbbed248a64a18b8b4e89ba4..0000000000000000000000000000000000000000
--- a/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/* The option -mslow-flash-data is just for performance tuning, it
-   doesn't totally disable the use of literal pools.  But for below
-   simple cases, the use of literal pool should be replaced by
-   movw/movt or read-only constant pool.  */
-
-/* { dg-do compile } */
-/* { dg-require-effective-target arm_cortex_m } */
-/* { dg-require-effective-target arm_thumb2_ok } */
-/* { dg-options "-O2 -mthumb -mslow-flash-data" } */
-
-float sf;
-double df;
-long long l;
-static char *p = "Hello World";
-
-float
-testsf (float *p)
-{
-  if (*p > 1.1234f)
-    return 2.1234f;
-  else
-    return 3.1234f;
-}
-
-double
-testdf (double *p)
-{
-  if (*p > 4.1234)
-    return 2.1234;
-  else
-    return 3.1234;
-}
-
-long long
-testll (long long *p)
-{
-  if (*p > 0x123456789ABCDEFll)
-    return 0x111111111ll;
-  else
-    return 0x222222222ll;
-}
-
-char *
-testchar ()
-{
-  return p + 4;
-}
-
-int
-foo (int a, int b)
-{
-  int i;
-  volatile int *labelref = &&label1;
-
-  if (a > b)
-    {
-      while (i < b)
-	{
-	  a += *labelref;
-	  i += 1;
-	}
-      goto *labelref;
-    }
-  else
-    b = b + 3;
-
-  a = a * b;
-
-label1:
-  return a + b;
-}
-
-/* { dg-final { scan-assembler-not "\\.(float|l\\?double|\d?byte|short|int|long|quad|word)\\s+\[^.\]" } } */
-- 
1.9.1

