PATCH: Use PLUS instead of HIGH/LO_SUM for large constants - take 2 for PA
John David Anglin
dave@hiauly1.hia.nrc.ca
Mon Oct 29 10:16:00 GMT 2001
Here is a revised version of the patch to change the handling of immediate
constants to use PLUS instead of HIGH/LO_SUM on the PA. I have addressed
the issue raised by Richard and removed the HImode HIGH/LO_SUM patterns.
I have extended the range of constants handled on 64-bit hosts by providing
both zero and one extension. Previously, only zero extension was done.
I tweaked the single instruction load to accept class 'N' constants.
Bootstrapped and checked on hppa1.1-hp-hpux10.20. It probably would be
a good idea to check that the 64-bit extensions work but I am not currently
capable of doing this. Jeff could you do it?
OK?
Dave
--
J. David Anglin dave.anglin@nrc.ca
National Research Council of Canada (613) 990-0752 (FAX: 952-6605)
2001-10-29 John David Anglin <dave@hiauly1.hia.nrc.ca>
* pa.c (emit_move_sequence): Use cint_ok_for_move to check whether a
constant can be loaded in a single instruction to a register. When
loading immediate constants, use PLUS instead of HIGH/LO_SUM. Handle
both zero and one extension of "32-bit" constants on 64-bit hosts.
* pa.h (LEGITIMATE_CONSTANT_P): Accept constants that can be built
with ldil/ldo/depdi instruction sequence on 64-bit hosts.
* pa.md: New addmove pattern for adding constant_int to HImode
register and moving result to HImode register. Remove HImode HIGH
and LO_SUM patterns.
--- pa.c.orig Sun Oct 7 16:14:17 2001
+++ pa.c Fri Oct 26 18:19:54 2001
@@ -1394,7 +1394,8 @@
else if (register_operand (operand0, mode))
{
if (register_operand (operand1, mode)
- || (GET_CODE (operand1) == CONST_INT && INT_14_BITS (operand1))
+ || (GET_CODE (operand1) == CONST_INT
+ && cint_ok_for_move (INTVAL (operand1)))
|| (operand1 == CONST0_RTX (mode))
|| (GET_CODE (operand1) == HIGH
&& !symbolic_operand (XEXP (operand1, 0), VOIDmode))
@@ -1597,7 +1598,7 @@
|| ! cint_ok_for_move (INTVAL (operand1)))
{
rtx temp;
- int need_zero_extend = 0;
+ int extend = 0;
if (TARGET_64BIT && GET_CODE (operand1) == CONST_INT
&& HOST_BITS_PER_WIDE_INT > 32
@@ -1606,15 +1607,20 @@
HOST_WIDE_INT val = INTVAL (operand1);
HOST_WIDE_INT nval;
- /* If the value is the same after a 32->64bit sign
- extension, then we can use it as-is. Else we will
- need to sign extend the constant from 32->64bits
- then zero extend the result from 32->64bits. */
+ /* Extract the low order 32 bits of the value and sign extend.
+ If the new value is the same as the original value, we can
+ can use the value as-is. If the new value is different, we
+ use it, and either zero or one extend the final result
+ depending on whether the original value was positive or
+ negative. */
nval = ((val & (((HOST_WIDE_INT) 2 << 31) - 1))
^ ((HOST_WIDE_INT) 1 << 31)) - ((HOST_WIDE_INT) 1 << 31);
if (val != nval)
{
- need_zero_extend = 1;
+ if (val >= 0)
+ extend = 1;
+ else
+ extend = 2;
operand1 = GEN_INT (nval);
}
}
@@ -1624,19 +1630,44 @@
else
temp = gen_reg_rtx (mode);
- emit_insn (gen_rtx_SET (VOIDmode, temp,
- gen_rtx_HIGH (mode, operand1)));
- operands[1] = gen_rtx_LO_SUM (mode, temp, operand1);
- emit_move_insn (operands[0], operands[1]);
+ if (GET_CODE (operand1) == CONST_INT)
+ {
+ /* Directly break constant into low and high parts. This
+ provides better optimization opportunities because various
+ passes recognize constants split with PLUS but not LO_SUM.
+ We use a 14-bit signed low part except when the addition
+ of 0x4000 to the high part might change the sign of the
+ high part. */
+ HOST_WIDE_INT value = INTVAL (operand1);
+ HOST_WIDE_INT low = value & 0x3fff;
+ HOST_WIDE_INT high = value & ~ 0x3fff;
+
+ if (low >= 0x2000)
+ {
+ if (high == 0x7fffc000 || (mode == HImode && high == 0x4000))
+ high += 0x2000;
+ else
+ high += 0x4000;
+ }
+
+ low = value - high;
- if (need_zero_extend)
+ emit_insn (gen_rtx_SET (VOIDmode, temp, GEN_INT (high)));
+ operands[1] = gen_rtx_PLUS (mode, temp, GEN_INT (low));
+ }
+ else
{
- emit_insn (gen_zero_extendsidi2 (operands[0],
- gen_rtx_SUBREG (SImode,
- operands[0],
- 0)));
+ emit_insn (gen_rtx_SET (VOIDmode, temp,
+ gen_rtx_HIGH (mode, operand1)));
+ operands[1] = gen_rtx_LO_SUM (mode, temp, operand1);
}
+ emit_move_insn (operands[0], operands[1]);
+
+ if (extend)
+ emit_insn (gen_insv (operands[0], GEN_INT (32), const0_rtx,
+ extend == 1 ? const0_rtx : constm1_rtx));
+
return 1;
}
}
--- pa.h.orig Mon Sep 24 12:18:02 2001
+++ pa.h Fri Oct 26 14:08:52 2001
@@ -1106,8 +1106,8 @@
&& !(TARGET_64BIT && GET_CODE (X) == CONST_DOUBLE) \
&& !(TARGET_64BIT && GET_CODE (X) == CONST_INT \
&& !(HOST_BITS_PER_WIDE_INT <= 32 \
- || (INTVAL (X) >= (HOST_WIDE_INT) -1 << 31 \
- && INTVAL (X) < (HOST_WIDE_INT) 1 << 32) \
+ || (INTVAL (X) >= (HOST_WIDE_INT) -2 << 31 \
+ && INTVAL (X) < (HOST_WIDE_INT) 2 << 31) \
|| cint_ok_for_move (INTVAL (X)))) \
&& !function_label_operand (X, VOIDmode))
--- pa.md.orig Sat Jul 14 20:54:21 2001
+++ pa.md Fri Oct 26 16:03:12 2001
@@ -2604,19 +2604,12 @@
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
- (high:HI (match_operand 1 "const_int_operand" "")))]
+ (plus:HI (match_operand:HI 1 "register_operand" "r")
+ (match_operand 2 "const_int_operand" "J")))]
""
- "ldil L'%G1,%0"
- [(set_attr "type" "move")
- (set_attr "length" "4")])
-
-(define_insn ""
- [(set (match_operand:HI 0 "register_operand" "=r")
- (lo_sum:HI (match_operand:HI 1 "register_operand" "r")
- (match_operand 2 "const_int_operand" "")))]
- ""
- "ldo R'%G2(%1),%0"
- [(set_attr "type" "move")
+ "ldo %2(%1),%0"
+ [(set_attr "type" "binary")
+ (set_attr "pa_combine_type" "addmove")
(set_attr "length" "4")])
(define_expand "movqi"
More information about the Gcc-patches
mailing list