From 009ac3d3247f0e5fef4ced6dd013e9a85a862869 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 18 May 2000 09:52:10 -0700 Subject: [PATCH] h8300.c (ok_for_bclr): Take a HOST_WIDE_INT. * 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. From-SVN: r33985 --- gcc/ChangeLog | 17 ++++ gcc/config/h8300/h8300-protos.h | 8 +- gcc/config/h8300/h8300.c | 160 +++++++++++++------------------- gcc/config/h8300/h8300.h | 18 ++-- gcc/config/h8300/h8300.md | 122 ++++++++---------------- 5 files changed, 133 insertions(+), 192 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 66fdc617a77..0788cdfee9d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2000-05-18 Richard Henderson + + * 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. + 2000-05-18 Zack Weinberg * cppexp.c (parse_assertion): New. diff --git a/gcc/config/h8300/h8300-protos.h b/gcc/config/h8300/h8300-protos.h index 0f4bf78e5d8..147e8995ad3 100644 --- a/gcc/config/h8300/h8300-protos.h +++ b/gcc/config/h8300/h8300-protos.h @@ -36,14 +36,14 @@ extern void notice_update_cc PARAMS ((rtx, rtx)); 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 adds_subs_operand PARAMS ((rtx, enum machine_mode)); -extern int one_insn_adds_subs_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)); @@ -70,6 +70,6 @@ extern void function_prologue PARAMS ((FILE *, int)); 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 ok_for_bclr PARAMS ((HOST_WIDE_INT)); +extern int small_power_of_two PARAMS ((HOST_WIDE_INT)); extern int initial_offset PARAMS ((int, int)); diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c index ee4d0ad31d4..9425cbf6bca 100644 --- a/gcc/config/h8300/h8300.c +++ b/gcc/config/h8300/h8300.c @@ -542,29 +542,10 @@ asm_file_end (file) int small_power_of_two (value) - int value; + HOST_WIDE_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; + int power = exact_log2 (value); + return power >= 0 && power <= 15; } /* Return true if VALUE is a valid constant for constraint 'O', which @@ -573,7 +554,7 @@ small_power_of_two (value) int ok_for_bclr (value) - int value; + HOST_WIDE_INT value; { return small_power_of_two ((~value) & 0xff); } @@ -645,107 +626,92 @@ call_insn_operand (op, mode) } int -adds_subs_operand (op, mode) +two_insn_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; -} + HOST_WIDE_INT value = INTVAL (op); -/* 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 (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; + } + } - 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) +/* Split an add of a small constant into two adds/subs insns. */ + +void +split_adds_subs (mode, operands) + enum machine_mode mode; rtx *operands; { - int val = INTVAL (operands[2]); + HOST_WIDE_INT val = INTVAL (operands[1]); + rtx reg = operands[0]; + rtx tmp; - /* 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) + /* Take care of +/- 4 for H8300H and H8300S. */ + if (TARGET_H8300H || TARGET_H8300S) { - output_asm_insn ("adds #4,%A0", operands); - val -= 4; - } + /* 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) - { - output_asm_insn ("subs #4,%A0", operands); - 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; + } } - /* 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"; - + /* Get the value in range of +/- 2. */ if (val > 2) { - output_asm_insn ("adds #2,%A0", operands); + tmp = gen_rtx_PLUS (mode, reg, GEN_INT (2)); + emit_insn (gen_rtx_SET (VOIDmode, reg, tmp)); val -= 2; } - - if (val < -2) + else if (val < -2) { - output_asm_insn ("subs #2,%A0", operands); + tmp = gen_rtx_PLUS (mode, reg, GEN_INT (-2)); + emit_insn (gen_rtx_SET (VOIDmode, reg, tmp)); 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 ""; + 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 (); diff --git a/gcc/config/h8300/h8300.h b/gcc/config/h8300/h8300.h index 276a3c0753a..7fdedf8e3cd 100644 --- a/gcc/config/h8300/h8300.h +++ b/gcc/config/h8300/h8300.h @@ -399,11 +399,17 @@ enum reg_class { 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_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)) @@ -415,7 +421,7 @@ enum reg_class { (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) : \ + (C) == 'P' ? CONST_OK_FOR_P (VALUE) : \ 0) /* Similar, but for floating constants, and defining letters G and H. diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md index fe0cca18ef3..eeabdeeb3d9 100644 --- a/gcc/config/h8300/h8300.md +++ b/gcc/config/h8300/h8300.md @@ -614,43 +614,40 @@ "" "") -;; 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")))] + [(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" "4,2,6") - (set_attr "cc" "clobber,set_zn,set_zn")]) + [(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") - (plus:HI (match_operand:HI 1 "register_operand" "%0,0") - (match_operand:HI 2 "nonmemory_operand" "n,r")))] + [(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" "4,2") - (set_attr "cc" "set_zn,set_zn")]) + [(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,21 +656,6 @@ "" "") -;; 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") @@ -687,15 +669,25 @@ (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")))] + [(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" "6,2") - (set_attr "cc" "set_zn,set_zn")]) + [(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,26 +711,6 @@ "" "") -;; 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") @@ -777,26 +749,6 @@ [(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") (minus:SI (match_operand:SI 1 "general_operand" "0,0") -- 2.30.2