mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-30 03:50:27 +08:00
Implement support for int iterators.
From-SVN: r188726
This commit is contained in:
parent
b7104c55e7
commit
57a4717bd3
@ -1,3 +1,16 @@
|
|||||||
|
2012-06-18 Tejas Belagod <tejas.belagod@arm.com>
|
||||||
|
|
||||||
|
* doc/md.texi: Document int iterators.
|
||||||
|
* read-rtl.c (ints): New iterator group.
|
||||||
|
(find_int): Int iterator group callback.
|
||||||
|
(apply_int_iterator): Likewise.
|
||||||
|
(apply_iterators): Traverse int iterator table and add all the used
|
||||||
|
iterators to list.
|
||||||
|
(initialize_iterators): Initialize data structures and callbacks for int
|
||||||
|
iterators.
|
||||||
|
(read_rtx): Parse and read mappings for int iterators.
|
||||||
|
(read_rtx_code): Record int iterator usage.
|
||||||
|
|
||||||
2012-06-18 Richard Sandiford <rdsandiford@googlemail.com>
|
2012-06-18 Richard Sandiford <rdsandiford@googlemail.com>
|
||||||
|
|
||||||
PR middle-end/53698
|
PR middle-end/53698
|
||||||
|
@ -8895,6 +8895,7 @@ facilities to make this process easier.
|
|||||||
@menu
|
@menu
|
||||||
* Mode Iterators:: Generating variations of patterns for different modes.
|
* Mode Iterators:: Generating variations of patterns for different modes.
|
||||||
* Code Iterators:: Doing the same for codes.
|
* Code Iterators:: Doing the same for codes.
|
||||||
|
* Int Iterators:: Doing the same for integers.
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
@node Mode Iterators
|
@node Mode Iterators
|
||||||
@ -9166,4 +9167,81 @@ This is equivalent to:
|
|||||||
@dots{}
|
@dots{}
|
||||||
@end smallexample
|
@end smallexample
|
||||||
|
|
||||||
|
@node Int Iterators
|
||||||
|
@subsection Int Iterators
|
||||||
|
@cindex int iterators in @file{.md} files
|
||||||
|
@findex define_int_iterator
|
||||||
|
@findex define_int_attr
|
||||||
|
|
||||||
|
Int iterators operate in a similar way to code iterators. @xref{Code Iterators}.
|
||||||
|
|
||||||
|
The construct:
|
||||||
|
|
||||||
|
@smallexample
|
||||||
|
(define_int_iterator @var{name} [(@var{int1} "@var{cond1}") @dots{} (@var{intn} "@var{condn}")])
|
||||||
|
@end smallexample
|
||||||
|
|
||||||
|
defines a pseudo integer constant @var{name} that can be instantiated as
|
||||||
|
@var{inti} if condition @var{condi} is true. Each @var{int}
|
||||||
|
must have the same rtx format. @xref{RTL Classes}. Int iterators can appear
|
||||||
|
in only those rtx fields that have 'i' as the specifier. This means that
|
||||||
|
each @var{int} has to be a constant defined using define_constant or
|
||||||
|
define_c_enum.
|
||||||
|
|
||||||
|
As with mode and code iterators, each pattern that uses @var{name} will be
|
||||||
|
expanded @var{n} times, once with all uses of @var{name} replaced by
|
||||||
|
@var{int1}, once with all uses replaced by @var{int2}, and so on.
|
||||||
|
@xref{Defining Mode Iterators}.
|
||||||
|
|
||||||
|
It is possible to define attributes for ints as well as for codes and modes.
|
||||||
|
Attributes are defined using:
|
||||||
|
|
||||||
|
@smallexample
|
||||||
|
(define_int_attr @var{name} [(@var{int1} "@var{value1}") @dots{} (@var{intn} "@var{valuen}")])
|
||||||
|
@end smallexample
|
||||||
|
|
||||||
|
Here's an example of int iterators in action, taken from the ARM port:
|
||||||
|
|
||||||
|
@smallexample
|
||||||
|
(define_int_iterator QABSNEG [UNSPEC_VQABS UNSPEC_VQNEG])
|
||||||
|
|
||||||
|
(define_int_attr absneg [(UNSPEC_VQABS "abs") (UNSPEC_VQNEG "neg")])
|
||||||
|
|
||||||
|
(define_insn "neon_vq<absneg><mode>"
|
||||||
|
[(set (match_operand:VDQIW 0 "s_register_operand" "=w")
|
||||||
|
(unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
|
||||||
|
(match_operand:SI 2 "immediate_operand" "i")]
|
||||||
|
QABSNEG))]
|
||||||
|
"TARGET_NEON"
|
||||||
|
"vq<absneg>.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
|
||||||
|
[(set_attr "neon_type" "neon_vqneg_vqabs")]
|
||||||
|
)
|
||||||
|
|
||||||
|
@end smallexample
|
||||||
|
|
||||||
|
This is equivalent to:
|
||||||
|
|
||||||
|
@smallexample
|
||||||
|
(define_insn "neon_vqabs<mode>"
|
||||||
|
[(set (match_operand:VDQIW 0 "s_register_operand" "=w")
|
||||||
|
(unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
|
||||||
|
(match_operand:SI 2 "immediate_operand" "i")]
|
||||||
|
UNSPEC_VQABS))]
|
||||||
|
"TARGET_NEON"
|
||||||
|
"vqabs.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
|
||||||
|
[(set_attr "neon_type" "neon_vqneg_vqabs")]
|
||||||
|
)
|
||||||
|
|
||||||
|
(define_insn "neon_vqneg<mode>"
|
||||||
|
[(set (match_operand:VDQIW 0 "s_register_operand" "=w")
|
||||||
|
(unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
|
||||||
|
(match_operand:SI 2 "immediate_operand" "i")]
|
||||||
|
UNSPEC_VQNEG))]
|
||||||
|
"TARGET_NEON"
|
||||||
|
"vqneg.<V_s_elem>\t%<V_reg>0, %<V_reg>1"
|
||||||
|
[(set_attr "neon_type" "neon_vqneg_vqabs")]
|
||||||
|
)
|
||||||
|
|
||||||
|
@end smallexample
|
||||||
|
|
||||||
@end ifset
|
@end ifset
|
||||||
|
@ -114,7 +114,7 @@ static rtx read_nested_rtx (void);
|
|||||||
static rtx read_rtx_variadic (rtx);
|
static rtx read_rtx_variadic (rtx);
|
||||||
|
|
||||||
/* The mode and code iterator structures. */
|
/* The mode and code iterator structures. */
|
||||||
static struct iterator_group modes, codes;
|
static struct iterator_group modes, codes, ints;
|
||||||
|
|
||||||
/* All iterators used in the current rtx. */
|
/* All iterators used in the current rtx. */
|
||||||
static VEC (mapping_ptr, heap) *current_iterators;
|
static VEC (mapping_ptr, heap) *current_iterators;
|
||||||
@ -165,6 +165,25 @@ apply_code_iterator (void *loc, int code)
|
|||||||
PUT_CODE ((rtx) loc, (enum rtx_code) code);
|
PUT_CODE ((rtx) loc, (enum rtx_code) code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Implementations of the iterator_group callbacks for ints. */
|
||||||
|
|
||||||
|
/* Since GCC does not construct a table of valid constants,
|
||||||
|
we have to accept any int as valid. No cross-checking can
|
||||||
|
be done. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
find_int (const char *name)
|
||||||
|
{
|
||||||
|
validate_const_int (name);
|
||||||
|
return atoi (name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
apply_int_iterator (void *loc, int value)
|
||||||
|
{
|
||||||
|
*(int *)loc = value;
|
||||||
|
}
|
||||||
|
|
||||||
/* Map attribute string P to its current value. Return null if the attribute
|
/* Map attribute string P to its current value. Return null if the attribute
|
||||||
isn't known. */
|
isn't known. */
|
||||||
|
|
||||||
@ -412,6 +431,7 @@ apply_iterators (rtx original, rtx *queue)
|
|||||||
definition order within each group. */
|
definition order within each group. */
|
||||||
htab_traverse (modes.iterators, add_current_iterators, NULL);
|
htab_traverse (modes.iterators, add_current_iterators, NULL);
|
||||||
htab_traverse (codes.iterators, add_current_iterators, NULL);
|
htab_traverse (codes.iterators, add_current_iterators, NULL);
|
||||||
|
htab_traverse (ints.iterators, add_current_iterators, NULL);
|
||||||
gcc_assert (!VEC_empty (mapping_ptr, current_iterators));
|
gcc_assert (!VEC_empty (mapping_ptr, current_iterators));
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
@ -518,6 +538,12 @@ initialize_iterators (void)
|
|||||||
codes.find_builtin = find_code;
|
codes.find_builtin = find_code;
|
||||||
codes.apply_iterator = apply_code_iterator;
|
codes.apply_iterator = apply_code_iterator;
|
||||||
|
|
||||||
|
ints.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
|
||||||
|
ints.iterators = htab_create (13, leading_string_hash,
|
||||||
|
leading_string_eq_p, 0);
|
||||||
|
ints.find_builtin = find_int;
|
||||||
|
ints.apply_iterator = apply_int_iterator;
|
||||||
|
|
||||||
lower = add_mapping (&modes, modes.attrs, "mode");
|
lower = add_mapping (&modes, modes.attrs, "mode");
|
||||||
upper = add_mapping (&modes, modes.attrs, "MODE");
|
upper = add_mapping (&modes, modes.attrs, "MODE");
|
||||||
lower_ptr = &lower->values;
|
lower_ptr = &lower->values;
|
||||||
@ -827,6 +853,16 @@ read_rtx (const char *rtx_name, rtx *x)
|
|||||||
check_code_iterator (read_mapping (&codes, codes.iterators));
|
check_code_iterator (read_mapping (&codes, codes.iterators));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (strcmp (rtx_name, "define_int_attr") == 0)
|
||||||
|
{
|
||||||
|
read_mapping (&ints, ints.attrs);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (strcmp (rtx_name, "define_int_iterator") == 0)
|
||||||
|
{
|
||||||
|
read_mapping (&ints, ints.iterators);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
apply_iterators (read_rtx_code (rtx_name), &queue_head);
|
apply_iterators (read_rtx_code (rtx_name), &queue_head);
|
||||||
VEC_truncate (iterator_use, iterator_uses, 0);
|
VEC_truncate (iterator_use, iterator_uses, 0);
|
||||||
@ -850,7 +886,6 @@ read_rtx_code (const char *code_name)
|
|||||||
struct md_name name;
|
struct md_name name;
|
||||||
rtx return_rtx;
|
rtx return_rtx;
|
||||||
int c;
|
int c;
|
||||||
int tmp_int;
|
|
||||||
HOST_WIDE_INT tmp_wide;
|
HOST_WIDE_INT tmp_wide;
|
||||||
|
|
||||||
/* Linked list structure for making RTXs: */
|
/* Linked list structure for making RTXs: */
|
||||||
@ -1026,10 +1061,10 @@ read_rtx_code (const char *code_name)
|
|||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
case 'n':
|
case 'n':
|
||||||
|
/* Can be an iterator or an integer constant. */
|
||||||
read_name (&name);
|
read_name (&name);
|
||||||
validate_const_int (name.string);
|
record_potential_iterator_use (&ints, &XINT (return_rtx, i),
|
||||||
tmp_int = atoi (name.string);
|
name.string);
|
||||||
XINT (return_rtx, i) = tmp_int;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user