llvm-6502/lib/Target/X86/X86RegisterInfo.td
Alkis Evlogimenos 9c22aeb0b2 Improve allocation order:
1) For 8-bit registers try to use first the ones that are parts of the
   same register (AL then AH). This way we only alias 2 16/32-bit
   registers after allocating 4 8-bit variables.

2) Move EBX as the last register to allocate. This will cause less
   spills to happen since we will have 8-bit registers available up to
   register excaustion (assuming we use the allocation order). It
   would be nice if we could push all of the 8-bit aliased registers
   towards the end but we much prefer to keep callee saved register to
   the end to avoid saving them on entry and exit of the function.

For example this gives a slight reduction of spills with linear scan
on 164.gzip.

Before:

11221 asm-printer           - Number of machine instrs printed
  975 spiller               - Number of loads added
  675 spiller               - Number of stores added
  398 spiller               - Number of register spills

After:

11182 asm-printer           - Number of machine instrs printed
  952 spiller               - Number of loads added
  652 spiller               - Number of stores added
  386 spiller               - Number of register spills


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@11996 91177308-0d34-0410-b5e6-96231b3b80d8
2004-02-29 09:17:01 +00:00

108 lines
4.3 KiB
C++

//===- X86RegisterInfo.td - Describe the X86 Register File ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file describes the X86 Register file, defining the registers themselves,
// aliases between the registers, and the register classes built out of the
// registers.
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Register definitions...
//
let Namespace = "X86" in {
// 32-bit registers
def EAX : Register; def ECX : Register;
def EDX : Register; def EBX : Register;
def ESP : Register; def EBP : Register;
def ESI : Register; def EDI : Register;
// 16-bit registers
def AX : Register; def CX : Register;
def DX : Register; def BX : Register;
def SP : Register; def BP : Register;
def SI : Register; def DI : Register;
// 8-bit registers
def AL : Register; def CL : Register;
def DL : Register; def BL : Register;
def AH : Register; def CH : Register;
def DH : Register; def BH : Register;
// Pseudo Floating Point registers
def FP0 : Register; def FP1 : Register;
def FP2 : Register; def FP3 : Register;
def FP4 : Register; def FP5 : Register;
def FP6 : Register;
// Floating point stack registers
def ST0 : NamedReg<"ST(0)">; def ST1 : NamedReg<"ST(1)">;
def ST2 : NamedReg<"ST(2)">; def ST3 : NamedReg<"ST(3)">;
def ST4 : NamedReg<"ST(4)">; def ST5 : NamedReg<"ST(5)">;
def ST6 : NamedReg<"ST(6)">; def ST7 : NamedReg<"ST(7)">;
// Flags, Segment registers, etc...
// This is a slimy hack to make it possible to say that flags are clobbered...
// Ideally we'd model instructions based on which particular flag(s) they
// could clobber.
//def EFLAGS : Register;
}
//===----------------------------------------------------------------------===//
// Register alias definitions... define which registers alias which others. We
// only specify which registers the small registers alias, because the register
// file generator is smart enough to figure out that AL aliases AX if we tell it
// that AX aliases AL (for example).
//
def : RegisterAliases<AL, [AX, EAX]>; def : RegisterAliases<BL, [BX, EBX]>;
def : RegisterAliases<CL, [CX, ECX]>; def : RegisterAliases<DL, [DX, EDX]>;
def : RegisterAliases<AH, [AX, EAX]>; def : RegisterAliases<BH, [BX, EBX]>;
def : RegisterAliases<CH, [CX, ECX]>; def : RegisterAliases<DH, [DX, EDX]>;
def : RegisterAliases<AX, [EAX]>; def : RegisterAliases<BX, [EBX]>;
def : RegisterAliases<CX, [ECX]>; def : RegisterAliases<DX, [EDX]>;
def : RegisterAliases<SI, [ESI]>; def : RegisterAliases<DI, [EDI]>;
def : RegisterAliases<SP, [ESP]>; def : RegisterAliases<BP, [EBP]>;
//===----------------------------------------------------------------------===//
// Register Class Definitions... now that we have all of the pieces, define the
// top-level register classes. The order specified in the register list is
// implicitly defined to be the register allocation order.
//
def R8 : RegisterClass<i8, 1, [AL, AH, CL, CH, DL, DH, BL, BH]>;
def R16 : RegisterClass<i16, 2, [AX, CX, DX, SI, DI, BX, BP, SP]> {
let Methods = [{
iterator allocation_order_end(MachineFunction &MF) const {
if (hasFP(MF)) // Does the function dedicate EBP to being a frame ptr?
return end()-2; // If so, don't allocate SP or BP
else
return end()-1; // If not, just don't allocate SP
}
}];
}
def R32 : RegisterClass<i32, 4, [EAX, ECX, EDX, ESI, EDI, EBX, EBP, ESP]> {
let Methods = [{
iterator allocation_order_end(MachineFunction &MF) const {
if (hasFP(MF)) // Does the function dedicate EBP to being a frame ptr?
return end()-2; // If so, don't allocate ESP or EBP
else
return end()-1; // If not, just don't allocate ESP
}
}];
}
def RFP : RegisterClass<f80, 4, [FP0, FP1, FP2, FP3, FP4, FP5, FP6]>;
// Registers which cannot be allocated... and are thus left unnamed.
def : RegisterClass<f80, 4, [ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7]>;
//def : RegisterClass<i16, 2, [EFLAGS]>;