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]

[PATCH ARM] More improvements to 64-bit constant handling


This patch adds further improvements to the handling of 64-bit
literals.  For all cases we now split out constants where one of the
32-bit words is a valid ARM immediate.  We also split the operands out
into separate instructions if we are optimizing for space, or if we have
LDR instructions with delay slots.  Doing it this way often results in
smaller overall code and on processes with load delay slots should also
result in faster code and more scheduling flexibility.

tested on arm-elf.

2005-04-08  Richard Earnshaw  <richard.earnshaw@arm.com>

	* arm.c (arm_const_double_by_parts): New function.
	* arm-protos.h (arm_const_double_by_parts): Add prototype.
	* arm.md (define_split for 64-bit constants): Add another one.


Index: arm-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm-protos.h,v
retrieving revision 1.84
diff -p -r1.84 arm-protos.h
*** arm-protos.h	7 Apr 2005 11:24:11 -0000	1.84
--- arm-protos.h	8 Apr 2005 13:09:07 -0000
*************** extern rtx arm_gen_return_addr_mask (voi
*** 91,96 ****
--- 91,97 ----
  extern void arm_reload_in_hi (rtx *);
  extern void arm_reload_out_hi (rtx *);
  extern int arm_const_double_inline_cost (rtx);
+ extern bool arm_const_double_by_parts (rtx);
  extern const char *fp_immediate_constant (rtx);
  extern const char *output_call (rtx *);
  extern const char *output_call_mem (rtx *);
Index: arm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.c,v
retrieving revision 1.437
diff -p -r1.437 arm.c
*** arm.c	7 Apr 2005 11:24:08 -0000	1.437
--- arm.c	8 Apr 2005 13:09:08 -0000
*************** arm_const_double_inline_cost (rtx val)
*** 7418,7423 ****
--- 7418,7458 ----
  			      NULL_RTX, NULL_RTX, 0, 0));
  }
  
+ /* Return true if it is worthwile to split a 64-bit constant into two
+    32-bit operations.  This is the case if optimizing for size, or
+    if we have load delay slots, or if one 32-bit part can be done with
+    a single data operation.  */
+ bool
+ arm_const_double_by_parts (rtx val)
+ {
+   enum machine_mode mode = GET_MODE (val);
+   rtx part;
+ 
+   if (optimize_size || arm_ld_sched)
+     return true;
+ 
+   if (mode == VOIDmode)
+     mode = DImode;
+   
+   part = gen_highpart_mode (SImode, mode, val);
+   
+   gcc_assert (GET_CODE (part) == CONST_INT);
+   
+   if (const_ok_for_arm (INTVAL (part))
+       || const_ok_for_arm (~INTVAL (part)))
+     return true;
+   
+   part = gen_lowpart (SImode, val);
+   
+   gcc_assert (GET_CODE (part) == CONST_INT);
+   
+   if (const_ok_for_arm (INTVAL (part))
+       || const_ok_for_arm (~INTVAL (part)))
+     return true;
+   
+   return false;
+ }
+ 
  /* Scan INSN and note any of its operands that need fixing.
     If DO_PUSHES is false we do not actually push any of the fixups
     needed.  The function returns TRUE if any fixups were needed/pushed.
Index: arm.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.md,v
retrieving revision 1.195
diff -p -r1.195 arm.md
*** arm.md	7 Apr 2005 11:24:09 -0000	1.195
--- arm.md	8 Apr 2005 13:09:08 -0000
***************
*** 4192,4197 ****
--- 4192,4221 ----
    "
  )
  
+ ; If optimizing for size, or if we have load delay slots, then 
+ ; we want to split the constant into two separate operations. 
+ ; In both cases this may split a trivial part into a single data op
+ ; leaving a single complex constant to load.  We can also get longer
+ ; offsets in a LDR which means we get better chances of sharing the pool
+ ; entries.  Finally, we can normally do a better job of scheduling
+ ; LDR instructions than we can with LDM.
+ ; This pattern will only match if the one above did not.
+ (define_split
+   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
+ 	(match_operand:ANY64 1 "const_double_operand" ""))]
+   "TARGET_ARM && reload_completed
+    && arm_const_double_by_parts (operands[1])"
+   [(set (match_dup 0) (match_dup 1))
+    (set (match_dup 2) (match_dup 3))]
+   "
+   operands[2] = gen_highpart (SImode, operands[0]);
+   operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
+ 				   operands[1]);
+   operands[0] = gen_lowpart (SImode, operands[0]);
+   operands[1] = gen_lowpart (SImode, operands[1]);
+   "
+ )
+ 
  (define_split
    [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
  	(match_operand:ANY64 1 "arm_general_register_operand" ""))]

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