This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [patch] gcc/reload1.c
- To: Kazu Hirata <kazu at hxi dot com>
- Subject: Re: [patch] gcc/reload1.c
- From: Richard Henderson <rth at cygnus dot com>
- Date: Wed, 17 May 2000 17:24:36 -0700
- Cc: gcc-patches at gcc dot gnu dot org, "Jeffrey A. Law" <law at cygnus dot com>
- References: <41ECF07CC183D111A6F800805FEDAB190CE5B1@EXCHANGE1>
On Wed, May 17, 2000 at 11:26:44AM -0400, Kazu Hirata wrote:
> After chasing the bug, I found that, in reload1.c, when eliminating a frame
> pointer (thus changing "fp + offset1" to "sp + offset2"), the insn is left
> unrecognized. Hitachi H8/300[HS] series support increment/decrement by 1, 2,
> and 4, and gcc tries to utilize them because they are fast, but when the
> offset changes, you might be adding/subtracting something big, in which case
> a regular addition/subtraction is faster. Therefore, we need to recognize
> the insn even though the only change is the integer value of an operand.
This isn't correct. The problem is actaully in the h8 machine
description -- it has violated the rule that all alternatives
must be represented in the same insn pattern.
A more correct solution follows. I've checked this against the
test case, but not with a full simulator bootstrap, but I do not
expect problems.
Ok, Jeff?
r~
* config/h8300/h8300.c (ok_for_bclr): Take a HOST_WIDE_INT.
(small_power_of_two): Likewise; use exact_log2.
(adds_subs_operand, one_insn_adds_subs_operand): Remove.
(output_adds_subs): Remove.
(two_insn_adds_subs_operand): New.
(split_adds_subs): New.
* config/h8300/h8300-protos.h: Update.
* config/h8300/h8300.h (CONST_OK_FOR_J): Cast to uns HOST_WIDE_INT.
(CONST_OK_FOR_L): Match strict adds operands.
(CONST_OK_FOR_N): Match struct subs operands.
* config/h8300/h8300.md (adds_subs insns): Remove.
(addhi patterns): Output adds/subs directly.
(addsi_h8300h): Likewise.
(addhi/addsi splitters): New. Decompose two_insn_adds_subs_operand.
Index: h8300-protos.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/h8300/h8300-protos.h,v
retrieving revision 1.1
diff -c -p -d -r1.1 h8300-protos.h
*** h8300-protos.h 2000/01/14 22:57:31 1.1
--- h8300-protos.h 2000/05/17 22:38:06
*************** extern void notice_update_cc PARAMS ((rt
*** 36,49 ****
extern int expand_a_shift PARAMS ((enum machine_mode, int, rtx[]));
extern int fix_bit_operand PARAMS ((rtx *, int, enum rtx_code));
extern int h8300_adjust_insn_length PARAMS ((rtx, int));
extern int general_operand_src PARAMS ((rtx, enum machine_mode));
extern int general_operand_dst PARAMS ((rtx, enum machine_mode));
extern int o_operand PARAMS ((rtx, enum machine_mode));
extern int p_operand PARAMS ((rtx, enum machine_mode));
extern int call_insn_operand PARAMS ((rtx, enum machine_mode));
! extern int adds_subs_operand PARAMS ((rtx, enum machine_mode));
! extern int one_insn_adds_subs_operand PARAMS ((rtx, enum machine_mode));
extern int small_call_insn_operand PARAMS ((rtx, enum machine_mode));
extern int jump_address_operand PARAMS ((rtx, enum machine_mode));
extern int bit_operand PARAMS ((rtx, enum machine_mode));
--- 36,49 ----
extern int expand_a_shift PARAMS ((enum machine_mode, int, rtx[]));
extern int fix_bit_operand PARAMS ((rtx *, int, enum rtx_code));
extern int h8300_adjust_insn_length PARAMS ((rtx, int));
+ extern void split_adds_subs PARAMS ((enum machine_mode, rtx[]));
extern int general_operand_src PARAMS ((rtx, enum machine_mode));
extern int general_operand_dst PARAMS ((rtx, enum machine_mode));
extern int o_operand PARAMS ((rtx, enum machine_mode));
extern int p_operand PARAMS ((rtx, enum machine_mode));
extern int call_insn_operand PARAMS ((rtx, enum machine_mode));
! extern int two_insn_adds_subs_operand PARAMS ((rtx, enum machine_mode));
extern int small_call_insn_operand PARAMS ((rtx, enum machine_mode));
extern int jump_address_operand PARAMS ((rtx, enum machine_mode));
extern int bit_operand PARAMS ((rtx, enum machine_mode));
*************** extern void function_prologue PARAMS ((F
*** 70,75 ****
extern void function_epilogue PARAMS ((FILE *, int));
extern void asm_file_start PARAMS ((FILE *));
extern void asm_file_end PARAMS ((FILE *));
! extern int ok_for_bclr PARAMS ((int));
! extern int small_power_of_two PARAMS ((int));
extern int initial_offset PARAMS ((int, int));
--- 70,75 ----
extern void function_epilogue PARAMS ((FILE *, int));
extern void asm_file_start PARAMS ((FILE *));
extern void asm_file_end PARAMS ((FILE *));
! extern int ok_for_bclr PARAMS ((HOST_WIDE_INT));
! extern int small_power_of_two PARAMS ((HOST_WIDE_INT));
extern int initial_offset PARAMS ((int, int));
Index: h8300.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/h8300/h8300.c,v
retrieving revision 1.25
diff -c -p -d -r1.25 h8300.c
*** h8300.c 2000/05/04 13:49:50 1.25
--- h8300.c 2000/05/17 22:38:06
*************** asm_file_end (file)
*** 542,570 ****
int
small_power_of_two (value)
! int value;
{
! switch (value)
! {
! case 1:
! case 2:
! case 4:
! case 8:
! case 16:
! case 32:
! case 64:
! case 128:
! case 256:
! case 512:
! case 1024:
! case 2048:
! case 4096:
! case 8192:
! case 16384:
! case 32768:
! return 1;
! }
! return 0;
}
/* Return true if VALUE is a valid constant for constraint 'O', which
--- 542,551 ----
int
small_power_of_two (value)
! HOST_WIDE_INT value;
{
! int power = exact_log2 (value);
! return power >= 0 && power <= 15;
}
/* Return true if VALUE is a valid constant for constraint 'O', which
*************** small_power_of_two (value)
*** 573,579 ****
int
ok_for_bclr (value)
! int value;
{
return small_power_of_two ((~value) & 0xff);
}
--- 554,560 ----
int
ok_for_bclr (value)
! HOST_WIDE_INT value;
{
return small_power_of_two ((~value) & 0xff);
}
*************** call_insn_operand (op, mode)
*** 645,751 ****
}
int
! adds_subs_operand (op, mode)
rtx op;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
if (GET_CODE (op) == CONST_INT)
{
! if (INTVAL (op) <= 4 && INTVAL (op) >= 0)
! return 1;
! if (INTVAL (op) >= -4 && INTVAL (op) <= 0)
! return 1;
! if ((TARGET_H8300H || TARGET_H8300S)
! && INTVAL (op) != 7
! && (INTVAL (op) <= 8 && INTVAL (op) >= 0))
! return 1;
! if ((TARGET_H8300H || TARGET_H8300S)
! && INTVAL (op) != -7
! && (INTVAL (op) >= -8 && INTVAL (op) <= 0))
! return 1;
! }
! return 0;
! }
! /* Return nonzero if op is an adds/subs operand which only requires
! one insn to implement. It is assumed that OP is already an adds/subs
! operand. */
! int
! one_insn_adds_subs_operand (op, mode)
! rtx op;
! enum machine_mode mode ATTRIBUTE_UNUSED;
! {
! int val = INTVAL (op);
- if (val == 1 || val == -1
- || val == 2 || val == -2
- || ((TARGET_H8300H || TARGET_H8300S)
- && (val == 4 || val == -4)))
- return 1;
return 0;
}
! const char *
! output_adds_subs (operands)
rtx *operands;
{
! int val = INTVAL (operands[2]);
!
! /* First get the value into the range -4..4 inclusive.
! The only way it can be out of this range is when TARGET_H8300H
! or TARGET_H8300S is true, thus it is safe to use adds #4 and subs #4. */
! if (val > 4)
{
! output_asm_insn ("adds #4,%A0", operands);
! val -= 4;
! }
! if (val < -4)
! {
! output_asm_insn ("subs #4,%A0", operands);
! val += 4;
}
-
- /* Handle case were val == 4 or val == -4 and we're compiling
- for TARGET_H8300H or TARGET_H8300S. */
- if ((TARGET_H8300H || TARGET_H8300S)
- && val == 4)
- return "adds #4,%A0";
-
- if ((TARGET_H8300H || TARGET_H8300S)
- && val == -4)
- return "subs #4,%A0";
if (val > 2)
{
! output_asm_insn ("adds #2,%A0", operands);
val -= 2;
}
!
! if (val < -2)
{
! output_asm_insn ("subs #2,%A0", operands);
val += 2;
}
- /* val should be one or two now. */
- if (val == 2)
- return "adds #2,%A0";
-
- if (val == -2)
- return "subs #2,%A0";
-
- /* val should be one now. */
- if (val == 1)
- return "adds #1,%A0";
-
- if (val == -1)
- return "subs #1,%A0";
-
/* If not optimizing, we might be asked to add 0. */
if (val == 0)
! return "";
/* In theory, this can't happen. */
abort ();
--- 626,717 ----
}
int
! two_insn_adds_subs_operand (op, mode)
rtx op;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
if (GET_CODE (op) == CONST_INT)
{
! HOST_WIDE_INT value = INTVAL (op);
! if (TARGET_H8300H || TARGET_H8300S)
! {
! if (value >= -8 && value < -4 && value != -7)
! return 1;
! if (value > 4 && value <= 8 && value != 7)
! return 1;
! }
! else
! {
! if (value == -4 || value == -3 || value == 3 || value == 4)
! return 1;
! }
! }
return 0;
}
! /* Split an add of a small constant into two adds/subs insns. */
!
! void
! split_adds_subs (mode, operands)
! enum machine_mode mode;
rtx *operands;
{
! HOST_WIDE_INT val = INTVAL (operands[1]);
! rtx reg = operands[0];
! rtx tmp;
! /* Take care of +/- 4 for H8300H and H8300S. */
! if (TARGET_H8300H || TARGET_H8300S)
{
! /* Get the value in range of +/- 4. */
! if (val > 4)
! {
! tmp = gen_rtx_PLUS (mode, reg, GEN_INT (4));
! emit_insn (gen_rtx_SET (VOIDmode, reg, tmp));
! val -= 4;
! }
! else if (val < -4)
! {
! tmp = gen_rtx_PLUS (mode, reg, GEN_INT (-4));
! emit_insn (gen_rtx_SET (VOIDmode, reg, tmp));
! val += 4;
! }
! if (val == 4 || val == -4)
! {
! tmp = gen_rtx_PLUS (mode, reg, GEN_INT (val));
! emit_insn (gen_rtx_SET (VOIDmode, reg, tmp));
! return;
! }
}
+ /* Get the value in range of +/- 2. */
if (val > 2)
{
! tmp = gen_rtx_PLUS (mode, reg, GEN_INT (2));
! emit_insn (gen_rtx_SET (VOIDmode, reg, tmp));
val -= 2;
}
! else if (val < -2)
{
! tmp = gen_rtx_PLUS (mode, reg, GEN_INT (-2));
! emit_insn (gen_rtx_SET (VOIDmode, reg, tmp));
val += 2;
}
/* If not optimizing, we might be asked to add 0. */
if (val == 0)
! return;
!
! /* We should have one or two now. */
! if (val >= -2 && val <= 2)
! {
! tmp = gen_rtx_PLUS (mode, reg, GEN_INT (val));
! emit_insn (gen_rtx_SET (VOIDmode, reg, tmp));
! return;
! }
/* In theory, this can't happen. */
abort ();
Index: h8300.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/h8300/h8300.h,v
retrieving revision 1.21
diff -c -p -d -r1.21 h8300.h
*** h8300.h 2000/02/26 21:01:24 1.21
--- h8300.h 2000/05/17 22:38:06
*************** enum reg_class {
*** 399,409 ****
Return 1 if VALUE is in the range specified by C. */
#define CONST_OK_FOR_I(VALUE) ((VALUE) == 0)
! #define CONST_OK_FOR_J(VALUE) ((unsigned) (VALUE) < 256)
! #define CONST_OK_FOR_K(VALUE) (((VALUE) == 1) || (VALUE) == 2)
! #define CONST_OK_FOR_L(VALUE) (((VALUE) == -1) || (VALUE) == -2)
! #define CONST_OK_FOR_M(VALUE) (((VALUE) == 3) || (VALUE) == 4)
! #define CONST_OK_FOR_N(VALUE) (((VALUE) == -3) || (VALUE) == -4)
#define CONST_OK_FOR_O(VALUE) (ok_for_bclr (VALUE))
#define CONST_OK_FOR_P(VALUE) (small_power_of_two (VALUE))
--- 399,415 ----
Return 1 if VALUE is in the range specified by C. */
#define CONST_OK_FOR_I(VALUE) ((VALUE) == 0)
! #define CONST_OK_FOR_J(VALUE) ((unsigned HOST_WIDE_INT) (VALUE) < 256)
! #define CONST_OK_FOR_K(VALUE) ((VALUE) == 1 || (VALUE) == 2)
! #define CONST_OK_FOR_L(VALUE) \
! (TARGET_H8300H || TARGET_H8300S \
! ? (VALUE) == 1 || (VALUE) == 2 || (VALUE) == 4 \
! : (VALUE) == 1 || (VALUE) == 2)
! #define CONST_OK_FOR_M(VALUE) ((VALUE) == 3 || (VALUE) == 4)
! #define CONST_OK_FOR_N(VALUE) \
! (TARGET_H8300H || TARGET_H8300S \
! ? (VALUE) == -1 || (VALUE) == -2 || (VALUE) == -4 \
! : (VALUE) == -1 || (VALUE) == -2)
#define CONST_OK_FOR_O(VALUE) (ok_for_bclr (VALUE))
#define CONST_OK_FOR_P(VALUE) (small_power_of_two (VALUE))
*************** enum reg_class {
*** 415,421 ****
(C) == 'M' ? CONST_OK_FOR_M (VALUE) : \
(C) == 'N' ? CONST_OK_FOR_N (VALUE) : \
(C) == 'O' ? CONST_OK_FOR_O (VALUE) : \
! (C) == 'P' ? CONST_OK_FOR_P(VALUE) : \
0)
/* Similar, but for floating constants, and defining letters G and H.
--- 421,427 ----
(C) == 'M' ? CONST_OK_FOR_M (VALUE) : \
(C) == 'N' ? CONST_OK_FOR_N (VALUE) : \
(C) == 'O' ? CONST_OK_FOR_O (VALUE) : \
! (C) == 'P' ? CONST_OK_FOR_P (VALUE) : \
0)
/* Similar, but for floating constants, and defining letters G and H.
Index: h8300.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/h8300/h8300.md,v
retrieving revision 1.8
diff -c -p -d -r1.8 h8300.md
*** h8300.md 2000/02/26 21:01:24 1.8
--- h8300.md 2000/05/17 22:38:06
***************
*** 614,656 ****
""
"")
- ;; Specialized version using adds/subs. This must come before
- ;; the more general patterns below.
- (define_insn ""
- [(set (match_operand:HI 0 "register_operand" "=r")
- (plus:HI (match_operand:HI 1 "register_operand" "%0")
- (match_operand:HI 2 "adds_subs_operand" "n")))]
- ""
- "* return output_adds_subs (operands);"
- [(set_attr "cc" "none_0hit")
- (set (attr "length")
- (if_then_else (ne (match_operand:HI 2 "one_insn_adds_subs_operand" "")
- (const_int 0))
- (const_int 2)
- (const_int 4)))])
-
(define_insn ""
! [(set (match_operand:HI 0 "register_operand" "=&r,r,&r")
! (plus:HI (match_operand:HI 1 "register_operand" "%0,0,g")
! (match_operand:HI 2 "nonmemory_operand" "n,r,r")))]
"TARGET_H8300"
"@
add.b %s2,%s0\;addx %t2,%t0
add.w %T2,%T0
mov.w %T1,%T0\;add.w %T2,%T0"
! [(set_attr "length" "4,2,6")
! (set_attr "cc" "clobber,set_zn,set_zn")])
(define_insn ""
! [(set (match_operand:HI 0 "register_operand" "=r,r")
! (plus:HI (match_operand:HI 1 "register_operand" "%0,0")
! (match_operand:HI 2 "nonmemory_operand" "n,r")))]
"TARGET_H8300H || TARGET_H8300S"
"@
add.w %T2,%T0
add.w %T2,%T0"
! [(set_attr "length" "4,2")
! (set_attr "cc" "set_zn,set_zn")])
(define_expand "addsi3"
[(set (match_operand:SI 0 "register_operand" "")
--- 614,653 ----
""
"")
(define_insn ""
! [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,&r")
! (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,g")
! (match_operand:HI 2 "nonmemory_operand" "L,N,n,r,r")))]
"TARGET_H8300"
"@
+ adds %2,%A0
+ subs %2,%A0
add.b %s2,%s0\;addx %t2,%t0
add.w %T2,%T0
mov.w %T1,%T0\;add.w %T2,%T0"
! [(set_attr "length" "2,2,4,2,6")
! (set_attr "cc" "none_0hit,none_0hit,clobber,set_zn,set_zn")])
(define_insn ""
! [(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
! (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0")
! (match_operand:HI 2 "nonmemory_operand" "L,N,n,r")))]
"TARGET_H8300H || TARGET_H8300S"
"@
+ adds %2,%A0
+ subs %2,%A0
add.w %T2,%T0
add.w %T2,%T0"
! [(set_attr "length" "2,2,4,2")
! (set_attr "cc" "none_0hit,none_0hit,set_zn,set_zn")])
!
! (define_split
! [(set (match_operand:HI 0 "register_operand" "")
! (plus:HI (match_dup 0)
! (match_operand:HI 1 "two_insn_adds_subs_operand" "")))]
! ""
! [(const_int 0)]
! "split_adds_subs (HImode, operands); DONE;")
(define_expand "addsi3"
[(set (match_operand:SI 0 "register_operand" "")
***************
*** 659,679 ****
""
"")
- ;; Specialized version using adds/subs. This must come before
- ;; the more general patterns below.
- (define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_operand:SI 1 "register_operand" "%0")
- (match_operand:SI 2 "adds_subs_operand" "n")))]
- "TARGET_H8300H || TARGET_H8300S"
- "* return output_adds_subs (operands);"
- [(set_attr "cc" "none_0hit")
- (set (attr "length")
- (if_then_else (ne (match_operand:HI 2 "one_insn_adds_subs_operand" "")
- (const_int 0))
- (const_int 2)
- (const_int 4)))])
-
(define_insn "addsi_h8300"
[(set (match_operand:SI 0 "register_operand" "=r,r,&r")
(plus:SI (match_operand:SI 1 "register_operand" "%0,0,r")
--- 656,661 ----
***************
*** 687,702 ****
(set_attr "cc" "clobber")])
(define_insn "addsi_h8300h"
! [(set (match_operand:SI 0 "register_operand" "=r,r")
! (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
! (match_operand:SI 2 "nonmemory_operand" "i,r")))]
"TARGET_H8300H || TARGET_H8300S"
"@
add.l %S2,%S0
add.l %S2,%S0"
! [(set_attr "length" "6,2")
! (set_attr "cc" "set_zn,set_zn")])
;; ----------------------------------------------------------------------
;; SUBTRACT INSTRUCTIONS
;; ----------------------------------------------------------------------
--- 669,694 ----
(set_attr "cc" "clobber")])
(define_insn "addsi_h8300h"
! [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
! (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
! (match_operand:SI 2 "nonmemory_operand" "L,N,i,r")))]
"TARGET_H8300H || TARGET_H8300S"
"@
+ adds %2,%A0
+ subs %2,%A0
add.l %S2,%S0
add.l %S2,%S0"
! [(set_attr "length" "2,2,6,2")
! (set_attr "cc" "none_0hit,none_0hit,set_zn,set_zn")])
+ (define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (plus:SI (match_dup 0)
+ (match_operand:SI 1 "two_insn_adds_subs_operand" "")))]
+ "TARGET_H8300H || TARGET_H8300S"
+ [(const_int 0)]
+ "split_adds_subs (SImode, operands); DONE;")
+
;; ----------------------------------------------------------------------
;; SUBTRACT INSTRUCTIONS
;; ----------------------------------------------------------------------
***************
*** 719,745 ****
""
"")
- ;; Specialized version using adds/subs. This must come before
- ;; the more general patterns below. This may not be needed
- ;; due to instruction canonicalization.
(define_insn ""
- [(set (match_operand:HI 0 "register_operand" "=r")
- (minus:HI (match_operand:HI 1 "register_operand" "r")
- (match_operand:HI 2 "adds_subs_operand" "n")))]
- ""
- "*
- {
- operands[2] = GEN_INT (-INTVAL (operands[2]));
- return output_adds_subs (operands);
- }"
- [(set_attr "cc" "none_0hit")
- (set (attr "length")
- (if_then_else (ne (match_operand:HI 2 "one_insn_adds_subs_operand" "")
- (const_int 0))
- (const_int 2)
- (const_int 4)))])
-
- (define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r,&r")
(minus:HI (match_operand:HI 1 "general_operand" "0,0")
(match_operand:HI 2 "nonmemory_operand" "r,n")))]
--- 711,717 ----
***************
*** 776,801 ****
"sub.w %f2,%f0\;subx %y2,%y0\;subx %z2,%z0"
[(set_attr "length" "6")
(set_attr "cc" "clobber")])
-
- ;; Specialized version using adds/subs. This must come before
- ;; the more general patterns below. This may not be needed
- ;; due to instruction canonicalization.
- (define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=r")
- (minus:SI (match_operand:SI 1 "general_operand" "0")
- (match_operand:SI 2 "adds_subs_operand" "n")))]
- "TARGET_H8300H || TARGET_H8300S"
- "*
- {
- operands[2] = GEN_INT (-INTVAL (operands[2]));
- return output_adds_subs (operands);
- }"
- [(set_attr "cc" "none_0hit")
- (set (attr "length")
- (if_then_else (ne (match_operand:HI 2 "one_insn_adds_subs_operand" "")
- (const_int 0))
- (const_int 2)
- (const_int 4)))])
(define_insn "subsi3_h8300h"
[(set (match_operand:SI 0 "register_operand" "=r,r")
--- 748,753 ----