diff options
author | Richard Henderson <rth@cygnus.com> | 1998-08-26 11:48:21 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 1998-08-26 11:48:21 -0700 |
commit | 68aed21b05c657635e6a37efe8a992cc8b39883e (patch) | |
tree | a1b1bdc9b3978737aba1793850f82ca03dfffd60 /gcc | |
parent | 4bdc8810f6b2233b34b51c1491d9b70fad203e8d (diff) | |
download | gcc-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/ChangeLog | 19 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.c | 343 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.md | 50 |
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. |