diff options
author | Hariharan Sandanagobalane <hariharan@picochip.com> | 2010-04-30 09:40:21 +0000 |
---|---|---|
committer | Hariharan Sandanagobalane <hariharans@gcc.gnu.org> | 2010-04-30 09:40:21 +0000 |
commit | 41700fc33bd80f9bac8565ca78a9a5fe3c896337 (patch) | |
tree | 4d431d1801fd8cfcc9e1bf12e77b84f78e83e81a /gcc | |
parent | 8b4765bf42585ab649517308c69d4df7e570636d (diff) | |
download | gcc-41700fc33bd80f9bac8565ca78a9a5fe3c896337.zip gcc-41700fc33bd80f9bac8565ca78a9a5fe3c896337.tar.gz gcc-41700fc33bd80f9bac8565ca78a9a5fe3c896337.tar.bz2 |
picochip.c (picochip_legitimize_address): Define.
* config/picochip/picochip.c (picochip_legitimize_address): Define.
Use this function to do machine-specific conversion.
(picochip_legitimize_reload_address): Likewise.
(picochip_legitimate_address_p): Check valid base register only if
strict.
(picochip_check_conditional_copy): Check for modw only if opnd is
register.
* config/picochip/picochip.h (LEGITIMIZE_RELOAD_ADDRESS): Use this
to call the function in c.
* config/picochip/picochip-protos.h
(picochip_legitimize_reload_address): Define.
* config/picochip/picochip.md (supported_compare1): Define.
From-SVN: r158927
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/config/picochip/picochip-protos.h | 4 | ||||
-rw-r--r-- | gcc/config/picochip/picochip.c | 159 | ||||
-rw-r--r-- | gcc/config/picochip/picochip.h | 5 | ||||
-rw-r--r-- | gcc/config/picochip/picochip.md | 17 |
5 files changed, 194 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index dc50ee4..1a428b9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2010-04-30 Hariharan Sandanagobalane <hariharan@picochip.com> + + * config/picochip/picochip.c (picochip_legitimize_address): Define. + Use this function to do machine-specific conversion. + (picochip_legitimize_reload_address): Likewise. + (picochip_legitimate_address_p): Check valid base register only if + strict. + (picochip_check_conditional_copy): Check for modw only if opnd is + register. + * config/picochip/picochip.h (LEGITIMIZE_RELOAD_ADDRESS): Use this + to call the function in c. + * config/picochip/picochip-protos.h + (picochip_legitimize_reload_address): Define. + * config/picochip/picochip.md (supported_compare1): Define. + 2010-04-30 Jan Hubicka <jh@suse.cz> * cgraph.h (cgraph_local_info): Remove for_functions_valid. diff --git a/gcc/config/picochip/picochip-protos.h b/gcc/config/picochip/picochip-protos.h index de68c81..875bb1d 100644 --- a/gcc/config/picochip/picochip-protos.h +++ b/gcc/config/picochip/picochip-protos.h @@ -99,6 +99,10 @@ extern rtx picochip_struct_value_rtx(tree fntype ATTRIBUTE_UNUSED, #endif /* RTX_CODE inside TREE_CODE */ +extern int picochip_legitimize_reload_address (rtx *x, enum machine_mode mode, + int opnum, int type, int ind_levels); + + void picochip_output_ascii (FILE * file, const char *str, int length); extern int picochip_hard_regno_mode_ok (int regno, enum machine_mode mode); diff --git a/gcc/config/picochip/picochip.c b/gcc/config/picochip/picochip.c index 03df3fb..0d6db58 100644 --- a/gcc/config/picochip/picochip.c +++ b/gcc/config/picochip/picochip.c @@ -96,6 +96,10 @@ bool picochip_rtx_costs (rtx x, int code, int outer_code, int* total, bool speed bool picochip_return_in_memory(const_tree type, const_tree fntype ATTRIBUTE_UNUSED); bool picochip_legitimate_address_p (enum machine_mode, rtx, bool); +rtx picochip_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, + enum machine_mode mode); +int picochip_legitimize_reload_address (rtx *x, enum machine_mode mode, + int opnum, int type, int ind_levels); rtx picochip_struct_value_rtx(tree fntype ATTRIBUTE_UNUSED, int incoming ATTRIBUTE_UNUSED); rtx picochip_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED, @@ -279,6 +283,9 @@ static char picochip_get_vliw_alu_id (void); #undef TARGET_LEGITIMATE_ADDRESS_P #define TARGET_LEGITIMATE_ADDRESS_P picochip_legitimate_address_p +#undef TARGET_LEGITIMIZE_ADDRESS +#define TARGET_LEGITIMIZE_ADDRESS picochip_legitimize_address + /* Loading and storing QImode values to and from memory usually requires a scratch register. */ #undef TARGET_SECONDARY_RELOAD @@ -1268,9 +1275,13 @@ picochip_legitimate_address_p (enum machine_mode mode, rtx x, bool strict) { rtx base = XEXP (x, 0); rtx offset = XEXP (x, 1); + if (strict && !REGNO_OK_FOR_BASE_P (REGNO(base))) + { + valid = 0; + break; + } valid = (REG == GET_CODE (base) && - REGNO_OK_FOR_BASE_P (REGNO(base)) && picochip_legitimate_address_register (base, strict) && CONST_INT == GET_CODE (offset) && picochip_const_ok_for_base (mode, REGNO (base), @@ -1311,6 +1322,144 @@ picochip_legitimate_address_p (enum machine_mode mode, rtx x, bool strict) } +/* For all memory operations, picochip allows a uconst4 offset value. It + is hence beneficial to turn an + addr = <reg + long_const> + ld/st addr + + into + + X = reg + long_const & FFF0 + diff = long_const - (long_const & FFF0) + ld/st <X + diff> + + X can be reused in subsequent memory operations. + */ +rtx +picochip_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, + enum machine_mode mode) +{ + if (!optimize) + return x; + + unsigned mask_val; + // Depending on mode, the offsets allowed are either 16/32/64. + switch (mode) + { + case QImode: + mask_val = 0xFFF0; + break; + case HImode: + mask_val = 0xFFE0; + break; + case SImode: + mask_val = 0xFFC0; + break; + default: + return x; + } + + if (GET_CODE (x) == PLUS + && GET_CODE (XEXP (x, 0)) == REG + && GET_CODE (XEXP (x, 1)) == CONST_INT) + { + int offset = INTVAL (XEXP (x, 1)); + // Ignore cases with negative offsets. + if (offset < 0) + return x; + int high_val = offset & mask_val; + int low_val = offset - high_val; + if (high_val != 0) + { + rtx temp_reg = force_reg (Pmode, gen_rtx_PLUS (Pmode, XEXP (x, 0), GEN_INT(high_val))); + x = gen_rtx_PLUS (Pmode, temp_reg, GEN_INT(low_val)); + return x; + } + } + return x; +} + +/* For all memory operations, picochip allows a uconst4 offset value. It + is hence beneficial to turn an + addr = <reg + long_const> + ld/st addr + + into + + X = reg + long_const & FFF0 + diff = long_const - (long_const & FFF0) + ld/st <X + diff> + + X can be reused in subsequent memory operations. + */ +int +picochip_legitimize_reload_address (rtx *x, + enum machine_mode mode, + int opnum, int type, + int ind_levels ATTRIBUTE_UNUSED) +{ + if (picochip_symbol_offset(*x)) + { + *x = gen_rtx_CONST(mode, *x); + return 0; + } + if (!optimize) + return 0; + + /* We should recognise addresses that we created.*/ + if (GET_CODE (*x) == PLUS + && GET_CODE (XEXP (*x, 0)) == PLUS + && GET_CODE (XEXP (XEXP (*x, 0), 0)) == REG + && GET_CODE (XEXP (XEXP (*x, 0), 1)) == CONST_INT + && GET_CODE (XEXP (*x, 1)) == CONST_INT) + { + push_reload (XEXP (*x, 0), NULL_RTX, &XEXP (*x, 0), NULL, + BASE_REG_CLASS, GET_MODE (*x), VOIDmode, 0, 0, + opnum, (enum reload_type)type); + return 1; + } + + unsigned mask_val; + // Depending on mode, the offsets allowed are either 16/32/64. + switch (mode) + { + case QImode: + mask_val = 0xFFF0; + break; + case HImode: + mask_val = 0xFFE0; + break; + case SImode: + mask_val = 0xFFC0; + break; + default: + return 0; + } + + if (GET_CODE (*x) == PLUS + && GET_CODE (XEXP (*x, 0)) == REG + && GET_CODE (XEXP (*x, 1)) == CONST_INT) + { + int offset = INTVAL (XEXP (*x, 1)); + // Ignore cases with negative offsets. + if (offset < 0) + return 0; + int high_val = offset & mask_val; + int low_val = offset - high_val; + if (high_val != 0) + { + rtx temp_reg = gen_rtx_PLUS (Pmode, XEXP (*x, 0), GEN_INT(high_val)); + *x = gen_rtx_PLUS (Pmode, temp_reg, GEN_INT(low_val)); + push_reload (XEXP (*x, 0), NULL_RTX, &XEXP (*x, 0), NULL, + BASE_REG_CLASS, GET_MODE (*x), VOIDmode, 0, 0, + opnum, (enum reload_type)type); + return 1; + } + } + + return 0; +} + /* Detect an rtx which matches (plus (symbol_ref) (const_int)). */ int picochip_symbol_offset (rtx operand) @@ -4395,11 +4544,11 @@ picochip_check_conditional_copy (rtx * operands) handled using logical operations (e.g., SIreg != 0 when low || high). Need to find test cases to provoke this though (fixunssfdi in libgcc does, but is complicated). */ - if (GET_MODE (branch_op_0) != HImode || - !(register_operand (branch_op_0, GET_MODE (branch_op_0)))) + if (register_operand(branch_op_0, GET_MODE(branch_op_0)) && + GET_MODE(branch_op_0) != HImode) return 0; - if (GET_MODE (branch_op_1) != HImode || - !(picochip_comparison_operand (branch_op_1, GET_MODE (branch_op_1)))) + if (register_operand(branch_op_1, GET_MODE(branch_op_1)) && + GET_MODE(branch_op_1) != HImode) return 0; return 1; diff --git a/gcc/config/picochip/picochip.h b/gcc/config/picochip/picochip.h index bf2ecc0..7269fa0 100644 --- a/gcc/config/picochip/picochip.h +++ b/gcc/config/picochip/picochip.h @@ -495,7 +495,10 @@ extern const enum reg_class picochip_regno_reg_class[FIRST_PSEUDO_REGISTER]; correct code is generated. */ #define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \ -if (picochip_symbol_offset(X)) { X = gen_rtx_CONST(MODE, X); } +do { \ + if (picochip_legitimize_reload_address(&X,MODE,OPNUM,TYPE,IND_LEVELS)) \ + goto WIN; \ + } while(0); \ /* Nonzero if the constant rtx X is a legitimate general operand. X satisfies CONSTANT_P. */ diff --git a/gcc/config/picochip/picochip.md b/gcc/config/picochip/picochip.md index 02f0f14..62103506 100644 --- a/gcc/config/picochip/picochip.md +++ b/gcc/config/picochip/picochip.md @@ -590,6 +590,23 @@ (set_attr "length" "2,2,4") ]) +;; This pattern was added to match the previous pattern. When doing if-convert +;; the pattern generated using movhicc does not have a eq:CC but only a eq for +;; operator. If this pattern were not to be there, Gcc decides not to use +;; movhicc at all. Whereas, in Gcc 4.4, it seems to be cleverer. +(define_insn "*supported_compare1" + [(set (reg:CC CC_REGNUM) + (match_operator 0 "picochip_supported_comparison_operator" + [(match_operand:HI 1 "register_operand" "r,r,r") + (match_operand:HI 2 "picochip_comparison_operand" "r,J,i")]))] + "" + "* return picochip_output_compare(operands);" + [; Must be picoAlu because it sets the condition flags. + (set_attr "type" "picoAlu,picoAlu,picoAlu") + (set_attr "longConstant" "false,false,true") + (set_attr "length" "2,2,4") + ]) + (define_insn "*compare" [(set (reg:CC CC_REGNUM) (match_operator:CC 0 "comparison_operator" |