From: Michael Hayes Date: Fri, 3 Sep 1999 23:58:44 +0000 (+0000) Subject: c4x.c (c4x_emit_move_sequence): Do not force large constants into memory. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=483dd5bec16a1a1acc2bc65f4f5fda522e67277d;p=platform%2Fupstream%2Fgcc.git c4x.c (c4x_emit_move_sequence): Do not force large constants into memory. Sat Sep 4 11:37:15 1999 Michael Hayes * config/c4x/c4x.c (c4x_emit_move_sequence): Do not force large constants into memory. (c4x_shiftable_constant): New function. * config/c4x/c4x.c (LEGITIMATE_CONSTANT_P): Allow any CONST_INT. (c4x_shiftable_constant): Declare. * config/c4x/c4x.md (loadqi_big_constant, loadhi_big_constant, ashlqi3_noclobber): Add new patterns and associated splitters. From-SVN: r29092 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f391242..2c509e3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +Sat Sep 4 11:37:15 1999 Michael Hayes + + * config/c4x/c4x.c (c4x_emit_move_sequence): Do not force large + constants into memory. + (c4x_shiftable_constant): New function. + * config/c4x/c4x.c (LEGITIMATE_CONSTANT_P): Allow any CONST_INT. + (c4x_shiftable_constant): Declare. + * config/c4x/c4x.md (loadqi_big_constant, loadhi_big_constant, + ashlqi3_noclobber): Add new patterns and associated splitters. + Fri Sep 3 16:22:17 1999 Richard Henderson * dbxout.c (dbxout_init): Use xcalloc instead of xmalloc+bzero. diff --git a/gcc/config/c4x/c4x.c b/gcc/config/c4x/c4x.c index 35bd196..677c38c 100644 --- a/gcc/config/c4x/c4x.c +++ b/gcc/config/c4x/c4x.c @@ -1074,20 +1074,6 @@ c4x_emit_move_sequence (operands, mode) constants... */ op1 = force_const_mem (mode, op1); } - else if (mode == QImode && CONSTANT_P (op1) && ! LEGITIMATE_CONSTANT_P (op1)) - { - /* We shouldn't need this test if only emit_move_insn was called. - However, some routines call gen_move_insn which doesn't check that - the constants are legitimate. */ - op1 = force_const_mem (mode, op1); - } - else if (mode == HImode && CONSTANT_P (op1) && ! LEGITIMATE_CONSTANT_P (op1)) - { - /* We could load all sorts of constants in two goes by pulling all - sorts of tricks... The tricky thing is that we cannot clobber CC - so that stifles most of the obvious methods. */ - op1 = force_const_mem (mode, op1); - } /* Convert (MEM (SYMREF)) to a (MEM (LO_SUM (REG) (SYMREF))) and emit associated (HIGH (SYMREF)) if large memory model. @@ -2259,6 +2245,27 @@ c4x_immed_float_constant (op) int +c4x_shiftable_constant (op) + rtx op; +{ + int i; + int mask; + int val = INTVAL (op); + + for (i = 0; i < 16; i++) + { + if (val & (1 << i)) + break; + } + mask = ((0xffff >> i) << 16) | 0xffff; + if (IS_INT16_CONST (val & 0x80000000 ? (val >> i) | ~mask + : (val >> i) & mask)) + return i; + return -1; +} + + +int c4x_H_constant (op) rtx op; { @@ -2760,7 +2767,7 @@ reg_operand (op, mode) int mixed_subreg_operand (op, mode) rtx op; - enum machine_mode mode; + enum machine_mode mode ATTRIBUTE_UNUSED; { /* Allow (subreg:HF (reg:HI)) that be generated for a union of an int and a long double. */ diff --git a/gcc/config/c4x/c4x.h b/gcc/config/c4x/c4x.h index 2d019b5..14b0133 100644 --- a/gcc/config/c4x/c4x.h +++ b/gcc/config/c4x/c4x.h @@ -1675,7 +1675,7 @@ extern struct rtx_def *c4x_legitimize_reload_address (); #define LEGITIMATE_CONSTANT_P(X) \ ((GET_CODE (X) == CONST_DOUBLE && c4x_H_constant (X)) \ - || (GET_CODE (X) == CONST_INT && c4x_I_constant (X)) \ + || (GET_CODE (X) == CONST_INT) \ || (GET_CODE (X) == SYMBOL_REF) \ || (GET_CODE (X) == LABEL_REF) \ || (GET_CODE (X) == CONST) \ @@ -2750,6 +2750,8 @@ extern int not_rc_reg (); extern int not_modify_reg (); +extern int c4x_shiftable_constant (); + extern int c4x_H_constant (); extern int c4x_I_constant (); diff --git a/gcc/config/c4x/c4x.md b/gcc/config/c4x/c4x.md index 7f1b0f3..3504bd3 100644 --- a/gcc/config/c4x/c4x.md +++ b/gcc/config/c4x/c4x.md @@ -1130,11 +1130,13 @@ "") (define_split - [(set (match_operand:QI 0 "std_reg_operand" "") + [(set (match_operand:QI 0 "reg_operand" "") (match_operand:QI 1 "const_int_operand" ""))] "! TARGET_C3X - && (INTVAL (operands[1]) & ~0xffff) != 0 - && (INTVAL (operands[1]) & 0xffff) != 0" + && ! IS_INT16_CONST (INTVAL (operands[1])) + && ! IS_HIGH_CONST (INTVAL (operands[1])) + && reload_completed + && std_reg_operand (operands[0], QImode)" [(set (match_dup 0) (match_dup 2)) (set (match_dup 0) (ior:QI (match_dup 0) (match_dup 3)))] " @@ -1143,6 +1145,104 @@ operands[3] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 0xffff); }") +(define_split + [(set (match_operand:QI 0 "reg_operand" "") + (match_operand:QI 1 "const_int_operand" ""))] + "TARGET_C3X && ! TARGET_SMALL + && ! IS_INT16_CONST (INTVAL (operands[1])) + && reload_completed + && std_reg_operand (operands[0], QImode) + && c4x_shiftable_constant (operands[1]) < 0" + [(set (match_dup 0) (match_dup 2)) + (set (match_dup 0) (ashift:QI (match_dup 0) (match_dup 4))) + (set (match_dup 0) (ior:QI (match_dup 0) (match_dup 3)))] + " +{ + /* Generate two's complement value of 16 MSBs. */ + operands[2] = gen_rtx (CONST_INT, VOIDmode, + (((INTVAL (operands[1]) >> 16) & 0xffff) + - 0x8000) ^ ~0x7fff); + operands[3] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 0xffff); + operands[4] = gen_rtx (CONST_INT, VOIDmode, 16); +}") + +(define_split + [(set (match_operand:QI 0 "reg_operand" "") + (match_operand:QI 1 "const_int_operand" ""))] + "TARGET_C3X + && ! IS_INT16_CONST (INTVAL (operands[1])) + && reload_completed + && std_reg_operand (operands[0], QImode) + && c4x_shiftable_constant (operands[1]) >= 0" + [(set (match_dup 0) (match_dup 2)) + (set (match_dup 0) (ashift:QI (match_dup 0) (match_dup 3)))] + " +{ + /* Generate two's complement value of MSBs. */ + int shift = c4x_shiftable_constant (operands[1]); + + operands[2] = gen_rtx (CONST_INT, VOIDmode, + (((INTVAL (operands[1]) >> shift) & 0xffff) + - 0x8000) ^ ~0x7fff); + operands[3] = gen_rtx (CONST_INT, VOIDmode, shift); +}") + +(define_split + [(set (match_operand:QI 0 "reg_operand" "") + (match_operand:QI 1 "const_int_operand" ""))] + "! TARGET_SMALL + && ! IS_INT16_CONST (INTVAL (operands[1])) + && ! IS_HIGH_CONST (INTVAL (operands[1])) + && reload_completed + && ! std_reg_operand (operands[0], QImode)" + [(set (match_dup 2) (high:QI (match_dup 3))) + (set (match_dup 0) (match_dup 4)) + (use (match_dup 1))] + " +{ + rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO); + operands[2] = dp_reg; + operands[3] = force_const_mem (Pmode, operands[1]); + operands[4] = change_address (operands[3], QImode, + gen_rtx_LO_SUM (Pmode, dp_reg, + XEXP (operands[3], 0))); + operands[3] = XEXP (operands[3], 0); +}") + +(define_split + [(set (match_operand:QI 0 "reg_operand" "") + (match_operand:QI 1 "const_int_operand" ""))] + "TARGET_SMALL + && ! IS_INT16_CONST (INTVAL (operands[1])) + && ! IS_HIGH_CONST (INTVAL (operands[1])) + && reload_completed + && (TARGET_C3X && c4x_shiftable_constant (operands[1]) < 0 + || ! std_reg_operand (operands[0], QImode))" + [(set (match_dup 0) (match_dup 2)) + (use (match_dup 1))] + " +{ + rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO); + operands[2] = force_const_mem (Pmode, operands[1]); + operands[2] = change_address (operands[2], QImode, + gen_rtx_LO_SUM (Pmode, dp_reg, + XEXP (operands[2], 0))); +}") + +(define_split + [(set (match_operand:HI 0 "reg_operand" "") + (match_operand:HI 1 "const_int_operand" ""))] + "reload_completed" + [(set (match_dup 2) (match_dup 4)) + (set (match_dup 3) (match_dup 5))] + " +{ + operands[2] = c4x_operand_subword (operands[0], 0, 1, HImode); + operands[3] = c4x_operand_subword (operands[0], 1, 1, HImode); + operands[4] = c4x_operand_subword (operands[1], 0, 1, HImode); + operands[5] = c4x_operand_subword (operands[1], 1, 1, HImode); +}") + ; CC has been selected to load a symbolic address. We force the address ; into memory and then generate LDP and LDIU insns. ; This is also required for the C30 if we pretend that we can @@ -1189,7 +1289,14 @@ (define_insn "load_immed_address" [(set (match_operand:QI 0 "reg_operand" "=a?x?c*r") (match_operand:QI 1 "symbolic_address_operand" ""))] - "TARGET_LOAD_ADDRESS" + "TARGET_LOAD_ADDRESS" + "#" + [(set_attr "type" "multi")]) + +(define_insn "loadhi_big_constant" + [(set (match_operand:HI 0 "reg_operand" "=c*d") + (match_operand:HI 1 "const_int_operand" ""))] + "" "#" [(set_attr "type" "multi")]) @@ -1207,6 +1314,14 @@ "stik\\t%1,%0" [(set_attr "type" "store")]) +(define_insn "loadqi_big_constant" + [(set (match_operand:QI 0 "reg_operand" "=c*d") + (match_operand:QI 1 "const_int_operand" ""))] + "! IS_INT16_CONST (INTVAL (operands[1])) + && ! IS_HIGH_CONST (INTVAL (operands[1]))" + "#" + [(set_attr "type" "multi")]) + ; We must provide an alternative to store to memory in case we have to ; spill a register. (define_insn "movqi_noclobber" @@ -2516,6 +2631,19 @@ [(set_attr "type" "binarycc,binarycc,binarycc")]) ; Default to int16 data attr. +(define_insn "ashlqi3_noclobber" + [(set (match_operand:QI 0 "std_reg_operand" "=c,c,?c") + (ashift:QI (match_operand:QI 1 "src_operand" "0,rR,rS<>") + (match_operand:QI 2 "src_operand" "rIm,JR,rS<>")))] + "valid_operands (ASHIFT, operands, QImode)" + "@ + ash\\t%2,%0 + ash3\\t%2,%1,%0 + ash3\\t%2,%1,%0" + [(set_attr "type" "binary,binary,binary")]) +; Default to int16 data attr. + + ; This is only used by lshrhi3_reg where we need a LSH insn that will ; shift both ways. (define_insn "*lshlqi3_clobber"