alpha call patterns
John Carr
jfc@tiac.net
Sat Sep 27 07:22:00 GMT 1997
A while back I was working on improving the call patterns on Alpha. The
problem is, the compiler doesn't know that a call is really a load
instruction followed by a jump. Neither gcc nor the GNU assembler would
separate the load and use so every call took a few cycles longer than it
should have. (I think the OSF assembler would but gcc tells it not to.)
I don't know if newer versions of gcc or gas are any better. I gave up on
Alpha a year ago (Linux/Alpha was so bad that I decided I would be better
off using my Alpha as a table to hold my SPARC manuals).
Here are the diffs relative to a year old gcc2 snapshot. I'm not asking
that they be installed in egcs. They should be used as a starting point
for anyone who wants to do similar work.
In summary, r27 is now in a new register class, call instructions use a
register in that class, and operand 1 of a call instruction is used to hold
the real function being called (if known) to set the branch target
prediction field.
*** gcc-ss/config/alpha/alpha.h Sat Nov 16 07:23:09 1996
--- gcc/config/alpha/alpha.h Sun Dec 15 16:32:47 1996
***************
*** 562,568 ****
For any two classes, it is very desirable that there be another
class that represents their union. */
! enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS,
LIM_REG_CLASSES };
#define N_REG_CLASSES (int) LIM_REG_CLASSES
--- 562,568 ----
For any two classes, it is very desirable that there be another
class that represents their union. */
! enum reg_class { NO_REGS, R27_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS,
LIM_REG_CLASSES };
#define N_REG_CLASSES (int) LIM_REG_CLASSES
***************
*** 570,583 ****
/* Give names of register classes as strings for dump file. */
#define REG_CLASS_NAMES \
! {"NO_REGS", "GENERAL_REGS", "FLOAT_REGS", "ALL_REGS" }
/* Define which registers fit in which classes.
This is an initializer for a vector of HARD_REG_SET
of length N_REG_CLASSES. */
#define REG_CLASS_CONTENTS \
! { {0, 0}, {~0, 0x80000000}, {0, 0x7fffffff}, {~0, ~0} }
/* The same information, inverted:
Return the class number of the smallest class containing
--- 570,583 ----
/* Give names of register classes as strings for dump file. */
#define REG_CLASS_NAMES \
! {"NO_REGS", "R27", "GENERAL_REGS", "FLOAT_REGS", "ALL_REGS" }
/* Define which registers fit in which classes.
This is an initializer for a vector of HARD_REG_SET
of length N_REG_CLASSES. */
#define REG_CLASS_CONTENTS \
! { {0, 0}, {1<<27, 0}, {~0, 0x80000000}, {0, 0x7fffffff}, {~0, ~0} }
/* The same information, inverted:
Return the class number of the smallest class containing
***************
*** 585,591 ****
or could index an array. */
#define REGNO_REG_CLASS(REGNO) \
! ((REGNO) >= 32 && (REGNO) <= 62 ? FLOAT_REGS : GENERAL_REGS)
/* The class value for index registers, and the one for base regs. */
#define INDEX_REG_CLASS NO_REGS
--- 585,592 ----
or could index an array. */
#define REGNO_REG_CLASS(REGNO) \
! ((REGNO) == 27 ? R27_REGS : \
! ((REGNO) >= 32 && (REGNO) <= 62 ? FLOAT_REGS : GENERAL_REGS))
/* The class value for index registers, and the one for base regs. */
#define INDEX_REG_CLASS NO_REGS
***************
*** 594,600 ****
/* Get reg_class from a letter such as appears in the machine description. */
#define REG_CLASS_FROM_LETTER(C) \
! ((C) == 'f' ? FLOAT_REGS : NO_REGS)
/* Define this macro to change register usage conditional on target flags. */
/* #define CONDITIONAL_REGISTER_USAGE */
--- 595,601 ----
/* Get reg_class from a letter such as appears in the machine description. */
#define REG_CLASS_FROM_LETTER(C) \
! ((C) == 'f' ? FLOAT_REGS : (C) == 'c' ? R27_REGS : NO_REGS)
/* Define this macro to change register usage conditional on target flags. */
/* #define CONDITIONAL_REGISTER_USAGE */
diff -c -r gcc-ss/config/alpha/alpha.md gcc/config/alpha/alpha.md
*** gcc-ss/config/alpha/alpha.md Wed Dec 11 17:06:35 1996
--- gcc/config/alpha/alpha.md Sun Dec 15 16:35:00 1996
***************
*** 3003,3019 ****
(clobber (reg:DI 26))])]
""
"
! { if (GET_CODE (operands[0]) != MEM)
abort ();
! operands[0] = XEXP (operands[0], 0);
! if (GET_CODE (operands[0]) != SYMBOL_REF
! && ! (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 27))
{
! rtx tem = gen_rtx (REG, DImode, 27);
! emit_move_insn (tem, operands[0]);
! operands[0] = tem;
}
}")
--- 2892,2909 ----
(clobber (reg:DI 26))])]
""
"
! { rtx addr;
! if (GET_CODE (operands[0]) != MEM)
abort ();
! operands[0] = addr = XEXP (operands[0], 0);
! operands[1] = GET_CODE (addr) == SYMBOL_REF ? addr : const0_rtx;
! if ((GET_CODE (addr) != REG || REGNO (addr) != 27)
! && ! (GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FLAG (addr)))
{
! operands[0] = gen_rtx (REG, DImode, 27);
! emit_move_insn (operands[0], addr);
}
}")
***************
*** 3115,3131 ****
(clobber (reg:DI 26))])]
""
"
! { if (GET_CODE (operands[1]) != MEM)
abort ();
! operands[1] = XEXP (operands[1], 0);
! if (GET_CODE (operands[1]) != SYMBOL_REF
! && ! (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 27))
{
! rtx tem = gen_rtx (REG, DImode, 27);
! emit_move_insn (tem, operands[1]);
! operands[1] = tem;
}
}")
--- 3005,3022 ----
(clobber (reg:DI 26))])]
""
"
! { rtx addr;
! if (GET_CODE (operands[1]) != MEM)
abort ();
! operands[1] = addr = XEXP (operands[1], 0);
! operands[2] = GET_CODE (addr) == SYMBOL_REF ? addr : const0_rtx;
! if ((GET_CODE (addr) != REG || REGNO (addr) != 27)
! && ! (GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FLAG (addr)))
{
! operands[1] = gen_rtx (REG, DImode, 27);
! emit_move_insn (operands[1], addr);
}
}")
***************
*** 3136,3142 ****
(clobber (reg:DI 26))])]
""
"
! { if (GET_CODE (operands[1]) != MEM)
abort ();
operands[1] = XEXP (operands[1], 0);
--- 3027,3034 ----
(clobber (reg:DI 26))])]
""
"
! { extern int cse_not_expected;
! if (GET_CODE (operands[1]) != MEM)
abort ();
operands[1] = XEXP (operands[1], 0);
***************
*** 3147,3152 ****
--- 3039,3052 ----
emit_move_insn (tem, operands[1]);
operands[1] = tem;
}
+ else if (! cse_not_expected && GET_CODE (operands[1]) == SYMBOL_REF
+ && ! SYMBOL_REF_FLAG (operands[1]))
+ {
+ rtx tem = gen_rtx (REG, DImode, 27);
+ operands[2] = operands[1];
+ emit_move_insn (tem, copy_to_reg (operands[1]));
+ operands[1] = tem;
+ }
}")
(define_expand "call_value_vms"
***************
*** 3196,3224 ****
}")
(define_insn ""
! [(call (mem:DI (match_operand:DI 0 "call_operand" "r,R,i"))
(match_operand 1 "" ""))
(clobber (reg:DI 27))
(clobber (reg:DI 26))]
"! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS && alpha_tp == ALPHA_TP_INSN"
"@
! jsr $26,($27),0\;trapb\;ldgp $29,4($26)
! bsr $26,%0..ng\;trapb
! jsr $26,%0\;trapb\;ldgp $29,4($26)"
! [(set_attr "type" "jsr,jsr,ibr")])
!
(define_insn ""
! [(call (mem:DI (match_operand:DI 0 "call_operand" "r,R,i"))
(match_operand 1 "" ""))
(clobber (reg:DI 27))
(clobber (reg:DI 26))]
"! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS"
"@
! jsr $26,($27),0\;ldgp $29,0($26)
! bsr $26,%0..ng
! jsr $26,%0\;ldgp $29,0($26)"
! [(set_attr "type" "jsr,jsr,ibr")])
!
(define_insn ""
[(call (mem:DI (match_operand:DI 0 "call_operand" "r,i"))
(match_operand 1 "" ""))
--- 3096,3122 ----
}")
(define_insn ""
! [(call (mem:DI (match_operand:DI 0 "call_operand" "c,R"))
(match_operand 1 "" ""))
(clobber (reg:DI 27))
(clobber (reg:DI 26))]
"! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS && alpha_tp == ALPHA_TP_INSN"
"@
! jsr $26,($27),%1\;trapb\;ldgp $29,4($26)
! bsr $26,%0..ng\;trapb"
! [(set_attr "type" "jsr,ibr")])
!
(define_insn ""
! [(call (mem:DI (match_operand:DI 0 "call_operand" "c,R"))
(match_operand 1 "" ""))
(clobber (reg:DI 27))
(clobber (reg:DI 26))]
"! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS"
"@
! jsr $26,($27),%1\;ldgp $29,0($26)
! bsr $26,%0..ng"
! [(set_attr "type" "jsr,ibr")])
!
(define_insn ""
[(call (mem:DI (match_operand:DI 0 "call_operand" "r,i"))
(match_operand 1 "" ""))
***************
*** 3243,3272 ****
[(set_attr "type" "jsr")])
(define_insn ""
! [(set (match_operand 0 "register_operand" "=rf,rf,rf")
! (call (mem:DI (match_operand:DI 1 "call_operand" "r,R,i"))
(match_operand 2 "" "")))
(clobber (reg:DI 27))
(clobber (reg:DI 26))]
"! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS && alpha_tp == ALPHA_TP_INSN"
"@
! jsr $26,($27),0\;trapb\;ldgp $29,4($26)
! bsr $26,%1..ng\;trapb
! jsr $26,%1\;trapb\;ldgp $29,4($26)"
! [(set_attr "type" "jsr,jsr,ibr")])
(define_insn ""
! [(set (match_operand 0 "register_operand" "=rf,rf,rf")
! (call (mem:DI (match_operand:DI 1 "call_operand" "r,R,i"))
(match_operand 2 "" "")))
(clobber (reg:DI 27))
(clobber (reg:DI 26))]
"! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS"
"@
! jsr $26,($27),0\;ldgp $29,0($26)
! bsr $26,%1..ng
! jsr $26,%1\;ldgp $29,0($26)"
! [(set_attr "type" "jsr,jsr,ibr")])
(define_insn ""
[(set (match_operand 0 "register_operand" "=rf,rf")
--- 3141,3168 ----
[(set_attr "type" "jsr")])
(define_insn ""
! [(set (match_operand 0 "register_operand" "=rf,rf")
! (call (mem:DI (match_operand:DI 1 "call_operand" "c,R"))
(match_operand 2 "" "")))
(clobber (reg:DI 27))
(clobber (reg:DI 26))]
"! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS && alpha_tp == ALPHA_TP_INSN"
"@
! jsr $26,($27),%2\;trapb\;ldgp $29,4($26)
! bsr $26,%1..ng\;trapb"
! [(set_attr "type" "jsr,ibr")])
(define_insn ""
! [(set (match_operand 0 "register_operand" "=rf,rf")
! (call (mem:DI (match_operand:DI 1 "call_operand" "c,R"))
(match_operand 2 "" "")))
(clobber (reg:DI 27))
(clobber (reg:DI 26))]
"! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS"
"@
! jsr $26,($27),%2\;ldgp $29,0($26)
! bsr $26,%1..ng"
! [(set_attr "type" "jsr,ibr")])
(define_insn ""
[(set (match_operand 0 "register_operand" "=rf,rf")
More information about the Gcc
mailing list