- if (ia64_tune == PROCESSOR_ITANIUM)
- /* Insert additional cycles for MM-insns (MMMUL and MMSHF).
- Itanium1 has a strange design, if the distance between an insn
- and dependent MM-insn is less 4 then we have a 6 additional
- cycles stall. So we make the distance equal to 4 cycles if it
- is less. */
- for (insn = get_next_important_insn (NEXT_INSN (prev_head_insn), tail);
- insn != NULL_RTX;
- insn = next_insn)
- {
- gcc_assert (INSN_P (insn)
- && ia64_safe_itanium_class (insn) != ITANIUM_CLASS_IGNORE
- && GET_CODE (PATTERN (insn)) != USE
- && GET_CODE (PATTERN (insn)) != CLOBBER);
- next_insn = get_next_important_insn (NEXT_INSN (insn), tail);
- if (INSN_UID (insn) < clocks_length && add_cycles [INSN_UID (insn)])
- /* We found a MM-insn which needs additional cycles. */
- {
- rtx last;
- int i, j, n;
- int pred_stop_p;
-
- /* Now we are searching for a template of the bundle in
- which the MM-insn is placed and the position of the
- insn in the bundle (0, 1, 2). Also we are searching
- for that there is a stop before the insn. */
- last = prev_active_insn (insn);
- pred_stop_p = recog_memoized (last) == CODE_FOR_insn_group_barrier;
- if (pred_stop_p)
- last = prev_active_insn (last);
- n = 0;
- for (;; last = prev_active_insn (last))
- if (recog_memoized (last) == CODE_FOR_bundle_selector)
- {
- template0 = XINT (XVECEXP (PATTERN (last), 0, 0), 0);
- if (template0 == 9)
- /* The insn is in MLX bundle. Change the template
- onto MFI because we will add nops before the
- insn. It simplifies subsequent code a lot. */
- PATTERN (last)
- = gen_bundle_selector (const2_rtx); /* -> MFI */
- break;
- }
- else if (recog_memoized (last) != CODE_FOR_insn_group_barrier
- && (ia64_safe_itanium_class (last)
- != ITANIUM_CLASS_IGNORE))
- n++;
- /* Some check of correctness: the stop is not at the
- bundle start, there are no more 3 insns in the bundle,
- and the MM-insn is not at the start of bundle with
- template MLX. */
- gcc_assert ((!pred_stop_p || n)
- && n <= 2
- && (template0 != 9 || !n));
- /* Put nops after the insn in the bundle. */
- for (j = 3 - n; j > 0; j --)
- ia64_emit_insn_before (gen_nop (), insn);
- /* It takes into account that we will add more N nops
- before the insn lately -- please see code below. */
- add_cycles [INSN_UID (insn)]--;
- if (!pred_stop_p || add_cycles [INSN_UID (insn)])
- ia64_emit_insn_before (gen_insn_group_barrier (GEN_INT (3)),
- insn);
- if (pred_stop_p)
- add_cycles [INSN_UID (insn)]--;
- for (i = add_cycles [INSN_UID (insn)]; i > 0; i--)
- {
- /* Insert "MII;" template. */
- ia64_emit_insn_before (gen_bundle_selector (const0_rtx),
- insn);
- ia64_emit_insn_before (gen_nop (), insn);
- ia64_emit_insn_before (gen_nop (), insn);
- if (i > 1)
- {
- /* To decrease code size, we use "MI;I;"
- template. */
- ia64_emit_insn_before
- (gen_insn_group_barrier (GEN_INT (3)), insn);
- i--;
- }
- ia64_emit_insn_before (gen_nop (), insn);
- ia64_emit_insn_before (gen_insn_group_barrier (GEN_INT (3)),
- insn);
- }
- /* Put the MM-insn in the same slot of a bundle with the
- same template as the original one. */
- ia64_add_bundle_selector_before (template0, insn);
- /* To put the insn in the same slot, add necessary number
- of nops. */
- for (j = n; j > 0; j --)
- ia64_emit_insn_before (gen_nop (), insn);
- /* Put the stop if the original bundle had it. */
- if (pred_stop_p)
- ia64_emit_insn_before (gen_insn_group_barrier (GEN_INT (3)),
- insn);
- }
- }