From lattner at cs.uiuc.edu Mon Dec 16 08:38:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 08:38:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212161437.IAA09545@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.28 -> 1.29 --- Log message: Rename createSimpleX86RegisterAllocator to createSimpleRegisterAllocator. Remvoe some dead code --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.28 llvm/lib/CodeGen/RegAllocSimple.cpp:1.29 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.28 Sun Dec 15 17:01:26 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Mon Dec 16 08:37:00 2002 @@ -1,4 +1,4 @@ -//===-- RegAllocSimple.cpp - A simple generic register allocator --- ------===// +//===-- RegAllocSimple.cpp - A simple generic register allocator ----------===// // // This file implements a simple register allocator. *Very* simple. // @@ -12,32 +12,6 @@ #include #include -#if 0 -/// PhysRegClassMap - Construct a mapping of physical register numbers to their -/// register classes. -/// -/// NOTE: This class will eventually be pulled out to somewhere shared. -/// -class PhysRegClassMap { - std::map PhysReg2RegClassMap; -public: - PhysRegClassMap(const MRegisterInfo *RI) { - for (MRegisterInfo::const_iterator I = RI->regclass_begin(), - E = RI->regclass_end(); I != E; ++I) - for (unsigned i=0; i < (*I)->getNumRegs(); ++i) - PhysReg2RegClassMap[(*I)->getRegister(i)] = *I; - } - - const TargetRegisterClass *operator[](unsigned Reg) { - assert(PhysReg2RegClassMap[Reg] && "Register is not a known physreg!"); - return PhysReg2RegClassMap[Reg]; - } - - const TargetRegisterClass *get(unsigned Reg) { return operator[](Reg); } -}; -#endif - - namespace { Statistic<> NumSpilled ("ra-simple", "Number of registers spilled"); Statistic<> NumReloaded("ra-simple", "Number of registers reloaded"); @@ -367,6 +341,6 @@ return true; } -Pass *createSimpleX86RegisterAllocator(TargetMachine &TM) { +Pass *createSimpleRegisterAllocator(TargetMachine &TM) { return new RegAllocSimple(TM); } From lattner at cs.uiuc.edu Mon Dec 16 08:39:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 08:39:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86.h X86TargetMachine.cpp Message-ID: <200212161438.IAA09561@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86.h updated: 1.7 -> 1.8 X86TargetMachine.cpp updated: 1.5 -> 1.6 --- Log message: Rename createSimpleX86RegisterAllocator to createSimpleRegisterAllocator --- Diffs of the changes: Index: llvm/lib/Target/X86/X86.h diff -u llvm/lib/Target/X86/X86.h:1.7 llvm/lib/Target/X86/X86.h:1.8 --- llvm/lib/Target/X86/X86.h:1.7 Mon Dec 2 23:42:53 2002 +++ llvm/lib/Target/X86/X86.h Mon Dec 16 08:38:13 2002 @@ -20,11 +20,11 @@ /// Pass *createSimpleX86InstructionSelector(TargetMachine &TM); -/// X86SimpleRegisterAllocation - This function converts the specified machine -/// code function from SSA form to use explicit registers by spilling every -/// register. Wow, great policy huh? +/// createSimpleRegisterAllocation - This function converts the specified +/// machine code function from SSA form to use explicit registers by spilling +/// every register. Wow, great policy huh? /// -Pass *createSimpleX86RegisterAllocator(TargetMachine &TM); +Pass *createSimpleRegisterAllocator(TargetMachine &TM); /// createX86CodePrinterPass - Print out the specified machine code function to /// the specified stream. This function should work regardless of whether or Index: llvm/lib/Target/X86/X86TargetMachine.cpp diff -u llvm/lib/Target/X86/X86TargetMachine.cpp:1.5 llvm/lib/Target/X86/X86TargetMachine.cpp:1.6 --- llvm/lib/Target/X86/X86TargetMachine.cpp:1.5 Fri Dec 13 07:16:14 2002 +++ llvm/lib/Target/X86/X86TargetMachine.cpp Mon Dec 16 08:38:13 2002 @@ -43,7 +43,7 @@ DEBUG(PM.add(createMachineFunctionPrinterPass())); // Perform register allocation to convert to a concrete x86 representation - PM.add(createSimpleX86RegisterAllocator(*this)); + PM.add(createSimpleRegisterAllocator(*this)); // Print the instruction selected machine code... // PM.add(createMachineFunctionPrinterPass()); From lattner at cs.uiuc.edu Mon Dec 16 09:56:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 09:56:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86RegisterInfo.def Message-ID: <200212161555.JAA10371@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86RegisterInfo.def updated: 1.6 -> 1.7 --- Log message: Add information about register file aliasing --- Diffs of the changes: Index: llvm/lib/Target/X86/X86RegisterInfo.def diff -u llvm/lib/Target/X86/X86RegisterInfo.def:1.6 llvm/lib/Target/X86/X86RegisterInfo.def:1.7 --- llvm/lib/Target/X86/X86RegisterInfo.def:1.6 Tue Nov 19 18:47:40 2002 +++ llvm/lib/Target/X86/X86RegisterInfo.def Mon Dec 16 09:54:59 2002 @@ -9,19 +9,22 @@ // NOTE: No include guards desired #ifndef R -#errror "Must define R macro before including X86/X86RegisterInfo.def!" +#define R(ENUM, NAME, FLAGS, TSFLAGS, A1, A2, A3) #endif #ifndef R8 -#define R8(ENUM, NAME, FLAGS, TSFLAGS) R(ENUM, NAME, FLAGS, TSFLAGS) +#define R8(ENUM, NAME, FLAGS, TSFLAGS, A1, A2, A3) \ + R(ENUM, NAME, FLAGS, TSFLAGS, A1, A2, A3) #endif #ifndef R16 -#define R16(ENUM, NAME, FLAGS, TSFLAGS) R(ENUM, NAME, FLAGS, TSFLAGS) +#define R16(ENUM, NAME, FLAGS, TSFLAGS, A1, A2, A3) \ + R(ENUM, NAME, FLAGS, TSFLAGS, A1, A2, A3) #endif #ifndef R32 -#define R32(ENUM, NAME, FLAGS, TSFLAGS) R(ENUM, NAME, FLAGS, TSFLAGS) +#define R32(ENUM, NAME, FLAGS, TSFLAGS, A1, A2, A3) \ + R(ENUM, NAME, FLAGS, TSFLAGS, A1, A2, A3) #endif // Arguments passed into the R macro @@ -42,44 +45,45 @@ // The X86 backend uses this value as an operand register only in memory // references where it means that there is no base or index register. // -R(NoReg, "none", 0, 0) +R(NoReg,"none", 0, 0, 0, 0, 0) // 32 bit registers, ordered as the processor does... -R32(EAX, "EAX", MRF::INT32, 0) -R32(ECX, "ECX", MRF::INT32, 0) -R32(EDX, "EDX", MRF::INT32, 0) -R32(EBX, "EBX", MRF::INT32, 0) -R32(ESP, "ESP", MRF::INT32, 0) -R32(EBP, "EBP", MRF::INT32, 0) -R32(ESI, "ESI", MRF::INT32, 0) -R32(EDI, "EDI", MRF::INT32, 0) +R32(EAX, "EAX", MRF::INT32, 0, X86::AX, X86::AH, X86::AL) +R32(ECX, "ECX", MRF::INT32, 0, X86::CX, X86::CH, X86::CL) +R32(EDX, "EDX", MRF::INT32, 0, X86::DX, X86::DH, X86::DL) +R32(EBX, "EBX", MRF::INT32, 0, X86::BX, X86::BH, X86::BL) +R32(ESP, "ESP", MRF::INT32, 0, X86::SP, 0, 0) +R32(EBP, "EBP", MRF::INT32, 0, X86::BP, 0, 0) +R32(ESI, "ESI", MRF::INT32, 0, X86::SI, 0, 0) +R32(EDI, "EDI", MRF::INT32, 0, X86::DI, 0, 0) // 16 bit registers, aliased with the corresponding 32 bit registers above -R16(AX, "AX", MRF::INT16, 0) -R16(CX, "CX", MRF::INT16, 0) -R16(DX, "DX", MRF::INT16, 0) -R16(BX, "BX", MRF::INT16, 0) -R16(SP, "SP", MRF::INT16, 0) -R16(BP, "BP", MRF::INT16, 0) -R16(SI, "SI", MRF::INT16, 0) -R16(DI, "DI", MRF::INT16, 0) +R16( AX, "AX" , MRF::INT16, 0, X86::EAX, X86::AH, X86::AL) +R16( CX, "CX" , MRF::INT16, 0, X86::ECX, X86::CH, X86::CL) +R16( DX, "DX" , MRF::INT16, 0, X86::EDX, X86::DH, X86::DL) +R16( BX, "BX" , MRF::INT16, 0, X86::EBX, X86::BH, X86::BL) +R16( SP, "SP" , MRF::INT16, 0, X86::ESP, 0, 0) +R16( BP, "BP" , MRF::INT16, 0, X86::EBP, 0, 0) +R16( SI, "SI" , MRF::INT16, 0, X86::ESI, 0, 0) +R16( DI, "DI" , MRF::INT16, 0, X86::EDI, 0, 0) // 8 bit registers aliased with registers above as well -R8(AL, "AL", MRF::INT8, 0) -R8(CL, "CL", MRF::INT8, 0) -R8(DL, "DL", MRF::INT8, 0) -R8(BL, "BL", MRF::INT8, 0) -R8(AH, "AH", MRF::INT8, 0) -R8(CH, "CH", MRF::INT8, 0) -R8(DH, "DH", MRF::INT8, 0) -R8(BH, "BH", MRF::INT8, 0) +R8 ( AL, "AL" , MRF::INT8 , 0, X86::EAX, X86::AX, 0) +R8 ( CL, "CL" , MRF::INT8 , 0, X86::ECX, X86::CX, 0) +R8 ( DL, "DL" , MRF::INT8 , 0, X86::EDX, X86::DX, 0) +R8 ( BL, "BL" , MRF::INT8 , 0, X86::EBX, X86::BX, 0) +R8 ( AH, "AH" , MRF::INT8 , 0, X86::EAX, X86::AX, 0) +R8 ( CH, "CH" , MRF::INT8 , 0, X86::ECX, X86::CX, 0) +R8 ( DH, "DH" , MRF::INT8 , 0, X86::EDX, X86::DX, 0) +R8 ( BH, "BH" , MRF::INT8 , 0, X86::EBX, X86::BX, 0) // 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. -R(EFLAGS, "EFLAGS", MRF::INT16, 0) +R(EFLAGS, "EFLAGS", MRF::INT16, 0, 0, 0, 0) + // We are now done with the R* macros #undef R From lattner at cs.uiuc.edu Mon Dec 16 09:56:02 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 09:56:02 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86RegisterClasses.cpp X86RegisterInfo.cpp Message-ID: <200212161555.JAA10385@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86RegisterClasses.cpp updated: 1.5 -> 1.6 X86RegisterInfo.cpp updated: 1.15 -> 1.16 --- Log message: Add info about register file aliasing --- Diffs of the changes: Index: llvm/lib/Target/X86/X86RegisterClasses.cpp diff -u llvm/lib/Target/X86/X86RegisterClasses.cpp:1.5 llvm/lib/Target/X86/X86RegisterClasses.cpp:1.6 --- llvm/lib/Target/X86/X86RegisterClasses.cpp:1.5 Sun Dec 15 13:29:34 2002 +++ llvm/lib/Target/X86/X86RegisterClasses.cpp Mon Dec 16 09:55:25 2002 @@ -7,16 +7,11 @@ #include "llvm/Target/MRegisterInfo.h" #include "X86RegisterInfo.h" #include "llvm/Type.h" - -enum { -#define R(ENUM, NAME, FLAGS, TSFLAGS) ENUM, -#include "X86RegisterInfo.def" -}; +#include "X86.h" namespace { const unsigned ByteRegClassRegs[] = { -#define R(ENUM, NAME, FLAGS, TSFLAGS) -#define R8(ENUM, NAME, FLAGS, TSFLAGS) ENUM, +#define R8(ENUM, NAME, FLAGS, TSFLAGS, A1, A2, A3) X86::ENUM, #include "X86RegisterInfo.def" }; @@ -27,8 +22,7 @@ // // const unsigned ShortRegClassRegs[] = { -#define R(ENUM, NAME, FLAGS, TSFLAGS) -#define R16(ENUM, NAME, FLAGS, TSFLAGS) ENUM, +#define R16(ENUM, NAME, FLAGS, TSFLAGS, A1, A2, A3) X86::ENUM, #include "X86RegisterInfo.def" }; @@ -40,8 +34,7 @@ // const unsigned IntRegClassRegs[] = { -#define R(ENUM, NAME, FLAGS, TSFLAGS) -#define R32(ENUM, NAME, FLAGS, TSFLAGS) ENUM, +#define R32(ENUM, NAME, FLAGS, TSFLAGS, A1, A2, A3) X86::ENUM, #include "X86RegisterInfo.def" }; Index: llvm/lib/Target/X86/X86RegisterInfo.cpp diff -u llvm/lib/Target/X86/X86RegisterInfo.cpp:1.15 llvm/lib/Target/X86/X86RegisterInfo.cpp:1.16 --- llvm/lib/Target/X86/X86RegisterInfo.cpp:1.15 Sun Dec 15 16:38:47 2002 +++ llvm/lib/Target/X86/X86RegisterInfo.cpp Mon Dec 16 09:55:25 2002 @@ -16,7 +16,7 @@ // descriptors // static const MRegisterDesc X86Regs[] = { -#define R(ENUM, NAME, FLAGS, TSFLAGS) { NAME, FLAGS, TSFLAGS }, +#define R(ENUM, NAME, FLAGS, TSFLAGS, A1, A2, A3) { NAME, FLAGS, TSFLAGS }, #include "X86RegisterInfo.def" }; From lattner at cs.uiuc.edu Mon Dec 16 09:56:02 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 09:56:02 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86InstrInfo.def Message-ID: <200212161555.JAA10394@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86InstrInfo.def updated: 1.41 -> 1.42 --- Log message: Add call clobber info --- Diffs of the changes: Index: llvm/lib/Target/X86/X86InstrInfo.def diff -u llvm/lib/Target/X86/X86InstrInfo.def:1.41 llvm/lib/Target/X86/X86InstrInfo.def:1.42 --- llvm/lib/Target/X86/X86InstrInfo.def:1.41 Fri Dec 13 08:13:27 2002 +++ llvm/lib/Target/X86/X86InstrInfo.def Mon Dec 16 09:54:42 2002 @@ -35,7 +35,7 @@ IMPREGSLIST(O_EBP, X86::EBP, 0) IMPREGSLIST(T_AXDX , X86::AX , X86::DX , 0) IMPREGSLIST(T_EAXEDX, X86::EAX, X86::EDX, 0) - +IMPREGSLIST(C_CLOBBER, X86::EAX, X86::ECX, X86::EDX, 0) // Callee clobber regs #undef IMPREGSLIST @@ -67,9 +67,9 @@ NoIR) // je foo I(CALLpcrel32 , "call", 0xE8, M_BRANCH_FLAG, X86II::Void, NoIR, NoIR) // call pc+42 I(CALLr32 , "call", 0xFF, M_BRANCH_FLAG, X86II::Void | X86II::MRMS2r | X86II::Arg32, - NoIR, NoIR) // call [r32] + NoIR, C_CLOBBER) // call [r32] I(CALLm32 , "call", 0xFF, M_BRANCH_FLAG, X86II::Void | X86II::MRMS2m | X86II::Arg32, - NoIR, NoIR) // call [m32] + NoIR, C_CLOBBER) // call [m32] // Misc instructions I(LEAVE , "leave", 0xC9, 0, X86II::RawFrm, O_EBP, O_EBP) // leave From lattner at cs.uiuc.edu Mon Dec 16 09:57:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 09:57:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86.h Message-ID: <200212161556.JAA10404@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86.h updated: 1.8 -> 1.9 --- Log message: Add info about register aliases, add prototype for createLocalRegisterAllocator --- Diffs of the changes: Index: llvm/lib/Target/X86/X86.h diff -u llvm/lib/Target/X86/X86.h:1.8 llvm/lib/Target/X86/X86.h:1.9 --- llvm/lib/Target/X86/X86.h:1.8 Mon Dec 16 08:38:13 2002 +++ llvm/lib/Target/X86/X86.h Mon Dec 16 09:55:51 2002 @@ -25,6 +25,7 @@ /// every register. Wow, great policy huh? /// Pass *createSimpleRegisterAllocator(TargetMachine &TM); +Pass *createLocalRegisterAllocator(TargetMachine &TM); /// createX86CodePrinterPass - Print out the specified machine code function to /// the specified stream. This function should work regardless of whether or @@ -46,7 +47,7 @@ // mapping from register name to register number. // enum Register { -#define R(ENUM, NAME, FLAGS, TSFLAGS) ENUM, +#define R(ENUM, NAME, FLAGS, TSFLAGS, A1, A2, A3) ENUM, #include "X86RegisterInfo.def" }; From lattner at cs.uiuc.edu Mon Dec 16 09:58:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 09:58:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86RegisterInfo.def Message-ID: <200212161557.JAA10420@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86RegisterInfo.def updated: 1.7 -> 1.8 --- Log message: Add comments --- Diffs of the changes: Index: llvm/lib/Target/X86/X86RegisterInfo.def diff -u llvm/lib/Target/X86/X86RegisterInfo.def:1.7 llvm/lib/Target/X86/X86RegisterInfo.def:1.8 --- llvm/lib/Target/X86/X86RegisterInfo.def:1.7 Mon Dec 16 09:54:59 2002 +++ llvm/lib/Target/X86/X86RegisterInfo.def Mon Dec 16 09:57:44 2002 @@ -27,13 +27,15 @@ R(ENUM, NAME, FLAGS, TSFLAGS, A1, A2, A3) #endif -// Arguments passed into the R macro +// Arguments passed into the R macros // #1: Enum Name - This ends up being a symbol in the X86 namespace // #2: Register name - The name of the register as used by the gnu assembler // #3: Register Flags - A bitfield of flags or'd together from the // MRegisterInfo.h file. // #4: Target Specific Flags - Another bitfield containing X86 specific flags // as neccesary. +// +// #5,6,7: Registers aliased to this register, or 0 if none. // The first register must always be a 'noop' register for all backends. This From lattner at cs.uiuc.edu Mon Dec 16 10:16:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 10:16:00 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86RegisterClasses.cpp X86RegisterInfo.cpp X86RegisterInfo.def X86.h Message-ID: <200212161615.KAA10630@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86RegisterClasses.cpp updated: 1.6 -> 1.7 X86RegisterInfo.cpp updated: 1.16 -> 1.17 X86RegisterInfo.def updated: 1.8 -> 1.9 X86.h updated: 1.9 -> 1.10 --- Log message: Try #2 to get alias set stuff to work --- Diffs of the changes: Index: llvm/lib/Target/X86/X86RegisterClasses.cpp diff -u llvm/lib/Target/X86/X86RegisterClasses.cpp:1.6 llvm/lib/Target/X86/X86RegisterClasses.cpp:1.7 --- llvm/lib/Target/X86/X86RegisterClasses.cpp:1.6 Mon Dec 16 09:55:25 2002 +++ llvm/lib/Target/X86/X86RegisterClasses.cpp Mon Dec 16 10:14:51 2002 @@ -11,7 +11,7 @@ namespace { const unsigned ByteRegClassRegs[] = { -#define R8(ENUM, NAME, FLAGS, TSFLAGS, A1, A2, A3) X86::ENUM, +#define R8(ENUM, NAME, FLAGS, TSFLAGS, ALIAS_SET) X86::ENUM, #include "X86RegisterInfo.def" }; @@ -22,7 +22,7 @@ // // const unsigned ShortRegClassRegs[] = { -#define R16(ENUM, NAME, FLAGS, TSFLAGS, A1, A2, A3) X86::ENUM, +#define R16(ENUM, NAME, FLAGS, TSFLAGS, ALIAS_SET) X86::ENUM, #include "X86RegisterInfo.def" }; @@ -34,7 +34,7 @@ // const unsigned IntRegClassRegs[] = { -#define R32(ENUM, NAME, FLAGS, TSFLAGS, A1, A2, A3) X86::ENUM, +#define R32(ENUM, NAME, FLAGS, TSFLAGS, ALIAS_SET) X86::ENUM, #include "X86RegisterInfo.def" }; Index: llvm/lib/Target/X86/X86RegisterInfo.cpp diff -u llvm/lib/Target/X86/X86RegisterInfo.cpp:1.16 llvm/lib/Target/X86/X86RegisterInfo.cpp:1.17 --- llvm/lib/Target/X86/X86RegisterInfo.cpp:1.16 Mon Dec 16 09:55:25 2002 +++ llvm/lib/Target/X86/X86RegisterInfo.cpp Mon Dec 16 10:14:51 2002 @@ -16,7 +16,7 @@ // descriptors // static const MRegisterDesc X86Regs[] = { -#define R(ENUM, NAME, FLAGS, TSFLAGS, A1, A2, A3) { NAME, FLAGS, TSFLAGS }, +#define R(ENUM, NAME, FLAGS, TSFLAGS, ALIAS_SET) { NAME, FLAGS, TSFLAGS }, #include "X86RegisterInfo.def" }; Index: llvm/lib/Target/X86/X86RegisterInfo.def diff -u llvm/lib/Target/X86/X86RegisterInfo.def:1.8 llvm/lib/Target/X86/X86RegisterInfo.def:1.9 --- llvm/lib/Target/X86/X86RegisterInfo.def:1.8 Mon Dec 16 09:57:44 2002 +++ llvm/lib/Target/X86/X86RegisterInfo.def Mon Dec 16 10:14:51 2002 @@ -9,22 +9,22 @@ // NOTE: No include guards desired #ifndef R -#define R(ENUM, NAME, FLAGS, TSFLAGS, A1, A2, A3) +#define R(ENUM, NAME, FLAGS, TSFLAGS, ALIAS_SET) #endif #ifndef R8 -#define R8(ENUM, NAME, FLAGS, TSFLAGS, A1, A2, A3) \ - R(ENUM, NAME, FLAGS, TSFLAGS, A1, A2, A3) +#define R8(ENUM, NAME, FLAGS, TSFLAGS, ALIAS_SET) \ + R(ENUM, NAME, FLAGS, TSFLAGS, ALIAS_SET) #endif #ifndef R16 -#define R16(ENUM, NAME, FLAGS, TSFLAGS, A1, A2, A3) \ - R(ENUM, NAME, FLAGS, TSFLAGS, A1, A2, A3) +#define R16(ENUM, NAME, FLAGS, TSFLAGS, ALIAS_SET) \ + R(ENUM, NAME, FLAGS, TSFLAGS, ALIAS_SET) #endif #ifndef R32 -#define R32(ENUM, NAME, FLAGS, TSFLAGS, A1, A2, A3) \ - R(ENUM, NAME, FLAGS, TSFLAGS, A1, A2, A3) +#define R32(ENUM, NAME, FLAGS, TSFLAGS, ALIAS_SET) \ + R(ENUM, NAME, FLAGS, TSFLAGS, ALIAS_SET) #endif // Arguments passed into the R macros @@ -34,8 +34,7 @@ // MRegisterInfo.h file. // #4: Target Specific Flags - Another bitfield containing X86 specific flags // as neccesary. -// -// #5,6,7: Registers aliased to this register, or 0 if none. +// #5: Alias set for registers aliased to this register (sets defined below). // The first register must always be a 'noop' register for all backends. This @@ -47,45 +46,79 @@ // The X86 backend uses this value as an operand register only in memory // references where it means that there is no base or index register. // -R(NoReg,"none", 0, 0, 0, 0, 0) +R(NoReg,"none", 0, 0, 0/*noalias*/) // 32 bit registers, ordered as the processor does... -R32(EAX, "EAX", MRF::INT32, 0, X86::AX, X86::AH, X86::AL) -R32(ECX, "ECX", MRF::INT32, 0, X86::CX, X86::CH, X86::CL) -R32(EDX, "EDX", MRF::INT32, 0, X86::DX, X86::DH, X86::DL) -R32(EBX, "EBX", MRF::INT32, 0, X86::BX, X86::BH, X86::BL) -R32(ESP, "ESP", MRF::INT32, 0, X86::SP, 0, 0) -R32(EBP, "EBP", MRF::INT32, 0, X86::BP, 0, 0) -R32(ESI, "ESI", MRF::INT32, 0, X86::SI, 0, 0) -R32(EDI, "EDI", MRF::INT32, 0, X86::DI, 0, 0) +R32(EAX, "EAX", MRF::INT32, 0, A_EAX) +R32(ECX, "ECX", MRF::INT32, 0, A_ECX) +R32(EDX, "EDX", MRF::INT32, 0, A_EDX) +R32(EBX, "EBX", MRF::INT32, 0, A_EBX) +R32(ESP, "ESP", MRF::INT32, 0, A_ESP) +R32(EBP, "EBP", MRF::INT32, 0, A_EBP) +R32(ESI, "ESI", MRF::INT32, 0, A_ESI) +R32(EDI, "EDI", MRF::INT32, 0, A_EDI) // 16 bit registers, aliased with the corresponding 32 bit registers above -R16( AX, "AX" , MRF::INT16, 0, X86::EAX, X86::AH, X86::AL) -R16( CX, "CX" , MRF::INT16, 0, X86::ECX, X86::CH, X86::CL) -R16( DX, "DX" , MRF::INT16, 0, X86::EDX, X86::DH, X86::DL) -R16( BX, "BX" , MRF::INT16, 0, X86::EBX, X86::BH, X86::BL) -R16( SP, "SP" , MRF::INT16, 0, X86::ESP, 0, 0) -R16( BP, "BP" , MRF::INT16, 0, X86::EBP, 0, 0) -R16( SI, "SI" , MRF::INT16, 0, X86::ESI, 0, 0) -R16( DI, "DI" , MRF::INT16, 0, X86::EDI, 0, 0) +R16( AX, "AX" , MRF::INT16, 0, A_AX) +R16( CX, "CX" , MRF::INT16, 0, A_CX) +R16( DX, "DX" , MRF::INT16, 0, A_DX) +R16( BX, "BX" , MRF::INT16, 0, A_BX) +R16( SP, "SP" , MRF::INT16, 0, A_SP) +R16( BP, "BP" , MRF::INT16, 0, A_BP) +R16( SI, "SI" , MRF::INT16, 0, A_SI) +R16( DI, "DI" , MRF::INT16, 0, A_DI) // 8 bit registers aliased with registers above as well -R8 ( AL, "AL" , MRF::INT8 , 0, X86::EAX, X86::AX, 0) -R8 ( CL, "CL" , MRF::INT8 , 0, X86::ECX, X86::CX, 0) -R8 ( DL, "DL" , MRF::INT8 , 0, X86::EDX, X86::DX, 0) -R8 ( BL, "BL" , MRF::INT8 , 0, X86::EBX, X86::BX, 0) -R8 ( AH, "AH" , MRF::INT8 , 0, X86::EAX, X86::AX, 0) -R8 ( CH, "CH" , MRF::INT8 , 0, X86::ECX, X86::CX, 0) -R8 ( DH, "DH" , MRF::INT8 , 0, X86::EDX, X86::DX, 0) -R8 ( BH, "BH" , MRF::INT8 , 0, X86::EBX, X86::BX, 0) + R8 ( AL, "AL" , MRF::INT8 , 0, A_AL) + R8 ( CL, "CL" , MRF::INT8 , 0, A_CL) + R8 ( DL, "DL" , MRF::INT8 , 0, A_DL) + R8 ( BL, "BL" , MRF::INT8 , 0, A_BL) + R8 ( AH, "AH" , MRF::INT8 , 0, A_AH) + R8 ( CH, "CH" , MRF::INT8 , 0, A_CH) + R8 ( DH, "DH" , MRF::INT8 , 0, A_DH) + R8 ( BH, "BH" , MRF::INT8 , 0, A_BH) // 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. -R(EFLAGS, "EFLAGS", MRF::INT16, 0, 0, 0, 0) +R(EFLAGS, "EFLAGS", MRF::INT16, 0, 0 /*noalias*/) + + +//===----------------------------------------------------------------------===// +// Register alias set handling... +// + +// Macro to handle definitions of alias sets that registers use... +#ifndef ALIASLIST +#define ALIASLIST(NAME, ...) +#endif +ALIASLIST(A_EAX , X86::AX, X86::AH, X86::AL, 0) +ALIASLIST(A_ECX , X86::CX, X86::CH, X86::CL, 0) +ALIASLIST(A_EDX , X86::DX, X86::DH, X86::DL, 0) +ALIASLIST(A_EBX , X86::BX, X86::BH, X86::BL, 0) +ALIASLIST(A_ESP , X86::SP, 0) +ALIASLIST(A_EBP , X86::BP, 0) +ALIASLIST(A_ESI , X86::SI, 0) +ALIASLIST(A_EDI , X86::DI, 0) +ALIASLIST(A_AX , X86::EAX, X86::AH, X86::AL, 0) +ALIASLIST(A_CX , X86::ECX, X86::CH, X86::CL, 0) +ALIASLIST(A_DX , X86::EDX, X86::DH, X86::DL, 0) +ALIASLIST(A_BX , X86::EBX, X86::BH, X86::BL, 0) +ALIASLIST(A_SP , X86::ESP, 0) +ALIASLIST(A_BP , X86::EBP, 0) +ALIASLIST(A_SI , X86::ESI, 0) +ALIASLIST(A_DI , X86::EDI, 0) +ALIASLIST(A_AL , X86::EAX, X86::AX, 0) +ALIASLIST(A_CL , X86::ECX, X86::CX, 0) +ALIASLIST(A_DL , X86::EDX, X86::DX, 0) +ALIASLIST(A_BL , X86::EBX, X86::BX, 0) +ALIASLIST(A_AH , X86::EAX, X86::AX, 0) +ALIASLIST(A_CH , X86::ECX, X86::CX, 0) +ALIASLIST(A_DH , X86::EDX, X86::DX, 0) +ALIASLIST(A_BH , X86::EBX, X86::BX, 0) // We are now done with the R* macros #undef R Index: llvm/lib/Target/X86/X86.h diff -u llvm/lib/Target/X86/X86.h:1.9 llvm/lib/Target/X86/X86.h:1.10 --- llvm/lib/Target/X86/X86.h:1.9 Mon Dec 16 09:55:51 2002 +++ llvm/lib/Target/X86/X86.h Mon Dec 16 10:14:51 2002 @@ -47,7 +47,7 @@ // mapping from register name to register number. // enum Register { -#define R(ENUM, NAME, FLAGS, TSFLAGS, A1, A2, A3) ENUM, +#define R(ENUM, NAME, FLAGS, TSFLAGS, ALIAS_SET) ENUM, #include "X86RegisterInfo.def" }; From lattner at cs.uiuc.edu Mon Dec 16 10:16:02 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 10:16:02 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocLocal.cpp Message-ID: <200212161615.KAA10642@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocLocal.cpp added (r1.1) --- Log message: Initial checkin of "local" register allocator. Bugs are still present. --- Diffs of the changes: From lattner at cs.uiuc.edu Mon Dec 16 10:17:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 10:17:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86TargetMachine.cpp Message-ID: <200212161616.KAA10651@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86TargetMachine.cpp updated: 1.6 -> 1.7 --- Log message: Add mechanism to select register allocator to use --- Diffs of the changes: Index: llvm/lib/Target/X86/X86TargetMachine.cpp diff -u llvm/lib/Target/X86/X86TargetMachine.cpp:1.6 llvm/lib/Target/X86/X86TargetMachine.cpp:1.7 --- llvm/lib/Target/X86/X86TargetMachine.cpp:1.6 Mon Dec 16 08:38:13 2002 +++ llvm/lib/Target/X86/X86TargetMachine.cpp Mon Dec 16 10:15:51 2002 @@ -8,11 +8,17 @@ #include "llvm/Transforms/Scalar.h" #include "llvm/Target/TargetMachineImpls.h" #include "llvm/CodeGen/MachineFunction.h" -#include "Support/Statistic.h" #include "llvm/PassManager.h" #include "X86.h" +#include "Support/CommandLine.h" +#include "Support/Statistic.h" #include +namespace { + cl::opt UseLocalRA("local-ra", + cl::desc("Use Local RegAlloc instead of Simple RA")); +} + // allocateX86TargetMachine - Allocate and return a subclass of TargetMachine // that implements the X86 backend. // @@ -43,7 +49,10 @@ DEBUG(PM.add(createMachineFunctionPrinterPass())); // Perform register allocation to convert to a concrete x86 representation - PM.add(createSimpleRegisterAllocator(*this)); + if (UseLocalRA) + PM.add(createLocalRegisterAllocator(*this)); + else + PM.add(createSimpleRegisterAllocator(*this)); // Print the instruction selected machine code... // PM.add(createMachineFunctionPrinterPass()); From lattner at cs.uiuc.edu Mon Dec 16 10:40:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 10:40:01 2002 Subject: [llvm-commits] CVS: llvm/include/llvm/Target/MRegisterInfo.h Message-ID: <200212161639.KAA11033@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Target: MRegisterInfo.h updated: 1.11 -> 1.12 --- Log message: Add support for register alias set description --- Diffs of the changes: Index: llvm/include/llvm/Target/MRegisterInfo.h diff -u llvm/include/llvm/Target/MRegisterInfo.h:1.11 llvm/include/llvm/Target/MRegisterInfo.h:1.12 --- llvm/include/llvm/Target/MRegisterInfo.h:1.11 Sun Dec 15 14:06:25 2002 +++ llvm/include/llvm/Target/MRegisterInfo.h Mon Dec 16 10:39:14 2002 @@ -16,12 +16,16 @@ class MachineFunction; /// MRegisterDesc - This record contains all of the information known about a -/// particular register. +/// particular register. The AliasSet field (if not null) contains a pointer to +/// a Zero terminated array of registers that this register aliases. This is +/// needed for architectures like X86 which have AL alias AX alias EAX. +/// Registers that this does not apply to simply should set this to null. /// struct MRegisterDesc { - const char *Name; // Assembly language name for the register - unsigned Flags; // Flags identifying register properties (defined below) - unsigned TSFlags; // Target Specific Flags + const char *Name; // Assembly language name for the register + const unsigned *AliasSet; // Register Alias Set, described above + unsigned Flags; // Flags identifying register properties (below) + unsigned TSFlags; // Target Specific Flags }; /// MRF namespace - This namespace contains flags that pertain to machine @@ -88,7 +92,7 @@ /// produce a value. Some frontends may use this as an operand register to /// mean special things, for example, the Sparc backend uses R0 to mean %g0 /// which always PRODUCES the value 0. The X86 backend does not use this - /// value as an operand register. + /// value as an operand register, except for memory references. /// NoRegister = 0, @@ -111,6 +115,13 @@ /// const MRegisterDesc &get(unsigned RegNo) const { return operator[](RegNo); } + /// getAliasSet - Return the set of registers aliased by the specified + /// register, or a null list of there are none. The list returned is zero + /// terminated. + /// + const unsigned *getAliasSet(unsigned RegNo) const { + return get(RegNo).AliasSet; + } virtual MachineBasicBlock::iterator storeReg2RegOffset(MachineBasicBlock &MBB, From lattner at cs.uiuc.edu Mon Dec 16 11:43:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 11:43:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212161742.LAA12525@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.29 -> 1.30 --- Log message: Keep the stack frame aligned. --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.29 llvm/lib/CodeGen/RegAllocSimple.cpp:1.30 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.29 Mon Dec 16 08:37:00 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Mon Dec 16 11:42:40 2002 @@ -324,6 +324,10 @@ MBB != MBBe; ++MBB) AllocateBasicBlock(*MBB); + // Round stack allocation up to a nice alignment to keep the stack aligned + // FIXME: This is X86 specific! Move to frame manager + NumBytesAllocated = (NumBytesAllocated + 3) & ~3; + // Add prologue to the function... RegInfo->emitPrologue(Fn, NumBytesAllocated); From lattner at cs.uiuc.edu Mon Dec 16 11:45:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 11:45:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocLocal.cpp Message-ID: <200212161744.LAA12542@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocLocal.cpp updated: 1.1 -> 1.2 --- Log message: * Fix a gross X86 hack that was intended to avoid allocating SP and BP * Implement register alias set support --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocLocal.cpp diff -u llvm/lib/CodeGen/RegAllocLocal.cpp:1.1 llvm/lib/CodeGen/RegAllocLocal.cpp:1.2 --- llvm/lib/CodeGen/RegAllocLocal.cpp:1.1 Mon Dec 16 10:15:28 2002 +++ llvm/lib/CodeGen/RegAllocLocal.cpp Mon Dec 16 11:44:42 2002 @@ -111,6 +111,22 @@ /// in predecessor basic blocks. void EliminatePHINodes(MachineBasicBlock &MBB); + /// isAllocatableRegister - A register may be used by the program if it's + /// not the stack or frame pointer. + bool isAllocatableRegister(unsigned R) const { + unsigned FP = RegInfo->getFramePointer(), SP = RegInfo->getStackPointer(); + // Don't allocate the Frame or Stack pointers + if (R == FP || R == SP) + return false; + + // Check to see if this register aliases the stack or frame pointer... + if (const unsigned *AliasSet = RegInfo->getAliasSet(R)) { + for (unsigned i = 0; AliasSet[i]; ++i) + if (AliasSet[i] == FP || AliasSet[i] == SP) + return false; + } + return true; + } /// getStackSpaceFor - This returns the offset of the specified virtual /// register on the stack, allocating space if neccesary. @@ -130,6 +146,16 @@ void spillVirtReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I, unsigned VirtReg, unsigned PhysReg); + /// spillPhysReg - This method spills the specified physical register into + /// the virtual register slot associated with it. + // + void spillPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I, + unsigned PhysReg) { + assert(PhysRegsUsed.find(PhysReg) != PhysRegsUsed.end() && + "Physical register is not used: cannot spill it!"); + spillVirtReg(MBB, I, PhysRegsUsed[PhysReg], PhysReg); + } + void AssignVirtToPhysReg(unsigned VirtReg, unsigned PhysReg); @@ -219,9 +245,7 @@ It != E; ++It) { unsigned R = *It; if (PhysRegsUsed.find(R) == PhysRegsUsed.end()) // Is reg unused? - /// FIXME: Hack - if (R != RegInfo->getFramePointer() && R != RegInfo->getStackPointer() && - R != 13 && R != 14) { + if (isAllocatableRegister(R)) { // Found an unused register! PhysReg = R; break; @@ -231,6 +255,7 @@ // If we didn't find an unused register, scavange one now! if (PhysReg == 0) { unsigned i = 0; + assert(!PhysRegsUseOrder.empty() && "No allocated registers??"); while (PhysRegClasses[PhysRegsUseOrder[i]] != RegClass) { ++i; assert(i != PhysRegsUseOrder.size() && @@ -240,9 +265,17 @@ // At this point PhysRegsUseOrder[i] is the least recently used register of // compatible register class. Spill it to memory and reap its remains. PhysReg = PhysRegsUseOrder[i]; - spillVirtReg(MBB, I, PhysRegsUsed[PhysReg], PhysReg); + spillPhysReg(MBB, I, PhysReg); } + // If the selected register aliases any other registers, we must make sure to + // spill them as well... + if (const unsigned *AliasSet = RegInfo->getAliasSet(PhysReg)) + for (unsigned i = 0; AliasSet[i]; ++i) + if (PhysRegsUsed.count(AliasSet[i])) // Spill aliased register... + spillPhysReg(MBB, I, AliasSet[i]); + + // Now that we know which register we need to assign this to, do it now! AssignVirtToPhysReg(VirtReg, PhysReg); return PhysReg; @@ -417,7 +450,7 @@ // Spill the incoming value, because we are about to change the // register contents. - spillVirtReg(MBB, I, PhysRegsUsed[DestPhysReg], DestPhysReg); + spillPhysReg(MBB, I, DestPhysReg); AssignVirtToPhysReg(DestVirtReg, DestPhysReg); } else { DestPhysReg = getFreeReg(MBB, I, DestVirtReg); From lattner at cs.uiuc.edu Mon Dec 16 13:32:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 13:32:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86RegisterInfo.cpp X86RegisterInfo.def Message-ID: <200212161931.NAA13689@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86RegisterInfo.cpp updated: 1.17 -> 1.18 X86RegisterInfo.def updated: 1.9 -> 1.10 --- Log message: Finish implementation of alias list impl --- Diffs of the changes: Index: llvm/lib/Target/X86/X86RegisterInfo.cpp diff -u llvm/lib/Target/X86/X86RegisterInfo.cpp:1.17 llvm/lib/Target/X86/X86RegisterInfo.cpp:1.18 --- llvm/lib/Target/X86/X86RegisterInfo.cpp:1.17 Mon Dec 16 10:14:51 2002 +++ llvm/lib/Target/X86/X86RegisterInfo.cpp Mon Dec 16 13:31:48 2002 @@ -12,11 +12,18 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineFunction.h" +// Create static lists to contain register alias sets... +#define ALIASLIST(NAME, ...) \ + static const unsigned NAME[] = { __VA_ARGS__ }; +#include "X86RegisterInfo.def" + + // X86Regs - Turn the X86RegisterInfo.def file into a bunch of register // descriptors // static const MRegisterDesc X86Regs[] = { -#define R(ENUM, NAME, FLAGS, TSFLAGS, ALIAS_SET) { NAME, FLAGS, TSFLAGS }, +#define R(ENUM, NAME, FLAGS, TSFLAGS, ALIAS_SET) \ + { NAME, ALIAS_SET, FLAGS, TSFLAGS }, #include "X86RegisterInfo.def" }; Index: llvm/lib/Target/X86/X86RegisterInfo.def diff -u llvm/lib/Target/X86/X86RegisterInfo.def:1.9 llvm/lib/Target/X86/X86RegisterInfo.def:1.10 --- llvm/lib/Target/X86/X86RegisterInfo.def:1.9 Mon Dec 16 10:14:51 2002 +++ llvm/lib/Target/X86/X86RegisterInfo.def Mon Dec 16 13:31:48 2002 @@ -119,6 +119,7 @@ ALIASLIST(A_CH , X86::ECX, X86::CX, 0) ALIASLIST(A_DH , X86::EDX, X86::DX, 0) ALIASLIST(A_BH , X86::EBX, X86::BX, 0) +#undef ALIASLIST // We are now done with the R* macros #undef R From lattner at cs.uiuc.edu Mon Dec 16 13:34:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 13:34:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Message-ID: <200212161933.NAA13704@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.71 -> 1.72 --- Log message: Add some special cases to make common getelementptr cases easier to read/faster --- Diffs of the changes: Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.71 llvm/lib/Target/X86/InstSelectSimple.cpp:1.72 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.71 Sun Dec 15 22:23:29 2002 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Mon Dec 16 13:32:50 2002 @@ -124,10 +124,9 @@ void visitSimpleBinary(BinaryOperator &B, unsigned OpcodeClass); void visitAdd(BinaryOperator &B) { visitSimpleBinary(B, 0); } void visitSub(BinaryOperator &B) { visitSimpleBinary(B, 1); } - void doMultiply(unsigned destReg, const Type *resultType, - unsigned op0Reg, unsigned op1Reg, - MachineBasicBlock *MBB, - MachineBasicBlock::iterator &MBBI); + void doMultiply(MachineBasicBlock *MBB, MachineBasicBlock::iterator &MBBI, + unsigned destReg, const Type *resultType, + unsigned op0Reg, unsigned op1Reg); void visitMul(BinaryOperator &B); void visitDiv(BinaryOperator &B) { visitDivRem(B); } @@ -179,9 +178,9 @@ /// copyConstantToRegister - Output the instructions required to put the /// specified constant into the specified register. /// - void copyConstantToRegister(Constant *C, unsigned Reg, - MachineBasicBlock *MBB, - MachineBasicBlock::iterator &MBBI); + void copyConstantToRegister(MachineBasicBlock *MBB, + MachineBasicBlock::iterator &MBBI, + Constant *C, unsigned Reg); /// makeAnotherReg - This method returns the next register number /// we haven't yet used. @@ -213,7 +212,7 @@ // the register here... // if (Constant *C = dyn_cast(V)) { - copyConstantToRegister(C, Reg, MBB, IPt); + copyConstantToRegister(MBB, IPt, C, Reg); } else if (GlobalValue *GV = dyn_cast(V)) { // Move the address of the global into the register BMI(MBB, IPt, X86::MOVir32, 1, Reg).addReg(GV); @@ -287,9 +286,9 @@ /// copyConstantToRegister - Output the instructions required to put the /// specified constant into the specified register. /// -void ISel::copyConstantToRegister(Constant *C, unsigned R, - MachineBasicBlock *MBB, - MachineBasicBlock::iterator &IP) { +void ISel::copyConstantToRegister(MachineBasicBlock *MBB, + MachineBasicBlock::iterator &IP, + Constant *C, unsigned R) { if (ConstantExpr *CE = dyn_cast(C)) { if (CE->getOpcode() == Instruction::GetElementPtr) { emitGEPOperation(MBB, IP, CE->getOperand(0), @@ -669,11 +668,9 @@ /// doMultiply - Emit appropriate instructions to multiply together /// the registers op0Reg and op1Reg, and put the result in destReg. /// The type of the result should be given as resultType. -void -ISel::doMultiply(unsigned destReg, const Type *resultType, - unsigned op0Reg, unsigned op1Reg, - MachineBasicBlock *MBB, MachineBasicBlock::iterator &MBBI) -{ +void ISel::doMultiply(MachineBasicBlock *MBB, MachineBasicBlock::iterator &MBBI, + unsigned destReg, const Type *resultType, + unsigned op0Reg, unsigned op1Reg) { unsigned Class = getClass (resultType); // FIXME: @@ -704,7 +701,7 @@ unsigned Op0Reg = getReg(I.getOperand(0)); unsigned Op1Reg = getReg(I.getOperand(1)); MachineBasicBlock::iterator MBBI = BB->end(); - doMultiply(DestReg, I.getType(), Op0Reg, Op1Reg, BB, MBBI); + doMultiply(BB, MBBI, DestReg, I.getType(), Op0Reg, Op1Reg); } @@ -934,6 +931,19 @@ visitInstruction (CI); } +// ExactLog2 - This function solves for (Val == 1 << (N-1)) and returns N. It +// returns zero when the input is not exactly a power of two. +static unsigned ExactLog2(unsigned Val) { + if (Val == 0) return 0; + unsigned Count = 0; + while (Val != 1) { + if (Val & 1) return 0; + Val >>= 1; + ++Count; + } + return Count+1; +} + /// visitGetElementPtrInst - I don't know, most programs don't have /// getelementptr instructions, right? That means we can put off /// implementing this, right? Right. This method emits machine @@ -983,34 +993,56 @@ // The next type is the member of the structure selected by the // index. Ty = StTy->getElementTypes ()[idxValue]; - } else if (const SequentialType *SqTy = cast (Ty)) { + } else if (const SequentialType *SqTy = cast (Ty)) { // It's an array or pointer access: [ArraySize x ElementType]. - const Type *typeOfSequentialTypeIndex = SqTy->getIndexType (); + // idx is the index into the array. Unlike with structure // indices, we may not know its actual value at code-generation // time. - assert (idx->getType () == typeOfSequentialTypeIndex - && "Funny-looking array index in GEP"); - // We want to add basePtrReg to (idxReg * sizeof - // ElementType). First, we must find the size of the pointed-to - // type. (Not coincidentally, the next type is the type of the - // elements in the array.) - Ty = SqTy->getElementType (); - unsigned elementSize = TD.getTypeSize (Ty); - unsigned elementSizeReg = makeAnotherReg(typeOfSequentialTypeIndex); - copyConstantToRegister(ConstantSInt::get(typeOfSequentialTypeIndex, - elementSize), elementSizeReg, - MBB, IP); - - unsigned idxReg = getReg(idx, MBB, IP); - // Emit a MUL to multiply the register holding the index by - // elementSize, putting the result in memberOffsetReg. - unsigned memberOffsetReg = makeAnotherReg(Type::UIntTy); - doMultiply (memberOffsetReg, typeOfSequentialTypeIndex, - elementSizeReg, idxReg, MBB, IP); - // Emit an ADD to add memberOffsetReg to the basePtr. - BMI(MBB, IP, X86::ADDrr32, 2, - nextBasePtrReg).addReg (basePtrReg).addReg (memberOffsetReg); + assert(idx->getType() == Type::LongTy && "Bad GEP array index!"); + + // We want to add basePtrReg to (idxReg * sizeof ElementType). First, we + // must find the size of the pointed-to type (Not coincidentally, the next + // type is the type of the elements in the array). + Ty = SqTy->getElementType(); + unsigned elementSize = TD.getTypeSize(Ty); + + // If idxReg is a constant, we don't need to perform the multiply! + if (ConstantSInt *CSI = dyn_cast(idx)) { + if (CSI->isNullValue()) { + BMI(MBB, IP, X86::MOVrr32, 1, nextBasePtrReg).addReg(basePtrReg); + } else { + unsigned Offset = elementSize*CSI->getValue(); + + BMI(MBB, IP, X86::ADDri32, 2, + nextBasePtrReg).addReg(basePtrReg).addZImm(Offset); + } + } else if (elementSize == 1) { + // If the element size is 1, we don't have to multiply, just add + unsigned idxReg = getReg(idx, MBB, IP); + BMI(MBB, IP, X86::ADDrr32, 2, + nextBasePtrReg).addReg(basePtrReg).addReg(idxReg); + } else { + unsigned idxReg = getReg(idx, MBB, IP); + unsigned OffsetReg = makeAnotherReg(Type::UIntTy); + if (unsigned Shift = ExactLog2(elementSize)) { + // If the element size is exactly a power of 2, use a shift to get it. + + BMI(MBB, IP, X86::SHLir32, 2, + OffsetReg).addReg(idxReg).addZImm(Shift-1); + } else { + // Most general case, emit a multiply... + unsigned elementSizeReg = makeAnotherReg(Type::LongTy); + BMI(MBB, IP, X86::MOVir32, 1, elementSizeReg).addZImm(elementSize); + + // Emit a MUL to multiply the register holding the index by + // elementSize, putting the result in OffsetReg. + doMultiply(MBB, IP, OffsetReg, Type::LongTy, idxReg, elementSizeReg); + } + // Emit an ADD to add OffsetReg to the basePtr. + BMI(MBB, IP, X86::ADDrr32, 2, + nextBasePtrReg).addReg (basePtrReg).addReg (OffsetReg); + } } // Now that we are here, further indices refer to subtypes of this // one, so we don't need to worry about basePtrReg itself, anymore. From lattner at cs.uiuc.edu Mon Dec 16 14:11:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 14:11:01 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/Jello/2002-12-16-ArgTest.ll Message-ID: <200212162010.OAA13894@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Jello: 2002-12-16-ArgTest.ll added (r1.1) --- Log message: New testcase for printing out arguments --- Diffs of the changes: From lattner at cs.uiuc.edu Mon Dec 16 16:30:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 16:30:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Message-ID: <200212162229.QAA15352@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.72 -> 1.73 --- Log message: Make sure stack manipulation refers to ESP the right number of times --- Diffs of the changes: Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.72 llvm/lib/Target/X86/InstSelectSimple.cpp:1.73 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.72 Mon Dec 16 13:32:50 2002 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Mon Dec 16 16:29:06 2002 @@ -1092,7 +1092,8 @@ unsigned int allocatedTypeWords = allocatedTypeSize / 4; if (allocatedTypeSize % 4 != 0) { allocatedTypeWords++; } // Subtract size from stack pointer, thereby allocating some space. - BuildMI (BB, X86::SUBri32, 1, X86::ESP).addZImm (allocatedTypeWords * 4); + BuildMI(BB, X86::SUBri32, 2, + X86::ESP).addReg(X86::ESP).addZImm(allocatedTypeWords * 4); // Put a pointer to the space into the result register, by copying // the stack pointer. BuildMI (BB, X86::MOVrr32, 1, getReg (I)).addReg (X86::ESP); From lattner at cs.uiuc.edu Mon Dec 16 16:30:03 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 16:30:03 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86RegisterInfo.cpp Message-ID: <200212162229.QAA15364@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86RegisterInfo.cpp updated: 1.18 -> 1.19 --- Log message: Fix prolog/epilog in the presence of alloca --- Diffs of the changes: Index: llvm/lib/Target/X86/X86RegisterInfo.cpp diff -u llvm/lib/Target/X86/X86RegisterInfo.cpp:1.18 llvm/lib/Target/X86/X86RegisterInfo.cpp:1.19 --- llvm/lib/Target/X86/X86RegisterInfo.cpp:1.18 Mon Dec 16 13:31:48 2002 +++ llvm/lib/Target/X86/X86RegisterInfo.cpp Mon Dec 16 16:29:30 2002 @@ -117,6 +117,14 @@ MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB MachineBasicBlock::iterator MBBI = MBB.begin(); + // PUSH all callee-save registers + const unsigned* regs = getCalleeSaveRegs(); + while (*regs) { + MachineInstr *MI = BuildMI(X86::PUSHr32, 1).addReg(*regs); + MBBI = ++MBB.insert(MBBI, MI); + ++regs; + } + // PUSH ebp MachineInstr *MI = BuildMI(X86::PUSHr32, 1).addReg(X86::EBP); MBBI = ++MBB.insert(MBBI, MI); @@ -128,14 +136,6 @@ // adjust stack pointer: ESP -= numbytes MI = BuildMI(X86::SUBri32, 2, X86::ESP).addReg(X86::ESP).addZImm(numBytes); MBBI = ++MBB.insert(MBBI, MI); - - // PUSH all callee-save registers - const unsigned* regs = getCalleeSaveRegs(); - while (*regs) { - MI = BuildMI(X86::PUSHr32, 1).addReg(*regs); - MBBI = ++MBB.insert(MBBI, MI); - ++regs; - } } void X86RegisterInfo::emitEpilogue(MachineBasicBlock &MBB, @@ -144,6 +144,9 @@ assert((*MBBI)->getOpcode() == X86::RET && "Can only insert epilog into returning blocks"); + // insert LEAVE + MBBI = ++MBB.insert(MBBI, BuildMI(X86::LEAVE, 0)); + // POP all callee-save registers in REVERSE ORDER static const unsigned regs[] = { X86::EBX, X86::EDI, X86::ESI, MRegisterInfo::NoRegister }; @@ -152,7 +155,4 @@ MachineInstr *MI = BuildMI(X86::POPr32, 0, regs[idx++]); MBBI = ++(MBB.insert(MBBI, MI)); } - - // insert LEAVE - MBB.insert(MBBI, BuildMI(X86::LEAVE, 0)); } From lattner at cs.uiuc.edu Mon Dec 16 16:55:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 16:55:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Message-ID: <200212162254.QAA15770@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.73 -> 1.74 --- Log message: Two fixes: * Only load incoming arguments into virtual registers once at the beginning of the function * Assign different virtual registers to each reference to constants/globals --- Diffs of the changes: Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.73 llvm/lib/Target/X86/InstSelectSimple.cpp:1.74 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.73 Mon Dec 16 16:29:06 2002 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Mon Dec 16 16:54:46 2002 @@ -78,6 +78,27 @@ for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) F->getBasicBlockList().push_back(MBBMap[I] = new MachineBasicBlock(I)); + // Emit instructions to load the arguments... The function's arguments + // look like this: + // + // [EBP] -- copy of old EBP + // [EBP + 4] -- return address + // [EBP + 8] -- first argument (leftmost lexically) + // + // So we want to start with counter = 2. + // + BB = &F->front(); + unsigned ArgOffset = 8; + for (Function::aiterator I = Fn.abegin(), E = Fn.aend(); I != E; + ++I, ArgOffset += 4) { + unsigned Reg = getReg(*I); + + // Load it out of the stack frame at EBP + 4*argPos. + + // FIXME: This should load the argument of the appropriate size!! + addRegOffset(BuildMI(BB, X86::MOVmr32, 4, Reg), X86::EBP, ArgOffset); + } + // Instruction select everything except PHI nodes visit(Fn); @@ -213,30 +234,11 @@ // if (Constant *C = dyn_cast(V)) { copyConstantToRegister(MBB, IPt, C, Reg); + RegMap.erase(V); // Assign a new name to this constant if ref'd again } else if (GlobalValue *GV = dyn_cast(V)) { // Move the address of the global into the register BMI(MBB, IPt, X86::MOVir32, 1, Reg).addReg(GV); - } else if (Argument *A = dyn_cast(V)) { - // Find the position of the argument in the argument list. - const Function *f = F->getFunction (); - // The function's arguments look like this: - // [EBP] -- copy of old EBP - // [EBP + 4] -- return address - // [EBP + 8] -- first argument (leftmost lexically) - // So we want to start with counter = 2. - int counter = 2, argPos = -1; - for (Function::const_aiterator ai = f->abegin (), ae = f->aend (); - ai != ae; ++ai) { - if (&(*ai) == A) { - argPos = counter; - break; // Only need to find it once. ;-) - } - ++counter; - } - assert (argPos != -1 - && "Argument not found in current function's argument list"); - // Load it out of the stack frame at EBP + 4*argPos. - addRegOffset(BMI(MBB, IPt, X86::MOVmr32, 4, Reg), X86::EBP, 4*argPos); + RegMap.erase(V); // Assign a new name to this address if ref'd again } return Reg; From lattner at cs.uiuc.edu Mon Dec 16 17:32:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 17:32:00 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/Jello/2002-12-16-ArgTest.ll Message-ID: <200212162331.RAA16472@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Jello: 2002-12-16-ArgTest.ll updated: 1.1 -> 1.2 --- Log message: Add dummy implementation of __main --- Diffs of the changes: Index: llvm/test/Regression/Jello/2002-12-16-ArgTest.ll diff -u llvm/test/Regression/Jello/2002-12-16-ArgTest.ll:1.1 llvm/test/Regression/Jello/2002-12-16-ArgTest.ll:1.2 --- llvm/test/Regression/Jello/2002-12-16-ArgTest.ll:1.1 Mon Dec 16 14:09:54 2002 +++ llvm/test/Regression/Jello/2002-12-16-ArgTest.ll Mon Dec 16 17:31:48 2002 @@ -2,7 +2,7 @@ implementation ; Functions: -declare void %__main() +void %__main() { ret void } declare int %puts(sbyte*) From lattner at cs.uiuc.edu Mon Dec 16 17:38:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 17:38:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Message-ID: <200212162337.RAA16558@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.74 -> 1.75 --- Log message: Build add instructions of the correct form! --- Diffs of the changes: Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.74 llvm/lib/Target/X86/InstSelectSimple.cpp:1.75 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.74 Mon Dec 16 16:54:46 2002 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Mon Dec 16 17:36:57 2002 @@ -599,7 +599,7 @@ // Adjust the stack by `bytesPushed' amount if non-zero if (bytesPushed > 0) - BuildMI (BB, X86::ADDri32, 2).addReg(X86::ESP).addZImm(bytesPushed); + BuildMI (BB, X86::ADDri32,2,X86::ESP).addReg(X86::ESP).addZImm(bytesPushed); // If there is a return value, scavenge the result from the location the call // leaves it in... From lattner at cs.uiuc.edu Mon Dec 16 20:03:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 20:03:01 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/Jello/test-logical.ll Message-ID: <200212170202.UAA17472@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Jello: test-logical.ll updated: 1.2 -> 1.3 --- Log message: Make testcase return 0 on success --- Diffs of the changes: Index: llvm/test/Regression/Jello/test-logical.ll diff -u llvm/test/Regression/Jello/test-logical.ll:1.2 llvm/test/Regression/Jello/test-logical.ll:1.3 --- llvm/test/Regression/Jello/test-logical.ll:1.2 Wed Dec 4 11:15:07 2002 +++ llvm/test/Regression/Jello/test-logical.ll Mon Dec 16 20:02:01 2002 @@ -1,5 +1,5 @@ -void %main() { +int %main() { %A = and sbyte 4, 8 %B = or sbyte %A, 7 %C = xor sbyte %B, %A @@ -12,5 +12,5 @@ %B = or int %A, 7 %C = xor int %B, %A - ret void + ret int 0 } From lattner at cs.uiuc.edu Mon Dec 16 20:50:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 20:50:00 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86RegisterInfo.cpp Message-ID: <200212170249.UAA18403@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86RegisterInfo.cpp updated: 1.19 -> 1.20 --- Log message: Register allocator is responsible for spilling callee saved regs --- Diffs of the changes: Index: llvm/lib/Target/X86/X86RegisterInfo.cpp diff -u llvm/lib/Target/X86/X86RegisterInfo.cpp:1.19 llvm/lib/Target/X86/X86RegisterInfo.cpp:1.20 --- llvm/lib/Target/X86/X86RegisterInfo.cpp:1.19 Mon Dec 16 16:29:30 2002 +++ llvm/lib/Target/X86/X86RegisterInfo.cpp Mon Dec 16 20:48:57 2002 @@ -117,14 +117,6 @@ MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB MachineBasicBlock::iterator MBBI = MBB.begin(); - // PUSH all callee-save registers - const unsigned* regs = getCalleeSaveRegs(); - while (*regs) { - MachineInstr *MI = BuildMI(X86::PUSHr32, 1).addReg(*regs); - MBBI = ++MBB.insert(MBBI, MI); - ++regs; - } - // PUSH ebp MachineInstr *MI = BuildMI(X86::PUSHr32, 1).addReg(X86::EBP); MBBI = ++MBB.insert(MBBI, MI); @@ -144,15 +136,7 @@ assert((*MBBI)->getOpcode() == X86::RET && "Can only insert epilog into returning blocks"); - // insert LEAVE - MBBI = ++MBB.insert(MBBI, BuildMI(X86::LEAVE, 0)); - - // POP all callee-save registers in REVERSE ORDER - static const unsigned regs[] = { X86::EBX, X86::EDI, X86::ESI, - MRegisterInfo::NoRegister }; - unsigned idx = 0; - while (regs[idx]) { - MachineInstr *MI = BuildMI(X86::POPr32, 0, regs[idx++]); - MBBI = ++(MBB.insert(MBBI, MI)); - } + // insert LEAVE: mov ESP, EBP; pop EBP + MBBI = ++MBB.insert(MBBI, BuildMI(X86::MOVrr32, 1,X86::ESP).addReg(X86::EBP)); + MBBI = ++MBB.insert(MBBI, BuildMI(X86::POPr32, 1).addReg(X86::EBP)); } From lattner at cs.uiuc.edu Mon Dec 16 20:51:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 20:51:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocLocal.cpp Message-ID: <200212170250.UAA18421@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocLocal.cpp updated: 1.2 -> 1.3 --- Log message: Fix many bugs, regallocator now saves callee-save registers instead of target --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocLocal.cpp diff -u llvm/lib/CodeGen/RegAllocLocal.cpp:1.2 llvm/lib/CodeGen/RegAllocLocal.cpp:1.3 --- llvm/lib/CodeGen/RegAllocLocal.cpp:1.2 Mon Dec 16 11:44:42 2002 +++ llvm/lib/CodeGen/RegAllocLocal.cpp Mon Dec 16 20:50:10 2002 @@ -20,9 +20,9 @@ class PhysRegClassMap { std::map PhysReg2RegClassMap; public: - PhysRegClassMap(const MRegisterInfo *RI) { - for (MRegisterInfo::const_iterator I = RI->regclass_begin(), - E = RI->regclass_end(); I != E; ++I) + PhysRegClassMap(const MRegisterInfo &RI) { + for (MRegisterInfo::const_iterator I = RI.regclass_begin(), + E = RI.regclass_end(); I != E; ++I) for (unsigned i=0; i < (*I)->getNumRegs(); ++i) PhysReg2RegClassMap[(*I)->getRegister(i)] = *I; } @@ -42,7 +42,8 @@ class RA : public FunctionPass { TargetMachine &TM; MachineFunction *MF; - const MRegisterInfo *RegInfo; + const MRegisterInfo &RegInfo; + const MachineInstrInfo &MIInfo; unsigned NumBytesAllocated; PhysRegClassMap PhysRegClasses; @@ -88,7 +89,8 @@ public: RA(TargetMachine &tm) - : TM(tm), RegInfo(tm.getRegisterInfo()), PhysRegClasses(RegInfo) { + : TM(tm), RegInfo(*tm.getRegisterInfo()), MIInfo(tm.getInstrInfo()), + PhysRegClasses(RegInfo) { cleanupAfterFunction(); } @@ -111,16 +113,23 @@ /// in predecessor basic blocks. void EliminatePHINodes(MachineBasicBlock &MBB); + /// EmitPrologue/EmitEpilogue - Use the register info object to add a + /// prologue/epilogue to the function and save/restore any callee saved + /// registers we are responsible for. + /// + void EmitPrologue(); + void EmitEpilogue(MachineBasicBlock &MBB); + /// isAllocatableRegister - A register may be used by the program if it's /// not the stack or frame pointer. bool isAllocatableRegister(unsigned R) const { - unsigned FP = RegInfo->getFramePointer(), SP = RegInfo->getStackPointer(); + unsigned FP = RegInfo.getFramePointer(), SP = RegInfo.getStackPointer(); // Don't allocate the Frame or Stack pointers if (R == FP || R == SP) return false; // Check to see if this register aliases the stack or frame pointer... - if (const unsigned *AliasSet = RegInfo->getAliasSet(R)) { + if (const unsigned *AliasSet = RegInfo.getAliasSet(R)) { for (unsigned i = 0; AliasSet[i]; ++i) if (AliasSet[i] == FP || AliasSet[i] == SP) return false; @@ -151,13 +160,18 @@ // void spillPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I, unsigned PhysReg) { - assert(PhysRegsUsed.find(PhysReg) != PhysRegsUsed.end() && - "Physical register is not used: cannot spill it!"); - spillVirtReg(MBB, I, PhysRegsUsed[PhysReg], PhysReg); + std::map::iterator PI = PhysRegsUsed.find(PhysReg); + if (PI != PhysRegsUsed.end()) // Only spill it if it's used! + spillVirtReg(MBB, I, PI->second, PhysReg); } void AssignVirtToPhysReg(unsigned VirtReg, unsigned PhysReg); + /// isPhysRegAvailable - Return true if the specified physical register is + /// free and available for use. This also includes checking to see if + /// aliased registers are all free... + /// + bool RA::isPhysRegAvailable(unsigned PhysReg) const; /// getFreeReg - Find a physical register to hold the specified virtual /// register. If all compatible physical registers are used, this method @@ -176,9 +190,9 @@ unsigned reloadVirtReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I, unsigned VirtReg); }; - } + /// getStackSpaceFor - This allocates space for the specified virtual /// register to be held on the stack. unsigned RA::getStackSpaceFor(unsigned VirtReg, @@ -206,6 +220,7 @@ return NumBytesAllocated-RegSize; } + /// spillVirtReg - This method spills the value specified by PhysReg into the /// virtual register slot specified by VirtReg. It then updates the RA data /// structures to indicate the fact that PhysReg is now available. @@ -218,8 +233,8 @@ unsigned stackOffset = getStackSpaceFor(VirtReg, RegClass); // Add move instruction(s) - I = RegInfo->storeReg2RegOffset(MBB, I, PhysReg, RegInfo->getFramePointer(), - -stackOffset, RegClass->getDataSize()); + I = RegInfo.storeReg2RegOffset(MBB, I, PhysReg, RegInfo.getFramePointer(), + -stackOffset, RegClass->getDataSize()); ++NumSpilled; // Update statistics Virt2PhysRegMap.erase(VirtReg); // VirtReg no longer available } @@ -232,6 +247,25 @@ PhysRegsUseOrder.erase(It); } + +/// isPhysRegAvailable - Return true if the specified physical register is free +/// and available for use. This also includes checking to see if aliased +/// registers are all free... +/// +bool RA::isPhysRegAvailable(unsigned PhysReg) const { + if (PhysRegsUsed.count(PhysReg)) return false; + + // If the selected register aliases any other allocated registers, it is + // not free! + if (const unsigned *AliasSet = RegInfo.getAliasSet(PhysReg)) + for (unsigned i = 0; AliasSet[i]; ++i) + if (PhysRegsUsed.count(AliasSet[i])) // Aliased register in use? + return false; // Can't use this reg then. + return true; +} + + + /// getFreeReg - Find a physical register to hold the specified virtual /// register. If all compatible physical registers are used, this method spills /// the last used virtual register to the stack, and uses that register. @@ -240,47 +274,72 @@ unsigned VirtReg) { const TargetRegisterClass *RegClass = MF->getRegClass(VirtReg); unsigned PhysReg = 0; - + + // First check to see if we have a free register of the requested type... for (TargetRegisterClass::iterator It = RegClass->begin(),E = RegClass->end(); It != E; ++It) { unsigned R = *It; - if (PhysRegsUsed.find(R) == PhysRegsUsed.end()) // Is reg unused? - if (isAllocatableRegister(R)) { + if (isPhysRegAvailable(R)) { // Is reg unused? + if (isAllocatableRegister(R)) { // And is not a frame register? // Found an unused register! PhysReg = R; break; } + } } - // If we didn't find an unused register, scavange one now! + // If we didn't find an unused register, scavenge one now! if (PhysReg == 0) { - unsigned i = 0; assert(!PhysRegsUseOrder.empty() && "No allocated registers??"); - while (PhysRegClasses[PhysRegsUseOrder[i]] != RegClass) { - ++i; + + // Loop over all of the preallocated registers from the least recently used + // to the most recently used. When we find one that is capable of holding + // our register, use it. + for (unsigned i = 0; PhysReg == 0; ++i) { assert(i != PhysRegsUseOrder.size() && "Couldn't find a register of the appropriate class!"); + + unsigned R = PhysRegsUseOrder[i]; + // If the current register is compatible, use it. + if (isAllocatableRegister(R)) { + if (PhysRegClasses[R] == RegClass) { + PhysReg = R; + break; + } else { + // If one of the registers aliased to the current register is + // compatible, use it. + if (const unsigned *AliasSet = RegInfo.getAliasSet(R)) + for (unsigned a = 0; AliasSet[a]; ++a) + if (PhysRegClasses[AliasSet[a]] == RegClass) { + PhysReg = AliasSet[a]; // Take an aliased register + break; + } + } + } } + assert(isAllocatableRegister(PhysReg) && "Register is not allocatable!"); + + assert(PhysReg && "Physical register not assigned!?!?"); + // At this point PhysRegsUseOrder[i] is the least recently used register of // compatible register class. Spill it to memory and reap its remains. - PhysReg = PhysRegsUseOrder[i]; spillPhysReg(MBB, I, PhysReg); - } - - // If the selected register aliases any other registers, we must make sure to - // spill them as well... - if (const unsigned *AliasSet = RegInfo->getAliasSet(PhysReg)) - for (unsigned i = 0; AliasSet[i]; ++i) - if (PhysRegsUsed.count(AliasSet[i])) // Spill aliased register... - spillPhysReg(MBB, I, AliasSet[i]); + // If the selected register aliases any other registers, we must make sure + // to spill them as well... + if (const unsigned *AliasSet = RegInfo.getAliasSet(PhysReg)) + for (unsigned i = 0; AliasSet[i]; ++i) + if (PhysRegsUsed.count(AliasSet[i])) // Spill aliased register... + spillPhysReg(MBB, I, AliasSet[i]); + } // Now that we know which register we need to assign this to, do it now! AssignVirtToPhysReg(VirtReg, PhysReg); return PhysReg; } + void RA::AssignVirtToPhysReg(unsigned VirtReg, unsigned PhysReg) { assert(PhysRegsUsed.find(PhysReg) == PhysRegsUsed.end() && "Phys reg already assigned!"); @@ -312,12 +371,13 @@ unsigned StackOffset = getStackSpaceFor(VirtReg, RegClass); // Add move instruction(s) - I = RegInfo->loadRegOffset2Reg(MBB, I, PhysReg, RegInfo->getFramePointer(), - -StackOffset, RegClass->getDataSize()); + I = RegInfo.loadRegOffset2Reg(MBB, I, PhysReg, RegInfo.getFramePointer(), + -StackOffset, RegClass->getDataSize()); ++NumReloaded; // Update statistics return PhysReg; } + /// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions in /// predecessor basic blocks. /// @@ -375,12 +435,12 @@ // Retrieve the constant value from this op, move it to target // register of the phi if (opVal.isImmediate()) { - opI = RegInfo->moveImm2Reg(opBlock, opI, virtualReg, - (unsigned) opVal.getImmedValue(), - dataSize); + opI = RegInfo.moveImm2Reg(opBlock, opI, virtualReg, + (unsigned) opVal.getImmedValue(), + dataSize); } else { - opI = RegInfo->moveReg2Reg(opBlock, opI, virtualReg, - opVal.getAllocatedRegNum(), dataSize); + opI = RegInfo.moveReg2Reg(opBlock, opI, virtualReg, + opVal.getAllocatedRegNum(), dataSize); } } } @@ -390,31 +450,39 @@ } } + void RA::AllocateBasicBlock(MachineBasicBlock &MBB) { // loop over each instruction MachineBasicBlock::iterator I = MBB.begin(); for (; I != MBB.end(); ++I) { MachineInstr *MI = *I; + const MachineInstrDescriptor &MID = MIInfo.get(MI->getOpcode()); // Loop over all of the operands of the instruction, spilling registers that // are defined, and marking explicit destinations in the PhysRegsUsed map. for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) if (MI->getOperand(i).opIsDef() && MI->getOperand(i).isPhysicalRegister()) { - unsigned Reg = MI->getOperand(i).getAllocatedRegNum(); - unsigned VMap = PhysRegsUsed[Reg]; - if (VMap) { // Spill the value in this register... - spillVirtReg(MBB, I, VMap, Reg); - PhysRegsUsed[Reg] = 0; // It's free now, and it's reserved - } + unsigned Reg = MI->getOperand(i).getAllocatedRegNum(); + spillPhysReg(MBB, I, Reg); + PhysRegsUsed[Reg] = 0; // It's free now, and it's reserved PhysRegsUseOrder.push_back(Reg); } - // FIXME: Loop over the implicit defs, spilling them, as above. - + // Loop over the implicit defs, spilling them, as above. + if (const unsigned *ImplicitDefs = MID.ImplicitDefs) + for (unsigned i = 0; ImplicitDefs[i]; ++i) { + unsigned Reg = ImplicitDefs[i]; + spillPhysReg(MBB, I, Reg); + PhysRegsUsed[Reg] = 0; // It's free now, and it's reserved + PhysRegsUseOrder.push_back(Reg); + } - // FIXME: Loop over the implicit uses, making sure that they are at the head - // of the use order list, so they don't get reallocated. + // Loop over the implicit uses, making sure that they are at the head of the + // use order list, so they don't get reallocated. + if (const unsigned *ImplicitUses = MID.ImplicitUses) + for (unsigned i = 0; ImplicitUses[i]; ++i) + MarkPhysRegRecentlyUsed(ImplicitUses[i]); // Loop over all of the operands again, getting the used operands into // registers. This has the potiential to spill incoming values because we @@ -479,6 +547,52 @@ assert(PhysRegsUseOrder.empty() && "Physical regs still allocated?"); } +/// EmitPrologue - Use the register info object to add a prologue to the +/// function and save any callee saved registers we are responsible for. +/// +void RA::EmitPrologue() { + // Get a list of the callee saved registers, so that we can save them on entry + // to the function. + // + + MachineBasicBlock &MBB = MF->front(); // Prolog goes in entry BB + MachineBasicBlock::iterator I = MBB.begin(); + + const unsigned *CSRegs = RegInfo.getCalleeSaveRegs(); + for (unsigned i = 0; CSRegs[i]; ++i) { + const TargetRegisterClass *RegClass = PhysRegClasses[CSRegs[i]]; + unsigned Offset = getStackSpaceFor(CSRegs[i], RegClass); + + // Insert the spill to the stack frame... + I = RegInfo.storeReg2RegOffset(MBB, I, CSRegs[i], RegInfo.getFramePointer(), + -Offset, RegClass->getDataSize()); + } + + // Round stack allocation up to a nice alignment to keep the stack aligned + // FIXME: This is X86 specific! Move to RegInfo.emitPrologue()! + NumBytesAllocated = (NumBytesAllocated + 3) & ~3; + + // Add prologue to the function... + RegInfo.emitPrologue(*MF, NumBytesAllocated); +} + +void RA::EmitEpilogue(MachineBasicBlock &MBB) { + // Insert instructions before the return. + MachineBasicBlock::iterator I = --MBB.end(); + + const unsigned *CSRegs = RegInfo.getCalleeSaveRegs(); + for (unsigned i = 0; CSRegs[i]; ++i) { + const TargetRegisterClass *RegClass = PhysRegClasses[CSRegs[i]]; + unsigned Offset = getStackSpaceFor(CSRegs[i], RegClass); + I = RegInfo.loadRegOffset2Reg(MBB, I, CSRegs[i], RegInfo.getFramePointer(), + -Offset, RegClass->getDataSize()); + --I; // Insert in reverse order + } + + RegInfo.emitEpilogue(MBB, NumBytesAllocated); +} + + /// runOnMachineFunction - Register allocate the whole function /// bool RA::runOnMachineFunction(MachineFunction &Fn) { @@ -497,12 +611,9 @@ MBB != MBBe; ++MBB) AllocateBasicBlock(*MBB); - // Round stack allocation up to a nice alignment to keep the stack aligned - // FIXME: This is X86 specific! Move to frame manager - NumBytesAllocated = (NumBytesAllocated + 3) & ~3; - // Add prologue to the function... - RegInfo->emitPrologue(Fn, NumBytesAllocated); + // Emit a prologue for the function... + EmitPrologue(); const MachineInstrInfo &MII = TM.getInstrInfo(); @@ -511,7 +622,7 @@ MBB != MBBe; ++MBB) { // If last instruction is a return instruction, add an epilogue if (MII.isReturn(MBB->back()->getOpcode())) - RegInfo->emitEpilogue(*MBB, NumBytesAllocated); + EmitEpilogue(*MBB); } cleanupAfterFunction(); From lattner at cs.uiuc.edu Mon Dec 16 20:52:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 20:52:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86TargetMachine.cpp Message-ID: <200212170251.UAA18490@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86TargetMachine.cpp updated: 1.7 -> 1.8 --- Log message: Local register allocator is now stable enough for use, it passes all tests --- Diffs of the changes: Index: llvm/lib/Target/X86/X86TargetMachine.cpp diff -u llvm/lib/Target/X86/X86TargetMachine.cpp:1.7 llvm/lib/Target/X86/X86TargetMachine.cpp:1.8 --- llvm/lib/Target/X86/X86TargetMachine.cpp:1.7 Mon Dec 16 10:15:51 2002 +++ llvm/lib/Target/X86/X86TargetMachine.cpp Mon Dec 16 20:51:15 2002 @@ -15,8 +15,8 @@ #include namespace { - cl::opt UseLocalRA("local-ra", - cl::desc("Use Local RegAlloc instead of Simple RA")); + cl::opt NoLocalRA("no-local-ra", + cl::desc("Use Simple RA instead of Local RegAlloc")); } // allocateX86TargetMachine - Allocate and return a subclass of TargetMachine @@ -49,10 +49,10 @@ DEBUG(PM.add(createMachineFunctionPrinterPass())); // Perform register allocation to convert to a concrete x86 representation - if (UseLocalRA) - PM.add(createLocalRegisterAllocator(*this)); - else + if (NoLocalRA) PM.add(createSimpleRegisterAllocator(*this)); + else + PM.add(createLocalRegisterAllocator(*this)); // Print the instruction selected machine code... // PM.add(createMachineFunctionPrinterPass()); From lattner at cs.uiuc.edu Mon Dec 16 21:16:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 21:16:00 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86RegisterInfo.cpp Message-ID: <200212170315.VAA19038@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86RegisterInfo.cpp updated: 1.20 -> 1.21 --- Log message: Round number of bytes allocated on the stack up to a multiple of 4 so that the stack remains aligned --- Diffs of the changes: Index: llvm/lib/Target/X86/X86RegisterInfo.cpp diff -u llvm/lib/Target/X86/X86RegisterInfo.cpp:1.20 llvm/lib/Target/X86/X86RegisterInfo.cpp:1.21 --- llvm/lib/Target/X86/X86RegisterInfo.cpp:1.20 Mon Dec 16 20:48:57 2002 +++ llvm/lib/Target/X86/X86RegisterInfo.cpp Mon Dec 16 21:15:26 2002 @@ -113,10 +113,13 @@ } void X86RegisterInfo::emitPrologue(MachineFunction &MF, - unsigned numBytes) const { + unsigned NumBytes) const { MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB MachineBasicBlock::iterator MBBI = MBB.begin(); + // Round stack allocation up to a nice alignment to keep the stack aligned + NumBytes = (NumBytes + 3) & ~3; + // PUSH ebp MachineInstr *MI = BuildMI(X86::PUSHr32, 1).addReg(X86::EBP); MBBI = ++MBB.insert(MBBI, MI); @@ -126,7 +129,7 @@ MBBI = ++MBB.insert(MBBI, MI); // adjust stack pointer: ESP -= numbytes - MI = BuildMI(X86::SUBri32, 2, X86::ESP).addReg(X86::ESP).addZImm(numBytes); + MI = BuildMI(X86::SUBri32, 2, X86::ESP).addReg(X86::ESP).addZImm(NumBytes); MBBI = ++MBB.insert(MBBI, MI); } From lattner at cs.uiuc.edu Mon Dec 16 21:17:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 21:17:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocLocal.cpp Message-ID: <200212170316.VAA19049@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocLocal.cpp updated: 1.3 -> 1.4 --- Log message: Add prolog/epilog spills/reloads to counters Move X86 specific alignment gunk to X86 files --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocLocal.cpp diff -u llvm/lib/CodeGen/RegAllocLocal.cpp:1.3 llvm/lib/CodeGen/RegAllocLocal.cpp:1.4 --- llvm/lib/CodeGen/RegAllocLocal.cpp:1.3 Mon Dec 16 20:50:10 2002 +++ llvm/lib/CodeGen/RegAllocLocal.cpp Mon Dec 16 21:16:10 2002 @@ -547,6 +547,7 @@ assert(PhysRegsUseOrder.empty() && "Physical regs still allocated?"); } + /// EmitPrologue - Use the register info object to add a prologue to the /// function and save any callee saved registers we are responsible for. /// @@ -564,18 +565,19 @@ unsigned Offset = getStackSpaceFor(CSRegs[i], RegClass); // Insert the spill to the stack frame... + ++NumSpilled; I = RegInfo.storeReg2RegOffset(MBB, I, CSRegs[i], RegInfo.getFramePointer(), -Offset, RegClass->getDataSize()); } - // Round stack allocation up to a nice alignment to keep the stack aligned - // FIXME: This is X86 specific! Move to RegInfo.emitPrologue()! - NumBytesAllocated = (NumBytesAllocated + 3) & ~3; - // Add prologue to the function... RegInfo.emitPrologue(*MF, NumBytesAllocated); } + +/// EmitEpilogue - Use the register info object to add a epilogue to the +/// function and restore any callee saved registers we are responsible for. +/// void RA::EmitEpilogue(MachineBasicBlock &MBB) { // Insert instructions before the return. MachineBasicBlock::iterator I = --MBB.end(); @@ -584,6 +586,7 @@ for (unsigned i = 0; CSRegs[i]; ++i) { const TargetRegisterClass *RegClass = PhysRegClasses[CSRegs[i]]; unsigned Offset = getStackSpaceFor(CSRegs[i], RegClass); + ++NumReloaded; I = RegInfo.loadRegOffset2Reg(MBB, I, CSRegs[i], RegInfo.getFramePointer(), -Offset, RegClass->getDataSize()); --I; // Insert in reverse order From lattner at cs.uiuc.edu Mon Dec 16 22:04:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 22:04:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/MRegisterInfo.cpp Message-ID: <200212170403.WAA21066@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target: MRegisterInfo.cpp added (r1.1) --- Log message: New file --- Diffs of the changes: From lattner at cs.uiuc.edu Mon Dec 16 22:20:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 22:20:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86RegisterClasses.cpp X86RegisterInfo.cpp X86RegisterInfo.h Message-ID: <200212170419.WAA21128@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86RegisterClasses.cpp updated: 1.7 -> 1.8 X86RegisterInfo.cpp updated: 1.21 -> 1.22 X86RegisterInfo.h updated: 1.10 -> 1.11 --- Log message: Update to use new interface for register info --- Diffs of the changes: Index: llvm/lib/Target/X86/X86RegisterClasses.cpp diff -u llvm/lib/Target/X86/X86RegisterClasses.cpp:1.7 llvm/lib/Target/X86/X86RegisterClasses.cpp:1.8 --- llvm/lib/Target/X86/X86RegisterClasses.cpp:1.7 Mon Dec 16 10:14:51 2002 +++ llvm/lib/Target/X86/X86RegisterClasses.cpp Mon Dec 16 22:19:17 2002 @@ -48,6 +48,30 @@ }; } + +// Create static lists to contain register alias sets... +#define ALIASLIST(NAME, ...) \ + static const unsigned NAME[] = { __VA_ARGS__ }; +#include "X86RegisterInfo.def" + + +// X86Regs - Turn the X86RegisterInfo.def file into a bunch of register +// descriptors +// +static const MRegisterDesc X86Regs[] = { +#define R(ENUM, NAME, FLAGS, TSFLAGS, ALIAS_SET) \ + { NAME, ALIAS_SET, FLAGS, TSFLAGS }, +#include "X86RegisterInfo.def" +}; + +X86RegisterInfo::X86RegisterInfo() + : MRegisterInfo(X86Regs, sizeof(X86Regs)/sizeof(X86Regs[0]), + X86RegClasses, + X86RegClasses+sizeof(X86RegClasses)/sizeof(X86RegClasses[0])){ +} + + + const TargetRegisterClass* X86RegisterInfo::getRegClassForType(const Type* Ty) const { switch (Ty->getPrimitiveID()) { @@ -71,17 +95,3 @@ return 0; // not reached } } - - -MRegisterInfo::const_iterator X86RegisterInfo::regclass_begin() const { - return X86RegClasses; -} - -unsigned X86RegisterInfo::getNumRegClasses() const { - return sizeof(X86RegClasses)/sizeof(X86RegClasses[0]); -} - -MRegisterInfo::const_iterator X86RegisterInfo::regclass_end() const { - return X86RegClasses+getNumRegClasses(); -} - Index: llvm/lib/Target/X86/X86RegisterInfo.cpp diff -u llvm/lib/Target/X86/X86RegisterInfo.cpp:1.21 llvm/lib/Target/X86/X86RegisterInfo.cpp:1.22 --- llvm/lib/Target/X86/X86RegisterInfo.cpp:1.21 Mon Dec 16 21:15:26 2002 +++ llvm/lib/Target/X86/X86RegisterInfo.cpp Mon Dec 16 22:19:17 2002 @@ -12,25 +12,6 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineFunction.h" -// Create static lists to contain register alias sets... -#define ALIASLIST(NAME, ...) \ - static const unsigned NAME[] = { __VA_ARGS__ }; -#include "X86RegisterInfo.def" - - -// X86Regs - Turn the X86RegisterInfo.def file into a bunch of register -// descriptors -// -static const MRegisterDesc X86Regs[] = { -#define R(ENUM, NAME, FLAGS, TSFLAGS, ALIAS_SET) \ - { NAME, ALIAS_SET, FLAGS, TSFLAGS }, -#include "X86RegisterInfo.def" -}; - -X86RegisterInfo::X86RegisterInfo() - : MRegisterInfo(X86Regs, sizeof(X86Regs)/sizeof(X86Regs[0])) { -} - unsigned getIdx(unsigned dataSize) { switch (dataSize) { case 1: return 0; Index: llvm/lib/Target/X86/X86RegisterInfo.h diff -u llvm/lib/Target/X86/X86RegisterInfo.h:1.10 llvm/lib/Target/X86/X86RegisterInfo.h:1.11 --- llvm/lib/Target/X86/X86RegisterInfo.h:1.10 Sun Dec 15 14:06:11 2002 +++ llvm/lib/Target/X86/X86RegisterInfo.h Mon Dec 16 22:19:17 2002 @@ -14,9 +14,6 @@ struct X86RegisterInfo : public MRegisterInfo { X86RegisterInfo(); - MRegisterInfo::const_iterator regclass_begin() const; - MRegisterInfo::const_iterator regclass_end() const; - MachineBasicBlock::iterator storeReg2RegOffset(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, @@ -53,9 +50,6 @@ const TargetRegisterClass *getClassForReg(unsigned Reg) const; const TargetRegisterClass* getRegClassForType(const Type* Ty) const; - - unsigned getNumRegClasses() const; - }; #endif From lattner at cs.uiuc.edu Mon Dec 16 22:20:02 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 22:20:02 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocLocal.cpp RegAllocSimple.cpp Message-ID: <200212170419.WAA21143@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocLocal.cpp updated: 1.4 -> 1.5 RegAllocSimple.cpp updated: 1.30 -> 1.31 --- Log message: Use new reginfo interface --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocLocal.cpp diff -u llvm/lib/CodeGen/RegAllocLocal.cpp:1.4 llvm/lib/CodeGen/RegAllocLocal.cpp:1.5 --- llvm/lib/CodeGen/RegAllocLocal.cpp:1.4 Mon Dec 16 21:16:10 2002 +++ llvm/lib/CodeGen/RegAllocLocal.cpp Mon Dec 16 22:19:40 2002 @@ -12,29 +12,6 @@ #include "Support/Statistic.h" #include -/// PhysRegClassMap - Construct a mapping of physical register numbers to their -/// register classes. -/// -/// NOTE: This class will eventually be pulled out to somewhere shared. -/// -class PhysRegClassMap { - std::map PhysReg2RegClassMap; -public: - PhysRegClassMap(const MRegisterInfo &RI) { - for (MRegisterInfo::const_iterator I = RI.regclass_begin(), - E = RI.regclass_end(); I != E; ++I) - for (unsigned i=0; i < (*I)->getNumRegs(); ++i) - PhysReg2RegClassMap[(*I)->getRegister(i)] = *I; - } - - const TargetRegisterClass *operator[](unsigned Reg) { - assert(PhysReg2RegClassMap[Reg] && "Register is not a known physreg!"); - return PhysReg2RegClassMap[Reg]; - } - - const TargetRegisterClass *get(unsigned Reg) { return operator[](Reg); } -}; - namespace { Statistic<> NumSpilled ("ra-local", "Number of registers spilled"); Statistic<> NumReloaded("ra-local", "Number of registers reloaded"); @@ -45,7 +22,6 @@ const MRegisterInfo &RegInfo; const MachineInstrInfo &MIInfo; unsigned NumBytesAllocated; - PhysRegClassMap PhysRegClasses; // Maps SSA Regs => offsets on the stack where these values are stored std::map VirtReg2OffsetMap; @@ -89,8 +65,7 @@ public: RA(TargetMachine &tm) - : TM(tm), RegInfo(*tm.getRegisterInfo()), MIInfo(tm.getInstrInfo()), - PhysRegClasses(RegInfo) { + : TM(tm), RegInfo(*tm.getRegisterInfo()), MIInfo(tm.getInstrInfo()) { cleanupAfterFunction(); } @@ -302,7 +277,7 @@ unsigned R = PhysRegsUseOrder[i]; // If the current register is compatible, use it. if (isAllocatableRegister(R)) { - if (PhysRegClasses[R] == RegClass) { + if (RegInfo.getRegClass(R) == RegClass) { PhysReg = R; break; } else { @@ -310,7 +285,7 @@ // compatible, use it. if (const unsigned *AliasSet = RegInfo.getAliasSet(R)) for (unsigned a = 0; AliasSet[a]; ++a) - if (PhysRegClasses[AliasSet[a]] == RegClass) { + if (RegInfo.getRegClass(AliasSet[a]) == RegClass) { PhysReg = AliasSet[a]; // Take an aliased register break; } @@ -561,7 +536,7 @@ const unsigned *CSRegs = RegInfo.getCalleeSaveRegs(); for (unsigned i = 0; CSRegs[i]; ++i) { - const TargetRegisterClass *RegClass = PhysRegClasses[CSRegs[i]]; + const TargetRegisterClass *RegClass = RegInfo.getRegClass(CSRegs[i]); unsigned Offset = getStackSpaceFor(CSRegs[i], RegClass); // Insert the spill to the stack frame... @@ -584,7 +559,7 @@ const unsigned *CSRegs = RegInfo.getCalleeSaveRegs(); for (unsigned i = 0; CSRegs[i]; ++i) { - const TargetRegisterClass *RegClass = PhysRegClasses[CSRegs[i]]; + const TargetRegisterClass *RegClass = RegInfo.getRegClass(CSRegs[i]); unsigned Offset = getStackSpaceFor(CSRegs[i], RegClass); ++NumReloaded; I = RegInfo.loadRegOffset2Reg(MBB, I, CSRegs[i], RegInfo.getFramePointer(), @@ -606,8 +581,9 @@ // blocks. // FIXME: In this pass, count how many uses of each VReg exist! for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); - MBB != MBBe; ++MBB) + MBB != MBBe; ++MBB) { EliminatePHINodes(*MBB); + } // Loop over all of the basic blocks, eliminating virtual register references for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.30 llvm/lib/CodeGen/RegAllocSimple.cpp:1.31 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.30 Mon Dec 16 11:42:40 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Mon Dec 16 22:19:40 2002 @@ -62,6 +62,13 @@ /// in predecessor basic blocks. void EliminatePHINodes(MachineBasicBlock &MBB); + /// EmitPrologue/EmitEpilogue - Use the register info object to add a + /// prologue/epilogue to the function and save/restore any callee saved + /// registers we are responsible for. + /// + void EmitPrologue(); + void EmitEpilogue(MachineBasicBlock &MBB); + /// getStackSpaceFor - This returns the offset of the specified virtual /// register on the stack, allocating space if neccesary. @@ -307,6 +314,55 @@ } } + +/// EmitPrologue - Use the register info object to add a prologue to the +/// function and save any callee saved registers we are responsible for. +/// +void RegAllocSimple::EmitPrologue() { + // Get a list of the callee saved registers, so that we can save them on entry + // to the function. + // + MachineBasicBlock &MBB = MF->front(); // Prolog goes in entry BB + MachineBasicBlock::iterator I = MBB.begin(); + + const unsigned *CSRegs = RegInfo->getCalleeSaveRegs(); + for (unsigned i = 0; CSRegs[i]; ++i) { + const TargetRegisterClass *RegClass = RegInfo->getRegClass(CSRegs[i]); + unsigned Offset = getStackSpaceFor(CSRegs[i], RegClass); + + // Insert the spill to the stack frame... + I = RegInfo->storeReg2RegOffset(MBB, I,CSRegs[i],RegInfo->getFramePointer(), + -Offset, RegClass->getDataSize()); + ++NumSpilled; + } + + // Add prologue to the function... + RegInfo->emitPrologue(*MF, NumBytesAllocated); +} + + +/// EmitEpilogue - Use the register info object to add a epilogue to the +/// function and restore any callee saved registers we are responsible for. +/// +void RegAllocSimple::EmitEpilogue(MachineBasicBlock &MBB) { + // Insert instructions before the return. + MachineBasicBlock::iterator I = --MBB.end(); + + const unsigned *CSRegs = RegInfo->getCalleeSaveRegs(); + for (unsigned i = 0; CSRegs[i]; ++i) { + const TargetRegisterClass *RegClass = RegInfo->getRegClass(CSRegs[i]); + unsigned Offset = getStackSpaceFor(CSRegs[i], RegClass); + + I = RegInfo->loadRegOffset2Reg(MBB, I, CSRegs[i],RegInfo->getFramePointer(), + -Offset, RegClass->getDataSize()); + --I; // Insert in reverse order + ++NumReloaded; + } + + RegInfo->emitEpilogue(MBB, NumBytesAllocated); +} + + /// runOnMachineFunction - Register allocate the whole function /// bool RegAllocSimple::runOnMachineFunction(MachineFunction &Fn) { @@ -328,8 +384,8 @@ // FIXME: This is X86 specific! Move to frame manager NumBytesAllocated = (NumBytesAllocated + 3) & ~3; - // Add prologue to the function... - RegInfo->emitPrologue(Fn, NumBytesAllocated); + // Emit a prologue for the function... + EmitPrologue(); const MachineInstrInfo &MII = TM.getInstrInfo(); @@ -338,7 +394,7 @@ MBB != MBBe; ++MBB) { // If last instruction is a return instruction, add an epilogue if (MII.isReturn(MBB->back()->getOpcode())) - RegInfo->emitEpilogue(*MBB, NumBytesAllocated); + EmitEpilogue(*MBB); } cleanupAfterFunction(); From lattner at cs.uiuc.edu Mon Dec 16 22:21:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Dec 16 22:21:01 2002 Subject: [llvm-commits] CVS: llvm/include/llvm/Target/MRegisterInfo.h Message-ID: <200212170420.WAA21159@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Target: MRegisterInfo.h updated: 1.12 -> 1.13 --- Log message: Simplify interface to remove virtual function references --- Diffs of the changes: Index: llvm/include/llvm/Target/MRegisterInfo.h diff -u llvm/include/llvm/Target/MRegisterInfo.h:1.12 llvm/include/llvm/Target/MRegisterInfo.h:1.13 --- llvm/include/llvm/Target/MRegisterInfo.h:1.12 Mon Dec 16 10:39:14 2002 +++ llvm/include/llvm/Target/MRegisterInfo.h Mon Dec 16 22:20:39 2002 @@ -69,8 +69,6 @@ } unsigned getDataSize() const { return RegSize; } - - //void getAliases(void); }; @@ -80,10 +78,19 @@ /// that we can turn register number into a register descriptor. /// class MRegisterInfo { - const MRegisterDesc *Desc; // Pointer to the descriptor array - unsigned NumRegs; // Number of entries in the array +public: + typedef const TargetRegisterClass * const * regclass_iterator; +private: + const MRegisterDesc *Desc; // Pointer to the descriptor array + unsigned NumRegs; // Number of entries in the array + + regclass_iterator RegClassBegin, RegClassEnd; // List of regclasses + + const TargetRegisterClass **PhysRegClasses; // Reg class for each register protected: - MRegisterInfo(const MRegisterDesc *D, unsigned NR) : Desc(D), NumRegs(NR) {} + MRegisterInfo(const MRegisterDesc *D, unsigned NR, + regclass_iterator RegClassBegin, regclass_iterator RegClassEnd); + virtual ~MRegisterInfo(); public: enum { // Define some target independant constants @@ -115,6 +122,15 @@ /// const MRegisterDesc &get(unsigned RegNo) const { return operator[](RegNo); } + /// getRegClass - Return the register class for the specified physical + /// register. + /// + const TargetRegisterClass *getRegClass(unsigned RegNo) const { + assert(RegNo < NumRegs && "Register number out of range!"); + assert(PhysRegClasses[RegNo] && "Register is not in a class!"); + return PhysRegClasses[RegNo]; + } + /// getAliasSet - Return the set of registers aliased by the specified /// register, or a null list of there are none. The list returned is zero /// terminated. @@ -123,6 +139,35 @@ return get(RegNo).AliasSet; } + virtual unsigned getFramePointer() const = 0; + virtual unsigned getStackPointer() const = 0; + + virtual const unsigned* getCalleeSaveRegs() const = 0; + virtual const unsigned* getCallerSaveRegs() const = 0; + + + //===--------------------------------------------------------------------===// + // Register Class Information + // + + /// Register class iterators + regclass_iterator regclass_begin() const { return RegClassBegin; } + regclass_iterator regclass_end() const { return RegClassEnd; } + + unsigned getNumRegClasses() const { + return regclass_end()-regclass_begin(); + } + virtual const TargetRegisterClass* getRegClassForType(const Type* Ty) const=0; + + + //===--------------------------------------------------------------------===// + // Interfaces used primarily by the register allocator to move data around + // between registers, immediates and memory. + // + + virtual void emitPrologue(MachineFunction &MF, unsigned Bytes) const = 0; + virtual void emitEpilogue(MachineBasicBlock &MBB, unsigned Bytes) const = 0; + virtual MachineBasicBlock::iterator storeReg2RegOffset(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, @@ -144,27 +189,6 @@ moveImm2Reg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned DestReg, unsigned Imm, unsigned dataSize) const = 0; - - virtual void - emitPrologue(MachineFunction &MF, unsigned numBytes) const = 0; - - virtual void - emitEpilogue(MachineBasicBlock &MBB, unsigned numBytes) const = 0; - - virtual const unsigned* getCalleeSaveRegs() const = 0; - virtual const unsigned* getCallerSaveRegs() const = 0; - - virtual unsigned getFramePointer() const = 0; - virtual unsigned getStackPointer() const = 0; - - /// Register class iterators - typedef const TargetRegisterClass * const * const_iterator; - - virtual const_iterator regclass_begin() const = 0; - virtual const_iterator regclass_end() const = 0; - - virtual unsigned getNumRegClasses() const = 0; - virtual const TargetRegisterClass* getRegClassForType(const Type* Ty) const=0; }; #endif From lattner at cs.uiuc.edu Tue Dec 17 19:06:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Dec 17 19:06:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86InstrInfo.def Message-ID: <200212180105.TAA24321@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86InstrInfo.def updated: 1.42 -> 1.43 --- Log message: Add reg clobber list for direct calls Represent empty use/def list as a null pointer --- Diffs of the changes: Index: llvm/lib/Target/X86/X86InstrInfo.def diff -u llvm/lib/Target/X86/X86InstrInfo.def:1.42 llvm/lib/Target/X86/X86InstrInfo.def:1.43 --- llvm/lib/Target/X86/X86InstrInfo.def:1.42 Mon Dec 16 09:54:42 2002 +++ llvm/lib/Target/X86/X86InstrInfo.def Tue Dec 17 19:05:31 2002 @@ -24,7 +24,7 @@ // Implicit register usage info: O_ is for one register, T_ is for two registers // NoIR means the instruction does not use implicit registers, in this form. -IMPREGSLIST(NoIR , 0) +#define NoIR 0 IMPREGSLIST(O_AL , X86::AL , 0) IMPREGSLIST(O_AH , X86::AH , 0) IMPREGSLIST(O_CL , X86::CL , 0) @@ -65,7 +65,7 @@ NoIR) // jne foo I(JE , "je", 0x84, M_BRANCH_FLAG, X86II::RawFrm | X86II::TB | X86II::Void, NoIR, NoIR) // je foo -I(CALLpcrel32 , "call", 0xE8, M_BRANCH_FLAG, X86II::Void, NoIR, NoIR) // call pc+42 +I(CALLpcrel32 , "call", 0xE8, M_BRANCH_FLAG, X86II::Void, NoIR, C_CLOBBER) // call pc+42 I(CALLr32 , "call", 0xFF, M_BRANCH_FLAG, X86II::Void | X86II::MRMS2r | X86II::Arg32, NoIR, C_CLOBBER) // call [r32] I(CALLm32 , "call", 0xFF, M_BRANCH_FLAG, X86II::Void | X86II::MRMS2m | X86II::Arg32, @@ -198,3 +198,5 @@ // At this point, I is dead, so undefine the macro #undef I +#undef NoIR + From lattner at cs.uiuc.edu Tue Dec 17 19:07:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Dec 17 19:07:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86InstrInfo.cpp Message-ID: <200212180106.TAA24335@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86InstrInfo.cpp updated: 1.10 -> 1.11 --- Log message: Add comments, switch uses/defs to match InstrInfo.def file --- Diffs of the changes: Index: llvm/lib/Target/X86/X86InstrInfo.cpp diff -u llvm/lib/Target/X86/X86InstrInfo.cpp:1.10 llvm/lib/Target/X86/X86InstrInfo.cpp:1.11 --- llvm/lib/Target/X86/X86InstrInfo.cpp:1.10 Mon Dec 2 23:42:53 2002 +++ llvm/lib/Target/X86/X86InstrInfo.cpp Tue Dec 17 19:05:54 2002 @@ -18,11 +18,19 @@ // descriptors // static const MachineInstrDescriptor X86Insts[] = { -#define I(ENUM, NAME, BASEOPCODE, FLAGS, TSFLAGS, IMPDEFS, IMPUSES) \ +#define I(ENUM, NAME, BASEOPCODE, FLAGS, TSFLAGS, IMPUSES, IMPDEFS) \ { NAME, \ -1, /* Always vararg */ \ ((TSFLAGS) & X86II::Void) ? -1 : 0, /* Result is in 0 */ \ - 0, false, 0, 0, TSFLAGS, FLAGS, TSFLAGS, IMPDEFS, IMPUSES }, + 0, /* maxImmedConst field */\ + false, /* immedIsSignExtended */\ + 0, /* numDelaySlots */\ + 0, /* latency */\ + 0, /* schedClass */\ + FLAGS, /* Flags */\ + TSFLAGS, /* TSFlags */\ + IMPUSES, /* ImplicitUses */\ + IMPDEFS }, /* ImplicitDefs */ #include "X86InstrInfo.def" }; From lattner at cs.uiuc.edu Tue Dec 17 19:12:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Dec 17 19:12:00 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocSimple.cpp Message-ID: <200212180111.TAA24443@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocSimple.cpp updated: 1.31 -> 1.32 --- Log message: Implicit defs/uses list may be empty. --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.31 llvm/lib/CodeGen/RegAllocSimple.cpp:1.32 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.31 Mon Dec 16 22:19:40 2002 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Tue Dec 17 19:11:14 2002 @@ -92,13 +92,13 @@ void invalidatePhysRegs(const MachineInstr *MI) { unsigned Opcode = MI->getOpcode(); const MachineInstrDescriptor &Desc = TM.getInstrInfo().get(Opcode); - const unsigned *regs = Desc.ImplicitUses; - while (*regs) - RegsUsed.insert(*regs++); + if (const unsigned *regs = Desc.ImplicitUses) + while (*regs) + RegsUsed.insert(*regs++); - regs = Desc.ImplicitDefs; - while (*regs) - RegsUsed.insert(*regs++); + if (const unsigned *regs = Desc.ImplicitDefs) + while (*regs) + RegsUsed.insert(*regs++); } void cleanupAfterFunction() { From lattner at cs.uiuc.edu Tue Dec 17 19:45:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Dec 17 19:45:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Message-ID: <200212180144.TAA24580@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.75 -> 1.76 --- Log message: Don't force setCC instructions into AL --- Diffs of the changes: Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.75 llvm/lib/Target/X86/InstSelectSimple.cpp:1.76 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.75 Mon Dec 16 17:36:57 2002 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Tue Dec 17 19:44:31 2002 @@ -437,10 +437,7 @@ {X86::SETEr, X86::SETNEr, X86::SETLr, X86::SETGr, X86::SETLEr, X86::SETGEr}, }; - BuildMI(BB, OpcodeTab[CompTy->isSigned()][OpNum], 0, X86::AL); - - // Put it in the result using a move. - BuildMI (BB, X86::MOVrr8, 1, getReg(I)).addReg(X86::AL); + BuildMI(BB, OpcodeTab[CompTy->isSigned()][OpNum], 0, getReg(I)); } /// promote32 - Emit instructions to turn a narrow operand into a 32-bit-wide From lattner at cs.uiuc.edu Tue Dec 17 20:08:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Dec 17 20:08:01 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/Jello/2002-12-16-ArgTest.ll Message-ID: <200212180207.UAA24901@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Jello: 2002-12-16-ArgTest.ll updated: 1.2 -> 1.3 --- Log message: Print argc as well as argv --- Diffs of the changes: Index: llvm/test/Regression/Jello/2002-12-16-ArgTest.ll diff -u llvm/test/Regression/Jello/2002-12-16-ArgTest.ll:1.2 llvm/test/Regression/Jello/2002-12-16-ArgTest.ll:1.3 --- llvm/test/Regression/Jello/2002-12-16-ArgTest.ll:1.2 Mon Dec 16 17:31:48 2002 +++ llvm/test/Regression/Jello/2002-12-16-ArgTest.ll Tue Dec 17 20:07:21 2002 @@ -1,9 +1,7 @@ -%.LC0 = internal global [14 x sbyte] c"in getoptions\00" ; <[14 x sbyte]*> [#uses=1] +%.LC0 = internal global [10 x sbyte] c"argc: %d\0A\00" implementation ; Functions: -void %__main() { ret void } - declare int %puts(sbyte*) void %getoptions(int* %argc) { @@ -11,12 +9,14 @@ ret void } +declare int %printf(sbyte*, ...) + int %main(int %argc, sbyte** %argv) { bb0: ; No predecessors! + call int (sbyte*, ...)* %printf( sbyte* getelementptr ([10 x sbyte]* %.LC0, long 0, long 0), int %argc) %cast224 = cast sbyte** %argv to sbyte* ; [#uses=1] %local = alloca sbyte* ; [#uses=3] store sbyte* %cast224, sbyte** %local - call void %__main( ) %cond226 = setle int %argc, 0 ; [#uses=1] br bool %cond226, label %bb3, label %bb2 From lattner at cs.uiuc.edu Wed Dec 18 02:15:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Dec 18 02:15:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAllocLocal.cpp Message-ID: <200212180814.CAA28291@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocLocal.cpp updated: 1.5 -> 1.6 --- Log message: * Fix several register aliasing bugs * Add a new option to eliminate spilling of registers that are only used within a basic block. --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAllocLocal.cpp diff -u llvm/lib/CodeGen/RegAllocLocal.cpp:1.5 llvm/lib/CodeGen/RegAllocLocal.cpp:1.6 --- llvm/lib/CodeGen/RegAllocLocal.cpp:1.5 Mon Dec 16 22:19:40 2002 +++ llvm/lib/CodeGen/RegAllocLocal.cpp Wed Dec 18 02:14:26 2002 @@ -10,11 +10,14 @@ #include "llvm/Target/MachineInstrInfo.h" #include "llvm/Target/TargetMachine.h" #include "Support/Statistic.h" +#include "Support/CommandLine.h" #include namespace { Statistic<> NumSpilled ("ra-local", "Number of registers spilled"); Statistic<> NumReloaded("ra-local", "Number of registers reloaded"); + cl::opt DisableKill("no-kill", cl::Hidden, + cl::desc("Disable register kill in local-ra")); class RA : public FunctionPass { TargetMachine &TM; @@ -49,15 +52,23 @@ // std::vector PhysRegsUseOrder; + // LastUserOf map - This multimap contains the set of registers that each + // key instruction is the last user of. If an instruction has an entry in + // this map, that means that the specified operands are killed after the + // instruction is executed, thus they don't need to be spilled into memory + // + std::multimap LastUserOf; + void MarkPhysRegRecentlyUsed(unsigned Reg) { - assert(std::find(PhysRegsUseOrder.begin(), PhysRegsUseOrder.end(), Reg) != - PhysRegsUseOrder.end() && "Register isn't used yet!"); + assert(!PhysRegsUseOrder.empty() && "No registers used!"); if (PhysRegsUseOrder.back() != Reg) { - for (unsigned i = PhysRegsUseOrder.size(); ; --i) - if (PhysRegsUseOrder[i-1] == Reg) { // remove from middle + for (unsigned i = PhysRegsUseOrder.size(); i != 0; --i) + if (areRegsEqual(Reg, PhysRegsUseOrder[i-1])) { // remove from middle + unsigned RegMatch = PhysRegsUseOrder[i-1]; PhysRegsUseOrder.erase(PhysRegsUseOrder.begin()+i-1); - PhysRegsUseOrder.push_back(Reg); // Add it to the end of the list - return; + PhysRegsUseOrder.push_back(RegMatch); // Add it to the end of the list + if (RegMatch == Reg) + return; // Found an exact match, exit early } } } @@ -88,6 +99,16 @@ /// in predecessor basic blocks. void EliminatePHINodes(MachineBasicBlock &MBB); + /// CalculateLastUseOfVReg - Calculate an approximation of the killing + /// uses for the virtual registers in the function. Here we try to capture + /// registers that are defined and only used within the same basic block. + /// Because we don't have use-def chains yet, we have to do this the hard + /// way. + /// + void CalculateLastUseOfVReg(MachineBasicBlock &MBB, + std::map &LastUseOfVReg) const; + + /// EmitPrologue/EmitEpilogue - Use the register info object to add a /// prologue/epilogue to the function and save/restore any callee saved /// registers we are responsible for. @@ -95,21 +116,23 @@ void EmitPrologue(); void EmitEpilogue(MachineBasicBlock &MBB); + /// areRegsEqual - This method returns true if the specified registers are + /// related to each other. To do this, it checks to see if they are equal + /// or if the first register is in the alias set of the second register. + /// + bool areRegsEqual(unsigned R1, unsigned R2) const { + if (R1 == R2) return true; + if (const unsigned *AliasSet = RegInfo.getAliasSet(R2)) + for (unsigned i = 0; AliasSet[i]; ++i) + if (AliasSet[i] == R1) return true; + return false; + } + /// isAllocatableRegister - A register may be used by the program if it's /// not the stack or frame pointer. bool isAllocatableRegister(unsigned R) const { unsigned FP = RegInfo.getFramePointer(), SP = RegInfo.getStackPointer(); - // Don't allocate the Frame or Stack pointers - if (R == FP || R == SP) - return false; - - // Check to see if this register aliases the stack or frame pointer... - if (const unsigned *AliasSet = RegInfo.getAliasSet(R)) { - for (unsigned i = 0; AliasSet[i]; ++i) - if (AliasSet[i] == FP || AliasSet[i] == SP) - return false; - } - return true; + return !areRegsEqual(FP, R) && !areRegsEqual(SP, R); } /// getStackSpaceFor - This returns the offset of the specified virtual @@ -122,6 +145,7 @@ NumBytesAllocated = 4; // FIXME: This is X86 specific } + void removePhysReg(unsigned PhysReg); /// spillVirtReg - This method spills the value specified by PhysReg into /// the virtual register slot specified by VirtReg. It then updates the RA @@ -136,8 +160,17 @@ void spillPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I, unsigned PhysReg) { std::map::iterator PI = PhysRegsUsed.find(PhysReg); - if (PI != PhysRegsUsed.end()) // Only spill it if it's used! + if (PI != PhysRegsUsed.end()) { // Only spill it if it's used! spillVirtReg(MBB, I, PI->second, PhysReg); + } else if (const unsigned *AliasSet = RegInfo.getAliasSet(PhysReg)) { + // If the selected register aliases any other registers, we must make sure + // that one of the aliases isn't alive... + for (unsigned i = 0; AliasSet[i]; ++i) { + PI = PhysRegsUsed.find(AliasSet[i]); + if (PI != PhysRegsUsed.end()) // Spill aliased register... + spillVirtReg(MBB, I, PI->second, AliasSet[i]); + } + } } void AssignVirtToPhysReg(unsigned VirtReg, unsigned PhysReg); @@ -146,7 +179,7 @@ /// free and available for use. This also includes checking to see if /// aliased registers are all free... /// - bool RA::isPhysRegAvailable(unsigned PhysReg) const; + bool isPhysRegAvailable(unsigned PhysReg) const; /// getFreeReg - Find a physical register to hold the specified virtual /// register. If all compatible physical registers are used, this method @@ -196,6 +229,19 @@ } +/// removePhysReg - This method marks the specified physical register as no +/// longer being in use. +/// +void RA::removePhysReg(unsigned PhysReg) { + PhysRegsUsed.erase(PhysReg); // PhyReg no longer used + + std::vector::iterator It = + std::find(PhysRegsUseOrder.begin(), PhysRegsUseOrder.end(), PhysReg); + assert(It != PhysRegsUseOrder.end() && + "Spilled a physical register, but it was not in use list!"); + PhysRegsUseOrder.erase(It); +} + /// spillVirtReg - This method spills the value specified by PhysReg into the /// virtual register slot specified by VirtReg. It then updates the RA data /// structures to indicate the fact that PhysReg is now available. @@ -213,13 +259,8 @@ ++NumSpilled; // Update statistics Virt2PhysRegMap.erase(VirtReg); // VirtReg no longer available } - PhysRegsUsed.erase(PhysReg); // PhyReg no longer used - std::vector::iterator It = - std::find(PhysRegsUseOrder.begin(), PhysRegsUseOrder.end(), PhysReg); - assert(It != PhysRegsUseOrder.end() && - "Spilled a physical register, but it was not in use list!"); - PhysRegsUseOrder.erase(It); + removePhysReg(PhysReg); } @@ -300,13 +341,6 @@ // At this point PhysRegsUseOrder[i] is the least recently used register of // compatible register class. Spill it to memory and reap its remains. spillPhysReg(MBB, I, PhysReg); - - // If the selected register aliases any other registers, we must make sure - // to spill them as well... - if (const unsigned *AliasSet = RegInfo.getAliasSet(PhysReg)) - for (unsigned i = 0; AliasSet[i]; ++i) - if (PhysRegsUsed.count(AliasSet[i])) // Spill aliased register... - spillPhysReg(MBB, I, AliasSet[i]); } // Now that we know which register we need to assign this to, do it now! @@ -352,6 +386,41 @@ return PhysReg; } +/// CalculateLastUseOfVReg - Calculate an approximation of the killing uses for +/// the virtual registers in the function. Here we try to capture registers +/// that are defined and only used within the same basic block. Because we +/// don't have use-def chains yet, we have to do this the hard way. +/// +void RA::CalculateLastUseOfVReg(MachineBasicBlock &MBB, + std::map &LastUseOfVReg) const { + // Calculate the last machine instruction in this basic block that uses the + // specified virtual register defined in this basic block. + std::map LastLocalUses; + + for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E;++I){ + MachineInstr *MI = *I; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &Op = MI->getOperand(i); + if (Op.isVirtualRegister()) { + if (Op.opIsDef()) { // Definition of a new virtual reg? + LastLocalUses[Op.getAllocatedRegNum()] = 0; // Record it + } else { // Use of a virtual reg. + std::map::iterator It = + LastLocalUses.find(Op.getAllocatedRegNum()); + if (It != LastLocalUses.end()) // Local use? + It->second = MI; // Update last use + else + LastUseOfVReg[Op.getAllocatedRegNum()] = 0; + } + } + } + } + + // Move local uses over... if there are any uses of a local already in the + // lastuse map, the newly inserted entry is ignored. + LastUseOfVReg.insert(LastLocalUses.begin(), LastLocalUses.end()); +} + /// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions in /// predecessor basic blocks. @@ -364,7 +433,6 @@ // Unlink the PHI node from the basic block... but don't delete the PHI yet MBB.erase(MBB.begin()); - DEBUG(std::cerr << "num ops: " << MI->getNumOperands() << "\n"); assert(MI->getOperand(0).isVirtualRegister() && "PHI node doesn't write virt reg?"); @@ -448,9 +516,15 @@ if (const unsigned *ImplicitDefs = MID.ImplicitDefs) for (unsigned i = 0; ImplicitDefs[i]; ++i) { unsigned Reg = ImplicitDefs[i]; - spillPhysReg(MBB, I, Reg); - PhysRegsUsed[Reg] = 0; // It's free now, and it's reserved - PhysRegsUseOrder.push_back(Reg); + + // We don't want to spill implicit definitions if they were explicitly + // chosen. For this reason, check to see now if the register we are + // to spill has a vreg of 0. + if (PhysRegsUsed.count(Reg) && PhysRegsUsed[Reg] != 0) { + spillPhysReg(MBB, I, Reg); + PhysRegsUsed[Reg] = 0; // It's free now, and it's reserved + PhysRegsUseOrder.push_back(Reg); + } } // Loop over the implicit uses, making sure that they are at the head of the @@ -475,7 +549,7 @@ // that would be destroyed by defs of this instruction. Loop over the // implicit defs and assign them to a register, spilling the incoming value // if we need to scavange a register. - + // for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) if (MI->getOperand(i).opIsDef() && !MI->getOperand(i).isPhysicalRegister()) { @@ -500,6 +574,23 @@ } MI->SetMachineOperandReg(i, DestPhysReg); // Assign the output register } + + if (!DisableKill) { + // If this instruction is the last user of anything in registers, kill the + // value, freeing the register being used, so it doesn't need to be spilled + // to memory at the end of the block. + std::multimap::iterator LUOI = + LastUserOf.lower_bound(MI); + for (; LUOI != LastUserOf.end() && LUOI->first == MI; ++MI) {// entry found? + unsigned VirtReg = LUOI->second; + unsigned PhysReg = Virt2PhysRegMap[VirtReg]; + if (PhysReg) { + DEBUG(std::cout << "V: " << VirtReg << " P: " << PhysReg << " Last use of: " << *MI); + removePhysReg(PhysReg); + } + Virt2PhysRegMap.erase(VirtReg); + } + } } // Rewind the iterator to point to the first flow control instruction... @@ -578,13 +669,30 @@ MF = &Fn; // First pass: eliminate PHI instructions by inserting copies into predecessor - // blocks. - // FIXME: In this pass, count how many uses of each VReg exist! + // blocks, and calculate a simple approximation of killing uses for virtual + // registers. + // + std::map LastUseOfVReg; for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); MBB != MBBe; ++MBB) { + if (!DisableKill) + CalculateLastUseOfVReg(*MBB, LastUseOfVReg); EliminatePHINodes(*MBB); } + // At this point LastUseOfVReg has been filled in to contain the last + // MachineInstr user of the specified virtual register, if that user is + // within the same basic block as the definition (otherwise it contains + // null). Invert this mapping now: + if (!DisableKill) + for (std::map::iterator I = LastUseOfVReg.begin(), + E = LastUseOfVReg.end(); I != E; ++I) + if (I->second) + LastUserOf.insert(std::make_pair(I->second, I->first)); + + // We're done with the temporary list now. + LastUseOfVReg.clear(); + // Loop over all of the basic blocks, eliminating virtual register references for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); MBB != MBBe; ++MBB) @@ -604,6 +712,7 @@ EmitEpilogue(*MBB); } + LastUserOf.clear(); cleanupAfterFunction(); return true; } From lattner at cs.uiuc.edu Thu Dec 19 22:13:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Dec 19 22:13:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/MachineCodeEmitter.cpp Message-ID: <200212200412.WAA00819@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: MachineCodeEmitter.cpp updated: 1.13 -> 1.14 --- Log message: fix warning --- Diffs of the changes: Index: llvm/lib/Target/X86/MachineCodeEmitter.cpp diff -u llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.13 llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.14 --- llvm/lib/Target/X86/MachineCodeEmitter.cpp:1.13 Sun Dec 15 15:13:40 2002 +++ llvm/lib/Target/X86/MachineCodeEmitter.cpp Thu Dec 19 22:12:48 2002 @@ -213,6 +213,7 @@ case X86II::Arg80: return 10; case X86II::Arg128: return 16; default: assert(0 && "Memory size not set!"); + return 0; } } From lattner at cs.uiuc.edu Thu Dec 19 22:14:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Dec 19 22:14:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86InstrInfo.def Message-ID: <200212200413.WAA00835@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86InstrInfo.def updated: 1.43 -> 1.44 --- Log message: CBW doesn't modify AL --- Diffs of the changes: Index: llvm/lib/Target/X86/X86InstrInfo.def diff -u llvm/lib/Target/X86/X86InstrInfo.def:1.43 llvm/lib/Target/X86/X86InstrInfo.def:1.44 --- llvm/lib/Target/X86/X86InstrInfo.def:1.43 Tue Dec 17 19:05:31 2002 +++ llvm/lib/Target/X86/X86InstrInfo.def Thu Dec 19 22:13:11 2002 @@ -184,7 +184,7 @@ I(CMPri8 , "cmp", 0x80, 0, X86II::MRMS7r | X86II::Arg8, NoIR, NoIR) // compare R8, imm8 // Sign extenders (first 3 are good for DIV/IDIV; the others are more general) -I(CBW , "cbw", 0x98, 0, X86II::RawFrm | X86II::OpSize, O_AL, O_AX) // AX = signext(AL) +I(CBW , "cbw", 0x98, 0, X86II::RawFrm | X86II::OpSize, O_AL, O_AH) // AX = signext(AL) I(CWD , "cwd", 0x99, 0, X86II::RawFrm, O_AX, O_DX) // DX:AX = signext(AX) I(CDQ , "cdq", 0x99, 0, X86II::RawFrm, O_EAX, O_EDX) // EDX:EAX = signext(EAX) I(MOVSXr16r8 , "movsx", 0xBE, 0, X86II::MRMSrcReg | X86II::TB | // R16 = signext(R8) From lattner at cs.uiuc.edu Thu Dec 19 22:14:02 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Dec 19 22:14:02 2002 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86RegisterInfo.cpp Message-ID: <200212200413.WAA00847@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86RegisterInfo.cpp updated: 1.22 -> 1.23 --- Log message: Fix warning --- Diffs of the changes: Index: llvm/lib/Target/X86/X86RegisterInfo.cpp diff -u llvm/lib/Target/X86/X86RegisterInfo.cpp:1.22 llvm/lib/Target/X86/X86RegisterInfo.cpp:1.23 --- llvm/lib/Target/X86/X86RegisterInfo.cpp:1.22 Mon Dec 16 22:19:17 2002 +++ llvm/lib/Target/X86/X86RegisterInfo.cpp Thu Dec 19 22:13:28 2002 @@ -14,12 +14,12 @@ unsigned getIdx(unsigned dataSize) { switch (dataSize) { + default: assert(0 && "Invalid data size!"); case 1: return 0; case 2: return 1; case 4: return 2; // FIXME: longs handled as ints case 8: return 2; - default: assert(0 && "Invalid data size!"); } } From lattner at cs.uiuc.edu Thu Dec 19 22:15:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Dec 19 22:15:01 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/Jello/Makefile Message-ID: <200212200414.WAA00860@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Jello: Makefile updated: 1.2 -> 1.3 --- Log message: Add stats output --- Diffs of the changes: Index: llvm/test/Regression/Jello/Makefile diff -u llvm/test/Regression/Jello/Makefile:1.2 llvm/test/Regression/Jello/Makefile:1.3 --- llvm/test/Regression/Jello/Makefile:1.2 Fri Nov 1 19:40:24 2002 +++ llvm/test/Regression/Jello/Makefile Thu Dec 19 22:14:19 2002 @@ -12,7 +12,7 @@ Output/%.out: Output/%.bc $(LJELLO) @echo "======== Running $< ===================" - $(VERB) jello $< > $@ 2>&1 || \ + $(VERB) jello -stats $< > $@ 2>&1 || \ ( cat $@; rm -f $@; $(FAILURE) $@ ) From lattner at cs.uiuc.edu Thu Dec 19 22:19:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Dec 19 22:19:00 2002 Subject: [llvm-commits] CVS: llvm/tools/lli/ExternalFunctions.cpp Message-ID: <200212200418.WAA01003@apoc.cs.uiuc.edu> Changes in directory llvm/tools/lli: ExternalFunctions.cpp updated: 1.39 -> 1.40 --- Log message: Add support for isnan --- Diffs of the changes: Index: llvm/tools/lli/ExternalFunctions.cpp diff -u llvm/tools/lli/ExternalFunctions.cpp:1.39 llvm/tools/lli/ExternalFunctions.cpp:1.40 --- llvm/tools/lli/ExternalFunctions.cpp:1.39 Wed Nov 20 12:35:26 2002 +++ llvm/tools/lli/ExternalFunctions.cpp Thu Dec 19 22:18:13 2002 @@ -272,6 +272,14 @@ return GV; } +// int isnan(double value); +GenericValue lle_X_isnan(FunctionType *F, const vector &Args) { + assert(Args.size() == 1); + GenericValue GV; + GV.IntVal = isnan(Args[0].DoubleVal); + return GV; +} + // double floor(double) GenericValue lle_X_floor(FunctionType *M, const vector &Args) { assert(Args.size() == 1); @@ -627,6 +635,7 @@ FuncNames["lle_X_pow"] = lle_X_pow; FuncNames["lle_X_exp"] = lle_X_exp; FuncNames["lle_X_log"] = lle_X_log; + FuncNames["lle_X_isnan"] = lle_X_isnan; FuncNames["lle_X_floor"] = lle_X_floor; FuncNames["lle_X_srand"] = lle_X_srand; FuncNames["lle_X_drand48"] = lle_X_drand48; From lattner at cs.uiuc.edu Sun Dec 22 12:54:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun Dec 22 12:54:01 2002 Subject: [llvm-commits] CVS: llvm/tools/jello/GlobalVars.cpp Message-ID: <200212221853.MAA03219@psmith.cs.uiuc.edu> Changes in directory llvm/tools/jello: GlobalVars.cpp updated: 1.3 -> 1.4 --- Log message: brg Add statistic for number of bytes of data area initialized. We used this statistic in collecting data for the paper, but I forgot to commit it. --- Diffs of the changes: Index: llvm/tools/jello/GlobalVars.cpp diff -u llvm/tools/jello/GlobalVars.cpp:1.3 llvm/tools/jello/GlobalVars.cpp:1.4 --- llvm/tools/jello/GlobalVars.cpp:1.3 Fri Dec 13 07:15:36 2002 +++ llvm/tools/jello/GlobalVars.cpp Sun Dec 22 12:53:23 2002 @@ -12,6 +12,8 @@ #include "VM.h" #include +Statistic<> NumInitBytes("jello", "Number of bytes of data area initialized"); + /// EmitGlobals - Emit all of the global variables to memory, storing their /// addresses into GlobalAddress. This must make sure to copy the contents of /// their initializers into the memory. @@ -48,6 +50,7 @@ /// void VM::emitConstantToMemory(Constant *Init, void *Addr) { const TargetData &TD = TM.getTargetData(); + NumInitBytes += TD.getTypeSize (Init->getType ()); if (ConstantIntegral *CI = dyn_cast(Init)) { switch (CI->getType()->getPrimitiveID()) { case Type::BoolTyID: