From lattner at cs.uiuc.edu Mon May 26 13:39:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon May 26 13:39:01 2003 Subject: [llvm-commits] CVS: llvm/www/pubs/2003-05-01-GCCSummit2003.html Message-ID: <200305261838.NAA04738@tank.cs.uiuc.edu> Changes in directory llvm/www/pubs: 2003-05-01-GCCSummit2003.html updated: 1.4 -> 1.5 --- Log message: Update to include links to the presentation --- Diffs of the changes: Index: llvm/www/pubs/2003-05-01-GCCSummit2003.html diff -u llvm/www/pubs/2003-05-01-GCCSummit2003.html:1.4 llvm/www/pubs/2003-05-01-GCCSummit2003.html:1.5 --- llvm/www/pubs/2003-05-01-GCCSummit2003.html:1.4 Fri May 2 12:33:50 2003 +++ llvm/www/pubs/2003-05-01-GCCSummit2003.html Mon May 26 13:37:55 2003 @@ -46,6 +46,12 @@
  • Architecture for a Next-Generation GCC (PDF) +Presentation: + +

    Bibtex Entry:

       @inproceedings{LattnerAdve:GCCSummit03,
    
    
    
    
    From lattner at cs.uiuc.edu  Mon May 26 13:40:01 2003
    From: lattner at cs.uiuc.edu (Chris Lattner)
    Date: Mon May 26 13:40:01 2003
    Subject: [llvm-commits] CVS: llvm/www/pubs/2003-05-01-GCCSummit2003.html
    Message-ID: <200305261839.NAA04770@tank.cs.uiuc.edu>
    
    
    Changes in directory llvm/www/pubs:
    
    2003-05-01-GCCSummit2003.html updated: 1.5 -> 1.6
    
    ---
    Log message:
    
    Correct link
    
    
    ---
    Diffs of the changes:
    
    Index: llvm/www/pubs/2003-05-01-GCCSummit2003.html
    diff -u llvm/www/pubs/2003-05-01-GCCSummit2003.html:1.5 llvm/www/pubs/2003-05-01-GCCSummit2003.html:1.6
    --- llvm/www/pubs/2003-05-01-GCCSummit2003.html:1.5	Mon May 26 13:37:55 2003
    +++ llvm/www/pubs/2003-05-01-GCCSummit2003.html	Mon May 26 13:39:42 2003
    @@ -48,8 +48,8 @@
     
     Presentation:
     
     
     

    Bibtex Entry:

    From vadve at cs.uiuc.edu Mon May 26 17:04:00 2003 From: vadve at cs.uiuc.edu (Vikram Adve) Date: Mon May 26 17:04:00 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/SingleSource/UnitTests/2003-05-26-Shorts.c Message-ID: <200305262203.RAA29070@trinity.cs.uiuc.edu> Changes in directory llvm/test/Programs/SingleSource/UnitTests: 2003-05-26-Shorts.c added (r1.1) --- Log message: Unit test for handling of short signed and unsigned integers less than a word size, especially in -, * and / operations. --- Diffs of the changes: Index: llvm/test/Programs/SingleSource/UnitTests/2003-05-26-Shorts.c diff -c /dev/null llvm/test/Programs/SingleSource/UnitTests/2003-05-26-Shorts.c:1.1 *** /dev/null Mon May 26 17:03:36 2003 --- llvm/test/Programs/SingleSource/UnitTests/2003-05-26-Shorts.c Mon May 26 17:03:25 2003 *************** *** 0 **** --- 1,54 ---- + /* + * This test stresses masking and sign-extension for operations on + * signed and unsigned types less than the machine integer reg. size. + * Several things have to happen correctly: + * -- correct constant folding if it is done at compile-time + * -- correct sign-extensions during native code generation for -, * and /. + * -- correct handling of high bits during native code generation for + * a sequence of operations involving -, * and /. + */ + #include + #include + #include + + int + main(int argc, char** argv) + { + unsigned long UL = 0xafafafafc5c5b8a3; + long L = (long) UL; + + unsigned int ui = (unsigned int) UL; /* 0xc5c5b8a3 = 3318069411 */ + int i = (int) UL; /* 0xc5c5b8a3 = -976897885 */ + + unsigned short us = (unsigned short) UL; /* 0xb8a3 = 47267 */ + short s = (short) UL; /* 0xb8a3 = -18269 */ + + uint8_t ub = (uint8_t) UL; /* 0xa3 = 163 */ + int8_t b = ( int8_t) UL; /* 0xa3 = -93 */ + + printf(" ui = %u (0x%x)\t\tUL-ui = %ld (0x%x)\n", ui, ui, UL-ui, UL-ui); + printf("ui*ui = %u (0x%x)\t UL/ui = %ld (0x%x)\n\n", + (unsigned int) ui*ui, (unsigned int) ui*ui, UL/ui, UL/ui); + + printf(" i = %d (0x%x)\tL-i = %ld (0x%x)\n", i, i, L-i, L-i); + printf(" i* i = %d (0x%x)\tL/ i = %ld (0x%x)\n\n", + (int) i*i, (int) i*i, L/i, L/i); + + printf("us = %u (0x%x)\t\tUL-us = %ld (0x%x)\n", us, us, UL-us, UL-us); + printf("us*us = %u (0x%x)\t UL/us = %ld (0x%x)\n\n", + (unsigned short) us*us, (unsigned short) us*us, UL/us, UL/us); + + printf(" s = %d (0x%x)\tL-s = %ld (0x%x)\n", s, s, L-s, L-s); + printf(" s* s = %d (0x%x)\tL/ s = %ld (0x%x)\n\n", + (short) s*s, (short) s*s, L/s, L/s); + + printf("ub = %u (0x%x)\t\tUL-ub = %ld (0x%x)\n", ub, ub, UL-ub, UL-ub); + printf("ub*ub = %u (0x%x)\t\tUL/ub = %ld (0x%x)\n\n", + (uint8_t) ub*ub, (uint8_t) ub*ub, UL/ub, UL/ub); + + printf(" b = %d (0x%x)\t\tL-b = %ld (0x%x)\n", b, b, L-b, L-b); + printf(" b* b = %d (0x%x)\t\t\tL/b = %ld (0x%x)\n\n", + (int8_t) b*b, (int8_t) b*b, L/b, L/b); + + return 0; + } From lattner at cs.uiuc.edu Mon May 26 18:42:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon May 26 18:42:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200305262341.SAA21498@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.83 -> 1.84 --- Log message: Fix bug: InstCombine/2003-05-26-CastMiscompile.ll --- Diffs of the changes: Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.83 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.84 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.83 Thu May 22 14:07:21 2003 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Mon May 26 18:41:32 2003 @@ -897,7 +897,7 @@ CSrc->getType()->getPrimitiveSize() < CI.getType()->getPrimitiveSize()){ assert(CSrc->getType() != Type::ULongTy && "Cannot have type bigger than ulong!"); - unsigned AndValue = (1U << CSrc->getType()->getPrimitiveSize()*8)-1; + uint64_t AndValue = (1ULL << CSrc->getType()->getPrimitiveSize()*8)-1; Constant *AndOp = ConstantUInt::get(CI.getType(), AndValue); return BinaryOperator::create(Instruction::And, CSrc->getOperand(0), AndOp); From lattner at cs.uiuc.edu Mon May 26 18:42:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon May 26 18:42:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/InstCombine/2003-05-26-CastMiscompile.ll Message-ID: <200305262341.SAA21488@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/InstCombine: 2003-05-26-CastMiscompile.ll added (r1.1) --- Log message: New testcase --- Diffs of the changes: Index: llvm/test/Regression/Transforms/InstCombine/2003-05-26-CastMiscompile.ll diff -c /dev/null llvm/test/Regression/Transforms/InstCombine/2003-05-26-CastMiscompile.ll:1.1 *** /dev/null Mon May 26 18:41:23 2003 --- llvm/test/Regression/Transforms/InstCombine/2003-05-26-CastMiscompile.ll Mon May 26 18:41:13 2003 *************** *** 0 **** --- 1,7 ---- + ; RUN: as < %s | opt -instcombine | dis | grep 4294967295 + + ulong %test(ulong %Val) { + %tmp.3 = cast ulong %Val to uint ; [#uses=1] + %tmp.8 = cast uint %tmp.3 to ulong ; [#uses=1] + ret ulong %tmp.8 + } From vadve at cs.uiuc.edu Mon May 26 19:03:01 2003 From: vadve at cs.uiuc.edu (Vikram Adve) Date: Mon May 26 19:03:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/EmitAssembly.cpp SparcInstrSelection.cpp SparcInternals.h SparcOptInfo.cpp SparcRegClassInfo.h SparcRegInfo.cpp Message-ID: <200305270002.TAA30652@psmith.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: EmitAssembly.cpp updated: 1.75 -> 1.76 SparcInstrSelection.cpp updated: 1.93 -> 1.94 SparcInternals.h updated: 1.84 -> 1.85 SparcOptInfo.cpp updated: 1.6 -> 1.7 SparcRegClassInfo.h updated: 1.15 -> 1.16 SparcRegInfo.cpp updated: 1.93 -> 1.94 --- Log message: Added special register class containing (for now) %fsr. Fixed spilling of %fcc[0-3] which are part of %fsr. Moved some machine-independent reg-class code to class TargetRegInfo from SparcReg{Class,}Info. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/EmitAssembly.cpp diff -u llvm/lib/Target/Sparc/EmitAssembly.cpp:1.75 llvm/lib/Target/Sparc/EmitAssembly.cpp:1.76 --- llvm/lib/Target/Sparc/EmitAssembly.cpp:1.75 Sun May 25 16:59:09 2003 +++ llvm/lib/Target/Sparc/EmitAssembly.cpp Mon May 26 19:02:22 2003 @@ -302,7 +302,7 @@ void emitMachineInst(const MachineInstr *MI); unsigned int printOperands(const MachineInstr *MI, unsigned int opNum); - void printOneOperand(const MachineOperand &Op); + void printOneOperand(const MachineOperand &Op, MachineOpCode opCode); bool OpIsBranchTargetLabel(const MachineInstr *MI, unsigned int opNum); bool OpIsMemoryAddressBase(const MachineInstr *MI, unsigned int opNum); @@ -341,10 +341,10 @@ } -#define PrintOp1PlusOp2(mop1, mop2) \ - printOneOperand(mop1); \ +#define PrintOp1PlusOp2(mop1, mop2, opCode) \ + printOneOperand(mop1, opCode); \ toAsm << "+"; \ - printOneOperand(mop2); + printOneOperand(mop2, opCode); unsigned int SparcFunctionAsmPrinter::printOperands(const MachineInstr *MI, @@ -354,26 +354,26 @@ if (OpIsBranchTargetLabel(MI, opNum)) { - PrintOp1PlusOp2(mop, MI->getOperand(opNum+1)); + PrintOp1PlusOp2(mop, MI->getOperand(opNum+1), MI->getOpCode()); return 2; } else if (OpIsMemoryAddressBase(MI, opNum)) { toAsm << "["; - PrintOp1PlusOp2(mop, MI->getOperand(opNum+1)); + PrintOp1PlusOp2(mop, MI->getOperand(opNum+1), MI->getOpCode()); toAsm << "]"; return 2; } else { - printOneOperand(mop); + printOneOperand(mop, MI->getOpCode()); return 1; } } - void -SparcFunctionAsmPrinter::printOneOperand(const MachineOperand &mop) +SparcFunctionAsmPrinter::printOneOperand(const MachineOperand &mop, + MachineOpCode opCode) { bool needBitsFlag = true; @@ -394,13 +394,13 @@ case MachineOperand::MO_CCRegister: case MachineOperand::MO_MachineRegister: { - int RegNum = (int)mop.getAllocatedRegNum(); + int regNum = (int)mop.getAllocatedRegNum(); - // better to print code with NULL registers than to die - if (RegNum == Target.getRegInfo().getInvalidRegNum()) { + if (regNum == Target.getRegInfo().getInvalidRegNum()) { + // better to print code with NULL registers than to die toAsm << ""; } else { - toAsm << "%" << Target.getRegInfo().getUnifiedRegName(RegNum); + toAsm << "%" << Target.getRegInfo().getUnifiedRegName(regNum); } break; } Index: llvm/lib/Target/Sparc/SparcInstrSelection.cpp diff -u llvm/lib/Target/Sparc/SparcInstrSelection.cpp:1.93 llvm/lib/Target/Sparc/SparcInstrSelection.cpp:1.94 --- llvm/lib/Target/Sparc/SparcInstrSelection.cpp:1.93 Sun May 25 16:59:47 2003 +++ llvm/lib/Target/Sparc/SparcInstrSelection.cpp Mon May 26 19:02:22 2003 @@ -1318,8 +1318,8 @@ for (unsigned i=0,numOps=minstr->getNumImplicitRefs(); igetImplicitRef(i) == unusedOp) minstr->setImplicitRef(i, fwdOp, - minstr->implicitRefIsDefined(i), - minstr->implicitRefIsDefinedAndUsed(i)); + minstr->getImplicitOp(i).opIsDefOnly(), + minstr->getImplicitOp(i).opIsDefAndUse()); } } } Index: llvm/lib/Target/Sparc/SparcInternals.h diff -u llvm/lib/Target/Sparc/SparcInternals.h:1.84 llvm/lib/Target/Sparc/SparcInternals.h:1.85 --- llvm/lib/Target/Sparc/SparcInternals.h:1.84 Sun May 25 10:59:47 2003 +++ llvm/lib/Target/Sparc/SparcInternals.h Mon May 26 19:02:22 2003 @@ -255,7 +255,8 @@ IntRegClassID, // Integer FloatRegClassID, // Float (both single/double) IntCCRegClassID, // Int Condition Code - FloatCCRegClassID // Float Condition code + FloatCCRegClassID, // Float Condition code + SpecialRegClassID // Special (unallocated) registers }; @@ -268,7 +269,8 @@ FPSingleRegType, FPDoubleRegType, IntCCRegType, - FloatCCRegType + FloatCCRegType, + SpecialRegType }; // **** WARNING: If the above enum order is changed, also modify @@ -308,6 +310,9 @@ std::vector& AddedInstrnsBefore) const; + // Get the register type for a register identified different ways. + // The first function is a helper used by the all the hoter functions. + int getRegTypeForClassAndType(unsigned regClassID, const Type* type) const; int getRegType(const Type* type) const; int getRegType(const LiveRange *LR) const; int getRegType(int unifiedRegNum) const; @@ -352,7 +357,6 @@ // To find the register class to which a specified register belongs // - unsigned getRegClassIDOfReg(int unifiedRegNum) const; unsigned getRegClassIDOfRegType(int regType) const; // getZeroRegNum - returns the register that contains always zero this is the @@ -403,56 +407,8 @@ // method used for printing a register for debugging purposes // - static void printReg(const LiveRange *LR); - - // Each register class has a seperate space for register IDs. To convert - // a regId in a register class to a common Id, or vice versa, - // we use the folloing methods. - // - // This method provides a unique number for each register - inline int getUnifiedRegNum(unsigned regClassID, int reg) const { - - if (regClassID == IntRegClassID) { - assert(reg < 32 && "Invalid reg. number"); - return reg; - } - else if (regClassID == FloatRegClassID) { - assert(reg < 64 && "Invalid reg. number"); - return reg + 32; // we have 32 int regs - } - else if (regClassID == FloatCCRegClassID) { - assert(reg < 4 && "Invalid reg. number"); - return reg + 32 + 64; // 32 int, 64 float - } - else if (regClassID == IntCCRegClassID ) { - assert(reg == 0 && "Invalid reg. number"); - return reg + 4+ 32 + 64; // only one int CC reg - } - else if (reg==InvalidRegNum) { - return InvalidRegNum; - } - else - assert(0 && "Invalid register class"); - return 0; - } - - // This method converts the unified number to the number in its class, - // and returns the class ID in regClassID. - inline int getClassRegNum(int ureg, unsigned& regClassID) const { - if (ureg < 32) { regClassID = IntRegClassID; return ureg; } - else if (ureg < 32+64) { regClassID = FloatRegClassID; return ureg-32; } - else if (ureg < 4 +96) { regClassID = FloatCCRegClassID; return ureg-96; } - else if (ureg < 1 +100) { regClassID = IntCCRegClassID; return ureg-100;} - else if (ureg == InvalidRegNum) { return InvalidRegNum; } - else { assert(0 && "Invalid unified register number"); } - return 0; - } + void printReg(const LiveRange *LR) const; - // Returns the assembly-language name of the specified machine register. - // - virtual const char * const getUnifiedRegName(int reg) const; - - // returns the # of bytes of stack space allocated for each register // type. For Sparc, currently we allocate 8 bytes on stack for all // register types. We can optimize this later if necessary to save stack Index: llvm/lib/Target/Sparc/SparcOptInfo.cpp diff -u llvm/lib/Target/Sparc/SparcOptInfo.cpp:1.6 llvm/lib/Target/Sparc/SparcOptInfo.cpp:1.7 --- llvm/lib/Target/Sparc/SparcOptInfo.cpp:1.6 Tue May 20 15:32:24 2003 +++ llvm/lib/Target/Sparc/SparcOptInfo.cpp Mon May 26 19:02:22 2003 @@ -45,7 +45,7 @@ target.getRegInfo().getZeroRegNum()) || /* or operand otherOp == 0 */ - (MI->getOperandType(otherOp) + (MI->getOperand(otherOp).getType() == MachineOperand::MO_SignExtendedImmed && MI->getOperand(otherOp).getImmedValue() == 0)); } Index: llvm/lib/Target/Sparc/SparcRegClassInfo.h diff -u llvm/lib/Target/Sparc/SparcRegClassInfo.h:1.15 llvm/lib/Target/Sparc/SparcRegClassInfo.h:1.16 --- llvm/lib/Target/Sparc/SparcRegClassInfo.h:1.15 Sat Dec 28 21:13:02 2002 +++ llvm/lib/Target/Sparc/SparcRegClassInfo.h Mon May 26 19:02:22 2003 @@ -63,7 +63,7 @@ StartOfAllRegs = o0, }; - static const char * const getRegName(unsigned reg); + const char * const getRegName(unsigned reg) const; }; @@ -104,7 +104,7 @@ StartOfAllRegs = f0, }; - static const char * const getRegName(unsigned reg); + const char * const getRegName(unsigned reg) const; }; @@ -138,7 +138,7 @@ xcc, ccr // only one is available - see the note above }; - static const char * const getRegName(unsigned reg); + const char * const getRegName(unsigned reg) const; }; @@ -146,12 +146,12 @@ //----------------------------------------------------------------------------- // Float CC Register Class -// Only 4 Float CC registers are available +// Only 4 Float CC registers are available for allocation. //----------------------------------------------------------------------------- struct SparcFloatCCRegClass : public TargetRegClassInfo { SparcFloatCCRegClass(unsigned ID) - : TargetRegClassInfo(ID, 4, 4) { } + : TargetRegClassInfo(ID, 4, 5) { } void colorIGNode(IGNode *Node, std::vector &IsColorUsedArr) const { for(unsigned c = 0; c != 4; ++c) @@ -168,10 +168,33 @@ inline bool isRegVolatile(int Reg) const { return true; } enum { - fcc0, fcc1, fcc2, fcc3 + fcc0, fcc1, fcc2, fcc3, fsr // fsr is not used in allocation + }; // but has a name in getRegName() + + const char * const getRegName(unsigned reg) const; +}; + +//----------------------------------------------------------------------------- +// Sparc special register class. These registers are not used for allocation +// but are used as arguments of some instructions. +//----------------------------------------------------------------------------- + +struct SparcSpecialRegClass : public TargetRegClassInfo { + SparcSpecialRegClass(unsigned ID) + : TargetRegClassInfo(ID, 0, 1) { } + + void colorIGNode(IGNode *Node, std::vector &IsColorUsedArr) const { + assert(0 && "SparcSpecialRegClass should never be used for allocation"); + } + + // all currently included special regs are volatile + inline bool isRegVolatile(int Reg) const { return true; } + + enum { + fsr // floating point state register }; - static const char * const getRegName(unsigned reg); + const char * const getRegName(unsigned reg) const; }; #endif Index: llvm/lib/Target/Sparc/SparcRegInfo.cpp diff -u llvm/lib/Target/Sparc/SparcRegInfo.cpp:1.93 llvm/lib/Target/Sparc/SparcRegInfo.cpp:1.94 --- llvm/lib/Target/Sparc/SparcRegInfo.cpp:1.93 Wed May 21 12:59:06 2003 +++ llvm/lib/Target/Sparc/SparcRegInfo.cpp Mon May 26 19:02:22 2003 @@ -32,6 +32,7 @@ MachineRegClassArr.push_back(new SparcFloatRegClass(FloatRegClassID)); MachineRegClassArr.push_back(new SparcIntCCRegClass(IntCCRegClassID)); MachineRegClassArr.push_back(new SparcFloatCCRegClass(FloatCCRegClassID)); + MachineRegClassArr.push_back(new SparcSpecialRegClass(SpecialRegClassID)); assert(SparcFloatRegClass::StartOfNonVolatileRegs == 32 && "32 Float regs are used for float arg passing"); @@ -75,7 +76,7 @@ "o6" }; -const char * const SparcIntRegClass::getRegName(unsigned reg) { +const char * const SparcIntRegClass::getRegName(unsigned reg) const { assert(reg < NumOfAllRegs); return IntRegNames[reg]; } @@ -90,7 +91,7 @@ "f60", "f61", "f62", "f63" }; -const char * const SparcFloatRegClass::getRegName(unsigned reg) { +const char * const SparcFloatRegClass::getRegName(unsigned reg) const { assert (reg < NumOfAllRegs); return FloatRegNames[reg]; } @@ -100,7 +101,7 @@ "xcc", "ccr" }; -const char * const SparcIntCCRegClass::getRegName(unsigned reg) { +const char * const SparcIntCCRegClass::getRegName(unsigned reg) const { assert(reg < 2); return IntCCRegNames[reg]; } @@ -109,28 +110,18 @@ "fcc0", "fcc1", "fcc2", "fcc3" }; -const char * const SparcFloatCCRegClass::getRegName(unsigned reg) { - assert (reg < 4); +const char * const SparcFloatCCRegClass::getRegName(unsigned reg) const { + assert (reg < 5); return FloatCCRegNames[reg]; } -// given the unified register number, this gives the name -// for generating assembly code or debugging. -// -const char * const UltraSparcRegInfo::getUnifiedRegName(int reg) const { - if( reg < 32 ) - return SparcIntRegClass::getRegName(reg); - else if ( reg < (64 + 32) ) - return SparcFloatRegClass::getRegName( reg - 32); - else if( reg < (64+32+4) ) - return SparcFloatCCRegClass::getRegName( reg -32 - 64); - else if( reg < (64+32+4+2) ) // two names: %xcc and %ccr - return SparcIntCCRegClass::getRegName( reg -32 - 64 - 4); - else if (reg== InvalidRegNum) //****** TODO: Remove */ - return "<*NoReg*>"; - else - assert(0 && "Invalid register number"); - return ""; +static const char * const SpecialRegNames[] = { + "fsr" +}; + +const char * const SparcSpecialRegClass::getRegName(unsigned reg) const { + assert (reg < 1); + return SpecialRegNames[reg]; } // Get unified reg number for frame pointer @@ -230,43 +221,34 @@ // The following 4 methods are used to find the RegType (SparcInternals.h) // of a LiveRange, a Value, and for a given register unified reg number. // -int UltraSparcRegInfo::getRegType(const Type* type) const { - unsigned regClassID = getRegClassIDOfType(type); +int UltraSparcRegInfo::getRegTypeForClassAndType(unsigned regClassID, + const Type* type) const +{ switch (regClassID) { - case IntRegClassID: return IntRegType; - case FloatRegClassID: { - if (type == Type::FloatTy) - return FPSingleRegType; - else if (type == Type::DoubleTy) - return FPDoubleRegType; - assert(0 && "Unknown type in FloatRegClass"); - } - case IntCCRegClassID: return IntCCRegType; - case FloatCCRegClassID: return FloatCCRegType; + case IntRegClassID: return IntRegType; + case FloatRegClassID: + if (type == Type::FloatTy) return FPSingleRegType; + else if (type == Type::DoubleTy) return FPDoubleRegType; + assert(0 && "Unknown type in FloatRegClass"); return 0; + case IntCCRegClassID: return IntCCRegType; + case FloatCCRegClassID: return FloatCCRegType; + case SpecialRegClassID: return SpecialRegType; default: assert( 0 && "Unknown reg class ID"); return 0; } } -int UltraSparcRegInfo::getRegType(const LiveRange *LR) const { - const Type* type = LR->getType(); - - unsigned regClassID = LR->getRegClassID(); - switch (regClassID) { - default: assert( 0 && "Unknown reg class ID"); - case IntRegClassID: return IntRegType; - case FloatRegClassID: - if (type == Type::FloatTy) - return FPSingleRegType; - else if (type == Type::DoubleTy) - return FPDoubleRegType; - assert(0 && "Unknown type in FloatRegClass"); - case IntCCRegClassID: return IntCCRegType; - case FloatCCRegClassID: return FloatCCRegType; - } +int UltraSparcRegInfo::getRegType(const Type* type) const +{ + return getRegTypeForClassAndType(getRegClassIDOfType(type), type); } +int UltraSparcRegInfo::getRegType(const LiveRange *LR) const +{ + return getRegTypeForClassAndType(LR->getRegClassID(), LR->getType()); +} -int UltraSparcRegInfo::getRegType(int unifiedRegNum) const { +int UltraSparcRegInfo::getRegType(int unifiedRegNum) const +{ if (unifiedRegNum < 32) return IntRegType; else if (unifiedRegNum < (32 + 32)) @@ -308,14 +290,6 @@ return res; } -// To find the register class to which a specified register belongs -// -unsigned UltraSparcRegInfo::getRegClassIDOfReg(int unifiedRegNum) const { - unsigned classId = 0; - (void) getClassRegNum(unifiedRegNum, classId); - return classId; -} - unsigned UltraSparcRegInfo::getRegClassIDOfRegType(int regType) const { switch(regType) { case IntRegType: return IntRegClassID; @@ -1183,13 +1157,14 @@ cpReg2MemMI(mvec, scratchReg, DestPtrReg, Offset, IntRegType); return; - case FloatCCRegType: - assert(0 && "Tell Vikram if this assertion fails: we may have to mask out the other bits here"); + case FloatCCRegType: { assert(target.getInstrInfo().constantFitsInImmedField(V9::STXFSR, Offset)); - MI = BuildMI(V9::STXFSR, 3).addMReg(SrcReg).addMReg(DestPtrReg) - .addSImm(Offset); + unsigned fsrRegNum = getUnifiedRegNum(UltraSparcRegInfo::SpecialRegClassID, + SparcSpecialRegClass::fsr); + MI = BuildMI(V9::STXFSR, 3) + .addMReg(fsrRegNum).addMReg(DestPtrReg).addSImm(Offset); break; - + } default: assert(0 && "Unknown RegType in cpReg2MemMI"); } @@ -1239,14 +1214,14 @@ MI = BuildMI(V9::WRCCR, 2).addMReg(scratchReg).addMReg(DestReg+1,MOTy::Def); break; - case FloatCCRegType: - assert(0 && "Tell Vikram if this assertion fails: we may have to mask " - "out the other bits here"); + case FloatCCRegType: { assert(target.getInstrInfo().constantFitsInImmedField(V9::LDXFSR, Offset)); + unsigned fsrRegNum = getUnifiedRegNum(UltraSparcRegInfo::SpecialRegClassID, + SparcSpecialRegClass::fsr); MI = BuildMI(V9::LDXFSR, 3).addMReg(SrcPtrReg).addSImm(Offset) - .addMReg(DestReg, MOTy::Def); + .addMReg(fsrRegNum, MOTy::UseAndDef); break; - + } default: assert(0 && "Unknown RegType in cpMem2RegMI"); } @@ -1462,7 +1437,7 @@ // Print the register assigned to a LR //--------------------------------------------------------------------------- -void UltraSparcRegInfo::printReg(const LiveRange *LR) { +void UltraSparcRegInfo::printReg(const LiveRange *LR) const { unsigned RegClassID = LR->getRegClassID(); std::cerr << " *Node " << (LR->getUserIGNode())->getIndex(); @@ -1475,15 +1450,13 @@ std::cerr << " colored with color "<< LR->getColor(); - if (RegClassID == IntRegClassID) { - std::cerr<< " [" << SparcIntRegClass::getRegName(LR->getColor()) << "]\n"; - - } else if (RegClassID == FloatRegClassID) { - std::cerr << "[" << SparcFloatRegClass::getRegName(LR->getColor()); - if( LR->getType() == Type::DoubleTy) - std::cerr << "+" << SparcFloatRegClass::getRegName(LR->getColor()+1); - std::cerr << "]\n"; - } + unsigned uRegName = getUnifiedRegNum(RegClassID, LR->getColor()); + + std::cerr << "["; + std::cerr<< getUnifiedRegName(uRegName); + if (RegClassID == FloatRegClassID && LR->getType() == Type::DoubleTy) + std::cerr << "+" << getUnifiedRegName(uRegName+1); + std::cerr << "]\n"; } //--------------------------------------------------------------------------- @@ -1559,7 +1532,7 @@ // last operand is the def (unless for a store which has no def reg) MachineOperand& DefOp = DefInst->getOperand(DefInst->getNumOperands()-1); - if (DefOp.opIsDef() && + if ((DefOp.opIsDefOnly() || DefOp.opIsDefAndUse()) && DefOp.getType() == MachineOperand::MO_MachineRegister) { // If the operand in DefInst is a def ... @@ -1576,7 +1549,7 @@ // for each inst (UseInst) that is below the DefInst do ... MachineOperand& UseOp = UseInst->getOperand(0); - if (!UseOp.opIsDef() && + if (!UseOp.opIsDefOnly() && UseOp.getType() == MachineOperand::MO_MachineRegister) { // if use is a register ... @@ -1637,7 +1610,7 @@ PhyRegAlloc &PRA) const { MachineOperand& UseOp = UnordInst->getOperand(0); - if (!UseOp.opIsDef() && + if (!UseOp.opIsDefOnly() && UseOp.getType() == MachineOperand::MO_MachineRegister) { // for the use of UnordInst, see whether there is a defining instr @@ -1653,7 +1626,7 @@ MachineOperand& DefOp = OrdInst->getOperand(OrdInst->getNumOperands()-1); - if( DefOp.opIsDef() && + if( (DefOp.opIsDefOnly() || DefOp.opIsDefAndUse()) && DefOp.getType() == MachineOperand::MO_MachineRegister) { //std::cerr << "\nDefining Ord Inst: " << *OrdInst; @@ -1686,7 +1659,8 @@ // Load directly into DReg (%oy) MachineOperand& DOp= (UnordInst->getOperand(UnordInst->getNumOperands()-1)); - assert(DOp.opIsDef() && "Last operand is not the def"); + assert((DOp.opIsDefOnly() || DefOp.opIsDefAndUse()) && + "Last operand is not the def"); const int DReg = DOp.getMachineRegNum(); cpMem2RegMI(OrdVec, getFramePointer(), StackOff, DReg, RegType); From vadve at cs.uiuc.edu Mon May 26 19:04:01 2003 From: vadve at cs.uiuc.edu (Vikram Adve) Date: Mon May 26 19:04:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/Printer.cpp Message-ID: <200305270003.TAA30702@psmith.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: Printer.cpp updated: 1.34 -> 1.35 --- Log message: Renamed opIsDef to opIsDefOnly. --- Diffs of the changes: Index: llvm/lib/Target/X86/Printer.cpp diff -u llvm/lib/Target/X86/Printer.cpp:1.34 llvm/lib/Target/X86/Printer.cpp:1.35 --- llvm/lib/Target/X86/Printer.cpp:1.34 Tue Jan 14 15:59:16 2003 +++ llvm/lib/Target/X86/Printer.cpp Mon May 26 19:03:17 2003 @@ -221,7 +221,8 @@ } } else { unsigned i = 0; - if (MI->getNumOperands() && MI->getOperand(0).opIsDef()) { + if (MI->getNumOperands() && (MI->getOperand(0).opIsDefOnly() || + MI->getOperand(0).opIsDefAndUse())) { printOp(O, MI->getOperand(0), RI); O << " = "; ++i; @@ -230,9 +231,11 @@ for (unsigned e = MI->getNumOperands(); i != e; ++i) { O << " "; - if (MI->getOperand(i).opIsDef()) O << "*"; + if (MI->getOperand(i).opIsDefOnly() || + MI->getOperand(i).opIsDefAndUse()) O << "*"; printOp(O, MI->getOperand(i), RI); - if (MI->getOperand(i).opIsDef()) O << "*"; + if (MI->getOperand(i).opIsDefOnly() || + MI->getOperand(i).opIsDefAndUse()) O << "*"; } } O << "\n"; From vadve at cs.uiuc.edu Mon May 26 19:06:01 2003 From: vadve at cs.uiuc.edu (Vikram Adve) Date: Mon May 26 19:06:01 2003 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAlloc/LiveRangeInfo.cpp PhyRegAlloc.cpp Message-ID: <200305270005.TAA31234@psmith.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/RegAlloc: LiveRangeInfo.cpp updated: 1.39 -> 1.40 PhyRegAlloc.cpp updated: 1.94 -> 1.95 --- Log message: (1) Added special register class containing (for now) %fsr. Fixed spilling of %fcc[0-3] which are part of %fsr. (2) Moved some machine-independent reg-class code to class TargetRegInfo from SparcReg{Class,}Info. (3) Renamed MachienOperand::opIsDef to MachineOperand::opIsDefOnly() and related functions and flags. Fixed several bugs where only "isDef" was being checked, not "isDefAndUse". --- Diffs of the changes: Index: llvm/lib/CodeGen/RegAlloc/LiveRangeInfo.cpp diff -u llvm/lib/CodeGen/RegAlloc/LiveRangeInfo.cpp:1.39 llvm/lib/CodeGen/RegAlloc/LiveRangeInfo.cpp:1.40 --- llvm/lib/CodeGen/RegAlloc/LiveRangeInfo.cpp:1.39 Wed Jan 15 15:14:01 2003 +++ llvm/lib/CodeGen/RegAlloc/LiveRangeInfo.cpp Mon May 26 19:05:23 2003 @@ -170,7 +170,7 @@ // for each operand that is defined by the instruction for (MachineInstr::val_op_iterator OpI = MInst->begin(), OpE = MInst->end(); OpI != OpE; ++OpI) - if (OpI.isDef()) { + if (OpI.isDefOnly() || OpI.isDefAndUse()) { const Value *Def = *OpI; bool isCC = (OpI.getMachineOperand().getType() == MachineOperand::MO_CCRegister); @@ -180,7 +180,8 @@ // iterate over implicit MI operands and create a new LR // for each operand that is defined by the instruction for (unsigned i = 0; i < MInst->getNumImplicitRefs(); ++i) - if (MInst->implicitRefIsDefined(i)) { + if (MInst->getImplicitOp(i).opIsDefOnly() || + MInst->getImplicitOp(i).opIsDefAndUse()) { const Value *Def = MInst->getImplicitRef(i); createOrAddToLiveRange(Def, /*isCC*/ false); } @@ -264,7 +265,7 @@ // iterate over MI operands to find defs for(MachineInstr::const_val_op_iterator DefI = MI->begin(), DefE = MI->end(); DefI != DefE; ++DefI) { - if (DefI.isDef()) { // iff this operand is a def + if (DefI.isDefOnly() || DefI.isDefAndUse()) { // this operand is modified LiveRange *LROfDef = getLiveRangeForValue( *DefI ); RegClass *RCOfDef = LROfDef->getRegClass(); Index: llvm/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp diff -u llvm/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp:1.94 llvm/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp:1.95 --- llvm/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp:1.94 Wed Jan 15 15:14:01 2003 +++ llvm/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp Mon May 26 19:05:23 2003 @@ -302,7 +302,7 @@ // for (MachineInstr::const_val_op_iterator OpI = MInst->begin(), OpE = MInst->end(); OpI != OpE; ++OpI) { - if (OpI.isDef()) // create a new LR iff this operand is a def + if (OpI.isDefOnly() || OpI.isDefAndUse()) // create a new LR since def addInterference(*OpI, &LVSetAI, isCallInst); // Calculate the spill cost of each live range @@ -322,12 +322,10 @@ // instr (currently, only calls have this). // unsigned NumOfImpRefs = MInst->getNumImplicitRefs(); - if ( NumOfImpRefs > 0 ) { - for (unsigned z=0; z < NumOfImpRefs; z++) - if (MInst->implicitRefIsDefined(z) ) - addInterference( MInst->getImplicitRef(z), &LVSetAI, isCallInst ); - } - + for (unsigned z=0; z < NumOfImpRefs; z++) + if (MInst->getImplicitOp(z).opIsDefOnly() || + MInst->getImplicitOp(z).opIsDefAndUse()) + addInterference( MInst->getImplicitRef(z), &LVSetAI, isCallInst ); } // for all machine instructions in BB } // for all BBs in function @@ -359,7 +357,7 @@ for (MachineInstr::const_val_op_iterator It1 = MInst->begin(), ItE = MInst->end(); It1 != ItE; ++It1) { const LiveRange *LROfOp1 = LRI.getLiveRangeForValue(*It1); - assert((LROfOp1 || !It1.isDef()) && "No LR for Def in PSEUDO insruction"); + assert((LROfOp1 || !It1.isUseOnly())&& "No LR for Def in PSEUDO insruction"); MachineInstr::const_val_op_iterator It2 = It1; for (++It2; It2 != ItE; ++It2) { @@ -652,8 +650,8 @@ "Return value of a ret must be handled elsewhere"); MachineOperand& Op = MInst->getOperand(OpNum); - bool isDef = MInst->operandIsDefined(OpNum); - bool isDefAndUse = MInst->operandIsDefinedAndUsed(OpNum); + bool isDef = Op.opIsDefOnly(); + bool isDefAndUse = Op.opIsDefAndUse(); unsigned RegType = MRI.getRegType(LR); int SpillOff = LR->getSpillOffFromFP(); RegClass *RC = LR->getRegClass(); @@ -885,8 +883,8 @@ { const MachineOperand& Op = MInst->getOperand(OpNum); - if (MInst->getOperandType(OpNum) == MachineOperand::MO_VirtualRegister || - MInst->getOperandType(OpNum) == MachineOperand::MO_CCRegister) + if (Op.getType() == MachineOperand::MO_VirtualRegister || + Op.getType() == MachineOperand::MO_CCRegister) if (const Value* Val = Op.getVRegValue()) if (MRI.getRegClassIDOfType(Val->getType()) == RC->getID()) if (Op.getAllocatedRegNum() == -1) @@ -987,7 +985,7 @@ else cerr << "(" << Val << ")"; - if (Op.opIsDef() ) + if (Op.opIsDefOnly() || Op.opIsDefAndUse()) cerr << "*"; const LiveRange *LROfVal = LRI.getLiveRangeForValue(Val); From vadve at cs.uiuc.edu Mon May 26 19:06:02 2003 From: vadve at cs.uiuc.edu (Vikram Adve) Date: Mon May 26 19:06:02 2003 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/InstrSched/SchedGraph.cpp Message-ID: <200305270005.TAA31219@psmith.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/InstrSched: SchedGraph.cpp updated: 1.43 -> 1.44 --- Log message: (1) Added special register class containing (for now) %fsr. Fixed spilling of %fcc[0-3] which are part of %fsr. (2) Moved some machine-independent reg-class code to class TargetRegInfo from SparcReg{Class,}Info. (3) Renamed MachienOperand::opIsDef to MachineOperand::opIsDefOnly() and related functions and flags. Fixed several bugs where only "isDef" was being checked, not "isDefAndUse". --- Diffs of the changes: Index: llvm/lib/CodeGen/InstrSched/SchedGraph.cpp diff -u llvm/lib/CodeGen/InstrSched/SchedGraph.cpp:1.43 llvm/lib/CodeGen/InstrSched/SchedGraph.cpp:1.44 --- llvm/lib/CodeGen/InstrSched/SchedGraph.cpp:1.43 Thu May 22 16:49:18 2003 +++ llvm/lib/CodeGen/InstrSched/SchedGraph.cpp Mon May 26 19:05:20 2003 @@ -525,18 +525,18 @@ for (unsigned i=0; i < regRefVec.size(); ++i) { SchedGraphNode* node = regRefVec[i].first; unsigned int opNum = regRefVec[i].second; - bool isDef = node->getMachineInstr()->operandIsDefined(opNum); + bool isDef = node->getMachineInstr()->getOperand(opNum).opIsDefOnly(); bool isDefAndUse = - node->getMachineInstr()->operandIsDefinedAndUsed(opNum); + node->getMachineInstr()->getOperand(opNum).opIsDefAndUse(); for (unsigned p=0; p < i; ++p) { SchedGraphNode* prevNode = regRefVec[p].first; if (prevNode != node) { unsigned int prevOpNum = regRefVec[p].second; bool prevIsDef = - prevNode->getMachineInstr()->operandIsDefined(prevOpNum); + prevNode->getMachineInstr()->getOperand(prevOpNum).opIsDefOnly(); bool prevIsDefAndUse = - prevNode->getMachineInstr()->operandIsDefinedAndUsed(prevOpNum); + prevNode->getMachineInstr()->getOperand(prevOpNum).opIsDefAndUse(); if (isDef) { if (prevIsDef) new SchedGraphEdge(prevNode, node, regNum, @@ -612,7 +612,7 @@ // for (unsigned i = 0, numOps = MI.getNumOperands(); i != numOps; ++i) { - switch (MI.getOperandType(i)) + switch (MI.getOperand(i).getType()) { case MachineOperand::MO_VirtualRegister: case MachineOperand::MO_CCRegister: @@ -622,8 +622,8 @@ ValueToDefVecMap::const_iterator I = valueToDefVecMap.find(srcI); if (I != valueToDefVecMap.end()) addEdgesForValue(node, I->second, srcI, - MI.operandIsDefined(i), - MI.operandIsDefinedAndUsed(i), target); + MI.getOperand(i).opIsDefOnly(), + MI.getOperand(i).opIsDefAndUse(), target); } break; @@ -646,16 +646,15 @@ // value of a Ret instruction. // for (unsigned i=0, N=MI.getNumImplicitRefs(); i < N; ++i) - if (! MI.implicitRefIsDefined(i) || - MI.implicitRefIsDefinedAndUsed(i)) + if (MI.getImplicitOp(i).opIsUse() || MI.getImplicitOp(i).opIsDefAndUse()) if (const Instruction *srcI = dyn_cast_or_null(MI.getImplicitRef(i))) { ValueToDefVecMap::const_iterator I = valueToDefVecMap.find(srcI); if (I != valueToDefVecMap.end()) addEdgesForValue(node, I->second, srcI, - MI.implicitRefIsDefined(i), - MI.implicitRefIsDefinedAndUsed(i), target); + MI.getImplicitOp(i).opIsDefOnly(), + MI.getImplicitOp(i).opIsDefAndUse(), target); } } @@ -693,7 +692,8 @@ } // ignore all other non-def operands - if (! minstr.operandIsDefined(i)) + if (!minstr.getOperand(i).opIsDefOnly() && + !minstr.getOperand(i).opIsDefAndUse()) continue; // We must be defining a value. @@ -710,7 +710,8 @@ // them assumes they must be virtual registers! // for (unsigned i=0, N = minstr.getNumImplicitRefs(); i != N; ++i) - if (minstr.implicitRefIsDefined(i)) + if (minstr.getImplicitOp(i).opIsDefOnly() || + minstr.getImplicitOp(i).opIsDefAndUse()) if (const Instruction* defInstr = dyn_cast_or_null(minstr.getImplicitRef(i))) valueToDefVecMap[defInstr].push_back(std::make_pair(node, -i)); From vadve at cs.uiuc.edu Mon May 26 19:06:03 2003 From: vadve at cs.uiuc.edu (Vikram Adve) Date: Mon May 26 19:06:03 2003 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/LiveVariables.cpp MachineInstr.cpp PHIElimination.cpp PrologEpilogInserter.cpp RegAllocLocal.cpp RegAllocSimple.cpp Message-ID: <200305270005.TAA31211@psmith.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: LiveVariables.cpp updated: 1.7 -> 1.8 MachineInstr.cpp updated: 1.70 -> 1.71 PHIElimination.cpp updated: 1.8 -> 1.9 PrologEpilogInserter.cpp updated: 1.10 -> 1.11 RegAllocLocal.cpp updated: 1.15 -> 1.16 RegAllocSimple.cpp updated: 1.38 -> 1.39 --- Log message: (1) Added special register class containing (for now) %fsr. Fixed spilling of %fcc[0-3] which are part of %fsr. (2) Moved some machine-independent reg-class code to class TargetRegInfo from SparcReg{Class,}Info. (3) Renamed MachienOperand::opIsDef to MachineOperand::opIsDefOnly() and related functions and flags. Fixed several bugs where only "isDef" was being checked, not "isDefAndUse". --- Diffs of the changes: Index: llvm/lib/CodeGen/LiveVariables.cpp diff -u llvm/lib/CodeGen/LiveVariables.cpp:1.7 llvm/lib/CodeGen/LiveVariables.cpp:1.8 --- llvm/lib/CodeGen/LiveVariables.cpp:1.7 Mon May 12 09:24:00 2003 +++ llvm/lib/CodeGen/LiveVariables.cpp Mon May 26 19:05:17 2003 @@ -231,7 +231,7 @@ // Process all explicit defs... for (unsigned i = 0; i != NumOperandsToProcess; ++i) { MachineOperand &MO = MI->getOperand(i); - if (MO.opIsDef() || MO.opIsDefAndUse()) { + if (MO.opIsDefOnly() || MO.opIsDefAndUse()) { if (MO.isVirtualRegister()) { VarInfo &VRInfo = getVarInfo(MO.getReg()); Index: llvm/lib/CodeGen/MachineInstr.cpp diff -u llvm/lib/CodeGen/MachineInstr.cpp:1.70 llvm/lib/CodeGen/MachineInstr.cpp:1.71 --- llvm/lib/CodeGen/MachineInstr.cpp:1.70 Wed Jan 15 13:47:02 2003 +++ llvm/lib/CodeGen/MachineInstr.cpp Mon May 26 19:05:17 2003 @@ -94,7 +94,7 @@ if (isDefAndUse) operands[i].flags = MachineOperand::DEFUSEFLAG; else if (isdef || TargetInstrDescriptors[opCode].resultPos == (int) i) - operands[i].flags = MachineOperand::DEFFLAG; + operands[i].flags = MachineOperand::DEFONLYFLAG; else operands[i].flags = 0; } @@ -126,7 +126,7 @@ operands[i].regNum = regNum; if (isdef || TargetInstrDescriptors[opCode].resultPos == (int) i) - operands[i].flags = MachineOperand::DEFFLAG; + operands[i].flags = MachineOperand::DEFONLYFLAG; else operands[i].flags = 0; @@ -152,7 +152,7 @@ // Subsitute operands for (MachineInstr::val_op_iterator O = begin(), E = end(); O != E; ++O) if (*O == oldVal) - if (!defsOnly || O.isDef()) + if (!defsOnly || !O.isUseOnly()) { O.getMachineOperand().value = newVal; ++numSubst; @@ -161,7 +161,7 @@ // Subsitute implicit refs for (unsigned i=0, N=getNumImplicitRefs(); i < N; ++i) if (getImplicitRef(i) == oldVal) - if (!defsOnly || implicitRefIsDefined(i)) + if (!defsOnly || !getImplicitOp(i).opIsUse()) { getImplicitOp(i).value = newVal; ++numSubst; @@ -281,7 +281,8 @@ unsigned StartOp = 0; // Specialize printing if op#0 is definition - if (getNumOperands() && operandIsDefined(0)) { + if (getNumOperands() && + (getOperand(0).opIsDefOnly() || getOperand(0).opIsDefAndUse())) { ::print(getOperand(0), OS, TM); OS << " = "; ++StartOp; // Don't print this operand again! @@ -289,14 +290,15 @@ OS << TM.getInstrInfo().getName(getOpcode()); for (unsigned i = StartOp, e = getNumOperands(); i != e; ++i) { + const MachineOperand& mop = getOperand(i); if (i != StartOp) OS << ","; OS << " "; - ::print(getOperand(i), OS, TM); + ::print(mop, OS, TM); - if (operandIsDefinedAndUsed(i)) + if (mop.opIsDefAndUse()) OS << ""; - else if (operandIsDefined(i)) + else if (mop.opIsDefOnly()) OS << ""; } @@ -305,10 +307,10 @@ OS << "\tImplicitRefs: "; for(unsigned i = 0, e = getNumImplicitRefs(); i != e; ++i) { OS << "\t"; - OutputValue(OS, getImplicitRef(i)); - if (implicitRefIsDefinedAndUsed(i)) + OutputValue(OS, getImplicitRef(i)); + if (getImplicitOp(i).opIsDefAndUse()) OS << ""; - else if (implicitRefIsDefined(i)) + else if (getImplicitOp(i).opIsDefOnly()) OS << ""; } } @@ -323,9 +325,9 @@ for (unsigned i=0, N=MI.getNumOperands(); i < N; i++) { os << "\t" << MI.getOperand(i); - if (MI.operandIsDefined(i)) + if (MI.getOperand(i).opIsDefOnly()) os << ""; - if (MI.operandIsDefinedAndUsed(i)) + if (MI.getOperand(i).opIsDefAndUse()) os << ""; } @@ -335,8 +337,8 @@ os << "\tImplicit: "; for (unsigned z=0; z < NumOfImpRefs; z++) { OutputValue(os, MI.getImplicitRef(z)); - if (MI.implicitRefIsDefined(z)) os << ""; - if (MI.implicitRefIsDefinedAndUsed(z)) os << ""; + if (MI.getImplicitOp(z).opIsDefOnly()) os << ""; + if (MI.getImplicitOp(z).opIsDefAndUse()) os << ""; os << "\t"; } } Index: llvm/lib/CodeGen/PHIElimination.cpp diff -u llvm/lib/CodeGen/PHIElimination.cpp:1.8 llvm/lib/CodeGen/PHIElimination.cpp:1.9 --- llvm/lib/CodeGen/PHIElimination.cpp:1.8 Mon May 12 12:37:30 2003 +++ llvm/lib/CodeGen/PHIElimination.cpp Mon May 26 19:05:17 2003 @@ -165,7 +165,7 @@ for (unsigned i = 0, e = PrevInst->getNumOperands(); i != e; ++i) { MachineOperand &MO = PrevInst->getOperand(i); if (MO.isVirtualRegister() && MO.getReg() == IncomingReg) - if (MO.opIsDef() || MO.opIsDefAndUse()) { + if (MO.opIsDefOnly() || MO.opIsDefAndUse()) { HaveNotEmitted = false; break; } Index: llvm/lib/CodeGen/PrologEpilogInserter.cpp diff -u llvm/lib/CodeGen/PrologEpilogInserter.cpp:1.10 llvm/lib/CodeGen/PrologEpilogInserter.cpp:1.11 --- llvm/lib/CodeGen/PrologEpilogInserter.cpp:1.10 Fri May 2 13:44:42 2003 +++ llvm/lib/CodeGen/PrologEpilogInserter.cpp Mon May 26 19:05:17 2003 @@ -108,7 +108,8 @@ MachineOperand &MO = (*I)->getOperand(i); assert(!MO.isVirtualRegister() && "Register allocation must be performed!"); - if (MO.isPhysicalRegister() && MO.opIsDef()) + if (MO.isPhysicalRegister() && + (MO.opIsDefOnly() || MO.opIsDefAndUse())) ModifiedRegs[MO.getReg()] = true; // Register is modified } ++I; Index: llvm/lib/CodeGen/RegAllocLocal.cpp diff -u llvm/lib/CodeGen/RegAllocLocal.cpp:1.15 llvm/lib/CodeGen/RegAllocLocal.cpp:1.16 --- llvm/lib/CodeGen/RegAllocLocal.cpp:1.15 Sun May 11 22:54:14 2003 +++ llvm/lib/CodeGen/RegAllocLocal.cpp Mon May 26 19:05:17 2003 @@ -489,7 +489,7 @@ // 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).opIsDefAndUse()) && + if ((MI->getOperand(i).opIsDefOnly() || MI->getOperand(i).opIsDefAndUse()) && MI->getOperand(i).isPhysicalRegister()) { unsigned Reg = MI->getOperand(i).getAllocatedRegNum(); spillPhysReg(MBB, I, Reg); // Spill any existing value in the reg @@ -512,8 +512,8 @@ // we need to scavenge a register. // for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) - if (MI->getOperand(i).opIsDef() && - MI->getOperand(i).isVirtualRegister()) { + if ((MI->getOperand(i).opIsDefOnly() || MI->getOperand(i).opIsDefAndUse()) + && MI->getOperand(i).isVirtualRegister()) { unsigned DestVirtReg = MI->getOperand(i).getAllocatedRegNum(); unsigned DestPhysReg; Index: llvm/lib/CodeGen/RegAllocSimple.cpp diff -u llvm/lib/CodeGen/RegAllocSimple.cpp:1.38 llvm/lib/CodeGen/RegAllocSimple.cpp:1.39 --- llvm/lib/CodeGen/RegAllocSimple.cpp:1.38 Tue Jan 14 15:58:41 2003 +++ llvm/lib/CodeGen/RegAllocSimple.cpp Mon May 26 19:05:17 2003 @@ -173,7 +173,7 @@ // register in any given instruction unsigned physReg = Virt2PhysRegMap[virtualReg]; if (physReg == 0) { - if (op.opIsDef()) { + if (op.opIsDefOnly() || op.opIsDefAndUse()) { if (TM->getInstrInfo().isTwoAddrInstr(MI->getOpcode()) && i == 0) { // must be same register number as the first operand // This maps a = b + c into b += c, and saves b into a's spot From vadve at cs.uiuc.edu Mon May 26 19:07:00 2003 From: vadve at cs.uiuc.edu (Vikram Adve) Date: Mon May 26 19:07:00 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/CodeGen/MachineInstr.h Message-ID: <200305270006.TAA31399@psmith.cs.uiuc.edu> Changes in directory llvm/include/llvm/CodeGen: MachineInstr.h updated: 1.98 -> 1.99 --- Log message: Renamed MachienOperand::opIsDef to MachineOperand::opIsDefOnly() and related functions and flags. Fixed several bugs where only "isDef" was being checked, not "isDefAndUse". --- Diffs of the changes: Index: llvm/include/llvm/CodeGen/MachineInstr.h diff -u llvm/include/llvm/CodeGen/MachineInstr.h:1.98 llvm/include/llvm/CodeGen/MachineInstr.h:1.99 --- llvm/include/llvm/CodeGen/MachineInstr.h:1.98 Wed Jan 15 13:46:51 2003 +++ llvm/include/llvm/CodeGen/MachineInstr.h Mon May 26 19:06:48 2003 @@ -88,13 +88,13 @@ private: // Bit fields of the flags variable used for different operand properties enum { - DEFFLAG = 0x01, // this is a def of the operand - DEFUSEFLAG = 0x02, // this is both a def and a use - HIFLAG32 = 0x04, // operand is %hi32(value_or_immedVal) - LOFLAG32 = 0x08, // operand is %lo32(value_or_immedVal) - HIFLAG64 = 0x10, // operand is %hi64(value_or_immedVal) - LOFLAG64 = 0x20, // operand is %lo64(value_or_immedVal) - PCRELATIVE = 0x40, // Operand is relative to PC, not a global address + DEFONLYFLAG = 0x01, // this is a def but not a use of the operand + DEFUSEFLAG = 0x02, // this is both a def and a use + HIFLAG32 = 0x04, // operand is %hi32(value_or_immedVal) + LOFLAG32 = 0x08, // operand is %lo32(value_or_immedVal) + HIFLAG64 = 0x10, // operand is %hi64(value_or_immedVal) + LOFLAG64 = 0x20, // operand is %lo64(value_or_immedVal) + PCRELATIVE = 0x40, // Operand is relative to PC, not a global address USEDEFMASK = 0x03, }; @@ -137,7 +137,7 @@ regNum(Reg) { switch (UseTy) { case MOTy::Use: flags = 0; break; - case MOTy::Def: flags = DEFFLAG; break; + case MOTy::Def: flags = DEFONLYFLAG; break; case MOTy::UseAndDef: flags = DEFUSEFLAG; break; default: assert(0 && "Invalid value for UseTy!"); } @@ -148,7 +148,7 @@ : value(V), opType(OpTy), regNum(-1) { switch (UseTy) { case MOTy::Use: flags = 0; break; - case MOTy::Def: flags = DEFFLAG; break; + case MOTy::Def: flags = DEFONLYFLAG; break; case MOTy::UseAndDef: flags = DEFUSEFLAG; break; default: assert(0 && "Invalid value for UseTy!"); } @@ -259,7 +259,7 @@ } bool opIsUse () const { return (flags & USEDEFMASK) == 0; } - bool opIsDef () const { return flags & DEFFLAG; } + bool opIsDefOnly () const { return flags & DEFONLYFLAG; } bool opIsDefAndUse () const { return flags & DEFUSEFLAG; } bool opHiBits32 () const { return flags & HIFLAG32; } bool opLoBits32 () const { return flags & LOFLAG32; } @@ -332,15 +332,6 @@ std::vector operands; // the operands unsigned numImplicitRefs; // number of implicit operands - MachineOperand& getImplicitOp(unsigned i) { - assert(i < numImplicitRefs && "implicit ref# out of range!"); - return operands[i + operands.size() - numImplicitRefs]; - } - const MachineOperand& getImplicitOp(unsigned i) const { - assert(i < numImplicitRefs && "implicit ref# out of range!"); - return operands[i + operands.size() - numImplicitRefs]; - } - // regsUsed - all machine registers used for this instruction, including regs // used to save values across the instruction. This is a bitset of registers. std::vector regsUsed; @@ -371,7 +362,7 @@ const MachineOpCode getOpCode() const { return opCode; } // - // Information about explicit operands of the instruction + // Access to explicit operands of the instruction // unsigned getNumOperands() const { return operands.size() - numImplicitRefs; } @@ -384,38 +375,27 @@ return operands[i]; } - // FIXME: ELIMINATE - MachineOperand::MachineOperandType getOperandType(unsigned i) const { - return getOperand(i).getType(); - } - - // FIXME: ELIMINATE: Misleading name: Definition not defined. - bool operandIsDefined(unsigned i) const { - return getOperand(i).opIsDef(); - } - - bool operandIsDefinedAndUsed(unsigned i) const { - return getOperand(i).opIsDefAndUse(); - } - // - // Information about implicit operands of the instruction + // Access to implicit operands of the instruction // unsigned getNumImplicitRefs() const{ return numImplicitRefs; } - const Value* getImplicitRef(unsigned i) const { - return getImplicitOp(i).getVRegValue(); + MachineOperand& getImplicitOp(unsigned i) { + assert(i < numImplicitRefs && "implicit ref# out of range!"); + return operands[i + operands.size() - numImplicitRefs]; } - Value* getImplicitRef(unsigned i) { - return getImplicitOp(i).getVRegValue(); + const MachineOperand& getImplicitOp(unsigned i) const { + assert(i < numImplicitRefs && "implicit ref# out of range!"); + return operands[i + operands.size() - numImplicitRefs]; } - bool implicitRefIsDefined(unsigned i) const { - return getImplicitOp(i).opIsDef(); + Value* getImplicitRef(unsigned i) { + return getImplicitOp(i).getVRegValue(); } - bool implicitRefIsDefinedAndUsed(unsigned i) const { - return getImplicitOp(i).opIsDefAndUse(); + const Value* getImplicitRef(unsigned i) const { + return getImplicitOp(i).getVRegValue(); } + inline void addImplicitRef (Value* V, bool isDef=false,bool isDefAndUse=false); inline void setImplicitRef (unsigned i, Value* V, @@ -647,8 +627,8 @@ void skipToNextVal() { while (i < MI->getNumOperands() && - !( (MI->getOperandType(i) == MachineOperand::MO_VirtualRegister || - MI->getOperandType(i) == MachineOperand::MO_CCRegister) + !( (MI->getOperand(i).getType() == MachineOperand::MO_VirtualRegister || + MI->getOperand(i).getType() == MachineOperand::MO_CCRegister) && MI->getOperand(i).getVRegValue() != 0)) ++i; } @@ -669,7 +649,8 @@ inline VTy operator->() const { return operator*(); } - inline bool isDef() const { return MI->getOperand(i).opIsDef(); } + inline bool isUseOnly() const { return MI->getOperand(i).opIsUse(); } + inline bool isDefOnly() const { return MI->getOperand(i).opIsDefOnly(); } inline bool isDefAndUse() const { return MI->getOperand(i).opIsDefAndUse();} inline _Self& operator++() { i++; skipToNextVal(); return *this; } From vadve at cs.uiuc.edu Mon May 26 19:07:01 2003 From: vadve at cs.uiuc.edu (Vikram Adve) Date: Mon May 26 19:07:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Analysis/LiveVar/BBLiveVar.cpp FunctionLiveVarInfo.cpp Message-ID: <200305270006.TAA31369@psmith.cs.uiuc.edu> Changes in directory llvm/lib/Analysis/LiveVar: BBLiveVar.cpp updated: 1.34 -> 1.35 FunctionLiveVarInfo.cpp updated: 1.42 -> 1.43 --- Log message: Renamed MachienOperand::opIsDef to MachineOperand::opIsDefOnly() and related functions and flags. Fixed several bugs where only "isDef" was being checked, not "isDefAndUse". --- Diffs of the changes: Index: llvm/lib/Analysis/LiveVar/BBLiveVar.cpp diff -u llvm/lib/Analysis/LiveVar/BBLiveVar.cpp:1.34 llvm/lib/Analysis/LiveVar/BBLiveVar.cpp:1.35 --- llvm/lib/Analysis/LiveVar/BBLiveVar.cpp:1.34 Tue May 20 15:36:39 2003 +++ llvm/lib/Analysis/LiveVar/BBLiveVar.cpp Mon May 26 19:06:00 2003 @@ -64,12 +64,12 @@ // iterate over MI operands to find defs for (MachineInstr::const_val_op_iterator OpI = MI->begin(), OpE = MI->end(); OpI != OpE; ++OpI) - if (OpI.isDef()) // add to Defs only if this operand is a def + if (OpI.isDefOnly() || OpI.isDefAndUse()) // add to Defs if this operand is a def addDef(*OpI); // do for implicit operands as well for (unsigned i = 0; i < MI->getNumImplicitRefs(); ++i) - if (MI->implicitRefIsDefined(i)) + if (MI->getImplicitOp(i).opIsDefOnly() || MI->getImplicitOp(i).opIsDefAndUse()) addDef(MI->getImplicitRef(i)); // iterate over MI operands to find uses @@ -80,7 +80,7 @@ if (isa(Op)) continue; // don't process labels - if (!OpI.isDef() || OpI.isDefAndUse()) { + if (OpI.isUseOnly() || OpI.isDefAndUse()) { // add to Uses only if this operand is a use // // *** WARNING: The following code for handling dummy PHI machine @@ -116,7 +116,7 @@ if (Op->getType() == Type::LabelTy) // don't process labels continue; - if (!MI->implicitRefIsDefined(i) || MI->implicitRefIsDefinedAndUsed(i) ) + if (MI->getImplicitOp(i).opIsUse() || MI->getImplicitOp(i).opIsDefAndUse()) addUse(Op); } } // for all machine instructions Index: llvm/lib/Analysis/LiveVar/FunctionLiveVarInfo.cpp diff -u llvm/lib/Analysis/LiveVar/FunctionLiveVarInfo.cpp:1.42 llvm/lib/Analysis/LiveVar/FunctionLiveVarInfo.cpp:1.43 --- llvm/lib/Analysis/LiveVar/FunctionLiveVarInfo.cpp:1.42 Tue Jan 14 17:05:00 2003 +++ llvm/lib/Analysis/LiveVar/FunctionLiveVarInfo.cpp Mon May 26 19:06:00 2003 @@ -213,13 +213,14 @@ static void applyTranferFuncForMInst(ValueSet &LVS, const MachineInstr *MInst) { for (MachineInstr::const_val_op_iterator OpI = MInst->begin(), OpE = MInst->end(); OpI != OpE; ++OpI) { - if (OpI.isDef()) // kill only if this operand is a def - LVS.erase(*OpI); // this definition kills any uses + if (OpI.isDefOnly() || OpI.isDefAndUse()) // kill if this operand is a def + LVS.erase(*OpI); // this definition kills any uses } // do for implicit operands as well for (unsigned i=0; i < MInst->getNumImplicitRefs(); ++i) { - if (MInst->implicitRefIsDefined(i)) + if (MInst->getImplicitOp(i).opIsDefOnly() || + MInst->getImplicitOp(i).opIsDefAndUse()) LVS.erase(MInst->getImplicitRef(i)); } @@ -227,14 +228,14 @@ OpE = MInst->end(); OpI != OpE; ++OpI) { if (!isa(*OpI)) // don't process labels // add only if this operand is a use - if (!OpI.isDef() || OpI.isDefAndUse() ) + if (!OpI.isDefOnly() || OpI.isDefAndUse() ) LVS.insert(*OpI); // An operand is a use - so add to use set } // do for implicit operands as well for (unsigned i = 0, e = MInst->getNumImplicitRefs(); i != e; ++i) - if (!MInst->implicitRefIsDefined(i) || - MInst->implicitRefIsDefinedAndUsed(i)) + if (MInst->getImplicitOp(i).opIsUse() || + MInst->getImplicitOp(i).opIsDefAndUse()) LVS.insert(MInst->getImplicitRef(i)); } From vadve at cs.uiuc.edu Mon May 26 19:08:01 2003 From: vadve at cs.uiuc.edu (Vikram Adve) Date: Mon May 26 19:08:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Target/TargetRegInfo.h Message-ID: <200305270007.TAA31473@psmith.cs.uiuc.edu> Changes in directory llvm/include/llvm/Target: TargetRegInfo.h updated: 1.33 -> 1.34 --- Log message: (1) Added special register class containing (for now) %fsr. Fixed spilling of %fcc[0-3] which are part of %fsr. (2) Moved some machine-independent reg-class code to class TargetRegInfo from SparcReg{Class,}Info. --- Diffs of the changes: Index: llvm/include/llvm/Target/TargetRegInfo.h diff -u llvm/include/llvm/Target/TargetRegInfo.h:1.33 llvm/include/llvm/Target/TargetRegInfo.h:1.34 --- llvm/include/llvm/Target/TargetRegInfo.h:1.33 Sun May 25 11:02:05 2003 +++ llvm/include/llvm/Target/TargetRegInfo.h Mon May 26 19:07:13 2003 @@ -45,6 +45,8 @@ std::vector &IsColorUsedArr) const = 0; virtual bool isRegVolatile(int Reg) const = 0; + virtual const char* const getRegName(unsigned reg) const = 0; + TargetRegClassInfo(unsigned ID, unsigned NVR, unsigned NAR) : RegClassID(ID), NumOfAvailRegs(NVR), NumOfAllRegs(NAR) {} }; @@ -75,11 +77,16 @@ // code register class will be returned. Otherwise, the normal register // class (eg. int, float) must be returned. virtual unsigned getRegClassIDOfType (const Type *type, - bool isCCReg = false) const =0; - virtual unsigned getRegClassIDOfReg (int unifiedRegNum) const =0; - virtual unsigned getRegClassIDOfRegType(int regType) const =0; - - inline unsigned int getNumOfRegClasses() const { + bool isCCReg = false) const = 0; + virtual unsigned getRegClassIDOfRegType(int regType) const = 0; + + unsigned getRegClassIDOfReg(int unifiedRegNum) const { + unsigned classId = 0; + (void) getClassRegNum(unifiedRegNum, classId); + return classId; + } + + unsigned int getNumOfRegClasses() const { return MachineRegClassArr.size(); } @@ -169,13 +176,43 @@ // Each register class has a seperate space for register IDs. To convert // a regId in a register class to a common Id, or vice versa, - // we use the folloing methods. + // we use the folloing two methods. // - virtual int getUnifiedRegNum(unsigned regClassID, int reg) const = 0; - virtual int getClassRegNum(int unifiedRegNum, unsigned& regClassID) const =0; + // Thsi method converts from class reg. number to unified register number. + int getUnifiedRegNum(unsigned regClassID, int reg) const { + if (reg == getInvalidRegNum()) { return getInvalidRegNum(); } + assert(regClassID < getNumOfRegClasses() && "Invalid register class"); + int totalRegs = 0; + for (unsigned rcid = 0; rcid < regClassID; ++rcid) + totalRegs += MachineRegClassArr[rcid]->getNumOfAllRegs(); + return reg + totalRegs; + } + + // This method converts the unified number to the number in its class, + // and returns the class ID in regClassID. + int getClassRegNum(int uRegNum, unsigned& regClassID) const { + if (uRegNum == getInvalidRegNum()) { return getInvalidRegNum(); } + + int totalRegs = 0, rcid = 0, NC = getNumOfRegClasses(); + while (rcid < NC && + uRegNum >= totalRegs + (int) MachineRegClassArr[rcid]->getNumOfAllRegs()) { + totalRegs += MachineRegClassArr[rcid]->getNumOfAllRegs(); + rcid++; + } + if (rcid == NC) { + assert(0 && "getClassRegNum(): Invalid register number"); + return getInvalidRegNum(); + } + regClassID = rcid; + return uRegNum - totalRegs; + } // Returns the assembly-language name of the specified machine register. - virtual const char * const getUnifiedRegName(int UnifiedRegNum) const = 0; + const char * const getUnifiedRegName(int UnifiedRegNum) const { + unsigned regClassID = getNumOfRegClasses(); // initialize to invalid value + int regNumInClass = getClassRegNum(UnifiedRegNum, regClassID); + return MachineRegClassArr[regClassID]->getRegName(regNumInClass); + } virtual int getRegType(const Type* type) const = 0; virtual int getRegType(const LiveRange *LR) const = 0; @@ -190,7 +227,6 @@ // be obtained using this method. // virtual int getInvalidRegNum() const = 0; - // Method for inserting caller saving code. The caller must save all the // volatile registers across a call based on the calling conventions of From lattner at cs.uiuc.edu Tue May 27 09:10:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 27 09:10:02 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c Message-ID: <200305271409.JAA30370@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/SingleSource/UnitTests: 2003-05-07-VarArgs.c updated: 1.5 -> 1.6 --- Log message: Revert the last revision which is stopping the nightly tester. :( --- Diffs of the changes: Index: llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c diff -u llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c:1.5 llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c:1.6 --- llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c:1.5 Sun May 25 11:30:15 2003 +++ llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c Tue May 27 09:09:04 2003 @@ -1,7 +1,7 @@ #include #include -/* 8 bytes if alignon(int) is 4. */ +/* 5 bytes. */ typedef struct DWordS_struct { int i; char c; } DWordS; /* 12 bytes if d is 4-byte aligned; 16 bytes if d is 8-byte aligned. */ @@ -47,17 +47,17 @@ printf("char %c\n", c); break; case 'D': - dw = va_arg(ap, DWordS); + /* dw = va_arg(ap, DWordS); printf("DWord { %d, %c }\n", dw.i, dw.c); - break; + */ break; case 'Q': - qw = va_arg(ap, QuadWordS); + /* qw = va_arg(ap, QuadWordS); printf("QuadWord { %d, %f }\n", qw.i, qw.d); - break; + */ break; case 'L': - ls = va_arg(ap, LargeS); + /* ls = va_arg(ap, LargeS); printf("LargeS { %d, %f, 0x%p, %d }\n", ls.i, ls.d, ls.ptr, ls.j); - break; + */ break; } va_end(ap); } From lattner at cs.uiuc.edu Tue May 27 09:16:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 27 09:16:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/SingleSource/mandel.c Message-ID: <200305271415.JAA30434@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/SingleSource: mandel.c added (r1.1) --- Log message: Simple test for C99 complex numbers --- Diffs of the changes: Index: llvm/test/Programs/SingleSource/mandel.c diff -c /dev/null llvm/test/Programs/SingleSource/mandel.c:1.1 *** /dev/null Tue May 27 09:15:40 2003 --- llvm/test/Programs/SingleSource/mandel.c Tue May 27 09:15:30 2003 *************** *** 0 **** --- 1,32 ---- + #include + #define ESCAPE 2 + #define IMAGE_SIZE 10 + #define START_X -2.0 + #define START_Y START_X + #define MAX_ITER 10 + #define step (-START_X - START_X)/IMAGE_SIZE + void emit(double complex X) { + printf("%f\n", (double)X); + } + + void mandel() { + int x, y, n; + for (x = 0; x < IMAGE_SIZE; ++x) { + for (y = 0; y < IMAGE_SIZE; ++y) { + double complex c = (START_X+x*step) + (START_Y-y*step) * I; + double complex z = 0.0; + + for (n = 0; n < MAX_ITER; ++n) { + z = z * z + c; + if (cabs(z) >= ESCAPE) + break; + } + emit(z); + } + } + } + + int main() { + mandel(); + return 0; + } From lattner at cs.uiuc.edu Tue May 27 10:46:05 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 27 10:46:05 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp Message-ID: <200305271545.KAA30848@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: ScalarReplAggregates.cpp added (r1.1) --- Log message: Implementation of the simple "scalar replacement of aggregates" transformation --- Diffs of the changes: Index: llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp diff -c /dev/null llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp:1.1 *** /dev/null Tue May 27 10:45:37 2003 --- llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp Tue May 27 10:45:27 2003 *************** *** 0 **** --- 1,164 ---- + //===- ScalarReplAggregates.cpp - Scalar Replacement of Aggregates --------===// + // + // This transformation implements the well known scalar replacement of + // aggregates transformation. This xform breaks up alloca instructions of + // aggregate type (structure or array) into individual alloca instructions for + // each member (if possible). + // + //===----------------------------------------------------------------------===// + + #include "llvm/Transforms/Scalar.h" + #include "llvm/Function.h" + #include "llvm/Pass.h" + #include "llvm/iMemory.h" + #include "llvm/DerivedTypes.h" + #include "llvm/Constants.h" + #include "Support/StringExtras.h" + #include "Support/Statistic.h" + + namespace { + Statistic<> NumReplaced("scalarrepl", "Number of alloca's broken up"); + + struct SROA : public FunctionPass { + bool runOnFunction(Function &F); + + private: + AllocaInst *AddNewAlloca(Function &F, const Type *Ty, AllocationInst *Base); + }; + + RegisterOpt X("scalarrepl", "Scalar Replacement of Aggregates"); + } + + Pass *createScalarReplAggregatesPass() { return new SROA(); } + + + // runOnFunction - This algorithm is a simple worklist driven algorithm, which + // runs on all of the malloc/alloca instructions in the function, removing them + // if they are only used by getelementptr instructions. + // + bool SROA::runOnFunction(Function &F) { + std::vector WorkList; + + // Scan the entry basic block, adding any alloca's and mallocs to the worklist + BasicBlock &BB = F.getEntryNode(); + for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) + if (AllocationInst *A = dyn_cast(I)) + WorkList.push_back(A); + + // Process the worklist + bool Changed = false; + while (!WorkList.empty()) { + AllocationInst *AI = WorkList.back(); + WorkList.pop_back(); + + // We cannot transform the allocation instruction if it is an array + // allocation, and an allocation of a scalar value cannot be decomposed + if (AI->isArrayAllocation() || + (!isa(AI->getAllocatedType()) /*&& + !isa(AI->getAllocatedType())*/ + )) continue; + + // Loop over the use list of the alloca. We can only transform it if there + // are only getelementptr instructions (with a zero first index) and free + // instructions. + // + bool CannotTransform = false; + for (Value::use_iterator I = AI->use_begin(), E = AI->use_end(); + I != E; ++I) { + Instruction *User = cast(*I); + if (GetElementPtrInst *GEPI = dyn_cast(User)) { + // The GEP is safe to transform if it is of the form GEP , 0, + if (GEPI->getNumOperands() <= 2 || + GEPI->getOperand(1) != Constant::getNullValue(Type::LongTy) || + !isa(GEPI->getOperand(2)) || + isa(GEPI->getOperand(2))) { + DEBUG(std::cerr << "Cannot transform: " << *AI << " due to user: " + << User); + CannotTransform = true; + break; + } + } else { + DEBUG(std::cerr << "Cannot transform: " << *AI << " due to user: " + << User); + CannotTransform = true; + break; + } + } + + if (CannotTransform) continue; + + DEBUG(std::cerr << "Found inst to xform: " << *AI); + Changed = true; + + std::vector ElementAllocas; + if (const StructType *ST = dyn_cast(AI->getAllocatedType())) { + ElementAllocas.reserve(ST->getNumContainedTypes()); + for (unsigned i = 0, e = ST->getNumContainedTypes(); i != e; ++i) { + AllocaInst *NA = new AllocaInst(ST->getContainedType(i), 0, + AI->getName() + "." + utostr(i), AI); + ElementAllocas.push_back(NA); + WorkList.push_back(NA); // Add to worklist for recursive processing + } + } else { + const ArrayType *AT = cast(AI->getAllocatedType()); + ElementAllocas.reserve(AT->getNumElements()); + const Type *ElTy = AT->getElementType(); + for (unsigned i = 0, e = AT->getNumElements(); i != e; ++i) { + AllocaInst *NA = new AllocaInst(ElTy, 0, + AI->getName() + "." + utostr(i), AI); + ElementAllocas.push_back(NA); + WorkList.push_back(NA); // Add to worklist for recursive processing + } + } + + // Now that we have created the alloca instructions that we want to use, + // expand the getelementptr instructions to use them. + // + for (Value::use_iterator I = AI->use_begin(), E = AI->use_end(); + I != E; ++I) { + Instruction *User = cast(*I); + if (GetElementPtrInst *GEPI = dyn_cast(User)) { + // We now know that the GEP is of the form: GEP , 0, + uint64_t Idx; + if (ConstantSInt *CSI = dyn_cast(GEPI->getOperand(2))) + Idx = CSI->getValue(); + else + Idx = cast(GEPI->getOperand(2))->getValue(); + + assert(Idx < ElementAllocas.size() && "Index out of range?"); + AllocaInst *AllocaToUse = ElementAllocas[Idx]; + + Value *RepValue; + if (GEPI->getNumOperands() == 3) { + // Do not insert a new getelementptr instruction with zero indices, + // only to have it optimized out later. + RepValue = AllocaToUse; + } else { + // We are indexing deeply into the structure, so we still need a + // getelement ptr instruction to finish the indexing. This may be + // expanded itself once the worklist is rerun. + // + std::string OldName = GEPI->getName(); // Steal the old name... + GEPI->setName(""); + RepValue = + new GetElementPtrInst(AllocaToUse, + std::vector(GEPI->op_begin()+3, + GEPI->op_end()), + OldName, GEPI); + } + + // Move all of the users over to the new GEP. + GEPI->replaceAllUsesWith(RepValue); + // Delete the old GEP + GEPI->getParent()->getInstList().erase(GEPI); + } else { + assert(0 && "Unexpected instruction type!"); + } + } + + // Finally, delete the Alloca instruction + AI->getParent()->getInstList().erase(AI); + } + + return Changed; + } From lattner at cs.uiuc.edu Tue May 27 10:48:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 27 10:48:02 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/ScalarRepl/ Message-ID: <200305271547.KAA30876@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/ScalarRepl: --- Log message: Directory /home/vadve/vadve/Research/DynOpt/CVSRepository/llvm/test/Regression/Transforms/ScalarRepl added to the repository --- Diffs of the changes: From lattner at cs.uiuc.edu Tue May 27 10:52:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 27 10:52:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/ScalarRepl/Makefile arraytest.ll badarray.ll basictest.ll Message-ID: <200305271551.KAA30980@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/ScalarRepl: Makefile added (r1.1) arraytest.ll added (r1.1) badarray.ll added (r1.1) basictest.ll added (r1.1) --- Log message: Initial testcases for scalar replacement of aggregates pass --- Diffs of the changes: Index: llvm/test/Regression/Transforms/ScalarRepl/Makefile diff -c /dev/null llvm/test/Regression/Transforms/ScalarRepl/Makefile:1.1 *** /dev/null Tue May 27 10:51:27 2003 --- llvm/test/Regression/Transforms/ScalarRepl/Makefile Tue May 27 10:51:17 2003 *************** *** 0 **** --- 1,10 ---- + + LEVEL = ../../../.. + include $(LEVEL)/test/Makefile.tests + + TESTS := $(wildcard *.ll) + + all:: $(addprefix Output/, $(TESTS:%.ll=%.ll.out)) + + Output/%.ll.out: %.ll Output/.dir $(LOPT) + -$(TESTRUNR) $< Index: llvm/test/Regression/Transforms/ScalarRepl/arraytest.ll diff -c /dev/null llvm/test/Regression/Transforms/ScalarRepl/arraytest.ll:1.1 *** /dev/null Tue May 27 10:51:27 2003 --- llvm/test/Regression/Transforms/ScalarRepl/arraytest.ll Tue May 27 10:51:17 2003 *************** *** 0 **** --- 1,13 ---- + ; RUN: if as < %s | opt -scalarrepl -mem2reg | dis | grep alloca + ; RUN: then exit 1 + ; RUN: else exit 0 + ; RUN: fi + + int %test() { + %X = alloca [ 4 x int ] + %Y = getelementptr [4x int]* %X, long 0, long 0 + store int 0, int* %Y + + %Z = load int* %Y + ret int %Z + } Index: llvm/test/Regression/Transforms/ScalarRepl/badarray.ll diff -c /dev/null llvm/test/Regression/Transforms/ScalarRepl/badarray.ll:1.1 *** /dev/null Tue May 27 10:51:27 2003 --- llvm/test/Regression/Transforms/ScalarRepl/badarray.ll Tue May 27 10:51:17 2003 *************** *** 0 **** --- 1,10 ---- + ; RUN: as < %s | opt -scalarrepl -mem2reg | dis | grep alloca + + int %test() { + %X = alloca [ 4 x int ] + %Y = getelementptr [4x int]* %X, long 0, long 6 ; Off end of array! + store int 0, int* %Y + + %Z = load int* %Y + ret int %Z + } Index: llvm/test/Regression/Transforms/ScalarRepl/basictest.ll diff -c /dev/null llvm/test/Regression/Transforms/ScalarRepl/basictest.ll:1.1 *** /dev/null Tue May 27 10:51:27 2003 --- llvm/test/Regression/Transforms/ScalarRepl/basictest.ll Tue May 27 10:51:17 2003 *************** *** 0 **** --- 1,13 ---- + ; RUN: if as < %s | opt -scalarrepl -mem2reg | dis | grep alloca + ; RUN: then exit 1 + ; RUN: else exit 0 + ; RUN: fi + + int %test() { + %X = alloca { int, float } + %Y = getelementptr {int,float}* %X, long 0, ubyte 0 + store int 0, int* %Y + + %Z = load int* %Y + ret int %Z + } From lattner at cs.uiuc.edu Tue May 27 10:53:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 27 10:53:00 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Transforms/Scalar.h Message-ID: <200305271552.KAA31051@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Transforms: Scalar.h updated: 1.16 -> 1.17 --- Log message: Expose proto for SRoA pass. --- Diffs of the changes: Index: llvm/include/llvm/Transforms/Scalar.h diff -u llvm/include/llvm/Transforms/Scalar.h:1.16 llvm/include/llvm/Transforms/Scalar.h:1.17 --- llvm/include/llvm/Transforms/Scalar.h:1.16 Tue May 20 16:01:09 2003 +++ llvm/include/llvm/Transforms/Scalar.h Tue May 27 10:52:45 2003 @@ -56,6 +56,13 @@ //===----------------------------------------------------------------------===// +// +// Scalar Replacement of Aggregates - Break up alloca's of aggregates into +// multiple allocas if possible. +// +Pass *createScalarReplAggregatesPass(); + +//===----------------------------------------------------------------------===// // // DecomposeMultiDimRefs - Convert multi-dimensional references consisting of // any combination of 2 or more array and structure indices into a sequence of From lattner at cs.uiuc.edu Tue May 27 11:10:05 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 27 11:10:05 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp Message-ID: <200305271609.LAA31125@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: ScalarReplAggregates.cpp updated: 1.1 -> 1.2 --- Log message: * Actually USE the statistic that we made * Implement SRoA for arrays --- Diffs of the changes: Index: llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp diff -u llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp:1.1 llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp:1.2 --- llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp:1.1 Tue May 27 10:45:27 2003 +++ llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp Tue May 27 11:09:27 2003 @@ -52,12 +52,15 @@ WorkList.pop_back(); // We cannot transform the allocation instruction if it is an array - // allocation, and an allocation of a scalar value cannot be decomposed + // allocation (allocations OF arrays are ok though), and an allocation of a + // scalar value cannot be decomposed at all. + // if (AI->isArrayAllocation() || - (!isa(AI->getAllocatedType()) /*&& - !isa(AI->getAllocatedType())*/ - )) continue; - + (!isa(AI->getAllocatedType()) && + !isa(AI->getAllocatedType()))) continue; + + const ArrayType *AT = dyn_cast(AI->getAllocatedType()); + // Loop over the use list of the alloca. We can only transform it if there // are only getelementptr instructions (with a zero first index) and free // instructions. @@ -77,6 +80,18 @@ CannotTransform = true; break; } + + // If this is an array access, check to make sure that index falls + // within the array. If not, something funny is going on, so we won't + // do the optimization. + if (AT && cast(GEPI->getOperand(2))->getValue() >= + AT->getNumElements()) { + DEBUG(std::cerr << "Cannot transform: " << *AI << " due to user: " + << User); + CannotTransform = true; + break; + } + } else { DEBUG(std::cerr << "Cannot transform: " << *AI << " due to user: " << User); @@ -100,7 +115,6 @@ WorkList.push_back(NA); // Add to worklist for recursive processing } } else { - const ArrayType *AT = cast(AI->getAllocatedType()); ElementAllocas.reserve(AT->getNumElements()); const Type *ElTy = AT->getElementType(); for (unsigned i = 0, e = AT->getNumElements(); i != e; ++i) { @@ -158,6 +172,7 @@ // Finally, delete the Alloca instruction AI->getParent()->getInstList().erase(AI); + NumReplaced++; } return Changed; From lattner at cs.uiuc.edu Tue May 27 11:11:05 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 27 11:11:05 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/Makefile Message-ID: <200305271610.LAA31160@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms: Makefile updated: 1.22 -> 1.23 --- Log message: Start testing SRoA --- Diffs of the changes: Index: llvm/test/Regression/Transforms/Makefile diff -u llvm/test/Regression/Transforms/Makefile:1.22 llvm/test/Regression/Transforms/Makefile:1.23 --- llvm/test/Regression/Transforms/Makefile:1.22 Tue May 6 14:04:02 2003 +++ llvm/test/Regression/Transforms/Makefile Tue May 27 11:10:03 2003 @@ -22,6 +22,7 @@ ProfilePaths \ Reassociate \ SCCP \ + ScalarRepl \ SimplifyCFG include $(LEVEL)/Makefile.common From lattner at cs.uiuc.edu Tue May 27 11:26:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 27 11:26:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Support/Signals.cpp Message-ID: <200305271625.LAA31273@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Support: Signals.cpp updated: 1.4 -> 1.5 --- Log message: Make _sure_ we don't go into an infinite loop if a signal happens! --- Diffs of the changes: Index: llvm/lib/Support/Signals.cpp diff -u llvm/lib/Support/Signals.cpp:1.4 llvm/lib/Support/Signals.cpp:1.5 --- llvm/lib/Support/Signals.cpp:1.4 Thu May 22 16:59:35 2003 +++ llvm/lib/Support/Signals.cpp Tue May 27 11:25:04 2003 @@ -42,6 +42,7 @@ exit(1); // If this is an interrupt signal, exit the program // Otherwise if it is a fault (like SEGV) reissue the signal to die... + signal(Sig, SIG_DFL); } static void RegisterHandler(int Signal) { signal(Signal, SignalHandler); } From lattner at cs.uiuc.edu Tue May 27 11:42:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 27 11:42:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200305271641.LAA31340@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.84 -> 1.85 --- Log message: Fix bug: Instcombine/2003-05-27-ConstExprCrash.ll --- Diffs of the changes: Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.84 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.85 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.84 Mon May 26 18:41:32 2003 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Tue May 27 11:40:51 2003 @@ -17,9 +17,10 @@ #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Local.h" -#include "llvm/ConstantHandling.h" #include "llvm/Instructions.h" #include "llvm/Pass.h" +#include "llvm/Constants.h" +#include "llvm/ConstantHandling.h" #include "llvm/DerivedTypes.h" #include "llvm/Support/InstIterator.h" #include "llvm/Support/InstVisitor.h" @@ -149,9 +150,9 @@ if (BinaryOperator *Op = dyn_cast(I.getOperand(0))) if (Op->getOpcode() == Opcode && isa(Op->getOperand(1))) { if (isa(I.getOperand(1))) { - Constant *Folded = ConstantFoldBinaryInstruction(I.getOpcode(), - cast(I.getOperand(1)), cast(Op->getOperand(1))); - assert(Folded && "Couldn't constant fold commutative operand?"); + Constant *Folded = ConstantExpr::get(I.getOpcode(), + cast(I.getOperand(1)), + cast(Op->getOperand(1))); I.setOperand(0, Op->getOperand(0)); I.setOperand(1, Folded); return true; @@ -162,8 +163,7 @@ Constant *C2 = cast(Op1->getOperand(1)); // Fold (op (op V1, C1), (op V2, C2)) ==> (op (op V1, V2), (op C1,C2)) - Constant *Folded = ConstantFoldBinaryInstruction(I.getOpcode(),C1,C2); - assert(Folded && "Couldn't constant fold commutative operand?"); + Constant *Folded = ConstantExpr::get(I.getOpcode(), C1, C2); Instruction *New = BinaryOperator::create(Opcode, Op->getOperand(0), Op1->getOperand(0), Op1->getName(), &I); @@ -185,7 +185,8 @@ // Constants can be considered to be negated values if they can be folded... if (Constant *C = dyn_cast(V)) - return *Constant::getNullValue(V->getType()) - *C; + return ConstantExpr::get(Instruction::Sub, + Constant::getNullValue(V->getType()), C); return 0; } @@ -195,7 +196,8 @@ // Constants can be considered to be not'ed values... if (ConstantIntegral *C = dyn_cast(V)) - return *ConstantIntegral::getAllOnesValue(C->getType()) ^ *C; + return ConstantExpr::get(Instruction::Xor, + ConstantIntegral::getAllOnesValue(C->getType()),C); return 0; } @@ -256,24 +258,26 @@ // X*C + X --> X * (C+1) if (dyn_castFoldableMul(LHS) == RHS) { - Constant *CP1 = *cast(cast(LHS)->getOperand(1)) + - *ConstantInt::get(I.getType(), 1); - assert(CP1 && "Couldn't constant fold C + 1?"); + Constant *CP1 = + ConstantExpr::get(Instruction::Add, + cast(cast(LHS)->getOperand(1)), + ConstantInt::get(I.getType(), 1)); return BinaryOperator::create(Instruction::Mul, RHS, CP1); } // X + X*C --> X * (C+1) if (dyn_castFoldableMul(RHS) == LHS) { - Constant *CP1 = *cast(cast(RHS)->getOperand(1)) + - *ConstantInt::get(I.getType(), 1); - assert(CP1 && "Couldn't constant fold C + 1?"); + Constant *CP1 = + ConstantExpr::get(Instruction::Add, + cast(cast(RHS)->getOperand(1)), + ConstantInt::get(I.getType(), 1)); return BinaryOperator::create(Instruction::Mul, LHS, CP1); } // (A & C1)+(B & C2) -> (A & C1)|(B & C2) iff C1&C2 == 0 if (Constant *C1 = dyn_castMaskingAnd(LHS)) if (Constant *C2 = dyn_castMaskingAnd(RHS)) - if ((*C1 & *C2)->isNullValue()) + if (ConstantExpr::get(Instruction::And, C1, C2)->isNullValue()) return BinaryOperator::create(Instruction::Or, LHS, RHS); return Changed ? &I : 0; @@ -321,8 +325,10 @@ // X - X*C --> X * (1-C) if (dyn_castFoldableMul(Op1I) == Op0) { - Constant *CP1 = *ConstantInt::get(I.getType(), 1) - - *cast(cast(Op1)->getOperand(1)); + Constant *CP1 = + ConstantExpr::get(Instruction::Sub, + ConstantInt::get(I.getType(), 1), + cast(cast(Op1)->getOperand(1))); assert(CP1 && "Couldn't constant fold 1-C?"); return BinaryOperator::create(Instruction::Mul, Op0, CP1); } @@ -330,8 +336,10 @@ // X*C - X --> X * (C-1) if (dyn_castFoldableMul(Op0) == Op1) { - Constant *CP1 = *cast(cast(Op0)->getOperand(1)) - - *ConstantInt::get(I.getType(), 1); + Constant *CP1 = + ConstantExpr::get(Instruction::Sub, + cast(cast(Op0)->getOperand(1)), + ConstantInt::get(I.getType(), 1)); assert(CP1 && "Couldn't constant fold C - 1?"); return BinaryOperator::create(Instruction::Mul, Op1, CP1); } @@ -595,7 +603,7 @@ // (A & C1)^(B & C2) -> (A & C1)|(B & C2) iff C1^C2 == 0 if (Constant *C1 = dyn_castMaskingAnd(Op0)) if (Constant *C2 = dyn_castMaskingAnd(Op1)) - if ((*C1 & *C2)->isNullValue()) + if (ConstantExpr::get(Instruction::And, C1, C2)->isNullValue()) return BinaryOperator::create(Instruction::Or, Op0, Op1); return Changed ? &I : 0; @@ -603,12 +611,14 @@ // AddOne, SubOne - Add or subtract a constant one from an integer constant... static Constant *AddOne(ConstantInt *C) { - Constant *Result = *C + *ConstantInt::get(C->getType(), 1); + Constant *Result = ConstantExpr::get(Instruction::Add, C, + ConstantInt::get(C->getType(), 1)); assert(Result && "Constant folding integer addition failed!"); return Result; } static Constant *SubOne(ConstantInt *C) { - Constant *Result = *C - *ConstantInt::get(C->getType(), 1); + Constant *Result = ConstantExpr::get(Instruction::Sub, C, + ConstantInt::get(C->getType(), 1)); assert(Result && "Constant folding integer addition failed!"); return Result; } @@ -745,10 +755,9 @@ // Calculate bitmask for what gets shifted off the edge... Constant *C = ConstantIntegral::getAllOnesValue(I.getType()); if (I.getOpcode() == Instruction::Shr) - C = *C >> *ShiftAmt1C; + C = ConstantExpr::getShift(Instruction::Shr, C, ShiftAmt1C); else - C = *C << *ShiftAmt1C; - assert(C && "Couldn't constant fold shift expression?"); + C = ConstantExpr::getShift(Instruction::Shl, C, ShiftAmt1C); Instruction *Mask = BinaryOperator::create(Instruction::And, Op0SI->getOperand(0), @@ -957,8 +966,9 @@ isa(GEP.getOperand(1))) { // Replace: gep (gep %P, long C1), long C2, ... // With: gep %P, long (C1+C2), ... - Value *Sum = *cast(Src->getOperand(1)) + - *cast(GEP.getOperand(1)); + Value *Sum = ConstantExpr::get(Instruction::Add, + cast(Src->getOperand(1)), + cast(GEP.getOperand(1))); assert(Sum && "Constant folding of longs failed!?"); GEP.setOperand(0, Src->getOperand(0)); GEP.setOperand(1, Sum); From lattner at cs.uiuc.edu Tue May 27 11:46:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 27 11:46:02 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/InstCombine/2003-05-27-ConstExprCrash.ll Message-ID: <200305271645.LAA31422@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/InstCombine: 2003-05-27-ConstExprCrash.ll added (r1.1) --- Log message: New testcase --- Diffs of the changes: Index: llvm/test/Regression/Transforms/InstCombine/2003-05-27-ConstExprCrash.ll diff -c /dev/null llvm/test/Regression/Transforms/InstCombine/2003-05-27-ConstExprCrash.ll:1.1 *** /dev/null Tue May 27 11:45:19 2003 --- llvm/test/Regression/Transforms/InstCombine/2003-05-27-ConstExprCrash.ll Tue May 27 11:45:09 2003 *************** *** 0 **** --- 1,8 ---- + ; RUN: as < %s | opt -instcombine -disable-output + + %X = global int 5 + long %test() { + %C = add long 1, 2 + %V = add long cast(int* %X to long), %C + ret long %V + } From lattner at cs.uiuc.edu Tue May 27 14:16:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 27 14:16:01 2003 Subject: [llvm-commits] CVS: llvm/tools/gccld/gccld.cpp Message-ID: <200305271915.OAA32506@apoc.cs.uiuc.edu> Changes in directory llvm/tools/gccld: gccld.cpp updated: 1.31 -> 1.32 --- Log message: Add compatibility option --- Diffs of the changes: Index: llvm/tools/gccld/gccld.cpp diff -u llvm/tools/gccld/gccld.cpp:1.31 llvm/tools/gccld/gccld.cpp:1.32 --- llvm/tools/gccld/gccld.cpp:1.31 Fri May 23 15:27:07 2003 +++ llvm/tools/gccld/gccld.cpp Tue May 27 14:15:11 2003 @@ -68,6 +68,8 @@ CO4("version-script", cl::Hidden, cl::desc("Compatibility option: ignored")); cl::opt CO5("eh-frame-hdr", cl::Hidden, cl::desc("Compatibility option: ignored")); + cl::opt + CO6("r", cl::Hidden, cl::desc("Compatibility option: ignored")); } // FileExists - Return true if the specified string is an openable file... From lattner at cs.uiuc.edu Tue May 27 14:17:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 27 14:17:01 2003 Subject: [llvm-commits] CVS: llvm/lib/VMCore/ConstantHandling.cpp Message-ID: <200305271916.OAA32536@apoc.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: ConstantHandling.cpp updated: 1.30 -> 1.31 --- Log message: Fix constant folding to ALWAYS work. --- Diffs of the changes: Index: llvm/lib/VMCore/ConstantHandling.cpp diff -u llvm/lib/VMCore/ConstantHandling.cpp:1.30 llvm/lib/VMCore/ConstantHandling.cpp:1.31 --- llvm/lib/VMCore/ConstantHandling.cpp:1.30 Wed May 14 12:51:05 2003 +++ llvm/lib/VMCore/ConstantHandling.cpp Tue May 27 14:16:07 2003 @@ -6,6 +6,7 @@ #include "llvm/ConstantHandling.h" #include "llvm/iPHINode.h" +#include "llvm/InstrTypes.h" #include "llvm/DerivedTypes.h" #include @@ -45,26 +46,15 @@ } } + if (isa(I)) + return ConstantExpr::get(I->getOpcode(), Op0, Op1); + switch (I->getOpcode()) { case Instruction::Cast: - return ConstRules::get(*Op0, *Op0)->castTo(Op0, I->getType()); - case Instruction::Add: return *Op0 + *Op1; - case Instruction::Sub: return *Op0 - *Op1; - case Instruction::Mul: return *Op0 * *Op1; - case Instruction::Div: return *Op0 / *Op1; - case Instruction::Rem: return *Op0 % *Op1; - case Instruction::And: return *Op0 & *Op1; - case Instruction::Or: return *Op0 | *Op1; - case Instruction::Xor: return *Op0 ^ *Op1; - - case Instruction::SetEQ: return *Op0 == *Op1; - case Instruction::SetNE: return *Op0 != *Op1; - case Instruction::SetLE: return *Op0 <= *Op1; - case Instruction::SetGE: return *Op0 >= *Op1; - case Instruction::SetLT: return *Op0 < *Op1; - case Instruction::SetGT: return *Op0 > *Op1; - case Instruction::Shl: return *Op0 << *Op1; - case Instruction::Shr: return *Op0 >> *Op1; + return ConstantExpr::getCast(Op0, I->getType()); + case Instruction::Shl: + case Instruction::Shr: + return ConstantExpr::getShift(I->getOpcode(), Op0, Op1); case Instruction::GetElementPtr: { std::vector IdxList; IdxList.reserve(I->getNumOperands()-1); @@ -74,7 +64,7 @@ IdxList.push_back(C); else return 0; // Non-constant operand - return ConstantFoldGetElementPtr(Op0, IdxList); + return ConstantExpr::getGetElementPtr(Op0, IdxList); } default: return 0; From brukman at cs.uiuc.edu Tue May 27 15:04:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 15:04:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcV9.td Message-ID: <200305272003.PAA22586@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcV9.td updated: 1.1 -> 1.2 --- Log message: Added definitions for a bunch of floating-point instructions. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/SparcV9.td diff -u llvm/lib/Target/Sparc/SparcV9.td:1.1 llvm/lib/Target/Sparc/SparcV9.td:1.2 --- llvm/lib/Target/Sparc/SparcV9.td:1.1 Wed May 7 16:52:39 2003 +++ llvm/lib/Target/Sparc/SparcV9.td Tue May 27 15:03:29 2003 @@ -1,5 +1,5 @@ //===- Sparc.td - Target Description for Sparc V9 Target --------*- C++ -*-===// -// +// vim:ft=cpp //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// @@ -35,7 +35,15 @@ // Ri - One of the 32 64 bit integer registers class Ri num> : V9Reg { set Size = 64; field bits<5> Num = num; } -def G0 : Ri<0>; def G1 : Ri<1>; def G2 : Ri<2>; def G3 : Ri<3>; +def G0 : Ri< 0>; def G1 : Ri< 1>; def G2 : Ri< 2>; def G3 : Ri< 3>; +def G4 : Ri< 4>; def G5 : Ri< 5>; def G6 : Ri< 6>; def G7 : Ri< 7>; +def O0 : Ri< 8>; def O1 : Ri< 9>; def O2 : Ri<10>; def O3 : Ri<11>; +def O4 : Ri<12>; def O5 : Ri<13>; def O6 : Ri<14>; def O7 : Ri<15>; +def L0 : Ri<16>; def L1 : Ri<17>; def L2 : Ri<18>; def L3 : Ri<19>; +def L4 : Ri<20>; def L5 : Ri<21>; def L6 : Ri<22>; def L7 : Ri<23>; +def I0 : Ri<24>; def I1 : Ri<25>; def I2 : Ri<26>; def I3 : Ri<27>; +def I4 : Ri<28>; def I5 : Ri<29>; def I6 : Ri<30>; def I7 : Ri<31>; +// Floating-point registers? // ... @@ -67,6 +75,16 @@ set Inst{24-22} = op2; } +// Format 2.1 instructions +class F2_1 : F2 { + bits<5> rd; + bits<22> imm; + + set Name = name; + set Inst{29-25} = rd; + set Inst{21-0} = imm; +} + class F2_br : F2 { // Format 2 Branch instruction bit annul; // All branches have an annul bit set Inst{29} = annul; @@ -129,13 +147,17 @@ } // F3_rs1rd - Common superclass of instructions that use rs1 & rd... -class F3_rs1rd : F3_rs1 { +class F3_rs1rd : F3 { + // Added rs1 here manually to have rd appear before rs1 + // Formerly inherited directly from F3_rs1 bits<5> rd; + bits<5> rs1; set Inst{29-25} = rd; + set Inst{18-14} = rs1; } // F3_rs1rdrs2 - Common superclass of instructions with rs1, rd, & rs2 fields -class F3_rs1rdrs2 : F3_rs1 { +class F3_rs1rdrs2 : F3_rs1rd { bits<5> rs2; set Inst{4-0} = rs2; } @@ -172,18 +194,55 @@ set Inst{4-0} = rs2; } -class F3_4 opVal, bits<6> op3val, string name> : F3_rs1 { +class F3_4 opVal, bits<6> op3Val, string name> : F3_rs1 { bits<13> simm; set op = opVal; - set op3 = op3val; + set op3 = op3Val; set Name = name; //set Inst{29-25} = dontcare; set Inst{13} = 1; set Inst{12-0} = simm; } +class F3_11 opVal, bits<6> op3Val, string name> : F3_rs1rdrs2 { + bit x; + set op = opVal; + set op3 = op3Val; + set Name = name; + set Inst{13} = 0; // i field = 0 + set Inst{12} = x; + //set Inst{11-5} = dontcare; +} + +class F3_12 opVal, bits<6> op3Val, string name> : F3 { + bits<5> shcnt; + + set Name = name; + set Inst{13} = 1; // i field = 1 + set Inst{12} = 0; // x field = 0 + //set Inst{11-5} = dontcare; + set Inst{4-0} = shcnt; +} +class F3_13 opVal, bits<6> op3Val, string name> : F3 { + bits<6> shcnt; + set Name = name; + set Inst{13} = 1; // i field = 1 + set Inst{12} = 1; // x field = 1 + //set Inst{11-6} = dontcare; + set Inst{5-0} = shcnt; +} + +class F3_14 opVal, bits<6> op3val, + bits<9> opfval, string name> : F3_rs1rdrs2 { + set op = opVal; + set op3 = op3val; + set Name = name; + //set Inst{18-14} = dontcare; + set Inst{13-5} = opfval; +} + class F3_16 opVal, bits<6> op3val, bits<9> opfval, string name> : F3_rs1rdrs2 { set op = opVal; @@ -207,12 +266,12 @@ // Section A.2: p161 def ADDr : F3_1<2, 0b000000, "add">; // add r, r, r def ADDi : F3_2<2, 0b000000, "add">; // add r, r, i -def ADDCCr : F3_1<2, 0b010000, "addcc">; // addcc r, r, r -def ADDCCi : F3_2<2, 0b010000, "addcc">; // addcc r, r, i +def ADDccr : F3_1<2, 0b010000, "addcc">; // addcc r, r, r +def ADDcci : F3_2<2, 0b010000, "addcc">; // addcc r, r, i def ADDCr : F3_1<2, 0b001000, "addC">; // addC r, r, r def ADDCi : F3_2<2, 0b001000, "addC">; // addC r, r, i -def ADDCCCr : F3_1<2, 0b011000, "addCcc">; // addCcc r, r, r -def ADDCCCi : F3_2<2, 0b011000, "addCcc">; // addCcc r, r, i +def ADDCccr : F3_1<2, 0b011000, "addCcc">; // addCcc r, r, r +def ADDCcci : F3_2<2, 0b011000, "addCcc">; // addCcc r, r, i // Section A.3: p162 set op2 = 0b011 in { @@ -247,24 +306,24 @@ } // Section A.5: p167 -set op2 = 0b101 in { - def FBPA : F2_3<0b1000, "fbpa">; // Branch always - def FBPN : F2_3<0b0000, "fbpn">; // Branch never - def FBPU : F2_3<0b0111, "fbpu">; // Branch on unordered - def FBPG : F2_3<0b0110, "fbpg">; // Branch > - def FBPUG : F2_3<0b0101, "fbpug">; // Branch on unordered or > - def FBPL : F2_3<0b0100, "fbpl">; // Branch < - def FBPUL : F2_3<0b0011, "fbpul">; // Branch on unordered or < - def FBPLG : F2_3<0b0010, "fbplg">; // Branch < or > - def FBPNE : F2_3<0b0001, "fbpne">; // Branch != - def FBPE : F2_3<0b1001, "fbpe">; // Branch == - def FBPUE : F2_3<0b1010, "fbpue">; // Branch on unordered or == - def FBPGE : F2_3<0b1011, "fbpge">; // Branch > or == - def FBPUGE : F2_3<0b1100, "fbpuge">; // Branch unord or > or == - def FBPLE : F2_3<0b1101, "fbple">; // Branch < or == - def FBPULE : F2_3<0b1110, "fbpule">; // Branch unord or < or == - def FBPO : F2_3<0b1111, "fbpo">; // Branch on ordered -} +//set op2 = 0b101 in { + //def FBPA : F2_3<0b1000, "fbpa">; // Branch always + //def FBPN : F2_3<0b0000, "fbpn">; // Branch never + //def FBPU : F2_3<0b0111, "fbpu">; // Branch on unordered + //def FBPG : F2_3<0b0110, "fbpg">; // Branch > + //def FBPUG : F2_3<0b0101, "fbpug">; // Branch on unordered or > + //def FBPL : F2_3<0b0100, "fbpl">; // Branch < + //def FBPUL : F2_3<0b0011, "fbpul">; // Branch on unordered or < + //def FBPLG : F2_3<0b0010, "fbplg">; // Branch < or > + //def FBPNE : F2_3<0b0001, "fbpne">; // Branch != + //def FBPE : F2_3<0b1001, "fbpe">; // Branch == + //def FBPUE : F2_3<0b1010, "fbpue">; // Branch on unordered or == + //def FBPGE : F2_3<0b1011, "fbpge">; // Branch > or == + //def FBPUGE : F2_3<0b1100, "fbpuge">; // Branch unord or > or == + //def FBPLE : F2_3<0b1101, "fbple">; // Branch < or == + //def FBPULE : F2_3<0b1110, "fbpule">; // Branch unord or < or == + //def FBPO : F2_3<0b1111, "fbpo">; // Branch on ordered +//} // Section A.6: p170: Bicc set isDeprecated = 1 in { @@ -289,25 +348,24 @@ } // Section A.7: p172 -set op2 = 0b001 in { - def BPA : F2_3<0b1000, "bpa">; // Branch always - def BPN : F2_3<0b0000, "bpn">; // Branch never - def BPNE : F2_3<0b1001, "bpne">; // Branch != - def BPE : F2_3<0b0001, "bpe">; // Branch == - def BPG : F2_3<0b1010, "bpg">; // Branch > - def BPLE : F2_3<0b0010, "bple">; // Branch <= - def BPGE : F2_3<0b1011, "bpge">; // Branch >= - def BPL : F2_3<0b0011, "bpl">; // Branch < - def BPGU : F2_3<0b1100, "bpgu">; // Branch unsigned > - - def BPLEU : F2_3<0b0100, "bpleu">; // Branch unsigned <= - def BPCC : F2_3<0b1101, "bpcc">; // Branch unsigned >= - def BPCS : F2_3<0b0101, "bpcs">; // Branch unsigned <= - def BPPOS : F2_3<0b1110, "bppos">; // Branch on positive - def BPNEG : F2_3<0b0110, "bpneg">; // Branch on negative - def BPVC : F2_3<0b1111, "bpvc">; // Branch on overflow clear - def BPVS : F2_3<0b0111, "bpvs">; // Branch on overflow set -} +//set op2 = 0b001 in { +// def BPA : F2_3<0b1000, "bpa">; // Branch always +// def BPN : F2_3<0b0000, "bpn">; // Branch never +// def BPNE : F2_3<0b1001, "bpne">; // Branch != +// def BPE : F2_3<0b0001, "bpe">; // Branch == +// def BPG : F2_3<0b1010, "bpg">; // Branch > +// def BPLE : F2_3<0b0010, "bple">; // Branch <= +// def BPGE : F2_3<0b1011, "bpge">; // Branch >= +// def BPL : F2_3<0b0011, "bpl">; // Branch < +// def BPGU : F2_3<0b1100, "bpgu">; // Branch unsigned > +// def BPLEU : F2_3<0b0100, "bpleu">; // Branch unsigned <= +// def BPCC : F2_3<0b1101, "bpcc">; // Branch unsigned >= +// def BPCS : F2_3<0b0101, "bpcs">; // Branch unsigned <= +// def BPPOS : F2_3<0b1110, "bppos">; // Branch on positive +// def BPNEG : F2_3<0b0110, "bpneg">; // Branch on negative +// def BPVC : F2_3<0b1111, "bpvc">; // Branch on overflow clear +// def BPVS : F2_3<0b0111, "bpvs">; // Branch on overflow set +//} // Section A.8: p175 - CALL - the only Format #1 instruction def CALL : InstV9 { @@ -323,22 +381,23 @@ // Section A.10: Divide (64-bit / 32-bit) - p178 -set isDeprecated = 1 in { - def UDIVr : F3_1<2, 0b001110, "udiv">; // udiv r, r, r - def UDIVi : F3_2<2, 0b001110, "udiv">; // udiv r, r, i - def SDIVr : F3_1<2, 0b001111, "sdiv">; // sdiv r, r, r - def SDIVi : F3_2<2, 0b001111, "sdiv">; // sdiv r, r, i - def UDIVCCr : F3_1<2, 0b011110, "udivcc">; // udivcc r, r, r - def UDIVCCi : F3_2<2, 0b011110, "udivcc">; // udivcc r, r, i - def SDIVCCr : F3_1<2, 0b011111, "sdivcc">; // sdivcc r, r, r - def SDIVCCi : F3_2<2, 0b011111, "sdivcc">; // sdivcc r, r, i -} +// Not used in the Sparc backend +//set isDeprecated = 1 in { + //def UDIVr : F3_1<2, 0b001110, "udiv">; // udiv r, r, r + //def UDIVi : F3_2<2, 0b001110, "udiv">; // udiv r, r, i + //def SDIVr : F3_1<2, 0b001111, "sdiv">; // sdiv r, r, r + //def SDIVi : F3_2<2, 0b001111, "sdiv">; // sdiv r, r, i + //def UDIVCCr : F3_1<2, 0b011110, "udivcc">; // udivcc r, r, r + //def UDIVCCi : F3_2<2, 0b011110, "udivcc">; // udivcc r, r, i + //def SDIVCCr : F3_1<2, 0b011111, "sdivcc">; // sdivcc r, r, r + //def SDIVCCi : F3_2<2, 0b011111, "sdivcc">; // sdivcc r, r, i +//} // Section A.11: DONE and RETRY - p181 -set isPrivileged = 1 in { - def DONE : F3_18<0, "done">; // done - def RETRY : F3_18<1, "retry">; // retry -} +//set isPrivileged = 1 in { + //def DONE : F3_18<0, "done">; // done + //def RETRY : F3_18<1, "retry">; // retry +//} // Section A.12: Floating-Point Add and Subtract - p182 def FADDS : F3_16<2, 0b110100, 0x41, "fadds">; // fadds f, f, f @@ -348,12 +407,269 @@ def FSUBD : F3_16<2, 0b110100, 0x46, "fsubd">; // fsubd f, f, f def FSUBQ : F3_16<2, 0b110100, 0x47, "fsubq">; // fsubq f, f, f -// -// ... -// +// Section A.17: Floating-Point Move - p164 +def FMOVS : F3_14<2, 0b110100, 0b000000001, "fmovs">; // fmovs r, r +def FMOVD : F3_14<2, 0b110100, 0b000000010, "fmovs">; // fmovd r, r +//def FMOVQ : F3_14<2, 0b110100, 0b000000011, "fmovs">; // fmovq r, r +def FNEGS : F3_14<2, 0b110100, 0b000000101, "fnegs">; // fnegs r, r +def FNEGD : F3_14<2, 0b110100, 0b000000110, "fnegs">; // fnegs r, r +//def FNEGQ : F3_14<2, 0b110100, 0b000000111, "fnegs">; // fnegs r, r +def FABSS : F3_14<2, 0b110100, 0b000001001, "fabss">; // fabss r, r +def FABSD : F3_14<2, 0b110100, 0b000001010, "fabss">; // fabss r, r +//def FABSQ : F3_14<2, 0b110100, 0b000001011, "fabss">; // fabss r, r + +// Section A.18: Floating-Point Multiply and Divide - p165 +def FMULS : F3_16<2, 0b110100, 0b001001001, "fmuls">; // fmuls r, r, r +def FMULD : F3_16<2, 0b110100, 0b001001010, "fmuld">; // fmuld r, r, r +def FMULQ : F3_16<2, 0b110100, 0b001001011, "fmulq">; // fmulq r, r, r +def FSMULD : F3_16<2, 0b110100, 0b001101001, "fsmuld">; // fsmuls r, r, r +def FDMULQ : F3_16<2, 0b110100, 0b001101110, "fdmulq">; // fdmuls r, r, r +def FDIVS : F3_16<2, 0b110100, 0b001001101, "fdivs">; // fdivs r, r, r +def FDIVD : F3_16<2, 0b110100, 0b001001110, "fdivs">; // fdivd r, r, r +def FDIVQ : F3_16<2, 0b110100, 0b001001111, "fdivs">; // fdivq r, r, r + +// Section A.19: Floating-Point Square Root - p166 +def FSQRTS : F3_14<2, 0b110100, 0b000101001, "fsqrts">; // fsqrts r, r +def FSQRTD : F3_14<2, 0b110100, 0b000101010, "fsqrts">; // fsqrts r, r +def FSQRTQ : F3_14<2, 0b110100, 0b000101011, "fsqrts">; // fsqrts r, r + +// Section A.24: Jump and Link +// Mimicking the Sparc's instr def... +def JMPLCALLr : F3_1<2, 0b111000, "jmpl">; // jmpl [r+r], r +def JMPLCALLi : F3_1<2, 0b111000, "jmpl">; // jmpl [r+i], r +def JMPLRETr : F3_1<2, 0b111000, "jmpl">; // jmpl [r+r], r +def JMPLRETi : F3_1<2, 0b111000, "jmpl">; // jmpl [r+i], r + +// FIXME: FCMPS, FCMPD, FCMPQ !!! +// FIXME: FMULS, FMULD, FMULQ, ... + +// Section A.25: Load Floating-Point - p173 +def LDFr : F3_1<3, 0b100000, "ld">; // ld [r+r], r +def LDFi : F3_2<3, 0b100000, "ld">; // ld [r+i], r +def LDDFr : F3_1<3, 0b100011, "ldd">; // ldd [r+r], r +def LDDFi : F3_2<3, 0b100011, "ldd">; // ldd [r+i], r +def LDQFr : F3_1<3, 0b100010, "ldq">; // ldq [r+r], r +def LDQFi : F3_2<3, 0b100010, "ldq">; // ldq [r+i], r +set isDeprecated = 1 in { + set rd = 0 in { + def LDFSRr : F3_1<3, 0b100001, "ld">; // ld [r+r], r + def LDFSRi : F3_2<3, 0b100001, "ld">; // ld [r+i], r + } +} +set rd = 1 in { + def LDXFSRr : F3_1<3, 0b100001, "ldx">; // ldx [r+r], r + def LDXFSRi : F3_2<3, 0b100001, "ldx">; // ldx [r+i], r +} + +// Section A.27: Load Integer - p178 +def LDSBr : F3_1<3, 0b001001, "ldsb">; // ldsb [r+r], r +def LDSBi : F3_2<3, 0b001001, "ldsb">; // ldsb [r+i], r +def LDSHr : F3_1<3, 0b001010, "ldsh">; // ldsh [r+r], r +def LDSHi : F3_2<3, 0b001010, "ldsh">; // ldsh [r+i], r +def LDSWr : F3_1<3, 0b001000, "ldsw">; // ldsh [r+r], r +def LDSWi : F3_2<3, 0b001000, "ldsw">; // ldsh [r+i], r +def LDUBr : F3_1<3, 0b000001, "ldub">; // ldub [r+r], r +def LDUBi : F3_2<3, 0b000001, "ldub">; // ldub [r+i], r +def LDUHr : F3_1<3, 0b000010, "lduh">; // lduh [r+r], r +def LDUHi : F3_2<3, 0b000010, "lduh">; // lduh [r+i], r +// synonym: LD +def LDUWr : F3_1<3, 0b000000, "lduw">; // lduw [r+r], r +def LDUWi : F3_2<3, 0b000000, "lduw">; // lduw [r+i], r +// LDD should no longer be used, LDX should be used instead +def LDXr : F3_1<3, 0b001011, "ldx">; // ldx [r+r], r +def LDXi : F3_2<3, 0b001011, "ldx">; // ldx [r+i], r +//set isDeprecated = 1 in { +// def LDDr : F3_1<3, 0b000011, "ldd">; // ldd [r+r], r +// def LDDi : F3_2<3, 0b000011, "ldd">; // ldd [r+i], r +//} + +// Section A.31: Logical operations +def ANDr : F3_1<2, 0b000001, "and">; // and r, r, r +def ANDi : F3_2<2, 0b000001, "and">; // and r, r, i +def ANDccr : F3_1<2, 0b010001, "andcc">; // andcc r, r, r +def ANDcci : F3_2<2, 0b010001, "andcc">; // andcc r, r, i +def ANDNr : F3_1<2, 0b000101, "andn">; // andn r, r, r +def ANDNi : F3_2<2, 0b000101, "andn">; // andn r, r, i +def ANDNccr : F3_1<2, 0b010101, "andncc">; // andncc r, r, r +def ANDNcci : F3_2<2, 0b010101, "andncc">; // andncc r, r, i + +def ORr : F3_1<2, 0b000010, "or">; // or r, r, r +def ORi : F3_2<2, 0b000010, "or">; // or r, r, i +def ORccr : F3_1<2, 0b010010, "orcc">; // orcc r, r, r +def ORcci : F3_2<2, 0b010010, "orcc">; // orcc r, r, i +def ORNr : F3_1<2, 0b000110, "orn">; // orn r, r, r +def ORNi : F3_2<2, 0b000110, "orn">; // orn r, r, i +def ORNccr : F3_1<2, 0b010110, "orncc">; // orncc r, r, r +def ORNcci : F3_2<2, 0b010110, "orncc">; // orncc r, r, i + +def XORr : F3_1<2, 0b000011, "xor">; // xor r, r, r +def XORi : F3_2<2, 0b000011, "xor">; // xor r, r, i +def XORccr : F3_1<2, 0b010011, "xorcc">; // xorcc r, r, r +def XORcci : F3_2<2, 0b010011, "xorcc">; // xorcc r, r, i +def XNORr : F3_1<2, 0b000111, "xnor">; // xnor r, r, r +def XNORi : F3_2<2, 0b000111, "xnor">; // xnor r, r, i +def XNORccr : F3_1<2, 0b010111, "xnorcc">; // xnorcc r, r, r +def XNORcci : F3_2<2, 0b010111, "xnorcc">; // xnorcc r, r, i + +#if 0 +// Section A.33: Move Floating-Point Register on Condition (FMOVcc) +// For integer condition codes +def FMOVA : F4_7<2, 0b110101, 0b1000, "fmova">; // fmova r, r +def FMOVN : F4_7<2, 0b110101, 0b0000, "fmovn">; // fmovn r, r +def FMOVNE : F4_7<2, 0b110101, 0b1001, "fmovne">; // fmovne r, r +def FMOVE : F4_7<2, 0b110101, 0b0000, "fmove">; // fmove r, r +def FMOVG : F4_7<2, 0b110101, 0b1010, "fmovg">; // fmovg r, r +def FMOVLE : F4_7<2, 0b110101, 0b0000, "fmovle">; // fmovle r, r +def FMOVGE : F4_7<2, 0b110101, 0b1011, "fmovge">; // fmovge r, r +def FMOVL : F4_7<2, 0b110101, 0b0011, "fmovl">; // fmovl r, r +def FMOVGU : F4_7<2, 0b110101, 0b1100, "fmovgu">; // fmovgu r, r +def FMOVLEU : F4_7<2, 0b110101, 0b0100, "fmovleu">; // fmovleu r, r +def FMOVCC : F4_7<2, 0b110101, 0b1101, "fmovcc">; // fmovcc r, r +def FMOVCS : F4_7<2, 0b110101, 0b0101, "fmovcs">; // fmovcs r, r +def FMOVPOS : F4_7<2, 0b110101, 0b1110, "fmovpos">; // fmovpos r, r +def FMOVNEG : F4_7<2, 0b110101, 0b0110, "fmovneg">; // fmovneg r, r +def FMOVVC : F4_7<2, 0b110101, 0b1111, "fmovvc">; // fmovvc r, r +def FMOVVS : F4_7<2, 0b110101, 0b0111, "fmovvs">; // fmovvs r, r + +// For floating-point condition codes +def FMOVFA : F4_7<2, 0b110101, 0b0100, "fmovfa">; // fmovfa r, r +def FMOVFN : F4_7<2, 0b110101, 0b0000, "fmovfn">; // fmovfa r, r +def FMOVFU : F4_7<2, 0b110101, 0b0111, "fmovfu">; // fmovfu r, r +def FMOVFG : F4_7<2, 0b110101, 0b0110, "fmovfg">; // fmovfg r, r +def FMOVFUG : F4_7<2, 0b110101, 0b0101, "fmovfug">; // fmovfug r, r +def FMOVFL : F4_7<2, 0b110101, 0b0100, "fmovfl">; // fmovfl r, r +def FMOVFUL : F4_7<2, 0b110101, 0b0011, "fmovful">; // fmovful r, r +def FMOVFLG : F4_7<2, 0b110101, 0b0010, "fmovflg">; // fmovflg r, r +def FMOVFNE : F4_7<2, 0b110101, 0b0001, "fmovfne">; // fmovfne r, r +def FMOVFE : F4_7<2, 0b110101, 0b1001, "fmovfe">; // fmovfe r, r +def FMOVFUE : F4_7<2, 0b110101, 0b1010, "fmovfue">; // fmovfue r, r +def FMOVGE : F4_7<2, 0b110101, 0b1011, "fmovge">; // fmovge r, r +def FMOVFUGE : F4_7<2, 0b110101, 0b1100, "fmovfuge">; // fmovfuge r, r +def FMOVFLE : F4_7<2, 0b110101, 0b1101, "fmovfle">; // fmovfle r, r +def FMOVFULE : F4_7<2, 0b110101, 0b1110, "fmovfule">; // fmovfule r, r +def FMOVFO : F4_7<2, 0b110101, 0b1111, "fmovfo">; // fmovfo r, r +#endif + +// Section A.37: Multiply and Divide (64-bit) - p199 +def MULXr : F3_1<2, 0b001001, "mulx">; // mulx r, r, r +def SDIVXr : F3_1<2, 0b101101, "sdivx">; // mulx r, r, r +def UDIVXr : F3_1<2, 0b001101, "udivx">; // mulx r, r, r +def MULXi : F3_2<2, 0b001001, "mulx">; // mulx r, i, r +def SDIVXi : F3_2<2, 0b101101, "sdivx">; // mulx r, i, r +def UDIVXi : F3_2<2, 0b001101, "udivx">; // mulx r, i, r + +// Section A.38: Multiply (32-bit) - p200 +// Not used in the Sparc backend? +//set Inst{13} = 0 in { +// def UMULr : F3_1<2, 0b001010, "umul">; // umul r, r, r +// def SMULr : F3_1<2, 0b001011, "smul">; // smul r, r, r +// def UMULCCr : F3_1<2, 0b011010, "umulcc">; // mulcc r, r, r +// def SMULCCr : F3_1<2, 0b011011, "smulcc">; // smulcc r, r, r +//} +//set Inst{13} = 1 in { +// def UMULi : F3_1<2, 0b001010, "umul">; // umul r, i, r +// def SMULi : F3_1<2, 0b001011, "smul">; // smul r, i, r +// def UMULCCi : F3_1<2, 0b011010, "umulcc">; // umulcc r, i, r +// def SMULCCi : F3_1<2, 0b011011, "smulcc">; // smulcc r, i, r +//} + +// Section A.40: No operation - p204 +// NOP is really a pseudo-instruction (special case of SETHI) +set op2 = 0b100 in { + set rd = 0 in { + set imm = 0 in { + def NOP : F2_1<"nop">; // nop + } + } +} -// Section A.45: RETURN - p240 +// Section A.45: RETURN - p216 set isReturn = 1 in { def RETURNr : F3_3<2, 0b111001, "return">; // return def RETURNi : F3_4<2, 0b111001, "return">; // return } + +// Section A.46: SAVE and RESTORE - p217 +def SAVEr : F3_1<2, 0b111100, "save">; // save r, r, r +def SAVEi : F3_2<2, 0b111100, "save">; // save r, i, r +def RESTOREr : F3_1<2, 0b111101, "restore">; // restore r, r, r +def RESTOREi : F3_2<2, 0b111101, "restore">; // restore r, i, r + +// Section A.47: SAVED and RESTORED - p219 +// FIXME: add these instrs + +// Section A.48: SETHI - p220 +set op2 = 0b100 in { + def SETHI : F2_1<"sethi">; // sethi +} + +// Section A.49: Shift - p221 +// uses 5 least significant bits of rs2 +//set x = 0 in { +// def SLLr5 : F3_11<2, 0b100101, "sll">; // sll r, r, r +// def SRLr5 : F3_11<2, 0b100110, "srl">; // srl r, r, r +// def SRAr5 : F3_11<2, 0b100111, "sra">; // sra r, r, r +// def SLLXr5 : F3_11<2, 0b100101, "sllx">; // sllx r, r, r +// def SRLXr5 : F3_11<2, 0b100110, "srlx">; // srlx r, r, r +// def SRAXr5 : F3_11<2, 0b100111, "srax">; // srax r, r, r +//} +// uses 6 least significant bits of rs2 +set x = 1 in { + // def SLLr6 : F3_11<2, 0b100101, "sll">; // sll r, r, r + // def SRLr6 : F3_11<2, 0b100110, "srl">; // srl r, r, r + // def SRAr6 : F3_11<2, 0b100111, "sra">; // sra r, r, r + def SLLXr6 : F3_11<2, 0b100101, "sllx">; // sllx r, r, r + def SRLXr6 : F3_11<2, 0b100110, "srlx">; // srlx r, r, r + def SRAXr6 : F3_11<2, 0b100111, "srax">; // srax r, r, r +} + +//def SLLi5 : F3_12<2, 0b100101, "sll">; // sll r, shcnt32, r +//def SRLi5 : F3_12<2, 0b100110, "srl">; // srl r, shcnt32, r +//def SRAi5 : F3_12<2, 0b100111, "sra">; // sra r, shcnt32, r +//def SLLXi5 : F3_12<2, 0b100101, "sllx">; // sllx r, shcnt32, r +//def SRLXi5 : F3_12<2, 0b100110, "srlx">; // srlx r, shcnt32, r +//def SRAXi5 : F3_12<2, 0b100111, "srax">; // srax r, shcnt32, r + +//def SLLi6 : F3_13<2, 0b100101, "sll">; // sll r, shcnt64, r +//def SRLi6 : F3_13<2, 0b100110, "srl">; // srl r, shcnt64, r +//def SRAi6 : F3_13<2, 0b100111, "sra">; // sra r, shcnt64, r +def SLLXi6 : F3_13<2, 0b100101, "sllx">; // sllx r, shcnt64, r +def SRLXi6 : F3_13<2, 0b100110, "srlx">; // srlx r, shcnt64, r +def SRAXi6 : F3_13<2, 0b100111, "srax">; // srax r, shcnt64, r + +// Section A.52: Store Floating-point -p225 +def STFr : F3_1<3, 0b100100, "st">; // st r, [r+r] +def STFi : F3_2<3, 0b100100, "st">; // st r, [r+i] +def STDFr : F3_1<3, 0b100111, "std">; // std r, [r+r] +def STDFi : F3_2<3, 0b100111, "std">; // std r, [r+i] +// Not currently used in the Sparc backend +//def STQFr : F3_1<3, 0b100110, "stq">; // stq r, [r+r] +//def STQFi : F3_2<3, 0b100110, "stq">; // stq r, [r+i] +set isDeprecated = 1 in { + def STFSRr : F3_1<3, 0b100101, "st">; // st r, [r+r] + def STFSRi : F3_2<3, 0b100101, "st">; // st r, [r+i] +} +def STXFSRr : F3_1<3, 0b100101, "stq">; // stx r, [r+r] +def STXFSRi : F3_2<3, 0b100101, "stq">; // stx r, [r+i] + +// Section A.54: Store Integer - p229 +def STBr : F3_1<3, 0b000101, "stb">; // stb r, [r+r] +def STBi : F3_2<3, 0b000101, "stb">; // stb r, [r+i] +def STHr : F3_1<3, 0b000110, "stb">; // stb r, [r+r] +def STHi : F3_2<3, 0b000110, "stb">; // stb r, [r+i] +def STWr : F3_1<3, 0b000100, "stb">; // stb r, [r+r] +def STWi : F3_2<3, 0b000100, "stb">; // stb r, [r+i] +def STXr : F3_1<3, 0b001110, "stb">; // stb r, [r+r] +def STXi : F3_2<3, 0b001110, "stb">; // stb r, [r+i] + +// Floating point store... + +// Section A.56: Subtract - p233 +def SUBr : F3_1<2, 0b000100, "sub">; // sub r, r, r +def SUBi : F3_1<2, 0b000100, "sub">; // sub r, i, r +def SUBccr : F3_1<2, 0b010100, "subcc">; // subcc r, r, r +def SUBcci : F3_1<2, 0b010100, "subcc">; // subcc r, i, r +def SUBCr : F3_1<2, 0b001100, "subc">; // subc r, r, r +def SUBCi : F3_1<2, 0b001100, "subc">; // subc r, i, r +def SUBCccr : F3_1<2, 0b011100, "subccc">; // subccc r, r, r +def SUBCcci : F3_1<2, 0b011100, "subccc">; // subccc r, i, r From brukman at cs.uiuc.edu Tue May 27 15:06:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 15:06:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/AddRegNumToValues.cpp Message-ID: <200305272005.PAA22613@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: AddRegNumToValues.cpp added (r1.1) --- Log message: This file provides the `glue' to turn the Value*-based MachineInstrs that the Sparc instruction selector produces to the unsigned-register-based MachineInstrs that the target-independent register allocators in the JIT prefer. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/AddRegNumToValues.cpp diff -c /dev/null llvm/lib/Target/Sparc/AddRegNumToValues.cpp:1.1 *** /dev/null Tue May 27 15:05:37 2003 --- llvm/lib/Target/Sparc/AddRegNumToValues.cpp Tue May 27 15:05:27 2003 *************** *** 0 **** --- 1,64 ---- + //===-- AddRegNumToValues.cpp - Adds unsigned register indices for Value* -===// + // + // This is a placeholder pass, just so that it doesn't intrude too much into + // the MachineOperand class: + // * The Sparc back-end uses Value* in instructions for dataflow + // * The RegisterAllocator in the JIT expects unsigned register numbers instead + // of Value* + // + // This pass is an attempt to bridge the gap between the two, without putting an + // explicit conversion in the shortest path (i.e., the original LLC codegen). + // + //===----------------------------------------------------------------------===// + + #include "llvm/CodeGen/Passes.h" + #include "llvm/CodeGen/MachineFunctionPass.h" + #include "llvm/CodeGen/MachineInstr.h" + #include "SparcInternals.h" + + namespace { + struct AddRegNumToValues : MachineFunctionPass { + + AddRegNumToValues() {} + bool runOnMachineFunction(MachineFunction &F); + }; + + static RegisterOpt + X("add-regnum", "Add reg numbers to Values", createAddRegNumToValuesPass); + } + + bool AddRegNumToValues::runOnMachineFunction(MachineFunction &F) { + unsigned regNum = MRegisterInfo::FirstVirtualRegister; + std::map Value2RegMap; + + for (MachineFunction::iterator i = F.begin(), e = F.end(); i != e; ++i) { + MachineBasicBlock &BB = *i; + for (MachineBasicBlock::iterator Bi = BB.begin(), Be = BB.end(); + Bi != Be; ++Bi) + { + MachineInstr *MI = *Bi; + + // Loop over uses, move from memory into registers + for (int i = MI->getNumOperands()-1; i >= 0; --i) { + MachineOperand &op = MI->getOperand(i); + + Value *val = op.getVRegValueOrNull(); + if (Instruction *inst = dyn_cast(val)) { + if (Value2RegMap[val] != 0) { + MI->SetRegForOperand(i, Value2RegMap[val]); + } else { + MI->SetRegForOperand(i, regNum); + Value2RegMap[val] = regNum++; + } + } + } + } + } + + Value2RegMap.clear(); + return false; + } + + Pass *createAddRegNumToValuesPass() { + return new AddRegNumToValues(); + } From brukman at cs.uiuc.edu Tue May 27 15:09:02 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 15:09:02 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp .cvsignore Makefile Message-ID: <200305272008.PAA22644@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcV9CodeEmitter.cpp added (r1.1) .cvsignore added (r1.1) Makefile updated: 1.13 -> 1.14 --- Log message: SparcV9CodeEmitter.cpp is a part of the Sparc code emitter. The main function that assembles instructions is generated via TableGen (and hence must be built before building this directory, but that's already the case in the top-level Makefile). Also added is .cvsignore to ignore the generated file `SparcV9CodeEmitter.inc', which is included by SparcV9CodeEmitter.cpp . --- Diffs of the changes: Index: llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp diff -c /dev/null llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp:1.1 *** /dev/null Tue May 27 15:08:08 2003 --- llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp Tue May 27 15:07:58 2003 *************** *** 0 **** --- 1,90 ---- + #include "llvm/PassManager.h" + #include "llvm/CodeGen/MachineCodeEmitter.h" + #include "llvm/CodeGen/MachineFunctionPass.h" + #include "llvm/CodeGen/MachineInstr.h" + #include "SparcInternals.h" + + namespace { + class SparcV9CodeEmitter : public MachineFunctionPass { + MachineCodeEmitter &MCE; + + public: + SparcV9CodeEmitter(MachineCodeEmitter &M) : MCE(M) {} + + bool runOnMachineFunction(MachineFunction &F); + + private: + int64_t getMachineOpValue(MachineOperand &MO); + unsigned getValueBit(int64_t Val, unsigned bit); + + void emitConstant(unsigned Val, unsigned Size); + + void emitBasicBlock(MachineBasicBlock &MBB); + void emitInstruction(MachineInstr &MI); + + /// Function generated by the CodeEmitterGenerator using TableGen + /// + unsigned getBinaryCodeForInstr(MachineInstr &MI); + }; + } + + bool UltraSparc::addPassesToEmitMachineCode(PassManager &PM, + MachineCodeEmitter &MCE) { + //PM.add(new SparcV9CodeEmitter(MCE)); + //MachineCodeEmitter *M = MachineCodeEmitter::createDebugMachineCodeEmitter(); + MachineCodeEmitter *M = + MachineCodeEmitter::createFilePrinterMachineCodeEmitter(); + PM.add(new SparcV9CodeEmitter(*M)); + return false; + } + + void SparcV9CodeEmitter::emitConstant(unsigned Val, unsigned Size) { + // Output the constant in big endian byte order... + unsigned byteVal; + for (int i = Size-1; i >= 0; --i) { + byteVal = Val >> 8*i; + MCE.emitByte(byteVal & 255); + } + } + + int64_t SparcV9CodeEmitter::getMachineOpValue(MachineOperand &MO) { + if (MO.isPhysicalRegister()) { + return MO.getReg(); + } else if (MO.isImmediate()) { + return MO.getImmedValue(); + } else if (MO.isPCRelativeDisp()) { + // FIXME!!! + //return MO.getPCRelativeDisp(); + return 0; + } else { + assert(0 && "Unknown type of MachineOperand"); + return 0; + } + } + + unsigned SparcV9CodeEmitter::getValueBit(int64_t Val, unsigned bit) { + Val >>= bit; + return (Val & 1); + } + + + bool SparcV9CodeEmitter::runOnMachineFunction(MachineFunction &MF) { + MCE.startFunction(MF); + MCE.emitConstantPool(MF.getConstantPool()); + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) + emitBasicBlock(*I); + MCE.finishFunction(MF); + return false; + } + + void SparcV9CodeEmitter::emitBasicBlock(MachineBasicBlock &MBB) { + MCE.startBasicBlock(MBB); + for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I) + emitInstruction(**I); + } + + void SparcV9CodeEmitter::emitInstruction(MachineInstr &MI) { + emitConstant(getBinaryCodeForInstr(MI), 4); + } + + #include "SparcV9CodeEmitter.inc" Index: llvm/lib/Target/Sparc/.cvsignore diff -c /dev/null llvm/lib/Target/Sparc/.cvsignore:1.1 *** /dev/null Tue May 27 15:08:08 2003 --- llvm/lib/Target/Sparc/.cvsignore Tue May 27 15:07:58 2003 *************** *** 0 **** --- 1 ---- + SparcV9CodeEmitter.inc Index: llvm/lib/Target/Sparc/Makefile diff -u llvm/lib/Target/Sparc/Makefile:1.13 llvm/lib/Target/Sparc/Makefile:1.14 --- llvm/lib/Target/Sparc/Makefile:1.13 Mon Sep 23 08:12:28 2002 +++ llvm/lib/Target/Sparc/Makefile Tue May 27 15:07:58 2003 @@ -32,3 +32,6 @@ $(BUILD_ROOT)/Depend/Sparc.burm.d: $(BUILD_ROOT)/Depend/.dir touch $@ +SparcV9CodeEmitter.inc: SparcV9.td + @echo "TableGen-erating $@" + cpp -P SparcV9.td | tblgen -gen-emitter > SparcV9CodeEmitter.inc From lattner at cs.uiuc.edu Tue May 27 16:24:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 27 16:24:01 2003 Subject: [llvm-commits] CVS: llvm/tools/llc/Makefile llc.cpp Message-ID: <200305272123.QAA00923@apoc.cs.uiuc.edu> Changes in directory llvm/tools/llc: Makefile updated: 1.34 -> 1.35 llc.cpp updated: 1.71 -> 1.72 --- Log message: Remove ugly hack (that I put in originally) for building in trace stuff automatically in LLC --- Diffs of the changes: Index: llvm/tools/llc/Makefile diff -u llvm/tools/llc/Makefile:1.34 llvm/tools/llc/Makefile:1.35 --- llvm/tools/llc/Makefile:1.34 Sun Jan 19 15:55:43 2003 +++ llvm/tools/llc/Makefile Tue May 27 16:23:02 2003 @@ -9,11 +9,9 @@ preopts \ postopts.a \ target.a \ - instrument \ livevar \ - ipo.a \ - scalaropts.a \ transforms.a \ + scalaropts.a \ analysis.a \ transformutils.a \ bcreader \ Index: llvm/tools/llc/llc.cpp diff -u llvm/tools/llc/llc.cpp:1.71 llvm/tools/llc/llc.cpp:1.72 --- llvm/tools/llc/llc.cpp:1.71 Sun Apr 27 22:28:56 2003 +++ llvm/tools/llc/llc.cpp Tue May 27 16:23:02 2003 @@ -7,12 +7,8 @@ #include "llvm/Bytecode/Reader.h" #include "llvm/Target/TargetMachineImpls.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/Utils/Linker.h" #include "llvm/Assembly/PrintModulePass.h" -#include "llvm/Bytecode/WriteBytecodePass.h" -#include "llvm/Transforms/IPO.h" #include "llvm/Module.h" #include "llvm/PassManager.h" #include "llvm/Pass.h" @@ -57,16 +53,6 @@ DumpAsm("d", cl::desc("Print bytecode before native code generation"), cl::Hidden); -static cl::opt -TraceLibPath("tracelibpath", cl::desc("Path to libinstr for trace code"), - cl::value_desc("directory"), cl::Hidden); - - -// flags set from -tracem and -trace options to control tracing -static bool TraceFunctions = false; -static bool TraceBasicBlocks = false; - - // GetFileNameRoot - Helper function to get the basename of a filename... static inline std::string GetFileNameRoot(const std::string &InputFilename) @@ -82,81 +68,6 @@ return outputFilename; } -static bool -insertTraceCodeFor(Module &M) -{ - PassManager Passes; - - // Insert trace code in all functions in the module - if (TraceBasicBlocks) - Passes.add(createTraceValuesPassForBasicBlocks()); - else if (TraceFunctions) - Passes.add(createTraceValuesPassForFunction()); - else - return false; - - // Eliminate duplication in constant pool - Passes.add(createConstantMergePass()); - - // Run passes to insert and clean up trace code... - Passes.run(M); - - std::string ErrorMessage; - - // Load the module that contains the runtime helper routines neccesary for - // pointer hashing and stuff... link this module into the program if possible - // - Module *TraceModule = ParseBytecodeFile(TraceLibPath+"libinstr.bc"); - - // Check if the TraceLibPath contains a valid module. If not, try to load - // the module from the current LLVM-GCC install directory. This is kindof - // a hack, but allows people to not HAVE to have built the library. - // - if (TraceModule == 0) - TraceModule = ParseBytecodeFile("/home/vadve/lattner/cvs/gcc_install/lib/" - "gcc-lib/llvm/3.1/libinstr.bc"); - - // If we still didn't get it, cancel trying to link it in... - if (TraceModule == 0) - std::cerr <<"WARNING: couldn't load trace routines to link into program!\n"; - else - { - // Link in the trace routines... if this fails, don't panic, because the - // compile should still succeed, but the native linker will probably fail. - // - std::auto_ptr TraceRoutines(TraceModule); - if (LinkModules(&M, TraceRoutines.get(), &ErrorMessage)) - std::cerr << "WARNING: Error linking in trace routines: " - << ErrorMessage << "\n"; - } - - // Write out the module with tracing code just before code generation - assert (InputFilename != "-" - && "Cannot write out traced bytecode when reading input from stdin"); - std::string TraceFilename = GetFileNameRoot(InputFilename) + ".trace.bc"; - - std::ofstream Out(TraceFilename.c_str()); - if (!Out.good()) - std::cerr << "Error opening '" << TraceFilename - << "'!: Skipping output of trace code as bytecode\n"; - else - { - std::cerr << "Emitting trace code to '" << TraceFilename - << "' for comparison...\n"; - WriteBytecodeToFile(&M, Out); - } - - return true; -} - -// Making tracing a module pass so the entire module with tracing -// can be written out before continuing. -struct InsertTracingCodePass: public Pass { - virtual bool run(Module &M) { - return insertTraceCodeFor(M); - } -}; - //===---------------------------------------------------------------------===// // Function main() @@ -194,36 +105,27 @@ // Create a new optimization pass for each one specified on the command line // Deal specially with tracing passes, which must be run differently than opt. // - for (unsigned i = 0; i < OptimizationList.size(); ++i) - { - const PassInfo *Opt = OptimizationList[i]; - - if (std::string(Opt->getPassArgument()) == "trace") - TraceFunctions = !(TraceBasicBlocks = true); - else if (std::string(Opt->getPassArgument()) == "tracem") - TraceFunctions = !(TraceBasicBlocks = false); - else - { // handle other passes as normal optimization passes - if (Opt->getNormalCtor()) - Passes.add(Opt->getNormalCtor()()); - else if (Opt->getTargetCtor()) - Passes.add(Opt->getTargetCtor()(Target)); - else - std::cerr << argv[0] << ": cannot create pass: " - << Opt->getPassName() << "\n"; - } - } - - // Run tracing passes after other optimization passes and before llc passes. - if (TraceFunctions || TraceBasicBlocks) - Passes.add(new InsertTracingCodePass); + for (unsigned i = 0; i < OptimizationList.size(); ++i) { + const PassInfo *Opt = OptimizationList[i]; + + // handle other passes as normal optimization passes + if (Opt->getNormalCtor()) + Passes.add(Opt->getNormalCtor()()); + else if (Opt->getTargetCtor()) + Passes.add(Opt->getTargetCtor()(Target)); + else + std::cerr << argv[0] << ": cannot create pass: " + << Opt->getPassName() << "\n"; + } // Decompose multi-dimensional refs into a sequence of 1D refs + // FIXME: This is sparc specific! Passes.add(createDecomposeMultiDimRefsPass()); // Replace malloc and free instructions with library calls. // Do this after tracing until lli implements these lib calls. // For now, it will emulate malloc and free internally. + // FIXME: This is sparc specific! Passes.add(createLowerAllocationsPass()); // If LLVM dumping after transformations is requested, add it to the pipeline From lattner at cs.uiuc.edu Tue May 27 16:35:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 27 16:35:00 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/SingleSource/mandel.c Message-ID: <200305272134.QAA00996@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/SingleSource: mandel.c (r1.1) removed --- Log message: Remove test until it can be fixed on sparc --- Diffs of the changes: From brukman at cs.uiuc.edu Tue May 27 16:41:00 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 16:41:00 2003 Subject: [llvm-commits] CVS: llvm/tools/lli/JIT/SparcEmitter.cpp Emitter.cpp JIT.cpp VM.h Message-ID: <200305272140.QAA24901@zion.cs.uiuc.edu> Changes in directory llvm/tools/lli/JIT: SparcEmitter.cpp added (r1.1) Emitter.cpp updated: 1.6 -> 1.7 JIT.cpp updated: 1.3 -> 1.4 VM.h updated: 1.5 -> 1.6 --- Log message: Allow for specification of which JIT to run on the commandline. `lli -march=x86' or `lli -march=sparc' will forcefully select the JIT even on a different platform. Running lli without the -march option will select the JIT for the platform that it's currently running on. Pro: can test Sparc JIT (debug printing mode) on X86 -- faster to compile/link LLVM source base to test changes. Con: Linking lli on x86 now pulls in all the Sparc libs -> longer link time (but X86 can bear it, right?) In the future, perhaps this should be a ./configure option to enable/disable target JITting... --- Diffs of the changes: Index: llvm/tools/lli/JIT/SparcEmitter.cpp diff -c /dev/null llvm/tools/lli/JIT/SparcEmitter.cpp:1.1 *** /dev/null Tue May 27 16:40:49 2003 --- llvm/tools/lli/JIT/SparcEmitter.cpp Tue May 27 16:40:39 2003 *************** *** 0 **** --- 1,218 ---- + //===-- SparcEmitter.cpp - Write machine code to executable memory --------===// + // + // This file defines a MachineCodeEmitter object that is used by Jello to write + // machine code to memory and remember where relocatable values lie. + // + //===----------------------------------------------------------------------===// + + #include "VM.h" + #include "llvm/CodeGen/MachineCodeEmitter.h" + #include "llvm/CodeGen/MachineFunction.h" + #include "llvm/CodeGen/MachineConstantPool.h" + #include "llvm/CodeGen/MachineInstr.h" + #include "llvm/Target/TargetData.h" + #include "llvm/Function.h" + #include "Support/Statistic.h" + // FIXME + #include "../../../lib/Target/Sparc/SparcV9CodeEmitter.h" + + namespace { + Statistic<> NumBytes("jello", "Number of bytes of machine code compiled"); + + class SparcEmitter : public MachineCodeEmitter { + VM &TheVM; + + unsigned char *CurBlock, *CurByte; + + // When outputting a function stub in the context of some other function, we + // save CurBlock and CurByte here. + unsigned char *SavedCurBlock, *SavedCurByte; + + std::vector > > BBRefs; + std::map BBLocations; + std::vector ConstantPoolAddresses; + public: + SparcEmitter(VM &vm) : TheVM(vm) {} + + virtual void startFunction(MachineFunction &F); + virtual void finishFunction(MachineFunction &F); + virtual void emitConstantPool(MachineConstantPool *MCP); + virtual void startBasicBlock(MachineBasicBlock &BB); + virtual void startFunctionStub(const Function &F, unsigned StubSize); + virtual void* finishFunctionStub(const Function &F); + virtual void emitByte(unsigned char B); + virtual void emitPCRelativeDisp(Value *V); + virtual void emitGlobalAddress(GlobalValue *V, bool isPCRelative); + virtual void emitGlobalAddress(const std::string &Name, bool isPCRelative); + virtual void emitFunctionConstantValueAddress(unsigned ConstantNum, + int Offset); + + virtual void saveBBreference(BasicBlock *BB, MachineInstr &MI); + + private: + void emitAddress(void *Addr, bool isPCRelative); + }; + } + + MachineCodeEmitter *VM::createSparcEmitter(VM &V) { + return new SparcEmitter(V); + } + + + #define _POSIX_MAPPED_FILES + #include + #include + + // FIXME: This should be rewritten to support a real memory manager for + // executable memory pages! + static void *getMemory(unsigned NumPages) { + return mmap(0, 4096*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); + } + + + void SparcEmitter::startFunction(MachineFunction &F) { + CurBlock = (unsigned char *)getMemory(8); + CurByte = CurBlock; // Start writing at the beginning of the fn. + TheVM.addGlobalMapping(F.getFunction(), CurBlock); + } + + void SparcEmitter::finishFunction(MachineFunction &F) { + ConstantPoolAddresses.clear(); + for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) { + // Re-write branches to BasicBlocks for the entire function + unsigned Location = BBLocations[BBRefs[i].first]; + unsigned *Ref = BBRefs[i].second.first; + MachineInstr *MI = BBRefs[i].second.second; + for (unsigned i=0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &op = MI->getOperand(i); + if (op.isImmediate()) { + MI->SetMachineOperandConst(i, op.getType(), Location); + break; + } + } + unsigned fixedInstr = SparcV9CodeEmitter::getBinaryCodeForInstr(*MI); + *Ref = fixedInstr; + } + BBRefs.clear(); + BBLocations.clear(); + + NumBytes += CurByte-CurBlock; + + DEBUG(std::cerr << "Finished CodeGen of [0x" << std::hex + << (unsigned)(intptr_t)CurBlock + << std::dec << "] Function: " << F.getFunction()->getName() + << ": " << CurByte-CurBlock << " bytes of text\n"); + } + + void SparcEmitter::emitConstantPool(MachineConstantPool *MCP) { + const std::vector &Constants = MCP->getConstants(); + for (unsigned i = 0, e = Constants.size(); i != e; ++i) { + // For now we just allocate some memory on the heap, this can be + // dramatically improved. + const Type *Ty = ((Value*)Constants[i])->getType(); + void *Addr = malloc(TheVM.getTargetData().getTypeSize(Ty)); + TheVM.InitializeMemory(Constants[i], Addr); + ConstantPoolAddresses.push_back(Addr); + } + } + + + void SparcEmitter::startBasicBlock(MachineBasicBlock &BB) { + BBLocations[BB.getBasicBlock()] = (unsigned)(intptr_t)CurByte; + } + + + void SparcEmitter::startFunctionStub(const Function &F, unsigned StubSize) { + SavedCurBlock = CurBlock; SavedCurByte = CurByte; + // FIXME: this is a huge waste of memory. + CurBlock = (unsigned char *)getMemory((StubSize+4095)/4096); + CurByte = CurBlock; // Start writing at the beginning of the fn. + } + + void *SparcEmitter::finishFunctionStub(const Function &F) { + NumBytes += CurByte-CurBlock; + DEBUG(std::cerr << "Finished CodeGen of [0x" << std::hex + << (unsigned)(intptr_t)CurBlock + << std::dec << "] Function stub for: " << F.getName() + << ": " << CurByte-CurBlock << " bytes of text\n"); + std::swap(CurBlock, SavedCurBlock); + CurByte = SavedCurByte; + return SavedCurBlock; + } + + void SparcEmitter::emitByte(unsigned char B) { + *CurByte++ = B; // Write the byte to memory + } + + // BasicBlock -> pair + // when the BB is emitted, machineinstr is modified with then-currbyte, + // processed with MCE, and written out at memloc. + void SparcEmitter::saveBBreference(BasicBlock *BB, MachineInstr &MI) { + BBRefs.push_back(std::make_pair(BB, std::make_pair((unsigned*)CurByte, &MI))); + } + + + // emitPCRelativeDisp - For functions, just output a displacement that will + // cause a reference to the zero page, which will cause a seg-fault, causing + // things to get resolved on demand. Keep track of these markers. + // + // For basic block references, keep track of where the references are so they + // may be patched up when the basic block is defined. + // + // BasicBlock -> pair + // when the BB is emitted, machineinstr is modified with then-currbyte, + // processed with MCE, and written out at memloc. + + void SparcEmitter::emitPCRelativeDisp(Value *V) { + #if 0 + BasicBlock *BB = cast(V); // Keep track of reference... + BBRefs.push_back(std::make_pair(BB, (unsigned*)CurByte)); + CurByte += 4; + #endif + } + + // emitAddress - Emit an address in either direct or PCRelative form... + // + void SparcEmitter::emitAddress(void *Addr, bool isPCRelative) { + #if 0 + if (isPCRelative) { + *(intptr_t*)CurByte = (intptr_t)Addr - (intptr_t)CurByte-4; + } else { + *(void**)CurByte = Addr; + } + CurByte += 4; + #endif + } + + void SparcEmitter::emitGlobalAddress(GlobalValue *V, bool isPCRelative) { + if (isPCRelative) { // must be a call, this is a major hack! + // Try looking up the function to see if it is already compiled! + if (void *Addr = TheVM.getPointerToGlobalIfAvailable(V)) { + emitAddress(Addr, isPCRelative); + } else { // Function has not yet been code generated! + TheVM.addFunctionRef(CurByte, cast(V)); + + // Delayed resolution... + emitAddress((void*)VM::CompilationCallback, isPCRelative); + } + } else { + emitAddress(TheVM.getPointerToGlobal(V), isPCRelative); + } + } + + void SparcEmitter::emitGlobalAddress(const std::string &Name, bool isPCRelative) + { + #if 0 + emitAddress(TheVM.getPointerToNamedFunction(Name), isPCRelative); + #endif + } + + void SparcEmitter::emitFunctionConstantValueAddress(unsigned ConstantNum, + int Offset) { + assert(ConstantNum < ConstantPoolAddresses.size() && + "Invalid ConstantPoolIndex!"); + *(void**)CurByte = (char*)ConstantPoolAddresses[ConstantNum]+Offset; + CurByte += 4; + } Index: llvm/tools/lli/JIT/Emitter.cpp diff -u llvm/tools/lli/JIT/Emitter.cpp:1.6 llvm/tools/lli/JIT/Emitter.cpp:1.7 --- llvm/tools/lli/JIT/Emitter.cpp:1.6 Thu May 8 22:30:07 2003 +++ llvm/tools/lli/JIT/Emitter.cpp Tue May 27 16:40:39 2003 @@ -48,7 +48,7 @@ }; } -MachineCodeEmitter *VM::createEmitter(VM &V) { +MachineCodeEmitter *VM::createX86Emitter(VM &V) { return new Emitter(V); } Index: llvm/tools/lli/JIT/JIT.cpp diff -u llvm/tools/lli/JIT/JIT.cpp:1.3 llvm/tools/lli/JIT/JIT.cpp:1.4 --- llvm/tools/lli/JIT/JIT.cpp:1.3 Wed May 14 08:53:40 2003 +++ llvm/tools/lli/JIT/JIT.cpp Tue May 27 16:40:39 2003 @@ -9,28 +9,65 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetMachineImpls.h" #include "llvm/Module.h" +#include "Support/CommandLine.h" + +namespace { + cl::opt + Arch("march", cl::desc("Architecture: `x86' or `sparc'"), cl::Prefix, + cl::value_desc("machine architecture")); + + static std::string DefaultArch = +#if defined(i386) || defined(__i386__) || defined(__x86__) + "x86"; +#elif defined(sparc) || defined(__sparc__) || defined(__sparcv9) + "sparc"; +#else + ""; +#endif + +} /// createJIT - Create an return a new JIT compiler if there is one available /// for the current target. Otherwise it returns null. /// ExecutionEngine *ExecutionEngine::createJIT(Module *M, unsigned Config) { - // FIXME: This should be controlled by which subdirectory gets linked in! -#if !defined(i386) && !defined(__i386__) && !defined(__x86__) - return 0; -#endif - // Allocate a target... in the future this will be controllable on the - // command line. - TargetMachine *Target = allocateX86TargetMachine(Config); - assert(Target && "Could not allocate X86 target machine!"); + + TargetMachine* (*TargetMachineAllocator)(unsigned) = 0; + if (Arch == "") + Arch = DefaultArch; - // Create the virtual machine object... - return new VM(M, Target); + // Allow a command-line switch to override what *should* be the default target + // machine for this platform. This allows for debugging a Sparc JIT on X86 -- + // our X86 machines are much faster at recompiling LLVM and linking lli. + if (Arch == "x86") { + TargetMachineAllocator = allocateX86TargetMachine; + } else if (Arch == "sparc") { + TargetMachineAllocator = allocateSparcTargetMachine; + } + + if (TargetMachineAllocator) { + // Allocate a target... + TargetMachine *Target = (*TargetMachineAllocator)(Config); + assert(Target && "Could not allocate target machine!"); + + // Create the virtual machine object... + return new VM(M, Target); + } else { + return 0; + } } VM::VM(Module *M, TargetMachine *tm) : ExecutionEngine(M), TM(*tm) { setTargetData(TM.getTargetData()); - MCE = createEmitter(*this); // Initialize MCE + + // Initialize MCE + if (Arch == "x86") { + MCE = createX86Emitter(*this); + } else if (Arch == "sparc") { + MCE = createSparcEmitter(*this); + } + setupPassManager(); registerCallback(); emitGlobals(); Index: llvm/tools/lli/JIT/VM.h diff -u llvm/tools/lli/JIT/VM.h:1.5 llvm/tools/lli/JIT/VM.h:1.6 --- llvm/tools/lli/JIT/VM.h:1.5 Wed May 14 08:53:40 2003 +++ llvm/tools/lli/JIT/VM.h Tue May 27 16:40:39 2003 @@ -62,7 +62,8 @@ static void runAtExitHandlers(); private: - static MachineCodeEmitter *createEmitter(VM &V); + static MachineCodeEmitter *createX86Emitter(VM &V); + static MachineCodeEmitter *createSparcEmitter(VM &V); void setupPassManager(); void *getPointerToFunction(const Function *F); From brukman at cs.uiuc.edu Tue May 27 16:43:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 16:43:01 2003 Subject: [llvm-commits] CVS: llvm/tools/lli/Makefile Message-ID: <200305272142.QAA24916@zion.cs.uiuc.edu> Changes in directory llvm/tools/lli: Makefile updated: 1.23 -> 1.24 --- Log message: Link in Sparc libs for the JIT, even on X86 to be able to support debugging of Sparc JIT (printing out instrs) on X86. Con: this increases linking time. --- Diffs of the changes: Index: llvm/tools/lli/Makefile diff -u llvm/tools/lli/Makefile:1.23 llvm/tools/lli/Makefile:1.24 --- llvm/tools/lli/Makefile:1.23 Wed Apr 23 11:43:02 2003 +++ llvm/tools/lli/Makefile Tue May 27 16:42:05 2003 @@ -2,9 +2,25 @@ TOOLNAME = lli PARALLEL_DIRS = Interpreter JIT -JITLIBS = lli-jit codegen x86 -USEDLIBS = lli-interpreter $(JITLIBS) bcreader vmcore scalaropts.a \ - analysis.a support.a target.a +# FIXME: This enables testing the Sparc JIT on x86. +# Perhaps in the future this should be a ./configure option. + +# Generic JIT libraries +JITLIBS = lli-jit codegen +ARCHLIBS = + +# What the X86 JIT requires +JITLIBS += x86 +ARCHLIBS += + +# What the Sparc JIT requires +JITLIBS += sparc +ARCHLIBS = sched livevar instrument.a profpaths transformutils.a \ + bcwriter transforms.a ipo.a ipa.a datastructure.a regalloc \ + mapping select postopts.a preopts + +USEDLIBS = lli-interpreter $(JITLIBS) bcreader vmcore scalaropts \ + analysis.a support.a target.a $(ARCHLIBS) # Have gcc tell the linker to export symbols from the program so that # dynamically loaded modules can be linked against them. From lattner at cs.uiuc.edu Tue May 27 16:44:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 27 16:44:01 2003 Subject: [llvm-commits] CVS: llvm/test/Libraries/libinstr/Makefile tracelib.c Message-ID: <200305272143.QAA01062@apoc.cs.uiuc.edu> Changes in directory llvm/test/Libraries/libinstr: Makefile updated: 1.2 -> 1.3 tracelib.c updated: 1.2 -> 1.3 --- Log message: Update to match the reality that is now. --- Diffs of the changes: Index: llvm/test/Libraries/libinstr/Makefile diff -u llvm/test/Libraries/libinstr/Makefile:1.2 llvm/test/Libraries/libinstr/Makefile:1.3 --- llvm/test/Libraries/libinstr/Makefile:1.2 Mon May 20 16:16:19 2002 +++ llvm/test/Libraries/libinstr/Makefile Tue May 27 16:43:14 2003 @@ -2,10 +2,5 @@ LIBNAME = instr -# We use assert and memset here... and we are linked into the program AFTER final -# link. Because of this, we have to play funny games here. :( -LDFLAGS = /home/vadve/lattner/cvs/gcc_install/lib/gcc-lib/llvm/3.1/libgcc.bc \ - /home/vadve/lattner/cvs/gcc_install/lib/gcc-lib/llvm/3.1/libc.bc - include ../Makefile.libs Index: llvm/test/Libraries/libinstr/tracelib.c diff -u llvm/test/Libraries/libinstr/tracelib.c:1.2 llvm/test/Libraries/libinstr/tracelib.c:1.3 --- llvm/test/Libraries/libinstr/tracelib.c:1.2 Mon May 20 16:15:30 2002 +++ llvm/test/Libraries/libinstr/tracelib.c Tue May 27 16:43:14 2003 @@ -10,7 +10,7 @@ #include #include #include - +#include /*===---------------------------------------------------------------------===== * HASH FUNCTIONS From brukman at cs.uiuc.edu Tue May 27 16:46:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 16:46:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcV9CodeEmitter.h SparcV9CodeEmitter.cpp Message-ID: <200305272145.QAA25124@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcV9CodeEmitter.h added (r1.1) SparcV9CodeEmitter.cpp updated: 1.1 -> 1.2 --- Log message: Broke out class definition from SparcV9CodeEmitter, and added ability to take a MachineCodeEmitter to make a pass-through debugger -- output to memory and to std::cerr. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/SparcV9CodeEmitter.h diff -c /dev/null llvm/lib/Target/Sparc/SparcV9CodeEmitter.h:1.1 *** /dev/null Tue May 27 16:45:15 2003 --- llvm/lib/Target/Sparc/SparcV9CodeEmitter.h Tue May 27 16:45:05 2003 *************** *** 0 **** --- 1,33 ---- + + + #ifndef SPARCV9CODEEMITTER_H + #define SPARCV9CODEEMITTER_H + + #include "llvm/CodeGen/MachineCodeEmitter.h" + #include "llvm/CodeGen/MachineFunctionPass.h" + #include "llvm/CodeGen/MachineInstr.h" + + class SparcV9CodeEmitter : public MachineFunctionPass { + MachineCodeEmitter &MCE; + + public: + SparcV9CodeEmitter(MachineCodeEmitter &M) : MCE(M) {} + + bool runOnMachineFunction(MachineFunction &F); + + /// Function generated by the CodeEmitterGenerator using TableGen + /// + static unsigned getBinaryCodeForInstr(MachineInstr &MI); + + private: + static int64_t getMachineOpValue(MachineOperand &MO); + static unsigned getValueBit(int64_t Val, unsigned bit); + + void emitConstant(unsigned Val, unsigned Size); + + void emitBasicBlock(MachineBasicBlock &MBB); + void emitInstruction(MachineInstr &MI); + + }; + + #endif Index: llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp diff -u llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp:1.1 llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp:1.2 --- llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp:1.1 Tue May 27 15:07:58 2003 +++ llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp Tue May 27 16:45:05 2003 @@ -3,37 +3,14 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" #include "SparcInternals.h" - -namespace { - class SparcV9CodeEmitter : public MachineFunctionPass { - MachineCodeEmitter &MCE; - - public: - SparcV9CodeEmitter(MachineCodeEmitter &M) : MCE(M) {} - - bool runOnMachineFunction(MachineFunction &F); - - private: - int64_t getMachineOpValue(MachineOperand &MO); - unsigned getValueBit(int64_t Val, unsigned bit); - - void emitConstant(unsigned Val, unsigned Size); - - void emitBasicBlock(MachineBasicBlock &MBB); - void emitInstruction(MachineInstr &MI); - - /// Function generated by the CodeEmitterGenerator using TableGen - /// - unsigned getBinaryCodeForInstr(MachineInstr &MI); - }; -} +#include "SparcV9CodeEmitter.h" bool UltraSparc::addPassesToEmitMachineCode(PassManager &PM, MachineCodeEmitter &MCE) { //PM.add(new SparcV9CodeEmitter(MCE)); //MachineCodeEmitter *M = MachineCodeEmitter::createDebugMachineCodeEmitter(); MachineCodeEmitter *M = - MachineCodeEmitter::createFilePrinterMachineCodeEmitter(); + MachineCodeEmitter::createFilePrinterMachineCodeEmitter(MCE); PM.add(new SparcV9CodeEmitter(*M)); return false; } From brukman at cs.uiuc.edu Tue May 27 16:47:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 16:47:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Target/TargetMachineImpls.h Message-ID: <200305272146.QAA25140@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Target: TargetMachineImpls.h updated: 1.3 -> 1.4 --- Log message: Allow allocation of a Sparc TargetMachine. --- Diffs of the changes: Index: llvm/include/llvm/Target/TargetMachineImpls.h diff -u llvm/include/llvm/Target/TargetMachineImpls.h:1.3 llvm/include/llvm/Target/TargetMachineImpls.h:1.4 --- llvm/include/llvm/Target/TargetMachineImpls.h:1.3 Mon Dec 23 18:02:17 2002 +++ llvm/include/llvm/Target/TargetMachineImpls.h Tue May 27 16:46:07 2003 @@ -25,7 +25,8 @@ // allocateSparcTargetMachine - Allocate and return a subclass of TargetMachine // that implements the Sparc backend. // -TargetMachine *allocateSparcTargetMachine(); +TargetMachine *allocateSparcTargetMachine(unsigned Configuration = + TM::PtrSize64|TM::BigEndian); // allocateX86TargetMachine - Allocate and return a subclass of TargetMachine // that implements the X86 backend. The X86 target machine can run in @@ -33,6 +34,6 @@ // size and different endianness if desired. // TargetMachine *allocateX86TargetMachine(unsigned Configuration = - TM::PtrSize32|TM::LittleEndian); + TM::PtrSize32|TM::LittleEndian); #endif From brukman at cs.uiuc.edu Tue May 27 16:48:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 16:48:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/CodeGen/MachineCodeEmitter.h Message-ID: <200305272147.QAA25163@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/CodeGen: MachineCodeEmitter.h updated: 1.9 -> 1.10 --- Log message: Defines a pass-through debugging emitter -- it writes to a file for inspection and to memory to test execution (using a passed-in code emitter). --- Diffs of the changes: Index: llvm/include/llvm/CodeGen/MachineCodeEmitter.h diff -u llvm/include/llvm/CodeGen/MachineCodeEmitter.h:1.9 llvm/include/llvm/CodeGen/MachineCodeEmitter.h:1.10 --- llvm/include/llvm/CodeGen/MachineCodeEmitter.h:1.9 Thu May 8 22:27:28 2003 +++ llvm/include/llvm/CodeGen/MachineCodeEmitter.h Tue May 27 16:46:56 2003 @@ -84,6 +84,13 @@ /// can be used for debugging users of the MachineCodeEmitter interface. /// static MachineCodeEmitter *createDebugMachineCodeEmitter(); + + /// createFilePrinterMachineCodeEmitter - Return a dynamically allocated + /// machine code emitter, which prints binary code to a file. This + /// can be used for debugging users of the MachineCodeEmitter interface. + /// + static MachineCodeEmitter* + createFilePrinterMachineCodeEmitter(MachineCodeEmitter&); }; #endif From brukman at cs.uiuc.edu Tue May 27 17:02:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 17:02:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcInternals.h Message-ID: <200305272201.RAA26532@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcInternals.h updated: 1.85 -> 1.86 --- Log message: Add prototypes to add passes to JIT compilation and code emission. Also, added annotations to how instructions are modified (reg/imm operands). Added prototype for adding register numbers to values pass for interfacing with the target-independent register allocators in the JIT. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/SparcInternals.h diff -u llvm/lib/Target/Sparc/SparcInternals.h:1.85 llvm/lib/Target/Sparc/SparcInternals.h:1.86 --- llvm/lib/Target/Sparc/SparcInternals.h:1.85 Mon May 26 19:02:22 2003 +++ llvm/lib/Target/Sparc/SparcInternals.h Tue May 27 17:01:10 2003 @@ -90,14 +90,14 @@ bool ignore; if (this->maxImmedConstant(opCode, ignore) != 0) { // 1st store opcode - assert(! this->isStore((MachineOpCode) V9::STB - 1)); + assert(! this->isStore((MachineOpCode) V9::STB - 1)); //r // last store opcode - assert(! this->isStore((MachineOpCode) V9::STXFSR + 1)); + assert(! this->isStore((MachineOpCode) V9::STXFSR + 1)); //i if (opCode == V9::SETSW || opCode == V9::SETUW || opCode == V9::SETX || opCode == V9::SETHI) return 0; - if (opCode >= V9::STB && opCode <= V9::STXFSR) + if (opCode >= V9::STB && opCode <= V9::STXFSR) //r, i return 2; return 1; } @@ -107,10 +107,10 @@ /// createNOPinstr - returns the target's implementation of NOP, which is /// usually a pseudo-instruction, implemented by a degenerate version of - /// another instruction, e.g. X86: xchg ax, ax; SparcV9: sethi g0, 0 + /// another instruction, e.g. X86: xchg ax, ax; SparcV9: sethi 0, g0 /// MachineInstr* createNOPinstr() const { - return BuildMI(V9::SETHI, 2).addReg(SparcIntRegClass::g0).addZImm(0); + return BuildMI(V9::SETHI, 2).addZImm(0).addReg(SparcIntRegClass::g0); } /// isNOPinstr - not having a special NOP opcode, we need to know if a given @@ -121,9 +121,9 @@ // Make sure the instruction is EXACTLY `sethi g0, 0' if (MI.getOpcode() == V9::SETHI && MI.getNumOperands() == 2) { const MachineOperand &op0 = MI.getOperand(0), &op1 = MI.getOperand(1); - if (op0.isMachineRegister() && - op0.getMachineRegNum() == SparcIntRegClass::g0 && - op1.isImmediate() && op1.getImmedValue() == 0) + if (op0.isImmediate() && op0.getImmedValue() == 0 && + op1.isMachineRegister() && + op1.getMachineRegNum() == SparcIntRegClass::g0) { return true; } @@ -688,6 +688,12 @@ virtual bool IsUselessCopy (const MachineInstr* MI) const; }; +/// createAddRegNumToValuesPass - this pass adds unsigned register numbers to +/// instructions, since that's not done by the Sparc InstSelector, but that's +/// how the target-independent register allocator in the JIT likes to see +/// instructions. This pass enables the usage of the JIT register allocator(s). +Pass *createAddRegNumToValuesPass(); + //--------------------------------------------------------------------------- // class UltraSparcMachine // @@ -716,6 +722,9 @@ virtual const TargetOptInfo &getOptInfo() const { return optInfo; } virtual bool addPassesToEmitAssembly(PassManager &PM, std::ostream &Out); + virtual bool addPassesToJITCompile(PassManager &PM); + virtual bool addPassesToEmitMachineCode(PassManager &PM, + MachineCodeEmitter &MCE); // getPrologEpilogInsertionPass - Inserts prolog/epilog code. Pass* getPrologEpilogInsertionPass(); From brukman at cs.uiuc.edu Tue May 27 17:05:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 17:05:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/Makefile Message-ID: <200305272204.RAA27387@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: Makefile updated: 1.14 -> 1.15 --- Log message: Moved generation of the SparcV9CodeEmitter.inc file higher in the Makefile so that Makefile.common would see it. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/Makefile diff -u llvm/lib/Target/Sparc/Makefile:1.14 llvm/lib/Target/Sparc/Makefile:1.15 --- llvm/lib/Target/Sparc/Makefile:1.14 Tue May 27 15:07:58 2003 +++ llvm/lib/Target/Sparc/Makefile Tue May 27 17:04:38 2003 @@ -3,6 +3,10 @@ ExtraSource = Debug/Sparc.burm.cpp +SparcV9CodeEmitter.inc: SparcV9.td + @echo "TableGen-erating $@" + cpp -P SparcV9.td | tblgen -gen-emitter > SparcV9CodeEmitter.inc + include $(LEVEL)/Makefile.common ifdef ENABLE_OPTIMIZED @@ -32,6 +36,3 @@ $(BUILD_ROOT)/Depend/Sparc.burm.d: $(BUILD_ROOT)/Depend/.dir touch $@ -SparcV9CodeEmitter.inc: SparcV9.td - @echo "TableGen-erating $@" - cpp -P SparcV9.td | tblgen -gen-emitter > SparcV9CodeEmitter.inc From brukman at cs.uiuc.edu Tue May 27 17:21:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 17:21:01 2003 Subject: [llvm-commits] CVS: llvm/utils/TableGen/CodeEmitterGen.cpp Message-ID: <200305272220.RAA30394@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: CodeEmitterGen.cpp updated: 1.1 -> 1.2 --- Log message: * Now outputting a static function getBinaryCodeForInstr() (JIT-accessible) * For debugging purposes: + output the predefined bit pattern of the instruction * Fixed inefficiency: only load an operand from MachineInstr once * Bug fix: did not advance bit index when seeing named bit-fields "annul", "cc" and "predict" * Added a catch-all for non-supported instructions at the end of switch stmt. --- Diffs of the changes: Index: llvm/utils/TableGen/CodeEmitterGen.cpp diff -u llvm/utils/TableGen/CodeEmitterGen.cpp:1.1 llvm/utils/TableGen/CodeEmitterGen.cpp:1.2 --- llvm/utils/TableGen/CodeEmitterGen.cpp:1.1 Fri May 23 19:15:53 2003 +++ llvm/utils/TableGen/CodeEmitterGen.cpp Tue May 27 17:19:58 2003 @@ -18,9 +18,10 @@ std::string ClassName = "SparcV9CodeEmitter::"; //const std::string &Namespace = Inst->getValue("Namespace")->getName(); - o << "unsigned " << ClassName + o << "static unsigned " << ClassName << "getBinaryCodeForInstr(MachineInstr &MI) {\n" << " unsigned Value = 0;\n" + << " std::cerr << MI;\n" << " switch (MI.getOpcode()) {\n"; for (std::vector::iterator I = Insts.begin(), E = Insts.end(); I != E; ++I) @@ -38,18 +39,25 @@ unsigned Value = 0; const std::vector &Vals = R->getValues(); + o << " // prefilling: "; // Start by filling in fixed values... - for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) - if (BitInit *B = dynamic_cast(BI->getBit(i))) - Value |= B->getValue() << i; + for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) { + if (BitInit *B = dynamic_cast(BI->getBit(e-i-1))) { + Value |= B->getValue() << (e-i-1); + o << B->getValue(); + } else { + o << "0"; + } + } + o << "\n\n"; - o << " Value = " << Value << "U;\n"; - o << " // " << *InstVal << "\n"; + o << " // " << *InstVal << "\n\n"; + o << " Value = " << Value << "U;\n\n"; // Loop over all of the fields in the instruction adding in any // contributions to this value (due to bit references). // - unsigned Offset = 31, opNum=0; + unsigned op = 0; std::map OpOrder; for (unsigned i = 0, e = Vals.size(); i != e; ++i) { if (Vals[i].getName() != "Inst" && @@ -58,11 +66,15 @@ Vals[i].getName() != "cc" && Vals[i].getName() != "predict") { - o << " // " << opNum << ": " << Vals[i].getName() << "\n"; - OpOrder[Vals[i].getName()] = opNum++; + o << " // op" << op << ": " << Vals[i].getName() << "\n" + << " int64_t op" << op + <<" = getMachineOpValue(MI.getOperand("<= 0; --f) { if (Vals[f].getPrefix()) { BitsInit *FieldInitializer = (BitsInit*)Vals[f].getValue(); @@ -70,7 +82,6 @@ // Scan through the field looking for bit initializers of the current // variable... for (int i = FieldInitializer->getNumBits()-1; i >= 0; --i) { - if (BitInit *BI=dynamic_cast(FieldInitializer->getBit(i))){ --Offset; } else if (UnsetInit *UI = @@ -80,26 +91,32 @@ dynamic_cast(FieldInitializer->getBit(i))) { TypedInit *TI = VBI->getVariable(); if (VarInit *VI = dynamic_cast(TI)) { - o << " Value |= getValueBit(MI.getOperand(" - << OpOrder[VI->getName()] - << "), " << VBI->getBitNum() + o << " Value |= getValueBit(op" << OpOrder[VI->getName()] + << ", " << VBI->getBitNum() << ")" << " << " << Offset << ";\n"; --Offset; } else if (FieldInit *FI = dynamic_cast(TI)) { // FIXME: implement this! o << "FIELD INIT not implemented yet!\n"; } else { - o << "something else\n"; + o << "Error: UNIMPLEMENTED\n"; } } - } + } + } else { + if (Vals[f].getName() == "annul" || Vals[f].getName() == "cc" || + Vals[f].getName() == "predict") + --Offset; } } o << " break;\n" << " }\n"; } - o << " }\n" + o << " default:\n" + << " std::cerr << \"Not supported instr: \" << MI << \"\\n\";\n" + << " abort();\n" + << " }\n" << " return Value;\n" << "}\n"; } From brukman at cs.uiuc.edu Tue May 27 17:25:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 17:25:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/Sparc.cpp Message-ID: <200305272224.RAA30613@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: Sparc.cpp updated: 1.62 -> 1.63 --- Log message: * Allow passing in an unsigned configuration to allocateSparcTargetMachine() a default value is set in the header file. * Fixed some code layout to make it more consistent with the rest of codebase * Added addPassesToJITCompile() with relevant passes --- Diffs of the changes: Index: llvm/lib/Target/Sparc/Sparc.cpp diff -u llvm/lib/Target/Sparc/Sparc.cpp:1.62 llvm/lib/Target/Sparc/Sparc.cpp:1.63 --- llvm/lib/Target/Sparc/Sparc.cpp:1.62 Sat Apr 26 15:11:01 2003 +++ llvm/lib/Target/Sparc/Sparc.cpp Tue May 27 17:24:48 2003 @@ -53,9 +53,9 @@ // that implements the Sparc backend. (the llvm/CodeGen/Sparc.h interface) //---------------------------------------------------------------------------- -TargetMachine *allocateSparcTargetMachine() { return new UltraSparc(); } - - +TargetMachine *allocateSparcTargetMachine(unsigned Configuration) { + return new UltraSparc(); +} //--------------------------------------------------------------------------- // class UltraSparcFrameInfo @@ -155,13 +155,12 @@ // Specialize LLVM code for this target machine and then // run basic dataflow optimizations on LLVM code. - if (!DisablePreSelect) - { - PM.add(createPreSelectionPass(*this)); - PM.add(createReassociatePass()); - PM.add(createLICMPass()); - PM.add(createGCSEPass()); - } + if (!DisablePreSelect) { + PM.add(createPreSelectionPass(*this)); + PM.add(createReassociatePass()); + PM.add(createLICMPass()); + PM.add(createGCSEPass()); + } PM.add(createInstructionSelectionPass(*this)); @@ -193,4 +192,30 @@ PM.add(getEmitBytecodeToAsmPass(Out)); PM.add(getFunctionInfo(Out)); return false; +} + +// addPassesToJITCompile - This method controls the JIT method of code +// generation for the UltraSparc. +// +bool UltraSparc::addPassesToJITCompile(PassManager &PM) { + // FIXME: implement the switch instruction in the instruction selector. + PM.add(createLowerSwitchPass()); + + // Construct and initialize the MachineFunction object for this fn. + PM.add(createMachineCodeConstructionPass(*this)); + + //Insert empty stackslots in the stack frame of each function + //so %fp+offset-8 and %fp+offset-16 are empty slots now! + PM.add(createStackSlotsPass(*this)); + + PM.add(createInstructionSelectionPass(*this)); + + // new pass: convert Value* in MachineOperand to an unsigned register + // this brings it in line with what the X86 JIT's RegisterAllocator expects + //PM.add(createAddRegNumToValuesPass()); + + PM.add(getRegisterAllocator(*this)); + PM.add(getPrologEpilogInsertionPass()); + + return false; // success! } From brukman at cs.uiuc.edu Tue May 27 17:30:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 17:30:01 2003 Subject: [llvm-commits] CVS: llvm/utils/TableGen/CodeEmitterGen.cpp Message-ID: <200305272229.RAA31228@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: CodeEmitterGen.cpp updated: 1.2 -> 1.3 --- Log message: Cannot output `static' in generated cpp code: results in error. It's already specified as a static member in class definition. --- Diffs of the changes: Index: llvm/utils/TableGen/CodeEmitterGen.cpp diff -u llvm/utils/TableGen/CodeEmitterGen.cpp:1.2 llvm/utils/TableGen/CodeEmitterGen.cpp:1.3 --- llvm/utils/TableGen/CodeEmitterGen.cpp:1.2 Tue May 27 17:19:58 2003 +++ llvm/utils/TableGen/CodeEmitterGen.cpp Tue May 27 17:29:02 2003 @@ -18,7 +18,7 @@ std::string ClassName = "SparcV9CodeEmitter::"; //const std::string &Namespace = Inst->getValue("Namespace")->getName(); - o << "static unsigned " << ClassName + o << "unsigned " << ClassName << "getBinaryCodeForInstr(MachineInstr &MI) {\n" << " unsigned Value = 0;\n" << " std::cerr << MI;\n" From brukman at cs.uiuc.edu Tue May 27 17:33:00 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 17:33:00 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcInstr.def Message-ID: <200305272232.RAA31250@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcInstr.def updated: 1.15 -> 1.16 --- Log message: One of the first major changes to make the work of JITting easier: adding annotations on instructions to specify which format they are (i.e., do they take 2 registers and 1 immediate or just 3 registers) as that changes their binary representation and hence, code emission. This makes instructions more like how X86 defines them to be. Now, writers of instruction selection must choose the correct opcode based on what instruction type they are building, which they already know. Thus, the JIT doesn't have to do the same work by `discovering' which operands an instruction really has. As this involves lots of small changes to a lot of files in lib/target/Sparc, I'll commit them individually because otherwise the diffs will be unreadable. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/SparcInstr.def diff -u llvm/lib/Target/Sparc/SparcInstr.def:1.15 llvm/lib/Target/Sparc/SparcInstr.def:1.16 --- llvm/lib/Target/Sparc/SparcInstr.def:1.15 Tue Jan 14 15:59:15 2003 +++ llvm/lib/Target/Sparc/SparcInstr.def Tue May 27 17:32:38 2003 @@ -52,22 +52,33 @@ I(SETHI, "sethi", 2, 1, B22, false, 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG | M_ARITH_FLAG) // Add or add with carry. -I(ADD , "add", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG) -I(ADDcc , "addcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_ARITH_FLAG | M_CC_FLAG ) -I(ADDC , "addc", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG) -I(ADDCcc, "addccc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_ARITH_FLAG | M_CC_FLAG ) +I(ADDr , "add", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG) +I(ADDi , "add", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG) +I(ADDccr, "addcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_ARITH_FLAG | M_CC_FLAG ) +I(ADDcci, "addcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_ARITH_FLAG | M_CC_FLAG ) +I(ADDCr , "addc", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG) +I(ADDCi , "addc", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG) +I(ADDCccr, "addccc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_ARITH_FLAG | M_CC_FLAG ) +I(ADDCcci, "addccc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_ARITH_FLAG | M_CC_FLAG ) // Subtract or subtract with carry. -I(SUB , "sub", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG) -I(SUBcc , "subcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_ARITH_FLAG | M_CC_FLAG ) -I(SUBC , "subc", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG) -I(SUBCcc, "subccc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_ARITH_FLAG | M_CC_FLAG ) +I(SUBr , "sub", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG) +I(SUBi , "sub", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG) +I(SUBccr , "subcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_ARITH_FLAG | M_CC_FLAG ) +I(SUBcci , "subcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_ARITH_FLAG | M_CC_FLAG ) +I(SUBCr , "subc", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG) +I(SUBCi , "subc", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG) +I(SUBCccr, "subccc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_ARITH_FLAG | M_CC_FLAG ) +I(SUBCcci, "subccc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_ARITH_FLAG | M_CC_FLAG ) // Integer multiply, signed divide, unsigned divide. // Note that the deprecated 32-bit multiply and multiply-step are not used. -I(MULX , "mulx", 3, 2, B12, true , 0, 3, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG) -I(SDIVX, "sdivx", 3, 2, B12, true , 0, 6, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG) -I(UDIVX, "udivx", 3, 2, B12, true , 0, 6, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG) +I(MULXr , "mulx", 3, 2, B12, true , 0, 3, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG) +I(MULXi , "mulx", 3, 2, B12, true , 0, 3, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG) +I(SDIVXr, "sdivx", 3, 2, B12, true , 0, 6, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG) +I(SDIVXi, "sdivx", 3, 2, B12, true , 0, 6, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG) +I(UDIVXr, "udivx", 3, 2, B12, true , 0, 6, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG) +I(UDIVXi, "udivx", 3, 2, B12, true , 0, 6, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG) // Floating point add, subtract, compare. // Note that destination of FCMP* instructions is operand 0, not operand 2. @@ -96,26 +107,48 @@ I(FSQRTQ, "fsqrtq", 3, 2, 0, false, 0, 0, SPARC_FPM, M_FLOAT_FLAG | M_ARITH_FLAG) // Logical operations -I(AND , "and", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG) -I(ANDcc , "andcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG) -I(ANDN , "andn", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG) -I(ANDNcc, "andncc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG) -I(OR , "or", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG) -I(ORcc , "orcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG) -I(ORN , "orn", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG) -I(ORNcc , "orncc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG) -I(XOR , "xor", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG) -I(XORcc , "xorcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG) -I(XNOR , "xnor", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG) -I(XNORcc, "xnorcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG) +I(ANDr , "and", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG) +I(ANDi , "and", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG) +I(ANDccr , "andcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG) +I(ANDcci , "andcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG) +I(ANDNr , "andn", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG) +I(ANDNi , "andn", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG) +I(ANDNccr, "andncc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG) +I(ANDNcci, "andncc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG) + +I(ORr , "or", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG) +I(ORi , "or", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG) +I(ORccr , "orcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG) +I(ORcci , "orcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG) +I(ORNr , "orn", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG) +I(ORNi , "orn", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG) +I(ORNccr, "orncc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG) +I(ORNcci, "orncc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG) + +I(XORr , "xor", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG) +I(XORi , "xor", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG) +I(XORccr , "xorcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG) +I(XORcci , "xorcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG) +I(XNORr , "xnor", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG) +I(XNORi , "xnor", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG) +I(XNORccr, "xnorcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG) +I(XNORcci, "xnorcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG) // Shift operations -I(SLL , "sll", 3, 2, B5, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG) -I(SRL , "srl", 3, 2, B5, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG) -I(SRA , "sra", 3, 2, B5, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_ARITH_FLAG) -I(SLLX, "sllx", 3, 2, B6, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG) -I(SRLX, "srlx", 3, 2, B6, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG) -I(SRAX, "srax", 3, 2, B6, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_ARITH_FLAG) +I(SLLr6 , "sll", 3, 2, B5, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG) +I(SRLr6 , "srl", 3, 2, B5, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG) +I(SRAr6 , "sra", 3, 2, B5, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_ARITH_FLAG) +I(SLLXr6, "sllx", 3, 2, B6, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG) +I(SRLXr6, "srlx", 3, 2, B6, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG) +I(SRAXr6, "srax", 3, 2, B6, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_ARITH_FLAG) + +I(SLLi6 , "sll", 3, 2, B5, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG) +I(SRLi6 , "srl", 3, 2, B5, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG) +I(SRAi6 , "sra", 3, 2, B5, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_ARITH_FLAG) +I(SLLXi6, "sllx", 3, 2, B6, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG) +I(SRLXi6, "srlx", 3, 2, B6, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG) +I(SRAXi6, "srax", 3, 2, B6, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_ARITH_FLAG) + // Floating point move, negate, and abs instructions I(FMOVS, "fmovs", 2, 1, 0, false, 0, 1, SPARC_FPA, M_FLOAT_FLAG) @@ -388,47 +421,72 @@ // Not reflected here: After a 3-cycle loads, all subsequent consecutive // loads also require 3 cycles to avoid contention for the load return // stage. Latency returns to 2 cycles after the first cycle with no load. -I(LDSB, "ldsb", 3, 2, B12, true , 0, 6, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG) -I(LDSH, "ldsh", 3, 2, B12, true , 0, 6, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG) -I(LDSW, "ldsw", 3, 2, B12, true , 0, 6, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG) -I(LDUB, "ldub", 3, 2, B12, true , 0, 5, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG) -I(LDUH, "lduh", 3, 2, B12, true , 0, 5, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG) -I(LDUW, "lduw", 3, 2, B12, true , 0, 5, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG) -I(LDX , "ldx", 3, 2, B12, true , 0, 5, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG) +I(LDSBr, "ldsb", 3, 2, B12, true , 0, 6, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG) +I(LDSBi, "ldsb", 3, 2, B12, true , 0, 6, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG) +I(LDSHr, "ldsh", 3, 2, B12, true , 0, 6, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG) +I(LDSHi, "ldsh", 3, 2, B12, true , 0, 6, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG) +I(LDSWr, "ldsw", 3, 2, B12, true , 0, 6, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG) +I(LDSWi, "ldsw", 3, 2, B12, true , 0, 6, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG) +I(LDUBr, "ldub", 3, 2, B12, true , 0, 5, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG) +I(LDUBi, "ldub", 3, 2, B12, true , 0, 5, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG) +I(LDUHr, "lduh", 3, 2, B12, true , 0, 5, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG) +I(LDUHi, "lduh", 3, 2, B12, true , 0, 5, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG) +I(LDUWr, "lduw", 3, 2, B12, true , 0, 5, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG) +I(LDUWi, "lduw", 3, 2, B12, true , 0, 5, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG) +I(LDXr , "ldx" , 3, 2, B12, true , 0, 5, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG) +I(LDXi , "ldx" , 3, 2, B12, true , 0, 5, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG) // Load floating-point instructions // Latency includes 1 cycle for address generation (Sparc IIi) -I(LD , "ld", 3, 2, B12, true , 0, 5, SPARC_LD, M_FLOAT_FLAG | M_LOAD_FLAG) -I(LDD, "ldd", 3, 2, B12, true , 0, 5, SPARC_LD, M_FLOAT_FLAG | M_LOAD_FLAG) -I(LDQ, "ldq", 3, 2, B12, true , 0, 5, SPARC_LD, M_FLOAT_FLAG | M_LOAD_FLAG) -I(LDFSR, "ld", 3, 2, B12, true , 0, 5, SPARC_LD, M_FLOAT_FLAG | M_LOAD_FLAG) -I(LDXFSR, "ldx", 3, 2, B12, true , 0, 5, SPARC_LD, M_FLOAT_FLAG | M_LOAD_FLAG) +I(LDFr , "ld", 3, 2, B12, true , 0, 5, SPARC_LD, M_FLOAT_FLAG | M_LOAD_FLAG) +I(LDFi , "ld", 3, 2, B12, true , 0, 5, SPARC_LD, M_FLOAT_FLAG | M_LOAD_FLAG) +I(LDDFr, "ldd", 3, 2, B12, true , 0, 5, SPARC_LD, M_FLOAT_FLAG | M_LOAD_FLAG) +I(LDDFi, "ldd", 3, 2, B12, true , 0, 5, SPARC_LD, M_FLOAT_FLAG | M_LOAD_FLAG) +I(LDQFr, "ldq", 3, 2, B12, true , 0, 5, SPARC_LD, M_FLOAT_FLAG | M_LOAD_FLAG) +I(LDQFi, "ldq", 3, 2, B12, true , 0, 5, SPARC_LD, M_FLOAT_FLAG | M_LOAD_FLAG) +I(LDFSRr, "ld", 3, 2, B12, true , 0, 5, SPARC_LD, M_FLOAT_FLAG | M_LOAD_FLAG) +I(LDFSRi, "ld", 3, 2, B12, true , 0, 5, SPARC_LD, M_FLOAT_FLAG | M_LOAD_FLAG) +I(LDXFSRr, "ldx", 3, 2, B12, true , 0, 5, SPARC_LD, M_FLOAT_FLAG | M_LOAD_FLAG) +I(LDXFSRi, "ldx", 3, 2, B12, true , 0, 5, SPARC_LD, M_FLOAT_FLAG | M_LOAD_FLAG) // Store integer instructions. // Requires 1 cycle for address generation (Sparc IIi). // Default latency is 0 because value is not explicitly used. -I(STB, "stb", 3, -1, B12, true , 0, 0, SPARC_ST, M_INT_FLAG | M_STORE_FLAG) -I(STH, "sth", 3, -1, B12, true , 0, 0, SPARC_ST, M_INT_FLAG | M_STORE_FLAG) -I(STW, "stw", 3, -1, B12, true , 0, 0, SPARC_ST, M_INT_FLAG | M_STORE_FLAG) -I(STX, "stx", 3, -1, B12, true , 0, 0, SPARC_ST, M_INT_FLAG | M_STORE_FLAG) +I(STBr, "stb", 3, -1, B12, true , 0, 0, SPARC_ST, M_INT_FLAG | M_STORE_FLAG) +I(STBi, "stb", 3, -1, B12, true , 0, 0, SPARC_ST, M_INT_FLAG | M_STORE_FLAG) +I(STHr, "sth", 3, -1, B12, true , 0, 0, SPARC_ST, M_INT_FLAG | M_STORE_FLAG) +I(STHi, "sth", 3, -1, B12, true , 0, 0, SPARC_ST, M_INT_FLAG | M_STORE_FLAG) +I(STWr, "stw", 3, -1, B12, true , 0, 0, SPARC_ST, M_INT_FLAG | M_STORE_FLAG) +I(STWi, "stw", 3, -1, B12, true , 0, 0, SPARC_ST, M_INT_FLAG | M_STORE_FLAG) +I(STXr, "stx", 3, -1, B12, true , 0, 0, SPARC_ST, M_INT_FLAG | M_STORE_FLAG) +I(STXi, "stx", 3, -1, B12, true , 0, 0, SPARC_ST, M_INT_FLAG | M_STORE_FLAG) // Store floating-point instructions (Sparc IIi) -I(ST , "st", 3, -1, B12, true , 0, 0, SPARC_ST, M_FLOAT_FLAG | M_STORE_FLAG) -I(STD, "std", 3, -1, B12, true , 0, 0, SPARC_ST, M_FLOAT_FLAG | M_STORE_FLAG) -I(STFSR, "st", 3, -1, B12, true , 0, 0, SPARC_ST, M_FLOAT_FLAG | M_STORE_FLAG) -I(STXFSR, "stx", 3, -1, B12, true , 0, 0, SPARC_ST, M_FLOAT_FLAG | M_STORE_FLAG) +I(STFr, "st", 3, -1, B12, true , 0, 0, SPARC_ST, M_FLOAT_FLAG | M_STORE_FLAG) +I(STFi, "st", 3, -1, B12, true , 0, 0, SPARC_ST, M_FLOAT_FLAG | M_STORE_FLAG) +I(STDFr, "std", 3, -1, B12, true , 0, 0, SPARC_ST, M_FLOAT_FLAG | M_STORE_FLAG) +I(STDFi, "std", 3, -1, B12, true , 0, 0, SPARC_ST, M_FLOAT_FLAG | M_STORE_FLAG) +I(STFSRr, "st", 3, -1, B12, true , 0, 0, SPARC_ST, M_FLOAT_FLAG | M_STORE_FLAG) +I(STFSRi, "st", 3, -1, B12, true , 0, 0, SPARC_ST, M_FLOAT_FLAG | M_STORE_FLAG) +I(STXFSRr, "stx", 3, -1, B12, true , 0, 0, SPARC_ST, M_FLOAT_FLAG | M_STORE_FLAG) +I(STXFSRi, "stx", 3, -1, B12, true , 0, 0, SPARC_ST, M_FLOAT_FLAG | M_STORE_FLAG) // Call, Return and "Jump and link". Operand (2) for JMPL is marked as // a "result" because JMPL stores the return address for the call in it. // Latency includes the delay slot. -I(CALL , "call", 1, -1, B29, true , 1, 2, SPARC_CTI, M_CALL_FLAG) -I(JMPLCALL, "jmpl", 3, 2, B12, true , 1, 2, SPARC_CTI, M_CALL_FLAG) -I(JMPLRET, "jmpl", 3, 2, B12, true , 1, 2, SPARC_CTI, M_RET_FLAG) -I(RETURN, "return", 2, -1, 0, false, 1, 2, SPARC_CTI, M_RET_FLAG) +I(CALL, "call", 1, -1, B29, true , 1, 2, SPARC_CTI, M_CALL_FLAG) +I(JMPLCALLr, "jmpl", 3, 2, B12, true , 1, 2, SPARC_CTI, M_CALL_FLAG) +I(JMPLCALLi, "jmpl", 3, 2, B12, true , 1, 2, SPARC_CTI, M_CALL_FLAG) +I(JMPLRETr, "jmpl", 3, 2, B12, true , 1, 2, SPARC_CTI, M_RET_FLAG) +I(JMPLRETi, "jmpl", 3, 2, B12, true , 1, 2, SPARC_CTI, M_RET_FLAG) +I(RETURNr, "return", 2, -1, 0, false, 1, 2, SPARC_CTI, M_RET_FLAG) +I(RETURNi, "return", 2, -1, 0, false, 1, 2, SPARC_CTI, M_RET_FLAG) // SAVE and restore instructions -I(SAVE , "save", 3, 2, B12, true , 0, 1, SPARC_SINGLE, M_INT_FLAG | M_ARITH_FLAG) -I(RESTORE, "restore", 3, 2, B12, true , 0, 1, SPARC_SINGLE, M_INT_FLAG | M_ARITH_FLAG) +I(SAVEr, "save", 3, 2, B12, true , 0, 1, SPARC_SINGLE, M_INT_FLAG | M_ARITH_FLAG) +I(SAVEi, "save", 3, 2, B12, true , 0, 1, SPARC_SINGLE, M_INT_FLAG | M_ARITH_FLAG) +I(RESTOREr, "restore", 3, 2, B12, true , 0, 1, SPARC_SINGLE, M_INT_FLAG | M_ARITH_FLAG) +I(RESTOREi, "restore", 3, 2, B12, true , 0, 1, SPARC_SINGLE, M_INT_FLAG | M_ARITH_FLAG) // Read and Write CCR register from/to an int reg I(RDCCR, "rd", 2, 2, 0, false, 0, 1, SPARC_SINGLE, M_INT_FLAG | M_CC_FLAG) From brukman at cs.uiuc.edu Tue May 27 17:34:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 17:34:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/UltraSparcSchedInfo.cpp Message-ID: <200305272233.RAA31264@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: UltraSparcSchedInfo.cpp updated: 1.4 -> 1.5 --- Log message: Added entries for each of the instructions with annotations ('r' or 'i'). --- Diffs of the changes: Index: llvm/lib/Target/Sparc/UltraSparcSchedInfo.cpp diff -u llvm/lib/Target/Sparc/UltraSparcSchedInfo.cpp:1.4 llvm/lib/Target/Sparc/UltraSparcSchedInfo.cpp:1.5 --- llvm/lib/Target/Sparc/UltraSparcSchedInfo.cpp:1.4 Tue May 20 15:32:24 2003 +++ llvm/lib/Target/Sparc/UltraSparcSchedInfo.cpp Tue May 27 17:33:39 2003 @@ -420,10 +420,14 @@ //{ V9::STDA, true, true, 0 }, //{ V9::LDDF, true, true, 0 }, //{ V9::LDDFA, true, true, 0 }, - { V9::ADDC, true, true, 0 }, - { V9::ADDCcc, true, true, 0 }, - { V9::SUBC, true, true, 0 }, - { V9::SUBCcc, true, true, 0 }, + { V9::ADDCr, true, true, 0 }, + { V9::ADDCi, true, true, 0 }, + { V9::ADDCccr, true, true, 0 }, + { V9::ADDCcci, true, true, 0 }, + { V9::SUBCr, true, true, 0 }, + { V9::SUBCi, true, true, 0 }, + { V9::SUBCccr, true, true, 0 }, + { V9::SUBCcci, true, true, 0 }, //{ V9::LDSTUB, true, true, 0 }, //{ V9::SWAP, true, true, 0 }, //{ V9::SWAPA, true, true, 0 }, @@ -444,7 +448,8 @@ //{ V9::FLUSH, true, true, 9 }, //{ V9::FLUSHW, true, true, 9 }, //{ V9::ALIGNADDR, true, true, 0 }, - { V9::RETURN, true, true, 0 }, + { V9::RETURNr, true, true, 0 }, + { V9::RETURNi, true, true, 0 }, //{ V9::DONE, true, true, 0 }, //{ V9::RETRY, true, true, 0 }, //{ V9::TCC, true, true, 0 }, @@ -453,11 +458,14 @@ // Special cases for breaking group *before* // CURRENTLY NOT SUPPORTED! { V9::CALL, false, false, 0 }, - { V9::JMPLCALL, false, false, 0 }, - { V9::JMPLRET, false, false, 0 }, + { V9::JMPLCALLr, false, false, 0 }, + { V9::JMPLCALLi, false, false, 0 }, + { V9::JMPLRETr, false, false, 0 }, + { V9::JMPLRETi, false, false, 0 }, // Special cases for breaking the group *after* - { V9::MULX, true, true, (4+34)/2 }, + { V9::MULXr, true, true, (4+34)/2 }, + { V9::MULXi, true, true, (4+34)/2 }, { V9::FDIVS, false, true, 0 }, { V9::FDIVD, false, true, 0 }, { V9::FDIVQ, false, true, 0 }, @@ -470,8 +478,10 @@ //{ V9::MULScc, true, true, 2 }, //{ V9::SMULcc, true, true, (4+18)/2 }, //{ V9::UMULcc, true, true, (4+19)/2 }, - { V9::SDIVX, true, true, 68 }, - { V9::UDIVX, true, true, 68 }, + { V9::SDIVXr, true, true, 68 }, + { V9::SDIVXi, true, true, 68 }, + { V9::UDIVXr, true, true, 68 }, + { V9::UDIVXi, true, true, 68 }, //{ V9::SDIVcc, true, true, 36 }, //{ V9::UDIVcc, true, true, 37 }, { V9::WRCCR, true, true, 4 }, @@ -498,8 +508,10 @@ // // JMPL counts as a load/store instruction for issue! // - { V9::JMPLCALL, LSIssueSlots.rid, 0, 1 }, - { V9::JMPLRET, LSIssueSlots.rid, 0, 1 }, + { V9::JMPLCALLr, LSIssueSlots.rid, 0, 1 }, + { V9::JMPLCALLi, LSIssueSlots.rid, 0, 1 }, + { V9::JMPLRETr, LSIssueSlots.rid, 0, 1 }, + { V9::JMPLRETi, LSIssueSlots.rid, 0, 1 }, // // Many instructions cannot issue for the next 2 cycles after an FCMP @@ -509,14 +521,18 @@ { V9::FCMPD, FCMPDelayCycle.rid, 1, 3 }, { V9::FCMPQ, FCMPDelayCycle.rid, 1, 3 }, - { V9::MULX, FCMPDelayCycle.rid, 1, 1 }, - { V9::SDIVX, FCMPDelayCycle.rid, 1, 1 }, - { V9::UDIVX, FCMPDelayCycle.rid, 1, 1 }, + { V9::MULXr, FCMPDelayCycle.rid, 1, 1 }, + { V9::MULXi, FCMPDelayCycle.rid, 1, 1 }, + { V9::SDIVXr, FCMPDelayCycle.rid, 1, 1 }, + { V9::SDIVXi, FCMPDelayCycle.rid, 1, 1 }, + { V9::UDIVXr, FCMPDelayCycle.rid, 1, 1 }, + { V9::UDIVXi, FCMPDelayCycle.rid, 1, 1 }, //{ V9::SMULcc, FCMPDelayCycle.rid, 1, 1 }, //{ V9::UMULcc, FCMPDelayCycle.rid, 1, 1 }, //{ V9::SDIVcc, FCMPDelayCycle.rid, 1, 1 }, //{ V9::UDIVcc, FCMPDelayCycle.rid, 1, 1 }, - { V9::STD, FCMPDelayCycle.rid, 1, 1 }, + { V9::STDFr, FCMPDelayCycle.rid, 1, 1 }, + { V9::STDFi, FCMPDelayCycle.rid, 1, 1 }, { V9::FMOVRSZ, FCMPDelayCycle.rid, 1, 1 }, { V9::FMOVRSLEZ,FCMPDelayCycle.rid, 1, 1 }, { V9::FMOVRSLZ, FCMPDelayCycle.rid, 1, 1 }, @@ -528,7 +544,8 @@ // Some instructions are stalled in the GROUP stage if a CTI is in // the E or C stage. We model that with a fake resource CTIDelayCycle. // - { V9::LDD, CTIDelayCycle.rid, 1, 1 }, + { V9::LDDFr, CTIDelayCycle.rid, 1, 1 }, + { V9::LDDFi, CTIDelayCycle.rid, 1, 1 }, //{ V9::LDDA, CTIDelayCycle.rid, 1, 1 }, //{ V9::LDDSTUB, CTIDelayCycle.rid, 1, 1 }, //{ V9::LDDSTUBA, CTIDelayCycle.rid, 1, 1 }, @@ -543,14 +560,20 @@ // Signed int loads of less than dword size return data in cycle N1 (not C) // and put all loads in consecutive cycles into delayed load return mode. // - { V9::LDSB, LdReturn.rid, 2, -1 }, - { V9::LDSB, LdReturn.rid, 3, 1 }, - - { V9::LDSH, LdReturn.rid, 2, -1 }, - { V9::LDSH, LdReturn.rid, 3, 1 }, - - { V9::LDSW, LdReturn.rid, 2, -1 }, - { V9::LDSW, LdReturn.rid, 3, 1 }, + { V9::LDSBr, LdReturn.rid, 2, -1 }, + { V9::LDSBr, LdReturn.rid, 3, 1 }, + { V9::LDSBi, LdReturn.rid, 2, -1 }, + { V9::LDSBi, LdReturn.rid, 3, 1 }, + + { V9::LDSHr, LdReturn.rid, 2, -1 }, + { V9::LDSHr, LdReturn.rid, 3, 1 }, + { V9::LDSHi, LdReturn.rid, 2, -1 }, + { V9::LDSHi, LdReturn.rid, 3, 1 }, + + { V9::LDSWr, LdReturn.rid, 2, -1 }, + { V9::LDSWr, LdReturn.rid, 3, 1 }, + { V9::LDSWi, LdReturn.rid, 2, -1 }, + { V9::LDSWi, LdReturn.rid, 3, 1 }, // // RDPR from certain registers and RD from any register are not dispatchable @@ -574,7 +597,7 @@ //{ V9::MULScc, AllIssueSlots.rid, 2, 2-1 }, //{ V9::MULScc, AllIssueSlots.rid, 2, 2-1 }, //{ V9::MULScc, AllIssueSlots.rid, 2, 2-1 }, -//{ V9::MULScc, AllIssueSlots.rid, 2, 2-1 }, +//{ V9::MULScc, AllIssueSlots.rid, 2, 2-1 }, // // SMULcc inserts between 4 and 18 bubbles, depending on #leading 0s in rs1. @@ -583,13 +606,13 @@ //{ V9::SMULcc, AllIssueSlots.rid, 2, ((4+18)/2)-1 }, //{ V9::SMULcc, AllIssueSlots.rid, 2, ((4+18)/2)-1 }, //{ V9::SMULcc, AllIssueSlots.rid, 2, ((4+18)/2)-1 }, -//{ V9::SMULcc, AllIssueSlots.rid, 2, ((4+18)/2)-1 }, +//{ V9::SMULcc, AllIssueSlots.rid, 2, ((4+18)/2)-1 }, // SMULcc inserts between 4 and 19 bubbles, depending on #leading 0s in rs1. //{ V9::UMULcc, AllIssueSlots.rid, 2, ((4+19)/2)-1 }, //{ V9::UMULcc, AllIssueSlots.rid, 2, ((4+19)/2)-1 }, //{ V9::UMULcc, AllIssueSlots.rid, 2, ((4+19)/2)-1 }, -//{ V9::UMULcc, AllIssueSlots.rid, 2, ((4+19)/2)-1 }, +//{ V9::UMULcc, AllIssueSlots.rid, 2, ((4+19)/2)-1 }, // // MULX inserts between 4 and 34 bubbles, depending on #leading 0s in rs1. @@ -597,7 +620,7 @@ { V9::MULX, AllIssueSlots.rid, 2, ((4+34)/2)-1 }, { V9::MULX, AllIssueSlots.rid, 2, ((4+34)/2)-1 }, { V9::MULX, AllIssueSlots.rid, 2, ((4+34)/2)-1 }, - { V9::MULX, AllIssueSlots.rid, 2, ((4+34)/2)-1 }, + { V9::MULX, AllIssueSlots.rid, 2, ((4+34)/2)-1 }, // // SDIVcc inserts 36 bubbles. @@ -605,13 +628,13 @@ //{ V9::SDIVcc, AllIssueSlots.rid, 2, 36-1 }, //{ V9::SDIVcc, AllIssueSlots.rid, 2, 36-1 }, //{ V9::SDIVcc, AllIssueSlots.rid, 2, 36-1 }, -//{ V9::SDIVcc, AllIssueSlots.rid, 2, 36-1 }, +//{ V9::SDIVcc, AllIssueSlots.rid, 2, 36-1 }, // UDIVcc inserts 37 bubbles. //{ V9::UDIVcc, AllIssueSlots.rid, 2, 37-1 }, //{ V9::UDIVcc, AllIssueSlots.rid, 2, 37-1 }, //{ V9::UDIVcc, AllIssueSlots.rid, 2, 37-1 }, -//{ V9::UDIVcc, AllIssueSlots.rid, 2, 37-1 }, +//{ V9::UDIVcc, AllIssueSlots.rid, 2, 37-1 }, // // SDIVX inserts 68 bubbles. @@ -619,7 +642,7 @@ { V9::SDIVX, AllIssueSlots.rid, 2, 68-1 }, { V9::SDIVX, AllIssueSlots.rid, 2, 68-1 }, { V9::SDIVX, AllIssueSlots.rid, 2, 68-1 }, - { V9::SDIVX, AllIssueSlots.rid, 2, 68-1 }, + { V9::SDIVX, AllIssueSlots.rid, 2, 68-1 }, // // UDIVX inserts 68 bubbles. @@ -627,7 +650,7 @@ { V9::UDIVX, AllIssueSlots.rid, 2, 68-1 }, { V9::UDIVX, AllIssueSlots.rid, 2, 68-1 }, { V9::UDIVX, AllIssueSlots.rid, 2, 68-1 }, - { V9::UDIVX, AllIssueSlots.rid, 2, 68-1 }, + { V9::UDIVX, AllIssueSlots.rid, 2, 68-1 }, // // WR inserts 4 bubbles. @@ -635,7 +658,7 @@ //{ V9::WR, AllIssueSlots.rid, 2, 68-1 }, //{ V9::WR, AllIssueSlots.rid, 2, 68-1 }, //{ V9::WR, AllIssueSlots.rid, 2, 68-1 }, -//{ V9::WR, AllIssueSlots.rid, 2, 68-1 }, +//{ V9::WR, AllIssueSlots.rid, 2, 68-1 }, // // WRPR inserts 4 bubbles. @@ -643,7 +666,7 @@ //{ V9::WRPR, AllIssueSlots.rid, 2, 68-1 }, //{ V9::WRPR, AllIssueSlots.rid, 2, 68-1 }, //{ V9::WRPR, AllIssueSlots.rid, 2, 68-1 }, -//{ V9::WRPR, AllIssueSlots.rid, 2, 68-1 }, +//{ V9::WRPR, AllIssueSlots.rid, 2, 68-1 }, // // DONE inserts 9 bubbles. @@ -659,7 +682,7 @@ //{ V9::RETRY, AllIssueSlots.rid, 2, 9-1 }, //{ V9::RETRY, AllIssueSlots.rid, 2, 9-1 }, //{ V9::RETRY, AllIssueSlots.rid, 2, 9-1 }, -//{ V9::RETRY, AllIssueSlots.rid, 2, 9-1 }, +//{ V9::RETRY, AllIssueSlots.rid, 2, 9-1 }, #endif /*EXPLICIT_BUBBLES_NEEDED */ }; From brukman at cs.uiuc.edu Tue May 27 17:35:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 17:35:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/EmitAssembly.cpp Message-ID: <200305272234.RAA31277@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: EmitAssembly.cpp updated: 1.76 -> 1.77 --- Log message: Added 'r' or 'i' annotations to instructions, as SparcInstr.def has changed. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/EmitAssembly.cpp diff -u llvm/lib/Target/Sparc/EmitAssembly.cpp:1.76 llvm/lib/Target/Sparc/EmitAssembly.cpp:1.77 --- llvm/lib/Target/Sparc/EmitAssembly.cpp:1.76 Mon May 26 19:02:22 2003 +++ llvm/lib/Target/Sparc/EmitAssembly.cpp Tue May 27 17:34:18 2003 @@ -309,7 +309,8 @@ unsigned getOperandMask(unsigned Opcode) { switch (Opcode) { - case V9::SUBcc: return 1 << 3; // Remove CC argument + case V9::SUBccr: + case V9::SUBcci: return 1 << 3; // Remove CC argument //case BA: return 1 << 0; // Remove Arg #0, which is always null or xcc default: return 0; // By default, don't hack operands... } @@ -320,8 +321,10 @@ SparcFunctionAsmPrinter::OpIsBranchTargetLabel(const MachineInstr *MI, unsigned int opNum) { switch (MI->getOpCode()) { - case V9::JMPLCALL: - case V9::JMPLRET: + case V9::JMPLCALLr: + case V9::JMPLCALLi: + case V9::JMPLRETr: + case V9::JMPLRETi: return (opNum == 0); default: return false; From brukman at cs.uiuc.edu Tue May 27 17:36:00 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 17:36:00 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcInstrInfo.cpp Message-ID: <200305272235.RAA31314@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcInstrInfo.cpp updated: 1.43 -> 1.44 --- Log message: Added 'r' or 'i' annotations to instructions, as SparcInstr.def has changed. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/SparcInstrInfo.cpp diff -u llvm/lib/Target/Sparc/SparcInstrInfo.cpp:1.43 llvm/lib/Target/Sparc/SparcInstrInfo.cpp:1.44 --- llvm/lib/Target/Sparc/SparcInstrInfo.cpp:1.43 Sun May 25 16:58:11 2003 +++ llvm/lib/Target/Sparc/SparcInstrInfo.cpp Tue May 27 17:35:43 2003 @@ -108,12 +108,12 @@ if (miSETHI==NULL || C & MAXLO) { if (miSETHI) { // unsigned value with high-order bits set using SETHI - miOR = BuildMI(V9::OR,3).addReg(dest).addZImm(C).addRegDef(dest); + miOR = BuildMI(V9::ORi,3).addReg(dest).addZImm(C).addRegDef(dest); miOR->setOperandLo32(1); } else { // unsigned or small signed value that fits in simm13 field of OR assert(smallNegValue || (C & ~MAXSIMM) == 0); - miOR = BuildMI(V9::OR, 3).addMReg(target.getRegInfo() + miOR = BuildMI(V9::ORi, 3).addMReg(target.getRegInfo() .getZeroRegNum()) .addSImm(sC).addRegDef(dest); } @@ -145,7 +145,7 @@ // Sign-extend to the high 32 bits if needed. // NOTE: The value C = 0x80000000 is bad: -C == C and so -C is < MAXSIMM if (C < 0 && (C == -C || -C > (int32_t) MAXSIMM)) - mvec.push_back(BuildMI(V9::SRA, 3).addReg(dest).addZImm(0).addRegDef(dest)); + mvec.push_back(BuildMI(V9::SRAi6, 3).addReg(dest).addZImm(0).addRegDef(dest)); } @@ -172,14 +172,14 @@ CreateSETUWConst(target, (C >> 32), tmpReg, mvec); // Shift tmpReg left by 32 bits - mvec.push_back(BuildMI(V9::SLLX, 3).addReg(tmpReg).addZImm(32) + mvec.push_back(BuildMI(V9::SLLXi6, 3).addReg(tmpReg).addZImm(32) .addRegDef(tmpReg)); // Code to set the low 32 bits of the value in register `dest' CreateSETUWConst(target, C, dest, mvec); // dest = OR(tmpReg, dest) - mvec.push_back(BuildMI(V9::OR,3).addReg(dest).addReg(tmpReg).addRegDef(dest)); + mvec.push_back(BuildMI(V9::ORr,3).addReg(dest).addReg(tmpReg).addRegDef(dest)); } @@ -201,7 +201,7 @@ mvec.push_back(MI); // Set the low 10 bits in dest - MI = BuildMI(V9::OR, 3).addReg(dest).addReg(val).addRegDef(dest); + MI = BuildMI(V9::ORr, 3).addReg(dest).addReg(val).addRegDef(dest); MI->setOperandLo32(1); mvec.push_back(MI); } @@ -227,20 +227,20 @@ MI->setOperandHi64(0); mvec.push_back(MI); - MI = BuildMI(V9::OR, 3).addReg(tmpReg).addPCDisp(val).addRegDef(tmpReg); + MI = BuildMI(V9::ORi, 3).addReg(tmpReg).addPCDisp(val).addRegDef(tmpReg); MI->setOperandLo64(1); mvec.push_back(MI); - mvec.push_back(BuildMI(V9::SLLX, 3).addReg(tmpReg).addZImm(32) + mvec.push_back(BuildMI(V9::SLLXi6, 3).addReg(tmpReg).addZImm(32) .addRegDef(tmpReg)); MI = BuildMI(V9::SETHI, 2).addPCDisp(val).addRegDef(dest); MI->setOperandHi32(0); mvec.push_back(MI); - MI = BuildMI(V9::OR, 3).addReg(dest).addReg(tmpReg).addRegDef(dest); + MI = BuildMI(V9::ORr, 3).addReg(dest).addReg(tmpReg).addRegDef(dest); mvec.push_back(MI); - MI = BuildMI(V9::OR, 3).addReg(dest).addPCDisp(val).addRegDef(dest); + MI = BuildMI(V9::ORi, 3).addReg(dest).addPCDisp(val).addRegDef(dest); MI->setOperandLo32(1); mvec.push_back(MI); } @@ -311,20 +311,20 @@ if (llvmOpCode >= Instruction::BinaryOpsBegin && llvmOpCode < Instruction::BinaryOpsEnd) - modelOpCode = V9::ADD; + modelOpCode = V9::ADDi; else switch(llvmOpCode) { - case Instruction::Ret: modelOpCode = V9::JMPLCALL; break; + case Instruction::Ret: modelOpCode = V9::JMPLCALLi; break; case Instruction::Malloc: case Instruction::Alloca: case Instruction::GetElementPtr: case Instruction::PHINode: case Instruction::Cast: - case Instruction::Call: modelOpCode = V9::ADD; break; + case Instruction::Call: modelOpCode = V9::ADDi; break; case Instruction::Shl: - case Instruction::Shr: modelOpCode = V9::SLLX; break; + case Instruction::Shr: modelOpCode = V9::SLLXi6; break; default: break; }; @@ -673,12 +673,12 @@ TmpInstruction *tmpI = new TmpInstruction(destVal->getType(), srcVal, destVal, "make32"); mcfi.addTemp(tmpI); - mvec.push_back(BuildMI(V9::SLLX, 3).addReg(srcVal) + mvec.push_back(BuildMI(V9::SLLXi6, 3).addReg(srcVal) .addZImm(32-numLowBits).addRegDef(tmpI)); srcVal = tmpI; } - mvec.push_back(BuildMI(signExtend? V9::SRA : V9::SRL, 3) + mvec.push_back(BuildMI(signExtend? V9::SRAi6 : V9::SRLi6, 3) .addReg(srcVal).addZImm(32-numLowBits).addRegDef(destVal)); } From brukman at cs.uiuc.edu Tue May 27 17:36:03 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 17:36:03 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/PrologEpilogCodeInserter.cpp Message-ID: <200305272235.RAA31294@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: PrologEpilogCodeInserter.cpp updated: 1.25 -> 1.26 --- Log message: Added 'r' or 'i' annotations to instructions, as SparcInstr.def has changed. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/PrologEpilogCodeInserter.cpp diff -u llvm/lib/Target/Sparc/PrologEpilogCodeInserter.cpp:1.25 llvm/lib/Target/Sparc/PrologEpilogCodeInserter.cpp:1.26 --- llvm/lib/Target/Sparc/PrologEpilogCodeInserter.cpp:1.25 Sun May 25 10:59:47 2003 +++ llvm/lib/Target/Sparc/PrologEpilogCodeInserter.cpp Tue May 27 17:35:03 2003 @@ -63,9 +63,9 @@ int32_t C = - (int) staticStackSize; int SP = TM.getRegInfo().getStackPointer(); - if (TM.getInstrInfo().constantFitsInImmedField(V9::SAVE,staticStackSize)) { - mvec.push_back(BuildMI(V9::SAVE, 3).addMReg(SP).addSImm(C).addMReg(SP, - MOTy::Def)); + if (TM.getInstrInfo().constantFitsInImmedField(V9::SAVEi,staticStackSize)) { + mvec.push_back(BuildMI(V9::SAVEi, 3).addMReg(SP).addSImm(C) + .addMReg(SP, MOTy::Def)); } else { // We have to put the stack size value into a register before SAVE. // Use register %g1 since it is volatile across calls. Note that the @@ -81,17 +81,17 @@ M->setOperandHi32(0); mvec.push_back(M); - M = BuildMI(V9::OR, 3).addMReg(uregNum).addSImm(C) + M = BuildMI(V9::ORi, 3).addMReg(uregNum).addSImm(C) .addMReg(uregNum, MOTy::Def); M->setOperandLo32(1); mvec.push_back(M); - M = BuildMI(V9::SRA, 3).addMReg(uregNum).addZImm(0) + M = BuildMI(V9::SRAi6, 3).addMReg(uregNum).addZImm(0) .addMReg(uregNum, MOTy::Def); mvec.push_back(M); // Now generate the SAVE using the value in register %g1 - M = BuildMI(V9::SAVE, 3).addMReg(SP).addMReg(uregNum).addMReg(SP,MOTy::Def); + M = BuildMI(V9::SAVEr,3).addMReg(SP).addMReg(uregNum).addMReg(SP,MOTy::Def); mvec.push_back(M); } @@ -116,7 +116,7 @@ int nextArgOffset = firstArgOffset + numFixedArgs * argSize; for (int i=numFixedArgs; i < numArgRegs; ++i) { - mvec.push_back(BuildMI(V9::STX, 3).addMReg(firstArgReg+i). + mvec.push_back(BuildMI(V9::STXi, 3).addMReg(firstArgReg+i). addMReg(fpReg).addSImm(nextArgOffset)); nextArgOffset += argSize; } @@ -139,7 +139,7 @@ { int ZR = TM.getRegInfo().getZeroRegNum(); MachineInstr *Restore = - BuildMI(V9::RESTORE, 3).addMReg(ZR).addSImm(0).addMReg(ZR, MOTy::Def); + BuildMI(V9::RESTOREi, 3).addMReg(ZR).addSImm(0).addMReg(ZR, MOTy::Def); MachineCodeForInstruction &termMvec = MachineCodeForInstruction::get(TermInst); From vadve at cs.uiuc.edu Tue May 27 17:37:01 2003 From: vadve at cs.uiuc.edu (Vikram Adve) Date: Tue May 27 17:37:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/MultiSource/aha/Makefile Message-ID: <200305272236.RAA13825@psmith.cs.uiuc.edu> Changes in directory llvm/test/Programs/MultiSource/aha: Makefile updated: 1.2 -> 1.3 --- Log message: Increase limit for aha to 300 seconds since the Sparcs are so slow! --- Diffs of the changes: Index: llvm/test/Programs/MultiSource/aha/Makefile diff -u llvm/test/Programs/MultiSource/aha/Makefile:1.2 llvm/test/Programs/MultiSource/aha/Makefile:1.3 --- llvm/test/Programs/MultiSource/aha/Makefile:1.2 Mon May 12 11:03:21 2003 +++ llvm/test/Programs/MultiSource/aha/Makefile Tue May 27 17:36:34 2003 @@ -2,5 +2,5 @@ PROG = aha CPPFLAGS = LDFLAGS = -RUNTIMELIMIT = 60 +RUNTIMELIMIT = 300 include ../Makefile.multisrc From brukman at cs.uiuc.edu Tue May 27 17:38:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 17:38:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcInstrSelection.cpp Message-ID: <200305272237.RAA31328@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcInstrSelection.cpp updated: 1.94 -> 1.95 --- Log message: Added 'r' or 'i' annotations to instructions, as SparcInstr.def has changed. Here I had to make one non-trivial change: add a function to get a version of the opcode that takes an immediate, given an opcode that takes all registers. This is required because sometimes it is not known at construction time which opcode is used because opcodes are passed around between functions. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/SparcInstrSelection.cpp diff -u llvm/lib/Target/Sparc/SparcInstrSelection.cpp:1.94 llvm/lib/Target/Sparc/SparcInstrSelection.cpp:1.95 --- llvm/lib/Target/Sparc/SparcInstrSelection.cpp:1.94 Mon May 26 19:02:22 2003 +++ llvm/lib/Target/Sparc/SparcInstrSelection.cpp Tue May 27 17:37:00 2003 @@ -618,7 +618,7 @@ MachineOpCode opCode = V9::INVALID_OPCODE; if (resultType->isInteger() || isa(resultType)) { - opCode = V9::SUB; + opCode = V9::SUBr; } else { switch(resultType->getPrimitiveID()) { @@ -695,7 +695,7 @@ MachineOpCode opCode = V9::INVALID_OPCODE; if (resultType->isInteger()) - opCode = V9::MULX; + opCode = V9::MULXr; else switch(resultType->getPrimitiveID()) { @@ -713,7 +713,7 @@ CreateIntNegInstruction(const TargetMachine& target, Value* vreg) { - return BuildMI(V9::SUB, 3).addMReg(target.getRegInfo().getZeroRegNum()) + return BuildMI(V9::SUBr, 3).addMReg(target.getRegInfo().getZeroRegNum()) .addReg(vreg).addRegDef(vreg); } @@ -747,7 +747,7 @@ // Value* shiftDest = destVal; unsigned opSize = target.getTargetData().getTypeSize(argVal1->getType()); - if ((shiftOpCode == V9::SLL || shiftOpCode == V9::SLLX) && opSize < 8) + if ((shiftOpCode == V9::SLLr6 || shiftOpCode == V9::SLLXr6) && opSize < 8) { // put SLL result into a temporary shiftDest = new TmpInstruction(argVal1, optArgVal2, "sllTmp"); mcfi.addTemp(shiftDest); @@ -781,7 +781,7 @@ MachineCodeForInstruction& mcfi) { /* Use max. multiply cost, viz., cost of MULX */ - unsigned cost = target.getInstrInfo().minLatency(V9::MULX); + unsigned cost = target.getInstrInfo().minLatency(V9::MULXr); unsigned firstNewInstr = mvec.size(); Value* constOp = rval; @@ -806,18 +806,18 @@ } if (C == 0 || C == 1) { - cost = target.getInstrInfo().minLatency(V9::ADD); + cost = target.getInstrInfo().minLatency(V9::ADDr); unsigned Zero = target.getRegInfo().getZeroRegNum(); MachineInstr* M; if (C == 0) - M = BuildMI(V9::ADD,3).addMReg(Zero).addMReg(Zero).addRegDef(destVal); + M =BuildMI(V9::ADDr,3).addMReg(Zero).addMReg(Zero).addRegDef(destVal); else - M = BuildMI(V9::ADD,3).addReg(lval).addMReg(Zero).addRegDef(destVal); + M = BuildMI(V9::ADDr,3).addReg(lval).addMReg(Zero).addRegDef(destVal); mvec.push_back(M); } else if (isPowerOf2(C, pow)) { unsigned opSize = target.getTargetData().getTypeSize(resultType); - MachineOpCode opCode = (opSize <= 32)? V9::SLL : V9::SLLX; + MachineOpCode opCode = (opSize <= 32)? V9::SLLr6 : V9::SLLXr6; CreateShiftInstructions(target, F, opCode, lval, NULL, pow, destVal, mvec, mcfi); } @@ -913,7 +913,7 @@ const Type* resultType = instrNode->getInstruction()->getType(); if (resultType->isInteger()) - opCode = resultType->isSigned()? V9::SDIVX : V9::UDIVX; + opCode = resultType->isSigned()? V9::SDIVXr : V9::UDIVXr; else switch(resultType->getPrimitiveID()) { @@ -959,7 +959,7 @@ } if (C == 1) { - mvec.push_back(BuildMI(V9::ADD, 3).addReg(LHS).addMReg(ZeroReg) + mvec.push_back(BuildMI(V9::ADDr, 3).addReg(LHS).addMReg(ZeroReg) .addRegDef(destVal)); } else if (isPowerOf2(C, pow)) { unsigned opCode; @@ -982,23 +982,24 @@ mcfi.addTemp(addTmp); // Create the SRL or SRLX instruction to get the sign bit - mvec.push_back(BuildMI((resultType==Type::LongTy)? V9::SRLX:V9::SRL,3) + mvec.push_back(BuildMI((resultType==Type::LongTy) ? + V9::SRLXi6 : V9::SRLi6, 3) .addReg(LHS) .addSImm((resultType==Type::LongTy)? 63 : 31) .addRegDef(srlTmp)); // Create the ADD instruction to add 1 for negative values - mvec.push_back(BuildMI(V9::ADD, 3).addReg(LHS).addReg(srlTmp) + mvec.push_back(BuildMI(V9::ADDr, 3).addReg(LHS).addReg(srlTmp) .addRegDef(addTmp)); // Get the shift operand and "right-shift" opcode to do the divide shiftOperand = addTmp; - opCode = (resultType==Type::LongTy) ? V9::SRAX : V9::SRA; + opCode = (resultType==Type::LongTy) ? V9::SRAXi6 : V9::SRAi6; } else { // Get the shift operand and "right-shift" opcode to do the divide shiftOperand = LHS; - opCode = (resultType==Type::LongTy) ? V9::SRLX : V9::SRL; + opCode = (resultType==Type::LongTy) ? V9::SRLXi6 : V9::SRLi6; } // Now do the actual shift! @@ -1088,11 +1089,11 @@ unsigned SPReg = target.getRegInfo().getStackPointer(); // Instruction 2: sub %sp, totalSizeVal -> %sp - getMvec.push_back(BuildMI(V9::SUB, 3).addMReg(SPReg).addReg(totalSizeVal) + getMvec.push_back(BuildMI(V9::SUBr, 3).addMReg(SPReg).addReg(totalSizeVal) .addMReg(SPReg,MOTy::Def)); // Instruction 3: add %sp, frameSizeBelowDynamicArea -> result - getMvec.push_back(BuildMI(V9::ADD, 3).addMReg(SPReg).addReg(dynamicAreaOffset) + getMvec.push_back(BuildMI(V9::ADDr,3).addMReg(SPReg).addReg(dynamicAreaOffset) .addRegDef(result)); } @@ -1118,7 +1119,7 @@ int offsetFromFP = mcInfo.getInfo()->computeOffsetforLocalVar(result, paddedSizeIgnored, tsize * numElements); - if (! target.getInstrInfo().constantFitsInImmedField(V9::LDX, offsetFromFP)) { + if (! target.getInstrInfo().constantFitsInImmedField(V9::LDXi,offsetFromFP)) { CreateCodeForVariableSizeAlloca(target, result, tsize, ConstantSInt::get(Type::IntTy,numElements), getMvec); @@ -1134,11 +1135,44 @@ // Instruction 1: add %fp, offsetFromFP -> result unsigned FPReg = target.getRegInfo().getFramePointer(); - getMvec.push_back(BuildMI(V9::ADD, 3).addMReg(FPReg).addReg(offsetVal) + getMvec.push_back(BuildMI(V9::ADDr, 3).addMReg(FPReg).addReg(offsetVal) .addRegDef(result)); } +static unsigned +convertOpcodeFromRegToImm(unsigned Opcode) { + switch (Opcode) { + case V9::ADDr: return V9::ADDi; + + /* load opcodes */ + case V9::LDUBr: return V9::LDUBi; + case V9::LDSBr: return V9::LDSBi; + case V9::LDUHr: return V9::LDUHi; + case V9::LDSHr: return V9::LDSHi; + case V9::LDUWr: return V9::LDUWi; + case V9::LDSWr: return V9::LDSWi; + case V9::LDXr: return V9::LDXi; + case V9::LDFr: return V9::LDFi; + case V9::LDDFr: return V9::LDDFi; + + /* store opcodes */ + case V9::STBr: return V9::STBi; + case V9::STHr: return V9::STHi; + case V9::STWr: return V9::STWi; + case V9::STXr: return V9::STXi; + case V9::STFr: return V9::STFi; + case V9::STDFr: return V9::STDFi; + + default: + std::cerr << "Not handled opcode in convert from reg to imm: " << Opcode + << "\n"; + abort(); + return 0; + } +} + + //------------------------------------------------------------------------ // Function SetOperandsForMemInstr // @@ -1248,16 +1282,20 @@ if (offsetOpType == MachineOperand::MO_VirtualRegister) MI = BuildMI(Opcode, 3).addReg(vmInstrNode->leftChild()->getValue()) .addReg(ptrVal).addReg(valueForRegOffset); - else + else { + Opcode = convertOpcodeFromRegToImm(Opcode); MI = BuildMI(Opcode, 3).addReg(vmInstrNode->leftChild()->getValue()) .addReg(ptrVal).addSImm(smallConstOffset); + } } else { if (offsetOpType == MachineOperand::MO_VirtualRegister) MI = BuildMI(Opcode, 3).addReg(ptrVal).addReg(valueForRegOffset) .addRegDef(memInst); - else + else { + Opcode = convertOpcodeFromRegToImm(Opcode); MI = BuildMI(Opcode, 3).addReg(ptrVal).addSImm(smallConstOffset) .addRegDef(memInst); + } } mvec.push_back(MI); } @@ -1355,7 +1393,7 @@ int argSize = target.getFrameInfo().getSizeOfEachArgOnStack(); int firstVarArgOff = numFixedArgs * argSize + target.getFrameInfo(). getFirstIncomingArgOffset(MachineFunction::get(func), ignore); - mvec.push_back(BuildMI(V9::ADD, 3).addMReg(fpReg).addSImm(firstVarArgOff). + mvec.push_back(BuildMI(V9::ADDi, 3).addMReg(fpReg).addSImm(firstVarArgOff). addReg(callInstr.getOperand(1))); return true; } @@ -1365,7 +1403,7 @@ case LLVMIntrinsic::va_copy: // Simple copy of current va_list (arg2) to new va_list (arg1) - mvec.push_back(BuildMI(V9::OR, 3). + mvec.push_back(BuildMI(V9::ORr, 3). addMReg(target.getRegInfo().getZeroRegNum()). addReg(callInstr.getOperand(2)). addReg(callInstr.getOperand(1))); @@ -1482,7 +1520,7 @@ Instruction* returnReg = new TmpInstruction(returnInstr); MachineCodeForInstruction::get(returnInstr).addTemp(returnReg); - M = BuildMI(V9::JMPLRET, 3).addReg(returnReg).addSImm(8) + M = BuildMI(V9::JMPLRETi, 3).addReg(returnReg).addSImm(8) .addMReg(target.getRegInfo().getZeroRegNum(), MOTy::Def); if (returnInstr->getReturnValue() != NULL) @@ -1634,7 +1672,7 @@ Value* notArg = BinaryOperator::getNotArgument( cast(subtreeRoot->getInstruction())); unsigned ZeroReg = target.getRegInfo().getZeroRegNum(); - mvec.push_back(BuildMI(V9::XNOR, 3).addReg(notArg).addMReg(ZeroReg) + mvec.push_back(BuildMI(V9::XNORr, 3).addReg(notArg).addMReg(ZeroReg) .addRegDef(subtreeRoot->getValue())); break; } @@ -1935,7 +1973,7 @@ case 238: // bool: And(bool, boolconst) case 338: // reg : BAnd(reg, reg) case 538: // reg : BAnd(reg, Constant) - Add3OperandInstr(V9::AND, subtreeRoot, mvec); + Add3OperandInstr(V9::ANDr, subtreeRoot, mvec); break; case 138: // bool: And(bool, not) @@ -1948,7 +1986,7 @@ notNode->markFoldedIntoParent(); Value *LHS = subtreeRoot->leftChild()->getValue(); Value *Dest = subtreeRoot->getValue(); - mvec.push_back(BuildMI(V9::ANDN, 3).addReg(LHS).addReg(notArg) + mvec.push_back(BuildMI(V9::ANDNr, 3).addReg(LHS).addReg(notArg) .addReg(Dest, MOTy::Def)); break; } @@ -1957,7 +1995,7 @@ case 239: // bool: Or(bool, boolconst) case 339: // reg : BOr(reg, reg) case 539: // reg : BOr(reg, Constant) - Add3OperandInstr(V9::OR, subtreeRoot, mvec); + Add3OperandInstr(V9::ORr, subtreeRoot, mvec); break; case 139: // bool: Or(bool, not) @@ -1970,7 +2008,7 @@ notNode->markFoldedIntoParent(); Value *LHS = subtreeRoot->leftChild()->getValue(); Value *Dest = subtreeRoot->getValue(); - mvec.push_back(BuildMI(V9::ORN, 3).addReg(LHS).addReg(notArg) + mvec.push_back(BuildMI(V9::ORNr, 3).addReg(LHS).addReg(notArg) .addReg(Dest, MOTy::Def)); break; } @@ -1979,7 +2017,7 @@ case 240: // bool: Xor(bool, boolconst) case 340: // reg : BXor(reg, reg) case 540: // reg : BXor(reg, Constant) - Add3OperandInstr(V9::XOR, subtreeRoot, mvec); + Add3OperandInstr(V9::XORr, subtreeRoot, mvec); break; case 140: // bool: Xor(bool, not) @@ -1992,7 +2030,7 @@ notNode->markFoldedIntoParent(); Value *LHS = subtreeRoot->leftChild()->getValue(); Value *Dest = subtreeRoot->getValue(); - mvec.push_back(BuildMI(V9::XNOR, 3).addReg(LHS).addReg(notArg) + mvec.push_back(BuildMI(V9::XNORr, 3).addReg(LHS).addReg(notArg) .addReg(Dest, MOTy::Def)); break; } @@ -2059,13 +2097,13 @@ // result of SUBcc instruction anyway. // if (keepSubVal) { - M = BuildMI(V9::SUBcc, 4) + M = BuildMI(V9::SUBccr, 4) .addReg(subtreeRoot->leftChild()->getValue()) .addReg(subtreeRoot->rightChild()->getValue()) .addRegDef(subtreeRoot->getValue()) .addCCReg(tmpForCC, MOTy::Def); } else { - M = BuildMI(V9::SUBcc, 4) + M = BuildMI(V9::SUBccr, 4) .addReg(subtreeRoot->leftChild()->getValue()) .addReg(subtreeRoot->rightChild()->getValue()) .addMReg(target.getRegInfo().getZeroRegNum(), MOTy::Def) @@ -2125,7 +2163,7 @@ case 56: // reg: GetElemPtrIdx(reg,reg) // If the GetElemPtr was folded into the user (parent), it will be // caught above. For other cases, we have to compute the address. - SetOperandsForMemInstr(V9::ADD, mvec, subtreeRoot, target); + SetOperandsForMemInstr(V9::ADDr, mvec, subtreeRoot, target); break; case 57: // reg: Alloca: Implement as 1 instruction: @@ -2207,7 +2245,7 @@ if (calledFunc) // direct function call M = BuildMI(V9::CALL, 1).addPCDisp(callee); else // indirect function call - M = BuildMI(V9::JMPLCALL, 3).addReg(callee).addSImm((int64_t)0) + M = BuildMI(V9::JMPLCALLi, 3).addReg(callee).addSImm((int64_t)0) .addRegDef(retAddrReg); mvec.push_back(M); @@ -2299,7 +2337,7 @@ "Shl unsupported for other types"); CreateShiftInstructions(target, shlInstr->getParent()->getParent(), - (opType == Type::LongTy)? V9::SLLX : V9::SLL, + (opType == Type::LongTy)? V9::SLLXr6:V9::SLLr6, argVal1, argVal2, 0, shlInstr, mvec, MachineCodeForInstruction::get(shlInstr)); break; @@ -2310,8 +2348,8 @@ assert((opType->isInteger() || isa(opType)) && "Shr unsupported for other types"); Add3OperandInstr(opType->isSigned() - ? (opType == Type::LongTy ? V9::SRAX : V9::SRA) - : (opType == Type::LongTy ? V9::SRLX : V9::SRL), + ? (opType == Type::LongTy ? V9::SRAXr6 : V9::SRAr6) + : (opType == Type::LongTy ? V9::SRLXr6 : V9::SRLr6), subtreeRoot, mvec); break; } @@ -2325,9 +2363,9 @@ // Load argument via current pointer value, then increment pointer. int argSize = target.getFrameInfo().getSizeOfEachArgOnStack(); Instruction* vaArgI = subtreeRoot->getInstruction(); - mvec.push_back(BuildMI(V9::LDX, 3).addReg(vaArgI->getOperand(0)). + mvec.push_back(BuildMI(V9::LDXi, 3).addReg(vaArgI->getOperand(0)). addSImm(0).addRegDef(vaArgI)); - mvec.push_back(BuildMI(V9::ADD, 3).addReg(vaArgI->getOperand(0)). + mvec.push_back(BuildMI(V9::ADDi, 3).addReg(vaArgI->getOperand(0)). addSImm(argSize).addRegDef(vaArgI->getOperand(0))); break; } @@ -2384,7 +2422,7 @@ for (unsigned i=0, N=mvec.size(); i < N; ++i) mvec[i]->substituteValue(dest, tmpI); - M = BuildMI(V9::SRL, 3).addReg(tmpI).addZImm(8*(4-destSize)) + M = BuildMI(V9::SRLi6, 3).addReg(tmpI).addZImm(8*(4-destSize)) .addReg(dest, MOTy::Def); mvec.push_back(M); } From brukman at cs.uiuc.edu Tue May 27 17:40:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 17:40:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcOptInfo.cpp Message-ID: <200305272239.RAA31360@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcOptInfo.cpp updated: 1.7 -> 1.8 --- Log message: Added 'r' and 'i' annotations to instructions as SparcInstr.def has changed. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/SparcOptInfo.cpp diff -u llvm/lib/Target/Sparc/SparcOptInfo.cpp:1.7 llvm/lib/Target/Sparc/SparcOptInfo.cpp:1.8 --- llvm/lib/Target/Sparc/SparcOptInfo.cpp:1.7 Mon May 26 19:02:22 2003 +++ llvm/lib/Target/Sparc/SparcOptInfo.cpp Tue May 27 17:39:29 2003 @@ -25,7 +25,7 @@ return (/* both operands are allocated to the same register */ MI->getOperand(0).getAllocatedRegNum() == MI->getOperand(1).getAllocatedRegNum()); - } else if (MI->getOpCode() == V9::ADD || MI->getOpCode() == V9::OR){ + } else if (MI->getOpCode() == V9::ADDr || MI->getOpCode() == V9::ORr) { unsigned srcWithDestReg; for (srcWithDestReg = 0; srcWithDestReg < 2; ++srcWithDestReg) From brukman at cs.uiuc.edu Tue May 27 17:40:04 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 17:40:04 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcInstrSelectionSupport.h Message-ID: <200305272239.RAA31342@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcInstrSelectionSupport.h updated: 1.6 -> 1.7 --- Log message: Added 'r' or 'i' annotations to instructions, as SparcInstr.def has changed. Non-obvious change: since I have changed ST and STD to be STF and STDF to (a) closer resemble their name (NOT assembly text) in the Sparc manual, and (b) clearly specify that they they are floating-point opcodes, I made the same changes in this file. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/SparcInstrSelectionSupport.h diff -u llvm/lib/Target/Sparc/SparcInstrSelectionSupport.h:1.6 llvm/lib/Target/Sparc/SparcInstrSelectionSupport.h:1.7 --- llvm/lib/Target/Sparc/SparcInstrSelectionSupport.h:1.6 Tue May 20 15:32:24 2003 +++ llvm/lib/Target/Sparc/SparcInstrSelectionSupport.h Tue May 27 17:39:01 2003 @@ -14,17 +14,17 @@ { switch (DestTy->getPrimitiveID()) { case Type::BoolTyID: - case Type::UByteTyID: return V9::LDUB; - case Type::SByteTyID: return V9::LDSB; - case Type::UShortTyID: return V9::LDUH; - case Type::ShortTyID: return V9::LDSH; - case Type::UIntTyID: return V9::LDUW; - case Type::IntTyID: return V9::LDSW; + case Type::UByteTyID: return V9::LDUBr; + case Type::SByteTyID: return V9::LDSBr; + case Type::UShortTyID: return V9::LDUHr; + case Type::ShortTyID: return V9::LDSHr; + case Type::UIntTyID: return V9::LDUWr; + case Type::IntTyID: return V9::LDSWr; case Type::PointerTyID: case Type::ULongTyID: - case Type::LongTyID: return V9::LDX; - case Type::FloatTyID: return V9::LD; - case Type::DoubleTyID: return V9::LDD; + case Type::LongTyID: return V9::LDXr; + case Type::FloatTyID: return V9::LDFr; + case Type::DoubleTyID: return V9::LDDFr; default: assert(0 && "Invalid type for Load instruction"); } @@ -37,16 +37,16 @@ switch (DestTy->getPrimitiveID()) { case Type::BoolTyID: case Type::UByteTyID: - case Type::SByteTyID: return V9::STB; + case Type::SByteTyID: return V9::STBr; case Type::UShortTyID: - case Type::ShortTyID: return V9::STH; + case Type::ShortTyID: return V9::STHr; case Type::UIntTyID: - case Type::IntTyID: return V9::STW; + case Type::IntTyID: return V9::STWr; case Type::PointerTyID: case Type::ULongTyID: - case Type::LongTyID: return V9::STX; - case Type::FloatTyID: return V9::ST; - case Type::DoubleTyID: return V9::STD; + case Type::LongTyID: return V9::STXr; + case Type::FloatTyID: return V9::STFr; + case Type::DoubleTyID: return V9::STDFr; default: assert(0 && "Invalid type for Store instruction"); } @@ -64,7 +64,7 @@ isa(resultType) || resultType == Type::LabelTy) { - opCode = V9::ADD; + opCode = V9::ADDr; } else switch(resultType->getPrimitiveID()) From brukman at cs.uiuc.edu Tue May 27 17:41:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 17:41:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcRegInfo.cpp Message-ID: <200305272240.RAA31375@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcRegInfo.cpp updated: 1.94 -> 1.95 --- Log message: Added 'r' and 'i' annotations to instructions as SparcInstr.def has changed. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/SparcRegInfo.cpp diff -u llvm/lib/Target/Sparc/SparcRegInfo.cpp:1.94 llvm/lib/Target/Sparc/SparcRegInfo.cpp:1.95 --- llvm/lib/Target/Sparc/SparcRegInfo.cpp:1.94 Mon May 26 19:02:22 2003 +++ llvm/lib/Target/Sparc/SparcRegInfo.cpp Tue May 27 17:40:34 2003 @@ -1096,7 +1096,7 @@ break; case IntRegType: - MI = BuildMI(V9::ADD, 3).addMReg(SrcReg).addMReg(getZeroRegNum()) + MI = BuildMI(V9::ADDr, 3).addMReg(SrcReg).addMReg(getZeroRegNum()) .addMReg(DestReg, MOTy::Def); break; @@ -1132,18 +1132,21 @@ MachineInstr * MI = NULL; switch (RegType) { case IntRegType: - assert(target.getInstrInfo().constantFitsInImmedField(V9::STX, Offset)); - MI = BuildMI(V9::STX,3).addMReg(SrcReg).addMReg(DestPtrReg).addSImm(Offset); + assert(target.getInstrInfo().constantFitsInImmedField(V9::STXi, Offset)); + MI = BuildMI(V9::STXi,3).addMReg(SrcReg).addMReg(DestPtrReg) + .addSImm(Offset); break; case FPSingleRegType: - assert(target.getInstrInfo().constantFitsInImmedField(V9::ST, Offset)); - MI = BuildMI(V9::ST, 3).addMReg(SrcReg).addMReg(DestPtrReg).addSImm(Offset); + assert(target.getInstrInfo().constantFitsInImmedField(V9::STFi, Offset)); + MI = BuildMI(V9::STFi, 3).addMReg(SrcReg).addMReg(DestPtrReg) + .addSImm(Offset); break; case FPDoubleRegType: - assert(target.getInstrInfo().constantFitsInImmedField(V9::STD, Offset)); - MI = BuildMI(V9::STD,3).addMReg(SrcReg).addMReg(DestPtrReg).addSImm(Offset); + assert(target.getInstrInfo().constantFitsInImmedField(V9::STDFi, Offset)); + MI = BuildMI(V9::STDFi,3).addMReg(SrcReg).addMReg(DestPtrReg) + .addSImm(Offset); break; case IntCCRegType: @@ -1158,10 +1161,10 @@ return; case FloatCCRegType: { - assert(target.getInstrInfo().constantFitsInImmedField(V9::STXFSR, Offset)); + assert(target.getInstrInfo().constantFitsInImmedField(V9::STXFSRi, Offset)); unsigned fsrRegNum = getUnifiedRegNum(UltraSparcRegInfo::SpecialRegClassID, SparcSpecialRegClass::fsr); - MI = BuildMI(V9::STXFSR, 3) + MI = BuildMI(V9::STXFSRi, 3) .addMReg(fsrRegNum).addMReg(DestPtrReg).addSImm(Offset); break; } @@ -1188,21 +1191,21 @@ MachineInstr * MI = NULL; switch (RegType) { case IntRegType: - assert(target.getInstrInfo().constantFitsInImmedField(V9::LDX, Offset)); - MI = BuildMI(V9::LDX, 3).addMReg(SrcPtrReg).addSImm(Offset) + assert(target.getInstrInfo().constantFitsInImmedField(V9::LDXi, Offset)); + MI = BuildMI(V9::LDXi, 3).addMReg(SrcPtrReg).addSImm(Offset) .addMReg(DestReg, MOTy::Def); break; case FPSingleRegType: - assert(target.getInstrInfo().constantFitsInImmedField(V9::LD, Offset)); - MI = BuildMI(V9::LD, 3).addMReg(SrcPtrReg).addSImm(Offset) + assert(target.getInstrInfo().constantFitsInImmedField(V9::LDFi, Offset)); + MI = BuildMI(V9::LDFi, 3).addMReg(SrcPtrReg).addSImm(Offset) .addMReg(DestReg, MOTy::Def); break; case FPDoubleRegType: - assert(target.getInstrInfo().constantFitsInImmedField(V9::LDD, Offset)); - MI = BuildMI(V9::LDD, 3).addMReg(SrcPtrReg).addSImm(Offset).addMReg(DestReg, - MOTy::Def); + assert(target.getInstrInfo().constantFitsInImmedField(V9::LDDFi, Offset)); + MI = BuildMI(V9::LDDFi, 3).addMReg(SrcPtrReg).addSImm(Offset) + .addMReg(DestReg, MOTy::Def); break; case IntCCRegType: @@ -1215,10 +1218,10 @@ break; case FloatCCRegType: { - assert(target.getInstrInfo().constantFitsInImmedField(V9::LDXFSR, Offset)); + assert(target.getInstrInfo().constantFitsInImmedField(V9::LDXFSRi, Offset)); unsigned fsrRegNum = getUnifiedRegNum(UltraSparcRegInfo::SpecialRegClassID, SparcSpecialRegClass::fsr); - MI = BuildMI(V9::LDXFSR, 3).addMReg(SrcPtrReg).addSImm(Offset) + MI = BuildMI(V9::LDXFSRi, 3).addMReg(SrcPtrReg).addSImm(Offset) .addMReg(fsrRegNum, MOTy::UseAndDef); break; } @@ -1243,7 +1246,7 @@ switch( RegType ) { case IntRegType: - MI = BuildMI(V9::ADD, 3).addReg(Src).addMReg(getZeroRegNum()) + MI = BuildMI(V9::ADDr, 3).addReg(Src).addMReg(getZeroRegNum()) .addRegDef(Dest); break; case FPSingleRegType: From brukman at cs.uiuc.edu Tue May 27 17:42:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 17:42:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcV9CodeEmitter.h SparcV9CodeEmitter.cpp Message-ID: <200305272241.RAA31396@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcV9CodeEmitter.h updated: 1.1 -> 1.2 SparcV9CodeEmitter.cpp updated: 1.2 -> 1.3 --- Log message: Keep track of the current BasicBlock being processed so that a referencing MachineInstr can later be patched up correctly. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/SparcV9CodeEmitter.h diff -u llvm/lib/Target/Sparc/SparcV9CodeEmitter.h:1.1 llvm/lib/Target/Sparc/SparcV9CodeEmitter.h:1.2 --- llvm/lib/Target/Sparc/SparcV9CodeEmitter.h:1.1 Tue May 27 16:45:05 2003 +++ llvm/lib/Target/Sparc/SparcV9CodeEmitter.h Tue May 27 17:41:44 2003 @@ -3,12 +3,14 @@ #ifndef SPARCV9CODEEMITTER_H #define SPARCV9CODEEMITTER_H +#include "llvm/BasicBlock.h" #include "llvm/CodeGen/MachineCodeEmitter.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" class SparcV9CodeEmitter : public MachineFunctionPass { MachineCodeEmitter &MCE; + BasicBlock *BB; public: SparcV9CodeEmitter(MachineCodeEmitter &M) : MCE(M) {} Index: llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp diff -u llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp:1.2 llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp:1.3 --- llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp:1.2 Tue May 27 16:45:05 2003 +++ llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp Tue May 27 17:41:44 2003 @@ -30,8 +30,7 @@ } else if (MO.isImmediate()) { return MO.getImmedValue(); } else if (MO.isPCRelativeDisp()) { - // FIXME!!! - //return MO.getPCRelativeDisp(); + MCE->saveBBreference(currBB, MO); return 0; } else { assert(0 && "Unknown type of MachineOperand"); @@ -55,6 +54,7 @@ } void SparcV9CodeEmitter::emitBasicBlock(MachineBasicBlock &MBB) { + currBB = MBB.getBasicBlock(); MCE.startBasicBlock(MBB); for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I) emitInstruction(**I); From brukman at cs.uiuc.edu Tue May 27 17:44:00 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 17:44:00 2003 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/MachineCodeEmitter.cpp Message-ID: <200305272243.RAA31425@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: MachineCodeEmitter.cpp updated: 1.5 -> 1.6 --- Log message: Added a debugging code emitter that prints code to a file, debug to std::cerr, and passes the real code to a memory-outputting code emitter. This may be removed at a later point in development. --- Diffs of the changes: Index: llvm/lib/CodeGen/MachineCodeEmitter.cpp diff -u llvm/lib/CodeGen/MachineCodeEmitter.cpp:1.5 llvm/lib/CodeGen/MachineCodeEmitter.cpp:1.6 --- llvm/lib/CodeGen/MachineCodeEmitter.cpp:1.5 Thu May 8 22:27:41 2003 +++ llvm/lib/CodeGen/MachineCodeEmitter.cpp Tue May 27 17:43:19 2003 @@ -8,6 +8,7 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/Function.h" #include +#include namespace { struct DebugMachineCodeEmitter : public MachineCodeEmitter { @@ -58,4 +59,124 @@ /// MachineCodeEmitter *MachineCodeEmitter::createDebugMachineCodeEmitter() { return new DebugMachineCodeEmitter(); +} + +namespace { + class FilePrinterMachineCodeEmitter : public MachineCodeEmitter { + std::ofstream f, actual; + std::ostream &o; + MachineCodeEmitter *MCE; + unsigned counter; + bool mustClose; + unsigned values[4]; + + public: + FilePrinterMachineCodeEmitter() : + f("lli.out"), o(f), counter(0), mustClose(true) + { + if (! f.good()) { + std::cerr << "Cannot open 'lli.out' for writing\n"; + abort(); + } + openActual(); + } + + FilePrinterMachineCodeEmitter(MachineCodeEmitter &M, std::ostream &os) : + o(os), MCE(&M), counter(0) + { + FilePrinterMachineCodeEmitter(); + mustClose = false; + openActual(); + } + + ~FilePrinterMachineCodeEmitter() { + o << "\n"; + actual.close(); + if (mustClose) f.close(); + } + + void openActual() { + actual.open("lli.actual.obj"); + if (! actual.good()) { + std::cerr << "Cannot open 'lli.actual.obj' for writing\n"; + abort(); + } + } + + void startFunction(MachineFunction &F) { + // resolve any outstanding calls + if (MCE) MCE->startFunction(F); + } + void finishFunction(MachineFunction &F) { + if (MCE) MCE->finishFunction(F); + } + + void startBasicBlock(MachineBasicBlock &BB) { + // if any instructions were waiting for the address of this block, + // let them fix their addresses now + if (MCE) MCE->startBasicBlock(BB); + } + + void startFunctionStub(const Function &F, unsigned StubSize) { + // + if (MCE) MCE->startFunctionStub(F, StubSize); + } + + void *finishFunctionStub(const Function &F) { + if (MCE) return MCE->finishFunctionStub(F); + else return 0; + } + + void emitByte(unsigned char B) { + if (MCE) MCE->emitByte(B); + + values[counter] = (unsigned int) B; + if (++counter % 4 == 0 && counter != 0) { + o << std::hex; + for (unsigned i=0; i<4; ++i) { + if (values[i] < 16) o << "0"; + o << values[i] << " "; + actual << values[i]; + } + actual.flush(); + + o << std::dec << "\t"; + for (unsigned i=0; i<4; ++i) { + for (int j=7; j>=0; --j) { + o << ((values[i] >> j) & 1); + } + o << " "; + } + + o << "\n"; + + unsigned instr = 0; + for (unsigned i=0; i<4; ++i) + instr |= values[i] << (i*8); + + o << "--- * --- * --- * --- * ---\n"; + counter %= 4; + } + } + void emitPCRelativeDisp(Value *V) { + // put block in mapping BB -> { instr, address }. when BB is beginning to + // output, find instr, set disp, overwrite instr at addr using the + // unsigned value gotten from emitter + } + + void emitGlobalAddress(GlobalValue *V, bool isPCRelative) { + if (MCE) MCE->emitGlobalAddress(V, isPCRelative); + } + void emitGlobalAddress(const std::string &Name, bool isPCRelative) { + if (MCE) MCE->emitGlobalAddress(Name, isPCRelative); + } + + void emitFunctionConstantValueAddress(unsigned ConstantNum, int Offset) { + if (MCE) MCE->emitFunctionConstantValueAddress(ConstantNum, Offset); + } + }; +} + +MachineCodeEmitter *MachineCodeEmitter::createFilePrinterMachineCodeEmitter(MachineCodeEmitter &MCE) { + return new FilePrinterMachineCodeEmitter(MCE, std::cerr); } From brukman at cs.uiuc.edu Tue May 27 17:45:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 17:45:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcInternals.h Message-ID: <200305272244.RAA31963@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcInternals.h updated: 1.86 -> 1.87 --- Log message: Added the 'r' and 'i' annotations to instructions as their opcode names have changed. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/SparcInternals.h diff -u llvm/lib/Target/Sparc/SparcInternals.h:1.86 llvm/lib/Target/Sparc/SparcInternals.h:1.87 --- llvm/lib/Target/Sparc/SparcInternals.h:1.86 Tue May 27 17:01:10 2003 +++ llvm/lib/Target/Sparc/SparcInternals.h Tue May 27 17:44:44 2003 @@ -90,14 +90,14 @@ bool ignore; if (this->maxImmedConstant(opCode, ignore) != 0) { // 1st store opcode - assert(! this->isStore((MachineOpCode) V9::STB - 1)); //r + assert(! this->isStore((MachineOpCode) V9::STBr - 1)); // last store opcode - assert(! this->isStore((MachineOpCode) V9::STXFSR + 1)); //i + assert(! this->isStore((MachineOpCode) V9::STXFSRi + 1)); if (opCode == V9::SETSW || opCode == V9::SETUW || opCode == V9::SETX || opCode == V9::SETHI) return 0; - if (opCode >= V9::STB && opCode <= V9::STXFSR) //r, i + if (opCode >= V9::STBr && opCode <= V9::STXFSRi) return 2; return 1; } From brukman at cs.uiuc.edu Tue May 27 17:49:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 27 17:49:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcV9CodeEmitter.h SparcV9CodeEmitter.cpp Message-ID: <200305272248.RAA00699@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcV9CodeEmitter.h updated: 1.2 -> 1.3 SparcV9CodeEmitter.cpp updated: 1.3 -> 1.4 --- Log message: Fixed an error preventing compilation. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/SparcV9CodeEmitter.h diff -u llvm/lib/Target/Sparc/SparcV9CodeEmitter.h:1.2 llvm/lib/Target/Sparc/SparcV9CodeEmitter.h:1.3 --- llvm/lib/Target/Sparc/SparcV9CodeEmitter.h:1.2 Tue May 27 17:41:44 2003 +++ llvm/lib/Target/Sparc/SparcV9CodeEmitter.h Tue May 27 17:48:28 2003 @@ -10,7 +10,7 @@ class SparcV9CodeEmitter : public MachineFunctionPass { MachineCodeEmitter &MCE; - BasicBlock *BB; + BasicBlock *currBB; public: SparcV9CodeEmitter(MachineCodeEmitter &M) : MCE(M) {} Index: llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp diff -u llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp:1.3 llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp:1.4 --- llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp:1.3 Tue May 27 17:41:44 2003 +++ llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp Tue May 27 17:48:28 2003 @@ -30,7 +30,7 @@ } else if (MO.isImmediate()) { return MO.getImmedValue(); } else if (MO.isPCRelativeDisp()) { - MCE->saveBBreference(currBB, MO); + //MCE.saveBBreference(currBB, MO); return 0; } else { assert(0 && "Unknown type of MachineOperand"); From jstanley at cs.uiuc.edu Wed May 28 08:53:01 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Wed May 28 08:53:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp Message-ID: <200305281352.IAA17785@trinity.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst/lib: SparcInstManip.cpp updated: 1.15 -> 1.16 --- Log message: --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp diff -u llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.15 llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.16 --- llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.15 Sun May 18 22:00:38 2003 +++ llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp Wed May 28 08:52:41 2003 @@ -411,8 +411,8 @@ // NB: Clearing PROT_WRITE here will result in subsequent valloc/memalign calls // segfaulting. Apparently, write access to the page is still needed for later heap - // allocations from the same page, although the requirement of write access is - // somewhat unclear. + // allocations from the same page, although the reasons why write access are somewhat + // unclear. setPageBits(heapSlot, numHeapBytes, PROT_READ | PROT_WRITE | PROT_EXEC); From jstanley at cs.uiuc.edu Wed May 28 08:54:01 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Wed May 28 08:54:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Reoptimizer/BinInterface/sparc9.h Message-ID: <200305281353.IAA17815@trinity.cs.uiuc.edu> Changes in directory llvm/include/llvm/Reoptimizer/BinInterface: sparc9.h updated: 1.12 -> 1.13 --- Log message: --- Diffs of the changes: Index: llvm/include/llvm/Reoptimizer/BinInterface/sparc9.h diff -u llvm/include/llvm/Reoptimizer/BinInterface/sparc9.h:1.12 llvm/include/llvm/Reoptimizer/BinInterface/sparc9.h:1.13 --- llvm/include/llvm/Reoptimizer/BinInterface/sparc9.h:1.12 Tue Apr 15 16:32:53 2003 +++ llvm/include/llvm/Reoptimizer/BinInterface/sparc9.h Wed May 28 08:53:48 2003 @@ -443,9 +443,25 @@ MK_FLD(INSTR_X, 1) | \ MK_FLD(INSTR_SHCNT64, shcnt)) +#define MK_STORE_IMM(srcreg, basereg, offset) \ + (MK_FLD(INSTR_OP, OP_3) | \ + MK_FLD(INSTR_RD, srcreg) | \ + MK_FLD(INSTR_OP3, OP3_STX) | \ + MK_FLD(INSTR_RS1, basereg) | \ + MK_FLD(INSTR_I, 1) | \ + MK_FLD(INSTR_SIMM13, offset)) + +#define MK_LOAD_IMM(destreg, basereg, offset) \ + (MK_FLD(INSTR_OP, OP_3) | \ + MK_FLD(INSTR_RD, destreg) | \ + MK_FLD(INSTR_OP3, OP3_LDX) | \ + MK_FLD(INSTR_RS1, basereg) | \ + MK_FLD(INSTR_I, 1) | \ + MK_FLD(INSTR_SIMM13, offset)) + // Construct save instruction -#define MK_SAVE(dreg, sreg, imm) \ +#define MK_SAVE_IMM(dreg, sreg, imm) \ (MK_FLD(INSTR_OP, OP_2) | \ MK_FLD(INSTR_RD, dreg) | \ MK_FLD(INSTR_OP3, OP3_SAVE) | \ @@ -453,10 +469,26 @@ MK_FLD(INSTR_I, 1) | \ MK_FLD(INSTR_SIMM13, imm)) -#define MK_RESTORE(dreg, sreg, imm) \ +#define MK_SAVE_REG(dreg, sreg1, sreg2) \ + (MK_FLD(INSTR_OP, OP_2) | \ + MK_FLD(INSTR_RD, dreg) | \ + MK_FLD(INSTR_OP3, OP3_SAVE) | \ + MK_FLD(INSTR_RS1, sreg1) | \ + MK_FLD(INSTR_I, 0) | \ + MK_FLD(INSTR_RS2, sreg2)) + +#define MK_RESTORE_IMM(dreg, sreg, imm) \ (MK_FLD(INSTR_OP, OP_2) | \ MK_FLD(INSTR_RD, dreg) | \ MK_FLD(INSTR_OP3, OP3_RESTORE) | \ + MK_FLD(INSTR_RS1, sreg) | \ + MK_FLD(INSTR_I, 1) | \ + MK_FLD(INSTR_SIMM13, imm)) + +#define MK_JMPL_INDIRECT(dreg, sreg, imm) \ + (MK_FLD(INSTR_OP, OP_2) | \ + MK_FLD(INSTR_RD, dreg) | \ + MK_FLD(INSTR_OP3, OP3_JMPL) | \ MK_FLD(INSTR_RS1, sreg) | \ MK_FLD(INSTR_I, 1) | \ MK_FLD(INSTR_SIMM13, imm)) From jstanley at cs.uiuc.edu Wed May 28 08:54:04 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Wed May 28 08:54:04 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Reoptimizer/TraceCache.h Message-ID: <200305281353.IAA17807@trinity.cs.uiuc.edu> Changes in directory llvm/include/llvm/Reoptimizer: TraceCache.h updated: 1.7 -> 1.8 --- Log message: --- Diffs of the changes: Index: llvm/include/llvm/Reoptimizer/TraceCache.h diff -u llvm/include/llvm/Reoptimizer/TraceCache.h:1.7 llvm/include/llvm/Reoptimizer/TraceCache.h:1.8 --- llvm/include/llvm/Reoptimizer/TraceCache.h:1.7 Fri Apr 4 14:28:23 2003 +++ llvm/include/llvm/Reoptimizer/TraceCache.h Wed May 28 08:53:48 2003 @@ -110,6 +110,9 @@ //remove trace starting with address n void removeTrace(uint64_t n); + MemoryManager* getMemMgr() { return mm; } + VirtualMem* getVM() { return vm; } + VirtualMem *vm; MemoryManager *mm; }; From vadve at cs.uiuc.edu Wed May 28 08:55:00 2003 From: vadve at cs.uiuc.edu (Vikram Adve) Date: Wed May 28 08:55:00 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/LLC/2003-05-27-phifcmpd.ll 2003-05-27-useboolinotherbb.ll 2003-05-27-usefsubasbool.ll Message-ID: <200305281354.IAA18811@psmith.cs.uiuc.edu> Changes in directory llvm/test/Regression/LLC: 2003-05-27-phifcmpd.ll added (r1.1) 2003-05-27-useboolinotherbb.ll added (r1.1) 2003-05-27-usefsubasbool.ll added (r1.1) --- Log message: Three kinds of boolean values handled incorrectly: -- setCC of FP type used by a Phi: have to save in reg. -- setNE of FP type used by a branch: cannot use result directly in branch! -- setCC used outside the same basic block: have to save in reg. for now --- Diffs of the changes: Index: llvm/test/Regression/LLC/2003-05-27-phifcmpd.ll diff -c /dev/null llvm/test/Regression/LLC/2003-05-27-phifcmpd.ll:1.1 *** /dev/null Wed May 28 08:54:51 2003 --- llvm/test/Regression/LLC/2003-05-27-phifcmpd.ll Wed May 28 08:54:41 2003 *************** *** 0 **** --- 1,71 ---- + ;; Date: May 28, 2003. + ;; From: test/Programs/MultiSource/McCat-05-eks/QRfact.c + ;; Function: Matrix QRiterate(Matrix A, Matrix U) + ;; + ;; Error: llc produces an invalid register for the + ;; phi argument %tmp.213 produced by fcmpd: + ;; + ;; LLC Output: + ;; + ;; !****** Outputing Function: QRiterate_1 ****** + ;; + ;; .section ".text" + ;; .align 4 + ;; .global QRiterate_1 + ;; .type QRiterate_1, 2 + ;; QRiterate_1: + ;; .L_QRiterate_1_LL_0: + ;; save %o6, -192, %o6 + ;; brgz %i0, .L_QRiterate_1_LL_1 + ;; add %g0, %g0, %o0 + ;; ba .L_QRiterate_1_LL_2 + ;; nop + ;; + ;; .L_QRiterate_1_LL_1: + ;; sethi %lm(LLVMGlobal__2), %o1 + ;; sethi %hh(LLVMGlobal__2), %o0 + ;; or %o0, %hm(LLVMGlobal__2), %o0 + ;; sllx %o0, 32, %o0 + ;; or %o1, %o0, %o1 + ;; or %o1, %lo(LLVMGlobal__2), %o1 + ;; ldd [%o1+0], %f32 + ;; fcmpd %fcc0, %f2, %f32 + ;; ba .L_QRiterate_1_LL_2 + ;; add , %g0, %o0 + ;; + ;; .L_QRiterate_1_LL_2: + ;; brnz %o0, .L_QRiterate_1_LL_1 + ;; nop + ;; ba .L_QRiterate_1_LL_3 + ;; nop + ;; + ;; .L_QRiterate_1_LL_3: + ;; jmpl %i7+8, %g0 + ;; restore %g0, 0, %g0 + ;; + ;; .EndOf_QRiterate_1: + ;; .size QRiterate_1, .EndOf_QRiterate_1-QRiterate_1 + ;; + + + target endian = big + target pointersize = 64 + + implementation ; Functions: + + internal void %QRiterate(int %p.1, double %tmp.212) { + entry: ; No predecessors! + %tmp.184 = setgt int %p.1, 0 ; [#uses=1] + br bool %tmp.184, label %shortcirc_next.1, label %shortcirc_done.1 + + shortcirc_next.1: ; preds = %entry + %tmp.213 = setne double %tmp.212, 0.000000e+00 + br label %shortcirc_done.1 + + shortcirc_done.1: ; preds = %entry, %shortcirc_next.1 + %val.1 = phi bool [ false, %entry ], [ %tmp.213, %shortcirc_next.1 ] + br bool %val.1, label %shortcirc_next.1, label %exit.1 + + exit.1: + ret void + } Index: llvm/test/Regression/LLC/2003-05-27-useboolinotherbb.ll diff -c /dev/null llvm/test/Regression/LLC/2003-05-27-useboolinotherbb.ll:1.1 *** /dev/null Wed May 28 08:54:51 2003 --- llvm/test/Regression/LLC/2003-05-27-useboolinotherbb.ll Wed May 28 08:54:41 2003 *************** *** 0 **** --- 1,63 ---- + ;; Date: May 27, 2003. + ;; From: Variant of 2003-05-27-usefsubasbool.ll + ;; + ;; Error: llc fails to save a boolean value in a register (and later uses an + ;; invalid register in a BRNZ) for a boolean value + ;; used only by branches but in a different basic block. + ;; + ;; Cause: In SparcInstrSelection.cpp, for SetCC, when a result of setCC + ;; is used only for branches, it is not saved into an int. register. + ;; But if the boolean is used in a branch in a different basic block, + ;; that branch uses a BRNZ inst. instead of a branch-on-CC. + ;; + ;; LLC Output before fix: + ;; !****** Outputing Function: QRiterate_1 ****** + ;; + ;; .section ".text" + ;; .align 4 + ;; .global QRiterate_1 + ;; .type QRiterate_1, 2 + ;; QRiterate_1: + ;; .L_QRiterate_1_LL_0: + ;; save %o6, -192, %o6 + ;; sethi %lm(LLVMGlobal__2), %o2 + ;; sethi %hh(LLVMGlobal__2), %o1 + ;; or %o1, %hm(LLVMGlobal__2), %o1 + ;; sllx %o1, 32, %o1 + ;; or %o2, %o1, %o2 + ;; or %o2, %lo(LLVMGlobal__2), %o2 + ;; ldd [%o2+0], %f32 + ;; fcmpd %fcc0, %f0, %f32 + ;; ba .L_QRiterate_1_LL_1 + ;; nop + ;; + ;; .L_QRiterate_1_LL_1: + ;; brnz , .L_QRiterate_1_LL_1 + ;; nop + ;; ba .L_QRiterate_1_LL_2 + ;; nop + ;; + ;; .L_QRiterate_1_LL_2: + ;; jmpl %i7+8, %g0 + ;; restore %g0, 0, %g0 + ;; + ;; .EndOf_QRiterate_1: + ;; .size QRiterate_1, .EndOf_QRiterate_1-QRiterate_1 + ;; + + target endian = big + target pointersize = 64 + + implementation ; Functions: + + internal void %QRiterate(double %tmp.212) { + entry: ; No predecessors! + %tmp.213 = setne double %tmp.212, 0.000000e+00 + br label %shortcirc_next.1 + + shortcirc_next.1: ; preds = %entry + br bool %tmp.213, label %shortcirc_next.1, label %exit.1 + + exit.1: + ret void + } Index: llvm/test/Regression/LLC/2003-05-27-usefsubasbool.ll diff -c /dev/null llvm/test/Regression/LLC/2003-05-27-usefsubasbool.ll:1.1 *** /dev/null Wed May 28 08:54:51 2003 --- llvm/test/Regression/LLC/2003-05-27-usefsubasbool.ll Wed May 28 08:54:41 2003 *************** *** 0 **** --- 1,63 ---- + ;; Date: May 27, 2003. + ;; From: test/Programs/MultiSource/McCat-05-eks/QRfact.c + ;; Function: Matrix QRiterate(Matrix A, Matrix U) + ;; + ;; Error: llc produces an invalid register for the + ;; a boolean value computed using setne with a double. + ;; + ;; Cause: In SparcInstrSelection.cpp, for SetCC, when a result of setne + ;; is used for a branch, it can generate a "branch-on-integer-register" + ;; for integer registers. In that case, it never saves the value of + ;; the boolean result. It was attempting to do the same thing for an + ;; FP compare! + ;; + ;; LLC Output: + ;; !****** Outputing Function: QRiterate_1 ****** + ;; + ;; .section ".text" + ;; .align 4 + ;; .global QRiterate_1 + ;; .type QRiterate_1, 2 + ;; QRiterate_1: + ;; .L_QRiterate_1_LL_0: + ;; save %o6, -192, %o6 + ;; sethi %hh(LLVMGlobal__2), %o1 + ;; sethi %lm(LLVMGlobal__2), %o0 + ;; or %o1, %hm(LLVMGlobal__2), %o1 + ;; sllx %o1, 32, %o1 + ;; or %o0, %o1, %o0 + ;; or %o0, %lo(LLVMGlobal__2), %o0 + ;; ldd [%o0+0], %f32 + ;; ba .L_QRiterate_1_LL_1 + ;; fcmpd %fcc0, %f0, %f32 + ;; + ;; .L_QRiterate_1_LL_1: + ;; brnz , .L_QRiterate_1_LL_1 + ;; nop + ;; ba .L_QRiterate_1_LL_2 + ;; nop + ;; + ;; .L_QRiterate_1_LL_2: + ;; jmpl %i7+8, %g0 + ;; restore %g0, 0, %g0 + ;; + ;; .EndOf_QRiterate_1: + ;; .size QRiterate_1, .EndOf_QRiterate_1-QRiterate_1 + ;; + + target endian = big + target pointersize = 64 + + implementation ; Functions: + + internal void %QRiterate(double %tmp.212) { + entry: ; No predecessors! + br label %shortcirc_next.1 + + shortcirc_next.1: ; preds = %entry + %tmp.213 = setne double %tmp.212, 0.000000e+00 + br bool %tmp.213, label %shortcirc_next.1, label %exit.1 + + exit.1: + ret void + } From jstanley at cs.uiuc.edu Wed May 28 09:49:05 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Wed May 28 09:49:05 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp Message-ID: <200305281425.JAA19011@trinity.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst/lib/Phase1: Phase1.cpp updated: 1.26.2.1 -> 1.26.2.2 --- Log message: Testing CVS branch checkin. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp diff -u llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp:1.26.2.1 llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp:1.26.2.2 --- llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp:1.26.2.1 Wed May 28 09:21:12 2003 +++ llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp Wed May 28 09:25:21 2003 @@ -54,8 +54,6 @@ bool run(Module& m); private: - // TESTING CVS BRANCHING, JUST IGNORE... - // placeholder pairs holds: glob volatile ptr, glob temporary variable ptr typedef std::pair PlaceholderPair; From jstanley at cs.uiuc.edu Wed May 28 10:00:48 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Wed May 28 10:00:48 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp Message-ID: <200305281421.JAA18697@trinity.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst/lib/Phase1: Phase1.cpp updated: 1.26 -> 1.26.2.1 --- Log message: Testing CVS branch checkin. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp diff -u llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp:1.26 llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp:1.26.2.1 --- llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp:1.26 Thu May 22 22:26:13 2003 +++ llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp Wed May 28 09:21:12 2003 @@ -54,6 +54,8 @@ bool run(Module& m); private: + // TESTING CVS BRANCHING, JUST IGNORE... + // placeholder pairs holds: glob volatile ptr, glob temporary variable ptr typedef std::pair PlaceholderPair; From gaeke at cs.uiuc.edu Wed May 28 12:42:00 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Wed May 28 12:42:00 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/Makefile Message-ID: <200305281741.MAA31693@gally.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: Makefile updated: 1.15 -> 1.16 --- Log message: Add dependency to make TableGen rule fire. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/Makefile diff -u llvm/lib/Target/Sparc/Makefile:1.15 llvm/lib/Target/Sparc/Makefile:1.16 --- llvm/lib/Target/Sparc/Makefile:1.15 Tue May 27 17:04:38 2003 +++ llvm/lib/Target/Sparc/Makefile Wed May 28 12:41:09 2003 @@ -3,6 +3,8 @@ ExtraSource = Debug/Sparc.burm.cpp +SparcV9CodeEmitter.cpp: SparcV9CodeEmitter.inc + SparcV9CodeEmitter.inc: SparcV9.td @echo "TableGen-erating $@" cpp -P SparcV9.td | tblgen -gen-emitter > SparcV9CodeEmitter.inc From brukman at cs.uiuc.edu Wed May 28 12:50:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 28 12:50:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcV9.td Message-ID: <200305281749.MAA14126@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcV9.td updated: 1.2 -> 1.3 --- Log message: Fixed ordering of elements in instructions: although the binary instructions list (rd, rs1, imm), in that order (bit-wise), the actual assembly syntax is instr rd, imm, rs1, and that is how they are constructed in the instruction selector. This fixes the discrepancy. Also fixed some comments along the same lines and fixed page numbers referring to where instructions are described in the Sparc manual. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/SparcV9.td diff -u llvm/lib/Target/Sparc/SparcV9.td:1.2 llvm/lib/Target/Sparc/SparcV9.td:1.3 --- llvm/lib/Target/Sparc/SparcV9.td:1.2 Tue May 27 15:03:29 2003 +++ llvm/lib/Target/Sparc/SparcV9.td Wed May 28 12:49:29 2003 @@ -140,32 +140,59 @@ set Inst{24-19} = op3; } -// F3_rs1 - Common superclass of instructions that use rs1 -class F3_rs1 : F3 { +class F3_rd : F3 { + bits<5> rd; + set Inst{29-25} = rd; +} + +class F3_rdsimm13 : F3_rd { + bits<13> simm13; + set Inst{12-0} = simm13; +} + +class F3_rdsimm13rs1 : F3_rdsimm13 { bits<5> rs1; set Inst{18-14} = rs1; } -// F3_rs1rd - Common superclass of instructions that use rs1 & rd... -class F3_rs1rd : F3 { - // Added rs1 here manually to have rd appear before rs1 - // Formerly inherited directly from F3_rs1 - bits<5> rd; +// F3_rdrs1 - Common superclass of instructions that use rd & rs1 +class F3_rdrs1 : F3_rd { bits<5> rs1; - set Inst{29-25} = rd; set Inst{18-14} = rs1; } -// F3_rs1rdrs2 - Common superclass of instructions with rs1, rd, & rs2 fields -class F3_rs1rdrs2 : F3_rs1rd { +// F3_rs1rdrs2 - Common superclass of instructions with rd, rs1, & rs2 fields +class F3_rdrs1rs2 : F3_rdrs1 { + bits<5> rs2; + set Inst{4-0} = rs2; +} + +// F3_rs1 - Common class of instructions that do not have an rd field, +// but start at rs1 +class F3_rs1 : F3 { + bits<5> rs1; + //set Inst{29-25} = dontcare; + set Inst{18-14} = rs1; +} + +// F3_rs1rs2 - Common class of instructions that only have rs1 and rs2 fields +class F3_rs1rs2 : F3_rs1 { bits<5> rs2; + //set Inst{12-5} = dontcare; set Inst{4-0} = rs2; } +// F3_rs1rs2 - Common class of instructions that only have rs1 and rs2 fields +class F3_rs1simm13 : F3_rs1 { + bits<13> simm13; + set Inst{12-0} = simm13; +} + + // Specific F3 classes... // -class F3_1 opVal, bits<6> op3val, string name> : F3_rs1rdrs2 { +class F3_1 opVal, bits<6> op3val, string name> : F3_rdrs1rs2 { set op = opVal; set op3 = op3val; set Name = name; @@ -173,28 +200,21 @@ //set Inst{12-5} = dontcare; } -class F3_2 opVal, bits<6> op3val, string name> : F3_rs1rd { - bits<13> simm; - +class F3_2 opVal, bits<6> op3val, string name> : F3_rdsimm13rs1 { set op = opVal; set op3 = op3val; set Name = name; set Inst{13} = 1; // i field = 1 - set Inst{12-0} = simm; } -class F3_3 opVal, bits<6> op3val, string name> : F3_rs1 { - bits<5> rs2; +class F3_3 opVal, bits<6> op3val, string name> : F3_rs1rs2 { set op = opVal; set op3 = op3val; set Name = name; - //set Inst{29-25} = dontcare; set Inst{13} = 0; - //set Inst{12-5} = dontcare; - set Inst{4-0} = rs2; } -class F3_4 opVal, bits<6> op3Val, string name> : F3_rs1 { +class F3_4 opVal, bits<6> op3Val, string name> : F3_rs1simm13 { bits<13> simm; set op = opVal; set op3 = op3Val; @@ -204,7 +224,7 @@ set Inst{12-0} = simm; } -class F3_11 opVal, bits<6> op3Val, string name> : F3_rs1rdrs2 { +class F3_11 opVal, bits<6> op3Val, string name> : F3_rdrs1rs2 { bit x; set op = opVal; set op3 = op3Val; @@ -235,7 +255,7 @@ } class F3_14 opVal, bits<6> op3val, - bits<9> opfval, string name> : F3_rs1rdrs2 { + bits<9> opfval, string name> : F3_rdrs1rs2 { set op = opVal; set op3 = op3val; set Name = name; @@ -244,7 +264,7 @@ } class F3_16 opVal, bits<6> op3val, - bits<9> opfval, string name> : F3_rs1rdrs2 { + bits<9> opfval, string name> : F3_rdrs1rs2 { set op = opVal; set op3 = op3val; set Name = name; @@ -263,17 +283,17 @@ // Instruction list... // -// Section A.2: p161 +// Section A.2: Add - p137 def ADDr : F3_1<2, 0b000000, "add">; // add r, r, r -def ADDi : F3_2<2, 0b000000, "add">; // add r, r, i +def ADDi : F3_2<2, 0b000000, "add">; // add r, i, r def ADDccr : F3_1<2, 0b010000, "addcc">; // addcc r, r, r -def ADDcci : F3_2<2, 0b010000, "addcc">; // addcc r, r, i +def ADDcci : F3_2<2, 0b010000, "addcc">; // addcc r, i, r def ADDCr : F3_1<2, 0b001000, "addC">; // addC r, r, r -def ADDCi : F3_2<2, 0b001000, "addC">; // addC r, r, i +def ADDCi : F3_2<2, 0b001000, "addC">; // addC r, i, r def ADDCccr : F3_1<2, 0b011000, "addCcc">; // addCcc r, r, r -def ADDCcci : F3_2<2, 0b011000, "addCcc">; // addCcc r, r, i +def ADDCcci : F3_2<2, 0b011000, "addCcc">; // addCcc r, i, r -// Section A.3: p162 +// Section A.3: Branch on Integer Register with Prediction - p162 set op2 = 0b011 in { def BRZ : F2_4<0b001, "brz">; // Branch on rs1 == 0 def BRLEZ : F2_4<0b010, "brlez">; // Branch on rs1 <= 0 From brukman at cs.uiuc.edu Wed May 28 13:28:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 28 13:28:01 2003 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/MachineCodeEmitter.cpp Message-ID: <200305281827.NAA14581@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: MachineCodeEmitter.cpp updated: 1.6 -> 1.7 --- Log message: Correctly write out binary data as chars, before they're cast to ints. --- Diffs of the changes: Index: llvm/lib/CodeGen/MachineCodeEmitter.cpp diff -u llvm/lib/CodeGen/MachineCodeEmitter.cpp:1.6 llvm/lib/CodeGen/MachineCodeEmitter.cpp:1.7 --- llvm/lib/CodeGen/MachineCodeEmitter.cpp:1.6 Tue May 27 17:43:19 2003 +++ llvm/lib/CodeGen/MachineCodeEmitter.cpp Wed May 28 13:27:19 2003 @@ -129,6 +129,7 @@ void emitByte(unsigned char B) { if (MCE) MCE->emitByte(B); + actual << B; actual.flush(); values[counter] = (unsigned int) B; if (++counter % 4 == 0 && counter != 0) { @@ -136,9 +137,7 @@ for (unsigned i=0; i<4; ++i) { if (values[i] < 16) o << "0"; o << values[i] << " "; - actual << values[i]; } - actual.flush(); o << std::dec << "\t"; for (unsigned i=0; i<4; ++i) { From brukman at cs.uiuc.edu Wed May 28 13:30:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 28 13:30:01 2003 Subject: [llvm-commits] CVS: llvm/utils/TableGen/CodeEmitterGen.cpp Message-ID: <200305281829.NAA14625@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: CodeEmitterGen.cpp updated: 1.3 -> 1.4 --- Log message: Output the opcode name of the instruction being emitted to cerr. --- Diffs of the changes: Index: llvm/utils/TableGen/CodeEmitterGen.cpp diff -u llvm/utils/TableGen/CodeEmitterGen.cpp:1.3 llvm/utils/TableGen/CodeEmitterGen.cpp:1.4 --- llvm/utils/TableGen/CodeEmitterGen.cpp:1.3 Tue May 27 17:29:02 2003 +++ llvm/utils/TableGen/CodeEmitterGen.cpp Wed May 28 13:29:10 2003 @@ -27,7 +27,8 @@ I != E; ++I) { Record *R = *I; - o << " case " << Namespace << R->getName() << ": {\n"; + o << " case " << Namespace << R->getName() << ": {\n" + << " std::cerr << \"Emitting " << R->getName() << "\\n\";\n"; const RecordVal *InstVal = R->getValue("Inst"); Init *InitVal = InstVal->getValue(); @@ -49,9 +50,9 @@ o << "0"; } } - o << "\n\n"; + o << "\n"; - o << " // " << *InstVal << "\n\n"; + o << " // " << *InstVal << "\n"; o << " Value = " << Value << "U;\n\n"; // Loop over all of the fields in the instruction adding in any From brukman at cs.uiuc.edu Wed May 28 13:45:02 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 28 13:45:02 2003 Subject: [llvm-commits] CVS: llvm/tools/lli/JIT/SparcEmitter.cpp Message-ID: <200305281844.NAA15255@zion.cs.uiuc.edu> Changes in directory llvm/tools/lli/JIT: SparcEmitter.cpp updated: 1.1 -> 1.2 --- Log message: mmap() seems to be failing on Sparc, so just use malloc()/free() . --- Diffs of the changes: Index: llvm/tools/lli/JIT/SparcEmitter.cpp diff -u llvm/tools/lli/JIT/SparcEmitter.cpp:1.1 llvm/tools/lli/JIT/SparcEmitter.cpp:1.2 --- llvm/tools/lli/JIT/SparcEmitter.cpp:1.1 Tue May 27 16:40:39 2003 +++ llvm/tools/lli/JIT/SparcEmitter.cpp Wed May 28 13:44:38 2003 @@ -32,8 +32,16 @@ std::pair > > BBRefs; std::map BBLocations; std::vector ConstantPoolAddresses; + std::vector funcMemory; public: SparcEmitter(VM &vm) : TheVM(vm) {} + ~SparcEmitter() { + while (! funcMemory.empty()) { + void* addr = funcMemory.back(); + free(addr); + funcMemory.pop_back(); + } + } virtual void startFunction(MachineFunction &F); virtual void finishFunction(MachineFunction &F); @@ -49,9 +57,11 @@ int Offset); virtual void saveBBreference(BasicBlock *BB, MachineInstr &MI); + private: void emitAddress(void *Addr, bool isPCRelative); + void* getMemory(unsigned NumPages); }; } @@ -66,22 +76,36 @@ // FIXME: This should be rewritten to support a real memory manager for // executable memory pages! -static void *getMemory(unsigned NumPages) { - return mmap(0, 4096*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC, - MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); +void * SparcEmitter::getMemory(unsigned NumPages) { +#if 0 + void *pa = mmap(0, 4096*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); + if (pa == MAP_FAILED) { + perror("mmap"); + abort(); + } +#endif + void *pa = malloc(4096*NumPages); + if (!pa) { + perror("malloc"); + abort(); + } + funcMemory.push_back(pa); + return pa; } void SparcEmitter::startFunction(MachineFunction &F) { CurBlock = (unsigned char *)getMemory(8); + std::cerr << "Starting function " << F.getFunction()->getName() << "\n"; CurByte = CurBlock; // Start writing at the beginning of the fn. TheVM.addGlobalMapping(F.getFunction(), CurBlock); } void SparcEmitter::finishFunction(MachineFunction &F) { ConstantPoolAddresses.clear(); + // Re-write branches to BasicBlocks for the entire function for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) { - // Re-write branches to BasicBlocks for the entire function unsigned Location = BBLocations[BBRefs[i].first]; unsigned *Ref = BBRefs[i].second.first; MachineInstr *MI = BBRefs[i].second.second; @@ -149,6 +173,7 @@ // BasicBlock -> pair // when the BB is emitted, machineinstr is modified with then-currbyte, // processed with MCE, and written out at memloc. +// Should be called by the emitter if its outputting a PCRelative disp void SparcEmitter::saveBBreference(BasicBlock *BB, MachineInstr &MI) { BBRefs.push_back(std::make_pair(BB, std::make_pair((unsigned*)CurByte, &MI))); } From brukman at cs.uiuc.edu Wed May 28 22:32:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 28 22:32:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcV9_F2.td SparcV9_F3.td SparcV9_F4.td SparcV9_Reg.td SparcV9.td Message-ID: <200305290331.WAA23025@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcV9_F2.td added (r1.1) SparcV9_F3.td added (r1.1) SparcV9_F4.td added (r1.1) SparcV9_Reg.td added (r1.1) SparcV9.td updated: 1.3 -> 1.4 --- Log message: * Broke up SparcV9.td into separate files as it was getting unmanageable * Added some Format 4 classes, but not instructions * Added notes on missing sections with FIXMEs * Added RDCCR instr --- Diffs of the changes: Index: llvm/lib/Target/Sparc/SparcV9_F2.td diff -c /dev/null llvm/lib/Target/Sparc/SparcV9_F2.td:1.1 *** /dev/null Wed May 28 22:31:53 2003 --- llvm/lib/Target/Sparc/SparcV9_F2.td Wed May 28 22:31:43 2003 *************** *** 0 **** --- 1,64 ---- + //===- Sparc.td - Target Description for Sparc V9 Target --------*- C++ -*-===// + // vim:ft=cpp + //===----------------------------------------------------------------------===// + + //===----------------------------------------------------------------------===// + // Format #2 classes + // + class F2 : InstV9 { // Format 2 instructions + bits<3> op2; + set op = 0; // Op = 0 + set Inst{24-22} = op2; + } + + // Format 2.1 instructions + class F2_1 : F2 { + bits<5> rd; + bits<22> imm; + + set Name = name; + set Inst{29-25} = rd; + set Inst{21-0} = imm; + } + + class F2_br : F2 { // Format 2 Branch instruction + bit annul; // All branches have an annul bit + set Inst{29} = annul; + set isBranch = 1; // All instances are branch instructions + } + + class F2_2 cond, string name> : F2_br { // Format 2.2 instructions + bits<22> disp; + + set Name = name; + set Inst{28-25} = cond; + set Inst{21-0} = disp; + } + + class F2_3 cond, string name> : F2_br { // Format 2.3 instructions + bits<2> cc; + bits<19> disp; + bit predict; + + set Name = name; + set Inst{28-25} = cond; + set Inst{21-20} = cc; + set Inst{19} = predict; + set Inst{18-0} = disp; + } + + class F2_4 rcond, string name> : F2_br { // Format 2.4 instructions + // Variables exposed by the instruction... + bit predict; + bits<5> rs1; + bits<16> disp; + + set Name = name; + set Inst{28} = 0; + set Inst{27-25} = rcond; + // Inst{24-22} = op2 field + set Inst{21-20} = disp{15-14}; + set Inst{19} = predict; + set Inst{18-14} = rs1; + set Inst{13-0 } = disp{13-0}; + } Index: llvm/lib/Target/Sparc/SparcV9_F3.td diff -c /dev/null llvm/lib/Target/Sparc/SparcV9_F3.td:1.1 *** /dev/null Wed May 28 22:31:53 2003 --- llvm/lib/Target/Sparc/SparcV9_F3.td Wed May 28 22:31:43 2003 *************** *** 0 **** --- 1,171 ---- + //===- Sparc.td - Target Description for Sparc V9 Target --------*- C++ -*-===// + // vim:ft=cpp + //===----------------------------------------------------------------------===// + + //===----------------------------------------------------------------------===// + // Format #3 classes + // + + // F3 - Common superclass of all F3 instructions. All instructions have an op3 + // field. + class F3 : InstV9 { + bits<6> op3; + set op{1} = 1; // Op = 2 or 3 + set Inst{24-19} = op3; + } + + class F3_rd : F3 { + bits<5> rd; + set Inst{29-25} = rd; + } + + class F3_rdsimm13 : F3_rd { + bits<13> simm13; + set Inst{12-0} = simm13; + } + + class F3_rdsimm13rs1 : F3_rdsimm13 { + bits<5> rs1; + set Inst{18-14} = rs1; + } + + // F3_rdrs1 - Common superclass of instructions that use rd & rs1 + class F3_rdrs1 : F3_rd { + bits<5> rs1; + set Inst{18-14} = rs1; + } + + // F3_rs1rdrs2 - Common superclass of instructions with rd, rs1, & rs2 fields + class F3_rdrs1rs2 : F3_rdrs1 { + bits<5> rs2; + set Inst{4-0} = rs2; + } + + // F3_rs1 - Common class of instructions that do not have an rd field, + // but start at rs1 + class F3_rs1 : F3 { + bits<5> rs1; + //set Inst{29-25} = dontcare; + set Inst{18-14} = rs1; + } + + // F3_rs1rs2 - Common class of instructions that only have rs1 and rs2 fields + class F3_rs1rs2 : F3_rs1 { + bits<5> rs2; + //set Inst{12-5} = dontcare; + set Inst{4-0} = rs2; + } + + // F3_rs1simm13 - Common class of instructions that only have rs1 and simm13 + class F3_rs1simm13 : F3_rs1 { + bits<13> simm13; + set Inst{12-0} = simm13; + } + + + // Specific F3 classes... + // + + class F3_1 opVal, bits<6> op3val, string name> : F3_rdrs1rs2 { + set op = opVal; + set op3 = op3val; + set Name = name; + set Inst{13} = 0; // i field = 0 + //set Inst{12-5} = dontcare; + } + + class F3_2 opVal, bits<6> op3val, string name> : F3_rdsimm13rs1 { + set op = opVal; + set op3 = op3val; + set Name = name; + set Inst{13} = 1; // i field = 1 + } + + class F3_3 opVal, bits<6> op3val, string name> : F3_rs1rs2 { + set op = opVal; + set op3 = op3val; + set Name = name; + set Inst{13} = 0; + } + + class F3_4 opVal, bits<6> op3Val, string name> : F3_rs1simm13 { + bits<13> simm; + set op = opVal; + set op3 = op3Val; + set Name = name; + //set Inst{29-25} = dontcare; + set Inst{13} = 1; + set Inst{12-0} = simm; + } + + class F3_11 opVal, bits<6> op3Val, string name> : F3_rdrs1rs2 { + bit x; + set op = opVal; + set op3 = op3Val; + set Name = name; + set Inst{13} = 0; // i field = 0 + set Inst{12} = x; + //set Inst{11-5} = dontcare; + } + + class F3_12 opVal, bits<6> op3Val, string name> : F3 { + bits<5> shcnt; + + set Name = name; + set Inst{13} = 1; // i field = 1 + set Inst{12} = 0; // x field = 0 + //set Inst{11-5} = dontcare; + set Inst{4-0} = shcnt; + } + + class F3_13 opVal, bits<6> op3Val, string name> : F3 { + bits<6> shcnt; + + set Name = name; + set Inst{13} = 1; // i field = 1 + set Inst{12} = 1; // x field = 1 + //set Inst{11-6} = dontcare; + set Inst{5-0} = shcnt; + } + + class F3_14 opVal, bits<6> op3Val, + bits<9> opfval, string name> : F3_rdrs1rs2 { + set op = opVal; + set op3 = op3Val; + set Name = name; + //set Inst{18-14} = dontcare; + set Inst{13-5} = opfval; + } + + class F3_16 opVal, bits<6> op3Val, + bits<9> opfval, string name> : F3_rdrs1rs2 { + set op = opVal; + set op3 = op3Val; + set Name = name; + set Inst{13-5} = opfval; + } + + class F3_17 opVal, bits<6> op3Val, string name> : F3_rdrs1 { + set op = opVal; + set op3 = op3Val; + set Name = name; + //Inst{13-0} = dontcare; + } + + class F3_18 fcn, string name> : F3 { + set op = 2; + set op3 = 0b111110; + set Name = name; + set Inst{29-25} = fcn; + //set Inst{18-0 } = dontcare; + } + + class F3_19 opVal, bits<6> op3Val, string name> : F3_rd { + set op = opVal; + set op3 = op3Val; + set Name = name; + //Inst{18-0} = dontcare; + } + + // FIXME: class F3_20 + // FIXME: class F3_21 Index: llvm/lib/Target/Sparc/SparcV9_F4.td diff -c /dev/null llvm/lib/Target/Sparc/SparcV9_F4.td:1.1 *** /dev/null Wed May 28 22:31:53 2003 --- llvm/lib/Target/Sparc/SparcV9_F4.td Wed May 28 22:31:43 2003 *************** *** 0 **** --- 1,90 ---- + //===- Sparc.td - Target Description for Sparc V9 Target --------*- C++ -*-===// + // vim:ft=cpp + //===----------------------------------------------------------------------===// + + //----------------------- F4 classes ----------------------------------------- + + // F4 - Common superclass of all F4 instructions. All instructions have an op3 + // field. + class F4 : InstV9 { + bits<6> op3; + set Inst{24-19} = op3; + } + + class F4_rd : F4 { + bits<5> rd; + set Inst{29-25} = rd; + } + + class F4_rdsimm11 : F4_rd { + bits<11> simm11; + set Inst{10-0} = simm11; + } + + class F4_rdsimm11rs1 : F4_rdsimm11 { + bits<5> rs1; + set Inst{18-14} = rs1; + } + + // F4_rdrs1 - Common superclass of instructions that use rd & rs1 + class F4_rdrs1 : F4_rd { + bits<5> rs1; + set Inst{18-14} = rs1; + } + + // F4_rs1rdrs2 - Common superclass of instructions with rd, rs1, & rs2 fields + class F4_rdrs1rs2 : F4_rdrs1 { + bits<5> rs2; + set Inst{4-0} = rs2; + } + + // F4_rs1 - Common class of instructions that do not have an rd field, + // but start at rs1 + class F4_rs1 : F4 { + bits<5> rs1; + //set Inst{29-25} = dontcare; + set Inst{18-14} = rs1; + } + + // F4_rs1rs2 - Common class of instructions that only have rs1 and rs2 fields + class F4_rs1rs2 : F4_rs1 { + bits<5> rs2; + //set Inst{12-5} = dontcare; + set Inst{4-0} = rs2; + } + + // Actual F4 instruction classes + + class F4_1 opVal, bits<6> op3Val, string name> : F4_rdrs1rs2 { + bits<2> cc; + + set op = opVal; + set op3 = op3Val; + set Name = name; + set Inst{13} = 0; // i bit + set Inst{12-11} = cc; + //set Inst{10-5} = dontcare; + } + + class F4_2 opVal, bits<6> op3Val, string name> : F4_rdsimm11rs1 { + bits<2> cc; + + set op = opVal; + set op3 = op3Val; + set Name = name; + set Inst{13} = 1; // i bit + set Inst{12-11} = cc; + } + + class F4_3 opVal, bits<6> op3Val, string name> : F3_rd { + bits<5> rs2; + bits<2> cc; + + set op = opVal; + set op3 = op3Val; + set Name = name; + set Inst{13} = 0; // i bit + set Inst{12-11} = cc; + //set Inst{10-5} = dontcare; + set Inst{4-0} = rs2; + } Index: llvm/lib/Target/Sparc/SparcV9_Reg.td diff -c /dev/null llvm/lib/Target/Sparc/SparcV9_Reg.td:1.1 *** /dev/null Wed May 28 22:31:53 2003 --- llvm/lib/Target/Sparc/SparcV9_Reg.td Wed May 28 22:31:43 2003 *************** *** 0 **** --- 1,23 ---- + //===- Sparc.td - Target Description for Sparc V9 Target --------*- C++ -*-===// + // vim:ft=cpp + //===----------------------------------------------------------------------===// + + //===----------------------------------------------------------------------===// + // Declarations that describe the Sparc register file + //===----------------------------------------------------------------------===// + + class V9Reg : Register { set Namespace = "SparcV9"; } + + // Ri - One of the 32 64 bit integer registers + class Ri num> : V9Reg { set Size = 64; field bits<5> Num = num; } + + def G0 : Ri< 0>; def G1 : Ri< 1>; def G2 : Ri< 2>; def G3 : Ri< 3>; + def G4 : Ri< 4>; def G5 : Ri< 5>; def G6 : Ri< 6>; def G7 : Ri< 7>; + def O0 : Ri< 8>; def O1 : Ri< 9>; def O2 : Ri<10>; def O3 : Ri<11>; + def O4 : Ri<12>; def O5 : Ri<13>; def O6 : Ri<14>; def O7 : Ri<15>; + def L0 : Ri<16>; def L1 : Ri<17>; def L2 : Ri<18>; def L3 : Ri<19>; + def L4 : Ri<20>; def L5 : Ri<21>; def L6 : Ri<22>; def L7 : Ri<23>; + def I0 : Ri<24>; def I1 : Ri<25>; def I2 : Ri<26>; def I3 : Ri<27>; + def I4 : Ri<28>; def I5 : Ri<29>; def I6 : Ri<30>; def I7 : Ri<31>; + // Floating-point registers? + // ... Index: llvm/lib/Target/Sparc/SparcV9.td diff -u llvm/lib/Target/Sparc/SparcV9.td:1.3 llvm/lib/Target/Sparc/SparcV9.td:1.4 --- llvm/lib/Target/Sparc/SparcV9.td:1.3 Wed May 28 12:49:29 2003 +++ llvm/lib/Target/Sparc/SparcV9.td Wed May 28 22:31:43 2003 @@ -2,53 +2,12 @@ // vim:ft=cpp //===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// -// Target-Independent interface -//===----------------------------------------------------------------------===// - -class Register { - string Namespace = ""; - int Size; -} - -class Instruction { - string Name; // The opcode string for this instruction - string Namespace = ""; - - list Uses = []; // Default to using no non-operand registers - list Defs = []; // Default to modifying no non-operand registers - - // These bits capture information about the high-level semantics of the - // instruction. - bit isReturn = 0; // Is this instruction a return instruction? - bit isBranch = 0; // Is this instruction a branch instruction? - bit isCall = 0; // Is this instruction a call instruction? -} +#include "../Target.td" +#include "SparcV9_Reg.td" //===----------------------------------------------------------------------===// -// Declarations that describe the Sparc register file -//===----------------------------------------------------------------------===// - -class V9Reg : Register { set Namespace = "SparcV9"; } - -// Ri - One of the 32 64 bit integer registers -class Ri num> : V9Reg { set Size = 64; field bits<5> Num = num; } - -def G0 : Ri< 0>; def G1 : Ri< 1>; def G2 : Ri< 2>; def G3 : Ri< 3>; -def G4 : Ri< 4>; def G5 : Ri< 5>; def G6 : Ri< 6>; def G7 : Ri< 7>; -def O0 : Ri< 8>; def O1 : Ri< 9>; def O2 : Ri<10>; def O3 : Ri<11>; -def O4 : Ri<12>; def O5 : Ri<13>; def O6 : Ri<14>; def O7 : Ri<15>; -def L0 : Ri<16>; def L1 : Ri<17>; def L2 : Ri<18>; def L3 : Ri<19>; -def L4 : Ri<20>; def L5 : Ri<21>; def L6 : Ri<22>; def L7 : Ri<23>; -def I0 : Ri<24>; def I1 : Ri<25>; def I2 : Ri<26>; def I3 : Ri<27>; -def I4 : Ri<28>; def I5 : Ri<29>; def I6 : Ri<30>; def I7 : Ri<31>; -// Floating-point registers? -// ... - - -//===----------------------------------------------------------------------===// -// This is temporary testing stuff..... +// Instructions //===----------------------------------------------------------------------===// class InstV9 : Instruction { // Sparc instruction baseline @@ -65,219 +24,9 @@ bit isPrivileged = 0; // Is this a privileged instruction? } - -//===----------------------------------------------------------------------===// -// Format #2 classes -// -class F2 : InstV9 { // Format 2 instructions - bits<3> op2; - set op = 0; // Op = 0 - set Inst{24-22} = op2; -} - -// Format 2.1 instructions -class F2_1 : F2 { - bits<5> rd; - bits<22> imm; - - set Name = name; - set Inst{29-25} = rd; - set Inst{21-0} = imm; -} - -class F2_br : F2 { // Format 2 Branch instruction - bit annul; // All branches have an annul bit - set Inst{29} = annul; - set isBranch = 1; // All instances are branch instructions -} - -class F2_2 cond, string name> : F2_br { // Format 2.2 instructions - bits<22> disp; - - set Name = name; - set Inst{28-25} = cond; - set Inst{21-0} = disp; -} - -class F2_3 cond, string name> : F2_br { // Format 2.3 instructions - bits<2> cc; - bits<19> disp; - bit predict; - - set Name = name; - set Inst{28-25} = cond; - set Inst{21-20} = cc; - set Inst{19} = predict; - set Inst{18-0} = disp; -} - -class F2_4 rcond, string name> : F2_br { // Format 2.4 instructions - // Variables exposed by the instruction... - bit predict; - bits<5> rs1; - bits<16> disp; - - set Name = name; - set Inst{28} = 0; - set Inst{27-25} = rcond; - // Inst{24-22} = op2 field - set Inst{21-20} = disp{15-14}; - set Inst{19} = predict; - set Inst{18-14} = rs1; - set Inst{13-0 } = disp{13-0}; -} - - -//===----------------------------------------------------------------------===// -// Format #3 classes -// - -// F3 - Common superclass of all F3 instructions. All instructions have an op3 -// field. -class F3 : InstV9 { - bits<6> op3; - set op{1} = 1; // Op = 2 or 3 - set Inst{24-19} = op3; -} - -class F3_rd : F3 { - bits<5> rd; - set Inst{29-25} = rd; -} - -class F3_rdsimm13 : F3_rd { - bits<13> simm13; - set Inst{12-0} = simm13; -} - -class F3_rdsimm13rs1 : F3_rdsimm13 { - bits<5> rs1; - set Inst{18-14} = rs1; -} - -// F3_rdrs1 - Common superclass of instructions that use rd & rs1 -class F3_rdrs1 : F3_rd { - bits<5> rs1; - set Inst{18-14} = rs1; -} - -// F3_rs1rdrs2 - Common superclass of instructions with rd, rs1, & rs2 fields -class F3_rdrs1rs2 : F3_rdrs1 { - bits<5> rs2; - set Inst{4-0} = rs2; -} - -// F3_rs1 - Common class of instructions that do not have an rd field, -// but start at rs1 -class F3_rs1 : F3 { - bits<5> rs1; - //set Inst{29-25} = dontcare; - set Inst{18-14} = rs1; -} - -// F3_rs1rs2 - Common class of instructions that only have rs1 and rs2 fields -class F3_rs1rs2 : F3_rs1 { - bits<5> rs2; - //set Inst{12-5} = dontcare; - set Inst{4-0} = rs2; -} - -// F3_rs1rs2 - Common class of instructions that only have rs1 and rs2 fields -class F3_rs1simm13 : F3_rs1 { - bits<13> simm13; - set Inst{12-0} = simm13; -} - - -// Specific F3 classes... -// - -class F3_1 opVal, bits<6> op3val, string name> : F3_rdrs1rs2 { - set op = opVal; - set op3 = op3val; - set Name = name; - set Inst{13} = 0; // i field = 0 - //set Inst{12-5} = dontcare; -} - -class F3_2 opVal, bits<6> op3val, string name> : F3_rdsimm13rs1 { - set op = opVal; - set op3 = op3val; - set Name = name; - set Inst{13} = 1; // i field = 1 -} - -class F3_3 opVal, bits<6> op3val, string name> : F3_rs1rs2 { - set op = opVal; - set op3 = op3val; - set Name = name; - set Inst{13} = 0; -} - -class F3_4 opVal, bits<6> op3Val, string name> : F3_rs1simm13 { - bits<13> simm; - set op = opVal; - set op3 = op3Val; - set Name = name; - //set Inst{29-25} = dontcare; - set Inst{13} = 1; - set Inst{12-0} = simm; -} - -class F3_11 opVal, bits<6> op3Val, string name> : F3_rdrs1rs2 { - bit x; - set op = opVal; - set op3 = op3Val; - set Name = name; - set Inst{13} = 0; // i field = 0 - set Inst{12} = x; - //set Inst{11-5} = dontcare; -} - -class F3_12 opVal, bits<6> op3Val, string name> : F3 { - bits<5> shcnt; - - set Name = name; - set Inst{13} = 1; // i field = 1 - set Inst{12} = 0; // x field = 0 - //set Inst{11-5} = dontcare; - set Inst{4-0} = shcnt; -} - -class F3_13 opVal, bits<6> op3Val, string name> : F3 { - bits<6> shcnt; - - set Name = name; - set Inst{13} = 1; // i field = 1 - set Inst{12} = 1; // x field = 1 - //set Inst{11-6} = dontcare; - set Inst{5-0} = shcnt; -} - -class F3_14 opVal, bits<6> op3val, - bits<9> opfval, string name> : F3_rdrs1rs2 { - set op = opVal; - set op3 = op3val; - set Name = name; - //set Inst{18-14} = dontcare; - set Inst{13-5} = opfval; -} - -class F3_16 opVal, bits<6> op3val, - bits<9> opfval, string name> : F3_rdrs1rs2 { - set op = opVal; - set op3 = op3val; - set Name = name; - set Inst{13-5} = opfval; -} - -class F3_18 fcn, string name> : F3 { - set op = 2; - set op3 = 0b111110; - set Name = name; - set Inst{29-25} = fcn; - //set Inst{18-0 } = dontcare; -} +#include "SparcV9_F2.td" +#include "SparcV9_F3.td" +#include "SparcV9_F4.td" //===----------------------------------------------------------------------===// // Instruction list... @@ -570,6 +319,12 @@ def FMOVFO : F4_7<2, 0b110101, 0b1111, "fmovfo">; // fmovfo r, r #endif +// Section A.34: Move F-P Register on Integer Register (FMOVr) + +// Section A.35: Move Integer Register on Condition (MOVcc) + +// Section A.36: Move Integer Register on Register Condition (MOVR) + // Section A.37: Multiply and Divide (64-bit) - p199 def MULXr : F3_1<2, 0b001001, "mulx">; // mulx r, r, r def SDIVXr : F3_1<2, 0b101101, "sdivx">; // mulx r, r, r @@ -593,6 +348,8 @@ // def SMULCCi : F3_1<2, 0b011011, "smulcc">; // smulcc r, i, r //} +// Section A.39: FIXME + // Section A.40: No operation - p204 // NOP is really a pseudo-instruction (special case of SETHI) set op2 = 0b100 in { @@ -603,6 +360,16 @@ } } +// Section A.41: FIXME +// Section A.42: FIXME +// Section A.43: FIXME + +// Section A.44: Read State Register +// The only instr from this section currently used is RDCCR +set rs1 = 2 in { + def RDCCR : F3_17<2, 0b101000, "rd">; // rd %ccr, r +} + // Section A.45: RETURN - p216 set isReturn = 1 in { def RETURNr : F3_3<2, 0b111001, "return">; // return @@ -616,7 +383,7 @@ def RESTOREi : F3_2<2, 0b111101, "restore">; // restore r, i, r // Section A.47: SAVED and RESTORED - p219 -// FIXME: add these instrs +// Not currently used in Sparc backend // Section A.48: SETHI - p220 set op2 = 0b100 in { @@ -657,6 +424,9 @@ def SRLXi6 : F3_13<2, 0b100110, "srlx">; // srlx r, shcnt64, r def SRAXi6 : F3_13<2, 0b100111, "srax">; // srax r, shcnt64, r +// Section A.50: FIXME +// Section A.51: FIXME + // Section A.52: Store Floating-point -p225 def STFr : F3_1<3, 0b100100, "st">; // st r, [r+r] def STFi : F3_2<3, 0b100100, "st">; // st r, [r+i] @@ -672,6 +442,8 @@ def STXFSRr : F3_1<3, 0b100101, "stq">; // stx r, [r+r] def STXFSRi : F3_2<3, 0b100101, "stq">; // stx r, [r+i] +// Section A.53: FIXME + // Section A.54: Store Integer - p229 def STBr : F3_1<3, 0b000101, "stb">; // stb r, [r+r] def STBi : F3_2<3, 0b000101, "stb">; // stb r, [r+i] @@ -683,6 +455,7 @@ def STXi : F3_2<3, 0b001110, "stb">; // stb r, [r+i] // Floating point store... +// Section A.55: FIXME // Section A.56: Subtract - p233 def SUBr : F3_1<2, 0b000100, "sub">; // sub r, r, r @@ -693,3 +466,5 @@ def SUBCi : F3_1<2, 0b001100, "subc">; // subc r, i, r def SUBCccr : F3_1<2, 0b011100, "subccc">; // subccc r, r, r def SUBCcci : F3_1<2, 0b011100, "subccc">; // subccc r, i, r + +// FIXME: More...? From brukman at cs.uiuc.edu Wed May 28 22:33:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 28 22:33:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/Makefile Message-ID: <200305290332.WAA23043@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: Makefile updated: 1.16 -> 1.17 --- Log message: This should work better with re-generating the SparcV9CodeEmitter.inc file. Also, added a rule to delete the generated .inc file on `make clean'. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/Makefile diff -u llvm/lib/Target/Sparc/Makefile:1.16 llvm/lib/Target/Sparc/Makefile:1.17 --- llvm/lib/Target/Sparc/Makefile:1.16 Wed May 28 12:41:09 2003 +++ llvm/lib/Target/Sparc/Makefile Wed May 28 22:32:49 2003 @@ -3,12 +3,6 @@ ExtraSource = Debug/Sparc.burm.cpp -SparcV9CodeEmitter.cpp: SparcV9CodeEmitter.inc - -SparcV9CodeEmitter.inc: SparcV9.td - @echo "TableGen-erating $@" - cpp -P SparcV9.td | tblgen -gen-emitter > SparcV9CodeEmitter.inc - include $(LEVEL)/Makefile.common ifdef ENABLE_OPTIMIZED @@ -38,3 +32,11 @@ $(BUILD_ROOT)/Depend/Sparc.burm.d: $(BUILD_ROOT)/Depend/.dir touch $@ +SparcV9CodeEmitter.cpp: SparcV9CodeEmitter.inc + +SparcV9CodeEmitter.inc: SparcV9.td + @echo "TableGen-erating $@" + cpp -P SparcV9.td | tblgen -gen-emitter > SparcV9CodeEmitter.inc + +clean:: + rm -f SparcV9CodeEmitter.inc From brukman at cs.uiuc.edu Wed May 28 23:55:00 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 28 23:55:00 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcV9.td Message-ID: <200305290454.XAA23864@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcV9.td updated: 1.4 -> 1.5 --- Log message: Fixed to use the correct format of the instruction. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/SparcV9.td diff -u llvm/lib/Target/Sparc/SparcV9.td:1.4 llvm/lib/Target/Sparc/SparcV9.td:1.5 --- llvm/lib/Target/Sparc/SparcV9.td:1.4 Wed May 28 22:31:43 2003 +++ llvm/lib/Target/Sparc/SparcV9.td Wed May 28 23:53:56 2003 @@ -205,9 +205,9 @@ // Section A.24: Jump and Link // Mimicking the Sparc's instr def... def JMPLCALLr : F3_1<2, 0b111000, "jmpl">; // jmpl [r+r], r -def JMPLCALLi : F3_1<2, 0b111000, "jmpl">; // jmpl [r+i], r -def JMPLRETr : F3_1<2, 0b111000, "jmpl">; // jmpl [r+r], r -def JMPLRETi : F3_1<2, 0b111000, "jmpl">; // jmpl [r+i], r +def JMPLCALLi : F3_2<2, 0b111000, "jmpl">; // jmpl [r+i], r +def JMPLRETr : F3_1<2, 0b111000, "jmpl">; // jmpl [r+r], r +def JMPLRETi : F3_2<2, 0b111000, "jmpl">; // jmpl [r+i], r // FIXME: FCMPS, FCMPD, FCMPQ !!! // FIXME: FMULS, FMULD, FMULQ, ... From brukman at cs.uiuc.edu Thu May 29 00:01:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu May 29 00:01:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Target/TargetRegInfo.h Message-ID: <200305290500.AAA23921@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Target: TargetRegInfo.h updated: 1.34 -> 1.35 --- Log message: Fixed misspelling and broke a line that was wrapping. --- Diffs of the changes: Index: llvm/include/llvm/Target/TargetRegInfo.h diff -u llvm/include/llvm/Target/TargetRegInfo.h:1.34 llvm/include/llvm/Target/TargetRegInfo.h:1.35 --- llvm/include/llvm/Target/TargetRegInfo.h:1.34 Mon May 26 19:07:13 2003 +++ llvm/include/llvm/Target/TargetRegInfo.h Thu May 29 00:00:14 2003 @@ -178,7 +178,7 @@ // a regId in a register class to a common Id, or vice versa, // we use the folloing two methods. // - // Thsi method converts from class reg. number to unified register number. + // This method converts from class reg. number to unified register number. int getUnifiedRegNum(unsigned regClassID, int reg) const { if (reg == getInvalidRegNum()) { return getInvalidRegNum(); } assert(regClassID < getNumOfRegClasses() && "Invalid register class"); @@ -195,7 +195,8 @@ int totalRegs = 0, rcid = 0, NC = getNumOfRegClasses(); while (rcid < NC && - uRegNum >= totalRegs + (int) MachineRegClassArr[rcid]->getNumOfAllRegs()) { + uRegNum>= totalRegs+(int)MachineRegClassArr[rcid]->getNumOfAllRegs()) + { totalRegs += MachineRegClassArr[rcid]->getNumOfAllRegs(); rcid++; } From brukman at cs.uiuc.edu Thu May 29 00:30:03 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu May 29 00:30:03 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/Makefile Message-ID: <200305290529.AAA24180@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: Makefile updated: 1.17 -> 1.18 --- Log message: When TableGen finds an error in the SparcV9.td file, it exits with a non-zero exit code. This, in turn, makes an empty file SparcV9CodeEmitter.inc, and only much later, produces a link error because the key function that TableGen creates isn't found. Using a temporary file in the middle forces a good .INC file to be generated by TableGen, and it will keep trying until you fix the input file. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/Makefile diff -u llvm/lib/Target/Sparc/Makefile:1.17 llvm/lib/Target/Sparc/Makefile:1.18 --- llvm/lib/Target/Sparc/Makefile:1.17 Wed May 28 22:32:49 2003 +++ llvm/lib/Target/Sparc/Makefile Thu May 29 00:29:22 2003 @@ -34,9 +34,12 @@ SparcV9CodeEmitter.cpp: SparcV9CodeEmitter.inc +TEMP_EMITTER_INC = _temp_emitter.inc + SparcV9CodeEmitter.inc: SparcV9.td @echo "TableGen-erating $@" - cpp -P SparcV9.td | tblgen -gen-emitter > SparcV9CodeEmitter.inc + cpp -P SparcV9.td | tblgen -gen-emitter > $(TEMP_EMITTER_INC) + mv -f $(TEMP_EMITTER_INC) SparcV9CodeEmitter.inc clean:: rm -f SparcV9CodeEmitter.inc From lattner at cs.uiuc.edu Thu May 29 10:07:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 29 10:07:02 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Transforms/Utils/Cloning.h Message-ID: <200305291506.KAA15214@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Transforms/Utils: Cloning.h updated: 1.5 -> 1.6 --- Log message: Doxygenify comments --- Diffs of the changes: Index: llvm/include/llvm/Transforms/Utils/Cloning.h diff -u llvm/include/llvm/Transforms/Utils/Cloning.h:1.5 llvm/include/llvm/Transforms/Utils/Cloning.h:1.6 --- llvm/include/llvm/Transforms/Utils/Cloning.h:1.5 Thu Apr 17 22:49:22 2003 +++ llvm/include/llvm/Transforms/Utils/Cloning.h Thu May 29 10:06:40 2003 @@ -68,28 +68,27 @@ return CloneFunction(F, ValueMap); } -// Clone OldFunc into NewFunc, transforming the old arguments into references to -// ArgMap values. Note that if NewFunc already has basic blocks, the ones -// cloned into it will be added to the end of the function. This function fills -// in a list of return instructions, and can optionally append the specified -// suffix to all values cloned. -// +/// Clone OldFunc into NewFunc, transforming the old arguments into references +/// to ArgMap values. Note that if NewFunc already has basic blocks, the ones +/// cloned into it will be added to the end of the function. This function +/// fills in a list of return instructions, and can optionally append the +/// specified suffix to all values cloned. +/// void CloneFunctionInto(Function *NewFunc, const Function *OldFunc, std::map &ValueMap, std::vector &Returns, const char *NameSuffix = ""); -// InlineFunction - This function forcibly inlines the called function into the -// basic block of the caller. This returns true if it is not possible to inline -// this call. The program is still in a well defined state if this occurs -// though. -// -// Note that this only does one level of inlining. For example, if the -// instruction 'call B' is inlined, and 'B' calls 'C', then the call to 'C' now -// exists in the instruction stream. Similiarly this will inline a recursive -// function by one level. -// +/// InlineFunction - This function inlines the called function into the basic +/// block of the caller. This returns true if it is not possible to inline this +/// call. The program is still in a well defined state if this occurs though. +/// +/// Note that this only does one level of inlining. For example, if the +/// instruction 'call B' is inlined, and 'B' calls 'C', then the call to 'C' now +/// exists in the instruction stream. Similiarly this will inline a recursive +/// function by one level. +/// bool InlineFunction(CallInst *C); #endif From lattner at cs.uiuc.edu Thu May 29 10:08:04 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 29 10:08:04 2003 Subject: [llvm-commits] CVS: llvm/include/Support/Casting.h Message-ID: <200305291507.KAA15272@apoc.cs.uiuc.edu> Changes in directory llvm/include/Support: Casting.h updated: 1.4 -> 1.5 --- Log message: dyn_cast_or_null should work just the same as dyn_cast does --- Diffs of the changes: Index: llvm/include/Support/Casting.h diff -u llvm/include/Support/Casting.h:1.4 llvm/include/Support/Casting.h:1.5 --- llvm/include/Support/Casting.h:1.4 Wed Apr 23 11:17:28 2003 +++ llvm/include/Support/Casting.h Thu May 29 10:07:48 2003 @@ -207,7 +207,7 @@ // be used to test for a type as well as cast if successful. This should be // used in the context of an if statement like this: // -// if (const Instruction *I = dyn_cast(myVal)) { ... } +// if (const Instruction *I = dyn_cast(myVal)) { ... } // template @@ -219,8 +219,8 @@ // value is accepted. // template -inline typename cast_retty::ret_type dyn_cast_or_null(Y *Val) { - return (Val && isa(Val)) ? cast(Val) : 0; +inline typename cast_retty::ret_type dyn_cast_or_null(Y Val) { + return (Val && isa(Val)) ? cast(Val) : 0; } From lattner at cs.uiuc.edu Thu May 29 10:09:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 29 10:09:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/User.h Message-ID: <200305291508.KAA15323@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm: User.h updated: 1.16 -> 1.17 --- Log message: Don't require the user to do something like isa(II->get()). The ->get should be implicit. --- Diffs of the changes: Index: llvm/include/llvm/User.h diff -u llvm/include/llvm/User.h:1.16 llvm/include/llvm/User.h:1.17 --- llvm/include/llvm/User.h:1.16 Tue Oct 1 18:41:17 2002 +++ llvm/include/llvm/User.h Thu May 29 10:08:33 2003 @@ -73,4 +73,24 @@ } }; +template<> struct simplify_type { + typedef Value* SimpleType; + + static SimpleType getSimplifiedValue(const User::op_iterator &Val) { + return (SimpleType)Val->get(); + } +}; +template<> struct simplify_type + : public simplify_type {}; + +template<> struct simplify_type { + typedef Value* SimpleType; + + static SimpleType getSimplifiedValue(const User::const_op_iterator &Val) { + return (SimpleType)Val->get(); + } +}; +template<> struct simplify_type + : public simplify_type {}; + #endif From lattner at cs.uiuc.edu Thu May 29 10:12:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 29 10:12:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/InlineFunction.cpp Message-ID: <200305291511.KAA15380@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: InlineFunction.cpp added (r1.1) --- Log message: * Separate all of the grunt work of inlining out into the Utils library. * Make the function inliner _significantly_ smarter. :) --- Diffs of the changes: Index: llvm/lib/Transforms/Utils/InlineFunction.cpp diff -c /dev/null llvm/lib/Transforms/Utils/InlineFunction.cpp:1.1 *** /dev/null Thu May 29 10:11:41 2003 --- llvm/lib/Transforms/Utils/InlineFunction.cpp Thu May 29 10:11:31 2003 *************** *** 0 **** --- 1,164 ---- + //===- InlineFunction.cpp - Code to perform function inlining -------------===// + // + // This file implements inlining of a function into a call site, resolving + // parameters and the return value as appropriate. + // + // FIXME: This pass should transform alloca instructions in the called function + // into malloc/free pairs! Or perhaps it should refuse to inline them! + // + //===----------------------------------------------------------------------===// + + #include "llvm/Transforms/Utils/Cloning.h" + #include "llvm/Module.h" + #include "llvm/iTerminators.h" + #include "llvm/iPHINode.h" + #include "llvm/iMemory.h" + #include "llvm/iOther.h" + #include "llvm/DerivedTypes.h" + + // InlineFunction - This function inlines the called function into the basic + // block of the caller. This returns false if it is not possible to inline this + // call. The program is still in a well defined state if this occurs though. + // + // Note that this only does one level of inlining. For example, if the + // instruction 'call B' is inlined, and 'B' calls 'C', then the call to 'C' now + // exists in the instruction stream. Similiarly this will inline a recursive + // function by one level. + // + bool InlineFunction(CallInst *CI) { + assert(isa(CI) && "InlineFunction only works on CallInst nodes"); + assert(CI->getParent() && "Instruction not embedded in basic block!"); + assert(CI->getParent()->getParent() && "Instruction not in function!"); + + const Function *CalledFunc = CI->getCalledFunction(); + if (CalledFunc == 0 || // Can't inline external function or indirect + CalledFunc->isExternal() || // call, or call to a vararg function! + CalledFunc->getFunctionType()->isVarArg()) return false; + + BasicBlock *OrigBB = CI->getParent(); + Function *Caller = OrigBB->getParent(); + + // Call splitBasicBlock - The original basic block now ends at the instruction + // immediately before the call. The original basic block now ends with an + // unconditional branch to NewBB, and NewBB starts with the call instruction. + // + BasicBlock *NewBB = OrigBB->splitBasicBlock(CI); + NewBB->setName(OrigBB->getName()+".split"); + + // Remove (unlink) the CallInst from the start of the new basic block. + NewBB->getInstList().remove(CI); + + // If we have a return value generated by this call, convert it into a PHI + // node that gets values from each of the old RET instructions in the original + // function. + // + PHINode *PHI = 0; + if (!CI->use_empty()) { + // The PHI node should go at the front of the new basic block to merge all + // possible incoming values. + // + PHI = new PHINode(CalledFunc->getReturnType(), CI->getName(), + NewBB->begin()); + + // Anything that used the result of the function call should now use the PHI + // node as their operand. + // + CI->replaceAllUsesWith(PHI); + } + + // Get an iterator to the last basic block in the function, which will have + // the new function inlined after it. + // + Function::iterator LastBlock = &Caller->back(); + + // Calculate the vector of arguments to pass into the function cloner... + std::map ValueMap; + assert((unsigned)std::distance(CalledFunc->abegin(), CalledFunc->aend()) == + CI->getNumOperands()-1 && "No varargs calls can be inlined yet!"); + + unsigned i = 1; + for (Function::const_aiterator I = CalledFunc->abegin(), E=CalledFunc->aend(); + I != E; ++I, ++i) + ValueMap[I] = CI->getOperand(i); + + // Since we are now done with the CallInst, we can delete it. + delete CI; + + // Make a vector to capture the return instructions in the cloned function... + std::vector Returns; + + // Populate the value map with all of the globals in the program. + Module &M = *Caller->getParent(); + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + ValueMap[I] = I; + for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; ++I) + ValueMap[I] = I; + + // Do all of the hard part of cloning the callee into the caller... + CloneFunctionInto(Caller, CalledFunc, ValueMap, Returns, ".i"); + + // Loop over all of the return instructions, turning them into unconditional + // branches to the merge point now... + for (unsigned i = 0, e = Returns.size(); i != e; ++i) { + ReturnInst *RI = Returns[i]; + BasicBlock *BB = RI->getParent(); + + // Add a branch to the merge point where the PHI node would live... + new BranchInst(NewBB, RI); + + if (PHI) { // The PHI node should include this value! + assert(RI->getReturnValue() && "Ret should have value!"); + assert(RI->getReturnValue()->getType() == PHI->getType() && + "Ret value not consistent in function!"); + PHI->addIncoming(RI->getReturnValue(), BB); + } + + // Delete the return instruction now + BB->getInstList().erase(RI); + } + + // Check to see if the PHI node only has one argument. This is a common + // case resulting from there only being a single return instruction in the + // function call. Because this is so common, eliminate the PHI node. + // + if (PHI && PHI->getNumIncomingValues() == 1) { + PHI->replaceAllUsesWith(PHI->getIncomingValue(0)); + PHI->getParent()->getInstList().erase(PHI); + } + + // Change the branch that used to go to NewBB to branch to the first basic + // block of the inlined function. + // + TerminatorInst *Br = OrigBB->getTerminator(); + assert(Br && Br->getOpcode() == Instruction::Br && + "splitBasicBlock broken!"); + Br->setOperand(0, ++LastBlock); + + // If there are any alloca instructions in the block that used to be the entry + // block for the callee, move them to the entry block of the caller. First + // calculate which instruction they should be inserted before. We insert the + // instructions at the end of the current alloca list. + // + BasicBlock::iterator InsertPoint = Caller->begin()->begin(); + while (isa(InsertPoint)) ++InsertPoint; + + for (BasicBlock::iterator I = LastBlock->begin(), E = LastBlock->end(); + I != E; ) + if (AllocaInst *AI = dyn_cast(I)) { + ++I; // Move to the next instruction + LastBlock->getInstList().remove(AI); + Caller->front().getInstList().insert(InsertPoint, AI); + + } else { + ++I; + } + + // Now that the function is correct, make it a little bit nicer. In + // particular, move the basic blocks inserted from the end of the function + // into the space made by splitting the source basic block. + // + Caller->getBasicBlockList().splice(NewBB, Caller->getBasicBlockList(), + LastBlock, Caller->end()); + + return true; + } From lattner at cs.uiuc.edu Thu May 29 10:12:06 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 29 10:12:06 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/FunctionInlining.cpp Message-ID: <200305291511.KAA15387@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: FunctionInlining.cpp updated: 1.44 -> 1.45 --- Log message: * Separate all of the grunt work of inlining out into the Utils library. * Make the function inliner _significantly_ smarter. :) --- Diffs of the changes: Index: llvm/lib/Transforms/IPO/FunctionInlining.cpp diff -u llvm/lib/Transforms/IPO/FunctionInlining.cpp:1.44 llvm/lib/Transforms/IPO/FunctionInlining.cpp:1.45 --- llvm/lib/Transforms/IPO/FunctionInlining.cpp:1.44 Wed May 7 21:36:43 2003 +++ llvm/lib/Transforms/IPO/FunctionInlining.cpp Thu May 29 10:11:31 2003 @@ -1,15 +1,6 @@ //===- FunctionInlining.cpp - Code to perform function inlining -----------===// // -// This file implements inlining of functions. -// -// Specifically, this: -// * Exports functionality to inline any function call -// * Inlines functions that consist of a single basic block -// * Is able to inline ANY function call -// . Has a smart heuristic for when to inline a function -// -// FIXME: This pass should transform alloca instructions in the called function -// into malloc/free pairs! Or perhaps it should refuse to inline them! +// This file implements bottom-up inlining of functions into callees. // //===----------------------------------------------------------------------===// @@ -17,194 +8,161 @@ #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Module.h" #include "llvm/Pass.h" -#include "llvm/iTerminators.h" -#include "llvm/iPHINode.h" #include "llvm/iOther.h" -#include "llvm/DerivedTypes.h" +#include "llvm/iMemory.h" #include "Support/Statistic.h" -#include +#include -static Statistic<> NumInlined("inline", "Number of functions inlined"); +namespace { + Statistic<> NumInlined("inline", "Number of functions inlined"); -// InlineFunction - This function forcibly inlines the called function into the -// basic block of the caller. This returns false if it is not possible to -// inline this call. The program is still in a well defined state if this -// occurs though. -// -// Note that this only does one level of inlining. For example, if the -// instruction 'call B' is inlined, and 'B' calls 'C', then the call to 'C' now -// exists in the instruction stream. Similiarly this will inline a recursive -// function by one level. -// -bool InlineFunction(CallInst *CI) { - assert(isa(CI) && "InlineFunction only works on CallInst nodes"); - assert(CI->getParent() && "Instruction not embedded in basic block!"); - assert(CI->getParent()->getParent() && "Instruction not in function!"); - - const Function *CalledFunc = CI->getCalledFunction(); - if (CalledFunc == 0 || // Can't inline external function or indirect - CalledFunc->isExternal() || // call, or call to a vararg function! - CalledFunc->getFunctionType()->isVarArg()) return false; - - //std::cerr << "Inlining " << CalledFunc->getName() << " into " - // << CurrentMeth->getName() << "\n"; - - BasicBlock *OrigBB = CI->getParent(); - - // Call splitBasicBlock - The original basic block now ends at the instruction - // immediately before the call. The original basic block now ends with an - // unconditional branch to NewBB, and NewBB starts with the call instruction. - // - BasicBlock *NewBB = OrigBB->splitBasicBlock(CI); - NewBB->setName("InlinedFunctionReturnNode"); + struct FunctionInlining : public Pass { + virtual bool run(Module &M) { + bool Changed = false; + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + Changed |= doInlining(I); + ProcessedFunctions.clear(); + return Changed; + } - // Remove (unlink) the CallInst from the start of the new basic block. - NewBB->getInstList().remove(CI); + private: + std::set ProcessedFunctions; // Prevent infinite recursion + bool doInlining(Function *F); + }; + RegisterOpt X("inline", "Function Integration/Inlining"); +} - // If we have a return value generated by this call, convert it into a PHI - // node that gets values from each of the old RET instructions in the original - // function. - // - PHINode *PHI = 0; - if (!CI->use_empty()) { - // The PHI node should go at the front of the new basic block to merge all - // possible incoming values. - // - PHI = new PHINode(CalledFunc->getReturnType(), CI->getName(), - NewBB->begin()); +Pass *createFunctionInliningPass() { return new FunctionInlining(); } - // Anything that used the result of the function call should now use the PHI - // node as their operand. - // - CI->replaceAllUsesWith(PHI); - } - // Get a pointer to the last basic block in the function, which will have the - // new function inlined after it. - // - Function::iterator LastBlock = &OrigBB->getParent()->back(); +// ShouldInlineFunction - The heuristic used to determine if we should inline +// the function call or not. +// +static inline bool ShouldInlineFunction(const CallInst *CI) { + assert(CI->getParent() && CI->getParent()->getParent() && + "Call not embedded into a function!"); - // Calculate the vector of arguments to pass into the function cloner... - std::map ValueMap; - assert((unsigned)std::distance(CalledFunc->abegin(), CalledFunc->aend()) == - CI->getNumOperands()-1 && "No varargs calls can be inlined yet!"); - - unsigned i = 1; - for (Function::const_aiterator I = CalledFunc->abegin(), E=CalledFunc->aend(); - I != E; ++I, ++i) - ValueMap[I] = CI->getOperand(i); - - // Since we are now done with the CallInst, we can delete it. - delete CI; - - // Make a vector to capture the return instructions in the cloned function... - std::vector Returns; - - // Populate the value map with all of the globals in the program. - Module &M = *OrigBB->getParent()->getParent(); - for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) - ValueMap[I] = I; - for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; ++I) - ValueMap[I] = I; - - // Do all of the hard part of cloning the callee into the caller... - CloneFunctionInto(OrigBB->getParent(), CalledFunc, ValueMap, Returns, ".i"); - - // Loop over all of the return instructions, turning them into unconditional - // branches to the merge point now... - for (unsigned i = 0, e = Returns.size(); i != e; ++i) { - ReturnInst *RI = Returns[i]; - BasicBlock *BB = RI->getParent(); - - // Add a branch to the merge point where the PHI node would live... - new BranchInst(NewBB, RI); - - if (PHI) { // The PHI node should include this value! - assert(RI->getReturnValue() && "Ret should have value!"); - assert(RI->getReturnValue()->getType() == PHI->getType() && - "Ret value not consistent in function!"); - PHI->addIncoming(RI->getReturnValue(), BB); - } + const Function *Callee = CI->getCalledFunction(); + if (Callee == 0 || Callee->isExternal()) + return false; // Cannot inline an indirect call... or external function. - // Delete the return instruction now - BB->getInstList().erase(RI); - } + // Don't inline a recursive call. + const Function *Caller = CI->getParent()->getParent(); + if (Caller == Callee) return false; - // Check to see if the PHI node only has one argument. This is a common - // case resulting from there only being a single return instruction in the - // function call. Because this is so common, eliminate the PHI node. + // InlineQuality - This value measures how good of an inline candidate this + // call site is to inline. The initial value determines how aggressive the + // inliner is. If this value is negative after the final computation, + // inlining is not performed. // - if (PHI && PHI->getNumIncomingValues() == 1) { - PHI->replaceAllUsesWith(PHI->getIncomingValue(0)); - PHI->getParent()->getInstList().erase(PHI); - } + int InlineQuality = 200; // FIXME: This is VERY conservative - // Change the branch that used to go to NewBB to branch to the first basic - // block of the inlined function. + // If there is only one call of the function, and it has internal linkage, + // make it almost guaranteed to be inlined. // - TerminatorInst *Br = OrigBB->getTerminator(); - assert(Br && Br->getOpcode() == Instruction::Br && - "splitBasicBlock broken!"); - Br->setOperand(0, ++LastBlock); - return true; -} + if (Callee->use_size() == 1 && Callee->hasInternalLinkage()) + InlineQuality += 30000; -static inline bool ShouldInlineFunction(const CallInst *CI, const Function *F) { - assert(CI->getParent() && CI->getParent()->getParent() && - "Call not embedded into a function!"); - - // Don't inline a recursive call. - if (CI->getParent()->getParent() == F) return false; + // Add to the inline quality for properties that make the call valueable to + // inline. This includes factors that indicate that the result of inlining + // the function will be optimizable. Currently this just looks at arguments + // passed into the function. + // + for (User::const_op_iterator I = CI->op_begin()+1, E = CI->op_end(); + I != E; ++I){ + // Each argument passed in has a cost at both the caller and the callee + // sides. This favors functions that take many arguments over functions + // that take few arguments. + InlineQuality += 20; + + // If this is a function being passed in, it is very likely that we will be + // able to turn an indirect function call into a direct function call. + if (isa(I)) + InlineQuality += 100; + + // If a constant, global variable or alloca is passed in, inlining this + // function is likely to allow significant future optimization possibilities + // (constant propagation, scalar promotion, and scalarization), so encourage + // the inlining of the function. + // + else if (isa(I) || isa(I) || isa(I)) + InlineQuality += 60; + } - // Don't inline something too big. This is a really crappy heuristic - if (F->size() > 3) return false; + // Now that we have considered all of the factors that make the call site more + // likely to be inlined, look at factors that make us not want to inline it. + // As soon as the inline quality gets negative, bail out. + + // Look at the size of the callee. Each basic block counts as 20 units, and + // each instruction counts as 10. + for (Function::const_iterator BB = Callee->begin(), E = Callee->end(); + BB != E; ++BB) { + InlineQuality -= BB->size()*10 + 20; + if (InlineQuality < 0) return false; + } - // Don't inline into something too big. This is a **really** crappy heuristic - if (CI->getParent()->getParent()->size() > 10) return false; + // Don't inline into something too big, which would make it bigger. Here, we + // count each basic block as a single unit. + for (Function::const_iterator BB = Caller->begin(), E = Caller->end(); + BB != E; ++BB) { + --InlineQuality; + if (InlineQuality < 0) return false; + } - // Go ahead and try just about anything else. + // If we get here, this call site is high enough "quality" to inline. + DEBUG(std::cerr << "Inlining in '" << Caller->getName() + << "', quality = " << InlineQuality << ": " << *CI); return true; } -static inline bool DoFunctionInlining(BasicBlock *BB) { - for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) { - if (CallInst *CI = dyn_cast(I)) { - // Check to see if we should inline this function - Function *F = CI->getCalledFunction(); - if (F && ShouldInlineFunction(CI, F)) { - return InlineFunction(CI); - } - } - } - return false; -} - -// doFunctionInlining - Use a heuristic based approach to inline functions that -// seem to look good. +// doInlining - Use a heuristic based approach to inline functions that seem to +// look good. // -static bool doFunctionInlining(Function &F) { - bool Changed = false; +bool FunctionInlining::doInlining(Function *F) { + // If we have already processed this function (ie, it is recursive) don't + // revisit. + std::set::iterator PFI = ProcessedFunctions.lower_bound(F); + if (PFI != ProcessedFunctions.end() && *PFI == F) return false; + + // Insert the function in the set so it doesn't get revisited. + ProcessedFunctions.insert(PFI, F); - // Loop through now and inline instructions a basic block at a time... - for (Function::iterator I = F.begin(); I != F.end(); ) - if (DoFunctionInlining(I)) { - ++NumInlined; - Changed = true; - } else { - ++I; + bool Changed = false; + for (Function::iterator BB = F->begin(); BB != F->end(); ++BB) + for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ) { + bool ShouldInc = true; + // Found a call instruction? FIXME: This should also handle INVOKEs + if (CallInst *CI = dyn_cast(I)) { + if (Function *Callee = CI->getCalledFunction()) + doInlining(Callee); // Inline in callees before callers! + + // Decide whether we should inline this function... + if (ShouldInlineFunction(CI)) { + // Save an iterator to the instruction before the call if it exists, + // otherwise get an iterator at the end of the block... because the + // call will be destroyed. + // + BasicBlock::iterator SI; + if (I != BB->begin()) { + SI = I; --SI; // Instruction before the call... + } else { + SI = BB->end(); + } + + // Attempt to inline the function... + if (InlineFunction(CI)) { + ++NumInlined; + Changed = true; + // Move to instruction before the call... + I = (SI == BB->end()) ? BB->begin() : SI; + ShouldInc = false; // Don't increment iterator until next time + } + } + } + if (ShouldInc) ++I; } return Changed; } -namespace { - struct FunctionInlining : public FunctionPass { - virtual bool runOnFunction(Function &F) { - return doFunctionInlining(F); - } - }; - RegisterOpt X("inline", "Function Integration/Inlining"); -} - -Pass *createFunctionInliningPass() { return new FunctionInlining(); } From lattner at cs.uiuc.edu Thu May 29 10:13:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 29 10:13:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/DemoteRegToStack.cpp Message-ID: <200305291512.KAA15453@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: DemoteRegToStack.cpp updated: 1.1 -> 1.2 --- Log message: Eliminate unnecessary ->get calls that are now automatically handled. --- Diffs of the changes: Index: llvm/lib/Transforms/Utils/DemoteRegToStack.cpp diff -u llvm/lib/Transforms/Utils/DemoteRegToStack.cpp:1.1 llvm/lib/Transforms/Utils/DemoteRegToStack.cpp:1.2 --- llvm/lib/Transforms/Utils/DemoteRegToStack.cpp:1.1 Tue Dec 10 07:07:58 2002 +++ llvm/lib/Transforms/Utils/DemoteRegToStack.cpp Thu May 29 10:12:27 2003 @@ -1,14 +1,14 @@ //===- DemoteRegToStack.cpp - Move a virtual reg. to stack ------*- C++ -*-===// // -// This file provide the function DemoteRegToStack(). -// This function takes a virtual register computed by an -// Instruction& X and replaces it with a slot in the stack frame, -// allocated via alloca. It returns the pointer to the AllocaInst inserted. +// This file provide the function DemoteRegToStack(). This function takes a +// virtual register computed by an Instruction& X and replaces it with a slot in +// the stack frame, allocated via alloca. It returns the pointer to the +// AllocaInst inserted. +// //===----------------------------------------------------------------------===// #include "llvm/Transforms/Utils/DemoteRegToStack.h" #include "llvm/Function.h" -#include "llvm/BasicBlock.h" #include "llvm/iMemory.h" #include "llvm/iPHINode.h" #include "llvm/iTerminators.h" @@ -16,7 +16,6 @@ #include "Support/hash_set" #include - //---------------------------------------------------------------------------- // function DemoteRegToStack() // @@ -28,11 +27,10 @@ // Helper function to push a phi *and* all its operands to the worklist! // Do not push an instruction if it is already in the result set of Phis to go. inline void PushOperandsOnWorkList(std::stack& workList, - PhiSet& phisToGo, PHINode* phiN) -{ - for (User::op_iterator OI=phiN->op_begin(), OE=phiN->op_end(); + PhiSet& phisToGo, PHINode* phiN) { + for (User::op_iterator OI = phiN->op_begin(), OE = phiN->op_end(); OI != OE; ++OI) - if (Instruction* opI = dyn_cast(OI->get())) + if (Instruction* opI = dyn_cast(OI)) if (!isa(opI) || phisToGo.find(cast(opI)) == phisToGo.end()) workList.push(opI); From lattner at cs.uiuc.edu Thu May 29 10:13:05 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 29 10:13:05 2003 Subject: [llvm-commits] CVS: llvm/lib/CWriter/Writer.cpp Message-ID: <200305291512.KAA15432@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CWriter: Writer.cpp updated: 1.88 -> 1.89 --- Log message: Eliminate unnecessary ->get calls that are now automatically handled. --- Diffs of the changes: Index: llvm/lib/CWriter/Writer.cpp diff -u llvm/lib/CWriter/Writer.cpp:1.88 llvm/lib/CWriter/Writer.cpp:1.89 --- llvm/lib/CWriter/Writer.cpp:1.88 Sat May 17 17:26:30 2003 +++ llvm/lib/CWriter/Writer.cpp Thu May 29 10:12:27 2003 @@ -694,7 +694,7 @@ E = STy->getElementTypes().end(); I != E; ++I) { const Type *Ty1 = I->get(); if (isa(Ty1) || isa(Ty1)) - printContainedStructs(Ty1, StructPrinted); + printContainedStructs(*I, StructPrinted); } //Print structure type out.. @@ -1121,7 +1121,7 @@ return; } - const Constant *CI = dyn_cast(I->get()); + const Constant *CI = dyn_cast(I); if (HasImplicitAddress && (!CI || !CI->isNullValue())) Out << "(&"; From lattner at cs.uiuc.edu Thu May 29 10:13:08 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 29 10:13:08 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/ExprTypeConvert.cpp Message-ID: <200305291512.KAA15439@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms: ExprTypeConvert.cpp updated: 1.72 -> 1.73 --- Log message: Eliminate unnecessary ->get calls that are now automatically handled. --- Diffs of the changes: Index: llvm/lib/Transforms/ExprTypeConvert.cpp diff -u llvm/lib/Transforms/ExprTypeConvert.cpp:1.72 llvm/lib/Transforms/ExprTypeConvert.cpp:1.73 --- llvm/lib/Transforms/ExprTypeConvert.cpp:1.72 Tue May 20 16:01:14 2003 +++ llvm/lib/Transforms/ExprTypeConvert.cpp Thu May 29 10:12:27 2003 @@ -1257,7 +1257,7 @@ for (User::op_iterator OI = I->op_begin(), OE = I->op_end(); OI != OE; ++OI) - if (Instruction *U = dyn_cast(OI->get())) { + if (Instruction *U = dyn_cast(OI)) { *OI = 0; RecursiveDelete(Cache, U); } From lattner at cs.uiuc.edu Thu May 29 10:13:12 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 29 10:13:12 2003 Subject: [llvm-commits] CVS: llvm/lib/Analysis/IPA/PgmDependenceGraph.cpp Message-ID: <200305291512.KAA15425@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis/IPA: PgmDependenceGraph.cpp updated: 1.1 -> 1.2 --- Log message: Eliminate unnecessary ->get calls that are now automatically handled. --- Diffs of the changes: Index: llvm/lib/Analysis/IPA/PgmDependenceGraph.cpp diff -u llvm/lib/Analysis/IPA/PgmDependenceGraph.cpp:1.1 llvm/lib/Analysis/IPA/PgmDependenceGraph.cpp:1.2 --- llvm/lib/Analysis/IPA/PgmDependenceGraph.cpp:1.1 Sun Dec 8 08:13:19 2002 +++ llvm/lib/Analysis/IPA/PgmDependenceGraph.cpp Thu May 29 10:12:27 2003 @@ -15,15 +15,13 @@ // The MemoryDepAnalysis does build an explicit graph, which is used internally // here. That graph could be augmented with the other dependences above if // desired, but for most uses there will be little need to do that. +// //===----------------------------------------------------------------------===// #include "llvm/Analysis/PgmDependenceGraph.h" #include "llvm/Analysis/MemoryDepAnalysis.h" #include "llvm/Analysis/PostDominators.h" #include "llvm/Function.h" -#include "llvm/BasicBlock.h" -#include "llvm/Instruction.h" - //---------------------------------------------------------------------------- @@ -78,7 +76,7 @@ if (doIncomingDeps) for (Instruction::op_iterator E = depNode->getInstr().op_end(); ssaInEdgeIter != E && - (firstTarget = dyn_cast(ssaInEdgeIter->get()))== NULL; ) + (firstTarget = dyn_cast(ssaInEdgeIter))== NULL; ) ++ssaInEdgeIter; else for (Value::use_iterator E = depNode->getInstr().use_end(); From lattner at cs.uiuc.edu Thu May 29 10:14:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 29 10:14:00 2003 Subject: [llvm-commits] CVS: llvm/tools/gccld/gccld.cpp Message-ID: <200305291513.KAA15504@apoc.cs.uiuc.edu> Changes in directory llvm/tools/gccld: gccld.cpp updated: 1.32 -> 1.33 --- Log message: Fix formatting in file --- Diffs of the changes: Index: llvm/tools/gccld/gccld.cpp diff -u llvm/tools/gccld/gccld.cpp:1.32 llvm/tools/gccld/gccld.cpp:1.33 --- llvm/tools/gccld/gccld.cpp:1.32 Tue May 27 14:15:11 2003 +++ llvm/tools/gccld/gccld.cpp Thu May 29 10:13:15 2003 @@ -122,22 +122,22 @@ // IsArchive - Returns true iff FILENAME appears to be the name of an ar // archive file. It determines this by checking the magic string at the // beginning of the file. -static bool IsArchive (const std::string &filename) { - static const std::string ArchiveMagic ("!\012"); - char buf[1 + ArchiveMagic.size ()]; - std::ifstream f (filename.c_str ()); - f.read (buf, ArchiveMagic.size ()); - buf[ArchiveMagic.size ()] = '\0'; - return (ArchiveMagic == buf); +static bool IsArchive(const std::string &filename) { + std::string ArchiveMagic("!\012"); + char buf[1 + ArchiveMagic.size()]; + std::ifstream f(filename.c_str()); + f.read(buf, ArchiveMagic.size()); + buf[ArchiveMagic.size()] = '\0'; + return ArchiveMagic == buf; } // LoadLibraryExactName - This looks for a file with a known name and tries to // load it, similarly to LoadLibraryFromDirectory(). -static inline bool LoadLibraryExactName (const std::string &FileName, +static inline bool LoadLibraryExactName(const std::string &FileName, std::vector &Objects, bool &isArchive) { if (Verbose) std::cerr << " Considering '" << FileName << "'\n"; if (FileExists(FileName)) { - if (IsArchive (FileName)) { + if (IsArchive(FileName)) { std::string ErrorMessage; if (Verbose) std::cerr << " Loading '" << FileName << "'\n"; if (!ReadArchiveFile(FileName, Objects, &ErrorMessage)) { @@ -176,7 +176,7 @@ // directories in LibPaths, looking for a suitable match for LibName // in each one. for (unsigned NextLibPathIdx = 0; NextLibPathIdx != LibPaths.size(); - ++NextLibPathIdx) { + ++NextLibPathIdx) { std::string Directory = LibPaths[NextLibPathIdx] + "/"; if (!LoadLibraryExactName(Directory + "lib" + LibName + ".a", Objects, isArchive)) @@ -330,10 +330,10 @@ for (unsigned i = 1; i < InputFilenames.size(); ++i) { // A user may specify an ar archive without -l, perhaps because it // is not installed as a library. Detect that and link the library. - if (IsArchive (InputFilenames[i])) { + if (IsArchive(InputFilenames[i])) { if (Verbose) std::cerr << "Linking archive '" << InputFilenames[i] << "'\n"; - if (LinkLibrary (Composite.get(), InputFilenames[i], false, ErrorMessage)) + if (LinkLibrary(Composite.get(), InputFilenames[i], false, ErrorMessage)) return PrintAndReturn(argv[0], ErrorMessage, ": error linking in '" + InputFilenames[i] + "'"); continue; From lattner at cs.uiuc.edu Thu May 29 10:17:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 29 10:17:00 2003 Subject: [llvm-commits] CVS: llvm/test/Libraries/Makefile.libs Message-ID: <200305291516.KAA15645@apoc.cs.uiuc.edu> Changes in directory llvm/test/Libraries: Makefile.libs updated: 1.6 -> 1.7 --- Log message: Run more post-link xforms --- Diffs of the changes: Index: llvm/test/Libraries/Makefile.libs diff -u llvm/test/Libraries/Makefile.libs:1.6 llvm/test/Libraries/Makefile.libs:1.7 --- llvm/test/Libraries/Makefile.libs:1.6 Thu May 22 15:27:30 2003 +++ llvm/test/Libraries/Makefile.libs Thu May 29 10:16:45 2003 @@ -31,10 +31,13 @@ LLINK_OPTS += -internalize -internalize-public-api-list=$(EXPORTED_SYMBOL_LIST) endif +# Standard set of postlink optimizations... +LLINK_OPTS += -inline -globaldce -funcresolve -deadtypeelim -instcombine -simplifycfg + # Link the library, then perform postlink optimization... $(DESTLIBNAME): $(DESTLIBDIR)/.dir $(LObjects) $(LLINK) $(LOPT) $(LLINK) -f $(LObjects) $(LDFLAGS) | \ - $(LOPT) -f -q -funcresolve -deadtypeelim $(LLINK_OPTS) -globaldce -o $@ + $(LOPT) -f -q $(LLINK_OPTS) -o $@ # Install target for libraries: Copy into the gcc install directory. # From lattner at cs.uiuc.edu Thu May 29 10:17:05 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 29 10:17:05 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/Inline/alloca_test.ll Makefile basictest.ll Message-ID: <200305291516.KAA15615@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/Inline: alloca_test.ll added (r1.1) Makefile updated: 1.1 -> 1.2 basictest.ll updated: 1.1 -> 1.2 --- Log message: Change tests to use testrunner new test --- Diffs of the changes: Index: llvm/test/Regression/Transforms/Inline/alloca_test.ll diff -c /dev/null llvm/test/Regression/Transforms/Inline/alloca_test.ll:1.1 *** /dev/null Thu May 29 10:16:20 2003 --- llvm/test/Regression/Transforms/Inline/alloca_test.ll Thu May 29 10:16:10 2003 *************** *** 0 **** --- 1,19 ---- + ; This test ensures that alloca instructions in the entry block for an inlined + ; function are moved to the top of the function they are inlined into. + ; + ; RUN: as < %s | opt -inline | dis | grep -C 1 alloca | grep Entry: + + int %func(int %i) { + %X = alloca int + ret int %i + } + + declare void %bar() + + int %main(int %argc) { + Entry: + call void %bar() + %X = call int %func(int 7) + %Y = add int %X, %argc + ret int %Y + } Index: llvm/test/Regression/Transforms/Inline/Makefile diff -u llvm/test/Regression/Transforms/Inline/Makefile:1.1 llvm/test/Regression/Transforms/Inline/Makefile:1.2 --- llvm/test/Regression/Transforms/Inline/Makefile:1.1 Mon Jun 24 12:46:05 2002 +++ llvm/test/Regression/Transforms/Inline/Makefile Thu May 29 10:16:09 2003 @@ -4,9 +4,7 @@ TESTS := $(wildcard *.ll) -all:: $(addprefix Output/, $(TESTS:%.ll=%.ibc)) - -Output/%.ibc: %.ll Output/.dir $(LOPT) - ($(LAS) < $< | $(LOPT) -inline -q -f -o $@) || \ - ( rm -f $@; $(FAILURE) $@ ) +all:: $(addprefix Output/, $(TESTS:%.ll=%.ll.out)) +Output/%.ll.out: %.ll Output/.dir $(LOPT) + -$(TESTRUNR) $< Index: llvm/test/Regression/Transforms/Inline/basictest.ll diff -u llvm/test/Regression/Transforms/Inline/basictest.ll:1.1 llvm/test/Regression/Transforms/Inline/basictest.ll:1.2 --- llvm/test/Regression/Transforms/Inline/basictest.ll:1.1 Mon Jun 24 12:46:05 2002 +++ llvm/test/Regression/Transforms/Inline/basictest.ll Thu May 29 10:16:10 2003 @@ -1,4 +1,4 @@ - +; RUN: as < %s | opt -inline -disable-output -print int %func(int %i) { ret int %i From lattner at cs.uiuc.edu Thu May 29 10:19:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 29 10:19:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/External/SPEC/Makefile.spec Message-ID: <200305291518.KAA15808@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/External/SPEC: Makefile.spec updated: 1.3 -> 1.4 --- Log message: Move bytecode target AFTER include so that it is not the default target! --- Diffs of the changes: Index: llvm/test/Programs/External/SPEC/Makefile.spec diff -u llvm/test/Programs/External/SPEC/Makefile.spec:1.3 llvm/test/Programs/External/SPEC/Makefile.spec:1.4 --- llvm/test/Programs/External/SPEC/Makefile.spec:1.3 Fri May 23 15:07:10 2003 +++ llvm/test/Programs/External/SPEC/Makefile.spec Thu May 29 10:18:30 2003 @@ -34,15 +34,14 @@ PROG := $(BENCH_NAME) Source := $(wildcard $(SPEC_BENCH_DIR)/src/*.c) -# Pseudo target to build just the bytecode file. -bytecode: Output/$(PROG).llvm.bc - - # Disable the default Output/%.out-* targets... PROGRAMS_HAVE_CUSTOM_RUN_RULES := 1 SourceDir := $(SPEC_BENCH_DIR)/src/ include $(LEVEL)/test/Programs/MultiSource/Makefile.multisrc + +# Pseudo target to build just the bytecode file. +bytecode: Output/$(PROG).llvm.bc LCCFLAGS := -DSPEC_CPU2000 -O2 CFLAGS := -DSPEC_CPU2000 -O2 From dhurjati at cs.uiuc.edu Thu May 29 11:19:01 2003 From: dhurjati at cs.uiuc.edu (Dinakar Dhurjati) Date: Thu May 29 11:19:01 2003 Subject: [llvm-commits] CVS: llvm/Makefile.common Message-ID: <200305291618.LAA16980@apoc.cs.uiuc.edu> Changes in directory llvm: Makefile.common updated: 1.81 -> 1.82 --- Log message: Added project options to the Makefile.common --- Diffs of the changes: Index: llvm/Makefile.common diff -u llvm/Makefile.common:1.81 llvm/Makefile.common:1.82 --- llvm/Makefile.common:1.81 Thu May 15 16:28:55 2003 +++ llvm/Makefile.common Thu May 29 11:18:20 2003 @@ -92,10 +92,18 @@ # exist in the build tree (for example the test/ heirarchy). Thus we evaluate # the directory to eliminate the ../'s # +ifdef PROJ_COMPILE +TOP_DIRECTORY := $(shell cd $(TOPLEVEL); pwd) +else TOP_DIRECTORY := $(shell cd $(LEVEL); pwd) +endif + BUILD_ROOT_TOP := $(LLVM_OBJ_DIR)$(patsubst $(HOME)%,%,$(TOP_DIRECTORY)) endif + + + #-------------------------------------------------------------------- # Variables derived from configuration options... #-------------------------------------------------------------------- @@ -120,10 +128,30 @@ endif # Shorthand for commonly accessed directories -LIBDEBUG := $(BUILD_ROOT_TOP)/lib/Debug -LIBRELEASE := $(BUILD_ROOT_TOP)/lib/Release -LIBPROFILE := $(BUILD_ROOT_TOP)/lib/Profile -LIBCURRENT := $(BUILD_ROOT_TOP)/lib/$(CONFIGURATION) +DESTLIBDEBUG := $(BUILD_ROOT_TOP)/lib/Debug +DESTLIBRELEASE := $(BUILD_ROOT_TOP)/lib/Release +DESTLIBPROFILE := $(BUILD_ROOT_TOP)/lib/Profile +DESTLIBCURRENT := $(BUILD_ROOT_TOP)/lib/$(CONFIGURATION) + +ifdef PROJ_COMPILE +LLVMLIBDEBUGSOURCE := $(LLVM_LIB_DIR)/lib/Debug +LLVMLIBRELEASESOURCE := $(LLVM_LIB_DIR)/lib/Release +LLVMLIBPROFILESOURCE := $(LLVM_LIB_DIR)/lib/Profile +LLVMLIBCURRENTSOURCE := $(LLVM_LIB_DIR)/lib/$(CONFIGURATION) + +PROJLIBDEBUGSOURCE := $(BUILD_ROOT_TOP)/lib/Debug +PROJLIBRELEASESOURCE := $(BUILD_ROOT_TOP)/lib/Release +PROJLIBPROFILESOURCE := $(BUILD_ROOT_TOP)/lib/Profile +PROJLIBCURRENTSOURCE := $(BUILD_ROOT_TOP)/lib/$(CONFIGURATION) + +else + +LLVMLIBDEBUGSOURCE := $(BUILD_ROOT_TOP)/lib/Debug +LLVMLIBRELEASESOURCE := $(BUILD_ROOT_TOP)/lib/Release +LLVMLIBPROFILESOURCE := $(BUILD_ROOT_TOP)/lib/Profile +LLVMLIBCURRENTSOURCE := $(BUILD_ROOT_TOP)/lib/$(CONFIGURATION) +endif + TOOLDEBUG := $(BUILD_ROOT_TOP)/tools/Debug TOOLRELEASE := $(BUILD_ROOT_TOP)/tools/Release @@ -152,6 +180,13 @@ PROFILE = -pg endif +#if PROJDIR is defined then we include PROJ DIR includes and libraries +ifndef PROJ_COMPILE +PROJ_INCLUDE = "." +else +PROJ_INCLUDE = $(PROJ_DIR)/include +endif + # By default, strip symbol information from executable ifndef KEEP_SYMBOLS STRIP = $(PLATFORMSTRIPOPTS) @@ -162,7 +197,7 @@ CPPFLAGS += -D_GNU_SOURCE # -Wno-unused-parameter -CompileCommonOpts := -Wall -W -Wwrite-strings -Wno-unused -I$(LEVEL)/include +CompileCommonOpts := -Wall -W -Wwrite-strings -Wno-unused -I$(LEVEL)/include -I$(PROJ_INCLUDE) CompileOptimizeOpts := -O3 -DNDEBUG -finline-functions -fshort-enums # Compile a cpp file, don't link... @@ -185,9 +220,18 @@ else Link := $(CXX) endif -LinkG := $(Link) -g -L$(LIBDEBUG) $(STRIP) -LinkO := $(Link) -O3 -L$(LIBRELEASE) -LinkP := $(Link) -O3 -L$(LIBPROFILE) $(PROFILE) + +ifdef PROJ_COMPILE +LinkG := $(Link) -g -L$(PROJLIBDEBUGSOURCE) -L$(LLVMLIBDEBUGSOURCE) $(STRIP) +LinkO := $(Link) -O3 -L$(PROJLIBRELEASESOURCE) -L$(LLVMLIBRELEASESOURCE) +LinkP := $(Link) -O3 -L$(PROJLIBPROFILESOURCE) -L$(LLVMLIBPROFILESOURCE) $(PROFILE) +else +LinkG := $(Link) -g -L$(LLVMLIBDEBUGSOURCE) $(STRIP) +LinkO := $(Link) -O3 -L$(LLVMLIBRELEASESOURCE) +LinkP := $(Link) -O3 -L$(LLVMLIBPROFILESOURCE) $(PROFILE) +endif + + # Create one .o file from a bunch of .o files... Relink = ld -r @@ -198,8 +242,8 @@ MakeSOP := $(MakeSOO) $(PROFILE) # Create dependancy file from CPP file, send to stdout. -Depend := $(CXX) -MM -I$(LEVEL)/include $(CPPFLAGS) -DependC := $(CC) -MM -I$(LEVEL)/include $(CPPFLAGS) +Depend := $(CXX) -MM -I$(LEVEL)/include -I$(PROJ_INCLUDE) $(CPPFLAGS) +DependC := $(CC) -MM -I$(LEVEL)/include -I$(PROJ_INCLUDE) $(CPPFLAGS) # Archive a bunch of .o files into a .a file... AR = ar cq @@ -265,65 +309,65 @@ # Make sure there isn't any extranous whitespace on the LIBRARYNAME option LIBRARYNAME := $(strip $(LIBRARYNAME)) -LIBNAME_O := $(LIBRELEASE)/lib$(LIBRARYNAME).so -LIBNAME_P := $(LIBPROFILE)/lib$(LIBRARYNAME).so -LIBNAME_G := $(LIBDEBUG)/lib$(LIBRARYNAME).so -LIBNAME_AO := $(LIBRELEASE)/lib$(LIBRARYNAME).a -LIBNAME_AP := $(LIBPROFILE)/lib$(LIBRARYNAME).a -LIBNAME_AG := $(LIBDEBUG)/lib$(LIBRARYNAME).a -LIBNAME_OBJO := $(LIBRELEASE)/$(LIBRARYNAME).o -LIBNAME_OBJP := $(LIBPROFILE)/$(LIBRARYNAME).o -LIBNAME_OBJG := $(LIBDEBUG)/$(LIBRARYNAME).o +LIBNAME_O := $(DESTLIBRELEASE)/lib$(LIBRARYNAME).so +LIBNAME_P := $(DESTLIBPROFILE)/lib$(LIBRARYNAME).so +LIBNAME_G := $(DESTLIBDEBUG)/lib$(LIBRARYNAME).so +LIBNAME_AO := $(DESTLIBRELEASE)/lib$(LIBRARYNAME).a +LIBNAME_AP := $(DESTLIBPROFILE)/lib$(LIBRARYNAME).a +LIBNAME_AG := $(DESTLIBDEBUG)/lib$(LIBRARYNAME).a +LIBNAME_OBJO := $(DESTLIBRELEASE)/$(LIBRARYNAME).o +LIBNAME_OBJP := $(DESTLIBPROFILE)/$(LIBRARYNAME).o +LIBNAME_OBJG := $(DESTLIBDEBUG)/$(LIBRARYNAME).o # dynamic target builds a shared object version of the library... -dynamic:: $(LIBCURRENT)/lib$(LIBRARYNAME).so +dynamic:: $(DESTLIBCURRENT)/lib$(LIBRARYNAME).so # Does the library want a .o version built? ifndef DONT_BUILD_RELINKED -all:: $(LIBCURRENT)/$(LIBRARYNAME).o +all:: $(DESTLIBCURRENT)/$(LIBRARYNAME).o endif # Does the library want an archive version built? ifdef BUILD_ARCHIVE -all:: $(LIBCURRENT)/lib$(LIBRARYNAME).a +all:: $(DESTLIBCURRENT)/lib$(LIBRARYNAME).a endif -$(LIBNAME_O): $(ObjectsO) $(LibSubDirs) $(LIBRELEASE)/.dir +$(LIBNAME_O): $(ObjectsO) $(LibSubDirs) $(DESTLIBRELEASE)/.dir @echo ======= Linking $(LIBRARYNAME) release library ======= $(VERB) $(MakeSOO) -o $@ $(ObjectsO) $(LibSubDirs) $(LibLinkOpts) -$(LIBNAME_P): $(ObjectsP) $(LibSubDirs) $(LIBPROFILE)/.dir +$(LIBNAME_P): $(ObjectsP) $(LibSubDirs) $(DESTLIBPROFILE)/.dir @echo ======= Linking $(LIBRARYNAME) profile library ======= $(VERB) $(MakeSOP) -o $@ $(ObjectsP) $(LibSubDirs) $(LibLinkOpts) -$(LIBNAME_G): $(ObjectsG) $(LibSubDirs) $(LIBDEBUG)/.dir +$(LIBNAME_G): $(ObjectsG) $(LibSubDirs) $(DESTLIBDEBUG)/.dir @echo ======= Linking $(LIBRARYNAME) debug library ======= $(VERB) $(MakeSO) -g -o $@ $(ObjectsG) $(LibSubDirs) $(LibLinkOpts) -$(LIBNAME_AO): $(ObjectsO) $(LibSubDirs) $(LIBRELEASE)/.dir +$(LIBNAME_AO): $(ObjectsO) $(LibSubDirs) $(DESTLIBRELEASE)/.dir @echo ======= Linking $(LIBRARYNAME) release library ======= @rm -f $@ $(VERB) $(AR) $@ $(ObjectsO) $(LibSubDirs) -$(LIBNAME_AP): $(ObjectsP) $(LibSubDirs) $(LIBPROFILE)/.dir +$(LIBNAME_AP): $(ObjectsP) $(LibSubDirs) $(DESTLIBPROFILE)/.dir @echo ======= Linking $(LIBRARYNAME) profile library ======= @rm -f $@ $(VERB) $(AR) $@ $(ObjectsP) $(LibSubDirs) -$(LIBNAME_AG): $(ObjectsG) $(LibSubDirs) $(LIBDEBUG)/.dir +$(LIBNAME_AG): $(ObjectsG) $(LibSubDirs) $(DESTLIBDEBUG)/.dir @echo ======= Linking $(LIBRARYNAME) debug library ======= @rm -f $@ $(VERB) $(AR) $@ $(ObjectsG) $(LibSubDirs) -$(LIBNAME_OBJO): $(ObjectsO) $(LibSubDirs) $(LIBRELEASE)/.dir +$(LIBNAME_OBJO): $(ObjectsO) $(LibSubDirs) $(DESTLIBRELEASE)/.dir @echo "Linking $@" $(VERB) $(Relink) -o $@ $(ObjectsO) $(LibSubDirs) -$(LIBNAME_OBJP): $(ObjectsP) $(LibSubDirs) $(LIBPROFILE)/.dir +$(LIBNAME_OBJP): $(ObjectsP) $(LibSubDirs) $(DESTLIBPROFILE)/.dir @echo "Linking $@" $(VERB) $(Relink) -o $@ $(ObjectsP) $(LibSubDirs) -$(LIBNAME_OBJG): $(ObjectsG) $(LibSubDirs) $(LIBDEBUG)/.dir +$(LIBNAME_OBJG): $(ObjectsG) $(LibSubDirs) $(DESTLIBDEBUG)/.dir @echo "Linking $@" $(VERB) $(Relink) -o $@ $(ObjectsG) $(LibSubDirs) @@ -357,10 +401,37 @@ TOOLEXENAMES := $(BUILD_ROOT_TOP)/tools/$(CONFIGURATION)/$(TOOLNAME) # USED_LIBS_OPTIONS - Compute the options line that add -llib1 -llib2, etc. -USED_LIBS_OPTIONS := $(patsubst %.a.o, -l%, $(addsuffix .o, $(USEDLIBS))) -USED_LIBS_OPTIONS_G := $(patsubst %.o, $(LIBDEBUG)/%.o, $(USED_LIBS_OPTIONS)) -USED_LIBS_OPTIONS_O := $(patsubst %.o, $(LIBRELEASE)/%.o,$(USED_LIBS_OPTIONS)) -USED_LIBS_OPTIONS_P := $(patsubst %.o, $(LIBPROFILE)/%.o,$(USED_LIBS_OPTIONS)) +ifdef PROJ_COMPILE + +PROJ_LIBS_OPTIONS := $(patsubst %.a.o, -l%, $(addsuffix .o, $(USEDLIBS))) +PROJ_LIBS_OPTIONS_G := $(patsubst %.o, $(PROJLIBDEBUGSOURCE)/%.o, $(PROJ_LIBS_OPTIONS)) +PROJ_LIBS_OPTIONS_O := $(patsubst %.o, $(PROJLIBRELEASESOURCE)/%.o,$(PROJ_LIBS_OPTIONS)) +PROJ_LIBS_OPTIONS_P := $(patsubst %.o, $(PROJLIBPROFILESOURCE)/%.o,$(PROJ_LIBS_OPTIONS)) + +LLVM_LIBS_OPTIONS := $(patsubst %.a.o, -l%, $(addsuffix .o, $(LLVMLIBS))) +LLVM_LIBS_OPTIONS_G := $(patsubst %.o, $(LLVMLIBDEBUGSOURCE)/%.o, $(LLVM_LIBS_OPTIONS)) +LLVM_LIBS_OPTIONS_O := $(patsubst %.o, $(LLVMLIBRELEASESOURCE)/%.o,$(LLVM_LIBS_OPTIONS)) +LLVM_LIBS_OPTIONS_P := $(patsubst %.o, $(LLVMLIBPROFILESOURCE)/%.o,$(LLVM_LIBS_OPTIONS)) + +LIB_OPTS_G := $(LLVM_LIBS_OPTIONS_G) $(PROJ_LIBS_OPTIONS_G) +LIB_OPTS_O := $(LLVM_LIBS_OPTIONS_O) $(PROJ_LIBS_OPTIONS_P) +LIB_OPTS_P := $(LLVM_LIBS_OPTIONS_P) $(PROJ_LIBS_OPTIONS_P) + +else + +LLVM_LIBS_OPTIONS := $(patsubst %.a.o, -l%, $(addsuffix .o, $(USEDLIBS))) +LLVM_LIBS_OPTIONS_G := $(patsubst %.o, $(LLVMLIBDEBUGSOURCE)/%.o, $(LLVM_LIBS_OPTIONS)) +LLVM_LIBS_OPTIONS_O := $(patsubst %.o, $(LLVMLIBRELEASESOURCE)/%.o,$(LLVM_LIBS_OPTIONS)) +LLVM_LIBS_OPTIONS_P := $(patsubst %.o, $(LLVMLIBPROFILESOURCE)/%.o,$(LLVM_LIBS_OPTIONS)) + +LIB_OPTS_G := $(LLVM_LIBS_OPTIONS_G) +LIB_OPTS_O := $(LLVM_LIBS_OPTIONS_O) +LIB_OPTS_P := $(LLVM_LIBS_OPTIONS_P) +endif + + + + # USED_LIB_PATHS - Compute the path of the libraries used so that tools are @@ -368,12 +439,16 @@ # files seperately. # STATICUSEDLIBS := $(patsubst %.a.o, lib%.a, $(addsuffix .o, $(USEDLIBS))) -USED_LIB_PATHS_G := $(addprefix $(LIBDEBUG)/, $(STATICUSEDLIBS)) -USED_LIB_PATHS_O := $(addprefix $(LIBRELEASE)/, $(STATICUSEDLIBS)) -USED_LIB_PATHS_P := $(addprefix $(LIBPROFILE)/, $(STATICUSEDLIBS)) +USED_LIB_PATHS_G := $(addprefix $(DESTLIBDEBUG)/, $(STATICUSEDLIBS)) +USED_LIB_PATHS_O := $(addprefix $(DESTLIBRELEASE)/, $(STATICUSEDLIBS)) +USED_LIB_PATHS_P := $(addprefix $(DESTLIBPROFILE)/, $(STATICUSEDLIBS)) LINK_OPTS := $(TOOLLINKOPTS) $(PLATFORMLINKOPTS) + + + + # Tell make that we need to rebuild subdirectories before we can link the tool. # This affects things like LLI which has library subdirectories. $(USED_LIB_PATHS_G) $(USED_LIB_PATHS_O) $(USED_LIB_PATHS_P): \ @@ -384,16 +459,16 @@ $(VERB) rm -f $(TOOLEXENAMES) $(TOOLEXENAME_G): $(ObjectsG) $(USED_LIB_PATHS_G) $(TOOLDEBUG)/.dir - @echo ======= Linking $(TOOLNAME) debug executable $(STRIP_WARN_MSG) ======= - $(VERB) $(LinkG) -o $@ $(ObjectsG) $(USED_LIBS_OPTIONS_G) $(LINK_OPTS) + @echo ======= Linking $(TOOLNAME) debug executable $(STRIP_WARN_MSG)======= + $(VERB) $(LinkG) -o $@ $(ObjectsG) $(LIB_OPTS_G) $(LINK_OPTS) $(TOOLEXENAME_O): $(ObjectsO) $(USED_LIB_PATHS_O) $(TOOLRELEASE)/.dir @echo ======= Linking $(TOOLNAME) release executable ======= - $(VERB) $(LinkO) -o $@ $(ObjectsO) $(USED_LIBS_OPTIONS_O) $(LINK_OPTS) + $(VERB) $(LinkO) -o $@ $(ObjectsO) $(LIB_OPTS_O) $(LINK_OPTS) $(TOOLEXENAME_P): $(ObjectsP) $(USED_LIB_PATHS_P) $(TOOLPROFILE)/.dir @echo ======= Linking $(TOOLNAME) profile executable ======= - $(VERB) $(LinkP) -o $@ $(ObjectsP) $(USED_LIBS_OPTIONS_P) $(LINK_OPTS) + $(VERB) $(LinkP) -o $@ $(ObjectsP) $(LIB_OPTS_P) $(LINK_OPTS) endif From brukman at cs.uiuc.edu Thu May 29 13:49:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu May 29 13:49:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Target.td Message-ID: <200305291848.NAA24951@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target: Target.td added (r1.1) --- Log message: Added the target-independent part of TableGen data. --- Diffs of the changes: Index: llvm/lib/Target/Target.td diff -c /dev/null llvm/lib/Target/Target.td:1.1 *** /dev/null Thu May 29 13:48:27 2003 --- llvm/lib/Target/Target.td Thu May 29 13:48:17 2003 *************** *** 0 **** --- 1,26 ---- + //===- Sparc.td - Target Description for Sparc V9 Target --------*- C++ -*-===// + // vim:ft=cpp + //===----------------------------------------------------------------------===// + + //===----------------------------------------------------------------------===// + // Target-Independent interface + //===----------------------------------------------------------------------===// + + class Register { + string Namespace = ""; + int Size; + } + + class Instruction { + string Name; // The opcode string for this instruction + string Namespace = ""; + + list Uses = []; // Default to using no non-operand registers + list Defs = []; // Default to modifying no non-operand registers + + // These bits capture information about the high-level semantics of the + // instruction. + bit isReturn = 0; // Is this instruction a return instruction? + bit isBranch = 0; // Is this instruction a branch instruction? + bit isCall = 0; // Is this instruction a call instruction? + } From criswell at cs.uiuc.edu Thu May 29 13:52:02 2003 From: criswell at cs.uiuc.edu (John Criswell) Date: Thu May 29 13:52:02 2003 Subject: [llvm-commits] CVS: llvm/Makefile.config Message-ID: <200305291851.NAA27468@choi.cs.uiuc.edu> Changes in directory llvm: Makefile.config updated: 1.11 -> 1.12 --- Log message: Moved the FLEX and BISON macros from Makefile.common since they are configuration options like CC and CXX. Updated LLVMGCCDIR so that it refers to the valid LLVM gcc code. Added pathnames and flags to be used by some of the tests. Moved configuration options from Makefile.common to here since they should all be in one place. --- Diffs of the changes: Index: llvm/Makefile.config diff -u llvm/Makefile.config:1.11 llvm/Makefile.config:1.12 --- llvm/Makefile.config:1.11 Fri Jan 17 11:36:47 2003 +++ llvm/Makefile.config Thu May 29 13:51:11 2003 @@ -18,6 +18,12 @@ # CC := PATH=/usr/bin /usr/dcs/software/evaluation/bin/gcc +# +# The pathnames of the Flex and Bison programs, respectively. +# +BISON = bison +FLEX = flex + # Path to directory where object files should be stored during a build. # Set LLVM_OBJ_DIR to "." if you do not want to use a separate place for # object files. @@ -28,7 +34,7 @@ # Path to location for LLVM front-end this should only be specified here if you # want to override the value set in Makefile.$(uname) # -#LLVMGCCDIR := /home/vadve/lattner/cvs/gcc_install_x86 +#LLVMGCCDIR := /home/vadve/lattner/local/x86/llvm-gcc/ # When this setting is set to true, programs in the llvm/test/Programs hierarchy # are not recompiled from source code. Instead, the bytecode for the file is @@ -49,3 +55,46 @@ # ENABLE_PURIFY=1 # PURIFY = /usr/dcs/applications/purify/bin/purify + +# +# SPEC benchmarks: +# Set this variable to enable the use of the SPEC benchmarks. You must +# provide the SPEC benchmarks on your own. +# +USE_SPEC := 1 + +# +# Path to the SPEC benchmarks. If you have the SPEC benchmarks, place the +# path here. +# +SPEC_ROOT := /home/vadve/shared/benchmarks/speccpu2000/benchspec + +# +# Path to the PAPI code. +# +PAPIDIR := /home/vadve/shared/papi-2.3.4.1 + +# These are options that can either be enabled here, or can be enabled on the +# make command line (ie, make ENABLE_PROFILING=1) +# + +# When ENABLE_PROFILING is enabled, the llvm source base is built with profile +# information to allow gprof to be used to get execution frequencies. +# +#ENABLE_PROFILING = 1 + +# When ENABLE_PURIFY is enabled, the LLVM tools are linked with purify (which +# must be locally installed) to allow for some automated memory error debugging. +# +#ENABLE_PURIFY = 1 + +# When ENABLE_OPTIMIZED is enabled, Release builds of all of the LLVM code are +# turned on, and Debug builds are turned off. +# +#ENABLE_OPTIMIZED = 1 + +# +# This open tells the Makefiles to produce verbose output. +# It essentially prints the commands that make is executing +# +#VERBOSE = 1 From criswell at cs.uiuc.edu Thu May 29 13:53:01 2003 From: criswell at cs.uiuc.edu (John Criswell) Date: Thu May 29 13:53:01 2003 Subject: [llvm-commits] CVS: llvm/Makefile.common Message-ID: <200305291852.NAA27480@choi.cs.uiuc.edu> Changes in directory llvm: Makefile.common updated: 1.82 -> 1.83 --- Log message: Removed configuration options that are better served in Makefile.config. Fixed the LibInstDir macro. Added the use of the FLEX variable. --- Diffs of the changes: Index: llvm/Makefile.common diff -u llvm/Makefile.common:1.82 llvm/Makefile.common:1.83 --- llvm/Makefile.common:1.82 Thu May 29 11:18:20 2003 +++ llvm/Makefile.common Thu May 29 13:52:10 2003 @@ -36,26 +36,6 @@ # include $(LEVEL)/Makefile.config -# These are options that can either be enabled here, or can be enabled on the -# make command line (ie, make ENABLE_PROFILING=1) -# - -# When ENABLE_PROFILING is enabled, the llvm source base is built with profile -# information to allow gprof to be used to get execution frequencies. -# -#ENABLE_PROFILING = 1 - -# When ENABLE_PURIFY is enabled, the LLVM tools are linked with purify (which -# must be locally installed) to allow for some automated memory error debugging. -# -#ENABLE_PURIFY = 1 - -# When ENABLE_OPTIMIZED is enabled, Release builds of all of the LLVM code are -# turned on, and Debug builds are turned off. -# -#ENABLE_OPTIMIZED = 1 - - # Figure out how to do platform specific stuff on this platform. This is really # gross and should be autoconfiscated (automake actually), but should hopefully # work on Linux and solaris (SunOS). @@ -109,7 +89,7 @@ #-------------------------------------------------------------------- #BinInstDir=/usr/local/bin -#LibInstDir=/usrl/local/lib/xxx +#LibInstDir=/usr/local/lib/xxx #DocInstDir=/usr/doc/xxx BURG_OPTS = -I @@ -247,7 +227,6 @@ # Archive a bunch of .o files into a .a file... AR = ar cq -BISON = bison #---------------------------------------------------------- @@ -519,7 +498,7 @@ # FIXME. (f.e. char Buffer[10000]; ) # %.cpp: %.l - flex -t $< | sed '/^find_rule/d' | \ + $(FLEX) -t $< | sed '/^find_rule/d' | \ sed 's/void yyunput/inline void yyunput/' | \ sed 's/void \*yy_flex_realloc/inline void *yy_flex_realloc/' | \ sed 's/#define YY_BUF_SIZE 16384/#define YY_BUF_SIZE (16384*64)/' > $@ From criswell at cs.uiuc.edu Thu May 29 13:56:00 2003 From: criswell at cs.uiuc.edu (John Criswell) Date: Thu May 29 13:56:00 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/NoSource/SPEC/Makefile.spec Message-ID: <200305291855.NAA27502@choi.cs.uiuc.edu> Changes in directory llvm/test/Programs/NoSource/SPEC: Makefile.spec updated: 1.4 -> 1.5 --- Log message: Modified the Makefile so that it uses SPEC_ROOT from the master Makefile.config to determine the location of the SPEC benchmarks. --- Diffs of the changes: Index: llvm/test/Programs/NoSource/SPEC/Makefile.spec diff -u llvm/test/Programs/NoSource/SPEC/Makefile.spec:1.4 llvm/test/Programs/NoSource/SPEC/Makefile.spec:1.5 --- llvm/test/Programs/NoSource/SPEC/Makefile.spec:1.4 Fri Jan 17 12:56:06 2003 +++ llvm/test/Programs/NoSource/SPEC/Makefile.spec Thu May 29 13:54:56 2003 @@ -28,10 +28,8 @@ ##--- SPEC-dependent rules to do a test run or a reportable reference run -SPECROOT := /home/vadve/shared/benchmarks/speccpu2000/benchspec - # DATADIR - The directory holding expected SPEC benchmark results -DATADIR := $(SPECROOT)/CINT2000/$(PROG)/data +DATADIR := $(SPEC_ROOT)/CINT2000/$(PROG)/data data: @test -L data || ln -s $(DATADIR) From criswell at cs.uiuc.edu Thu May 29 13:57:01 2003 From: criswell at cs.uiuc.edu (John Criswell) Date: Thu May 29 13:57:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Reoptimizer/Makefile.mk Message-ID: <200305291856.NAA27518@choi.cs.uiuc.edu> Changes in directory llvm/test/Regression/Reoptimizer: Makefile.mk updated: 1.2 -> 1.3 --- Log message: The Makefile now grabs the location in which to build from the master Makefile.config (via the LLVM_OBJ_DIR environment variable). --- Diffs of the changes: Index: llvm/test/Regression/Reoptimizer/Makefile.mk diff -u llvm/test/Regression/Reoptimizer/Makefile.mk:1.2 llvm/test/Regression/Reoptimizer/Makefile.mk:1.3 --- llvm/test/Regression/Reoptimizer/Makefile.mk:1.2 Mon Oct 21 18:56:53 2002 +++ llvm/test/Regression/Reoptimizer/Makefile.mk Thu May 29 13:56:21 2003 @@ -4,7 +4,7 @@ # find the src and obj root directories LEVEL := ../../../.. -OBJ_ROOT := /localhome/$(USER) +OBJ_ROOT := $(LLVM_OBJ_DIR) LLVM_SRC = $(shell cd $(LEVEL); pwd) LLVM_OBJ = $(OBJ_ROOT)$(patsubst $(HOME)%,%,$(LLVM_SRC)) LLVM_LIB := $(LLVM_OBJ)/lib/Debug From criswell at cs.uiuc.edu Thu May 29 13:59:00 2003 From: criswell at cs.uiuc.edu (John Criswell) Date: Thu May 29 13:59:00 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/rtl/Makefile Message-ID: <200305291858.NAA27536@choi.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst/rtl: Makefile updated: 1.3 -> 1.4 --- Log message: Removed the definition of PAPIDIR. It now fetches the value from the master Makefile.config. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/rtl/Makefile diff -u llvm/lib/Reoptimizer/Inst/rtl/Makefile:1.3 llvm/lib/Reoptimizer/Inst/rtl/Makefile:1.4 --- llvm/lib/Reoptimizer/Inst/rtl/Makefile:1.3 Thu May 22 22:26:13 2003 +++ llvm/lib/Reoptimizer/Inst/rtl/Makefile Thu May 29 13:58:12 2003 @@ -1,7 +1,6 @@ LEVEL = ../../../.. LIBRARYNAME = pprtl BUILD_ARCHIVE = 1 -PAPIDIR = /home/vadve/shared/papi-2.3.4.1 CPPFLAGS += -D_BUILDING_RUNTIME_LIBRARY_ -I$(PAPIDIR)/include CXXFLAGS += -D_BUILDING_RUNTIME_LIBRARY_ -I$(PAPIDIR)/include From criswell at cs.uiuc.edu Thu May 29 14:02:02 2003 From: criswell at cs.uiuc.edu (John Criswell) Date: Thu May 29 14:02:02 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/External/SPEC/Makefile.spec Message-ID: <200305291901.OAA27598@choi.cs.uiuc.edu> Changes in directory llvm/test/Programs/External/SPEC: Makefile.spec updated: 1.4 -> 1.5 --- Log message: Removed the definition of SPEC_ROOT. The master Makefile.config now defines it for us. --- Diffs of the changes: Index: llvm/test/Programs/External/SPEC/Makefile.spec diff -u llvm/test/Programs/External/SPEC/Makefile.spec:1.4 llvm/test/Programs/External/SPEC/Makefile.spec:1.5 --- llvm/test/Programs/External/SPEC/Makefile.spec:1.4 Thu May 29 10:18:30 2003 +++ llvm/test/Programs/External/SPEC/Makefile.spec Thu May 29 14:01:13 2003 @@ -4,9 +4,6 @@ # ##===----------------------------------------------------------------------===## -# Configuration item: Where to find the spec CD-ROM -SPEC_ROOT := /home/vadve/shared/benchmarks/speccpu2000/benchspec - # RUN_TYPE - Either ref, test, or train. May be specified on the command line. RUN_TYPE := test From lattner at cs.uiuc.edu Thu May 29 14:18:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 29 14:18:01 2003 Subject: [llvm-commits] CVS: llvm/Makefile.config Message-ID: <200305291917.OAA21552@apoc.cs.uiuc.edu> Changes in directory llvm: Makefile.config updated: 1.12 -> 1.13 --- Log message: Minor reordering of options --- Diffs of the changes: Index: llvm/Makefile.config diff -u llvm/Makefile.config:1.12 llvm/Makefile.config:1.13 --- llvm/Makefile.config:1.12 Thu May 29 13:51:11 2003 +++ llvm/Makefile.config Thu May 29 14:16:55 2003 @@ -70,7 +70,7 @@ SPEC_ROOT := /home/vadve/shared/benchmarks/speccpu2000/benchspec # -# Path to the PAPI code. +# Path to the PAPI code. This is used by the reoptimizer only. # PAPIDIR := /home/vadve/shared/papi-2.3.4.1 @@ -78,23 +78,24 @@ # make command line (ie, make ENABLE_PROFILING=1) # -# When ENABLE_PROFILING is enabled, the llvm source base is built with profile -# information to allow gprof to be used to get execution frequencies. -# -#ENABLE_PROFILING = 1 - -# When ENABLE_PURIFY is enabled, the LLVM tools are linked with purify (which -# must be locally installed) to allow for some automated memory error debugging. -# -#ENABLE_PURIFY = 1 - # When ENABLE_OPTIMIZED is enabled, Release builds of all of the LLVM code are # turned on, and Debug builds are turned off. # #ENABLE_OPTIMIZED = 1 +# When ENABLE_PROFILING is enabled, the llvm source base is built with profile +# information to allow gprof to be used to get execution frequencies. +# +#ENABLE_PROFILING = 1 + # # This open tells the Makefiles to produce verbose output. # It essentially prints the commands that make is executing # #VERBOSE = 1 + +# When ENABLE_PURIFY is enabled, the LLVM tools are linked with purify (which +# must be locally installed) to allow for some automated memory error debugging. +# +#ENABLE_PURIFY = 1 + From lattner at cs.uiuc.edu Thu May 29 14:19:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 29 14:19:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/DSAnalysis/fieldmerge.ll structpadding.ll Message-ID: <200305291918.OAA21569@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/DSAnalysis: fieldmerge.ll added (r1.1) structpadding.ll added (r1.1) --- Log message: Check in old tests --- Diffs of the changes: Index: llvm/test/Regression/Transforms/DSAnalysis/fieldmerge.ll diff -c /dev/null llvm/test/Regression/Transforms/DSAnalysis/fieldmerge.ll:1.1 *** /dev/null Thu May 29 14:18:01 2003 --- llvm/test/Regression/Transforms/DSAnalysis/fieldmerge.ll Thu May 29 14:17:51 2003 *************** *** 0 **** --- 1,18 ---- + + %str = type { int*, int* } + + implementation + + void %bar(%str* %S, bool %C) { + br bool %C, label %T, label %F + T: + %A = getelementptr %str* %S, long 0, ubyte 0 + br label %Out + F: + %B = getelementptr %str* %S, long 0, ubyte 1 + br label %Out + Out: + %P = phi int** [%A, %T], [%B, %F] + store int* null, int** %P + ret void + } Index: llvm/test/Regression/Transforms/DSAnalysis/structpadding.ll diff -c /dev/null llvm/test/Regression/Transforms/DSAnalysis/structpadding.ll:1.1 *** /dev/null Thu May 29 14:18:01 2003 --- llvm/test/Regression/Transforms/DSAnalysis/structpadding.ll Thu May 29 14:17:51 2003 *************** *** 0 **** --- 1,18 ---- + + %str = type { int, int* } + + implementation + + void %bar(%str* %S, %str* %T) { + %A1 = getelementptr %str* %S, long 0, ubyte 0 + %B1 = getelementptr %str* %S, long 0, ubyte 1 + %A2 = getelementptr %str* %S, long 0, ubyte 0 + %B2 = getelementptr %str* %S, long 0, ubyte 1 + %a1 = cast int* %A1 to long* + %a2 = cast int* %A2 to long* + %V = load long* %a1 + ;store long %V, long* %a2 + %V2 = load int** %B1 + store int* %V2, int** %B2 + ret void + } From brukman at cs.uiuc.edu Thu May 29 15:10:05 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu May 29 15:10:05 2003 Subject: [llvm-commits] CVS: llvm/Makefile.common Message-ID: <200305292009.PAA25230@zion.cs.uiuc.edu> Changes in directory llvm: Makefile.common updated: 1.83 -> 1.84 --- Log message: Added a path to the current version of the built TableGen. --- Diffs of the changes: Index: llvm/Makefile.common diff -u llvm/Makefile.common:1.83 llvm/Makefile.common:1.84 --- llvm/Makefile.common:1.83 Thu May 29 13:52:10 2003 +++ llvm/Makefile.common Thu May 29 15:09:23 2003 @@ -153,6 +153,7 @@ BURG := $(TOOLCURRENT)/burg RunBurg := $(BURG) $(BURG_OPTS) +TBLGEN := $(TOOLCURRENT)/tblgen # Enable this for profiling support with 'gprof' # This automatically enables optimized builds. From brukman at cs.uiuc.edu Thu May 29 15:11:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu May 29 15:11:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/Makefile Message-ID: <200305292010.PAA25243@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: Makefile updated: 1.18 -> 1.19 --- Log message: Use an absolute path to TableGen because not everyone (e.g. automatic tester) has their path set up by this point. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/Makefile diff -u llvm/lib/Target/Sparc/Makefile:1.18 llvm/lib/Target/Sparc/Makefile:1.19 --- llvm/lib/Target/Sparc/Makefile:1.18 Thu May 29 00:29:22 2003 +++ llvm/lib/Target/Sparc/Makefile Thu May 29 15:09:56 2003 @@ -38,7 +38,7 @@ SparcV9CodeEmitter.inc: SparcV9.td @echo "TableGen-erating $@" - cpp -P SparcV9.td | tblgen -gen-emitter > $(TEMP_EMITTER_INC) + cpp -P SparcV9.td | $(TBLGEN) -gen-emitter > $(TEMP_EMITTER_INC) mv -f $(TEMP_EMITTER_INC) SparcV9CodeEmitter.inc clean:: From lattner at cs.uiuc.edu Thu May 29 15:16:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 29 15:16:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/CorrelatedExprs/2002-10-08-DominatorTest.ll 2002-10-08-DominatorTest2.ll Message-ID: <200305292015.PAA22015@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/CorrelatedExprs: 2002-10-08-DominatorTest.ll added (r1.1) 2002-10-08-DominatorTest2.ll added (r1.1) --- Log message: New testcases --- Diffs of the changes: Index: llvm/test/Regression/Transforms/CorrelatedExprs/2002-10-08-DominatorTest.ll diff -c /dev/null llvm/test/Regression/Transforms/CorrelatedExprs/2002-10-08-DominatorTest.ll:1.1 *** /dev/null Thu May 29 15:15:45 2003 --- llvm/test/Regression/Transforms/CorrelatedExprs/2002-10-08-DominatorTest.ll Thu May 29 15:15:35 2003 *************** *** 0 **** --- 1,32 ---- + ; Test to make sure that SSA is correctly updated + ; RUN: as < %s | opt -cee + ; + implementation ; Functions: + + int %test(int %A, int %B, bool %c0) { + Start: ; No predecessors! + %c1 = seteq int %A, %B ; [#uses=1] + br bool %c1, label %Eq, label %Start_crit_edge + + Start_crit_edge: ; preds = %Start + br label %Loop + + Eq: ; preds = %Start + br label %Loop + + Loop: ; preds = %Bottom, %Eq, %Start_crit_edge + %Z = phi int [ %A, %Start_crit_edge ], [ %B, %Eq ], [ %Z, %Bottom ] ; [#uses=2] + %c2 = setge int %A, %B ; [#uses=1] + br bool %c2, label %Forwarded, label %Loop_crit_edge + + Loop_crit_edge: ; preds = %Loop + br label %Bottom + + Forwarded: ; preds = %Loop + %Z2 = phi int [ %Z, %Loop ] ; [#uses=1] + call int %test( int 0, int %Z2, bool true ) ; :0 [#uses=0] + br label %Bottom + + Bottom: ; preds = %Forwarded, %Loop_crit_edge + br label %Loop + } Index: llvm/test/Regression/Transforms/CorrelatedExprs/2002-10-08-DominatorTest2.ll diff -c /dev/null llvm/test/Regression/Transforms/CorrelatedExprs/2002-10-08-DominatorTest2.ll:1.1 *** /dev/null Thu May 29 15:15:45 2003 --- llvm/test/Regression/Transforms/CorrelatedExprs/2002-10-08-DominatorTest2.ll Thu May 29 15:15:35 2003 *************** *** 0 **** --- 1,34 ---- + ; Simple test to make sure dominators are updated properly + ; RUN: as < %s | opt -cee + + implementation ; Functions: + + int %test(int %A, int %B, bool %c0) { + Start: ; No predecessors! + %c1 = seteq int %A, %B ; [#uses=1] + br bool %c1, label %Eq, label %Start_crit_edge + + Start_crit_edge: ; preds = %Start + br label %Loop + + Eq: ; preds = %Start + br label %Loop + + Loop: ; preds = %Bottom, %Eq, %Start_crit_edge + %Z = phi int [ %A, %Start_crit_edge ], [ %B, %Eq ];, [ %Z, %Bottom ] ; [#uses=2] + %c2 = setge int %A, %B ; [#uses=1] + br bool %c2, label %Forwarded, label %Loop_crit_edge + + Loop_crit_edge: ; preds = %Loop + %X = seteq int %Z, 7 + br bool %X, label %Forwarded, label %Bottom + + Forwarded: ; preds = %Loop + %Z2 = phi int [ %Z, %Loop ], [%Z, %Loop_crit_edge] ; [#uses=1] + call int %test( int %Z, int %Z2, bool true ) ; :0 [#uses=0] + br label %Bottom + + Bottom: ; preds = %Forwarded, %Loop_crit_edge + ret int %Z + ;br label %Loop + } From brukman at cs.uiuc.edu Thu May 29 15:16:06 2003 From: brukman at cs.uiuc.edu (Michael Brukman) Date: Thu May 29 15:16:06 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/.cvsignore Message-ID: <200305292015.PAA09706@trinity.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: .cvsignore updated: 1.1 -> 1.2 --- Log message: Since there is now another derived .inc file, ignore them all. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/.cvsignore diff -u llvm/lib/Target/Sparc/.cvsignore:1.1 llvm/lib/Target/Sparc/.cvsignore:1.2 --- llvm/lib/Target/Sparc/.cvsignore:1.1 Tue May 27 15:07:58 2003 +++ llvm/lib/Target/Sparc/.cvsignore Thu May 29 15:15:27 2003 @@ -1 +1 @@ -SparcV9CodeEmitter.inc +*.inc From lattner at cs.uiuc.edu Thu May 29 15:25:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 29 15:25:02 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/External/Makefile.external Message-ID: <200305292024.PAA22339@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/External: Makefile.external added (r1.1) --- Log message: Checkin file --- Diffs of the changes: Index: llvm/test/Programs/External/Makefile.external diff -c /dev/null llvm/test/Programs/External/Makefile.external:1.1 *** /dev/null Thu May 29 15:24:21 2003 --- llvm/test/Programs/External/Makefile.external Thu May 29 15:24:10 2003 *************** *** 0 **** --- 1,10 ---- + ##===- test/Programs/SingleSource/Makefile.external --------*- Makefile -*-===## + # + # This makefile is used to build programs that are not directly in the LLVM + # build system. It relies on a set of external makefiles to build the program, + # then imports the resultant bytecode file for use with the normal LLVM scripts. + # + ##===----------------------------------------------------------------------===## + + include $(LEVEL)/test/Programs/Makefile.programs + .PRECIOUS: Output/%.linked.rll From lattner at cs.uiuc.edu Thu May 29 15:26:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 29 15:26:02 2003 Subject: [llvm-commits] CVS: llvm/test/Libraries/libc/qsort.c Message-ID: <200305292025.PAA22362@apoc.cs.uiuc.edu> Changes in directory llvm/test/Libraries/libc: qsort.c added (r1.1) --- Log message: Initial checkin --- Diffs of the changes: Index: llvm/test/Libraries/libc/qsort.c diff -c /dev/null llvm/test/Libraries/libc/qsort.c:1.1 *** /dev/null Thu May 29 15:25:04 2003 --- llvm/test/Libraries/libc/qsort.c Thu May 29 15:24:54 2003 *************** *** 0 **** --- 1,251 ---- + /* Copyright (C) 1991, 1992, 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Douglas C. Schmidt (schmidt at ics.uci.edu). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + /* If you consider tuning this algorithm, you should consult first: + Engineering a sort function; Jon Bentley and M. Douglas McIlroy; + Software - Practice and Experience; Vol. 23 (11), 1249-1265, 1993. */ + + #if 0 + + #include + #include + #include + + /* Byte-wise swap two items of size SIZE. */ + #define SWAP(a, b, size) \ + do \ + { \ + register size_t __size = (size); \ + register char *__a = (a), *__b = (b); \ + do \ + { \ + char __tmp = *__a; \ + *__a++ = *__b; \ + *__b++ = __tmp; \ + } while (--__size > 0); \ + } while (0) + + /* Discontinue quicksort algorithm when partition gets below this size. + This particular magic number was chosen to work best on a Sun 4/260. */ + #define MAX_THRESH 4 + + /* Stack node declarations used to store unfulfilled partition obligations. */ + typedef struct + { + char *lo; + char *hi; + } stack_node; + + /* The next 4 #defines implement a very fast in-line stack abstraction. */ + /* The stack needs log (total_elements) entries (we could even subtract + log(MAX_THRESH)). Since total_elements has type size_t, we get as + upper bound for log (total_elements): + bits per byte (CHAR_BIT) * sizeof(size_t). */ + #define STACK_SIZE (CHAR_BIT * sizeof(size_t)) + #define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top)) + #define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi))) + #define STACK_NOT_EMPTY (stack < top) + + + /* Order size using quicksort. This implementation incorporates + four optimizations discussed in Sedgewick: + + 1. Non-recursive, using an explicit stack of pointer that store the + next array partition to sort. To save time, this maximum amount + of space required to store an array of SIZE_MAX is allocated on the + stack. Assuming a 32-bit (64 bit) integer for size_t, this needs + only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes). + Pretty cheap, actually. + + 2. Chose the pivot element using a median-of-three decision tree. + This reduces the probability of selecting a bad pivot value and + eliminates certain extraneous comparisons. + + 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving + insertion sort to order the MAX_THRESH items within each partition. + This is a big win, since insertion sort is faster for small, mostly + sorted array segments. + + 4. The larger of the two sub-partitions is always pushed onto the + stack first, with the algorithm then concentrating on the + smaller partition. This *guarantees* no more than log (total_elems) + stack size is needed (actually O(1) in this case)! */ + + typedef int(*__compar_fn_t)(const void *, const void *); + void + qsort (void *const pbase, size_t total_elems, size_t size, + __compar_fn_t cmp) + { + register char *base_ptr = (char *) pbase; + + const size_t max_thresh = MAX_THRESH * size; + + if (total_elems == 0) + /* Avoid lossage with unsigned arithmetic below. */ + return; + + if (total_elems > MAX_THRESH) + { + char *lo = base_ptr; + char *hi = &lo[size * (total_elems - 1)]; + stack_node stack[STACK_SIZE]; + stack_node *top = stack + 1; + + while (STACK_NOT_EMPTY) + { + char *left_ptr; + char *right_ptr; + + /* Select median value from among LO, MID, and HI. Rearrange + LO and HI so the three values are sorted. This lowers the + probability of picking a pathological pivot value and + skips a comparison for both the LEFT_PTR and RIGHT_PTR in + the while loops. */ + + char *mid = lo + size * ((hi - lo) / size >> 1); + + if ((*cmp) ((void *) mid, (void *) lo) < 0) + SWAP (mid, lo, size); + if ((*cmp) ((void *) hi, (void *) mid) < 0) + SWAP (mid, hi, size); + else + goto jump_over; + if ((*cmp) ((void *) mid, (void *) lo) < 0) + SWAP (mid, lo, size); + jump_over:; + + left_ptr = lo + size; + right_ptr = hi - size; + + /* Here's the famous ``collapse the walls'' section of quicksort. + Gotta like those tight inner loops! They are the main reason + that this algorithm runs much faster than others. */ + do + { + while ((*cmp) ((void *) left_ptr, (void *) mid) < 0) + left_ptr += size; + + while ((*cmp) ((void *) mid, (void *) right_ptr) < 0) + right_ptr -= size; + + if (left_ptr < right_ptr) + { + SWAP (left_ptr, right_ptr, size); + if (mid == left_ptr) + mid = right_ptr; + else if (mid == right_ptr) + mid = left_ptr; + left_ptr += size; + right_ptr -= size; + } + else if (left_ptr == right_ptr) + { + left_ptr += size; + right_ptr -= size; + break; + } + } + while (left_ptr <= right_ptr); + + /* Set up pointers for next iteration. First determine whether + left and right partitions are below the threshold size. If so, + ignore one or both. Otherwise, push the larger partition's + bounds on the stack and continue sorting the smaller one. */ + + if ((size_t) (right_ptr - lo) <= max_thresh) + { + if ((size_t) (hi - left_ptr) <= max_thresh) + /* Ignore both small partitions. */ + POP (lo, hi); + else + /* Ignore small left partition. */ + lo = left_ptr; + } + else if ((size_t) (hi - left_ptr) <= max_thresh) + /* Ignore small right partition. */ + hi = right_ptr; + else if ((right_ptr - lo) > (hi - left_ptr)) + { + /* Push larger left partition indices. */ + PUSH (lo, right_ptr); + lo = left_ptr; + } + else + { + /* Push larger right partition indices. */ + PUSH (left_ptr, hi); + hi = right_ptr; + } + } + } + + /* Once the BASE_PTR array is partially sorted by quicksort the rest + is completely sorted using insertion sort, since this is efficient + for partitions below MAX_THRESH size. BASE_PTR points to the beginning + of the array to sort, and END_PTR points at the very last element in + the array (*not* one beyond it!). */ + + #define min(x, y) ((x) < (y) ? (x) : (y)) + + { + char *const end_ptr = &base_ptr[size * (total_elems - 1)]; + char *tmp_ptr = base_ptr; + char *thresh = min(end_ptr, base_ptr + max_thresh); + register char *run_ptr; + + /* Find smallest element in first threshold and place it at the + array's beginning. This is the smallest array element, + and the operation speeds up insertion sort's inner loop. */ + + for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size) + if ((*cmp) ((void *) run_ptr, (void *) tmp_ptr) < 0) + tmp_ptr = run_ptr; + + if (tmp_ptr != base_ptr) + SWAP (tmp_ptr, base_ptr, size); + + /* Insertion sort, running from left-hand-side up to right-hand-side. */ + + run_ptr = base_ptr + size; + while ((run_ptr += size) <= end_ptr) + { + tmp_ptr = run_ptr - size; + while ((*cmp) ((void *) run_ptr, (void *) tmp_ptr) < 0) + tmp_ptr -= size; + + tmp_ptr += size; + if (tmp_ptr != run_ptr) + { + char *trav; + + trav = run_ptr + size; + while (--trav >= run_ptr) + { + char c = *trav; + char *hi, *lo; + + for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo) + *hi = *lo; + *hi = c; + } + } + } + } + } + #endif From lattner at cs.uiuc.edu Thu May 29 15:27:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 29 15:27:00 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/PRE.cpp Message-ID: <200305292026.PAA22387@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: PRE.cpp updated: 1.1 -> 1.2 --- Log message: Add comment --- Diffs of the changes: Index: llvm/lib/Transforms/Scalar/PRE.cpp diff -u llvm/lib/Transforms/Scalar/PRE.cpp:1.1 llvm/lib/Transforms/Scalar/PRE.cpp:1.2 --- llvm/lib/Transforms/Scalar/PRE.cpp:1.1 Mon Mar 31 13:55:43 2003 +++ llvm/lib/Transforms/Scalar/PRE.cpp Thu May 29 15:26:30 2003 @@ -307,6 +307,17 @@ std::vector Values; VN->getEqualNumberNodes(Expr, Values); +#if 0 + // FIXME: This should handle PHI nodes correctly. To do this, we need to + // consider expressions of the following form equivalent to this set of + // expressions: + // + // If an operand is a PHI node, add any occurances of the expression with the + // PHI operand replaced with the PHI node operands. This is only valid if the + // PHI operand occurances exist in blocks post-dominated by the incoming edge + // of the PHI node. +#endif + // We have to be careful to handle expression definitions which dominated by // other expressions. These can be directly eliminated in favor of their // dominating value. Keep track of which blocks contain definitions (the key) From lattner at cs.uiuc.edu Thu May 29 15:41:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 29 15:41:01 2003 Subject: [llvm-commits] CVS: llvm/Makefile.common Message-ID: <200305292040.PAA24676@apoc.cs.uiuc.edu> Changes in directory llvm: Makefile.common updated: 1.84 -> 1.85 --- Log message: Get rid of extraneous ""s --- Diffs of the changes: Index: llvm/Makefile.common diff -u llvm/Makefile.common:1.84 llvm/Makefile.common:1.85 --- llvm/Makefile.common:1.84 Thu May 29 15:09:23 2003 +++ llvm/Makefile.common Thu May 29 15:40:32 2003 @@ -163,7 +163,7 @@ #if PROJDIR is defined then we include PROJ DIR includes and libraries ifndef PROJ_COMPILE -PROJ_INCLUDE = "." +PROJ_INCLUDE = . else PROJ_INCLUDE = $(PROJ_DIR)/include endif From lattner at cs.uiuc.edu Thu May 29 16:08:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 29 16:08:02 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/ScalarRepl/2003-05-29-ArrayFail.ll Message-ID: <200305292107.QAA24828@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/ScalarRepl: 2003-05-29-ArrayFail.ll added (r1.1) --- Log message: New testcase --- Diffs of the changes: Index: llvm/test/Regression/Transforms/ScalarRepl/2003-05-29-ArrayFail.ll diff -c /dev/null llvm/test/Regression/Transforms/ScalarRepl/2003-05-29-ArrayFail.ll:1.1 *** /dev/null Thu May 29 16:07:44 2003 --- llvm/test/Regression/Transforms/ScalarRepl/2003-05-29-ArrayFail.ll Thu May 29 16:07:34 2003 *************** *** 0 **** --- 1,11 ---- + ; RUN: as < %s | opt -scalarrepl | dis | grep alloca | grep '4 x' + + ; Test that an array is not incorrectly deconstructed... + + int %test() { + %X = alloca [4 x int] + %Y = getelementptr [4 x int]* %X, long 0, long 0 + %Z = getelementptr int* %Y, long 1 ; Must preserve arrayness! + %A = load int* %Z + ret int %A + } From dhurjati at cs.uiuc.edu Thu May 29 16:50:01 2003 From: dhurjati at cs.uiuc.edu (Dinakar Dhurjati) Date: Thu May 29 16:50:01 2003 Subject: [llvm-commits] CVS: llvm/Makefile.common Message-ID: <200305292149.QAA27351@apoc.cs.uiuc.edu> Changes in directory llvm: Makefile.common updated: 1.85 -> 1.86 --- Log message: Added documentation for the project options --- Diffs of the changes: Index: llvm/Makefile.common diff -u llvm/Makefile.common:1.85 llvm/Makefile.common:1.86 --- llvm/Makefile.common:1.85 Thu May 29 15:40:32 2003 +++ llvm/Makefile.common Thu May 29 16:49:00 2003 @@ -30,6 +30,15 @@ # are in, if they are not in the current directory. This should include a # trailing / character. # +# 6. PROJ_COMPILE - If set to 1, then this makefile can also be used to +# compile other projects using llvm. Note if this option is set then the +# following *must* hold +# PROJLEVEL should be set to the top of the source directory for the +# project files +# LEVEL should be set to the top of LLVM source tree +# LLVM_LIB_DIR should be set to the top of the LLVM build tree +# +# #===-----------------------------------------------------------------------==== # Configuration file to set paths specific to local installation of LLVM @@ -59,9 +68,16 @@ # /shared directory by default because it is guaranteed to be local to the # current machine. # + ifeq ($(LLVM_OBJ_DIR),.) BUILD_ROOT = $(LLVM_OBJ_DIR) + +ifdef PROJ_COMPILE +BUILD_ROOT_TOP = $(PROJLEVEL) +else BUILD_ROOT_TOP = $(LEVEL) +endif + else BUILD_ROOT := $(LLVM_OBJ_DIR)$(patsubst $(HOME)%,%,$(shell pwd)) @@ -73,7 +89,7 @@ # the directory to eliminate the ../'s # ifdef PROJ_COMPILE -TOP_DIRECTORY := $(shell cd $(TOPLEVEL); pwd) +TOP_DIRECTORY := $(shell cd $(PROJLEVEL); pwd) else TOP_DIRECTORY := $(shell cd $(LEVEL); pwd) endif @@ -108,12 +124,14 @@ endif # Shorthand for commonly accessed directories +# DESTLIBXYZ indicates destination for the libraries built DESTLIBDEBUG := $(BUILD_ROOT_TOP)/lib/Debug DESTLIBRELEASE := $(BUILD_ROOT_TOP)/lib/Release DESTLIBPROFILE := $(BUILD_ROOT_TOP)/lib/Profile DESTLIBCURRENT := $(BUILD_ROOT_TOP)/lib/$(CONFIGURATION) ifdef PROJ_COMPILE +#get the llvm libraries from LLVM_LIB_DIR LLVMLIBDEBUGSOURCE := $(LLVM_LIB_DIR)/lib/Debug LLVMLIBRELEASESOURCE := $(LLVM_LIB_DIR)/lib/Release LLVMLIBPROFILESOURCE := $(LLVM_LIB_DIR)/lib/Profile @@ -125,7 +143,7 @@ PROJLIBCURRENTSOURCE := $(BUILD_ROOT_TOP)/lib/$(CONFIGURATION) else - +#when we are building llvm, destination is same as source LLVMLIBDEBUGSOURCE := $(BUILD_ROOT_TOP)/lib/Debug LLVMLIBRELEASESOURCE := $(BUILD_ROOT_TOP)/lib/Release LLVMLIBPROFILESOURCE := $(BUILD_ROOT_TOP)/lib/Profile @@ -161,11 +179,11 @@ PROFILE = -pg endif -#if PROJDIR is defined then we include PROJ DIR includes and libraries +#if PROJDIR is defined then we include project include directory ifndef PROJ_COMPILE PROJ_INCLUDE = . else -PROJ_INCLUDE = $(PROJ_DIR)/include +PROJ_INCLUDE = $(TOP_DIRECTORY)/include endif # By default, strip symbol information from executable @@ -203,6 +221,7 @@ endif ifdef PROJ_COMPILE +# include both projlib source and llvmlib source LinkG := $(Link) -g -L$(PROJLIBDEBUGSOURCE) -L$(LLVMLIBDEBUGSOURCE) $(STRIP) LinkO := $(Link) -O3 -L$(PROJLIBRELEASESOURCE) -L$(LLVMLIBRELEASESOURCE) LinkP := $(Link) -O3 -L$(PROJLIBPROFILESOURCE) -L$(LLVMLIBPROFILESOURCE) $(PROFILE) From brukman at cs.uiuc.edu Thu May 29 17:13:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu May 29 17:13:01 2003 Subject: [llvm-commits] CVS: llvm/test/Libraries/libc/qsort.c Message-ID: <200305292212.RAA27646@zion.cs.uiuc.edu> Changes in directory llvm/test/Libraries/libc: qsort.c updated: 1.1 -> 1.2 --- Log message: Prevent lines from wrapping. --- Diffs of the changes: Index: llvm/test/Libraries/libc/qsort.c diff -u llvm/test/Libraries/libc/qsort.c:1.1 llvm/test/Libraries/libc/qsort.c:1.2 --- llvm/test/Libraries/libc/qsort.c:1.1 Thu May 29 15:24:54 2003 +++ llvm/test/Libraries/libc/qsort.c Thu May 29 17:12:35 2003 @@ -28,17 +28,17 @@ #include /* Byte-wise swap two items of size SIZE. */ -#define SWAP(a, b, size) \ - do \ - { \ - register size_t __size = (size); \ - register char *__a = (a), *__b = (b); \ - do \ - { \ - char __tmp = *__a; \ - *__a++ = *__b; \ - *__b++ = __tmp; \ - } while (--__size > 0); \ +#define SWAP(a, b, size) \ + do \ + { \ + register size_t __size = (size); \ + register char *__a = (a), *__b = (b); \ + do \ + { \ + char __tmp = *__a; \ + *__a++ = *__b; \ + *__b++ = __tmp; \ + } while (--__size > 0); \ } while (0) /* Discontinue quicksort algorithm when partition gets below this size. @@ -59,8 +59,8 @@ bits per byte (CHAR_BIT) * sizeof(size_t). */ #define STACK_SIZE (CHAR_BIT * sizeof(size_t)) #define PUSH(low, high) ((void) ((top->lo = (low)), (top->hi = (high)), ++top)) -#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi))) -#define STACK_NOT_EMPTY (stack < top) +#define POP(low, high) ((void) (--top, (low = top->lo), (high = top->hi))) +#define STACK_NOT_EMPTY (stack < top) /* Order size using quicksort. This implementation incorporates From kowshik at cs.uiuc.edu Thu May 29 17:43:01 2003 From: kowshik at cs.uiuc.edu (Sumant Kowshik) Date: Thu May 29 17:43:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/PoolAllocate.cpp Message-ID: <200305292242.RAA28080@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: PoolAllocate.cpp updated: 1.5 -> 1.6 --- Log message: --- Diffs of the changes: Index: llvm/lib/Transforms/IPO/PoolAllocate.cpp diff -u llvm/lib/Transforms/IPO/PoolAllocate.cpp:1.5 llvm/lib/Transforms/IPO/PoolAllocate.cpp:1.6 --- llvm/lib/Transforms/IPO/PoolAllocate.cpp:1.5 Wed Apr 16 15:28:39 2003 +++ llvm/lib/Transforms/IPO/PoolAllocate.cpp Thu May 29 17:42:44 2003 @@ -33,9 +33,73 @@ void PoolAllocate::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); + AU.addRequired(); AU.addRequired(); } +// Prints out the functions mapped to the leader of the equivalence class they +// belong to. +void PoolAllocate::printFuncECs() { + map leaderMap = FuncECs.getLeaderMap(); + std::cerr << "Indirect Function Map \n"; + for (map::iterator LI = leaderMap.begin(), + LE = leaderMap.end(); LI != LE; ++LI) { + std::cerr << LI->first->getName() << ": leader is " + << LI->second->getName() << "\n"; + } +} + +void PoolAllocate::buildIndirectFunctionSets(Module &M) { + // Iterate over the module looking for indirect calls to functions + + // Get top down DSGraph for the functions + TDDS = &getAnalysis(); + + for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) { + + DEBUG(std::cerr << "Processing indirect calls function:" << MI->getName() << "\n"); + + if (MI->isExternal()) + continue; + + DSGraph &TDG = TDDS->getDSGraph(*MI); + + std::vector callSites = TDG.getFunctionCalls(); + + // For each call site in the function + // All the functions that can be called at the call site are put in the + // same equivalence class. + for (vector::iterator CSI = callSites.begin(), + CSE = callSites.end(); CSI != CSE ; ++CSI) { + if (CSI->isIndirectCall()) { + DSNode *DSN = CSI->getCalleeNode(); + // assert(DSN->NodeType == DSNode::GlobalNode); + std::vector Callees = DSN->getGlobals(); + if (Callees.size() > 0) { + Function *firstCalledF = dyn_cast(*Callees.begin()); + FuncECs.addElement(firstCalledF); + CallInstTargets[&CSI->getCallInst()].push_back(firstCalledF); + if (Callees.size() > 1) { + for (std::vector::iterator CalleesI = + ++Callees.begin(), CalleesE = Callees.end(); + CalleesI != CalleesE; ++CalleesI) { + Function *calledF = dyn_cast(*CalleesI); + FuncECs.unionElements(firstCalledF, calledF); + CallInstTargets[&CSI->getCallInst()].push_back(calledF); + } + } + } else { + std::cerr << "Callee has no targets\n"; + } + } + } + } + + // Print the equivalence classes + DEBUG(printFuncECs()); + +} + bool PoolAllocate::run(Module &M) { if (M.begin() == M.end()) return false; CurModule = &M; @@ -43,18 +107,32 @@ AddPoolPrototypes(); BU = &getAnalysis(); + buildIndirectFunctionSets(M); + std::map FuncMap; + // Loop over the functions in the original program finding the pool desc. + // arguments necessary for each function that is indirectly callable. + // For each equivalence class, make a list of pool arguments and update + // the PoolArgFirst and PoolArgLast values for each function. + Module::iterator LastOrigFunction = --M.end(); + for (Module::iterator I = M.begin(); ; ++I) { + if (!I->isExternal()) + FindFunctionPoolArgs(*I); + if (I == LastOrigFunction) break; + } + + // Now clone a function using the pool arg list obtained in the previous + // pass over the modules. // Loop over only the function initially in the program, don't traverse newly // added ones. If the function uses memory, make its clone. - Module::iterator LastOrigFunction = --M.end(); for (Module::iterator I = M.begin(); ; ++I) { if (!I->isExternal()) if (Function *R = MakeFunctionClone(*I)) FuncMap[I] = R; if (I == LastOrigFunction) break; } - + ++LastOrigFunction; // Now that all call targets are available, rewrite the function bodies of the @@ -65,7 +143,6 @@ ProcessFunctionBody(*I, FI != FuncMap.end() ? *FI->second : *I); } - FunctionInfo.clear(); return true; } @@ -75,7 +152,7 @@ // void PoolAllocate::AddPoolPrototypes() { CurModule->addTypeName("PoolDescriptor", PoolDescType); - + // Get poolinit function... FunctionType *PoolInitTy = FunctionType::get(Type::VoidTy, @@ -88,42 +165,54 @@ FunctionType *PoolDestroyTy = FunctionType::get(Type::VoidTy, PDArgs, false); PoolDestroy = CurModule->getOrInsertFunction("pooldestroy", PoolDestroyTy); - + // Get the poolalloc function... FunctionType *PoolAllocTy = FunctionType::get(VoidPtrTy, PDArgs, false); PoolAlloc = CurModule->getOrInsertFunction("poolalloc", PoolAllocTy); - + // Get the poolfree function... PDArgs.push_back(VoidPtrTy); // Pointer to free FunctionType *PoolFreeTy = FunctionType::get(Type::VoidTy, PDArgs, false); PoolFree = CurModule->getOrInsertFunction("poolfree", PoolFreeTy); - -#if 0 - Args[0] = Type::UIntTy; // Number of slots to allocate - FunctionType *PoolAllocArrayTy = FunctionType::get(VoidPtrTy, Args, true); - PoolAllocArray = CurModule->getOrInsertFunction("poolallocarray", - PoolAllocArrayTy); -#endif + + // The poolallocarray function + FunctionType *PoolAllocArrayTy = + FunctionType::get(VoidPtrTy, + make_vector(PoolDescPtr, Type::UIntTy, 0), + false); + PoolAllocArray = CurModule->getOrInsertFunction("poolallocarray", + PoolAllocArrayTy); + } - -// MakeFunctionClone - If the specified function needs to be modified for pool -// allocation support, make a clone of it, adding additional arguments as -// neccesary, and return it. If not, just return null. -// -Function *PoolAllocate::MakeFunctionClone(Function &F) { +void PoolAllocate::FindFunctionPoolArgs(Function &F) { DSGraph &G = BU->getDSGraph(F); std::vector &Nodes = G.getNodes(); - if (Nodes.empty()) return 0; // No memory activity, nothing is required + if (Nodes.empty()) return ; // No memory activity, nothing is required FuncInfo &FI = FunctionInfo[&F]; // Create a new entry for F + FI.Clone = 0; - + + // Initialize the PoolArgFirst and PoolArgLast for the function depending + // on whether there have been other functions in the equivalence class + // that have pool arguments so far in the analysis. + if (!FuncECs.findClass(&F)) { + FI.PoolArgFirst = FI.PoolArgLast = 0; + } else { + if (EqClass2LastPoolArg.find(FuncECs.findClass(&F)) != + EqClass2LastPoolArg.end()) + FI.PoolArgFirst = FI.PoolArgLast = + EqClass2LastPoolArg[FuncECs.findClass(&F)] + 1; + else + FI.PoolArgFirst = FI.PoolArgLast = 0; + } + // Find DataStructure nodes which are allocated in pools non-local to the // current function. This set will contain all of the DSNodes which require // pools to be passed in from outside of the function. hash_set &MarkedNodes = FI.MarkedNodes; - + // Mark globals and incomplete nodes as live... (this handles arguments) if (F.getName() != "main") for (unsigned i = 0, e = Nodes.size(); i != e; ++i) @@ -137,22 +226,86 @@ RetNode->markReachableNodes(MarkedNodes); if (MarkedNodes.empty()) // We don't need to clone the function if there - return 0; // are no incoming arguments to be added. + return; // are no incoming arguments to be added. + + for (hash_set::iterator I = MarkedNodes.begin(), + E = MarkedNodes.end(); I != E; ++I) + FI.PoolArgLast++; + + if (FuncECs.findClass(&F)) { + // Update the equivalence class last pool argument information + // only if there actually were pool arguments to the function. + // Also, there is no entry for the Eq. class in EqClass2LastPoolArg + // if there are no functions in the equivalence class with pool arguments. + if (FI.PoolArgLast != FI.PoolArgFirst) + EqClass2LastPoolArg[FuncECs.findClass(&F)] = FI.PoolArgLast - 1; + } + +} +// MakeFunctionClone - If the specified function needs to be modified for pool +// allocation support, make a clone of it, adding additional arguments as +// neccesary, and return it. If not, just return null. +// +Function *PoolAllocate::MakeFunctionClone(Function &F) { + + DSGraph &G = BU->getDSGraph(F); + std::vector &Nodes = G.getNodes(); + if (Nodes.empty()) + return 0; + + FuncInfo &FI = FunctionInfo[&F]; + + hash_set &MarkedNodes = FI.MarkedNodes; + + if (!FuncECs.findClass(&F)) { + // Not in any equivalence class + + if (MarkedNodes.empty()) + return 0; + } else { + // No need to clone if there are no pool arguments in any function in the + // equivalence class + if (!EqClass2LastPoolArg.count(FuncECs.findClass(&F))) + return 0; + } + // Figure out what the arguments are to be for the new version of the function const FunctionType *OldFuncTy = F.getFunctionType(); std::vector ArgTys; - ArgTys.reserve(OldFuncTy->getParamTypes().size() + MarkedNodes.size()); - - FI.ArgNodes.reserve(MarkedNodes.size()); - for (hash_set::iterator I = MarkedNodes.begin(), - E = MarkedNodes.end(); I != E; ++I) - if ((*I)->NodeType & DSNode::Incomplete) { + if (!FuncECs.findClass(&F)) { + ArgTys.reserve(OldFuncTy->getParamTypes().size() + MarkedNodes.size()); + FI.ArgNodes.reserve(MarkedNodes.size()); + for (hash_set::iterator I = MarkedNodes.begin(), + E = MarkedNodes.end(); I != E; ++I) { ArgTys.push_back(PoolDescPtr); // Add the appropriate # of pool descs FI.ArgNodes.push_back(*I); } - if (FI.ArgNodes.empty()) return 0; // No nodes to be pool allocated! + if (FI.ArgNodes.empty()) return 0; // No nodes to be pool allocated! + + } + else { + // This function is a member of an equivalence class and needs to be cloned + ArgTys.reserve(OldFuncTy->getParamTypes().size() + + EqClass2LastPoolArg[FuncECs.findClass(&F)] + 1); + FI.ArgNodes.reserve(EqClass2LastPoolArg[FuncECs.findClass(&F)] + 1); + + for (int i = 0; i <= EqClass2LastPoolArg[FuncECs.findClass(&F)]; ++i) { + ArgTys.push_back(PoolDescPtr); // Add the appropriate # of pool + // descs + } + + for (hash_set::iterator I = MarkedNodes.begin(), + E = MarkedNodes.end(); I != E; ++I) { + FI.ArgNodes.push_back(*I); + } + assert ((FI.ArgNodes.size() == (unsigned) (FI.PoolArgLast - + FI.PoolArgFirst)) && + "Number of ArgNodes equal to the number of pool arguments used by this function"); + } + + ArgTys.insert(ArgTys.end(), OldFuncTy->getParamTypes().begin(), OldFuncTy->getParamTypes().end()); @@ -168,18 +321,45 @@ // pool descriptors map std::map &PoolDescriptors = FI.PoolDescriptors; Function::aiterator NI = New->abegin(); - for (unsigned i = 0, e = FI.ArgNodes.size(); i != e; ++i, ++NI) { - NI->setName("PDa"); // Add pd entry - PoolDescriptors.insert(std::make_pair(FI.ArgNodes[i], NI)); + + if (FuncECs.findClass(&F)) { + for (int i = 0; i <= EqClass2LastPoolArg[FuncECs.findClass(&F)]; ++i, + ++NI) + NI->setName("PDa"); + + NI = New->abegin(); + if (FI.PoolArgFirst > 0) + for (int i = 0; i < FI.PoolArgFirst; ++NI, ++i) + ; + + if (FI.ArgNodes.size() > 0) + for (unsigned i = 0, e = FI.ArgNodes.size(); i != e; ++i, ++NI) + PoolDescriptors.insert(std::make_pair(FI.ArgNodes[i], NI)); + + NI = New->abegin(); + if (EqClass2LastPoolArg.count(FuncECs.findClass(&F))) + for (int i = 0; i <= EqClass2LastPoolArg[FuncECs.findClass(&F)]; ++i, ++NI) + ; + } else { + if (FI.ArgNodes.size()) + for (unsigned i = 0, e = FI.ArgNodes.size(); i != e; ++i, ++NI) { + NI->setName("PDa"); // Add pd entry + PoolDescriptors.insert(std::make_pair(FI.ArgNodes[i], NI)); + } + NI = New->abegin(); + if (FI.ArgNodes.size()) + for (unsigned i = 0; i < FI.ArgNodes.size(); ++NI, ++i) + ; } // Map the existing arguments of the old function to the corresponding // arguments of the new function. std::map ValueMap; - for (Function::aiterator I = F.abegin(), E = F.aend(); I != E; ++I, ++NI) { - ValueMap[I] = NI; - NI->setName(I->getName()); - } + if (NI != New->aend()) + for (Function::aiterator I = F.abegin(), E = F.aend(); I != E; ++I, ++NI) { + ValueMap[I] = NI; + NI->setName(I->getName()); + } // Populate the value map with all of the globals in the program. // FIXME: This should be unneccesary! @@ -208,28 +388,27 @@ DSGraph &G = BU->getDSGraph(F); std::vector &Nodes = G.getNodes(); if (Nodes.empty()) return; // Quick exit if nothing to do... - + FuncInfo &FI = FunctionInfo[&F]; // Get FuncInfo for F hash_set &MarkedNodes = FI.MarkedNodes; - + DEBUG(std::cerr << "[" << F.getName() << "] Pool Allocate: "); - + // Loop over all of the nodes which are non-escaping, adding pool-allocatable // ones to the NodesToPA vector. std::vector NodesToPA; for (unsigned i = 0, e = Nodes.size(); i != e; ++i) if (Nodes[i]->NodeType & DSNode::HeapNode && // Pick nodes with heap elems - !(Nodes[i]->NodeType & DSNode::Array) && // Doesn't handle arrays yet. !MarkedNodes.count(Nodes[i])) // Can't be marked NodesToPA.push_back(Nodes[i]); - + DEBUG(std::cerr << NodesToPA.size() << " nodes to pool allocate\n"); if (!NodesToPA.empty()) { // Create pool construction/destruction code std::map &PoolDescriptors = FI.PoolDescriptors; CreatePools(NewF, NodesToPA, PoolDescriptors); } - + // Transform the body of the function now... TransformFunctionBody(NewF, G, FI); } @@ -257,23 +436,28 @@ Instruction *InsertPoint = F.front().begin(); for (unsigned i = 0, e = NodesToPA.size(); i != e; ++i) { DSNode *Node = NodesToPA[i]; - + // Create a new alloca instruction for the pool... Value *AI = new AllocaInst(PoolDescType, 0, "PD", InsertPoint); - - Value *ElSize = - ConstantUInt::get(Type::UIntTy, TD.getTypeSize(Node->getType())); - + + Value *ElSize; + + // Void types in DS graph are never used + if (Node->getType() != Type::VoidTy) + ElSize = ConstantUInt::get(Type::UIntTy, TD.getTypeSize(Node->getType())); + else + ElSize = ConstantUInt::get(Type::UIntTy, 0); + // Insert the call to initialize the pool... new CallInst(PoolInit, make_vector(AI, ElSize, 0), "", InsertPoint); - + // Update the PoolDescriptors map PoolDescriptors.insert(std::make_pair(Node, AI)); - + // Insert a call to pool destroy before each return inst in the function for (unsigned r = 0, e = ReturnNodes.size(); r != e; ++r) new CallInst(PoolDestroy, make_vector(AI, 0), "", - ReturnNodes[r]->getTerminator()); + ReturnNodes[r]->getTerminator()); } } @@ -284,17 +468,41 @@ struct FuncTransform : public InstVisitor { PoolAllocate &PAInfo; DSGraph &G; + DSGraph &TDG; FuncInfo &FI; - FuncTransform(PoolAllocate &P, DSGraph &g, FuncInfo &fi) - : PAInfo(P), G(g), FI(fi) {} + FuncTransform(PoolAllocate &P, DSGraph &g, DSGraph &tdg, FuncInfo &fi) + : PAInfo(P), G(g), TDG(tdg), FI(fi) { + } void visitMallocInst(MallocInst &MI); void visitFreeInst(FreeInst &FI); void visitCallInst(CallInst &CI); + + // The following instructions are never modified by pool allocation + void visitBranchInst(BranchInst &I) { } + void visitBinaryOperator(Instruction &I) { } + void visitShiftInst (ShiftInst &I) { } + void visitSwitchInst (SwitchInst &I) { } + void visitCastInst (CastInst &I) { } + void visitAllocaInst(AllocaInst &I) { } + void visitLoadInst(LoadInst &I) { } + void visitGetElementPtrInst (GetElementPtrInst &I) { } + + void visitReturnInst(ReturnInst &I); + void visitStoreInst (StoreInst &I); + void visitPHINode(PHINode &I); + + void visitInstruction(Instruction &I) { + std::cerr << "PoolAllocate does not recognize this instruction\n"; + abort(); + } private: DSNode *getDSNodeFor(Value *V) { + if (isa(V)) + return 0; + if (!FI.NewToOldValueMap.empty()) { // If the NewToOldValueMap is in effect, use it. std::map::iterator I = FI.NewToOldValueMap.find(V); @@ -310,13 +518,130 @@ std::map::iterator I = FI.PoolDescriptors.find(Node); return I != FI.PoolDescriptors.end() ? I->second : 0; } + + bool isFuncPtr(Value *V); + + Function* getFuncClass(Value *V); + + Value* retCloneIfNotFP(Value *V); }; } void PoolAllocate::TransformFunctionBody(Function &F, DSGraph &G, FuncInfo &FI){ - FuncTransform(*this, G, FI).visit(F); + DSGraph &TDG = TDDS->getDSGraph(G.getFunction()); + FuncTransform(*this, G, TDG, FI).visit(F); +} + +// Returns true if V is a function pointer +bool FuncTransform::isFuncPtr(Value *V) { + if (V->getType()->getPrimitiveID() == Type::PointerTyID) { + const PointerType *PTy = dyn_cast(V->getType()); + + if (PTy->getElementType()->getPrimitiveID() == Type::FunctionTyID) + return true; + } + + return false; +} + +// Given a function pointer, return the function eq. class if one exists +Function* FuncTransform::getFuncClass(Value *V) { + // Look at DSGraph and see if the set of of functions it could point to + // are pool allocated. + + if (!isFuncPtr(V)) + return 0; + + // Two cases: + // if V is a constant + if (Function *theFunc = dyn_cast(V)) { + if (!PAInfo.FuncECs.findClass(theFunc)) + // If this function does not belong to any equivalence class + return 0; + if (PAInfo.EqClass2LastPoolArg.count(PAInfo.FuncECs.findClass(theFunc))) + return PAInfo.FuncECs.findClass(theFunc); + else + return 0; + } + + // if V is not a constant + DSNode *DSN = TDG.getNodeForValue(V).getNode(); + if (!DSN) { + return 0; + } + std::vector Callees = DSN->getGlobals(); + if (Callees.size() > 0) { + Function *calledF = dyn_cast(*Callees.begin()); + assert(PAInfo.FuncECs.findClass(calledF) && "should exist in some eq. class"); + if (PAInfo.EqClass2LastPoolArg.count(PAInfo.FuncECs.findClass(calledF))) + return PAInfo.FuncECs.findClass(calledF); + } + + return 0; +} + +// Returns the clone if V is not a function pointer +Value* FuncTransform::retCloneIfNotFP(Value *V) { + if (isFuncPtr(V)) + if (isa(V)) + if (getFuncClass(V)) { + Function *fixedFunc = dyn_cast(V); + return PAInfo.getFuncInfo(*fixedFunc)->Clone; + } + + return 0; +} + +void FuncTransform::visitReturnInst (ReturnInst &I) { + if (I.getNumOperands()) + if (Value *clonedFunc = retCloneIfNotFP(I.getOperand(0))) { + // Cast the clone of I.getOperand(0) to the non-pool-allocated type + CastInst *CastI = new CastInst(clonedFunc, I.getOperand(0)->getType(), + "", &I); + // Insert return instruction that returns the casted value + new ReturnInst(CastI, &I); + + // Remove original return instruction + I.setName(""); + I.getParent()->getInstList().erase(&I); + } +} + +void FuncTransform::visitStoreInst (StoreInst &I) { + // Check if a constant function is being stored + if (Value *clonedFunc = retCloneIfNotFP(I.getOperand(0))) { + CastInst *CastI = new CastInst(clonedFunc, I.getOperand(0)->getType(), "", + &I); + new StoreInst(CastI, I.getOperand(1), &I); + I.setName(""); + I.getParent()->getInstList().erase(&I); + } } +void FuncTransform::visitPHINode(PHINode &I) { + // If any of the operands of the PHI node is a constant function pointer + // that is cloned, the cast instruction has to be inserted at the end of the + // previous basic block + + if (isFuncPtr(&I)) { + PHINode *V = new PHINode(I.getType(), I.getName(), &I); + for (unsigned i = 0 ; i < I.getNumIncomingValues(); ++i) { + if (Value *clonedFunc = retCloneIfNotFP(I.getIncomingValue(i))) { + // Insert CastInst at the end of I.getIncomingBlock(i) + BasicBlock::iterator BBI = --I.getIncomingBlock(i)->end(); + // BBI now points to the terminator instruction of the basic block. + CastInst *CastI = new CastInst(clonedFunc, I.getType(), "", BBI); + V->addIncoming(CastI, I.getIncomingBlock(i)); + } else { + V->addIncoming(I.getIncomingValue(i), I.getIncomingBlock(i)); + } + + } + I.replaceAllUsesWith(V); + I.setName(""); + I.getParent()->getInstList().erase(&I); + } +} void FuncTransform::visitMallocInst(MallocInst &MI) { // Get the pool handle for the node that this contributes to... @@ -324,8 +649,15 @@ if (PH == 0) return; // Insert a call to poolalloc - Value *V = new CallInst(PAInfo.PoolAlloc, make_vector(PH, 0), - MI.getName(), &MI); + Value *V; + if (MI.isArrayAllocation()) + V = new CallInst(PAInfo.PoolAllocArray, + make_vector(PH, MI.getOperand(0), 0), + MI.getName(), &MI); + else + V = new CallInst(PAInfo.PoolAlloc, make_vector(PH, 0), + MI.getName(), &MI); + MI.setName(""); // Nuke MIs name // Cast to the appropriate type... @@ -372,7 +704,13 @@ static void CalcNodeMapping(DSNode *Caller, DSNode *Callee, std::map &NodeMapping) { if (Callee == 0) return; - assert(Caller && "Callee has node but caller doesn't??"); + // assert(Caller && "Callee has node but caller doesn't??"); + + // If callee has a node and caller doesn't, then a constant argument was + // passed by the caller + if (Caller == 0) { + NodeMapping.insert(NodeMapping.end(), std::make_pair(Callee, (DSNode*) 0)); + } std::map::iterator I = NodeMapping.find(Callee); if (I != NodeMapping.end()) { // Node already in map... @@ -381,66 +719,207 @@ NodeMapping.insert(I, std::make_pair(Callee, Caller)); // Recursively add pointed to nodes... - for (unsigned i = 0, e = Callee->getNumLinks(); i != e; ++i) - CalcNodeMapping(Caller->getLink(i << DS::PointerShift).getNode(), - Callee->getLink(i << DS::PointerShift).getNode(), - NodeMapping); + unsigned numCallerLinks = Caller->getNumLinks(); + unsigned numCalleeLinks = Callee->getNumLinks(); + + assert (numCallerLinks <= numCalleeLinks || numCalleeLinks == 0); + + for (unsigned i = 0, e = numCalleeLinks; i != e; ++i) + CalcNodeMapping(Caller->getLink((i%numCallerLinks) << DS::PointerShift).getNode(), Callee->getLink(i << DS::PointerShift).getNode(), NodeMapping); } } void FuncTransform::visitCallInst(CallInst &CI) { Function *CF = CI.getCalledFunction(); - assert(CF && "FIXME: Pool allocation doesn't handle indirect calls!"); - - FuncInfo *CFI = PAInfo.getFuncInfo(*CF); - if (CFI == 0 || CFI->Clone == 0) return; // Nothing to transform... + + // optimization for function pointers that are basically gotten from a cast + // with only one use and constant expressions with casts in them + if (!CF) { + if (CastInst* CastI = dyn_cast(CI.getCalledValue())) { + if (isa(CastI->getOperand(0)) && + CastI->getOperand(0)->getType() == CastI->getType()) + CF = dyn_cast(CastI->getOperand(0)); + } else if (isa(CI.getOperand(0))) { + ConstantExpr *CE = dyn_cast(CI.getOperand(0)); + if (CE->getOpcode() == Instruction::Cast) { + if (isa(CE->getOperand(0))) + return; + else + assert(0 && "Function pointer cast not handled as called function\n"); + } + } - DEBUG(std::cerr << " Handling call: " << CI); + } - DSGraph &CG = PAInfo.getBUDataStructures().getDSGraph(*CF); // Callee graph + std::vector Args; + if (!CF) { + // Indirect call + + DEBUG(std::cerr << " Handling call: " << CI); + + std::map PoolArgs; + Function *FuncClass; + + for (vector::iterator TFI = PAInfo.CallInstTargets[&CI].begin(), + TFE = PAInfo.CallInstTargets[&CI].end(); TFI != TFE; ++TFI) { + if (TFI == PAInfo.CallInstTargets[&CI].begin()) { + FuncClass = PAInfo.FuncECs.findClass(*TFI); + // Nothing to transform if there are no pool arguments in this + // equivalence class of functions. + if (!PAInfo.EqClass2LastPoolArg.count(FuncClass)) + return; + } + + FuncInfo *CFI = PAInfo.getFuncInfo(**TFI); - // We need to figure out which local pool descriptors correspond to the pool - // descriptor arguments passed into the function call. Calculate a mapping - // from callee DSNodes to caller DSNodes. We construct a partial isomophism - // between the graphs to figure out which pool descriptors need to be passed - // in. The roots of this mapping is found from arguments and return values. - // - std::map NodeMapping; + if (!CFI->ArgNodes.size()) continue; // Nothing to transform... + + DSGraph &CG = PAInfo.getBUDataStructures().getDSGraph(**TFI); + std::map NodeMapping; + + Function::aiterator AI = (*TFI)->abegin(), AE = (*TFI)->aend(); + unsigned OpNum = 1; + for ( ; AI != AE; ++AI, ++OpNum) { + if (!isa(CI.getOperand(OpNum))) + CalcNodeMapping(getDSNodeFor(CI.getOperand(OpNum)), + CG.getScalarMap()[AI].getNode(), + NodeMapping); + } + assert(OpNum == CI.getNumOperands() && "Varargs calls not handled yet!"); + + if (CI.getType() != Type::VoidTy) + CalcNodeMapping(getDSNodeFor(&CI), CG.getRetNode().getNode(), + NodeMapping); + + unsigned idx = CFI->PoolArgFirst; + + // The following loop determines the pool pointers corresponding to + // CFI. + for (unsigned i = 0, e = CFI->ArgNodes.size(); i != e; ++i, ++idx) { + if (NodeMapping.count(CFI->ArgNodes[i])) { + assert(NodeMapping.count(CFI->ArgNodes[i]) && "Node not in mapping!"); + DSNode *LocalNode = NodeMapping.find(CFI->ArgNodes[i])->second; + if (LocalNode) { + assert(FI.PoolDescriptors.count(LocalNode) && "Node not pool allocated?"); + PoolArgs[idx] = FI.PoolDescriptors.find(LocalNode)->second; + } + else + // LocalNode is null when a constant is passed in as a parameter + PoolArgs[idx] = Constant::getNullValue(PoolDescPtr); + } else { + PoolArgs[idx] = Constant::getNullValue(PoolDescPtr); + } + } + } + + // Push the pool arguments into Args. + if (PAInfo.EqClass2LastPoolArg.count(FuncClass)) { + for (int i = 0; i <= PAInfo.EqClass2LastPoolArg[FuncClass]; ++i) { + if (PoolArgs.find(i) != PoolArgs.end()) + Args.push_back(PoolArgs[i]); + else + Args.push_back(Constant::getNullValue(PoolDescPtr)); + } + + assert (Args.size()== (unsigned) PAInfo.EqClass2LastPoolArg[FuncClass] + 1 + && "Call has same number of pool args as the called function"); + } - Function::aiterator AI = CF->abegin(), AE = CF->aend(); - unsigned OpNum = 1; - for (; AI != AE; ++AI, ++OpNum) - CalcNodeMapping(getDSNodeFor(CI.getOperand(OpNum)), - CG.getScalarMap()[AI].getNode(), NodeMapping); - assert(OpNum == CI.getNumOperands() && "Varargs calls not handled yet!"); - - // Map the return value as well... - CalcNodeMapping(getDSNodeFor(&CI), CG.getRetNode().getNode(), NodeMapping); - - - // Okay, now that we have established our mapping, we can figure out which - // pool descriptors to pass in... - std::vector Args; - - // Add an argument for each pool which must be passed in... - for (unsigned i = 0, e = CFI->ArgNodes.size(); i != e; ++i) { - if (NodeMapping.count(CFI->ArgNodes[i])) { - assert(NodeMapping.count(CFI->ArgNodes[i]) && "Node not in mapping!"); - DSNode *LocalNode = NodeMapping.find(CFI->ArgNodes[i])->second; - assert(FI.PoolDescriptors.count(LocalNode) && "Node not pool allocated?"); - Args.push_back(FI.PoolDescriptors.find(LocalNode)->second); + // Add the rest of the arguments (the original arguments of the function)... + Args.insert(Args.end(), CI.op_begin()+1, CI.op_end()); + + std::string Name = CI.getName(); + + Value *NewCall; + if (Args.size() > CI.getNumOperands() - 1) { + CastInst *CastI = + new CastInst(CI.getOperand(0), + PAInfo.getFuncInfo(*FuncClass)->Clone->getType(), "", &CI); + NewCall = new CallInst(CastI, Args, Name, &CI); } else { - Args.push_back(Constant::getNullValue(PoolDescPtr)); + NewCall = new CallInst(CI.getOperand(0), Args, Name, &CI); } + + CI.setName(""); + CI.replaceAllUsesWith(NewCall); + DEBUG(std::cerr << " Result Call: " << *NewCall); } + else { + + FuncInfo *CFI = PAInfo.getFuncInfo(*CF); + + if (CFI == 0 || CFI->Clone == 0) return; // Nothing to transform... + + DEBUG(std::cerr << " Handling call: " << CI); + + DSGraph &CG = PAInfo.getBUDataStructures().getDSGraph(*CF); // Callee graph + + // We need to figure out which local pool descriptors correspond to the pool + // descriptor arguments passed into the function call. Calculate a mapping + // from callee DSNodes to caller DSNodes. We construct a partial isomophism + // between the graphs to figure out which pool descriptors need to be passed + // in. The roots of this mapping is found from arguments and return values. + // + std::map NodeMapping; + + Function::aiterator AI = CF->abegin(), AE = CF->aend(); + unsigned OpNum = 1; + for (; AI != AE; ++AI, ++OpNum) { + // Check if the operand of the call is a return of another call + // for the operand will be transformed in which case. + // Look up the OldToNewRetValMap to see if the operand is a new value. + Value *callOp = CI.getOperand(OpNum); + if (!isa(callOp)) + CalcNodeMapping(getDSNodeFor(callOp),CG.getScalarMap()[AI].getNode(), + NodeMapping); + } + assert(OpNum == CI.getNumOperands() && "Varargs calls not handled yet!"); + + // Map the return value as well... + if (CI.getType() != Type::VoidTy) + CalcNodeMapping(getDSNodeFor(&CI), CG.getRetNode().getNode(), + NodeMapping); + + // Okay, now that we have established our mapping, we can figure out which + // pool descriptors to pass in... + + // Add an argument for each pool which must be passed in... + if (CFI->PoolArgFirst != 0) { + for (int i = 0; i < CFI->PoolArgFirst; ++i) + Args.push_back(Constant::getNullValue(PoolDescPtr)); + } - // Add the rest of the arguments... - Args.insert(Args.end(), CI.op_begin()+1, CI.op_end()); + for (unsigned i = 0, e = CFI->ArgNodes.size(); i != e; ++i) { + if (NodeMapping.count(CFI->ArgNodes[i])) { + assert(NodeMapping.count(CFI->ArgNodes[i]) && "Node not in mapping!"); + DSNode *LocalNode = NodeMapping.find(CFI->ArgNodes[i])->second; + if (LocalNode) { + assert(FI.PoolDescriptors.count(LocalNode) && "Node not pool allocated?"); + Args.push_back(FI.PoolDescriptors.find(LocalNode)->second); + } + else + Args.push_back(Constant::getNullValue(PoolDescPtr)); + } else { + Args.push_back(Constant::getNullValue(PoolDescPtr)); + } + } - std::string Name = CI.getName(); CI.setName(""); - Value *NewCall = new CallInst(CFI->Clone, Args, Name, &CI); - CI.replaceAllUsesWith(NewCall); + Function *FuncClass = PAInfo.FuncECs.findClass(CF); + + if (PAInfo.EqClass2LastPoolArg.count(FuncClass)) + for (unsigned i = CFI->PoolArgLast; + i <= PAInfo.EqClass2LastPoolArg.count(FuncClass); ++i) + Args.push_back(Constant::getNullValue(PoolDescPtr)); + + // Add the rest of the arguments... + Args.insert(Args.end(), CI.op_begin()+1, CI.op_end()); + + std::string Name = CI.getName(); CI.setName(""); + Value *NewCall = new CallInst(CFI->Clone, Args, Name, &CI); + CI.replaceAllUsesWith(NewCall); + DEBUG(std::cerr << " Result Call: " << *NewCall); - DEBUG(std::cerr << " Result Call: " << *NewCall); + } + CI.getParent()->getInstList().erase(&CI); } From kowshik at cs.uiuc.edu Thu May 29 17:44:01 2003 From: kowshik at cs.uiuc.edu (Sumant Kowshik) Date: Thu May 29 17:44:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Transforms/PoolAllocate.h Message-ID: <200305292243.RAA28132@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Transforms: PoolAllocate.h updated: 1.1 -> 1.2 --- Log message: --- Diffs of the changes: Index: llvm/include/llvm/Transforms/PoolAllocate.h diff -u llvm/include/llvm/Transforms/PoolAllocate.h:1.1 llvm/include/llvm/Transforms/PoolAllocate.h:1.2 --- llvm/include/llvm/Transforms/PoolAllocate.h:1.1 Mon Feb 3 13:07:46 2003 +++ llvm/include/llvm/Transforms/PoolAllocate.h Thu May 29 17:43:46 2003 @@ -12,9 +12,12 @@ #include "llvm/Pass.h" #include "Support/hash_set" +#include "Support/EquivalenceClasses.h" class BUDataStructures; +class TDDataStructures; class DSNode; class DSGraph; +class CallInst; namespace PA { /// FuncInfo - Represent the pool allocation information for one function in @@ -33,9 +36,15 @@ Function *Clone; /// ArgNodes - The list of DSNodes which have pools passed in as arguments. - /// + /// std::vector ArgNodes; + /// In order to handle indirect functions, the start and end of the + /// arguments that are useful to this function. + /// The pool arguments useful to this function are PoolArgFirst to + /// PoolArgLast not inclusive. + int PoolArgFirst, PoolArgLast; + /// PoolDescriptors - The Value* (either an argument or an alloca) which /// defines the pool descriptor for this DSNode. Pools are mapped one to /// one with nodes in the DSGraph, so this contains a pointer to the node it @@ -44,7 +53,8 @@ /// alloca instruction. This entry contains a pointer to that alloca if the /// pool is locally allocated or the argument it is passed in through if /// not. - /// + /// Note: Does not include pool arguments that are passed in because of + /// indirect function calls that are not used in the function. std::map PoolDescriptors; /// NewToOldValueMap - When and if a function needs to be cloned, this map @@ -60,10 +70,35 @@ class PoolAllocate : public Pass { Module *CurModule; BUDataStructures *BU; + + TDDataStructures *TDDS; std::map FunctionInfo; + + void buildIndirectFunctionSets(Module &M); + + void FindFunctionPoolArgs(Function &F); + + // Debug function to print the FuncECs + void printFuncECs(); + public: - Function *PoolInit, *PoolDestroy, *PoolAlloc, *PoolFree; + Function *PoolInit, *PoolDestroy, *PoolAlloc, *PoolAllocArray, *PoolFree; + + // Equivalence class where functions that can potentially be called via + // the same function pointer are in the same class. + EquivalenceClasses FuncECs; + + // Map from an Indirect CallInst to the set of Functions that it can point to + map > CallInstTargets; + + // This maps an equivalence class to the last pool argument number for that + // class. This is used because the pool arguments for all functions within + // an equivalence class is passed to all the functions in that class. + // If an equivalence class does not require pool arguments, it is not + // on this map. + map EqClass2LastPoolArg; + public: bool run(Module &M); @@ -75,7 +110,9 @@ std::map::iterator I = FunctionInfo.find(&F); return I != FunctionInfo.end() ? &I->second : 0; } - + + Module *getCurModule() { return CurModule; } + private: /// AddPoolPrototypes - Add prototypes for the pool functions to the From kowshik at cs.uiuc.edu Thu May 29 17:45:01 2003 From: kowshik at cs.uiuc.edu (Sumant Kowshik) Date: Thu May 29 17:45:01 2003 Subject: [llvm-commits] CVS: llvm/include/Support/EquivalenceClasses.h Message-ID: <200305292244.RAA28148@apoc.cs.uiuc.edu> Changes in directory llvm/include/Support: EquivalenceClasses.h added (r1.1) --- Log message: --- Diffs of the changes: Index: llvm/include/Support/EquivalenceClasses.h diff -c /dev/null llvm/include/Support/EquivalenceClasses.h:1.1 *** /dev/null Thu May 29 17:44:35 2003 --- llvm/include/Support/EquivalenceClasses.h Thu May 29 17:44:25 2003 *************** *** 0 **** --- 1,93 ---- + //===-- Support/EquivalenceClasses.h -------------------------*- C++ -*--=// + // + // Generic implementation of equivalence classes and implementation of + // union-find algorithms + // A not-so-fancy implementation: 2 level tree i.e root and one more level + // Overhead of a union = size of the equivalence class being attached + // Overhead of a find = 1. + // + //===------------------------------------------------------------------===// + + #ifndef LLVM_SUPPORT_EQUIVALENCE_CLASSES_H + #define LLVM_SUPPORT_EQUIVALENCE_CLASSES_H + + #include + #include + #include + using std::map; + using std::set; + using std::vector; + + template + class EquivalenceClasses { + // Maps each element to the element that is the leader of its + // equivalence class. + map Elem2ECLeaderMap; + + // Make Element2 the leader of the union of classes Element1 and Element2 + // Element1 and Element2 are presumed to be leaders of their respective + // equivalence classes. + void attach(ElemTy Element1, ElemTy Element2) { + for (typename map::iterator ElemI = + Elem2ECLeaderMap.begin(), ElemE = Elem2ECLeaderMap.end(); + ElemI != ElemE; ++ElemI) { + if (ElemI->second == Element1) + Elem2ECLeaderMap[ElemI->first] = Element2; + } + } + + public: + + void addElement (ElemTy NewElement) { + if (Elem2ECLeaderMap.find(NewElement) == Elem2ECLeaderMap.end()) + Elem2ECLeaderMap[NewElement] = NewElement; + } + + ElemTy findClass(ElemTy Element) { + if (Elem2ECLeaderMap.find(Element) == Elem2ECLeaderMap.end()) + return 0; + else + return Elem2ECLeaderMap[Element]; + } + + /// Attach the set with Element1 to the set with Element2 adding Element1 and + /// Element2 to the set of equivalence classes if they are not there already. + /// Implication: Make Element1 the element in the smaller set. + void unionElements(ElemTy Element1, ElemTy Element2) { + // If either Element1 or Element2 does not already exist, include it + if (Elem2ECLeaderMap.find(Element1) == Elem2ECLeaderMap.end()) + Elem2ECLeaderMap[Element1] = Element1; + if (Elem2ECLeaderMap.find(Element2) == Elem2ECLeaderMap.end()) + Elem2ECLeaderMap[Element2] = Element2; + + attach(Elem2ECLeaderMap[Element1], Elem2ECLeaderMap[Element2]); + } + + // Returns a vector containing all the elements in the equivalent class + // including Element1 + vector getEqClass(ElemTy Element1) { + vector EqClass; + + if (Elem2ECLeaderMap.find(EqClass) == Elem2ECLeaderMap.end()) + return EqClass; + + ElemTy classLeader = Elem2ECLeaderMap[Element1]; + + for (typename map::iterator ElemI = + Elem2ECLeaderMap.begin(), ElemE = Elem2ECLeaderMap.end(); + ElemI != ElemE; ++ElemI) { + if (ElemI->second == classLeader) + EqClass.push_back(ElemI->first); + } + + return EqClass; + + } + + map getLeaderMap() { + return Elem2ECLeaderMap ; + } + + }; + + #endif From gshi1 at cs.uiuc.edu Thu May 29 19:18:01 2003 From: gshi1 at cs.uiuc.edu (Guochun Shi) Date: Thu May 29 19:18:01 2003 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp ModuloScheduling.h Message-ID: <200305300017.TAA29499@psmith.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/ModuloScheduling: ModuloScheduling.cpp updated: 1.4 -> 1.5 ModuloScheduling.h updated: 1.4 -> 1.5 --- Log message: so far everything compiles --- Diffs of the changes: Index: llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp diff -u llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp:1.4 llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp:1.5 --- llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp:1.4 Thu Apr 10 14:19:23 2003 +++ llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp Thu May 29 19:17:09 2003 @@ -35,19 +35,19 @@ // see ModuloSchedulingPass::runOnFunction() //************************************************************ -namespace { - cl::opt - SDL_opt("modsched", cl::Hidden, cl::location(ModuloScheduling::DebugLevel), - cl::desc("enable modulo scheduling debugging information"), - cl::values(clEnumValN(ModuloScheduling::DebugLevel_NoDebugInfo, - "none", "disable debug output"), - clEnumValN(ModuloScheduling::DebugLevel_PrintSchedule, - "psched", "print original and new schedule"), - clEnumValN(ModuloScheduling::DebugLevel_PrintScheduleProcess, - "pschedproc", - "print how the new schdule is produced"), - 0)); -} +ModuloSchedDebugLevel_t ModuloSchedDebugLevel; + +cl::opt +SDL_opt("modsched", cl::Hidden, cl::location(ModuloSchedDebugLevel), + cl::desc("enable modulo scheduling debugging information"), + cl::values(clEnumValN(ModuloSchedDebugLevel_NoDebugInfo, + "none", "disable debug output"), + clEnumValN(ModuloSchedDebugLevel_PrintSchedule, + "psched", "print original and new schedule"), + clEnumValN(ModuloSchedDebugLevel_PrintScheduleProcess, + "pschedproc", + "print how the new schdule is produced"), + 0)); // Computes the schedule and inserts epilogue and prologue // Index: llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.h diff -u llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.h:1.4 llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.h:1.5 --- llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.h:1.4 Thu Apr 10 14:19:23 2003 +++ llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.h Thu May 29 19:17:09 2003 @@ -13,6 +13,13 @@ #include #include +// for debug information selecton +enum ModuloSchedDebugLevel_t { + ModuloSchedDebugLevel_NoDebugInfo, + ModuloSchedDebugLevel_PrintSchedule, + ModuloSchedDebugLevel_PrintScheduleProcess, +}; + class ModuloScheduling: NonCopyable { private: @@ -48,6 +55,10 @@ typedef BasicBlock::InstListType InstListType; typedef std::vector > vvNodeType; + + + + public: ModuloScheduling(ModuloSchedGraph & _graph): @@ -60,18 +71,23 @@ ~ModuloScheduling() {}; - // for debug information selecton - enum DebugLevel_t { - DebugLevel_NoDebugInfo, - DebugLevel_PrintSchedule, - DebugLevel_PrintScheduleProcess, - }; - static DebugLevel_t DebugLevel; - static bool printSchedule() { return DebugLevel >= DebugLevel_PrintSchedule; } - static bool printScheduleProcess() { - return DebugLevel >= DebugLevel_PrintScheduleProcess; + static bool + printSchedule() { + + //return ModuloScheduling::DebugLevel >= DebugLevel_PrintSchedule; + return false; + + + } + static bool + printScheduleProcess() { + + //return DebugLevel >= DebugLevel_PrintScheduleProcess; + return false; + + } // The method to compute schedule and instert epilogue and prologue From sabre at nondot.org Thu May 29 21:58:01 2003 From: sabre at nondot.org (Chris Lattner) Date: Thu May 29 21:58:01 2003 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp ModuloScheduling.h In-Reply-To: <200305300017.TAA29499@psmith.cs.uiuc.edu> Message-ID: I get the following error: Compiling ModuloSchedGraph.cpp In file included from ModuloScheduling.h:12, from ModuloSchedGraph.cpp:17: ModuloSchedGraph.h:17:44: ../InstrSched/SchedGraphCommon.h: No such file or directory ... -Chris > Changes in directory llvm/lib/CodeGen/ModuloScheduling: > > ModuloScheduling.cpp updated: 1.4 -> 1.5 > ModuloScheduling.h updated: 1.4 -> 1.5 > > --- > Log message: > > so far everything compiles > > > --- > Diffs of the changes: > > Index: llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp > diff -u llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp:1.4 llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp:1.5 > --- llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp:1.4 Thu Apr 10 14:19:23 2003 > +++ llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp Thu May 29 19:17:09 2003 > @@ -35,19 +35,19 @@ > // see ModuloSchedulingPass::runOnFunction() > //************************************************************ > > -namespace { > - cl::opt > - SDL_opt("modsched", cl::Hidden, cl::location(ModuloScheduling::DebugLevel), > - cl::desc("enable modulo scheduling debugging information"), > - cl::values(clEnumValN(ModuloScheduling::DebugLevel_NoDebugInfo, > - "none", "disable debug output"), > - clEnumValN(ModuloScheduling::DebugLevel_PrintSchedule, > - "psched", "print original and new schedule"), > - clEnumValN(ModuloScheduling::DebugLevel_PrintScheduleProcess, > - "pschedproc", > - "print how the new schdule is produced"), > - 0)); > -} > +ModuloSchedDebugLevel_t ModuloSchedDebugLevel; > + > +cl::opt > +SDL_opt("modsched", cl::Hidden, cl::location(ModuloSchedDebugLevel), > + cl::desc("enable modulo scheduling debugging information"), > + cl::values(clEnumValN(ModuloSchedDebugLevel_NoDebugInfo, > + "none", "disable debug output"), > + clEnumValN(ModuloSchedDebugLevel_PrintSchedule, > + "psched", "print original and new schedule"), > + clEnumValN(ModuloSchedDebugLevel_PrintScheduleProcess, > + "pschedproc", > + "print how the new schdule is produced"), > + 0)); > > // Computes the schedule and inserts epilogue and prologue > // > > > Index: llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.h > diff -u llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.h:1.4 llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.h:1.5 > --- llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.h:1.4 Thu Apr 10 14:19:23 2003 > +++ llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.h Thu May 29 19:17:09 2003 > @@ -13,6 +13,13 @@ > #include > #include > > +// for debug information selecton > +enum ModuloSchedDebugLevel_t { > + ModuloSchedDebugLevel_NoDebugInfo, > + ModuloSchedDebugLevel_PrintSchedule, > + ModuloSchedDebugLevel_PrintScheduleProcess, > +}; > + > class ModuloScheduling: NonCopyable { > private: > > @@ -48,6 +55,10 @@ > typedef BasicBlock::InstListType InstListType; > typedef std::vector > vvNodeType; > > + > + > + > + > public: > > ModuloScheduling(ModuloSchedGraph & _graph): > @@ -60,18 +71,23 @@ > > ~ModuloScheduling() {}; > > - // for debug information selecton > - enum DebugLevel_t { > - DebugLevel_NoDebugInfo, > - DebugLevel_PrintSchedule, > - DebugLevel_PrintScheduleProcess, > - }; > > - static DebugLevel_t DebugLevel; > > - static bool printSchedule() { return DebugLevel >= DebugLevel_PrintSchedule; } > - static bool printScheduleProcess() { > - return DebugLevel >= DebugLevel_PrintScheduleProcess; > + static bool > + printSchedule() { > + > + //return ModuloScheduling::DebugLevel >= DebugLevel_PrintSchedule; > + return false; > + > + > + } > + static bool > + printScheduleProcess() { > + > + //return DebugLevel >= DebugLevel_PrintScheduleProcess; > + return false; > + > + > } > > // The method to compute schedule and instert epilogue and prologue > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://mail.cs.uiuc.edu/mailman/listinfo/llvm-commits > -Chris -- http://llvm.cs.uiuc.edu/ http://www.nondot.org/~sabre/Projects/ From gaeke at cs.uiuc.edu Thu May 29 22:38:01 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Thu May 29 22:38:01 2003 Subject: [llvm-commits] CVS: llvm/tools/lli/JIT/SparcEmitter.cpp Message-ID: <200305300337.WAA02413@apoc.cs.uiuc.edu> Changes in directory llvm/tools/lli/JIT: SparcEmitter.cpp updated: 1.2 -> 1.3 --- Log message: Fix call to mmap, so that it can be used on sparc. --- Diffs of the changes: Index: llvm/tools/lli/JIT/SparcEmitter.cpp diff -u llvm/tools/lli/JIT/SparcEmitter.cpp:1.2 llvm/tools/lli/JIT/SparcEmitter.cpp:1.3 --- llvm/tools/lli/JIT/SparcEmitter.cpp:1.2 Wed May 28 13:44:38 2003 +++ llvm/tools/lli/JIT/SparcEmitter.cpp Thu May 29 22:37:13 2003 @@ -77,20 +77,15 @@ // FIXME: This should be rewritten to support a real memory manager for // executable memory pages! void * SparcEmitter::getMemory(unsigned NumPages) { -#if 0 - void *pa = mmap(0, 4096*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC, - MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); + void *pa; + if (NumPages == 0) return 0; + static const long pageSize = sysconf (_SC_PAGESIZE); + pa = mmap(0, pageSize*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); if (pa == MAP_FAILED) { perror("mmap"); abort(); } -#endif - void *pa = malloc(4096*NumPages); - if (!pa) { - perror("malloc"); - abort(); - } - funcMemory.push_back(pa); return pa; } From lattner at cs.uiuc.edu Thu May 29 23:16:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 29 23:16:00 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp Message-ID: <200305300415.XAA03043@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: ScalarReplAggregates.cpp updated: 1.2 -> 1.3 --- Log message: Fix bug: ScalarRepl/2003-05-29-ArrayFail.ll --- Diffs of the changes: Index: llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp diff -u llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp:1.2 llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp:1.3 --- llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp:1.2 Tue May 27 11:09:27 2003 +++ llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp Thu May 29 23:15:41 2003 @@ -23,6 +23,10 @@ bool runOnFunction(Function &F); private: + bool isSafeArrayElementUse(Value *Ptr); + bool isSafeUseOfAllocation(Instruction *User); + bool isSafeStructAllocaToPromote(AllocationInst *AI); + bool isSafeArrayAllocaToPromote(AllocationInst *AI); AllocaInst *AddNewAlloca(Function &F, const Type *Ty, AllocationInst *Base); }; @@ -59,48 +63,13 @@ (!isa(AI->getAllocatedType()) && !isa(AI->getAllocatedType()))) continue; - const ArrayType *AT = dyn_cast(AI->getAllocatedType()); - - // Loop over the use list of the alloca. We can only transform it if there - // are only getelementptr instructions (with a zero first index) and free - // instructions. - // - bool CannotTransform = false; - for (Value::use_iterator I = AI->use_begin(), E = AI->use_end(); - I != E; ++I) { - Instruction *User = cast(*I); - if (GetElementPtrInst *GEPI = dyn_cast(User)) { - // The GEP is safe to transform if it is of the form GEP , 0, - if (GEPI->getNumOperands() <= 2 || - GEPI->getOperand(1) != Constant::getNullValue(Type::LongTy) || - !isa(GEPI->getOperand(2)) || - isa(GEPI->getOperand(2))) { - DEBUG(std::cerr << "Cannot transform: " << *AI << " due to user: " - << User); - CannotTransform = true; - break; - } - - // If this is an array access, check to make sure that index falls - // within the array. If not, something funny is going on, so we won't - // do the optimization. - if (AT && cast(GEPI->getOperand(2))->getValue() >= - AT->getNumElements()) { - DEBUG(std::cerr << "Cannot transform: " << *AI << " due to user: " - << User); - CannotTransform = true; - break; - } - - } else { - DEBUG(std::cerr << "Cannot transform: " << *AI << " due to user: " - << User); - CannotTransform = true; - break; - } - } - - if (CannotTransform) continue; + // Check that all of the users of the allocation are capable of being + // transformed. + if (isa(AI->getAllocatedType())) { + if (!isSafeStructAllocaToPromote(AI)) + continue; + } else if (!isSafeArrayAllocaToPromote(AI)) + continue; DEBUG(std::cerr << "Found inst to xform: " << *AI); Changed = true; @@ -115,6 +84,7 @@ WorkList.push_back(NA); // Add to worklist for recursive processing } } else { + const ArrayType *AT = cast(AI->getAllocatedType()); ElementAllocas.reserve(AT->getNumElements()); const Type *ElTy = AT->getElementType(); for (unsigned i = 0, e = AT->getNumElements(); i != e; ++i) { @@ -177,3 +147,119 @@ return Changed; } + + +/// isSafeUseOfAllocation - Check to see if this user is an allowed use for an +/// aggregate allocation. +/// +bool SROA::isSafeUseOfAllocation(Instruction *User) { + if (GetElementPtrInst *GEPI = dyn_cast(User)) { + // The GEP is safe to transform if it is of the form GEP , 0, + if (GEPI->getNumOperands() <= 2 || + GEPI->getOperand(1) != Constant::getNullValue(Type::LongTy) || + !isa(GEPI->getOperand(2)) || + isa(GEPI->getOperand(2))) + return false; + } else { + return false; + } + return true; +} + + +/// isSafeArrayElementUse - Check to see if this use is an allowed use for a +/// getelementptr instruction of an array aggregate allocation. +/// +bool SROA::isSafeArrayElementUse(Value *Ptr) { + for (Value::use_iterator I = Ptr->use_begin(), E = Ptr->use_end(); + I != E; ++I) { + Instruction *User = cast(*I); + switch (User->getOpcode()) { + case Instruction::Load: return true; + case Instruction::Store: return User->getOperand(0) != Ptr; + case Instruction::GetElementPtr: { + GetElementPtrInst *GEP = cast(User); + if (GEP->getNumOperands() > 1) { + if (!isa(GEP->getOperand(1)) || + !cast(GEP->getOperand(1))->isNullValue()) + return false; // Using pointer arithmetic to navigate the array... + + // Check to see if there are any structure indexes involved in this GEP. + // If so, then we can safely break the array up until at least the + // structure. + for (unsigned i = 2, e = GEP->getNumOperands(); i != e; ++i) + if (GEP->getOperand(i)->getType()->isUnsigned()) + break; + } + return isSafeArrayElementUse(GEP); + } + default: + DEBUG(std::cerr << " Transformation preventing inst: " << *User); + return false; + } + } + return true; // All users look ok :) +} + + +/// isSafeStructAllocaToPromote - Check to see if the specified allocation of a +/// structure can be broken down into elements. +/// +bool SROA::isSafeStructAllocaToPromote(AllocationInst *AI) { + // Loop over the use list of the alloca. We can only transform it if all of + // the users are safe to transform. + // + for (Value::use_iterator I = AI->use_begin(), E = AI->use_end(); + I != E; ++I) + if (!isSafeUseOfAllocation(cast(*I))) { + DEBUG(std::cerr << "Cannot transform: " << *AI << " due to user: " + << *I); + return false; + } + return true; +} + + +/// isSafeArrayAllocaToPromote - Check to see if the specified allocation of a +/// structure can be broken down into elements. +/// +bool SROA::isSafeArrayAllocaToPromote(AllocationInst *AI) { + const ArrayType *AT = cast(AI->getAllocatedType()); + int64_t NumElements = AT->getNumElements(); + + // Loop over the use list of the alloca. We can only transform it if all of + // the users are safe to transform. Array allocas have extra constraints to + // meet though. + // + for (Value::use_iterator I = AI->use_begin(), E = AI->use_end(); + I != E; ++I) { + Instruction *User = cast(*I); + if (!isSafeUseOfAllocation(User)) { + DEBUG(std::cerr << "Cannot transform: " << *AI << " due to user: " + << User); + return false; + } + + // Check to make sure that getelementptr follow the extra rules for arrays: + if (GetElementPtrInst *GEPI = dyn_cast(User)) { + // Check to make sure that index falls within the array. If not, + // something funny is going on, so we won't do the optimization. + // + if (cast(GEPI->getOperand(2))->getValue() >= NumElements) + return false; + + // Check to make sure that the only thing that uses the resultant pointer + // is safe for an array access. For example, code that looks like: + // P = &A[0]; P = P + 1 + // is legal, and should prevent promotion. + // + if (!isSafeArrayElementUse(GEPI)) { + DEBUG(std::cerr << "Cannot transform: " << *AI + << " due to uses of user: " << *GEPI); + return false; + } + } + } + return true; +} + From lattner at cs.uiuc.edu Fri May 30 00:15:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri May 30 00:15:02 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/SingleSource/UnitTests/2003-05-26-Shorts.c Message-ID: <200305300514.AAA04976@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/SingleSource/UnitTests: 2003-05-26-Shorts.c updated: 1.1 -> 1.2 --- Log message: Make the testcase work on X86 --- Diffs of the changes: Index: llvm/test/Programs/SingleSource/UnitTests/2003-05-26-Shorts.c diff -u llvm/test/Programs/SingleSource/UnitTests/2003-05-26-Shorts.c:1.1 llvm/test/Programs/SingleSource/UnitTests/2003-05-26-Shorts.c:1.2 --- llvm/test/Programs/SingleSource/UnitTests/2003-05-26-Shorts.c:1.1 Mon May 26 17:03:25 2003 +++ llvm/test/Programs/SingleSource/UnitTests/2003-05-26-Shorts.c Fri May 30 00:14:24 2003 @@ -7,15 +7,13 @@ * -- correct handling of high bits during native code generation for * a sequence of operations involving -, * and /. */ -#include #include -#include int main(int argc, char** argv) { - unsigned long UL = 0xafafafafc5c5b8a3; - long L = (long) UL; + unsigned long long UL = 0xafafafafc5c5b8a3ULL; + long long L = (long long) UL; unsigned int ui = (unsigned int) UL; /* 0xc5c5b8a3 = 3318069411 */ int i = (int) UL; /* 0xc5c5b8a3 = -976897885 */ @@ -23,32 +21,32 @@ unsigned short us = (unsigned short) UL; /* 0xb8a3 = 47267 */ short s = (short) UL; /* 0xb8a3 = -18269 */ - uint8_t ub = (uint8_t) UL; /* 0xa3 = 163 */ - int8_t b = ( int8_t) UL; /* 0xa3 = -93 */ + unsigned char ub = (unsigned char) UL; /* 0xa3 = 163 */ + signed char b = ( signed char) UL; /* 0xa3 = -93 */ - printf(" ui = %u (0x%x)\t\tUL-ui = %ld (0x%x)\n", ui, ui, UL-ui, UL-ui); - printf("ui*ui = %u (0x%x)\t UL/ui = %ld (0x%x)\n\n", + printf(" ui = %u (0x%x)\t\tUL-ui = %lld (0x%llx)\n", ui, ui, UL-ui, UL-ui); + printf("ui*ui = %u (0x%x)\t UL/ui = %lld (0x%llx)\n\n", (unsigned int) ui*ui, (unsigned int) ui*ui, UL/ui, UL/ui); - printf(" i = %d (0x%x)\tL-i = %ld (0x%x)\n", i, i, L-i, L-i); - printf(" i* i = %d (0x%x)\tL/ i = %ld (0x%x)\n\n", + printf(" i = %d (0x%x)\tL-i = %lld (0x%llx)\n", i, i, L-i, L-i); + printf(" i* i = %d (0x%x)\tL/ i = %lld (0x%llx)\n\n", (int) i*i, (int) i*i, L/i, L/i); - printf("us = %u (0x%x)\t\tUL-us = %ld (0x%x)\n", us, us, UL-us, UL-us); - printf("us*us = %u (0x%x)\t UL/us = %ld (0x%x)\n\n", + printf("us = %u (0x%x)\t\tUL-us = %lld (0x%llx)\n", us, us, UL-us, UL-us); + printf("us*us = %u (0x%x)\t UL/us = %lld (0x%llx)\n\n", (unsigned short) us*us, (unsigned short) us*us, UL/us, UL/us); - printf(" s = %d (0x%x)\tL-s = %ld (0x%x)\n", s, s, L-s, L-s); - printf(" s* s = %d (0x%x)\tL/ s = %ld (0x%x)\n\n", + printf(" s = %d (0x%x)\tL-s = %lld (0x%llx)\n", s, s, L-s, L-s); + printf(" s* s = %d (0x%x)\tL/ s = %lld (0x%llx)\n\n", (short) s*s, (short) s*s, L/s, L/s); - printf("ub = %u (0x%x)\t\tUL-ub = %ld (0x%x)\n", ub, ub, UL-ub, UL-ub); - printf("ub*ub = %u (0x%x)\t\tUL/ub = %ld (0x%x)\n\n", - (uint8_t) ub*ub, (uint8_t) ub*ub, UL/ub, UL/ub); - - printf(" b = %d (0x%x)\t\tL-b = %ld (0x%x)\n", b, b, L-b, L-b); - printf(" b* b = %d (0x%x)\t\t\tL/b = %ld (0x%x)\n\n", - (int8_t) b*b, (int8_t) b*b, L/b, L/b); + printf("ub = %u (0x%x)\t\tUL-ub = %lld (0x%llx)\n", ub, ub, UL-ub, UL-ub); + printf("ub*ub = %u (0x%x)\t\tUL/ub = %lld (0x%llx)\n\n", + (unsigned char) ub*ub, (unsigned char) ub*ub, UL/ub, UL/ub); + + printf(" b = %d (0x%x)\t\tL-b = %lld (0x%llx)\n", b, b, L-b, L-b); + printf(" b* b = %d (0x%x)\t\t\tL/b = %lld (0x%llx)\n\n", + (signed char) b*b, (signed char) b*b, L/b, L/b); return 0; } From lattner at cs.uiuc.edu Fri May 30 00:27:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri May 30 00:27:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp Message-ID: <200305300526.AAA07874@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: ScalarReplAggregates.cpp updated: 1.3 -> 1.4 --- Log message: Fix bug: ScalarRepl/2003-05-30-MultiLevel.ll --- Diffs of the changes: Index: llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp diff -u llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp:1.3 llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp:1.4 --- llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp:1.3 Thu May 29 23:15:41 2003 +++ llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp Fri May 30 00:26:30 2003 @@ -123,12 +123,12 @@ // expanded itself once the worklist is rerun. // std::string OldName = GEPI->getName(); // Steal the old name... + std::vector NewArgs; + NewArgs.push_back(Constant::getNullValue(Type::LongTy)); + NewArgs.insert(NewArgs.end(), GEPI->op_begin()+3, GEPI->op_end()); GEPI->setName(""); RepValue = - new GetElementPtrInst(AllocaToUse, - std::vector(GEPI->op_begin()+3, - GEPI->op_end()), - OldName, GEPI); + new GetElementPtrInst(AllocaToUse, NewArgs, OldName, GEPI); } // Move all of the users over to the new GEP. From lattner at cs.uiuc.edu Fri May 30 00:27:09 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri May 30 00:27:09 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/ScalarRepl/2003-05-30-MultiLevel.ll Message-ID: <200305300526.AAA07862@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/ScalarRepl: 2003-05-30-MultiLevel.ll added (r1.1) --- Log message: New testcase --- Diffs of the changes: Index: llvm/test/Regression/Transforms/ScalarRepl/2003-05-30-MultiLevel.ll diff -c /dev/null llvm/test/Regression/Transforms/ScalarRepl/2003-05-30-MultiLevel.ll:1.1 *** /dev/null Fri May 30 00:26:18 2003 --- llvm/test/Regression/Transforms/ScalarRepl/2003-05-30-MultiLevel.ll Fri May 30 00:26:08 2003 *************** *** 0 **** --- 1,9 ---- + ; RUN: as < %s | opt -scalarrepl + + int %test() { + %X = alloca { [ 4 x int] } + %Y = getelementptr { [ 4 x int] }* %X, long 0, ubyte 0, long 2 + store int 4, int* %Y + %Z = load int* %Y + ret int %Z + } From gaeke at cs.uiuc.edu Fri May 30 03:03:01 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Fri May 30 03:03:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/Makefile SparcV9_F3.td Message-ID: <200305300802.DAA28161@morpheus.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: Makefile updated: 1.19 -> 1.20 SparcV9_F3.td updated: 1.1 -> 1.2 --- Log message: Makefile: Make SparcV9CodeEmitter.inc depend on SparcV9_F*.td as well. SparcV9_F3.td: F3_12 and F3_13 instructions have rd and rs1 fields. Also, their fields were totally screwed up. This seems to fix the problem. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/Makefile diff -u llvm/lib/Target/Sparc/Makefile:1.19 llvm/lib/Target/Sparc/Makefile:1.20 --- llvm/lib/Target/Sparc/Makefile:1.19 Thu May 29 15:09:56 2003 +++ llvm/lib/Target/Sparc/Makefile Fri May 30 03:02:14 2003 @@ -36,7 +36,7 @@ TEMP_EMITTER_INC = _temp_emitter.inc -SparcV9CodeEmitter.inc: SparcV9.td +SparcV9CodeEmitter.inc: SparcV9.td SparcV9_F2.td SparcV9_F3.td SparcV9_F4.td SparcV9_Reg.td @echo "TableGen-erating $@" cpp -P SparcV9.td | $(TBLGEN) -gen-emitter > $(TEMP_EMITTER_INC) mv -f $(TEMP_EMITTER_INC) SparcV9CodeEmitter.inc Index: llvm/lib/Target/Sparc/SparcV9_F3.td diff -u llvm/lib/Target/Sparc/SparcV9_F3.td:1.1 llvm/lib/Target/Sparc/SparcV9_F3.td:1.2 --- llvm/lib/Target/Sparc/SparcV9_F3.td:1.1 Wed May 28 22:31:43 2003 +++ llvm/lib/Target/Sparc/SparcV9_F3.td Fri May 30 03:02:14 2003 @@ -108,9 +108,11 @@ //set Inst{11-5} = dontcare; } -class F3_12 opVal, bits<6> op3Val, string name> : F3 { +class F3_12 opVal, bits<6> op3Val, string name> : F3_rdrs1 { bits<5> shcnt; + set op = opVal; + set op3 = op3Val; set Name = name; set Inst{13} = 1; // i field = 1 set Inst{12} = 0; // x field = 0 @@ -118,9 +120,11 @@ set Inst{4-0} = shcnt; } -class F3_13 opVal, bits<6> op3Val, string name> : F3 { +class F3_13 opVal, bits<6> op3Val, string name> : F3_rdrs1 { bits<6> shcnt; + set op = opVal; + set op3 = op3Val; set Name = name; set Inst{13} = 1; // i field = 1 set Inst{12} = 1; // x field = 1 From jstanley at cs.uiuc.edu Fri May 30 10:25:01 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Fri May 30 10:25:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Reoptimizer/inst/Test1.c Message-ID: <200305301524.KAA18779@trinity.cs.uiuc.edu> Changes in directory llvm/test/Regression/Reoptimizer/inst: Test1.c updated: 1.4 -> 1.4.2.1 --- Log message: Modified to use new dynamic-inst mechanism. --- Diffs of the changes: Index: llvm/test/Regression/Reoptimizer/inst/Test1.c diff -u llvm/test/Regression/Reoptimizer/inst/Test1.c:1.4 llvm/test/Regression/Reoptimizer/inst/Test1.c:1.4.2.1 --- llvm/test/Regression/Reoptimizer/inst/Test1.c:1.4 Thu May 22 22:25:43 2003 +++ llvm/test/Regression/Reoptimizer/inst/Test1.c Fri May 30 10:23:50 2003 @@ -3,40 +3,33 @@ // The following is actually the semantic result of processing a metric // declaration (need more sigfun support) -double elapsedTime = 0; -double elapsedTime2 = 0; +double elapsedTime = 3.14; int l1cachemiss = 0; #include -void phase2(); - int fib(int n); void fibs(); -void someOtherFunction() -{ - int x; - pp_L1_cache_miss_start(&x); - printf("this statement resides within a region!\n"); - pp_L1_cache_miss_end(&l1cachemiss, &x); - printf("someOtherFunction complete: retval is %d\n", l1cachemiss); -} - int main(int argc, char** argv) { phase2(); - printf("Just about to call fibs()...\n"); + registerIntervalInst(42, pp_elapsed_time_start, + pp_elapsed_time_end, sizeof(double), + &elapsedTime); + + printf("Just about to call fibs() for the first time...\n"); fibs(); - printf("Just about to call someOtherFunction()...\n"); - someOtherFunction(); + registerIntervalInst(42, pp_L1_cache_miss_start, + pp_L1_cache_miss_end, sizeof(int), + &l1cachemiss); - printf("Leaving main...\n"); + printf("Just about to call fibs() for the second time...\n"); + fibs(); - pp_regionPair(pp_elapsed_time_start, pp_elapsed_time_end); - pp_regionPair(pp_L1_cache_miss_start, pp_L1_cache_miss_end); + printf("Leaving main...\n"); return 0; } @@ -49,39 +42,12 @@ return fib(n-2) + fib(n-1); } -void functionToBeInlined() -{ - double y; - pp_elapsed_time_start(&y); - printf("This function should be inlined..."); - pp_elapsed_time_end(&elapsedTime2, &y); -} - void fibs() { int i; + double tmp; - printf("Inside fibs now, calling functionToBeInlined...\n"); - - functionToBeInlined(); - - //////////////// - // The following is the "scope" that the sampling applies to, represented by - // sigfuns. We need better sigfun support. - // - // That is, the below should look like: - // - // pp_region_start(elapsedTime); - // - // pp_region_end(elaspedTime); - // - // or something similar. We should not be putting the actual invoked functions below, - // although the post-phase1 transformed code should be "similar" (calls removed and - // volatile loads put in their place, of course!) - - long x; - double y; - pp_elapsed_time_start(&y); + pp_declareIntervalStart(&tmp, 42); for(i = 10; i > 0; i--) { printf("fib(%d) = %d\n", i, fib(i)); @@ -90,9 +56,10 @@ printf("after for loop...\n"); fflush(stdout); - pp_elapsed_time_end(&elapsedTime, &y); + pp_declareIntervalEnd(42, &tmp); - printf("ElapsedTime (metric variable) has address %lx, value %f\n", &elapsedTime, elapsedTime); + printf("value of variable elapsedTime: %f\n", elapsedTime); + printf("value of variable l1cachemiss: %d\n", l1cachemiss); // //////////////// From jstanley at cs.uiuc.edu Fri May 30 10:26:01 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Fri May 30 10:26:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/rtl/pprtl.cpp pprtl.h Message-ID: <200305301525.KAA18824@trinity.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst/rtl: pprtl.cpp updated: 1.2 -> 1.2.2.1 pprtl.h updated: 1.3 -> 1.3.2.1 --- Log message: Implemented new dynamic-registration mechanism to split apart the notion of instrumentation intervals/points and the metrics that are associated with them. This allows new metrics to be associated with particular intervals at runtime instead of at compile-time, which means that the runtime system is free to register new metrics on the fly. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/rtl/pprtl.cpp diff -u llvm/lib/Reoptimizer/Inst/rtl/pprtl.cpp:1.2 llvm/lib/Reoptimizer/Inst/rtl/pprtl.cpp:1.2.2.1 --- llvm/lib/Reoptimizer/Inst/rtl/pprtl.cpp:1.2 Thu May 22 22:26:13 2003 +++ llvm/lib/Reoptimizer/Inst/rtl/pprtl.cpp Fri May 30 10:25:35 2003 @@ -57,7 +57,7 @@ printf("pp_L1_cache_miss_start invoked: retVal addr is 0x%lx\n", (unsigned long) retVal); start_papi_sample(events, 1); *retVal = PAPI_L1_ICM; - printf("pp_L1_cache_miss_start returning!\n"); + printf("pp_L1_cache_miss_start returning value %x!\n", *retVal); } void pp_L1_cache_miss_end(int* retVal, int* start) Index: llvm/lib/Reoptimizer/Inst/rtl/pprtl.h diff -u llvm/lib/Reoptimizer/Inst/rtl/pprtl.h:1.3 llvm/lib/Reoptimizer/Inst/rtl/pprtl.h:1.3.2.1 --- llvm/lib/Reoptimizer/Inst/rtl/pprtl.h:1.3 Thu May 22 22:26:13 2003 +++ llvm/lib/Reoptimizer/Inst/rtl/pprtl.h Fri May 30 10:25:36 2003 @@ -16,11 +16,22 @@ void pp_L1_cache_miss_end(int* retVal, int* start); unsigned pp_counterPrim(void); - // significant functions + // significant functions and rtl functions + + void phase2(); + void registerIntervalInst(unsigned siteID, + void* startFunc, + void* endFunc, + unsigned paramSize, + void* retVal); void pp_regionPair(void*, void*); void pp_metricSpec(void*); + // Interval declaration sigfuns: the placeholder variable is to connect the + // two sigfuns via uses. + void pp_declareIntervalStart(double* placeHolder, unsigned intervalID); + void pp_declareIntervalEnd(unsigned intervalID, double* placeHolder); #ifdef _BUILDING_RUNTIME_LIBRARY_ } From jstanley at cs.uiuc.edu Fri May 30 10:26:06 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Fri May 30 10:26:06 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp PrimInfo.cpp PrimInfo.h Message-ID: <200305301525.KAA18814@trinity.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst/lib/Phase1: Phase1.cpp updated: 1.26.2.2 -> 1.26.2.3 PrimInfo.cpp updated: 1.15 -> 1.15.2.1 PrimInfo.h updated: 1.10 -> 1.10.2.1 --- Log message: Implemented new dynamic-registration mechanism to split apart the notion of instrumentation intervals/points and the metrics that are associated with them. This allows new metrics to be associated with particular intervals at runtime instead of at compile-time, which means that the runtime system is free to register new metrics on the fly. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp diff -u llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp:1.26.2.2 llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp:1.26.2.3 --- llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp:1.26.2.2 Wed May 28 09:25:21 2003 +++ llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp Fri May 30 10:25:34 2003 @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include "llvm/Pass.h" #include "llvm/Module.h" @@ -78,6 +78,12 @@ Module* m_module; // Current module vector m_primInfos; // Deferred documentation structures TargetData m_targetData; // For obtaining target-specific info + + static const unsigned NUM_START_OPDS = 3; + static const unsigned NUM_END_OPDS = 3; + static const unsigned NUM_STOPD_USES = 2; + static const unsigned ENDCALL_ID_OPIDX = 1; + static const unsigned POINTCALL_ID_OPIDX = 1; }; //////////////// Phase1 implementation //////////////// @@ -112,7 +118,7 @@ m_module); // Invoke PrimInfo's static initializer - PrimInfo::buildStructType(&m); + PrimInfo::buildStructTypes(&m); // //////////////// @@ -181,12 +187,17 @@ // Populate with builtins - // TODO: Replace the hard-coded mechanism for the point metrics with a - // sigfun registration mechanism like that which exists for region metrics - // (pp_regionPair()). + // The new approach: pp_declareInterval{Start,End} are the only sigfuns used + // to declare an interval, instead of the interval being implicit by the + // given locations of the calls to (registered) region sigfuns. For now, we + // will still use the old code for processing the contents of 'rpairs', but + // the only element of rpairs will be the pair of interval-declaration + // sigfuns. TODO: Clean up this approach. + + Function* intervalStartDeclFunc = m_module->getNamedFunction("pp_declareIntervalStart"); + Function* intervalEndDeclFunc = m_module->getNamedFunction("pp_declareIntervalEnd"); - // Find user-declared region-pairs and add them to the list - findRegionPairs(rpairs); + rpairs.push_back(std::make_pair(intervalStartDeclFunc, intervalEndDeclFunc)); //////////////// // Build list of point metric spec sigfuns, finding ppMetricSpec will yield @@ -295,19 +306,19 @@ CallInst* startCall = dyn_cast(*u); assert(startCall && "Use of a registered pp sigfun not in a call"); - + // Find call to endpoint: The first operand of the start function is used in only // two places: the call to the start function, and the call to the end // function. Find the call to the end function. - assert(startCall->getNumOperands() == 2 && - "Start-region call insts should only have 2 operands"); + assert(startCall->getNumOperands() == NUM_START_OPDS && + "Start-region call inst has unexpected number of operands"); Value* stOpd = startCall->getOperand(1); assert(isa(stOpd) && "Unexpected first operand of start call"); - assert(stOpd->use_size() == 2 && - "Expect only two uses of start-region operand"); + assert(stOpd->use_size() == NUM_STOPD_USES && + "Unexpected number of uses of of start-region (\"connector\") operand"); CallInst* endCall; if((endCall = dyn_cast(stOpd->use_back()))) { @@ -338,11 +349,21 @@ return cast(ci->getOperand(1)); } - + +static unsigned extractUnsignedValue(CallInst* ci, unsigned nth) +{ + // extract the literal value of the nth actual of ci, which must be of type + // unsigned. + + if(ConstantUInt* ui = dyn_cast(ci->getOperand(nth))) + return ui->getValue(); + + assert(0 && "Failed to find unsigned value as call actual"); + return 0; // squash warning +} + void Phase1::transformSite(CallInst* startCall, CallInst* endCall) { - GlobalVariable* metricVar = GetLHSGlobal(endCall); - // Insert placeholder code PlaceholderPair startPair, endPair; generatePlaceholder(startCall, startPair); @@ -350,8 +371,9 @@ // Create info about this site for later documentation - m_primInfos.push_back(PrimInfo(PrimInfo::REGION, startPair.first, endPair.first, - metricVar, m_module, + unsigned siteID = extractUnsignedValue(endCall, ENDCALL_ID_OPIDX); + m_primInfos.push_back(PrimInfo(PrimInfo::REGION, siteID, + startPair.first, endPair.first, m_module, startCall->getCalledFunction(), endCall->getCalledFunction())); @@ -379,8 +401,6 @@ void Phase1::transformSite(CallInst* pointCall) { - GlobalVariable* metricVar = GetLHSGlobal(pointCall); - // Insert placeholder code PlaceholderPair php; generatePlaceholder(pointCall, php); @@ -391,7 +411,8 @@ PrimInfo::PrimType type = pointCall->getCalledFunction() == m_counterPrimFunc ? PrimInfo::COUNTER : PrimInfo::POINT; - m_primInfos.push_back(PrimInfo(type, php.first, metricVar, m_module, + unsigned siteID = extractUnsignedValue(pointCall, POINTCALL_ID_OPIDX); + m_primInfos.push_back(PrimInfo(type, siteID, php.first, m_module, pointCall->getCalledFunction())); // Remove the call Index: llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.cpp diff -u llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.cpp:1.15 llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.cpp:1.15.2.1 --- llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.cpp:1.15 Tue May 13 14:43:03 2003 +++ llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.cpp Fri May 30 10:25:34 2003 @@ -29,18 +29,19 @@ //////////////// PrimInfo implementation //////////////// StructType* PrimInfo::sm_structType = 0; +StructType* PrimInfo::sm_infoNodeType = 0; PrimInfo::PrimInfo(PrimType type, + unsigned siteID, GlobalVariable* startGlob, GlobalVariable* endGlob, - GlobalVariable* metricVar, Module* module, Function* startFunc, Function* endFunc): m_type(type), + m_siteID(siteID), m_globVol(startGlob), m_globVolEnd(endGlob), - m_metricVar(metricVar), m_module(module), m_startFunc(startFunc), m_endFunc(endFunc) @@ -48,24 +49,59 @@ } PrimInfo::PrimInfo(PrimType type, + unsigned siteID, GlobalVariable* globVol, - GlobalVariable* metricVar, Module* module, Function* calledFunc): m_type(type), + m_siteID(siteID), m_globVol(globVol), - m_metricVar(metricVar), m_module(module), m_startFunc(calledFunc) { assert(type != POINT || calledFunc && "point type --> non-null called function"); } -void PrimInfo::buildStructType(Module* module) +void PrimInfo::buildStructTypes(Module* module) { - // The structure deposited into the LLVM bytecode essentially looks like: - // struct PrimInfo + static bool init = false; + + assert(!init && "Expect only one invocation of this function"); + init = true; + + // The linked list of containing information about each instrumentation function + // registered for a particular site. + + // {{{ struct InstInfoNode + // { + // // Size, in bytes, of the parameter to the instrumentation function. + // unsigned paramSize; + // + // // Pointer to memory for instFunc's return value This is initialized to null for + // // start-interval sites, and filled in at runtime by a pointer to heap-allocated + // // memory of the appropriate size. For all other site types, the address is + // // specified explicitly when a particular instrumentation is bound to a particular + // // interval. + // void* retVal; + // + // // Pointer to the instrumentation function itself. + // void* instFunc; + // + // // The next node in the list + // InstInfoNode* next; + // }; + // }}} + + // TODO: figger out how to make a recursive struct type + PointerType* vpt = PointerType::get(Type::VoidTy); + sm_infoNodeType = StructType::get(make_vector(Type::UIntTy, vpt, vpt, 0)); + module->addTypeName("InstInfoNode", sm_infoNodeType); + + // {{{ struct PrimInfo // { + // // Site ID for this site (one value identifies one entire interval as well) + // unsigned siteID; + // // // Type of GBT entry type (i.e., member of enum GBTEntryType) // unsigned gbtType; // @@ -76,72 +112,37 @@ // // (NB: Only valid if gbtType == GBT_INTERVAL_END) // unsigned gbtStartIdx; // - // // Size, in bytes, of the parameter to the instrumentation function that must be - // // invoked at the instrumentation that corresponds to this structure instance. - // unsigned paramSize; - // - // // Pointer to memory for instFunc's return value - // // This is initalized to null for start-interval sites, and filled in at runtime - // // by a pointer to heap-allocated memory of the appropriate size. For all other - // // site types, this is initialized to the metric variable address. - // void* retVal; - // - // // Pointer to instrumentation function - // void* instFunc; + // // Linked list of info about what inst functions are registered for this site + // // Always initialized to null, and is filled in at runtime. + // InstInfoNode* instInfoList; // // Other stuff will need to go here...(TODO) // }; - - static bool init = false; - - assert(!init && "Expect only one invocation of this function"); - init = true; + // }}} PointerType* uspt = PointerType::get(Type::UShortTy); - PointerType* vpt = PointerType::get(Type::VoidTy); + sm_structType = StructType::get(make_vector( - Type::UIntTy, uspt, Type::UIntTy, Type::UIntTy, vpt, vpt, 0)); - module->addTypeName("PrimInfo", sm_structType); -} - + Type::UIntTy, Type::UIntTy, uspt, Type::UIntTy, + PointerType::get(sm_infoNodeType), 0)); -// For start sites -static ConstantStruct* makeConstStruct(StructType* st, - unsigned gbtType, - GlobalVariable* loadVar, - unsigned paramSize, - Function* instFunc) -{ - std::vector init; - init.push_back(ConstantUInt::get(Type::UIntTy, gbtType)); - init.push_back(ConstantPointerRef::get(loadVar)); - init.push_back(ConstantUInt::get(Type::UIntTy, 0)); - init.push_back(ConstantUInt::get(Type::UIntTy, paramSize)); - init.push_back(Constant::getNullValue(PointerType::get(Type::VoidTy))); - init.push_back(ConstantExpr::getCast(ConstantPointerRef::get(instFunc), - PointerType::get(Type::VoidTy))); - return ConstantStruct::get(st, init); + module->addTypeName("PrimInfo", sm_structType); } -// For non-start sites static ConstantStruct* makeConstStruct(StructType* st, + unsigned siteID, unsigned gbtType, GlobalVariable* loadVar, - unsigned startLinkIdx, - unsigned paramSize, - GlobalVariable* metricVar, - Function* instFunc) + StructType* infoNodeType, + unsigned startLinkIdx = 0) { std::vector init; - init.push_back(ConstantUInt::get(Type::UIntTy, gbtType)); - init.push_back(ConstantPointerRef::get(loadVar)); - init.push_back(ConstantUInt::get(Type::UIntTy, startLinkIdx)); - init.push_back(ConstantUInt::get(Type::UIntTy, paramSize)); - init.push_back(ConstantExpr::getCast(ConstantPointerRef::get(metricVar), - PointerType::get(Type::VoidTy))); - init.push_back(ConstantExpr::getCast(ConstantPointerRef::get(instFunc), - PointerType::get(Type::VoidTy))); + init.push_back(ConstantUInt::get(Type::UIntTy, siteID)); // siteID + init.push_back(ConstantUInt::get(Type::UIntTy, gbtType)); // gbtType + init.push_back(ConstantPointerRef::get(loadVar)); // loadVar + init.push_back(ConstantUInt::get(Type::UIntTy, startLinkIdx)); // gbtStartIdx + init.push_back(Constant::getNullValue(PointerType::get(infoNodeType))); // instInfoList return ConstantStruct::get(st, init); } @@ -158,16 +159,15 @@ assert(i != gbtIdxMap.end() && "No entry in map for this PrimInfo instance"); // Create the struct for the start of the region - assert(m_startFunc->asize() == 1 && "Unexpected # args for start func"); - unsigned psize = targetData->getTypeSize(m_startFunc->afront().getType()); - gbtElems.push_back(makeConstStruct(st, GBT_INTERVAL_START, m_globVol, - psize, m_startFunc)); + assert(m_startFunc->asize() == 2 && "Unexpected # args for start func"); + + gbtElems.push_back(makeConstStruct(st, m_siteID, GBT_INTERVAL_START, + m_globVol, sm_infoNodeType)); // Create the struct for the end of the region assert(m_endFunc->asize() == 2 && "Unexpected # args for end func"); - psize = targetData->getTypeSize(m_endFunc->afront().getType()); - gbtElems.push_back(makeConstStruct(st, GBT_INTERVAL_END, m_globVolEnd, - i->second, psize, m_metricVar, m_endFunc)); + gbtElems.push_back(makeConstStruct(st, m_siteID, GBT_INTERVAL_END, + m_globVolEnd, sm_infoNodeType, i->second)); break; } Index: llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.h diff -u llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.h:1.10 llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.h:1.10.2.1 --- llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.h:1.10 Mon May 12 21:00:24 2003 +++ llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.h Fri May 30 10:25:35 2003 @@ -26,7 +26,6 @@ PrimInfo(Module* m): m_globVol(0), m_globVolEnd(0), - m_metricVar(0), m_module(m), m_startFunc(0), m_endFunc(0) @@ -35,16 +34,16 @@ // Phase 1 construction -- point/counter computation site PrimInfo(PrimType type, + unsigned siteID, GlobalVariable* globVol, - GlobalVariable* metricVar, Module* m, Function* calledFunc = 0); // Phase 1 construction -- region computation site PrimInfo(PrimType type, + unsigned siteID, GlobalVariable* startGlob, GlobalVariable* endGlob, - GlobalVariable* metricVar, Module* m, Function* startFunc, Function* endFunc); @@ -57,15 +56,13 @@ const Function* getStartFunc() const { return m_startFunc; } Function* getEndFunc() { return m_endFunc; } const Function* getEndFunc() const { return m_endFunc; } - GlobalVariable* getMetricVar() { return m_metricVar; } - const GlobalVariable* getMetricVar() const { return m_metricVar; } PrimType getType() const { return m_type; } void buildStructInstances(std::vector& gbtElems, std::map& gbtIdxMap, const TargetData* targetData); - static void buildStructType(Module* module); + static void buildStructTypes(Module* module); static StructType* getStructType() { return sm_structType; } private: @@ -74,14 +71,15 @@ // supplied configuration parameters. PrimType m_type; + unsigned m_siteID; GlobalVariable* m_globVol; GlobalVariable* m_globVolEnd; - GlobalVariable* m_metricVar; Module* m_module; Function* m_startFunc; Function* m_endFunc; static StructType* sm_structType; + static StructType* sm_infoNodeType; }; }; // end namespace pp From jstanley at cs.uiuc.edu Fri May 30 10:26:12 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Fri May 30 10:26:12 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h Phases.cpp SparcInstManip.cpp Message-ID: <200305301525.KAA18802@trinity.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst/lib: PhaseInfo.h updated: 1.9 -> 1.9.2.1 Phases.cpp updated: 1.35 -> 1.35.2.1 SparcInstManip.cpp updated: 1.16 -> 1.16.2.1 --- Log message: Implemented new dynamic-registration mechanism to split apart the notion of instrumentation intervals/points and the metrics that are associated with them. This allows new metrics to be associated with particular intervals at runtime instead of at compile-time, which means that the runtime system is free to register new metrics on the fly. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h diff -u llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h:1.9 llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h:1.9.2.1 --- llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h:1.9 Sun May 18 15:33:46 2003 +++ llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h Fri May 30 10:25:33 2003 @@ -26,13 +26,19 @@ typedef std::pair AddressRange; +typedef struct InstInfoNode { + unsigned paramSize; + void* retVal; + void* instFunc; + //InstInfoNode* next; +}; + typedef struct GBTElem { - unsigned gbtType; - unsigned short* loadVar; - unsigned gbtStartIdx; - unsigned paramSize; - void* retVal; - void* instFunc; + unsigned siteID; + unsigned gbtType; + unsigned short* loadVar; + unsigned gbtStartIdx; + InstInfoNode* instInfoList; }; class Phase3Info Index: llvm/lib/Reoptimizer/Inst/lib/Phases.cpp diff -u llvm/lib/Reoptimizer/Inst/lib/Phases.cpp:1.35 llvm/lib/Reoptimizer/Inst/lib/Phases.cpp:1.35.2.1 --- llvm/lib/Reoptimizer/Inst/lib/Phases.cpp:1.35 Thu May 22 22:26:12 2003 +++ llvm/lib/Reoptimizer/Inst/lib/Phases.cpp Fri May 30 10:25:33 2003 @@ -56,6 +56,7 @@ #include #include #include +#include #include "llvm/Reoptimizer/Inst/ElfReader.h" #include "llvm/Reoptimizer/MemoryManager.h" @@ -146,11 +147,165 @@ uint64_t m_tag; // Entry to look for in the GBT }; +// InstFunctionInfo is the class used to represent information (e.g., address of +// return value, pointer-to-instrumentation function) about particular +// registered instrumentation functions. In the case of end-interval functions, +// the link 'm_pStart' is filled in to refer to the InstFunctionInfo instance +// that contains information about the corresponding start-interval function. + +class InstFunctionInfo +{ + public: + InstFunctionInfo(void* pRetVal, + void* pInstFunc, + InstFunctionInfo* pStart = 0): + m_pRetVal(pRetVal), m_pInstFunc(pInstFunc), m_pStart(pStart) + { + } + + InstFunctionInfo(): m_pRetVal(0), m_pInstFunc(0), m_pStart(0) + { + } + + void invoke(); + + protected: + void* m_pRetVal; + void* m_pInstFunc; + InstFunctionInfo* m_pStart; // Info about start-interval function +}; + +// InstSiteInfo instances contain information about the state of particular +// instrumentation sites. More specifically, it holds the instrumentation +// status (e.g. whether or not the site has been handled by phase 4 yet) of the +// sites as well as the list of (pointers to) the InstFunctionInfo instances +// registered with a particular site. + +class InstSiteInfo +{ + public: + InstSiteInfo(): + m_branchInstalled(false), + m_instrumented(false) + { + } + + // For start-interval sites only -- allocates memory for the return value of + // the instrumentation function (size of allocated memory is retValBytes). + // Returns a pointer to the InstFunctionInfo* that corresponds to the + // instrumentation function, or null if the function has already been + // registered. + + InstFunctionInfo* push_back(unsigned retValBytes, + void* func); + + // For end-interval sites (w/ optional link to corresponding start); other + // site types should use this routine as well. The provided retVal ptr is + // used as the return-value parameter of the instrumentation function. + + void push_back(void* retVal, + void* func, + InstFunctionInfo* startInfo = 0); + + void invokeFunctions(); + + protected: + bool m_branchInstalled; // Installed branch to slot yet? + bool m_instrumented; // Has phase 4 instrumented site? + uint64_t m_brInstallAddr; // Address to install branch inst + unsigned m_branchInst; // The branch inst to install + std::set m_registeredFuncs; // Set of func-ptrs registered here + vector m_instFuncInfos; // Info for all registered funcs + + friend void Phase4::transform(); + + void installBranch(); + + bool isRegistered(void* func) + { + return m_registeredFuncs.find(func) != m_registeredFuncs.end(); + } + + void setInstrumented() { m_instrumented = true; } + + void setBranchInst(uint64_t addr, unsigned branchInst) + { + m_brInstallAddr = addr; + m_branchInst = branchInst; + } +}; + +// InstInfo is the class that holds data about the instrumentation that gets +// bound to instrumentation sites and intervals at runtime. There should only +// be on instance of this class (i.e., it is a singleton class). The +// implementation hides an STL map that maps the unique identifier associated +// with an instrumentation interval/site to a pair of InstSiteInfo instances, +// which contains the information about the instrumentations registered for the +// given interval or point site. In the case of intervals, the first element of +// the pair is the InstSiteInfo instance that contains data about the start +// site, whereas the second element of the pair contains data about the end +// site. For point sites, only the first element of the pair contains valid +// data. + +class InstInfo +{ + public: + typedef std::pair SiteInfoPair; + + static InstInfo* instance() + { + if(!m_pInstance) + m_pInstance = new InstInfo; + return m_pInstance; + } + + static InstSiteInfo* findSiteInfo(unsigned siteID, unsigned gbtType) + { + SiteInfoPair* sip = instance()->findSiteInfo(siteID); + InstSiteInfo* siteInfo; + + switch(gbtType) { + case pp::GBT_INTERVAL_START: siteInfo = &sip->first; break; + case pp::GBT_INTERVAL_END: siteInfo = &sip->second; break; + default: assert(0 && "Unhandled gbtType encountered"); break; + } + + return siteInfo; + } + + SiteInfoPair* findSiteInfo(unsigned siteID) + { + SiteInfoMap::iterator i = m_siteInfoMap.find(siteID); + if(i == m_siteInfoMap.end()) + return &m_siteInfoMap[siteID]; + return &i->second; + } + + void setVM(VirtualMem* vm) { m_pVM = vm; } + VirtualMem* getVM() const { return m_pVM; } + + protected: + typedef std::map SiteInfoMap; + + InstInfo(): m_pVM(0) + { + } + + SiteInfoMap m_siteInfoMap; + VirtualMem* m_pVM; + + private: + static InstInfo* m_pInstance; +}; + +InstInfo* InstInfo::m_pInstance = 0; + //////////////// Phase 2 implementation //////////////// extern "C" void phase2() { TraceCache* pTC = new TraceCache(); + InstInfo::instance()->setVM(pTC->getVM()); Phase2 ph(pTC, new SparcInstManip(pTC)); ph.transform(); } @@ -192,7 +347,7 @@ if(m_excludeSet.find(i->first) == m_excludeSet.end()) { // Function is not in exclude set, so go ahead and transform it - DEBUG_MSG(1, "Transforming function " << i->first + DEBUG_MSG(4, "Transforming function " << i->first << "[" << HEX(i->second.first) << ", " << HEX(i->second.second) << "]...\n"); @@ -217,11 +372,35 @@ ::doFlush(slotBase, slotBase + im->getInstWidth() * snippet.size()); } +static uint64_t makeNewSlot(uint64_t srcAddr, + unsigned slotSize, + unsigned& branchInst, + TraceCache* tc, + InstManip* im) +{ + // Return a branch instruction to the new slot via branchInst. + uint64_t slotBase = tc->getMemMgr()->getMemory(slotSize); + assert(slotBase && "Unable to obtain memory from MemoryManager instance"); + + branchInst = im->getBranchAlways(slotBase, srcAddr); + return slotBase; +} + static uint64_t replaceInstWithBrToSlot(uint64_t srcAddr, unsigned slotSize, TraceCache* tc, InstManip* im) { + unsigned branchInst; + uint64_t slotBase = makeNewSlot(srcAddr, slotSize, branchInst, tc, im); + + // Replace instruction at srcAddr with branch to start of new slot + tc->getVM()->writeInstToVM(srcAddr, branchInst); + ::doFlush(srcAddr, srcAddr + im->getInstWidth()); + + return slotBase; + +#if 0 // Obtain a new slot of the given size uint64_t slotBase = tc->getMemMgr()->getMemory(slotSize); assert(slotBase && "Unable to obtain memory from MemoryManager instance"); @@ -231,6 +410,7 @@ ::doFlush(srcAddr, srcAddr + im->getInstWidth()); return slotBase; +#endif } static void dumpSnippet(vector& snippet, InstManip* im) @@ -363,8 +543,8 @@ vector snippet; m_pIM->buildSlot(p4info, snippet); - DEBUG_MSG(3, "phase4 slot instructions:\n"); -#if VERBOSE > 2 + DEBUG_MSG(4, "phase4 slot instructions:\n"); +#if VERBOSE > 3 dumpSnippet(snippet, m_pIM); #endif @@ -460,29 +640,44 @@ && "Unexpected number of instructions in candidate"); // Write NOPs over the original instructions that were associated with the elected - // candidate. No need to no-op over the candidate load instruction itself since - // we're about to write over it with a branch to the phase 5 slot. + // candidate. VirtualMem* vm = m_pTC->getVM(); - for(vector >::const_iterator i = cand.getInsts().begin() + 1, + for(vector >::const_iterator i = cand.getInsts().begin(), e = cand.getInsts().end(); i != e; ++i) vm->writeInstToVM(i->first, m_pIM->getNOP()); - // Obtain memory (& rewrite branch) to the phase 5 jump slot. + // Obtain new slot, the phase 5 jump slot. unsigned slotSize = m_pIM->getSlotSize(this); uint64_t repAddr = cand.front().first; - uint64_t slotBase = replaceInstWithBrToSlot(repAddr, slotSize, m_pTC, m_pIM); + unsigned branchInst; + uint64_t slotBase = makeNewSlot(repAddr, slotSize, branchInst, m_pTC, m_pIM); vector snippet; m_pIM->buildSlot(gbte, slotBase, repAddr, m_pPhase4Info->getRange(), snippet); - DEBUG_MSG(3, "phase 5 slot contents:\n"); -#if VERBOSE > 2 + DEBUG_MSG(4, "phase 5 slot contents:\n"); +#if VERBOSE > 3 dumpSnippet(snippet, m_pIM); #endif copySnippetToSlot(snippet, slotBase, m_pTC->getVM(), m_pIM); + + // Grab the information about this particular site. + + assert(gbte->gbtType == pp::GBT_INTERVAL_START || + gbte->gbtType == pp::GBT_INTERVAL_END && + "Unhandled gbtType encountered (must implement)"); + + InstSiteInfo* siteInfo = InstInfo::findSiteInfo(gbte->siteID, gbte->gbtType); + + // Take steps to install the branch; note that the InstSiteInfo instance + // knows whether or not to actually write the branch instruction, etc. + + siteInfo->setInstrumented(); + siteInfo->setBranchInst(repAddr, branchInst); + siteInfo->installBranch(); } else { DEBUG_MSG(1, "does not match\n"); @@ -510,6 +705,12 @@ void phase5(GBTElem* gbte) { + DEBUG_MSG(1, "================ Begin Phase 5 ================\n"); + InstSiteInfo* siteInfo = InstInfo::findSiteInfo(gbte->siteID, gbte->gbtType); + siteInfo->invokeFunctions(); + DEBUG_MSG(1, "================ End Phase 5 ================\n"); + +#if 0 switch(gbte->gbtType){ case pp::GBT_INTERVAL_START: { DEBUG_MSG(1, "--- phase 5 start site invocation ---\n"); @@ -533,4 +734,111 @@ } DEBUG_MSG(1, "--- phase 5 invocation completed ---\n" << std::flush); +#endif +} + +//////////////// InstSiteInfo implementation //////////////// + +InstFunctionInfo* InstSiteInfo::push_back(unsigned retValBytes, + void* func) +{ + DEBUG_MSG(3, "Inside InstSiteInfo::push_back, registering func w/ address " + << HEX(func) << ", new retVal of size " << retValBytes << endl); + + InstFunctionInfo* fi = 0; + + if(!isRegistered(func)) { + DEBUG_MSG(3, "not yet registered, registering...\n"); + void* retVal = static_cast(new char[retValBytes]); + m_registeredFuncs.insert(func); + fi = new InstFunctionInfo(retVal, func); + m_instFuncInfos.push_back(fi); + installBranch(); + } + else + DEBUG_MSG(3, "WARNING: Attempt to register instrumentation at site that was already instrumented\n"); + + return fi; +} + +void InstSiteInfo::push_back(void* retVal, + void* func, + InstFunctionInfo* startInfo) +{ + DEBUG_MSG(3, "Inside InstSiteInfo::push_back, registering func w/ address " + << HEX(func) << ", retVal addr " << HEX(retVal) << endl); + + if(!isRegistered(func)) { + DEBUG_MSG(3, "not yet registered, registering...\n"); + m_registeredFuncs.insert(func); + m_instFuncInfos.push_back(new InstFunctionInfo(retVal, func, startInfo)); + installBranch(); + } + else + DEBUG_MSG(3, "WARNING: Attempt to register instrumentation at site that was already instrumented\n"); +} + +void InstSiteInfo::invokeFunctions() +{ + assert(m_branchInstalled && m_instrumented && "Invoking functions not permitted"); + + for(int i = 0, e = m_instFuncInfos.size(); i < e; ++i) { + DEBUG_MSG(3, "Invoking function " << i << endl); + m_instFuncInfos[i]->invoke(); + } +} + +void InstSiteInfo::installBranch() +{ + if(!m_branchInstalled && m_instrumented && m_instFuncInfos.size() > 0) { + DEBUG_MSG(3, "(InstSiteInfo::installBranch) Installing branch...\n"); + VirtualMem* vm = InstInfo::instance()->getVM(); + vm->writeInstToVM(m_brInstallAddr, m_branchInst); + m_branchInstalled = true; + } + else + DEBUG_MSG(3, "(InstSiteInfo::installBranch) Not installing branch, it's not needed\n"); +} + +//////////////// InstFunctionInfo implementation //////////////// + +void InstFunctionInfo::invoke() +{ + DEBUG_MSG(3, "(InstFunctionInfo::invoke) retVal address is: " << HEX(m_pRetVal) << endl); + if(m_pStart) { + DEBUG_MSG(3, "End-interval inst func detected\n"); + void (*instFunc)(void*, void*) = (void (*)(void*, void*)) m_pInstFunc; + instFunc(m_pRetVal, m_pStart->m_pRetVal); + } + else { + DEBUG_MSG(3, "Start-interval or non-end inst func detected\n"); + void (*instFunc)(void*) = (void (*)(void*)) m_pInstFunc; + instFunc(m_pRetVal); + } + + DEBUG_MSG(3, "(InstFunctionInfo::invoke) instrumentation function returned\n"); +} + +//////////////// register{Interval,Point}Inst implementation //////////////// + +extern "C" void registerIntervalInst(unsigned siteID, + void* startFunc, + void* endFunc, + unsigned paramSize, + void* retVal) +{ + InstInfo::SiteInfoPair* sip = InstInfo::instance()->findSiteInfo(siteID); + assert(sip && "Unable to obtain SiteInfoPair"); + + // Handle start function + DEBUG_MSG(3, "registerIntervalInst: Registering start function...\n"); + InstFunctionInfo* fi = sip->first.push_back(paramSize, startFunc); + + if(fi) { + // Handle end function + DEBUG_MSG(3, "registerIntervalInst: Registering end function...\n"); + sip->second.push_back(retVal, endFunc, fi); + } + else + DEBUG_MSG(3, "WARNING: Register-start-function returned 0, which implies redundant registration"); } Index: llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp diff -u llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.16 llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.16.2.1 --- llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.16 Wed May 28 08:52:41 2003 +++ llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp Fri May 30 10:25:34 2003 @@ -242,6 +242,7 @@ DEBUG_MSG(2, "buildPhase5HeapSlot completed\n"); +#if 0 // If we're dealing with a start-interval instrumentation function, heap-allocate // its parameter memory @@ -249,6 +250,7 @@ assert(!gbte->retVal && "Expected null retVal value"); gbte->retVal = static_cast(new char[gbte->paramSize]); } +#endif //////////////// // Construct the phase 5 jump slot @@ -363,7 +365,7 @@ unsigned sizeBytes, int protBits) { - DEBUG_MSG(3, "Setting access bits on heap slot page(s)" << endl); + DEBUG_MSG(4, "Setting access bits on heap slot page(s)" << endl); int rc = mprotect(pageBase, sizeBytes, protBits); if(rc < 0) { @@ -416,10 +418,10 @@ setPageBits(heapSlot, numHeapBytes, PROT_READ | PROT_WRITE | PROT_EXEC); -#if VERBOSE > 2 - DEBUG_MSG(3, "Dumping contents of heap-slot memory...\n"); +#if VERBOSE > 3 + DEBUG_MSG(4, "Dumping contents of heap-slot memory...\n"); dumpHeapSlot(heapSlot, getPhase5HeapSize(), this); - DEBUG_MSG(3, "Done with heap region construction, moving on to jump slot\n"); + DEBUG_MSG(4, "Done with heap region construction, moving on to jump slot\n"); #endif return heapSlot; @@ -462,7 +464,7 @@ return addr + getInstWidth(); } else { - DEBUG_MSG(2, "WARNING: Non-save instruction at function entry\n"); + DEBUG_MSG(4, "WARNING: Non-save instruction at function entry\n"); return addr; } @@ -569,7 +571,7 @@ m_logicalToActualReg[useForIndirect], offset)); - DEBUG_MSG(3, "JMPL instruction word is " << HEX(m_pCurrSnippet->back()) << endl); + DEBUG_MSG(4, "JMPL instruction word is " << HEX(m_pCurrSnippet->back()) << endl); m_pCurrSnippet->push_back(getNOP()); assert(m_pCurrSnippet->size() - initSize == GEN_JMPL_SIZE && From tbrethou at cs.uiuc.edu Fri May 30 10:49:02 2003 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Fri May 30 10:49:02 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Transforms/Utils/Cloning.h Message-ID: <200305301548.KAA12625@tank.cs.uiuc.edu> Changes in directory llvm/include/llvm/Transforms/Utils: Cloning.h updated: 1.6 -> 1.7 --- Log message: Added support for cloning a trace. --- Diffs of the changes: Index: llvm/include/llvm/Transforms/Utils/Cloning.h diff -u llvm/include/llvm/Transforms/Utils/Cloning.h:1.6 llvm/include/llvm/Transforms/Utils/Cloning.h:1.7 --- llvm/include/llvm/Transforms/Utils/Cloning.h:1.6 Thu May 29 10:06:40 2003 +++ llvm/include/llvm/Transforms/Utils/Cloning.h Fri May 30 10:48:23 2003 @@ -91,4 +91,11 @@ /// bool InlineFunction(CallInst *C); + +/// CloneTrace - Returns a copy of the specified trace. It removes internal phi +/// nodes, copies the basic blocks, remaps variables, and returns a new vector +/// of basic blocks (the cloned trace). +/// +std::vector cloneTrace(std::vector &origTrace); + #endif From criswell at cs.uiuc.edu Fri May 30 10:50:04 2003 From: criswell at cs.uiuc.edu (John Criswell) Date: Fri May 30 10:50:04 2003 Subject: [llvm-commits] CVS: llvm/Makefile.config Message-ID: <200305301549.KAA24083@choi.cs.uiuc.edu> Changes in directory llvm: Makefile.config updated: 1.13 -> 1.14 --- Log message: Added configurable options for the Linker and Archiver. --- Diffs of the changes: Index: llvm/Makefile.config diff -u llvm/Makefile.config:1.13 llvm/Makefile.config:1.14 --- llvm/Makefile.config:1.13 Thu May 29 14:16:55 2003 +++ llvm/Makefile.config Fri May 30 10:49:28 2003 @@ -19,6 +19,16 @@ CC := PATH=/usr/bin /usr/dcs/software/evaluation/bin/gcc # +# Path to the linker. +# +LD = ld + +# +# Path to the archiver program. +# +AR_PATH = ar + +# # The pathnames of the Flex and Bison programs, respectively. # BISON = bison From criswell at cs.uiuc.edu Fri May 30 10:51:01 2003 From: criswell at cs.uiuc.edu (John Criswell) Date: Fri May 30 10:51:01 2003 Subject: [llvm-commits] CVS: llvm/Makefile.common Message-ID: <200305301550.KAA24108@choi.cs.uiuc.edu> Changes in directory llvm: Makefile.common updated: 1.86 -> 1.87 --- Log message: Added configurable options for the Linker and Archiver. --- Diffs of the changes: Index: llvm/Makefile.common diff -u llvm/Makefile.common:1.86 llvm/Makefile.common:1.87 --- llvm/Makefile.common:1.86 Thu May 29 16:49:00 2003 +++ llvm/Makefile.common Fri May 30 10:50:31 2003 @@ -234,7 +234,7 @@ # Create one .o file from a bunch of .o files... -Relink = ld -r +Relink = ${LD} -r # MakeSO - Create a .so file from a .o files... MakeSO := $(CXX) $(MakeSharedObjectOption) @@ -246,7 +246,7 @@ DependC := $(CC) -MM -I$(LEVEL)/include -I$(PROJ_INCLUDE) $(CPPFLAGS) # Archive a bunch of .o files into a .a file... -AR = ar cq +AR = ${AR_PATH} cq #---------------------------------------------------------- From tbrethou at cs.uiuc.edu Fri May 30 10:51:09 2003 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Fri May 30 10:51:09 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/CloneTrace.cpp Message-ID: <200305301550.KAA12649@tank.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: CloneTrace.cpp added (r1.1) --- Log message: Added the CloneTrace function which clones traces. It takes a vector of basic blocks, removes internal phi nodes, and returns a new vector of basic blocks. --- Diffs of the changes: Index: llvm/lib/Transforms/Utils/CloneTrace.cpp diff -c /dev/null llvm/lib/Transforms/Utils/CloneTrace.cpp:1.1 *** /dev/null Fri May 30 10:50:28 2003 --- llvm/lib/Transforms/Utils/CloneTrace.cpp Fri May 30 10:50:18 2003 *************** *** 0 **** --- 1,83 ---- + //===- CloneTrace.cpp - Clone a trace ---------===// + // + // This file implements the CloneTrace interface, which is used + // when writing runtime optimizations. It takes a vector of basic blocks + // removes internal phi nodes, clones the basic blocks, and returns the new + // vector of basic blocks. + // + //===----------------------------------------------------------------------===// + + #include "llvm/Instruction.h" + #include "llvm/BasicBlock.h" + #include "llvm/iPHINode.h" + #include "llvm/Function.h" + #include "llvm/Transforms/Utils/Cloning.h" + #include + + + //Clones the trace (a vector of basic blocks) + std::vector CloneTrace(std::vector &origTrace) { + + std::vector clonedTrace; + std::map ValueMap; + + //First, loop over all the Basic Blocks in the trace and copy + //them using CloneBasicBlock. Also fix the phi nodes during + //this loop. To fix the phi nodes, we delete incoming branches + //that are not in the trace. + for(std::vector::const_iterator T = origTrace.begin(), + End = origTrace.end(); T != End; ++T) { + + //Clone Basic Block + BasicBlock *clonedBlock = CloneBasicBlock(*T, ValueMap); + + //Add it to our new trace + clonedTrace.push_back(clonedBlock); + + //Add this new mapping to our Value Map + ValueMap[*T] = clonedBlock; + + //Add this cloned BB to the old BB's function + (*T)->getParent()->getBasicBlockList().push_back(clonedBlock); + + //Loop over the phi instructions and delete operands + //that are from blocks not in the trace + //only do this if we are NOT the first block + if(T != origTrace.begin()) { + for (BasicBlock::iterator I = clonedBlock->begin(); + PHINode *PN = dyn_cast(I); ++I) { + //get incoming value for the previous BB + Value *V = PN->getIncomingValueForBlock(*(T-1)); + assert(V && "No incoming value from a BasicBlock in our trace!"); + + //remap our phi node to point to incoming value + ValueMap[*&I] = V; + + //remove phi node + clonedBlock->getInstList().erase(PN); + } + } + } + + //Second loop to do the remapping + for(std::vector::const_iterator BB = clonedTrace.begin(), + BE = clonedTrace.end(); BB != BE; ++BB) { + for(BasicBlock::iterator I = (*BB)->begin(); I != (*BB)->end(); ++I) { + + //Loop over all the operands of the instruction + for(unsigned op=0, E = I->getNumOperands(); op != E; ++op) { + const Value *Op = I->getOperand(op); + + //Get it out of the value map + Value *V = ValueMap[Op]; + + //If not in the value map, then its outside our trace so ignore + if(V != 0) + I->setOperand(op,V); + } + } + } + + //return new vector of basic blocks + return clonedTrace; + } From tbrethou at cs.uiuc.edu Fri May 30 10:55:03 2003 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Fri May 30 10:55:03 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Transforms/Utils/Cloning.h Message-ID: <200305301554.KAA12725@tank.cs.uiuc.edu> Changes in directory llvm/include/llvm/Transforms/Utils: Cloning.h updated: 1.7 -> 1.8 --- Log message: Sorry, correcting small typo. --- Diffs of the changes: Index: llvm/include/llvm/Transforms/Utils/Cloning.h diff -u llvm/include/llvm/Transforms/Utils/Cloning.h:1.7 llvm/include/llvm/Transforms/Utils/Cloning.h:1.8 --- llvm/include/llvm/Transforms/Utils/Cloning.h:1.7 Fri May 30 10:48:23 2003 +++ llvm/include/llvm/Transforms/Utils/Cloning.h Fri May 30 10:53:50 2003 @@ -96,6 +96,6 @@ /// nodes, copies the basic blocks, remaps variables, and returns a new vector /// of basic blocks (the cloned trace). /// -std::vector cloneTrace(std::vector &origTrace); +std::vector CloneTrace(std::vector &origTrace); #endif From jstanley at cs.uiuc.edu Fri May 30 10:58:02 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Fri May 30 10:58:02 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp PrimInfo.cpp PrimInfo.h Message-ID: <200305301557.KAA19448@trinity.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst/lib/Phase1: Phase1.cpp updated: 1.26.2.3 -> 1.26.2.4 PrimInfo.cpp updated: 1.15.2.1 -> 1.15.2.2 PrimInfo.h updated: 1.10.2.1 -> 1.10.2.2 --- Log message: Just cleaning up. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp diff -u llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp:1.26.2.3 llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp:1.26.2.4 --- llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp:1.26.2.3 Fri May 30 10:25:34 2003 +++ llvm/lib/Reoptimizer/Inst/lib/Phase1/Phase1.cpp Fri May 30 10:57:09 2003 @@ -187,12 +187,12 @@ // Populate with builtins - // The new approach: pp_declareInterval{Start,End} are the only sigfuns used - // to declare an interval, instead of the interval being implicit by the - // given locations of the calls to (registered) region sigfuns. For now, we - // will still use the old code for processing the contents of 'rpairs', but - // the only element of rpairs will be the pair of interval-declaration - // sigfuns. TODO: Clean up this approach. + // The new approach: pp_declareInterval{Start,End} are the only sigfuns used to + // declare an interval, instead of the interval being implicit by the given locations + // of the calls to (registered) region sigfuns. For now, we will still use the old + // code for processing the contents of 'rpairs', but the only element of rpairs will + // be the pair of interval-declaration sigfuns. TODO: Clean up this approach, and do + // the same for point-site declarations. Function* intervalStartDeclFunc = m_module->getNamedFunction("pp_declareIntervalStart"); Function* intervalEndDeclFunc = m_module->getNamedFunction("pp_declareIntervalEnd"); @@ -229,26 +229,10 @@ for(unsigned i = 0, e = rpairs.size(); i < e; ++i) transformSites(rpairs[i]); - // Build the interval PrimInfo instance -> GBT index map. This maps the address of a - // particular interval PrimInfo instance to the index in the GBT that corresponds to - // the record that represents the start-interval global-volatile and related - // information. - - std::map gbtIdxMap; - int idx = 0; - for(vector::iterator i = m_primInfos.begin(), e = m_primInfos.end(); i != e; ++i){ - if(i->getType() == PrimInfo::REGION) { - gbtIdxMap[&*i] = idx; - idx += 2; - } - else - idx++; - } - // Build the global bookkeeping table (GBT) contents vector gbtElems; for(vector::iterator i = m_primInfos.begin(), e = m_primInfos.end(); i != e; ++i) - i->buildStructInstances(gbtElems, gbtIdxMap, &m_targetData); + i->buildStructInstances(gbtElems); // Make the GBT itself, and the corresponding global variable. ArrayType* gbtType = ArrayType::get(PrimInfo::getStructType(), gbtElems.size()); Index: llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.cpp diff -u llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.cpp:1.15.2.1 llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.cpp:1.15.2.2 --- llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.cpp:1.15.2.1 Fri May 30 10:25:34 2003 +++ llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.cpp Fri May 30 10:57:10 2003 @@ -2,10 +2,8 @@ // programmer: Joel Stanley // date: Tue Jan 28 14:07:05 CST 2003 // fileid: PrimInfo.cpp -// purpose: Captures information about an instance of a performance primitive. The -// information is intended to be carried between phases by reconstructing PrimInfo -// contents that have been placed in global static data structures by Phase1's -// invocation of PrimInfo::Document. +// purpose: Captures information about an instance of a performance primitive "marker" +// in the code. #include "llvm/Module.h" #include "llvm/Type.h" @@ -15,7 +13,6 @@ #include "llvm/GlobalVariable.h" #include "llvm/Constant.h" #include "Support/VectorExtras.h" -#include "llvm/Target/TargetData.h" #include "PrimInfo.h" #include "Intraphase.h" @@ -29,7 +26,6 @@ //////////////// PrimInfo implementation //////////////// StructType* PrimInfo::sm_structType = 0; -StructType* PrimInfo::sm_infoNodeType = 0; PrimInfo::PrimInfo(PrimType type, unsigned siteID, @@ -69,34 +65,6 @@ assert(!init && "Expect only one invocation of this function"); init = true; - // The linked list of containing information about each instrumentation function - // registered for a particular site. - - // {{{ struct InstInfoNode - // { - // // Size, in bytes, of the parameter to the instrumentation function. - // unsigned paramSize; - // - // // Pointer to memory for instFunc's return value This is initialized to null for - // // start-interval sites, and filled in at runtime by a pointer to heap-allocated - // // memory of the appropriate size. For all other site types, the address is - // // specified explicitly when a particular instrumentation is bound to a particular - // // interval. - // void* retVal; - // - // // Pointer to the instrumentation function itself. - // void* instFunc; - // - // // The next node in the list - // InstInfoNode* next; - // }; - // }}} - - // TODO: figger out how to make a recursive struct type - PointerType* vpt = PointerType::get(Type::VoidTy); - sm_infoNodeType = StructType::get(make_vector(Type::UIntTy, vpt, vpt, 0)); - module->addTypeName("InstInfoNode", sm_infoNodeType); - // {{{ struct PrimInfo // { // // Site ID for this site (one value identifies one entire interval as well) @@ -108,15 +76,6 @@ // // Address of global variable corresponding to this primitive. // unsigned short* loadVar; // - // // Index in GBT of struct of corresponding GBT_INTERVAL_START entry - // // (NB: Only valid if gbtType == GBT_INTERVAL_END) - // unsigned gbtStartIdx; - // - // // Linked list of info about what inst functions are registered for this site - // // Always initialized to null, and is filled in at runtime. - // InstInfoNode* instInfoList; - // - // Other stuff will need to go here...(TODO) // }; // }}} @@ -124,8 +83,7 @@ sm_structType = StructType::get(make_vector( - Type::UIntTy, Type::UIntTy, uspt, Type::UIntTy, - PointerType::get(sm_infoNodeType), 0)); + Type::UIntTy, Type::UIntTy, uspt, 0)); module->addTypeName("PrimInfo", sm_structType); } @@ -133,41 +91,29 @@ static ConstantStruct* makeConstStruct(StructType* st, unsigned siteID, unsigned gbtType, - GlobalVariable* loadVar, - StructType* infoNodeType, - unsigned startLinkIdx = 0) + GlobalVariable* loadVar) { std::vector init; - init.push_back(ConstantUInt::get(Type::UIntTy, siteID)); // siteID - init.push_back(ConstantUInt::get(Type::UIntTy, gbtType)); // gbtType - init.push_back(ConstantPointerRef::get(loadVar)); // loadVar - init.push_back(ConstantUInt::get(Type::UIntTy, startLinkIdx)); // gbtStartIdx - init.push_back(Constant::getNullValue(PointerType::get(infoNodeType))); // instInfoList + init.push_back(ConstantUInt::get(Type::UIntTy, siteID)); // siteID + init.push_back(ConstantUInt::get(Type::UIntTy, gbtType)); // gbtType + init.push_back(ConstantPointerRef::get(loadVar)); // loadVar return ConstantStruct::get(st, init); } -void PrimInfo::buildStructInstances(std::vector& gbtElems, - std::map& gbtIdxMap, - const TargetData* targetData) +void PrimInfo::buildStructInstances(std::vector& gbtElems) { StructType* st = getStructType(); switch(m_type) { case REGION: { - - std::map::iterator i = gbtIdxMap.find(this); - assert(i != gbtIdxMap.end() && "No entry in map for this PrimInfo instance"); - + // Create the struct for the start of the region assert(m_startFunc->asize() == 2 && "Unexpected # args for start func"); - - gbtElems.push_back(makeConstStruct(st, m_siteID, GBT_INTERVAL_START, - m_globVol, sm_infoNodeType)); + gbtElems.push_back(makeConstStruct(st, m_siteID, GBT_INTERVAL_START, m_globVol)); // Create the struct for the end of the region assert(m_endFunc->asize() == 2 && "Unexpected # args for end func"); - gbtElems.push_back(makeConstStruct(st, m_siteID, GBT_INTERVAL_END, - m_globVolEnd, sm_infoNodeType, i->second)); + gbtElems.push_back(makeConstStruct(st, m_siteID, GBT_INTERVAL_END, m_globVolEnd)); break; } Index: llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.h diff -u llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.h:1.10.2.1 llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.h:1.10.2.2 --- llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.h:1.10.2.1 Fri May 30 10:25:35 2003 +++ llvm/lib/Reoptimizer/Inst/lib/Phase1/PrimInfo.h Fri May 30 10:57:10 2003 @@ -13,8 +13,6 @@ #include -class TargetData; - namespace pp { @@ -58,9 +56,7 @@ const Function* getEndFunc() const { return m_endFunc; } PrimType getType() const { return m_type; } - void buildStructInstances(std::vector& gbtElems, - std::map& gbtIdxMap, - const TargetData* targetData); + void buildStructInstances(std::vector& gbtElems); static void buildStructTypes(Module* module); static StructType* getStructType() { return sm_structType; } @@ -79,7 +75,6 @@ Function* m_endFunc; static StructType* sm_structType; - static StructType* sm_infoNodeType; }; }; // end namespace pp From jstanley at cs.uiuc.edu Fri May 30 10:58:09 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Fri May 30 10:58:09 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h Phases.cpp SparcInstManip.cpp Message-ID: <200305301557.KAA19435@trinity.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst/lib: PhaseInfo.h updated: 1.9.2.1 -> 1.9.2.2 Phases.cpp updated: 1.35.2.1 -> 1.35.2.2 SparcInstManip.cpp updated: 1.16.2.1 -> 1.16.2.2 --- Log message: Just cleaning up. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h diff -u llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h:1.9.2.1 llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h:1.9.2.2 --- llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h:1.9.2.1 Fri May 30 10:25:33 2003 +++ llvm/lib/Reoptimizer/Inst/lib/PhaseInfo.h Fri May 30 10:57:08 2003 @@ -26,19 +26,10 @@ typedef std::pair AddressRange; -typedef struct InstInfoNode { - unsigned paramSize; - void* retVal; - void* instFunc; - //InstInfoNode* next; -}; - typedef struct GBTElem { unsigned siteID; unsigned gbtType; unsigned short* loadVar; - unsigned gbtStartIdx; - InstInfoNode* instInfoList; }; class Phase3Info Index: llvm/lib/Reoptimizer/Inst/lib/Phases.cpp diff -u llvm/lib/Reoptimizer/Inst/lib/Phases.cpp:1.35.2.1 llvm/lib/Reoptimizer/Inst/lib/Phases.cpp:1.35.2.2 --- llvm/lib/Reoptimizer/Inst/lib/Phases.cpp:1.35.2.1 Fri May 30 10:25:33 2003 +++ llvm/lib/Reoptimizer/Inst/lib/Phases.cpp Fri May 30 10:57:09 2003 @@ -45,10 +45,13 @@ // // 2. Change the branch to the phase 4 slot to branch to a (new) phase 5 slot. See // appropriate InstManip instance for detailed information about phase 5 slot -// contents. +// contents. If there is no registered instrumentation for the phase 5 slot, leave a +// nop in place of the branch to reduce runtime overhead. // // 3. Deallocate the slot that originated this invocation of phase4(). // +// PHASE 5: Phase 5 isn't like the other phases; rather, it simply invokes all +// registered instrumentation functions for a particular site. #include #include @@ -399,18 +402,6 @@ ::doFlush(srcAddr, srcAddr + im->getInstWidth()); return slotBase; - -#if 0 - // Obtain a new slot of the given size - uint64_t slotBase = tc->getMemMgr()->getMemory(slotSize); - assert(slotBase && "Unable to obtain memory from MemoryManager instance"); - - // Replace instruction at srcAddr with branch to start of new slot - tc->getVM()->writeInstToVM(srcAddr, im->getBranchAlways(slotBase, srcAddr)); - ::doFlush(srcAddr, srcAddr + im->getInstWidth()); - - return slotBase; -#endif } static void dumpSnippet(vector& snippet, InstManip* im) @@ -610,7 +601,7 @@ for(unsigned i = 0; i < ppGBTSize; ++i) { ostr << "[pp] ppGBT[" << i << "]: " << ppGBT[i].gbtType << ", " - << ppGBT[i].loadVar << ", " << ppGBT[i].gbtStartIdx << endl; + << ppGBT[i].loadVar << endl; } } @@ -690,14 +681,6 @@ m_pPhase4Info->getCandidate().front().second); } -#if 0 - // (TEMP) For now, restore the candidate load to its original position for debugging - // purposes. - - m_pPhase4Info->getTraceCache()->getVM()->writeInstToVM(m_pPhase4Info->getCandidate().front().first, - m_pPhase4Info->getCandidate().front().second); -#endif - DEBUG_MSG(1, "================ End Phase 4 ================\n"); } @@ -709,32 +692,6 @@ InstSiteInfo* siteInfo = InstInfo::findSiteInfo(gbte->siteID, gbte->gbtType); siteInfo->invokeFunctions(); DEBUG_MSG(1, "================ End Phase 5 ================\n"); - -#if 0 - switch(gbte->gbtType){ - case pp::GBT_INTERVAL_START: { - DEBUG_MSG(1, "--- phase 5 start site invocation ---\n"); - DEBUG_MSG(2, "retVal address is " << HEX(gbte->retVal) << endl); - - void (*instFunc)(void*) = (void (*)(void*)) gbte->instFunc; - instFunc(gbte->retVal); - break; - } - case pp::GBT_INTERVAL_END: { - DEBUG_MSG(1, "--- phase 5 end site invocation ---\n"); - DEBUG_MSG(2, "start parameter is at gbt index " << gbte->gbtStartIdx << endl); - DEBUG_MSG(2, "start parameter addr is " - << HEX(ppGBT[gbte->gbtStartIdx].retVal) << endl); - - void (*instFunc)(void*, void*) = (void (*)(void*, void*)) gbte->instFunc; - instFunc(gbte->retVal, ppGBT[gbte->gbtStartIdx].retVal); - - break; - } - } - - DEBUG_MSG(1, "--- phase 5 invocation completed ---\n" << std::flush); -#endif } //////////////// InstSiteInfo implementation //////////////// @@ -749,10 +706,10 @@ if(!isRegistered(func)) { DEBUG_MSG(3, "not yet registered, registering...\n"); + void* retVal = static_cast(new char[retValBytes]); m_registeredFuncs.insert(func); - fi = new InstFunctionInfo(retVal, func); - m_instFuncInfos.push_back(fi); + m_instFuncInfos.push_back(fi = new InstFunctionInfo(retVal, func)); installBranch(); } else @@ -770,6 +727,7 @@ if(!isRegistered(func)) { DEBUG_MSG(3, "not yet registered, registering...\n"); + m_registeredFuncs.insert(func); m_instFuncInfos.push_back(new InstFunctionInfo(retVal, func, startInfo)); installBranch(); Index: llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp diff -u llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.16.2.1 llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.16.2.2 --- llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp:1.16.2.1 Fri May 30 10:25:34 2003 +++ llvm/lib/Reoptimizer/Inst/lib/SparcInstManip.cpp Fri May 30 10:57:09 2003 @@ -242,16 +242,6 @@ DEBUG_MSG(2, "buildPhase5HeapSlot completed\n"); -#if 0 - // If we're dealing with a start-interval instrumentation function, heap-allocate - // its parameter memory - - if(gbte->gbtType == pp::GBT_INTERVAL_START) { - assert(!gbte->retVal && "Expected null retVal value"); - gbte->retVal = static_cast(new char[gbte->paramSize]); - } -#endif - //////////////// // Construct the phase 5 jump slot From jstanley at cs.uiuc.edu Fri May 30 11:36:00 2003 From: jstanley at cs.uiuc.edu (Joel Stanley) Date: Fri May 30 11:36:00 2003 Subject: [llvm-commits] CVS: llvm/lib/Reoptimizer/Inst/lib/Phases.cpp Message-ID: <200305301635.LAA20706@trinity.cs.uiuc.edu> Changes in directory llvm/lib/Reoptimizer/Inst/lib: Phases.cpp updated: 1.35.2.2 -> 1.35.2.3 --- Log message: Added handling for the case where new instrumentation is dynamically registered with an interval while within the interval boundaries. --- Diffs of the changes: Index: llvm/lib/Reoptimizer/Inst/lib/Phases.cpp diff -u llvm/lib/Reoptimizer/Inst/lib/Phases.cpp:1.35.2.2 llvm/lib/Reoptimizer/Inst/lib/Phases.cpp:1.35.2.3 --- llvm/lib/Reoptimizer/Inst/lib/Phases.cpp:1.35.2.2 Fri May 30 10:57:09 2003 +++ llvm/lib/Reoptimizer/Inst/lib/Phases.cpp Fri May 30 11:34:48 2003 @@ -150,11 +150,11 @@ uint64_t m_tag; // Entry to look for in the GBT }; -// InstFunctionInfo is the class used to represent information (e.g., address of -// return value, pointer-to-instrumentation function) about particular -// registered instrumentation functions. In the case of end-interval functions, -// the link 'm_pStart' is filled in to refer to the InstFunctionInfo instance -// that contains information about the corresponding start-interval function. +// InstFunctionInfo is the class used to represent information (e.g., address of return +// value, pointer-to-instrumentation function) about particular registered instrumentation +// functions. In the case of end-interval functions, the link 'm_pStart' is filled in to +// refer to the InstFunctionInfo instance that contains information about the +// corresponding start-interval function. class InstFunctionInfo { @@ -162,11 +162,18 @@ InstFunctionInfo(void* pRetVal, void* pInstFunc, InstFunctionInfo* pStart = 0): - m_pRetVal(pRetVal), m_pInstFunc(pInstFunc), m_pStart(pStart) + m_pRetVal(pRetVal), + m_pInstFunc(pInstFunc), + m_pStart(pStart), + m_invoked(false) { } - InstFunctionInfo(): m_pRetVal(0), m_pInstFunc(0), m_pStart(0) + InstFunctionInfo(): + m_pRetVal(0), + m_pInstFunc(0), + m_pStart(0), + m_invoked(false) { } @@ -176,6 +183,7 @@ void* m_pRetVal; void* m_pInstFunc; InstFunctionInfo* m_pStart; // Info about start-interval function + bool m_invoked; // Has this function been invoked yet? }; // InstSiteInfo instances contain information about the state of particular @@ -762,16 +770,32 @@ void InstFunctionInfo::invoke() { + // In the case of start-interval functions, the boolean m_invoked is set to true upon + // completion of the invocation. This same boolean (i.e, the one associated with the + // start-interval InstFunctionInfo instance) is cleared by the corresponding + // end-interval function invocation. This is to ensure that no end-interval + // instrumentation function is ever invoked unless its corresponding start-interval + // instrumentation function has been invoked (which implies that the start-interval + // site has been handled properly and all of the registration mechanisms). + DEBUG_MSG(3, "(InstFunctionInfo::invoke) retVal address is: " << HEX(m_pRetVal) << endl); if(m_pStart) { DEBUG_MSG(3, "End-interval inst func detected\n"); void (*instFunc)(void*, void*) = (void (*)(void*, void*)) m_pInstFunc; - instFunc(m_pRetVal, m_pStart->m_pRetVal); + + if(m_pStart->m_invoked) { + DEBUG_MSG(4, "Corresponding start function has been invoked, so invoking this inst func\n"); + instFunc(m_pRetVal, m_pStart->m_pRetVal); + m_pStart->m_invoked = false; + } + else + DEBUG_MSG(4, "Corresponding start func has not been invoked, so not invoking\n"); } else { DEBUG_MSG(3, "Start-interval or non-end inst func detected\n"); void (*instFunc)(void*) = (void (*)(void*)) m_pInstFunc; instFunc(m_pRetVal); + m_invoked = true; } DEBUG_MSG(3, "(InstFunctionInfo::invoke) instrumentation function returned\n"); From lattner at cs.uiuc.edu Fri May 30 12:50:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri May 30 12:50:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/SingleSource/mandel.c Message-ID: <200305301749.MAA29511@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/SingleSource: mandel.c updated: 1.2 -> 1.3 --- Log message: Recheckin testcase that now works due to CFE bug fixes --- Diffs of the changes: Index: llvm/test/Programs/SingleSource/mandel.c diff -u /dev/null llvm/test/Programs/SingleSource/mandel.c:1.3 --- /dev/null Fri May 30 12:49:46 2003 +++ llvm/test/Programs/SingleSource/mandel.c Fri May 30 12:49:36 2003 @@ -0,0 +1,32 @@ +#include +#define ESCAPE 2 +#define IMAGE_SIZE 10 +#define START_X -2.0 +#define START_Y START_X +#define MAX_ITER 10 +#define step (-START_X - START_X)/IMAGE_SIZE +void emit(double complex X) { + printf("%f\n", (double)X); +} + +void mandel() { + int x, y, n; + for (x = 0; x < IMAGE_SIZE; ++x) { + for (y = 0; y < IMAGE_SIZE; ++y) { + double complex c = (START_X+x*step) + (START_Y-y*step) * I; + double complex z = 0.0; + + for (n = 0; n < MAX_ITER; ++n) { + z = z * z + c; + if (cabs(z) >= ESCAPE) + break; + } + emit(z); + } + } +} + +int main() { + mandel(); + return 0; +} From lattner at cs.uiuc.edu Fri May 30 13:06:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri May 30 13:06:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/SingleSource/mandel.c Message-ID: <200305301805.NAA31930@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/SingleSource: mandel.c updated: 1.3 -> 1.4 --- Log message: Remove dependency on complex.h which is not available on sun --- Diffs of the changes: Index: llvm/test/Programs/SingleSource/mandel.c diff -u llvm/test/Programs/SingleSource/mandel.c:1.3 llvm/test/Programs/SingleSource/mandel.c:1.4 --- llvm/test/Programs/SingleSource/mandel.c:1.3 Fri May 30 12:49:36 2003 +++ llvm/test/Programs/SingleSource/mandel.c Fri May 30 13:04:52 2003 @@ -1,11 +1,13 @@ -#include #define ESCAPE 2 #define IMAGE_SIZE 10 #define START_X -2.0 #define START_Y START_X #define MAX_ITER 10 #define step (-START_X - START_X)/IMAGE_SIZE -void emit(double complex X) { + +#define I 1.0iF + +void emit(double __complex__ X) { printf("%f\n", (double)X); } @@ -13,8 +15,8 @@ int x, y, n; for (x = 0; x < IMAGE_SIZE; ++x) { for (y = 0; y < IMAGE_SIZE; ++y) { - double complex c = (START_X+x*step) + (START_Y-y*step) * I; - double complex z = 0.0; + double __complex__ c = (START_X+x*step) + (START_Y-y*step) * I; + double __complex__ z = 0.0; for (n = 0; n < MAX_ITER; ++n) { z = z * z + c; From lattner at cs.uiuc.edu Fri May 30 13:06:10 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri May 30 13:06:10 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/SingleSource/Makefile Message-ID: <200305301805.NAA31898@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/SingleSource: Makefile updated: 1.7 -> 1.8 --- Log message: Add support for tests that use the math library --- Diffs of the changes: Index: llvm/test/Programs/SingleSource/Makefile diff -u llvm/test/Programs/SingleSource/Makefile:1.7 llvm/test/Programs/SingleSource/Makefile:1.8 --- llvm/test/Programs/SingleSource/Makefile:1.7 Wed May 14 14:00:38 2003 +++ llvm/test/Programs/SingleSource/Makefile Fri May 30 13:05:03 2003 @@ -1,4 +1,5 @@ LEVEL = ../../.. PARALLEL_DIRS = UnitTests Shootout Stanford CustomChecked +LDFLAGS += -lm include Makefile.singlesrc From brukman at cs.uiuc.edu Fri May 30 13:07:03 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 30 13:07:03 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcV9_F3.td Message-ID: <200305301806.NAA31427@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcV9_F3.td updated: 1.2 -> 1.3 --- Log message: Because the format of the shift instructions is `shift r, shcnt, r', the instructions of format 3.12 and 3.13 cannot inherit from F3rdrs1, because that implies that the two registers are the first two parameters to the instruction. Thus I made the instructions inherit from F3rd again, and manually added an rs1 field AFTER the shcnt field in the instruction, which maps to the appropriate place in the instruction. The other changes are just elimination of unnecessary spaces. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/SparcV9_F3.td diff -u llvm/lib/Target/Sparc/SparcV9_F3.td:1.2 llvm/lib/Target/Sparc/SparcV9_F3.td:1.3 --- llvm/lib/Target/Sparc/SparcV9_F3.td:1.2 Fri May 30 03:02:14 2003 +++ llvm/lib/Target/Sparc/SparcV9_F3.td Fri May 30 13:06:10 2003 @@ -66,7 +66,7 @@ // Specific F3 classes... // -class F3_1 opVal, bits<6> op3val, string name> : F3_rdrs1rs2 { +class F3_1 opVal, bits<6> op3val, string name> : F3_rdrs1rs2 { set op = opVal; set op3 = op3val; set Name = name; @@ -74,21 +74,21 @@ //set Inst{12-5} = dontcare; } -class F3_2 opVal, bits<6> op3val, string name> : F3_rdsimm13rs1 { +class F3_2 opVal, bits<6> op3val, string name> : F3_rdsimm13rs1 { set op = opVal; set op3 = op3val; set Name = name; set Inst{13} = 1; // i field = 1 } -class F3_3 opVal, bits<6> op3val, string name> : F3_rs1rs2 { +class F3_3 opVal, bits<6> op3val, string name> : F3_rs1rs2 { set op = opVal; set op3 = op3val; set Name = name; set Inst{13} = 0; } -class F3_4 opVal, bits<6> op3Val, string name> : F3_rs1simm13 { +class F3_4 opVal, bits<6> op3Val, string name> : F3_rs1simm13 { bits<13> simm; set op = opVal; set op3 = op3Val; @@ -98,7 +98,7 @@ set Inst{12-0} = simm; } -class F3_11 opVal, bits<6> op3Val, string name> : F3_rdrs1rs2 { +class F3_11 opVal, bits<6> op3Val, string name> : F3_rdrs1rs2 { bit x; set op = opVal; set op3 = op3Val; @@ -108,24 +108,28 @@ //set Inst{11-5} = dontcare; } -class F3_12 opVal, bits<6> op3Val, string name> : F3_rdrs1 { +class F3_12 opVal, bits<6> op3Val, string name> : F3_rd { bits<5> shcnt; + bits<5> rs1; set op = opVal; set op3 = op3Val; set Name = name; + set Inst{18-14} = rs1; set Inst{13} = 1; // i field = 1 set Inst{12} = 0; // x field = 0 //set Inst{11-5} = dontcare; set Inst{4-0} = shcnt; } -class F3_13 opVal, bits<6> op3Val, string name> : F3_rdrs1 { +class F3_13 opVal, bits<6> op3Val, string name> : F3_rd { bits<6> shcnt; + bits<5> rs1; set op = opVal; set op3 = op3Val; set Name = name; + set Inst{18-14} = rs1; set Inst{13} = 1; // i field = 1 set Inst{12} = 1; // x field = 1 //set Inst{11-6} = dontcare; From lattner at cs.uiuc.edu Fri May 30 13:11:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri May 30 13:11:02 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp Message-ID: <200305301810.NAA00692@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: ScalarReplAggregates.cpp updated: 1.4 -> 1.5 --- Log message: add a check that allows the SRoA pass to avoid breaking programs, even if their behavior is technically undefined --- Diffs of the changes: Index: llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp diff -u llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp:1.4 llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp:1.5 --- llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp:1.4 Fri May 30 00:26:30 2003 +++ llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp Fri May 30 13:09:57 2003 @@ -23,6 +23,7 @@ bool runOnFunction(Function &F); private: + bool isSafeStructElementUse(Value *Ptr); bool isSafeArrayElementUse(Value *Ptr); bool isSafeUseOfAllocation(Instruction *User); bool isSafeStructAllocaToPromote(AllocationInst *AI); @@ -166,6 +167,31 @@ return true; } +/// isSafeStructElementUse - It is illegal in C to take the address of a +/// structure sub-element, and then use pointer arithmetic to access other +/// elements of the struct. Despite the fact that this is illegal, some +/// programs do this, so do at least a simple check to try to avoid breaking +/// broken programs if possible. +/// +bool SROA::isSafeStructElementUse(Value *Ptr) { + for (Value::use_iterator I = Ptr->use_begin(), E = Ptr->use_end(); + I != E; ++I) + if (GetElementPtrInst *GEP = dyn_cast(*I)) { + if (GEP->getNumOperands() > 1) { + if (!isa(GEP->getOperand(1)) || + !cast(GEP->getOperand(1))->isNullValue()) { + std::cerr << "WARNING: Undefined behavior found: " << *GEP + << " ... uses pointer arithmetic to access other struct " + << "elements!\n"; + return false; + + return false; // Using pointer arithmetic to navigate the array... + } + } + } + + return true; +} /// isSafeArrayElementUse - Check to see if this use is an allowed use for a /// getelementptr instruction of an array aggregate allocation. @@ -210,12 +236,18 @@ // the users are safe to transform. // for (Value::use_iterator I = AI->use_begin(), E = AI->use_end(); - I != E; ++I) + I != E; ++I) { if (!isSafeUseOfAllocation(cast(*I))) { DEBUG(std::cerr << "Cannot transform: " << *AI << " due to user: " << *I); return false; } + + // Pedantic check to avoid breaking broken programs... + if (GetElementPtrInst *GEPI = dyn_cast(*I)) + if (GEPI->getNumOperands() == 3 && !isSafeStructElementUse(GEPI)) + return false; + } return true; } From brukman at cs.uiuc.edu Fri May 30 14:15:05 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 30 14:15:05 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcInstr.def Message-ID: <200305301914.OAA31957@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcInstr.def updated: 1.16 -> 1.17 --- Log message: Made the register and immediate versions of instructions consecutive. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/SparcInstr.def diff -u llvm/lib/Target/Sparc/SparcInstr.def:1.16 llvm/lib/Target/Sparc/SparcInstr.def:1.17 --- llvm/lib/Target/Sparc/SparcInstr.def:1.16 Tue May 27 17:32:38 2003 +++ llvm/lib/Target/Sparc/SparcInstr.def Fri May 30 14:14:01 2003 @@ -136,19 +136,17 @@ // Shift operations I(SLLr6 , "sll", 3, 2, B5, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG) -I(SRLr6 , "srl", 3, 2, B5, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG) -I(SRAr6 , "sra", 3, 2, B5, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_ARITH_FLAG) -I(SLLXr6, "sllx", 3, 2, B6, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG) -I(SRLXr6, "srlx", 3, 2, B6, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG) -I(SRAXr6, "srax", 3, 2, B6, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_ARITH_FLAG) - I(SLLi6 , "sll", 3, 2, B5, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG) +I(SRLr6 , "srl", 3, 2, B5, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG) I(SRLi6 , "srl", 3, 2, B5, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG) +I(SRAr6 , "sra", 3, 2, B5, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_ARITH_FLAG) I(SRAi6 , "sra", 3, 2, B5, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_ARITH_FLAG) +I(SLLXr6, "sllx", 3, 2, B6, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG) I(SLLXi6, "sllx", 3, 2, B6, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG) +I(SRLXr6, "srlx", 3, 2, B6, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG) I(SRLXi6, "srlx", 3, 2, B6, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG) +I(SRAXr6, "srax", 3, 2, B6, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_ARITH_FLAG) I(SRAXi6, "srax", 3, 2, B6, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_ARITH_FLAG) - // Floating point move, negate, and abs instructions I(FMOVS, "fmovs", 2, 1, 0, false, 0, 1, SPARC_FPA, M_FLOAT_FLAG) From lattner at cs.uiuc.edu Fri May 30 14:23:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri May 30 14:23:02 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp Message-ID: <200305301922.OAA07196@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: ScalarReplAggregates.cpp updated: 1.5 -> 1.6 --- Log message: Okay totally give up on trying to optimize aggregates that cannot be completely broken up into their elements. Too many programs break because of this. --- Diffs of the changes: Index: llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp diff -u llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp:1.5 llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp:1.6 --- llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp:1.5 Fri May 30 13:09:57 2003 +++ llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp Fri May 30 14:22:14 2003 @@ -23,8 +23,7 @@ bool runOnFunction(Function &F); private: - bool isSafeStructElementUse(Value *Ptr); - bool isSafeArrayElementUse(Value *Ptr); + bool isSafeElementUse(Value *Ptr); bool isSafeUseOfAllocation(Instruction *User); bool isSafeStructAllocaToPromote(AllocationInst *AI); bool isSafeArrayAllocaToPromote(AllocationInst *AI); @@ -167,36 +166,10 @@ return true; } -/// isSafeStructElementUse - It is illegal in C to take the address of a -/// structure sub-element, and then use pointer arithmetic to access other -/// elements of the struct. Despite the fact that this is illegal, some -/// programs do this, so do at least a simple check to try to avoid breaking -/// broken programs if possible. -/// -bool SROA::isSafeStructElementUse(Value *Ptr) { - for (Value::use_iterator I = Ptr->use_begin(), E = Ptr->use_end(); - I != E; ++I) - if (GetElementPtrInst *GEP = dyn_cast(*I)) { - if (GEP->getNumOperands() > 1) { - if (!isa(GEP->getOperand(1)) || - !cast(GEP->getOperand(1))->isNullValue()) { - std::cerr << "WARNING: Undefined behavior found: " << *GEP - << " ... uses pointer arithmetic to access other struct " - << "elements!\n"; - return false; - - return false; // Using pointer arithmetic to navigate the array... - } - } - } - - return true; -} - -/// isSafeArrayElementUse - Check to see if this use is an allowed use for a +/// isSafeElementUse - Check to see if this use is an allowed use for a /// getelementptr instruction of an array aggregate allocation. /// -bool SROA::isSafeArrayElementUse(Value *Ptr) { +bool SROA::isSafeElementUse(Value *Ptr) { for (Value::use_iterator I = Ptr->use_begin(), E = Ptr->use_end(); I != E; ++I) { Instruction *User = cast(*I); @@ -209,15 +182,8 @@ if (!isa(GEP->getOperand(1)) || !cast(GEP->getOperand(1))->isNullValue()) return false; // Using pointer arithmetic to navigate the array... - - // Check to see if there are any structure indexes involved in this GEP. - // If so, then we can safely break the array up until at least the - // structure. - for (unsigned i = 2, e = GEP->getNumOperands(); i != e; ++i) - if (GEP->getOperand(i)->getType()->isUnsigned()) - break; } - return isSafeArrayElementUse(GEP); + return isSafeElementUse(GEP); } default: DEBUG(std::cerr << " Transformation preventing inst: " << *User); @@ -245,7 +211,7 @@ // Pedantic check to avoid breaking broken programs... if (GetElementPtrInst *GEPI = dyn_cast(*I)) - if (GEPI->getNumOperands() == 3 && !isSafeStructElementUse(GEPI)) + if (GEPI->getNumOperands() == 3 && !isSafeElementUse(GEPI)) return false; } return true; @@ -285,7 +251,7 @@ // P = &A[0]; P = P + 1 // is legal, and should prevent promotion. // - if (!isSafeArrayElementUse(GEPI)) { + if (!isSafeElementUse(GEPI)) { DEBUG(std::cerr << "Cannot transform: " << *AI << " due to uses of user: " << *GEPI); return false; From lattner at cs.uiuc.edu Fri May 30 14:24:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri May 30 14:24:01 2003 Subject: [llvm-commits] CVS: llvm/tools/gccas/gccas.cpp Message-ID: <200305301923.OAA08354@apoc.cs.uiuc.edu> Changes in directory llvm/tools/gccas: gccas.cpp updated: 1.63 -> 1.64 --- Log message: Move indvars pass after mem2reg pass where it is more likely to be useful --- Diffs of the changes: Index: llvm/tools/gccas/gccas.cpp diff -u llvm/tools/gccas/gccas.cpp:1.63 llvm/tools/gccas/gccas.cpp:1.64 --- llvm/tools/gccas/gccas.cpp:1.63 Fri May 2 13:19:05 2003 +++ llvm/tools/gccas/gccas.cpp Fri May 30 14:23:10 2003 @@ -71,10 +71,10 @@ addPass(PM, createDeadInstEliminationPass()); // Remove Dead code/vars addPass(PM, createRaiseAllocationsPass()); // call %malloc -> malloc inst addPass(PM, createInstructionCombiningPass()); // Cleanup code for raise - addPass(PM, createIndVarSimplifyPass()); // Simplify indvars addPass(PM, createRaisePointerReferencesPass());// Recover type information addPass(PM, createInstructionCombiningPass()); // Combine silly seq's addPass(PM, createPromoteMemoryToRegister()); // Promote alloca's to regs + addPass(PM, createIndVarSimplifyPass()); // Simplify indvars addPass(PM, createReassociatePass()); // Reassociate expressions //addPass(PM, createCorrelatedExpressionEliminationPass());// Kill corr branches addPass(PM, createInstructionCombiningPass()); // Combine silly seq's From lattner at cs.uiuc.edu Fri May 30 14:25:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri May 30 14:25:01 2003 Subject: [llvm-commits] CVS: llvm/tools/gccas/gccas.cpp Message-ID: <200305301924.OAA08872@apoc.cs.uiuc.edu> Changes in directory llvm/tools/gccas: gccas.cpp updated: 1.64 -> 1.65 --- Log message: Add SRoA pass to gccas --- Diffs of the changes: Index: llvm/tools/gccas/gccas.cpp diff -u llvm/tools/gccas/gccas.cpp:1.64 llvm/tools/gccas/gccas.cpp:1.65 --- llvm/tools/gccas/gccas.cpp:1.64 Fri May 30 14:23:10 2003 +++ llvm/tools/gccas/gccas.cpp Fri May 30 14:24:06 2003 @@ -73,6 +73,7 @@ addPass(PM, createInstructionCombiningPass()); // Cleanup code for raise addPass(PM, createRaisePointerReferencesPass());// Recover type information addPass(PM, createInstructionCombiningPass()); // Combine silly seq's + addPass(PM, createScalarReplAggregatesPass()); // Break up aggregate allocas addPass(PM, createPromoteMemoryToRegister()); // Promote alloca's to regs addPass(PM, createIndVarSimplifyPass()); // Simplify indvars addPass(PM, createReassociatePass()); // Reassociate expressions From brukman at cs.uiuc.edu Fri May 30 14:59:01 2003 From: brukman at cs.uiuc.edu (Michael Brukman) Date: Fri May 30 14:59:01 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/SingleSource/mandel.c Message-ID: <200305301958.OAA06604@trinity.cs.uiuc.edu> Changes in directory llvm/test/Programs/SingleSource: mandel.c updated: 1.4 -> 1.5 --- Log message: Sparcs are not C99-compliant and do not support complex numbers. So we must ignore this test case if compiling in Sparc. --- Diffs of the changes: Index: llvm/test/Programs/SingleSource/mandel.c diff -u llvm/test/Programs/SingleSource/mandel.c:1.4 llvm/test/Programs/SingleSource/mandel.c:1.5 --- llvm/test/Programs/SingleSource/mandel.c:1.4 Fri May 30 13:04:52 2003 +++ llvm/test/Programs/SingleSource/mandel.c Fri May 30 14:58:09 2003 @@ -1,3 +1,10 @@ +/* Sparc is not C99-compliant */ +#if defined(sparc) || defined(__sparc__) || defined(__sparcv9) + +int main() { return 0; } + +#else /* sparc */ + #define ESCAPE 2 #define IMAGE_SIZE 10 #define START_X -2.0 @@ -32,3 +39,5 @@ mandel(); return 0; } + +#endif /* sparc */ From brukman at cs.uiuc.edu Fri May 30 15:01:02 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 30 15:01:02 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/Sparc.cpp Message-ID: <200305302000.PAA32146@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: Sparc.cpp updated: 1.63 -> 1.64 --- Log message: Make LLI behave just like LLC with regard to the compile passes it uses. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/Sparc.cpp diff -u llvm/lib/Target/Sparc/Sparc.cpp:1.63 llvm/lib/Target/Sparc/Sparc.cpp:1.64 --- llvm/lib/Target/Sparc/Sparc.cpp:1.63 Tue May 27 17:24:48 2003 +++ llvm/lib/Target/Sparc/Sparc.cpp Fri May 30 15:00:13 2003 @@ -208,14 +208,29 @@ //so %fp+offset-8 and %fp+offset-16 are empty slots now! PM.add(createStackSlotsPass(*this)); + // Specialize LLVM code for this target machine and then + // run basic dataflow optimizations on LLVM code. + if (!DisablePreSelect) { + PM.add(createPreSelectionPass(*this)); + PM.add(createReassociatePass()); + PM.add(createLICMPass()); + PM.add(createGCSEPass()); + } + PM.add(createInstructionSelectionPass(*this)); + if (!DisableSched) + PM.add(createInstructionSchedulingWithSSAPass(*this)); + // new pass: convert Value* in MachineOperand to an unsigned register // this brings it in line with what the X86 JIT's RegisterAllocator expects //PM.add(createAddRegNumToValuesPass()); PM.add(getRegisterAllocator(*this)); PM.add(getPrologEpilogInsertionPass()); + + if (!DisablePeephole) + PM.add(createPeepholeOptsPass(*this)); return false; // success! } From lattner at cs.uiuc.edu Fri May 30 15:12:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri May 30 15:12:02 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c Message-ID: <200305302011.PAA11601@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/SingleSource/UnitTests: 2003-05-07-VarArgs.c updated: 1.6 -> 1.7 --- Log message: Test for va_arg support for aggregates --- Diffs of the changes: Index: llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c diff -u llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c:1.6 llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c:1.7 --- llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c:1.6 Tue May 27 09:09:04 2003 +++ llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c Fri May 30 15:11:06 2003 @@ -47,17 +47,17 @@ printf("char %c\n", c); break; case 'D': - /* dw = va_arg(ap, DWordS); + dw = va_arg(ap, DWordS); printf("DWord { %d, %c }\n", dw.i, dw.c); - */ break; + break; case 'Q': - /* qw = va_arg(ap, QuadWordS); + qw = va_arg(ap, QuadWordS); printf("QuadWord { %d, %f }\n", qw.i, qw.d); - */ break; + break; case 'L': - /* ls = va_arg(ap, LargeS); + ls = va_arg(ap, LargeS); printf("LargeS { %d, %f, 0x%p, %d }\n", ls.i, ls.d, ls.ptr, ls.j); - */ break; + break; } va_end(ap); } From brukman at cs.uiuc.edu Fri May 30 15:13:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 30 15:13:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcInstrSelection.cpp SparcInstrSelectionSupport.h Message-ID: <200305302012.PAA32195@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcInstrSelection.cpp updated: 1.95 -> 1.96 SparcInstrSelectionSupport.h updated: 1.7 -> 1.8 --- Log message: Moved and expanded convertOpcodeFromRegToImm() to conver more opcodes. Code beautification for the rest of the code: changed layout to match the rest of the code base. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/SparcInstrSelection.cpp diff -u llvm/lib/Target/Sparc/SparcInstrSelection.cpp:1.95 llvm/lib/Target/Sparc/SparcInstrSelection.cpp:1.96 --- llvm/lib/Target/Sparc/SparcInstrSelection.cpp:1.95 Tue May 27 17:37:00 2003 +++ llvm/lib/Target/Sparc/SparcInstrSelection.cpp Fri May 30 15:11:56 2003 @@ -698,11 +698,11 @@ opCode = V9::MULXr; else switch(resultType->getPrimitiveID()) - { - case Type::FloatTyID: opCode = V9::FMULS; break; - case Type::DoubleTyID: opCode = V9::FMULD; break; - default: assert(0 && "Invalid type for MUL instruction"); break; - } + { + case Type::FloatTyID: opCode = V9::FMULS; break; + case Type::DoubleTyID: opCode = V9::FMULD; break; + default: assert(0 && "Invalid type for MUL instruction"); break; + } return opCode; } @@ -747,11 +747,11 @@ // Value* shiftDest = destVal; unsigned opSize = target.getTargetData().getTypeSize(argVal1->getType()); - if ((shiftOpCode == V9::SLLr6 || shiftOpCode == V9::SLLXr6) && opSize < 8) - { // put SLL result into a temporary - shiftDest = new TmpInstruction(argVal1, optArgVal2, "sllTmp"); - mcfi.addTemp(shiftDest); - } + if ((shiftOpCode == V9::SLLr6 || shiftOpCode == V9::SLLXr6) && opSize < 8) { + // put SLL result into a temporary + shiftDest = new TmpInstruction(argVal1, optArgVal2, "sllTmp"); + mcfi.addTemp(shiftDest); + } MachineInstr* M = (optArgVal2 != NULL) ? BuildMI(shiftOpCode, 3).addReg(argVal1).addReg(optArgVal2) @@ -760,13 +760,13 @@ .addReg(shiftDest, MOTy::Def); mvec.push_back(M); - if (shiftDest != destVal) - { // extend the sign-bit of the result into all upper bits of dest - assert(8*opSize <= 32 && "Unexpected type size > 4 and < IntRegSize?"); - target.getInstrInfo(). - CreateSignExtensionInstructions(target, F, shiftDest, destVal, - 8*opSize, mvec, mcfi); - } + if (shiftDest != destVal) { + // extend the sign-bit of the result into all upper bits of dest + assert(8*opSize <= 32 && "Unexpected type size > 4 and < IntRegSize?"); + target.getInstrInfo(). + CreateSignExtensionInstructions(target, F, shiftDest, destVal, + 8*opSize, mvec, mcfi); + } } @@ -814,16 +814,15 @@ else M = BuildMI(V9::ADDr,3).addReg(lval).addMReg(Zero).addRegDef(destVal); mvec.push_back(M); - } - else if (isPowerOf2(C, pow)) { + } else if (isPowerOf2(C, pow)) { unsigned opSize = target.getTargetData().getTypeSize(resultType); MachineOpCode opCode = (opSize <= 32)? V9::SLLr6 : V9::SLLXr6; CreateShiftInstructions(target, F, opCode, lval, NULL, pow, destVal, mvec, mcfi); } - if (mvec.size() > 0 && needNeg) - { // insert after the instr to flip the sign + if (mvec.size() > 0 && needNeg) { + // insert after the instr to flip the sign MachineInstr* M = CreateIntNegInstruction(target, destVal); mvec.push_back(M); } @@ -862,12 +861,13 @@ MachineCodeForInstruction& mcfi) { Value* constOp; - if (isa(lval) && isa(rval)) - { // both operands are constant: evaluate and "set" in dest - Constant* P = ConstantFoldBinaryInstruction(Instruction::Mul, - cast(lval), cast(rval)); - target.getInstrInfo().CreateCodeToLoadConst(target,F,P,destVal,mvec,mcfi); - } + if (isa(lval) && isa(rval)) { + // both operands are constant: evaluate and "set" in dest + Constant* P = ConstantFoldBinaryInstruction(Instruction::Mul, + cast(lval), + cast(rval)); + target.getInstrInfo().CreateCodeToLoadConst(target,F,P,destVal,mvec,mcfi); + } else if (isa(rval)) // rval is constant, but not lval CreateMulConstInstruction(target, F, lval, rval, destVal, mvec, mcfi); else if (isa(lval)) // lval is constant, but not rval @@ -946,8 +946,7 @@ // const Type* resultType = instrNode->getInstruction()->getType(); - if (resultType->isInteger()) - { + if (resultType->isInteger()) { unsigned pow; bool isValidConst; int64_t C = GetConstantValueAsSignedInt(constOp, isValidConst); @@ -995,8 +994,7 @@ // Get the shift operand and "right-shift" opcode to do the divide shiftOperand = addTmp; opCode = (resultType==Type::LongTy) ? V9::SRAXi6 : V9::SRAi6; - } - else { + } else { // Get the shift operand and "right-shift" opcode to do the divide shiftOperand = LHS; opCode = (resultType==Type::LongTy) ? V9::SRLXi6 : V9::SRLi6; @@ -1041,41 +1039,38 @@ // Enforce the alignment constraints on the stack pointer at // compile time if the total size is a known constant. - if (isa(numElementsVal)) - { - bool isValid; - int64_t numElem = GetConstantValueAsSignedInt(numElementsVal, isValid); - assert(isValid && "Unexpectedly large array dimension in alloca!"); - int64_t total = numElem * tsize; - if (int extra= total % target.getFrameInfo().getStackFrameSizeAlignment()) - total += target.getFrameInfo().getStackFrameSizeAlignment() - extra; - totalSizeVal = ConstantSInt::get(Type::IntTy, total); - } - else - { - // The size is not a constant. Generate code to compute it and - // code to pad the size for stack alignment. - // Create a Value to hold the (constant) element size - Value* tsizeVal = ConstantSInt::get(Type::IntTy, tsize); - - // Create temporary values to hold the result of MUL, SLL, SRL - // THIS CASE IS INCOMPLETE AND WILL BE FIXED SHORTLY. - TmpInstruction* tmpProd = new TmpInstruction(numElementsVal, tsizeVal); - TmpInstruction* tmpSLL = new TmpInstruction(numElementsVal, tmpProd); - TmpInstruction* tmpSRL = new TmpInstruction(numElementsVal, tmpSLL); - mcfi.addTemp(tmpProd); - mcfi.addTemp(tmpSLL); - mcfi.addTemp(tmpSRL); - - // Instruction 1: mul numElements, typeSize -> tmpProd - // This will optimize the MUL as far as possible. - CreateMulInstruction(target, F, numElementsVal, tsizeVal, tmpProd,getMvec, - mcfi, INVALID_MACHINE_OPCODE); + if (isa(numElementsVal)) { + bool isValid; + int64_t numElem = GetConstantValueAsSignedInt(numElementsVal, isValid); + assert(isValid && "Unexpectedly large array dimension in alloca!"); + int64_t total = numElem * tsize; + if (int extra= total % target.getFrameInfo().getStackFrameSizeAlignment()) + total += target.getFrameInfo().getStackFrameSizeAlignment() - extra; + totalSizeVal = ConstantSInt::get(Type::IntTy, total); + } else { + // The size is not a constant. Generate code to compute it and + // code to pad the size for stack alignment. + // Create a Value to hold the (constant) element size + Value* tsizeVal = ConstantSInt::get(Type::IntTy, tsize); + + // Create temporary values to hold the result of MUL, SLL, SRL + // THIS CASE IS INCOMPLETE AND WILL BE FIXED SHORTLY. + TmpInstruction* tmpProd = new TmpInstruction(numElementsVal, tsizeVal); + TmpInstruction* tmpSLL = new TmpInstruction(numElementsVal, tmpProd); + TmpInstruction* tmpSRL = new TmpInstruction(numElementsVal, tmpSLL); + mcfi.addTemp(tmpProd); + mcfi.addTemp(tmpSLL); + mcfi.addTemp(tmpSRL); + + // Instruction 1: mul numElements, typeSize -> tmpProd + // This will optimize the MUL as far as possible. + CreateMulInstruction(target, F, numElementsVal, tsizeVal, tmpProd,getMvec, + mcfi, INVALID_MACHINE_OPCODE); - assert(0 && "Need to insert padding instructions here!"); + assert(0 && "Need to insert padding instructions here!"); - totalSizeVal = tmpProd; - } + totalSizeVal = tmpProd; + } // Get the constant offset from SP for dynamically allocated storage // and create a temporary Value to hold it. @@ -1140,39 +1135,6 @@ } -static unsigned -convertOpcodeFromRegToImm(unsigned Opcode) { - switch (Opcode) { - case V9::ADDr: return V9::ADDi; - - /* load opcodes */ - case V9::LDUBr: return V9::LDUBi; - case V9::LDSBr: return V9::LDSBi; - case V9::LDUHr: return V9::LDUHi; - case V9::LDSHr: return V9::LDSHi; - case V9::LDUWr: return V9::LDUWi; - case V9::LDSWr: return V9::LDSWi; - case V9::LDXr: return V9::LDXi; - case V9::LDFr: return V9::LDFi; - case V9::LDDFr: return V9::LDDFi; - - /* store opcodes */ - case V9::STBr: return V9::STBi; - case V9::STHr: return V9::STHi; - case V9::STWr: return V9::STWi; - case V9::STXr: return V9::STXi; - case V9::STFr: return V9::STFi; - case V9::STDFr: return V9::STDFi; - - default: - std::cerr << "Not handled opcode in convert from reg to imm: " << Opcode - << "\n"; - abort(); - return 0; - } -} - - //------------------------------------------------------------------------ // Function SetOperandsForMemInstr // @@ -1211,65 +1173,59 @@ // Check if there is an index vector and if so, compute the // right offset for structures and for arrays // - if (!idxVec.empty()) - { - const PointerType* ptrType = cast(ptrVal->getType()); + if (!idxVec.empty()) { + const PointerType* ptrType = cast(ptrVal->getType()); - // If all indices are constant, compute the combined offset directly. - if (allConstantIndices) - { - // Compute the offset value using the index vector. Create a - // virtual reg. for it since it may not fit in the immed field. - uint64_t offset = target.getTargetData().getIndexedOffset(ptrType,idxVec); - valueForRegOffset = ConstantSInt::get(Type::LongTy, offset); - } - else - { - // There is at least one non-constant offset. Therefore, this must - // be an array ref, and must have been lowered to a single non-zero - // offset. (An extra leading zero offset, if any, can be ignored.) - // Generate code sequence to compute address from index. - // - bool firstIdxIsZero = IsZero(idxVec[0]); - assert(idxVec.size() == 1U + firstIdxIsZero - && "Array refs must be lowered before Instruction Selection"); - - Value* idxVal = idxVec[firstIdxIsZero]; - - std::vector mulVec; - Instruction* addr = new TmpInstruction(Type::ULongTy, memInst); - MachineCodeForInstruction::get(memInst).addTemp(addr); - - // Get the array type indexed by idxVal, and compute its element size. - // The call to getTypeSize() will fail if size is not constant. - const Type* vecType = (firstIdxIsZero - ? GetElementPtrInst::getIndexedType(ptrType, + // If all indices are constant, compute the combined offset directly. + if (allConstantIndices) { + // Compute the offset value using the index vector. Create a + // virtual reg. for it since it may not fit in the immed field. + uint64_t offset = target.getTargetData().getIndexedOffset(ptrType,idxVec); + valueForRegOffset = ConstantSInt::get(Type::LongTy, offset); + } else { + // There is at least one non-constant offset. Therefore, this must + // be an array ref, and must have been lowered to a single non-zero + // offset. (An extra leading zero offset, if any, can be ignored.) + // Generate code sequence to compute address from index. + // + bool firstIdxIsZero = IsZero(idxVec[0]); + assert(idxVec.size() == 1U + firstIdxIsZero + && "Array refs must be lowered before Instruction Selection"); + + Value* idxVal = idxVec[firstIdxIsZero]; + + std::vector mulVec; + Instruction* addr = new TmpInstruction(Type::ULongTy, memInst); + MachineCodeForInstruction::get(memInst).addTemp(addr); + + // Get the array type indexed by idxVal, and compute its element size. + // The call to getTypeSize() will fail if size is not constant. + const Type* vecType = (firstIdxIsZero + ? GetElementPtrInst::getIndexedType(ptrType, std::vector(1U, idxVec[0]), /*AllowCompositeLeaf*/ true) : ptrType); - const Type* eltType = cast(vecType)->getElementType(); - ConstantUInt* eltSizeVal = ConstantUInt::get(Type::ULongTy, - target.getTargetData().getTypeSize(eltType)); - - // CreateMulInstruction() folds constants intelligently enough. - CreateMulInstruction(target, memInst->getParent()->getParent(), - idxVal, /* lval, not likely to be const*/ - eltSizeVal, /* rval, likely to be constant */ - addr, /* result */ - mulVec, MachineCodeForInstruction::get(memInst), - INVALID_MACHINE_OPCODE); + const Type* eltType = cast(vecType)->getElementType(); + ConstantUInt* eltSizeVal = ConstantUInt::get(Type::ULongTy, + target.getTargetData().getTypeSize(eltType)); + + // CreateMulInstruction() folds constants intelligently enough. + CreateMulInstruction(target, memInst->getParent()->getParent(), + idxVal, /* lval, not likely to be const*/ + eltSizeVal, /* rval, likely to be constant */ + addr, /* result */ + mulVec, MachineCodeForInstruction::get(memInst), + INVALID_MACHINE_OPCODE); - assert(mulVec.size() > 0 && "No multiply code created?"); - mvec.insert(mvec.end(), mulVec.begin(), mulVec.end()); - - valueForRegOffset = addr; - } - } - else - { - offsetOpType = MachineOperand::MO_SignExtendedImmed; - smallConstOffset = 0; + assert(mulVec.size() > 0 && "No multiply code created?"); + mvec.insert(mvec.end(), mulVec.begin(), mulVec.end()); + + valueForRegOffset = addr; } + } else { + offsetOpType = MachineOperand::MO_SignExtendedImmed; + smallConstOffset = 0; + } // For STORE: // Operand 0 is value, operand 1 is ptr, operand 2 is offset @@ -1279,19 +1235,19 @@ unsigned offsetOpNum, ptrOpNum; MachineInstr *MI; if (memInst->getOpcode() == Instruction::Store) { - if (offsetOpType == MachineOperand::MO_VirtualRegister) + if (offsetOpType == MachineOperand::MO_VirtualRegister) { MI = BuildMI(Opcode, 3).addReg(vmInstrNode->leftChild()->getValue()) .addReg(ptrVal).addReg(valueForRegOffset); - else { + } else { Opcode = convertOpcodeFromRegToImm(Opcode); MI = BuildMI(Opcode, 3).addReg(vmInstrNode->leftChild()->getValue()) .addReg(ptrVal).addSImm(smallConstOffset); } } else { - if (offsetOpType == MachineOperand::MO_VirtualRegister) + if (offsetOpType == MachineOperand::MO_VirtualRegister) { MI = BuildMI(Opcode, 3).addReg(ptrVal).addReg(valueForRegOffset) .addRegDef(memInst); - else { + } else { Opcode = convertOpcodeFromRegToImm(Opcode); MI = BuildMI(Opcode, 3).addReg(ptrVal).addSImm(smallConstOffset) .addRegDef(memInst); @@ -1333,33 +1289,31 @@ // The parent's mvec would be empty if it was itself forwarded. // Recursively call ForwardOperand in that case... // - if (mvec.size() == 0) - { - assert(parent->parent() != NULL && - "Parent could not have been forwarded, yet has no instructions?"); - ForwardOperand(treeNode, parent->parent(), operandNum); - } - else - { - for (unsigned i=0, N=mvec.size(); i < N; i++) + if (mvec.size() == 0) { + assert(parent->parent() != NULL && + "Parent could not have been forwarded, yet has no instructions?"); + ForwardOperand(treeNode, parent->parent(), operandNum); + } else { + for (unsigned i=0, N=mvec.size(); i < N; i++) { + MachineInstr* minstr = mvec[i]; + for (unsigned i=0, numOps=minstr->getNumOperands(); i < numOps; ++i) { + const MachineOperand& mop = minstr->getOperand(i); + if (mop.getType() == MachineOperand::MO_VirtualRegister && + mop.getVRegValue() == unusedOp) { - MachineInstr* minstr = mvec[i]; - for (unsigned i=0, numOps=minstr->getNumOperands(); i < numOps; ++i) - { - const MachineOperand& mop = minstr->getOperand(i); - if (mop.getType() == MachineOperand::MO_VirtualRegister && - mop.getVRegValue() == unusedOp) - minstr->SetMachineOperandVal(i, - MachineOperand::MO_VirtualRegister, fwdOp); - } + minstr->SetMachineOperandVal(i, MachineOperand::MO_VirtualRegister, + fwdOp); + } + } - for (unsigned i=0,numOps=minstr->getNumImplicitRefs(); igetImplicitRef(i) == unusedOp) - minstr->setImplicitRef(i, fwdOp, - minstr->getImplicitOp(i).opIsDefOnly(), - minstr->getImplicitOp(i).opIsDefAndUse()); + for (unsigned i=0,numOps=minstr->getNumImplicitRefs(); igetImplicitRef(i) == unusedOp) { + minstr->setImplicitRef(i, fwdOp, + minstr->getImplicitOp(i).opIsDefOnly(), + minstr->getImplicitOp(i).opIsDefAndUse()); } } + } } @@ -1728,34 +1682,30 @@ Instruction* destI = subtreeRoot->getInstruction(); Value* opVal = subtreeRoot->leftChild()->getValue(); const Type* opType = opVal->getType(); - if (opType->isIntegral() || isa(opType)) - { - unsigned opSize = target.getTargetData().getTypeSize(opType); - unsigned destSize = target.getTargetData().getTypeSize(destI->getType()); - if (opSize >= destSize) - { // Operand is same size as or larger than dest: - // zero- or sign-extend, according to the signeddness of - // the destination (see above). - if (destI->getType()->isSigned()) - target.getInstrInfo().CreateSignExtensionInstructions(target, + if (opType->isIntegral() || isa(opType)) { + unsigned opSize = target.getTargetData().getTypeSize(opType); + unsigned destSize = + target.getTargetData().getTypeSize(destI->getType()); + if (opSize >= destSize) { + // Operand is same size as or larger than dest: + // zero- or sign-extend, according to the signeddness of + // the destination (see above). + if (destI->getType()->isSigned()) + target.getInstrInfo().CreateSignExtensionInstructions(target, destI->getParent()->getParent(), opVal, destI, 8*destSize, mvec, MachineCodeForInstruction::get(destI)); - else - target.getInstrInfo().CreateZeroExtensionInstructions(target, + else + target.getInstrInfo().CreateZeroExtensionInstructions(target, destI->getParent()->getParent(), opVal, destI, 8*destSize, mvec, MachineCodeForInstruction::get(destI)); - } - else - forwardOperandNum = 0; // forward first operand to user - } - else if (opType->isFloatingPoint()) - { - CreateCodeToConvertFloatToInt(target, opVal, destI, mvec, - MachineCodeForInstruction::get(destI)); - if (destI->getType()->isUnsigned()) - maskUnsignedResult = true; // not handled by fp->int code - } - else + } else + forwardOperandNum = 0; // forward first operand to user + } else if (opType->isFloatingPoint()) { + CreateCodeToConvertFloatToInt(target, opVal, destI, mvec, + MachineCodeForInstruction::get(destI)); + if (destI->getType()->isUnsigned()) + maskUnsignedResult = true; // not handled by fp->int code + } else assert(0 && "Unrecognized operand type for convert-to-unsigned"); break; @@ -1768,13 +1718,11 @@ const Type* opType = opVal->getType(); if (opType->isIntegral() || isa(opType)) forwardOperandNum = 0; // forward first operand to user - else if (opType->isFloatingPoint()) - { - Instruction* destI = subtreeRoot->getInstruction(); - CreateCodeToConvertFloatToInt(target, opVal, destI, mvec, - MachineCodeForInstruction::get(destI)); - } - else + else if (opType->isFloatingPoint()) { + Instruction* destI = subtreeRoot->getInstruction(); + CreateCodeToConvertFloatToInt(target, opVal, destI, mvec, + MachineCodeForInstruction::get(destI)); + } else assert(0 && "Unrecognized operand type for convert-to-signed"); break; } @@ -1789,61 +1737,54 @@ // In the future, we'll want to do the same for the FdMULq instruction, // so do the check here instead of only for ToFloatTy(reg). // - if (subtreeRoot->parent() != NULL) - { - const MachineCodeForInstruction& mcfi = - MachineCodeForInstruction::get( + if (subtreeRoot->parent() != NULL) { + const MachineCodeForInstruction& mcfi = + MachineCodeForInstruction::get( cast(subtreeRoot->parent())->getInstruction()); - if (mcfi.size() == 0 || mcfi.front()->getOpCode() == V9::FSMULD) - forwardOperandNum = 0; // forward first operand to user - } + if (mcfi.size() == 0 || mcfi.front()->getOpCode() == V9::FSMULD) + forwardOperandNum = 0; // forward first operand to user + } - if (forwardOperandNum != 0) // we do need the cast - { - Value* leftVal = subtreeRoot->leftChild()->getValue(); - const Type* opType = leftVal->getType(); - MachineOpCode opCode=ChooseConvertToFloatInstr( + if (forwardOperandNum != 0) { // we do need the cast + Value* leftVal = subtreeRoot->leftChild()->getValue(); + const Type* opType = leftVal->getType(); + MachineOpCode opCode=ChooseConvertToFloatInstr( subtreeRoot->getOpLabel(), opType); - if (opCode == V9::INVALID_OPCODE) // no conversion needed - { - forwardOperandNum = 0; // forward first operand to user - } - else - { - // If the source operand is a non-FP type it must be - // first copied from int to float register via memory! - Instruction *dest = subtreeRoot->getInstruction(); - Value* srcForCast; - int n = 0; - if (! opType->isFloatingPoint()) - { - // Create a temporary to represent the FP register - // into which the integer will be copied via memory. - // The type of this temporary will determine the FP - // register used: single-prec for a 32-bit int or smaller, - // double-prec for a 64-bit int. - // - uint64_t srcSize = - target.getTargetData().getTypeSize(leftVal->getType()); - Type* tmpTypeToUse = - (srcSize <= 4)? Type::FloatTy : Type::DoubleTy; - srcForCast = new TmpInstruction(tmpTypeToUse, dest); - MachineCodeForInstruction &destMCFI = - MachineCodeForInstruction::get(dest); - destMCFI.addTemp(srcForCast); + if (opCode == V9::INVALID_OPCODE) { // no conversion needed + forwardOperandNum = 0; // forward first operand to user + } else { + // If the source operand is a non-FP type it must be + // first copied from int to float register via memory! + Instruction *dest = subtreeRoot->getInstruction(); + Value* srcForCast; + int n = 0; + if (! opType->isFloatingPoint()) { + // Create a temporary to represent the FP register + // into which the integer will be copied via memory. + // The type of this temporary will determine the FP + // register used: single-prec for a 32-bit int or smaller, + // double-prec for a 64-bit int. + // + uint64_t srcSize = + target.getTargetData().getTypeSize(leftVal->getType()); + Type* tmpTypeToUse = + (srcSize <= 4)? Type::FloatTy : Type::DoubleTy; + srcForCast = new TmpInstruction(tmpTypeToUse, dest); + MachineCodeForInstruction &destMCFI = + MachineCodeForInstruction::get(dest); + destMCFI.addTemp(srcForCast); - target.getInstrInfo().CreateCodeToCopyIntToFloat(target, + target.getInstrInfo().CreateCodeToCopyIntToFloat(target, dest->getParent()->getParent(), leftVal, cast(srcForCast), mvec, destMCFI); - } - else - srcForCast = leftVal; - - M = BuildMI(opCode, 2).addReg(srcForCast).addRegDef(dest); - mvec.push_back(M); - } + } else + srcForCast = leftVal; + + M = BuildMI(opCode, 2).addReg(srcForCast).addRegDef(dest); + mvec.push_back(M); } + } break; case 19: // reg: ToArrayTy(reg): @@ -1854,11 +1795,10 @@ case 233: // reg: Add(reg, Constant) maskUnsignedResult = true; M = CreateAddConstInstruction(subtreeRoot); - if (M != NULL) - { - mvec.push_back(M); - break; - } + if (M != NULL) { + mvec.push_back(M); + break; + } // ELSE FALL THROUGH case 33: // reg: Add(reg, reg) @@ -1869,11 +1809,10 @@ case 234: // reg: Sub(reg, Constant) maskUnsignedResult = true; M = CreateSubConstInstruction(subtreeRoot); - if (M != NULL) - { - mvec.push_back(M); - break; - } + if (M != NULL) { + mvec.push_back(M); + break; + } // ELSE FALL THROUGH case 34: // reg: Sub(reg, reg) @@ -2089,68 +2028,64 @@ isFPCompare ? Type::FloatTy : Type::IntTy); MachineCodeForInstruction::get(setCCInstr).addTemp(tmpForCC); - if (! isFPCompare) - { - // Integer condition: dest. should be %g0 or an integer register. - // If result must be saved but condition is not SetEQ then we need - // a separate instruction to compute the bool result, so discard - // result of SUBcc instruction anyway. - // - if (keepSubVal) { - M = BuildMI(V9::SUBccr, 4) - .addReg(subtreeRoot->leftChild()->getValue()) - .addReg(subtreeRoot->rightChild()->getValue()) - .addRegDef(subtreeRoot->getValue()) - .addCCReg(tmpForCC, MOTy::Def); - } else { - M = BuildMI(V9::SUBccr, 4) - .addReg(subtreeRoot->leftChild()->getValue()) - .addReg(subtreeRoot->rightChild()->getValue()) - .addMReg(target.getRegInfo().getZeroRegNum(), MOTy::Def) - .addCCReg(tmpForCC, MOTy::Def); - } - mvec.push_back(M); + if (! isFPCompare) { + // Integer condition: dest. should be %g0 or an integer register. + // If result must be saved but condition is not SetEQ then we need + // a separate instruction to compute the bool result, so discard + // result of SUBcc instruction anyway. + // + if (keepSubVal) { + M = BuildMI(V9::SUBccr, 4) + .addReg(subtreeRoot->leftChild()->getValue()) + .addReg(subtreeRoot->rightChild()->getValue()) + .addRegDef(subtreeRoot->getValue()) + .addCCReg(tmpForCC, MOTy::Def); + } else { + M = BuildMI(V9::SUBccr, 4) + .addReg(subtreeRoot->leftChild()->getValue()) + .addReg(subtreeRoot->rightChild()->getValue()) + .addMReg(target.getRegInfo().getZeroRegNum(), MOTy::Def) + .addCCReg(tmpForCC, MOTy::Def); + } + mvec.push_back(M); - if (computeBoolVal) - { // recompute bool using the integer condition codes - movOpCode = - ChooseMovpccAfterSub(subtreeRoot,mustClearReg,valueToMove); - } + if (computeBoolVal) { + // recompute bool using the integer condition codes + movOpCode = + ChooseMovpccAfterSub(subtreeRoot,mustClearReg,valueToMove); } - else - { - // FP condition: dest of FCMP should be some FCCn register - M = BuildMI(ChooseFcmpInstruction(subtreeRoot), 3) - .addCCReg(tmpForCC, MOTy::Def) - .addReg(subtreeRoot->leftChild()->getValue()) - .addRegDef(subtreeRoot->rightChild()->getValue()); - mvec.push_back(M); + } else { + // FP condition: dest of FCMP should be some FCCn register + M = BuildMI(ChooseFcmpInstruction(subtreeRoot), 3) + .addCCReg(tmpForCC, MOTy::Def) + .addReg(subtreeRoot->leftChild()->getValue()) + .addRegDef(subtreeRoot->rightChild()->getValue()); + mvec.push_back(M); - if (computeBoolVal) - {// recompute bool using the FP condition codes - mustClearReg = true; - valueToMove = 1; - movOpCode = ChooseMovFpccInstruction(subtreeRoot); - } + if (computeBoolVal) { + // recompute bool using the FP condition codes + mustClearReg = true; + valueToMove = 1; + movOpCode = ChooseMovFpccInstruction(subtreeRoot); } + } - if (computeBoolVal) - { - if (mustClearReg) - {// Unconditionally set register to 0 - M = BuildMI(V9::SETHI, 2).addZImm(0).addRegDef(setCCInstr); - mvec.push_back(M); - } - - // Now conditionally move `valueToMove' (0 or 1) into the register - // Mark the register as a use (as well as a def) because the old - // value should be retained if the condition is false. - M = BuildMI(movOpCode, 3).addCCReg(tmpForCC).addZImm(valueToMove) - .addReg(setCCInstr, MOTy::UseAndDef); + if (computeBoolVal) { + if (mustClearReg) { + // Unconditionally set register to 0 + M = BuildMI(V9::SETHI, 2).addZImm(0).addRegDef(setCCInstr); mvec.push_back(M); } + + // Now conditionally move `valueToMove' (0 or 1) into the register + // Mark the register as a use (as well as a def) because the old + // value should be retained if the condition is false. + M = BuildMI(movOpCode, 3).addCCReg(tmpForCC).addZImm(valueToMove) + .addReg(setCCInstr, MOTy::UseAndDef); + mvec.push_back(M); + } break; - } + } case 51: // reg: Load(reg) case 52: // reg: Load(ptrreg) @@ -2192,12 +2127,13 @@ if (!isArray || isa(numElementsVal = instr->getArraySize())) - { // total size is constant: generate code for fixed-size alloca - unsigned numElements = isArray? - cast(numElementsVal)->getValue() : 1; - CreateCodeForFixedSizeAlloca(target, instr, tsize, - numElements, mvec); - } + { + // total size is constant: generate code for fixed-size alloca + unsigned numElements = isArray? + cast(numElementsVal)->getValue() : 1; + CreateCodeForFixedSizeAlloca(target, instr, tsize, + numElements, mvec); + } else // total size is not constant. CreateCodeForVariableSizeAlloca(target, instr, tsize, numElementsVal, mvec); @@ -2230,98 +2166,93 @@ // If not, generate the normal call sequence for the function. // This can also handle any intrinsics that are just function calls. // - if (! specialIntrinsic) - { - // Create hidden virtual register for return address with type void* - TmpInstruction* retAddrReg = - new TmpInstruction(PointerType::get(Type::VoidTy), callInstr); - MachineCodeForInstruction::get(callInstr).addTemp(retAddrReg); - - // Generate the machine instruction and its operands. - // Use CALL for direct function calls; this optimistically assumes - // the PC-relative address fits in the CALL address field (22 bits). - // Use JMPL for indirect calls. - // - if (calledFunc) // direct function call - M = BuildMI(V9::CALL, 1).addPCDisp(callee); - else // indirect function call - M = BuildMI(V9::JMPLCALLi, 3).addReg(callee).addSImm((int64_t)0) - .addRegDef(retAddrReg); - mvec.push_back(M); + if (! specialIntrinsic) { + // Create hidden virtual register for return address with type void* + TmpInstruction* retAddrReg = + new TmpInstruction(PointerType::get(Type::VoidTy), callInstr); + MachineCodeForInstruction::get(callInstr).addTemp(retAddrReg); + + // Generate the machine instruction and its operands. + // Use CALL for direct function calls; this optimistically assumes + // the PC-relative address fits in the CALL address field (22 bits). + // Use JMPL for indirect calls. + // + if (calledFunc) // direct function call + M = BuildMI(V9::CALL, 1).addPCDisp(callee); + else // indirect function call + M = BuildMI(V9::JMPLCALLi, 3).addReg(callee).addSImm((int64_t)0) + .addRegDef(retAddrReg); + mvec.push_back(M); - const FunctionType* funcType = - cast(cast(callee->getType()) + const FunctionType* funcType = + cast(cast(callee->getType()) ->getElementType()); - bool isVarArgs = funcType->isVarArg(); - bool noPrototype = isVarArgs && funcType->getNumParams() == 0; + bool isVarArgs = funcType->isVarArg(); + bool noPrototype = isVarArgs && funcType->getNumParams() == 0; - // Use a descriptor to pass information about call arguments - // to the register allocator. This descriptor will be "owned" - // and freed automatically when the MachineCodeForInstruction - // object for the callInstr goes away. - CallArgsDescriptor* argDesc = new CallArgsDescriptor(callInstr, + // Use a descriptor to pass information about call arguments + // to the register allocator. This descriptor will be "owned" + // and freed automatically when the MachineCodeForInstruction + // object for the callInstr goes away. + CallArgsDescriptor* argDesc = new CallArgsDescriptor(callInstr, retAddrReg, isVarArgs,noPrototype); - assert(callInstr->getOperand(0) == callee - && "This is assumed in the loop below!"); + assert(callInstr->getOperand(0) == callee + && "This is assumed in the loop below!"); - for (unsigned i=1, N=callInstr->getNumOperands(); i < N; ++i) - { - Value* argVal = callInstr->getOperand(i); - Instruction* intArgReg = NULL; + for (unsigned i=1, N=callInstr->getNumOperands(); i < N; ++i) { + Value* argVal = callInstr->getOperand(i); + Instruction* intArgReg = NULL; - // Check for FP arguments to varargs functions. - // Any such argument in the first $K$ args must be passed in an - // integer register, where K = #integer argument registers. - if (isVarArgs && argVal->getType()->isFloatingPoint()) - { - // If it is a function with no prototype, pass value - // as an FP value as well as a varargs value - if (noPrototype) - argDesc->getArgInfo(i-1).setUseFPArgReg(); + // Check for FP arguments to varargs functions. + // Any such argument in the first $K$ args must be passed in an + // integer register, where K = #integer argument registers. + if (isVarArgs && argVal->getType()->isFloatingPoint()) { + // If it is a function with no prototype, pass value + // as an FP value as well as a varargs value + if (noPrototype) + argDesc->getArgInfo(i-1).setUseFPArgReg(); - // If this arg. is in the first $K$ regs, add a copy - // float-to-int instruction to pass the value as an integer. - if (i <= target.getRegInfo().getNumOfIntArgRegs()) - { - MachineCodeForInstruction &destMCFI = - MachineCodeForInstruction::get(callInstr); - intArgReg = new TmpInstruction(Type::IntTy, argVal); - destMCFI.addTemp(intArgReg); + // If this arg. is in the first $K$ regs, add a copy + // float-to-int instruction to pass the value as an integer. + if (i <= target.getRegInfo().getNumOfIntArgRegs()) { + MachineCodeForInstruction &destMCFI = + MachineCodeForInstruction::get(callInstr); + intArgReg = new TmpInstruction(Type::IntTy, argVal); + destMCFI.addTemp(intArgReg); - std::vector copyMvec; - target.getInstrInfo().CreateCodeToCopyFloatToInt(target, + std::vector copyMvec; + target.getInstrInfo().CreateCodeToCopyFloatToInt(target, callInstr->getParent()->getParent(), argVal, (TmpInstruction*) intArgReg, copyMvec, destMCFI); - mvec.insert(mvec.begin(),copyMvec.begin(),copyMvec.end()); + mvec.insert(mvec.begin(),copyMvec.begin(),copyMvec.end()); - argDesc->getArgInfo(i-1).setUseIntArgReg(); - argDesc->getArgInfo(i-1).setArgCopy(intArgReg); - } - else - // Cannot fit in first $K$ regs so pass arg on stack - argDesc->getArgInfo(i-1).setUseStackSlot(); - } + argDesc->getArgInfo(i-1).setUseIntArgReg(); + argDesc->getArgInfo(i-1).setArgCopy(intArgReg); + } else + // Cannot fit in first $K$ regs so pass arg on stack + argDesc->getArgInfo(i-1).setUseStackSlot(); + } - if (intArgReg) - mvec.back()->addImplicitRef(intArgReg); + if (intArgReg) + mvec.back()->addImplicitRef(intArgReg); - mvec.back()->addImplicitRef(argVal); - } + mvec.back()->addImplicitRef(argVal); + } - // Add the return value as an implicit ref. The call operands - // were added above. - if (callInstr->getType() != Type::VoidTy) - mvec.back()->addImplicitRef(callInstr, /*isDef*/ true); - - // For the CALL instruction, the ret. addr. reg. is also implicit - if (isa(callee)) - mvec.back()->addImplicitRef(retAddrReg, /*isDef*/ true); + // Add the return value as an implicit ref. The call operands + // were added above. + if (callInstr->getType() != Type::VoidTy) + mvec.back()->addImplicitRef(callInstr, /*isDef*/ true); + + // For the CALL instruction, the ret. addr. reg. is also implicit + if (isa(callee)) + mvec.back()->addImplicitRef(retAddrReg, /*isDef*/ true); - // delay slot - mvec.push_back(BuildMI(V9::NOP, 0)); - } + // delay slot + mvec.push_back(BuildMI(V9::NOP, 0)); + } break; } @@ -2344,7 +2275,8 @@ } case 63: // reg: Shr(reg, reg) - { const Type* opType = subtreeRoot->leftChild()->getValue()->getType(); + { + const Type* opType = subtreeRoot->leftChild()->getValue()->getType(); assert((opType->isInteger() || isa(opType)) && "Shr unsupported for other types"); Add3OperandInstr(opType->isSigned() @@ -2380,54 +2312,52 @@ } } - if (forwardOperandNum >= 0) - { // We did not generate a machine instruction but need to use operand. - // If user is in the same tree, replace Value in its machine operand. - // If not, insert a copy instruction which should get coalesced away - // by register allocation. - if (subtreeRoot->parent() != NULL) - ForwardOperand(subtreeRoot, subtreeRoot->parent(), forwardOperandNum); - else - { - std::vector minstrVec; - Instruction* instr = subtreeRoot->getInstruction(); - target.getInstrInfo(). - CreateCopyInstructionsByType(target, - instr->getParent()->getParent(), - instr->getOperand(forwardOperandNum), - instr, minstrVec, - MachineCodeForInstruction::get(instr)); - assert(minstrVec.size() > 0); - mvec.insert(mvec.end(), minstrVec.begin(), minstrVec.end()); - } + if (forwardOperandNum >= 0) { + // We did not generate a machine instruction but need to use operand. + // If user is in the same tree, replace Value in its machine operand. + // If not, insert a copy instruction which should get coalesced away + // by register allocation. + if (subtreeRoot->parent() != NULL) + ForwardOperand(subtreeRoot, subtreeRoot->parent(), forwardOperandNum); + else { + std::vector minstrVec; + Instruction* instr = subtreeRoot->getInstruction(); + target.getInstrInfo(). + CreateCopyInstructionsByType(target, + instr->getParent()->getParent(), + instr->getOperand(forwardOperandNum), + instr, minstrVec, + MachineCodeForInstruction::get(instr)); + assert(minstrVec.size() > 0); + mvec.insert(mvec.end(), minstrVec.begin(), minstrVec.end()); } + } - if (maskUnsignedResult) - { // If result is unsigned and smaller than int reg size, - // we need to clear high bits of result value. - assert(forwardOperandNum < 0 && "Need mask but no instruction generated"); - Instruction* dest = subtreeRoot->getInstruction(); - if (dest->getType()->isUnsigned()) - { - unsigned destSize=target.getTargetData().getTypeSize(dest->getType()); - if (destSize <= 4) - { // Mask high bits. Use a TmpInstruction to represent the - // intermediate result before masking. Since those instructions - // have already been generated, go back and substitute tmpI - // for dest in the result position of each one of them. - TmpInstruction *tmpI = new TmpInstruction(dest->getType(), dest, - NULL, "maskHi"); - MachineCodeForInstruction::get(dest).addTemp(tmpI); - - for (unsigned i=0, N=mvec.size(); i < N; ++i) - mvec[i]->substituteValue(dest, tmpI); - - M = BuildMI(V9::SRLi6, 3).addReg(tmpI).addZImm(8*(4-destSize)) - .addReg(dest, MOTy::Def); - mvec.push_back(M); - } - else if (destSize < 8) - assert(0 && "Unsupported type size: 32 < size < 64 bits"); - } + if (maskUnsignedResult) { + // If result is unsigned and smaller than int reg size, + // we need to clear high bits of result value. + assert(forwardOperandNum < 0 && "Need mask but no instruction generated"); + Instruction* dest = subtreeRoot->getInstruction(); + if (dest->getType()->isUnsigned()) { + unsigned destSize=target.getTargetData().getTypeSize(dest->getType()); + if (destSize <= 4) { + // Mask high bits. Use a TmpInstruction to represent the + // intermediate result before masking. Since those instructions + // have already been generated, go back and substitute tmpI + // for dest in the result position of each one of them. + TmpInstruction *tmpI = new TmpInstruction(dest->getType(), dest, + NULL, "maskHi"); + MachineCodeForInstruction::get(dest).addTemp(tmpI); + + for (unsigned i=0, N=mvec.size(); i < N; ++i) + mvec[i]->substituteValue(dest, tmpI); + + M = BuildMI(V9::SRLi6, 3).addReg(tmpI).addZImm(8*(4-destSize)) + .addReg(dest, MOTy::Def); + mvec.push_back(M); + } else if (destSize < 8) { + assert(0 && "Unsupported type size: 32 < size < 64 bits"); + } } + } } Index: llvm/lib/Target/Sparc/SparcInstrSelectionSupport.h diff -u llvm/lib/Target/Sparc/SparcInstrSelectionSupport.h:1.7 llvm/lib/Target/Sparc/SparcInstrSelectionSupport.h:1.8 --- llvm/lib/Target/Sparc/SparcInstrSelectionSupport.h:1.7 Tue May 27 17:39:01 2003 +++ llvm/lib/Target/Sparc/SparcInstrSelectionSupport.h Fri May 30 15:11:56 2003 @@ -8,6 +8,7 @@ #define SPARC_INSTR_SELECTION_SUPPORT_h #include "llvm/DerivedTypes.h" +#include "SparcInternals.h" inline MachineOpCode ChooseLoadInstruction(const Type *DestTy) @@ -75,6 +76,84 @@ } return opCode; +} + + +static unsigned +convertOpcodeFromRegToImm(unsigned Opcode) { + switch (Opcode) { + /* arithmetic */ + case V9::ADDr: return V9::ADDi; + case V9::ADDccr: return V9::ADDcci; + case V9::ADDCr: return V9::ADDCi; + case V9::ADDCccr: return V9::ADDCcci; + case V9::SUBr: return V9::SUBi; + case V9::SUBccr: return V9::SUBcci; + case V9::SUBCr: return V9::SUBCi; + case V9::SUBCccr: return V9::SUBCcci; + case V9::MULXr: return V9::MULXi; + case V9::SDIVXr: return V9::SDIVXi; + case V9::UDIVXr: return V9::UDIVXi; + + /* logical */ + case V9::ANDr: return V9::ANDi; + case V9::ANDccr: return V9::ANDcci; + case V9::ANDNr: return V9::ANDNi; + case V9::ANDNccr: return V9::ANDNcci; + case V9::ORr: return V9::ORi; + case V9::ORccr: return V9::ORcci; + case V9::ORNr: return V9::ORNi; + case V9::ORNccr: return V9::ORNcci; + case V9::XORr: return V9::XORi; + case V9::XORccr: return V9::XORcci; + case V9::XNORr: return V9::XNORi; + case V9::XNORccr: return V9::XNORcci; + + /* shift */ + case V9::SLLr6: return V9::SLLi6; + case V9::SRLr6: return V9::SRLi6; + case V9::SRAr6: return V9::SRAi6; + case V9::SLLXr6: return V9::SLLXi6; + case V9::SRLXr6: return V9::SRLXi6; + case V9::SRAXr6: return V9::SRAXi6; + + /* load */ + case V9::LDSBr: return V9::LDSBi; + case V9::LDSHr: return V9::LDSHi; + case V9::LDSWr: return V9::LDSWi; + case V9::LDUBr: return V9::LDUBi; + case V9::LDUHr: return V9::LDUHi; + case V9::LDUWr: return V9::LDUWi; + case V9::LDXr: return V9::LDXi; + case V9::LDFr: return V9::LDFi; + case V9::LDDFr: return V9::LDDFi; + case V9::LDQFr: return V9::LDQFi; + case V9::LDFSRr: return V9::LDFSRi; + case V9::LDXFSRr: return V9::LDXFSRi; + + /* store */ + case V9::STBr: return V9::STBi; + case V9::STHr: return V9::STHi; + case V9::STWr: return V9::STWi; + case V9::STXr: return V9::STXi; + case V9::STFr: return V9::STFi; + case V9::STDFr: return V9::STDFi; + case V9::STFSRr: return V9::STFSRi; + case V9::STXFSRr: return V9::STXFSRi; + + /* jump & return */ + case V9::JMPLCALLr: return V9::JMPLCALLi; + case V9::JMPLRETr: return V9::JMPLRETi; + case V9::RETURNr: return V9::RETURNi; + + /* save and restore */ + case V9::SAVEr: return V9::SAVEi; + case V9::RESTOREr: return V9::RESTOREi; + + default: + // It's already in correct format + return Opcode; + } } #endif From brukman at cs.uiuc.edu Fri May 30 15:13:09 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 30 15:13:09 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcInternals.h Message-ID: <200305302012.PAA32209@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcInternals.h updated: 1.87 -> 1.88 --- Log message: The register types need to be visible outside of the class to be useful. For one, converting register numbers based on class in the code emitter. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/SparcInternals.h diff -u llvm/lib/Target/Sparc/SparcInternals.h:1.87 llvm/lib/Target/Sparc/SparcInternals.h:1.88 --- llvm/lib/Target/Sparc/SparcInternals.h:1.87 Tue May 27 17:44:44 2003 +++ llvm/lib/Target/Sparc/SparcInternals.h Fri May 30 15:12:42 2003 @@ -259,20 +259,6 @@ SpecialRegClassID // Special (unallocated) registers }; - - // Type of registers available in Sparc. There can be several reg types - // in the same class. For instace, the float reg class has Single/Double - // types - // - enum RegTypes { - IntRegType, - FPSingleRegType, - FPDoubleRegType, - IntCCRegType, - FloatCCRegType, - SpecialRegType - }; - // **** WARNING: If the above enum order is changed, also modify // getRegisterClassOfValue method below since it assumes this particular // order for efficiency. @@ -348,6 +334,19 @@ unsigned& regClassId) const; public: + // Type of registers available in Sparc. There can be several reg types + // in the same class. For instace, the float reg class has Single/Double + // types + // + enum RegTypes { + IntRegType, + FPSingleRegType, + FPDoubleRegType, + IntCCRegType, + FloatCCRegType, + SpecialRegType + }; + UltraSparcRegInfo(const UltraSparc &tgt); // To find the register class used for a specified Type From brukman at cs.uiuc.edu Fri May 30 15:17:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 30 15:17:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcV9.td Message-ID: <200305302016.PAA32243@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcV9.td updated: 1.5 -> 1.6 --- Log message: Fixed the namespace to match SparcInternals.h; added notes on some missing sections of instructions. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/SparcV9.td diff -u llvm/lib/Target/Sparc/SparcV9.td:1.5 llvm/lib/Target/Sparc/SparcV9.td:1.6 --- llvm/lib/Target/Sparc/SparcV9.td:1.5 Wed May 28 23:53:56 2003 +++ llvm/lib/Target/Sparc/SparcV9.td Fri May 30 15:15:59 2003 @@ -13,7 +13,7 @@ class InstV9 : Instruction { // Sparc instruction baseline field bits<32> Inst; - set Namespace = "SparcV9"; + set Namespace = "V9"; bits<2> op; set Inst{31-30} = op; // Top two bits are the 'op' field @@ -202,7 +202,16 @@ def FSQRTD : F3_14<2, 0b110100, 0b000101010, "fsqrts">; // fsqrts r, r def FSQRTQ : F3_14<2, 0b110100, 0b000101011, "fsqrts">; // fsqrts r, r -// Section A.24: Jump and Link +// FIXME: A.20: Flush Instruction Memory - p167 +// FIXME: A.21: Flush Register Windows - p169 + +// A.22: Illegal instruction Trap - p170 +// Not used + +// A.23: Implementation-Dependent Instructions - p171 +// Not used + +// Section A.24: Jump and Link - p172 // Mimicking the Sparc's instr def... def JMPLCALLr : F3_1<2, 0b111000, "jmpl">; // jmpl [r+r], r def JMPLCALLi : F3_2<2, 0b111000, "jmpl">; // jmpl [r+i], r @@ -319,11 +328,14 @@ def FMOVFO : F4_7<2, 0b110101, 0b1111, "fmovfo">; // fmovfo r, r #endif -// Section A.34: Move F-P Register on Integer Register (FMOVr) +// FIXME: Section A.34: Move F-P Register on Integer Register (FMOVr) + -// Section A.35: Move Integer Register on Condition (MOVcc) +// FIXME: Section A.35: Move Integer Register on Condition (MOVcc) + + +// FIXME: Section A.36: Move Integer Register on Register Condition (MOVR) -// Section A.36: Move Integer Register on Register Condition (MOVR) // Section A.37: Multiply and Divide (64-bit) - p199 def MULXr : F3_1<2, 0b001001, "mulx">; // mulx r, r, r @@ -425,6 +437,7 @@ def SRAXi6 : F3_13<2, 0b100111, "srax">; // srax r, shcnt64, r // Section A.50: FIXME + // Section A.51: FIXME // Section A.52: Store Floating-point -p225 From brukman at cs.uiuc.edu Fri May 30 15:18:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 30 15:18:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp SparcV9CodeEmitter.h Message-ID: <200305302017.PAA32270@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcV9CodeEmitter.cpp updated: 1.4 -> 1.5 SparcV9CodeEmitter.h updated: 1.3 -> 1.4 --- Log message: Added: * ability to save BasicBlock references to be resolved later * register remappings from the enum values to the real hardware numbers --- Diffs of the changes: Index: llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp diff -u llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp:1.4 llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp:1.5 --- llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp:1.4 Tue May 27 17:48:28 2003 +++ llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp Fri May 30 15:17:33 2003 @@ -1,17 +1,26 @@ +//===-- SparcV9CodeEmitter.cpp - --------===// +// +// +//===----------------------------------------------------------------------===// + #include "llvm/PassManager.h" #include "llvm/CodeGen/MachineCodeEmitter.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Target/TargetMachine.h" #include "SparcInternals.h" #include "SparcV9CodeEmitter.h" +MachineCodeEmitter * SparcV9CodeEmitter::MCE = 0; +TargetMachine * SparcV9CodeEmitter::TM = 0; + bool UltraSparc::addPassesToEmitMachineCode(PassManager &PM, MachineCodeEmitter &MCE) { //PM.add(new SparcV9CodeEmitter(MCE)); //MachineCodeEmitter *M = MachineCodeEmitter::createDebugMachineCodeEmitter(); MachineCodeEmitter *M = MachineCodeEmitter::createFilePrinterMachineCodeEmitter(MCE); - PM.add(new SparcV9CodeEmitter(*M)); + PM.add(new SparcV9CodeEmitter(this, *M)); return false; } @@ -20,20 +29,96 @@ unsigned byteVal; for (int i = Size-1; i >= 0; --i) { byteVal = Val >> 8*i; - MCE.emitByte(byteVal & 255); + MCE->emitByte(byteVal & 255); + } +#if 0 + MCE->emitByte((Val >> 16) & 255); // byte 2 + MCE->emitByte((Val >> 24) & 255); // byte 3 + MCE->emitByte((Val >> 8) & 255); // byte 1 + MCE->emitByte(Val & 255); // byte 0 +#endif +} + +unsigned getRealRegNum(unsigned fakeReg, unsigned regClass) { + switch (regClass) { + case UltraSparcRegInfo::IntRegType: { + // Sparc manual, p31 + static const unsigned IntRegMap[] = { + // "o0", "o1", "o2", "o3", "o4", "o5", "o7", + 8, 9, 10, 11, 12, 13, 15, + // "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", + 16, 17, 18, 19, 20, 21, 22, 23, + // "i0", "i1", "i2", "i3", "i4", "i5", + 24, 25, 26, 27, 28, 29, + // "i6", "i7", + 30, 31, + // "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", + 0, 1, 2, 3, 4, 5, 6, 7, + // "o6" + 14 + }; + + return IntRegMap[fakeReg]; + break; + } + case UltraSparcRegInfo::FPSingleRegType: { + return fakeReg; + } + case UltraSparcRegInfo::FPDoubleRegType: { + return fakeReg; + } + case UltraSparcRegInfo::FloatCCRegType: { + return fakeReg; + + } + case UltraSparcRegInfo::IntCCRegType: { + return fakeReg; + } + default: + assert(0 && "Invalid unified register number in getRegType"); + return fakeReg; } } -int64_t SparcV9CodeEmitter::getMachineOpValue(MachineOperand &MO) { +int64_t SparcV9CodeEmitter::getMachineOpValue(MachineInstr &MI, + MachineOperand &MO) { if (MO.isPhysicalRegister()) { - return MO.getReg(); + // This is necessary because the Sparc doesn't actually lay out registers + // in the real fashion -- it skips those that it chooses not to allocate, + // i.e. those that are the SP, etc. + unsigned fakeReg = MO.getReg(), realReg, regClass, regType; + regType = TM->getRegInfo().getRegType(fakeReg); + // At least map fakeReg into its class + fakeReg = TM->getRegInfo().getClassRegNum(fakeReg, regClass); + // Find the real register number for use in an instruction + realReg = getRealRegNum(fakeReg, regClass); + std::cerr << "Reg[" << fakeReg << "] = " << realReg << "\n"; + return realReg; } else if (MO.isImmediate()) { return MO.getImmedValue(); } else if (MO.isPCRelativeDisp()) { - //MCE.saveBBreference(currBB, MO); + std::cerr << "Saving reference to BB (PCRelDisp)\n"; + MCE->saveBBreference((BasicBlock*)MO.getVRegValue(), MI); + return 0; + } else if (MO.isMachineBasicBlock()) { + std::cerr << "Saving reference to BB (MBB)\n"; + MCE->saveBBreference(MO.getMachineBasicBlock()->getBasicBlock(), MI); + return 0; + } else if (MO.isFrameIndex()) { + std::cerr << "ERROR: Frame index unhandled.\n"; + return 0; + } else if (MO.isConstantPoolIndex()) { + std::cerr << "ERROR: Constant Pool index unhandled.\n"; + return 0; + } else if (MO.isGlobalAddress()) { + std::cerr << "ERROR: Global addr unhandled.\n"; + return 0; + } else if (MO.isExternalSymbol()) { + std::cerr << "ERROR: External symbol unhandled.\n"; return 0; } else { - assert(0 && "Unknown type of MachineOperand"); + std::cerr << "ERROR: Unknown type of MachineOperand: " << MO << "\n"; + //abort(); return 0; } } @@ -45,17 +130,17 @@ bool SparcV9CodeEmitter::runOnMachineFunction(MachineFunction &MF) { - MCE.startFunction(MF); - MCE.emitConstantPool(MF.getConstantPool()); + MCE->startFunction(MF); + MCE->emitConstantPool(MF.getConstantPool()); for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) emitBasicBlock(*I); - MCE.finishFunction(MF); + MCE->finishFunction(MF); return false; } void SparcV9CodeEmitter::emitBasicBlock(MachineBasicBlock &MBB) { currBB = MBB.getBasicBlock(); - MCE.startBasicBlock(MBB); + MCE->startBasicBlock(MBB); for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I) emitInstruction(**I); } Index: llvm/lib/Target/Sparc/SparcV9CodeEmitter.h diff -u llvm/lib/Target/Sparc/SparcV9CodeEmitter.h:1.3 llvm/lib/Target/Sparc/SparcV9CodeEmitter.h:1.4 --- llvm/lib/Target/Sparc/SparcV9CodeEmitter.h:1.3 Tue May 27 17:48:28 2003 +++ llvm/lib/Target/Sparc/SparcV9CodeEmitter.h Fri May 30 15:17:33 2003 @@ -1,4 +1,7 @@ - +//===-- SparcV9CodeEmitter.h ------------------------------------*- C++ -*-===// +// +// +//===----------------------------------------------------------------------===// #ifndef SPARCV9CODEEMITTER_H #define SPARCV9CODEEMITTER_H @@ -7,14 +10,19 @@ #include "llvm/CodeGen/MachineCodeEmitter.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Target/TargetMachine.h" class SparcV9CodeEmitter : public MachineFunctionPass { - MachineCodeEmitter &MCE; + static MachineCodeEmitter *MCE; + static TargetMachine *TM; BasicBlock *currBB; public: - SparcV9CodeEmitter(MachineCodeEmitter &M) : MCE(M) {} - + SparcV9CodeEmitter(TargetMachine *tm, MachineCodeEmitter &M) { + MCE = &M; + TM = tm; + } + bool runOnMachineFunction(MachineFunction &F); /// Function generated by the CodeEmitterGenerator using TableGen @@ -22,7 +30,7 @@ static unsigned getBinaryCodeForInstr(MachineInstr &MI); private: - static int64_t getMachineOpValue(MachineOperand &MO); + static int64_t getMachineOpValue(MachineInstr &MI, MachineOperand &MO); static unsigned getValueBit(int64_t Val, unsigned bit); void emitConstant(unsigned Val, unsigned Size); From brukman at cs.uiuc.edu Fri May 30 15:33:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 30 15:33:01 2003 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/MachineCodeEmitter.cpp Message-ID: <200305302032.PAA32500@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: MachineCodeEmitter.cpp updated: 1.7 -> 1.8 --- Log message: Added saveBBreferences() for BasicBlock resolution. --- Diffs of the changes: Index: llvm/lib/CodeGen/MachineCodeEmitter.cpp diff -u llvm/lib/CodeGen/MachineCodeEmitter.cpp:1.7 llvm/lib/CodeGen/MachineCodeEmitter.cpp:1.8 --- llvm/lib/CodeGen/MachineCodeEmitter.cpp:1.7 Wed May 28 13:27:19 2003 +++ llvm/lib/CodeGen/MachineCodeEmitter.cpp Fri May 30 15:32:45 2003 @@ -158,9 +158,7 @@ } } void emitPCRelativeDisp(Value *V) { - // put block in mapping BB -> { instr, address }. when BB is beginning to - // output, find instr, set disp, overwrite instr at addr using the - // unsigned value gotten from emitter + if (MCE) MCE->emitPCRelativeDisp(V); } void emitGlobalAddress(GlobalValue *V, bool isPCRelative) { @@ -173,9 +171,15 @@ void emitFunctionConstantValueAddress(unsigned ConstantNum, int Offset) { if (MCE) MCE->emitFunctionConstantValueAddress(ConstantNum, Offset); } + + virtual void saveBBreference(BasicBlock* BB, MachineInstr &MI) { + if (MCE) MCE->saveBBreference(BB, MI); + } + }; } -MachineCodeEmitter *MachineCodeEmitter::createFilePrinterMachineCodeEmitter(MachineCodeEmitter &MCE) { +MachineCodeEmitter *MachineCodeEmitter::createFilePrinterMachineCodeEmitter +(MachineCodeEmitter &MCE) { return new FilePrinterMachineCodeEmitter(MCE, std::cerr); } From brukman at cs.uiuc.edu Fri May 30 15:33:08 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 30 15:33:08 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/CodeGen/MachineCodeEmitter.h Message-ID: <200305302032.PAA32493@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/CodeGen: MachineCodeEmitter.h updated: 1.10 -> 1.11 --- Log message: Added saveBBreferences() for BasicBlock resolution. --- Diffs of the changes: Index: llvm/include/llvm/CodeGen/MachineCodeEmitter.h diff -u llvm/include/llvm/CodeGen/MachineCodeEmitter.h:1.10 llvm/include/llvm/CodeGen/MachineCodeEmitter.h:1.11 --- llvm/include/llvm/CodeGen/MachineCodeEmitter.h:1.10 Tue May 27 16:46:56 2003 +++ llvm/include/llvm/CodeGen/MachineCodeEmitter.h Fri May 30 15:32:44 2003 @@ -10,7 +10,10 @@ #ifndef LLVM_CODEGEN_MACHINE_CODE_EMITTER_H #define LLVM_CODEGEN_MACHINE_CODE_EMITTER_H +#include #include +class BasicBlock; +class MachineInstr; class MachineFunction; class MachineBasicBlock; class MachineConstantPool; @@ -91,6 +94,11 @@ /// static MachineCodeEmitter* createFilePrinterMachineCodeEmitter(MachineCodeEmitter&); + + /// + virtual void saveBBreference(BasicBlock* BB, MachineInstr &MI) { + std::cerr << "Save BB reference unimplemented\n"; + } }; #endif From brukman at cs.uiuc.edu Fri May 30 15:33:16 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 30 15:33:16 2003 Subject: [llvm-commits] CVS: llvm/utils/TableGen/CodeEmitterGen.cpp Message-ID: <200305302032.PAA32464@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: CodeEmitterGen.cpp updated: 1.4 -> 1.5 --- Log message: getValueOp() now takes a MachineInstr as well as a MachineOperand. --- Diffs of the changes: Index: llvm/utils/TableGen/CodeEmitterGen.cpp diff -u llvm/utils/TableGen/CodeEmitterGen.cpp:1.4 llvm/utils/TableGen/CodeEmitterGen.cpp:1.5 --- llvm/utils/TableGen/CodeEmitterGen.cpp:1.4 Wed May 28 13:29:10 2003 +++ llvm/utils/TableGen/CodeEmitterGen.cpp Fri May 30 15:32:01 2003 @@ -69,7 +69,7 @@ { o << " // op" << op << ": " << Vals[i].getName() << "\n" << " int64_t op" << op - <<" = getMachineOpValue(MI.getOperand("< Changes in directory llvm/lib/CodeGen/InstrSelection: InstrSelectionSupport.cpp updated: 1.46 -> 1.47 --- Log message: When converting virtual registers to immediate constants, change the opcode. --- Diffs of the changes: Index: llvm/lib/CodeGen/InstrSelection/InstrSelectionSupport.cpp diff -u llvm/lib/CodeGen/InstrSelection/InstrSelectionSupport.cpp:1.46 llvm/lib/CodeGen/InstrSelection/InstrSelectionSupport.cpp:1.47 --- llvm/lib/CodeGen/InstrSelection/InstrSelectionSupport.cpp:1.46 Wed Jan 15 15:36:49 2003 +++ llvm/lib/CodeGen/InstrSelection/InstrSelectionSupport.cpp Fri May 30 15:36:27 2003 @@ -16,6 +16,7 @@ #include "llvm/Constants.h" #include "llvm/BasicBlock.h" #include "llvm/DerivedTypes.h" +#include "../../Target/Sparc/SparcInstrSelectionSupport.h" using std::vector; //*************************** Local Functions ******************************/ @@ -186,6 +187,12 @@ immedValue); if (opType == MachineOperand::MO_VirtualRegister) constantThatMustBeLoaded = true; + else { + // The optype has changed from being a register to an immediate + // This means we need to change the opcode, e.g. ADDr -> ADDi + unsigned newOpcode = convertOpcodeFromRegToImm(opCode); + minstr->setOpcode(newOpcode); + } } } else @@ -212,6 +219,13 @@ opValue = isSigned ? (Value*)ConstantSInt::get(Type::LongTy, immedValue) : (Value*)ConstantUInt::get(Type::ULongTy,(uint64_t)immedValue); + } + else + { + // The optype has changed from being a register to an immediate + // This means we need to change the opcode, e.g. ADDr -> ADDi + unsigned newOpcode = convertOpcodeFromRegToImm(opCode); + minstr->setOpcode(newOpcode); } } From brukman at cs.uiuc.edu Fri May 30 15:40:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 30 15:40:01 2003 Subject: [llvm-commits] CVS: llvm/tools/lli/JIT/SparcEmitter.cpp Message-ID: <200305302039.PAA32573@zion.cs.uiuc.edu> Changes in directory llvm/tools/lli/JIT: SparcEmitter.cpp updated: 1.3 -> 1.4 --- Log message: Since malloc is no longer used, no need to free() memory. Fixed BasicBlock patching by supplying correct type for the displacement. --- Diffs of the changes: Index: llvm/tools/lli/JIT/SparcEmitter.cpp diff -u llvm/tools/lli/JIT/SparcEmitter.cpp:1.3 llvm/tools/lli/JIT/SparcEmitter.cpp:1.4 --- llvm/tools/lli/JIT/SparcEmitter.cpp:1.3 Thu May 29 22:37:13 2003 +++ llvm/tools/lli/JIT/SparcEmitter.cpp Fri May 30 15:39:37 2003 @@ -32,16 +32,8 @@ std::pair > > BBRefs; std::map BBLocations; std::vector ConstantPoolAddresses; - std::vector funcMemory; public: SparcEmitter(VM &vm) : TheVM(vm) {} - ~SparcEmitter() { - while (! funcMemory.empty()) { - void* addr = funcMemory.back(); - free(addr); - funcMemory.pop_back(); - } - } virtual void startFunction(MachineFunction &F); virtual void finishFunction(MachineFunction &F); @@ -76,12 +68,12 @@ // FIXME: This should be rewritten to support a real memory manager for // executable memory pages! -void * SparcEmitter::getMemory(unsigned NumPages) { +void* SparcEmitter::getMemory(unsigned NumPages) { void *pa; if (NumPages == 0) return 0; static const long pageSize = sysconf (_SC_PAGESIZE); pa = mmap(0, pageSize*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC, - MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); if (pa == MAP_FAILED) { perror("mmap"); abort(); @@ -91,28 +83,32 @@ void SparcEmitter::startFunction(MachineFunction &F) { - CurBlock = (unsigned char *)getMemory(8); std::cerr << "Starting function " << F.getFunction()->getName() << "\n"; + CurBlock = (unsigned char *)getMemory(8); CurByte = CurBlock; // Start writing at the beginning of the fn. TheVM.addGlobalMapping(F.getFunction(), CurBlock); } void SparcEmitter::finishFunction(MachineFunction &F) { + std::cerr << "Finishing function " << F.getFunction()->getName() << "\n"; ConstantPoolAddresses.clear(); // Re-write branches to BasicBlocks for the entire function for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) { unsigned Location = BBLocations[BBRefs[i].first]; unsigned *Ref = BBRefs[i].second.first; MachineInstr *MI = BBRefs[i].second.second; + std::cerr << "attempting to resolve BB: " << i << "\n"; for (unsigned i=0, e = MI->getNumOperands(); i != e; ++i) { MachineOperand &op = MI->getOperand(i); - if (op.isImmediate()) { - MI->SetMachineOperandConst(i, op.getType(), Location); + if (op.isPCRelativeDisp()) { + MI->SetMachineOperandConst(i, MachineOperand::MO_SignExtendedImmed, + Location); + std::cerr << "Rewrote BB ref: "; + unsigned fixedInstr = SparcV9CodeEmitter::getBinaryCodeForInstr(*MI); + *Ref = fixedInstr; break; } } - unsigned fixedInstr = SparcV9CodeEmitter::getBinaryCodeForInstr(*MI); - *Ref = fixedInstr; } BBRefs.clear(); BBLocations.clear(); From lattner at cs.uiuc.edu Fri May 30 16:04:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri May 30 16:04:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/C++Frontend/pointer_arithmetic.c Message-ID: <200305302103.QAA13010@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/C++Frontend: pointer_arithmetic.c added (r1.1) --- Log message: New testcase --- Diffs of the changes: Index: llvm/test/Regression/C++Frontend/pointer_arithmetic.c diff -c /dev/null llvm/test/Regression/C++Frontend/pointer_arithmetic.c:1.1 *** /dev/null Fri May 30 16:03:10 2003 --- llvm/test/Regression/C++Frontend/pointer_arithmetic.c Fri May 30 16:03:00 2003 *************** *** 0 **** --- 1,21 ---- + typedef struct { + int w; + // float x; + // double y; + // long long z; + } S1Ty; + + typedef struct { + S1Ty A, B; + } S2Ty; + + void takeS1(S1Ty *V) {} + void takeVoid(void *P) {} + + int main() { + S2Ty E; + takeS1(&E.B); + takeVoid(&E); + return 0; + } + From lattner at cs.uiuc.edu Fri May 30 17:07:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri May 30 17:07:03 2003 Subject: [llvm-commits] CVS: llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c Message-ID: <200305302206.RAA18576@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/SingleSource/UnitTests: 2003-05-07-VarArgs.c updated: 1.7 -> 1.8 --- Log message: Remove pointer printing and use of uninitialized structure --- Diffs of the changes: Index: llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c diff -u llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c:1.7 llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c:1.8 --- llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c:1.7 Fri May 30 15:11:06 2003 +++ llvm/test/Programs/SingleSource/UnitTests/2003-05-07-VarArgs.c Fri May 30 17:06:05 2003 @@ -56,7 +56,7 @@ break; case 'L': ls = va_arg(ap, LargeS); - printf("LargeS { %d, %f, 0x%p, %d }\n", ls.i, ls.d, ls.ptr, ls.j); + printf("LargeS { %d, %f, 0x%d, %d }\n", ls.i, ls.d, ls.ptr != 0, ls.j); break; } va_end(ap); @@ -64,7 +64,6 @@ int main() { DWordS dw = { 18, 'a' }; - DWordS dw2; QuadWordS qw = { 19, 20.0 }; LargeS ls = { 21, 22.0, &dw, 23 }; @@ -74,7 +73,7 @@ test("ddil", 1.0, 2.0f, (short)32764, 12345677823423LL); /* test passing structs by value to varargs */ - test("DQL", dw2, qw, ls); + test("DQL", dw, qw, ls); return 0; } From brukman at cs.uiuc.edu Fri May 30 23:23:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 30 23:23:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcV9_F3.td Message-ID: <200305310422.XAA06937@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcV9_F3.td updated: 1.3 -> 1.4 --- Log message: The actual order of parameters in a 2-reg-immediate assembly instructions is "rs1, imm, rd": most importantly, rd goes last. --- Diffs of the changes: Index: llvm/lib/Target/Sparc/SparcV9_F3.td diff -u llvm/lib/Target/Sparc/SparcV9_F3.td:1.3 llvm/lib/Target/Sparc/SparcV9_F3.td:1.4 --- llvm/lib/Target/Sparc/SparcV9_F3.td:1.3 Fri May 30 13:06:10 2003 +++ llvm/lib/Target/Sparc/SparcV9_F3.td Fri May 30 23:22:26 2003 @@ -56,17 +56,47 @@ set Inst{4-0} = rs2; } +// F3_rs1rs2 - Common class of instructions that only have rs1 and rs2 fields +class F3_rs1rs2rd : F3_rs1rs2 { + bits<5> rd; + set Inst{29-25} = rd; + set Inst{4-0} = rs2; +} + // F3_rs1simm13 - Common class of instructions that only have rs1 and simm13 class F3_rs1simm13 : F3_rs1 { bits<13> simm13; set Inst{12-0} = simm13; } +class F3_rs1simm13rd : F3_rs1simm13 { + bits<5> rd; + set Inst{29-25} = rd; +} + // Specific F3 classes... // -class F3_1 opVal, bits<6> op3val, string name> : F3_rdrs1rs2 { +class F3_1 opVal, bits<6> op3val, string name> : F3_rs1rs2rd { + set op = opVal; + set op3 = op3val; + set Name = name; + set Inst{13} = 0; // i field = 0 + //set Inst{12-5} = dontcare; +} + +class F3_2 opVal, bits<6> op3val, string name> : F3_rs1simm13rd { + set op = opVal; + set op3 = op3val; + set Name = name; + set Inst{13} = 1; // i field = 1 +} + +#if 0 +// The ordering is actually incorrect in these: in the assemble syntax, +// rd appears last! +class F3_1a opVal, bits<6> op3val, string name> : F3_rdrs1rs2 { set op = opVal; set op3 = op3val; set Name = name; @@ -74,12 +104,14 @@ //set Inst{12-5} = dontcare; } -class F3_2 opVal, bits<6> op3val, string name> : F3_rdsimm13rs1 { +class F3_2a opVal, bits<6> op3val, string name> : F3_rdsimm13rs1 { set op = opVal; set op3 = op3val; set Name = name; set Inst{13} = 1; // i field = 1 } +#endif + class F3_3 opVal, bits<6> op3val, string name> : F3_rs1rs2 { set op = opVal; From brukman at cs.uiuc.edu Fri May 30 23:24:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 30 23:24:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/Sparc.cpp Message-ID: <200305310423.XAA06954@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: Sparc.cpp updated: 1.64 -> 1.65 --- Log message: Enabling some of these passes causes lli to break --- Diffs of the changes: Index: llvm/lib/Target/Sparc/Sparc.cpp diff -u llvm/lib/Target/Sparc/Sparc.cpp:1.64 llvm/lib/Target/Sparc/Sparc.cpp:1.65 --- llvm/lib/Target/Sparc/Sparc.cpp:1.64 Fri May 30 15:00:13 2003 +++ llvm/lib/Target/Sparc/Sparc.cpp Fri May 30 23:23:04 2003 @@ -210,17 +210,21 @@ // Specialize LLVM code for this target machine and then // run basic dataflow optimizations on LLVM code. +#if 0 if (!DisablePreSelect) { PM.add(createPreSelectionPass(*this)); PM.add(createReassociatePass()); PM.add(createLICMPass()); PM.add(createGCSEPass()); } +#endif PM.add(createInstructionSelectionPass(*this)); +#if 0 if (!DisableSched) PM.add(createInstructionSchedulingWithSSAPass(*this)); +#endif // new pass: convert Value* in MachineOperand to an unsigned register // this brings it in line with what the X86 JIT's RegisterAllocator expects @@ -229,8 +233,10 @@ PM.add(getRegisterAllocator(*this)); PM.add(getPrologEpilogInsertionPass()); +#if 0 if (!DisablePeephole) PM.add(createPeepholeOptsPass(*this)); +#endif return false; // success! } From vadve at cs.uiuc.edu Fri May 30 23:47:01 2003 From: vadve at cs.uiuc.edu (Vikram Adve) Date: Fri May 30 23:47:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/LLC/2003-05-28-ManyArgs.ll 2003-05-30-BadFoldGEP.ll 2003-05-30-BadPreselectPhi.ll Message-ID: <200305310446.XAA10457@psmith.cs.uiuc.edu> Changes in directory llvm/test/Regression/LLC: 2003-05-28-ManyArgs.ll added (r1.1) 2003-05-30-BadFoldGEP.ll added (r1.1) 2003-05-30-BadPreselectPhi.ll added (r1.1) --- Log message: 3 more bugs from the SPEC codes and from richards_benchmark.c --- Diffs of the changes: Index: llvm/test/Regression/LLC/2003-05-28-ManyArgs.ll diff -c /dev/null llvm/test/Regression/LLC/2003-05-28-ManyArgs.ll:1.1 *** /dev/null Fri May 30 23:46:07 2003 --- llvm/test/Regression/LLC/2003-05-28-ManyArgs.ll Fri May 30 23:45:56 2003 *************** *** 0 **** --- 1,156 ---- + ;; Date: May 28, 2003. + ;; From: test/Programs/External/SPEC/CINT2000/175.vpr.llvm.bc + ;; Function: int %main(int %argc.1, sbyte** %argv.1) + ;; + ;; Error: A function call with about 56 arguments causes an assertion failure + ;; in llc because the register allocator cannot find a register + ;; not used explicitly by the call instruction. + ;; + ;; Cause: Regalloc was not keeping track of free registers correctly. + ;; It was counting the registers allocated to all outgoing arguments, + ;; even though most of those are copied to the stack (so those + ;; registers are not actually used by the call instruction). + ;; + ;; Fixed: By rewriting selection and allocation so that selection explicitly + ;; inserts all copy operations required for passing arguments and + ;; for the return value of a call, copying to/from registers + ;; and/or to stack locations as needed. + ;; + + target endian = little + target pointersize = 32 + %struct..s_annealing_sched = type { uint, float, float, float, float } + %struct..s_chan = type { uint, float, float, float, float } + %struct..s_det_routing_arch = type { uint, float, float, float, uint, int, short, short, short, float, float } + %struct..s_placer_opts = type { int, float, int, uint, sbyte*, uint, int } + %struct..s_router_opts = type { float, float, float, float, float, int, int, uint, int } + %struct..s_segment_inf = type { float, int, short, short, float, float, uint, float, float } + %struct..s_switch_inf = type { uint, float, float, float, float } + + implementation + + int %main(int %argc.1, sbyte** %argv.1) { + entry: + %net_file = alloca [300 x sbyte] + %place_file = alloca [300 x sbyte] + %arch_file = alloca [300 x sbyte] + %route_file = alloca [300 x sbyte] + %full_stats = alloca uint + %operation = alloca int + %verify_binary_search = alloca uint + %show_graphics = alloca uint + %annealing_sched = alloca %struct..s_annealing_sched + %placer_opts = alloca %struct..s_placer_opts + %router_opts = alloca %struct..s_router_opts + %det_routing_arch = alloca %struct..s_det_routing_arch + %segment_inf = alloca %struct..s_segment_inf* + %timing_inf = alloca { uint, float, float, float, float, float, float, float, float, float, float } + %tmp.101 = getelementptr %struct..s_placer_opts* %placer_opts, long 0, ubyte 4 + %tmp.105 = getelementptr [300 x sbyte]* %net_file, long 0, long 0 + %tmp.106 = getelementptr [300 x sbyte]* %arch_file, long 0, long 0 + %tmp.107 = getelementptr [300 x sbyte]* %place_file, long 0, long 0 + %tmp.108 = getelementptr [300 x sbyte]* %route_file, long 0, long 0 + %tmp.109 = getelementptr { uint, float, float, float, float, float, float, float, float, float, float }* %timing_inf, long 0, ubyte 0 + %tmp.112 = getelementptr %struct..s_placer_opts* %placer_opts, long 0, ubyte 0 + %tmp.114 = getelementptr %struct..s_placer_opts* %placer_opts, long 0, ubyte 6 + %tmp.118 = getelementptr %struct..s_router_opts* %router_opts, long 0, ubyte 7 + %tmp.135 = load int* %operation + %tmp.137 = load int* %tmp.112 + %tmp.138 = getelementptr %struct..s_placer_opts* %placer_opts, long 0, ubyte 1 + %tmp.139 = load float* %tmp.138 + %tmp.140 = getelementptr %struct..s_placer_opts* %placer_opts, long 0, ubyte 2 + %tmp.141 = load int* %tmp.140 + %tmp.142 = getelementptr %struct..s_placer_opts* %placer_opts, long 0, ubyte 3 + %tmp.143 = load uint* %tmp.142 + %tmp.145 = load sbyte** %tmp.101 + %tmp.146 = getelementptr %struct..s_placer_opts* %placer_opts, long 0, ubyte 5 + %tmp.147 = load uint* %tmp.146 + %tmp.149 = load int* %tmp.114 + %tmp.154 = load uint* %full_stats + %tmp.155 = load uint* %verify_binary_search + %tmp.156 = getelementptr %struct..s_annealing_sched* %annealing_sched, long 0, ubyte 0 + %tmp.157 = load uint* %tmp.156 + %tmp.158 = getelementptr %struct..s_annealing_sched* %annealing_sched, long 0, ubyte 1 + %tmp.159 = load float* %tmp.158 + %tmp.160 = getelementptr %struct..s_annealing_sched* %annealing_sched, long 0, ubyte 2 + %tmp.161 = load float* %tmp.160 + %tmp.162 = getelementptr %struct..s_annealing_sched* %annealing_sched, long 0, ubyte 3 + %tmp.163 = load float* %tmp.162 + %tmp.164 = getelementptr %struct..s_annealing_sched* %annealing_sched, long 0, ubyte 4 + %tmp.165 = load float* %tmp.164 + %tmp.166 = getelementptr %struct..s_router_opts* %router_opts, long 0, ubyte 0 + %tmp.167 = load float* %tmp.166 + %tmp.168 = getelementptr %struct..s_router_opts* %router_opts, long 0, ubyte 1 + %tmp.169 = load float* %tmp.168 + %tmp.170 = getelementptr %struct..s_router_opts* %router_opts, long 0, ubyte 2 + %tmp.171 = load float* %tmp.170 + %tmp.172 = getelementptr %struct..s_router_opts* %router_opts, long 0, ubyte 3 + %tmp.173 = load float* %tmp.172 + %tmp.174 = getelementptr %struct..s_router_opts* %router_opts, long 0, ubyte 4 + %tmp.175 = load float* %tmp.174 + %tmp.176 = getelementptr %struct..s_router_opts* %router_opts, long 0, ubyte 5 + %tmp.177 = load int* %tmp.176 + %tmp.178 = getelementptr %struct..s_router_opts* %router_opts, long 0, ubyte 6 + %tmp.179 = load int* %tmp.178 + %tmp.181 = load uint* %tmp.118 + %tmp.182 = getelementptr %struct..s_router_opts* %router_opts, long 0, ubyte 8 + %tmp.183 = load int* %tmp.182 + %tmp.184 = getelementptr %struct..s_det_routing_arch* %det_routing_arch, long 0, ubyte 0 + %tmp.185 = load uint* %tmp.184 + %tmp.186 = getelementptr %struct..s_det_routing_arch* %det_routing_arch, long 0, ubyte 1 + %tmp.187 = load float* %tmp.186 + %tmp.188 = getelementptr %struct..s_det_routing_arch* %det_routing_arch, long 0, ubyte 2 + %tmp.189 = load float* %tmp.188 + %tmp.190 = getelementptr %struct..s_det_routing_arch* %det_routing_arch, long 0, ubyte 3 + %tmp.191 = load float* %tmp.190 + %tmp.192 = getelementptr %struct..s_det_routing_arch* %det_routing_arch, long 0, ubyte 4 + %tmp.193 = load uint* %tmp.192 + %tmp.194 = getelementptr %struct..s_det_routing_arch* %det_routing_arch, long 0, ubyte 5 + %tmp.195 = load int* %tmp.194 + %tmp.196 = getelementptr %struct..s_det_routing_arch* %det_routing_arch, long 0, ubyte 6 + %tmp.197 = load short* %tmp.196 + %tmp.198 = getelementptr %struct..s_det_routing_arch* %det_routing_arch, long 0, ubyte 7 + %tmp.199 = load short* %tmp.198 + %tmp.200 = getelementptr %struct..s_det_routing_arch* %det_routing_arch, long 0, ubyte 8 + %tmp.201 = load short* %tmp.200 + %tmp.202 = getelementptr %struct..s_det_routing_arch* %det_routing_arch, long 0, ubyte 9 + %tmp.203 = load float* %tmp.202 + %tmp.204 = getelementptr %struct..s_det_routing_arch* %det_routing_arch, long 0, ubyte 10 + %tmp.205 = load float* %tmp.204 + %tmp.206 = load %struct..s_segment_inf** %segment_inf + %tmp.208 = load uint* %tmp.109 + %tmp.209 = getelementptr { uint, float, float, float, float, float, float, float, float, float, float }* %timing_inf, long 0, ubyte 1 + %tmp.210 = load float* %tmp.209 + %tmp.211 = getelementptr { uint, float, float, float, float, float, float, float, float, float, float }* %timing_inf, long 0, ubyte 2 + %tmp.212 = load float* %tmp.211 + %tmp.213 = getelementptr { uint, float, float, float, float, float, float, float, float, float, float }* %timing_inf, long 0, ubyte 3 + %tmp.214 = load float* %tmp.213 + %tmp.215 = getelementptr { uint, float, float, float, float, float, float, float, float, float, float }* %timing_inf, long 0, ubyte 4 + %tmp.216 = load float* %tmp.215 + %tmp.217 = getelementptr { uint, float, float, float, float, float, float, float, float, float, float }* %timing_inf, long 0, ubyte 5 + %tmp.218 = load float* %tmp.217 + %tmp.219 = getelementptr { uint, float, float, float, float, float, float, float, float, float, float }* %timing_inf, long 0, ubyte 6 + %tmp.220 = load float* %tmp.219 + %tmp.221 = getelementptr { uint, float, float, float, float, float, float, float, float, float, float }* %timing_inf, long 0, ubyte 7 + %tmp.222 = load float* %tmp.221 + %tmp.223 = getelementptr { uint, float, float, float, float, float, float, float, float, float, float }* %timing_inf, long 0, ubyte 8 + %tmp.224 = load float* %tmp.223 + %tmp.225 = getelementptr { uint, float, float, float, float, float, float, float, float, float, float }* %timing_inf, long 0, ubyte 9 + %tmp.226 = load float* %tmp.225 + %tmp.227 = getelementptr { uint, float, float, float, float, float, float, float, float, float, float }* %timing_inf, long 0, ubyte 10 + %tmp.228 = load float* %tmp.227 + call void %place_and_route( int %tmp.135, int %tmp.137, float %tmp.139, int %tmp.141, uint %tmp.143, sbyte* %tmp.145, uint %tmp.147, int %tmp.149, sbyte* %tmp.107, sbyte* %tmp.105, sbyte* %tmp.106, sbyte* %tmp.108, uint %tmp.154, uint %tmp.155, uint %tmp.157, float %tmp.159, float %tmp.161, float %tmp.163, float %tmp.165, float %tmp.167, float %tmp.169, float %tmp.171, float %tmp.173, float %tmp.175, int %tmp.177, int %tmp.179, uint %tmp.181, int %tmp.183, uint %tmp.185, float %tmp.187, float %tmp.189, float %tmp.191, uint %tmp.193, int %tmp.195, short %tmp.197, short %tmp.199, short %tmp.201, float %tmp.203, float %tmp.205, %struct..s_segment_inf* %tmp.206, uint %tmp.208, float %tmp.210, float %tmp.212, float %tmp.214, float %tmp.216, float %tmp.218, float %tmp.220, float %tmp.222, float %tmp.224, float %tmp.226, float %tmp.228 ) + %tmp.231 = load uint* %show_graphics + %tmp.232 = setne uint %tmp.231, 0 + br bool %tmp.232, label %then.2, label %endif.2 + + then.2: + br label %endif.2 + + endif.2: + ret int 0 + } + + declare int %printf(sbyte*, ...) + + declare void %place_and_route(int, int, float, int, uint, sbyte*, uint, int, sbyte*, sbyte*, sbyte*, sbyte*, uint, uint, uint, float, float, float, float, float, float, float, float, float, int, int, uint, int, uint, float, float, float, uint, int, short, short, short, float, float, %struct..s_segment_inf*, uint, float, float, float, float, float, float, float, float, float, float) Index: llvm/test/Regression/LLC/2003-05-30-BadFoldGEP.ll diff -c /dev/null llvm/test/Regression/LLC/2003-05-30-BadFoldGEP.ll:1.1 *** /dev/null Fri May 30 23:46:07 2003 --- llvm/test/Regression/LLC/2003-05-30-BadFoldGEP.ll Fri May 30 23:45:56 2003 *************** *** 0 **** --- 1,48 ---- + ;; Date: May 28, 2003. + ;; From: test/Programs/External/SPEC/CINT2000/254.gap.llvm.bc + ;; Function: int %OpenOutput(sbyte* %filename.1) + ;; + ;; Error: A sequence of GEPs is folded incorrectly by llc during selection + ;; causing an assertion about a dynamic casting error. + ;; This code sequence was produced (correctly) by preselection + ;; from a nested pair of ConstantExpr getelementptrs. + ;; The code below is the output of preselection. + ;; The original ConstantExprs are included in a comment. + ;; + ;; Cause: FoldGetElemChain() was inserting an extra leading 0 even though + ;; the first instruction in the sequence contributes no indices. + ;; The next instruction contributes a leading non-zero so another + ;; zero should not be added before it! + ;; + + + %FileType = type { int, [256 x sbyte], int, int, int, int } + %OutputFiles = uninitialized global [16 x %FileType] + %Output = internal global %FileType* null + + + implementation; Functions: + + internal int %OpenOutput(sbyte* %filename.1) { + entry: + %tmp.0 = load %FileType** %Output + %tmp.4 = getelementptr %FileType* %tmp.0, long 1 + + ;;------ Original instruction in 254.gap.llvm.bc: + ;; %tmp.10 = seteq { int, [256 x sbyte], int, int, int, int }* %tmp.4, getelementptr ([16 x { int, [256 x sbyte], int, int, int, int }]* getelementptr ([16 x { int, [256 x sbyte], int, int, int, int }]* %OutputFiles, long 1), long 0, long 0) + + ;;------ Code sequence produced by preselection phase for above instr: + ;; This code sequence is folded incorrectly by llc during selection + ;; causing an assertion about a dynamic casting error. + %addrOfGlobal = getelementptr [16 x %FileType]* %OutputFiles, long 0 + %constantGEP = getelementptr [16 x %FileType]* %addrOfGlobal, long 1 + %constantGEP = getelementptr [16 x %FileType]* %constantGEP, long 0, long 0 + %tmp.10 = seteq %FileType* %tmp.4, %constantGEP + br bool %tmp.10, label %return, label %endif.0 + + endif.0: + ret int 0 + + return: + ret int 1 + } Index: llvm/test/Regression/LLC/2003-05-30-BadPreselectPhi.ll diff -c /dev/null llvm/test/Regression/LLC/2003-05-30-BadPreselectPhi.ll:1.1 *** /dev/null Fri May 30 23:46:07 2003 --- llvm/test/Regression/LLC/2003-05-30-BadPreselectPhi.ll Fri May 30 23:45:56 2003 *************** *** 0 **** --- 1,58 ---- + ;; Date: May 28, 2003. + ;; From: test/Programs/SingleSource/richards_benchmark.c + ;; Function: struct task *handlerfn(struct packet *pkt) + ;; + ;; Error: PreSelection puts the arguments of the Phi just before + ;; the Phi instead of in predecessor blocks. This later + ;; causes llc to produces an invalid register + ;; for the phi arguments. + ;; + ;; PreSelection Output: + ;; *** LLVM code after pre-selection for function handlerfn: + ;; + ;; + ;; %struct..task* %handlerfn(%struct..packet*) { + ;; ;