genattrtab bit-rot, and if_then_else in values
This patch started off just by adding if_then_else support in write_attr_value to be able to write a saner expression for powerpc tls_gdld_nomark length. Then I noticed bit-rot in functions used to calculate insn_default_length, insn_min_length, and length_unit_log (which are used by the shorten_branches pass). These functions don't handle a const_int length value and return an "unknown" status that isn't used, or in the case of or_attr_value, doesn't need to be used. min_attr_value also attempts to return INT_MAX for the unhandled rtl case, but this can get lost in recursive calls. I fixed that problem by returning INT_MIN instead, and translating that to INT_MAX in the only caller of min_attr_value. PR target/88614 * genattrtab.c (max_attr_value, min_attr_value, or_attr_value): Delete "unknownp" parameter. Adjust callers. Handle CONST_INT, PLUS, MINUS, and MULT. (attr_value_aligned): Renamed from or_attr_value. (min_attr_value): Return INT_MIN for unhandled rtl case.. (min_fn): ..and translate to INT_MAX here. (write_length_unit_log): Modify to cope without "unknown". (write_attr_value): Handle IF_THEN_ELSE. From-SVN: r267666
This commit is contained in:
parent
65c5b1eb85
commit
2d8d93c783
2 changed files with 155 additions and 45 deletions
|
@ -1,3 +1,15 @@
|
|||
2019-01-08 Alan Modra <amodra@gmail.com>
|
||||
|
||||
PR target/88614
|
||||
* genattrtab.c (max_attr_value, min_attr_value, or_attr_value):
|
||||
Delete "unknownp" parameter. Adjust callers. Handle
|
||||
CONST_INT, PLUS, MINUS, and MULT.
|
||||
(attr_value_aligned): Renamed from or_attr_value.
|
||||
(min_attr_value): Return INT_MIN for unhandled rtl case..
|
||||
(min_fn): ..and translate to INT_MAX here.
|
||||
(write_length_unit_log): Modify to cope without "unknown".
|
||||
(write_attr_value): Handle IF_THEN_ELSE.
|
||||
|
||||
2019-01-07 Richard Sandiford <richard.sandiford@arm.com>
|
||||
|
||||
* tree-vect-stmts.c (vectorizable_store): Don't use the dataref_offset
|
||||
|
|
188
gcc/genattrtab.c
188
gcc/genattrtab.c
|
@ -266,9 +266,9 @@ static int compares_alternatives_p (rtx);
|
|||
static void make_internal_attr (const char *, rtx, int);
|
||||
static void insert_insn_ent (struct attr_value *, struct insn_ent *);
|
||||
static void walk_attr_value (rtx);
|
||||
static int max_attr_value (rtx, int*);
|
||||
static int min_attr_value (rtx, int*);
|
||||
static int or_attr_value (rtx, int*);
|
||||
static int max_attr_value (rtx);
|
||||
static int min_attr_value (rtx);
|
||||
static unsigned int attr_value_alignment (rtx);
|
||||
static rtx simplify_test_exp (rtx, int, int);
|
||||
static rtx simplify_test_exp_in_temp (rtx, int, int);
|
||||
static rtx copy_rtx_unchanging (rtx);
|
||||
|
@ -1550,15 +1550,16 @@ one_fn (rtx exp ATTRIBUTE_UNUSED)
|
|||
static rtx
|
||||
max_fn (rtx exp)
|
||||
{
|
||||
int unknown;
|
||||
return make_numeric_value (max_attr_value (exp, &unknown));
|
||||
return make_numeric_value (max_attr_value (exp));
|
||||
}
|
||||
|
||||
static rtx
|
||||
min_fn (rtx exp)
|
||||
{
|
||||
int unknown;
|
||||
return make_numeric_value (min_attr_value (exp, &unknown));
|
||||
int val = min_attr_value (exp);
|
||||
if (val < 0)
|
||||
val = INT_MAX;
|
||||
return make_numeric_value (val);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1568,24 +1569,21 @@ write_length_unit_log (FILE *outf)
|
|||
struct attr_value *av;
|
||||
struct insn_ent *ie;
|
||||
unsigned int length_unit_log, length_or;
|
||||
int unknown = 0;
|
||||
|
||||
if (length_attr)
|
||||
{
|
||||
length_or = or_attr_value (length_attr->default_val->value, &unknown);
|
||||
length_or = attr_value_alignment (length_attr->default_val->value);
|
||||
for (av = length_attr->first_value; av; av = av->next)
|
||||
for (ie = av->first_insn; ie; ie = ie->next)
|
||||
length_or |= or_attr_value (av->value, &unknown);
|
||||
}
|
||||
length_or |= attr_value_alignment (av->value);
|
||||
|
||||
if (length_attr == NULL || unknown)
|
||||
length_unit_log = 0;
|
||||
else
|
||||
{
|
||||
length_or = ~length_or;
|
||||
for (length_unit_log = 0; length_or & 1; length_or >>= 1)
|
||||
length_unit_log++;
|
||||
}
|
||||
else
|
||||
length_unit_log = 0;
|
||||
|
||||
fprintf (outf, "EXPORTED_CONST int length_unit_log = %u;\n", length_unit_log);
|
||||
}
|
||||
|
||||
|
@ -3753,11 +3751,12 @@ write_test_expr (FILE *outf, rtx exp, unsigned int attrs_cached, int flags,
|
|||
return attrs_cached;
|
||||
}
|
||||
|
||||
/* Given an attribute value, return the maximum CONST_STRING argument
|
||||
encountered. Set *UNKNOWNP and return INT_MAX if the value is unknown. */
|
||||
/* Given an attribute value expression, return the maximum value that
|
||||
might be evaluated. Return INT_MAX if the value can't be
|
||||
calculated by this function. */
|
||||
|
||||
static int
|
||||
max_attr_value (rtx exp, int *unknownp)
|
||||
max_attr_value (rtx exp)
|
||||
{
|
||||
int current_max;
|
||||
int i, n;
|
||||
|
@ -3768,25 +3767,62 @@ max_attr_value (rtx exp, int *unknownp)
|
|||
current_max = atoi (XSTR (exp, 0));
|
||||
break;
|
||||
|
||||
case CONST_INT:
|
||||
current_max = INTVAL (exp);
|
||||
break;
|
||||
|
||||
case PLUS:
|
||||
current_max = max_attr_value (XEXP (exp, 0));
|
||||
if (current_max != INT_MAX)
|
||||
{
|
||||
n = current_max;
|
||||
current_max = max_attr_value (XEXP (exp, 1));
|
||||
if (current_max != INT_MAX)
|
||||
current_max += n;
|
||||
}
|
||||
break;
|
||||
|
||||
case MINUS:
|
||||
current_max = max_attr_value (XEXP (exp, 0));
|
||||
if (current_max != INT_MAX)
|
||||
{
|
||||
n = min_attr_value (XEXP (exp, 1));
|
||||
if (n == INT_MIN)
|
||||
current_max = INT_MAX;
|
||||
else
|
||||
current_max -= n;
|
||||
}
|
||||
break;
|
||||
|
||||
case MULT:
|
||||
current_max = max_attr_value (XEXP (exp, 0));
|
||||
if (current_max != INT_MAX)
|
||||
{
|
||||
n = current_max;
|
||||
current_max = max_attr_value (XEXP (exp, 1));
|
||||
if (current_max != INT_MAX)
|
||||
current_max *= n;
|
||||
}
|
||||
break;
|
||||
|
||||
case COND:
|
||||
current_max = max_attr_value (XEXP (exp, 1), unknownp);
|
||||
current_max = max_attr_value (XEXP (exp, 1));
|
||||
for (i = 0; i < XVECLEN (exp, 0); i += 2)
|
||||
{
|
||||
n = max_attr_value (XVECEXP (exp, 0, i + 1), unknownp);
|
||||
n = max_attr_value (XVECEXP (exp, 0, i + 1));
|
||||
if (n > current_max)
|
||||
current_max = n;
|
||||
}
|
||||
break;
|
||||
|
||||
case IF_THEN_ELSE:
|
||||
current_max = max_attr_value (XEXP (exp, 1), unknownp);
|
||||
n = max_attr_value (XEXP (exp, 2), unknownp);
|
||||
current_max = max_attr_value (XEXP (exp, 1));
|
||||
n = max_attr_value (XEXP (exp, 2));
|
||||
if (n > current_max)
|
||||
current_max = n;
|
||||
break;
|
||||
|
||||
default:
|
||||
*unknownp = 1;
|
||||
current_max = INT_MAX;
|
||||
break;
|
||||
}
|
||||
|
@ -3794,11 +3830,12 @@ max_attr_value (rtx exp, int *unknownp)
|
|||
return current_max;
|
||||
}
|
||||
|
||||
/* Given an attribute value, return the minimum CONST_STRING argument
|
||||
encountered. Set *UNKNOWNP and return 0 if the value is unknown. */
|
||||
/* Given an attribute value expression, return the minimum value that
|
||||
might be evaluated. Return INT_MIN if the value can't be
|
||||
calculated by this function. */
|
||||
|
||||
static int
|
||||
min_attr_value (rtx exp, int *unknownp)
|
||||
min_attr_value (rtx exp)
|
||||
{
|
||||
int current_min;
|
||||
int i, n;
|
||||
|
@ -3809,40 +3846,77 @@ min_attr_value (rtx exp, int *unknownp)
|
|||
current_min = atoi (XSTR (exp, 0));
|
||||
break;
|
||||
|
||||
case CONST_INT:
|
||||
current_min = INTVAL (exp);
|
||||
break;
|
||||
|
||||
case PLUS:
|
||||
current_min = min_attr_value (XEXP (exp, 0));
|
||||
if (current_min != INT_MIN)
|
||||
{
|
||||
n = current_min;
|
||||
current_min = min_attr_value (XEXP (exp, 1));
|
||||
if (current_min != INT_MIN)
|
||||
current_min += n;
|
||||
}
|
||||
break;
|
||||
|
||||
case MINUS:
|
||||
current_min = min_attr_value (XEXP (exp, 0));
|
||||
if (current_min != INT_MIN)
|
||||
{
|
||||
n = max_attr_value (XEXP (exp, 1));
|
||||
if (n == INT_MAX)
|
||||
current_min = INT_MIN;
|
||||
else
|
||||
current_min -= n;
|
||||
}
|
||||
break;
|
||||
|
||||
case MULT:
|
||||
current_min = min_attr_value (XEXP (exp, 0));
|
||||
if (current_min != INT_MIN)
|
||||
{
|
||||
n = current_min;
|
||||
current_min = min_attr_value (XEXP (exp, 1));
|
||||
if (current_min != INT_MIN)
|
||||
current_min *= n;
|
||||
}
|
||||
break;
|
||||
|
||||
case COND:
|
||||
current_min = min_attr_value (XEXP (exp, 1), unknownp);
|
||||
current_min = min_attr_value (XEXP (exp, 1));
|
||||
for (i = 0; i < XVECLEN (exp, 0); i += 2)
|
||||
{
|
||||
n = min_attr_value (XVECEXP (exp, 0, i + 1), unknownp);
|
||||
n = min_attr_value (XVECEXP (exp, 0, i + 1));
|
||||
if (n < current_min)
|
||||
current_min = n;
|
||||
}
|
||||
break;
|
||||
|
||||
case IF_THEN_ELSE:
|
||||
current_min = min_attr_value (XEXP (exp, 1), unknownp);
|
||||
n = min_attr_value (XEXP (exp, 2), unknownp);
|
||||
current_min = min_attr_value (XEXP (exp, 1));
|
||||
n = min_attr_value (XEXP (exp, 2));
|
||||
if (n < current_min)
|
||||
current_min = n;
|
||||
break;
|
||||
|
||||
default:
|
||||
*unknownp = 1;
|
||||
current_min = INT_MAX;
|
||||
current_min = INT_MIN;
|
||||
break;
|
||||
}
|
||||
|
||||
return current_min;
|
||||
}
|
||||
|
||||
/* Given an attribute value, return the result of ORing together all
|
||||
CONST_STRING arguments encountered. Set *UNKNOWNP and return -1
|
||||
if the numeric value is not known. */
|
||||
/* Given an attribute value expression, return the alignment of values.
|
||||
Return 0 if EXP is known to be zero, and 1 if the value can't be
|
||||
calculated by this function. */
|
||||
|
||||
static int
|
||||
or_attr_value (rtx exp, int *unknownp)
|
||||
static unsigned int
|
||||
attr_value_alignment (rtx exp)
|
||||
{
|
||||
int current_or;
|
||||
unsigned int current_or;
|
||||
int i;
|
||||
|
||||
switch (GET_CODE (exp))
|
||||
|
@ -3851,24 +3925,38 @@ or_attr_value (rtx exp, int *unknownp)
|
|||
current_or = atoi (XSTR (exp, 0));
|
||||
break;
|
||||
|
||||
case CONST_INT:
|
||||
current_or = INTVAL (exp);
|
||||
break;
|
||||
|
||||
case PLUS:
|
||||
case MINUS:
|
||||
current_or = attr_value_alignment (XEXP (exp, 0));
|
||||
current_or |= attr_value_alignment (XEXP (exp, 1));
|
||||
break;
|
||||
|
||||
case MULT:
|
||||
current_or = attr_value_alignment (XEXP (exp, 0));
|
||||
current_or *= attr_value_alignment (XEXP (exp, 1));
|
||||
break;
|
||||
|
||||
case COND:
|
||||
current_or = or_attr_value (XEXP (exp, 1), unknownp);
|
||||
current_or = attr_value_alignment (XEXP (exp, 1));
|
||||
for (i = 0; i < XVECLEN (exp, 0); i += 2)
|
||||
current_or |= or_attr_value (XVECEXP (exp, 0, i + 1), unknownp);
|
||||
current_or |= attr_value_alignment (XVECEXP (exp, 0, i + 1));
|
||||
break;
|
||||
|
||||
case IF_THEN_ELSE:
|
||||
current_or = or_attr_value (XEXP (exp, 1), unknownp);
|
||||
current_or |= or_attr_value (XEXP (exp, 2), unknownp);
|
||||
current_or = attr_value_alignment (XEXP (exp, 1));
|
||||
current_or |= attr_value_alignment (XEXP (exp, 2));
|
||||
break;
|
||||
|
||||
default:
|
||||
*unknownp = 1;
|
||||
current_or = -1;
|
||||
current_or = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return current_or;
|
||||
return current_or & -current_or;
|
||||
}
|
||||
|
||||
/* Scan an attribute value, possibly a conditional, and record what actions
|
||||
|
@ -4343,6 +4431,16 @@ write_attr_value (FILE *outf, struct attr_desc *attr, rtx value)
|
|||
write_attr_value (outf, attr, XEXP (value, 1));
|
||||
break;
|
||||
|
||||
case IF_THEN_ELSE:
|
||||
fprintf (outf, "(");
|
||||
write_test_expr (outf, XEXP (value, 0), 0, 0, false);
|
||||
fprintf (outf, " ? ");
|
||||
write_attr_value (outf, attr, XEXP (value, 1));
|
||||
fprintf (outf, " : ");
|
||||
write_attr_value (outf, attr, XEXP (value, 2));
|
||||
fprintf (outf, ")");
|
||||
break;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue