+/* BYPASS is a define_bypass decl that includes glob pattern PATTERN.
+ Call FN (BYPASS, INSN, DATA) for each matching instruction INSN. */
+
+static void
+for_each_matching_insn (decl_t bypass, const char *pattern,
+ void (*fn) (decl_t, decl_t, void *), void *data)
+{
+ decl_t insn_reserv;
+ bool matched_p;
+ int i;
+
+ matched_p = false;
+ if (strpbrk (pattern, "*?["))
+ for (i = 0; i < description->decls_num; i++)
+ {
+ insn_reserv = description->decls[i];
+ if (insn_reserv->mode == dm_insn_reserv
+ && fnmatch (pattern, DECL_INSN_RESERV (insn_reserv)->name, 0) == 0)
+ {
+ fn (bypass, insn_reserv, data);
+ matched_p = true;
+ }
+ }
+ else
+ {
+ insn_reserv = find_insn_decl (pattern);
+ if (insn_reserv)
+ {
+ fn (bypass, insn_reserv, data);
+ matched_p = true;
+ }
+ }
+ if (!matched_p)
+ error ("there is no insn reservation that matches `%s'", pattern);
+}
+
+/* A subroutine of process_bypass that is called for each pair
+ of matching instructions. OUT_INSN_RESERV is the output
+ instruction and DATA is the input instruction. */
+
+static void
+process_bypass_2 (decl_t model, decl_t out_insn_reserv, void *data)
+{
+ struct bypass_decl *bypass;
+ decl_t in_insn_reserv;
+
+ in_insn_reserv = (decl_t) data;
+ if (strcmp (DECL_INSN_RESERV (in_insn_reserv)->name,
+ DECL_BYPASS (model)->in_pattern) == 0
+ && strcmp (DECL_INSN_RESERV (out_insn_reserv)->name,
+ DECL_BYPASS (model)->out_pattern) == 0)
+ bypass = DECL_BYPASS (model);
+ else
+ {
+ bypass = XCNEW (struct bypass_decl);
+ bypass->latency = DECL_BYPASS (model)->latency;
+ bypass->out_pattern = DECL_INSN_RESERV (out_insn_reserv)->name;
+ bypass->in_pattern = DECL_INSN_RESERV (in_insn_reserv)->name;
+ bypass->bypass_guard_name = DECL_BYPASS (model)->bypass_guard_name;
+ }
+ bypass->out_insn_reserv = DECL_INSN_RESERV (out_insn_reserv);
+ bypass->in_insn_reserv = DECL_INSN_RESERV (in_insn_reserv);
+ insert_bypass (bypass);
+}
+
+/* A subroutine of process_bypass that is called for each input
+ instruction IN_INSN_RESERV. */
+
+static void
+process_bypass_1 (decl_t bypass, decl_t in_insn_reserv,
+ void *data ATTRIBUTE_UNUSED)
+{
+ for_each_matching_insn (bypass, DECL_BYPASS (bypass)->out_pattern,
+ process_bypass_2, in_insn_reserv);
+}
+
+/* Process define_bypass decl BYPASS, inserting a bypass for each specific
+ pair of insn reservations. */
+
+static void
+process_bypass (decl_t bypass)
+{
+ for_each_matching_insn (bypass, DECL_BYPASS (bypass)->in_pattern,
+ process_bypass_1, NULL);
+}
+