arm.h (TARGET_HAVE_MOVT): Include ARMv8-M as having MOVT.
authorThomas Preud'homme <thomas.preudhomme@arm.com>
Wed, 13 Jul 2016 10:54:01 +0000 (10:54 +0000)
committerThomas Preud'homme <thopre01@gcc.gnu.org>
Wed, 13 Jul 2016 10:54:01 +0000 (10:54 +0000)
2016-07-13  Thomas Preud'homme  <thomas.preudhomme@arm.com>

    gcc/
    * config/arm/arm.h (TARGET_HAVE_MOVT): Include ARMv8-M as having MOVT.
    * config/arm/arm.c (arm_arch_name): (const_ok_for_op): Check MOVT/MOVW
    availability with TARGET_HAVE_MOVT.
    (thumb_legitimate_constant_p): Strip the high part of a label_ref.
    (thumb1_rtx_costs): Also return 0 if setting a half word constant and
    MOVW is available and replace (unsigned HOST_WIDE_INT) INTVAL by
    UINTVAL.
    (thumb1_size_rtx_costs): Make set of half word constant also cost 1
    extra instruction if MOVW is available.  Use a cost variable
    incremented by COSTS_N_INSNS (1) when the condition match rather than
    returning an arithmetic expression based on COSTS_N_INSNS.  Make
    constant with bottom half word zero cost 2 instruction if MOVW is
    available.
    * config/arm/arm.md (define_attr "arch"): Add v8mb.
    (define_attr "arch_enabled"): Set to yes if arch value is v8mb and
    target is ARMv8-M Baseline.
    (arm_movt): New unpredicable alternative for ARMv8-M Baseline.
    (arm_movtas_ze): Likewise.
    * config/arm/thumb1.md (thumb1_movdi_insn): Add ARMv8-M Baseline only
    alternative for constants satisfying j constraint.
    (thumb1_movsi_insn): Likewise.
    (movsi splitter for K alternative): Tighten condition to not trigger
    if movt is available and j constraint is satisfied.
    (Pe immediate splitter): Likewise.
    (thumb1_movhi_insn): Add ARMv8-M Baseline only alternative for
    constant fitting in an halfword to use MOVW.
    * doc/sourcebuild.texi (arm_thumb1_movt_ok): Document new ARM
    effective target.

    gcc/testsuite/
    * lib/target-supports.exp (check_effective_target_arm_thumb1_movt_ok):
    Define effective target.
    * gcc.target/arm/pr42574.c: Require arm_thumb1_ok and
    !arm_thumb1_movt_ok to exclude ARMv8-M Baseline.
    * gcc.target/arm/movhi_movw.c: New test.
    * gcc.target/arm/movsi_movw.c: Likewise.
    * gcc.target/arm/movdi_movw.c: Likewise.

From-SVN: r238288

12 files changed:
gcc/ChangeLog
gcc/config/arm/arm.c
gcc/config/arm/arm.h
gcc/config/arm/arm.md
gcc/config/arm/thumb1.md
gcc/doc/sourcebuild.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/arm/movdi_movw.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/movhi_movw.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/movsi_movw.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/pr42574.c
gcc/testsuite/lib/target-supports.exp

