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