This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Use ARM MOVW/MOVT


The patch below teaches gcc how to make use of the ARM MOVW/MOVT instructions. 
These allow loading of large immediates and addresses without requiring a 
constant pool entry. A MOVW/MOVT pair tends to be faster and have better 
cache footprint, whereas constant pool loads tend to be slightly smaller.

In addition, MOVW/MOVT cannot be used if the address needs to be fixed up by 
the OS dynamic loader.

Tested on arm-none-eabi and arm-linux-gnueabi.
Applied to svn trunk.

Paul

2008-09-01  Paul Brook  <paul@codesourcery.com>

	* doc/invoke.texi: Document -mword-relocations.
	* config/arm/uclinux-elf.h (TARGET_DEFAULT_WORD_RELOCATIONS): Define.
	* config/arm/symbian.h (TARGET_DEFAULT_WORD_RELOCATIONS): Define.
	* config/arm/vxworks.h (TARGET_DEFAULT_WORD_RELOCATIONS): Define.
	* config/arm/arm.c (arm_split_constant): Use arm_emit_movpair.
	(arm_rtx_costs_1, arm_size_rtx_costs): Handle HIGH and LO_SUM.
	(arm_emit_movpair): New function.
	(arm_print_operand <c>): Handle sybolic addresses.
	* config/arm/arm.h (TARGET_USE_MOVT): Define.
	(TARGET_DEFAULT_WORD_RELOCATIONS): Define.
	* config/arm/arm-protos.h (arm_emit_movpair): Add prototype.
	* config/arm/arm.opt: Add -mword-relocations.
	* config/arm/arm.md (movsi): Use arm_emit_movpair.
	(arm_movt, arm_movw): New.

Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 139879)
+++ gcc/doc/invoke.texi	(working copy)
@@ -448,7 +448,8 @@ Objective-C and Objective-C++ Dialects}.
 -mthumb  -marm @gol
 -mtpcs-frame  -mtpcs-leaf-frame @gol
 -mcaller-super-interworking  -mcallee-super-interworking @gol