index e42e288653f48924f953049c40dd0363804cd54c..3f7e7f10bd08df80e5e885c859c36251eb5230cb 100644 (file)
@@ -1,3 +1,34 @@
+2016-07-13  Thomas Preud'homme  <thomas.preudhomme@arm.com>
+
+       * config/arm/arm.h (TARGET_HAVE_MOVT): Include ARMv8-M as having MOVT.
+       * config/arm/arm.c (arm_arch_name): (const_ok_for_op): Check MOVT/MOVW
+       availability with TARGET_HAVE_MOVT.
+       (thumb_legitimate_constant_p): Strip the high part of a label_ref.
+       (thumb1_rtx_costs): Also return 0 if setting a half word constant and
+       MOVW is available and replace (unsigned HOST_WIDE_INT) INTVAL by
+       UINTVAL.
+       (thumb1_size_rtx_costs): Make set of half word constant also cost 1
+       extra instruction if MOVW is available.  Use a cost variable
+       incremented by COSTS_N_INSNS (1) when the condition match rather than
+       returning an arithmetic expression based on COSTS_N_INSNS.  Make
+       constant with bottom half word zero cost 2 instruction if MOVW is
+       available.
+       * config/arm/arm.md (define_attr "arch"): Add v8mb.
+       (define_attr "arch_enabled"): Set to yes if arch value is v8mb and
+       target is ARMv8-M Baseline.
+       (arm_movt): New unpredicable alternative for ARMv8-M Baseline.
+       (arm_movtas_ze): Likewise.
+       * config/arm/thumb1.md (thumb1_movdi_insn): Add ARMv8-M Baseline only
+       alternative for constants satisfying j constraint.
+       (thumb1_movsi_insn): Likewise.
+       (movsi splitter for K alternative): Tighten condition to not trigger
+       if movt is available and j constraint is satisfied.
+       (Pe immediate splitter): Likewise.
+       (thumb1_movhi_insn): Add ARMv8-M Baseline only alternative for
+       constant fitting in an halfword to use MOVW.
+       * doc/sourcebuild.texi (arm_thumb1_movt_ok): Document new ARM
+       effective target.
+
 2016-07-13  Richard Biener  <rguenther@suse.de>
 
        PR middle-end/71104
