aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Henderson <rth@cygnus.com>1998-08-26 11:48:21 -0700
committerRichard Henderson <rth@gcc.gnu.org>1998-08-26 11:48:21 -0700
commit68aed21b05c657635e6a37efe8a992cc8b39883e (patch)
treea1b1bdc9b3978737aba1793850f82ca03dfffd60 /gcc
parent4bdc8810f6b2233b34b51c1491d9b70fad203e8d (diff)
downloadgcc-68aed21b05c657635e6a37efe8a992cc8b39883e.zip
gcc-68aed21b05c657635e6a37efe8a992cc8b39883e.tar.gz
gcc-68aed21b05c657635e6a37efe8a992cc8b39883e.tar.bz2
alpha.c (alpha_handle_trap_shadows): Remove do-nothing exit.
* alpha.c (alpha_handle_trap_shadows): Remove do-nothing exit. Tag trapb and next insn with TImode. (alphaev5_insn_pipe, alphaev5_next_group, alphaev5_align_insns): New. (alpha_reorg): Add conditional for alpha_handle_trap_shadows. Invoke alphaev5_align_insns as appropriate. * alpha.md (attr type): Add multi. (define_asm_attributes): New. (prologue_stack_probe_loop, builtin_setjmp_receiver): Set type multi. (arg_home): Likewise. (fnop, unop, realign): New. From-SVN: r22010
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog19
-rw-r--r--gcc/config/alpha/alpha.c343
-rw-r--r--gcc/config/alpha/alpha.md50
3 files changed, 394 insertions, 18 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 223e78a..aef593f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,22 @@
+Wed Aug 26 18:38:15 1998 Richard Henderson <rth@cygnus.com>
+
+ * haifa-sched.c (last_clock_var): New.
+ (schedule_block): Initialize it.
+ (schedule_insn): Use it to fill insn modes with issue information.
+
+ * alpha.c (alpha_handle_trap_shadows): Remove do-nothing exit.
+ Tag trapb and next insn with TImode.
+ (alphaev5_insn_pipe, alphaev5_next_group, alphaev5_align_insns): New.
+ (alpha_reorg): Add conditional for alpha_handle_trap_shadows.
+ Invoke alphaev5_align_insns as appropriate.
+ * alpha.h (LABEL_ALIGN_AFTER_BARRIER): Was ALIGN_LABEL_AFTER_BARRIER.
+ (MD_SCHED_VARIABLE_ISSUE): New.
+ * alpha.md (attr type): Add multi.
+ (define_asm_attributes): New.
+ (prologue_stack_probe_loop, builtin_setjmp_receiver): Set type multi.
+ (arg_home): Likewise.
+ (fnop, unop, realign): New.
+
Wed Aug 26 15:55:41 1998 Jim Wilson <wilson@cygnus.com>
* iris5.h (PREFERRED_DEBUGGING_TYPE): Undef.
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index efbb528..17cab88 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -1416,7 +1416,7 @@ alpha_emit_conditional_move (cmp, mode)
abort ();
}
- /* ??? We mark the the branch mode to be CCmode to prevent the compare
+ /* ??? We mark the branch mode to be CCmode to prevent the compare
and cmov from being combined, since the compare insn follows IEEE
rules that the cmov does not. */
if (alpha_compare_fp_p && !flag_fast_math)
@@ -4090,10 +4090,7 @@ alpha_handle_trap_shadows (insns)
{
struct shadow_summary shadow;
int trap_pending, exception_nesting;
- rtx i;
-
- if (alpha_tp == ALPHA_TP_PROG && !flag_exceptions)
- return;
+ rtx i, n;
trap_pending = 0;
exception_nesting = 0;
@@ -4196,7 +4193,9 @@ alpha_handle_trap_shadows (insns)
else
{
close_shadow:
- emit_insn_before (gen_trapb (), i);
+ n = emit_insn_before (gen_trapb (), i);
+ PUT_MODE (n, TImode);
+ PUT_MODE (i, TImode);
trap_pending = 0;
shadow.used.i = 0;
shadow.used.fp = 0;
@@ -4218,14 +4217,344 @@ alpha_handle_trap_shadows (insns)
}
}
}
+
+#ifdef HAIFA
+/* Alpha can only issue instruction groups simultaneously if they are
+ suitibly aligned. This is very processor-specific. */
+
+enum alphaev5_pipe {
+ EV5_STOP = 0,
+ EV5_NONE = 1,
+ EV5_E01 = 2,
+ EV5_E0 = 4,
+ EV5_E1 = 8,
+ EV5_FAM = 16,
+ EV5_FA = 32,
+ EV5_FM = 64
+};
+
+static enum alphaev5_pipe
+alphaev5_insn_pipe (insn)
+ rtx insn;
+{
+ if (recog_memoized (insn) < 0)
+ return EV5_STOP;
+ if (get_attr_length (insn) != 4)
+ return EV5_STOP;
+
+ switch (get_attr_type (insn))
+ {
+ case TYPE_ILD:
+ case TYPE_FLD:
+ case TYPE_LDSYM:
+ case TYPE_IADD:
+ case TYPE_ILOG:
+ case TYPE_ICMOV:
+ case TYPE_ICMP:
+ return EV5_E01;
+
+ case TYPE_IST:
+ case TYPE_FST:
+ case TYPE_SHIFT:
+ case TYPE_IMUL:
+ case TYPE_MISC:
+ case TYPE_MVI:
+ return EV5_E0;
+
+ case TYPE_IBR:
+ case TYPE_JSR:
+ return EV5_E1;
+
+ case TYPE_FCPYS:
+ return EV5_FAM;
+
+ case TYPE_FBR:
+ case TYPE_FCMOV:
+ case TYPE_FADD:
+ case TYPE_FDIV:
+ return EV5_FA;
+
+ case TYPE_FMUL:
+ return EV5_FM;
+ }
+ abort();
+}
+
+/* IN_USE is a mask of the slots currently filled within the
+ insn group. The mask bits come from alphaev5_pipe above.
+ If EV5_E01 is set, then the insn in EV5_E0 can be swapp
+ by the hardware into EV5_E1.
+
+ LEN is, of course, the length of the group in bytes. */
+
+static rtx
+alphaev5_next_group (insn, pin_use, plen)
+ rtx insn;
+ int *pin_use, *plen;
+{
+ int len, in_use;
+
+ len = in_use = 0;
+
+ if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+ goto next;
+
+ do
+ {
+ enum alphaev5_pipe pipe;
+ rtx prev;
+
+ pipe = alphaev5_insn_pipe (insn);
+ switch (pipe)
+ {
+ case EV5_STOP:
+ /* Force complex instructions to start new groups. */
+ if (in_use)
+ goto done;
+
+ /* If this is a completely unrecognized insn, its an asm.
+ We don't know how long it is, so record length as -1 to
+ signal a needed realignment. */
+ if (recog_memoized (insn) < 0)
+ len = -1;
+ else
+ len = get_attr_length (insn);
+ goto next;
+
+ /* ??? Most of the places below, we would like to abort, as
+ it would indicate an error either in Haifa, or in the
+ scheduling description. Unfortunately, Haifa never
+ schedules the last instruction of the BB, so we don't
+ have an accurate TI bit to go off. */
+ case EV5_E01:
+ if (in_use & EV5_E0)
+ {
+ if (in_use & EV5_E1)
+ goto done;
+ in_use |= EV5_E1;
+ }
+ else
+ in_use |= EV5_E0 | EV5_E01;
+ break;
+
+ case EV5_E0:
+ if (in_use & EV5_E0)
+ {
+ if (!(in_use & EV5_E01) || in_use & EV5_E1)
+ goto done;
+ in_use |= EV5_E1;
+ }
+ in_use |= EV5_E0;
+ break;
+
+ case EV5_E1:
+ if (in_use & EV5_E1)
+ goto done;
+ in_use |= EV5_E1;
+ break;
+
+ case EV5_FAM:
+ if (in_use & EV5_FA)
+ {
+ if (in_use & EV5_FM)
+ goto done;
+ in_use |= EV5_FM;
+ }
+ else
+ in_use |= EV5_FA | EV5_FAM;
+ break;
+
+ case EV5_FA:
+ if (in_use & EV5_FA)
+ goto done;
+ in_use |= EV5_FA;
+ break;
+
+ case EV5_FM:
+ if (in_use & EV5_FM)
+ goto done;
+ in_use |= EV5_FM;
+ break;
+
+ case EV5_NONE:
+ break;
+
+ default:
+ abort();
+ }
+ len += 4;
+
+ /* Haifa doesn't do well scheduling branches. */
+ /* ??? If this is predicted not-taken, slotting continues, except
+ that no more IBR, FBR, or JSR insns may be slotted. */
+ if (GET_CODE (insn) == JUMP_INSN)
+ goto next;
+
+ insn = next_nonnote_insn (insn);
+
+ if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+ goto done;
+ /* Let Haifa tell us where it thinks insn group boundaries are. */
+ if (GET_MODE (insn) == TImode)
+ goto done;
+
+ }
+ while (insn);
+
+ done:
+ *plen = len;
+ *pin_use = in_use;
+ return insn;
+
+ next:
+ insn = next_nonnote_insn (insn);
+ goto done;
+}
+
+static void
+alphaev5_align_insns (insns)
+ rtx insns;
+{
+ /* ALIGN is the known alignment for the insn group. */
+ int align;
+ /* OFS is the offset of the current insn in the insn group. */
+ int ofs;
+ int prev_in_use, in_use, len;
+ rtx i, next;
+
+ /* Let shorten branches care for assigning alignments to code labels. */
+ shorten_branches (insns);
+
+ ofs = prev_in_use = 0;
+ if (alpha_does_function_need_gp())
+ {
+ ofs = 8;
+ prev_in_use = EV5_E01 | EV5_E0;
+ }
+ align = (FUNCTION_BOUNDARY/BITS_PER_UNIT < 16
+ ? FUNCTION_BOUNDARY/BITS_PER_UNIT : 16);
+
+ i = insns;
+ if (GET_CODE (i) == NOTE)
+ i = next_nonnote_insn (i);
+
+ while (i)
+ {
+ next = alphaev5_next_group (i, &in_use, &len);
+
+ /* When we see a label, resync alignment etc. */
+ if (GET_CODE (i) == CODE_LABEL)
+ {
+ int new_align = 1 << label_to_alignment (i);
+ if (new_align >= align)
+ {
+ align = new_align < 16 ? new_align : 16;
+ ofs = 0;
+ }
+ else if (ofs & (new_align-1))
+ ofs = (ofs | (new_align-1)) + 1;
+ if (len != 0)
+ abort();
+ }
+
+ /* Handle complex instructions special. */
+ else if (in_use == 0)
+ {
+ /* Asms will have length < 0. This is a signal that we have
+ lost alignment knowledge. Assume, however, that the asm
+ will not mis-align instructions. */
+ if (len < 0)
+ {
+ ofs = 0;
+ align = 4;
+ len = 0;
+ }
+ }
+
+ /* If the known alignment is smaller than the recognized insn group,
+ realign the output. */
+ else if (align < len)
+ {
+ int new_log_align = len > 8 ? 4 : 3;
+ rtx where;
+
+ where = prev_nonnote_insn (i);
+ if (!where || GET_CODE (where) != CODE_LABEL)
+ where = i;
+
+ emit_insn_before (gen_realign (GEN_INT (new_log_align)), where);
+ align = 1 << new_log_align;
+ ofs = 0;
+ }
+
+ /* If the group won't fit in the same INT16 as the previous,
+ we need to add padding to keep the group together. Rather
+ than simply leaving the insn filling to the assembler, we
+ can make use of the knowledge of what sorts of instructions
+ were issued in the previous group to make sure that all of
+ the added nops are really free. */
+ else if (ofs + len > align)
+ {
+ int nop_count = (align - ofs) / 4;
+ rtx where;
+
+ where = prev_nonnote_insn (i);
+ if (!where || GET_CODE (where) != CODE_LABEL)
+ where = i;
+
+ do
+ {
+ if (!(prev_in_use & EV5_E1))
+ {
+ prev_in_use |= EV5_E1;
+ emit_insn_before (gen_nop(), where);
+ }
+ else if (TARGET_FP && !(prev_in_use & EV5_FA))
+ {
+ prev_in_use |= EV5_FA;
+ emit_insn_before (gen_fnop(), where);
+ }
+ else if (TARGET_FP && !(prev_in_use & EV5_FM))
+ {
+ prev_in_use |= EV5_FM;
+ emit_insn_before (gen_fnop(), where);
+ }
+ else
+ emit_insn_before (gen_unop(), where);
+ }
+ while (--nop_count);
+ ofs = 0;
+ }
+
+ ofs = (ofs + len) & (align - 1);
+ prev_in_use = in_use;
+ i = next;
+ }
+}
+#endif /* HAIFA */
+
/* Machine dependant reorg pass. */
void
alpha_reorg (insns)
rtx insns;
{
- alpha_handle_trap_shadows (insns);
+ if (alpha_tp != ALPHA_TP_PROG || flag_exceptions)
+ alpha_handle_trap_shadows (insns);
+
+#ifdef HAIFA
+ /* Due to the number of extra trapb insns, don't bother fixing up
+ alignment when trap precision is instruction. Moreover, we can
+ only do our job when sched2 is run and Haifa is our scheduler. */
+ if (optimize && !optimize_size
+ && alpha_tp != ALPHA_TP_INSN
+ && flag_schedule_insns_after_reload)
+ {
+ if (alpha_cpu == PROCESSOR_EV5)
+ alphaev5_align_insns (insns);
+ }
+#endif
}
diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md
index b4afc21..89184bf 100644
--- a/gcc/config/alpha/alpha.md
+++ b/gcc/config/alpha/alpha.md
@@ -38,6 +38,7 @@
;; 3 builtin_longjmp
;; 4 trapb
;; 5 prologue_stack_probe_loop
+;; 6 realign
;; Processor type -- this attribute must exactly match the processor_type
;; enumeration in alpha.h.
@@ -51,9 +52,13 @@
;; separately.
(define_attr "type"
- "ild,fld,ldsym,ist,fst,ibr,fbr,jsr,iadd,ilog,shift,icmov,fcmov,icmp,imul,fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof"
+ "ild,fld,ldsym,ist,fst,ibr,fbr,jsr,iadd,ilog,shift,icmov,fcmov,icmp,imul,fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(const_string "iadd"))
+;; Describe a user's asm statement.
+(define_asm_attributes
+ [(set_attr "type" "multi")])
+
;; Define the operand size an insn operates on. Used primarily by mul
;; and div operations that have size dependant timings.
@@ -3833,12 +3838,6 @@
"jmp $31,(%0),0"
[(set_attr "type" "ibr")])
-(define_insn "nop"
- [(const_int 0)]
- ""
- "nop"
- [(set_attr "type" "ilog")])
-
(define_expand "tablejump"
[(use (match_operand:SI 0 "register_operand" ""))
(use (match_operand:SI 1 "" ""))]
@@ -5124,7 +5123,8 @@
return \"\";
}"
- [(set_attr "length" "16")])
+ [(set_attr "length" "16")
+ (set_attr "type" "multi")])
(define_expand "prologue"
[(clobber (const_int 0))]
@@ -5171,13 +5171,15 @@
[(unspec_volatile [(match_operand 0 "" "")] 2)]
"! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT && TARGET_AS_CAN_SUBTRACT_LABELS"
"\\n$LSJ%=:\;ldgp $29,$LSJ%=-%l0($27)"
- [(set_attr "length" "8")])
+ [(set_attr "length" "8")
+ (set_attr "type" "multi")])
(define_insn ""
[(unspec_volatile [(match_operand 0 "" "")] 2)]
"! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT"
"br $27,$LSJ%=\\n$LSJ%=:\;ldgp $29,0($27)"
- [(set_attr "length" "12")])
+ [(set_attr "length" "12")
+ (set_attr "type" "multi")])
(define_expand "nonlocal_goto_receiver"
[(unspec_volatile [(const_int 0)] 1)
@@ -5209,7 +5211,8 @@
(clobber (reg:DI 0))]
"TARGET_OPEN_VMS"
"lda $0,OTS$HOME_ARGS\;ldq $0,8($0)\;jsr $0,OTS$HOME_ARGS"
- [(set_attr "length" "16")])
+ [(set_attr "length" "16")
+ (set_attr "type" "multi")])
;; Close the trap shadow of preceeding instructions. This is generated
;; by alpha_reorg.
@@ -5219,6 +5222,31 @@
""
"trapb"
[(set_attr "type" "misc")])
+
+;; No-op instructions used by machine-dependant reorg to preserve
+;; alignment for instruction issue.
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "nop"
+ [(set_attr "type" "ilog")])
+
+(define_insn "fnop"
+ [(const_int 1)]
+ "TARGET_FP"
+ "fnop"
+ [(set_attr "type" "fcpys")])
+
+(define_insn "unop"
+ [(const_int 2)]
+ ""
+ "unop")
+
+(define_insn "realign"
+ [(unspec_volatile [(match_operand 0 "immediate_operand" "i")] 6)]
+ ""
+ ".align %0 #realign")
;; Peepholes go at the end.