--mtp=@var{name}}
+-mtp=@var{name}
+-mword-relocations}
 
 @emph{AVR Options}
 @gccoptlist{-mmcu=@var{mcu}  -msize  -minit-stack=@var{n}  -mno-interrupts 
@gol
@@ -8910,6 +8911,13 @@ models are @option{soft}, which generate
 best available method for the selected processor.  The default setting is
 @option{auto}.
 
+@item -mword-relocations
+@opindex mword-relocations
+Only generate absolute relocations on word sized values (i.e. R_ARM_ABS32).
+This is enabled by default on targets (uClinux, SymbianOS) where the runtime
+loader imposes this restriction, and when @option{-fpic} or @option{-fPIC}
+is speficied.
+
 @end table
 
 @node AVR Options
Index: gcc/config/arm/uclinux-elf.h
===================================================================
--- gcc/config/arm/uclinux-elf.h	(revision 139879)
+++ gcc/config/arm/uclinux-elf.h	(working copy)
@@ -83,3 +83,5 @@
   "%{pthread:-lpthread} \
    %{shared:-lc} \
    %{!shared:%{profile:-lc_p}%{!profile:-lc}}"
+
+#define TARGET_DEFAULT_WORD_RELOCATIONS 1
Index: gcc/config/arm/symbian.h
===================================================================
--- gcc/config/arm/symbian.h	(revision 139879)
+++ gcc/config/arm/symbian.h	(working copy)
@@ -101,3 +101,5 @@
 
 /* SymbianOS cannot merge entities with vague linkage at runtime.  */
 #define TARGET_ARM_DYNAMIC_VAGUE_LINKAGE_P false
+
+#define TARGET_DEFAULT_WORD_RELOCATIONS 1
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	(revision 139879)
+++ gcc/config/arm/arm.c	(working copy)
@@ -1926,14 +1926,22 @@ arm_split_constant (enum rtx_code code, 
 	    {
 	      /* Currently SET is the only monadic value for CODE, all
 		 the rest are diadic.  */
-	      emit_set_insn (target, GEN_INT (val));
+	      if (TARGET_USE_MOVT)
+		arm_emit_movpair (target, GEN_INT (val));
+	      else
+		emit_set_insn (target, GEN_INT (val));
+
 	      return 1;
 	    }
 	  else
 	    {
 	      rtx temp = subtargets ? gen_reg_rtx (mode) : target;
 
-	      emit_set_insn (temp, GEN_INT (val));
+	      if (TARGET_USE_MOVT)
+		arm_emit_movpair (temp, GEN_INT (val));
+	      else
+		emit_set_insn (temp, GEN_INT (val));
+
 	      /* For MINUS, the value is subtracted from, since we never
 		 have subtraction of a constant.  */
 	      if (code == MINUS)
@@ -5117,6 +5125,10 @@ arm_rtx_costs_1 (rtx x, enum rtx_code co
     case SYMBOL_REF:
       return 6;
 
+    case HIGH:
+    case LO_SUM:
+      return (outer == SET) ? 1 : -1;
+
     case CONST_DOUBLE:
       if (arm_const_double_rtx (x) || vfp3_const_double_rtx (x))
 	return outer == SET ? 2 : -1;
@@ -5343,6 +5355,13 @@ arm_size_rtx_costs (rtx x, int code, int
       *total = COSTS_N_INSNS (4);
       return true;
 
+    case HIGH:
+    case LO_SUM:
+      /* We prefer constant pool entries to MOVW/MOVT pairs, so bump the
+	 cost of these slightly.  */
+      *total = COSTS_N_INSNS (1) + 1;
+      return true;
+
     default:
       if (mode != VOIDmode)
 	*total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
@@ -9891,6 +9910,14 @@ output_mov_long_double_arm_from_arm (rtx
 }
 
 
+/* Emit a MOVW/MOVT pair.  */
+void arm_emit_movpair (rtx dest, rtx src)
+{
+  emit_set_insn (dest, gen_rtx_HIGH (SImode, src));
+  emit_set_insn (dest, gen_rtx_LO_SUM (SImode, dest, src));
+}
+
+
 /* Output a move from arm registers to an fpa registers.
    OPERANDS[0] is an fpa register.
    OPERANDS[1] is the first registers of an arm register pair.  */
@@ -12906,10 +12933,21 @@ arm_print_operand (FILE *stream, rtx x, 
       }
       return;
 
-    /* An integer without a preceding # sign.  */
+    /* An integer or symbol address without a preceding # sign.  */
     case 'c':
-      gcc_assert (GET_CODE (x) == CONST_INT);
-      fprintf (stream, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
+      switch (GET_CODE (x))
+	{
+	case CONST_INT:
+	  fprintf (stream, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
+	  break;
+
+	case SYMBOL_REF:
+	  output_addr_const (stream, x);
+	  break;
+
+	default:
+	  gcc_unreachable ();
+	}
       return;
 
     case 'B':
Index: gcc/config/arm/arm.h
===================================================================
--- gcc/config/arm/arm.h	(revision 139879)
+++ gcc/config/arm/arm.h	(working copy)
@@ -241,6 +241,9 @@ extern void (*arm_lang_output_object_att
 #define TARGET_INT_SIMD \
   (TARGET_32BIT && arm_arch6 && arm_arch_notm)
 
+/* Should MOVW/MOVT be used in preference to a constant pool.  */
+#define TARGET_USE_MOVT (arm_arch_thumb2 && !optimize_size)
+
 /* We could use unified syntax for arm mode, but for now we just use it
    for Thumb-2.  */
 #define TARGET_UNIFIED_ASM TARGET_THUMB2
@@ -1962,6 +1965,11 @@ typedef struct
    SYMBOL's section.  */
 #define ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P 0
 
+/* Nonzero if all target requires all absolute relocations be R_ARM_ABS32.  
*/
+#ifndef TARGET_DEFAULT_WORD_RELOCATIONS
+#define TARGET_DEFAULT_WORD_RELOCATIONS 0
+#endif
+
 /* Nonzero if the constant value X is a legitimate general operand.
    It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.
 
Index: gcc/config/arm/arm-protos.h
===================================================================
--- gcc/config/arm/arm-protos.h	(revision 139879)
+++ gcc/config/arm/arm-protos.h	(working copy)
@@ -123,6 +123,7 @@ extern const char *fp_immediate_constant
 extern void arm_emit_call_insn (rtx, rtx);
 extern const char *output_call (rtx *);
 extern const char *output_call_mem (rtx *);
+void arm_emit_movpair (rtx, rtx);
 extern const char *output_mov_long_double_fpa_from_arm (rtx *);
 extern const char *output_mov_long_double_arm_from_fpa (rtx *);
 extern const char *output_mov_long_double_arm_from_arm (rtx *);
Index: gcc/config/arm/arm.opt
===================================================================
--- gcc/config/arm/arm.opt	(revision 139879)
+++ gcc/config/arm/arm.opt	(working copy)
@@ -156,3 +156,7 @@ Assume big endian bytes, little endian w
 mvectorize-with-neon-quad
 Target Report Mask(NEON_VECTORIZE_QUAD)
 Use Neon quad-word (rather than double-word) registers for vectorization
+
+mword-relocations
+Target Report Var(target_word_relocations) 
Init(TARGET_DEFAULT_WORD_RELOCATIONS)
++Only generate absolute relocations on word sized values.
Index: gcc/config/arm/arm.md
===================================================================
--- gcc/config/arm/arm.md	(revision 139879)
+++ gcc/config/arm/arm.md	(working copy)
@@ -4823,6 +4823,14 @@ (define_expand "movsi"
 			       optimize && can_create_pseudo_p ());
           DONE;
         }
+
+      if (TARGET_USE_MOVT && !target_word_relocations
+	  && GET_CODE (operands[1]) == SYMBOL_REF
+	  && !flag_pic && !arm_tls_referenced_p (operands[1]))
+	{
+	  arm_emit_movpair (operands[0], operands[1]);
+	  DONE;
+	}
     }
   else /* TARGET_THUMB1...  */
     {
@@ -4883,6 +4891,28 @@ (define_expand "movsi"
   "
 )
 
+;; The ARM LO_SUM and HIGH are backwards - HIGH sets the low bits, and
+;; 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")))]
+  "TARGET_32BIT"
+  "movt%?\t%0, #:upper16:%c2"
+  [(set_attr "predicable" "yes")
+   (set_attr "length" "4")]
+)
+
+(define_insn "*arm_movw"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
+	(high:SI (match_operand:SI 1 "general_operand"      "i")))]
+  "TARGET_32BIT"
+  "movw%?\t%0, #:lower16:%c1"
+  [(set_attr "predicable" "yes")
+   (set_attr "length" "4")]
+)
+
 (define_insn "*arm_movsi_insn"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=rk,r,r,r,rk,m")
 	(match_operand:SI 1 "general_operand"      "rk, I,K,N,mi,rk"))]
Index: gcc/config/arm/vxworks.h
===================================================================
--- gcc/config/arm/vxworks.h	(revision 139879)
+++ gcc/config/arm/vxworks.h	(working copy)
@@ -113,3 +113,6 @@ along with GCC; see the file COPYING3.  
    cannot allow arbitrary offsets for shared libraries either.  */
 #undef ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P
 #define ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P 1
+
+#undef TARGET_DEFAULT_WORD_RELOCATIONS
+#define TARGET_DEFAULT_WORD_RELOCATIONS 1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]