index 6af0d365fcefbae96a7630d88e342decf5dacdc7..195de4822c8f26acbd67e08604719365b3d68534 100644 (file)
@@ -8280,6 +8280,12 @@ arm_legitimate_constant_p_1 (machine_mode, rtx x)
 static bool
 thumb_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
 {
+  /* Splitters for TARGET_USE_MOVT call arm_emit_movpair which creates high
+     RTX.  These RTX must therefore be allowed for Thumb-1 so that when run
+     for ARMv8-M Baseline or later the result is valid.  */
+  if (TARGET_HAVE_MOVT && GET_CODE (x) == HIGH)
+    x = XEXP (x, 0);
+
   return (CONST_INT_P (x)
          || CONST_DOUBLE_P (x)
          || CONSTANT_ADDRESS_P (x)
@@ -8366,7 +8372,9 @@ thumb1_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer)
     case CONST_INT:
       if (outer == SET)
        {
-         if ((unsigned HOST_WIDE_INT) INTVAL (x) < 256)
+         if (UINTVAL (x) < 256
+             /* 16-bit constant.  */
+             || (TARGET_HAVE_MOVT && !(INTVAL (x) & 0xffff0000)))
            return 0;
          if (thumb_shiftable_const (INTVAL (x)))
            return COSTS_N_INSNS (2);
@@ -9069,7 +9077,7 @@ static inline int
 thumb1_size_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer)
 {
   machine_mode mode = GET_MODE (x);
-  int words;
+  int words, cost;
 
   switch (code)
     {
@@ -9115,17 +9123,26 @@ thumb1_size_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer)
       /* A SET doesn't have a mode, so let's look at the SET_DEST to get
         the mode.  */
       words = ARM_NUM_INTS (GET_MODE_SIZE (GET_MODE (SET_DEST (x))));
-      return COSTS_N_INSNS (words)
-            + COSTS_N_INSNS (1) * (satisfies_constraint_J (SET_SRC (x))
-                                   || satisfies_constraint_K (SET_SRC (x))
-                                      /* thumb1_movdi_insn.  */
-                                   || ((words > 1) && MEM_P (SET_SRC (x))));
+      cost = COSTS_N_INSNS (words);
+      if (satisfies_constraint_J (SET_SRC (x))
+         || satisfies_constraint_K (SET_SRC (x))
+            /* Too big an immediate for a 2-byte mov, using MOVT.  */
+         || (UINTVAL (SET_SRC (x)) >= 256
+             && TARGET_HAVE_MOVT
+             && satisfies_constraint_j (SET_SRC (x)))
+            /* thumb1_movdi_insn.  */
+         || ((words > 1) && MEM_P (SET_SRC (x))))
+       cost += COSTS_N_INSNS (1);
+      return cost;
 
     case CONST_INT:
       if (outer == SET)
         {
           if (UINTVAL (x) < 256)
             return COSTS_N_INSNS (1);
+         /* movw is 4byte long.  */
+         if (TARGET_HAVE_MOVT && !(INTVAL (x) & 0xffff0000))
+           return COSTS_N_INSNS (2);
          /* See split "TARGET_THUMB1 && satisfies_constraint_J".  */
          if (INTVAL (x) >= -255 && INTVAL (x) <= -1)
             return COSTS_N_INSNS (2);
index c9aaa6090872c24d9e6ffcadd5f1bf81d0a5890f..6a0f64537f8e5d0d913d082cb919ae6cbd2100ec 100644 (file)
@@ -263,8 +263,8 @@ extern void (*arm_lang_output_object_attributes_hook)(void);
 /* Nonzero if this chip supports load-acquire and store-release.  */
 #define TARGET_HAVE_LDACQ      (TARGET_ARM_ARCH >= 8 && arm_arch_notm)
 
-/* Nonzero if this chip provides the MOVW and MOVW instructions.  */
-#define TARGET_HAVE_MOVT       (arm_arch_thumb2)
+/* Nonzero if this chip provides the MOVW and MOVT instructions.  */
+#define TARGET_HAVE_MOVT       (arm_arch_thumb2 || arm_arch8)
 
 /* Nonzero if integer division instructions supported.  */
 #define TARGET_IDIV    ((TARGET_ARM && arm_arch_arm_hwdiv)     \
index 3cd76f935a45305b4e7fe7b55b517a1404edfa0b..8727c6df16ea95007dfcdb3249a8467ede3d72ac 100644 (file)
 ; This can be "a" for ARM, "t" for either of the Thumbs, "32" for
 ; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode.  "v6"
 ; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without
-; arm_arch6.  "v6t2" for Thumb-2 with arm_arch6.  This attribute is
-; used to compute attribute "enabled", use type "any" to enable an
-; alternative in all cases.
-(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,v6t2,neon_for_64bits,avoid_neon_for_64bits,iwmmxt,iwmmxt2,armv6_or_vfpv3,neon"
+; arm_arch6.  "v6t2" for Thumb-2 with arm_arch6 and "v8mb" for ARMv8-M
+; Baseline.  This attribute is used to compute attribute "enabled",
+; use type "any" to enable an alternative in all cases.
+(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,v6t2,v8mb,neon_for_64bits,avoid_neon_for_64bits,iwmmxt,iwmmxt2,armv6_or_vfpv3,neon"
   (const_string "any"))
 
 (define_attr "arch_enabled" "no,yes"
              (match_test "TARGET_32BIT && arm_arch6 && arm_arch_thumb2"))
         (const_string "yes")
 
+        (and (eq_attr "arch" "v8mb")
+             (match_test "TARGET_THUMB1 && arm_arch8"))
+        (const_string "yes")
+
         (and (eq_attr "arch" "avoid_neon_for_64bits")
              (match_test "TARGET_NEON")
              (not (match_test "TARGET_PREFER_NEON_64BITS")))
 ;; LO_SUM adds in the high bits.  Fortunately these are opaque operations
 ;; so this does not matter.
 (define_insn "*arm_movt"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
-       (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0")
-                  (match_operand:SI 2 "general_operand"      "i")))]
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
+       (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
+                  (match_operand:SI 2 "general_operand"      "i,i")))]
   "TARGET_HAVE_MOVT && arm_valid_symbolic_address_p (operands[2])"
-  "movt%?\t%0, #:upper16:%c2"
-  [(set_attr "predicable" "yes")
+  "@
+   movt%?\t%0, #:upper16:%c2
+   movt\t%0, #:upper16:%c2"
+  [(set_attr "arch"  "32,v8mb")
+   (set_attr "predicable" "yes")
    (set_attr "predicable_short_it" "no")
    (set_attr "length" "4")
    (set_attr "type" "alu_sreg")]
 ;; We only care about the lower 16 bits of the constant 
 ;; being inserted into the upper 16 bits of the register.
 (define_insn "*arm_movtas_ze" 
-  [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r")
+  [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "+r,r")
                    (const_int 16)
                    (const_int 16))
         (match_operand:SI 1 "const_int_operand" ""))]
   "TARGET_HAVE_MOVT"
-  "movt%?\t%0, %L1"
- [(set_attr "predicable" "yes")
+  "@
+   movt%?\t%0, %L1
+   movt\t%0, %L1"
+ [(set_attr "arch" "32,v8mb")
+  (set_attr "predicable" "yes")
   (set_attr "predicable_short_it" "no")
   (set_attr "length" "4")
   (set_attr "type" "alu_sreg")]
index 035641b3335797cb843a5741d7372492d5a91cfc..b317f1b0637e02f105f10efb18270f4a35801c7c 100644 (file)
 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
 ;;; thumb_reorg with a memory reference.
 (define_insn "*thumb1_movdi_insn"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
-       (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,r,l,>,l, m,*r")
+       (match_operand:DI 1 "general_operand"      "l, I,J,j,>,l,mi,l,*r"))]
   "TARGET_THUMB1
    && (   register_operand (operands[0], DImode)
        || register_operand (operands[1], DImode))"
       operands[1] = GEN_INT (- INTVAL (operands[1]));
       return \"movs\\t%Q0, %1\;rsbs\\t%Q0, %Q0, #0\;asrs\\t%R0, %Q0, #31\";
     case 3:
-      return \"ldmia\\t%1, {%0, %H0}\";
+      gcc_assert (TARGET_HAVE_MOVT);
+      return \"movw\\t%Q0, %L1\;movs\\tR0, #0\";
     case 4:
-      return \"stmia\\t%0, {%1, %H1}\";
+      return \"ldmia\\t%1, {%0, %H0}\";
     case 5:
-      return thumb_load_double_from_address (operands);
+      return \"stmia\\t%0, {%1, %H1}\";
     case 6:
+      return thumb_load_double_from_address (operands);
+    case 7:
       operands[2] = gen_rtx_MEM (SImode,
                             plus_constant (Pmode, XEXP (operands[0], 0), 4));
       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
       return \"\";
-    case 7:
+    case 8:
       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
        return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
     }
   }"
