mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-20 11:29:24 +00:00
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
108 lines
4.3 KiB
C++
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]>;
|
|
|