Hi Kyrill,

I've tested on armeb-none-eabi with -mslow-flash-data for both
-mfloat-abi=hard and -mfloat-abi=soft. Both show no regression and the
former shows some new PASS.

Regarding the part you are hesitant about, the code was taken from
aarch64_reinterpret_float_as_int in config/aarch64/aarch64.c. I'm not
too keen on splitting the patch unless it's just for review (ie still
committed as one) since the changes really go together. The tighter
predicate and constraint are to prevent normal pattern to match when
-mslow-flash-data is in effect while the new splitter and expander is
to deal with load under those circumstances.

Best regards,

Thomas
On Fri, 30 Nov 2018 at 14:11, Kyrill Tkachov
<kyrylo.tkac...@foss.arm.com> wrote:
>
> Hi Thomas,
>
> On 19/11/18 17:56, Thomas Preudhomme wrote:
> > Hi,
> >
> > Current code to handle -mslow-flash-data in machine description files
> > suffers from a number of issues which this patch fixes:
> >
> > 1) The insn_and_split in vfp.md to load a generic floating-point
> > constant via GPR first and move it to VFP register are guarded by
> > !reload_completed which is forbidden explicitely in the GCC internals
> > documentation section 17.2 point 3;
> >
> > 2) A number of testcase in the testsuite ICEs under -mslow-flash-data
> > when targeting the hardfloat ABI [1];
> >
> > 3) Instructions performing load from literal pool are not disabled.
> >
> > These problems are addressed by 2 separate actions:
> >
> > 1) Making the splitters take a clobber and changing the expanders
> > accordingly to generate a mov with clobber in cases where a literal
> > pool would be used. The splitter can thus be enabled after reload since
> > it does not call gen_reg_rtx anymore;
> >
> > 2) Adding new predicates and constraints to disable literal pool loads
> > in existing instructions when -mslow-flash-data is in effect.
> >
>
> Please split these into two separate patches so we can more clearly see which 
> changes address which problem
>
> > The patch also rework the splitter for DFmode slightly to generate an
> > intermediate DI load instead of 2 intermediate SI loads, thus relying on
> > the existing DI splitters instead of redoing their job. At last, the
> > patch adds some missing arm_fp_ok effective target to some of the
> > slow-flash-data testcases.
> >
> > [1]
> > c-c++-common/Wunused-var-3.c
> > gcc.c-torture/compile/pr72771.c
> > gcc.c-torture/compile/vector-5.c
> > gcc.c-torture/compile/vector-6.c
> > gcc.c-torture/execute/20030914-1.c
> > gcc.c-torture/execute/20050316-1.c
> > gcc.c-torture/execute/pr59643.c
> > gcc.dg/builtin-tgmath-1.c
> > gcc.dg/debug/pr55730.c
> > gcc.dg/graphite/interchange-7.c
> > gcc.dg/pr56890-2.c
> > gcc.dg/pr68474.c
> > gcc.dg/pr80286.c
> > gcc.dg/torture/pr35227.c
> > gcc.dg/torture/pr65077.c
> > gcc.dg/torture/pr86363.c
> > g++.dg/torture/pr81112.C
> > g++.dg/torture/pr82985.C
> > g++.dg/warn/Wunused-var-7.C
> > and a lot more in libstdc++ in special_functions/*_comp_ellint_* and
> > special_functions/*_ellint_* directories.
> >
> > ChangeLog entries are as follows:
> >
> > *** gcc/ChangeLog ***
> >
> > 2018-11-14  Thomas Preud'homme <thomas.preudho...@arm.com>
> >
> >         * config/arm/arm.md (arm_movdi): Split if -mslow-flash-data and
> >         source is a constant that would be loaded by literal pool.
> >         (movsf expander): Generate a no_literal_pool_sf_immediate insn if
> >         -mslow-flash-data is present, targeting hardfloat ABI and source is 
> > a
> >         float constant that cannot be loaded via vmov.
> >         (movdf expander): Likewise but generate a 
> > no_literal_pool_df_immediate
> >         insn.
> >         (arm_movsf_soft_insn): Split if -mslow-flash-data and source is a
> >         float constant that would be loaded by literal pool.
> >         (softfloat constant movsf splitter): Splitter for the above case.
> >         (movdf_soft_insn): Split if -mslow-flash-data and source is a float
> >         constant that would be loaded by literal pool.
> >         (softfloat constant movdf splitter): Splitter for the above case.
> >         * config/arm/constraints.md (Pz): Document existing constraint.
> >         (Ha): Define constraint.
> >         (Tu): Likewise.
> >         * config/arm/predicates.md (hard_sf_operand): New predicate.
> >         (hard_df_operand): Likewise.
> >         * config/arm/thumb2.md (thumb2_movsi_insn): Split if
> >         -mslow-flash-data and constant would be loaded by literal pool.
> >         * constant/arm/vfp.md (thumb2_movsi_vfp): Likewise and disable 
> > constant
> >         load in VFP register.
> >         (movdi_vfp): Likewise.
> >         (thumb2_movsf_vfp): Use hard_sf_operand as predicate for source to
> >         prevent match for a constant load if -mslow-flash-data and constant
> >         cannot be loaded via vmov.  Adapt constraint accordingly by
> >         using Ha instead of E for generic floating-point constant load.
> >         (thumb2_movdf_vfp): Likewise using hard_df_operand predicate 
> > instead.
> >         (no_literal_pool_df_immediate): Add a clobber to use as the
> >         intermediate general purpose register and also enable it after 
> > reload
> >         but disable it constant is a valid FP constant.  Add constraints and
> >         generate a DI intermediate load rather than 2 SI loads.
> >         (no_literal_pool_sf_immediate): Add a clobber to use as the
> >         intermediate general purpose register and also enable it after
> >         reload.
> >
> > *** gcc/testsuite/ChangeLog ***
> >
> > 2018-11-14  Thomas Preud'homme <thomas.preudho...@arm.com>
> >
> >         * gcc.target/arm/thumb2-slow-flash-data-2.c: Require arm_fp_ok
> >         effective target.
> >         * gcc.target/arm/thumb2-slow-flash-data-3.c: Likewise.
> >         * gcc.target/arm/thumb2-slow-flash-data-4.c: Likewise.
> >         * gcc.target/arm/thumb2-slow-flash-data-5.c: Likewise.
> >
> > Testing: Built arm-none-eabi cross compilers for Armv7E-M defaulting to
> > softfloat and hardfloat ABI which showed no regression and some
> > FAIL->PASS for hardfloat ABI. Bootstraped on Arm and Thumb-2 without any
> > regression. Compiled SPEC2k6 without -mslow-flash-data and checked that
> > code generation didn't change.
> >
> > Is this ok for stage3?
> >
> > Best regards,
> >
> > Thomas
>
> diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
> index 
> a773518cefaf8451e77fead9e072ee8ef39f1eb8..a08298bbb9f93fc132aa64a206fad64dcda9ed65
>  100644
> --- a/gcc/config/arm/arm.md
> +++ b/gcc/config/arm/arm.md
> @@ -5831,6 +5831,11 @@
>       case 1:
>       case 2:
>         return \"#\";
> +    case 3:
> +      /* Cannot load it directly, split to load it via MOV / MOVT.  */
> +      if (!MEM_P (operands[1]) && arm_disable_literal_pool)
> +       return \"#\";
> +      /* Fall through.  */
>       default:
>         return output_move_double (operands, true, NULL);
>       }
> @@ -6939,6 +6944,20 @@
>              operands[1] = force_reg (SFmode, operands[1]);
>           }
>       }
> +
> +  /* Cannot load it directly, generate a load with clobber so that it can be
> +     loaded via GPR with MOV / MOVT.  */
> +  if (arm_disable_literal_pool
> +      && (REG_P (operands[0]) || SUBREG_P (operands[0]))
> +      && CONST_DOUBLE_P (operands[1])
> +      && TARGET_HARD_FLOAT
> +      && !vfp3_const_double_rtx (operands[1]))
> +    {
> +      rtx clobreg = gen_reg_rtx (SFmode);
> +      emit_insn (gen_no_literal_pool_sf_immediate (operands[0], operands[1],
> +                                                  clobreg));
> +      DONE;
> +    }
>     "
>   )
>
> @@ -6966,10 +6985,19 @@
>      && TARGET_SOFT_FLOAT
>      && (!MEM_P (operands[0])
>          || register_operand (operands[1], SFmode))"
> -  "@
> -   mov%?\\t%0, %1
> -   ldr%?\\t%0, %1\\t%@ float
> -   str%?\\t%1, %0\\t%@ float"
> +{
> +  switch (which_alternative)
> +    {
> +    case 0: return \"mov%?\\t%0, %1\";
> +    case 1:
> +      /* Cannot load it directly, split to load it via MOV / MOVT.  */
> +      if (!MEM_P (operands[1]) && arm_disable_literal_pool)
> +       return \"#\";
> +      return \"ldr%?\\t%0, %1\\t%@ float\";
> +    case 2: return \"str%?\\t%1, %0\\t%@ float\";
> +    default: gcc_unreachable ();
> +    }
> +}
>     [(set_attr "predicable" "yes")
>      (set_attr "type" "mov_reg,load_4,store_4")
>      (set_attr "arm_pool_range" "*,4096,*")
> @@ -6978,6 +7006,21 @@
>      (set_attr "thumb2_neg_pool_range" "*,0,*")]
>   )
>
> +;; Splitter for the above.
> +(define_split
> +  [(set (match_operand:SF 0 "s_register_operand")
> +       (match_operand:SF 1 "const_double_operand"))]
> +  "arm_disable_literal_pool && TARGET_SOFT_FLOAT"
> +  [(const_int 0)]
> +{
> +  long buf;
> +  real_to_target (&buf, CONST_DOUBLE_REAL_VALUE (operands[1]), SFmode);
> +  rtx cst = gen_int_mode (buf, SImode);
> +  emit_move_insn (simplify_gen_subreg (SImode, operands[0], SFmode, 0), cst);
> +  DONE;
> +}
> +)
> +
>   (define_expand "movdf"
>     [(set (match_operand:DF 0 "general_operand" "")
>         (match_operand:DF 1 "general_operand" ""))]
> @@ -6996,6 +7039,21 @@
>             operands[1] = force_reg (DFmode, operands[1]);
>           }
>       }
> +
> +  /* Cannot load it directly, generate a load with clobber so that it can be
> +     loaded via GPR with MOV / MOVT.  */
> +  if (arm_disable_literal_pool
> +      && (REG_P (operands[0]) || SUBREG_P (operands[0]))
> +      && CONSTANT_P (operands[1])
> +      && TARGET_HARD_FLOAT
> +      && !arm_const_double_rtx (operands[1])
> +      && !(TARGET_VFP_DOUBLE && vfp3_const_double_rtx (operands[1])))
> +    {
> +      rtx clobreg = gen_reg_rtx (DFmode);
> +      emit_insn (gen_no_literal_pool_df_immediate (operands[0], operands[1],
> +                                                  clobreg));
> +      DONE;
> +    }
>     "
>   )
>
> @@ -7055,6 +7113,11 @@
>       case 1:
>       case 2:
>         return \"#\";
> +    case 3:
> +      /* Cannot load it directly, split to load it via MOV / MOVT.  */
> +      if (!MEM_P (operands[1]) && arm_disable_literal_pool)
> +       return \"#\";
> +      /* Fall through.  */
>       default:
>         return output_move_double (operands, true, NULL);
>       }
> @@ -7066,6 +7129,24 @@
>      (set_attr "arm_neg_pool_range" "*,*,*,1004,*")
>      (set_attr "thumb2_neg_pool_range" "*,*,*,0,*")]
>   )
> +
> +;; Splitter for the above.
> +(define_split
> +  [(set (match_operand:DF 0 "s_register_operand")
> +       (match_operand:DF 1 "const_double_operand"))]
> +  "arm_disable_literal_pool && TARGET_SOFT_FLOAT"
> +  [(const_int 0)]
> +{
> +  long buf[2];
> +  int order = BYTES_BIG_ENDIAN ? 1 : 0;
> +  real_to_target (buf, CONST_DOUBLE_REAL_VALUE (operands[1]), DFmode);
> +  unsigned HOST_WIDE_INT ival = zext_hwi (buf[order], 32);
> +  ival |= (zext_hwi (buf[1 - order], 32) << 32);
> +  rtx cst = gen_int_mode (ival, DImode);
> +  emit_move_insn (simplify_gen_subreg (DImode, operands[0], DFmode, 0), cst);
>
> This is the part I'm most hesitant about, especially for big-endian.
> Did you run any armeb tests tahat exercise this?
> Would you not want to use gen_highpart_mode/gen_lowpart that handles all the 
> endianness-subreg subtleties for you?
>
>
> Thanks,
> Kyrill
>
>
>   +  DONE;
> +}
> +)
>
>
>   ;; load- and store-multiple insns
> diff --git a/gcc/config/arm/constraints.md b/gcc/config/arm/constraints.md
> index 
> 7576c6fc401fc5ce25245fa2b740db99169ce7ce..657e540816bdd82cddd23059dea2be19df7eb1bb
>  100644
> --- a/gcc/config/arm/constraints.md
> +++ b/gcc/config/arm/constraints.md
> @@ -31,9 +31,10 @@
>   ;; 'H' was previously used for FPA.
>
>   ;; The following multi-letter normal constraints have been used:
> -;; in ARM/Thumb-2 state: Da, Db, Dc, Dd, Dn, Dl, DL, Do, Dv, Dy, Di, Dt, Dp, 
> Dz
> +;; in ARM/Thumb-2 state: Da, Db, Dc, Dd, Dn, Dl, DL, Do, Dv, Dy, Di, Dt, Dp,
> +;;                      Dz, Tu
>   ;; in Thumb-1 state: Pa, Pb, Pc, Pd, Pe
> -;; in Thumb-2 state: Pj, PJ, Ps, Pt, Pu, Pv, Pw, Px, Py
> +;; in Thumb-2 state: Ha, Pj, PJ, Ps, Pt, Pu, Pv, Pw, Px, Py, Pz
>   ;; in all states: Pf
>
>   ;; The following memory constraints have been used:
> @@ -234,6 +235,12 @@
>    (and (match_code "const_double")
>         (match_test "TARGET_32BIT && arm_const_double_rtx (op)")))
>
> +(define_constraint "Ha"
> +  "@internal In ARM / Thumb-2 a float constant iff literal pools are 
> allowed."
> +  (and (match_code "const_double")
> +       (match_test "satisfies_constraint_E (op)")
> +       (match_test "!arm_disable_literal_pool")))
> +
>   (define_constraint "Dz"
>    "@internal
>     In ARM/Thumb-2 state a vector of constant zeros."
> @@ -351,6 +358,12 @@
>          (match_test "TARGET_32BIT
>                     && vfp3_const_double_for_bits (op) > 0")))
>
> +(define_constraint "Tu"
> +  "@internal In ARM / Thumb-2 an integer constant iff literal pools are
> +   allowed."
> +  (and (match_test "CONSTANT_P (op)")
> +       (match_test "!arm_disable_literal_pool")))
> +
>   (define_register_constraint "Ts" "(arm_restrict_it) ? LO_REGS : 
> GENERAL_REGS"
>    "For arm_restrict_it the core registers @code{r0}-@code{r7}.  GENERAL_REGS 
> otherwise.")
>
> diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md
> index 
> 7e198f9bce441c55913615e4c601a760d7e62c20..f73264cc2a07cacec5e7c4e31ce12299a1fadd0b
>  100644
> --- a/gcc/config/arm/predicates.md
> +++ b/gcc/config/arm/predicates.md
> @@ -456,6 +456,24 @@
>          (and (match_code "reg,subreg,mem")
>             (match_operand 0 "nonimmediate_soft_df_operand"))))
>
> +;; Predicate for thumb2_movsf_vfp.  Compared to general_operand, this
> +;; forbids constant loaded via literal pool iff literal pools are disabled.
> +(define_predicate "hard_sf_operand"
> +  (and (match_operand 0 "general_operand")
> +       (ior (not (match_code "const_double"))
> +           (not (match_test "arm_disable_literal_pool"))
> +           (match_test "satisfies_constraint_Dv (op)"))))
> +
> +;; Predicate for thumb2_movdf_vfp.  Compared to soft_df_operand used in
> +;; movdf_soft_insn, this forbids constant loaded via literal pool iff
> +;; literal pools are disabled.
> +(define_predicate "hard_df_operand"
> +  (and (match_operand 0 "soft_df_operand")
> +       (ior (not (match_code "const_double"))
> +           (not (match_test "arm_disable_literal_pool"))
> +           (match_test "satisfies_constraint_Dy (op)")
> +           (match_test "satisfies_constraint_G (op)"))))
> +
>   (define_special_predicate "load_multiple_operation"
>     (match_code "parallel")
>   {
> diff --git a/gcc/config/arm/thumb2.md b/gcc/config/arm/thumb2.md
> index 
> c42670f8643c3286bc5abf537d4fd0483cba68ac..727ceb9b37957efbc7ab8809f57e8825deb6b1df
>  100644
> --- a/gcc/config/arm/thumb2.md
> +++ b/gcc/config/arm/thumb2.md
> @@ -252,16 +252,26 @@
>     "TARGET_THUMB2 && !TARGET_IWMMXT && !TARGET_HARD_FLOAT
>      && (   register_operand (operands[0], SImode)
>          || register_operand (operands[1], SImode))"
> -  "@
> -   mov%?\\t%0, %1
> -   mov%?\\t%0, %1
> -   mov%?\\t%0, %1
> -   mvn%?\\t%0, #%B1
> -   movw%?\\t%0, %1
> -   ldr%?\\t%0, %1
> -   ldr%?\\t%0, %1
> -   str%?\\t%1, %0
> -   str%?\\t%1, %0"
> +{
> +  switch (which_alternative)
> +    {
> +    case 0:
> +    case 1:
> +    case 2:
> +      return \"mov%?\\t%0, %1\";
> +    case 3: return \"mvn%?\\t%0, #%B1\";
> +    case 4: return \"movw%?\\t%0, %1\";
> +    case 5:
> +    case 6:
> +      /* Cannot load it directly, split to load it via MOV / MOVT.  */
> +      if (!MEM_P (operands[1]) && arm_disable_literal_pool)
> +       return \"#\";
> +      return \"ldr%?\\t%0, %1\";
> +    case 7:
> +    case 8: return \"str%?\\t%1, %0\";
> +    default: gcc_unreachable ();
> +    }
> +}
>     [(set_attr "type" 
> "mov_reg,mov_imm,mov_imm,mvn_imm,mov_imm,load_4,load_4,store_4,store_4")
>      (set_attr "length" "2,4,2,4,4,4,4,4,4")
>      (set_attr "predicable" "yes")
> diff --git a/gcc/config/arm/vfp.md b/gcc/config/arm/vfp.md
> index 
> 611ebe2d83698e3129df6c55a03e4f5f33c891e7..f3d4f30cb53d82e2ffd2c4fcaad2cc873d97c24b
>  100644
> --- a/gcc/config/arm/vfp.md
> +++ b/gcc/config/arm/vfp.md
> @@ -259,7 +259,7 @@
>   ;; arm_restrict_it.
>   (define_insn "*thumb2_movsi_vfp"
>     [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,l,r,r, l,*hk,m, 
> *m,*t, r,*t,*t,  *Uv")
> -       (match_operand:SI 1 "general_operand"      "rk,I,Py,K,j,mi,*mi,l,*hk, 
> r,*t,*t,*Uvi,*t"))]
> +       (match_operand:SI 1 "general_operand"      "rk,I,Py,K,j,mi,*mi,l,*hk, 
> r,*t,*t,*UvTu,*t"))]
>     "TARGET_THUMB2 && TARGET_HARD_FLOAT
>      && (   s_register_operand (operands[0], SImode)
>          || s_register_operand (operands[1], SImode))"
> @@ -276,6 +276,9 @@
>         return \"movw%?\\t%0, %1\";
>       case 5:
>       case 6:
> +      /* Cannot load it directly, split to load it via MOV / MOVT.  */
> +      if (!MEM_P (operands[1]) && arm_disable_literal_pool)
> +       return \"#\";
>         return \"ldr%?\\t%0, %1\";
>       case 7:
>       case 8:
> @@ -305,7 +308,7 @@
>
>   (define_insn "*movdi_vfp"
>     [(set (match_operand:DI 0 "nonimmediate_di_operand" 
> "=r,r,r,r,q,q,m,w,!r,w,w, Uv")
> -       (match_operand:DI 1 "di_operand"              
> "r,rDa,Db,Dc,mi,mi,q,r,w,w,Uvi,w"))]
> +       (match_operand:DI 1 "di_operand"              
> "r,rDa,Db,Dc,mi,mi,q,r,w,w,UvTu,w"))]
>     "TARGET_32BIT && TARGET_HARD_FLOAT
>      && (   register_operand (operands[0], DImode)
>          || register_operand (operands[1], DImode))
> @@ -321,6 +324,10 @@
>         return \"#\";
>       case 4:
>       case 5:
> +      /* Cannot load it directly, split to load it via MOV / MOVT.  */
> +      if (!MEM_P (operands[1]) && arm_disable_literal_pool)
> +       return \"#\";
> +      /* Fall through.  */
>       case 6:
>         return output_move_double (operands, true, NULL);
>       case 7:
> @@ -587,7 +594,7 @@
>
>   (define_insn "*thumb2_movsf_vfp"
>     [(set (match_operand:SF 0 "nonimmediate_operand" "=t,?r,t, t  ,Uv,r 
> ,m,t,r")
> -       (match_operand:SF 1 "general_operand"      " ?r,t,Dv,UvE,t, 
> mE,r,t,r"))]
> +       (match_operand:SF 1 "hard_sf_operand"      " ?r,t,Dv,UvHa,t, 
> mHa,r,t,r"))]
>     "TARGET_THUMB2 && TARGET_HARD_FLOAT
>      && (   s_register_operand (operands[0], SFmode)
>          || s_register_operand (operands[1], SFmode))"
> @@ -676,7 +683,7 @@
>
>   (define_insn "*thumb2_movdf_vfp"
>     [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,w,w  
> ,Uv,r ,m,w,r")
> -       (match_operand:DF 1 "soft_df_operand"              " ?r,w,Dy,G,UvF,w, 
> mF,r, w,r"))]
> +       (match_operand:DF 1 "hard_df_operand"              " 
> ?r,w,Dy,G,UvHa,w, mHa,r, w,r"))]
>     "TARGET_THUMB2 && TARGET_HARD_FLOAT
>      && (   register_operand (operands[0], DFmode)
>          || register_operand (operands[1], DFmode))"
> @@ -1983,39 +1990,50 @@
>   ;; Support for xD (single precision only) variants.
>   ;; fmrrs, fmsrr
>
> -;; Split an immediate DF move to two immediate SI moves.
> +;; Load a DF immediate via GPR (where combinations of MOV and MOVT can be 
> used)
> +;; and then move it into a VFP register.
>   (define_insn_and_split "no_literal_pool_df_immediate"
> -  [(set (match_operand:DF 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]))"
> +  [(set (match_operand:DF 0 "s_register_operand" "=w")
> +       (match_operand:DF 1 "const_double_operand" "F"))
> +   (clobber (match_operand:DF 2 "s_register_operand" "=r"))]
> +  "arm_disable_literal_pool
> +   && TARGET_HARD_FLOAT
> +   && !arm_const_double_rtx (operands[1])
> +   && !(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))]
> -  "
> +  ""
> +  [(const_int 0)]
> +{
>     long buf[2];
> +  int order = BYTES_BIG_ENDIAN ? 1 : 0;
>     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);
> -  ")
> +  unsigned HOST_WIDE_INT ival = zext_hwi (buf[order], 32);
> +  ival |= (zext_hwi (buf[1 - order], 32) << 32);
> +  rtx cst = gen_int_mode (ival, DImode);
> +  emit_move_insn (simplify_gen_subreg (DImode, operands[2], DFmode, 0), cst);
> +  emit_move_insn (operands[0], operands[2]);
> +  DONE;
> +}
> +)
>
> -;; Split an immediate SF move to one immediate SI move.
> +;; Load a SF immediate via GPR (where combinations of MOV and MOVT can be 
> used)
> +;; and then move it into a VFP register.
>   (define_insn_and_split "no_literal_pool_sf_immediate"
> -  [(set (match_operand:SF 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]))"
> +  [(set (match_operand:SF 0 "s_register_operand" "=t")
> +       (match_operand:SF 1 "const_double_operand" "E"))
> +   (clobber (match_operand:SF 2 "s_register_operand" "=r"))]
> +  "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))]
> -  "
> +  ""
> +  [(const_int 0)]
> +{
>     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);
> -  ")
> +  rtx cst = gen_int_mode (buf, SImode);
> +  emit_move_insn (simplify_gen_subreg (SImode, operands[2], SFmode, 0), cst);
> +  emit_move_insn (operands[0], operands[2]);
> +  DONE;
> +}
> +)
> 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
> index 
> 90bd44e27e5c53d34f2816f4d6320acbc1dc709b..231243759cfe486c390ca27f10bd06177f60bd43
>  100644
> --- a/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data-2.c
> +++ b/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data-2.c
> @@ -1,6 +1,7 @@
>   /* { dg-do compile } */
>   /* { dg-require-effective-target arm_cortex_m } */
>   /* { dg-require-effective-target arm_thumb2_ok } */
> +/* { dg-require-effective-target arm_fp_ok } */
>   /* { dg-skip-if "avoid conflicts with multilib options" { *-*-* } { 
> "-mcpu=*" } { "-mcpu=cortex-m4" "-mcpu=cortex-m7" } } */
>   /* { dg-skip-if "do not override -mfloat-abi" { *-*-* } { "-mfloat-abi=*" } 
> { "-mfloat-abi=hard" } } */
>   /* { dg-skip-if "-mslow-flash-data and -mword-relocations incompatible" { 
> *-*-* } { "-mword-relocations" } } */
> 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
> index 
> 5d9cd9c4df28837b81b2de48c25d38cdf2c15999..27e72ec20863866acdc5e7fea632bc6880678dfd
>  100644
> --- a/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data-3.c
> +++ b/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data-3.c
> @@ -1,6 +1,7 @@
>   /* { dg-do compile } */
>   /* { dg-require-effective-target arm_cortex_m } */
>   /* { dg-require-effective-target arm_thumb2_ok } */
> +/* { dg-require-effective-target arm_fp_ok } */
>   /* { dg-skip-if "avoid conflicts with multilib options" { *-*-* } { 
> "-mcpu=*" } { "-mcpu=cortex-m4" "-mcpu=cortex-m7" } } */
>   /* { dg-skip-if "do not override -mfloat-abi" { *-*-* } { "-mfloat-abi=*" } 
> { "-mfloat-abi=hard" } } */
>   /* { dg-skip-if "-mslow-flash-data and -mword-relocations incompatible" { 
> *-*-* } { "-mword-relocations" } } */
> diff --git a/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data-4.c 
> b/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data-4.c
> index 
> 0eeddd5e6ec1f42a96fc6220277f9ecb7cad44f5..8dbe87a1e68d5eb2edfd8259948988fbe0658ced
>  100644
> --- a/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data-4.c
> +++ b/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data-4.c
> @@ -1,6 +1,7 @@
>   /* { dg-do compile } */
>   /* { dg-require-effective-target arm_cortex_m } */
>   /* { dg-require-effective-target arm_thumb2_ok } */
> +/* { dg-require-effective-target arm_fp_ok } */
>   /* { dg-skip-if "avoid conflicts with multilib options" { *-*-* } { 
> "-mcpu=*" } { "-mcpu=cortex-m4" "-mcpu=cortex-m7" } } */
>   /* { dg-skip-if "do not override -mfloat-abi" { *-*-* } { "-mfloat-abi=*" } 
> { "-mfloat-abi=hard" } } */
>   /* { dg-skip-if "-mslow-flash-data and -mword-relocations incompatible" { 
> *-*-* } { "-mword-relocations" } } */
> diff --git a/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data-5.c 
> b/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data-5.c
> index 
> 7d52f3801b6d4b62b27833871ac830d6d077894d..b98eb7624e42b5a7f4a11c604c7d2826339bcfd5
>  100644
> --- a/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data-5.c
> +++ b/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data-5.c
> @@ -1,6 +1,7 @@
>   /* { dg-do compile } */
>   /* { dg-require-effective-target arm_cortex_m } */
>   /* { dg-require-effective-target arm_thumb2_ok } */
> +/* { dg-require-effective-target arm_fp_ok } */
>   /* { dg-skip-if "avoid conflicts with multilib options" { *-*-* } { 
> "-mcpu=*" } { "-mcpu=cortex-m4" "-mcpu=cortex-m7" } } */
>   /* { dg-skip-if "do not override -mfloat-abi" { *-*-* } { "-mfloat-abi=*" } 
> { "-mfloat-abi=hard" } } */
>   /* { dg-skip-if "-mslow-flash-data and -mword-relocations incompatible" { 
> *-*-* } { "-mword-relocations" } } */
>
>
>

Reply via email to