-  [(set_attr "length" "4,4,6,2,2,6,4,4")
-   (set_attr "type" "multiple,multiple,multiple,load2,store2,load2,store2,multiple")
-   (set_attr "pool_range" "*,*,*,*,*,1018,*,*")]
+  [(set_attr "length" "4,4,6,6,2,2,6,4,4")
+   (set_attr "type" "multiple,multiple,multiple,multiple,load2,store2,load2,store2,multiple")
+   (set_attr "arch" "t1,t1,t1,v8mb,t1,t1,t1,t1,t1")
+   (set_attr "pool_range" "*,*,*,*,*,*,1018,*,*")]
 )
 
 (define_insn "*thumb1_movsi_insn"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*l*h*k")
-       (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*l*h*k"))]
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,r,l,l,l,>,l, m,*l*h*k")
+       (match_operand:SI 1 "general_operand"      "l, I,j,J,K,>,l,mi,l,*l*h*k"))]
   "TARGET_THUMB1
    && (   register_operand (operands[0], SImode)
        || register_operand (operands[1], SImode))"
   "@
    movs        %0, %1
    movs        %0, %1
+   movw        %0, %1
    #
    #
    ldmia\\t%1, {%0}
    ldr\\t%0, %1
    str\\t%1, %0
    mov\\t%0, %1"
-  [(set_attr "length" "2,2,4,4,2,2,2,2,2")
-   (set_attr "type" "mov_reg,mov_imm,multiple,multiple,load1,store1,load1,store1,mov_reg")
-   (set_attr "pool_range" "*,*,*,*,*,*,1018,*,*")
-   (set_attr "conds" "set,clob,*,*,nocond,nocond,nocond,nocond,nocond")])
+  [(set_attr "length" "2,2,4,4,4,2,2,2,2,2")
+   (set_attr "type" "mov_reg,mov_imm,mov_imm,multiple,multiple,load1,store1,load1,store1,mov_reg")
+   (set_attr "pool_range" "*,*,*,*,*,*,*,1018,*,*")
+   (set_attr "arch" "t1,t1,v8mb,t1,t1,t1,t1,t1,t1,t1")
+   (set_attr "conds" "set,clob,nocond,*,*,nocond,nocond,nocond,nocond,nocond")])
 
 ; Split the load of 64-bit constant into two loads for high and low 32-bit parts respectively
 ; to see if we can load them in fewer instructions or fewer cycles.
 (define_split
   [(set (match_operand:SI 0 "register_operand" "")
        (match_operand:SI 1 "const_int_operand" ""))]
-  "TARGET_THUMB1 && satisfies_constraint_K (operands[1])"
+  "TARGET_THUMB1 && satisfies_constraint_K (operands[1])
+   && !(TARGET_HAVE_MOVT && satisfies_constraint_j (operands[1]))"
   [(set (match_dup 2) (match_dup 1))
    (set (match_dup 0) (ashift:SI (match_dup 2) (match_dup 3)))]
   "
 (define_split
   [(set (match_operand:SI 0 "register_operand" "")
        (match_operand:SI 1 "const_int_operand" ""))]
-  "TARGET_THUMB1 && satisfies_constraint_Pe (operands[1])"
+  "TARGET_THUMB1 && satisfies_constraint_Pe (operands[1])
+   && !(TARGET_HAVE_MOVT && satisfies_constraint_j (operands[1]))"
   [(set (match_dup 2) (match_dup 1))
    (set (match_dup 0) (plus:SI (match_dup 2) (match_dup 3)))]
   "
 )
 
 (define_insn "*thumb1_movhi_insn"
-  [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,l*r,*h,l")
-       (match_operand:HI 1 "general_operand"       "l,m,l,k*h,*r,I"))]
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,l*r,*h,l,r")
+       (match_operand:HI 1 "general_operand"       "l,m,l,k*h,*r,I,n"))]
   "TARGET_THUMB1
    && (   register_operand (operands[0], HImode)
        || register_operand (operands[1], HImode))"
     case 3: return \"mov       %0, %1\";
     case 4: return \"mov       %0, %1\";
     case 5: return \"movs      %0, %1\";
