aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorTejas Belagod <tejas.belagod@arm.com>2012-06-18 11:43:03 +0100
committerTejas Belagod <belagod@gcc.gnu.org>2012-06-18 11:43:03 +0100
commit57a4717bd3f09f2270cf928a381fe204fd702a90 (patch)
tree3f348986a905d10f6625171379da020acb5abe77 /gcc
parentb7104c55e7d5c7335d1263131ac12ec9214b1dce (diff)
downloadgcc-57a4717bd3f09f2270cf928a381fe204fd702a90.zip
gcc-57a4717bd3f09f2270cf928a381fe204fd702a90.tar.gz
gcc-57a4717bd3f09f2270cf928a381fe204fd702a90.tar.bz2
Implement support for int iterators.
From-SVN: r188726
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/doc/md.texi78
-rw-r--r--gcc/read-rtl.c45
3 files changed, 131 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index be59b02..2f8e62d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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>
PR middle-end/53698
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index 50fa2f9..c71c59c 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -8895,6 +8895,7 @@ facilities to make this process easier.
@menu
* Mode Iterators:: Generating variations of patterns for different modes.
* Code Iterators:: Doing the same for codes.
+* Int Iterators:: Doing the same for integers.
@end menu
@node Mode Iterators
@@ -9166,4 +9167,81 @@ This is equivalent to:
@dots{}
@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
diff --git a/gcc/read-rtl.c b/gcc/read-rtl.c
index c588722..71ecf53 100644
--- a/gcc/read-rtl.c
+++ b/gcc/read-rtl.c
@@ -114,7 +114,7 @@ static rtx read_nested_rtx (void);
static rtx read_rtx_variadic (rtx);
/* 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. */
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);
}
+/* 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
isn't known. */
@@ -412,6 +431,7 @@ apply_iterators (rtx original, rtx *queue)
definition order within each group. */
htab_traverse (modes.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));
for (;;)
@@ -518,6 +538,12 @@ initialize_iterators (void)
codes.find_builtin = find_code;
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");
upper = add_mapping (&modes, modes.attrs, "MODE");
lower_ptr = &lower->values;
@@ -827,6 +853,16 @@ read_rtx (const char *rtx_name, rtx *x)
check_code_iterator (read_mapping (&codes, codes.iterators));
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);
VEC_truncate (iterator_use, iterator_uses, 0);
@@ -850,7 +886,6 @@ read_rtx_code (const char *code_name)
struct md_name name;
rtx return_rtx;
int c;
- int tmp_int;
HOST_WIDE_INT tmp_wide;
/* Linked list structure for making RTXs: */
@@ -1026,10 +1061,10 @@ read_rtx_code (const char *code_name)
case 'i':
case 'n':
+ /* Can be an iterator or an integer constant. */
read_name (&name);
- validate_const_int (name.string);
- tmp_int = atoi (name.string);
- XINT (return_rtx, i) = tmp_int;
+ record_potential_iterator_use (&ints, &XINT (return_rtx, i),
+ name.string);
break;
default: