public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH, ARM 5/6] Add support for MOVT/MOVW to ARMv8-M Baseline
@ 2015-12-17  8:08 Thomas Preud'homme
  2016-05-17 10:13 ` [PATCH, ARM 5/7, ping1] " Thomas Preudhomme
  0 siblings, 1 reply; 11+ messages in thread
From: Thomas Preud'homme @ 2015-12-17  8:08 UTC (permalink / raw)
  To: gcc-patches, Richard Earnshaw, Ramana Radhakrishnan, Kyrylo Tkachov

Hi,

This patch is part of a patch series to add support for ARMv8-M[1] to GCC. This specific patch makes the compiler start generating code with the new MOVT/MOVW instructions for ARMv8-M Baseline.

[1] For a quick overview of ARMv8-M please refer to the initial cover letter.

ChangeLog entry is as follows:


*** gcc/ChangeLog ***

2015-11-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): Legalize high part of a label_ref as a
        constant.
        (thumb1_rtx_costs): Also return 0 if setting a half word constant and
        movw is available.
        (thumb1_size_rtx_costs): Make set of half word constant also cost 1
        extra instruction if MOVW is available.  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.
        * 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_ko): Document new ARM
        effective target.


*** gcc/testsuite/ChangeLog ***

2015-11-13  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * lib/target-supports.exp (check_effective_target_arm_thumb1_movt_ko):
        Define effective target.
        * gcc.target/arm/pr42574.c: Require arm_thumb1_movt_ko instead of
        arm_thumb1_ok as effective target to exclude ARMv8-M Baseline.


diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index ff3cfcd..015df50 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -261,7 +261,7 @@ extern void (*arm_lang_output_object_attributes_hook)(void);
 #define TARGET_HAVE_LDACQ	(TARGET_ARM_ARCH >= 8 && arm_arch_notm)
 
 /* Nonzero if this chip provides the movw and movt instructions.  */
-#define TARGET_HAVE_MOVT	(arm_arch_thumb2)
+#define TARGET_HAVE_MOVT	(arm_arch_thumb2 || arm_arch8)
 
 /* Nonzero if integer division instructions supported.  */
 #define TARGET_IDIV	((TARGET_ARM && arm_arch_arm_hwdiv)	\
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 51d501e..d832309 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -8158,6 +8158,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)
@@ -8244,7 +8250,8 @@ 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 ((unsigned HOST_WIDE_INT) INTVAL (x) < 256
+	      || (TARGET_HAVE_MOVT && !(INTVAL (x) & 0xffff0000)))
 	    return 0;
 	  if (thumb_shiftable_const (INTVAL (x)))
 	    return COSTS_N_INSNS (2);
@@ -8994,16 +9001,24 @@ thumb1_size_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer)
 	 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))));
+	     + COSTS_N_INSNS (1)
+	       * (satisfies_constraint_J (SET_SRC (x))
+		  || satisfies_constraint_K (SET_SRC (x))
+		     /* Too big immediate for 2byte mov, using movt.  */
+		  || ((unsigned HOST_WIDE_INT) INTVAL (SET_SRC (x)) >= 256
+		      && TARGET_HAVE_MOVT
+		      && satisfies_constraint_j (SET_SRC (x)))
+		     /* thumb1_movdi_insn.  */
+		  || ((words > 1) && MEM_P (SET_SRC (x))));
 
     case CONST_INT:
       if (outer == SET)
         {
           if ((unsigned HOST_WIDE_INT) INTVAL (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);
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 78dafa0..ce5ea83 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -115,10 +115,10 @@
 ; 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"
+; 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"
   (const_string "any"))
 
 (define_attr "arch_enabled" "no,yes"
@@ -157,6 +157,10 @@
 	      (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")))
diff --git a/gcc/config/arm/thumb1.md b/gcc/config/arm/thumb1.md
index 3847b33b..7e3bcb4 100644
--- a/gcc/config/arm/thumb1.md
+++ b/gcc/config/arm/thumb1.md
@@ -590,8 +590,8 @@
 ;;; ??? 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))"
@@ -609,37 +609,41 @@
     case 2:
       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}\";
+    case 3: if (!TARGET_HAVE_MOVT) gcc_unreachable ();
+	    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}
@@ -647,10 +651,11 @@
    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.
@@ -687,7 +692,8 @@
 (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)))]
   "
@@ -714,7 +720,8 @@
 (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)))]
   "
@@ -726,8 +733,8 @@
 )
 
 (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))"
@@ -739,6 +746,8 @@
     case 3: return \"mov	%0, %1\";
     case 4: return \"mov	%0, %1\";
     case 5: return \"movs	%0, %1\";
+    case 6: if (!TARGET_HAVE_MOVT) gcc_unreachable ();
+	    return \"movw	%0, %L1\";
     default: gcc_unreachable ();
     case 1:
       /* The stack pointer can end up being taken as an index register.
@@ -758,9 +767,10 @@
 	}
       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"   "")
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 61de4a56..6c6f0f1 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -1586,6 +1586,10 @@ Some multilibs may be incompatible with these options.
 ARM target prefers @code{LDRD} and @code{STRD} instructions over
 @code{LDM} and @code{STM} instructions.
 
+@item arm_thumb1_movt_ko
+ARM target generates Thumb-1 code for @code{-mthumb} with no
+@code{MOVT} instruction available.
+
 @end table
 
 @subsubsection AArch64-specific attributes
diff --git a/gcc/testsuite/gcc.target/arm/pr42574.c b/gcc/testsuite/gcc.target/arm/pr42574.c
index 0ccd05f..53aea62 100644
--- a/gcc/testsuite/gcc.target/arm/pr42574.c
+++ b/gcc/testsuite/gcc.target/arm/pr42574.c
@@ -1,5 +1,5 @@
 /* { dg-options "-mthumb -Os -fpic" }  */
-/* { dg-require-effective-target arm_thumb1_ok } */
+/* { dg-require-effective-target arm_thumb1_movt_ko } */
 /* { 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).  */
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 37c273a..44ebbe3 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -3211,6 +3211,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 no movt/movw instructions to be available.
+
+proc check_effective_target_arm_thumb1_movt_ko {} {
+    if [check_effective_target_arm_thumb1_ok] {
+	return [expr ![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 { } {


Testing:

* Toolchain was built successfully with and without the ARMv8-M support patches[1] with the following multilib list: armv6-m,armv7-m,armv7e-m,cortex-m7. The code generation for crtbegin.o, crtend.o, crti.o, crtn.o, libgcc.a, libgcov.a, libc.a, libg.a, libgloss-linux.a, libm.a, libnosys.a, librdimon.a, librdpmon.a, libstdc++.a and libsupc++.a is unchanged for all these targets. 

[1] the binutils one, the GCC one, the newlib one and the 4 ld ones (adding support to ARMv8-M security extension)

* GCC also showed no testsuite regression when targeting ARMv8-M Baseline compared to ARMv6-M on ARM Fast Models and when targeting ARMv6-M and ARMv7-M (compared to without the patch)
* GCC was bootstrapped successfully targeting Thumb-1 and targeting Thumb-2

Is this ok for stage3?

Best regards,

Thomas

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH, ARM 5/7, ping1] Add support for MOVT/MOVW to ARMv8-M Baseline
  2015-12-17  8:08 [PATCH, ARM 5/6] Add support for MOVT/MOVW to ARMv8-M Baseline Thomas Preud'homme
@ 2016-05-17 10:13 ` Thomas Preudhomme
  2016-05-18 11:31   ` Kyrill Tkachov
  0 siblings, 1 reply; 11+ messages in thread
From: Thomas Preudhomme @ 2016-05-17 10:13 UTC (permalink / raw)
  To: Richard Earnshaw, Ramana Radhakrishnan, Kyrylo Tkachov; +Cc: gcc-patches

Ping?

*** gcc/ChangeLog ***

2015-11-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): Legalize high part of a label_ref as a
        constant.
        (thumb1_rtx_costs): Also return 0 if setting a half word constant and
        movw is available.
        (thumb1_size_rtx_costs): Make set of half word constant also cost 1
        extra instruction if MOVW is available.  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.
        * 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_ko): Document new ARM
        effective target.


*** gcc/testsuite/ChangeLog ***

2015-11-13  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * lib/target-supports.exp (check_effective_target_arm_thumb1_movt_ko):
        Define effective target.
        * gcc.target/arm/pr42574.c: Require arm_thumb1_movt_ko instead of
        arm_thumb1_ok as effective target to exclude ARMv8-M Baseline.


diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 
47216b4a1959ccdb18e329db411bf7f941e67163..f42e996e5a7ce979fe406b8261d50fb2ba005f6b 
100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -269,7 +269,7 @@ extern void (*arm_lang_output_object_attributes_hook)
(void);
 #define TARGET_HAVE_LDACQ	(TARGET_ARM_ARCH >= 8 && arm_arch_notm)
 
 /* Nonzero if this chip provides the movw and movt instructions.  */
-#define TARGET_HAVE_MOVT	(arm_arch_thumb2)
+#define TARGET_HAVE_MOVT	(arm_arch_thumb2 || arm_arch8)
 
 /* Nonzero if integer division instructions supported.  */
 #define TARGET_IDIV	((TARGET_ARM && arm_arch_arm_hwdiv)	\
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 
d75a34f10d5ed22cff0a0b5d3ad433f111b059ee..13b4b71ac8f9c1da8ef1945f7ff6985ca59f6832 
100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -8220,6 +8220,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)
@@ -8306,7 +8312,8 @@ 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 ((unsigned HOST_WIDE_INT) INTVAL (x) < 256
+	      || (TARGET_HAVE_MOVT && !(INTVAL (x) & 0xffff0000)))
 	    return 0;
 	  if (thumb_shiftable_const (INTVAL (x)))
 	    return COSTS_N_INSNS (2);
@@ -9056,16 +9063,24 @@ thumb1_size_rtx_costs (rtx x, enum rtx_code code, enum 
rtx_code outer)
 	 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))));
+	     + COSTS_N_INSNS (1)
+	       * (satisfies_constraint_J (SET_SRC (x))
+		  || satisfies_constraint_K (SET_SRC (x))
+		     /* Too big immediate for 2byte mov, using movt.  */
+		  || ((unsigned HOST_WIDE_INT) INTVAL (SET_SRC (x)) >= 256
+		      && TARGET_HAVE_MOVT
+		      && satisfies_constraint_j (SET_SRC (x)))
+		     /* thumb1_movdi_insn.  */
+		  || ((words > 1) && MEM_P (SET_SRC (x))));
 
     case CONST_INT:
       if (outer == SET)
         {
           if ((unsigned HOST_WIDE_INT) INTVAL (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);
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 
0333394423477acb8d9223fd06c17e82bfd0a94d..6fc1c437d9929fe3f44b513be3fb38f831089f52 
100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -118,10 +118,10 @@
 ; 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"
@@ -160,6 +160,10 @@
 	      (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")))
diff --git a/gcc/config/arm/thumb1.md b/gcc/config/arm/thumb1.md
index 
072ed4da47ad164eb406bedc3fccc589ac705e9f..4572456b8bc98503061846cad94bc642943db3a2 
100644
--- a/gcc/config/arm/thumb1.md
+++ b/gcc/config/arm/thumb1.md
@@ -590,8 +590,8 @@
 ;;; ??? 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))"
@@ -609,37 +609,41 @@
     case 2:
       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}\";
+    case 3: if (!TARGET_HAVE_MOVT) gcc_unreachable ();
+	    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}
@@ -647,10 +651,11 @@
    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.
@@ -687,7 +692,8 @@
 (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)))]
   "
@@ -714,7 +720,8 @@
 (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)))]
   "
@@ -726,8 +733,8 @@
 )
 
 (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))"
@@ -739,6 +746,8 @@
     case 3: return \"mov	%0, %1\";
     case 4: return \"mov	%0, %1\";
     case 5: return \"movs	%0, %1\";
+    case 6: if (!TARGET_HAVE_MOVT) gcc_unreachable ();
+	    return \"movw	%0, %L1\";
     default: gcc_unreachable ();
     case 1:
       /* The stack pointer can end up being taken as an index register.
@@ -758,9 +767,10 @@
 	}
       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"   "")
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 
3142cd53ae53e90bb1af2f595fe53778c1cbfd3b..860b4c0627e094bae8b3801f9256ff4fec5c8fc2 
100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -1601,6 +1601,10 @@ arm_v8_1a_neon_ok.
 ARM target prefers @code{LDRD} and @code{STRD} instructions over
 @code{LDM} and @code{STM} instructions.
 
+@item arm_thumb1_movt_ko
+ARM target generates Thumb-1 code for @code{-mthumb} with no
+@code{MOVT} instruction available.
+
 @end table
 
 @subsubsection AArch64-specific attributes
diff --git a/gcc/testsuite/gcc.target/arm/pr42574.c 
b/gcc/testsuite/gcc.target/arm/pr42574.c
index 
0ccd05f9922c798611e479d97890aa69b180e989..53aea6224be89d2d771a22f8ecb397276f586234 
100644
--- a/gcc/testsuite/gcc.target/arm/pr42574.c
+++ b/gcc/testsuite/gcc.target/arm/pr42574.c
@@ -1,5 +1,5 @@
 /* { dg-options "-mthumb -Os -fpic" }  */
-/* { dg-require-effective-target arm_thumb1_ok } */
+/* { dg-require-effective-target arm_thumb1_movt_ko } */
 /* { 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).  */
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-
supports.exp
index 
46352b90de7202960116d93523b017d5dc4a1423..f5d73ad2620fa35f0091a890bca63c7d35de1a85 
100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -3329,6 +3329,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 no movt/movw instructions to be available.
+
+proc check_effective_target_arm_thumb1_movt_ko {} {
+    if [check_effective_target_arm_thumb1_ok] {
+	return [expr ![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 { } {


Best regards,

Thomas

On Thursday 17 December 2015 16:08:00 Thomas Preud'homme wrote:
> Hi,
> 
> This patch is part of a patch series to add support for ARMv8-M[1] to GCC.
> This specific patch makes the compiler start generating code with the new
> MOVT/MOVW instructions for ARMv8-M Baseline.
> 
> [1] For a quick overview of ARMv8-M please refer to the initial cover
> letter.
> 
> ChangeLog entry is as follows:
> 
> 
> *** gcc/ChangeLog ***
> 
> 2015-11-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): Legalize high part of a label_ref as
> a constant.
>         (thumb1_rtx_costs): Also return 0 if setting a half word constant
> and movw is available.
>         (thumb1_size_rtx_costs): Make set of half word constant also cost 1
>         extra instruction if MOVW is available.  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.
>         * 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_ko): Document new ARM
>         effective target.
> 
> 
> *** gcc/testsuite/ChangeLog ***
> 
> 2015-11-13  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> 
>         * lib/target-supports.exp
> (check_effective_target_arm_thumb1_movt_ko): Define effective target.
>         * gcc.target/arm/pr42574.c: Require arm_thumb1_movt_ko instead of
>         arm_thumb1_ok as effective target to exclude ARMv8-M Baseline.
> 
> 
> diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
> index ff3cfcd..015df50 100644
> --- a/gcc/config/arm/arm.h
> +++ b/gcc/config/arm/arm.h
> @@ -261,7 +261,7 @@ extern void
> (*arm_lang_output_object_attributes_hook)(void); #define
> TARGET_HAVE_LDACQ	(TARGET_ARM_ARCH >= 8 && arm_arch_notm)
> 
>  /* Nonzero if this chip provides the movw and movt instructions.  */
> -#define TARGET_HAVE_MOVT	(arm_arch_thumb2)
> +#define TARGET_HAVE_MOVT	(arm_arch_thumb2 || arm_arch8)
> 
>  /* Nonzero if integer division instructions supported.  */
>  #define TARGET_IDIV	((TARGET_ARM && arm_arch_arm_hwdiv)	\
> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
> index 51d501e..d832309 100644
> --- a/gcc/config/arm/arm.c
> +++ b/gcc/config/arm/arm.c
> @@ -8158,6 +8158,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)
> 
> @@ -8244,7 +8250,8 @@ 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 ((unsigned HOST_WIDE_INT) INTVAL (x) < 256
> +	      || (TARGET_HAVE_MOVT && !(INTVAL (x) & 0xffff0000)))
>  	    return 0;
>  	  if (thumb_shiftable_const (INTVAL (x)))
>  	    return COSTS_N_INSNS (2);
> @@ -8994,16 +9001,24 @@ thumb1_size_rtx_costs (rtx x, enum rtx_code code,
> enum rtx_code outer) 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))));
> +	     + COSTS_N_INSNS (1)
> +	       * (satisfies_constraint_J (SET_SRC (x))
> +		  || satisfies_constraint_K (SET_SRC (x))
> +		     /* Too big immediate for 2byte mov, using movt.  */
> +		  || ((unsigned HOST_WIDE_INT) INTVAL (SET_SRC (x)) >= 256
> +		      && TARGET_HAVE_MOVT
> +		      && satisfies_constraint_j (SET_SRC (x)))
> +		     /* thumb1_movdi_insn.  */
> +		  || ((words > 1) && MEM_P (SET_SRC (x))));
> 
>      case CONST_INT:
>        if (outer == SET)
>          {
>            if ((unsigned HOST_WIDE_INT) INTVAL (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);
> diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
> index 78dafa0..ce5ea83 100644
> --- a/gcc/config/arm/arm.md
> +++ b/gcc/config/arm/arm.md
> @@ -115,10 +115,10 @@
>  ; 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" +; 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,i
> wmmxt,iwmmxt2,armv6_or_vfpv3" (const_string "any"))
> 
>  (define_attr "arch_enabled" "no,yes"
> @@ -157,6 +157,10 @@
>  	      (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")))
> diff --git a/gcc/config/arm/thumb1.md b/gcc/config/arm/thumb1.md
> index 3847b33b..7e3bcb4 100644
> --- a/gcc/config/arm/thumb1.md
> +++ b/gcc/config/arm/thumb1.md
> @@ -590,8 +590,8 @@
>  ;;; ??? 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))"
> 
> @@ -609,37 +609,41 @@
>      case 2:
>        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}\";
> +    case 3: if (!TARGET_HAVE_MOVT) gcc_unreachable ();
> +	    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}
> @@ -647,10 +651,11 @@
>     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_re
> g") +   (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. @@ -687,7 +692,8 @@
>  (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)))]
>    "
> @@ -714,7 +720,8 @@
>  (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)))]
>    "
> @@ -726,8 +733,8 @@
>  )
> 
>  (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))"
> 
> @@ -739,6 +746,8 @@
>      case 3: return \"mov	%0, %1\";
>      case 4: return \"mov	%0, %1\";
>      case 5: return \"movs	%0, %1\";
> +    case 6: if (!TARGET_HAVE_MOVT) gcc_unreachable ();
> +	    return \"movw	%0, %L1\";
>      default: gcc_unreachable ();
>      case 1:
>        /* The stack pointer can end up being taken as an index register.
> @@ -758,9 +767,10 @@
>  	}
>        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"   "")
> diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
> index 61de4a56..6c6f0f1 100644
> --- a/gcc/doc/sourcebuild.texi
> +++ b/gcc/doc/sourcebuild.texi
> @@ -1586,6 +1586,10 @@ Some multilibs may be incompatible with these
> options. ARM target prefers @code{LDRD} and @code{STRD} instructions over
>  @code{LDM} and @code{STM} instructions.
> 
> +@item arm_thumb1_movt_ko
> +ARM target generates Thumb-1 code for @code{-mthumb} with no
> +@code{MOVT} instruction available.
> +
>  @end table
> 
>  @subsubsection AArch64-specific attributes
> diff --git a/gcc/testsuite/gcc.target/arm/pr42574.c
> b/gcc/testsuite/gcc.target/arm/pr42574.c index 0ccd05f..53aea62 100644
> --- a/gcc/testsuite/gcc.target/arm/pr42574.c
> +++ b/gcc/testsuite/gcc.target/arm/pr42574.c
> @@ -1,5 +1,5 @@
>  /* { dg-options "-mthumb -Os -fpic" }  */
> -/* { dg-require-effective-target arm_thumb1_ok } */
> +/* { dg-require-effective-target arm_thumb1_movt_ko } */
>  /* { 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).  */
> diff --git a/gcc/testsuite/lib/target-supports.exp
> b/gcc/testsuite/lib/target-supports.exp index 37c273a..44ebbe3 100644
> --- a/gcc/testsuite/lib/target-supports.exp
> +++ b/gcc/testsuite/lib/target-supports.exp
> @@ -3211,6 +3211,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 no movt/movw instructions to be available.
> +
> +proc check_effective_target_arm_thumb1_movt_ko {} {
> +    if [check_effective_target_arm_thumb1_ok] {
> +	return [expr ![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 { } {
> 
> 
> Testing:
> 
> * Toolchain was built successfully with and without the ARMv8-M support
> patches[1] with the following multilib list:
> armv6-m,armv7-m,armv7e-m,cortex-m7. The code generation for crtbegin.o,
> crtend.o, crti.o, crtn.o, libgcc.a, libgcov.a, libc.a, libg.a,
> libgloss-linux.a, libm.a, libnosys.a, librdimon.a, librdpmon.a, libstdc++.a
> and libsupc++.a is unchanged for all these targets.
> 
> [1] the binutils one, the GCC one, the newlib one and the 4 ld ones (adding
> support to ARMv8-M security extension)
> 
> * GCC also showed no testsuite regression when targeting ARMv8-M Baseline
> compared to ARMv6-M on ARM Fast Models and when targeting ARMv6-M and
> ARMv7-M (compared to without the patch) * GCC was bootstrapped successfully
> targeting Thumb-1 and targeting Thumb-2
> 
> Is this ok for stage3?
> 
> Best regards,
> 
> Thomas

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH, ARM 5/7, ping1] Add support for MOVT/MOVW to ARMv8-M Baseline
  2016-05-17 10:13 ` [PATCH, ARM 5/7, ping1] " Thomas Preudhomme