+    case 6: gcc_assert (TARGET_HAVE_MOVT);
+           return \"movw       %0, %L1\";
     default: gcc_unreachable ();
     case 1:
       /* The stack pointer can end up being taken as an index register.
        }
       return \"ldrh    %0, %1\";
     }"
-  [(set_attr "length" "2,4,2,2,2,2")
-   (set_attr "type" "alus_imm,load1,store1,mov_reg,mov_reg,mov_imm")
-   (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")])
+  [(set_attr "length" "2,4,2,2,2,2,4")
+   (set_attr "type" "alus_imm,load1,store1,mov_reg,mov_reg,mov_imm,mov_imm")
+   (set_attr "arch" "t1,t1,t1,t1,t1,t1,v8mb")
+   (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob,nocond")])
 
 (define_expand "thumb_movhi_clobber"
   [(set (match_operand:HI     0 "memory_operand"   "")
index 23d3c3f0f547274e2d281ac5513a3509962062cc..b437c1711321194467dc4d6867f18655cc8b3272 100644 (file)
@@ -1614,6 +1614,10 @@ ARM target supports acquire-release instructions.
 ARM target prefers @code{LDRD} and @code{STRD} instructions over
 @code{LDM} and @code{STM} instructions.
 
+@item arm_thumb1_movt_ok
+ARM target generates Thumb-1 code for @code{-mthumb} with @code{MOVW}
+and @code{MOVT} instructions available.
+
 @end table
 
 @subsubsection AArch64-specific attributes
index d4e0fcabdc038d4113cae00e4d0e1d71521291ff..d1204e73e8df4a944727cf950059ade5dab0d0d0 100644 (file)
@@ -1,3 +1,13 @@
+2016-07-13  Thomas Preud'homme  <thomas.preudhomme@arm.com>
+
+       * lib/target-supports.exp (check_effective_target_arm_thumb1_movt_ok):
+       Define effective target.
+       * gcc.target/arm/pr42574.c: Require arm_thumb1_ok and
+       !arm_thumb1_movt_ok to exclude ARMv8-M Baseline.
+       * gcc.target/arm/movhi_movw.c: New test.
+       * gcc.target/arm/movsi_movw.c: Likewise.
+       * gcc.target/arm/movdi_movw.c: Likewise.
+
 2016-07-13  Richard Biener  <rguenther@suse.de>
 
        PR middle-end/71104
diff --git a/gcc/testsuite/gcc.target/arm/movdi_movw.c b/gcc/testsuite/gcc.target/arm/movdi_movw.c
new file mode 100644 (file)
index 0000000..0f6b839
--- /dev/null
@@ -0,0 +1,10 @@
+/* { dg-do compile { target { arm_thumb2 || arm_thumb1_movt_ok } } } */
+/* { dg-options "-O2" } */
+
+long long
+movdi (int a)
+{
+  return 0xF0F0;
+}
+
+/* { dg-final { scan-assembler-times "movw\tr0, #61680" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/movhi_movw.c b/gcc/testsuite/gcc.target/arm/movhi_movw.c
new file mode 100644 (file)
index 0000000..b097a8a
--- /dev/null
@@ -0,0 +1,10 @@
+/* { dg-do compile { target { arm_thumb2 || arm_thumb1_movt_ok } } } */
+/* { dg-options "-O2" } */
+
+short
+movsi (void)
+{
+  return (short) 0x7070;
+}
+
+/* { dg-final { scan-assembler-times "movw\tr0, #28784" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/movsi_movw.c b/gcc/testsuite/gcc.target/arm/movsi_movw.c
new file mode 100644 (file)
index 0000000..d50906e
--- /dev/null
@@ -0,0 +1,10 @@
+/* { dg-do compile { target { arm_thumb2 || arm_thumb1_movt_ok } } } */
+/* { dg-options "-O2" } */
+
+int
+movsi (void)
+{
+  return 0xF0F0;
+}
+
+/* { dg-final { scan-assembler-times "movw\tr0, #61680" 1 } } */
index 0ccd05f9922c798611e479d97890aa69b180e989..e3476f37788a2b3144454aef04a9b45c0b4ac398 100644 (file)
@@ -1,5 +1,5 @@
+/* { dg-do compile { arm_thumb1_ok && { ! arm_thumb1_movt_ok } } } */
 /* { dg-options "-mthumb -Os -fpic" }  */
-/* { dg-require-effective-target arm_thumb1_ok } */
 /* { dg-require-effective-target fpic } */
 /* Make sure the address of glob.c is calculated only once and using
    a logical shift for the offset (200<<1).  */
index b26f8a29c8dc472c563fc2eb3a7d8768f1647bbe..e6a117022f8f16e61fabfd40dbf5dd7eb0da2bbc 100644 (file)
@@ -3485,6 +3485,23 @@ proc check_effective_target_arm_cortex_m { } {
     } "-mthumb"]
 }
 
+# Return 1 if this is an ARM target where -mthumb causes Thumb-1 to be
+# used and MOVT/MOVW instructions to be available.
+
+proc check_effective_target_arm_thumb1_movt_ok {} {
+    if [check_effective_target_arm_thumb1_ok] {
+       return [check_no_compiler_messages arm_movt object {
+           int
+           foo (void)
+           {
+             asm ("movt r0, #42");
+           }
+       } "-mthumb"]
+    } else {
+       return 0
+    }
+}
+
 # Return 1 if this compilation turns on string_ops_prefer_neon on.
 
 proc check_effective_target_arm_tune_string_ops_prefer_neon { } {