[PATCH 5/17][ARM] Enable HI mode moves for floating point values.
authorMatthew Wahab <mwahab@gcc.gnu.org>
Fri, 23 Sep 2016 09:15:24 +0000 (09:15 +0000)
committerMatthew Wahab <mwahab@gcc.gnu.org>
Fri, 23 Sep 2016 09:15:24 +0000 (09:15 +0000)
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

gcc/ChangeLog
gcc/config/arm/arm.c
gcc/config/arm/arm.md
gcc/config/arm/vfp.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/arm/short-vfp-1.c [new file with mode: 0644]

index 12adfb96c9a43304adace1a850571f8ec6b911b2..d5b764d4a8ae0ecdab4e1e7abf807d4bd039ea1d 100644 (file)
@@ -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
index 664c5820257e3b77d17347abcee8aa6ecb6ec424..04c73d98e34f8cd97aa38ad08b76b766572b1a57 100644 (file)
@@ -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)
index 4df856a98d7934befdd6f9c942763f998c9f0f26..fe4c6e79e0d215a00437bacbcb417e0c0561d167 100644 (file)
   [(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))"
   "@
 (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
   [(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.
index 9750ba16260af5a10defc7cfcecd5e8f78039205..d7c874aa08ebea69a6ba8dd0e849c687497ab4eb 100644 (file)
 ;; 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.
index f2fb03ca693c375ee6cab57b5227d8ffeda1c9e0..f19e24b883f42a66dbf579a91ff7f4c0b7ebd890 100644 (file)
@@ -1,3 +1,7 @@
+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.
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 (file)
index 0000000..d96c763
--- /dev/null
@@ -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 }} */