From lattner at cs.uiuc.edu Mon May 10 00:11:04 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon May 10 00:11:04 2004 Subject: [llvm-commits] CVS: llvm/test/Regression/CodeGen/Generic/2004-05-09-LiveVarPartialRegister.llx Message-ID: <200405100511.AAA25472@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/CodeGen/Generic: 2004-05-09-LiveVarPartialRegister.llx added (r1.1) --- Log message: Testcase for PR337: http://llvm.cs.uiuc.edu/PR337 , which was reduced by Reid Spencer. --- Diffs of the changes: (+15 -0) Index: llvm/test/Regression/CodeGen/Generic/2004-05-09-LiveVarPartialRegister.llx diff -c /dev/null llvm/test/Regression/CodeGen/Generic/2004-05-09-LiveVarPartialRegister.llx:1.1 *** /dev/null Mon May 10 00:11:34 2004 --- llvm/test/Regression/CodeGen/Generic/2004-05-09-LiveVarPartialRegister.llx Mon May 10 00:11:24 2004 *************** *** 0 **** --- 1,15 ---- + ; RUN: llvm-as < %s | lli + + %global_long_1 = linkonce global long 7 + %global_long_2 = linkonce global long 49 + + implementation ; Functions: + + int %main() { + %l1 = load long* %global_long_1 + %l2 = load long* %global_long_2 + %cond = setle long %l1, %l2 + %cast2 = cast bool %cond to int + %RV = sub int 1, %cast2 + ret int %RV + } From lattner at cs.uiuc.edu Mon May 10 00:13:03 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon May 10 00:13:03 2004 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/LiveVariables.cpp Message-ID: <200405100512.AAA25489@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: LiveVariables.cpp updated: 1.30 -> 1.31 --- Log message: Patch to fix PR337: http://llvm.cs.uiuc.edu/PR337 . Make sure to mark all aliased physical registers as used when we see a read of a register. This is important in cases like: AL = ... AH = ... = AX The read of AX must make both the AL and AH defs live until the use. --- Diffs of the changes: (+8 -3) Index: llvm/lib/CodeGen/LiveVariables.cpp diff -u llvm/lib/CodeGen/LiveVariables.cpp:1.30 llvm/lib/CodeGen/LiveVariables.cpp:1.31 --- llvm/lib/CodeGen/LiveVariables.cpp:1.30 Sat May 1 16:24:24 2004 +++ llvm/lib/CodeGen/LiveVariables.cpp Mon May 10 00:12:43 2004 @@ -126,6 +126,12 @@ void LiveVariables::HandlePhysRegUse(unsigned Reg, MachineInstr *MI) { PhysRegInfo[Reg] = MI; PhysRegUsed[Reg] = true; + + for (const unsigned *AliasSet = RegInfo->getAliasSet(Reg); + unsigned Alias = *AliasSet; ++AliasSet) { + PhysRegInfo[Alias] = MI; + PhysRegUsed[Alias] = true; + } } void LiveVariables::HandlePhysRegDef(unsigned Reg, MachineInstr *MI) { @@ -140,11 +146,10 @@ PhysRegUsed[Reg] = false; for (const unsigned *AliasSet = RegInfo->getAliasSet(Reg); - *AliasSet; ++AliasSet) { - unsigned Alias = *AliasSet; + unsigned Alias = *AliasSet; ++AliasSet) { if (MachineInstr *LastUse = PhysRegInfo[Alias]) { if (PhysRegUsed[Alias]) - RegistersKilled.insert(std::make_pair(LastUse, Alias)); + RegistersKilled.insert(std::make_pair(LastUse, Alias)); else RegistersDead.insert(std::make_pair(LastUse, Alias)); } From lattner at cs.uiuc.edu Mon May 10 09:28:01 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon May 10 09:28:01 2004 Subject: [llvm-commits] CVS: llvm/docs/ReleaseNotes.html Message-ID: <200405101428.JAA00718@zion.cs.uiuc.edu> Changes in directory llvm/docs: ReleaseNotes.html updated: 1.177 -> 1.178 --- Log message: Bug fixed --- Diffs of the changes: (+2 -1) Index: llvm/docs/ReleaseNotes.html diff -u llvm/docs/ReleaseNotes.html:1.177 llvm/docs/ReleaseNotes.html:1.178 --- llvm/docs/ReleaseNotes.html:1.177 Sun May 9 18:32:39 2004 +++ llvm/docs/ReleaseNotes.html Mon May 10 09:28:09 2004 @@ -211,6 +211,7 @@
  • [adce] Crash handling unreachable code that unwinds
  • [sparc] LLC can't emit 2 functions of the same name, both having constant pools
  • +
  • [livevar] Live variables missed physical register use of aliased definition
  • Bugs in the C/C++ front-end:

    @@ -643,7 +644,7 @@ src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01!" /> The LLVM Compiler Infrastructure
    - Last modified: $Date: 2004/05/09 23:32:39 $ + Last modified: $Date: 2004/05/10 14:28:09 $ From lattner at cs.uiuc.edu Mon May 10 09:29:01 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon May 10 09:29:01 2004 Subject: [llvm-commits] CVS: llvm-www/releases/1.2/docs/ReleaseNotes.html Message-ID: <200405101429.JAA01346@zion.cs.uiuc.edu> Changes in directory llvm-www/releases/1.2/docs: ReleaseNotes.html updated: 1.15 -> 1.16 --- Log message: Bug found --- Diffs of the changes: (+2 -1) Index: llvm-www/releases/1.2/docs/ReleaseNotes.html diff -u llvm-www/releases/1.2/docs/ReleaseNotes.html:1.15 llvm-www/releases/1.2/docs/ReleaseNotes.html:1.16 --- llvm-www/releases/1.2/docs/ReleaseNotes.html:1.15 Fri May 7 13:40:52 2004 +++ llvm-www/releases/1.2/docs/ReleaseNotes.html Mon May 10 09:29:17 2004 @@ -608,6 +608,7 @@
  • [X86] JIT miscompiles unsigned short to floating point cast
  • [sparc] LLC can't emit 2 fns of same name, both w/ constant pools
  • +
  • [livevar] Live variables missed physical register use of aliased definition
  • @@ -682,7 +683,7 @@ src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01!" /> The LLVM Compiler Infrastructure
    - Last modified: $Date: 2004/05/07 18:40:52 $ + Last modified: $Date: 2004/05/10 14:29:17 $ From lattner at cs.uiuc.edu Mon May 10 10:17:27 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon May 10 10:17:27 2004 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Message-ID: <200405101516.KAA01991@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.249 -> 1.250 --- Log message: Fix a fairly serious pessimizaion that was preventing us from efficiently compiling things like 'add long %X, 1'. The problem is that we were switching the order of the operands for longs even though we can't fold them yet. --- Diffs of the changes: (+3 -2) Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.249 llvm/lib/Target/X86/InstSelectSimple.cpp:1.250 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.249 Sun May 9 18:16:33 2004 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Mon May 10 10:15:55 2004 @@ -1863,13 +1863,14 @@ unsigned DestReg = getReg(B); MachineBasicBlock::iterator MI = BB->end(); Value *Op0 = B.getOperand(0), *Op1 = B.getOperand(1); + unsigned Class = getClassB(B.getType()); // Special case: op Reg, load [mem] - if (isa(Op0) && !isa(Op1)) + if (isa(Op0) && !isa(Op1) && Class != cLong && + isSafeToFoldLoadIntoInstruction(*cast(Op0), B)) if (!B.swapOperands()) std::swap(Op0, Op1); // Make sure any loads are in the RHS. - unsigned Class = getClassB(B.getType()); if (isa(Op1) && Class != cLong && isSafeToFoldLoadIntoInstruction(*cast(Op1), B)) { From lattner at cs.uiuc.edu Mon May 10 13:47:03 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon May 10 13:47:03 2004 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/PHIElimination.cpp Message-ID: <200405101847.NAA09145@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: PHIElimination.cpp updated: 1.22 -> 1.23 --- Log message: Now that we use an ilist of machine instructions, iterators are more robust than before. Because this is the case, we can compute the first non-phi instruction once when de-phi'ing a block. This shaves ~4s off of phielimination of _Z7yyparsev in kimwitu++ from 109s -> 105s. There are still much more important gains to come. --- Diffs of the changes: (+8 -5) Index: llvm/lib/CodeGen/PHIElimination.cpp diff -u llvm/lib/CodeGen/PHIElimination.cpp:1.22 llvm/lib/CodeGen/PHIElimination.cpp:1.23 --- llvm/lib/CodeGen/PHIElimination.cpp:1.22 Sat May 1 16:24:39 2004 +++ llvm/lib/CodeGen/PHIElimination.cpp Mon May 10 13:47:18 2004 @@ -68,6 +68,13 @@ const TargetInstrInfo &MII = MF.getTarget().getInstrInfo(); const MRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo(); + // Get an iterator to the first instruction after the last PHI node (this may + // allso be the end of the basic block). + MachineBasicBlock::iterator AfterPHIsIt = MBB.begin(); + while (AfterPHIsIt != MBB.end() && + AfterPHIsIt->getOpcode() == TargetInstrInfo::PHI) + ++AfterPHIsIt; // Skip over all of the PHI nodes... + while (MBB.front().getOpcode() == TargetInstrInfo::PHI) { // Unlink the PHI node from the basic block... but don't delete the PHI yet MachineInstr *MI = MBB.remove(MBB.begin()); @@ -85,15 +92,11 @@ // after any remaining phi nodes) which copies the new incoming register // into the phi node destination. // - MachineBasicBlock::iterator AfterPHIsIt = MBB.begin(); - while (AfterPHIsIt != MBB.end() && - AfterPHIsIt->getOpcode() == TargetInstrInfo::PHI) - ++AfterPHIsIt; // Skip over all of the PHI nodes... RegInfo->copyRegToReg(MBB, AfterPHIsIt, DestReg, IncomingReg, RC); // Update live variable information if there is any... if (LV) { - MachineInstr *PHICopy = --AfterPHIsIt; + MachineInstr *PHICopy = prior(AfterPHIsIt); // Add information to LiveVariables to know that the incoming value is // killed. Note that because the value is defined in several places (once From lattner at cs.uiuc.edu Mon May 10 14:06:02 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon May 10 14:06:02 2004 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/PHIElimination.cpp Message-ID: <200405101906.OAA10135@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: PHIElimination.cpp updated: 1.23 -> 1.24 --- Log message: Use a new VRegPHIUseCount to compute uses of PHI values by other phi values in the basic block being processed. This fixes PhiElimination on kimwitu++ from taking 105s to taking a much more reasonable 0.6s (in a debug build). --- Diffs of the changes: (+21 -14) Index: llvm/lib/CodeGen/PHIElimination.cpp diff -u llvm/lib/CodeGen/PHIElimination.cpp:1.23 llvm/lib/CodeGen/PHIElimination.cpp:1.24 --- llvm/lib/CodeGen/PHIElimination.cpp:1.23 Mon May 10 13:47:18 2004 +++ llvm/lib/CodeGen/PHIElimination.cpp Mon May 10 14:06:37 2004 @@ -68,12 +68,21 @@ const TargetInstrInfo &MII = MF.getTarget().getInstrInfo(); const MRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo(); + // VRegPHIUseCount - Keep track of the number of times each virtual register + // is used by PHI nodes in this block. + std::map VRegPHIUseCount; + // Get an iterator to the first instruction after the last PHI node (this may - // allso be the end of the basic block). + // allso be the end of the basic block). While we are scanning the PHIs, + // populate the VRegPHIUseCount map. MachineBasicBlock::iterator AfterPHIsIt = MBB.begin(); while (AfterPHIsIt != MBB.end() && - AfterPHIsIt->getOpcode() == TargetInstrInfo::PHI) + AfterPHIsIt->getOpcode() == TargetInstrInfo::PHI) { + MachineInstr *PHI = AfterPHIsIt; + for (unsigned i = 1, e = PHI->getNumOperands(); i < e; i += 2) + VRegPHIUseCount[PHI->getOperand(i).getReg()]++; ++AfterPHIsIt; // Skip over all of the PHI nodes... + } while (MBB.front().getOpcode() == TargetInstrInfo::PHI) { // Unlink the PHI node from the basic block... but don't delete the PHI yet @@ -134,6 +143,11 @@ } } + // Adjust the VRegPHIUseCount map to account for the removal of this PHI + // node. + for (unsigned i = 1; i != MI->getNumOperands(); i += 2) + VRegPHIUseCount[MI->getOperand(i).getReg()]--; + // Now loop over all of the incoming arguments, changing them to copy into // the IncomingReg register in the corresponding predecessor basic block. // @@ -217,18 +231,11 @@ } // Is it used by any PHI instructions in this block? - if (ValueIsLive) break; - - // Loop over all of the PHIs in this successor, checking to see if - // the register is being used... - for (MachineBasicBlock::iterator BBI = MBB->begin(), E=MBB->end(); - BBI != E && BBI->getOpcode() == TargetInstrInfo::PHI; - ++BBI) - for (unsigned i = 1, e = BBI->getNumOperands(); i < e; i += 2) - if (BBI->getOperand(i).getReg() == SrcReg) { - ValueIsLive = true; - break; - } + if (!ValueIsLive) { + std::map::iterator I = + VRegPHIUseCount.find(SrcReg); + ValueIsLive = I != VRegPHIUseCount.end() && I->second; + } } // Okay, if we now know that the value is not live out of the block, From lattner at cs.uiuc.edu Mon May 10 14:17:02 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon May 10 14:17:02 2004 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/PHIElimination.cpp Message-ID: <200405101917.OAA12131@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: PHIElimination.cpp updated: 1.24 -> 1.25 --- Log message: Switch this from using an std::map to using a DenseMap. This speeds up phi-elimination from 0.6 to 0.54s on kc++. --- Diffs of the changes: (+5 -6) Index: llvm/lib/CodeGen/PHIElimination.cpp diff -u llvm/lib/CodeGen/PHIElimination.cpp:1.24 llvm/lib/CodeGen/PHIElimination.cpp:1.25 --- llvm/lib/CodeGen/PHIElimination.cpp:1.24 Mon May 10 14:06:37 2004 +++ llvm/lib/CodeGen/PHIElimination.cpp Mon May 10 14:17:36 2004 @@ -20,6 +20,7 @@ #include "llvm/CodeGen/LiveVariables.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" +#include "Support/DenseMap.h" #include "Support/STLExtras.h" using namespace llvm; @@ -70,7 +71,8 @@ // VRegPHIUseCount - Keep track of the number of times each virtual register // is used by PHI nodes in this block. - std::map VRegPHIUseCount; + DenseMap VRegPHIUseCount; + VRegPHIUseCount.grow(MF.getSSARegMap()->getLastVirtReg()); // Get an iterator to the first instruction after the last PHI node (this may // allso be the end of the basic block). While we are scanning the PHIs, @@ -231,11 +233,8 @@ } // Is it used by any PHI instructions in this block? - if (!ValueIsLive) { - std::map::iterator I = - VRegPHIUseCount.find(SrcReg); - ValueIsLive = I != VRegPHIUseCount.end() && I->second; - } + if (!ValueIsLive) + ValueIsLive = VRegPHIUseCount[SrcReg] != 0; } // Okay, if we now know that the value is not live out of the block, From gaeke at cs.uiuc.edu Mon May 10 16:07:03 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Mon May 10 16:07:03 2004 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp Message-ID: <200405102106.QAA22542@seraph.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: UnpackTraceFunction.cpp updated: 1.59 -> 1.60 --- Log message: Fix problems with stack pointer oddness (literally). Simplify code by using the new SparcV9:: names for the unified register numbers. Re-enable epilog rewriting. Restore stack pointer before returning to the MatrixFn. --- Diffs of the changes: (+20 -33) Index: reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp diff -u reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.59 reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.60 --- reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp:1.59 Wed Apr 28 12:15:30 2004 +++ reopt/lib/LightWtProfiling/UnpackTraceFunction.cpp Mon May 10 16:06:20 2004 @@ -222,27 +222,17 @@ // only put %fsr in the set, not the floatcc regs which were actually used. // If the intcc regs are used, then we only put %ccr in the // set, not the individual intcc regs. - if (floatCCRegSeen) { - unsigned fsrReg = TRI.getUnifiedRegNum(SparcV9RegInfo::SpecialRegClassID, - SparcV9SpecialRegClass::fsr); - regsUsed.insert (fsrReg); - } - if (intCCRegSeen) { - unsigned ccrReg = TRI.getUnifiedRegNum(SparcV9RegInfo::IntCCRegClassID, - SparcV9IntCCRegClass::ccr); - regsUsed.insert (ccrReg); - } + if (floatCCRegSeen) + regsUsed.insert (SparcV9::fsr); + if (intCCRegSeen) + regsUsed.insert (SparcV9::ccr); } void UnpackTraceFunction::rewriteProlog (MachineFunction &MF, MachineBasicBlock &E) { const TargetRegInfo &TRI = TM->getRegInfo (); - static const unsigned -fp = TRI.getUnifiedRegNum(SparcV9RegInfo::IntRegClassID,SparcV9IntRegClass::i6), -sp = TRI.getUnifiedRegNum(SparcV9RegInfo::IntRegClassID,SparcV9IntRegClass::o6), -g0 = TRI.getUnifiedRegNum(SparcV9RegInfo::IntRegClassID,SparcV9IntRegClass::g0), -g1 = TRI.getUnifiedRegNum(SparcV9RegInfo::IntRegClassID,SparcV9IntRegClass::g1), -g2 = TRI.getUnifiedRegNum(SparcV9RegInfo::IntRegClassID,SparcV9IntRegClass::g2); + static const unsigned fp = SparcV9::i6, sp = SparcV9::o6, g0 = SparcV9::g0, + g1 = SparcV9::g1, g2 = SparcV9::g2; // UTF prolog: start out by clearing everything out of the entry basic block // (FIXME: may not work once we start doing optimizations!!! We will probably @@ -265,8 +255,8 @@ e = regsUsed.end (); i != e; ++i) { std::cerr << *i << " "; }); DEBUG(std::cerr << " )\n"); - // 2. Get some stack space: (Stack Frame Size + Space for Regs). - int Size = (stackSize + 104 * 8); + // 2. Get some stack space: (Stack Frame Size + Slop + Space for Regs). + int Size = (stackSize + 176 + 104 * 8); E.push_back (BuildMI (V9::ADDi, 3).addMReg (sp).addSImm (-Size).addMReg (sp, MachineOperand::Def)); @@ -290,7 +280,7 @@ << " (" << RegClassStrings[TRI.getRegClassIDOfRegType(RegType)] << ")\n"); - TRI.cpReg2MemMI (mvec, R, sp, stackSize + R * 8, RegType, g2); + TRI.cpReg2MemMI (mvec, R, sp, 2047 + stackSize + 176 + R * 8, RegType, g2); // Add whatever the TargetRegInfo gave us to the MachineBasicBlock we are // working on. for (std::vector::iterator vi = mvec.begin (), @@ -476,14 +466,9 @@ void UnpackTraceFunction::rewriteEpilog (MachineFunction &MF, MachineBasicBlock &MBB) { - return; // FIXME - disabling epilog rewriting for now const TargetRegInfo &TRI = TM->getRegInfo (); - static const unsigned -fp = TRI.getUnifiedRegNum(SparcV9RegInfo::IntRegClassID,SparcV9IntRegClass::i6), -sp = TRI.getUnifiedRegNum(SparcV9RegInfo::IntRegClassID,SparcV9IntRegClass::o6), -g0 = TRI.getUnifiedRegNum(SparcV9RegInfo::IntRegClassID,SparcV9IntRegClass::g0), -g1 = TRI.getUnifiedRegNum(SparcV9RegInfo::IntRegClassID,SparcV9IntRegClass::g1), -g2 = TRI.getUnifiedRegNum(SparcV9RegInfo::IntRegClassID,SparcV9IntRegClass::g2); + static const unsigned fp = SparcV9::i6, sp = SparcV9::o6, g0 = SparcV9::g0, + g1 = SparcV9::g1, g2 = SparcV9::g2; Function *TraceF = TF->TraceFn, *MatrixF = TF->MatrixFn; LiveVariableSet &So = TF->LiveOutSet; @@ -495,12 +480,10 @@ // Restore old FP. std::vector mvec; unsigned stackSize = getStaticStackSize (MF); - TRI.cpMem2RegMI (mvec, sp, stackSize + fp * 8, fp, TRI.getRegType(fp), g2); - - // Add whatever the TargetRegInfo gave us to the MachineBasicBlock we are - // working on. + TRI.cpMem2RegMI (mvec, sp, 2047 + stackSize + 176 + fp * 8, fp, + TRI.getRegType(fp), g2); for (std::vector::iterator vi = mvec.begin (), - ve = mvec.end (); vi != ve; ++vi) + ve = mvec.end (); vi != ve; ++vi) MBB.push_back (*vi); // Insert copies from each live-out variable's reg. in the trace @@ -527,14 +510,18 @@ DEBUG (std::cerr << "rewriteEpilog: Reloading reg#" << R << ", type = " << RegType << ", " << "Class = " << TRI.getRegClassIDOfRegType(RegType) << "\n"); - TRI.cpMem2RegMI (mvec, sp, stackSize + R * 8, R, RegType, g2); - + TRI.cpMem2RegMI (mvec, sp, 2047 + stackSize + 176 + R * 8, R, RegType, g2); // Add whatever the TargetRegInfo gave us to the MachineBasicBlock we are // working on. for (std::vector::iterator vi = mvec.begin (), ve = mvec.end (); vi != ve; ++vi) MBB.push_back (*vi); } + + // Restore stack pointer. + int Size = (stackSize + 176 + 104 * 8); + MBB.push_back (BuildMI (V9::ADDi, 3).addMReg (sp).addSImm (Size).addMReg (sp, + MachineOperand::Def)); // Let ReturnAddress be the address in memory of the compiled // code for the MachineBasicBlock in MatrixF that RI would have From lattner at cs.uiuc.edu Mon May 10 17:14:02 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon May 10 17:14:02 2004 Subject: [llvm-commits] CVS: poolalloc/runtime/HeapFrag/ Message-ID: <200405102214.RAA07615@zion.cs.uiuc.edu> Changes in directory poolalloc/runtime/HeapFrag: --- Log message: Directory /home/vadve/vadve/Research/DynOpt/CVSRepository/poolalloc/runtime/HeapFrag added to the repository --- Diffs of the changes: (+0 -0) From lattner at cs.uiuc.edu Mon May 10 17:15:03 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon May 10 17:15:03 2004 Subject: [llvm-commits] CVS: poolalloc/runtime/HeapFrag/HeapFrag.c Makefile Message-ID: <200405102215.RAA07644@zion.cs.uiuc.edu> Changes in directory poolalloc/runtime/HeapFrag: HeapFrag.c added (r1.1) Makefile added (r1.1) --- Log message: Initial checking of a simple heap fragmenter. It's not even a particularly good one. --- Diffs of the changes: (+56 -0) Index: poolalloc/runtime/HeapFrag/HeapFrag.c diff -c /dev/null poolalloc/runtime/HeapFrag/HeapFrag.c:1.1 *** /dev/null Mon May 10 17:15:09 2004 --- poolalloc/runtime/HeapFrag/HeapFrag.c Mon May 10 17:14:58 2004 *************** *** 0 **** --- 1,47 ---- + /*===- HeapFrag.c - Routine to fragment the heap --------------------------===// + // + // 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 a function 'EnsureHeapFragmentation', which is used to + // artificially fragment the heap, to show the value of pool allocator even for + // silly benchmarks that never free memory and thus have no fragmentation at + // all. + // + //===----------------------------------------------------------------------===*/ + + #include + + static void **AllocateNodes(unsigned N, unsigned Size) { + void **Spine = (void**)malloc(N*sizeof(void*)); + unsigned i; + for (i = 0; i != N; ++i) + Spine[i] = malloc(Size); + return Spine; + } + + static void DeallocateNodes(void **Spine, unsigned N, unsigned Stride) { + unsigned i; + for (i = 0; i < N; i += Stride) { + free(Spine[i]); + Spine[i] = 0; + } + } + + + void EnsureHeapFragmentation() { + void **DS1 = AllocateNodes(10000, 16); + void **DS2; + void *A, *B, *C; + DeallocateNodes(DS1+9000, 1000, 1); /* Free last elements */ + DS2 = AllocateNodes(40000, 40); + DeallocateNodes(DS1, 9000, 2); + DeallocateNodes(DS2, 40000, 2); + DS1 = AllocateNodes(2000, 8); + DeallocateNodes(DS1, 2000, 2); + DeallocateNodes(DS1, 2000, 3); + } Index: poolalloc/runtime/HeapFrag/Makefile diff -c /dev/null poolalloc/runtime/HeapFrag/Makefile:1.1 *** /dev/null Mon May 10 17:15:09 2004 --- poolalloc/runtime/HeapFrag/Makefile Mon May 10 17:14:59 2004 *************** *** 0 **** --- 1,9 ---- + LEVEL = ../.. + #BYTECODE_LIBRARY=1 + #SHARED_LIBRARY=1 + LIBRARYNAME=heapfrag + + include $(LEVEL)/Makefile.common + + # Always build optimized and debug versions + all:: $(LIBNAME_OBJO) $(LIBNAME_OBJG) From gaeke at cs.uiuc.edu Mon May 10 19:21:01 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Mon May 10 19:21:01 2004 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/Trace.cpp Trace.h Message-ID: <200405110020.TAA26962@seraph.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: Trace.cpp (r1.4) removed Trace.h (r1.7) removed --- Log message: The Trace class has been integrated into LLVM proper. Yay! --- Diffs of the changes: (+0 -0) From gaeke at cs.uiuc.edu Mon May 10 19:21:04 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Mon May 10 19:21:04 2004 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/TraceToFunction.h Message-ID: <200405110020.TAA26957@seraph.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: TraceToFunction.h updated: 1.10 -> 1.11 --- Log message: Include llvm/Analysis/Trace.h instead of our own, outdated local copy. --- Diffs of the changes: (+1 -1) Index: reopt/lib/LightWtProfiling/TraceToFunction.h diff -u reopt/lib/LightWtProfiling/TraceToFunction.h:1.10 reopt/lib/LightWtProfiling/TraceToFunction.h:1.11 --- reopt/lib/LightWtProfiling/TraceToFunction.h:1.10 Thu May 6 16:47:49 2004 +++ reopt/lib/LightWtProfiling/TraceToFunction.h Mon May 10 19:20:00 2004 @@ -8,7 +8,7 @@ #ifndef TRACETOFUNCTION_H #define TRACETOFUNCTION_H -#include "Trace.h" +#include "llvm/Analysis/Trace.h" #include "llvm/Function.h" #include #include From gaeke at cs.uiuc.edu Mon May 10 19:21:06 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Mon May 10 19:21:06 2004 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/TraceToFunction.cpp Message-ID: <200405110020.TAA26950@seraph.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: TraceToFunction.cpp updated: 1.29 -> 1.30 --- Log message: Rename our old Trace::dominates function as just dominates(). (We'll see about getting rid of it for good later.) This allows us to use llvm/Analysis/Trace.h instead of our own, outdated local copy. Call the entryfixup block EntryFixup instead of FEntry. Dump trace on entry if DEBUG set. --- Diffs of the changes: (+13 -12) Index: reopt/lib/LightWtProfiling/TraceToFunction.cpp diff -u reopt/lib/LightWtProfiling/TraceToFunction.cpp:1.29 reopt/lib/LightWtProfiling/TraceToFunction.cpp:1.30 --- reopt/lib/LightWtProfiling/TraceToFunction.cpp:1.29 Sun Apr 4 20:32:11 2004 +++ reopt/lib/LightWtProfiling/TraceToFunction.cpp Mon May 10 19:19:59 2004 @@ -64,10 +64,10 @@ virtual TraceFunction *traceToFunction (Trace &T); }; -bool Trace::dominates (const BasicBlock *B1, const BasicBlock *B2, - const BasicBlock *start) { +static bool dominates (Trace &T, const BasicBlock *B1, + const BasicBlock *B2, const BasicBlock *start = 0) { if (!start) - start = getEntryBasicBlock (); + start = T.getEntryBasicBlock (); if (start == B1) { return true; // Seen B1 on this path, if we see B2 later it's OK. } else if (start == B2) { @@ -78,8 +78,8 @@ for (succ_const_iterator i = succ_begin (start), e = succ_end (start); i != e; ++i) { const BasicBlock *succ = *i; - if (contains (succ) && (getEntryBasicBlock () != succ) - && (!dominates (B1, B2, succ))) + if (T.contains (succ) && (T.getEntryBasicBlock () != succ) + && (!dominates (T, B1, B2, succ))) return false; } return true; // Dominates on all successors ==> dominates here too @@ -117,7 +117,7 @@ // If UBlock appears BEFORE Block on some path from the first // basic block of the trace to an exit BB of the trace, return // false. - if (!T.dominates (Block, UBlock)) + if (!dominates (T, Block, UBlock)) return false; } } @@ -419,10 +419,10 @@ // the function. So create new entry basic block to serve as source // for old entry's initial phi node. if (srcB == T.getEntryBasicBlock ()) { - BasicBlock *FEntry = new BasicBlock ("entryfixup", F, dstB); - FEntry->getInstList ().push_back (new BranchInst (dstB)); + BasicBlock *EntryFixup = new BasicBlock ("entryfixup", F, dstB); + EntryFixup->getInstList ().push_back (new BranchInst (dstB)); // Replace the references to the trace's predecessor with a - // reference to FEntry now. This is kind of a dodge because we + // reference to EntryFixup now. This is kind of a dodge because we // don't have a pointer to the trace's predecessor, so we have // to guess which one it is. Assume it's any phi value source in // the entry BB which is not in the trace. @@ -436,7 +436,7 @@ PHINode *PNinF = dyn_cast (V); assert (PNinF && "Clone of Phi node from entry BB is not a Phi node"); - PNinF->setIncomingBlock (i, FEntry); + PNinF->setIncomingBlock (i, EntryFixup); } } @@ -467,8 +467,8 @@ unsigned Slot = 0; for (LiveVariableSet::iterator SI = So.begin (), SE = So.end (); SI != SE; ++SI) { - if (T.dominates (cast ((*SI))->getParent (), - BI->getParent ())) { + if (dominates (T, cast ((*SI))->getParent (), + BI->getParent ())) { std::vector Index; Index.push_back (Constant::getNullValue (Type::LongTy)); //long 0 Index.push_back (ConstantUInt::get (Type::UIntTy, Slot));//uint Slot @@ -579,6 +579,7 @@ std::string CurrentFnName = T.getFunction ()->getName (); DEBUG(std::cerr << "In traceToFunction() for " << CurrentFnName << "\n"); + DEBUG(T.dump ()); // Get some information about the trace's relationship to its parent // function. From gaeke at cs.uiuc.edu Tue May 11 02:21:02 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Tue May 11 02:21:02 2004 Subject: [llvm-commits] CVS: llvm/projects/Stacker/lib/runtime/stacker_rt.c Message-ID: <200405110718.CAA20793@zion.cs.uiuc.edu> Changes in directory llvm/projects/Stacker/lib/runtime: stacker_rt.c updated: 1.5 -> 1.6 --- Log message: Include to get the definition of int64_t on Solaris. --- Diffs of the changes: (+1 -0) Index: llvm/projects/Stacker/lib/runtime/stacker_rt.c diff -u llvm/projects/Stacker/lib/runtime/stacker_rt.c:1.5 llvm/projects/Stacker/lib/runtime/stacker_rt.c:1.6 --- llvm/projects/Stacker/lib/runtime/stacker_rt.c:1.5 Sun May 9 18:20:19 2004 +++ llvm/projects/Stacker/lib/runtime/stacker_rt.c Tue May 11 02:18:02 2004 @@ -20,6 +20,7 @@ #include #include #include +#include extern int64_t _index_; extern int64_t _stack_[]; From gaeke at cs.uiuc.edu Tue May 11 02:43:00 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Tue May 11 02:43:00 2004 Subject: [llvm-commits] CVS: llvm/projects/Stacker/test/runtests Message-ID: <200405110742.CAA29144@seraph.cs.uiuc.edu> Changes in directory llvm/projects/Stacker/test: runtests updated: 1.1 -> 1.2 --- Log message: Do not depend on the path to bash --- Diffs of the changes: (+1 -1) Index: llvm/projects/Stacker/test/runtests diff -u llvm/projects/Stacker/test/runtests:1.1 llvm/projects/Stacker/test/runtests:1.2 --- llvm/projects/Stacker/test/runtests:1.1 Sun Nov 23 12:12:51 2003 +++ llvm/projects/Stacker/test/runtests Tue May 11 02:42:19 2004 @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash path=$1 shift let $((success=0)) From gaeke at cs.uiuc.edu Tue May 11 02:44:01 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Tue May 11 02:44:01 2004 Subject: [llvm-commits] CVS: llvm/projects/Stacker/test/Makefile Message-ID: <200405110743.CAA29162@seraph.cs.uiuc.edu> Changes in directory llvm/projects/Stacker/test: Makefile updated: 1.3 -> 1.4 --- Log message: Do not hardcode the name of gcc, because its full pathname may have been specified by top-level configure --- Diffs of the changes: (+1 -1) Index: llvm/projects/Stacker/test/Makefile diff -u llvm/projects/Stacker/test/Makefile:1.3 llvm/projects/Stacker/test/Makefile:1.4 --- llvm/projects/Stacker/test/Makefile:1.3 Mon Dec 8 01:07:56 2003 +++ llvm/projects/Stacker/test/Makefile Tue May 11 02:42:58 2004 @@ -44,7 +44,7 @@ % : %.s testing.s @$(ECHO) "Compiling and Linking $< to $*" - $(VERB)gcc -ggdb -L$(BUILD_OBJ_ROOT)/lib/$(CONFIGURATION) testing.s -lstkr_runtime -o $* $*.s + $(VERB)$(CC) -ggdb -L$(BUILD_OBJ_ROOT)/lib/$(CONFIGURATION) testing.s -lstkr_runtime -o $* $*.s %.s : %.bc @$(ECHO) "Compiling $< to $*.s" From gaeke at cs.uiuc.edu Tue May 11 02:46:01 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Tue May 11 02:46:01 2004 Subject: [llvm-commits] CVS: llvm/projects/Stacker/lib/runtime/stacker_rt.c Message-ID: <200405110745.CAA29450@seraph.cs.uiuc.edu> Changes in directory llvm/projects/Stacker/lib/runtime: stacker_rt.c updated: 1.6 -> 1.7 --- Log message: Squash warnings on Solaris/sparc... the test suite is not working for me so I can't be sure if these are OK, but they look OK. --- Diffs of the changes: (+2 -2) Index: llvm/projects/Stacker/lib/runtime/stacker_rt.c diff -u llvm/projects/Stacker/lib/runtime/stacker_rt.c:1.6 llvm/projects/Stacker/lib/runtime/stacker_rt.c:1.7 --- llvm/projects/Stacker/lib/runtime/stacker_rt.c:1.6 Tue May 11 02:18:02 2004 +++ llvm/projects/Stacker/lib/runtime/stacker_rt.c Tue May 11 02:45:28 2004 @@ -33,7 +33,7 @@ printf("Stack Dump:\n"); for (i = _index_; i > 0; i-- ) { - printf("#%03lld: %lld\n", i, _stack_[i] ); + printf("#%03lld: %lld\n", (long long int) i, (long long int) _stack_[i] ); } } @@ -56,7 +56,7 @@ } else { - _stack_[_index_++] = (int) argv[a]; + _stack_[_index_++] = (int64_t) (intptr_t) argv[a]; } } From lattner at cs.uiuc.edu Tue May 11 09:09:05 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 11 09:09:05 2004 Subject: [llvm-commits] CVS: llvm/projects/Stacker/lib/runtime/stacker_rt.c Message-ID: <200405111409.JAA03282@zion.cs.uiuc.edu> Changes in directory llvm/projects/Stacker/lib/runtime: stacker_rt.c updated: 1.7 -> 1.8 --- Log message: Unbreak the build on X86. --- Diffs of the changes: (+1 -0) Index: llvm/projects/Stacker/lib/runtime/stacker_rt.c diff -u llvm/projects/Stacker/lib/runtime/stacker_rt.c:1.7 llvm/projects/Stacker/lib/runtime/stacker_rt.c:1.8 --- llvm/projects/Stacker/lib/runtime/stacker_rt.c:1.7 Tue May 11 02:45:28 2004 +++ llvm/projects/Stacker/lib/runtime/stacker_rt.c Tue May 11 09:08:54 2004 @@ -20,6 +20,7 @@ #include #include #include +#include #include extern int64_t _index_; From gaeke at cs.uiuc.edu Tue May 11 11:15:05 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Tue May 11 11:15:05 2004 Subject: [llvm-commits] CVS: llvm/projects/Stacker/lib/runtime/stacker_rt.c Message-ID: <200405111615.LAA03838@zion.cs.uiuc.edu> Changes in directory llvm/projects/Stacker/lib/runtime: stacker_rt.c updated: 1.8 -> 1.9 --- Log message: Use inttypes.h, which exists on all of Linux, Solaris and Darwin. --- Diffs of the changes: (+1 -2) Index: llvm/projects/Stacker/lib/runtime/stacker_rt.c diff -u llvm/projects/Stacker/lib/runtime/stacker_rt.c:1.8 llvm/projects/Stacker/lib/runtime/stacker_rt.c:1.9 --- llvm/projects/Stacker/lib/runtime/stacker_rt.c:1.8 Tue May 11 09:08:54 2004 +++ llvm/projects/Stacker/lib/runtime/stacker_rt.c Tue May 11 11:14:53 2004 @@ -20,8 +20,7 @@ #include #include #include -#include -#include +#include extern int64_t _index_; extern int64_t _stack_[]; From lattner at cs.uiuc.edu Tue May 11 13:44:04 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 11 13:44:04 2004 Subject: [llvm-commits] CVS: llvm-www/demo/index.cgi Message-ID: <200405111844.NAA06567@zion.cs.uiuc.edu> Changes in directory llvm-www/demo: index.cgi updated: 1.23 -> 1.24 --- Log message: Enable more warnings --- Diffs of the changes: (+2 -2) Index: llvm-www/demo/index.cgi diff -u llvm-www/demo/index.cgi:1.23 llvm-www/demo/index.cgi:1.24 --- llvm-www/demo/index.cgi:1.23 Mon Mar 29 13:20:30 2004 +++ llvm-www/demo/index.cgi Tue May 11 13:44:17 2004 @@ -5,7 +5,7 @@ # doing remote web JO99C compilations. (It could still be used for that # purpose, though the two scripts have diverged somewhat.) # -# Last modified $Date: 2004/03/29 19:20:30 $ +# Last modified $Date: 2004/05/11 18:44:17 $ # use CGI; @@ -309,7 +309,7 @@ $stats = "-Wa,--stats,--time-passes,--info-output-file=$timerFile" if ( $c->param('showstats') ); try_run( "llvm C/C++ front-end (llvm-gcc)", - "llvm-gcc -Wall $stats -o $bytecodeFile -c $inputFile > $outputFile 2>&1", + "llvm-gcc -W -Wall -O2 $stats -o $bytecodeFile -c $inputFile > $outputFile 2>&1", $outputFile ); if ( $c->param('showstats') && -s $timerFile ) { ( $UnhilightedResult, $HtmlResult ) = From criswell at cs.uiuc.edu Tue May 11 14:31:03 2004 From: criswell at cs.uiuc.edu (John Criswell) Date: Tue May 11 14:31:03 2004 Subject: [llvm-commits] CVS: llvm/LICENSE.TXT Message-ID: <200405111930.OAA27220@choi.cs.uiuc.edu> Changes in directory llvm: LICENSE.TXT updated: 1.16 -> 1.17 --- Log message: Added obsequi. --- Diffs of the changes: (+1 -0) Index: llvm/LICENSE.TXT diff -u llvm/LICENSE.TXT:1.16 llvm/LICENSE.TXT:1.17 --- llvm/LICENSE.TXT:1.16 Tue Apr 13 15:59:47 2004 +++ llvm/LICENSE.TXT Tue May 11 14:29:59 2004 @@ -74,6 +74,7 @@ hbd: llvm/test/Programs/MultiSource/Applications/hbd treecc: llvm/test/Programs/MultiSource/Applications/treecc kimwitu++: llvm/test/Programs/MultiSource/Applications/kimwitu++ +obsequi: llvm/test/Programs/MultiSource/Applications/obsequi Fhourstones: llvm/test/Programs/MultiSource/Benchmarks/Fhourstones McCat: llvm/test/Programs/MultiSource/Benchmarks/McCat Olden: llvm/test/Programs/MultiSource/Benchmarks/Olden From criswell at cs.uiuc.edu Tue May 11 14:32:01 2004 From: criswell at cs.uiuc.edu (John Criswell) Date: Tue May 11 14:32:01 2004 Subject: [llvm-commits] CVS: llvm/test/Programs/MultiSource/Applications/obsequi/ Message-ID: <200405111931.OAA27237@choi.cs.uiuc.edu> Changes in directory llvm/test/Programs/MultiSource/Applications/obsequi: --- Log message: Directory /home/vadve/shared/PublicCVS/llvm/test/Programs/MultiSource/Applications/obsequi added to the repository --- Diffs of the changes: (+0 -0) From lattner at cs.uiuc.edu Tue May 11 14:34:04 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 11 14:34:04 2004 Subject: [llvm-commits] CVS: llvm/docs/HowToSubmitABug.html Message-ID: <200405111934.OAA08146@zion.cs.uiuc.edu> Changes in directory llvm/docs: HowToSubmitABug.html updated: 1.16 -> 1.17 --- Log message: Add a note to make sure the program is memory correct --- Diffs of the changes: (+10 -4) Index: llvm/docs/HowToSubmitABug.html diff -u llvm/docs/HowToSubmitABug.html:1.16 llvm/docs/HowToSubmitABug.html:1.17 --- llvm/docs/HowToSubmitABug.html:1.16 Sun Apr 18 22:07:29 2004 +++ llvm/docs/HowToSubmitABug.html Tue May 11 14:34:27 2004 @@ -230,9 +230,15 @@ before defining them, etc.) which the verifier will check for after a pass finishes its run.

    -

    To debug a miscompilation, you should choose which program you wish to run -the output through, e.g. C backend, the JIT, or LLC, and a selection of passes, -one of which may be causing the error, and run, for example:

    +

    If it looks like the LLVM compiler is miscompiling a program, the very first +thing to check is to make sure it is not using undefined behavior. In +particular, check to see if the program valgrinds clean, passes purify, or some +other memory checker tool. Many of the "LLVM bugs" that we have chased down +ended up being bugs in the program being compiled, not LLVM.

    + +

    Once you determine that the program itself is not buggy, you should choose +which code generator you wish to compile the program with (e.g. C backend, the +JIT, or LLC) and optionally a series of LLVM passes to run. For example:

    bugpoint -run-cbe [... optimization passes ...] file-to-test.bc @@ -334,7 +340,7 @@ Chris Lattner
    The LLVM Compiler Infrastructure
    - Last modified: $Date: 2004/04/19 03:07:29 $ + Last modified: $Date: 2004/05/11 19:34:27 $ From criswell at cs.uiuc.edu Tue May 11 14:35:03 2004 From: criswell at cs.uiuc.edu (John Criswell) Date: Tue May 11 14:35:03 2004 Subject: [llvm-commits] CVS: llvm/test/Programs/MultiSource/Applications/obsequi/COPYRIGHT GPL LICENSE.TXT Makefile README consts.h cppflags.h display.c does_x_win.c globals.h hash.c init.c interface.h macros.h move_gen.c move_sort.c negamax.c obsequi.c position_values.c structs.h tables.c toggle_move.c traits.c utils.c utils.h Message-ID: <200405111934.OAA27329@choi.cs.uiuc.edu> Changes in directory llvm/test/Programs/MultiSource/Applications/obsequi: COPYRIGHT added (r1.1) GPL added (r1.1) LICENSE.TXT added (r1.1) Makefile added (r1.1) README added (r1.1) consts.h added (r1.1) cppflags.h added (r1.1) display.c added (r1.1) does_x_win.c added (r1.1) globals.h added (r1.1) hash.c added (r1.1) init.c added (r1.1) interface.h added (r1.1) macros.h added (r1.1) move_gen.c added (r1.1) move_sort.c added (r1.1) negamax.c added (r1.1) obsequi.c added (r1.1) position_values.c added (r1.1) structs.h added (r1.1) tables.c added (r1.1) toggle_move.c added (r1.1) traits.c added (r1.1) utils.c added (r1.1) utils.h added (r1.1) --- Log message: Addition of the obsequi program. This program solves domineering boards. --- Diffs of the changes: (+4819 -0) Index: llvm/test/Programs/MultiSource/Applications/obsequi/COPYRIGHT diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/COPYRIGHT:1.1 *** /dev/null Tue May 11 14:34:23 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/COPYRIGHT Tue May 11 14:34:12 2004 *************** *** 0 **** --- 1,21 ---- + Obsequi is a program which is able to solve the game of domineering + for various board sizes. + + Copyright (C) 2002 Nathan Bullock + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + bullock at cs.ualberta.ca + jonathan at cs.ualberta.ca Index: llvm/test/Programs/MultiSource/Applications/obsequi/GPL diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/GPL:1.1 *** /dev/null Tue May 11 14:34:23 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/GPL Tue May 11 14:34:12 2004 *************** *** 0 **** --- 1,340 ---- + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your + freedom to share and change it. By contrast, the GNU General Public + License is intended to guarantee your freedom to share and change free + software--to make sure the software is free for all its users. This + General Public License applies to most of the Free Software + Foundation's software and to any other program whose authors commit to + using it. (Some other Free Software Foundation software is covered by + the GNU Library General Public License instead.) You can apply it to + your programs, too. + + When we speak of free software, we are referring to freedom, not + price. Our General Public Licenses are designed to make sure that you + have the freedom to distribute copies of free software (and charge for + this service if you wish), that you receive source code or can get it + if you want it, that you can change the software or use pieces of it + in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid + anyone to deny you these rights or to ask you to surrender the rights. + These restrictions translate to certain responsibilities for you if you + distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether + gratis or for a fee, you must give the recipients all the rights that + you have. You must make sure that they, too, receive or can get the + source code. And you must show them these terms so they know their + rights. + + We protect your rights with two steps: (1) copyright the software, and + (2) offer you this license which gives you legal permission to copy, + distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain + that everyone understands that there is no warranty for this free + software. If the software is modified by someone else and passed on, we + want its recipients to know that what they have is not the original, so + that any problems introduced by others will not reflect on the original + authors' reputations. + + Finally, any free program is threatened constantly by software + patents. We wish to avoid the danger that redistributors of a free + program will individually obtain patent licenses, in effect making the + program proprietary. To prevent this, we have made it clear that any + patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and + modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains + a notice placed by the copyright holder saying it may be distributed + under the terms of this General Public License. The "Program", below, + refers to any such program or work, and a "work based on the Program" + means either the Program or any derivative work under copyright law: + that is to say, a work containing the Program or a portion of it, + either verbatim or with modifications and/or translated into another + language. (Hereinafter, translation is included without limitation in + the term "modification".) Each licensee is addressed as "you". + + Activities other than copying, distribution and modification are not + covered by this License; they are outside its scope. The act of + running the Program is not restricted, and the output from the Program + is covered only if its contents constitute a work based on the + Program (independent of having been made by running the Program). + Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's + source code as you receive it, in any medium, provided that you + conspicuously and appropriately publish on each copy an appropriate + copyright notice and disclaimer of warranty; keep intact all the + notices that refer to this License and to the absence of any warranty; + and give any other recipients of the Program a copy of this License + along with the Program. + + You may charge a fee for the physical act of transferring a copy, and + you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion + of it, thus forming a work based on the Program, and copy and + distribute such modifications or work under the terms of Section 1 + above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + + These requirements apply to the modified work as a whole. If + identifiable sections of that work are not derived from the Program, + and can be reasonably considered independent and separate works in + themselves, then this License, and its terms, do not apply to those + sections when you distribute them as separate works. But when you + distribute the same sections as part of a whole which is a work based + on the Program, the distribution of the whole must be on the terms of + this License, whose permissions for other licensees extend to the + entire whole, and thus to each and every part regardless of who wrote it. + + Thus, it is not the intent of this section to claim rights or contest + your rights to work written entirely by you; rather, the intent is to + exercise the right to control the distribution of derivative or + collective works based on the Program. + + In addition, mere aggregation of another work not based on the Program + with the Program (or with a work based on the Program) on a volume of + a storage or distribution medium does not bring the other work under + the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, + under Section 2) in object code or executable form under the terms of + Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + + The source code for a work means the preferred form of the work for + making modifications to it. For an executable work, complete source + code means all the source code for all modules it contains, plus any + associated interface definition files, plus the scripts used to + control compilation and installation of the executable. However, as a + special exception, the source code distributed need not include + anything that is normally distributed (in either source or binary + form) with the major components (compiler, kernel, and so on) of the + operating system on which the executable runs, unless that component + itself accompanies the executable. + + If distribution of executable or object code is made by offering + access to copy from a designated place, then offering equivalent + access to copy the source code from the same place counts as + distribution of the source code, even though third parties are not + compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program + except as expressly provided under this License. Any attempt + otherwise to copy, modify, sublicense or distribute the Program is + void, and will automatically terminate your rights under this License. + However, parties who have received copies, or rights, from you under + this License will not have their licenses terminated so long as such + parties remain in full compliance. + + 5. You are not required to accept this License, since you have not + signed it. However, nothing else grants you permission to modify or + distribute the Program or its derivative works. These actions are + prohibited by law if you do not accept this License. Therefore, by + modifying or distributing the Program (or any work based on the + Program), you indicate your acceptance of this License to do so, and + all its terms and conditions for copying, distributing or modifying + the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the + Program), the recipient automatically receives a license from the + original licensor to copy, distribute or modify the Program subject to + these terms and conditions. You may not impose any further + restrictions on the recipients' exercise of the rights granted herein. + You are not responsible for enforcing compliance by third parties to + this License. + + 7. If, as a consequence of a court judgment or allegation of patent + infringement or for any other reason (not limited to patent issues), + conditions are imposed on you (whether by court order, agreement or + otherwise) that contradict the conditions of this License, they do not + excuse you from the conditions of this License. If you cannot + distribute so as to satisfy simultaneously your obligations under this + License and any other pertinent obligations, then as a consequence you + may not distribute the Program at all. For example, if a patent + license would not permit royalty-free redistribution of the Program by + all those who receive copies directly or indirectly through you, then + the only way you could satisfy both it and this License would be to + refrain entirely from distribution of the Program. + + If any portion of this section is held invalid or unenforceable under + any particular circumstance, the balance of the section is intended to + apply and the section as a whole is intended to apply in other + circumstances. + + It is not the purpose of this section to induce you to infringe any + patents or other property right claims or to contest validity of any + such claims; this section has the sole purpose of protecting the + integrity of the free software distribution system, which is + implemented by public license practices. Many people have made + generous contributions to the wide range of software distributed + through that system in reliance on consistent application of that + system; it is up to the author/donor to decide if he or she is willing + to distribute software through any other system and a licensee cannot + impose that choice. + + This section is intended to make thoroughly clear what is believed to + be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in + certain countries either by patents or by copyrighted interfaces, the + original copyright holder who places the Program under this License + may add an explicit geographical distribution limitation excluding + those countries, so that distribution is permitted only in or among + countries not thus excluded. In such case, this License incorporates + the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions + of the General Public License from time to time. Such new versions will + be similar in spirit to the present version, but may differ in detail to + address new problems or concerns. + + Each version is given a distinguishing version number. If the Program + specifies a version number of this License which applies to it and "any + later version", you have the option of following the terms and conditions + either of that version or of any later version published by the Free + Software Foundation. If the Program does not specify a version number of + this License, you may choose any version ever published by the Free Software + Foundation. + + 10. If you wish to incorporate parts of the Program into other free + programs whose distribution conditions are different, write to the author + to ask for permission. For software which is copyrighted by the Free + Software Foundation, write to the Free Software Foundation; we sometimes + make exceptions for this. Our decision will be guided by the two goals + of preserving the free status of all derivatives of our free software and + of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY + FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN + OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES + PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED + OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS + TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE + PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, + REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING + WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR + REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, + INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING + OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED + TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY + YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER + PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest + possible use to the public, the best way to achieve this is to make it + free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest + to attach them to the start of each source file to most effectively + convey the exclusion of warranty; and each file should have at least + the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + Also add information on how to contact you by electronic and paper mail. + + If the program is interactive, make it output a short notice like this + when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + + The hypothetical commands `show w' and `show c' should show the appropriate + parts of the General Public License. Of course, the commands you use may + be called something other than `show w' and `show c'; they could even be + mouse-clicks or menu items--whatever suits your program. + + You should also get your employer (if you work as a programmer) or your + school, if any, to sign a "copyright disclaimer" for the program, if + necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + + This General Public License does not permit incorporating your program into + proprietary programs. If your program is a subroutine library, you may + consider it more useful to permit linking proprietary applications with the + library. If this is what you want to do, use the GNU Library General + Public License instead of this License. Index: llvm/test/Programs/MultiSource/Applications/obsequi/LICENSE.TXT diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/LICENSE.TXT:1.1 *** /dev/null Tue May 11 14:34:23 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/LICENSE.TXT Tue May 11 14:34:12 2004 *************** *** 0 **** --- 1,5 ---- + Obsequi + ------------------------------------------------------------------------------ + Obsequi is licensed under the GNU General Public License. Please see the file + COPYRIGHT and GPL for more information. + Index: llvm/test/Programs/MultiSource/Applications/obsequi/Makefile diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/Makefile:1.1 *** /dev/null Tue May 11 14:34:23 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/Makefile Tue May 11 14:34:12 2004 *************** *** 0 **** --- 1,8 ---- + LEVEL = ../../../../.. + PROG = Obsequi + CPPFLAGS += -DCOUNTBITS16 -DLASTBIT16 -DCOUNTMOVES_TABLE -DHASHCODEBITS=23 + CPPFLAGS += -DTWO_STAGE_GENERATION + LDFLAGS = -lsupc++ + LIBS += -lsupc++ + STDIN_FILENAME=$(BUILD_SRC_DIR)/input + include ../../Makefile.multisrc Index: llvm/test/Programs/MultiSource/Applications/obsequi/README diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/README:1.1 *** /dev/null Tue May 11 14:34:23 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/README Tue May 11 14:34:12 2004 *************** *** 0 **** --- 1,23 ---- + obsequi - latin for compliance, indulgence, submission, pliancy. + + This program is able to play and solve domineering boards. + Currently it can solve 9x9 and larger boards with a single processor. + + To compile cd to the directory "obsequi", type make. + + Should work, if not, you must be using a different compiler or + libraries. (I use gcc and glibc). + + There isn't really any documentation for obsequi (sorry). + + To get it to solve an 8x8 board use: + echo "solve rows 8 cols 8 V" | ./Obsequi + + You can also pre-place blocks on the board. + The V says it is verticals turn first. + There are a number of run time options and compile time options, the + compile time options are in cppflags.raw (don't change the other cppflags* + files they are automatically changed.) + + + Index: llvm/test/Programs/MultiSource/Applications/obsequi/consts.h diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/consts.h:1.1 *** /dev/null Tue May 11 14:34:23 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/consts.h Tue May 11 14:34:12 2004 *************** *** 0 **** --- 1,48 ---- + + + //######################################################## + // Constants which we use. + // Any constants which we commonly change or try to tweak + // should be in cppflags.raw. + //######################################################## + + // max number of empty squares which should ever exist is 256 + // therefore we could possible get close to this number of moves. + #define MAXMOVES 256 + + // Player stuff. (Used for example with g_board to get the current player). + #define HORIZONTAL 0 + #define VERTICAL 1 + #define PLAYER_MASK 1 + + // Used with g_board_size (to get num of rows and num of cols). + #define ROW_INDEX HORIZONTAL + #define COL_INDEX VERTICAL + + + #define LOWER 0 + #define EXACT 1 + #define UPPER 2 + + + // blah + #define ERASE_NEXT_BIT 0x80000000; + #define NEXT_BIT 0x00010000; + + //######################################################## + // Constants used in conjuction with the transposition table + // and the zobrist values. + //######################################################## + + // HASHCODEBITS should already be defined. + #ifndef HASHCODEBITS + #error "HASHCODEBITS must be defined.\n" + #endif + + // It should have a value of between 0 and 31. + #if ! (HASHCODEBITS > 0 && HASHCODEBITS < 31) + #error "Invalid value for HASHCODEBITS, it should be a value from 1 - 30." + #endif + + #define HASHSIZE (1 << HASHCODEBITS) + #define HASHMASK (HASHSIZE - 1) Index: llvm/test/Programs/MultiSource/Applications/obsequi/cppflags.h diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/cppflags.h:1.1 *** /dev/null Tue May 11 14:34:23 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/cppflags.h Tue May 11 14:34:12 2004 *************** *** 0 **** --- 1,10 ---- + // This file is automatically generated from CPPFLAGS_raw + + char option_string[] = + "-Wall -O2\n" + "-DCOUNTBITS16\n" + "-DLASTBIT16\n" + "-DCOUNTMOVES_TABLE\n" + "-DHASHCODEBITS=23\n" + "-DTWO_STAGE_GENERATION\n" + ; Index: llvm/test/Programs/MultiSource/Applications/obsequi/display.c diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/display.c:1.1 *** /dev/null Tue May 11 14:34:23 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/display.c Tue May 11 14:34:12 2004 *************** *** 0 **** --- 1,333 ---- + + + #include "globals.h" + + + //######################################################## + // Sanity check functions. + // These functions try to do a quick check of some set of + // information. They crash and burn if the check fails. + //######################################################## + + static void + check_hashkey_bit_set(Hash_Key key, s32bit index) + { + if(! (key.key[index/32] & NTH_BIT(index%32)) ){ + + printf("%d", index); + + print_bitboard(HORIZONTAL); + + print_hashkey(key); + + fatal_error(1, "HashKey Incorrect.\n"); + } + } + + static void + check_hashkey_bit_not_set(Hash_Key key, s32bit index) + { + if( (key.key[index/32] & NTH_BIT(index%32)) ){ + + printf("%d", index); + + print_bitboard(HORIZONTAL); + + print_hashkey(key); + + fatal_error(1, "HashKey Incorrect.\n"); + } + } + + static void + check_hashkey_code(Hash_Key key) + { + s32bit i, j, index, n_rows, n_cols, code; + + n_rows = g_board_size[HORIZONTAL], n_cols = g_board_size[VERTICAL]; + + code = key.code; + + for(i = 0; i < n_rows; i++) + for(j = 0; j < n_cols; j++){ + index = (i*n_cols) + j; + if(key.key[index/32] & NTH_BIT(index%32)) + code ^= g_zobrist[i+1][j+1]; + } + + if(code != 0){ + fatal_error(1, "Invalid hash code.\n"); + } + } + + + + //======================================================== + // This function checks to make sure hash codes + // and keys are correct. + //======================================================== + extern void + check_hash_code_sanity() + { + s32bit i, j, index, n_rows, n_cols; + + n_rows = g_board_size[HORIZONTAL], n_cols = g_board_size[VERTICAL]; + + for(i = 0; i < n_rows; i++) + for(j = 0; j < n_cols; j++) + if(g_board[HORIZONTAL][i+1] & NTH_BIT(j+1)) { + + index = (i*n_cols)+j; + check_hashkey_bit_set(g_norm_hashkey, index); + + index = (i*n_cols) + (n_cols - j - 1); + check_hashkey_bit_set(g_flipV_hashkey, index); + + index = ( (n_rows - i - 1) *n_cols) + j; + check_hashkey_bit_set(g_flipH_hashkey, index); + + index = ( (n_rows - i - 1) *n_cols) + (n_cols - j - 1); + check_hashkey_bit_set(g_flipVH_hashkey, index); + } else { + index = (i*n_cols)+j; + check_hashkey_bit_not_set(g_norm_hashkey, index); + + index = (i*n_cols) + (n_cols - j - 1); + check_hashkey_bit_not_set(g_flipV_hashkey, index); + + index = ( (n_rows - i - 1) *n_cols) + j; + check_hashkey_bit_not_set(g_flipH_hashkey, index); + + index = ( (n_rows - i - 1) *n_cols) + (n_cols - j - 1); + check_hashkey_bit_not_set(g_flipVH_hashkey, index); + } + + check_hashkey_code(g_norm_hashkey); + check_hashkey_code(g_flipV_hashkey); + check_hashkey_code(g_flipH_hashkey); + check_hashkey_code(g_flipVH_hashkey); + } + + + + //======================================================== + // This function compares the Horizontal board info to + // the vertical board info. + //======================================================== + extern void + check_board_sanity() + { + s32bit i, j; + s32bit count; + + for(j = 0; j < g_board_size[HORIZONTAL] + 2; j++) + for(i = 0; i < g_board_size[VERTICAL] + 2; i++){ + count = 0; + + if(g_board[VERTICAL][i] & NTH_BIT(j)) count++; + if(g_board[HORIZONTAL][j] & NTH_BIT(i)) count++; + + if(count == 1){ + print_board(VERTICAL); + print_board(HORIZONTAL); + + printf("%d %d - %d.\n", j, i, count); + + fatal_error(1, "Board is inconsistent.\n"); + } + } + } + + //======================================================== + // Check the board info which we have to make sure that it + // is accurate. + //======================================================== + /* + extern void + check_info_sanity() + { + }*/ + + + + //######################################################## + // Display functions. + // These functions print out some set of information in what + // is hopefully a fairly readable format. + //######################################################## + extern void + print_hashentry(s32bit index) + { + Hash_Entry entry = g_trans_table[index]; + + printf("Hash entry: %d.\n", index); + printf(" Key:%8X:%8X:%8X:%8X, n:%u, d:%d, w:%d" + ", v:%d, t:%d, int:%d.\n", + entry.key[0], entry.key[1], entry.key[2], entry.key[3], + entry.nodes, entry.depth, entry.whos_turn, + entry.value, entry.type, entry.best_move); + } + + + extern void + print_board(s32bit player) + { + s32bit player_index; + s32bit row, col, i, j; + + player_index = player&PLAYER_MASK; + + row = g_board_size[player_index]; + col = g_board_size[player_index^PLAYER_MASK]; + + for(i = 0; i < row; i++){ + for(j = 0; j < col; j++){ + if(g_board[player_index][i+1] & NTH_BIT(j+1)) + printf(" #"); + else + printf(" 0"); + } + printf("\n"); + } + } + + extern void + print_board_info(s32bit player) + { + s32bit num_rows, num_cols, max_dim, i; + char str[32][80], null_str[1] = ""; + + num_rows = g_board_size[HORIZONTAL]; + num_cols = g_board_size[VERTICAL]; + max_dim = MAX_TWO(num_rows, num_cols); + + sprintf(str[1], "Number of rows = %d", g_board_size[HORIZONTAL]); + sprintf(str[2], "Number of columns = %d", g_board_size[VERTICAL]); + + printf("%7s %15s %15s\n", + null_str, "Vertical", "Horizontal"); + printf("%7s %7s %7s %7s %7s\n", + null_str, "Real", "Safe", "Real", "Safe"); + + for(i = 0; i < max_dim; i++){ + printf("%6d) %7d %7d %7d %7d %s\n", i + 1, + g_info[VERTICAL][i+1].real, g_info[VERTICAL][i+1].safe, + g_info[HORIZONTAL][i+1].real, g_info[HORIZONTAL][i+1].safe, + (i < 2) ? str[i+1] : null_str); + } + + printf("Totals: %7d %7d %7d %7d\n", + g_info_totals[VERTICAL].real, g_info_totals[VERTICAL].safe, + g_info_totals[HORIZONTAL].real, g_info_totals[HORIZONTAL].safe); + } + + extern void + print_bitboard(s32bit player) + { + s32bit player_index; + s32bit i; + + player_index = player&PLAYER_MASK; + + for(i = 0; i < g_board_size[player_index] + 2; i++) + printf("%X\n", g_board[player_index][i]); + } + + extern void + print_hashkey(Hash_Key key) + { + printf("Key: %8X:%8X:%8X:%8X, Code: %8X.\n", + key.key[0], key.key[1], key.key[2], key.key[3], key.code); + } + + extern void + print_u64bit(u64bit val) + { + s32bit vals[10]; + s32bit i = 0; + + do { + vals[i] = val % 1000; + val = val / 1000; + i++; + } while(val != 0); + + if(i > 10) fatal_error(1, "Too large???\n"); + + printf("%d", vals[--i]); + + while(i != 0) + printf(",%3d", vals[--i]); + } + + extern void + print_keyinfo(KeyInfo_s info, s32bit with) + { + if(info.bit1_index == -1) fatal_error(1, "bit1_index equal to -1"); + + if(with) + printf("%3d:%3d %8X ", + info.bit1_index, info.bit2_index, info.hash_code); + else + printf("%3d:%3d ", + info.bit1_index, info.bit2_index); + } + + + extern void + print_keyinfo_table(s32bit player, s32bit with_hashcode) + { + s32bit r, c; + + for(r = 0; r < 32; r++) + for(c = 0; c < 32; c++){ + if(g_keyinfo[player][r][c].norm.bit1_index != -1){ + + printf("(%2d,%2d)>> ", r, c); + + print_keyinfo(g_keyinfo[player][r][c].norm, with_hashcode); + print_keyinfo(g_keyinfo[player][r][c].flipV, with_hashcode); + print_keyinfo(g_keyinfo[player][r][c].flipH, with_hashcode); + print_keyinfo(g_keyinfo[player][r][c].flipVH, with_hashcode); + putchar('\n'); + } + } + } + + + extern void + print_external() + { + // print_keyinfo_table(HORIZONTAL, 1); + print_keyinfo_table(VERTICAL, 1); + } + + extern s32bit g_print; + + extern void + print_current_state() + { + print_board(HORIZONTAL); + printf("\n"); + print_board_info(HORIZONTAL); + g_print = 0; + } + + + extern const char* + current_search_state() + { + static char* str = NULL; + + g_print = 1; + + if(str != NULL) free(str); + + asprintf(&str, "Nodes: %s.\n%d %d %d %d %d %d %d %d %d.", + u64bit_to_string(g_num_nodes), + g_move_number[1], g_move_number[2], g_move_number[3], + g_move_number[4], g_move_number[5], g_move_number[6], + g_move_number[7], g_move_number[8], g_move_number[9]); + + return str; + } Index: llvm/test/Programs/MultiSource/Applications/obsequi/does_x_win.c diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/does_x_win.c:1.1 *** /dev/null Tue May 11 14:34:23 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/does_x_win.c Tue May 11 14:34:12 2004 *************** *** 0 **** --- 1,641 ---- + + #include "globals.h" + + #define PRINT_DOES_X_WIN_INFO + + // If defined we just immediately return from each function with + // a value of -1. (In other words no winner yet.) + //#define NOTHING + + // If defined don't pack any protected moves onto the board. + //#define NO_PROT + + // If defined pretend all (unpacked) squares are available to opponent. + //#define NO_UNUSED + + // If defined pretend we didn't find any vulnerable moves with a prot square. + //#define NO_VULN_W_PROT + + // If defined pretend we didn't find any vulnerable moves with a prot square. + //#define NO_VULN_TYPE_1 + + // If defined pretend there were no vulnerable moves (note this also + // means NO_VULN_W_PROT). + //#define NO_VULN + + // If defined don't look for safe options. + //#define NO_SAFE_OPT + + //################################################################# + // This function tries to pack as many 'protective' areas onto + // the board as it can. (no guarantee of optimality). + //################################################################# + static inline void + pack_prot(u32bit tmp_board[32], s32bit player, s32bit *prot) + { + s32bit r = 0, p = 0; //row, and number of prot. areas we have placed. + + u32bit tmp, inter, walls; + + for(r = 0; r < g_board_size[player]; r++){ + // set bit at each position where there is interference. + inter = (tmp_board[r] | tmp_board[r+1] | tmp_board[r+2] | tmp_board[r+3] + | g_board[player][r+1] | g_board[player][r+2]); + inter = (inter >> 1) | inter; + + // set bit at each position which there is a wall. + walls = ( ((g_board[player][r] >> 1) & g_board[player][r]) + | ((g_board[player][r+3] >> 1) & g_board[player][r+3]) ); + + // combine (bit set at each position which we can place a prot. area). + inter = walls & ~inter; + + // process the positions. + while(inter){ + tmp = (inter & -inter); // least sig bit of m + inter &= ~(tmp | (tmp << 1)); // remove bit and next bit. + + tmp_board[r+1] |= tmp | (tmp << 1); //record where we put + tmp_board[r+2] |= tmp | (tmp << 1); // the protective square. + + p++; // count it. + } + } + + *prot = p; + } + + + //################################################################# + // This function tries to pack as many 'vuln. type 1 and 2' areas + // onto the board as it can. (no guarantee of optimality). + // It also counts the number of unused squares. + //################################################################# + static void + pack_vuln(u32bit tmp_board[32], s32bit player, + s32bit *vuln2, s32bit *vuln2_w_prot, + s32bit *vuln1, s32bit *vuln1_w_prot, + s32bit *unused) //, s32bit print) + { + u32bit curr_row, adj_rows, next_prev_row; + u32bit tmp = 0, tmp_; + + s32bit v2 = 0, v2_p = 0, v1 = 0, v1_p = 0, u = 0; + + s32bit r, state; + u32bit s_v = 0; //start of vulnerable + + for(r = 0; r < g_board_size[player]; r++){ + next_prev_row = tmp_board[r]; + next_prev_row |= ~(g_board[player][r+2] | (g_board[player][r+2] << 1)); + next_prev_row |= ~(g_board[player][r+2] | (g_board[player][r+2] >> 1)); + + curr_row = ~(g_board[player][r+1] | tmp_board[r+1]); + adj_rows = g_board[player][r] & g_board[player][r+2]; + state = 0; + + //======================================================== + // Three types of squares, prot, empty, occ. + // + // state = 0 + // if(prot) -> state = 1 + // if(empty) -> state = 2, c_t = c, + // if(occ) -> state = 0 + // + // state = 1 + // if(prot) -> state = 0, safe++ + // if(empty) -> state = 0, v_p++, mark(c-1) + // if(occ) -> state = 0, unu++ + // + // state = 2 + // if(prot) -> state = 3, + // if(empty) -> state = 0, vuln++, mark(c_t) + // if(occ) -> state = 0, + // + // state = 3 + // if(prot) -> state = 4, safe++ + // if(empty) -> state = 2, v_p++, mark(c_t), c_t = c + // if(occ) -> state = 0, v_p++, mark(c_t) + // + // state = 4 + // if(prot) -> state = 3 + // if(empty) -> state = 2, c_t = c + // if(occ) -> state = 0 + //======================================================== + + while(curr_row){ + tmp_ = (curr_row & -curr_row); //get least sig bit of curr_row + curr_row ^= tmp_; //remove least sig bit of curr_row. + + // if true then this iteration and last iteration are not contiguous. + // Which means there was an occupied square. + if ( ((tmp_ >> 1) & tmp) == 0 ) { + if(state == 1) { + u++; + tmp_board[r+1] |= tmp; + } else if(state == 3) { + tmp_board[r+1] |= (s_v | (s_v << 1)); + if((s_v & next_prev_row) || ((s_v << 1) & next_prev_row)) + v2_p++; + else + v1_p++; + } + state = 0; + } + tmp = tmp_; + + // empty and protected + if( tmp & adj_rows ){ + if(state == 0) { + state = 1; + } else if(state == 1) { + state = 0; + //safe + } else if(state == 2) { + state = 3; + } else if(state == 3) { + state = 4; + //safe + } else if(state == 4) { + state = 3; + } + } + + // unprotected + else { + if(state == 0) { + state = 2; + s_v = tmp; + } else if(state == 1){ + state = 0; + + // Check tmp >> 1 + + tmp_board[r+1] |= (tmp | (tmp >> 1)); + if((tmp & next_prev_row) || ((tmp >> 1) & next_prev_row)) + v2_p++; + else + v1_p++; + } else if(state == 2){ + state = 0; + tmp_board[r+1] |= (s_v | (s_v << 1)); + if((s_v & next_prev_row) || ((s_v << 1) & next_prev_row)) + v2++; + else + v1++; + } else if(state == 3){ + state = 2; + tmp_board[r+1] |= (s_v | (s_v << 1)); + if((s_v & next_prev_row) || ((s_v << 1) & next_prev_row)) + v2_p++; + else + v1_p++; + s_v = tmp; + } else if(state == 4){ + state = 2; + s_v = tmp; + } + } + } + + if(state == 1) { + u++; + tmp_board[r+1] |= tmp; + } else if(state == 3) { + tmp_board[r+1] |= (s_v | (s_v << 1)); + if((s_v & next_prev_row) || ((s_v << 1) & next_prev_row)) + v2_p++; + else + v1_p++; + } + + // if(print) + // printf("%d %d %d %d %d - %X\n", v2, v2_p, v1, v1_p, u, + // tmp_board[r+1]); + + } + // if(print) printf("\n"); + + *vuln2 = v2 + v2_p; + *vuln2_w_prot = v2_p; + *vuln1 = v1 + v1_p; + *vuln1_w_prot = v1_p; + *unused = u; + } + + + //################################################################# + // This function tries to pack as many 'option of vulnerability' areas + // onto the board as it can. (no guarantee of optimality). + //################################################################# + static inline void + pack_safe(u32bit tmp_board[32], s32bit player, + s32bit *safe_op2, s32bit *safe_op1, s32bit *safe_op0) + { + u32bit guard, mask, curr, tmp; + + s32bit r; //row + s32bit s2 = 0, s1 = 0, s0 = 0; + + for(r = 0; r < g_board_size[player]; r++){ + guard = g_board[player][r] & g_board[player][r+2]; + curr = g_board[player][r+1] | tmp_board[r+1]; + + // mask contains a bit for each safe move. + mask = ( (~(curr | (curr >> 1))) & (guard & (guard >> 1)) ); + + while(mask){ + tmp = (mask & -mask); // least sig bit of m + mask &= ~(tmp | (tmp << 1)); // remove bit and next bit. + + // add these bits to current. + curr |= (tmp | (tmp << 1)); + + if( ! ( (curr | tmp_board[r] | tmp_board[r+2]) & (tmp >> 1) ) ){ + // we have an option to move vulnerably. (which option is it). + curr |= (tmp >> 1); + tmp_board[r+1] |= (tmp >> 1); + + // check up. + if( (!(g_board[player][r] & (tmp >> 1))) + && (g_board[player][r-1] & (tmp >> 1)) ){ + // up is good now check down. + if( (!(g_board[player][r+2] & (tmp >> 1))) + && (g_board[player][r+3] & (tmp >> 1)) ){ + s2++; + } else { + s1++; + } + } else if( (!(g_board[player][r+2] & (tmp >> 1))) + && (g_board[player][r+3] & (tmp >> 1)) ){ + s1++; + } else { + s0++; + } + } else + if( ! ( (mask | curr | tmp_board[r] | tmp_board[r+2]) & (tmp << 2) ) ){ + // we have an option to move vulnerably. (which option is it). + curr |= (tmp << 2); + tmp_board[r+1] |= (tmp << 2); + + // check up. + if( (!(g_board[player][r] & (tmp << 2))) + && (g_board[player][r-1] & (tmp << 2)) ){ + // up is good now check down. + if( (!(g_board[player][r+2] & (tmp << 2))) + && (g_board[player][r+3] & (tmp << 2)) ){ + s2++; + } else { + s1++; + } + } else if( (!(g_board[player][r+2] & (tmp << 2))) + && (g_board[player][r+3] & (tmp << 2)) ){ + s1++; + } else { + s0++; + } + } + } + // if(debug) printf("(%d,%d) ", s0, s1); + } + // if(debug) printf("\n"); + + *safe_op2 = s2; + *safe_op1 = s1; + *safe_op0 = s0; + } + + //################################################################# + // + //################################################################# + extern s32bit + #ifdef PRINT_DOES_X_WIN_INFO + does_next_player_win(s32bit next_player, s32bit print) + #else + does_next_player_win(s32bit next_player) + #endif + { + // info we directly get from the board. + s32bit prot; // This is the number of protective regions. + + s32bit vuln2; // Total number of vulnerable moves (includes vuln_w_prot). + // Num of vuln moves which contain a square unavailable to the opponent. + s32bit vuln2_w_prot; + s32bit vuln1; // Total number of vulnerable moves (includes vuln_w_prot). + // Num of vuln moves which contain a square unavailable to the opponent. + s32bit vuln1_w_prot; + + s32bit safe; // Number of safe moves horizontal has. + // Number of squares unused in our packing and unavailable for opponent. + s32bit unused; + s32bit empty; // Number of empty squares on board. + s32bit safe_op2, safe_op1, safe_op0; //safe moves with options. + + // value we return and other variables. + s32bit r_value = 0, i; + + // temporary board to store which positions have already been packed. + u32bit tmp_board[32]; + + #ifdef NOTHING + return -1; + #endif + + //======================================================== + // Initialize all of the values. + //======================================================== + for(i = 0; i < 32; i++) tmp_board[i] = 0; + safe = g_info_totals[next_player].safe; + empty = g_empty_squares; + + // Determine the number of protective regions that we have. + #ifdef NO_PROT + prot = 0; + #else + pack_prot(tmp_board, next_player, &prot); + #endif + + // Determine the number of vuln, vuln_w_prot, and unused. + pack_vuln(tmp_board, next_player, &vuln2, &vuln2_w_prot, + &vuln1, &vuln1_w_prot, &unused); //, print); + + #ifdef NO_VULN_W_PROT + vuln1_w_prot = vuln2_w_prot = 0; + #endif + + #ifdef NO_VULN_TYPE_1 + vuln2 += vuln1; + vuln2_w_prot += vuln1_w_prot; + vuln1 = vuln1_w_prot = 0; + #endif + + #ifdef NO_UNUSED + unused = 0; + #endif + + #ifdef NO_VULN + vuln2 = vuln1 = vuln2_w_prot = vuln1_w_prot = 0; + #endif + + // Determine the number of safe moves with options we have. + #ifdef NO_SAFE_OPT + safe_op2 = safe_op1 = safe_op0 = 0; + #else + pack_safe(tmp_board, next_player, &safe_op2, &safe_op1, &safe_op0); + #endif + + #ifdef PRINT_DOES_X_WIN_INFO + if(print){ + fprintf(stderr, "%d moves next, do they win?\n", next_player); + fprintf(stderr, "prot %d, vuln2 %d(%d), vuln1 %d(%d), " + "safe %d, unused %d, empty %d.\n", + prot, vuln2, vuln2_w_prot, vuln1, vuln1_w_prot, + safe, unused, empty); + fprintf(stderr, "safe_op2 %d, safe_op1 %d, safe_op0 %d.\n", + safe_op2, safe_op1, safe_op0); + } + #endif + + { + s32bit moves, opp_moves, x = 0; + + if(prot % 2 == 1){ + prot--; + safe += 2; + } else if(vuln2 % 3 != 0){ + vuln2--; + safe++; + if(vuln2_w_prot > vuln2) vuln2_w_prot--; + } else if(vuln1 % 2 != 0){ + vuln1--; + safe++; + if(vuln1_w_prot > vuln1) vuln1_w_prot--; + } else if(safe_op2 % 2 != 0){ + safe_op2--; + unused+=3; + } else if(safe_op1 % 2 != 0){ + safe_op1--; + unused+=2; + } else if(safe_op0 % 2 != 0){ + safe_op0--; + unused+=1; + } else if(vuln2 > 0){ + vuln2--; + safe++; + if(vuln2_w_prot > vuln2) vuln2_w_prot--; + } else if(vuln1 > 0){ + vuln1--; + safe++; + if(vuln1_w_prot > vuln1) vuln1_w_prot--; + } else if(prot > 0){ + prot--; + safe += 2; + } else { + return -1; + } + + if(prot % 2 == 1){ + prot--; + vuln2 += 2; + } + + moves = (prot) + (vuln2/3) + (vuln1/2) + safe; + + if(vuln2 % 3 != 0 && vuln1 % 2 != 0){ + moves++, unused--, x=1; + // if(vuln2 > 0 || vuln1 > 0) unused--; + } else if(vuln2 % 3 == 0 && vuln1 % 2 == 0) x=1; + + if(x == 1){ + if(safe_op2%2 == 1) safe_op2--, safe_op1++; + if(safe_op1%2 == 1) safe_op1--, safe_op0++; + } else { + if(safe_op2%2 == 1){ + unused += 3; + if(safe_op1%2==1) safe_op1--, safe_op0++; + } else if(safe_op1%2 == 1) { unused += 2; } + else if(safe_op0%2 == 1) { unused += 1; } + } + + unused += vuln2_w_prot - ( (vuln2)/3 - (vuln2-vuln2_w_prot)/3 ); + unused += vuln1_w_prot - ( (vuln1)/2 - (vuln1-vuln1_w_prot)/2 ); + + unused += (safe_op2/2) * 3; + unused += (safe_op1/2) * 2; + unused += (safe_op0/2) * 1; + + opp_moves = (empty - (moves*2) - unused)/2; + + //======================================================== + // If r_value > 0 then next_player wins. + //======================================================== + r_value = moves - opp_moves; + + #ifdef PRINT_DOES_X_WIN_INFO + if(print){ + printf("moves:%d, opp:%d.\n", moves, opp_moves); + if(moves - opp_moves >= 0) printf("H WINS\n"); + } + #endif + } + + return r_value; + } + + + //################################################################# + // + //################################################################# + extern s32bit + #ifdef PRINT_DOES_X_WIN_INFO + does_who_just_moved_win(s32bit who_just_moved, s32bit print) + #else + does_who_just_moved_win(s32bit who_just_moved) + #endif + { + // info we directly get from the board. + s32bit prot; // This is the number of protective regions. + + s32bit vuln2; // Total number of vulnerable moves (includes vuln_w_prot). + // Num of vuln moves which contain a square unavailable to the opponent. + s32bit vuln2_w_prot; + s32bit vuln1; // Total number of vulnerable moves (includes vuln_w_prot). + // Num of vuln moves which contain a square unavailable to the opponent. + s32bit vuln1_w_prot; + + s32bit safe; // Number of safe moves horizontal has. + // Number of squares unused in our packing and unavailable for opponent. + s32bit unused; + s32bit empty; // Number of empty squares on board. + s32bit safe_op2, safe_op1, safe_op0; //safe moves with options. + + // value we return and other variables. + s32bit r_value = 0, i; + + // temporary board to store which positions have already been packed. + u32bit tmp_board[32]; + + #ifdef NOTHING + return -1; + #endif + + //======================================================== + // Initialize all of the values. + //======================================================== + for(i = 0; i < 32; i++) tmp_board[i] = 0; + safe = g_info_totals[who_just_moved].safe; + empty = g_empty_squares; + + // Determine the number of protective regions that we have. + #ifdef NO_PROT + prot = 0; + #else + pack_prot(tmp_board, who_just_moved, &prot); + #endif + + // Determine the number of vuln, vuln_w_prot, and unused. + pack_vuln(tmp_board, who_just_moved, &vuln2, &vuln2_w_prot, + &vuln1, &vuln1_w_prot, &unused); + + #ifdef NO_VULN_W_PROT + vuln1_w_prot = vuln2_w_prot = 0; + #endif + + #ifdef NO_VULN_TYPE_1 + vuln2 += vuln1; + vuln2_w_prot += vuln1_w_prot; + vuln1 = vuln1_w_prot = 0; + #endif + + #ifdef NO_UNUSED + unused = 0; + #endif + + #ifdef NO_VULN + vuln2 = vuln1 = vuln2_w_prot = vuln1_w_prot = 0; + #endif + + // Determine the number of safe moves with options we have. + #ifdef NO_SAFE_OPT + safe_op2 = safe_op1 = safe_op0 = 0; + #else + pack_safe(tmp_board, who_just_moved, &safe_op2, &safe_op1, &safe_op0); + #endif + + /* + if(prot % 2 == 1){ + prot--; + vuln2 += 2; + } + + if(print == 1 && unused > 0 + && prot >= 2 // && (vuln2%3 != 0 || vuln1%2 != 0) + && vuln2 >= 3 && vuln1 >= 2 + && safe_op1 + safe_op0 >= 2){ + print_board(who_just_moved); + } else { + print = 0; + } + */ + #ifdef PRINT_DOES_X_WIN_INFO + if(print){ + fprintf(stderr, "%d just moved, do they win?\n", who_just_moved); + fprintf(stderr, "prot %d, vuln2 %d(%d), vuln1 %d(%d), " + "safe %d, unused %d, empty %d.\n", + prot, vuln2, vuln2_w_prot, vuln1, vuln1_w_prot, + safe, unused, empty); + fprintf(stderr, "safe_op2 %d, safe_op1 %d, safe_op0 %d.\n", + safe_op2, safe_op1, safe_op0); + } + #endif + + { + s32bit moves, opp_moves, x = 0; + + if(prot % 2 == 1){ + prot--; + vuln2 += 2; + } + + moves = (prot) + (vuln2/3) + (vuln1/2) + safe; + + if(vuln2 % 3 != 0 && vuln1 % 2 != 0){ + moves++, unused--, x=1; + // if(vuln2 > 0 || vuln1 > 0) unused--; + } else if(vuln2 % 3 == 0 && vuln1 % 2 == 0) x=1; + + if(x == 1){ + if(safe_op2%2 == 1) safe_op2--, safe_op1++; + if(safe_op1%2 == 1) safe_op1--, safe_op0++; + } else { + if(safe_op2%2 == 1){ + unused += 3; + if(safe_op1%2==1) safe_op1--, safe_op0++; + } else if(safe_op1%2 == 1) { unused += 2; } + else if(safe_op0%2 == 1) { unused += 1; } + } + + unused += vuln2_w_prot - ( (vuln2)/3 - (vuln2-vuln2_w_prot)/3 ); + unused += vuln1_w_prot - ( (vuln1)/2 - (vuln1-vuln1_w_prot)/2 ); + + unused += (safe_op2/2) * 3; + unused += (safe_op1/2) * 2; + unused += (safe_op0/2) * 1; + + opp_moves = (empty - (moves*2) - unused)/2; + + //======================================================== + // If r_value >= 0 then who_just_moved wins. + //======================================================== + r_value = moves - opp_moves; + + #ifdef PRINT_DOES_X_WIN_INFO + if(print){ + printf("moves:%d, opp:%d.\n", moves, opp_moves); + if(moves - opp_moves >= 0) printf("H WINS\n"); + } + #endif + } + + return r_value; + } Index: llvm/test/Programs/MultiSource/Applications/obsequi/globals.h diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/globals.h:1.1 *** /dev/null Tue May 11 14:34:23 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/globals.h Tue May 11 14:34:12 2004 *************** *** 0 **** --- 1,224 ---- + + #ifndef GLOBALS_H + #define GLOBALS_H + + #include "utils.h" + + #include "interface.h" + + #include "structs.h" + #include "consts.h" + + + //######################################################## + // Function prototypes. + //######################################################## + + //======================================================== + // Generate a list of moves that 'player' + // can make in the given position. (excluding safe moves). + // + // The moves are places in the movelist array. + // Returns the number of moves that were placed in movelist. + //======================================================== + s32bit move_generator (Move movelist[MAXMOVES], s32bit player); + + s32bit move_generator_stage1 (Move movelist[MAXMOVES], s32bit player); + + s32bit move_generator_stage2 (Move movelist[MAXMOVES], + s32bit start, s32bit player); + + //================================================================= + // Move ordering uses a simple evaluation function as well as + // a value associated with each position. + // The first two function set these values in a dynamic way. + // The 'set_position_values' function does it statically. + //================================================================= + #ifdef DYNAMIC_POSITION_VALUES + void init_move_value (); + s32bit set_move_value (Move movelist, s32bit player); + void unset_move_value (Move movelist, s32bit player); + #else + void set_position_values (); + #endif + + //======================================================== + // Toggle a move, if a move hasn't been played then play it, if + // it has then undo it. + //======================================================== + void toggle_move (Move move, s32bit player); + + //======================================================== + // Give score of move relative to current position. + //======================================================== + //s32bit score_move(Move move, s32bit player); + void + score_and_get_first(Move movelist[MAXMOVES], s32bit num_moves, + s32bit player, Move first); + + //======================================================== + // Use the value of movelist[i].info to sort the moves in + // descending order. + //======================================================== + void sort_moves(Move movelist[MAXMOVES], s32bit start, s32bit num_moves); + + + void + update_safe(s32bit player, s32bit row); + + void + update_real(s32bit player, s32bit row); + + + void init_less_static_tables(); + + + void init_static_tables(); + + + + // make the bitboard consistent with the info past into this function. + void init__board(s32bit num_rows, s32bit num_cols, s32bit board[30][30]); + + void initialize_tables(); + + + + //######################################################## + // Functions for interacting with the hashtable. + //======================================================== + // Store the current search value into the hashtable if there + // is a position available. + //======================================================== + void hashstore (s32bit value, s32bit alpha, s32bit beta, + u32bit nodes, s32bit depth_remaining, + Move best, s32bit player); + + + //======================================================== + // Check the hashtable to see if we have already seen the current + // position before. + //======================================================== + s32bit hashlookup (s32bit *value, s32bit *alpha, s32bit *beta, + s32bit depth_remaining, + Move *force_first, s32bit player); + + + //######################################################## + // Functions for information display or sanity checks. + //======================================================== + // Functions which varify pieces of information. + //======================================================== + void check_board(); + void check_board_info(); + + void check_hash_code_sanity(); + + + //======================================================== + // Functions which print various pieces of information in a + // readable format. + //======================================================== + void print_board(s32bit player); + void print_board_info(); + void print_bitboard(s32bit player); + void print_hashkey(Hash_Key key); + void print_u64bit(u64bit val); + void print_hashentry(s32bit index); + + + + //######################################################## + // Global variables. + //######################################################## + + extern u64bit g_num_nodes; + + + // two bitboard arrays [0] is horizontals, [1] is verticals. + extern u32bit g_board[2][32]; + + // number of rows and cols in the board. + // [0] is the num of rows, [1] is the num of cols. + extern s32bit g_board_size[2]; + + // keep track of simple info such as real and safe moves. + extern Basic_Info g_info[2][32]; + extern Basic_Info g_info_totals[2]; + extern s32bit g_empty_squares; + + // zobrist value for each position on the board. + extern s32bit g_zobrist[32][32]; + + // Transposition table. + extern Hash_Entry *g_trans_table; + + // Current boards hash key and code (flipped in various ways). + extern Hash_Key g_norm_hashkey; + extern Hash_Key g_flipV_hashkey; + extern Hash_Key g_flipH_hashkey; + extern Hash_Key g_flipVH_hashkey; + + extern s32bit g_first_move[2][32][32]; + + extern s32bit g_move_number[128]; + + + + //######################################################## + // Tables of precalculated information. + // + // Calling initialize_board should initialize the information in + // all these tables. + //######################################################## + + + //======================================================== + // Declare the table we use for updating our hashkey after each move. + //======================================================== + extern KeyInfo g_keyinfo[2][32][32]; + + + //======================================================== + // Declare the table we use in countmoves. + //======================================================== + #ifdef COUNTMOVES_TABLE + extern s32bit move_table16[65536]; + #endif + + + //======================================================== + // Declare the table we use in countbits32. + //======================================================== + #if defined COUNTBITS16 + extern s32bit countbits16[65536]; + + #if defined COUNTBITS8 + #error "Both COUNTBITS8 and COUNTBITS16 are defined." + #endif + + #elif defined COUNTBITS8 + extern s32bit countbits8[256]; + #else + #error "Neither COUNTBITS8 or COUNTBITS16 are defined." + #endif + + + //======================================================== + // Declare the table we use in lastbit32. + //======================================================== + #if defined LASTBIT16 + extern s32bit lastbit16[65536]; + + #if defined LASTBIT8 + #error "Both LASTBIT8 and LASTBIT16 are defined." + #endif + + #elif defined LASTBIT8 + extern s32bit lastbit8[256]; + #else + #error "Neither LASTBIT8 and LASTBIT16 are defined." + #endif + + + #endif //ifndef GLOBALS_H Index: llvm/test/Programs/MultiSource/Applications/obsequi/hash.c diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/hash.c:1.1 *** /dev/null Tue May 11 14:34:23 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/hash.c Tue May 11 14:34:12 2004 *************** *** 0 **** --- 1,109 ---- + + #include "globals.h" + + #define MOVE_TO_INT(mv, player) \ + ((mv).mask_index-1)*g_board_size[(player)]+((mv).array_index-1) + + #define TABLE_SET_KEY(table,index,k) \ + table[index].key[0] = k[0], table[index].key[1] = k[1], \ + table[index].key[2] = k[2], table[index].key[3] = k[3]; + + #define TABLE_CMP_KEY(table,index,k) \ + (table[index].key[0] == k[0] && table[index].key[1] == k[1] && \ + table[index].key[2] == k[2] && table[index].key[3] == k[3]) + + + #define STORE_ENTRY(x) \ + index = (x).code; \ + \ + if(TABLE_CMP_KEY(g_trans_table, index, (x).key) \ + || g_trans_table[index].nodes <= nodes){ \ + TABLE_SET_KEY(g_trans_table, index, (x).key); \ + g_trans_table[index].nodes =nodes; \ + g_trans_table[index].best_move =MOVE_TO_INT(best,player); \ + g_trans_table[index].depth =depth; \ + g_trans_table[index].whos_turn =player; \ + g_trans_table[index].value =value; \ + if (value>=beta) g_trans_table[index].type =LOWER; \ + else if(value>alpha) g_trans_table[index].type =EXACT; \ + else g_trans_table[index].type =UPPER; \ + return; \ + } + + + extern void + hashstore(s32bit value, s32bit alpha, s32bit beta, + u32bit nodes, s32bit depth, Move best, s32bit player) + { + s32bit index; + + STORE_ENTRY(g_norm_hashkey); + STORE_ENTRY(g_flipV_hashkey); + STORE_ENTRY(g_flipH_hashkey); + STORE_ENTRY(g_flipVH_hashkey); + } + + + #define INT_TO_MOVE(mv, int, player) \ + (mv).mask_index = ((int)/g_board_size[(player)])+1; \ + (mv).array_index = ((int)%g_board_size[(player)])+1 + + #define LOOKUP_ENTRY(x) \ + index = (x).code; \ + if(TABLE_CMP_KEY(g_trans_table, index, (x).key) \ + && g_trans_table[index].whos_turn == player ) { \ + /* found matching entry.*/ \ + \ + /* If nothing else we can use this entry to give us a good move. */ \ + INT_TO_MOVE(*force_first, g_trans_table[index].best_move, player); \ + \ + /* use value if depth >= than the depth remaining in our search. */ \ + if(g_trans_table[index].depth >= depth_remaining) { \ + \ + /* if the value is exact we can use it. */ \ + if(g_trans_table[index].type == EXACT) { \ + *value=g_trans_table[index].value; \ + return 1; \ + } \ + \ + /* if value is a lower bound we can possibly use it. */ \ + if(g_trans_table[index].type == LOWER) { \ + if(g_trans_table[index].value>=(*beta)){ \ + *value=g_trans_table[index].value; \ + return 1; \ + } \ + if(g_trans_table[index].value>(*alpha)){ \ + *alpha=g_trans_table[index].value; \ + } \ + return 0; \ + } \ + \ + /* if value is a upper bound we can possibly use it. */ \ + if(g_trans_table[index].type == UPPER) { \ + if(g_trans_table[index].value<=(*alpha)){ \ + *value=g_trans_table[index].value; \ + return 1; \ + } \ + if(g_trans_table[index].value<(*beta)){ \ + *beta=g_trans_table[index].value; \ + } \ + return 0; \ + } \ + } \ + } + + + + extern s32bit + hashlookup(s32bit *value, s32bit *alpha, s32bit *beta, + s32bit depth_remaining, Move *force_first, s32bit player) + { + s32bit index; + + LOOKUP_ENTRY(g_norm_hashkey); + LOOKUP_ENTRY(g_flipV_hashkey); + LOOKUP_ENTRY(g_flipH_hashkey); + LOOKUP_ENTRY(g_flipVH_hashkey); + + return 0; + } Index: llvm/test/Programs/MultiSource/Applications/obsequi/init.c diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/init.c:1.1 *** /dev/null Tue May 11 14:34:23 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/init.c Tue May 11 14:34:12 2004 *************** *** 0 **** --- 1,172 ---- + + #include "globals.h" + + + u32bit g_board[2][32]; + s32bit g_board_size[2] = {-1,-1}; + + Basic_Info g_info[2][32]; + Basic_Info g_info_totals[2]; + + // zobrist value for each position on the board. + s32bit g_zobrist[32][32]; + + // Transposition table. + Hash_Entry *g_trans_table = 0; + + // Current boards hash key and code (flipped in various ways). + Hash_Key norm_hashkey; + Hash_Key flipV_hashkey; + Hash_Key flipH_hashkey; + Hash_Key flipVH_hashkey; + + + extern void + init__safe_count(s32bit player) + { + s32bit i; + + g_info_totals[player].safe = 0; + + for(i = 0; i < g_board_size[player]; i++){ + g_info[player][i+1].safe = 0; + + update_safe(player, i+1); + } + } + + extern void + init__real_count(s32bit player) + { + s32bit i; + + g_info_totals[player].real = 0; + + for(i = 0; i < g_board_size[player]; i++){ + g_info[player][i+1].real = 0; + + update_real(player, i+1); + } + } + + extern void + initialize_solver() + { + s32bit i, j; + + if(g_trans_table == NULL){ + + // first time initialization stuff. + g_trans_table = malloc(HASHSIZE*sizeof(Hash_Entry)); + + // initialize zobrist values + srandom(1); + for(i=1; i<31; i++) { + for(j=1; j<31; j++) { + g_zobrist[i][j] = random() & HASHMASK; + } + } + + init_static_tables(); + } + + init_less_static_tables(); + } + + + + static void + init_hashkey_code(Hash_Key* key) + { + s32bit i, j, index, n_rows, n_cols; + + n_rows = g_board_size[HORIZONTAL], n_cols = g_board_size[VERTICAL]; + + key->code = 0; + + for(i = 0; i < n_rows; i++) + for(j = 0; j < n_cols; j++){ + index = (i*n_cols) + j; + if(key->key[index/32] & NTH_BIT(index%32)) + key->code ^= g_zobrist[i+1][j+1]; + } + } + + extern void + initialize_board(s32bit num_rows, s32bit num_cols, s32bit board[30][30]) + { + s32bit i, j; + s32bit init = 0; + + if(num_rows > 30 || num_rows < 1 || num_cols > 30 || num_cols < 1) + fatal_error(1, "Invalid board size %dX%d.\n", num_rows, num_cols); + + if(num_rows * num_cols >= 128) + fatal_error(1, "Invalid board size %dX%d.\n", num_rows, num_cols); + + // Check if we need to re-initialize the solver. + if(g_trans_table == NULL || g_board_size[HORIZONTAL] != num_rows + || g_board_size[VERTICAL] != num_cols) init = 1; + + g_board_size[HORIZONTAL] = num_rows; + g_board_size[VERTICAL] = num_cols; + + if(init) initialize_solver(); + + // Fill all positions on the board. + for(i = 0; i < 32; i++){ + g_board[0][i] = ALL_BITS; + g_board[1][i] = ALL_BITS; + } + + // Clear positions where there isn't a piece. + for(i = 0; i < num_rows; i++) + for(j = 0; j < num_cols; j++) + if(board[i][j] == 0){ + g_board[HORIZONTAL][i+1] &= ~(NTH_BIT(j+1)); + g_board[VERTICAL][j+1] &= ~(NTH_BIT(i+1)); + } + + init__real_count(VERTICAL); + init__real_count(HORIZONTAL); + + init__safe_count(VERTICAL); + init__safe_count(HORIZONTAL); + + for(i = 0; i < 4; i++){ + g_norm_hashkey.key[i] = 0; + g_flipV_hashkey.key[i] = 0; + g_flipH_hashkey.key[i] = 0; + g_flipVH_hashkey.key[i] = 0; + } + + // Modify hashkeys to deal with positions which are already occupied. + for(i = 0; i < num_rows; i++) + for(j = 0; j < num_cols; j++) + if(board[i][j] != 0){ + s32bit index; + + index = (i*num_cols)+j; + g_norm_hashkey.key[index/32] |= NTH_BIT(index%32); + + index = (i*num_cols) + (num_cols - j - 1); + g_flipV_hashkey.key[index/32] |= NTH_BIT(index%32); + + index = ( (num_rows - i - 1) *num_cols) + j; + g_flipH_hashkey.key[index/32] |= NTH_BIT(index%32); + + index = ( (num_rows - i - 1) *num_cols) + (num_cols - j - 1); + g_flipVH_hashkey.key[index/32] |= NTH_BIT(index%32); + } + + init_hashkey_code(&g_norm_hashkey); + init_hashkey_code(&g_flipV_hashkey); + init_hashkey_code(&g_flipH_hashkey); + init_hashkey_code(&g_flipVH_hashkey); + + print_board(HORIZONTAL); + printf("\n"); + print_board_info(HORIZONTAL); + + check_hash_code_sanity(); + } Index: llvm/test/Programs/MultiSource/Applications/obsequi/interface.h diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/interface.h:1.1 *** /dev/null Tue May 11 14:34:23 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/interface.h Tue May 11 14:34:12 2004 *************** *** 0 **** --- 1,45 ---- + + #ifndef OBSEQUI_INTERFACE_H + #define OBSEQUI_INTERFACE_H + + //######################################################## + // + //######################################################## + void print_external(); + + //######################################################## + // This function initializes the solver. + // + // This includes things like allocating and zeroing data + // for the hashtable. + // + // If it is called a second time it will re-zero all the + // data, (restart from scratch). + //######################################################## + void initialize_solver (); + + + //######################################################## + // This function gives the solver the current board that + // we want to work with. + //######################################################## + void initialize_board (s32bit row, s32bit col, + s32bit board[30][30]); + + + //######################################################## + // This function tries to find the best move for 'player'. + // + // - player is either 'V' or 'H'. + //######################################################## + s32bit search_for_move (char player, + s32bit *row, s32bit *col, u64bit *nodes); + + + //######################################################## + // This function returns a string about the current + // state of the search. + //######################################################## + const char* current_search_state(); + + #endif Index: llvm/test/Programs/MultiSource/Applications/obsequi/macros.h diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/macros.h:1.1 *** /dev/null Tue May 11 14:34:23 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/macros.h Tue May 11 14:34:12 2004 *************** *** 0 **** --- 1,138 ---- + + + #ifndef MACROS_H + #define MACROS_H + + #include "globals.h" + + + //######################################################## + // We use tables to count how many bits are set in a bitmask. + //######################################################## + #ifdef COUNTBITS8 + #define countbits32(x) (countbits8[x&0x000000FF] \ + +countbits8[(x>>8)&0x000000FF]\ + +countbits8[(x>>16)&0x000000FF]\ + +countbits8[(x>>24)&0x000000FF]) + #endif + + #ifdef COUNTBITS16 + #define countbits32(x) (countbits16[x&0x0000FFFF] \ + +countbits16[(x>>16)&0x0000FFFF]) + #endif + + + //######################################################## + // Assume we have a mask with only one bit set - + // we use tables to determine the index of this bit. + //######################################################## + static inline u32bit + lastbit32(u32bit x) + { + #ifdef LASTBIT8 + /* returns the position of the last bit in x */ + if(x&0x000000FF) + return(lastbit8[x&0x000000FF]); + if(x&0x0000FF00) + return(lastbit8[(x>>8)&0x000000FF]+8); + if(x&0x00FF0000) + return(lastbit8[(x>>16)&0x000000FF]+16); + if(x&0xFF000000) + return(lastbit8[(x>>24)&0x000000FF]+24); + return 100; + #endif + + #ifdef LASTBIT16 + /* returns the position of the last bit in x */ + if(x&0x0000FFFF) + return(lastbit16[x&0x0000FFFF]); + if(x&0xFFFF0000) + return(lastbit16[(x>>16)&0x0000FFFF]+16); + return 100; + #endif + } + + + //######################################################## + // Define the function COUNTMOVES. + // This is either a macro or an inline function. + //######################################################## + static inline s32bit + COUNTMOVES_DYN(u32bit mask) + { + s32bit count = 0; + u32bit tmp; + + while(mask){ + tmp = (mask&-mask); // least sig bit of m + mask &= ~(tmp | (tmp << 1)); // remove bit and next bit. + count++; + } + return count; + } + + #ifdef COUNTMOVES_TABLE + #ifdef BOARD_SIZE_LT_16 + //======================================================== + // count moves (assuming small board). + //======================================================== + #define COUNTMOVES(mask) move_table16[(mask)] + + #else + //======================================================== + // count moves (assuming large board). + //======================================================== + static inline s32bit + COUNTMOVES(u32bit mask) + { + s32bit count = 0; + count = move_table16[mask & 0x0000FFFF]; + + if(count&0xF0000000) + count = ((count & 0x0000FFFF) + move_table16[mask >> 16]) & 0x0000FFFE; + else + count = (count + move_table16[mask >> 16]) & 0x0000FFFF; + + return count; + + /* + if(count&ERASE_NEXT_BIT) mask &= ~(NEXT_BIT); + return (count + move_table16[mask >> 16]) & 0x0000FFFF; + */ + } + + #endif + #else + //======================================================== + // count moves (move_table doesn't exist). + //======================================================== + #define COUNTMOVES(mask) COUNTMOVES_DYN(mask) + + #endif + + + + + #define HASHKEY_UPDATE(key,index) key[index/32] ^= NTH_BIT(index%32) + + + #define toggle_hash_code(info) \ + \ + HASHKEY_UPDATE(g_norm_hashkey.key, info.norm.bit1_index); \ + HASHKEY_UPDATE(g_norm_hashkey.key, info.norm.bit2_index); \ + g_norm_hashkey.code ^= info.norm.hash_code; \ + \ + HASHKEY_UPDATE(g_flipV_hashkey.key, info.flipV.bit1_index); \ + HASHKEY_UPDATE(g_flipV_hashkey.key, info.flipV.bit2_index); \ + g_flipV_hashkey.code ^= info.flipV.hash_code; \ + \ + HASHKEY_UPDATE(g_flipH_hashkey.key, info.flipH.bit1_index); \ + HASHKEY_UPDATE(g_flipH_hashkey.key, info.flipH.bit2_index); \ + g_flipH_hashkey.code ^= info.flipH.hash_code; \ + \ + HASHKEY_UPDATE(g_flipVH_hashkey.key, info.flipVH.bit1_index); \ + HASHKEY_UPDATE(g_flipVH_hashkey.key, info.flipVH.bit2_index); \ + g_flipVH_hashkey.code ^= info.flipVH.hash_code; + + + #endif //MACROS_H Index: llvm/test/Programs/MultiSource/Applications/obsequi/move_gen.c diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/move_gen.c:1.1 *** /dev/null Tue May 11 14:34:23 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/move_gen.c Tue May 11 14:34:12 2004 *************** *** 0 **** --- 1,127 ---- + + #include "globals.h" + #include "macros.h" + + //################################################################# + // The following functions are used to generate all the possible + // moves which could be made, for a certain player, given + // the current board position. + //################################################################# + + //================================================================= + // This function generates all the moves in one pass. + //================================================================= + extern s32bit + move_generator(Move movelist[MAXMOVES], s32bit player) + { + s32bit i, count = 0, player_index; + u32bit prot_rows, curr_row, m, tmp; + + // Will be 0 if horizontal, 1 if vertical. + // Appears to be redundant but seems to help the compiler optimize. + player_index = player&PLAYER_MASK; + + for(i = 0; i < g_board_size[player_index]; i++){ + prot_rows = g_board[player_index][i] & g_board[player_index][i+2]; + curr_row = g_board[player_index][i+1]; + + #ifndef PLAY_SAFE_MOVES + // m contains a 1 at each position where there is valid move. + // (except safe moves, there is no need to play them) + m = ~((curr_row|(curr_row>>1)) | (prot_rows&(prot_rows>>1))); + #else + // if you uncomment this it will also play safe moves. + m = ~(curr_row|(curr_row>>1)); + #endif + + while(m){ + tmp = (m&-m); // least sig bit of m + m ^= tmp; // remove least sig bit of m. + movelist[count].mask_index = lastbit32(tmp); + movelist[count].array_index = i+1; + movelist[count].info = 0; + count++; + } + } + + return count; + } + + //================================================================= + // The following functions use a two pass system. This means possibly + // less cost in evaluating (because if we find a cutoff quickly + // we will not have to evaluate the second half) and in sorting the + // moves. + //================================================================= + extern s32bit + move_generator_stage1(Move movelist[MAXMOVES], s32bit player) + { + s32bit i, count = 0; + s32bit player_index; + + u32bit prot_rows, curr_row, m, tmp; + + // will be 0 if horizontal, 1 if vertical. + // This appears to be redundant but it seems to helps the compiler + // optimize. + player_index = player&PLAYER_MASK; + + for(i = 0; i < g_board_size[player_index]; i++){ + prot_rows = g_board[player_index][i] & g_board[player_index][i+2]; + curr_row = g_board[player_index][i+1]; + + // m will contain a 1 at each position that there is a move + // which is a vulnerable move with no protected squares. + m = ~((curr_row|(curr_row>>1)) | (prot_rows|(prot_rows>>1))); + + while(m){ + tmp = (m&-m); // least sig bit of m + m ^= tmp; // remove least sig bit of m. + movelist[count].mask_index = lastbit32(tmp); + movelist[count].array_index = i+1; + movelist[count].info = 0; + count++; + } + } + + return count; + } + + extern s32bit + move_generator_stage2(Move movelist[MAXMOVES], s32bit count, s32bit player) + { + s32bit i, player_index; + u32bit prot_rows, curr_row, m, tmp; + + // will be 0 if horizontal, 1 if vertical. + // This appears to be redundant but it seems to helps the compiler + // optimize. + player_index = player&PLAYER_MASK; + + for(i = 0; i < g_board_size[player_index]; i++){ + prot_rows = g_board[player_index][i] & g_board[player_index][i+2]; + curr_row = g_board[player_index][i+1]; + + #ifndef PLAY_SAFE_MOVES + // m will contain a 1 at each position that there is a move + // which is a vulnerable move with a protected squares. + m = ~((curr_row|(curr_row>>1)) | (~(prot_rows^(prot_rows>>1))) ); + #else + // m will contain a 1 at each position that there is a move + // which is a vulnerable move with a protected squares. + m = ((~((curr_row|(curr_row>>1)) | (prot_rows|(prot_rows>>1)))) + ^ (~(curr_row|(curr_row>>1)))); + #endif + + while(m){ + tmp = (m&-m); // least sig bit of m + m ^= tmp; // remove least sig bit of m. + movelist[count].mask_index = lastbit32(tmp); + movelist[count].array_index = i+1; + movelist[count].info = 0; + count++; + } + } + + return count; + } Index: llvm/test/Programs/MultiSource/Applications/obsequi/move_sort.c diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/move_sort.c:1.1 *** /dev/null Tue May 11 14:34:23 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/move_sort.c Tue May 11 14:34:12 2004 *************** *** 0 **** --- 1,63 ---- + + #include "globals.h" + + //******************************************************** + // Move sorting function. + // + // This is where the program spends some of the larger + // portions of its time. Sometime it should be sped up. + //******************************************************** + + #define NUM_BUCKETS 128 + + //================================================================= + // This is a stable sort algorithm (uses a bucket sort algorithm). + //================================================================= + extern void + sort_moves(Move movelist[MAXMOVES], s32bit start, s32bit num_moves) + { + Move bucket[NUM_BUCKETS][MAXMOVES]; + s32bit buck_val[NUM_BUCKETS]; + s32bit buck_size[NUM_BUCKETS]; + + s32bit num_buckets = 0, i, j; + + // place each move in it's proper bucket. + for(i = start; i < num_moves; i++){ + for(j = 0; j < num_buckets; j++){ + if(movelist[i].info == buck_val[j]){ + bucket[j][buck_size[j]++] = movelist[i]; + break; + } + } + if(j == num_buckets){ + if(j == NUM_BUCKETS) fatal_error(1, "Not enough buckets.\n"); + bucket[j][0] = movelist[i]; + buck_val[j] = movelist[i].info; + buck_size[j] = 1; + num_buckets++; + } + } + + // remove the moves from their buckets in the proper order. + { + s32bit best, index, count = start; + + while(count != num_moves){ + + best = buck_val[0]; + index = 0; + + for(i = 1; i < num_buckets; i++) + if(buck_val[i] > best) index = i, best = buck_val[i]; + + // every bucket must have at least one move. + i = 0; + do { + movelist[count++] = bucket[index][i++]; + } while(i < buck_size[index]); + + buck_val[index] = -5000; + } + } + } Index: llvm/test/Programs/MultiSource/Applications/obsequi/negamax.c diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/negamax.c:1.1 *** /dev/null Tue May 11 14:34:23 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/negamax.c Tue May 11 14:34:12 2004 *************** *** 0 **** --- 1,552 ---- + + #include "globals.h" + #include "macros.h" + + #include + #include + + + //################################################################# + // Statistics gathering variables and functions. + //################################################################# + + //Determines if we should collect this data. + #define COLLECT_STATS + + //================================================================= + // Variables used for statistics gathering. + //================================================================= + #ifdef COLLECT_STATS + static s32bit cut1 = 0, cut2 = 0, cut3 = 0, cut4 = 0; + static s32bit stat_cutoffs[40]; + static s32bit stat_nodes[40]; + static s32bit stat_nth_try[40][10]; + #endif + + //================================================================= + // Print the statistics which we have gathered. + //================================================================= + static void + print_stats() + { + #ifdef COLLECT_STATS + s32bit i, j; + + printf("%d %d %d %d.\n\n", cut1, cut2, cut3, cut4); + + for(i = 0; i < 40; i++){ + if(stat_cutoffs[i] != 0 || stat_nodes[i] != 0){ + printf("cutoffs depth %d: (%d) %d -", + i, stat_nodes[i], stat_cutoffs[i]); + for(j = 0; j < 5; j++) + printf(" %d", stat_nth_try[i][j]); + printf(" >%d.\n", stat_nth_try[i][5]); + } + } + #else + printf("\n"); + #endif + } + + //================================================================= + // Initialize the statistical variables. + //================================================================= + static void + init_stats() + { + #ifdef COLLECT_STATS + s32bit i, j; + + // zero all data. + for(i = 0; i < 40; i++){ + for(j = 0; j < 6; j++) + stat_nth_try[i][j] = 0; + stat_cutoffs[i] = 0; + stat_nodes[i] = 0; + } + #endif + } + + + //################################################################# + // Other variables. + //################################################################# + + //#define RECORD_MOVES + //#define DEBUG_NEGAMAX + + + extern s32bit debug_score_move; + + Hash_Key g_norm_hashkey; + Hash_Key g_flipV_hashkey; + Hash_Key g_flipH_hashkey; + Hash_Key g_flipVH_hashkey; + + u64bit g_num_nodes; + + s32bit g_first_move[2][32][32]; + s32bit g_empty_squares = 0; + + s32bit g_move_number[128]; + + #ifdef RECORD_MOVES + static s32bit g_move_player[128]; + static Move g_move_position[128]; + #endif + + s32bit g_print = 0; + + + static s32bit starting_depth; + + + //################################################################# + // Negamax and driver functions. (and function prototype). + //################################################################# + static s32bit + negamax(s32bit depth_remaining, s32bit whos_turn_t, s32bit alpha, s32bit beta); + + + //================================================================= + // Search for move function. (Negamax Driver) + //================================================================= + extern s32bit + search_for_move(char dir, s32bit *row, s32bit *col, u64bit *nodes) + { + s32bit d, i, value = 0, num_moves; + Move movelist[MAXMOVES]; + s32bit whos_turn; + Move forcefirst; + + // Set who's turn it is. + if(toupper(dir) == 'V') whos_turn = VERTICAL; + else if(toupper(dir) == 'H') whos_turn = HORIZONTAL; + else { fatal_error(1, "Invalid player.\n"); exit(1); } + + // initialize the number of empty squares. + g_empty_squares = 0; + for(i = 0; i < g_board_size[0]; i++) + g_empty_squares += countbits32( (~g_board[0][i+1]) ); + + // zero out all the statistics variables. + init_stats(); + + // Can we already determine a winner? + { + s32bit opponent = whos_turn ^ PLAYER_MASK; + + // stop search if game over. + if(g_info_totals[whos_turn].safe > g_info_totals[opponent].real){ + // current player wins. + *col = *row = -1; + *nodes = 0; + return 5000; + } + + if(g_info_totals[opponent].safe >= g_info_totals[whos_turn].real){ + // opponent wins. + *col = *row = -1; + *nodes = 0; + return -5000; + } + } + + // generate all possible moves for current player given current position. + num_moves = move_generator(movelist, whos_turn); + + // This should never happen. + if(num_moves == 0) fatal_error(1, "No moves"); + + // should possibly sort the whole list instead of just get first. + forcefirst.array_index = -1; + score_and_get_first(movelist, num_moves, whos_turn, forcefirst); + sort_moves(movelist, 1, num_moves); + + // Really this is for iterative deepening. + for(d = 1; d < 50; d += 44){ + + // Initialize alpha and beta. + s32bit alpha = -5000, beta = 5000; + + // Re-initialize the statistics for each iteration. + g_num_nodes = 0; + init_stats(); + + // set what the starting max depth is. + starting_depth = d; + + // iterate through all the possible moves. + for(i = 0; i < num_moves; i++){ + + #ifdef DYNAMIC_POSITION_VALUES + init_move_value(); + set_move_value(movelist[i], whos_turn); + #else + set_position_values(); + #endif + + g_move_number[0] = i; + #ifdef RECORD_MOVES + g_move_player[0] = whos_turn; + g_move_position[0] = movelist[i]; + #endif + + g_empty_squares -= 2; + toggle_move(movelist[i], whos_turn); + toggle_hash_code + (g_keyinfo[whos_turn][movelist[i].array_index][movelist[i].mask_index]); + check_hash_code_sanity(); + + value = -negamax(d-1, whos_turn^PLAYER_MASK, -beta, -alpha); + + #ifdef DYNAMIC_POSITION_VALUES + unset_move_value(movelist[i], whos_turn); + #endif + + g_empty_squares += 2; + toggle_move(movelist[i], whos_turn); + toggle_hash_code + (g_keyinfo[whos_turn][movelist[i].array_index][movelist[i].mask_index]); + check_hash_code_sanity(); + + printf("Move (%d,%d), value %d: %s.\n", + movelist[i].array_index, movelist[i].mask_index, + value, u64bit_to_string(g_num_nodes)); + printf("alpha %d, beta %d.\n", alpha, beta); + + movelist[i].info = value; + + if(value >= beta){ + alpha = value; + break; + } + if(value > alpha) { + alpha = value; + } + } + + if(value >= 5000){ + printf("Winner found: %d.\n", value); + if(whos_turn == HORIZONTAL){ + *row = movelist[i].array_index; + *col = movelist[i].mask_index; + } else if(whos_turn == VERTICAL){ + *col = movelist[i].array_index; + *row = movelist[i].mask_index; + } else { + fatal_error(1, "oops."); + } + + *nodes = g_num_nodes; + + print_stats(); + + return value; + } + + // remove lossing moves from movelist. + { + s32bit rem = 0; + for(i = 0; i < num_moves; i++){ + if(movelist[i].info <= -5000) rem++; + else if(rem > 0) movelist[i-rem] = movelist[i]; + } + num_moves -= rem; + /* + for(i = 0; i < num_moves; i++){ + printf("(%d,%d): %d.\n", + movelist[i].array_index, movelist[i].mask_index, + movelist[i].info); + } + */ + } + + print_stats(); + + if(num_moves == 0){ + break; + } + + // use a stable sort algorithm + { + Move swp; + s32bit max, index, j; + + for(i=0; i max){ + max = movelist[j].info; + index = j; + } + + if(index != i){ + swp = movelist[index]; + // printf("%d %d\n", index, i); + for(j = index; j != i; j--){ + movelist[j] = movelist[j-1]; + } + movelist[i] = swp; + } + } + } + + printf("The value is %d at a depth of %d.\n", value, d); + printf("Nodes: %u.\n", (u32bit)g_num_nodes); + } + + *col = *row = -1; + *nodes = g_num_nodes; + + return value; + } + + + //================================================================= + // Negamax Function. + //================================================================= + static s32bit + negamax(s32bit depth_remaining, s32bit whos_turn_t, s32bit alpha, s32bit beta) + { + Move movelist[MAXMOVES], best; + s32bit whos_turn = whos_turn_t & PLAYER_MASK; + s32bit opponent = whos_turn_t ^ PLAYER_MASK; + s32bit value; + s32bit init_alpha = alpha, init_beta = beta; + u32bit start_nodes = g_num_nodes; + Move forcefirst; + s32bit who_wins_value; + + s32bit stage = 0, state = 0, true_count, i = 0, num_moves = 1; + + #ifdef DYNAMIC_POSITION_VALUES + s32bit dyn_set; + #endif + + // increment a couple of stats + g_num_nodes++; + #ifdef COLLECT_STATS + stat_nodes[starting_depth - depth_remaining]++; + #endif + + // if no depth remaining stop search. + if( depth_remaining <= 0 ){ + s32bit a = 0, b = 0; + + if( (a = does_next_player_win(whos_turn, 0)) > 0 ) { + // current player wins. + return 5000; + } + + if( (b = does_who_just_moved_win(opponent, 0)) >= 0 ) { + // opponent wins. + return -5000; + } + + return a - b; + } + + + //------------------------------------------ + // Can we determine a winner yet (simple check). + //------------------------------------------ + + // does current player win + if(g_info_totals[whos_turn].safe > g_info_totals[opponent].real){ + #ifdef COLLECT_STATS + cut1++; + #endif + return 5000; + } + + // does opponent win + if(g_info_totals[opponent].safe >= g_info_totals[whos_turn].real){ + #ifdef COLLECT_STATS + cut2++; + #endif + return -5000; + } + + + //------------------------------------------ + // check transposition table + //------------------------------------------ + + forcefirst.array_index = -1; + if(hashlookup(&value, &alpha, &beta, depth_remaining, + &forcefirst, whos_turn)) + return value; + // since we aren't using iter deep not interested in forcefirst. + forcefirst.array_index = -1; + + + //------------------------------------------ + // Can we determine a winner yet (look harder). + //------------------------------------------ + + // does current player win + if( (who_wins_value = does_next_player_win(whos_turn, 0)) > 0 ) { + + #ifdef DEBUG_NEGAMAX + if(random() % 1000000 == -1){ + does_next_player_win(whos_turn, 1); + print_board(whos_turn); + } + #endif + + #ifdef COLLECT_STATS + cut3++; + #endif + return 5000; + } + + // does opponent win + if( (who_wins_value = does_who_just_moved_win(opponent, 0)) >= 0 ) { + + #ifdef DEBUG_NEGAMAX + if(who_wins_value < 3){ // && random() % 500 == -1){ + does_who_just_moved_win(opponent, 1); + // print_board(opponent); + } + #endif + + #ifdef COLLECT_STATS + cut4++; + #endif + return -5000; + } + + #if 0 + { + s32bit num; + num = move_generator_stage1(movelist, whos_turn); + num = move_generator_stage2(movelist, num, whos_turn); + if(move_generator(movelist, whos_turn) != num) + fatal_error(1, "NOPE\n"); + } + #endif + + + //------------------------------------------ + // Generate child nodes and examine them. + //------------------------------------------ + + // initialize a few variables. (some of them don't really need to be.) + stage = state = true_count = i = 0; + num_moves = 1; + + #ifdef TWO_STAGE_GENERATION + true_count = move_generator_stage1(movelist, whos_turn); + if(true_count == 0){ + true_count = move_generator_stage2(movelist, 0, whos_turn); + stage = 1; + if(true_count == 0) fatal_error(1, "Should always have a move.\n"); + } + #else + true_count = move_generator(movelist, whos_turn); + stage = 1; + if(true_count == 0) fatal_error(1, "Should always have a move.\n"); + #endif + + // score all the moves and move the best to the front. + score_and_get_first(movelist, true_count, whos_turn, forcefirst); + + best = movelist[0]; + + // need to sort moves and generate more moves in certain situations. + while(state < 3){ + if(state == 0) { + state = 1; + } else if(state == 1){ + sort_moves(movelist, 1, true_count); + num_moves = true_count; + if(stage == 0) state = 2; + else state = 3; + } else { + num_moves = move_generator_stage2(movelist, num_moves, whos_turn); + state = 3; + } + + // Iterate through all the moves. + for(; i < num_moves; i++){ + + // A few statistics + g_move_number[starting_depth - depth_remaining] = i; + #ifdef RECORD_MOVES + g_move_player[starting_depth - depth_remaining] = whos_turn; + g_move_position[starting_depth - depth_remaining] = movelist[i]; + #endif + + // make move. + g_empty_squares -= 2; + toggle_move(movelist[i], whos_turn); + toggle_hash_code + (g_keyinfo[whos_turn][movelist[i].array_index][movelist[i].mask_index]); + #ifdef DYNAMIC_POSITION_VALUES + dyn_set = set_move_value(movelist[i], whos_turn); + #endif + + // recurse. + value = -negamax(depth_remaining-1,whos_turn^PLAYER_MASK, + -beta, -alpha); + + // undo move. + g_empty_squares += 2; + toggle_move(movelist[i], whos_turn); + toggle_hash_code + (g_keyinfo[whos_turn][movelist[i].array_index][movelist[i].mask_index]); + #ifdef DYNAMIC_POSITION_VALUES + if(dyn_set != 0) unset_move_value(movelist[i], whos_turn); + #endif + + #if 0 + if(starting_depth - depth_remaining == 8) { + s32bit g; + + printf("goof:"); + + for(g = 0; g < 8; g++){ + printf(" :%c:%d(%d,%d)", + (g_move_player[g] == VERTICAL) ? 'V' : 'H', + g_move_number[g], + g_move_position[g].array_index - 1, + g_move_position[g].mask_index - 1); + } + printf("\n"); + } + #endif + + // If this is a cutoff, break. + if(value >= beta){ + alpha = value; + best = movelist[i]; + + #ifdef COLLECT_STATS + stat_cutoffs[starting_depth - depth_remaining]++; + if(i < 5) stat_nth_try[starting_depth - depth_remaining][i]++; + else stat_nth_try[starting_depth - depth_remaining][5]++; + #endif + break; + } + + // If the current value is greater than alpha, increase alpha. + if(value > alpha) { + alpha = value; + best = movelist[i]; + } + } + + // If we have broken out of previous FOR loop make sure we break out + // of this loop as well. + if(value >= beta) break; + } + + // save the position in the hashtable + hashstore(alpha, init_alpha, init_beta, (g_num_nodes - start_nodes) >> 5, + depth_remaining, best, whos_turn); + + return alpha; + } Index: llvm/test/Programs/MultiSource/Applications/obsequi/obsequi.c diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/obsequi.c:1.1 *** /dev/null Tue May 11 14:34:23 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/obsequi.c Tue May 11 14:34:12 2004 *************** *** 0 **** --- 1,620 ---- + //******************************************************** + // This file part of my Obsequi front end. + //******************************************************** + // + // Copyright (C) 2001 Nathan Bullock + // + // This program is free software; you can redistribute it and/or modify + // it under the terms of the GNU General Public License as published by + // the Free Software Foundation; either version 2 of the License, or + // (at your option) any later version. + // + // This program is distributed in the hope that it will be useful, + // but WITHOUT ANY WARRANTY; without even the implied warranty of + // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + // GNU General Public License for more details. + // + // You should have received a copy of the GNU General Public License + // along with this program; if not, write to the Free Software + // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + // + //******************************************************** + // Email address - bullock at cs.ualberta.ca + // Web address - www.cs.ualberta.ca/~bullock + //******************************************************** + + #include "utils.h" + + #include + #include + #include + #include + #include + + #include "cppflags.h" + #include "interface.h" + + + //######################################################## + // Function templates. + //######################################################## + + // handle command line options. + static void decode_switches (int argc, char **argv); + + // signal handlers. + static void sig_int_setup (); + static void sig_int_handler (int sig); + static void sig_alrm_setup (); + static void sig_alrm_handler (int sig); + static void sig_block (); + static void set_stop_alrm (long minutes); + + // main command loop functions. + static void get_solve_command (); + + // lock file stuff. + static void get_solve_command_from_lock_file(); + static void write_to_lock_file(char winner, const char* num_nodes); + + + //######################################################## + // Global variables. + //######################################################## + + // Determines if we will have an alarm checking the input every so often. + static s32bit main_batch = 1; + + // Determines if we should be reading a lock file and what it's name is. + static char *lock_file = NULL; + + // Determines if we should be stopping program after x minutes. + static long stop_minutes = 0; + + static char main_whos_turn; + + + //######################################################## + // Entry point to obsequi. + //######################################################## + int + main(int argc, char** argv) + { + decode_switches(argc, argv); + + if(lock_file){ + get_solve_command_from_lock_file(); + if(stop_minutes) set_stop_alrm(stop_minutes); + } else { + get_solve_command(); + if(!main_batch) sig_alrm_setup(); + } + + sig_int_setup(); + + // start solver. + { + s32bit row, col; + u64bit nodes; + s32bit score; + const char* num_nodes; + + score = search_for_move(main_whos_turn, &row, &col, &nodes); + + sig_block(); + + num_nodes = u64bit_to_string(nodes); + + // print results. + if(score >= 5000){ + printf("winner %c, move (%d,%d), nodes %s.\n", + main_whos_turn, row, col, num_nodes); + } else if(score <= 5000){ + printf("winner %c, move (%d,%d), nodes %s.\n", + (main_whos_turn == 'V') ? 'H' : 'V', + row, col, num_nodes); + } else { + printf("Undecided, Best score: %d, nodes %s.\n", + score, num_nodes); + } + + fflush(stdout); + + if(lock_file){ + char winner = 0; + + if(score >= 5000) winner = main_whos_turn; + else if(score <= -5000) winner = (main_whos_turn == 'V') ? 'H' : 'V'; + else fatal_error(1, "Undecided.\n"); + + write_to_lock_file(winner, num_nodes); + } + } + + // if not in batch mode don't exit until stdin has been closed. + fcntl(STDIN_FILENO, F_SETFL, 0); + if (!main_batch){ + while(getchar() != EOF); + } + + return 0; + } + + + //######################################################## + // Main input - output commands. + //######################################################## + + //======================================================== + // This function reads stdin one line at a time. + // It initializes the solver engine when it finds a line of the format: + // + // "solve rows m cols n bx0,y0;x1,y1;...;x,y f" + // where: + // - m is the number of rows. + // - n is the number of cols. + // - bx0,y0 is the position of a block on the board. + // - f is H if it is horizontals turn and V if verticals turn. + // + // It discards all input which does not match this format and + // writes an error message to stderr. + //======================================================== + static void + get_solve_command() + { + char* line = NULL, *blocks = NULL; + size_t line_size = 0, len; + + // Board info for the board which we are solving. + u32bit num_rows; + u32bit num_cols; + s32bit board[30][30]; + char c1, c2; + + s32bit r, c; + + while( (len = getline(&line, &line_size, stdin)) != -1){ + s32bit t; + + if(len > 0){ + if(blocks != NULL) blocks = realloc(blocks, line_size); + else blocks = malloc(line_size); + } else continue; + line[len - 1] = 0; + + t = sscanf(line, "solve rows %u cols %u %c%s %c", + &num_rows, &num_cols, &c1, blocks, &c2); + + if(t != 3 && t != 5){ + fprintf(stderr, "Invalid command: '%s'.\n", line); + continue; + } + + if(num_rows > 30){ + fprintf(stderr, "Too many rows: %u > 30.\n", num_rows); + continue; + } + + if(num_cols > 30){ + fprintf(stderr, "Too many cols: %u > 30.\n", num_cols); + continue; + } + + if(num_cols * num_rows > 256){ + fprintf(stderr, + "Search space too large: %u > 256.\n", num_cols*num_rows); + continue; + } + + for(r = 0; r < 30; r++) + for(c = 0; c < 30; c++) board[r][c] = 0; + + if(t == 5) { + char *tok; + + c1 = toupper(c1); + if(c1 != 'B') { + fprintf(stderr, "Invalid command: '%s'.\n", line); + continue; + } + + tok = strtok(blocks, ";"); + while(tok != NULL){ + if(sscanf(tok, "%u,%u", &r, &c) != 2){ + fprintf(stderr, "Invalid block string: '%s'.\n", tok); + c1 = 0; + break; + } + if(r >= num_rows || c >= num_cols){ + fprintf(stderr, "Invalid block string: '%s'.\n", tok); + c1 = 0; + break; + } + + board[r][c] = 1; + + tok = strtok(NULL, ";"); + } + if(c1 == 0) continue; + } else { + c2 = c1; + } + + c2 = toupper(c2); + if(c2 != 'V' && c2 != 'H'){ + fprintf(stderr, "Invalid players turn: %c.\n", c2); + continue; + } + + // everything should be initialized properly at this point. + printf("Starting\n"); + fflush(stdout); + break; + } + + if(len == -1) fatal_error(1, "No valid command given.\n"); + + /* + main_num_rows = num_rows; + main_num_cols = num_cols; + + for(r = 0; r < 30; r++) + for(c = 0; c < 30; c++) + main_board[r][c] = board[r][c]; + */ + main_whos_turn = c2; + + initialize_board(num_rows, num_cols, board); + + //print_external(); exit(0); + + free(line); + free(blocks); + } + + + //======================================================== + // Non blocking input loop. + //======================================================== + static void + get_other_commands() + { + static size_t line_size; + static char *line; + char c1; + + fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); + + // get next line of input, exit at end of input. + while (getline(&line, &line_size, stdin) > 0){ + + printf(line); + + // stop the search. + if(sscanf(line, "stop%c", &c1) == 1){ + exit(0); + } + + /* + // print info (whatever that is). + else if(sscanf(line, "info%c", &c1) == 1){ + stringify_stack(&line, &line_size); + fprintf(stderr, "%s", line); + } + */ + + else { + fprintf(stderr, "Invalid command.\n"); + } + } + + fflush(stderr); + clearerr(stdin); + } + + + //######################################################## + // Obsequi takes a number of arguments + // -e print flags used at compile time. + // -h print out help message and exit. + // -l specify file which contains a position to solve. + // -t specify maximum time limit for solving position. + // only works when using a "lock file" -l. + // -v print version information. + // -w wait for standard in to be closed before exiting. + //######################################################## + static void + decode_switches(int argc, char **argv) + { + int c; + + while ((c = getopt(argc, argv, "wehl:t:v")) != -1){ + switch(c){ + case 'e': + printf(option_string); + exit(0); + + case 'h': + printf("No help available in this version.\n"); + exit(0); + + case 'l': + lock_file = strdup(optarg); + break; + + case 't': + stop_minutes = atoi(optarg); + break; + + case 'v': + printf("No version info available.\n"); + exit(0); + + case 'w': + main_batch = 0; + break; + + default: + fatal_error(1, "Invalid option: '-%c'.\n", c); + } + } + + if(optind < argc) + fatal_error(1, "Extra unknown options on command line.\n"); + } + + + + //######################################################## + // Signal handling stuff. + //######################################################## + + //======================================================== + // sig int stuff + //======================================================== + static void + sig_int_handler(int sig) + { + const char* str; + + str = current_search_state(); + + fprintf(stderr, "%s\n", str); + + fflush(stderr); + } + + static void + sig_int_setup() + { + struct sigaction act; + + // sigemptyset(&act.sa_mask); + sigfillset(&act.sa_mask); + act.sa_flags = 0; + + act.sa_handler = sig_int_handler; + if ( sigaction(SIGINT, &act, NULL) ) + fatal_error(1, "`sigaction' failed."); + } + + + //======================================================== + // sig alarm stuff + //======================================================== + static void + sig_alrm_handler(int sig) + { + get_other_commands(); + } + + static void + stop_alrm_handler(int sig) + { + exit(0); + } + + static void + set_stop_alrm(long minutes) + { + struct sigaction act; + struct itimerval itime; + + // sigemptyset(&act.sa_mask); + sigfillset(&act.sa_mask); + act.sa_flags = 0; + + act.sa_handler = stop_alrm_handler; + if ( sigaction(SIGVTALRM, &act, NULL) ) + fatal_error(1, "`sigaction' failed."); + + itime.it_interval.tv_sec = minutes * 60; + itime.it_interval.tv_usec = 0; + itime.it_value.tv_sec = minutes * 60; + itime.it_value.tv_usec = 0; + + if ( setitimer(ITIMER_VIRTUAL, &itime, NULL) ) + fatal_error(1, "`setitimer' failed.\n"); + } + + static void + sig_alrm_setup() + { + struct sigaction act; + struct itimerval itime; + + // sigemptyset(&act.sa_mask); + sigfillset(&act.sa_mask); + act.sa_flags = 0; + + act.sa_handler = sig_alrm_handler; + if ( sigaction(SIGALRM, &act, NULL) ) + fatal_error(1, "`sigaction' failed."); + + itime.it_interval.tv_sec = 2; + itime.it_interval.tv_usec = 0; + itime.it_value.tv_sec = 1; + itime.it_value.tv_usec = 0; + + if ( setitimer(ITIMER_REAL, &itime, NULL) ) + fatal_error(1, "`setitimer' failed.\n"); + } + + + //======================================================== + // block all new signals stuff + //======================================================== + static void + sig_block() + { + sigset_t set; + sigemptyset(&set); + sigaddset(&set, SIGALRM); + sigaddset(&set, SIGINT); + + sigprocmask(SIG_BLOCK, &set, NULL); + } + + + //######################################################## + // Lock and read lock file. + //######################################################## + + //======================================================== + // Some local variables for the lock file stuff. + //======================================================== + static s32bit lock_file_offset; + + static s32bit + next_valid_pos(const char *line, s32bit line_pos) + { + s32bit i, state = 0; + for(i = line_pos; line[i] != 0; i++){ + if(line[i] == ' ') { + if(state != 0) state = 2; + } else { + if(state == 2) break; + state = 1; + } + } + return i; + } + + + static void + write_to_lock_file(char winner, const char* num_nodes) + { + FILE* file = NULL; + + if( (file = fopen(lock_file, "r+")) == NULL ) + fatal_error(1, "Can't open file.\n"); + + // if(lockf(fileno(file), F_LOCK, 0) != 0) + // fatal_error(1, "Lock failed.\n"); + + printf("%s\n", lock_file); + + fseek(file, lock_file_offset, SEEK_SET); + fprintf(file, "%c %15s", winner, num_nodes); + fflush(file); + + // lockf(fileno(file), F_ULOCK, 0); + fclose(file); + } + + + static void + get_solve_command_from_lock_file() + { + FILE* file = NULL; + + char* line = NULL; + size_t line_size = 0, len, line_pos; + + // Board info for the board which we are solving. + u32bit num_rows; + u32bit num_cols; + s32bit board[30][30]; + char player = 0; + + s32bit r, c; + + if( (file = fopen(lock_file, "r+")) == NULL ) + fatal_error(1, "Can't open file.\n"); + + // if(lockf(fileno(file), F_LOCK, 0) != 0) + // fatal_error(1, "Lock failed.\n"); + + printf("%s\n", lock_file); + + while( lock_file_offset = ftell(file), + (len = getline(&line, &line_size, file)) != -1){ + // if line has a length of 0 line[0] will be '\0'. + if(line[0] != 'A') continue; + + printf("%s", line); + + if(len <= 18) fatal_error(1, line); + + if(sscanf(line + 18, "(%d,%d)", &num_rows, &num_cols) != 2) + fatal_error(1, "Invalid row and columns.\n%s\n", line); + + if(num_rows > 30) + fatal_error(1, "Too many rows: %u > 30.\n", num_rows); + if(num_cols > 30) + fatal_error(1, "Too many cols: %u > 30.\n", num_cols); + if(num_cols * num_rows > 128) + fatal_error(1, "Search space too large: %u > 256.\n", num_cols*num_rows); + + for(r = 0; r < 30; r++) + for(c = 0; c < 30; c++) board[r][c] = 0; + + line_pos = 18; + + while(1){ + s32bit ignore; + + line_pos = next_valid_pos(line, line_pos); + + if(line_pos >= len) break; + + if(sscanf(line + line_pos, ":%c:%d(%d,%d)", &player, + &ignore, &r, &c) != 4) + break; + + printf("%c %d %d\n", player, r, c); + + if(player == 'V'){ + if(board[c][r] == 1 || board[c+1][r] == 1) + fatal_error(1, line); + board[c][r] = board[c+1][r] = 1; + } else if(player == 'H'){ + if(board[r][c] == 1 || board[r][c+1] == 1) + fatal_error(1, line); + board[r][c] = board[r][c+1] = 1; + } else fatal_error(1, "Invalid player.\n"); + } + + // everything should be initialized properly at this point. + printf("Starting\n"); + fflush(stdout); + break; + } + + if(len == -1) fatal_error(1, "No valid command given.\n"); + + fseek(file, lock_file_offset, SEEK_SET); + fprintf(file, "W"); + fflush(file); + + if(player == 'V') main_whos_turn = 'H'; + else if(player == 'H') main_whos_turn = 'V'; + else fatal_error(1, "Invalid player.\n"); + + initialize_board(num_rows, num_cols, board); + + free(line); + + // lockf(fileno(file), F_ULOCK, 0); + fclose(file); + } Index: llvm/test/Programs/MultiSource/Applications/obsequi/position_values.c diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/position_values.c:1.1 *** /dev/null Tue May 11 14:34:23 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/position_values.c Tue May 11 14:34:13 2004 *************** *** 0 **** --- 1,178 ---- + + + #include "globals.h" + + //################################################################# + // Give all the positions for this PLAYER which are symmetrical + // to the position (ROW, COL) a value of VALUE. + //################################################################# + static void + set_position_value(s32bit player, s32bit row, s32bit col, s32bit value) + { + s32bit num_rows, num_cols; + + num_rows = g_board_size[player] + 1; + num_cols = g_board_size[player^PLAYER_MASK]; + + //printf("1 - %d %d %d\n", player, row, col); + g_first_move[player][row][col] = value; + //printf("2 - %d %d %d\n", player, num_rows-row, col); + g_first_move[player][num_rows-row][col] = value; + //printf("3 - %d %d %d\n", player, num_rows-row, num_cols-col); + g_first_move[player][num_rows-row][num_cols-col] = value; + // printf("4 - %d %d %d\n", player, row, num_cols-col); + g_first_move[player][row][num_cols-col] = value; + } + + + #ifdef DYNAMIC_POSITION_VALUES + //################################################################# + // If we are using dynamic position values then these are the + // functions (and variables) which we use to set these values. + //################################################################# + + //================================================================= + // Variable to keep track of value we will give to the next position. + //================================================================= + static s32bit set_move_value_current = 127; + + //================================================================= + // Initialize all positions with a value of 0 + //================================================================= + extern void + init_move_value () + { + s32bit i, j, k; + set_move_value_current = 127; + + for(i = 0; i < 2; i++) + for(j = 0; j < 32; j++) + for(k = 0; k < 32; k++) + g_first_move[i][j][k] = 0; + } + + //================================================================= + // Set the value of the positions symetrical to MOVE. + // return 0 if these positions already have a value, otherwise 1. + //================================================================= + extern s32bit + set_move_value (Move move, s32bit player) + { + if(g_first_move[player][move.array_index][move.mask_index] != 0) + return 0; + + set_position_value(player, move.array_index, move.mask_index, + set_move_value_current--); + return 1; + } + + //================================================================= + // UnSet the value of the positions symetrical to MOVE. + // Shouldn't be called if when 'set' was called it returned a value of 0. + //================================================================= + extern void + unset_move_value (Move move, s32bit player) + { + set_move_value_current + = g_first_move[player][move.array_index][move.mask_index]; + + set_position_value(player, move.array_index, move.mask_index, 0); + } + + #else + //################################################################# + // If we are using dynamic position values then these are the + // functions which we use to set these values. + //################################################################# + + //================================================================= + // Set the value of all the positions on the board. + // We only do this once at the start of the search. + //================================================================= + extern void + set_position_values() + { + s32bit i, j, k, count; + + // set them all to zero. + for(i = 0; i < 2; i++) + for(j = 0; j < 32; j++) + for(k = 0; k < 32; k++) + g_first_move[i][j][k] = 0; + + #if 0 + // Set values using very simple scheme. + for(i = 0; i < 2; i++){ + count = 64; + for(j = 1; j < (g_board_size[i]+3)/2; j++){ + for(k = 1; k < (g_board_size[i^PLAYER_MASK]/2)+1; k++){ + if(g_first_move[i][j][k] == 0) + set_position_value(i, j, k, --count); + } + } + } + #elif 1 + // Set values using a more complex (seems to be better) scheme. + for(i = 0; i < 2; i++){ + count = 127; + for(j = 2; j < (g_board_size[i]+3)/2; j+=2){ + for(k = 1; k < (g_board_size[i^PLAYER_MASK]/2)+1; k+=2){ + set_position_value(i, j, k, --count); + } + } + } + for(i = 0; i < 2; i++){ + count = 90; + for(j = 2; j < (g_board_size[i]+3)/2; j+=2){ + for(k = 1; k < (g_board_size[i^PLAYER_MASK]/2)+1; k++){ + if(g_first_move[i][j][k] == 0) + set_position_value(i, j, k, --count); + } + } + } + for(i = 0; i < 2; i++){ + count = 70; + for(j = 3; j < (g_board_size[i]+3)/2; j++){ + for(k = 1; k < (g_board_size[i^PLAYER_MASK]/2)+1; k+=2){ + if(g_first_move[i][j][k] == 0) + set_position_value(i, j, k, --count); + } + } + } + for(i = 0; i < 2; i++){ + count = 50; + for(j = 3; j < (g_board_size[i]+3)/2; j++){ + for(k = 1; k < (g_board_size[i^PLAYER_MASK]/2)+1; k++){ + if(g_first_move[i][j][k] == 0) + set_position_value(i, j, k, --count); + } + } + } + for(i = 0; i < 2; i++){ + count = 30; + for(j = 1; j < (g_board_size[i]+3)/2; j++){ + for(k = 1; k < (g_board_size[i^PLAYER_MASK]/2)+1; k++){ + if(g_first_move[i][j][k] == 0) + set_position_value(i, j, k, --count); + } + } + } + #endif + + // print the values. (mostly for debugging) + #if 0 + for(i = 0; i < 2; i++){ + for(j = 0; j < 32; j++){ + for(k = 0; k < 32; k++){ + printf("%d ", g_first_move[i][j][k]); + } + printf("\n"); + } + printf("\n"); + } + exit(0); + #endif + + } + + #endif Index: llvm/test/Programs/MultiSource/Applications/obsequi/structs.h diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/structs.h:1.1 *** /dev/null Tue May 11 14:34:23 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/structs.h Tue May 11 14:34:13 2004 *************** *** 0 **** --- 1,266 ---- + + + #ifndef STRUCTS_H + #define STRUCTS_H + + #include "utils.h" + + //######################################################## + // Basic board info which we keep track of. + //######################################################## + typedef struct + { + s32bit safe; + s32bit real; + s32bit mobility; + } Basic_Info; + + + //######################################################## + // Info we need to describe a move. + //######################################################## + typedef struct + { + s32bit array_index; + s32bit mask_index; + s32bit info; + } Move; + + + //######################################################## + // Info we need for each entry in the hashtable. + //######################################################## + typedef struct + { + // uniquely identifies a board position. + u32bit key[4]; + + // if real num of nodes exceeds ULONG_MAX set to ULONG_MAX. + // or maybe we could just shift the bits (larger granularity). + u32bit nodes; + + // uniquely identifies the previous best move for this position. + u8bit best_move; + + // depth of the search when this value was determined. + u8bit depth : 7; + + // whos turn it is. + u8bit whos_turn : 1; + + // value of node determined with a search to `depth`. + s16bit value : 14; + + // value of node determined with a search to `depth`. + u16bit type : 2; //UPPER, LOWER, EXACT. + } Hash_Entry; + + + //######################################################## + // structure used to store current key and it's hash code. + //######################################################## + typedef struct + { + u32bit key[4]; + s32bit code; + } Hash_Key; + + + //######################################################## + // table_keyinfo + //######################################################## + typedef struct + { + s32bit bit1_index; + s32bit bit2_index; + u32bit hash_code; + } KeyInfo_s; + + typedef struct + { + KeyInfo_s norm; + KeyInfo_s flipV; + KeyInfo_s flipH; + KeyInfo_s flipVH; + } KeyInfo; + + #endif + + #ifndef STRUCTS_H + + extern void + hashstore(s32bit value, s32bit alpha, s23bit beta, + u64bit nodes, int depth, struct move best, int color) + { + /* write the record anyway where the index is*/ + int32 index, minindex; + int mindepth=1000,iter=0; + int from,to; + + if(depth<0) return; + hashstores++; + + if(realdepth < DEEPLEVEL) { + /* its in the "deep" hashtable: take care not to overwrite other entries */ + index=Gkey&HASHMASKDEEP; + minindex=index; + while(iter=beta) {deep[index].info|=LOWER;return;} + if(value>alpha) {deep[index].info|=EXACT;return;} + deep[index].info|=UPPER; + return; + } else { + if( hashdepth(deep[index].info) < mindepth) { + minindex=index; + mindepth=hashdepth(deep[index].info); + } + } + iter++; + index++; + index=index&HASHMASKDEEP; + } + /* if we arrive here it means we have gone through all hashiter + entries and all were occupied. in this case, we write the entry + to minindex */ + if(mindepth>(depth)) return; + deep[minindex].lock=Glock; + deep[minindex].info=(int16) (depth); + if(color==BLACK) + deep[minindex].best=best.bm|best.bk; + else + deep[minindex].best=best.wm|best.wk; + deep[minindex].info|=(int16)((color>>1)<<13); + deep[minindex].value=value; + /* determine valuetype */ + if(value>=beta) {deep[minindex].info|=LOWER;return;} + if(value>alpha) {deep[minindex].info|=EXACT;return;} + deep[minindex].info|=UPPER; + return; + /* and return */ + } else { + index=Gkey&HASHMASKSHALLOW; + if( hashdepth(shallow[index].info) <= depth ) + /* replace the old entry if the new depth is larger */ + { + shallow[index].lock=Glock; + shallow[index].info=(int16)depth; + shallow[index].value=(sint16)value; + if(color==BLACK) + { + shallow[index].best=best.bm|best.bk; + shallow[index].info|=HASHBLACK; + } + else + shallow[index].best=best.wm|best.wk; + + /* determine valuetype */ + + if(value>=beta) {shallow[index].info|=LOWER;return;} + if(value>alpha) {shallow[index].info|=EXACT;return;} + shallow[index].info|=UPPER; + } + } + return; + } + + int hashlookup(int *value, int *alpha, int *beta, int depth, int32 *forcefirst, int color) + { + int32 index; + int iter=0; + + hashsearch++; + + if(realdepth>13)==(color>>1)) + { + /* we have found the position */ + hashhit++; + /* move ordering */ + *forcefirst=deep[index].best; + /* use value if depth in hashtable >= current depth)*/ + if(hashdepth(deep[index].info)>=depth) + { + /* if it's an exact value we can use it */ + if(hashvaluetype(deep[index].info) == EXACT) + { + *value=deep[index].value; + return 1; + } + /* lower bound */ + if(hashvaluetype(deep[index].info) == LOWER) + { + if(deep[index].value>=(*beta)) {*value=deep[index].value;return 1;} + if(deep[index].value>(*alpha)) {*alpha=deep[index].value;} + return 0; + } + /* upper bound */ + if(hashvaluetype(deep[index].info) == UPPER) + { + if(deep[index].value<=*alpha) {*value=deep[index].value;return 1;} + if(deep[index].value<*beta) {*beta=deep[index].value;} + return 0; + } + } + } + iter++; + index++; + index&=HASHMASKDEEP; + } + return 0; + } + /* use shallow hashtable */ + else + { + index=Gkey&HASHMASKSHALLOW; + if(shallow[index].lock==Glock && (hashcolor(shallow[index].info)>>13)==(color>>1)) + { + hashhit++; + /*found the right entry!*/ + *forcefirst=shallow[index].best; + if(hashdepth(shallow[index].info)>=depth) + { + if(hashvaluetype(shallow[index].info) == EXACT) + { + *value=shallow[index].value; + return 1; + } + /* lower bound */ + if(hashvaluetype(shallow[index].info) == LOWER) + { + if(shallow[index].value>=*beta) {*value=shallow[index].value;return 1;} + if(shallow[index].value>*alpha) {*alpha=shallow[index].value;} + return 0; + } + /* upper bound */ + if(hashvaluetype(shallow[index].info) == UPPER) + { + if(shallow[index].value<=*alpha) {*value=shallow[index].value;return 1;} + if(shallow[index].value<*beta) {*beta=shallow[index].value;} + return 0; + } + } + } + } + return 0; + } + */ + #endif Index: llvm/test/Programs/MultiSource/Applications/obsequi/tables.c diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/tables.c:1.1 *** /dev/null Tue May 11 14:34:23 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/tables.c Tue May 11 14:34:13 2004 *************** *** 0 **** --- 1,227 ---- + + + #include "globals.h" + + #ifdef COUNTBITS16 + s32bit countbits16[65536]; + + static void + init_countbits() + { + s32bit i; + + countbits16[0] = 0; + + for(i = 1; i < 65536; i++){ + countbits16[i] = (i & 1) + countbits16[i >> 1]; + } + } + #endif + + #ifdef COUNTBITS8 + s32bit countbits8[256]; + + static void + init_countbits() + { + s32bit i; + + countbits8[0] = 0; + + for(i = 1; i < 256; i++){ + countbits8[i] = (i & 1) + countbits8[i >> 1]; + } + } + #endif + + #ifdef LASTBIT16 + s32bit lastbit16[65536]; + + static void + init_lastbit() + { + s32bit i; + + for(i = 1; i < 65536; i++){ + if(i&NTH_BIT(0)) {lastbit16[i] = 0; continue;} + if(i&NTH_BIT(1)) {lastbit16[i] = 1; continue;} + if(i&NTH_BIT(2)) {lastbit16[i] = 2; continue;} + if(i&NTH_BIT(3)) {lastbit16[i] = 3; continue;} + if(i&NTH_BIT(4)) {lastbit16[i] = 4; continue;} + if(i&NTH_BIT(5)) {lastbit16[i] = 5; continue;} + if(i&NTH_BIT(6)) {lastbit16[i] = 6; continue;} + if(i&NTH_BIT(7)) {lastbit16[i] = 7; continue;} + if(i&NTH_BIT(8)) {lastbit16[i] = 8; continue;} + if(i&NTH_BIT(9)) {lastbit16[i] = 9; continue;} + if(i&NTH_BIT(10)) {lastbit16[i] = 10; continue;} + if(i&NTH_BIT(11)) {lastbit16[i] = 11; continue;} + if(i&NTH_BIT(12)) {lastbit16[i] = 12; continue;} + if(i&NTH_BIT(13)) {lastbit16[i] = 13; continue;} + if(i&NTH_BIT(14)) {lastbit16[i] = 14; continue;} + if(i&NTH_BIT(15)) {lastbit16[i] = 15; continue;} + } + + lastbit16[0] = 100; + } + #endif + + #ifdef LASTBIT8 + s32bit lastbit8[256]; + + static void + init_lastbit() + { + s32bit i; + + for(i = 1; i < 256; i++){ + if(i&NTH_BIT(0)) {lastbit8[i] = 0; continue;} + if(i&NTH_BIT(1)) {lastbit8[i] = 1; continue;} + if(i&NTH_BIT(2)) {lastbit8[i] = 2; continue;} + if(i&NTH_BIT(3)) {lastbit8[i] = 3; continue;} + if(i&NTH_BIT(4)) {lastbit8[i] = 4; continue;} + if(i&NTH_BIT(5)) {lastbit8[i] = 5; continue;} + if(i&NTH_BIT(6)) {lastbit8[i] = 6; continue;} + if(i&NTH_BIT(7)) {lastbit8[i] = 7; continue;} + } + + lastbit8[0] = 100; + } + #endif + + #ifdef COUNTMOVES_TABLE + s32bit move_table16[65536]; + + static void + init_movetable() + { + u32bit i = 0, mask, tmp = 0, count; + + while(i < 65536){ + mask = i; + count = 0; + + while(mask){ + tmp = (mask&-mask); // least sig bit of m + mask &= ~(tmp | (tmp << 1)); // remove bit and next bit. + count++; + } + + #ifndef BOARD_SIZE_LT_16 + if(tmp & 0x00008000) count |= 0xF0000000; + #endif + + move_table16[i] = count; + i++; + } + } + #else + #define init_movetable() ; + #endif + + extern void + init_static_tables() + { + init_countbits(); + init_lastbit(); + init_movetable(); + } + + + KeyInfo g_keyinfo[2][32][32]; + + static void + negate_keyinfo(KeyInfo_s *keyinfo) + { + keyinfo->bit1_index = keyinfo->bit2_index = -1; + keyinfo->hash_code = 0; + } + + + static void + fill_in_hash_code(KeyInfo_s *info, s32bit num_cols) + { + s32bit r, c, hash = 0; + + r = info->bit1_index/num_cols; + c = info->bit1_index%num_cols; + + hash = g_zobrist[r+1][c+1]; + + r = info->bit2_index/num_cols; + c = info->bit2_index%num_cols; + + hash ^= g_zobrist[r+1][c+1]; + + info->hash_code = hash; + } + + + static void + fill_in_key_entry(KeyInfo *keyinfo, s32bit num_rows, s32bit num_cols) + { + if(keyinfo->norm.bit1_index == -1){ + negate_keyinfo( & keyinfo->norm); + negate_keyinfo( & keyinfo->flipV); + negate_keyinfo( & keyinfo->flipH); + negate_keyinfo( & keyinfo->flipVH); + } else { + s32bit r1, c1, r2, c2; + + r1 = keyinfo->norm.bit1_index/num_cols; + c1 = keyinfo->norm.bit1_index%num_cols; + r2 = keyinfo->norm.bit2_index/num_cols; + c2 = keyinfo->norm.bit2_index%num_cols; + + keyinfo->flipV.bit1_index = (r1*num_cols)+(num_cols - c1 - 1); + keyinfo->flipV.bit2_index = (r2*num_cols)+(num_cols - c2 - 1); + + keyinfo->flipH.bit1_index = ((num_rows - r1 - 1) * num_cols) + c1; + keyinfo->flipH.bit2_index = ((num_rows - r2 - 1) * num_cols) + c2; + + keyinfo->flipVH.bit1_index = ( ((num_rows - r1 - 1) * num_cols) + + (num_cols - c1 - 1) ); + keyinfo->flipVH.bit2_index = ( ((num_rows - r2 - 1) * num_cols) + + (num_cols - c2 - 1) ); + + fill_in_hash_code( & keyinfo->norm, num_cols); + fill_in_hash_code( & keyinfo->flipV, num_cols); + fill_in_hash_code( & keyinfo->flipH, num_cols); + fill_in_hash_code( & keyinfo->flipVH, num_cols); + } + } + + + extern void + init_less_static_tables() + { + s32bit n_rows, n_cols, i, j, k; + + n_rows = g_board_size[HORIZONTAL], n_cols = g_board_size[VERTICAL]; + + for(i = 0; i < 32; i++) + for(j = 0; j < 32; j++) + for(k = 0; k < 2; k++) + negate_keyinfo( & g_keyinfo[k][i][j].norm); + + for(i = 0; i < n_rows; i++){ + for(j = 0; j < n_cols; j++){ + //Horizontal Entry + if(j + 1 < n_cols){ + g_keyinfo[HORIZONTAL][i+1][j+1].norm.bit1_index = (i*n_cols)+j; + g_keyinfo[HORIZONTAL][i+1][j+1].norm.bit2_index = (i*n_cols)+(j+1); + } + + //Vertical Entry + if(i + 1 < n_rows){ + g_keyinfo[VERTICAL][j+1][i+1].norm.bit1_index = (i*n_cols)+j; + g_keyinfo[VERTICAL][j+1][i+1].norm.bit2_index = ((i+1)*n_cols)+j; + } + } + } + + for(i = 0; i < 32; i++) + for(j = 0; j < 32; j++) + for(k = 0; k < 2; k++) + fill_in_key_entry(&g_keyinfo[k][i][j], n_rows, n_cols); + } + Index: llvm/test/Programs/MultiSource/Applications/obsequi/toggle_move.c diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/toggle_move.c:1.1 *** /dev/null Tue May 11 14:34:23 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/toggle_move.c Tue May 11 14:34:13 2004 *************** *** 0 **** --- 1,189 ---- + + #include "globals.h" + #include "macros.h" + + //######################################################## + // This function counts the number of safe moves in a row. + // + // Never call this function for rows 0 or 31. + //######################################################## + static inline s32bit + count_safe(s32bit player, s32bit row) + { + u32bit guard = g_board[player][row-1] & g_board[player][row+1]; + + // mask contains a bit for each safe move. + u32bit mask= ( (~(g_board[player][row] | (g_board[player][row] << 1))) + & (guard & (guard << 1)) ); + + return COUNTMOVES(mask); + } + + //######################################################## + // This function counts the number of real moves in a row. + // + // Never call this function for rows 0 or 31. + //######################################################## + static inline s32bit + count_real(s32bit player, s32bit row) + { + // mask contains a bit for each real move. + u32bit mask= ~(g_board[player][row] | (g_board[player][row] << 1)); + + return COUNTMOVES(mask); + } + + + static inline void + _update_safe(s32bit player, s32bit row) + { + s32bit count = count_safe(player, row); + + g_info_totals[player].safe += count - g_info[player][row].safe; + g_info[player][row].safe = count; + } + + static inline void + _update_real(s32bit player, s32bit row) + { + s32bit count = count_real(player, row); + + g_info_totals[player].real += count - g_info[player][row].real; + g_info[player][row].real = count; + } + + + + extern void + update_safe(s32bit player, s32bit row) + { _update_safe(player, row); } + + extern void + update_real(s32bit player, s32bit row) + { _update_real(player, row); } + + extern void + toggle_move(Move move, s32bit player) + { + s32bit row, col, horz_play, vert_play; + + row = (move).array_index, col = (move).mask_index; + horz_play = player & PLAYER_MASK; + vert_play = player ^ PLAYER_MASK; + + g_board[horz_play][row] ^= (3< %d %d\n", movelist[z].array_index, movelist[z].mask_index); + } + */ + if(first.array_index != -1){ + for(i = 0; i < num_moves; i++){ + if(first.array_index == movelist[i].array_index + && first.mask_index == movelist[i].mask_index){ + movelist[i].info = 450000; + max_index = i; + } else { + movelist[i].info = score_move(movelist[i], player); + } + } + } + + else { + for(i = 0; i < num_moves; i++){ + movelist[i].info = score_move(movelist[i], player); + if(movelist[i].info > max){ + max = movelist[i].info; + max_index = i; + } + } + } + + if(max_index == -1) fatal_error(1, "No maximum\n"); + + // put biggest at front + if(num_moves > 1) { + Move tmp_move = movelist[max_index]; + for(i = max_index; i > 0; i--) + movelist[i] = movelist[i - 1]; + movelist[0] = tmp_move; + } + } Index: llvm/test/Programs/MultiSource/Applications/obsequi/traits.c diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/traits.c:1.1 *** /dev/null Tue May 11 14:34:23 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/traits.c Tue May 11 14:34:13 2004 *************** *** 0 **** --- 1,174 ---- + + #include "globals.h" + #include "macros.h" + + static FILE *trait_file = NULL; + + + static s32bit + tr_total_non_safe_moves(s32bit player) + { + u32bit mask1, mask2; + s32bit num_rows = g_board_size[player]; + s32bit count = 0, i; + + for(i = 0; i < num_rows; i++){ + mask1 = g_board[player][i] & g_board[player][i+2]; + mask2 = ~g_board[player][i+1]; + + mask1 = (~((mask1 >> 1) & mask1)) & ((mask2 >> 1) & mask2); + + // printf("%X\n", mask1); + + count += countbits32(mask1); + } + + return count; + } + + static s32bit + tr_non_safe_moves_a_little_touchy(s32bit player) + { + u32bit mask1, mask2; + s32bit num_rows = g_board_size[player]; + s32bit count = 0, i; + + for(i = 0; i < num_rows; i++){ + mask1 = g_board[player][i] | g_board[player][i+2]; + mask2 = g_board[player][i+1]; + + mask1 = ( (mask1 << 1) | mask1 + | (mask2 >> 1) | mask2 | (mask2 << 1) | (mask2 << 2) ); + + count += countbits32(~mask1); + } + + if(count == -1){ + print_board(player); + printf("%d %d\n", player, count); + exit(1); + } + + return count; + } + + static s32bit + tr_non_safe_moves_no_touchy(s32bit player) + { + return 1; + } + + static s32bit + tr_total_empty_squares() + { + u32bit mask; + s32bit num_rows = g_board_size[0]; + s32bit count = 0, i; + + for(i = 0; i < num_rows; i++){ + mask = ~(g_board[0][i+1]); + + count += countbits32(mask); + } + + return count; + } + + static s32bit + tr_border_length_col(player) + { + u32bit mask; + s32bit num_rows = g_board_size[player]; + s32bit count = 0, i; + + for(i = 0; i <= num_rows; i++){ + mask = g_board[player][i] ^ g_board[player][i+1]; + + count += countbits32(mask); + } + + return count; + } + + static s32bit + tr_border_length_row(player) + { + u32bit mask; + s32bit num_rows = g_board_size[player]; + s32bit count = 0, i; + + for(i = 0; i <= num_rows; i++){ + mask = (g_board[player][i+1]>>1) ^ g_board[player][i+1]; + mask &= 0x7FFFFFFF; + + count += countbits32(mask); + } + + return count; + } + + + + + extern void + write_node_info(u64bit num_nodes, s32bit winner) + { + s32bit num; + + if(trait_file == NULL) { + trait_file = fopen("trait_file", "w"); + if(trait_file == NULL) + fprintf(stderr, "Couldn't open \"trait_file\".\n"); + } + + fprintf(trait_file, "%c %15s :", (winner == VERTICAL) ? 'V' : 'H', + u64bit_to_string(num_nodes)); + + //======================================================== + // number of non-safe moves. + //======================================================== + + // total number allowing overlapping of other non-safe moves + // and of safe moves. + num = tr_total_non_safe_moves(winner); + fprintf(trait_file, " %2d", num); + + num = tr_total_non_safe_moves(winner^PLAYER_MASK); + fprintf(trait_file, " %2d :", num); + + + // non safe moves that don't touch a border, except diagonally. + num = tr_non_safe_moves_a_little_touchy(winner); + fprintf(trait_file, " %2d", num); + + num = tr_non_safe_moves_a_little_touchy(winner^PLAYER_MASK); + fprintf(trait_file, " %2d :", num); + + + // non safe moves that don't touch a border, never. + num = tr_non_safe_moves_no_touchy(winner); + fprintf(trait_file, " %2d", num); + + num = tr_non_safe_moves_no_touchy(winner^PLAYER_MASK); + fprintf(trait_file, " %2d :", num); + + + //======================================================== + // Miscellaneous other info. + //======================================================== + + // empty squares. + num = tr_total_empty_squares(); + fprintf(trait_file, " %2d :", num); + + // border length. + num = tr_border_length_col(winner); + fprintf(trait_file, " %2d", num); + + // border length. + num = tr_border_length_row(winner); + fprintf(trait_file, " %2d", num); + + fprintf(trait_file, "\n"); + } + Index: llvm/test/Programs/MultiSource/Applications/obsequi/utils.c diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/utils.c:1.1 *** /dev/null Tue May 11 14:34:23 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/utils.c Tue May 11 14:34:13 2004 *************** *** 0 **** --- 1,163 ---- + + #include "utils.h" + + #include + #include + #include + #include + #include + #include + #include + #include + + + //######################################################## + // This function prints a message to both stderr and + // to the file ".fatal_error". + // + // If ERR_NUM != 0 then exit is called with the value ERR_NUM. + //######################################################## + extern void + _fatal_error_aux(const char *file, const s32bit line, const s32bit err_num, + const char *format, ... ) + { + va_list ap; + static FILE* err_file = NULL; + char *msg_type = (err_num == 0) ? "WARNING: " : "ERROR: "; + + // only need to open this if not already open. + if(err_file == NULL) err_file = fopen(".fatal_error", "w"); + if(err_file == NULL) fprintf(stderr, "Couldn't open \".fatal_error\".\n"); + + if(err_num == 0) { + // Check size of file, we don't want to end up filling up the whole disk. + s32bit size = ftell(err_file); + if(size == -1) + fatal_error(1, "size == -1.\n"); + + else if(size > (2<<24) + 2000 ){ + return; + } + + else if(size > (2<<24)){ + fprintf(stderr, "Log file getting too large.\n"); + fprintf(err_file, "Log file getting too large.\n"); + } + } + + // start writing the real message. + fprintf(stderr, msg_type); + fprintf(err_file, msg_type); + + va_start (ap, format); + vfprintf (stderr, format, ap); + vfprintf (err_file, format, ap); + va_end (ap); + + fprintf(stderr, "> File: %s, Line: %d.\n", file, line); + fprintf(err_file, "> File: %s, Line: %d.\n", file, line); + + fflush(stderr); + fflush(err_file); + + if (err_num != 0) exit(err_num); + } + + + //######################################################## + // These are dynamic sprintf function, they malloc space as needed. + //######################################################## + + //======================================================== + // This function stores the string created from FORMAT and the + // following args to the string STR, starting at position OFFSET. + //======================================================== + extern s32bit + Asprintf(char **str, s32bit *len, s32bit offset, const char *format, ... ) + { + va_list ap; + s32bit nchars; + + va_start (ap, format); + + // if no space allocated yet, allocate some. + if(*len == 0){ *len = 128; *str = malloc(*len); } + + while (1) { + // attempt printing in the allocated space + nchars = vsnprintf (*str + offset, *len - offset, format, ap); + + if (nchars < *len - offset) break; + + // if not enough space allocate some more. + *len += 128; + *str = realloc(*str, *len); + } + + va_end (ap); + return nchars; + } + + //======================================================== + // This function stores the string created from FORMAT and the + // following args to the end of the string STR. + //======================================================== + extern s32bit + asprintf_my(char **str, s32bit offset, const char *format, ... ) + { + va_list ap; + s32bit nchars, len = ALLOCED(*str,char); + + va_start (ap, format); + + // if no space allocated yet, allocate some. + if(len == 0){ len = 128; *str = malloc(len); } + + while (1) { + // attempt printing in the allocated space + nchars = vsnprintf (*str + offset, len - offset, format, ap); + + if (nchars < len - offset) break; + + // if not enough space allocate some more. + len += 128; + *str = realloc(*str, len); + } + + va_end (ap); + return nchars; + } + + + //######################################################## + // Return a string with the printed value of a 64 bit number. + //######################################################## + extern const char* + u64bit_to_string(u64bit val) + { + static char big_num[80]; // plenty large + s32bit vals[10]; // plenty large + s32bit i = 0, offset; + + do { + vals[i] = val % 1000; + val = val / 1000; + i++; + } while(val != 0); + + offset = sprintf(big_num, "%d", vals[--i]); + + while(i != 0) + offset += sprintf(big_num + offset, ",%03d", vals[--i]); + + return big_num; + } + + + //######################################################## + // I'm not sure why I have this function. + // I suppose it may come in useful for performance analysis. + //######################################################## + extern void + null_command() {} + Index: llvm/test/Programs/MultiSource/Applications/obsequi/utils.h diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/utils.h:1.1 *** /dev/null Tue May 11 14:34:23 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/utils.h Tue May 11 14:34:13 2004 *************** *** 0 **** --- 1,143 ---- + + + #ifndef OBSEQUI_UTILS_H + #define OBSEQUI_UTILS_H + + #define _GNU_SOURCE //Need this so that __USE_GNU is defined + #include + + #include + #include + #include + #include + + + //################################################################# + // Define a couple of types which I like to use. + //################################################################# + + typedef u_int8_t u8bit; + typedef u_int16_t u16bit; + typedef u_int32_t u32bit; + typedef u_int64_t u64bit; + + typedef int16_t s16bit; + typedef int32_t s32bit; + + + //################################################################# + // Define a number of useful constants and macros. + //################################################################# + + //================================================================= + // I think that DEFINED should always be defined. + // Also make sure NOT_DEFINED is not. + //================================================================= + #define DEFINED + #undef NOT_DEFINED + + //================================================================= + // Determine the max value of two numbers. + //================================================================= + #define MAX_TWO(a,b) (((a) > (b)) ? (a) : (b)) + + //================================================================= + // Determine the min value of two numbers. + //================================================================= + #define MIN_TWO(a,b) (((a) > (b)) ? (b) : (a)) + + //================================================================= + // Constants and Macros for dealing with bit masks. + //================================================================= + #define ALL_BITS 0xFFFFFFFF + #define NTH_BIT(i) ( 1 << (i) ) + #define FIRST_N_BITS(i) (~(ALL_BITS << (i))) + #define LAST_N_BITS(i) (~(ALL_BITS >> (i))) + + //================================================================= + // Determine how many elements have been alloced for ptr. + // - this probably only works if using glibc. + //================================================================= + #define ALLOCED(ptr,type) (malloc_usable_size(ptr)/sizeof(type)) + + + //######################################################## + // The following functions print a message to both stderr and + // to the file ".fatal_error". These messages can be helpful + // for debugging since they contain both the file name and line number + // of where this function was called. (They all return void.) + //######################################################## + + //======================================================== + // Besides printing a message this function also causes the + // program to exit with the value 'err_num'. + //======================================================== + #define fatal_error(err_num, format, rest...) \ + (_fatal_error((err_num) ? (err_num) : 256, format, ## rest )) + + //======================================================== + // This function justs prints the message. + //======================================================== + #define warning(format, rest...) \ + (_fatal_error(0, format, ## rest )) + + //======================================================== + // This function prints the message "Check Point." + // Exclusively used for debugging. + //======================================================== + #define check_point() \ + (_fatal_error(0, "Check Point.\n")) + + + #define _fatal_error(err_num, format, rest...) \ + (_fatal_error_aux(__FILE__, __LINE__, (err_num), format, ## rest )) + + + //######################################################## + // These are dynamic sprintf function, they malloc space as needed. + //######################################################## + + //======================================================== + // stores the string created from FORMAT, and ..., in *str. + // + // allocates space as needed. + // returns the number of characters written to *str. + //======================================================== + extern s32bit + Asprintf(char **str, s32bit *len, s32bit offset, const char *format, ... ) + __attribute__ ((format (printf, 4, 5))); + + //======================================================== + // returns the number of characters written to *(str+offset) + //======================================================== + extern s32bit + asprintf_my(char **str, s32bit offset, const char *format, ... ) + __attribute__ ((format (printf, 3, 4))); + + + + //######################################################## + // This function does absolutely nothing. + //######################################################## + extern void + null_command(); + + + //######################################################## + // Return a string with the printed value of a 64 bit number. + // Note: It returns a static buffer so don't free it, and + // always copy the value before you call it again. + //######################################################## + extern const char* + u64bit_to_string(u64bit val); + + + //######################################################## + // Internals. + //######################################################## + extern void + _fatal_error_aux(const char *file, const s32bit line, + const s32bit err_num, const char *format, ... ) + __attribute__ ((format (printf, 4, 5))); + + #endif From criswell at cs.uiuc.edu Tue May 11 14:36:06 2004 From: criswell at cs.uiuc.edu (John Criswell) Date: Tue May 11 14:36:06 2004 Subject: [llvm-commits] CVS: llvm/test/Programs/MultiSource/Applications/obsequi/LICENSE.TXT Message-ID: <200405111935.OAA27342@choi.cs.uiuc.edu> Changes in directory llvm/test/Programs/MultiSource/Applications/obsequi: LICENSE.TXT updated: 1.1 -> 1.2 --- Log message: Added notes about what has been removed. --- Diffs of the changes: (+2 -0) Index: llvm/test/Programs/MultiSource/Applications/obsequi/LICENSE.TXT diff -u llvm/test/Programs/MultiSource/Applications/obsequi/LICENSE.TXT:1.1 llvm/test/Programs/MultiSource/Applications/obsequi/LICENSE.TXT:1.2 --- llvm/test/Programs/MultiSource/Applications/obsequi/LICENSE.TXT:1.1 Tue May 11 14:34:12 2004 +++ llvm/test/Programs/MultiSource/Applications/obsequi/LICENSE.TXT Tue May 11 14:34:52 2004 @@ -3,3 +3,5 @@ Obsequi is licensed under the GNU General Public License. Please see the file COPYRIGHT and GPL for more information. +The original Makefiles and other configuration machinery have been removed. + From criswell at cs.uiuc.edu Tue May 11 14:47:04 2004 From: criswell at cs.uiuc.edu (John Criswell) Date: Tue May 11 14:47:04 2004 Subject: [llvm-commits] CVS: llvm/test/Programs/MultiSource/Applications/obsequi/init.c utils.h Message-ID: <200405111945.OAA29856@choi.cs.uiuc.edu> Changes in directory llvm/test/Programs/MultiSource/Applications/obsequi: init.c updated: 1.1 -> 1.2 utils.h updated: 1.1 -> 1.2 --- Log message: init.c : Changed malloc() to calloc() so that allocated memory is zeroed. utils.h: Added #include guard to turn off annoying warnings. --- Diffs of the changes: (+4 -1) Index: llvm/test/Programs/MultiSource/Applications/obsequi/init.c diff -u llvm/test/Programs/MultiSource/Applications/obsequi/init.c:1.1 llvm/test/Programs/MultiSource/Applications/obsequi/init.c:1.2 --- llvm/test/Programs/MultiSource/Applications/obsequi/init.c:1.1 Tue May 11 14:34:12 2004 +++ llvm/test/Programs/MultiSource/Applications/obsequi/init.c Tue May 11 14:45:39 2004 @@ -57,7 +57,7 @@ if(g_trans_table == NULL){ // first time initialization stuff. - g_trans_table = malloc(HASHSIZE*sizeof(Hash_Entry)); + g_trans_table = calloc(HASHSIZE,sizeof(Hash_Entry)); // initialize zobrist values srandom(1); Index: llvm/test/Programs/MultiSource/Applications/obsequi/utils.h diff -u llvm/test/Programs/MultiSource/Applications/obsequi/utils.h:1.1 llvm/test/Programs/MultiSource/Applications/obsequi/utils.h:1.2 --- llvm/test/Programs/MultiSource/Applications/obsequi/utils.h:1.1 Tue May 11 14:34:13 2004 +++ llvm/test/Programs/MultiSource/Applications/obsequi/utils.h Tue May 11 14:45:39 2004 @@ -3,7 +3,10 @@ #ifndef OBSEQUI_UTILS_H #define OBSEQUI_UTILS_H +#ifndef _GNU_SOURCE #define _GNU_SOURCE //Need this so that __USE_GNU is defined +#endif + #include #include From criswell at cs.uiuc.edu Tue May 11 14:50:03 2004 From: criswell at cs.uiuc.edu (John Criswell) Date: Tue May 11 14:50:03 2004 Subject: [llvm-commits] CVS: llvm/test/Programs/MultiSource/Applications/obsequi/input Message-ID: <200405111948.OAA30853@choi.cs.uiuc.edu> Changes in directory llvm/test/Programs/MultiSource/Applications/obsequi: input added (r1.1) --- Log message: Input file, based off of the recommendation in the original README file. --- Diffs of the changes: (+2 -0) Index: llvm/test/Programs/MultiSource/Applications/obsequi/input diff -c /dev/null llvm/test/Programs/MultiSource/Applications/obsequi/input:1.1 *** /dev/null Tue May 11 14:48:49 2004 --- llvm/test/Programs/MultiSource/Applications/obsequi/input Tue May 11 14:48:39 2004 *************** *** 0 **** --- 1,2 ---- + solve rows 8 cols 8 V + From criswell at cs.uiuc.edu Tue May 11 15:05:04 2004 From: criswell at cs.uiuc.edu (John Criswell) Date: Tue May 11 15:05:04 2004 Subject: [llvm-commits] CVS: llvm/test/Programs/MultiSource/Applications/Makefile Message-ID: <200405112004.PAA31846@choi.cs.uiuc.edu> Changes in directory llvm/test/Programs/MultiSource/Applications: Makefile updated: 1.8 -> 1.9 --- Log message: Enabling obsequi for automatic testing. --- Diffs of the changes: (+1 -1) Index: llvm/test/Programs/MultiSource/Applications/Makefile diff -u llvm/test/Programs/MultiSource/Applications/Makefile:1.8 llvm/test/Programs/MultiSource/Applications/Makefile:1.9 --- llvm/test/Programs/MultiSource/Applications/Makefile:1.8 Tue Apr 6 17:00:20 2004 +++ llvm/test/Programs/MultiSource/Applications/Makefile Tue May 11 15:04:06 2004 @@ -6,7 +6,7 @@ PARALLEL_DIRS = Burg aha sgefa siod lambda-0.1.3 d ifeq ($(OS),Linux) -PARALLEL_DIRS += kimwitu++ treecc hbd +PARALLEL_DIRS += kimwitu++ treecc hbd obsequi endif include $(LEVEL)/test/Programs/Makefile.programs From lattner at cs.uiuc.edu Tue May 11 15:11:05 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 11 15:11:05 2004 Subject: [llvm-commits] CVS: llvm/test/Programs/MultiSource/Applications/obsequi/obsequi.c Message-ID: <200405112011.PAA09250@zion.cs.uiuc.edu> Changes in directory llvm/test/Programs/MultiSource/Applications/obsequi: obsequi.c updated: 1.1 -> 1.2 --- Log message: Don't use timer interrupts to change the behavior of the program. We like deterministic programs for the testsuite --- Diffs of the changes: (+1 -1) Index: llvm/test/Programs/MultiSource/Applications/obsequi/obsequi.c diff -u llvm/test/Programs/MultiSource/Applications/obsequi/obsequi.c:1.1 llvm/test/Programs/MultiSource/Applications/obsequi/obsequi.c:1.2 --- llvm/test/Programs/MultiSource/Applications/obsequi/obsequi.c:1.1 Tue May 11 14:34:12 2004 +++ llvm/test/Programs/MultiSource/Applications/obsequi/obsequi.c Tue May 11 15:11:16 2004 @@ -87,7 +87,7 @@ if(stop_minutes) set_stop_alrm(stop_minutes); } else { get_solve_command(); - if(!main_batch) sig_alrm_setup(); + //if(!main_batch) sig_alrm_setup(); } sig_int_setup(); From lattner at cs.uiuc.edu Tue May 11 15:41:04 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 11 15:41:04 2004 Subject: [llvm-commits] CVS: llvm/tools/bugpoint/ListReducer.h Message-ID: <200405112041.PAA10371@zion.cs.uiuc.edu> Changes in directory llvm/tools/bugpoint: ListReducer.h updated: 1.9 -> 1.10 --- Log message: A class that is meant to be a base class should have a virtual destructor --- Diffs of the changes: (+2 -0) Index: llvm/tools/bugpoint/ListReducer.h diff -u llvm/tools/bugpoint/ListReducer.h:1.9 llvm/tools/bugpoint/ListReducer.h:1.10 --- llvm/tools/bugpoint/ListReducer.h:1.9 Sat Nov 29 14:04:13 2003 +++ llvm/tools/bugpoint/ListReducer.h Tue May 11 15:41:07 2004 @@ -28,6 +28,8 @@ KeepPrefix, // The prefix alone satisfies the predicate }; + virtual ~ListReducer() {} + // doTest - This virtual function should be overriden by subclasses to // implement the test desired. The testcase is only required to test to see // if the Kept list still satisfies the property, but if it is going to check From lattner at cs.uiuc.edu Tue May 11 16:54:02 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 11 16:54:02 2004 Subject: [llvm-commits] CVS: llvm/tools/bugpoint/BugDriver.h ExtractFunction.cpp Miscompilation.cpp Message-ID: <200405112154.QAA17720@zion.cs.uiuc.edu> Changes in directory llvm/tools/bugpoint: BugDriver.h updated: 1.37 -> 1.38 ExtractFunction.cpp updated: 1.33 -> 1.34 Miscompilation.cpp updated: 1.44 -> 1.45 --- Log message: Implement basic block extraction for the miscompilation debugger. This still needs two things: the FIXME in ExtractBlocks needs to be implemented, and the basic block extractor itself needs to have enough bugs fixed for this to be more or less useful. Until the time that this is generally useful, it is hidden behind the new bugpoint -enable-block-extraction option. I hope to get the FIXME done tonight. Also of note, this patch adds a -extract-bbs option to bugpoint which can be used to debug the block extractor. (hint hint Misha :) --- Diffs of the changes: (+188 -0) Index: llvm/tools/bugpoint/BugDriver.h diff -u llvm/tools/bugpoint/BugDriver.h:1.37 llvm/tools/bugpoint/BugDriver.h:1.38 --- llvm/tools/bugpoint/BugDriver.h:1.37 Mon Apr 5 17:58:16 2004 +++ llvm/tools/bugpoint/BugDriver.h Tue May 11 16:54:12 2004 @@ -24,6 +24,7 @@ class PassInfo; class Module; class Function; +class BasicBlock; class AbstractInterpreter; class Instruction; @@ -199,6 +200,14 @@ /// function. This returns null if there are no extractable loops in the /// program or if the loop extractor crashes. Module *ExtractLoop(Module *M); + + /// ExtractMappedBlocksFromModule - Extract all but the specified basic blocks + /// into their own functions. The only detail is that M is actually a module + /// cloned from the one the BBs are in, so some mapping needs to be performed. + /// If this operation fails for some reason (ie the implementation is buggy), + /// this function should return null, otherwise it returns a new Module. + Module *ExtractMappedBlocksFromModule(const std::vector &BBs, + Module *M); /// runPassesOn - Carefully run the specified set of pass on the specified /// module, returning the transformed module on success, or a null pointer on Index: llvm/tools/bugpoint/ExtractFunction.cpp diff -u llvm/tools/bugpoint/ExtractFunction.cpp:1.33 llvm/tools/bugpoint/ExtractFunction.cpp:1.34 --- llvm/tools/bugpoint/ExtractFunction.cpp:1.33 Fri Apr 2 10:28:32 2004 +++ llvm/tools/bugpoint/ExtractFunction.cpp Tue May 11 16:54:13 2004 @@ -22,6 +22,7 @@ #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/Transforms/Utils/FunctionUtils.h" #include "llvm/Target/TargetData.h" #include "Support/CommandLine.h" #include "Support/Debug.h" @@ -198,4 +199,70 @@ if (!TestFunctions.count(std::make_pair(I->getName(), I->getType()))) DeleteFunctionBody(I); return New; +} + +//===----------------------------------------------------------------------===// +// Basic Block Extraction Code +//===----------------------------------------------------------------------===// + +namespace { + std::vector BlocksToNotExtract; + + /// BlockExtractorPass - This pass is used by bugpoint to extract all blocks + /// from the module into their own functions except for those specified by the + /// BlocksToNotExtract list. + class BlockExtractorPass : public Pass { + bool run(Module &M); + }; + RegisterOpt + XX("extract-bbs", "Extract Basic Blocks From Module (for bugpoint use)"); +} + +bool BlockExtractorPass::run(Module &M) { + std::set TranslatedBlocksToNotExtract; + for (unsigned i = 0, e = BlocksToNotExtract.size(); i != e; ++i) { + BasicBlock *BB = BlocksToNotExtract[i]; + Function *F = BB->getParent(); + + // Map the corresponding function in this module. + Function *MF = M.getFunction(F->getName(), F->getFunctionType()); + + // Figure out which index the basic block is in its function. + Function::iterator BBI = MF->begin(); + std::advance(BBI, std::distance(F->begin(), Function::iterator(BB))); + TranslatedBlocksToNotExtract.insert(BBI); + } + + // Now that we know which blocks to not extract, figure out which ones we WANT + // to extract. + std::vector BlocksToExtract; + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) + if (!TranslatedBlocksToNotExtract.count(BB)) + BlocksToExtract.push_back(BB); + + for (unsigned i = 0, e = BlocksToExtract.size(); i != e; ++i) + ExtractBasicBlock(BlocksToExtract[i]); + + return !BlocksToExtract.empty(); +} + +/// ExtractMappedBlocksFromModule - Extract all but the specified basic blocks +/// into their own functions. The only detail is that M is actually a module +/// cloned from the one the BBs are in, so some mapping needs to be performed. +/// If this operation fails for some reason (ie the implementation is buggy), +/// this function should return null, otherwise it returns a new Module. +Module *BugDriver::ExtractMappedBlocksFromModule(const + std::vector &BBs, + Module *M) { + // Set the global list so that pass will be able to access it. + BlocksToNotExtract = BBs; + + std::vector PI; + PI.push_back(getPI(new BlockExtractorPass())); + Module *Ret = runPassesOn(M, PI); + BlocksToNotExtract.clear(); + if (Ret == 0) + std::cout << "*** Basic Block extraction failed, please report a bug!\n"; + return Ret; } Index: llvm/tools/bugpoint/Miscompilation.cpp diff -u llvm/tools/bugpoint/Miscompilation.cpp:1.44 llvm/tools/bugpoint/Miscompilation.cpp:1.45 --- llvm/tools/bugpoint/Miscompilation.cpp:1.44 Fri Apr 23 15:36:51 2004 +++ llvm/tools/bugpoint/Miscompilation.cpp Tue May 11 16:54:13 2004 @@ -29,6 +29,10 @@ namespace llvm { extern cl::list InputArgv; + cl::opt + EnableBlockExtraction("enable-block-extraction", + cl::desc("Enable basic block extraction for " + "miscompilation debugging (experimental)")); } namespace { @@ -320,6 +324,95 @@ } } +namespace { + class ReduceMiscompiledBlocks : public ListReducer { + BugDriver &BD; + bool (*TestFn)(BugDriver &, Module *, Module *); + std::vector FunctionsBeingTested; + public: + ReduceMiscompiledBlocks(BugDriver &bd, + bool (*F)(BugDriver &, Module *, Module *), + const std::vector &Fns) + : BD(bd), TestFn(F), FunctionsBeingTested(Fns) {} + + virtual TestResult doTest(std::vector &Prefix, + std::vector &Suffix) { + if (!Suffix.empty() && TestFuncs(Suffix)) + return KeepSuffix; + if (TestFuncs(Prefix)) + return KeepPrefix; + return NoFailure; + } + + bool TestFuncs(const std::vector &Prefix); + }; +} + +/// TestFuncs - Extract all blocks for the miscompiled functions except for the +/// specified blocks. If the problem still exists, return true. +/// +bool ReduceMiscompiledBlocks::TestFuncs(const std::vector &BBs) { + // Test to see if the function is misoptimized if we ONLY run it on the + // functions listed in Funcs. + std::cout << "Checking to see if the program is misoptimized when all but " + << "these " << BBs.size() << " blocks are extracted: "; + for (unsigned i = 0, e = BBs.size() < 10 ? BBs.size() : 10; i != e; ++i) + std::cout << BBs[i]->getName() << " "; + if (BBs.size() > 10) std::cout << "..."; + std::cout << "\n"; + + // Split the module into the two halves of the program we want. + Module *ToNotOptimize = CloneModule(BD.getProgram()); + Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, + FunctionsBeingTested); + + // Try the extraction. If it doesn't work, then the block extractor crashed + // or something, in which case bugpoint can't chase down this possibility. + if (Module *New = BD.ExtractMappedBlocksFromModule(BBs, ToOptimize)) { + delete ToOptimize; + // Run the predicate, not that the predicate will delete both input modules. + return TestFn(BD, New, ToNotOptimize); + } + delete ToOptimize; + delete ToNotOptimize; + return false; +} + + +/// ExtractBlocks - Given a reduced list of functions that still expose the bug, +/// extract as many basic blocks from the region as possible without obscuring +/// the bug. +/// +static bool ExtractBlocks(BugDriver &BD, + bool (*TestFn)(BugDriver &, Module *, Module *), + std::vector &MiscompiledFunctions) { + // Not enabled?? + if (!EnableBlockExtraction) return false; + + std::vector Blocks; + for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i) + for (Function::iterator I = MiscompiledFunctions[i]->begin(), + E = MiscompiledFunctions[i]->end(); I != E; ++I) + Blocks.push_back(I); + + // Use the list reducer to identify blocks that can be extracted without + // obscuring the bug. The Blocks list will end up containing blocks that must + // be retained from the original program. + unsigned OldSize = Blocks.size(); + ReduceMiscompiledBlocks(BD, TestFn, MiscompiledFunctions).reduceList(Blocks); + if (Blocks.size() == OldSize) + return false; + + + + // FIXME: This should actually update the module in the bugdriver! + + + + return false; +} + + /// DebugAMiscompilation - This is a generic driver to narrow down /// miscompilations, either in an optimization or a code generator. /// @@ -352,6 +445,25 @@ // can eliminate some of the created functions from being candidates. // Loop extraction can introduce functions with the same name (foo_code). + // Make sure to disambiguate the symbols so that when the program is split + // apart that we can link it back together again. + DisambiguateGlobalSymbols(BD.getProgram()); + + // Do the reduction... + ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions); + + std::cout << "\n*** The following function" + << (MiscompiledFunctions.size() == 1 ? " is" : "s are") + << " being miscompiled: "; + PrintFunctionList(MiscompiledFunctions); + std::cout << "\n"; + } + + if (ExtractBlocks(BD, TestFn, MiscompiledFunctions)) { + // Okay, we extracted some blocks and the problem still appears. See if we + // can eliminate some of the created functions from being candidates. + + // Block extraction can introduce functions with the same name (foo_code). // Make sure to disambiguate the symbols so that when the program is split // apart that we can link it back together again. DisambiguateGlobalSymbols(BD.getProgram()); From brukman at cs.uiuc.edu Tue May 11 19:57:02 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 11 19:57:02 2004 Subject: [llvm-commits] CVS: llvm/docs/HowToSubmitABug.html Message-ID: <200405120057.TAA24805@zion.cs.uiuc.edu> Changes in directory llvm/docs: HowToSubmitABug.html updated: 1.17 -> 1.18 --- Log message: Add link to Valgrind. --- Diffs of the changes: (+4 -3) Index: llvm/docs/HowToSubmitABug.html diff -u llvm/docs/HowToSubmitABug.html:1.17 llvm/docs/HowToSubmitABug.html:1.18 --- llvm/docs/HowToSubmitABug.html:1.17 Tue May 11 14:34:27 2004 +++ llvm/docs/HowToSubmitABug.html Tue May 11 19:57:24 2004 @@ -231,8 +231,9 @@ finishes its run.

    If it looks like the LLVM compiler is miscompiling a program, the very first -thing to check is to make sure it is not using undefined behavior. In -particular, check to see if the program valgrinds clean, passes purify, or some +thing to check is to make sure it is not using undefined behavior. In +particular, check to see if the program valgrinds clean, passes purify, or some other memory checker tool. Many of the "LLVM bugs" that we have chased down ended up being bugs in the program being compiled, not LLVM.

    @@ -340,7 +341,7 @@ Chris Lattner
    The LLVM Compiler Infrastructure
    - Last modified: $Date: 2004/05/11 19:34:27 $ + Last modified: $Date: 2004/05/12 00:57:24 $ From brukman at cs.uiuc.edu Tue May 11 21:30:03 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 11 21:30:03 2004 Subject: [llvm-commits] CVS: llvm-www/releases/index.html Message-ID: <200405120230.VAA07318@zion.cs.uiuc.edu> Changes in directory llvm-www/releases: index.html updated: 1.15 -> 1.16 --- Log message: Eliminate repeated/obvious wording: naturally all listed releases are available. --- Diffs of the changes: (+8 -9) Index: llvm-www/releases/index.html diff -u llvm-www/releases/index.html:1.15 llvm-www/releases/index.html:1.16 --- llvm-www/releases/index.html:1.15 Tue Mar 23 20:03:22 2004 +++ llvm-www/releases/index.html Tue May 11 21:29:52 2004 @@ -39,17 +39,16 @@
    -

    The 1.2 release (19 Mar 2004) is available for -download. You can read the Release Notes -here.

    +
    From brukman at cs.uiuc.edu Tue May 11 21:34:01 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 11 21:34:01 2004 Subject: [llvm-commits] CVS: llvm-www/releases/index.html Message-ID: <200405120234.VAA21284@zion.cs.uiuc.edu> Changes in directory llvm-www/releases: index.html updated: 1.16 -> 1.17 --- Log message: * Of course our documentation is complete, no need to re-iterate it. * The link names are semantic information as to what they point to, let's not make numerous links that all say "complete documentation": mention the release number in the link * Since we're going to be reverse-chronological in nature, list the link to "current bleeding-edge" docs at the top of the list --- Diffs of the changes: (+5 -6) Index: llvm-www/releases/index.html diff -u llvm-www/releases/index.html:1.16 llvm-www/releases/index.html:1.17 --- llvm-www/releases/index.html:1.16 Tue May 11 21:29:52 2004 +++ llvm-www/releases/index.html Tue May 11 21:33:51 2004 @@ -58,14 +58,13 @@

    LLVM provides extensive documentation in HTML form. The documentation is included in the source download (see README.TXT for details). You can also see -the documentation here:

    +the documentation online:

    From lattner at cs.uiuc.edu Tue May 11 21:43:01 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 11 21:43:01 2004 Subject: [llvm-commits] CVS: llvm/tools/bugpoint/Miscompilation.cpp Message-ID: <200405120243.VAA27116@zion.cs.uiuc.edu> Changes in directory llvm/tools/bugpoint: Miscompilation.cpp updated: 1.45 -> 1.46 --- Log message: Implement the final missing bits for block extractor support. Now bugpoint can extract basic blocks up to the limit of the block extractor implementation. --- Diffs of the changes: (+35 -2) Index: llvm/tools/bugpoint/Miscompilation.cpp diff -u llvm/tools/bugpoint/Miscompilation.cpp:1.45 llvm/tools/bugpoint/Miscompilation.cpp:1.46 --- llvm/tools/bugpoint/Miscompilation.cpp:1.45 Tue May 11 16:54:13 2004 +++ llvm/tools/bugpoint/Miscompilation.cpp Tue May 11 21:43:24 2004 @@ -403,13 +403,46 @@ if (Blocks.size() == OldSize) return false; + Module *ProgClone = CloneModule(BD.getProgram()); + Module *ToExtract = SplitFunctionsOutOfModule(ProgClone, + MiscompiledFunctions); + Module *Extracted = BD.ExtractMappedBlocksFromModule(Blocks, ToExtract); + if (Extracted == 0) { + // Wierd, extraction should have worked. + std::cerr << "Nondeterministic problem extracting blocks??\n"; + delete ProgClone; + delete ToExtract; + return false; + } + // Otherwise, block extraction succeeded. Link the two program fragments back + // together. + delete ToExtract; - // FIXME: This should actually update the module in the bugdriver! + std::string ErrorMsg; + if (LinkModules(ProgClone, Extracted, &ErrorMsg)) { + std::cerr << BD.getToolName() << ": Error linking modules together:" + << ErrorMsg << "\n"; + exit(1); + } + // Set the new program and delete the old one. + BD.setNewProgram(ProgClone); + // Update the list of miscompiled functions. + MiscompiledFunctions.clear(); - return false; + for (Module::iterator I = Extracted->begin(), E = Extracted->end(); I != E; + ++I) + if (!I->isExternal()) { + Function *NF = ProgClone->getFunction(I->getName(), I->getFunctionType()); + assert(NF && "Mapped function not found!"); + MiscompiledFunctions.push_back(NF); + } + + delete Extracted; + + return true; } From brukman at cs.uiuc.edu Tue May 11 21:48:01 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 11 21:48:01 2004 Subject: [llvm-commits] CVS: llvm/README.txt Message-ID: <200405120248.VAA27268@zion.cs.uiuc.edu> Changes in directory llvm: README.txt updated: 1.5 -> 1.6 --- Log message: This file has been superseded by docs/index.html . --- Diffs of the changes: (+1 -128) Index: llvm/README.txt diff -u llvm/README.txt:1.5 llvm/README.txt:1.6 --- llvm/README.txt:1.5 Mon Oct 27 12:02:06 2003 +++ llvm/README.txt Tue May 11 21:48:30 2004 @@ -1,128 +1 @@ - The LLVM Compiler Infrastructure - http://llvm.cs.uiuc.edu - -Welcome to LLVM! ----------------- -This file is intended to do four things: -(1) help you get started using LLVM; -(2) tell you how to get questions about LLVM answered; -(3) tell you where to find documentation for different kinds of questions; and -(4) tell you about three LLVM-related mailing lists. - - -Getting Started with LLVM -------------------------- - -(1) For license information: - llvm/LICENSE.txt - -(2) Installing and compiling LLVM: - llvm/docs/GettingStarted.html - -(3) Learn about features and limitations of this release: - llvm/docs/ReleaseNotes.html - -(4) Learn how to write a pass within the LLVM system: - llvm/docs/WritingAnLLVMPass.html - -(5) Learn how to start a new development project using LLVM, where your - new source code can live anywhere (outside or inside the LLVM tree), - while using LLVM header files and libraries: - llvm/docs/Projects.html - - -Getting Help with LLVM ----------------------- - -(1) If you have questions or development problems not answered in the - documentation, send e-mail to llvmdev at cs.uiuc.edu. This mailing list is - monitored by all the people in the LLVM group at Illinois, and you should - expect prompt first responses. - -(2) To report a bug, submit a bug report as described in the document: - http://llvm.cs.uiuc.edu/docs/HowToSubmitABug.html - -(3) We now use Bugzilla to track bugs, so you can check the status of - previous bugs at: - http://llvm.cs.uiuc.edu/bugs/query.cgi - -LLVM Documentation ------------------- - -All the documents mentioned below except the design overview tech report -are included as part of the LLVM release (in llvm/docs/*): - -LLVM Design Overview: - LLVM : A Compilation Framework for Lifelong Program Analysis - and Transformation: - http://llvm.cs.uiuc.edu/pubs/2003-09-30-LifelongOptimizationTR.html - -LLVM User Guides: - - Download and Installation Instructions: - llvm/docs/GettingStarted.html - - LLVM Command Guide: - llvm/docs/CommandGuide/index.html - - LLVM Assembly Language: - llvm/docs/LangRef.html - - LLVM Test Suite Guide: - llvm/docs/TestingGuide.html - -LLVM Programming Documentation: - - LLVM Programmers Manual: - llvm/docs/ProgrammersManual.html - - Writing an LLVM Pass: - llvm/docs/WritingAnLLVMPass.html - - Alias Analysis in LLVM: - llvm/docs/AliasAnalysis.html - - Command Line Library: - llvm/docs/CommandLine.html - - Coding Standards: - llvm/docs/CodingStandards.html - -Other LLVM Resources: - - Submitting a Bug: - http://llvm.cs.uiuc.edu/docs/HowToSubmitABug.html - - Open Projects: - llvm/docs/OpenProjects.html - - Creating a new LLVM Project: - llvm/docs/Projects.html - -Mailing Lists --------------- -There are three mailing lists for providing LLVM users with information: - -(1) LLVM Announcements List: - http://mail.cs.uiuc.edu/mailman/listinfo/llvm-announce - - This is a low volume list that provides important announcements regarding - LLVM. It is primarily intended to announce new releases, major updates to - the software, etc. This list is highly recommended for anyone that uses - LLVM. - -(2) LLVM Developers List: - http://mail.cs.uiuc.edu/mailman/listinfo/llvmdev - - This list is for people who want to be included in technical discussions - of LLVM. People post to this list when they have questions about writing - code for or using the LLVM tools. It is relatively low volume. - -(3) LLVM Commits List - http://mail.cs.uiuc.edu/mailman/listinfo/llvm-commits - - This list contains all commit messages that are made when LLVM developers - commit code changes to the CVS archive. It is useful for those who want to - stay on the bleeding edge of LLVM development. This list is very high - volume. - +This file is a placeholder; see docs/index.html for documentation. From brukman at cs.uiuc.edu Tue May 11 21:51:01 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue May 11 21:51:01 2004 Subject: [llvm-commits] CVS: llvm-www/releases/index.html Message-ID: <200405120251.VAA01201@zion.cs.uiuc.edu> Changes in directory llvm-www/releases: index.html updated: 1.17 -> 1.18 --- Log message: * Instead of saying 'under development for X years', just say since 2000, so we don't have to update it every year * Simplify wording of availability of documentation in the tarball and online --- Diffs of the changes: (+9 -10) Index: llvm-www/releases/index.html diff -u llvm-www/releases/index.html:1.17 llvm-www/releases/index.html:1.18 --- llvm-www/releases/index.html:1.17 Tue May 11 21:33:51 2004 +++ llvm-www/releases/index.html Tue May 11 21:51:02 2004 @@ -13,14 +13,14 @@
    -

    We are pleased to announce the public release of the LLVM Compiler - Infrastructure.

    +

    We are pleased to announce the public release of the LLVM Compiler +Infrastructure.

    -

    LLVM is a new infrastructure designed for compile-time, link-time, runtime, - and "idle-time" optimization of programs from arbitrary programming - languages. LLVM is written in C++ and has been developed over the past 3 - years at the University of Illinois. It currently supports compilation of - C and C++ programs, using front-ends derived from GCC 3.4.

    +

    LLVM is a new infrastructure designed for compile-time, link-time, runtime, +and "idle-time" optimization of programs from arbitrary programming languages. +LLVM is written in C++ and has been developed since 2000 A.D. at the University +of Illinois. It currently supports compilation of C and C++ programs, using +front-ends derived from GCC 3.4.

    @@ -56,9 +56,8 @@
    -

    LLVM provides extensive documentation in HTML form. The documentation is -included in the source download (see README.TXT for details). You can also see -the documentation online:

    +

    LLVM provides extensive documentation in HTML form, which is available in the +source download and online:

    • Current LLVM documentation
    • From lattner at cs.uiuc.edu Tue May 11 21:55:01 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 11 21:55:01 2004 Subject: [llvm-commits] CVS: llvm/tools/bugpoint/OptimizerDriver.cpp Message-ID: <200405120255.VAA06914@zion.cs.uiuc.edu> Changes in directory llvm/tools/bugpoint: OptimizerDriver.cpp updated: 1.21 -> 1.22 --- Log message: Don't leave dead bytecode.output files around if the optimizer/block extractor crashes. --- Diffs of the changes: (+5 -6) Index: llvm/tools/bugpoint/OptimizerDriver.cpp diff -u llvm/tools/bugpoint/OptimizerDriver.cpp:1.21 llvm/tools/bugpoint/OptimizerDriver.cpp:1.22 --- llvm/tools/bugpoint/OptimizerDriver.cpp:1.21 Sun Mar 14 15:37:41 2004 +++ llvm/tools/bugpoint/OptimizerDriver.cpp Tue May 11 21:55:45 2004 @@ -135,13 +135,12 @@ exit(1); } - // If we are supposed to delete the bytecode file, remove it now - // unconditionally... this may fail if the file was never created, but that's - // ok. - if (DeleteOutput) - removeFile(OutputFilename); - bool ExitedOK = WIFEXITED(Status) && WEXITSTATUS(Status) == 0; + + // If we are supposed to delete the bytecode file or if the passes crashed, + // remove it now. This may fail if the file was never created, but that's ok. + if (DeleteOutput || !ExitedOK) + removeFile(OutputFilename); if (!Quiet) { if (ExitedOK) From lattner at cs.uiuc.edu Tue May 11 22:22:01 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 11 22:22:01 2004 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/CodeExtractor.cpp Message-ID: <200405120322.WAA11387@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: CodeExtractor.cpp updated: 1.17 -> 1.18 --- Log message: Two minor improvements: 1. Get rid of the silly abort block. When doing bb extraction, we get one abort block for every block extracted, which is kinda annoying. 2. If the switch ends up having a single destination, turn it into an unconditional branch. I would like to add support for conditional branches, but to do this we will want to have the function return a bool instead of a ushort. --- Diffs of the changes: (+14 -18) Index: llvm/lib/Transforms/Utils/CodeExtractor.cpp diff -u llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.17 llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.18 --- llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.17 Fri Apr 23 18:54:17 2004 +++ llvm/lib/Transforms/Utils/CodeExtractor.cpp Tue May 11 22:22:33 2004 @@ -390,24 +390,20 @@ } } - // Now that we've done the deed, make the default destination of the switch - // instruction be a block with a call to abort() -- since this path should not - // be taken, this will abort sooner rather than later. - if (TheSwitch->getNumSuccessors() > 1) { - Function *container = codeReplacer->getParent(); - BasicBlock *abortBB = new BasicBlock("abortBlock", container); - std::vector paramTypes; - FunctionType *abortTy = FunctionType::get(Type::VoidTy, paramTypes, false); - Function *abortFunc = - container->getParent()->getOrInsertFunction("abort", abortTy); - abortBB->getInstList().push_back(new CallInst(abortFunc)); - Function *ParentFunc = TheSwitch->getParent()->getParent(); - if (ParentFunc->getReturnType() == Type::VoidTy) - new ReturnInst(0, abortBB); - else - new ReturnInst(Constant::getNullValue(ParentFunc->getReturnType()), - abortBB); - TheSwitch->setSuccessor(0, abortBB); + // Now that we've done the deed, simplify the switch instruction. + unsigned NumSuccs = TheSwitch->getNumSuccessors(); + if (NumSuccs > 1) { + if (NumSuccs-1 == 1) { + // Only a single destination, change the switch into an unconditional + // branch. + new BranchInst(TheSwitch->getSuccessor(1), TheSwitch); + TheSwitch->getParent()->getInstList().erase(TheSwitch); + } else { + // Otherwise, make the default destination of the switch instruction be + // one of the other successors. + TheSwitch->setSuccessor(0, TheSwitch->getSuccessor(NumSuccs-1)); + TheSwitch->removeCase(NumSuccs-1); // Remove redundant case + } } else { // There is only 1 successor (the block containing the switch itself), which // means that previously this was the last part of the function, and hence From lattner at cs.uiuc.edu Tue May 11 23:14:01 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue May 11 23:14:01 2004 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/CodeExtractor.cpp Message-ID: <200405120414.XAA16114@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: CodeExtractor.cpp updated: 1.18 -> 1.19 --- Log message: Generate substantially better code when there are a limited number of exits from the extracted region. If the return has 0 or 1 exit blocks, the new function returns void. If it has 2 exits, it returns bool, otherwise it returns a ushort as before. This allows us to use a conditional branch instruction when there are two exit blocks, as often happens during block extraction. --- Diffs of the changes: (+61 -22) Index: llvm/lib/Transforms/Utils/CodeExtractor.cpp diff -u llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.18 llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.19 --- llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.18 Tue May 11 22:22:33 2004 +++ llvm/lib/Transforms/Utils/CodeExtractor.cpp Tue May 11 23:14:24 2004 @@ -44,9 +44,11 @@ std::set BlocksToExtract; DominatorSet *DS; bool AggregateArgs; + unsigned NumExitBlocks; + const Type *RetTy; public: CodeExtractor(DominatorSet *ds = 0, bool AggArgs = false) - : DS(ds), AggregateArgs(AggregateArgsOpt) {} + : DS(ds), AggregateArgs(AggregateArgsOpt), NumExitBlocks(~0U) {} Function *ExtractCodeRegion(const std::vector &code); @@ -76,6 +78,7 @@ void CodeExtractor::findInputsOutputs(Values &inputs, Values &outputs, BasicBlock *newHeader, BasicBlock *newRootNode) { + std::set ExitBlocks; for (std::set::const_iterator ci = BlocksToExtract.begin(), ce = BlocksToExtract.end(); ci != ce; ++ci) { BasicBlock *BB = *ci; @@ -116,7 +119,14 @@ break; } } // for: insts + + TerminatorInst *TI = BB->getTerminator(); + for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) + if (!BlocksToExtract.count(TI->getSuccessor(i))) + ExitBlocks.insert(TI->getSuccessor(i)); } // for: basic blocks + + NumExitBlocks = ExitBlocks.size(); } /// constructFunction - make a function based on inputs and outputs, as follows: @@ -133,7 +143,13 @@ DEBUG(std::cerr << "outputs: " << outputs.size() << "\n"); // This function returns unsigned, outputs will go back by reference. - Type *retTy = Type::UShortTy; + switch (NumExitBlocks) { + case 0: + case 1: RetTy = Type::VoidTy; break; + case 2: RetTy = Type::BoolTy; break; + default: RetTy = Type::UShortTy; break; + } + std::vector paramTy; // Add the types of the input values to the function's argument list @@ -154,7 +170,7 @@ paramTy.push_back(PointerType::get((*I)->getType())); } - DEBUG(std::cerr << "Function type: " << retTy << " f("); + DEBUG(std::cerr << "Function type: " << RetTy << " f("); DEBUG(for (std::vector::iterator i = paramTy.begin(), e = paramTy.end(); i != e; ++i) std::cerr << *i << ", "); DEBUG(std::cerr << ")\n"); @@ -164,7 +180,7 @@ paramTy.clear(); paramTy.push_back(StructPtr); } - const FunctionType *funcType = FunctionType::get(retTy, paramTy, false); + const FunctionType *funcType = FunctionType::get(RetTy, paramTy, false); // Create the new function Function *newFunction = new Function(funcType, @@ -296,7 +312,8 @@ } // Emit the call to the function - CallInst *call = new CallInst(newFunction, params, "targetBlock"); + CallInst *call = new CallInst(newFunction, params, + NumExitBlocks > 1 ? "targetBlock": ""); codeReplacer->getInstList().push_back(call); Function::aiterator OutputArgBegin = newFunction->abegin(); @@ -330,7 +347,9 @@ } // Now we can emit a switch statement using the call as a value. - SwitchInst *TheSwitch = new SwitchInst(call, codeReplacer, codeReplacer); + SwitchInst *TheSwitch = + new SwitchInst(ConstantUInt::getNullValue(Type::UShortTy), + codeReplacer, codeReplacer); // Since there may be multiple exits from the original region, make the new // function return an unsigned, switch on that number. This loop iterates @@ -353,12 +372,25 @@ // destination, create one now! NewTarget = new BasicBlock(OldTarget->getName() + ".exitStub", newFunction); + unsigned SuccNum = switchVal++; + + Value *brVal = 0; + switch (NumExitBlocks) { + case 0: + case 1: break; // No value needed. + case 2: // Conditional branch, return a bool + brVal = SuccNum ? ConstantBool::False : ConstantBool::True; + break; + default: + brVal = ConstantUInt::get(Type::UShortTy, SuccNum); + break; + } - ConstantUInt *brVal = ConstantUInt::get(Type::UShortTy, switchVal++); ReturnInst *NTRet = new ReturnInst(brVal, NewTarget); // Update the switch instruction. - TheSwitch->addCase(brVal, OldTarget); + TheSwitch->addCase(ConstantUInt::get(Type::UShortTy, SuccNum), + OldTarget); // Restore values just before we exit Function::aiterator OAI = OutputArgBegin; @@ -391,20 +423,8 @@ } // Now that we've done the deed, simplify the switch instruction. - unsigned NumSuccs = TheSwitch->getNumSuccessors(); - if (NumSuccs > 1) { - if (NumSuccs-1 == 1) { - // Only a single destination, change the switch into an unconditional - // branch. - new BranchInst(TheSwitch->getSuccessor(1), TheSwitch); - TheSwitch->getParent()->getInstList().erase(TheSwitch); - } else { - // Otherwise, make the default destination of the switch instruction be - // one of the other successors. - TheSwitch->setSuccessor(0, TheSwitch->getSuccessor(NumSuccs-1)); - TheSwitch->removeCase(NumSuccs-1); // Remove redundant case - } - } else { + switch (NumExitBlocks) { + case 0: // There is only 1 successor (the block containing the switch itself), which // means that previously this was the last part of the function, and hence // this should be rewritten as a `ret' @@ -420,6 +440,25 @@ new ReturnInst(0, TheSwitch); TheSwitch->getParent()->getInstList().erase(TheSwitch); + break; + case 1: + // Only a single destination, change the switch into an unconditional + // branch. + new BranchInst(TheSwitch->getSuccessor(1), TheSwitch); + TheSwitch->getParent()->getInstList().erase(TheSwitch); + break; + case 2: + new BranchInst(TheSwitch->getSuccessor(1), TheSwitch->getSuccessor(2), + call, TheSwitch); + TheSwitch->getParent()->getInstList().erase(TheSwitch); + break; + default: + // Otherwise, make the default destination of the switch instruction be one + // of the other successors. + TheSwitch->setOperand(0, call); + TheSwitch->setSuccessor(0, TheSwitch->getSuccessor(NumExitBlocks)); + TheSwitch->removeCase(NumExitBlocks); // Remove redundant case + break; } } From lattner at cs.uiuc.edu Wed May 12 01:01:01 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 12 01:01:01 2004 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/CodeExtractor.cpp Message-ID: <200405120601.BAA22399@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: CodeExtractor.cpp updated: 1.19 -> 1.20 --- Log message: * Pull some code out into the definedInRegion/definedInCaller methods * Add a stub for the severSplitPHINodes which will allow us to bbextract bb's with PHI nodes in them soon. * Remove unused arguments from findInputsOutputs * Dramatically simplify the code in findInputsOutputs. In particular, nothing really cares whether or not a PHI node is using something. * Move moveCodeToFunction to after emitCallAndSwitchStatement as that's the order they get called. * Fix a bug where we would code extract a region that included a call to vastart. Like 'alloca', calls to vastart must stay in the function that they are defined in. * Add some comments. --- Diffs of the changes: (+77 -77) Index: llvm/lib/Transforms/Utils/CodeExtractor.cpp diff -u llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.19 llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.20 --- llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.19 Tue May 11 23:14:24 2004 +++ llvm/lib/Transforms/Utils/CodeExtractor.cpp Wed May 12 01:01:40 2004 @@ -17,6 +17,7 @@ #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" #include "llvm/Module.h" #include "llvm/Pass.h" #include "llvm/Analysis/Dominators.h" @@ -55,9 +56,28 @@ bool isEligible(const std::vector &code); private: - void findInputsOutputs(Values &inputs, Values &outputs, - BasicBlock *newHeader, - BasicBlock *newRootNode); + /// definedInRegion - Return true if the specified value is defined in the + /// extracted region. + bool definedInRegion(Value *V) const { + if (Instruction *I = dyn_cast(V)) + if (BlocksToExtract.count(I->getParent())) + return true; + return false; + } + + /// definedInCaller - Return true if the specified value is defined in the + /// function being code extracted, but not in the region being extracted. + /// These values must be passed in as live-ins to the function. + bool definedInCaller(Value *V) const { + if (isa(V)) return true; + if (Instruction *I = dyn_cast(V)) + if (!BlocksToExtract.count(I->getParent())) + return true; + return false; + } + + void severSplitPHINodes(BasicBlock *&Header); + void findInputsOutputs(Values &inputs, Values &outputs); Function *constructFunction(const Values &inputs, const Values &outputs, @@ -75,51 +95,40 @@ }; } -void CodeExtractor::findInputsOutputs(Values &inputs, Values &outputs, - BasicBlock *newHeader, - BasicBlock *newRootNode) { +/// severSplitPHINodes - If a PHI node has multiple inputs from outside of the +/// region, we need to split the entry block of the region so that the PHI node +/// is easier to deal with. +void CodeExtractor::severSplitPHINodes(BasicBlock *&Header) { + + + +} + +// findInputsOutputs - Find inputs to, outputs from the code region. +// +void CodeExtractor::findInputsOutputs(Values &inputs, Values &outputs) { std::set ExitBlocks; for (std::set::const_iterator ci = BlocksToExtract.begin(), ce = BlocksToExtract.end(); ci != ce; ++ci) { BasicBlock *BB = *ci; + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { // If a used value is defined outside the region, it's an input. If an // instruction is used outside the region, it's an output. - if (PHINode *PN = dyn_cast(I)) { - for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { - Value *V = PN->getIncomingValue(i); - if (!BlocksToExtract.count(PN->getIncomingBlock(i)) && - (isa(V) || isa(V))) - inputs.push_back(V); - else if (Instruction *opI = dyn_cast(V)) { - if (!BlocksToExtract.count(opI->getParent())) - inputs.push_back(opI); - } else if (isa(V)) - inputs.push_back(V); - } - } else { - // All other instructions go through the generic input finder - // Loop over the operands of each instruction (inputs) - for (User::op_iterator op = I->op_begin(), opE = I->op_end(); - op != opE; ++op) - if (Instruction *opI = dyn_cast(*op)) { - // Check if definition of this operand is within the loop - if (!BlocksToExtract.count(opI->getParent())) - inputs.push_back(opI); - } else if (isa(*op)) { - inputs.push_back(*op); - } - } + for (User::op_iterator O = I->op_begin(), E = I->op_end(); O != E; ++O) + if (definedInCaller(*O)) + inputs.push_back(*O); - // Consider uses of this instruction (outputs) + // Consider uses of this instruction (outputs). for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E; ++UI) - if (!BlocksToExtract.count(cast(*UI)->getParent())) { + if (!definedInRegion(*UI)) { outputs.push_back(I); break; } } // for: insts + // Keep track of the exit blocks from the region. TerminatorInst *TI = BB->getTerminator(); for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) if (!BlocksToExtract.count(TI->getSuccessor(i))) @@ -238,30 +247,14 @@ return newFunction; } -void CodeExtractor::moveCodeToFunction(Function *newFunction) { - Function *oldFunc = (*BlocksToExtract.begin())->getParent(); - Function::BasicBlockListType &oldBlocks = oldFunc->getBasicBlockList(); - Function::BasicBlockListType &newBlocks = newFunction->getBasicBlockList(); - - for (std::set::const_iterator i = BlocksToExtract.begin(), - e = BlocksToExtract.end(); i != e; ++i) { - // Delete the basic block from the old function, and the list of blocks - oldBlocks.remove(*i); - - // Insert this basic block into the new function - newBlocks.push_back(*i); - } -} - -void -CodeExtractor::emitCallAndSwitchStatement(Function *newFunction, - BasicBlock *codeReplacer, - Values &inputs, - Values &outputs) { - - // Emit a call to the new function, passing in: - // *pointer to struct (if aggregating parameters), or - // plan inputs and allocated memory for outputs +/// emitCallAndSwitchStatement - This method sets up the caller side by adding +/// the call instruction, splitting any PHI nodes in the header block as +/// necessary. +void CodeExtractor:: +emitCallAndSwitchStatement(Function *newFunction, BasicBlock *codeReplacer, + Values &inputs, Values &outputs) { + // Emit a call to the new function, passing in: *pointer to struct (if + // aggregating parameters), or plan inputs and allocated memory for outputs std::vector params, StructValues, ReloadOutputs; // Add inputs as params, or to be filled into the struct @@ -462,6 +455,20 @@ } } +void CodeExtractor::moveCodeToFunction(Function *newFunction) { + Function *oldFunc = (*BlocksToExtract.begin())->getParent(); + Function::BasicBlockListType &oldBlocks = oldFunc->getBasicBlockList(); + Function::BasicBlockListType &newBlocks = newFunction->getBasicBlockList(); + + for (std::set::const_iterator i = BlocksToExtract.begin(), + e = BlocksToExtract.end(); i != e; ++i) { + // Delete the basic block from the old function, and the list of blocks + oldBlocks.remove(*i); + + // Insert this basic block into the new function + newBlocks.push_back(*i); + } +} /// ExtractRegion - Removes a loop from a function, replaces it with a call to /// new function. Returns pointer to the new function. @@ -497,6 +504,10 @@ // Assumption: this is a single-entry code region, and the header is the first // block in the region. BasicBlock *header = code[0]; + + // If we have to split PHI nodes, do so now. + severSplitPHINodes(header); + for (unsigned i = 1, e = code.size(); i != e; ++i) for (pred_iterator PI = pred_begin(code[i]), E = pred_end(code[i]); PI != E; ++PI) @@ -510,29 +521,14 @@ BasicBlock *codeReplacer = new BasicBlock("codeRepl", oldFunction); // The new function needs a root node because other nodes can branch to the - // head of the loop, and the root cannot have predecessors + // head of the region, but the entry node of a function cannot have preds. BasicBlock *newFuncRoot = new BasicBlock("newFuncRoot"); newFuncRoot->getInstList().push_back(new BranchInst(header)); - // Find inputs to, outputs from the code region - // - // If one of the inputs is coming from a different basic block and it's in a - // phi node, we need to rewrite the phi node: - // - // * All the inputs which involve basic blocks OUTSIDE of this region go into - // a NEW phi node that takes care of finding which value really came in. - // The result of this phi is passed to the function as an argument. - // - // * All the other phi values stay. - // - // FIXME: PHI nodes' incoming blocks aren't being rewritten to accomodate for - // blocks moving to a new function. - // SOLUTION: move Phi nodes out of the loop header into the codeReplacer, pass - // the values as parameters to the function - findInputsOutputs(inputs, outputs, codeReplacer, newFuncRoot); + // Find inputs to, outputs from the code region. + findInputsOutputs(inputs, outputs); - // Step 2: Construct new function based on inputs/outputs, - // Add allocas for all defs + // Construct new function based on inputs/outputs & add allocas for all defs. Function *newFunction = constructFunction(inputs, outputs, code[0], newFuncRoot, codeReplacer, oldFunction, @@ -568,13 +564,17 @@ } bool CodeExtractor::isEligible(const std::vector &code) { - // Deny code region if it contains allocas + // Deny code region if it contains allocas or vastarts. for (std::vector::const_iterator BB = code.begin(), e=code.end(); BB != e; ++BB) for (BasicBlock::const_iterator I = (*BB)->begin(), Ie = (*BB)->end(); I != Ie; ++I) if (isa(*I)) return false; + else if (const CallInst *CI = dyn_cast(I)) + if (const Function *F = CI->getCalledFunction()) + if (F->getIntrinsicID() == Intrinsic::vastart) + return false; return true; } From lattner at cs.uiuc.edu Wed May 12 10:29:03 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 12 10:29:03 2004 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/CodeExtractor.cpp Message-ID: <200405121529.KAA28354@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: CodeExtractor.cpp updated: 1.20 -> 1.21 --- Log message: Implement splitting of PHI nodes, allowing block extraction of BB's that have PHI node entries from multiple outside-the-region blocks. This also fixes extraction of the entry block in a function. Yaay. This has successfully block extracted all (but one) block from the score_move function in obsequi (out of 33). Hrm, I wonder which block the bug is in. :) --- Diffs of the changes: (+96 -7) Index: llvm/lib/Transforms/Utils/CodeExtractor.cpp diff -u llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.20 llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.21 --- llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.20 Wed May 12 01:01:40 2004 +++ llvm/lib/Transforms/Utils/CodeExtractor.cpp Wed May 12 10:29:13 2004 @@ -99,9 +99,93 @@ /// region, we need to split the entry block of the region so that the PHI node /// is easier to deal with. void CodeExtractor::severSplitPHINodes(BasicBlock *&Header) { - + bool HasPredsFromRegion = false; + unsigned NumPredsOutsideRegion = 0; + + if (Header != &Header->getParent()->front()) { + PHINode *PN = dyn_cast(Header->begin()); + if (!PN) return; // No PHI nodes. + + // If the header node contains any PHI nodes, check to see if there is more + // than one entry from outside the region. If so, we need to sever the + // header block into two. + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + if (BlocksToExtract.count(PN->getIncomingBlock(i))) + HasPredsFromRegion = true; + else + ++NumPredsOutsideRegion; + + // If there is one (or fewer) predecessor from outside the region, we don't + // need to do anything special. + if (NumPredsOutsideRegion <= 1) return; + } + + // Otherwise, we need to split the header block into two pieces: one + // containing PHI nodes merging values from outside of the region, and a + // second that contains all of the code for the block and merges back any + // incoming values from inside of the region. + BasicBlock::iterator AfterPHIs = Header->begin(); + while (isa(AfterPHIs)) ++AfterPHIs; + BasicBlock *NewBB = Header->splitBasicBlock(AfterPHIs, + Header->getName()+".ce"); + + // We only want to code extract the second block now, and it becomes the new + // header of the region. + BasicBlock *OldPred = Header; + BlocksToExtract.erase(OldPred); + BlocksToExtract.insert(NewBB); + Header = NewBB; + + // Okay, update dominator sets. The blocks that dominate the new one are the + // blocks that dominate TIBB plus the new block itself. + if (DS) { + DominatorSet::DomSetType DomSet = DS->getDominators(OldPred); + DomSet.insert(NewBB); // A block always dominates itself. + DS->addBasicBlock(NewBB, DomSet); + + // Additionally, NewBB dominates all blocks in the function that are + // dominated by OldPred. + Function *F = Header->getParent(); + for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) + if (DS->properlyDominates(OldPred, I)) + DS->addDominator(I, NewBB); + } + + // Okay, now we need to adjust the PHI nodes and any branches from within the + // region to go to the new header block instead of the old header block. + if (HasPredsFromRegion) { + PHINode *PN = cast(OldPred->begin()); + // Loop over all of the predecessors of OldPred that are in the region, + // changing them to branch to NewBB instead. + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + if (BlocksToExtract.count(PN->getIncomingBlock(i))) { + TerminatorInst *TI = PN->getIncomingBlock(i)->getTerminator(); + TI->replaceUsesOfWith(OldPred, NewBB); + } + // Okay, everthing within the region is now branching to the right block, we + // just have to update the PHI nodes now, inserting PHI nodes into NewBB. + for (AfterPHIs = OldPred->begin(); + PHINode *PN = dyn_cast(AfterPHIs); ++AfterPHIs) { + // Create a new PHI node in the new region, which has an incoming value + // from OldPred of PN. + PHINode *NewPN = new PHINode(PN->getType(), PN->getName()+".ce", + NewBB->begin()); + NewPN->addIncoming(PN, OldPred); + + // Loop over all of the incoming value in PN, moving them to NewPN if they + // are from the extracted region. + for (unsigned i = 0; i != PN->getNumIncomingValues(); ++i) { + if (BlocksToExtract.count(PN->getIncomingBlock(i))) { + NewPN->addIncoming(PN->getIncomingValue(i), PN->getIncomingBlock(i)); + PN->removeIncomingValue(i); + --i; + } + } + } + } + verifyFunction(*NewBB->getParent()); } // findInputsOutputs - Find inputs to, outputs from the code region. @@ -505,9 +589,6 @@ // block in the region. BasicBlock *header = code[0]; - // If we have to split PHI nodes, do so now. - severSplitPHINodes(header); - for (unsigned i = 1, e = code.size(); i != e; ++i) for (pred_iterator PI = pred_begin(code[i]), E = pred_end(code[i]); PI != E; ++PI) @@ -515,6 +596,9 @@ "No blocks in this region may have entries from outside the region" " except for the first block!"); + // If we have to split PHI nodes, do so now. + severSplitPHINodes(header); + Function *oldFunction = header->getParent(); // This takes place of the original loop @@ -529,7 +613,7 @@ findInputsOutputs(inputs, outputs); // Construct new function based on inputs/outputs & add allocas for all defs. - Function *newFunction = constructFunction(inputs, outputs, code[0], + Function *newFunction = constructFunction(inputs, outputs, header, newFuncRoot, codeReplacer, oldFunction, oldFunction->getParent()); @@ -538,9 +622,9 @@ moveCodeToFunction(newFunction); - // Loop over all of the PHI nodes in the entry block (code[0]), and change any + // Loop over all of the PHI nodes in the header block, and change any // references to the old incoming edge to be the new incoming edge. - for (BasicBlock::iterator I = code[0]->begin(); + for (BasicBlock::iterator I = header->begin(); PHINode *PN = dyn_cast(I); ++I) for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) if (!BlocksToExtract.count(PN->getIncomingBlock(i))) @@ -558,6 +642,11 @@ if (BlocksToExtract.count(PN->getIncomingBlock(i))) PN->setIncomingBlock(i, codeReplacer); + //std::cerr << "NEW FUNCTION: " << *newFunction; + // verifyFunction(*newFunction); + + // std::cerr << "OLD FUNCTION: " << *oldFunction; + // verifyFunction(*oldFunction); DEBUG(if (verifyFunction(*newFunction)) abort()); return newFunction; From lattner at cs.uiuc.edu Wed May 12 11:08:07 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 12 11:08:07 2004 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/CodeExtractor.cpp Message-ID: <200405121607.LAA05305@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: CodeExtractor.cpp updated: 1.21 -> 1.22 --- Log message: Implement support for code extracting basic blocks that have a return instruction in them. --- Diffs of the changes: (+12 -2) Index: llvm/lib/Transforms/Utils/CodeExtractor.cpp diff -u llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.21 llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.22 --- llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.21 Wed May 12 10:29:13 2004 +++ llvm/lib/Transforms/Utils/CodeExtractor.cpp Wed May 12 11:07:41 2004 @@ -77,6 +77,7 @@ } void severSplitPHINodes(BasicBlock *&Header); + void splitReturnBlocks(); void findInputsOutputs(Values &inputs, Values &outputs); Function *constructFunction(const Values &inputs, @@ -184,8 +185,13 @@ } } } +} - verifyFunction(*NewBB->getParent()); +void CodeExtractor::splitReturnBlocks() { + for (std::set::iterator I = BlocksToExtract.begin(), + E = BlocksToExtract.end(); I != E; ++I) + if (ReturnInst *RI = dyn_cast((*I)->getTerminator())) + (*I)->splitBasicBlock(RI, (*I)->getName()+".ret"); } // findInputsOutputs - Find inputs to, outputs from the code region. @@ -596,8 +602,12 @@ "No blocks in this region may have entries from outside the region" " except for the first block!"); - // If we have to split PHI nodes, do so now. + // If we have to split PHI nodes or the entry block, do so now. severSplitPHINodes(header); + + // If we have any return instructions in the region, split those blocks so + // that the return is not in the region. + splitReturnBlocks(); Function *oldFunction = header->getParent(); From lattner at cs.uiuc.edu Wed May 12 11:08:24 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 12 11:08:24 2004 Subject: [llvm-commits] CVS: llvm/tools/bugpoint/Miscompilation.cpp Message-ID: <200405121608.LAA05318@zion.cs.uiuc.edu> Changes in directory llvm/tools/bugpoint: Miscompilation.cpp updated: 1.46 -> 1.47 --- Log message: Check to see if all blocks are extractible first. --- Diffs of the changes: (+19 -8) Index: llvm/tools/bugpoint/Miscompilation.cpp diff -u llvm/tools/bugpoint/Miscompilation.cpp:1.46 llvm/tools/bugpoint/Miscompilation.cpp:1.47 --- llvm/tools/bugpoint/Miscompilation.cpp:1.46 Tue May 11 21:43:24 2004 +++ llvm/tools/bugpoint/Miscompilation.cpp Wed May 12 11:08:01 2004 @@ -354,11 +354,15 @@ bool ReduceMiscompiledBlocks::TestFuncs(const std::vector &BBs) { // Test to see if the function is misoptimized if we ONLY run it on the // functions listed in Funcs. - std::cout << "Checking to see if the program is misoptimized when all but " - << "these " << BBs.size() << " blocks are extracted: "; - for (unsigned i = 0, e = BBs.size() < 10 ? BBs.size() : 10; i != e; ++i) - std::cout << BBs[i]->getName() << " "; - if (BBs.size() > 10) std::cout << "..."; + std::cout << "Checking to see if the program is misoptimized when all "; + if (!BBs.empty()) { + std::cout << "but these " << BBs.size() << " blocks are extracted: "; + for (unsigned i = 0, e = BBs.size() < 10 ? BBs.size() : 10; i != e; ++i) + std::cout << BBs[i]->getName() << " "; + if (BBs.size() > 10) std::cout << "..."; + } else { + std::cout << "blocks are extracted."; + } std::cout << "\n"; // Split the module into the two halves of the program we want. @@ -399,9 +403,16 @@ // obscuring the bug. The Blocks list will end up containing blocks that must // be retained from the original program. unsigned OldSize = Blocks.size(); - ReduceMiscompiledBlocks(BD, TestFn, MiscompiledFunctions).reduceList(Blocks); - if (Blocks.size() == OldSize) - return false; + + // Check to see if all blocks are extractible first. + if (ReduceMiscompiledBlocks(BD, TestFn, + MiscompiledFunctions).TestFuncs(std::vector())) { + Blocks.clear(); + } else { + ReduceMiscompiledBlocks(BD, TestFn,MiscompiledFunctions).reduceList(Blocks); + if (Blocks.size() == OldSize) + return false; + } Module *ProgClone = CloneModule(BD.getProgram()); Module *ToExtract = SplitFunctionsOutOfModule(ProgClone, From lattner at cs.uiuc.edu Wed May 12 11:26:03 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 12 11:26:03 2004 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/CodeExtractor.cpp Message-ID: <200405121626.LAA09454@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: CodeExtractor.cpp updated: 1.22 -> 1.23 --- Log message: Do not pass in the same argument to the extracted function more than once, and give the extracted function a more useful name than just foo_code. --- Diffs of the changes: (+8 -1) Index: llvm/lib/Transforms/Utils/CodeExtractor.cpp diff -u llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.22 llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.23 --- llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.22 Wed May 12 11:07:41 2004 +++ llvm/lib/Transforms/Utils/CodeExtractor.cpp Wed May 12 11:26:18 2004 @@ -226,6 +226,12 @@ } // for: basic blocks NumExitBlocks = ExitBlocks.size(); + + // Eliminate duplicates. + std::sort(inputs.begin(), inputs.end()); + inputs.erase(std::unique(inputs.begin(), inputs.end()), inputs.end()); + std::sort(outputs.begin(), outputs.end()); + outputs.erase(std::unique(outputs.begin(), outputs.end()), outputs.end()); } /// constructFunction - make a function based on inputs and outputs, as follows: @@ -284,7 +290,8 @@ // Create the new function Function *newFunction = new Function(funcType, GlobalValue::InternalLinkage, - oldFunction->getName() + "_code", M); + oldFunction->getName() + "_" + + header->getName(), M); newFunction->getBasicBlockList().push_back(newRootNode); // Create an iterator to name all of the arguments we inserted. From llvm at cs.uiuc.edu Wed May 12 11:33:04 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Wed May 12 11:33:04 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/tools/bugpoint/CrashDebugger.cpp Message-ID: <200405121633.LAA09953@zion.cs.uiuc.edu> Changes in directory llvm/tools/bugpoint: CrashDebugger.cpp updated: 1.34 -> 1.34.4.1 --- Log message: Change SymbolTable to not subclass from std::map but to embed one instead and cleanup use of SymbolTable in rest of LLVM. Also, add some new methods to SymbolTable for small/utility cases and substitute calls to them in LLVM. --- Diffs of the changes: (+1 -1) Index: llvm/tools/bugpoint/CrashDebugger.cpp diff -u llvm/tools/bugpoint/CrashDebugger.cpp:1.34 llvm/tools/bugpoint/CrashDebugger.cpp:1.34.4.1 --- llvm/tools/bugpoint/CrashDebugger.cpp:1.34 Sun Mar 14 14:50:42 2004 +++ llvm/tools/bugpoint/CrashDebugger.cpp Wed May 12 11:33:43 2004 @@ -245,7 +245,7 @@ BBs.clear(); for (unsigned i = 0, e = BlockInfo.size(); i != e; ++i) { SymbolTable &ST = BlockInfo[i].first->getSymbolTable(); - SymbolTable::iterator I = ST.find(Type::LabelTy); + SymbolTable::type_iterator I = ST.find(Type::LabelTy); if (I != ST.end() && I->second.count(BlockInfo[i].second)) BBs.push_back(cast(I->second[BlockInfo[i].second])); } From llvm at cs.uiuc.edu Wed May 12 11:33:10 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Wed May 12 11:33:10 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/lib/Transforms/IPO/DeadTypeElimination.cpp MutateStructTypes.cpp Message-ID: <200405121633.LAA09917@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: DeadTypeElimination.cpp updated: 1.49 -> 1.49.4.1 MutateStructTypes.cpp updated: 1.46 -> 1.46.4.1 --- Log message: Change SymbolTable to not subclass from std::map but to embed one instead and cleanup use of SymbolTable in rest of LLVM. Also, add some new methods to SymbolTable for small/utility cases and substitute calls to them in LLVM. --- Diffs of the changes: (+6 -6) Index: llvm/lib/Transforms/IPO/DeadTypeElimination.cpp diff -u llvm/lib/Transforms/IPO/DeadTypeElimination.cpp:1.49 llvm/lib/Transforms/IPO/DeadTypeElimination.cpp:1.49.4.1 --- llvm/lib/Transforms/IPO/DeadTypeElimination.cpp:1.49 Thu Feb 26 14:02:23 2004 +++ llvm/lib/Transforms/IPO/DeadTypeElimination.cpp Wed May 12 11:33:43 2004 @@ -74,11 +74,11 @@ // Check the symbol table for superfluous type entries... // // Grab the 'type' plane of the module symbol... - SymbolTable::iterator STI = ST.find(Type::TypeTy); + SymbolTable::type_iterator STI = ST.find(Type::TypeTy); if (STI != ST.end()) { // Loop over all entries in the type plane... - SymbolTable::VarMap &Plane = STI->second; - for (SymbolTable::VarMap::iterator PI = Plane.begin(); PI != Plane.end();) { + SymbolTable::ValueMap &Plane = STI->second; + for (SymbolTable::value_iterator PI = Plane.begin(); PI != Plane.end();) { // If this entry should be unconditionally removed, or if we detect that // the type is not used, remove it. const Type *RHS = cast(PI->second); Index: llvm/lib/Transforms/IPO/MutateStructTypes.cpp diff -u llvm/lib/Transforms/IPO/MutateStructTypes.cpp:1.46 llvm/lib/Transforms/IPO/MutateStructTypes.cpp:1.46.4.1 --- llvm/lib/Transforms/IPO/MutateStructTypes.cpp:1.46 Sun Feb 8 22:37:31 2004 +++ llvm/lib/Transforms/IPO/MutateStructTypes.cpp Wed May 12 11:33:43 2004 @@ -269,10 +269,10 @@ // Remap the symbol table to refer to the types in a nice way // SymbolTable &ST = M.getSymbolTable(); - SymbolTable::iterator I = ST.find(Type::TypeTy); + SymbolTable::type_iterator I = ST.find(Type::TypeTy); if (I != ST.end()) { // Get the type plane for Type's - SymbolTable::VarMap &Plane = I->second; - for (SymbolTable::type_iterator TI = Plane.begin(), TE = Plane.end(); + SymbolTable::ValueMap &Plane = I->second; + for (SymbolTable::value_iterator TI = Plane.begin(), TE = Plane.end(); TI != TE; ++TI) { // FIXME: This is gross, I'm reaching right into a symbol table and // mucking around with it's internals... but oh well. From llvm at cs.uiuc.edu Wed May 12 11:33:15 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Wed May 12 11:33:15 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/lib/VMCore/AsmWriter.cpp Module.cpp SlotCalculator.cpp SymbolTable.cpp Verifier.cpp Message-ID: <200405121633.LAA09952@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: AsmWriter.cpp updated: 1.128 -> 1.128.2.1 Module.cpp updated: 1.49 -> 1.49.2.1 SlotCalculator.cpp updated: 1.53 -> 1.53.2.1 SymbolTable.cpp updated: 1.42 -> 1.42.6.1 Verifier.cpp updated: 1.97 -> 1.97.2.1 --- Log message: Change SymbolTable to not subclass from std::map but to embed one instead and cleanup use of SymbolTable in rest of LLVM. Also, add some new methods to SymbolTable for small/utility cases and substitute calls to them in LLVM. --- Diffs of the changes: (+135 -89) Index: llvm/lib/VMCore/AsmWriter.cpp diff -u llvm/lib/VMCore/AsmWriter.cpp:1.128 llvm/lib/VMCore/AsmWriter.cpp:1.128.2.1 --- llvm/lib/VMCore/AsmWriter.cpp:1.128 Wed Apr 28 14:24:28 2004 +++ llvm/lib/VMCore/AsmWriter.cpp Wed May 12 11:33:43 2004 @@ -105,18 +105,18 @@ std::map &TypeNames) { if (!M) return; const SymbolTable &ST = M->getSymbolTable(); - SymbolTable::const_iterator PI = ST.find(Type::TypeTy); + SymbolTable::type_const_iterator PI = ST.find(Type::TypeTy); if (PI != ST.end()) { - SymbolTable::type_const_iterator I = PI->second.begin(); - for (; I != PI->second.end(); ++I) { + SymbolTable::value_const_iterator VI = PI->second.begin(); + for (; VI != PI->second.end(); ++VI) { // As a heuristic, don't insert pointer to primitive types, because // they are used too often to have a single useful name. // - const Type *Ty = cast(I->second); + const Type *Ty = cast(VI->second); if (!isa(Ty) || !cast(Ty)->getElementType()->isPrimitiveType() || isa(cast(Ty)->getElementType())) - TypeNames.insert(std::make_pair(Ty, getLLVMName(I->first))); + TypeNames.insert(std::make_pair(Ty, getLLVMName(VI->first))); } } } @@ -609,9 +609,9 @@ /// if a named constant is found, emit it's declaration... /// void AssemblyWriter::printSymbolTable(const SymbolTable &ST) { - for (SymbolTable::const_iterator TI = ST.begin(); TI != ST.end(); ++TI) { - SymbolTable::type_const_iterator I = ST.type_begin(TI->first); - SymbolTable::type_const_iterator End = ST.type_end(TI->first); + for (SymbolTable::type_const_iterator TI = ST.begin(); TI != ST.end(); ++TI) { + SymbolTable::value_const_iterator I = ST.type_begin(TI->first); + SymbolTable::value_const_iterator End = ST.type_end(TI->first); for (; I != End; ++I) { const Value *V = I->second; Index: llvm/lib/VMCore/Module.cpp diff -u llvm/lib/VMCore/Module.cpp:1.49 llvm/lib/VMCore/Module.cpp:1.49.2.1 --- llvm/lib/VMCore/Module.cpp:1.49 Wed Apr 21 13:27:56 2004 +++ llvm/lib/VMCore/Module.cpp Wed May 12 11:33:43 2004 @@ -267,18 +267,7 @@ // std::string Module::getTypeName(const Type *Ty) const { const SymbolTable &ST = getSymbolTable(); - if (ST.find(Type::TypeTy) == ST.end()) - return ""; // No names for types... - - SymbolTable::type_const_iterator TI = ST.type_begin(Type::TypeTy); - SymbolTable::type_const_iterator TE = ST.type_end(Type::TypeTy); - - while (TI != TE && TI->second != (const Value*)Ty) - ++TI; - - if (TI != TE) // Must have found an entry! - return TI->first; - return ""; // Must not have found anything... + return ST.get_name( (const Value*) Ty ); } Index: llvm/lib/VMCore/SlotCalculator.cpp diff -u llvm/lib/VMCore/SlotCalculator.cpp:1.53 llvm/lib/VMCore/SlotCalculator.cpp:1.53.2.1 --- llvm/lib/VMCore/SlotCalculator.cpp:1.53 Tue Apr 27 10:13:09 2004 +++ llvm/lib/VMCore/SlotCalculator.cpp Wed May 12 11:33:43 2004 @@ -248,18 +248,19 @@ // into the values table... // void SlotCalculator::processSymbolTable(const SymbolTable *ST) { - for (SymbolTable::const_iterator I = ST->begin(), E = ST->end(); I != E; ++I) - for (SymbolTable::type_const_iterator TI = I->second.begin(), - TE = I->second.end(); TI != TE; ++TI) - getOrCreateSlot(TI->second); + for (SymbolTable::type_const_iterator TI = ST->begin(), TE = ST->end(); + TI != TE; ++TI) + for (SymbolTable::value_const_iterator VI = TI->second.begin(), + VE = TI->second.end(); VI != VE; ++VI) + getOrCreateSlot(VI->second); } void SlotCalculator::processSymbolTableConstants(const SymbolTable *ST) { - for (SymbolTable::const_iterator I = ST->begin(), E = ST->end(); I != E; ++I) - for (SymbolTable::type_const_iterator TI = I->second.begin(), - TE = I->second.end(); TI != TE; ++TI) - if (isa(TI->second) || isa(TI->second)) - getOrCreateSlot(TI->second); + for (SymbolTable::type_const_iterator TI = ST->begin(), TE = ST->end(); TI != TE; ++TI) + for (SymbolTable::value_const_iterator VI = TI->second.begin(), + VE = TI->second.end(); VI != VE; ++VI) + if (isa(VI->second) || isa(VI->second)) + getOrCreateSlot(VI->second); } @@ -453,12 +454,13 @@ } const SymbolTable &ST = F->getSymbolTable(); - for (SymbolTable::const_iterator I = ST.begin(), E = ST.end(); I != E; ++I) - for (SymbolTable::type_const_iterator TI = I->second.begin(), - TE = I->second.end(); TI != TE; ++TI) - if (isa(TI->second) || isa(TI->second) || - isa(TI->second)) - getOrCreateCompactionTableSlot(TI->second); + for (SymbolTable::type_const_iterator TI = ST.begin(), TE = ST.end(); + TI != TE; ++TI) + for (SymbolTable::value_const_iterator VI = TI->second.begin(), + VE = TI->second.end(); VI != VE; ++VI) + if (isa(VI->second) || isa(VI->second) || + isa(VI->second)) + getOrCreateCompactionTableSlot(VI->second); // Now that we have all of the values in the table, and know what types are // referenced, make sure that there is at least the zero initializer in any Index: llvm/lib/VMCore/SymbolTable.cpp diff -u llvm/lib/VMCore/SymbolTable.cpp:1.42 llvm/lib/VMCore/SymbolTable.cpp:1.42.6.1 --- llvm/lib/VMCore/SymbolTable.cpp:1.42 Wed Dec 31 01:08:19 2003 +++ llvm/lib/VMCore/SymbolTable.cpp Wed May 12 11:33:43 2004 @@ -23,10 +23,10 @@ SymbolTable::~SymbolTable() { // Drop all abstract type references in the type plane... - iterator TyPlane = find(Type::TypeTy); - if (TyPlane != end()) { - VarMap &TyP = TyPlane->second; - for (VarMap::iterator I = TyP.begin(), E = TyP.end(); I != E; ++I) { + type_iterator TyPlane = map.find(Type::TypeTy); + if (TyPlane != map.end()) { + ValueMap &TyP = TyPlane->second; + for (value_iterator I = TyP.begin(), E = TyP.end(); I != E; ++I) { const Type *Ty = cast(I->second); if (Ty->isAbstract()) // If abstract, drop the reference... cast(Ty)->removeAbstractTypeUser(this); @@ -38,8 +38,8 @@ #ifndef NDEBUG // Only do this in -g mode... bool LeftoverValues = true; - for (iterator i = begin(); i != end(); ++i) { - for (type_iterator I = i->second.begin(); I != i->second.end(); ++I) + for (type_iterator i = map.begin(); i != map.end(); ++i) { + for (value_iterator I = i->second.begin(); I != i->second.end(); ++I) if (!isa(I->second) && !isa(I->second)) { std::cerr << "Value still in symbol table! Type = '" << i->first->getDescription() << "' Name = '" @@ -57,12 +57,12 @@ // the specified type. // std::string SymbolTable::getUniqueName(const Type *Ty, - const std::string &BaseName) { - iterator I = find(Ty); - if (I == end()) return BaseName; + const std::string &BaseName) const { + type_const_iterator I = map.find(Ty); + if (I == map.end()) return BaseName; std::string TryName = BaseName; - type_iterator End = I->second.end(); + value_const_iterator End = I->second.end(); while (I->second.find(TryName) != End) // Loop until we find a free TryName = BaseName + utostr(++LastUnique); // name in the symbol table @@ -73,9 +73,9 @@ // lookup - Returns null on failure... Value *SymbolTable::lookup(const Type *Ty, const std::string &Name) const { - const_iterator I = find(Ty); - if (I != end()) { // We have symbols in that plane... - type_const_iterator J = I->second.find(Name); + type_const_iterator I = map.find(Ty); + if (I != map.end()) { // We have symbols in that plane... + value_const_iterator J = I->second.find(Name); if (J != I->second.end()) // and the name is in our hash table... return J->second; } @@ -87,17 +87,17 @@ assert(N->hasName() && "Value doesn't have name!"); if (InternallyInconsistent) return; - iterator I = find(N->getType()); - assert(I != end() && + type_iterator I = map.find(N->getType()); + assert(I != map.end() && "Trying to remove a type that doesn't have a plane yet!"); removeEntry(I, I->second.find(N->getName())); } // removeEntry - Remove a value from the symbol table... // -Value *SymbolTable::removeEntry(iterator Plane, type_iterator Entry) { +Value *SymbolTable::removeEntry(type_iterator Plane, value_iterator Entry) { if (InternallyInconsistent) return 0; - assert(Plane != super::end() && + assert(Plane != map.end() && Entry != Plane->second.end() && "Invalid entry to remove!"); Value *Result = Entry->second; @@ -123,7 +123,7 @@ cast(Plane->first)->removeAbstractTypeUser(this); } - erase(Plane); + map.erase(Plane); } // If we are removing an abstract type, remove the symbol table from it's use @@ -163,11 +163,11 @@ << VTy->getDescription() << "\n"; #endif - iterator I = find(VTy); - if (I == end()) { // Not in collection yet... insert dummy entry + type_iterator I = map.find(VTy); + if (I == map.end()) { // Not in collection yet... insert dummy entry // Insert a new empty element. I points to the new elements. - I = super::insert(make_pair(VTy, VarMap())).first; - assert(I != end() && "How did insert fail?"); + I = map.insert(make_pair(VTy, ValueMap())).first; + assert(I != map.end() && "How did insert fail?"); // Check to see if the type is abstract. If so, it might be refined in the // future, which would cause the plane of the old type to get merged into @@ -196,17 +196,71 @@ } } +bool +SymbolTable::hasTypes( void ) const { + type_const_iterator PI = map.find(Type::TypeTy); + if (PI == map.end()) return false; + return true; +} + +bool +SymbolTable::isEmpty( void ) const { + return map.empty(); +} + +std::string SymbolTable::get_name( const Value* v ) const { + if (map.find(Type::TypeTy) == map.end()) + return ""; // No names for types... + + value_const_iterator VI = type_begin(Type::TypeTy); + value_const_iterator VE = type_end(Type::TypeTy); + + while (VI != VE && VI->second != v ) + ++VI; + + if (VI != VE) // Must have found an entry! + return VI->first; + return ""; // Must not have found anything... +} + +bool SymbolTable::strip( void ) { + bool RemovedSymbol = false; + for (type_iterator I = map.begin(); I != map.end();) { + // Removing items from the plane can cause the plane itself to get deleted. + // If this happens, make sure we incremented our plane iterator already! + ValueMap &Plane = (I++)->second; + value_iterator B = Plane.begin(), Bend = Plane.end(); + while (B != Bend) { // Found nonempty type plane! + Value *V = B->second; + + if (isa(V) || isa(V)) { + type_remove(B++); + RemovedSymbol = true; + } else { + ++B; + if (!isa(V) || cast(V)->hasInternalLinkage()){ + // Set name to "", removing from symbol table! + V->setName("", this); + RemovedSymbol = true; + } + } + } + } + + return RemovedSymbol; +} + // This function is called when one of the types in the type plane are refined void SymbolTable::refineAbstractType(const DerivedType *OldType, const Type *NewType) { // Search to see if we have any values of the type oldtype. If so, we need to // move them into the newtype plane... - iterator TPI = find(OldType); - if (TPI != end()) { + type_iterator TPI = map.find(OldType); + if (TPI != map.end()) { // Get a handle to the new type plane... - iterator NewTypeIt = find(NewType); - if (NewTypeIt == super::end()) { // If no plane exists, add one - NewTypeIt = super::insert(make_pair(NewType, VarMap())).first; + type_iterator NewTypeIt = map.find(NewType); + if (NewTypeIt == map.end()) { // If no plane exists, add one + NewTypeIt = map.insert(make_pair(NewType, ValueMap())).first; if (NewType->isAbstract()) { cast(NewType)->addAbstractTypeUser(this); @@ -217,14 +271,14 @@ } } - VarMap &NewPlane = NewTypeIt->second; - VarMap &OldPlane = TPI->second; + ValueMap &NewPlane = NewTypeIt->second; + ValueMap &OldPlane = TPI->second; while (!OldPlane.empty()) { std::pair V = *OldPlane.begin(); // Check to see if there is already a value in the symbol table that this // would collide with. - type_iterator TI = NewPlane.find(V.first); + value_iterator TI = NewPlane.find(V.first); if (TI != NewPlane.end() && TI->second == V.second) { // No action @@ -294,18 +348,18 @@ OldType->removeAbstractTypeUser(this); // Remove the plane that is no longer used - erase(TPI); + map.erase(TPI); } - TPI = find(Type::TypeTy); - if (TPI != end()) { + TPI = map.find(Type::TypeTy); + if (TPI != map.end()) { // Loop over all of the types in the symbol table, replacing any references // to OldType with references to NewType. Note that there may be multiple // occurrences, and although we only need to remove one at a time, it's // faster to remove them all in one pass. // - VarMap &TyPlane = TPI->second; - for (VarMap::iterator I = TyPlane.begin(), E = TyPlane.end(); I != E; ++I) + ValueMap &TyPlane = TPI->second; + for (value_iterator I = TyPlane.begin(), E = TyPlane.end(); I != E; ++I) if (I->second == (Value*)OldType) { // FIXME when Types aren't const. #if DEBUG_ABSTYPE std::cerr << "Removing type " << OldType->getDescription() << "\n"; @@ -324,21 +378,21 @@ } void SymbolTable::typeBecameConcrete(const DerivedType *AbsTy) { - iterator TPI = find(AbsTy); + type_iterator TPI = map.find(AbsTy); // If there are any values in the symbol table of this type, then the type // plan is a use of the abstract type which must be dropped. - if (TPI != end()) + if (TPI != map.end()) AbsTy->removeAbstractTypeUser(this); - TPI = find(Type::TypeTy); - if (TPI != end()) { + TPI = map.find(Type::TypeTy); + if (TPI != map.end()) { // Loop over all of the types in the symbol table, dropping any abstract // type user entries for AbsTy which occur because there are names for the // type. // - VarMap &TyPlane = TPI->second; - for (VarMap::iterator I = TyPlane.begin(), E = TyPlane.end(); I != E; ++I) + ValueMap &TyPlane = TPI->second; + for (value_iterator I = TyPlane.begin(), E = TyPlane.end(); I != E; ++I) if (I->second == (Value*)AbsTy) // FIXME when Types aren't const. AbsTy->removeAbstractTypeUser(this); } @@ -360,5 +414,7 @@ void SymbolTable::dump() const { std::cout << "Symbol table dump:\n"; - for_each(begin(), end(), DumpPlane); + for_each(map.begin(), map.end(), DumpPlane); } + +// vim: sw=2 ai Index: llvm/lib/VMCore/Verifier.cpp diff -u llvm/lib/VMCore/Verifier.cpp:1.97 llvm/lib/VMCore/Verifier.cpp:1.97.2.1 --- llvm/lib/VMCore/Verifier.cpp:1.97 Tue May 4 16:46:05 2004 +++ llvm/lib/VMCore/Verifier.cpp Wed May 12 11:33:43 2004 @@ -240,20 +240,19 @@ // verifySymbolTable - Verify that a function or module symbol table is ok // void Verifier::verifySymbolTable(SymbolTable &ST) { - // Loop over all of the types in the symbol table... - for (SymbolTable::iterator TI = ST.begin(), TE = ST.end(); TI != TE; ++TI) - for (SymbolTable::type_iterator I = TI->second.begin(), - E = TI->second.end(); I != E; ++I) { - Value *V = I->second; - // Check that there are no void typed values in the symbol table. Values - // with a void type cannot be put into symbol tables because they cannot - // have names! - Assert1(V->getType() != Type::VoidTy, - "Values with void type are not allowed to have names!", V); - } + // Loop over all of the types in the symbol table... + for (SymbolTable::type_const_iterator TI = ST.begin(), TE = ST.end(); TI != TE; ++TI) + for (SymbolTable::value_const_iterator I = TI->second.begin(), + E = TI->second.end(); I != E; ++I) { + Value *V = I->second; + // Check that there are no void typed values in the symbol table. Values + // with a void type cannot be put into symbol tables because they cannot + // have names! + Assert1(V->getType() != Type::VoidTy, + "Values with void type are not allowed to have names!", V); + } } - // visitFunction - Verify that a function is ok. // From llvm at cs.uiuc.edu Wed May 12 11:33:21 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Wed May 12 11:33:21 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/lib/Target/CBackend/Writer.cpp Message-ID: <200405121633.LAA09908@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/CBackend: Writer.cpp updated: 1.174 -> 1.174.2.1 --- Log message: Change SymbolTable to not subclass from std::map but to embed one instead and cleanup use of SymbolTable in rest of LLVM. Also, add some new methods to SymbolTable for small/utility cases and substitute calls to them in LLVM. --- Diffs of the changes: (+4 -4) Index: llvm/lib/Target/CBackend/Writer.cpp diff -u llvm/lib/Target/CBackend/Writer.cpp:1.174 llvm/lib/Target/CBackend/Writer.cpp:1.174.2.1 --- llvm/lib/Target/CBackend/Writer.cpp:1.174 Sun May 9 15:41:32 2004 +++ llvm/lib/Target/CBackend/Writer.cpp Wed May 12 11:33:43 2004 @@ -216,9 +216,9 @@ // SymbolTable &MST = M.getSymbolTable(); if (MST.find(Type::TypeTy) != MST.end()) - for (SymbolTable::type_iterator I = MST.type_begin(Type::TypeTy), + for (SymbolTable::value_iterator I = MST.type_begin(Type::TypeTy), E = MST.type_end(Type::TypeTy); I != E; ) { - SymbolTable::type_iterator It = I++; + SymbolTable::value_iterator It = I++; if (StructType *STy = dyn_cast(It->second)) { // If this is not used, remove it from the symbol table. std::set::iterator UTI = UT.find(STy); @@ -865,8 +865,8 @@ return; // We are only interested in the type plane of the symbol table... - SymbolTable::type_const_iterator I = ST.type_begin(Type::TypeTy); - SymbolTable::type_const_iterator End = ST.type_end(Type::TypeTy); + SymbolTable::value_const_iterator I = ST.type_begin(Type::TypeTy); + SymbolTable::value_const_iterator End = ST.type_end(Type::TypeTy); // Print out forward declarations for structure types before anything else! Out << "/* Structure forward decls */\n"; From llvm at cs.uiuc.edu Wed May 12 11:33:27 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Wed May 12 11:33:27 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/include/llvm/Transforms/MutateStructTypes.h Message-ID: <200405121633.LAA09881@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Transforms: MutateStructTypes.h updated: 1.12 -> 1.12.8.1 --- Log message: Change SymbolTable to not subclass from std::map but to embed one instead and cleanup use of SymbolTable in rest of LLVM. Also, add some new methods to SymbolTable for small/utility cases and substitute calls to them in LLVM. --- Diffs of the changes: (+8 -0) Index: llvm/include/llvm/Transforms/MutateStructTypes.h diff -u llvm/include/llvm/Transforms/MutateStructTypes.h:1.12 llvm/include/llvm/Transforms/MutateStructTypes.h:1.12.8.1 --- llvm/include/llvm/Transforms/MutateStructTypes.h:1.12 Tue Nov 11 16:41:31 2003 +++ llvm/include/llvm/Transforms/MutateStructTypes.h Wed May 12 11:33:43 2004 @@ -111,6 +111,14 @@ // void AdjustIndices(const CompositeType *OldTy, std::vector &Idx, unsigned idx = 0); + + /// A functor for replacement of Types used by processGlobals + struct ProcessGlobalsFunctor { + MutateStructTypes* mst; + Value* MutateStructTypes::ProcessGlobalsFunctor::operator()( + const Type* Ty, const std::string& Name, const Value* Val); + }; + }; } // End llvm namespace From llvm at cs.uiuc.edu Wed May 12 11:33:34 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Wed May 12 11:33:34 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/lib/Transforms/Utils/CloneModule.cpp Linker.cpp Message-ID: <200405121633.LAA09933@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: CloneModule.cpp updated: 1.9 -> 1.9.6.1 Linker.cpp updated: 1.69 -> 1.69.2.1 --- Log message: Change SymbolTable to not subclass from std::map but to embed one instead and cleanup use of SymbolTable in rest of LLVM. Also, add some new methods to SymbolTable for small/utility cases and substitute calls to them in LLVM. --- Diffs of the changes: (+8 -8) Index: llvm/lib/Transforms/Utils/CloneModule.cpp diff -u llvm/lib/Transforms/Utils/CloneModule.cpp:1.9 llvm/lib/Transforms/Utils/CloneModule.cpp:1.9.6.1 --- llvm/lib/Transforms/Utils/CloneModule.cpp:1.9 Fri Jan 9 00:12:15 2004 +++ llvm/lib/Transforms/Utils/CloneModule.cpp Wed May 12 11:33:43 2004 @@ -33,9 +33,9 @@ // Copy all of the type symbol table entries over... const SymbolTable &SymTab = M->getSymbolTable(); - SymbolTable::const_iterator TypeI = SymTab.find(Type::TypeTy); + SymbolTable::type_const_iterator TypeI = SymTab.find(Type::TypeTy); if (TypeI != SymTab.end()) - for (SymbolTable::VarMap::const_iterator I = TypeI->second.begin(), + for (SymbolTable::value_const_iterator I = TypeI->second.begin(), E = TypeI->second.end(); I != E; ++I) New->addTypeName(I->first, cast(I->second)); Index: llvm/lib/Transforms/Utils/Linker.cpp diff -u llvm/lib/Transforms/Utils/Linker.cpp:1.69 llvm/lib/Transforms/Utils/Linker.cpp:1.69.2.1 --- llvm/lib/Transforms/Utils/Linker.cpp:1.69 Tue Mar 30 20:58:28 2004 +++ llvm/lib/Transforms/Utils/Linker.cpp Wed May 12 11:33:43 2004 @@ -172,7 +172,7 @@ const SymbolTable *SrcST = &Src->getSymbolTable(); // Look for a type plane for Type's... - SymbolTable::const_iterator PI = SrcST->find(Type::TypeTy); + SymbolTable::type_const_iterator PI = SrcST->find(Type::TypeTy); if (PI == SrcST->end()) return false; // No named types, do nothing. // Some types cannot be resolved immediately because they depend on other @@ -180,8 +180,8 @@ // are waiting to recheck. std::vector DelayedTypesToResolve; - const SymbolTable::VarMap &VM = PI->second; - for (SymbolTable::type_const_iterator I = VM.begin(), E = VM.end(); + const SymbolTable::ValueMap &VM = PI->second; + for (SymbolTable::value_const_iterator I = VM.begin(), E = VM.end(); I != E; ++I) { const std::string &Name = I->first; Type *RHS = cast(I->second); @@ -383,12 +383,12 @@ // It doesn't exist exactly, scan through all of the type planes in the symbol // table, checking each of them for a type-compatible version. // - for (SymbolTable::iterator I = ST->begin(), E = ST->end(); I != E; ++I) + for (SymbolTable::type_iterator I = ST->begin(), E = ST->end(); I != E; ++I) if (I->first != Type::TypeTy) { - SymbolTable::VarMap &VM = I->second; + SymbolTable::ValueMap &VM = I->second; // Does this type plane contain an entry with the specified name? - SymbolTable::type_iterator TI = VM.find(Name); + SymbolTable::value_iterator TI = VM.find(Name); if (TI != VM.end()) { // // Ensure that this type if placed correctly into the symbol table. From llvm at cs.uiuc.edu Wed May 12 11:33:41 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Wed May 12 11:33:41 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/lib/Transforms/Scalar/SymbolStripping.cpp Message-ID: <200405121633.LAA09924@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: SymbolStripping.cpp updated: 1.25 -> 1.25.6.1 --- Log message: Change SymbolTable to not subclass from std::map but to embed one instead and cleanup use of SymbolTable in rest of LLVM. Also, add some new methods to SymbolTable for small/utility cases and substitute calls to them in LLVM. --- Diffs of the changes: (+1 -26) Index: llvm/lib/Transforms/Scalar/SymbolStripping.cpp diff -u llvm/lib/Transforms/Scalar/SymbolStripping.cpp:1.25 llvm/lib/Transforms/Scalar/SymbolStripping.cpp:1.25.6.1 --- llvm/lib/Transforms/Scalar/SymbolStripping.cpp:1.25 Sat Jan 10 15:36:49 2004 +++ llvm/lib/Transforms/Scalar/SymbolStripping.cpp Wed May 12 11:33:43 2004 @@ -28,32 +28,7 @@ using namespace llvm; static bool StripSymbolTable(SymbolTable &SymTab) { - bool RemovedSymbol = false; - - for (SymbolTable::iterator I = SymTab.begin(); I != SymTab.end();) { - // Removing items from the plane can cause the plane itself to get deleted. - // If this happens, make sure we incremented our plane iterator already! - std::map &Plane = (I++)->second; - - SymbolTable::type_iterator B = Plane.begin(), Bend = Plane.end(); - while (B != Bend) { // Found nonempty type plane! - Value *V = B->second; - - if (isa(V) || isa(V)) { - SymTab.type_remove(B++); - RemovedSymbol = true; - } else { - ++B; - if (!isa(V) || cast(V)->hasInternalLinkage()){ - // Set name to "", removing from symbol table! - V->setName("", &SymTab); - RemovedSymbol = true; - } - } - } - } - - return RemovedSymbol; + return SymTab.strip(); } namespace { From llvm at cs.uiuc.edu Wed May 12 11:33:51 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Wed May 12 11:33:51 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp Message-ID: <200405121633.LAA09901@zion.cs.uiuc.edu> Changes in directory llvm/lib/ExecutionEngine/Interpreter: ExternalFunctions.cpp updated: 1.73 -> 1.73.2.1 --- Log message: Change SymbolTable to not subclass from std::map but to embed one instead and cleanup use of SymbolTable in rest of LLVM. Also, add some new methods to SymbolTable for small/utility cases and substitute calls to them in LLVM. --- Diffs of the changes: (+2 -32) Index: llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp diff -u llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp:1.73 llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp:1.73.2.1 --- llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp:1.73 Sat May 1 01:42:15 2004 +++ llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp Wed May 12 11:33:43 2004 @@ -547,38 +547,8 @@ // change the FILE into the REAL stdio stream. // static FILE *getFILE(void *Ptr) { - static Module *LastMod = 0; - static PointerTy IOBBase = 0; - static unsigned FILESize; - - if (LastMod != &TheInterpreter->getModule()) { // Module change or initialize? - Module *M = LastMod = &TheInterpreter->getModule(); - - // Check to see if the currently loaded module contains an __iob symbol... - GlobalVariable *IOB = 0; - SymbolTable &ST = M->getSymbolTable(); - for (SymbolTable::iterator I = ST.begin(), E = ST.end(); I != E; ++I) { - SymbolTable::VarMap &M = I->second; - for (SymbolTable::VarMap::iterator J = M.begin(), E = M.end(); - J != E; ++J) - if (J->first == "__iob") - if ((IOB = dyn_cast(J->second))) - break; - if (IOB) break; - } - } - - // Check to see if this is a reference to __iob... - if (IOBBase) { - unsigned FDNum = ((unsigned long)Ptr-IOBBase)/FILESize; - if (FDNum == 0) - return stdin; - else if (FDNum == 1) - return stdout; - else if (FDNum == 2) - return stderr; - } - + // Content of this function was excised because it had no effect. + // Probably need to avoid its use . return (FILE*)Ptr; } From llvm at cs.uiuc.edu Wed May 12 11:33:58 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Wed May 12 11:33:58 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/include/llvm/SymbolTable.h Message-ID: <200405121633.LAA09883@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm: SymbolTable.h updated: 1.30 -> 1.30.6.1 --- Log message: Change SymbolTable to not subclass from std::map but to embed one instead and cleanup use of SymbolTable in rest of LLVM. Also, add some new methods to SymbolTable for small/utility cases and substitute calls to them in LLVM. --- Diffs of the changes: (+316 -74) Index: llvm/include/llvm/SymbolTable.h diff -u llvm/include/llvm/SymbolTable.h:1.30 llvm/include/llvm/SymbolTable.h:1.30.6.1 --- llvm/include/llvm/SymbolTable.h:1.30 Wed Dec 31 01:08:19 2003 +++ llvm/include/llvm/SymbolTable.h Wed May 12 11:33:43 2004 @@ -7,16 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file implements a symbol table that has planes broken up by type. -// Identical types may have overlapping symbol names as long as they are -// distinct. -// -// Note that this implements a chained symbol table. If a name being 'lookup'd -// isn't found in the current symbol table, then the parent symbol table is -// searched. -// -// This chaining behavior does NOT affect iterators though: only the lookup -// method. +// This file implements the main symbol table for LLVM. // //===----------------------------------------------------------------------===// @@ -28,112 +19,363 @@ namespace llvm { -class SymbolTable : public AbstractTypeUser, - public std::map > { +/// This class provides a symbol table of name/value pairs that is broken +/// up by type. Each Type* represents a "type plane" in the symbol table. +/// Identical types may have overlapping symbol names as long as they are +/// distinct. Note that this implements a chained symbol table. If a name +/// being looked up (with lookup()) isn't found in the current symbol +/// table, then the parent symbol table is searched. This chaining behavior +/// does NOT affect iterators though: only the lookup method. +/// +/// The SymbolTable provides several utility functions for answering common +/// questions about its contents as well as an iterator interface for +/// directly iterating over the contents. +/// +class SymbolTable : public AbstractTypeUser { + +/// @name Types +/// @{ public: - typedef std::map VarMap; - typedef std::map super; - typedef VarMap::iterator type_iterator; - typedef VarMap::const_iterator type_const_iterator; + /// @brief A mapping of names to values + typedef std::map ValueMap; + + /// @brief A mapping of types to names to values + typedef std::map TypeMap; + + /// @brief An iterator over the TypeMap + typedef TypeMap::iterator type_iterator; + + /// @brief A const_iterator over the TypeMap + typedef TypeMap::const_iterator type_const_iterator; + + /// @brief A iterator over a ValueMap + typedef ValueMap::iterator value_iterator; + + /// @brief A const_iterator over a ValueMap + typedef ValueMap::const_iterator value_const_iterator; + +/// @} +/// @name Constructors +/// @{ +public: inline SymbolTable() : InternallyInconsistent(false), LastUnique(0) {} ~SymbolTable(); - // lookup - Returns null on failure... +/// @} +/// @name Accessors +/// @{ +public: + + /// This method finds the value with the given \p name in the + /// type plane \p Ty and returns it. + /// @returns null on failure, otherwise the Value associated with + /// the \p name in type plane \p Ty. + /// @brief Lookup a named, typed value. Value *lookup(const Type *Ty, const std::string &name) const; - // insert - Add named definition to the symbol table... + /// @brief Determine if there are types in the symbol table + bool hasTypes( void ) const; + + /// @brief Determine if the symbol table is empty + bool isEmpty( void ) const; + + /// The type plane associated with the \p TypeID parameter is + /// found and the number of entries in the plane is returned. + /// @returns Number of entries in the specified type plane. + /// @brief Get the size of a type plane. + inline unsigned type_size(const Type *TypeID) const { + return map.find(TypeID)->second.size(); + } + + /// Finds the value \p val in the symbol table and returns its + /// name. Only the type plane associated with the type of \p val + /// is searched. + /// @brief Return the name of a value + std::string get_name( const Value* val ) const; + + /// Given a base name, return a string that is either equal to it or + /// derived from it that does not already occur in the symbol table + /// for the specified type. + /// @brief Get a name unique to this symbol table + std::string getUniqueName(const Type *Ty, + const std::string &BaseName) const; + + /// @brief Debug method, print out symbol table + void dump() const; + +/// @} +/// @name Mutators +/// @{ +public: + + /// This method adds the provided value \p N to the symbol table. + /// The Value must have both a name and a type which are extracted + /// and used to place the value in the correct type plane under + /// the value's name. + /// @brief Add a named value to the symbol table inline void insert(Value *N) { assert(N->hasName() && "Value must be named to go into symbol table!"); insertEntry(N->getName(), N->getType(), N); } - void remove(Value *N); - Value *type_remove(const type_iterator &It) { - return removeEntry(find(It->second->getType()), It); - } - - // insert - Insert a constant or type into the symbol table with the specified - // name... There can be a many to one mapping between names and - // (constant/type)s. - // + /// Inserts a constant or type into the symbol table with the specified + /// name. There can be a many to one mapping between names and constants + /// or types. + /// @brief Insert a constant or type. inline void insert(const std::string &Name, Value *V) { assert((isa(V) || isa(V)) && - "Can only insert types and constants here!"); + "Can only insert types and constants into a symbol table!"); insertEntry(Name, V->getType(), V); } - /// remove - Remove a constant or type from the symbol table with the - /// specified name. + /// This method removes a named value from the symbol table. The + /// type and name of the Value are extracted from \N and used to + /// lookup the Value in the correct type plane. If the Value is + /// not in the symbol table, this method silently ignores the + /// request. + /// @brief Remove a named value from the symbol table. + void remove(Value *N); + + /// Remove a constant or type with the specified name from the + /// symbol table. + /// @returns the removed Value. + /// @breif Remove a constant or type from the symbol table. Value *remove(const std::string &Name, Value *V) { - iterator TI = find(V->getType()); + TypeMap::iterator TI = map.find(V->getType()); return removeEntry(TI, TI->second.find(Name)); } - // getUniqueName - Given a base name, return a string that is either equal to - // it (or derived from it) that does not already occur in the symbol table for - // the specified type. - // - std::string getUniqueName(const Type *Ty, const std::string &BaseName); + /// @brief Strip the symbol table. This leaves the values without names. + bool strip( void ); - inline unsigned type_size(const Type *TypeID) const { - return find(TypeID)->second.size(); + /// @brief Empty the symbol table completely + void clear( void ) { map.clear(); } + +/// @} +/// @name Iteration +/// @{ +public: + + inline type_iterator begin() { return map.begin(); } + + inline type_const_iterator begin() const { return map.begin(); } + + inline type_iterator end() { return map.end(); } + + inline type_const_iterator end() const { return map.end(); } + + /// Get an iterator that starts at the beginning of a type plane. + /// The iterator will iterate over the name/value pairs in the type plane. + /// @note The type plane must already exist before using this. + inline value_iterator type_begin(const Type *TypeID) { + return map.find(TypeID)->second.begin(); } - // Note that type_begin / type_end only work if you know that an element of - // TypeID is already in the symbol table!!! - // - inline type_iterator type_begin(const Type *TypeID) { - return find(TypeID)->second.begin(); + /// Get a const_iterator that starts at the beginning of a type plane. + /// The iterator will iterate over the name/value pairs in the type plane. + /// @note The type plane must already exist before using this. + inline value_const_iterator type_begin(const Type *TypeID) const { + return map.find(TypeID)->second.begin(); } - inline type_const_iterator type_begin(const Type *TypeID) const { - return find(TypeID)->second.begin(); + + /// Get an iterator to the end of a type plane. This serves as the marker + /// for end of iteration of the type plane. + /// @note The type plane must already exist before using this. + inline value_iterator type_end(const Type *TypeID) { + return map.find(TypeID)->second.end(); } - inline type_iterator type_end(const Type *TypeID) { - return find(TypeID)->second.end(); + /// Get a const_iterator to the end of a type plane. This serves as the + /// marker for end of iteration of the type plane. + /// @note The type plane must already exist before using this. + inline value_const_iterator type_end(const Type *TypeID) const { + return map.find(TypeID)->second.end(); } - inline type_const_iterator type_end(const Type *TypeID) const { - return find(TypeID)->second.end(); + + /// This method returns a type_const_iterator for iteration over + /// the type planes. + /// @brief Find a type plane. + type_const_iterator find(const Type* Ty ) const { + return map.find( Ty ); } - void dump() const; // Debug method, print out symbol table + type_iterator find( const Type* Ty ) { return map.find(Ty); } -private: - // InternallyInconsistent - There are times when the symbol table is - // internally inconsistent with the rest of the program. In this one case, a - // value exists with a Name, and it's not in the symbol table. When we call - // V->setName(""), it tries to remove itself from the symbol table and dies. - // We know this is happening, and so if the flag InternallyInconsistent is - // set, removal from the symbol table is a noop. - // - bool InternallyInconsistent; + /// @brief Find a Type Plane + const ValueMap* findPlane( const Type* Ty ) const { + type_const_iterator I = map.find( Ty ); + if ( I == map.end() ) return 0; + return &I->second; + } - // LastUnique - This value is used to retain the last unique value used - // by getUniqueName to generate unique names. - unsigned long LastUnique; - - inline super::value_type operator[](const Type *Ty) { - assert(0 && "Should not use this operator to access symbol table!"); - return super::value_type(); + /// @returns the removed value. + /// @brief Remove a specific value given by an iterator + Value *type_remove(const value_iterator &It) { + return this->removeEntry(map.find(It->second->getType()), It); } - // insertEntry - Insert a value into the symbol table with the specified - // name... - // +/// @} +/// @name Applicators +/// @{ +public: + /// This function calls the functor doIt for each type in the Symbol + /// Table. The arguments to the functor are the name and type. + /// @brief Apply a functor to the types in the Symbol Table. + // template + // void applyToTypes(FUNCTOR& doIt) const; + + /// This function calls the functor doIt for each type in the Symbol + /// Table that has the specified name. If the functor returns true, + /// the search stops. + //template + //void findTypeNamed( FUNCTOR& doIt, const std::string& Name) const; + + /// This function calls the functor doIt for each value in the Symbol + /// Table. The arguments to the functor are the type, name and value. + //template + //void apply( FUNCTOR& doIt ) const; + + /// This function removes any Types for which the functor \p decide + /// returns true. + /// @returns the number of types removed + //template + //unsigned removeMatchingTypes( FUNCTOR& decide ); + + /// This function replaces the named value of each entry in the + /// Type plane with value provided by the replace functor. The functor + /// should return the new Value* or null if no replacement should be + /// made. + /// @returns the number of replacements made. + //template + //unsigned replaceTypes( FUNCTOR& replace ); + +/// @} +/// @name Internal Methods +/// @{ +private: + /// Insert a value into the symbol table with the specified name. void insertEntry(const std::string &Name, const Type *Ty, Value *V); - // removeEntry - Remove a value from the symbol table... - // - Value *removeEntry(iterator Plane, type_iterator Entry); + /// Remove a value from the symbol table... + Value *removeEntry(TypeMap::iterator Plane, value_iterator Entry); - // This function is called when one of the types in the type plane are refined + /// This function is called when one of the types in the type plane + /// is refined. virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); + + /// This function markes a type as being concrete (defined). virtual void typeBecameConcrete(const DerivedType *AbsTy); + +/// @} +/// @name Internal Data +/// @{ +private: + + /// This is the main content of the symbol table. It provides + /// separate type planes for named values. That is, each named + /// value is organized into a separate dictionary based on + /// Type. This means that the same name can be used for different + /// types without conflict. + /// @brief The mapping of types to names to values. + TypeMap map; + + /// There are times when the symbol table is internally inconsistent with + /// the rest of the program. In this one case, a value exists with a Name, + /// and it's not in the symbol table. When we call V->setName(""), it + /// tries to remove itself from the symbol table and dies. We know this + /// is happening, and so if the flag InternallyInconsistent is set, + /// removal from the symbol table is a noop. + /// @brief Indicator of symbol table internal inconsistency. + bool InternallyInconsistent; + + /// This value is used to retain the last unique value used + /// by getUniqueName to generate unique names. + mutable unsigned long LastUnique; + +/// @} + }; +/* +template +void SymbolTable::applyToTypes( FUNCTOR& doIt ) const { + type_const_iterator TI = map.find(Type::TypeTy); + if (TI != map.end()) { + value_const_iterator VI = TI->second.begin(); + for (; VI != TI->second.end(); ++VI) { + doIt( Type::TypeTy, VI->first, VI->second ); + } + } +} + +template +void SymbolTable::findTypeNamed( FUNCTOR& decide, + const std::string& Name ) const { + type_const_iterator TI = map.begin(); + type_const_iterator TE = map.end(); + for ( ; TI != TE; ++TI ) { + if (TI->first != Type::TypeTy) { + const ValueMap& VM = TI->second; + // Does this type plane contain an entry with the specified name? + value_const_iterator VI = VM.find(Name); + if (VI != VM.end()) { + if ( decide( TI->first, VI->first, VI->second ) ) break; + } + } + } +} + +template +void SymbolTable::apply( FUNCTOR& doIt ) const { + for (type_const_iterator TI = map.begin(), TE = map.end(); + TI != TE; ++TI) { + for (value_const_iterator VI = TI->second.begin(), + VE = TI->second.end(); VI != VE; ++VI) { + doIt( TI->first, VI->first, VI->second ); + } + } +} + +template +unsigned SymbolTable::removeMatchingTypes( FUNCTOR& decide ) { + unsigned result = 0; + type_iterator PI = map.find(Type::TypeTy); + if (PI != map.end()) { + ValueMap& Plane = PI->second; + for (value_iterator I=Plane.begin(); I != Plane.end(); ++I) { + if ( decide( PI->first, I->first, I->second ) ) + { + Plane.erase( I++ ); + result++; + } + } + } + return result; +} + +template +unsigned SymbolTable::replaceTypes( FUNCTOR& replace ) { + unsigned result = 0; + type_iterator PI = map.find(Type::TypeTy); + if (PI != map.end()) { + ValueMap& Plane = PI->second; + for (value_iterator I=Plane.begin(), PE=Plane.end(); I != PE; ++I) { + Value* v = replace( PI->first, I->first, I->second ); + if ( v ) { + I->second = v; + result++; + result++; + } + } + } + return result; +} +*/ + } // End llvm namespace #endif + +// vim: sw=2 From llvm at cs.uiuc.edu Wed May 12 11:34:04 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Wed May 12 11:34:04 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/lib/Bytecode/Writer/Writer.cpp WriterInternals.h Message-ID: <200405121633.LAA09889@zion.cs.uiuc.edu> Changes in directory llvm/lib/Bytecode/Writer: Writer.cpp updated: 1.62 -> 1.62.2.1 WriterInternals.h updated: 1.20 -> 1.20.6.1 --- Log message: Change SymbolTable to not subclass from std::map but to embed one instead and cleanup use of SymbolTable in rest of LLVM. Also, add some new methods to SymbolTable for small/utility cases and substitute calls to them in LLVM. --- Diffs of the changes: (+11 -3) Index: llvm/lib/Bytecode/Writer/Writer.cpp diff -u llvm/lib/Bytecode/Writer/Writer.cpp:1.62 llvm/lib/Bytecode/Writer/Writer.cpp:1.62.2.1 --- llvm/lib/Bytecode/Writer/Writer.cpp:1.62 Sun Apr 4 20:27:26 2004 +++ llvm/lib/Bytecode/Writer/Writer.cpp Wed May 12 11:33:43 2004 @@ -312,9 +312,9 @@ BytecodeBlock SymTabBlock(BytecodeFormat::SymbolTable, Out, true/* ElideIfEmpty*/); - for (SymbolTable::const_iterator TI = MST.begin(); TI != MST.end(); ++TI) { - SymbolTable::type_const_iterator I = MST.type_begin(TI->first); - SymbolTable::type_const_iterator End = MST.type_end(TI->first); + for (SymbolTable::type_const_iterator TI = MST.begin(); TI != MST.end(); ++TI) { + SymbolTable::value_const_iterator I = MST.type_begin(TI->first); + SymbolTable::value_const_iterator End = MST.type_end(TI->first); int Slot; if (I == End) continue; // Don't mess with an absent type... Index: llvm/lib/Bytecode/Writer/WriterInternals.h diff -u llvm/lib/Bytecode/Writer/WriterInternals.h:1.20 llvm/lib/Bytecode/Writer/WriterInternals.h:1.20.6.1 --- llvm/lib/Bytecode/Writer/WriterInternals.h:1.20 Tue Jan 20 13:50:34 2004 +++ llvm/lib/Bytecode/Writer/WriterInternals.h Wed May 12 11:33:43 2004 @@ -50,6 +50,14 @@ unsigned StartNo); void outputConstant(const Constant *CPV); void outputType(const Type *T); + + struct OutputSymbolTableFunctor { + const SymbolTable* MST; + BytecodeWriter* bw; + int Slot; + const Type* LastType; + void operator() ( const Type* Ty, const std::string& Name, const Value* V ); + }; }; From llvm at cs.uiuc.edu Wed May 12 11:34:10 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Wed May 12 11:34:10 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/include/llvm/Analysis/SlotCalculator.h Message-ID: <200405121633.LAA09879@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: SlotCalculator.h updated: 1.18 -> 1.18.6.1 --- Log message: Change SymbolTable to not subclass from std::map but to embed one instead and cleanup use of SymbolTable in rest of LLVM. Also, add some new methods to SymbolTable for small/utility cases and substitute calls to them in LLVM. --- Diffs of the changes: (+17 -0) Index: llvm/include/llvm/Analysis/SlotCalculator.h diff -u llvm/include/llvm/Analysis/SlotCalculator.h:1.18 llvm/include/llvm/Analysis/SlotCalculator.h:1.18.6.1 --- llvm/include/llvm/Analysis/SlotCalculator.h:1.18 Tue Jan 20 13:50:12 2004 +++ llvm/include/llvm/Analysis/SlotCalculator.h Wed May 12 11:33:43 2004 @@ -26,6 +26,7 @@ namespace llvm { class Value; +class Type; class Module; class Function; class SymbolTable; @@ -140,6 +141,22 @@ void buildCompactionTable(const Function *F); unsigned getOrCreateCompactionTableSlot(const Value *V); void pruneCompactionTable(); + + struct ProcessSymbolTableFunctor { + inline void operator() ( + const Type*Ty, const std::string& name, const Value* V ); + SlotCalculator* sc; + }; + struct ProcessSymbolTableConstantsFunctor { + inline void operator() ( + const Type*Ty, const std::string& name, const Value* V ); + SlotCalculator* sc; + }; + struct CompactionTableFunctor { + inline void operator() ( + const Type*Ty, const std::string& name,const Value* V ); + SlotCalculator* sc; + }; }; } // End llvm namespace From lattner at cs.uiuc.edu Wed May 12 11:35:06 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 12 11:35:06 2004 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Message-ID: <200405121635.LAA10219@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.250 -> 1.251 --- Log message: Pass boolean constants into function calls more efficiently, generating: mov DWORD PTR [%ESP + 4], 1 instead of: mov %EAX, 1 mov DWORD PTR [%ESP + 4], %EAX --- Diffs of the changes: (+7 -1) Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.250 llvm/lib/Target/X86/InstSelectSimple.cpp:1.251 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.250 Mon May 10 10:15:55 2004 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Wed May 12 11:35:04 2004 @@ -1207,7 +1207,7 @@ // copy. if (ConstantInt *CI = dyn_cast(Val)) { int TheVal = CI->getRawValue() & 0xFFFFFFFF; - BuildMI(BB, X86::MOV32ri, 1, targetReg).addImm(TheVal); + BuildMI(BB, X86::MOV32ri, 1, targetReg).addImm(TheVal); return; } } @@ -1405,6 +1405,12 @@ unsigned ArgReg; switch (getClassB(Args[i].Ty)) { case cByte: + if (Args[i].Val && isa(Args[i].Val)) { + addRegOffset(BuildMI(BB, X86::MOV32mi, 5), X86::ESP, ArgOffset) + .addImm(Args[i].Val == ConstantBool::True); + break; + } + // FALL THROUGH case cShort: if (Args[i].Val && isa(Args[i].Val)) { // Zero/Sign extend constant, then stuff into memory. From brukman at cs.uiuc.edu Wed May 12 13:01:02 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 12 13:01:02 2004 Subject: [llvm-commits] CVS: llvm/docs/index.html Message-ID: <200405121800.NAA15061@zion.cs.uiuc.edu> Changes in directory llvm/docs: index.html updated: 1.11 -> 1.12 --- Log message: * Make the document format follow the stringent purple standards (like the rest of the documentation) * Do not make the link text be the link itself, use some keywords * Make doc use stylesheets and HTML markup for lists instead of definitions * Shorten page by not making multiple lines per link with description + link of the same name as the target --- Diffs of the changes: (+165 -268) Index: llvm/docs/index.html diff -u llvm/docs/index.html:1.11 llvm/docs/index.html:1.12 --- llvm/docs/index.html:1.11 Mon Apr 5 23:22:43 2004 +++ llvm/docs/index.html Wed May 12 13:00:48 2004 @@ -1,288 +1,185 @@ + - The LLVM Compiler Infrastructure + The LLVM Compiler Infrastructure documentation + -
      -

      - The LLVM Compiler Infrastructure -
      - http://llvm.cs.uiuc.edu -

      -
      +
      The LLVM Compiler Infrastructure Documentation
      -
      + + + + + + + + + + + + +
      +
        + +
      • If you have questions or development problems not answered in the +documentation, send e-mail to LLVM-dev. This +mailing list is monitored by all the people in the LLVM group at Illinois, and +you should expect prompt first responses.
      • + +
      • Please read How +to submit a bug for tips on how to track down bugs to their correct +originating component -- sometimes, it's a bug in external software and not in +LLVM, or for help with debugging your own LLVM passes and extensions.
      • + +
      • We now use Bugzilla to +track bugs, so you can submit bugs and check their progress in real-time.
      • + +
      + +
      + + + + + +
      + +

      All the documents mentioned below except the design overview tech report +are included as part of the LLVM release (in llvm/docs/*):

      + +
      + + +
      LLVM Design Overview
      + + + + +
      + LLVM User Guides +
      + + + + +
      LLVM Programming Documentation
      + +
      + +
      + + +
      Other LLVM Resources
      + + + + + + + +
      -

      Welcome to LLVM!

      +

      There are three mailing lists for providing LLVM users with information:

      -This file is intended to do four things:
        -
      1. help you get started using LLVM;
      2. -
      3. tell you how to get questions about LLVM answered;
      4. +
      5. LLVM +Announcements List -
      6. tell you where to find documentation for different kinds of questions; - and
      7. +

        This is a low volume list that provides important announcements regarding +LLVM. It is primarily intended to announce new releases, major updates to the +software, etc. This list is highly recommended for anyone that uses +LLVM.

        + +
      8. LLVM Developers +List + +

        This list is for people who want to be included in technical discussions of +LLVM. People post to this list when they have questions about writing code for +or using the LLVM tools. It is relatively low volume.

      9. + +
      10. LLVM Commits +List + +

        This list contains all commit messages that are made when LLVM developers +commit code changes to the CVS archive. It is useful for those who want to +stay on the bleeding edge of LLVM development. This list is very high +volume.

      11. -
      12. tell you about three LLVM-related mailing lists.
      +
      -
      - -

      -Getting Started with LLVM -

      - -
      -
      - For license information: -
      - llvm/LICENSE.TXT -

      - -

      - Installing and compiling LLVM: -
      - llvm/docs/GettingStarted.html -

      - -

      - Learn about features and limitations of this release: -
      - llvm/docs/ReleaseNotes.html -

      - -

      - Learn how to write a pass within the LLVM system: -
      - llvm/docs/WritingAnLLVMPass.html -

      - -

      - Learn how to start a new development project using LLVM, where your - new source code can live anywhere (outside or inside the LLVM tree), - while using LLVM header files and libraries: -
      - llvm/docs/Projects.html -
      - -
      - -

      -Getting Help with LLVM -

      - -
        -
      1. - If you have questions or development problems not answered in the - documentation, send e-mail to llvmdev at cs.uiuc.edu. This mailing list is - monitored by all the people in the LLVM group at Illinois, and you - should expect prompt first responses. -
      2. - -
      3. - To report a bug, submit a bug report as described in the document: - - http://llvm.cs.uiuc.edu/docs/HowToSubmitABug.html -
      4. - -
      5. - We now use Bugzilla to track bugs, so you can check the status of - previous bugs at: - - http://llvm.cs.uiuc.edu/bugs/query.cgi -
      6. -
      +
      - -

      -LLVM Documentation -

      - -All the documents mentioned below except the design overview tech report -are included as part of the LLVM release (in llvm/docs/*): - -

      -LLVM Design Overview: -

      - -
      -
      - LLVM: A Compilation Framework for Lifelong Program Analysis - & Transformation -
      - - http://llvm.cs.uiuc.edu/pubs/2004-01-30-CGO-LLVM.html - -
      - -

      -LLVM User Guides: -

      - -
      -
      - Download and Installation Instructions: -
      - llvm/docs/GettingStarted.html -

      - -

      - LLVM Command Guide: -
      - - llvm/docs/CommandGuide/index.html -

      - -

      - LLVM Assembly Language: -
      - llvm/docs/LangRef.html -

      - -

      - LLVM Test Suite Guide: -
      - llvm/docs/TestingGuide.html -

      -

      - -

      -LLVM Programming Documentation: -

      - -
      -
      - LLVM Programmers Manual: -
      - llvm/docs/ProgrammersManual.html -

      - -

      - Writing an LLVM Pass: -
      - llvm/docs/WritingAnLLVMPass.html -

      - -

      - Alias Analysis in LLVM: -
      - llvm/docs/AliasAnalysis.html -

      - -

      - Source Level Debugging with LLVM: -
      - llvm/docs/SourceLevelDebugging.html -

      - - -

      - TableGen Fundamentals: -
      - llvm/docs/TableGenFundamentals.html -

      - - -

      - The Stacker Cronicles -
      - The Stacker Cronicles - - This document describes both the Stacker language and - LLVM frontend, but also some details about LLVM useful for - those writing front-ends.

      - - -

      - Command Line Library: -
      - llvm/docs/CommandLine.html -

      - -

      - Extending LLVM: -
      - llvm/docs/ExtendingLLVM.html -

      - -

      - Coding Standards: -
      - llvm/docs/CodingStandards.html -

      -

      - -

      Other LLVM Resources

      - -
      -
      - Building the LLVM C/C++ front-end: -
      - llvm/docs/CFEBuildInstrs.html -

      -

      - Submitting a Bug: -
      - - http://llvm.cs.uiuc.edu/docs/HowToSubmitABug.html -

      - -

      - Open Projects: -
      - llvm/docs/OpenProjects.html -

      - -

      - Creating a new LLVM Project: -
      - llvm/docs/Projects.html -

      -

      - -
      - -

      Mailing Lists

      - -There are three mailing lists for providing LLVM users with information: - -
        -
      1. LLVM Announcements List:
        - - http://mail.cs.uiuc.edu/mailman/listinfo/llvm-announce - -

        - This is a low volume list that provides important announcements regarding - LLVM. It is primarily intended to announce new releases, major updates to - the software, etc. This list is highly recommended for anyone that uses - LLVM. -

        - -
      2. LLVM Developers List:
        - - http://mail.cs.uiuc.edu/mailman/listinfo/llvmdev - -

        - This list is for people who want to be included in technical discussions - of LLVM. People post to this list when they have questions about writing - code for or using the LLVM tools. It is relatively low volume. -

        - -
      3. LLVM Commits List
        - - http://mail.cs.uiuc.edu/mailman/listinfo/llvm-commits - -

        - This list contains all commit messages that are made when LLVM developers - commit code changes to the CVS archive. It is useful for those who want to - stay on the bleeding edge of LLVM development. This list is very high - volume. -

        -
      +
      + Valid CSS! + Valid HTML 4.01! + + John Criswell
      + LLVM Compiler Infrastructure
      + Last modified: $Date: 2004/05/12 18:00:48 $ +
      - From brukman at cs.uiuc.edu Wed May 12 13:02:05 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 12 13:02:05 2004 Subject: [llvm-commits] CVS: llvm/docs/AliasAnalysis.html Message-ID: <200405121802.NAA30733@zion.cs.uiuc.edu> Changes in directory llvm/docs: AliasAnalysis.html updated: 1.17 -> 1.18 --- Log message: Fix grammar: remove `the' before LLVM. --- Diffs of the changes: (+3 -3) Index: llvm/docs/AliasAnalysis.html diff -u llvm/docs/AliasAnalysis.html:1.17 llvm/docs/AliasAnalysis.html:1.18 --- llvm/docs/AliasAnalysis.html:1.17 Thu Jan 15 13:04:12 2004 +++ llvm/docs/AliasAnalysis.html Wed May 12 13:02:00 2004 @@ -509,11 +509,11 @@ Valid CSS! Valid HTML 4.01! + src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01!"> Chris Lattner
      - The LLVM Compiler Infrastructure
      - Last modified: $Date: 2004/01/15 19:04:12 $ + LLVM Compiler Infrastructure
      + Last modified: $Date: 2004/05/12 18:02:00 $ From gaeke at cs.uiuc.edu Wed May 12 13:25:02 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Wed May 12 13:25:02 2004 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/Makefile Message-ID: <200405121825.NAA08514@zion.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: Makefile updated: 1.6 -> 1.7 --- Log message: Trace.cpp is gone --- Diffs of the changes: (+1 -1) Index: reopt/lib/LightWtProfiling/Makefile diff -u reopt/lib/LightWtProfiling/Makefile:1.6 reopt/lib/LightWtProfiling/Makefile:1.7 --- reopt/lib/LightWtProfiling/Makefile:1.6 Thu May 6 16:47:49 2004 +++ reopt/lib/LightWtProfiling/Makefile Wed May 12 13:25:28 2004 @@ -5,7 +5,7 @@ include $(LEVEL)/Makefile.config ifneq ($(ARCH),Sparc) -Source := Initialization.cpp RuntimeOptimizations.cpp SLI.cpp Trace.cpp TraceOptEmitter.cpp TraceToFunction.cpp UnpackTraceFunction.cpp +Source := Initialization.cpp RuntimeOptimizations.cpp SLI.cpp TraceOptEmitter.cpp TraceToFunction.cpp UnpackTraceFunction.cpp all :: @echo "This code assumes an LP64 machine- please ignore ptr cast warnings!" endif From brukman at cs.uiuc.edu Wed May 12 13:31:02 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 12 13:31:02 2004 Subject: [llvm-commits] CVS: llvm/docs/TableGenFundamentals.html Message-ID: <200405121831.NAA12848@zion.cs.uiuc.edu> Changes in directory llvm/docs: TableGenFundamentals.html updated: 1.4 -> 1.5 --- Log message: Make document HTML-4.01 (Strict) compliant. --- Diffs of the changes: (+182 -263) Index: llvm/docs/TableGenFundamentals.html diff -u llvm/docs/TableGenFundamentals.html:1.4 llvm/docs/TableGenFundamentals.html:1.5 --- llvm/docs/TableGenFundamentals.html:1.4 Thu Feb 12 12:11:53 2004 +++ llvm/docs/TableGenFundamentals.html Wed May 12 13:31:21 2004 @@ -9,42 +9,44 @@
      TableGen Fundamentals
      + @@ -62,72 +64,56 @@

      The core part of TableGen parses a file, instantiates the declarations, and hands the result off to a domain-specific "TableGen backend" for processing. The current major user -of TableGen is the LLVM code generator. -

      +of TableGen is the LLVM code generator.

      -

      -Note that if you work on TableGen much, and use emacs or vim, that you can find -an emacs "TableGen mode" and a vim language file in llvm/utils/emacs -and llvm/utils/vim directory of your LLVM distribution, respectively. -

      +

      Note that if you work on TableGen much, and use emacs or vim, that you can +find an emacs "TableGen mode" and a vim language file in +llvm/utils/emacs and llvm/utils/vim directory of your LLVM +distribution, respectively.

    - +
    -

    -TableGen files consist of two key parts: 'classes' and 'definitions', both of -which are considered 'records'. -

    +

    TableGen files consist of two key parts: 'classes' and 'definitions', both +of which are considered 'records'.

    -

    -TableGen records have a unique name, a list of values, and a list of +

    TableGen records have a unique name, a list of values, and a list of superclasses. The list of values is main data that TableGen builds for each record, it is this that holds the domain specific information for the application. The interpretation of this data is left to a specific TableGen backend, but the structure and format rules are -taken care of and fixed by TableGen. -

    +taken care of and fixed by TableGen.

    -

    -TableGen definitions are the concrete form of 'records'. These generally -do not have any undefined values, and are marked with the 'def' -keyword. -

    - -

    -TableGen classes are abstract records that are used to build and describe -other records. These 'classes' allow the end-user to build abstractions for -either the domain they are targetting (such as "Register", "RegisterClass", and -"Instruction" in the LLVM code generator) or for the implementor to help factor -out common properties of records (such as "FPInst", which is used to represent -floating point instructions in the X86 backend). TableGen keeps track of all of -the classes that are used to build up a definition, so the backend can find all -definitions of a particular class, such as "Instruction". -

    +

    TableGen definitions are the concrete form of 'records'. These +generally do not have any undefined values, and are marked with the +'def' keyword.

    + +

    TableGen classes are abstract records that are used to build and +describe other records. These 'classes' allow the end-user to build +abstractions for either the domain they are targetting (such as "Register", +"RegisterClass", and "Instruction" in the LLVM code generator) or for the +implementor to help factor out common properties of records (such as "FPInst", +which is used to represent floating point instructions in the X86 backend). +TableGen keeps track of all of the classes that are used to build up a +definition, so the backend can find all definitions of a particular class, such +as "Instruction".

    - +
    -

    -With no other arguments, TableGen parses the specified file and prints out all -of the classes, then all of the definitions. This is a good way to see what the -various definitions expand to fully. Running this on the X86.td file -prints this (at the time of this writing): -

    +

    With no other arguments, TableGen parses the specified file and prints out +all of the classes, then all of the definitions. This is a good way to see what +the various definitions expand to fully. Running this on the X86.td +file prints this (at the time of this writing):

    -

     ...
     def ADDrr8 {    // Instruction X86Inst I2A8 Pattern
    @@ -153,64 +139,53 @@
       bits<3> FPFormBits = { 0, 0, 0 };
     }
     ...
    -

    + -

    -This definition corresponds to an 8-bit register-register add instruction in the -X86. The string after the 'def' string indicates the name of the +

    This definition corresponds to an 8-bit register-register add instruction in +the X86. The string after the 'def' string indicates the name of the record ("ADDrr8" in this case), and the comment at the end of the line indicates the superclasses of the definition. The body of the record contains all of the data that TableGen assembled for the record, indicating that the instruction is part of the "X86" namespace, should be printed as "add" in the assembly file, it is a two-address instruction, has a particular encoding, etc. The contents and semantics of the information in the record is -specific to the needs of the X86 backend, and is only shown as an example. -

    +specific to the needs of the X86 backend, and is only shown as an example.

    -

    -As you can see, a lot of information is needed for every instruction supported -by the code generator, and specifying it all manually would be unmaintainble, -prone to bugs, and tiring to do in the first place. Because we are using -TableGen, all of the information was derived from the following definition: -

    +

    As you can see, a lot of information is needed for every instruction +supported by the code generator, and specifying it all manually would be +unmaintainble, prone to bugs, and tiring to do in the first place. Because we +are using TableGen, all of the information was derived from the following +definition:

    -

    +
     def ADDrr8   : I2A8<"add", 0x00, MRMDestReg>,
                    Pattern<(set R8, (plus R8, R8))>;
    -

    +
    -

    -This definition makes use of the custom I2A8 (two address instruction with 8-bit -operand) class, which is defined in the X86-specific TableGen file to factor out -the common features that instructions of its class share. A key feature of -TableGen is that it allows the end-user to define the abstractions they prefer -to use when describing their information. -

    +

    This definition makes use of the custom I2A8 (two address instruction with +8-bit operand) class, which is defined in the X86-specific TableGen file to +factor out the common features that instructions of its class share. A key +feature of TableGen is that it allows the end-user to define the abstractions +they prefer to use when describing their information.

    - +
    -

    -TableGen runs just like any other LLVM tool. The first (optional) argument +

    TableGen runs just like any other LLVM tool. The first (optional) argument specifies the file to read. If a filename is not specified, tblgen -reads from standard input. -

    +reads from standard input.

    -

    -To be useful, one of the TableGen backends must be used. -These backends are selectable on the command line (type 'tblgen --help' -for a list). For example, to get a list of all of the definitions that subclass -a particular type (which can be useful for building up an enum list of these -records), use the --print-enums option: -

    +

    To be useful, one of the TableGen backends must be +used. These backends are selectable on the command line (type 'tblgen +--help' for a list). For example, to get a list of all of the definitions +that subclass a particular type (which can be useful for building up an enum +list of these records), use the --print-enums option:

    -

    +
     $ tblgen X86.td -print-enums -class=Register
     AH, AL, AX, BH, BL, BP, BX, CH, CL, CX, DH, DI, DL, DX,
     EAX, EBP, EBX, ECX, EDI, EDX, ESI, ESP, FP0, FP1, FP2, FP3, FP4, FP5, FP6,
    @@ -220,18 +195,14 @@
     ADCrr32, ADDri16, ADDri16b, ADDri32, ADDri32b, ADDri8, ADDrr16, ADDrr32,
     ADDrr8, ADJCALLSTACKDOWN, ADJCALLSTACKUP, ANDri16, ANDri16b, ANDri32, ANDri32b,
     ANDri8, ANDrr16, ANDrr32, ANDrr8, BSWAPr32, CALLm32, CALLpcrel32, ...
    -

    +
    -

    -The default backend prints out all of the records, as described above. -

    +

    The default backend prints out all of the records, as described above.

    -

    -If you plan to use TableGen for some purpose, you will most likely have to write a backend that extracts the information specific to -what you need and formats it in the appropriate way. -

    +

    If you plan to use TableGen for some purpose, you will most likely have to +write a backend that extracts the information specific +to what you need and formats it in the appropriate way.

    @@ -241,54 +212,39 @@
    - -

    -TableGen doesn't care about the meaning of data (that is up to the backend to -define), but it does care about syntax, and it enforces a simple type system. +

    TableGen doesn't care about the meaning of data (that is up to the backend +to define), but it does care about syntax, and it enforces a simple type system. This section describes the syntax and the constructs allowed in a TableGen file.

    -
    -
    + - - + +
    -

    TableGen supports BCPL style "//" comments, which run to the end of the line, and it also supports nestable "/* */" comments.

    -
    - - -
    - The TableGen type system + +
    -

    -TableGen files are strongly typed, in a simple (but complete) type-system. +

    TableGen files are strongly typed, in a simple (but complete) type-system. These types are used to perform automatic conversions, check for errors, and to help interface designers constrain the input that they allow. Every value definition is required to have an associated type.

    -

    -TableGen supports a mixture of very low-level types (such as bit) and -very high-level types (such as dag). This flexibility is what allows -it to describe a wide range of information conveniently and compactly. The -TableGen types are: -

    +

    TableGen supports a mixture of very low-level types (such as bit) +and very high-level types (such as dag). This flexibility is what +allows it to describe a wide range of information conveniently and compactly. +The TableGen types are:

    -

    • "bit" - A 'bit' is a boolean value that can hold either 0 or 1.
    • @@ -319,29 +275,25 @@
    • "dag" - This type represents a nestable directed graph of elements.
    -

    -

    -To date, these types have been sufficient for describing things that TableGen -has been used for, but it is straight-forward to extend this list if needed. -

    +

    To date, these types have been sufficient for describing things that +TableGen has been used for, but it is straight-forward to extend this list if +needed.

    - +
    -

    -TableGen allows for a pretty reasonable number of different expression forms +

    TableGen allows for a pretty reasonable number of different expression forms when building up values. These forms allow the TableGen file to be written in a natural syntax and flavor for the application. The current expression forms -supported include: -

    +supported include:

    -

      +
      • ? - Uninitialized field.
      • 0b1001011 - Binary integer value.
      • 07654321 - Octal integer value (indicated by a leading 0).
      • @@ -360,27 +312,20 @@ definition, the remaining elements in the list may be arbitrary other values, including nested 'dag' values. -

      +
    -

    -Note that all of the values have rules specifying how they convert to values +

    Note that all of the values have rules specifying how they convert to values for different types. These rules allow you to assign a value like "7" to a -"bits<4>" value, for example. -

    - - +"bits<4>" value, for example.

    - -
    - Classes and definitions +
    -

    -As mentioned in the intro, classes and definitions +

    As mentioned in the intro, classes and definitions (collectively known as 'records') in TableGen are the main high-level unit of information that TableGen collects. Records are defined with a def or class keyword, the record name, and an optional list of "value definitions or let expressions are needed for the class, they are enclosed in curly braces ("{}"); otherwise, the record ends with a semicolon. Here is a simple TableGen -file: -

    +file:

    -

    +
     class C { bit V = 1; }
     def X : C;
     def Y : C {
       string Greeting = "hello";
     }
    -

    +
    -

    -This example defines two definitions, X and Y, both of which -derive from the C class. Because of this, they both get the V -bit value. The Y definition also gets the Greeting member as well. -

    +

    This example defines two definitions, X and Y, both of +which derive from the C class. Because of this, they both get the +V bit value. The Y definition also gets the Greeting member +as well.

    -

    -In general, classes are useful for collecting together the commonality between a -group of records and isolating it in a single place. Also, classes permit the -specification of default values for their subclasses, allowing the subclasses to -override them as they wish. -

    +

    In general, classes are useful for collecting together the commonality +between a group of records and isolating it in a single place. Also, classes +permit the specification of default values for their subclasses, allowing the +subclasses to override them as they wish.

    - +
    -

    -Value definitions define named entries in records. A value must be defined +

    Value definitions define named entries in records. A value must be defined before it can be referred to as the operand for another value definition or before the value is reset with a let expression. A value is defined by specifying a TableGen type and a name. If an initial value is available, it may be specified after the type with an -equal sign. Value definitions require terminating semicolons. +equal sign. Value definitions require terminating semicolons.

    - +
    -

    -A record-level let expression is used to change the value of a value definition -in a record. This is primarily useful when a superclass defines a value that a -derived class or definition wants to override. Let expressions consist of the -'let' keyword followed by a value name, an equal sign ("="), and a new -value. For example, a new class could be added to the example above, redefining -the V field for all of its subclasses:

    +

    A record-level let expression is used to change the value of a value +definition in a record. This is primarily useful when a superclass defines a +value that a derived class or definition wants to override. Let expressions +consist of the 'let' keyword followed by a value name, an equal sign +("="), and a new value. For example, a new class could be added to the example +above, redefining the V field for all of its subclasses:

    -

    +
     class D : C { let V = 0; }
     def Z : D;
    -

    +
    -

    -In this case, the Z definition will have a zero value for its "V" +

    In this case, the Z definition will have a zero value for its "V" value, despite the fact that it derives (indirectly) from the C class, -because the D class overrode its value. -

    +because the D class overrode its value.

    - +
    -

    -TableGen permits the definition of parameterized classes as well as normal +

    TableGen permits the definition of parameterized classes as well as normal concrete classes. Parameterized TableGen classes specify a list of variable bindings (which may optionally have defaults) that are bound when used. Here is a simple example:

    -

    +
     class FPFormat<bits<3> val> {
       bits<3> Value = val;
     }
    @@ -479,17 +415,16 @@
     def OneArgFPRW : FPFormat<3>;
     def TwoArgFP   : FPFormat<4>;
     def SpecialFP  : FPFormat<5>;
    -

    +
    -

    -In this case, template arguments are used as a space efficient way to specify a -list of "enumeration values", each with a "Value" field set to the specified +

    In this case, template arguments are used as a space efficient way to specify +a list of "enumeration values", each with a "Value" field set to the specified integer.

    The more esoteric forms of TableGen expressions are useful in conjunction with template arguments. As an example:

    -

    +
     class ModRefVal<bits<2> val> {
       bits<2> Value = val;
     }
    @@ -512,15 +447,14 @@
     def bork : Value<Mod>;
     def zork : Value<Ref>;
     def hork : Value<ModRef>;
    -

    +
    -

    -This is obviously a contrived example, but it shows how template arguments can -be used to decouple the interface provided to the user of the class from the +

    This is obviously a contrived example, but it shows how template arguments +can be used to decouple the interface provided to the user of the class from the actual internal data representation expected by the class. In this case, running tblgen on the example prints the following definitions:

    -

    +
     def bork {      // Value
       bit isMod = 1;
       bit isRef = 0;
    @@ -533,61 +467,54 @@
       bit isMod = 0;
       bit isRef = 1;
     }
    -

    +
    -

    -This shows that TableGen was able to dig into the argument and extract a piece -of information that was requested by the designer of the "Value" class. For -more realistic examples, please see existing users of TableGen, such as the X86 -backend.

    +

    This shows that TableGen was able to dig into the argument and extract a +piece of information that was requested by the designer of the "Value" class. +For more realistic examples, please see existing users of TableGen, such as the +X86 backend.

    - - - +
    -

    -TableGen supports the 'include' token, which textually substitutes the -specified file in place of the include directive. The filename should be +

    TableGen supports the 'include' token, which textually substitutes +the specified file in place of the include directive. The filename should be specified as a double quoted string immediately after the 'include' -keyword. Example: +keyword. Example:

    -

    +
     include "foo.td"
    -

    +
    - +
    -

    -"let" expressions at file scope are similar to "let" +

    "let" expressions at file scope are similar to "let" expressions within a record, except they can specify a value binding for multiple records at a time, and may be useful in certain other cases. File-scope let expressions are really just another way that TableGen allows the -end-user to factor out commonality from the records. -

    +end-user to factor out commonality from the records.

    -

    -File-scope "let" expressions take a comma-seperated list of bindings to apply, -and one of more records to bind the values in. Here are some examples: -

    +

    File-scope "let" expressions take a comma-seperated list of bindings to +apply, and one of more records to bind the values in. Here are some +examples:

    -

    +
     let isTerminator = 1, isReturn = 1 in
       def RET : X86Inst<"ret", 0xC3, RawFrm, NoArg>;
     
    @@ -598,56 +525,48 @@
         def CALLr32     : X86Inst<"call", 0xFF, MRMS2r, Arg32>;
         def CALLm32     : X86Inst<"call", 0xFF, MRMS2m, Arg32>;
       }
    -

    +
    -

    -File-scope "let" expressions are often useful when a couple of definitions need -to be added to several records, and the records do not otherwise need to be -opened, as in the case with the CALL* instructions above. -

    +

    File-scope "let" expressions are often useful when a couple of definitions +need to be added to several records, and the records do not otherwise need to be +opened, as in the case with the CALL* instructions above.

    -
    - -

    -How they work, how to write one. This section should not contain details about -any particular backend, except maybe -print-enums as an example. This should -highlight the APIs in TableGen/Record.h. -

    - +

    How they work, how to write one. This section should not contain details +about any particular backend, except maybe -print-enums as an example. This +should highlight the APIs in TableGen/Record.h.

    - - +
    - -

    -This is just a temporary, convenient, place to put stuff about the code +

    This is just a temporary, convenient, place to put stuff about the code generator before it gets its own document. This should describe all of the tablegen backends used by the code generator and the classes/definitions they -expect. -

    - +expect.

    - - +
    - +
    + Valid CSS! + Valid HTML 4.01! + + Chris Lattner
    + LLVM Compiler Infrastructure
    + Last modified: $Date: 2004/05/12 18:31:21 $ +
    From brukman at cs.uiuc.edu Wed May 12 13:37:02 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 12 13:37:02 2004 Subject: [llvm-commits] CVS: llvm/docs/CodingStandards.html Message-ID: <200405121837.NAA27757@zion.cs.uiuc.edu> Changes in directory llvm/docs: CodingStandards.html updated: 1.14 -> 1.15 --- Log message: Add proper footer since this file is HTML-4.01 compliant. --- Diffs of the changes: (+9 -6) Index: llvm/docs/CodingStandards.html diff -u llvm/docs/CodingStandards.html:1.14 llvm/docs/CodingStandards.html:1.15 --- llvm/docs/CodingStandards.html:1.14 Mon Oct 27 12:18:16 2003 +++ llvm/docs/CodingStandards.html Wed May 12 13:37:22 2004 @@ -947,13 +947,16 @@
    +
    + Valid CSS! + Valid HTML 4.01! - + Chris Lattner
    + LLVM Compiler Infrastructure
    + Last modified: $Date: 2004/05/12 18:37:22 $ +
    From brukman at cs.uiuc.edu Wed May 12 13:42:01 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 12 13:42:01 2004 Subject: [llvm-commits] CVS: llvm/docs/CommandLine.html Message-ID: <200405121842.NAA06536@zion.cs.uiuc.edu> Changes in directory llvm/docs: CommandLine.html updated: 1.20 -> 1.21 --- Log message: Made to be HTML-4.01 (Strict) -compliant. --- Diffs of the changes: (+19 -14) Index: llvm/docs/CommandLine.html diff -u llvm/docs/CommandLine.html:1.20 llvm/docs/CommandLine.html:1.21 --- llvm/docs/CommandLine.html:1.20 Thu May 6 17:03:59 2004 +++ llvm/docs/CommandLine.html Wed May 12 13:42:35 2004 @@ -215,10 +215,10 @@ to specify where to put the output. With the CommandLine library, this is represented like this:

    -

    - -cl::opt<string> OutputFilename("o", cl::desc("Specify output filename"), cl::value_desc("filename")); -

    + +
    +cl::opt<string> OutputFilename("o", cl::desc("Specify output filename"), cl::value_desc("filename"));
    +

    This declares a global variable "OutputFilename" that is used to capture the result of the "o" argument (first parameter). We specify @@ -934,7 +934,7 @@

     bool DebugFlag;      // the actual value
     static cl::opt<bool, true>       // The parser
    -Debug("debug", cl::desc("Enable debug output"), cl::Hidden,
    +Debug("debug", cl::desc("Enable debug output"), cl::Hidden,
           cl::location(DebugFlag));
     
    @@ -1242,6 +1242,7 @@ strategy basically looks like this:

    parse(string OrigInput) { +

    1. string input = OrigInput;
    2. if (isOption(input)) return getOption(input).parse();    // Normal option @@ -1255,11 +1256,11 @@   input = OrigInput;
        while (!isOption(input) && !input.empty()) input.pop_back();
      } -
    3. if (!OrigInput.empty()) error(); - +
    4. if (!OrigInput.empty()) error();
    -}

    + +

    }

    @@ -1698,12 +1699,16 @@
    - +
    + Valid CSS! + Valid HTML 4.01! + + Chris Lattner
    + LLVM Compiler Infrastructure
    + Last modified: $Date: 2004/05/12 18:42:35 $ +
    From brukman at cs.uiuc.edu Wed May 12 13:49:01 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 12 13:49:01 2004 Subject: [llvm-commits] CVS: llvm/docs/CFEBuildInstrs.html Message-ID: <200405121849.NAA19366@zion.cs.uiuc.edu> Changes in directory llvm/docs: CFEBuildInstrs.html updated: 1.14 -> 1.15 --- Log message: Made to be HTML-4.01 (Strict)-compliant. --- Diffs of the changes: (+17 -15) Index: llvm/docs/CFEBuildInstrs.html diff -u llvm/docs/CFEBuildInstrs.html:1.14 llvm/docs/CFEBuildInstrs.html:1.15 --- llvm/docs/CFEBuildInstrs.html:1.14 Fri Mar 12 12:02:17 2004 +++ llvm/docs/CFEBuildInstrs.html Wed May 12 13:49:47 2004 @@ -1,8 +1,9 @@ - + - - + + Bootstrapping the LLVM C/C++ Front-End @@ -132,13 +133,13 @@
  • Fix 1: If you have system header files that include inline assembly, you may have to modify them to remove the inline assembly, and install the modified versions in - $CFEINSTALL/target-triplet/sys-include.

  • + $CFEINSTALL/target-triplet/sys-include.
  • Fix 2: If you are building the C++ front-end on a CPU we haven't tried yet, you will probably have to edit the appropriate version of atomicity.h under src/libstdc++-v3/config/cpu/name-of-cpu/atomicity.h - and apply a patch so that it does not use inline assembly.

  • + and apply a patch so that it does not use inline assembly.

    Porting to a new architecture: If you are porting the new front-end @@ -197,9 +198,7 @@

  • compiling and running a "hello, LLVM" program in C and C++.
  • running the tests under test/Programs using gmake -C test/Programs
  • - -

    - +
    @@ -265,15 +264,18 @@ -
    - +
    + Valid CSS! + Valid HTML 4.01! + + Brian Gaeke
    + LLVM Compiler Infrastructure
    + Last modified: $Date: 2004/05/12 18:49:47 $ +
    From brukman at cs.uiuc.edu Wed May 12 13:58:03 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 12 13:58:03 2004 Subject: [llvm-commits] CVS: llvm/docs/OpenProjects.html Message-ID: <200405121858.NAA30965@zion.cs.uiuc.edu> Changes in directory llvm/docs: OpenProjects.html updated: 1.24 -> 1.25 --- Log message: Made file HTML-4.01 (Strict)-compliant. --- Diffs of the changes: (+13 -13) Index: llvm/docs/OpenProjects.html diff -u llvm/docs/OpenProjects.html:1.24 llvm/docs/OpenProjects.html:1.25 --- llvm/docs/OpenProjects.html:1.24 Fri Apr 16 11:55:30 2004 +++ llvm/docs/OpenProjects.html Wed May 12 13:57:54 2004 @@ -55,13 +55,9 @@ or to suggest other projects to add to this page.

    -

    The projects in this page are open ended. More specific projects are -filed as unassigned enhancements in our -LLVM bug tracker. Here is the current list: -

    - - +

    The projects in this page are open-ended. More specific projects are +filed as unassigned enhancements in the +LLVM bug tracker. See the list of currently outstanding issues if you wish to help improve LLVM.

    @@ -329,12 +325,16 @@
    - +
    + Valid CSS! + Valid HTML 4.01! + + Chris Lattner
    + LLVM Compiler Infrastructure
    + Last modified: $Date: 2004/05/12 18:57:54 $ +
    From lattner at cs.uiuc.edu Wed May 12 14:02:02 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 12 14:02:02 2004 Subject: [llvm-commits] CVS: llvm/tools/bugpoint/Miscompilation.cpp Message-ID: <200405121902.OAA04046@zion.cs.uiuc.edu> Changes in directory llvm/tools/bugpoint: Miscompilation.cpp updated: 1.47 -> 1.48 --- Log message: Turn the block extractor on by default now that it basically works, eliminating the option. --- Diffs of the changes: (+0 -7) Index: llvm/tools/bugpoint/Miscompilation.cpp diff -u llvm/tools/bugpoint/Miscompilation.cpp:1.47 llvm/tools/bugpoint/Miscompilation.cpp:1.48 --- llvm/tools/bugpoint/Miscompilation.cpp:1.47 Wed May 12 11:08:01 2004 +++ llvm/tools/bugpoint/Miscompilation.cpp Wed May 12 14:02:44 2004 @@ -29,10 +29,6 @@ namespace llvm { extern cl::list InputArgv; - cl::opt - EnableBlockExtraction("enable-block-extraction", - cl::desc("Enable basic block extraction for " - "miscompilation debugging (experimental)")); } namespace { @@ -390,9 +386,6 @@ static bool ExtractBlocks(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *, Module *), std::vector &MiscompiledFunctions) { - // Not enabled?? - if (!EnableBlockExtraction) return false; - std::vector Blocks; for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i) for (Function::iterator I = MiscompiledFunctions[i]->begin(), From brukman at cs.uiuc.edu Wed May 12 14:22:02 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 12 14:22:02 2004 Subject: [llvm-commits] CVS: llvm/docs/SourceLevelDebugging.html Message-ID: <200405121922.OAA10065@zion.cs.uiuc.edu> Changes in directory llvm/docs: SourceLevelDebugging.html updated: 1.2 -> 1.3 --- Log message: Made file comply with HTML-4.01 (Strict) --- Diffs of the changes: (+177 -232) Index: llvm/docs/SourceLevelDebugging.html diff -u llvm/docs/SourceLevelDebugging.html:1.2 llvm/docs/SourceLevelDebugging.html:1.3 --- llvm/docs/SourceLevelDebugging.html:1.2 Mon Jan 5 23:31:32 2004 +++ llvm/docs/SourceLevelDebugging.html Wed May 12 14:21:57 2004 @@ -9,17 +9,17 @@
    Source Level Debugging with LLVM
    + + + + + +
  • Debugger intrinsic functions
  • Values for debugger tags
  • - -
  • C/C++ front-end specific debug information
  • + +
  • C/C++ front-end specific debug information
      -
    1. Program Scope Entries
    2. +
    3. Program Scope Entries +
    4. Data objects (program variables)
    5. -
    +
  • +
    +A leafy and green bug eater +
    + - - +
    @@ -87,13 +95,12 @@
    -

    -The idea of the LLVM debugging information is to capture how the important +

    The idea of the LLVM debugging information is to capture how the important pieces of the source-language's Abstract Syntax Tree map onto LLVM code. Several design aspects have shaped the solution that appears here. The important ones are:

    -

      +
      • Debugging information should have very little impact on the rest of the compiler. No transformations, analyses, or code generators should need to be modified because of debugging information.
      • @@ -114,10 +121,9 @@ This allows compatibility with traditional machine-code level debuggers, like GDB or DBX. -

      +
    -

    -The approach used by the LLVM implementation is to use a small set of The approach used by the LLVM implementation is to use a small set of intrinsic functions to define a mapping between LLVM program objects and the source-level objects. The description of the source-level program is maintained in LLVM global variables in an Dwarf 3 standard).

    -

    -When a program is debugged, the debugger interacts with the user and turns the -stored debug information into source-language specific information. As such, -the debugger must be aware of the source-language, and is thus tied to a +

    When a program is debugged, the debugger interacts with the user and turns +the stored debug information into source-language specific information. As +such, the debugger must be aware of the source-language, and is thus tied to a specific language of family of languages. The LLVM -debugger is designed to be modular in its support for source-languages. -

    +debugger is designed to be modular in its support for source-languages.

    @@ -142,12 +146,12 @@
    -

    -An extremely high priority of LLVM debugging information is to make it interact -well with optimizations and analysis. In particular, the LLVM debug information -provides the following guarantees:

    -

      +

      An extremely high priority of LLVM debugging information is to make it +interact well with optimizations and analysis. In particular, the LLVM debug +information provides the following guarantees:

      + +
      • LLVM debug information always provides information to accurately read the source-level state of the program, regardless of which LLVM optimizations @@ -176,60 +180,51 @@ automatically merged by the linker, and unused information is automatically removed.
      • -

      +
    -

    -Basically, the debug information allows you to compile a program with "-O0 --g" and get full debug information, allowing you to arbitrarily modify the -program as it executes from the debugger. Compiling a program with "-O3 --g" gives you full debug information that is always available and accurate -for reading (e.g., you get accurate stack traces despite tail call elimination -and inlining), but you might lose the ability to modify the program and call -functions where were optimized out of the program, or inlined away completely. -

    +

    Basically, the debug information allows you to compile a program with +"-O0 -g" and get full debug information, allowing you to arbitrarily +modify the program as it executes from the debugger. Compiling a program with +"-O3 -g" gives you full debug information that is always available and +accurate for reading (e.g., you get accurate stack traces despite tail call +elimination and inlining), but you might lose the ability to modify the program +and call functions where were optimized out of the program, or inlined away +completely.

    -
    -

    -There are several important extensions that could be eventually added to the +

    There are several important extensions that could be eventually added to the LLVM debugger. The most important extension would be to upgrade the LLVM code generators to support debugging information. This would also allow, for example, the X86 code generator to emit native objects that contain debugging information consumable by traditional source-level debuggers like GDB or DBX.

    -

    -Additionally, LLVM optimizations can be upgraded to incrementally update the +

    Additionally, LLVM optimizations can be upgraded to incrementally update the debugging information, new commands can be added to the debugger, and thread support could be added to the debugger.

    -

    -The "SourceLanguage" modules provided by llvm-db could be substantially -improved to provide good support for C++ language features like namespaces and -scoping rules.

    +

    The "SourceLanguage" modules provided by llvm-db could be +substantially improved to provide good support for C++ language features like +namespaces and scoping rules.

    -

    -After working with the debugger for a while, perhaps the nicest improvement +

    After working with the debugger for a while, perhaps the nicest improvement would be to add some sort of line editor, such as GNU readline (but one that is compatible with the LLVM license).

    -

    -For someone so inclined, it should be straight-forward to write different +

    For someone so inclined, it should be straight-forward to write different front-ends for the LLVM debugger, as the LLVM debugging engine is cleanly separated from the llvm-db front-end. A new LLVM GUI debugger or IDE -would be nice. :) -

    +would be nice. :)

    -
    Using the llvm-db tool @@ -238,12 +233,10 @@
    -

    -The llvm-db tool provides a GDB-like interface for source-level +

    The llvm-db tool provides a GDB-like interface for source-level debugging of programs. This tool provides many standard commands for inspecting and modifying the program as it executes, loading new programs, single stepping, -placing breakpoints, etc. This section describes how to use the debugger. -

    +placing breakpoints, etc. This section describes how to use the debugger.

    llvm-db has been designed to be as similar to GDB in its user interface as possible. This should make it extremely easy to learn @@ -273,7 +266,7 @@ any cooperation from the code generators. Because it is so simple, it suffers from the following inherent limitations:

    -

      +
      • Running a program in llvm-db is a bit slower than running it with lli (i.e., in the JIT).
      • @@ -292,7 +285,7 @@
      • Attaching to existing processes and core files is not currently supported.
      • -

      +

    That said, the debugger is still quite useful, and all of these limitations can be eliminated by integrating support for the debugger into the code @@ -313,7 +306,7 @@

    TODO: this is obviously lame, when more is implemented, this can be much better.

    -

    +
     $ llvm-db funccall
     llvm-db: The LLVM source-level debugger
     Loading program... successfully loaded 'funccall.bc'!
    @@ -351,7 +344,7 @@
     The program stopped with exit code 0
     (llvm-db) quit
     $
    -

    +
    @@ -459,7 +452,7 @@
  • info catch
  • ... many others
  • -

    +
    @@ -469,15 +462,12 @@
    - -

    -The LLVM debugger is built out of three distinct layers of software. These +

    The LLVM debugger is built out of three distinct layers of software. These layers provide clients with different interface options depending on what pieces of they want to implement themselves, and it also promotes code modularity and good design. The three layers are the Debugger -interface, the "info" interfaces, and the -llvm-db tool itself. -

    +interface, the "info" interfaces, and the llvm-db tool itself.

    @@ -486,15 +476,13 @@
    -

    -The Debugger class (defined in the include/llvm/Debugger/ directory) is -a low-level class which is used to maintain information about the loaded +

    The Debugger class (defined in the include/llvm/Debugger/ directory) +is a low-level class which is used to maintain information about the loaded program, as well as start and stop the program running as necessary. This class does not provide any high-level analysis or control over the program, only exposing simple interfaces like load/unloadProgram, create/killProgram, step/next/finish/contProgram, and -low-level methods for installing breakpoints. -

    +low-level methods for installing breakpoints.

    The Debugger class is itself a wrapper around the lowest-level InferiorProcess @@ -656,17 +644,15 @@ module to decode the information that represents variables, types, functions, namespaces, etc: this allows for arbitrary source-language semantics and type-systems to be used, as long as there is a module written for the -debugger to interpret the information. -

    +debugger to interpret the information.

    -

    -To provide basic functionality, the LLVM debugger does have to make some +

    To provide basic functionality, the LLVM debugger does have to make some assumptions about the source-level language being debugged, though it keeps these to a minimum. The only common features that the LLVM debugger assumes exist are source files, and program objects. These abstract objects are used by the debugger to form stack traces, show information about local -variables, etc. +variables, etc.

    This section of the documentation first describes the representation aspects common to any source-language. The next section @@ -680,38 +666,32 @@

    -

    -One important aspect of the LLVM debug representation is that it allows the LLVM -debugger to efficiently index all of the global objects without having the scan -the program. To do this, all of the global objects use "anchor" globals of type -"{}", with designated names. These anchor objects obviously do not -contain any content or meaning by themselves, but all of the global objects of a -particular type (e.g., source file descriptors) contain a pointer to the anchor. -This pointer allows the debugger to use def-use chains to find all global -objects of that type. -

    +

    One important aspect of the LLVM debug representation is that it allows the +LLVM debugger to efficiently index all of the global objects without having the +scan the program. To do this, all of the global objects use "anchor" globals of +type "{}", with designated names. These anchor objects obviously do +not contain any content or meaning by themselves, but all of the global objects +of a particular type (e.g., source file descriptors) contain a pointer to the +anchor. This pointer allows the debugger to use def-use chains to find all +global objects of that type.

    -

    -So far, the following names are recognized as anchors by the LLVM debugger: -

    +

    So far, the following names are recognized as anchors by the LLVM +debugger:

    -

    +
       %llvm.dbg.translation_units = linkonce global {} {}
       %llvm.dbg.globals         = linkonce global {} {}
    -

    +
    -

    -Using anchors in this way (where the source file descriptor points to the +

    Using anchors in this way (where the source file descriptor points to the anchors, as opposed to having a list of source file descriptors) allows for the standard dead global elimination and merging passes to automatically remove unused debugging information. If the globals were kept track of through lists, there would always be an object pointing to the descriptors, thus would never be -deleted. -

    +deleted.

    -
    @@ -732,10 +712,9 @@ recommended to only put them after every source statement that includes executable code.

    -

    -Using calls to this intrinsic function to demark legal points for the debugger -to inspect the program automatically disables any optimizations that could -potentially confuse debugging information. To non-debug-information-aware +

    Using calls to this intrinsic function to demark legal points for the +debugger to inspect the program automatically disables any optimizations that +could potentially confuse debugging information. To non-debug-information-aware transformations, these calls simply look like calls to an external function, which they must assume to do anything (including reading or writing to any part of reachable memory). On the other hand, it does not impact many optimizations, @@ -743,12 +722,11 @@ optimization of subexpressions, code duplication transformations, or basic-block reordering transformations.

    -

    -An important aspect of the calls to the %llvm.dbg.stoppoint intrinsic -is that the function-local debugging information is woven together with use-def -chains. This makes it easy for the debugger to, for example, locate the 'next' -stop point. For a concrete example of stop points, see the example in the next section.

    +

    An important aspect of the calls to the %llvm.dbg.stoppoint +intrinsic is that the function-local debugging information is woven together +with use-def chains. This makes it easy for the debugger to, for example, +locate the 'next' stop point. For a concrete example of stop points, see the +example in the next section.

    @@ -759,24 +737,20 @@
    -

    -In many languages, the local variables in functions can have their lifetime or -scope limited to a subset of a function. In the C family of languages, for +

    In many languages, the local variables in functions can have their lifetime +or scope limited to a subset of a function. In the C family of languages, for example, variables are only live (readable and writable) within the source block that they are defined in. In functional languages, values are only readable after they have been defined. Though this is a very obvious concept, it is also non-trivial to model in LLVM, because it has no notion of scoping in this sense, -and does not want to be tied to a language's scoping rules. -

    +and does not want to be tied to a language's scoping rules.

    -

    -In order to handle this, the LLVM debug format uses the notion of "regions" of a -function, delineated by calls to intrinsic functions. These intrinsic functions -define new regions of the program and indicate when the region lifetime expires. -Consider the following C fragment, for example: -

    +

    In order to handle this, the LLVM debug format uses the notion of "regions" +of a function, delineated by calls to intrinsic functions. These intrinsic +functions define new regions of the program and indicate when the region +lifetime expires. Consider the following C fragment, for example:

    -

    +
     1.  void foo() {
     2.    int X = ...;
     3.    int Y = ...;
    @@ -786,14 +760,12 @@
     7.    }
     8.    ...
     9.  }
    -

    +
    -

    -Compiled to LLVM, this function would be represented like this (FIXME: CHECK AND -UPDATE THIS): -

    +

    Compiled to LLVM, this function would be represented like this (FIXME: CHECK +AND UPDATE THIS):

    -

    +
     void %foo() {
         %X = alloca int
         %Y = alloca int
    @@ -822,18 +794,16 @@
         %D12 = call {}* %llvm.region.end({}* %D11)
         ret void
     }
    -

    +
    -

    -This example illustrates a few important details about the LLVM debugging +

    This example illustrates a few important details about the LLVM debugging information. In particular, it shows how the various intrinsics used are woven together with def-use and use-def chains, similar to how anchors are used with globals. This allows the -debugger to analyze the relationship between statements, variable definitions, -and the code used to implement the function.

    +href="#format_common_anchors">anchors are used with globals. This allows +the debugger to analyze the relationship between statements, variable +definitions, and the code used to implement the function.

    -

    -In this example, two explicit regions are defined, one with the In this example, two explicit regions are defined, one with the definition of the %D1 variable and one with the definition of %D7. In the case of %D1, the debug information indicates that the function whose the %D12 call.

    -

    -Using regions to represent the boundaries of source-level functions allow LLVM -interprocedural optimizations to arbitrarily modify LLVM functions without +

    Using regions to represent the boundaries of source-level functions allow +LLVM interprocedural optimizations to arbitrarily modify LLVM functions without having to worry about breaking mapping information between the LLVM code and the and source-level program. In particular, the inliner requires no modification to support inlining with debugging information: there is no explicit correlation @@ -852,45 +821,37 @@ its caller that it will not be possible for the user to manually invoke the inlined function from the debugger).

    -

    -Once the function has been defined, the stopping point corresponding to line #2 of the -function is encountered. At this point in the function, no local +

    Once the function has been defined, the stopping point corresponding to line #2 of +the function is encountered. At this point in the function, no local variables are live. As lines 2 and 3 of the example are executed, their variable definitions are automatically introduced into the program, without the need to specify a new region. These variables do not require new regions to be introduced because they go out of scope at the same point in the program: line -9. -

    +9.

    -

    -In contrast, the Z variable goes out of scope at a different time, on -line 7. For this reason, it is defined within the +

    In contrast, the Z variable goes out of scope at a different time, +on line 7. For this reason, it is defined within the %D7 region, which kills the availability of Z before the code for line 8 is executed. In this way, regions can support arbitrary source-language scoping rules, as long as they can only be nested (ie, one scope -cannot partially overlap with a part of another scope). -

    +cannot partially overlap with a part of another scope).

    -

    -It is worth noting that this scoping mechanism is used to control scoping of all -declarations, not just variable declarations. For example, the scope of a C++ -using declaration is controlled with this, and the llvm-db C++ support -routines could use this to change how name lookup is performed (though this is -not implemented yet). -

    +

    It is worth noting that this scoping mechanism is used to control scoping of +all declarations, not just variable declarations. For example, the scope of a +C++ using declaration is controlled with this, and the llvm-db C++ +support routines could use this to change how name lookup is performed (though +this is not implemented yet).

    -
    -

    -The LLVM debugger expects the descriptors for program objects to start in a +

    The LLVM debugger expects the descriptors for program objects to start in a canonical format, but the descriptors can include additional information appended at the end that is source-language specific. All LLVM debugging information is versioned, allowing backwards compatibility in the case that the @@ -906,7 +867,7 @@

    - + + @@ -979,39 +940,35 @@ fields in the descriptor for each object:

    -

    +
     %lldb.object = type {
            uint,                  ;; A tag
            any*,                  ;; The context for the object
            sbyte*                 ;; The object 'name'
     }
    -

    +
    -

    -The first field contains a tag for the descriptor. The second field contains +

    The first field contains a tag for the descriptor. The second field contains either a pointer to the descriptor for the containing source file, or it contains a pointer to another program object whose context pointer eventually reaches a source file. Through this context pointer, the LLVM debugger can establish the debug version number of the object.

    -

    -The third field contains a string that the debugger can use to identify the +

    The third field contains a string that the debugger can use to identify the object if it does not contain explicit support for the source-language in use (ie, the 'unknown' source language handler uses this string). This should be some sort of unmangled string that corresponds to the object, but it is a quality of implementation issue what exactly it contains (it is legal, though -not useful, for all of these strings to be null). -

    +not useful, for all of these strings to be null).

    -

    -Note again that descriptors can be extended to include source-language-specific -information in addition to the fields required by the LLVM debugger. See the section on the C/C++ front-end for more -information. Also remember that global objects (functions, selectors, global -variables, etc) must contain an anchor to -the llvm.dbg.globals variable. -

    +

    Note again that descriptors can be extended to include +source-language-specific information in addition to the fields required by the +LLVM debugger. See the section on the C/C++ +front-end for more information. Also remember that global objects +(functions, selectors, global variables, etc) must contain an anchor to the llvm.dbg.globals +variable.

    @@ -1021,22 +978,20 @@
    -

    +
     Allow source-language specific contexts, use to identify namespaces etc
     Must end up in a source file descriptor.
     Debugger core ignores all unknown context objects.
    -

    +
    - -
    -

    +
     Define each intrinsics, as an extension of the language reference manual.
     
     llvm.dbg.stoppoint
    @@ -1044,11 +999,9 @@
     llvm.dbg.region.end
     llvm.dbg.function.start
     llvm.dbg.declare
    -

    +
    - -
    Values for debugger tags @@ -1056,18 +1009,15 @@
    -

    -Happen to be the same value as the similarly named Dwarf-3 tags, this may change -in the future. -

    +

    Happen to be the same value as the similarly named Dwarf-3 tags, this may +change in the future.

    -

    -

    +
       LLVM_COMPILE_UNIT     : 17
       LLVM_SUBPROGRAM       : 46
       LLVM_VARIABLE         : 52
     
    -

    +
    @@ -1079,32 +1029,28 @@
    -

    -The C and C++ front-ends represent information about the program in a format +

    The C and C++ front-ends represent information about the program in a format that is effectively identical to Dwarf 3.0 in terms of information content. This allows code generators to trivially support native debuggers by generating standard dwarf information, and contains enough information for non-dwarf targets to translate it as needed.

    -

    -The basic debug information required by the debugger is (intentionally) designed -to be as minimal as possible. This basic information is so minimal that it is -unlikely that any source-language could be adequately described by it. -Because of this, the debugger format was designed for extension to support -source-language-specific information. The extended descriptors are read and -interpreted by the language-specific modules in the -debugger if there is support available, otherwise it is ignored. -

    +

    The basic debug information required by the debugger is (intentionally) +designed to be as minimal as possible. This basic information is so minimal +that it is unlikely that any source-language could be adequately +described by it. Because of this, the debugger format was designed for +extension to support source-language-specific information. The extended +descriptors are read and interpreted by the language-specific modules in the debugger if there is +support available, otherwise it is ignored.

    -

    -This section describes the extensions used to represent C and C++ programs. +

    This section describes the extensions used to represent C and C++ programs. Other languages could pattern themselves after this (which itself is tuned to representing programs in the same way that Dwarf 3 does), or they could choose to provide completely different extensions if they don't fit into the Dwarf model. As support for debugging information gets added to the various LLVM -source-language front-ends, the information used should be documented here. -

    +source-language front-ends, the information used should be documented here.

    @@ -1114,12 +1060,10 @@
    -

    - -

    +

    TODO

    - + @@ -1133,15 +1077,13 @@

    - +
    -

    - -

    +

    TODO

    @@ -1150,20 +1092,23 @@
    -

    - -

    +

    TODO

    +
    - +
    + Valid CSS! + Valid HTML 4.01! + + Chris Lattner
    + LLVM Compiler Infrastructure
    + Last modified: $Date: 2004/05/12 19:21:57 $ +
    From brukman at cs.uiuc.edu Wed May 12 14:26:06 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 12 14:26:06 2004 Subject: [llvm-commits] CVS: llvm/docs/GettingStarted.html Message-ID: <200405121926.OAA23065@zion.cs.uiuc.edu> Changes in directory llvm/docs: GettingStarted.html updated: 1.54 -> 1.55 --- Log message: Make file standard-compliant once again. --- Diffs of the changes: (+11 -22) Index: llvm/docs/GettingStarted.html diff -u llvm/docs/GettingStarted.html:1.54 llvm/docs/GettingStarted.html:1.55 --- llvm/docs/GettingStarted.html:1.54 Sat May 1 06:40:07 2004 +++ llvm/docs/GettingStarted.html Wed May 12 14:25:59 2004 @@ -282,7 +282,7 @@ These are needed to use the LLVM test suite. Please note that newer versions of QMTest may not work with the LLVM test suite. QMTest 2.0.3 can be retrieved from the QMTest CVS repository using the following - commands: + commands:

    • cvs -d :pserver:anoncvs at cvs.codesourcery.com:/home/qm/Repository login
    • @@ -291,7 +291,7 @@
    • cvs -d :pserver:anoncvs at cvs.codesourcery.com:/home/qm/Repository co -r release-2-0-3 qm
    -

    + @@ -446,27 +446,16 @@ label:

      -
    • - Release 1.2: RELEASE_12 -
    • - -
    • - Release 1.1: RELEASE_11 -
    • - -
    • - Release 1.0: RELEASE_1 -
    • +
    • Release 1.2: RELEASE_12
    • +
    • Release 1.1: RELEASE_11
    • +
    • Release 1.0: RELEASE_1
    -

    -If you would like to get the GCC front end source code, you can also get it -from the CVS repository: -

      -
    • cvs -z3 -d :pserver:anon at llvm-cvs.cs.uiuc.edu:/var/cvs/llvm co - llvm-gcc -
    -

    +

    If you would like to get the GCC front end source code, you can also get it +from the CVS repository:

    + +
    cvs -z3 -d :pserver:anon at llvm-cvs.cs.uiuc.edu:/var/cvs/llvm co llvm-gcc
    +
    @@ -1215,7 +1204,7 @@ Chris Lattner
    The LLVM Compiler Infrastructure
    - Last modified: $Date: 2004/05/01 11:40:07 $ + Last modified: $Date: 2004/05/12 19:25:59 $ From brukman at cs.uiuc.edu Wed May 12 14:52:04 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 12 14:52:04 2004 Subject: [llvm-commits] CVS: llvm/docs/Stacker.html Message-ID: <200405121952.OAA04328@zion.cs.uiuc.edu> Changes in directory llvm/docs: Stacker.html updated: 1.9 -> 1.10 --- Log message: Made document HTML-4.01 (Strict)-compliant. --- Diffs of the changes: (+78 -69) Index: llvm/docs/Stacker.html diff -u llvm/docs/Stacker.html:1.9 llvm/docs/Stacker.html:1.10 --- llvm/docs/Stacker.html:1.9 Fri Apr 16 11:20:07 2004 +++ llvm/docs/Stacker.html Wed May 12 14:52:00 2004 @@ -1,12 +1,14 @@ - + - Stacker: An Example Of Using LLVM + Stacker: An Example Of Using LLVM +
    Stacker: An Example Of Using LLVM
    -
    +
    1. Abstract
    2. Introduction
    3. @@ -19,19 +21,17 @@
    4. The Wily GetElementPtrInst
    5. Getting Linkage Types Right
    6. Constants Are Easier Than That!
    7. -
    - +
  • The Stacker Lexicon
      -
    1. The Stack -
    2. Punctuation -
    3. Comments -
    4. Literals -
    5. Words -
    6. Standard Style -
    7. Built-Ins -
    -
  • +
  • The Stack
  • +
  • Punctuation
  • +
  • Comments
  • +
  • Literals
  • +
  • Words
  • +
  • Standard Style
  • +
  • Built-Ins
  • +
  • Prime: A Complete Example
  • Internal Code Details
      @@ -44,16 +44,15 @@
    1. Test Programs
    2. Exercise
    3. Things Remaining To Be Done
    4. -
    -
  • + +
    -

    Written by Reid Spencer

    -

    +

    Written by Reid Spencer

    -
    + - +

    This document is another way to learn about LLVM. Unlike the LLVM Reference Manual or @@ -222,11 +221,11 @@ before. This makes for some very clean compiler design.

    The foregoing is such an important principal, its worth making an idiom:

    -
    
    -BasicBlock* bb = new BasicBlock();
    +
    +BasicBlock* bb = new BasicBlock();
     bb->getInstList().push_back( new Branch( ... ) );
     new Instruction(..., bb->getTerminator() );
    -
    +

    To make this clear, consider the typical if-then-else statement (see StackerCompiler::handle_if() method). We can set this up in a single function using LLVM in the following way:

    @@ -301,20 +300,21 @@ missed a few very key points:

      -
    • GetElementPtrInst gives you back a Value for the last thing indexed. -
    • All global variables in LLVM are pointers. -
    • Pointers must also be dereferenced with the GetElementPtrInst instruction. +
    • GetElementPtrInst gives you back a Value for the last thing indexed.
    • +
    • All global variables in LLVM are pointers.
    • +
    • Pointers must also be dereferenced with the GetElementPtrInst +instruction.

    This means that when you look up an element in the global variable (assuming it's a struct or array), you must deference the pointer first! For many things, this leads to the idiom:

    -
    
    -std::vector index_vector;
    +
    +std::vector<Value*> index_vector;
     index_vector.push_back( ConstantSInt::get( Type::LongTy, 0 );
     // ... push other indices ...
     GetElementPtrInst* gep = new GetElementPtrInst( ptr, index_vector );
    -
    +

    For example, suppose we have a global variable whose type is [24 x int]. The variable itself represents a pointer to that array. To subscript the array, we need two indices, not just one. The first index (0) dereferences the @@ -513,10 +513,10 @@ Definition Of Operation Of Built In Words LOGICAL OPERATIONS - Word - Name - Operation - Description + Word + Name + Operation + Description < LT @@ -576,10 +576,10 @@ BITWISE OPERATORS - Word - Name - Operation - Description + Word + Name + Operation + Description << SHL @@ -618,10 +618,10 @@ ARITHMETIC OPERATORS - Word - Name - Operation - Description + Word + Name + Operation + Description ABS ABS @@ -699,10 +699,10 @@ STACK MANIPULATION OPERATORS - Word - Name - Operation - Description + Word + Name + Operation + Description DROP DROP @@ -754,7 +754,7 @@ The top four stack items are swapped in pairs. That is, two values are popped and retained. Then, two more values are popped and retained. The values are pushed back on to the stack in the reverse order but - in pairs.

    + in pairs. OVER OVER @@ -844,10 +844,10 @@ MEMORY OPERATORS - Word - Name - Operation - Description + Word + Name + Operation + Description MALLOC MALLOC @@ -897,10 +897,10 @@ CONTROL FLOW OPERATORS - Word - Name - Operation - Description + Word + Name + Operation + Description RETURN RETURN @@ -964,10 +964,10 @@ INPUT & OUTPUT OPERATORS - Word - Name - Operation - Description + Word + Name + Operation + Description SPACE SPACE @@ -1311,32 +1311,32 @@
    The Lexer

    See projects/Stacker/lib/compiler/Lexer.l

    -

    +
    The Parser

    See projects/Stacker/lib/compiler/StackerParser.y

    -

    +
    The Compiler

    See projects/Stacker/lib/compiler/StackerCompiler.cpp

    -

    +
    The Runtime

    See projects/Stacker/lib/runtime/stacker_rt.c

    -

    +
    Compiler Driver

    See projects/Stacker/tools/stkrc/stkrc.cpp

    -

    +
    Test Programs

    See projects/Stacker/test/*.st

    -

    +
    @@ -1390,11 +1390,20 @@ Lessons I Learned About LLVM section.
    - + + +
    - +
    + Valid CSS! + Valid HTML 4.01! + + Reid Spencer
    + LLVM Compiler Infrastructure
    + Last modified: $Date: 2004/05/12 19:52:00 $ +
    + From brukman at cs.uiuc.edu Wed May 12 15:57:02 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 12 15:57:02 2004 Subject: [llvm-commits] CVS: llvm/docs/Projects.html Message-ID: <200405122057.PAA16106@zion.cs.uiuc.edu> Changes in directory llvm/docs: Projects.html updated: 1.9 -> 1.10 --- Log message: Make file use stylesheets and be HTML-4.01 (Strict)-compliant. --- Diffs of the changes: (+442 -386) Index: llvm/docs/Projects.html diff -u llvm/docs/Projects.html:1.9 llvm/docs/Projects.html:1.10 --- llvm/docs/Projects.html:1.9 Wed Oct 29 19:23:40 2003 +++ llvm/docs/Projects.html Wed May 12 15:57:43 2004 @@ -1,391 +1,447 @@ - + - - Creating an LLVM Project - - - - -

    Creating an LLVM Project

    - - -

    Overview

    - - - The LLVM build system is designed to facilitate the building of third party - projects that use LLVM header files, libraries, and tools. In order to use - these facilities, a Makefile from a project must do the following things: - -
      -
    1. Set environment variables. -

      - There are several environment variables that a Makefile needs to set to - use the LLVM build system: -

      -
      LLVM_SRC_ROOT -
      - The root of the LLVM source tree. -

      - -

      LLVM_OBJ_ROOT -
      - The root of the LLVM object tree. -

      - -

      BUILD_SRC_ROOT -
      - The root of the project's source tree. -

      - -

      BUILD_OBJ_ROOT -
      - The root of the project's object tree. -

      - -

      BUILD_SRC_DIR -
      - The directory containing the current source to be compiled. -

      - -

      BUILD_OBJ_DIR -
      - The directory where the current source will place the new object - files. This should always be the current directory. -

      - -

      LEVEL -
      - The relative path from the current directory to the root of the - object tree. -

      -

      - -
    2. Include the LLVM Makefile.config from $(LLVM_OBJ_ROOT). -

      - -

    3. Include the LLVM Makefile.rules from $(LLVM_SRC_ROOT). -
    - - There are two ways that you can set all of these variables: -
      -
    1. - You can write your own Makefiles which hard-code these values. - -
    2. - You can use the pre-made LLVM sample project. This sample project - includes Makefiles, a configure script that can be used to configure - the location of LLVM, and the ability to support multiple object - directories from a single source directory. -
    - - This document assumes that you will base your project off of the LLVM - sample project found in llvm/projects/sample. If you want to - devise your own build system, studying the sample project and LLVM - Makefiles will probably provide enough information on how to write your own - Makefiles. -

    - - -

    Create a Project from the Sample Project

    - - - Follow these simple steps to start your project: - -
      -
    1. - Copy the llvm/projects/sample directory to any place - of your choosing. You can place it anywhere you like. Rename the - directory to match the name of your project. -

      - -

    2. - Add your source code and Makefiles to your source tree. -

      - -

    3. - If you want your Makefiles to be configured by the - configure script, or if you want to support multiple - object directories, add your Makefiles to the configure - script by adding them into the autoconf/configure.ac file. - The macro AC_CONFIG_MAKEFILE will copy a file, unmodified, - from the source directory to the object directory. - -

      - After updating autoconf/configure.ac, regenerate the - configure script with these commands: -

      - - cd autoconf
      - autoconf -o ../configure -
      - -

      - - You must be using Autoconf version 2.57 or higher. -

      - -

    4. - Run configure in the directory in which you want to place - object code. Use the following options to tell your project where it - can find LLVM: - -
      -
      --with-llvmsrc=<directory> -
      - Tell your project where the LLVM source tree is located. -

      -

      --with-llvmobj=<directory> -
      - Tell your project where the LLVM object tree is located. -
      -
    - - That's it! Now all you have to do is type gmake in the root of - your object directory, and your project should build. - - -

    Source Tree Layout

    - - - In order to use the LLVM build system, you will want to organize your - source code so that it can benefit from the build system's features. - Mainly, you want your source tree layout to look similar to the LLVM - source tree layout. The best way to do this is to just copy the - project tree from llvm/projects/sample and modify it to meet - your needs, but you can certainly add to it if you want. - - Underneath your top level directory, you should have the following - directories: - -
    -
    lib -
    - This subdirectory should contain all of your library source - code. For each library that you build, you will have one - directory in lib that will contain that library's source - code. - -

    - Libraries can be object files, archives, or dynamic libraries. - The lib directory is just a convenient place for libraries - as it places them all in a directory from which they can be linked - later. - -

    include -
    - This subdirectory should contain any header files that are - global to your project. By global, we mean that they are used - by more than one library or executable of your project. -

    - By placing your header files in include, they will be - found automatically by the LLVM build system. For example, if - you have a file include/jazz/note.h, then your source - files can include it simply with #include "jazz/note.h". - -

    tools -
    - This subdirectory should contain all of your source - code for executables. For each program that you build, you - will have one directory in tools that will contain that - program's source code. -

    - -

    test -
    - This subdirectory should contain tests that verify that your code - works correctly. Automated tests are especially useful. -

    - Currently, the LLVM build system provides little support for tests, - although some exists. Expanded support for tests will hopefully - occur in the future. In the meantime, the LLVM system does provide the - following: -

      -
    • - LLVM provides several QMTest test classes that can be used to - create tests. They can be found in - llvm/test/QMTest/llvm.py. These test classes perform a - variety of functions, including code optimization tests, assembly - tests, and code analysis tests. The Makefile in - llvm/test provides the QMTest context needed by LLVM test - classes. -

      - -

    • - The LLVM source tree provides benchmarks and programs which are - known to compile with the LLVM GCC front ends. You can use these - programs to test your code, gather statistics information, and - compare it to the current LLVM performance statistics. These - programs are found in the llvm/test/Programs directory. -

      - Currently, there is no way to hook your tests directly into the - llvm/test/Programs testing harness. You will simply - need to find a way to use the source provided within that directory - on your own. -

    -
    - - Typically, you will want to build your lib directory first - followed by your tools directory. - - -

    Writing LLVM Style Makefiles

    - - The LLVM build system provides a convenient way to build libraries and - executables. Most of your project Makefiles will only need to define a few - variables. Below is a list of the variables one can set and what they can - do: - -

    Required Variables

    -
    -
    LEVEL -
    - This variable is the relative path from this Makefile to the - top directory of your project's source code. For example, if - your source code is in /tmp/src, then the Makefile in - /tmp/src/jump/high would set LEVEL to "../..". -
    - -

    Variables for Building Subdirectories

    -
    -
    DIRS -
    - This is a space separated list of subdirectories that should be - built. They will be built, one at a time, in the order - specified. -

    - -

    PARALLEL_DIRS -
    - This is a list of directories that can be built in parallel. - These will be built after the directories in DIRS have been - built. -

    - -

    OPTIONAL_DIRS -
    - This is a list of directories that can be built if they exist, - but will not cause an error if they do not exist. They are - built serially in the order in which they are listed. -
    - -

    Variables for Building Libraries

    -
    -
    LIBRARYNAME -
    - This variable contains the base name of the library that will - be built. For example, to build a library named - libsample.a, LIBRARYNAME should be set to - sample. -

    - -

    BUILD_ARCHIVE -
    - By default, a library is a .o file that is linked - directly into a program. To build an archive (also known as - a static library), set the BUILD_ARCHIVE variable. -

    - -

    SHARED_LIBRARY -
    - If SHARED_LIBRARY is defined in your Makefile, a shared - (or dynamic) library will be built. -
    - -

    Variables for Building Programs

    -
    -
    TOOLNAME -
    - This variable contains the name of the program that will - be built. For example, to build an executable named - sample, TOOLNAME should be set to sample. -

    - -

    USEDLIBS -
    - This variable holds a space separated list of libraries that - should be linked into the program. These libraries must either - be LLVM libraries or libraries that come from your lib - directory. The libraries must be specified by their base name. - For example, to link libsample.a, you would set USEDLIBS to - sample. -

    - Note that this works only for statically linked libraries. -

    - -

    LIBS -
    - To link dynamic libraries, add -l<library base name> to - the LIBS variable. The LLVM build system will look in the same places - for dynamic libraries as it does for static libraries. -

    - For example, to link libsample.so, you would have the - following line in your Makefile: -

    - - LIBS+=-lsample - -

    - -

    Miscellaneous Variables

    -
    -
    ExtraSource -
    - This variable contains a space separated list of extra source - files that need to be built. It is useful for including the - output of Lex and Yacc programs. -

    - -

    CFLAGS -
    CPPFLAGS -
    - This variable can be used to add options to the C and C++ - compiler, respectively. It is typically used to add options - that tell the compiler the location of additional directories - to search for header files. -

    - It is highly suggested that you append to CFLAGS and CPPFLAGS as - opposed to overwriting them. The master Makefiles may already - have useful options in them that you may not want to overwrite. -

    -

    - - -

    Placement of Object Code

    - - - The final location of built libraries and executables will depend upon - whether you do a Debug, Release, or Profile build. - -
    -
    Libraries -
    - All libraries (static and dynamic) will be stored in - BUILD_OBJ_ROOT/lib/<type>, where type is Debug, - Release, or Profile for a debug, optimized, or - profiled build, respectively. -

    - -

    Executables -
    - All executables will be stored in BUILD_OBJ_ROOT/lib/<type>, - where type is Debug, Release, or Profile for - a debug, optimized, or profiled build, respectively. -
    - - -

    Further Help

    - - - If you have any questions or need any help creating an LLVM project, - the LLVM team would be more than happy to help. You can always post your - questions to the LLVM Developers - Mailing List. - + + Creating an LLVM Project + + + + +
    Creating an LLVM Project
    + +
      +
    1. Overview
    2. +
    3. Create a project from the Sample Project
    4. +
    5. Source tree layout
    6. +
    7. Writing LLVM-style Makefiles +
        +
      1. Required Variables
      2. +
      3. Variables for Building Subdirectories
      4. +
      5. Variables for Building Libraries
      6. +
      7. Variables for Building Programs
      8. +
      9. Miscellaneous Variables
      10. +
    8. +
    9. Placement of object code
    10. +
    11. Further help
    12. +
    + + + + + +
    + +

    The LLVM build system is designed to facilitate the building of third party +projects that use LLVM header files, libraries, and tools. In order to use +these facilities, a Makefile from a project must do the following things:

    + +
      +
    1. Set environment variables.There are several environment variables that a +Makefile needs to set to use the LLVM build system: + +
        +
      • LLVM_SRC_ROOT - The root of the LLVM source tree.
      • +
      • LLVM_OBJ_ROOT - The root of the LLVM object tree.
      • +
      • BUILD_SRC_ROOT - The root of the project's source tree.
      • +
      • BUILD_OBJ_ROOT - The root of the project's object tree.
      • +
      • BUILD_SRC_DIR - The directory containing the current source to be + compiled.
      • +
      • BUILD_OBJ_DIR - The directory where the current source will place + the new object files. This should always be the current directory.
      • +
      • LEVEL - The relative path from the current directory to the root + of the object tree.
      • +
    2. +
    3. Include Makefile.config from $(LLVM_OBJ_ROOT).
    4. +
    5. Include Makefile.rules from $(LLVM_SRC_ROOT).
    6. +
    + +

    There are two ways that you can set all of these variables:

    + +
      +
    1. You can write your own Makefiles which hard-code these values.
    2. + +
    3. You can use the pre-made LLVM sample project. This sample project includes +Makefiles, a configure script that can be used to configure the location of +LLVM, and the ability to support multiple object directories from a single +source directory.
    4. +
    + +

    This document assumes that you will base your project off of the LLVM sample +project found in llvm/projects/sample. If you want to devise your own +build system, studying the sample project and LLVM Makefiles will probably +provide enough information on how to write your own Makefiles.

    + +
    + + + + + +
    + +

    Follow these simple steps to start your project:

    + +
      +
    1. Copy the llvm/projects/sample directory to any place of your +choosing. You can place it anywhere you like. Rename the directory to match +the name of your project.
    2. + +
    3. Add your source code and Makefiles to your source tree.
    4. + +
    5. If you want your Makefiles to be configured by the configure +script, or if you want to support multiple object directories, add your +Makefiles to the configure script by adding them into the +autoconf/configure.ac file. The macro AC_CONFIG_MAKEFILE will +copy a file, unmodified, from the source directory to the object directory.
    6. + +
    7. After updating autoconf/configure.ac, regenerate the +configure script with these commands: + +
      +

      % cd autoconf
      + % autoconf -o ../configure

      +
      + +

      You must be using Autoconf version 2.57 or higher.

    8. + +
    9. Run configure in the directory in which you want to place +object code. Use the following options to tell your project where it +can find LLVM: + +
      +
      --with-llvmsrc=<directory> +
      + Tell your project where the LLVM source tree is located. +

      +

      --with-llvmobj=<directory> +
      + Tell your project where the LLVM object tree is located. +
      +
    + +

    That's it! Now all you have to do is type gmake in the root of +your object directory, and your project should build.

    + +
    + + + + + +
    + +

    In order to use the LLVM build system, you will want to organize your +source code so that it can benefit from the build system's features. +Mainly, you want your source tree layout to look similar to the LLVM +source tree layout. The best way to do this is to just copy the +project tree from llvm/projects/sample and modify it to meet +your needs, but you can certainly add to it if you want.

    + +

    Underneath your top level directory, you should have the following +directories:

    + +
    +
    lib +
    + This subdirectory should contain all of your library source + code. For each library that you build, you will have one + directory in lib that will contain that library's source + code. + +

    + Libraries can be object files, archives, or dynamic libraries. + The lib directory is just a convenient place for libraries + as it places them all in a directory from which they can be linked + later. + +

    include +
    + This subdirectory should contain any header files that are + global to your project. By global, we mean that they are used + by more than one library or executable of your project. +

    + By placing your header files in include, they will be + found automatically by the LLVM build system. For example, if + you have a file include/jazz/note.h, then your source + files can include it simply with #include "jazz/note.h". + +

    tools +
    + This subdirectory should contain all of your source + code for executables. For each program that you build, you + will have one directory in tools that will contain that + program's source code. +

    + +

    test +
    + This subdirectory should contain tests that verify that your code + works correctly. Automated tests are especially useful. +

    + Currently, the LLVM build system provides little support for tests, + although some exists. Expanded support for tests will hopefully + occur in the future. In the meantime, the LLVM system does provide the + following: +

      +
    • + LLVM provides several QMTest test classes that can be used to + create tests. They can be found in + llvm/test/QMTest/llvm.py. These test classes perform a + variety of functions, including code optimization tests, assembly + tests, and code analysis tests. The Makefile in + llvm/test provides the QMTest context needed by LLVM test + classes. +

      + +

    • + The LLVM source tree provides benchmarks and programs which are + known to compile with the LLVM GCC front ends. You can use these + programs to test your code, gather statistics information, and + compare it to the current LLVM performance statistics. These + programs are found in the llvm/test/Programs directory. +

      + Currently, there is no way to hook your tests directly into the + llvm/test/Programs testing harness. You will simply + need to find a way to use the source provided within that directory + on your own. +

    +
    + +

    Typically, you will want to build your lib directory first followed by +your tools directory.

    + +
    + + + + + +
    + +

    The LLVM build system provides a convenient way to build libraries and +executables. Most of your project Makefiles will only need to define a few +variables. Below is a list of the variables one can set and what they can +do:

    + +
    + + + + +
    + +
    +
    LEVEL +
    + This variable is the relative path from this Makefile to the + top directory of your project's source code. For example, if + your source code is in /tmp/src, then the Makefile in + /tmp/src/jump/high would set LEVEL to "../..". +
    + +
    + + + + +
    + +
    +
    DIRS +
    + This is a space separated list of subdirectories that should be + built. They will be built, one at a time, in the order + specified. +

    + +

    PARALLEL_DIRS +
    + This is a list of directories that can be built in parallel. + These will be built after the directories in DIRS have been + built. +

    + +

    OPTIONAL_DIRS +
    + This is a list of directories that can be built if they exist, + but will not cause an error if they do not exist. They are + built serially in the order in which they are listed. +
    + +
    + + + + +
    + +
    +
    LIBRARYNAME +
    + This variable contains the base name of the library that will + be built. For example, to build a library named + libsample.a, LIBRARYNAME should be set to + sample. +

    + +

    BUILD_ARCHIVE +
    + By default, a library is a .o file that is linked + directly into a program. To build an archive (also known as + a static library), set the BUILD_ARCHIVE variable. +

    + +

    SHARED_LIBRARY +
    + If SHARED_LIBRARY is defined in your Makefile, a shared + (or dynamic) library will be built. +
    + +
    + + + + +
    + +
    +
    TOOLNAME +
    + This variable contains the name of the program that will + be built. For example, to build an executable named + sample, TOOLNAME should be set to sample. +

    + +

    USEDLIBS +
    + This variable holds a space separated list of libraries that + should be linked into the program. These libraries must either + be LLVM libraries or libraries that come from your lib + directory. The libraries must be specified by their base name. + For example, to link libsample.a, you would set USEDLIBS to + sample. +

    + Note that this works only for statically linked libraries. +

    + +

    LIBS +
    + To link dynamic libraries, add -l<library base name> to + the LIBS variable. The LLVM build system will look in the same places + for dynamic libraries as it does for static libraries. +

    + For example, to link libsample.so, you would have the + following line in your Makefile: +

    + + LIBS += -lsample + +

    + +
    + + + + +
    + +
    +
    ExtraSource +
    + This variable contains a space separated list of extra source + files that need to be built. It is useful for including the + output of Lex and Yacc programs. +

    + +

    CFLAGS +
    CPPFLAGS +
    + This variable can be used to add options to the C and C++ + compiler, respectively. It is typically used to add options + that tell the compiler the location of additional directories + to search for header files. +

    + It is highly suggested that you append to CFLAGS and CPPFLAGS as + opposed to overwriting them. The master Makefiles may already + have useful options in them that you may not want to overwrite. +

    +

    + +
    + + + + + +
    + +

    The final location of built libraries and executables will depend upon +whether you do a Debug, Release, or Profile build.

    + +
    +
    Libraries +
    + All libraries (static and dynamic) will be stored in + BUILD_OBJ_ROOT/lib/<type>, where type is Debug, + Release, or Profile for a debug, optimized, or + profiled build, respectively.

    + +

    Executables +
    All executables will be stored in + BUILD_OBJ_ROOT/tools/<type>, where type is Debug, + Release, or Profile for a debug, optimized, or profiled + build, respectively. +
    + +
    + + + + + +
    + +

    If you have any questions or need any help creating an LLVM project, +the LLVM team would be more than happy to help. You can always post your +questions to the LLVM Developers +Mailing List.

    + +
    + +
    -
    John Criswell

    -The LLVM Compiler Infrastructure
    -Last modified: $Date: 2003/10/30 01:23:40 $ +
    + Valid CSS! + Valid HTML 4.01! + + John Criswell
    + The LLVM Compiler Infrastructure +
    + Last modified: $Date: 2004/05/12 20:57:43 $ +
    From alkis at cs.uiuc.edu Wed May 12 16:07:10 2004 From: alkis at cs.uiuc.edu (Alkis Evlogimenos) Date: Wed May 12 16:07:10 2004 Subject: [llvm-commits] CVS: llvm-www/ProjectsWithLLVM/index.html Message-ID: <200405122107.QAA27939@zion.cs.uiuc.edu> Changes in directory llvm-www/ProjectsWithLLVM: index.html updated: 1.11 -> 1.12 --- Log message: Fix broken link --- Diffs of the changes: (+1 -1) Index: llvm-www/ProjectsWithLLVM/index.html diff -u llvm-www/ProjectsWithLLVM/index.html:1.11 llvm-www/ProjectsWithLLVM/index.html:1.12 --- llvm-www/ProjectsWithLLVM/index.html:1.11 Thu Apr 1 16:12:36 2004 +++ llvm-www/ProjectsWithLLVM/index.html Wed May 12 16:06:52 2004 @@ -195,7 +195,7 @@

    Project report: PS, -PDF +PDF

    From brukman at cs.uiuc.edu Wed May 12 16:19:04 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 12 16:19:04 2004 Subject: [llvm-commits] CVS: llvm/docs/img/ Message-ID: <200405122119.QAA06739@zion.cs.uiuc.edu> Changes in directory llvm/docs/img: --- Log message: Directory /home/vadve/shared/PublicCVS/llvm/docs/img added to the repository --- Diffs of the changes: (+0 -0) From brukman at cs.uiuc.edu Wed May 12 16:20:01 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 12 16:20:01 2004 Subject: [llvm-commits] CVS: llvm/docs/img/Debugging.gif lines.gif venusflytrap.jpg Message-ID: <200405122120.QAA18634@zion.cs.uiuc.edu> Changes in directory llvm/docs/img: Debugging.gif added (r1.1) lines.gif added (r1.1) venusflytrap.jpg added (r1.1) --- Log message: Centralize images in this dir; add lines.gif from website for consistent formatting. --- Diffs of the changes: (+0 -0) Index: llvm/docs/img/Debugging.gif Index: llvm/docs/img/lines.gif Index: llvm/docs/img/venusflytrap.jpg From brukman at cs.uiuc.edu Wed May 12 16:21:02 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 12 16:21:02 2004 Subject: [llvm-commits] CVS: llvm/docs/llvm.css Message-ID: <200405122121.QAA30024@zion.cs.uiuc.edu> Changes in directory llvm/docs: llvm.css updated: 1.13 -> 1.14 --- Log message: Finally, switch to a stylesheet that makes the documentation easier on the eyes and consistent with the LLVM website. --- Diffs of the changes: (+8 -12) Index: llvm/docs/llvm.css diff -u llvm/docs/llvm.css:1.13 llvm/docs/llvm.css:1.14 --- llvm/docs/llvm.css:1.13 Thu Apr 15 15:49:32 2004 +++ llvm/docs/llvm.css Wed May 12 16:20:56 2004 @@ -16,8 +16,12 @@ */ /* Common for title and header */ .doc_title, .doc_section, .doc_subsection { - color: #ffffff; background: #330077; + color: black; background: url("img/lines.gif"); font-family: "Georgia,Palatino,Times,Roman"; font-weight: bold; + border-width: 1px; + border-style: solid none solid none; + text-align: center; + vertical-align: middle; padding-left: 8pt; padding-top: 1px; padding-bottom: 2px @@ -25,21 +29,13 @@ .doc_title { text-align: left; font-size: 25pt } .doc_section { text-align: center; font-size: 22pt; } -.doc_subsection { background: #441188; width: 50%; - text-align: left; font-size: 12pt; padding: 4pt 4pt 4pt 4pt; +.doc_subsection { width: 50%; + text-align: left; font-size: 12pt; padding: 4pt 4pt 4pt 4pt; margin: 1.5em 0.5em 1.5em 0.5em } -/* In the future, the 2nd level subsection style may want to become this: .doc_subsubsection { margin: 1.5em 0.5em 1.5 0.5em; font-weight: bold; font-style: oblique; - border-bottom: 2px dotted #999999 } -*/ - -/* However, to be consistent with the rest of current documentation which is not - all yet using stylesheets, we try to emulate the former layout. */ -.doc_subsubsection { margin: 1.5em 0.5em 1.5em 0.5em; - font-weight: bold; - border-top: 2px solid #cecece } + border-bottom: 1px solid #999999 } .doc_text { text-align: left; padding-left: 20pt } From brukman at cs.uiuc.edu Wed May 12 16:26:01 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 12 16:26:01 2004 Subject: [llvm-commits] CVS: llvm/docs/Debugging.gif venusflytrap.jpg Message-ID: <200405122126.QAA21290@zion.cs.uiuc.edu> Changes in directory llvm/docs: Debugging.gif (r1.1) removed venusflytrap.jpg (r1.1) removed --- Log message: These images have been moved to img/ --- Diffs of the changes: (+0 -0) From brukman at cs.uiuc.edu Wed May 12 16:26:08 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 12 16:26:08 2004 Subject: [llvm-commits] CVS: llvm/docs/HowToSubmitABug.html SourceLevelDebugging.html Message-ID: <200405122126.QAA09620@zion.cs.uiuc.edu> Changes in directory llvm/docs: HowToSubmitABug.html updated: 1.18 -> 1.19 SourceLevelDebugging.html updated: 1.3 -> 1.4 --- Log message: Use the images in the img/ directory. --- Diffs of the changes: (+4 -4) Index: llvm/docs/HowToSubmitABug.html diff -u llvm/docs/HowToSubmitABug.html:1.18 llvm/docs/HowToSubmitABug.html:1.19 --- llvm/docs/HowToSubmitABug.html:1.18 Tue May 11 19:57:24 2004 +++ llvm/docs/HowToSubmitABug.html Wed May 12 16:26:16 2004 @@ -36,7 +36,7 @@ - Debugging + Debugging @@ -341,7 +341,7 @@ Chris Lattner
    The LLVM Compiler Infrastructure
    - Last modified: $Date: 2004/05/12 00:57:24 $ + Last modified: $Date: 2004/05/12 21:26:16 $ Index: llvm/docs/SourceLevelDebugging.html diff -u llvm/docs/SourceLevelDebugging.html:1.3 llvm/docs/SourceLevelDebugging.html:1.4 --- llvm/docs/SourceLevelDebugging.html:1.3 Wed May 12 14:21:57 2004 +++ llvm/docs/SourceLevelDebugging.html Wed May 12 16:26:16 2004 @@ -62,7 +62,7 @@ -A leafy and green bug eater @@ -1107,7 +1107,7 @@ Chris Lattner
    LLVM Compiler Infrastructure
    - Last modified: $Date: 2004/05/12 19:21:57 $ + Last modified: $Date: 2004/05/12 21:26:16 $ From lattner at cs.uiuc.edu Wed May 12 16:28:01 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 12 16:28:01 2004 Subject: [llvm-commits] CVS: llvm/docs/llvm.css Message-ID: <200405122128.QAA26130@zion.cs.uiuc.edu> Changes in directory llvm/docs: llvm.css updated: 1.14 -> 1.15 --- Log message: Make the subsubsections stand out a bit more --- Diffs of the changes: (+2 -1) Index: llvm/docs/llvm.css diff -u llvm/docs/llvm.css:1.14 llvm/docs/llvm.css:1.15 --- llvm/docs/llvm.css:1.14 Wed May 12 16:20:56 2004 +++ llvm/docs/llvm.css Wed May 12 16:28:08 2004 @@ -34,8 +34,9 @@ margin: 1.5em 0.5em 1.5em 0.5em } .doc_subsubsection { margin: 1.5em 0.5em 1.5 0.5em; + padding: 20pt 4pt 4pt 4pt; font-weight: bold; font-style: oblique; - border-bottom: 1px solid #999999 } + border-bottom: 1px solid #999999; font-size: 12pt } .doc_text { text-align: left; padding-left: 20pt } From gaeke at cs.uiuc.edu Wed May 12 16:35:01 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Wed May 12 16:35:01 2004 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/MachineFunction.cpp Message-ID: <200405122135.QAA26354@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: MachineFunction.cpp updated: 1.55 -> 1.56 --- Log message: Start NextMBBNumber out at zero. --- Diffs of the changes: (+1 -1) Index: llvm/lib/CodeGen/MachineFunction.cpp diff -u llvm/lib/CodeGen/MachineFunction.cpp:1.55 llvm/lib/CodeGen/MachineFunction.cpp:1.56 --- llvm/lib/CodeGen/MachineFunction.cpp:1.55 Mon Mar 29 15:58:31 2004 +++ llvm/lib/CodeGen/MachineFunction.cpp Wed May 12 16:35:23 2004 @@ -87,7 +87,7 @@ MachineFunction::MachineFunction(const Function *F, const TargetMachine &TM) - : Annotation(MF_AID), Fn(F), Target(TM) { + : Annotation(MF_AID), Fn(F), Target(TM), NextMBBNumber(0) { SSARegMapping = new SSARegMap(); MFInfo = new MachineFunctionInfo(*this); FrameInfo = new MachineFrameInfo(); From gaeke at cs.uiuc.edu Wed May 12 16:35:08 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Wed May 12 16:35:08 2004 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/MachineBasicBlock.cpp Message-ID: <200405122135.QAA26347@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: MachineBasicBlock.cpp updated: 1.9 -> 1.10 --- Log message: Add non-const MachineBasicBlock::getParent() accessor method. MBBs start out as #-1. When a MBB is added to a MachineFunction, it gets the next available unique MBB number. If it is removed from a MachineFunction, it goes back to being #-1. --- Diffs of the changes: (+19 -0) Index: llvm/lib/CodeGen/MachineBasicBlock.cpp diff -u llvm/lib/CodeGen/MachineBasicBlock.cpp:1.9 llvm/lib/CodeGen/MachineBasicBlock.cpp:1.10 --- llvm/lib/CodeGen/MachineBasicBlock.cpp:1.9 Mon Feb 23 12:36:38 2004 +++ llvm/lib/CodeGen/MachineBasicBlock.cpp Wed May 12 16:35:22 2004 @@ -26,6 +26,25 @@ return &MachineFunction::get(getBasicBlock()->getParent()); } +MachineFunction *MachineBasicBlock::getParent() { + // Get the parent by getting the Function parent of the basic block, and + // getting the MachineFunction from it. + return &MachineFunction::get(getBasicBlock()->getParent()); +} + +// MBBs start out as #-1. When a MBB is added to a MachineFunction, it +// gets the next available unique MBB number. If it is removed from a +// MachineFunction, it goes back to being #-1. +void ilist_traits::addNodeToList (MachineBasicBlock* N) +{ + N->Number = N->getParent ()->getNextMBBNumber (); +} + +void ilist_traits::removeNodeFromList (MachineBasicBlock* N) +{ + N->Number = -1; +} + MachineInstr* ilist_traits::createNode() { From gaeke at cs.uiuc.edu Wed May 12 16:35:14 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Wed May 12 16:35:14 2004 Subject: [llvm-commits] CVS: llvm/include/llvm/CodeGen/MachineFunction.h Message-ID: <200405122135.QAA26340@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/CodeGen: MachineFunction.h updated: 1.32 -> 1.33 --- Log message: Add a NextMBBNumber field w/ incrementing accessor method, for function-level unique numbering of MBBs. --- Diffs of the changes: (+7 -0) Index: llvm/include/llvm/CodeGen/MachineFunction.h diff -u llvm/include/llvm/CodeGen/MachineFunction.h:1.32 llvm/include/llvm/CodeGen/MachineFunction.h:1.33 --- llvm/include/llvm/CodeGen/MachineFunction.h:1.32 Wed Feb 11 20:27:10 2004 +++ llvm/include/llvm/CodeGen/MachineFunction.h Wed May 12 16:35:21 2004 @@ -49,6 +49,9 @@ // Keep track of constants which are spilled to memory MachineConstantPool *ConstantPool; + // Function-level unique numbering for MachineBasicBlocks + int NextMBBNumber; + public: MachineFunction(const Function *Fn, const TargetMachine &TM); ~MachineFunction(); @@ -82,6 +85,10 @@ /// MachineFunctionInfo *getInfo() const { return MFInfo; } + /// getNextMBBNumber - Returns the next unique number to be assigned + /// to a MachineBasicBlock in this MachineFunction. + /// + int getNextMBBNumber() { return NextMBBNumber++; } /// print - Print out the MachineFunction in a format suitable for debugging /// to the specified stream. From gaeke at cs.uiuc.edu Wed May 12 16:35:20 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Wed May 12 16:35:20 2004 Subject: [llvm-commits] CVS: llvm/include/llvm/CodeGen/MachineBasicBlock.h Message-ID: <200405122135.QAA26333@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/CodeGen: MachineBasicBlock.h updated: 1.30 -> 1.31 --- Log message: Add a Number field w/ accessor method, for function-level unique numbering of MBBs. Add non-const MachineBasicBlock::getParent() accessor method. --- Diffs of the changes: (+8 -1) Index: llvm/include/llvm/CodeGen/MachineBasicBlock.h diff -u llvm/include/llvm/CodeGen/MachineBasicBlock.h:1.30 llvm/include/llvm/CodeGen/MachineBasicBlock.h:1.31 --- llvm/include/llvm/CodeGen/MachineBasicBlock.h:1.30 Sat May 1 20:04:52 2004 +++ llvm/include/llvm/CodeGen/MachineBasicBlock.h Wed May 12 16:35:20 2004 @@ -63,9 +63,11 @@ const BasicBlock *BB; std::vector Predecessors; std::vector Successors; + int Number; public: - MachineBasicBlock(const BasicBlock *bb = 0) : Prev(0), Next(0), BB(bb) { + MachineBasicBlock(const BasicBlock *bb = 0) : Prev(0), Next(0), BB(bb), + Number(-1) { Insts.parent = this; } ~MachineBasicBlock() {} @@ -78,6 +80,7 @@ /// getParent - Return the MachineFunction containing this basic block. /// const MachineFunction *getParent() const; + MachineFunction *getParent(); typedef ilist::iterator iterator; typedef ilist::const_iterator const_iterator; @@ -157,6 +160,10 @@ // Debugging methods. void dump() const; void print(std::ostream &OS) const; + + // MachineBasicBlocks are uniquely numbered at the function level + // (unless they're not in a MachineFunction yet) + int getNumber() const { return Number; } private: // Methods used to maintain doubly linked list of blocks... friend class ilist_traits; From brukman at cs.uiuc.edu Wed May 12 16:46:02 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 12 16:46:02 2004 Subject: [llvm-commits] CVS: llvm/docs/ReleaseNotes.html Message-ID: <200405122146.QAA00779@zion.cs.uiuc.edu> Changes in directory llvm/docs: ReleaseNotes.html updated: 1.178 -> 1.179 --- Log message: Break lines at 80 cols; eliminate extra space caused by a single

    tag on a line by itself. --- Diffs of the changes: (+36 -35) Index: llvm/docs/ReleaseNotes.html diff -u llvm/docs/ReleaseNotes.html:1.178 llvm/docs/ReleaseNotes.html:1.179 --- llvm/docs/ReleaseNotes.html:1.178 Mon May 10 09:28:09 2004 +++ llvm/docs/ReleaseNotes.html Wed May 12 16:46:05 2004 @@ -69,21 +69,17 @@

    -

    -This is the fourth public release of the LLVM compiler infrastructure. This +

    This is the fourth public release of the LLVM compiler infrastructure. This release primarily improves the performance of the code produced by all aspects of the LLVM compiler and adds some new features, though it does fix a few -bugs as well. -

    +bugs as well.

    -

    -At this time, LLVM is known to correctly compile and run all C & C++ SPEC -CPU2000 benchmarks, the Olden benchmarks, and the Ptrdist benchmarks. It has -also been used to compile many other programs. LLVM now also works with -a broad variety of C++ programs, though it has still received less testing than -the C front-end. -

    +

    At this time, LLVM is known to correctly compile and run all C & C++ +SPEC CPU2000 benchmarks, the Olden benchmarks, and the Ptrdist benchmarks. It +has also been used to compile many other programs. LLVM now also works +with a broad variety of C++ programs, though it has still received less testing +than the C front-end.

      -
    1. Minor configure bugs with -disable/enable-povray and -disable-spec
    2. -
    3. shell scripts output by gccld don't work if you change PATH
    4. +
    5. Minor configure bugs with +-disable/enable-povray and -disable-spec
    6. +
    7. shell scripts output by gccld don't +work if you change PATH
    @@ -208,17 +207,21 @@ breaks SSA form
  • [X86] JIT miscompiles unsigned short to floating point cast
  • -
  • [adce] Crash handling unreachable code that unwinds
  • -
  • [sparc] LLC can't emit 2 functions of -the same name, both having constant pools
  • -
  • [livevar] Live variables missed physical register use of aliased definition
  • +
  • [adce] Crash handling unreachable +code that unwinds
  • +
  • [sparc] LLC can't emit 2 functions +of the same name, both having constant pools
  • +
  • [livevar] Live variables missed +physical register use of aliased definition
  • Bugs in the C/C++ front-end:

      -
    1. [llvmgcc] Crash on use of undeclared enum type
    2. -
    3. [llvmgcc] Variable length array indexing miscompiled
    4. +
    5. [llvmgcc] Crash on use of undeclared +enum type
    6. +
    7. [llvmgcc] Variable length array +indexing miscompiled
    @@ -251,8 +254,10 @@
      -
    1. warnings compiling Stacker compiler on Mac OS X
    2. -
    3. Archive file reader doesn't understand abbreviated names in headers
    4. +
    5. warnings compiling Stacker compiler +on Mac OS X
    6. +
    7. Archive file reader doesn't +understand abbreviated names in headers
    @@ -278,13 +283,11 @@
    -

    -The following components of this LLVM release are either untested, known to be -broken or unreliable, or are in early development. These components should not -be relied on, and bugs should not be filed against them, but they may be useful -to some people. In particular, if you would like to work on one of these -components, please contact us on the llvmdev list. -

    +

    The following components of this LLVM release are either untested, known to +be broken or unreliable, or are in early development. These components should +not be relied on, and bugs should not be filed against them, but they may be +useful to some people. In particular, if you would like to work on one of these +components, please contact us on the llvmdev list.

    • The following passes are incomplete or buggy: -pgmdep, -memdep, @@ -348,11 +351,9 @@ }
    • -
    • -Initialization of global union variables can only be done -with the largest -union member. -
    • +
    • Initialization of global union variables can only be done with the largest union +member.
    • [llvm-gcc] Error when an implicitly external function is re-declared as static
    • @@ -644,7 +645,7 @@ src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01!" /> The LLVM Compiler Infrastructure
      - Last modified: $Date: 2004/05/10 14:28:09 $ + Last modified: $Date: 2004/05/12 21:46:05 $ From lattner at cs.uiuc.edu Wed May 12 16:48:03 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed May 12 16:48:03 2004 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/PHIElimination.cpp Message-ID: <200405122148.QAA07620@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: PHIElimination.cpp updated: 1.25 -> 1.26 --- Log message: Fix a really nasty bug from my changes on Monday to PHIElim. These changes broke obsequi and a lot of other things. It all boiled down to MBB being overloaded in an inner scope and me confusing it with the one in the outer scope. Ugh! --- Diffs of the changes: (+19 -11) Index: llvm/lib/CodeGen/PHIElimination.cpp diff -u llvm/lib/CodeGen/PHIElimination.cpp:1.25 llvm/lib/CodeGen/PHIElimination.cpp:1.26 --- llvm/lib/CodeGen/PHIElimination.cpp:1.25 Mon May 10 14:17:36 2004 +++ llvm/lib/CodeGen/PHIElimination.cpp Wed May 12 16:47:57 2004 @@ -70,21 +70,29 @@ const MRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo(); // VRegPHIUseCount - Keep track of the number of times each virtual register - // is used by PHI nodes in this block. + // is used by PHI nodes in successors of this block. DenseMap VRegPHIUseCount; VRegPHIUseCount.grow(MF.getSSARegMap()->getLastVirtReg()); + unsigned BBIsSuccOfPreds = 0; // Number of times MBB is a succ of preds + for (MachineBasicBlock::pred_iterator PI = MBB.pred_begin(), + E = MBB.pred_end(); PI != E; ++PI) + for (MachineBasicBlock::succ_iterator SI = (*PI)->succ_begin(), + E = (*PI)->succ_end(); SI != E; ++SI) { + BBIsSuccOfPreds += *SI == &MBB; + for (MachineBasicBlock::iterator BBI = (*SI)->begin(); BBI !=(*SI)->end() && + BBI->getOpcode() == TargetInstrInfo::PHI; ++BBI) + for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2) + VRegPHIUseCount[BBI->getOperand(i).getReg()]++; + } + // Get an iterator to the first instruction after the last PHI node (this may - // allso be the end of the basic block). While we are scanning the PHIs, + // also be the end of the basic block). While we are scanning the PHIs, // populate the VRegPHIUseCount map. MachineBasicBlock::iterator AfterPHIsIt = MBB.begin(); while (AfterPHIsIt != MBB.end() && - AfterPHIsIt->getOpcode() == TargetInstrInfo::PHI) { - MachineInstr *PHI = AfterPHIsIt; - for (unsigned i = 1, e = PHI->getNumOperands(); i < e; i += 2) - VRegPHIUseCount[PHI->getOperand(i).getReg()]++; + AfterPHIsIt->getOpcode() == TargetInstrInfo::PHI) ++AfterPHIsIt; // Skip over all of the PHI nodes... - } while (MBB.front().getOpcode() == TargetInstrInfo::PHI) { // Unlink the PHI node from the basic block... but don't delete the PHI yet @@ -148,7 +156,7 @@ // Adjust the VRegPHIUseCount map to account for the removal of this PHI // node. for (unsigned i = 1; i != MI->getNumOperands(); i += 2) - VRegPHIUseCount[MI->getOperand(i).getReg()]--; + VRegPHIUseCount[MI->getOperand(i).getReg()] -= BBIsSuccOfPreds; // Now loop over all of the incoming arguments, changing them to copy into // the IncomingReg register in the corresponding predecessor basic block. @@ -215,10 +223,10 @@ bool ValueIsLive = false; for (MachineBasicBlock::succ_iterator SI = opBlock.succ_begin(), E = opBlock.succ_end(); SI != E && !ValueIsLive; ++SI) { - MachineBasicBlock *MBB = *SI; + MachineBasicBlock *SuccMBB = *SI; // Is it alive in this successor? - unsigned SuccIdx = LV->getMachineBasicBlockIndex(MBB); + unsigned SuccIdx = LV->getMachineBasicBlockIndex(SuccMBB); if (SuccIdx < InRegVI.AliveBlocks.size() && InRegVI.AliveBlocks[SuccIdx]) { ValueIsLive = true; @@ -227,7 +235,7 @@ // Is it killed in this successor? for (unsigned i = 0, e = InRegVI.Kills.size(); i != e; ++i) - if (InRegVI.Kills[i].first == MBB) { + if (InRegVI.Kills[i].first == SuccMBB) { ValueIsLive = true; break; } From gaeke at cs.uiuc.edu Wed May 12 16:57:01 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Wed May 12 16:57:01 2004 Subject: [llvm-commits] CVS: llvm/include/llvm/CodeGen/MachineBasicBlock.h Message-ID: <200405122157.QAA08916@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/CodeGen: MachineBasicBlock.h updated: 1.31 -> 1.32 --- Log message: Fix a comment. --- Diffs of the changes: (+4 -2) Index: llvm/include/llvm/CodeGen/MachineBasicBlock.h diff -u llvm/include/llvm/CodeGen/MachineBasicBlock.h:1.31 llvm/include/llvm/CodeGen/MachineBasicBlock.h:1.32 --- llvm/include/llvm/CodeGen/MachineBasicBlock.h:1.31 Wed May 12 16:35:20 2004 +++ llvm/include/llvm/CodeGen/MachineBasicBlock.h Wed May 12 16:57:23 2004 @@ -161,8 +161,10 @@ void dump() const; void print(std::ostream &OS) const; - // MachineBasicBlocks are uniquely numbered at the function level - // (unless they're not in a MachineFunction yet) + /// getNumber - MachineBasicBlocks are uniquely numbered at the function + /// level, unless they're not in a MachineFunction yet, in which case this + /// will return -1. + /// int getNumber() const { return Number; } private: // Methods used to maintain doubly linked list of blocks... From brukman at cs.uiuc.edu Wed May 12 18:53:02 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 12 18:53:02 2004 Subject: [llvm-commits] CVS: llvm-www/ProjectsWithLLVM/index.html Message-ID: <200405122353.SAA21827@zion.cs.uiuc.edu> Changes in directory llvm-www/ProjectsWithLLVM: index.html updated: 1.12 -> 1.13 --- Log message: * Mention that Jello (which is the LLVM JIT) is now part of lli. * Reduce extraneous space caused by placing

      and

      on lines by themselves --- Diffs of the changes: (+36 -49) Index: llvm-www/ProjectsWithLLVM/index.html diff -u llvm-www/ProjectsWithLLVM/index.html:1.12 llvm-www/ProjectsWithLLVM/index.html:1.13 --- llvm-www/ProjectsWithLLVM/index.html:1.12 Wed May 12 16:06:52 2004 +++ llvm-www/ProjectsWithLLVM/index.html Wed May 12 18:53:24 2004 @@ -85,13 +85,13 @@ compilation and execution details are taken care of by LLVM.

      Further information about XPS can be obtained at http://extprosys.sourceforge.net/. This -information is somewhat dated but may provide an overview. XPS is getting a new -home on the Internet soon. We'll update this link when its available. -

      +href="http://extprosys.sourceforge.net/">http://extprosys.sourceforge.net/. +This information is somewhat dated but may provide an overview. XPS is getting +a new home on the Internet soon. We'll update this link when its available.

      -
      CS497YYZ: Hot Topics in Operating Systems (Fall 2003)
      +
      CS497YYZ: Hot Topics in Operating Systems (Fall +2003)
      @@ -138,26 +138,22 @@ Brian Fahs
    -

    -"As every modern computer user has experienced, software updates and upgrades -frequently require programs and sometimes the entire operating system to be -restarted. This can be a painful and annoying experience. What if this common -annoyance could be avoided completely or at least significantly reduced? Imagine -only rebooting your system when you wanted to shut your computer down or only -closing an application when you wanted rather than when an update occurs. The -purpose of this project is to investigate the potential of performing dynamic -patching of executables and create a patching tool capable of automatically -generating patches and applying them to applications that are already -running. This project should answer questions like: How can dynamic updating be -performed? What type of analysis is required? Can this analysis be effectively -automated? What can be updated in the running executable (e.g., algorithms, -organization, data, etc.)?" -

    +

    "As every modern computer user has experienced, software updates and +upgrades frequently require programs and sometimes the entire operating system +to be restarted. This can be a painful and annoying experience. What if this +common annoyance could be avoided completely or at least significantly reduced? +Imagine only rebooting your system when you wanted to shut your computer down or +only closing an application when you wanted rather than when an update occurs. +The purpose of this project is to investigate the potential of performing +dynamic patching of executables and create a patching tool capable of +automatically generating patches and applying them to applications that are +already running. This project should answer questions like: How can dynamic +updating be performed? What type of analysis is required? Can this analysis be +effectively automated? What can be updated in the running executable (e.g., +algorithms, organization, data, etc.)?"

    -

    -Project report: PS, -PDF -

    +

    Project report: PS, PDF

    @@ -181,25 +177,22 @@ Joel Stanley, Bill Wendling -

    -"In this report we present implementation details, empirical performance data, -and notable modifications to an algorithm for PRE based on [the 1999 TOPLAS -SSAPRE paper]. In [the 1999 TOPLAS SSAPRE paper], a particular realization of -PRE, known as SSAPRE, is described, which is more efficient than traditional PRE -implementations because it relies on useful properties of Static +

    "In this report we present implementation details, empirical performance +data, and notable modifications to an algorithm for PRE based on [the 1999 +TOPLAS SSAPRE paper]. In [the 1999 TOPLAS SSAPRE paper], a particular +realization of PRE, known as SSAPRE, is described, which is more efficient than +traditional PRE implementations because it relies on useful properties of Static Single-Assignment (SSA) form to perform dataflow analysis in a much more sparse manner than the traditional bit-vector-based approach. Our implementation is specific to a SSA-based compiler infrastructure known as LLVM (Low-Level Virtual -Machine)." -

    +Machine)."

    -

    -Project report: PS, -PDF -

    +

    Project report: PS, PDF

    -
    CS497CZ: Dynamic Translation and Optimization (Spring 2002)
    +
    CS497CZ: Dynamic Translation and Optimization +(Spring 2002)
    @@ -211,8 +204,7 @@ Brian Gaeke -

    -"We present the design and implementation of Jello, a retargetable +

    "We present the design and implementation of Jello, a retargetable Just-In-Time (JIT) compiler for the Intel IA32 architecture. The input to Jello is a C program statically compiled to Low-Level Virtual Machine (LLVM) bytecode. Jello takes advantage of the features of the LLVM bytecode representation to @@ -224,17 +216,12 @@ target-independent, making the JIT easily retargetable to new platforms without changing the code generator. Jello's ultimate goal is to provide a flexible host for future research in runtime optimization for programs written in -languages which are traditionally compiled statically." -

    - -

    -Note that Jello eventually evolved into the current LLVM JIT. -

    +languages which are traditionally compiled statically."

    -

    -Project report: PS, -PDF -

    +

    Note that Jello eventually evolved into the current LLVM JIT, which is part +of the tool lli.

    +

    Project report: PS, PDF

    From brukman at cs.uiuc.edu Wed May 12 19:24:02 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 12 19:24:02 2004 Subject: [llvm-commits] CVS: llvm/docs/Stacker.html Message-ID: <200405130024.TAA07786@zion.cs.uiuc.edu> Changes in directory llvm/docs: Stacker.html updated: 1.10 -> 1.11 --- Log message: * Use stylesheets for table borders so we factor out the formatting and can adjust it much easier. Also changed border to gray to fit into the current color scheme. * Convert < and > to < and >, respectively. * Wrap long lines at 80 cols --- Diffs of the changes: (+345 -338) Index: llvm/docs/Stacker.html diff -u llvm/docs/Stacker.html:1.10 llvm/docs/Stacker.html:1.11 --- llvm/docs/Stacker.html:1.10 Wed May 12 14:52:00 2004 +++ llvm/docs/Stacker.html Wed May 12 19:24:43 2004 @@ -4,6 +4,10 @@ Stacker: An Example Of Using LLVM + @@ -509,330 +513,331 @@
    - - - +
    Definition Of Operation Of Built In Words
    LOGICAL OPERATIONS
    + + - - - - - - - - - + + + + + + + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - - - - - - + + + + + + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - - - - - - + + + + + + + + - - - - + + + - - - - + + + - - - - + + + - - - - - - - - - + + + + + + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1051,7 +1058,7 @@ ################################################################################ # Utility definitions ################################################################################ -: print >d CR ; +: print >d CR ; : it_is_a_prime TRUE ; : it_is_not_a_prime FALSE ; : continue_loop TRUE ; @@ -1061,10 +1068,10 @@ # This definition tries an actual division of a candidate prime number. It # determines whether the division loop on this candidate should continue or # not. -# STACK<: +# STACK<: # div - the divisor to try # p - the prime number we are working on -# STACK>: +# STACK>: # cont - should we continue the loop ? # div - the next divisor to try # p - the prime number we are working on @@ -1090,7 +1097,7 @@ # cont - should we continue the loop (ignored)? # div - the divisor to try # p - the prime number we are working on -# STACK>: +# STACK>: # cont - should we continue the loop ? # div - the next divisor to try # p - the prime number we are working on @@ -1115,9 +1122,9 @@ # definition which returns a loop continuation value (which we also seed with # the value 1). After the loop, we check the divisor. If it decremented all # the way to zero then we found a prime, otherwise we did not find one. -# STACK<: +# STACK<: # p - the prime number to check -# STACK>: +# STACK>: # yn - boolean indicating if its a prime or not # p - the prime number checked ################################################################################ @@ -1138,18 +1145,18 @@ ################################################################################ # This definition determines if the number on the top of the stack is a prime -# or not. It does this by testing if the value is degenerate (<= 3) and +# or not. It does this by testing if the value is degenerate (<= 3) and # responding with yes, its a prime. Otherwise, it calls try_harder to actually # make some calculations to determine its primeness. -# STACK<: +# STACK<: # p - the prime number to check -# STACK>: +# STACK>: # yn - boolean indicating if its a prime or not # p - the prime number checked ################################################################################ : is_prime DUP ( save the prime number ) - 3 >= IF ( see if its <= 3 ) + 3 >= IF ( see if its <= 3 ) it_is_a_prime ( its <= 3 just indicate its prime ) ELSE try_harder ( have to do a little more work ) @@ -1159,11 +1166,11 @@ ################################################################################ # This definition is called when it is time to exit the program, after we have # found a sufficiently large number of primes. -# STACK<: ignored -# STACK>: exits +# STACK<: ignored +# STACK>: exits ################################################################################ : done - "Finished" >s CR ( say we are finished ) + "Finished" >s CR ( say we are finished ) 0 EXIT ( exit nicely ) ; @@ -1174,14 +1181,14 @@ # If it is a prime, it prints it. Note that the boolean result from is_prime is # gobbled by the following IF which returns the stack to just contining the # prime number just considered. -# STACK<: +# STACK<: # p - one less than the prime number to consider -# STACK> +# STAC>K # p+1 - the prime number considered ################################################################################ : consider_prime DUP ( save the prime number to consider ) - 1000000 < IF ( check to see if we are done yet ) + 1000000 < IF ( check to see if we are done yet ) done ( we are done, call "done" ) ENDIF ++ ( increment to next prime number ) @@ -1195,11 +1202,11 @@ # This definition starts at one, prints it out and continues into a loop calling # consider_prime on each iteration. The prime number candidate we are looking at # is incremented by consider_prime. -# STACK<: empty -# STACK>: empty +# STACK<: empty +# STACK>: empty ################################################################################ : find_primes - "Prime Numbers: " >s CR ( say hello ) + "Prime Numbers: " >s CR ( say hello ) DROP ( get rid of that pesky string ) 1 ( stoke the fires ) print ( print the first one, we know its prime ) @@ -1212,17 +1219,17 @@ # ################################################################################ : say_yes - >d ( Print the prime number ) + >d ( Print the prime number ) " is prime." ( push string to output ) - >s ( output it ) + >s ( output it ) CR ( print carriage return ) DROP ( pop string ) ; : say_no - >d ( Print the prime number ) + >d ( Print the prime number ) " is NOT prime." ( push string to put out ) - >s ( put out the string ) + >s ( put out the string ) CR ( print carriage return ) DROP ( pop string ) ; @@ -1230,10 +1237,10 @@ ################################################################################ # This definition processes a single command line argument and determines if it # is a prime number or not. -# STACK<: +# STACK<: # n - number of arguments # arg1 - the prime numbers to examine -# STACK>: +# STACK>: # n-1 - one less than number of arguments # arg2 - we processed one argument ################################################################################ @@ -1250,7 +1257,7 @@ ################################################################################ # The MAIN program just prints a banner and processes its arguments. -# STACK<: +# STACK<: # n - number of arguments # ... - the arguments ################################################################################ @@ -1262,13 +1269,13 @@ ################################################################################ # The MAIN program just prints a banner and processes its arguments. -# STACK<: arguments +# STACK<: arguments ################################################################################ : MAIN NIP ( get rid of the program name ) -- ( reduce number of arguments ) DUP ( save the arg counter ) - 1 <= IF ( See if we got an argument ) + 1 <= IF ( See if we got an argument ) process_arguments ( tell user if they are prime ) ELSE find_primes ( see how many we can find ) @@ -1402,7 +1409,7 @@ Reid Spencer
    LLVM Compiler Infrastructure
    - Last modified: $Date: 2004/05/12 19:52:00 $ + Last modified: $Date: 2004/05/13 00:24:43 $ From brukman at cs.uiuc.edu Wed May 12 19:37:02 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed May 12 19:37:02 2004 Subject: [llvm-commits] CVS: llvm/docs/Stacker.html Message-ID: <200405130037.TAA19475@zion.cs.uiuc.edu> Changes in directory llvm/docs: Stacker.html updated: 1.11 -> 1.12 --- Log message: Insert spacing between the table and the next section. --- Diffs of the changes: (+3 -2) Index: llvm/docs/Stacker.html diff -u llvm/docs/Stacker.html:1.11 llvm/docs/Stacker.html:1.12 --- llvm/docs/Stacker.html:1.11 Wed May 12 19:24:43 2004 +++ llvm/docs/Stacker.html Wed May 12 19:37:23 2004 @@ -6,7 +6,7 @@ @@ -1032,6 +1032,7 @@ to see instantly the net effect of the definition.
    Definition Of Operation Of Built In Words
    LOGICAL OPERATIONS
    WordNameOperationDescription
    <LTw1 w2 -- bTwo values (w1 and w2) are popped off the stack and + WordNameOperationDescription
    <LTw1 w2 -- bTwo values (w1 and w2) are popped off the stack and compared. If w1 is less than w2, TRUE is pushed back on the stack, otherwise FALSE is pushed back on the stack.
    >GTw1 w2 -- bTwo values (w1 and w2) are popped off the stack and +
    >GTw1 w2 -- bTwo values (w1 and w2) are popped off the stack and compared. If w1 is greater than w2, TRUE is pushed back on the stack, otherwise FALSE is pushed back on the stack.
    >=GEw1 w2 -- bTwo values (w1 and w2) are popped off the stack and +
    >=GEw1 w2 -- bTwo values (w1 and w2) are popped off the stack and compared. If w1 is greater than or equal to w2, TRUE is pushed back on the stack, otherwise FALSE is pushed back on the stack.
    <=LEw1 w2 -- bTwo values (w1 and w2) are popped off the stack and +
    <=LEw1 w2 -- bTwo values (w1 and w2) are popped off the stack and compared. If w1 is less than or equal to w2, TRUE is pushed back on the stack, otherwise FALSE is pushed back on the stack.
    =EQw1 w2 -- bTwo values (w1 and w2) are popped off the stack and +
    =EQw1 w2 -- bTwo values (w1 and w2) are popped off the stack and compared. If w1 is equal to w2, TRUE is pushed back on the stack, otherwise FALSE is pushed back
    <>NEw1 w2 -- bTwo values (w1 and w2) are popped off the stack and +
    <>NEw1 w2 -- bTwo values (w1 and w2) are popped off the stack and compared. If w1 is equal to w2, TRUE is pushed back on the stack, otherwise FALSE is pushed back
    FALSEFALSE -- bThe boolean value FALSE (0) is pushed on to the stack.
    TRUETRUE -- bThe boolean value TRUE (-1) is pushed on to the stack.
    FALSEFALSE -- bThe boolean value FALSE (0) is pushed on to the stack.
    TRUETRUE -- bThe boolean value TRUE (-1) is pushed on to the stack.
    BITWISE OPERATORS
    WordNameOperationDescription
    <<SHLw1 w2 -- w1<<w2Two values (w1 and w2) are popped off the stack. The w2 + WordNameOperationDescription
    <<SHLw1 w2 -- w1<<w2Two values (w1 and w2) are popped off the stack. The w2 operand is shifted left by the number of bits given by the w1 operand. The result is pushed back to the stack.
    >>SHRw1 w2 -- w1>>w2Two values (w1 and w2) are popped off the stack. The w2 +
    >>SHRw1 w2 -- w1>>w2Two values (w1 and w2) are popped off the stack. The w2 operand is shifted right by the number of bits given by the w1 operand. The result is pushed back to the stack.
    ORORw1 w2 -- w2|w1Two values (w1 and w2) are popped off the stack. The values +
    ORORw1 w2 -- w2|w1Two values (w1 and w2) are popped off the stack. The values are bitwise OR'd together and pushed back on the stack. This is not a logical OR. The sequence 1 2 OR yields 3 not 1.
    ANDANDw1 w2 -- w2&w1Two values (w1 and w2) are popped off the stack. The values +
    ANDANDw1 w2 -- w2&w1Two values (w1 and w2) are popped off the stack. The values are bitwise AND'd together and pushed back on the stack. This is not a logical AND. The sequence 1 2 AND yields 0 not 1.
    XORXORw1 w2 -- w2^w1Two values (w1 and w2) are popped off the stack. The values +
    XORXORw1 w2 -- w2^w1Two values (w1 and w2) are popped off the stack. The values are bitwise exclusive OR'd together and pushed back on the stack. For example, The sequence 1 3 XOR yields 2.
    ARITHMETIC OPERATORS
    WordNameOperationDescription
    ABSABSw -- |w|One value s popped off the stack; its absolute value is computed + WordNameOperationDescription
    ABSABSw -- |w|One value s popped off the stack; its absolute value is computed and then pushed on to the stack. If w1 is -1 then w2 is 1. If w1 is 1 then w2 is also 1.
    NEGNEGw -- -wOne value is popped off the stack which is negated and then +
    NEGNEGw -- -wOne value is popped off the stack which is negated and then pushed back on to the stack. If w1 is -1 then w2 is 1. If w1 is 1 then w2 is -1.
    + ADDw1 w2 -- w2+w1Two values are popped off the stack. Their sum is pushed back +
    + ADDw1 w2 -- w2+w1Two values are popped off the stack. Their sum is pushed back on to the stack
    - SUBw1 w2 -- w2-w1Two values are popped off the stack. Their difference is pushed back +
    - SUBw1 w2 -- w2-w1Two values are popped off the stack. Their difference is pushed back on to the stack
    * MULw1 w2 -- w2*w1Two values are popped off the stack. Their product is pushed back +
    * MULw1 w2 -- w2*w1Two values are popped off the stack. Their product is pushed back on to the stack
    / DIVw1 w2 -- w2/w1Two values are popped off the stack. Their quotient is pushed back +
    / DIVw1 w2 -- w2/w1Two values are popped off the stack. Their quotient is pushed back on to the stack
    MODMODw1 w2 -- w2%w1Two values are popped off the stack. Their remainder after division +
    MODMODw1 w2 -- w2%w1Two values are popped off the stack. Their remainder after division of w1 by w2 is pushed back on to the stack
    */ STAR_SLAHw1 w2 w3 -- (w3*w2)/w1Three values are popped off the stack. The product of w1 and w2 is +
    */ STAR_SLAHw1 w2 w3 -- (w3*w2)/w1Three values are popped off the stack. The product of w1 and w2 is divided by w3. The result is pushed back on to the stack.
    ++ INCRw -- w+1One value is popped off the stack. It is incremented by one and then +
    ++ INCRw -- w+1One value is popped off the stack. It is incremented by one and then pushed back on to the stack.
    -- DECRw -- w-1One value is popped off the stack. It is decremented by one and then +
    -- DECRw -- w-1One value is popped off the stack. It is decremented by one and then pushed back on to the stack.
    MINMINw1 w2 -- (w2<w1?w2:w1)Two values are popped off the stack. The larger one is pushed back +
    MINMINw1 w2 -- (w2<w1?w2:w1)Two values are popped off the stack. The larger one is pushed back on to the stack.
    MAXMAXw1 w2 -- (w2>w1?w2:w1)Two values are popped off the stack. The larger value is pushed back +
    MAXMAXw1 w2 -- (w2>w1?w2:w1)Two values are popped off the stack. The larger value is pushed back on to the stack.
    STACK MANIPULATION OPERATORS
    WordNameOperationDescription
    DROPDROPw -- One value is popped off the stack.
    DROP2DROP2w1 w2 -- Two values are popped off the stack.
    NIPNIPw1 w2 -- w2The second value on the stack is removed from the stack. That is, + WordNameOperationDescription
    DROPDROPw -- One value is popped off the stack.
    DROP2DROP2w1 w2 -- Two values are popped off the stack.
    NIPNIPw1 w2 -- w2The second value on the stack is removed from the stack. That is, a value is popped off the stack and retained. Then a second value is popped and the retained value is pushed.
    NIP2NIP2w1 w2 w3 w4 -- w3 w4The third and fourth values on the stack are removed from it. That is, +
    NIP2NIP2w1 w2 w3 w4 -- w3 w4The third and fourth values on the stack are removed from it. That is, two values are popped and retained. Then two more values are popped and the two retained values are pushed back on.
    DUPDUPw1 -- w1 w1One value is popped off the stack. That value is then pushed on to +
    DUPDUPw1 -- w1 w1One value is popped off the stack. That value is then pushed on to the stack twice to duplicate the top stack vaue.
    DUP2DUP2w1 w2 -- w1 w2 w1 w2The top two values on the stack are duplicated. That is, two vaues +
    DUP2DUP2w1 w2 -- w1 w2 w1 w2The top two values on the stack are duplicated. That is, two vaues are popped off the stack. They are alternately pushed back on the stack twice each.
    SWAPSWAPw1 w2 -- w2 w1The top two stack items are reversed in their order. That is, two +
    SWAPSWAPw1 w2 -- w2 w1The top two stack items are reversed in their order. That is, two values are popped off the stack and pushed back on to the stack in the opposite order they were popped.
    SWAP2SWAP2w1 w2 w3 w4 -- w3 w4 w2 w1The top four stack items are swapped in pairs. That is, two values +
    SWAP2SWAP2w1 w2 w3 w4 -- w3 w4 w2 w1The top four stack items are swapped in pairs. That is, two values are popped and retained. Then, two more values are popped and retained. The values are pushed back on to the stack in the reverse order but in pairs.
    OVEROVERw1 w2-- w1 w2 w1Two values are popped from the stack. They are pushed back +
    OVEROVERw1 w2-- w1 w2 w1Two values are popped from the stack. They are pushed back on to the stack in the order w1 w2 w1. This seems to cause the top stack element to be duplicated "over" the next value.
    OVER2OVER2w1 w2 w3 w4 -- w1 w2 w3 w4 w1 w2The third and fourth values on the stack are replicated on to the +
    OVER2OVER2w1 w2 w3 w4 -- w1 w2 w3 w4 w1 w2The third and fourth values on the stack are replicated on to the top of the stack
    ROTROTw1 w2 w3 -- w2 w3 w1The top three values are rotated. That is, three value are popped +
    ROTROTw1 w2 w3 -- w2 w3 w1The top three values are rotated. That is, three value are popped off the stack. They are pushed back on to the stack in the order w1 w3 w2.
    ROT2ROT2w1 w2 w3 w4 w5 w6 -- w3 w4 w5 w6 w1 w2Like ROT but the rotation is done using three pairs instead of +
    ROT2ROT2w1 w2 w3 w4 w5 w6 -- w3 w4 w5 w6 w1 w2Like ROT but the rotation is done using three pairs instead of three singles.
    RROTRROTw1 w2 w3 -- w2 w3 w1Reverse rotation. Like ROT, but it rotates the other way around. +
    RROTRROTw1 w2 w3 -- w2 w3 w1Reverse rotation. Like ROT, but it rotates the other way around. Essentially, the third element on the stack is moved to the top of the stack.
    RROT2RROT2w1 w2 w3 w4 w5 w6 -- w3 w4 w5 w6 w1 w2Double reverse rotation. Like RROT but the rotation is done using +
    RROT2RROT2w1 w2 w3 w4 w5 w6 -- w3 w4 w5 w6 w1 w2Double reverse rotation. Like RROT but the rotation is done using three pairs instead of three singles. The fifth and sixth stack elements are moved to the first and second positions
    TUCKTUCKw1 w2 -- w2 w1 w2Similar to OVER except that the second operand is being +
    TUCKTUCKw1 w2 -- w2 w1 w2Similar to OVER except that the second operand is being replicated. Essentially, the first operand is being "tucked" in between two instances of the second operand. Logically, two values are popped off the stack. They are placed back on the stack in the order w2 w1 w2.
    TUCK2TUCK2w1 w2 w3 w4 -- w3 w4 w1 w2 w3 w4Like TUCK but a pair of elements is tucked over two pairs. +
    TUCK2TUCK2w1 w2 w3 w4 -- w3 w4 w1 w2 w3 w4Like TUCK but a pair of elements is tucked over two pairs. That is, the top two elements of the stack are duplicated and inserted into the stack at the fifth and positions.
    PICKPICKx0 ... Xn n -- x0 ... Xn x0The top of the stack is used as an index into the remainder of +
    PICKPICKx0 ... Xn n -- x0 ... Xn x0The top of the stack is used as an index into the remainder of the stack. The element at the nth position replaces the index (top of stack). This is useful for cycling through a set of values. Note that indexing is zero based. So, if n=0 then you get the second item on the stack. If n=1 you get the third, etc. Note also that the index is replaced by the n'th value.
    SELECTSELECTm n X0..Xm Xm+1 .. Xn -- XmThis is like PICK but the list is removed and you need to specify +
    SELECTSELECTm n X0..Xm Xm+1 .. Xn -- XmThis is like PICK but the list is removed and you need to specify both the index and the size of the list. Careful with this one, the wrong value for n can blow away a huge amount of the stack.
    ROLLROLLx0 x1 .. xn n -- x1 .. xn x0Not Implemented. This one has been left as an exercise to +
    ROLLROLLx0 x1 .. xn n -- x1 .. xn x0Not Implemented. This one has been left as an exercise to the student. See Exercise. ROLL requires a value, "n", to be on the top of the stack. This value specifies how far into the stack to "roll". The n'th value is moved (not @@ -844,23 +849,23 @@
    MEMORY OPERATORS
    WordNameOperationDescription
    MALLOCMALLOCw1 -- pOne value is popped off the stack. The value is used as the size + WordNameOperationDescription
    MALLOCMALLOCw1 -- pOne value is popped off the stack. The value is used as the size of a memory block to allocate. The size is in bytes, not words. The memory allocation is completed and the address of the memory block is pushed on to the stack.
    FREEFREEp -- One pointer value is popped off the stack. The value should be +
    FREEFREEp -- One pointer value is popped off the stack. The value should be the address of a memory block created by the MALLOC operation. The associated memory block is freed. Nothing is pushed back on the stack. Many bugs can be created by attempting to FREE something @@ -872,20 +877,20 @@ the stack (for the FREE at the end) and that every use of the pointer is preceded by a DUP to retain the copy for FREE.
    GETGETw1 p -- w2 pAn integer index and a pointer to a memory block are popped of +
    GETGETw1 p -- w2 pAn integer index and a pointer to a memory block are popped of the block. The index is used to index one byte from the memory block. That byte value is retained, the pointer is pushed again and the retained value is pushed. Note that the pointer value s essentially retained in its position so this doesn't count as a "use ptr" in the FREE idiom.
    PUTPUTw1 w2 p -- p An integer value is popped of the stack. This is the value to +
    PUTPUTw1 w2 p -- p An integer value is popped of the stack. This is the value to be put into a memory block. Another integer value is popped of the stack. This is the indexed byte in the memory block. A pointer to the memory block is popped off the stack. The @@ -897,31 +902,31 @@
    CONTROL FLOW OPERATORS
    WordNameOperationDescription
    RETURNRETURN -- The currently executing definition returns immediately to its caller. + WordNameOperationDescription
    RETURNRETURN -- The currently executing definition returns immediately to its caller. Note that there is an implicit RETURN at the end of each definition, logically located at the semi-colon. The sequence RETURN ; is valid but redundant.
    EXITEXITw1 -- A return value for the program is popped off the stack. The program is +
    EXITEXITw1 -- A return value for the program is popped off the stack. The program is then immediately terminated. This is normally an abnormal exit from the program. For a normal exit (when MAIN finishes), the exit code will always be zero in accordance with UNIX conventions.
    RECURSERECURSE -- The currently executed definition is called again. This operation is +
    RECURSERECURSE -- The currently executed definition is called again. This operation is needed since the definition of a word doesn't exist until the semi colon is reacher. Attempting something like:
    : recurser recurser ;
    will yield and error saying that @@ -929,24 +934,24 @@ to:
    : recurser RECURSE ;
    IF (words...) ENDIFIF (words...) ENDIFb -- A boolean value is popped of the stack. If it is non-zero then the "words..." +
    IF (words...) ENDIFIF (words...) ENDIFb -- A boolean value is popped of the stack. If it is non-zero then the "words..." are executed. Otherwise, execution continues immediately following the ENDIF.
    IF (words...) ELSE (words...) ENDIFIF (words...) ELSE (words...) ENDIFb -- A boolean value is popped of the stack. If it is non-zero then the "words..." +
    IF (words...) ELSE (words...) ENDIFIF (words...) ELSE (words...) ENDIFb -- A boolean value is popped of the stack. If it is non-zero then the "words..." between IF and ELSE are executed. Otherwise the words between ELSE and ENDIF are executed. In either case, after the (words....) have executed, execution continues immediately following the ENDIF.
    WHILE (words...) ENDWHILE (words...) ENDb -- b The boolean value on the top of the stack is examined. If it is non-zero then the +
    WHILE (words...) ENDWHILE (words...) ENDb -- b The boolean value on the top of the stack is examined. If it is non-zero then the "words..." between WHILE and END are executed. Execution then begins again at the WHILE where another boolean is popped off the stack. To prevent this operation from eating up the entire stack, you should push on to the stack (just before the END) a boolean value that indicates @@ -964,63 +969,65 @@
    INPUT & OUTPUT OPERATORS
    WordNameOperationDescription
    SPACESPACE -- A space character is put out. There is no stack effect.
    TABTAB -- A tab character is put out. There is no stack effect.
    CRCR -- A carriage return character is put out. There is no stack effect.
    >sOUT_STR -- A string pointer is popped from the stack. It is put out.
    >dOUT_STR -- A value is popped from the stack. It is put out as a decimal integer.
    >cOUT_CHR -- A value is popped from the stack. It is put out as an ASCII character.
    <sIN_STR -- s A string is read from the input via the scanf(3) format string " %as". The - resulting string is pushed on to the stack.
    <dIN_STR -- w An integer is read from the input via the scanf(3) format string " %d". The - resulting value is pushed on to the stack
    <cIN_CHR -- w A single character is read from the input via the scanf(3) format string - " %c". The value is converted to an integer and pushed on to the stack.
    DUMPDUMP -- The stack contents are dumped to standard output. This is useful for + WordNameOperationDescription
    SPACESPACE -- A space character is put out. There is no stack effect.
    TABTAB -- A tab character is put out. There is no stack effect.
    CRCR -- A carriage return character is put out. There is no stack effect.
    >sOUT_STR -- A string pointer is popped from the stack. It is put out.
    >dOUT_STR -- A value is popped from the stack. It is put out as a decimal + integer.
    >cOUT_CHR -- A value is popped from the stack. It is put out as an ASCII + character.
    <sIN_STR -- s A string is read from the input via the scanf(3) format string " %as". + The resulting string is pushed on to the stack.
    <dIN_STR -- w An integer is read from the input via the scanf(3) format string " %d". + The resulting value is pushed on to the stack
    <cIN_CHR -- w A single character is read from the input via the scanf(3) format string + " %c". The value is converted to an integer and pushed on to the stack.
    DUMPDUMP -- The stack contents are dumped to standard output. This is useful for debugging your definitions. Put DUMP at the beginning and end of a definition to see instantly the net effect of the definition.
    +
    @@ -1409,7 +1410,7 @@ Reid Spencer
    LLVM Compiler Infrastructure
    - Last modified: $Date: 2004/05/13 00:24:43 $ + Last modified: $Date: 2004/05/13 00:37:23 $ From llvm at cs.uiuc.edu Wed May 12 22:40:01 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Wed May 12 22:40:01 2004 Subject: [llvm-commits] CVS: llvm/docs/HistoricalNotes/2001-04-16-DynamicCompilation.txt Message-ID: <200405130340.WAA11994@zion.cs.uiuc.edu> Changes in directory llvm/docs/HistoricalNotes: 2001-04-16-DynamicCompilation.txt updated: 1.1.1.1 -> 1.2 --- Log message: Reduce line length to about 80 chars. --- Diffs of the changes: (+43 -6) Index: llvm/docs/HistoricalNotes/2001-04-16-DynamicCompilation.txt diff -u llvm/docs/HistoricalNotes/2001-04-16-DynamicCompilation.txt:1.1.1.1 llvm/docs/HistoricalNotes/2001-04-16-DynamicCompilation.txt:1.2 --- llvm/docs/HistoricalNotes/2001-04-16-DynamicCompilation.txt:1.1.1.1 Wed Jun 6 15:29:03 2001 +++ llvm/docs/HistoricalNotes/2001-04-16-DynamicCompilation.txt Wed May 12 22:40:27 2004 @@ -1,12 +1,49 @@ By Chris: -LLVM has been designed with two primary goals in mind. First we strive to enable the best possible division of labor between static and dynamic compilers, and second, we need a flexible and powerful interface between these two complementary stages of compilation. We feel that providing a solution to these two goals will yield an excellent solution to the performance problem faced by modern architectures and programming languages. +LLVM has been designed with two primary goals in mind. First we strive to +enable the best possible division of labor between static and dynamic +compilers, and second, we need a flexible and powerful interface +between these two complementary stages of compilation. We feel that +providing a solution to these two goals will yield an excellent solution +to the performance problem faced by modern architectures and programming +languages. -A key insight into current compiler and runtime systems is that a compiler may fall in anywhere in a "continuum of compilation" to do its job. On one side, scripting languages statically compile nothing and dynamically compile (or equivalently, interpret) everything. On the far other side, traditional static compilers process everything statically and nothing dynamically. These approaches have typically been seen as a tradeoff between performance and portability. On a deeper level, however, there are two reasons that optimal system performance may be obtained by a system somewhere in between these two extremes: Dynamic application behavior and social constraints. +A key insight into current compiler and runtime systems is that a +compiler may fall in anywhere in a "continuum of compilation" to do its +job. On one side, scripting languages statically compile nothing and +dynamically compile (or equivalently, interpret) everything. On the far +other side, traditional static compilers process everything statically and +nothing dynamically. These approaches have typically been seen as a +tradeoff between performance and portability. On a deeper level, however, +there are two reasons that optimal system performance may be obtained by a +system somewhere in between these two extremes: Dynamic application +behavior and social constraints. -From a technical perspective, pure static compilation cannot ever give optimal performance in all cases, because applications have varying dynamic behavior that the static compiler cannot take into consideration. Even compilers that support profile guided optimization generate poor code in the real world, because using such optimization tunes that application to one particular usage pattern, whereas real programs (as opposed to benchmarks) often have several different usage patterns. +From a technical perspective, pure static compilation cannot ever give +optimal performance in all cases, because applications have varying dynamic +behavior that the static compiler cannot take into consideration. Even +compilers that support profile guided optimization generate poor code in +the real world, because using such optimization tunes that application +to one particular usage pattern, whereas real programs (as opposed to +benchmarks) often have several different usage patterns. -On a social level, static compilation is a very shortsighted solution to the performance problem. Instruction set architectures (ISAs) continuously evolve, and each implementation of an ISA (a processor) must choose a set of tradeoffs that make sense in the market context that it is designed for. With every new processor introduced, the vendor faces two fundamental problems: First, there is a lag time between when a processor is introduced to when compilers generate quality code for the architecture. Secondly, even when compilers catch up to the new architecture there is often a large body of legacy code that was compiled for previous generations and will not or can not be upgraded. Thus a large percentage of code running on a processor may be compiled quite sub-optimally for the current characteristics of the dynamic execution environment. - -For these reasons, LLVM has been designed from the beginning as a long-term solution to these problems. Its design allows the large body of platform independent, static, program optimizations currently in compilers to be reused unchanged in their current form. It also provides important static type information to enable powerful dynamic and link time optimizations to be performed quickly and efficiently. This combination enables an increase in effective system performance for real world environments. +On a social level, static compilation is a very shortsighted solution to +the performance problem. Instruction set architectures (ISAs) continuously +evolve, and each implementation of an ISA (a processor) must choose a set +of tradeoffs that make sense in the market context that it is designed for. +With every new processor introduced, the vendor faces two fundamental +problems: First, there is a lag time between when a processor is introduced +to when compilers generate quality code for the architecture. Secondly, +even when compilers catch up to the new architecture there is often a large +body of legacy code that was compiled for previous generations and will +not or can not be upgraded. Thus a large percentage of code running on a +processor may be compiled quite sub-optimally for the current +characteristics of the dynamic execution environment. +For these reasons, LLVM has been designed from the beginning as a long-term +solution to these problems. Its design allows the large body of platform +independent, static, program optimizations currently in compilers to be +reused unchanged in their current form. It also provides important static +type information to enable powerful dynamic and link time optimizations +to be performed quickly and efficiently. This combination enables an +increase in effective system performance for real world environments. From lattner at cs.uiuc.edu Thu May 13 02:40:01 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 13 02:40:01 2004 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Message-ID: <200405130740.CAA29861@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.251 -> 1.252 --- Log message: Substantially improve code generation for address exposed locals (aka fixed sized allocas in the entry block). Instead of generating code like this: entry: reg1024 = ESP+1234 ... (much later) *reg1024 = 17 Generate code that looks like this: entry: (no code generated) ... (much later) t = ESP+1234 *t = 17 The advantage being that we DRAMATICALLY reduce the register pressure for these silly temporaries (they were all being spilled to the stack, resulting in very silly code). This is actually a manual implementation of rematerialization :) I have a patch to fold the alloca address computation into loads & stores, which will make this much better still, but just getting this right took way too much time and I'm sleepy. --- Diffs of the changes: (+101 -64) Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.251 llvm/lib/Target/X86/InstSelectSimple.cpp:1.252 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.251 Wed May 12 11:35:04 2004 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Thu May 13 02:40:27 2004 @@ -86,6 +86,10 @@ // MBBMap - Mapping between LLVM BB -> Machine BB std::map MBBMap; + // AllocaMap - Mapping from fixed sized alloca instructions to the + // FrameIndex for the alloca. + std::map AllocaMap; + ISel(TargetMachine &tm) : TM(tm), F(0), BB(0) {} /// runOnFunction - Top level implementation of instruction selection for @@ -122,6 +126,7 @@ RegMap.clear(); MBBMap.clear(); + AllocaMap.clear(); F = 0; // We always build a machine code representation for the function return true; @@ -350,9 +355,7 @@ return F->getSSARegMap()->createVirtualRegister(RC); } - /// getReg - This method turns an LLVM value into a register number. This - /// is guaranteed to produce the same register number for a particular value - /// every time it is queried. + /// getReg - This method turns an LLVM value into a register number. /// unsigned getReg(Value &V) { return getReg(&V); } // Allow references unsigned getReg(Value *V) { @@ -361,36 +364,86 @@ return getReg(V, BB, It); } unsigned getReg(Value *V, MachineBasicBlock *MBB, - MachineBasicBlock::iterator IPt) { - // If this operand is a constant, emit the code to copy the constant into - // the register here... - // - if (Constant *C = dyn_cast(V)) { - unsigned Reg = makeAnotherReg(V->getType()); - copyConstantToRegister(MBB, IPt, C, Reg); - return Reg; - } else if (GlobalValue *GV = dyn_cast(V)) { - unsigned Reg = makeAnotherReg(V->getType()); - // Move the address of the global into the register - BuildMI(*MBB, IPt, X86::MOV32ri, 1, Reg).addGlobalAddress(GV); - return Reg; - } else if (CastInst *CI = dyn_cast(V)) { - // Do not emit noop casts at all. - if (getClassB(CI->getType()) == getClassB(CI->getOperand(0)->getType())) - return getReg(CI->getOperand(0), MBB, IPt); - } - - unsigned &Reg = RegMap[V]; - if (Reg == 0) { - Reg = makeAnotherReg(V->getType()); - RegMap[V] = Reg; - } + MachineBasicBlock::iterator IPt); - return Reg; - } + /// getFixedSizedAllocaFI - Return the frame index for a fixed sized alloca + /// that is to be statically allocated with the initial stack frame + /// adjustment. + unsigned getFixedSizedAllocaFI(AllocaInst *AI); }; } +/// dyn_castFixedAlloca - If the specified value is a fixed size alloca +/// instruction in the entry block, return it. Otherwise, return a null +/// pointer. +static AllocaInst *dyn_castFixedAlloca(Value *V) { + if (AllocaInst *AI = dyn_cast(V)) { + BasicBlock *BB = AI->getParent(); + if (isa(AI->getArraySize()) && BB ==&BB->getParent()->front()) + return AI; + } + return 0; +} + +/// getReg - This method turns an LLVM value into a register number. +/// +unsigned ISel::getReg(Value *V, MachineBasicBlock *MBB, + MachineBasicBlock::iterator IPt) { + // If this operand is a constant, emit the code to copy the constant into + // the register here... + // + if (Constant *C = dyn_cast(V)) { + unsigned Reg = makeAnotherReg(V->getType()); + copyConstantToRegister(MBB, IPt, C, Reg); + return Reg; + } else if (GlobalValue *GV = dyn_cast(V)) { + unsigned Reg = makeAnotherReg(V->getType()); + // Move the address of the global into the register + BuildMI(*MBB, IPt, X86::MOV32ri, 1, Reg).addGlobalAddress(GV); + return Reg; + } else if (CastInst *CI = dyn_cast(V)) { + // Do not emit noop casts at all. + if (getClassB(CI->getType()) == getClassB(CI->getOperand(0)->getType())) + return getReg(CI->getOperand(0), MBB, IPt); + } else if (AllocaInst *AI = dyn_castFixedAlloca(V)) { + // If the alloca address couldn't be folded into the instruction addressing, + // emit an explicit LEA as appropriate. + unsigned Reg = makeAnotherReg(V->getType()); + unsigned FI = getFixedSizedAllocaFI(AI); + addFrameReference(BuildMI(*MBB, IPt, X86::LEA32r, 4, Reg), FI); + return Reg; + } + + unsigned &Reg = RegMap[V]; + if (Reg == 0) { + Reg = makeAnotherReg(V->getType()); + RegMap[V] = Reg; + } + + return Reg; +} + +/// getFixedSizedAllocaFI - Return the frame index for a fixed sized alloca +/// that is to be statically allocated with the initial stack frame +/// adjustment. +unsigned ISel::getFixedSizedAllocaFI(AllocaInst *AI) { + // Already computed this? + std::map::iterator I = AllocaMap.lower_bound(AI); + if (I != AllocaMap.end() && I->first == AI) return I->second; + + const Type *Ty = AI->getAllocatedType(); + ConstantUInt *CUI = cast(AI->getArraySize()); + unsigned TySize = TM.getTargetData().getTypeSize(Ty); + TySize *= CUI->getValue(); // Get total allocated size... + unsigned Alignment = TM.getTargetData().getTypeAlignment(Ty); + + // Create a new stack object using the frame manager... + int FrameIdx = F->getFrameInfo()->CreateStackObject(TySize, Alignment); + AllocaMap.insert(I, std::make_pair(AI, FrameIdx)); + return FrameIdx; +} + + /// copyConstantToRegister - Output the instructions required to put the /// specified constant into the specified register. /// @@ -630,27 +683,24 @@ // If this is a constant or GlobalValue, we may have to insert code // into the basic block to compute it into a virtual register. - if (isa(Val) || isa(Val)) { - if (isa(Val)) { - // Because we don't want to clobber any values which might be in - // physical registers with the computation of this constant (which - // might be arbitrarily complex if it is a constant expression), - // just insert the computation at the top of the basic block. - MachineBasicBlock::iterator PI = PredMBB->begin(); - - // Skip over any PHI nodes though! - while (PI != PredMBB->end() && PI->getOpcode() == X86::PHI) - ++PI; - - ValReg = getReg(Val, PredMBB, PI); - } else { - // Simple constants get emitted at the end of the basic block, - // before any terminator instructions. We "know" that the code to - // move a constant into a register will never clobber any flags. - ValReg = getReg(Val, PredMBB, PredMBB->getFirstTerminator()); - } + if ((isa(Val) && !isa(Val)) || + isa(Val)) { + // Simple constants get emitted at the end of the basic block, + // before any terminator instructions. We "know" that the code to + // move a constant into a register will never clobber any flags. + ValReg = getReg(Val, PredMBB, PredMBB->getFirstTerminator()); } else { - ValReg = getReg(Val); + // Because we don't want to clobber any values which might be in + // physical registers with the computation of this constant (which + // might be arbitrarily complex if it is a constant expression), + // just insert the computation at the top of the basic block. + MachineBasicBlock::iterator PI = PredMBB->begin(); + + // Skip over any PHI nodes though! + while (PI != PredMBB->end() && PI->getOpcode() == X86::PHI) + ++PI; + + ValReg = getReg(Val, PredMBB, PI); } // Remember that we inserted a value for this PHI for this predecessor @@ -3582,25 +3632,12 @@ /// frame manager, otherwise do it the hard way. /// void ISel::visitAllocaInst(AllocaInst &I) { + if (dyn_castFixedAlloca(&I)) return; + // Find the data size of the alloca inst's getAllocatedType. const Type *Ty = I.getAllocatedType(); unsigned TySize = TM.getTargetData().getTypeSize(Ty); - // If this is a fixed size alloca in the entry block for the function, - // statically stack allocate the space. - // - if (ConstantUInt *CUI = dyn_cast(I.getArraySize())) { - if (I.getParent() == I.getParent()->getParent()->begin()) { - TySize *= CUI->getValue(); // Get total allocated size... - unsigned Alignment = TM.getTargetData().getTypeAlignment(Ty); - - // Create a new stack object using the frame manager... - int FrameIdx = F->getFrameInfo()->CreateStackObject(TySize, Alignment); - addFrameReference(BuildMI(BB, X86::LEA32r, 5, getReg(I)), FrameIdx); - return; - } - } - // Create a register to hold the temporary result of multiplying the type size // constant by the variable amount. unsigned TotalSizeReg = makeAnotherReg(Type::UIntTy); From lattner at cs.uiuc.edu Thu May 13 10:13:07 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 13 10:13:07 2004 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Message-ID: <200405131512.KAA32362@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.252 -> 1.253 --- Log message: Second half of my fixed-sized-alloca patch. This folds the LEA to compute the alloca address into common operations like loads/stores. In a simple testcase like this (which is just designed to excersize the alloca A, nothing more): int %test(int %X, bool %C) { %A = alloca int store int %X, int* %A store int* %A, int** %G br bool %C, label %T, label %F T: call int %test(int 1, bool false) %V = load int* %A ret int %V F: call int %test(int 123, bool true) %V2 = load int* %A ret int %V2 } We now generate: test: sub %ESP, 12 mov %EAX, DWORD PTR [%ESP + 16] mov %CL, BYTE PTR [%ESP + 20] *** mov DWORD PTR [%ESP + 8], %EAX mov %EAX, OFFSET G lea %EDX, DWORD PTR [%ESP + 8] mov DWORD PTR [%EAX], %EDX test %CL, %CL je .LBB2 # PC rel: F .LBB1: # T mov DWORD PTR [%ESP], 1 mov DWORD PTR [%ESP + 4], 0 call test *** mov %EAX, DWORD PTR [%ESP + 8] add %ESP, 12 ret .LBB2: # F mov DWORD PTR [%ESP], 123 mov DWORD PTR [%ESP + 4], 1 call test *** mov %EAX, DWORD PTR [%ESP + 8] add %ESP, 12 ret Instead of: test: sub %ESP, 20 mov %EAX, DWORD PTR [%ESP + 24] mov %CL, BYTE PTR [%ESP + 28] *** lea %EDX, DWORD PTR [%ESP + 16] *** mov DWORD PTR [%EDX], %EAX mov %EAX, OFFSET G mov DWORD PTR [%EAX], %EDX test %CL, %CL *** mov DWORD PTR [%ESP + 12], %EDX je .LBB2 # PC rel: F .LBB1: # T mov DWORD PTR [%ESP], 1 mov %EAX, 0 mov DWORD PTR [%ESP + 4], %EAX call test *** mov %EAX, DWORD PTR [%ESP + 12] *** mov %EAX, DWORD PTR [%EAX] add %ESP, 20 ret .LBB2: # F mov DWORD PTR [%ESP], 123 mov %EAX, 1 mov DWORD PTR [%ESP + 4], %EAX call test *** mov %EAX, DWORD PTR [%ESP + 12] *** mov %EAX, DWORD PTR [%EAX] add %ESP, 20 ret --- Diffs of the changes: (+179 -93) Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.252 llvm/lib/Target/X86/InstSelectSimple.cpp:1.253 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.252 Thu May 13 02:40:27 2004 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Thu May 13 10:12:43 2004 @@ -814,6 +814,25 @@ } +void ISel::getAddressingMode(Value *Addr, unsigned &BaseReg, unsigned &Scale, + unsigned &IndexReg, unsigned &Disp) { + BaseReg = 0; Scale = 1; IndexReg = 0; Disp = 0; + if (GetElementPtrInst *GEP = dyn_cast(Addr)) { + if (isGEPFoldable(BB, GEP->getOperand(0), GEP->op_begin()+1, GEP->op_end(), + BaseReg, Scale, IndexReg, Disp)) + return; + } else if (ConstantExpr *CE = dyn_cast(Addr)) { + if (CE->getOpcode() == Instruction::GetElementPtr) + if (isGEPFoldable(BB, CE->getOperand(0), CE->op_begin()+1, CE->op_end(), + BaseReg, Scale, IndexReg, Disp)) + return; + } + + // If it's not foldable, reset addr mode. + BaseReg = getReg(Addr); + Scale = 1; IndexReg = 0; Disp = 0; +} + // canFoldSetCCIntoBranchOrSelect - Return the setcc instruction if we can fold // it into the conditional branch or select instruction which is the only user // of the cc instruction. This is the case if the conditional branch is the @@ -1953,13 +1972,20 @@ Opcode = OpcodeTab[OperatorClass][Ty == Type::DoubleTy]; } - unsigned BaseReg, Scale, IndexReg, Disp; - getAddressingMode(cast(Op1)->getOperand(0), BaseReg, - Scale, IndexReg, Disp); - unsigned Op0r = getReg(Op0); - addFullAddress(BuildMI(BB, Opcode, 2, DestReg).addReg(Op0r), - BaseReg, Scale, IndexReg, Disp); + if (AllocaInst *AI = + dyn_castFixedAlloca(cast(Op1)->getOperand(0))) { + unsigned FI = getFixedSizedAllocaFI(AI); + addFrameReference(BuildMI(BB, Opcode, 5, DestReg).addReg(Op0r), FI); + + } else { + unsigned BaseReg, Scale, IndexReg, Disp; + getAddressingMode(cast(Op1)->getOperand(0), BaseReg, + Scale, IndexReg, Disp); + + addFullAddress(BuildMI(BB, Opcode, 5, DestReg).addReg(Op0r), + BaseReg, Scale, IndexReg, Disp); + } return; } @@ -1972,13 +1998,19 @@ assert(Ty == Type::FloatTy || Ty == Type::DoubleTy && "Unknown FP type!"); unsigned Opcode = Ty == Type::FloatTy ? X86::FSUBR32m : X86::FSUBR64m; - unsigned BaseReg, Scale, IndexReg, Disp; - getAddressingMode(cast(Op0)->getOperand(0), BaseReg, - Scale, IndexReg, Disp); - unsigned Op1r = getReg(Op1); - addFullAddress(BuildMI(BB, Opcode, 2, DestReg).addReg(Op1r), - BaseReg, Scale, IndexReg, Disp); + if (AllocaInst *AI = + dyn_castFixedAlloca(cast(Op0)->getOperand(0))) { + unsigned FI = getFixedSizedAllocaFI(AI); + addFrameReference(BuildMI(BB, Opcode, 5, DestReg).addReg(Op1r), FI); + } else { + unsigned BaseReg, Scale, IndexReg, Disp; + getAddressingMode(cast(Op0)->getOperand(0), BaseReg, + Scale, IndexReg, Disp); + + addFullAddress(BuildMI(BB, Opcode, 5, DestReg).addReg(Op1r), + BaseReg, Scale, IndexReg, Disp); + } return; } @@ -2337,13 +2369,18 @@ assert(Ty == Type::FloatTy||Ty == Type::DoubleTy && "Unknown FP type!"); unsigned Opcode = Ty == Type::FloatTy ? X86::FMUL32m : X86::FMUL64m; - unsigned BaseReg, Scale, IndexReg, Disp; - getAddressingMode(LI->getOperand(0), BaseReg, - Scale, IndexReg, Disp); - unsigned Op0r = getReg(Op0); - addFullAddress(BuildMI(BB, Opcode, 2, ResultReg).addReg(Op0r), - BaseReg, Scale, IndexReg, Disp); + if (AllocaInst *AI = dyn_castFixedAlloca(LI->getOperand(0))) { + unsigned FI = getFixedSizedAllocaFI(AI); + addFrameReference(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op0r), FI); + } else { + unsigned BaseReg, Scale, IndexReg, Disp; + getAddressingMode(LI->getOperand(0), BaseReg, + Scale, IndexReg, Disp); + + addFullAddress(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op0r), + BaseReg, Scale, IndexReg, Disp); + } return; } } @@ -2476,13 +2513,18 @@ assert(Ty == Type::FloatTy||Ty == Type::DoubleTy && "Unknown FP type!"); unsigned Opcode = Ty == Type::FloatTy ? X86::FDIV32m : X86::FDIV64m; - unsigned BaseReg, Scale, IndexReg, Disp; - getAddressingMode(LI->getOperand(0), BaseReg, - Scale, IndexReg, Disp); - unsigned Op0r = getReg(Op0); - addFullAddress(BuildMI(BB, Opcode, 2, ResultReg).addReg(Op0r), - BaseReg, Scale, IndexReg, Disp); + if (AllocaInst *AI = dyn_castFixedAlloca(LI->getOperand(0))) { + unsigned FI = getFixedSizedAllocaFI(AI); + addFrameReference(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op0r), FI); + } else { + unsigned BaseReg, Scale, IndexReg, Disp; + getAddressingMode(LI->getOperand(0), BaseReg, + Scale, IndexReg, Disp); + + addFullAddress(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op0r), + BaseReg, Scale, IndexReg, Disp); + } return; } @@ -2492,13 +2534,16 @@ assert(Ty == Type::FloatTy||Ty == Type::DoubleTy && "Unknown FP type!"); unsigned Opcode = Ty == Type::FloatTy ? X86::FDIVR32m : X86::FDIVR64m; - unsigned BaseReg, Scale, IndexReg, Disp; - getAddressingMode(LI->getOperand(0), BaseReg, - Scale, IndexReg, Disp); - unsigned Op1r = getReg(Op1); - addFullAddress(BuildMI(BB, Opcode, 2, ResultReg).addReg(Op1r), - BaseReg, Scale, IndexReg, Disp); + if (AllocaInst *AI = dyn_castFixedAlloca(LI->getOperand(0))) { + unsigned FI = getFixedSizedAllocaFI(AI); + addFrameReference(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op1r), FI); + } else { + unsigned BaseReg, Scale, IndexReg, Disp; + getAddressingMode(LI->getOperand(0), BaseReg, Scale, IndexReg, Disp); + addFullAddress(BuildMI(BB, Opcode, 5, ResultReg).addReg(Op1r), + BaseReg, Scale, IndexReg, Disp); + } return; } } @@ -2796,26 +2841,6 @@ } -void ISel::getAddressingMode(Value *Addr, unsigned &BaseReg, unsigned &Scale, - unsigned &IndexReg, unsigned &Disp) { - BaseReg = 0; Scale = 1; IndexReg = 0; Disp = 0; - if (GetElementPtrInst *GEP = dyn_cast(Addr)) { - if (isGEPFoldable(BB, GEP->getOperand(0), GEP->op_begin()+1, GEP->op_end(), - BaseReg, Scale, IndexReg, Disp)) - return; - } else if (ConstantExpr *CE = dyn_cast(Addr)) { - if (CE->getOpcode() == Instruction::GetElementPtr) - if (isGEPFoldable(BB, CE->getOperand(0), CE->op_begin()+1, CE->op_end(), - BaseReg, Scale, IndexReg, Disp)) - return; - } - - // If it's not foldable, reset addr mode. - BaseReg = getReg(Addr); - Scale = 1; IndexReg = 0; Disp = 0; -} - - /// visitLoadInst - Implement LLVM load instructions in terms of the x86 'mov' /// instruction. The load and store instructions are the only place where we /// need to worry about the memory layout of the target machine. @@ -2838,10 +2863,16 @@ static const unsigned Opcode[] = { 0/*BYTE*/, X86::FILD16m, X86::FILD32m, 0/*FP*/, X86::FILD64m }; - unsigned BaseReg = 0, Scale = 1, IndexReg = 0, Disp = 0; - getAddressingMode(I.getOperand(0), BaseReg, Scale, IndexReg, Disp); - addFullAddress(BuildMI(BB, Opcode[Class], 5, DestReg), - BaseReg, Scale, IndexReg, Disp); + + if (AllocaInst *AI = dyn_castFixedAlloca(I.getOperand(0))) { + unsigned FI = getFixedSizedAllocaFI(AI); + addFrameReference(BuildMI(BB, Opcode[Class], 4, DestReg), FI); + } else { + unsigned BaseReg = 0, Scale = 1, IndexReg = 0, Disp = 0; + getAddressingMode(I.getOperand(0), BaseReg, Scale, IndexReg, Disp); + addFullAddress(BuildMI(BB, Opcode[Class], 4, DestReg), + BaseReg, Scale, IndexReg, Disp); + } return; } else { User = 0; @@ -2887,33 +2918,49 @@ } } - unsigned DestReg = getReg(I); - unsigned BaseReg = 0, Scale = 1, IndexReg = 0, Disp = 0; - getAddressingMode(I.getOperand(0), BaseReg, Scale, IndexReg, Disp); - - if (Class == cLong) { - addFullAddress(BuildMI(BB, X86::MOV32rm, 4, DestReg), - BaseReg, Scale, IndexReg, Disp); - addFullAddress(BuildMI(BB, X86::MOV32rm, 4, DestReg+1), - BaseReg, Scale, IndexReg, Disp+4); - return; - } - static const unsigned Opcodes[] = { - X86::MOV8rm, X86::MOV16rm, X86::MOV32rm, X86::FLD32m + X86::MOV8rm, X86::MOV16rm, X86::MOV32rm, X86::FLD32m, X86::MOV32rm }; unsigned Opcode = Opcodes[Class]; if (I.getType() == Type::DoubleTy) Opcode = X86::FLD64m; - addFullAddress(BuildMI(BB, Opcode, 4, DestReg), - BaseReg, Scale, IndexReg, Disp); + + unsigned DestReg = getReg(I); + + if (AllocaInst *AI = dyn_castFixedAlloca(I.getOperand(0))) { + unsigned FI = getFixedSizedAllocaFI(AI); + if (Class == cLong) { + addFrameReference(BuildMI(BB, X86::MOV32rm, 4, DestReg), FI); + addFrameReference(BuildMI(BB, X86::MOV32rm, 4, DestReg+1), FI, 4); + } else { + addFrameReference(BuildMI(BB, Opcode, 4, DestReg), FI); + } + } else { + unsigned BaseReg = 0, Scale = 1, IndexReg = 0, Disp = 0; + getAddressingMode(I.getOperand(0), BaseReg, Scale, IndexReg, Disp); + + if (Class == cLong) { + addFullAddress(BuildMI(BB, X86::MOV32rm, 4, DestReg), + BaseReg, Scale, IndexReg, Disp); + addFullAddress(BuildMI(BB, X86::MOV32rm, 4, DestReg+1), + BaseReg, Scale, IndexReg, Disp+4); + } else { + addFullAddress(BuildMI(BB, Opcode, 4, DestReg), + BaseReg, Scale, IndexReg, Disp); + } + } } /// visitStoreInst - Implement LLVM store instructions in terms of the x86 'mov' /// instruction. /// void ISel::visitStoreInst(StoreInst &I) { - unsigned BaseReg, Scale, IndexReg, Disp; - getAddressingMode(I.getOperand(1), BaseReg, Scale, IndexReg, Disp); + unsigned BaseReg = ~0U, Scale = ~0U, IndexReg = ~0U, Disp = ~0U; + unsigned AllocaFrameIdx = ~0U; + + if (AllocaInst *AI = dyn_castFixedAlloca(I.getOperand(1))) + AllocaFrameIdx = getFixedSizedAllocaFI(AI); + else + getAddressingMode(I.getOperand(1), BaseReg, Scale, IndexReg, Disp); const Type *ValTy = I.getOperand(0)->getType(); unsigned Class = getClassB(ValTy); @@ -2921,21 +2968,36 @@ if (ConstantInt *CI = dyn_cast(I.getOperand(0))) { uint64_t Val = CI->getRawValue(); if (Class == cLong) { - addFullAddress(BuildMI(BB, X86::MOV32mi, 5), - BaseReg, Scale, IndexReg, Disp).addImm(Val & ~0U); - addFullAddress(BuildMI(BB, X86::MOV32mi, 5), - BaseReg, Scale, IndexReg, Disp+4).addImm(Val>>32); + if (AllocaFrameIdx != ~0U) { + addFrameReference(BuildMI(BB, X86::MOV32mi, 5), + AllocaFrameIdx).addImm(Val & ~0U); + addFrameReference(BuildMI(BB, X86::MOV32mi, 5), + AllocaFrameIdx, 4).addImm(Val>>32); + } else { + addFullAddress(BuildMI(BB, X86::MOV32mi, 5), + BaseReg, Scale, IndexReg, Disp).addImm(Val & ~0U); + addFullAddress(BuildMI(BB, X86::MOV32mi, 5), + BaseReg, Scale, IndexReg, Disp+4).addImm(Val>>32); + } } else { static const unsigned Opcodes[] = { X86::MOV8mi, X86::MOV16mi, X86::MOV32mi }; unsigned Opcode = Opcodes[Class]; - addFullAddress(BuildMI(BB, Opcode, 5), - BaseReg, Scale, IndexReg, Disp).addImm(Val); + if (AllocaFrameIdx != ~0U) { + addFrameReference(BuildMI(BB, Opcode, 5), AllocaFrameIdx).addImm(Val); + } else { + addFullAddress(BuildMI(BB, Opcode, 5), + BaseReg, Scale, IndexReg, Disp).addImm(Val); + } } } else if (ConstantBool *CB = dyn_cast(I.getOperand(0))) { - addFullAddress(BuildMI(BB, X86::MOV8mi, 5), - BaseReg, Scale, IndexReg, Disp).addImm(CB->getValue()); + if (AllocaFrameIdx != ~0U) + addFrameReference(BuildMI(BB, X86::MOV8mi, 5), + AllocaFrameIdx).addImm(CB->getValue()); + else + addFullAddress(BuildMI(BB, X86::MOV8mi, 5), + BaseReg, Scale, IndexReg, Disp).addImm(CB->getValue()); } else if (ConstantFP *CFP = dyn_cast(I.getOperand(0))) { // Store constant FP values with integer instructions to avoid having to // load the constants from the constant pool then do a store. @@ -2945,27 +3007,45 @@ float F; } V; V.F = CFP->getValue(); - addFullAddress(BuildMI(BB, X86::MOV32mi, 5), - BaseReg, Scale, IndexReg, Disp).addImm(V.I); + if (AllocaFrameIdx != ~0U) + addFrameReference(BuildMI(BB, X86::MOV32mi, 5), + AllocaFrameIdx).addImm(V.I); + else + addFullAddress(BuildMI(BB, X86::MOV32mi, 5), + BaseReg, Scale, IndexReg, Disp).addImm(V.I); } else { union { uint64_t I; double F; } V; V.F = CFP->getValue(); - addFullAddress(BuildMI(BB, X86::MOV32mi, 5), - BaseReg, Scale, IndexReg, Disp).addImm((unsigned)V.I); - addFullAddress(BuildMI(BB, X86::MOV32mi, 5), - BaseReg, Scale, IndexReg, Disp+4).addImm( + if (AllocaFrameIdx != ~0U) { + addFrameReference(BuildMI(BB, X86::MOV32mi, 5), + AllocaFrameIdx).addImm((unsigned)V.I); + addFrameReference(BuildMI(BB, X86::MOV32mi, 5), + AllocaFrameIdx, 4).addImm(unsigned(V.I >> 32)); + } else { + addFullAddress(BuildMI(BB, X86::MOV32mi, 5), + BaseReg, Scale, IndexReg, Disp).addImm((unsigned)V.I); + addFullAddress(BuildMI(BB, X86::MOV32mi, 5), + BaseReg, Scale, IndexReg, Disp+4).addImm( unsigned(V.I >> 32)); + } } } else if (Class == cLong) { unsigned ValReg = getReg(I.getOperand(0)); - addFullAddress(BuildMI(BB, X86::MOV32mr, 5), - BaseReg, Scale, IndexReg, Disp).addReg(ValReg); - addFullAddress(BuildMI(BB, X86::MOV32mr, 5), - BaseReg, Scale, IndexReg, Disp+4).addReg(ValReg+1); + if (AllocaFrameIdx != ~0U) { + addFrameReference(BuildMI(BB, X86::MOV32mr, 5), + AllocaFrameIdx).addReg(ValReg); + addFrameReference(BuildMI(BB, X86::MOV32mr, 5), + AllocaFrameIdx, 4).addReg(ValReg+1); + } else { + addFullAddress(BuildMI(BB, X86::MOV32mr, 5), + BaseReg, Scale, IndexReg, Disp).addReg(ValReg); + addFullAddress(BuildMI(BB, X86::MOV32mr, 5), + BaseReg, Scale, IndexReg, Disp+4).addReg(ValReg+1); + } } else { unsigned ValReg = getReg(I.getOperand(0)); static const unsigned Opcodes[] = { @@ -2973,8 +3053,12 @@ }; unsigned Opcode = Opcodes[Class]; if (ValTy == Type::DoubleTy) Opcode = X86::FST64m; - addFullAddress(BuildMI(BB, Opcode, 1+4), - BaseReg, Scale, IndexReg, Disp).addReg(ValReg); + + if (AllocaFrameIdx != ~0U) + addFrameReference(BuildMI(BB, Opcode, 5), AllocaFrameIdx).addReg(ValReg); + else + addFullAddress(BuildMI(BB, Opcode, 1+4), + BaseReg, Scale, IndexReg, Disp).addReg(ValReg); } } @@ -3627,13 +3711,15 @@ } } - /// visitAllocaInst - If this is a fixed size alloca, allocate space from the /// frame manager, otherwise do it the hard way. /// void ISel::visitAllocaInst(AllocaInst &I) { + // If this is a fixed size alloca in the entry block for the function, we + // statically stack allocate the space, so we don't need to do anything here. + // if (dyn_castFixedAlloca(&I)) return; - + // Find the data size of the alloca inst's getAllocatedType. const Type *Ty = I.getAllocatedType(); unsigned TySize = TM.getTargetData().getTypeSize(Ty); From lattner at cs.uiuc.edu Thu May 13 10:26:02 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 13 10:26:02 2004 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Message-ID: <200405131526.KAA00670@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.253 -> 1.254 --- Log message: Two more improvements for null pointer handling: storing a null pointer and passing a null pointer into a function. For this testcase: void %test(int** %X) { store int* null, int** %X call void %test(int** null) ret void } we now generate this: test: sub %ESP, 12 mov %EAX, DWORD PTR [%ESP + 16] mov DWORD PTR [%EAX], 0 mov DWORD PTR [%ESP], 0 call test add %ESP, 12 ret instead of this: test: sub %ESP, 12 mov %EAX, DWORD PTR [%ESP + 16] mov %ECX, 0 mov DWORD PTR [%EAX], %ECX mov %EAX, 0 mov DWORD PTR [%ESP], %EAX call test add %ESP, 12 ret --- Diffs of the changes: (+12 -3) Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.253 llvm/lib/Target/X86/InstSelectSimple.cpp:1.254 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.253 Thu May 13 10:12:43 2004 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Thu May 13 10:26:48 2004 @@ -1500,6 +1500,9 @@ unsigned Val = cast(Args[i].Val)->getRawValue(); addRegOffset(BuildMI(BB, X86::MOV32mi, 5), X86::ESP, ArgOffset).addImm(Val); + } else if (Args[i].Val && isa(Args[i].Val)) { + addRegOffset(BuildMI(BB, X86::MOV32mi, 5), + X86::ESP, ArgOffset).addImm(0); } else { ArgReg = Args[i].Val ? getReg(Args[i].Val) : Args[i].Reg; addRegOffset(BuildMI(BB, X86::MOV32mr, 5), @@ -2984,13 +2987,19 @@ X86::MOV8mi, X86::MOV16mi, X86::MOV32mi }; unsigned Opcode = Opcodes[Class]; - if (AllocaFrameIdx != ~0U) { + if (AllocaFrameIdx != ~0U) addFrameReference(BuildMI(BB, Opcode, 5), AllocaFrameIdx).addImm(Val); - } else { + else addFullAddress(BuildMI(BB, Opcode, 5), BaseReg, Scale, IndexReg, Disp).addImm(Val); - } } + } else if (isa(I.getOperand(0))) { + if (AllocaFrameIdx != ~0U) + addFrameReference(BuildMI(BB, X86::MOV32mi, 5), AllocaFrameIdx).addImm(0); + else + addFullAddress(BuildMI(BB, X86::MOV32mi, 5), + BaseReg, Scale, IndexReg, Disp).addImm(0); + } else if (ConstantBool *CB = dyn_cast(I.getOperand(0))) { if (AllocaFrameIdx != ~0U) addFrameReference(BuildMI(BB, X86::MOV8mi, 5), From brukman at cs.uiuc.edu Thu May 13 11:39:41 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu May 13 11:39:41 2004 Subject: [llvm-commits] CVS: llvm/docs/index.html Message-ID: <200405131638.LAA21783@zion.cs.uiuc.edu> Changes in directory llvm/docs: index.html updated: 1.12 -> 1.13 --- Log message: Make page HTML-4.01 compliant (& => & in URL). --- Diffs of the changes: (+2 -2) Index: llvm/docs/index.html diff -u llvm/docs/index.html:1.12 llvm/docs/index.html:1.13 --- llvm/docs/index.html:1.12 Wed May 12 13:00:48 2004 +++ llvm/docs/index.html Thu May 13 11:37:23 2004 @@ -26,7 +26,7 @@
      -
    • Distribution license
    • +
    • Distribution license
    • Installing and compiling LLVM components
    • Features and limitations of this release @@ -178,7 +178,7 @@ John Criswell
      LLVM Compiler Infrastructure
      - Last modified: $Date: 2004/05/12 18:00:48 $ + Last modified: $Date: 2004/05/13 16:37:23 $ From brukman at cs.uiuc.edu Thu May 13 11:39:54 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Thu May 13 11:39:54 2004 Subject: [llvm-commits] CVS: llvm/docs/llvm.css Message-ID: <200405131638.LAA20045@zion.cs.uiuc.edu> Changes in directory llvm/docs: llvm.css updated: 1.15 -> 1.16 --- Log message: Specify units in padding length. --- Diffs of the changes: (+1 -1) Index: llvm/docs/llvm.css diff -u llvm/docs/llvm.css:1.15 llvm/docs/llvm.css:1.16 --- llvm/docs/llvm.css:1.15 Wed May 12 16:28:08 2004 +++ llvm/docs/llvm.css Thu May 13 11:37:52 2004 @@ -33,7 +33,7 @@ text-align: left; font-size: 12pt; padding: 4pt 4pt 4pt 4pt; margin: 1.5em 0.5em 1.5em 0.5em } -.doc_subsubsection { margin: 1.5em 0.5em 1.5 0.5em; +.doc_subsubsection { margin: 1.5em 0.5em 1.5em 0.5em; padding: 20pt 4pt 4pt 4pt; font-weight: bold; font-style: oblique; border-bottom: 1px solid #999999; font-size: 12pt } From lattner at cs.uiuc.edu Thu May 13 15:41:18 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 13 15:41:18 2004 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/LoopUnroll/ Message-ID: <200405132041.PAA15320@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/LoopUnroll: --- Log message: Directory /home/vadve/shared/PublicCVS/llvm/test/Regression/Transforms/LoopUnroll added to the repository --- Diffs of the changes: (+0 -0) From lattner at cs.uiuc.edu Thu May 13 15:43:01 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 13 15:43:01 2004 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp LoopUnroll.cpp Message-ID: <200405132043.PAA15362@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.201 -> 1.202 LoopUnroll.cpp updated: 1.9 -> 1.10 --- Log message: Fix a nasty bug that caused us to unroll EXTREMELY large loops due to overflow in the size calculation. This is not something you want to see: Loop Unroll: F[main] Loop %no_exit Loop Size = 2 Trip Count = 2147483648 - UNROLLING! The problem was that 2*2147483648 == 0. Now we get: Loop Unroll: F[main] Loop %no_exit Loop Size = 2 Trip Count = 2147483648 - TOO LARGE: 4294967296>100 Thanks to some anonymous person playing with the demo page that repeatedly caused zion to go into swapping land. That's one way to ensure you'll get a quick bugfix. :) Testcase here: Transforms/LoopUnroll/2004-05-13-DontUnrollTooMuch.ll --- Diffs of the changes: (+10 -3) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.201 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.202 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.201 Sat May 8 17:41:42 2004 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Thu May 13 15:43:31 2004 @@ -1475,6 +1475,13 @@ // integers at the end of their ranges... // if (ConstantInt *CI = dyn_cast(Op1)) { + if (Instruction *LHSI = dyn_cast(Op0)) + if (LHSI->getOpcode() == Instruction::Div && LHSI->hasOneUse() && + isa(LHSI->getOperand(1))) { + std::cerr << "COULD FOLD: " << *LHSI; + std::cerr << "COULD FOLD: " << I << "\n"; + } + // Simplify seteq and setne instructions... if (I.getOpcode() == Instruction::SetEQ || I.getOpcode() == Instruction::SetNE) { Index: llvm/lib/Transforms/Scalar/LoopUnroll.cpp diff -u llvm/lib/Transforms/Scalar/LoopUnroll.cpp:1.9 llvm/lib/Transforms/Scalar/LoopUnroll.cpp:1.10 --- llvm/lib/Transforms/Scalar/LoopUnroll.cpp:1.9 Tue Apr 20 15:26:03 2004 +++ llvm/lib/Transforms/Scalar/LoopUnroll.cpp Thu May 13 15:43:31 2004 @@ -139,9 +139,9 @@ DEBUG(std::cerr << "Loop Unroll: F[" << BB->getParent()->getName() << "] Loop %" << BB->getName() << " Loop Size = " << LoopSize << " Trip Count = " << TripCount << " - "); - if (LoopSize*TripCount > UnrollThreshold) { - DEBUG(std::cerr << "TOO LARGE: " << LoopSize*TripCount << ">" - << UnrollThreshold << "\n"); + uint64_t Size = (uint64_t)LoopSize*(uint64_t)TripCount; + if (Size > UnrollThreshold) { + DEBUG(std::cerr << "TOO LARGE: " << Size << ">" << UnrollThreshold << "\n"); return Changed; } DEBUG(std::cerr << "UNROLLING!\n"); From lattner at cs.uiuc.edu Thu May 13 15:43:10 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 13 15:43:10 2004 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/LoopUnroll/2004-05-13-DontUnrollTooMuch.ll Message-ID: <200405132043.PAA15349@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/LoopUnroll: 2004-05-13-DontUnrollTooMuch.ll added (r1.1) --- Log message: New testcase that used to cause the unroller to try to unroll the loop 2G times. :( --- Diffs of the changes: (+15 -0) Index: llvm/test/Regression/Transforms/LoopUnroll/2004-05-13-DontUnrollTooMuch.ll diff -c /dev/null llvm/test/Regression/Transforms/LoopUnroll/2004-05-13-DontUnrollTooMuch.ll:1.1 *** /dev/null Thu May 13 15:43:25 2004 --- llvm/test/Regression/Transforms/LoopUnroll/2004-05-13-DontUnrollTooMuch.ll Thu May 13 15:43:15 2004 *************** *** 0 **** --- 1,15 ---- + ; RUN: llvm-as < %s | opt -loop-unroll -disable-output + + int %main() { + entry: + br label %no_exit + + no_exit: ; preds = %entry, %no_exit + %indvar = phi uint [ 0, %entry ], [ %indvar.next, %no_exit ] ; [#uses=1] + %indvar.next = add uint %indvar, 1 ; [#uses=2] + %exitcond = setne uint %indvar.next, 2147483648 ; [#uses=1] + br bool %exitcond, label %no_exit, label %loopexit + + loopexit: ; preds = %no_exit + ret int 0 + } From lattner at cs.uiuc.edu Thu May 13 15:56:01 2004 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu May 13 15:56:01 2004 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200405132056.PAA16881@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.202 -> 1.203 --- Log message: This was not meant to be committed --- Diffs of the changes: (+0 -7) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.202 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.203 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.202 Thu May 13 15:43:31 2004 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Thu May 13 15:56:34 2004 @@ -1475,13 +1475,6 @@ // integers at the end of their ranges... // if (ConstantInt *CI = dyn_cast(Op1)) { - if (Instruction *LHSI = dyn_cast(Op0)) - if (LHSI->getOpcode() == Instruction::Div && LHSI->hasOneUse() && - isa(LHSI->getOperand(1))) { - std::cerr << "COULD FOLD: " << *LHSI; - std::cerr << "COULD FOLD: " << I << "\n"; - } - // Simplify seteq and setne instructions... if (I.getOpcode() == Instruction::SetEQ || I.getOpcode() == Instruction::SetNE) { From reid at x10sys.com Thu May 13 16:46:01 2004 From: reid at x10sys.com (Reid Spencer) Date: Thu May 13 16:46:01 2004 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp LoopUnroll.cpp In-Reply-To: <200405132043.PAA15362@zion.cs.uiuc.edu> References: <200405132043.PAA15362@zion.cs.uiuc.edu> Message-ID: <1084484731.10195.143.camel@bashful.x10sys.com> LOL So we have anonymous spammers finding bugs now. How would we give them credit in the contributors file? :) Reid. On Thu, 2004-05-13 at 13:43, Chris Lattner wrote: > Changes in directory llvm/lib/Transforms/Scalar: > > InstructionCombining.cpp updated: 1.201 -> 1.202 > LoopUnroll.cpp updated: 1.9 -> 1.10 > > --- > Log message: > > Fix a nasty bug that caused us to unroll EXTREMELY large loops due to overflow > in the size calculation. > > This is not something you want to see: > Loop Unroll: F[main] Loop %no_exit Loop Size = 2 Trip Count = 2147483648 - UNROLLING! > > The problem was that 2*2147483648 == 0. > > Now we get: > Loop Unroll: F[main] Loop %no_exit Loop Size = 2 Trip Count = 2147483648 - TOO LARGE: 4294967296>100 > > Thanks to some anonymous person playing with the demo page that repeatedly > caused zion to go into swapping land. That's one way to ensure you'll get > a quick bugfix. :) > > Testcase here: Transforms/LoopUnroll/2004-05-13-DontUnrollTooMuch.ll > > > > --- > Diffs of the changes: (+10 -3) > > Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp > diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.201 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.202 > --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.201 Sat May 8 17:41:42 2004 > +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Thu May 13 15:43:31 2004 > @@ -1475,6 +1475,13 @@ > // integers at the end of their ranges... > // > if (ConstantInt *CI = dyn_cast(Op1)) { > + if (Instruction *LHSI = dyn_cast(Op0)) > + if (LHSI->getOpcode() == Instruction::Div && LHSI->hasOneUse() && > + isa(LHSI->getOperand(1))) { > + std::cerr << "COULD FOLD: " << *LHSI; > + std::cerr << "COULD FOLD: " << I << "\n"; > + } > + > // Simplify seteq and setne instructions... > if (I.getOpcode() == Instruction::SetEQ || > I.getOpcode() == Instruction::SetNE) { > > > Index: llvm/lib/Transforms/Scalar/LoopUnroll.cpp > diff -u llvm/lib/Transforms/Scalar/LoopUnroll.cpp:1.9 llvm/lib/Transforms/Scalar/LoopUnroll.cpp:1.10 > --- llvm/lib/Transforms/Scalar/LoopUnroll.cpp:1.9 Tue Apr 20 15:26:03 2004 > +++ llvm/lib/Transforms/Scalar/LoopUnroll.cpp Thu May 13 15:43:31 2004 > @@ -139,9 +139,9 @@ > DEBUG(std::cerr << "Loop Unroll: F[" << BB->getParent()->getName() > << "] Loop %" << BB->getName() << " Loop Size = " << LoopSize > << " Trip Count = " << TripCount << " - "); > - if (LoopSize*TripCount > UnrollThreshold) { > - DEBUG(std::cerr << "TOO LARGE: " << LoopSize*TripCount << ">" > - << UnrollThreshold << "\n"); > + uint64_t Size = (uint64_t)LoopSize*(uint64_t)TripCount; > + if (Size > UnrollThreshold) { > + DEBUG(std::cerr << "TOO LARGE: " << Size << ">" << UnrollThreshold << "\n"); > return Changed; > } > DEBUG(std::cerr << "UNROLLING!\n"); > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://mail.cs.uiuc.edu/mailman/listinfo/llvm-commits _______________________ Reid Spencer President & CTO eXtensible Systems, Inc. rspencer at x10sys.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 189 bytes Desc: This is a digitally signed message part URL: From gaeke at cs.uiuc.edu Thu May 13 16:50:01 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Thu May 13 16:50:01 2004 Subject: [llvm-commits] CVS: llvm-www/ProjectsWithLLVM/index.html Message-ID: <200405132150.QAA18380@zion.cs.uiuc.edu> Changes in directory llvm-www/ProjectsWithLLVM: index.html updated: 1.13 -> 1.14 --- Log message: Add LLVM-TV; fix my at-school website URL; fix typo. --- Diffs of the changes: (+40 -5) Index: llvm-www/ProjectsWithLLVM/index.html diff -u llvm-www/ProjectsWithLLVM/index.html:1.13 llvm-www/ProjectsWithLLVM/index.html:1.14 --- llvm-www/ProjectsWithLLVM/index.html:1.13 Wed May 12 18:53:24 2004 +++ llvm-www/ProjectsWithLLVM/index.html Thu May 13 16:50:00 2004 @@ -2,7 +2,7 @@
      Projects built with LLVM

      This page is an incomplete list of the projects built with LLVM, sorted in -reverse cronological order. The idea of this list is to show some of the things +reverse chronological order. The idea of this list is to show some of the things that have been done with LLVM for various course projects or for other purposes, which can be used as a source of ideas for future projects.

      @@ -21,12 +21,47 @@ papers, presentations, posters, or anything else you have.

      - +
      +CS497rej: Object-Oriented Programming and Design (Spring 2004) +
      + + + +

      +The LLVM Visualization Tool (LLVM-TV) can be used to visualize the effects +of transformations written in the LLVM framework. Our visualizations +reflect the state of a compilation unit at a single instant in time, +between transformations; we call these saved states "snapshots". A user +can visualize a sequence of snapshots of the same module---for example, +as a program is being optimized---or snapshots of different modules, +for comparison purposes. +

      + +

      +Our target audience consists of developers working within the LLVM +framework, who are trying to understand the LLVM representation and its +analyses and transformations. In addition, LLVM-TV has been designed +to make it easy to add new kinds of program visualization modules. +LLVM-TV is based on the wxWidgets +cross-platform GUI framework, and uses AT&T Research's +GraphViz to +draw graphs. +

      + +

      Wiki +page with overview; design doc, user manual & download on the +LLVM-TV website

      +
      -CS426: Advanced Compilers (Fall 2004) +CS426: Advanced Compilers (Fall 2003)
      @@ -98,7 +133,7 @@

      "Traditional architectures use the hardware instruction set for dual @@ -201,7 +236,7 @@ for LLVM bytecode
      Chris Lattner, Misha Brukman, -Brian Gaeke +Brian Gaeke

    "We present the design and implementation of Jello, a retargetable From gaeke at cs.uiuc.edu Fri May 14 01:55:03 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Fri May 14 01:55:03 2004 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Message-ID: <200405140655.BAA27048@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: InstSelectSimple.cpp updated: 1.254 -> 1.255 --- Log message: Generate branch machine instructions with MachineBasicBlock operands instead of LLVM BasicBlock operands. --- Diffs of the changes: (+9 -7) Index: llvm/lib/Target/X86/InstSelectSimple.cpp diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.254 llvm/lib/Target/X86/InstSelectSimple.cpp:1.255 --- llvm/lib/Target/X86/InstSelectSimple.cpp:1.254 Thu May 13 10:26:48 2004 +++ llvm/lib/Target/X86/InstSelectSimple.cpp Fri May 14 01:54:56 2004 @@ -1379,7 +1379,7 @@ if (!BI.isConditional()) { // Unconditional branch? if (BI.getSuccessor(0) != NextBB) - BuildMI(BB, X86::JMP, 1).addPCDisp(BI.getSuccessor(0)); + BuildMI(BB, X86::JMP, 1).addMBB(MBBMap[BI.getSuccessor(0)]); return; } @@ -1392,12 +1392,12 @@ BuildMI(BB, X86::TEST8rr, 2).addReg(condReg).addReg(condReg); if (BI.getSuccessor(1) == NextBB) { if (BI.getSuccessor(0) != NextBB) - BuildMI(BB, X86::JNE, 1).addPCDisp(BI.getSuccessor(0)); + BuildMI(BB, X86::JNE, 1).addMBB(MBBMap[BI.getSuccessor(0)]); } else { - BuildMI(BB, X86::JE, 1).addPCDisp(BI.getSuccessor(1)); + BuildMI(BB, X86::JE, 1).addMBB(MBBMap[BI.getSuccessor(1)]); if (BI.getSuccessor(0) != NextBB) - BuildMI(BB, X86::JMP, 1).addPCDisp(BI.getSuccessor(0)); + BuildMI(BB, X86::JMP, 1).addMBB(MBBMap[BI.getSuccessor(0)]); } return; } @@ -1429,14 +1429,16 @@ }; if (BI.getSuccessor(0) != NextBB) { - BuildMI(BB, OpcodeTab[isSigned][OpNum], 1).addPCDisp(BI.getSuccessor(0)); + BuildMI(BB, OpcodeTab[isSigned][OpNum], 1) + .addMBB(MBBMap[BI.getSuccessor(0)]); if (BI.getSuccessor(1) != NextBB) - BuildMI(BB, X86::JMP, 1).addPCDisp(BI.getSuccessor(1)); + BuildMI(BB, X86::JMP, 1).addMBB(MBBMap[BI.getSuccessor(1)]); } else { // Change to the inverse condition... if (BI.getSuccessor(1) != NextBB) { OpNum ^= 1; - BuildMI(BB, OpcodeTab[isSigned][OpNum], 1).addPCDisp(BI.getSuccessor(1)); + BuildMI(BB, OpcodeTab[isSigned][OpNum], 1) + .addMBB(MBBMap[BI.getSuccessor(1)]); } } } From gaeke at cs.uiuc.edu Fri May 14 01:55:12 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Fri May 14 01:55:12 2004 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/Printer.cpp Message-ID: <200405140655.BAA27053@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: Printer.cpp updated: 1.97 -> 1.98 --- Log message: Support MachineBasicBlock operands on RawFrm instructions. Get rid of separate numbering for LLVM BasicBlocks; use the automatically generated MachineBasicBlock numbering. --- Diffs of the changes: (+12 -27) Index: llvm/lib/Target/X86/Printer.cpp diff -u llvm/lib/Target/X86/Printer.cpp:1.97 llvm/lib/Target/X86/Printer.cpp:1.98 --- llvm/lib/Target/X86/Printer.cpp:1.97 Tue Apr 13 12:18:39 2004 +++ llvm/lib/Target/X86/Printer.cpp Fri May 14 01:54:57 2004 @@ -87,13 +87,6 @@ Printer(std::ostream &o, TargetMachine &tm) : O(o), TM(tm) { } - /// We name each basic block in a Function with a unique number, so - /// that we can consistently refer to them later. This is cleared - /// at the beginning of each call to runOnMachineFunction(). - /// - typedef std::map ValueMapTy; - ValueMapTy NumberForBB; - /// Cache of mangled name for current function. This is /// recalculated at the beginning of each call to /// runOnMachineFunction(). @@ -366,10 +359,6 @@ /// method to print assembly for each instruction. /// bool Printer::runOnMachineFunction(MachineFunction &MF) { - // BBNumber is used here so that a given Printer will never give two - // BBs the same name. (If you have a better way, please let me know!) - static unsigned BBNumber = 0; - O << "\n\n"; // What's my mangled name? CurrentFnName = Mang->getValueName(MF.getFunction()); @@ -385,19 +374,11 @@ O << "\t.type\t" << CurrentFnName << ", @function\n"; O << CurrentFnName << ":\n"; - // Number each basic block so that we can consistently refer to them - // in PC-relative references. - NumberForBB.clear(); - for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); - I != E; ++I) { - NumberForBB[I->getBasicBlock()] = BBNumber++; - } - // Print out code for the function. for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); I != E; ++I) { // Print a label for the basic block. - O << ".LBB" << NumberForBB[I->getBasicBlock()] << ":\t# " + O << ".LBB" << CurrentFnName << "_" << I->getNumber() << ":\t# " << I->getBasicBlock()->getName() << "\n"; for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); II != E; ++II) { @@ -449,13 +430,17 @@ case MachineOperand::MO_UnextendedImmed: O << (int)MO.getImmedValue(); return; - case MachineOperand::MO_PCRelativeDisp: { - ValueMapTy::const_iterator i = NumberForBB.find(MO.getVRegValue()); - assert (i != NumberForBB.end() - && "Could not find a BB in the NumberForBB map!"); - O << ".LBB" << i->second << " # PC rel: " << MO.getVRegValue()->getName(); + case MachineOperand::MO_MachineBasicBlock: { + MachineBasicBlock *MBBOp = MO.getMachineBasicBlock(); + O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction()) + << "_" << MBBOp->getNumber () << "\t# " + << MBBOp->getBasicBlock ()->getName (); return; } + case MachineOperand::MO_PCRelativeDisp: + std::cerr << "Shouldn't use addPCDisp() when building X86 MachineInstrs"; + abort (); + return; case MachineOperand::MO_GlobalAddress: if (!elideOffsetKeyword) O << "OFFSET "; @@ -682,13 +667,13 @@ { // The accepted forms of Raw instructions are: // 1. nop - No operand required - // 2. jmp foo - PC relative displacement operand + // 2. jmp foo - MachineBasicBlock operand // 3. call bar - GlobalAddress Operand or External Symbol Operand // 4. in AL, imm - Immediate operand // assert(MI->getNumOperands() == 0 || (MI->getNumOperands() == 1 && - (MI->getOperand(0).isPCRelativeDisp() || + (MI->getOperand(0).isMachineBasicBlock() || MI->getOperand(0).isGlobalAddress() || MI->getOperand(0).isExternalSymbol() || MI->getOperand(0).isImmediate())) && From gaeke at cs.uiuc.edu Fri May 14 01:55:19 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Fri May 14 01:55:19 2004 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86CodeEmitter.cpp Message-ID: <200405140655.BAA27062@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86CodeEmitter.cpp updated: 1.59 -> 1.60 --- Log message: Don't keep track of references to LLVM BasicBlocks while emitting; use MachineBasicBlocks instead. --- Diffs of the changes: (+9 -11) Index: llvm/lib/Target/X86/X86CodeEmitter.cpp diff -u llvm/lib/Target/X86/X86CodeEmitter.cpp:1.59 llvm/lib/Target/X86/X86CodeEmitter.cpp:1.60 --- llvm/lib/Target/X86/X86CodeEmitter.cpp:1.59 Fri Apr 23 12:11:16 2004 +++ llvm/lib/Target/X86/X86CodeEmitter.cpp Fri May 14 01:54:58 2004 @@ -172,8 +172,8 @@ class Emitter : public MachineFunctionPass { const X86InstrInfo *II; MachineCodeEmitter &MCE; - std::map BasicBlockAddrs; - std::vector > BBRefs; + std::map BasicBlockAddrs; + std::vector > BBRefs; public: explicit Emitter(MachineCodeEmitter &mce) : II(0), MCE(mce) {} Emitter(MachineCodeEmitter &mce, const X86InstrInfo& ii) @@ -190,7 +190,7 @@ private: void emitBasicBlock(const MachineBasicBlock &MBB); - void emitPCRelativeBlockAddress(const BasicBlock *BB); + void emitPCRelativeBlockAddress(const MachineBasicBlock *BB); void emitMaybePCRelativeValue(unsigned Address, bool isPCRelative); void emitGlobalAddressForCall(GlobalValue *GV); void emitGlobalAddressForPtr(GlobalValue *GV); @@ -249,22 +249,21 @@ void Emitter::emitBasicBlock(const MachineBasicBlock &MBB) { if (uint64_t Addr = MCE.getCurrentPCValue()) - BasicBlockAddrs[MBB.getBasicBlock()] = Addr; + BasicBlockAddrs[&MBB] = Addr; for (MachineBasicBlock::const_iterator I = MBB.begin(), E = MBB.end(); I != E; ++I) emitInstruction(*I); } - /// emitPCRelativeBlockAddress - This method emits the PC relative address of /// the specified basic block, or if the basic block hasn't been emitted yet /// (because this is a forward branch), it keeps track of the information /// necessary to resolve this address later (and emits a dummy value). /// -void Emitter::emitPCRelativeBlockAddress(const BasicBlock *BB) { +void Emitter::emitPCRelativeBlockAddress(const MachineBasicBlock *MBB) { // FIXME: Emit backward branches directly - BBRefs.push_back(std::make_pair(BB, MCE.getCurrentPCValue())); - MCE.emitWord(0); // Emit a dummy value + BBRefs.push_back(std::make_pair(MBB, MCE.getCurrentPCValue())); + MCE.emitWord(0); } /// emitMaybePCRelativeValue - Emit a 32-bit address which may be PC relative. @@ -527,9 +526,8 @@ MCE.emitByte(BaseOpcode); if (MI.getNumOperands() == 1) { const MachineOperand &MO = MI.getOperand(0); - if (MO.isPCRelativeDisp()) { - // Conditional branch... FIXME: this should use an MBB destination! - emitPCRelativeBlockAddress(cast(MO.getVRegValue())); + if (MO.isMachineBasicBlock()) { + emitPCRelativeBlockAddress(MO.getMachineBasicBlock()); } else if (MO.isGlobalAddress()) { assert(MO.isPCRelative() && "Call target is not PC Relative?"); emitGlobalAddressForCall(MO.getGlobal()); From gaeke at cs.uiuc.edu Fri May 14 12:59:03 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Fri May 14 12:59:03 2004 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/TraceToFunction.cpp Message-ID: <200405141758.MAA20436@seraph.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: TraceToFunction.cpp updated: 1.30 -> 1.31 --- Log message: Update head-of-file comment --- Diffs of the changes: (+3 -7) Index: reopt/lib/LightWtProfiling/TraceToFunction.cpp diff -u reopt/lib/LightWtProfiling/TraceToFunction.cpp:1.30 reopt/lib/LightWtProfiling/TraceToFunction.cpp:1.31 --- reopt/lib/LightWtProfiling/TraceToFunction.cpp:1.30 Mon May 10 19:19:59 2004 +++ reopt/lib/LightWtProfiling/TraceToFunction.cpp Fri May 14 12:58:20 2004 @@ -13,17 +13,13 @@ // TODO (also search for FIXME in this file): // 1) Only let things go into the LiveIn/Out sets for which we have register // allocation information available. Otherwise abort. -// 2) For each basic block that exits the trace, we need to keep track -// of the address that the "ret" instruction would have returned to. -// Use the mapping information (probably BB TO MI MAP) to translate -// the BasicBlocks in ReturnBlockForTraceExit to a uint64_t -// address. (Figure out how Anand's code does this.) -// 3) Check these: +// 2) Check these: // a) Used before defined --> live-in and live-out // b) Live in and not defined by trace --> not live out // // Potential optimizations: -// Get rid of BranchNumber +// Make it possible to turn off BranchNumber...it is only useful (now) when a +// human is reading the code. // //===----------------------------------------------------------------------===// From gaeke at cs.uiuc.edu Fri May 14 13:03:03 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Fri May 14 13:03:03 2004 Subject: [llvm-commits] CVS: llvm/docs/CommandGuide/llvm-prof.pod Message-ID: <200405141803.NAA04050@zion.cs.uiuc.edu> Changes in directory llvm/docs/CommandGuide: llvm-prof.pod added (r1.1) --- Log message: This seems like as good a place as any to keep POD files. --- Diffs of the changes: (+58 -0) Index: llvm/docs/CommandGuide/llvm-prof.pod diff -c /dev/null llvm/docs/CommandGuide/llvm-prof.pod:1.1 *** /dev/null Fri May 14 13:03:33 2004 --- llvm/docs/CommandGuide/llvm-prof.pod Fri May 14 13:03:22 2004 *************** *** 0 **** --- 1,58 ---- + =pod + + =head1 NAME + + llvm-prof + + =head1 SYNOPSIS + + llvm-prof [options] [bytecode file] [llvmprof.out] + + =head1 DESCRIPTION + + The B tool reads in an F file (which can + optionally use a specific file with the third program argument), a bytecode file + for the program, and produces a human readable report, suitable for determining + where the program hotspots are. + + This program is often used in conjunction with the F + script. This script automatically instruments a program, runs it with the JIT, + then runs B to format a report. To get more information about + F, execute it with the B<--help> option. + + =head1 OPTIONS + + =over + + =item B<--annotated-llvm> or B<-A> + + In addition to the normal report printed, print out the code for the + program, annotated with 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. + + =item B<--print-all-code> + + Using this option enables the B<--annotated-llvm> option, but it + prints the entire module, instead of just the most commonly executed + functions. + + =item B<--time-passes> + + Record the amount of time needed for each pass and print it to standard + error. + + =back + + =head1 EXIT STATUS + + B returns 1 if it cannot load the bytecode file or the profile + information. Otherwise, it exits with zero. + + =head1 AUTHOR + + B is maintained by the LLVM Team (L). + + =cut + From gaeke at cs.uiuc.edu Fri May 14 13:31:05 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Fri May 14 13:31:05 2004 Subject: [llvm-commits] CVS: llvm/docs/CommandGuide/llvm-prof.pod Message-ID: <200405141831.NAA04494@zion.cs.uiuc.edu> Changes in directory llvm/docs/CommandGuide: llvm-prof.pod updated: 1.1 -> 1.2 --- Log message: NAME section is supposed to have a brief description, for apropos(1) & whatis(1) --- Diffs of the changes: (+1 -1) Index: llvm/docs/CommandGuide/llvm-prof.pod diff -u llvm/docs/CommandGuide/llvm-prof.pod:1.1 llvm/docs/CommandGuide/llvm-prof.pod:1.2 --- llvm/docs/CommandGuide/llvm-prof.pod:1.1 Fri May 14 13:03:22 2004 +++ llvm/docs/CommandGuide/llvm-prof.pod Fri May 14 13:31:13 2004 @@ -2,7 +2,7 @@ =head1 NAME -llvm-prof +llvm-prof - print execution profile of LLVM program =head1 SYNOPSIS From brukman at cs.uiuc.edu Fri May 14 13:54:03 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 14 13:54:03 2004 Subject: [llvm-commits] CVS: llvm/docs/index.html Message-ID: <200405141854.NAA11446@zion.cs.uiuc.edu> Changes in directory llvm/docs: index.html updated: 1.13 -> 1.14 --- Log message: Make link to HowToSubmitABug.html local instead of to LLVM website. --- Diffs of the changes: (+5 -5) Index: llvm/docs/index.html diff -u llvm/docs/index.html:1.13 llvm/docs/index.html:1.14 --- llvm/docs/index.html:1.13 Thu May 13 11:37:23 2004 +++ llvm/docs/index.html Fri May 14 13:54:04 2004 @@ -51,10 +51,10 @@ mailing list is monitored by all the people in the LLVM group at Illinois, and you should expect prompt first responses. -

  • Please read How -to submit a bug for tips on how to track down bugs to their correct -originating component -- sometimes, it's a bug in external software and not in -LLVM, or for help with debugging your own LLVM passes and extensions.
  • +
  • Please read How to submit a bug for tips +on how to track down bugs to their correct originating component -- sometimes, +it's a bug in external software and not in LLVM, or for help with debugging your +own LLVM passes and extensions.
  • We now use Bugzilla to track bugs, so you can submit bugs and check their progress in real-time.
  • @@ -178,7 +178,7 @@ John Criswell
    LLVM Compiler Infrastructure
    - Last modified: $Date: 2004/05/13 16:37:23 $ + Last modified: $Date: 2004/05/14 18:54:04 $ From brukman at cs.uiuc.edu Fri May 14 13:57:02 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 14 13:57:02 2004 Subject: [llvm-commits] CVS: llvm/docs/HowToSubmitABug.html Message-ID: <200405141857.NAA23159@zion.cs.uiuc.edu> Changes in directory llvm/docs: HowToSubmitABug.html updated: 1.19 -> 1.20 --- Log message: Mention the --tool-args option that Brian and Chris added. --- Diffs of the changes: (+11 -5) Index: llvm/docs/HowToSubmitABug.html diff -u llvm/docs/HowToSubmitABug.html:1.19 llvm/docs/HowToSubmitABug.html:1.20 --- llvm/docs/HowToSubmitABug.html:1.19 Wed May 12 16:26:16 2004 +++ llvm/docs/HowToSubmitABug.html Fri May 14 13:57:24 2004 @@ -272,15 +272,21 @@

    To debug the JIT:

    -

    bugpoint -run-jit -output=[correct output file] [bytecode file] ---args -- [program arguments]

    +
    +bugpoint -run-jit -output=[correct output file] [bytecode file]  \
    +         --tool-args -- [arguments to pass to lli]               \
    +         --args -- [program arguments]
    +

    Similarly, to debug the LLC, one would run:

    -

    bugpoint -run-llc -output=[correct output file] [bytecode file] ---args -- [program arguments]

    +
    +bugpoint -run-llc -output=[correct output file] [bytecode file]  \
    +         --tool-args -- [arguments to pass to llc]               \
    +         --args -- [program arguments]
    +

    Special note: if you are debugging MultiSource or SPEC tests that @@ -341,7 +347,7 @@ Chris Lattner
    The LLVM Compiler Infrastructure
    - Last modified: $Date: 2004/05/12 21:26:16 $ + Last modified: $Date: 2004/05/14 18:57:24 $ From brukman at cs.uiuc.edu Fri May 14 14:04:09 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 14 14:04:09 2004 Subject: [llvm-commits] CVS: llvm/docs/HowToSubmitABug.html Message-ID: <200405141904.OAA03102@zion.cs.uiuc.edu> Changes in directory llvm/docs: HowToSubmitABug.html updated: 1.20 -> 1.21 --- Log message: Use

     instead of 

    combo to decrease space used for code blocks. --- Diffs of the changes: (+37 -31) Index: llvm/docs/HowToSubmitABug.html diff -u llvm/docs/HowToSubmitABug.html:1.20 llvm/docs/HowToSubmitABug.html:1.21 --- llvm/docs/HowToSubmitABug.html:1.20 Fri May 14 13:57:24 2004 +++ llvm/docs/HowToSubmitABug.html Fri May 14 14:04:07 2004 @@ -148,8 +148,7 @@ -save-temps option to llvm-gcc. Then run:

    -

    gccas -debug-pass=Arguments < /dev/null -o - > /dev/null -

    +
    gccas -debug-pass=Arguments < /dev/null -o - > /dev/null

    ... which will print a list of arguments, indicating the list of passes that @@ -172,8 +171,9 @@ the full list of objects linked). Then run:

    -

    llvm-as < /dev/null > null.bc - gccld -debug-pass=Arguments null.bc

    +
    +llvm-as < /dev/null > null.bc
    +gccld -debug-pass=Arguments null.bc

    ... which will print a list of arguments, indicating the list of passes that @@ -196,7 +196,7 @@ something tractable, use the bugpoint tool as follows:

    -

    bugpoint <input files> <list of passes>

    +
    bugpoint <input files> <list of passes>

    bugpoint will print a bunch of output as it reduces the @@ -242,8 +242,8 @@ JIT, or LLC) and optionally a series of LLVM passes to run. For example:

    -

    bugpoint -run-cbe [... optimization passes ...] file-to-test.bc ---args -- [program arguments]

    +
    +bugpoint -run-cbe [... optimization passes ...] file-to-test.bc --args -- [program arguments]

    bugpoint will try to narrow down your list of passes to the one pass @@ -295,8 +295,10 @@ will pass the program options specified in the Makefiles:

    -

    cd llvm/test/../../program
    - make bugpoint-jit

    +
    +cd llvm/test/../../program
    +make bugpoint-jit
    +

    At the end of a successful bugpoint run, you will be presented @@ -309,28 +311,32 @@

      -
    1. Regenerate the shared object from the safe bytecode file:

      +
    2. Regenerate the shared object from the safe bytecode file:

      + +
      +
      +llc -march=c safe.bc -o safe.c
      +gcc -shared safe.c -o safe.so
      +
      +
    3. + +
    4. If debugging LLC, compile test bytecode native and link with the shared + object:

      -
      -

      llc -march=c safe.bc -o safe.c
      - gcc -shared safe.c -o safe.so

      -
    5. - -
    6. If debugging LLC, compile test bytecode native and link with the shared - object:

      - -
      -

      llc test.bc -o test.s -f
      - gcc test.s safe.so -o test.llc
      - ./test.llc [program options]

      -
    7. - -
    8. If debugging the JIT, load the shared object and supply the test - bytecode:

      - -
      -

      lli -load=safe.so test.bc [program options]

      -
    9. +
      +
      +llc test.bc -o test.s -f
      +gcc test.s safe.so -o test.llc
      +./test.llc [program options]
      +
      +
      + +
    10. If debugging the JIT, load the shared object and supply the test + bytecode:

      + +
      +
      lli -load=safe.so test.bc [program options]
      +
    @@ -347,7 +353,7 @@ Chris Lattner
    The LLVM Compiler Infrastructure
    - Last modified: $Date: 2004/05/14 18:57:24 $ + Last modified: $Date: 2004/05/14 19:04:07 $ From gaeke at cs.uiuc.edu Fri May 14 14:50:01 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Fri May 14 14:50:01 2004 Subject: [llvm-commits] CVS: llvm/docs/CommandGuide/Makefile llc.pod lli.pod Message-ID: <200405141950.OAA07681@zion.cs.uiuc.edu> Changes in directory llvm/docs/CommandGuide: Makefile added (r1.1) llc.pod added (r1.1) lli.pod added (r1.1) --- Log message: More pods... work in progress --- Diffs of the changes: (+303 -0) Index: llvm/docs/CommandGuide/Makefile diff -c /dev/null llvm/docs/CommandGuide/Makefile:1.1 *** /dev/null Fri May 14 14:50:43 2004 --- llvm/docs/CommandGuide/Makefile Fri May 14 14:50:33 2004 *************** *** 0 **** --- 1,23 ---- + POD = $(wildcard *.pod) + HTML = $(patsubst %.pod, %.html, $(POD)) + MAN = $(patsubst %.pod, %.1, $(POD)) + PS = $(patsubst %.pod, %.ps, $(POD)) + + all: $(HTML) $(MAN) $(PS) + + .SUFFIXES: + .SUFFIXES: .html .pod .1 .ps + + %.html: %.pod + pod2html --css=http://www.perldoc.com/css/perldoc.css \ + --podpath=/`pwd` --noindex --infile=$< --outfile=$@ + + %.1: %.pod + pod2man --release=1.3 --center="LLVM User's Guide" $< $@ + + %.ps: %.1 + groff -Tps -man $< > $@ + + clean: + rm -f pod2htm*.*~~ $(HTML) $(MAN) $(PS) + Index: llvm/docs/CommandGuide/llc.pod diff -c /dev/null llvm/docs/CommandGuide/llc.pod:1.1 *** /dev/null Fri May 14 14:50:43 2004 --- llvm/docs/CommandGuide/llc.pod Fri May 14 14:50:33 2004 *************** *** 0 **** --- 1,204 ---- + + =pod + + =head1 NAME + + llc - LLVM static compiler + + =head1 SYNOPSIS + + llc [options] [filename] + + =head1 DESCRIPTION + + The B command compiles LLVM bytecode into assembly language for a + specified architecture. The assembly language output can then be passed through + a native assembler and linker to generate native code. + + The choice of architecture for the output assembly code is determined as + follows, by attempting to satisfy each of the following rules in turn (first + one wins): + + =over + + =item * + + If the user has specified an architecture with the -m option, use that + architecture. + + =item * + + Examine the input LLVM bytecode file: if it is little endian and has a + pointer size of 32 bits, select the Intel IA-32 architecture. If it is big + endian and has a pointer size of 64 bits, select the SparcV9 architecture. + + =item * + + If B was compiled on an architecture for which it can generate code, select + the architecture upon which B was compiled. + + =item * + + Exit with an error message telling the user to specify the output + architecture explicitly. + + =back + + =head1 OPTIONS + + If I is - or omitted, B reads LLVM bytecode from standard input. + Otherwise, it will read LLVM bytecode from I. + + If the B<-o> option is omitted, then B will send its output to standard + output if the input is from standard input. If the B<-o> option specifies -, + then the output will also be sent to standard output. + + If no B<-o> option is specified and an input file other than - is specified, + then B creates the output filename by taking the input filename, + removing any existing F<.bc> extension, and adding a F<.s> suffix. + + Other B options are as follows: + + =over + + =item B<-f> + + Overwrite output files. By default, B will refuse to overwrite + an output file which already exists. + + =item B<-march>=I + + Specify the architecture for which to generate assembly. Valid + architectures are: + + =over + + =item I + + Intel IA-32 (Pentium and above) + + =item I + + 64-bit SPARC V9 + + =item I + + Emit C code, not assembly + + =back + + =item B<-enable-correct-eh-support> + + Instruct the B<-lowerinvoke> pass to insert code for correct exception handling + support. This is expensive and is by default omitted for efficiency. + + =item B<-help> + + Print a summary of command line options. + + =item B<-stats> + + Print statistics recorded by code-generation passes. + + =item B<-time-passes> + + Record the amount of time needed for each pass and print a report to standard + error. + + =back + + =head2 Intel IA-32-specific Options + + =over + + =item B<--disable-fp-elim> + + Disable frame pointer elimination optimization. + + =item B<--disable-pattern-isel> + + Use the 'simple' X86 instruction selector (the default). + + =item B<--print-machineinstrs> + + Print generated machine code. + + =item B<--regalloc>=I + + Specify the register allocator to use. The default I is I. + Valid register allocators are: + + =over + + =item I + + Very simple "always spill" register allocator + + =item I + + Local register allocator + + =item I + + Linear scan global register allocator (experimental) + + =back + + =item B<--spiller>=I + + Specify the spiller to use for register allocators that support it. Currently + this option is used only by the linear scan register allocator. The default + I is I. Valid spillers are: + + =over + + =item I + + Simple spiller + + =item I + + Local spiller + + =back + + =back + + =head2 SPARCV9-specific Options + + =over + + =item B<--disable-peephole> + + Disable peephole optimization pass. + + =item B<--disable-sched> + + Disable local scheduling pass. + + =item B<--disable-strip> + + The Sparc backend embeds the LLVM bytecode into the assembly output. This + option requests that symbol names be retained; by default, they are stripped out. + + =item B<--enable-maps> + + Emit LLVM-to-machine code mapping information into the assembly output. + + =back + + =head1 EXIT STATUS + + If B succeeds, it will exit with 0. Otherwise, if an error occurs, + it will exit with a non-zero value. + + =head1 SEE ALSO + + L + + =head1 AUTHORS + + Maintained by the LLVM Team (L). + + =cut + Index: llvm/docs/CommandGuide/lli.pod diff -c /dev/null llvm/docs/CommandGuide/lli.pod:1.1 *** /dev/null Fri May 14 14:50:43 2004 --- llvm/docs/CommandGuide/lli.pod Fri May 14 14:50:33 2004 *************** *** 0 **** --- 1,76 ---- + =pod + + =head1 NAME + + lli - directly execute programs from LLVM bytecode + + =head1 SYNOPSIS + + lli [options] [filename] [args ...] + + =head1 DESCRIPTION + + B directly executes programs in LLVM bytecode format. It takes a program in + LLVM bytecode format and executes it using a just-in-time compiler, if one is + available for the current architecture, or an interpreter. B takes + all of the same code generator options as L, but they are only effective + when B is using the just-in-time compiler. + + If I is not specified, then B reads the LLVM bytecode for the + program from standard input. + + The optional I specified on the command line are passed to the program as + arguments. + + =head1 OPTIONS + + =over + + =item B<-help> + + Print a summary of command line options. + + =item B<-stats> + + Print statistics from the code-generation passes. This is only meaningful for + the just-in-time compiler, at present. + + =item B<-time-passes> + + Record the amount of time needed for each code-generation pass and print it to + standard error. + + =item B<-march>=I + + Use the specified non-default architecture arch when selecting a code generator + for the just-in-time compiler. This may result in a crash if you pick an + architecture which is not compatible with the hardware you are running B on. + + =item B<-force-interpreter>=I<{false,true}> + + If set to true, use the interpreter even if a just-in-time compiler is available + for this architecture. Defaults to false. + + =item B<-f>=I + + Call the function named I to start the program. Note: The + function is assumed to have the C signature C I C<(int, + char **, char **)>. If you try to use this option to call a function of + incompatible type, undefined behavior may result. Defaults to C
    . + + =back + + =head1 EXIT STATUS + + If B fails to load the program, it will exit with an exit code of 1. + Otherwise, it will return the exit code of the program it executes. + + =head1 SEE ALSO + + L + + =head1 AUTHOR + + Maintained by the LLVM Team (L). + + =cut From brukman at cs.uiuc.edu Fri May 14 15:22:02 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 14 15:22:02 2004 Subject: [llvm-commits] CVS: llvm/docs/CommandGuide/man/ Message-ID: <200405142022.PAA22385@zion.cs.uiuc.edu> Changes in directory llvm/docs/CommandGuide/man: --- Log message: Directory /home/vadve/shared/PublicCVS/llvm/docs/CommandGuide/man added to the repository --- Diffs of the changes: (+0 -0) From brukman at cs.uiuc.edu Fri May 14 15:22:10 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 14 15:22:10 2004 Subject: [llvm-commits] CVS: llvm/docs/CommandGuide/ps/ Message-ID: <200405142022.PAA22387@zion.cs.uiuc.edu> Changes in directory llvm/docs/CommandGuide/ps: --- Log message: Directory /home/vadve/shared/PublicCVS/llvm/docs/CommandGuide/ps added to the repository --- Diffs of the changes: (+0 -0) From brukman at cs.uiuc.edu Fri May 14 15:22:19 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 14 15:22:19 2004 Subject: [llvm-commits] CVS: llvm/docs/CommandGuide/html/ Message-ID: <200405142022.PAA22325@zion.cs.uiuc.edu> Changes in directory llvm/docs/CommandGuide/html: --- Log message: Directory /home/vadve/shared/PublicCVS/llvm/docs/CommandGuide/html added to the repository --- Diffs of the changes: (+0 -0) From brukman at cs.uiuc.edu Fri May 14 15:24:01 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 14 15:24:01 2004 Subject: [llvm-commits] CVS: llvm/docs/CommandGuide/man/man1/ Message-ID: <200405142024.PAA18392@zion.cs.uiuc.edu> Changes in directory llvm/docs/CommandGuide/man/man1: --- Log message: Directory /home/vadve/shared/PublicCVS/llvm/docs/CommandGuide/man/man1 added to the repository --- Diffs of the changes: (+0 -0) From brukman at cs.uiuc.edu Fri May 14 15:25:01 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 14 15:25:01 2004 Subject: [llvm-commits] CVS: llvm/docs/CommandGuide/Makefile Message-ID: <200405142025.PAA29723@zion.cs.uiuc.edu> Changes in directory llvm/docs/CommandGuide: Makefile updated: 1.1 -> 1.2 --- Log message: Put outputs of each type into a separate subdirectory. --- Diffs of the changes: (+8 -8) Index: llvm/docs/CommandGuide/Makefile diff -u llvm/docs/CommandGuide/Makefile:1.1 llvm/docs/CommandGuide/Makefile:1.2 --- llvm/docs/CommandGuide/Makefile:1.1 Fri May 14 14:50:33 2004 +++ llvm/docs/CommandGuide/Makefile Fri May 14 15:24:59 2004 @@ -1,21 +1,21 @@ POD = $(wildcard *.pod) -HTML = $(patsubst %.pod, %.html, $(POD)) -MAN = $(patsubst %.pod, %.1, $(POD)) -PS = $(patsubst %.pod, %.ps, $(POD)) +HTML = $(patsubst %.pod, html/%.html, $(POD)) +MAN = $(patsubst %.pod, man/man1/%.1, $(POD)) +PS = $(patsubst %.pod, ps/%.ps, $(POD)) all: $(HTML) $(MAN) $(PS) .SUFFIXES: .SUFFIXES: .html .pod .1 .ps -%.html: %.pod - pod2html --css=http://www.perldoc.com/css/perldoc.css \ - --podpath=/`pwd` --noindex --infile=$< --outfile=$@ +html/%.html: %.pod + pod2html --css=manpage.css --htmlroot=. \ + --podpath=. --noindex --infile=$< --outfile=$@ -%.1: %.pod +man/man1/%.1: %.pod pod2man --release=1.3 --center="LLVM User's Guide" $< $@ -%.ps: %.1 +ps/%.ps: man/man1/%.1 groff -Tps -man $< > $@ clean: From brukman at cs.uiuc.edu Fri May 14 15:25:11 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 14 15:25:11 2004 Subject: [llvm-commits] CVS: llvm/docs/CommandGuide/html/manpage.css Message-ID: <200405142025.PAA08760@zion.cs.uiuc.edu> Changes in directory llvm/docs/CommandGuide/html: manpage.css added (r1.1) --- Log message: This is the stylesheet used by perldoc.com; we shall modify it as we see fit. --- Diffs of the changes: (+256 -0) Index: llvm/docs/CommandGuide/html/manpage.css diff -c /dev/null llvm/docs/CommandGuide/html/manpage.css:1.1 *** /dev/null Fri May 14 15:25:45 2004 --- llvm/docs/CommandGuide/html/manpage.css Fri May 14 15:25:35 2004 *************** *** 0 **** --- 1,256 ---- + /* Based on http://www.perldoc.com/css/perldoc.css */ + + @import url("../llvm.css"); + + body { font-family: Arial,Helvetica; } + + blockquote { margin: 10pt; } + + h1, a { color: #336699; } + + + /*** Top menu style ****/ + .mmenuon { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #ff6600; font-size: 10pt; + } + .mmenuoff { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #ffffff; font-size: 10pt; + } + .cpyright { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #ffffff; font-size: xx-small; + } + .cpyrightText { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #ffffff; font-size: xx-small; + } + .sections { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: 11pt; + } + .dsections { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: 12pt; + } + .slink { + font-family: Arial,Helvetica; font-weight: normal; text-decoration: none; + color: #000000; font-size: 9pt; + } + + .slink2 { font-family: Arial,Helvetica; text-decoration: none; color: #336699; } + + .maintitle { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: 18pt; + } + .dblArrow { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: small; + } + .menuSec { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: small; + } + + .newstext { + font-family: Arial,Helvetica; font-size: small; + } + + .linkmenu { + font-family: Arial,Helvetica; color: #000000; font-weight: bold; + text-decoration: none; + } + + P { + font-family: Arial,Helvetica; + } + + PRE { + font-size: 10pt; + } + .quote { + font-family: Times; text-decoration: none; + color: #000000; font-size: 9pt; font-style: italic; + } + .smstd { font-family: Arial,Helvetica; color: #000000; font-size: x-small; } + .std { font-family: Arial,Helvetica; color: #000000; } + .meerkatTitle { + font-family: sans-serif; font-size: x-small; color: black; } + + .meerkatDescription { font-family: sans-serif; font-size: 10pt; color: black } + .meerkatCategory { + font-family: sans-serif; font-size: 9pt; font-weight: bold; font-style: italic; + color: brown; } + .meerkatChannel { + font-family: sans-serif; font-size: 9pt; font-style: italic; color: brown; } + .meerkatDate { font-family: sans-serif; font-size: xx-small; color: #336699; } + + .tocTitle { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #333333; font-size: 10pt; + } + + .toc-item { + font-family: Arial,Helvetica; font-weight: bold; + color: #336699; font-size: 10pt; text-decoration: underline; + } + + .perlVersion { + font-family: Arial,Helvetica; font-weight: bold; + color: #336699; font-size: 10pt; text-decoration: none; + } + + .podTitle { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #000000; + } + + .docTitle { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #000000; font-size: 10pt; + } + .dotDot { + font-family: Arial,Helvetica; font-weight: bold; + color: #000000; font-size: 9pt; + } + + .docSec { + font-family: Arial,Helvetica; font-weight: normal; + color: #333333; font-size: 9pt; + } + .docVersion { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: 10pt; + } + + .docSecs-on { + font-family: Arial,Helvetica; font-weight: normal; text-decoration: none; + color: #ff0000; font-size: 10pt; + } + .docSecs-off { + font-family: Arial,Helvetica; font-weight: normal; text-decoration: none; + color: #333333; font-size: 10pt; + } + + h2 { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: medium; + } + h1 { + font-family: Verdana,Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: large; + } + + DL { + font-family: Arial,Helvetica; font-weight: normal; text-decoration: none; + color: #333333; font-size: 10pt; + } + + UL > LI > A { + font-family: Arial,Helvetica; font-weight: bold; + color: #336699; font-size: 10pt; + } + + .moduleInfo { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #333333; font-size: 11pt; + } + + .moduleInfoSec { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: 10pt; + } + + .moduleInfoVal { + font-family: Arial,Helvetica; font-weight: normal; text-decoration: underline; + color: #000000; font-size: 10pt; + } + + .cpanNavTitle { + font-family: Arial,Helvetica; font-weight: bold; + color: #ffffff; font-size: 10pt; + } + .cpanNavLetter { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #333333; font-size: 9pt; + } + .cpanCat { + font-family: Arial,Helvetica; font-weight: bold; text-decoration: none; + color: #336699; font-size: 9pt; + } + + .bttndrkblue-bkgd-top { + background-color: #225688; + background-image: url(/global/mvc_objects/images/bttndrkblue_bgtop.gif); + } + .bttndrkblue-bkgd-left { + background-color: #225688; + background-image: url(/global/mvc_objects/images/bttndrkblue_bgleft.gif); + } + .bttndrkblue-bkgd { + padding-top: 0px; + padding-bottom: 0px; + margin-bottom: 0px; + margin-top: 0px; + background-repeat: no-repeat; + background-color: #225688; + background-image: url(/global/mvc_objects/images/bttndrkblue_bgmiddle.gif); + vertical-align: top; + } + .bttndrkblue-bkgd-right { + background-color: #225688; + background-image: url(/global/mvc_objects/images/bttndrkblue_bgright.gif); + } + .bttndrkblue-bkgd-bottom { + background-color: #225688; + background-image: url(/global/mvc_objects/images/bttndrkblue_bgbottom.gif); + } + .bttndrkblue-text a { + color: #ffffff; + text-decoration: none; + } + a.bttndrkblue-text:hover { + color: #ffDD3C; + text-decoration: none; + } + .bg-ltblue { + background-color: #f0f5fa; + } + + .border-left-b { + background: #f0f5fa url(/i/corner-leftline.gif) repeat-y; + } + + .border-right-b { + background: #f0f5fa url(/i/corner-rightline.gif) repeat-y; + } + + .border-top-b { + background: #f0f5fa url(/i/corner-topline.gif) repeat-x; + } + + .border-bottom-b { + background: #f0f5fa url(/i/corner-botline.gif) repeat-x; + } + + .border-right-w { + background: #ffffff url(/i/corner-rightline.gif) repeat-y; + } + + .border-top-w { + background: #ffffff url(/i/corner-topline.gif) repeat-x; + } + + .border-bottom-w { + background: #ffffff url(/i/corner-botline.gif) repeat-x; + } + + .bg-white { + background-color: #ffffff; + } + + .border-left-w { + background: #ffffff url(/i/corner-leftline.gif) repeat-y; + } From brukman at cs.uiuc.edu Fri May 14 15:26:02 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 14 15:26:02 2004 Subject: [llvm-commits] CVS: llvm/docs/CommandGuide/ps/.cvsignore Message-ID: <200405142026.PAA20155@zion.cs.uiuc.edu> Changes in directory llvm/docs/CommandGuide/ps: .cvsignore added (r1.1) --- Log message: Ignore generated ps files. --- Diffs of the changes: (+1 -0) Index: llvm/docs/CommandGuide/ps/.cvsignore diff -c /dev/null llvm/docs/CommandGuide/ps/.cvsignore:1.1 *** /dev/null Fri May 14 15:26:55 2004 --- llvm/docs/CommandGuide/ps/.cvsignore Fri May 14 15:26:45 2004 *************** *** 0 **** --- 1 ---- + *ps From brukman at cs.uiuc.edu Fri May 14 15:26:11 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 14 15:26:11 2004 Subject: [llvm-commits] CVS: llvm/docs/CommandGuide/man/man1/.cvsignore Message-ID: <200405142026.PAA14115@zion.cs.uiuc.edu> Changes in directory llvm/docs/CommandGuide/man/man1: .cvsignore added (r1.1) --- Log message: Ignore generated man files. --- Diffs of the changes: (+1 -0) Index: llvm/docs/CommandGuide/man/man1/.cvsignore diff -c /dev/null llvm/docs/CommandGuide/man/man1/.cvsignore:1.1 *** /dev/null Fri May 14 15:26:49 2004 --- llvm/docs/CommandGuide/man/man1/.cvsignore Fri May 14 15:26:39 2004 *************** *** 0 **** --- 1 ---- + *.1 From brukman at cs.uiuc.edu Fri May 14 15:27:03 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 14 15:27:03 2004 Subject: [llvm-commits] CVS: llvm/docs/CommandGuide/html/.cvsignore Message-ID: <200405142027.PAA01407@zion.cs.uiuc.edu> Changes in directory llvm/docs/CommandGuide/html: .cvsignore added (r1.1) --- Log message: Ignore generated HTML files. --- Diffs of the changes: (+1 -0) Index: llvm/docs/CommandGuide/html/.cvsignore diff -c /dev/null llvm/docs/CommandGuide/html/.cvsignore:1.1 *** /dev/null Fri May 14 15:27:15 2004 --- llvm/docs/CommandGuide/html/.cvsignore Fri May 14 15:26:34 2004 *************** *** 0 **** --- 1 ---- + *html From brukman at cs.uiuc.edu Fri May 14 15:29:03 2004 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Fri May 14 15:29:03 2004 Subject: [llvm-commits] CVS: llvm/docs/CommandGuide/Makefile Message-ID: <200405142029.PAA22865@zion.cs.uiuc.edu> Changes in directory llvm/docs/CommandGuide: Makefile updated: 1.2 -> 1.3 --- Log message: Rename "User's Guide" to "Command Guide" to be consistent with current scheme. --- Diffs of the changes: (+1 -1) Index: llvm/docs/CommandGuide/Makefile diff -u llvm/docs/CommandGuide/Makefile:1.2 llvm/docs/CommandGuide/Makefile:1.3 --- llvm/docs/CommandGuide/Makefile:1.2 Fri May 14 15:24:59 2004 +++ llvm/docs/CommandGuide/Makefile Fri May 14 15:29:11 2004 @@ -13,7 +13,7 @@ --podpath=. --noindex --infile=$< --outfile=$@ man/man1/%.1: %.pod - pod2man --release=1.3 --center="LLVM User's Guide" $< $@ + pod2man --release=1.3 --center="LLVM Command Guide" $< $@ ps/%.ps: man/man1/%.1 groff -Tps -man $< > $@ From gaeke at cs.uiuc.edu Fri May 14 16:23:03 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Fri May 14 16:23:03 2004 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Instrumentation/ProfilePaths/InstLoops.cpp Message-ID: <200405142122.QAA21353@seraph.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Instrumentation/ProfilePaths: InstLoops.cpp updated: 1.12 -> 1.13 --- Log message: Clean up this pass somewhat: Add better comments, including a better head-of-file comment. Prune #includes. Fix a FIXME that Chris put here by using doInitialization(). Use DEBUG() to print out debug msgs. Give names to basic blocks inserted by this pass. Expand tabs. Use InsertProfilingInitCall() from ProfilingUtils to insert the initialize call. --- Diffs of the changes: (+38 -42) Index: llvm/lib/Transforms/Instrumentation/ProfilePaths/InstLoops.cpp diff -u llvm/lib/Transforms/Instrumentation/ProfilePaths/InstLoops.cpp:1.12 llvm/lib/Transforms/Instrumentation/ProfilePaths/InstLoops.cpp:1.13 --- llvm/lib/Transforms/Instrumentation/ProfilePaths/InstLoops.cpp:1.12 Thu Nov 20 12:25:21 2003 +++ llvm/lib/Transforms/Instrumentation/ProfilePaths/InstLoops.cpp Fri May 14 16:21:52 2004 @@ -7,25 +7,23 @@ // //===----------------------------------------------------------------------===// // -// Pass to instrument loops -// -// At every backedge, insert a counter for that backedge and a call function +// This is the first-level instrumentation pass for the Reoptimizer. It +// instrument the back-edges of loops by inserting a basic block +// containing a call to llvm_first_trigger (the first-level trigger function), +// and inserts an initialization call to the main() function. // //===----------------------------------------------------------------------===// #include "llvm/Analysis/Dominators.h" #include "llvm/Support/CFG.h" -#include "llvm/Constants.h" -#include "llvm/iMemory.h" -#include "llvm/GlobalVariable.h" -#include "llvm/DerivedTypes.h" #include "llvm/iOther.h" -#include "llvm/iOperators.h" +#include "llvm/Type.h" #include "llvm/iTerminators.h" #include "llvm/iPHINode.h" #include "llvm/Module.h" -#include "llvm/Function.h" #include "llvm/Pass.h" +#include "Support/Debug.h" +#include "../ProfilingUtils.h" namespace llvm { @@ -45,6 +43,7 @@ AU.addRequired(); } private: + Function *inCountMth; DominatorSet *DS; void getBackEdgesVisit(BasicBlock *u, std::map &color, @@ -53,6 +52,7 @@ void removeRedundant(BBMap &be); void findAndInstrumentBackEdges(Function &F); public: + bool doInitialization(Module &M); bool runOnFunction(Function &F); }; @@ -123,24 +123,19 @@ removeRedundant(be); - // FIXME: THIS IS HORRIBLY BROKEN. FunctionPass's cannot do this, except in - // their initialize function!! - Function *inCountMth = - F.getParent()->getOrInsertFunction("llvm_first_trigger", - Type::VoidTy, 0); - for(std::map::iterator MI = be.begin(), ME = be.end(); MI != ME; ++MI){ BasicBlock *u = MI->first; BasicBlock *BB = MI->second; - //std::cerr<<"Edge from: "<getName()<<"->"<getName()<<"\n"; - //insert a new basic block: modify terminator accordingly! - BasicBlock *newBB = new BasicBlock("", u->getParent()); + // We have a back-edge from BB --> u. + DEBUG (std::cerr << "Instrumenting back-edge from " << BB->getName () + << "-->" << u->getName () << "\n"); + // Split the back-edge, inserting a new basic block on it, and modify the + // source BB's terminator accordingly. + BasicBlock *newBB = new BasicBlock("backEdgeInst", u->getParent()); BranchInst *ti = cast(u->getTerminator()); - unsigned char index = 1; - if(ti->getSuccessor(0) == BB){ - index = 0; - } + unsigned char index = ((ti->getSuccessor(0) == BB) ? 0 : 1); + assert(ti->getNumSuccessors() > index && "Not enough successors!"); ti->setSuccessor(index, newBB); @@ -148,36 +143,37 @@ lt.push_back(new CallInst(inCountMth)); new BranchInst(BB, newBB); - //now iterate over *vl, and set its Phi nodes right + // Now, set the sources of Phi nodes corresponding to the back-edge + // in BB to come from the instrumentation block instead. for(BasicBlock::iterator BB2Inst = BB->begin(), BBend = BB->end(); - BB2Inst != BBend; ++BB2Inst){ - - if (PHINode *phiInst = dyn_cast(BB2Inst)){ - int bbIndex = phiInst->getBasicBlockIndex(u); - if(bbIndex>=0){ - phiInst->setIncomingBlock(bbIndex, newBB); - } + BB2Inst != BBend; ++BB2Inst) { + if (PHINode *phiInst = dyn_cast(BB2Inst)) { + int bbIndex = phiInst->getBasicBlockIndex(u); + if (bbIndex>=0) + phiInst->setIncomingBlock(bbIndex, newBB); } } } } -/// Entry point for FunctionPass that inserts calls to trigger function. +bool InstLoops::doInitialization (Module &M) { + inCountMth = M.getOrInsertFunction("llvm_first_trigger", Type::VoidTy, 0); + return true; // Module was modified. +} + +/// runOnFunction - Entry point for FunctionPass that inserts calls to +/// trigger function. /// bool InstLoops::runOnFunction(Function &F){ - DS = &getAnalysis(); - if(F.isExternal()) { + if (F.isExternal ()) return false; - } + + DS = &getAnalysis (); + // Add a call to reoptimizerInitialize() to beginning of function named main. - if(F.getName() == "main"){ - std::vector argTypes; // Empty formal parameter list. - const FunctionType *Fty = FunctionType::get(Type::VoidTy, argTypes, false); - Function *initialMeth = - F.getParent()->getOrInsertFunction("reoptimizerInitialize", Fty); - assert(initialMeth && "Initialize method could not be inserted!"); - new CallInst(initialMeth, "", F.begin()->begin()); // Insert it. - } + if (F.getName() == "main") + InsertProfilingInitCall (&F, "reoptimizerInitialize"); + findAndInstrumentBackEdges(F); return true; // Function was modified. } From dhurjati at cs.uiuc.edu Fri May 14 17:42:01 2004 From: dhurjati at cs.uiuc.edu (Dinakar Dhurjati) Date: Fri May 14 17:42:01 2004 Subject: [llvm-commits] CVS: poolalloc/include/poolalloc/PoolAllocate.h Message-ID: <200405142241.RAA03045@psmith.cs.uiuc.edu> Changes in directory poolalloc/include/poolalloc: PoolAllocate.h updated: 1.21 -> 1.22 --- Log message: Changed OneCalledFunction to take DSNode --- Diffs of the changes: (+5 -1) Index: poolalloc/include/poolalloc/PoolAllocate.h diff -u poolalloc/include/poolalloc/PoolAllocate.h:1.21 poolalloc/include/poolalloc/PoolAllocate.h:1.22 --- poolalloc/include/poolalloc/PoolAllocate.h:1.21 Tue Mar 2 22:01:15 2004 +++ poolalloc/include/poolalloc/PoolAllocate.h Fri May 14 17:41:35 2004 @@ -60,6 +60,10 @@ /// indirect function calls that are not used in the function. std::map PoolDescriptors; + //This is a map from Old to New Value Map reverse of the one above + //Useful in SAFECode for check insertion + std::map ValueMap; + /// NewToOldValueMap - When and if a function needs to be cloned, this map /// contains a mapping from all of the values in the new function back to /// the values they correspond to in the old function. @@ -111,7 +115,7 @@ /// OneCalledFunction - For each indirect function call, we keep track of one /// target of the call. This is used to find the equivalence class called by /// a call site. - std::map OneCalledFunction; + std::map OneCalledFunction; public: From dhurjati at cs.uiuc.edu Fri May 14 17:44:01 2004 From: dhurjati at cs.uiuc.edu (Dinakar Dhurjati) Date: Fri May 14 17:44:01 2004 Subject: [llvm-commits] CVS: poolalloc/lib/PoolAllocate/PoolAllocate.cpp Message-ID: <200405142243.RAA03068@psmith.cs.uiuc.edu> Changes in directory poolalloc/lib/PoolAllocate: PoolAllocate.cpp updated: 1.67 -> 1.68 --- Log message: Fixed couple of bugs (1) OneCalledFunction now takes DSNode instead of Function (2) All the globals are now replaced by the cloned version of the pool allocation --- Diffs of the changes: (+23 -6) Index: poolalloc/lib/PoolAllocate/PoolAllocate.cpp diff -u poolalloc/lib/PoolAllocate/PoolAllocate.cpp:1.67 poolalloc/lib/PoolAllocate/PoolAllocate.cpp:1.68 --- poolalloc/lib/PoolAllocate/PoolAllocate.cpp:1.67 Fri Apr 2 14:32:56 2004 +++ poolalloc/lib/PoolAllocate/PoolAllocate.cpp Fri May 14 17:43:09 2004 @@ -11,6 +11,7 @@ #include "llvm/DerivedTypes.h" #include "llvm/Instructions.h" #include "llvm/Module.h" +#include "llvm/Constants.h" #include "llvm/Analysis/DataStructure.h" #include "llvm/Analysis/DSGraph.h" #include "llvm/Analysis/DSGraphTraits.h" @@ -124,6 +125,19 @@ ProcessFunctionBody(*I, FI != FuncMap.end() ? *FI->second : *I); } + //Loop to replace all uses of original functions with new values + // create a new ConstantPtrRef + //create a new ConstantExpr cast + std::map::iterator fmI = FuncMap.begin(), + fmE = FuncMap.end(); + for (; fmI != fmE; ++fmI) { + Function *origF = fmI->first; + Function *cloneF = fmI->second; + + ConstantPointerRef *Ref = ConstantPointerRef::get(cloneF); + Constant *expr = ConstantExpr::getCast(Ref, origF->getType()); + origF->replaceAllUsesWith(expr); + } return true; } @@ -212,10 +226,11 @@ const PA::EquivClassInfo &PoolAllocate::getECIForIndirectCallSite(CallSite CS) { Instruction *I = CS.getInstruction(); assert(I && "Not a call site?"); - - if (!OneCalledFunction.count(I)) + Function *thisFunc = I->getParent()->getParent(); + DSNode *calleeNode = BU->getDSGraph(*thisFunc).getNodeForValue(CS.getCalledValue()).getNode(); + if (!OneCalledFunction.count(calleeNode)) return ECInfoForLeadersMap[0]; // Special null function for empty graphs - Function *Called = OneCalledFunction[I]; + Function *Called = OneCalledFunction[calleeNode]; Function *Leader = FuncECs.findClass(Called); assert(Leader && "Leader not found for indirect call target!"); assert(ECInfoForLeadersMap.count(Leader) && "No ECI for indirect call site!"); @@ -245,7 +260,11 @@ // This is the first callee from this call site. LastInst = I->first; FirstFunc = I->second; - OneCalledFunction[LastInst] = FirstFunc; + //Instead of storing the lastInst For Indirection call Sites we store the + //DSNode for the function ptr arguemnt + Function *thisFunc = LastInst->getParent()->getParent(); + DSNode *calleeNode = BU->getDSGraph(*thisFunc).getNodeForValue(CS.getCalledValue()).getNode(); + OneCalledFunction[calleeNode] = FirstFunc; FuncECs.addElement(I->second); } else { // This is not the first possible callee from a particular call site. @@ -935,7 +954,6 @@ DE = idf_ext_end(*I, DestroyedAfter); DI != DE; ++DI) /* empty */; } - // Now that we have created the sets, intersect them. std::set LiveBlocks; std::set_intersection(InitializedBefore.begin(),InitializedBefore.end(), @@ -988,7 +1006,6 @@ PoolInitInsertedBlocks.insert(*PI); } } - // Check the successors of this block. If some succs are not in the // set, insert destroys on those successor edges. If all succs are // not in the set, insert a destroy in this block. From gaeke at cs.uiuc.edu Sat May 15 19:02:02 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Sat May 15 19:02:02 2004 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/TraceToFunction.cpp Message-ID: <200405160001.TAA23502@seraph.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: TraceToFunction.cpp updated: 1.31 -> 1.32 --- Log message: Use a better class name for TraceToFunction, and add comments. Stub out an interface for finding FLI blocks. Apply a few minor simplifications. Expand some tabs. --- Diffs of the changes: (+48 -30) Index: reopt/lib/LightWtProfiling/TraceToFunction.cpp diff -u reopt/lib/LightWtProfiling/TraceToFunction.cpp:1.31 reopt/lib/LightWtProfiling/TraceToFunction.cpp:1.32 --- reopt/lib/LightWtProfiling/TraceToFunction.cpp:1.31 Fri May 14 12:58:20 2004 +++ reopt/lib/LightWtProfiling/TraceToFunction.cpp Sat May 15 19:00:52 2004 @@ -45,7 +45,10 @@ typedef std::vector TypeVector; typedef std::map BranchNumberMap; -class TraceToFunction { +/// TraceFunctionBuilder - a Method Object which encapsulates the algorithm +/// for building TraceFunctions given Traces. +/// +class TraceFunctionBuilder { BranchNumberMap BranchNumber; TraceFunction *TF; virtual TypeVector createFunctionArgTypeVector (PointerType *ST, @@ -55,9 +58,14 @@ BasicBlock *dstB, ValueMap &O2CMap, LiveVariableSet &So); public: - TraceToFunction () { } - virtual ~TraceToFunction () { } - virtual TraceFunction *traceToFunction (Trace &T); + TraceFunctionBuilder () { } + virtual ~TraceFunctionBuilder () { } + + /// buildTraceFunction - Given a Trace object, returns a pointer to a new + /// TraceFunction containing the same code as the Trace, along with some. + /// auxiliary data structures. + /// + virtual TraceFunction *buildTraceFunction (Trace &T); }; static bool dominates (Trace &T, const BasicBlock *B1, @@ -203,7 +211,7 @@ /// mapping between live-ins and parameters in /// TF->LiveInToParameterMap. /// -TypeVector TraceToFunction::createFunctionArgTypeVector (PointerType *PST, +TypeVector TraceFunctionBuilder::createFunctionArgTypeVector (PointerType *PST, LiveVariableSet S) { TypeVector P; P.push_back (PST); @@ -374,7 +382,7 @@ /// consistent and that the live-outs So get stored in F's first /// argument. /// -void TraceToFunction::fillInFunctionBody (Trace &T, Function *F, +void TraceFunctionBuilder::fillInFunctionBody (Trace &T, Function *F, LiveVariableSet &So) { ValueMap &O2CMap = TF->O2CMap; // First copy the basic blocks from the trace. @@ -395,13 +403,21 @@ fixupPhisAndCalls (FI, O2CMap); } +/// isFirstLevelInstrumentationBlock - returns true iff BB is a basic block +/// inserted by the first-level instrumentation (-instloops) pass. +/// +static bool isFirstLevelInstrumentationBlock (BasicBlock *BB) { + // not yet implemented + return false; +} + /// fixupFunctionBodyBB - Given srcB in T and its clone dstB in F, and /// the map O2CMap detailing the correspondences between values in T /// and values in F, fix up dstB so that its contents are internally /// consistent, and so that it stores its live-out values So in F's first /// argument. (This is where all the magic gets done...) /// -void TraceToFunction::fixupFunctionBodyBB (Trace &T, Function *F, +void TraceFunctionBuilder::fixupFunctionBodyBB (Trace &T, Function *F, BasicBlock *srcB, BasicBlock *dstB, ValueMap &O2CMap, LiveVariableSet &So) { @@ -496,8 +512,7 @@ }); assert(isa (V2) && "Clone of basic block on trace is not a basic block?"); - BasicBlock *BIsuccInF = cast (V2); - BIinF->setSuccessor (i, BIsuccInF); + BIinF->setSuccessor (i, cast (V2)); } } } @@ -518,10 +533,10 @@ TF->MatrixFn->getParent ()); std::cerr << " in instruction:\n " << I << " is argument " << TF->LiveInToParameterMap[V] << " in new function\n"); - assert (V->getType () == - getFunctionArg (F, TF->LiveInToParameterMap[V])->getType () - && "Live-in Value's type doesn't match corresponding arg type"); - I.setOperand(i, getFunctionArg (F, TF->LiveInToParameterMap[V])); + assert (V->getType () == + getFunctionArg (F, TF->LiveInToParameterMap[V])->getType () + && "Live-in Value's type doesn't match corresponding arg type"); + I.setOperand(i, getFunctionArg (F, TF->LiveInToParameterMap[V])); } // If the instruction I has an operand which is in the // trace, that operand will have been cloned into the @@ -529,23 +544,24 @@ // outside the function. Replace any reference to an operand // which has had a clone made with a reference to its clone. else if (O2CMap.find (V) != O2CMap.end () && O2CMap[V]) { - DEBUG(std::cerr << *V << " in instruction " << I - << " is value " << O2CMap[V] << " in new function\n"); - assert (V->getType () == O2CMap[V]->getType () - && "Value's type doesn't match clone's type"); - I.setOperand(i, O2CMap[V]); + DEBUG(std::cerr << *V << " in instruction " << I + << " is value " << O2CMap[V] << " in new function\n"); + assert (V->getType () == O2CMap[V]->getType () + && "Value's type doesn't match clone's type"); + I.setOperand(i, O2CMap[V]); } } + // Make sure that our operand fixups did not try to branch into a // BB outside the trace function or a non-cloned BB. DEBUG(if (BranchInst *BrI = dyn_cast (&I)) { for (unsigned i = 0; i < BrI->getNumSuccessors (); ++i) { BasicBlock *succ = BrI->getSuccessor (i); - assert (succ->getParent () == F - && "Branch out of function missed by copyTraceToFunction"); - assert (O2CMap.find (succ) == O2CMap.end () - && "Branch's clone found as key in original-->clone map; " - "no one told me today was opposite day!"); + assert (succ->getParent () == F + && "Branch out of function missed by fixupFunctionBodyBB"); + assert (O2CMap.find (succ) == O2CMap.end () + && "Branch's clone found as key in original-->clone map; " + "no one told me today was opposite day!"); } }); } @@ -555,7 +571,7 @@ /// Only called when debugging. /// static void cloneMapDump (TraceFunction *TF, std::ostream &OS) { - OS << "\n; TraceToFunction Original-->Clone map follows:\n"; + OS << "\n; TraceFunctionBuilder Original-->Clone map follows:\n"; for (ValueMap::const_iterator i = TF->O2CMap.begin(), e = TF->O2CMap.end(); i != e; ++i) { const std::pair &elem = *i; @@ -568,13 +584,13 @@ OS << "\n"; } -TraceFunction *TraceToFunction::traceToFunction (Trace &T) { +TraceFunction *TraceFunctionBuilder::buildTraceFunction (Trace &T) { // Create a TraceFunction object to hold the trace function along with // its auxiliary data structures. TF = new TraceFunction (T); std::string CurrentFnName = T.getFunction ()->getName (); - DEBUG(std::cerr << "In traceToFunction() for " << CurrentFnName << "\n"); + DEBUG(std::cerr << "In buildTraceFunction() for " << CurrentFnName << "\n"); DEBUG(T.dump ()); // Get some information about the trace's relationship to its parent @@ -598,11 +614,13 @@ return TF; } -/// runTraceToFunction - Entry point for TraceToFunction transformation. - +/// TraceFunction::get - Given a Trace, returns a TraceFunction, which is +/// a Function containing the code from the Trace along with some supporting +/// data structures. +/// TraceFunction *TraceFunction::get (Trace &T) { - TraceToFunction TTF; - return TTF.traceToFunction (T); + TraceFunctionBuilder TTF; + return TTF.buildTraceFunction (T); } } // end namespace llvm From gaeke at cs.uiuc.edu Sat May 15 19:25:01 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Sat May 15 19:25:01 2004 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/TraceToFunction.cpp Message-ID: <200405160024.TAA23728@seraph.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: TraceToFunction.cpp updated: 1.32 -> 1.33 --- Log message: Extract first-level trigger call detector out into isFirstTriggerCall(); isFirstLevelInstrumentationBlock is going to use it. --- Diffs of the changes: (+25 -14) Index: reopt/lib/LightWtProfiling/TraceToFunction.cpp diff -u reopt/lib/LightWtProfiling/TraceToFunction.cpp:1.32 reopt/lib/LightWtProfiling/TraceToFunction.cpp:1.33 --- reopt/lib/LightWtProfiling/TraceToFunction.cpp:1.32 Sat May 15 19:00:52 2004 +++ reopt/lib/LightWtProfiling/TraceToFunction.cpp Sat May 15 19:24:08 2004 @@ -288,6 +288,23 @@ } } +/// isFirstTriggerCall - Returns true iff I is a call instruction which appears +/// to call into the first-level trigger function. +/// +static bool isFirstTriggerCall (Instruction &I) { + if (CallInst *CI = dyn_cast (&I)) { + Function *CF = CI->getCalledFunction (); + // Look for an external function call with no args to "llvm_first_trigger". + if (CF && CF->isExternal () && CF->hasName() + && CF->getName () == "llvm_first_trigger" && CF->asize () == 0) { + DEBUG(std::cerr << " (Found a call instruction " << *CI + << " ... Smells like llvm_first_trigger.)\n"); + return true; + } + } + return false; +} + static void fixupPhisAndCalls (BasicBlock *dstB, ValueMap &O2CMap) { std::vector goners; Function *F = dstB->getParent (); @@ -349,19 +366,9 @@ // Remove calls to first-level instrumentation if we find them. for (BasicBlock::iterator BI = dstB->begin (), BE = dstB->end (); - BI != BE; ++BI) { - Instruction &I = *BI; - if (CallInst *CI = dyn_cast (&I)) { - Function *CF = CI->getCalledFunction (); - - if (CF && CF->isExternal () && CF->hasName() - && CF->getName () == "llvm_first_trigger") { - DEBUG(std::cerr << " (Found a call instruction " << *CI - << " ... Smells like llvm_first_trigger.)\n"); - goners.push_back (BI); - } - } - } + BI != BE; ++BI) + if (isFirstTriggerCall (*BI)) + goners.push_back (BI); while (!goners.empty ()) { assert (goners.back ()->use_size () == 0 @@ -407,7 +414,11 @@ /// inserted by the first-level instrumentation (-instloops) pass. /// static bool isFirstLevelInstrumentationBlock (BasicBlock *BB) { - // not yet implemented + BasicBlock::iterator i = BB->begin (); + if (!isFirstTriggerCall (*i)) + return false; + ++i; + // FIXME return false; } From gaeke at cs.uiuc.edu Sat May 15 19:29:01 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Sat May 15 19:29:01 2004 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/TraceToFunction.cpp Message-ID: <200405160028.TAA23850@seraph.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: TraceToFunction.cpp updated: 1.33 -> 1.34 --- Log message: Finish off isFirstLevelInstrumentationBlock() --- Diffs of the changes: (+9 -3) Index: reopt/lib/LightWtProfiling/TraceToFunction.cpp diff -u reopt/lib/LightWtProfiling/TraceToFunction.cpp:1.33 reopt/lib/LightWtProfiling/TraceToFunction.cpp:1.34 --- reopt/lib/LightWtProfiling/TraceToFunction.cpp:1.33 Sat May 15 19:24:08 2004 +++ reopt/lib/LightWtProfiling/TraceToFunction.cpp Sat May 15 19:28:41 2004 @@ -411,15 +411,21 @@ } /// isFirstLevelInstrumentationBlock - returns true iff BB is a basic block -/// inserted by the first-level instrumentation (-instloops) pass. +/// containing only a call to the first-level instrumentation function. +/// Basic blocks of this form are inserted by the -instloops pass on loop +/// back-edges. /// static bool isFirstLevelInstrumentationBlock (BasicBlock *BB) { BasicBlock::iterator i = BB->begin (); + // starts with llvm_first_trigger call if (!isFirstTriggerCall (*i)) return false; + // next thing is an unconditional branch ++i; - // FIXME - return false; + if (!(isa (i) && cast (i)->isUnconditional ())) + return false; + // looks like the real thing to me... + return true; } /// fixupFunctionBodyBB - Given srcB in T and its clone dstB in F, and From gaeke at cs.uiuc.edu Sat May 15 19:53:01 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Sat May 15 19:53:01 2004 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/TraceToFunction.cpp Message-ID: <200405160052.TAA24083@seraph.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: TraceToFunction.cpp updated: 1.34 -> 1.35 --- Log message: Since FLI blocks are only inserted on back-edges, make isFirstLevelInstrumentationBlock() return the back-edge target. This should allow us to fold the branch into the block's predecessor. Make fixupFunctionBodyBB() call it to try to detect FLI blocks. --- Diffs of the changes: (+17 -11) Index: reopt/lib/LightWtProfiling/TraceToFunction.cpp diff -u reopt/lib/LightWtProfiling/TraceToFunction.cpp:1.34 reopt/lib/LightWtProfiling/TraceToFunction.cpp:1.35 --- reopt/lib/LightWtProfiling/TraceToFunction.cpp:1.34 Sat May 15 19:28:41 2004 +++ reopt/lib/LightWtProfiling/TraceToFunction.cpp Sat May 15 19:52:05 2004 @@ -410,22 +410,22 @@ fixupPhisAndCalls (FI, O2CMap); } -/// isFirstLevelInstrumentationBlock - returns true iff BB is a basic block -/// containing only a call to the first-level instrumentation function. -/// Basic blocks of this form are inserted by the -instloops pass on loop -/// back-edges. +/// isFirstLevelInstrumentationBlock - returns a nonzero value iff BB is a +/// basic block containing only a call to the first-level instrumentation +/// function. Basic blocks of this form are inserted by the -instloops pass on +/// loop back-edges. The return value is the target of the back-edge. /// -static bool isFirstLevelInstrumentationBlock (BasicBlock *BB) { +static BasicBlock *isFirstLevelInstrumentationBlock (BasicBlock *BB) { BasicBlock::iterator i = BB->begin (); // starts with llvm_first_trigger call if (!isFirstTriggerCall (*i)) return false; - // next thing is an unconditional branch - ++i; - if (!(isa (i) && cast (i)->isUnconditional ())) - return false; - // looks like the real thing to me... - return true; + // Next instr. should be an unconditional branch - return its target, or NULL if + // there is a mismatch. + BranchInst *BI = dyn_cast (++i); + if (!(BI && BI->isUnconditional())) + return 0; + return BI->getSuccessor (0); } /// fixupFunctionBodyBB - Given srcB in T and its clone dstB in F, and @@ -480,6 +480,12 @@ && "Trace-exiting branch's clone is null, or not a branch?"); BranchInst *BIinF = cast (V); for (unsigned i = 0; i < BI->getNumSuccessors (); ++i) { + if (BasicBlock *backEdgeTarget = + isFirstLevelInstrumentationBlock (BI->getSuccessor (i))) { + std::cerr << "Branch instr " << *BI << " looks like an instrumented " + << "backedge from " << srcB->getName() << " to " + << backEdgeTarget->getName () << "\n"; + } if (!T.contains (BI->getSuccessor (i))) { // This is a trace-exiting destination of branch BI. Create a new // basic block FB for its destination in the function. From gaeke at cs.uiuc.edu Sat May 15 23:59:01 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Sat May 15 23:59:01 2004 Subject: [llvm-commits] CVS: reopt/lib/BinInterface/LLVMTrace.cpp Message-ID: <200405160458.XAA24279@seraph.cs.uiuc.edu> Changes in directory reopt/lib/BinInterface: LLVMTrace.cpp updated: 1.5 -> 1.6 --- Log message: Use DEBUG() for debug messages. Get rid of some of the using std:: directives and some commented-out code. Inline LLVMTrace constructor. Other very minor cleanups. --- Diffs of the changes: (+26 -58) Index: reopt/lib/BinInterface/LLVMTrace.cpp diff -u reopt/lib/BinInterface/LLVMTrace.cpp:1.5 reopt/lib/BinInterface/LLVMTrace.cpp:1.6 --- reopt/lib/BinInterface/LLVMTrace.cpp:1.5 Wed Nov 19 16:51:46 2003 +++ reopt/lib/BinInterface/LLVMTrace.cpp Sat May 15 23:58:06 2004 @@ -13,28 +13,18 @@ #include "llvm/iTerminators.h" #include "llvm/BasicBlock.h" #include "llvm/iPHINode.h" +#include "Support/Debug.h" #include -using std::map; -using std::cerr; -using std::vector; using namespace llvm; -LLVMTrace::LLVMTrace(BinInterface *b,VirtualMem *v, TraceCache *t){ - bb = b; - tr = t; - vm = v; -} - -void LLVMTrace::addTrace(map &bbToCid, - map &bbToSec, - map &removedBranch, - unsigned int lastSecId, unsigned int cidOffset, - unsigned int unroll){ -#ifdef FOR_DEBUG - cerr<<"Adding---------------------------\n"; -#endif - for(map::iterator MI = bbToCid.begin(), +void LLVMTrace::addTrace(std::map &bbToCid, + std::map &bbToSec, + std::map &removedBranch, + unsigned int lastSecId, unsigned int cidOffset, + unsigned int unroll) { + DEBUG(std::cerr<<"Adding trace.\n"); + for(std::map::iterator MI = bbToCid.begin(), ME = bbToCid.end(); MI != ME; ++MI){ if(!MI->second) @@ -50,48 +40,32 @@ if(BranchInst *br = dyn_cast(&*II)) continue; - vector positions = getLLVMInstrPositionInfo(II); + std::vector positions = getLLVMInstrPositionInfo(II); if(positions.size() == 0) continue; -#ifdef FOR_DEBUG - cerr<::iterator PI = positions.begin(), + DEBUG (std::cerr << II << "\t\tPushing back\n"); + for(std::vector::iterator PI = positions.begin(), PE = positions.end(); PI != PE; ++PI){ uint64_t addr = getBasicBlockInfo(MI->first).first; addr += (*PI)*4; -#ifdef FOR_DEBUG - std::cerr<<"Section: "<< bbToSec[MI->first]<<" Last: "<first] <= lastSecId) + DEBUG (std::cerr << "Section: " << bbToSec[MI->first] << " Last: " << lastSecId << "\n"); + if (bbToSec[MI->first] <= lastSecId) InstrToSec[II] = bbToSec[MI->first]; else InstrToSec[II] = 0; //see if previous instruction was a branch unsigned instr = vm->readInstrFrmVm(addr-4, tr); - //if((isBranchAlways(instr) || isBranchNever(instr)) && - // removedBranch[MI->first]){ - if(isBranchInstr(instr) && removedBranch[MI->first]){ + if(isBranchInstr(instr) && removedBranch[MI->first]) InstrToCid[II].push_back(MI->second+ *PI - 1); -#ifdef FOR_DEBUG - std::cerr<<(MI->second+ *PI - 1)<<"\n"; -#endif - } - else{ + else InstrToCid[II].push_back(MI->second+ *PI); -#ifdef FOR_DEBUG - std::cerr<<(MI->second+ *PI)<<"\n"; -#endif - } + DEBUG (std::cerr << InstrToCid[II].back () << "\n"); } } } -#ifdef FOR_DEBUG - cerr<<"-------------------------------\n"; -#endif + DEBUG (std::cerr << "Finished adding trace.\n"); traceInstructions = cidOffset; unrollFactor = unroll; numberOfEpilogs = (lastSecId - 1); @@ -105,35 +79,29 @@ void LLVMTrace::getAllCids(Instruction *I, vector &vec){ vec.clear(); for(unsigned int i = 0; i < unrollFactor; i++){ - for(vector::iterator VI = InstrToCid[I].begin(), + for(std::vector::iterator VI = InstrToCid[I].begin(), VE = InstrToCid[I].end(); VI != VE; ++VI) vec.push_back(*VI+traceInstructions*i); } } -unsigned int LLVMTrace::getSec(Instruction *I){ +unsigned int LLVMTrace::getSec(Instruction *I) { return InstrToSec[I]; } -void LLVMTrace::getAllSec(Instruction *I, vector &vec){ +void LLVMTrace::getAllSec(Instruction *I, vector &vec) { vec.clear(); - for(unsigned int i = 0; i < unrollFactor; i++){ + for(unsigned int i = 0; i < unrollFactor; i++) vec.push_back(InstrToSec[I] + numberOfEpilogs*i); - } } //Should be invoked BEFORE reduce() void LLVMTrace::moveInstrToSec(Instruction *I, unsigned int sec){ if(InstrToCid.find(I) != InstrToCid.end()){ -#ifdef FOR_DEBUG - std::cerr<<"Moving\n"; - std::cerr<::iterator VI = InstrToCid[I].begin(), + DEBUG (std::cerr << "Moving: " << I); + for(std::vector::iterator VI = InstrToCid[I].begin(), VE = InstrToCid[I].end(); VI != VE; ++VI){ -#ifdef FOR_DEBUG - std::cerr<<"ID: "<<*VI<<"\n"; -#endif + DEBUG (std::cerr << "ID: " << *VI << "\n"); bb->moveToEnd(*VI, sec); } } @@ -142,7 +110,7 @@ void LLVMTrace::moveInstrAfter(Instruction *I, unsigned int cid){ if(InstrToCid.find(I) != InstrToCid.end()){ unsigned int after = cid; - for(vector::iterator VI = InstrToCid[I].begin(), + for(std::vector::iterator VI = InstrToCid[I].begin(), VE = InstrToCid[I].end(); VI != VE; ++VI){ bb->move_instr(*VI, after); after = *VI; @@ -153,7 +121,7 @@ void LLVMTrace::moveInstrBefore(Instruction *I, unsigned int cid){ if(InstrToCid.find(I) != InstrToCid.end()){ unsigned int before = cid; - for(vector::iterator VI = InstrToCid[I].begin(), + for(std::vector::iterator VI = InstrToCid[I].begin(), VE = InstrToCid[I].end(); VI != VE; ++VI){ bb->move_instr_before(*VI, before); } From gaeke at cs.uiuc.edu Sat May 15 23:59:10 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Sat May 15 23:59:10 2004 Subject: [llvm-commits] CVS: reopt/include/reopt/BinInterface/LLVMTrace.h Message-ID: <200405160458.XAA24272@seraph.cs.uiuc.edu> Changes in directory reopt/include/reopt/BinInterface: LLVMTrace.h updated: 1.4 -> 1.5 --- Log message: Inline LLVMTrace constructor. --- Diffs of the changes: (+2 -2) Index: reopt/include/reopt/BinInterface/LLVMTrace.h diff -u reopt/include/reopt/BinInterface/LLVMTrace.h:1.4 reopt/include/reopt/BinInterface/LLVMTrace.h:1.5 --- reopt/include/reopt/BinInterface/LLVMTrace.h:1.4 Wed Nov 19 16:51:43 2003 +++ reopt/include/reopt/BinInterface/LLVMTrace.h Sat May 15 23:58:05 2004 @@ -33,7 +33,8 @@ unsigned numberOfEpilogs; public: - LLVMTrace(BinInterface *b, VirtualMem *v, TraceCache *t); + LLVMTrace(BinInterface *b, VirtualMem *v, TraceCache *t) + : bb (b), vm (v), tr (t) { } void addTrace(std::map &bbToCid, std::map &bbToSec, @@ -87,7 +88,6 @@ //move instruction to before an instruction cid void moveInstrBefore(Instruction *I, unsigned int cid); - }; } // end namespace llvm From gaeke at cs.uiuc.edu Sun May 16 00:13:02 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Sun May 16 00:13:02 2004 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/SLI.cpp Message-ID: <200405160512.AAA24408@seraph.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: SLI.cpp updated: 1.18 -> 1.19 --- Log message: A few minor refactorings. --- Diffs of the changes: (+5 -12) Index: reopt/lib/LightWtProfiling/SLI.cpp diff -u reopt/lib/LightWtProfiling/SLI.cpp:1.18 reopt/lib/LightWtProfiling/SLI.cpp:1.19 --- reopt/lib/LightWtProfiling/SLI.cpp:1.18 Fri Mar 5 13:44:17 2004 +++ reopt/lib/LightWtProfiling/SLI.cpp Sun May 16 00:12:14 2004 @@ -213,9 +213,6 @@ // a BasicBlock, but since branchAddr ends a basic block, we must scan // backwards hoping to find the beginning of its basic block. BasicBlock *root = 0, *end = 0; - // FIXME: Rewrite as: - // MappingInfo::reconstruct(M)->getBasicBlockForAddress (brTarget); - // returning either NULL or a valid BB *. assert(getReverseBBMap(brTarget, M, root) && "Branch target's BasicBlock not found in map!"); assert(root && "Branch target mapped to NULL BasicBlock?"); @@ -345,16 +342,15 @@ callMap[index] = getCallTarget(instr, addr); toInline[callTarget] = 1; index += 2; - addr += 4; - } else{ + } else { trace.push_back(call_code[0]); trace.push_back(instr); trace.push_back(vm->readInstrFrmVm(addr+4, tr, tr2)); trace.push_back(call_code[1]); callMap[index+1] = getCallTarget(instr, addr); index += 4; - addr += 4; } + addr += 4; } else{ trace.push_back(call_code[2]); //save o7 trace.push_back(loop_top_code[0]); @@ -414,19 +410,16 @@ assert((taken != vBB[0]) && "Conditional branch to top!"); trace[index] = succ0_code[0]; trace.push_back(succ0_code[1]); - trace.push_back(BRANCH_ALWAYS); - trace.push_back(NOP); branchStub[index+2] = taken; - index += 4; } else{ assert((ntaken != vBB[0]) && "Conditional branch to top!"); trace[index] = succ1_code[0]; trace.push_back(succ1_code[1]); - trace.push_back(BRANCH_ALWAYS); - trace.push_back(NOP); branchStub[index+2] = ntaken; - index += 4; } + trace.push_back(BRANCH_ALWAYS); // this is index+2, above + trace.push_back(NOP); + index += 4; } } } From gaeke at cs.uiuc.edu Sun May 16 00:24:01 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Sun May 16 00:24:01 2004 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/Makefile Message-ID: <200405160524.AAA07877@zion.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: Makefile updated: 1.7 -> 1.8 --- Log message: Make FirstTrigger compile on X86. --- Diffs of the changes: (+1 -1) Index: reopt/lib/LightWtProfiling/Makefile diff -u reopt/lib/LightWtProfiling/Makefile:1.7 reopt/lib/LightWtProfiling/Makefile:1.8 --- reopt/lib/LightWtProfiling/Makefile:1.7 Wed May 12 13:25:28 2004 +++ reopt/lib/LightWtProfiling/Makefile Sun May 16 00:24:37 2004 @@ -5,7 +5,7 @@ include $(LEVEL)/Makefile.config ifneq ($(ARCH),Sparc) -Source := Initialization.cpp RuntimeOptimizations.cpp SLI.cpp TraceOptEmitter.cpp TraceToFunction.cpp UnpackTraceFunction.cpp +Source := FirstTrigger.cpp Initialization.cpp RuntimeOptimizations.cpp SLI.cpp TraceOptEmitter.cpp TraceToFunction.cpp UnpackTraceFunction.cpp all :: @echo "This code assumes an LP64 machine- please ignore ptr cast warnings!" endif From gaeke at cs.uiuc.edu Sun May 16 00:24:09 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Sun May 16 00:24:09 2004 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/Initialization.cpp Message-ID: <200405160524.AAA07867@zion.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: Initialization.cpp updated: 1.16 -> 1.17 --- Log message: Change reoptimizerInitialize() to use the same signature as the other profiling init calls. --- Diffs of the changes: (+5 -1) Index: reopt/lib/LightWtProfiling/Initialization.cpp diff -u reopt/lib/LightWtProfiling/Initialization.cpp:1.16 reopt/lib/LightWtProfiling/Initialization.cpp:1.17 --- reopt/lib/LightWtProfiling/Initialization.cpp:1.16 Fri Apr 23 16:40:57 2004 +++ reopt/lib/LightWtProfiling/Initialization.cpp Sun May 16 00:23:57 2004 @@ -72,7 +72,9 @@ /// the opt -instloops pass /// (Transforms/Instrumentation/ProfilePaths/InstLoops.cpp). /// -extern "C" void reoptimizerInitialize(){ +extern "C" +int reoptimizerInitialize(int argc, const char **argv, + unsigned *arrayStart, unsigned numElements) { cl::ParseEnvironmentOptions ("reopt", "LLVM_REOPT", " llvm dynamic optimizer"); vm = new VirtualMem(); @@ -84,6 +86,8 @@ // Set up the phase-change detection stuff (normally disabled). if (enable_phase_detect) initialize_timer(); + + return argc; } /// Initialization method for the reoptimizer that parses the bytecode From gaeke at cs.uiuc.edu Sun May 16 00:24:17 2004 From: gaeke at cs.uiuc.edu (Brian Gaeke) Date: Sun May 16 00:24:17 2004 Subject: [llvm-commits] CVS: reopt/lib/LightWtProfiling/RegSaveRestore.h Message-ID: <200405160524.AAA07858@zion.cs.uiuc.edu> Changes in directory reopt/lib/LightWtProfiling: RegSaveRestore.h updated: 1.3 -> 1.4 --- Log message: If not on sparc, then these assembly macros should expand to nothing. --- Diffs of the changes: (+28 -0) Index: reopt/lib/LightWtProfiling/RegSaveRestore.h diff -u reopt/lib/LightWtProfiling/RegSaveRestore.h:1.3 reopt/lib/LightWtProfiling/RegSaveRestore.h:1.4 --- reopt/lib/LightWtProfiling/RegSaveRestore.h:1.3 Wed Jan 14 17:02:22 2004 +++ reopt/lib/LightWtProfiling/RegSaveRestore.h Sun May 16 00:24:19 2004 @@ -17,6 +17,8 @@ #ifndef REGSAVERESTORE_H #define REGSAVERESTORE_H +#if defined(__sparc__) + #define SAVE_I_REGS(i_reg_save) \ do { \ asm volatile ("stx %%i0, %0": "=m"(i_reg_save[0])); \ @@ -186,5 +188,31 @@ #define LOAD_CCR_REG(ccr_reg) \ asm volatile ("wr %0, 0, %%ccr":: "r"(ccr_reg)) + +#else // defined (__sparc__) + +// In non-SPARC compilation environments, the SAVE/LOAD macros expand to +// nothing. This lets the files compile (even though they won't work.) + +#define SAVE_I_REGS(i_reg_save) +#define LOAD_I_REGS(i_reg_save) +#define SAVE_G1_REG(g1_reg) +#define LOAD_G1_REG(g1_reg) +#define SAVE_G5_REG(g1_reg) +#define LOAD_G5_REG(g1_reg) +#define SAVE_F_REGS_1(f_reg_save) +#define LOAD_F_REGS_1(f_reg_save) +#define SAVE_F_REGS_2(f_reg_save) +#define LOAD_F_REGS_2(f_reg_save) +#define SAVE_FD_REGS(fd_reg_save) +#define LOAD_FD_REGS(fd_reg_save) +#define SAVE_FSR_REG(fsr_reg) +#define LOAD_FSR_REG(fsr_reg) +#define SAVE_FPRS_REG(fprs_reg) +#define LOAD_FPRS_REG(fprs_reg) +#define SAVE_CCR_REG(ccr_reg) +#define LOAD_CCR_REG(ccr_reg) + +#endif // defined (__sparc__) #endif // REGSAVERESTORE_H From llvm at cs.uiuc.edu Sun May 16 18:24:01 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Sun May 16 18:24:01 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/include/llvm/SymbolTable.h Message-ID: <200405162324.SAA30009@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm: SymbolTable.h updated: 1.30.6.1 -> 1.30.6.2 --- Log message: Revisions to support a separate map of name/type pairs and clarification of the interface of the SymbolTable. Three sets of iterators are now possible: (1) Over the type planes of values (plane_*), (2) Over the values in a type plane (value_*), and (3) Over the named types (type_*). --- Diffs of the changes: (+165 -178) Index: llvm/include/llvm/SymbolTable.h diff -u llvm/include/llvm/SymbolTable.h:1.30.6.1 llvm/include/llvm/SymbolTable.h:1.30.6.2 --- llvm/include/llvm/SymbolTable.h:1.30.6.1 Wed May 12 11:33:43 2004 +++ llvm/include/llvm/SymbolTable.h Sun May 16 18:24:36 2004 @@ -20,12 +20,16 @@ namespace llvm { /// This class provides a symbol table of name/value pairs that is broken -/// up by type. Each Type* represents a "type plane" in the symbol table. -/// Identical types may have overlapping symbol names as long as they are -/// distinct. Note that this implements a chained symbol table. If a name +/// up by type. For each Type* there is a "plane" of name/value pairs in +/// the symbol table. Identical types may have overlapping symbol names as +/// long as they are distinct. The SymbolTable also tracks separately a +/// map of name/type pairs. This allows types to be named. Types are treated +/// distinctly from Values since Types are not Values. +/// +/// Note that the value map implements a chained symbol table. If a name /// being looked up (with lookup()) isn't found in the current symbol /// table, then the parent symbol table is searched. This chaining behavior -/// does NOT affect iterators though: only the lookup method. +/// does NOT affect the iterators though: only the lookup method. /// /// The SymbolTable provides several utility functions for answering common /// questions about its contents as well as an iterator interface for @@ -37,11 +41,8 @@ /// @{ public: - /// @brief A mapping of names to values - typedef std::map ValueMap; - - /// @brief A mapping of types to names to values - typedef std::map TypeMap; + /// @brief A mapping of names to types + typedef std::map TypeMap; /// @brief An iterator over the TypeMap typedef TypeMap::iterator type_iterator; @@ -49,12 +50,24 @@ /// @brief A const_iterator over the TypeMap typedef TypeMap::const_iterator type_const_iterator; - /// @brief A iterator over a ValueMap + /// @brief A mapping of names to values + typedef std::map ValueMap; + + /// @brief An iterator over a ValueMap typedef ValueMap::iterator value_iterator; /// @brief A const_iterator over a ValueMap typedef ValueMap::const_iterator value_const_iterator; + /// @brief A mapping of types to names to values (type planes) + typedef std::map TypePlaneMap; + + /// @brief An iterator over the type planes + typedef TypePlaneMap::iterator plane_iterator; + + /// @brief A const_iterator over the type planes + typedef TypePlaneMap::const_iterator plane_const_iterator; + /// @} /// @name Constructors /// @{ @@ -69,31 +82,47 @@ public: /// This method finds the value with the given \p name in the - /// type plane \p Ty and returns it. + /// type plane \p Ty and returns it. This method will not find any + /// Types, only Values. Use lookupType to find Types by name. /// @returns null on failure, otherwise the Value associated with /// the \p name in type plane \p Ty. /// @brief Lookup a named, typed value. Value *lookup(const Type *Ty, const std::string &name) const; + /// This method finds the type with the given \p name in the + /// type map and returns it. + /// @returns null if the name is not found, otherwise the Type + /// associated with the \p name. + /// @brief Lookup a type by name. + Type* lookupType( const std::string& name ) const; + + /// @returns true iff the type map is not empty. /// @brief Determine if there are types in the symbol table - bool hasTypes( void ) const; + inline bool hasTypes() const { return ! tmap.empty(); } + /// @returns true iff the type map and the type plane are both not + /// empty. /// @brief Determine if the symbol table is empty - bool isEmpty( void ) const; + inline bool isEmpty() const { return pmap.empty() && tmap.empty(); } - /// The type plane associated with the \p TypeID parameter is - /// found and the number of entries in the plane is returned. - /// @returns Number of entries in the specified type plane. + /// The plane associated with the \p TypeID parameter is found + /// and the number of entries in the plane is returned. + /// @returns Number of entries in the specified type plane or 0. /// @brief Get the size of a type plane. - inline unsigned type_size(const Type *TypeID) const { - return map.find(TypeID)->second.size(); - } + inline unsigned type_size(const Type *TypeID) const; + + /// The number of name/type pairs is returned. + inline unsigned num_types() const { return tmap.size(); } /// Finds the value \p val in the symbol table and returns its /// name. Only the type plane associated with the type of \p val /// is searched. /// @brief Return the name of a value - std::string get_name( const Value* val ) const; + std::string get_name( const Value* Val ) const; + + /// Finds the type \p Ty in the symbol table and returns its name. + /// @brief Return the name of a type + std::string get_name( const Type* Ty ) const; /// Given a base name, return a string that is either equal to it or /// derived from it that does not already occur in the symbol table @@ -102,7 +131,9 @@ std::string getUniqueName(const Type *Ty, const std::string &BaseName) const; - /// @brief Debug method, print out symbol table + /// This function can be used from the debugger to display the + /// content of the symbol table while debugging. + /// @brief Print out symbol table on stderr void dump() const; /// @} @@ -126,140 +157,165 @@ /// @brief Insert a constant or type. inline void insert(const std::string &Name, Value *V) { assert((isa(V) || isa(V)) && - "Can only insert types and constants into a symbol table!"); + "Can only insert types and constants into a symbol table!"); insertEntry(Name, V->getType(), V); } + /// Inserts a type into the symbol table with the specified name. There + /// can be a many-to-one mapping between names and types. This method + /// allows a type with an existing entry in the symbol table to get + /// a new name. + /// @brief Insert a type under a new name. + inline void insert(const std::string &Name, Type *T) { + insertEntry(Name, T ); + } + /// This method removes a named value from the symbol table. The - /// type and name of the Value are extracted from \N and used to + /// type and name of the Value are extracted from \p N and used to /// lookup the Value in the correct type plane. If the Value is /// not in the symbol table, this method silently ignores the /// request. /// @brief Remove a named value from the symbol table. - void remove(Value *N); + void remove(Value* N); + + /// This method removes a named type from the symbol table. The + /// name of the type is extracted from \P T and used to look up + /// the Type in the type map. If the Type is not in the symbol + /// table, this method silently ignores the request. + /// @brief Remove a named type from the symbol table. + void remove(Type* T ); /// Remove a constant or type with the specified name from the /// symbol table. /// @returns the removed Value. - /// @breif Remove a constant or type from the symbol table. - Value *remove(const std::string &Name, Value *V) { - TypeMap::iterator TI = map.find(V->getType()); - return removeEntry(TI, TI->second.find(Name)); + /// @brief Remove a constant or type from the symbol table. + inline Value* remove(const std::string &Name, Value *V) { + plane_iterator PI = pmap.find(V->getType()); + return removeEntry(PI, PI->second.find(Name)); } - /// @brief Strip the symbol table. This leaves the values without names. - bool strip( void ); + /// Remove a type with the specified name from the symbol table. + /// @returns the removed Type. + /// @brief Remove a named tyep from the symbol table. + inline Type* remove(const std::string& Name, Type* T ) { + return removeEntry( tmap.find(Name) ); + } - /// @brief Empty the symbol table completely - void clear( void ) { map.clear(); } + /// Removes a specific value from the symbol table. + /// @returns the removed value. + /// @brief Remove a specific value given by an iterator + inline Value *value_remove(const value_iterator &It) { + return this->removeEntry(pmap.find(It->second->getType()), It); + } + + /// This method will strip the symbol table of its names leaving + /// the type and values. + /// @brief Strip the symbol table. + bool strip(); + + /// @brief Empty the symbol table completely. + inline void clear() { pmap.clear(); tmap.clear(); } /// @} /// @name Iteration /// @{ public: - inline type_iterator begin() { return map.begin(); } - - inline type_const_iterator begin() const { return map.begin(); } - - inline type_iterator end() { return map.end(); } - - inline type_const_iterator end() const { return map.end(); } + /// Get an iterator that starts at the beginning of the type planes. + /// The iterator will iterate over the Type/ValueMap pairs in the + /// type planes. + inline plane_iterator plane_begin() { return pmap.begin(); } + + /// Get a const_iterator that starts at the beginning of the type + /// planes. The iterator will iterate over the Type/ValueMap pairs + /// in the type planes. + inline plane_const_iterator plane_begin() const { return pmap.begin(); } + + /// Get an iterator at the end of the type planes. This serves as + /// the marker for end of iteration over the type planes. + inline plane_iterator plane_end() { return pmap.end(); } + + /// Get a const_iterator at the end of the type planes. This serves as + /// the marker for end of iteration over the type planes. + inline plane_const_iterator plane_end() const { return pmap.end(); } /// Get an iterator that starts at the beginning of a type plane. /// The iterator will iterate over the name/value pairs in the type plane. /// @note The type plane must already exist before using this. - inline value_iterator type_begin(const Type *TypeID) { - return map.find(TypeID)->second.begin(); + inline value_iterator value_begin(const Type *TypeID) { + return pmap.find(TypeID)->second.begin(); } /// Get a const_iterator that starts at the beginning of a type plane. /// The iterator will iterate over the name/value pairs in the type plane. /// @note The type plane must already exist before using this. - inline value_const_iterator type_begin(const Type *TypeID) const { - return map.find(TypeID)->second.begin(); + inline value_const_iterator value_begin(const Type *TypeID) const { + return pmap.find(TypeID)->second.begin(); } /// Get an iterator to the end of a type plane. This serves as the marker /// for end of iteration of the type plane. /// @note The type plane must already exist before using this. - inline value_iterator type_end(const Type *TypeID) { - return map.find(TypeID)->second.end(); + inline value_iterator value_end(const Type *TypeID) { + return pmap.find(TypeID)->second.end(); } /// Get a const_iterator to the end of a type plane. This serves as the /// marker for end of iteration of the type plane. /// @note The type plane must already exist before using this. - inline value_const_iterator type_end(const Type *TypeID) const { - return map.find(TypeID)->second.end(); + inline value_const_iterator value_end(const Type *TypeID) const { + return pmap.find(TypeID)->second.end(); } - /// This method returns a type_const_iterator for iteration over + /// Get an iterator to the start of the name/Type map. + inline type_iterator type_begin() { return tmap.begin(); } + + /// Get a const_iterator to the start of the name/Type map. + inline type_const_iterator type_begin() const { return tmap.begin(); } + + /// Get an iterator to the end of the name/Type map. This serves as the + /// marker for end of iteration of the types. + inline type_iterator type_end() { return tmap.end(); } + + /// Get a const-iterator to the end of the name/Type map. This serves + /// as the marker for end of iteration of the types. + inline type_const_iterator type_end() const { return tmap.end(); } + + /// This method returns a plane_const_iterator for iteration over /// the type planes. /// @brief Find a type plane. - type_const_iterator find(const Type* Ty ) const { - return map.find( Ty ); + inline plane_const_iterator find(const Type* Ty ) const { + return pmap.find( Ty ); } - type_iterator find( const Type* Ty ) { return map.find(Ty); } - - /// @brief Find a Type Plane - const ValueMap* findPlane( const Type* Ty ) const { - type_const_iterator I = map.find( Ty ); - if ( I == map.end() ) return 0; + /// This method returns a plane_iterator for iteration over the + /// type planes. + /// @breif Find a type plane. + inline plane_iterator find( const Type* Ty ) { return pmap.find(Ty); } + + /// This method returns a ValueMap* for a specific type plane. + /// @brief Find a type plane + inline const ValueMap* findPlane( const Type* Ty ) const { + plane_const_iterator I = pmap.find( Ty ); + if ( I == pmap.end() ) return 0; return &I->second; } - /// @returns the removed value. - /// @brief Remove a specific value given by an iterator - Value *type_remove(const value_iterator &It) { - return this->removeEntry(map.find(It->second->getType()), It); - } - -/// @} -/// @name Applicators -/// @{ -public: - /// This function calls the functor doIt for each type in the Symbol - /// Table. The arguments to the functor are the name and type. - /// @brief Apply a functor to the types in the Symbol Table. - // template - // void applyToTypes(FUNCTOR& doIt) const; - - /// This function calls the functor doIt for each type in the Symbol - /// Table that has the specified name. If the functor returns true, - /// the search stops. - //template - //void findTypeNamed( FUNCTOR& doIt, const std::string& Name) const; - - /// This function calls the functor doIt for each value in the Symbol - /// Table. The arguments to the functor are the type, name and value. - //template - //void apply( FUNCTOR& doIt ) const; - - /// This function removes any Types for which the functor \p decide - /// returns true. - /// @returns the number of types removed - //template - //unsigned removeMatchingTypes( FUNCTOR& decide ); - - /// This function replaces the named value of each entry in the - /// Type plane with value provided by the replace functor. The functor - /// should return the new Value* or null if no replacement should be - /// made. - /// @returns the number of replacements made. - //template - //unsigned replaceTypes( FUNCTOR& replace ); - /// @} /// @name Internal Methods /// @{ private: /// Insert a value into the symbol table with the specified name. void insertEntry(const std::string &Name, const Type *Ty, Value *V); + void insertEntry(const std::string &Name, Type *T); + + /// Remove a specific value from a specific plane in the SymbolTable. + /// @returns the removed Value. + Value* removeEntry(plane_iterator Plane, value_iterator Entry); - /// Remove a value from the symbol table... - Value *removeEntry(TypeMap::iterator Plane, value_iterator Entry); + /// Remove a specific type from the SymbolTable. + /// @returns the removed Type. + Type* removeEntry(type_iterator Entry); /// This function is called when one of the types in the type plane /// is refined. @@ -277,9 +333,15 @@ /// separate type planes for named values. That is, each named /// value is organized into a separate dictionary based on /// Type. This means that the same name can be used for different - /// types without conflict. + /// types without conflict. Note that the Type::TypeTy plane is + /// not stored in this map but is in tmap. /// @brief The mapping of types to names to values. - TypeMap map; + TypePlaneMap pmap; + + /// This is the Type::TypeTy plane. It is separated from the pmap + /// because the elements of the map are name/Type pairs not + /// name/Value pairs and Type is not a Value. + TypeMap tmap; /// There are times when the symbol table is internally inconsistent with /// the rest of the program. In this one case, a value exists with a Name, @@ -298,84 +360,9 @@ }; -/* -template -void SymbolTable::applyToTypes( FUNCTOR& doIt ) const { - type_const_iterator TI = map.find(Type::TypeTy); - if (TI != map.end()) { - value_const_iterator VI = TI->second.begin(); - for (; VI != TI->second.end(); ++VI) { - doIt( Type::TypeTy, VI->first, VI->second ); - } - } -} - -template -void SymbolTable::findTypeNamed( FUNCTOR& decide, - const std::string& Name ) const { - type_const_iterator TI = map.begin(); - type_const_iterator TE = map.end(); - for ( ; TI != TE; ++TI ) { - if (TI->first != Type::TypeTy) { - const ValueMap& VM = TI->second; - // Does this type plane contain an entry with the specified name? - value_const_iterator VI = VM.find(Name); - if (VI != VM.end()) { - if ( decide( TI->first, VI->first, VI->second ) ) break; - } - } - } -} - -template -void SymbolTable::apply( FUNCTOR& doIt ) const { - for (type_const_iterator TI = map.begin(), TE = map.end(); - TI != TE; ++TI) { - for (value_const_iterator VI = TI->second.begin(), - VE = TI->second.end(); VI != VE; ++VI) { - doIt( TI->first, VI->first, VI->second ); - } - } -} - -template -unsigned SymbolTable::removeMatchingTypes( FUNCTOR& decide ) { - unsigned result = 0; - type_iterator PI = map.find(Type::TypeTy); - if (PI != map.end()) { - ValueMap& Plane = PI->second; - for (value_iterator I=Plane.begin(); I != Plane.end(); ++I) { - if ( decide( PI->first, I->first, I->second ) ) - { - Plane.erase( I++ ); - result++; - } - } - } - return result; -} - -template -unsigned SymbolTable::replaceTypes( FUNCTOR& replace ) { - unsigned result = 0; - type_iterator PI = map.find(Type::TypeTy); - if (PI != map.end()) { - ValueMap& Plane = PI->second; - for (value_iterator I=Plane.begin(), PE=Plane.end(); I != PE; ++I) { - Value* v = replace( PI->first, I->first, I->second ); - if ( v ) { - I->second = v; - result++; - result++; - } - } - } - return result; -} -*/ - } // End llvm namespace +// vim: sw=2 + #endif -// vim: sw=2 From llvm at cs.uiuc.edu Sun May 16 18:27:01 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Sun May 16 18:27:01 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/include/llvm/SymbolTable.h Message-ID: <200405162327.SAA30029@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm: SymbolTable.h updated: 1.30.6.2 -> 1.30.6.3 --- Log message: Redact an untrue statement in the class comments. --- Diffs of the changes: (+0 -5) Index: llvm/include/llvm/SymbolTable.h diff -u llvm/include/llvm/SymbolTable.h:1.30.6.2 llvm/include/llvm/SymbolTable.h:1.30.6.3 --- llvm/include/llvm/SymbolTable.h:1.30.6.2 Sun May 16 18:24:36 2004 +++ llvm/include/llvm/SymbolTable.h Sun May 16 18:27:41 2004 @@ -26,11 +26,6 @@ /// map of name/type pairs. This allows types to be named. Types are treated /// distinctly from Values since Types are not Values. /// -/// Note that the value map implements a chained symbol table. If a name -/// being looked up (with lookup()) isn't found in the current symbol -/// table, then the parent symbol table is searched. This chaining behavior -/// does NOT affect the iterators though: only the lookup method. -/// /// The SymbolTable provides several utility functions for answering common /// questions about its contents as well as an iterator interface for /// directly iterating over the contents. From llvm at cs.uiuc.edu Sun May 16 18:43:00 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Sun May 16 18:43:00 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/lib/VMCore/SymbolTable.cpp Message-ID: <200405162344.SAA30071@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: SymbolTable.cpp updated: 1.42.6.1 -> 1.42.6.2 --- Log message: Implement new functions to deal with Types separately since Types are not Values now. Also make consistent the names of the various iterators. PI is used for plane_iterator, VI for value_iterator, and TI for type_iterator. --- Diffs of the changes: (+187 -121) Index: llvm/lib/VMCore/SymbolTable.cpp diff -u llvm/lib/VMCore/SymbolTable.cpp:1.42.6.1 llvm/lib/VMCore/SymbolTable.cpp:1.42.6.2 --- llvm/lib/VMCore/SymbolTable.cpp:1.42.6.1 Wed May 12 11:33:43 2004 +++ llvm/lib/VMCore/SymbolTable.cpp Sun May 16 18:43:51 2004 @@ -23,14 +23,9 @@ SymbolTable::~SymbolTable() { // Drop all abstract type references in the type plane... - type_iterator TyPlane = map.find(Type::TypeTy); - if (TyPlane != map.end()) { - ValueMap &TyP = TyPlane->second; - for (value_iterator I = TyP.begin(), E = TyP.end(); I != E; ++I) { - const Type *Ty = cast(I->second); - if (Ty->isAbstract()) // If abstract, drop the reference... - cast(Ty)->removeAbstractTypeUser(this); - } + for (type_iterator TI = tmap.begin(), TE = tmap.end(); TI != TE; ++TI) { + if (TI->second->isAbstract()) // If abstract, drop the reference... + cast(TI->second)->removeAbstractTypeUser(this); } // TODO: FIXME: BIG ONE: This doesn't unreference abstract types for the planes @@ -38,12 +33,12 @@ #ifndef NDEBUG // Only do this in -g mode... bool LeftoverValues = true; - for (type_iterator i = map.begin(); i != map.end(); ++i) { - for (value_iterator I = i->second.begin(); I != i->second.end(); ++I) - if (!isa(I->second) && !isa(I->second)) { + for (plane_iterator PI = pmap.begin(); PI != pmap.end(); ++PI) { + for (value_iterator VI = PI->second.begin(); VI != PI->second.end(); ++VI) + if (!isa(VI->second) ) { std::cerr << "Value still in symbol table! Type = '" - << i->first->getDescription() << "' Name = '" - << I->first << "'\n"; + << PI->first->getDescription() << "' Name = '" + << VI->first << "'\n"; LeftoverValues = false; } } @@ -58,46 +53,55 @@ // std::string SymbolTable::getUniqueName(const Type *Ty, const std::string &BaseName) const { - type_const_iterator I = map.find(Ty); - if (I == map.end()) return BaseName; + plane_const_iterator PI = pmap.find(Ty); + if (PI == pmap.end()) return BaseName; std::string TryName = BaseName; - value_const_iterator End = I->second.end(); + const ValueMap& vmap = PI->second; + value_const_iterator End = vmap.end(); - while (I->second.find(TryName) != End) // Loop until we find a free + while (vmap.find(TryName) != End) // Loop until we find a free TryName = BaseName + utostr(++LastUnique); // name in the symbol table return TryName; } - -// lookup - Returns null on failure... +// lookup a value - Returns null on failure... Value *SymbolTable::lookup(const Type *Ty, const std::string &Name) const { - type_const_iterator I = map.find(Ty); - if (I != map.end()) { // We have symbols in that plane... - value_const_iterator J = I->second.find(Name); - if (J != I->second.end()) // and the name is in our hash table... - return J->second; + plane_const_iterator PI = pmap.find(Ty); + if (PI != pmap.end()) { // We have symbols in that plane... + value_const_iterator VI = PI->second.find(Name); + if (VI != PI->second.end()) // and the name is in our hash table... + return VI->second; } + return 0; +} + +// lookup a type by name - returns null on failure +Type* SymbolTable::lookupType( const std::string& Name ) const { + type_const_iterator TI = tmap.find( Name ); + if ( TI != tmap.end() ) + return TI->second; return 0; } +// Remove a value void SymbolTable::remove(Value *N) { assert(N->hasName() && "Value doesn't have name!"); if (InternallyInconsistent) return; - type_iterator I = map.find(N->getType()); - assert(I != map.end() && - "Trying to remove a type that doesn't have a plane yet!"); - removeEntry(I, I->second.find(N->getName())); + plane_iterator PI = pmap.find(N->getType()); + assert(PI != pmap.end() && + "Trying to remove a value that doesn't have a type plane yet!"); + removeEntry(PI, PI->second.find(N->getName())); } + // removeEntry - Remove a value from the symbol table... -// -Value *SymbolTable::removeEntry(type_iterator Plane, value_iterator Entry) { +Value *SymbolTable::removeEntry(plane_iterator Plane, value_iterator Entry) { if (InternallyInconsistent) return 0; - assert(Plane != map.end() && + assert(Plane != pmap.end() && Entry != Plane->second.end() && "Invalid entry to remove!"); Value *Result = Entry->second; @@ -123,34 +127,60 @@ cast(Plane->first)->removeAbstractTypeUser(this); } - map.erase(Plane); + pmap.erase(Plane); } + return Result; +} + + +// remove - Remove a type +void SymbolTable::remove(Type* Ty ) { + type_iterator TI = this->type_begin(); + type_iterator TE = this->type_end(); + + // Search for the entry + while ( TI != TE && TI->second != Ty ) + ++TI; + + if ( TI != TE ) + this->removeEntry( TI ); +} + + +// removeEntry - Remove a type from the symbol table... +Type* SymbolTable::removeEntry(type_iterator Entry) { + if (InternallyInconsistent) return 0; + assert( Entry != tmap.end() && "Invalid entry to remove!"); + + Type* Result = Entry->second; + +#if DEBUG_SYMBOL_TABLE + dump(); + std::cerr << " Removing Value: " << Result->getName() << "\n"; +#endif + + tmap.erase(Entry); // If we are removing an abstract type, remove the symbol table from it's use // list... - if (Ty == Type::TypeTy) { - const Type *T = cast(Result); - if (T->isAbstract()) { + if (Result->isAbstract()) { #if DEBUG_ABSTYPE - std::cerr << "Removing abs type from symtab" << T->getDescription()<<"\n"; + std::cerr << "Removing abstract type from symtab" << Result->getDescription()<<"\n"; #endif - cast(T)->removeAbstractTypeUser(this); - } + cast(Result)->removeAbstractTypeUser(this); } return Result; } -// insertEntry - Insert a value into the symbol table with the specified -// name... -// + +// insertEntry - Insert a value into the symbol table with the specified name. void SymbolTable::insertEntry(const std::string &Name, const Type *VTy, Value *V) { - // Check to see if there is a naming conflict. If so, rename this value! if (lookup(VTy, Name)) { std::string UniqueName = getUniqueName(VTy, Name); - assert(InternallyInconsistent == false && "Infinite loop inserting entry!"); + assert(InternallyInconsistent == false && "Infinite loop inserting value!"); InternallyInconsistent = true; V->setName(UniqueName, this); InternallyInconsistent = false; @@ -163,11 +193,11 @@ << VTy->getDescription() << "\n"; #endif - type_iterator I = map.find(VTy); - if (I == map.end()) { // Not in collection yet... insert dummy entry + plane_iterator PI = pmap.find(VTy); + if (PI == pmap.end()) { // Not in collection yet... insert dummy entry // Insert a new empty element. I points to the new elements. - I = map.insert(make_pair(VTy, ValueMap())).first; - assert(I != map.end() && "How did insert fail?"); + PI = pmap.insert(make_pair(VTy, ValueMap())).first; + assert(PI != pmap.end() && "How did insert fail?"); // Check to see if the type is abstract. If so, it might be refined in the // future, which would cause the plane of the old type to get merged into @@ -182,85 +212,120 @@ } } - I->second.insert(make_pair(Name, V)); + PI->second.insert(make_pair(Name, V)); +} + + +// insertEntry - Insert a value into the symbol table with the specified +// name... +// +void SymbolTable::insertEntry(const std::string& Name, Type* T) { + + // Check to see if there is a naming conflict. If so, rename this type! + std::string UniqueName = Name; + if (lookupType(Name)) + UniqueName = getUniqueName(T, Name); + +#if DEBUG_SYMBOL_TABLE + dump(); + std::cerr << " Inserting type: " << UniqueName << ": " + << T->getDescription() << "\n"; +#endif + + // Insert the tmap entry + tmap.insert(make_pair(UniqueName, T)); // If we are adding an abstract type, add the symbol table to it's use list. - if (VTy == Type::TypeTy) { - const Type *T = cast(V); - if (T->isAbstract()) { - cast(T)->addAbstractTypeUser(this); + if (T->isAbstract()) { + cast(T)->addAbstractTypeUser(this); #if DEBUG_ABSTYPE - std::cerr << "Added abstract type to ST: " << T->getDescription() << "\n"; + std::cerr << "Added abstract type to ST: " << T->getDescription() << "\n"; #endif - } } } -bool -SymbolTable::hasTypes( void ) const { - type_const_iterator PI = map.find(Type::TypeTy); - if (PI == map.end()) return false; - return true; -} -bool -SymbolTable::isEmpty( void ) const { - return map.empty(); +// Determine how many entries for a given type. +unsigned SymbolTable::type_size(const Type *Ty) const { + plane_const_iterator PI = pmap.find(Ty); + if ( PI == pmap.end() ) return 0; + return PI->second.size(); } -std::string SymbolTable::get_name( const Value* v ) const { - if (map.find(Type::TypeTy) == map.end()) - return ""; // No names for types... - value_const_iterator VI = type_begin(Type::TypeTy); - value_const_iterator VE = type_end(Type::TypeTy); +// Get the name of a value +std::string SymbolTable::get_name( const Value* V ) const { + value_const_iterator VI = this->value_begin( V->getType() ); + value_const_iterator VE = this->value_end( V->getType() ); - while (VI != VE && VI->second != v ) + // Search for the entry + while ( VI != VE && VI->second != V ) ++VI; - if (VI != VE) // Must have found an entry! + if ( VI != VE ) return VI->first; + + return ""; +} + + +// Get the name of a type +std::string SymbolTable::get_name( const Type* T ) const { + if (tmap.empty()) return ""; // No types at all. + + type_const_iterator TI = tmap.begin(); + type_const_iterator TE = tmap.end(); + + // Search for the entry + while (TI != TE && TI->second != T ) + ++TI; + + if (TI != TE) // Must have found an entry! + return TI->first; return ""; // Must not have found anything... } + +// Strip the symbol table of its names. bool SymbolTable::strip( void ) { bool RemovedSymbol = false; - for (type_iterator I = map.begin(); I != map.end();) { + for (plane_iterator I = pmap.begin(); I != pmap.end();) { // Removing items from the plane can cause the plane itself to get deleted. // If this happens, make sure we incremented our plane iterator already! ValueMap &Plane = (I++)->second; value_iterator B = Plane.begin(), Bend = Plane.end(); while (B != Bend) { // Found nonempty type plane! Value *V = B->second; - - if (isa(V) || isa(V)) { - type_remove(B++); + if (isa(V)) { + remove(V); RemovedSymbol = true; } else { - ++B; if (!isa(V) || cast(V)->hasInternalLinkage()){ // Set name to "", removing from symbol table! V->setName("", this); RemovedSymbol = true; } } + ++B; } } return RemovedSymbol; } + // This function is called when one of the types in the type plane are refined void SymbolTable::refineAbstractType(const DerivedType *OldType, const Type *NewType) { - // Search to see if we have any values of the type oldtype. If so, we need to + + // Search to see if we have any values of the type Oldtype. If so, we need to // move them into the newtype plane... - type_iterator TPI = map.find(OldType); - if (TPI != map.end()) { + plane_iterator PI = pmap.find(OldType); + if (PI != pmap.end()) { // Get a handle to the new type plane... - type_iterator NewTypeIt = map.find(NewType); - if (NewTypeIt == map.end()) { // If no plane exists, add one - NewTypeIt = map.insert(make_pair(NewType, ValueMap())).first; + plane_iterator NewTypeIt = pmap.find(NewType); + if (NewTypeIt == pmap.end()) { // If no plane exists, add one + NewTypeIt = pmap.insert(make_pair(NewType, ValueMap())).first; if (NewType->isAbstract()) { cast(NewType)->addAbstractTypeUser(this); @@ -272,21 +337,21 @@ } ValueMap &NewPlane = NewTypeIt->second; - ValueMap &OldPlane = TPI->second; + ValueMap &OldPlane = PI->second; while (!OldPlane.empty()) { std::pair V = *OldPlane.begin(); // Check to see if there is already a value in the symbol table that this // would collide with. - value_iterator TI = NewPlane.find(V.first); - if (TI != NewPlane.end() && TI->second == V.second) { + value_iterator VI = NewPlane.find(V.first); + if (VI != NewPlane.end() && VI->second == V.second) { // No action - } else if (TI != NewPlane.end()) { + } else if (VI != NewPlane.end()) { // The only thing we are allowing for now is two external global values // folded into one. // - GlobalValue *ExistGV = dyn_cast(TI->second); + GlobalValue *ExistGV = dyn_cast(VI->second); GlobalValue *NewGV = dyn_cast(V.second); if (ExistGV && NewGV) { @@ -348,54 +413,48 @@ OldType->removeAbstractTypeUser(this); // Remove the plane that is no longer used - map.erase(TPI); + pmap.erase(PI); } - TPI = map.find(Type::TypeTy); - if (TPI != map.end()) { - // Loop over all of the types in the symbol table, replacing any references - // to OldType with references to NewType. Note that there may be multiple - // occurrences, and although we only need to remove one at a time, it's - // faster to remove them all in one pass. - // - ValueMap &TyPlane = TPI->second; - for (value_iterator I = TyPlane.begin(), E = TyPlane.end(); I != E; ++I) - if (I->second == (Value*)OldType) { // FIXME when Types aren't const. + // Loop over all of the types in the symbol table, replacing any references + // to OldType with references to NewType. Note that there may be multiple + // occurrences, and although we only need to remove one at a time, it's + // faster to remove them all in one pass. + // + for (type_iterator I = type_begin(), E = type_end(); I != E; ++I) { + if (I->second == (Type*)OldType) { // FIXME when Types aren't const. #if DEBUG_ABSTYPE - std::cerr << "Removing type " << OldType->getDescription() << "\n"; + std::cerr << "Removing type " << OldType->getDescription() << "\n"; #endif - OldType->removeAbstractTypeUser(this); + OldType->removeAbstractTypeUser(this); - I->second = (Value*)NewType; // TODO FIXME when types aren't const - if (NewType->isAbstract()) { + I->second = (Type*)NewType; // TODO FIXME when types aren't const + if (NewType->isAbstract()) { #if DEBUG_ABSTYPE - std::cerr << "Added type " << NewType->getDescription() << "\n"; + std::cerr << "Added type " << NewType->getDescription() << "\n"; #endif - cast(NewType)->addAbstractTypeUser(this); - } + cast(NewType)->addAbstractTypeUser(this); } + } } } + +// Handle situation where type becomes Concreate from Abstract void SymbolTable::typeBecameConcrete(const DerivedType *AbsTy) { - type_iterator TPI = map.find(AbsTy); + plane_iterator PI = pmap.find(AbsTy); // If there are any values in the symbol table of this type, then the type - // plan is a use of the abstract type which must be dropped. - if (TPI != map.end()) + // plane is a use of the abstract type which must be dropped. + if (PI != pmap.end()) AbsTy->removeAbstractTypeUser(this); - TPI = map.find(Type::TypeTy); - if (TPI != map.end()) { - // Loop over all of the types in the symbol table, dropping any abstract - // type user entries for AbsTy which occur because there are names for the - // type. - // - ValueMap &TyPlane = TPI->second; - for (value_iterator I = TyPlane.begin(), E = TyPlane.end(); I != E; ++I) - if (I->second == (Value*)AbsTy) // FIXME when Types aren't const. - AbsTy->removeAbstractTypeUser(this); - } + // Loop over all of the types in the symbol table, dropping any abstract + // type user entries for AbsTy which occur because there are names for the + // type. + for (type_iterator TI = type_begin(), TE = type_end(); TI != TE; ++TI) + if (TI->second == (Type*)AbsTy) // FIXME when Types aren't const. + AbsTy->removeAbstractTypeUser(this); } static void DumpVal(const std::pair &V) { @@ -406,15 +465,22 @@ static void DumpPlane(const std::pair >&P){ - std::cout << " Plane: "; P.first->dump(); std::cout << "\n"; for_each(P.second.begin(), P.second.end(), DumpVal); } +static void DumpTypes(const std::pair& T ) { + std::cout << " '" << T.first << "' = "; + T.second->dump(); + std::cout << "\n"; +} + void SymbolTable::dump() const { - std::cout << "Symbol table dump:\n"; - for_each(map.begin(), map.end(), DumpPlane); + std::cout << "Symbol table dump:\n Plane:"; + for_each(pmap.begin(), pmap.end(), DumpPlane); + std::cout << " Types: "; + for_each(tmap.begin(), tmap.end(), DumpTypes); } // vim: sw=2 ai From llvm at cs.uiuc.edu Sun May 16 18:49:01 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Sun May 16 18:49:01 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/lib/VMCore/AsmWriter.cpp Message-ID: <200405162349.SAA30104@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: AsmWriter.cpp updated: 1.128.2.1 -> 1.128.2.2 --- Log message: Changes to reflect interface changes in SymbolTable and the fact that Type is no longer a Value. --- Diffs of the changes: (+28 -35) Index: llvm/lib/VMCore/AsmWriter.cpp diff -u llvm/lib/VMCore/AsmWriter.cpp:1.128.2.1 llvm/lib/VMCore/AsmWriter.cpp:1.128.2.2 --- llvm/lib/VMCore/AsmWriter.cpp:1.128.2.1 Wed May 12 11:33:43 2004 +++ llvm/lib/VMCore/AsmWriter.cpp Sun May 16 18:49:32 2004 @@ -59,7 +59,6 @@ } static SlotCalculator *createSlotCalculator(const Value *V) { - assert(!isa(V) && "Can't create an SC for a type!"); if (const Argument *FA = dyn_cast(V)) { return new SlotCalculator(FA->getParent(), false); } else if (const Instruction *I = dyn_cast(V)) { @@ -105,19 +104,15 @@ std::map &TypeNames) { if (!M) return; const SymbolTable &ST = M->getSymbolTable(); - SymbolTable::type_const_iterator PI = ST.find(Type::TypeTy); - if (PI != ST.end()) { - SymbolTable::value_const_iterator VI = PI->second.begin(); - for (; VI != PI->second.end(); ++VI) { - // As a heuristic, don't insert pointer to primitive types, because - // they are used too often to have a single useful name. - // - const Type *Ty = cast(VI->second); - if (!isa(Ty) || - !cast(Ty)->getElementType()->isPrimitiveType() || - isa(cast(Ty)->getElementType())) - TypeNames.insert(std::make_pair(Ty, getLLVMName(VI->first))); - } + SymbolTable::type_const_iterator TI = ST.type_begin(); + for (; TI != ST.type_end(); ++TI ) { + // As a heuristic, don't insert pointer to primitive types, because + // they are used too often to have a single useful name. + const Type *Ty = TI->second; + if (!isa(Ty) || + !cast(Ty)->getElementType()->isPrimitiveType() || + isa(cast(Ty)->getElementType())) + TypeNames.insert(std::make_pair(Ty, getLLVMName(TI->first))); } } @@ -401,11 +396,6 @@ if (Table) { Slot = Table->getSlot(V); } else { - if (const Type *Ty = dyn_cast(V)) { - Out << Ty->getDescription(); - return; - } - Table = createSlotCalculator(V); if (Table == 0) { Out << "BAD VALUE TYPE!"; return; } @@ -606,28 +596,30 @@ /// printSymbolTable - Run through symbol table looking for named constants -/// if a named constant is found, emit it's declaration... -/// +/// if a named constant is found, emit it's declaration. Do the same for +/// types. void AssemblyWriter::printSymbolTable(const SymbolTable &ST) { - for (SymbolTable::type_const_iterator TI = ST.begin(); TI != ST.end(); ++TI) { - SymbolTable::value_const_iterator I = ST.type_begin(TI->first); - SymbolTable::value_const_iterator End = ST.type_end(TI->first); + for (SymbolTable::plane_const_iterator PI = ST.plane_begin(); + PI != ST.plane_end(); ++PI) { + SymbolTable::value_const_iterator I = ST.value_begin(PI->first); + SymbolTable::value_const_iterator End = ST.value_end(PI->first); for (; I != End; ++I) { const Value *V = I->second; if (const Constant *CPV = dyn_cast(V)) { printConstant(CPV); - } else if (const Type *Ty = dyn_cast(V)) { - assert(Ty->getType() == Type::TypeTy && TI->first == Type::TypeTy); - *Out << "\t" << getLLVMName(I->first) << " = type "; - - // Make sure we print out at least one level of the type structure, so - // that we do not get %FILE = type %FILE - // - printTypeAtLeastOneLevel(Ty) << "\n"; - } + } } } + for (SymbolTable::type_const_iterator TI = ST.type_begin(); + TI != ST.type_end(); ++TI ) { + const Type* Ty = TI->second; + *Out << "\t" << getLLVMName(TI->first) << " = type "; + + // Make sure we print out at least one level of the type structure, so + // that we do not get %FILE = type %FILE + printTypeAtLeastOneLevel(Ty) << "\n"; + } } @@ -1013,7 +1005,7 @@ o << getType() << " " << getName(); } -void Value::dump() const { print(std::cerr); } +void PrintableItem::dump() const { this->print(std::cerr); } //===----------------------------------------------------------------------===// // CachedWriter Class Implementation @@ -1039,7 +1031,6 @@ switch (V->getValueType()) { case Value::ConstantVal: case Value::ArgumentVal: AW->writeOperand(V, true, true); break; - case Value::TypeVal: AW->write(cast(V)); break; case Value::InstructionVal: AW->write(cast(V)); break; case Value::BasicBlockVal: AW->write(cast(V)); break; case Value::FunctionVal: AW->write(cast(V)); break; @@ -1062,3 +1053,5 @@ Out = &os; if (AW) AW->setStream(os); } + +// vim: sw=2 From llvm at cs.uiuc.edu Sun May 16 18:52:00 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Sun May 16 18:52:00 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/lib/VMCore/Module.cpp Message-ID: <200405162352.SAA30131@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Module.cpp updated: 1.49.2.1 -> 1.49.2.2 --- Log message: Changes necessary for interface changes to SymbolTable and to reflect that Type is no long a Value. --- Diffs of the changes: (+13 -7) Index: llvm/lib/VMCore/Module.cpp diff -u llvm/lib/VMCore/Module.cpp:1.49.2.1 llvm/lib/VMCore/Module.cpp:1.49.2.2 --- llvm/lib/VMCore/Module.cpp:1.49.2.1 Wed May 12 11:33:43 2004 +++ llvm/lib/VMCore/Module.cpp Sun May 16 18:52:24 2004 @@ -246,11 +246,15 @@ bool Module::addTypeName(const std::string &Name, const Type *Ty) { SymbolTable &ST = getSymbolTable(); - if (ST.lookup(Type::TypeTy, Name)) return true; // Already in symtab... - - // Not in symbol table? Set the name with the Symtab as an argument so the - // type knows what to update... - ((Value*)Ty)->setName(Name, &ST); + Type* OtherType = ST.lookupType(Name); + if ( OtherType ) + { + assert( OtherType == Ty && "Attempt to reset a type with a name"); + return true; + } + + // Not in symbol table? Simply give the type a name in the symbol table. + ST.insert(Name,const_cast(Ty)); return false; } @@ -259,7 +263,7 @@ /// null if there is none by that name. const Type *Module::getTypeByName(const std::string &Name) const { const SymbolTable &ST = getSymbolTable(); - return cast_or_null(ST.lookup(Type::TypeTy, Name)); + return ST.lookupType(Name); } // getTypeName - If there is at least one entry in the symbol table for the @@ -267,7 +271,7 @@ // std::string Module::getTypeName(const Type *Ty) const { const SymbolTable &ST = getSymbolTable(); - return ST.get_name( (const Value*) Ty ); + return ST.get_name( Ty ); } @@ -324,3 +328,5 @@ GVRefMap = 0; } } + +// vim: sw=2 From llvm at cs.uiuc.edu Sun May 16 18:56:00 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Sun May 16 18:56:00 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/include/llvm/Type.def Type.h Value.h AbstractTypeUser.h DerivedTypes.h Message-ID: <200405162356.SAA30183@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm: Type.def updated: 1.6 -> 1.6.8.1 Type.h updated: 1.42 -> 1.42.2.1 Value.h updated: 1.50 -> 1.50.4.1 AbstractTypeUser.h updated: 1.19 -> 1.19.4.1 DerivedTypes.h updated: 1.56 -> 1.56.2.1 --- Log message: Changes to make Type not derive from Value. A new "PrintableItem" class was created to contain the remaining common functionality between Value and Type. The PATypeHolder implementation was taken out of Type.h. --- Diffs of the changes: (+59 -117) Index: llvm/include/llvm/Type.def diff -u llvm/include/llvm/Type.def:1.6 llvm/include/llvm/Type.def:1.6.8.1 --- llvm/include/llvm/Type.def:1.6 Tue Nov 11 16:41:30 2003 +++ llvm/include/llvm/Type.def Sun May 16 18:56:20 2004 @@ -44,7 +44,6 @@ HANDLE_PRIM_TYPE(ULong , 8) HANDLE_PRIM_TYPE(Float , 4) HANDLE_PRIM_TYPE(Double, 8) -HANDLE_PRIM_TYPE(Type , 0) HANDLE_PRIM_TYPE(Label , 0) Index: llvm/include/llvm/Type.h diff -u llvm/include/llvm/Type.h:1.42 llvm/include/llvm/Type.h:1.42.2.1 --- llvm/include/llvm/Type.h:1.42 Fri Mar 26 15:43:12 2004 +++ llvm/include/llvm/Type.h Sun May 16 18:56:20 2004 @@ -33,13 +33,17 @@ #ifndef LLVM_TYPE_H #define LLVM_TYPE_H -#include "llvm/Value.h" +#include "llvm/PrintableItem.h" +#include "llvm/AbstractTypeUser.h" #include "Support/GraphTraits.h" #include "Support/iterator" +#include "Support/Casting.h" #include namespace llvm { +class Value; +class SymbolTable; class DerivedType; class FunctionType; class ArrayType; @@ -47,7 +51,7 @@ class StructType; class OpaqueType; -struct Type : public Value { +struct Type : public PrintableItem { ///===-------------------------------------------------------------------===// /// Definitions of all of the base types for the Type system. Based on this /// value, you can cast to a "DerivedType" subclass (see DerivedTypes.h) @@ -55,22 +59,19 @@ /// Type::getPrimitiveType function, or else things will break! /// enum PrimitiveID { - VoidTyID = 0 , BoolTyID, // 0, 1: Basics... - UByteTyID , SByteTyID, // 2, 3: 8 bit types... - UShortTyID , ShortTyID, // 4, 5: 16 bit types... - UIntTyID , IntTyID, // 6, 7: 32 bit types... - ULongTyID , LongTyID, // 8, 9: 64 bit types... + VoidTyID = 0 , BoolTyID, // 0, 1: Basics + UByteTyID , SByteTyID, // 2, 3: 8 bit types + UShortTyID , ShortTyID, // 4, 5: 16 bit types + UIntTyID , IntTyID, // 6, 7: 32 bit types + ULongTyID , LongTyID, // 8, 9: 64 bit types + FloatTyID , DoubleTyID, // 10,11: Floating point types + LabelTyID , // 12 : Labels - FloatTyID , DoubleTyID, // 10,11: Floating point types... - - TypeTyID, // 12 : Type definitions - LabelTyID , // 13 : Labels... - - // Derived types... see DerivedTypes.h file... + // Derived types... see DerivedTypes.h file // Make sure FirstDerivedTyID stays up to date!!! - FunctionTyID , StructTyID, // Functions... Structs... - ArrayTyID , PointerTyID, // Array... pointer... - OpaqueTyID, // Opaque type instances... + FunctionTyID , StructTyID, // 13,14: Functions,Structs + ArrayTyID , PointerTyID, // 15,16: Array,Pointer + OpaqueTyID, // 17 : Opaque type instances //PackedTyID , // SIMD 'packed' format... TODO //... @@ -93,14 +94,9 @@ const Type *getForwardedTypeInternal() const; protected: /// ctor is protected, so only subclasses can create Type objects... - Type(const std::string &Name, PrimitiveID id); + Type(PrimitiveID id); virtual ~Type() {} - /// setName - Associate the name with this type in the symbol table, but don't - /// set the local name to be equal specified name. - /// - virtual void setName(const std::string &Name, SymbolTable *ST = 0); - /// Types can become nonabstract later, if they are refined. /// inline void setAbstract(bool Val) { Abstract = Val; } @@ -194,7 +190,7 @@ /// isFirstClassType - Return true if the value is holdable in a register. inline bool isFirstClassType() const { - return (ID != VoidTyID && ID < TypeTyID) || ID == PointerTyID; + return (ID != VoidTyID && ID < LabelTyID) || ID == PointerTyID; } /// isSized - Return true if it makes sense to take the size of this type. To @@ -202,8 +198,8 @@ /// TargetData subsystem to do this. /// bool isSized() const { - return ID != VoidTyID && ID != TypeTyID && - ID != FunctionTyID && ID != LabelTyID && ID != OpaqueTyID; + return ID != VoidTyID && ID != FunctionTyID && + ID != LabelTyID && ID != OpaqueTyID; } /// getPrimitiveSize - Return the basic size of this type if it is a primative @@ -229,6 +225,10 @@ return getForwardedTypeInternal(); } + /// Compatibility function to make Type work like Value. The type of a Type is + /// of course "this". + inline const Type *getType() const { return this; } + //===--------------------------------------------------------------------===// // Type Iteration support // @@ -268,13 +268,11 @@ *LongTy , *ULongTy; static Type *FloatTy, *DoubleTy; - static Type *TypeTy , *LabelTy; + static Type* LabelTy; /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Type *T) { return true; } - static inline bool classof(const Value *V) { - return V->getValueType() == Value::TypeVal; - } + static inline bool classof(const Value *V) { return false; } #include "llvm/Type.def" @@ -301,62 +299,13 @@ if (--RefCount == 0) RefCountIsZero(); } + private: virtual void RefCountIsZero() const { abort(); // only on derived types! } }; - -//===----------------------------------------------------------------------===// -// Define some inline methods for the AbstractTypeUser.h:PATypeHandle class. -// These are defined here because they MUST be inlined, yet are dependent on -// the definition of the Type class. Of course Type derives from Value, which -// contains an AbstractTypeUser instance, so there is no good way to factor out -// the code. Hence this bit of uglyness. -// -// In the long term, Type should not derive from Value, allowing -// AbstractTypeUser.h to #include Type.h, allowing us to eliminate this -// nastyness entirely. -// -inline void PATypeHandle::addUser() { - assert(Ty && "Type Handle has a null type!"); - if (Ty->isAbstract()) - Ty->addAbstractTypeUser(User); -} -inline void PATypeHandle::removeUser() { - if (Ty->isAbstract()) - Ty->removeAbstractTypeUser(User); -} - -inline void PATypeHandle::removeUserFromConcrete() { - if (!Ty->isAbstract()) - Ty->removeAbstractTypeUser(User); -} - -// Define inline methods for PATypeHolder... - -inline void PATypeHolder::addRef() { - if (Ty->isAbstract()) - Ty->addRef(); -} - -inline void PATypeHolder::dropRef() { - if (Ty->isAbstract()) - Ty->dropRef(); -} - -/// get - This implements the forwarding part of the union-find algorithm for -/// abstract types. Before every access to the Type*, we check to see if the -/// type we are pointing to is forwarding to a new type. If so, we drop our -/// reference to the type. -/// -inline const Type* PATypeHolder::get() const { - const Type *NewTy = Ty->getForwardedType(); - if (!NewTy) return Ty; - return *const_cast(this) = NewTy; -} - //===----------------------------------------------------------------------===// Index: llvm/include/llvm/Value.h diff -u llvm/include/llvm/Value.h:1.50 llvm/include/llvm/Value.h:1.50.4.1 --- llvm/include/llvm/Value.h:1.50 Thu Feb 26 02:08:38 2004 +++ llvm/include/llvm/Value.h Sun May 16 18:56:20 2004 @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // // This file defines the very important Value class. This is subclassed by a -// bunch of other important classes, like Instruction, Function, Type, etc... +// bunch of other important classes, like Instruction, Function, etc... // // This file also defines the Use<> template for users of value. // @@ -17,14 +17,12 @@ #ifndef LLVM_VALUE_H #define LLVM_VALUE_H -#include "llvm/AbstractTypeUser.h" +#include "llvm/Type.h" #include "llvm/Use.h" -#include "Support/Casting.h" #include namespace llvm { -class Type; class Constant; class Argument; class Instruction; @@ -41,9 +39,8 @@ /// Value - The base class of all values computed by a program that may be used /// as operands to other values. /// -struct Value { +struct Value : public PrintableItem { enum ValueTy { - TypeVal, // This is an instance of Type ConstantVal, // This is an instance of Constant ArgumentVal, // This is an instance of Argument InstructionVal, // This is an instance of Instruction @@ -64,10 +61,6 @@ Value(const Type *Ty, ValueTy vty, const std::string &name = ""); virtual ~Value(); - /// dump - Support for debugging, callable in GDB: V->dump() - // - virtual void dump() const; - /// print - Implement operator<< on Value... /// virtual void print(std::ostream &O) const = 0; @@ -76,13 +69,23 @@ /// inline const Type *getType() const { return Ty; } - // All values can potentially be named... - inline bool hasName() const { return !Name.empty(); } - inline const std::string &getName() const { return Name; } - + /// This method sets the Value's name. The SymbolTable argument is + /// always ignored but provided because subclasses may wish to install + /// the NamedItem into a symbol table any time it is given a name. + /// @brief Set the NamedItem's name. virtual void setName(const std::string &name, SymbolTable * = 0) { Name = name; } + + /// Determine if the Value has a name or not. It is legal for + /// a NamedItem to have an empty name. + /// @brief Determine if the Value has a name. + inline bool hasName() const { return !Name.empty(); } + + /// Obtain the name of the Value, which might be empty. + /// @returns the name of the Value. + /// @brief Get the Value's name. + inline const std::string &getName() const { return Name; } /// getValueType - Return the immediate subclass of this Value. /// @@ -129,19 +132,6 @@ void killUse(Use &U) { Uses.remove(&U); } }; -inline std::ostream &operator<<(std::ostream &OS, const Value *V) { - if (V == 0) - OS << " value!\n"; - else - V->print(OS); - return OS; -} - -inline std::ostream &operator<<(std::ostream &OS, const Value &V) { - V.print(OS); - return OS; -} - inline User *UseListIteratorWrapper::operator*() const { return Super::operator*().getUser(); @@ -174,9 +164,6 @@ // isa - Provide some specializations of isa so that we don't have to include // the subtype header files to test to see if the value is a subclass... // -template <> inline bool isa_impl(const Value &Val) { - return Val.getValueType() == Value::TypeVal; -} template <> inline bool isa_impl(const Value &Val) { return Val.getValueType() == Value::ConstantVal; } Index: llvm/include/llvm/AbstractTypeUser.h diff -u llvm/include/llvm/AbstractTypeUser.h:1.19 llvm/include/llvm/AbstractTypeUser.h:1.19.4.1 --- llvm/include/llvm/AbstractTypeUser.h:1.19 Thu Feb 26 01:24:08 2004 +++ llvm/include/llvm/AbstractTypeUser.h Sun May 16 18:56:20 2004 @@ -73,10 +73,10 @@ const Type *Ty; AbstractTypeUser * const User; - // These functions are defined at the bottom of Type.h. See the comment there - // for justification. + // These functions are defined at the top of Type.cpp. void addUser(); void removeUser(); + public: // ctor - Add use to type if abstract. Note that Ty must not be null inline PATypeHandle(const Type *ty, AbstractTypeUser *user) @@ -128,6 +128,7 @@ }; + /// PATypeHolder - Holder class for a potentially abstract type. This uses /// efficient union-find techniques to handle dynamic type resolution. Unless /// you need to do custom processing when types are resolved, you should always @@ -146,7 +147,12 @@ ~PATypeHolder() { dropRef(); } operator const Type *() const { return get(); } - const Type *get() const; + /// This implements the forwarding part of the union-find algorithm for + /// abstract types. Before every access to the Type*, we check to see if the + /// type we are pointing to is forwarding to a new type. If so, we drop our + /// reference to the type. + /// + const Type* get() const; // operator-> - Allow user to dereference handle naturally... const Type *operator->() const { return get(); } @@ -166,9 +172,10 @@ private: void addRef(); - void dropRef(); + void dropRef() ; }; } // End llvm namespace +// vim: sw=2 #endif Index: llvm/include/llvm/DerivedTypes.h diff -u llvm/include/llvm/DerivedTypes.h:1.56 llvm/include/llvm/DerivedTypes.h:1.56.2.1 --- llvm/include/llvm/DerivedTypes.h:1.56 Sun Apr 4 20:25:21 2004 +++ llvm/include/llvm/DerivedTypes.h Sun May 16 18:56:20 2004 @@ -18,7 +18,7 @@ #ifndef LLVM_DERIVED_TYPES_H #define LLVM_DERIVED_TYPES_H -#include "llvm/Type.h" +#include "llvm/Value.h" namespace llvm { @@ -35,7 +35,7 @@ mutable std::vector AbstractTypeUsers; protected: - DerivedType(PrimitiveID id) : Type("", id) {} + DerivedType(PrimitiveID id) : Type(id) {} ~DerivedType() { assert(AbstractTypeUsers.empty()); } @@ -88,7 +88,7 @@ /// void refineAbstractTypeTo(const Type *NewType); - void dump() const { Value::dump(); } + void dump() const { Type::dump(); } // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const DerivedType *T) { return true; } From llvm at cs.uiuc.edu Sun May 16 18:57:01 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Sun May 16 18:57:01 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/include/llvm/PrintableItem.h Message-ID: <200405162357.SAA30199@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm: PrintableItem.h added (r1.1.2.1) --- Log message: Added this abstract base class to encapsulate the print(std::ostream&) and dump() methods common to Types and Values. Can be used elsewhere to obtain an object for which "call OBJ->dump()" in the debugger will print out the object. --- Diffs of the changes: (+66 -0) Index: llvm/include/llvm/PrintableItem.h diff -c /dev/null llvm/include/llvm/PrintableItem.h:1.1.2.1 *** /dev/null Sun May 16 18:57:53 2004 --- llvm/include/llvm/PrintableItem.h Sun May 16 18:57:43 2004 *************** *** 0 **** --- 1,66 ---- + //===-- llvm/NamedItem.h - Definition of the Value class --------*- 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 common base class for Type and Value. It provides some + // basic, common functionality that both Type and Value use. + // + //===----------------------------------------------------------------------===// + + #ifndef LLVM_PRINTABLEITEM_H + #define LLVM_PRINTABLEITEM_H + + #include + + namespace llvm { + + //===----------------------------------------------------------------------===// + // PrintableItem Class + //===----------------------------------------------------------------------===// + + /// A base class endowing its subclasses with the ability to be printed on + /// an iostream and dumped in the debugger. + struct PrintableItem { + + public: + /// We have nothing to destruct but we declare the virtual destructor here + /// because PrintableItem is the super class of many other classes. + virtual ~PrintableItem(); + + /// This method is overridden by subclasses to dump the contents + /// of the named item. It is intended to support debugging and + /// is callable in GDB with "call NI->dump()". + /// @brief Dump the named item to stderr. + void dump() const; + + /// Implement operator<< on PrintableItem + virtual void print(std::ostream &O) const = 0; + + }; + + /// An ostream inserter for a pointer to any PrintableItem subclass. + inline std::ostream &operator<<(std::ostream &OS, const PrintableItem *NI) { + if (NI == 0) + OS << " value!\n"; + else + NI->print(OS); + return OS; + } + + /// An ostream inserter for a reference to any PrintableItem subclass. + inline std::ostream &operator<<(std::ostream &OS, const PrintableItem &NI) { + NI.print(OS); + return OS; + } + + } // End llvm namespace + + // vim: sw=2 + + #endif + From llvm at cs.uiuc.edu Sun May 16 19:01:01 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Sun May 16 19:01:01 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/lib/VMCore/Verifier.cpp Message-ID: <200405170001.TAA30232@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Verifier.cpp updated: 1.97.2.1 -> 1.97.2.2 --- Log message: Changes resulting from making Type not be a Value. Had to create a WriteType function and a few more CheckFailed methods to handle the checks involving Types. --- Diffs of the changes: (+19 -7) Index: llvm/lib/VMCore/Verifier.cpp diff -u llvm/lib/VMCore/Verifier.cpp:1.97.2.1 llvm/lib/VMCore/Verifier.cpp:1.97.2.2 --- llvm/lib/VMCore/Verifier.cpp:1.97.2.1 Wed May 12 11:33:43 2004 +++ llvm/lib/VMCore/Verifier.cpp Sun May 16 19:01:17 2004 @@ -183,14 +183,17 @@ if (!V) return; if (isa(V)) { msgs << *V; - } else if (const Type *Ty = dyn_cast(V)) { - WriteTypeSymbolic(msgs, Ty, Mod); } else { WriteAsOperand (msgs, V, true, true, Mod); msgs << "\n"; } } + void WriteType(const Type* T ) { + if ( !T ) return; + WriteTypeSymbolic(msgs, T, Mod ); + } + // CheckFailed - A check failed, so print out the condition and the message // that failed. This provides a nice place to put a breakpoint if you want @@ -205,6 +208,14 @@ WriteValue(V4); Broken = true; } + + void CheckFailed( const std::string& Message, const Value* V1, + const Type* T2, const Value* V3 = 0 ) { + msgs << Message << "\n"; + WriteValue(V1); + WriteType(T2); + WriteValue(V3); + } }; RegisterOpt X("verify", "Module Verifier"); @@ -241,11 +252,12 @@ // void Verifier::verifySymbolTable(SymbolTable &ST) { - // Loop over all of the types in the symbol table... - for (SymbolTable::type_const_iterator TI = ST.begin(), TE = ST.end(); TI != TE; ++TI) - for (SymbolTable::value_const_iterator I = TI->second.begin(), - E = TI->second.end(); I != E; ++I) { - Value *V = I->second; + // Loop over all of the type planes in the symbol table. + for (SymbolTable::plane_const_iterator PI = ST.plane_begin(), + PE = ST.plane_end(); PI != PE; ++PI) + for (SymbolTable::value_const_iterator VI = PI->second.begin(), + VE = PI->second.end(); VI != VE; ++VI) { + Value *V = VI->second; // Check that there are no void typed values in the symbol table. Values // with a void type cannot be put into symbol tables because they cannot // have names! From llvm at cs.uiuc.edu Sun May 16 19:02:01 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Sun May 16 19:02:01 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/lib/VMCore/Type.cpp Message-ID: <200405170002.TAA30258@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Type.cpp updated: 1.99 -> 1.99.2.1 --- Log message: Changes resulting from making Type not be a Value. Moved the implementation of PrintableItem here as well as PATypeHandle and PATypeHolder which used to be in Type.h. Removed unnecessary constructor parameters and global variables pertaining to TypeTy and TypeTyID which do not exist any more. --- Diffs of the changes: (+58 -37) Index: llvm/lib/VMCore/Type.cpp diff -u llvm/lib/VMCore/Type.cpp:1.99 llvm/lib/VMCore/Type.cpp:1.99.2.1 --- llvm/lib/VMCore/Type.cpp:1.99 Sun Apr 4 20:30:19 2004 +++ llvm/lib/VMCore/Type.cpp Sun May 16 19:02:32 2004 @@ -18,6 +18,7 @@ #include "Support/StringExtras.h" #include "Support/STLExtras.h" #include + using namespace llvm; // DEBUG_MERGE_TYPES - Enable this #define to see how and when derived types are @@ -27,6 +28,39 @@ //#define DEBUG_MERGE_TYPES 1 AbstractTypeUser::~AbstractTypeUser() {} +PrintableItem::~PrintableItem() {} + +void PATypeHandle::addUser() { + assert(Ty && "Type Handle has a null type!"); + if (Ty->isAbstract()) + Ty->addAbstractTypeUser(User); +} + +void PATypeHandle::removeUser() { + if (Ty->isAbstract()) + Ty->removeAbstractTypeUser(User); +} + +void PATypeHandle::removeUserFromConcrete() { + if (!Ty->isAbstract()) + Ty->removeAbstractTypeUser(User); +} + +const Type* PATypeHolder::get() const { + const Type *NewTy = Ty->getForwardedType(); + if (!NewTy) return Ty; + return *const_cast(this) = NewTy; +} + +void PATypeHolder::addRef() { + if (Ty->isAbstract()) + Ty->addRef(); +} + +void PATypeHolder::dropRef() { + if (Ty->isAbstract()) + Ty->dropRef(); +} //===----------------------------------------------------------------------===// // Type Class Implementation @@ -42,23 +76,14 @@ static std::map ConcreteTypeDescriptions; static std::map AbstractTypeDescriptions; -Type::Type(const std::string &name, PrimitiveID id) - : Value(Type::TypeTy, Value::TypeVal), RefCount(0), ForwardType(0) { - if (!name.empty()) - ConcreteTypeDescriptions[this] = name; +Type::Type(PrimitiveID id) + : RefCount(0), ForwardType(0) { ID = id; Abstract = false; UID = CurUID++; // Assign types UID's as they are created UIDMappings.push_back(this); } -void Type::setName(const std::string &Name, SymbolTable *ST) { - assert(ST && "Type::setName - Must provide symbol table argument!"); - - if (Name.size()) ST->insert(Name, this); -} - - const Type *Type::getUniqueIDType(unsigned UID) { assert(UID < UIDMappings.size() && "Type::getPrimitiveType: UID out of range!"); @@ -79,7 +104,6 @@ case LongTyID : return LongTy; case FloatTyID : return FloatTy; case DoubleTyID: return DoubleTy; - case TypeTyID : return TypeTy; case LabelTyID : return LabelTy; default: return 0; @@ -319,7 +343,7 @@ // type. // struct SignedIntType : public Type { - SignedIntType(const std::string &Name, PrimitiveID id) : Type(Name, id) {} + SignedIntType(PrimitiveID id) : Type(id) {} // isSigned - Return whether a numeric type is signed. virtual bool isSigned() const { return 1; } @@ -331,7 +355,7 @@ }; struct UnsignedIntType : public Type { - UnsignedIntType(const std::string &N, PrimitiveID id) : Type(N, id) {} + UnsignedIntType(PrimitiveID id) : Type(id) {} // isUnsigned - Return whether a numeric type is signed. virtual bool isUnsigned() const { return 1; } @@ -343,31 +367,27 @@ }; struct OtherType : public Type { - OtherType(const std::string &N, PrimitiveID id) : Type(N, id) {} + OtherType(PrimitiveID id) : Type(id) {} }; -static struct TypeType : public Type { - TypeType() : Type("type", TypeTyID) {} -} TheTypeTy; // Implement the type that is global. - //===----------------------------------------------------------------------===// // Static 'Type' data //===----------------------------------------------------------------------===// -static OtherType TheVoidTy ("void" , Type::VoidTyID); -static OtherType TheBoolTy ("bool" , Type::BoolTyID); -static SignedIntType TheSByteTy ("sbyte" , Type::SByteTyID); -static UnsignedIntType TheUByteTy ("ubyte" , Type::UByteTyID); -static SignedIntType TheShortTy ("short" , Type::ShortTyID); -static UnsignedIntType TheUShortTy("ushort", Type::UShortTyID); -static SignedIntType TheIntTy ("int" , Type::IntTyID); -static UnsignedIntType TheUIntTy ("uint" , Type::UIntTyID); -static SignedIntType TheLongTy ("long" , Type::LongTyID); -static UnsignedIntType TheULongTy ("ulong" , Type::ULongTyID); -static OtherType TheFloatTy ("float" , Type::FloatTyID); -static OtherType TheDoubleTy("double", Type::DoubleTyID); -static OtherType TheLabelTy ("label" , Type::LabelTyID); +static OtherType TheVoidTy ( Type::VoidTyID ); +static OtherType TheBoolTy ( Type::BoolTyID ); +static SignedIntType TheSByteTy ( Type::SByteTyID ); +static UnsignedIntType TheUByteTy ( Type::UByteTyID ); +static SignedIntType TheShortTy ( Type::ShortTyID ); +static UnsignedIntType TheUShortTy( Type::UShortTyID ); +static SignedIntType TheIntTy ( Type::IntTyID ); +static UnsignedIntType TheUIntTy ( Type::UIntTyID ); +static SignedIntType TheLongTy ( Type::LongTyID ); +static UnsignedIntType TheULongTy ( Type::ULongTyID ); +static OtherType TheFloatTy ( Type::FloatTyID ); +static OtherType TheDoubleTy( Type::DoubleTyID ); +static OtherType TheLabelTy ( Type::LabelTyID ); Type *Type::VoidTy = &TheVoidTy; Type *Type::BoolTy = &TheBoolTy; @@ -381,7 +401,6 @@ Type *Type::ULongTy = &TheULongTy; Type *Type::FloatTy = &TheFloatTy; Type *Type::DoubleTy = &TheDoubleTy; -Type *Type::TypeTy = &TheTypeTy; Type *Type::LabelTy = &TheLabelTy; @@ -502,7 +521,7 @@ // that assumes that two graphs are the same until proven otherwise. // static bool TypesEqual(const Type *Ty, const Type *Ty2, - std::map &EqTypes) { + std::map &EqTypes) { if (Ty == Ty2) return true; if (Ty->getPrimitiveID() != Ty2->getPrimitiveID()) return false; if (isa(Ty)) @@ -1130,7 +1149,7 @@ // concrete type. // void ArrayType::refineAbstractType(const DerivedType *OldType, - const Type *NewType) { + const Type *NewType) { ArrayTypes.finishRefinement(this, OldType, NewType); } @@ -1144,7 +1163,7 @@ // concrete type. // void StructType::refineAbstractType(const DerivedType *OldType, - const Type *NewType) { + const Type *NewType) { StructTypes.finishRefinement(this, OldType, NewType); } @@ -1157,10 +1176,12 @@ // concrete type. // void PointerType::refineAbstractType(const DerivedType *OldType, - const Type *NewType) { + const Type *NewType) { PointerTypes.finishRefinement(this, OldType, NewType); } void PointerType::typeBecameConcrete(const DerivedType *AbsTy) { refineAbstractType(AbsTy, AbsTy); } + +// vim: sw=2 From llvm at cs.uiuc.edu Sun May 16 19:05:01 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Sun May 16 19:05:01 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/lib/Analysis/Expressions.cpp Message-ID: <200405170005.TAA30289@zion.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: Expressions.cpp updated: 1.41 -> 1.41.6.1 --- Log message: Remove Value::TypeVal from a case label because there is no such thing as a "Type Value" any more. --- Diffs of the changes: (+1 -1) Index: llvm/lib/Analysis/Expressions.cpp diff -u llvm/lib/Analysis/Expressions.cpp:1.41 llvm/lib/Analysis/Expressions.cpp:1.41.6.1 --- llvm/lib/Analysis/Expressions.cpp:1.41 Mon Jan 12 12:02:15 2004 +++ llvm/lib/Analysis/Expressions.cpp Sun May 16 19:05:07 2004 @@ -248,7 +248,7 @@ switch (Expr->getValueType()) { case Value::InstructionVal: break; // Instruction... hmmm... investigate. - case Value::TypeVal: case Value::BasicBlockVal: + case Value::BasicBlockVal: case Value::FunctionVal: default: //assert(0 && "Unexpected expression type to classify!"); std::cerr << "Bizarre thing to expr classify: " << Expr << "\n"; From llvm at cs.uiuc.edu Sun May 16 19:06:01 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Sun May 16 19:06:01 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/lib/AsmParser/Lexer.l Message-ID: <200405170006.TAA30319@zion.cs.uiuc.edu> Changes in directory llvm/lib/AsmParser: Lexer.l updated: 1.48 -> 1.48.2.1 --- Log message: Don't include "Type" as a primitive type any more. --- Diffs of the changes: (+1 -1) Index: llvm/lib/AsmParser/Lexer.l diff -u llvm/lib/AsmParser/Lexer.l:1.48 llvm/lib/AsmParser/Lexer.l:1.48.2.1 --- llvm/lib/AsmParser/Lexer.l:1.48 Tue Mar 30 21:48:33 2004 +++ llvm/lib/AsmParser/Lexer.l Sun May 16 19:06:31 2004 @@ -212,8 +212,8 @@ ulong { llvmAsmlval.PrimType = Type::ULongTy ; return ULONG; } float { llvmAsmlval.PrimType = Type::FloatTy ; return FLOAT; } double { llvmAsmlval.PrimType = Type::DoubleTy; return DOUBLE; } -type { llvmAsmlval.PrimType = Type::TypeTy ; return TYPE; } label { llvmAsmlval.PrimType = Type::LabelTy ; return LABEL; } +type { return TYPE; } opaque { return OPAQUE; } add { RET_TOK(BinaryOpVal, Add, ADD); } From llvm at cs.uiuc.edu Sun May 16 19:08:01 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Sun May 16 19:08:01 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/lib/AsmParser/llvmAsmParser.y Message-ID: <200405170008.TAA30339@zion.cs.uiuc.edu> Changes in directory llvm/lib/AsmParser: llvmAsmParser.y updated: 1.163 -> 1.163.2.1 --- Log message: Changes resulting from Type not being a Value any more. Had to create a new "setTypeName" function to handle types separately from Values. Made the parser conform its use of SymbolTable to that class's new interface. None of the productions changed significantly. --- Diffs of the changes: (+66 -22) Index: llvm/lib/AsmParser/llvmAsmParser.y diff -u llvm/lib/AsmParser/llvmAsmParser.y:1.163 llvm/lib/AsmParser/llvmAsmParser.y:1.163.2.1 --- llvm/lib/AsmParser/llvmAsmParser.y:1.163 Sat Apr 17 18:49:15 2004 +++ llvm/lib/AsmParser/llvmAsmParser.y Sun May 16 19:08:47 2004 @@ -236,10 +236,10 @@ case ValID::NameVal: { // Is it a named definition? std::string Name(D.Name); SymbolTable *SymTab = 0; - Value *N = 0; + Type *N = 0; if (inFunctionScope()) { SymTab = &CurFun.CurrentFunction->getSymbolTable(); - N = SymTab->lookup(Type::TypeTy, Name); + N = SymTab->lookupType(Name); } if (N == 0) { @@ -247,12 +247,12 @@ // hasn't been added to the module... // SymTab = &CurModule.CurrentModule->getSymbolTable(); - N = SymTab->lookup(Type::TypeTy, Name); + N = SymTab->lookupType(Name); if (N == 0) break; } D.destroy(); // Free old strdup'd memory... - return cast(N); + return N; } default: ThrowException("Internal parser error: Invalid symbol type reference!"); @@ -377,7 +377,6 @@ // real thing. // static Value *getVal(const Type *Ty, const ValID &D) { - assert(Ty != Type::TypeTy && "Should use getTypeVal for types!"); // See if the value has already been defined... Value *V = getValNonImprovising(Ty, D); @@ -517,23 +516,9 @@ Value *Existing = ST.lookup(V->getType(), Name); if (Existing) { // Inserting a name that is already defined??? - // There is only one case where this is allowed: when we are refining an - // opaque type. In this case, Existing will be an opaque type. - if (const Type *Ty = dyn_cast(Existing)) { - if (const OpaqueType *OpTy = dyn_cast(Ty)) { - // We ARE replacing an opaque type! - ((OpaqueType*)OpTy)->refineAbstractTypeTo(cast(V)); - return true; - } - } - // Otherwise, we are a simple redefinition of a value, check to see if it - // is defined the same as the old one... - if (const Type *Ty = dyn_cast(Existing)) { - if (Ty == cast(V)) return true; // Yes, it's equal. - // std::cerr << "Type: " << Ty->getDescription() << " != " - // << cast(V)->getDescription() << "!\n"; - } else if (const Constant *C = dyn_cast(Existing)) { + // Check for legal redefinitions of constants and global variables. + if (const Constant *C = dyn_cast(Existing)) { if (C == V) return true; // Constants are equal to themselves } else if (GlobalVariable *EGV = dyn_cast(Existing)) { // We are allowed to redefine a global variable in two circumstances: @@ -586,6 +571,65 @@ } +static bool setTypeName(Type *T, char *NameStr) { + if (NameStr == 0) return false; + + std::string Name(NameStr); // Copy string + free(NameStr); // Free old string + + if (T->getType() == Type::VoidTy) + ThrowException("Can't assign name '" + Name + + "' to a null valued instruction!"); + + SymbolTable &ST = inFunctionScope() ? + CurFun.CurrentFunction->getSymbolTable() : + CurModule.CurrentModule->getSymbolTable(); + + Type *Existing = ST.lookupType(Name); + if (Existing) { // Inserting a name that is already defined??? + // There is only one case where this is allowed: when we are refining an + // opaque type. In this case, Existing will be an opaque type. + if ( Existing ) { + if (const OpaqueType *OpTy = dyn_cast(T)) { + // We ARE replacing an opaque type! + ((OpaqueType*)OpTy)->refineAbstractTypeTo(T); + return true; + } + } + + // Otherwise, we are a simple redefinition of a value, check to see if it + // is defined the same as the old one... + if ( Existing ) { + if (Existing == T) return true; // Yes, it's equal. + // std::cerr << "Type: " << Ty->getDescription() << " != " + // << cast(V)->getDescription() << "!\n"; + } + + ThrowException("Redefinition of type named '" + Name + "' in the '" + + T->getDescription() + "' type plane!"); + } + + // If we're in function scope + if (inFunctionScope()) { + // Look up the symbol in the function's local symboltable + Existing = CurFun.LocalSymtab.lookupType(Name); + + // If it already exists + if (Existing) { + // Bail + ThrowException("Redefinition of type named '" + Name + "' in the '" + + T->getDescription() + "' type plane!"); + + // otherwise, since it doesn't exist + } else { + // Insert it. + CurFun.LocalSymtab.insert(Name,T); + } + } + return false; +} + + //===----------------------------------------------------------------------===// // Code for handling upreferences in type names... // @@ -1346,7 +1390,7 @@ ResolveTypeTo($2, $4->get()); // TODO: FIXME when Type are not const - if (!setValueName(const_cast($4->get()), $2)) { + if (!setTypeName(const_cast($4->get()), $2)) { // If this is not a redefinition of a type... if (!$2) { InsertType($4->get(), From llvm at cs.uiuc.edu Sun May 16 21:27:02 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Sun May 16 21:27:02 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp Message-ID: <200405170227.VAA30756@zion.cs.uiuc.edu> Changes in directory llvm/lib/ExecutionEngine/Interpreter: ExternalFunctions.cpp updated: 1.73.2.1 -> 1.73.2.2 --- Log message: Remove the getFILE function who's body became null and replace with a macro that performs the type conversion necessary. *NOTE* This change can be merged from bug_122 branch to mainline. --- Diffs of the changes: (+2 -12) Index: llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp diff -u llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp:1.73.2.1 llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp:1.73.2.2 --- llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp:1.73.2.1 Wed May 12 11:33:43 2004 +++ llvm/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp Sun May 16 21:27:31 2004 @@ -22,7 +22,6 @@ #include "Interpreter.h" #include "llvm/DerivedTypes.h" #include "llvm/Module.h" -#include "llvm/SymbolTable.h" #include "llvm/Target/TargetData.h" #include "Support/DynamicLinker.h" #include "Config/dlfcn.h" @@ -541,17 +540,8 @@ //===----------------------------------------------------------------------===// // getFILE - Turn a pointer in the host address space into a legit pointer in -// the interpreter address space. For the most part, this is an identity -// transformation, but if the program refers to stdio, stderr, stdin then they -// have pointers that are relative to the __iob array. If this is the case, -// change the FILE into the REAL stdio stream. -// -static FILE *getFILE(void *Ptr) { - // Content of this function was excised because it had no effect. - // Probably need to avoid its use . - return (FILE*)Ptr; -} - +// the interpreter address space. This is an identity transformation. +#define getFILE(ptr) ((FILE*)ptr) // FILE *fopen(const char *filename, const char *mode); GenericValue lle_X_fopen(FunctionType *M, const vector &Args) { From llvm at cs.uiuc.edu Sun May 16 21:33:01 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Sun May 16 21:33:01 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/lib/Target/SparcV9/SparcV9AsmPrinter.cpp Message-ID: <200405170233.VAA30813@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/SparcV9: SparcV9AsmPrinter.cpp updated: 1.112 -> 1.112.2.1 --- Log message: Remove use of Type::TypeTy because it doesn't exist any more. --- Diffs of the changes: (+1 -3) Index: llvm/lib/Target/SparcV9/SparcV9AsmPrinter.cpp diff -u llvm/lib/Target/SparcV9/SparcV9AsmPrinter.cpp:1.112 llvm/lib/Target/SparcV9/SparcV9AsmPrinter.cpp:1.112.2.1 --- llvm/lib/Target/SparcV9/SparcV9AsmPrinter.cpp:1.112 Tue May 4 16:41:45 2004 +++ llvm/lib/Target/SparcV9/SparcV9AsmPrinter.cpp Sun May 16 21:32:58 2004 @@ -300,9 +300,7 @@ /// Print a single constant value. /// void AsmPrinter::printSingleConstantValue(const Constant* CV) { - assert(CV->getType() != Type::VoidTy && - CV->getType() != Type::TypeTy && - CV->getType() != Type::LabelTy && + assert(CV->getType() != Type::VoidTy && CV->getType() != Type::LabelTy && "Unexpected type for Constant"); assert((!isa(CV) && ! isa(CV)) From llvm at cs.uiuc.edu Sun May 16 21:34:02 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Sun May 16 21:34:02 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/lib/Target/CBackend/Writer.cpp Message-ID: <200405170234.VAA30828@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/CBackend: Writer.cpp updated: 1.174.2.1 -> 1.174.2.2 --- Log message: Apply changes resulting from SymbolTable's interface changes supporting Types distinctly from Values. --- Diffs of the changes: (+19 -18) Index: llvm/lib/Target/CBackend/Writer.cpp diff -u llvm/lib/Target/CBackend/Writer.cpp:1.174.2.1 llvm/lib/Target/CBackend/Writer.cpp:1.174.2.2 --- llvm/lib/Target/CBackend/Writer.cpp:1.174.2.1 Wed May 12 11:33:43 2004 +++ llvm/lib/Target/CBackend/Writer.cpp Sun May 16 21:34:01 2004 @@ -215,19 +215,18 @@ // already named, and removing names for structure types that are not used. // SymbolTable &MST = M.getSymbolTable(); - if (MST.find(Type::TypeTy) != MST.end()) - for (SymbolTable::value_iterator I = MST.type_begin(Type::TypeTy), - E = MST.type_end(Type::TypeTy); I != E; ) { - SymbolTable::value_iterator It = I++; - if (StructType *STy = dyn_cast(It->second)) { - // If this is not used, remove it from the symbol table. - std::set::iterator UTI = UT.find(STy); - if (UTI == UT.end()) - MST.remove(It->first, It->second); - else - UT.erase(UTI); - } + for (SymbolTable::type_iterator TI = MST.type_begin(), TE = MST.type_end(); + TI != TE; ) { + SymbolTable::type_iterator I = TI++; + if (StructType *STy = dyn_cast(I->second)) { + // If this is not used, remove it from the symbol table. + std::set::iterator UTI = UT.find(STy); + if (UTI == UT.end()) + MST.remove(I->first, I->second); + else + UT.erase(UTI); } + } // UT now contains types that are not named. Loop over it, naming // structure types. @@ -861,17 +860,17 @@ /// void CWriter::printModuleTypes(const SymbolTable &ST) { // If there are no type names, exit early. - if (ST.find(Type::TypeTy) == ST.end()) + if ( ST.hasTypes() ) return; // We are only interested in the type plane of the symbol table... - SymbolTable::value_const_iterator I = ST.type_begin(Type::TypeTy); - SymbolTable::value_const_iterator End = ST.type_end(Type::TypeTy); + SymbolTable::type_const_iterator I = ST.type_begin(); + SymbolTable::type_const_iterator End = ST.type_end(); // Print out forward declarations for structure types before anything else! Out << "/* Structure forward decls */\n"; for (; I != End; ++I) - if (const Type *STy = dyn_cast(I->second)) { + if (const StructType *STy = dyn_cast(I->second)) { std::string Name = "struct l_" + Mangler::makeNameProper(I->first); Out << Name << ";\n"; TypeNames.insert(std::make_pair(STy, Name)); @@ -881,7 +880,7 @@ // Now we can print out typedefs... Out << "/* Typedefs */\n"; - for (I = ST.type_begin(Type::TypeTy); I != End; ++I) { + for (I = ST.type_begin(); I != End; ++I) { const Type *Ty = cast(I->second); std::string Name = "l_" + Mangler::makeNameProper(I->first); Out << "typedef "; @@ -898,7 +897,7 @@ // printed in the correct order. // Out << "/* Structure contents */\n"; - for (I = ST.type_begin(Type::TypeTy); I != End; ++I) + for (I = ST.type_begin(); I != End; ++I) if (const StructType *STy = dyn_cast(I->second)) // Only print out used types! printContainedStructs(STy, StructPrinted); @@ -1505,3 +1504,5 @@ IntrinsicLowering *IL) { return new CTargetMachine(M, IL); } + +// vim: sw=2 From llvm at cs.uiuc.edu Sun May 16 21:35:01 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Sun May 16 21:35:01 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/lib/Target/TargetData.cpp Message-ID: <200405170235.VAA30846@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target: TargetData.cpp updated: 1.45 -> 1.45.2.1 --- Log message: Remove use of Type::TypeTyID which no longer exists. --- Diffs of the changes: (+0 -1) Index: llvm/lib/Target/TargetData.cpp diff -u llvm/lib/Target/TargetData.cpp:1.45 llvm/lib/Target/TargetData.cpp:1.45.2.1 --- llvm/lib/Target/TargetData.cpp:1.45 Wed Apr 14 16:21:56 2004 +++ llvm/lib/Target/TargetData.cpp Sun May 16 21:35:06 2004 @@ -180,7 +180,6 @@ return; } - case Type::TypeTyID: default: assert(0 && "Bad type for getTypeInfo!!!"); return; From llvm at cs.uiuc.edu Sun May 16 21:36:00 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Sun May 16 21:36:00 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/lib/Transforms/Utils/CloneModule.cpp Message-ID: <200405170236.VAA30867@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: CloneModule.cpp updated: 1.9.6.1 -> 1.9.6.2 --- Log message: Use correct iterators for type iteration resulting from changes in SymbolTable's interface for supporting Types distinctly from Values. --- Diffs of the changes: (+7 -5) Index: llvm/lib/Transforms/Utils/CloneModule.cpp diff -u llvm/lib/Transforms/Utils/CloneModule.cpp:1.9.6.1 llvm/lib/Transforms/Utils/CloneModule.cpp:1.9.6.2 --- llvm/lib/Transforms/Utils/CloneModule.cpp:1.9.6.1 Wed May 12 11:33:43 2004 +++ llvm/lib/Transforms/Utils/CloneModule.cpp Sun May 16 21:36:38 2004 @@ -33,11 +33,11 @@ // Copy all of the type symbol table entries over... const SymbolTable &SymTab = M->getSymbolTable(); - SymbolTable::type_const_iterator TypeI = SymTab.find(Type::TypeTy); - if (TypeI != SymTab.end()) - for (SymbolTable::value_const_iterator I = TypeI->second.begin(), - E = TypeI->second.end(); I != E; ++I) - New->addTypeName(I->first, cast(I->second)); + SymbolTable::type_const_iterator TypeI = SymTab.type_begin(); + SymbolTable::type_const_iterator TypeE = SymTab.type_end(); + for ( ; TypeI != TypeE; ++TypeI ) { + New->addTypeName(TypeI->first, TypeI->second); + } // Create the value map that maps things from the old module over to the new // module. @@ -89,3 +89,5 @@ return New; } + +// vim: sw=2 From llvm at cs.uiuc.edu Sun May 16 21:37:01 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Sun May 16 21:37:01 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/lib/Transforms/Utils/Linker.cpp Message-ID: <200405170237.VAA30896@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: Linker.cpp updated: 1.69.2.1 -> 1.69.2.2 --- Log message: Use correct iterators for scanning types; resulting from changes to SymbolTable's interface to support distinct handling of Types and Values. --- Diffs of the changes: (+24 -24) Index: llvm/lib/Transforms/Utils/Linker.cpp diff -u llvm/lib/Transforms/Utils/Linker.cpp:1.69.2.1 llvm/lib/Transforms/Utils/Linker.cpp:1.69.2.2 --- llvm/lib/Transforms/Utils/Linker.cpp:1.69.2.1 Wed May 12 11:33:43 2004 +++ llvm/lib/Transforms/Utils/Linker.cpp Sun May 16 21:37:40 2004 @@ -172,22 +172,21 @@ const SymbolTable *SrcST = &Src->getSymbolTable(); // Look for a type plane for Type's... - SymbolTable::type_const_iterator PI = SrcST->find(Type::TypeTy); - if (PI == SrcST->end()) return false; // No named types, do nothing. + SymbolTable::type_const_iterator TI = SrcST->type_begin(); + SymbolTable::type_const_iterator TE = SrcST->type_end(); + if (TI == TE) return false; // No named types, do nothing. // Some types cannot be resolved immediately because they depend on other // types being resolved to each other first. This contains a list of types we // are waiting to recheck. std::vector DelayedTypesToResolve; - const SymbolTable::ValueMap &VM = PI->second; - for (SymbolTable::value_const_iterator I = VM.begin(), E = VM.end(); - I != E; ++I) { - const std::string &Name = I->first; - Type *RHS = cast(I->second); + for ( ; TI != TE; ++TI ) { + const std::string &Name = TI->first; + Type *RHS = TI->second; // Check to see if this type name is already in the dest module... - Type *Entry = cast_or_null(DestST->lookup(Type::TypeTy, Name)); + Type *Entry = DestST->lookupType(Name); if (ResolveTypes(Entry, RHS, DestST, Name)) { // They look different, save the types 'till later to resolve. @@ -203,8 +202,8 @@ // Try direct resolution by name... for (unsigned i = 0; i != DelayedTypesToResolve.size(); ++i) { const std::string &Name = DelayedTypesToResolve[i]; - Type *T1 = cast(VM.find(Name)->second); - Type *T2 = cast(DestST->lookup(Type::TypeTy, Name)); + Type *T1 = SrcST->lookupType(Name); + Type *T2 = DestST->lookupType(Name); if (!ResolveTypes(T2, T1, DestST, Name)) { // We are making progress! DelayedTypesToResolve.erase(DelayedTypesToResolve.begin()+i); @@ -218,8 +217,8 @@ // two types: { int* } and { opaque* } for (unsigned i = 0, e = DelayedTypesToResolve.size(); i != e; ++i) { const std::string &Name = DelayedTypesToResolve[i]; - PATypeHolder T1(cast(VM.find(Name)->second)); - PATypeHolder T2(cast(DestST->lookup(Type::TypeTy, Name))); + PATypeHolder T1(SrcST->lookupType(Name)); + PATypeHolder T2(DestST->lookupType(Name)); if (!RecursiveResolveTypes(T2, T1, DestST, Name)) { // We are making progress! @@ -236,8 +235,8 @@ if (DelayedTypesToResolve.size() == OldSize) { const std::string &Name = DelayedTypesToResolve.back(); - const Type *T1 = cast(VM.find(Name)->second); - const Type *T2 = cast(DestST->lookup(Type::TypeTy, Name)); + const Type *T1 = SrcST->lookupType(Name); + const Type *T2 = DestST->lookupType(Name); std::cerr << "WARNING: Type conflict between types named '" << Name << "'.\n Src='"; WriteTypeSymbolic(std::cerr, T1, Src); @@ -383,29 +382,29 @@ // It doesn't exist exactly, scan through all of the type planes in the symbol // table, checking each of them for a type-compatible version. // - for (SymbolTable::type_iterator I = ST->begin(), E = ST->end(); I != E; ++I) - if (I->first != Type::TypeTy) { - SymbolTable::ValueMap &VM = I->second; - - // Does this type plane contain an entry with the specified name? - SymbolTable::value_iterator TI = VM.find(Name); - if (TI != VM.end()) { + for (SymbolTable::plane_iterator PI = ST->plane_begin(), PE = ST->plane_end(); + PI != PE; ++PI) { + SymbolTable::ValueMap &VM = PI->second; + + // Does this type plane contain an entry with the specified name? + SymbolTable::value_iterator VI = VM.find(Name); + if (VI != VM.end()) { // // Ensure that this type if placed correctly into the symbol table. // - assert(TI->second->getType() == I->first && "Type conflict!"); + assert(VI->second->getType() == PI->first && "Type conflict!"); // // Save a reference to the new type. Resolving the type can modify the // symbol table, invalidating the TI variable. // - Value *ValPtr = TI->second; + Value *ValPtr = VI->second; // // Determine whether we can fold the two types together, resolving them. // If so, we can use this value. // - if (!RecursiveResolveTypes(Ty, I->first, ST, "")) + if (!RecursiveResolveTypes(Ty, PI->first, ST, "")) return cast(ValPtr); } } @@ -925,3 +924,4 @@ return false; } +// vim: sw=2 From llvm at cs.uiuc.edu Sun May 16 21:38:09 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Sun May 16 21:38:09 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/lib/Transforms/IPO/DeadTypeElimination.cpp Message-ID: <200405170238.VAA30915@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: DeadTypeElimination.cpp updated: 1.49.4.1 -> 1.49.4.2 --- Log message: Changes necessary resulting from the new SymbolTable interface for distinctly handling Types and Values. --- Diffs of the changes: (+16 -17) Index: llvm/lib/Transforms/IPO/DeadTypeElimination.cpp diff -u llvm/lib/Transforms/IPO/DeadTypeElimination.cpp:1.49.4.1 llvm/lib/Transforms/IPO/DeadTypeElimination.cpp:1.49.4.2 --- llvm/lib/Transforms/IPO/DeadTypeElimination.cpp:1.49.4.1 Wed May 12 11:33:43 2004 +++ llvm/lib/Transforms/IPO/DeadTypeElimination.cpp Sun May 16 21:38:42 2004 @@ -74,25 +74,24 @@ // Check the symbol table for superfluous type entries... // // Grab the 'type' plane of the module symbol... - SymbolTable::type_iterator STI = ST.find(Type::TypeTy); - if (STI != ST.end()) { - // Loop over all entries in the type plane... - SymbolTable::ValueMap &Plane = STI->second; - for (SymbolTable::value_iterator PI = Plane.begin(); PI != Plane.end();) { - // If this entry should be unconditionally removed, or if we detect that - // the type is not used, remove it. - const Type *RHS = cast(PI->second); - if (ShouldNukeSymtabEntry(RHS) || !UsedTypes.count(RHS)) { - Plane.erase(PI++); - ++NumKilled; - Changed = true; - } else { - ++PI; - // We only need to leave one name for each type. - UsedTypes.erase(RHS); - } + SymbolTable::type_iterator TI = ST.type_begin(); + while ( TI != ST.type_end() ) { + // If this entry should be unconditionally removed, or if we detect that + // the type is not used, remove it. + const Type *RHS = TI->second; + if (ShouldNukeSymtabEntry(RHS) || !UsedTypes.count(RHS)) { + SymbolTable::type_iterator ToRemove = TI++; + ST.remove(TI->second); + ++NumKilled; + Changed = true; + } else { + ++TI; + // We only need to leave one name for each type. + UsedTypes.erase(RHS); } } return Changed; } + +// vim: sw=2 From llvm at cs.uiuc.edu Sun May 16 21:39:02 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Sun May 16 21:39:02 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/lib/Transforms/IPO/MutateStructTypes.cpp Message-ID: <200405170239.VAA30934@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: MutateStructTypes.cpp updated: 1.46.4.1 -> 1.46.4.2 --- Log message: Changes necessary resulting from SymbolTable's new interface for handling Types and Values distinctly. --- Diffs of the changes: (+8 -10) Index: llvm/lib/Transforms/IPO/MutateStructTypes.cpp diff -u llvm/lib/Transforms/IPO/MutateStructTypes.cpp:1.46.4.1 llvm/lib/Transforms/IPO/MutateStructTypes.cpp:1.46.4.2 --- llvm/lib/Transforms/IPO/MutateStructTypes.cpp:1.46.4.1 Wed May 12 11:33:43 2004 +++ llvm/lib/Transforms/IPO/MutateStructTypes.cpp Sun May 16 21:39:41 2004 @@ -269,16 +269,13 @@ // Remap the symbol table to refer to the types in a nice way // SymbolTable &ST = M.getSymbolTable(); - SymbolTable::type_iterator I = ST.find(Type::TypeTy); - if (I != ST.end()) { // Get the type plane for Type's - SymbolTable::ValueMap &Plane = I->second; - for (SymbolTable::value_iterator TI = Plane.begin(), TE = Plane.end(); - TI != TE; ++TI) { - // FIXME: This is gross, I'm reaching right into a symbol table and - // mucking around with it's internals... but oh well. - // - TI->second = (Value*)cast(ConvertType(cast(TI->second))); - } + SymbolTable::type_iterator TI = ST.type_begin(); + SymbolTable::type_iterator TE = ST.type_end(); + for ( ; TI != TE; ++TI ) { + // FIXME: This is gross, I'm reaching right into a symbol table and + // mucking around with it's internals... but oh well. + // + TI->second = const_cast(ConvertType(TI->second)); } } @@ -495,3 +492,4 @@ return true; } +// vim: sw=2 From llvm at cs.uiuc.edu Sun May 16 21:40:01 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Sun May 16 21:40:01 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/lib/Transforms/Scalar/SymbolStripping.cpp Message-ID: <200405170240.VAA30957@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: SymbolStripping.cpp updated: 1.25.6.1 -> 1.25.6.2 --- Log message: Move basic symbol stripping functionality into the SymbolTable class. --- Diffs of the changes: (+2 -6) Index: llvm/lib/Transforms/Scalar/SymbolStripping.cpp diff -u llvm/lib/Transforms/Scalar/SymbolStripping.cpp:1.25.6.1 llvm/lib/Transforms/Scalar/SymbolStripping.cpp:1.25.6.2 --- llvm/lib/Transforms/Scalar/SymbolStripping.cpp:1.25.6.1 Wed May 12 11:33:43 2004 +++ llvm/lib/Transforms/Scalar/SymbolStripping.cpp Sun May 16 21:40:46 2004 @@ -27,14 +27,10 @@ #include "llvm/Pass.h" using namespace llvm; -static bool StripSymbolTable(SymbolTable &SymTab) { - return SymTab.strip(); -} - namespace { struct SymbolStripping : public FunctionPass { virtual bool runOnFunction(Function &F) { - return StripSymbolTable(F.getSymbolTable()); + return F.getSymbolTable().strip(); } virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); @@ -44,7 +40,7 @@ struct FullSymbolStripping : public SymbolStripping { virtual bool doInitialization(Module &M) { - return StripSymbolTable(M.getSymbolTable()); + return M.getSymbolTable().strip(); } }; RegisterOpt Y("mstrip", From llvm at cs.uiuc.edu Sun May 16 21:41:02 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Sun May 16 21:41:02 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/lib/Transforms/Scalar/TailDuplication.cpp Message-ID: <200405170241.VAA30975@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: TailDuplication.cpp updated: 1.19 -> 1.19.2.1 --- Log message: Remove un-needed header file. --- Diffs of the changes: (+0 -1) Index: llvm/lib/Transforms/Scalar/TailDuplication.cpp diff -u llvm/lib/Transforms/Scalar/TailDuplication.cpp:1.19 llvm/lib/Transforms/Scalar/TailDuplication.cpp:1.19.2.1 --- llvm/lib/Transforms/Scalar/TailDuplication.cpp:1.19 Sat Apr 17 19:52:43 2004 +++ llvm/lib/Transforms/Scalar/TailDuplication.cpp Sun May 16 21:41:21 2004 @@ -26,7 +26,6 @@ #include "llvm/Pass.h" #include "llvm/Type.h" #include "llvm/Support/CFG.h" -#include "llvm/Support/ValueHolder.h" #include "llvm/Transforms/Utils/Local.h" #include "Support/CommandLine.h" #include "Support/Debug.h" From llvm at cs.uiuc.edu Sun May 16 21:42:02 2004 From: llvm at cs.uiuc.edu (LLVM) Date: Sun May 16 21:42:02 2004 Subject: [llvm-commits] [bug_122] CVS: llvm/include/llvm/Support/ValueHolder.h Message-ID: <200405170242.VAA30990@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Support: ValueHolder.h (r1.5) removed --- Log message: File not referenced any longer. --- Diffs of the changes: (+0 -0) From reid at x10sys.com Sun May 16 21:47:00 2004 From: reid at x10sys.com (Reid Spencer) Date: Sun May 16 21:47:00 2004 Subject: [llvm-commits] bug_122 changes In-Reply-To: <200405170239.VAA30934@zion.cs.uiuc.edu> References: <200405170239.VAA30934@zion.cs.uiuc.edu> Message-ID: <1084761913.10195.1164.camel@bashful.x10sys.com> Just a note to those watching the commits. I've now committed all the *basic* changes needed to support goals 1 and 2 of bug 122. That is, make Type not be a Value and clean up the SymbolTable interface. I've committed this (on the bug_122 branch) in case any of you want to review the changes and make comments. What *hasn't* been committed yet is the SlotCalculator. The changes necessary to this class are extensive and I'll be working on it for a while. I'll commit those at a late date. You shouldn't expect this branch to compile (yet). Reid. -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 189 bytes Desc: This is a digitally signed message part URL: