From gaeke at cs.uiuc.edu Mon Nov 3 00:17:01 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Mon Nov 3 00:17:01 2003 Subject: [llvm-commits] CVS: reopt/lib/Makefile Message-ID: <200311030616.AAA10320@kain.cs.uiuc.edu> Changes in directory reopt/lib: Makefile updated: 1.16 -> 1.17 --- Log message: Define ARCH before testing it in a conditional. --- Diffs of the changes: (+2 -0) Index: reopt/lib/Makefile diff -u reopt/lib/Makefile:1.16 reopt/lib/Makefile:1.17 --- reopt/lib/Makefile:1.16 Fri Sep 12 12:18:58 2003 +++ reopt/lib/Makefile Mon Nov 3 00:16:38 2003 @@ -1,6 +1,8 @@ LEVEL = .. DIRS := BinInterface Mapping ScratchMemory TraceCache Trigger +include $(LEVEL)/Makefile.config + # These dirs contain files that don't currently even compile under Linux/x86: ifeq ($(ARCH),Sparc) DIRS := $(DIRS) Inst LightWtProfiling From gaeke at cs.uiuc.edu Mon Nov 3 00:57:01 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Mon Nov 3 00:57:01 2003 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/TraceToFunction.h Message-ID: <200311030656.AAA05117@kain.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: TraceToFunction.h added (r1.1) --- Log message: Add a header file with the public interface, such as it is, for the TraceToFunction code. --- Diffs of the changes: (+25 -0) Index: reopt/lib/LightWtProfiling/TraceToFunction.h diff -c /dev/null reopt/lib/LightWtProfiling/TraceToFunction.h:1.1 *** /dev/null Mon Nov 3 00:56:47 2003 --- reopt/lib/LightWtProfiling/TraceToFunction.h Mon Nov 3 00:56:37 2003 *************** *** 0 **** --- 1,25 ---- + //===- LightWtProfiling/TraceToFunction.h ------------------------*- C++ -*--=// + // + // Repackage traces as functions, so that global (function-level) optimizations + // can be applied to traces. + // + //===----------------------------------------------------------------------===// + + #ifndef TRACETOFUNCTION_H + #define TRACETOFUNCTION_H + + #include "llvm/Function.h" + #include + #include + class Trace; + + typedef std::set LiveVariableSet; + typedef std::map BasicBlockMap; + + extern BasicBlockMap ReturnBlockForTraceExit; + + /// runTraceToFunction - Entry point for TraceToFunction transformation. + /// + Function *runTraceToFunction (Trace &T); + + #endif // TRACETOFUNCTION_H From gaeke at cs.uiuc.edu Mon Nov 3 01:01:01 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Mon Nov 3 01:01:01 2003 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/TraceToFunction.cpp Message-ID: <200311030700.BAA06924@kain.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: TraceToFunction.cpp updated: 1.12 -> 1.13 --- Log message: Include TraceToFunction.h. Move some typedefs shared with other code to that header. --- Diffs of the changes: (+1 -2) Index: reopt/lib/LightWtProfiling/TraceToFunction.cpp diff -u reopt/lib/LightWtProfiling/TraceToFunction.cpp:1.12 reopt/lib/LightWtProfiling/TraceToFunction.cpp:1.13 --- reopt/lib/LightWtProfiling/TraceToFunction.cpp:1.12 Thu Oct 30 23:36:21 2003 +++ reopt/lib/LightWtProfiling/TraceToFunction.cpp Mon Nov 3 01:00:12 2003 @@ -18,6 +18,7 @@ // //===----------------------------------------------------------------------===// +#include "TraceToFunction.h" #include "Trace.h" #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Pass.h" @@ -35,11 +36,9 @@ #include typedef std::vector TypeVector; -typedef std::set LiveVariableSet; typedef std::map ValueToIntMap; typedef std::map ValueMap; typedef std::map BranchNumberMap; -typedef std::map BasicBlockMap; BasicBlockMap ReturnBlockForTraceExit; From gaeke at cs.uiuc.edu Mon Nov 3 01:01:03 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Mon Nov 3 01:01:03 2003 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp Message-ID: <200311030700.BAA06919@kain.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: UnpackTraceFunction.cpp updated: 1.7 -> 1.8 --- Log message: Include TraceToFunction.h. Don't duplicate stuff here which we're sharing with TraceToFunction. Add some pseudocode for insertCopyMachineInstrs(). Include PhyRegAlloc.h, gag. Declare ExportedFnAllocState extern; start out getValueAllocStateFromGlobal() by fetching the AllocInfo from it. --- Diffs of the changes: (+19 -5) Index: reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp diff -u reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.7 reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.8 --- reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.7 Thu Oct 30 23:36:44 2003 +++ reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp Mon Nov 3 01:00:32 2003 @@ -6,7 +6,9 @@ // //===----------------------------------------------------------------------===// +#include "TraceToFunction.h" #include "../../../../lib/CodeGen/RegAlloc/AllocInfo.h" +#include "../../../../lib/CodeGen/RegAlloc/PhyRegAlloc.h" #include "../../../../lib/Target/Sparc/SparcInternals.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunction.h" @@ -17,11 +19,6 @@ #include "Support/Debug.h" #include -// FIXME: following decls should be shared with TraceToFunction.cpp in a header -typedef std::set LiveVariableSet; -typedef std::map BasicBlockMap; -extern BasicBlockMap ReturnBlockForTraceExit; - /// Insert (a) machine instruction(s) for the current architecture, that /// copies the value in Source to the location specified by Target, at /// the beginning of B. @@ -29,6 +26,19 @@ void insertCopyMachineInstrs (AllocInfo &Source, AllocInfo &Target, MachineBasicBlock &B) { // FIXME: not yet implemented +#if 0 + if (Source is memory && Target is register) { + Insert load instruction from stack loc. Source into register Target + } else if (Source is register && Target is register) { + Insert move instruction from register Source to register Target + } else if (Source is register && Target is memory) { + Insert store instruction from register Source to stack loc. Target + } else if (Source is memory && Target is memory) { + Get a temporary register somehow + Insert load instruction from stack loc. Source into register Temp + Insert store instruction from register Temp to stack loc. Target + } +#endif } /// Emit the same sequence of MachineInstrs that @@ -117,6 +127,8 @@ extern struct ModuleAllocState _llvm_regAllocState; }; +extern PhyRegAlloc::SavedStateMapTy ExportedFnAllocState; + /// Get the register number or stack position where V can be found in the /// machine code for the function F. /// @@ -133,6 +145,8 @@ /// AllocInfo getValueAllocStateFromGlobal (Function *F, Value *V) { // get the saved PhyRegAlloc state for F out of ExportedFnAllocState + std::vector &FState = ExportedFnAllocState[F]; + // get the AllocInfo for V from the saved PhyRegAlloc state for F } From gaeke at cs.uiuc.edu Mon Nov 3 01:01:05 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Mon Nov 3 01:01:05 2003 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/RuntimeOptimizations.cpp Message-ID: <200311030700.BAA06911@kain.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: RuntimeOptimizations.cpp updated: 1.8 -> 1.9 --- Log message: Include TraceToFunction.h. Don't separately declare runTraceToFunction(). Update some comments. --- Diffs of the changes: (+2 -14) Index: reopt/lib/LightWtProfiling/RuntimeOptimizations.cpp diff -u reopt/lib/LightWtProfiling/RuntimeOptimizations.cpp:1.8 reopt/lib/LightWtProfiling/RuntimeOptimizations.cpp:1.9 --- reopt/lib/LightWtProfiling/RuntimeOptimizations.cpp:1.8 Thu Oct 23 13:51:13 2003 +++ reopt/lib/LightWtProfiling/RuntimeOptimizations.cpp Mon Nov 3 01:00:01 2003 @@ -9,6 +9,7 @@ #include "GetTimer.h" #include "Globals.h" #include "Trace.h" +#include "TraceToFunction.h" #include "Support/Debug.h" #include "Support/StringExtras.h" #include "llvm/PassManager.h" @@ -17,9 +18,6 @@ #include #include -// From TraceToFunction.cpp -extern Function *runTraceToFunction (Trace &T); - // From Initialization.cpp extern void initModules (); @@ -62,21 +60,11 @@ PM.add (createVerifierPass ()); PM.run (*TF); - // Make the ExecutionEngine generate code for the function and give us - // a pointer to it. + // the MachineFunctions so that we can run UnpackTraceFunction on them. // FIXME: Register allocation hints presumably would need to be added // to the PassManager of the ExecutionEngine. ExecutionEngine *EE = new ExecutionEngine (TF->getParent (), false, false); void (*p)() = EE->getPointerToFunction (TF); - - // Generate basic block with fixup code for entry: - // Suppose we have a ValueToRegMap which maps values to machine registers - // at the entry to the first on-trace basic block. - // (How would we get this?) - // For each value V in the Trace's live-in set, - // We want to copy V from its register in the matrix function ... - - #endif } From gaeke at cs.uiuc.edu Mon Nov 3 01:04:01 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Mon Nov 3 01:04:01 2003 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/RuntimeOptimizations.cpp TraceToFunction.cpp UnpackTraceFunction.cpp Message-ID: <200311030703.BAA07445@kain.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: RuntimeOptimizations.cpp updated: 1.9 -> 1.10 TraceToFunction.cpp updated: 1.13 -> 1.14 UnpackTraceFunction.cpp updated: 1.8 -> 1.9 --- Log message: Remove some redundant #includes. --- Diffs of the changes: (+0 -4) Index: reopt/lib/LightWtProfiling/RuntimeOptimizations.cpp diff -u reopt/lib/LightWtProfiling/RuntimeOptimizations.cpp:1.9 reopt/lib/LightWtProfiling/RuntimeOptimizations.cpp:1.10 --- reopt/lib/LightWtProfiling/RuntimeOptimizations.cpp:1.9 Mon Nov 3 01:00:01 2003 +++ reopt/lib/LightWtProfiling/RuntimeOptimizations.cpp Mon Nov 3 01:03:30 2003 @@ -15,7 +15,6 @@ #include "llvm/PassManager.h" #include "llvm/BasicBlock.h" #include "llvm/Analysis/Verifier.h" -#include #include // From Initialization.cpp Index: reopt/lib/LightWtProfiling/TraceToFunction.cpp diff -u reopt/lib/LightWtProfiling/TraceToFunction.cpp:1.13 reopt/lib/LightWtProfiling/TraceToFunction.cpp:1.14 --- reopt/lib/LightWtProfiling/TraceToFunction.cpp:1.13 Mon Nov 3 01:00:12 2003 +++ reopt/lib/LightWtProfiling/TraceToFunction.cpp Mon Nov 3 01:03:30 2003 @@ -33,7 +33,6 @@ #include "Support/StringExtras.h" // for utostr() #include "Support/Debug.h" // for DEBUG() #include -#include typedef std::vector TypeVector; typedef std::map ValueToIntMap; Index: reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp diff -u reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.8 reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.9 --- reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.8 Mon Nov 3 01:00:32 2003 +++ reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp Mon Nov 3 01:03:30 2003 @@ -13,11 +13,9 @@ #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstr.h" -#include "llvm/Function.h" #include "reopt/ScratchMemory.h" #include "reopt/MappingInfo.h" #include "Support/Debug.h" -#include /// Insert (a) machine instruction(s) for the current architecture, that /// copies the value in Source to the location specified by Target, at From gaeke at cs.uiuc.edu Mon Nov 3 01:07:01 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Mon Nov 3 01:07:01 2003 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/SecondTrigger.cpp Message-ID: <200311030706.BAA07594@kain.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: SecondTrigger.cpp updated: 1.22 -> 1.23 --- Log message: These '#ifdef __sparc' directives are not necessary. --- Diffs of the changes: (+0 -4) Index: reopt/lib/LightWtProfiling/SecondTrigger.cpp diff -u reopt/lib/LightWtProfiling/SecondTrigger.cpp:1.22 reopt/lib/LightWtProfiling/SecondTrigger.cpp:1.23 --- reopt/lib/LightWtProfiling/SecondTrigger.cpp:1.22 Thu Oct 30 14:13:18 2003 +++ reopt/lib/LightWtProfiling/SecondTrigger.cpp Mon Nov 3 01:05:59 2003 @@ -42,15 +42,11 @@ std::map firstTriggerAddr; extern "C" void llvm_time_start(){ -#ifdef __sparc cpc_count_usr_events(1); -#endif } extern "C" void llvm_time_end2(){ -#ifdef __sparc cpc_count_usr_events(0); -#endif } static void resetCounters (uint64_t pcAddr, uint64_t reverseAddr) { From lattner at cs.uiuc.edu Mon Nov 3 11:28:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Nov 3 11:28:00 2003 Subject: [llvm-commits] CVS: llvm/tools/gccld/gccld.cpp Message-ID: <200311031727.LAA03559@neo.cs.uiuc.edu> Changes in directory llvm/tools/gccld: gccld.cpp updated: 1.58 -> 1.59 --- Log message: If linking a library, do not link other libraries, like libc, into it! This fixes lots of annoying warnings and error messages --- Diffs of the changes: (+4 -1) Index: llvm/tools/gccld/gccld.cpp diff -u llvm/tools/gccld/gccld.cpp:1.58 llvm/tools/gccld/gccld.cpp:1.59 --- llvm/tools/gccld/gccld.cpp:1.58 Fri Oct 24 15:00:06 2003 +++ llvm/tools/gccld/gccld.cpp Mon Nov 3 11:27:17 2003 @@ -234,7 +234,10 @@ // Link in all of the files if (LinkFiles(argv[0], Composite.get(), InputFilenames, Verbose)) return 1; // Error already printed - LinkLibraries(argv[0], Composite.get(), Libraries, LibPaths, Verbose, Native); + + if (!LinkAsLibrary) + LinkLibraries(argv[0], Composite.get(), Libraries, LibPaths, + Verbose, Native); // Link in all of the libraries next... From lattner at cs.uiuc.edu Mon Nov 3 11:34:33 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Nov 3 11:34:33 2003 Subject: [llvm-commits] CVS: llvm/lib/CWriter/Writer.cpp Message-ID: <200311031732.LAA02534@zion.cs.uiuc.edu> Changes in directory llvm/lib/CWriter: Writer.cpp updated: 1.140 -> 1.141 --- Log message: Fix bugs with attribute weak emission --- Diffs of the changes: (+6 -3) Index: llvm/lib/CWriter/Writer.cpp diff -u llvm/lib/CWriter/Writer.cpp:1.140 llvm/lib/CWriter/Writer.cpp:1.141 --- llvm/lib/CWriter/Writer.cpp:1.140 Sun Nov 2 22:31:54 2003 +++ llvm/lib/CWriter/Writer.cpp Mon Nov 3 11:32:38 2003 @@ -653,6 +653,7 @@ if ((I->hasInternalLinkage() || !MangledGlobals.count(I)) && !I->getIntrinsicID()) { printFunctionSignature(I, true); + if (I->hasWeakLinkage()) Out << " __attribute__((weak))"; Out << ";\n"; } } @@ -671,7 +672,11 @@ if (!I->isExternal()) { Out << "extern "; printType(Out, I->getType()->getElementType(), Mang->getValueName(I)); - + + if (I->hasLinkOnceLinkage()) + Out << " __attribute__((common))"; + else if (I->hasWeakLinkage()) + Out << " __attribute__((weak))"; Out << ";\n"; } } @@ -903,8 +908,6 @@ FunctionInnards << ")"; // Print out the return type and the entire signature for that matter printType(Out, F->getReturnType(), FunctionInnards.str()); - - if (F->hasWeakLinkage()) Out << " __attribute((weak))"; } void CWriter::printFunction(Function *F) { From lattner at cs.uiuc.edu Mon Nov 3 11:36:04 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Nov 3 11:36:04 2003 Subject: [llvm-commits] CVS: llvm/lib/CWriter/Writer.cpp Message-ID: <200311031735.LAA02808@zion.cs.uiuc.edu> Changes in directory llvm/lib/CWriter: Writer.cpp updated: 1.141 -> 1.142 --- Log message: Work around a bug in GCC where it can't handle common variables marked weak. --- Diffs of the changes: (+8 -1) Index: llvm/lib/CWriter/Writer.cpp diff -u llvm/lib/CWriter/Writer.cpp:1.141 llvm/lib/CWriter/Writer.cpp:1.142 --- llvm/lib/CWriter/Writer.cpp:1.141 Mon Nov 3 11:32:38 2003 +++ llvm/lib/CWriter/Writer.cpp Mon Nov 3 11:35:00 2003 @@ -693,7 +693,14 @@ Out << " __attribute__((common))"; else if (I->hasWeakLinkage()) Out << " __attribute__((weak))"; - if (!I->getInitializer()->isNullValue()) { + + // If the initializer is not null, emit the initializer. If it is null, + // we try to avoid emitting large amounts of zeros. The problem with + // this, however, occurs when the variable has weak linkage. In this + // case, the assembler will complain about the variable being both weak + // and common, so we disable this optimization. + if (!I->getInitializer()->isNullValue() || + I->hasWeakLinkage()) { Out << " = " ; writeOperand(I->getInitializer()); } From lattner at cs.uiuc.edu Mon Nov 3 12:34:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Nov 3 12:34:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/InstCombine/2003-11-03-VarargsCallBug.ll Message-ID: <200311031833.MAA04720@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/InstCombine: 2003-11-03-VarargsCallBug.ll added (r1.1) --- Log message: New testcase for a bug in instcombine --- Diffs of the changes: (+13 -0) Index: llvm/test/Regression/Transforms/InstCombine/2003-11-03-VarargsCallBug.ll diff -c /dev/null llvm/test/Regression/Transforms/InstCombine/2003-11-03-VarargsCallBug.ll:1.1 *** /dev/null Mon Nov 3 12:33:55 2003 --- llvm/test/Regression/Transforms/InstCombine/2003-11-03-VarargsCallBug.ll Mon Nov 3 12:33:44 2003 *************** *** 0 **** --- 1,13 ---- + ; The cast in this testcase is not eliminatable on a 32-bit target! + ; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep cast + + target endian = little + target pointersize = 32 + + declare void %foo(...) + + void %test(long %X) { + %Y = cast long %X to int* + call void (...)* %foo(int* %Y) + ret void + } From lattner at cs.uiuc.edu Mon Nov 3 12:46:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Nov 3 12:46:01 2003 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Type.cpp Message-ID: <200311031845.MAA05014@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Type.cpp updated: 1.78 -> 1.79 --- Log message: Fix InstCombine/2003-11-03-VarargsCallBug.ll --- Diffs of the changes: (+3 -4) Index: llvm/lib/VMCore/Type.cpp diff -u llvm/lib/VMCore/Type.cpp:1.78 llvm/lib/VMCore/Type.cpp:1.79 --- llvm/lib/VMCore/Type.cpp:1.78 Mon Oct 20 14:43:21 2003 +++ llvm/lib/VMCore/Type.cpp Mon Nov 3 12:44:58 2003 @@ -102,10 +102,9 @@ case Type::ShortTyID: return Ty == Type::UShortTy; case Type::UIntTyID: return Ty == Type::IntTy; case Type::IntTyID: return Ty == Type::UIntTy; - case Type::ULongTyID: - case Type::LongTyID: - case Type::PointerTyID: - return Ty == Type::ULongTy || Ty == Type::LongTy || isa(Ty); + case Type::ULongTyID: return Ty == Type::LongTy; + case Type::LongTyID: return Ty == Type::ULongTy; + case Type::PointerTyID: return isa(Ty); default: return false; // Other types have no identity values } From lattner at cs.uiuc.edu Mon Nov 3 13:28:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Nov 3 13:28:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Jello/2003-11-03-GlobalBool.llx Message-ID: <200311031927.NAA15404@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Jello: 2003-11-03-GlobalBool.llx added (r1.1) --- Log message: New testcase --- Diffs of the changes: (+4 -0) Index: llvm/test/Regression/Jello/2003-11-03-GlobalBool.llx diff -c /dev/null llvm/test/Regression/Jello/2003-11-03-GlobalBool.llx:1.1 *** /dev/null Mon Nov 3 13:27:28 2003 --- llvm/test/Regression/Jello/2003-11-03-GlobalBool.llx Mon Nov 3 13:27:17 2003 *************** *** 0 **** --- 1,4 ---- + ; RUN: llvm-as < %s | llc -march=x86 | not grep '.byte[[:space:]]*true' + + %X = global bool true + From lattner at cs.uiuc.edu Mon Nov 3 13:34:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Nov 3 13:34:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/Printer.cpp Message-ID: <200311031933.NAA15837@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: Printer.cpp updated: 1.67 -> 1.68 --- Log message: * Reformat some code * Emit bools as 1/0 instead of true/false, fixing compilation of eon and PR 83 & Jello/2003-11-03-GlobalBool.llx --- Diffs of the changes: (+34 -42) Index: llvm/lib/Target/X86/Printer.cpp diff -u llvm/lib/Target/X86/Printer.cpp:1.67 llvm/lib/Target/X86/Printer.cpp:1.68 --- llvm/lib/Target/X86/Printer.cpp:1.67 Mon Oct 20 14:43:18 2003 +++ llvm/lib/Target/X86/Printer.cpp Mon Nov 3 13:33:45 2003 @@ -222,49 +222,41 @@ } O << "\t"; - if (const ConstantExpr* CE = dyn_cast(CV)) - { - // Constant expression built from operators, constants, and - // symbolic addrs - O << ConstantExprToString(CE) << "\n"; - } - else if (type->isPrimitiveType()) - { - if (type->isFloatingPoint()) { - // FP Constants are printed as integer constants to avoid losing - // precision... - double Val = cast(CV)->getValue(); - if (type == Type::FloatTy) { - float FVal = (float)Val; - char *ProxyPtr = (char*)&FVal; // Abide by C TBAA rules - O << *(unsigned int*)ProxyPtr; - } else if (type == Type::DoubleTy) { - char *ProxyPtr = (char*)&Val; // Abide by C TBAA rules - O << *(uint64_t*)ProxyPtr; - } else { - assert(0 && "Unknown floating point type!"); - } - - O << "\t# " << type->getDescription() << " value: " << Val << "\n"; - } else { - WriteAsOperand(O, CV, false, false) << "\n"; - } - } - else if (const ConstantPointerRef* CPR = dyn_cast(CV)) - { - // This is a constant address for a global variable or method. - // Use the name of the variable or method as the address value. - O << Mang->getValueName(CPR->getValue()) << "\n"; - } - else if (isa(CV)) - { - // Null pointer value - O << "0\n"; - } - else - { - assert(0 && "Unknown elementary type for constant"); + if (const ConstantExpr* CE = dyn_cast(CV)) { + // Constant expression built from operators, constants, and + // symbolic addrs + O << ConstantExprToString(CE) << "\n"; + } else if (const ConstantBool *CB = dyn_cast(CV)) { + O << (CB->getValue() ? "1\n" : "0\n"); + } else if (type->isFloatingPoint()) { + // FP Constants are printed as integer constants to avoid losing + // precision... + double Val = cast(CV)->getValue(); + if (type == Type::FloatTy) { + float FVal = (float)Val; + char *ProxyPtr = (char*)&FVal; // Abide by C TBAA rules + O << *(unsigned int*)ProxyPtr; + } else if (type == Type::DoubleTy) { + char *ProxyPtr = (char*)&Val; // Abide by C TBAA rules + O << *(uint64_t*)ProxyPtr; + } else { + assert(0 && "Unknown floating point type!"); } + + O << "\t# " << type->getDescription() << " value: " << Val << "\n"; + } else if (type->isPrimitiveType()) { + + WriteAsOperand(O, CV, false, false) << "\n"; + } else if (const ConstantPointerRef* CPR = dyn_cast(CV)) { + // This is a constant address for a global variable or method. + // Use the name of the variable or method as the address value. + O << Mang->getValueName(CPR->getValue()) << "\n"; + } else if (isa(CV)) { + // Null pointer value + O << "0\n"; + } else { + assert(0 && "Unknown elementary type for constant"); + } } /// isStringCompatible - Can we treat the specified array as a string? From lattner at cs.uiuc.edu Mon Nov 3 13:45:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Nov 3 13:45:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/Printer.cpp Message-ID: <200311031944.NAA16920@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: Printer.cpp updated: 1.68 -> 1.69 --- Log message: Incorporate printSingleConstantValue into its single caller --- Diffs of the changes: (+66 -89) Index: llvm/lib/Target/X86/Printer.cpp diff -u llvm/lib/Target/X86/Printer.cpp:1.68 llvm/lib/Target/X86/Printer.cpp:1.69 --- llvm/lib/Target/X86/Printer.cpp:1.68 Mon Nov 3 13:33:45 2003 +++ llvm/lib/Target/X86/Printer.cpp Mon Nov 3 13:44:05 2003 @@ -82,7 +82,6 @@ bool doInitialization(Module &M); bool doFinalization(Module &M); void printConstantValueOnly(const Constant* CV); - void printSingleConstantValue(const Constant* CV); }; } // end of anonymous namespace @@ -174,91 +173,6 @@ } } -/// printSingleConstantValue - Print a single constant value. -/// -void -Printer::printSingleConstantValue(const Constant* CV) -{ - assert(CV->getType() != Type::VoidTy && - CV->getType() != Type::TypeTy && - CV->getType() != Type::LabelTy && - "Unexpected type for Constant"); - - assert((!isa(CV) && ! isa(CV)) - && "Aggregate types should be handled outside this function"); - - const Type *type = CV->getType(); - O << "\t"; - switch(type->getPrimitiveID()) - { - case Type::BoolTyID: case Type::UByteTyID: case Type::SByteTyID: - O << ".byte"; - break; - case Type::UShortTyID: case Type::ShortTyID: - O << ".word"; - break; - case Type::UIntTyID: case Type::IntTyID: case Type::PointerTyID: - O << ".long"; - break; - case Type::ULongTyID: case Type::LongTyID: - O << ".quad"; - break; - case Type::FloatTyID: - O << ".long"; - break; - case Type::DoubleTyID: - O << ".quad"; - break; - case Type::ArrayTyID: - if ((cast(type)->getElementType() == Type::UByteTy) || - (cast(type)->getElementType() == Type::SByteTy)) - O << ".string"; - else - assert (0 && "Can't handle printing this type of array"); - break; - default: - assert (0 && "Can't handle printing this type of thing"); - break; - } - O << "\t"; - - if (const ConstantExpr* CE = dyn_cast(CV)) { - // Constant expression built from operators, constants, and - // symbolic addrs - O << ConstantExprToString(CE) << "\n"; - } else if (const ConstantBool *CB = dyn_cast(CV)) { - O << (CB->getValue() ? "1\n" : "0\n"); - } else if (type->isFloatingPoint()) { - // FP Constants are printed as integer constants to avoid losing - // precision... - double Val = cast(CV)->getValue(); - if (type == Type::FloatTy) { - float FVal = (float)Val; - char *ProxyPtr = (char*)&FVal; // Abide by C TBAA rules - O << *(unsigned int*)ProxyPtr; - } else if (type == Type::DoubleTy) { - char *ProxyPtr = (char*)&Val; // Abide by C TBAA rules - O << *(uint64_t*)ProxyPtr; - } else { - assert(0 && "Unknown floating point type!"); - } - - O << "\t# " << type->getDescription() << " value: " << Val << "\n"; - } else if (type->isPrimitiveType()) { - - WriteAsOperand(O, CV, false, false) << "\n"; - } else if (const ConstantPointerRef* CPR = dyn_cast(CV)) { - // This is a constant address for a global variable or method. - // Use the name of the variable or method as the address value. - O << Mang->getValueName(CPR->getValue()) << "\n"; - } else if (isa(CV)) { - // Null pointer value - O << "0\n"; - } else { - assert(0 && "Unknown elementary type for constant"); - } -} - /// isStringCompatible - Can we treat the specified array as a string? /// Only if it is an array of ubytes or non-negative sbytes. /// @@ -319,12 +233,12 @@ } // Print a constant value or values (it may be an aggregate). -// Uses printSingleConstantValue() to print each individual value. void Printer::printConstantValueOnly(const Constant *CV) { const TargetData &TD = TM.getTargetData(); if (CV->isNullValue()) { O << "\t.zero\t " << TD.getTypeSize(CV->getType()) << "\n"; + return; } else if (const ConstantArray *CVA = dyn_cast(CV)) { if (isStringCompatible(CVA)) { // print the string alone and return @@ -334,6 +248,7 @@ for (unsigned i=0; i < constValues.size(); i++) printConstantValueOnly(cast(constValues[i].get())); } + return; } else if (const ConstantStruct *CVS = dyn_cast(CV)) { // Print the fields in successive locations. Pad to align if needed! const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType()); @@ -358,8 +273,70 @@ } assert(sizeSoFar == cvsLayout->StructSize && "Layout of constant struct may be incorrect!"); - } else - printSingleConstantValue(CV); + return; + } + + const Type *type = CV->getType(); + O << "\t"; + switch (type->getPrimitiveID()) { + case Type::BoolTyID: case Type::UByteTyID: case Type::SByteTyID: + O << ".byte"; + break; + case Type::UShortTyID: case Type::ShortTyID: + O << ".word"; + break; + case Type::FloatTyID: case Type::PointerTyID: + case Type::UIntTyID: case Type::IntTyID: + O << ".long"; + break; + case Type::DoubleTyID: + case Type::ULongTyID: case Type::LongTyID: + O << ".quad"; + break; + default: + assert (0 && "Can't handle printing this type of thing"); + break; + } + O << "\t"; + + if (const ConstantExpr* CE = dyn_cast(CV)) { + // Constant expression built from operators, constants, and + // symbolic addrs + O << ConstantExprToString(CE) << "\n"; + } else if (const ConstantBool *CB = dyn_cast(CV)) { + O << (CB->getValue() ? "1\n" : "0\n"); + } else if (type->isFloatingPoint()) { + // FP Constants are printed as integer constants to avoid losing + // precision... + double Val = cast(CV)->getValue(); + if (type == Type::FloatTy) { + union FU { // Abide by C TBAA rules + float FVal; + unsigned UVal; + } U; + U.FVal = Val; + O << U.UVal; + } else if (type == Type::DoubleTy) { + union DU { // Abide by C TBAA rules + double FVal; + uint64_t UVal; + } U; + U.FVal = Val; + O << U.UVal; + } else { + assert(0 && "Unknown floating point type!"); + } + + O << "\t# " << *type << " value: " << Val << "\n"; + } else if (type->isPrimitiveType()) { + WriteAsOperand(O, CV, false, false) << "\n"; + } else if (const ConstantPointerRef* CPR = dyn_cast(CV)) { + // This is a constant address for a global variable or method. + // Use the name of the variable or method as the address value. + O << Mang->getValueName(CPR->getValue()) << "\n"; + } else { + assert(0 && "Unknown elementary type for constant"); + } } /// printConstantPool - Print to the current output stream assembly From lattner at cs.uiuc.edu Mon Nov 3 14:09:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Nov 3 14:09:02 2003 Subject: [llvm-commits] CVS: llvm-www/releases/1.0/docs/ReleaseNotes.html Message-ID: <200311032008.OAA19119@zion.cs.uiuc.edu> Changes in directory llvm-www/releases/1.0/docs: ReleaseNotes.html updated: 1.17 -> 1.18 --- Log message: Bugz --- Diffs of the changes: (+2 -1) Index: llvm-www/releases/1.0/docs/ReleaseNotes.html diff -u llvm-www/releases/1.0/docs/ReleaseNotes.html:1.17 llvm-www/releases/1.0/docs/ReleaseNotes.html:1.18 --- llvm-www/releases/1.0/docs/ReleaseNotes.html:1.17 Sat Nov 1 20:15:38 2003 +++ llvm-www/releases/1.0/docs/ReleaseNotes.html Mon Nov 3 14:08:22 2003 @@ -373,6 +373,7 @@ support the unwind instruction, so code that throws a C++ exception or calls the C longjmp function will abort.

+

  • [X86] Emission of global bool initializers broken (fixed in 1.1).

  • Known problems with the Sparc back-end

      @@ -435,6 +436,6 @@ Maintained By: The LLVM Team
      -Last modified: Sat Nov 1 20:14:52 CST 2003 +Last modified: Mon Nov 3 14:07:40 CST 2003 From lattner at cs.uiuc.edu Mon Nov 3 14:09:06 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Nov 3 14:09:06 2003 Subject: [llvm-commits] CVS: llvm/docs/ReleaseNotes.html Message-ID: <200311032008.OAA18802@zion.cs.uiuc.edu> Changes in directory llvm/docs: ReleaseNotes.html updated: 1.28 -> 1.29 --- Log message: updates to release notes --- Diffs of the changes: (+3 -3) Index: llvm/docs/ReleaseNotes.html diff -u llvm/docs/ReleaseNotes.html:1.28 llvm/docs/ReleaseNotes.html:1.29 --- llvm/docs/ReleaseNotes.html:1.28 Sat Nov 1 20:15:11 2003 +++ llvm/docs/ReleaseNotes.html Mon Nov 3 14:08:08 2003 @@ -65,7 +65,7 @@ release implements the following new features:

        -
      1. temp
      2. +
      3. A new LLVM profiler, similar to gprof is available
      4. temp
      5. temp

      @@ -96,7 +96,7 @@

    • llvm-gcc crashes compiling global union initializer
    • C front-end crash on empty structure
    • CFrontend crashes when compiling C99 compound expressions
    • - +
    • [X86] Emission of global bool initializers broken
    • At this time, LLVM is known to work properly with SPEC CPU 2000, the Olden @@ -393,6 +393,6 @@ Maintained By: The LLVM Team
      -Last modified: Sat Nov 1 20:14:25 CST 2003 +Last modified: Mon Nov 3 14:07:07 CST 2003 From lattner at cs.uiuc.edu Mon Nov 3 14:20:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Nov 3 14:20:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/Printer.cpp Message-ID: <200311032019.OAA21794@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: Printer.cpp updated: 1.69 -> 1.70 --- Log message: Significantly simplify constant emission by unifying the stuff which used to build up strings with the stuff that used to print to an ostream directly. We now NEVER build up big strings, only to print them once they are formed. --- Diffs of the changes: (+119 -147) Index: llvm/lib/Target/X86/Printer.cpp diff -u llvm/lib/Target/X86/Printer.cpp:1.69 llvm/lib/Target/X86/Printer.cpp:1.70 --- llvm/lib/Target/X86/Printer.cpp:1.69 Mon Nov 3 13:44:05 2003 +++ llvm/lib/Target/X86/Printer.cpp Mon Nov 3 14:19:49 2003 @@ -77,11 +77,10 @@ void printMemReference(const MachineInstr *MI, unsigned Op); void printConstantPool(MachineConstantPool *MCP); bool runOnMachineFunction(MachineFunction &F); - std::string ConstantExprToString(const ConstantExpr* CE); - std::string valToExprString(const Value* V); bool doInitialization(Module &M); bool doFinalization(Module &M); - void printConstantValueOnly(const Constant* CV); + void emitGlobalConstant(const Constant* CV); + void emitConstantValueOnly(const Constant *CV); }; } // end of anonymous namespace @@ -94,85 +93,6 @@ return new Printer(o, tm); } -/// valToExprString - Helper function for ConstantExprToString(). -/// Appends result to argument string S. -/// -std::string Printer::valToExprString(const Value* V) { - std::string S; - bool failed = false; - if (const Constant* CV = dyn_cast(V)) { // symbolic or known - if (const ConstantBool *CB = dyn_cast(CV)) - S += std::string(CB == ConstantBool::True ? "1" : "0"); - else if (const ConstantSInt *CI = dyn_cast(CV)) - S += itostr(CI->getValue()); - else if (const ConstantUInt *CI = dyn_cast(CV)) - S += utostr(CI->getValue()); - else if (const ConstantFP *CFP = dyn_cast(CV)) - S += ftostr(CFP->getValue()); - else if (isa(CV)) - S += "0"; - else if (const ConstantPointerRef *CPR = dyn_cast(CV)) - S += valToExprString(CPR->getValue()); - else if (const ConstantExpr *CE = dyn_cast(CV)) - S += ConstantExprToString(CE); - else - failed = true; - } else if (const GlobalValue* GV = dyn_cast(V)) { - S += Mang->getValueName(GV); - } - else - failed = true; - - if (failed) { - assert(0 && "Cannot convert value to string"); - S += ""; - } - return S; -} - -/// ConstantExprToString - Convert a ConstantExpr to an asm expression -/// and return this as a string. -/// -std::string Printer::ConstantExprToString(const ConstantExpr* CE) { - const TargetData &TD = TM.getTargetData(); - switch(CE->getOpcode()) { - case Instruction::GetElementPtr: - { // generate a symbolic expression for the byte address - const Value* ptrVal = CE->getOperand(0); - std::vector idxVec(CE->op_begin()+1, CE->op_end()); - if (unsigned Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec)) - return "(" + valToExprString(ptrVal) + ") + " + utostr(Offset); - else - return valToExprString(ptrVal); - } - - case Instruction::Cast: - // Support only non-converting or widening casts for now, that is, - // ones that do not involve a change in value. This assertion is - // not a complete check. - { - Constant *Op = CE->getOperand(0); - const Type *OpTy = Op->getType(), *Ty = CE->getType(); - assert(((isa(OpTy) - && (Ty == Type::LongTy || Ty == Type::ULongTy)) - || (isa(Ty) - && (OpTy == Type::LongTy || OpTy == Type::ULongTy))) - || (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy)) - && (OpTy->isLosslesslyConvertibleTo(Ty)))) - && "FIXME: Don't yet support this kind of constant cast expr"); - return "(" + valToExprString(Op) + ")"; - } - - case Instruction::Add: - return "(" + valToExprString(CE->getOperand(0)) + ") + (" - + valToExprString(CE->getOperand(1)) + ")"; - - default: - assert(0 && "Unsupported operator in ConstantExprToString()"); - return ""; - } -} - /// isStringCompatible - Can we treat the specified array as a string? /// Only if it is an array of ubytes or non-negative sbytes. /// @@ -197,43 +117,106 @@ /// getAsCString - Return the specified array as a C compatible /// string, only if the predicate isStringCompatible is true. /// -static std::string getAsCString(const ConstantArray *CVA) { +static void printAsCString(std::ostream &O, const ConstantArray *CVA) { assert(isStringCompatible(CVA) && "Array is not string compatible!"); - std::string Result; - const Type *ETy = cast(CVA->getType())->getElementType(); - Result = "\""; + O << "\""; for (unsigned i = 0; i < CVA->getNumOperands(); ++i) { unsigned char C = cast(CVA->getOperand(i))->getRawValue(); if (C == '"') { - Result += "\\\""; + O << "\\\""; } else if (C == '\\') { - Result += "\\\\"; + O << "\\\\"; } else if (isprint(C)) { - Result += C; + O << C; } else { switch(C) { - case '\b': Result += "\\b"; break; - case '\f': Result += "\\f"; break; - case '\n': Result += "\\n"; break; - case '\r': Result += "\\r"; break; - case '\t': Result += "\\t"; break; + case '\b': O << "\\b"; break; + case '\f': O << "\\f"; break; + case '\n': O << "\\n"; break; + case '\r': O << "\\r"; break; + case '\t': O << "\\t"; break; default: - Result += '\\'; - Result += toOctal(C >> 6); - Result += toOctal(C >> 3); - Result += toOctal(C >> 0); + O << '\\'; + O << toOctal(C >> 6); + O << toOctal(C >> 3); + O << toOctal(C >> 0); break; } } } - Result += "\""; - return Result; + O << "\""; +} + +// Print out the specified constant, without a storage class. Only the +// constants valid in constant expressions can occur here. +void Printer::emitConstantValueOnly(const Constant *CV) { + if (CV->isNullValue()) + O << "0"; + else if (const ConstantBool *CB = dyn_cast(CV)) { + assert(CB == ConstantBool::True); + O << "1"; + } else if (const ConstantSInt *CI = dyn_cast(CV)) + O << CI->getValue(); + else if (const ConstantUInt *CI = dyn_cast(CV)) + O << CI->getValue(); + else if (const ConstantPointerRef *CPR = dyn_cast(CV)) + // This is a constant address for a global variable or function. Use the + // name of the variable or function as the address value. + O << Mang->getValueName(CPR->getValue()) << "\n"; + else if (const ConstantExpr *CE = dyn_cast(CV)) { + const TargetData &TD = TM.getTargetData(); + switch(CE->getOpcode()) { + case Instruction::GetElementPtr: { + // generate a symbolic expression for the byte address + const Constant *ptrVal = CE->getOperand(0); + std::vector idxVec(CE->op_begin()+1, CE->op_end()); + if (unsigned Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec)) { + O << "("; + emitConstantValueOnly(ptrVal); + O << ") + " + Offset; + } else { + emitConstantValueOnly(ptrVal); + } + break; + } + case Instruction::Cast: { + // Support only non-converting or widening casts for now, that is, ones + // that do not involve a change in value. This assertion is not a + // complete check. + Constant *Op = CE->getOperand(0); + const Type *OpTy = Op->getType(), *Ty = CE->getType(); + assert(((isa(OpTy) + && (Ty == Type::LongTy || Ty == Type::ULongTy)) + || (isa(Ty) + && (OpTy == Type::LongTy || OpTy == Type::ULongTy))) + || (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy)) + && (OpTy->isLosslesslyConvertibleTo(Ty)))) + && "FIXME: Don't yet support this kind of constant cast expr"); + O << "("; + emitConstantValueOnly(Op); + O << ")"; + break; + } + case Instruction::Add: + O << "("; + emitConstantValueOnly(CE->getOperand(0)); + O << ") + ("; + emitConstantValueOnly(CE->getOperand(1)); + O << ")"; + break; + default: + assert(0 && "Unsupported operator!"); + } + } else { + assert(0 && "Unknown constant value!"); + } } -// Print a constant value or values (it may be an aggregate). -void Printer::printConstantValueOnly(const Constant *CV) { +// Print a constant value or values, with the appropriate storage class as a +// prefix. +void Printer::emitGlobalConstant(const Constant *CV) { const TargetData &TD = TM.getTargetData(); if (CV->isNullValue()) { @@ -241,12 +224,13 @@ return; } else if (const ConstantArray *CVA = dyn_cast(CV)) { if (isStringCompatible(CVA)) { - // print the string alone and return - O << "\t.ascii\t" << getAsCString(CVA) << "\n"; + O << "\t.ascii\t"; + printAsCString(O, CVA); + O << "\n"; } else { // Not a string. Print the values in successive locations const std::vector &constValues = CVA->getValues(); for (unsigned i=0; i < constValues.size(); i++) - printConstantValueOnly(cast(constValues[i].get())); + emitGlobalConstant(cast(constValues[i].get())); } return; } else if (const ConstantStruct *CVS = dyn_cast(CV)) { @@ -265,7 +249,7 @@ sizeSoFar += fieldSize + padSize; // Now print the actual field value - printConstantValueOnly(field); + emitGlobalConstant(field); // Insert the field padding unless it's zero bytes... if (padSize) @@ -274,6 +258,31 @@ assert(sizeSoFar == cvsLayout->StructSize && "Layout of constant struct may be incorrect!"); return; + } else if (const ConstantFP *CFP = dyn_cast(CV)) { + // FP Constants are printed as integer constants to avoid losing + // precision... + double Val = CFP->getValue(); + switch (CFP->getType()->getPrimitiveID()) { + default: assert(0 && "Unknown floating point type!"); + case Type::FloatTyID: { + union FU { // Abide by C TBAA rules + float FVal; + unsigned UVal; + } U; + U.FVal = Val; + O << ".long\t" << U.UVal << "\t# float " << Val << "\n"; + return; + } + case Type::DoubleTyID: { + union DU { // Abide by C TBAA rules + double FVal; + uint64_t UVal; + } U; + U.FVal = Val; + O << ".quad\t" << U.UVal << "\t# double " << Val << "\n"; + return; + } + } } const Type *type = CV->getType(); @@ -298,45 +307,8 @@ break; } O << "\t"; - - if (const ConstantExpr* CE = dyn_cast(CV)) { - // Constant expression built from operators, constants, and - // symbolic addrs - O << ConstantExprToString(CE) << "\n"; - } else if (const ConstantBool *CB = dyn_cast(CV)) { - O << (CB->getValue() ? "1\n" : "0\n"); - } else if (type->isFloatingPoint()) { - // FP Constants are printed as integer constants to avoid losing - // precision... - double Val = cast(CV)->getValue(); - if (type == Type::FloatTy) { - union FU { // Abide by C TBAA rules - float FVal; - unsigned UVal; - } U; - U.FVal = Val; - O << U.UVal; - } else if (type == Type::DoubleTy) { - union DU { // Abide by C TBAA rules - double FVal; - uint64_t UVal; - } U; - U.FVal = Val; - O << U.UVal; - } else { - assert(0 && "Unknown floating point type!"); - } - - O << "\t# " << *type << " value: " << Val << "\n"; - } else if (type->isPrimitiveType()) { - WriteAsOperand(O, CV, false, false) << "\n"; - } else if (const ConstantPointerRef* CPR = dyn_cast(CV)) { - // This is a constant address for a global variable or method. - // Use the name of the variable or method as the address value. - O << Mang->getValueName(CPR->getValue()) << "\n"; - } else { - assert(0 && "Unknown elementary type for constant"); - } + emitConstantValueOnly(CV); + O << "\n"; } /// printConstantPool - Print to the current output stream assembly @@ -356,7 +328,7 @@ << "\n"; O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t#" << *CP[i] << "\n"; - printConstantValueOnly (CP[i]); + emitGlobalConstant(CP[i]); } } @@ -980,7 +952,7 @@ O << " = "; WriteAsOperand(O, C, false, false, &M); O << "\n"; - printConstantValueOnly(C); + emitGlobalConstant(C); } } From lattner at cs.uiuc.edu Mon Nov 3 15:15:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Nov 3 15:15:02 2003 Subject: [llvm-commits] CVS: poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp Message-ID: <200311032114.PAA28596@zion.cs.uiuc.edu> Changes in directory poolalloc/runtime/PoolAllocator: PoolAllocatorChained.cpp updated: 1.18 -> 1.19 --- Log message: Fix bugs freeing memory --- Diffs of the changes: (+8 -4) Index: poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp diff -u poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp:1.18 poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp:1.19 --- poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp:1.18 Mon Oct 27 14:38:57 2003 +++ poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp Mon Nov 3 15:13:44 2003 @@ -455,9 +455,10 @@ int Idx = -1; if (PS) { // Pool->Ptr1 could be null if Ptr2 isn't PPS = (PoolSlab**)&Pool->Ptr1; - PS->containsElement(Node, NodeSize); - for (; Idx == -1 && PS; PPS = &PS->Next, PS = PS->Next) + for (; PS; PPS = &PS->Next, PS = PS->Next) { Idx = PS->containsElement(Node, NodeSize); + if (Idx != -1) break; + } } // If the partially allocated slab list doesn't contain it, maybe the @@ -465,12 +466,15 @@ if (PS == 0) { PS = (PoolSlab*)Pool->Ptr2; PPS = (PoolSlab**)&Pool->Ptr2; + assert(Idx == -1 && "Found node but don't have PS?"); - Idx = PS->containsElement(Node, NodeSize); - for (; Idx == -1; PPS = &PS->Next, PS = PS->Next) { + while (1) { assert(PS && "poolfree: node being free'd not found in allocation " " pool specified!\n"); Idx = PS->containsElement(Node, NodeSize); + if (Idx != -1) break; + PPS = &PS->Next; + PS = PS->Next; } // Now that we found the node, we are about to free an element from it. From lattner at cs.uiuc.edu Mon Nov 3 15:15:04 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Nov 3 15:15:04 2003 Subject: [llvm-commits] CVS: poolalloc/runtime/PoolAllocator/Makefile Message-ID: <200311032114.PAA28591@zion.cs.uiuc.edu> Changes in directory poolalloc/runtime/PoolAllocator: Makefile updated: 1.3 -> 1.4 --- Log message: Build shared library version of the runtime as well --- Diffs of the changes: (+2 -1) Index: poolalloc/runtime/PoolAllocator/Makefile diff -u poolalloc/runtime/PoolAllocator/Makefile:1.3 poolalloc/runtime/PoolAllocator/Makefile:1.4 --- poolalloc/runtime/PoolAllocator/Makefile:1.3 Fri Oct 24 14:15:04 2003 +++ poolalloc/runtime/PoolAllocator/Makefile Mon Nov 3 15:13:58 2003 @@ -1,8 +1,9 @@ LEVEL = ../.. BYTECODE_LIBRARY=1 +SHARED_LIBRARY=1 LIBRARYNAME=poolalloc_rt include $(LEVEL)/Makefile.common # Always build optimized and debug versions -all:: $(LIBNAME_OBJO) $(LIBNAME_OBJG) \ No newline at end of file +all:: $(LIBNAME_OBJO) $(LIBNAME_OBJG) From lattner at cs.uiuc.edu Mon Nov 3 15:38:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Nov 3 15:38:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/CFrontend/2003-11-03-AddrArrayElement.c.tr Message-ID: <200311032137.PAA29381@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/CFrontend: 2003-11-03-AddrArrayElement.c.tr added (r1.1) --- Log message: New testcase for PR84 --- Diffs of the changes: (+11 -0) Index: llvm/test/Regression/CFrontend/2003-11-03-AddrArrayElement.c.tr diff -c /dev/null llvm/test/Regression/CFrontend/2003-11-03-AddrArrayElement.c.tr:1.1 *** /dev/null Mon Nov 3 15:37:18 2003 --- llvm/test/Regression/CFrontend/2003-11-03-AddrArrayElement.c.tr Mon Nov 3 15:37:08 2003 *************** *** 0 **** --- 1,11 ---- + // RUN: llvmgcc -xc %s -c -o - | llvm-dis | grep getelementptr + + // This should be turned into a tasty getelementptr instruction, not a nasty + // series of casts and address arithmetic. + + char Global[100]; + + char *test1(unsigned i) { + return &Global[i]; + } + From lattner at cs.uiuc.edu Mon Nov 3 18:43:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Nov 3 18:43:01 2003 Subject: [llvm-commits] CVS: poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp Message-ID: <200311040042.SAA00305@zion.cs.uiuc.edu> Changes in directory poolalloc/runtime/PoolAllocator: PoolAllocatorChained.cpp updated: 1.19 -> 1.20 --- Log message: Merge the two bitvectors together, reducing memory traffic --- Diffs of the changes: (+14 -17) Index: poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp diff -u poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp:1.19 poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp:1.20 --- poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp:1.19 Mon Nov 3 15:13:44 2003 +++ poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp Mon Nov 3 18:42:28 2003 @@ -52,38 +52,36 @@ // UsedEnd - 1 past the last allocated node in slab. 0 if slab is empty unsigned short UsedEnd; - // AllocatedBitVector - One bit is set for every node in this slab which has - // been allocated. - unsigned char AllocatedBitVector[NodesPerSlab/8]; - - // StartOfAllocation - A bit is set if this is the start of an allocation, - // either a unit allocation or an array. - unsigned char StartOfAllocation[NodesPerSlab/8]; + // NodeFlagsVector - This array contains two bits for each node in this pool + // slab. The first (low address) bit indicates whether this node has been + // allocated, and the second (next higher) bit indicates whether this is the + // start of an allocation. + unsigned char NodeFlagsVector[NodesPerSlab/4]; char Data[1]; // Buffer to hold data in this slab... VARIABLE SIZED bool isNodeAllocated(unsigned NodeNum) { - return AllocatedBitVector[NodeNum >> 3] & (1 << (NodeNum & 7)); + return NodeFlagsVector[NodeNum >> 2] & (1 << (NodeNum & 3)); } void markNodeAllocated(unsigned NodeNum) { - AllocatedBitVector[NodeNum >> 3] |= 1 << (NodeNum & 7); + NodeFlagsVector[NodeNum >> 2] |= 1 << (NodeNum & 3); + } + + void markNodeFree(unsigned NodeNum) { + NodeFlagsVector[NodeNum >> 2] &= ~(1 << (NodeNum & 3)); } void setStartBit(unsigned NodeNum) { - StartOfAllocation[NodeNum >> 3] |= 1 << (NodeNum & 7); + NodeFlagsVector[NodeNum >> 2] |= 1 << ((NodeNum & 3)+4); } bool isStartOfAllocation(unsigned NodeNum) { - return StartOfAllocation[NodeNum >> 3] & (1 << (NodeNum & 7)); + return NodeFlagsVector[NodeNum >> 2] & (1 << ((NodeNum & 3)+4)); } - void markNodeFree(unsigned NodeNum) { - AllocatedBitVector[NodeNum >> 3] &= ~(1 << (NodeNum & 7)); - } - void clearStartBit(unsigned NodeNum) { - StartOfAllocation[NodeNum >> 3] &= ~(1 << (NodeNum & 7)); + NodeFlagsVector[NodeNum >> 2] &= ~(1 << ((NodeNum & 3)+4)); } public: @@ -127,7 +125,6 @@ // freeElement - Free the single node, small array, or entire array indicated. void freeElement(unsigned ElementIdx); }; - // create - Create a new (empty) slab and add it to the end of the Pools list. PoolSlab *PoolSlab::create(PoolTy *Pool) { From lattner at cs.uiuc.edu Mon Nov 3 19:08:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Nov 3 19:08:02 2003 Subject: [llvm-commits] CVS: poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp Message-ID: <200311040107.TAA01699@zion.cs.uiuc.edu> Changes in directory poolalloc/runtime/PoolAllocator: PoolAllocatorChained.cpp updated: 1.20 -> 1.21 --- Log message: Various performance improvements by caching things in registers --- Diffs of the changes: (+21 -15) Index: poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp diff -u poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp:1.20 poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp:1.21 --- poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp:1.20 Mon Nov 3 18:42:28 2003 +++ poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp Mon Nov 3 19:06:50 2003 @@ -168,11 +168,12 @@ // Check to see if there are empty entries at the end of the slab... if (UsedEnd < NodesPerSlab) { // Mark the returned entry used - markNodeAllocated(UsedEnd); - setStartBit(UsedEnd); + unsigned short UE = UsedEnd; + markNodeAllocated(UE); + setStartBit(UE); // If we are allocating out the first unused field, bump its index also - if (FirstUnused == UsedEnd) + if (FirstUnused == UE) FirstUnused++; // Return the entry, increment UsedEnd field. @@ -185,15 +186,16 @@ if (FirstUnused < NodesPerSlab) { // Successfully allocate out the first unused node unsigned Idx = FirstUnused; - markNodeAllocated(Idx); setStartBit(Idx); // Increment FirstUnused to point to the new first unused value... // FIXME: this should be optimized + unsigned short FU = FirstUnused; do { - ++FirstUnused; - } while (FirstUnused != NodesPerSlab && isNodeAllocated(FirstUnused)); + ++FU; + } while (FU != NodesPerSlab && isNodeAllocated(FU)); + FirstUnused = FU; return Idx; } @@ -211,19 +213,20 @@ // end of the slab... if (UsedEnd+Size <= NodesPerSlab) { // Mark the returned entry used and set the start bit - setStartBit(UsedEnd); - for (unsigned i = UsedEnd; i != UsedEnd + Size; ++i) + unsigned UE = UsedEnd; + setStartBit(UE); + for (unsigned i = UE; i != UE+Size; ++i) markNodeAllocated(i); // If we are allocating out the first unused field, bump its index also - if (FirstUnused == UsedEnd) + if (FirstUnused == UE) FirstUnused += Size; // Increment UsedEnd UsedEnd += Size; // Return the entry - return UsedEnd - Size; + return UE; } // If not, check to see if this node has a declared "FirstUnused" value @@ -311,7 +314,9 @@ // FIXME: This should use manual strength reduction if GCC isn't producing // decent code (which is almost certainly isn't). - while (ElementEndIdx != UsedEnd && !isStartOfAllocation(ElementEndIdx) && + unsigned UE = UsedEnd; + while (ElementEndIdx != UE && + !isStartOfAllocation(ElementEndIdx) && isNodeAllocated(ElementEndIdx)) { markNodeFree(ElementEndIdx); ++ElementEndIdx; @@ -322,13 +327,14 @@ // If we are freeing the last element in a slab, shrink the UsedEnd marker // down to the last used node. - if (ElementEndIdx == UsedEnd) { - UsedEnd = ElementIdx; + if (ElementEndIdx == UE) { + UE = ElementIdx; do { - --UsedEnd; + --UE; // FIXME, this should scan the allocated array an entire byte at a time // for performance when skipping large empty blocks! - } while (UsedEnd && !isNodeAllocated(UsedEnd-1)); + } while (UE && !isNodeAllocated(UE-1)); + UsedEnd = UE; assert(FirstUnused <= UsedEnd && "FirstUnused field was out of date!"); From alkis at cs.uiuc.edu Tue Nov 4 01:58:01 2003 From: alkis at cs.uiuc.edu (Alkis Evlogimenos) Date: Tue Nov 4 01:58:01 2003 Subject: [llvm-commits] [regalloc_linearscan] CVS: llvm/include/llvm/CodeGen/LiveIntervals.h Message-ID: <200311040757.BAA25678@morpheus.cs.uiuc.edu> Changes in directory llvm/include/llvm/CodeGen: LiveIntervals.h updated: 1.1.2.3 -> 1.1.2.4 --- Log message: Change private member variable names to have a trailing rather than a leading underscore. --- Diffs of the changes: (+11 -10) Index: llvm/include/llvm/CodeGen/LiveIntervals.h diff -u llvm/include/llvm/CodeGen/LiveIntervals.h:1.1.2.3 llvm/include/llvm/CodeGen/LiveIntervals.h:1.1.2.4 --- llvm/include/llvm/CodeGen/LiveIntervals.h:1.1.2.3 Sun Oct 26 20:37:59 2003 +++ llvm/include/llvm/CodeGen/LiveIntervals.h Tue Nov 4 01:57:28 2003 @@ -97,27 +97,28 @@ }; private: - MachineFunction* _mf; - const TargetMachine* _tm; - const MRegisterInfo* _mri; - MachineBasicBlock* _currentMbb; - MachineBasicBlock::iterator _currentInstr; - LiveVariables* _lv; + MachineFunction* mf_; + const TargetMachine* tm_; + const MRegisterInfo* mri_; + MachineBasicBlock* currentMbb_; + MachineBasicBlock::iterator currentInstr_; + LiveVariables* lv_; typedef std::map Index2MbbMap; - Index2MbbMap _i2mbbMap; + Index2MbbMap i2mbbMap_; typedef std::map Mi2IndexMap; - Mi2IndexMap _mi2iMap; + Mi2IndexMap mi2iMap_; typedef std::vector Intervals; - Intervals _intervals; + Intervals intervals_; typedef std::map Reg2IntervalMap; - Reg2IntervalMap _r2iMap; + Reg2IntervalMap r2iMap_; public: virtual void getAnalysisUsage(AnalysisUsage &AU) const; + Intervals& getIntervals() { return intervals_; } private: /// runOnMachineFunction - pass entry point From alkis at cs.uiuc.edu Tue Nov 4 01:58:03 2003 From: alkis at cs.uiuc.edu (Alkis Evlogimenos) Date: Tue Nov 4 01:58:03 2003 Subject: [llvm-commits] [regalloc_linearscan] CVS: llvm/lib/CodeGen/LiveIntervals.cpp Message-ID: <200311040757.BAA25669@morpheus.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: LiveIntervals.cpp updated: 1.1.2.4 -> 1.1.2.5 --- Log message: Change private member variable names to have a trailing rather than a leading underscore. --- Diffs of the changes: (+24 -24) Index: llvm/lib/CodeGen/LiveIntervals.cpp diff -u llvm/lib/CodeGen/LiveIntervals.cpp:1.1.2.4 llvm/lib/CodeGen/LiveIntervals.cpp:1.1.2.5 --- llvm/lib/CodeGen/LiveIntervals.cpp:1.1.2.4 Sun Oct 26 20:37:58 2003 +++ llvm/lib/CodeGen/LiveIntervals.cpp Tue Nov 4 01:57:28 2003 @@ -53,24 +53,24 @@ /// bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) { DEBUG(std::cerr << "Machine Function\n"); - _mf = &fn; - _tm = &fn.getTarget(); - _mri = _tm->getRegisterInfo(); - _lv = &getAnalysis(); + mf_ = &fn; + tm_ = &fn.getTarget(); + mri_ = tm_->getRegisterInfo(); + lv_ = &getAnalysis(); // number MachineInstrs unsigned miIndex = 0; - for (MachineFunction::iterator mbb = _mf->begin(), mbbEnd = _mf->end(); + for (MachineFunction::iterator mbb = mf_->begin(), mbbEnd = mf_->end(); mbb != mbbEnd; ++mbb) { const std::pair& entry = - _lv->getMachineBasicBlockInfo(&*mbb); - bool inserted = _i2mbbMap.insert(std::make_pair(entry.second, + lv_->getMachineBasicBlockInfo(&*mbb); + bool inserted = i2mbbMap_.insert(std::make_pair(entry.second, entry.first)).second; assert(inserted && "multiple index -> MachineBasicBlock"); for (MachineBasicBlock::iterator mi = mbb->begin(), miEnd = mbb->end(); mi != miEnd; ++mi) { - inserted = _mi2iMap.insert(std::make_pair(*mi, miIndex++)).second; + inserted = mi2iMap_.insert(std::make_pair(*mi, miIndex++)).second; assert(inserted && "multiple MachineInstr -> index mappings"); } } @@ -94,35 +94,35 @@ MachineInstr* instr, unsigned reg) { - DEBUG(std::cerr << "\t\t\tregister: "; printRegName(_mri, reg)); + DEBUG(std::cerr << "\t\t\tregister: "; printRegName(mri_, reg)); unsigned start = getInstructionIndex(instr); - LiveVariables::VarInfo& vi = _lv->getVarInfo(reg); + LiveVariables::VarInfo& vi = lv_->getVarInfo(reg); - Reg2IntervalMap::iterator r2iit = _r2iMap.find(reg); - if (r2iit != _r2iMap.end()) { + Reg2IntervalMap::iterator r2iit = r2iMap_.find(reg); + if (r2iit != r2iMap_.end()) { unsigned ii = r2iit->second; - Interval& interval = _intervals[ii]; + Interval& interval = intervals_[ii]; unsigned end = getInstructionIndex(mbb->back()) + 1; interval.addRange(start, end); DEBUG(std::cerr << " -> " << interval << '\n'); } else { // add new interval - _intervals.push_back(Interval(reg)); - Interval& interval = _intervals.back(); + intervals_.push_back(Interval(reg)); + Interval& interval = intervals_.back(); // update interval index for this register - _r2iMap[reg] = _intervals.size() - 1; + r2iMap_[reg] = intervals_.size() - 1; - unsigned index = _lv->getMachineBasicBlockInfo(mbb).second; + unsigned index = lv_->getMachineBasicBlockInfo(mbb).second; if (index < vi.AliveBlocks.size() && vi.AliveBlocks[index]) { unsigned end = getInstructionIndex(mbb->back()) + 1; interval.addRange(start, end); } for (Index2MbbMap::iterator - it = _i2mbbMap.begin(), itEnd = _i2mbbMap.end(); + it = i2mbbMap_.begin(), itEnd = i2mbbMap_.end(); it != itEnd; ++it) { unsigned mbbIndex = it->first; MachineBasicBlock* mbb2 = it->second; @@ -145,9 +145,9 @@ unsigned LiveIntervals::getInstructionIndex(MachineInstr* instr) { - assert(_mi2iMap.find(instr) != _mi2iMap.end() && + assert(mi2iMap_.find(instr) != mi2iMap_.end() && "instruction not assigned a number"); - return _mi2iMap.find(instr)->second; + return mi2iMap_.find(instr)->second; } /// computeIntervals - computes the live intervals for virtual @@ -158,7 +158,7 @@ { DEBUG(std::cerr << "computing live intervals:\n"); - for (Index2MbbMap::iterator it = _i2mbbMap.begin(), itEnd = _i2mbbMap.end(); + for (Index2MbbMap::iterator it = i2mbbMap_.begin(), itEnd = i2mbbMap_.end(); it != itEnd; ++it) { MachineBasicBlock* mbb = it->second; DEBUG(std::cerr << "machine basic block: " @@ -167,9 +167,9 @@ mi != miEnd; ++mi) { MachineInstr* instr = *mi; const TargetInstrDescriptor& tid = - _tm->getInstrInfo().get(instr->getOpcode()); + tm_->getInstrInfo().get(instr->getOpcode()); DEBUG(std::cerr << "\t\tinstruction[" - << _mi2iMap.find(instr)->second << "]: " + << mi2iMap_.find(instr)->second << "]: " << *instr << '\n'); for (int i = instr->getNumOperands() - 1; i >= 0; --i) { @@ -187,6 +187,6 @@ } } - DEBUG(std::copy(_intervals.begin(), _intervals.end(), + DEBUG(std::copy(intervals_.begin(), intervals_.end(), std::ostream_iterator(std::cerr, "\n"))); } From alkis at cs.uiuc.edu Tue Nov 4 02:05:01 2003 From: alkis at cs.uiuc.edu (Alkis Evlogimenos) Date: Tue Nov 4 02:05:01 2003 Subject: [llvm-commits] [regalloc_linearscan] CVS: llvm/include/llvm/CodeGen/LiveIntervals.h Message-ID: <200311040804.CAA25739@morpheus.cs.uiuc.edu> Changes in directory llvm/include/llvm/CodeGen: LiveIntervals.h updated: 1.1.2.4 -> 1.1.2.5 --- Log message: Made Intervals typedef public. --- Diffs of the changes: (+2 -1) Index: llvm/include/llvm/CodeGen/LiveIntervals.h diff -u llvm/include/llvm/CodeGen/LiveIntervals.h:1.1.2.4 llvm/include/llvm/CodeGen/LiveIntervals.h:1.1.2.5 --- llvm/include/llvm/CodeGen/LiveIntervals.h:1.1.2.4 Tue Nov 4 01:57:28 2003 +++ llvm/include/llvm/CodeGen/LiveIntervals.h Tue Nov 4 02:04:39 2003 @@ -96,6 +96,8 @@ } }; + typedef std::vector Intervals; + private: MachineFunction* mf_; const TargetMachine* tm_; @@ -110,7 +112,6 @@ typedef std::map Mi2IndexMap; Mi2IndexMap mi2iMap_; - typedef std::vector Intervals; Intervals intervals_; typedef std::map Reg2IntervalMap; From lattner at cs.uiuc.edu Tue Nov 4 10:05:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Nov 4 10:05:03 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/Printer.cpp Message-ID: <200311041604.KAA13352@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: Printer.cpp updated: 1.70 -> 1.71 --- Log message: Fix problems in previous changes. This fixes several regressions last night. --- Diffs of the changes: (+6 -5) Index: llvm/lib/Target/X86/Printer.cpp diff -u llvm/lib/Target/X86/Printer.cpp:1.70 llvm/lib/Target/X86/Printer.cpp:1.71 --- llvm/lib/Target/X86/Printer.cpp:1.70 Mon Nov 3 14:19:49 2003 +++ llvm/lib/Target/X86/Printer.cpp Tue Nov 4 10:04:32 2003 @@ -164,7 +164,7 @@ else if (const ConstantPointerRef *CPR = dyn_cast(CV)) // This is a constant address for a global variable or function. Use the // name of the variable or function as the address value. - O << Mang->getValueName(CPR->getValue()) << "\n"; + O << Mang->getValueName(CPR->getValue()); else if (const ConstantExpr *CE = dyn_cast(CV)) { const TargetData &TD = TM.getTargetData(); switch(CE->getOpcode()) { @@ -175,7 +175,7 @@ if (unsigned Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec)) { O << "("; emitConstantValueOnly(ptrVal); - O << ") + " + Offset; + O << ") + " << Offset; } else { emitConstantValueOnly(ptrVal); } @@ -187,12 +187,13 @@ // complete check. Constant *Op = CE->getOperand(0); const Type *OpTy = Op->getType(), *Ty = CE->getType(); + assert(((isa(OpTy) && (Ty == Type::LongTy || Ty == Type::ULongTy)) || (isa(Ty) - && (OpTy == Type::LongTy || OpTy == Type::ULongTy))) - || (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy)) - && (OpTy->isLosslesslyConvertibleTo(Ty)))) + && (OpTy == Type::LongTy || OpTy == Type::ULongTy)) + || (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy)) + && OpTy->isLosslesslyConvertibleTo(Ty)))) && "FIXME: Don't yet support this kind of constant cast expr"); O << "("; emitConstantValueOnly(Op); From lattner at cs.uiuc.edu Tue Nov 4 10:41:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Nov 4 10:41:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/BasicAA/2003-11-04-SimpleCases.ll Message-ID: <200311041640.KAA05583@neo.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/BasicAA: 2003-11-04-SimpleCases.ll added (r1.1) --- Log message: While working on the pool allocator, I noticed that basicaa is failing a scary number of simple cases. Someday when I get a chance to work on it again, this testcase should be corrected. --- Diffs of the changes: (+15 -0) Index: llvm/test/Regression/Transforms/BasicAA/2003-11-04-SimpleCases.ll diff -c /dev/null llvm/test/Regression/Transforms/BasicAA/2003-11-04-SimpleCases.ll:1.1 *** /dev/null Tue Nov 4 10:40:51 2003 --- llvm/test/Regression/Transforms/BasicAA/2003-11-04-SimpleCases.ll Tue Nov 4 10:40:40 2003 *************** *** 0 **** --- 1,15 ---- + ; This testcase consists of alias relations which should be completely + ; resolvable by basicaa. + + ; RUN: llvm-as < %s | opt -aa-eval -print-may-aliases 2>&1 -disable-output | not grep May: + + %T = type { uint, [10 x ubyte] } + + void %test(%T* %P) { + %A = getelementptr %T* %P, long 0 + %B = getelementptr %T* %P, long 0, ubyte 0 + %C = getelementptr %T* %P, long 0, ubyte 1 + %D = getelementptr %T* %P, long 0, ubyte 1, long 0 + %E = getelementptr %T* %P, long 0, ubyte 1, long 5 + ret void + } From lattner at cs.uiuc.edu Tue Nov 4 11:26:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Nov 4 11:26:01 2003 Subject: [llvm-commits] CVS: poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp Message-ID: <200311041725.LAA17565@zion.cs.uiuc.edu> Changes in directory poolalloc/runtime/PoolAllocator: PoolAllocatorChained.cpp updated: 1.21 -> 1.22 --- Log message: Hide the NodesPerSlab implementation detail --- Diffs of the changes: (+21 -12) Index: poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp diff -u poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp:1.21 poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp:1.22 --- poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp:1.21 Mon Nov 3 19:06:50 2003 +++ poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp Tue Nov 4 11:25:01 2003 @@ -92,6 +92,15 @@ // entries in it, returning the pointer into the pool directly. static void *createSingleArray(PoolTy *Pool, unsigned NumNodes); + // getSlabSize - Return the number of nodes that each slab should contain. + static unsigned getSlabSize(PoolTy *Pool) { + return NodesPerSlab; + } + + unsigned getSlabSize() const { + return NodesPerSlab; + } + // destroy - Release the memory for the current object. void destroy() { free(this); @@ -103,7 +112,7 @@ // isFull - This is a quick check to see if the slab is completely allocated. // - bool isFull() const { return isSingleArray || FirstUnused == NodesPerSlab; } + bool isFull() const { return isSingleArray || FirstUnused == getSlabSize(); } // allocateSingle - Allocate a single element from this pool, returning -1 if // there is no space. @@ -129,7 +138,7 @@ // create - Create a new (empty) slab and add it to the end of the Pools list. PoolSlab *PoolSlab::create(PoolTy *Pool) { PoolSlab *PS = (PoolSlab*)malloc(sizeof(PoolSlab) + - Pool->NodeSize*NodesPerSlab-1); + Pool->NodeSize*getSlabSize(Pool)-1); assert(PS && "poolalloc: Could not allocate memory!"); PS->isSingleArray = 0; // Not a single array! @@ -145,7 +154,7 @@ void *PoolSlab::createSingleArray(PoolTy *Pool, unsigned NumNodes) { PoolSlab *PS = (PoolSlab*)malloc(sizeof(PoolSlab) + Pool->NodeSize*NumNodes-1); - assert(NumNodes > NodesPerSlab && "No need to create a single array!"); + assert(NumNodes > getSlabSize(Pool) && "No need to create a single array!"); assert(PS && "poolalloc: Could not allocate memory!"); PS->isSingleArray = 1; // Not a single array! @@ -166,7 +175,7 @@ if (isSingleArray) return -1; // Check to see if there are empty entries at the end of the slab... - if (UsedEnd < NodesPerSlab) { + if (UsedEnd < getSlabSize()) { // Mark the returned entry used unsigned short UE = UsedEnd; markNodeAllocated(UE); @@ -183,7 +192,7 @@ // If not, check to see if this node has a declared "FirstUnused" value that // is less than the number of nodes allocated... // - if (FirstUnused < NodesPerSlab) { + if (FirstUnused < getSlabSize()) { // Successfully allocate out the first unused node unsigned Idx = FirstUnused; markNodeAllocated(Idx); @@ -194,7 +203,7 @@ unsigned short FU = FirstUnused; do { ++FU; - } while (FU != NodesPerSlab && isNodeAllocated(FU)); + } while (FU != getSlabSize() && isNodeAllocated(FU)); FirstUnused = FU; return Idx; @@ -211,7 +220,7 @@ // For small array allocation, check to see if there are empty entries at the // end of the slab... - if (UsedEnd+Size <= NodesPerSlab) { + if (UsedEnd+Size <= getSlabSize()) { // Mark the returned entry used and set the start bit unsigned UE = UsedEnd; setStartBit(UE); @@ -233,7 +242,7 @@ // starting which Size nodes can be allocated // unsigned Idx = FirstUnused; - while (Idx+Size <= NodesPerSlab) { + while (Idx+Size <= getSlabSize()) { assert(!isNodeAllocated(Idx) && "FirstUsed is not accurate!"); // Check if there is a continuous array of Size nodes starting FirstUnused @@ -262,7 +271,7 @@ // Otherwise, try later in the pool. Find the next unused entry. Idx = LastUnused; - while (Idx+Size <= NodesPerSlab && isNodeAllocated(Idx)) + while (Idx+Size <= getSlabSize() && isNodeAllocated(Idx)) ++Idx; } @@ -273,14 +282,14 @@ // containsElement - Return the element number of the specified address in // this slab. If the address is not in slab, return -1. int PoolSlab::containsElement(void *Ptr, unsigned ElementSize) const { - if (&Data[0] > Ptr || &Data[ElementSize*NodesPerSlab-1] < Ptr) + if (&Data[0] > Ptr || &Data[ElementSize*getSlabSize()-1] < Ptr) return -1; unsigned Index = (char*)Ptr-(char*)&Data[0]; assert(Index % ElementSize == 0 && "Freeing pointer into the middle of an element!"); Index /= ElementSize; - assert(Index < PoolSlab::NodesPerSlab && "Pool slab searching loop broken!"); + assert(Index < getSlabSize() && "Pool slab searching loop broken!"); return Index; } @@ -419,7 +428,7 @@ void *poolallocarray(PoolTy* Pool, unsigned Size) { assert(Pool && "Null pool pointer passed into poolallocarray!\n"); - if (Size > PoolSlab::NodesPerSlab) + if (Size > PoolSlab::getSlabSize(Pool)) return PoolSlab::createSingleArray(Pool, Size); PoolSlab *PS = (PoolSlab*)Pool->Ptr1; From gaeke at cs.uiuc.edu Tue Nov 4 12:27:01 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Tue Nov 4 12:27:01 2003 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp Message-ID: <200311041826.MAA08463@gally.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: UnpackTraceFunction.cpp updated: 1.9 -> 1.10 --- Log message: Add comments. Flesh out insertCopyMachineInstrs() a little bit. Rename OperandAllocStateTuple to OperandAllocState, to match the others. Implement getValueAllocStateFromModule in terms of three new stub functions. --- Diffs of the changes: (+36 -20) Index: reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp diff -u reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.9 reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.10 --- reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.9 Mon Nov 3 01:03:30 2003 +++ reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp Tue Nov 4 12:26:06 2003 @@ -21,22 +21,21 @@ /// copies the value in Source to the location specified by Target, at /// the beginning of B. /// +/// FIXME: Not yet finished +/// void insertCopyMachineInstrs (AllocInfo &Source, AllocInfo &Target, MachineBasicBlock &B) { - // FIXME: not yet implemented -#if 0 - if (Source is memory && Target is register) { - Insert load instruction from stack loc. Source into register Target - } else if (Source is register && Target is register) { - Insert move instruction from register Source to register Target - } else if (Source is register && Target is memory) { - Insert store instruction from register Source to stack loc. Target - } else if (Source is memory && Target is memory) { - Get a temporary register somehow - Insert load instruction from stack loc. Source into register Temp - Insert store instruction from register Temp to stack loc. Target + if (Source.AllocState == Spilled && Target.AllocState == Allocated) { + //Insert load instruction from stack loc. Source into register Target + } else if (Source.AllocState == Allocated && Target.AllocState == Allocated) { + //Insert move instruction from register Source to register Target + } else if (Source.AllocState == Allocated && Target.AllocState == Spilled) { + //Insert store instruction from register Source to stack loc. Target + } else if (Source.AllocState == Spilled && Target.AllocState == Spilled) { + //Get a temporary register Temp somehow + //Insert load instruction from stack loc. Source into register Temp + //Insert store instruction from register Temp to stack loc. Target } -#endif } /// Emit the same sequence of MachineInstrs that @@ -103,7 +102,7 @@ } extern "C" { - struct OperandAllocStateTuple { + struct OperandAllocState { unsigned Instruction; unsigned Operand; unsigned AllocState; @@ -112,12 +111,12 @@ struct FunctionAllocState { unsigned numTuples; - struct OperandAllocStateTuple tuples[0]; + struct OperandAllocState tuples[0]; }; struct ModuleAllocState { unsigned numFunctions; - struct FunctionAllocStateTuple *functions[0]; + struct FunctionAllocState *functions[0]; }; /// This global is filled in by PhyRegAlloc's -save-ra-state option: @@ -127,15 +126,32 @@ extern PhyRegAlloc::SavedStateMapTy ExportedFnAllocState; +unsigned getSavedStateIndexOfFunction (Function *F) { +} + +unsigned getSavedStateIndexOfInstruction (Function *F, Value *V) { +} + +unsigned getSavedStateIndexOfOperandInInstruction (Function *F, Value *V, + unsigned VI) { +} + /// Get the register number or stack position where V can be found in the /// machine code for the function F. /// AllocInfo getValueAllocStateFromModule (Function *F, Value *V) { - - // figure out the index I of F in _llvm_regAllocState - - // reconstruct the AllocInfo for V by looking at F's state, which is + // Figure out the indices of the in _llvm_regAllocState + unsigned FI = getSavedStateIndexOfFunction (F); + unsigned VI = getSavedStateIndexOfInstruction (F, V); + unsigned VO = getSavedStateIndexOfOperandInInstruction (F, V, VI); + // Reconstruct the AllocInfo for V by looking at F's state, which is // in _llvm_regAllocState.functions[I] + FunctionAllocState &FAllocState = _llvm_regAllocState.functions[FI]; + for (unsigned i = 0; i < FAllocState.numTuples; ++i) { + OperandAllocState &T = FAllocState.tuples[VI]; + if (T.Instruction == VI && T.Operand == VO) + return AllocInfo (T.Instruction, T.Operand, T.AllocState, T.Placement); + } } /// Get the register number or stack position where V can be found in the From gaeke at cs.uiuc.edu Tue Nov 4 12:27:04 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Tue Nov 4 12:27:04 2003 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp Message-ID: <200311041826.MAA08444@gally.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/RegAlloc: PhyRegAlloc.cpp updated: 1.125 -> 1.126 --- Log message: Add comments. --- Diffs of the changes: (+4 -0) Index: llvm/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp diff -u llvm/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp:1.125 llvm/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp:1.126 --- llvm/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp:1.125 Thu Oct 30 15:21:33 2003 +++ llvm/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp Tue Nov 4 12:25:56 2003 @@ -1204,6 +1204,7 @@ } } + /// Finish the job of saveState(), by collapsing FnAllocState into an LLVM /// Constant and stuffing it inside the Module. (NOTE: Soon, there will be /// other, better ways of storing the saved state; this one is cumbersome and @@ -1213,8 +1214,11 @@ if (!SaveRegAllocState) return false; // Nothing to do here, unless we're saving state. + // If saving state into the module, just copy new elements to the + // correct global. if (!SaveStateToModule) { ExportedFnAllocState = FnAllocState; + // FIXME: should ONLY copy new elements in FnAllocState return false; } From lattner at cs.uiuc.edu Tue Nov 4 12:35:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Nov 4 12:35:03 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/CFrontend/2003-11-04-OutOfMemory.c Message-ID: <200311041834.MAA31656@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/CFrontend: 2003-11-04-OutOfMemory.c added (r1.1) --- Log message: New testcase --- Diffs of the changes: (+7 -0) Index: llvm/test/Regression/CFrontend/2003-11-04-OutOfMemory.c diff -c /dev/null llvm/test/Regression/CFrontend/2003-11-04-OutOfMemory.c:1.1 *** /dev/null Tue Nov 4 12:34:15 2003 --- llvm/test/Regression/CFrontend/2003-11-04-OutOfMemory.c Tue Nov 4 12:34:05 2003 *************** *** 0 **** --- 1,7 ---- + void schedule_timeout(signed long timeout) + { + switch (timeout) + { + case ((long)(~0UL>>1)): break; + } + } From lattner at cs.uiuc.edu Tue Nov 4 12:53:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Nov 4 12:53:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/CFrontend/2003-11-04-EmptyStruct.c Message-ID: <200311041852.MAA00698@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/CFrontend: 2003-11-04-EmptyStruct.c added (r1.1) --- Log message: New testcase for PR80 --- Diffs of the changes: (+5 -0) Index: llvm/test/Regression/CFrontend/2003-11-04-EmptyStruct.c diff -c /dev/null llvm/test/Regression/CFrontend/2003-11-04-EmptyStruct.c:1.1 *** /dev/null Tue Nov 4 12:52:11 2003 --- llvm/test/Regression/CFrontend/2003-11-04-EmptyStruct.c Tue Nov 4 12:52:01 2003 *************** *** 0 **** --- 1,5 ---- + typedef struct { } rwlock_t; + struct fs_struct { rwlock_t lock; int umask; }; + void __copy_fs_struct(struct fs_struct *fs) { fs->lock = (rwlock_t) { }; } + + From lattner at cs.uiuc.edu Tue Nov 4 14:07:05 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Nov 4 14:07:05 2003 Subject: [llvm-commits] CVS: llvm/docs/ReleaseNotes.html Message-ID: <200311042007.OAA18326@zion.cs.uiuc.edu> Changes in directory llvm/docs: ReleaseNotes.html updated: 1.29 -> 1.30 --- Log message: Substantial release notes updates --- Diffs of the changes: (+17 -6) Index: llvm/docs/ReleaseNotes.html diff -u llvm/docs/ReleaseNotes.html:1.29 llvm/docs/ReleaseNotes.html:1.30 --- llvm/docs/ReleaseNotes.html:1.29 Mon Nov 3 14:08:08 2003 +++ llvm/docs/ReleaseNotes.html Tue Nov 4 14:06:53 2003 @@ -97,6 +97,7 @@

    • C front-end crash on empty structure
    • CFrontend crashes when compiling C99 compound expressions
    • [X86] Emission of global bool initializers broken
    • +
    • llvm-gcc infinite loops on "case MAXINT:"
    • At this time, LLVM is known to work properly with SPEC CPU 2000, the Olden @@ -150,7 +151,13 @@

    • It is not possible to dlopen an LLVM bytecode file in the JIT.

    • Linking in static archive files (.a files) is very slow (there is no symbol -table in the archive). +table in the archive).

      + +

    • Interpreter does not support invoke +or unwind.

      + +

    • LLVM cannot handle structures with +more than 256 elements.


    Known problems with the C front-end

      @@ -356,13 +363,17 @@
    • Initializers for global variables cannot include special floating point numbers like Not-A-Number or Infinity.

      -

    • Zero arg vararg functions are not +
    • Zero arg vararg functions are not supported. This should not affect LLVM produced by the C or C++ frontends.

      -

    • The code produces by the C back-end has only been tested with the Sun CC and -GCC compilers. It is possible that it will have to be adjusted to support other -C compilers.

      +

    • Variables in scope of output setjmp +calls should be volatile. Note that this does not effect correctness on +many platforms.

      + +

    • The code produces by the C back-end has only been tested with the Sun CC, +GCC, and Intel compilers. It is possible that it will have to be adjusted to +support other C compilers.

      @@ -393,6 +404,6 @@ Maintained By: The LLVM Team
      -Last modified: Mon Nov 3 14:07:07 CST 2003 +Last modified: Tue Nov 4 14:05:01 CST 2003 From lattner at cs.uiuc.edu Tue Nov 4 14:08:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Nov 4 14:08:01 2003 Subject: [llvm-commits] CVS: llvm-www/releases/1.0/docs/ReleaseNotes.html Message-ID: <200311042007.OAA18444@zion.cs.uiuc.edu> Changes in directory llvm-www/releases/1.0/docs: ReleaseNotes.html updated: 1.18 -> 1.19 --- Log message: Substantial updates --- Diffs of the changes: (+19 -2) Index: llvm-www/releases/1.0/docs/ReleaseNotes.html diff -u llvm-www/releases/1.0/docs/ReleaseNotes.html:1.18 llvm-www/releases/1.0/docs/ReleaseNotes.html:1.19 --- llvm-www/releases/1.0/docs/ReleaseNotes.html:1.18 Mon Nov 3 14:08:22 2003 +++ llvm-www/releases/1.0/docs/ReleaseNotes.html Tue Nov 4 14:07:03 2003 @@ -157,6 +157,13 @@

    • Linking in static archive files (.a files) is very slow (there is no symbol table in the archive).

      +

    • Interpreter does not support invoke +or unwind.

      + +

    • LLVM cannot handle structures with +more than 256 elements.

      + +

    Bugs in 1.0 fixed in 1.1:Bugs:Bugs in 1.0 fixed in 1.1:Bugs in 1.0 fixed in 1.1:


    Known problems with the C front-end

    Bugs in 1.0 fixed in 1.1:Bugs in 1.0 fixed in 1.1:Notes:

    • Inline assembly is not yet supported.

      @@ -345,10 +345,13 @@

    • The C++ front-end inherits all problems afflicting the C front-end

      +

    Bugs in 1.0 fixed in 1.1:Notes:Bugs in 1.0 fixed in 1.1:


    Known problems with the Sparc back-end

    Bugs in 1.0 fixed in 1.1:

      + +

    • C backend fails on constant cast expr +to ptr-to-anonymous struct
    • @@ -453,6 +459,6 @@ Maintained By: The LLVM Team
      -Last modified: Tue Nov 4 14:06:04 CST 2003 +Last modified: Tue Nov 4 14:10:15 CST 2003 From lattner at cs.uiuc.edu Tue Nov 4 14:27:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Nov 4 14:27:03 2003 Subject: [llvm-commits] CVS: poolalloc/runtime/PoolAllocator/PageManager.cpp PageManager.h Message-ID: <200311042026.OAA19791@zion.cs.uiuc.edu> Changes in directory poolalloc/runtime/PoolAllocator: PageManager.cpp added (r1.1) PageManager.h added (r1.1) --- Log message: Simple implementation of a manager for pages allocated with mmap --- Diffs of the changes: (+94 -0) Index: poolalloc/runtime/PoolAllocator/PageManager.cpp diff -c /dev/null poolalloc/runtime/PoolAllocator/PageManager.cpp:1.1 *** /dev/null Tue Nov 4 14:26:19 2003 --- poolalloc/runtime/PoolAllocator/PageManager.cpp Tue Nov 4 14:26:09 2003 *************** *** 0 **** --- 1,64 ---- + //===- PageManager.cpp - Implementation of the page allocator -------------===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by the LLVM research group and is distributed under + // the University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + // + // This file implements the PageManager.h interface. + // + //===----------------------------------------------------------------------===// + + #include "PageManager.h" + #ifndef _POSIX_MAPPED_FILES + #define _POSIX_MAPPED_FILES + #endif + #include "Config/unistd.h" + #include "Config/sys/mman.h" + #include + + static unsigned PageSize; + + + /// getPageSize - Return the size of the unit of memory allocated by + /// AllocatePage. This is a value that is typically several kilobytes in size. + unsigned getPageSize() { + if (!PageSize) PageSize = sysconf(_SC_PAGESIZE); + return PageSize; + } + + /// AllocatePage - This function returns a chunk of memory with size and + /// alignment specified by getPageSize(). + void *AllocatePage() { + #if defined(i386) || defined(__i386__) || defined(__x86__) + /* Linux and *BSD tend to have these flags named differently. */ + #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) + # define MAP_ANONYMOUS MAP_ANON + #endif /* defined(MAP_ANON) && !defined(MAP_ANONYMOUS) */ + #elif defined(sparc) || defined(__sparc__) || defined(__sparcv9) + /* nothing */ + #else + std::cerr << "This architecture is not supported by the pool allocator!\n"; + abort(); + #endif + + #if defined(__linux__) + #define fd 0 + #else + #define fd -1 + #endif + + void *pa = mmap(0, getPageSize(), PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_PRIVATE|MAP_ANONYMOUS, fd, 0); + assert(pa != MAP_FAILED && "MMAP FAILED!"); + return pa; + } + + + /// FreePage - This function returns the specified page to the pagemanager for + /// future allocation. + void FreePage(void *Page) { + munmap(Page, 1); + } Index: poolalloc/runtime/PoolAllocator/PageManager.h diff -c /dev/null poolalloc/runtime/PoolAllocator/PageManager.h:1.1 *** /dev/null Tue Nov 4 14:26:19 2003 --- poolalloc/runtime/PoolAllocator/PageManager.h Tue Nov 4 14:26:09 2003 *************** *** 0 **** --- 1,30 ---- + //===- PageManager.h - Allocates memory on page boundaries ------*- C++ -*-===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by the LLVM research group and is distributed under + // the University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + // + // This file defines the interface used by the pool allocator to allocate memory + // on large alignment boundaries. + // + //===----------------------------------------------------------------------===// + + #ifndef PAGEMANAGER_H + #define PAGEMANAGER_H + + /// getPageSize - Return the size of the unit of memory allocated by + /// AllocatePage. This is a value that is typically several kilobytes in size. + unsigned getPageSize(); + + /// AllocatePage - This function returns a chunk of memory with size and + /// alignment specified by getPageSize(). + void *AllocatePage(); + + /// FreePage - This function returns the specified page to the pagemanager for + /// future allocation. + void FreePage(void *Page); + + #endif From gaeke at cs.uiuc.edu Tue Nov 4 16:12:02 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Tue Nov 4 16:12:02 2003 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp Message-ID: <200311042211.QAA29469@seraph.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: UnpackTraceFunction.cpp updated: 1.10 -> 1.11 --- Log message: Fix some compilation errors in the stubby insertCopyMachineInstrs(). Fill in the rest of getValueAllocStateFromModule() and getValueAllocStateFromGlobal(), and update their comments. --- Diffs of the changes: (+46 -18) Index: reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp diff -u reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.10 reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.11 --- reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.10 Tue Nov 4 12:26:06 2003 +++ reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp Tue Nov 4 16:11:41 2003 @@ -25,13 +25,13 @@ /// void insertCopyMachineInstrs (AllocInfo &Source, AllocInfo &Target, MachineBasicBlock &B) { - if (Source.AllocState == Spilled && Target.AllocState == Allocated) { + if (Source.AllocState == AllocInfo::Spilled && Target.AllocState == AllocInfo::Allocated) { //Insert load instruction from stack loc. Source into register Target - } else if (Source.AllocState == Allocated && Target.AllocState == Allocated) { + } else if (Source.AllocState == AllocInfo::Allocated && Target.AllocState == AllocInfo::Allocated) { //Insert move instruction from register Source to register Target - } else if (Source.AllocState == Allocated && Target.AllocState == Spilled) { + } else if (Source.AllocState == AllocInfo::Allocated && Target.AllocState == AllocInfo::Spilled) { //Insert store instruction from register Source to stack loc. Target - } else if (Source.AllocState == Spilled && Target.AllocState == Spilled) { + } else if (Source.AllocState == AllocInfo::Spilled && Target.AllocState == AllocInfo::Spilled) { //Get a temporary register Temp somehow //Insert load instruction from stack loc. Source into register Temp //Insert store instruction from register Temp to stack loc. Target @@ -136,32 +136,60 @@ unsigned VI) { } -/// Get the register number or stack position where V can be found in the -/// machine code for the function F. +/// Returns the register number or stack position where V can be found in the +/// machine code for the function F, which it finds by searching the global +/// variable _llvm_regAllocState written out by PhyRegAlloc.cpp during a +/// previous invocation of llc. /// AllocInfo getValueAllocStateFromModule (Function *F, Value *V) { - // Figure out the indices of the in _llvm_regAllocState + // Figure out the indices (FI, VI, VO) that can be used to look up V, which + // is an operand of some instruction in F, in _llvm_regAllocState: unsigned FI = getSavedStateIndexOfFunction (F); unsigned VI = getSavedStateIndexOfInstruction (F, V); unsigned VO = getSavedStateIndexOfOperandInInstruction (F, V, VI); - // Reconstruct the AllocInfo for V by looking at F's state, which is - // in _llvm_regAllocState.functions[I] - FunctionAllocState &FAllocState = _llvm_regAllocState.functions[FI]; - for (unsigned i = 0; i < FAllocState.numTuples; ++i) { - OperandAllocState &T = FAllocState.tuples[VI]; + // Reconstruct the AllocInfo for V by searching + // _llvm_regAllocState.functions[FI] for a tuple that starts with + // (VI, VO, ...): + FunctionAllocState *FAllocState = _llvm_regAllocState.functions[FI]; + for (unsigned i = 0; i < FAllocState->numTuples; ++i) { + OperandAllocState &T = FAllocState->tuples[VI]; if (T.Instruction == VI && T.Operand == VO) - return AllocInfo (T.Instruction, T.Operand, T.AllocState, T.Placement); + return AllocInfo (T.Instruction, T.Operand, + (AllocInfo::AllocStateTy) T.AllocState, + T.Placement); } + // By this time we had better have found it, otherwise we are about to do bad + // things. + std::cerr << "ERROR: UnpackTraceFunction: No saved AllocInfo found for " + << F->getName () << "()'s value " << *V + << " in getValueAllocStateFromModule()\n"; + abort (); } -/// Get the register number or stack position where V can be found in the -/// machine code for the function F. +/// Returns the register number or stack position where V can be found in the +/// machine code for the function F, which it finds by searching the global +/// variable ExportedFnAllocState exported by PhyRegAlloc.cpp. /// AllocInfo getValueAllocStateFromGlobal (Function *F, Value *V) { - // get the saved PhyRegAlloc state for F out of ExportedFnAllocState + // Get the saved PhyRegAlloc state for F out of ExportedFnAllocState: std::vector &FState = ExportedFnAllocState[F]; - - // get the AllocInfo for V from the saved PhyRegAlloc state for F + // Figure out the indices (VI, VO) that can be used to look up V, which is an + // operand of some instruction in F, in FState: + unsigned VI = getSavedStateIndexOfInstruction (F, V); + unsigned VO = getSavedStateIndexOfOperandInInstruction (F, V, VI); + // Retrieve the AllocInfo for V by searching FState for a tuple that starts + // with (VI, VO, ...): + for (unsigned i = 0, s = FState.size (); i < s; ++i) { + AllocInfo &T = FState[i]; + if (T.Instruction == VI && T.Operand == VO) + return T; + } + // By this time we had better have found it, otherwise we are about to do bad + // things. + std::cerr << "ERROR: UnpackTraceFunction: No saved AllocInfo found for " + << F->getName () << "()'s value " << *V + << " in getValueAllocStateFromGlobal()\n"; + abort (); } /// Returns a pointer to the return instruction in B, if B contains one, From lattner at cs.uiuc.edu Tue Nov 4 16:39:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Nov 4 16:39:01 2003 Subject: [llvm-commits] CVS: llvm/include/Support/MallocAllocator.h Message-ID: <200311042238.QAA09524@zion.cs.uiuc.edu> Changes in directory llvm/include/Support: MallocAllocator.h added (r1.1) --- Log message: New file, for use by the pool allocator project --- Diffs of the changes: (+68 -0) Index: llvm/include/Support/MallocAllocator.h diff -c /dev/null llvm/include/Support/MallocAllocator.h:1.1 *** /dev/null Tue Nov 4 16:38:38 2003 --- llvm/include/Support/MallocAllocator.h Tue Nov 4 16:38:28 2003 *************** *** 0 **** --- 1,68 ---- + //===-- Support/MallocAllocator.h - Allocator using malloc/free -*- C++ -*-===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by the LLVM research group and is distributed under + // the University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + // + // This file defines MallocAllocator class, an STL compatible allocator which + // just uses malloc/free to get and release memory. The default allocator uses + // the STL pool allocator runtime library, this explicitly avoids it. + // + // This file is used for variety of purposes, including the pool allocator + // project and testing, regardless of whether or not it's used directly in the + // LLVM code, so don't delete this from CVS if you think it's unused! + // + //===----------------------------------------------------------------------===// + + #ifndef SUPPORT_MALLOCALLOCATOR_H + #define SUPPORT_MALLOCALLOCATOR_H + + #include + #include + + template + struct MallocAllocator { + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; + template struct rebind { + typedef MallocAllocator other; + }; + + pointer address(reference x) const { return &x; } + const_pointer address(const_reference x) const { return &x; } + size_type max_size() const { return ~0 / sizeof(T); } + + pointer allocate(size_t n, void* hint = 0) { + return (pointer)malloc(n*sizeof(T)); + } + + void deallocate(pointer p, size_t n) { + free((void*)p); + } + + void construct(pointer p, const T &val) { + new((void*)p) T(val); + } + void destroy(pointer p) { + p->~T(); + } + }; + + template + inline bool operator==(const MallocAllocator &, const MallocAllocator &) { + return true; + } + template + inline bool operator!=(const MallocAllocator&, const MallocAllocator&) { + return false; + } + + #endif From gaeke at cs.uiuc.edu Tue Nov 4 16:41:00 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Tue Nov 4 16:41:00 2003 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp Message-ID: <200311042240.QAA00100@seraph.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: UnpackTraceFunction.cpp updated: 1.11 -> 1.12 --- Log message: Update another comment in insertCopyMachineInstrs(). Implement getSavedStateIndexOfFunction(). --- Diffs of the changes: (+22 -1) Index: reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp diff -u reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.11 reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.12 --- reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.11 Tue Nov 4 16:11:41 2003 +++ reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp Tue Nov 4 16:39:52 2003 @@ -13,6 +13,7 @@ #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Module.h" #include "reopt/ScratchMemory.h" #include "reopt/MappingInfo.h" #include "Support/Debug.h" @@ -32,7 +33,7 @@ } else if (Source.AllocState == AllocInfo::Allocated && Target.AllocState == AllocInfo::Spilled) { //Insert store instruction from register Source to stack loc. Target } else if (Source.AllocState == AllocInfo::Spilled && Target.AllocState == AllocInfo::Spilled) { - //Get a temporary register Temp somehow + //Get a temporary register Temp somehow (maybe use the path reg, %g1?) //Insert load instruction from stack loc. Source into register Temp //Insert store instruction from register Temp to stack loc. Target } @@ -126,7 +127,27 @@ extern PhyRegAlloc::SavedStateMapTy ExportedFnAllocState; +/// Returns the index in _llvm_regAllocState.functions[] where F's register +/// allocation data may be found. +/// +/// FIXME: This is basically the same as Anand's FunctionKey[] in +/// getLLVMinfo.cpp; merge the two! +/// unsigned getSavedStateIndexOfFunction (Function *F) { + unsigned Key = 0; + Module *M = F->getParent (); + for (Module::iterator I = M->begin (), E = M->end (); I != E; ++I) { + Function *FI = I; + if (FI->isExternal ()) continue; + if (FI == F) return Key; + ++Key; + } + // By this time we had better have found it, otherwise we are about to do bad + // things. + std::cerr << "ERROR: UnpackTraceFunction: Cannot find index of Function " + << F->getName() << "() in its parent Module, in " + << "getSavedStateIndexOfFunction()\n"; + abort (); } unsigned getSavedStateIndexOfInstruction (Function *F, Value *V) { From gaeke at cs.uiuc.edu Tue Nov 4 16:43:00 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Tue Nov 4 16:43:00 2003 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp Message-ID: <200311042242.QAA00125@seraph.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/RegAlloc: PhyRegAlloc.cpp updated: 1.126 -> 1.127 --- Log message: Update verifySavedState()'s comment, so that it reflects its current status. In doFinalization(), skip over external functions, just like Anand's mapping info does. --- Diffs of the changes: (+3 -1) Index: llvm/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp diff -u llvm/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp:1.126 llvm/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp:1.127 --- llvm/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp:1.126 Tue Nov 4 12:25:56 2003 +++ llvm/lib/CodeGen/RegAlloc/PhyRegAlloc.cpp Tue Nov 4 16:42:41 2003 @@ -1177,7 +1177,8 @@ /// Check the saved state filled in by saveState(), and abort if it looks -/// wrong. Only used when debugging. +/// wrong. Only used when debugging. FIXME: Currently it just prints out +/// the state, which isn't quite as useful. /// void PhyRegAlloc::verifySavedState () { std::vector &state = FnAllocState[Fn]; @@ -1233,6 +1234,7 @@ std::vector allstate; for (Module::iterator I = M.begin (), E = M.end (); I != E; ++I) { Function *F = I; + if (F->isExternal ()) continue; if (FnAllocState.find (F) == FnAllocState.end ()) { allstate.push_back (ConstantPointerNull::get (PT)); } else { From alkis at cs.uiuc.edu Tue Nov 4 16:58:01 2003 From: alkis at cs.uiuc.edu (Alkis Evlogimenos) Date: Tue Nov 4 16:58:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86RegisterInfo.h X86RegisterInfo.cpp Message-ID: <200311042257.QAA27335@morpheus.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86RegisterInfo.h updated: 1.16 -> 1.17 X86RegisterInfo.cpp updated: 1.38 -> 1.39 --- Log message: Change all machine basic block modifier functions in MRegisterInfo to return the number of instructions added to/removed from the basic block passed as their first argument. Note: This is only needed because we use a std::vector instead of an ilist to keep MachineBasicBlock instructions. Inserting an instruction to a MachineBasicBlock invalidates all iterators to the basic block. The return value can be used to update an index to the machine basic block instruction vector and circumvent the iterator elimination problem but this is really not needed if we move to a better representation. --- Diffs of the changes: (+53 -40) Index: llvm/lib/Target/X86/X86RegisterInfo.h diff -u llvm/lib/Target/X86/X86RegisterInfo.h:1.16 llvm/lib/Target/X86/X86RegisterInfo.h:1.17 --- llvm/lib/Target/X86/X86RegisterInfo.h:1.16 Tue Oct 21 10:17:13 2003 +++ llvm/lib/Target/X86/X86RegisterInfo.h Tue Nov 4 16:57:09 2003 @@ -25,31 +25,31 @@ const TargetRegisterClass* getRegClassForType(const Type* Ty) const; /// Code Generation virtual methods... - void storeRegToStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator &MBBI, - unsigned SrcReg, int FrameIndex, - const TargetRegisterClass *RC) const; + int storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + unsigned SrcReg, int FrameIndex, + const TargetRegisterClass *RC) const; - void loadRegFromStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator &MBBI, - unsigned DestReg, int FrameIndex, - const TargetRegisterClass *RC) const; + int loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + unsigned DestReg, int FrameIndex, + const TargetRegisterClass *RC) const; - void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, + int copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, unsigned DestReg, unsigned SrcReg, const TargetRegisterClass *RC) const; - void eliminateCallFramePseudoInstr(MachineFunction &MF, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator &I) const; + int eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator &I) const; - void eliminateFrameIndex(MachineFunction &MF, - MachineBasicBlock::iterator &II) const; + int eliminateFrameIndex(MachineFunction &MF, + MachineBasicBlock::iterator &II) const; - void processFunctionBeforeFrameFinalized(MachineFunction &MF) const; + int processFunctionBeforeFrameFinalized(MachineFunction &MF) const; - void emitPrologue(MachineFunction &MF) const; - void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; + int emitPrologue(MachineFunction &MF) const; + int emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; }; #endif Index: llvm/lib/Target/X86/X86RegisterInfo.cpp diff -u llvm/lib/Target/X86/X86RegisterInfo.cpp:1.38 llvm/lib/Target/X86/X86RegisterInfo.cpp:1.39 --- llvm/lib/Target/X86/X86RegisterInfo.cpp:1.38 Mon Oct 20 14:43:18 2003 +++ llvm/lib/Target/X86/X86RegisterInfo.cpp Tue Nov 4 16:57:09 2003 @@ -44,36 +44,39 @@ } } -void X86RegisterInfo::storeRegToStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator &MBBI, - unsigned SrcReg, int FrameIdx, - const TargetRegisterClass *RC) const { +int X86RegisterInfo::storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + unsigned SrcReg, int FrameIdx, + const TargetRegisterClass *RC) const { static const unsigned Opcode[] = { X86::MOVrm8, X86::MOVrm16, X86::MOVrm32, X86::FSTPr80 }; MachineInstr *MI = addFrameReference(BuildMI(Opcode[getIdx(RC)], 5), FrameIdx).addReg(SrcReg); MBBI = MBB.insert(MBBI, MI)+1; + return 1; } -void X86RegisterInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator &MBBI, - unsigned DestReg, int FrameIdx, - const TargetRegisterClass *RC) const{ +int X86RegisterInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + unsigned DestReg, int FrameIdx, + const TargetRegisterClass *RC) const{ static const unsigned Opcode[] = { X86::MOVmr8, X86::MOVmr16, X86::MOVmr32, X86::FLDr80 }; MachineInstr *MI = addFrameReference(BuildMI(Opcode[getIdx(RC)], 4, DestReg), FrameIdx); MBBI = MBB.insert(MBBI, MI)+1; + return 1; } -void X86RegisterInfo::copyRegToReg(MachineBasicBlock &MBB, - MachineBasicBlock::iterator &MBBI, - unsigned DestReg, unsigned SrcReg, - const TargetRegisterClass *RC) const { +int X86RegisterInfo::copyRegToReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *RC) const { static const unsigned Opcode[] = { X86::MOVrr8, X86::MOVrr16, X86::MOVrr32, X86::FpMOV }; MachineInstr *MI = BuildMI(Opcode[getIdx(RC)],1,DestReg).addReg(SrcReg); MBBI = MBB.insert(MBBI, MI)+1; + return 1; } //===----------------------------------------------------------------------===// @@ -88,8 +91,8 @@ return NoFPElim || MF.getFrameInfo()->hasVarSizedObjects(); } -void X86RegisterInfo::eliminateCallFramePseudoInstr(MachineFunction &MF, - MachineBasicBlock &MBB, +int X86RegisterInfo::eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, MachineBasicBlock::iterator &I) const { MachineInstr *New = 0, *Old = *I;; if (hasFP(MF)) { @@ -113,15 +116,19 @@ } } - if (New) + if (New) { *I = New; // Replace the pseudo instruction with a new instruction... - else + delete Old; + return 0; + } else { I = MBB.erase(I);// Just delete the pseudo instruction... - delete Old; + delete Old; + return -1; + } } -void X86RegisterInfo::eliminateFrameIndex(MachineFunction &MF, - MachineBasicBlock::iterator &II) const { +int X86RegisterInfo::eliminateFrameIndex(MachineFunction &MF, + MachineBasicBlock::iterator &II) const { unsigned i = 0; MachineInstr &MI = **II; while (!MI.getOperand(i).isFrameIndex()) { @@ -143,9 +150,10 @@ Offset += MF.getFrameInfo()->getStackSize(); MI.SetMachineOperandConst(i+3, MachineOperand::MO_SignExtendedImmed, Offset); + return 0; } -void X86RegisterInfo::processFunctionBeforeFrameFinalized(MachineFunction &MF) +int X86RegisterInfo::processFunctionBeforeFrameFinalized(MachineFunction &MF) const { if (hasFP(MF)) { // Create a frame entry for the EBP register that must be saved. @@ -153,14 +161,16 @@ assert(FrameIdx == MF.getFrameInfo()->getObjectIndexEnd()-1 && "Slot for EBP register must be last in order to be found!"); } + return 0; } -void X86RegisterInfo::emitPrologue(MachineFunction &MF) const { +int X86RegisterInfo::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB MachineBasicBlock::iterator MBBI = MBB.begin(); MachineFrameInfo *MFI = MF.getFrameInfo(); MachineInstr *MI; + unsigned oldSize = MBB.size(); // Get the number of bytes to allocate from the FrameInfo unsigned NumBytes = MFI->getStackSize(); if (hasFP(MF)) { @@ -207,10 +217,12 @@ MBB.insert(MBBI, MI); } } + return MBB.size() - oldSize; } -void X86RegisterInfo::emitEpilogue(MachineFunction &MF, - MachineBasicBlock &MBB) const { +int X86RegisterInfo::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + unsigned oldSize = MBB.size(); const MachineFrameInfo *MFI = MF.getFrameInfo(); MachineBasicBlock::iterator MBBI = MBB.end()-1; MachineInstr *MI; @@ -238,6 +250,7 @@ MBBI = 1+MBB.insert(MBBI, MI); } } + return MBB.size() - oldSize; } #include "X86GenRegisterInfo.inc" From alkis at cs.uiuc.edu Tue Nov 4 16:58:04 2003 From: alkis at cs.uiuc.edu (Alkis Evlogimenos) Date: Tue Nov 4 16:58:04 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Target/MRegisterInfo.h Message-ID: <200311042257.QAA27338@morpheus.cs.uiuc.edu> Changes in directory llvm/include/llvm/Target: MRegisterInfo.h updated: 1.22 -> 1.23 --- Log message: Change all machine basic block modifier functions in MRegisterInfo to return the number of instructions added to/removed from the basic block passed as their first argument. Note: This is only needed because we use a std::vector instead of an ilist to keep MachineBasicBlock instructions. Inserting an instruction to a MachineBasicBlock invalidates all iterators to the basic block. The return value can be used to update an index to the machine basic block instruction vector and circumvent the iterator elimination problem but this is really not needed if we move to a better representation. --- Diffs of the changes: (+47 -25) Index: llvm/include/llvm/Target/MRegisterInfo.h diff -u llvm/include/llvm/Target/MRegisterInfo.h:1.22 llvm/include/llvm/Target/MRegisterInfo.h:1.23 --- llvm/include/llvm/Target/MRegisterInfo.h:1.22 Mon Oct 20 15:19:40 2003 +++ llvm/include/llvm/Target/MRegisterInfo.h Tue Nov 4 16:57:09 2003 @@ -185,24 +185,40 @@ } //===--------------------------------------------------------------------===// + // All basic block modifier functions below return the number of + // instructions added to/removed from the basic block passed as their + // first argument. + // + // FIXME: This is only needed because we use a std::vector instead + // of an ilist to keep MachineBasicBlock instructions. Inserting an + // instruction to a MachineBasicBlock invalidates all iterators to + // the basic block. The return value can be used to update an index + // to the machine basic block instruction vector and circumvent the + // iterator elimination problem but this is really not needed if we + // move to a better representation. + // + + //===--------------------------------------------------------------------===// // Interfaces used by the register allocator and stack frame manipulation // passes to move data around between registers, immediates and memory. + // The return value is the number of instructions added/deleted to/from the + // basic block. // - virtual void storeRegToStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator &MBBI, - unsigned SrcReg, int FrameIndex, - const TargetRegisterClass *RC) const = 0; - - virtual void loadRegFromStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator &MBBI, - unsigned DestReg, int FrameIndex, - const TargetRegisterClass *RC) const = 0; - - virtual void copyRegToReg(MachineBasicBlock &MBB, - MachineBasicBlock::iterator &MBBI, - unsigned DestReg, unsigned SrcReg, - const TargetRegisterClass *RC) const = 0; + virtual int storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + unsigned SrcReg, int FrameIndex, + const TargetRegisterClass *RC) const = 0; + + virtual int loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + unsigned DestReg, int FrameIndex, + const TargetRegisterClass *RC) const = 0; + + virtual int copyRegToReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator &MBBI, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *RC) const = 0; /// getCallFrameSetup/DestroyOpcode - These methods return the opcode of the @@ -220,9 +236,10 @@ /// instructions (but only if the Target is using them). It is responsible /// for eliminating these instructions, replacing them with concrete /// instructions. This method need only be implemented if using call frame - /// setup/destroy pseudo instructions. + /// setup/destroy pseudo instructions. The return value is the number of + /// instructions added/deleted to/from the basic block. /// - virtual void eliminateCallFramePseudoInstr(MachineFunction &MF, + virtual int eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator &I) const { assert(getCallFrameSetupOpcode()== -1 && getCallFrameDestroyOpcode()== -1 && @@ -234,25 +251,30 @@ /// processFunctionBeforeFrameFinalized - This method is called immediately /// before the specified functions frame layout (MF.getFrameInfo()) is /// finalized. Once the frame is finalized, MO_FrameIndex operands are - /// replaced with direct constants. This method is optional. + /// replaced with direct constants. This method is optional. The return value + /// is the number of instructions added/deleted to/from the basic block /// - virtual void processFunctionBeforeFrameFinalized(MachineFunction &MF) const {} + virtual int processFunctionBeforeFrameFinalized(MachineFunction &MF) const { + return 0; + } /// eliminateFrameIndex - This method must be overriden to eliminate abstract /// frame indices from instructions which may use them. The instruction /// referenced by the iterator contains an MO_FrameIndex operand which must be /// eliminated by this method. This method may modify or replace the /// specified instruction, as long as it keeps the iterator pointing the the - /// finished product. + /// finished product. The return value is the number of instructions + /// added/deleted to/from the basic block /// - virtual void eliminateFrameIndex(MachineFunction &MF, - MachineBasicBlock::iterator &II) const = 0; + virtual int eliminateFrameIndex(MachineFunction &MF, + MachineBasicBlock::iterator &II) const = 0; /// emitProlog/emitEpilog - These methods insert prolog and epilog code into - /// the function. - virtual void emitPrologue(MachineFunction &MF) const = 0; - virtual void emitEpilogue(MachineFunction &MF, - MachineBasicBlock &MBB) const = 0; + /// the function. The return value is the number of instructions + /// added/deleted to/from the basic block (entry for prologue, + virtual int emitPrologue(MachineFunction &MF) const = 0; + virtual int emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const = 0; }; #endif From alkis at cs.uiuc.edu Tue Nov 4 17:08:01 2003 From: alkis at cs.uiuc.edu (Alkis Evlogimenos) Date: Tue Nov 4 17:08:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Target/MRegisterInfo.h Message-ID: <200311042307.RAA27374@morpheus.cs.uiuc.edu> Changes in directory llvm/include/llvm/Target: MRegisterInfo.h updated: 1.23 -> 1.24 --- Log message: Update documentation since it was misleading: make it clear that a negative instruction count is returned if instructions are removed from a basic block. --- Diffs of the changes: (+12 -10) Index: llvm/include/llvm/Target/MRegisterInfo.h diff -u llvm/include/llvm/Target/MRegisterInfo.h:1.23 llvm/include/llvm/Target/MRegisterInfo.h:1.24 --- llvm/include/llvm/Target/MRegisterInfo.h:1.23 Tue Nov 4 16:57:09 2003 +++ llvm/include/llvm/Target/MRegisterInfo.h Tue Nov 4 17:07:00 2003 @@ -186,8 +186,8 @@ //===--------------------------------------------------------------------===// // All basic block modifier functions below return the number of - // instructions added to/removed from the basic block passed as their - // first argument. + // instructions added to (negative if removed from) the basic block + // passed as their first argument. // // FIXME: This is only needed because we use a std::vector instead // of an ilist to keep MachineBasicBlock instructions. Inserting an @@ -199,10 +199,10 @@ // //===--------------------------------------------------------------------===// - // Interfaces used by the register allocator and stack frame manipulation - // passes to move data around between registers, immediates and memory. - // The return value is the number of instructions added/deleted to/from the - // basic block. + // Interfaces used by the register allocator and stack frame + // manipulation passes to move data around between registers, + // immediates and memory. The return value is the number of + // instructions added to (negative if removed from) the basic block. // virtual int storeRegToStackSlot(MachineBasicBlock &MBB, @@ -237,7 +237,7 @@ /// for eliminating these instructions, replacing them with concrete /// instructions. This method need only be implemented if using call frame /// setup/destroy pseudo instructions. The return value is the number of - /// instructions added/deleted to/from the basic block. + /// instructions added to (negative if removed from) the basic block. /// virtual int eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, @@ -252,7 +252,8 @@ /// before the specified functions frame layout (MF.getFrameInfo()) is /// finalized. Once the frame is finalized, MO_FrameIndex operands are /// replaced with direct constants. This method is optional. The return value - /// is the number of instructions added/deleted to/from the basic block + /// is the number of instructions added to (negative if removed from) the + /// basic block /// virtual int processFunctionBeforeFrameFinalized(MachineFunction &MF) const { return 0; @@ -264,14 +265,15 @@ /// eliminated by this method. This method may modify or replace the /// specified instruction, as long as it keeps the iterator pointing the the /// finished product. The return value is the number of instructions - /// added/deleted to/from the basic block + /// added to (negative if removed from) the basic block. /// virtual int eliminateFrameIndex(MachineFunction &MF, MachineBasicBlock::iterator &II) const = 0; /// emitProlog/emitEpilog - These methods insert prolog and epilog code into /// the function. The return value is the number of instructions - /// added/deleted to/from the basic block (entry for prologue, + /// added to (negative if removed from) the basic block (entry for prologue). + /// virtual int emitPrologue(MachineFunction &MF) const = 0; virtual int emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const = 0; From lattner at cs.uiuc.edu Tue Nov 4 17:22:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Nov 4 17:22:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/InstCombine/xor.ll Message-ID: <200311042321.RAA12418@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/InstCombine: xor.ll updated: 1.6 -> 1.7 --- Log message: New testcase for masking operation that frequently occurs in the pool allocator for converting a number that is a power of two into a mask --- Diffs of the changes: (+6 -0) Index: llvm/test/Regression/Transforms/InstCombine/xor.ll diff -u llvm/test/Regression/Transforms/InstCombine/xor.ll:1.6 llvm/test/Regression/Transforms/InstCombine/xor.ll:1.7 --- llvm/test/Regression/Transforms/InstCombine/xor.ll:1.6 Tue Sep 16 10:29:34 2003 +++ llvm/test/Regression/Transforms/InstCombine/xor.ll Tue Nov 4 17:21:22 2003 @@ -98,3 +98,9 @@ %E = xor bool %C, %D ; E = true ret bool %E } + +uint %test15(uint %A) { ; ~(X-1) == -X + %B = add uint %A, 4294967295 + %C = xor uint %B, 4294967295 + ret uint %C +} From lattner at cs.uiuc.edu Tue Nov 4 17:38:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Nov 4 17:38:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/ConstantHandling.h Message-ID: <200311042337.RAA16016@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm: ConstantHandling.h updated: 1.30 -> 1.31 --- Log message: Fix spello Add negate overload --- Diffs of the changes: (+5 -1) Index: llvm/include/llvm/ConstantHandling.h diff -u llvm/include/llvm/ConstantHandling.h:1.30 llvm/include/llvm/ConstantHandling.h:1.31 --- llvm/include/llvm/ConstantHandling.h:1.30 Mon Oct 20 15:19:13 2003 +++ llvm/include/llvm/ConstantHandling.h Tue Nov 4 17:37:40 2003 @@ -134,9 +134,13 @@ // Unary operators... inline Constant *operator~(const Constant &V) { - assert(V.getType()->isIntegral() && "Cannot invert non-intergral constant!"); + assert(V.getType()->isIntegral() && "Cannot invert non-integral constant!"); return ConstRules::get(V, V)->op_xor(&V, ConstantInt::getAllOnesValue(V.getType())); +} + +inline Constant *operator-(const Constant &V) { + return ConstRules::get(V, V)->sub(Constant::getNullValue(V.getType()), &V); } // Standard binary operators... From lattner at cs.uiuc.edu Tue Nov 4 17:38:04 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Nov 4 17:38:04 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200311042337.RAA14711@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.137 -> 1.138 --- Log message: Implement InstCombine/xor.ll:test(15|16) --- Diffs of the changes: (+8 -1) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.137 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.138 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.137 Sun Nov 2 23:17:03 2003 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Tue Nov 4 17:37:10 2003 @@ -1002,7 +1002,14 @@ SCI->getOperand(0), SCI->getOperand(1)); if (ConstantInt *Op0CI = dyn_cast(Op0I->getOperand(1))) - if (Op0I->getOpcode() == Instruction::And) { + if (Op0I->getOpcode() == Instruction::Add) { + // ~(X-c) --> (-c-1)-X + if (RHS->isAllOnesValue()) + return BinaryOperator::create(Instruction::Sub, + *-*Op0CI - + *ConstantInt::get(I.getType(), 1), + Op0I->getOperand(0)); + } else if (Op0I->getOpcode() == Instruction::And) { // (X & C1) ^ C2 --> (X & C1) | C2 iff (C1&C2) == 0 if ((*RHS & *Op0CI)->isNullValue()) return BinaryOperator::create(Instruction::Or, Op0, RHS); From lattner at cs.uiuc.edu Tue Nov 4 17:38:07 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Nov 4 17:38:07 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/InstCombine/xor.ll Message-ID: <200311042337.RAA14273@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/InstCombine: xor.ll updated: 1.7 -> 1.8 --- Log message: Add a generalization of the previous case --- Diffs of the changes: (+6 -0) Index: llvm/test/Regression/Transforms/InstCombine/xor.ll diff -u llvm/test/Regression/Transforms/InstCombine/xor.ll:1.7 llvm/test/Regression/Transforms/InstCombine/xor.ll:1.8 --- llvm/test/Regression/Transforms/InstCombine/xor.ll:1.7 Tue Nov 4 17:21:22 2003 +++ llvm/test/Regression/Transforms/InstCombine/xor.ll Tue Nov 4 17:36:50 2003 @@ -104,3 +104,9 @@ %C = xor uint %B, 4294967295 ret uint %C } + +uint %test16(uint %A) { ; ~(X+c) == (-c-1)-X + %B = add uint %A, 123 ; A generalization of the previous case + %C = xor uint %B, 4294967295 + ret uint %C +} From lattner at cs.uiuc.edu Tue Nov 4 17:51:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Nov 4 17:51:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/InstCombine/xor.ll Message-ID: <200311042350.RAA19488@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/InstCombine: xor.ll updated: 1.8 -> 1.9 --- Log message: Since we're in the neighborhood, test for the inverse --- Diffs of the changes: (+6 -0) Index: llvm/test/Regression/Transforms/InstCombine/xor.ll diff -u llvm/test/Regression/Transforms/InstCombine/xor.ll:1.8 llvm/test/Regression/Transforms/InstCombine/xor.ll:1.9 --- llvm/test/Regression/Transforms/InstCombine/xor.ll:1.8 Tue Nov 4 17:36:50 2003 +++ llvm/test/Regression/Transforms/InstCombine/xor.ll Tue Nov 4 17:49:53 2003 @@ -110,3 +110,9 @@ %C = xor uint %B, 4294967295 ret uint %C } + +uint %test17(uint %A) { ; ~(c-X) == X-(c-1) == X+(-c+1) + %B = sub uint 123, %A + %C = xor uint %B, 4294967295 + ret uint %C +} From lattner at cs.uiuc.edu Tue Nov 4 17:52:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Nov 4 17:52:00 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200311042351.RAA19925@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.138 -> 1.139 --- Log message: Minor cleanup, plus implement InstCombine/xor.ll:test17 --- Diffs of the changes: (+17 -3) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.138 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.139 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.138 Tue Nov 4 17:37:10 2003 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Tue Nov 4 17:50:51 2003 @@ -1000,23 +1000,37 @@ if (RHS == ConstantBool::True && SCI->hasOneUse()) return new SetCondInst(SCI->getInverseCondition(), SCI->getOperand(0), SCI->getOperand(1)); + + // ~(c-X) == X-(c-1) == X+(-c+1) + if (Op0I->getOpcode() == Instruction::Sub && RHS->isAllOnesValue() && + isa(Op0I->getOperand(0))) { + Constant *ConstantRHS = *-*cast(Op0I->getOperand(0)) + + *ConstantInt::get(I.getType(), 1); + return BinaryOperator::create(Instruction::Add, Op0I->getOperand(1), + ConstantRHS); + } if (ConstantInt *Op0CI = dyn_cast(Op0I->getOperand(1))) - if (Op0I->getOpcode() == Instruction::Add) { + switch (Op0I->getOpcode()) { + case Instruction::Add: // ~(X-c) --> (-c-1)-X if (RHS->isAllOnesValue()) return BinaryOperator::create(Instruction::Sub, *-*Op0CI - *ConstantInt::get(I.getType(), 1), Op0I->getOperand(0)); - } else if (Op0I->getOpcode() == Instruction::And) { + break; + case Instruction::And: // (X & C1) ^ C2 --> (X & C1) | C2 iff (C1&C2) == 0 if ((*RHS & *Op0CI)->isNullValue()) return BinaryOperator::create(Instruction::Or, Op0, RHS); - } else if (Op0I->getOpcode() == Instruction::Or) { + break; + case Instruction::Or: // (X | C1) ^ C2 --> (X | C1) & ~C2 iff (C1&C2) == C2 if ((*RHS & *Op0CI) == RHS) return BinaryOperator::create(Instruction::And, Op0, ~*RHS); + break; + default: break; } } } From gaeke at cs.uiuc.edu Tue Nov 4 19:00:01 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Tue Nov 4 19:00:01 2003 Subject: [llvm-commits] CVS: llvm/lib/ExecutionEngine/Interpreter/Execution.cpp Message-ID: <200311050059.SAA26845@zion.cs.uiuc.edu> Changes in directory llvm/lib/ExecutionEngine/Interpreter: Execution.cpp updated: 1.103 -> 1.104 --- Log message: Remove a comment which no longer applies. --- Diffs of the changes: (+0 -5) Index: llvm/lib/ExecutionEngine/Interpreter/Execution.cpp diff -u llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.103 llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.104 --- llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.103 Fri Oct 24 14:59:01 2003 +++ llvm/lib/ExecutionEngine/Interpreter/Execution.cpp Tue Nov 4 18:59:28 2003 @@ -815,11 +815,6 @@ return; } - // Process the function, assigning instruction numbers to the instructions in - // the function. Also calculate the number of values for each type slot - // active. - // - // Make a new stack frame... and fill it in. ECStack.push_back(ExecutionContext()); ExecutionContext &StackFrame = ECStack.back(); From gaeke at cs.uiuc.edu Tue Nov 4 19:03:01 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Tue Nov 4 19:03:01 2003 Subject: [llvm-commits] CVS: llvm/lib/ExecutionEngine/Interpreter/Execution.cpp Message-ID: <200311050102.TAA27483@zion.cs.uiuc.edu> Changes in directory llvm/lib/ExecutionEngine/Interpreter: Execution.cpp updated: 1.104 -> 1.105 --- Log message: Use regular old malloc to emulate malloc/alloca instructions. --- Diffs of the changes: (+1 -2) Index: llvm/lib/ExecutionEngine/Interpreter/Execution.cpp diff -u llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.104 llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.105 --- llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.104 Tue Nov 4 18:59:28 2003 +++ llvm/lib/ExecutionEngine/Interpreter/Execution.cpp Tue Nov 4 19:02:14 2003 @@ -546,8 +546,7 @@ unsigned NumElements = getOperandValue(I.getOperand(0), SF).UIntVal; // Allocate enough memory to hold the type... - // FIXME: Don't use CALLOC, use a tainted malloc. - void *Memory = calloc(NumElements, TD.getTypeSize(Ty)); + void *Memory = malloc(NumElements * TD.getTypeSize(Ty)); GenericValue Result = PTOGV(Memory); assert(Result.PointerVal != 0 && "Null pointer returned by malloc!"); From lattner at cs.uiuc.edu Tue Nov 4 19:06:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Nov 4 19:06:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/InstCombine/xor.ll Message-ID: <200311050105.TAA28811@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/InstCombine: xor.ll updated: 1.9 -> 1.10 --- Log message: New testcase for the other side --- Diffs of the changes: (+6 -0) Index: llvm/test/Regression/Transforms/InstCombine/xor.ll diff -u llvm/test/Regression/Transforms/InstCombine/xor.ll:1.9 llvm/test/Regression/Transforms/InstCombine/xor.ll:1.10 --- llvm/test/Regression/Transforms/InstCombine/xor.ll:1.9 Tue Nov 4 17:49:53 2003 +++ llvm/test/Regression/Transforms/InstCombine/xor.ll Tue Nov 4 19:05:22 2003 @@ -116,3 +116,9 @@ %C = xor uint %B, 4294967295 ret uint %C } + +uint %test18(uint %A) { ; C - ~X == X + (1+C) + %B = xor uint %A, 4294967295; -~X == 0 - ~X == X+1 + %C = sub uint 123, %B + ret uint %C +} From lattner at cs.uiuc.edu Tue Nov 4 19:07:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Nov 4 19:07:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200311050106.TAA28827@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.139 -> 1.140 --- Log message: Fix bug with previous implementation: - // ~(c-X) == X-(c-1) == X+(-c+1) + // ~(c-X) == X-c-1 == X+(-c-1) Implement: C - ~X == X + (1+C) --- Diffs of the changes: (+11 -4) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.139 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.140 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.139 Tue Nov 4 17:50:51 2003 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Tue Nov 4 19:06:05 2003 @@ -488,11 +488,18 @@ if (Value *V = dyn_castNegVal(Op1)) return BinaryOperator::create(Instruction::Add, Op0, V); - // Replace (-1 - A) with (~A)... - if (ConstantInt *C = dyn_cast(Op0)) + if (ConstantInt *C = dyn_cast(Op0)) { + // Replace (-1 - A) with (~A)... if (C->isAllOnesValue()) return BinaryOperator::createNot(Op1); + // C - ~X == X + (1+C) + if (BinaryOperator::isNot(Op1)) + return BinaryOperator::create(Instruction::Add, + BinaryOperator::getNotArgument(cast(Op1)), + *C + *ConstantInt::get(I.getType(), 1)); + } + if (BinaryOperator *Op1I = dyn_cast(Op1)) if (Op1I->hasOneUse()) { // Replace (x - (y - z)) with (x + (z - y)) if the (y - z) subexpression @@ -1001,10 +1008,10 @@ return new SetCondInst(SCI->getInverseCondition(), SCI->getOperand(0), SCI->getOperand(1)); - // ~(c-X) == X-(c-1) == X+(-c+1) + // ~(c-X) == X-c-1 == X+(-c-1) if (Op0I->getOpcode() == Instruction::Sub && RHS->isAllOnesValue() && isa(Op0I->getOperand(0))) { - Constant *ConstantRHS = *-*cast(Op0I->getOperand(0)) + + Constant *ConstantRHS = *-*cast(Op0I->getOperand(0)) - *ConstantInt::get(I.getType(), 1); return BinaryOperator::create(Instruction::Add, Op0I->getOperand(1), ConstantRHS); From gaeke at cs.uiuc.edu Tue Nov 4 19:20:02 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Tue Nov 4 19:20:02 2003 Subject: [llvm-commits] CVS: llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp Message-ID: <200311050118.TAA30252@zion.cs.uiuc.edu> Changes in directory llvm/lib/ExecutionEngine/Interpreter: ExternalFunctions.cpp updated: 1.66 -> 1.67 --- Log message: Abort when the user program calls abort, instead of printing a funny message and calling exit(1). --- Diffs of the changes: (+2 -4) Index: llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp diff -u llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp:1.66 llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp:1.67 --- llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp:1.66 Sat Oct 25 11:18:03 2003 +++ llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp Tue Nov 4 19:18:49 2003 @@ -28,6 +28,7 @@ #include "Config/dlfcn.h" #include "Config/link.h" #include +#include #include using std::vector; @@ -142,10 +143,7 @@ // void abort(void) GenericValue lle_X_abort(FunctionType *M, const vector &Args) { - std::cerr << "***PROGRAM ABORTED***!\n"; - GenericValue GV; - GV.IntVal = 1; - TheInterpreter->exitCalled(GV); + raise (SIGABRT); return GenericValue(); } From lattner at cs.uiuc.edu Tue Nov 4 19:32:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Nov 4 19:32:01 2003 Subject: [llvm-commits] CVS: llvm/include/boost/config/compiler/gcc.hpp Message-ID: <200311050131.TAA10292@zion.cs.uiuc.edu> Changes in directory llvm/include/boost/config/compiler: gcc.hpp updated: 1.3 -> 1.4 --- Log message: This works with GCC 3.4 also --- Diffs of the changes: (+2 -2) Index: llvm/include/boost/config/compiler/gcc.hpp diff -u llvm/include/boost/config/compiler/gcc.hpp:1.3 llvm/include/boost/config/compiler/gcc.hpp:1.4 --- llvm/include/boost/config/compiler/gcc.hpp:1.3 Fri Jul 25 12:33:45 2003 +++ llvm/include/boost/config/compiler/gcc.hpp Tue Nov 4 19:31:12 2003 @@ -49,8 +49,8 @@ # error "Compiler not configured - please reconfigure" #endif // -// last known and checked version is 3.3: -#if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ > 3)) +// last known and checked version is 3.4: +#if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ > 4)) # if defined(BOOST_ASSERT_CONFIG) # error "Unknown compiler version - please run the configure tests and report the results" # else From lattner at cs.uiuc.edu Tue Nov 4 19:38:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Nov 4 19:38:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/C++Frontend/2003-11-04-CatchLabelName.cpp Message-ID: <200311050136.TAA14556@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/C++Frontend: 2003-11-04-CatchLabelName.cpp added (r1.1) --- Log message: New testcase --- Diffs of the changes: (+9 -0) Index: llvm/test/Regression/C++Frontend/2003-11-04-CatchLabelName.cpp diff -c /dev/null llvm/test/Regression/C++Frontend/2003-11-04-CatchLabelName.cpp:1.1 *** /dev/null Tue Nov 4 19:36:59 2003 --- llvm/test/Regression/C++Frontend/2003-11-04-CatchLabelName.cpp Tue Nov 4 19:36:49 2003 *************** *** 0 **** --- 1,9 ---- + #include + + void bar(); + + void test() { + try { + bar(); + } catch (std::string) {} + } From lattner at cs.uiuc.edu Tue Nov 4 23:16:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Nov 4 23:16:01 2003 Subject: [llvm-commits] CVS: llvm/lib/VMCore/BasicBlock.cpp Function.cpp Module.cpp PassManagerT.h Message-ID: <200311050515.XAA18848@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: BasicBlock.cpp updated: 1.34 -> 1.35 Function.cpp updated: 1.54 -> 1.55 Module.cpp updated: 1.42 -> 1.43 PassManagerT.h updated: 1.44 -> 1.45 --- Log message: Make code gcc 3.4 clean --- Diffs of the changes: (+6 -6) Index: llvm/lib/VMCore/BasicBlock.cpp diff -u llvm/lib/VMCore/BasicBlock.cpp:1.34 llvm/lib/VMCore/BasicBlock.cpp:1.35 --- llvm/lib/VMCore/BasicBlock.cpp:1.34 Mon Oct 20 14:43:20 2003 +++ llvm/lib/VMCore/BasicBlock.cpp Tue Nov 4 23:15:42 2003 @@ -56,7 +56,7 @@ // Explicit instantiation of SymbolTableListTraits since some of the methods // are not in the public header file... -template SymbolTableListTraits; +template class SymbolTableListTraits; // BasicBlock ctor - If the function parameter is specified, the basic block is Index: llvm/lib/VMCore/Function.cpp diff -u llvm/lib/VMCore/Function.cpp:1.54 llvm/lib/VMCore/Function.cpp:1.55 --- llvm/lib/VMCore/Function.cpp:1.54 Mon Oct 20 14:43:21 2003 +++ llvm/lib/VMCore/Function.cpp Tue Nov 4 23:15:42 2003 @@ -43,8 +43,8 @@ // Explicit instantiations of SymbolTableListTraits since some of the methods // are not in the public header file... -template SymbolTableListTraits; -template SymbolTableListTraits; +template class SymbolTableListTraits; +template class SymbolTableListTraits; //===----------------------------------------------------------------------===// // Argument Implementation Index: llvm/lib/VMCore/Module.cpp diff -u llvm/lib/VMCore/Module.cpp:1.42 llvm/lib/VMCore/Module.cpp:1.43 --- llvm/lib/VMCore/Module.cpp:1.42 Mon Oct 20 14:43:21 2003 +++ llvm/lib/VMCore/Module.cpp Tue Nov 4 23:15:42 2003 @@ -47,8 +47,8 @@ // Explicit instantiations of SymbolTableListTraits since some of the methods // are not in the public header file... -template SymbolTableListTraits; -template SymbolTableListTraits; +template class SymbolTableListTraits; +template class SymbolTableListTraits; // Define the GlobalValueRefMap as a struct that wraps a map so that we don't // have Module.h depend on Index: llvm/lib/VMCore/PassManagerT.h diff -u llvm/lib/VMCore/PassManagerT.h:1.44 llvm/lib/VMCore/PassManagerT.h:1.45 --- llvm/lib/VMCore/PassManagerT.h:1.44 Tue Oct 21 10:17:13 2003 +++ llvm/lib/VMCore/PassManagerT.h Tue Nov 4 23:15:42 2003 @@ -141,7 +141,7 @@ friend class PassManagerTraits::PassClass; friend class PassManagerTraits::SubPassClass; - friend class Traits; + friend class PassManagerTraits; friend class ImmutablePass; std::vector Passes; // List of passes to run From lattner at cs.uiuc.edu Tue Nov 4 23:23:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Nov 4 23:23:03 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/C++Frontend/2003-11-04-ArrayConstructors.cpp Message-ID: <200311050522.XAA19063@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/C++Frontend: 2003-11-04-ArrayConstructors.cpp added (r1.1) --- Log message: NEw testcase --- Diffs of the changes: (+9 -0) Index: llvm/test/Regression/C++Frontend/2003-11-04-ArrayConstructors.cpp diff -c /dev/null llvm/test/Regression/C++Frontend/2003-11-04-ArrayConstructors.cpp:1.1 *** /dev/null Tue Nov 4 23:22:25 2003 --- llvm/test/Regression/C++Frontend/2003-11-04-ArrayConstructors.cpp Tue Nov 4 23:22:15 2003 *************** *** 0 **** --- 1,9 ---- + + struct Foo { + Foo(int); + }; + void foo() { + struct { + Foo name; + } Int[] = { 1 }; + } From lattner at cs.uiuc.edu Tue Nov 4 23:32:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Nov 4 23:32:02 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/C++Frontend/2003-11-04-ArrayConstructors.cpp Message-ID: <200311050531.XAA01912@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/C++Frontend: 2003-11-04-ArrayConstructors.cpp updated: 1.1 -> 1.2 --- Log message: Add a dtor to ensure that they are called the right number of times. --- Diffs of the changes: (+1 -0) Index: llvm/test/Regression/C++Frontend/2003-11-04-ArrayConstructors.cpp diff -u llvm/test/Regression/C++Frontend/2003-11-04-ArrayConstructors.cpp:1.1 llvm/test/Regression/C++Frontend/2003-11-04-ArrayConstructors.cpp:1.2 --- llvm/test/Regression/C++Frontend/2003-11-04-ArrayConstructors.cpp:1.1 Tue Nov 4 23:22:15 2003 +++ llvm/test/Regression/C++Frontend/2003-11-04-ArrayConstructors.cpp Tue Nov 4 23:31:24 2003 @@ -1,6 +1,7 @@ struct Foo { Foo(int); + ~Foo(); }; void foo() { struct { From lattner at cs.uiuc.edu Tue Nov 4 23:56:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Nov 4 23:56:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Analysis/IPA/IPModRef.cpp Message-ID: <200311050555.XAA13733@zion.cs.uiuc.edu> Changes in directory llvm/lib/Analysis/IPA: IPModRef.cpp updated: 1.18 -> 1.19 --- Log message: Fix name collision --- Diffs of the changes: (+2 -2) Index: llvm/lib/Analysis/IPA/IPModRef.cpp diff -u llvm/lib/Analysis/IPA/IPModRef.cpp:1.18 llvm/lib/Analysis/IPA/IPModRef.cpp:1.19 --- llvm/lib/Analysis/IPA/IPModRef.cpp:1.18 Mon Oct 20 14:43:08 2003 +++ llvm/lib/Analysis/IPA/IPModRef.cpp Tue Nov 4 23:55:45 2003 @@ -167,11 +167,11 @@ Args.push_back(Result->getNodeForValue(*I)); // Build the call site... - DSCallSite CS(CS, RetVal, F, Args); + DSCallSite NCS(CS, RetVal, F, Args); // Perform the merging now of the graph for the callee, which will // come with mod/ref bits set... - Result->mergeInGraph(CS, *F, IPModRefObj.getBUDSGraph(*F), + Result->mergeInGraph(NCS, *F, IPModRefObj.getBUDSGraph(*F), DSGraph::StripAllocaBit | DSGraph::DontCloneCallNodes | DSGraph::DontCloneAuxCallNodes); From alkis at cs.uiuc.edu Tue Nov 4 23:59:01 2003 From: alkis at cs.uiuc.edu (Alkis Evlogimenos) Date: Tue Nov 4 23:59:01 2003 Subject: [llvm-commits] CVS: llvm/include/Support/STLExtras.h Message-ID: <200311050558.XAA28210@morpheus.cs.uiuc.edu> Changes in directory llvm/include/Support: STLExtras.h updated: 1.8 -> 1.9 --- Log message: Add std::pair tier. This is a much simplified version of boost::tie that works only for std::pair. --- Diffs of the changes: (+48 -0) Index: llvm/include/Support/STLExtras.h diff -u llvm/include/Support/STLExtras.h:1.8 llvm/include/Support/STLExtras.h:1.9 --- llvm/include/Support/STLExtras.h:1.8 Mon Oct 20 14:46:57 2003 +++ llvm/include/Support/STLExtras.h Tue Nov 4 23:58:26 2003 @@ -19,6 +19,7 @@ #include #include "Support/iterator" +#include "boost/type_traits/transform_traits.hpp" //===----------------------------------------------------------------------===// // Extra additions to @@ -230,4 +231,51 @@ inline OutIt mapto(InIt Begin, InIt End, OutIt Dest, Functor F) { return copy(map_iterator(Begin, F), map_iterator(End, F), Dest); } + + +//===----------------------------------------------------------------------===// +// Extra additions to +//===----------------------------------------------------------------------===// + +// tie - this function ties two objects and returns a temporary object +// that is assignable from a std::pair. This can be used to make code +// more readable when using values returned from functions bundled in +// a std::pair. Since an example is worth 1000 words: +// +// typedef std::map Int2IntMap; +// +// Int2IntMap myMap; +// Int2IntMap::iterator where; +// bool inserted; +// tie(where, inserted) = myMap.insert(std::make_pair(123,456)); +// +// if (inserted) +// // do stuff +// else +// // do other stuff + +namespace +{ + template + struct tier { + typedef typename boost::add_reference::type first_type; + typedef typename boost::add_reference::type second_type; + + first_type first; + second_type second; + + tier(first_type f, second_type s) : first(f), second(s) { } + tier& operator=(const std::pair& p) { + first = p.first; + second = p.second; + return *this; + } + }; +} + +template +inline tier tie(T1& f, T2& s) { + return tier(f, s); +} + #endif From lattner at cs.uiuc.edu Wed Nov 5 00:06:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Nov 5 00:06:03 2003 Subject: [llvm-commits] CVS: llvm/tools/gccld/gccld.cpp Message-ID: <200311050605.AAA16202@zion.cs.uiuc.edu> Changes in directory llvm/tools/gccld: gccld.cpp updated: 1.59 -> 1.60 --- Log message: Make -r work, fixing PR 91 --- Diffs of the changes: (+4 -3) Index: llvm/tools/gccld/gccld.cpp diff -u llvm/tools/gccld/gccld.cpp:1.59 llvm/tools/gccld/gccld.cpp:1.60 --- llvm/tools/gccld/gccld.cpp:1.59 Mon Nov 3 11:27:17 2003 +++ llvm/tools/gccld/gccld.cpp Wed Nov 5 00:05:21 2003 @@ -62,13 +62,16 @@ cl::opt NoInternalize("disable-internalize", cl::desc("Do not mark all symbols as internal")); - static cl::alias + cl::alias ExportDynamic("export-dynamic", cl::desc("Alias for -disable-internalize"), cl::aliasopt(NoInternalize)); cl::opt LinkAsLibrary("link-as-library", cl::desc("Link the .bc files together as a" " library, not an executable")); + cl::alias + Relink("r", cl::desc("Alias for -link-as-library"), + cl::aliasopt(LinkAsLibrary)); cl::opt Native("native", @@ -81,8 +84,6 @@ 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")); } // From lattner at cs.uiuc.edu Wed Nov 5 00:13:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Nov 5 00:13:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Instrumentation/ProfilePaths/Graph.h Message-ID: <200311050612.AAA22953@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Instrumentation/ProfilePaths: Graph.h updated: 1.10 -> 1.11 --- Log message: Be gcc 3.4 clean --- Diffs of the changes: (+3 -1) Index: llvm/lib/Transforms/Instrumentation/ProfilePaths/Graph.h diff -u llvm/lib/Transforms/Instrumentation/ProfilePaths/Graph.h:1.10 llvm/lib/Transforms/Instrumentation/ProfilePaths/Graph.h:1.11 --- llvm/lib/Transforms/Instrumentation/ProfilePaths/Graph.h:1.10 Tue Oct 21 10:17:13 2003 +++ llvm/lib/Transforms/Instrumentation/ProfilePaths/Graph.h Wed Nov 5 00:12:18 2003 @@ -114,12 +114,14 @@ namespace std { + template<> struct less : public binary_function { bool operator()(Node *n1, Node *n2) const { return n1->getElement() < n2->getElement(); } }; - + + template<> struct less : public binary_function { bool operator()(Edge e1, Edge e2) const { assert(!e1.isNull() && !e2.isNull()); From lattner at cs.uiuc.edu Wed Nov 5 00:21:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Nov 5 00:21:01 2003 Subject: [llvm-commits] CVS: llvm/lib/ExecutionEngine/Interpreter/Execution.cpp Interpreter.cpp Interpreter.h Message-ID: <200311050620.AAA29558@zion.cs.uiuc.edu> Changes in directory llvm/lib/ExecutionEngine/Interpreter: Execution.cpp updated: 1.105 -> 1.106 Interpreter.cpp updated: 1.15 -> 1.16 Interpreter.h updated: 1.46 -> 1.47 --- Log message: Be friendly to gcc 3.4... good compiler. Nice compiler. --- Diffs of the changes: (+1 -3) Index: llvm/lib/ExecutionEngine/Interpreter/Execution.cpp diff -u llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.105 llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.106 --- llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.105 Tue Nov 4 19:02:14 2003 +++ llvm/lib/ExecutionEngine/Interpreter/Execution.cpp Wed Nov 5 00:20:27 2003 @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "Interpreter.h" -#include "llvm/Function.h" #include "llvm/Instructions.h" #include "llvm/DerivedTypes.h" #include "llvm/Constants.h" Index: llvm/lib/ExecutionEngine/Interpreter/Interpreter.cpp diff -u llvm/lib/ExecutionEngine/Interpreter/Interpreter.cpp:1.15 llvm/lib/ExecutionEngine/Interpreter/Interpreter.cpp:1.16 --- llvm/lib/ExecutionEngine/Interpreter/Interpreter.cpp:1.15 Fri Oct 24 14:59:28 2003 +++ llvm/lib/ExecutionEngine/Interpreter/Interpreter.cpp Wed Nov 5 00:20:27 2003 @@ -16,7 +16,6 @@ #include "Interpreter.h" #include "llvm/Module.h" #include "llvm/DerivedTypes.h" -#include "llvm/Function.h" /// create - Create a new interpreter object. This can never fail. /// Index: llvm/lib/ExecutionEngine/Interpreter/Interpreter.h diff -u llvm/lib/ExecutionEngine/Interpreter/Interpreter.h:1.46 llvm/lib/ExecutionEngine/Interpreter/Interpreter.h:1.47 --- llvm/lib/ExecutionEngine/Interpreter/Interpreter.h:1.46 Fri Oct 24 14:59:37 2003 +++ llvm/lib/ExecutionEngine/Interpreter/Interpreter.h Wed Nov 5 00:20:27 2003 @@ -14,7 +14,7 @@ #ifndef LLI_INTERPRETER_H #define LLI_INTERPRETER_H -#include "llvm/BasicBlock.h" +#include "llvm/Function.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/Support/InstVisitor.h" From lattner at cs.uiuc.edu Wed Nov 5 00:26:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Nov 5 00:26:02 2003 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/InstrSched/InstrScheduling.cpp Message-ID: <200311050625.AAA31067@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/InstrSched: InstrScheduling.cpp updated: 1.60 -> 1.61 --- Log message: Do not use a class before it is defined. Be gcc 3.4 clean --- Diffs of the changes: (+9 -6) Index: llvm/lib/CodeGen/InstrSched/InstrScheduling.cpp diff -u llvm/lib/CodeGen/InstrSched/InstrScheduling.cpp:1.60 llvm/lib/CodeGen/InstrSched/InstrScheduling.cpp:1.61 --- llvm/lib/CodeGen/InstrSched/InstrScheduling.cpp:1.60 Mon Oct 20 14:43:15 2003 +++ llvm/lib/CodeGen/InstrSched/InstrScheduling.cpp Wed Nov 5 00:25:06 2003 @@ -111,10 +111,7 @@ inline bool operator!=(const _Self& x) const { return !operator==(x); } - inline _NodeType* operator*() const { - assert(cycleNum < S.groups.size()); - return (*S.groups[cycleNum])[slotNum]; - } + inline _NodeType* operator*() const; inline _NodeType* operator->() const { return operator*(); } _Self& operator++(); // Preincrement @@ -201,10 +198,16 @@ } private: - friend class iterator; - friend class const_iterator; + friend class ScheduleIterator; + friend class ScheduleIterator; /*ctor*/ InstrSchedule (); // Disable: DO NOT IMPLEMENT. }; + +template +inline NodeType *ScheduleIterator::operator*() const { + assert(cycleNum < S.groups.size()); + return (*S.groups[cycleNum])[slotNum]; +} /*ctor*/ From lattner at cs.uiuc.edu Wed Nov 5 00:31:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Nov 5 00:31:01 2003 Subject: [llvm-commits] CVS: llvm-www/releases/1.0/docs/ReleaseNotes.html Message-ID: <200311050630.AAA00586@zion.cs.uiuc.edu> Changes in directory llvm-www/releases/1.0/docs: ReleaseNotes.html updated: 1.20 -> 1.21 --- Log message: 3 more bugz --- Diffs of the changes: (+7 -1) Index: llvm-www/releases/1.0/docs/ReleaseNotes.html diff -u llvm-www/releases/1.0/docs/ReleaseNotes.html:1.20 llvm-www/releases/1.0/docs/ReleaseNotes.html:1.21 --- llvm-www/releases/1.0/docs/ReleaseNotes.html:1.20 Tue Nov 4 14:10:56 2003 +++ llvm-www/releases/1.0/docs/ReleaseNotes.html Wed Nov 5 00:30:26 2003 @@ -179,6 +179,8 @@

    • [build problem] Callgraph.cpp not pulled in from libipa.a
    • +

    • [gccld] The -r (relinking) option does not work correctly
    • +


    Known problems with the C front-end

    Notes:

    • The C++ front-end is based on a pre-release of the GCC 3.4 C++ parser. This @@ -459,6 +465,6 @@ Maintained By: The LLVM Team
      -Last modified: Tue Nov 4 14:10:15 CST 2003 +Last modified: Wed Nov 5 00:07:37 CST 2003 From lattner at cs.uiuc.edu Wed Nov 5 00:31:04 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Nov 5 00:31:04 2003 Subject: [llvm-commits] CVS: llvm/docs/ReleaseNotes.html Message-ID: <200311050630.AAA00385@zion.cs.uiuc.edu> Changes in directory llvm/docs: ReleaseNotes.html updated: 1.30 -> 1.31 --- Log message: Add three more bugs --- Diffs of the changes: (+4 -3) Index: llvm/docs/ReleaseNotes.html diff -u llvm/docs/ReleaseNotes.html:1.30 llvm/docs/ReleaseNotes.html:1.31 --- llvm/docs/ReleaseNotes.html:1.30 Tue Nov 4 14:06:53 2003 +++ llvm/docs/ReleaseNotes.html Wed Nov 5 00:30:04 2003 @@ -66,8 +66,6 @@
      1. A new LLVM profiler, similar to gprof is available
      2. -
      3. temp
      4. -
      5. temp

      In this release, the following Quality of Implementation issues were fixed:

      @@ -98,6 +96,9 @@

    • CFrontend crashes when compiling C99 compound expressions
    • [X86] Emission of global bool initializers broken
    • llvm-gcc infinite loops on "case MAXINT:"
    • +
    • [C++] Catch blocks make unparsable labels
    • +
    • [C++] Initializing array with constructable objects fail
    • +
    • [gccld] The -r (relinking) option does not work correctly
    • At this time, LLVM is known to work properly with SPEC CPU 2000, the Olden @@ -404,6 +405,6 @@ Maintained By: The LLVM Team
      -Last modified: Tue Nov 4 14:05:01 CST 2003 +Last modified: Wed Nov 5 00:07:20 CST 2003 From brukman at cs.uiuc.edu Wed Nov 5 00:42:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed Nov 5 00:42:01 2003 Subject: [llvm-commits] CVS: llvm/Makefile.rules Message-ID: <200311050641.AAA06559@zion.cs.uiuc.edu> Changes in directory llvm: Makefile.rules updated: 1.153 -> 1.154 --- Log message: Output only the .y filename, not the full path to it for ease of reading. --- Diffs of the changes: (+1 -1) Index: llvm/Makefile.rules diff -u llvm/Makefile.rules:1.153 llvm/Makefile.rules:1.154 --- llvm/Makefile.rules:1.153 Mon Nov 3 15:12:49 2003 +++ llvm/Makefile.rules Wed Nov 5 00:41:14 2003 @@ -748,7 +748,7 @@ %.c: %.y # Cancel built-in rules for yacc %.h: %.y # Cancel built-in rules for yacc %.cpp %.h : %.y - @${ECHO} Bisoning $< + @${ECHO} "Bisoning `basename $<`" $(VERB) $(BISON) -v -d -p $( /dev/null || ${MV} -f $*.tab.c $*.cpp $(VERB) cmp -s $*.tab.h $*.h > /dev/null || ${MV} -f $*.tab.h $*.h From brukman at cs.uiuc.edu Wed Nov 5 00:44:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed Nov 5 00:44:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/Makefile Message-ID: <200311050643.AAA06587@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: Makefile updated: 1.13 -> 1.14 --- Log message: We know exactly what the value of $< is, so instead of using `basename $<` to get just the filename and not the full path, just use the filename directly. --- Diffs of the changes: (+7 -8) Index: llvm/lib/Target/X86/Makefile diff -u llvm/lib/Target/X86/Makefile:1.13 llvm/lib/Target/X86/Makefile:1.14 --- llvm/lib/Target/X86/Makefile:1.13 Mon Oct 20 17:26:57 2003 +++ llvm/lib/Target/X86/Makefile Wed Nov 5 00:43:36 2003 @@ -1,4 +1,4 @@ -##===- lib/Target/X86/Makefile ----------------------------*- Makefile -*-===## +##===- lib/Target/X86/Makefile -----------------------------*- Makefile -*-===## # # The LLVM Compiler Infrastructure # @@ -16,29 +16,28 @@ X86GenInstrInfo.inc X86GenInstrSelector.inc X86GenRegisterNames.inc:: X86.td X86RegisterInfo.td ../Target.td $(TBLGEN) - @echo "Building $< register names with tblgen" + @echo "Building X86.td register names with tblgen" $(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $< -gen-register-enums -o $@ X86GenRegisterInfo.h.inc:: X86.td X86RegisterInfo.td ../Target.td $(TBLGEN) - @echo "Building $< register information header with tblgen" + @echo "Building X86.td register information header with tblgen" $(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $< -gen-register-desc-header -o $@ X86GenRegisterInfo.inc:: X86.td X86RegisterInfo.td ../Target.td $(TBLGEN) - @echo "Building $< register information implementation with tblgen" + @echo "Building X86.td register information implementation with tblgen" $(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $< -gen-register-desc -o $@ X86GenInstrNames.inc:: X86.td X86InstrInfo.td ../Target.td $(TBLGEN) - @echo "Building $< instruction names with tblgen" + @echo "Building X86.td instruction names with tblgen" $(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $< -gen-instr-enums -o $@ X86GenInstrInfo.inc:: X86.td X86InstrInfo.td ../Target.td $(TBLGEN) - @echo "Building $< instruction information with tblgen" + @echo "Building X86.td instruction information with tblgen" $(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $< -gen-instr-desc -o $@ X86GenInstrSelector.inc:: X86.td X86InstrInfo.td ../Target.td $(TBLGEN) - @echo "Building $< instruction selector with tblgen" + @echo "Building X86.td instruction selector with tblgen" $(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $< -gen-instr-selector -o $@ clean:: $(VERB) rm -f *.inc - From alkis at cs.uiuc.edu Wed Nov 5 01:28:02 2003 From: alkis at cs.uiuc.edu (Alkis Evlogimenos) Date: Wed Nov 5 01:28:02 2003 Subject: [llvm-commits] [regalloc_linearscan] CVS: llvm/include/llvm/CodeGen/LiveIntervals.h Message-ID: <200311050727.BAA28295@morpheus.cs.uiuc.edu> Changes in directory llvm/include/llvm/CodeGen: LiveIntervals.h updated: 1.1.2.5 -> 1.1.2.6 --- Log message: Add and expose auxiliary data structures for use with the linear scan register allocator. --- Diffs of the changes: (+34 -4) Index: llvm/include/llvm/CodeGen/LiveIntervals.h diff -u llvm/include/llvm/CodeGen/LiveIntervals.h:1.1.2.5 llvm/include/llvm/CodeGen/LiveIntervals.h:1.1.2.6 --- llvm/include/llvm/CodeGen/LiveIntervals.h:1.1.2.5 Tue Nov 4 02:04:39 2003 +++ llvm/include/llvm/CodeGen/LiveIntervals.h Wed Nov 5 01:27:17 2003 @@ -43,6 +43,30 @@ } + unsigned start() const { + assert(!ranges.empty() && "empty interval for register"); + return ranges.front().first; + } + + unsigned end() const { + assert(!ranges.empty() && "empty interval for register"); + return ranges.back().second; + } + + bool expired(unsigned index) const { + return end() <= index; + } + + bool overlaps(unsigned index) const { + for (Ranges::const_iterator i = ranges.begin(), e = ranges.end(); + i != e; ++i) { + if (index >= i->first && index < i->second) { + return true; + } + } + return false; + } + void addRange(unsigned start, unsigned end) { Range range = std::make_pair(start, end); Ranges::iterator it = @@ -97,6 +121,8 @@ }; typedef std::vector Intervals; + typedef std::map MiIndex2MbbMap; + typedef std::map Mbb2MiIndexMap; private: MachineFunction* mf_; @@ -106,20 +132,24 @@ MachineBasicBlock::iterator currentInstr_; LiveVariables* lv_; - typedef std::map Index2MbbMap; - Index2MbbMap i2mbbMap_; + typedef std::map MbbIndex2MbbMap; + MbbIndex2MbbMap mbbi2mbbMap_; typedef std::map Mi2IndexMap; Mi2IndexMap mi2iMap_; - Intervals intervals_; - typedef std::map Reg2IntervalMap; Reg2IntervalMap r2iMap_; + Intervals intervals_; + MiIndex2MbbMap mii2mbbMap_; + Mbb2MiIndexMap mbb2miiMap_; + public: virtual void getAnalysisUsage(AnalysisUsage &AU) const; Intervals& getIntervals() { return intervals_; } + MiIndex2MbbMap& getMiIndex2MbbMap() { return mii2mbbMap_; } + Mbb2MiIndexMap& getMbb2MiIndexMap() { return mbb2miiMap_; } private: /// runOnMachineFunction - pass entry point From alkis at cs.uiuc.edu Wed Nov 5 01:28:09 2003 From: alkis at cs.uiuc.edu (Alkis Evlogimenos) Date: Wed Nov 5 01:28:09 2003 Subject: [llvm-commits] [regalloc_linearscan] CVS: llvm/lib/CodeGen/LiveIntervals.cpp Message-ID: <200311050727.BAA28288@morpheus.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: LiveIntervals.cpp updated: 1.1.2.5 -> 1.1.2.6 --- Log message: Add and expose auxiliary data structures for use with the linear scan register allocator. --- Diffs of the changes: (+13 -6) Index: llvm/lib/CodeGen/LiveIntervals.cpp diff -u llvm/lib/CodeGen/LiveIntervals.cpp:1.1.2.5 llvm/lib/CodeGen/LiveIntervals.cpp:1.1.2.6 --- llvm/lib/CodeGen/LiveIntervals.cpp:1.1.2.5 Tue Nov 4 01:57:28 2003 +++ llvm/lib/CodeGen/LiveIntervals.cpp Wed Nov 5 01:27:16 2003 @@ -64,14 +64,20 @@ mbb != mbbEnd; ++mbb) { const std::pair& entry = lv_->getMachineBasicBlockInfo(&*mbb); - bool inserted = i2mbbMap_.insert(std::make_pair(entry.second, - entry.first)).second; + bool inserted = mbbi2mbbMap_.insert(std::make_pair(entry.second, + entry.first)).second; assert(inserted && "multiple index -> MachineBasicBlock"); + inserted = mbb2miiMap_.insert(std::make_pair(&*mbb, miIndex)).second; + assert(inserted && "multiple MachineBasicBlock -> index mappings"); for (MachineBasicBlock::iterator mi = mbb->begin(), miEnd = mbb->end(); mi != miEnd; ++mi) { - inserted = mi2iMap_.insert(std::make_pair(*mi, miIndex++)).second; + inserted = mi2iMap_.insert(std::make_pair(*mi, miIndex)).second; assert(inserted && "multiple MachineInstr -> index mappings"); + inserted = + mii2mbbMap_.insert(std::make_pair(miIndex, &*mbb)).second; + assert(inserted && "multiple index -> MachineBasicBlock mappings"); + ++miIndex; } } @@ -121,8 +127,8 @@ interval.addRange(start, end); } - for (Index2MbbMap::iterator - it = i2mbbMap_.begin(), itEnd = i2mbbMap_.end(); + for (MbbIndex2MbbMap::iterator + it = mbbi2mbbMap_.begin(), itEnd = mbbi2mbbMap_.end(); it != itEnd; ++it) { unsigned mbbIndex = it->first; MachineBasicBlock* mbb2 = it->second; @@ -158,7 +164,8 @@ { DEBUG(std::cerr << "computing live intervals:\n"); - for (Index2MbbMap::iterator it = i2mbbMap_.begin(), itEnd = i2mbbMap_.end(); + for (MbbIndex2MbbMap::iterator + it = mbbi2mbbMap_.begin(), itEnd = mbbi2mbbMap_.end(); it != itEnd; ++it) { MachineBasicBlock* mbb = it->second; DEBUG(std::cerr << "machine basic block: " From lattner at cs.uiuc.edu Wed Nov 5 11:32:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Nov 5 11:32:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200311051731.LAA13200@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.140 -> 1.141 --- Log message: Fix flawed logic that was breaking several SPEC benchmarks, including gzip and crafty. --- Diffs of the changes: (+3 -3) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.140 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.141 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.140 Tue Nov 4 19:06:05 2003 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Wed Nov 5 11:31:36 2003 @@ -1337,8 +1337,8 @@ // because the source would be zero extended. unsigned SrcBits = SrcTy == Type::BoolTy ? 1 : SrcTy->getPrimitiveSize()*8; - bool HasSignBit = 1ULL << (DestTy->getPrimitiveSize()*8-1); - if (ConstVal & ((1ULL << SrcBits)-1)) { + bool HasSignBit = ConstVal & (1ULL << (DestTy->getPrimitiveSize()*8-1)); + if (ConstVal & ~((1ULL << SrcBits)-1)) { switch (I.getOpcode()) { default: assert(0 && "Unknown comparison type!"); case Instruction::SetEQ: @@ -1655,7 +1655,7 @@ unsigned AllocElTySize = TD->getTypeSize(AllocElTy); const Type *CastElTy = PTy->getElementType(); unsigned CastElTySize = TD->getTypeSize(CastElTy); - + // If the allocation is for an even multiple of the cast type size if (CastElTySize && (AllocElTySize % CastElTySize == 0)) { Value *Amt = ConstantUInt::get(Type::UIntTy, From lattner at cs.uiuc.edu Wed Nov 5 13:10:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Nov 5 13:10:02 2003 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Value.cpp Message-ID: <200311051909.NAA29526@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Value.cpp updated: 1.38 -> 1.39 --- Log message: If we're not checking, don't check! --- Diffs of the changes: (+1 -1) Index: llvm/lib/VMCore/Value.cpp diff -u llvm/lib/VMCore/Value.cpp:1.38 llvm/lib/VMCore/Value.cpp:1.39 --- llvm/lib/VMCore/Value.cpp:1.38 Mon Oct 20 14:43:21 2003 +++ llvm/lib/VMCore/Value.cpp Wed Nov 5 13:09:40 2003 @@ -66,7 +66,7 @@ // Must handle Constants specially, we cannot call replaceUsesOfWith on a // constant! if (Constant *C = dyn_cast(U.getUser())) { - C->replaceUsesOfWithOnConstant(this, New); + C->replaceUsesOfWithOnConstant(this, New, true); } else { U.set(New); } From lattner at cs.uiuc.edu Wed Nov 5 13:44:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Nov 5 13:44:00 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Assembler/2003-10-05-ConstantExprShift.llx Message-ID: <200311051943.NAA07864@neo.cs.uiuc.edu> Changes in directory llvm/test/Regression/Assembler: 2003-10-05-ConstantExprShift.llx added (r1.1) --- Log message: New testcase --- Diffs of the changes: (+5 -0) Index: llvm/test/Regression/Assembler/2003-10-05-ConstantExprShift.llx diff -c /dev/null llvm/test/Regression/Assembler/2003-10-05-ConstantExprShift.llx:1.1 *** /dev/null Wed Nov 5 13:43:50 2003 --- llvm/test/Regression/Assembler/2003-10-05-ConstantExprShift.llx Wed Nov 5 13:43:36 2003 *************** *** 0 **** --- 1,5 ---- + ; RUN: llvm-as < %s | llvm-dis + + int %test() { + ret int shr (int cast (int()* %test to int), ubyte 2) + } From brukman at cs.uiuc.edu Wed Nov 5 13:49:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed Nov 5 13:49:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Target/MRegisterInfo.h Message-ID: <200311051948.NAA32720@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Target: MRegisterInfo.h updated: 1.24 -> 1.25 --- Log message: Since this function returns an int, let's actually return something. --- Diffs of the changes: (+1 -0) Index: llvm/include/llvm/Target/MRegisterInfo.h diff -u llvm/include/llvm/Target/MRegisterInfo.h:1.24 llvm/include/llvm/Target/MRegisterInfo.h:1.25 --- llvm/include/llvm/Target/MRegisterInfo.h:1.24 Tue Nov 4 17:07:00 2003 +++ llvm/include/llvm/Target/MRegisterInfo.h Wed Nov 5 13:48:05 2003 @@ -246,6 +246,7 @@ "eliminateCallFramePseudoInstr must be implemented if using" " call frame setup/destroy pseudo instructions!"); assert(0 && "Call Frame Pseudo Instructions do not exist on this target!"); + return -1; } /// processFunctionBeforeFrameFinalized - This method is called immediately From lattner at cs.uiuc.edu Wed Nov 5 13:54:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Nov 5 13:54:02 2003 Subject: [llvm-commits] CVS: llvm/lib/Bytecode/Reader/ReaderInternals.h Message-ID: <200311051953.NAA01199@zion.cs.uiuc.edu> Changes in directory llvm/lib/Bytecode/Reader: ReaderInternals.h updated: 1.62 -> 1.63 --- Log message: no need for endl --- Diffs of the changes: (+1 -1) Index: llvm/lib/Bytecode/Reader/ReaderInternals.h diff -u llvm/lib/Bytecode/Reader/ReaderInternals.h:1.62 llvm/lib/Bytecode/Reader/ReaderInternals.h:1.63 --- llvm/lib/Bytecode/Reader/ReaderInternals.h:1.62 Thu Oct 30 12:33:58 2003 +++ llvm/lib/Bytecode/Reader/ReaderInternals.h Wed Nov 5 13:53:32 2003 @@ -219,7 +219,7 @@ #ifdef DEBUG_OUTPUT bool Result = read(Buf, EndBuf, Type) || read(Buf, EndBuf, Size); std::cerr << "StartLoc = " << ((unsigned)Buf & 4095) - << " Type = " << Type << " Size = " << Size << std::endl; + << " Type = " << Type << " Size = " << Size << "\n"; if (Result) throw Error_read; #else if (read(Buf, EndBuf, Type) || read(Buf, EndBuf, Size)) throw Error_read; From lattner at cs.uiuc.edu Wed Nov 5 13:54:06 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Nov 5 13:54:06 2003 Subject: [llvm-commits] CVS: llvm/lib/Bytecode/Reader/ConstantReader.cpp Message-ID: <200311051953.NAA01184@zion.cs.uiuc.edu> Changes in directory llvm/lib/Bytecode/Reader: ConstantReader.cpp updated: 1.60 -> 1.61 --- Log message: Add support for constant expr shifts --- Diffs of the changes: (+2 -0) Index: llvm/lib/Bytecode/Reader/ConstantReader.cpp diff -u llvm/lib/Bytecode/Reader/ConstantReader.cpp:1.60 llvm/lib/Bytecode/Reader/ConstantReader.cpp:1.61 --- llvm/lib/Bytecode/Reader/ConstantReader.cpp:1.60 Mon Oct 20 14:43:14 2003 +++ llvm/lib/Bytecode/Reader/ConstantReader.cpp Wed Nov 5 13:53:03 2003 @@ -182,6 +182,8 @@ } else if (Opcode == Instruction::GetElementPtr) { // GetElementPtr std::vector IdxList(ArgVec.begin()+1, ArgVec.end()); return ConstantExpr::getGetElementPtr(ArgVec[0], IdxList); + } else if (Opcode == Instruction::Shl || Opcode == Instruction::Shr) { + return ConstantExpr::getShift(Opcode, ArgVec[0], ArgVec[1]); } else { // All other 2-operand expressions return ConstantExpr::get(Opcode, ArgVec[0], ArgVec[1]); } From lattner at cs.uiuc.edu Wed Nov 5 13:54:09 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Nov 5 13:54:09 2003 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Constants.cpp Message-ID: <200311051953.NAA01171@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Constants.cpp updated: 1.60 -> 1.61 --- Log message: Add support for constant expr shifts --- Diffs of the changes: (+7 -0) Index: llvm/lib/VMCore/Constants.cpp diff -u llvm/lib/VMCore/Constants.cpp:1.60 llvm/lib/VMCore/Constants.cpp:1.61 --- llvm/lib/VMCore/Constants.cpp:1.60 Thu Oct 23 00:21:48 2003 +++ llvm/lib/VMCore/Constants.cpp Wed Nov 5 13:52:52 2003 @@ -493,6 +493,13 @@ } else if (getOpcode() == Instruction::Cast) { assert(getOperand(0) == From && "Cast only has one use!"); Replacement = ConstantExpr::getCast(To, getType()); + } else if (getOpcode() == Instruction::Shl || + getOpcode() == Instruction::Shr) { + Constant *C1 = getOperand(0); + Constant *C2 = getOperand(1); + if (C1 == From) C1 = To; + if (C2 == From) C2 = To; + Replacement = ConstantExpr::getShift(getOpcode(), C1, C2); } else if (getNumOperands() == 2) { Constant *C1 = getOperand(0); Constant *C2 = getOperand(1); From gaeke at cs.uiuc.edu Wed Nov 5 14:26:01 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Wed Nov 5 14:26:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Support/CallSite.h Message-ID: <200311052025.OAA16827@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Support: CallSite.h updated: 1.10 -> 1.11 --- Log message: A few handy methods that seem to mesh well with what CallSite already provides. --- Diffs of the changes: (+5 -0) Index: llvm/include/llvm/Support/CallSite.h diff -u llvm/include/llvm/Support/CallSite.h:1.10 llvm/include/llvm/Support/CallSite.h:1.11 --- llvm/include/llvm/Support/CallSite.h:1.10 Sun Nov 2 17:04:33 2003 +++ llvm/include/llvm/Support/CallSite.h Wed Nov 5 14:25:33 2003 @@ -44,6 +44,10 @@ return CallSite(); } + /// getType - Return the type of the instruction that generated this call site + /// + const Type *getType () const { return I->getType (); } + /// getInstruction - Return the instruction this call site corresponds to /// Instruction *getInstruction() const { return I; } @@ -83,6 +87,7 @@ return I->op_begin()+3; // Skip Function, BB, BB } arg_iterator arg_end() const { return I->op_end(); } + unsigned arg_size() const { return arg_end() - arg_begin(); } bool operator<(const CallSite &CS) const { return getInstruction() < CS.getInstruction(); From lattner at cs.uiuc.edu Wed Nov 5 14:38:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Nov 5 14:38:02 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/Linker.cpp Message-ID: <200311052037.OAA29801@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: Linker.cpp updated: 1.61 -> 1.62 --- Log message: Further fixes for PR93 --- Diffs of the changes: (+7 -1) Index: llvm/lib/Transforms/Utils/Linker.cpp diff -u llvm/lib/Transforms/Utils/Linker.cpp:1.61 llvm/lib/Transforms/Utils/Linker.cpp:1.62 --- llvm/lib/Transforms/Utils/Linker.cpp:1.61 Tue Nov 4 09:22:26 2003 +++ llvm/lib/Transforms/Utils/Linker.cpp Wed Nov 5 14:37:01 2003 @@ -318,13 +318,19 @@ assert(CE->getOpcode() == Instruction::Cast); Value *V = RemapOperand(CE->getOperand(0), LocalMap, GlobalMap); Result = ConstantExpr::getCast(cast(V), CE->getType()); + } else if (CE->getOpcode() == Instruction::Shl || + CE->getOpcode() == Instruction::Shr) { // Shift + Value *V1 = RemapOperand(CE->getOperand(0), LocalMap, GlobalMap); + Value *V2 = RemapOperand(CE->getOperand(1), LocalMap, GlobalMap); + Result = ConstantExpr::getShift(CE->getOpcode(), cast(V1), + cast(V2)); } else if (CE->getNumOperands() == 2) { // Binary operator... Value *V1 = RemapOperand(CE->getOperand(0), LocalMap, GlobalMap); Value *V2 = RemapOperand(CE->getOperand(1), LocalMap, GlobalMap); Result = ConstantExpr::get(CE->getOpcode(), cast(V1), - cast(V2)); + cast(V2)); } else { assert(0 && "Unknown constant expr type!"); } From lattner at cs.uiuc.edu Wed Nov 5 14:45:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Nov 5 14:45:02 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/ValueMapper.cpp Message-ID: <200311052044.OAA31927@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: ValueMapper.cpp updated: 1.6 -> 1.7 --- Log message: Yet more fixes for constant expr shifts --- Diffs of the changes: (+6 -0) Index: llvm/lib/Transforms/Utils/ValueMapper.cpp diff -u llvm/lib/Transforms/Utils/ValueMapper.cpp:1.6 llvm/lib/Transforms/Utils/ValueMapper.cpp:1.7 --- llvm/lib/Transforms/Utils/ValueMapper.cpp:1.6 Mon Oct 20 14:43:20 2003 +++ llvm/lib/Transforms/Utils/ValueMapper.cpp Wed Nov 5 14:43:58 2003 @@ -82,6 +82,12 @@ for (unsigned i = 1, e = CE->getNumOperands(); i != e; ++i) Idx.push_back(cast(MapValue(CE->getOperand(i), VM))); return VMSlot = ConstantExpr::getGetElementPtr(MV, Idx); + } else if (CE->getOpcode() == Instruction::Shl || + CE->getOpcode() == Instruction::Shr) { + assert(CE->getNumOperands() == 2 && "Must be a shift!"); + Constant *MV1 = cast(MapValue(CE->getOperand(0), VM)); + Constant *MV2 = cast(MapValue(CE->getOperand(1), VM)); + return VMSlot = ConstantExpr::getShift(CE->getOpcode(), MV1, MV2); } else { assert(CE->getNumOperands() == 2 && "Must be binary operator?"); Constant *MV1 = cast(MapValue(CE->getOperand(0), VM)); From lattner at cs.uiuc.edu Wed Nov 5 15:16:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Nov 5 15:16:01 2003 Subject: [llvm-commits] CVS: llvm/tools/bugpoint/BugDriver.h CodeGeneratorBug.cpp CrashDebugger.cpp ExtractFunction.cpp Message-ID: <200311052115.PAA07104@zion.cs.uiuc.edu> Changes in directory llvm/tools/bugpoint: BugDriver.h updated: 1.19 -> 1.20 CodeGeneratorBug.cpp updated: 1.29 -> 1.30 CrashDebugger.cpp updated: 1.22 -> 1.23 ExtractFunction.cpp updated: 1.17 -> 1.18 --- Log message: Simplify the performFinalCleanups interface --- Diffs of the changes: (+11 -13) Index: llvm/tools/bugpoint/BugDriver.h diff -u llvm/tools/bugpoint/BugDriver.h:1.19 llvm/tools/bugpoint/BugDriver.h:1.20 --- llvm/tools/bugpoint/BugDriver.h:1.19 Mon Oct 20 12:57:12 2003 +++ llvm/tools/bugpoint/BugDriver.h Wed Nov 5 15:15:19 2003 @@ -158,11 +158,11 @@ Module *deleteInstructionFromProgram(Instruction *I, unsigned Simp) const; /// performFinalCleanups - This method clones the current Program and performs - /// a series of cleanups intended to get rid of extra cruft on the module - /// before handing it to the user... if the module parameter is specified, it - /// operates directly on the specified Module, modifying it in place. + /// a series of cleanups intended to get rid of extra cruft on the module. If + /// the MayModifySemantics argument is true, then the cleanups is allowed to + /// modify how the code behaves. /// - Module *performFinalCleanups(Module *M = 0) const; + void performFinalCleanups(Module *M, bool MayModifySemantics = false) const; /// initializeExecutionEnvironment - This method is used to set up the /// environment for executing LLVM programs. Index: llvm/tools/bugpoint/CodeGeneratorBug.cpp diff -u llvm/tools/bugpoint/CodeGeneratorBug.cpp:1.29 llvm/tools/bugpoint/CodeGeneratorBug.cpp:1.30 --- llvm/tools/bugpoint/CodeGeneratorBug.cpp:1.29 Mon Oct 20 14:43:47 2003 +++ llvm/tools/bugpoint/CodeGeneratorBug.cpp Wed Nov 5 15:15:19 2003 @@ -224,8 +224,8 @@ } // Clean up the modules, removing extra cruft that we don't need anymore... - SafeModule = BD.performFinalCleanups(SafeModule); - TestModule = BD.performFinalCleanups(TestModule); + BD.performFinalCleanups(SafeModule); + BD.performFinalCleanups(TestModule); if (BD.writeProgramToFile(TestModuleBC, TestModule)) { std::cerr << "Error writing bytecode to `" << SafeModuleBC << "'\nExiting."; Index: llvm/tools/bugpoint/CrashDebugger.cpp diff -u llvm/tools/bugpoint/CrashDebugger.cpp:1.22 llvm/tools/bugpoint/CrashDebugger.cpp:1.23 --- llvm/tools/bugpoint/CrashDebugger.cpp:1.22 Sun Oct 26 22:44:59 2003 +++ llvm/tools/bugpoint/CrashDebugger.cpp Wed Nov 5 15:15:19 2003 @@ -378,7 +378,8 @@ // Try to clean up the testcase by running funcresolve and globaldce... std::cout << "\n*** Attempting to perform final cleanups: "; - Module *M = performFinalCleanups(); + Module *M = CloneModule(Program); + performFinalCleanups(M, true); std::swap(Program, M); // Find out if the pass still crashes on the cleaned up program... Index: llvm/tools/bugpoint/ExtractFunction.cpp diff -u llvm/tools/bugpoint/ExtractFunction.cpp:1.17 llvm/tools/bugpoint/ExtractFunction.cpp:1.18 --- llvm/tools/bugpoint/ExtractFunction.cpp:1.17 Thu Oct 23 10:42:55 2003 +++ llvm/tools/bugpoint/ExtractFunction.cpp Wed Nov 5 15:15:19 2003 @@ -93,15 +93,13 @@ /// a series of cleanups intended to get rid of extra cruft on the module /// before handing it to the user... /// -Module *BugDriver::performFinalCleanups(Module *InM) const { - Module *M = InM ? InM : CloneModule(Program); - +void BugDriver::performFinalCleanups(Module *M, bool MayModifySemantics) const { // Allow disabling these passes if they crash bugpoint. // // FIXME: This should eventually run these passes in a pass list to prevent // them from being able to crash bugpoint at all! // - if (NoFinalCleanup) return M; + if (NoFinalCleanup) return; // Make all functions external, so GlobalDCE doesn't delete them... for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) @@ -113,8 +111,7 @@ CleanupPasses.add(createFunctionResolvingPass()); CleanupPasses.add(createGlobalDCEPass()); CleanupPasses.add(createDeadTypeEliminationPass()); - CleanupPasses.add(createDeadArgEliminationPass(InM == 0)); + CleanupPasses.add(createDeadArgEliminationPass(MayModifySemantics)); CleanupPasses.add(createVerifierPass()); CleanupPasses.run(*M); - return M; } From lattner at cs.uiuc.edu Wed Nov 5 15:44:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Nov 5 15:44:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Transforms/IPO.h Message-ID: <200311052143.PAA13295@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Transforms: IPO.h updated: 1.23 -> 1.24 --- Log message: Split the DAE pass into DAE and DAH passes --- Diffs of the changes: (+6 -5) Index: llvm/include/llvm/Transforms/IPO.h diff -u llvm/include/llvm/Transforms/IPO.h:1.23 llvm/include/llvm/Transforms/IPO.h:1.24 --- llvm/include/llvm/Transforms/IPO.h:1.23 Thu Oct 23 11:51:49 2003 +++ llvm/include/llvm/Transforms/IPO.h Wed Nov 5 15:43:42 2003 @@ -97,12 +97,13 @@ //===----------------------------------------------------------------------===// // createDeadArgEliminationPass - This pass removes arguments from functions -// which are not used by the body of the function. If -// DeleteFromExternalFunctions is true, the pass will modify functions that have -// external linkage, which is not usually safe (this is used by bugpoint to -// reduce testcases). +// which are not used by the body of the function. // -Pass *createDeadArgEliminationPass(bool DeleteFromExternalFunctions=false); +Pass *createDeadArgEliminationPass(); + +// DeadArgHacking pass - Same as DAE, but delete arguments of external functions +// as well. This is definately not safe, and should only be used by bugpoint. +Pass *createDeadArgHackingPass(); //===----------------------------------------------------------------------===// // createIPConstantPropagationPass - This pass propagates constants from call From lattner at cs.uiuc.edu Wed Nov 5 15:44:05 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Nov 5 15:44:05 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp Message-ID: <200311052143.PAA13224@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: DeadArgumentElimination.cpp updated: 1.10 -> 1.11 --- Log message: Split behavior into two pieces --- Diffs of the changes: (+13 -13) Index: llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp diff -u llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp:1.10 llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp:1.11 --- llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp:1.10 Sat Nov 1 20:06:27 2003 +++ llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp Wed Nov 5 15:43:02 2003 @@ -39,10 +39,6 @@ /// DAE - The dead argument elimination pass. /// class DAE : public Pass { - /// DeleteFromExternalFunctions - Bugpoint sets this flag to indicate that - /// it is safe to hack apart functions without internal linkage. - bool DeleteFromExternalFunctions; - /// Liveness enum - During our initial pass over the program, we determine /// that things are either definately alive, definately dead, or in need of /// interprocedural analysis (MaybeLive). @@ -79,9 +75,10 @@ std::multimap CallSites; public: - DAE(bool DFEF = false) : DeleteFromExternalFunctions(DFEF) {} bool run(Module &M); + virtual bool ShouldHackArguments() const { return false; } + private: Liveness getArgumentLiveness(const Argument &A); bool isMaybeLiveArgumentNowLive(Argument *Arg); @@ -95,17 +92,20 @@ void RemoveDeadArgumentsFromFunction(Function *F); }; RegisterOpt X("deadargelim", "Dead Argument Elimination"); + + /// DAH - DeadArgumentHacking pass - Same as dead argument elimination, but + /// deletes arguments to functions which are external. This is only for use + /// by bugpoint. + struct DAH : public DAE { + virtual bool ShouldHackArguments() const { return true; } + }; } /// createDeadArgEliminationPass - This pass removes arguments from functions -/// which are not used by the body of the function. If -/// DeleteFromExternalFunctions is true, the pass will modify functions that -/// have external linkage, which is not usually safe (this is used by bugpoint -/// to reduce testcases). +/// which are not used by the body of the function. /// -Pass *createDeadArgEliminationPass(bool DeleteFromExternalFunctions) { - return new DAE(DeleteFromExternalFunctions); -} +Pass *createDeadArgEliminationPass() { return new DAE(); } +Pass *createDeadArgHackingPass() { return new DAH(); } static inline bool CallPassesValueThoughVararg(Instruction *Call, const Value *Arg) { @@ -163,7 +163,7 @@ bool FunctionIntrinsicallyLive = false; Liveness RetValLiveness = F.getReturnType() == Type::VoidTy ? Live : Dead; - if (!F.hasInternalLinkage() && !DeleteFromExternalFunctions) + if (!F.hasInternalLinkage() && !ShouldHackArguments()) FunctionIntrinsicallyLive = true; else for (Value::use_iterator I = F.use_begin(), E = F.use_end(); I != E; ++I) { From lattner at cs.uiuc.edu Wed Nov 5 15:46:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Nov 5 15:46:01 2003 Subject: [llvm-commits] CVS: llvm/tools/bugpoint/BugDriver.h CodeGeneratorBug.cpp CrashDebugger.cpp ExtractFunction.cpp Message-ID: <200311052145.PAA13720@zion.cs.uiuc.edu> Changes in directory llvm/tools/bugpoint: BugDriver.h updated: 1.20 -> 1.21 CodeGeneratorBug.cpp updated: 1.30 -> 1.31 CrashDebugger.cpp updated: 1.23 -> 1.24 ExtractFunction.cpp updated: 1.18 -> 1.19 --- Log message: I hate it when bugpoint is all ready to give me a bytecode file, then crashes in final cleanups. Then you had to run the whole mess again with -disable-final-cleanups. This makes bugpoint run the cleanups in a protected environment so that if they crash, bugpoint itself doesn't crash. This makes things much happier, implements a FIXME, and gets rid of YABPO (yet another bugpoint option). --- Diffs of the changes: (+35 -25) Index: llvm/tools/bugpoint/BugDriver.h diff -u llvm/tools/bugpoint/BugDriver.h:1.20 llvm/tools/bugpoint/BugDriver.h:1.21 --- llvm/tools/bugpoint/BugDriver.h:1.20 Wed Nov 5 15:15:19 2003 +++ llvm/tools/bugpoint/BugDriver.h Wed Nov 5 15:45:35 2003 @@ -120,7 +120,7 @@ /// EmitProgressBytecode - This function is used to output the current Program - /// to a file named "bugpoing-ID.bc". + /// to a file named "bugpoint-ID.bc". /// void EmitProgressBytecode(const std::string &ID, bool NoFlyer = false); @@ -162,7 +162,7 @@ /// the MayModifySemantics argument is true, then the cleanups is allowed to /// modify how the code behaves. /// - void performFinalCleanups(Module *M, bool MayModifySemantics = false) const; + Module *performFinalCleanups(Module *M, bool MayModifySemantics = false); /// initializeExecutionEnvironment - This method is used to set up the /// environment for executing LLVM programs. Index: llvm/tools/bugpoint/CodeGeneratorBug.cpp diff -u llvm/tools/bugpoint/CodeGeneratorBug.cpp:1.30 llvm/tools/bugpoint/CodeGeneratorBug.cpp:1.31 --- llvm/tools/bugpoint/CodeGeneratorBug.cpp:1.30 Wed Nov 5 15:15:19 2003 +++ llvm/tools/bugpoint/CodeGeneratorBug.cpp Wed Nov 5 15:45:35 2003 @@ -224,8 +224,8 @@ } // Clean up the modules, removing extra cruft that we don't need anymore... - BD.performFinalCleanups(SafeModule); - BD.performFinalCleanups(TestModule); + SafeModule = BD.performFinalCleanups(SafeModule); + TestModule = BD.performFinalCleanups(TestModule); if (BD.writeProgramToFile(TestModuleBC, TestModule)) { std::cerr << "Error writing bytecode to `" << SafeModuleBC << "'\nExiting."; Index: llvm/tools/bugpoint/CrashDebugger.cpp diff -u llvm/tools/bugpoint/CrashDebugger.cpp:1.23 llvm/tools/bugpoint/CrashDebugger.cpp:1.24 --- llvm/tools/bugpoint/CrashDebugger.cpp:1.23 Wed Nov 5 15:15:19 2003 +++ llvm/tools/bugpoint/CrashDebugger.cpp Wed Nov 5 15:45:35 2003 @@ -379,7 +379,7 @@ // Try to clean up the testcase by running funcresolve and globaldce... std::cout << "\n*** Attempting to perform final cleanups: "; Module *M = CloneModule(Program); - performFinalCleanups(M, true); + M = performFinalCleanups(M, true); std::swap(Program, M); // Find out if the pass still crashes on the cleaned up program... Index: llvm/tools/bugpoint/ExtractFunction.cpp diff -u llvm/tools/bugpoint/ExtractFunction.cpp:1.18 llvm/tools/bugpoint/ExtractFunction.cpp:1.19 --- llvm/tools/bugpoint/ExtractFunction.cpp:1.18 Wed Nov 5 15:15:19 2003 +++ llvm/tools/bugpoint/ExtractFunction.cpp Wed Nov 5 15:45:35 2003 @@ -37,9 +37,6 @@ cl::opt NoSCFG("disable-simplifycfg", cl::location(DisableSimplifyCFG), cl::desc("Do not use the -simplifycfg pass to reduce testcases")); - cl::opt - NoFinalCleanup("disable-final-cleanup", - cl::desc("Disable the final cleanup phase of narrowing")); } /// deleteInstructionFromProgram - This method clones the current Program and @@ -89,29 +86,42 @@ return Result; } +static const PassInfo *getPI(Pass *P) { + const PassInfo *PI = P->getPassInfo(); + delete P; + return PI; +} + /// performFinalCleanups - This method clones the current Program and performs /// a series of cleanups intended to get rid of extra cruft on the module /// before handing it to the user... /// -void BugDriver::performFinalCleanups(Module *M, bool MayModifySemantics) const { - // Allow disabling these passes if they crash bugpoint. - // - // FIXME: This should eventually run these passes in a pass list to prevent - // them from being able to crash bugpoint at all! - // - if (NoFinalCleanup) return; - +Module *BugDriver::performFinalCleanups(Module *M, bool MayModifySemantics) { // Make all functions external, so GlobalDCE doesn't delete them... for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) I->setLinkage(GlobalValue::ExternalLinkage); - PassManager CleanupPasses; - // Make sure that the appropriate target data is always used... - CleanupPasses.add(new TargetData("bugpoint", M)); - CleanupPasses.add(createFunctionResolvingPass()); - CleanupPasses.add(createGlobalDCEPass()); - CleanupPasses.add(createDeadTypeEliminationPass()); - CleanupPasses.add(createDeadArgEliminationPass(MayModifySemantics)); - CleanupPasses.add(createVerifierPass()); - CleanupPasses.run(*M); + std::vector CleanupPasses; + CleanupPasses.push_back(getPI(createFunctionResolvingPass())); + CleanupPasses.push_back(getPI(createGlobalDCEPass())); + CleanupPasses.push_back(getPI(createDeadTypeEliminationPass())); + CleanupPasses.push_back(getPI(createDeadArgHackingPass())); + + std::swap(Program, M); + std::string Filename; + bool Failed = runPasses(CleanupPasses, Filename); + std::swap(Program, M); + + if (Failed) { + std::cerr << "Final cleanups failed. Sorry. :(\n"; + } else { + delete M; + M = ParseInputFile(Filename); + if (M == 0) { + std::cerr << getToolName() << ": Error reading bytecode file '" + << Filename << "'!\n"; + exit(1); + } + } + return M; } From lattner at cs.uiuc.edu Wed Nov 5 15:47:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Nov 5 15:47:01 2003 Subject: [llvm-commits] CVS: llvm/docs/CommandGuide/bugpoint.html Message-ID: <200311052146.PAA13949@zion.cs.uiuc.edu> Changes in directory llvm/docs/CommandGuide: bugpoint.html updated: 1.18 -> 1.19 --- Log message: Bugpoint no longer has this option --- Diffs of the changes: (+1 -1) Index: llvm/docs/CommandGuide/bugpoint.html diff -u llvm/docs/CommandGuide/bugpoint.html:1.18 llvm/docs/CommandGuide/bugpoint.html:1.19 --- llvm/docs/CommandGuide/bugpoint.html:1.18 Mon Oct 20 14:47:25 2003 +++ llvm/docs/CommandGuide/bugpoint.html Wed Nov 5 15:46:13 2003 @@ -175,7 +175,7 @@ part of the -args option, not as options to bugpoint itself.

      -

    • -disable-{adce,dce,final-cleanup,simplifycfg}
      +
    • -disable-{adce,dce,simplifycfg}
      Do not run the specified passes to clean up and reduce the size of the test program. By default, bugpoint uses these passes internally when attempting to reduce test programs. If you're trying to find From lattner at cs.uiuc.edu Wed Nov 5 15:54:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Nov 5 15:54:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp Message-ID: <200311052153.PAA15795@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: DeadArgumentElimination.cpp updated: 1.11 -> 1.12 --- Log message: Fix the problem with running cleanups in bugpoint: We were deleting arguments of intrinsic functions, causing the verifier to fail. --- Diffs of the changes: (+4 -1) Index: llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp diff -u llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp:1.11 llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp:1.12 --- llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp:1.11 Wed Nov 5 15:43:02 2003 +++ llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp Wed Nov 5 15:53:41 2003 @@ -99,6 +99,8 @@ struct DAH : public DAE { virtual bool ShouldHackArguments() const { return true; } }; + RegisterPass Y("deadarghaX0r", + "Dead Argument Hacking (bugpoint usage only)"); } /// createDeadArgEliminationPass - This pass removes arguments from functions @@ -163,7 +165,8 @@ bool FunctionIntrinsicallyLive = false; Liveness RetValLiveness = F.getReturnType() == Type::VoidTy ? Live : Dead; - if (!F.hasInternalLinkage() && !ShouldHackArguments()) + if (!F.hasInternalLinkage() && + (!ShouldHackArguments() || F.getIntrinsicID())) FunctionIntrinsicallyLive = true; else for (Value::use_iterator I = F.use_begin(), E = F.use_end(); I != E; ++I) { From lattner at cs.uiuc.edu Wed Nov 5 16:07:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Nov 5 16:07:02 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/LowerSetJmp/2003-11-05-DominanceProperties.ll Message-ID: <200311052206.QAA17768@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/LowerSetJmp: 2003-11-05-DominanceProperties.ll added (r1.1) --- Log message: new testcase --- Diffs of the changes: (+16 -0) Index: llvm/test/Regression/Transforms/LowerSetJmp/2003-11-05-DominanceProperties.ll diff -c /dev/null llvm/test/Regression/Transforms/LowerSetJmp/2003-11-05-DominanceProperties.ll:1.1 *** /dev/null Wed Nov 5 16:06:14 2003 --- llvm/test/Regression/Transforms/LowerSetJmp/2003-11-05-DominanceProperties.ll Wed Nov 5 16:06:03 2003 *************** *** 0 **** --- 1,16 ---- + ; RUN: llvm-as < %s | opt -lowersetjmp -disable-output + %struct.jmpenv = type { int, sbyte } + + implementation + + declare void %Perl_sv_setpv() + declare int %llvm.setjmp(int *) + + void %perl_call_sv() { + call void %Perl_sv_setpv( ) + %tmp.335 = getelementptr %struct.jmpenv* null, long 0, ubyte 0 + %tmp.336 = call int %llvm.setjmp( int* null ) + store int %tmp.336, int* %tmp.335 + ret void + } + From gaeke at cs.uiuc.edu Wed Nov 5 16:14:01 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Wed Nov 5 16:14:01 2003 Subject: [llvm-commits] CVS: llvm/tools/gccld/gccld.cpp Message-ID: <200311052213.QAA18071@zion.cs.uiuc.edu> Changes in directory llvm/tools/gccld: gccld.cpp updated: 1.60 -> 1.61 --- Log message: Do not assume the first file is a bytecode file. Instead, construct a dummy Module and link things into that. Also, fix a typo in an error message. --- Diffs of the changes: (+3 -5) Index: llvm/tools/gccld/gccld.cpp diff -u llvm/tools/gccld/gccld.cpp:1.60 llvm/tools/gccld/gccld.cpp:1.61 --- llvm/tools/gccld/gccld.cpp:1.60 Wed Nov 5 00:05:21 2003 +++ llvm/tools/gccld/gccld.cpp Wed Nov 5 16:13:00 2003 @@ -215,10 +215,8 @@ int main(int argc, char **argv, char **envp) { cl::ParseCommandLineOptions(argc, argv, " llvm linker for GCC\n"); - std::string ErrorMessage; - std::auto_ptr Composite(LoadObject(InputFilenames[0], ErrorMessage)); - if (Composite.get() == 0) - return PrintAndReturn(argv[0], ErrorMessage); + std::string ModuleID ("gccld-output"); + std::auto_ptr Composite(new Module(ModuleID)); // We always look first in the current directory when searching for libraries. LibPaths.insert(LibPaths.begin(), "."); @@ -257,7 +255,7 @@ // Generate the bytecode file. if (GenerateBytecode(Composite.get(), Strip, !NoInternalize, &Out)) { Out.close(); - return PrintAndReturn(argv[0], "error generating bytcode"); + return PrintAndReturn(argv[0], "error generating bytecode"); } // Close the bytecode file. From gaeke at cs.uiuc.edu Wed Nov 5 16:14:05 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Wed Nov 5 16:14:05 2003 Subject: [llvm-commits] CVS: llvm/tools/gccld/gccld.h Message-ID: <200311052213.QAA18066@zion.cs.uiuc.edu> Changes in directory llvm/tools/gccld: gccld.h updated: 1.3 -> 1.4 --- Log message: Give this header file an Emacs mode-line. --- Diffs of the changes: (+1 -1) Index: llvm/tools/gccld/gccld.h diff -u llvm/tools/gccld/gccld.h:1.3 llvm/tools/gccld/gccld.h:1.4 --- llvm/tools/gccld/gccld.h:1.3 Mon Oct 20 12:58:43 2003 +++ llvm/tools/gccld/gccld.h Wed Nov 5 16:13:10 2003 @@ -1,4 +1,4 @@ -//===- gccld.h - Utility functions header file ----------------------------===// +//===- gccld.h - Utility functions header file ------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // From gaeke at cs.uiuc.edu Wed Nov 5 16:14:09 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Wed Nov 5 16:14:09 2003 Subject: [llvm-commits] CVS: llvm/tools/gccld/Linker.cpp Message-ID: <200311052213.QAA18049@zion.cs.uiuc.edu> Changes in directory llvm/tools/gccld: Linker.cpp updated: 1.12 -> 1.13 --- Log message: Shorten and correct some function-header comments. Make "verbose" output MUCH nicer. Now it tells you when you are linking a bytecode file, or an archive, and whether it's because you called it by name, or because you gave it a -l option, and it says "Trying" before it takes action and prints a message in the past tense afterwards. Make LinkFiles not skip the first file in Files. Make LinkFiles warn you if it can't find a file and LLVM_LIB_SEARCH_PATH is unset. --- Diffs of the changes: (+28 -53) Index: llvm/tools/gccld/Linker.cpp diff -u llvm/tools/gccld/Linker.cpp:1.12 llvm/tools/gccld/Linker.cpp:1.13 --- llvm/tools/gccld/Linker.cpp:1.12 Tue Oct 21 16:07:12 2003 +++ llvm/tools/gccld/Linker.cpp Wed Nov 5 16:12:52 2003 @@ -30,39 +30,21 @@ #include #include -/// FileExists - determines if the specified filename exists and is readable. -/// -/// Inputs: -/// FN - The name of the file. -/// -/// Outputs: -/// None. -/// -/// Return Value: -/// TRUE - The file exists and is readable. -/// FALSE - The file does not exist or is unreadable. +/// FileExists - Returns true IFF a file named FN exists and is readable. /// static inline bool FileExists(const std::string &FN) { return access(FN.c_str(), R_OK | F_OK) != -1; } -/// IsArchive - determines if the specified file is an ar archive -/// by checking the magic string at the beginning of the file. -/// -/// Inputs: -/// filename - A C++ string containing the name of the file. +/// IsArchive - Returns true IFF the file named FN appears to be a "ar" library +/// archive. The file named FN must exist. /// -/// Outputs: -/// None. -/// -/// Return value: -/// TRUE - The file is an archive. -/// FALSE - The file is not an archive. -/// -static inline bool IsArchive(const std::string &filename) { +static inline bool IsArchive(const std::string &FN) { + // Inspect the beginning of the file to see if it contains the "ar" magic + // string. std::string ArchiveMagic("!\012"); char buf[1 + ArchiveMagic.size()]; - std::ifstream f(filename.c_str()); + std::ifstream f(FN.c_str()); f.read(buf, ArchiveMagic.size()); buf[ArchiveMagic.size()] = '\0'; return ArchiveMagic == buf; @@ -118,18 +100,8 @@ return std::string(); } -/// GetAllDefinedSymbols - finds all of the defined symbols in the specified -/// module. -/// -/// Inputs: -/// M - The module in which to find defined symbols. -/// -/// Outputs: -/// DefinedSymbols - A set of C++ strings that will contain the name of all -/// defined symbols. -/// -/// Return value: -/// None. +/// GetAllDefinedSymbols - Modifies its parameter DefinedSymbols to contain the +/// name of each externally-visible symbol defined in M. /// void GetAllDefinedSymbols(Module *M, std::set &DefinedSymbols) { for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) @@ -238,7 +210,7 @@ } // Load in the archive objects. - if (Verbose) std::cerr << " Loading '" << Filename << "'\n"; + if (Verbose) std::cerr << " Loading archive file '" << Filename << "'\n"; std::vector Objects; if (ReadArchiveFile(Filename, Objects, &ErrorMessage)) return true; @@ -294,12 +266,12 @@ return false; } -/// LinkInFile - opens an archive library and link in all objects which +/// LinkInFile - opens a bytecode file and links in all objects which /// provide symbols that are currently undefined. /// /// Inputs: -/// HeadModule - The module in which to link the archives. -/// Filename - The pathname of the archive. +/// HeadModule - The module in which to link the bytecode file. +/// Filename - The pathname of the bytecode file. /// Verbose - Flags whether verbose messages should be printed. /// /// Outputs: @@ -316,8 +288,9 @@ { std::auto_ptr M(LoadObject(Filename, ErrorMessage)); if (M.get() == 0) return true; - if (Verbose) std::cerr << "Linking in '" << Filename << "'\n"; - return LinkModules(HeadModule, M.get(), &ErrorMessage); + bool Result = LinkModules(HeadModule, M.get(), &ErrorMessage); + if (Verbose) std::cerr << "Linked in bytecode file '" << Filename << "'\n"; + return Result; } /// LinkFiles - takes a module and a list of files and links them all together. @@ -354,7 +327,7 @@ // Get the library search path from the environment char *SearchPath = getenv("LLVM_LIB_SEARCH_PATH"); - for (unsigned i = 1; i < Files.size(); ++i) { + for (unsigned i = 0; i < Files.size(); ++i) { // Determine where this file lives. if (FileExists(Files[i])) { Pathname = Files[i]; @@ -362,6 +335,8 @@ if (SearchPath == NULL) { std::cerr << progname << ": Cannot find linker input file '" << Files[i] << "'\n"; + std::cerr << progname + << ": Warning: Your LLVM_LIB_SEARCH_PATH is unset.\n"; return true; } @@ -377,20 +352,20 @@ // is not installed as a library. Detect that and link the library. if (IsArchive(Pathname)) { if (Verbose) - std::cerr << "Linking archive '" << Files[i] << "'\n"; + std::cerr << "Trying to link archive '" << Pathname << "'\n"; if (LinkInArchive(HeadModule, Pathname, ErrorMessage, Verbose)) { PrintAndReturn(progname, ErrorMessage, - ": Error linking in '" + Files[i] + "'"); + ": Error linking in archive '" + Pathname + "'"); return true; } } else { if (Verbose) - std::cerr << "Linking file '" << Files[i] << "'\n"; + std::cerr << "Trying to link bytecode file '" << Pathname << "'\n"; if (LinkInFile(HeadModule, Pathname, ErrorMessage, Verbose)) { PrintAndReturn(progname, ErrorMessage, - ": Error linking in '" + Files[i] + "'"); + ": Error linking in bytecode file '" + Pathname + "'"); return true; } } @@ -435,7 +410,7 @@ // we're doing a native link and give an error if we're doing a bytecode // link. if (!Native) { - PrintAndReturn(progname, "Cannot find " + Libraries[i] + "\n"); + PrintAndReturn(progname, "Cannot find library -l" + Libraries[i] + "\n"); return true; } } @@ -444,20 +419,20 @@ // is not installed as a library. Detect that and link the library. if (IsArchive(Pathname)) { if (Verbose) - std::cerr << "Linking archive '" << Libraries[i] << "'\n"; + std::cerr << "Trying to link archive '" << Pathname << "' (-l" << Libraries[i] << ")\n"; if (LinkInArchive(HeadModule, Pathname, ErrorMessage, Verbose)) { PrintAndReturn(progname, ErrorMessage, - ": Error linking in '" + Libraries[i] + "'"); + ": Error linking in archive '" + Pathname + "' (-l" + Libraries[i] + ")"); return true; } } else { if (Verbose) - std::cerr << "Linking file '" << Libraries[i] << "'\n"; + std::cerr << "Trying to link bytecode file '" << Pathname << "' (-l" << Libraries[i] << ")\n"; if (LinkInFile(HeadModule, Pathname, ErrorMessage, Verbose)) { PrintAndReturn(progname, ErrorMessage, - ": error linking in '" + Libraries[i] + "'"); + ": error linking in bytecode file '" + Pathname + "' (-l" + Libraries[i] + ")"); return true; } } From brukman at cs.uiuc.edu Wed Nov 5 18:05:02 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed Nov 5 18:05:02 2003 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/InstrSched/SchedGraph.cpp Message-ID: <200311060004.SAA25235@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/InstrSched: SchedGraph.cpp updated: 1.51 -> 1.52 --- Log message: Let's not forget about our friends -- Constant Pool indices. --- Diffs of the changes: (+1 -0) Index: llvm/lib/CodeGen/InstrSched/SchedGraph.cpp diff -u llvm/lib/CodeGen/InstrSched/SchedGraph.cpp:1.51 llvm/lib/CodeGen/InstrSched/SchedGraph.cpp:1.52 --- llvm/lib/CodeGen/InstrSched/SchedGraph.cpp:1.51 Mon Oct 20 14:43:15 2003 +++ llvm/lib/CodeGen/InstrSched/SchedGraph.cpp Wed Nov 5 18:04:11 2003 @@ -438,6 +438,7 @@ case MachineOperand::MO_SignExtendedImmed: case MachineOperand::MO_UnextendedImmed: case MachineOperand::MO_PCRelativeDisp: + case MachineOperand::MO_ConstantPoolIndex: break; // nothing to do for immediate fields default: From alkis at cs.uiuc.edu Wed Nov 5 20:26:01 2003 From: alkis at cs.uiuc.edu (Alkis Evlogimenos) Date: Wed Nov 5 20:26:01 2003 Subject: [llvm-commits] [regalloc_linearscan] CVS: llvm/lib/CodeGen/RegAllocLinearScan.cpp Message-ID: <200311060225.UAA00710@morpheus.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocLinearScan.cpp updated: 1.1.2.6 -> 1.1.2.7 --- Log message: A compilable sketch of the linear register allocation algorithm. --- Diffs of the changes: (+214 -254) Index: llvm/lib/CodeGen/RegAllocLinearScan.cpp diff -u llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.1.2.6 llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.1.2.7 --- llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.1.2.6 Fri Oct 24 10:57:32 2003 +++ llvm/lib/CodeGen/RegAllocLinearScan.cpp Wed Nov 5 20:25:37 2003 @@ -1,10 +1,10 @@ //===-- RegAllocLinearScan.cpp - Linear Scan register allocator -----------===// -// +// // The LLVM Compiler Infrastructure // // This file was developed by the LLVM research group and is distributed under // the University of Illinois Open Source License. See LICENSE.TXT for details. -// +// //===----------------------------------------------------------------------===// // // This file implements a linear scan register allocator. @@ -26,6 +26,7 @@ #include "Support/Debug.h" #include "Support/DepthFirstIterator.h" #include "Support/Statistic.h" +#include "Support/STLExtras.h" #include namespace { @@ -34,26 +35,38 @@ class RA : public MachineFunctionPass { private: - MachineFunction* _mf; - const TargetMachine* _tm; - const TargetRegInfo* _tri; - const MRegisterInfo* _mri; - MachineBasicBlock* _currentMbb; - MachineBasicBlock::iterator _currentInstr; + MachineFunction* mf_; + const TargetMachine* tm_; + const TargetRegInfo* tri_; + const MRegisterInfo* mri_; + MachineBasicBlock* currentMbb_; + MachineBasicBlock::iterator currentInstr_; + + typedef LiveIntervals::Intervals Intervals; + Intervals* li_; + + typedef std::vector IntervalPtrs; + IntervalPtrs active_, inactive_; - LiveIntervals* _li; + typedef LiveIntervals::MiIndex2MbbMap MiIndex2MbbMap; + MiIndex2MbbMap* mii2mbbMap_; + + typedef LiveIntervals::Mbb2MiIndexMap Mbb2MiIndexMap; + Mbb2MiIndexMap* mbb2miiMap_; typedef std::map Instr2IndexMap; - Instr2IndexMap _i2iMap; + Instr2IndexMap i2iMap_; typedef std::vector Phys2VirtMap; - Phys2VirtMap _p2vMap; + Phys2VirtMap p2vMap_; typedef std::map Virt2PhysMap; - Virt2PhysMap _v2pMap; + Virt2PhysMap v2pMap_; typedef std::map Virt2StackSlotMap; - Virt2StackSlotMap _v2ssMap; + Virt2StackSlotMap v2ssMap_; + + int instrAdded_; public: virtual const char* getPassName() const { @@ -66,27 +79,39 @@ } private: - /// runOnMachineFunction - Register allocate the whole function + /// runOnMachineFunction - register allocate the whole function bool runOnMachineFunction(MachineFunction&); - /// expireOldIntervals - in each iteration of the linear scan - /// loop, expire the old intervals; that is the registers that - /// are killed -// void expireOldIntervals(Intervals::iterator li); + /// processActiveIntervals - expire old intervals and move + /// non-overlapping ones to the incative list + void processActiveIntervals(Intervals::iterator cur); + + /// expireOldInterval - expire old intervals and move + /// overlapping ones to the active list + void processInactiveIntervals(Intervals::iterator cur); /// spillAtInterval - choose and spill at the specified - /// interval. Currently we spill using a heuristic: the active - /// interval that ends last -// void spillAtInterval(Intervals::iterator li); - - /// computeIntervals - computes the live intervals for - /// virtual registers - void computeIntervals(); + /// interval. Currently we spill the interval with the last + /// end point in the active and inactive lists + void spillAtInterval(Intervals::iterator cur); /// getFreeReg - return a free register for this virtual /// register if we have one, otherwise return 0 unsigned getFreeReg(unsigned virtReg); + /// freeReg - free the physical register associated with this + /// virtual register and disassociate virtual->physical and + /// physical->virtual mappings + void freeReg(unsigned virtReg); + + /// markReg - mark the physical register as not free + /// (preserves mappings) + void markReg(unsigned virtReg); + + /// unmarkReg - mark the physical register as free (preserves + /// mappings) + void unmarkReg(unsigned virtReg); + /// physRegAvailable - returns true if the specifed physical /// register is available bool physRegAvailable(unsigned physReg); @@ -97,240 +122,142 @@ int findOrCreateStackSlot(unsigned virtReg); /// spillVirtReg - spills the virtual register - void spillVirtReg(unsigned virtReg, unsigned physReg); + void spillVirtReg(unsigned virtReg); /// loadPhysReg - loads to the physical register the value of /// the virtual register specifed void loadPhysReg(unsigned physReg, unsigned virtReg); + + /// getMbbMbbIteratorPair - returns a pair of the + /// MachineBasicBlock this instruction is on and the iterator + /// pointing to the instruction + std::pair + getMbbMbbIteratorPair(unsigned miIndex) const; }; } -/// runOnMachineFunction - Register allocate the whole function -/// bool RA::runOnMachineFunction(MachineFunction &fn) { DEBUG(std::cerr << "Machine Function\n"); - _mf = &fn; - _tm = &fn.getTarget(); - _tri = &_tm->getRegInfo(); - _mri = _tm->getRegisterInfo(); - _li = &getAnalysis(); - _p2vMap.clear(); - _v2pMap.clear(); - _v2ssMap.clear(); - -// computeIntervals(); - -// // liner scan algorithm -// for (Intervals::iterator li = _intervals.begin(), liEnd = _intervals.end(); -// li != liEnd; ++li) { -// // FIXME: find a more efficient way to keep track of the -// // iterator on the current instruction -// MachineInstr* mi = _instrOrdering[li->start].first; -// _currentMbb = _instrOrdering[li->start].second; -// _currentInstr = find(_currentMbb->begin(), _currentMbb->end(), mi); -// assert(_currentInstr != _currentMbb->end() && -// "Cannot find instruction in basic block"); -// // check if this interval is for a physical or a virtual register -// if (li->mop->isVirtualRegister()) { -// expireOldIntervals(li); -// if (unsigned physReg = getFreeReg(li->mop->getAllocatedRegNum())) { -// loadPhysReg(physReg, li->mop->getAllocatedRegNum()); -// } -// else { -// spillAtInterval(li); -// } -// } -// else { -// // spill register if it is used -// // mark register as used -// } -// } + mf_ = &fn; + tm_ = &fn.getTarget(); + tri_ = &tm_->getRegInfo(); + mri_ = tm_->getRegisterInfo(); + li_ = &getAnalysis().getIntervals(); + active_.clear(); + inactive_.clear(); + mii2mbbMap_ = &getAnalysis().getMiIndex2MbbMap(); + mbb2miiMap_ = &getAnalysis().getMbb2MiIndexMap(); + p2vMap_.clear(); + v2pMap_.clear(); + v2ssMap_.clear(); + instrAdded_ = 0; + + // liner scan algorithm + + for (Intervals::iterator i = li_->begin(), e = li_->end(); i != e; ++i) { + unsigned curInstrIndex = i->start(); + tie(currentMbb_, currentInstr_) = getMbbMbbIteratorPair(curInstrIndex); + assert(currentInstr_ >= currentMbb_->begin() && + currentInstr_ < currentMbb_->end() && + "current instruction/machine basic block mismatch"); + processActiveIntervals(i); + processInactiveIntervals(i); + + unsigned physReg = getFreeReg(i->reg); + if (!physReg) { + spillAtInterval(i); + physReg = getFreeReg(i->reg); + } + loadPhysReg(physReg, i->reg); + active_.push_back(&*i); + } return true; } -/// computeIntervals - computes the live intervals for virtual -/// registers. for some ordering of the machine instructions [1,N] a -/// live interval is an interval [i, j] where 1 <= i <= j <= N for -/// which a variable is live -void RA::computeIntervals() -{ - DEBUG(std::cerr << "\tcomputing live intervals:\n"); - - // create a mapping from BasicBlock* to MachineBasicBlock* - typedef std::map BB2MBBMap; - BB2MBBMap bb2mbbMap; - for (MachineFunction::iterator mbb = _mf->begin(), mbbEnd = _mf->end(); - mbb != mbbEnd; ++mbb) { - bool inserted = bb2mbbMap.insert( - std::make_pair(mbb->getBasicBlock(), &*mbb)).second; - assert(inserted && "multiple BasicBlock -> MachineBasicBlock mappings"); +void RA::processActiveIntervals(Intervals::iterator cur) +{ + unsigned curInstrIndex = cur->start(); + for (IntervalPtrs::iterator + i = active_.begin(), e = active_.end(); i != e;) { + unsigned virtReg = (*i)->reg; + // remove expired intervals + if ((*i)->expired(curInstrIndex)) { + freeReg(virtReg); + // remove interval from active + i = active_.erase(i); + } + else if (!(*i)->overlaps(curInstrIndex)) { + unmarkReg(virtReg); + // add interval to inactive + inactive_.push_back(*i); + // remove interval from active + i = active_.erase(i); + } + else { + ++i; + } + } +} + +void RA::processInactiveIntervals(Intervals::iterator cur) +{ + unsigned curInstrIndex = cur->start(); + for (IntervalPtrs::iterator + i = inactive_.begin(), e = inactive_.end(); i != e;) { + unsigned virtReg = (*i)->reg; + if ((*i)->expired(curInstrIndex)) { + freeReg(virtReg); + // remove from inactive + i = inactive_.erase(i); + } + else if ((*i)->overlaps(curInstrIndex)) { + markReg(virtReg); + // add to active + active_.push_back(*i); + // remove from inactive + i = inactive_.erase(i); + } + else { + ++i; + } + } +} + +void RA::spillAtInterval(Intervals::iterator cur) +{ + assert(!active_.empty() && + "active set cannot be empty when choosing a register to spill"); + IntervalPtrs::iterator lastEnd = active_.begin(); + for (IntervalPtrs::iterator i = lastEnd + 1, e = active_.end(); + i != e; ++i) { + if ((*lastEnd)->end() < (*i)->end()) { + lastEnd = i; + } + } + bool inInactive = false; + for (IntervalPtrs::iterator i = inactive_.begin(), e = inactive_.end(); + i != e; ++i) { + if ((*lastEnd)->end() < (*i)->end()) { + lastEnd = i; + inInactive = true; + } } - // depth first ordering for the instructions (use depth first - // ordering of BasicBlocks, map to MachineBasicBlocks and - // sequentially order the instructions in each block - const BasicBlock* entry = _mf->getFunction()->begin(); - - // register -> live interval index - typedef std::map Reg2IntervalMap; - Reg2IntervalMap r2iMap; - - unsigned index = 0; -// for (df_iterator -// bb = df_begin(entry), bbEnd = df_end(entry); -// bb != bbEnd; ++bb) { -// MachineBasicBlock* mbb = bb2mbbMap.find(*bb)->second; -// assert(mbb && "MachineBasicBlock for BasicBlock cannot be null"); - -// for (MachineBasicBlock::iterator mi = mbb->begin(), miEnd = mbb->end(); -// mi != miEnd; ++index, ++mi) { -// MachineInstr* instr = *mi; -// const TargetInstrDescriptor& tid = -// _tm->getInstrInfo().get(instr->getOpcode()); -// _i2iMap.insert(std::make_pair(instr, index)); -// DEBUG(std::cerr << "\t\tinstruction[" << index << "]: " << *instr << '\n'); -// for (const unsigned* id =tid.ImplicitDefs; *id; ++id) { -// unsigned reg = *id; -// assert(r2iMap.find(reg) == r2iMap.end() && -// "multiple definitions of virtual register"); -// // initialize intervals to [index, inf] -// _intervals.push_back( -// Interval(reg, -// index, -// std::numeric_limits::max())); -// r2iMap.insert(std::make_pair(reg, _intervals.size() - 1)); -// DEBUG(std::cerr << "\t\t\tadded interval for register " -// << _tri->getUnifiedRegName(reg) -// << ": " << _intervals.back() << '\n'); -// } - -// for (int i = instr->getNumOperands() - 1; i >= 0; --i) { -// MachineOperand& mop = instr->getOperand(i); - -// if (!mop.isRegister()) -// continue; - -// // mark start and end points -// if (mop.opIsDefOnly() || mop.opIsDefAndUse()) { -// Intervals::iterator li; -// unsigned reg = mop.getAllocatedRegNum(); -// assert(r2iMap.find(reg) == r2iMap.end() && -// "multiple definitions of virtual register"); -// // initialize intervals to [index, inf] -// _intervals.push_back( -// Interval(reg, -// index, -// std::numeric_limits::max())); -// r2iMap.insert(std::make_pair(reg, _intervals.size() - 1)); -// DEBUG(std::cerr << "\t\t\tadded interval for register " -// << _tri->getUnifiedRegName(reg) -// << ": " << _intervals.back() << '\n'); -// } -// } - -// for (LiveVariables::killed_iterator -// ki = _lv->killed_begin(instr), -// kiEnd = _lv->killed_end(instr); -// ki != kiEnd; ++ki) { -// unsigned reg = ki->second; -// DEBUG(std::cerr << "\t\t\tmarking end of interval for register " << _tri->getUnifiedRegName(reg) << '\n'); -// Reg2IntervalMap::iterator ri = r2iMap.find(reg); -// assert(ri != r2iMap.end() -// && "did not find interval for killed register"); -// Interval& interval = _intervals[ri->second]; -// assert(interval.end > index -// && "attempt to mark killed an already killed variable"); -// interval.end = index; -// } -// } - -// // kill all physical registers in the end of each basic block -// for (Intervals::iterator it = -// _intervals.begin(), itEnd = _intervals.end(); -// it != itEnd; ++it) { -// if (it->reg < MRegisterInfo::FirstVirtualRegister) { -// Reg2IntervalMap::iterator ri = r2iMap.find(it->reg); -// assert(ri != r2iMap.end() -// && "did not find interval for killed register"); -// Interval& interval = _intervals[ri->second]; -// assert(interval.end > index -// && "attempt to mark killed an already killed variable"); -// interval.end = index; -// } -// } -// } - -// // sort the live intervals in increasing start point -// sort(_intervals.begin(), _intervals.end(), StartPointComp()); - -// DEBUG( -// for(Intervals::iterator -// it = _intervals.begin(), itEnd = _intervals.end(); -// it != itEnd; ++it) { -// std::cerr << *it << '\n'; -// }); -} - -//// expireOldIntervals - expire the old intervals -//// -// void RA::expireOldIntervals(Intervals::iterator li) -// { -// // the active list is sorted on increasing end point -// IntervalPtrs::iterator lip = _active.begin(); -// for (IntervalPtrs::iterator lipEnd = _active.end(); -// lip != lipEnd && (*lip)->end < li->start; -// ++lip) { -// unsigned reg = li->reg; -// // if it is a virtual register -// if (reg >= MRegisterInfo::FirstVirtualRegister) { -// Virt2PhysMap::iterator it = _v2pMap.find(reg); -// assert(it != _v2pMap.end()); -// reg = it->second; -// _v2pMap.erase(it); -// } -// assert(_p2vMap[reg] != 0); -// _p2vMap[reg] = 0; -// } -// _active.erase(_active.begin(), lip); -// } - -//// spillAtInterval - chooses and spills a register for this -//// interval. The heuristic here is the register with the last end -//// point thus it can be either the last of the active list or the -//// current one -//// -// void RA::spillAtInterval(Intervals::iterator li) -// { -// assert(!_active.empty() && "active set cannot be empty when choosing a register to spill"); -// Interval* toSpill = _active.back(); -// // if last in active is ending after the current spill it and add -// // current to active -// if (toSpill->end > li->end) { -// // spill register toSpill->mop->getAllocatedRegNum(); -// _active.pop_back(); -// for(IntervalPtrs::iterator it = _active.begin(), itEnd = _active.end(); -// it != itEnd; ++it) { -// if ((*it)->end > li->end) { -// _active.insert(it, &*li); -// } -// } -// } -// // spill the current -// else { -// // spill register li->mop->getAllocatedRegNum() -// } -// } + // spill last in active and inactive + spillVirtReg((*lastEnd)->reg); + freeReg((*lastEnd)->reg); +} bool RA::physRegAvailable(unsigned physReg) { - if (_p2vMap[physReg]) { + if (p2vMap_[physReg]) { return false; } // if it aliases other registers it is still not free - for (const unsigned* as = _mri->getAliasSet(physReg); *as; ++as) { - if (_p2vMap[*as]) { + for (const unsigned* as = mri_->getAliasSet(physReg); *as; ++as) { + if (p2vMap_[*as]) { return false; } } @@ -340,9 +267,9 @@ unsigned RA::getFreeReg(unsigned virtReg) { - const TargetRegisterClass* rc = _mf->getSSARegMap()->getRegClass(virtReg); - TargetRegisterClass::iterator reg = rc->allocation_order_begin(*_mf); - TargetRegisterClass::iterator regEnd = rc->allocation_order_end(*_mf); + const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(virtReg); + TargetRegisterClass::iterator reg = rc->allocation_order_begin(*mf_); + TargetRegisterClass::iterator regEnd = rc->allocation_order_end(*mf_); for (; reg != regEnd; ++reg) { if (physRegAvailable(*reg)) { @@ -354,39 +281,72 @@ return 0; } +void RA::freeReg(unsigned virtReg) +{ + unmarkReg(virtReg); + v2pMap_.erase(v2pMap_.find(virtReg)); +} + +void RA::markReg(unsigned virtReg) +{ + Virt2PhysMap::iterator it = v2pMap_.find(virtReg); + assert(it != v2pMap_.end() && + "attempting to mark an already disassociated register"); + unsigned physReg = it->second; + p2vMap_[physReg] = virtReg; +} + +void RA::unmarkReg(unsigned virtReg) +{ + Virt2PhysMap::iterator it = v2pMap_.find(virtReg); + assert(it != v2pMap_.end() && + "attempting to mark an already disassociated register"); + unsigned physReg = it->second; + p2vMap_[physReg] = 0; +} + int RA::findOrCreateStackSlot(unsigned virtReg) { // use lower_bound so that we can do a O(1) insert later if necessary - Virt2StackSlotMap::iterator it = _v2ssMap.lower_bound(virtReg); - if (it != _v2ssMap.end() && it->first == virtReg) { + Virt2StackSlotMap::iterator it = v2ssMap_.lower_bound(virtReg); + if (it != v2ssMap_.end() && it->first == virtReg) { return it->second; } - const TargetRegisterClass* rc = _mf->getSSARegMap()->getRegClass(virtReg); - int frameIndex = _mf->getFrameInfo()->CreateStackObject(rc); + const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(virtReg); + int frameIndex = mf_->getFrameInfo()->CreateStackObject(rc); - _v2ssMap.insert(it, std::make_pair(virtReg, frameIndex)); + v2ssMap_.insert(it, std::make_pair(virtReg, frameIndex)); return frameIndex; } -void RA::spillVirtReg(unsigned virtReg, unsigned physReg) +void RA::spillVirtReg(unsigned virtReg) { - const TargetRegisterClass* rc = _mf->getSSARegMap()->getRegClass(virtReg); + const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(virtReg); int frameIndex = findOrCreateStackSlot(virtReg); ++numSpilled; - _mri->storeRegToStackSlot(*_currentMbb, _currentInstr, - physReg, frameIndex, rc); + instrAdded_ += mri_->storeRegToStackSlot(*currentMbb_, currentInstr_, + v2pMap_[virtReg], frameIndex, rc); } void RA::loadPhysReg(unsigned physReg, unsigned virtReg) { - const TargetRegisterClass* rc = _mf->getSSARegMap()->getRegClass(virtReg); + const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(virtReg); int frameIndex = findOrCreateStackSlot(virtReg); ++numReloaded; - _mri->loadRegFromStackSlot(*_currentMbb, _currentInstr, - physReg, frameIndex, rc); - _v2pMap[virtReg] = physReg; - _p2vMap[physReg] = virtReg; + instrAdded_ += mri_->loadRegFromStackSlot(*currentMbb_, currentInstr_, + physReg, frameIndex, rc); + v2pMap_[virtReg] = physReg; + p2vMap_[physReg] = virtReg; +} + +std::pair +RA::getMbbMbbIteratorPair(unsigned miIndex) const +{ + MachineBasicBlock* mbb = (*mii2mbbMap_)[miIndex]; + MachineBasicBlock::iterator instr = + mbb->begin() + instrAdded_ + miIndex - (*mbb2miiMap_)[mbb]; + return std::make_pair(mbb, instr); } FunctionPass *createLinearScanRegisterAllocator() { From alkis at cs.uiuc.edu Wed Nov 5 20:59:01 2003 From: alkis at cs.uiuc.edu (Alkis Evlogimenos) Date: Wed Nov 5 20:59:01 2003 Subject: [llvm-commits] [regalloc_linearscan] CVS: llvm/lib/CodeGen/LiveIntervals.cpp Message-ID: <200311060258.UAA00780@morpheus.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: LiveIntervals.cpp updated: 1.1.2.6 -> 1.1.2.7 --- Log message: Fix bug in live interval analysis where vitrual registers that were killed in the same basic block that defined them, were not handled properly. --- Diffs of the changes: (+17 -15) Index: llvm/lib/CodeGen/LiveIntervals.cpp diff -u llvm/lib/CodeGen/LiveIntervals.cpp:1.1.2.6 llvm/lib/CodeGen/LiveIntervals.cpp:1.1.2.7 --- llvm/lib/CodeGen/LiveIntervals.cpp:1.1.2.6 Wed Nov 5 01:27:16 2003 +++ llvm/lib/CodeGen/LiveIntervals.cpp Wed Nov 5 20:58:12 2003 @@ -102,16 +102,18 @@ { DEBUG(std::cerr << "\t\t\tregister: "; printRegName(mri_, reg)); - unsigned start = getInstructionIndex(instr); + unsigned instrIndex = getInstructionIndex(instr); LiveVariables::VarInfo& vi = lv_->getVarInfo(reg); Reg2IntervalMap::iterator r2iit = r2iMap_.find(reg); + // handle multiple definition case (machine instructions violating + // ssa after phi-elimination if (r2iit != r2iMap_.end()) { unsigned ii = r2iit->second; Interval& interval = intervals_[ii]; unsigned end = getInstructionIndex(mbb->back()) + 1; - interval.addRange(start, end); + interval.addRange(instrIndex, end); DEBUG(std::cerr << " -> " << interval << '\n'); } else { @@ -121,28 +123,28 @@ // update interval index for this register r2iMap_[reg] = intervals_.size() - 1; - unsigned index = lv_->getMachineBasicBlockInfo(mbb).second; - if (index < vi.AliveBlocks.size() && vi.AliveBlocks[index]) { - unsigned end = getInstructionIndex(mbb->back()) + 1; - interval.addRange(start, end); - } - for (MbbIndex2MbbMap::iterator it = mbbi2mbbMap_.begin(), itEnd = mbbi2mbbMap_.end(); it != itEnd; ++it) { - unsigned mbbIndex = it->first; - MachineBasicBlock* mbb2 = it->second; - if (mbbIndex < vi.AliveBlocks.size() && - vi.AliveBlocks[mbbIndex] && mbb != mbb2) { - interval.addRange(getInstructionIndex(mbb2->front()), - getInstructionIndex(mbb2->back()) + 1); + unsigned liveBlockIndex = it->first; + MachineBasicBlock* liveBlock = it->second; + if (liveBlockIndex < vi.AliveBlocks.size() && + vi.AliveBlocks[liveBlockIndex]) { + unsigned start = mbb == liveBlock ? + instrIndex : + getInstructionIndex(liveBlock->front()); + interval.addRange(start, + getInstructionIndex(liveBlock->back()) + 1); } } for (int i = 0, e = vi.Kills.size(); i != e; ++i) { MachineBasicBlock* killerBlock = vi.Kills[i].first; MachineInstr* killerInstr = vi.Kills[i].second; - interval.addRange(getInstructionIndex(killerBlock->front()), + unsigned start = mbb == killerBlock ? + instrIndex : + getInstructionIndex(killerBlock->front()); + interval.addRange(start, getInstructionIndex(killerInstr) + 1); } DEBUG(std::cerr << " -> " << interval << '\n'); From alkis at cs.uiuc.edu Thu Nov 6 03:48:01 2003 From: alkis at cs.uiuc.edu (Alkis Evlogimenos) Date: Thu Nov 6 03:48:01 2003 Subject: [llvm-commits] [regalloc_linearscan] CVS: llvm/lib/CodeGen/RegAllocLinearScan.cpp Message-ID: <200311060947.DAA00961@morpheus.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocLinearScan.cpp updated: 1.1.2.7 -> 1.1.2.8 --- Log message: Reached a state where assignments for virtual => physical registers are computed. No operands are computed and no already physical register allocations are considered. --- Diffs of the changes: (+38 -10) Index: llvm/lib/CodeGen/RegAllocLinearScan.cpp diff -u llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.1.2.7 llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.1.2.8 --- llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.1.2.7 Wed Nov 5 20:25:37 2003 +++ llvm/lib/CodeGen/RegAllocLinearScan.cpp Thu Nov 6 03:47:43 2003 @@ -37,7 +37,6 @@ private: MachineFunction* mf_; const TargetMachine* tm_; - const TargetRegInfo* tri_; const MRegisterInfo* mri_; MachineBasicBlock* currentMbb_; MachineBasicBlock::iterator currentInstr_; @@ -137,29 +136,43 @@ } bool RA::runOnMachineFunction(MachineFunction &fn) { - DEBUG(std::cerr << "Machine Function\n"); mf_ = &fn; tm_ = &fn.getTarget(); - tri_ = &tm_->getRegInfo(); mri_ = tm_->getRegisterInfo(); li_ = &getAnalysis().getIntervals(); active_.clear(); inactive_.clear(); mii2mbbMap_ = &getAnalysis().getMiIndex2MbbMap(); mbb2miiMap_ = &getAnalysis().getMbb2MiIndexMap(); + p2vMap_.resize(MRegisterInfo::FirstVirtualRegister-1); p2vMap_.clear(); v2pMap_.clear(); v2ssMap_.clear(); instrAdded_ = 0; // liner scan algorithm - + DEBUG(std::cerr << "Processing " << li_->size() << " instervals\n"); for (Intervals::iterator i = li_->begin(), e = li_->end(); i != e; ++i) { - unsigned curInstrIndex = i->start(); - tie(currentMbb_, currentInstr_) = getMbbMbbIteratorPair(curInstrIndex); + tie(currentMbb_, currentInstr_) = getMbbMbbIteratorPair(i->start()); + DEBUG(std::cerr << "instruction[" << i->start() << "]: " + << **currentInstr_); assert(currentInstr_ >= currentMbb_->begin() && currentInstr_ < currentMbb_->end() && "current instruction/machine basic block mismatch"); + DEBUG( + std::cerr << "active intervals:\n"; + for (IntervalPtrs::const_iterator + i = active_.begin(), e = active_.end(); i != e; ++i) { + std::cerr << '\t' << **i << '\n'; + } + std::cerr << "inactive intervals:\n"; + for (IntervalPtrs::const_iterator + i = inactive_.begin(), e = inactive_.end(); i != e; ++i) { + std::cerr << '\t' << **i << '\n'; + } + ); + + processActiveIntervals(i); processInactiveIntervals(i); @@ -177,17 +190,19 @@ void RA::processActiveIntervals(Intervals::iterator cur) { + DEBUG(std::cerr << "\tprocessing active intervals:\n"); unsigned curInstrIndex = cur->start(); - for (IntervalPtrs::iterator - i = active_.begin(), e = active_.end(); i != e;) { + for (IntervalPtrs::iterator i = active_.begin(); i != active_.end();) { unsigned virtReg = (*i)->reg; // remove expired intervals if ((*i)->expired(curInstrIndex)) { + DEBUG(std::cerr << "\t\tinterval " << **i << " expired\n"); freeReg(virtReg); // remove interval from active i = active_.erase(i); } else if (!(*i)->overlaps(curInstrIndex)) { + DEBUG(std::cerr << "\t\tinterval " << **i << " inactive\n"); unmarkReg(virtReg); // add interval to inactive inactive_.push_back(*i); @@ -202,16 +217,18 @@ void RA::processInactiveIntervals(Intervals::iterator cur) { + DEBUG(std::cerr << "\tprocessing inactive intervals:\n"); unsigned curInstrIndex = cur->start(); - for (IntervalPtrs::iterator - i = inactive_.begin(), e = inactive_.end(); i != e;) { + for (IntervalPtrs::iterator i = inactive_.begin(); i != inactive_.end();) { unsigned virtReg = (*i)->reg; if ((*i)->expired(curInstrIndex)) { + DEBUG(std::cerr << "\t\tinterval " << **i << " expired\n"); freeReg(virtReg); // remove from inactive i = inactive_.erase(i); } else if ((*i)->overlaps(curInstrIndex)) { + DEBUG(std::cerr << "\t\tinterval " << **i << " active\n"); markReg(virtReg); // add to active active_.push_back(*i); @@ -226,6 +243,7 @@ void RA::spillAtInterval(Intervals::iterator cur) { + DEBUG(std::cerr << "\tspilling at interval " << *cur << ":\n"); assert(!active_.empty() && "active set cannot be empty when choosing a register to spill"); IntervalPtrs::iterator lastEnd = active_.begin(); @@ -244,9 +262,16 @@ } } + DEBUG(std::cerr << "\t\tspilling interval " << **lastEnd << "\n"); // spill last in active and inactive spillVirtReg((*lastEnd)->reg); freeReg((*lastEnd)->reg); + if (inInactive) { + inactive_.erase(lastEnd); + } + else { + active_.erase(lastEnd); + } } bool RA::physRegAvailable(unsigned physReg) @@ -267,6 +292,7 @@ unsigned RA::getFreeReg(unsigned virtReg) { + DEBUG(std::cerr << "\tgetting free register: "); const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(virtReg); TargetRegisterClass::iterator reg = rc->allocation_order_begin(*mf_); TargetRegisterClass::iterator regEnd = rc->allocation_order_end(*mf_); @@ -274,10 +300,12 @@ for (; reg != regEnd; ++reg) { if (physRegAvailable(*reg)) { assert(*reg != 0 && "Cannot use register!"); + DEBUG(std::cerr << mri_->getName(*reg) << '\n'); return *reg; // Found an unused register! } } + DEBUG(std::cerr << "no free register\n"); return 0; } From alkis at cs.uiuc.edu Thu Nov 6 04:00:01 2003 From: alkis at cs.uiuc.edu (Alkis Evlogimenos) Date: Thu Nov 6 04:00:01 2003 Subject: [llvm-commits] [regalloc_linearscan] CVS: llvm/lib/CodeGen/RegAllocLinearScan.cpp Message-ID: <200311060959.DAA00988@morpheus.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocLinearScan.cpp updated: 1.1.2.8 -> 1.1.2.9 --- Log message: Improved debugging output. --- Diffs of the changes: (+25 -23) Index: llvm/lib/CodeGen/RegAllocLinearScan.cpp diff -u llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.1.2.8 llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.1.2.9 --- llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.1.2.8 Thu Nov 6 03:47:43 2003 +++ llvm/lib/CodeGen/RegAllocLinearScan.cpp Thu Nov 6 03:59:26 2003 @@ -34,6 +34,9 @@ Statistic<> numReloaded("ra-linearscan", "Number of registers reloaded"); class RA : public MachineFunctionPass { + public: + typedef std::vector IntervalPtrs; + private: MachineFunction* mf_; const TargetMachine* tm_; @@ -44,7 +47,6 @@ typedef LiveIntervals::Intervals Intervals; Intervals* li_; - typedef std::vector IntervalPtrs; IntervalPtrs active_, inactive_; typedef LiveIntervals::MiIndex2MbbMap MiIndex2MbbMap; @@ -135,6 +137,17 @@ }; } +namespace { + void printIntervals(const char* const str, + RA::IntervalPtrs::const_iterator i, + RA::IntervalPtrs::const_iterator e) { + if (str) std::cerr << str << " intervals:\n"; + for (; i != e; ++i) { + std::cerr << "\t\t" << **i << '\n'; + } + } +} + bool RA::runOnMachineFunction(MachineFunction &fn) { mf_ = &fn; tm_ = &fn.getTarget(); @@ -159,19 +172,8 @@ assert(currentInstr_ >= currentMbb_->begin() && currentInstr_ < currentMbb_->end() && "current instruction/machine basic block mismatch"); - DEBUG( - std::cerr << "active intervals:\n"; - for (IntervalPtrs::const_iterator - i = active_.begin(), e = active_.end(); i != e; ++i) { - std::cerr << '\t' << **i << '\n'; - } - std::cerr << "inactive intervals:\n"; - for (IntervalPtrs::const_iterator - i = inactive_.begin(), e = inactive_.end(); i != e; ++i) { - std::cerr << '\t' << **i << '\n'; - } - ); - + DEBUG(printIntervals("\tactive", active_.begin(), active_.end())); + DEBUG(printIntervals("\tinactive", inactive_.begin(), inactive_.end())); processActiveIntervals(i); processInactiveIntervals(i); @@ -190,19 +192,19 @@ void RA::processActiveIntervals(Intervals::iterator cur) { - DEBUG(std::cerr << "\tprocessing active intervals:\n"); + DEBUG(std::cerr << "\t\tprocessing active intervals:\n"); unsigned curInstrIndex = cur->start(); for (IntervalPtrs::iterator i = active_.begin(); i != active_.end();) { unsigned virtReg = (*i)->reg; // remove expired intervals if ((*i)->expired(curInstrIndex)) { - DEBUG(std::cerr << "\t\tinterval " << **i << " expired\n"); + DEBUG(std::cerr << "\t\t\tinterval " << **i << " expired\n"); freeReg(virtReg); // remove interval from active i = active_.erase(i); } else if (!(*i)->overlaps(curInstrIndex)) { - DEBUG(std::cerr << "\t\tinterval " << **i << " inactive\n"); + DEBUG(std::cerr << "\t\t\tinterval " << **i << " inactive\n"); unmarkReg(virtReg); // add interval to inactive inactive_.push_back(*i); @@ -217,18 +219,18 @@ void RA::processInactiveIntervals(Intervals::iterator cur) { - DEBUG(std::cerr << "\tprocessing inactive intervals:\n"); + DEBUG(std::cerr << "\t\tprocessing inactive intervals:\n"); unsigned curInstrIndex = cur->start(); for (IntervalPtrs::iterator i = inactive_.begin(); i != inactive_.end();) { unsigned virtReg = (*i)->reg; if ((*i)->expired(curInstrIndex)) { - DEBUG(std::cerr << "\t\tinterval " << **i << " expired\n"); + DEBUG(std::cerr << "\t\t\tinterval " << **i << " expired\n"); freeReg(virtReg); // remove from inactive i = inactive_.erase(i); } else if ((*i)->overlaps(curInstrIndex)) { - DEBUG(std::cerr << "\t\tinterval " << **i << " active\n"); + DEBUG(std::cerr << "\t\t\tinterval " << **i << " active\n"); markReg(virtReg); // add to active active_.push_back(*i); @@ -243,7 +245,7 @@ void RA::spillAtInterval(Intervals::iterator cur) { - DEBUG(std::cerr << "\tspilling at interval " << *cur << ":\n"); + DEBUG(std::cerr << "\t\tspilling at interval " << *cur << ":\n"); assert(!active_.empty() && "active set cannot be empty when choosing a register to spill"); IntervalPtrs::iterator lastEnd = active_.begin(); @@ -262,7 +264,7 @@ } } - DEBUG(std::cerr << "\t\tspilling interval " << **lastEnd << "\n"); + DEBUG(std::cerr << "\t\t\tspilling interval " << **lastEnd << "\n"); // spill last in active and inactive spillVirtReg((*lastEnd)->reg); freeReg((*lastEnd)->reg); @@ -292,7 +294,7 @@ unsigned RA::getFreeReg(unsigned virtReg) { - DEBUG(std::cerr << "\tgetting free register: "); + DEBUG(std::cerr << "\t\tgetting free register: "); const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(virtReg); TargetRegisterClass::iterator reg = rc->allocation_order_begin(*mf_); TargetRegisterClass::iterator regEnd = rc->allocation_order_end(*mf_); From brukman at cs.uiuc.edu Thu Nov 6 12:07:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu Nov 6 12:07:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/StackSlots.cpp Message-ID: <200311061806.MAA08788@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: StackSlots.cpp updated: 1.7 -> 1.8 --- Log message: * Make the comment header 80 columns long * Alphabetize #includes --- Diffs of the changes: (+3 -3) Index: llvm/lib/Target/Sparc/StackSlots.cpp diff -u llvm/lib/Target/Sparc/StackSlots.cpp:1.7 llvm/lib/Target/Sparc/StackSlots.cpp:1.8 --- llvm/lib/Target/Sparc/StackSlots.cpp:1.7 Mon Oct 20 14:43:17 2003 +++ llvm/lib/Target/Sparc/StackSlots.cpp Thu Nov 6 12:06:13 2003 @@ -1,4 +1,4 @@ -//===- StackSlots.cpp - Specialize LLVM code for target machine ---------===// +//===- StackSlots.cpp - Specialize LLVM code for target machine ----------===// // // The LLVM Compiler Infrastructure // @@ -15,10 +15,10 @@ #include "SparcInternals.h" #include "llvm/Constant.h" -#include "llvm/Function.h" #include "llvm/DerivedTypes.h" -#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Function.h" #include "llvm/CodeGen/MachineFunctionInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" namespace { class StackSlots : public MachineFunctionPass { From gaeke at cs.uiuc.edu Thu Nov 6 13:09:45 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Thu Nov 6 13:09:45 2003 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp Message-ID: <200311061857.MAA28177@gally.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: UnpackTraceFunction.cpp updated: 1.12 -> 1.13 --- Log message: Include llvm/Support/InstIterator.h. Add a stub function to load pointers to values on the stack into registers. Flesh out the body of insertCopyMachineInstrs somewhat. Add comments that say certain methods are currently SPARC-specific. Fix a >80-char line. Flesh out the body of getSavedStateIndexOfInstruction(). Make it take an Instruction *. Change callers to match. Add an abort to the stub of getSavedStateIndexOfOperandInInstruction(). --- Diffs of the changes: (+72 -21) Index: reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp diff -u reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.12 reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.13 --- reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.12 Tue Nov 4 16:39:52 2003 +++ reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp Thu Nov 6 12:56:48 2003 @@ -13,35 +13,69 @@ #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Support/InstIterator.h" #include "llvm/Module.h" #include "reopt/ScratchMemory.h" #include "reopt/MappingInfo.h" #include "Support/Debug.h" -/// Insert (a) machine instruction(s) for the current architecture, that -/// copies the value in Source to the location specified by Target, at -/// the beginning of B. +void addGetPointerToStackValInstrs (std::vector &mvec, + AllocInfo &Source, unsigned SrcReg) { + // Let OFFSET be the offset of the value from %fp + // construct add %fp, , +} + +/// Insert (a) machine instruction(s) that copies the value in Source +/// to the location specified by Target, at the beginning of B. Note +/// that the current implementation is SPARC-specific. /// -/// FIXME: Not yet finished +/// FIXME: Not yet finished. /// void insertCopyMachineInstrs (AllocInfo &Source, AllocInfo &Target, MachineBasicBlock &B) { - if (Source.AllocState == AllocInfo::Spilled && Target.AllocState == AllocInfo::Allocated) { - //Insert load instruction from stack loc. Source into register Target - } else if (Source.AllocState == AllocInfo::Allocated && Target.AllocState == AllocInfo::Allocated) { - //Insert move instruction from register Source to register Target - } else if (Source.AllocState == AllocInfo::Allocated && Target.AllocState == AllocInfo::Spilled) { - //Insert store instruction from register Source to stack loc. Target - } else if (Source.AllocState == AllocInfo::Spilled && Target.AllocState == AllocInfo::Spilled) { - //Get a temporary register Temp somehow (maybe use the path reg, %g1?) - //Insert load instruction from stack loc. Source into register Temp - //Insert store instruction from register Temp to stack loc. Target + UltraSparc TM; + const TargetRegInfo &TRI = TM.getRegInfo (); + std::vector mvec; + unsigned SrcReg, TargReg; + int Offset, RegType; + if (Source.AllocState == AllocInfo::Spilled + && Target.AllocState == AllocInfo::Allocated) { + // Emit instructions to construct pointer to Source into SrcReg + addGetPointerToStackValInstrs (mvec, Source, SrcReg); + // Emit load instruction from stack loc. Source into register Target + TRI.cpMem2RegMI (mvec, SrcReg, Offset, TargReg, RegType); + } else if (Source.AllocState == AllocInfo::Allocated\ + && Target.AllocState == AllocInfo::Allocated) { + // Emit move instruction from register Source to register Target + TRI.cpReg2RegMI (mvec, Source.Placement, Target.Placement, RegType); + } else if (Source.AllocState == AllocInfo::Allocated + && Target.AllocState == AllocInfo::Spilled) { + // Emit instructions to construct pointer to Target into TargReg + addGetPointerToStackValInstrs (mvec, Target, TargReg); + // Emit store instruction from register Source to stack loc. Target + TRI.cpReg2MemMI (mvec, Source.Placement, TargReg, Offset, RegType); + } else if (Source.AllocState == AllocInfo::Spilled + && Target.AllocState == AllocInfo::Spilled) { + // Emit instructions to construct pointer to Source into SrcReg + addGetPointerToStackValInstrs (mvec, Source, SrcReg); + // Emit load instruction from address in SrcReg into register SrcReg + TRI.cpMem2RegMI (mvec, SrcReg, Offset, SrcReg, RegType); + // Emit instructions to construct pointer to Target into TargReg + addGetPointerToStackValInstrs (mvec, Target, TargReg); + // Emit store instruction from register SrcReg to stack loc. Target + TRI.cpReg2MemMI (mvec, SrcReg, TargReg, Offset, RegType); } + // Add whatever the TargetRegInfo gave us to the MachineBasicBlock we were + // provided. + for (std::vector::iterator i = mvec.begin (), + e = mvec.end (); i != e; ++i) + B.push_back (*i); } /// Emit the same sequence of MachineInstrs that /// replaceMachineCodeForFunction() would emit, to branch from the end -/// of B to TargetAddr. +/// of B to TargetAddr. Note that the current implementation is +/// SPARC-specific. /// /// FIXME: refactor this so it shares code with SparcV9CodeEmitter.cpp's /// JITResolver::insertJumpAtAddr(), JITResolver::insertFarJumpAtAddr() @@ -70,7 +104,7 @@ // sethi %uhi(Target), %g5 ;; get upper 22 bits of Target into %g5 BuildMI(V9::SETHI, 2).addSImm(Target >> 42).addReg(g5), // or %g5, %ulo(Target), %g5 ;; get 10 lower bits of upper word into %g5 - BuildMI(V9::ORi, 3).addReg(g5).addSImm((Target >> 32) & 0x03ff).addReg(g5), + BuildMI(V9::ORi,3).addReg(g5).addSImm((Target >> 32) & 0x03ff).addReg(g5), // sllx %g5, 32, %g5 ;; shift those 10 bits to the upper word BuildMI(V9::SLLXi6, 3).addReg(g5).addSImm(32).addReg(g5), // sethi %hi(Target), %g1 ;; extract bits 10-31 into the dest reg @@ -150,11 +184,25 @@ abort (); } -unsigned getSavedStateIndexOfInstruction (Function *F, Value *V) { +unsigned getSavedStateIndexOfInstruction (const Function *F, + const Instruction *I) { + unsigned Key = 0; + for (const_inst_iterator II=inst_begin (F), IE=inst_end (F); II!=IE; ++II) { + if (*II == I) return Key; + ++Key; + } + // By this time we had better have found it, otherwise we are about to do bad + // things. + std::cerr << "ERROR: UnpackTraceFunction: Cannot find index of Value " + << F->getName() << "() in its parent Function using inst_iterator, " + << "in getSavedStateIndexOfInstruction()\n"; + abort (); } unsigned getSavedStateIndexOfOperandInInstruction (Function *F, Value *V, unsigned VI) { + // FIXME; not yet implemented + abort (); } /// Returns the register number or stack position where V can be found in the @@ -165,8 +213,9 @@ AllocInfo getValueAllocStateFromModule (Function *F, Value *V) { // Figure out the indices (FI, VI, VO) that can be used to look up V, which // is an operand of some instruction in F, in _llvm_regAllocState: + Instruction *Instr = cast (V); unsigned FI = getSavedStateIndexOfFunction (F); - unsigned VI = getSavedStateIndexOfInstruction (F, V); + unsigned VI = getSavedStateIndexOfInstruction (F, Instr); unsigned VO = getSavedStateIndexOfOperandInInstruction (F, V, VI); // Reconstruct the AllocInfo for V by searching // _llvm_regAllocState.functions[FI] for a tuple that starts with @@ -192,11 +241,12 @@ /// variable ExportedFnAllocState exported by PhyRegAlloc.cpp. /// AllocInfo getValueAllocStateFromGlobal (Function *F, Value *V) { + Instruction *Instr = cast (V); // Get the saved PhyRegAlloc state for F out of ExportedFnAllocState: std::vector &FState = ExportedFnAllocState[F]; // Figure out the indices (VI, VO) that can be used to look up V, which is an // operand of some instruction in F, in FState: - unsigned VI = getSavedStateIndexOfInstruction (F, V); + unsigned VI = getSavedStateIndexOfInstruction (F, Instr); unsigned VO = getSavedStateIndexOfOperandInInstruction (F, V, VI); // Retrieve the AllocInfo for V by searching FState for a tuple that starts // with (VI, VO, ...): @@ -213,8 +263,9 @@ abort (); } -/// Returns a pointer to the return instruction in B, if B contains one, -/// or null otherwise. FIXME: SPARC target-specific. +/// Returns a pointer to the return instruction in B, if B contains +/// one, or null otherwise. Note that the current implementation is +/// SPARC-specific. /// const MachineInstr *containsReturnInstruction (MachineBasicBlock &B) { for (MachineBasicBlock::const_reverse_iterator i = B.rbegin (), From lattner at cs.uiuc.edu Thu Nov 6 13:19:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Nov 6 13:19:02 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/LowerSetJmp.cpp Message-ID: <200311061918.NAA12989@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: LowerSetJmp.cpp updated: 1.10 -> 1.11 --- Log message: Fix bug: PR93 --- Diffs of the changes: (+29 -0) Index: llvm/lib/Transforms/IPO/LowerSetJmp.cpp diff -u llvm/lib/Transforms/IPO/LowerSetJmp.cpp:1.10 llvm/lib/Transforms/IPO/LowerSetJmp.cpp:1.11 --- llvm/lib/Transforms/IPO/LowerSetJmp.cpp:1.10 Tue Oct 28 17:14:59 2003 +++ llvm/lib/Transforms/IPO/LowerSetJmp.cpp Thu Nov 6 13:18:49 2003 @@ -41,6 +41,7 @@ #include "llvm/Pass.h" #include "llvm/Support/CFG.h" #include "llvm/Support/InstVisitor.h" +#include "llvm/Transforms/Utils/DemoteRegToStack.h" #include "Support/DepthFirstIterator.h" #include "Support/Statistic.h" #include "Support/StringExtras.h" @@ -376,6 +377,34 @@ ConstantUInt::get(Type::UIntTy, SetJmpIDMap[Func]++), 0), "", Inst); + + // We are guaranteed that there are no values live across basic blocks + // (because we are "not in SSA form" yet), but there can still be values live + // in basic blocks. Because of this, splitting the setjmp block can cause + // values above the setjmp to not dominate uses which are after the setjmp + // call. For all of these occasions, we must spill the value to the stack. + // + std::set InstrsAfterCall; + + // The call is probably very close to the end of the basic block, for the + // common usage pattern of: 'if (setjmp(...))', so keep track of the + // instructions after the call. + for (BasicBlock::iterator I = ++BasicBlock::iterator(Inst), E = ABlock->end(); + I != E; ++I) + InstrsAfterCall.insert(I); + + for (BasicBlock::iterator II = ABlock->begin(); + II != BasicBlock::iterator(Inst); ++II) + // Loop over all of the uses of instruction. If any of them are after the + // call, "spill" the value to the stack. + for (Value::use_iterator UI = II->use_begin(), E = II->use_end(); + UI != E; ++UI) + if (cast(*UI)->getParent() != ABlock || + InstrsAfterCall.count(cast(*UI))) { + DemoteRegToStack(*II); + break; + } + InstrsAfterCall.clear(); // Change the setjmp call into a branch statement. We'll remove the // setjmp call in a little bit. No worries. From gaeke at cs.uiuc.edu Thu Nov 6 13:41:01 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Thu Nov 6 13:41:01 2003 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp Message-ID: <200311061940.NAA05771@seraph.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: UnpackTraceFunction.cpp updated: 1.13 -> 1.14 --- Log message: Mess around with insertCopyMachineInstrs. Update comment in insertBranchMachineInstrs. --- Diffs of the changes: (+11 -9) Index: reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp diff -u reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.13 reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.14 --- reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.13 Thu Nov 6 12:56:48 2003 +++ reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp Thu Nov 6 13:40:35 2003 @@ -36,8 +36,12 @@ UltraSparc TM; const TargetRegInfo &TRI = TM.getRegInfo (); std::vector mvec; - unsigned SrcReg, TargReg; - int Offset, RegType; + unsigned SrcReg = 31337, TargReg = 31337; + int Offset = -1, RegType = -1; + if (Source.AllocState == AllocInfo::Allocated) + SrcReg = Source.Placement; + if (Target.AllocState == AllocInfo::Allocated) + TargReg = Target.Placement; if (Source.AllocState == AllocInfo::Spilled && Target.AllocState == AllocInfo::Allocated) { // Emit instructions to construct pointer to Source into SrcReg @@ -83,16 +87,14 @@ void insertBranchMachineInstrs (uint64_t Target, MachineBasicBlock &B) { DEBUG(std::cerr << "Emitting a jump to 0x" << std::hex << Target << "\n"); - // FIXME: How do we know where this branch is going to end up in - // memory? For now, let's take a wild guess by saying it's at the - // beginning of the trace cache. Once we have a TraceCache - // MachineCodeEmitter, we should be able to ask it for - // getCurrentPCValue() for a much closer value (but not exactly - // right; we'll have to really fix this later.) + // FIXME: A "near jump" (Branch Always instruction) will get the + // WRONG address by this method, because the binary value of the + // instruction depends on the exact displacement from the branch + // source. Near jumps are disabled for now. const int64_t Addr = (int64_t)(intptr_t)dummyFunction2; int64_t BranchTarget = (Target-Addr) >> 2; - if (BranchTarget >= (1 << 19) || BranchTarget <= -(1 << 19)) { + if (1 || (BranchTarget >= (1 << 19) || BranchTarget <= -(1 << 19))) { /// FAR JUMP static const unsigned o6 = SparcIntRegClass::o6, g0 = SparcIntRegClass::g0, From lattner at cs.uiuc.edu Thu Nov 6 13:47:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Nov 6 13:47:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/DemoteRegToStack.cpp Message-ID: <200311061946.NAA15776@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: DemoteRegToStack.cpp updated: 1.5 -> 1.6 --- Log message: Various cleanups and efficiency improvements --- Diffs of the changes: (+24 -38) Index: llvm/lib/Transforms/Utils/DemoteRegToStack.cpp diff -u llvm/lib/Transforms/Utils/DemoteRegToStack.cpp:1.5 llvm/lib/Transforms/Utils/DemoteRegToStack.cpp:1.6 --- llvm/lib/Transforms/Utils/DemoteRegToStack.cpp:1.5 Mon Oct 20 14:43:20 2003 +++ llvm/lib/Transforms/Utils/DemoteRegToStack.cpp Thu Nov 6 13:46:29 2003 @@ -1,4 +1,4 @@ -//===- DemoteRegToStack.cpp - Move a virtual reg. to stack ----------------===// +//===- DemoteRegToStack.cpp - Move a virtual register to the stack --------===// // // The LLVM Compiler Infrastructure // @@ -21,26 +21,25 @@ #include "llvm/iTerminators.h" #include "llvm/Type.h" #include "Support/hash_set" -#include typedef hash_set PhiSet; typedef hash_set::iterator PhiSetIterator; // 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, +inline void PushOperandsOnWorkList(std::vector& workList, 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)) - if (!isa(opI) || - phisToGo.find(cast(opI)) == phisToGo.end()) - workList.push(opI); + OI != OE; ++OI) { + Instruction* opI = cast(OI); + if (!isa(opI) || !phisToGo.count(cast(opI))) + workList.push_back(opI); + } } static void FindPhis(Instruction& X, PhiSet& phisToGo) { - std::stack workList; - workList.push(&X); + std::vector workList; + workList.push_back(&X); // Handle the case that X itself is a Phi! if (PHINode* phiX = dyn_cast(&X)) { @@ -50,31 +49,21 @@ // Now use a worklist to find all phis reachable from X, and // (recursively) all phis reachable from operands of such phis. - for (Instruction* workI; !workList.empty(); workList.pop()) { - workI = workList.top(); - for (Value::use_iterator UI=workI->use_begin(), UE=workI->use_end(); - UI != UE; ++UI) + while (!workList.empty()) { + Instruction *I = workList.back(); + workList.pop_back(); + for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI!=E; ++UI) if (PHINode* phiN = dyn_cast(*UI)) if (phisToGo.find(phiN) == phisToGo.end()) { // Seeing this phi for the first time: it must go! phisToGo.insert(phiN); - workList.push(phiN); + workList.push_back(phiN); PushOperandsOnWorkList(workList, phisToGo, phiN); } } } -// Create the Alloca for X -static AllocaInst* CreateAllocaForX(Instruction& X) { - Function* parentFunc = X.getParent()->getParent(); - Instruction* entryInst = parentFunc->getEntryBlock().begin(); - return new AllocaInst(X.getType(), /*arraySize*/ NULL, - X.hasName()? X.getName()+std::string("OnStack") - : "DemotedTmp", - entryInst); -} - // Insert loads before all uses of I, except uses in Phis // since all such Phis *must* be deleted. static void LoadBeforeUses(Instruction* def, AllocaInst* XSlot) { @@ -105,8 +94,7 @@ for (unsigned i=0, N=pn->getNumIncomingValues(); i < N; ++i) { Value* phiOp = pn->getIncomingValue(i); if (phiOp != &X && - (!isa(phiOp) || - phisToGo.find(cast(phiOp)) == phisToGo.end())) { + (!isa(phiOp) || !phisToGo.count(cast(phiOp)))) { // This operand is not a phi that will be deleted: need to store. assert(!isa(phiOp)); @@ -128,12 +116,6 @@ } } -static void DeletePhis(PhiSet& phisToGo) { - for (PhiSetIterator PI = phisToGo.begin(), PE =phisToGo.end(); PI != PE; ++PI) - (*PI)->getParent()->getInstList().erase(*PI); - phisToGo.clear(); -} - //---------------------------------------------------------------------------- // function DemoteRegToStack() // @@ -148,11 +130,10 @@ // (4) Delete all the Phis, which should all now be dead. // // Returns the pointer to the alloca inserted to create a stack slot for X. -//---------------------------------------------------------------------------- - +// AllocaInst* DemoteRegToStack(Instruction& X) { if (X.getType() == Type::VoidTy) - return NULL; // nothing to do! + return 0; // nothing to do! // Find all Phis involving X or recursively using such Phis or Phis // involving operands of such Phis (essentially all Phis in the "web" of X) @@ -160,7 +141,10 @@ FindPhis(X, phisToGo); // Create a stack slot to hold X - AllocaInst* XSlot = CreateAllocaForX(X); + Function* parentFunc = X.getParent()->getParent(); + AllocaInst *XSlot = new AllocaInst(X.getType(), 0, X.getName(), + parentFunc->getEntryBlock().begin()); + // Insert loads before all uses of X and (*only then*) insert store after X assert(X.getNext() && "Non-terminator (since non-void) with no successor?"); @@ -171,6 +155,8 @@ AddLoadsAndStores(XSlot, X, phisToGo); // Delete the phis and return the alloca instruction - DeletePhis(phisToGo); + for (PhiSetIterator PI = phisToGo.begin(), E = phisToGo.end(); PI != E; ++PI) + (*PI)->getParent()->getInstList().erase(*PI); + return XSlot; } From gaeke at cs.uiuc.edu Thu Nov 6 13:52:03 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Thu Nov 6 13:52:03 2003 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp Message-ID: <200311061951.NAA05978@seraph.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: UnpackTraceFunction.cpp updated: 1.14 -> 1.15 --- Log message: Get TargetRegInfo to cough up the frame pointer, stack pointer regs. Pass them to addGetPointerToStackValInstrs(). --- Diffs of the changes: (+11 -7) Index: reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp diff -u reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.14 reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.15 --- reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.14 Thu Nov 6 13:40:35 2003 +++ reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp Thu Nov 6 13:51:06 2003 @@ -20,8 +20,10 @@ #include "Support/Debug.h" void addGetPointerToStackValInstrs (std::vector &mvec, - AllocInfo &Source, unsigned SrcReg) { + AllocInfo &Source, unsigned SrcReg, + unsigned FramePtrReg) { // Let OFFSET be the offset of the value from %fp + mvec.push_back (BuildMI (V9::ADDi, 3).addReg (FramePtrReg)); // FIXME // construct add %fp, , } @@ -37,35 +39,37 @@ const TargetRegInfo &TRI = TM.getRegInfo (); std::vector mvec; unsigned SrcReg = 31337, TargReg = 31337; - int Offset = -1, RegType = -1; + int Offset = -1, RegType = -1; // FIXME: How do we set these correctly? if (Source.AllocState == AllocInfo::Allocated) SrcReg = Source.Placement; if (Target.AllocState == AllocInfo::Allocated) TargReg = Target.Placement; + const unsigned FramePtrReg = TRI.getFramePointer (); + const unsigned StackPtrReg = TRI.getStackPointer (); if (Source.AllocState == AllocInfo::Spilled && Target.AllocState == AllocInfo::Allocated) { // Emit instructions to construct pointer to Source into SrcReg - addGetPointerToStackValInstrs (mvec, Source, SrcReg); + addGetPointerToStackValInstrs (mvec, Source, SrcReg, FramePtrReg); // Emit load instruction from stack loc. Source into register Target TRI.cpMem2RegMI (mvec, SrcReg, Offset, TargReg, RegType); - } else if (Source.AllocState == AllocInfo::Allocated\ + } else if (Source.AllocState == AllocInfo::Allocated && Target.AllocState == AllocInfo::Allocated) { // Emit move instruction from register Source to register Target TRI.cpReg2RegMI (mvec, Source.Placement, Target.Placement, RegType); } else if (Source.AllocState == AllocInfo::Allocated && Target.AllocState == AllocInfo::Spilled) { // Emit instructions to construct pointer to Target into TargReg - addGetPointerToStackValInstrs (mvec, Target, TargReg); + addGetPointerToStackValInstrs (mvec, Target, TargReg, FramePtrReg); // Emit store instruction from register Source to stack loc. Target TRI.cpReg2MemMI (mvec, Source.Placement, TargReg, Offset, RegType); } else if (Source.AllocState == AllocInfo::Spilled && Target.AllocState == AllocInfo::Spilled) { // Emit instructions to construct pointer to Source into SrcReg - addGetPointerToStackValInstrs (mvec, Source, SrcReg); + addGetPointerToStackValInstrs (mvec, Source, SrcReg, FramePtrReg); // Emit load instruction from address in SrcReg into register SrcReg TRI.cpMem2RegMI (mvec, SrcReg, Offset, SrcReg, RegType); // Emit instructions to construct pointer to Target into TargReg - addGetPointerToStackValInstrs (mvec, Target, TargReg); + addGetPointerToStackValInstrs (mvec, Target, TargReg, FramePtrReg); // Emit store instruction from register SrcReg to stack loc. Target TRI.cpReg2MemMI (mvec, SrcReg, TargReg, Offset, RegType); } From lattner at cs.uiuc.edu Thu Nov 6 14:30:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Nov 6 14:30:02 2003 Subject: [llvm-commits] CVS: llvm/docs/CommandGuide/llvm-prof.html Message-ID: <200311062029.OAA19599@zion.cs.uiuc.edu> Changes in directory llvm/docs/CommandGuide: llvm-prof.html updated: 1.2 -> 1.3 --- Log message: Add new commandline option --- Diffs of the changes: (+7 -1) Index: llvm/docs/CommandGuide/llvm-prof.html diff -u llvm/docs/CommandGuide/llvm-prof.html:1.2 llvm/docs/CommandGuide/llvm-prof.html:1.3 --- llvm/docs/CommandGuide/llvm-prof.html:1.2 Sat Nov 1 23:20:44 2003 +++ llvm/docs/CommandGuide/llvm-prof.html Thu Nov 6 14:29:33 2003 @@ -26,13 +26,19 @@

      OPTIONS

        -
      • -annotated-llvm or -A
        +
      • --annotated-llvm or -A
        In addition to the normal report printed, print out the code for the program, annotated we execution frequency information. This can be particularly useful when trying to visualize how frequently basic blocks are executed. This is most useful with basic block profiling information or better.

        + +

      • --print-all-code
        + + Using this option enables the --annotated-llvm option, but it + prints the entire module, instead of just the most commonly executed + functions.

      EXIT STATUS

      From lattner at cs.uiuc.edu Thu Nov 6 14:30:08 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Nov 6 14:30:08 2003 Subject: [llvm-commits] CVS: llvm/tools/llvm-prof/llvm-prof.cpp Message-ID: <200311062029.OAA19484@zion.cs.uiuc.edu> Changes in directory llvm/tools/llvm-prof: llvm-prof.cpp updated: 1.14 -> 1.15 --- Log message: Add new command line option --- Diffs of the changes: (+5 -2) Index: llvm/tools/llvm-prof/llvm-prof.cpp diff -u llvm/tools/llvm-prof/llvm-prof.cpp:1.14 llvm/tools/llvm-prof/llvm-prof.cpp:1.15 --- llvm/tools/llvm-prof/llvm-prof.cpp:1.14 Thu Oct 30 18:34:05 2003 +++ llvm/tools/llvm-prof/llvm-prof.cpp Thu Nov 6 14:29:25 2003 @@ -37,6 +37,9 @@ cl::desc("Print LLVM code with frequency annotations")); cl::alias PrintAnnotated2("A", cl::desc("Alias for --annotated-llvm"), cl::aliasopt(PrintAnnotatedLLVM)); + cl::opt + PrintAllCode("print-all-code", + cl::desc("Print annotated code for the entire program")); } // PairSecondSort - A sorting predicate to sort by the second element of a pair. @@ -171,13 +174,13 @@ BlockFreqs.insert(Counts.begin(), Counts.end()); } - if (PrintAnnotatedLLVM) { + if (PrintAnnotatedLLVM || PrintAllCode) { std::cout << "\n===" << std::string(73, '-') << "===\n"; std::cout << "Annotated LLVM code for the module:\n\n"; ProfileAnnotator PA(FuncFreqs, BlockFreqs); - if (FunctionsToPrint.empty()) + if (FunctionsToPrint.empty() || PrintAllCode) M->print(std::cout, &PA); else // Print just a subset of the functions... From lattner at cs.uiuc.edu Thu Nov 6 14:52:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Nov 6 14:52:00 2003 Subject: [llvm-commits] CVS: llvm/docs/GettingStarted.html Message-ID: <200311062051.OAA20927@zion.cs.uiuc.edu> Changes in directory llvm/docs: GettingStarted.html updated: 1.43 -> 1.44 --- Log message: No wonder noone can set up LLVMGCCDIR correctly! --- Diffs of the changes: (+6 -6) Index: llvm/docs/GettingStarted.html diff -u llvm/docs/GettingStarted.html:1.43 llvm/docs/GettingStarted.html:1.44 --- llvm/docs/GettingStarted.html:1.43 Mon Oct 27 12:18:16 2003 +++ llvm/docs/GettingStarted.html Thu Nov 6 14:51:45 2003 @@ -315,14 +315,14 @@ .cshrc or .profile.
      -
      LLVM_LIB_SEARCH_PATH=LLVMGCCDIR/llvm-gcc/bytecode-libs +
      LLVM_LIB_SEARCH_PATH=LLVMGCCDIR/bytecode-libs
      This environment variable helps the LLVM GCC front end find bytecode libraries that it will need for compilation.

      -

      alias llvmgcc LLVMGCCDIR/llvm-gcc/bin/gcc -
      alias llvmg++ LLVMGCCDIR/llvm-gcc/bin/g++ +
      alias llvmgcc LLVMGCCDIR/bin/gcc +
      alias llvmg++ LLVMGCCDIR/bin/g++
      This alias allows you to use the LLVM C and C++ front ends without putting them in your PATH or typing in their complete pathnames. @@ -515,7 +515,7 @@ This environment variable is used to locate "system" libraries like "-lc" and "-lm" when linking. This variable should be set to the absolute path for the bytecode-libs subdirectory of the GCC front end - install, or LLVMGCCDIR/llvm-gcc/bytecode-libs. For example, one might + install, or LLVMGCCDIR/bytecode-libs. For example, one might set LLVM_LIB_SEARCH_PATH to /home/vadve/lattner/local/x86/llvm-gcc/bytecode-libs for the X86 version of the GCC front end on our research machines.

      @@ -1043,7 +1043,7 @@ - Last modified: Mon Oct 27 12:00:00 CDT 2003 - +Last modified: Thu Nov 6 14:50:33 CST 2003 + From lattner at cs.uiuc.edu Thu Nov 6 14:53:03 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Nov 6 14:53:03 2003 Subject: [llvm-commits] CVS: llvm-www/releases/1.0/docs/GettingStarted.html Message-ID: <200311062052.OAA21054@zion.cs.uiuc.edu> Changes in directory llvm-www/releases/1.0/docs: GettingStarted.html updated: 1.1 -> 1.2 --- Log message: No wonder noone can set up LLVMGCCDIR correctly! --- Diffs of the changes: (+6 -6) Index: llvm-www/releases/1.0/docs/GettingStarted.html diff -u llvm-www/releases/1.0/docs/GettingStarted.html:1.1 llvm-www/releases/1.0/docs/GettingStarted.html:1.2 --- llvm-www/releases/1.0/docs/GettingStarted.html:1.1 Fri Oct 24 15:51:39 2003 +++ llvm-www/releases/1.0/docs/GettingStarted.html Thu Nov 6 14:52:02 2003 @@ -315,14 +315,14 @@ .cshrc or .profile.

      -
      LLVM_LIB_SEARCH_PATH=LLVMGCCDIR/llvm-gcc/bytecode-libs +
      LLVM_LIB_SEARCH_PATH=LLVMGCCDIR/bytecode-libs
      This environment variable helps the LLVM GCC front end find bytecode libraries that it will need for compilation.

      -

      alias llvmgcc LLVMGCCDIR/llvm-gcc/bin/gcc -
      alias llvmg++ LLVMGCCDIR/llvm-gcc/bin/g++ +
      alias llvmgcc LLVMGCCDIR/bin/gcc +
      alias llvmg++ LLVMGCCDIR/bin/g++
      This alias allows you to use the LLVM C and C++ front ends without putting them in your PATH or typing in their complete pathnames. @@ -515,7 +515,7 @@ This environment variable is used to locate "system" libraries like "-lc" and "-lm" when linking. This variable should be set to the absolute path for the bytecode-libs subdirectory of the GCC front end - install, or LLVMGCCDIR/llvm-gcc/bytecode-libs. For example, one might + install, or LLVMGCCDIR/bytecode-libs. For example, one might set LLVM_LIB_SEARCH_PATH to /home/vadve/lattner/local/x86/llvm-gcc/bytecode-libs for the X86 version of the GCC front end on our research machines.

      @@ -1043,7 +1043,7 @@ - Last modified: Mon Aug 11 13:52:22 CDT 2003 - +Last modified: Thu Nov 6 14:51:02 CST 2003 + From gaeke at cs.uiuc.edu Thu Nov 6 15:14:01 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Thu Nov 6 15:14:01 2003 Subject: [llvm-commits] CVS: llvm/test/Regression/CFrontend/2003-07-22-ArrayAccessTypeSafety.c.tr 2003-08-06-BuiltinSetjmpLongjmp.c.tr 2003-08-17-DeadCodeShortCircuit.c.tr 2003-11-03-AddrArrayElement.c.tr Message-ID: <200311062113.PAA04454@gally.cs.uiuc.edu> Changes in directory llvm/test/Regression/CFrontend: 2003-07-22-ArrayAccessTypeSafety.c.tr updated: 1.2 -> 1.3 2003-08-06-BuiltinSetjmpLongjmp.c.tr updated: 1.1 -> 1.2 2003-08-17-DeadCodeShortCircuit.c.tr updated: 1.1 -> 1.2 2003-11-03-AddrArrayElement.c.tr updated: 1.1 -> 1.2 --- Log message: All 'llvmgcc' tests should specify %llvmgcc so that the path is passed in by qmtest. --- Diffs of the changes: (+4 -4) Index: llvm/test/Regression/CFrontend/2003-07-22-ArrayAccessTypeSafety.c.tr diff -u llvm/test/Regression/CFrontend/2003-07-22-ArrayAccessTypeSafety.c.tr:1.2 llvm/test/Regression/CFrontend/2003-07-22-ArrayAccessTypeSafety.c.tr:1.3 --- llvm/test/Regression/CFrontend/2003-07-22-ArrayAccessTypeSafety.c.tr:1.2 Tue Aug 19 16:57:23 2003 +++ llvm/test/Regression/CFrontend/2003-07-22-ArrayAccessTypeSafety.c.tr Thu Nov 6 15:13:45 2003 @@ -1,4 +1,4 @@ -/* RUN: llvmgcc -xc %s -c -o - | dis | not grep cast +/* RUN: %llvmgcc -xc %s -c -o - | dis | not grep cast */ void test(int* array, long long N) { Index: llvm/test/Regression/CFrontend/2003-08-06-BuiltinSetjmpLongjmp.c.tr diff -u llvm/test/Regression/CFrontend/2003-08-06-BuiltinSetjmpLongjmp.c.tr:1.1 llvm/test/Regression/CFrontend/2003-08-06-BuiltinSetjmpLongjmp.c.tr:1.2 --- llvm/test/Regression/CFrontend/2003-08-06-BuiltinSetjmpLongjmp.c.tr:1.1 Wed Aug 6 13:26:19 2003 +++ llvm/test/Regression/CFrontend/2003-08-06-BuiltinSetjmpLongjmp.c.tr Thu Nov 6 15:13:45 2003 @@ -1,4 +1,4 @@ -/* RUN: llvmgcc -xc %s -c -o - | dis | not grep __builtin_ +/* RUN: %llvmgcc -xc %s -c -o - | dis | not grep __builtin_ * * __builtin_longjmp/setjmp should get transformed into llvm.setjmp/longjmp * just like explicit setjmp/longjmp calls are. Index: llvm/test/Regression/CFrontend/2003-08-17-DeadCodeShortCircuit.c.tr diff -u llvm/test/Regression/CFrontend/2003-08-17-DeadCodeShortCircuit.c.tr:1.1 llvm/test/Regression/CFrontend/2003-08-17-DeadCodeShortCircuit.c.tr:1.2 --- llvm/test/Regression/CFrontend/2003-08-17-DeadCodeShortCircuit.c.tr:1.1 Sun Aug 17 21:57:31 2003 +++ llvm/test/Regression/CFrontend/2003-08-17-DeadCodeShortCircuit.c.tr Thu Nov 6 15:13:45 2003 @@ -1,4 +1,4 @@ -// RUN: llvmgcc -xc %s -c +// RUN: %llvmgcc -xc %s -c int test(_Bool pos, _Bool color) { return 0; Index: llvm/test/Regression/CFrontend/2003-11-03-AddrArrayElement.c.tr diff -u llvm/test/Regression/CFrontend/2003-11-03-AddrArrayElement.c.tr:1.1 llvm/test/Regression/CFrontend/2003-11-03-AddrArrayElement.c.tr:1.2 --- llvm/test/Regression/CFrontend/2003-11-03-AddrArrayElement.c.tr:1.1 Mon Nov 3 15:37:08 2003 +++ llvm/test/Regression/CFrontend/2003-11-03-AddrArrayElement.c.tr Thu Nov 6 15:13:45 2003 @@ -1,4 +1,4 @@ -// RUN: llvmgcc -xc %s -c -o - | llvm-dis | grep getelementptr +// RUN: %llvmgcc -xc %s -c -o - | llvm-dis | grep getelementptr // This should be turned into a tasty getelementptr instruction, not a nasty // series of casts and address arithmetic. From lattner at cs.uiuc.edu Thu Nov 6 15:31:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Nov 6 15:31:01 2003 Subject: [llvm-commits] CVS: llvm/utils/Burg/be.c closure.c Message-ID: <200311062130.PAA22408@zion.cs.uiuc.edu> Changes in directory llvm/utils/Burg: be.c updated: 1.3 -> 1.4 closure.c updated: 1.1 -> 1.2 --- Log message: fix warnings on sparc --- Diffs of the changes: (+4 -4) Index: llvm/utils/Burg/be.c diff -u llvm/utils/Burg/be.c:1.3 llvm/utils/Burg/be.c:1.4 --- llvm/utils/Burg/be.c:1.3 Mon Jan 20 00:19:18 2003 +++ llvm/utils/Burg/be.c Thu Nov 6 15:30:15 2003 @@ -1,4 +1,4 @@ -char rcsid_be[] = "$Id: be.c,v 1.3 2003/01/20 06:19:18 lattner Exp $"; +char rcsid_be[] = "$Id: be.c,v 1.4 2003/11/06 21:30:15 lattner Exp $"; #include #include @@ -414,7 +414,7 @@ fprintf(outfile, "short %s_cost[][%d] = {\n", prefix, DELTAWIDTH); for (i = 0; i <= max_erule_num; i++) { - makeCostVector(pVector[i], pVector[i] ? pVector[i]->rule->delta : 0); + makeCostVector(pVector[i] != 0, pVector[i] ? pVector[i]->rule->delta : 0); fprintf(outfile, ", /* "); printRule(pVector[i], "(none)"); fprintf(outfile, " = %d */\n", i); Index: llvm/utils/Burg/closure.c diff -u llvm/utils/Burg/closure.c:1.1 llvm/utils/Burg/closure.c:1.2 --- llvm/utils/Burg/closure.c:1.1 Tue Sep 17 18:03:29 2002 +++ llvm/utils/Burg/closure.c Thu Nov 6 15:30:15 2003 @@ -1,4 +1,4 @@ -char rcsid_closure[] = "$Id: closure.c,v 1.1 2002/09/17 23:03:29 lattner Exp $"; +char rcsid_closure[] = "$Id: closure.c,v 1.2 2003/11/06 21:30:15 lattner Exp $"; #include #include "b.h" @@ -31,7 +31,7 @@ int i; DeltaCost base; int exists; - int base_nt; + int base_nt = 0; assert(!t->closed); From lattner at cs.uiuc.edu Thu Nov 6 15:31:06 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Nov 6 15:31:06 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86TargetMachine.cpp Message-ID: <200311062130.PAA22397@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86TargetMachine.cpp updated: 1.35 -> 1.36 --- Log message: Fix warnings building on sparc --- Diffs of the changes: (+2 -2) Index: llvm/lib/Target/X86/X86TargetMachine.cpp diff -u llvm/lib/Target/X86/X86TargetMachine.cpp:1.35 llvm/lib/Target/X86/X86TargetMachine.cpp:1.36 --- llvm/lib/Target/X86/X86TargetMachine.cpp:1.35 Mon Oct 20 14:43:18 2003 +++ llvm/lib/Target/X86/X86TargetMachine.cpp Thu Nov 6 15:30:05 2003 @@ -149,7 +149,7 @@ char *OldByte = (char *) Old; *OldByte++ = 0xE9; // Emit JMP opcode. int32_t *OldWord = (int32_t *) OldByte; - int32_t NewAddr = (int32_t) New; - int32_t OldAddr = (int32_t) OldWord; + int32_t NewAddr = (intptr_t) New; + int32_t OldAddr = (intptr_t) OldWord; *OldWord = NewAddr - OldAddr - 4; // Emit PC-relative addr of New code. } From brukman at cs.uiuc.edu Thu Nov 6 15:56:02 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu Nov 6 15:56:02 2003 Subject: [llvm-commits] CVS: llvm/docs/FAQ.html Message-ID: <200311062155.PAA13711@zion.cs.uiuc.edu> Changes in directory llvm/docs: FAQ.html updated: 1.9 -> 1.10 --- Log message: * Added a "contents"-like list of questions at the beginning of the file * Use stylsheets. Really, people, work with me here. * Stop using those silly

      and
      and whatever else tags * Close tags --- Diffs of the changes: (+311 -207) Index: llvm/docs/FAQ.html diff -u llvm/docs/FAQ.html:1.9 llvm/docs/FAQ.html:1.10 --- llvm/docs/FAQ.html:1.9 Wed Oct 29 19:16:18 2003 +++ llvm/docs/FAQ.html Thu Nov 6 15:55:44 2003 @@ -1,214 +1,318 @@ - + + + + LLVM: Frequently Asked Questions + + + + +
      + LLVM: Frequently Asked Questions +
      + +
        +
      1. License +
          +
        1. Why are the LLVM source code and the front-end distributed under different + licenses?
        2. +
        3. Does the University of Illinois Open Source License really qualify as an + "open source" license?
        4. +
        5. Can I modify LLVM source code and redistribute the modified source?
        6. +
        7. Can I modify LLVM source code and redistribute binaries or other tools + based on it, without redistributing the source?
        8. +
      2. + +
      3. Source code +
          +
        1. In what language is LLVM written?
        2. +
        3. How portable is the LLVM source code?
        4. +
      4. + +
      5. Build Problems +
          +
        1. When I run configure, it finds the wrong C compiler.
        2. +
        3. I compile the code, and I get some error about /localhome.
        4. +
        5. The configure script finds the right C compiler, but it uses the + LLVM linker from a previous build. What do I do?
        6. +
        7. When creating a dynamic library, I get a strange GLIBC error.
        8. +
        9. I've updated my source tree from CVS, and now my build is trying to use a + file/directory that doesn't exist.
        10. +
        11. I've modified a Makefile in my source tree, but my build tree keeps using + the old version. What do I do?
        12. +
        13. I've upgraded to a new version of LLVM, and I get strange build + errors.
        14. +
        15. I've built LLVM and am testing it, but the tests freeze.
        16. +
        17. Why do test results differ when I perform different types of builds?
        18. +
      6. +
      + + +
      + License +
      + + +
      +

      Why are the LLVM source code and the front-end distributed under different +licenses?

      +
      + +
      +

      The C/C++ front-ends are based on GCC and must be distributed under the GPL. +Our aim is to distribute LLVM source code under a much less restrictive +license, in particular one that does not compel users who distribute tools based +on modifying the source to redistribute the modified source code as well.

      +
      + +
      +

      Does the University of Illinois Open Source License really qualify as an +"open source" license?

      +
      + +
      +

      Yes, the license is certified by the Open +Source Initiative (OSI).

      +
      + +
      +

      Can I modify LLVM source code and redistribute the modified source?

      +
      + +
      +

      Yes. The modified source distribution must retain the copyright notice and +follow the three bulletted conditions listed in the LLVM license.

      +
      + +
      +

      Can I modify LLVM source code and redistribute binaries or other tools based +on it, without redistributing the source?

      +
      + +
      +

      Yes, this is why we distribute LLVM under a less restrictive license than +GPL, as explained in the first question above.

      +
      + + + + + +
      +

      In what language is LLVM written?

      +
      + +
      +

      All of the LLVM tools and libraries are written in C++ with extensive use of +the STL.

      +
      + +
      +

      How portable is the LLVM source code?

      +
      + +
      +

      The LLVM source code should be portable to most modern UNIX-like operating +systems. Most of the code is written in standard C++ with operating system +services abstracted to a support library. The tools required to build and test +LLVM have been ported to a plethora of platforms.

      + +

      Some porting problems may exist in the following areas:

      + +
        + +
      • The GCC front end code is not as portable as the LLVM suite, so it may not + compile as well on unsupported platforms.
      • + +
      • The Python test classes are more UNIX-centric than they should be, so + porting to non-UNIX like platforms (i.e. Windows, MacOS 9) will require some + effort.
      • + +
      • The LLVM build system relies heavily on UNIX shell tools, like the Bourne + Shell and sed. Porting to systems without these tools (MacOS 9, Plan 9) will + require more effort.
      • + +
      + +
      + + + + + +
      +

      When I run configure, it finds the wrong C compiler.

      +
      + +
      + +

      The configure script attempts to locate first gcc and then +cc, unless it finds compiler paths set in CC and CXX +for the C and C++ compiler, respectively.

      + +

      If configure finds the wrong compiler, either adjust your +PATH environment variable or set CC and CXX +explicitly.

      + +
      + +
      +

      I compile the code, and I get some error about /localhome.

      +
      + +
      + +

      There are several possible causes for this. The first is that you didn't set +a pathname properly when using configure, and it defaulted to a +pathname that we use on our research machines.

      + +

      Another possibility is that we hardcoded a path in our Makefiles. If you see +this, please email the LLVM bug mailing list with the name of the offending +Makefile and a description of what is wrong with it.

      + +
      + +
      +

      The configure script finds the right C compiler, but it uses the +LLVM linker from a previous build. What do I do?

      +
      + +
      +

      The configure script uses the PATH to find executables, so +if it's grabbing the wrong linker/assembler/etc, there are two ways to fix +it:

      + +
        + +
      1. Adjust your PATH environment variable so that the correct + program appears first in the PATH. This may work, but may not be + convenient when you want them first in your path for other + work.

      2. + +
      3. Run configure with an alternative PATH that is + correct. In a Borne compatible shell, the syntax would be:

        + +

        PATH= ./configure ...

        + +

        This is still somewhat inconvenient, but it allows configure + to do its work without having to adjust your PATH + permanently.

      4. + +
      + +
      + +
      +

      When creating a dynamic library, I get a strange GLIBC error.

      +
      + +
      +

      Under some operating systems (i.e. Linux), libtool does not work correctly if +GCC was compiled with the --disable-shared option. To work around this, install +your own version of GCC that has shared libraries enabled by default.

      +
      + +
      +

      I've updated my source tree from CVS, and now my build is trying to use a +file/directory that doesn't exist.

      +
      + +
      +

      You need to re-run configure in your object directory. When new Makefiles +are added to the source tree, they have to be copied over to the object tree in +order to be used by the build.

      +
      + +
      +

      I've modified a Makefile in my source tree, but my build tree keeps using the +old version. What do I do?

      +
      + +
      + +

      If the Makefile already exists in your object tree, you +can just run the following command in the top level directory of your object +tree:

      + +

      ./config.status <relative path to Makefile>

      + +

      If the Makefile is new, you will have to modify the configure script to copy +it over.

      + +
      + +
      +

      I've upgraded to a new version of LLVM, and I get strange build errors.

      +
      + +
      + +

      Sometimes, changes to the LLVM source code alters how the build system works. +Changes in libtool, autoconf, or header file dependencies are especially prone +to this sort of problem.

      + +

      The best thing to try is to remove the old files and re-build. In most +cases, this takes care of the problem. To do this, just type make +clean and then make in the directory that fails to build.

      + +
      + +
      +

      I've built LLVM and am testing it, but the tests freeze.

      +
      + +
      + +

      This is most likely occurring because you built a profile or release +(optimized) build of LLVM and have not specified the same information on the +gmake command line.

      + +

      For example, if you built LLVM with the command:

      + +

      gmake ENABLE_PROFILING=1 + +

      ...then you must run the tests with the following commands:

      + +

      cd llvm/test
      gmake ENABLE_PROFILING=1

      + +
      + +
      +

      Why do test results differ when I perform different types of builds?

      +
      + +
      + +

      The LLVM test suite is dependent upon several features of the LLVM tools and +libraries.

      + +

      First, the debugging assertions in code are not enabled in optimized or +profiling builds. Hence, tests that used to fail may pass.

      + +

      Second, some tests may rely upon debugging options or behavior that is only +available in the debug build. These tests will fail in an optimized or profile +build.

      -

      -
      -LLVM: Frequently Asked Questions -
      -

      +
      -
      - - -

      -Licenses -

      - - -
      -
      Why are the LLVM source code and the front-end distributed - under different licenses? -
      - The C/C++ front-ends are based on GCC and must be distributed under - the GPL. Our aim is to distribute LLVM source code under a much - less restrictive license, in particular one that does not - compel users who distribute tools based on modifying the source to - redistribute the modified source code as well. -

      -

      Does the University of Illinois Open Source License really qualify - as an "open source" license? -
      Yes, the license is - certified - by the Open Source Initiative (OSI). -

      -

      Can I modify LLVM source code and redistribute the modified - source? -
      - Yes. The modified source distribution must retain the - copyright notice and follow the three bulletted conditions listed in - the LLVM license. -

      -

      Can I modify LLVM source code and redistribute binaries or - other tools based on it, without redistributing the source? -
      - Yes, this is why we distribute LLVM under a less restrictive license - than GPL, as explained in the first question above. -

      -

      -
      - - -

      -Source Code -

      - - -
      -
      In what language is LLVM written? -
      - All of the LLVM tools and libraries are written in C++ with extensive use - of the STL. -

      - -

      How portable is the LLVM source code? -
      - The LLVM source code should be portable to most modern UNIX-like operating - systems. Most of the code is written in standard C++ with operating - system services abstracted to a support library. The tools required to - build and test LLVM have been ported to a plethora of platforms. -

      - Some porting problems may exist in the following areas: -

        -
      • The GCC front end code is not as portable as the LLVM suite, so it - may not compile as well on unsupported platforms. - -

        - -

      • The Python test classes are more UNIX-centric than they should be, - so porting to non-UNIX like platforms (i.e. Windows, MacOS 9) will - require some effort. -

        - -

      • The LLVM build system relies heavily on UNIX shell tools, like the - Bourne Shell and sed. Porting to systems without these tools (MacOS 9, - Plan 9) will require more effort. -
      -
      +
      - - -

      -Build Problems -

      - - -
      -
      When I run configure, it finds the wrong C compiler. -
      - The configure script attempts to locate first gcc and - then cc, unless it finds compiler paths set in CC and - CXX for the C and C++ compiler, respectively. - - If configure finds the wrong compiler, either adjust your - PATH environment variable or set CC and CXX - explicitly. -

      - -

      I compile the code, and I get some error about /localhome. -
      - There are several possible causes for this. The first is that you - didn't set a pathname properly when using configure, and it - defaulted to a pathname that we use on our research machines. -

      - Another possibility is that we hardcoded a path in our Makefiles. If - you see this, please email the LLVM bug mailing list with the name of - the offending Makefile and a description of what is wrong with it. - -

      The configure script finds the right C compiler, but it - uses the LLVM linker from a previous build. What do I do? -
      - The configure script uses the PATH to find - executables, so if it's grabbing the wrong linker/assembler/etc, there - are two ways to fix it: -
        -
      1. Adjust your PATH environment variable so that the - correct program appears first in the PATH. This may work, - but may not be convenient when you want them first in your - path for other work. -

        - -

      2. Run configure with an alternative PATH that - is correct. In a Borne compatible shell, the syntax would be: -

        - PATH= ./configure ... -

        - This is still somewhat inconvenient, but it allows - configure to do its work without having to adjust your - PATH permanently. -

      - -
      When creating a dynamic library, I get a strange GLIBC error. -
      - Under some operating systems (i.e. Linux), libtool does not work correctly - if GCC was compiled with the --disable-shared option. To work around this, - install your own version of GCC that has shared libraries enabled by - default. -

      - -

      I've updated my source tree from CVS, and now my build is trying to - use a file/directory that doesn't exist. -
      - You need to re-run configure in your object directory. When new Makefiles - are added to the source tree, they have to be copied over to the object - tree in order to be used by the build. -

      - -

      I've modified a Makefile in my source tree, but my build tree keeps - using the old version. What do I do? -
      - If the Makefile already exists in your object tree, you can just run the - following command in the top level directory of your object tree: -

      - ./config.status <relative path to Makefile> -

      - If the Makefile is new, you will have to modify the configure script to copy - it over. -

      - -

      I've upgraded to a new version of LLVM, and I get strange build - errors. -
      - Sometimes changes to the LLVM source code alters how the build system - works. Changes in libtool, autoconf, or header file dependencies are - especially prone to this sort of problem. -

      - The best thing to try is to remove the old files and re-build. In most - cases, this takes care of the problem. To do this, just type make - clean and then make in the directory that fails to build. -

      - -

      I've built LLVM and am testing it, but the tests freeze. -
      - This is most likely occurring because you built a profile or release - (optimized) build of LLVM and have not specified the same information on - the gmake command line. -

      - For example, if you built LLVM with the command: -

      - gmake ENABLE_PROFILING=1 -

      - ...then you must run the tests with the following commands: -

      - cd llvm/test
      gmake ENABLE_PROFILING=1
      -

      - -

      Why do test results differ when I perform different types of - builds? -
      - The LLVM test suite is dependent upon several features of the LLVM tools - and libraries. -

      - First, the debugging assertions in code are not enabled in optimized or - profiling builds. Hence, tests that used to fail may pass. -

      - Second, some tests may rely upon debugging options or behavior that is - only available in the debug build. These tests will fail in an optimized - or profile build. -

      -
      - -The LLVM Compiler Infrastructure -
      + From lattner at cs.uiuc.edu Thu Nov 6 18:35:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Nov 6 18:35:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/Makefile Message-ID: <200311070034.SAA31784@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: Makefile updated: 1.14 -> 1.15 --- Log message: Hopefully fix the objdir != srcdir issue --- Diffs of the changes: (+12 -6) Index: llvm/lib/Target/X86/Makefile diff -u llvm/lib/Target/X86/Makefile:1.14 llvm/lib/Target/X86/Makefile:1.15 --- llvm/lib/Target/X86/Makefile:1.14 Wed Nov 5 00:43:36 2003 +++ llvm/lib/Target/X86/Makefile Thu Nov 6 18:34:33 2003 @@ -15,27 +15,33 @@ X86GenRegisterInfo.inc X86GenInstrNames.inc \ X86GenInstrInfo.inc X86GenInstrSelector.inc -X86GenRegisterNames.inc:: X86.td X86RegisterInfo.td ../Target.td $(TBLGEN) +X86GenRegisterNames.inc:: $(SourceDir)/X86.td $(SourceDir)/X86RegisterInfo.td \ + $(SourceDir)/../Target.td $(TBLGEN) @echo "Building X86.td register names with tblgen" $(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $< -gen-register-enums -o $@ -X86GenRegisterInfo.h.inc:: X86.td X86RegisterInfo.td ../Target.td $(TBLGEN) +X86GenRegisterInfo.h.inc:: $(SourceDir)/X86.td $(SourceDir)/X86RegisterInfo.td \ + $(SourceDir)/../Target.td $(TBLGEN) @echo "Building X86.td register information header with tblgen" $(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $< -gen-register-desc-header -o $@ -X86GenRegisterInfo.inc:: X86.td X86RegisterInfo.td ../Target.td $(TBLGEN) +X86GenRegisterInfo.inc:: $(SourceDir)/X86.td $(SourceDir)/X86RegisterInfo.td \ + $(SourceDir)/../Target.td $(TBLGEN) @echo "Building X86.td register information implementation with tblgen" $(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $< -gen-register-desc -o $@ -X86GenInstrNames.inc:: X86.td X86InstrInfo.td ../Target.td $(TBLGEN) +X86GenInstrNames.inc:: $(SourceDir)/X86.td $(SourceDir)/X86InstrInfo.td \ + $(SourceDir)/../Target.td $(TBLGEN) @echo "Building X86.td instruction names with tblgen" $(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $< -gen-instr-enums -o $@ -X86GenInstrInfo.inc:: X86.td X86InstrInfo.td ../Target.td $(TBLGEN) +X86GenInstrInfo.inc:: $(SourceDir)/X86.td $(SourceDir)/X86InstrInfo.td \ + $(SourceDir)/../Target.td $(TBLGEN) @echo "Building X86.td instruction information with tblgen" $(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $< -gen-instr-desc -o $@ -X86GenInstrSelector.inc:: X86.td X86InstrInfo.td ../Target.td $(TBLGEN) +X86GenInstrSelector.inc:: $(SourceDir)/X86.td $(SourceDir)/X86InstrInfo.td \ + $(SourceDir)/../Target.td $(TBLGEN) @echo "Building X86.td instruction selector with tblgen" $(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $< -gen-instr-selector -o $@ From lattner at cs.uiuc.edu Thu Nov 6 18:39:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Nov 6 18:39:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/Makefile Message-ID: <200311070038.SAA00974@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: Makefile updated: 1.34 -> 1.35 --- Log message: Hopefully this will fix PR98 --- Diffs of the changes: (+2 -2) Index: llvm/lib/Target/Sparc/Makefile diff -u llvm/lib/Target/Sparc/Makefile:1.34 llvm/lib/Target/Sparc/Makefile:1.35 --- llvm/lib/Target/Sparc/Makefile:1.34 Wed Oct 29 14:07:35 2003 +++ llvm/lib/Target/Sparc/Makefile Thu Nov 6 18:38:09 2003 @@ -19,7 +19,7 @@ DEBUG_FLAG = -D_DEBUG endif -Sparc.burg.in1 : Sparc.burg.in +Sparc.burg.in1 : $(SourceDir)/Sparc.burg.in $(CXX) -E -I$(LLVM_SRC_ROOT)/include $(DEBUG_FLAG) -x c++ $< | $(SED) '/^#/d' | $(SED) 's/Ydefine/#define/' > $@ Sparc.burm : Sparc.burg.in1 @@ -47,7 +47,7 @@ $(TARGET_NAME)CodeEmitter.cpp:: $(TARGET_NAME)CodeEmitter.inc -$(TARGET_NAME)CodeEmitter.inc:: $(TARGET_NAME).td $(TABLEGEN_FILES) $(TBLGEN) +$(TARGET_NAME)CodeEmitter.inc:: $(SourceDir)/$(TARGET_NAME).td $(TABLEGEN_FILES) $(TBLGEN) @echo "Tblgen'ing $<" $(TBLGEN) -I $(SourceDir) $< -gen-emitter -o $@ From lattner at cs.uiuc.edu Thu Nov 6 22:43:04 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Nov 6 22:43:04 2003 Subject: [llvm-commits] CVS: llvm/Makefile.rules Message-ID: <200311070440.WAA06923@zion.cs.uiuc.edu> Changes in directory llvm: Makefile.rules updated: 1.154 -> 1.155 --- Log message: Fix a really bad build problem for users who have .o in their build directory! Thanks to Reid Spencer for figuring this out! :) --- Diffs of the changes: (+2 -2) Index: llvm/Makefile.rules diff -u llvm/Makefile.rules:1.154 llvm/Makefile.rules:1.155 --- llvm/Makefile.rules:1.154 Wed Nov 5 00:41:14 2003 +++ llvm/Makefile.rules Thu Nov 6 22:39:53 2003 @@ -800,11 +800,11 @@ # Create dependencies for the *.cpp files... $(BUILD_OBJ_DIR)/Depend/%.d: %.cpp $(BUILD_OBJ_DIR)/Depend/.dir - $(VERB) $(Depend) $< | $(SED) 's|\.o|\.lo|' | $(SED) 's|$*\.lo *|$(BUILD_OBJ_DIR)/Release/& $(BUILD_OBJ_DIR)/Profile/& $(BUILD_OBJ_DIR)/Debug/& $(BUILD_OBJ_DIR)/Depend/$(@F)|g' > $@ + $(VERB) $(Depend) $< | $(SED) 's|\.o$$|\.lo|' | $(SED) 's|$*\.lo *|$(BUILD_OBJ_DIR)/Release/& $(BUILD_OBJ_DIR)/Profile/& $(BUILD_OBJ_DIR)/Debug/& $(BUILD_OBJ_DIR)/Depend/$(@F)|g' > $@ # Create dependencies for the *.c files... $(BUILD_OBJ_DIR)/Depend/%.d: %.c $(BUILD_OBJ_DIR)/Depend/.dir - $(VERB) $(DependC) -o $@ $< | $(SED) 's|\.o|\.lo|' | $(SED) 's|$*\.lo *|$(BUILD_OBJ_DIR)/Release/& $(BUILD_OBJ_DIR)/Profile/& $(BUILD_OBJ_DIR)/Debug/& $(BUILD_OBJ_DIR)/Depend/$(@F)|g' > $@ + $(VERB) $(DependC) -o $@ $< | $(SED) 's|\.o$$|\.lo|' | $(SED) 's|$*\.lo *|$(BUILD_OBJ_DIR)/Release/& $(BUILD_OBJ_DIR)/Profile/& $(BUILD_OBJ_DIR)/Debug/& $(BUILD_OBJ_DIR)/Depend/$(@F)|g' > $@ # # Autoconf Dependencies. From lattner at cs.uiuc.edu Thu Nov 6 22:48:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Nov 6 22:48:01 2003 Subject: [llvm-commits] CVS: llvm/docs/ReleaseNotes.html Message-ID: <200311070447.WAA08279@zion.cs.uiuc.edu> Changes in directory llvm/docs: ReleaseNotes.html updated: 1.31 -> 1.32 --- Log message: Add bugz --- Diffs of the changes: (+6 -1) Index: llvm/docs/ReleaseNotes.html diff -u llvm/docs/ReleaseNotes.html:1.31 llvm/docs/ReleaseNotes.html:1.32 --- llvm/docs/ReleaseNotes.html:1.31 Wed Nov 5 00:30:04 2003 +++ llvm/docs/ReleaseNotes.html Thu Nov 6 22:46:56 2003 @@ -66,6 +66,7 @@
      1. A new LLVM profiler, similar to gprof is available
      2. +
      3. The LLVM C/C++ front-end now compiles on Mac OSX!

      In this release, the following Quality of Implementation issues were fixed:

      @@ -99,6 +100,10 @@

    • [C++] Catch blocks make unparsable labels
    • [C++] Initializing array with constructable objects fail
    • [gccld] The -r (relinking) option does not work correctly
    • +
    • [bcreader] Cannot read shift constant expressions from bytecode file
    • +
    • [lowersetjmp] Lowersetjmp pass breaks dominance properties!
    • +
    • llvm-gcc tries to add bools
    • +
    • [buildscripts] Building into objdir with .o in it fails
    • At this time, LLVM is known to work properly with SPEC CPU 2000, the Olden @@ -405,6 +410,6 @@ Maintained By: The LLVM Team
      -Last modified: Wed Nov 5 00:07:20 CST 2003 +Last modified: Thu Nov 6 13:21:28 CST 2003 From lattner at cs.uiuc.edu Thu Nov 6 22:48:07 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu Nov 6 22:48:07 2003 Subject: [llvm-commits] CVS: llvm-www/releases/1.0/docs/ReleaseNotes.html Message-ID: <200311070447.WAA08405@zion.cs.uiuc.edu> Changes in directory llvm-www/releases/1.0/docs: ReleaseNotes.html updated: 1.21 -> 1.22 --- Log message: Bugz --- Diffs of the changes: (+13 -1) Index: llvm-www/releases/1.0/docs/ReleaseNotes.html diff -u llvm-www/releases/1.0/docs/ReleaseNotes.html:1.21 llvm-www/releases/1.0/docs/ReleaseNotes.html:1.22 --- llvm-www/releases/1.0/docs/ReleaseNotes.html:1.21 Wed Nov 5 00:30:26 2003 +++ llvm-www/releases/1.0/docs/ReleaseNotes.html Thu Nov 6 22:47:20 2003 @@ -181,6 +181,14 @@

    • [gccld] The -r (relinking) option does not work correctly
    • +

    • [bcreader] Cannot read shift constant +expressions from bytecode file
    • + +

    • [lowersetjmp] Lowersetjmp pass breaks +dominance properties!
    • + +

    • [buildscripts] Building into objdir with .o in it fails
    • +


    Known problems with the C front-end

    Notes:

    • Inline assembly is not yet supported.

      @@ -465,6 +477,6 @@ Maintained By: The LLVM Team
      -Last modified: Wed Nov 5 00:07:37 CST 2003 +Last modified: Thu Nov 6 13:21:50 CST 2003 From gaeke at cs.uiuc.edu Thu Nov 6 23:24:01 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Thu Nov 6 23:24:01 2003 Subject: [llvm-commits] CVS: llvm/lib/ExecutionEngine/Interpreter/Execution.cpp Interpreter.h Message-ID: <200311070523.XAA12573@zion.cs.uiuc.edu> Changes in directory llvm/lib/ExecutionEngine/Interpreter: Execution.cpp updated: 1.106 -> 1.107 Interpreter.h updated: 1.47 -> 1.48 --- Log message: Refactor the return-from-function code into popStackAndReturnValueToCaller(). Make external function calls slightly less special; now they get a stack frame. --- Diffs of the changes: (+42 -37) Index: llvm/lib/ExecutionEngine/Interpreter/Execution.cpp diff -u llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.106 llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.107 --- llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.106 Wed Nov 5 00:20:27 2003 +++ llvm/lib/ExecutionEngine/Interpreter/Execution.cpp Thu Nov 6 23:22:49 2003 @@ -432,9 +432,38 @@ ECStack.clear(); } +/// Pop the last stack frame off of ECStack and then copy the result +/// back into the result variable if we are not returning void. The +/// result variable may be the ExitCode, or the Value of the calling +/// CallInst if there was a previous stack frame. This procedure may +/// invalidate any ECStack iterators you have. +/// +void Interpreter::popStackAndReturnValueToCaller (const Type *RetTy, + GenericValue Result) { + // Pop the current stack frame. + ECStack.pop_back(); + + if (ECStack.empty()) { // Finished main. Put result into exit code... + if (RetTy && RetTy->isIntegral()) { // Nonvoid return type? + ExitCode = Result.IntVal; // Capture the exit code of the program + } else { + ExitCode = 0; + } + } else { + // If we have a previous stack frame, and we have a previous call, + // fill in the return value... + ExecutionContext &CallingSF = ECStack.back(); + if (CallingSF.Caller) { + if (CallingSF.Caller->getType() != Type::VoidTy) // Save result... + SetValue(CallingSF.Caller, Result, CallingSF); + CallingSF.Caller = 0; // We returned from the call... + } + } +} + void Interpreter::visitReturnInst(ReturnInst &I) { ExecutionContext &SF = ECStack.back(); - const Type *RetTy = 0; + const Type *RetTy = Type::VoidTy; GenericValue Result; // Save away the return value... (if we are not 'ret void') @@ -443,25 +472,7 @@ Result = getOperandValue(I.getReturnValue(), SF); } - // Pop the current stack frame... this invalidates SF - ECStack.pop_back(); - - if (ECStack.empty()) { // Finished main. Put result into exit code... - if (RetTy && RetTy->isIntegral()) { // Nonvoid return type? - ExitCode = Result.IntVal; // Capture the exit code of the program - } else { - ExitCode = 0; - } - } else { - // If we have a previous stack frame, and we have a previous call, - // fill in the return value... - ExecutionContext &NewSF = ECStack.back(); - if (NewSF.Caller) { - if (NewSF.Caller->getType() != Type::VoidTy) // Save result... - SetValue(NewSF.Caller, Result, NewSF); - NewSF.Caller = 0; // We returned from the call... - } - } + popStackAndReturnValueToCaller(RetTy, Result); } void Interpreter::visitBranchInst(BranchInst &I) { @@ -796,27 +807,20 @@ assert((ECStack.empty() || ECStack.back().Caller == 0 || ECStack.back().Caller->getNumOperands()-1 == ArgVals.size()) && "Incorrect number of arguments passed into function call!"); - if (F->isExternal()) { - GenericValue Result = callExternalFunction(F, ArgVals); - const Type *RetTy = F->getReturnType(); - - // Copy the result back into the result variable if we are not returning - // void. - if (RetTy != Type::VoidTy) { - if (!ECStack.empty() && ECStack.back().Caller) { - ExecutionContext &SF = ECStack.back(); - SetValue(SF.Caller, Result, SF); - SF.Caller = 0; // We returned from the call... - } - } - - return; - } - // Make a new stack frame... and fill it in. ECStack.push_back(ExecutionContext()); ExecutionContext &StackFrame = ECStack.back(); StackFrame.CurFunction = F; + + // Special handling for external functions. + if (F->isExternal()) { + GenericValue Result = callExternalFunction (F, ArgVals); + // Simulate a 'ret' instruction of the appropriate type. + popStackAndReturnValueToCaller (F->getReturnType (), Result); + return; + } + + // Get pointers to first LLVM BB & Instruction in function. StackFrame.CurBB = F->begin(); StackFrame.CurInst = StackFrame.CurBB->begin(); Index: llvm/lib/ExecutionEngine/Interpreter/Interpreter.h diff -u llvm/lib/ExecutionEngine/Interpreter/Interpreter.h:1.47 llvm/lib/ExecutionEngine/Interpreter/Interpreter.h:1.48 --- llvm/lib/ExecutionEngine/Interpreter/Interpreter.h:1.47 Wed Nov 5 00:20:27 2003 +++ llvm/lib/ExecutionEngine/Interpreter/Interpreter.h Thu Nov 6 23:22:49 2003 @@ -157,6 +157,7 @@ GenericValue getOperandValue(Value *V, ExecutionContext &SF); GenericValue executeCastOperation(Value *SrcVal, const Type *Ty, ExecutionContext &SF); + void popStackAndReturnValueToCaller(const Type *RetTy, GenericValue Result); }; #endif From lattner at cs.uiuc.edu Fri Nov 7 09:21:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Nov 7 09:21:01 2003 Subject: [llvm-commits] CVS: llvm/include/Support/MallocAllocator.h Message-ID: <200311071520.JAA11351@neo.cs.uiuc.edu> Changes in directory llvm/include/Support: MallocAllocator.h updated: 1.1 -> 1.2 --- Log message: Add some ctors for this allocator --- Diffs of the changes: (+4 -0) Index: llvm/include/Support/MallocAllocator.h diff -u llvm/include/Support/MallocAllocator.h:1.1 llvm/include/Support/MallocAllocator.h:1.2 --- llvm/include/Support/MallocAllocator.h:1.1 Tue Nov 4 16:38:28 2003 +++ llvm/include/Support/MallocAllocator.h Fri Nov 7 09:20:06 2003 @@ -36,6 +36,10 @@ typedef MallocAllocator other; }; + template + MallocAllocator(const MallocAllocator &) {} + MallocAllocator() {} + pointer address(reference x) const { return &x; } const_pointer address(const_reference x) const { return &x; } size_type max_size() const { return ~0 / sizeof(T); } From brukman at cs.uiuc.edu Fri Nov 7 11:20:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Nov 7 11:20:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/Transforms/Scalar.h Message-ID: <200311071719.LAA15423@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Transforms: Scalar.h updated: 1.28 -> 1.29 --- Log message: Declare FunctionPasses as such. --- Diffs of the changes: (+3 -3) Index: llvm/include/llvm/Transforms/Scalar.h diff -u llvm/include/llvm/Transforms/Scalar.h:1.28 llvm/include/llvm/Transforms/Scalar.h:1.29 --- llvm/include/llvm/Transforms/Scalar.h:1.28 Mon Oct 20 15:19:47 2003 +++ llvm/include/llvm/Transforms/Scalar.h Fri Nov 7 11:19:39 2003 @@ -101,7 +101,7 @@ // examining the SSA value graph of the function, instead of doing slow // bit-vector computations. // -Pass *createGCSEPass(); +FunctionPass *createGCSEPass(); //===----------------------------------------------------------------------===// @@ -132,7 +132,7 @@ // LICM - This pass is a simple natural loop based loop invariant code motion // pass. // -Pass *createLICMPass(); +FunctionPass *createLICMPass(); //===----------------------------------------------------------------------===// @@ -179,7 +179,7 @@ // // For example: 4 + (x + 5) -> x + (4 + 5) // -Pass *createReassociatePass(); +FunctionPass *createReassociatePass(); //===----------------------------------------------------------------------===// // From brukman at cs.uiuc.edu Fri Nov 7 11:21:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Nov 7 11:21:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/GCSE.cpp LICM.cpp Reassociate.cpp Message-ID: <200311071720.LAA15662@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: GCSE.cpp updated: 1.30 -> 1.31 LICM.cpp updated: 1.39 -> 1.40 Reassociate.cpp updated: 1.27 -> 1.28 --- Log message: Declare FunctionPasses as such so that they can be used in FunctionPassManager. --- Diffs of the changes: (+3 -3) Index: llvm/lib/Transforms/Scalar/GCSE.cpp diff -u llvm/lib/Transforms/Scalar/GCSE.cpp:1.30 llvm/lib/Transforms/Scalar/GCSE.cpp:1.31 --- llvm/lib/Transforms/Scalar/GCSE.cpp:1.30 Mon Oct 20 14:43:19 2003 +++ llvm/lib/Transforms/Scalar/GCSE.cpp Fri Nov 7 11:20:18 2003 @@ -54,7 +54,7 @@ } // createGCSEPass - The public interface to this file... -Pass *createGCSEPass() { return new GCSE(); } +FunctionPass *createGCSEPass() { return new GCSE(); } // GCSE::runOnFunction - This is the main transformation entry point for a Index: llvm/lib/Transforms/Scalar/LICM.cpp diff -u llvm/lib/Transforms/Scalar/LICM.cpp:1.39 llvm/lib/Transforms/Scalar/LICM.cpp:1.40 --- llvm/lib/Transforms/Scalar/LICM.cpp:1.39 Mon Oct 20 14:43:19 2003 +++ llvm/lib/Transforms/Scalar/LICM.cpp Fri Nov 7 11:20:18 2003 @@ -174,7 +174,7 @@ RegisterOpt X("licm", "Loop Invariant Code Motion"); } -Pass *createLICMPass() { return new LICM(); } +FunctionPass *createLICMPass() { return new LICM(); } /// runOnFunction - For LICM, this simply traverses the loop structure of the /// function, hoisting expressions out of loops if possible. Index: llvm/lib/Transforms/Scalar/Reassociate.cpp diff -u llvm/lib/Transforms/Scalar/Reassociate.cpp:1.27 llvm/lib/Transforms/Scalar/Reassociate.cpp:1.28 --- llvm/lib/Transforms/Scalar/Reassociate.cpp:1.27 Mon Oct 20 14:43:19 2003 +++ llvm/lib/Transforms/Scalar/Reassociate.cpp Fri Nov 7 11:20:18 2003 @@ -58,7 +58,7 @@ RegisterOpt X("reassociate", "Reassociate expressions"); } -Pass *createReassociatePass() { return new Reassociate(); } +FunctionPass *createReassociatePass() { return new Reassociate(); } void Reassociate::BuildRankMap(Function &F) { unsigned i = 2; From lattner at cs.uiuc.edu Fri Nov 7 11:22:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Nov 7 11:22:00 2003 Subject: [llvm-commits] CVS: poolalloc/runtime/PoolAllocator/PageManager.h PageManager.cpp Message-ID: <200311071721.LAA16265@zion.cs.uiuc.edu> Changes in directory poolalloc/runtime/PoolAllocator: PageManager.h updated: 1.1 -> 1.2 PageManager.cpp updated: 1.1 -> 1.2 --- Log message: Make the page manager more efficient, by allocating more than one page at a time --- Diffs of the changes: (+42 -13) Index: poolalloc/runtime/PoolAllocator/PageManager.h diff -u poolalloc/runtime/PoolAllocator/PageManager.h:1.1 poolalloc/runtime/PoolAllocator/PageManager.h:1.2 --- poolalloc/runtime/PoolAllocator/PageManager.h:1.1 Tue Nov 4 14:26:09 2003 +++ poolalloc/runtime/PoolAllocator/PageManager.h Fri Nov 7 11:21:24 2003 @@ -15,9 +15,16 @@ #ifndef PAGEMANAGER_H #define PAGEMANAGER_H -/// getPageSize - Return the size of the unit of memory allocated by -/// AllocatePage. This is a value that is typically several kilobytes in size. -unsigned getPageSize(); +/// InitializePageManager - This function must be called before any other page +/// manager accesses are performed. It may be called multiple times. +/// +void InitializePageManager(); + +/// PageSize - Contains the size of the unit of memory allocated by +/// AllocatePage. This is a value that is typically several kilobytes in size, +/// and is guaranteed to be a power of two. +/// +extern unsigned PageSize; /// AllocatePage - This function returns a chunk of memory with size and /// alignment specified by getPageSize(). Index: poolalloc/runtime/PoolAllocator/PageManager.cpp diff -u poolalloc/runtime/PoolAllocator/PageManager.cpp:1.1 poolalloc/runtime/PoolAllocator/PageManager.cpp:1.2 --- poolalloc/runtime/PoolAllocator/PageManager.cpp:1.1 Tue Nov 4 14:26:09 2003 +++ poolalloc/runtime/PoolAllocator/PageManager.cpp Fri Nov 7 11:21:24 2003 @@ -15,23 +15,23 @@ #ifndef _POSIX_MAPPED_FILES #define _POSIX_MAPPED_FILES #endif +#include "Support/MallocAllocator.h" #include "Config/unistd.h" #include "Config/sys/mman.h" #include +#include -static unsigned PageSize; +unsigned PageSize = 0; +// Explicitly use the malloc allocator here, to avoid depending on the C++ +// runtime library. +static std::vector > *FreePages = 0; -/// getPageSize - Return the size of the unit of memory allocated by -/// AllocatePage. This is a value that is typically several kilobytes in size. -unsigned getPageSize() { +void InitializePageManager() { if (!PageSize) PageSize = sysconf(_SC_PAGESIZE); - return PageSize; } -/// AllocatePage - This function returns a chunk of memory with size and -/// alignment specified by getPageSize(). -void *AllocatePage() { +static void *GetPages(unsigned NumPages) { #if defined(i386) || defined(__i386__) || defined(__x86__) /* Linux and *BSD tend to have these flags named differently. */ #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) @@ -50,15 +50,37 @@ #define fd -1 #endif - void *pa = mmap(0, getPageSize(), PROT_READ|PROT_WRITE|PROT_EXEC, + void *pa = mmap(0, NumPages*PageSize, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, fd, 0); assert(pa != MAP_FAILED && "MMAP FAILED!"); return pa; } +/// AllocatePage - This function returns a chunk of memory with size and +/// alignment specified by PageSize. +void *AllocatePage() { + if (FreePages && !FreePages->empty()) { + void *Result = FreePages->back(); + FreePages->pop_back(); + return Result; + } + + // Allocate several pages, and put the extras on the freelist... + unsigned NumToAllocate = 10; + char *Ptr = (char*)GetPages(NumToAllocate); + + if (!FreePages) FreePages = new std::vector >(); + for (unsigned i = 1; i != NumToAllocate; ++i) + FreePages->push_back(Ptr+i*PageSize); + return Ptr; +} + + /// FreePage - This function returns the specified page to the pagemanager for /// future allocation. void FreePage(void *Page) { - munmap(Page, 1); + assert(FreePages && "No pages allocated!"); + FreePages->push_back(Page); + //munmap(Page, 1); } From brukman at cs.uiuc.edu Fri Nov 7 11:27:02 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Nov 7 11:27:02 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/Makefile Message-ID: <200311071726.LAA20089@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: Makefile updated: 1.35 -> 1.36 --- Log message: Use `basename $<` to get just the filename, not full path, for ease of reading. --- Diffs of the changes: (+2 -2) Index: llvm/lib/Target/Sparc/Makefile diff -u llvm/lib/Target/Sparc/Makefile:1.35 llvm/lib/Target/Sparc/Makefile:1.36 --- llvm/lib/Target/Sparc/Makefile:1.35 Thu Nov 6 18:38:09 2003 +++ llvm/lib/Target/Sparc/Makefile Fri Nov 7 11:26:27 2003 @@ -26,7 +26,7 @@ $(CXX) -E -I$(LLVM_SRC_ROOT)/include $(DEBUG_FLAG) -x c++ $< | $(SED) '/^#/d' | $(SED) 's/^Xinclude/#include/' | $(SED) 's/^Xdefine/#define/' > $@ Sparc.burm.cpp: Sparc.burm - @echo "Burging $<" + @echo "Burging `basename $<`" $(RunBurg) $< -o $@ $(BUILD_OBJ_DIR)/Debug/Sparc.burm.lo: Sparc.burm.cpp @@ -48,7 +48,7 @@ $(TARGET_NAME)CodeEmitter.cpp:: $(TARGET_NAME)CodeEmitter.inc $(TARGET_NAME)CodeEmitter.inc:: $(SourceDir)/$(TARGET_NAME).td $(TABLEGEN_FILES) $(TBLGEN) - @echo "Tblgen'ing $<" + @echo "Tblgen'ing `basename $<`" $(TBLGEN) -I $(SourceDir) $< -gen-emitter -o $@ clean:: From brukman at cs.uiuc.edu Fri Nov 7 11:30:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Nov 7 11:30:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcInstrInfo.cpp Message-ID: <200311071729.LAA22802@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcInstrInfo.cpp updated: 1.56 -> 1.57 --- Log message: * Use the MachineConstantPool for storing constants instead of a hash_set; * Do not create new globals for constants! Also, order #includes as per coding style guide --- Diffs of the changes: (+41 -17) Index: llvm/lib/Target/Sparc/SparcInstrInfo.cpp diff -u llvm/lib/Target/Sparc/SparcInstrInfo.cpp:1.56 llvm/lib/Target/Sparc/SparcInstrInfo.cpp:1.57 --- llvm/lib/Target/Sparc/SparcInstrInfo.cpp:1.56 Tue Oct 21 12:22:23 2003 +++ llvm/lib/Target/Sparc/SparcInstrInfo.cpp Fri Nov 7 11:29:48 2003 @@ -11,21 +11,21 @@ #include "SparcInternals.h" #include "SparcInstrSelectionSupport.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/iTerminators.h" #include "llvm/CodeGen/InstrSelection.h" #include "llvm/CodeGen/InstrSelectionSupport.h" +#include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionInfo.h" #include "llvm/CodeGen/MachineCodeForInstruction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/Function.h" -#include "llvm/Constants.h" -#include "llvm/iTerminators.h" -#include "llvm/DerivedTypes.h" static const uint32_t MAXLO = (1 << 10) - 1; // set bits set by %lo(*) static const uint32_t MAXSIMM = (1 << 12) - 1; // set bits in simm13 field of OR - //--------------------------------------------------------------------------- // Function ConvertConstantToIntType // @@ -496,24 +496,48 @@ // First, create a tmp register to be used by the SETX sequence. TmpInstruction* tmpReg = - new TmpInstruction(mcfi, PointerType::get(val->getType()), val); + new TmpInstruction(mcfi, PointerType::get(val->getType())); // Create another TmpInstruction for the address register TmpInstruction* addrReg = - new TmpInstruction(mcfi, PointerType::get(val->getType()), val); + new TmpInstruction(mcfi, PointerType::get(val->getType())); - // Put the address (a symbolic name) into a register - CreateSETXLabel(target, val, tmpReg, addrReg, mvec); - - // Generate the load instruction - int64_t zeroOffset = 0; // to avoid ambiguity with (Value*) 0 + // Get the constant pool index for this constant + MachineConstantPool *CP = MachineFunction::get(F).getConstantPool(); + Constant *C = cast(val); + unsigned CPI = CP->getConstantPoolIndex(C); + + // Put the address of the constant into a register + MachineInstr* MI; + + MI = BuildMI(V9::SETHI, 2).addConstantPoolIndex(CPI).addRegDef(tmpReg); + MI->setOperandHi64(0); + mvec.push_back(MI); + + MI = BuildMI(V9::ORi, 3).addReg(tmpReg).addConstantPoolIndex(CPI) + .addRegDef(tmpReg); + MI->setOperandLo64(1); + mvec.push_back(MI); + + mvec.push_back(BuildMI(V9::SLLXi6, 3).addReg(tmpReg).addZImm(32) + .addRegDef(tmpReg)); + MI = BuildMI(V9::SETHI, 2).addConstantPoolIndex(CPI).addRegDef(addrReg); + MI->setOperandHi32(0); + mvec.push_back(MI); + + MI = BuildMI(V9::ORr, 3).addReg(addrReg).addReg(tmpReg).addRegDef(addrReg); + mvec.push_back(MI); + + MI = BuildMI(V9::ORi, 3).addReg(addrReg).addConstantPoolIndex(CPI) + .addRegDef(addrReg); + MI->setOperandLo32(1); + mvec.push_back(MI); + + // Now load the constant from out ConstantPool label unsigned Opcode = ChooseLoadInstruction(val->getType()); Opcode = convertOpcodeFromRegToImm(Opcode); - mvec.push_back(BuildMI(Opcode, 3).addReg(addrReg). - addSImm(zeroOffset).addRegDef(dest)); - - // Make sure constant is emitted to constant pool in assembly code. - MachineFunction::get(F).getInfo()->addToConstantPool(cast(val)); + mvec.push_back(BuildMI(Opcode, 3) + .addReg(addrReg).addSImm((int64_t)0).addRegDef(dest)); } } From lattner at cs.uiuc.edu Fri Nov 7 11:30:07 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Nov 7 11:30:07 2003 Subject: [llvm-commits] CVS: poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp Message-ID: <200311071729.LAA22553@zion.cs.uiuc.edu> Changes in directory poolalloc/runtime/PoolAllocator: PoolAllocatorChained.cpp updated: 1.22 -> 1.23 --- Log message: * Implement a much more efficient pool free in a variety of ways: 1. We now allocate slabs of memory with the page manager instead of with malloc. 2. We no longer have to scan the list of slabs to find the slab a node is in. Instead we can just mask off the low-order bits of the node address to get the slab pointer. 3. The NodeFlags is now variable length, and allocated in units of 32 bits instead of units of 8 bits. 4. PoolSlabs are now maintained in a doubly linked list. 5. We use builtin_expect in a few places. * Note that this checkin breaks "large single array" allocations. --- Diffs of the changes: (+192 -91) Index: poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp diff -u poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp:1.22 poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp:1.23 --- poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp:1.22 Tue Nov 4 11:25:01 2003 +++ poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp Fri Nov 7 11:29:46 2003 @@ -18,11 +18,13 @@ //===----------------------------------------------------------------------===// #include "PoolAllocator.h" +#include "PageManager.h" #include #include +#include -//#undef assert -//#define assert(X) +#undef assert +#define assert(X) //===----------------------------------------------------------------------===// // @@ -35,15 +37,8 @@ // Invariants: FirstUnused <= UsedEnd // struct PoolSlab { - // In the current implementation, each slab in the pool has NodesPerSlab - // nodes unless the isSingleArray flag is set in which case it contains a - // single array of size ArraySize. Small arrays (size <= NodesPerSlab) are - // still allocated in the slabs of size NodesPerSlab - // - static const unsigned NodesPerSlab = 4096; - - PoolSlab *Next; - unsigned isSingleArray; // If this slab is used for exactly one array + PoolSlab **PrevPtr, *Next; + bool isSingleArray; // If this slab is used for exactly one array private: // FirstUnused - First empty node in slab @@ -52,36 +47,42 @@ // UsedEnd - 1 past the last allocated node in slab. 0 if slab is empty unsigned short UsedEnd; + // NumNodesInSlab - This contains the number of nodes in this slab, which + // effects the size of the NodeFlags vector, and indicates the number of nodes + // which are in the slab. + unsigned short NumNodesInSlab; + // NodeFlagsVector - This array contains two bits for each node in this pool // slab. The first (low address) bit indicates whether this node has been // allocated, and the second (next higher) bit indicates whether this is the // start of an allocation. - unsigned char NodeFlagsVector[NodesPerSlab/4]; - - char Data[1]; // Buffer to hold data in this slab... VARIABLE SIZED - + // + // This is a variable sized array, which has 2*NumNodesInSlab bits (rounded up + // to 4 bytes). + unsigned NodeFlagsVector[]; + bool isNodeAllocated(unsigned NodeNum) { - return NodeFlagsVector[NodeNum >> 2] & (1 << (NodeNum & 3)); + return NodeFlagsVector[NodeNum/16] & (1 << (NodeNum & 15)); } void markNodeAllocated(unsigned NodeNum) { - NodeFlagsVector[NodeNum >> 2] |= 1 << (NodeNum & 3); + NodeFlagsVector[NodeNum/16] |= 1 << (NodeNum & 15); } void markNodeFree(unsigned NodeNum) { - NodeFlagsVector[NodeNum >> 2] &= ~(1 << (NodeNum & 3)); + NodeFlagsVector[NodeNum/16] &= ~(1 << (NodeNum & 15)); } void setStartBit(unsigned NodeNum) { - NodeFlagsVector[NodeNum >> 2] |= 1 << ((NodeNum & 3)+4); + NodeFlagsVector[NodeNum/16] |= 1 << ((NodeNum & 15)+16); } bool isStartOfAllocation(unsigned NodeNum) { - return NodeFlagsVector[NodeNum >> 2] & (1 << ((NodeNum & 3)+4)); + return NodeFlagsVector[NodeNum/16] & (1 << ((NodeNum & 15)+16)); } void clearStartBit(unsigned NodeNum) { - NodeFlagsVector[NodeNum >> 2] &= ~(1 << ((NodeNum & 3)+4)); + NodeFlagsVector[NodeNum/16] &= ~(1 << ((NodeNum & 15)+16)); } public: @@ -94,17 +95,28 @@ // getSlabSize - Return the number of nodes that each slab should contain. static unsigned getSlabSize(PoolTy *Pool) { - return NodesPerSlab; + return 325; + } + + void addToList(PoolSlab **PrevPtrPtr) { + PoolSlab *InsertBefore = *PrevPtrPtr; + *PrevPtrPtr = this; + PrevPtr = PrevPtrPtr; + Next = InsertBefore; + if (InsertBefore) InsertBefore->PrevPtr = &Next; + } + + void unlinkFromList() { + *PrevPtr = Next; + if (Next) Next->PrevPtr = PrevPtr; } unsigned getSlabSize() const { - return NodesPerSlab; + return NumNodesInSlab; } // destroy - Release the memory for the current object. - void destroy() { - free(this); - } + void destroy(); // isEmpty - This is a quick check to see if this slab is completely empty or // not. @@ -124,6 +136,12 @@ // getElementAddress - Return the address of the specified element. void *getElementAddress(unsigned ElementNum, unsigned ElementSize) { + char *Data = (char*)&NodeFlagsVector[((unsigned)NumNodesInSlab+15)/16]; + return &Data[ElementNum*ElementSize]; + } + const void *getElementAddress(unsigned ElementNum, unsigned ElementSize)const{ + const char *Data = + (const char *)&NodeFlagsVector[(unsigned)(NumNodesInSlab+15)/16]; return &Data[ElementNum*ElementSize]; } @@ -133,39 +151,55 @@ // freeElement - Free the single node, small array, or entire array indicated. void freeElement(unsigned ElementIdx); + + // lastNodeAllocated - Return one past the last node in the pool which is + // before ScanIdx, that is allocated. If there are no allocated nodes in this + // slab before ScanIdx, return 0. + unsigned lastNodeAllocated(unsigned ScanIdx); }; // create - Create a new (empty) slab and add it to the end of the Pools list. PoolSlab *PoolSlab::create(PoolTy *Pool) { - PoolSlab *PS = (PoolSlab*)malloc(sizeof(PoolSlab) + - Pool->NodeSize*getSlabSize(Pool)-1); - assert(PS && "poolalloc: Could not allocate memory!"); + unsigned NodesPerSlab = getSlabSize(Pool); + unsigned Size = sizeof(PoolSlab) + 4*((NodesPerSlab+15)/16) + + Pool->NodeSize*getSlabSize(Pool); + assert(Size < PageSize && "Trying to allocate a slab larger than a page!"); + PoolSlab *PS = (PoolSlab*)AllocatePage(); + + PS->NumNodesInSlab = NodesPerSlab; PS->isSingleArray = 0; // Not a single array! PS->FirstUnused = 0; // Nothing allocated. PS->UsedEnd = 0; // Nothing allocated. // Add the slab to the list... - PS->Next = (PoolSlab*)Pool->Ptr1; - Pool->Ptr1 = PS; + PS->addToList((PoolSlab**)&Pool->Ptr1); return PS; } void *PoolSlab::createSingleArray(PoolTy *Pool, unsigned NumNodes) { - PoolSlab *PS = (PoolSlab*)malloc(sizeof(PoolSlab) + - Pool->NodeSize*NumNodes-1); - assert(NumNodes > getSlabSize(Pool) && "No need to create a single array!"); + if (0) { + printf("PoolSlab::createSingleArray has not been tested and is probably broken!"); + abort(); + } + unsigned NodesPerSlab = getSlabSize(Pool); + assert(NumNodes > NodesPerSlab && "No need to create a single array!"); + PoolSlab *PS = (PoolSlab*)malloc(sizeof(PoolSlab) + 4*((NodesPerSlab+15)/16) + + Pool->NodeSize*NumNodes); assert(PS && "poolalloc: Could not allocate memory!"); + PS->NumNodesInSlab = NodesPerSlab; // FIXME: Calculate right. PS->isSingleArray = 1; // Not a single array! PS->markNodeAllocated(0); - // Add the slab to the list of completely allocated slabs... - PS->Next = (PoolSlab*)Pool->Ptr2; - Pool->Ptr2 = PS; - return &PS->Data[0]; + // Add the slab to the list... + PS->addToList((PoolSlab**)&Pool->Ptr1); + return PS->getElementAddress(0, 0); } +void PoolSlab::destroy() { + FreePage(this); +} // allocateSingle - Allocate a single element from this pool, returning -1 if // there is no space. @@ -174,8 +208,10 @@ // single nodes in a SingleArray slab. if (isSingleArray) return -1; + unsigned SlabSize = getSlabSize(); + // Check to see if there are empty entries at the end of the slab... - if (UsedEnd < getSlabSize()) { + if (UsedEnd < SlabSize) { // Mark the returned entry used unsigned short UE = UsedEnd; markNodeAllocated(UE); @@ -192,7 +228,7 @@ // If not, check to see if this node has a declared "FirstUnused" value that // is less than the number of nodes allocated... // - if (FirstUnused < getSlabSize()) { + if (FirstUnused < SlabSize) { // Successfully allocate out the first unused node unsigned Idx = FirstUnused; markNodeAllocated(Idx); @@ -203,7 +239,7 @@ unsigned short FU = FirstUnused; do { ++FU; - } while (FU != getSlabSize() && isNodeAllocated(FU)); + } while (FU != SlabSize && isNodeAllocated(FU)); FirstUnused = FU; return Idx; @@ -282,10 +318,12 @@ // containsElement - Return the element number of the specified address in // this slab. If the address is not in slab, return -1. int PoolSlab::containsElement(void *Ptr, unsigned ElementSize) const { - if (&Data[0] > Ptr || &Data[ElementSize*getSlabSize()-1] < Ptr) + const void *FirstElement = getElementAddress(0, 0); + if (FirstElement > Ptr || + (char*)getElementAddress(ElementSize, getSlabSize())-1 < Ptr) return -1; - unsigned Index = (char*)Ptr-(char*)&Data[0]; + unsigned Index = (char*)Ptr-(char*)FirstElement; assert(Index % ElementSize == 0 && "Freeing pointer into the middle of an element!"); Index /= ElementSize; @@ -321,8 +359,7 @@ // Free all nodes if this was a small array allocation. unsigned ElementEndIdx = ElementIdx + 1; - // FIXME: This should use manual strength reduction if GCC isn't producing - // decent code (which is almost certainly isn't). + // FIXME: This should use manual strength reduction to produce decent code. unsigned UE = UsedEnd; while (ElementEndIdx != UE && !isStartOfAllocation(ElementEndIdx) && @@ -337,19 +374,47 @@ // If we are freeing the last element in a slab, shrink the UsedEnd marker // down to the last used node. if (ElementEndIdx == UE) { - UE = ElementIdx; - do { - --UE; - // FIXME, this should scan the allocated array an entire byte at a time - // for performance when skipping large empty blocks! - } while (UE && !isNodeAllocated(UE-1)); - UsedEnd = UE; - + UsedEnd = lastNodeAllocated(ElementIdx); assert(FirstUnused <= UsedEnd && "FirstUnused field was out of date!"); } } +unsigned PoolSlab::lastNodeAllocated(unsigned ScanIdx) { + // Check the last few nodes in the current word of flags... + unsigned CurWord = ScanIdx/16; + unsigned short Flags = NodeFlagsVector[CurWord] & 0xFFFF; + if (Flags) { + // Mask off nodes above this one + Flags &= (1 << (ScanIdx & 15))-1; + if (Flags) { + // If there is still something in the flags vector, then there is a node + // allocated in this part. The goto is a hack to get the uncommonly + // executed code away from the common code path. + goto ContainsAllocatedNode; + } + } + + // Ok, the top word doesn't contain anything, scan the whole flag words now. + ScanIdx &= ~15; + --CurWord; + while (CurWord != ~0U) { + if (NodeFlagsVector[CurWord] & 0xFFFF) + goto ContainsAllocatedNode; + CurWord--; + ScanIdx -= 16; + } + return 0; + +ContainsAllocatedNode: + // Figure out exactly which node is allocated in this word now. + // FIXME: this could be made to be more efficient! + do { + --ScanIdx; + } while (ScanIdx && !isNodeAllocated(ScanIdx-1)); + return ScanIdx; +} + //===----------------------------------------------------------------------===// // @@ -362,6 +427,9 @@ void poolinit(PoolTy *Pool, unsigned NodeSize) { assert(Pool && "Null pool pointer passed into poolinit!\n"); + // Ensure the page manager is initialized + InitializePageManager(); + // We must alway return unique pointers, even if they asked for 0 bytes Pool->NodeSize = NodeSize ? NodeSize : 1; Pool->Ptr1 = Pool->Ptr2 = 0; @@ -398,23 +466,34 @@ void *poolalloc(PoolTy *Pool) { assert(Pool && "Null pool pointer passed in to poolalloc!\n"); - unsigned NodeSize = Pool->NodeSize; PoolSlab *PS = (PoolSlab*)Pool->Ptr1; - PoolSlab **PPS = (PoolSlab**)&Pool->Ptr1; - // Loop through all of the slabs looking for one with an opening - for (; PS; PPS = &PS->Next, PS = PS->Next) { + if (__builtin_expect(PS != 0, 1)) { int Element = PS->allocateSingle(); - if (Element != -1) { - // We allocated an element. Check to see if this slab has been completely - // filled up. If so, move it to the Ptr2 list. - if (PS->isFull()) { - *PPS = PS->Next; // Unlink it from the current list - PS->Next = (PoolSlab*)Pool->Ptr2; // Link it into the filled list - Pool->Ptr2 = PS; + if (__builtin_expect(Element != -1, 1)) { + // We allocated an element. Check to see if this slab has been + // completely filled up. If so, move it to the Ptr2 list. + if (__builtin_expect(PS->isFull(), false)) { + PS->unlinkFromList(); + PS->addToList((PoolSlab**)&Pool->Ptr2); } + + return PS->getElementAddress(Element, Pool->NodeSize); + } - return PS->getElementAddress(Element, NodeSize); + // Loop through all of the slabs looking for one with an opening + for (PS = PS->Next; PS; PS = PS->Next) { + int Element = PS->allocateSingle(); + if (Element != -1) { + // We allocated an element. Check to see if this slab has been + // completely filled up. If so, move it to the Ptr2 list. + if (PS->isFull()) { + PS->unlinkFromList(); + PS->addToList((PoolSlab**)&Pool->Ptr2); + } + + return PS->getElementAddress(Element, Pool->NodeSize); + } } } @@ -428,22 +507,23 @@ void *poolallocarray(PoolTy* Pool, unsigned Size) { assert(Pool && "Null pool pointer passed into poolallocarray!\n"); + // Special case size=1, because poolalloc is much faster than this function. + if (Size == 1 || Size == 0) + return poolalloc(Pool); if (Size > PoolSlab::getSlabSize(Pool)) return PoolSlab::createSingleArray(Pool, Size); PoolSlab *PS = (PoolSlab*)Pool->Ptr1; - PoolSlab **PPS = (PoolSlab**)&Pool->Ptr1; // Loop through all of the slabs looking for one with an opening - for (; PS; PPS = &PS->Next, PS = PS->Next) { + for (; PS; PS = PS->Next) { int Element = PS->allocateMultiple(Size); if (Element != -1) { // We allocated an element. Check to see if this slab has been completely // filled up. If so, move it to the Ptr2 list. if (PS->isFull()) { - *PPS = PS->Next; // Unlink it from the current list - PS->Next = (PoolSlab*)Pool->Ptr2; // Link it into the filled list - Pool->Ptr2 = PS; + PS->unlinkFromList(); + PS->addToList((PoolSlab**)&Pool->Ptr2); } return PS->getElementAddress(Element, Pool->NodeSize); } @@ -455,19 +535,19 @@ return New->getElementAddress(0, 0); } -void poolfree(PoolTy *Pool, void *Node) { - assert(Pool && "Null pool pointer passed in to poolfree!\n"); - unsigned NodeSize = Pool->NodeSize; - +// SearchForContainingSlab - Do a brute force search through the list of +// allocated slabs for the node in question. +// +static PoolSlab *SearchForContainingSlab(PoolTy *Pool, void *Node, + unsigned &TheIndex) { PoolSlab *PS = (PoolSlab*)Pool->Ptr1; - PoolSlab **PPS; + unsigned NodeSize = Pool->NodeSize; // Search the partially allocated slab list for the slab that contains this // node. int Idx = -1; if (PS) { // Pool->Ptr1 could be null if Ptr2 isn't - PPS = (PoolSlab**)&Pool->Ptr1; - for (; PS; PPS = &PS->Next, PS = PS->Next) { + for (; PS; PS = PS->Next) { Idx = PS->containsElement(Node, NodeSize); if (Idx != -1) break; } @@ -477,7 +557,6 @@ // completely allocated list does. if (PS == 0) { PS = (PoolSlab*)Pool->Ptr2; - PPS = (PoolSlab**)&Pool->Ptr2; assert(Idx == -1 && "Found node but don't have PS?"); while (1) { @@ -485,14 +564,40 @@ " pool specified!\n"); Idx = PS->containsElement(Node, NodeSize); if (Idx != -1) break; - PPS = &PS->Next; PS = PS->Next; } + } + TheIndex = Idx; + return PS; +} +void poolfree(PoolTy *Pool, void *Node) { + assert(Pool && "Null pool pointer passed in to poolfree!\n"); + + PoolSlab *PS; + unsigned Idx; + if (0) { // THIS SHOULD BE SET FOR SAFECODE! + unsigned TheIndex; + PS = SearchForContainingSlab(Pool, Node, TheIndex); + Idx = TheIndex; + } else { + // Since it is undefined behavior to free a node which has not been + // allocated, we know that the pointer coming in has to be a valid node + // pointer in the pool. Mask off some bits of the address to find the base + // of the pool. + assert((PageSize & PageSize-1) == 0 && "Page size is not a power of 2??"); + PS = (PoolSlab*)((long)Node & ~(PageSize-1)); + Idx = PS->containsElement(Node, Pool->NodeSize); + assert((int)Idx != -1 && "Node not contained in slab??"); + } + + // If PS was full, it must have been in list #2. Unlink it and move it to + // list #1. + if (PS->isFull()) { // Now that we found the node, we are about to free an element from it. // This will make the slab no longer completely full, so we must move it to // the other list! - *PPS = PS->Next; // Remove it from the Ptr2 list. + PS->unlinkFromList(); // Remove it from the Ptr2 list. PoolSlab **InsertPosPtr = (PoolSlab**)&Pool->Ptr1; @@ -500,10 +605,8 @@ // list, insert right after it. if ((*InsertPosPtr)->isEmpty()) InsertPosPtr = &(*InsertPosPtr)->Next; - - // Insert it now in the Ptr1 list. - PS->Next = *InsertPosPtr; - *InsertPosPtr = PS; + + PS->addToList(InsertPosPtr); // Insert it now in the Ptr1 list. } // Free the actual element now! @@ -517,7 +620,7 @@ if (PS->isSingleArray) if (Pool->FreeablePool) { // If it is a SingleArray, just free it - *PPS = PS->Next; + PS->unlinkFromList(); PS->destroy(); return; } else { @@ -529,23 +632,21 @@ // No more singlearray objects exist at this point. assert(!PS->isSingleArray); - *PPS = PS->Next; // Unlink from the list of slabs... - PoolSlab *FirstSlab = (PoolSlab*)Pool->Ptr1; + PS->unlinkFromList(); // Unlink from the list of slabs... // If we can free this pool, check to see if there are any empty slabs at // the start of this list. If so, delete the FirstSlab! + PoolSlab *FirstSlab = (PoolSlab*)Pool->Ptr1; if (Pool->FreeablePool && FirstSlab->isEmpty()) { // Here we choose to delete FirstSlab instead of the pool we just freed // from because the pool we just freed from is more likely to be in the // processor cache. - PoolSlab *NextSlab = FirstSlab->Next; + FirstSlab->unlinkFromList(); FirstSlab->destroy(); - FirstSlab = NextSlab; } // Link our slab onto the head of the list so that allocations will find it // efficiently. - PS->Next = FirstSlab; - Pool->Ptr1 = PS; + PS->addToList((PoolSlab**)&Pool->Ptr1); } } From brukman at cs.uiuc.edu Fri Nov 7 11:32:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Nov 7 11:32:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/PreSelection.cpp Message-ID: <200311071731.LAA23199@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: PreSelection.cpp updated: 1.24 -> 1.25 --- Log message: * Stop making a global for each constant that cannot live in an instruction; it will be converted to a MachineConstantPool index during instruction selection * This is now eligible to become a FunctionPass since it does not have any side effects outside of the function it is processing. --- Diffs of the changes: (+14 -36) Index: llvm/lib/Target/Sparc/PreSelection.cpp diff -u llvm/lib/Target/Sparc/PreSelection.cpp:1.24 llvm/lib/Target/Sparc/PreSelection.cpp:1.25 --- llvm/lib/Target/Sparc/PreSelection.cpp:1.24 Tue Oct 21 23:51:36 2003 +++ llvm/lib/Target/Sparc/PreSelection.cpp Fri Nov 7 11:31:22 2003 @@ -34,38 +34,16 @@ //===--------------------------------------------------------------------===// // PreSelection Pass - Specialize LLVM code for the current target machine. // - class PreSelection : public Pass, public InstVisitor { + class PreSelection : public FunctionPass, public InstVisitor { const TargetInstrInfo &instrInfo; - Module *TheModule; - - std::map gvars; - - GlobalVariable* getGlobalForConstant(Constant* CV) { - std::map::iterator I = gvars.find(CV); - if (I != gvars.end()) return I->second; // global exists so return it - - return I->second = new GlobalVariable(CV->getType(), true, - GlobalValue::InternalLinkage, CV, - "immcst", TheModule); - } public: PreSelection(const TargetMachine &T) - : instrInfo(T.getInstrInfo()), TheModule(0) {} - - // run - apply this pass to the entire Module - bool run(Module &M) { - TheModule = &M; - - // Build reverse map for pre-existing global constants so we can find them - for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; ++I) - if (I->hasInitializer() && I->isConstant()) - gvars[I->getInitializer()] = I; - - for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) - visit(*I); + : instrInfo(T.getInstrInfo()) {} - gvars.clear(); + // runOnFunction - apply this pass to each Function + bool runOnFunction(Function &F) { + visit(F); return true; } @@ -87,10 +65,12 @@ Instruction& insertBefore); }; +#if 0 // Register the pass... - RegisterOpt X("preselect", - "Specialize LLVM code for a target machine", - createPreSelectionPass); + RegisterPass X("preselect", + "Specialize LLVM code for a target machine" + createPreselectionPass); +#endif } // end anonymous namespace @@ -184,10 +164,8 @@ I.setOperand(opNum, computeConst); // replace expr operand with result } else if (instrInfo.ConstantTypeMustBeLoaded(CV)) { // load address of constant into a register, then load the constant - GetElementPtrInst* gep = getGlobalAddr(getGlobalForConstant(CV), - insertBefore); - LoadInst* ldI = new LoadInst(gep, "loadConst", &insertBefore); - I.setOperand(opNum, ldI); // replace operand with copy in v.reg. + // this is now done during instruction selection + // the constant will live in the MachineConstantPool later on } else if (instrInfo.ConstantMayNotFitInImmedField(CV, &I)) { // put the constant into a virtual register using a cast CastInst* castI = new CastInst(CV, CV->getType(), "copyConst", @@ -263,6 +241,6 @@ // createPreSelectionPass - Public entrypoint for pre-selection pass // and this file as a whole... // -Pass* createPreSelectionPass(TargetMachine &T) { - return new PreSelection(T); +FunctionPass* createPreSelectionPass(const TargetMachine &TM) { + return new PreSelection(TM); } From brukman at cs.uiuc.edu Fri Nov 7 11:44:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Nov 7 11:44:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcInternals.h Message-ID: <200311071743.LAA01988@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcInternals.h updated: 1.105 -> 1.106 --- Log message: PreSelection and PeepholeOpts are now FunctionPasses. --- Diffs of the changes: (+2 -2) Index: llvm/lib/Target/Sparc/SparcInternals.h diff -u llvm/lib/Target/Sparc/SparcInternals.h:1.105 llvm/lib/Target/Sparc/SparcInternals.h:1.106 --- llvm/lib/Target/Sparc/SparcInternals.h:1.105 Tue Oct 21 10:17:13 2003 +++ llvm/lib/Target/Sparc/SparcInternals.h Fri Nov 7 11:43:43 2003 @@ -643,10 +643,10 @@ // Interface to pre-selection pass that specializes LLVM code for a target // machine. -Pass *createPreSelectionPass(TargetMachine &Target); +FunctionPass *createPreSelectionPass(const TargetMachine &TM); // External interface to peephole optimization pass operating on machine code. -FunctionPass *createPeepholeOptsPass(TargetMachine &Target); +FunctionPass *createPeepholeOptsPass(const TargetMachine &TM); //--------------------------------------------------------------------------- From brukman at cs.uiuc.edu Fri Nov 7 11:45:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Nov 7 11:45:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/PeepholeOpts.cpp Message-ID: <200311071744.LAA02006@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: PeepholeOpts.cpp updated: 1.14 -> 1.15 --- Log message: We accept TargetMachine as a const reference. --- Diffs of the changes: (+3 -3) Index: llvm/lib/Target/Sparc/PeepholeOpts.cpp diff -u llvm/lib/Target/Sparc/PeepholeOpts.cpp:1.14 llvm/lib/Target/Sparc/PeepholeOpts.cpp:1.15 --- llvm/lib/Target/Sparc/PeepholeOpts.cpp:1.14 Tue Oct 21 07:29:45 2003 +++ llvm/lib/Target/Sparc/PeepholeOpts.cpp Fri Nov 7 11:44:18 2003 @@ -112,7 +112,7 @@ bool visit(MachineBasicBlock& mvec, MachineBasicBlock::iterator BBI) const; public: - PeepholeOpts(const TargetMachine &T): target(T) { } + PeepholeOpts(const TargetMachine &TM): target(TM) { } bool runOnBasicBlock(BasicBlock &BB); // apply this pass to each BB virtual const char *getPassName() const { return "Peephole Optimization"; } }; @@ -160,6 +160,6 @@ // createPeepholeOptsPass - Public entrypoint for peephole optimization // and this file as a whole... // -FunctionPass* createPeepholeOptsPass(TargetMachine &T) { - return new PeepholeOpts(T); +FunctionPass* createPeepholeOptsPass(const TargetMachine &TM) { + return new PeepholeOpts(TM); } From brukman at cs.uiuc.edu Fri Nov 7 11:46:02 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Nov 7 11:46:02 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/EmitAssembly.cpp Message-ID: <200311071745.LAA02026@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: EmitAssembly.cpp updated: 1.93 -> 1.94 --- Log message: Switch to using the standard representation of the constant pool -- namely, the MachineConstantPool. This involved refactoring the two classes involved in printing out Sparc assembly. In fact, they should share all this code anyway. --- Diffs of the changes: (+322 -338) Index: llvm/lib/Target/Sparc/EmitAssembly.cpp diff -u llvm/lib/Target/Sparc/EmitAssembly.cpp:1.93 llvm/lib/Target/Sparc/EmitAssembly.cpp:1.94 --- llvm/lib/Target/Sparc/EmitAssembly.cpp:1.93 Mon Oct 20 14:43:17 2003 +++ llvm/lib/Target/Sparc/EmitAssembly.cpp Fri Nov 7 11:45:28 2003 @@ -19,6 +19,7 @@ //===----------------------------------------------------------------------===// #include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionInfo.h" #include "llvm/Constants.h" @@ -52,6 +53,150 @@ AnnotationID GlobalIdTable::AnnotId = AnnotationManager::getID("ASM PRINTER GLOBAL TABLE ANNOT"); + +// Can we treat the specified array as a string? Only if it is an array of +// ubytes or non-negative sbytes. +// +static bool isStringCompatible(const ConstantArray *CVA) { + const Type *ETy = cast(CVA->getType())->getElementType(); + if (ETy == Type::UByteTy) return true; + if (ETy != Type::SByteTy) return false; + + for (unsigned i = 0; i < CVA->getNumOperands(); ++i) + if (cast(CVA->getOperand(i))->getValue() < 0) + return false; + + return true; +} + +// toOctal - Convert the low order bits of X into an octal letter +static inline char toOctal(int X) { + return (X&7)+'0'; +} + +// getAsCString - Return the specified array as a C compatible string, only if +// the predicate isStringCompatible is true. +// +static std::string getAsCString(const ConstantArray *CVA) { + assert(isStringCompatible(CVA) && "Array is not string compatible!"); + + std::string Result; + const Type *ETy = cast(CVA->getType())->getElementType(); + Result = "\""; + for (unsigned i = 0; i < CVA->getNumOperands(); ++i) { + unsigned char C = cast(CVA->getOperand(i))->getRawValue(); + + if (C == '"') { + Result += "\\\""; + } else if (C == '\\') { + Result += "\\\\"; + } else if (isprint(C)) { + Result += C; + } else { + Result += '\\'; // print all other chars as octal value + Result += toOctal(C >> 6); + Result += toOctal(C >> 3); + Result += toOctal(C >> 0); + } + } + Result += "\""; + + return Result; +} + +inline bool +ArrayTypeIsString(const ArrayType* arrayType) +{ + return (arrayType->getElementType() == Type::UByteTy || + arrayType->getElementType() == Type::SByteTy); +} + + +inline const std::string +TypeToDataDirective(const Type* type) +{ + switch(type->getPrimitiveID()) + { + case Type::BoolTyID: case Type::UByteTyID: case Type::SByteTyID: + return ".byte"; + case Type::UShortTyID: case Type::ShortTyID: + return ".half"; + case Type::UIntTyID: case Type::IntTyID: + return ".word"; + case Type::ULongTyID: case Type::LongTyID: case Type::PointerTyID: + return ".xword"; + case Type::FloatTyID: + return ".word"; + case Type::DoubleTyID: + return ".xword"; + case Type::ArrayTyID: + if (ArrayTypeIsString((ArrayType*) type)) + return ".ascii"; + else + return ""; + default: + return ""; + } +} + +// Get the size of the type +// +inline unsigned int +TypeToSize(const Type* type, const TargetMachine& target) +{ + return target.findOptimalStorageSize(type); +} + +// Get the size of the constant for the given target. +// If this is an unsized array, return 0. +// +inline unsigned int +ConstantToSize(const Constant* CV, const TargetMachine& target) +{ + if (const ConstantArray* CVA = dyn_cast(CV)) + { + const ArrayType *aty = cast(CVA->getType()); + if (ArrayTypeIsString(aty)) + return 1 + CVA->getNumOperands(); + } + + return TypeToSize(CV->getType(), target); +} + +// Align data larger than one L1 cache line on L1 cache line boundaries. +// Align all smaller data on the next higher 2^x boundary (4, 8, ...). +// +inline unsigned int +SizeToAlignment(unsigned int size, const TargetMachine& target) +{ + unsigned short cacheLineSize = target.getCacheInfo().getCacheLineSize(1); + if (size > (unsigned) cacheLineSize / 2) + return cacheLineSize; + else + for (unsigned sz=1; /*no condition*/; sz *= 2) + if (sz >= size) + return sz; +} + +// Get the size of the type and then use SizeToAlignment. +// +inline unsigned int +TypeToAlignment(const Type* type, const TargetMachine& target) +{ + return SizeToAlignment(TypeToSize(type, target), target); +} + +// Get the size of the constant and then use SizeToAlignment. +// Handles strings as a special case; +inline unsigned int +ConstantToAlignment(const Constant* CV, const TargetMachine& target) +{ + if (const ConstantArray* CVA = dyn_cast(CV)) + if (ArrayTypeIsString(cast(CVA->getType()))) + return SizeToAlignment(1 + CVA->getNumOperands(), target); + + return TypeToAlignment(CV->getType(), target); +} //===---------------------------------------------------------------------===// // Code Shared By the two printer passes, as a mixin @@ -83,6 +228,158 @@ M.addAnnotation(idTable); } } + + void + PrintZeroBytesToPad(int numBytes) + { + for ( ; numBytes >= 8; numBytes -= 8) + printSingleConstantValue(Constant::getNullValue(Type::ULongTy)); + + if (numBytes >= 4) + { + printSingleConstantValue(Constant::getNullValue(Type::UIntTy)); + numBytes -= 4; + } + + while (numBytes--) + printSingleConstantValue(Constant::getNullValue(Type::UByteTy)); + } + + // Print a single constant value. + void printSingleConstantValue(const Constant* CV) + { + assert(CV->getType() != Type::VoidTy && + CV->getType() != Type::TypeTy && + CV->getType() != Type::LabelTy && + "Unexpected type for Constant"); + + assert((!isa(CV) && ! isa(CV)) + && "Aggregate types should be handled outside this function"); + + toAsm << "\t" << TypeToDataDirective(CV->getType()) << "\t"; + + if (const ConstantPointerRef* CPR = dyn_cast(CV)) + { // This is a constant address for a global variable or method. + // Use the name of the variable or method as the address value. + assert(isa(CPR->getValue()) && "Unexpected non-global"); + toAsm << getID(CPR->getValue()) << "\n"; + } + else if (isa(CV)) + { // Null pointer value + toAsm << "0\n"; + } + else if (const ConstantExpr* CE = dyn_cast(CV)) + { // Constant expression built from operators, constants, and symbolic addrs + toAsm << ConstantExprToString(CE, Target) << "\n"; + } + else if (CV->getType()->isPrimitiveType()) // Check primitive types last + { + if (CV->getType()->isFloatingPoint()) { + // FP Constants are printed as integer constants to avoid losing + // precision... + double Val = cast(CV)->getValue(); + if (CV->getType() == Type::FloatTy) { + float FVal = (float)Val; + char *ProxyPtr = (char*)&FVal; // Abide by C TBAA rules + toAsm << *(unsigned int*)ProxyPtr; + } else if (CV->getType() == Type::DoubleTy) { + char *ProxyPtr = (char*)&Val; // Abide by C TBAA rules + toAsm << *(uint64_t*)ProxyPtr; + } else { + assert(0 && "Unknown floating point type!"); + } + + toAsm << "\t! " << CV->getType()->getDescription() + << " value: " << Val << "\n"; + } else { + WriteAsOperand(toAsm, CV, false, false) << "\n"; + } + } + else + { + assert(0 && "Unknown elementary type for constant"); + } + } + + // Print a constant value or values (it may be an aggregate). + // Uses printSingleConstantValue() to print each individual value. + void + printConstantValueOnly(const Constant* CV, + int numPadBytesAfter = 0) + { + const ConstantArray *CVA = dyn_cast(CV); + + if (CVA && isStringCompatible(CVA)) + { // print the string alone and return + toAsm << "\t" << ".ascii" << "\t" << getAsCString(CVA) << "\n"; + } + else if (CVA) + { // Not a string. Print the values in successive locations + const std::vector &constValues = CVA->getValues(); + for (unsigned i=0; i < constValues.size(); i++) + printConstantValueOnly(cast(constValues[i].get())); + } + else if (const ConstantStruct *CVS = dyn_cast(CV)) + { // Print the fields in successive locations. Pad to align if needed! + const StructLayout *cvsLayout = + Target.getTargetData().getStructLayout(CVS->getType()); + const std::vector& constValues = CVS->getValues(); + unsigned sizeSoFar = 0; + for (unsigned i=0, N = constValues.size(); i < N; i++) + { + const Constant* field = cast(constValues[i].get()); + + // Check if padding is needed and insert one or more 0s. + unsigned fieldSize = + Target.getTargetData().getTypeSize(field->getType()); + int padSize = ((i == N-1? cvsLayout->StructSize + : cvsLayout->MemberOffsets[i+1]) + - cvsLayout->MemberOffsets[i]) - fieldSize; + sizeSoFar += (fieldSize + padSize); + + // Now print the actual field value + printConstantValueOnly(field, padSize); + } + assert(sizeSoFar == cvsLayout->StructSize && + "Layout of constant struct may be incorrect!"); + } + else + printSingleConstantValue(CV); + + if (numPadBytesAfter) + PrintZeroBytesToPad(numPadBytesAfter); + } + + // Print a constant (which may be an aggregate) prefixed by all the + // appropriate directives. Uses printConstantValueOnly() to print the + // value or values. + void printConstant(const Constant* CV, std::string valID = "") + { + if (valID.length() == 0) + valID = getID(CV); + + toAsm << "\t.align\t" << ConstantToAlignment(CV, Target) << "\n"; + + // Print .size and .type only if it is not a string. + const ConstantArray *CVA = dyn_cast(CV); + if (CVA && isStringCompatible(CVA)) + { // print it as a string and return + toAsm << valID << ":\n"; + toAsm << "\t" << ".ascii" << "\t" << getAsCString(CVA) << "\n"; + return; + } + + toAsm << "\t.type" << "\t" << valID << ",#object\n"; + + unsigned int constSize = ConstantToSize(CV, Target); + if (constSize) + toAsm << "\t.size" << "\t" << valID << "," << constSize << "\n"; + + toAsm << valID << ":\n"; + + printConstantValueOnly(CV); + } + void startFunction(Function &F) { // Make sure the slot table has information about this function... idTable->Table.incorporateFunction(&F); @@ -321,6 +618,8 @@ inline SparcFunctionAsmPrinter(std::ostream &os, const TargetMachine &t) : AsmPrinter(os, t) {} + const Function *currFunction; + const char *getPassName() const { return "Output Sparc Assembly for Functions"; } @@ -331,6 +630,7 @@ } virtual bool runOnFunction(Function &F) { + currFunction = &F; startFunction(F); emitFunction(F); endFunction(F); @@ -458,6 +758,13 @@ break; } + case MachineOperand::MO_ConstantPoolIndex: + { + toAsm << ".CPI_" << currFunction->getName() + << "_" << mop.getConstantPoolIndex(); + break; + } + case MachineOperand::MO_PCRelativeDisp: { const Value *Val = mop.getVRegValue(); @@ -537,6 +844,17 @@ { std::string methName = getID(&F); toAsm << "!****** Outputing Function: " << methName << " ******\n"; + + // Emit constant pool for this function + const MachineConstantPool *MCP = MachineFunction::get(&F).getConstantPool(); + const std::vector &CP = MCP->getConstants(); + + enterSection(AsmPrinter::ReadOnlyData); + for (unsigned i = 0, e = CP.size(); i != e; ++i) { + std::string cpiName = ".CPI_" + F.getName() + "_" + utostr(i); + printConstant(CP[i], cpiName); + } + enterSection(AsmPrinter::Text); toAsm << "\t.align\t4\n\t.global\t" << methName << "\n"; //toAsm << "\t.type\t" << methName << ",#function\n"; @@ -582,7 +900,7 @@ virtual bool run(Module &M) { startModule(M); - emitGlobalsAndConstants(M); + emitGlobals(M); endModule(); return false; } @@ -592,328 +910,10 @@ } private: - void emitGlobalsAndConstants (const Module &M); - - void printGlobalVariable (const GlobalVariable *GV); - void PrintZeroBytesToPad (int numBytes); - void printSingleConstantValue (const Constant* CV); - void printConstantValueOnly (const Constant* CV, int numPadBytesAfter = 0); - void printConstant (const Constant* CV, std::string valID = ""); - - static void FoldConstants (const Module &M, - hash_set &moduleConstants); + void emitGlobals(const Module &M); + void printGlobalVariable(const GlobalVariable *GV); }; - -// Can we treat the specified array as a string? Only if it is an array of -// ubytes or non-negative sbytes. -// -static bool isStringCompatible(const ConstantArray *CVA) { - const Type *ETy = cast(CVA->getType())->getElementType(); - if (ETy == Type::UByteTy) return true; - if (ETy != Type::SByteTy) return false; - - for (unsigned i = 0; i < CVA->getNumOperands(); ++i) - if (cast(CVA->getOperand(i))->getValue() < 0) - return false; - - return true; -} - -// toOctal - Convert the low order bits of X into an octal letter -static inline char toOctal(int X) { - return (X&7)+'0'; -} - -// getAsCString - Return the specified array as a C compatible string, only if -// the predicate isStringCompatible is true. -// -static std::string getAsCString(const ConstantArray *CVA) { - assert(isStringCompatible(CVA) && "Array is not string compatible!"); - - std::string Result; - const Type *ETy = cast(CVA->getType())->getElementType(); - Result = "\""; - for (unsigned i = 0; i < CVA->getNumOperands(); ++i) { - unsigned char C = cast(CVA->getOperand(i))->getRawValue(); - - if (C == '"') { - Result += "\\\""; - } else if (C == '\\') { - Result += "\\\\"; - } else if (isprint(C)) { - Result += C; - } else { - Result += '\\'; // print all other chars as octal value - Result += toOctal(C >> 6); - Result += toOctal(C >> 3); - Result += toOctal(C >> 0); - } - } - Result += "\""; - - return Result; -} - -inline bool -ArrayTypeIsString(const ArrayType* arrayType) -{ - return (arrayType->getElementType() == Type::UByteTy || - arrayType->getElementType() == Type::SByteTy); -} - - -inline const std::string -TypeToDataDirective(const Type* type) -{ - switch(type->getPrimitiveID()) - { - case Type::BoolTyID: case Type::UByteTyID: case Type::SByteTyID: - return ".byte"; - case Type::UShortTyID: case Type::ShortTyID: - return ".half"; - case Type::UIntTyID: case Type::IntTyID: - return ".word"; - case Type::ULongTyID: case Type::LongTyID: case Type::PointerTyID: - return ".xword"; - case Type::FloatTyID: - return ".word"; - case Type::DoubleTyID: - return ".xword"; - case Type::ArrayTyID: - if (ArrayTypeIsString((ArrayType*) type)) - return ".ascii"; - else - return ""; - default: - return ""; - } -} - -// Get the size of the type -// -inline unsigned int -TypeToSize(const Type* type, const TargetMachine& target) -{ - return target.findOptimalStorageSize(type); -} - -// Get the size of the constant for the given target. -// If this is an unsized array, return 0. -// -inline unsigned int -ConstantToSize(const Constant* CV, const TargetMachine& target) -{ - if (const ConstantArray* CVA = dyn_cast(CV)) - { - const ArrayType *aty = cast(CVA->getType()); - if (ArrayTypeIsString(aty)) - return 1 + CVA->getNumOperands(); - } - - return TypeToSize(CV->getType(), target); -} - -// Align data larger than one L1 cache line on L1 cache line boundaries. -// Align all smaller data on the next higher 2^x boundary (4, 8, ...). -// -inline unsigned int -SizeToAlignment(unsigned int size, const TargetMachine& target) -{ - unsigned short cacheLineSize = target.getCacheInfo().getCacheLineSize(1); - if (size > (unsigned) cacheLineSize / 2) - return cacheLineSize; - else - for (unsigned sz=1; /*no condition*/; sz *= 2) - if (sz >= size) - return sz; -} - -// Get the size of the type and then use SizeToAlignment. -// -inline unsigned int -TypeToAlignment(const Type* type, const TargetMachine& target) -{ - return SizeToAlignment(TypeToSize(type, target), target); -} - -// Get the size of the constant and then use SizeToAlignment. -// Handles strings as a special case; -inline unsigned int -ConstantToAlignment(const Constant* CV, const TargetMachine& target) -{ - if (const ConstantArray* CVA = dyn_cast(CV)) - if (ArrayTypeIsString(cast(CVA->getType()))) - return SizeToAlignment(1 + CVA->getNumOperands(), target); - - return TypeToAlignment(CV->getType(), target); -} - - -// Print a single constant value. -void -SparcModuleAsmPrinter::printSingleConstantValue(const Constant* CV) -{ - assert(CV->getType() != Type::VoidTy && - CV->getType() != Type::TypeTy && - CV->getType() != Type::LabelTy && - "Unexpected type for Constant"); - - assert((!isa(CV) && ! isa(CV)) - && "Aggregate types should be handled outside this function"); - - toAsm << "\t" << TypeToDataDirective(CV->getType()) << "\t"; - - if (const ConstantPointerRef* CPR = dyn_cast(CV)) - { // This is a constant address for a global variable or method. - // Use the name of the variable or method as the address value. - assert(isa(CPR->getValue()) && "Unexpected non-global"); - toAsm << getID(CPR->getValue()) << "\n"; - } - else if (isa(CV)) - { // Null pointer value - toAsm << "0\n"; - } - else if (const ConstantExpr* CE = dyn_cast(CV)) - { // Constant expression built from operators, constants, and symbolic addrs - toAsm << ConstantExprToString(CE, Target) << "\n"; - } - else if (CV->getType()->isPrimitiveType()) // Check primitive types last - { - if (CV->getType()->isFloatingPoint()) { - // FP Constants are printed as integer constants to avoid losing - // precision... - double Val = cast(CV)->getValue(); - if (CV->getType() == Type::FloatTy) { - float FVal = (float)Val; - char *ProxyPtr = (char*)&FVal; // Abide by C TBAA rules - toAsm << *(unsigned int*)ProxyPtr; - } else if (CV->getType() == Type::DoubleTy) { - char *ProxyPtr = (char*)&Val; // Abide by C TBAA rules - toAsm << *(uint64_t*)ProxyPtr; - } else { - assert(0 && "Unknown floating point type!"); - } - - toAsm << "\t! " << CV->getType()->getDescription() - << " value: " << Val << "\n"; - } else { - WriteAsOperand(toAsm, CV, false, false) << "\n"; - } - } - else - { - assert(0 && "Unknown elementary type for constant"); - } -} - -void -SparcModuleAsmPrinter::PrintZeroBytesToPad(int numBytes) -{ - for ( ; numBytes >= 8; numBytes -= 8) - printSingleConstantValue(Constant::getNullValue(Type::ULongTy)); - - if (numBytes >= 4) - { - printSingleConstantValue(Constant::getNullValue(Type::UIntTy)); - numBytes -= 4; - } - - while (numBytes--) - printSingleConstantValue(Constant::getNullValue(Type::UByteTy)); -} - -// Print a constant value or values (it may be an aggregate). -// Uses printSingleConstantValue() to print each individual value. -void -SparcModuleAsmPrinter::printConstantValueOnly(const Constant* CV, - int numPadBytesAfter /* = 0*/) -{ - const ConstantArray *CVA = dyn_cast(CV); - - if (CVA && isStringCompatible(CVA)) - { // print the string alone and return - toAsm << "\t" << ".ascii" << "\t" << getAsCString(CVA) << "\n"; - } - else if (CVA) - { // Not a string. Print the values in successive locations - const std::vector &constValues = CVA->getValues(); - for (unsigned i=0; i < constValues.size(); i++) - printConstantValueOnly(cast(constValues[i].get())); - } - else if (const ConstantStruct *CVS = dyn_cast(CV)) - { // Print the fields in successive locations. Pad to align if needed! - const StructLayout *cvsLayout = - Target.getTargetData().getStructLayout(CVS->getType()); - const std::vector& constValues = CVS->getValues(); - unsigned sizeSoFar = 0; - for (unsigned i=0, N = constValues.size(); i < N; i++) - { - const Constant* field = cast(constValues[i].get()); - - // Check if padding is needed and insert one or more 0s. - unsigned fieldSize = - Target.getTargetData().getTypeSize(field->getType()); - int padSize = ((i == N-1? cvsLayout->StructSize - : cvsLayout->MemberOffsets[i+1]) - - cvsLayout->MemberOffsets[i]) - fieldSize; - sizeSoFar += (fieldSize + padSize); - - // Now print the actual field value - printConstantValueOnly(field, padSize); - } - assert(sizeSoFar == cvsLayout->StructSize && - "Layout of constant struct may be incorrect!"); - } - else - printSingleConstantValue(CV); - - if (numPadBytesAfter) - PrintZeroBytesToPad(numPadBytesAfter); -} - -// Print a constant (which may be an aggregate) prefixed by all the -// appropriate directives. Uses printConstantValueOnly() to print the -// value or values. -void -SparcModuleAsmPrinter::printConstant(const Constant* CV, std::string valID) -{ - if (valID.length() == 0) - valID = getID(CV); - - toAsm << "\t.align\t" << ConstantToAlignment(CV, Target) << "\n"; - - // Print .size and .type only if it is not a string. - const ConstantArray *CVA = dyn_cast(CV); - if (CVA && isStringCompatible(CVA)) - { // print it as a string and return - toAsm << valID << ":\n"; - toAsm << "\t" << ".ascii" << "\t" << getAsCString(CVA) << "\n"; - return; - } - - toAsm << "\t.type" << "\t" << valID << ",#object\n"; - - unsigned int constSize = ConstantToSize(CV, Target); - if (constSize) - toAsm << "\t.size" << "\t" << valID << "," << constSize << "\n"; - - toAsm << valID << ":\n"; - - printConstantValueOnly(CV); -} - - -void SparcModuleAsmPrinter::FoldConstants(const Module &M, - hash_set &MC) { - for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) - if (!I->isExternal()) { - const hash_set &pool = - MachineFunction::get(I).getInfo()->getConstantPoolValues(); - MC.insert(pool.begin(), pool.end()); - } -} - void SparcModuleAsmPrinter::printGlobalVariable(const GlobalVariable* GV) { if (GV->hasExternalLinkage()) @@ -931,23 +931,7 @@ } } - -void SparcModuleAsmPrinter::emitGlobalsAndConstants(const Module &M) { - // First, get the constants there were marked by the code generator for - // inclusion in the assembly code data area and fold them all into a - // single constant pool since there may be lots of duplicates. Also, - // lets force these constants into the slot table so that we can get - // unique names for unnamed constants also. - // - hash_set moduleConstants; - FoldConstants(M, moduleConstants); - - // Output constants spilled to memory - enterSection(AsmPrinter::ReadOnlyData); - for (hash_set::const_iterator I = moduleConstants.begin(), - E = moduleConstants.end(); I != E; ++I) - printConstant(*I); - +void SparcModuleAsmPrinter::emitGlobals(const Module &M) { // Output global variables... for (Module::const_giterator GI = M.gbegin(), GE = M.gend(); GI != GE; ++GI) if (! GI->isExternal()) { From brukman at cs.uiuc.edu Fri Nov 7 12:07:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Nov 7 12:07:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp SparcV9CodeEmitter.h Message-ID: <200311071806.MAA02335@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcV9CodeEmitter.cpp updated: 1.39 -> 1.40 SparcV9CodeEmitter.h updated: 1.15 -> 1.16 --- Log message: Switch to emitting MachineConstantPool the way it was meant to be done. --- Diffs of the changes: (+8 -49) Index: llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp diff -u llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp:1.39 llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp:1.40 --- llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp:1.39 Mon Oct 20 14:43:17 2003 +++ llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp Fri Nov 7 12:06:26 2003 @@ -593,13 +593,8 @@ unsigned* CurrPC = (unsigned*)(intptr_t)MCE.getCurrentPCValue(); BBRefs.push_back(std::make_pair(BB, std::make_pair(CurrPC, &MI))); } else if (const Constant *C = dyn_cast(V)) { - if (ConstantMap.find(C) != ConstantMap.end()) { - rv = (int64_t)MCE.getConstantPoolEntryAddress(ConstantMap[C]); - DEBUG(std::cerr << "const: 0x" << std::hex << rv << "\n"); - } else { - std::cerr << "ERROR: constant not in map:" << MO << "\n"; - abort(); - } + std::cerr << "ERROR: constants should not appear in PcRel:" << MO << "\n"; + abort(); } else if (GlobalValue *GV = dyn_cast(V)) { // same as MO.isGlobalAddress() DEBUG(std::cerr << "GlobalValue: "); @@ -623,17 +618,6 @@ } } else { rv = (int64_t)MCE.getGlobalValueAddress(GV); - if (rv == 0) { - if (Constant *C = ConstantPointerRef::get(GV)) { - if (ConstantMap.find(C) != ConstantMap.end()) { - rv = MCE.getConstantPoolEntryAddress(ConstantMap[C]); - } else { - std::cerr << "Constant: 0x" << std::hex << (intptr_t)C - << ", " << *V << " not found in ConstantMap!\n"; - abort(); - } - } - } DEBUG(std::cerr << "Global addr: 0x" << std::hex << rv << "\n"); } // The real target of the call is Addr = PC + (rv * 4) @@ -698,9 +682,8 @@ std::cerr << "ERROR: Frame index unhandled.\n"; abort(); } else if (MO.isConstantPoolIndex()) { - // Sparc backend doesn't generate this (yet...) - std::cerr << "ERROR: Constant Pool index unhandled.\n"; - abort(); + unsigned Index = MO.getConstantPoolIndex(); + rv = MCE.getConstantPoolEntryAddress(Index); } else { std::cerr << "ERROR: Unknown type of MachineOperand: " << MO << "\n"; abort(); @@ -734,27 +717,12 @@ << ", address: " << "0x" << std::hex << (long)MCE.getCurrentPCValue() << "\n"); - // The Sparc backend does not use MachineConstantPool; - // instead, it has its own constant pool implementation. - // We create a new MachineConstantPool here to be compatible with the emitter. - MachineConstantPool MCP; - const hash_set &pool = MF.getInfo()->getConstantPoolValues(); - for (hash_set::const_iterator I = pool.begin(), - E = pool.end(); I != E; ++I) - { - Constant *C = (Constant*)*I; - unsigned idx = MCP.getConstantPoolIndex(C); - DEBUG(std::cerr << "Constant[" << idx << "] = 0x" << (intptr_t)C << "\n"); - ConstantMap[C] = idx; - } - MCE.emitConstantPool(&MCP); - + MCE.emitConstantPool(MF.getConstantPool()); for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) emitBasicBlock(*I); MCE.finishFunction(MF); DEBUG(std::cerr << "Finishing fn " << MF.getFunction()->getName() << "\n"); - ConstantMap.clear(); // Resolve branches to BasicBlocks for the entire function for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) { @@ -831,14 +799,9 @@ (void*)(intptr_t)TheJITResolver->getLazyResolver(cast(V)); } else if (Constant *C = ConstantPointerRef::get(V)) { - if (ConstantMap.find(C) != ConstantMap.end()) { - return (void*) - (intptr_t)MCE.getConstantPoolEntryAddress(ConstantMap[C]); - } else { - std::cerr << "Constant: 0x" << std::hex << &*C << std::dec - << ", " << *V << " not found in ConstantMap!\n"; - abort(); - } + // no longer applicable + std::cerr << "Unhandled Constant: " << *C << "\n"; + abort(); } else { std::cerr << "Unhandled global: " << *V << "\n"; abort(); Index: llvm/lib/Target/Sparc/SparcV9CodeEmitter.h diff -u llvm/lib/Target/Sparc/SparcV9CodeEmitter.h:1.15 llvm/lib/Target/Sparc/SparcV9CodeEmitter.h:1.16 --- llvm/lib/Target/Sparc/SparcV9CodeEmitter.h:1.15 Tue Oct 21 10:17:13 2003 +++ llvm/lib/Target/Sparc/SparcV9CodeEmitter.h Fri Nov 7 12:06:26 2003 @@ -34,10 +34,6 @@ // Tracks where each BasicBlock starts std::map BBLocations; - // Tracks locations of Constants which are laid out in memory (e.g. FP) - // But we also need to map Constants to ConstantPool indices - std::map ConstantMap; - public: SparcV9CodeEmitter(TargetMachine &T, MachineCodeEmitter &M); ~SparcV9CodeEmitter(); From lattner at cs.uiuc.edu Fri Nov 7 12:10:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Nov 7 12:10:00 2003 Subject: [llvm-commits] CVS: poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp Message-ID: <200311071809.MAA02839@zion.cs.uiuc.edu> Changes in directory poolalloc/runtime/PoolAllocator: PoolAllocatorChained.cpp updated: 1.23 -> 1.24 --- Log message: Implement PoolSlab::getSlabSize(PoolTy *) correctly. --- Diffs of the changes: (+9 -1) Index: poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp diff -u poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp:1.23 poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp:1.24 --- poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp:1.23 Fri Nov 7 11:29:46 2003 +++ poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp Fri Nov 7 12:09:00 2003 @@ -95,7 +95,15 @@ // getSlabSize - Return the number of nodes that each slab should contain. static unsigned getSlabSize(PoolTy *Pool) { - return 325; + // We need space for the header... + unsigned NumNodes = PageSize-sizeof(PoolSlab); + + // We need space for the NodeFlags... + unsigned NodeFlagsBytes = NumNodes/Pool->NodeSize * 2 / 8; + NumNodes -= (NodeFlagsBytes+3) & ~3; // Round up to int boundaries. + + // Divide the remainder among the nodes! + return NumNodes / Pool->NodeSize; } void addToList(PoolSlab **PrevPtrPtr) { From brukman at cs.uiuc.edu Fri Nov 7 12:12:02 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Nov 7 12:12:02 2003 Subject: [llvm-commits] CVS: llvm/docs/CommandLine.html Message-ID: <200311071811.MAA07663@zion.cs.uiuc.edu> Changes in directory llvm/docs: CommandLine.html updated: 1.17 -> 1.18 --- Log message: Make the page footer consistent with the rest of the site. --- Diffs of the changes: (+5 -5) Index: llvm/docs/CommandLine.html diff -u llvm/docs/CommandLine.html:1.17 llvm/docs/CommandLine.html:1.18 --- llvm/docs/CommandLine.html:1.17 Mon Oct 27 12:18:16 2003 +++ llvm/docs/CommandLine.html Fri Nov 7 12:11:14 2003 @@ -2,8 +2,8 @@ "http://www.w3.org/TR/html4/strict.dtd"> - CommandLine 2.0 Library Manual + @@ -1689,10 +1689,10 @@


      From lattner at cs.uiuc.edu Fri Nov 7 12:41:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Nov 7 12:41:00 2003 Subject: [llvm-commits] CVS: poolalloc/lib/PoolAllocate/PoolAllocate.cpp Message-ID: <200311071840.MAA08652@zion.cs.uiuc.edu> Changes in directory poolalloc/lib/PoolAllocate: PoolAllocate.cpp updated: 1.30 -> 1.31 --- Log message: Add support for invoke instructions: do not turn invokes into calls, turn invokes into invokes! --- Diffs of the changes: (+19 -17) Index: poolalloc/lib/PoolAllocate/PoolAllocate.cpp diff -u poolalloc/lib/PoolAllocate/PoolAllocate.cpp:1.30 poolalloc/lib/PoolAllocate/PoolAllocate.cpp:1.31 --- poolalloc/lib/PoolAllocate/PoolAllocate.cpp:1.30 Sun Nov 2 18:32:28 2003 +++ poolalloc/lib/PoolAllocate/PoolAllocate.cpp Fri Nov 7 12:40:04 2003 @@ -896,13 +896,8 @@ } assert((phtype != 0) && "Needs to be implemented \n "); std::map &PoolDescType = FI.PoolDescType; - if (PoolDescType.count(PH)) { - //There is already an entry, so this is just sanity check - assert((phtype == PoolDescType[PH]) && "pool allocate type info wrong"); - } else { + if (!PoolDescType.count(PH)) PoolDescType[PH] = phtype; - } - // Insert a cast and a call to poolfree... Value *Casted = Arg; @@ -1100,17 +1095,19 @@ std::string Name = TheCall->getName(); TheCall->setName(""); Value *NewCall; - if (Args.size() > (unsigned)std::distance(CS.arg_begin(), CS.arg_end())) { + Value *CalledValuePtr = CS.getCalledValue(); + if (Args.size() > (unsigned)CS.arg_size()) { // If there are any pool arguments - CastInst *CastI = - new CastInst(CS.getCalledValue(), - PAInfo.getFuncInfo(*FuncClass)->Clone->getType(), "tmp", - TheCall); - // FIXME: Should create invoke instructions as needed! - NewCall = new CallInst(CastI, Args, Name, TheCall); + CalledValuePtr = new CastInst(CS.getCalledValue(), + PAInfo.getFuncInfo(*FuncClass)->Clone->getType(), "tmp", + TheCall); + } + + if (InvokeInst *II = dyn_cast(TheCall)) { + NewCall = new InvokeInst(CalledValuePtr, II->getNormalDest(), + II->getExceptionalDest(), Args, Name, TheCall); } else { - // FIXME: Should create invoke instructions as needed! - NewCall = new CallInst(CS.getCalledValue(), Args, Name, TheCall); + NewCall = new CallInst(CalledValuePtr, Args, Name, TheCall); } TheCall->replaceAllUsesWith(NewCall); @@ -1207,8 +1204,13 @@ std::string Name = TheCall->getName(); TheCall->setName(""); - // FIXME: Insert an invoke if necessary... - Value *NewCall = new CallInst(CFI->Clone, Args, Name, TheCall); + Value *NewCall; + if (InvokeInst *II = dyn_cast(TheCall)) { + NewCall = new InvokeInst(CFI->Clone, II->getNormalDest(), + II->getExceptionalDest(), Args, Name, TheCall); + } else { + NewCall = new CallInst(CFI->Clone, Args, Name, TheCall); + } TheCall->replaceAllUsesWith(NewCall); DEBUG(std::cerr << " Result Call: " << *NewCall); From brukman at cs.uiuc.edu Fri Nov 7 12:57:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Nov 7 12:57:01 2003 Subject: [llvm-commits] CVS: llvm/include/llvm/PassSupport.h Message-ID: <200311071856.MAA13365@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm: PassSupport.h updated: 1.15 -> 1.16 --- Log message: Added ability to register FunctionPasses as optimizations, with TargetMachine-accepting constructors (thanks to Chris). --- Diffs of the changes: (+20 -0) Index: llvm/include/llvm/PassSupport.h diff -u llvm/include/llvm/PassSupport.h:1.15 llvm/include/llvm/PassSupport.h:1.16 --- llvm/include/llvm/PassSupport.h:1.15 Mon Oct 20 15:19:14 2003 +++ llvm/include/llvm/PassSupport.h Fri Nov 7 12:56:32 2003 @@ -219,12 +219,32 @@ if (CFGOnly) setOnlyUsesCFG(); } + /// Register FunctionPass using default constructor explicitly... + /// + RegisterOpt(const char *PassArg, const char *Name, FunctionPass *(*ctor)(), + bool CFGOnly = false) { + registerPass(new PassInfo(Name, PassArg, typeid(PassName), + PassInfo::Optimization, (Pass*(*)())ctor)); + if (CFGOnly) setOnlyUsesCFG(); + } + /// Register Pass using TargetMachine constructor... /// RegisterOpt(const char *PassArg, const char *Name, Pass *(*targetctor)(TargetMachine &), bool CFGOnly = false) { registerPass(new PassInfo(Name, PassArg, typeid(PassName), PassInfo::Optimization, 0, targetctor)); + if (CFGOnly) setOnlyUsesCFG(); + } + + /// Register FunctionPass using TargetMachine constructor... + /// + RegisterOpt(const char *PassArg, const char *Name, + FunctionPass *(*targetctor)(TargetMachine &), + bool CFGOnly = false) { + registerPass(new PassInfo(Name, PassArg, typeid(PassName), + PassInfo::Optimization, 0, + (Pass*(*)(TargetMachine&))targetctor)); if (CFGOnly) setOnlyUsesCFG(); } }; From gaeke at cs.uiuc.edu Fri Nov 7 13:26:01 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Fri Nov 7 13:26:01 2003 Subject: [llvm-commits] CVS: llvm/docs/ProgrammersManual.html Message-ID: <200311071925.NAA19572@zion.cs.uiuc.edu> Changes in directory llvm/docs: ProgrammersManual.html updated: 1.48 -> 1.49 --- Log message: Mention class CallSite --- Diffs of the changes: (+28 -1) Index: llvm/docs/ProgrammersManual.html diff -u llvm/docs/ProgrammersManual.html:1.48 llvm/docs/ProgrammersManual.html:1.49 --- llvm/docs/ProgrammersManual.html:1.48 Mon Oct 27 12:18:16 2003 +++ llvm/docs/ProgrammersManual.html Fri Nov 7 13:25:45 2003 @@ -49,6 +49,8 @@ pointer
    • Finding call sites: a more complex example +
    • Treating calls and invokes the + same way
    • Iterating over def-use & use-def chains
    @@ -742,6 +744,31 @@ }; + + +


    Treating calls and +invokes the same way


    Iterating over def-use & use-def chains

    - -

    - -

  • Configure the LLVM Build Environment -
      -
    1. Change directory to where you want to store the LLVM object - files and run configure to configure the Makefiles and - header files for the default platform. - Useful options include: -
        -
      • --with-llvmgccdir=directory -
        - Specify where the LLVM GCC frontend is installed. -

        - -

      • --enable-spec2000=directory -
        - Enable the SPEC2000 benchmarks for testing. The SPEC2000 - benchmarks should be available in directory. -
      -
    - -

    - -

  • Build the LLVM Suite -
      -
    1. Set your LLVM_LIB_SEARCH_PATH environment variable. -
    2. gmake -k |& tee gnumake.out -    # this is csh or tcsh syntax -
    +
  • cd where-you-want-the-C-front-end-to-live +
  • gunzip --stdout cfrontend.platform.tar.gz | tar -xvf - +
  • Sparc Only:
    + cd cfrontend/sparc
    + ./fixheaders
    +
  • + +
  • Get the Source Code +
      +
    • With the distributed files: +
        +
      1. cd where-you-want-llvm-to-live +
      2. gunzip --stdout llvm.tar.gz | tar -xvf - +
      3. cd llvm +
    • -

      +

    • With anonymous CVS access: +
        +
      1. cd where-you-want-llvm-to-live
      2. +
      3. cvs -d + :pserver:anon at llvm-cvs.cs.uiuc.edu:/var/cvs/llvm login
      4. +
      5. Hit the return key when prompted for the password. +
      6. cvs -z3 -d :pserver:anon at llvm-cvs.cs.uiuc.edu:/var/cvs/llvm + co llvm
      7. +
      8. cd llvm
      9. +
    • +
  • + +
  • Configure the LLVM Build Environment +
      +
    1. Change directory to where you want to store the LLVM object + files and run configure to configure the Makefiles and + header files for the default platform. Useful options include: +
        +
      • --with-llvmgccdir=directory +

        Specify where the LLVM GCC frontend is installed.

      • +
      • --enable-spec2000=directory +

        Enable the SPEC2000 benchmarks for testing. The SPEC2000 + benchmarks should be available in + directory.

      • +
      +
  • + +
  • Build the LLVM Suite: +
      +
    1. Set your LLVM_LIB_SEARCH_PATH environment variable. +
    2. gmake -k |& tee gnumake.out +    # this is csh or tcsh syntax +
    + + + +

    Consult the Getting Started with LLVM section for +detailed information on configuring and compiling LLVM. See Setting Up Your Environment for tips that simplify +working with the GCC front end and LLVM tools. Go to Program +Layout to learn about the layout of the source code tree.

    + + + + + + + +
    + +

    Before you begin to use the LLVM system, review the requirements given below. +This may save you some trouble by knowing ahead of time what hardware and +software you will need.

    + +
    + + + + +
    + +

    LLVM is known to work on the following platforms:

    + +
      + +
    • Linux on x86 (Pentium and above) +
        +
      • Approximately 760 MB of Free Disk Space +
          +
        • Source code: 30 MB
        • +
        • Object code: 670 MB
        • +
        • GCC front end: 60 MB
        • +
      • +
    • - +
    • Solaris on SparcV9 (Ultrasparc) +
        +
      • Approximately 1.24 GB of Free Disk Space +
          +
        • Source code: 30 MB
        • +
        • Object code: 1000 MB
        • +
        • GCC front end: 210 MB
        • +
      • +
    • -

      - Consult the Getting Started with LLVM section for - detailed information on configuring and compiling LLVM. See - Setting Up Your Environment for tips that - simplify working with the GCC front end and LLVM tools. Go to - Program Layout to learn about the layout of the - source code tree. - - -

      -

      Requirements

      -
      -
      - - - Before you begin to use the LLVM system, review the requirements given - below. This may save you some trouble by knowing ahead of time what - hardware and software you will need. - - -

      Hardware

      - - LLVM is known to work on the following platforms: -
        -
      • Linux on x86 (Pentium and above) -
          -
        • Approximately 760 MB of Free Disk Space -
            -
          • Source code: 30 MB -
          • Object code: 670 MB -
          • GCC front end: 60 MB -
          -
        - -

        - -

      • Solaris on SparcV9 (Ultrasparc) -
          -
        • Approximately 1.24 GB of Free Disk Space -
            -
          • Source code: 30 MB -
          • Object code: 1000 MB -
          • GCC front end: 210 MB -
          -
        -
      - - The LLVM suite may compile on other platforms, but it is not - guaranteed to do so. If compilation is successful, the LLVM utilities - should be able to assemble, disassemble, analyze, and optimize LLVM - bytecode. Code generation should work as well, although the generated - native code may not work on your platform. -

      - The GCC front end is not very portable at the moment. If you want to get - it to work on another platform, you can download a copy of the source - and try to compile it on your platform. -

      - - -

      Software

      - -

      +

    - Compiling LLVM requires that you have several software packages installed: +

    The LLVM suite may compile on other platforms, but it is not +guaranteed to do so. If compilation is successful, the LLVM utilities should be +able to assemble, disassemble, analyze, and optimize LLVM bytecode. Code +generation should work as well, although the generated native code may not work +on your platform.

    -
      -
    • - GCC 3.x with C and C++ language support +

      The GCC front end is not very portable at the moment. If you want to get it +to work on another platform, you can download a copy of the source and try to +compile it on your platform.

      -
    • - GNU Make +
    -
  • - Flex + + -
  • - Bison - +
    -

    - There are some additional tools that you may want to have when working with - LLVM: -

    +

    Compiling LLVM requires that you have several software packages +installed:

    -
      -
    • GNU Autoconf -
    • GNU M4 -

      - If you want to make changes to the configure scripts, you will need - GNU autoconf (2.57 or higher), and consequently, GNU M4 (version 1.4 - or higher). -

      - -
    • QMTest -
    • Python -

      - These are needed to use the LLVM test suite. -

    - - -

    The remainder of this guide is meant to get you up and running with - LLVM and to give you some basic information about the LLVM environment. - A complete guide to installation is provided in the - next section. - -

    The later sections of this guide describe the general layout of the the LLVM source tree, a simple example using the LLVM tool chain, and links to find more information about LLVM or to get - help via e-mail. - - -

    -

    Getting Started with LLVM

    -
    -
    - - - -

    Terminology and Notation

    - - -

    Throughout this manual, the following names are used to denote paths - specific to the local system and working environment. These are not - environment variables you need to set but just strings used in the rest - of this document below. In any of the examples below, simply replace - each of these names with the appropriate pathname on your local system. - All these paths are absolute:

    -
    -
    SRC_ROOT -
    - This is the top level directory of the LLVM source tree. -

    - -

    OBJ_ROOT -
    - This is the top level directory of the LLVM object tree (i.e. the - tree where object files and compiled programs will be placed. It - can be the same as SRC_ROOT). -

    - -

    LLVMGCCDIR -
    - This is the where the LLVM GCC Front End is installed. -

    - For the pre-built GCC front end binaries, the LLVMGCCDIR is - cfrontend/platform/llvm-gcc. -

    - - -

    Setting Up Your Environment

    - +
      +
    • GCC 3.x with C and C++ language + support
    • -

      - In order to compile and use LLVM, you will need to set some environment - variables. There are also some shell aliases which you may find useful. - You can set these on the command line, or better yet, set them in your - .cshrc or .profile. - -

      -
      LLVM_LIB_SEARCH_PATH=LLVMGCCDIR/bytecode-libs -
      - This environment variable helps the LLVM GCC front end find bytecode - libraries that it will need for compilation. -

      - -

      alias llvmgcc LLVMGCCDIR/bin/gcc -
      alias llvmg++ LLVMGCCDIR/bin/g++ -
      - This alias allows you to use the LLVM C and C++ front ends without putting - them in your PATH or typing in their complete pathnames. -
      - - -

      Unpacking the LLVM Archives

      - +
    • GNU Make
    • -

      - If you have the LLVM distribution, you will need to unpack it before you - can begin to compile it. LLVM is distributed as a set of three files. Each - file is a TAR archive that is compressed with the gzip program. -

      - -

      The three files are as follows: -

      -
      llvm.tar.gz -
      This is the source code to the LLVM suite. -

      - -

      cfrontend.sparc.tar.gz -
      This is the binary release of the GCC front end for Solaris/Sparc. -

      - -

      cfrontend.x86.tar.gz -
      This is the binary release of the GCC front end for Linux/x86. -
      - - -

      Checkout LLVM from CVS

      - - -

      If you have access to our CVS repository, you can get a fresh copy of - the entire source code. All you need to do is check it out from CVS as - follows: -

        -
      • cd where-you-want-llvm-to-live -
      • cvs -d :pserver:anon at llvm-cvs.cs.uiuc.edu:/var/cvs/llvm login -
      • Hit the return key when prompted for the password. -
      • cvs -z3 -d :pserver:anon at llvm-cvs.cs.uiuc.edu:/var/cvs/llvm co llvm -
      - -

      This will create an 'llvm' directory in the current - directory and fully populate it with the LLVM source code, Makefiles, - test directories, and local copies of documentation files.

      +
    • Flex
    • -

      - Note that the GCC front end is not included in the CVS repository. You - should have downloaded the binary distribution for your platform. -

      - - -

      Install the GCC Front End

      - +
    • Bison
    • +
    -

    - Before configuring and compiling the LLVM suite, you need to extract the - LLVM GCC front end from the binary distribution. It is used for building - the - bytecode libraries later used by the GCC front end for linking programs, and - its location must be specified when the LLVM suite is configured. -

    +

    There are some additional tools that you may want to have when working with +LLVM:

    -

    - To install the GCC front end, do the following: -

      -
    1. cd where-you-want-the-front-end-to-live -
    2. gunzip --stdout cfrontend.platform.tar.gz | tar -xvf - - -
    +
      +
    • GNU Autoconf +
    • GNU M4 - If you are on a Sparc/Solaris machine, you will need to fix the header - files: +

      If you want to make changes to the configure scripts, you will need GNU + autoconf (2.57 or higher), and consequently, GNU M4 (version 1.4 or + higher).

    • -

      +

    • QMTest
    • +
    • Python - - cd cfrontend/sparc -
      - ./fixheaders -
      +

      These are needed to use the LLVM test suite.

    • -

      - The binary versions of the GCC front end may not suit all of your needs. - For example, the binary distribution may include an old version of a system - header file, not "fix" a header file that needs to be fixed for GCC, or it - may be linked with libraries not available on your system. -

      +
    -

    - In cases like these, you may want to try - building the GCC front end from source. - This is not for the faint of heart, so be forewarned. -

    - -

    Local LLVM Configuration

    - - -

    Once checked out from the CVS repository, the LLVM suite source code - must be configured via the configure script. This script sets - variables in llvm/Makefile.config and - llvm/include/Config/config.h. It also populates OBJ_ROOT - with the Makefiles needed to build LLVM. -

    - The following environment variables are used by the configure - script to configure the build system: -

    - - - - - - - - - - - - - - - - -
    Variable - Purpose -
    CC - Tells configure which C compiler to use. By default, - configure will look for the first GCC C compiler in - PATH. Use this variable to override - configure's default behavior. -
    CXX - Tells configure which C++ compiler to use. By default, - configure will look for the first GCC C++ compiler in - PATH. Use this variable to override - configure's default behavior. -
    +

    The remainder of this guide is meant to get you up and running with +LLVM and to give you some basic information about the LLVM environment. +A complete guide to installation is provided in the +next section.

    -

    - The following options can be used to set or enable LLVM specific options: -

    +

    The later sections of this guide describe the general layout of the the LLVM source tree, a simple example using the LLVM tool chain, and links to find more information about LLVM or to get +help via e-mail.

    -
    -
    --with-llvmgccdir=LLVMGCCDIR -
    - Path to the location where the LLVM C front end binaries and - associated libraries will be installed. -

    -

    --enable-optimized -
    - Enables optimized compilation by default (debugging symbols are removed - and GCC optimization flags are enabled). The default is to use an - unoptimized build (also known as a debug build). -

    -

    --enable-jit -
    - Compile the Just In Time (JIT) functionality. This is not available - on all platforms. The default is dependent on platform, so it is best - to explicitly enable it if you want it. -

    -

    --enable-spec2000 -
    --enable-spec2000=<directory> -
    - Enable the use of SPEC2000 when testing LLVM. This is disabled by default - (unless configure finds SPEC2000 installed). By specifying - directory, you can tell configure where to find the SPEC2000 - benchmarks. If directory is left unspecified, configure - uses the default value - /home/vadve/shared/benchmarks/speccpu2000/benchspec. -
    +
    -

    - To configure LLVM, follow these steps: -

      -
    1. Change directory into the object root directory: -
      - cd OBJ_ROOT -

      - -

    2. Run the configure script located in the LLVM source tree: -
      - SRC_ROOT/configure -

      -

    -

    - - In addition to running configure, you must set the - LLVM_LIB_SEARCH_PATH environment variable in your startup scripts. - This environment variable is used to locate "system" libraries like - "-lc" and "-lm" when linking. This variable should be set - to the absolute path for the bytecode-libs subdirectory of the GCC front end - install, or LLVMGCCDIR/bytecode-libs. For example, one might - set LLVM_LIB_SEARCH_PATH to - /home/vadve/lattner/local/x86/llvm-gcc/bytecode-libs for the X86 - version of the GCC front end on our research machines.

    - - -

    Compiling the LLVM Suite Source Code

    - - - Once you have configured LLVM, you can build it. There are three types of - builds: - -
    -
    Debug Builds -
    - These builds are the default when one types gmake (unless the - --enable-optimized option was used during configuration). The - build system will compile the tools and libraries with debugging - information. -

    - -

    Release (Optimized) Builds -
    - These builds are enabled with the --enable-optimized option to - configure or by specifying ENABLE_OPTIMIZED=1 on the - gmake command line. For these builds, the build system will - compile the tools and libraries with GCC optimizations enabled and strip - debugging information from the libraries and executables it generates. -

    - -

    Profile Builds -
    - These builds are for use with profiling. They compile profiling - information into the code for use with programs like gprof. - Profile builds must be started by specifying ENABLE_PROFILING=1 - on the gmake command line. -
    + + + - Once you have LLVM configured, you can build it by entering the - OBJ_ROOT directory and issuing the following command: -

    - gmake + +

    +
    + +

    Throughout this manual, the following names are used to denote paths +specific to the local system and working environment. These are not +environment variables you need to set but just strings used in the rest +of this document below. In any of the examples below, simply replace +each of these names with the appropriate pathname on your local system. +All these paths are absolute:

    + +
    +
    SRC_ROOT +
    + This is the top level directory of the LLVM source tree.

    - If you have multiple processors in your machine, you may wish to use some - of the parallel build options provided by GNU Make. For example, you could - use the command: -

    +
    OBJ_ROOT +
    + This is the top level directory of the LLVM object tree (i.e. the + tree where object files and compiled programs will be placed. It + can be the same as SRC_ROOT).

    - gmake -j2 +

    LLVMGCCDIR +
    + This is the where the LLVM GCC Front End is installed.

    - There are several special targets which are useful when working with the LLVM - source code: + For the pre-built GCC front end binaries, the LLVMGCCDIR is + cfrontend/platform/llvm-gcc. +

    -
    -
    gmake clean -
    - Removes all files generated by the build. This includes object files, - generated C/C++ files, libraries, and executables. -

    - -

    gmake distclean -
    - Removes everything that gmake clean does, but also removes - files generated by configure. It attempts to return the - source tree to the original state in which it was shipped. -

    - -

    gmake install -
    - Installs LLVM files into the proper location. For the most part, - this does nothing, but it does install bytecode libraries into the - GCC front end's bytecode library directory. If you need to update - your bytecode libraries, this is the target to use once you've built - them. -

    - -

    - - It is also possible to override default values from configure by - declaring variables on the command line. The following are some examples: - -
    -
    gmake ENABLE_OPTIMIZED=1 -
    - Perform a Release (Optimized) build. -

    - -

    gmake ENABLE_PROFILING=1 -
    - Perform a Profiling build. -

    - -

    gmake VERBOSE=1 -
    - Print what gmake is doing on standard output. -

    -

    - - Every directory in the LLVM object tree includes a Makefile to - build it and any subdirectories that it contains. Entering any directory - inside the LLVM object tree and typing gmake should rebuild - anything in or below that directory that is out of date. - - -

    The Location of LLVM Object Files

    - +
    + + + +
    + +

    +In order to compile and use LLVM, you will need to set some environment +variables. There are also some shell aliases which you may find useful. +You can set these on the command line, or better yet, set them in your +.cshrc or .profile. + +

    +
    LLVM_LIB_SEARCH_PATH=LLVMGCCDIR/bytecode-libs +
    + This environment variable helps the LLVM GCC front end find bytecode + libraries that it will need for compilation.

    - The LLVM build system is capable of sharing a single LLVM source tree among - several LLVM builds. Hence, it is possible to build LLVM for several - different platforms or configurations using the same source tree. -

    - This is accomplished in the typical autoconf manner: -

      -
    • Change directory to where the LLVM object files should live: -

      - cd OBJ_ROOT - -

    • Run the configure script found in the LLVM source directory: -

      - SRC_ROOT/configure -

    +
    alias llvmgcc LLVMGCCDIR/bin/gcc +
    alias llvmg++ LLVMGCCDIR/bin/g++ +
    + This alias allows you to use the LLVM C and C++ front ends without putting + them in your PATH or typing in their complete pathnames. +
    + +
    + + + + +
    + +

    +If you have the LLVM distribution, you will need to unpack it before you +can begin to compile it. LLVM is distributed as a set of three files. Each +file is a TAR archive that is compressed with the gzip program. +

    + +

    The three files are as follows: +

    +
    llvm.tar.gz +
    This is the source code to the LLVM suite. +

    + +

    cfrontend.sparc.tar.gz +
    This is the binary release of the GCC front end for Solaris/Sparc. +

    + +

    cfrontend.x86.tar.gz +
    This is the binary release of the GCC front end for Linux/x86. +
    + +
    + + + + +
    + +

    If you have access to our CVS repository, you can get a fresh copy of +the entire source code. All you need to do is check it out from CVS as +follows:

    + +
      +
    • cd where-you-want-llvm-to-live +
    • cvs -d :pserver:anon at llvm-cvs.cs.uiuc.edu:/var/cvs/llvm login +
    • Hit the return key when prompted for the password. +
    • cvs -z3 -d :pserver:anon at llvm-cvs.cs.uiuc.edu:/var/cvs/llvm co + llvm +
    + +

    This will create an 'llvm' directory in the current +directory and fully populate it with the LLVM source code, Makefiles, +test directories, and local copies of documentation files.

    + +

    Note that the GCC front end is not included in the CVS repository. You +should have downloaded the binary distribution for your platform.

    + +
    + + + + +
    + +

    Before configuring and compiling the LLVM suite, you need to extract the LLVM +GCC front end from the binary distribution. It is used for building the +bytecode libraries later used by the GCC front end for linking programs, and its +location must be specified when the LLVM suite is configured.

    + +

    To install the GCC front end, do the following:

    + +
      +
    1. cd where-you-want-the-front-end-to-live
    2. +
    3. gunzip --stdout cfrontend.platform.tar.gz | tar -xvf + -
    4. +
    + +

    If you are on a Sparc/Solaris machine, you will need to fix the header +files:

    + +

    cd cfrontend/sparc
    + ./fixheaders

    + +

    The binary versions of the GCC front end may not suit all of your needs. For +example, the binary distribution may include an old version of a system header +file, not "fix" a header file that needs to be fixed for GCC, or it may be +linked with libraries not available on your system.

    + +

    In cases like these, you may want to try building the GCC front end from source. This is +not for the faint of heart, so be forewarned.

    + +
    + + + + +
    + +

    Once checked out from the CVS repository, the LLVM suite source code must be +configured via the configure script. This script sets variables in +llvm/Makefile.config and llvm/include/Config/config.h. It +also populates OBJ_ROOT with the Makefiles needed to build LLVM.

    + +

    The following environment variables are used by the configure +script to configure the build system:

    + + + + + + + + + + + + + + + + +
    VariablePurpose
    CCTells configure which C compiler to use. By default, + configure will look for the first GCC C compiler in + PATH. Use this variable to override + configure's default behavior.
    CXXTells configure which C++ compiler to use. By default, + configure will look for the first GCC C++ compiler in + PATH. Use this variable to override + configure's default behavior.
    + +

    The following options can be used to set or enable LLVM specific options:

    + +
    +
    --with-llvmgccdir=LLVMGCCDIR +
    + Path to the location where the LLVM C front end binaries and + associated libraries will be installed. +

    +

    --enable-optimized +
    + Enables optimized compilation by default (debugging symbols are removed + and GCC optimization flags are enabled). The default is to use an + unoptimized build (also known as a debug build). +

    +

    --enable-jit +
    + Compile the Just In Time (JIT) functionality. This is not available + on all platforms. The default is dependent on platform, so it is best + to explicitly enable it if you want it. +

    +

    --enable-spec2000 +
    --enable-spec2000=<directory> +
    + Enable the use of SPEC2000 when testing LLVM. This is disabled by default + (unless configure finds SPEC2000 installed). By specifying + directory, you can tell configure where to find the SPEC2000 + benchmarks. If directory is left unspecified, configure + uses the default value + /home/vadve/shared/benchmarks/speccpu2000/benchspec. +
    + +

    To configure LLVM, follow these steps:

    + +
      +
    1. Change directory into the object root directory: +
      + cd OBJ_ROOT

      - The LLVM build will place files underneath OBJ_ROOT in directories - named after the build type: -

      - -
      -
      Debug Builds -
      -
      -
      Tools -
      OBJ_ROOT/tools/Debug -
      Libraries -
      OBJ_ROOT/lib/Debug -
      -

      - -

      Release Builds -
      -
      -
      Tools -
      OBJ_ROOT/tools/Release -
      Libraries -
      OBJ_ROOT/lib/Release -
      -

      - -

      Profile Builds -
      -
      -
      Tools -
      OBJ_ROOT/tools/Profile -
      Libraries -
      OBJ_ROOT/lib/Profile -
      -
      - - -
      -

      Program Layout

      -
      -
      - +
    2. Run the configure script located in the LLVM source tree: +
      + SRC_ROOT/configure

      - One useful source of information about the LLVM source base is the LLVM doxygen documentation, available at http://llvm.cs.uiuc.edu/doxygen/. - The following is a brief introduction to code layout: -

      - - -

      CVS directories

      - - - Every directory checked out of CVS will contain a CVS directory; - for the most part these can just be ignored. - - - -

      llvm/include

      - +
    - This directory contains public header files exported from the LLVM - library. The three main subdirectories of this directory are:

    +

    In addition to running configure, you must set the +LLVM_LIB_SEARCH_PATH environment variable in your startup scripts. +This environment variable is used to locate "system" libraries like +"-lc" and "-lm" when linking. This variable should be set to +the absolute path for the bytecode-libs subdirectory of the GCC front end +install, or LLVMGCCDIR/bytecode-libs. For example, one might set +LLVM_LIB_SEARCH_PATH to +/home/vadve/lattner/local/x86/llvm-gcc/bytecode-libs for the X86 +version of the GCC front end on our research machines.

    + +
    + + + -
      -
    1. llvm/include/llvm - This directory contains all of the LLVM - specific header files. This directory also has subdirectories for - different portions of LLVM: Analysis, CodeGen, - Target, Transforms, etc... - -
    2. llvm/include/Support - This directory contains generic - support libraries that are independent of LLVM, but are used by LLVM. - For example, some C++ STL utilities and a Command Line option processing - library store their header files here. - -
    3. llvm/include/Config - This directory contains header files - configured by the configure script. They wrap "standard" UNIX - and C header files. Source code can include these header files which - automatically take care of the conditional #includes that the - configure script generates. -
    - - -

    llvm/lib

    - - - This directory contains most of the source files of the LLVM system. In - LLVM, almost all - code exists in libraries, making it very easy to share code among the - different tools.

    - -

    -
    llvm/lib/VMCore/
    This directory holds the core LLVM - source files that implement core classes like Instruction and BasicBlock. - -
    llvm/lib/AsmParser/
    This directory holds the source code - for the LLVM assembly language parser library. - -
    llvm/lib/ByteCode/
    This directory holds code for reading - and write LLVM bytecode. - -
    llvm/lib/CWriter/
    This directory implements the LLVM to C - converter. - -
    llvm/lib/Analysis/
    This directory contains a variety of - different program analyses, such as Dominator Information, Call Graphs, - Induction Variables, Interval Identification, Natural Loop Identification, - etc... - -
    llvm/lib/Transforms/
    This directory contains the source - code for the LLVM to LLVM program transformations, such as Aggressive Dead - Code Elimination, Sparse Conditional Constant Propagation, Inlining, Loop - Invariant Code Motion, Dead Global Elimination, and many others... - -
    llvm/lib/Target/
    This directory contains files that - describe various target architectures for code generation. For example, - the llvm/lib/Target/Sparc directory holds the Sparc machine - description.
    - -
    llvm/lib/CodeGen/
    This directory contains the major parts - of the code generator: Instruction Selector, Instruction Scheduling, and - Register Allocation. - -
    llvm/lib/Support/
    This directory contains the source code - that corresponds to the header files located in - llvm/include/Support/. -
    - - -

    llvm/runtime

    - +
    -

    - This directory contains libraries which are compiled into LLVM bytecode and - used when linking programs with the GCC front end. Most of these libraries - are skeleton versions of real libraries; for example, libc is a stripped down - version of glibc. -

    +

    Once you have configured LLVM, you can build it. There are three types of +builds:

    +
    +
    Debug Builds +
    + These builds are the default when one types gmake (unless the + --enable-optimized option was used during configuration). The + build system will compile the tools and libraries with debugging + information.

    - Unlike the rest of the LLVM suite, this directory needs the LLVM GCC front end - to compile. -

    - - -

    llvm/test

    - - -

    This directory contains regression tests and source code that is used to - test the LLVM infrastructure. -

    - - -

    llvm/tools

    - - -

    The tools directory contains the executables built out of the - libraries above, which form the main part of the user interface. You can - always get help for a tool by typing tool_name --help. The - following is a brief introduction to the most important tools.

    - -
    -
    - -
    analyze
    analyze is used to run a specific - analysis on an input LLVM bytecode file and print out the results. It is - primarily useful for debugging analyses, or familiarizing yourself with - what an analysis does.

    - -

    bugpoint
    bugpoint is used to debug - optimization passes or code generation backends by narrowing down the - given test case to the minimum number of passes and/or instructions that - still cause a problem, whether it is a crash or miscompilation. See HowToSubmitABug.html for more information - on using bugpoint.

    - -

    llvm-ar
    The archiver produces an archive containing - the given LLVM bytecode files, optionally with an index for faster - lookup.

    - -

    llvm-as
    The assembler transforms the human readable - LLVM assembly to LLVM bytecode.

    -

    llvm-dis
    The disassembler transforms the LLVM - bytecode to human readable LLVM assembly. Additionally, it can convert - LLVM bytecode to C, which is enabled with the -c option.

    +

    Release (Optimized) Builds +
    + These builds are enabled with the --enable-optimized option to + configure or by specifying ENABLE_OPTIMIZED=1 on the + gmake command line. For these builds, the build system will + compile the tools and libraries with GCC optimizations enabled and strip + debugging information from the libraries and executables it generates. +

    -

    llvm-link
    llvm-link, not surprisingly, - links multiple LLVM modules into a single program.

    - -

    lli
    lli is the LLVM interpreter, which - can directly execute LLVM bytecode (although very slowly...). In addition - to a simple interpreter, lli also has a tracing mode (entered by - specifying -trace on the command line). Finally, for - architectures that support it (currently only x86 and Sparc), by default, - lli will function as a Just-In-Time compiler (if the - functionality was compiled in), and will execute the code much - faster than the interpreter.

    - -

    llc
    llc is the LLVM backend compiler, - which translates LLVM bytecode to a SPARC or x86 assembly file.

    - -

    llvmgcc
    llvmgcc is a GCC-based C frontend - that has been retargeted to emit LLVM code as the machine code output. It - works just like any other GCC compiler, taking the typical -c, -S, -E, - -o options that are typically used. The source code for the - llvmgcc tool is currently not included in the LLVM CVS tree - because it is quite large and not very interesting.

    - -

      -
      gccas
      This tool is invoked by the - llvmgcc frontend as the "assembler" part of the compiler. This - tool actually assembles LLVM assembly to LLVM bytecode, - performs a variety of optimizations, and outputs LLVM bytecode. Thus - when you invoke llvmgcc -c x.c -o x.o, you are causing - gccas to be run, which writes the x.o file (which is - an LLVM bytecode file that can be disassembled or manipulated just like - any other bytecode file). The command line interface to gccas - is designed to be as close as possible to the system - `as' utility so that the gcc frontend itself did not have to be - modified to interface to a "weird" assembler.

      - -

      gccld
      gccld links together several LLVM - bytecode files into one bytecode file and does some optimization. It is - the linker invoked by the GCC frontend when multiple .o files need to be - linked together. Like gccas, the command line interface of - gccld is designed to match the system linker, to aid - interfacing with the GCC frontend.

      -

    - -
    opt
    opt reads LLVM bytecode, applies a - series of LLVM to LLVM transformations (which are specified on the command - line), and then outputs the resultant bytecode. The 'opt --help' - command is a good way to get a list of the program transformations - available in LLVM.

    - -

    - - -

    llvm/utils

    - - - This directory contains utilities for working with LLVM source code, and some - of the utilities are actually required as part of the build process because - they are code generators for parts of LLVM infrastructure. - -
    - Burg/
    Burg is an instruction selector - generator -- it builds trees on which it then performs pattern-matching to - select instructions according to the patterns the user has specified. Burg - is currently used in the Sparc V9 backend.

    - -

    codegen-diff
    codegen-diff is a script - that finds differences between code that LLC generates and code that LLI - generates. This is a useful tool if you are debugging one of them, - assuming that the other generates correct output. For the full user - manual, run `perldoc codegen-diff'.

    - -

    cvsupdate
    cvsupdate is a script that will - update your CVS tree, but produce a much cleaner and more organized output - than simply running `cvs -z3 up -dP' will. For example, it will group - together all the new and updated files and modified files in separate - sections, so you can see at a glance what has changed. If you are at the - top of your LLVM CVS tree, running utils/cvsupdate is the - preferred way of updating the tree.

    - -

    emacs/
    The emacs directory contains - syntax-highlighting files which will work with Emacs and XEmacs editors, - providing syntax highlighting support for LLVM assembly files and TableGen - description files. For information on how to use the syntax files, consult - the README file in that directory.

    - -

    getsrcs.sh
    The getsrcs.sh script finds - and outputs all non-generated source files, which is useful if one wishes - to do a lot of development across directories and does not want to - individually find each file. One way to use it is to run, for example: - xemacs `utils/getsources.sh` from the top of your LLVM source - tree.

    - -

    makellvm
    The makellvm script compiles all - files in the current directory and then compiles and links the tool that - is the first argument. For example, assuming you are in the directory - llvm/lib/Target/Sparc, if makellvm is in your path, - simply running makellvm llc will make a build of the current - directory, switch to directory llvm/tools/llc and build it, - causing a re-linking of LLC.

    - -

    NightlyTest.pl and - NightlyTestTemplate.html
    These files are used in a - cron script to generate nightly status reports of the functionality of - tools, and the results can be seen by following the appropriate link on - the LLVM homepage.

    - -

    TableGen/
    The TableGen directory contains - the tool used to generate register descriptions, instruction set - descriptions, and even assemblers from common TableGen description - files.

    - -

    vim/
    The vim directory contains - syntax-highlighting files which will work with the VIM editor, providing - syntax highlighting support for LLVM assembly files and TableGen - description files. For information on how to use the syntax files, consult - the README file in that directory.

    - -

    +
    Profile Builds +
    + These builds are for use with profiling. They compile profiling + information into the code for use with programs like gprof. + Profile builds must be started by specifying ENABLE_PROFILING=1 + on the gmake command line. +
    + +

    Once you have LLVM configured, you can build it by entering the +OBJ_ROOT directory and issuing the following command:

    + +

    gmake

    + +

    If you have multiple processors in your machine, you may wish to use some of +the parallel build options provided by GNU Make. For example, you could use the +command:

    + +

    gmake -j2

    + +

    There are several special targets which are useful when working with the LLVM +source code:

    + +
    +
    gmake clean +
    + Removes all files generated by the build. This includes object files, + generated C/C++ files, libraries, and executables. +

    + +

    gmake distclean +
    + Removes everything that gmake clean does, but also removes + files generated by configure. It attempts to return the + source tree to the original state in which it was shipped. +

    + +

    gmake install +
    + Installs LLVM files into the proper location. For the most part, + this does nothing, but it does install bytecode libraries into the + GCC front end's bytecode library directory. If you need to update + your bytecode libraries, this is the target to use once you've built + them. +

    +

    + +

    It is also possible to override default values from configure by +declaring variables on the command line. The following are some examples:

    + +
    +
    gmake ENABLE_OPTIMIZED=1 +
    + Perform a Release (Optimized) build. +

    + +

    gmake ENABLE_PROFILING=1 +
    + Perform a Profiling build. +

    + +

    gmake VERBOSE=1 +
    + Print what gmake is doing on standard output. +

    +

    + +

    Every directory in the LLVM object tree includes a Makefile to build +it and any subdirectories that it contains. Entering any directory inside the +LLVM object tree and typing gmake should rebuild anything in or below +that directory that is out of date.

    + +
    + + + + +
    + +

    The LLVM build system is capable of sharing a single LLVM source tree among +several LLVM builds. Hence, it is possible to build LLVM for several different +platforms or configurations using the same source tree.

    + +

    This is accomplished in the typical autoconf manner:

    + +
      +
    • Change directory to where the LLVM object files should live:

      + +

      cd OBJ_ROOT

    • + +
    • Run the configure script found in the LLVM source + directory:

      + +

      SRC_ROOT/configure

    • +
    + +

    The LLVM build will place files underneath OBJ_ROOT in directories +named after the build type:

    + +
    +
    Debug Builds +
    +
    +
    Tools +
    OBJ_ROOT/tools/Debug +
    Libraries +
    OBJ_ROOT/lib/Debug +
    +

    + +

    Release Builds +
    +
    +
    Tools +
    OBJ_ROOT/tools/Release +
    Libraries +
    OBJ_ROOT/lib/Release +
    +

    + +

    Profile Builds +
    +
    +
    Tools +
    OBJ_ROOT/tools/Profile +
    Libraries +
    OBJ_ROOT/lib/Profile +
    +
    + +
    + + + + + +
    + +

    One useful source of information about the LLVM source base is the LLVM doxygen documentation, available at http://llvm.cs.uiuc.edu/doxygen/. +The following is a brief introduction to code layout:

    + +
    + + + + +
    + +

    Every directory checked out of CVS will contain a CVS directory; for +the most part these can just be ignored.

    + +
    + + + + +
    + +

    This directory contains public header files exported from the LLVM +library. The three main subdirectories of this directory are:

    + +
      +
    1. llvm/include/llvm - This directory contains all of the LLVM + specific header files. This directory also has subdirectories for + different portions of LLVM: Analysis, CodeGen, + Target, Transforms, etc...
    2. + +
    3. llvm/include/Support - This directory contains generic + support libraries that are independent of LLVM, but are used by LLVM. + For example, some C++ STL utilities and a Command Line option processing + library store their header files here.
    4. + +
    5. llvm/include/Config - This directory contains header files + configured by the configure script. They wrap "standard" UNIX + and C header files. Source code can include these header files which + automatically take care of the conditional #includes that the + configure script generates.
    6. +
    + +
    + + + + +
    + +

    This directory contains most of the source files of the LLVM system. In LLVM, +almost all code exists in libraries, making it very easy to share code among the +different tools.

    + +
    +
    llvm/lib/VMCore/
    This directory holds the core LLVM + source files that implement core classes like Instruction and BasicBlock. + +
    llvm/lib/AsmParser/
    This directory holds the source code + for the LLVM assembly language parser library. + +
    llvm/lib/ByteCode/
    This directory holds code for reading + and write LLVM bytecode. + +
    llvm/lib/CWriter/
    This directory implements the LLVM to C + converter. + +
    llvm/lib/Analysis/
    This directory contains a variety of + different program analyses, such as Dominator Information, Call Graphs, + Induction Variables, Interval Identification, Natural Loop Identification, + etc... + +
    llvm/lib/Transforms/
    This directory contains the source + code for the LLVM to LLVM program transformations, such as Aggressive Dead + Code Elimination, Sparse Conditional Constant Propagation, Inlining, Loop + Invariant Code Motion, Dead Global Elimination, and many others... + +
    llvm/lib/Target/
    This directory contains files that + describe various target architectures for code generation. For example, + the llvm/lib/Target/Sparc directory holds the Sparc machine + description.
    + +
    llvm/lib/CodeGen/
    This directory contains the major parts + of the code generator: Instruction Selector, Instruction Scheduling, and + Register Allocation. + +
    llvm/lib/Support/
    This directory contains the source code + that corresponds to the header files located in + llvm/include/Support/. +
    + +
    + + + + +
    + +

    This directory contains libraries which are compiled into LLVM bytecode and +used when linking programs with the GCC front end. Most of these libraries are +skeleton versions of real libraries; for example, libc is a stripped down +version of glibc.

    + +

    Unlike the rest of the LLVM suite, this directory needs the LLVM GCC front +end to compile.

    + +
    + + + + +
    + +

    This directory contains regression tests and source code that is used to test +the LLVM infrastructure.

    + +
    + + + + +
    + +

    The tools directory contains the executables built out of the +libraries above, which form the main part of the user interface. You can +always get help for a tool by typing tool_name --help. The +following is a brief introduction to the most important tools.

    + +
    +
    + +
    analyze
    analyze is used to run a specific + analysis on an input LLVM bytecode file and print out the results. It is + primarily useful for debugging analyses, or familiarizing yourself with + what an analysis does.

    + +

    bugpoint
    bugpoint is used to debug + optimization passes or code generation backends by narrowing down the + given test case to the minimum number of passes and/or instructions that + still cause a problem, whether it is a crash or miscompilation. See HowToSubmitABug.html for more information + on using bugpoint.

    + +

    llvm-ar
    The archiver produces an archive containing + the given LLVM bytecode files, optionally with an index for faster + lookup.

    + +

    llvm-as
    The assembler transforms the human readable + LLVM assembly to LLVM bytecode.

    + +

    llvm-dis
    The disassembler transforms the LLVM + bytecode to human readable LLVM assembly. Additionally, it can convert + LLVM bytecode to C, which is enabled with the -c option.

    + +

    llvm-link
    llvm-link, not surprisingly, + links multiple LLVM modules into a single program.

    + +

    lli
    lli is the LLVM interpreter, which + can directly execute LLVM bytecode (although very slowly...). In addition + to a simple interpreter, lli also has a tracing mode (entered by + specifying -trace on the command line). Finally, for + architectures that support it (currently only x86 and Sparc), by default, + lli will function as a Just-In-Time compiler (if the + functionality was compiled in), and will execute the code much + faster than the interpreter.

    + +

    llc
    llc is the LLVM backend compiler, + which translates LLVM bytecode to a SPARC or x86 assembly file.

    + +

    llvmgcc
    llvmgcc is a GCC-based C frontend + that has been retargeted to emit LLVM code as the machine code output. It + works just like any other GCC compiler, taking the typical -c, -S, -E, + -o options that are typically used. The source code for the + llvmgcc tool is currently not included in the LLVM CVS tree + because it is quite large and not very interesting.

    + +

      +
      gccas
      This tool is invoked by the + llvmgcc frontend as the "assembler" part of the compiler. This + tool actually assembles LLVM assembly to LLVM bytecode, + performs a variety of optimizations, and outputs LLVM bytecode. Thus + when you invoke llvmgcc -c x.c -o x.o, you are causing + gccas to be run, which writes the x.o file (which is + an LLVM bytecode file that can be disassembled or manipulated just like + any other bytecode file). The command line interface to gccas + is designed to be as close as possible to the system + `as' utility so that the gcc frontend itself did not have to be + modified to interface to a "weird" assembler.

      + +

      gccld
      gccld links together several LLVM + bytecode files into one bytecode file and does some optimization. It is + the linker invoked by the GCC frontend when multiple .o files need to be + linked together. Like gccas, the command line interface of + gccld is designed to match the system linker, to aid + interfacing with the GCC frontend.

      +

    + +
    opt
    opt reads LLVM bytecode, applies a + series of LLVM to LLVM transformations (which are specified on the command + line), and then outputs the resultant bytecode. The 'opt --help' + command is a good way to get a list of the program transformations + available in LLVM.

    + +

    + +
    + + + + +
    + +

    This directory contains utilities for working with LLVM source code, and some +of the utilities are actually required as part of the build process because they +are code generators for parts of LLVM infrastructure.

    + +
    + Burg/
    Burg is an instruction selector + generator -- it builds trees on which it then performs pattern-matching to + select instructions according to the patterns the user has specified. Burg + is currently used in the Sparc V9 backend.

    + +

    codegen-diff
    codegen-diff is a script + that finds differences between code that LLC generates and code that LLI + generates. This is a useful tool if you are debugging one of them, + assuming that the other generates correct output. For the full user + manual, run `perldoc codegen-diff'.

    + +

    cvsupdate
    cvsupdate is a script that will + update your CVS tree, but produce a much cleaner and more organized output + than simply running `cvs -z3 up -dP' will. For example, it will group + together all the new and updated files and modified files in separate + sections, so you can see at a glance what has changed. If you are at the + top of your LLVM CVS tree, running utils/cvsupdate is the + preferred way of updating the tree.

    + +

    emacs/
    The emacs directory contains + syntax-highlighting files which will work with Emacs and XEmacs editors, + providing syntax highlighting support for LLVM assembly files and TableGen + description files. For information on how to use the syntax files, consult + the README file in that directory.

    + +

    getsrcs.sh
    The getsrcs.sh script finds + and outputs all non-generated source files, which is useful if one wishes + to do a lot of development across directories and does not want to + individually find each file. One way to use it is to run, for example: + xemacs `utils/getsources.sh` from the top of your LLVM source + tree.

    + +

    makellvm
    The makellvm script compiles all + files in the current directory and then compiles and links the tool that + is the first argument. For example, assuming you are in the directory + llvm/lib/Target/Sparc, if makellvm is in your path, + simply running makellvm llc will make a build of the current + directory, switch to directory llvm/tools/llc and build it, + causing a re-linking of LLC.

    + +

    NightlyTest.pl and + NightlyTestTemplate.html
    These files are used in a + cron script to generate nightly status reports of the functionality of + tools, and the results can be seen by following the appropriate link on + the LLVM homepage.

    + +

    TableGen/
    The TableGen directory contains + the tool used to generate register descriptions, instruction set + descriptions, and even assemblers from common TableGen description + files.

    + +

    vim/
    The vim directory contains + syntax-highlighting files which will work with the VIM editor, providing + syntax highlighting support for LLVM assembly files and TableGen + description files. For information on how to use the syntax files, consult + the README file in that directory.

    + +

    + +
    + + + + - -

    -
    An Example Using the LLVM Tool Chain
    -

    -
    - +
    -
      -
    1. First, create a simple C file, name it 'hello.c': +
        +
      1. First, create a simple C file, name it 'hello.c':
            #include <stdio.h>
            int main() {
              printf("hello world\n");
              return 0;
            }
        -       
        +
      2. -
      3. Next, compile the C file into a LLVM bytecode file:

        +

      4. Next, compile the C file into a LLVM bytecode file:

        +

        % llvmgcc hello.c -o hello

        - % llvmgcc hello.c -o hello

        - - This will create two result files: hello and +

        This will create two result files: hello and hello.bc. The hello.bc is the LLVM bytecode that corresponds the the compiled program and the library facilities that it required. hello is a simple shell script that runs the bytecode - file with lli, making the result directly executable.

        + file with lli, making the result directly executable.

      5. -
      6. Run the program. To make sure the program ran, execute one of the - following commands:

        +

      7. Run the program. To make sure the program ran, execute one of the + following commands:

        - % ./hello

        +

        % ./hello

        - or

        +

        or

        - % lli hello.bc

        +

        % lli hello.bc

      8. -
      9. Use the llvm-dis utility to take a look at the LLVM assembly - code:

        +

      10. Use the llvm-dis utility to take a look at the LLVM assembly + code:

        - % llvm-dis < hello.bc | less

        +

        % llvm-dis < hello.bc | less

      11. -
      12. Compile the program to native Sparc assembly using the code - generator (assuming you are currently on a Sparc system):

        +

      13. Compile the program to native Sparc assembly using the code + generator (assuming you are currently on a Sparc system):

        - % llc hello.bc -o hello.s

        +

        % llc hello.bc -o hello.s

        -
      14. Assemble the native sparc assemble file into a program:

        +

      15. Assemble the native sparc assemble file into a program:

        - % /opt/SUNWspro/bin/cc -xarch=v9 hello.s -o hello.sparc

        +

        % /opt/SUNWspro/bin/cc -xarch=v9 hello.s -o hello.sparc

        -
      16. Execute the native sparc program:

        +

      17. Execute the native sparc program:

        - % ./hello.sparc

        +

        % ./hello.sparc

      18. -
      +
    +
    - -

    -
    Common Problems
    -

    -
    - + + + - If you are having problems building or using LLVM, or if you have any other - general questions about LLVM, please consult the - Frequently Asked Questions page. +
    - -

    Links

    -
    - +

    If you are having problems building or using LLVM, or if you have any other +general questions about LLVM, please consult the Frequently +Asked Questions page.

    -

    This document is just an introduction to how to use LLVM to do - some simple things... there are many more interesting and complicated things - that you can do that aren't documented here (but we'll gladly accept a patch - if you want to write something up!). For more information about LLVM, check - out:

    +
    - - -
    - - If you have any questions or run into any snags (or you have any - additions...), please send an email to - Chris Lattner.

    - The LLVM Compiler Infrastructure -
    + +
    + Links +
    + + +
    + +

    This document is just an introduction to how to use LLVM to do +some simple things... there are many more interesting and complicated things +that you can do that aren't documented here (but we'll gladly accept a patch +if you want to write something up!). For more information about LLVM, check +out:

    + + + +
    + + + +
    + - - -Last modified: Thu Nov 6 14:50:33 CST 2003 - - + From gaeke at cs.uiuc.edu Fri Nov 7 14:06:03 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Fri Nov 7 14:06:03 2003 Subject: [llvm-commits] CVS: llvm/lib/ExecutionEngine/Interpreter/Execution.cpp Interpreter.h Message-ID: <200311072004.OAA10605@gally.cs.uiuc.edu> Changes in directory llvm/lib/ExecutionEngine/Interpreter: Execution.cpp updated: 1.109 -> 1.110 Interpreter.h updated: 1.49 -> 1.50 --- Log message: visitCallInst --> visitCallSite. Use visitCallSite to implement both CallInsts and InvokeInsts. --- Diffs of the changes: (+7 -4) Index: llvm/lib/ExecutionEngine/Interpreter/Execution.cpp diff -u llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.109 llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.110 --- llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.109 Fri Nov 7 13:59:08 2003 +++ llvm/lib/ExecutionEngine/Interpreter/Execution.cpp Fri Nov 7 14:04:21 2003 @@ -637,9 +637,9 @@ // Miscellaneous Instruction Implementations //===----------------------------------------------------------------------===// -void Interpreter::visitCallInst(CallInst &I) { +void Interpreter::visitCallSite(CallSite CS) { ExecutionContext &SF = ECStack.back(); - SF.Caller = CallSite(&I); + SF.Caller = CS; std::vector ArgVals; const unsigned NumArgs = SF.Caller.arg_size(); ArgVals.reserve(NumArgs); Index: llvm/lib/ExecutionEngine/Interpreter/Interpreter.h diff -u llvm/lib/ExecutionEngine/Interpreter/Interpreter.h:1.49 llvm/lib/ExecutionEngine/Interpreter/Interpreter.h:1.50 --- llvm/lib/ExecutionEngine/Interpreter/Interpreter.h:1.49 Fri Nov 7 13:26:23 2003 +++ llvm/lib/ExecutionEngine/Interpreter/Interpreter.h Fri Nov 7 14:04:22 2003 @@ -119,10 +119,13 @@ void visitLoadInst(LoadInst &I); void visitStoreInst(StoreInst &I); void visitGetElementPtrInst(GetElementPtrInst &I); - void visitPHINode(PHINode &PN) { assert(0 && "PHI nodes already handled!"); } void visitCastInst(CastInst &I); - void visitCallInst(CallInst &I); + + void visitCallSite(CallSite CS); + void visitCallInst(CallInst &I) { visitCallSite (CallSite (&I)); } + void visitInvokeInst(InvokeInst &I) { visitCallSite (CallSite (&I)); } + void visitShl(ShiftInst &I); void visitShr(ShiftInst &I); void visitVANextInst(VANextInst &I); From gaeke at cs.uiuc.edu Fri Nov 7 14:06:14 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Fri Nov 7 14:06:14 2003 Subject: [llvm-commits] CVS: llvm/lib/ExecutionEngine/Interpreter/Execution.cpp Message-ID: <200311071959.NAA10266@gally.cs.uiuc.edu> Changes in directory llvm/lib/ExecutionEngine/Interpreter: Execution.cpp updated: 1.108 -> 1.109 --- Log message: Make the operation of visitCallInst() only depend on the CallSite. --- Diffs of the changes: (+9 -7) Index: llvm/lib/ExecutionEngine/Interpreter/Execution.cpp diff -u llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.108 llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.109 --- llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.108 Fri Nov 7 13:26:22 2003 +++ llvm/lib/ExecutionEngine/Interpreter/Execution.cpp Fri Nov 7 13:59:08 2003 @@ -641,15 +641,17 @@ ExecutionContext &SF = ECStack.back(); SF.Caller = CallSite(&I); std::vector ArgVals; - ArgVals.reserve(I.getNumOperands()-1); - for (unsigned i = 1; i < I.getNumOperands(); ++i) { - ArgVals.push_back(getOperandValue(I.getOperand(i), SF)); + const unsigned NumArgs = SF.Caller.arg_size(); + ArgVals.reserve(NumArgs); + for (CallSite::arg_iterator i = SF.Caller.arg_begin(), + e = SF.Caller.arg_end(); i != e; ++i) { + Value *V = *i; + ArgVals.push_back(getOperandValue(V, SF)); // Promote all integral types whose size is < sizeof(int) into ints. We do // this by zero or sign extending the value as appropriate according to the // source type. - if (I.getOperand(i)->getType()->isIntegral() && - I.getOperand(i)->getType()->getPrimitiveSize() < 4) { - const Type *Ty = I.getOperand(i)->getType(); + const Type *Ty = V->getType(); + if (Ty->isIntegral() && Ty->getPrimitiveSize() < 4) { if (Ty == Type::ShortTy) ArgVals.back().IntVal = ArgVals.back().ShortVal; else if (Ty == Type::UShortTy) @@ -667,7 +669,7 @@ // To handle indirect calls, we must get the pointer value from the argument // and treat it as a function pointer. - GenericValue SRC = getOperandValue(I.getCalledValue(), SF); + GenericValue SRC = getOperandValue(SF.Caller.getCalledValue(), SF); callFunction((Function*)GVTOP(SRC), ArgVals); } From gaeke at cs.uiuc.edu Fri Nov 7 14:08:05 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Fri Nov 7 14:08:05 2003 Subject: [llvm-commits] CVS: llvm/lib/ExecutionEngine/Interpreter/Execution.cpp Interpreter.h Message-ID: <200311072007.OAA10816@gally.cs.uiuc.edu> Changes in directory llvm/lib/ExecutionEngine/Interpreter: Execution.cpp updated: 1.110 -> 1.111 Interpreter.h updated: 1.50 -> 1.51 --- Log message: Add stub version of unwind support --- Diffs of the changes: (+5 -0) Index: llvm/lib/ExecutionEngine/Interpreter/Execution.cpp diff -u llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.110 llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.111 --- llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.110 Fri Nov 7 14:04:21 2003 +++ llvm/lib/ExecutionEngine/Interpreter/Execution.cpp Fri Nov 7 14:07:05 2003 @@ -475,6 +475,10 @@ popStackAndReturnValueToCaller(RetTy, Result); } +void Interpreter::visitUnwindInst(UnwindInst &I) { + abort (); +} + void Interpreter::visitBranchInst(BranchInst &I) { ExecutionContext &SF = ECStack.back(); BasicBlock *Dest; Index: llvm/lib/ExecutionEngine/Interpreter/Interpreter.h diff -u llvm/lib/ExecutionEngine/Interpreter/Interpreter.h:1.50 llvm/lib/ExecutionEngine/Interpreter/Interpreter.h:1.51 --- llvm/lib/ExecutionEngine/Interpreter/Interpreter.h:1.50 Fri Nov 7 14:04:22 2003 +++ llvm/lib/ExecutionEngine/Interpreter/Interpreter.h Fri Nov 7 14:07:06 2003 @@ -125,6 +125,7 @@ void visitCallSite(CallSite CS); void visitCallInst(CallInst &I) { visitCallSite (CallSite (&I)); } void visitInvokeInst(InvokeInst &I) { visitCallSite (CallSite (&I)); } + void visitUnwindInst(UnwindInst &I); void visitShl(ShiftInst &I); void visitShr(ShiftInst &I); From brukman at cs.uiuc.edu Fri Nov 7 14:33:03 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Nov 7 14:33:03 2003 Subject: [llvm-commits] CVS: llvm/lib/ExecutionEngine/JIT/JIT.cpp Message-ID: <200311072032.OAA10696@zion.cs.uiuc.edu> Changes in directory llvm/lib/ExecutionEngine/JIT: JIT.cpp updated: 1.22 -> 1.23 --- Log message: Remove the *BIG UGLY HACK* from the JIT: PreSelection is now a FunctionPass. --- Diffs of the changes: (+0 -15) Index: llvm/lib/ExecutionEngine/JIT/JIT.cpp diff -u llvm/lib/ExecutionEngine/JIT/JIT.cpp:1.22 llvm/lib/ExecutionEngine/JIT/JIT.cpp:1.23 --- llvm/lib/ExecutionEngine/JIT/JIT.cpp:1.22 Tue Oct 28 22:24:09 2003 +++ llvm/lib/ExecutionEngine/JIT/JIT.cpp Fri Nov 7 14:32:08 2003 @@ -97,21 +97,6 @@ setupPassManager(); -#ifdef ENABLE_SPARC_JIT - // THIS GOES BEYOND UGLY HACKS - if (TM.getName() == "UltraSparc-Native") { - extern Pass *createPreSelectionPass(TargetMachine &TM); - PassManager PM; - // Specialize LLVM code for this target machine and then - // run basic dataflow optimizations on LLVM code. - PM.add(createPreSelectionPass(TM)); - // We cannot utilize function-at-a-time loading here because PreSelection - // is a ModulePass. - MP->materializeModule(); - PM.run(*MP->getModule()); - } -#endif - emitGlobals(); } From brukman at cs.uiuc.edu Fri Nov 7 14:34:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Nov 7 14:34:01 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/Sparc.cpp Message-ID: <200311072033.OAA10738@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: Sparc.cpp updated: 1.87 -> 1.88 --- Log message: PreSelection is not optional, it performs a necessary and vital transformation for the Sparc backend: breaking up constant expressions. Thus, we cannot have it guarded by a conditional, it should never be disabled. Also, it's now available for the JIT since it is a FunctionPass. --- Diffs of the changes: (+15 -12) Index: llvm/lib/Target/Sparc/Sparc.cpp diff -u llvm/lib/Target/Sparc/Sparc.cpp:1.87 llvm/lib/Target/Sparc/Sparc.cpp:1.88 --- llvm/lib/Target/Sparc/Sparc.cpp:1.87 Mon Oct 20 15:44:03 2003 +++ llvm/lib/Target/Sparc/Sparc.cpp Fri Nov 7 14:33:25 2003 @@ -42,9 +42,6 @@ // Command line options to control choice of code generation passes. //--------------------------------------------------------------------------- -static cl::opt DisablePreOpt("disable-preopt", - cl::desc("Disable optimizations prior to instruction selection")); - static cl::opt DisableSched("disable-sched", cl::desc("Disable local scheduling pass")); @@ -178,15 +175,13 @@ //so %fp+offset-8 and %fp+offset-16 are empty slots now! PM.add(createStackSlotsPass(*this)); - if (!DisablePreOpt) { - // Specialize LLVM code for this target machine - PM.add(createPreSelectionPass(*this)); - // Run basic dataflow optimizations on LLVM code - PM.add(createReassociatePass()); - PM.add(createLICMPass()); - PM.add(createGCSEPass()); - } - + // Specialize LLVM code for this target machine + PM.add(createPreSelectionPass(*this)); + // Run basic dataflow optimizations on LLVM code + PM.add(createReassociatePass()); + PM.add(createLICMPass()); + PM.add(createGCSEPass()); + // If LLVM dumping after transformations is requested, add it to the pipeline if (DumpInput) PM.add(new PrintFunctionPass("Input code to instr. selection:\n", @@ -251,6 +246,14 @@ // Construct and initialize the MachineFunction object for this fn. PM.add(createMachineCodeConstructionPass(*this)); + + // Specialize LLVM code for this target machine and then + // run basic dataflow optimizations on LLVM code. + PM.add(createPreSelectionPass(*this)); + // Run basic dataflow optimizations on LLVM code + PM.add(createReassociatePass()); + PM.add(createLICMPass()); + PM.add(createGCSEPass()); PM.add(createInstructionSelectionPass(*this)); From gaeke at cs.uiuc.edu Fri Nov 7 14:46:02 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Fri Nov 7 14:46:02 2003 Subject: [llvm-commits] CVS: llvm/lib/ExecutionEngine/Interpreter/Execution.cpp Message-ID: <200311072045.OAA13099@gally.cs.uiuc.edu> Changes in directory llvm/lib/ExecutionEngine/Interpreter: Execution.cpp updated: 1.111 -> 1.112 --- Log message: popStackAndReturnValueToCaller() must advance instruction pointer to normal destination, if returning from an invoke. Implement 'unwind' instruction. --- Diffs of the changes: (+24 -5) Index: llvm/lib/ExecutionEngine/Interpreter/Execution.cpp diff -u llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.111 llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.112 --- llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.111 Fri Nov 7 14:07:05 2003 +++ llvm/lib/ExecutionEngine/Interpreter/Execution.cpp Fri Nov 7 14:44:58 2003 @@ -435,8 +435,10 @@ /// Pop the last stack frame off of ECStack and then copy the result /// back into the result variable if we are not returning void. The /// result variable may be the ExitCode, or the Value of the calling -/// CallInst if there was a previous stack frame. This procedure may -/// invalidate any ECStack iterators you have. +/// CallInst if there was a previous stack frame. This method may +/// invalidate any ECStack iterators you have. This method also takes +/// care of switching to the normal destination BB, if we are returning +/// from an invoke. /// void Interpreter::popStackAndReturnValueToCaller (const Type *RetTy, GenericValue Result) { @@ -453,9 +455,11 @@ // If we have a previous stack frame, and we have a previous call, // fill in the return value... ExecutionContext &CallingSF = ECStack.back(); - if (CallingSF.Caller.getInstruction()) { + if (Instruction *I = CallingSF.Caller.getInstruction()) { if (CallingSF.Caller.getType() != Type::VoidTy) // Save result... - SetValue(CallingSF.Caller.getInstruction(), Result, CallingSF); + SetValue(I, Result, CallingSF); + if (InvokeInst *II = dyn_cast (I)) + SwitchToNewBasicBlock (II->getNormalDest (), CallingSF); CallingSF.Caller = CallSite(); // We returned from the call... } } @@ -476,7 +480,22 @@ } void Interpreter::visitUnwindInst(UnwindInst &I) { - abort (); + // Unwind stack + Instruction *Inst; + do { + ECStack.pop_back (); + if (ECStack.empty ()) + abort (); + Inst = ECStack.back ().Caller.getInstruction (); + } while (!(Inst && isa (Inst))); + + // Return from invoke + ExecutionContext &InvokingSF = ECStack.back (); + InvokingSF.Caller = CallSite (); + + // Go to exceptional destination BB of invoke instruction + SwitchToNewBasicBlock (cast (Inst)->getExceptionalDest (), + InvokingSF); } void Interpreter::visitBranchInst(BranchInst &I) { From brukman at cs.uiuc.edu Fri Nov 7 15:08:02 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Nov 7 15:08:02 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp Message-ID: <200311072107.PAA16519@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: SparcV9CodeEmitter.cpp updated: 1.40 -> 1.41 --- Log message: Implement branching to a PC-relative constant (not a BasicBlock). --- Diffs of the changes: (+7 -7) Index: llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp diff -u llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp:1.40 llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp:1.41 --- llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp:1.40 Fri Nov 7 12:06:26 2003 +++ llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp Fri Nov 7 15:07:30 2003 @@ -593,8 +593,13 @@ unsigned* CurrPC = (unsigned*)(intptr_t)MCE.getCurrentPCValue(); BBRefs.push_back(std::make_pair(BB, std::make_pair(CurrPC, &MI))); } else if (const Constant *C = dyn_cast(V)) { - std::cerr << "ERROR: constants should not appear in PcRel:" << MO << "\n"; - abort(); + if (const ConstantInt *CI = dyn_cast(C)) { + rv = CI->getRawValue() - MCE.getCurrentPCValue(); + } else { + std::cerr << "Cannot have non-integral const in instruction: " + << *C; + abort(); + } } else if (GlobalValue *GV = dyn_cast(V)) { // same as MO.isGlobalAddress() DEBUG(std::cerr << "GlobalValue: "); @@ -797,11 +802,6 @@ // Delayed resolution... return (void*)(intptr_t)TheJITResolver->getLazyResolver(cast(V)); - - } else if (Constant *C = ConstantPointerRef::get(V)) { - // no longer applicable - std::cerr << "Unhandled Constant: " << *C << "\n"; - abort(); } else { std::cerr << "Unhandled global: " << *V << "\n"; abort(); From gaeke at cs.uiuc.edu Fri Nov 7 15:21:01 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Fri Nov 7 15:21:01 2003 Subject: [llvm-commits] CVS: llvm/lib/ExecutionEngine/Interpreter/Execution.cpp Interpreter.h Message-ID: <200311072120.PAA15302@gally.cs.uiuc.edu> Changes in directory llvm/lib/ExecutionEngine/Interpreter: Execution.cpp updated: 1.112 -> 1.113 Interpreter.h updated: 1.51 -> 1.52 --- Log message: Implement vaarg instruction. This is not quite perfect: 2003-08-11-VaListArg still causes a crash. But it's better than before. --- Diffs of the changes: (+36 -0) Index: llvm/lib/ExecutionEngine/Interpreter/Execution.cpp diff -u llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.112 llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.113 --- llvm/lib/ExecutionEngine/Interpreter/Execution.cpp:1.112 Fri Nov 7 14:44:58 2003 +++ llvm/lib/ExecutionEngine/Interpreter/Execution.cpp Fri Nov 7 15:20:46 2003 @@ -820,6 +820,41 @@ SetValue(&I, VAList, SF); } +#define IMPLEMENT_VAARG(TY) \ + case Type::TY##TyID: Dest.TY##Val = Src.TY##Val; break + +void Interpreter::visitVAArgInst(VAArgInst &I) { + ExecutionContext &SF = ECStack.back(); + + // Get the incoming valist element. LLI treats the valist as an integer. + GenericValue VAList = getOperandValue(I.getOperand(0), SF); + unsigned Argument = VAList.IntVal; + assert(Argument < SF.VarArgs.size() && + "Accessing past the last vararg argument!"); + GenericValue Dest, Src = SF.VarArgs[Argument]; + const Type *Ty = I.getType(); + switch (Ty->getPrimitiveID()) { + IMPLEMENT_VAARG(UByte); + IMPLEMENT_VAARG(SByte); + IMPLEMENT_VAARG(UShort); + IMPLEMENT_VAARG(Short); + IMPLEMENT_VAARG(UInt); + IMPLEMENT_VAARG(Int); + IMPLEMENT_VAARG(ULong); + IMPLEMENT_VAARG(Long); + IMPLEMENT_VAARG(Pointer); + IMPLEMENT_VAARG(Float); + IMPLEMENT_VAARG(Double); + IMPLEMENT_VAARG(Bool); + default: + std::cout << "Unhandled dest type for vaarg instruction: " << *Ty << "\n"; + abort(); + } + + // Set the Value of this Instruction. + SetValue(&I, Dest, SF); +} + //===----------------------------------------------------------------------===// // Dispatch and Execution Code //===----------------------------------------------------------------------===// Index: llvm/lib/ExecutionEngine/Interpreter/Interpreter.h diff -u llvm/lib/ExecutionEngine/Interpreter/Interpreter.h:1.51 llvm/lib/ExecutionEngine/Interpreter/Interpreter.h:1.52 --- llvm/lib/ExecutionEngine/Interpreter/Interpreter.h:1.51 Fri Nov 7 14:07:06 2003 +++ llvm/lib/ExecutionEngine/Interpreter/Interpreter.h Fri Nov 7 15:20:47 2003 @@ -130,6 +130,7 @@ void visitShl(ShiftInst &I); void visitShr(ShiftInst &I); void visitVANextInst(VANextInst &I); + void visitVAArgInst(VAArgInst &I); void visitInstruction(Instruction &I) { std::cerr << I; assert(0 && "Instruction not interpretable yet!"); From gaeke at cs.uiuc.edu Fri Nov 7 16:03:01 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Fri Nov 7 16:03:01 2003 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp Message-ID: <200311072202.QAA14920@seraph.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: UnpackTraceFunction.cpp updated: 1.15 -> 1.16 --- Log message: I finished addGetPointerToStackValInstrs and then realized it may not be needed after all. insertCopyMachineInstrs is looking better too, now that it doesn't need addGetPointerToStackValInstrs. But it does need to know the type of values. --- Diffs of the changes: (+34 -25) Index: reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp diff -u reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.15 reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.16 --- reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.15 Thu Nov 6 13:51:06 2003 +++ reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp Fri Nov 7 16:02:12 2003 @@ -19,27 +19,43 @@ #include "reopt/MappingInfo.h" #include "Support/Debug.h" +#if 0 +/// Append to MVEC the appropriate machine instruction(s) to get a pointer to +/// the stack-spilled object whose location is described by Source into +/// register number PointerReg. The frame pointer is in register number +/// FramePtrReg. Note that the current implementation is SPARC-specific. +/// void addGetPointerToStackValInstrs (std::vector &mvec, - AllocInfo &Source, unsigned SrcReg, - unsigned FramePtrReg) { - // Let OFFSET be the offset of the value from %fp - mvec.push_back (BuildMI (V9::ADDi, 3).addReg (FramePtrReg)); // FIXME - // construct add %fp, , + AllocInfo &Source, unsigned PointerReg, + const unsigned FramePtrReg) { + // Only works with objects spilled to the stack. + assert (Source.AllocState == AllocInfo::Spilled); + // Let Offset be the offset of the value from %fp. + int Offset = Source.Placement - 2047; + // Construct add %fp, , + mvec.push_back (BuildMI (V9::ADDi, 3).addReg (FramePtrReg) + .addSImm (Offset).addReg (PointerReg, MOTy::Def)); } +#endif -/// Insert (a) machine instruction(s) that copies the value in Source -/// to the location specified by Target, at the beginning of B. Note +/// Insert the appropriate machine instruction(s) that copies the value in +/// Source to the location specified by Target, at the beginning of B. Note /// that the current implementation is SPARC-specific. /// -/// FIXME: Not yet finished. -/// void insertCopyMachineInstrs (AllocInfo &Source, AllocInfo &Target, - MachineBasicBlock &B) { + MachineBasicBlock &B, const Type *Ty) { UltraSparc TM; const TargetRegInfo &TRI = TM.getRegInfo (); std::vector mvec; unsigned SrcReg = 31337, TargReg = 31337; - int Offset = -1, RegType = -1; // FIXME: How do we set these correctly? + int RegType; + // Guess what kind of reg the register was allocated to. + if (Ty == Type::FloatTy) + RegType = UltraSparcRegInfo::FPSingleRegType; + else if (Ty == Type::DoubleTy) + RegType = UltraSparcRegInfo::FPDoubleRegType; + else + RegType = UltraSparcRegInfo::IntRegType; if (Source.AllocState == AllocInfo::Allocated) SrcReg = Source.Placement; if (Target.AllocState == AllocInfo::Allocated) @@ -48,30 +64,23 @@ const unsigned StackPtrReg = TRI.getStackPointer (); if (Source.AllocState == AllocInfo::Spilled && Target.AllocState == AllocInfo::Allocated) { - // Emit instructions to construct pointer to Source into SrcReg - addGetPointerToStackValInstrs (mvec, Source, SrcReg, FramePtrReg); // Emit load instruction from stack loc. Source into register Target - TRI.cpMem2RegMI (mvec, SrcReg, Offset, TargReg, RegType); + TRI.cpMem2RegMI (mvec, FramePtrReg, Source.Placement, TargReg, RegType); } else if (Source.AllocState == AllocInfo::Allocated && Target.AllocState == AllocInfo::Allocated) { // Emit move instruction from register Source to register Target TRI.cpReg2RegMI (mvec, Source.Placement, Target.Placement, RegType); } else if (Source.AllocState == AllocInfo::Allocated && Target.AllocState == AllocInfo::Spilled) { - // Emit instructions to construct pointer to Target into TargReg - addGetPointerToStackValInstrs (mvec, Target, TargReg, FramePtrReg); // Emit store instruction from register Source to stack loc. Target - TRI.cpReg2MemMI (mvec, Source.Placement, TargReg, Offset, RegType); + TRI.cpReg2MemMI (mvec, Source.Placement, FramePtrReg, Target.Placement, + RegType); } else if (Source.AllocState == AllocInfo::Spilled && Target.AllocState == AllocInfo::Spilled) { - // Emit instructions to construct pointer to Source into SrcReg - addGetPointerToStackValInstrs (mvec, Source, SrcReg, FramePtrReg); // Emit load instruction from address in SrcReg into register SrcReg - TRI.cpMem2RegMI (mvec, SrcReg, Offset, SrcReg, RegType); - // Emit instructions to construct pointer to Target into TargReg - addGetPointerToStackValInstrs (mvec, Target, TargReg, FramePtrReg); + TRI.cpMem2RegMI (mvec, FramePtrReg, Source.Placement, SrcReg, RegType); // Emit store instruction from register SrcReg to stack loc. Target - TRI.cpReg2MemMI (mvec, SrcReg, TargReg, Offset, RegType); + TRI.cpReg2MemMI (mvec, SrcReg, FramePtrReg, Target.Placement, RegType); } // Add whatever the TargetRegInfo gave us to the MachineBasicBlock we were // provided. @@ -303,7 +312,7 @@ AllocInfo Source = getValueAllocStateFromModule (MatrixF, V); AllocInfo Target = getValueAllocStateFromGlobal (TraceF, V); if (Source != Target) - insertCopyMachineInstrs (Source, Target, E); + insertCopyMachineInstrs (Source, Target, E, V->getType ()); } // Modify EXIT MachineBasicBlocks of MF @@ -334,7 +343,7 @@ AllocInfo Source = getValueAllocStateFromGlobal (TraceF, V); AllocInfo Target = getValueAllocStateFromModule (MatrixF, V); if (Source != Target) - insertCopyMachineInstrs (Source, Target, MBB); + insertCopyMachineInstrs (Source, Target, MBB, V->getType ()); } // Insert a branch back to the return BasicBlock of the matrix fn. insertBranchMachineInstrs (ReturnAddress, MBB); From gaeke at cs.uiuc.edu Fri Nov 7 16:04:02 2003 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Fri Nov 7 16:04:02 2003 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp Message-ID: <200311072203.QAA14946@seraph.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: UnpackTraceFunction.cpp updated: 1.16 -> 1.17 --- Log message: Don't think we'll need addGetPointerToStackValInstrs() for now. --- Diffs of the changes: (+0 -19) Index: reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp diff -u reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.16 reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.17 --- reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.16 Fri Nov 7 16:02:12 2003 +++ reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp Fri Nov 7 16:03:26 2003 @@ -19,25 +19,6 @@ #include "reopt/MappingInfo.h" #include "Support/Debug.h" -#if 0 -/// Append to MVEC the appropriate machine instruction(s) to get a pointer to -/// the stack-spilled object whose location is described by Source into -/// register number PointerReg. The frame pointer is in register number -/// FramePtrReg. Note that the current implementation is SPARC-specific. -/// -void addGetPointerToStackValInstrs (std::vector &mvec, - AllocInfo &Source, unsigned PointerReg, - const unsigned FramePtrReg) { - // Only works with objects spilled to the stack. - assert (Source.AllocState == AllocInfo::Spilled); - // Let Offset be the offset of the value from %fp. - int Offset = Source.Placement - 2047; - // Construct add %fp, , - mvec.push_back (BuildMI (V9::ADDi, 3).addReg (FramePtrReg) - .addSImm (Offset).addReg (PointerReg, MOTy::Def)); -} -#endif - /// Insert the appropriate machine instruction(s) that copies the value in /// Source to the location specified by Target, at the beginning of B. Note /// that the current implementation is SPARC-specific. From lattner at cs.uiuc.edu Fri Nov 7 16:21:02 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Nov 7 16:21:02 2003 Subject: [llvm-commits] CVS: llvm-www/releases/1.0/docs/ReleaseNotes.html Message-ID: <200311072220.QAA25299@zion.cs.uiuc.edu> Changes in directory llvm-www/releases/1.0/docs: ReleaseNotes.html updated: 1.22 -> 1.23 --- Log message: Bugz --- Diffs of the changes: (+7 -2) Index: llvm-www/releases/1.0/docs/ReleaseNotes.html diff -u llvm-www/releases/1.0/docs/ReleaseNotes.html:1.22 llvm-www/releases/1.0/docs/ReleaseNotes.html:1.23 --- llvm-www/releases/1.0/docs/ReleaseNotes.html:1.22 Thu Nov 6 22:47:20 2003 +++ llvm-www/releases/1.0/docs/ReleaseNotes.html Fri Nov 7 16:20:17 2003 @@ -163,6 +163,10 @@
  • LLVM cannot handle structures with more than 256 elements.

    +

  • Interpreter does not support the +vaarg instruction
  • + + Bugs in 1.0 fixed in 1.1:


    Known problems with the C front-end

      @@ -477,6 +482,6 @@ Maintained By: The LLVM Team
      -Last modified: Thu Nov 6 13:21:50 CST 2003 +Last modified: Fri Nov 7 16:19:42 CST 2003 From lattner at cs.uiuc.edu Fri Nov 7 17:22:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Nov 7 17:22:01 2003 Subject: [llvm-commits] CVS: llvm/include/Support/MallocAllocator.h Message-ID: <200311072321.RAA31960@zion.cs.uiuc.edu> Changes in directory llvm/include/Support: MallocAllocator.h updated: 1.2 -> 1.3 --- Log message: Provide a specialization of _Alloc_traits, which allows the G++ runtime to avoid storing an instance of the allocator in each data structure it uses. Yaay. --- Diffs of the changes: (+13 -2) Index: llvm/include/Support/MallocAllocator.h diff -u llvm/include/Support/MallocAllocator.h:1.2 llvm/include/Support/MallocAllocator.h:1.3 --- llvm/include/Support/MallocAllocator.h:1.2 Fri Nov 7 09:20:06 2003 +++ llvm/include/Support/MallocAllocator.h Fri Nov 7 17:20:56 2003 @@ -44,11 +44,11 @@ const_pointer address(const_reference x) const { return &x; } size_type max_size() const { return ~0 / sizeof(T); } - pointer allocate(size_t n, void* hint = 0) { + static pointer allocate(size_t n, void* hint = 0) { return (pointer)malloc(n*sizeof(T)); } - void deallocate(pointer p, size_t n) { + static void deallocate(pointer p, size_t n) { free((void*)p); } @@ -68,5 +68,16 @@ inline bool operator!=(const MallocAllocator&, const MallocAllocator&) { return false; } + +namespace std { + template + struct _Alloc_traits > { + static const bool _S_instanceless = true; + typedef ::MallocAllocator base_alloc_type; + typedef ::MallocAllocator _Alloc_type; + typedef ::MallocAllocator allocator_type; + }; +} + #endif From lattner at cs.uiuc.edu Fri Nov 7 17:57:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Nov 7 17:57:01 2003 Subject: [llvm-commits] CVS: poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp Message-ID: <200311072356.RAA00646@zion.cs.uiuc.edu> Changes in directory poolalloc/runtime/PoolAllocator: PoolAllocatorChained.cpp updated: 1.24 -> 1.25 --- Log message: Don't segfault freeing the last slab :( --- Diffs of the changes: (+1 -1) Index: poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp diff -u poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp:1.24 poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp:1.25 --- poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp:1.24 Fri Nov 7 12:09:00 2003 +++ poolalloc/runtime/PoolAllocator/PoolAllocatorChained.cpp Fri Nov 7 17:55:35 2003 @@ -645,7 +645,7 @@ // If we can free this pool, check to see if there are any empty slabs at // the start of this list. If so, delete the FirstSlab! PoolSlab *FirstSlab = (PoolSlab*)Pool->Ptr1; - if (Pool->FreeablePool && FirstSlab->isEmpty()) { + if (Pool->FreeablePool && FirstSlab && FirstSlab->isEmpty()) { // Here we choose to delete FirstSlab instead of the pool we just freed // from because the pool we just freed from is more likely to be in the // processor cache. From lattner at cs.uiuc.edu Fri Nov 7 17:57:09 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Nov 7 17:57:09 2003 Subject: [llvm-commits] CVS: poolalloc/runtime/PoolAllocator/PageManager.cpp Message-ID: <200311072356.RAA00460@zion.cs.uiuc.edu> Changes in directory poolalloc/runtime/PoolAllocator: PageManager.cpp updated: 1.2 -> 1.3 --- Log message: Do not use operator new to allocate the vector. This adds a pointless dependency on libstdc++ --- Diffs of the changes: (+8 -2) Index: poolalloc/runtime/PoolAllocator/PageManager.cpp diff -u poolalloc/runtime/PoolAllocator/PageManager.cpp:1.2 poolalloc/runtime/PoolAllocator/PageManager.cpp:1.3 --- poolalloc/runtime/PoolAllocator/PageManager.cpp:1.2 Fri Nov 7 11:21:24 2003 +++ poolalloc/runtime/PoolAllocator/PageManager.cpp Fri Nov 7 17:56:01 2003 @@ -25,7 +25,8 @@ // Explicitly use the malloc allocator here, to avoid depending on the C++ // runtime library. -static std::vector > *FreePages = 0; +typedef std::vector > FreePagesListType; +static FreePagesListType *FreePages = 0; void InitializePageManager() { if (!PageSize) PageSize = sysconf(_SC_PAGESIZE); @@ -70,7 +71,12 @@ unsigned NumToAllocate = 10; char *Ptr = (char*)GetPages(NumToAllocate); - if (!FreePages) FreePages = new std::vector >(); + if (!FreePages) { + // Avoid using operator new! + FreePages = (FreePagesListType*)malloc(sizeof(FreePagesListType)); + // Use placement new now. + new (FreePages) std::vector >(); + } for (unsigned i = 1; i != NumToAllocate; ++i) FreePages->push_back(Ptr+i*PageSize); return Ptr; From brukman at cs.uiuc.edu Fri Nov 7 18:02:00 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Nov 7 18:02:00 2003 Subject: [llvm-commits] CVS: llvm/lib/Target/Sparc/Sparc.cpp Message-ID: <200311080001.SAA00771@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Sparc: Sparc.cpp updated: 1.88 -> 1.89 --- Log message: For some reason, LICM and GCSE like to crash the FunctionPassManager when they are being added as FunctionPasses... Sigh. --- Diffs of the changes: (+4 -2) Index: llvm/lib/Target/Sparc/Sparc.cpp diff -u llvm/lib/Target/Sparc/Sparc.cpp:1.88 llvm/lib/Target/Sparc/Sparc.cpp:1.89 --- llvm/lib/Target/Sparc/Sparc.cpp:1.88 Fri Nov 7 14:33:25 2003 +++ llvm/lib/Target/Sparc/Sparc.cpp Fri Nov 7 18:01:39 2003 @@ -252,8 +252,10 @@ PM.add(createPreSelectionPass(*this)); // Run basic dataflow optimizations on LLVM code PM.add(createReassociatePass()); - PM.add(createLICMPass()); - PM.add(createGCSEPass()); + + // FIXME: these passes crash the FunctionPassManager when being added... + //PM.add(createLICMPass()); + //PM.add(createGCSEPass()); PM.add(createInstructionSelectionPass(*this)); From alkis at cs.uiuc.edu Fri Nov 7 18:24:02 2003 From: alkis at cs.uiuc.edu (Alkis Evlogimenos) Date: Fri Nov 7 18:24:02 2003 Subject: [llvm-commits] [regalloc_linearscan] CVS: llvm/lib/CodeGen/RegAllocLinearScan.cpp LiveIntervals.cpp Message-ID: <200311080023.SAA05368@morpheus.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: RegAllocLinearScan.cpp updated: 1.1.2.9 -> 1.1.2.10 LiveIntervals.cpp updated: 1.1.2.7 -> 1.1.2.8 --- Log message: LiveIntervals: - be a little stricter in terms of constness - make runOnMachineFunction reentrant - make debugging output prettier - fix wrong interval computation of variables that get killed in their defining basic block RegAlloc: - disable inactive interval processing, handle the simple case for now (ignore holes) - improve debugging output - succeed in register allocating a simple hello world llvm assembly file --- Diffs of the changes: (+214 -96) Index: llvm/lib/CodeGen/RegAllocLinearScan.cpp diff -u llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.1.2.9 llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.1.2.10 --- llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.1.2.9 Thu Nov 6 03:59:26 2003 +++ llvm/lib/CodeGen/RegAllocLinearScan.cpp Fri Nov 7 18:23:03 2003 @@ -35,7 +35,7 @@ class RA : public MachineFunctionPass { public: - typedef std::vector IntervalPtrs; + typedef std::vector IntervalPtrs; private: MachineFunction* mf_; @@ -45,8 +45,8 @@ MachineBasicBlock::iterator currentInstr_; typedef LiveIntervals::Intervals Intervals; - Intervals* li_; - + const Intervals* li_; + Intervals::const_iterator currentInterval_; IntervalPtrs active_, inactive_; typedef LiveIntervals::MiIndex2MbbMap MiIndex2MbbMap; @@ -55,6 +55,9 @@ typedef LiveIntervals::Mbb2MiIndexMap Mbb2MiIndexMap; Mbb2MiIndexMap* mbb2miiMap_; + typedef LiveIntervals::MachineBasicBlockPtrs MachineBasicBlockPtrs; + MachineBasicBlockPtrs mbbs_; + typedef std::map Instr2IndexMap; Instr2IndexMap i2iMap_; @@ -83,18 +86,22 @@ /// runOnMachineFunction - register allocate the whole function bool runOnMachineFunction(MachineFunction&); + /// processInterval - entry to the linear scan register + /// allocator. this happens one every instruction we look at + void processInterval(unsigned curIndex); + /// processActiveIntervals - expire old intervals and move /// non-overlapping ones to the incative list - void processActiveIntervals(Intervals::iterator cur); + void processActiveIntervals(unsigned curIndex); /// expireOldInterval - expire old intervals and move /// overlapping ones to the active list - void processInactiveIntervals(Intervals::iterator cur); + void processInactiveIntervals(unsigned curIndex); - /// spillAtInterval - choose and spill at the specified + /// spill - choose and spill at the current /// interval. Currently we spill the interval with the last /// end point in the active and inactive lists - void spillAtInterval(Intervals::iterator cur); + void spill(); /// getFreeReg - return a free register for this virtual /// register if we have one, otherwise return 0 @@ -129,23 +136,29 @@ /// the virtual register specifed void loadPhysReg(unsigned physReg, unsigned virtReg); - /// getMbbMbbIteratorPair - returns a pair of the - /// MachineBasicBlock this instruction is on and the iterator - /// pointing to the instruction - std::pair - getMbbMbbIteratorPair(unsigned miIndex) const; - }; -} - -namespace { - void printIntervals(const char* const str, - RA::IntervalPtrs::const_iterator i, - RA::IntervalPtrs::const_iterator e) { - if (str) std::cerr << str << " intervals:\n"; - for (; i != e; ++i) { - std::cerr << "\t\t" << **i << '\n'; + /// getInstructionIndex() - returns the instruction index as + /// it was computed by the live interval analysis (adjusts for + /// inserted instructions. + unsigned getInstructionIndex() const; + + void printVirt2PhysMap() const { + std::cerr << "\tallocated registers: "; + for (Virt2PhysMap::const_iterator + i = v2pMap_.begin(), e = v2pMap_.end(); i != e; ++i) { + std::cerr << '[' << i->first << ',' + << mri_->getName(i->second) << "] "; + } + std::cerr << '\n'; + } + void printIntervals(const char* const str, + RA::IntervalPtrs::const_iterator i, + RA::IntervalPtrs::const_iterator e) const { + if (str) std::cerr << str << " intervals:\n"; + for (; i != e; ++i) { + std::cerr << "\t\t" << **i << '\n'; + } } - } + }; } bool RA::runOnMachineFunction(MachineFunction &fn) { @@ -153,83 +166,165 @@ tm_ = &fn.getTarget(); mri_ = tm_->getRegisterInfo(); li_ = &getAnalysis().getIntervals(); + currentInterval_ = li_->begin(); active_.clear(); inactive_.clear(); mii2mbbMap_ = &getAnalysis().getMiIndex2MbbMap(); mbb2miiMap_ = &getAnalysis().getMbb2MiIndexMap(); + mbbs_ = getAnalysis().getOrderedMachineBasicBlockPtrs(); p2vMap_.resize(MRegisterInfo::FirstVirtualRegister-1); p2vMap_.clear(); v2pMap_.clear(); v2ssMap_.clear(); - instrAdded_ = 0; - - // liner scan algorithm - DEBUG(std::cerr << "Processing " << li_->size() << " instervals\n"); - for (Intervals::iterator i = li_->begin(), e = li_->end(); i != e; ++i) { - tie(currentMbb_, currentInstr_) = getMbbMbbIteratorPair(i->start()); - DEBUG(std::cerr << "instruction[" << i->start() << "]: " - << **currentInstr_); - assert(currentInstr_ >= currentMbb_->begin() && - currentInstr_ < currentMbb_->end() && - "current instruction/machine basic block mismatch"); - DEBUG(printIntervals("\tactive", active_.begin(), active_.end())); - DEBUG(printIntervals("\tinactive", inactive_.begin(), inactive_.end())); - processActiveIntervals(i); - processInactiveIntervals(i); + for (MachineBasicBlockPtrs::iterator + mbbi = mbbs_.begin(), mbbe = mbbs_.end(); mbbi != mbbe; ++mbbi) { + instrAdded_ = 0; + currentMbb_ = *mbbi; + for (currentInstr_ = currentMbb_->begin(); + currentInstr_ != currentMbb_->end(); ++currentInstr_) { + + assert(currentInstr_ >= currentMbb_->begin() && + currentInstr_ < currentMbb_->end() && + "current instruction/machine basic block mismatch"); + unsigned curIndex = getInstructionIndex(); + DEBUG(std::cerr << "instruction[" << curIndex << "]: "; + (*currentInstr_)->print(std::cerr, *tm_)); + DEBUG(std::cerr << "\tcurrent interval: "; + if (currentInterval_ == li_->end()) std::cerr << "NONE\n"; + else std::cerr << *currentInterval_ << '\n'); + DEBUG(printIntervals("\tactive", active_.begin(), active_.end())); + DEBUG(printIntervals("\tinactive", + inactive_.begin(), + inactive_.end())); + DEBUG(printVirt2PhysMap()); + + // process the active intervals (this will potentially + // free physical registers) + processActiveIntervals(curIndex); + // processInactiveIntervals(curIndex); + + + // get used operands into registers + DEBUG(std::cerr << "\t\tprocessing operands:\n"); + for (unsigned i = 0, e = (*currentInstr_)->getNumOperands(); + i != e; ++i) { + MachineOperand& op = (*currentInstr_)->getOperand(i); + if (op.opIsUse() && op.isVirtualRegister()) { + unsigned virtReg = op.getAllocatedRegNum(); + Virt2PhysMap::iterator it = v2pMap_.find(virtReg); + if (it == v2pMap_.end()) { + unsigned physReg = it->second; + loadPhysReg(physReg, virtReg); + } + } + } + + // loop over implicit defs spilling them + DEBUG(std::cerr << "\t\tprocessing implicit defs:\n"); + const TargetInstrDescriptor& tid = + tm_->getInstrInfo().get((*currentInstr_)->getOpcode()); + for (const unsigned* id = tid.ImplicitDefs; *id; ++id) { + DEBUG(printVirt2PhysMap()); + unsigned virtReg = p2vMap_[*id]; + if (virtReg) { + spillVirtReg(virtReg); + for (IntervalPtrs::iterator + i = active_.begin(); i != active_.end(); ) { + if ((*i)->reg == virtReg) { + i = active_.erase(i); + break; + } + else { + ++i; + } + } + } + } + + processInterval(curIndex); + + for (unsigned i = 0, e = (*currentInstr_)->getNumOperands(); + i != e; ++i) { + MachineOperand& op = (*currentInstr_)->getOperand(i); + if (op.isVirtualRegister()) { + unsigned virtReg = op.getAllocatedRegNum(); + unsigned physReg = v2pMap_[virtReg]; + assert(physReg && "should not have virtual registers here"); + (*currentInstr_)->SetMachineOperandReg(i, physReg); + } + } - unsigned physReg = getFreeReg(i->reg); - if (!physReg) { - spillAtInterval(i); - physReg = getFreeReg(i->reg); + DEBUG(std::cerr << "instruction[" << curIndex << "]: "; + (*currentInstr_)->print(std::cerr, *tm_)); } - loadPhysReg(physReg, i->reg); - active_.push_back(&*i); } return true; } -void RA::processActiveIntervals(Intervals::iterator cur) +void RA::processInterval(unsigned curIndex) +{ + // liner scan algorithm + assert((currentInterval_ == li_->end() || + currentInterval_->start() >= curIndex) + && "skipping intervals?"); + + if (currentInterval_ != li_->end() && + currentInterval_->start() == curIndex) { + DEBUG(std::cerr << "\t\tprocessing current interval:\n"); + unsigned virtReg = currentInterval_->reg; + unsigned physReg = getFreeReg(virtReg); + if (!physReg) { + spill(); + physReg = getFreeReg(virtReg); + } + bool inserted = v2pMap_.insert(std::make_pair(virtReg, physReg)).second; + assert (inserted && "attempt to allocate already allocated register"); + markReg(virtReg); + active_.push_back(&*currentInterval_); + ++currentInterval_; + } +} + +void RA::processActiveIntervals(unsigned curIndex) { DEBUG(std::cerr << "\t\tprocessing active intervals:\n"); - unsigned curInstrIndex = cur->start(); for (IntervalPtrs::iterator i = active_.begin(); i != active_.end();) { unsigned virtReg = (*i)->reg; // remove expired intervals - if ((*i)->expired(curInstrIndex)) { + if ((*i)->expired(curIndex)) { DEBUG(std::cerr << "\t\t\tinterval " << **i << " expired\n"); freeReg(virtReg); // remove interval from active i = active_.erase(i); } - else if (!(*i)->overlaps(curInstrIndex)) { - DEBUG(std::cerr << "\t\t\tinterval " << **i << " inactive\n"); - unmarkReg(virtReg); - // add interval to inactive - inactive_.push_back(*i); - // remove interval from active - i = active_.erase(i); - } +// else if (!(*i)->overlaps(curIndex)) { +// DEBUG(std::cerr << "\t\t\tinterval " << **i << " inactive\n"); +// unmarkReg(virtReg); +// // add interval to inactive +// inactive_.push_back(*i); +// // remove interval from active +// i = active_.erase(i); +// } else { ++i; } } } -void RA::processInactiveIntervals(Intervals::iterator cur) +void RA::processInactiveIntervals(unsigned curIndex) { DEBUG(std::cerr << "\t\tprocessing inactive intervals:\n"); - unsigned curInstrIndex = cur->start(); for (IntervalPtrs::iterator i = inactive_.begin(); i != inactive_.end();) { unsigned virtReg = (*i)->reg; - if ((*i)->expired(curInstrIndex)) { + if ((*i)->expired(curIndex)) { DEBUG(std::cerr << "\t\t\tinterval " << **i << " expired\n"); freeReg(virtReg); // remove from inactive i = inactive_.erase(i); } - else if ((*i)->overlaps(curInstrIndex)) { + else if ((*i)->overlaps(curIndex)) { DEBUG(std::cerr << "\t\t\tinterval " << **i << " active\n"); markReg(virtReg); // add to active @@ -243,9 +338,9 @@ } } -void RA::spillAtInterval(Intervals::iterator cur) +void RA::spill() { - DEBUG(std::cerr << "\t\tspilling at interval " << *cur << ":\n"); + DEBUG(std::cerr << "\t\tspilling at interval "<< *currentInterval_<< ":\n"); assert(!active_.empty() && "active set cannot be empty when choosing a register to spill"); IntervalPtrs::iterator lastEnd = active_.begin(); @@ -294,7 +389,7 @@ unsigned RA::getFreeReg(unsigned virtReg) { - DEBUG(std::cerr << "\t\tgetting free register: "); + DEBUG(std::cerr << "\t\t\tgetting free register: "); const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(virtReg); TargetRegisterClass::iterator reg = rc->allocation_order_begin(*mf_); TargetRegisterClass::iterator regEnd = rc->allocation_order_end(*mf_); @@ -314,7 +409,6 @@ void RA::freeReg(unsigned virtReg) { unmarkReg(virtReg); - v2pMap_.erase(v2pMap_.find(virtReg)); } void RA::markReg(unsigned virtReg) @@ -323,6 +417,8 @@ assert(it != v2pMap_.end() && "attempting to mark an already disassociated register"); unsigned physReg = it->second; + DEBUG(std::cerr << "\t\t\t\tmarked registster " << mri_->getName(physReg) + << " used by " << virtReg << '\n'); p2vMap_[physReg] = virtReg; } @@ -330,9 +426,12 @@ { Virt2PhysMap::iterator it = v2pMap_.find(virtReg); assert(it != v2pMap_.end() && - "attempting to mark an already disassociated register"); + "attempting to unmark an already disassociated register"); unsigned physReg = it->second; + DEBUG(std::cerr << "\t\t\t\tmarked registster " << mri_->getName(physReg) + << " free\n"); p2vMap_[physReg] = 0; + v2pMap_.erase(it); } int RA::findOrCreateStackSlot(unsigned virtReg) @@ -352,11 +451,13 @@ void RA::spillVirtReg(unsigned virtReg) { + DEBUG(std::cerr << "\t\t\tspilling register: " << virtReg << '\n'); const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(virtReg); int frameIndex = findOrCreateStackSlot(virtReg); ++numSpilled; instrAdded_ += mri_->storeRegToStackSlot(*currentMbb_, currentInstr_, v2pMap_[virtReg], frameIndex, rc); + unmarkReg(virtReg); } void RA::loadPhysReg(unsigned physReg, unsigned virtReg) @@ -366,17 +467,17 @@ ++numReloaded; instrAdded_ += mri_->loadRegFromStackSlot(*currentMbb_, currentInstr_, physReg, frameIndex, rc); - v2pMap_[virtReg] = physReg; - p2vMap_[physReg] = virtReg; + bool inserted = v2pMap_.insert(std::make_pair(virtReg, physReg)).second; + assert (inserted && "attempt to allocate already allocated register"); + markReg(virtReg); } -std::pair -RA::getMbbMbbIteratorPair(unsigned miIndex) const +unsigned RA::getInstructionIndex() const { - MachineBasicBlock* mbb = (*mii2mbbMap_)[miIndex]; - MachineBasicBlock::iterator instr = - mbb->begin() + instrAdded_ + miIndex - (*mbb2miiMap_)[mbb]; - return std::make_pair(mbb, instr); + Mbb2MiIndexMap::const_iterator it = mbb2miiMap_->find(currentMbb_); + assert(it != mbb2miiMap_->end() && + "no MachineInstruction index for basic block?"); + return it->second + (currentInstr_ - currentMbb_->begin()) - instrAdded_; } FunctionPass *createLinearScanRegisterAllocator() { Index: llvm/lib/CodeGen/LiveIntervals.cpp diff -u llvm/lib/CodeGen/LiveIntervals.cpp:1.1.2.7 llvm/lib/CodeGen/LiveIntervals.cpp:1.1.2.8 --- llvm/lib/CodeGen/LiveIntervals.cpp:1.1.2.7 Wed Nov 5 20:58:12 2003 +++ llvm/lib/CodeGen/LiveIntervals.cpp Fri Nov 7 18:23:03 2003 @@ -57,6 +57,13 @@ tm_ = &fn.getTarget(); mri_ = tm_->getRegisterInfo(); lv_ = &getAnalysis(); + mbbi2mbbMap_.clear(); + mi2iMap_.clear(); + r2iMap_.clear(); + r2iMap_.clear(); + intervals_.clear(); + mii2mbbMap_.clear(); + mbb2miiMap_.clear(); // number MachineInstrs unsigned miIndex = 0; @@ -86,21 +93,19 @@ return true; } -namespace { - void printRegName(const MRegisterInfo* mri, int reg) { - DEBUG( - if (reg < MRegisterInfo::FirstVirtualRegister) - std::cerr << mri->getName(reg); - else - std::cerr << '%' << reg); - } +void LiveIntervals::printRegName(unsigned reg) const +{ + if (reg < MRegisterInfo::FirstVirtualRegister) + std::cerr << mri_->getName(reg); + else + std::cerr << '%' << reg; } void LiveIntervals::handleRegisterDef(MachineBasicBlock* mbb, MachineInstr* instr, unsigned reg) { - DEBUG(std::cerr << "\t\t\tregister: "; printRegName(mri_, reg)); + DEBUG(std::cerr << "\t\t\tregister: ";printRegName(reg); std::cerr << '\n'); unsigned instrIndex = getInstructionIndex(instr); @@ -113,8 +118,10 @@ unsigned ii = r2iit->second; Interval& interval = intervals_[ii]; unsigned end = getInstructionIndex(mbb->back()) + 1; + DEBUG(std::cerr << "\t\t\t\tadding range: [" + << instrIndex << ',' << end << "]\n"); interval.addRange(instrIndex, end); - DEBUG(std::cerr << " -> " << interval << '\n'); + DEBUG(std::cerr << "\t\t\t\t" << interval << '\n'); } else { // add new interval @@ -130,28 +137,38 @@ MachineBasicBlock* liveBlock = it->second; if (liveBlockIndex < vi.AliveBlocks.size() && vi.AliveBlocks[liveBlockIndex]) { - unsigned start = mbb == liveBlock ? - instrIndex : - getInstructionIndex(liveBlock->front()); - interval.addRange(start, - getInstructionIndex(liveBlock->back()) + 1); + unsigned start = getInstructionIndex(liveBlock->front()); + unsigned end = getInstructionIndex(liveBlock->back()) + 1; + DEBUG(std::cerr << "\t\t\t\tadding range: [" + << start << ',' << end << "]\n"); + interval.addRange(start, end); } } + bool killedInDefiningBasicBlock = false; for (int i = 0, e = vi.Kills.size(); i != e; ++i) { MachineBasicBlock* killerBlock = vi.Kills[i].first; MachineInstr* killerInstr = vi.Kills[i].second; - unsigned start = mbb == killerBlock ? - instrIndex : - getInstructionIndex(killerBlock->front()); - interval.addRange(start, - getInstructionIndex(killerInstr) + 1); + killedInDefiningBasicBlock |= mbb == killerBlock; + unsigned start = (mbb == killerBlock ? + instrIndex : + getInstructionIndex(killerBlock->front())); + unsigned end = getInstructionIndex(killerInstr) + 1; + DEBUG(std::cerr << "\t\t\t\tadding range: [" + << start << ',' << end << "]\n"); + interval.addRange(start, end); } - DEBUG(std::cerr << " -> " << interval << '\n'); + + if (!killedInDefiningBasicBlock) { + unsigned end = getInstructionIndex(mbb->back()) + 1; + interval.addRange(instrIndex, end); + } + + DEBUG(std::cerr << "\t\t\t\t" << interval << '\n'); } } -unsigned LiveIntervals::getInstructionIndex(MachineInstr* instr) +unsigned LiveIntervals::getInstructionIndex(MachineInstr* instr) const { assert(mi2iMap_.find(instr) != mi2iMap_.end() && "instruction not assigned a number"); @@ -178,8 +195,8 @@ const TargetInstrDescriptor& tid = tm_->getInstrInfo().get(instr->getOpcode()); DEBUG(std::cerr << "\t\tinstruction[" - << mi2iMap_.find(instr)->second << "]: " - << *instr << '\n'); + << getInstructionIndex(instr) << "]: "; + instr->print(std::cerr, *tm_);); for (int i = instr->getNumOperands() - 1; i >= 0; --i) { MachineOperand& mop = instr->getOperand(i); From alkis at cs.uiuc.edu Fri Nov 7 18:24:11 2003 From: alkis at cs.uiuc.edu (Alkis Evlogimenos) Date: Fri Nov 7 18:24:11 2003 Subject: [llvm-commits] [regalloc_linearscan] CVS: llvm/include/llvm/CodeGen/LiveIntervals.h Message-ID: <200311080023.SAA05363@morpheus.cs.uiuc.edu> Changes in directory llvm/include/llvm/CodeGen: LiveIntervals.h updated: 1.1.2.6 -> 1.1.2.7 --- Log message: LiveIntervals: - be a little stricter in terms of constness - make runOnMachineFunction reentrant - make debugging output prettier - fix wrong interval computation of variables that get killed in their defining basic block RegAlloc: - disable inactive interval processing, handle the simple case for now (ignore holes) - improve debugging output - succeed in register allocating a simple hello world llvm assembly file --- Diffs of the changes: (+14 -2) Index: llvm/include/llvm/CodeGen/LiveIntervals.h diff -u llvm/include/llvm/CodeGen/LiveIntervals.h:1.1.2.6 llvm/include/llvm/CodeGen/LiveIntervals.h:1.1.2.7 --- llvm/include/llvm/CodeGen/LiveIntervals.h:1.1.2.6 Wed Nov 5 01:27:17 2003 +++ llvm/include/llvm/CodeGen/LiveIntervals.h Fri Nov 7 18:23:05 2003 @@ -123,6 +123,7 @@ typedef std::vector Intervals; typedef std::map MiIndex2MbbMap; typedef std::map Mbb2MiIndexMap; + typedef std::vector MachineBasicBlockPtrs; private: MachineFunction* mf_; @@ -147,9 +148,18 @@ public: virtual void getAnalysisUsage(AnalysisUsage &AU) const; - Intervals& getIntervals() { return intervals_; } + const Intervals& getIntervals() const { return intervals_; } MiIndex2MbbMap& getMiIndex2MbbMap() { return mii2mbbMap_; } Mbb2MiIndexMap& getMbb2MiIndexMap() { return mbb2miiMap_; } + MachineBasicBlockPtrs getOrderedMachineBasicBlockPtrs() const { + MachineBasicBlockPtrs result; + for (MbbIndex2MbbMap::const_iterator + it = mbbi2mbbMap_.begin(), itEnd = mbbi2mbbMap_.end(); + it != itEnd; ++it) { + result.push_back(it->second); + } + return result; + } private: /// runOnMachineFunction - pass entry point @@ -163,7 +173,9 @@ MachineInstr* instr, unsigned reg); - unsigned getInstructionIndex(MachineInstr* instr); + unsigned getInstructionIndex(MachineInstr* instr) const; + + void printRegName(unsigned reg) const; }; inline bool operator==(const LiveIntervals::Interval& lhs, From brukman at cs.uiuc.edu Fri Nov 7 19:06:01 2003 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri Nov 7 19:06:01 2003 Subject: [llvm-commits] CVS: llvm/docs/LangRef.html Message-ID: <200311080105.TAA06790@zion.cs.uiuc.edu> Changes in directory llvm/docs: LangRef.html updated: 1.37 -> 1.38 --- Log message: First pass at cleaning up LangRef.html: stylesheet-ification, consistent formatting, more strict adherence to HTML 4.01, other misc. cleanups. --- Diffs of the changes: (+1011 -660) Index: llvm/docs/LangRef.html diff -u llvm/docs/LangRef.html:1.37 llvm/docs/LangRef.html:1.38 --- llvm/docs/LangRef.html:1.37 Wed Oct 29 22:35:26 2003 +++ llvm/docs/LangRef.html Fri Nov 7 19:05:38 2003 @@ -1,132 +1,136 @@ - -LLVM Assembly Language Reference Manual - - - - -
        LLVM Language Reference Manual
      + + + + LLVM Assembly Language Reference Manual + + + + +
      + LLVM Language Reference Manual +
        -
      1. Abstract -
      2. Introduction -
      3. Identifiers +
      4. Abstract
      5. +
      6. Introduction
      7. +
      8. Identifiers
      9. Type System
        1. Primitive Types
            -
          1. Type Classifications -
          +
        2. Type Classifications
        3. +
      10. Derived Types
          -
        1. Array Type -
        2. Function Type -
        3. Pointer Type -
        4. Structure Type +
        5. Array Type
        6. +
        7. Function Type
        8. +
        9. Pointer Type
        10. +
        11. Structure Type
        12. -
        -
      + +
    • High Level Structure
        -
      1. Module Structure -
      2. Global Variables -
      3. Function Structure -
      +
    • Module Structure
    • +
    • Global Variables
    • +
    • Function Structure
    • +
    • Instruction Reference
      1. Terminator Instructions
          -
        1. 'ret' Instruction -
        2. 'br' Instruction -
        3. 'switch' Instruction -
        4. 'invoke' Instruction -
        5. 'unwind' Instruction -
        +
      2. 'ret' Instruction
      3. +
      4. 'br' Instruction
      5. +
      6. 'switch' Instruction
      7. +
      8. 'invoke' Instruction
      9. +
      10. 'unwind' Instruction
      11. +
    • Binary Operations
        -
      1. 'add' Instruction -
      2. 'sub' Instruction -
      3. 'mul' Instruction -
      4. 'div' Instruction -
      5. 'rem' Instruction -
      6. 'setcc' Instructions -
      +
    • 'add' Instruction
    • +
    • 'sub' Instruction
    • +
    • 'mul' Instruction
    • +
    • 'div' Instruction
    • +
    • 'rem' Instruction
    • +
    • 'setcc' Instructions
    • +
    • Bitwise Binary Operations
        -
      1. 'and' Instruction -
      2. 'or' Instruction -
      3. 'xor' Instruction -
      4. 'shl' Instruction -
      5. 'shr' Instruction -
      +
    • 'and' Instruction
    • +
    • 'or' Instruction
    • +
    • 'xor' Instruction
    • +
    • 'shl' Instruction
    • +
    • 'shr' Instruction
    • +
    • Memory Access Operations
        -
      1. 'malloc' Instruction -
      2. 'free' Instruction -
      3. 'alloca' Instruction -
      4. 'load' Instruction -
      5. 'store' Instruction -
      6. 'getelementptr' Instruction -
      +
    • 'malloc' Instruction
    • +
    • 'free' Instruction
    • +
    • 'alloca' Instruction
    • +
    • 'load' Instruction
    • +
    • 'store' Instruction
    • +
    • 'getelementptr' Instruction
    • +
    • Other Operations
        -
      1. 'phi' Instruction -
      2. 'cast .. to' Instruction -
      3. 'call' Instruction -
      4. 'vanext' Instruction -
      5. 'vaarg' Instruction +
      6. 'phi' Instruction
      7. +
      8. 'cast .. to' Instruction
      9. +
      10. 'call' Instruction
      11. +
      12. 'vanext' Instruction
      13. +
      14. 'vaarg' Instruction
    • Intrinsic Functions
      1. Variable Argument Handling Intrinsics
          -
        1. 'llvm.va_start' Intrinsic -
        2. 'llvm.va_end' Intrinsic -
        3. 'llvm.va_copy' Intrinsic -
        -
      - -

      Written by Chris Lattner and Vikram Adve

      - +

    • 'llvm.va_start' Intrinsic
    • +
    • 'llvm.va_end' Intrinsic
    • +
    • 'llvm.va_copy' Intrinsic
    • + + +
      +

      Written by Chris Lattner and Vikram Adve

      +

      -

      -
      -Abstract -

      -
      -Introduction -
        + -The LLVM code representation is designed to be used in three different forms: as -an in-memory compiler IR, as an on-disk bytecode representation (suitable for +
        + +

        The LLVM code representation is designed to be used in three different forms: +as an in-memory compiler IR, as an on-disk bytecode representation (suitable for fast loading by a Just-In-Time compiler), and as a human readable assembly language representation. This allows LLVM to provide a powerful intermediate representation for efficient compiler transformations and analysis, while providing a natural means to debug and visualize the transformations. The three different forms of LLVM are all equivalent. This document describes the human -readable representation and notation.

        +readable representation and notation.

        -The LLVM representation aims to be a light-weight and low-level while being +

        The LLVM representation aims to be a light-weight and low-level while being expressive, typed, and extensible at the same time. It aims to be a "universal IR" of sorts, by being at a low enough level that high-level ideas may be cleanly mapped to it (similar to how microprocessors are "universal IR's", @@ -134,103 +138,121 @@ information, LLVM can be used as the target of optimizations: for example, through pointer analysis, it can be proven that a C automatic variable is never accessed outside of the current function... allowing it to be promoted to a -simple SSA value instead of a memory location.

        +simple SSA value instead of a memory location.

        + +
        -


      Well Formedness

        + + +
        -It is important to note that this document describes 'well formed' LLVM assembly -language. There is a difference between what the parser accepts and what is -considered 'well formed'. For example, the following instruction is -syntactically okay, but not well formed:

        +

        It is important to note that this document describes 'well formed' LLVM +assembly language. There is a difference between what the parser accepts and +what is considered 'well formed'. For example, the following instruction is +syntactically okay, but not well formed:

           %x = add int 1, %x
         
        -...because the definition of %x does not dominate all of its uses. The -LLVM infrastructure provides a verification pass that may be used to verify that -an LLVM module is well formed. This pass is automatically run by the parser -after parsing input assembly, and by the optimizer before it outputs bytecode. -The violations pointed out by the verifier pass indicate bugs in transformation -passes or input to the parser.

        +

        ...because the definition of %x does not dominate all of its uses. +The LLVM infrastructure provides a verification pass that may be used to verify +that an LLVM module is well formed. This pass is automatically run by the +parser after parsing input assembly, and by the optimizer before it outputs +bytecode. The violations pointed out by the verifier pass indicate bugs in +transformation passes or input to the parser.

        +
        -
      -
      -Identifiers -
        + -LLVM uses three different forms of identifiers, for different purposes:

        +

        + +

        LLVM uses three different forms of identifiers, for different purposes:

          -
        1. Numeric constants are represented as you would expect: 12, -3 123.421, etc. -Floating point constants have an optional hexidecimal notation. -
        2. Named values are represented as a string of characters with a '%' prefix. -For example, %foo, %DivisionByZero, %a.really.long.identifier. The actual -regular expression used is '%[a-zA-Z$._][a-zA-Z$._0-9]*'. Identifiers -which require other characters in their names can be surrounded with quotes. In -this way, anything except a " character can be used in a name. - -
        3. Unnamed values are represented as an unsigned numeric value with a '%' -prefix. For example, %12, %2, %44. -

        - -LLVM requires the values start with a '%' sign for two reasons: Compilers don't -need to worry about name clashes with reserved words, and the set of reserved -words may be expanded in the future without penalty. Additionally, unnamed -identifiers allow a compiler to quickly come up with a temporary variable -without having to avoid symbol table conflicts.

        +

      • Numeric constants are represented as you would expect: 12, -3 123.421, + etc. Floating point constants have an optional hexidecimal notation.
      • + +
      • Named values are represented as a string of characters with a '%' prefix. + For example, %foo, %DivisionByZero, %a.really.long.identifier. The actual + regular expression used is '%[a-zA-Z$._][a-zA-Z$._0-9]*'. + Identifiers which require other characters in their names can be surrounded + with quotes. In this way, anything except a " character can be used + in a name.
      • + +
      • Unnamed values are represented as an unsigned numeric value with a '%' + prefix. For example, %12, %2, %44.
      • + + + +

        LLVM requires the values start with a '%' sign for two reasons: Compilers +don't need to worry about name clashes with reserved words, and the set of +reserved words may be expanded in the future without penalty. Additionally, +unnamed identifiers allow a compiler to quickly come up with a temporary +variable without having to avoid symbol table conflicts.

        -Reserved words in LLVM are very similar to reserved words in other languages. +

        Reserved words in LLVM are very similar to reserved words in other languages. There are keywords for different opcodes ('add', 'cast', 'ret', etc...), for primitive type names ('void', 'uint', etc...), and others. These reserved words cannot conflict with variable names, because none of them start with a '%' -character.

        +character.

        + +

        Here is an example of LLVM code to multiply the integer variable +'%X' by 8:

        -Here is an example of LLVM code to multiply the integer variable '%X' -by 8:

        +

        The easy way:

        -The easy way:
           %result = mul uint %X, 8
         
        -After strength reduction: +

        After strength reduction:

        +
           %result = shl uint %X, ubyte 3
         
        -And the hard way: +

        And the hard way:

        +
           add uint %X, %X           ; yields {uint}:%0
           add uint %0, %0           ; yields {uint}:%1
           %result = add uint %1, %1
         
        -This last way of multiplying %X by 8 illustrates several important lexical features of LLVM:

        +

        This last way of multiplying %X by 8 illustrates several important +lexical features of LLVM:

          -
        1. Comments are delimited with a ';' and go until the end of line. -
        2. Unnamed temporaries are created when the result of a computation is not - assigned to a named value. -
        3. Unnamed temporaries are numbered sequentially -

        +

      • Comments are delimited with a ';' and go until the end of + line.
      • + +
      • Unnamed temporaries are created when the result of a computation is not + assigned to a named value.
      • + +
      • Unnamed temporaries are numbered sequentially
      • + -...and it also show a convention that we follow in this document. When +

        ...and it also show a convention that we follow in this document. When demonstrating instructions, we will follow an instruction with a comment that defines the type and name of value produced. Comments are shown in italic -text.

        +text.

        -The one non-intuitive notation for constants is the optional hexidecimal form of -floating point constants. For example, the form 'double +

        The one non-intuitive notation for constants is the optional hexidecimal form +of floating point constants. For example, the form 'double 0x432ff973cafa8000' is equivalent to (but harder to read than) 'double 4.5e+15' which is also supported by the parser. The only time hexadecimal floating point constants are useful (and the only time that they are generated @@ -238,41 +260,47 @@ representable as a decimal floating point number exactly. For example, NaN's, infinities, and other special cases are represented in their IEEE hexadecimal format so that assembly and disassembly do not cause any bits to change in the -constants.

        +constants.

        +
        -
      -
      -Type System -
        + -The LLVM type system is one of the most important features of the intermediate -representation. Being typed enables a number of optimizations to be performed -on the IR directly, without having to do extra analyses on the side before the -transformation. A strong type system makes it easier to read the generated code -and enables novel analyses and transformations that are not feasible to perform -on normal three address code representations.

        +

        + +

        The LLVM type system is one of the most important features of the +intermediate representation. Being typed enables a number of optimizations to +be performed on the IR directly, without having to do extra analyses on the side +before the transformation. A strong type system makes it easier to read the +generated code and enables novel analyses and transformations that are not +feasible to perform on normal three address code representations.

        - +
        -
      -
         -Primitive Types -
        + -The primitive types are the fundemental building blocks of the LLVM system. The -current set of primitive types are as follows:

        +

        -
        +

        The primitive types are the fundemental building blocks of the LLVM system. +The current set of primitive types are as follows:

        + +

        + + + + +
        - +
        @@ -284,7 +312,7 @@
        void No value
        ubyte Unsigned 8 bit value
        ushortUnsigned 16 bit value
        - +
        @@ -293,161 +321,234 @@
        bool True or False value
        sbyte Signed 8 bit value
        short Signed 16 bit value
        double64 bit floating point value
        -

        - +

        +

        + -


        Type Classifications

          + + +
          -These different primitive types fall into a few useful classifications:

          +

          These different primitive types fall into a few useful classifications:

          - - - - - - - -
          signed sbyte, short, int, long, float, double
          unsignedubyte, ushort, uint, ulong
          integerubyte, sbyte, ushort, short, uint, int, ulong, long
          integralbool, ubyte, sbyte, ushort, short, uint, int, ulong, long
          floating pointfloat, double
          first classbool, ubyte, sbyte, ushort, short,
          uint, int, ulong, long, float, double, pointer

          +

          + + + + + + + + + + + + + + + + + + + + + + + + + +
          signedsbyte, short, int, long, float, double
          unsignedubyte, ushort, uint, ulong
          integerubyte, sbyte, ushort, short, uint, int, ulong, long
          integralbool, ubyte, sbyte, ushort, short, uint, int, ulong, long
          floating pointfloat, double
          first classbool, ubyte, sbyte, ushort, short,
          + uint, int, ulong, long, float, double, + pointer
          +

          -The first class types are perhaps the most +

          The first class types are perhaps the most important. Values of these types are the only ones which can be produced by instructions, passed as arguments, or used as operands to instructions. This means that all structures and arrays must be manipulated either by pointer or by -component.

          +component.

          +
          -
           -Derived Types -
          + -The real power in LLVM comes from the derived types in the system. This is what -allows a programmer to represent arrays, functions, pointers, and other useful -types. Note that these derived types may be recursive: For example, it is -possible to have a two dimensional array.

          +

          +

          The real power in LLVM comes from the derived types in the system. This is +what allows a programmer to represent arrays, functions, pointers, and other +useful types. Note that these derived types may be recursive: For example, it +is possible to have a two dimensional array.

          +
          -


        Array Type

          + + +
          Overview:
          -The array type is a very simple derived type that arranges elements sequentially -in memory. The array type requires a size (number of elements) and an -underlying data type.

          +

          The array type is a very simple derived type that arranges elements +sequentially in memory. The array type requires a size (number of elements) and +an underlying data type.

          Syntax:
          +
             [<# elements> x <elementtype>]
           
          -The number of elements is a constant integer value, elementtype may be any type -with a size.

          +

          The number of elements is a constant integer value, elementtype may be any +type with a size.

          Examples:
          -
            + +

            [40 x int ]: Array of 40 integer values.
            [41 x int ]: Array of 41 integer values.
            [40 x uint]: Array of 40 unsigned integer values.

            -

          +

          + +

          Here are some examples of multidimensional arrays:

          -Here are some examples of multidimensional arrays:

          -

            - - - - +

            +

            [3 x [4 x int]]: 3x4 array integer values.
            [12 x [10 x float]]: 12x10 array of single precision floating point values.
            [2 x [3 x [4 x uint]]]: 2x3x4 array of unsigned integer values.
            + + + + + + + + + + + +
            [3 x [4 x int]]: 3x4 array integer values.
            [12 x [10 x float]]: 12x10 array of single precision floating point values.
            [2 x [3 x [4 x uint]]]: 2x3x4 array of unsigned integer values.
            -
          +

          +
          -


        Function Type

          + + +
          Overview:
          -The function type can be thought of as a function signature. It consists of a -return type and a list of formal parameter types. Function types are usually +

          The function type can be thought of as a function signature. It consists of +a return type and a list of formal parameter types. Function types are usually used when to build virtual function tables (which are structures of pointers to -functions), for indirect function calls, and when defining a function.

          +functions), for indirect function calls, and when defining a function.

          Syntax:
          +
             <returntype> (<parameter list>)
           
          -Where '<parameter list>' is a comma-separated list of type +

          Where '<parameter list>' is a comma-separated list of type specifiers. Optionally, the parameter list may include a type ..., which indicates that the function takes a variable number of arguments. Variable argument functions can access their arguments with the variable argument handling intrinsic functions. -

          +href="#int_varargs">variable argument handling intrinsic functions.

          Examples:
          -
            - - - - - - +

            +

            int (int): function taking an int, returning -an int
            float (int, int *) *: Pointer -to a function that takes an int and a pointer -to int, returning float.
            int (sbyte *, ...): A vararg function that takes at -least one pointer to sbyte (signed char in C), -which returns an integer. This is the signature for printf in -LLVM.
            + + + + + + + + + + + +
            int (int): function taking an int, returning an int
            float (int, int *) *: Pointer to a function that takes an + int and a pointer to int, + returning float.
            int (sbyte *, ...): A vararg function that takes at least one pointer to sbyte (signed char in C), which + returns an integer. This is the signature for printf in + LLVM.
            -
          - +

          +
          -


        Structure Type

          + + +
          Overview:
          -The structure type is used to represent a collection of data members together in -memory. The packing of the field types is defined to match the ABI of the +

          The structure type is used to represent a collection of data members together +in memory. The packing of the field types is defined to match the ABI of the underlying processor. The elements of a structure may be any type that has a -size.

          +size.

          -Structures are accessed using 'load and 'store' by getting a pointer to a field with the 'getelementptr' instruction.

          +

          Structures are accessed using 'load and +'store' by getting a pointer to a field with the +'getelementptr' instruction.

          Syntax:
          +
             { <type list> }
           
          -
          Examples:
          - - - - - +

          +

          { int, int, int }: a triple of three int -values
          { float, int (int) * }: A pair, where the first -element is a float and the second element is a pointer to a function that takes -an int, returning an int.
          + + + + + + + +
          { int, int, int }: a triple of three int values
          { float, int (int) * }: A pair, where the first element is a float and the second + element is a pointer to a function that takes an int, returning an + int.
          +

          +
          -


        Pointer Type

          + + +
          Overview:
          -As in many languages, the pointer type represents a pointer or reference to -another object, which must live in memory.

          +

          As in many languages, the pointer type represents a pointer or reference to +another object, which must live in memory.

          Syntax:
          @@ -456,49 +557,61 @@
           
           
          Examples:
          - - - - - - -
          [4x int]*: pointer to array of four int values
          int (int *) *: A pointer to a -function that takes an int, returning an -int.

          + + + + + + + + + +
          [4x int]*: pointer to array of four + int values
          int (int *) *: A pointer to a function that takes an int, returning an + int.
          +

          +
          -
        -
        -High Level Structure -
        -
           -Module Structure -
        -
           -Global Variables -
        -
           -Functions -
          + + +
          -LLVM functions definitions are composed of a (possibly empty) argument list, an -opening curly brace, a list of basic blocks, and a closing curly brace. LLVM +

          LLVM functions definitions are composed of a (possibly empty) argument list, +an opening curly brace, a list of basic blocks, and a closing curly brace. LLVM function declarations are defined with the "declare" keyword, a -function name and a function signature.

          +function name and a function signature.

          -A function definition contains a list of basic blocks, forming the CFG for the -function. Each basic block may optionally start with a label (giving the basic -block a symbol table entry), contains a list of instructions, and ends with a terminator instruction (such as a branch or function -return).

          +

          A function definition contains a list of basic blocks, forming the CFG for +the function. Each basic block may optionally start with a label (giving the +basic block a symbol table entry), contains a list of instructions, and ends +with a terminator instruction (such as a branch or +function return).

          -The first basic block in program is special in two ways: it is immediately +

          The first basic block in program is special in two ways: it is immediately executed on entrance to the function, and it is not allowed to have predecessor basic blocks (i.e. there can not be any branches to the entry block of a function). Because the block can have no predecessors, it also cannot have any -PHI nodes.

          +PHI nodes.

          +
          -
        -
        -Instruction Reference -
        -
           -Terminator Instructions -
          - -As mentioned previously, every basic block in a -program ends with a "Terminator" instruction, which indicates which block should -be executed after the current block is finished. These terminator instructions -typically yield a 'void' value: they produce control flow, not values -(the one exception being the 'invoke' -instruction).

          +

          + +
          + +

          As mentioned previously, every basic block +in a program ends with a "Terminator" instruction, which indicates which block +should be executed after the current block is finished. These terminator +instructions typically yield a 'void' value: they produce control flow, +not values (the one exception being the 'invoke' instruction).

          -There are five different terminator instructions: the 'There are five different terminator instructions: the 'ret' instruction, the 'br' instruction, the 'switch' instruction, the 'invoke' instruction, and the 'unwind' instruction.

          +href="#i_unwind">unwind' instruction.

          +
          -


        'ret' Instruction

          + + +
          Syntax:
          @@ -670,30 +794,29 @@
           
           
          Overview:
          -The 'ret' instruction is used to return control flow (and a value) from -a function, back to the caller.

          +

          The 'ret' instruction is used to return control flow (and a value) +from a function, back to the caller.

          -There are two forms of the 'ret' instructruction: one that returns a +

          There are two forms of the 'ret' instructruction: one that returns a value and then causes control flow, and one that just causes control flow to -occur.

          +occur.

          Arguments:
          -The 'ret' instruction may return any 'first +

          The 'ret' instruction may return any 'first class' type. Notice that a function is not well formed if there exists a 'ret' instruction inside of the function -that returns a value that does not match the return type of the function.

          +that returns a value that does not match the return type of the function.

          Semantics:
          -When the 'ret' instruction is executed, control flow returns back to +

          When the 'ret' instruction is executed, control flow returns back to the calling function's context. If the caller is a "call instruction, execution continues at the instruction after the call. If the caller was an "invoke" instruction, execution continues at the beginning "normal" of the destination block. If the instruction returns a -value, that value shall set the call or invoke instruction's return value.

          - +value, that value shall set the call or invoke instruction's return value.

          Example:
          @@ -701,11 +824,17 @@
             ret void                        ; Return from a void function
           
          +
          -


        'br' Instruction

          + + +
          Syntax:
          +
             br bool <cond>, label <iftrue>, label <iffalse>
             br label <dest>          ; Unconditional branch
          @@ -713,26 +842,28 @@
           
           
          Overview:
          -The 'br' instruction is used to cause control flow to transfer to a +

          The 'br' instruction is used to cause control flow to transfer to a different basic block in the current function. There are two forms of this instruction, corresponding to a conditional branch and an unconditional -branch.

          +branch.

          Arguments:
          -The conditional branch form of the 'br' instruction takes a single +

          The conditional branch form of the 'br' instruction takes a single 'bool' value and two 'label' values. The unconditional form of the 'br' instruction takes a single 'label' value as a -target.

          +target.

          Semantics:
          -Upon execution of a conditional 'br' instruction, the 'bool' -argument is evaluated. If the value is true, control flows to the -'iftrue' label argument. If "cond" is false, -control flows to the 'iffalse' label argument.

          +

          Upon execution of a conditional 'br' instruction, the +'bool' argument is evaluated. If the value is true, control +flows to the 'iftrue' label argument. If "cond" is +false, control flows to the 'iffalse' label +argument.

          Example:
          +
           Test:
             %cond = seteq int %a, %b
          @@ -743,42 +874,49 @@
             ret int 0
           
          +
          -


        'switch' Instruction

          + + +
          Syntax:
          +
             switch uint <value>, label <defaultdest> [ int <val>, label &dest>, ... ]
          -
           
          Overview:
          -The 'switch' instruction is used to transfer control flow to one of +

          The 'switch' instruction is used to transfer control flow to one of several different places. It is a generalization of the 'br' -instruction, allowing a branch to occur to one of many possible destinations.

          +instruction, allowing a branch to occur to one of many possible +destinations.

          Arguments:
          -The 'switch' instruction uses three parameters: a 'uint' +

          The 'switch' instruction uses three parameters: a 'uint' comparison value 'value', a default 'label' destination, and -an array of pairs of comparison value constants and 'label's.

          +an array of pairs of comparison value constants and 'label's.

          Semantics:
          -The switch instruction specifies a table of values and destinations. +

          The switch instruction specifies a table of values and destinations. When the 'switch' instruction is executed, this table is searched for the given value. If the value is found, the corresponding destination is -branched to, otherwise the default value it transfered to.

          +branched to, otherwise the default value it transfered to.

          Implementation:
          -Depending on properties of the target machine and the particular switch -instruction, this instruction may be code generated as a series of chained -conditional branches, or with a lookup table.

          +

          Depending on properties of the target machine and the particular +switch instruction, this instruction may be code generated as a series +of chained conditional branches, or with a lookup table.

          Example:
          +
             ; Emulate a conditional br instruction
             %Val = cast bool %value to uint
          @@ -793,12 +931,17 @@
                                                  int 2, label %ontwo ]
           
          - +
          -


        'invoke' Instruction

          + + +
          Syntax:
          +
             <result> = invoke <ptr to function ty> %<function ptr val>(<function args>)
                            to label <normal label> except label <exception label>
          @@ -806,19 +949,19 @@
           
           
          Overview:
          -The 'invoke' instruction causes control to transfer to a specified +

          The 'invoke' instruction causes control to transfer to a specified function, with the possibility of control flow transfer to either the 'normal' label label or the 'exception' label. If the callee function returns with the "ret" instruction, control flow will return to the "normal" label. If the callee (or any indirect callees) returns with the "unwind" instruction, control is interrupted, and -continued at the dynamically nearest "except" label.

          - +continued at the dynamically nearest "except" label.

          Arguments:
          -This instruction requires several arguments:

          +

          This instruction requires several arguments:

          +
          1. 'ptr to function ty': shall be the signature of the pointer to @@ -842,207 +985,274 @@
            Semantics:
            -This instruction is designed to operate as a standard 'This instruction is designed to operate as a standard 'call' instruction in most regards. The primary -difference is that it establishes an association with a label, which is used by the runtime library to unwind the stack.

            +difference is that it establishes an association with a label, which is used by the runtime library to unwind the stack.

            -This instruction is used in languages with destructors to ensure that proper +

            This instruction is used in languages with destructors to ensure that proper cleanup is performed in the case of either a longjmp or a thrown exception. Additionally, this is important for implementation of -'catch' clauses in high-level languages that support them.

            +'catch' clauses in high-level languages that support them.

            Example:
            +
               %retval = invoke int %Test(int 15)
                           to label %Continue
                           except label %TestCleanup     ; {int}:retval set
             
            +
          + -


        'unwind' Instruction

          + + +
          Syntax:
          +
             unwind
           
          Overview:
          -The 'unwind' instruction unwinds the stack, continuing control flow at -the first callee in the dynamic call stack which used an The 'unwind' instruction unwinds the stack, continuing control flow +at the first callee in the dynamic call stack which used an invoke instruction to perform the call. This is -primarily used to implement exception handling. +primarily used to implement exception handling.

          Semantics:
          -The 'unwind' intrinsic causes execution of the current function to +

          The 'unwind' intrinsic causes execution of the current function to immediately halt. The dynamic call stack is then searched for the first invoke instruction on the call stack. Once found, execution continues at the "exceptional" destination block specified by the invoke instruction. If there is no invoke instruction in the -dynamic call chain, undefined behavior results. - +dynamic call chain, undefined behavior results.

          +
          -
           -Binary Operations -
          + -Binary operators are used to do most of the computation in a program. They +
          + +

          Binary operators are used to do most of the computation in a program. They require two operands, execute an operation on them, and produce a single value. The result value of a binary operator is not necessarily the same type as its -operands.

          +operands.

          -There are several different binary operators:

          +

          There are several different binary operators:

          +
          -


        'add' Instruction

          + + +
          Syntax:
          +
             <result> = add <ty> <var1>, <var2>   ; yields {ty}:result
           
          Overview:
          -The 'add' instruction returns the sum of its two operands.

          + +

          The 'add' instruction returns the sum of its two operands.

          Arguments:
          -The two arguments to the 'add' instruction must be either integer or floating point values. Both arguments must have identical types.

          + +

          The two arguments to the 'add' instruction must be either integer or floating point +values. Both arguments must have identical types.

          Semantics:
          -The value produced is the integer or floating point sum of the two operands.

          +

          The value produced is the integer or floating point sum of the two +operands.

          Example:
          +
             <result> = add int 4, %var          ; yields {int}:result = 4 + %var
           
          +
          -


        'sub' Instruction

          + + +
          Syntax:
          +
             <result> = sub <ty> <var1>, <var2>   ; yields {ty}:result
           
          Overview:
          -The 'sub' instruction returns the difference of its two operands.

          +

          The 'sub' instruction returns the difference of its two +operands.

          -Note that the 'sub' instruction is used to represent the 'neg' -instruction present in most other intermediate representations.

          +

          Note that the 'sub' instruction is used to represent the +'neg' instruction present in most other intermediate +representations.

          Arguments:
          -The two arguments to the 'sub' instruction must be either The two arguments to the 'sub' instruction must be either integer or floating point -values. Both arguments must have identical types.

          +values. Both arguments must have identical types.

          Semantics:
          -The value produced is the integer or floating point difference of the two -operands.

          +

          The value produced is the integer or floating point difference of the two +operands.

          Example:
          +
             <result> = sub int 4, %var          ; yields {int}:result = 4 - %var
             <result> = sub int 0, %val          ; yields {int}:result = -%var
           
          +
          + -


        'mul' Instruction

          + + +
          Syntax:
          +
             <result> = mul <ty> <var1>, <var2>   ; yields {ty}:result
           
          Overview:
          -The 'mul' instruction returns the product of its two operands.

          + +

          The 'mul' instruction returns the product of its two operands.

          Arguments:
          -The two arguments to the 'mul' instruction must be either integer or floating point values. Both arguments must have identical types.

          -

          Semantics:
          +

          The two arguments to the 'mul' instruction must be either integer or floating point +values. Both arguments must have identical types.

          -The value produced is the integer or floating point product of the two -operands.

          +

          Semantics:
          -There is no signed vs unsigned multiplication. The appropriate action is taken -based on the type of the operand.

          +

          The value produced is the integer or floating point product of the two +operands.

          +

          There is no signed vs unsigned multiplication. The appropriate action is +taken based on the type of the operand.

          Example:
          +
             <result> = mul int 4, %var          ; yields {int}:result = 4 * %var
           
          +
          -


        'div' Instruction

          + + +
          Syntax:
          +
             <result> = div <ty> <var1>, <var2>   ; yields {ty}:result
           
          Overview:
          -The 'div' instruction returns the quotient of its two operands.

          +

          The 'div' instruction returns the quotient of its two operands.

          Arguments:
          -The two arguments to the 'div' instruction must be either The two arguments to the 'div' instruction must be either integer or floating point -values. Both arguments must have identical types.

          +values. Both arguments must have identical types.

          Semantics:
          -The value produced is the integer or floating point quotient of the two -operands.

          +

          The value produced is the integer or floating point quotient of the two +operands.

          Example:
          +
             <result> = div int 4, %var          ; yields {int}:result = 4 / %var
           
          +
          -


        'rem' Instruction

          + + +
          Syntax:
          +
             <result> = rem <ty> <var1>, <var2>   ; yields {ty}:result
           
          Overview:
          -The 'rem' instruction returns the remainder from the division of its two operands.

          + +

          The 'rem' instruction returns the remainder from the division of its +two operands.

          Arguments:
          -The two arguments to the 'rem' instruction must be either integer or floating point values. Both arguments must have identical types.

          + +

          The two arguments to the 'rem' instruction must be either integer or floating point +values. Both arguments must have identical types.

          Semantics:
          -This returns the remainder of a division (where the result has the same -sign as the divisor), not the modulus (where the result has the same sign -as the dividend) of a value. For more information about the difference, see: The Math -Forum.

          +

          This returns the remainder of a division (where the result has the +same sign as the divisor), not the modulus (where the result has the same +sign as the dividend) of a value. For more information about the difference, +see: The Math +Forum.

          Example:
          +
             <result> = rem int 4, %var          ; yields {int}:result = 4 % %var
           
          +
          -


        'setcc' Instructions

          + + +
          Syntax:
          +
             <result> = seteq <ty> <var1>, <var2>   ; yields {bool}:result
             <result> = setne <ty> <var1>, <var2>   ; yields {bool}:result
          @@ -1052,19 +1262,22 @@
             <result> = setge <ty> <var1>, <var2>   ; yields {bool}:result
           
          -
          Overview:
          The 'setcc' family of instructions returns a -boolean value based on a comparison of their two operands.

          +

          Overview:
          + +

          The 'setcc' family of instructions returns a boolean value +based on a comparison of their two operands.

          -
          Arguments:
          The two arguments to the 'setcc' -instructions must be of first class type (it is not -possible to compare 'label's, 'array's, 'structure' -or 'void' values, etc...). Both arguments must have identical -types.

          +

          Arguments:
          + +

          The two arguments to the 'setcc' instructions must be of first class type (it is not possible to compare +'label's, 'array's, 'structure' or 'void' +values, etc...). Both arguments must have identical types.

          Semantics:
          -The 'seteq' instruction yields a true 'bool' value if -both operands are equal.
          +

          The 'seteq' instruction yields a true 'bool' value +if both operands are equal.
          The 'setne' instruction yields a true 'bool' value if both operands are unequal.
          @@ -1079,9 +1292,10 @@ the first operand is less than or equal to the second operand.
          The 'setge' instruction yields a true 'bool' value if -the first operand is greater than or equal to the second operand.

          +the first operand is greater than or equal to the second operand.

          Example:
          +
             <result> = seteq int   4, 5        ; yields {bool}:result = false
             <result> = setne float 4, 5        ; yields {bool}:result = true
          @@ -1091,134 +1305,161 @@
             <result> = setge sbyte 4, 5        ; yields {bool}:result = false
           
          - +
          -
        -
           -Bitwise Binary Operations -
          + + +
          -Bitwise binary operators are used to do various forms of bit-twiddling in a +

          Bitwise binary operators are used to do various forms of bit-twiddling in a program. They are generally very efficient instructions, and can commonly be strength reduced from other instructions. They require two operands, execute an operation on them, and produce a single value. The resulting value of the -bitwise binary operators is always the same type as its first operand.

          +bitwise binary operators is always the same type as its first operand.

          + +
          -


        'and' Instruction

          + + +
          Syntax:
          +
             <result> = and <ty> <var1>, <var2>   ; yields {ty}:result
           
          Overview:
          -The 'and' instruction returns the bitwise logical and of its two operands.

          + +

          The 'and' instruction returns the bitwise logical and of its two +operands.

          Arguments:
          -The two arguments to the 'and' instruction must be The two arguments to the 'and' instruction must be integral values. Both arguments must have identical -types.

          - +types.

          Semantics:
          -The truth table used for the 'and' instruction is:

          +

          The truth table used for the 'and' instruction is:

          -
          +

          +

          +
          -
          In0 In1 Out
          0 0 0
          0 1 0
          1 0 0
          1 1 1

          - +

        +

        Example:
        +
           <result> = and int 4, %var         ; yields {int}:result = 4 & %var
           <result> = and int 15, 40          ; yields {int}:result = 8
           <result> = and int 4, 8            ; yields {int}:result = 0
         
        - +
        -


      'or' Instruction

        + + +
        Syntax:
        +
           <result> = or <ty> <var1>, <var2>   ; yields {ty}:result
         
        -
        Overview:
        The 'or' instruction returns the bitwise logical -inclusive or of its two operands.

        +

        Overview:
        + +

        The 'or' instruction returns the bitwise logical inclusive or of its +two operands.

        Arguments:
        -The two arguments to the 'or' instruction must be The two arguments to the 'or' instruction must be integral values. Both arguments must have identical -types.

        - +types.

        Semantics:
        -The truth table used for the 'or' instruction is:

        +

        The truth table used for the 'or' instruction is:

        -
        +

        +

        -
        In0 In1 Out
        0 0 0
        0 1 1
        1 0 1
        1 1 1

        - + +

        Example:
        +
           <result> = or int 4, %var         ; yields {int}:result = 4 | %var
           <result> = or int 15, 40          ; yields {int}:result = 47
           <result> = or int 4, 8            ; yields {int}:result = 12
         
        +
        -


      'xor' Instruction

        + + +
        Syntax:
        +
           <result> = xor <ty> <var1>, <var2>   ; yields {ty}:result
         
        Overview:
        -The 'xor' instruction returns the bitwise logical exclusive or of its -two operands. The xor is used to implement the "one's complement" -operation, which is the "~" operator in C.

        +

        The 'xor' instruction returns the bitwise logical exclusive or of +its two operands. The xor is used to implement the "one's complement" +operation, which is the "~" operator in C.

        Arguments:
        -The two arguments to the 'xor' instruction must be The two arguments to the 'xor' instruction must be integral values. Both arguments must have identical -types.

        - +types.

        Semantics:
        -The truth table used for the 'xor' instruction is:

        +

        The truth table used for the 'xor' instruction is:

        -
        +

        +

        -
        In0 In1 Out
        0 0 0
        0 1 1
        1 0 1
        1 1 0

        - + +

        Example:
        +
           <result> = xor int 4, %var         ; yields {int}:result = 4 ^ %var
           <result> = xor int 15, 40          ; yields {int}:result = 39
        @@ -1226,61 +1467,78 @@
           <result> = xor int %V, -1          ; yields {int}:result = ~%V
         
        +
        -


      'shl' Instruction

        + + +
        Syntax:
        +
           <result> = shl <ty> <var1>, ubyte <var2>   ; yields {ty}:result
         
        Overview:
        -The 'shl' instruction returns the first operand shifted to the left a -specified number of bits. +

        The 'shl' instruction returns the first operand shifted to the left +a specified number of bits.

        Arguments:
        -The first argument to the 'shl' instruction must be an The first argument to the 'shl' instruction must be an integer type. The second argument must be an -'ubyte' type.

        +'ubyte' type.

        Semantics:
        -The value produced is var1 * 2var2.

        - +

        The value produced is var1 * 2var2.

        Example:
        +
           <result> = shl int 4, ubyte %var   ; yields {int}:result = 4 << %var
           <result> = shl int 4, ubyte 2      ; yields {int}:result = 16
           <result> = shl int 1, ubyte 10     ; yields {int}:result = 1024
         
        +
        -


      'shr' Instruction

        + +
        Syntax:
        +
           <result> = shr <ty> <var1>, ubyte <var2>   ; yields {ty}:result
         
        Overview:
        -The 'shr' instruction returns the first operand shifted to the right a specified number of bits. + +

        The 'shr' instruction returns the first operand shifted to the right +a specified number of bits.

        Arguments:
        -The first argument to the 'shr' instruction must be an integer type. The second argument must be an 'ubyte' type.

        + +

        The first argument to the 'shr' instruction must be an integer type. The second argument must be an +'ubyte' type.

        Semantics:
        -If the first argument is a signed type, the most +

        If the first argument is a signed type, the most significant bit is duplicated in the newly free'd bit positions. If the first -argument is unsigned, zero bits shall fill the empty positions.

        +argument is unsigned, zero bits shall fill the empty positions.

        Example:
        +
           <result> = shr int 4, ubyte %var   ; yields {int}:result = 4 >> %var
           <result> = shr uint 4, ubyte 1     ; yields {uint}:result = 2
        @@ -1289,49 +1547,58 @@
           <result> = shr sbyte -2, ubyte 1   ; yields {sbyte}:result = -1
         
        - - - +
        -
      -
         -Memory Access Operations -


      'malloc' Instruction

        + + +
        Syntax:
        +
           <result> = malloc <type>, uint <NumElements>     ; yields {type*}:result
           <result> = malloc <type>                         ; yields {type*}:result
         
        Overview:
        -The 'malloc' instruction allocates memory from the system heap and returns a pointer to it.

        + +

        The 'malloc' instruction allocates memory from the system heap and +returns a pointer to it.

        Arguments:
        -The the 'malloc' instruction allocates +

        The the 'malloc' instruction allocates sizeof(<type>)*NumElements bytes of memory from the operating system, and returns a pointer of the appropriate type to the program. The second form of the instruction is a shorter version of the first instruction -that defaults to allocating one element.

        +that defaults to allocating one element.

        -'type' must be a sized type.

        +

        'type' must be a sized type.

        Semantics:
        -Memory is allocated using the system "malloc" function, and a pointer -is returned.

        +

        Memory is allocated using the system "malloc" function, and a +pointer is returned.

        Example:
        +
           %array  = malloc [4 x ubyte ]                    ; yields {[%4 x ubyte]*}:array
         
        @@ -1340,29 +1607,35 @@
           %array2 = malloc [12 x ubyte], uint %size        ; yields {[12 x ubyte]*}:array2
         
        +
        -


      'free' Instruction

        + + +
        Syntax:
        +
           free <type> <value>                              ; yields {void}
         
        -
        Overview:
        -The 'free' instruction returns memory back to the unused memory heap, to be reallocated in the future.

        +

        The 'free' instruction returns memory back to the unused memory +heap, to be reallocated in the future.

        Arguments:
        -'value' shall be a pointer value that points to a value that was -allocated with the 'malloc' instruction.

        - +

        'value' shall be a pointer value that points to a value that was +allocated with the 'malloc' instruction.

        Semantics:
        -Access to the memory pointed to by the pointer is not longer defined after this instruction executes.

        +

        Access to the memory pointed to by the pointer is not longer defined after +this instruction executes.

        Example:
        @@ -1370,11 +1643,17 @@
                     free   [4 x ubyte]* %array
         
        +
        -


      'alloca' Instruction

        + + +
        Syntax:
        +
           <result> = alloca <type>, uint <NumElements>  ; yields {type*}:result
           <result> = alloca <type>                      ; yields {type*}:result
        @@ -1382,129 +1661,148 @@
         
         
        Overview:
        -The 'alloca' instruction allocates memory on the current stack frame of -the procedure that is live until the current function returns to its caller.

        +

        The 'alloca' instruction allocates memory on the current stack frame +of the procedure that is live until the current function returns to its +caller.

        Arguments:
        -The the 'alloca' instruction allocates +

        The the 'alloca' instruction allocates sizeof(<type>)*NumElements bytes of memory on the runtime stack, returning a pointer of the appropriate type to the program. The second form of the instruction is a shorter version of the first that defaults to allocating -one element.

        +one element.

        -'type' may be any sized type.

        +

        'type' may be any sized type.

        Semantics:
        -Memory is allocated, a pointer is returned. 'alloca'd memory is +

        Memory is allocated, a pointer is returned. 'alloca'd memory is automatically released when the function returns. The 'alloca' instruction is commonly used to represent automatic variables that must have an address available. When the function returns (either with the ret or invoke -instructions), the memory is reclaimed.

        +instructions), the memory is reclaimed.

        Example:
        +
           %ptr = alloca int                              ; yields {int*}:ptr
           %ptr = alloca int, uint 4                      ; yields {int*}:ptr
         
        +
        -


      'load' Instruction

        + + +
        Syntax:
        +
           <result> = load <ty>* <pointer>
           <result> = volatile load <ty>* <pointer>
         
        Overview:
        -The 'load' instruction is used to read from memory.

        + +

        The 'load' instruction is used to read from memory.

        Arguments:
        -The argument to the 'load' instruction specifies the memory address to -load from. The pointer must point to a first class -type. If the load is marked as volatile then the optimizer is -not allowed to modify the number or order of execution of this load -with other volatile load and store -instructions.

        +

        The argument to the 'load' instruction specifies the memory address +to load from. The pointer must point to a first +class type. If the load is marked as volatile then the +optimizer is not allowed to modify the number or order of execution of this +load with other volatile load and store instructions.

        Semantics:
        -The location of memory pointed to is loaded. +

        The location of memory pointed to is loaded.

        Examples:
        +
           %ptr = alloca int                               ; yields {int*}:ptr
           store int 3, int* %ptr                          ; yields {void}
           %val = load int* %ptr                           ; yields {int}:val = int 3
         
        - - +
        -


      'store' Instruction

        +
        Syntax:
        +
           store <ty> <value>, <ty>* <pointer>                   ; yields {void}
           volatile store <ty> <value>, <ty>* <pointer>                   ; yields {void}
         
        Overview:
        -The 'store' instruction is used to write to memory.

        + +

        The 'store' instruction is used to write to memory.

        Arguments:
        -There are two arguments to the 'store' instruction: a value to store +

        There are two arguments to the 'store' instruction: a value to store and an address to store it into. The type of the '<pointer>' operand must be a pointer to the type of the '<value>' operand. If the store is marked as volatile then the optimizer is not allowed to modify the number or order of execution of this store with other volatile load and store -instructions.

        +instructions.

        + +
        Semantics:
        -
        Semantics:
        The contents of memory are updated to contain -'<value>' at the location specified by the -'<pointer>' operand.

        +

        The contents of memory are updated to contain '<value>' at the +location specified by the '<pointer>' operand.

        Example:
        +
           %ptr = alloca int                               ; yields {int*}:ptr
           store int 3, int* %ptr                          ; yields {void}
           %val = load int* %ptr                           ; yields {int}:val = int 3
         
        - - + -


      'getelementptr' Instruction

        + + +
        Syntax:
        +
           <result> = getelementptr <ty>* <ptrval>{, long <aidx>|, ubyte <sidx>}*
         
        Overview:
        -The 'getelementptr' instruction is used to get the address of a -subelement of an aggregate data structure.

        +

        The 'getelementptr' instruction is used to get the address of a +subelement of an aggregate data structure.

        Arguments:
        -This instruction takes a list of long values and ubyte +

        This instruction takes a list of long values and ubyte constants that indicate what form of addressing to perform. The actual types of the arguments provided depend on the type of the first pointer argument. The 'getelementptr' instruction is used to index down through the type -levels of a structure.

        +levels of a structure.

        -For example, lets consider a C code fragment and how it gets compiled to -LLVM:

        +

        For example, let's consider a C code fragment and how it gets compiled to +LLVM:

         struct RT {
        @@ -1523,7 +1821,7 @@
         }
         
        -The LLVM code generated by the GCC frontend is: +

        The LLVM code generated by the GCC frontend is:

         %RT = type { sbyte, [10 x [20 x int]], sbyte }
        @@ -1537,25 +1835,25 @@
         
         
        Semantics:
        -The index types specified for the 'getelementptr' instruction depend on -the pointer type that is being index into. Pointer and -array types require 'long' values, and The index types specified for the 'getelementptr' instruction depend +on the pointer type that is being index into. Pointer +and array types require 'long' values, and structure types require 'ubyte' -constants.

        +constants.

        -In the example above, the first index is indexing into the '%ST*' type, -which is a pointer, yielding a '%ST' = '{ int, double, %RT }' -type, a structure. The second index indexes into the third element of the -structure, yielding a '%RT' = '{ sbyte, [10 x [20 x int]], sbyte -}' type, another structure. The third index indexes into the second +

        In the example above, the first index is indexing into the '%ST*' +type, which is a pointer, yielding a '%ST' = '{ int, double, %RT +}' type, a structure. The second index indexes into the third element of +the structure, yielding a '%RT' = '{ sbyte, [10 x [20 x int]], +sbyte }' type, another structure. The third index indexes into the second element of the structure, yielding a '[10 x [20 x int]]' type, an array. The two dimensions of the array are subscripted into, yielding an 'int' type. The 'getelementptr' instruction return a pointer -to this element, thus yielding a 'int*' type.

        +to this element, thus yielding a 'int*' type.

        -Note that it is perfectly legal to index partially through a structure, +

        Note that it is perfectly legal to index partially through a structure, returning a pointer to an inner element. Because of this, the LLVM code for the -given testcase is equivalent to:

        +given testcase is equivalent to:

         int* "foo"(%ST* %s) {
        @@ -1568,54 +1866,61 @@
         }
         
        - -
        Example:
        +
           ; yields [12 x ubyte]*:aptr
           %aptr = getelementptr {int, [12 x ubyte]}* %sptr, long 0, ubyte 1
         
        - +
        -
      -
         -Other Operations -
        + -The instructions in this catagory are the "miscellaneous" instructions, which defy better classification.

        +

        +

        The instructions in this catagory are the "miscellaneous" instructions, which +defy better classification.

        + +
        -


      'phi' Instruction

        + + +
        Syntax:
        +
           <result> = phi <ty> [ <val0>, <label0>], ...
         
        Overview:
        -The 'phi' instruction is used to implement the φ node in the SSA -graph representing the function.

        +

        The 'phi' instruction is used to implement the φ node in the SSA +graph representing the function.

        Arguments:
        -The type of the incoming values are specified with the first type field. After -this, the 'phi' instruction takes a list of pairs as arguments, with -one pair for each predecessor basic block of the current block. Only values of -first class type may be used as the value arguments -to the PHI node. Only labels may be used as the label arguments.

        +

        The type of the incoming values are specified with the first type field. +After this, the 'phi' instruction takes a list of pairs as arguments, +with one pair for each predecessor basic block of the current block. Only +values of first class type may be used as the value +arguments to the PHI node. Only labels may be used as the label arguments.

        -There must be no non-phi instructions between the start of a basic block and the -PHI instructions: i.e. PHI instructions must be first in a basic block.

        +

        There must be no non-phi instructions between the start of a basic block and +the PHI instructions: i.e. PHI instructions must be first in a basic block.

        Semantics:
        -At runtime, the 'phi' instruction logically takes on the value +

        At runtime, the 'phi' instruction logically takes on the value specified by the parameter, depending on which basic block we came from in the -last terminator instruction.

        +last terminator instruction.

        Example:
        @@ -1626,222 +1931,253 @@ br label %Loop +
        -


      'cast .. to' Instruction

        + + +
        Syntax:
        +
           <result> = cast <ty> <value> to <ty2>             ; yields ty2
         
        Overview:
        -The 'cast' instruction is used as the primitive means to convert +

        The 'cast' instruction is used as the primitive means to convert integers to floating point, change data type sizes, and break type safety (by -casting pointers).

        +casting pointers).

        Arguments:
        -The 'cast' instruction takes a value to cast, which must be a first +

        The 'cast' instruction takes a value to cast, which must be a first class value, and a type to cast it to, which must also be a first class type.

        +href="#t_firstclass">first class type.

        Semantics:
        -This instruction follows the C rules for explicit casts when determining how the -data being cast must change to fit in its new container.

        +

        This instruction follows the C rules for explicit casts when determining how +the data being cast must change to fit in its new container.

        -When casting to bool, any value that would be considered true in the context of -a C 'if' condition is converted to the boolean 'true' values, -all else are 'false'.

        +

        When casting to bool, any value that would be considered true in the context +of a C 'if' condition is converted to the boolean 'true' +values, all else are 'false'.

        -When extending an integral value from a type of one signness to another (for +

        When extending an integral value from a type of one signness to another (for example 'sbyte' to 'ulong'), the value is sign-extended if the source value is signed, and zero-extended if the source value is unsigned. bool values are always zero extended into either zero or -one.

        +one.

        Example:
        +
           %X = cast int 257 to ubyte              ; yields ubyte:1
           %Y = cast int 123 to bool               ; yields bool:true
         
        - +
        -


      'call' Instruction

        + + +
        Syntax:
        +
           <result> = call <ty>* <fnptrval>(<param list>)
         
        Overview:
        -The 'call' instruction represents a simple function call.

        +

        The 'call' instruction represents a simple function call.

        Arguments:
        -This instruction requires several arguments:

        -

          +

          This instruction requires several arguments:

          -
        1. 'ty': shall be the signature of the pointer to function value being -invoked. The argument types must match the types implied by this signature.

          +

            -
          1. 'fnptrval': An LLVM value containing a pointer to a function to be -invoked. In most cases, this is a direct function invocation, but indirect -calls are just as possible, calling an arbitrary pointer to function -values.

            +

          2. 'ty': shall be the signature of the pointer to function value + being invoked. The argument types must match the types implied by this + signature.

          3. + +
          4. 'fnptrval': An LLVM value containing a pointer to a function + to be invoked. In most cases, this is a direct function invocation, but + indirect calls are just as possible, calling an arbitrary pointer to + function values.

          5. + +
          6. 'function args': argument list whose types match the function + signature argument types. If the function signature indicates the function + accepts a variable number of arguments, the extra arguments can be + specified.

          7. -
          8. 'function args': argument list whose types match the function -signature argument types. If the function signature indicates the function -accepts a variable number of arguments, the extra arguments can be specified.
          Semantics:
          -The 'call' instruction is used to cause control flow to transfer to a -specified function, with its incoming arguments bound to the specified values. +

          The 'call' instruction is used to cause control flow to transfer to +a specified function, with its incoming arguments bound to the specified values. Upon a 'ret' instruction in the called function, control flow continues with the instruction after the function call, and the return value of the function is bound to the result argument. This is a simpler -case of the invoke instruction.

          +case of the invoke instruction.

          Example:
          +
             %retval = call int %test(int %argc)
             call int(sbyte*, ...) *%printf(sbyte* %msg, int 12, sbyte 42);
          -
           
          +
        + -


      'vanext' Instruction

        + + +
        Syntax:
        +
           <resultarglist> = vanext <va_list> <arglist>, <argty>
         
        Overview:
        -The 'vanext' instruction is used to access arguments passed through +

        The 'vanext' instruction is used to access arguments passed through the "variable argument" area of a function call. It is used to implement the -va_arg macro in C.

        +va_arg macro in C.

        Arguments:
        -This instruction takes a valist value and the type of the argument. It -returns another valist. +

        This instruction takes a valist value and the type of the argument. +It returns another valist.

        Semantics:
        -The 'vanext' instruction advances the specified valist past +

        The 'vanext' instruction advances the specified valist past an argument of the specified type. In conjunction with the vaarg instruction, it is used to implement the va_arg macro available in C. For more information, see the variable -argument handling Intrinsic Functions.

        +argument handling Intrinsic Functions.

        -It is legal for this instruction to be called in a function which does not take -a variable number of arguments, for example, the vfprintf function.

        +

        It is legal for this instruction to be called in a function which does not +take a variable number of arguments, for example, the vfprintf +function.

        -vanext is an LLVM instruction instead of an vanext is an LLVM instruction instead of an intrinsic function because it takes an type as an argument.

        Example:
        -See the variable argument processing section.

        - +

        See the variable argument processing section.

        +
        -


      'vaarg' Instruction

        + + +
        Syntax:
        +
           <resultval> = vaarg <va_list> <arglist>, <argty>
         
        Overview:
        -The 'vaarg' instruction is used to access arguments passed through +

        The 'vaarg' instruction is used to access arguments passed through the "variable argument" area of a function call. It is used to implement the -va_arg macro in C.

        +va_arg macro in C.

        Arguments:
        -This instruction takes a valist value and the type of the argument. It -returns a value of the specified argument type. +

        This instruction takes a valist value and the type of the argument. +It returns a value of the specified argument type.

        Semantics:
        -The 'vaarg' instruction loads an argument of the specified type from +

        The 'vaarg' instruction loads an argument of the specified type from the specified va_list. In conjunction with the vanext instruction, it is used to implement the va_arg macro available in C. For more information, see the variable -argument handling Intrinsic Functions.

        +argument handling Intrinsic Functions.

        -It is legal for this instruction to be called in a function which does not take -a variable number of arguments, for example, the vfprintf function.

        +

        It is legal for this instruction to be called in a function which does not +take a variable number of arguments, for example, the vfprintf +function.

        -vaarg is an LLVM instruction instead of an vaarg is an LLVM instruction instead of an intrinsic function because it takes an type as an argument.

        Example:
        -See the variable argument processing section.

        - - - +

        See the variable argument processing section.

        +
        -
      -
      -Intrinsic Functions -
        + -LLVM supports the notion of an "intrinsic function". These functions have well -known names and semantics, and are required to follow certain restrictions. +
        + +

        LLVM supports the notion of an "intrinsic function". These functions have +well known names and semantics, and are required to follow certain restrictions. Overall, these instructions represent an extension mechanism for the LLVM language that does not require changing all of the transformations in LLVM to -add to the language (or the bytecode reader/writer, the parser, etc...).

        +add to the language (or the bytecode reader/writer, the parser, etc...).

        -Intrinsic function names must all start with an "llvm." prefix, this +

        Intrinsic function names must all start with an "llvm." prefix, this prefix is reserved in LLVM for intrinsic names, thus functions may not be named this. Intrinsic functions must always be external functions: you cannot define the body of intrinsic functions. Intrinsic functions may only be used in call or invoke instructions: it is illegal to take the address of an intrinsic function. Additionally, because intrinsic functions are part of the LLVM -language, it is required that they all be documented here if any are added.

        +language, it is required that they all be documented here if any are added.

        -Unless an intrinsic function is target-specific, there must be a lowering pass -to eliminate the intrinsic or all backends must support the intrinsic -function.

        +

        Unless an intrinsic function is target-specific, there must be a lowering +pass to eliminate the intrinsic or all backends must support the intrinsic +function.

        +
        -
      -
         -Variable Argument Handling Intrinsics -
        + -Variable argument support is defined in LLVM with the + +

        Variable argument support is defined in LLVM with the vanext instruction and these three intrinsic functions. These functions are related to the similarly named macros defined in -the <stdarg.h> header file.

        +the <stdarg.h> header file.

        -All of these functions operate on arguments that use a target-specific value +

        All of these functions operate on arguments that use a target-specific value type "va_list". The LLVM assembly language reference manual does not define what this type is, so all transformations should be prepared to handle -intrinsics with any type used.

        +intrinsics with any type used.

        -This example shows how the vanext instruction -and the variable argument handling intrinsic functions are used.

        +

        This example shows how the vanext +instruction and the variable argument handling intrinsic functions are used.

         int %test(int %X, ...) {
        @@ -1864,100 +2200,115 @@
         }
         
        + + -


      'llvm.va_start' Intrinsic

        + + +
        Syntax:
        +
           call va_list ()* %llvm.va_start()
         
        Overview:
        -The 'llvm.va_start' intrinsic returns a new <arglist> -for subsequent use by the variable argument intrinsics.

        +

        The 'llvm.va_start' intrinsic returns a new <arglist> +for subsequent use by the variable argument intrinsics.

        Semantics:
        -The 'llvm.va_start' intrinsic works just like the va_start +

        The 'llvm.va_start' intrinsic works just like the va_start macro available in C. In a target-dependent way, it initializes and returns a va_list element, so that the next vaarg will produce the first variable argument passed to the function. Unlike the C va_start macro, this intrinsic does not need to know the last argument of the function, the -compiler can figure that out.

        +compiler can figure that out.

        -Note that this intrinsic function is only legal to be called from within the -body of a variable argument function.

        +

        Note that this intrinsic function is only legal to be called from within the +body of a variable argument function.

        +
        -


      'llvm.va_end' Intrinsic


      'llvm.va_copy' Intrinsic

        + + +
        Syntax:
        +
           call va_list (va_list)* %llvm.va_copy(va_list <destarglist>)
         
        Overview:
        -The 'llvm.va_copy' intrinsic copies the current argument position from -the source argument list to the destination argument list.

        +

        The 'llvm.va_copy' intrinsic copies the current argument position +from the source argument list to the destination argument list.

        Arguments:
        -The argument is the va_list to copy. +

        The argument is the va_list to copy.

        Semantics:
        -The 'llvm.va_copy' intrinsic works just like the va_copy macro -available in C. In a target-dependent way, it copies the source +

        The 'llvm.va_copy' intrinsic works just like the va_copy +macro available in C. In a target-dependent way, it copies the source va_list element into the returned list. This intrinsic is necessary because the llvm.va_start intrinsic may be -arbitrarily complex and require memory allocation, for example.

        +arbitrarily complex and require memory allocation, for example.

        +
        -
      - -
      - -
      Chris Lattner
      -The LLVM Compiler Infrastructure -
      - - -Last modified: Wed Oct 29 19:30:46 CST 2003 - -
      - + + + + From lattner at cs.uiuc.edu Fri Nov 7 22:30:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Nov 7 22:30:01 2003 Subject: [llvm-commits] CVS: llvm-www/releases/1.0/docs/ReleaseNotes.html Message-ID: <200311080429.WAA08595@zion.cs.uiuc.edu> Changes in directory llvm-www/releases/1.0/docs: ReleaseNotes.html updated: 1.23 -> 1.24 --- Log message: Update --- Diffs of the changes: (+7 -1) Index: llvm-www/releases/1.0/docs/ReleaseNotes.html diff -u llvm-www/releases/1.0/docs/ReleaseNotes.html:1.23 llvm-www/releases/1.0/docs/ReleaseNotes.html:1.24 --- llvm-www/releases/1.0/docs/ReleaseNotes.html:1.23 Fri Nov 7 16:20:17 2003 +++ llvm-www/releases/1.0/docs/ReleaseNotes.html Fri Nov 7 22:29:18 2003 @@ -167,6 +167,12 @@ vaarg instruction

      +

    Missing features in 1.0, implemented in 1.1:Bugs in 1.0 fixed in 1.1:

    • [inliner] Inlining invoke with PHI in unwind target is broken
    • @@ -482,6 +488,6 @@ Maintained By: The LLVM Team
      -Last modified: Fri Nov 7 16:19:42 CST 2003 +Last modified: Fri Nov 7 22:27:02 CST 2003 From lattner at cs.uiuc.edu Fri Nov 7 22:30:09 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Nov 7 22:30:09 2003 Subject: [llvm-commits] CVS: llvm/docs/ReleaseNotes.html Message-ID: <200311080429.WAA08468@zion.cs.uiuc.edu> Changes in directory llvm/docs: ReleaseNotes.html updated: 1.32 -> 1.33 --- Log message: Add news from brian --- Diffs of the changes: (+22 -7) Index: llvm/docs/ReleaseNotes.html diff -u llvm/docs/ReleaseNotes.html:1.32 llvm/docs/ReleaseNotes.html:1.33 --- llvm/docs/ReleaseNotes.html:1.32 Thu Nov 6 22:46:56 2003 +++ llvm/docs/ReleaseNotes.html Fri Nov 7 22:28:55 2003 @@ -65,16 +65,34 @@ release implements the following new features:

        -
      1. A new LLVM profiler, similar to gprof is available
      2. -
      3. The LLVM C/C++ front-end now compiles on Mac OSX!
      4. +
      5. A new LLVM profiler, similar to gprof is available
      6. + +

      7. LLVM and the C/C++ front-end now compile on Mac OSX! Mac OSX users can now +explore the LLVM optimizer with the C backend (note that LLVM requires GCC 3.3 +on Mac OSX).
      8. + +

      + +In this release, the following missing features were implemented:

      + +

        +
      1. The interpreter does not support +invoke or unwind

      In this release, the following Quality of Implementation issues were fixed:

        -
      1. C++ front-end is not generating linkonce linkage type when it can
      2. + +
      3. C++ front-end is not generating +linkonce linkage type when it can
      4. + +
      5. C front-end doesn't emit +getelementptr for address of array element
      6. +

      + In this release, the following bugs in the previous release were fixed:

        @@ -159,9 +177,6 @@
      1. Linking in static archive files (.a files) is very slow (there is no symbol table in the archive).

        -

      2. Interpreter does not support invoke -or unwind.

        -

      3. LLVM cannot handle structures with more than 256 elements.

        @@ -410,6 +425,6 @@ Maintained By: The LLVM Team
        -Last modified: Thu Nov 6 13:21:28 CST 2003 +Last modified: Fri Nov 7 22:26:24 CST 2003 From lattner at cs.uiuc.edu Fri Nov 7 23:14:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Nov 7 23:14:00 2003 Subject: [llvm-commits] CVS: llvm/runtime/GCCLibraries/crtend/Exception.cpp Message-ID: <200311080513.XAA09161@zion.cs.uiuc.edu> Changes in directory llvm/runtime/GCCLibraries/crtend: Exception.cpp updated: 1.1 -> 1.2 --- Log message: Fix wierd problems linking C programs which look for symbols in libstdc++. This was due to the 'assert' macro expanding into a function call on some platforms which could throw. The C++ compiler then added checks for the exception specifications in these functions, which pulled in the C++ runtime. This was bad, and the assertions can never fire (the library is now debugged) so just remove them. --- Diffs of the changes: (+0 -3) Index: llvm/runtime/GCCLibraries/crtend/Exception.cpp diff -u llvm/runtime/GCCLibraries/crtend/Exception.cpp:1.1 llvm/runtime/GCCLibraries/crtend/Exception.cpp:1.2 --- llvm/runtime/GCCLibraries/crtend/Exception.cpp:1.1 Sat Aug 30 18:17:51 2003 +++ llvm/runtime/GCCLibraries/crtend/Exception.cpp Fri Nov 7 23:13:40 2003 @@ -6,7 +6,6 @@ //===----------------------------------------------------------------------===// #include "Exception.h" -#include // Thread local state for exception handling. FIXME: This should really be made // thread-local! @@ -26,7 +25,6 @@ // returns a pointer to the exception area data. // void *__llvm_eh_current_uncaught_exception_type(unsigned HandlerType) throw() { - assert(UncaughtExceptionStack && "No uncaught exception!"); if (UncaughtExceptionStack->ExceptionType == HandlerType) return UncaughtExceptionStack+1; return 0; @@ -44,7 +42,6 @@ // __llvm_eh_get_uncaught_exception - Returns the current uncaught exception. // There must be an uncaught exception for this to work! llvm_exception *__llvm_eh_get_uncaught_exception() throw() { - assert(UncaughtExceptionStack && "There are no uncaught exceptions!?!?"); return UncaughtExceptionStack; } From lattner at cs.uiuc.edu Fri Nov 7 23:20:00 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Nov 7 23:20:00 2003 Subject: [llvm-commits] CVS: llvm/docs/ReleaseNotes.html Message-ID: <200311080519.XAA09372@zion.cs.uiuc.edu> Changes in directory llvm/docs: ReleaseNotes.html updated: 1.33 -> 1.34 --- Log message: sjlj bug --- Diffs of the changes: (+1 -0) Index: llvm/docs/ReleaseNotes.html diff -u llvm/docs/ReleaseNotes.html:1.33 llvm/docs/ReleaseNotes.html:1.34 --- llvm/docs/ReleaseNotes.html:1.33 Fri Nov 7 22:28:55 2003 +++ llvm/docs/ReleaseNotes.html Fri Nov 7 23:18:50 2003 @@ -122,6 +122,7 @@

      4. [lowersetjmp] Lowersetjmp pass breaks dominance properties!
      5. llvm-gcc tries to add bools
      6. [buildscripts] Building into objdir with .o in it fails
      7. +
      8. [setjmp/longjmp] Linking C programs which use setjmp/longjmp sometimes fail with references to the C++ runtime library!

      At this time, LLVM is known to work properly with SPEC CPU 2000, the Olden From lattner at cs.uiuc.edu Fri Nov 7 23:21:01 2003 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri Nov 7 23:21:01 2003 Subject: [llvm-commits] CVS: llvm-www/releases/1.0/docs/ReleaseNotes.html Message-ID: <200311080520.XAA09503@zion.cs.uiuc.edu> Changes in directory llvm-www/releases/1.0/docs: ReleaseNotes.html updated: 1.24 -> 1.25 --- Log message: New bug --- Diffs of the changes: (+3 -0) Index: llvm-www/releases/1.0/docs/ReleaseNotes.html diff -u llvm-www/releases/1.0/docs/ReleaseNotes.html:1.24 llvm-www/releases/1.0/docs/ReleaseNotes.html:1.25 --- llvm-www/releases/1.0/docs/ReleaseNotes.html:1.24 Fri Nov 7 22:29:18 2003 +++ llvm-www/releases/1.0/docs/ReleaseNotes.html Fri Nov 7 23:20:14 2003 @@ -200,6 +200,9 @@

    • [buildscripts] Building into objdir with .o in it fails
    • +

    • [setjmp/longjmp] Linking C programs which use setjmp/longjmp sometimes fail with references to the C++ runtime library!
    • + +


    Known problems with the C front-end