diff mbox

[ARM,5/7] Add support for MOVT/MOVW to ARMv8-M Baseline

Message ID 3411698.fWmskm4cLi@e108577-lin
State New
Headers show

Commit Message

Thomas Preudhomme July 7, 2016, 2:32 p.m. UTC
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).

Comments

Kyrill Tkachov July 13, 2016, 10:01 a.m. UTC | #1
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).
Christophe Lyon July 13, 2016, 3:14 p.m. UTC | #2
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).
>
>
Thomas Preudhomme July 13, 2016, 3:34 p.m. UTC | #3
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
Christophe Lyon Oct. 10, 2016, 12:35 p.m. UTC | #4
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
Thomas Preudhomme Oct. 11, 2016, 1:28 p.m. UTC | #5
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
diff mbox

Patch

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 { } {