Commit df023e0f by James Greenhalgh Committed by James Greenhalgh

[ARM, AArch64] Make aarch-common.c files more robust.

gcc/
	* config/arm/aarch-common.c
	(search_term): New typedef.
	(shift_rtx_costs): New array.
	(arm_rtx_shift_left_p): New.
	(arm_find_sub_rtx_with_search_term): Likewise.
	(arm_find_sub_rtx_with_code): Likewise.
	(arm_early_load_addr_dep): Add sanity checking.
	(arm_no_early_alu_shift_dep): Likewise.
	(arm_no_early_alu_shift_value_dep): Likewise.
	(arm_no_early_mul_dep): Likewise.
	(arm_no_early_store_addr_dep): Likewise.

From-SVN: r204575
parent 34d1ff06
2013-11-08 James Greenhalgh <james.greenhalgh@arm.com>
* config/arm/aarch-common.c
(search_term): New typedef.
(shift_rtx_costs): New array.
(arm_rtx_shift_left_p): New.
(arm_find_sub_rtx_with_search_term): Likewise.
(arm_find_sub_rtx_with_code): Likewise.
(arm_early_load_addr_dep): Add sanity checking.
(arm_no_early_alu_shift_dep): Likewise.
(arm_no_early_alu_shift_value_dep): Likewise.
(arm_no_early_mul_dep): Likewise.
(arm_no_early_store_addr_dep): Likewise.
2013-11-08 Richard Biener <rguenther@suse.de> 2013-11-08 Richard Biener <rguenther@suse.de>
PR tree-optimization/59047 PR tree-optimization/59047
...@@ -31,30 +31,139 @@ ...@@ -31,30 +31,139 @@
#include "c-family/c-common.h" #include "c-family/c-common.h"
#include "rtl.h" #include "rtl.h"
/* Return nonzero if the CONSUMER instruction (a load) does need typedef struct
PRODUCER's value to calculate the address. */ {
rtx_code search_code;
rtx search_result;
bool find_any_shift;
} search_term;
/* Return TRUE if X is either an arithmetic shift left, or
is a multiplication by a power of two. */
static bool
arm_rtx_shift_left_p (rtx x)
{
enum rtx_code code = GET_CODE (x);
int if (code == MULT && CONST_INT_P (XEXP (x, 1))
arm_early_load_addr_dep (rtx producer, rtx consumer) && exact_log2 (INTVAL (XEXP (x, 1))) > 0)
return true;
if (code == ASHIFT)
return true;
return false;
}
static rtx_code shift_rtx_codes[] =
{ ASHIFT, ROTATE, ASHIFTRT, LSHIFTRT,
ROTATERT, ZERO_EXTEND, SIGN_EXTEND };
/* Callback function for arm_find_sub_rtx_with_code.
DATA is safe to treat as a SEARCH_TERM, ST. This will
hold a SEARCH_CODE. PATTERN is checked to see if it is an
RTX with that code. If it is, write SEARCH_RESULT in ST
and return 1. Otherwise, or if we have been passed a NULL_RTX
return 0. If ST.FIND_ANY_SHIFT then we are interested in
anything which can reasonably be described as a SHIFT RTX. */
static int
arm_find_sub_rtx_with_search_term (rtx *pattern, void *data)
{ {
rtx value = PATTERN (producer); search_term *st = (search_term *) data;
rtx addr = PATTERN (consumer); rtx_code pattern_code;
int found = 0;
if (GET_CODE (value) == COND_EXEC)
value = COND_EXEC_CODE (value); gcc_assert (pattern);
if (GET_CODE (value) == PARALLEL) gcc_assert (st);
value = XVECEXP (value, 0, 0);
value = XEXP (value, 0); /* Poorly formed patterns can really ruin our day. */
if (GET_CODE (addr) == COND_EXEC) if (*pattern == NULL_RTX)
addr = COND_EXEC_CODE (addr); return 0;
if (GET_CODE (addr) == PARALLEL)
pattern_code = GET_CODE (*pattern);
if (st->find_any_shift)
{ {
if (GET_CODE (XVECEXP (addr, 0, 0)) == RETURN) unsigned i = 0;
addr = XVECEXP (addr, 0, 1);
/* Left shifts might have been canonicalized to a MULT of some
power of two. Make sure we catch them. */
if (arm_rtx_shift_left_p (*pattern))
found = 1;
else else
addr = XVECEXP (addr, 0, 0); for (i = 0; i < ARRAY_SIZE (shift_rtx_codes); i++)
if (pattern_code == shift_rtx_codes[i])
found = 1;
}
if (pattern_code == st->search_code)
found = 1;
if (found)
st->search_result = *pattern;
return found;
}
/* Traverse PATTERN looking for a sub-rtx with RTX_CODE CODE. */
static rtx
arm_find_sub_rtx_with_code (rtx pattern, rtx_code code, bool find_any_shift)
{
search_term st;
int result = 0;
gcc_assert (pattern != NULL_RTX);
st.search_code = code;
st.search_result = NULL_RTX;
st.find_any_shift = find_any_shift;
result = for_each_rtx (&pattern, arm_find_sub_rtx_with_search_term, &st);
if (result)
return st.search_result;
else
return NULL_RTX;
}
/* Traverse PATTERN looking for any sub-rtx which looks like a shift. */
static rtx
arm_find_shift_sub_rtx (rtx pattern)
{
return arm_find_sub_rtx_with_code (pattern, ASHIFT, true);
}
/* PRODUCER and CONSUMER are two potentially dependant RTX. PRODUCER
(possibly) contains a SET which will provide a result we can access
using the SET_DEST macro. We will place the RTX which would be
written by PRODUCER in SET_SOURCE.
Similarly, CONSUMER (possibly) contains a SET which has an operand
we can access using SET_SRC. We place this operand in
SET_DESTINATION.
Return nonzero if we found the SET RTX we expected. */
static int
arm_get_set_operands (rtx producer, rtx consumer,
rtx *set_source, rtx *set_destination)
{
rtx set_producer = arm_find_sub_rtx_with_code (producer, SET, false);
rtx set_consumer = arm_find_sub_rtx_with_code (consumer, SET, false);
if (set_producer && set_consumer)
{
*set_source = SET_DEST (set_producer);
*set_destination = SET_SRC (set_consumer);
return 1;
} }
addr = XEXP (addr, 1); return 0;
}
/* Return nonzero if the CONSUMER instruction (a load) does need
PRODUCER's value to calculate the address. */
int
arm_early_load_addr_dep (rtx producer, rtx consumer)
{
rtx value, addr;
if (!arm_get_set_operands (producer, consumer, &value, &addr))
return 0;
return reg_overlap_mentioned_p (value, addr); return reg_overlap_mentioned_p (value, addr);
} }
...@@ -62,88 +171,56 @@ arm_early_load_addr_dep (rtx producer, rtx consumer) ...@@ -62,88 +171,56 @@ arm_early_load_addr_dep (rtx producer, rtx consumer)
/* Return nonzero if the CONSUMER instruction (an ALU op) does not /* Return nonzero if the CONSUMER instruction (an ALU op) does not
have an early register shift value or amount dependency on the have an early register shift value or amount dependency on the
result of PRODUCER. */ result of PRODUCER. */
int int
arm_no_early_alu_shift_dep (rtx producer, rtx consumer) arm_no_early_alu_shift_dep (rtx producer, rtx consumer)
{ {
rtx value = PATTERN (producer); rtx value, op;
rtx op = PATTERN (consumer);
rtx early_op; rtx early_op;
if (GET_CODE (value) == COND_EXEC) if (!arm_get_set_operands (producer, consumer, &value, &op))
value = COND_EXEC_CODE (value); return 0;
if (GET_CODE (value) == PARALLEL)
value = XVECEXP (value, 0, 0); if ((early_op = arm_find_shift_sub_rtx (op)))
value = XEXP (value, 0); {
if (GET_CODE (op) == COND_EXEC) if (REG_P (early_op))
op = COND_EXEC_CODE (op); early_op = op;
if (GET_CODE (op) == PARALLEL)
op = XVECEXP (op, 0, 0); return !reg_overlap_mentioned_p (value, early_op);
op = XEXP (op, 1); }
early_op = XEXP (op, 0); return 0;
/* This is either an actual independent shift, or a shift applied to
the first operand of another operation. We want the whole shift
operation. */
if (REG_P (early_op))
early_op = op;
return !reg_overlap_mentioned_p (value, early_op);
} }
/* Return nonzero if the CONSUMER instruction (an ALU op) does not /* Return nonzero if the CONSUMER instruction (an ALU op) does not
have an early register shift value dependency on the result of have an early register shift value dependency on the result of
PRODUCER. */ PRODUCER. */
int int
arm_no_early_alu_shift_value_dep (rtx producer, rtx consumer) arm_no_early_alu_shift_value_dep (rtx producer, rtx consumer)
{ {
rtx value = PATTERN (producer); rtx value, op;
rtx op = PATTERN (consumer);
rtx early_op; rtx early_op;
if (GET_CODE (value) == COND_EXEC) if (!arm_get_set_operands (producer, consumer, &value, &op))
value = COND_EXEC_CODE (value); return 0;
if (GET_CODE (value) == PARALLEL)
value = XVECEXP (value, 0, 0); if ((early_op = arm_find_shift_sub_rtx (op)))
value = XEXP (value, 0); /* We want to check the value being shifted. */
if (GET_CODE (op) == COND_EXEC) if (!reg_overlap_mentioned_p (value, XEXP (early_op, 0)))
op = COND_EXEC_CODE (op); return 1;
if (GET_CODE (op) == PARALLEL)
op = XVECEXP (op, 0, 0); return 0;
op = XEXP (op, 1);
early_op = XEXP (op, 0);
/* This is either an actual independent shift, or a shift applied to
the first operand of another operation. We want the value being
shifted, in either case. */
if (!REG_P (early_op))
early_op = XEXP (early_op, 0);
return !reg_overlap_mentioned_p (value, early_op);
} }
/* Return nonzero if the CONSUMER (a mul or mac op) does not /* Return nonzero if the CONSUMER (a mul or mac op) does not
have an early register mult dependency on the result of have an early register mult dependency on the result of
PRODUCER. */ PRODUCER. */
int int
arm_no_early_mul_dep (rtx producer, rtx consumer) arm_no_early_mul_dep (rtx producer, rtx consumer)
{ {
rtx value = PATTERN (producer); rtx value, op;
rtx op = PATTERN (consumer);
if (!arm_get_set_operands (producer, consumer, &value, &op))
if (GET_CODE (value) == COND_EXEC) return 0;
value = COND_EXEC_CODE (value);
if (GET_CODE (value) == PARALLEL)
value = XVECEXP (value, 0, 0);
value = XEXP (value, 0);
if (GET_CODE (op) == COND_EXEC)
op = COND_EXEC_CODE (op);
if (GET_CODE (op) == PARALLEL)
op = XVECEXP (op, 0, 0);
op = XEXP (op, 1);
if (GET_CODE (op) == PLUS || GET_CODE (op) == MINUS) if (GET_CODE (op) == PLUS || GET_CODE (op) == MINUS)
{ {
...@@ -162,19 +239,17 @@ arm_no_early_mul_dep (rtx producer, rtx consumer) ...@@ -162,19 +239,17 @@ arm_no_early_mul_dep (rtx producer, rtx consumer)
int int
arm_no_early_store_addr_dep (rtx producer, rtx consumer) arm_no_early_store_addr_dep (rtx producer, rtx consumer)
{ {
rtx value = PATTERN (producer); rtx value = arm_find_sub_rtx_with_code (producer, SET, false);
rtx addr = PATTERN (consumer); rtx addr = arm_find_sub_rtx_with_code (consumer, SET, false);
if (GET_CODE (value) == COND_EXEC) if (value)
value = COND_EXEC_CODE (value); value = SET_DEST (value);
if (GET_CODE (value) == PARALLEL)
value = XVECEXP (value, 0, 0); if (addr)
value = XEXP (value, 0); addr = SET_DEST (addr);
if (GET_CODE (addr) == COND_EXEC)
addr = COND_EXEC_CODE (addr); if (!value || !addr)
if (GET_CODE (addr) == PARALLEL) return 0;
addr = XVECEXP (addr, 0, 0);
addr = XEXP (addr, 0);
return !reg_overlap_mentioned_p (value, addr); return !reg_overlap_mentioned_p (value, addr);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment