From vadve at cs.uiuc.edu Mon Sep 30 11:15:01 2002 From: vadve at cs.uiuc.edu (Vikram Adve) Date: Mon Sep 30 11:15:01 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/LLC/badarg6.ll Message-ID: <200209301614.LAA00627@psmith.cs.uiuc.edu> Changes in directory llvm/test/Regression/LLC: badarg6.ll added (r1.1) --- Log message: On this code, llc did not pass the sixth argument (%reg321) to printf. --- Diffs of the changes: From lattner at cs.uiuc.edu Mon Sep 30 14:23:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Sep 30 14:23:01 2002 Subject: [llvm-commits] CVS: llvm/test/Programs/MultiSource/Makefile Message-ID: <200209301922.OAA24002@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/MultiSource: Makefile updated: 1.1 -> 1.2 --- Log message: Allow building tests in parallel. --- Diffs of the changes: Index: llvm/test/Programs/MultiSource/Makefile diff -u llvm/test/Programs/MultiSource/Makefile:1.1 llvm/test/Programs/MultiSource/Makefile:1.2 --- llvm/test/Programs/MultiSource/Makefile:1.1 Tue Jan 22 10:41:48 2002 +++ llvm/test/Programs/MultiSource/Makefile Mon Sep 30 14:22:22 2002 @@ -1,6 +1,6 @@ # MultiSource Makefile: Build all subdirectories automatically LEVEL = ../../.. -DIRS := $(filter-out %-disabled/, $(sort $(filter-out CVS/, $(wildcard */)))) +PARALLEL_DIRS := $(filter-out %-disabled/, $(sort $(filter-out CVS/, $(wildcard */)))) include ${LEVEL}/Makefile.common From lattner at cs.uiuc.edu Mon Sep 30 14:25:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Sep 30 14:25:00 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/DSAnalysis/Makefile Message-ID: <200209301924.OAA24031@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/DSAnalysis: Makefile added (r1.1) --- Log message: Allow production of -stats output for benchmarks by specifying ENABLE_STATS=1 on the make command line. --- Diffs of the changes: From lattner at cs.uiuc.edu Mon Sep 30 14:25:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Sep 30 14:25:01 2002 Subject: [llvm-commits] CVS: llvm/test/Programs/MultiSource/Makefile.multisrc Message-ID: <200209301924.OAA24036@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/MultiSource: Makefile.multisrc updated: 1.15 -> 1.16 --- Log message: Allow production of -stats output for benchmarks by specifying ENABLE_STATS=1 on the make command line. --- Diffs of the changes: Index: llvm/test/Programs/MultiSource/Makefile.multisrc diff -u llvm/test/Programs/MultiSource/Makefile.multisrc:1.15 llvm/test/Programs/MultiSource/Makefile.multisrc:1.16 --- llvm/test/Programs/MultiSource/Makefile.multisrc:1.15 Fri Sep 13 08:50:48 2002 +++ llvm/test/Programs/MultiSource/Makefile.multisrc Mon Sep 30 14:23:40 2002 @@ -53,12 +53,12 @@ $(LDIS) -f $< -o $@ Output/%.linked.bc: Output/%.linked.rll $(LGCCAS) - $(LGCCAS) $< -o $@ + $(LGCCAS) $(STATS) $< -o $@ # Link the program to the libraries it uses, then perform postlink # optimization... Output/%.llvm Output/%.llvm.bc: Output/%.linked.bc - $(LGCCLD) $< -lgcc -lc $(LIBS) -o $(<:.linked.bc=.llvm) + $(LGCCLD) $(STATS) $< -lgcc -lc $(LIBS) -o $(<:.linked.bc=.llvm) Output/%.native: $(NObjects) $(CC) -o $@ $(NObjects) $(LDFLAGS) $(CFLAGS) From lattner at cs.uiuc.edu Mon Sep 30 14:25:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Sep 30 14:25:01 2002 Subject: [llvm-commits] CVS: llvm/test/Makefile.tests Message-ID: <200209301924.OAA24043@apoc.cs.uiuc.edu> Changes in directory llvm/test: Makefile.tests updated: 1.45 -> 1.46 --- Log message: Allow production of -stats output for benchmarks by specifying ENABLE_STATS=1 on the make command line. --- Diffs of the changes: Index: llvm/test/Makefile.tests diff -u llvm/test/Makefile.tests:1.45 llvm/test/Makefile.tests:1.46 --- llvm/test/Makefile.tests:1.45 Sun Sep 29 17:58:51 2002 +++ llvm/test/Makefile.tests Mon Sep 30 14:23:22 2002 @@ -5,9 +5,15 @@ ## NOTE: This is preliminary and will change in the future - include ${LEVEL}/Makefile.common +# Specify ENABLE_STATS on the command line to enable -stats output from gccas +# and gccld. +ifdef ENABLE_STATS +STATS = -stats +endif + + .PHONY: clean default # These files, which might be intermediate results, should not be deleted by @@ -74,7 +80,7 @@ # from GCC output, so use GCCAS. # Output/%.bc: Output/%.ll $(LGCCAS) - $(LGCCAS) $< -o $@ + $(LGCCAS) $(STATS) $< -o $@ # LLVM Assemble from X.ll to Output/X.bc. Because we are coming directly from # LLVM source, use the non-transforming assembler. From lattner at cs.uiuc.edu Mon Sep 30 14:25:02 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Sep 30 14:25:02 2002 Subject: [llvm-commits] CVS: llvm/test/Programs/SingleSource/Makefile.singlesrc Message-ID: <200209301924.OAA24048@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/SingleSource: Makefile.singlesrc updated: 1.11 -> 1.12 --- Log message: Allow production of -stats output for benchmarks by specifying ENABLE_STATS=1 on the make command line. --- Diffs of the changes: Index: llvm/test/Programs/SingleSource/Makefile.singlesrc diff -u llvm/test/Programs/SingleSource/Makefile.singlesrc:1.11 llvm/test/Programs/SingleSource/Makefile.singlesrc:1.12 --- llvm/test/Programs/SingleSource/Makefile.singlesrc:1.11 Wed Aug 21 22:22:08 2002 +++ llvm/test/Programs/SingleSource/Makefile.singlesrc Mon Sep 30 14:23:55 2002 @@ -30,4 +30,4 @@ # # FIXME: LIBS should be specified, not hardcoded to -lc -lm Output/%.llvm Output/%.llvm.bc: Output/%.bc - $(LGCCLD) $< -lgcc -lc -lm -o $(<:.bc=.llvm) + $(LGCCLD) $(STATS) $< -lgcc -lc -lm -o $(<:.bc=.llvm) From lattner at cs.uiuc.edu Mon Sep 30 14:30:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Sep 30 14:30:01 2002 Subject: [llvm-commits] CVS: CVSROOT/commit-diffs.pl Message-ID: <200209301929.OAA24088@apoc.cs.uiuc.edu> Changes in directory CVSROOT: commit-diffs.pl updated: 1.29 -> 1.30 --- Log message: Attempt to get rid of "can not lock" messages from checkins --- Diffs of the changes: Index: CVSROOT/commit-diffs.pl diff -u CVSROOT/commit-diffs.pl:1.29 CVSROOT/commit-diffs.pl:1.30 --- CVSROOT/commit-diffs.pl:1.29 Tue Sep 17 18:22:08 2002 +++ CVSROOT/commit-diffs.pl Mon Sep 30 14:29:44 2002 @@ -51,7 +51,7 @@ # Do a small delay so that the main CVS task finishes and # releases locks first. -sleep 3; +sleep 10; if ($DEBUG) { for ($i=0; $i<8; $i++) { @@ -118,7 +118,7 @@ $msg .= "$m->{'filename'} (r$m->{'oldrev'}) removed\n"; } else { $msg .= "$m->{'filename'} updated: $m->{'oldrev'} -> $m->{'newrev'}\n"; - $diffs .= `cvs -Qf rdiff -u -r $m->{'oldrev'} -r $m->{'newrev'} $changedir/$m->{'filename'}` . "\n\n"; + $diffs .= `cvs -Qf rdiff -u -r $m->{'oldrev'} -r $m->{'newrev'} $changedir/$m->{'filename'} 2> /dev/null` . "\n\n"; } } $msg .= "\n---\nLog message:\n\n" . join('', at logmessage); From lattner at cs.uiuc.edu Mon Sep 30 14:45:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon Sep 30 14:45:01 2002 Subject: [llvm-commits] CVS: llvm/test/Programs/Makefile.programs Message-ID: <200209301944.OAA26756@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs: Makefile.programs updated: 1.14 -> 1.15 --- Log message: Make sure that the bytecode for a program is always built, regardless of what other options are specified --- Diffs of the changes: Index: llvm/test/Programs/Makefile.programs diff -u llvm/test/Programs/Makefile.programs:1.14 llvm/test/Programs/Makefile.programs:1.15 --- llvm/test/Programs/Makefile.programs:1.14 Mon Sep 23 09:23:52 2002 +++ llvm/test/Programs/Makefile.programs Mon Sep 30 14:44:40 2002 @@ -30,7 +30,7 @@ include $(LEVEL)/test/Makefile.tests .PRECIOUS: Output/%.llvm Output/%.native Output/%.llc Output/%.llc.s -.PRECIOUS: Output/%.cbe Output/%.cbe.c +.PRECIOUS: Output/%.cbe Output/%.cbe.c Output/%.llvm.bc # TIMEPROG - The program used to get timing results for a program TIMEPROG = $(LEVEL)/test/Programs/TimeProgram.sh @@ -41,8 +41,11 @@ # We will be working in the Output directory... PREFIXED_PROGRAMS_TO_TEST := $(addprefix Output/,$(PROGRAMS_TO_TEST)) +# Completed bytecode for a program +BYTECODE := $(addsuffix .llvm.bc, $(PREFIXED_PROGRAMS_TO_TEST)) + # Generated code for llc (which does not require the target platform) -LLCCODEGEN := $(addsuffix .llc.s, $(PREFIXED_PROGRAMS_TO_TEST)) +LLCCODEGEN := $(addsuffix .llc.s, $(PREFIXED_PROGRAMS_TO_TEST)) # Output produced by programs run GCCOUTPUT := $(addsuffix .ll, $(addprefix Output/,$(Source:.c=))) @@ -61,6 +64,10 @@ # Build diffs for LLI and LLC output... .PRECIOUS: Output/%.diff-lli Output/%.diff-llc Output/%.diff-cbe + +# Regardless of what other options are specified, build the program's bytecode +# representation. +all:: $(BYTECODE) ifdef RUN_GCC_ONLY DISABLE_LLC = 1 From hldnbrnd at cs.uiuc.edu Mon Sep 30 16:13:01 2002 From: hldnbrnd at cs.uiuc.edu (Nicholas Hildenbrandt) Date: Mon Sep 30 16:13:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CWriter/Writer.cpp Message-ID: <200209302112.QAA07831@trinity.cs.uiuc.edu> Changes in directory llvm/lib/CWriter: Writer.cpp updated: 1.54 -> 1.55 --- Log message: Fixed to properly escape quotes in strings. --- Diffs of the changes: Index: llvm/lib/CWriter/Writer.cpp diff -u llvm/lib/CWriter/Writer.cpp:1.54 llvm/lib/CWriter/Writer.cpp:1.55 --- llvm/lib/CWriter/Writer.cpp:1.54 Wed Sep 25 15:29:26 2002 +++ llvm/lib/CWriter/Writer.cpp Mon Sep 30 16:11:55 2002 @@ -287,7 +287,10 @@ (unsigned char)cast(CPA->getOperand(i))->getValue(); if (isprint(C)) { - Out << C; + if (C == '"') + Out << "\\\""; + else + Out << C; } else { switch (C) { case '\n': Out << "\\n"; break; @@ -295,6 +298,8 @@ case '\r': Out << "\\r"; break; case '\v': Out << "\\v"; break; case '\a': Out << "\\a"; break; + case '\"': Out << "\\\""; break; + case '\'': Out << "\\\'"; break; default: Out << "\\x"; Out << ( C/16 < 10) ? ( C/16 +'0') : ( C/16 -10+'A'); From lattner at cs.uiuc.edu Tue Oct 1 14:38:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Oct 1 14:38:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Support/Timer.cpp Message-ID: <200210011937.OAA01470@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Support: Timer.cpp added (r1.1) --- Log message: Checkin generic interval timer support --- Diffs of the changes: From lattner at cs.uiuc.edu Tue Oct 1 14:38:02 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Oct 1 14:38:02 2002 Subject: [llvm-commits] CVS: llvm/include/Support/Timer.h Message-ID: <200210011937.OAA01467@apoc.cs.uiuc.edu> Changes in directory llvm/include/Support: Timer.h added (r1.1) --- Log message: Checkin generic interval timer support --- Diffs of the changes: From lattner at cs.uiuc.edu Tue Oct 1 14:55:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Oct 1 14:55:01 2002 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Pass.cpp PassManagerT.h Message-ID: <200210011954.OAA02078@apoc.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Pass.cpp updated: 1.38 -> 1.39 PassManagerT.h updated: 1.30 -> 1.31 --- Log message: Factor timer code out of PassManager implementation, into a generic interface exposed by Support/Timer.h. --- Diffs of the changes: Index: llvm/lib/VMCore/Pass.cpp diff -u llvm/lib/VMCore/Pass.cpp:1.38 llvm/lib/VMCore/Pass.cpp:1.39 --- llvm/lib/VMCore/Pass.cpp:1.38 Wed Sep 25 16:59:11 2002 +++ llvm/lib/VMCore/Pass.cpp Tue Oct 1 14:54:07 2002 @@ -80,142 +80,12 @@ EnableTiming("time-passes", cl::desc("Time each pass, printing elapsed time for each on exit")); -static TimeRecord getTimeRecord() { - static unsigned long PageSize = 0; - - if (PageSize == 0) { -#ifdef _SC_PAGE_SIZE - PageSize = sysconf(_SC_PAGE_SIZE); -#else -#ifdef _SC_PAGESIZE - PageSize = sysconf(_SC_PAGESIZE); -#else - PageSize = getpagesize(); -#endif -#endif - } - - struct rusage RU; - struct timeval T; - gettimeofday(&T, 0); - if (getrusage(RUSAGE_SELF, &RU)) { - perror("getrusage call failed: -time-passes info incorrect!"); - } - - TimeRecord Result; - Result.Elapsed = T.tv_sec + T.tv_usec/1000000.0; - Result.UserTime = RU.ru_utime.tv_sec + RU.ru_utime.tv_usec/1000000.0; - Result.SystemTime = RU.ru_stime.tv_sec + RU.ru_stime.tv_usec/1000000.0; - Result.MaxRSS = RU.ru_maxrss*PageSize; - - return Result; -} - -bool TimeRecord::operator<(const TimeRecord &TR) const { - // Primary sort key is User+System time - if (UserTime+SystemTime < TR.UserTime+TR.SystemTime) - return true; - if (UserTime+SystemTime > TR.UserTime+TR.SystemTime) - return false; - - // Secondary sort key is Wall Time - return Elapsed < TR.Elapsed; -} - -void TimeRecord::passStart(const TimeRecord &T) { - Elapsed -= T.Elapsed; - UserTime -= T.UserTime; - SystemTime -= T.SystemTime; - RSSTemp = T.MaxRSS; -} - -void TimeRecord::passEnd(const TimeRecord &T) { - Elapsed += T.Elapsed; - UserTime += T.UserTime; - SystemTime += T.SystemTime; - RSSTemp = T.MaxRSS - RSSTemp; - MaxRSS = std::max(MaxRSS, RSSTemp); -} - -static void printVal(double Val, double Total) { - if (Total < 1e-7) // Avoid dividing by zero... - fprintf(stderr, " ----- "); - else - fprintf(stderr, " %7.4f (%5.1f%%)", Val, Val*100/Total); -} - -void TimeRecord::print(const char *PassName, const TimeRecord &Total) const { - printVal(UserTime, Total.UserTime); - printVal(SystemTime, Total.SystemTime); - printVal(UserTime+SystemTime, Total.UserTime+Total.SystemTime); - printVal(Elapsed, Total.Elapsed); - - fprintf(stderr, " "); - - if (Total.MaxRSS) - std::cerr << MaxRSS << "\t"; - std::cerr << PassName << "\n"; -} - - // Create method. If Timing is enabled, this creates and returns a new timing // object, otherwise it returns null. // TimingInfo *TimingInfo::create() { return EnableTiming ? new TimingInfo() : 0; } - -void TimingInfo::passStarted(Pass *P) { - TimingData[P].passStart(getTimeRecord()); -} -void TimingInfo::passEnded(Pass *P) { - TimingData[P].passEnd(getTimeRecord()); -} -void TimeRecord::sum(const TimeRecord &TR) { - Elapsed += TR.Elapsed; - UserTime += TR.UserTime; - SystemTime += TR.SystemTime; - MaxRSS += TR.MaxRSS; -} - -// TimingDtor - Print out information about timing information -TimingInfo::~TimingInfo() { - // Iterate over all of the data, converting it into the dual of the data map, - // so that the data is sorted by amount of time taken, instead of pointer. - // - std::vector > Data; - TimeRecord Total; - for (std::map::iterator I = TimingData.begin(), - E = TimingData.end(); I != E; ++I) - // Throw out results for "grouping" pass managers... - if (!dynamic_cast(I->first)) { - Data.push_back(std::make_pair(I->second, I->first)); - Total.sum(I->second); - } - - // Sort the data by time as the primary key, in reverse order... - std::sort(Data.begin(), Data.end(), - std::greater >()); - - // Print out timing header... - std::cerr << std::string(79, '=') << "\n" - << " ... Pass execution timing report ...\n" - << std::string(79, '=') << "\n Total Execution Time: " - << (Total.UserTime+Total.SystemTime) << " seconds (" - << Total.Elapsed << " wall clock)\n\n ---User Time--- " - << "--System Time-- --User+System-- ---Wall Time---"; - - if (Total.MaxRSS) - std::cerr << " ---Mem---"; - std::cerr << " --- Pass Name ---\n"; - - // Loop through all of the timing data, printing it out... - for (unsigned i = 0, e = Data.size(); i != e; ++i) - Data[i].first.print(Data[i].second->getPassName(), Total); - - Total.print("TOTAL", Total); -} - void PMDebug::PrintArgumentInformation(const Pass *P) { // Print out passes in pass manager... Index: llvm/lib/VMCore/PassManagerT.h diff -u llvm/lib/VMCore/PassManagerT.h:1.30 llvm/lib/VMCore/PassManagerT.h:1.31 --- llvm/lib/VMCore/PassManagerT.h:1.30 Sun Sep 29 17:50:22 2002 +++ llvm/lib/VMCore/PassManagerT.h Tue Oct 1 14:54:07 2002 @@ -18,6 +18,7 @@ #include "llvm/Pass.h" #include "Support/CommandLine.h" #include "Support/LeakDetector.h" +#include "Support/Timer.h" #include #include class Annotable; @@ -75,25 +76,13 @@ // amount of time each pass takes to execute. This only happens when // -time-passes is enabled on the command line. // -struct TimeRecord { // TimeRecord - Data we collect and print for each pass - double Elapsed; // Wall clock time elapsed in seconds - double UserTime; // User time elapsed - double SystemTime; // System time elapsed - unsigned long MaxRSS; // Maximum resident set size (in bytes) - unsigned long RSSTemp; // Temp for calculating maxrss - - TimeRecord() : Elapsed(0), UserTime(0), SystemTime(0), MaxRSS(0) {} - void passStart(const TimeRecord &T); - void passEnd(const TimeRecord &T); - void sum(const TimeRecord &TR); - bool operator<(const TimeRecord &TR) const; - - void print(const char *PassName, const TimeRecord &TotalTime) const; -}; class TimingInfo { - std::map TimingData; - TimingInfo() {} // Private ctor, must use create member + std::map TimingData; + TimerGroup TG; + + // Private ctor, must use 'create' member + TimingInfo() : TG("... Pass execution timing report ...") {} public: // Create method. If Timing is enabled, this creates and returns a new timing // object, otherwise it returns null. @@ -101,10 +90,23 @@ static TimingInfo *create(); // TimingDtor - Print out information about timing information - ~TimingInfo(); + ~TimingInfo() { + // Delete all of the timers... + TimingData.clear(); + // TimerGroup is deleted next, printing the report. + } - void passStarted(Pass *P); - void passEnded(Pass *P); + void passStarted(Pass *P) { + std::map::iterator I = TimingData.find(P); + if (I == TimingData.end()) + I = TimingData.insert(std::make_pair(P, Timer(P->getPassName()))).first; + I->second.startTimer(); + } + void passEnded(Pass *P) { + std::map::iterator I = TimingData.find(P); + assert (I != TimingData.end() && "passStarted/passEnded not nested right!"); + I->second.stopTimer(); + } }; //===----------------------------------------------------------------------===// From lattner at cs.uiuc.edu Tue Oct 1 15:09:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Oct 1 15:09:01 2002 Subject: [llvm-commits] CVS: llvm/lib/VMCore/PassManagerT.h Message-ID: <200210012008.PAA08982@apoc.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: PassManagerT.h updated: 1.31 -> 1.32 --- Log message: Make sure not to count the PassManager wrapers --- Diffs of the changes: Index: llvm/lib/VMCore/PassManagerT.h diff -u llvm/lib/VMCore/PassManagerT.h:1.31 llvm/lib/VMCore/PassManagerT.h:1.32 --- llvm/lib/VMCore/PassManagerT.h:1.31 Tue Oct 1 14:54:07 2002 +++ llvm/lib/VMCore/PassManagerT.h Tue Oct 1 15:08:11 2002 @@ -97,12 +97,14 @@ } void passStarted(Pass *P) { + if (dynamic_cast(P)) return; std::map::iterator I = TimingData.find(P); if (I == TimingData.end()) I = TimingData.insert(std::make_pair(P, Timer(P->getPassName()))).first; I->second.startTimer(); } void passEnded(Pass *P) { + if (dynamic_cast(P)) return; std::map::iterator I = TimingData.find(P); assert (I != TimingData.end() && "passStarted/passEnded not nested right!"); I->second.stopTimer(); From lattner at cs.uiuc.edu Tue Oct 1 15:13:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Oct 1 15:13:01 2002 Subject: [llvm-commits] CVS: llvm/lib/VMCore/PassManagerT.h Message-ID: <200210012012.PAA09835@apoc.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: PassManagerT.h updated: 1.32 -> 1.33 --- Log message: Make sure to use the TimerGroup that we created! --- Diffs of the changes: Index: llvm/lib/VMCore/PassManagerT.h diff -u llvm/lib/VMCore/PassManagerT.h:1.32 llvm/lib/VMCore/PassManagerT.h:1.33 --- llvm/lib/VMCore/PassManagerT.h:1.32 Tue Oct 1 15:08:11 2002 +++ llvm/lib/VMCore/PassManagerT.h Tue Oct 1 15:12:06 2002 @@ -100,7 +100,7 @@ if (dynamic_cast(P)) return; std::map::iterator I = TimingData.find(P); if (I == TimingData.end()) - I = TimingData.insert(std::make_pair(P, Timer(P->getPassName()))).first; + I=TimingData.insert(std::make_pair(P, Timer(P->getPassName(), TG))).first; I->second.startTimer(); } void passEnded(Pass *P) { From lattner at cs.uiuc.edu Tue Oct 1 15:20:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Oct 1 15:20:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Instrumentation/ProfilePaths/Graph.h Message-ID: <200210012019.PAA10179@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Instrumentation/ProfilePaths: Graph.h (r1.6) removed --- Log message: This file appears to be a duplicate of include/llvm/Transforms/Instrumentation/Graph.h It cannot be used because it contains garbage from conflicts from updating the file. I'm removing it, but it can be resurrected from CVS if needed. --- Diffs of the changes: From lattner at cs.uiuc.edu Tue Oct 1 17:35:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Oct 1 17:35:00 2002 Subject: [llvm-commits] CVS: llvm/lib/Analysis/DataStructure/Steensgaard.cpp Message-ID: <200210012234.RAA18175@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis/DataStructure: Steensgaard.cpp added (r1.1) --- Log message: Initial checkin of Steensgaards context insensitive flow insensitive alias analysis --- Diffs of the changes: From lattner at cs.uiuc.edu Tue Oct 1 17:35:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Oct 1 17:35:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp DataStructure.cpp Local.cpp Printer.cpp TopDownClosure.cpp Message-ID: <200210012234.RAA18188@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis/DataStructure: BottomUpClosure.cpp updated: 1.11 -> 1.12 DataStructure.cpp updated: 1.18 -> 1.19 Local.cpp updated: 1.11 -> 1.12 Printer.cpp updated: 1.7 -> 1.8 TopDownClosure.cpp updated: 1.4 -> 1.5 --- Log message: Checkin some major reworks of data structure analysis. This is not done, nor does it work very well, but I need to get it checked in before I break the tree unintentionally. --- Diffs of the changes: Index: llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp diff -u llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp:1.11 llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp:1.12 --- llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp:1.11 Wed Aug 21 12:09:36 2002 +++ llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp Tue Oct 1 17:33:50 2002 @@ -10,10 +10,12 @@ #include "llvm/Analysis/DataStructure.h" #include "llvm/Module.h" #include "llvm/DerivedTypes.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" #include using std::map; +#if 0 + static RegisterAnalysis X("budatastructure", "Bottom-up Data Structure Analysis Closure"); @@ -240,3 +242,4 @@ return *Graph; } +#endif Index: llvm/lib/Analysis/DataStructure/DataStructure.cpp diff -u llvm/lib/Analysis/DataStructure/DataStructure.cpp:1.18 llvm/lib/Analysis/DataStructure/DataStructure.cpp:1.19 --- llvm/lib/Analysis/DataStructure/DataStructure.cpp:1.18 Wed Aug 7 16:41:03 2002 +++ llvm/lib/Analysis/DataStructure/DataStructure.cpp Tue Oct 1 17:33:50 2002 @@ -4,35 +4,43 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Analysis/DataStructure.h" -#include "llvm/Module.h" +#include "llvm/Analysis/DSGraph.h" +#include "llvm/Function.h" #include "llvm/DerivedTypes.h" #include "Support/STLExtras.h" -#include "Support/StatisticReporter.h" -#include "Support/STLExtras.h" +#include "Support/Statistic.h" +#include "llvm/Target/TargetData.h" #include +#include using std::vector; +// TODO: FIXME +namespace DataStructureAnalysis { + // isPointerType - Return true if this first class type is big enough to hold + // a pointer. + // + bool isPointerType(const Type *Ty); + extern TargetData TD; +} +using namespace DataStructureAnalysis; + //===----------------------------------------------------------------------===// // DSNode Implementation //===----------------------------------------------------------------------===// -DSNode::DSNode(enum NodeTy NT, const Type *T) : Ty(T), NodeType(NT) { - // If this node has any fields, allocate them now, but leave them null. - switch (T->getPrimitiveID()) { - case Type::PointerTyID: Links.resize(1); break; - case Type::ArrayTyID: Links.resize(1); break; - case Type::StructTyID: - Links.resize(cast(T)->getNumContainedTypes()); - break; - default: break; - } +DSNode::DSNode(enum NodeTy NT, const Type *T) : NodeType(NT) { + // If this node is big enough to have pointer fields, add space for them now. + if (T != Type::VoidTy && !isa(T)) // Avoid TargetData assert's + LinkIndex.resize(TD.getTypeSize(T), -1); + + TypeEntries.push_back(std::make_pair(T, 0)); } // DSNode copy constructor... do not copy over the referrers list! DSNode::DSNode(const DSNode &N) - : Ty(N.Ty), Links(N.Links), Globals(N.Globals), NodeType(N.NodeType) { + : Links(N.Links), LinkIndex(N.LinkIndex), + TypeEntries(N.TypeEntries), Globals(N.Globals), NodeType(N.NodeType) { } void DSNode::removeReferrer(DSNodeHandle *H) { @@ -53,7 +61,7 @@ std::lower_bound(Globals.begin(), Globals.end(), GV); if (I == Globals.end() || *I != GV) { - assert(GV->getType()->getElementType() == Ty); + //assert(GV->getType()->getElementType() == Ty); Globals.insert(I, GV); NodeType |= GlobalNode; } @@ -63,58 +71,154 @@ // addEdgeTo - Add an edge from the current node to the specified node. This // can cause merging of nodes in the graph. // -void DSNode::addEdgeTo(unsigned LinkNo, DSNode *N) { - assert(LinkNo < Links.size() && "LinkNo out of range!"); - if (N == 0 || Links[LinkNo] == N) return; // Nothing to do - if (Links[LinkNo] == 0) { // No merging to perform - Links[LinkNo] = N; +void DSNode::addEdgeTo(unsigned Offset, const DSNodeHandle &NH) { + assert(Offset < LinkIndex.size() && "Offset out of range!"); + if (NH.getNode() == 0) return; // Nothing to do + + if (LinkIndex[Offset] == -1) { // No merging to perform... + LinkIndex[Offset] = Links.size(); // Allocate a new link... + Links.push_back(NH); + return; + } + + unsigned Idx = (unsigned)LinkIndex[Offset]; + if (!Links[Idx].getNode()) { // No merging to perform + Links[Idx] = NH; return; } // Merge the two nodes... - Links[LinkNo]->mergeWith(N); + Links[Idx].mergeWith(NH); } -// mergeWith - Merge this node into the specified node, moving all links to and -// from the argument node into the current node. The specified node may be a -// null pointer (in which case, nothing happens). +// MergeSortedVectors - Efficiently merge a vector into another vector where +// duplicates are not allowed and both are sorted. This assumes that 'T's are +// efficiently copyable and have sane comparison semantics. // -void DSNode::mergeWith(DSNode *N) { - if (N == 0 || N == this) return; // Noop - assert(N->Ty == Ty && N->Links.size() == Links.size() && - "Cannot merge nodes of two different types!"); +template +void MergeSortedVectors(vector &Dest, const vector &Src) { + // By far, the most common cases will be the simple ones. In these cases, + // avoid having to allocate a temporary vector... + // + if (Src.empty()) { // Nothing to merge in... + return; + } else if (Dest.empty()) { // Just copy the result in... + Dest = Src; + } else if (Src.size() == 1) { // Insert a single element... + const T &V = Src[0]; + typename vector::iterator I = + std::lower_bound(Dest.begin(), Dest.end(), V); + if (I == Dest.end() || *I != Src[0]) // If not already contained... + Dest.insert(I, Src[0]); + } else if (Dest.size() == 1) { + T Tmp = Dest[0]; // Save value in temporary... + Dest = Src; // Copy over list... + typename vector::iterator I = + std::lower_bound(Dest.begin(), Dest.end(),Tmp); + if (I == Dest.end() || *I != Src[0]) // If not already contained... + Dest.insert(I, Src[0]); + + } else { + // Make a copy to the side of Dest... + vector Old(Dest); + + // Make space for all of the type entries now... + Dest.resize(Dest.size()+Src.size()); + + // Merge the two sorted ranges together... into Dest. + std::merge(Old.begin(), Old.end(), Src.begin(), Src.end(), Dest.begin()); + + // Now erase any duplicate entries that may have accumulated into the + // vectors (because they were in both of the input sets) + Dest.erase(std::unique(Dest.begin(), Dest.end()), Dest.end()); + } +} + + +// mergeWith - Merge this node and the specified node, moving all links to and +// from the argument node into the current node, deleting the node argument. +// Offset indicates what offset the specified node is to be merged into the +// current node. +// +// The specified node may be a null pointer (in which case, nothing happens). +// +void DSNode::mergeWith(const DSNodeHandle &NH, unsigned Offset) { + DSNode *N = NH.getNode(); + if (N == 0 || (N == this && NH.getOffset() == Offset)) + return; // Noop + + assert(NH.getNode() != this && + "Cannot merge two portions of the same node yet!"); + + // If both nodes are not at offset 0, make sure that we are merging the node + // at an later offset into the node with the zero offset. + // + if (Offset > NH.getOffset()) { + N->mergeWith(DSNodeHandle(this, Offset), NH.getOffset()); + return; + } + +#if 0 + std::cerr << "\n\nMerging:\n"; + N->print(std::cerr, 0); + std::cerr << " and:\n"; + print(std::cerr, 0); +#endif + + // Now we know that Offset <= NH.Offset, so convert it so our "Offset" (with + // respect to NH.Offset) is now zero. + // + unsigned NOffset = NH.getOffset()-Offset; // Remove all edges pointing at N, causing them to point to 'this' instead. - while (!N->Referrers.empty()) - *N->Referrers.back() = this; + // Make sure to adjust their offset, not just the node pointer. + // + while (!N->Referrers.empty()) { + DSNodeHandle &Ref = *N->Referrers.back(); + Ref = DSNodeHandle(this, NOffset+Ref.getOffset()); + } // Make all of the outgoing links of N now be outgoing links of this. This // can cause recursive merging! // - for (unsigned i = 0, e = Links.size(); i != e; ++i) { - addEdgeTo(i, N->Links[i]); - N->Links[i] = 0; // Reduce unneccesary edges in graph. N is dead - } + for (unsigned i = 0, e = N->LinkIndex.size(); i != e; ++i) + if (N->LinkIndex[i] != -1) { + addEdgeTo(i+NOffset, N->Links[N->LinkIndex[i]]); + N->LinkIndex[i] = -1; // Reduce unneccesary edges in graph. N is dead + } + + // Now that there are no outgoing edges, all of the Links are dead. + N->Links.clear(); // Merge the node types NodeType |= N->NodeType; N->NodeType = 0; // N is now a dead node. - // Merge the globals list... - if (!N->Globals.empty()) { - // Save the current globals off to the side... - vector OldGlobals(Globals); + // If this merging into node has more than just void nodes in it, merge! + assert(!N->TypeEntries.empty() && "TypeEntries is empty for a node?"); + if (N->TypeEntries.size() != 1 || N->TypeEntries[0].first != Type::VoidTy) { + // If the current node just has a Void entry in it, remove it. + if (TypeEntries.size() == 1 && TypeEntries[0].first == Type::VoidTy) + TypeEntries.clear(); + + // Adjust all of the type entries we are merging in by the offset... and add + // them to the TypeEntries list. + // + if (NOffset != 0) { // This case is common enough to optimize for + // Offset all of the TypeEntries in N with their new offset + for (unsigned i = 0, e = N->TypeEntries.size(); i != e; ++i) + N->TypeEntries[i].second += NOffset; + } - // Resize the globals vector to be big enough to hold both of them... - Globals.resize(Globals.size()+N->Globals.size()); + MergeSortedVectors(TypeEntries, N->TypeEntries); - // Merge the two sorted globals lists together... - std::merge(OldGlobals.begin(), OldGlobals.end(), - N->Globals.begin(), N->Globals.end(), Globals.begin()); + N->TypeEntries.clear(); + } - // Erase duplicate entries from the globals list... - Globals.erase(std::unique(Globals.begin(), Globals.end()), Globals.end()); + // Merge the globals list... + if (!N->Globals.empty()) { + MergeSortedVectors(Globals, N->Globals); // Delete the globals from the old node... N->Globals.clear(); @@ -125,16 +229,13 @@ // DSGraph Implementation //===----------------------------------------------------------------------===// -DSGraph::DSGraph(const DSGraph &G) : Func(G.Func), GlobalsGraph(G.GlobalsGraph){ - GlobalsGraph->addReference(this); - std::map NodeMap; // ignored +DSGraph::DSGraph(const DSGraph &G) : Func(G.Func) { + std::map NodeMap; RetNode = cloneInto(G, ValueMap, NodeMap); } DSGraph::~DSGraph() { - GlobalsGraph->removeReference(this); FunctionCalls.clear(); - OrigFunctionCalls.clear(); ValueMap.clear(); RetNode = 0; @@ -151,24 +252,31 @@ // dump - Allow inspection of graph in a debugger. void DSGraph::dump() const { print(std::cerr); } - // Helper function used to clone a function list. -// Each call really shd have an explicit representation as a separate class. -void -CopyFunctionCallsList(const std::vector >& fromCalls, - std::vector >& toCalls, - std::map& NodeMap) { - +// +static void CopyFunctionCallsList(const vector >&fromCalls, + vector > &toCalls, + std::map &NodeMap) { + unsigned FC = toCalls.size(); // FirstCall toCalls.reserve(FC+fromCalls.size()); for (unsigned i = 0, ei = fromCalls.size(); i != ei; ++i) { - toCalls.push_back(std::vector()); - toCalls[FC+i].reserve(fromCalls[i].size()); + toCalls.push_back(vector()); + + const vector &CurCall = fromCalls[i]; + toCalls.back().reserve(CurCall.size()); for (unsigned j = 0, ej = fromCalls[i].size(); j != ej; ++j) - toCalls[FC+i].push_back(NodeMap[fromCalls[i][j]]); + toCalls[FC+i].push_back(DSNodeHandle(NodeMap[CurCall[j].getNode()], + CurCall[j].getOffset())); } } +/// remapLinks - Change all of the Links in the current node according to the +/// specified mapping. +void DSNode::remapLinks(std::map &OldNodeMap) { + for (unsigned i = 0, e = Links.size(); i != e; ++i) + Links[i].setNode(OldNodeMap[Links[i].getNode()]); +} // cloneInto - Clone the specified DSGraph into the current graph, returning the // Return node of the graph. The translated ValueMap for the old function is @@ -176,62 +284,61 @@ // Alloca markers are removed from the graph, as the graph is being cloned into // a calling function's graph. // -DSNode *DSGraph::cloneInto(const DSGraph &G, - std::map &OldValMap, - std::map &OldNodeMap, - bool StripScalars, bool StripAllocas, - bool CopyCallers, bool CopyOrigCalls) { - - assert(OldNodeMap.size()==0 && "Return arg. OldNodeMap shd be empty"); - - OldNodeMap[0] = 0; // Null pointer maps to null +DSNodeHandle DSGraph::cloneInto(const DSGraph &G, + std::map &OldValMap, + std::map &OldNodeMap, + bool StripScalars, bool StripAllocas, + bool CopyCallers, bool CopyOrigCalls) { + assert(OldNodeMap.empty() && "Returned OldNodeMap should be empty!"); unsigned FN = Nodes.size(); // First new node... // Duplicate all of the nodes, populating the node map... Nodes.reserve(FN+G.Nodes.size()); for (unsigned i = 0, e = G.Nodes.size(); i != e; ++i) { - DSNode *Old = G.Nodes[i], *New = new DSNode(*Old); + DSNode *Old = G.Nodes[i]; + DSNode *New = new DSNode(*Old); Nodes.push_back(New); OldNodeMap[Old] = New; } // Rewrite the links in the new nodes to point into the current graph now. for (unsigned i = FN, e = Nodes.size(); i != e; ++i) - for (unsigned j = 0, e = Nodes[i]->getNumLinks(); j != e; ++j) - Nodes[i]->setLink(j, OldNodeMap.find(Nodes[i]->getLink(j))->second); + Nodes[i]->remapLinks(OldNodeMap); // Remove local markers as specified - if (StripScalars || StripAllocas) { - char keepBits = ~((StripScalars? DSNode::ScalarNode : 0) | - (StripAllocas? DSNode::AllocaNode : 0)); + unsigned char StripBits = (StripScalars ? DSNode::ScalarNode : 0) | + (StripAllocas ? DSNode::AllocaNode : 0); + if (StripBits) for (unsigned i = FN, e = Nodes.size(); i != e; ++i) - Nodes[i]->NodeType &= keepBits; - } + Nodes[i]->NodeType &= ~StripBits; // Copy the value map... for (std::map::const_iterator I = G.ValueMap.begin(), E = G.ValueMap.end(); I != E; ++I) - OldValMap[I->first] = OldNodeMap[I->second]; - + OldValMap[I->first] = DSNodeHandle(OldNodeMap[I->second.getNode()], + I->second.getOffset()); // Copy the function calls list... CopyFunctionCallsList(G.FunctionCalls, FunctionCalls, OldNodeMap); + +#if 0 if (CopyOrigCalls) CopyFunctionCallsList(G.OrigFunctionCalls, OrigFunctionCalls, OldNodeMap); // Copy the list of unresolved callers if (CopyCallers) PendingCallers.insert(G.PendingCallers.begin(), G.PendingCallers.end()); +#endif // Return the returned node pointer... - return OldNodeMap[G.RetNode]; + return DSNodeHandle(OldNodeMap[G.RetNode.getNode()], G.RetNode.getOffset()); } - +#if 0 // cloneGlobalInto - Clone the given global node and all its target links // (and all their llinks, recursively). // -DSNode* DSGraph::cloneGlobalInto(const DSNode* GNode) { +DSNode *DSGraph::cloneGlobalInto(const DSNode *GNode) { if (GNode == 0 || GNode->getGlobals().size() == 0) return 0; // If a clone has already been created for GNode, return it. @@ -252,6 +359,7 @@ return NewNode; } +#endif // markIncompleteNodes - Mark the specified node as having contents that are not @@ -268,8 +376,9 @@ N->NodeType |= DSNode::Incomplete; // Recusively process children... - for (unsigned i = 0, e = N->getNumLinks(); i != e; ++i) - markIncompleteNode(N->getLink(i)); + for (unsigned i = 0, e = N->getSize(); i != e; ++i) + if (DSNodeHandle *DSNH = N->getLink(i)) + markIncompleteNode(DSNH->getNode()); } @@ -285,37 +394,41 @@ // void DSGraph::markIncompleteNodes(bool markFormalArgs) { // Mark any incoming arguments as incomplete... - if (markFormalArgs) - for (Function::aiterator I = Func.abegin(), E = Func.aend(); I != E; ++I) - if (isa(I->getType())) - markIncompleteNode(ValueMap[I]->getLink(0)); + if (markFormalArgs && Func) + for (Function::aiterator I = Func->abegin(), E = Func->aend(); I != E; ++I) + if (isPointerType(I->getType()) && ValueMap.find(I) != ValueMap.end()) { + DSNodeHandle &INH = ValueMap[I]; + if (INH.getNode() && INH.hasLink(0)) + markIncompleteNode(ValueMap[I].getLink(0)->getNode()); + } // Mark stuff passed into functions calls as being incomplete... for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i) { vector &Args = FunctionCalls[i]; // Then the return value is certainly incomplete! - markIncompleteNode(Args[0]); + markIncompleteNode(Args[0].getNode()); // The call does not make the function argument incomplete... // All arguments to the function call are incomplete though! for (unsigned i = 2, e = Args.size(); i != e; ++i) - markIncompleteNode(Args[i]); + markIncompleteNode(Args[i].getNode()); } // Mark all of the nodes pointed to by global or cast nodes as incomplete... for (unsigned i = 0, e = Nodes.size(); i != e; ++i) - if (Nodes[i]->NodeType & (DSNode::GlobalNode | DSNode::CastNode)) { + if (Nodes[i]->NodeType & DSNode::GlobalNode) { DSNode *N = Nodes[i]; - for (unsigned i = 0, e = N->getNumLinks(); i != e; ++i) - markIncompleteNode(N->getLink(i)); + for (unsigned i = 0, e = N->getSize(); i != e; ++i) + if (DSNodeHandle *DSNH = N->getLink(i)) + markIncompleteNode(DSNH->getNode()); } } // removeRefsToGlobal - Helper function that removes globals from the // ValueMap so that the referrer count will go down to zero. -static void -removeRefsToGlobal(DSNode* N, std::map& ValueMap) { +static void removeRefsToGlobal(DSNode* N, + std::map &ValueMap) { while (!N->getGlobals().empty()) { GlobalValue *GV = N->getGlobals().back(); N->getGlobals().pop_back(); @@ -336,7 +449,7 @@ // Is it a function node or some other trivially unused global? if (N->NodeType != 0 && (N->NodeType & ~DSNode::GlobalNode) == 0 && - N->getNumLinks() == 0 && + N->getSize() == 0 && N->getReferrers().size() == N->getGlobals().size()) { // Remove the globals from the valuemap, so that the referrer count will go @@ -349,7 +462,7 @@ return false; } -static void removeIdenticalCalls(std::vector > &Calls, +static void removeIdenticalCalls(vector > &Calls, const std::string &where) { // Remove trivially identical function calls unsigned NumFns = Calls.size(); @@ -375,38 +488,44 @@ Nodes.erase(Nodes.begin()+i--); // Remove from node list... } - removeIdenticalCalls(FunctionCalls, Func.getName()); + removeIdenticalCalls(FunctionCalls, Func ? Func->getName() : ""); } -// markAlive - Simple graph traverser that recursively walks the graph marking +// markAlive - Simple graph walker that recursively traverses the graph, marking // stuff to be alive. // static void markAlive(DSNode *N, std::set &Alive) { if (N == 0) return; Alive.insert(N); - for (unsigned i = 0, e = N->getNumLinks(); i != e; ++i) - if (N->getLink(i) && !Alive.count(N->getLink(i))) - markAlive(N->getLink(i), Alive); + for (unsigned i = 0, e = N->getSize(); i != e; ++i) + if (DSNodeHandle *DSNH = N->getLink(i)) + if (!Alive.count(DSNH->getNode())) + markAlive(DSNH->getNode(), Alive); } static bool checkGlobalAlive(DSNode *N, std::set &Alive, std::set &Visiting) { if (N == 0) return false; - if (Visiting.count(N) > 0) return false; // terminate recursion on a cycle + if (Visiting.count(N)) return false; // terminate recursion on a cycle Visiting.insert(N); // If any immediate successor is alive, N is alive - for (unsigned i = 0, e = N->getNumLinks(); i != e; ++i) - if (N->getLink(i) && Alive.count(N->getLink(i))) - { Visiting.erase(N); return true; } + for (unsigned i = 0, e = N->getSize(); i != e; ++i) + if (DSNodeHandle *DSNH = N->getLink(i)) + if (Alive.count(DSNH->getNode())) { + Visiting.erase(N); + return true; + } // Else if any successor reaches a live node, N is alive - for (unsigned i = 0, e = N->getNumLinks(); i != e; ++i) - if (N->getLink(i) && checkGlobalAlive(N->getLink(i), Alive, Visiting)) - { Visiting.erase(N); return true; } + for (unsigned i = 0, e = N->getSize(); i != e; ++i) + if (DSNodeHandle *DSNH = N->getLink(i)) + if (checkGlobalAlive(DSNH->getNode(), Alive, Visiting)) { + Visiting.erase(N); return true; + } Visiting.erase(N); return false; @@ -418,7 +537,7 @@ // the simple iterative loop in the first few lines below suffice. // static void markGlobalsIteration(std::set& GlobalNodes, - std::vector > &Calls, + vector > &Calls, std::set &Alive, bool FilterCalls) { @@ -444,16 +563,17 @@ for (int i = 0, ei = Calls.size(); i < ei; ++i) { bool CallIsDead = true, CallHasDeadArg = false; for (unsigned j = 0, ej = Calls[i].size(); j != ej; ++j) { - bool argIsDead = Calls[i][j] == 0 || Alive.count(Calls[i][j]) == 0; - CallHasDeadArg = CallHasDeadArg || (Calls[i][j] != 0 && argIsDead); - CallIsDead = CallIsDead && argIsDead; + bool argIsDead = Calls[i][j].getNode() == 0 || + Alive.count(Calls[i][j].getNode()) == 0; + CallHasDeadArg |= (Calls[i][j].getNode() != 0 && argIsDead); + CallIsDead &= argIsDead; } if (!CallIsDead && CallHasDeadArg) { // Some node in this call is live and another is dead. // Mark all nodes of call as live and iterate once more. recurse = true; for (unsigned j = 0, ej = Calls[i].size(); j != ej; ++j) - markAlive(Calls[i][j], Alive); + markAlive(Calls[i][j].getNode(), Alive); } } if (recurse) @@ -466,21 +586,21 @@ // can reach any other live node. Since this can produce new live nodes, // we use a simple iterative algorithm. // -static void markGlobalsAlive(DSGraph& G, std::set &Alive, +static void markGlobalsAlive(DSGraph &G, std::set &Alive, bool FilterCalls) { // Add global and cast nodes to a set so we don't walk all nodes every time std::set GlobalNodes; for (unsigned i = 0, e = G.getNodes().size(); i != e; ++i) - if (G.getNodes()[i]->NodeType & (DSNode::CastNode | DSNode::GlobalNode)) + if (G.getNodes()[i]->NodeType & DSNode::GlobalNode) GlobalNodes.insert(G.getNodes()[i]); // Add all call nodes to the same set - std::vector > &Calls = G.getFunctionCalls(); + vector > &Calls = G.getFunctionCalls(); if (FilterCalls) { for (unsigned i = 0, e = Calls.size(); i != e; ++i) for (unsigned j = 0, e = Calls[i].size(); j != e; ++j) - if (Calls[i][j]) - GlobalNodes.insert(Calls[i][j]); + if (Calls[i][j].getNode()) + GlobalNodes.insert(Calls[i][j].getNode()); } // Iterate and recurse until no new live node are discovered. @@ -497,8 +617,8 @@ if (FilterCalls) for (int ei = Calls.size(), i = ei-1; i >= 0; --i) { bool CallIsDead = true; - for (unsigned j = 0, ej= Calls[i].size(); CallIsDead && j != ej; ++j) - CallIsDead = (Alive.count(Calls[i][j]) == 0); + for (unsigned j = 0, ej = Calls[i].size(); CallIsDead && j != ej; ++j) + CallIsDead = Alive.count(Calls[i][j].getNode()) == 0; if (CallIsDead) Calls.erase(Calls.begin() + i); // remove the call entirely } @@ -526,21 +646,24 @@ if (KeepCalls) for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i) for (unsigned j = 0, e = FunctionCalls[i].size(); j != e; ++j) - markAlive(FunctionCalls[i][j], Alive); + markAlive(FunctionCalls[i][j].getNode(), Alive); +#if 0 for (unsigned i = 0, e = OrigFunctionCalls.size(); i != e; ++i) for (unsigned j = 0, e = OrigFunctionCalls[i].size(); j != e; ++j) - markAlive(OrigFunctionCalls[i][j], Alive); + markAlive(OrigFunctionCalls[i][j].getNode(), Alive); +#endif // Mark all nodes reachable by scalar nodes (and global nodes, if // keeping them was specified) as alive... - char keepBits = DSNode::ScalarNode | (KeepAllGlobals? DSNode::GlobalNode : 0); + unsigned char keepBits = DSNode::ScalarNode | + (KeepAllGlobals ? DSNode::GlobalNode : 0); for (unsigned i = 0, e = Nodes.size(); i != e; ++i) if (Nodes[i]->NodeType & keepBits) markAlive(Nodes[i], Alive); // The return value is alive as well... - markAlive(RetNode, Alive); + markAlive(RetNode.getNode(), Alive); // Mark all globals or cast nodes that can reach a live node as alive. // This also marks all nodes reachable from such nodes as alive. @@ -549,7 +672,7 @@ markGlobalsAlive(*this, Alive, ! KeepCalls); // Loop over all unreachable nodes, dropping their references... - std::vector DeadNodes; + vector DeadNodes; DeadNodes.reserve(Nodes.size()); // Only one allocation is allowed. for (unsigned i = 0; i != Nodes.size(); ++i) if (!Alive.count(Nodes[i])) { @@ -574,6 +697,7 @@ } +#if 0 //===----------------------------------------------------------------------===// // GlobalDSGraph Implementation //===----------------------------------------------------------------------===// @@ -601,10 +725,9 @@ } // Bits used in the next function -static const char ExternalTypeBits = (DSNode::GlobalNode | DSNode::NewNode | - DSNode::SubElement | DSNode::CastNode); - +static const char ExternalTypeBits = DSNode::GlobalNode | DSNode::NewNode; +#if 0 // GlobalDSGraph::cloneNodeInto - Clone a global node and all its externally // visible target links (and recursively their such links) into this graph. // NodeCache maps the node being cloned to its clone in the Globals graph, @@ -635,8 +758,8 @@ // If ValueCacheIsFinal==true, look for an existing node that has // an identical list of globals and return it if it exists. // - for (unsigned j = 0, N = OldNode->getGlobals().size(); j < N; ++j) - if (DSNode* PrevNode = ValueMap[OldNode->getGlobals()[j]]) { + for (unsigned j = 0, N = OldNode->getGlobals().size(); j != N; ++j) + if (DSNode *PrevNode = ValueMap[OldNode->getGlobals()[j]].getNode()) { if (NewNode == 0) { NewNode = PrevNode; // first existing node found if (GlobalsAreFinal && j == 0) @@ -695,14 +818,15 @@ // void GlobalDSGraph::cloneGlobals(DSGraph& Graph, bool CloneCalls) { std::map NodeCache; +#if 0 for (unsigned i = 0, N = Graph.Nodes.size(); i < N; ++i) if (Graph.Nodes[i]->NodeType & DSNode::GlobalNode) GlobalsGraph->cloneNodeInto(Graph.Nodes[i], NodeCache, false); - if (CloneCalls) GlobalsGraph->cloneCalls(Graph); GlobalsGraph->removeDeadNodes(/*KeepAllGlobals*/ true, /*KeepCalls*/ true); +#endif } @@ -711,12 +835,12 @@ // void GlobalDSGraph::cloneCalls(DSGraph& Graph) { std::map NodeCache; - std::vector >& FromCalls =Graph.FunctionCalls; + vector >& FromCalls =Graph.FunctionCalls; FunctionCalls.reserve(FunctionCalls.size() + FromCalls.size()); for (int i = 0, ei = FromCalls.size(); i < ei; ++i) { - FunctionCalls.push_back(std::vector()); + FunctionCalls.push_back(vector()); FunctionCalls.back().reserve(FromCalls[i].size()); for (unsigned j = 0, ej = FromCalls[i].size(); j != ej; ++j) FunctionCalls.back().push_back @@ -728,34 +852,6 @@ // remove trivially identical function calls removeIdenticalCalls(FunctionCalls, "Globals Graph"); } +#endif - -//===----------------------------------------------------------------------===// -// LocalDataStructures Implementation -//===----------------------------------------------------------------------===// - -// releaseMemory - If the pass pipeline is done with this pass, we can release -// our memory... here... -// -void LocalDataStructures::releaseMemory() { - for (std::map::iterator I = DSInfo.begin(), - E = DSInfo.end(); I != E; ++I) - delete I->second; - - // Empty map so next time memory is released, data structures are not - // re-deleted. - DSInfo.clear(); -} - -bool LocalDataStructures::run(Module &M) { - // Create a globals graph for the module. Deleted when all graphs go away. - GlobalDSGraph* GG = new GlobalDSGraph; - - // Calculate all of the graphs... - for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) - if (!I->isExternal()) - DSInfo.insert(std::make_pair(&*I, new DSGraph(*I, GG))); - - return false; -} - +#endif Index: llvm/lib/Analysis/DataStructure/Local.cpp diff -u llvm/lib/Analysis/DataStructure/Local.cpp:1.11 llvm/lib/Analysis/DataStructure/Local.cpp:1.12 --- llvm/lib/Analysis/DataStructure/Local.cpp:1.11 Thu Aug 22 18:36:35 2002 +++ llvm/lib/Analysis/DataStructure/Local.cpp Tue Oct 1 17:33:50 2002 @@ -1,4 +1,4 @@ -//===- ComputeLocal.cpp - Compute a local data structure graph for a fn ---===// +//===- Local.cpp - Compute a local data structure graph for a function ----===// // // Compute the local version of the data structure graph for a function. The // external interface to this file is the DSGraph constructor. @@ -6,30 +6,55 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/DataStructure.h" -#include "llvm/Function.h" #include "llvm/iMemory.h" #include "llvm/iTerminators.h" #include "llvm/iPHINode.h" #include "llvm/iOther.h" #include "llvm/Constants.h" -#include "llvm/GlobalVariable.h" #include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" #include "llvm/Support/InstVisitor.h" +#include "llvm/Target/TargetData.h" +#include "Support/Statistic.h" + +// FIXME: This should eventually be a FunctionPass that is automatically +// aggregated into a Pass. +// +#include "llvm/Module.h" + using std::map; using std::vector; static RegisterAnalysis X("datastructure", "Local Data Structure Analysis"); -//===----------------------------------------------------------------------===// -// GraphBuilder Class -//===----------------------------------------------------------------------===// -// -// This class is the builder class that constructs the local data structure -// graph by performing a single pass over the function in question. -// +using namespace DataStructureAnalysis; + +namespace DataStructureAnalysis { + // FIXME: Do something smarter with target data! + TargetData TD("temp-td"); + unsigned PointerSize(TD.getPointerSize()); + + // isPointerType - Return true if this type is big enough to hold a pointer. + bool isPointerType(const Type *Ty) { + if (isa(Ty)) + return true; + else if (Ty->isPrimitiveType() && Ty->isInteger()) + return Ty->getPrimitiveSize() >= PointerSize; + return false; + } +} + namespace { + //===--------------------------------------------------------------------===// + // GraphBuilder Class + //===--------------------------------------------------------------------===// + // + /// This class is the builder class that constructs the local data structure + /// graph by performing a single pass over the function in question. + /// class GraphBuilder : InstVisitor { DSGraph &G; vector &Nodes; @@ -46,8 +71,8 @@ // Create scalar nodes for all pointer arguments... for (Function::aiterator I = G.getFunction().abegin(), E = G.getFunction().aend(); I != E; ++I) - if (isa(I->getType())) - getValueNode(*I); + if (isPointerType(I->getType())) + getValueDest(*I); visit(G.getFunction()); // Single pass over the function @@ -71,51 +96,51 @@ void visitCallInst(CallInst &CI); void visitSetCondInst(SetCondInst &SCI) {} // SetEQ & friends are ignored void visitFreeInst(FreeInst &FI) {} // Ignore free instructions - void visitInstruction(Instruction &I); // Visit unsafe ptr instruction + void visitCastInst(CastInst &CI); + void visitInstruction(Instruction &I) {} private: // Helper functions used to implement the visitation functions... - // createNode - Create a new DSNode, ensuring that it is properly added to - // the graph. - // + /// createNode - Create a new DSNode, ensuring that it is properly added to + /// the graph. + /// DSNode *createNode(DSNode::NodeTy NodeType, const Type *Ty); - // getValueNode - Return a DSNode that corresponds the the specified LLVM - // value. This either returns the already existing node, or creates a new - // one and adds it to the graph, if none exists. - // - DSNode *getValueNode(Value &V); - - // getGlobalNode - Just like getValueNode, except the global node itself is - // returned, not a scalar node pointing to a global. - // - DSNode *getGlobalNode(GlobalValue &V); - - // getLink - This method is used to either return the specified link in the - // specified node if one exists. If a link does not already exist (it's - // null), then we create a new node, link it, then return it. - // - DSNode *getLink(DSNode *Node, unsigned Link); - - // getSubscriptedNode - Perform the basic getelementptr functionality that - // must be factored out of gep, load and store while they are all MAI's. - // - DSNode *getSubscriptedNode(GetElementPtrInst &GEP, DSNode *Ptr); + /// getValueNode - Return a DSNode that corresponds the the specified LLVM + /// value. This either returns the already existing node, or creates a new + /// one and adds it to the graph, if none exists. + /// + DSNodeHandle getValueNode(Value &V); + + /// getValueDest - Return the DSNode that the actual value points to. This + /// is basically the same thing as: getLink(getValueNode(V), 0) + /// + DSNodeHandle &getValueDest(Value &V); + + /// getGlobalNode - Just like getValueNode, except the global node itself is + /// returned, not a scalar node pointing to a global. + /// + DSNodeHandle &getGlobalNode(GlobalValue &V); + + /// getLink - This method is used to return the specified link in the + /// specified node if one exists. If a link does not already exist (it's + /// null), then we create a new node, link it, then return it. We must + /// specify the type of the Node field we are accessing so that we know what + /// type should be linked to if we need to create a new node. + /// + DSNodeHandle &getLink(const DSNodeHandle &Node, unsigned Link, + const Type *FieldTy); }; } //===----------------------------------------------------------------------===// // DSGraph constructor - Simply use the GraphBuilder to construct the local // graph. -DSGraph::DSGraph(Function &F, GlobalDSGraph* GlobalsG) - : Func(F), RetNode(0), GlobalsGraph(GlobalsG) { - if (GlobalsGraph != this) { - GlobalsGraph->addReference(this); - // Use the graph builder to construct the local version of the graph - GraphBuilder B(*this, Nodes, RetNode, ValueMap, FunctionCalls); - markIncompleteNodes(); - } +DSGraph::DSGraph(Function &F) : Func(&F) { + // Use the graph builder to construct the local version of the graph + GraphBuilder B(*this, Nodes, RetNode, ValueMap, FunctionCalls); + markIncompleteNodes(); } @@ -137,9 +162,9 @@ // getGlobalNode - Just like getValueNode, except the global node itself is // returned, not a scalar node pointing to a global. // -DSNode *GraphBuilder::getGlobalNode(GlobalValue &V) { +DSNodeHandle &GraphBuilder::getGlobalNode(GlobalValue &V) { DSNodeHandle &NH = ValueMap[&V]; - if (NH) return NH; // Already have a node? Just return it... + if (NH.getNode()) return NH; // Already have a node? Just return it... // Create a new global node for this global variable... DSNode *G = createNode(DSNode::GlobalNode, V.getType()->getElementType()); @@ -149,8 +174,8 @@ // each use. For functions and other global variables, this is unneccesary, // so avoid excessive merging by cloning these nodes on demand. // - NH = G; - return G; + NH.setNode(G); + return NH; } @@ -158,126 +183,145 @@ // This either returns the already existing node, or creates a new one and adds // it to the graph, if none exists. // -DSNode *GraphBuilder::getValueNode(Value &V) { - assert(isa(V.getType()) && "Should only use pointer scalars!"); - if (!isa(V)) { - DSNodeHandle &NH = ValueMap[&V]; - if (NH) return NH; // Already have a node? Just return it... - } +DSNodeHandle GraphBuilder::getValueNode(Value &V) { + assert(isPointerType(V.getType()) && "Should only use pointer scalars!"); + // Do not share the pointer value to globals... this would cause way too much + // false merging. + // + DSNodeHandle &NH = ValueMap[&V]; + if (!isa(V) && NH.getNode()) + return NH; // Already have a node? Just return it... // Otherwise we need to create a new scalar node... DSNode *N = createNode(DSNode::ScalarNode, V.getType()); // If this is a global value, create the global pointed to. if (GlobalValue *GV = dyn_cast(&V)) { - DSNode *G = getGlobalNode(*GV); - N->addEdgeTo(G); + N->addEdgeTo(0, getGlobalNode(*GV)); + return DSNodeHandle(N, 0); } else { - ValueMap[&V] = N; + NH.setOffset(0); + NH.setNode(N); } - return N; + return NH; } +/// getValueDest - Return the DSNode that the actual value points to. This +/// is basically the same thing as: getLink(getValueNode(V), 0) +/// +DSNodeHandle &GraphBuilder::getValueDest(Value &V) { + return getLink(getValueNode(V), 0, V.getType()); +} -// getLink - This method is used to either return the specified link in the -// specified node if one exists. If a link does not already exist (it's -// null), then we create a new node, link it, then return it. -// -DSNode *GraphBuilder::getLink(DSNode *Node, unsigned Link) { - assert(Link < Node->getNumLinks() && "Link accessed out of range!"); - if (Node->getLink(Link) == 0) { - DSNode::NodeTy NT; - const Type *Ty; - - switch (Node->getType()->getPrimitiveID()) { - case Type::PointerTyID: - Ty = cast(Node->getType())->getElementType(); - NT = DSNode::ShadowNode; - break; - case Type::ArrayTyID: - Ty = cast(Node->getType())->getElementType(); - NT = DSNode::SubElement; - break; - case Type::StructTyID: - Ty = cast(Node->getType())->getContainedType(Link); - NT = DSNode::SubElement; - break; - default: - assert(0 && "Unexpected type to dereference!"); - abort(); - } - DSNode *New = createNode(NT, Ty); - Node->addEdgeTo(Link, New); - } - return Node->getLink(Link); -} +/// getLink - This method is used to return the specified link in the +/// specified node if one exists. If a link does not already exist (it's +/// null), then we create a new node, link it, then return it. We must +/// specify the type of the Node field we are accessing so that we know what +/// type should be linked to if we need to create a new node. +/// +DSNodeHandle &GraphBuilder::getLink(const DSNodeHandle &node, + unsigned LinkNo, const Type *FieldTy) { + DSNodeHandle &Node = const_cast(node); -// getSubscriptedNode - Perform the basic getelementptr functionality that must -// be factored out of gep, load and store while they are all MAI's. -// -DSNode *GraphBuilder::getSubscriptedNode(GetElementPtrInst &GEP, DSNode *Ptr) { - for (unsigned i = 1, e = GEP.getNumOperands(); i != e; ++i) - if (GEP.getOperand(i)->getType() == Type::UIntTy) - Ptr = getLink(Ptr, 0); - else if (GEP.getOperand(i)->getType() == Type::UByteTy) - Ptr = getLink(Ptr, cast(GEP.getOperand(i))->getValue()); - - if (GEP.getNumOperands() == 1) - Ptr = getLink(Ptr, 0); // All GEP's have an implicit 0 if nothing else. + DSNodeHandle *Link = Node.getLink(LinkNo); + if (Link) return *Link; + + // If the link hasn't been created yet, make and return a new shadow node of + // the appropriate type for FieldTy... + // - return Ptr; + // If we are indexing with a typed pointer, then the thing we are pointing + // to is of the pointed type. If we are pointing to it with an integer + // (because of cast to an integer), we represent it with a void type. + // + const Type *ReqTy; + if (const PointerType *Ptr = dyn_cast(FieldTy)) + ReqTy = Ptr->getElementType(); + else + ReqTy = Type::VoidTy; + + DSNode *N = createNode(DSNode::ShadowNode, ReqTy); + Node.setLink(LinkNo, N); + return *Node.getLink(LinkNo); } + //===----------------------------------------------------------------------===// // Specific instruction type handler implementations... // -// Alloca & Malloc instruction implementation - Simply create a new memory -// object, pointing the scalar to it. -// +/// Alloca & Malloc instruction implementation - Simply create a new memory +/// object, pointing the scalar to it. +/// void GraphBuilder::handleAlloc(AllocationInst &AI, DSNode::NodeTy NodeType) { - DSNode *Scalar = getValueNode(AI); DSNode *New = createNode(NodeType, AI.getAllocatedType()); - Scalar->addEdgeTo(New); // Make the scalar point to the new node... + + // Make the scalar point to the new node... + getValueNode(AI).addEdgeTo(New); } // PHINode - Make the scalar for the PHI node point to all of the things the // incoming values point to... which effectively causes them to be merged. // void GraphBuilder::visitPHINode(PHINode &PN) { - if (!isa(PN.getType())) return; // Only pointer PHIs + if (!isPointerType(PN.getType())) return; // Only pointer PHIs - DSNode *Scalar = getValueNode(PN); - DSNode *ScalarDest = getLink(Scalar, 0); + DSNodeHandle &ScalarDest = getValueDest(PN); for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) - ScalarDest->mergeWith(getLink(getValueNode(*PN.getIncomingValue(i)), 0)); + if (!isa(PN.getIncomingValue(i))) + ScalarDest.mergeWith(getValueDest(*PN.getIncomingValue(i))); } void GraphBuilder::visitGetElementPtrInst(GetElementPtrInst &GEP) { - DSNode *Ptr = getSubscriptedNode(GEP, getValueNode(*GEP.getOperand(0))); - getValueNode(GEP)->addEdgeTo(Ptr); + DSNodeHandle Value = getValueDest(*GEP.getOperand(0)); + + unsigned Offset = 0; + const Type *CurTy = GEP.getOperand(0)->getType(); + + for (unsigned i = 1, e = GEP.getNumOperands(); i != e; ++i) + if (GEP.getOperand(i)->getType() == Type::LongTy) { + if (GEP.getOperand(i) != Constant::getNullValue(Type::LongTy)) { + std::cerr << "Array indexing not handled yet!\n"; + } + CurTy = cast(CurTy)->getElementType(); + } else if (GEP.getOperand(i)->getType() == Type::UByteTy) { + unsigned FieldNo = cast(GEP.getOperand(i))->getValue(); + const StructType *STy = cast(CurTy); + Offset += TD.getStructLayout(STy)->MemberOffsets[FieldNo]; + CurTy = STy->getContainedType(FieldNo); + } + + // Add in the offset calculated... + Value.setOffset(Value.getOffset()+Offset); + + // Value is now the pointer we want to GEP to be... + getValueNode(GEP).addEdgeTo(Value); } void GraphBuilder::visitLoadInst(LoadInst &LI) { - DSNode *Ptr = getValueNode(*LI.getOperand(0)); - if (!isa(LI.getType())) return; // only loads OF pointers - getValueNode(LI)->addEdgeTo(getLink(Ptr, 0)); + DSNodeHandle &Ptr = getValueDest(*LI.getOperand(0)); + if (isPointerType(LI.getType())) + getValueNode(LI).addEdgeTo(getLink(Ptr, 0, LI.getType())); } void GraphBuilder::visitStoreInst(StoreInst &SI) { - DSNode *DestPtr = getValueNode(*SI.getOperand(1)); - if (!isa(SI.getOperand(0)->getType())) return; - DSNode *Value = getValueNode(*SI.getOperand(0)); - DestPtr->addEdgeTo(getLink(Value, 0)); + DSNodeHandle &Dest = getValueDest(*SI.getOperand(1)); + + // Avoid adding edges from null, or processing non-"pointer" stores + if (isPointerType(SI.getOperand(0)->getType()) && + !isa(SI.getOperand(0))) { + Dest.addEdgeTo(getValueDest(*SI.getOperand(0))); + } } void GraphBuilder::visitReturnInst(ReturnInst &RI) { - if (RI.getNumOperands() && isa(RI.getOperand(0)->getType())) { - DSNode *Value = getLink(getValueNode(*RI.getOperand(0)), 0); - Value->mergeWith(RetNode); + if (RI.getNumOperands() && isPointerType(RI.getOperand(0)->getType()) && + !isa(RI.getOperand(0))) { + DSNodeHandle &Value = getValueDest(*RI.getOperand(0)); + Value.mergeWith(RetNode); RetNode = Value; } } @@ -288,13 +332,13 @@ vector &Args = FunctionCalls.back(); // Set up the return value... - if (isa(CI.getType())) - Args.push_back(getLink(getValueNode(CI), 0)); + if (isPointerType(CI.getType())) + Args.push_back(getLink(getValueNode(CI), 0, CI.getType())); else - Args.push_back(0); + Args.push_back(DSNodeHandle()); unsigned Start = 0; - // Special case for direct call, avoid creating spurious scalar node... + // Special case for a direct call, avoid creating spurious scalar node... if (GlobalValue *GV = dyn_cast(CI.getOperand(0))) { Args.push_back(getGlobalNode(*GV)); Start = 1; @@ -302,21 +346,43 @@ // Pass the arguments in... for (unsigned i = Start, e = CI.getNumOperands(); i != e; ++i) - if (isa(CI.getOperand(i)->getType())) - Args.push_back(getLink(getValueNode(*CI.getOperand(i)), 0)); + if (isPointerType(CI.getOperand(i)->getType())) + Args.push_back(getLink(getValueNode(*CI.getOperand(i)), 0, + CI.getOperand(i)->getType())); +} + +/// Handle casts... +void GraphBuilder::visitCastInst(CastInst &CI) { + if (isPointerType(CI.getType()) && isPointerType(CI.getOperand(0)->getType())) + getValueNode(CI).addEdgeTo(getLink(getValueNode(*CI.getOperand(0)), 0, + CI.getOperand(0)->getType())); } -// visitInstruction - All safe instructions have been processed above, this case -// is where unsafe ptr instructions land. + + + +//===----------------------------------------------------------------------===// +// LocalDataStructures Implementation +//===----------------------------------------------------------------------===// + +// releaseMemory - If the pass pipeline is done with this pass, we can release +// our memory... here... // -void GraphBuilder::visitInstruction(Instruction &I) { - // If the return type is a pointer, mark the pointed node as being a cast node - if (isa(I.getType())) - getLink(getValueNode(I), 0)->NodeType |= DSNode::CastNode; - - // If any operands are pointers, mark the pointed nodes as being a cast node - for (Instruction::op_iterator i = I.op_begin(), E = I.op_end(); i!=E; ++i) - if (isa(i->get()->getType())) - getLink(getValueNode(*i->get()), 0)->NodeType |= DSNode::CastNode; +void LocalDataStructures::releaseMemory() { + for (std::map::iterator I = DSInfo.begin(), + E = DSInfo.end(); I != E; ++I) + delete I->second; + + // Empty map so next time memory is released, data structures are not + // re-deleted. + DSInfo.clear(); +} + +bool LocalDataStructures::run(Module &M) { + // Calculate all of the graphs... + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) + if (!I->isExternal()) + DSInfo.insert(std::make_pair(I, new DSGraph(*I))); + return false; } Index: llvm/lib/Analysis/DataStructure/Printer.cpp diff -u llvm/lib/Analysis/DataStructure/Printer.cpp:1.7 llvm/lib/Analysis/DataStructure/Printer.cpp:1.8 --- llvm/lib/Analysis/DataStructure/Printer.cpp:1.7 Wed Jul 31 12:15:40 2002 +++ llvm/lib/Analysis/DataStructure/Printer.cpp Tue Oct 1 17:33:50 2002 @@ -14,35 +14,37 @@ void DSNode::dump() const { print(std::cerr, 0); } -string DSNode::getCaption(const DSGraph *G) const { +static string getCaption(const DSNode *N, const DSGraph *G) { std::stringstream OS; - Module *M = G && &G->getFunction()? G->getFunction().getParent() : 0; - WriteTypeSymbolic(OS, getType(), M); + Module *M = G && &G->getFunction() ? G->getFunction().getParent() : 0; - OS << " "; - if (NodeType & ScalarNode) OS << "S"; - if (NodeType & AllocaNode) OS << "A"; - if (NodeType & NewNode ) OS << "N"; - if (NodeType & GlobalNode) OS << "G"; - if (NodeType & SubElement) OS << "E"; - if (NodeType & CastNode ) OS << "C"; - if (NodeType & Incomplete) OS << "I"; + for (unsigned i = 0, e = N->getTypeEntries().size(); i != e; ++i) { + WriteTypeSymbolic(OS, N->getTypeEntries()[i].first, M); + if (N->getTypeEntries()[i].second) + OS << "@" << N->getTypeEntries()[i].second; + OS << "\n"; + } + + if (N->NodeType & DSNode::ScalarNode) OS << "S"; + if (N->NodeType & DSNode::AllocaNode) OS << "A"; + if (N->NodeType & DSNode::NewNode ) OS << "N"; + if (N->NodeType & DSNode::GlobalNode) OS << "G"; + if (N->NodeType & DSNode::Incomplete) OS << "I"; - for (unsigned i = 0, e = Globals.size(); i != e; ++i) { + for (unsigned i = 0, e = N->getGlobals().size(); i != e; ++i) { + WriteAsOperand(OS, N->getGlobals()[i], false, true, M); OS << "\n"; - WriteAsOperand(OS, Globals[i], false, true, M); } - if ((NodeType & ScalarNode) && G) { + if ((N->NodeType & DSNode::ScalarNode) && G) { const std::map &VM = G->getValueMap(); for (std::map::const_iterator I = VM.begin(), E = VM.end(); I != E; ++I) - if (I->second == this) { - OS << "\n"; + if (I->second.getNode() == N) { WriteAsOperand(OS, I->first, false, true, M); + OS << "\n"; } } - return OS.str(); } @@ -77,10 +79,12 @@ static void writeEdge(std::ostream &O, const void *SrcNode, const char *SrcNodePortName, int SrcNodeIdx, - const DSNode *VS, const std::string &EdgeAttr = "") { + const DSNodeHandle &VS, + const std::string &EdgeAttr = "") { O << "\tNode" << SrcNode << SrcNodePortName; if (SrcNodeIdx != -1) O << SrcNodeIdx; - O << " -> Node" << (void*)VS; + O << " -> Node" << (void*)VS.getNode(); + if (VS.getOffset()) O << ":g" << VS.getOffset(); if (!EdgeAttr.empty()) O << "[" << EdgeAttr << "]"; @@ -88,13 +92,13 @@ } void DSNode::print(std::ostream &O, const DSGraph *G) const { - std::string Caption = escapeLabel(getCaption(G)); + std::string Caption = escapeLabel(getCaption(this, G)); O << "\tNode" << (void*)this << " [ label =\"{" << Caption; - if (!Links.empty()) { + if (getSize() != 0) { O << "|{"; - for (unsigned i = 0; i < Links.size(); ++i) { + for (unsigned i = 0; i < getSize(); ++i) { if (i) O << "|"; O << ""; } @@ -102,9 +106,9 @@ } O << "}\"];\n"; - for (unsigned i = 0; i < Links.size(); ++i) - if (Links[i]) - writeEdge(O, this, ":g", i, Links[i]); + for (unsigned i = 0; i != getSize(); ++i) + if (const DSNodeHandle *DSN = getLink(i)) + writeEdge(O, this, ":g", i, *DSN); } void DSGraph::print(std::ostream &O) const { @@ -114,10 +118,8 @@ << "\tsize=\"10,7.5\";\n" << "\trotate=\"90\";\n"; - if (&Func != 0) - O << "\tlabel=\"Function\\ " << Func.getName() << "\";\n\n"; - else - O << "\tlabel=\"Global Graph\";\n\n"; + if (Func != 0) + O << "\tlabel=\"Function\\ " << Func->getName() << "\";\n\n"; // Output all of the nodes... for (unsigned i = 0, e = Nodes.size(); i != e; ++i) @@ -143,7 +145,7 @@ O << "}}\"];\n"; for (unsigned j = 0, e = Call.size(); j != e; ++j) - if (Call[j]) + if (Call[j].getNode()) writeEdge(O, &Call, ":g", j, Call[j], "color=gray63"); } @@ -152,16 +154,14 @@ } -static void printGraph(const DSGraph &Graph, std::ostream &O, - const string &GraphName, const string &Prefix) { - string Filename = Prefix + "." + GraphName + ".dot"; +void DSGraph::writeGraphToFile(std::ostream &O, const string &GraphName) { + string Filename = GraphName + ".dot"; O << "Writing '" << Filename << "'..."; std::ofstream F(Filename.c_str()); if (F.good()) { - Graph.print(F); - O << " [" << Graph.getGraphSize() << "+" - << Graph.getFunctionCalls().size() << "]\n"; + print(F); + O << " [" << getGraphSize() << "+" << getFunctionCalls().size() << "]\n"; } else { O << " error opening file for writing!\n"; } @@ -179,31 +179,33 @@ for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) if (!I->isExternal() && (I->getName() == "main" || !OnlyPrintMain)) - printGraph(C.getDSGraph((Function&)*I), O, I->getName(), Prefix); + C.getDSGraph((Function&)*I).writeGraphToFile(O, Prefix+I->getName()); } // print - Print out the analysis results... void LocalDataStructures::print(std::ostream &O, const Module *M) const { - printCollection(*this, O, M, "ds"); + printCollection(*this, O, M, "ds."); } +#if 0 void BUDataStructures::print(std::ostream &O, const Module *M) const { - printCollection(*this, O, M, "bu"); + printCollection(*this, O, M, "bu."); for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) if (!I->isExternal()) { - printGraph(*getDSGraph(*I).GlobalsGraph, O, "program", "gg"); + (*getDSGraph(*I).GlobalsGraph)->writeGraphToFile(O, "gg.program"); break; } } void TDDataStructures::print(std::ostream &O, const Module *M) const { - printCollection(*this, O, M, "td"); + printCollection(*this, O, M, "td."); for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) if (!I->isExternal()) { - printGraph(*getDSGraph(*I).GlobalsGraph, O, "program", "gg"); + (*getDSGraph(*I).GlobalsGraph)->writeGraphToFile(O, "gg.program"); break; } } +#endif Index: llvm/lib/Analysis/DataStructure/TopDownClosure.cpp diff -u llvm/lib/Analysis/DataStructure/TopDownClosure.cpp:1.4 llvm/lib/Analysis/DataStructure/TopDownClosure.cpp:1.5 --- llvm/lib/Analysis/DataStructure/TopDownClosure.cpp:1.4 Wed Aug 21 12:09:36 2002 +++ llvm/lib/Analysis/DataStructure/TopDownClosure.cpp Tue Oct 1 17:33:50 2002 @@ -10,9 +10,10 @@ #include "llvm/Analysis/DataStructure.h" #include "llvm/Module.h" #include "llvm/DerivedTypes.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" using std::map; +#if 0 static RegisterAnalysis Y("tddatastructure", "Top-down Data Structure Analysis Closure"); @@ -223,3 +224,4 @@ return *Graph; } +#endif From lattner at cs.uiuc.edu Tue Oct 1 17:35:04 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Oct 1 17:35:04 2002 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/DataStructure.h DataStructureGraph.h Message-ID: <200210012234.RAA18206@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: DataStructure.h updated: 1.40 -> 1.41 DataStructureGraph.h updated: 1.4 -> 1.5 --- Log message: Check in DataStructure rewrite so far. --- Diffs of the changes: Index: llvm/include/llvm/Analysis/DataStructure.h diff -u llvm/include/llvm/Analysis/DataStructure.h:1.40 llvm/include/llvm/Analysis/DataStructure.h:1.41 --- llvm/include/llvm/Analysis/DataStructure.h:1.40 Wed Aug 21 12:09:18 2002 +++ llvm/include/llvm/Analysis/DataStructure.h Tue Oct 1 17:34:45 2002 @@ -1,4 +1,4 @@ -//===- DataStructure.h - Build data structure graphs -------------*- C++ -*--=// +//===- DataStructure.h - Build data structure graphs ------------*- C++ -*-===// // // Implement the LLVM data structure analysis library. // @@ -7,350 +7,35 @@ #ifndef LLVM_ANALYSIS_DATA_STRUCTURE_H #define LLVM_ANALYSIS_DATA_STRUCTURE_H +#include "llvm/Analysis/DSGraph.h" #include "llvm/Pass.h" +#if 0 #include "llvm/GlobalValue.h" #include "Support/HashExtras.h" #include "Support/hash_set" +#endif #include -#include class Type; class GlobalValue; -class DSNode; // Each node in the graph -class DSGraph; // A graph for a function +#if 0 class GlobalDSGraph; // A common graph for globals in a program -class DSNodeIterator; // Data structure graph traversal iterator +#endif class LocalDataStructures; // A collection of local graphs for a program class BUDataStructures; // A collection of bu graphs for a program class TDDataStructures; // A collection of td graphs for a program -//===----------------------------------------------------------------------===// -// DSNodeHandle - Implement a "handle" to a data structure node that takes care -// of all of the add/un'refing of the node to prevent the backpointers in the -// graph from getting out of date. -// -class DSNodeHandle { - DSNode *N; -public: - // Allow construction, destruction, and assignment... - DSNodeHandle(DSNode *n = 0) : N(0) { operator=(n); } - DSNodeHandle(const DSNodeHandle &H) : N(0) { operator=(H.N); } - ~DSNodeHandle() { operator=(0); } - DSNodeHandle &operator=(const DSNodeHandle &H) {operator=(H.N); return *this;} - - // Assignment of DSNode*, implement all of the add/un'refing (defined later) - inline DSNodeHandle &operator=(DSNode *n); - - // Allow automatic, implicit, conversion to DSNode* - operator DSNode*() { return N; } - operator const DSNode*() const { return N; } - operator const DSNode*() { return N; } - operator bool() const { return N != 0; } - operator bool() { return N != 0; } - - bool operator<(const DSNodeHandle &H) const { // Allow sorting - return N < H.N; - } - bool operator==(const DSNodeHandle &H) const { return N == H.N; } - bool operator!=(const DSNodeHandle &H) const { return N != H.N; } - bool operator==(const DSNode *Node) const { return N == Node; } - bool operator!=(const DSNode *Node) const { return N != Node; } - bool operator==(DSNode *Node) const { return N == Node; } - bool operator!=(DSNode *Node) const { return N != Node; } - - // Avoid having comparisons to null cause errors... - bool operator==(int X) const { - assert(X == 0 && "Bad comparison!"); - return operator==((DSNode*)0); - } - bool operator!=(int X) const { return !operator==(X); } - - // Allow explicit conversion to DSNode... - DSNode *get() { return N; } - const DSNode *get() const { return N; } - - // Allow this to be treated like a pointer... - DSNode *operator->() { return N; } - const DSNode *operator->() const { return N; } -}; - - -//===----------------------------------------------------------------------===// -// DSNode - Data structure node class -// -// This class keeps track of a node's type, and the fields in the data -// structure. -// -// -class DSNode { - const Type *Ty; - std::vector Links; - std::vector Referrers; - - // Globals - The list of global values that are merged into this node. - std::vector Globals; - - void operator=(const DSNode &); // DO NOT IMPLEMENT -public: - enum NodeTy { - ShadowNode = 0, // Nothing is known about this node... - ScalarNode = 1 << 0, // Scalar of the current function contains this value - AllocaNode = 1 << 1, // This node was allocated with alloca - NewNode = 1 << 2, // This node was allocated with malloc - GlobalNode = 1 << 3, // This node was allocated by a global var decl - SubElement = 1 << 4, // This node is a part of some other node - CastNode = 1 << 5, // This node is accessed in unsafe ways - Incomplete = 1 << 6, // This node may not be complete - }; - - // NodeType - A union of the above bits. "Shadow" nodes do not add any flags - // to the nodes in the data structure graph, so it is possible to have nodes - // with a value of 0 for their NodeType. Scalar and Alloca markers go away - // when function graphs are inlined. - // - unsigned char NodeType; - - DSNode(enum NodeTy NT, const Type *T); - DSNode(const DSNode &); - - ~DSNode() { -#ifndef NDEBUG - dropAllReferences(); // Only needed to satisfy assertion checks... -#endif - assert(Referrers.empty() && "Referrers to dead node exist!"); - } - - // Iterator for graph interface... - typedef DSNodeIterator iterator; - inline iterator begin(); // Defined in DataStructureGraph.h - inline iterator end(); - - // Accessors - const Type *getType() const { return Ty; } - - unsigned getNumLinks() const { return Links.size(); } - DSNode *getLink(unsigned i) { - assert(i < getNumLinks() && "Field links access out of range..."); - return Links[i]; - } - const DSNode *getLink(unsigned i) const { - assert(i < getNumLinks() && "Field links access out of range..."); - return Links[i]; - } - - void setLink(unsigned i, DSNode *N) { - assert(i < getNumLinks() && "Field links access out of range..."); - Links[i] = N; - } - - // addGlobal - Add an entry for a global value to the Globals list. This also - // marks the node with the 'G' flag if it does not already have it. - // - void addGlobal(GlobalValue *GV); - const std::vector &getGlobals() const { return Globals; } - std::vector &getGlobals() { return Globals; } - - // addEdgeTo - Add an edge from the current node to the specified node. This - // can cause merging of nodes in the graph. - // - void addEdgeTo(unsigned LinkNo, DSNode *N); - void addEdgeTo(DSNode *N) { - assert(getNumLinks() == 1 && "Must specify a field number to add edge if " - " more than one field exists!"); - addEdgeTo(0, N); - } - // mergeWith - Merge this node into the specified node, moving all links to - // and from the argument node into the current node. The specified node may - // be a null pointer (in which case, nothing happens). +// FIXME: move this stuff to a private header +namespace DataStructureAnalysis { + // isPointerType - Return true if this first class type is big enough to hold + // a pointer. // - void mergeWith(DSNode *N); - - // addReferrer - Keep the referrer set up to date... - void addReferrer(DSNodeHandle *H) { Referrers.push_back(H); } - void removeReferrer(DSNodeHandle *H); - const std::vector &getReferrers() const { return Referrers; } - - void print(std::ostream &O, const DSGraph *G) const; - void dump() const; - - std::string getCaption(const DSGraph *G) const; - - void dropAllReferences() { - Links.clear(); - } -}; - - -inline DSNodeHandle &DSNodeHandle::operator=(DSNode *n) { - if (N) N->removeReferrer(this); - N = n; - if (N) N->addReferrer(this); - return *this; + bool isPointerType(const Type *Ty); } -// DSGraph - The graph that represents a function. -// -class DSGraph { - friend class GlobalDSGraph; -protected: - Function &Func; - std::vector Nodes; - DSNodeHandle RetNode; // Node that gets returned... - std::map ValueMap; - - // GlobalsGraph -- Reference to the common graph of globally visible objects. - // This includes GlobalValues, New nodes, Cast nodes, and Calls. - // - GlobalDSGraph* GlobalsGraph; - - // FunctionCalls - This vector maintains a single entry for each call - // instruction in the current graph. Each call entry contains DSNodeHandles - // that refer to the arguments that are passed into the function call. The - // first entry in the vector is the scalar that holds the return value for the - // call, the second is the function scalar being invoked, and the rest are - // pointer arguments to the function. - // - std::vector > FunctionCalls; - - // OrigFunctionCalls - This vector retains a copy of the original function - // calls of the current graph. This is needed to support top-down inlining - // after bottom-up inlining is complete, since the latter deletes call nodes. - // - std::vector > OrigFunctionCalls; - - // PendingCallers - This vector records all unresolved callers of the - // current function, i.e., ones whose graphs have not been inlined into - // the current graph. As long as there are unresolved callers, the nodes - // for formal arguments in the current graph cannot be eliminated, and - // nodes in the graph reachable from the formal argument nodes or - // global variable nodes must be considered incomplete. - std::set PendingCallers; - -protected: - // Define the interface only accessable to DataStructure - friend class LocalDataStructures; - friend class BUDataStructures; - friend class TDDataStructures; - DSGraph(Function &F, GlobalDSGraph* GlobalsG); // Compute the local DSGraph - DSGraph(const DSGraph &DSG); // Copy ctor - virtual ~DSGraph(); - - // clone all the call nodes and save the copies in OrigFunctionCalls - void saveOrigFunctionCalls() { - assert(OrigFunctionCalls.size() == 0 && "Do this only once!"); - OrigFunctionCalls = FunctionCalls; - } - - // get the saved copies of the original function call nodes - std::vector > &getOrigFunctionCalls() { - return OrigFunctionCalls; - } - - void operator=(const DSGraph &); // DO NOT IMPLEMENT -public: - - Function &getFunction() const { return Func; } - - // getNodes - Get a vector of all the nodes in the graph - // - const std::vector& getNodes() const { return Nodes; } - std::vector& getNodes() { return Nodes; } - - // getValueMap - Get a map that describes what the nodes the scalars in this - // function point to... - // - std::map &getValueMap() { return ValueMap; } - const std::map &getValueMap() const { return ValueMap;} - - std::vector > &getFunctionCalls() { - return FunctionCalls; - } - const std::vector > &getFunctionCalls() const { - return FunctionCalls; - } - - const DSNode *getRetNode() const { return RetNode; } - DSNode *getRetNode() { return RetNode; } - - unsigned getGraphSize() const { - return Nodes.size(); - } - - void print(std::ostream &O) const; - void dump() const; - - // maskNodeTypes - Apply a mask to all of the node types in the graph. This - // is useful for clearing out markers like Scalar or Incomplete. - // - void maskNodeTypes(unsigned char Mask); - void maskIncompleteMarkers() { maskNodeTypes(~DSNode::Incomplete); } - - // markIncompleteNodes - Traverse the graph, identifying nodes that may be - // modified by other functions that have not been resolved yet. This marks - // nodes that are reachable through three sources of "unknownness": - // Global Variables, Function Calls, and Incoming Arguments - // - // For any node that may have unknown components (because something outside - // the scope of current analysis may have modified it), the 'Incomplete' flag - // is added to the NodeType. - // - void markIncompleteNodes(bool markFormalArgs = true); - - // removeTriviallyDeadNodes - After the graph has been constructed, this - // method removes all unreachable nodes that are created because they got - // merged with other nodes in the graph. - // - void removeTriviallyDeadNodes(bool KeepAllGlobals = false); - - // removeDeadNodes - Use a more powerful reachability analysis to eliminate - // subgraphs that are unreachable. This often occurs because the data - // structure doesn't "escape" into it's caller, and thus should be eliminated - // from the caller's graph entirely. This is only appropriate to use when - // inlining graphs. - // - void removeDeadNodes(bool KeepAllGlobals = false, bool KeepCalls = true); - - // AddCaller - add a known caller node into the graph and mark it pending. - // getCallers - get a vector of the functions that call this one - // getCallersPending - get a matching vector of bools indicating if each - // caller's DSGraph has been resolved into this one. - // - void addCaller(Function& caller) { - PendingCallers.insert(&caller); - } - std::set& getPendingCallers() { - return PendingCallers; - } - - // cloneInto - Clone the specified DSGraph into the current graph, returning - // the Return node of the graph. The translated ValueMap for the old function - // is filled into the OldValMap member. - // If StripScalars (StripAllocas) is set to true, Scalar (Alloca) markers - // are removed from the graph as the graph is being cloned. - // If CopyCallers is set to true, the PendingCallers list is copied. - // If CopyOrigCalls is set to true, the OrigFunctionCalls list is copied. - // - DSNode *cloneInto(const DSGraph &G, std::map &OldValMap, - std::map& OldNodeMap, - bool StripScalars = false, bool StripAllocas = false, - bool CopyCallers = true, bool CopyOrigCalls = true); - - // cloneGlobalInto - Clone the given global node (or the node for the given - // GlobalValue) from the GlobalsGraph and all its target links (recursively). - // - DSNode* cloneGlobalInto(const DSNode* GNode); - DSNode* cloneGlobalInto(GlobalValue* GV) { - assert(!GV || (((DSGraph*) GlobalsGraph)->ValueMap[GV] != 0)); - return GV? cloneGlobalInto(((DSGraph*) GlobalsGraph)->ValueMap[GV]) : 0; - } - -private: - bool isNodeDead(DSNode *N); -}; - - +#if 0 // GlobalDSGraph - A common graph for all the globals and their outgoing links // to externally visible nodes. This includes GlobalValues, New nodes, // Cast nodes, and Calls. This graph can only be used by one of the @@ -376,7 +61,7 @@ void cloneGlobals(DSGraph& Graph, bool CloneCalls = false); void cloneCalls (DSGraph& Graph); }; - +#endif // LocalDataStructures - The analysis that computes the local data structure // graphs for all of the functions in the program. @@ -411,7 +96,7 @@ } }; - +#if 0 // BUDataStructures - The analysis that computes the interprocedurally closed // data structure graphs for all of the functions in the program. This pass // only performs a "Bottom Up" propogation (hence the name). @@ -483,4 +168,6 @@ std::map &OldValMap, std::map &OldNodeMap); }; +#endif + #endif Index: llvm/include/llvm/Analysis/DataStructureGraph.h diff -u llvm/include/llvm/Analysis/DataStructureGraph.h:1.4 llvm/include/llvm/Analysis/DataStructureGraph.h:1.5 --- llvm/include/llvm/Analysis/DataStructureGraph.h:1.4 Thu Jul 25 10:00:44 2002 +++ llvm/include/llvm/Analysis/DataStructureGraph.h Tue Oct 1 17:34:45 2002 @@ -13,6 +13,8 @@ #include "Support/GraphTraits.h" #include "Support/iterator" +#if 0 + class DSNodeIterator : public forward_iterator { friend class DSNode; DSNode * const Node; @@ -65,5 +67,7 @@ // Provide iterators for DSNode... inline DSNode::iterator DSNode::begin() { return DSNodeIterator(this); } inline DSNode::iterator DSNode::end() { return DSNodeIterator(this, false); } + +#endif #endif From lattner at cs.uiuc.edu Tue Oct 1 17:36:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Oct 1 17:36:01 2002 Subject: [llvm-commits] CVS: llvm/include/Support/Statistic.h StatisticReporter.h Message-ID: <200210012235.RAA18226@apoc.cs.uiuc.edu> Changes in directory llvm/include/Support: Statistic.h updated: 1.3 -> 1.4 StatisticReporter.h (r1.3) removed --- Log message: - Rework Statistics: * Renamed StatisticReporter.h/cpp to Statistic.h/cpp * Broke constructor to take two const char * arguments instead of one, so that indendation can be taken care of automatically. * Sort the list by pass name when printing * Make sure to print all statistics as a group, instead of randomly when the statistics dtors are called. --- Diffs of the changes: Index: llvm/include/Support/Statistic.h diff -u llvm/include/Support/Statistic.h:1.3 llvm/include/Support/Statistic.h:1.4 --- llvm/include/Support/Statistic.h:1.3 Tue Jun 25 15:14:19 2002 +++ llvm/include/Support/Statistic.h Tue Oct 1 17:35:42 2002 @@ -1,4 +1,4 @@ -//===-- Support/StatisticReporter.h - Easy way to expose stats ---*- C++ -*-==// +//===-- Support/Statistic.h - Easy way to expose stats ----------*- C++ -*-===// // // This file defines the 'Statistic' class, which is designed to be an easy way // to expose various success metrics from passes. These statistics are printed @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef SUPPORT_STATISTIC_REPORTER_H -#define SUPPORT_STATISTIC_REPORTER_H +#ifndef SUPPORT_STATISTIC_H +#define SUPPORT_STATISTIC_H #include @@ -43,8 +43,12 @@ // StatisticBase - Nontemplated base class for Statistic<> class... class StatisticBase { const char *Name; + const char *Desc; + static unsigned NumStats; protected: - StatisticBase(const char *name) : Name(name) {} + StatisticBase(const char *name, const char *desc) : Name(name), Desc(desc) { + ++NumStats; // Keep track of how many stats are created... + } virtual ~StatisticBase() {} // destroy - Called by subclass dtor so that we can still invoke virtual @@ -69,11 +73,12 @@ virtual bool hasSomeData() const { return Value != DataType(); } public: // Normal constructor, default initialize data item... - Statistic(const char *name) : StatisticBase(name), Value(DataType()) {} + Statistic(const char *name, const char *desc) + : StatisticBase(name, desc), Value(DataType()) {} // Constructor to provide an initial value... - Statistic(const DataType &Val, const char *name) - : StatisticBase(name), Value(Val) {} + Statistic(const DataType &Val, const char *name, const char *desc) + : StatisticBase(name, desc), Value(Val) {} // Print information when destroyed, iff command line option is specified ~Statistic() { destroy(); } From lattner at cs.uiuc.edu Tue Oct 1 17:36:03 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Oct 1 17:36:03 2002 Subject: [llvm-commits] CVS: llvm/lib/Support/Statistic.cpp StatisticReporter.cpp Message-ID: <200210012235.RAA18233@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Support: Statistic.cpp updated: 1.3 -> 1.4 StatisticReporter.cpp (r1.3) removed --- Log message: - Rework Statistics: * Renamed StatisticReporter.h/cpp to Statistic.h/cpp * Broke constructor to take two const char * arguments instead of one, so that indendation can be taken care of automatically. * Sort the list by pass name when printing * Make sure to print all statistics as a group, instead of randomly when the statistics dtors are called. --- Diffs of the changes: Index: llvm/lib/Support/Statistic.cpp diff -u llvm/lib/Support/Statistic.cpp:1.3 llvm/lib/Support/Statistic.cpp:1.4 --- llvm/lib/Support/Statistic.cpp:1.3 Sun Jul 21 21:09:03 2002 +++ llvm/lib/Support/Statistic.cpp Tue Oct 1 17:35:45 2002 @@ -1,4 +1,4 @@ -//===-- StatisticReporter.cpp - Easy way to expose stats information -------==// +//===-- Statistic.cpp - Easy way to expose stats information --------------===// // // This file implements the 'Statistic' class, which is designed to be an easy // way to expose various success metrics from passes. These statistics are @@ -14,12 +14,15 @@ // //===----------------------------------------------------------------------===// -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" #include "Support/CommandLine.h" #include +#include bool DebugFlag; // DebugFlag - Exported boolean set by the -debug option +unsigned StatisticBase::NumStats = 0; + // -stats - Command line option to cause transformations to emit stats about // what they did. // @@ -31,12 +34,62 @@ Debug("debug", cl::desc("Enable debug output"), cl::Hidden, cl::location(DebugFlag)); +struct StatRecord { + std::string Value; + const char *Name, *Desc; + + StatRecord(const std::string V, const char *N, const char *D) + : Value(V), Name(N), Desc(D) {} + + bool operator<(const StatRecord &SR) const { + return std::strcmp(Name, SR.Name) < 0; + } + + void print(unsigned ValFieldSize, unsigned NameFieldSize) { + std::cerr << std::string(ValFieldSize-Value.length(), ' ') + << Value << " " << Name + << std::string(NameFieldSize-std::strlen(Name), ' ') + << " - " << Desc << "\n"; + } +}; + +static std::vector *AccumStats = 0; + // Print information when destroyed, iff command line option is specified void StatisticBase::destroy() const { if (Enabled && hasSomeData()) { - std::cerr.width(7); - printValue(std::cerr); - std::cerr.width(0); - std::cerr << "\t" << Name << "\n"; + if (AccumStats == 0) + AccumStats = new std::vector(); + + std::ostringstream Out; + printValue(Out); + AccumStats->push_back(StatRecord(Out.str(), Name, Desc)); + } + + if (--NumStats == 0 && AccumStats) { + // Figure out how long the biggest Value and Name fields are... + unsigned MaxNameLen = 0, MaxValLen = 0; + for (unsigned i = 0, e = AccumStats->size(); i != e; ++i) { + MaxValLen = std::max(MaxValLen, (*AccumStats)[i].Value.length()); + MaxNameLen = std::max(MaxNameLen, std::strlen((*AccumStats)[i].Name)); + } + + // Sort the fields... + std::stable_sort(AccumStats->begin(), AccumStats->end()); + + // Print out the statistics header... + std::cerr << "===" << std::string(73, '-') << "===\n" + << " ... Statistics Collected ...\n" + << "===" << std::string(73, '-') << "===\n\n"; + + // Print all of the statistics accumulated... + for (unsigned i = 0, e = AccumStats->size(); i != e; ++i) + (*AccumStats)[i].print(MaxValLen, MaxNameLen); + + std::cerr << std::endl; // Flush the output stream... + + // Free all accumulated statistics... + delete AccumStats; + AccumStats = 0; } } From lattner at cs.uiuc.edu Tue Oct 1 17:37:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Oct 1 17:37:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Instrumentation/Makefile Message-ID: <200210012236.RAA18246@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Instrumentation: Makefile updated: 1.3 -> 1.4 --- Log message: Build subdirs in parallel --- Diffs of the changes: Index: llvm/lib/Transforms/Instrumentation/Makefile diff -u llvm/lib/Transforms/Instrumentation/Makefile:1.3 llvm/lib/Transforms/Instrumentation/Makefile:1.4 --- llvm/lib/Transforms/Instrumentation/Makefile:1.3 Tue Jul 23 12:52:36 2002 +++ llvm/lib/Transforms/Instrumentation/Makefile Tue Oct 1 17:36:35 2002 @@ -1,6 +1,6 @@ LEVEL = ../../.. LIBRARYNAME = instrument -DIRS = ProfilePaths +PARALLEL_DIRS = ProfilePaths BUILD_ARCHIVE = 1 include $(LEVEL)/Makefile.common From lattner at cs.uiuc.edu Tue Oct 1 17:39:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Oct 1 17:39:00 2002 Subject: [llvm-commits] CVS: llvm/lib/Bytecode/Writer/WriteInst.cpp Writer.cpp Message-ID: <200210012238.RAA18290@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Bytecode/Writer: WriteInst.cpp updated: 1.25 -> 1.26 Writer.cpp updated: 1.27 -> 1.28 --- Log message: Updates to work with recent Statistic's changes: * Renamed StatisticReporter.h/cpp to Statistic.h/cpp * Broke constructor to take two const char * arguments instead of one, so that indendation can be taken care of automatically. * Sort the list by pass name when printing * Make sure to print all statistics as a group, instead of randomly when the statistics dtors are called. * Updated ProgrammersManual with new semantics. --- Diffs of the changes: Index: llvm/lib/Bytecode/Writer/WriteInst.cpp diff -u llvm/lib/Bytecode/Writer/WriteInst.cpp:1.25 llvm/lib/Bytecode/Writer/WriteInst.cpp:1.26 --- llvm/lib/Bytecode/Writer/WriteInst.cpp:1.25 Fri Sep 13 21:18:57 2002 +++ llvm/lib/Bytecode/Writer/WriteInst.cpp Tue Oct 1 17:38:32 2002 @@ -14,13 +14,13 @@ #include "llvm/DerivedTypes.h" #include "llvm/iOther.h" #include "llvm/iTerminators.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" #include static Statistic<> -NumOversized("bytecodewriter\t- Number of oversized instructions"); +NumOversized("bytecodewriter", "Number of oversized instructions"); static Statistic<> -NumNormal("bytecodewriter\t- Number of normal instructions"); +NumNormal("bytecodewriter", "Number of normal instructions"); typedef unsigned char uchar; Index: llvm/lib/Bytecode/Writer/Writer.cpp diff -u llvm/lib/Bytecode/Writer/Writer.cpp:1.27 llvm/lib/Bytecode/Writer/Writer.cpp:1.28 --- llvm/lib/Bytecode/Writer/Writer.cpp:1.27 Fri Jul 26 13:40:10 2002 +++ llvm/lib/Bytecode/Writer/Writer.cpp Tue Oct 1 17:38:32 2002 @@ -25,14 +25,14 @@ #include "llvm/SymbolTable.h" #include "llvm/DerivedTypes.h" #include "Support/STLExtras.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" #include #include static RegisterPass X("emitbytecode", "Bytecode Writer"); static Statistic<> -BytesWritten("bytecodewriter\t- Number of bytecode bytes written"); +BytesWritten("bytecodewriter", "Number of bytecode bytes written"); BytecodeWriter::BytecodeWriter(std::deque &o, const Module *M) From lattner at cs.uiuc.edu Tue Oct 1 17:39:02 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Oct 1 17:39:02 2002 Subject: [llvm-commits] CVS: llvm/lib/Transforms/ExprTypeConvert.cpp FunctionInlining.cpp LevelRaise.cpp Message-ID: <200210012238.RAA18301@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms: ExprTypeConvert.cpp updated: 1.59 -> 1.60 FunctionInlining.cpp updated: 1.36 -> 1.37 LevelRaise.cpp updated: 1.71 -> 1.72 --- Log message: Updates to work with recent Statistic's changes: * Renamed StatisticReporter.h/cpp to Statistic.h/cpp * Broke constructor to take two const char * arguments instead of one, so that indendation can be taken care of automatically. * Sort the list by pass name when printing * Make sure to print all statistics as a group, instead of randomly when the statistics dtors are called. * Updated ProgrammersManual with new semantics. --- Diffs of the changes: Index: llvm/lib/Transforms/ExprTypeConvert.cpp diff -u llvm/lib/Transforms/ExprTypeConvert.cpp:1.59 llvm/lib/Transforms/ExprTypeConvert.cpp:1.60 --- llvm/lib/Transforms/ExprTypeConvert.cpp:1.59 Mon Sep 16 13:32:32 2002 +++ llvm/lib/Transforms/ExprTypeConvert.cpp Tue Oct 1 17:38:34 2002 @@ -13,7 +13,7 @@ #include "llvm/ConstantHandling.h" #include "llvm/Analysis/Expressions.h" #include "Support/STLExtras.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" #include using std::cerr; Index: llvm/lib/Transforms/FunctionInlining.cpp diff -u llvm/lib/Transforms/FunctionInlining.cpp:1.36 llvm/lib/Transforms/FunctionInlining.cpp:1.37 --- llvm/lib/Transforms/FunctionInlining.cpp:1.36 Sun Sep 22 13:41:25 2002 +++ llvm/lib/Transforms/FunctionInlining.cpp Tue Oct 1 17:38:34 2002 @@ -25,11 +25,10 @@ #include "llvm/iPHINode.h" #include "llvm/iOther.h" #include "llvm/Type.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" #include -#include -static Statistic<> NumInlined("inline\t\t- Number of functions inlined"); +static Statistic<> NumInlined("inline", "Number of functions inlined"); using std::cerr; // RemapInstruction - Convert the instruction operands from referencing the Index: llvm/lib/Transforms/LevelRaise.cpp diff -u llvm/lib/Transforms/LevelRaise.cpp:1.71 llvm/lib/Transforms/LevelRaise.cpp:1.72 --- llvm/lib/Transforms/LevelRaise.cpp:1.71 Tue Sep 17 19:42:45 2002 +++ llvm/lib/Transforms/LevelRaise.cpp Tue Oct 1 17:38:34 2002 @@ -17,7 +17,7 @@ #include "llvm/Analysis/Verifier.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "Support/STLExtras.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" #include "Support/CommandLine.h" #include using std::cerr; @@ -31,19 +31,19 @@ cl::desc("Start raise pass at the instruction with the specified name")); static Statistic<> -NumLoadStorePeepholes("raise\t\t- Number of load/store peepholes"); +NumLoadStorePeepholes("raise", "Number of load/store peepholes"); static Statistic<> -NumGEPInstFormed("raise\t\t- Number of other getelementptr's formed"); +NumGEPInstFormed("raise", "Number of other getelementptr's formed"); static Statistic<> -NumExprTreesConv("raise\t\t- Number of expression trees converted"); +NumExprTreesConv("raise", "Number of expression trees converted"); static Statistic<> -NumCastOfCast("raise\t\t- Number of cast-of-self removed"); +NumCastOfCast("raise", "Number of cast-of-self removed"); static Statistic<> -NumDCEorCP("raise\t\t- Number of insts DCEd or constprop'd"); +NumDCEorCP("raise", "Number of insts DCEd or constprop'd"); #define PRINT_PEEPHOLE(ID, NUM, I) \ From lattner at cs.uiuc.edu Tue Oct 1 17:39:03 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Oct 1 17:39:03 2002 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/ConstantMerge.cpp DeadTypeElimination.cpp FunctionResolution.cpp GlobalDCE.cpp Internalize.cpp MutateStructTypes.cpp Message-ID: <200210012238.RAA18318@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: ConstantMerge.cpp updated: 1.16 -> 1.17 DeadTypeElimination.cpp updated: 1.40 -> 1.41 FunctionResolution.cpp updated: 1.11 -> 1.12 GlobalDCE.cpp updated: 1.21 -> 1.22 Internalize.cpp updated: 1.9 -> 1.10 MutateStructTypes.cpp updated: 1.30 -> 1.31 --- Log message: Updates to work with recent Statistic's changes: * Renamed StatisticReporter.h/cpp to Statistic.h/cpp * Broke constructor to take two const char * arguments instead of one, so that indendation can be taken care of automatically. * Sort the list by pass name when printing * Make sure to print all statistics as a group, instead of randomly when the statistics dtors are called. * Updated ProgrammersManual with new semantics. --- Diffs of the changes: Index: llvm/lib/Transforms/IPO/ConstantMerge.cpp diff -u llvm/lib/Transforms/IPO/ConstantMerge.cpp:1.16 llvm/lib/Transforms/IPO/ConstantMerge.cpp:1.17 --- llvm/lib/Transforms/IPO/ConstantMerge.cpp:1.16 Mon Sep 23 18:00:46 2002 +++ llvm/lib/Transforms/IPO/ConstantMerge.cpp Tue Oct 1 17:38:35 2002 @@ -14,7 +14,7 @@ #include "llvm/Module.h" #include "llvm/Constants.h" #include "llvm/Pass.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" namespace { struct ConstantMerge : public Pass { @@ -28,7 +28,7 @@ void replaceConstantWith(Constant *Old, Constant *New); }; - Statistic<> NumMerged("constmerge\t\t- Number of global constants merged"); + Statistic<> NumMerged("constmerge", "Number of global constants merged"); RegisterOpt X("constmerge","Merge Duplicate Global Constants"); } Index: llvm/lib/Transforms/IPO/DeadTypeElimination.cpp diff -u llvm/lib/Transforms/IPO/DeadTypeElimination.cpp:1.40 llvm/lib/Transforms/IPO/DeadTypeElimination.cpp:1.41 --- llvm/lib/Transforms/IPO/DeadTypeElimination.cpp:1.40 Sun Sep 8 16:47:54 2002 +++ llvm/lib/Transforms/IPO/DeadTypeElimination.cpp Tue Oct 1 17:38:36 2002 @@ -10,7 +10,7 @@ #include "llvm/Module.h" #include "llvm/SymbolTable.h" #include "llvm/DerivedTypes.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" using std::vector; @@ -31,7 +31,8 @@ } }; RegisterOpt X("deadtypeelim", "Dead Type Elimination"); - Statistic<> NumKilled("deadtypeelim\t- Number of unused typenames removed from symtab"); + Statistic<> + NumKilled("deadtypeelim", "Number of unused typenames removed from symtab"); } Pass *createDeadTypeEliminationPass() { Index: llvm/lib/Transforms/IPO/FunctionResolution.cpp diff -u llvm/lib/Transforms/IPO/FunctionResolution.cpp:1.11 llvm/lib/Transforms/IPO/FunctionResolution.cpp:1.12 --- llvm/lib/Transforms/IPO/FunctionResolution.cpp:1.11 Tue Sep 10 12:02:57 2002 +++ llvm/lib/Transforms/IPO/FunctionResolution.cpp Tue Oct 1 17:38:36 2002 @@ -18,7 +18,7 @@ #include "llvm/Pass.h" #include "llvm/iOther.h" #include "llvm/Constant.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" #include using std::vector; @@ -26,7 +26,7 @@ using std::cerr; namespace { - Statistic<>NumResolved("funcresolve\t- Number of varargs functions resolved"); + Statistic<>NumResolved("funcresolve", "Number of varargs functions resolved"); struct FunctionResolvingPass : public Pass { bool run(Module &M); Index: llvm/lib/Transforms/IPO/GlobalDCE.cpp diff -u llvm/lib/Transforms/IPO/GlobalDCE.cpp:1.21 llvm/lib/Transforms/IPO/GlobalDCE.cpp:1.22 --- llvm/lib/Transforms/IPO/GlobalDCE.cpp:1.21 Sat Aug 17 20:28:30 2002 +++ llvm/lib/Transforms/IPO/GlobalDCE.cpp Tue Oct 1 17:38:36 2002 @@ -9,54 +9,53 @@ #include "llvm/Module.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" -#include "llvm/GlobalVariable.h" #include "llvm/Analysis/CallGraph.h" #include "Support/DepthFirstIterator.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" #include -static Statistic<> NumFunctions("globaldce\t- Number of functions removed"); -static Statistic<> NumVariables("globaldce\t- Number of global variables removed"); -static Statistic<> NumCPRs("globaldce\t- Number of const pointer refs removed"); -static Statistic<> NumConsts("globaldce\t- Number of init constants removed"); - -static bool RemoveUnreachableFunctions(Module &M, CallGraph &CallGraph) { - // Calculate which functions are reachable from the external functions in the - // call graph. - // - std::set ReachableNodes(df_begin(&CallGraph), - df_end(&CallGraph)); - - // Loop over the functions in the module twice. The first time is used to - // drop references that functions have to each other before they are deleted. - // The second pass removes the functions that need to be removed. - // - std::vector FunctionsToDelete; // Track unused functions - for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { - CallGraphNode *N = CallGraph[I]; - - if (!ReachableNodes.count(N)) { // Not reachable?? - I->dropAllReferences(); - N->removeAllCalledFunctions(); - FunctionsToDelete.push_back(N); - ++NumFunctions; +namespace { + Statistic<> NumFunctions("globaldce","Number of functions removed"); + Statistic<> NumVariables("globaldce","Number of global variables removed"); + Statistic<> NumCPRs("globaldce", "Number of const pointer refs removed"); + Statistic<> NumConsts("globaldce", "Number of init constants removed"); + + bool RemoveUnreachableFunctions(Module &M, CallGraph &CallGraph) { + // Calculate which functions are reachable from the external functions in + // the call graph. + // + std::set ReachableNodes(df_begin(&CallGraph), + df_end(&CallGraph)); + + // Loop over the functions in the module twice. The first time is used to + // drop references that functions have to each other before they are + // deleted. The second pass removes the functions that need to be removed. + // + std::vector FunctionsToDelete; // Track unused functions + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { + CallGraphNode *N = CallGraph[I]; + + if (!ReachableNodes.count(N)) { // Not reachable?? + I->dropAllReferences(); + N->removeAllCalledFunctions(); + FunctionsToDelete.push_back(N); + ++NumFunctions; + } } + + // Nothing to do if no unreachable functions have been found... + if (FunctionsToDelete.empty()) return false; + + // Unreachables functions have been found and should have no references to + // them, delete them now. + // + for (std::vector::iterator I = FunctionsToDelete.begin(), + E = FunctionsToDelete.end(); I != E; ++I) + delete CallGraph.removeFunctionFromModule(*I); + + return true; } - - // Nothing to do if no unreachable functions have been found... - if (FunctionsToDelete.empty()) return false; - - // Unreachables functions have been found and should have no references to - // them, delete them now. - // - for (std::vector::iterator I = FunctionsToDelete.begin(), - E = FunctionsToDelete.end(); I != E; ++I) - delete CallGraph.removeFunctionFromModule(*I); - - return true; -} - -namespace { + struct GlobalDCE : public Pass { // run - Do the GlobalDCE pass on the specified module, optionally updating // the specified callgraph to reflect the changes. Index: llvm/lib/Transforms/IPO/Internalize.cpp diff -u llvm/lib/Transforms/IPO/Internalize.cpp:1.9 llvm/lib/Transforms/IPO/Internalize.cpp:1.10 --- llvm/lib/Transforms/IPO/Internalize.cpp:1.9 Tue Jul 30 14:48:44 2002 +++ llvm/lib/Transforms/IPO/Internalize.cpp Tue Oct 1 17:38:36 2002 @@ -9,12 +9,11 @@ #include "llvm/Transforms/IPO.h" #include "llvm/Pass.h" #include "llvm/Module.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" namespace { - Statistic<> NumFunctions("internalize\t- Number of functions internalized"); - Statistic<> NumGlobals ("internalize\t- Number of global vars internalized"); - + Statistic<> NumFunctions("internalize", "Number of functions internalized"); + Statistic<> NumGlobals ("internalize", "Number of global vars internalized"); class InternalizePass : public Pass { virtual bool run(Module &M) { Index: llvm/lib/Transforms/IPO/MutateStructTypes.cpp diff -u llvm/lib/Transforms/IPO/MutateStructTypes.cpp:1.30 llvm/lib/Transforms/IPO/MutateStructTypes.cpp:1.31 --- llvm/lib/Transforms/IPO/MutateStructTypes.cpp:1.30 Fri Sep 13 21:06:53 2002 +++ llvm/lib/Transforms/IPO/MutateStructTypes.cpp Tue Oct 1 17:38:36 2002 @@ -19,12 +19,11 @@ #include "llvm/iMemory.h" #include "llvm/iTerminators.h" #include "llvm/iOther.h" -#include "llvm/Argument.h" #include "llvm/Constants.h" #include "Support/STLExtras.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" #include -#include + using std::map; using std::vector; From lattner at cs.uiuc.edu Tue Oct 1 17:39:05 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Oct 1 17:39:05 2002 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Instrumentation/ProfilePaths/Graph.cpp GraphAuxillary.cpp Message-ID: <200210012238.RAA18327@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Instrumentation/ProfilePaths: Graph.cpp updated: 1.6 -> 1.7 GraphAuxillary.cpp updated: 1.12 -> 1.13 --- Log message: Updates to work with recent Statistic's changes: * Renamed StatisticReporter.h/cpp to Statistic.h/cpp * Broke constructor to take two const char * arguments instead of one, so that indendation can be taken care of automatically. * Sort the list by pass name when printing * Make sure to print all statistics as a group, instead of randomly when the statistics dtors are called. * Updated ProgrammersManual with new semantics. --- Diffs of the changes: Index: llvm/lib/Transforms/Instrumentation/ProfilePaths/Graph.cpp diff -u llvm/lib/Transforms/Instrumentation/ProfilePaths/Graph.cpp:1.6 llvm/lib/Transforms/Instrumentation/ProfilePaths/Graph.cpp:1.7 --- llvm/lib/Transforms/Instrumentation/ProfilePaths/Graph.cpp:1.6 Mon Sep 16 00:25:42 2002 +++ llvm/lib/Transforms/Instrumentation/ProfilePaths/Graph.cpp Tue Oct 1 17:38:37 2002 @@ -8,8 +8,8 @@ #include "llvm/Transforms/Instrumentation/Graph.h" #include "llvm/iTerminators.h" #include "llvm/BasicBlock.h" +#include "Support/Statistic.h" #include -#include //using std::list; //using std::set; Index: llvm/lib/Transforms/Instrumentation/ProfilePaths/GraphAuxillary.cpp diff -u llvm/lib/Transforms/Instrumentation/ProfilePaths/GraphAuxillary.cpp:1.12 llvm/lib/Transforms/Instrumentation/ProfilePaths/GraphAuxillary.cpp:1.13 --- llvm/lib/Transforms/Instrumentation/ProfilePaths/GraphAuxillary.cpp:1.12 Fri Sep 20 11:43:52 2002 +++ llvm/lib/Transforms/Instrumentation/ProfilePaths/GraphAuxillary.cpp Tue Oct 1 17:38:37 2002 @@ -10,12 +10,9 @@ #include "llvm/Transforms/Instrumentation/Graph.h" #include "llvm/Pass.h" #include "llvm/Module.h" -#include "llvm/InstrTypes.h" #include "llvm/iTerminators.h" +#include "Support/Statistic.h" #include -#include -#include -#include //using std::list; using std::map; From lattner at cs.uiuc.edu Tue Oct 1 17:39:06 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Oct 1 17:39:06 2002 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/ADCE.cpp BreakCriticalEdges.cpp ConstantProp.cpp CorrelatedExprs.cpp DCE.cpp DecomposeMultiDimRefs.cpp GCSE.cpp IndVarSimplify.cpp InstructionCombining.cpp LICM.cpp LoopPreheaders.cpp LowerAllocations.cpp PiNodeInsertion.cpp PromoteMemoryToRegister.cpp RaiseAllocations.cpp Reassociate.cpp SCCP.cpp SimplifyCFG.cpp Message-ID: <200210012238.RAA18368@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: ADCE.cpp updated: 1.47 -> 1.48 BreakCriticalEdges.cpp updated: 1.4 -> 1.5 ConstantProp.cpp updated: 1.38 -> 1.39 CorrelatedExprs.cpp updated: 1.4 -> 1.5 DCE.cpp updated: 1.46 -> 1.47 DecomposeMultiDimRefs.cpp updated: 1.25 -> 1.26 GCSE.cpp updated: 1.23 -> 1.24 IndVarSimplify.cpp updated: 1.30 -> 1.31 InstructionCombining.cpp updated: 1.58 -> 1.59 LICM.cpp updated: 1.18 -> 1.19 LoopPreheaders.cpp updated: 1.3 -> 1.4 LowerAllocations.cpp updated: 1.32 -> 1.33 PiNodeInsertion.cpp updated: 1.7 -> 1.8 PromoteMemoryToRegister.cpp updated: 1.31 -> 1.32 RaiseAllocations.cpp updated: 1.13 -> 1.14 Reassociate.cpp updated: 1.10 -> 1.11 SCCP.cpp updated: 1.60 -> 1.61 SimplifyCFG.cpp updated: 1.5 -> 1.6 --- Log message: Updates to work with recent Statistic's changes: * Renamed StatisticReporter.h/cpp to Statistic.h/cpp * Broke constructor to take two const char * arguments instead of one, so that indendation can be taken care of automatically. * Sort the list by pass name when printing * Make sure to print all statistics as a group, instead of randomly when the statistics dtors are called. * Updated ProgrammersManual with new semantics. --- Diffs of the changes: Index: llvm/lib/Transforms/Scalar/ADCE.cpp diff -u llvm/lib/Transforms/Scalar/ADCE.cpp:1.47 llvm/lib/Transforms/Scalar/ADCE.cpp:1.48 --- llvm/lib/Transforms/Scalar/ADCE.cpp:1.47 Tue Sep 10 18:46:10 2002 +++ llvm/lib/Transforms/Scalar/ADCE.cpp Tue Oct 1 17:38:40 2002 @@ -17,16 +17,14 @@ #include "llvm/Support/CFG.h" #include "Support/STLExtras.h" #include "Support/DepthFirstIterator.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" #include -#include using std::cerr; using std::vector; -static Statistic<> NumBlockRemoved("adce\t\t- Number of basic blocks removed"); -static Statistic<> NumInstRemoved ("adce\t\t- Number of instructions removed"); - namespace { + Statistic<> NumBlockRemoved("adce", "Number of basic blocks removed"); + Statistic<> NumInstRemoved ("adce", "Number of instructions removed"); //===----------------------------------------------------------------------===// // ADCE Class Index: llvm/lib/Transforms/Scalar/BreakCriticalEdges.cpp diff -u llvm/lib/Transforms/Scalar/BreakCriticalEdges.cpp:1.4 llvm/lib/Transforms/Scalar/BreakCriticalEdges.cpp:1.5 --- llvm/lib/Transforms/Scalar/BreakCriticalEdges.cpp:1.4 Thu Sep 26 11:18:51 2002 +++ llvm/lib/Transforms/Scalar/BreakCriticalEdges.cpp Tue Oct 1 17:38:40 2002 @@ -14,10 +14,10 @@ #include "llvm/iTerminators.h" #include "llvm/iPHINode.h" #include "llvm/Support/CFG.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" namespace { - Statistic<> NumBroken("break-crit-edges\t- Number of blocks inserted"); + Statistic<> NumBroken("break-crit-edges", "Number of blocks inserted"); struct BreakCriticalEdges : public FunctionPass { virtual bool runOnFunction(Function &F); Index: llvm/lib/Transforms/Scalar/ConstantProp.cpp diff -u llvm/lib/Transforms/Scalar/ConstantProp.cpp:1.38 llvm/lib/Transforms/Scalar/ConstantProp.cpp:1.39 --- llvm/lib/Transforms/Scalar/ConstantProp.cpp:1.38 Fri Jul 26 16:12:40 2002 +++ llvm/lib/Transforms/Scalar/ConstantProp.cpp Tue Oct 1 17:38:40 2002 @@ -17,12 +17,12 @@ #include "llvm/Instruction.h" #include "llvm/Pass.h" #include "llvm/Support/InstIterator.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" #include -static Statistic<> NumInstKilled("constprop - Number of instructions killed"); - namespace { + Statistic<> NumInstKilled("constprop", "Number of instructions killed"); + struct ConstantPropogation : public FunctionPass { bool runOnFunction(Function &F); Index: llvm/lib/Transforms/Scalar/CorrelatedExprs.cpp diff -u llvm/lib/Transforms/Scalar/CorrelatedExprs.cpp:1.4 llvm/lib/Transforms/Scalar/CorrelatedExprs.cpp:1.5 --- llvm/lib/Transforms/Scalar/CorrelatedExprs.cpp:1.4 Tue Sep 24 10:43:56 2002 +++ llvm/lib/Transforms/Scalar/CorrelatedExprs.cpp Tue Oct 1 17:38:40 2002 @@ -32,13 +32,13 @@ #include "llvm/Support/ConstantRange.h" #include "llvm/Support/CFG.h" #include "Support/PostOrderIterator.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" #include namespace { - Statistic<>NumSetCCRemoved("cee\t\t- Number of setcc instruction eliminated"); - Statistic<>NumOperandsCann("cee\t\t- Number of operands cannonicalized"); - Statistic<>BranchRevectors("cee\t\t- Number of branches revectored"); + Statistic<> NumSetCCRemoved("cee", "Number of setcc instruction eliminated"); + Statistic<> NumOperandsCann("cee", "Number of operands cannonicalized"); + Statistic<> BranchRevectors("cee", "Number of branches revectored"); class ValueInfo; class Relation { Index: llvm/lib/Transforms/Scalar/DCE.cpp diff -u llvm/lib/Transforms/Scalar/DCE.cpp:1.46 llvm/lib/Transforms/Scalar/DCE.cpp:1.47 --- llvm/lib/Transforms/Scalar/DCE.cpp:1.46 Fri Jul 26 16:12:40 2002 +++ llvm/lib/Transforms/Scalar/DCE.cpp Tue Oct 1 17:38:40 2002 @@ -14,17 +14,17 @@ #include "llvm/Instruction.h" #include "llvm/Pass.h" #include "llvm/Support/InstIterator.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" #include -static Statistic<> DIEEliminated("die\t\t- Number of insts removed"); -static Statistic<> DCEEliminated("dce\t\t- Number of insts removed"); +namespace { + Statistic<> DIEEliminated("die", "Number of insts removed"); + Statistic<> DCEEliminated("dce", "Number of insts removed"); -//===----------------------------------------------------------------------===// -// DeadInstElimination pass implementation -// + //===--------------------------------------------------------------------===// + // DeadInstElimination pass implementation + // -namespace { struct DeadInstElimination : public BasicBlockPass { virtual bool runOnBasicBlock(BasicBlock &BB) { bool Changed = false; Index: llvm/lib/Transforms/Scalar/DecomposeMultiDimRefs.cpp diff -u llvm/lib/Transforms/Scalar/DecomposeMultiDimRefs.cpp:1.25 llvm/lib/Transforms/Scalar/DecomposeMultiDimRefs.cpp:1.26 --- llvm/lib/Transforms/Scalar/DecomposeMultiDimRefs.cpp:1.25 Mon Sep 16 11:40:07 2002 +++ llvm/lib/Transforms/Scalar/DecomposeMultiDimRefs.cpp Tue Oct 1 17:38:41 2002 @@ -16,10 +16,10 @@ #include "llvm/iOther.h" #include "llvm/BasicBlock.h" #include "llvm/Pass.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" namespace { - Statistic<> NumAdded("lowerrefs\t\t- # of getelementptr instructions added"); + Statistic<> NumAdded("lowerrefs", "# of getelementptr instructions added"); struct DecomposePass : public BasicBlockPass { virtual bool runOnBasicBlock(BasicBlock &BB); Index: llvm/lib/Transforms/Scalar/GCSE.cpp diff -u llvm/lib/Transforms/Scalar/GCSE.cpp:1.23 llvm/lib/Transforms/Scalar/GCSE.cpp:1.24 --- llvm/lib/Transforms/Scalar/GCSE.cpp:1.23 Fri Aug 30 17:53:30 2002 +++ llvm/lib/Transforms/Scalar/GCSE.cpp Tue Oct 1 17:38:41 2002 @@ -13,13 +13,13 @@ #include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/ValueNumbering.h" #include "llvm/Support/InstIterator.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" #include namespace { - Statistic<> NumInstRemoved("gcse\t\t- Number of instructions removed"); - Statistic<> NumLoadRemoved("gcse\t\t- Number of loads removed"); - Statistic<> NumNonInsts ("gcse\t\t- Number of instructions removed due " + Statistic<> NumInstRemoved("gcse", "Number of instructions removed"); + Statistic<> NumLoadRemoved("gcse", "Number of loads removed"); + Statistic<> NumNonInsts ("gcse", "Number of instructions removed due " "to non-instruction values"); class GCSE : public FunctionPass { Index: llvm/lib/Transforms/Scalar/IndVarSimplify.cpp diff -u llvm/lib/Transforms/Scalar/IndVarSimplify.cpp:1.30 llvm/lib/Transforms/Scalar/IndVarSimplify.cpp:1.31 --- llvm/lib/Transforms/Scalar/IndVarSimplify.cpp:1.30 Tue Sep 10 12:04:01 2002 +++ llvm/lib/Transforms/Scalar/IndVarSimplify.cpp Tue Oct 1 17:38:41 2002 @@ -14,11 +14,11 @@ #include "llvm/Constants.h" #include "llvm/Support/CFG.h" #include "Support/STLExtras.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" namespace { - Statistic<> NumRemoved ("indvars\t\t- Number of aux indvars removed"); - Statistic<> NumInserted("indvars\t\t- Number of cannonical indvars added"); + Statistic<> NumRemoved ("indvars", "Number of aux indvars removed"); + Statistic<> NumInserted("indvars", "Number of cannonical indvars added"); } // InsertCast - Cast Val to Ty, setting a useful name on the cast if Val has a Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.58 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.59 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.58 Mon Sep 23 18:39:43 2002 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Tue Oct 1 17:38:41 2002 @@ -25,14 +25,14 @@ #include "llvm/Pass.h" #include "llvm/Support/InstIterator.h" #include "llvm/Support/InstVisitor.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" #include -static Statistic<> NumCombined ("instcombine\t- Number of insts combined"); -static Statistic<> NumConstProp("instcombine\t- Number of constant folds"); -static Statistic<> NumDeadInst ("instcombine\t- Number of dead inst eliminate"); - namespace { + Statistic<> NumCombined ("instcombine", "Number of insts combined"); + Statistic<> NumConstProp("instcombine", "Number of constant folds"); + Statistic<> NumDeadInst ("instcombine", "Number of dead inst eliminated"); + class InstCombiner : public FunctionPass, public InstVisitor { // Worklist of all of the instructions that need to be simplified. Index: llvm/lib/Transforms/Scalar/LICM.cpp diff -u llvm/lib/Transforms/Scalar/LICM.cpp:1.18 llvm/lib/Transforms/Scalar/LICM.cpp:1.19 --- llvm/lib/Transforms/Scalar/LICM.cpp:1.18 Sun Sep 29 17:26:07 2002 +++ llvm/lib/Transforms/Scalar/LICM.cpp Tue Oct 1 17:38:41 2002 @@ -13,14 +13,14 @@ #include "llvm/iMemory.h" #include "llvm/Support/InstVisitor.h" #include "Support/STLExtras.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" #include "llvm/Assembly/Writer.h" #include using std::string; namespace { - Statistic<>NumHoisted("licm\t\t- Number of instructions hoisted out of loop"); - Statistic<> NumHoistedLoads("licm\t\t- Number of load insts hoisted"); + Statistic<> NumHoisted("licm", "Number of instructions hoisted out of loop"); + Statistic<> NumHoistedLoads("licm", "Number of load insts hoisted"); struct LICM : public FunctionPass, public InstVisitor { virtual bool runOnFunction(Function &F); Index: llvm/lib/Transforms/Scalar/LoopPreheaders.cpp diff -u llvm/lib/Transforms/Scalar/LoopPreheaders.cpp:1.3 llvm/lib/Transforms/Scalar/LoopPreheaders.cpp:1.4 --- llvm/lib/Transforms/Scalar/LoopPreheaders.cpp:1.3 Sun Sep 29 16:41:38 2002 +++ llvm/lib/Transforms/Scalar/LoopPreheaders.cpp Tue Oct 1 17:38:41 2002 @@ -13,10 +13,10 @@ #include "llvm/iPHINode.h" #include "llvm/Constant.h" #include "llvm/Support/CFG.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" namespace { - Statistic<> NumInserted("preheaders\t- Number of pre-header nodes inserted"); + Statistic<> NumInserted("preheaders", "Number of pre-header nodes inserted"); struct Preheaders : public FunctionPass { virtual bool runOnFunction(Function &F); Index: llvm/lib/Transforms/Scalar/LowerAllocations.cpp diff -u llvm/lib/Transforms/Scalar/LowerAllocations.cpp:1.32 llvm/lib/Transforms/Scalar/LowerAllocations.cpp:1.33 --- llvm/lib/Transforms/Scalar/LowerAllocations.cpp:1.32 Wed Sep 25 18:47:47 2002 +++ llvm/lib/Transforms/Scalar/LowerAllocations.cpp Tue Oct 1 17:38:41 2002 @@ -13,12 +13,12 @@ #include "llvm/Constants.h" #include "llvm/Pass.h" #include "llvm/Target/TargetData.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" -static Statistic<> NumLowered("lowerallocs\t- Number of allocations lowered"); using std::vector; namespace { + Statistic<> NumLowered("lowerallocs", "Number of allocations lowered"); /// LowerAllocations - Turn malloc and free instructions into %malloc and /// %free calls. Index: llvm/lib/Transforms/Scalar/PiNodeInsertion.cpp diff -u llvm/lib/Transforms/Scalar/PiNodeInsertion.cpp:1.7 llvm/lib/Transforms/Scalar/PiNodeInsertion.cpp:1.8 --- llvm/lib/Transforms/Scalar/PiNodeInsertion.cpp:1.7 Tue Sep 10 17:38:47 2002 +++ llvm/lib/Transforms/Scalar/PiNodeInsertion.cpp Tue Oct 1 17:38:41 2002 @@ -29,16 +29,15 @@ #include "llvm/Analysis/Dominators.h" #include "llvm/Pass.h" #include "llvm/Function.h" -#include "llvm/BasicBlock.h" #include "llvm/iTerminators.h" #include "llvm/iOperators.h" #include "llvm/iPHINode.h" #include "llvm/Support/CFG.h" -#include "Support/StatisticReporter.h" - -static Statistic<> NumInserted("pinodes\t\t- Number of Pi nodes inserted"); +#include "Support/Statistic.h" namespace { + Statistic<> NumInserted("pinodes", "Number of Pi nodes inserted"); + struct PiNodeInserter : public FunctionPass { virtual bool runOnFunction(Function &F); Index: llvm/lib/Transforms/Scalar/PromoteMemoryToRegister.cpp diff -u llvm/lib/Transforms/Scalar/PromoteMemoryToRegister.cpp:1.31 llvm/lib/Transforms/Scalar/PromoteMemoryToRegister.cpp:1.32 --- llvm/lib/Transforms/Scalar/PromoteMemoryToRegister.cpp:1.31 Tue Sep 24 16:19:41 2002 +++ llvm/lib/Transforms/Scalar/PromoteMemoryToRegister.cpp Tue Oct 1 17:38:41 2002 @@ -23,18 +23,17 @@ #include "llvm/iPHINode.h" #include "llvm/iTerminators.h" #include "llvm/Function.h" -#include "llvm/BasicBlock.h" #include "llvm/Constant.h" #include "llvm/Type.h" -#include "Support/StatisticReporter.h" - -static Statistic<> NumPromoted("mem2reg\t\t- Number of alloca's promoted"); +#include "Support/Statistic.h" using std::vector; using std::map; using std::set; namespace { + Statistic<> NumPromoted("mem2reg", "Number of alloca's promoted"); + struct PromotePass : public FunctionPass { vector Allocas; // the alloca instruction.. map AllocaLookup; // reverse mapping of above Index: llvm/lib/Transforms/Scalar/RaiseAllocations.cpp diff -u llvm/lib/Transforms/Scalar/RaiseAllocations.cpp:1.13 llvm/lib/Transforms/Scalar/RaiseAllocations.cpp:1.14 --- llvm/lib/Transforms/Scalar/RaiseAllocations.cpp:1.13 Fri Sep 13 22:04:02 2002 +++ llvm/lib/Transforms/Scalar/RaiseAllocations.cpp Tue Oct 1 17:38:41 2002 @@ -12,32 +12,31 @@ #include "llvm/iMemory.h" #include "llvm/iOther.h" #include "llvm/Pass.h" -#include "Support/StatisticReporter.h" - -static Statistic<> NumRaised("raiseallocs\t- Number of allocations raised"); +#include "Support/Statistic.h" namespace { + Statistic<> NumRaised("raiseallocs", "Number of allocations raised"); -// RaiseAllocations - Turn %malloc and %free calls into the appropriate -// instruction. -// -class RaiseAllocations : public BasicBlockPass { - Function *MallocFunc; // Functions in the module we are processing - Function *FreeFunc; // Initialized by doPassInitializationVirt -public: - RaiseAllocations() : MallocFunc(0), FreeFunc(0) {} - - // doPassInitialization - For the raise allocations pass, this finds a - // declaration for malloc and free if they exist. + // RaiseAllocations - Turn %malloc and %free calls into the appropriate + // instruction. // - bool doInitialization(Module &M); - - // runOnBasicBlock - This method does the actual work of converting - // instructions over, assuming that the pass has already been initialized. - // - bool runOnBasicBlock(BasicBlock &BB); -}; - + class RaiseAllocations : public BasicBlockPass { + Function *MallocFunc; // Functions in the module we are processing + Function *FreeFunc; // Initialized by doPassInitializationVirt + public: + RaiseAllocations() : MallocFunc(0), FreeFunc(0) {} + + // doPassInitialization - For the raise allocations pass, this finds a + // declaration for malloc and free if they exist. + // + bool doInitialization(Module &M); + + // runOnBasicBlock - This method does the actual work of converting + // instructions over, assuming that the pass has already been initialized. + // + bool runOnBasicBlock(BasicBlock &BB); + }; + RegisterOpt X("raiseallocs", "Raise allocations from calls to instructions"); } // end anonymous namespace Index: llvm/lib/Transforms/Scalar/Reassociate.cpp diff -u llvm/lib/Transforms/Scalar/Reassociate.cpp:1.10 llvm/lib/Transforms/Scalar/Reassociate.cpp:1.11 --- llvm/lib/Transforms/Scalar/Reassociate.cpp:1.10 Tue Sep 10 12:04:02 2002 +++ llvm/lib/Transforms/Scalar/Reassociate.cpp Tue Oct 1 17:38:41 2002 @@ -18,20 +18,19 @@ #include "llvm/Transforms/Scalar.h" #include "llvm/Function.h" -#include "llvm/BasicBlock.h" #include "llvm/iOperators.h" #include "llvm/Type.h" #include "llvm/Pass.h" #include "llvm/Constant.h" #include "llvm/Support/CFG.h" #include "Support/PostOrderIterator.h" -#include "Support/StatisticReporter.h" - -static Statistic<> NumLinear ("reassociate\t- Number of insts linearized"); -static Statistic<> NumChanged("reassociate\t- Number of insts reassociated"); -static Statistic<> NumSwapped("reassociate\t- Number of insts with operands swapped"); +#include "Support/Statistic.h" namespace { + Statistic<> NumLinear ("reassociate","Number of insts linearized"); + Statistic<> NumChanged("reassociate","Number of insts reassociated"); + Statistic<> NumSwapped("reassociate","Number of insts with operands swapped"); + class Reassociate : public FunctionPass { std::map RankMap; public: Index: llvm/lib/Transforms/Scalar/SCCP.cpp diff -u llvm/lib/Transforms/Scalar/SCCP.cpp:1.60 llvm/lib/Transforms/Scalar/SCCP.cpp:1.61 --- llvm/lib/Transforms/Scalar/SCCP.cpp:1.60 Fri Aug 30 18:39:00 2002 +++ llvm/lib/Transforms/Scalar/SCCP.cpp Tue Oct 1 17:38:41 2002 @@ -24,17 +24,17 @@ #include "llvm/Pass.h" #include "llvm/Support/InstVisitor.h" #include "Support/STLExtras.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" #include #include using std::cerr; -static Statistic<> NumInstRemoved("sccp\t\t- Number of instructions removed"); - // InstVal class - This class represents the different lattice values that an // instruction may occupy. It is a simple class with value semantics. // namespace { + Statistic<> NumInstRemoved("sccp", "Number of instructions removed"); + class InstVal { enum { undefined, // This instruction has no known value Index: llvm/lib/Transforms/Scalar/SimplifyCFG.cpp diff -u llvm/lib/Transforms/Scalar/SimplifyCFG.cpp:1.5 llvm/lib/Transforms/Scalar/SimplifyCFG.cpp:1.6 --- llvm/lib/Transforms/Scalar/SimplifyCFG.cpp:1.5 Tue Sep 24 16:18:40 2002 +++ llvm/lib/Transforms/Scalar/SimplifyCFG.cpp Tue Oct 1 17:38:41 2002 @@ -16,12 +16,12 @@ #include "llvm/Module.h" #include "llvm/Support/CFG.h" #include "llvm/Pass.h" -#include "Support/StatisticReporter.h" +#include "Support/Statistic.h" #include -static Statistic<> NumSimpl("cfgsimplify\t- Number of blocks simplified"); - namespace { + Statistic<> NumSimpl("cfgsimplify", "Number of blocks simplified"); + struct CFGSimplifyPass : public FunctionPass { virtual bool runOnFunction(Function &F); }; From lattner at cs.uiuc.edu Tue Oct 1 17:41:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Oct 1 17:41:01 2002 Subject: [llvm-commits] CVS: llvm/include/llvm/Transforms/Instrumentation/Graph.h Message-ID: <200210012240.RAA18421@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Transforms/Instrumentation: Graph.h updated: 1.4 -> 1.5 --- Log message: Changes to work with Statistics rework * Renamed StatisticReporter.h/cpp to Statistic.h/cpp * Broke constructor to take two const char * arguments instead of one, so that indendation can be taken care of automatically. * Sort the list by pass name when printing * Make sure to print all statistics as a group, instead of randomly when the statistics dtors are called. * Updated ProgrammersManual with new semantics. --- Diffs of the changes: Index: llvm/include/llvm/Transforms/Instrumentation/Graph.h diff -u llvm/include/llvm/Transforms/Instrumentation/Graph.h:1.4 llvm/include/llvm/Transforms/Instrumentation/Graph.h:1.5 --- llvm/include/llvm/Transforms/Instrumentation/Graph.h:1.4 Fri Sep 20 11:44:35 2002 +++ llvm/include/llvm/Transforms/Instrumentation/Graph.h Tue Oct 1 17:40:31 2002 @@ -9,18 +9,12 @@ #ifndef LLVM_GRAPH_H #define LLVM_GRAPH_H -#include "Support/StatisticReporter.h" - +#include "llvm/BasicBlock.h" #include -#include #include -#include "llvm/BasicBlock.h" - -class BasicBlock; class Module; class Function; -class Instruction; //Class Node //It forms the vertex for the graph From lattner at cs.uiuc.edu Tue Oct 1 17:42:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Oct 1 17:42:01 2002 Subject: [llvm-commits] CVS: llvm/tools/opt/Makefile Message-ID: <200210012241.RAA18434@apoc.cs.uiuc.edu> Changes in directory llvm/tools/opt: Makefile updated: 1.32 -> 1.33 --- Log message: Temporary change to make datastructure stuff link in right --- Diffs of the changes: Index: llvm/tools/opt/Makefile diff -u llvm/tools/opt/Makefile:1.32 llvm/tools/opt/Makefile:1.33 --- llvm/tools/opt/Makefile:1.32 Thu Sep 19 19:43:20 2002 +++ llvm/tools/opt/Makefile Tue Oct 1 17:41:01 2002 @@ -4,7 +4,7 @@ USEDLIBS = bcreader bcwriter instrument profpaths \ sparc target.a mapping regalloc.a sched select preopts postopts.a \ livevar scalaropts \ - ipo ipa.a datastructure.a transforms target.a analysis \ + ipo ipa.a datastructure transforms target.a analysis \ transformutils vmcore support TOOLLINKOPTS = -ldl $(ExportSymbols) From lattner at cs.uiuc.edu Tue Oct 1 18:04:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Oct 1 18:04:01 2002 Subject: [llvm-commits] CVS: llvm/www/docs/ProgrammersManual.html Message-ID: <200210012239.RAA05784@tank.cs.uiuc.edu> Changes in directory llvm/www/docs: ProgrammersManual.html updated: 1.32 -> 1.33 --- Log message: Update manual to reflect recent changes in the Statistic class. --- Diffs of the changes: Index: llvm/www/docs/ProgrammersManual.html diff -u llvm/www/docs/ProgrammersManual.html:1.32 llvm/www/docs/ProgrammersManual.html:1.33 --- llvm/www/docs/ProgrammersManual.html:1.32 Sun Sep 29 12:31:54 2002 +++ llvm/www/docs/ProgrammersManual.html Tue Oct 1 17:39:41 2002 @@ -319,7 +319,7 @@ them out, allowing you to enable them if you need them in the future.