@ 2016-05-18 11:31   ` Kyrill Tkachov
  2016-05-19 16:11     ` Thomas Preudhomme
  0 siblings, 1 reply; 11+ messages in thread
From: Kyrill Tkachov @ 2016-05-18 11:31 UTC (permalink / raw)
  To: Thomas Preudhomme, Richard Earnshaw, Ramana Radhakrishnan; +Cc: gcc-patches

Hi Thomas,

This looks mostly good with a few nits inline.
Please repost with the comments addressed.

Thanks,
Kyrill

On 17/05/16 11:13, Thomas Preudhomme wrote:
> Ping?
>
> *** gcc/ChangeLog ***
>
> 2015-11-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): Legalize high part of a label_ref as a
>          constant.

I don't think "Legalize" is the right word here. How about "Strip the HIGH part of a label_ref"?

>          (thumb1_rtx_costs): Also return 0 if setting a half word constant and
>          movw is available.
>          (thumb1_size_rtx_costs): Make set of half word constant also cost 1
>          extra instruction if MOVW is available.  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.
>          * 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.

Please use 'MOVW' consistently in the ChangeLog rather than the lowercase 'movw'

>          * doc/sourcebuild.texi (arm_thumb1_movt_ko): Document new ARM
>          effective target.
>
>
> *** gcc/testsuite/ChangeLog ***
>
> 2015-11-13  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>
>          * lib/target-supports.exp (check_effective_target_arm_thumb1_movt_ko):
>          Define effective target.
>          * gcc.target/arm/pr42574.c: Require arm_thumb1_movt_ko instead of
>          arm_thumb1_ok as effective target to exclude ARMv8-M Baseline.
>
>
> diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
> index
> 47216b4a1959ccdb18e329db411bf7f941e67163..f42e996e5a7ce979fe406b8261d50fb2ba005f6b
> 100644
> --- a/gcc/config/arm/arm.h
> +++ b/gcc/config/arm/arm.h
> @@ -269,7 +269,7 @@ extern void (*arm_lang_output_object_attributes_hook)
> (void);
>   #define TARGET_HAVE_LDACQ	(TARGET_ARM_ARCH >= 8 && arm_arch_notm)
>   
>   /* Nonzero if this chip provides the movw and movt instructions.  */
> -#define TARGET_HAVE_MOVT	(arm_arch_thumb2)
> +#define TARGET_HAVE_MOVT	(arm_arch_thumb2 || arm_arch8)
>   
>   /* Nonzero if integer division instructions supported.  */
>   #define TARGET_IDIV	((TARGET_ARM && arm_arch_arm_hwdiv)	\
> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
> index
> d75a34f10d5ed22cff0a0b5d3ad433f111b059ee..13b4b71ac8f9c1da8ef1945f7ff6985ca59f6832
> 100644
> --- a/gcc/config/arm/arm.c
> +++ b/gcc/config/arm/arm.c
> @@ -8220,6 +8220,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)
> @@ -8306,7 +8312,8 @@ 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 ((unsigned HOST_WIDE_INT) INTVAL (x) < 256
> +	      || (TARGET_HAVE_MOVT && !(INTVAL (x) & 0xffff0000)))
>   	    return 0;

Since you're modifying this line please replace (unsigned HOST_WIDE_INT) INTVAL (x)
with UINTVAL (x).

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH, ARM 5/7, ping1] Add support for MOVT/MOVW to ARMv8-M Baseline
  2016-05-18 11:31   ` Kyrill Tkachov
@ 2016-05-19 16:11     ` Thomas Preudhomme
  2016-05-20 11:15       ` Kyrill Tkachov
  0 siblings, 1 reply; 11+ messages in thread
From: Thomas Preudhomme @ 2016-05-19 16:11 UTC (permalink / raw)
  To: gcc-patches; +Cc: Kyrill Tkachov, Richard Earnshaw, Ramana Radhakrishnan

On Wednesday 18 May 2016 12:30:41 Kyrill Tkachov wrote:
> Hi Thomas,
> 
> This looks mostly good with a few nits inline.
> Please repost with the comments addressed.

Updated ChangeLog entries:

*** gcc/ChangeLog ***

2016-05-18  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.
        * 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_ko): Document new ARM
        effective target.


*** gcc/testsuite/ChangeLog ***

2015-11-13  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * lib/target-supports.exp (check_effective_target_arm_thumb1_movt_ko):
        Define effective target.
        * gcc.target/arm/pr42574.c: Require arm_thumb1_movt_ko instead of
        arm_thumb1_ok as effective target to exclude ARMv8-M Baseline.


and patch:

diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 
47216b4a1959ccdb18e329db411bf7f941e67163..f42e996e5a7ce979fe406b8261d50fb2ba005f6b 
100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -269,7 +269,7 @@ extern void (*arm_lang_output_object_attributes_hook)
(void);
 #define TARGET_HAVE_LDACQ	(TARGET_ARM_ARCH >= 8 && arm_arch_notm)
 
 /* Nonzero if this chip provides the movw and movt instructions.  */
-#define TARGET_HAVE_MOVT	(arm_arch_thumb2)
+#define TARGET_HAVE_MOVT	(arm_arch_thumb2 || arm_arch8)
 
 /* Nonzero if integer division instructions supported.  */
 #define TARGET_IDIV	((TARGET_ARM && arm_arch_arm_hwdiv)	\
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 
d75a34f10d5ed22cff0a0b5d3ad433f111b059ee..a05e559c905daa55e686491a038342360c721912 
100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -8220,6 +8220,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)
@@ -8306,7 +8312,8 @@ 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
+	      || (TARGET_HAVE_MOVT && !(INTVAL (x) & 0xffff0000)))
 	    return 0;
 	  if (thumb_shiftable_const (INTVAL (x)))
 	    return COSTS_N_INSNS (2);
@@ -9009,7 +9016,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)
     {
@@ -9055,17 +9062,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 immediate for 2byte 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 ((unsigned HOST_WIDE_INT) INTVAL (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);
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 
8aa9fedf5c07e78bc7ba793b39bebcc45a4d5921..ce39bdf5904dec3e12003c411f2a8b326ea939e3 
100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -118,10 +118,10 @@
 ; 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"
@@ -160,6 +160,10 @@
 	      (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")))
diff --git a/gcc/config/arm/thumb1.md b/gcc/config/arm/thumb1.md
index 
072ed4da47ad164eb406bedc3fccc589ac705e9f..47e569d0c259cd17d86a03061e5b47b3dab4579f 
100644
--- a/gcc/config/arm/thumb1.md
+++ b/gcc/config/arm/thumb1.md
@@ -590,8 +590,8 @@
 ;;; ??? 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))"
@@ -609,37 +609,41 @@
     case 2:
       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}\";
+    case 3: 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}
@@ -647,10 +651,11 @@
    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.
@@ -687,7 +692,8 @@
 (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)))]
   "
@@ -714,7 +720,8 @@
 (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)))]
   "
@@ -726,8 +733,8 @@
 )
 
 (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))"
@@ -739,6 +746,8 @@
     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.
@@ -758,9 +767,10 @@
 	}
       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"   "")
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 
3142cd53ae53e90bb1af2f595fe53778c1cbfd3b..860b4c0627e094bae8b3801f9256ff4fec5c8fc2 
100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -1601,6 +1601,10 @@ arm_v8_1a_neon_ok.
 ARM target prefers @code{LDRD} and @code{STRD} instructions over
 @code{LDM} and @code{STM} instructions.
 
+@item arm_thumb1_movt_ko
+ARM target generates Thumb-1 code for @code{-mthumb} with no
+@code{MOVT} instruction available.
+
 @end table
 
 @subsubsection AArch64-specific attributes
diff --git a/gcc/testsuite/gcc.target/arm/pr42574.c 
b/gcc/testsuite/gcc.target/arm/pr42574.c
index 
0ccd05f9922c798611e479d97890aa69b180e989..53aea6224be89d2d771a22f8ecb397276f586234 
100644
--- a/gcc/testsuite/gcc.target/arm/pr42574.c
+++ b/gcc/testsuite/gcc.target/arm/pr42574.c
@@ -1,5 +1,5 @@
 /* { dg-options "-mthumb -Os -fpic" }  */
-/* { dg-require-effective-target arm_thumb1_ok } */
+/* { dg-require-effective-target arm_thumb1_movt_ko } */
 /* { 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).  */
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-
supports.exp
index 
46352b90de7202960116d93523b017d5dc4a1423..f5d73ad2620fa35f0091a890bca63c7d35de1a85 
100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -3329,6 +3329,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 no movt/movw instructions to be available.
+
+proc check_effective_target_arm_thumb1_movt_ko {} {
+    if [check_effective_target_arm_thumb1_ok] {
+	return [expr ![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 { } {

Best regards,

Thomas

> 
> On 17/05/16 11:13, Thomas Preudhomme wrote:
> > Ping?
> > 
> > *** gcc/ChangeLog ***
> > 
> > 2015-11-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): Legalize high part of a label_ref
> >          as a
> >          constant.
> 
> I don't think "Legalize" is the right word here. How about "Strip the HIGH
> part of a label_ref"?
> >          (thumb1_rtx_costs): Also return 0 if setting a half word constant
> >          and
> >          movw is available.
> >          (thumb1_size_rtx_costs): Make set of half word constant also cost
> >          1
> >          extra instruction if MOVW is available.  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.
> >          * 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.
> 
> Please use 'MOVW' consistently in the ChangeLog rather than the lowercase
> 'movw'
> >          * doc/sourcebuild.texi (arm_thumb1_movt_ko): Document new ARM
> >          effective target.
> > 
> > *** gcc/testsuite/ChangeLog ***
> > 
> > 2015-11-13  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> > 
> >          * lib/target-supports.exp
> >          (check_effective_target_arm_thumb1_movt_ko):
> >          Define effective target.
> >          * gcc.target/arm/pr42574.c: Require arm_thumb1_movt_ko instead of
> >          arm_thumb1_ok as effective target to exclude ARMv8-M Baseline.
> > 
> > diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
> > index
> > 47216b4a1959ccdb18e329db411bf7f941e67163..f42e996e5a7ce979fe406b8261d50fb2
> > ba005f6b 100644
> > --- a/gcc/config/arm/arm.h
> > +++ b/gcc/config/arm/arm.h
> > @@ -269,7 +269,7 @@ extern void (*arm_lang_output_object_attributes_hook)
> > (void);
> > 
> >   #define TARGET_HAVE_LDACQ	(TARGET_ARM_ARCH >= 8 && arm_arch_notm)
> >   
> >   /* Nonzero if this chip provides the movw and movt instructions.  */
> > 
> > -#define TARGET_HAVE_MOVT	(arm_arch_thumb2)
> > +#define TARGET_HAVE_MOVT	(arm_arch_thumb2 || arm_arch8)
> > 
> >   /* Nonzero if integer division instructions supported.  */
> >   #define TARGET_IDIV	((TARGET_ARM && arm_arch_arm_hwdiv)	\
> > 
> > diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
> > index
> > d75a34f10d5ed22cff0a0b5d3ad433f111b059ee..13b4b71ac8f9c1da8ef1945f7ff6985c
> > a59f6832 100644
> > --- a/gcc/config/arm/arm.c
> > +++ b/gcc/config/arm/arm.c
> > @@ -8220,6 +8220,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)
> > 
> > @@ -8306,7 +8312,8 @@ 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 ((unsigned HOST_WIDE_INT) INTVAL (x) < 256
> > +	      || (TARGET_HAVE_MOVT && !(INTVAL (x) & 0xffff0000)))
> > 
> >   	    return 0;
> 
> Since you're modifying this line please replace (unsigned HOST_WIDE_INT)
> INTVAL (x) with UINTVAL (x).

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH, ARM 5/7, ping1] Add support for MOVT/MOVW to ARMv8-M Baseline
  2016-05-19 16:11     ` Thomas Preudhomme
@ 2016-05-20 11:15       ` Kyrill Tkachov
  2016-07-07 14:32         ` [PATCH, ARM 5/7] " Thomas Preudhomme
  0 siblings, 1 reply; 11+ messages in thread
From: Kyrill Tkachov @ 2016-05-20 11:15 UTC (permalink / raw)
  To: Thomas Preudhomme, gcc-patches; +Cc: Richard Earnshaw, Ramana Radhakrishnan

Hi Thomas,

On 19/05/16 17:11, Thomas Preudhomme wrote:
> On Wednesday 18 May 2016 12:30:41 Kyrill Tkachov wrote:
>> Hi Thomas,
>>
>> This looks mostly good with a few nits inline.
>> Please repost with the comments addressed.
> Updated ChangeLog entries:
>
> *** gcc/ChangeLog ***
>
> 2016-05-18  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.
>          * 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_ko): Document new ARM
>          effective target.
>
>
> *** gcc/testsuite/ChangeLog ***
>
> 2015-11-13  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>
>          * lib/target-supports.exp (check_effective_target_arm_thumb1_movt_ko):
>          Define effective target.
>          * gcc.target/arm/pr42574.c: Require arm_thumb1_movt_ko instead of
>          arm_thumb1_ok as effective target to exclude ARMv8-M Baseline.

This is ok now, thanks for the changes.
I'd like to see some tests that generate MOVW/MOVT instructions
on ARMv8-M Baseline. They should be easy, just an:
int
foo ()
{
   return CONST;
}

and same for short and long long return types
(to exercise the HI, SI and DImode move patterns).

You can add them as part of this patch or as a separate followup.

Thanks,
Kyrill


>
> and patch:
>
> diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
> index
> 47216b4a1959ccdb18e329db411bf7f941e67163..f42e996e5a7ce979fe406b8261d50fb2ba005f6b
> 100644
> --- a/gcc/config/arm/arm.h
> +++ b/gcc/config/arm/arm.h
> @@ -269,7 +269,7 @@ extern void (*arm_lang_output_object_attributes_hook)
> (void);
>   #define TARGET_HAVE_LDACQ	(TARGET_ARM_ARCH >= 8 && arm_arch_notm)
>   
>   /* Nonzero if this chip provides the movw and movt instructions.  */
> -#define TARGET_HAVE_MOVT	(arm_arch_thumb2)
> +#define TARGET_HAVE_MOVT	(arm_arch_thumb2 || arm_arch8)
>   
>   /* Nonzero if integer division instructions supported.  */
>   #define TARGET_IDIV	((TARGET_ARM && arm_arch_arm_hwdiv)	\
> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
> index
> d75a34f10d5ed22cff0a0b5d3ad433f111b059ee..a05e559c905daa55e686491a038342360c721912
> 100644
> --- a/gcc/config/arm/arm.c
> +++ b/gcc/config/arm/arm.c
> @@ -8220,6 +8220,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)
> @@ -8306,7 +8312,8 @@ 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
> +	      || (TARGET_HAVE_MOVT && !(INTVAL (x) & 0xffff0000)))
>   	    return 0;
>   	  if (thumb_shiftable_const (INTVAL (x)))
>   	    return COSTS_N_INSNS (2);
> @@ -9009,7 +9016,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)
>       {
> @@ -9055,17 +9062,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 immediate for 2byte 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 ((unsigned HOST_WIDE_INT) INTVAL (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);
> diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
> index
> 8aa9fedf5c07e78bc7ba793b39bebcc45a4d5921..ce39bdf5904dec3e12003c411f2a8b326ea939e3
> 100644
> --- a/gcc/config/arm/arm.md
> +++ b/gcc/config/arm/arm.md
> @@ -118,10 +118,10 @@
>   ; 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"
> @@ -160,6 +160,10 @@
>   	      (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")))
> diff --git a/gcc/config/arm/thumb1.md b/gcc/config/arm/thumb1.md
> index
> 072ed4da47ad164eb406bedc3fccc589ac705e9f..47e569d0c259cd17d86a03061e5b47b3dab4579f
> 100644
> --- a/gcc/config/arm/thumb1.md
> +++ b/gcc/config/arm/thumb1.md
> @@ -590,8 +590,8 @@
>   ;;; ??? 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))"
> @@ -609,37 +609,41 @@
>       case 2:
>         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}\";
> +    case 3: 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}
> @@ -647,10 +651,11 @@
>      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.
> @@ -687,7 +692,8 @@
>   (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)))]
>     "
> @@ -714,7 +720,8 @@
>   (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)))]
>     "
> @@ -726,8 +733,8 @@
>   )
>   
>   (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))"
> @@ -739,6 +746,8 @@
>       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.
> @@ -758,9 +767,10 @@
>   	}
>         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"   "")
> diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
> index
> 3142cd53ae53e90bb1af2f595fe53778c1cbfd3b..860b4c0627e094bae8b3801f9256ff4fec5c8fc2
> 100644
> --- a/gcc/doc/sourcebuild.texi
> +++ b/gcc/doc/sourcebuild.texi
> @@ -1601,6 +1601,10 @@ arm_v8_1a_neon_ok.
>   ARM target prefers @code{LDRD} and @code{STRD} instructions over
>   @code{LDM} and @code{STM} instructions.
>   
> +@item arm_thumb1_movt_ko
> +ARM target generates Thumb-1 code for @code{-mthumb} with no
> +@code{MOVT} instruction available.
> +
>   @end table
>   
>   @subsubsection AArch64-specific attributes
> diff --git a/gcc/testsuite/gcc.target/arm/pr42574.c
> b/gcc/testsuite/gcc.target/arm/pr42574.c
> index
> 0ccd05f9922c798611e479d97890aa69b180e989..53aea6224be89d2d771a22f8ecb397276f586234
> 100644
> --- a/gcc/testsuite/gcc.target/arm/pr42574.c
> +++ b/gcc/testsuite/gcc.target/arm/pr42574.c
> @@ -1,5 +1,5 @@
>   /* { dg-options "-mthumb -Os -fpic" }  */
> -/* { dg-require-effective-target arm_thumb1_ok } */
> +/* { dg-require-effective-target arm_thumb1_movt_ko } */
>   /* { 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).  */
> diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-
> supports.exp
> index
> 46352b90de7202960116d93523b017d5dc4a1423..f5d73ad2620fa35f0091a890bca63c7d35de1a85
> 100644
> --- a/gcc/testsuite/lib/target-supports.exp
> +++ b/gcc/testsuite/lib/target-supports.exp
> @@ -3329,6 +3329,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 no movt/movw instructions to be available.
> +
> +proc check_effective_target_arm_thumb1_movt_ko {} {
> +    if [check_effective_target_arm_thumb1_ok] {
> +	return [expr ![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 { } {
>
> Best regards,
>
> Thomas
>
>> On 17/05/16 11:13, Thomas Preudhomme wrote:
>>> Ping?
>>>
>>> *** gcc/ChangeLog ***
>>>
>>> 2015-11-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): Legalize high part of a label_ref
>>>           as a
>>>           constant.
>> I don't think "Legalize" is the right word here. How about "Strip the HIGH
>> part of a label_ref"?
>>>           (thumb1_rtx_costs): Also return 0 if setting a half word constant
>>>           and
>>>           movw is available.
>>>           (thumb1_size_rtx_costs): Make set of half word constant also cost
>>>           1
>>>           extra instruction if MOVW is available.  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.
>>>           * 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.
>> Please use 'MOVW' consistently in the ChangeLog rather than the lowercase
>> 'movw'
>>>           * doc/sourcebuild.texi (arm_thumb1_movt_ko): Document new ARM
>>>           effective target.
>>>
>>> *** gcc/testsuite/ChangeLog ***
>>>
>>> 2015-11-13  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>>
>>>           * lib/target-supports.exp
>>>           (check_effective_target_arm_thumb1_movt_ko):
>>>           Define effective target.
>>>           * gcc.target/arm/pr42574.c: Require arm_thumb1_movt_ko instead of
>>>           arm_thumb1_ok as effective target to exclude ARMv8-M Baseline.
>>>
>>> diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
>>> index
>>> 47216b4a1959ccdb18e329db411bf7f941e67163..f42e996e5a7ce979fe406b8261d50fb2
>>> ba005f6b 100644
>>> --- a/gcc/config/arm/arm.h
>>> +++ b/gcc/config/arm/arm.h
>>> @@ -269,7 +269,7 @@ extern void (*arm_lang_output_object_attributes_hook)
>>> (void);
>>>
>>>    #define TARGET_HAVE_LDACQ	(TARGET_ARM_ARCH >= 8 && arm_arch_notm)
>>>    
>>>    /* Nonzero if this chip provides the movw and movt instructions.  */
>>>
>>> -#define TARGET_HAVE_MOVT	(arm_arch_thumb2)
>>> +#define TARGET_HAVE_MOVT	(arm_arch_thumb2 || arm_arch8)
>>>
>>>    /* Nonzero if integer division instructions supported.  */
>>>    #define TARGET_IDIV	((TARGET_ARM && arm_arch_arm_hwdiv)	\
>>>
>>> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
>>> index
>>> d75a34f10d5ed22cff0a0b5d3ad433f111b059ee..13b4b71ac8f9c1da8ef1945f7ff6985c
>>> a59f6832 100644
>>> --- a/gcc/config/arm/arm.c
>>> +++ b/gcc/config/arm/arm.c
>>> @@ -8220,6 +8220,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)
>>>
>>> @@ -8306,7 +8312,8 @@ 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 ((unsigned HOST_WIDE_INT) INTVAL (x) < 256
>>> +	      || (TARGET_HAVE_MOVT && !(INTVAL (x) & 0xffff0000)))
>>>
>>>    	    return 0;
>> Since you're modifying this line please replace (unsigned HOST_WIDE_INT)
>> INTVAL (x) with UINTVAL (x).

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH, ARM 5/7] Add support for MOVT/MOVW to ARMv8-M Baseline
  2016-05-20 11:15       ` Kyrill Tkachov
@ 2016-07-07 14:32         ` Thomas Preudhomme
  2016-07-13 10:02           ` Kyrill Tkachov
  0 siblings, 1 reply; 11+ messages in thread
From: Thomas Preudhomme @ 2016-07-07 14:32 UTC (permalink / raw)
  To: Kyrill Tkachov; +Cc: gcc-patches, Richard Earnshaw, Ramana Radhakrishnan

[-- Attachment #1: Type: text/plain, Size: 25980 bytes --]

Hi Kyrill,

Please find an updated version in attachment. Please note I made quite a few 
other changes as well. The most important one was to add new ARMv8-M Baseline 
only alternatives to the two movt insns in order to have non predicable output 
template for ARMv8-M Baseline. I also inverted the logic for how to detect 
ARMv8-M Baseline in the testsuite (arm_thumb1_movt_ok rather than *_ko) and 
fixed a couple of typos. I didn't add MOVT test because it is difficult to 
generate. Using -mslow-flash-data should help but it is not available for 
ARMv8-M Baseline as only config/arm/thumb2.md was modified to support this 
option.

Update ChangeLog entries are as follow:


*** gcc/ChangeLog ***

2016-06-20  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.


*** gcc/testsuite/ChangeLog ***

2016-05-23  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.


Best regards,

Thomas

On Friday 20 May 2016 12:14:44 Kyrill Tkachov wrote:
> Hi Thomas,
> 
> On 19/05/16 17:11, Thomas Preudhomme wrote:
> > On Wednesday 18 May 2016 12:30:41 Kyrill Tkachov wrote:
> >> Hi Thomas,
> >> 
> >> This looks mostly good with a few nits inline.
> >> Please repost with the comments addressed.
> > 
> > Updated ChangeLog entries:
> > 
> > *** gcc/ChangeLog ***
> > 
> > 2016-05-18  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.
> >          * 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_ko): Document new ARM
> >          effective target.
> > 
> > *** gcc/testsuite/ChangeLog ***
> > 
> > 2015-11-13  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> > 
> >          * lib/target-supports.exp
> >          (check_effective_target_arm_thumb1_movt_ko):
> >          Define effective target.
> >          * gcc.target/arm/pr42574.c: Require arm_thumb1_movt_ko instead of
> >          arm_thumb1_ok as effective target to exclude ARMv8-M Baseline.
> 
> This is ok now, thanks for the changes.
> I'd like to see some tests that generate MOVW/MOVT instructions
> on ARMv8-M Baseline. They should be easy, just an:
> int
> foo ()
> {
>    return CONST;
> }
> 
> and same for short and long long return types
> (to exercise the HI, SI and DImode move patterns).
> 
> You can add them as part of this patch or as a separate followup.
> 
> Thanks,
> Kyrill
> 
> > and patch:
> > 
> > diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
> > index
> > 47216b4a1959ccdb18e329db411bf7f941e67163..f42e996e5a7ce979fe406b8261d50fb2
> > ba005f6b 100644
> > --- a/gcc/config/arm/arm.h
> > +++ b/gcc/config/arm/arm.h
> > @@ -269,7 +269,7 @@ extern void (*arm_lang_output_object_attributes_hook)
> > (void);
> > 
> >   #define TARGET_HAVE_LDACQ	(TARGET_ARM_ARCH >= 8 && arm_arch_notm)
> >   
> >   /* Nonzero if this chip provides the movw and movt instructions.  */
> > 
> > -#define TARGET_HAVE_MOVT	(arm_arch_thumb2)
> > +#define TARGET_HAVE_MOVT	(arm_arch_thumb2 || arm_arch8)
> > 
> >   /* Nonzero if integer division instructions supported.  */
> >   #define TARGET_IDIV	((TARGET_ARM && arm_arch_arm_hwdiv)	\
> > 
> > diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
> > index
> > d75a34f10d5ed22cff0a0b5d3ad433f111b059ee..a05e559c905daa55e686491a03834236
> > 0c721912 100644
> > --- a/gcc/config/arm/arm.c
> > +++ b/gcc/config/arm/arm.c
> > @@ -8220,6 +8220,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)
> > 
> > @@ -8306,7 +8312,8 @@ 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
> > +	      || (TARGET_HAVE_MOVT && !(INTVAL (x) & 0xffff0000)))
> > 
> >   	    return 0;
> >   	  
> >   	  if (thumb_shiftable_const (INTVAL (x)))
> >   	  
> >   	    return COSTS_N_INSNS (2);
> > 
> > @@ -9009,7 +9016,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)
> >     
> >       {
> > 
> > @@ -9055,17 +9062,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 immediate for 2byte 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 ((unsigned HOST_WIDE_INT) INTVAL (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);
> > 
> > diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
> > index
> > 8aa9fedf5c07e78bc7ba793b39bebcc45a4d5921..ce39bdf5904dec3e12003c411f2a8b32
> > 6ea939e3 100644
> > --- a/gcc/config/arm/arm.md
> > +++ b/gcc/config/arm/arm.md
> > @@ -118,10 +118,10 @@
> > 
> >   ; 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,iwmmx
> > t,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"
> > 
> > @@ -160,6 +160,10 @@
> > 
> >   	      (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")))
> > 
> > diff --git a/gcc/config/arm/thumb1.md b/gcc/config/arm/thumb1.md
> > index
> > 072ed4da47ad164eb406bedc3fccc589ac705e9f..47e569d0c259cd17d86a03061e5b47b3
> > dab4579f 100644
> > --- a/gcc/config/arm/thumb1.md
> > +++ b/gcc/config/arm/thumb1.md
> > @@ -590,8 +590,8 @@
> > 
> >   ;;; ??? 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))"
> > 
> > @@ -609,37 +609,41 @@
> > 
> >       case 2:
> >         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}\";
> > +    case 3: 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}
> > 
> > @@ -647,10 +651,11 @@
> > 
> >      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_r
> > eg") +   (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.
> > 
> > @@ -687,7 +692,8 @@
> > 
> >   (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)))]
> >     
> >     "
> > 
> > @@ -714,7 +720,8 @@
> > 
> >   (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)))]
> >     
> >     "
> > 
> > @@ -726,8 +733,8 @@
> > 
> >   )
> >   
> >   (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))"
> > 
> > @@ -739,6 +746,8 @@
> > 
> >       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.
> > 
> > @@ -758,9 +767,10 @@
> > 
> >   	}
> >   	
> >         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"   "")
> > 
> > diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
> > index
> > 3142cd53ae53e90bb1af2f595fe53778c1cbfd3b..860b4c0627e094bae8b3801f9256ff4f
> > ec5c8fc2 100644
> > --- a/gcc/doc/sourcebuild.texi
> > +++ b/gcc/doc/sourcebuild.texi
> > @@ -1601,6 +1601,10 @@ arm_v8_1a_neon_ok.
> > 
> >   ARM target prefers @code{LDRD} and @code{STRD} instructions over
> >   @code{LDM} and @code{STM} instructions.
> > 
> > +@item arm_thumb1_movt_ko
> > +ARM target generates Thumb-1 code for @code{-mthumb} with no
> > +@code{MOVT} instruction available.
> > +
> > 
> >   @end table
> >   
> >   @subsubsection AArch64-specific attributes
> > 
> > diff --git a/gcc/testsuite/gcc.target/arm/pr42574.c
> > b/gcc/testsuite/gcc.target/arm/pr42574.c
> > index
> > 0ccd05f9922c798611e479d97890aa69b180e989..53aea6224be89d2d771a22f8ecb39727
> > 6f586234 100644
> > --- a/gcc/testsuite/gcc.target/arm/pr42574.c
> > +++ b/gcc/testsuite/gcc.target/arm/pr42574.c
> > @@ -1,5 +1,5 @@
> > 
> >   /* { dg-options "-mthumb -Os -fpic" }  */
> > 
> > -/* { dg-require-effective-target arm_thumb1_ok } */
> > +/* { dg-require-effective-target arm_thumb1_movt_ko } */
> > 
> >   /* { 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).  */
> > 
> > diff --git a/gcc/testsuite/lib/target-supports.exp
> > b/gcc/testsuite/lib/target- supports.exp
> > index
> > 46352b90de7202960116d93523b017d5dc4a1423..f5d73ad2620fa35f0091a890bca63c7d
> > 35de1a85 100644
> > --- a/gcc/testsuite/lib/target-supports.exp
> > +++ b/gcc/testsuite/lib/target-supports.exp
> > @@ -3329,6 +3329,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 no movt/movw instructions to be available.
> > +
> > +proc check_effective_target_arm_thumb1_movt_ko {} {
> > +    if [check_effective_target_arm_thumb1_ok] {
> > +	return [expr ![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 { } {
> > 
> > Best regards,
> > 
> > Thomas
> > 
> >> On 17/05/16 11:13, Thomas Preudhomme wrote:
> >>> Ping?
> >>> 
> >>> *** gcc/ChangeLog ***
> >>> 
> >>> 2015-11-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): Legalize high part of a
> >>>           label_ref
> >>>           as a
> >>>           constant.
> >> 
> >> I don't think "Legalize" is the right word here. How about "Strip the
> >> HIGH
> >> part of a label_ref"?
> >> 
> >>>           (thumb1_rtx_costs): Also return 0 if setting a half word
> >>>           constant
> >>>           and
> >>>           movw is available.
> >>>           (thumb1_size_rtx_costs): Make set of half word constant also
> >>>           cost
> >>>           1
> >>>           extra instruction if MOVW is available.  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.
> >>>           * 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.
> >> 
> >> Please use 'MOVW' consistently in the ChangeLog rather than the lowercase
> >> 'movw'
> >> 
> >>>           * doc/sourcebuild.texi (arm_thumb1_movt_ko): Document new ARM
> >>>           effective target.
> >>> 
> >>> *** gcc/testsuite/ChangeLog ***
> >>> 
> >>> 2015-11-13  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> >>> 
> >>>           * lib/target-supports.exp
> >>>           (check_effective_target_arm_thumb1_movt_ko):
> >>>           Define effective target.
> >>>           * gcc.target/arm/pr42574.c: Require arm_thumb1_movt_ko instead
> >>>           of
> >>>           arm_thumb1_ok as effective target to exclude ARMv8-M Baseline.
> >>> 
> >>> diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
> >>> index
> >>> 47216b4a1959ccdb18e329db411bf7f941e67163..f42e996e5a7ce979fe406b8261d50f
> >>> b2
> >>> ba005f6b 100644
> >>> --- a/gcc/config/arm/arm.h
> >>> +++ b/gcc/config/arm/arm.h
> >>> @@ -269,7 +269,7 @@ extern void
> >>> (*arm_lang_output_object_attributes_hook)
> >>> (void);
> >>> 
> >>>    #define TARGET_HAVE_LDACQ	(TARGET_ARM_ARCH >= 8 && arm_arch_notm)
> >>>    
> >>>    /* Nonzero if this chip provides the movw and movt instructions.  */
> >>> 
> >>> -#define TARGET_HAVE_MOVT	(arm_arch_thumb2)
> >>> +#define TARGET_HAVE_MOVT	(arm_arch_thumb2 || arm_arch8)
> >>> 
> >>>    /* Nonzero if integer division instructions supported.  */
> >>>    #define TARGET_IDIV	((TARGET_ARM && arm_arch_arm_hwdiv)	\
> >>> 
> >>> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
> >>> index
> >>> d75a34f10d5ed22cff0a0b5d3ad433f111b059ee..13b4b71ac8f9c1da8ef1945f7ff698
> >>> 5c
> >>> a59f6832 100644
> >>> --- a/gcc/config/arm/arm.c
> >>> +++ b/gcc/config/arm/arm.c
> >>> @@ -8220,6 +8220,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)
> >>> 
> >>> @@ -8306,7 +8312,8 @@ 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 ((unsigned HOST_WIDE_INT) INTVAL (x) < 256
> >>> +	      || (TARGET_HAVE_MOVT && !(INTVAL (x) & 0xffff0000)))
> >>> 
> >>>    	    return 0;
> >> 
> >> Since you're modifying this line please replace (unsigned HOST_WIDE_INT)
> >> INTVAL (x) with UINTVAL (x).

[-- Attachment #2: movt_movw_armv8m_support.patch --]
[-- Type: text/x-patch, Size: 16040 bytes --]

diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 615065447b43ef44202a892a938bc7c8a2425222..269611060ec2f15047b4976d412b8c5aa2797005 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -268,8 +268,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)	\
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 109792dbf4e8b7ab130abdbc5622b71953b70df2..eea1960190a65ea9853c7ed7d7a3cfa9dd9c65ec 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -8225,6 +8225,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)
@@ -8311,7 +8317,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);
@@ -9014,7 +9022,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)
     {
@@ -9060,17 +9068,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);
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 45796578af061c3259ae02b1b403d81ed7b03807..1e6788f1180f9202b8aa06b244b7d1d07fc9ded0 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -118,10 +118,10 @@
 ; 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"
@@ -160,6 +160,10 @@
 	      (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")))
@@ -5699,12 +5703,15 @@
 ;; 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")]
@@ -10958,13 +10965,16 @@
 ;; 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")]
diff --git a/gcc/config/arm/thumb1.md b/gcc/config/arm/thumb1.md
index 035641b3335797cb843a5741d7372492d5a91cfc..b317f1b0637e02f105f10efb18270f4a35801c7c 100644
--- a/gcc/config/arm/thumb1.md
+++ b/gcc/config/arm/thumb1.md
@@ -590,8 +590,8 @@
 ;;; ??? 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))"
@@ -610,36 +610,41 @@
       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}
@@ -647,10 +652,11 @@
    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.
@@ -687,7 +693,8 @@
 (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)))]
   "
@@ -714,7 +721,8 @@
 (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)))]
   "
@@ -726,8 +734,8 @@
 )
 
 (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))"
@@ -739,6 +747,8 @@
     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.
@@ -758,9 +768,10 @@
 	}
       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"   "")
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 0c03920cbec090b07f2559d6471c6eac9bb0c18a..2735daf93d4ad07e8554fafd3cb3408c217e9f8f 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -1604,6 +1604,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
diff --git a/gcc/testsuite/gcc.target/arm/movdi_movw.c b/gcc/testsuite/gcc.target/arm/movdi_movw.c
new file mode 100644
index 0000000000000000000000000000000000000000..0f6b839da614c56766e92e3da125551df47890fc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/movdi_movw.c
@@ -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
index 0000000000000000000000000000000000000000..b097a8a019c74507f0c182af6ba5cf526369564b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/movhi_movw.c
@@ -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
index 0000000000000000000000000000000000000000..d50906e76ab412ead71ff576d2f28d520234f58d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/movsi_movw.c
@@ -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 } } */
diff --git a/gcc/testsuite/gcc.target/arm/pr42574.c b/gcc/testsuite/gcc.target/arm/pr42574.c
index 0ccd05f9922c798611e479d97890aa69b180e989..e3476f37788a2b3144454aef04a9b45c0b4ac398 100644
--- a/gcc/testsuite/gcc.target/arm/pr42574.c
+++ b/gcc/testsuite/gcc.target/arm/pr42574.c
@@ -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).  */
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index ace1b32f755d033eb035b217e422bdc5f4dc2dea..f678eaa86731ba552d4e528d326c90a5ae0bbfaf 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -3329,6 +3329,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 { } {

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH, ARM 5/7] Add support for MOVT/MOVW to ARMv8-M Baseline
  2016-07-07 14:32         ` [PATCH, ARM 5/7] " Thomas Preudhomme
@ 2016-07-13 10:02           ` Kyrill Tkachov
  2016-07-13 15:15             ` Christophe Lyon
  0 siblings, 1 reply; 11+ messages in thread
From: Kyrill Tkachov @ 2016-07-13 10:02 UTC (permalink / raw)
  To: Thomas Preudhomme; +Cc: gcc-patches, Richard Earnshaw, Ramana Radhakrishnan

Hi Thomas,

On 07/07/16 15:32, Thomas Preudhomme wrote:
> Hi Kyrill,
>
> Please find an updated version in attachment. Please note I made quite a few
> other changes as well. The most important one was to add new ARMv8-M Baseline
> only alternatives to the two movt insns in order to have non predicable output
> template for ARMv8-M Baseline. I also inverted the logic for how to detect
> ARMv8-M Baseline in the testsuite (arm_thumb1_movt_ok rather than *_ko) and
> fixed a couple of typos. I didn't add MOVT test because it is difficult to
> generate. Using -mslow-flash-data should help but it is not available for
> ARMv8-M Baseline as only config/arm/thumb2.md was modified to support this
> option.
>
> Update ChangeLog entries are as follow:
>
>
> *** gcc/ChangeLog ***
>
> 2016-06-20  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.
>
>
> *** gcc/testsuite/ChangeLog ***
>
> 2016-05-23  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.

Ok.
Thanks,
Kyrill

>
> Best regards,
>
> Thomas
>
> On Friday 20 May 2016 12:14:44 Kyrill Tkachov wrote:
>> Hi Thomas,
>>
>> On 19/05/16 17:11, Thomas Preudhomme wrote:
>>> On Wednesday 18 May 2016 12:30:41 Kyrill Tkachov wrote:
>>>> Hi Thomas,
>>>>
>>>> This looks mostly good with a few nits inline.
>>>> Please repost with the comments addressed.
>>> Updated ChangeLog entries:
>>>
>>> *** gcc/ChangeLog ***
>>>
>>> 2016-05-18  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.
>>>           * 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_ko): Document new ARM
>>>           effective target.
>>>
>>> *** gcc/testsuite/ChangeLog ***
>>>
>>> 2015-11-13  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>>
>>>           * lib/target-supports.exp
>>>           (check_effective_target_arm_thumb1_movt_ko):
>>>           Define effective target.
>>>           * gcc.target/arm/pr42574.c: Require arm_thumb1_movt_ko instead of
>>>           arm_thumb1_ok as effective target to exclude ARMv8-M Baseline.
>> This is ok now, thanks for the changes.
>> I'd like to see some tests that generate MOVW/MOVT instructions
>> on ARMv8-M Baseline. They should be easy, just an:
>> int
>> foo ()
>> {
>>     return CONST;
>> }
>>
>> and same for short and long long return types
>> (to exercise the HI, SI and DImode move patterns).
>>
>> You can add them as part of this patch or as a separate followup.
>>
>> Thanks,
>> Kyrill
>>
>>> and patch:
>>>
>>> diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
>>> index
>>> 47216b4a1959ccdb18e329db411bf7f941e67163..f42e996e5a7ce979fe406b8261d50fb2
>>> ba005f6b 100644
>>> --- a/gcc/config/arm/arm.h
>>> +++ b/gcc/config/arm/arm.h
>>> @@ -269,7 +269,7 @@ extern void (*arm_lang_output_object_attributes_hook)
>>> (void);
>>>
>>>    #define TARGET_HAVE_LDACQ	(TARGET_ARM_ARCH >= 8 && arm_arch_notm)
>>>    
>>>    /* Nonzero if this chip provides the movw and movt instructions.  */
>>>
>>> -#define TARGET_HAVE_MOVT	(arm_arch_thumb2)
>>> +#define TARGET_HAVE_MOVT	(arm_arch_thumb2 || arm_arch8)
>>>
>>>    /* Nonzero if integer division instructions supported.  */
>>>    #define TARGET_IDIV	((TARGET_ARM && arm_arch_arm_hwdiv)	\
>>>
>>> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
>>> index
>>> d75a34f10d5ed22cff0a0b5d3ad433f111b059ee..a05e559c905daa55e686491a03834236
>>> 0c721912 100644
>>> --- a/gcc/config/arm/arm.c
>>> +++ b/gcc/config/arm/arm.c
>>> @@ -8220,6 +8220,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)
>>>
>>> @@ -8306,7 +8312,8 @@ 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
>>> +	      || (TARGET_HAVE_MOVT && !(INTVAL (x) & 0xffff0000)))
>>>
>>>    	    return 0;
>>>    	
>>>    	  if (thumb_shiftable_const (INTVAL (x)))
>>>    	
>>>    	    return COSTS_N_INSNS (2);
>>>
>>> @@ -9009,7 +9016,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)
>>>      
>>>        {
>>>
>>> @@ -9055,17 +9062,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 immediate for 2byte 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 ((unsigned HOST_WIDE_INT) INTVAL (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);
>>>
>>> diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
>>> index
>>> 8aa9fedf5c07e78bc7ba793b39bebcc45a4d5921..ce39bdf5904dec3e12003c411f2a8b32
>>> 6ea939e3 100644
>>> --- a/gcc/config/arm/arm.md
>>> +++ b/gcc/config/arm/arm.md
>>> @@ -118,10 +118,10 @@
>>>
>>>    ; 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,iwmmx
>>> t,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"
>>>
>>> @@ -160,6 +160,10 @@
>>>
>>>    	      (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")))
>>>
>>> diff --git a/gcc/config/arm/thumb1.md b/gcc/config/arm/thumb1.md
>>> index
>>> 072ed4da47ad164eb406bedc3fccc589ac705e9f..47e569d0c259cd17d86a03061e5b47b3
>>> dab4579f 100644
>>> --- a/gcc/config/arm/thumb1.md
>>> +++ b/gcc/config/arm/thumb1.md
>>> @@ -590,8 +590,8 @@
>>>
>>>    ;;; ??? 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))"
>>>
>>> @@ -609,37 +609,41 @@
>>>
>>>        case 2:
>>>          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}\";
>>> +    case 3: 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}
>>>
>>> @@ -647,10 +651,11 @@
>>>
>>>       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_r
>>> eg") +   (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.
>>>
>>> @@ -687,7 +692,8 @@
>>>
>>>    (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)))]
>>>      
>>>      "
>>>
>>> @@ -714,7 +720,8 @@
>>>
>>>    (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)))]
>>>      
>>>      "
>>>
>>> @@ -726,8 +733,8 @@
>>>
>>>    )
>>>    
>>>    (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))"
>>>
>>> @@ -739,6 +746,8 @@
>>>
>>>        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.
>>>
>>> @@ -758,9 +767,10 @@
>>>
>>>    	}
>>>    	
>>>          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"   "")
>>>
>>> diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
>>> index
>>> 3142cd53ae53e90bb1af2f595fe53778c1cbfd3b..860b4c0627e094bae8b3801f9256ff4f
>>> ec5c8fc2 100644
>>> --- a/gcc/doc/sourcebuild.texi
>>> +++ b/gcc/doc/sourcebuild.texi
>>> @@ -1601,6 +1601,10 @@ arm_v8_1a_neon_ok.
>>>
>>>    ARM target prefers @code{LDRD} and @code{STRD} instructions over
>>>    @code{LDM} and @code{STM} instructions.
>>>
>>> +@item arm_thumb1_movt_ko
>>> +ARM target generates Thumb-1 code for @code{-mthumb} with no
>>> +@code{MOVT} instruction available.
>>> +
>>>
>>>    @end table
>>>    
>>>    @subsubsection AArch64-specific attributes
>>>
>>> diff --git a/gcc/testsuite/gcc.target/arm/pr42574.c
>>> b/gcc/testsuite/gcc.target/arm/pr42574.c
>>> index
>>> 0ccd05f9922c798611e479d97890aa69b180e989..53aea6224be89d2d771a22f8ecb39727
>>> 6f586234 100644
>>> --- a/gcc/testsuite/gcc.target/arm/pr42574.c
>>> +++ b/gcc/testsuite/gcc.target/arm/pr42574.c
>>> @@ -1,5 +1,5 @@
>>>
>>>    /* { dg-options "-mthumb -Os -fpic" }  */
>>>
>>> -/* { dg-require-effective-target arm_thumb1_ok } */
>>> +/* { dg-require-effective-target arm_thumb1_movt_ko } */
>>>
>>>    /* { 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).  */
>>>
>>> diff --git a/gcc/testsuite/lib/target-supports.exp
>>> b/gcc/testsuite/lib/target- supports.exp
>>> index
>>> 46352b90de7202960116d93523b017d5dc4a1423..f5d73ad2620fa35f0091a890bca63c7d
>>> 35de1a85 100644
>>> --- a/gcc/testsuite/lib/target-supports.exp
>>> +++ b/gcc/testsuite/lib/target-supports.exp
>>> @@ -3329,6 +3329,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 no movt/movw instructions to be available.
>>> +
>>> +proc check_effective_target_arm_thumb1_movt_ko {} {
>>> +    if [check_effective_target_arm_thumb1_ok] {
>>> +	return [expr ![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 { } {
>>>
>>> Best regards,
>>>
>>> Thomas
>>>
>>>> On 17/05/16 11:13, Thomas Preudhomme wrote:
>>>>> Ping?
>>>>>
>>>>> *** gcc/ChangeLog ***
>>>>>
>>>>> 2015-11-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): Legalize high part of a
>>>>>            label_ref
>>>>>            as a
>>>>>            constant.
>>>> I don't think "Legalize" is the right word here. How about "Strip the
>>>> HIGH
>>>> part of a label_ref"?
>>>>
>>>>>            (thumb1_rtx_costs): Also return 0 if setting a half word
>>>>>            constant
>>>>>            and
>>>>>            movw is available.
>>>>>            (thumb1_size_rtx_costs): Make set of half word constant also
>>>>>            cost
>>>>>            1
>>>>>            extra instruction if MOVW is available.  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.
>>>>>            * 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.
>>>> Please use 'MOVW' consistently in the ChangeLog rather than the lowercase
>>>> 'movw'
>>>>
>>>>>            * doc/sourcebuild.texi (arm_thumb1_movt_ko): Document new ARM
>>>>>            effective target.
>>>>>
>>>>> *** gcc/testsuite/ChangeLog ***
>>>>>
>>>>> 2015-11-13  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>>>>
>>>>>            * lib/target-supports.exp
>>>>>            (check_effective_target_arm_thumb1_movt_ko):
>>>>>            Define effective target.
>>>>>            * gcc.target/arm/pr42574.c: Require arm_thumb1_movt_ko instead
>>>>>            of
>>>>>            arm_thumb1_ok as effective target to exclude ARMv8-M Baseline.
>>>>>
>>>>> diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
>>>>> index
>>>>> 47216b4a1959ccdb18e329db411bf7f941e67163..f42e996e5a7ce979fe406b8261d50f
>>>>> b2
>>>>> ba005f6b 100644
>>>>> --- a/gcc/config/arm/arm.h
>>>>> +++ b/gcc/config/arm/arm.h
>>>>> @@ -269,7 +269,7 @@ extern void
>>>>> (*arm_lang_output_object_attributes_hook)
>>>>> (void);
>>>>>
>>>>>     #define TARGET_HAVE_LDACQ	(TARGET_ARM_ARCH >= 8 && arm_arch_notm)
>>>>>     
>>>>>     /* Nonzero if this chip provides the movw and movt instructions.  */
>>>>>
>>>>> -#define TARGET_HAVE_MOVT	(arm_arch_thumb2)
>>>>> +#define TARGET_HAVE_MOVT	(arm_arch_thumb2 || arm_arch8)
>>>>>
>>>>>     /* Nonzero if integer division instructions supported.  */
>>>>>     #define TARGET_IDIV	((TARGET_ARM && arm_arch_arm_hwdiv)	\
>>>>>
>>>>> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
>>>>> index
>>>>> d75a34f10d5ed22cff0a0b5d3ad433f111b059ee..13b4b71ac8f9c1da8ef1945f7ff698
>>>>> 5c
>>>>> a59f6832 100644
>>>>> --- a/gcc/config/arm/arm.c
>>>>> +++ b/gcc/config/arm/arm.c
>>>>> @@ -8220,6 +8220,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)
>>>>>
>>>>> @@ -8306,7 +8312,8 @@ 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 ((unsigned HOST_WIDE_INT) INTVAL (x) < 256
>>>>> +	      || (TARGET_HAVE_MOVT && !(INTVAL (x) & 0xffff0000)))
>>>>>
>>>>>     	    return 0;
>>>> Since you're modifying this line please replace (unsigned HOST_WIDE_INT)
>>>> INTVAL (x) with UINTVAL (x).

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH, ARM 5/7] Add support for MOVT/MOVW to ARMv8-M Baseline
  2016-07-13 10:02           ` Kyrill Tkachov
@ 2016-07-13 15:15             ` Christophe Lyon
  2016-07-13 15:34               ` Thomas Preudhomme
  0 siblings, 1 reply; 11+ messages in thread
From: Christophe Lyon @ 2016-07-13 15:15 UTC (permalink / raw)
  To: Kyrill Tkachov
  Cc: Thomas Preudhomme, gcc-patches, Richard Earnshaw, Ramana Radhakrishnan

Hi Thomas,


On 13 July 2016 at 12:01, Kyrill Tkachov <kyrylo.tkachov@foss.arm.com> wrote:
> Hi Thomas,
>
>
> On 07/07/16 15:32, Thomas Preudhomme wrote:
>>
>> Hi Kyrill,
>>
>> Please find an updated version in attachment. Please note I made quite a
>> few
>> other changes as well. The most important one was to add new ARMv8-M
>> Baseline
>> only alternatives to the two movt insns in order to have non predicable
>> output
>> template for ARMv8-M Baseline. I also inverted the logic for how to detect
>> ARMv8-M Baseline in the testsuite (arm_thumb1_movt_ok rather than *_ko)
>> and
>> fixed a couple of typos. I didn't add MOVT test because it is difficult to
>> generate. Using -mslow-flash-data should help but it is not available for
>> ARMv8-M Baseline as only config/arm/thumb2.md was modified to support this
>> option.
>>
>> Update ChangeLog entries are as follow:
>>
>>
>> *** gcc/ChangeLog ***
>>
>> 2016-06-20  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.
>>
>>
>> *** gcc/testsuite/ChangeLog ***
>>
>> 2016-05-23  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.
>
>
> Ok.
> Thanks,
> Kyrill
>

I'm seeing:
gcc.target/arm/pr42574.c: syntax error in target selector
"arm_thumb1_ok && { ! arm_thumb1_movt_ok }" for " dg-do 1 compile {
arm_thumb1_ok && { ! arm_thumb1_movt_ok } } "

Can you fix it?

Thanks,

Christophe

>
>>
>> Best regards,
>>
>> Thomas
>>
>> On Friday 20 May 2016 12:14:44 Kyrill Tkachov wrote:
>>>
>>> Hi Thomas,
>>>
>>> On 19/05/16 17:11, Thomas Preudhomme wrote:
>>>>
>>>> On Wednesday 18 May 2016 12:30:41 Kyrill Tkachov wrote:
>>>>>
>>>>> Hi Thomas,
>>>>>
>>>>> This looks mostly good with a few nits inline.
>>>>> Please repost with the comments addressed.
>>>>
>>>> Updated ChangeLog entries:
>>>>
>>>> *** gcc/ChangeLog ***
>>>>
>>>> 2016-05-18  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.
>>>>           * 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_ko): Document new ARM
>>>>           effective target.
>>>>
>>>> *** gcc/testsuite/ChangeLog ***
>>>>
>>>> 2015-11-13  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>>>
>>>>           * lib/target-supports.exp
>>>>           (check_effective_target_arm_thumb1_movt_ko):
>>>>           Define effective target.
>>>>           * gcc.target/arm/pr42574.c: Require arm_thumb1_movt_ko instead
>>>> of
>>>>           arm_thumb1_ok as effective target to exclude ARMv8-M Baseline.
>>>
>>> This is ok now, thanks for the changes.
>>> I'd like to see some tests that generate MOVW/MOVT instructions
>>> on ARMv8-M Baseline. They should be easy, just an:
>>> int
>>> foo ()
>>> {
>>>     return CONST;
>>> }
>>>
>>> and same for short and long long return types
>>> (to exercise the HI, SI and DImode move patterns).
>>>
>>> You can add them as part of this patch or as a separate followup.
>>>
>>> Thanks,
>>> Kyrill
>>>
>>>> and patch:
>>>>
>>>> diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
>>>> index
>>>>
>>>> 47216b4a1959ccdb18e329db411bf7f941e67163..f42e996e5a7ce979fe406b8261d50fb2
>>>> ba005f6b 100644
>>>> --- a/gcc/config/arm/arm.h
>>>> +++ b/gcc/config/arm/arm.h
>>>> @@ -269,7 +269,7 @@ extern void
>>>> (*arm_lang_output_object_attributes_hook)
>>>> (void);
>>>>
>>>>    #define TARGET_HAVE_LDACQ    (TARGET_ARM_ARCH >= 8 && arm_arch_notm)
>>>>       /* Nonzero if this chip provides the movw and movt instructions.
>>>> */
>>>>
>>>> -#define TARGET_HAVE_MOVT       (arm_arch_thumb2)
>>>> +#define TARGET_HAVE_MOVT       (arm_arch_thumb2 || arm_arch8)
>>>>
>>>>    /* Nonzero if integer division instructions supported.  */
>>>>    #define TARGET_IDIV  ((TARGET_ARM && arm_arch_arm_hwdiv)     \
>>>>
>>>> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
>>>> index
>>>>
>>>> d75a34f10d5ed22cff0a0b5d3ad433f111b059ee..a05e559c905daa55e686491a03834236
>>>> 0c721912 100644
>>>> --- a/gcc/config/arm/arm.c
>>>> +++ b/gcc/config/arm/arm.c
>>>> @@ -8220,6 +8220,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)
>>>>
>>>> @@ -8306,7 +8312,8 @@ 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
>>>> +             || (TARGET_HAVE_MOVT && !(INTVAL (x) & 0xffff0000)))
>>>>
>>>>             return 0;
>>>>
>>>>           if (thumb_shiftable_const (INTVAL (x)))
>>>>
>>>>             return COSTS_N_INSNS (2);
>>>>
>>>> @@ -9009,7 +9016,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)
>>>>             {
>>>>
>>>> @@ -9055,17 +9062,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 immediate for 2byte 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 ((unsigned HOST_WIDE_INT) INTVAL (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);
>>>>
>>>> diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
>>>> index
>>>>
>>>> 8aa9fedf5c07e78bc7ba793b39bebcc45a4d5921..ce39bdf5904dec3e12003c411f2a8b32
>>>> 6ea939e3 100644
>>>> --- a/gcc/config/arm/arm.md
>>>> +++ b/gcc/config/arm/arm.md
>>>> @@ -118,10 +118,10 @@
>>>>
>>>>    ; 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,iwmmx
>>>> t,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"
>>>>
>>>> @@ -160,6 +160,10 @@
>>>>
>>>>               (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")))
>>>>
>>>> diff --git a/gcc/config/arm/thumb1.md b/gcc/config/arm/thumb1.md
>>>> index
>>>>
>>>> 072ed4da47ad164eb406bedc3fccc589ac705e9f..47e569d0c259cd17d86a03061e5b47b3
>>>> dab4579f 100644
>>>> --- a/gcc/config/arm/thumb1.md
>>>> +++ b/gcc/config/arm/thumb1.md
>>>> @@ -590,8 +590,8 @@
>>>>
>>>>    ;;; ??? 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))"
>>>>
>>>> @@ -609,37 +609,41 @@
>>>>
>>>>        case 2:
>>>>          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}\";
>>>> +    case 3: 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}
>>>>
>>>> @@ -647,10 +651,11 @@
>>>>
>>>>       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_r
>>>> eg") +   (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.
>>>>
>>>> @@ -687,7 +692,8 @@
>>>>
>>>>    (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)))]
>>>>           "
>>>>
>>>> @@ -714,7 +720,8 @@
>>>>
>>>>    (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)))]
>>>>           "
>>>>
>>>> @@ -726,8 +733,8 @@
>>>>
>>>>    )
>>>>       (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))"
>>>>
>>>> @@ -739,6 +746,8 @@
>>>>
>>>>        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.
>>>>
>>>> @@ -758,9 +767,10 @@
>>>>
>>>>         }
>>>>
>>>>          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"   "")
>>>>
>>>> diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
>>>> index
>>>>
>>>> 3142cd53ae53e90bb1af2f595fe53778c1cbfd3b..860b4c0627e094bae8b3801f9256ff4f
>>>> ec5c8fc2 100644
>>>> --- a/gcc/doc/sourcebuild.texi
>>>> +++ b/gcc/doc/sourcebuild.texi
>>>> @@ -1601,6 +1601,10 @@ arm_v8_1a_neon_ok.
>>>>
>>>>    ARM target prefers @code{LDRD} and @code{STRD} instructions over
>>>>    @code{LDM} and @code{STM} instructions.
>>>>
>>>> +@item arm_thumb1_movt_ko
>>>> +ARM target generates Thumb-1 code for @code{-mthumb} with no
>>>> +@code{MOVT} instruction available.
>>>> +
>>>>
>>>>    @end table
>>>>       @subsubsection AArch64-specific attributes
>>>>
>>>> diff --git a/gcc/testsuite/gcc.target/arm/pr42574.c
>>>> b/gcc/testsuite/gcc.target/arm/pr42574.c
>>>> index
>>>>
>>>> 0ccd05f9922c798611e479d97890aa69b180e989..53aea6224be89d2d771a22f8ecb39727
>>>> 6f586234 100644
>>>> --- a/gcc/testsuite/gcc.target/arm/pr42574.c
>>>> +++ b/gcc/testsuite/gcc.target/arm/pr42574.c
>>>> @@ -1,5 +1,5 @@
>>>>
>>>>    /* { dg-options "-mthumb -Os -fpic" }  */
>>>>
>>>> -/* { dg-require-effective-target arm_thumb1_ok } */
>>>> +/* { dg-require-effective-target arm_thumb1_movt_ko } */
>>>>
>>>>    /* { 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).  */
>>>>
>>>> diff --git a/gcc/testsuite/lib/target-supports.exp
>>>> b/gcc/testsuite/lib/target- supports.exp
>>>> index
>>>>
>>>> 46352b90de7202960116d93523b017d5dc4a1423..f5d73ad2620fa35f0091a890bca63c7d
>>>> 35de1a85 100644
>>>> --- a/gcc/testsuite/lib/target-supports.exp
>>>> +++ b/gcc/testsuite/lib/target-supports.exp
>>>> @@ -3329,6 +3329,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 no movt/movw instructions to be available.
>>>> +
>>>> +proc check_effective_target_arm_thumb1_movt_ko {} {
>>>> +    if [check_effective_target_arm_thumb1_ok] {
>>>> +       return [expr ![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 { } {
>>>>
>>>> Best regards,
>>>>
>>>> Thomas
>>>>
>>>>> On 17/05/16 11:13, Thomas Preudhomme wrote:
>>>>>>
>>>>>> Ping?
>>>>>>
>>>>>> *** gcc/ChangeLog ***
>>>>>>
>>>>>> 2015-11-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): Legalize high part of a
>>>>>>            label_ref
>>>>>>            as a
>>>>>>            constant.
>>>>>
>>>>> I don't think "Legalize" is the right word here. How about "Strip the
>>>>> HIGH
>>>>> part of a label_ref"?
>>>>>
>>>>>>            (thumb1_rtx_costs): Also return 0 if setting a half word
>>>>>>            constant
>>>>>>            and
>>>>>>            movw is available.
>>>>>>            (thumb1_size_rtx_costs): Make set of half word constant
>>>>>> also
>>>>>>            cost
>>>>>>            1
>>>>>>            extra instruction if MOVW is available.  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.
>>>>>>            * 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.
>>>>>
>>>>> Please use 'MOVW' consistently in the ChangeLog rather than the
>>>>> lowercase
>>>>> 'movw'
>>>>>
>>>>>>            * doc/sourcebuild.texi (arm_thumb1_movt_ko): Document new
>>>>>> ARM
>>>>>>            effective target.
>>>>>>
>>>>>> *** gcc/testsuite/ChangeLog ***
>>>>>>
>>>>>> 2015-11-13  Thomas Preud'homme  <thomas.preudhomme@arm.com>
>>>>>>
>>>>>>            * lib/target-supports.exp
>>>>>>            (check_effective_target_arm_thumb1_movt_ko):
>>>>>>            Define effective target.
>>>>>>            * gcc.target/arm/pr42574.c: Require arm_thumb1_movt_ko
>>>>>> instead
>>>>>>            of
>>>>>>            arm_thumb1_ok as effective target to exclude ARMv8-M
>>>>>> Baseline.
>>>>>>
>>>>>> diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
>>>>>> index
>>>>>>
>>>>>> 47216b4a1959ccdb18e329db411bf7f941e67163..f42e996e5a7ce979fe406b8261d50f
>>>>>> b2
>>>>>> ba005f6b 100644
>>>>>> --- a/gcc/config/arm/arm.h
>>>>>> +++ b/gcc/config/arm/arm.h
>>>>>> @@ -269,7 +269,7 @@ extern void
>>>>>> (*arm_lang_output_object_attributes_hook)
>>>>>> (void);
>>>>>>
>>>>>>     #define TARGET_HAVE_LDACQ   (TARGET_ARM_ARCH >= 8 &&
>>>>>> arm_arch_notm)
>>>>>>         /* Nonzero if this chip provides the movw and movt
>>>>>> instructions.  */
>>>>>>
>>>>>> -#define TARGET_HAVE_MOVT       (arm_arch_thumb2)
>>>>>> +#define TARGET_HAVE_MOVT       (arm_arch_thumb2 || arm_arch8)
>>>>>>
>>>>>>     /* Nonzero if integer division instructions supported.  */
>>>>>>     #define TARGET_IDIV ((TARGET_ARM && arm_arch_arm_hwdiv)     \
>>>>>>
>>>>>> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
>>>>>> index
>>>>>>
>>>>>> d75a34f10d5ed22cff0a0b5d3ad433f111b059ee..13b4b71ac8f9c1da8ef1945f7ff698
>>>>>> 5c
>>>>>> a59f6832 100644
>>>>>> --- a/gcc/config/arm/arm.c
>>>>>> +++ b/gcc/config/arm/arm.c
>>>>>> @@ -8220,6 +8220,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)
>>>>>>
>>>>>> @@ -8306,7 +8312,8 @@ 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 ((unsigned HOST_WIDE_INT) INTVAL (x) < 256
>>>>>> +             || (TARGET_HAVE_MOVT && !(INTVAL (x) & 0xffff0000)))
>>>>>>
>>>>>>             return 0;
>>>>>
>>>>> Since you're modifying this line please replace (unsigned
>>>>> HOST_WIDE_INT)
>>>>> INTVAL (x) with UINTVAL (x).
>
>

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH, ARM 5/7] Add support for MOVT/MOVW to ARMv8-M Baseline
  2016-07-13 15:15             ` Christophe Lyon
@ 2016-07-13 15:34               ` Thomas Preudhomme
  2016-10-10 12:35                 ` Christophe Lyon
  0 siblings, 1 reply; 11+ messages in thread
From: Thomas Preudhomme @ 2016-07-13 15:34 UTC (permalink / raw)
  To: Christophe Lyon
  Cc: Kyrill Tkachov, gcc-patches, Richard Earnshaw, Ramana Radhakrishnan

On Wednesday 13 July 2016 17:14:52 Christophe Lyon wrote:
> Hi Thomas,

Hi Christophe,

> 
> I'm seeing:
> gcc.target/arm/pr42574.c: syntax error in target selector
> "arm_thumb1_ok && { ! arm_thumb1_movt_ok }" for " dg-do 1 compile {
> arm_thumb1_ok && { ! arm_thumb1_movt_ok } } "

Oops. I remember the trial and error to find the right amount of curly braces 
yet I can indeed reproduce the error now. The target keyword is missing. I'll 
submit a patch asap.

Best regards,

Thomas

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH, ARM 5/7] Add support for MOVT/MOVW to ARMv8-M Baseline
  2016-07-13 15:34               ` Thomas Preudhomme
@ 2016-10-10 12:35                 ` Christophe Lyon
  2016-10-11 13:28                   ` Thomas Preudhomme
  0 siblings, 1 reply; 11+ messages in thread
From: Christophe Lyon @ 2016-10-10 12:35 UTC (permalink / raw)
  To: Thomas Preudhomme
  Cc: Kyrill Tkachov, gcc-patches, Richard Earnshaw, Ramana Radhakrishnan

Hi Thomas,

On 13 July 2016 at 17:34, Thomas Preudhomme
<thomas.preudhomme@foss.arm.com> wrote:
> On Wednesday 13 July 2016 17:14:52 Christophe Lyon wrote:
>> Hi Thomas,
>
> Hi Christophe,
>
>>
>> I'm seeing:
>> gcc.target/arm/pr42574.c: syntax error in target selector
>> "arm_thumb1_ok && { ! arm_thumb1_movt_ok }" for " dg-do 1 compile {
>> arm_thumb1_ok && { ! arm_thumb1_movt_ok } } "
>
> Oops. I remember the trial and error to find the right amount of curly braces
> yet I can indeed reproduce the error now. The target keyword is missing. I'll
> submit a patch asap.
>
> Best regards,
>
> Thomas

I've noticed that the new test
  gcc.target/arm/movdi_movw.c scan-assembler-times movw\tr0, #61680 1
fails on armeb-none-linux-gnueabihf
--with-mode=thumb --with-cpu=cortex-a9 --with-fpu=neon-fp16

the other new tests pass, and using --with=mode=arm makes all three
of them unsupported.

Sorry I missed it when I reported the other error.

Can you have a look?

Thanks

Christophe

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH, ARM 5/7] Add support for MOVT/MOVW to ARMv8-M Baseline
  2016-10-10 12:35                 ` Christophe Lyon
@ 2016-10-11 13:28                   ` Thomas Preudhomme
  0 siblings, 0 replies; 11+ messages in thread
From: Thomas Preudhomme @ 2016-10-11 13:28 UTC (permalink / raw)
  To: Christophe Lyon
  Cc: Kyrill Tkachov, gcc-patches, Richard Earnshaw, Ramana Radhakrishnan

On 10/10/16 13:35, Christophe Lyon wrote:
> Hi Thomas,

Hi Christophe,

>
> On 13 July 2016 at 17:34, Thomas Preudhomme
> <thomas.preudhomme@foss.arm.com> wrote:
>> On Wednesday 13 July 2016 17:14:52 Christophe Lyon wrote:
>>> Hi Thomas,
>>
>> Hi Christophe,
>>
>>>
>>> I'm seeing:
>>> gcc.target/arm/pr42574.c: syntax error in target selector
>>> "arm_thumb1_ok && { ! arm_thumb1_movt_ok }" for " dg-do 1 compile {
>>> arm_thumb1_ok && { ! arm_thumb1_movt_ok } } "
>>
>> Oops. I remember the trial and error to find the right amount of curly braces
>> yet I can indeed reproduce the error now. The target keyword is missing. I'll
>> submit a patch asap.
>>
>> Best regards,
>>
>> Thomas
>
> I've noticed that the new test
>   gcc.target/arm/movdi_movw.c scan-assembler-times movw\tr0, #61680 1
> fails on armeb-none-linux-gnueabihf
> --with-mode=thumb --with-cpu=cortex-a9 --with-fpu=neon-fp16

It seems DImode values are stored differently in register depending on the 
endianness. For little endian the low bits would be in the lowest register, but 
it's reverse in big endian. I'll adapt the test accordingly.

>
> the other new tests pass, and using --with=mode=arm makes all three
> of them unsupported.

Right, there is no reason to forbid ARM state indeed. I'll fix that too.

>
> Sorry I missed it when I reported the other error.

No worry.

>
> Can you have a look?

Absolutely.

Cheers,

Thomas

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2016-10-11 13:28 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-17  8:08 [PATCH, ARM 5/6] Add support for MOVT/MOVW to ARMv8-M Baseline Thomas Preud'homme
2016-05-17 10:13 ` [PATCH, ARM 5/7, ping1] " Thomas Preudhomme
2016-05-18 11:31   ` Kyrill Tkachov
2016-05-19 16:11     ` Thomas Preudhomme
2016-05-20 11:15       ` Kyrill Tkachov
2016-07-07 14:32         ` [PATCH, ARM 5/7] " Thomas Preudhomme
2016-07-13 10:02           ` Kyrill Tkachov
2016-07-13 15:15             ` Christophe Lyon
2016-07-13 15:34               ` Thomas Preudhomme
2016-10-10 12:35                 ` Christophe Lyon
2016-10-11 13:28                   ` Thomas Preudhomme

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).