/* Generate code from machine description to recognize rtl as insns.
- Copyright (C) 1987-2017 Free Software Foundation, Inc.
+ Copyright (C) 1987-2020 Free Software Foundation, Inc.
This file is part of GCC.
return r;
break;
- case 'i': case 'r': case 'w': case '0': case 's':
+ case 'r': case 'p': case 'i': case 'w': case '0': case 's':
break;
default:
return r;
break;
- case 'i': case 'r': case 'w': case '0': case 's':
+ case 'r': case 'p': case 'i': case 'w': case '0': case 's':
break;
default:
case VEC_SELECT:
if (GET_MODE (pattern) != VOIDmode)
{
- enum machine_mode mode = GET_MODE (pattern);
- enum machine_mode imode = GET_MODE (XEXP (pattern, 0));
- enum machine_mode emode
+ machine_mode mode = GET_MODE (pattern);
+ machine_mode imode = GET_MODE (XEXP (pattern, 0));
+ machine_mode emode
= VECTOR_MODE_P (mode) ? GET_MODE_INNER (mode) : mode;
if (GET_CODE (XEXP (pattern, 1)) == PARALLEL)
{
- int expected = VECTOR_MODE_P (mode) ? GET_MODE_NUNITS (mode) : 1;
- if (XVECLEN (XEXP (pattern, 1), 0) != expected)
+ int expected = 1;
+ unsigned int nelems;
+ if (VECTOR_MODE_P (mode)
+ && !GET_MODE_NUNITS (mode).is_constant (&expected))
+ error_at (info->loc,
+ "vec_select with variable-sized mode %s",
+ GET_MODE_NAME (mode));
+ else if (XVECLEN (XEXP (pattern, 1), 0) != expected)
error_at (info->loc,
"vec_select parallel with %d elements, expected %d",
XVECLEN (XEXP (pattern, 1), 0), expected);
+ else if (VECTOR_MODE_P (imode)
+ && GET_MODE_NUNITS (imode).is_constant (&nelems))
+ {
+ int i;
+ for (i = 0; i < expected; ++i)
+ if (CONST_INT_P (XVECEXP (XEXP (pattern, 1), 0, i))
+ && (UINTVAL (XVECEXP (XEXP (pattern, 1), 0, i))
+ >= nelems))
+ error_at (info->loc,
+ "out of bounds selector %u in vec_select, "
+ "expected at most %u",
+ (unsigned)
+ UINTVAL (XVECEXP (XEXP (pattern, 1), 0, i)),
+ nelems - 1);
+ }
}
if (imode != VOIDmode && !VECTOR_MODE_P (imode))
error_at (info->loc, "%smode of first vec_select operand is not a "
validate_pattern (XVECEXP (pattern, i, j), info, NULL_RTX, 0);
break;
- case 'i': case 'r': case 'w': case '0': case 's':
+ case 'r': case 'p': case 'i': case 'w': case '0': case 's':
break;
default:
to "T *prev, *next;" and a function "void set_parent (list_head <T> *)"
to set the parent list. */
template <typename T>
-struct list_head
+class list_head
{
+public:
/* A range of linked items. */
- struct range
+ class range
{
+ public:
range (T *);
range (T *, T *);
return first == last ? first : 0;
}
\f
-struct state;
+class state;
/* Describes a possible successful return from a routine. */
struct acceptance_type
}
/* Represents a parameter to a pattern routine. */
-struct parameter
+class parameter
{
+public:
/* The C type of parameter. */
enum type_enum {
/* Represents an invalid parameter. */
an ad-hoc enum value on success and -1 on failure. The routine can
be used by any subroutine type. The match can be parameterized by
things like mode, code and UNSPEC number. */
-struct pattern_routine
+class pattern_routine
{
+public:
/* The state that implements the pattern. */
state *s;
static vec <pattern_routine *> patterns;
/* Represents one use of a pattern routine. */
-struct pattern_use
+class pattern_use
{
+public:
/* The pattern routine to use. */
pattern_routine *routine;
};
/* Represents a test performed by a decision. */
-struct rtx_test
+class rtx_test
{
+public:
rtx_test ();
/* The types of test that can be performed. Most of them take as input
/* Check REGNO (X) == LABEL. */
REGNO_FIELD,
+ /* Check known_eq (SUBREG_BYTE (X), LABEL). */
+ SUBREG_FIELD,
+
/* Check XINT (X, u.opno) == LABEL. */
INT_FIELD,
static rtx_test code (position *);
static rtx_test mode (position *);
static rtx_test regno_field (position *);
+ static rtx_test subreg_field (position *);
static rtx_test int_field (position *, int);
static rtx_test wide_int_field (position *, int);
static rtx_test veclen (position *);
return res;
}
+rtx_test
+rtx_test::subreg_field (position *pos)
+{
+ rtx_test res (pos, rtx_test::SUBREG_FIELD);
+ return res;
+}
+
rtx_test
rtx_test::int_field (position *pos, int opno)
{
case rtx_test::CODE:
case rtx_test::MODE:
case rtx_test::REGNO_FIELD:
+ case rtx_test::SUBREG_FIELD:
case rtx_test::VECLEN:
case rtx_test::HAVE_NUM_CLOBBERS:
return true;
/* A simple set of transition labels. Most transitions have a singleton
label, so try to make that case as efficient as possible. */
-struct int_set : public auto_vec <uint64_t, 1>
+class int_set : public auto_vec <uint64_t, 1>
{
+public:
typedef uint64_t *iterator;
int_set ();
iterator end ();
};
-int_set::int_set () {}
+int_set::int_set () : auto_vec<uint64_t, 1> () {}
-int_set::int_set (uint64_t label)
+int_set::int_set (uint64_t label) :
+ auto_vec<uint64_t, 1> ()
{
safe_push (label);
}
-int_set::int_set (const int_set &other)
+int_set::int_set (const int_set &other) :
+ auto_vec<uint64_t, 1> ()
{
safe_splice (other);
}
return !operator == (a, b);
}
-struct decision;
+class decision;
/* Represents a transition between states, dependent on the result of
a test T. */
-struct transition
+class transition
{
+public:
transition (const int_set &, state *, bool);
void set_parent (list_head <transition> *);
to the transition's target state. If no suitable transition exists,
the machine either falls through to the next decision or, if there are no
more decisions to try, fails the match. */
-struct decision : list_head <transition>
+class decision : public list_head <transition>
{
+public:
decision (const rtx_test &);
void set_parent (list_head <decision> *s);
/* Represents one machine state. For each state the machine tries a list
of decisions, in order, and acts on the first match. It fails without
further backtracking if no decisions match. */
-struct state : list_head <decision>
+class state : public list_head <decision>
{
+public:
void set_parent (list_head <state> *) {}
};
const unsigned char TESTED_VECLEN = 2;
/* Represents a set of conditions that are known to hold. */
-struct known_conditions
+class known_conditions
{
+public:
/* A mask of TESTED_ values for each position, indexed by the position's
id field. */
auto_vec <unsigned char> position_tests;
gcc_unreachable ();
case rtx_test::REGNO_FIELD:
+ case rtx_test::SUBREG_FIELD:
case rtx_test::INT_FIELD:
case rtx_test::WIDE_INT_FIELD:
case rtx_test::VECLEN:
return parameter::MODE;
case rtx_test::REGNO_FIELD:
+ case rtx_test::SUBREG_FIELD:
return parameter::UINT;
case rtx_test::INT_FIELD:
}
/* Statistics about a matching routine. */
-struct stats
+class stats
{
+public:
stats ();
/* The total number of decisions in the routine, excluding trivial
st.longest_backtrack, st.longest_backtrack_code);
}
-struct merge_pattern_info;
+class merge_pattern_info;
/* Represents a transition from one pattern to another. */
-struct merge_pattern_transition
+class merge_pattern_transition
{
+public:
merge_pattern_transition (merge_pattern_info *);
/* The target pattern. */
/* Represents a pattern that can might match several states. The pattern
may replace parts of the test with a parameter value. It may also
replace transition labels with parameters. */
-struct merge_pattern_info
+class merge_pattern_info
{
+public:
merge_pattern_info (unsigned int);
/* If PARAM_TEST_P, the state's singleton test should be generalized
/* Describes one way of matching a particular state to a particular
pattern. */
-struct merge_state_result
+class merge_state_result
{
+public:
merge_state_result (merge_pattern_info *, position *, merge_state_result *);
/* A pattern that matches the state. */
/* Information about a state, used while trying to match it against
a pattern. */
-struct merge_state_info
+class merge_state_info
{
+public:
merge_state_info (state *);
/* The state itself. */
/* Pairs a pattern that needs to be matched with the rtx position at
which the pattern should occur. */
-struct pattern_pos {
+class pattern_pos {
+public:
pattern_pos () {}
pattern_pos (rtx, position *);
XWINT (pattern, 0), false);
break;
+ case 'p':
+ /* We don't have a way of parsing polynomial offsets yet,
+ and hopefully never will. */
+ s = add_decision (s, rtx_test::subreg_field (pos),
+ SUBREG_BYTE (pattern).to_constant (),
+ false);
+ break;
+
case '0':
break;
/* Generated automatically by the program `genrecog' from the target\n\
machine description file. */\n\
\n\
+#define IN_TARGET_CODE 1\n\
+\n\
#include \"config.h\"\n\
#include \"system.h\"\n\
#include \"coretypes.h\"\n\
/* Information used while writing out code. */
-struct output_state
+class output_state
{
+public:
/* The type of routine that we're generating. */
routine_type type;
break;
case parameter::MODE:
- printf ("%smode", GET_MODE_NAME ((machine_mode) param.value));
+ printf ("E_%smode", GET_MODE_NAME ((machine_mode) param.value));
break;
case parameter::INT:
printf (")");
break;
+ case rtx_test::SUBREG_FIELD:
+ printf ("SUBREG_BYTE (");
+ print_test_rtx (os, test);
+ printf (")");
+ break;
+
case rtx_test::WIDE_INT_FIELD:
printf ("XWINT (");
print_test_rtx (os, test);
print_label_value (test, is_param, value);
break;
+ case rtx_test::SUBREG_FIELD:
+ printf ("%s (", invert_p ? "maybe_ne" : "known_eq");
+ print_nonbool_test (os, test);
+ printf (", ");
+ print_label_value (test, is_param, value);
+ printf (")");
+ break;
+
case rtx_test::SAVED_CONST_INT:
gcc_assert (!is_param && value == 1);
print_test_rtx (os, test);