Mercurial > hg > CbC > CbC_gcc
diff gcc/config/arm/vfp.md @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
line wrap: on
line diff
--- a/gcc/config/arm/vfp.md Thu Oct 25 07:37:49 2018 +0900 +++ b/gcc/config/arm/vfp.md Thu Feb 13 11:34:05 2020 +0900 @@ -1,5 +1,5 @@ ;; ARM VFP instruction patterns -;; Copyright (C) 2003-2018 Free Software Foundation, Inc. +;; Copyright (C) 2003-2020 Free Software Foundation, Inc. ;; Written by CodeSourcery. ;; ;; This file is part of GCC. @@ -258,8 +258,8 @@ ;; is chosen with length 2 when the instruction is predicated for ;; 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"))] + [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,l,r,r,lk*r,m,*t, r,*t,*t, *Uv") + (match_operand:SI 1 "general_operand" "rk,I,Py,K,j,mi,lk*r, r,*t,*t,*UvTu,*t"))] "TARGET_THUMB2 && TARGET_HARD_FLOAT && ( s_register_operand (operands[0], SImode) || s_register_operand (operands[1], SImode))" @@ -275,37 +275,38 @@ case 4: return \"movw%?\\t%0, %1\"; case 5: + /* 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 6: - return \"ldr%?\\t%0, %1\"; + return \"str%?\\t%1, %0\"; case 7: + return \"vmov%?\\t%0, %1\\t%@ int\"; case 8: - return \"str%?\\t%1, %0\"; + return \"vmov%?\\t%0, %1\\t%@ int\"; case 9: - return \"vmov%?\\t%0, %1\\t%@ int\"; - case 10: - return \"vmov%?\\t%0, %1\\t%@ int\"; - case 11: return \"vmov%?.f32\\t%0, %1\\t%@ int\"; - case 12: case 13: + case 10: case 11: return output_move_vfp (operands); default: gcc_unreachable (); } " [(set_attr "predicable" "yes") - (set_attr "predicable_short_it" "yes,no,yes,no,no,no,no,no,no,no,no,no,no,no") - (set_attr "type" "mov_reg,mov_reg,mov_reg,mvn_reg,mov_imm,load_4,load_4,store_4,store_4,f_mcr,f_mrc,fmov,f_loads,f_stores") - (set_attr "length" "2,4,2,4,4,4,4,4,4,4,4,4,4,4") - (set_attr "pool_range" "*,*,*,*,*,1018,4094,*,*,*,*,*,1018,*") - (set_attr "neg_pool_range" "*,*,*,*,*, 0, 0,*,*,*,*,*,1008,*")] + (set_attr "predicable_short_it" "yes,no,yes,no,no,no,no,no,no,no,no,no") + (set_attr "type" "mov_reg,mov_reg,mov_reg,mvn_reg,mov_imm,load_4,store_4,f_mcr,f_mrc,fmov,f_loads,f_stores") + (set_attr "length" "2,4,2,4,4,4,4,4,4,4,4,4") + (set_attr "pool_range" "*,*,*,*,*,1018,*,*,*,*,1018,*") + (set_attr "neg_pool_range" "*,*,*,*,*, 0,*,*,*,*,1008,*")] ) ;; DImode moves (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"))] + [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r,r,r,r,r,r,m,w,!r,w,w, Uv") + (match_operand:DI 1 "di_operand" "r,rDa,Db,Dc,mi,mi,r,r,w,w,UvTu,w"))] "TARGET_32BIT && TARGET_HARD_FLOAT && ( register_operand (operands[0], DImode) || register_operand (operands[1], DImode)) @@ -321,6 +322,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: @@ -358,32 +363,32 @@ (set_attr "arch" "t2,any,any,any,a,t2,any,any,any,any,any,any")] ) -;; HFmode moves +;; HFmode and BFmode moves -(define_insn "*movhf_vfp_fp16" - [(set (match_operand:HF 0 "nonimmediate_operand" - "= r,m,t,r,t,r,t,t,Um,r") - (match_operand:HF 1 "general_operand" - " m,r,t,r,r,t,Dv,Um,t,F"))] +(define_insn "*mov<mode>_vfp_<mode>16" + [(set (match_operand:HFBF 0 "nonimmediate_operand" + "= ?r,?m,t,r,t,r,t, t, Um,r") + (match_operand:HFBF 1 "general_operand" + " m,r,t,r,r,t,Dv,Um,t, F"))] "TARGET_32BIT && TARGET_VFP_FP16INST - && (s_register_operand (operands[0], HFmode) - || s_register_operand (operands[1], HFmode))" + && (s_register_operand (operands[0], <MODE>mode) + || s_register_operand (operands[1], <MODE>mode))" { switch (which_alternative) { case 0: /* ARM register from memory. */ - return \"ldrh%?\\t%0, %1\\t%@ __fp16\"; + return \"ldrh%?\\t%0, %1\\t%@ __<fporbf>\"; case 1: /* Memory from ARM register. */ - return \"strh%?\\t%1, %0\\t%@ __fp16\"; + return \"strh%?\\t%1, %0\\t%@ __<fporbf>\"; case 2: /* S register from S register. */ - return \"vmov\\t%0, %1\t%@ __fp16\"; + return \"vmov\\t%0, %1\t%@ __<fporbf>\"; case 3: /* ARM register from ARM register. */ - return \"mov%?\\t%0, %1\\t%@ __fp16\"; + return \"mov%?\\t%0, %1\\t%@ __<fporbf>\"; case 4: /* S register from ARM register. */ case 5: /* ARM register from S register. */ case 6: /* S register from immediate. */ - return \"vmov.f16\\t%0, %1\t%@ __fp16\"; + return \"vmov.f16\\t%0, %1\t%@ __<fporbf>\"; case 7: /* S register from memory. */ return \"vld1.16\\t{%z0}, %A1\"; case 8: /* Memory from S register. */ @@ -394,7 +399,7 @@ rtx ops[4]; bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]), - HFmode); + <MODE>mode); ops[0] = operands[0]; ops[1] = GEN_INT (bits); ops[2] = GEN_INT (bits & 0xff00); @@ -437,14 +442,14 @@ (const_int 8))])] ) -(define_insn "*movhf_vfp_neon" - [(set (match_operand:HF 0 "nonimmediate_operand" "= t,Um,r,m,t,r,t,r,r") - (match_operand:HF 1 "general_operand" " Um, t,m,r,t,r,r,t,F"))] +(define_insn "*mov<mode>_vfp_neon" + [(set (match_operand:HFBF 0 "nonimmediate_operand" "= t,Um,?r,?m,t,r,t,r,r") + (match_operand:HFBF 1 "general_operand" " Um, t, m, r,t,r,r,t,F"))] "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_NEON_FP16 && !TARGET_VFP_FP16INST - && ( s_register_operand (operands[0], HFmode) - || s_register_operand (operands[1], HFmode))" + && ( s_register_operand (operands[0], <MODE>mode) + || s_register_operand (operands[1], <MODE>mode))" "* switch (which_alternative) { @@ -453,13 +458,13 @@ case 1: /* memory from S register */ return \"vst1.16\\t{%z1}, %A0\"; case 2: /* ARM register from memory */ - return \"ldrh\\t%0, %1\\t%@ __fp16\"; + return \"ldrh\\t%0, %1\\t%@ __<fporbf>\"; case 3: /* memory from ARM register */ - return \"strh\\t%1, %0\\t%@ __fp16\"; + return \"strh\\t%1, %0\\t%@ __<fporbf>\"; case 4: /* S register from S register */ return \"vmov.f32\\t%0, %1\"; case 5: /* ARM register from ARM register */ - return \"mov\\t%0, %1\\t%@ __fp16\"; + return \"mov\\t%0, %1\\t%@ __<fporbf>\"; case 6: /* S register from ARM register */ return \"vmov\\t%0, %1\"; case 7: /* ARM register from S register */ @@ -470,7 +475,7 @@ rtx ops[4]; bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]), - HFmode); + <MODE>mode); ops[0] = operands[0]; ops[1] = GEN_INT (bits); ops[2] = GEN_INT (bits & 0xff00); @@ -493,26 +498,26 @@ ) ;; FP16 without element load/store instructions. -(define_insn "*movhf_vfp" - [(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,t,r,t,r,r") - (match_operand:HF 1 "general_operand" " m,r,t,r,r,t,F"))] +(define_insn "*mov<mode>_vfp" + [(set (match_operand:HFBF 0 "nonimmediate_operand" "=r,m,t,r,t,r,r") + (match_operand:HFBF 1 "general_operand" " m,r,t,r,r,t,F"))] "TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_NEON_FP16 && !TARGET_VFP_FP16INST - && ( s_register_operand (operands[0], HFmode) - || s_register_operand (operands[1], HFmode))" + && ( s_register_operand (operands[0], <MODE>mode) + || s_register_operand (operands[1], <MODE>mode))" "* switch (which_alternative) { case 0: /* ARM register from memory */ - return \"ldrh\\t%0, %1\\t%@ __fp16\"; + return \"ldrh\\t%0, %1\\t%@ __<fporbf>\"; case 1: /* memory from ARM register */ - return \"strh\\t%1, %0\\t%@ __fp16\"; + return \"strh\\t%1, %0\\t%@ __<fporbf>\"; case 2: /* S register from S register */ return \"vmov.f32\\t%0, %1\"; case 3: /* ARM register from ARM register */ - return \"mov\\t%0, %1\\t%@ __fp16\"; + return \"mov\\t%0, %1\\t%@ __<fporbf>\"; case 4: /* S register from ARM register */ return \"vmov\\t%0, %1\"; case 5: /* ARM register from S register */ @@ -523,7 +528,7 @@ rtx ops[4]; bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]), - HFmode); + <MODE>mode); ops[0] = operands[0]; ops[1] = GEN_INT (bits); ops[2] = GEN_INT (bits & 0xff00); @@ -587,7 +592,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 +681,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))" @@ -864,14 +869,15 @@ if (REGNO (operands[0]) == REGNO (operands[1])) { operands[0] = gen_highpart (SImode, operands[0]); - operands[1] = gen_rtx_XOR (SImode, operands[0], GEN_INT (0x80000000)); + operands[1] = gen_rtx_XOR (SImode, operands[0], + gen_int_mode (0x80000000, SImode)); } else { rtx in_hi, in_lo, out_hi, out_lo; in_hi = gen_rtx_XOR (SImode, gen_highpart (SImode, operands[1]), - GEN_INT (0x80000000)); + gen_int_mode (0x80000000, SImode)); in_lo = gen_lowpart (SImode, operands[1]); out_hi = gen_highpart (SImode, operands[0]); out_lo = gen_lowpart (SImode, operands[0]); @@ -1315,7 +1321,7 @@ (fma:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>") (match_operand:SDF 2 "register_operand" "<F_constraint>") (match_operand:SDF 3 "register_operand" "0")))] - "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA" + "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA <vfp_double_cond>" "vfma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2" [(set_attr "predicable" "yes") (set_attr "type" "ffma<vfp_type>")] @@ -1351,7 +1357,7 @@ "<F_constraint>")) (match_operand:SDF 2 "register_operand" "<F_constraint>") (match_operand:SDF 3 "register_operand" "0")))] - "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA" + "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA <vfp_double_cond>" "vfms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2" [(set_attr "predicable" "yes") (set_attr "type" "ffma<vfp_type>")] @@ -1373,7 +1379,7 @@ (fma:SDF (match_operand:SDF 1 "register_operand" "<F_constraint>") (match_operand:SDF 2 "register_operand" "<F_constraint>") (neg:SDF (match_operand:SDF 3 "register_operand" "0"))))] - "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA" + "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA <vfp_double_cond>" "vfnms%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2" [(set_attr "predicable" "yes") (set_attr "type" "ffma<vfp_type>")] @@ -1396,7 +1402,7 @@ "<F_constraint>")) (match_operand:SDF 2 "register_operand" "<F_constraint>") (neg:SDF (match_operand:SDF 3 "register_operand" "0"))))] - "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA" + "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FMA <vfp_double_cond>" "vfnma%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2" [(set_attr "predicable" "yes") (set_attr "type" "ffma<vfp_type>")] @@ -1593,6 +1599,103 @@ (set_attr "type" "f_flag")] ) +(define_insn "push_fpsysreg_insn" + [(set (mem:SI (post_dec:SI (match_operand:SI 0 "s_register_operand" "+&rk"))) + (unspec_volatile:SI [(match_operand:SI 1 "const_int_operand" "n")] + VUNSPEC_VSTR_VLDR))] + "TARGET_HAVE_FPCXT_CMSE && use_cmse" + { + static char buf[32]; + int fp_sysreg_enum = INTVAL (operands[1]); + + gcc_assert (IN_RANGE (fp_sysreg_enum, 0, NB_FP_SYSREGS - 1)); + + snprintf (buf, sizeof (buf), \"vstr%%?\\t%s, [%%0, #-4]!\", + fp_sysreg_names[fp_sysreg_enum]); + return buf; + } + [(set_attr "predicable" "yes") + (set_attr "type" "store_4")] +) + +(define_insn "pop_fpsysreg_insn" + [(set (mem:SI (post_inc:SI (match_operand:SI 0 "s_register_operand" "+&rk"))) + (unspec_volatile:SI [(match_operand:SI 1 "const_int_operand" "n")] + VUNSPEC_VSTR_VLDR))] + "TARGET_HAVE_FPCXT_CMSE && use_cmse" + { + static char buf[32]; + int fp_sysreg_enum = INTVAL (operands[1]); + + gcc_assert (IN_RANGE (fp_sysreg_enum, 0, NB_FP_SYSREGS - 1)); + + snprintf (buf, sizeof (buf), \"vldr%%?\\t%s, [%%0], #4\", + fp_sysreg_names[fp_sysreg_enum]); + return buf; + } + [(set_attr "predicable" "yes") + (set_attr "type" "load_4")] +) + +;; The operands are validated through the clear_multiple_operation +;; match_parallel predicate rather than through constraints so enable it only +;; after reload. +(define_insn "*clear_vfp_multiple" + [(match_parallel 0 "clear_vfp_multiple_operation" + [(unspec_volatile [(const_int 0)] + VUNSPEC_VSCCLRM_VPR)])] + "TARGET_HAVE_FPCXT_CMSE && use_cmse && reload_completed" + { + int num_regs = XVECLEN (operands[0], 0); + char pattern[30]; + rtx reg; + + strcpy (pattern, \"vscclrm%?\\t{%|\"); + if (num_regs > 1) + { + reg = XEXP (XVECEXP (operands[0], 0, 1), 0); + strcat (pattern, reg_names[REGNO (reg)]); + if (num_regs > 2) + { + strcat (pattern, \"-%|\"); + reg = XEXP (XVECEXP (operands[0], 0, num_regs - 1), 0); + strcat (pattern, reg_names[REGNO (reg)]); + } + strcat (pattern, \", \"); + } + + strcat (pattern, \"VPR}\"); + output_asm_insn (pattern, operands); + return \"\"; + } + [(set_attr "predicable" "yes") + (set_attr "type" "mov_reg")] +) + +(define_insn "lazy_store_multiple_insn" + [(set (match_operand:SI 0 "s_register_operand" "+&rk") + (post_dec:SI (match_dup 0))) + (unspec_volatile [(const_int 0) + (mem:SI (post_dec:SI (match_dup 0)))] + VUNSPEC_VLSTM)] + "use_cmse && reload_completed" + "vlstm%?\\t%0" + [(set_attr "predicable" "yes") + (set_attr "type" "store_4")] +) + +(define_insn "lazy_load_multiple_insn" + [(set (match_operand:SI 0 "s_register_operand" "+&rk") + (post_inc:SI (match_dup 0))) + (unspec_volatile:SI [(const_int 0) + (mem:SI (match_dup 0))] + VUNSPEC_VLLDM)] + "use_cmse && reload_completed" + "vlldm%?\\t%0" + [(set_attr "predicable" "yes") + (set_attr "type" "load_4")] +) + (define_insn_and_split "*cmpsf_split_vfp" [(set (reg:CCFP CC_REGNUM) (compare:CCFP (match_operand:SF 0 "s_register_operand" "t") @@ -1983,39 +2086,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; +} +)