The "StatisticReporter.h" +href="/doxygen/Statistic_8h-source.html">Support/Statistic.h" file provides a macro named DEBUG() that is a much nicer solution to this problem. Basically, you can put arbitrary code into the argument of the DEBUG macro, and it is only executed if 'opt' is run with the @@ -356,7 +356,7 @@

    The "StatisticReporter.h" +href="/doxygen/Statistic_8h-source.html">Support/Statistic.h" file provides a template named Statistic that is used as a unified way to keeping track of what the LLVM compiler is doing and how effective various optimizations are. It is useful to see what optimizations are contributing to @@ -376,7 +376,7 @@
  • Define your statistic like this:

    -static Statistic<> NumXForms("mypassname\t- The # of times I did stuff");
    +static Statistic<> NumXForms("mypassname", "The # of times I did stuff");
     

    The Statistic template can emulate just about any data-type, but if you @@ -1760,6 +1760,6 @@ Chris Lattner -Last modified: Sun Sep 29 12:31:23 CDT 2002 +Last modified: Tue Oct 1 15:35:42 CDT 2002 From brukman at cs.uiuc.edu Tue Oct 1 18:07:01 2002 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Tue Oct 1 18:07:01 2002 Subject: [llvm-commits] CVS: CVSROOT/commit-diffs.pl loginfo Message-ID: <200210012306.SAA25290@apoc.cs.uiuc.edu> Changes in directory CVSROOT: commit-diffs.pl updated: 1.30 -> 1.31 loginfo updated: 1.28 -> 1.29 --- Log message: Modified commit-diffs to not take a username (whoami) on the command line, and login no longer passes it in. It didn't work on Solaris anyway. Also, changed default admin on commit-diffs to llvm-commits so that any errors in loginfo will be sent to the list instead of to me. :) --- Diffs of the changes: Index: CVSROOT/commit-diffs.pl diff -u CVSROOT/commit-diffs.pl:1.30 CVSROOT/commit-diffs.pl:1.31 --- CVSROOT/commit-diffs.pl:1.30 Mon Sep 30 14:29:44 2002 +++ CVSROOT/commit-diffs.pl Tue Oct 1 18:06:18 2002 @@ -6,8 +6,7 @@ exit(0); } -$DEFAULT_ADMIN = 'brukman\@cs.uiuc.edu'; -$DEFAULT_USERNAME = 'brukman'; +$DEFAULT_ADMIN = 'llvm-commits\@cs.uiuc.edu'; $DEBUG = 0; $TEMPFILE = "/tmp/cvsmailtmp.$$"; @@ -62,8 +61,7 @@ } # Find out who did the changes and who shall we mail to. -my $user = $ARGV[1] || $DEFAULT_USERNAME; -my $target = $ARGV[2] || $DEFAULT_ADMIN; +my $target = $ARGV[1] || $DEFAULT_ADMIN; # Manipulate the CVS's change info; see docs for further information. my @changes = split(' ', $ARGV[0]); Index: CVSROOT/loginfo diff -u CVSROOT/loginfo:1.28 CVSROOT/loginfo:1.29 --- CVSROOT/loginfo:1.28 Sat Sep 7 00:40:56 2002 +++ CVSROOT/loginfo Tue Oct 1 18:06:18 2002 @@ -27,6 +27,6 @@ #^CVSROOT mailx -s 'CVSROOT commit %s' llvm-commits at cs.uiuc.edu #^llvm mailx -s 'LLVM CVS: %s' llvm-commits at cs.uiuc.edu -^llvm/www ( /home/vadve/vadve/Research/DynOpt/CVSRepository/CVSROOT/update-www.sh &); /home/vadve/vadve/Research/DynOpt/CVSRepository/CVSROOT/commit-diffs.pl %{sVv} `whoami` llvm-commits at cs.uiuc.edu -^llvm /home/vadve/vadve/Research/DynOpt/CVSRepository/CVSROOT/commit-diffs.pl %{sVv} `whoami` llvm-commits at cs.uiuc.edu -^CVSROOT /home/vadve/vadve/Research/DynOpt/CVSRepository/CVSROOT/commit-diffs.pl %{sVv} `whoami` llvm-commits at cs.uiuc.edu +^llvm/www ( /home/vadve/vadve/Research/DynOpt/CVSRepository/CVSROOT/update-www.sh &); /home/vadve/vadve/Research/DynOpt/CVSRepository/CVSROOT/commit-diffs.pl %{sVv} llvm-commits at cs.uiuc.edu +^llvm /home/vadve/vadve/Research/DynOpt/CVSRepository/CVSROOT/commit-diffs.pl %{sVv} llvm-commits at cs.uiuc.edu +^CVSROOT /home/vadve/vadve/Research/DynOpt/CVSRepository/CVSROOT/commit-diffs.pl %{sVv} llvm-commits at cs.uiuc.edu From lattner at cs.uiuc.edu Tue Oct 1 18:18:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Oct 1 18:18:01 2002 Subject: [llvm-commits] CVS: llvm/www/docs/ProgrammersManual.html Message-ID: <200210012317.SAA05952@tank.cs.uiuc.edu> Changes in directory llvm/www/docs: ProgrammersManual.html updated: 1.33 -> 1.34 --- Log message: Do some cleanups to the Type and Constant section to remove latex stuff There is still a lot of cleanup and fleshing out required here, but at least it gets rid of the flagrantly bad parts. --- Diffs of the changes: Index: llvm/www/docs/ProgrammersManual.html diff -u llvm/www/docs/ProgrammersManual.html:1.33 llvm/www/docs/ProgrammersManual.html:1.34 --- llvm/www/docs/ProgrammersManual.html:1.33 Tue Oct 1 17:39:41 2002 +++ llvm/www/docs/ProgrammersManual.html Tue Oct 1 18:17:09 2002 @@ -1173,7 +1173,7 @@ \end{itemize}

  • LoadInst, StoreInst, GetElemPtrInst : These subclasses represent load, store and getelementptr instructions in LLVM. \begin{itemize} -
  • Value * getPointerOperand (): Returns the Pointer Operand which is typically the 0th operand. +
  • Value * getPointerOperand(): Returns the Pointer Operand which is typically the 0th operand. \end{itemize}
  • BranchInst : This is a subclass of TerminatorInst and defines the interface for conditional and unconditional branches in LLVM. \begin{itemize} @@ -1641,39 +1641,39 @@
  • bool isConstantExpr(): Returns true if it is a ConstantExpr +
    +Important Subclasses of Constant

    - -\subsection{Important Subclasses of Constant} -\begin{itemize} +

    • ConstantSInt : This subclass of Constant represents a signed integer constant. - \begin{itemize} -
    • int64_t getValue () const: Returns the underlying value of this constant. - \end{itemize} +
        +
      • int64_t getValue() const: Returns the underlying value of this constant. +
    • ConstantUInt : This class represents an unsigned integer. - \begin{itemize} -
    • uint64_t getValue () const: Returns the underlying value of this constant. - \end{itemize} +
        +
      • uint64_t getValue() const: Returns the underlying value of this constant. +
    • ConstantFP : This class represents a floating point constant. - \begin{itemize} -
    • double getValue () const: Returns the underlying value of this constant. - \end{itemize} +
        +
      • double getValue() const: Returns the underlying value of this constant. +
    • ConstantBool : This represents a boolean constant. - \begin{itemize} -
    • bool getValue () const: Returns the underlying value of this constant. - \end{itemize} +
        +
      • bool getValue() const: Returns the underlying value of this constant. +
    • ConstantArray : This represents a constant array. - \begin{itemize} +
      • const std::vector &getValues() const: Returns a Vecotr of component constants that makeup this array. - \end{itemize} +
    • ConstantStruct : This represents a constant struct. - \begin{itemize} +
      • const std::vector &getValues() const: Returns a Vecotr of component constants that makeup this array. - \end{itemize} +
    • ConstantPointerRef : This represents a constant pointer value that is initialized to point to a global value, which lies at a constant fixed address. - \begin{itemize} +
      • GlobalValue *getValue(): Returns the global value to which this pointer is pointing to. - \end{itemize} -\end{itemize} +
      +
    @@ -1694,45 +1694,48 @@


