aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Wahab <mwahab@gcc.gnu.org>2016-09-23 09:15:24 +0000
committerMatthew Wahab <mwahab@gcc.gnu.org>2016-09-23 09:15:24 +0000
commit50df9464b86a58d5c959b10c33c1870c0c4c5e48 (patch)
tree582fdcac750944cd89464792e4717977ea423288
parent536b9f42cef7c74e3c92e5eaeb12b8514582907c (diff)
downloadgcc-50df9464b86a58d5c959b10c33c1870c0c4c5e48.zip
gcc-50df9464b86a58d5c959b10c33c1870c0c4c5e48.tar.gz
gcc-50df9464b86a58d5c959b10c33c1870c0c4c5e48.tar.bz2
[PATCH 5/17][ARM] Enable HI mode moves for floating point values.
gcc/ 2016-09-23 Jiong Wang <jiong.wang@arm.com> Matthew Wahab <matthew.wahab@arm.com> * 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. testsuite/ 2016-09-23 Matthew Wahab <matthew.wahab@arm.com> * gcc.target/arm/short-vfp-1.c: New. From-SVN: r240403
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/config/arm/arm.c5
-rw-r--r--gcc/config/arm/arm.md6
-rw-r--r--gcc/config/arm/vfp.md93
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/arm/short-vfp-1.c45
6 files changed, 161 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 12adfb9..d5b764d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+2016-09-23 Jiong Wang <jiong.wang@arm.com>
+ Matthew Wahab <matthew.wahab@arm.com>
+
+ * 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 <matthew.wahab@arm.com>
* config/arm/arm-c.c (arm_cpu_builtins): Define
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 664c582..04c73d9 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 4df856a..fe4c6e7 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 9750ba1..d7c874a 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
;; <http://www.gnu.org/licenses/>. */
+;; 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 f2fb03c..f19e24b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,9 @@
2016-09-23 Matthew Wahab <matthew.wahab@arm.com>
+ * gcc.target/arm/short-vfp-1.c: New.
+
+2016-09-23 Matthew Wahab <matthew.wahab@arm.com>
+
* gcc.target/arm/attr-fp16-arith-1.c: New.
2016-09-23 Matthew Wahab <matthew.wahab@arm.com>
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 0000000..d96c763
--- /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 }} */