diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 12adfb96c9a..d5b764d4a8a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2016-09-23 Jiong Wang + Matthew Wahab + + * config/arm/arm.c (output_move_vfp): Weaken assert to allow + HImode. + (arm_hard_regno_mode_ok): Allow HImode values in VFP registers. + * config/arm/arm.md (*movhi_bytes): Disable when VFP registers are + available. Also fix some white-space. + * config/arm/vfp.md (*arm_movhi_vfp): New. + (*thumb2_movhi_vfp): New. + 2016-09-23 Matthew Wahab * config/arm/arm-c.c (arm_cpu_builtins): Define diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 664c5820257..04c73d98e34 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -18722,6 +18722,7 @@ output_move_vfp (rtx *operands) gcc_assert ((mode == HFmode && TARGET_HARD_FLOAT && TARGET_VFP) || mode == SFmode || mode == DFmode + || mode == HImode || mode == SImode || mode == DImode || (TARGET_NEON && VALID_NEON_DREG_MODE (mode))); @@ -23515,6 +23516,10 @@ arm_hard_regno_mode_ok (unsigned int regno, machine_mode mode) if (mode == HFmode) return VFP_REGNO_OK_FOR_SINGLE (regno); + /* VFP registers can hold HImode values. */ + if (mode == HImode) + return VFP_REGNO_OK_FOR_SINGLE (regno); + if (TARGET_NEON) return (VALID_NEON_DREG_MODE (mode) && VFP_REGNO_OK_FOR_DOUBLE (regno)) || (VALID_NEON_QREG_MODE (mode) diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 4df856a98d7..fe4c6e79e0d 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -6700,7 +6700,7 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,r") (match_operand:HI 1 "general_operand" "rIk,K,n,r,mi"))] "TARGET_ARM - && arm_arch4 + && arm_arch4 && !(TARGET_HARD_FLOAT && TARGET_VFP) && (register_operand (operands[0], HImode) || register_operand (operands[1], HImode))" "@ @@ -6726,7 +6726,7 @@ (define_insn "*movhi_bytes" [(set (match_operand:HI 0 "s_register_operand" "=r,r,r") (match_operand:HI 1 "arm_rhs_operand" "I,rk,K"))] - "TARGET_ARM" + "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_VFP)" "@ mov%?\\t%0, %1\\t%@ movhi mov%?\\t%0, %1\\t%@ movhi @@ -6734,7 +6734,7 @@ [(set_attr "predicable" "yes") (set_attr "type" "mov_imm,mov_reg,mvn_imm")] ) - + ;; We use a DImode scratch because we may occasionally need an additional ;; temporary if the address isn't offsettable -- push_reload doesn't seem ;; to take any notice of the "o" constraints on reload_memory_operand operand. diff --git a/gcc/config/arm/vfp.md b/gcc/config/arm/vfp.md index 9750ba16260..d7c874aa08e 100644 --- a/gcc/config/arm/vfp.md +++ b/gcc/config/arm/vfp.md @@ -18,6 +18,99 @@ ;; along with GCC; see the file COPYING3. If not see ;; . */ +;; Patterns for HI moves which provide more data transfer instructions when VFP +;; support is enabled. +(define_insn "*arm_movhi_vfp" + [(set + (match_operand:HI 0 "nonimmediate_operand" + "=rk, r, r, m, r, *t, r, *t") + (match_operand:HI 1 "general_operand" + "rIk, K, n, r, mi, r, *t, *t"))] + "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP + && (register_operand (operands[0], HImode) + || register_operand (operands[1], HImode))" +{ + switch (which_alternative) + { + case 0: + return "mov%?\t%0, %1\t%@ movhi"; + case 1: + return "mvn%?\t%0, #%B1\t%@ movhi"; + case 2: + return "movw%?\t%0, %L1\t%@ movhi"; + case 3: + return "strh%?\t%1, %0\t%@ movhi"; + case 4: + return "ldrh%?\t%0, %1\t%@ movhi"; + case 5: + case 6: + return "vmov%?\t%0, %1\t%@ int"; + case 7: + return "vmov%?.f32\t%0, %1\t%@ int"; + default: + gcc_unreachable (); + } +} + [(set_attr "predicable" "yes") + (set_attr_alternative "type" + [(if_then_else + (match_operand 1 "const_int_operand" "") + (const_string "mov_imm") + (const_string "mov_reg")) + (const_string "mvn_imm") + (const_string "mov_imm") + (const_string "store1") + (const_string "load1") + (const_string "f_mcr") + (const_string "f_mrc") + (const_string "fmov")]) + (set_attr "pool_range" "*, *, *, *, 256, *, *, *") + (set_attr "neg_pool_range" "*, *, *, *, 244, *, *, *") + (set_attr "length" "4")] +) + +(define_insn "*thumb2_movhi_vfp" + [(set + (match_operand:HI 0 "nonimmediate_operand" + "=rk, r, l, r, m, r, *t, r, *t") + (match_operand:HI 1 "general_operand" + "rk, I, Py, n, r, m, r, *t, *t"))] + "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP + && (register_operand (operands[0], HImode) + || register_operand (operands[1], HImode))" +{ + switch (which_alternative) + { + case 0: + case 1: + case 2: + return "mov%?\t%0, %1\t%@ movhi"; + case 3: + return "movw%?\t%0, %L1\t%@ movhi"; + case 4: + return "strh%?\t%1, %0\t%@ movhi"; + case 5: + return "ldrh%?\t%0, %1\t%@ movhi"; + case 6: + case 7: + return "vmov%?\t%0, %1\t%@ int"; + case 8: + return "vmov%?.f32\t%0, %1\t%@ int"; + default: + gcc_unreachable (); + } +} + [(set_attr "predicable" "yes") + (set_attr "predicable_short_it" + "yes, no, yes, no, no, no, no, no, no") + (set_attr "type" + "mov_reg, mov_imm, mov_imm, mov_imm, store1, load1,\ + f_mcr, f_mrc, fmov") + (set_attr "pool_range" "*, *, *, *, *, 4094, *, *, *") + (set_attr "neg_pool_range" "*, *, *, *, *, 250, *, *, *") + (set_attr "length" "2, 4, 2, 4, 4, 4, 4, 4, 4")] +) + ;; SImode moves ;; ??? For now do not allow loading constants into vfp regs. This causes ;; problems because small constants get converted into adds. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f2fb03ca693..f19e24b883f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2016-09-23 Matthew Wahab + + * gcc.target/arm/short-vfp-1.c: New. + 2016-09-23 Matthew Wahab * gcc.target/arm/attr-fp16-arith-1.c: New. diff --git a/gcc/testsuite/gcc.target/arm/short-vfp-1.c b/gcc/testsuite/gcc.target/arm/short-vfp-1.c new file mode 100644 index 00000000000..d96c7631798 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/short-vfp-1.c @@ -0,0 +1,45 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_vfp_ok } +/* { dg-options "-mfpu=vfp" } */ + +int +test_sisf (float x) +{ + return (int)x; +} + +short +test_hisf (float x) +{ + return (short)x; +} + +float +test_sfsi (int x) +{ + return (float)x; +} + +float +test_sfhi (short x) +{ + return (float)x; +} + +short +test_hisi (int x) +{ + return (short)x; +} + +int +test_sihi (short x) +{ + return (int)x; +} + +/* {dg-final { scan-assembler-times {vcvt\.s32\.f32\ts[0-9]+,s[0-9]+} 2 }} */ +/* {dg-final { scan-assembler-times {vcvt\.f32\.s32\ts[0-9]+,s[0-9]+} 2 }} */ +/* {dg-final { scan-assembler-times {vmov\tr[0-9]+,s[0-9]+} 2 }} */ +/* {dg-final { scan-assembler-times {vmov\ts[0-9]+,r[0-9]+} 2 }} */ +/* {dg-final { scan-assembler-times {sxth\tr[0-9]+,r[0-9]+} 2 }} */