Important Public Methods

    -
  • PrimitiveID getPrimitiveID () const: Returns the base type of the type. -
  • bool isSigned () const: Returns whether an integral numeric type is signed. This is true for SByteTy, ShortTy, IntTy, LongTy. Note that this is not true for Float and Double. -
  • bool isUnsigned () const: Returns whether a numeric type is unsigned. This is not quite the complement of isSigned... nonnumeric types return false as they do with isSigned. This returns true for UByteTy, UShortTy, UIntTy, and ULongTy. -
  • bool isInteger () const: Equilivent to isSigned() || isUnsigned(), but with only a single virtual function invocation. -
  • bool isIntegral () const: Returns true if this is an integral type, which is either Bool type or one of the Integer types. +
  • PrimitiveID getPrimitiveID() const: Returns the base type of the type. +
  • bool isSigned() const: Returns whether an integral numeric type is signed. This is true for SByteTy, ShortTy, IntTy, LongTy. Note that this is not true for Float and Double. +
  • bool isUnsigned() const: Returns whether a numeric type is unsigned. This is not quite the complement of isSigned... nonnumeric types return false as they do with isSigned. This returns true for UByteTy, UShortTy, UIntTy, and ULongTy. +
  • bool isInteger() const: Equilivent to isSigned() || isUnsigned(), but with only a single virtual function invocation. +
  • bool isIntegral() const: Returns true if this is an integral type, which is either Bool type or one of the Integer types. -
  • bool isFloatingPoint (): Return true if this is one of the two floating point types. -
  • bool isRecursive () const: Returns rue if the type graph contains a cycle. +
  • bool isFloatingPoint(): Return true if this is one of the two floating point types. +
  • bool isRecursive() const: Returns rue if the type graph contains a cycle.
  • isLosslesslyConvertableTo (const Type *Ty) const: Return true if this type can be converted to 'Ty' without any reinterpretation of bits. For example, uint to int. -
  • bool isPrimitiveType () const: Returns true if it is a primitive type. -
  • bool isDerivedType () const: Returns true if it is a derived type. +
  • bool isPrimitiveType() const: Returns true if it is a primitive type. +
  • bool isDerivedType() const: Returns true if it is a derived type.
  • const Type * getContainedType (unsigned i) const: This method is used to implement the type iterator. For derived types, this returns the types 'contained' in the derived type, returning 0 when 'i' becomes invalid. This allows the user to iterate over the types in a struct, for example, really easily. -
  • unsigned getNumContainedTypes () const: Return the number of types in the derived type. +
  • unsigned getNumContainedTypes() const: Return the number of types in the derived type. +

    +


    +Derived Types

    -\subsection{Derived Types} -\begin{itemize} +

    • SequentialType : This is subclassed by ArrayType and PointerType - \begin{itemize} -
    • const Type * getElementType () const: Returns the type of each of the elements in the sequential type. - \end{itemize} +
        +
      • const Type * getElementType() const: Returns the type of each of the elements in the sequential type. +
    • ArrayType : This is a subclass of SequentialType and defines interface for array types. - \begin{itemize} -
    • unsigned getNumElements () const: Returns the number of elements in the array. - \end{itemize} +
        +
      • unsigned getNumElements() const: Returns the number of elements in the array. +
    • PointerType : Subclass of SequentialType for pointer types.
    • StructType : subclass of DerivedTypes for struct types
    • FunctionType : subclass of DerivedTypes for function types. - \begin{itemize} + +
        -
      • bool isVarArg () const: Returns true if its a vararg function -
      • const Type * getReturnType () const: Returns the return type of the function. -
      • const ParamTypes &getParamTypes () const: Returns a vector of parameter types. +
      • bool isVarArg() const: Returns true if its a vararg function +
      • const Type * getReturnType() const: Returns the return type of the function. +
      • const ParamTypes &getParamTypes() const: Returns a vector of parameter types.
      • const Type * getParamType (unsigned i): Returns the type of the ith parameter. -
      • const unsigned getNumParams () const: Returns the number of formal parameters. - \end{itemize} -\end{itemize} +
      • const unsigned getNumParams() const: Returns the number of formal parameters. +
      +
    @@ -1760,6 +1763,6 @@
    Chris Lattner -Last modified: Tue Oct 1 15:35:42 CDT 2002 +Last modified: Tue Oct 1 18:15:43 CDT 2002 From lattner at cs.uiuc.edu Tue Oct 1 18:42:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Oct 1 18:42:01 2002 Subject: [llvm-commits] CVS: llvm/include/llvm/User.h Message-ID: <200210012341.SAA26292@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm: User.h updated: 1.15 -> 1.16 --- Log message: - Remove the User::eraseOperand method which is never used, really dangerous, and not something we want to expose. --- Diffs of the changes: Index: llvm/include/llvm/User.h diff -u llvm/include/llvm/User.h:1.15 llvm/include/llvm/User.h:1.16 --- llvm/include/llvm/User.h:1.15 Mon Sep 16 11:06:12 2002 +++ llvm/include/llvm/User.h Tue Oct 1 18:41:17 2002 @@ -34,10 +34,6 @@ assert(i < Operands.size() && "setOperand() out of range!"); Operands[i] = Val; } - inline void eraseOperand(unsigned i) { - assert(i < Operands.size() && "setOperand() out of range!"); - Operands.erase(Operands.begin() + i); - } inline unsigned getNumOperands() const { return Operands.size(); } // --------------------------------------------------------------------------- From lattner at cs.uiuc.edu Tue Oct 1 23:58:00 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Oct 1 23:58:00 2002 Subject: [llvm-commits] CVS: llvm/lib/Analysis/DataStructure/DataStructure.cpp Message-ID: <200210020457.XAA28208@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis/DataStructure: DataStructure.cpp updated: 1.19 -> 1.20 --- Log message: * Significant rework of DSNode to support arbitrary aliasing due to merging * Now all and any bytes of a DSNode can be merged together individually. This is neccesary to support the full generality of C and support aliasing correctly. --- Diffs of the changes: Index: llvm/lib/Analysis/DataStructure/DataStructure.cpp diff -u llvm/lib/Analysis/DataStructure/DataStructure.cpp:1.19 llvm/lib/Analysis/DataStructure/DataStructure.cpp:1.20 --- llvm/lib/Analysis/DataStructure/DataStructure.cpp:1.19 Tue Oct 1 17:33:50 2002 +++ llvm/lib/Analysis/DataStructure/DataStructure.cpp Tue Oct 1 23:57:39 2002 @@ -7,9 +7,9 @@ #include "llvm/Analysis/DSGraph.h" #include "llvm/Function.h" #include "llvm/DerivedTypes.h" +#include "llvm/Target/TargetData.h" #include "Support/STLExtras.h" #include "Support/Statistic.h" -#include "llvm/Target/TargetData.h" #include #include @@ -31,15 +31,42 @@ DSNode::DSNode(enum NodeTy NT, const Type *T) : NodeType(NT) { // If this node is big enough to have pointer fields, add space for them now. - if (T != Type::VoidTy && !isa(T)) // Avoid TargetData assert's - LinkIndex.resize(TD.getTypeSize(T), -1); + if (T != Type::VoidTy && !isa(T)) { // Avoid TargetData assert's + MergeMap.resize(TD.getTypeSize(T)); + + // Assign unique values to all of the elements of MergeMap + if (MergeMap.size() < 128) { + // Handle the common case of reasonable size structures... + for (unsigned i = 0, e = MergeMap.size(); i != e; ++i) + MergeMap[i] = -1-i; // Assign -1, -2, -3, ... + } else { + // It's possible that we have something really big here. In this case, + // divide the object into chunks until it will fit into 128 elements. + unsigned Multiple = MergeMap.size()/128; + + // It's probably an array, and probably some power of two in size. + // Because of this, find the biggest power of two that is bigger than + // multiple to use as our real Multiple. + unsigned RealMultiple = 2; + while (RealMultiple < Multiple) RealMultiple <<= 1; + + unsigned RealBound = MergeMap.size()/RealMultiple; + assert(RealBound <= 128 && "Math didn't work out right"); + + // Now go through and assign indexes that are between -1 and -128 + // inclusive + // + for (unsigned i = 0, e = MergeMap.size(); i != e; ++i) + MergeMap[i] = -1-(i % RealBound); // Assign -1, -2, -3... + } + } TypeEntries.push_back(std::make_pair(T, 0)); } // DSNode copy constructor... do not copy over the referrers list! DSNode::DSNode(const DSNode &N) - : Links(N.Links), LinkIndex(N.LinkIndex), + : Links(N.Links), MergeMap(N.MergeMap), TypeEntries(N.TypeEntries), Globals(N.Globals), NodeType(N.NodeType) { } @@ -68,27 +95,89 @@ } +/// setLink - Set the link at the specified offset to the specified +/// NodeHandle, replacing what was there. It is uncommon to use this method, +/// instead one of the higher level methods should be used, below. +/// +void DSNode::setLink(unsigned i, const DSNodeHandle &NH) { + // Create a new entry in the Links vector to hold a new element for offset. + if (!hasLink(i)) { + signed char NewIdx = Links.size(); + // Check to see if we allocate more than 128 distinct links for this node. + // If so, just merge with the last one. This really shouldn't ever happen, + // but it should work regardless of whether it does or not. + // + if (NewIdx >= 0) { + Links.push_back(NH); // Allocate space: common case + } else { // Wrap around? Too many links? + NewIdx--; // Merge with whatever happened last + assert(NewIdx > 0 && "Should wrap back around"); + std::cerr << "\n*** DSNode found that requires more than 128 " + << "active links at once!\n\n"; + } + + signed char OldIdx = MergeMap[i]; + assert (OldIdx < 0 && "Shouldn't contain link!"); + + // Make sure that anything aliasing this field gets updated to point to the + // new link field. + rewriteMergeMap(OldIdx, NewIdx); + assert(MergeMap[i] == NewIdx && "Field not replaced!"); + } else { + Links[MergeMap[i]] = NH; + } +} + // addEdgeTo - Add an edge from the current node to the specified node. This // can cause merging of nodes in the graph. // void DSNode::addEdgeTo(unsigned Offset, const DSNodeHandle &NH) { - assert(Offset < LinkIndex.size() && "Offset out of range!"); + assert(Offset < getSize() && "Offset out of range!"); if (NH.getNode() == 0) return; // Nothing to do - if (LinkIndex[Offset] == -1) { // No merging to perform... - LinkIndex[Offset] = Links.size(); // Allocate a new link... - Links.push_back(NH); - return; + if (DSNodeHandle *ExistingNH = getLink(Offset)) { + // Merge the two nodes... + ExistingNH->mergeWith(NH); + } else { // No merging to perform... + setLink(Offset, NH); // Just force a link in there... } +} - unsigned Idx = (unsigned)LinkIndex[Offset]; - if (!Links[Idx].getNode()) { // No merging to perform - Links[Idx] = NH; - return; - } +/// mergeMappedValues - This is the higher level form of rewriteMergeMap. It is +/// fully capable of merging links together if neccesary as well as simply +/// rewriting the map entries. +/// +void DSNode::mergeMappedValues(signed char V1, signed char V2) { + assert(V1 != V2 && "Cannot merge two identical mapped values!"); + + if (V1 < 0) { // If there is no outgoing link from V1, merge it with V2 + if (V2 < 0 && V1 > V2) + // If both are not linked, merge to the field closer to 0 + rewriteMergeMap(V2, V1); + else + rewriteMergeMap(V1, V2); + } else if (V2 < 0) { // Is V2 < 0 && V1 >= 0? + rewriteMergeMap(V2, V1); // Merge into the one with the link... + } else { // Otherwise, links exist at both locations + // Merge Links[V1] with Links[V2] so they point to the same place now... + Links[V1].mergeWith(Links[V2]); + + // Merge the V2 link into V1 so that we reduce the overall value of the + // links are reduced... + // + if (V2 < V1) std::swap(V1, V2); // Ensure V1 < V2 + rewriteMergeMap(V2, V1); // After this, V2 is "dead" + + // Change the user of the last link to use V2 instead + if ((unsigned)V2 != Links.size()-1) { + rewriteMergeMap(Links.size()-1, V2); // Point to V2 instead of last el... + // Make sure V2 points the right DSNode + Links[V2] = Links.back(); + } - // Merge the two nodes... - Links[Idx].mergeWith(NH); + // Reduce the number of distinct outgoing links... + Links.pop_back(); + } } @@ -171,6 +260,10 @@ // unsigned NOffset = NH.getOffset()-Offset; + unsigned NSize = N->getSize(); + assert(NSize+NOffset <= getSize() && + "Don't know how to merge extend a merged nodes size yet!"); + // Remove all edges pointing at N, causing them to point to 'this' instead. // Make sure to adjust their offset, not just the node pointer. // @@ -179,13 +272,46 @@ Ref = DSNodeHandle(this, NOffset+Ref.getOffset()); } + // We must merge fields in this node due to nodes merged in the source node. + // In order to handle this we build a map that converts from the source node's + // MergeMap values to our MergeMap values. This map is indexed by the + // expression: MergeMap[SMM+SourceNodeSize] so we need to allocate at least + // 2*SourceNodeSize elements of space for the mapping. We can do this because + // we know that there are at most SourceNodeSize outgoing links in the node + // (thus that many positive values) and at most SourceNodeSize distinct fields + // (thus that many negative values). + // + std::vector MergeMapMap(NSize*2, 127); + + // Loop through the structures, merging them together... + for (unsigned i = 0, e = NSize; i != e; ++i) { + // Get what this byte of N maps to... + signed char NElement = N->MergeMap[i]; + + // Get what we map this byte to... + signed char Element = MergeMap[i+NOffset]; + // We use 127 as a sentinal and don't check for it's existence yet... + assert(Element != 127 && "MergeMapMap doesn't permit 127 values yet!"); + + signed char CurMappedVal = MergeMapMap[NElement+NSize]; + if (CurMappedVal == 127) { // Haven't seen this NElement yet? + MergeMapMap[NElement+NSize] = Element; // Map the two together... + } else if (CurMappedVal != Element) { + // If we are mapping two different fields together this means that we need + // to merge fields in the current node due to merging in the source node. + // + mergeMappedValues(CurMappedVal, Element); + MergeMapMap[NElement+NSize] = MergeMap[i+NOffset]; + } + } + // Make all of the outgoing links of N now be outgoing links of this. This // can cause recursive merging! // - for (unsigned i = 0, e = N->LinkIndex.size(); i != e; ++i) - if (N->LinkIndex[i] != -1) { - addEdgeTo(i+NOffset, N->Links[N->LinkIndex[i]]); - N->LinkIndex[i] = -1; // Reduce unneccesary edges in graph. N is dead + for (unsigned i = 0, e = NSize; i != e; ++i) + if (DSNodeHandle *Link = N->getLink(i)) { + addEdgeTo(i+NOffset, *Link); + N->MergeMap[i] = -1; // Kill outgoing edge } // Now that there are no outgoing edges, all of the Links are dead. From lattner at cs.uiuc.edu Tue Oct 1 23:59:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue Oct 1 23:59:01 2002 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/DSGraph.h Message-ID: <200210020458.XAA28220@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: DSGraph.h added (r1.1) --- Log message: Checkin the "meat" of the Data structure graph itself. I forgot to check this in before. :( --- Diffs of the changes: From lattner at cs.uiuc.edu Wed Oct 2 00:19:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Oct 2 00:19:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Analysis/DataStructure/Printer.cpp Message-ID: <200210020518.AAA28414@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis/DataStructure: Printer.cpp updated: 1.8 -> 1.9 --- Log message: When printing DS nodes, print the mergemap index as well to allow easier debugging of merging process. --- Diffs of the changes: Index: llvm/lib/Analysis/DataStructure/Printer.cpp diff -u llvm/lib/Analysis/DataStructure/Printer.cpp:1.8 llvm/lib/Analysis/DataStructure/Printer.cpp:1.9 --- llvm/lib/Analysis/DataStructure/Printer.cpp:1.8 Tue Oct 1 17:33:50 2002 +++ llvm/lib/Analysis/DataStructure/Printer.cpp Wed Oct 2 00:17:55 2002 @@ -100,7 +100,7 @@ O << "|{"; for (unsigned i = 0; i < getSize(); ++i) { if (i) O << "|"; - O << ""; + O << "" << (int)MergeMap[i]; } O << "}"; } From lattner at cs.uiuc.edu Wed Oct 2 01:25:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Oct 2 01:25:01 2002 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/DSGraph.h Message-ID: <200210020624.BAA28797@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: DSGraph.h updated: 1.1 -> 1.2 --- Log message: * Implement fully general merging of array subscripts on demand! This does not handle the initial pointer index case yet though. --- Diffs of the changes: Index: llvm/include/llvm/Analysis/DSGraph.h diff -u llvm/include/llvm/Analysis/DSGraph.h:1.1 llvm/include/llvm/Analysis/DSGraph.h:1.2 --- llvm/include/llvm/Analysis/DSGraph.h:1.1 Tue Oct 1 23:58:12 2002 +++ llvm/include/llvm/Analysis/DSGraph.h Wed Oct 2 01:24:29 2002 @@ -209,6 +209,18 @@ /// void mergeWith(const DSNodeHandle &NH, unsigned Offset); + /// mergeIndexes - If we discover that two indexes are equivalent and must be + /// merged, this function is used to do the dirty work. + /// + void mergeIndexes(unsigned idx1, unsigned idx2) { + assert(idx1 < getSize() && idx2 < getSize() && "Indexes out of range!"); + signed char MV1 = MergeMap[idx1]; + signed char MV2 = MergeMap[idx2]; + if (MV1 != MV2) + mergeMappedValues(MV1, MV2); + } + + /// addGlobal - Add an entry for a global value to the Globals list. This /// also marks the node with the 'G' flag if it does not already have it. /// From lattner at cs.uiuc.edu Wed Oct 2 01:25:04 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Oct 2 01:25:04 2002 Subject: [llvm-commits] CVS: llvm/lib/Analysis/DataStructure/Local.cpp Message-ID: <200210020624.BAA28804@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis/DataStructure: Local.cpp updated: 1.12 -> 1.13 --- Log message: * Implement fully general merging of array subscripts on demand! This does not handle the initial pointer index case yet though. --- Diffs of the changes: Index: llvm/lib/Analysis/DataStructure/Local.cpp diff -u llvm/lib/Analysis/DataStructure/Local.cpp:1.12 llvm/lib/Analysis/DataStructure/Local.cpp:1.13 --- llvm/lib/Analysis/DataStructure/Local.cpp:1.12 Tue Oct 1 17:33:50 2002 +++ llvm/lib/Analysis/DataStructure/Local.cpp Wed Oct 2 01:24:36 2002 @@ -283,10 +283,34 @@ for (unsigned i = 1, e = GEP.getNumOperands(); i != e; ++i) if (GEP.getOperand(i)->getType() == Type::LongTy) { - if (GEP.getOperand(i) != Constant::getNullValue(Type::LongTy)) { - std::cerr << "Array indexing not handled yet!\n"; + // Get the type indexing into... + const SequentialType *STy = cast(CurTy); + CurTy = STy->getElementType(); + if (ConstantSInt *CS = dyn_cast(GEP.getOperand(i))) { + if (isa(STy)) + std::cerr << "Pointer indexing not handled yet!\n"; + else + Offset += CS->getValue()*TD.getTypeSize(CurTy); + } else { + // Variable index into a node. We must merge all of the elements of the + // sequential type here. + if (isa(STy)) + std::cerr << "Pointer indexing not handled yet!\n"; + else { + const ArrayType *ATy = cast(STy); + unsigned ElSize = TD.getTypeSize(CurTy); + DSNode *N = Value.getNode(); + assert(N && "Value must have a node!"); + unsigned RawOffset = Offset+Value.getOffset(); + + // Loop over all of the elements of the array, merging them into the + // zero'th element. + for (unsigned i = 1, e = ATy->getNumElements(); i != e; ++i) + // Merge all of the byte components of this array element + for (unsigned j = 0; j != ElSize; ++j) + N->mergeIndexes(RawOffset+j, RawOffset+i*ElSize+j); + } } - CurTy = cast(CurTy)->getElementType(); } else if (GEP.getOperand(i)->getType() == Type::UByteTy) { unsigned FieldNo = cast(GEP.getOperand(i))->getValue(); const StructType *STy = cast(CurTy); From hldnbrnd at cs.uiuc.edu Wed Oct 2 13:21:01 2002 From: hldnbrnd at cs.uiuc.edu (Nicholas Hildenbrandt) Date: Wed Oct 2 13:21:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CWriter/Writer.cpp Message-ID: <200210021820.NAA19317@trinity.cs.uiuc.edu> Changes in directory llvm/lib/CWriter: Writer.cpp updated: 1.55 -> 1.56 --- Log message: No longer include malloc.h. If protoypes are needed for memory functions they will be present in the byte code and the generated c as well. --- Diffs of the changes: Index: llvm/lib/CWriter/Writer.cpp diff -u llvm/lib/CWriter/Writer.cpp:1.55 llvm/lib/CWriter/Writer.cpp:1.56 --- llvm/lib/CWriter/Writer.cpp:1.55 Mon Sep 30 16:11:55 2002 +++ llvm/lib/CWriter/Writer.cpp Wed Oct 2 13:20:18 2002 @@ -518,7 +518,6 @@ // get declaration for alloca Out << "/* Provide Declarations */\n" - << "#include \n" << "#include \n\n" // Provide a definition for null if one does not already exist, @@ -1019,8 +1018,68 @@ } } + + + + +/* +void CWriter::printIndexingExpression(Value *Ptr, User::op_iterator I, + User::op_iterator E) { + bool HasImplicitAddress = false; + // If accessing a global value with no indexing, avoid *(&GV) syndrome + if (GlobalValue *V = dyn_cast(Ptr)) { + HasImplicitAddress = true; + } else if (ConstantPointerRef *CPR = dyn_cast(Ptr)) { + HasImplicitAddress = true; + Ptr = CPR->getValue(); // Get to the global... + } + + if (I == E) { + if (!HasImplicitAddress) + Out << "*"; // Implicit zero first argument: '*x' is equivalent to 'x[0]' + + writeOperandInternal(Ptr); + return; + } + + const Constant *CI = dyn_cast(I->get()); + if (HasImplicitAddress && (!CI || !CI->isNullValue())) + Out << "(&"; + + writeOperandInternal(Ptr); + + if (HasImplicitAddress && (!CI || !CI->isNullValue())) { + Out << ")"; + HasImplicitAddress = false; // HIA is only true if we haven't addressed yet + } + + assert(!HasImplicitAddress || (CI && CI->isNullValue()) && + "Can only have implicit address with direct accessing"); + + if (HasImplicitAddress) { + ++I; + } else if (CI && CI->isNullValue() && I+1 != E) { + // Print out the -> operator if possible... + if ((*(I+1))->getType() == Type::UByteTy) { + Out << (HasImplicitAddress ? "." : "->"); + Out << "field" << cast(*(I+1))->getValue(); + I += 2; + } + } + + for (; I != E; ++I) + if ((*I)->getType() == Type::LongTy) { + Out << "["; + writeOperand(*I); + Out << "]"; + } else { + Out << ".field" << cast(*I)->getValue(); + } +} +*/ + void CWriter::visitLoadInst(LoadInst &I) { - Out << "*"; + //Out << "*"; writeOperand(I.getOperand(0)); } From hldnbrnd at cs.uiuc.edu Wed Oct 2 13:33:01 2002 From: hldnbrnd at cs.uiuc.edu (Nicholas Hildenbrandt) Date: Wed Oct 2 13:33:01 2002 Subject: [llvm-commits] CVS: llvm/lib/CWriter/Writer.cpp Message-ID: <200210021832.NAA19590@trinity.cs.uiuc.edu> Changes in directory llvm/lib/CWriter: Writer.cpp updated: 1.56 -> 1.57 --- Log message: Cleaned up my last check-in. --- Diffs of the changes: Index: llvm/lib/CWriter/Writer.cpp diff -u llvm/lib/CWriter/Writer.cpp:1.56 llvm/lib/CWriter/Writer.cpp:1.57 --- llvm/lib/CWriter/Writer.cpp:1.56 Wed Oct 2 13:20:18 2002 +++ llvm/lib/CWriter/Writer.cpp Wed Oct 2 13:32:35 2002 @@ -1018,73 +1018,13 @@ } } - - - - -/* -void CWriter::printIndexingExpression(Value *Ptr, User::op_iterator I, - User::op_iterator E) { - bool HasImplicitAddress = false; - // If accessing a global value with no indexing, avoid *(&GV) syndrome - if (GlobalValue *V = dyn_cast(Ptr)) { - HasImplicitAddress = true; - } else if (ConstantPointerRef *CPR = dyn_cast(Ptr)) { - HasImplicitAddress = true; - Ptr = CPR->getValue(); // Get to the global... - } - - if (I == E) { - if (!HasImplicitAddress) - Out << "*"; // Implicit zero first argument: '*x' is equivalent to 'x[0]' - - writeOperandInternal(Ptr); - return; - } - - const Constant *CI = dyn_cast(I->get()); - if (HasImplicitAddress && (!CI || !CI->isNullValue())) - Out << "(&"; - - writeOperandInternal(Ptr); - - if (HasImplicitAddress && (!CI || !CI->isNullValue())) { - Out << ")"; - HasImplicitAddress = false; // HIA is only true if we haven't addressed yet - } - - assert(!HasImplicitAddress || (CI && CI->isNullValue()) && - "Can only have implicit address with direct accessing"); - - if (HasImplicitAddress) { - ++I; - } else if (CI && CI->isNullValue() && I+1 != E) { - // Print out the -> operator if possible... - if ((*(I+1))->getType() == Type::UByteTy) { - Out << (HasImplicitAddress ? "." : "->"); - Out << "field" << cast(*(I+1))->getValue(); - I += 2; - } - } - - for (; I != E; ++I) - if ((*I)->getType() == Type::LongTy) { - Out << "["; - writeOperand(*I); - Out << "]"; - } else { - Out << ".field" << cast(*I)->getValue(); - } -} -*/ - void CWriter::visitLoadInst(LoadInst &I) { //Out << "*"; writeOperand(I.getOperand(0)); } void CWriter::visitStoreInst(StoreInst &I) { - //Out << "*"; + Out << "*"; writeOperand(I.getPointerOperand()); Out << " = "; writeOperand(I.getOperand(0)); From lattner at cs.uiuc.edu Wed Oct 2 13:33:03 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Oct 2 13:33:03 2002 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/LevelRaise/2002-10-02-SignExtensionProblem.ll Message-ID: <200210021832.NAA30590@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/LevelRaise: 2002-10-02-SignExtensionProblem.ll added (r1.1) --- Log message: New testcase for a problem discovered in the SPECINT gzip benchmark. --- Diffs of the changes: From hldnbrnd at cs.uiuc.edu Wed Oct 2 13:36:00 2002 From: hldnbrnd at cs.uiuc.edu (Nicholas Hildenbrandt) Date: Wed Oct 2 13:36:00 2002 Subject: [llvm-commits] CVS: llvm/lib/CWriter/Writer.cpp Message-ID: <200210021835.NAA19793@trinity.cs.uiuc.edu> Changes in directory llvm/lib/CWriter: Writer.cpp updated: 1.57 -> 1.58 --- Log message: Removed unneeded reference and dereferences. --- Diffs of the changes: Index: llvm/lib/CWriter/Writer.cpp diff -u llvm/lib/CWriter/Writer.cpp:1.57 llvm/lib/CWriter/Writer.cpp:1.58 --- llvm/lib/CWriter/Writer.cpp:1.57 Wed Oct 2 13:32:35 2002 +++ llvm/lib/CWriter/Writer.cpp Wed Oct 2 13:34:51 2002 @@ -1019,19 +1019,16 @@ } void CWriter::visitLoadInst(LoadInst &I) { - //Out << "*"; writeOperand(I.getOperand(0)); } void CWriter::visitStoreInst(StoreInst &I) { - Out << "*"; writeOperand(I.getPointerOperand()); Out << " = "; writeOperand(I.getOperand(0)); } void CWriter::visitGetElementPtrInst(GetElementPtrInst &I) { - //Out << "&"; printIndexingExpression(I.getPointerOperand(), I.idx_begin(), I.idx_end()); } From lattner at cs.uiuc.edu Wed Oct 2 13:54:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Oct 2 13:54:01 2002 Subject: [llvm-commits] CVS: llvm/lib/Transforms/TransformInternals.cpp Message-ID: <200210021853.NAA31568@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms: TransformInternals.cpp updated: 1.30 -> 1.31 --- Log message: Fix bug: 2002-10-02-SignExtensionProblem.ll --- Diffs of the changes: Index: llvm/lib/Transforms/TransformInternals.cpp diff -u llvm/lib/Transforms/TransformInternals.cpp:1.30 llvm/lib/Transforms/TransformInternals.cpp:1.31 --- llvm/lib/Transforms/TransformInternals.cpp:1.30 Mon Sep 16 13:32:32 2002 +++ llvm/lib/Transforms/TransformInternals.cpp Wed Oct 2 13:53:14 2002 @@ -147,15 +147,14 @@ if (ScaleAmt && ScaleAmt != 1) { // If we have to scale up our index, do so now - Value *ScaleAmtVal = ConstantSInt::get(Type::LongTy, - (unsigned)ScaleAmt); + Value *ScaleAmtVal = ConstantSInt::get(Type::LongTy, ScaleAmt); Expr.Var = BinaryOperator::create(Instruction::Mul, Expr.Var, ScaleAmtVal, Expr.Var->getName()+"-scale",*BI); } if (Index) { // Add an offset to the index - Value *IndexAmt = ConstantSInt::get(Type::LongTy, (unsigned)Index); + Value *IndexAmt = ConstantSInt::get(Type::LongTy, Index); Expr.Var = BinaryOperator::create(Instruction::Add, Expr.Var, IndexAmt, Expr.Var->getName()+"-offset", From lattner at cs.uiuc.edu Wed Oct 2 14:31:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Oct 2 14:31:01 2002 Subject: [llvm-commits] CVS: llvm/test/Programs/MultiSource/Fhourstones/ Message-ID: <200210021930.OAA02538@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/MultiSource/Fhourstones: --- Log message: Directory /home/vadve/vadve/Research/DynOpt/CVSRepository/llvm/test/Programs/MultiSource/Fhourstones added to the repository --- Diffs of the changes: From lattner at cs.uiuc.edu Wed Oct 2 14:31:03 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Oct 2 14:31:03 2002 Subject: [llvm-commits] CVS: llvm/test/Programs/MultiSource/Fhourstones/Makefile Makefile.original README_LLVM.txt c4.c c4.h input play.c time.c trans.c types.h Message-ID: <200210021930.OAA02551@apoc.cs.uiuc.edu> Changes in directory llvm/test/Programs/MultiSource/Fhourstones: Makefile added (r1.1) Makefile.original added (r1.1) README_LLVM.txt added (r1.1) c4.c added (r1.1) c4.h added (r1.1) input added (r1.1) play.c added (r1.1) time.c added (r1.1) trans.c added (r1.1) types.h added (r1.1) --- Log message: Initial checkin of new Fhourstones benchmark --- Diffs of the changes: From lattner at cs.uiuc.edu Wed Oct 2 14:40:01 2002 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed Oct 2 14:40:01 2002 Subject: [llvm-commits] CVS: llvm/lib/VMCore/AsmWriter.cpp Message-ID: <200210021939.OAA02612@apoc.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: AsmWriter.cpp updated: 1.76 -> 1.77 --- Log message: - Print the predecessors of a basic block instead of the number of uses of the block in the AsmWriter --- Diffs of the changes: Index: llvm/lib/VMCore/AsmWriter.cpp diff -u llvm/lib/VMCore/AsmWriter.cpp:1.76 llvm/lib/VMCore/AsmWriter.cpp:1.77 --- llvm/lib/VMCore/AsmWriter.cpp:1.76 Tue Sep 10 10:53:49 2002 +++ llvm/lib/VMCore/AsmWriter.cpp Wed Oct 2 14:38:55 2002 @@ -21,6 +21,7 @@ #include "llvm/iPHINode.h" #include "llvm/iOther.h" #include "llvm/SymbolTable.h" +#include "llvm/Support/CFG.h" #include "Support/StringExtras.h" #include "Support/STLExtras.h" #include @@ -661,8 +662,7 @@ // void AssemblyWriter::printBasicBlock(const BasicBlock *BB) { if (BB->hasName()) { // Print out the label if it exists... - Out << "\n" << BB->getName() << ":\t\t\t\t\t;[#uses=" - << BB->use_size() << "]"; // Output # uses + Out << "\n" << BB->getName() << ":"; } else if (!BB->use_empty()) { // Don't print block # of no uses... int Slot = Table.getValSlot(BB); Out << "\n;