aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorHariharan Sandanagobalane <hariharan@picochip.com>2010-04-30 09:40:21 +0000
committerHariharan Sandanagobalane <hariharans@gcc.gnu.org>2010-04-30 09:40:21 +0000
commit41700fc33bd80f9bac8565ca78a9a5fe3c896337 (patch)
tree4d431d1801fd8cfcc9e1bf12e77b84f78e83e81a /gcc
parent8b4765bf42585ab649517308c69d4df7e570636d (diff)
downloadgcc-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/ChangeLog15
-rw-r--r--gcc/config/picochip/picochip-protos.h4
-rw-r--r--gcc/config/picochip/picochip.c159
-rw-r--r--gcc/config/picochip/picochip.h5
-rw-r--r--gcc/config/picochip/picochip.md17
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"