@@ -300,6 +300,8 @@ static bool arm_asm_elf_flags_numeric (unsigned int flags, unsigned int *num);
static unsigned int arm_elf_section_type_flags (tree decl, const char *name,
int reloc);
static void arm_expand_divmod_libfunc (rtx, machine_mode, rtx, rtx, rtx *, rtx *);
+static bool arm_use_blocks_for_constant_p (machine_mode var, const_rtx x);
+
/* Table of machine attributes. */
static const struct attribute_spec arm_attribute_table[] =
@@ -738,6 +740,9 @@ static const struct attribute_spec arm_attribute_table[] =
#undef TARGET_EXPAND_DIVMOD_LIBFUNC
#define TARGET_EXPAND_DIVMOD_LIBFUNC arm_expand_divmod_libfunc
+#undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
+#define TARGET_USE_BLOCKS_FOR_CONSTANT_P arm_use_blocks_for_constant_p
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* Obstack for minipool constant handling. */
@@ -15983,10 +15988,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);
}
@@ -29668,4 +29669,14 @@ arm_expand_divmod_libfunc (rtx libfunc, machine_mode mode,
*rem_p = remainder;
}
+/* Implements the TARGET_USE_BLOCKS_FOR_CONSTANT_P hook.
+
+ If we have disabled the generation of constants inside a literal pool, then
+ this function returns false. Otherwise, return true. */
+
+static bool
+arm_use_blocks_for_constant_p (machine_mode /* var */, const_rtx /* x */)
+{
+ return !arm_disable_literal_pool;
+}
#include "gt-arm.h"
@@ -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")))
@@ -5846,8 +5842,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,
@@ -2059,3 +2059,40 @@
;; 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
+ && !(TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE
+ && vfp3_const_double_rtx (operands[1]))"
+ "#"
+ "&& !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 ((int) buf[0]);
+ operands[3] = GEN_INT ((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
+ && !(TARGET_HARD_FLOAT && vfp3_const_double_rtx (operands[1]))"
+ "#"
+ "&& !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 ((int) buf);
+ operands[1] = gen_reg_rtx (SFmode);
+ ")
new file mode 100644
@@ -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;
+}
new file mode 100644
@@ -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);
+}
new file mode 100644
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_cortex_m } */
+/* { dg-require-effective-target arm_thumb2_ok } */
+/* { dg-require-effective-target arm_vfp_ok } */
+/* { dg-skip-if "do not override -mfloat-abi" { *-*-* } { "-mfloat-abi=*" } { "-mfloat-abi=hard" } } */
+/* { dg-options "-O2 -mthumb -mfloat-abi=hard -mslow-flash-data" } */
+
+double __attribute__ ((target ("fpu=fpv5-d16")))
+foo (void)
+{
+ return 1.0f;
+}
+
+float __attribute__ ((target ("fpu=fpv5-d16")))
+bar (void)
+{
+ return 1.0f;
+}
+
+float __attribute__ ((target ("fpu=fpv5-sp-d16")))
+baz (void)
+{
+ return 1.0f;
+}
+
+/* { dg-final { scan-assembler-times "#1\\.0e\\+0" 3 } } */
new file mode 100644
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_cortex_m } */
+/* { dg-require-effective-target arm_vfp_ok } */
+/* { 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" } */
+
+double __attribute__ ((target ("fpu=fpv5-sp-d16")))
+foo (void)
+{
+ return 1.0f;
+}
+
+/* { dg-final { scan-assembler-not "#1\\.0e\\+0" } } */
similarity index 100%
rename from gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data.c
rename to gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data-1.c