From reid at x10sys.com Mon Apr 25 02:29:44 2005 From: reid at x10sys.com (Reid Spencer) Date: Mon, 25 Apr 2005 02:29:44 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/SimplifyLibCalls/2005-04-24-strcat.ll Message-ID: <200504250729.CAA32310@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/SimplifyLibCalls: 2005-04-24-strcat.ll added (r1.1) --- Log message: A test case for testing the StrCatOptimizer, currently XFAILed everywhere. --- Diffs of the changes: (+16 -0) 2005-04-24-strcat.ll | 16 ++++++++++++++++ 1 files changed, 16 insertions(+) Index: llvm/test/Regression/Transforms/SimplifyLibCalls/2005-04-24-strcat.ll diff -c /dev/null llvm/test/Regression/Transforms/SimplifyLibCalls/2005-04-24-strcat.ll:1.1 *** /dev/null Mon Apr 25 02:29:41 2005 --- llvm/test/Regression/Transforms/SimplifyLibCalls/2005-04-24-strcat.ll Mon Apr 25 02:29:30 2005 *************** *** 0 **** --- 1,16 ---- + ; Test that the StrCatOptimizer works correctly + ; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | grep strlen + ; XFAIL: * + + declare sbyte* %strcat(sbyte*,sbyte*) + %hello = constant [6 x sbyte] c"hello\00" + + implementation ; Functions: + + int %main () { + %target = alloca [1024 x sbyte] + %arg1 = getelementptr [1024 x sbyte]* %target, int 0, int 0 + %arg2 = getelementptr [6 x sbyte]* %hello, int 0, int 0 + %rslt = call sbyte* %strcat(sbyte* %arg1, sbyte* %arg2) + ret int 0 + } From reid at x10sys.com Mon Apr 25 10:40:46 2005 From: reid at x10sys.com (Reid Spencer) Date: Mon, 25 Apr 2005 10:40:46 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/SimplifyLibCalls/2005-04-24-strcat.ll Message-ID: <200504251540.KAA30892@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/SimplifyLibCalls: 2005-04-24-strcat.ll updated: 1.1 -> 1.2 --- Log message: Make sure the target buffer is null terminated so we don't blow up strcat when its called. --- Diffs of the changes: (+1 -0) 2005-04-24-strcat.ll | 1 + 1 files changed, 1 insertion(+) Index: llvm/test/Regression/Transforms/SimplifyLibCalls/2005-04-24-strcat.ll diff -u llvm/test/Regression/Transforms/SimplifyLibCalls/2005-04-24-strcat.ll:1.1 llvm/test/Regression/Transforms/SimplifyLibCalls/2005-04-24-strcat.ll:1.2 --- llvm/test/Regression/Transforms/SimplifyLibCalls/2005-04-24-strcat.ll:1.1 Mon Apr 25 02:29:30 2005 +++ llvm/test/Regression/Transforms/SimplifyLibCalls/2005-04-24-strcat.ll Mon Apr 25 10:40:35 2005 @@ -10,6 +10,7 @@ int %main () { %target = alloca [1024 x sbyte] %arg1 = getelementptr [1024 x sbyte]* %target, int 0, int 0 + store sbyte 0, sbyte* %arg1 %arg2 = getelementptr [6 x sbyte]* %hello, int 0, int 0 %rslt = call sbyte* %strcat(sbyte* %arg1, sbyte* %arg2) ret int 0 From lattner at cs.uiuc.edu Mon Apr 25 10:48:14 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 25 Apr 2005 10:48:14 -0500 Subject: [llvm-commits] CVS: llvm/docs/ProgrammersManual.html Message-ID: <200504251548.j3PFmEru016874@apoc.cs.uiuc.edu> Changes in directory llvm/docs: ProgrammersManual.html updated: 1.82 -> 1.83 --- Log message: Add feedback from Vikram --- Diffs of the changes: (+12 -3) ProgrammersManual.html | 15 ++++++++++++--- 1 files changed, 12 insertions(+), 3 deletions(-) Index: llvm/docs/ProgrammersManual.html diff -u llvm/docs/ProgrammersManual.html:1.82 llvm/docs/ProgrammersManual.html:1.83 --- llvm/docs/ProgrammersManual.html:1.82 Sat Apr 23 12:27:36 2005 +++ llvm/docs/ProgrammersManual.html Mon Apr 25 10:47:57 2005 @@ -970,6 +970,15 @@ system.

+

+For our purposes below, we need three concepts. First, an "Opaque Type" is +exactly as defined in the language +reference. Second an "Abstract Type" is any type which includes an +opaque type as part of its type graph (for example "{ opaque, int }"). +Third, a concrete type is a type that is not an abstract type (e.g. "[ int, +float }"). +

+ @@ -1093,8 +1102,8 @@ To support this, a class can derive from the AbstractTypeUser class. This class allows it to get callbacks when certain types are resolved. To register to get callbacks for a particular type, the DerivedType::{add/remove}AbstractTypeUser -methods can be called on a type. Note that these methods only work for {\em -abstract} types. Concrete types (those that do not include an opaque objects +methods can be called on a type. Note that these methods only work for +abstract types. Concrete types (those that do not include an opaque objects somewhere) can never be refined.

@@ -2227,7 +2236,7 @@ Dinakar Dhurjati and Chris Lattner
The LLVM Compiler Infrastructure
- Last modified: $Date: 2005/04/23 17:27:36 $ + Last modified: $Date: 2005/04/25 15:47:57 $ From lattner at cs.uiuc.edu Mon Apr 25 12:34:32 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 25 Apr 2005 12:34:32 -0500 Subject: [llvm-commits] CVS: llvm/docs/LangRef.html Message-ID: <200504251734.j3PHYW1x017065@apoc.cs.uiuc.edu> Changes in directory llvm/docs: LangRef.html updated: 1.92 -> 1.93 --- Log message: document 'opaque' types --- Diffs of the changes: (+44 -2) LangRef.html | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 44 insertions(+), 2 deletions(-) Index: llvm/docs/LangRef.html diff -u llvm/docs/LangRef.html:1.92 llvm/docs/LangRef.html:1.93 --- llvm/docs/LangRef.html:1.92 Fri Apr 22 13:02:52 2005 +++ llvm/docs/LangRef.html Mon Apr 25 12:34:15 2005 @@ -39,6 +39,7 @@
  • Pointer Type
  • Structure Type
  • Packed Type
  • +
  • Opaque Type
  • @@ -750,18 +751,27 @@
    Packed Type
    +
    Overview:
    +

    A packed type is a simple derived type that represents a vector of elements. Packed types are used when multiple primitive data are operated in parallel using a single instruction (SIMD). A packed type requires a size (number of elements) and an underlying primitive data type. Packed types are considered first class.

    +
    Syntax:
    -
      < <# elements> x <elementtype> >
    + +
    +  < <# elements> x <elementtype> >
    +
    +

    The number of elements is a constant integer value, elementtype may be any integral or floating point type.

    +
    Examples:
    +
    @@ -778,6 +788,38 @@
    + +
    Opaque Type
    +
    + +
    Overview:
    + +

    Opaque types are used to represent unknown types in the system. This +corresponds (for example) to the C notion of a foward declared structure type. +In LLVM, opaque types can eventually be resolved to any type (not just a +structure type).

    + +
    Syntax:
    + +
    +  opaque
    +
    + +
    Examples:
    + + + + + + +
    + opaque + + An opaque type.
    +
    +
    + +
    Constants
    @@ -3015,7 +3057,7 @@ Chris Lattner
    The LLVM Compiler Infrastructure
    - Last modified: $Date: 2005/04/22 18:02:52 $ + Last modified: $Date: 2005/04/25 17:34:15 $ From lattner at cs.uiuc.edu Mon Apr 25 14:16:47 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 25 Apr 2005 14:16:47 -0500 Subject: [llvm-commits] CVS: llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp Message-ID: <200504251916.j3PJGl9p018117@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis/DataStructure: BottomUpClosure.cpp updated: 1.114 -> 1.115 --- Log message: Correctly handle global-argument aliases induced in main --- Diffs of the changes: (+30 -2) BottomUpClosure.cpp | 32 ++++++++++++++++++++++++++++++-- 1 files changed, 30 insertions(+), 2 deletions(-) Index: llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp diff -u llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp:1.114 llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp:1.115 --- llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp:1.114 Thu Apr 21 16:07:28 2005 +++ llvm/lib/Analysis/DataStructure/BottomUpClosure.cpp Mon Apr 25 14:16:31 2005 @@ -434,14 +434,42 @@ void BUDataStructures::calculateGraph(DSGraph &Graph) { + // If this graph contains the main function, clone the globals graph into this + // graph before we inline callees and other fun stuff. + bool ContainsMain = false; + DSGraph::ReturnNodesTy &ReturnNodes = Graph.getReturnNodes(); + + for (DSGraph::ReturnNodesTy::iterator I = ReturnNodes.begin(), + E = ReturnNodes.end(); I != E; ++I) + if (I->first->hasExternalLinkage() && I->first->getName() == "main") { + ContainsMain = true; + break; + } + + // If this graph contains main, copy the contents of the globals graph over. + // Note that this is *required* for correctness. If a callee contains a use + // of a global, we have to make sure to link up nodes due to global-argument + // bindings. + if (ContainsMain) { + const DSGraph &GG = *Graph.getGlobalsGraph(); + ReachabilityCloner RC(Graph, GG, + DSGraph::DontCloneCallNodes | + DSGraph::DontCloneAuxCallNodes); + + // Clone the global nodes into this graph. + for (DSScalarMap::global_iterator I = GG.getScalarMap().global_begin(), + E = GG.getScalarMap().global_end(); I != E; ++I) + if (isa(*I)) + RC.getClonedNH(GG.getNodeForValue(*I)); + } + + // Move our call site list into TempFCs so that inline call sites go into the // new call site list and doesn't invalidate our iterators! std::list TempFCs; std::list &AuxCallsList = Graph.getAuxFunctionCalls(); TempFCs.swap(AuxCallsList); - DSGraph::ReturnNodesTy &ReturnNodes = Graph.getReturnNodes(); - bool Printed = false; std::vector CalledFuncs; while (!TempFCs.empty()) { From lattner at cs.uiuc.edu Mon Apr 25 14:17:01 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 25 Apr 2005 14:17:01 -0500 Subject: [llvm-commits] CVS: llvm/lib/Analysis/DataStructure/DataStructure.cpp Message-ID: <200504251917.j3PJH1TD018126@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis/DataStructure: DataStructure.cpp updated: 1.239 -> 1.240 --- Log message: Don't mess up SCC traversal when a node has null edges out of it. --- Diffs of the changes: (+6 -5) DataStructure.cpp | 11 ++++++----- 1 files changed, 6 insertions(+), 5 deletions(-) Index: llvm/lib/Analysis/DataStructure/DataStructure.cpp diff -u llvm/lib/Analysis/DataStructure/DataStructure.cpp:1.239 llvm/lib/Analysis/DataStructure/DataStructure.cpp:1.240 --- llvm/lib/Analysis/DataStructure/DataStructure.cpp:1.239 Thu Apr 21 16:07:28 2005 +++ llvm/lib/Analysis/DataStructure/DataStructure.cpp Mon Apr 25 14:16:17 2005 @@ -1430,11 +1430,12 @@ // Otherwise, check all successors. bool AnyDirectSuccessorsReachClonedNodes = false; for (DSNode::const_edge_iterator EI = N->edge_begin(), EE = N->edge_end(); - EI != EE; ++EI) { - std::pair &SuccInfo = VisitForSCCs(EI->getNode()); - if (SuccInfo.first < Min) Min = SuccInfo.first; - AnyDirectSuccessorsReachClonedNodes |= SuccInfo.second; - } + EI != EE; ++EI) + if (DSNode *Succ = EI->getNode()) { + std::pair &SuccInfo = VisitForSCCs(Succ); + if (SuccInfo.first < Min) Min = SuccInfo.first; + AnyDirectSuccessorsReachClonedNodes |= SuccInfo.second; + } if (Min != MyId) return ThisNodeInfo; // Part of a large SCC. Leave self on stack. From brukman at cs.uiuc.edu Mon Apr 25 14:50:05 2005 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Mon, 25 Apr 2005 14:50:05 -0500 Subject: [llvm-commits] CVS: llvm-test/External/PerfectClub/arc2d/Makefile Message-ID: <200504251950.OAA00395@zion.cs.uiuc.edu> Changes in directory llvm-test/External/PerfectClub/arc2d: Makefile updated: 1.1 -> 1.2 --- Log message: Get arc2d closer to working --- Diffs of the changes: (+3 -3) Makefile | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) Index: llvm-test/External/PerfectClub/arc2d/Makefile diff -u llvm-test/External/PerfectClub/arc2d/Makefile:1.1 llvm-test/External/PerfectClub/arc2d/Makefile:1.2 --- llvm-test/External/PerfectClub/arc2d/Makefile:1.1 Sun Apr 24 17:10:58 2005 +++ llvm-test/External/PerfectClub/arc2d/Makefile Mon Apr 25 14:49:54 2005 @@ -1,7 +1,7 @@ LEVEL = ../../.. include $(LEVEL)/Makefile.f2c -PROG = arc2d -Source := $(wildcard /home/vadve/tbrethou/cvs/llvm/projects/llvm-test/External/Perfect/arc2d/*.f) +Source = COUNTY.f DOEXTY.f ENTERY.f MINITY.f DOENTY.f DUMPY.f \ + EXITY.f MENDY.f SRSI.f TIMY.f TIMERS.f -include $(LEVEL)/MultiSource/Makefile.multisrc +include ../Makefile.perfect From lattner at cs.uiuc.edu Mon Apr 25 15:17:16 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 25 Apr 2005 15:17:16 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/InstCombine/getelementptr.ll Message-ID: <200504252017.j3PKHG9a021123@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/InstCombine: getelementptr.ll updated: 1.14 -> 1.15 --- Log message: new testcase --- Diffs of the changes: (+8 -0) getelementptr.ll | 8 ++++++++ 1 files changed, 8 insertions(+) Index: llvm/test/Regression/Transforms/InstCombine/getelementptr.ll diff -u llvm/test/Regression/Transforms/InstCombine/getelementptr.ll:1.14 llvm/test/Regression/Transforms/InstCombine/getelementptr.ll:1.15 --- llvm/test/Regression/Transforms/InstCombine/getelementptr.ll:1.14 Sat Oct 16 14:44:23 2004 +++ llvm/test/Regression/Transforms/InstCombine/getelementptr.ll Mon Apr 25 15:17:00 2005 @@ -58,3 +58,11 @@ %B = cast double* %A to int ret int %B } + +bool %g({int, int} * %x, {int, int} * %y) { + %tmp.1 = getelementptr {int,int}* %x, int 0, uint 1 + %tmp.3 = getelementptr {int,int}* %y, int 0, uint 1 + %tmp.4 = seteq int* %tmp.1, %tmp.3 ;; seteq x, y + ret bool %tmp.4 +} + From lattner at cs.uiuc.edu Mon Apr 25 15:17:30 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 25 Apr 2005 15:17:30 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/InstCombine/getelementptr.ll Message-ID: <200504252017.j3PKHUI5021136@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/InstCombine: getelementptr.ll updated: 1.15 -> 1.16 --- Log message: rename fn --- Diffs of the changes: (+1 -1) getelementptr.ll | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/test/Regression/Transforms/InstCombine/getelementptr.ll diff -u llvm/test/Regression/Transforms/InstCombine/getelementptr.ll:1.15 llvm/test/Regression/Transforms/InstCombine/getelementptr.ll:1.16 --- llvm/test/Regression/Transforms/InstCombine/getelementptr.ll:1.15 Mon Apr 25 15:17:00 2005 +++ llvm/test/Regression/Transforms/InstCombine/getelementptr.ll Mon Apr 25 15:17:16 2005 @@ -59,7 +59,7 @@ ret int %B } -bool %g({int, int} * %x, {int, int} * %y) { +bool %test10({int, int} * %x, {int, int} * %y) { %tmp.1 = getelementptr {int,int}* %x, int 0, uint 1 %tmp.3 = getelementptr {int,int}* %y, int 0, uint 1 %tmp.4 = seteq int* %tmp.1, %tmp.3 ;; seteq x, y From lattner at cs.uiuc.edu Mon Apr 25 15:17:43 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 25 Apr 2005 15:17:43 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200504252017.j3PKHhKQ021149@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.329 -> 1.330 --- Log message: implement getelementptr.ll:test10 --- Diffs of the changes: (+19 -1) InstructionCombining.cpp | 20 +++++++++++++++++++- 1 files changed, 19 insertions(+), 1 deletion(-) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.329 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.330 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.329 Sun Apr 24 12:46:05 2005 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Mon Apr 25 15:17:30 2005 @@ -2277,8 +2277,26 @@ Constant::getNullValue(Offset->getType())); } } else if (User *GEPRHS = dyn_castGetElementPtr(RHS)) { - if (PtrBase != GEPRHS->getOperand(0)) + // If the base pointers are different, but the indices are the same, just + // compare the base pointer. + if (PtrBase != GEPRHS->getOperand(0)) { + bool IndicesTheSame = GEPLHS->getNumOperands()==GEPRHS->getNumOperands(); + if (IndicesTheSame) + for (unsigned i = 1, e = GEPLHS->getNumOperands(); i != e; ++i) + if (GEPLHS->getOperand(i) != GEPRHS->getOperand(i)) { + IndicesTheSame = false; + break; + } + + // If all indices are the same, just compare the base pointers. + if (IndicesTheSame) + return new SetCondInst(Cond, GEPLHS->getOperand(0), + GEPRHS->getOperand(0)); + + // Otherwise, the base pointers are different and the indices are + // different, bail out. return 0; + } // If one of the GEPs has all zero indices, recurse. bool AllZeros = true; From tbrethou at cs.uiuc.edu Mon Apr 25 15:37:08 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Mon, 25 Apr 2005 15:37:08 -0500 Subject: [llvm-commits] CVS: llvm/docs/FAQ.html Message-ID: <200504252037.j3PKb8c3021413@apoc.cs.uiuc.edu> Changes in directory llvm/docs: FAQ.html updated: 1.29 -> 1.30 --- Log message: Added question about turning off all optimizations. I think this has been asked once or twice. --- Diffs of the changes: (+19 -1) FAQ.html | 20 +++++++++++++++++++- 1 files changed, 19 insertions(+), 1 deletion(-) Index: llvm/docs/FAQ.html diff -u llvm/docs/FAQ.html:1.29 llvm/docs/FAQ.html:1.30 --- llvm/docs/FAQ.html:1.29 Fri Feb 25 14:30:21 2005 +++ llvm/docs/FAQ.html Mon Apr 25 15:36:56 2005 @@ -67,6 +67,11 @@ When I compile code using the LLVM GCC front end, it complains that it cannot find libcrtend.a. + +
  • + How can I disable all optimizations when compiling code using the LLVM GCC front end? +
  • + @@ -442,6 +447,19 @@ +
    +

    +How can I disable all optimizations when compiling code using the LLVM GCC front end? +

    +
    + +
    +

    +Passing "-Wa,-disable-opt -Wl,-disable-opt" will disable *all* cleanup and +optimizations done at the llvm level, leaving you with the truly horrible +code that you desire. +

    +
    @@ -556,7 +574,7 @@ src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01!"> LLVM Compiler Infrastructure
    - Last modified: $Date: 2005/02/25 20:30:21 $ + Last modified: $Date: 2005/04/25 20:36:56 $ From lattner at cs.uiuc.edu Mon Apr 25 15:50:49 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 25 Apr 2005 15:50:49 -0500 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Dominators.cpp Message-ID: <200504252050.j3PKonk3023764@apoc.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Dominators.cpp updated: 1.62 -> 1.63 --- Log message: Make dominates(A,B) work with post dominators. Patch contributed by Naveen Neelakantam, thanks! --- Diffs of the changes: (+7 -2) Dominators.cpp | 9 +++++++-- 1 files changed, 7 insertions(+), 2 deletions(-) Index: llvm/lib/VMCore/Dominators.cpp diff -u llvm/lib/VMCore/Dominators.cpp:1.62 llvm/lib/VMCore/Dominators.cpp:1.63 --- llvm/lib/VMCore/Dominators.cpp:1.62 Sat Apr 23 16:38:35 2005 +++ llvm/lib/VMCore/Dominators.cpp Mon Apr 25 15:50:33 2005 @@ -245,8 +245,13 @@ BasicBlock::iterator I = BBA->begin(); for (; &*I != A && &*I != B; ++I) /*empty*/; - // A dominates B if it is found first in the basic block... - return &*I == A; + if(!IsPostDominators) { + // A dominates B if it is found first in the basic block. + return &*I == A; + } else { + // A post-dominates B if B is found first in the basic block. + return &*I == B; + } } From lattner at cs.uiuc.edu Mon Apr 25 16:03:42 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 25 Apr 2005 16:03:42 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Message-ID: <200504252103.j3PL3gk9030392@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: SelectionDAG.cpp updated: 1.92 -> 1.93 --- Log message: Codegen x < 0 | y < 0 as (x|y) < 0. This allows us to compile this to: _foo: or r2, r4, r3 srwi r3, r2, 31 blr instead of: _foo: srwi r2, r4, 31 srwi r3, r3, 31 or r3, r2, r3 blr --- Diffs of the changes: (+4 -1) SelectionDAG.cpp | 5 ++++- 1 files changed, 4 insertions(+), 1 deletion(-) Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.92 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.93 --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.92 Thu Apr 21 23:01:18 2005 +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Mon Apr 25 16:03:25 2005 @@ -809,6 +809,7 @@ return MaskedValueIsZero(Op.getOperand(0), NewVal, TLI); } return false; + // TODO we could handle some SRA cases here. default: break; } @@ -1061,11 +1062,13 @@ // (X != 0) | (Y != 0) -> (X|Y != 0) // (X == 0) & (Y == 0) -> (X|Y == 0) + // (X < 0) | (Y < 0) -> (X|Y < 0) if (LR == RR && isa(LR) && cast(LR)->getValue() == 0 && Op2 == LHS->getCondition() && MVT::isInteger(LL.getValueType())) { if ((Op2 == ISD::SETEQ && Opcode == ISD::AND) || - (Op2 == ISD::SETNE && Opcode == ISD::OR)) + (Op2 == ISD::SETNE && Opcode == ISD::OR) || + (Op2 == ISD::SETLT && Opcode == ISD::OR)) return getSetCC(Op2, VT, getNode(ISD::OR, LR.getValueType(), LL, RL), LR); } From reid at x10sys.com Mon Apr 25 16:08:45 2005 From: reid at x10sys.com (Reid Spencer) Date: Mon, 25 Apr 2005 16:08:45 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/SimplifyLibCalls/2005-04-24-strcat.ll Message-ID: <200504252108.QAA02084@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/SimplifyLibCalls: 2005-04-24-strcat.ll updated: 1.2 -> 1.3 --- Log message: Update the test case to handle a few more (degenerate) cases and remove the restriction that it is an XFAIL because it now passes. --- Diffs of the changes: (+10 -3) 2005-04-24-strcat.ll | 13 ++++++++++--- 1 files changed, 10 insertions(+), 3 deletions(-) Index: llvm/test/Regression/Transforms/SimplifyLibCalls/2005-04-24-strcat.ll diff -u llvm/test/Regression/Transforms/SimplifyLibCalls/2005-04-24-strcat.ll:1.2 llvm/test/Regression/Transforms/SimplifyLibCalls/2005-04-24-strcat.ll:1.3 --- llvm/test/Regression/Transforms/SimplifyLibCalls/2005-04-24-strcat.ll:1.2 Mon Apr 25 10:40:35 2005 +++ llvm/test/Regression/Transforms/SimplifyLibCalls/2005-04-24-strcat.ll Mon Apr 25 16:08:34 2005 @@ -1,9 +1,11 @@ ; Test that the StrCatOptimizer works correctly -; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | grep strlen -; XFAIL: * +; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | grep -v 'call.*strcat' declare sbyte* %strcat(sbyte*,sbyte*) +declare int %puts(sbyte*) %hello = constant [6 x sbyte] c"hello\00" +%null = constant [1 x sbyte] c"\00" +%null_hello = constant [7 x sbyte] c"\00hello\00" implementation ; Functions: @@ -12,6 +14,11 @@ %arg1 = getelementptr [1024 x sbyte]* %target, int 0, int 0 store sbyte 0, sbyte* %arg1 %arg2 = getelementptr [6 x sbyte]* %hello, int 0, int 0 - %rslt = call sbyte* %strcat(sbyte* %arg1, sbyte* %arg2) + %rslt1 = call sbyte* %strcat(sbyte* %arg1, sbyte* %arg2) + %arg3 = getelementptr [1 x sbyte]* %null, int 0, int 0 + %rslt2 = call sbyte* %strcat(sbyte* %rslt1, sbyte* %arg3) + %arg4 = getelementptr [7 x sbyte]* %null_hello, int 0, int 0 + %rslt3 = call sbyte* %strcat(sbyte* %rslt2, sbyte* %arg4) + call int %puts(sbyte* %rslt3) ret int 0 } From reid at x10sys.com Mon Apr 25 16:11:59 2005 From: reid at x10sys.com (Reid Spencer) Date: Mon, 25 Apr 2005 16:11:59 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Message-ID: <200504252111.QAA02205@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: SimplifyLibCalls.cpp updated: 1.2 -> 1.3 --- Log message: Lots of changes based on review and new functionality: * Use a  --- Diffs of the changes: (+267 -49) SimplifyLibCalls.cpp | 316 +++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 267 insertions(+), 49 deletions(-) Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.2 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.3 --- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.2 Sun Apr 24 22:59:26 2005 +++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Mon Apr 25 16:11:48 2005 @@ -19,9 +19,12 @@ #include "llvm/Transforms/IPO.h" #include "llvm/Module.h" #include "llvm/Pass.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Constants.h" #include "llvm/Instructions.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/hash_map" +#include using namespace llvm; namespace { @@ -58,6 +61,19 @@ virtual ~CallOptimizer(); + /// The implementation of this function in subclasses should determine if + /// \p F is suitable for the optimization. This method is called by + /// runOnModule to short circuit visiting all the call sites of such a + /// function if that function is not suitable in the first place. + /// If the called function is suitabe, this method should return true; + /// false, otherwise. This function should also perform any lazy + /// initialization that the CallOptimizer needs to do, if its to return + /// true. This avoids doing initialization until the optimizer is actually + /// going to be called upon to do some optimization. + virtual bool ValidateCalledFunction( + const Function* F ///< The function that is the target of call sites + ) const = 0; + /// The implementations of this function in subclasses is the heart of the /// SimplifyLibCalls algorithm. Sublcasses of this class implement /// OptimizeCall to determine if (a) the conditions are right for optimizing @@ -67,14 +83,17 @@ /// @param ci the call instruction under consideration /// @param f the function that ci calls. /// @brief Optimize a call, if possible. - virtual bool OptimizeCall(CallInst* ci) const = 0; + virtual bool OptimizeCall( + CallInst* ci ///< The call instruction that should be optimized. + ) const = 0; - const std::string& getFunctionName() const { return func_name; } + const char * getFunctionName() const { return func_name; } private: - std::string func_name; + const char* func_name; }; /// @brief The list of optimizations deriving from CallOptimizer + hash_map optlist; CallOptimizer::CallOptimizer(const char* fname) @@ -85,7 +104,10 @@ } /// Make sure we get our virtual table in this file. - CallOptimizer::~CallOptimizer() {} + CallOptimizer::~CallOptimizer() + { + optlist.clear(); + } } ModulePass *llvm::createSimplifyLibCallsPass() @@ -95,35 +117,52 @@ bool SimplifyLibCalls::runOnModule(Module &M) { - for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI) + bool result = false; + + // The call optimizations can be recursive. That is, the optimization might + // generate a call to another function which can also be optimized. This way + // we make the CallOptimizer instances very specific to the case they handle. + // It also means we need to keep running over the function calls in the module + // until we don't get any more optimizations possible. + bool found_optimization = false; + do { - // All the "well-known" functions are external because they live in a - // runtime library somewhere and were (probably) not compiled by LLVM. - // So, we only act on external functions that have non-empty uses. - if (FI->isExternal() && !FI->use_empty()) + found_optimization = false; + for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI) { - // Get the optimization class that pertains to this function - if (CallOptimizer* CO = optlist[FI->getName()] ) + // All the "well-known" functions are external and have external linkage + // because they live in a runtime library somewhere and were (probably) + // not compiled by LLVM. So, we only act on external functions that have + // external linkage and non-empty uses. + if (FI->isExternal() && FI->hasExternalLinkage() && !FI->use_empty()) { - // Loop over each of the uses of the function - for (Value::use_iterator UI = FI->use_begin(), UE = FI->use_end(); - UI != UE ; ) + // Get the optimization class that pertains to this function + if (CallOptimizer* CO = optlist[FI->getName().c_str()] ) { - // If the use of the function is a call instruction - if (CallInst* CI = dyn_cast(*UI++)) + // Make sure the called function is suitable for the optimization + if (CO->ValidateCalledFunction(FI)) { - // Do the optimization on the CallOptimizer we found earlier. - if (CO->OptimizeCall(CI)) + // Loop over each of the uses of the function + for (Value::use_iterator UI = FI->use_begin(), UE = FI->use_end(); + UI != UE ; ) { - ++SimplifiedLibCalls; - break; + // If the use of the function is a call instruction + if (CallInst* CI = dyn_cast(*UI++)) + { + // Do the optimization on the CallOptimizer. + if (CO->OptimizeCall(CI)) + { + ++SimplifiedLibCalls; + found_optimization = result = true; + } + } } } } } } - } - return true; + } while (found_optimization); + return result; } namespace { @@ -138,47 +177,226 @@ { ExitInMainOptimization() : CallOptimizer("exit") {} virtual ~ExitInMainOptimization() {} - virtual bool OptimizeCall(CallInst* ci) const - { - // If the call isn't coming from main or main doesn't have external linkage - // or the return type of main is not the same as the type of the exit(3) - // argument then we don't act - if (const Function* f = ci->getParent()->getParent()) - if (!(f->hasExternalLinkage() && - (f->getReturnType() == ci->getOperand(1)->getType()) && - (f->getName() == "main"))) - return false; - // Okay, time to replace it. Get the basic block of the call instruction - BasicBlock* bb = ci->getParent(); + // Make sure the called function looks like exit (int argument, int return + // type, external linkage, not varargs). + virtual bool ValidateCalledFunction(const Function* f) const + { + if (f->getReturnType()->getTypeID() == Type::VoidTyID && !f->isVarArg()) + if (f->arg_size() == 1) + if (f->arg_begin()->getType()->isInteger()) + return true; + return false; + } - // Create a return instruction that we'll replace the call with. Note that - // the argument of the return is the argument of the call instruction. - ReturnInst* ri = new ReturnInst(ci->getOperand(1), ci); - - // Erase everything from the call instruction to the end of the block. There - // really shouldn't be anything other than the call instruction, but just in - // case there is we delete it all because its now dead. - bb->getInstList().erase(ci, bb->end()); + virtual bool OptimizeCall(CallInst* ci) const + { + // To be careful, we check that the call to exit is coming from "main", that + // main has external linkage, and the return type of main and the argument + // to exit have the same type. + Function *from = ci->getParent()->getParent(); + if (from->hasExternalLinkage()) + if (from->getReturnType() == ci->getOperand(1)->getType()) + if (from->getName() == "main") + { + // Okay, time to actually do the optimization. First, get the basic + // block of the call instruction + BasicBlock* bb = ci->getParent(); + + // Create a return instruction that we'll replace the call with. + // Note that the argument of the return is the argument of the call + // instruction. + ReturnInst* ri = new ReturnInst(ci->getOperand(1), ci); + + // Split the block at the call instruction which places it in a new + // basic block. + bb->splitBasicBlock(BasicBlock::iterator(ci)); + + // The block split caused a branch instruction to be inserted into + // the end of the original block, right after the return instruction + // that we put there. That's not a valid block, so delete the branch + // instruction. + bb->back().eraseFromParent(); + + // Now we can finally get rid of the call instruction which now lives + // in the new basic block. + ci->eraseFromParent(); - return true; + // Optimization succeeded, return true. + return true; + } + // We didn't pass the criteria for this optimization so return false + return false; } } ExitInMainOptimizer; -/// This CallOptimizer will find instances of a call to "exit" that occurs -/// within the "main" function and change it to a simple "ret" instruction with -/// the same value as passed to the exit function. It assumes that the -/// instructions after the call to exit(3) can be deleted since they are -/// unreachable anyway. -/// @brief Replace calls to exit in main with a simple return +/// This CallOptimizer will simplify a call to the strcat library function. The +/// simplification is possible only if the string being concatenated is a +/// constant array or a constant expression that results in a constant array. In +/// this case, if the array is small, we can generate a series of inline store +/// instructions to effect the concatenation without calling strcat. +/// @brief Simplify the strcat library function. struct StrCatOptimization : public CallOptimizer { StrCatOptimization() : CallOptimizer("strcat") {} virtual ~StrCatOptimization() {} + + /// @brief Make sure that the "strcat" function has the right prototype + virtual bool ValidateCalledFunction(const Function* f) const + { + if (f->getReturnType() == PointerType::get(Type::SByteTy)) + if (f->arg_size() == 2) + { + Function::const_arg_iterator AI = f->arg_begin(); + if (AI++->getType() == PointerType::get(Type::SByteTy)) + if (AI->getType() == PointerType::get(Type::SByteTy)) + return true; + } + return false; + } + + /// Perform the optimization if the length of the string concatenated + /// is reasonably short and it is a constant array. virtual bool OptimizeCall(CallInst* ci) const { + // If the thing being appended is not a GEP instruction + GetElementPtrInst* GEP = dyn_cast(ci->getOperand(2)); + if (!GEP) + return false; + + // Double check that we're dealing with a pointer to sbyte here + if (GEP->getType() != PointerType::get(Type::SByteTy)) + return false; + + // We can only optimize if the appended string is a constant + Constant* C = dyn_cast(GEP->getPointerOperand()); + if (!C) + return false; + + // Check the various kinds of constants that are applicable + GlobalVariable* GV = dyn_cast(C); + if (!GV) + return false; + + // Only GVars that have initializers will do + if (GV->hasInitializer()) + { + Constant* INTLZR = GV->getInitializer(); + // And only if that initializer is ConstantArray + if (ConstantArray* A = dyn_cast(INTLZR)) + { + assert(A->isString() && "This ought to be a string"); + + // Get the value of the string and determine its length. If the length + // is zero, we can just substitute the destination pointer for the + // call. + std::string str = A->getAsString().c_str(); + if (str.length() == 0) + { + ci->replaceAllUsesWith(ci->getOperand(1)); + ci->eraseFromParent(); + return true; + } + + // Otherwise, lets just turn this into a memcpy call which will be + // optimized out on the next pass. + else + { + // Extract some information + Module* M = ci->getParent()->getParent()->getParent(); + // We need to find the end of the string of the first operand to the + // strcat call instruction. That's where the memory is to be moved + // to. So, generate code that does that + std::vector args; + args.push_back(PointerType::get(Type::SByteTy)); + FunctionType* strlen_type = + FunctionType::get(Type::IntTy, args, false); + Function* strlen = M->getOrInsertFunction("strlen",strlen_type); + CallInst* strlen_inst = + new CallInst(strlen,ci->getOperand(1),"",ci); + + // Now that we have the string length, we must add it to the pointer + // to get the memcpy destination. + std::vector idx; + idx.push_back(strlen_inst); + GetElementPtrInst* gep = + new GetElementPtrInst(ci->getOperand(1),idx,"",ci); + + // Generate the memcpy call + args.clear(); + args.push_back(PointerType::get(Type::SByteTy)); + args.push_back(PointerType::get(Type::SByteTy)); + args.push_back(Type::IntTy); + FunctionType* memcpy_type = FunctionType::get( + PointerType::get(Type::SByteTy), args, false); + Function* memcpy = M->getOrInsertFunction("memcpy",memcpy_type); + std::vector vals; + vals.push_back(gep); + vals.push_back(ci->getOperand(2)); + vals.push_back(ConstantSInt::get(Type::IntTy,str.length()+1)); + CallInst* memcpy_inst = new CallInst(memcpy, vals, "", ci); + + // Finally, cast the result of the memcpy to the correct type which is + // the result of the strcat. + CastInst* cast_inst = + new CastInst(memcpy_inst, PointerType::get(Type::SByteTy), + ci->getName(),ci); + + // And perform the stubstitution for the strcat call. + ci->replaceAllUsesWith(cast_inst); + ci->eraseFromParent(); + return true; + } + } + else if (ConstantAggregateZero* CAZ = + dyn_cast(INTLZR)) + { + // We know this is the zero length string case so we can just avoid + // the strcat altogether. + ci->replaceAllUsesWith(ci->getOperand(1)); + ci->eraseFromParent(); + return true; + } + else if (ConstantExpr* E = dyn_cast(INTLZR)) + { + return false; + } + } + + // We didn't pass the criteria for this optimization so return false. return false; } } StrCatOptimizer; +/// This CallOptimizer will simplify a call to the memcpy library function by +/// expanding it out to a small set of stores if the copy source is a constant +/// array. +/// @brief Simplify the memcpy library function. +struct MemCpyOptimization : public CallOptimizer +{ + MemCpyOptimization() : CallOptimizer("memcpy") {} + virtual ~MemCpyOptimization() {} + + /// @brief Make sure that the "memcpy" function has the right prototype + virtual bool ValidateCalledFunction(const Function* f) const + { + if (f->getReturnType() == PointerType::get(Type::SByteTy)) + if (f->arg_size() == 2) + { + Function::const_arg_iterator AI = f->arg_begin(); + if (AI++->getType() == PointerType::get(Type::SByteTy)) + if (AI->getType() == PointerType::get(Type::SByteTy)) + return true; + } + return false; + } + + /// Perform the optimization if the length of the string concatenated + /// is reasonably short and it is a constant array. + virtual bool OptimizeCall(CallInst* ci) const + { + // We didn't pass the criteria for this optimization so return false. + return false; + } +} MemCpyOptimizer; } From lattner at cs.uiuc.edu Mon Apr 25 16:20:45 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 25 Apr 2005 16:20:45 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Message-ID: <200504252120.j3PLKj4M030910@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: SelectionDAG.cpp updated: 1.93 -> 1.94 --- Log message: implement some more logical compares with constants, so that: int foo1(int x, int y) { int t1 = x >= 0; int t2 = y >= 0; return t1 & t2; } int foo2(int x, int y) { int t1 = x == -1; int t2 = y == -1; return t1 & t2; } produces: _foo1: or r2, r4, r3 srwi r2, r2, 31 xori r3, r2, 1 blr _foo2: and r2, r4, r3 addic r2, r2, 1 li r2, 0 addze r3, r2 blr instead of: _foo1: srwi r2, r4, 31 xori r2, r2, 1 srwi r3, r3, 31 xori r3, r3, 1 and r3, r2, r3 blr _foo2: addic r2, r4, 1 li r2, 0 addze r2, r2 addic r3, r3, 1 li r3, 0 addze r3, r3 and r3, r2, r3 blr --- Diffs of the changes: (+20 -7) SelectionDAG.cpp | 27 ++++++++++++++++++++------- 1 files changed, 20 insertions(+), 7 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.93 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.94 --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.93 Mon Apr 25 16:03:25 2005 +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Mon Apr 25 16:20:28 2005 @@ -1060,17 +1060,30 @@ SDOperand LR = LHS->getOperand(1), RR = RHS->getOperand(1); ISD::CondCode Op2 = RHS->getCondition(); - // (X != 0) | (Y != 0) -> (X|Y != 0) - // (X == 0) & (Y == 0) -> (X|Y == 0) - // (X < 0) | (Y < 0) -> (X|Y < 0) if (LR == RR && isa(LR) && - cast(LR)->getValue() == 0 && Op2 == LHS->getCondition() && MVT::isInteger(LL.getValueType())) { - if ((Op2 == ISD::SETEQ && Opcode == ISD::AND) || - (Op2 == ISD::SETNE && Opcode == ISD::OR) || - (Op2 == ISD::SETLT && Opcode == ISD::OR)) + // (X != 0) | (Y != 0) -> (X|Y != 0) + // (X == 0) & (Y == 0) -> (X|Y == 0) + // (X < 0) | (Y < 0) -> (X|Y < 0) + if (cast(LR)->getValue() == 0 && + ((Op2 == ISD::SETEQ && Opcode == ISD::AND) || + (Op2 == ISD::SETNE && Opcode == ISD::OR) || + (Op2 == ISD::SETLT && Opcode == ISD::OR))) return getSetCC(Op2, VT, getNode(ISD::OR, LR.getValueType(), LL, RL), LR); + + if (cast(LR)->isAllOnesValue()) { + // (X == -1) & (Y == -1) -> (X&Y == -1) + // (X != -1) | (Y != -1) -> (X&Y != -1) + if ((Opcode == ISD::AND && Op2 == ISD::SETEQ) || + (Opcode == ISD::OR && Op2 == ISD::SETNE)) + return getSetCC(Op2, VT, + getNode(ISD::AND, LR.getValueType(), LL, RL), LR); + // (X > -1) & (Y > -1) -> (X|Y > -1) + if (Opcode == ISD::AND && Op2 == ISD::SETGT) + return getSetCC(Op2, VT, + getNode(ISD::OR, LR.getValueType(), LL, RL), LR); + } } // (X op1 Y) | (Y op2 X) -> (X op1 Y) | (X swapop2 Y) From reid at x10sys.com Mon Apr 25 16:20:48 2005 From: reid at x10sys.com (Reid Spencer) Date: Mon, 25 Apr 2005 16:20:48 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Message-ID: <200504252120.QAA02580@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: SimplifyLibCalls.cpp updated: 1.3 -> 1.4 --- Log message: Changes due to code review and new implementation: * Don't use std::string for the function names, const char* will suffice * Allow each CallOptimizer to validate the function signature before doing anything * Repeatedly loop over the functions until an iteration produces no more optimizations. This allows one optimization to insert a call that is optimized by another optimization. * Implement the ConstantArray portion of the StrCatOptimization * Provide a template for the MemCpyOptimization * Make ExitInMainOptimization split the block, not delete everything after the return instruction. (This covers revision 1.3 and 1.4, as the 1.3 comments were botched) --- Diffs of the changes: (+1 -4) SimplifyLibCalls.cpp | 5 +---- 1 files changed, 1 insertion(+), 4 deletions(-) Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.3 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.4 --- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.3 Mon Apr 25 16:11:48 2005 +++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Mon Apr 25 16:20:38 2005 @@ -104,10 +104,7 @@ } /// Make sure we get our virtual table in this file. - CallOptimizer::~CallOptimizer() - { - optlist.clear(); - } + CallOptimizer::~CallOptimizer() { } } ModulePass *llvm::createSimplifyLibCallsPass() From brukman at cs.uiuc.edu Mon Apr 25 16:23:24 2005 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Mon, 25 Apr 2005 16:23:24 -0500 Subject: [llvm-commits] CVS: llvm-test/External/PerfectClub/adm/Makefile Message-ID: <200504252123.QAA02655@zion.cs.uiuc.edu> Changes in directory llvm-test/External/PerfectClub/adm: Makefile updated: 1.2 -> 1.3 --- Log message: include Makefile.f2c before listing any source files --- Diffs of the changes: (+1 -1) Makefile | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm-test/External/PerfectClub/adm/Makefile diff -u llvm-test/External/PerfectClub/adm/Makefile:1.2 llvm-test/External/PerfectClub/adm/Makefile:1.3 --- llvm-test/External/PerfectClub/adm/Makefile:1.2 Sun Apr 24 19:42:26 2005 +++ llvm-test/External/PerfectClub/adm/Makefile Mon Apr 25 16:23:13 2005 @@ -1,7 +1,7 @@ LEVEL = ../../.. +include $(LEVEL)/Makefile.f2c Source := APSI.f -include $(LEVEL)/Makefile.f2c include ../Makefile.perfect From tbrethou at cs.uiuc.edu Mon Apr 25 16:31:12 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Mon, 25 Apr 2005 16:31:12 -0500 Subject: [llvm-commits] CVS: llvm-test/External/PerfectClub/dyfesm/ Message-ID: <200504252131.j3PLVCS6031063@apoc.cs.uiuc.edu> Changes in directory llvm-test/External/PerfectClub/dyfesm: --- Log message: Directory /home/vadve/shared/PublicCVS/llvm-test/External/PerfectClub/dyfesm added to the repository --- Diffs of the changes: (+0 -0) 0 files changed From tbrethou at cs.uiuc.edu Mon Apr 25 16:31:34 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Mon, 25 Apr 2005 16:31:34 -0500 Subject: [llvm-commits] CVS: llvm-test/External/PerfectClub/dyfesm/Makefile Message-ID: <200504252131.j3PLVYqb031079@apoc.cs.uiuc.edu> Changes in directory llvm-test/External/PerfectClub/dyfesm: Makefile added (r1.1) --- Log message: adding makefile. --- Diffs of the changes: (+7 -0) Makefile | 7 +++++++ 1 files changed, 7 insertions(+) Index: llvm-test/External/PerfectClub/dyfesm/Makefile diff -c /dev/null llvm-test/External/PerfectClub/dyfesm/Makefile:1.1 *** /dev/null Mon Apr 25 16:31:28 2005 --- llvm-test/External/PerfectClub/dyfesm/Makefile Mon Apr 25 16:31:18 2005 *************** *** 0 **** --- 1,7 ---- + LEVEL = ../../.. + include $(LEVEL)/Makefile.f2c + + Source = COUNTY.f DOEXTY.f ENTERY.f MINITY.f DOENTY.f DUMPY.f \ + EXITY.f MENDY.f SDSI.f TIMY.f TIMERS.f + + include ../Makefile.perfect From tbrethou at cs.uiuc.edu Mon Apr 25 16:31:54 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Mon, 25 Apr 2005 16:31:54 -0500 Subject: [llvm-commits] CVS: llvm-test/External/PerfectClub/flo52/Makefile Message-ID: <200504252131.j3PLVsLH031100@apoc.cs.uiuc.edu> Changes in directory llvm-test/External/PerfectClub/flo52: Makefile added (r1.1) --- Log message: Adding makefile! --- Diffs of the changes: (+7 -0) Makefile | 7 +++++++ 1 files changed, 7 insertions(+) Index: llvm-test/External/PerfectClub/flo52/Makefile diff -c /dev/null llvm-test/External/PerfectClub/flo52/Makefile:1.1 *** /dev/null Mon Apr 25 16:31:53 2005 --- llvm-test/External/PerfectClub/flo52/Makefile Mon Apr 25 16:31:43 2005 *************** *** 0 **** --- 1,7 ---- + LEVEL = ../../.. + include $(LEVEL)/Makefile.f2c + + Source = COUNTY.f DOEXTY.f ENTERY.f MINITY.f DOENTY.f DUMPY.f \ + EXITY.f MENDY.f TFSI.f TIMY.f TIMERS.f + + include ../Makefile.perfect From tbrethou at cs.uiuc.edu Mon Apr 25 16:31:39 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Mon, 25 Apr 2005 16:31:39 -0500 Subject: [llvm-commits] CVS: llvm-test/External/PerfectClub/flo52/ Message-ID: <200504252131.j3PLVds1031087@apoc.cs.uiuc.edu> Changes in directory llvm-test/External/PerfectClub/flo52: --- Log message: Directory /home/vadve/shared/PublicCVS/llvm-test/External/PerfectClub/flo52 added to the repository --- Diffs of the changes: (+0 -0) 0 files changed From tbrethou at cs.uiuc.edu Mon Apr 25 16:32:17 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Mon, 25 Apr 2005 16:32:17 -0500 Subject: [llvm-commits] CVS: llvm-test/External/PerfectClub/mdg/ Message-ID: <200504252132.j3PLWHPK031123@apoc.cs.uiuc.edu> Changes in directory llvm-test/External/PerfectClub/mdg: --- Log message: Directory /home/vadve/shared/PublicCVS/llvm-test/External/PerfectClub/mdg added to the repository --- Diffs of the changes: (+0 -0) 0 files changed From tbrethou at cs.uiuc.edu Mon Apr 25 16:33:44 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Mon, 25 Apr 2005 16:33:44 -0500 Subject: [llvm-commits] CVS: llvm-test/External/PerfectClub/trfd/Makefile Message-ID: <200504252133.j3PLXiLW031230@apoc.cs.uiuc.edu> Changes in directory llvm-test/External/PerfectClub/trfd: Makefile added (r1.1) --- Log message: Adding makefile! --- Diffs of the changes: (+7 -0) Makefile | 7 +++++++ 1 files changed, 7 insertions(+) Index: llvm-test/External/PerfectClub/trfd/Makefile diff -c /dev/null llvm-test/External/PerfectClub/trfd/Makefile:1.1 *** /dev/null Mon Apr 25 16:33:39 2005 --- llvm-test/External/PerfectClub/trfd/Makefile Mon Apr 25 16:33:29 2005 *************** *** 0 **** --- 1,7 ---- + LEVEL = ../../.. + include $(LEVEL)/Makefile.f2c + + Source = COUNTY.f DOEXTY.f ENTERY.f MINITY.f DOENTY.f DUMPY.f \ + EXITY.f MENDY.f TISI.f TIMY.f TIMERS.f + + include ../Makefile.perfect From tbrethou at cs.uiuc.edu Mon Apr 25 16:33:43 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Mon, 25 Apr 2005 16:33:43 -0500 Subject: [llvm-commits] CVS: llvm-test/External/PerfectClub/mg3d/Makefile Message-ID: <200504252133.j3PLXhIf031226@apoc.cs.uiuc.edu> Changes in directory llvm-test/External/PerfectClub/mg3d: Makefile added (r1.1) --- Log message: Adding makefile! --- Diffs of the changes: (+7 -0) Makefile | 7 +++++++ 1 files changed, 7 insertions(+) Index: llvm-test/External/PerfectClub/mg3d/Makefile diff -c /dev/null llvm-test/External/PerfectClub/mg3d/Makefile:1.1 *** /dev/null Mon Apr 25 16:33:39 2005 --- llvm-test/External/PerfectClub/mg3d/Makefile Mon Apr 25 16:33:29 2005 *************** *** 0 **** --- 1,7 ---- + LEVEL = ../../.. + include $(LEVEL)/Makefile.f2c + + Source = COUNTY.f DOEXTY.f ENTERY.f MINITY.f DOENTY.f DUMPY.f \ + EXITY.f MENDY.f SMSI.f TIMY.f TIMERS.f + + include ../Makefile.perfect From tbrethou at cs.uiuc.edu Mon Apr 25 16:32:17 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Mon, 25 Apr 2005 16:32:17 -0500 Subject: [llvm-commits] CVS: llvm-test/External/PerfectClub/mg3d/ Message-ID: <200504252132.j3PLWHwC031126@apoc.cs.uiuc.edu> Changes in directory llvm-test/External/PerfectClub/mg3d: --- Log message: Directory /home/vadve/shared/PublicCVS/llvm-test/External/PerfectClub/mg3d added to the repository --- Diffs of the changes: (+0 -0) 0 files changed From tbrethou at cs.uiuc.edu Mon Apr 25 16:33:31 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Mon, 25 Apr 2005 16:33:31 -0500 Subject: [llvm-commits] CVS: llvm-test/External/PerfectClub/mdg/Makefile Message-ID: <200504252133.j3PLXV5i031199@apoc.cs.uiuc.edu> Changes in directory llvm-test/External/PerfectClub/mdg: Makefile added (r1.1) --- Log message: Adding makefile! --- Diffs of the changes: (+7 -0) Makefile | 7 +++++++ 1 files changed, 7 insertions(+) Index: llvm-test/External/PerfectClub/mdg/Makefile diff -c /dev/null llvm-test/External/PerfectClub/mdg/Makefile:1.1 *** /dev/null Mon Apr 25 16:33:30 2005 --- llvm-test/External/PerfectClub/mdg/Makefile Mon Apr 25 16:33:20 2005 *************** *** 0 **** --- 1,7 ---- + LEVEL = ../../.. + include $(LEVEL)/Makefile.f2c + + Source = COUNTY.f DOEXTY.f ENTERY.f MINITY.f DOENTY.f DUMPY.f \ + EXITY.f MENDY.f LWSI.f TIMY.f TIMERS.f + + include ../Makefile.perfect From tbrethou at cs.uiuc.edu Mon Apr 25 16:33:44 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Mon, 25 Apr 2005 16:33:44 -0500 Subject: [llvm-commits] CVS: llvm-test/External/PerfectClub/spice/Makefile Message-ID: <200504252133.j3PLXiu5031235@apoc.cs.uiuc.edu> Changes in directory llvm-test/External/PerfectClub/spice: Makefile added (r1.1) --- Log message: Adding makefile! --- Diffs of the changes: (+7 -0) Makefile | 7 +++++++ 1 files changed, 7 insertions(+) Index: llvm-test/External/PerfectClub/spice/Makefile diff -c /dev/null llvm-test/External/PerfectClub/spice/Makefile:1.1 *** /dev/null Mon Apr 25 16:33:39 2005 --- llvm-test/External/PerfectClub/spice/Makefile Mon Apr 25 16:33:29 2005 *************** *** 0 **** --- 1,7 ---- + LEVEL = ../../.. + include $(LEVEL)/Makefile.f2c + + Source = COUNTY.f DOEXTY.f ENTERY.f MINITY.f DOENTY.f DUMPY.f \ + EXITY.f MENDY.f CSS.f TIMY.f TIMERS.f + + include ../Makefile.perfect From tbrethou at cs.uiuc.edu Mon Apr 25 16:32:17 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Mon, 25 Apr 2005 16:32:17 -0500 Subject: [llvm-commits] CVS: llvm-test/External/PerfectClub/ocean/ Message-ID: <200504252132.j3PLWHTs031138@apoc.cs.uiuc.edu> Changes in directory llvm-test/External/PerfectClub/ocean: --- Log message: Directory /home/vadve/shared/PublicCVS/llvm-test/External/PerfectClub/ocean added to the repository --- Diffs of the changes: (+0 -0) 0 files changed From tbrethou at cs.uiuc.edu Mon Apr 25 16:33:05 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Mon, 25 Apr 2005 16:33:05 -0500 Subject: [llvm-commits] CVS: llvm-test/External/PerfectClub/trfd/ Message-ID: <200504252133.j3PLX5DL031171@apoc.cs.uiuc.edu> Changes in directory llvm-test/External/PerfectClub/trfd: --- Log message: Directory /home/vadve/shared/PublicCVS/llvm-test/External/PerfectClub/trfd added to the repository --- Diffs of the changes: (+0 -0) 0 files changed From tbrethou at cs.uiuc.edu Mon Apr 25 16:33:45 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Mon, 25 Apr 2005 16:33:45 -0500 Subject: [llvm-commits] CVS: llvm-test/External/PerfectClub/qcd/Makefile Message-ID: <200504252133.j3PLXjsj031249@apoc.cs.uiuc.edu> Changes in directory llvm-test/External/PerfectClub/qcd: Makefile added (r1.1) --- Log message: Adding makefile! --- Diffs of the changes: (+7 -0) Makefile | 7 +++++++ 1 files changed, 7 insertions(+) Index: llvm-test/External/PerfectClub/qcd/Makefile diff -c /dev/null llvm-test/External/PerfectClub/qcd/Makefile:1.1 *** /dev/null Mon Apr 25 16:33:39 2005 --- llvm-test/External/PerfectClub/qcd/Makefile Mon Apr 25 16:33:29 2005 *************** *** 0 **** --- 1,7 ---- + LEVEL = ../../.. + include $(LEVEL)/Makefile.f2c + + Source = COUNTY.f DOEXTY.f ENTERY.f MINITY.f DOENTY.f DUMPY.f \ + EXITY.f MENDY.f LGSI.f TIMY.f TIMERS.f + + include ../Makefile.perfect From tbrethou at cs.uiuc.edu Mon Apr 25 16:33:44 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Mon, 25 Apr 2005 16:33:44 -0500 Subject: [llvm-commits] CVS: llvm-test/External/PerfectClub/spec77/Makefile Message-ID: <200504252133.j3PLXifQ031238@apoc.cs.uiuc.edu> Changes in directory llvm-test/External/PerfectClub/spec77: Makefile added (r1.1) --- Log message: Adding makefile! --- Diffs of the changes: (+7 -0) Makefile | 7 +++++++ 1 files changed, 7 insertions(+) Index: llvm-test/External/PerfectClub/spec77/Makefile diff -c /dev/null llvm-test/External/PerfectClub/spec77/Makefile:1.1 *** /dev/null Mon Apr 25 16:33:39 2005 --- llvm-test/External/PerfectClub/spec77/Makefile Mon Apr 25 16:33:29 2005 *************** *** 0 **** --- 1,7 ---- + LEVEL = ../../.. + include $(LEVEL)/Makefile.f2c + + Source = COUNTY.f DOEXTY.f ENTERY.f MINITY.f DOENTY.f DUMPY.f \ + EXITY.f MENDY.f WSSI.f TIMY.f TIMERS.f + + include ../Makefile.perfect From tbrethou at cs.uiuc.edu Mon Apr 25 16:32:17 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Mon, 25 Apr 2005 16:32:17 -0500 Subject: [llvm-commits] CVS: llvm-test/External/PerfectClub/track/ Message-ID: <200504252132.j3PLWHsp031155@apoc.cs.uiuc.edu> Changes in directory llvm-test/External/PerfectClub/track: --- Log message: Directory /home/vadve/shared/PublicCVS/llvm-test/External/PerfectClub/track added to the repository --- Diffs of the changes: (+0 -0) 0 files changed From tbrethou at cs.uiuc.edu Mon Apr 25 16:33:45 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Mon, 25 Apr 2005 16:33:45 -0500 Subject: [llvm-commits] CVS: llvm-test/External/PerfectClub/ocean/Makefile Message-ID: <200504252133.j3PLXiW5031245@apoc.cs.uiuc.edu> Changes in directory llvm-test/External/PerfectClub/ocean: Makefile added (r1.1) --- Log message: Adding makefile! --- Diffs of the changes: (+7 -0) Makefile | 7 +++++++ 1 files changed, 7 insertions(+) Index: llvm-test/External/PerfectClub/ocean/Makefile diff -c /dev/null llvm-test/External/PerfectClub/ocean/Makefile:1.1 *** /dev/null Mon Apr 25 16:33:39 2005 --- llvm-test/External/PerfectClub/ocean/Makefile Mon Apr 25 16:33:29 2005 *************** *** 0 **** --- 1,7 ---- + LEVEL = ../../.. + include $(LEVEL)/Makefile.f2c + + Source = COUNTY.f DOEXTY.f ENTERY.f MINITY.f DOENTY.f DUMPY.f \ + EXITY.f MENDY.f OCSI.f TIMY.f TIMERS.f + + include ../Makefile.perfect From tbrethou at cs.uiuc.edu Mon Apr 25 16:32:17 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Mon, 25 Apr 2005 16:32:17 -0500 Subject: [llvm-commits] CVS: llvm-test/External/PerfectClub/qcd/ Message-ID: <200504252132.j3PLWH20031132@apoc.cs.uiuc.edu> Changes in directory llvm-test/External/PerfectClub/qcd: --- Log message: Directory /home/vadve/shared/PublicCVS/llvm-test/External/PerfectClub/qcd added to the repository --- Diffs of the changes: (+0 -0) 0 files changed From tbrethou at cs.uiuc.edu Mon Apr 25 16:32:17 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Mon, 25 Apr 2005 16:32:17 -0500 Subject: [llvm-commits] CVS: llvm-test/External/PerfectClub/spec77/ Message-ID: <200504252132.j3PLWH4H031144@apoc.cs.uiuc.edu> Changes in directory llvm-test/External/PerfectClub/spec77: --- Log message: Directory /home/vadve/shared/PublicCVS/llvm-test/External/PerfectClub/spec77 added to the repository --- Diffs of the changes: (+0 -0) 0 files changed From tbrethou at cs.uiuc.edu Mon Apr 25 16:32:17 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Mon, 25 Apr 2005 16:32:17 -0500 Subject: [llvm-commits] CVS: llvm-test/External/PerfectClub/spice/ Message-ID: <200504252132.j3PLWHoB031150@apoc.cs.uiuc.edu> Changes in directory llvm-test/External/PerfectClub/spice: --- Log message: Directory /home/vadve/shared/PublicCVS/llvm-test/External/PerfectClub/spice added to the repository --- Diffs of the changes: (+0 -0) 0 files changed From tbrethou at cs.uiuc.edu Mon Apr 25 16:33:45 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Mon, 25 Apr 2005 16:33:45 -0500 Subject: [llvm-commits] CVS: llvm-test/External/PerfectClub/track/Makefile Message-ID: <200504252133.j3PLXiqe031241@apoc.cs.uiuc.edu> Changes in directory llvm-test/External/PerfectClub/track: Makefile added (r1.1) --- Log message: Adding makefile! --- Diffs of the changes: (+7 -0) Makefile | 7 +++++++ 1 files changed, 7 insertions(+) Index: llvm-test/External/PerfectClub/track/Makefile diff -c /dev/null llvm-test/External/PerfectClub/track/Makefile:1.1 *** /dev/null Mon Apr 25 16:33:40 2005 --- llvm-test/External/PerfectClub/track/Makefile Mon Apr 25 16:33:29 2005 *************** *** 0 **** --- 1,7 ---- + LEVEL = ../../.. + include $(LEVEL)/Makefile.f2c + + Source = COUNTY.f DOEXTY.f ENTERY.f MINITY.f DOENTY.f DUMPY.f \ + EXITY.f MENDY.f MTSI.f TIMY.f TIMERS.f + + include ../Makefile.perfect From lattner at cs.uiuc.edu Mon Apr 25 20:18:50 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 25 Apr 2005 20:18:50 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Message-ID: <200504260118.j3Q1IoT7032643@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: SelectionDAG.cpp updated: 1.94 -> 1.95 --- Log message: Fold (X > -1) | (Y > -1) --> (X&Y > -1) --- Diffs of the changes: (+3 -1) SelectionDAG.cpp | 4 +++- 1 files changed, 3 insertions(+), 1 deletion(-) Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.94 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.95 --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.94 Mon Apr 25 16:20:28 2005 +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Mon Apr 25 20:18:33 2005 @@ -1075,8 +1075,10 @@ if (cast(LR)->isAllOnesValue()) { // (X == -1) & (Y == -1) -> (X&Y == -1) // (X != -1) | (Y != -1) -> (X&Y != -1) + // (X > -1) | (Y > -1) -> (X&Y > -1) if ((Opcode == ISD::AND && Op2 == ISD::SETEQ) || - (Opcode == ISD::OR && Op2 == ISD::SETNE)) + (Opcode == ISD::OR && Op2 == ISD::SETNE) || + (Opcode == ISD::OR && Op2 == ISD::SETGT)) return getSetCC(Op2, VT, getNode(ISD::AND, LR.getValueType(), LL, RL), LR); // (X > -1) & (Y > -1) -> (X|Y > -1) From reid at x10sys.com Mon Apr 25 21:33:36 2005 From: reid at x10sys.com (Reid Spencer) Date: Mon, 25 Apr 2005 21:33:36 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/SimplifyLibCalls/2005-04-24-strcat.ll Message-ID: <200504260233.VAA05306@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/SimplifyLibCalls: 2005-04-24-strcat.ll updated: 1.3 -> 1.4 --- Log message: Fix RUN: line to not always pass. --- Diffs of the changes: (+1 -1) 2005-04-24-strcat.ll | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/test/Regression/Transforms/SimplifyLibCalls/2005-04-24-strcat.ll diff -u llvm/test/Regression/Transforms/SimplifyLibCalls/2005-04-24-strcat.ll:1.3 llvm/test/Regression/Transforms/SimplifyLibCalls/2005-04-24-strcat.ll:1.4 --- llvm/test/Regression/Transforms/SimplifyLibCalls/2005-04-24-strcat.ll:1.3 Mon Apr 25 16:08:34 2005 +++ llvm/test/Regression/Transforms/SimplifyLibCalls/2005-04-24-strcat.ll Mon Apr 25 21:33:25 2005 @@ -1,5 +1,5 @@ ; Test that the StrCatOptimizer works correctly -; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | grep -v 'call.*strcat' +; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | not grep 'call.*strcat' declare sbyte* %strcat(sbyte*,sbyte*) declare int %puts(sbyte*) From jeffc at jolt-lang.org Mon Apr 25 21:58:00 2005 From: jeffc at jolt-lang.org (Jeff Cohen) Date: Mon, 25 Apr 2005 21:58:00 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Transforms/LinkAllPasses.h Message-ID: <200504260258.VAA05479@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Transforms: LinkAllPasses.h updated: 1.18 -> 1.19 --- Log message: Add SimplyLibCalls.cpp to VC++ build --- Diffs of the changes: (+1 -0) LinkAllPasses.h | 1 + 1 files changed, 1 insertion(+) Index: llvm/include/llvm/Transforms/LinkAllPasses.h diff -u llvm/include/llvm/Transforms/LinkAllPasses.h:1.18 llvm/include/llvm/Transforms/LinkAllPasses.h:1.19 --- llvm/include/llvm/Transforms/LinkAllPasses.h:1.18 Thu Apr 21 15:57:32 2005 +++ llvm/include/llvm/Transforms/LinkAllPasses.h Mon Apr 25 21:57:49 2005 @@ -105,6 +105,7 @@ (void) llvm::createReassociatePass(); (void) llvm::createSCCPPass(); (void) llvm::createScalarReplAggregatesPass(); + (void) llvm::createSimplifyLibCallsPass(); (void) llvm::createSingleLoopExtractorPass(); (void) llvm::createSteensgaardPass(); (void) llvm::createStripSymbolsPass(); From jeffc at jolt-lang.org Mon Apr 25 21:58:00 2005 From: jeffc at jolt-lang.org (Jeff Cohen) Date: Mon, 25 Apr 2005 21:58:00 -0500 Subject: [llvm-commits] CVS: llvm/win32/Transforms/Transforms.vcproj Message-ID: <200504260258.VAA05475@zion.cs.uiuc.edu> Changes in directory llvm/win32/Transforms: Transforms.vcproj updated: 1.12 -> 1.13 --- Log message: Add SimplyLibCalls.cpp to VC++ build --- Diffs of the changes: (+3 -0) Transforms.vcproj | 3 +++ 1 files changed, 3 insertions(+) Index: llvm/win32/Transforms/Transforms.vcproj diff -u llvm/win32/Transforms/Transforms.vcproj:1.12 llvm/win32/Transforms/Transforms.vcproj:1.13 --- llvm/win32/Transforms/Transforms.vcproj:1.12 Fri Apr 15 21:51:44 2005 +++ llvm/win32/Transforms/Transforms.vcproj Mon Apr 25 21:57:49 2005 @@ -226,6 +226,9 @@ RelativePath="..\..\lib\Transforms\Ipo\RaiseAllocations.cpp"> + + From reid at x10sys.com Mon Apr 25 22:26:26 2005 From: reid at x10sys.com (Reid Spencer) Date: Mon, 25 Apr 2005 22:26:26 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Message-ID: <200504260326.WAA05666@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: SimplifyLibCalls.cpp updated: 1.4 -> 1.5 --- Log message: Incorporate feedback from Chris: * Change signatures of OptimizeCall and ValidateCalledFunction so they are non-const, allowing the optimization object to be modified. This is in support of caching things used across multiple calls. * Provide two functions for constructing and caching function types * Modify the StrCatOptimization to cache Function objects for strlen and llvm.memcpy so it doesn't regenerate them on each call site. Make sure these are invalidated each time we start the pass. * Handle both a GEP Instruction and a GEP ConstantExpr * Add additional checks to make sure we really are dealing with an arary of sbyte and that all the element initializers are ConstantInt or ConstantExpr that reduce to ConstantInt. * Make sure the GlobalVariable is constant! * Don't use ConstantArray::getString as it can fail and it doesn't give us the right thing. We must check for null bytes in the middle of the array. * Use llvm.memcpy instead of memcpy so we can factor alignment into it. * Don't use void* types in signatures, replace with sbyte* instead. --- Diffs of the changes: (+184 -102) SimplifyLibCalls.cpp | 286 ++++++++++++++++++++++++++++++++------------------- 1 files changed, 184 insertions(+), 102 deletions(-) Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.4 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.5 --- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.4 Mon Apr 25 16:20:38 2005 +++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Mon Apr 25 22:26:15 2005 @@ -72,7 +72,7 @@ /// going to be called upon to do some optimization. virtual bool ValidateCalledFunction( const Function* F ///< The function that is the target of call sites - ) const = 0; + ) = 0; /// The implementations of this function in subclasses is the heart of the /// SimplifyLibCalls algorithm. Sublcasses of this class implement @@ -85,7 +85,7 @@ /// @brief Optimize a call, if possible. virtual bool OptimizeCall( CallInst* ci ///< The call instruction that should be optimized. - ) const = 0; + ) = 0; const char * getFunctionName() const { return func_name; } private: @@ -105,6 +105,37 @@ /// Make sure we get our virtual table in this file. CallOptimizer::~CallOptimizer() { } + + /// Provide some functions for accessing standard library prototypes and + /// caching them so we don't have to keep recomputing them + FunctionType* get_strlen() + { + static FunctionType* strlen_type = 0; + if (!strlen_type) + { + std::vector args; + args.push_back(PointerType::get(Type::SByteTy)); + strlen_type = FunctionType::get(Type::IntTy, args, false); + } + return strlen_type; + } + + FunctionType* get_memcpy() + { + static FunctionType* memcpy_type = 0; + if (!memcpy_type) + { + // Note: this is for llvm.memcpy intrinsic + std::vector args; + args.push_back(PointerType::get(Type::SByteTy)); + args.push_back(PointerType::get(Type::SByteTy)); + args.push_back(Type::IntTy); + args.push_back(Type::IntTy); + memcpy_type = FunctionType::get( + PointerType::get(Type::SByteTy), args, false); + } + return memcpy_type; + } } ModulePass *llvm::createSimplifyLibCallsPass() @@ -177,7 +208,7 @@ // Make sure the called function looks like exit (int argument, int return // type, external linkage, not varargs). - virtual bool ValidateCalledFunction(const Function* f) const + virtual bool ValidateCalledFunction(const Function* f) { if (f->getReturnType()->getTypeID() == Type::VoidTyID && !f->isVarArg()) if (f->arg_size() == 1) @@ -186,7 +217,7 @@ return false; } - virtual bool OptimizeCall(CallInst* ci) const + virtual bool OptimizeCall(CallInst* ci) { // To be careful, we check that the call to exit is coming from "main", that // main has external linkage, and the return type of main and the argument @@ -207,13 +238,13 @@ // Split the block at the call instruction which places it in a new // basic block. - bb->splitBasicBlock(BasicBlock::iterator(ci)); + bb->splitBasicBlock(ci); // The block split caused a branch instruction to be inserted into // the end of the original block, right after the return instruction // that we put there. That's not a valid block, so delete the branch // instruction. - bb->back().eraseFromParent(); + bb->getInstList().pop_back(); // Now we can finally get rid of the call instruction which now lives // in the new basic block. @@ -235,11 +266,33 @@ /// @brief Simplify the strcat library function. struct StrCatOptimization : public CallOptimizer { - StrCatOptimization() : CallOptimizer("strcat") {} +private: + Function* strlen_func; + Function* memcpy_func; +public: + StrCatOptimization() + : CallOptimizer("strcat") + , strlen_func(0) + , memcpy_func(0) + {} virtual ~StrCatOptimization() {} + inline Function* get_strlen_func(Module*M) + { + if (strlen_func) + return strlen_func; + return strlen_func = M->getOrInsertFunction("strlen",get_strlen()); + } + + inline Function* get_memcpy_func(Module* M) + { + if (memcpy_func) + return memcpy_func; + return memcpy_func = M->getOrInsertFunction("llvm.memcpy",get_memcpy()); + } + /// @brief Make sure that the "strcat" function has the right prototype - virtual bool ValidateCalledFunction(const Function* f) const + virtual bool ValidateCalledFunction(const Function* f) { if (f->getReturnType() == PointerType::get(Type::SByteTy)) if (f->arg_size() == 2) @@ -247,117 +300,143 @@ Function::const_arg_iterator AI = f->arg_begin(); if (AI++->getType() == PointerType::get(Type::SByteTy)) if (AI->getType() == PointerType::get(Type::SByteTy)) + { + // Invalidate the pre-computed strlen_func and memcpy_func Functions + // because, by definition, this method is only called when a new + // Module is being traversed. Invalidation causes re-computation for + // the new Module (if necessary). + strlen_func = 0; + memcpy_func = 0; + + // Indicate this is a suitable call type. return true; + } } return false; } /// Perform the optimization if the length of the string concatenated /// is reasonably short and it is a constant array. - virtual bool OptimizeCall(CallInst* ci) const + virtual bool OptimizeCall(CallInst* ci) { - // If the thing being appended is not a GEP instruction - GetElementPtrInst* GEP = dyn_cast(ci->getOperand(2)); - if (!GEP) + User* GEP = 0; + // If the thing being appended is not a GEP instruction nor a constant + // expression with a GEP instruction, then return false because this is + // not a situation we can optimize. + if (GetElementPtrInst* GEPI = + dyn_cast(ci->getOperand(2))) + GEP = GEPI; + else if (ConstantExpr* CE = dyn_cast(ci->getOperand(2))) + if (CE->getOpcode() == Instruction::GetElementPtr) + GEP = CE; + else + return false; + else return false; - // Double check that we're dealing with a pointer to sbyte here - if (GEP->getType() != PointerType::get(Type::SByteTy)) + // Check to make sure that the first operand of the GEP is an integer and + // has value 0 so that we are sure we're indexing into the initializer. + if (ConstantInt* op1 = dyn_cast(GEP->getOperand(1))) + if (op1->isNullValue()) + ; + else + return false; + else return false; - // We can only optimize if the appended string is a constant - Constant* C = dyn_cast(GEP->getPointerOperand()); - if (!C) + // Ensure that the second operand is a constant int. If it isn't then this + // GEP is wonky and we're not really sure what were referencing into and + // better of not optimizing it. + if (!dyn_cast(GEP->getOperand(2))) return false; - // Check the various kinds of constants that are applicable - GlobalVariable* GV = dyn_cast(C); - if (!GV) + // The GEP instruction, constant or instruction, must reference a global + // variable that is a constant and is initialized. The referenced constant + // initializer is the array that we'll use for optimization. + GlobalVariable* GV = dyn_cast(GEP->getOperand(0)); + if (!GV || !GV->isConstant() || !GV->hasInitializer()) return false; - // Only GVars that have initializers will do - if (GV->hasInitializer()) + // Get the initializer + Constant* INTLZR = GV->getInitializer(); + + // Handle the ConstantArray case. + if (ConstantArray* A = dyn_cast(INTLZR)) { - Constant* INTLZR = GV->getInitializer(); - // And only if that initializer is ConstantArray - if (ConstantArray* A = dyn_cast(INTLZR)) - { - assert(A->isString() && "This ought to be a string"); + // First off, we can't do this if the constant array isn't a string, + // meaning its base type is sbyte and its constant initializers for all + // the elements are constantInt or constantInt expressions. + if (!A->isString()) + return false; - // Get the value of the string and determine its length. If the length - // is zero, we can just substitute the destination pointer for the - // call. - std::string str = A->getAsString().c_str(); - if (str.length() == 0) + // Now we need to examine the source string to find its actual length. We + // can't rely on the size of the constant array becasue there could be a + // null terminator in the middle of the array. We also have to bail out if + // we find a non-integer constant initializer of one of the elements. + // Also, if we never find a terminator before the end of the array. + unsigned max_elems = A->getType()->getNumElements(); + unsigned len = 0; + for (; len < max_elems; len++) + { + if (ConstantInt* CI = dyn_cast(A->getOperand(len))) { - ci->replaceAllUsesWith(ci->getOperand(1)); - ci->eraseFromParent(); - return true; + if (CI->isNullValue()) + break; // we found end of string } - - // Otherwise, lets just turn this into a memcpy call which will be - // optimized out on the next pass. else - { - // Extract some information - Module* M = ci->getParent()->getParent()->getParent(); - // We need to find the end of the string of the first operand to the - // strcat call instruction. That's where the memory is to be moved - // to. So, generate code that does that - std::vector args; - args.push_back(PointerType::get(Type::SByteTy)); - FunctionType* strlen_type = - FunctionType::get(Type::IntTy, args, false); - Function* strlen = M->getOrInsertFunction("strlen",strlen_type); - CallInst* strlen_inst = - new CallInst(strlen,ci->getOperand(1),"",ci); - - // Now that we have the string length, we must add it to the pointer - // to get the memcpy destination. - std::vector idx; - idx.push_back(strlen_inst); - GetElementPtrInst* gep = - new GetElementPtrInst(ci->getOperand(1),idx,"",ci); - - // Generate the memcpy call - args.clear(); - args.push_back(PointerType::get(Type::SByteTy)); - args.push_back(PointerType::get(Type::SByteTy)); - args.push_back(Type::IntTy); - FunctionType* memcpy_type = FunctionType::get( - PointerType::get(Type::SByteTy), args, false); - Function* memcpy = M->getOrInsertFunction("memcpy",memcpy_type); - std::vector vals; - vals.push_back(gep); - vals.push_back(ci->getOperand(2)); - vals.push_back(ConstantSInt::get(Type::IntTy,str.length()+1)); - CallInst* memcpy_inst = new CallInst(memcpy, vals, "", ci); - - // Finally, cast the result of the memcpy to the correct type which is - // the result of the strcat. - CastInst* cast_inst = - new CastInst(memcpy_inst, PointerType::get(Type::SByteTy), - ci->getName(),ci); - - // And perform the stubstitution for the strcat call. - ci->replaceAllUsesWith(cast_inst); - ci->eraseFromParent(); - return true; - } - } - else if (ConstantAggregateZero* CAZ = - dyn_cast(INTLZR)) - { - // We know this is the zero length string case so we can just avoid - // the strcat altogether. - ci->replaceAllUsesWith(ci->getOperand(1)); - ci->eraseFromParent(); - return true; - } - else if (ConstantExpr* E = dyn_cast(INTLZR)) - { - return false; + return false; // This array isn't suitable, non-int initializer } + if (len >= max_elems) + return false; // This array isn't null terminated + else + len++; // increment for null terminator + + // Extract some information from the instruction + Module* M = ci->getParent()->getParent()->getParent(); + + // We need to find the end of the destination string. That's where the + // memory is to be moved to. We just generate a call to strlen (further + // optimized in another pass). Note that the get_strlen_func() call + // caches the Function* for us. + CallInst* strlen_inst = + new CallInst(get_strlen_func(M),ci->getOperand(1),"",ci); + + // Now that we have the destination's length, we must index into the + // destination's pointer to get the actual memcpy destination (end of + // the string .. we're concatenating). + std::vector idx; + idx.push_back(strlen_inst); + GetElementPtrInst* gep = + new GetElementPtrInst(ci->getOperand(1),idx,"",ci); + + // We have enough information to now generate the memcpy call to + // do the concatenation for us. + std::vector vals; + vals.push_back(gep); // destination + vals.push_back(ci->getOperand(2)); // source + vals.push_back(ConstantSInt::get(Type::IntTy,len)); // length + vals.push_back(ConstantSInt::get(Type::IntTy,1)); // alignment + CallInst* memcpy_inst = + new CallInst(get_memcpy_func(M), vals, "", ci); + + // Finally, substitute the first operand of the strcat call for the + // strcat call itself since strcat returns its first operand; and, + // kill the strcat CallInst. + ci->replaceAllUsesWith(ci->getOperand(1)); + ci->eraseFromParent(); + return true; + } + + // Handle the ConstantAggregateZero case + else if (ConstantAggregateZero* CAZ = + dyn_cast(INTLZR)) + { + // We know this is the zero length string case so we can just avoid + // the strcat altogether and replace the CallInst with its first operand + // (what strcat returns). + ci->replaceAllUsesWith(ci->getOperand(1)); + ci->eraseFromParent(); + return true; } // We didn't pass the criteria for this optimization so return false. @@ -371,18 +450,20 @@ /// @brief Simplify the memcpy library function. struct MemCpyOptimization : public CallOptimizer { - MemCpyOptimization() : CallOptimizer("memcpy") {} + MemCpyOptimization() : CallOptimizer("llvm.memcpy") {} virtual ~MemCpyOptimization() {} /// @brief Make sure that the "memcpy" function has the right prototype - virtual bool ValidateCalledFunction(const Function* f) const + virtual bool ValidateCalledFunction(const Function* f) { - if (f->getReturnType() == PointerType::get(Type::SByteTy)) + if (f->getReturnType() == PointerType::get(Type::VoidTy)) if (f->arg_size() == 2) { Function::const_arg_iterator AI = f->arg_begin(); if (AI++->getType() == PointerType::get(Type::SByteTy)) - if (AI->getType() == PointerType::get(Type::SByteTy)) + if (AI++->getType() == PointerType::get(Type::SByteTy)) + if (AI++->getType() == Type::IntTy) + if (AI->getType() == Type::IntTy) return true; } return false; @@ -390,8 +471,9 @@ /// Perform the optimization if the length of the string concatenated /// is reasonably short and it is a constant array. - virtual bool OptimizeCall(CallInst* ci) const + virtual bool OptimizeCall(CallInst* ci) { + // // We didn't pass the criteria for this optimization so return false. return false; } From duraid at octopus.com.au Mon Apr 25 22:44:16 2005 From: duraid at octopus.com.au (Duraid Madina) Date: Mon, 25 Apr 2005 22:44:16 -0500 Subject: [llvm-commits] CVS: llvm-test/MultiSource/Applications/SPASS/Makefile Message-ID: <200504260344.WAA05728@zion.cs.uiuc.edu> Changes in directory llvm-test/MultiSource/Applications/SPASS: Makefile updated: 1.2 -> 1.3 --- Log message: (llc/cbe/native builds were built differently, oops) --- Diffs of the changes: (+1 -1) Makefile | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm-test/MultiSource/Applications/SPASS/Makefile diff -u llvm-test/MultiSource/Applications/SPASS/Makefile:1.2 llvm-test/MultiSource/Applications/SPASS/Makefile:1.3 --- llvm-test/MultiSource/Applications/SPASS/Makefile:1.2 Sun Apr 24 23:43:19 2005 +++ llvm-test/MultiSource/Applications/SPASS/Makefile Mon Apr 25 22:44:05 2005 @@ -1,7 +1,7 @@ LEVEL = ../../.. PROG = SPASS -CFLAGS = -DCLOCK_NO_TIMING -w -DNO_MEMORY_MANAGEMENT +CPPFLAGS = -DCLOCK_NO_TIMING -w -DNO_MEMORY_MANAGEMENT LDFLAGS = -lm RUN_OPTIONS="$(PROJ_SRC_DIR)/problem.dfg" From duraid at octopus.com.au Mon Apr 25 23:51:39 2005 From: duraid at octopus.com.au (Duraid Madina) Date: Mon, 25 Apr 2005 23:51:39 -0500 Subject: [llvm-commits] CVS: llvm-test/MultiSource/Applications/SPASS/Makefile Message-ID: <200504260451.XAA05953@zion.cs.uiuc.edu> Changes in directory llvm-test/MultiSource/Applications/SPASS: Makefile updated: 1.3 -> 1.4 --- Log message: unfortunately, using plain old malloc() breaks CBE on ia64 (claims to be running out of memory but it shouldn't be) so for now, back this out --- Diffs of the changes: (+1 -1) Makefile | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm-test/MultiSource/Applications/SPASS/Makefile diff -u llvm-test/MultiSource/Applications/SPASS/Makefile:1.3 llvm-test/MultiSource/Applications/SPASS/Makefile:1.4 --- llvm-test/MultiSource/Applications/SPASS/Makefile:1.3 Mon Apr 25 22:44:05 2005 +++ llvm-test/MultiSource/Applications/SPASS/Makefile Mon Apr 25 23:51:28 2005 @@ -1,7 +1,7 @@ LEVEL = ../../.. PROG = SPASS -CPPFLAGS = -DCLOCK_NO_TIMING -w -DNO_MEMORY_MANAGEMENT +CPPFLAGS = -DCLOCK_NO_TIMING -w LDFLAGS = -lm RUN_OPTIONS="$(PROJ_SRC_DIR)/problem.dfg" From reid at x10sys.com Tue Apr 26 00:22:49 2005 From: reid at x10sys.com (Reid Spencer) Date: Tue, 26 Apr 2005 00:22:49 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/SimplifyLibCalls/ExitInMain.ll StrCat.ll StrLen.ll 2005-04-24-ExitInMain.ll 2005-04-24-strcat.ll Message-ID: <200504260522.AAA06106@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/SimplifyLibCalls: ExitInMain.ll added (r1.1) StrCat.ll added (r1.1) StrLen.ll added (r1.1) 2005-04-24-ExitInMain.ll (r1.2) removed 2005-04-24-strcat.ll (r1.4) removed --- Log message: * Add a test case for StrLenOptimization * Rename ExitInMain and StrCat tests so they don't have the date the regression was entered since they are feature tests, not regressions. --- Diffs of the changes: (+58 -0) ExitInMain.ll | 13 +++++++++++++ StrCat.ll | 24 ++++++++++++++++++++++++ StrLen.ll | 21 +++++++++++++++++++++ 3 files changed, 58 insertions(+) Index: llvm/test/Regression/Transforms/SimplifyLibCalls/ExitInMain.ll diff -c /dev/null llvm/test/Regression/Transforms/SimplifyLibCalls/ExitInMain.ll:1.1 *** /dev/null Tue Apr 26 00:22:48 2005 --- llvm/test/Regression/Transforms/SimplifyLibCalls/ExitInMain.ll Tue Apr 26 00:22:38 2005 *************** *** 0 **** --- 1,13 ---- + ; Test that the ExitInMainOptimization pass works correctly + ; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | grep -c 'ret int 3' | grep 1 + + declare void %exit(int) + declare void %exitonly(int) + + implementation ; Functions: + + int %main () { + call void %exitonly ( int 3 ) + call void %exit ( int 3 ) + ret int 0 + } Index: llvm/test/Regression/Transforms/SimplifyLibCalls/StrCat.ll diff -c /dev/null llvm/test/Regression/Transforms/SimplifyLibCalls/StrCat.ll:1.1 *** /dev/null Tue Apr 26 00:22:49 2005 --- llvm/test/Regression/Transforms/SimplifyLibCalls/StrCat.ll Tue Apr 26 00:22:38 2005 *************** *** 0 **** --- 1,24 ---- + ; Test that the StrCatOptimizer works correctly + ; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | not grep 'call.*strcat' + + declare sbyte* %strcat(sbyte*,sbyte*) + declare int %puts(sbyte*) + %hello = constant [6 x sbyte] c"hello\00" + %null = constant [1 x sbyte] c"\00" + %null_hello = constant [7 x sbyte] c"\00hello\00" + + implementation ; Functions: + + int %main () { + %target = alloca [1024 x sbyte] + %arg1 = getelementptr [1024 x sbyte]* %target, int 0, int 0 + store sbyte 0, sbyte* %arg1 + %arg2 = getelementptr [6 x sbyte]* %hello, int 0, int 0 + %rslt1 = call sbyte* %strcat(sbyte* %arg1, sbyte* %arg2) + %arg3 = getelementptr [1 x sbyte]* %null, int 0, int 0 + %rslt2 = call sbyte* %strcat(sbyte* %rslt1, sbyte* %arg3) + %arg4 = getelementptr [7 x sbyte]* %null_hello, int 0, int 0 + %rslt3 = call sbyte* %strcat(sbyte* %rslt2, sbyte* %arg4) + call int %puts(sbyte* %rslt3) + ret int 0 + } Index: llvm/test/Regression/Transforms/SimplifyLibCalls/StrLen.ll diff -c /dev/null llvm/test/Regression/Transforms/SimplifyLibCalls/StrLen.ll:1.1 *** /dev/null Tue Apr 26 00:22:49 2005 --- llvm/test/Regression/Transforms/SimplifyLibCalls/StrLen.ll Tue Apr 26 00:22:38 2005 *************** *** 0 **** --- 1,21 ---- + ; Test that the StrCatOptimizer works correctly + ; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | not grep 'call.*strlen' + + declare int %strlen(sbyte*) + %hello = constant [6 x sbyte] c"hello\00" + %null = constant [1 x sbyte] c"\00" + %null_hello = constant [7 x sbyte] c"\00hello\00" + + implementation ; Functions: + + int %main () { + %hello_p = getelementptr [6 x sbyte]* %hello, int 0, int 0 + %hello_l = call int %strlen(sbyte* %hello_p) + %null_p = getelementptr [1 x sbyte]* %null, int 0, int 0 + %null_l = call int %strlen(sbyte* %null_p) + %null_hello_p = getelementptr [7 x sbyte]* %null_hello, int 0, int 0 + %null_hello_l = call int %strlen(sbyte* %null_hello_p) + %sum1 = add int %hello_l, %null_l + %sum2 = add int %sum1, %null_hello_l + ret int %sum2 + } From reid at x10sys.com Tue Apr 26 00:24:11 2005 From: reid at x10sys.com (Reid Spencer) Date: Tue, 26 Apr 2005 00:24:11 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Message-ID: <200504260524.AAA06124@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: SimplifyLibCalls.cpp updated: 1.5 -> 1.6 --- Log message: * Implement StrLenOptimization * Factor out commonalities between StrLenOptimization and StrCatOptimization * Make sure that signatures return sbyte* not void* --- Diffs of the changes: (+137 -52) SimplifyLibCalls.cpp | 189 ++++++++++++++++++++++++++++++++++++--------------- 1 files changed, 137 insertions(+), 52 deletions(-) Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.5 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.6 --- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.5 Mon Apr 25 22:26:15 2005 +++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Tue Apr 26 00:24:00 2005 @@ -136,6 +136,79 @@ } return memcpy_type; } + + // Provide some utility functions for various checks common to more than + // one CallOptimizer + Constant* get_GVInitializer(Value* V) + { + User* GEP = 0; + // If the value not a GEP instruction nor a constant expression with a GEP + // instruction, then return 0 because ConstantArray can't occur any other + // way + if (GetElementPtrInst* GEPI = dyn_cast(V)) + GEP = GEPI; + else if (ConstantExpr* CE = dyn_cast(V)) + if (CE->getOpcode() == Instruction::GetElementPtr) + GEP = CE; + else + return 0; + else + return 0; + + // Check to make sure that the first operand of the GEP is an integer and + // has value 0 so that we are sure we're indexing into the initializer. + if (ConstantInt* op1 = dyn_cast(GEP->getOperand(1))) + if (op1->isNullValue()) + ; + else + return false; + else + return false; + + // Ensure that the second operand is a ConstantInt. If it isn't then this + // GEP is wonky and we're not really sure what were referencing into and + // better of not optimizing it. + if (!dyn_cast(GEP->getOperand(2))) + return 0; + + // The GEP instruction, constant or instruction, must reference a global + // variable that is a constant and is initialized. The referenced constant + // initializer is the array that we'll use for optimization. + GlobalVariable* GV = dyn_cast(GEP->getOperand(0)); + if (!GV || !GV->isConstant() || !GV->hasInitializer()) + return 0; + + // Return the result + return GV->getInitializer(); + } + + /// A function to compute the length of a null-terminated string of integers. + /// This function can't rely on the size of the constant array because there + /// could be a null terminator in the middle of the array. We also have to + /// bail out if we find a non-integer constant initializer of one of the + /// elements or if there is no null-terminator. The logic below checks + bool getCharArrayLength(ConstantArray* A, unsigned& len) + { + assert(A != 0 && "Invalid args to getCharArrayLength"); + // Get the supposed length + unsigned max_elems = A->getType()->getNumElements(); + len = 0; + // Examine all the elements + for (; len < max_elems; len++) + { + if (ConstantInt* CI = dyn_cast(A->getOperand(len))) + { + // Check for the null terminator + if (CI->isNullValue()) + break; // we found end of string + } + else + return false; // This array isn't suitable, non-int initializer + } + if (len >= max_elems) + return false; // This array isn't null terminated + return true; // success! + } } ModulePass *llvm::createSimplifyLibCallsPass() @@ -319,47 +392,13 @@ /// is reasonably short and it is a constant array. virtual bool OptimizeCall(CallInst* ci) { - User* GEP = 0; - // If the thing being appended is not a GEP instruction nor a constant - // expression with a GEP instruction, then return false because this is - // not a situation we can optimize. - if (GetElementPtrInst* GEPI = - dyn_cast(ci->getOperand(2))) - GEP = GEPI; - else if (ConstantExpr* CE = dyn_cast(ci->getOperand(2))) - if (CE->getOpcode() == Instruction::GetElementPtr) - GEP = CE; - else - return false; - else - return false; - - // Check to make sure that the first operand of the GEP is an integer and - // has value 0 so that we are sure we're indexing into the initializer. - if (ConstantInt* op1 = dyn_cast(GEP->getOperand(1))) - if (op1->isNullValue()) - ; - else - return false; - else - return false; - - // Ensure that the second operand is a constant int. If it isn't then this - // GEP is wonky and we're not really sure what were referencing into and - // better of not optimizing it. - if (!dyn_cast(GEP->getOperand(2))) - return false; - - // The GEP instruction, constant or instruction, must reference a global - // variable that is a constant and is initialized. The referenced constant - // initializer is the array that we'll use for optimization. - GlobalVariable* GV = dyn_cast(GEP->getOperand(0)); - if (!GV || !GV->isConstant() || !GV->hasInitializer()) + // Extract the initializer (while making numerous checks) from the + // source operand of the call to strcat. If we get null back, one of + // a variety of checks in get_GVInitializer failed + Constant* INTLZR = get_GVInitializer(ci->getOperand(2)); + if (!INTLZR) return false; - // Get the initializer - Constant* INTLZR = GV->getInitializer(); - // Handle the ConstantArray case. if (ConstantArray* A = dyn_cast(INTLZR)) { @@ -376,18 +415,8 @@ // Also, if we never find a terminator before the end of the array. unsigned max_elems = A->getType()->getNumElements(); unsigned len = 0; - for (; len < max_elems; len++) - { - if (ConstantInt* CI = dyn_cast(A->getOperand(len))) - { - if (CI->isNullValue()) - break; // we found end of string - } - else - return false; // This array isn't suitable, non-int initializer - } - if (len >= max_elems) - return false; // This array isn't null terminated + if (!getCharArrayLength(A,len)) + return false; else len++; // increment for null terminator @@ -444,6 +473,62 @@ } } StrCatOptimizer; +/// This CallOptimizer will simplify a call to the strlen library function by +/// replacing it with a constant value if the string provided to it is a +/// constant array. +/// @brief Simplify the strlen library function. +struct StrLenOptimization : public CallOptimizer +{ + StrLenOptimization() : CallOptimizer("strlen") {} + virtual ~StrLenOptimization() {} + + /// @brief Make sure that the "strlen" function has the right prototype + virtual bool ValidateCalledFunction(const Function* f) + { + if (f->getReturnType() == Type::IntTy) + if (f->arg_size() == 1) + if (Function::const_arg_iterator AI = f->arg_begin()) + if (AI->getType() == PointerType::get(Type::SByteTy)) + return true; + return false; + } + + /// @brief Perform the strlen optimization + virtual bool OptimizeCall(CallInst* ci) + { + // Extract the initializer (while making numerous checks) from the + // source operand of the call to strlen. If we get null back, one of + // a variety of checks in get_GVInitializer failed + Constant* INTLZR = get_GVInitializer(ci->getOperand(1)); + if (!INTLZR) + return false; + + if (ConstantArray* A = dyn_cast(INTLZR)) + { + unsigned len = 0; + if (!getCharArrayLength(A,len)) + return false; + ci->replaceAllUsesWith(ConstantInt::get(Type::IntTy,len)); + ci->eraseFromParent(); + return true; + } + + // Handle the ConstantAggregateZero case + else if (ConstantAggregateZero* CAZ = + dyn_cast(INTLZR)) + { + // We know this is the zero length string case so we can just avoid + // the strlen altogether and replace the CallInst with zero + ci->replaceAllUsesWith(ConstantInt::get(Type::IntTy,0)); + ci->eraseFromParent(); + return true; + } + + // We didn't pass the criteria for this optimization so return false. + return false; + } +} StrLenOptimizer; + /// This CallOptimizer will simplify a call to the memcpy library function by /// expanding it out to a small set of stores if the copy source is a constant /// array. @@ -456,7 +541,7 @@ /// @brief Make sure that the "memcpy" function has the right prototype virtual bool ValidateCalledFunction(const Function* f) { - if (f->getReturnType() == PointerType::get(Type::VoidTy)) + if (f->getReturnType() == PointerType::get(Type::SByteTy)) if (f->arg_size() == 2) { Function::const_arg_iterator AI = f->arg_begin(); From duraid at octopus.com.au Tue Apr 26 02:23:13 2005 From: duraid at octopus.com.au (Duraid Madina) Date: Tue, 26 Apr 2005 02:23:13 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/IA64/IA64ISelPattern.cpp Message-ID: <200504260723.CAA06726@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/IA64: IA64ISelPattern.cpp updated: 1.26 -> 1.27 --- Log message: * Add code to reduce multiplies by constant integers to shifts, adds and subtracts. This is a very rough and nasty implementation of Lefevre's "pattern finding" algorithm. With a few small changes though, it should end up beating most other methods in common use, regardless of the size of the constant (currently, it's often one or two shifts worse) TODO: rewrite it so it's not hideously ugly (this is a translation from perl, which doesn't help ;) bypass most of it for multiplies by 2^n+1 (eventually) teach it that some combinations of shift+add are cheaper than others (e.g. shladd on ia64, scaled adds on alpha) get it to try multiple booth encodings in search of the cheapest routine make it work for negative constants This is hacked up as a DAG->DAG transform, so once I clean it up I hope it'll be pulled out of here and put somewhere else. The only thing backends should really have to worry about for now is where to draw the line between using this code vs. going ahead and doing an integer multiply anyway. --- Diffs of the changes: (+439 -15) IA64ISelPattern.cpp | 454 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 439 insertions(+), 15 deletions(-) Index: llvm/lib/Target/IA64/IA64ISelPattern.cpp diff -u llvm/lib/Target/IA64/IA64ISelPattern.cpp:1.26 llvm/lib/Target/IA64/IA64ISelPattern.cpp:1.27 --- llvm/lib/Target/IA64/IA64ISelPattern.cpp:1.26 Fri Apr 22 12:54:15 2005 +++ llvm/lib/Target/IA64/IA64ISelPattern.cpp Tue Apr 26 02:23:02 2005 @@ -28,6 +28,7 @@ #include "llvm/Support/MathExtras.h" #include "llvm/ADT/Statistic.h" #include +#include #include using namespace llvm; @@ -412,6 +413,9 @@ /// IA64Lowering - This object fully describes how to lower LLVM code to an /// IA64-specific SelectionDAG. IA64TargetLowering IA64Lowering; + SelectionDAG *ISelDAG; // Hack to support us having a dag->dag transform + // for sdiv and udiv until it is put into the future + // dag combiner /// ExprMap - As shared expressions are codegen'd, we keep track of which /// vreg the value is produced in, so we only emit one copy of each compiled @@ -420,8 +424,8 @@ std::set LoweredTokens; public: - ISel(TargetMachine &TM) : SelectionDAGISel(IA64Lowering), IA64Lowering(TM) { - } + ISel(TargetMachine &TM) : SelectionDAGISel(IA64Lowering), IA64Lowering(TM), + ISelDAG(0) { } /// InstructionSelectBasicBlock - This callback is invoked by /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. @@ -429,6 +433,9 @@ unsigned SelectExpr(SDOperand N); void Select(SDOperand N); + // a dag->dag to transform mul-by-constant-int to shifts+adds/subs + SDOperand BuildConstmulSequence(SDOperand N); + }; } @@ -437,11 +444,419 @@ void ISel::InstructionSelectBasicBlock(SelectionDAG &DAG) { // Codegen the basic block. + ISelDAG = &DAG; Select(DAG.getRoot()); // Clear state used for selection. ExprMap.clear(); LoweredTokens.clear(); + ISelDAG = 0; +} + +const char sign[2]={'+','-'}; + + +// strip leading '0' characters from a string +void munchLeadingZeros(std::string& inString) { + while(inString.c_str()[0]=='0') { + inString.erase(0, 1); + } +} + +// strip trailing '0' characters from a string +void munchTrailingZeros(std::string& inString) { + int curPos=inString.length()-1; + + while(inString.c_str()[curPos]=='0') { + inString.erase(curPos, 1); + curPos--; + } +} + +// return how many consecutive '0' characters are at the end of a string +unsigned int countTrailingZeros(std::string& inString) { + int curPos=inString.length()-1; + unsigned int zeroCount=0; + // assert goes here + while(inString.c_str()[curPos--]=='0') { + zeroCount++; + } + return zeroCount; +} + +// booth encode a string of '1' and '0' characters (returns string of 'P' (+1) +// '0' and 'N' (-1) characters) +void boothEncode(std::string inString, std::string& boothEncodedString) { + + int curpos=0; + int replacements=0; + int lim=inString.size(); + + while(curpos1) { + inString.replace(curpos, runlength+1, replaceString); + curpos+=runlength-1; + } else + curpos++; + } else { // a zero, we just keep chugging along + curpos++; + } + } + + // clean up (trim the string, reverse it and turn '1's into 'P's) + munchTrailingZeros(inString); + boothEncodedString=""; + + for(int i=inString.size()-1;i>=0;i--) + if(inString[i]=='1') + boothEncodedString+="P"; + else + boothEncodedString+=inString[i]; + +} + +struct shiftaddblob { // this encodes stuff like (x=) "A << B [+-] C << D" + unsigned firstVal; // A + unsigned firstShift; // B + unsigned secondVal; // C + unsigned secondShift; // D + bool isSub; +}; + +/* this implements Lefevre's "pattern-based" constant multiplication, + * see "Multiplication by an Integer Constant", INRIA report 1999-06 + * + * TODO: implement a method to try rewriting P0N<->0PP / N0P<->0NN + * to get better booth encodings - this does help in practice + * TODO: weight shifts appropriately (most architectures can't + * fuse a shift and an add for arbitrary shift amounts) */ +unsigned lefevre(const std::string inString, + std::vector &ops) { + std::string retstring; + std::string s = inString; + munchTrailingZeros(s); + + int length=s.length()-1; + + if(length==0) { + return(0); + } + + std::vector p,n; + + for(int i=0; i<=length; i++) { + if (s.c_str()[length-i]=='P') { + p.push_back(i); + } else if (s.c_str()[length-i]=='N') { + n.push_back(i); + } + } + + std::string t, u; + int c,f; + std::map w; + + for(int i=0; i::const_iterator ii; + std::vector d; + std::multimap sorted_by_value; + + for(ii = w.begin(); ii!=w.end(); ii++) + sorted_by_value.insert(std::pair((*ii).second,(*ii).first)); + + for (std::multimap::iterator it = sorted_by_value.begin(); + it != sorted_by_value.end(); ++it) { + d.push_back((*it).second); + } + + int int_W=0; + int int_d; + + while(d.size()>0 && (w[int_d=d.back()] > int_W)) { + d.pop_back(); + retstring=s; // hmmm + int x=0; + int z=abs(int_d)-1; + + if(int_d>0) { + + for(int base=0; baseint_W) { + int_W = x; + t = retstring; + c = int_d; // tofix + } + + } d.pop_back(); // hmm + + u = t; + + for(int i=0; i(N.getOperand(1))->getValue(); + + bool flippedSign; + unsigned preliminaryShift=0; + + assert(constant > 0 && "erk, don't multiply by zero or negative nums\n"); + + // first, we make the constant to multiply by positive + if(constant<0) { + constant=-constant; + flippedSign=true; + } else { + flippedSign=false; + } + + // next, we make it odd. + for(; (constant%2==0); preliminaryShift++) + constant>>=1; + + //OK, we have a positive, odd number of 64 bits or less. Convert it + //to a binary string, constantString[0] is the LSB + char constantString[65]; + for(int i=0; i<64; i++) + constantString[i]='0'+((constant>>i)&0x1); + constantString[64]=0; + + // now, Booth encode it + std::string boothEncodedString; + boothEncode(constantString, boothEncodedString); + + std::vector ops; + // do the transformation, filling out 'ops' + lefevre(boothEncodedString, ops); + + SDOperand results[ops.size()]; // temporary results (of adds/subs of shifts) + + // now turn 'ops' into DAG bits + for(int i=0; igetConstant(ops[i].firstShift, MVT::i64); + SDOperand val = (ops[i].firstVal == 0) ? N.getOperand(0) : + results[ops[i].firstVal-1]; + SDOperand left = ISelDAG->getNode(ISD::SHL, MVT::i64, val, amt); + amt = ISelDAG->getConstant(ops[i].secondShift, MVT::i64); + val = (ops[i].secondVal == 0) ? N.getOperand(0) : + results[ops[i].secondVal-1]; + SDOperand right = ISelDAG->getNode(ISD::SHL, MVT::i64, val, amt); + if(ops[i].isSub) + results[i] = ISelDAG->getNode(ISD::SUB, MVT::i64, left, right); + else + results[i] = ISelDAG->getNode(ISD::ADD, MVT::i64, left, right); + } + + // don't forget flippedSign and preliminaryShift! + SDOperand finalresult; + if(preliminaryShift) { + SDOperand finalshift = ISelDAG->getConstant(preliminaryShift, MVT::i64); + finalresult = ISelDAG->getNode(ISD::SHL, MVT::i64, + results[ops.size()-1], finalshift); + } else { // there was no preliminary divide-by-power-of-2 required + finalresult = results[ops.size()-1]; + } + + return finalresult; } /// ExactLog2 - This function solves for (Val == 1 << (N-1)) and returns N. It @@ -909,23 +1324,32 @@ } case ISD::MUL: { - Tmp1 = SelectExpr(N.getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(1)); if(DestType != MVT::f64) { // TODO: speed! - // boring old integer multiply with xma - unsigned TempFR1=MakeReg(MVT::f64); - unsigned TempFR2=MakeReg(MVT::f64); - unsigned TempFR3=MakeReg(MVT::f64); - BuildMI(BB, IA64::SETFSIG, 1, TempFR1).addReg(Tmp1); - BuildMI(BB, IA64::SETFSIG, 1, TempFR2).addReg(Tmp2); - BuildMI(BB, IA64::XMAL, 1, TempFR3).addReg(TempFR1).addReg(TempFR2) - .addReg(IA64::F0); - BuildMI(BB, IA64::GETFSIG, 1, Result).addReg(TempFR3); + if(N.getOperand(1).getOpcode() != ISD::Constant) { // if not a const mul + // boring old integer multiply with xma + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + + unsigned TempFR1=MakeReg(MVT::f64); + unsigned TempFR2=MakeReg(MVT::f64); + unsigned TempFR3=MakeReg(MVT::f64); + BuildMI(BB, IA64::SETFSIG, 1, TempFR1).addReg(Tmp1); + BuildMI(BB, IA64::SETFSIG, 1, TempFR2).addReg(Tmp2); + BuildMI(BB, IA64::XMAL, 1, TempFR3).addReg(TempFR1).addReg(TempFR2) + .addReg(IA64::F0); + BuildMI(BB, IA64::GETFSIG, 1, Result).addReg(TempFR3); + return Result; // early exit + } else { // we are multiplying by an integer constant! yay + return Reg = SelectExpr(BuildConstmulSequence(N)); // avert your eyes! + } } - else // floating point multiply + else { // floating point multiply + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); BuildMI(BB, IA64::FMPY, 2, Result).addReg(Tmp1).addReg(Tmp2); - return Result; + return Result; + } } case ISD::SUB: { From reid at x10sys.com Tue Apr 26 02:40:52 2005 From: reid at x10sys.com (Reid Spencer) Date: Tue, 26 Apr 2005 02:40:52 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/SimplifyLibCalls/MemCpy.ll Message-ID: <200504260740.CAA06924@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/SimplifyLibCalls: MemCpy.ll added (r1.1) --- Log message: Add a new test case for the llvm.memcpy simplification case. --- Diffs of the changes: (+21 -0) MemCpy.ll | 21 +++++++++++++++++++++ 1 files changed, 21 insertions(+) Index: llvm/test/Regression/Transforms/SimplifyLibCalls/MemCpy.ll diff -c /dev/null llvm/test/Regression/Transforms/SimplifyLibCalls/MemCpy.ll:1.1 *** /dev/null Tue Apr 26 02:40:51 2005 --- llvm/test/Regression/Transforms/SimplifyLibCalls/MemCpy.ll Tue Apr 26 02:40:40 2005 *************** *** 0 **** --- 1,21 ---- + ; Test that the StrCatOptimizer works correctly + ; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | not grep 'call.*llvm.memcpy' + + declare sbyte* %llvm.memcpy(sbyte*,sbyte*,int,int) + %h = constant [2 x sbyte] c"h\00" + %hel = constant [4 x sbyte] c"hel\00" + %hello_u = constant [8 x sbyte] c"hello_u\00" + + implementation ; Functions: + + int %main () { + %h_p = getelementptr [2 x sbyte]* %h, int 0, int 0 + %hel_p = getelementptr [4 x sbyte]* %hel, int 0, int 0 + %hello_u_p = getelementptr [8 x sbyte]* %hello_u, int 0, int 0 + %target = alloca [1024 x sbyte] + %target_p = getelementptr [1024 x sbyte]* %target, int 0, int 0 + call sbyte* %llvm.memcpy(sbyte* %target_p, sbyte* %h_p, int 2, int 2) + call sbyte* %llvm.memcpy(sbyte* %target_p, sbyte* %hel_p, int 4, int 4) + call sbyte* %llvm.memcpy(sbyte* %target_p, sbyte* %hello_u_p, int 8, int 8) + ret int 0 + } From reid at x10sys.com Tue Apr 26 02:45:29 2005 From: reid at x10sys.com (Reid Spencer) Date: Tue, 26 Apr 2005 02:45:29 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Message-ID: <200504260745.CAA06959@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: SimplifyLibCalls.cpp updated: 1.6 -> 1.7 --- Log message: * Merge get_GVInitializer and getCharArrayLength into a single function named getConstantStringLength. This is the common part of StrCpy and StrLen optimizations and probably several others, yet to be written. It performs all the validity checks for looking at constant arrays that are supposed to be null-terminated strings and then computes the actual length of the string. * Implement the MemCpyOptimization class. This just turns memcpy of 1, 2, 4 and 8 byte data blocks that are properly aligned on those boundaries into a load and a store. Much more could be done here but alignment restrictions and lack of knowledge of the target instruction set prevent use from doing significantly more. That will have to be delegated to the code generators as they lower llvm.memcpy calls. --- Diffs of the changes: (+151 -136) SimplifyLibCalls.cpp | 287 ++++++++++++++++++++++++++------------------------- 1 files changed, 151 insertions(+), 136 deletions(-) Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.6 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.7 --- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.6 Tue Apr 26 00:24:00 2005 +++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Tue Apr 26 02:45:18 2005 @@ -137,64 +137,81 @@ return memcpy_type; } - // Provide some utility functions for various checks common to more than - // one CallOptimizer - Constant* get_GVInitializer(Value* V) + /// A function to compute the length of a null-terminated string of integers. + /// This function can't rely on the size of the constant array because there + /// could be a null terminator in the middle of the array. We also have to + /// bail out if we find a non-integer constant initializer of one of the + /// elements or if there is no null-terminator. The logic below checks + bool getConstantStringLength(Value* V, uint64_t& len ) { + assert(V != 0 && "Invalid args to getCharArrayLength"); + len = 0; // make sure we initialize this User* GEP = 0; - // If the value not a GEP instruction nor a constant expression with a GEP - // instruction, then return 0 because ConstantArray can't occur any other - // way + // If the value is not a GEP instruction nor a constant expression with a + // GEP instruction, then return false because ConstantArray can't occur + // any other way if (GetElementPtrInst* GEPI = dyn_cast(V)) GEP = GEPI; else if (ConstantExpr* CE = dyn_cast(V)) if (CE->getOpcode() == Instruction::GetElementPtr) GEP = CE; else - return 0; + return false; else - return 0; + return false; // Check to make sure that the first operand of the GEP is an integer and // has value 0 so that we are sure we're indexing into the initializer. if (ConstantInt* op1 = dyn_cast(GEP->getOperand(1))) - if (op1->isNullValue()) - ; - else + { + if (!op1->isNullValue()) return false; + } else return false; // Ensure that the second operand is a ConstantInt. If it isn't then this // GEP is wonky and we're not really sure what were referencing into and - // better of not optimizing it. - if (!dyn_cast(GEP->getOperand(2))) - return 0; + // better of not optimizing it. While we're at it, get the second index + // value. We'll need this later for indexing the ConstantArray. + uint64_t start_idx = 0; + if (ConstantInt* CI = dyn_cast(GEP->getOperand(2))) + start_idx = CI->getRawValue(); + else + return false; // The GEP instruction, constant or instruction, must reference a global // variable that is a constant and is initialized. The referenced constant // initializer is the array that we'll use for optimization. GlobalVariable* GV = dyn_cast(GEP->getOperand(0)); if (!GV || !GV->isConstant() || !GV->hasInitializer()) - return 0; + return false; - // Return the result - return GV->getInitializer(); - } + // Get the initializer and make sure its valid. + Constant* INTLZR = GV->getInitializer(); + if (!INTLZR) + return false; - /// A function to compute the length of a null-terminated string of integers. - /// This function can't rely on the size of the constant array because there - /// could be a null terminator in the middle of the array. We also have to - /// bail out if we find a non-integer constant initializer of one of the - /// elements or if there is no null-terminator. The logic below checks - bool getCharArrayLength(ConstantArray* A, unsigned& len) - { - assert(A != 0 && "Invalid args to getCharArrayLength"); - // Get the supposed length - unsigned max_elems = A->getType()->getNumElements(); - len = 0; - // Examine all the elements - for (; len < max_elems; len++) + // Handle the ConstantAggregateZero case + if (ConstantAggregateZero* CAZ = dyn_cast(INTLZR)) + { + // This is a degenerate case. The initializer is constant zero so the + // length of the string must be zero. + len = 0; + return true; + } + + // Must be a Constant Array + ConstantArray* A = dyn_cast(INTLZR); + if (!A) + return false; + + // Get the number of elements in the array + uint64_t max_elems = A->getType()->getNumElements(); + + // Traverse the constant array from start_idx (derived above) which is + // the place the GEP refers to in the array. + for ( len = start_idx; len < max_elems; len++) { if (ConstantInt* CI = dyn_cast(A->getOperand(len))) { @@ -207,6 +224,9 @@ } if (len >= max_elems) return false; // This array isn't null terminated + + // Subtract out the initial value from the length + len -= start_idx; return true; // success! } } @@ -283,10 +303,9 @@ // type, external linkage, not varargs). virtual bool ValidateCalledFunction(const Function* f) { - if (f->getReturnType()->getTypeID() == Type::VoidTyID && !f->isVarArg()) - if (f->arg_size() == 1) - if (f->arg_begin()->getType()->isInteger()) - return true; + if (f->arg_size() >= 1) + if (f->arg_begin()->getType()->isInteger()) + return true; return false; } @@ -395,81 +414,55 @@ // Extract the initializer (while making numerous checks) from the // source operand of the call to strcat. If we get null back, one of // a variety of checks in get_GVInitializer failed - Constant* INTLZR = get_GVInitializer(ci->getOperand(2)); - if (!INTLZR) + uint64_t len = 0; + if (!getConstantStringLength(ci->getOperand(2),len)) return false; - // Handle the ConstantArray case. - if (ConstantArray* A = dyn_cast(INTLZR)) - { - // First off, we can't do this if the constant array isn't a string, - // meaning its base type is sbyte and its constant initializers for all - // the elements are constantInt or constantInt expressions. - if (!A->isString()) - return false; - - // Now we need to examine the source string to find its actual length. We - // can't rely on the size of the constant array becasue there could be a - // null terminator in the middle of the array. We also have to bail out if - // we find a non-integer constant initializer of one of the elements. - // Also, if we never find a terminator before the end of the array. - unsigned max_elems = A->getType()->getNumElements(); - unsigned len = 0; - if (!getCharArrayLength(A,len)) - return false; - else - len++; // increment for null terminator - - // Extract some information from the instruction - Module* M = ci->getParent()->getParent()->getParent(); - - // We need to find the end of the destination string. That's where the - // memory is to be moved to. We just generate a call to strlen (further - // optimized in another pass). Note that the get_strlen_func() call - // caches the Function* for us. - CallInst* strlen_inst = - new CallInst(get_strlen_func(M),ci->getOperand(1),"",ci); - - // Now that we have the destination's length, we must index into the - // destination's pointer to get the actual memcpy destination (end of - // the string .. we're concatenating). - std::vector idx; - idx.push_back(strlen_inst); - GetElementPtrInst* gep = - new GetElementPtrInst(ci->getOperand(1),idx,"",ci); - - // We have enough information to now generate the memcpy call to - // do the concatenation for us. - std::vector vals; - vals.push_back(gep); // destination - vals.push_back(ci->getOperand(2)); // source - vals.push_back(ConstantSInt::get(Type::IntTy,len)); // length - vals.push_back(ConstantSInt::get(Type::IntTy,1)); // alignment - CallInst* memcpy_inst = - new CallInst(get_memcpy_func(M), vals, "", ci); - - // Finally, substitute the first operand of the strcat call for the - // strcat call itself since strcat returns its first operand; and, - // kill the strcat CallInst. - ci->replaceAllUsesWith(ci->getOperand(1)); - ci->eraseFromParent(); - return true; - } - - // Handle the ConstantAggregateZero case - else if (ConstantAggregateZero* CAZ = - dyn_cast(INTLZR)) + // Handle the simple, do-nothing case + if (len == 0) { - // We know this is the zero length string case so we can just avoid - // the strcat altogether and replace the CallInst with its first operand - // (what strcat returns). ci->replaceAllUsesWith(ci->getOperand(1)); ci->eraseFromParent(); return true; } - // We didn't pass the criteria for this optimization so return false. - return false; + // Increment the length because we actually want to memcpy the null + // terminator as well. + len++; + + // Extract some information from the instruction + Module* M = ci->getParent()->getParent()->getParent(); + + // We need to find the end of the destination string. That's where the + // memory is to be moved to. We just generate a call to strlen (further + // optimized in another pass). Note that the get_strlen_func() call + // caches the Function* for us. + CallInst* strlen_inst = + new CallInst(get_strlen_func(M),ci->getOperand(1),"",ci); + + // Now that we have the destination's length, we must index into the + // destination's pointer to get the actual memcpy destination (end of + // the string .. we're concatenating). + std::vector idx; + idx.push_back(strlen_inst); + GetElementPtrInst* gep = + new GetElementPtrInst(ci->getOperand(1),idx,"",ci); + + // We have enough information to now generate the memcpy call to + // do the concatenation for us. + std::vector vals; + vals.push_back(gep); // destination + vals.push_back(ci->getOperand(2)); // source + vals.push_back(ConstantSInt::get(Type::IntTy,len)); // length + vals.push_back(ConstantSInt::get(Type::IntTy,1)); // alignment + CallInst* memcpy_inst = new CallInst(get_memcpy_func(M), vals, "", ci); + + // Finally, substitute the first operand of the strcat call for the + // strcat call itself since strcat returns its first operand; and, + // kill the strcat CallInst. + ci->replaceAllUsesWith(ci->getOperand(1)); + ci->eraseFromParent(); + return true; } } StrCatOptimizer; @@ -496,36 +489,14 @@ /// @brief Perform the strlen optimization virtual bool OptimizeCall(CallInst* ci) { - // Extract the initializer (while making numerous checks) from the - // source operand of the call to strlen. If we get null back, one of - // a variety of checks in get_GVInitializer failed - Constant* INTLZR = get_GVInitializer(ci->getOperand(1)); - if (!INTLZR) + // Get the length of the string + uint64_t len = 0; + if (!getConstantStringLength(ci->getOperand(1),len)) return false; - if (ConstantArray* A = dyn_cast(INTLZR)) - { - unsigned len = 0; - if (!getCharArrayLength(A,len)) - return false; - ci->replaceAllUsesWith(ConstantInt::get(Type::IntTy,len)); - ci->eraseFromParent(); - return true; - } - - // Handle the ConstantAggregateZero case - else if (ConstantAggregateZero* CAZ = - dyn_cast(INTLZR)) - { - // We know this is the zero length string case so we can just avoid - // the strlen altogether and replace the CallInst with zero - ci->replaceAllUsesWith(ConstantInt::get(Type::IntTy,0)); - ci->eraseFromParent(); - return true; - } - - // We didn't pass the criteria for this optimization so return false. - return false; + ci->replaceAllUsesWith(ConstantInt::get(Type::IntTy,len)); + ci->eraseFromParent(); + return true; } } StrLenOptimizer; @@ -542,7 +513,7 @@ virtual bool ValidateCalledFunction(const Function* f) { if (f->getReturnType() == PointerType::get(Type::SByteTy)) - if (f->arg_size() == 2) + if (f->arg_size() == 4) { Function::const_arg_iterator AI = f->arg_begin(); if (AI++->getType() == PointerType::get(Type::SByteTy)) @@ -554,13 +525,57 @@ return false; } - /// Perform the optimization if the length of the string concatenated - /// is reasonably short and it is a constant array. + /// Because of alignment and instruction information that we don't have, we + /// leave the bulk of this to the code generators. The optimization here just + /// deals with a few degenerate cases where the length of the string and the + /// alignment match the sizes of our intrinsic types so we can do a load and + /// store instead of the memcpy call. + /// @brief Perform the memcpy optimization. virtual bool OptimizeCall(CallInst* ci) { - // - // We didn't pass the criteria for this optimization so return false. - return false; + ConstantInt* CI = dyn_cast(ci->getOperand(3)); + assert(CI && "Operand should be ConstantInt"); + uint64_t len = CI->getRawValue(); + CI = dyn_cast(ci->getOperand(4)); + assert(CI && "Operand should be ConstantInt"); + uint64_t alignment = CI->getRawValue(); + if (len != alignment) + return false; + + Value* dest = ci->getOperand(1); + Value* src = ci->getOperand(2); + LoadInst* LI = 0; + CastInst* SrcCast = 0; + CastInst* DestCast = 0; + switch (len) + { + case 1: + SrcCast = new CastInst(src,PointerType::get(Type::SByteTy),"",ci); + DestCast = new CastInst(dest,PointerType::get(Type::SByteTy),"",ci); + LI = new LoadInst(SrcCast,"",ci); + break; + case 2: + SrcCast = new CastInst(src,PointerType::get(Type::ShortTy),"",ci); + DestCast = new CastInst(dest,PointerType::get(Type::ShortTy),"",ci); + LI = new LoadInst(SrcCast,"",ci); + break; + case 4: + SrcCast = new CastInst(src,PointerType::get(Type::IntTy),"",ci); + DestCast = new CastInst(dest,PointerType::get(Type::IntTy),"",ci); + LI = new LoadInst(SrcCast,"",ci); + break; + case 8: + SrcCast = new CastInst(src,PointerType::get(Type::LongTy),"",ci); + DestCast = new CastInst(dest,PointerType::get(Type::LongTy),"",ci); + LI = new LoadInst(SrcCast,"",ci); + break; + default: + return false; + } + StoreInst* SI = new StoreInst(LI, DestCast, ci); + ci->replaceAllUsesWith(dest); + ci->eraseFromParent(); + return true; } } MemCpyOptimizer; } From duraid at octopus.com.au Tue Apr 26 03:43:58 2005 From: duraid at octopus.com.au (Duraid Madina) Date: Tue, 26 Apr 2005 03:43:58 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/IA64/IA64ISelPattern.cpp Message-ID: <200504260843.DAA27279@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/IA64: IA64ISelPattern.cpp updated: 1.27 -> 1.28 --- Log message: clean up the code! (oops) lots more cleaning left, however. --- Diffs of the changes: (+0 -22) IA64ISelPattern.cpp | 22 ---------------------- 1 files changed, 22 deletions(-) Index: llvm/lib/Target/IA64/IA64ISelPattern.cpp diff -u llvm/lib/Target/IA64/IA64ISelPattern.cpp:1.27 llvm/lib/Target/IA64/IA64ISelPattern.cpp:1.28 --- llvm/lib/Target/IA64/IA64ISelPattern.cpp:1.27 Tue Apr 26 02:23:02 2005 +++ llvm/lib/Target/IA64/IA64ISelPattern.cpp Tue Apr 26 03:43:47 2005 @@ -668,28 +668,6 @@ t.replace(i, 1, "0"); } - /* and now for something completely different: - - //\\\\\\ ` \`..(@) - : \\\\ (@)(@) / /(@) - \ ~L~ )\\\\ \ \ '\(__``',.. - /\_~ / |||| \ , | ~~~--/ - ////| |//// // / - ||||^ ~~~~~~--------~/ / - / ( ( _____---~~~~~\| / -( )| / / / / - \^\ \____/ / \ / - \ \/ \ \ / - )) ) ' ~ - | | ` , - |______| - | || | , - ( || | - \ | | , - \| / - /_^|| - */ - for(int i=0; i Changes in directory llvm/lib/Target/IA64: IA64ISelPattern.cpp updated: 1.28 -> 1.29 --- Log message: constmul bugfix: multiply by 27611 was broken --- Diffs of the changes: (+10 -11) IA64ISelPattern.cpp | 21 ++++++++++----------- 1 files changed, 10 insertions(+), 11 deletions(-) Index: llvm/lib/Target/IA64/IA64ISelPattern.cpp diff -u llvm/lib/Target/IA64/IA64ISelPattern.cpp:1.28 llvm/lib/Target/IA64/IA64ISelPattern.cpp:1.29 --- llvm/lib/Target/IA64/IA64ISelPattern.cpp:1.28 Tue Apr 26 03:43:47 2005 +++ llvm/lib/Target/IA64/IA64ISelPattern.cpp Tue Apr 26 04:42:50 2005 @@ -453,9 +453,6 @@ ISelDAG = 0; } -const char sign[2]={'+','-'}; - - // strip leading '0' characters from a string void munchLeadingZeros(std::string& inString) { while(inString.c_str()[0]=='0') { @@ -564,7 +561,8 @@ } std::string t, u; - int c,f; + int c; + bool f; std::map w; for(int i=0; i Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.330 -> 1.331 --- Log message: Fix the compile failures from last night. --- Diffs of the changes: (+2 -0) InstructionCombining.cpp | 2 ++ 1 files changed, 2 insertions(+) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.330 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.331 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.330 Mon Apr 25 15:17:30 2005 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Tue Apr 26 09:40:41 2005 @@ -2281,6 +2281,8 @@ // compare the base pointer. if (PtrBase != GEPRHS->getOperand(0)) { bool IndicesTheSame = GEPLHS->getNumOperands()==GEPRHS->getNumOperands(); + IndicesTheSame &= GEPLHS->getOperand(0)->getType() == + GEPRHS->getOperand(0)->getType(); if (IndicesTheSame) for (unsigned i = 1, e = GEPLHS->getNumOperands(); i != e; ++i) if (GEPLHS->getOperand(i) != GEPRHS->getOperand(i)) { From lattner at cs.uiuc.edu Tue Apr 26 09:48:44 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 26 Apr 2005 09:48:44 -0500 Subject: [llvm-commits] CVS: llvm/lib/Analysis/IntervalPartition.cpp Message-ID: <200504261448.j3QEmiJ8014635@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: IntervalPartition.cpp updated: 1.30 -> 1.31 --- Log message: Make interval partition print correctly, patch contributed by Vladimir Prus! --- Diffs of the changes: (+2 -2) IntervalPartition.cpp | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) Index: llvm/lib/Analysis/IntervalPartition.cpp diff -u llvm/lib/Analysis/IntervalPartition.cpp:1.30 llvm/lib/Analysis/IntervalPartition.cpp:1.31 --- llvm/lib/Analysis/IntervalPartition.cpp:1.30 Thu Apr 21 22:54:55 2005 +++ llvm/lib/Analysis/IntervalPartition.cpp Tue Apr 26 09:48:28 2005 @@ -31,8 +31,8 @@ } void IntervalPartition::print(std::ostream &O, const Module*) const { - std::copy(Intervals.begin(), Intervals.end(), - std::ostream_iterator(O, "\n")); + for(unsigned i = 0, e = Intervals.size(); i != e; ++i) + Intervals[i]->print(O); } // addIntervalToPartition - Add an interval to the internal list of intervals, From reid at x10sys.com Tue Apr 26 14:04:57 2005 From: reid at x10sys.com (Reid Spencer) Date: Tue, 26 Apr 2005 14:04:57 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/SimplifyLibCalls/StrLen.ll Message-ID: <200504261904.OAA05532@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/SimplifyLibCalls: StrLen.ll updated: 1.1 -> 1.2 --- Log message: Result of strlen is size_t which is either uint or ulong, not int. --- Diffs of the changes: (+4 -4) StrLen.ll | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) Index: llvm/test/Regression/Transforms/SimplifyLibCalls/StrLen.ll diff -u llvm/test/Regression/Transforms/SimplifyLibCalls/StrLen.ll:1.1 llvm/test/Regression/Transforms/SimplifyLibCalls/StrLen.ll:1.2 --- llvm/test/Regression/Transforms/SimplifyLibCalls/StrLen.ll:1.1 Tue Apr 26 00:22:38 2005 +++ llvm/test/Regression/Transforms/SimplifyLibCalls/StrLen.ll Tue Apr 26 14:04:46 2005 @@ -1,7 +1,7 @@ ; Test that the StrCatOptimizer works correctly ; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | not grep 'call.*strlen' -declare int %strlen(sbyte*) +declare uint %strlen(sbyte*) %hello = constant [6 x sbyte] c"hello\00" %null = constant [1 x sbyte] c"\00" %null_hello = constant [7 x sbyte] c"\00hello\00" @@ -10,11 +10,11 @@ int %main () { %hello_p = getelementptr [6 x sbyte]* %hello, int 0, int 0 - %hello_l = call int %strlen(sbyte* %hello_p) + %hello_l = call uint %strlen(sbyte* %hello_p) %null_p = getelementptr [1 x sbyte]* %null, int 0, int 0 - %null_l = call int %strlen(sbyte* %null_p) + %null_l = call uint %strlen(sbyte* %null_p) %null_hello_p = getelementptr [7 x sbyte]* %null_hello, int 0, int 0 - %null_hello_l = call int %strlen(sbyte* %null_hello_p) + %null_hello_l = call uint %strlen(sbyte* %null_hello_p) %sum1 = add int %hello_l, %null_l %sum2 = add int %sum1, %null_hello_l ret int %sum2 From reid at x10sys.com Tue Apr 26 14:06:02 2005 From: reid at x10sys.com (Reid Spencer) Date: Tue, 26 Apr 2005 14:06:02 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/SimplifyLibCalls/MemMove.ll Message-ID: <200504261906.OAA05553@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/SimplifyLibCalls: MemMove.ll added (r1.1) --- Log message: Add a test case for MemMove.ll --- Diffs of the changes: (+21 -0) MemMove.ll | 21 +++++++++++++++++++++ 1 files changed, 21 insertions(+) Index: llvm/test/Regression/Transforms/SimplifyLibCalls/MemMove.ll diff -c /dev/null llvm/test/Regression/Transforms/SimplifyLibCalls/MemMove.ll:1.1 *** /dev/null Tue Apr 26 14:06:01 2005 --- llvm/test/Regression/Transforms/SimplifyLibCalls/MemMove.ll Tue Apr 26 14:05:51 2005 *************** *** 0 **** --- 1,21 ---- + ; Test that the StrCatOptimizer works correctly + ; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | not grep 'call.*llvm.memmove' + + declare sbyte* %llvm.memmove(sbyte*,sbyte*,int,int) + %h = constant [2 x sbyte] c"h\00" + %hel = constant [4 x sbyte] c"hel\00" + %hello_u = constant [8 x sbyte] c"hello_u\00" + + implementation ; Functions: + + int %main () { + %h_p = getelementptr [2 x sbyte]* %h, int 0, int 0 + %hel_p = getelementptr [4 x sbyte]* %hel, int 0, int 0 + %hello_u_p = getelementptr [8 x sbyte]* %hello_u, int 0, int 0 + %target = alloca [1024 x sbyte] + %target_p = getelementptr [1024 x sbyte]* %target, int 0, int 0 + call sbyte* %llvm.memmove(sbyte* %target_p, sbyte* %h_p, int 2, int 2) + call sbyte* %llvm.memmove(sbyte* %target_p, sbyte* %hel_p, int 4, int 4) + call sbyte* %llvm.memmove(sbyte* %target_p, sbyte* %hello_u_p, int 8, int 8) + ret int 0 + } From reid at x10sys.com Tue Apr 26 14:13:28 2005 From: reid at x10sys.com (Reid Spencer) Date: Tue, 26 Apr 2005 14:13:28 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Message-ID: <200504261913.OAA05590@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: SimplifyLibCalls.cpp updated: 1.7 -> 1.8 --- Log message: Changes From Review Feedback: * Have the SimplifyLibCalls pass acquire the TargetData and pass it down to the optimization classes so they can use it to make better choices for the signatures of functions, etc. * Rearrange the code a little so the utility functions are closer to their usage and keep the core of the pass near the top of the files. * Adjust the StrLen pass to get/use the correct prototype depending on the TargetData::getIntPtrType() result. The result of strlen is size_t which could be either uint or ulong depending on the platform. * Clean up some coding nits (cast vs. dyn_cast, remove redundant items from a switch, etc.) * Implement the MemMoveOptimization as a twin of MemCpyOptimization (they only differ in name). --- Diffs of the changes: (+122 -97) SimplifyLibCalls.cpp | 219 ++++++++++++++++++++++++++++----------------------- 1 files changed, 122 insertions(+), 97 deletions(-) Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.7 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.8 --- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.7 Tue Apr 26 02:45:18 2005 +++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Tue Apr 26 14:13:17 2005 @@ -24,6 +24,7 @@ #include "llvm/Instructions.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/hash_map" +#include "llvm/Target/TargetData.h" #include using namespace llvm; @@ -44,6 +45,9 @@ /// @brief A ModulePass for optimizing well-known function calls struct SimplifyLibCalls : public ModulePass { + /// We need some target data for accurate signature details that are + /// target dependent. So we require target data in our AnalysisUsage. + virtual void getAnalysisUsage(AnalysisUsage& Info) const; /// For this pass, process all of the function calls in the module, calling /// RecognizeCall and OptimizeCall as appropriate. @@ -71,7 +75,8 @@ /// true. This avoids doing initialization until the optimizer is actually /// going to be called upon to do some optimization. virtual bool ValidateCalledFunction( - const Function* F ///< The function that is the target of call sites + const Function* F, ///< The function that is the target of call sites + const TargetData& TD ///< Information about the target ) = 0; /// The implementations of this function in subclasses is the heart of the @@ -84,7 +89,8 @@ /// @param f the function that ci calls. /// @brief Optimize a call, if possible. virtual bool OptimizeCall( - CallInst* ci ///< The call instruction that should be optimized. + CallInst* ci, ///< The call instruction that should be optimized. + const TargetData& TD ///< Information about the target ) = 0; const char * getFunctionName() const { return func_name; } @@ -106,16 +112,84 @@ /// Make sure we get our virtual table in this file. CallOptimizer::~CallOptimizer() { } +} + +ModulePass *llvm::createSimplifyLibCallsPass() +{ + return new SimplifyLibCalls(); +} + +void SimplifyLibCalls::getAnalysisUsage(AnalysisUsage& Info) const +{ + // Ask that the TargetData analysis be performed before us so we can use + // the target data. + Info.addRequired(); +} + +bool SimplifyLibCalls::runOnModule(Module &M) +{ + TargetData& TD = getAnalysis(); + + bool result = false; + + // The call optimizations can be recursive. That is, the optimization might + // generate a call to another function which can also be optimized. This way + // we make the CallOptimizer instances very specific to the case they handle. + // It also means we need to keep running over the function calls in the module + // until we don't get any more optimizations possible. + bool found_optimization = false; + do + { + found_optimization = false; + for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI) + { + // All the "well-known" functions are external and have external linkage + // because they live in a runtime library somewhere and were (probably) + // not compiled by LLVM. So, we only act on external functions that have + // external linkage and non-empty uses. + if (FI->isExternal() && FI->hasExternalLinkage() && !FI->use_empty()) + { + // Get the optimization class that pertains to this function + if (CallOptimizer* CO = optlist[FI->getName().c_str()] ) + { + // Make sure the called function is suitable for the optimization + if (CO->ValidateCalledFunction(FI,TD)) + { + // Loop over each of the uses of the function + for (Value::use_iterator UI = FI->use_begin(), UE = FI->use_end(); + UI != UE ; ) + { + // If the use of the function is a call instruction + if (CallInst* CI = dyn_cast(*UI++)) + { + // Do the optimization on the CallOptimizer. + if (CO->OptimizeCall(CI,TD)) + { + ++SimplifiedLibCalls; + found_optimization = result = true; + } + } + } + } + } + } + } + } while (found_optimization); + return result; +} + +namespace { + /// Provide some functions for accessing standard library prototypes and /// caching them so we don't have to keep recomputing them - FunctionType* get_strlen() + FunctionType* get_strlen(const Type* IntPtrTy) { static FunctionType* strlen_type = 0; if (!strlen_type) { std::vector args; args.push_back(PointerType::get(Type::SByteTy)); - strlen_type = FunctionType::get(Type::IntTy, args, false); + strlen_type = FunctionType::get(IntPtrTy, args, false); } return strlen_type; } @@ -144,7 +218,7 @@ /// elements or if there is no null-terminator. The logic below checks bool getConstantStringLength(Value* V, uint64_t& len ) { - assert(V != 0 && "Invalid args to getCharArrayLength"); + assert(V != 0 && "Invalid args to getConstantStringLength"); len = 0; // make sure we initialize this User* GEP = 0; // If the value is not a GEP instruction nor a constant expression with a @@ -160,6 +234,10 @@ else return false; + // Make sure the GEP has exactly three arguments. + if (GEP->getNumOperands() != 3) + return false; + // Check to make sure that the first operand of the GEP is an integer and // has value 0 so that we are sure we're indexing into the initializer. if (ConstantInt* op1 = dyn_cast(GEP->getOperand(1))) @@ -187,10 +265,8 @@ if (!GV || !GV->isConstant() || !GV->hasInitializer()) return false; - // Get the initializer and make sure its valid. + // Get the initializer. Constant* INTLZR = GV->getInitializer(); - if (!INTLZR) - return false; // Handle the ConstantAggregateZero case if (ConstantAggregateZero* CAZ = dyn_cast(INTLZR)) @@ -229,64 +305,6 @@ len -= start_idx; return true; // success! } -} - -ModulePass *llvm::createSimplifyLibCallsPass() -{ - return new SimplifyLibCalls(); -} - -bool SimplifyLibCalls::runOnModule(Module &M) -{ - bool result = false; - - // The call optimizations can be recursive. That is, the optimization might - // generate a call to another function which can also be optimized. This way - // we make the CallOptimizer instances very specific to the case they handle. - // It also means we need to keep running over the function calls in the module - // until we don't get any more optimizations possible. - bool found_optimization = false; - do - { - found_optimization = false; - for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI) - { - // All the "well-known" functions are external and have external linkage - // because they live in a runtime library somewhere and were (probably) - // not compiled by LLVM. So, we only act on external functions that have - // external linkage and non-empty uses. - if (FI->isExternal() && FI->hasExternalLinkage() && !FI->use_empty()) - { - // Get the optimization class that pertains to this function - if (CallOptimizer* CO = optlist[FI->getName().c_str()] ) - { - // Make sure the called function is suitable for the optimization - if (CO->ValidateCalledFunction(FI)) - { - // Loop over each of the uses of the function - for (Value::use_iterator UI = FI->use_begin(), UE = FI->use_end(); - UI != UE ; ) - { - // If the use of the function is a call instruction - if (CallInst* CI = dyn_cast(*UI++)) - { - // Do the optimization on the CallOptimizer. - if (CO->OptimizeCall(CI)) - { - ++SimplifiedLibCalls; - found_optimization = result = true; - } - } - } - } - } - } - } - } while (found_optimization); - return result; -} - -namespace { /// This CallOptimizer will find instances of a call to "exit" that occurs /// within the "main" function and change it to a simple "ret" instruction with @@ -301,7 +319,7 @@ // Make sure the called function looks like exit (int argument, int return // type, external linkage, not varargs). - virtual bool ValidateCalledFunction(const Function* f) + virtual bool ValidateCalledFunction(const Function* f, const TargetData& TD) { if (f->arg_size() >= 1) if (f->arg_begin()->getType()->isInteger()) @@ -309,7 +327,7 @@ return false; } - virtual bool OptimizeCall(CallInst* ci) + virtual bool OptimizeCall(CallInst* ci, const TargetData& TD) { // To be careful, we check that the call to exit is coming from "main", that // main has external linkage, and the return type of main and the argument @@ -369,11 +387,11 @@ {} virtual ~StrCatOptimization() {} - inline Function* get_strlen_func(Module*M) + inline Function* get_strlen_func(Module*M,const Type* IntPtrTy) { if (strlen_func) return strlen_func; - return strlen_func = M->getOrInsertFunction("strlen",get_strlen()); + return strlen_func = M->getOrInsertFunction("strlen",get_strlen(IntPtrTy)); } inline Function* get_memcpy_func(Module* M) @@ -384,7 +402,7 @@ } /// @brief Make sure that the "strcat" function has the right prototype - virtual bool ValidateCalledFunction(const Function* f) + virtual bool ValidateCalledFunction(const Function* f, const TargetData& TD) { if (f->getReturnType() == PointerType::get(Type::SByteTy)) if (f->arg_size() == 2) @@ -409,7 +427,7 @@ /// Perform the optimization if the length of the string concatenated /// is reasonably short and it is a constant array. - virtual bool OptimizeCall(CallInst* ci) + virtual bool OptimizeCall(CallInst* ci, const TargetData& TD) { // Extract the initializer (while making numerous checks) from the // source operand of the call to strcat. If we get null back, one of @@ -438,7 +456,8 @@ // optimized in another pass). Note that the get_strlen_func() call // caches the Function* for us. CallInst* strlen_inst = - new CallInst(get_strlen_func(M),ci->getOperand(1),"",ci); + new CallInst(get_strlen_func(M,TD.getIntPtrType()), + ci->getOperand(1),"",ci); // Now that we have the destination's length, we must index into the // destination's pointer to get the actual memcpy destination (end of @@ -476,9 +495,9 @@ virtual ~StrLenOptimization() {} /// @brief Make sure that the "strlen" function has the right prototype - virtual bool ValidateCalledFunction(const Function* f) + virtual bool ValidateCalledFunction(const Function* f, const TargetData& TD) { - if (f->getReturnType() == Type::IntTy) + if (f->getReturnType() == TD.getIntPtrType()) if (f->arg_size() == 1) if (Function::const_arg_iterator AI = f->arg_begin()) if (AI->getType() == PointerType::get(Type::SByteTy)) @@ -487,14 +506,14 @@ } /// @brief Perform the strlen optimization - virtual bool OptimizeCall(CallInst* ci) + virtual bool OptimizeCall(CallInst* ci, const TargetData& TD) { // Get the length of the string uint64_t len = 0; if (!getConstantStringLength(ci->getOperand(1),len)) return false; - ci->replaceAllUsesWith(ConstantInt::get(Type::IntTy,len)); + ci->replaceAllUsesWith(ConstantInt::get(TD.getIntPtrType(),len)); ci->eraseFromParent(); return true; } @@ -507,22 +526,16 @@ struct MemCpyOptimization : public CallOptimizer { MemCpyOptimization() : CallOptimizer("llvm.memcpy") {} +protected: + MemCpyOptimization(const char* fname) : CallOptimizer(fname) {} +public: virtual ~MemCpyOptimization() {} /// @brief Make sure that the "memcpy" function has the right prototype - virtual bool ValidateCalledFunction(const Function* f) + virtual bool ValidateCalledFunction(const Function* f, const TargetData& TD) { - if (f->getReturnType() == PointerType::get(Type::SByteTy)) - if (f->arg_size() == 4) - { - Function::const_arg_iterator AI = f->arg_begin(); - if (AI++->getType() == PointerType::get(Type::SByteTy)) - if (AI++->getType() == PointerType::get(Type::SByteTy)) - if (AI++->getType() == Type::IntTy) - if (AI->getType() == Type::IntTy) - return true; - } - return false; + // Just make sure this has 4 arguments per LLVM spec. + return f->arg_size() == 4; } /// Because of alignment and instruction information that we don't have, we @@ -531,51 +544,63 @@ /// alignment match the sizes of our intrinsic types so we can do a load and /// store instead of the memcpy call. /// @brief Perform the memcpy optimization. - virtual bool OptimizeCall(CallInst* ci) + virtual bool OptimizeCall(CallInst* ci, const TargetData& TD) { - ConstantInt* CI = dyn_cast(ci->getOperand(3)); + ConstantInt* CI = cast(ci->getOperand(3)); assert(CI && "Operand should be ConstantInt"); uint64_t len = CI->getRawValue(); CI = dyn_cast(ci->getOperand(4)); assert(CI && "Operand should be ConstantInt"); uint64_t alignment = CI->getRawValue(); - if (len != alignment) + if (len > alignment) return false; Value* dest = ci->getOperand(1); Value* src = ci->getOperand(2); - LoadInst* LI = 0; CastInst* SrcCast = 0; CastInst* DestCast = 0; switch (len) { + case 0: + // Just replace with the destination parameter since a zero length + // memcpy is a no-op. + ci->replaceAllUsesWith(dest); + ci->eraseFromParent(); + return true; case 1: SrcCast = new CastInst(src,PointerType::get(Type::SByteTy),"",ci); DestCast = new CastInst(dest,PointerType::get(Type::SByteTy),"",ci); - LI = new LoadInst(SrcCast,"",ci); break; case 2: SrcCast = new CastInst(src,PointerType::get(Type::ShortTy),"",ci); DestCast = new CastInst(dest,PointerType::get(Type::ShortTy),"",ci); - LI = new LoadInst(SrcCast,"",ci); break; case 4: SrcCast = new CastInst(src,PointerType::get(Type::IntTy),"",ci); DestCast = new CastInst(dest,PointerType::get(Type::IntTy),"",ci); - LI = new LoadInst(SrcCast,"",ci); break; case 8: SrcCast = new CastInst(src,PointerType::get(Type::LongTy),"",ci); DestCast = new CastInst(dest,PointerType::get(Type::LongTy),"",ci); - LI = new LoadInst(SrcCast,"",ci); break; default: return false; } + LoadInst* LI = new LoadInst(SrcCast,"",ci); StoreInst* SI = new StoreInst(LI, DestCast, ci); ci->replaceAllUsesWith(dest); ci->eraseFromParent(); return true; } } MemCpyOptimizer; + +/// This CallOptimizer will simplify a call to the memmove library function. It +/// is identical to MemCopyOptimization except for the name of the intrinsic. +/// @brief Simplify the memmove library function. +struct MemMoveOptimization : public MemCpyOptimization +{ + MemMoveOptimization() : MemCpyOptimization("llvm.memmove") {} + +} MemMoveOptimizer; + } From reid at x10sys.com Tue Apr 26 14:56:08 2005 From: reid at x10sys.com (Reid Spencer) Date: Tue, 26 Apr 2005 14:56:08 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Message-ID: <200504261956.OAA05915@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: SimplifyLibCalls.cpp updated: 1.8 -> 1.9 --- Log message: Fix some bugs found by running on llvm-test: * MemCpyOptimization can only be optimized if the 3rd and 4th arguments are constants and we weren't checking for that. * The result of llvm.memcpy (and llvm.memmove) is void* not sbyte*, put in a cast. --- Diffs of the changes: (+17 -9) SimplifyLibCalls.cpp | 26 +++++++++++++++++--------- 1 files changed, 17 insertions(+), 9 deletions(-) Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.8 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.9 --- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.8 Tue Apr 26 14:13:17 2005 +++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Tue Apr 26 14:55:57 2005 @@ -535,7 +535,8 @@ virtual bool ValidateCalledFunction(const Function* f, const TargetData& TD) { // Just make sure this has 4 arguments per LLVM spec. - return f->arg_size() == 4; + return (f->arg_size() == 4) && + (f->getReturnType() == PointerType::get(Type::VoidTy)); } /// Because of alignment and instruction information that we don't have, we @@ -546,12 +547,17 @@ /// @brief Perform the memcpy optimization. virtual bool OptimizeCall(CallInst* ci, const TargetData& TD) { - ConstantInt* CI = cast(ci->getOperand(3)); - assert(CI && "Operand should be ConstantInt"); - uint64_t len = CI->getRawValue(); - CI = dyn_cast(ci->getOperand(4)); - assert(CI && "Operand should be ConstantInt"); - uint64_t alignment = CI->getRawValue(); + // Make sure we have constant int values to work with + ConstantInt* LEN = dyn_cast(ci->getOperand(3)); + if (!LEN) + return false; + ConstantInt* ALIGN = dyn_cast(ci->getOperand(4)); + if (!ALIGN) + return false; + + // If the length is larger than the alignment, we can't optimize + uint64_t len = LEN->getRawValue(); + uint64_t alignment = ALIGN->getRawValue(); if (len > alignment) return false; @@ -564,7 +570,8 @@ case 0: // Just replace with the destination parameter since a zero length // memcpy is a no-op. - ci->replaceAllUsesWith(dest); + ci->replaceAllUsesWith( + new CastInst(dest,PointerType::get(Type::VoidTy),"",ci)); ci->eraseFromParent(); return true; case 1: @@ -588,7 +595,8 @@ } LoadInst* LI = new LoadInst(SrcCast,"",ci); StoreInst* SI = new StoreInst(LI, DestCast, ci); - ci->replaceAllUsesWith(dest); + ci->replaceAllUsesWith( + new CastInst(dest,PointerType::get(Type::VoidTy),"",ci)); ci->eraseFromParent(); return true; } From lattner at cs.uiuc.edu Tue Apr 26 15:03:49 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 26 Apr 2005 15:03:49 -0500 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Type.cpp Message-ID: <200504262003.j3QK3nwe018764@apoc.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Type.cpp updated: 1.126 -> 1.127 --- Log message: don't let Reid build void*'s :) --- Diffs of the changes: (+2 -0) Type.cpp | 2 ++ 1 files changed, 2 insertions(+) Index: llvm/lib/VMCore/Type.cpp diff -u llvm/lib/VMCore/Type.cpp:1.126 llvm/lib/VMCore/Type.cpp:1.127 --- llvm/lib/VMCore/Type.cpp:1.126 Sat Apr 23 17:01:39 2005 +++ llvm/lib/VMCore/Type.cpp Tue Apr 26 15:03:33 2005 @@ -1110,6 +1110,8 @@ PointerType *PointerType::get(const Type *ValueType) { assert(ValueType && "Can't get a pointer to type!"); + assert(ValueType != Type::VoidTy && + "Pointer to void is not valid, use sbyte* instead!"); PointerValType PVT(ValueType); PointerType *PT = PointerTypes.get(PVT); From reid at x10sys.com Tue Apr 26 15:41:27 2005 From: reid at x10sys.com (Reid Spencer) Date: Tue, 26 Apr 2005 15:41:27 -0500 Subject: [llvm-commits] CVS: llvm/docs/LangRef.html Message-ID: <200504262041.PAA06529@zion.cs.uiuc.edu> Changes in directory llvm/docs: LangRef.html updated: 1.93 -> 1.94 --- Log message: Use the declare syntax not the call syntax for intrinsic prototypes so the uninitiated reader is not confused. --- Diffs of the changes: (+7 -7) LangRef.html | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-) Index: llvm/docs/LangRef.html diff -u llvm/docs/LangRef.html:1.93 llvm/docs/LangRef.html:1.94 --- llvm/docs/LangRef.html:1.93 Mon Apr 25 12:34:15 2005 +++ llvm/docs/LangRef.html Tue Apr 26 15:41:16 2005 @@ -2848,8 +2848,8 @@
    Syntax:
    -  call void (sbyte*, sbyte*, uint, uint)* %llvm.memcpy(sbyte* <dest>, sbyte* <src>,
    -                                                       uint <len>, uint <align>)
    +  declare void %llvm.memcpy(sbyte* <dest>, sbyte* <src>,
    +                            uint <len>, uint <align>)
     
    Overview:
    @@ -2900,8 +2900,8 @@
    Syntax:
    -  call void (sbyte*, sbyte*, uint, uint)* %llvm.memmove(sbyte* <dest>, sbyte* <src>,
    -                                                       uint <len>, uint <align>)
    +  declare void %llvm.memmove(sbyte* <dest>, sbyte* <src>,
    +                             uint <len>, uint <align>)
     
    Overview:
    @@ -2953,8 +2953,8 @@
    Syntax:
    -  call void (sbyte*, ubyte, uint, uint)* %llvm.memset(sbyte* <dest>, ubyte <val>,
    -                                                      uint <len>, uint <align>)
    +  declare void %llvm.memset(sbyte* <dest>, ubyte <val>,
    +                            uint <len>, uint <align>)
     
    Overview:
    @@ -3057,7 +3057,7 @@ Chris Lattner
    The LLVM Compiler Infrastructure
    - Last modified: $Date: 2005/04/25 17:34:15 $ + Last modified: $Date: 2005/04/26 20:41:16 $ From reid at x10sys.com Tue Apr 26 15:50:55 2005 From: reid at x10sys.com (Reid Spencer) Date: Tue, 26 Apr 2005 15:50:55 -0500 Subject: [llvm-commits] CVS: llvm/docs/LangRef.html Message-ID: <200504262050.PAA06620@zion.cs.uiuc.edu> Changes in directory llvm/docs: LangRef.html updated: 1.94 -> 1.95 --- Log message: Convert the remainder of the intrinsic function prototypes to "declare" form from the "call" form. --- Diffs of the changes: (+16 -18) LangRef.html | 34 ++++++++++++++++------------------ 1 files changed, 16 insertions(+), 18 deletions(-) Index: llvm/docs/LangRef.html diff -u llvm/docs/LangRef.html:1.94 llvm/docs/LangRef.html:1.95 --- llvm/docs/LangRef.html:1.94 Tue Apr 26 15:41:16 2005 +++ llvm/docs/LangRef.html Tue Apr 26 15:50:44 2005 @@ -2257,7 +2257,7 @@
    Syntax:
    -
      call <va_list> ()* %llvm.va_start()
    +
      declare <va_list> %llvm.va_start()
    Overview:

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

    @@ -2279,7 +2279,7 @@
    Syntax:
    -
      call void (<va_list>)* %llvm.va_end(<va_list> <arglist>)
    +
      declare void %llvm.va_end(<va_list> <arglist>)
    Overview:

    The 'llvm.va_end' intrinsic destroys <arglist> which has been initialized previously with llvm.va_start @@ -2304,7 +2304,7 @@

    Syntax:
    -  call  <va_list> (<va_list>)* %llvm.va_copy(<va_list> <destarglist>)
    +  declare <va_list> %llvm.va_copy(<va_list> <destarglist>)
     
    Overview:
    @@ -2355,7 +2355,7 @@
    Syntax:
    -  call void (<ty>**, <ty2>*)* %llvm.gcroot(<ty>** %ptrloc, <ty2>* %metadata)
    +  declare void %llvm.gcroot(<ty>** %ptrloc, <ty2>* %metadata)
     
    Overview:
    @@ -2389,7 +2389,7 @@
    Syntax:
    -  call sbyte* (sbyte**)* %llvm.gcread(sbyte** %Ptr)
    +  declare sbyte* %llvm.gcread(sbyte** %Ptr)
     
    Overview:
    @@ -2422,7 +2422,7 @@
    Syntax:
    -  call void (sbyte*, sbyte**)* %llvm.gcwrite(sbyte* %P1, sbyte** %P2)
    +  declare void %llvm.gcwrite(sbyte* %P1, sbyte** %P2)
     
    Overview:
    @@ -2468,7 +2468,7 @@
    Syntax:
    -  call void* ()* %llvm.returnaddress(uint <level>)
    +  declare void* %llvm.returnaddress(uint <level>)
     
    Overview:
    @@ -2512,7 +2512,7 @@
    Syntax:
    -  call void* ()* %llvm.frameaddress(uint <level>)
    +  declare void* %llvm.frameaddress(uint <level>)
     
    Overview:
    @@ -2555,9 +2555,8 @@
    Syntax:
    -  call void (sbyte *, uint, uint)* %llvm.prefetch(sbyte * <address>,
    -                                                  uint <rw>, 
    -                                                  uint <locality>)
    +  declare void %llvm.prefetch(sbyte * <address>,
    +                                uint <rw>, uint <locality>)
     
    Overview:
    @@ -2600,7 +2599,7 @@
    Syntax:
    -  call void (uint)* %llvm.pcmarker( uint <id> )
    +  declare void %llvm.pcmarker( uint <id> )
     
    Overview:
    @@ -2654,7 +2653,7 @@
    Syntax:
    -  call <integer type> (<integer type>)* %llvm.readport (<integer type> <address>)
    +  declare <integer type> %llvm.readport (<integer type> <address>)
     
    Overview:
    @@ -2738,7 +2737,7 @@
    Syntax:
    -  call <result> (<ty>*)* %llvm.readio (<ty> * <pointer>)
    +  declare <result> %llvm.readio (<ty> * <pointer>)
     
    Overview:
    @@ -2786,7 +2785,7 @@
    Syntax:
    -  call void (<ty1>, <ty2>*)* %llvm.writeio (<ty1> <value>, <ty2> * <pointer>)
    +  declare void %llvm.writeio (<ty1> <value>, <ty2> * <pointer>)
     
    Overview:
    @@ -3004,8 +3003,7 @@
    Syntax:
    -  call bool (<float or double>, <float or double>)* %llvm.isunordered(<float or double> Val1,
    -                                                                      <float or double> Val2)
    +  declare bool %llvm.isunordered(<float or double> Val1, <float or double> Val2)
     
    Overview:
    @@ -3057,7 +3055,7 @@ Chris Lattner
    The LLVM Compiler Infrastructure
    - Last modified: $Date: 2005/04/26 20:41:16 $ + Last modified: $Date: 2005/04/26 20:50:44 $ From reid at x10sys.com Tue Apr 26 17:46:34 2005 From: reid at x10sys.com (Reid Spencer) Date: Tue, 26 Apr 2005 17:46:34 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Message-ID: <200504262246.RAA07543@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: SimplifyLibCalls.cpp updated: 1.9 -> 1.10 --- Log message: memcpy returns void!!!!! --- Diffs of the changes: (+2 -8) SimplifyLibCalls.cpp | 10 ++-------- 1 files changed, 2 insertions(+), 8 deletions(-) Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.9 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.10 --- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.9 Tue Apr 26 14:55:57 2005 +++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Tue Apr 26 17:46:23 2005 @@ -205,8 +205,7 @@ args.push_back(PointerType::get(Type::SByteTy)); args.push_back(Type::IntTy); args.push_back(Type::IntTy); - memcpy_type = FunctionType::get( - PointerType::get(Type::SByteTy), args, false); + memcpy_type = FunctionType::get(Type::VoidTy, args, false); } return memcpy_type; } @@ -568,10 +567,7 @@ switch (len) { case 0: - // Just replace with the destination parameter since a zero length - // memcpy is a no-op. - ci->replaceAllUsesWith( - new CastInst(dest,PointerType::get(Type::VoidTy),"",ci)); + // The memcpy is a no-op so just dump its call. ci->eraseFromParent(); return true; case 1: @@ -595,8 +591,6 @@ } LoadInst* LI = new LoadInst(SrcCast,"",ci); StoreInst* SI = new StoreInst(LI, DestCast, ci); - ci->replaceAllUsesWith( - new CastInst(dest,PointerType::get(Type::VoidTy),"",ci)); ci->eraseFromParent(); return true; } From reid at x10sys.com Tue Apr 26 17:49:59 2005 From: reid at x10sys.com (Reid Spencer) Date: Tue, 26 Apr 2005 17:49:59 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Message-ID: <200504262249.RAA07556@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: SimplifyLibCalls.cpp updated: 1.10 -> 1.11 --- Log message: No, seriously folks, memcpy really does return void. --- Diffs of the changes: (+1 -1) SimplifyLibCalls.cpp | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.10 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.11 --- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.10 Tue Apr 26 17:46:23 2005 +++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Tue Apr 26 17:49:48 2005 @@ -535,7 +535,7 @@ { // Just make sure this has 4 arguments per LLVM spec. return (f->arg_size() == 4) && - (f->getReturnType() == PointerType::get(Type::VoidTy)); + (f->getReturnType() == Type::VoidTy); } /// Because of alignment and instruction information that we don't have, we From lattner at cs.uiuc.edu Tue Apr 26 17:56:33 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 26 Apr 2005 17:56:33 -0500 Subject: [llvm-commits] CVS: llvm/docs/ProgrammersManual.html Message-ID: <200504262256.j3QMuXuL010539@apoc.cs.uiuc.edu> Changes in directory llvm/docs: ProgrammersManual.html updated: 1.83 -> 1.84 --- Log message: update some paths --- Diffs of the changes: (+5 -5) ProgrammersManual.html | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) Index: llvm/docs/ProgrammersManual.html diff -u llvm/docs/ProgrammersManual.html:1.83 llvm/docs/ProgrammersManual.html:1.84 --- llvm/docs/ProgrammersManual.html:1.83 Mon Apr 25 10:47:57 2005 +++ llvm/docs/ProgrammersManual.html Tue Apr 26 17:56:16 2005 @@ -274,7 +274,7 @@ the fact that dynamic_cast<> only works on classes that have a v-table). Because they are used so often, you must know what they do and how they work. All of these templates are defined in the Support/Casting.h + href="/doxygen/Casting_8h-source.html">llvm/Support/Casting.h file (note that you very rarely have to include this file directly).

    @@ -379,7 +379,7 @@ but you don't want them to always be noisy. A standard compromise is to comment them out, allowing you to enable them if you need them in the future.

    -

    The "Support/Debug.h" +

    The "llvm/Support/Debug.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' (or any other @@ -427,7 +427,7 @@

    Of course, in practice, you should only set DEBUG_TYPE at the top of a file, to specify the debug type for the entire module (if you do this before -you #include "Support/Debug.h", you don't have to insert the ugly +you #include "llvm/Support/Debug.h", you don't have to insert the ugly #undef's). Also, you should use names more meaningful than "foo" and "bar", because there is no system in place to ensure that names do not conflict. If two different modules use the same string, they will all be turned @@ -446,7 +446,7 @@

    The "Support/Statistic.h" file +href="/doxygen/Statistic_8h-source.html">llvm/ADT/Statistic.h" file provides a template named Statistic that is used as a unified way to keep track of what the LLVM compiler is doing and how effective various optimizations are. It is useful to see what optimizations are contributing to @@ -2236,7 +2236,7 @@ Dinakar Dhurjati and Chris Lattner
    The LLVM Compiler Infrastructure
    - Last modified: $Date: 2005/04/25 15:47:57 $ + Last modified: $Date: 2005/04/26 22:56:16 $ From lattner at cs.uiuc.edu Tue Apr 26 17:57:21 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 26 Apr 2005 17:57:21 -0500 Subject: [llvm-commits] CVS: llvm/docs/ProgrammersManual.html Message-ID: <200504262257.j3QMvLQD010592@apoc.cs.uiuc.edu> Changes in directory llvm/docs: ProgrammersManual.html updated: 1.84 -> 1.85 --- Log message: no parens --- Diffs of the changes: (+2 -2) ProgrammersManual.html | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) Index: llvm/docs/ProgrammersManual.html diff -u llvm/docs/ProgrammersManual.html:1.84 llvm/docs/ProgrammersManual.html:1.85 --- llvm/docs/ProgrammersManual.html:1.84 Tue Apr 26 17:56:16 2005 +++ llvm/docs/ProgrammersManual.html Tue Apr 26 17:57:07 2005 @@ -407,7 +407,7 @@

    @@ -2236,7 +2236,7 @@ Dinakar Dhurjati and Chris Lattner
    The LLVM Compiler Infrastructure
    - Last modified: $Date: 2005/04/26 22:56:16 $ + Last modified: $Date: 2005/04/26 22:57:07 $ From reid at x10sys.com Tue Apr 26 18:02:27 2005 From: reid at x10sys.com (Reid Spencer) Date: Tue, 26 Apr 2005 18:02:27 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Message-ID: <200504262302.SAA07635@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: SimplifyLibCalls.cpp updated: 1.11 -> 1.12 --- Log message: Add some debugging output so we can tell which calls are getting triggered --- Diffs of the changes: (+9 -7) SimplifyLibCalls.cpp | 16 +++++++++------- 1 files changed, 9 insertions(+), 7 deletions(-) Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.11 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.12 --- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.11 Tue Apr 26 17:49:48 2005 +++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Tue Apr 26 18:02:16 2005 @@ -16,15 +16,17 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Transforms/IPO.h" -#include "llvm/Module.h" -#include "llvm/Pass.h" -#include "llvm/DerivedTypes.h" +#define DEBUG_TYPE "argpromotion" #include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" #include "llvm/Instructions.h" -#include "llvm/ADT/Statistic.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" #include "llvm/ADT/hash_map" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/Debug.h" #include "llvm/Target/TargetData.h" +#include "llvm/Transforms/IPO.h" #include using namespace llvm; @@ -167,6 +169,7 @@ { ++SimplifiedLibCalls; found_optimization = result = true; + DEBUG(std::cerr << "simplify-libcall: " << CO->getFunctionName()); } } } @@ -534,8 +537,7 @@ virtual bool ValidateCalledFunction(const Function* f, const TargetData& TD) { // Just make sure this has 4 arguments per LLVM spec. - return (f->arg_size() == 4) && - (f->getReturnType() == Type::VoidTy); + return (f->arg_size() == 4); } /// Because of alignment and instruction information that we don't have, we From reid at x10sys.com Tue Apr 26 18:05:28 2005 From: reid at x10sys.com (Reid Spencer) Date: Tue, 26 Apr 2005 18:05:28 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Message-ID: <200504262305.SAA07652@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: SimplifyLibCalls.cpp updated: 1.12 -> 1.13 --- Log message: Uh, this isn't argpromotion. --- Diffs of the changes: (+1 -1) SimplifyLibCalls.cpp | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.12 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.13 --- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.12 Tue Apr 26 18:02:16 2005 +++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Tue Apr 26 18:05:17 2005 @@ -16,7 +16,7 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "argpromotion" +#define DEBUG_TYPE "simplify-libcalls" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Instructions.h" From reid at x10sys.com Tue Apr 26 18:07:19 2005 From: reid at x10sys.com (Reid Spencer) Date: Tue, 26 Apr 2005 18:07:19 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Message-ID: <200504262307.SAA07664@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: SimplifyLibCalls.cpp updated: 1.13 -> 1.14 --- Log message: Fix up the debug statement to actually use a newline .. radical concept. --- Diffs of the changes: (+1 -1) SimplifyLibCalls.cpp | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.13 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.14 --- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.13 Tue Apr 26 18:05:17 2005 +++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Tue Apr 26 18:07:08 2005 @@ -169,7 +169,7 @@ { ++SimplifiedLibCalls; found_optimization = result = true; - DEBUG(std::cerr << "simplify-libcall: " << CO->getFunctionName()); + DEBUG(std::cerr << "simplify-libcall: " << CO->getFunctionName() << "\n"); } } } From lattner at cs.uiuc.edu Tue Apr 26 18:53:42 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 26 Apr 2005 18:53:42 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/PruneEH.cpp Message-ID: <200504262353.j3QNrg6G012070@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: PruneEH.cpp updated: 1.18 -> 1.19 --- Log message: This analysis doesn't take 'throwing' into consideration, it looks at 'unwinding' --- Diffs of the changes: (+13 -13) PruneEH.cpp | 26 +++++++++++++------------- 1 files changed, 13 insertions(+), 13 deletions(-) Index: llvm/lib/Transforms/IPO/PruneEH.cpp diff -u llvm/lib/Transforms/IPO/PruneEH.cpp:1.18 llvm/lib/Transforms/IPO/PruneEH.cpp:1.19 --- llvm/lib/Transforms/IPO/PruneEH.cpp:1.18 Thu Apr 21 18:39:37 2005 +++ llvm/lib/Transforms/IPO/PruneEH.cpp Tue Apr 26 18:53:25 2005 @@ -29,9 +29,9 @@ Statistic<> NumRemoved("prune-eh", "Number of invokes removed"); struct PruneEH : public CallGraphSCCPass { - /// DoesNotThrow - This set contains all of the functions which we have + /// DoesNotUnwind - This set contains all of the functions which we have /// determined cannot throw exceptions. - std::set DoesNotThrow; + std::set DoesNotUnwind; // runOnSCC - Analyze the SCC, performing the transformation if possible. bool runOnSCC(const std::vector &SCC); @@ -50,17 +50,17 @@ // If this SCC includes the unwind instruction, we KNOW it throws, so // obviously the SCC might throw. // - bool SCCMightThrow = false; - for (unsigned i = 0, e = SCC.size(); !SCCMightThrow && i != e; ++i) { + bool SCCMightUnwind = false; + for (unsigned i = 0, e = SCC.size(); !SCCMightUnwind && i != e; ++i) { Function *F = SCC[i]->getFunction(); if (F == 0 || (F->isExternal() && !F->getIntrinsicID())) { - SCCMightThrow = true; + SCCMightUnwind = true; } else { // Check to see if this function performs an unwind or calls an // unwinding function. for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { if (isa(BB->getTerminator())) { // Uses unwind! - SCCMightThrow = true; + SCCMightUnwind = true; break; } @@ -73,18 +73,18 @@ // If the callee is outside our current SCC, or if it is not // known to throw, then we might throw also. if (std::find(SCC.begin(), SCC.end(), CalleeNode) == SCC.end()&& - !DoesNotThrow.count(CalleeNode)) { - SCCMightThrow = true; + !DoesNotUnwind.count(CalleeNode)) { + SCCMightUnwind = true; break; } } else { // Indirect call, it might throw. - SCCMightThrow = true; + SCCMightUnwind = true; break; } } - if (SCCMightThrow) break; + if (SCCMightUnwind) break; } } } @@ -92,8 +92,8 @@ for (unsigned i = 0, e = SCC.size(); i != e; ++i) { // If the SCC can't throw, remember this for callers... - if (!SCCMightThrow) - DoesNotThrow.insert(SCC[i]); + if (!SCCMightUnwind) + DoesNotUnwind.insert(SCC[i]); // Convert any invoke instructions to non-throwing functions in this node // into call instructions with a branch. This makes the exception blocks @@ -102,7 +102,7 @@ for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) if (InvokeInst *II = dyn_cast(I->getTerminator())) if (Function *F = II->getCalledFunction()) - if (DoesNotThrow.count(CG[F])) { + if (DoesNotUnwind.count(CG[F])) { // Insert a call instruction before the invoke... std::string Name = II->getName(); II->setName(""); Value *Call = new CallInst(II->getCalledValue(), From reid at x10sys.com Tue Apr 26 19:05:56 2005 From: reid at x10sys.com (Reid Spencer) Date: Tue, 26 Apr 2005 19:05:56 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Message-ID: <200504270005.TAA07985@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: SimplifyLibCalls.cpp updated: 1.14 -> 1.15 --- Log message: In debug builds, make a statistic for each kind of call optimization. This helps track down what gets triggered in the pass so its easier to identify good test cases. --- Diffs of the changes: (+35 -21) SimplifyLibCalls.cpp | 56 +++++++++++++++++++++++++++++++-------------------- 1 files changed, 35 insertions(+), 21 deletions(-) Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.14 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.15 --- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.14 Tue Apr 26 18:07:08 2005 +++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Tue Apr 26 19:05:45 2005 @@ -96,8 +96,16 @@ ) = 0; const char * getFunctionName() const { return func_name; } + +#ifndef NDEBUG + void activate() { ++activations; } +#endif + private: const char* func_name; +#ifndef NDEBUG + Statistic<> activations; +#endif }; /// @brief The list of optimizations deriving from CallOptimizer @@ -106,6 +114,9 @@ CallOptimizer::CallOptimizer(const char* fname) : func_name(fname) +#ifndef NDEBUG + , activations(fname,"Number of calls simplified") +#endif { // Register this call optimizer optlist[func_name] = this; @@ -149,30 +160,33 @@ // because they live in a runtime library somewhere and were (probably) // not compiled by LLVM. So, we only act on external functions that have // external linkage and non-empty uses. - if (FI->isExternal() && FI->hasExternalLinkage() && !FI->use_empty()) + if (!FI->isExternal() || !FI->hasExternalLinkage() || FI->use_empty()) + continue; + + // Get the optimization class that pertains to this function + CallOptimizer* CO = optlist[FI->getName().c_str()]; + if (!CO) + continue; + + // Make sure the called function is suitable for the optimization + if (!CO->ValidateCalledFunction(FI,TD)) + continue; + + // Loop over each of the uses of the function + for (Value::use_iterator UI = FI->use_begin(), UE = FI->use_end(); + UI != UE ; ) { - // Get the optimization class that pertains to this function - if (CallOptimizer* CO = optlist[FI->getName().c_str()] ) + // If the use of the function is a call instruction + if (CallInst* CI = dyn_cast(*UI++)) { - // Make sure the called function is suitable for the optimization - if (CO->ValidateCalledFunction(FI,TD)) + // Do the optimization on the CallOptimizer. + if (CO->OptimizeCall(CI,TD)) { - // Loop over each of the uses of the function - for (Value::use_iterator UI = FI->use_begin(), UE = FI->use_end(); - UI != UE ; ) - { - // If the use of the function is a call instruction - if (CallInst* CI = dyn_cast(*UI++)) - { - // Do the optimization on the CallOptimizer. - if (CO->OptimizeCall(CI,TD)) - { - ++SimplifiedLibCalls; - found_optimization = result = true; - DEBUG(std::cerr << "simplify-libcall: " << CO->getFunctionName() << "\n"); - } - } - } + ++SimplifiedLibCalls; + found_optimization = result = true; +#ifndef NDEBUG + CO->activate(); +#endif } } } From reid at x10sys.com Tue Apr 26 19:20:34 2005 From: reid at x10sys.com (Reid Spencer) Date: Tue, 26 Apr 2005 19:20:34 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Message-ID: <200504270020.TAA08044@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: SimplifyLibCalls.cpp updated: 1.15 -> 1.16 --- Log message: Prefix the debug statistics so they group together. --- Diffs of the changes: (+3 -1) SimplifyLibCalls.cpp | 4 +++- 1 files changed, 3 insertions(+), 1 deletion(-) Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.15 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.16 --- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.15 Tue Apr 26 19:05:45 2005 +++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Tue Apr 26 19:20:23 2005 @@ -104,6 +104,7 @@ private: const char* func_name; #ifndef NDEBUG + std::string stat_name; Statistic<> activations; #endif }; @@ -115,7 +116,8 @@ CallOptimizer::CallOptimizer(const char* fname) : func_name(fname) #ifndef NDEBUG - , activations(fname,"Number of calls simplified") + , stat_name(std::string("simplify-libcalls:")+fname) + , activations(stat_name.c_str(),"Number of calls simplified") #endif { // Register this call optimizer From alenhar2 at cs.uiuc.edu Tue Apr 26 21:13:36 2005 From: alenhar2 at cs.uiuc.edu (Andrew Lenharth) Date: Tue, 26 Apr 2005 21:13:36 -0500 Subject: [llvm-commits] CVS: llvm/utils/parseNLT.pl Message-ID: <200504270213.j3R2DaCD014884@apoc.cs.uiuc.edu> Changes in directory llvm/utils: parseNLT.pl added (r1.1) --- Log message: A first step towards being able to do more interesting things with the nightly tester data. Moreinteresting things will come soon, so tune in --- Diffs of the changes: (+32 -0) parseNLT.pl | 32 ++++++++++++++++++++++++++++++++ 1 files changed, 32 insertions(+) Index: llvm/utils/parseNLT.pl diff -c /dev/null llvm/utils/parseNLT.pl:1.1 *** /dev/null Tue Apr 26 21:13:30 2005 --- llvm/utils/parseNLT.pl Tue Apr 26 21:13:20 2005 *************** *** 0 **** --- 1,32 ---- + #!/usr/bin/perl + # a first attempt to parse the nightly tester pages into something + # one can reason about, namely import into a database + # USE: perl parseNLT.pl <2005-03-31.html + # for example + + while(<>) + { + if (/LLVM Test Results for (\w+) (\d+), (\d+)([^<]+)<\/td>/) + { + if ($prefix) + { $output .= "$1 "; } + } + if (/(Programs.+)<\/h2>/) + { + $prefix = $1; + } + } + + if ($output) + { print "\n$day $mon $year $prefix/$output"; $output = ""; } From reid at x10sys.com Tue Apr 26 21:22:58 2005 From: reid at x10sys.com (Reid Spencer) Date: Tue, 26 Apr 2005 21:22:58 -0500 Subject: [llvm-commits] CVS: llvm/tools/gccas/gccas.cpp Message-ID: <200504270222.VAA08450@zion.cs.uiuc.edu> Changes in directory llvm/tools/gccas: gccas.cpp updated: 1.112 -> 1.113 --- Log message: Add the simplify-libcalls pass. --- Diffs of the changes: (+1 -0) gccas.cpp | 1 + 1 files changed, 1 insertion(+) Index: llvm/tools/gccas/gccas.cpp diff -u llvm/tools/gccas/gccas.cpp:1.112 llvm/tools/gccas/gccas.cpp:1.113 --- llvm/tools/gccas/gccas.cpp:1.112 Thu Apr 21 18:59:26 2005 +++ llvm/tools/gccas/gccas.cpp Tue Apr 26 21:22:47 2005 @@ -95,6 +95,7 @@ if (!DisableInline) addPass(PM, createFunctionInliningPass()); // Inline small functions + addPass(PM, createSimplifyLibCallsPass()); // Library Call Optimizations addPass(PM, createArgumentPromotionPass()); // Scalarize uninlined fn args addPass(PM, createRaisePointerReferencesPass());// Recover type information From lattner at cs.uiuc.edu Tue Apr 26 23:51:17 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 26 Apr 2005 23:51:17 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/PruneEH/simplenoreturntest.ll Message-ID: <200504270451.j3R4pHWc021079@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/PruneEH: simplenoreturntest.ll added (r1.1) --- Log message: Test the noreturn function optimization --- Diffs of the changes: (+16 -0) simplenoreturntest.ll | 16 ++++++++++++++++ 1 files changed, 16 insertions(+) Index: llvm/test/Regression/Transforms/PruneEH/simplenoreturntest.ll diff -c /dev/null llvm/test/Regression/Transforms/PruneEH/simplenoreturntest.ll:1.1 *** /dev/null Tue Apr 26 23:51:11 2005 --- llvm/test/Regression/Transforms/PruneEH/simplenoreturntest.ll Tue Apr 26 23:51:01 2005 *************** *** 0 **** --- 1,16 ---- + ; RUN: llvm-as < %s | opt -prune-eh | llvm-dis | not grep 'ret int' + + void %noreturn() { + unwind + } + + int %caller() { + ; noreturn never returns, so the ret is unreachable. + call void %noreturn() + ret int 17 + } + + int %caller2() { + %T = call int %caller() + ret int %T ;; this is also unreachable! + } From lattner at cs.uiuc.edu Tue Apr 26 23:52:37 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 26 Apr 2005 23:52:37 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/PruneEH.cpp Message-ID: <200504270452.j3R4qbIh021090@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: PruneEH.cpp updated: 1.19 -> 1.20 --- Log message: detect functions that never return, and turn the instruction following a call to them into an 'unreachable' instruction. This triggers a bunch of times, particularly on gcc: gzip: 36 gcc: 601 eon: 12 bzip: 38 --- Diffs of the changes: (+142 -49) PruneEH.cpp | 191 ++++++++++++++++++++++++++++++++++++++++++++---------------- 1 files changed, 142 insertions(+), 49 deletions(-) Index: llvm/lib/Transforms/IPO/PruneEH.cpp diff -u llvm/lib/Transforms/IPO/PruneEH.cpp:1.19 llvm/lib/Transforms/IPO/PruneEH.cpp:1.20 --- llvm/lib/Transforms/IPO/PruneEH.cpp:1.19 Tue Apr 26 18:53:25 2005 +++ llvm/lib/Transforms/IPO/PruneEH.cpp Tue Apr 26 23:52:23 2005 @@ -16,25 +16,35 @@ #include "llvm/Transforms/IPO.h" #include "llvm/CallGraphSCCPass.h" +#include "llvm/Constants.h" #include "llvm/Function.h" #include "llvm/Intrinsics.h" #include "llvm/Instructions.h" #include "llvm/Analysis/CallGraph.h" #include "llvm/ADT/Statistic.h" +#include "llvm/Support/CFG.h" #include #include using namespace llvm; namespace { Statistic<> NumRemoved("prune-eh", "Number of invokes removed"); + Statistic<> NumUnreach("prune-eh", "Number of noreturn calls optimized"); struct PruneEH : public CallGraphSCCPass { /// DoesNotUnwind - This set contains all of the functions which we have - /// determined cannot throw exceptions. + /// determined cannot unwind. std::set DoesNotUnwind; + /// DoesNotReturn - This set contains all of the functions which we have + /// determined cannot return normally (but might unwind). + std::set DoesNotReturn; + // runOnSCC - Analyze the SCC, performing the transformation if possible. bool runOnSCC(const std::vector &SCC); + + bool SimplifyFunction(Function *F); + void DeleteBasicBlock(BasicBlock *BB); }; RegisterOpt X("prune-eh", "Remove unused exception handling info"); } @@ -44,89 +54,172 @@ bool PruneEH::runOnSCC(const std::vector &SCC) { CallGraph &CG = getAnalysis(); + bool MadeChange = false; + + // First pass, scan all of the functions in the SCC, simplifying them + // according to what we know. + for (unsigned i = 0, e = SCC.size(); i != e; ++i) + if (Function *F = SCC[i]->getFunction()) + MadeChange |= SimplifyFunction(F); - // First, check to see if any callees might throw or if there are any external + // Next, check to see if any callees might throw or if there are any external // functions in this SCC: if so, we cannot prune any functions in this SCC. // If this SCC includes the unwind instruction, we KNOW it throws, so // obviously the SCC might throw. // - bool SCCMightUnwind = false; - for (unsigned i = 0, e = SCC.size(); !SCCMightUnwind && i != e; ++i) { + bool SCCMightUnwind = false, SCCMightReturn = false; + for (unsigned i = 0, e = SCC.size(); + (!SCCMightUnwind || !SCCMightReturn) && i != e; ++i) { Function *F = SCC[i]->getFunction(); if (F == 0 || (F->isExternal() && !F->getIntrinsicID())) { SCCMightUnwind = true; + SCCMightReturn = true; } else { + if (F->isExternal()) + SCCMightReturn = true; + // Check to see if this function performs an unwind or calls an // unwinding function. for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { if (isa(BB->getTerminator())) { // Uses unwind! SCCMightUnwind = true; - break; + } else if (isa(BB->getTerminator())) { + SCCMightReturn = true; } // Invoke instructions don't allow unwinding to continue, so we are // only interested in call instructions. - for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) - if (CallInst *CI = dyn_cast(I)) { - if (Function *Callee = CI->getCalledFunction()) { - CallGraphNode *CalleeNode = CG[Callee]; - // If the callee is outside our current SCC, or if it is not - // known to throw, then we might throw also. - if (std::find(SCC.begin(), SCC.end(), CalleeNode) == SCC.end()&& - !DoesNotUnwind.count(CalleeNode)) { + if (!SCCMightUnwind) + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) + if (CallInst *CI = dyn_cast(I)) { + if (Function *Callee = CI->getCalledFunction()) { + CallGraphNode *CalleeNode = CG[Callee]; + // If the callee is outside our current SCC, or if it is not + // known to throw, then we might throw also. + if (std::find(SCC.begin(), SCC.end(), CalleeNode) == SCC.end()&& + !DoesNotUnwind.count(CalleeNode)) { + SCCMightUnwind = true; + break; + } + } else { + // Indirect call, it might throw. SCCMightUnwind = true; break; } - - } else { - // Indirect call, it might throw. - SCCMightUnwind = true; - break; } - } - if (SCCMightUnwind) break; + if (SCCMightUnwind && SCCMightReturn) break; } } } - bool MadeChange = false; - for (unsigned i = 0, e = SCC.size(); i != e; ++i) { - // If the SCC can't throw, remember this for callers... - if (!SCCMightUnwind) + // If the SCC doesn't unwind or doesn't throw, note this fact. + if (!SCCMightUnwind) + for (unsigned i = 0, e = SCC.size(); i != e; ++i) DoesNotUnwind.insert(SCC[i]); + if (!SCCMightReturn) + for (unsigned i = 0, e = SCC.size(); i != e; ++i) + DoesNotReturn.insert(SCC[i]); + for (unsigned i = 0, e = SCC.size(); i != e; ++i) { // Convert any invoke instructions to non-throwing functions in this node // into call instructions with a branch. This makes the exception blocks // dead. if (Function *F = SCC[i]->getFunction()) - for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) - if (InvokeInst *II = dyn_cast(I->getTerminator())) - if (Function *F = II->getCalledFunction()) - if (DoesNotUnwind.count(CG[F])) { - // Insert a call instruction before the invoke... - std::string Name = II->getName(); II->setName(""); - Value *Call = new CallInst(II->getCalledValue(), - std::vector(II->op_begin()+3, - II->op_end()), - Name, II); - - // Anything that used the value produced by the invoke instruction - // now uses the value produced by the call instruction. - II->replaceAllUsesWith(Call); - II->getUnwindDest()->removePredecessor(II->getParent()); - - // Insert a branch to the normal destination right before the - // invoke. - new BranchInst(II->getNormalDest(), II); + MadeChange |= SimplifyFunction(F); + } - // Finally, delete the invoke instruction! - I->getInstList().pop_back(); + return MadeChange; +} - ++NumRemoved; - MadeChange = true; - } - } +// SimplifyFunction - Given information about callees, simplify the specified +// function if we have invokes to non-unwinding functions or code after calls to +// no-return functions. +bool PruneEH::SimplifyFunction(Function *F) { + CallGraph &CG = getAnalysis(); + bool MadeChange = false; + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { + if (InvokeInst *II = dyn_cast(BB->getTerminator())) + if (Function *F = II->getCalledFunction()) + if (DoesNotUnwind.count(CG[F])) { + // Insert a call instruction before the invoke... + std::string Name = II->getName(); II->setName(""); + Value *Call = new CallInst(II->getCalledValue(), + std::vector(II->op_begin()+3, + II->op_end()), + Name, II); + + // Anything that used the value produced by the invoke instruction + // now uses the value produced by the call instruction. + II->replaceAllUsesWith(Call); + BasicBlock *UnwindBlock = II->getUnwindDest(); + UnwindBlock->removePredecessor(II->getParent()); + + // Insert a branch to the normal destination right before the + // invoke. + new BranchInst(II->getNormalDest(), II); + + // Finally, delete the invoke instruction! + BB->getInstList().pop_back(); + + // If the unwind block is now dead, nuke it. + if (pred_begin(UnwindBlock) == pred_end(UnwindBlock)) + DeleteBasicBlock(UnwindBlock); // Delete the new BB. + + ++NumRemoved; + MadeChange = true; + } + + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; I) + if (CallInst *CI = dyn_cast(I++)) + if (Function *Callee = CI->getCalledFunction()) + if (DoesNotReturn.count(CG[Callee]) && !isa(I)) { + // This call calls a function that cannot return. Insert an + // unreachable instruction after it and simplify the code. Do this + // by splitting the BB, adding the unreachable, then deleting the + // new BB. + BasicBlock *New = BB->splitBasicBlock(I); + + // Remove the uncond branch and add an unreachable. + BB->getInstList().pop_back(); + new UnreachableInst(BB); + + DeleteBasicBlock(New); // Delete the new BB. + MadeChange = true; + ++NumUnreach; + break; + } + + } return MadeChange; } +/// DeleteBasicBlock - remove the specified basic block from the program, +/// updating the callgraph to reflect any now-obsolete edges due to calls that +/// exist in the BB. +void PruneEH::DeleteBasicBlock(BasicBlock *BB) { + assert(pred_begin(BB) == pred_end(BB) && "BB is not dead!"); + CallGraph &CG = getAnalysis(); + + CallGraphNode *CGN = CG[BB->getParent()]; + for (BasicBlock::iterator I = BB->end(), E = BB->begin(); I != E; ) { + --I; + if (CallInst *CI = dyn_cast(I)) { + if (Function *Callee = CI->getCalledFunction()) + CGN->removeCallEdgeTo(CG[Callee]); + } else if (InvokeInst *II = dyn_cast(I)) { + if (Function *Callee = II->getCalledFunction()) + CGN->removeCallEdgeTo(CG[Callee]); + } + if (!I->use_empty()) + I->replaceAllUsesWith(UndefValue::get(I->getType())); + } + + // Get the list of successors of this block. + std::vector Succs(succ_begin(BB), succ_end(BB)); + + for (unsigned i = 0, e = Succs.size(); i != e; ++i) + Succs[i]->removePredecessor(BB); + + BB->eraseFromParent(); +} From tbrethou at cs.uiuc.edu Wed Apr 27 00:08:27 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Wed, 27 Apr 2005 00:08:27 -0500 Subject: [llvm-commits] CVS: llvm-test/MultiSource/Applications/Makefile Message-ID: <200504270508.j3R58RJ4021513@apoc.cs.uiuc.edu> Changes in directory llvm-test/MultiSource/Applications: Makefile updated: 1.17 -> 1.18 --- Log message: Disable SPASS on sparc since it seems to be infinitely looping. --- Diffs of the changes: (+4 -0) Makefile | 4 ++++ 1 files changed, 4 insertions(+) Index: llvm-test/MultiSource/Applications/Makefile diff -u llvm-test/MultiSource/Applications/Makefile:1.17 llvm-test/MultiSource/Applications/Makefile:1.18 --- llvm-test/MultiSource/Applications/Makefile:1.17 Sun Apr 24 23:26:57 2005 +++ llvm-test/MultiSource/Applications/Makefile Wed Apr 27 00:08:11 2005 @@ -21,4 +21,8 @@ PARALLEL_DIRS += kimwitu++ endif +ifeq ($(OS),SunOS) +PARALLEL_DIRS := $(filter-out SPASS, $(PARALLEL_DIRS)) +endif + include $(LEVEL)/Makefile.programs From reid at x10sys.com Wed Apr 27 02:54:51 2005 From: reid at x10sys.com (Reid Spencer) Date: Wed, 27 Apr 2005 02:54:51 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Message-ID: <200504270754.CAA11388@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: SimplifyLibCalls.cpp updated: 1.16 -> 1.17 --- Log message: This is a cleanup commit: * Correct stale documentation in a few places * Re-order the file to better associate things and reduce line count * Make the pass thread safe by caching the Function* objects needed by the optimizers in the pass object instead of globally. * Provide the SimplifyLibCalls pass object to the optimizer classes so they can access cached Function* objects and TargetData info * Make sure the pass resets its cache if the Module passed to runOnModule changes * Rename CallOptimizer LibCallOptimization. All the classes are named *Optimization while the objects are *Optimizer. * Don't cache Function* in the optimizer objects because they could be used by multiple PassManager's running in multiple threads * Add an optimization for strcpy which is similar to strcat * Add a "TODO" list at the end of the file for ideas on additional libcall optimizations that could be added (get ideas from other compilers). Sorry for the huge diff. Its mostly reorganization of code. That won't happen again as I believe the design and infrastructure for this pass is now done or close to it. --- Diffs of the changes: (+411 -306) SimplifyLibCalls.cpp | 717 +++++++++++++++++++++++++++++---------------------- 1 files changed, 411 insertions(+), 306 deletions(-) Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.16 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.17 --- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.16 Tue Apr 26 19:20:23 2005 +++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Wed Apr 27 02:54:40 2005 @@ -31,192 +31,192 @@ using namespace llvm; namespace { - Statistic<> SimplifiedLibCalls("simplified-lib-calls", - "Number of well-known library calls simplified"); - /// This class is the base class for a set of small but important - /// optimizations of calls to well-known functions, such as those in the c - /// library. This class provides the basic infrastructure for handling - /// runOnModule. Subclasses register themselves and provide two methods: - /// RecognizeCall and OptimizeCall. Whenever this class finds a function call, - /// it asks the subclasses to recognize the call. If it is recognized, then - /// the OptimizeCall method is called on that subclass instance. In this way - /// the subclasses implement the calling conditions on which they trigger and - /// the action to perform, making it easy to add new optimizations of this - /// form. - /// @brief A ModulePass for optimizing well-known function calls - struct SimplifyLibCalls : public ModulePass { - - /// We need some target data for accurate signature details that are - /// target dependent. So we require target data in our AnalysisUsage. - virtual void getAnalysisUsage(AnalysisUsage& Info) const; - - /// For this pass, process all of the function calls in the module, calling - /// RecognizeCall and OptimizeCall as appropriate. - virtual bool runOnModule(Module &M); - - }; - - RegisterOpt - X("simplify-libcalls","Simplify well-known library calls"); - - struct CallOptimizer - { - /// @brief Constructor that registers the optimization - CallOptimizer(const char * fname ); - - virtual ~CallOptimizer(); - - /// The implementation of this function in subclasses should determine if - /// \p F is suitable for the optimization. This method is called by - /// runOnModule to short circuit visiting all the call sites of such a - /// function if that function is not suitable in the first place. - /// If the called function is suitabe, this method should return true; - /// false, otherwise. This function should also perform any lazy - /// initialization that the CallOptimizer needs to do, if its to return - /// true. This avoids doing initialization until the optimizer is actually - /// going to be called upon to do some optimization. - virtual bool ValidateCalledFunction( - const Function* F, ///< The function that is the target of call sites - const TargetData& TD ///< Information about the target - ) = 0; - - /// The implementations of this function in subclasses is the heart of the - /// SimplifyLibCalls algorithm. Sublcasses of this class implement - /// OptimizeCall to determine if (a) the conditions are right for optimizing - /// the call and (b) to perform the optimization. If an action is taken - /// against ci, the subclass is responsible for returning true and ensuring - /// that ci is erased from its parent. - /// @param ci the call instruction under consideration - /// @param f the function that ci calls. - /// @brief Optimize a call, if possible. - virtual bool OptimizeCall( - CallInst* ci, ///< The call instruction that should be optimized. - const TargetData& TD ///< Information about the target - ) = 0; - - const char * getFunctionName() const { return func_name; } - -#ifndef NDEBUG - void activate() { ++activations; } -#endif - - private: - const char* func_name; -#ifndef NDEBUG - std::string stat_name; - Statistic<> activations; -#endif - }; - - /// @brief The list of optimizations deriving from CallOptimizer - - hash_map optlist; - - CallOptimizer::CallOptimizer(const char* fname) +/// This statistic keeps track of the total number of library calls that have +/// been simplified regardless of which call it is. +Statistic<> SimplifiedLibCalls("simplify-libcalls", + "Number of well-known library calls simplified"); + +/// @brief The list of optimizations deriving from LibCallOptimization +class LibCallOptimization; +class SimplifyLibCalls; +hash_map optlist; + +/// This class is the abstract base class for the set of optimizations that +/// corresponds to one library call. The SimplifyLibCall pass will call the +/// ValidateCalledFunction method to ask the optimization if a given Function +/// is the kind that the optimization can handle. It will also call the +/// OptimizeCall method to perform, or attempt to perform, the optimization(s) +/// for the library call. Subclasses of this class are located toward the +/// end of this file. +/// @brief Base class for library call optimizations +struct LibCallOptimization +{ + /// @brief Constructor that registers the optimization. The \p fname argument + /// must be the name of the library function being optimized by the subclass. + LibCallOptimization(const char * fname ) : func_name(fname) #ifndef NDEBUG , stat_name(std::string("simplify-libcalls:")+fname) - , activations(stat_name.c_str(),"Number of calls simplified") + , occurrences(stat_name.c_str(),"Number of calls simplified") #endif { // Register this call optimizer optlist[func_name] = this; } - /// Make sure we get our virtual table in this file. - CallOptimizer::~CallOptimizer() { } + /// @brief Destructor + virtual ~LibCallOptimization() {} -} - -ModulePass *llvm::createSimplifyLibCallsPass() -{ - return new SimplifyLibCalls(); -} + /// The implementation of this function in subclasses should determine if + /// \p F is suitable for the optimization. This method is called by + /// runOnModule to short circuit visiting all the call sites of such a + /// function if that function is not suitable in the first place. + /// If the called function is suitabe, this method should return true; + /// false, otherwise. This function should also perform any lazy + /// initialization that the LibCallOptimization needs to do, if its to return + /// true. This avoids doing initialization until the optimizer is actually + /// going to be called upon to do some optimization. + virtual bool ValidateCalledFunction( + const Function* F, ///< The function that is the target of call sites + SimplifyLibCalls& SLC ///< The pass object invoking us + ) = 0; + + /// The implementations of this function in subclasses is the heart of the + /// SimplifyLibCalls algorithm. Sublcasses of this class implement + /// OptimizeCall to determine if (a) the conditions are right for optimizing + /// the call and (b) to perform the optimization. If an action is taken + /// against ci, the subclass is responsible for returning true and ensuring + /// that ci is erased from its parent. + /// @param ci the call instruction under consideration + /// @param f the function that ci calls. + /// @brief Optimize a call, if possible. + virtual bool OptimizeCall( + CallInst* ci, ///< The call instruction that should be optimized. + SimplifyLibCalls& SLC ///< The pass object invoking us + ) = 0; -void SimplifyLibCalls::getAnalysisUsage(AnalysisUsage& Info) const -{ - // Ask that the TargetData analysis be performed before us so we can use - // the target data. - Info.addRequired(); -} + /// @brief Get the name of the library call being optimized + const char * getFunctionName() const { return func_name; } -bool SimplifyLibCalls::runOnModule(Module &M) -{ - TargetData& TD = getAnalysis(); +#ifndef NDEBUG + void occurred() { ++occurrences; } +#endif - bool result = false; +private: + const char* func_name; ///< Name of the library call we optimize +#ifndef NDEBUG + std::string stat_name; ///< Holder for debug statistic name + Statistic<> occurrences; ///< debug statistic (-debug-only=simplify-libcalls) +#endif +}; - // The call optimizations can be recursive. That is, the optimization might - // generate a call to another function which can also be optimized. This way - // we make the CallOptimizer instances very specific to the case they handle. - // It also means we need to keep running over the function calls in the module - // until we don't get any more optimizations possible. - bool found_optimization = false; - do - { - found_optimization = false; - for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI) +/// This class is the base class for a set of small but important +/// optimizations of calls to well-known functions, such as those in the c +/// library. + +/// This class is an LLVM Pass that applies each of the LibCallOptimization +/// instances to all the call sites in a module, relatively efficiently. The +/// purpose of this pass is to provide optimizations for calls to well-known +/// functions with well-known semantics, such as those in the c library. The +/// class provides the basic infrastructure for handling runOnModule. +/// Whenever this pass finds a function call, it asks the subclasses to +/// validate the call by calling ValidateLibraryCall. If it is validated, then +/// the OptimizeCall method is called. +/// @brief A ModulePass for optimizing well-known function calls. +struct SimplifyLibCalls : public ModulePass +{ + /// We need some target data for accurate signature details that are + /// target dependent. So we require target data in our AnalysisUsage. + virtual void getAnalysisUsage(AnalysisUsage& Info) const + { + // Ask that the TargetData analysis be performed before us so we can use + // the target data. + Info.addRequired(); + } + + /// For this pass, process all of the function calls in the module, calling + /// ValidateLibraryCall and OptimizeCall as appropriate. + virtual bool runOnModule(Module &M) + { + reset(M); + + bool result = false; + + // The call optimizations can be recursive. That is, the optimization might + // generate a call to another function which can also be optimized. This way + // we make the LibCallOptimization instances very specific to the case they + // handle. It also means we need to keep running over the function calls in + // the module until we don't get any more optimizations possible. + bool found_optimization = false; + do { - // All the "well-known" functions are external and have external linkage - // because they live in a runtime library somewhere and were (probably) - // not compiled by LLVM. So, we only act on external functions that have - // external linkage and non-empty uses. - if (!FI->isExternal() || !FI->hasExternalLinkage() || FI->use_empty()) - continue; - - // Get the optimization class that pertains to this function - CallOptimizer* CO = optlist[FI->getName().c_str()]; - if (!CO) - continue; - - // Make sure the called function is suitable for the optimization - if (!CO->ValidateCalledFunction(FI,TD)) - continue; - - // Loop over each of the uses of the function - for (Value::use_iterator UI = FI->use_begin(), UE = FI->use_end(); - UI != UE ; ) + found_optimization = false; + for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI) { - // If the use of the function is a call instruction - if (CallInst* CI = dyn_cast(*UI++)) + // All the "well-known" functions are external and have external linkage + // because they live in a runtime library somewhere and were (probably) + // not compiled by LLVM. So, we only act on external functions that have + // external linkage and non-empty uses. + if (!FI->isExternal() || !FI->hasExternalLinkage() || FI->use_empty()) + continue; + + // Get the optimization class that pertains to this function + LibCallOptimization* CO = optlist[FI->getName().c_str()]; + if (!CO) + continue; + + // Make sure the called function is suitable for the optimization + if (!CO->ValidateCalledFunction(FI,*this)) + continue; + + // Loop over each of the uses of the function + for (Value::use_iterator UI = FI->use_begin(), UE = FI->use_end(); + UI != UE ; ) { - // Do the optimization on the CallOptimizer. - if (CO->OptimizeCall(CI,TD)) + // If the use of the function is a call instruction + if (CallInst* CI = dyn_cast(*UI++)) { - ++SimplifiedLibCalls; - found_optimization = result = true; + // Do the optimization on the LibCallOptimization. + if (CO->OptimizeCall(CI,*this)) + { + ++SimplifiedLibCalls; + found_optimization = result = true; #ifndef NDEBUG - CO->activate(); + CO->occurred(); #endif + } } } } - } - } while (found_optimization); - return result; -} + } while (found_optimization); + return result; + } -namespace { + /// @brief Return the *current* module we're working on. + Module* getModule() { return M; } + + /// @brief Return the *current* target data for the module we're working on. + TargetData* getTargetData() { return TD; } - /// Provide some functions for accessing standard library prototypes and - /// caching them so we don't have to keep recomputing them - FunctionType* get_strlen(const Type* IntPtrTy) + /// @brief Return a Function* for the strlen libcall + Function* get_strlen() { - static FunctionType* strlen_type = 0; - if (!strlen_type) + if (!strlen_func) { std::vector args; args.push_back(PointerType::get(Type::SByteTy)); - strlen_type = FunctionType::get(IntPtrTy, args, false); + FunctionType* strlen_type = + FunctionType::get(TD->getIntPtrType(), args, false); + strlen_func = M->getOrInsertFunction("strlen",strlen_type); } - return strlen_type; + return strlen_func; } - FunctionType* get_memcpy() + /// @brief Return a Function* for the memcpy libcall + Function* get_memcpy() { - static FunctionType* memcpy_type = 0; - if (!memcpy_type) + if (!memcpy_func) { // Note: this is for llvm.memcpy intrinsic std::vector args; @@ -224,120 +224,65 @@ args.push_back(PointerType::get(Type::SByteTy)); args.push_back(Type::IntTy); args.push_back(Type::IntTy); - memcpy_type = FunctionType::get(Type::VoidTy, args, false); + FunctionType* memcpy_type = FunctionType::get(Type::VoidTy, args, false); + memcpy_func = M->getOrInsertFunction("llvm.memcpy",memcpy_type); } - return memcpy_type; + return memcpy_func; } - /// A function to compute the length of a null-terminated string of integers. - /// This function can't rely on the size of the constant array because there - /// could be a null terminator in the middle of the array. We also have to - /// bail out if we find a non-integer constant initializer of one of the - /// elements or if there is no null-terminator. The logic below checks - bool getConstantStringLength(Value* V, uint64_t& len ) - { - assert(V != 0 && "Invalid args to getConstantStringLength"); - len = 0; // make sure we initialize this - User* GEP = 0; - // If the value is not a GEP instruction nor a constant expression with a - // GEP instruction, then return false because ConstantArray can't occur - // any other way - if (GetElementPtrInst* GEPI = dyn_cast(V)) - GEP = GEPI; - else if (ConstantExpr* CE = dyn_cast(V)) - if (CE->getOpcode() == Instruction::GetElementPtr) - GEP = CE; - else - return false; - else - return false; - - // Make sure the GEP has exactly three arguments. - if (GEP->getNumOperands() != 3) - return false; - - // Check to make sure that the first operand of the GEP is an integer and - // has value 0 so that we are sure we're indexing into the initializer. - if (ConstantInt* op1 = dyn_cast(GEP->getOperand(1))) - { - if (!op1->isNullValue()) - return false; - } - else - return false; - - // Ensure that the second operand is a ConstantInt. If it isn't then this - // GEP is wonky and we're not really sure what were referencing into and - // better of not optimizing it. While we're at it, get the second index - // value. We'll need this later for indexing the ConstantArray. - uint64_t start_idx = 0; - if (ConstantInt* CI = dyn_cast(GEP->getOperand(2))) - start_idx = CI->getRawValue(); - else - return false; + /// @brief Compute length of constant string + bool getConstantStringLength(Value* V, uint64_t& len ); - // The GEP instruction, constant or instruction, must reference a global - // variable that is a constant and is initialized. The referenced constant - // initializer is the array that we'll use for optimization. - GlobalVariable* GV = dyn_cast(GEP->getOperand(0)); - if (!GV || !GV->isConstant() || !GV->hasInitializer()) - return false; +private: + void reset(Module& mod) + { + M = &mod; + TD = &getAnalysis(); + memcpy_func = 0; + strlen_func = 0; + } - // Get the initializer. - Constant* INTLZR = GV->getInitializer(); +private: + Function* memcpy_func; + Function* strlen_func; + Module* M; + TargetData* TD; +}; - // Handle the ConstantAggregateZero case - if (ConstantAggregateZero* CAZ = dyn_cast(INTLZR)) - { - // This is a degenerate case. The initializer is constant zero so the - // length of the string must be zero. - len = 0; - return true; - } +// Register the pass +RegisterOpt +X("simplify-libcalls","Simplify well-known library calls"); - // Must be a Constant Array - ConstantArray* A = dyn_cast(INTLZR); - if (!A) - return false; +} // anonymous namespace - // Get the number of elements in the array - uint64_t max_elems = A->getType()->getNumElements(); +// The only public symbol in this file which just instantiates the pass object +ModulePass *llvm::createSimplifyLibCallsPass() +{ + return new SimplifyLibCalls(); +} - // Traverse the constant array from start_idx (derived above) which is - // the place the GEP refers to in the array. - for ( len = start_idx; len < max_elems; len++) - { - if (ConstantInt* CI = dyn_cast(A->getOperand(len))) - { - // Check for the null terminator - if (CI->isNullValue()) - break; // we found end of string - } - else - return false; // This array isn't suitable, non-int initializer - } - if (len >= max_elems) - return false; // This array isn't null terminated +// Classes below here, in the anonymous namespace, are all subclasses of the +// LibCallOptimization class, each implementing all optimizations possible for a +// single well-known library call. Each has a static singleton instance that +// auto registers it into the "optlist" global above. +namespace { - // Subtract out the initial value from the length - len -= start_idx; - return true; // success! - } +bool getConstantStringLength(Value* V, uint64_t& len ); -/// This CallOptimizer will find instances of a call to "exit" that occurs +/// This LibCallOptimization will find instances of a call to "exit" that occurs /// within the "main" function and change it to a simple "ret" instruction with /// the same value as passed to the exit function. It assumes that the /// instructions after the call to exit(3) can be deleted since they are /// unreachable anyway. /// @brief Replace calls to exit in main with a simple return -struct ExitInMainOptimization : public CallOptimizer +struct ExitInMainOptimization : public LibCallOptimization { - ExitInMainOptimization() : CallOptimizer("exit") {} + ExitInMainOptimization() : LibCallOptimization("exit") {} virtual ~ExitInMainOptimization() {} // Make sure the called function looks like exit (int argument, int return // type, external linkage, not varargs). - virtual bool ValidateCalledFunction(const Function* f, const TargetData& TD) + virtual bool ValidateCalledFunction(const Function* f, SimplifyLibCalls& SLC) { if (f->arg_size() >= 1) if (f->arg_begin()->getType()->isInteger()) @@ -345,7 +290,7 @@ return false; } - virtual bool OptimizeCall(CallInst* ci, const TargetData& TD) + virtual bool OptimizeCall(CallInst* ci, SimplifyLibCalls& SLC) { // To be careful, we check that the call to exit is coming from "main", that // main has external linkage, and the return type of main and the argument @@ -386,41 +331,23 @@ } } ExitInMainOptimizer; -/// This CallOptimizer will simplify a call to the strcat library function. The -/// simplification is possible only if the string being concatenated is a -/// constant array or a constant expression that results in a constant array. In -/// this case, if the array is small, we can generate a series of inline store -/// instructions to effect the concatenation without calling strcat. +/// This LibCallOptimization will simplify a call to the strcat library +/// function. The simplification is possible only if the string being +/// concatenated is a constant array or a constant expression that results in +/// a constant array. In this case, if the array is small, we can generate a +/// series of inline store instructions to effect the concatenation without +/// calling strcat. /// @brief Simplify the strcat library function. -struct StrCatOptimization : public CallOptimizer +struct StrCatOptimization : public LibCallOptimization { -private: - Function* strlen_func; - Function* memcpy_func; public: - StrCatOptimization() - : CallOptimizer("strcat") - , strlen_func(0) - , memcpy_func(0) - {} - virtual ~StrCatOptimization() {} - - inline Function* get_strlen_func(Module*M,const Type* IntPtrTy) - { - if (strlen_func) - return strlen_func; - return strlen_func = M->getOrInsertFunction("strlen",get_strlen(IntPtrTy)); - } + StrCatOptimization() : LibCallOptimization("strcat") {} - inline Function* get_memcpy_func(Module* M) - { - if (memcpy_func) - return memcpy_func; - return memcpy_func = M->getOrInsertFunction("llvm.memcpy",get_memcpy()); - } +public: + virtual ~StrCatOptimization() {} /// @brief Make sure that the "strcat" function has the right prototype - virtual bool ValidateCalledFunction(const Function* f, const TargetData& TD) + virtual bool ValidateCalledFunction(const Function* f, SimplifyLibCalls& SLC) { if (f->getReturnType() == PointerType::get(Type::SByteTy)) if (f->arg_size() == 2) @@ -429,13 +356,6 @@ if (AI++->getType() == PointerType::get(Type::SByteTy)) if (AI->getType() == PointerType::get(Type::SByteTy)) { - // Invalidate the pre-computed strlen_func and memcpy_func Functions - // because, by definition, this method is only called when a new - // Module is being traversed. Invalidation causes re-computation for - // the new Module (if necessary). - strlen_func = 0; - memcpy_func = 0; - // Indicate this is a suitable call type. return true; } @@ -443,9 +363,8 @@ return false; } - /// Perform the optimization if the length of the string concatenated - /// is reasonably short and it is a constant array. - virtual bool OptimizeCall(CallInst* ci, const TargetData& TD) + /// @brief Optimize the strcat library function + virtual bool OptimizeCall(CallInst* ci, SimplifyLibCalls& SLC) { // Extract the initializer (while making numerous checks) from the // source operand of the call to strcat. If we get null back, one of @@ -471,11 +390,10 @@ // We need to find the end of the destination string. That's where the // memory is to be moved to. We just generate a call to strlen (further - // optimized in another pass). Note that the get_strlen_func() call + // optimized in another pass). Note that the SLC.get_strlen() call // caches the Function* for us. CallInst* strlen_inst = - new CallInst(get_strlen_func(M,TD.getIntPtrType()), - ci->getOperand(1),"",ci); + new CallInst(SLC.get_strlen(), ci->getOperand(1),"",ci); // Now that we have the destination's length, we must index into the // destination's pointer to get the actual memcpy destination (end of @@ -492,7 +410,7 @@ vals.push_back(ci->getOperand(2)); // source vals.push_back(ConstantSInt::get(Type::IntTy,len)); // length vals.push_back(ConstantSInt::get(Type::IntTy,1)); // alignment - CallInst* memcpy_inst = new CallInst(get_memcpy_func(M), vals, "", ci); + CallInst* memcpy_inst = new CallInst(SLC.get_memcpy(), vals, "", ci); // Finally, substitute the first operand of the strcat call for the // strcat call itself since strcat returns its first operand; and, @@ -503,19 +421,108 @@ } } StrCatOptimizer; -/// This CallOptimizer will simplify a call to the strlen library function by +/// This LibCallOptimization will simplify a call to the strcpy library function. +/// Several optimizations are possible: +/// (1) If src and dest are the same and not volatile, just return dest +/// (2) If the src is a constant then we can convert to llvm.memmove +/// @brief Simplify the strcpy library function. +struct StrCpyOptimization : public LibCallOptimization +{ +public: + StrCpyOptimization() : LibCallOptimization("strcpy") {} + virtual ~StrCpyOptimization() {} + + /// @brief Make sure that the "strcpy" function has the right prototype + virtual bool ValidateCalledFunction(const Function* f, SimplifyLibCalls& SLC) + { + if (f->getReturnType() == PointerType::get(Type::SByteTy)) + if (f->arg_size() == 2) + { + Function::const_arg_iterator AI = f->arg_begin(); + if (AI++->getType() == PointerType::get(Type::SByteTy)) + if (AI->getType() == PointerType::get(Type::SByteTy)) + { + // Indicate this is a suitable call type. + return true; + } + } + return false; + } + + /// @brief Perform the strcpy optimization + virtual bool OptimizeCall(CallInst* ci, SimplifyLibCalls& SLC) + { + // First, check to see if src and destination are the same. If they are, + // then the optimization is to replace the CallInst with the destination + // because the call is a no-op. Note that this corresponds to the + // degenerate strcpy(X,X) case which should have "undefined" results + // according to the C specification. However, it occurs sometimes and + // we optimize it as a no-op. + Value* dest = ci->getOperand(1); + Value* src = ci->getOperand(2); + if (dest == src) + { + ci->replaceAllUsesWith(dest); + ci->eraseFromParent(); + return true; + } + + // Get the length of the constant string referenced by the second operand, + // the "src" parameter. Fail the optimization if we can't get the length + // (note that getConstantStringLength does lots of checks to make sure this + // is valid). + uint64_t len = 0; + if (!getConstantStringLength(ci->getOperand(2),len)) + return false; + + // If the constant string's length is zero we can optimize this by just + // doing a store of 0 at the first byte of the destination + if (len == 0) + { + new StoreInst(ConstantInt::get(Type::SByteTy,0),ci->getOperand(1),ci); + ci->replaceAllUsesWith(dest); + ci->eraseFromParent(); + return true; + } + + // Increment the length because we actually want to memcpy the null + // terminator as well. + len++; + + // Extract some information from the instruction + Module* M = ci->getParent()->getParent()->getParent(); + + // We have enough information to now generate the memcpy call to + // do the concatenation for us. + std::vector vals; + vals.push_back(dest); // destination + vals.push_back(src); // source + vals.push_back(ConstantSInt::get(Type::IntTy,len)); // length + vals.push_back(ConstantSInt::get(Type::IntTy,1)); // alignment + CallInst* memcpy_inst = new CallInst(SLC.get_memcpy(), vals, "", ci); + + // Finally, substitute the first operand of the strcat call for the + // strcat call itself since strcat returns its first operand; and, + // kill the strcat CallInst. + ci->replaceAllUsesWith(dest); + ci->eraseFromParent(); + return true; + } +} StrCpyOptimizer; + +/// This LibCallOptimization will simplify a call to the strlen library function by /// replacing it with a constant value if the string provided to it is a /// constant array. /// @brief Simplify the strlen library function. -struct StrLenOptimization : public CallOptimizer +struct StrLenOptimization : public LibCallOptimization { - StrLenOptimization() : CallOptimizer("strlen") {} + StrLenOptimization() : LibCallOptimization("strlen") {} virtual ~StrLenOptimization() {} /// @brief Make sure that the "strlen" function has the right prototype - virtual bool ValidateCalledFunction(const Function* f, const TargetData& TD) + virtual bool ValidateCalledFunction(const Function* f, SimplifyLibCalls& SLC) { - if (f->getReturnType() == TD.getIntPtrType()) + if (f->getReturnType() == SLC.getTargetData()->getIntPtrType()) if (f->arg_size() == 1) if (Function::const_arg_iterator AI = f->arg_begin()) if (AI->getType() == PointerType::get(Type::SByteTy)) @@ -524,33 +531,34 @@ } /// @brief Perform the strlen optimization - virtual bool OptimizeCall(CallInst* ci, const TargetData& TD) + virtual bool OptimizeCall(CallInst* ci, SimplifyLibCalls& SLC) { // Get the length of the string uint64_t len = 0; if (!getConstantStringLength(ci->getOperand(1),len)) return false; - ci->replaceAllUsesWith(ConstantInt::get(TD.getIntPtrType(),len)); + ci->replaceAllUsesWith( + ConstantInt::get(SLC.getTargetData()->getIntPtrType(),len)); ci->eraseFromParent(); return true; } } StrLenOptimizer; -/// This CallOptimizer will simplify a call to the memcpy library function by -/// expanding it out to a small set of stores if the copy source is a constant -/// array. +/// This LibCallOptimization will simplify a call to the memcpy library function by +/// expanding it out to a single store of size 0, 1, 2, 4, or 8 bytes depending +/// on the length of the string and the alignment. /// @brief Simplify the memcpy library function. -struct MemCpyOptimization : public CallOptimizer +struct MemCpyOptimization : public LibCallOptimization { - MemCpyOptimization() : CallOptimizer("llvm.memcpy") {} + MemCpyOptimization() : LibCallOptimization("llvm.memcpy") {} protected: - MemCpyOptimization(const char* fname) : CallOptimizer(fname) {} + MemCpyOptimization(const char* fname) : LibCallOptimization(fname) {} public: virtual ~MemCpyOptimization() {} /// @brief Make sure that the "memcpy" function has the right prototype - virtual bool ValidateCalledFunction(const Function* f, const TargetData& TD) + virtual bool ValidateCalledFunction(const Function* f, SimplifyLibCalls& TD) { // Just make sure this has 4 arguments per LLVM spec. return (f->arg_size() == 4); @@ -562,7 +570,7 @@ /// alignment match the sizes of our intrinsic types so we can do a load and /// store instead of the memcpy call. /// @brief Perform the memcpy optimization. - virtual bool OptimizeCall(CallInst* ci, const TargetData& TD) + virtual bool OptimizeCall(CallInst* ci, SimplifyLibCalls& TD) { // Make sure we have constant int values to work with ConstantInt* LEN = dyn_cast(ci->getOperand(3)); @@ -614,8 +622,7 @@ } } MemCpyOptimizer; -/// This CallOptimizer will simplify a call to the memmove library function. It -/// is identical to MemCopyOptimization except for the name of the intrinsic. +/// This LibCallOptimization will simplify a call to the memmove library function. /// It is identical to MemCopyOptimization except for the name of the intrinsic. /// @brief Simplify the memmove library function. struct MemMoveOptimization : public MemCpyOptimization { @@ -623,4 +630,102 @@ } MemMoveOptimizer; +/// A function to compute the length of a null-terminated string of integers. +/// This function can't rely on the size of the constant array because there +/// could be a null terminator in the middle of the array. We also have to +/// bail out if we find a non-integer constant initializer of one of the +/// elements or if there is no null-terminator. The logic below checks +bool getConstantStringLength(Value* V, uint64_t& len ) +{ + assert(V != 0 && "Invalid args to getConstantStringLength"); + len = 0; // make sure we initialize this + User* GEP = 0; + // If the value is not a GEP instruction nor a constant expression with a + // GEP instruction, then return false because ConstantArray can't occur + // any other way + if (GetElementPtrInst* GEPI = dyn_cast(V)) + GEP = GEPI; + else if (ConstantExpr* CE = dyn_cast(V)) + if (CE->getOpcode() == Instruction::GetElementPtr) + GEP = CE; + else + return false; + else + return false; + + // Make sure the GEP has exactly three arguments. + if (GEP->getNumOperands() != 3) + return false; + + // Check to make sure that the first operand of the GEP is an integer and + // has value 0 so that we are sure we're indexing into the initializer. + if (ConstantInt* op1 = dyn_cast(GEP->getOperand(1))) + { + if (!op1->isNullValue()) + return false; + } + else + return false; + + // Ensure that the second operand is a ConstantInt. If it isn't then this + // GEP is wonky and we're not really sure what were referencing into and + // better of not optimizing it. While we're at it, get the second index + // value. We'll need this later for indexing the ConstantArray. + uint64_t start_idx = 0; + if (ConstantInt* CI = dyn_cast(GEP->getOperand(2))) + start_idx = CI->getRawValue(); + else + return false; + + // The GEP instruction, constant or instruction, must reference a global + // variable that is a constant and is initialized. The referenced constant + // initializer is the array that we'll use for optimization. + GlobalVariable* GV = dyn_cast(GEP->getOperand(0)); + if (!GV || !GV->isConstant() || !GV->hasInitializer()) + return false; + + // Get the initializer. + Constant* INTLZR = GV->getInitializer(); + + // Handle the ConstantAggregateZero case + if (ConstantAggregateZero* CAZ = dyn_cast(INTLZR)) + { + // This is a degenerate case. The initializer is constant zero so the + // length of the string must be zero. + len = 0; + return true; + } + + // Must be a Constant Array + ConstantArray* A = dyn_cast(INTLZR); + if (!A) + return false; + + // Get the number of elements in the array + uint64_t max_elems = A->getType()->getNumElements(); + + // Traverse the constant array from start_idx (derived above) which is + // the place the GEP refers to in the array. + for ( len = start_idx; len < max_elems; len++) + { + if (ConstantInt* CI = dyn_cast(A->getOperand(len))) + { + // Check for the null terminator + if (CI->isNullValue()) + break; // we found end of string + } + else + return false; // This array isn't suitable, non-int initializer + } + if (len >= max_elems) + return false; // This array isn't null terminated + + // Subtract out the initial value from the length + len -= start_idx; + return true; // success! +} + + +// TODO: Additional cases that we need to add to this file: +// 1. memmove -> memcpy if src is a global constant array } From duraid at octopus.com.au Wed Apr 27 06:57:51 2005 From: duraid at octopus.com.au (Duraid Madina) Date: Wed, 27 Apr 2005 06:57:51 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/IA64/IA64ISelPattern.cpp Message-ID: <200504271157.GAA04206@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/IA64: IA64ISelPattern.cpp updated: 1.29 -> 1.30 --- Log message: clean up some warnings --- Diffs of the changes: (+15 -15) IA64ISelPattern.cpp | 30 +++++++++++++++--------------- 1 files changed, 15 insertions(+), 15 deletions(-) Index: llvm/lib/Target/IA64/IA64ISelPattern.cpp diff -u llvm/lib/Target/IA64/IA64ISelPattern.cpp:1.29 llvm/lib/Target/IA64/IA64ISelPattern.cpp:1.30 --- llvm/lib/Target/IA64/IA64ISelPattern.cpp:1.29 Tue Apr 26 04:42:50 2005 +++ llvm/lib/Target/IA64/IA64ISelPattern.cpp Wed Apr 27 06:57:39 2005 @@ -565,20 +565,20 @@ bool f; std::map w; - for(int i=0; i0) { - for(int base=0; basegetConstant(ops[i].firstShift, MVT::i64); SDOperand val = (ops[i].firstVal == 0) ? N.getOperand(0) : results[ops[i].firstVal-1]; From alenhar2 at cs.uiuc.edu Wed Apr 27 09:57:46 2005 From: alenhar2 at cs.uiuc.edu (Andrew Lenharth) Date: Wed, 27 Apr 2005 09:57:46 -0500 Subject: [llvm-commits] CVS: llvm/utils/importNLT.pl parseNLT.pl Message-ID: <200504271457.JAA26486@cypher.cs.uiuc.edu> Changes in directory llvm/utils: importNLT.pl added (r1.1) parseNLT.pl updated: 1.1 -> 1.2 --- Log message: fix for parse, and a start at db import. Using CVS as scp :) --- Diffs of the changes: (+31 -3) importNLT.pl | 26 ++++++++++++++++++++++++++ parseNLT.pl | 8 +++++--- 2 files changed, 31 insertions(+), 3 deletions(-) Index: llvm/utils/importNLT.pl diff -c /dev/null llvm/utils/importNLT.pl:1.1 *** /dev/null Wed Apr 27 09:57:37 2005 --- llvm/utils/importNLT.pl Wed Apr 27 09:57:26 2005 *************** *** 0 **** --- 1,26 ---- + #!/usr/bin/perl + #take the output of parseNLT.pl and load it into a database + + use DBI; + + # database information + $db="llvmalpha"; + $host="narya.lenharth.org"; + $userid="llvmdbuser"; + $passwd=""; #removed for obvious reasons + $connectionInfo="dbi:mysql:$db;$host"; + + # make connection to database + $dbh = DBI->connect($connectionInfo,$userid,$passwd) or die DBI->errstr; + + while($d = <>) + { + if (18 == split / /, $d) + { + ($day, $mon, $year, $prog, $gccas, $bc, $llc-compile, $llc-beta-compile, $jit-compile, + $mc, $gcc, $cbe, $llc, $llc-beta, $jit, $foo1, $foo2, $foo3) = split / /, $d; + print "."; + } + } + # disconnect from database + $dbh->disconnect Index: llvm/utils/parseNLT.pl diff -u llvm/utils/parseNLT.pl:1.1 llvm/utils/parseNLT.pl:1.2 --- llvm/utils/parseNLT.pl:1.1 Tue Apr 26 21:13:20 2005 +++ llvm/utils/parseNLT.pl Wed Apr 27 09:57:26 2005 @@ -15,12 +15,14 @@ if (/([^<]+)<\/td>/) { if ($prefix) - { $output .= "$1 "; } + { $output .= "$1 "; $count++; } } if (/ 3) + { print "\n$day $mon $year $prefix/$output"; } + $output = ""; + $count = 0; } if (/

    (Programs.+)<\/h2>/) { From alenhar2 at cs.uiuc.edu Wed Apr 27 11:03:18 2005 From: alenhar2 at cs.uiuc.edu (Andrew Lenharth) Date: Wed, 27 Apr 2005 11:03:18 -0500 Subject: [llvm-commits] CVS: llvm/utils/importNLT.pl Message-ID: <200504271603.j3RG3IqB022525@apoc.cs.uiuc.edu> Changes in directory llvm/utils: importNLT.pl updated: 1.1 -> 1.2 --- Log message: So you want to import nightly tester data into a data base? Have we got the perl script for you --- Diffs of the changes: (+67 -7) importNLT.pl | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 67 insertions(+), 7 deletions(-) Index: llvm/utils/importNLT.pl diff -u llvm/utils/importNLT.pl:1.1 llvm/utils/importNLT.pl:1.2 --- llvm/utils/importNLT.pl:1.1 Wed Apr 27 09:57:26 2005 +++ llvm/utils/importNLT.pl Wed Apr 27 11:03:01 2005 @@ -1,26 +1,86 @@ #!/usr/bin/perl #take the output of parseNLT.pl and load it into a database +# use like: cat file |perl parseNLT.pl |perl importNLT.pl password use DBI; # database information $db="llvmalpha"; -$host="narya.lenharth.org"; +$host="localhost"; $userid="llvmdbuser"; -$passwd=""; #removed for obvious reasons +$passwd=shift @ARGV; $connectionInfo="dbi:mysql:$db;$host"; # make connection to database $dbh = DBI->connect($connectionInfo,$userid,$passwd) or die DBI->errstr; +my $sth = $dbh->prepare( q{ + INSERT INTO Tests (NAME, RUN, TEST, VALUE) VALUES (?, STR_TO_DATE(?, '\%d \%M \%Y'), ?, ?) + }) || die "Can't prepare statement: $DBI::errstr";; while($d = <>) { - if (18 == split / /, $d) + chomp $d; + if (18 == scalar split " ", $d) { - ($day, $mon, $year, $prog, $gccas, $bc, $llc-compile, $llc-beta-compile, $jit-compile, - $mc, $gcc, $cbe, $llc, $llc-beta, $jit, $foo1, $foo2, $foo3) = split / /, $d; - print "."; + ($day, $mon, $year, $prog, $gccas, $bc, $llccompile, $llcbetacompile, $jitcompile, + $mc, $gcc, $cbe, $llc, $llcbeta, $jit, $foo1, $foo2, $foo3) = split / /, $d; + if ($gccas =~ /\d+/) + { + $dbh->do("INSERT INTO Tests (NAME, RUN, TEST, VALUE) VALUES + ('$prog', STR_TO_DATE('$day $mon $year', '\%d \%M \%Y'), 'gccas', $gccas)") || die DBI->errstr; + } + if ($bc =~ /\d/) + { + $dbh->do("INSERT INTO Tests (NAME, RUN, TEST, VALUE) VALUES + ('$prog', STR_TO_DATE('$day $mon $year', '\%d \%M \%Y'), 'bytecode', $bc)") || die DBI->errstr; + } + if ($llccompile =~ /\d/) + { + $dbh->do("INSERT INTO Tests (NAME, RUN, TEST, VALUE) VALUES + ('$prog', STR_TO_DATE('$day $mon $year', '\%d \%M \%Y'), 'llc-compile', $llccompile)") || die DBI->errstr; + } + if ($llcbetacompile =~ /\d/) + { + $dbh->do("INSERT INTO Tests (NAME, RUN, TEST, VALUE) VALUES + ('$prog', STR_TO_DATE('$day $mon $year', '\%d \%M \%Y'), 'llc-beta-compile', $llcbetacompile)") || die DBI->errstr; + } + if ($jitcompile =~ /\d/) + { + $dbh->do("INSERT INTO Tests (NAME, RUN, TEST, VALUE) VALUES + ('$prog', STR_TO_DATE('$day $mon $year', '\%d \%M \%Y'), 'jit-compile', $jitcompile)") || die DBI->errstr; + } + if ($mc =~ /\d/) + { + $dbh->do("INSERT INTO Tests (NAME, RUN, TEST, VALUE) VALUES + ('$prog', STR_TO_DATE('$day $mon $year', '\%d \%M \%Y'), 'machine-code', $mc)") || die DBI->errstr; + } + if ($gcc =~ /\d/) + { + $dbh->do("INSERT INTO Tests (NAME, RUN, TEST, VALUE) VALUES + ('$prog', STR_TO_DATE('$day $mon $year', '\%d \%M \%Y'), 'gcc', $gcc)") || die DBI->errstr; + } + if ($llc =~ /\d/) + { + $dbh->do("INSERT INTO Tests (NAME, RUN, TEST, VALUE) VALUES + ('$prog', STR_TO_DATE('$day $mon $year', '\%d \%M \%Y'), 'llc', $llc)") || die DBI->errstr; + } + if ($llcbeta =~ /\d/) + { + $dbh->do("INSERT INTO Tests (NAME, RUN, TEST, VALUE) VALUES + ('$prog', STR_TO_DATE('$day $mon $year', '\%d \%M \%Y'), 'llc-beta', $llcbeta)") || die DBI->errstr; + } + if ($jit =~ /\d/) + { + $dbh->do("INSERT INTO Tests (NAME, RUN, TEST, VALUE) VALUES + ('$prog', STR_TO_DATE('$day $mon $year', '\%d \%M \%Y'), 'jit', $jit)") || die DBI->errstr; + } + print "."; + } + else + { + print "\nNO: $d\n"; } } +print "\n"; # disconnect from database -$dbh->disconnect +$dbh->disconnect; From alenhar2 at cs.uiuc.edu Wed Apr 27 11:42:07 2005 From: alenhar2 at cs.uiuc.edu (Andrew Lenharth) Date: Wed, 27 Apr 2005 11:42:07 -0500 Subject: [llvm-commits] CVS: llvm/utils/plotNLT.pl Message-ID: <200504271642.j3RGg7Va022591@apoc.cs.uiuc.edu> Changes in directory llvm/utils: plotNLT.pl added (r1.1) --- Log message: Generate a gnuplot script for any program and any test (like llc or gcc) --- Diffs of the changes: (+39 -0) plotNLT.pl | 39 +++++++++++++++++++++++++++++++++++++++ 1 files changed, 39 insertions(+) Index: llvm/utils/plotNLT.pl diff -c /dev/null llvm/utils/plotNLT.pl:1.1 *** /dev/null Wed Apr 27 11:42:01 2005 --- llvm/utils/plotNLT.pl Wed Apr 27 11:41:50 2005 *************** *** 0 **** --- 1,39 ---- + #!/usr/bin/perl + #takes a test and a program from a dp and produces a gnuplot script + #use like perl plotNLT.pl password Programs/MultiSource/Benchmarks/ASCI_Purple/SMG2000/smg2000 llc + + use DBI; + + # database information + $db="llvmalpha"; + $host="localhost"; + $userid="llvmdbuser"; + $passwd=shift @ARGV; + $connectionInfo="dbi:mysql:$db;$host"; + + # make connection to database + $dbh = DBI->connect($connectionInfo,$userid,$passwd) or die DBI->errstr; + + $prog = shift @ARGV; + $test = shift @ARGV; + + print "set xdata time\n"; + print 'set timefmt "%Y-%m-%d"'; + print "\nplot '-' using 1:2 with lines \n"; + + $query = "Select RUN, VALUE from Tests where TEST = '$test' AND NAME = '$prog' ORDER BY RUN"; + #print $query; + + my $sth = $dbh->prepare( $query) || die "Can't prepare statement: $DBI::errstr";; + + my $rc = $sth->execute or die DBI->errstr; + + while(($da,$v) = $sth->fetchrow_array) + { + print "$da $v\n"; + } + + print "e\n"; + + # disconnect from database + $dbh->disconnect; From brukman at cs.uiuc.edu Wed Apr 27 12:19:21 2005 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed, 27 Apr 2005 12:19:21 -0500 Subject: [llvm-commits] CVS: llvm-tv/lib/Snapshot/Makefile Message-ID: <200504271719.MAA10952@zion.cs.uiuc.edu> Changes in directory llvm-tv/lib/Snapshot: Makefile updated: 1.2 -> 1.3 --- Log message: Prevent name collisions -- mark library as belonging to llvm-tv --- Diffs of the changes: (+1 -1) Makefile | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm-tv/lib/Snapshot/Makefile diff -u llvm-tv/lib/Snapshot/Makefile:1.2 llvm-tv/lib/Snapshot/Makefile:1.3 --- llvm-tv/lib/Snapshot/Makefile:1.2 Fri Apr 16 16:59:42 2004 +++ llvm-tv/lib/Snapshot/Makefile Wed Apr 27 12:19:10 2005 @@ -1,5 +1,5 @@ LEVEL = ../.. -LIBRARYNAME = snapshot +LIBRARYNAME = LLVMTVSnapshot SHARED_LIBRARY = 1 include $(LEVEL)/Makefile.common From brukman at cs.uiuc.edu Wed Apr 27 12:19:51 2005 From: brukman at cs.uiuc.edu (Misha Brukman) Date: Wed, 27 Apr 2005 12:19:51 -0500 Subject: [llvm-commits] CVS: llvm-tv/tools/llvm-tv/Makefile Message-ID: <200504271719.MAA11017@zion.cs.uiuc.edu> Changes in directory llvm-tv/tools/llvm-tv: Makefile updated: 1.20 -> 1.21 --- Log message: * The shared libraries are actually built into llvm-tv's lib dir * Adjust to change in shared lib name --- Diffs of the changes: (+2 -2) Makefile | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) Index: llvm-tv/tools/llvm-tv/Makefile diff -u llvm-tv/tools/llvm-tv/Makefile:1.20 llvm-tv/tools/llvm-tv/Makefile:1.21 --- llvm-tv/tools/llvm-tv/Makefile:1.20 Tue Apr 19 15:15:07 2005 +++ llvm-tv/tools/llvm-tv/Makefile Wed Apr 27 12:19:40 2005 @@ -5,7 +5,7 @@ LLVMSystem.a LLVMbzip2 # note: delete when FileUtils is assimilated into libsupport -USEDLIBS = snapshot +USEDLIBS = LLVMTVSnapshot CPPFLAGS = $(shell wx-config --cflags) TOOLLINKOPTSB = $(shell wx-config --libs) @@ -26,7 +26,7 @@ $(LLVMToolDir)/opt-snap: Makefile echo exec env LD_LIBRARY_PATH=$(WXLIB):\$$LD_LIBRARY_PATH \ - OPTPASSES=\"$$\*\" opt -load=$(LLVMLibDir)/libsnapshot.so $$\* > $@ + OPTPASSES=\"$$\*\" opt -load=$(LibDir)/libLLVMTVSnapshot.so $$\* > $@ chmod u+x $@ ifeq ($(OS),Darwin) From alenhar2 at cs.uiuc.edu Wed Apr 27 12:32:58 2005 From: alenhar2 at cs.uiuc.edu (Andrew Lenharth) Date: Wed, 27 Apr 2005 12:32:58 -0500 Subject: [llvm-commits] CVS: llvm/utils/importNLT.pl plotNLT.pl Message-ID: <200504271732.j3RHWwg0022665@apoc.cs.uiuc.edu> Changes in directory llvm/utils: importNLT.pl updated: 1.2 -> 1.3 plotNLT.pl updated: 1.1 -> 1.2 --- Log message: import fix and plot multiple lines at once --- Diffs of the changes: (+26 -12) importNLT.pl | 2 +- plotNLT.pl | 36 +++++++++++++++++++++++++----------- 2 files changed, 26 insertions(+), 12 deletions(-) Index: llvm/utils/importNLT.pl diff -u llvm/utils/importNLT.pl:1.2 llvm/utils/importNLT.pl:1.3 --- llvm/utils/importNLT.pl:1.2 Wed Apr 27 11:03:01 2005 +++ llvm/utils/importNLT.pl Wed Apr 27 12:32:41 2005 @@ -23,7 +23,7 @@ if (18 == scalar split " ", $d) { ($day, $mon, $year, $prog, $gccas, $bc, $llccompile, $llcbetacompile, $jitcompile, - $mc, $gcc, $cbe, $llc, $llcbeta, $jit, $foo1, $foo2, $foo3) = split / /, $d; + $mc, $gcc, $cbe, $llc, $llcbeta, $jit, $foo1, $foo2, $foo3) = split " ", $d; if ($gccas =~ /\d+/) { $dbh->do("INSERT INTO Tests (NAME, RUN, TEST, VALUE) VALUES Index: llvm/utils/plotNLT.pl diff -u llvm/utils/plotNLT.pl:1.1 llvm/utils/plotNLT.pl:1.2 --- llvm/utils/plotNLT.pl:1.1 Wed Apr 27 11:41:50 2005 +++ llvm/utils/plotNLT.pl Wed Apr 27 12:32:41 2005 @@ -14,26 +14,40 @@ # make connection to database $dbh = DBI->connect($connectionInfo,$userid,$passwd) or die DBI->errstr; -$prog = shift @ARGV; -$test = shift @ARGV; + +$count = @ARGV / 2; print "set xdata time\n"; print 'set timefmt "%Y-%m-%d"'; -print "\nplot '-' using 1:2 with lines \n"; +print "\nplot"; +for ($iter = 0; $iter < $count; $iter++) { + if ($iter) + { print ","; } + print " '-' using 1:2 with lines"; +} -$query = "Select RUN, VALUE from Tests where TEST = '$test' AND NAME = '$prog' ORDER BY RUN"; -#print $query; +print "\n"; -my $sth = $dbh->prepare( $query) || die "Can't prepare statement: $DBI::errstr";; +for ($iter = 0; $iter < $count; $iter++) { -my $rc = $sth->execute or die DBI->errstr; + $prog = shift @ARGV; + $test = shift @ARGV; -while(($da,$v) = $sth->fetchrow_array) -{ - print "$da $v\n"; + $query = "Select RUN, VALUE from Tests where TEST = '$test' AND NAME = '$prog' ORDER BY RUN"; + #print "\n$query\n"; + + my $sth = $dbh->prepare( $query) || die "Can't prepare statement: $DBI::errstr";; + + my $rc = $sth->execute or die DBI->errstr; + + while(($da,$v) = $sth->fetchrow_array) + { + print "$da $v\n"; + } + + print "e\n"; } -print "e\n"; # disconnect from database $dbh->disconnect; From reid at x10sys.com Wed Apr 27 12:47:06 2005 From: reid at x10sys.com (Reid Spencer) Date: Wed, 27 Apr 2005 12:47:06 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Message-ID: <200504271747.MAA15150@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: SimplifyLibCalls.cpp updated: 1.17 -> 1.18 --- Log message: More Cleanup: * Name the instructions by appending to name of original * Factor common part out of a switch statement. --- Diffs of the changes: (+26 -28) SimplifyLibCalls.cpp | 54 ++++++++++++++++++++++++--------------------------- 1 files changed, 26 insertions(+), 28 deletions(-) Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.17 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.18 --- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.17 Wed Apr 27 02:54:40 2005 +++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Wed Apr 27 12:46:54 2005 @@ -267,6 +267,7 @@ // auto registers it into the "optlist" global above. namespace { +// Forward declare a utility function. bool getConstantStringLength(Value* V, uint64_t& len ); /// This LibCallOptimization will find instances of a call to "exit" that occurs @@ -366,17 +367,22 @@ /// @brief Optimize the strcat library function virtual bool OptimizeCall(CallInst* ci, SimplifyLibCalls& SLC) { + // Extract some information from the instruction + Module* M = ci->getParent()->getParent()->getParent(); + Value* dest = ci->getOperand(1); + Value* src = ci->getOperand(2); + // Extract the initializer (while making numerous checks) from the // source operand of the call to strcat. If we get null back, one of // a variety of checks in get_GVInitializer failed uint64_t len = 0; - if (!getConstantStringLength(ci->getOperand(2),len)) + if (!getConstantStringLength(src,len)) return false; // Handle the simple, do-nothing case if (len == 0) { - ci->replaceAllUsesWith(ci->getOperand(1)); + ci->replaceAllUsesWith(dest); ci->eraseFromParent(); return true; } @@ -385,15 +391,13 @@ // terminator as well. len++; - // Extract some information from the instruction - Module* M = ci->getParent()->getParent()->getParent(); // We need to find the end of the destination string. That's where the // memory is to be moved to. We just generate a call to strlen (further // optimized in another pass). Note that the SLC.get_strlen() call // caches the Function* for us. CallInst* strlen_inst = - new CallInst(SLC.get_strlen(), ci->getOperand(1),"",ci); + new CallInst(SLC.get_strlen(), dest, dest->getName()+".len",ci); // Now that we have the destination's length, we must index into the // destination's pointer to get the actual memcpy destination (end of @@ -401,7 +405,7 @@ std::vector idx; idx.push_back(strlen_inst); GetElementPtrInst* gep = - new GetElementPtrInst(ci->getOperand(1),idx,"",ci); + new GetElementPtrInst(dest,idx,dest->getName()+".indexed",ci); // We have enough information to now generate the memcpy call to // do the concatenation for us. @@ -410,12 +414,12 @@ vals.push_back(ci->getOperand(2)); // source vals.push_back(ConstantSInt::get(Type::IntTy,len)); // length vals.push_back(ConstantSInt::get(Type::IntTy,1)); // alignment - CallInst* memcpy_inst = new CallInst(SLC.get_memcpy(), vals, "", ci); + new CallInst(SLC.get_memcpy(), vals, "", ci); // Finally, substitute the first operand of the strcat call for the // strcat call itself since strcat returns its first operand; and, // kill the strcat CallInst. - ci->replaceAllUsesWith(ci->getOperand(1)); + ci->replaceAllUsesWith(dest); ci->eraseFromParent(); return true; } @@ -499,7 +503,7 @@ vals.push_back(src); // source vals.push_back(ConstantSInt::get(Type::IntTy,len)); // length vals.push_back(ConstantSInt::get(Type::IntTy,1)); // alignment - CallInst* memcpy_inst = new CallInst(SLC.get_memcpy(), vals, "", ci); + new CallInst(SLC.get_memcpy(), vals, "", ci); // Finally, substitute the first operand of the strcat call for the // strcat call itself since strcat returns its first operand; and, @@ -586,36 +590,30 @@ if (len > alignment) return false; + // Get the type we will cast to, based on size of the string Value* dest = ci->getOperand(1); Value* src = ci->getOperand(2); - CastInst* SrcCast = 0; - CastInst* DestCast = 0; + Type* castType = 0; switch (len) { case 0: // The memcpy is a no-op so just dump its call. ci->eraseFromParent(); return true; - case 1: - SrcCast = new CastInst(src,PointerType::get(Type::SByteTy),"",ci); - DestCast = new CastInst(dest,PointerType::get(Type::SByteTy),"",ci); - break; - case 2: - SrcCast = new CastInst(src,PointerType::get(Type::ShortTy),"",ci); - DestCast = new CastInst(dest,PointerType::get(Type::ShortTy),"",ci); - break; - case 4: - SrcCast = new CastInst(src,PointerType::get(Type::IntTy),"",ci); - DestCast = new CastInst(dest,PointerType::get(Type::IntTy),"",ci); - break; - case 8: - SrcCast = new CastInst(src,PointerType::get(Type::LongTy),"",ci); - DestCast = new CastInst(dest,PointerType::get(Type::LongTy),"",ci); - break; + case 1: castType = Type::SByteTy; break; + case 2: castType = Type::ShortTy; break; + case 4: castType = Type::IntTy; break; + case 8: castType = Type::LongTy; break; default: return false; } - LoadInst* LI = new LoadInst(SrcCast,"",ci); + + // Cast source and dest to the right sized primitive and then load/store + CastInst* SrcCast = + new CastInst(src,PointerType::get(castType),src->getName()+".cast",ci); + CastInst* DestCast = + new CastInst(dest,PointerType::get(castType),dest->getName()+".cast",ci); + LoadInst* LI = new LoadInst(SrcCast,SrcCast->getName()+".val",ci); StoreInst* SI = new StoreInst(LI, DestCast, ci); ci->eraseFromParent(); return true; From lattner at cs.uiuc.edu Wed Apr 27 13:57:31 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 27 Apr 2005 13:57:31 -0500 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Type.cpp Message-ID: <200504271857.j3RIvV9O022909@apoc.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Type.cpp updated: 1.127 -> 1.128 --- Log message: Unbreak the sparc backend. --- Diffs of the changes: (+4 -2) Type.cpp | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) Index: llvm/lib/VMCore/Type.cpp diff -u llvm/lib/VMCore/Type.cpp:1.127 llvm/lib/VMCore/Type.cpp:1.128 --- llvm/lib/VMCore/Type.cpp:1.127 Tue Apr 26 15:03:33 2005 +++ llvm/lib/VMCore/Type.cpp Wed Apr 27 13:57:15 2005 @@ -1110,8 +1110,10 @@ PointerType *PointerType::get(const Type *ValueType) { assert(ValueType && "Can't get a pointer to type!"); - assert(ValueType != Type::VoidTy && - "Pointer to void is not valid, use sbyte* instead!"); + // FIXME: The sparc backend makes void pointers, which is horribly broken. + // "Fix" it, then reenable this assertion. + //assert(ValueType != Type::VoidTy && + // "Pointer to void is not valid, use sbyte* instead!"); PointerValType PVT(ValueType); PointerType *PT = PointerTypes.get(PVT); From alenhar2 at cs.uiuc.edu Wed Apr 27 15:10:17 2005 From: alenhar2 at cs.uiuc.edu (Andrew Lenharth) Date: Wed, 27 Apr 2005 15:10:17 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/CodeGen/SelectionDAG.h SelectionDAGNodes.h Message-ID: <200504272010.j3RKAHrb023359@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/CodeGen: SelectionDAG.h updated: 1.21 -> 1.22 SelectionDAGNodes.h updated: 1.33 -> 1.34 --- Log message: Implement Value* tracking for loads and stores in the selection DAG. This enables one to use alias analysis in the backends. (TRUNK)Stores and (EXT|ZEXT|SEXT)Loads have an extra SDOperand which is a SrcValueSDNode which contains the Value*. Note that if the operation is introduced by the backend, it will still have the operand, but the value* will be null. --- Diffs of the changes: (+51 -5) SelectionDAG.h | 9 ++++++++- SelectionDAGNodes.h | 47 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 51 insertions(+), 5 deletions(-) Index: llvm/include/llvm/CodeGen/SelectionDAG.h diff -u llvm/include/llvm/CodeGen/SelectionDAG.h:1.21 llvm/include/llvm/CodeGen/SelectionDAG.h:1.22 --- llvm/include/llvm/CodeGen/SelectionDAG.h:1.21 Thu Apr 21 15:38:00 2005 +++ llvm/include/llvm/CodeGen/SelectionDAG.h Wed Apr 27 15:10:01 2005 @@ -162,6 +162,8 @@ SDOperand getNode(unsigned Opcode, MVT::ValueType VT, SDOperand N1, SDOperand N2, SDOperand N3); SDOperand getNode(unsigned Opcode, MVT::ValueType VT, + SDOperand N1, SDOperand N2, SDOperand N3, SDOperand N4); + SDOperand getNode(unsigned Opcode, MVT::ValueType VT, std::vector &Children); // getNode - These versions take an extra value type for extending and @@ -172,11 +174,16 @@ SDOperand N, MVT::ValueType EVT); SDOperand getNode(unsigned Opcode, MVT::ValueType VT, SDOperand N1, SDOperand N2, SDOperand N3, MVT::ValueType EVT); + SDOperand getNode(unsigned Opcode, MVT::ValueType VT, SDOperand N1, + SDOperand N2, SDOperand N3, SDOperand N4, MVT::ValueType EVT); /// getLoad - Loads are not normal binary operators: their result type is not /// determined by their operands, and they produce a value AND a token chain. /// - SDOperand getLoad(MVT::ValueType VT, SDOperand Chain, SDOperand Ptr); + SDOperand getLoad(MVT::ValueType VT, SDOperand Chain, SDOperand Ptr, SDOperand SV); + + // getSrcValue - construct a node to track a Value* through the backend + SDOperand getSrcValue(const Value* I); void replaceAllUsesWith(SDOperand Old, SDOperand New) { assert(Old != New && "RAUW self!"); Index: llvm/include/llvm/CodeGen/SelectionDAGNodes.h diff -u llvm/include/llvm/CodeGen/SelectionDAGNodes.h:1.33 llvm/include/llvm/CodeGen/SelectionDAGNodes.h:1.34 --- llvm/include/llvm/CodeGen/SelectionDAGNodes.h:1.33 Thu Apr 21 15:38:00 2005 +++ llvm/include/llvm/CodeGen/SelectionDAGNodes.h Wed Apr 27 15:10:01 2005 @@ -20,6 +20,7 @@ #define LLVM_CODEGEN_SELECTIONDAGNODES_H #include "llvm/CodeGen/ValueTypes.h" +#include "llvm/Value.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/iterator" @@ -251,6 +252,11 @@ // PCMARKER - This corresponds to the pcmarker intrinsic. PCMARKER, + // SRCVALUE - This corresponds to a Value*, and is used to carry associate + // memory operations with their corrosponding load. This lets one use the + // pointer analysis information in the backend + SRCVALUE, + // BUILTIN_OP_END - This must be the last enum value in this list. BUILTIN_OP_END, }; @@ -529,6 +535,22 @@ N1.Val->Uses.push_back(this); N2.Val->Uses.push_back(this); N3.Val->Uses.push_back(this); } + SDNode(unsigned NT, SDOperand N1, SDOperand N2, SDOperand N3, SDOperand N4) + : NodeType(NT) { + unsigned ND = N1.Val->getNodeDepth(); + if (ND < N2.Val->getNodeDepth()) + ND = N2.Val->getNodeDepth(); + if (ND < N3.Val->getNodeDepth()) + ND = N3.Val->getNodeDepth(); + if (ND < N4.Val->getNodeDepth()) + ND = N4.Val->getNodeDepth(); + NodeDepth = ND+1; + + Operands.reserve(3); Operands.push_back(N1); Operands.push_back(N2); + Operands.push_back(N3); Operands.push_back(N4); + N1.Val->Uses.push_back(this); N2.Val->Uses.push_back(this); + N3.Val->Uses.push_back(this); N4.Val->Uses.push_back(this); + } SDNode(unsigned NT, std::vector &Nodes) : NodeType(NT) { Operands.swap(Nodes); unsigned ND = 0; @@ -724,6 +746,22 @@ } }; +class SrcValueSDNode : public SDNode { + const Value *V; +protected: + friend class SelectionDAG; + SrcValueSDNode(const Value* v) + : SDNode(ISD::SRCVALUE, MVT::Other), V(v) {} + +public: + const Value *getValue() const { return V; } + + static bool classof(const SrcValueSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::SRCVALUE; + } +}; + class RegSDNode : public SDNode { unsigned Reg; @@ -791,13 +829,14 @@ setValueTypes(VT1); } MVTSDNode(unsigned Opc, MVT::ValueType VT1, MVT::ValueType VT2, - SDOperand Op0, SDOperand Op1, MVT::ValueType EVT) - : SDNode(Opc, Op0, Op1), ExtraValueType(EVT) { + SDOperand Op0, SDOperand Op1, SDOperand Op2, MVT::ValueType EVT) + : SDNode(Opc, Op0, Op1, Op2), ExtraValueType(EVT) { setValueTypes(VT1, VT2); } + MVTSDNode(unsigned Opc, MVT::ValueType VT, - SDOperand Op0, SDOperand Op1, SDOperand Op2, MVT::ValueType EVT) - : SDNode(Opc, Op0, Op1, Op2), ExtraValueType(EVT) { + SDOperand Op0, SDOperand Op1, SDOperand Op2, SDOperand Op3, MVT::ValueType EVT) + : SDNode(Opc, Op0, Op1, Op2, Op3), ExtraValueType(EVT) { setValueTypes(VT); } public: From alenhar2 at cs.uiuc.edu Wed Apr 27 15:10:22 2005 From: alenhar2 at cs.uiuc.edu (Andrew Lenharth) Date: Wed, 27 Apr 2005 15:10:22 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp SelectionDAG.cpp SelectionDAGISel.cpp Message-ID: <200504272010.j3RKAMhE023369@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: LegalizeDAG.cpp updated: 1.90 -> 1.91 SelectionDAG.cpp updated: 1.95 -> 1.96 SelectionDAGISel.cpp updated: 1.43 -> 1.44 --- Log message: Implement Value* tracking for loads and stores in the selection DAG. This enables one to use alias analysis in the backends. (TRUNK)Stores and (EXT|ZEXT|SEXT)Loads have an extra SDOperand which is a SrcValueSDNode which contains the Value*. Note that if the operation is introduced by the backend, it will still have the operand, but the value* will be null. --- Diffs of the changes: (+65 -33) LegalizeDAG.cpp | 51 +++++++++++++++++++++++++++++---------------------- SelectionDAG.cpp | 42 +++++++++++++++++++++++++++++++++--------- SelectionDAGISel.cpp | 5 +++-- 3 files changed, 65 insertions(+), 33 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.90 llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.91 --- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.90 Thu Apr 21 17:35:36 2005 +++ llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Wed Apr 27 15:10:01 2005 @@ -290,9 +290,9 @@ TLI.getPointerTy()); if (Extend) { Result = DAG.getNode(ISD::EXTLOAD, MVT::f64, DAG.getEntryNode(), CPIdx, - MVT::f32); + DAG.getSrcValue(NULL), MVT::f32); } else { - Result = DAG.getLoad(VT, DAG.getEntryNode(), CPIdx); + Result = DAG.getLoad(VT, DAG.getEntryNode(), CPIdx, DAG.getSrcValue(NULL)); } } break; @@ -428,9 +428,10 @@ case ISD::LOAD: Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain. Tmp2 = LegalizeOp(Node->getOperand(1)); // Legalize the pointer. + if (Tmp1 != Node->getOperand(0) || Tmp2 != Node->getOperand(1)) - Result = DAG.getLoad(Node->getValueType(0), Tmp1, Tmp2); + Result = DAG.getLoad(Node->getValueType(0), Tmp1, Tmp2, Node->getOperand(2)); else Result = SDOperand(Node, 0); @@ -452,7 +453,7 @@ case TargetLowering::Promote: assert(SrcVT == MVT::i1 && "Can only promote EXTLOAD from i1 -> i8!"); Result = DAG.getNode(Node->getOpcode(), Node->getValueType(0), - Tmp1, Tmp2, MVT::i8); + Tmp1, Tmp2, Node->getOperand(2), MVT::i8); // Since loads produce two values, make sure to remember that we legalized // both of them. AddLegalizedOperand(SDOperand(Node, 0), Result); @@ -463,7 +464,7 @@ if (Tmp1 != Node->getOperand(0) || Tmp2 != Node->getOperand(1)) Result = DAG.getNode(Node->getOpcode(), Node->getValueType(0), - Tmp1, Tmp2, SrcVT); + Tmp1, Tmp2, Node->getOperand(2), SrcVT); else Result = SDOperand(Node, 0); @@ -478,7 +479,7 @@ // Turn the unsupported load into an EXTLOAD followed by an explicit // zero/sign extend inreg. Result = DAG.getNode(ISD::EXTLOAD, Node->getValueType(0), - Tmp1, Tmp2, SrcVT); + Tmp1, Tmp2, Node->getOperand(2), SrcVT); SDOperand ValRes; if (Node->getOpcode() == ISD::SEXTLOAD) ValRes = DAG.getNode(ISD::SIGN_EXTEND_INREG, Result.getValueType(), @@ -591,8 +592,8 @@ float F; } V; V.F = CFP->getValue(); - Result = DAG.getNode(ISD::STORE, MVT::Other, Tmp1, - DAG.getConstant(V.I, MVT::i32), Tmp2); + Result = DAG.getNode(ISD::STORE, MVT::Other, Tmp1, + DAG.getConstant(V.I, MVT::i32), Tmp2, Node->getOperand(3)); } else { assert(CFP->getValueType(0) == MVT::f64 && "Unknown FP type!"); union { @@ -600,8 +601,8 @@ double F; } V; V.F = CFP->getValue(); - Result = DAG.getNode(ISD::STORE, MVT::Other, Tmp1, - DAG.getConstant(V.I, MVT::i64), Tmp2); + Result = DAG.getNode(ISD::STORE, MVT::Other, Tmp1, + DAG.getConstant(V.I, MVT::i64), Tmp2, Node->getOperand(3)); } Node = Result.Val; } @@ -611,14 +612,15 @@ SDOperand Val = LegalizeOp(Node->getOperand(1)); if (Val != Node->getOperand(1) || Tmp1 != Node->getOperand(0) || Tmp2 != Node->getOperand(2)) - Result = DAG.getNode(ISD::STORE, MVT::Other, Tmp1, Val, Tmp2); + Result = DAG.getNode(ISD::STORE, MVT::Other, Tmp1, Val, Tmp2, Node->getOperand(3)); break; } case Promote: // Truncate the value and store the result. Tmp3 = PromoteOp(Node->getOperand(1)); Result = DAG.getNode(ISD::TRUNCSTORE, MVT::Other, Tmp1, Tmp3, Tmp2, - Node->getOperand(1).getValueType()); + Node->getOperand(3), + Node->getOperand(1).getValueType()); break; case Expand: @@ -628,14 +630,16 @@ if (!TLI.isLittleEndian()) std::swap(Lo, Hi); - Lo = DAG.getNode(ISD::STORE, MVT::Other, Tmp1, Lo, Tmp2); + Lo = DAG.getNode(ISD::STORE, MVT::Other,Tmp1, Lo, Tmp2,Node->getOperand(3)); unsigned IncrementSize = MVT::getSizeInBits(Hi.getValueType())/8; Tmp2 = DAG.getNode(ISD::ADD, Tmp2.getValueType(), Tmp2, getIntPtrConstant(IncrementSize)); assert(isTypeLegal(Tmp2.getValueType()) && "Pointers must be legal!"); - Hi = DAG.getNode(ISD::STORE, MVT::Other, Tmp1, Hi, Tmp2); + //Again, claiming both parts of the store came form the same Instr + Hi = DAG.getNode(ISD::STORE, MVT::Other, Tmp1, Hi, Tmp2, Node->getOperand(3)); + Result = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi); break; } @@ -655,6 +659,7 @@ if (Tmp1 != Node->getOperand(0) || Tmp2 != Node->getOperand(1) || Tmp3 != Node->getOperand(2)) Result = DAG.getNode(ISD::TRUNCSTORE, MVT::Other, Tmp1, Tmp2, Tmp3, + Node->getOperand(3), cast(Node)->getExtraValueType()); break; case Promote: @@ -1138,9 +1143,9 @@ MF.getFrameInfo()->CreateStackObject((unsigned)TySize, Align); SDOperand StackSlot = DAG.getFrameIndex(SSFI, TLI.getPointerTy()); Result = DAG.getNode(ISD::TRUNCSTORE, MVT::Other, DAG.getEntryNode(), - Node->getOperand(0), StackSlot, ExtraVT); + Node->getOperand(0), StackSlot, DAG.getSrcValue(NULL), ExtraVT); Result = DAG.getNode(ISD::EXTLOAD, Node->getValueType(0), - Result, StackSlot, ExtraVT); + Result, StackSlot, DAG.getSrcValue(NULL), ExtraVT); } else { assert(0 && "Unknown op"); } @@ -1404,9 +1409,9 @@ Tmp2 = LegalizeOp(Node->getOperand(1)); // Legalize the pointer. // FIXME: When the DAG combiner exists, change this to use EXTLOAD! if (MVT::isInteger(NVT)) - Result = DAG.getNode(ISD::ZEXTLOAD, NVT, Tmp1, Tmp2, VT); + Result = DAG.getNode(ISD::ZEXTLOAD, NVT, Tmp1, Tmp2, Node->getOperand(2), VT); else - Result = DAG.getNode(ISD::EXTLOAD, NVT, Tmp1, Tmp2, VT); + Result = DAG.getNode(ISD::EXTLOAD, NVT, Tmp1, Tmp2, Node->getOperand(2), VT); // Remember that we legalized the chain. AddLegalizedOperand(Op.getValue(1), Result.getValue(1)); @@ -1846,11 +1851,11 @@ CPIdx = DAG.getNode(ISD::ADD, TLI.getPointerTy(), CPIdx, CstOffset); SDOperand FudgeInReg; if (DestTy == MVT::f32) - FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx); + FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx, DAG.getSrcValue(NULL)); else { assert(DestTy == MVT::f64 && "Unexpected conversion"); FudgeInReg = DAG.getNode(ISD::EXTLOAD, MVT::f64, DAG.getEntryNode(), - CPIdx, MVT::f32); + CPIdx, DAG.getSrcValue(NULL), MVT::f32); } return DAG.getNode(ISD::ADD, DestTy, SignedConv, FudgeInReg); } @@ -1941,13 +1946,15 @@ case ISD::LOAD: { SDOperand Ch = LegalizeOp(Node->getOperand(0)); // Legalize the chain. SDOperand Ptr = LegalizeOp(Node->getOperand(1)); // Legalize the pointer. - Lo = DAG.getLoad(NVT, Ch, Ptr); + Lo = DAG.getLoad(NVT, Ch, Ptr, Node->getOperand(2)); // Increment the pointer to the other half. unsigned IncrementSize = MVT::getSizeInBits(Lo.getValueType())/8; Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, getIntPtrConstant(IncrementSize)); - Hi = DAG.getLoad(NVT, Ch, Ptr); + //Is this safe? declaring that the two parts of the split load + //are from the same instruction? + Hi = DAG.getLoad(NVT, Ch, Ptr, Node->getOperand(2)); // Build a factor node to remember that this load is independent of the // other one. Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.95 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.96 --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.95 Mon Apr 25 20:18:33 2005 +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Wed Apr 27 15:10:01 2005 @@ -1174,10 +1174,11 @@ } SDOperand SelectionDAG::getLoad(MVT::ValueType VT, - SDOperand Chain, SDOperand Ptr) { + SDOperand Chain, SDOperand Ptr, + SDOperand SV) { SDNode *&N = Loads[std::make_pair(Ptr, std::make_pair(Chain, VT))]; if (N) return SDOperand(N, 0); - N = new SDNode(ISD::LOAD, Chain, Ptr); + N = new SDNode(ISD::LOAD, Chain, Ptr, SV); // Loads have a token chain. N->setValueTypes(VT, MVT::Other); @@ -1185,9 +1186,9 @@ return SDOperand(N, 0); } - SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, SDOperand N1, SDOperand N2, SDOperand N3) { + assert(Opcode != ISD::STORE && "Store shouldn't use this anymore"); // Perform various simplifications. ConstantSDNode *N1C = dyn_cast(N1.Val); ConstantSDNode *N2C = dyn_cast(N2.Val); @@ -1315,6 +1316,27 @@ } SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, + SDOperand N1, SDOperand N2, SDOperand N3, + SDOperand N4) { + assert(Opcode == ISD::STORE && "Only stores should use this"); + + SDNode *N = new SDNode(Opcode, N1, N2, N3, N4); + N->setValueTypes(VT); + + // FIXME: memoize NODES + AllNodes.push_back(N); + return SDOperand(N, 0); +} + +SDOperand SelectionDAG::getSrcValue(const Value* v) { + SDNode *N = new SrcValueSDNode(v); + N->setValueTypes(MVT::Other); + // FIXME: memoize NODES + AllNodes.push_back(N); + return SDOperand(N, 0); +} + +SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, std::vector &Children) { switch (Children.size()) { case 0: return getNode(Opcode, VT); @@ -1419,7 +1441,7 @@ } SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,SDOperand N1, - SDOperand N2, MVT::ValueType EVT) { + SDOperand N2, SDOperand N3, MVT::ValueType EVT) { switch (Opcode) { default: assert(0 && "Bad opcode for this accessor!"); case ISD::EXTLOAD: @@ -1428,7 +1450,7 @@ // If they are asking for an extending load from/to the same thing, return a // normal load. if (VT == EVT) - return getNode(ISD::LOAD, VT, N1, N2); + return getLoad(VT, N1, N2, N3); assert(EVT < VT && "Should only be an extending load, not truncating!"); assert((Opcode == ISD::EXTLOAD || MVT::isInteger(VT)) && "Cannot sign/zero extend a FP load!"); @@ -1443,16 +1465,17 @@ NN.EVT = EVT; NN.Ops.push_back(N1); NN.Ops.push_back(N2); + NN.Ops.push_back(N3); SDNode *&N = MVTSDNodes[NN]; if (N) return SDOperand(N, 0); - N = new MVTSDNode(Opcode, VT, MVT::Other, N1, N2, EVT); + N = new MVTSDNode(Opcode, VT, MVT::Other, N1, N2, N3, EVT); AllNodes.push_back(N); return SDOperand(N, 0); } SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,SDOperand N1, - SDOperand N2, SDOperand N3, MVT::ValueType EVT) { + SDOperand N2, SDOperand N3, SDOperand N4, MVT::ValueType EVT) { switch (Opcode) { default: assert(0 && "Bad opcode for this accessor!"); case ISD::TRUNCSTORE: @@ -1467,7 +1490,7 @@ // Also for ConstantFP? #endif if (N1.getValueType() == EVT) // Normal store? - return getNode(ISD::STORE, VT, N1, N2, N3); + return getNode(ISD::STORE, VT, N1, N2, N3, N4); assert(N2.getValueType() > EVT && "Not a truncation?"); assert(MVT::isInteger(N2.getValueType()) == MVT::isInteger(EVT) && "Can't do FP-INT conversion!"); @@ -1481,10 +1504,11 @@ NN.Ops.push_back(N1); NN.Ops.push_back(N2); NN.Ops.push_back(N3); + NN.Ops.push_back(N4); SDNode *&N = MVTSDNodes[NN]; if (N) return SDOperand(N, 0); - N = new MVTSDNode(Opcode, VT, N1, N2, N3, EVT); + N = new MVTSDNode(Opcode, VT, N1, N2, N3, N4, EVT); AllNodes.push_back(N); return SDOperand(N, 0); } Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.43 llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.44 --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.43 Thu Apr 21 23:01:18 2005 +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Wed Apr 27 15:10:01 2005 @@ -623,7 +623,7 @@ Root = DAG.getRoot(); } - SDOperand L = DAG.getLoad(TLI.getValueType(I.getType()), Root, Ptr); + SDOperand L = DAG.getLoad(TLI.getValueType(I.getType()), Root, Ptr, DAG.getSrcValue(&I)); setValue(&I, L); if (I.isVolatile()) @@ -637,7 +637,8 @@ Value *SrcV = I.getOperand(0); SDOperand Src = getValue(SrcV); SDOperand Ptr = getValue(I.getOperand(1)); - DAG.setRoot(DAG.getNode(ISD::STORE, MVT::Other, getRoot(), Src, Ptr)); + // DAG.setRoot(DAG.getNode(ISD::STORE, MVT::Other, getRoot(), Src, Ptr)); + DAG.setRoot(DAG.getNode(ISD::STORE, MVT::Other, getRoot(), Src, Ptr, DAG.getSrcValue(&I))); } void SelectionDAGLowering::visitCall(CallInst &I) { From alenhar2 at cs.uiuc.edu Wed Apr 27 15:10:24 2005 From: alenhar2 at cs.uiuc.edu (Andrew Lenharth) Date: Wed, 27 Apr 2005 15:10:24 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/IA64/IA64ISelPattern.cpp Message-ID: <200504272010.j3RKAOlA023384@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/IA64: IA64ISelPattern.cpp updated: 1.30 -> 1.31 --- Log message: Implement Value* tracking for loads and stores in the selection DAG. This enables one to use alias analysis in the backends. (TRUNK)Stores and (EXT|ZEXT|SEXT)Loads have an extra SDOperand which is a SrcValueSDNode which contains the Value*. Note that if the operation is introduced by the backend, it will still have the operand, but the value* will be null. --- Diffs of the changes: (+2 -2) IA64ISelPattern.cpp | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) Index: llvm/lib/Target/IA64/IA64ISelPattern.cpp diff -u llvm/lib/Target/IA64/IA64ISelPattern.cpp:1.30 llvm/lib/Target/IA64/IA64ISelPattern.cpp:1.31 --- llvm/lib/Target/IA64/IA64ISelPattern.cpp:1.30 Wed Apr 27 06:57:39 2005 +++ llvm/lib/Target/IA64/IA64ISelPattern.cpp Wed Apr 27 15:10:01 2005 @@ -223,7 +223,7 @@ //from this parameter SDOperand FIN = DAG.getFrameIndex(FI, MVT::i64); argt = newroot = DAG.getLoad(getValueType(I->getType()), - DAG.getEntryNode(), FIN); + DAG.getEntryNode(), FIN, DAG.getSrcValue(NULL)); } ++count; DAG.setRoot(newroot.getValue(1)); @@ -378,7 +378,7 @@ MVT::ValueType ArgVT = getValueType(ArgTy); SDOperand Result; if (!isVANext) { - Result = DAG.getLoad(ArgVT, DAG.getEntryNode(), VAList); + Result = DAG.getLoad(ArgVT, DAG.getEntryNode(), VAList, DAG.getSrcValue(NULL)); } else { unsigned Amt; if (ArgVT == MVT::i32 || ArgVT == MVT::f32) From alenhar2 at cs.uiuc.edu Wed Apr 27 15:10:23 2005 From: alenhar2 at cs.uiuc.edu (Andrew Lenharth) Date: Wed, 27 Apr 2005 15:10:23 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp PPC64ISelPattern.cpp Message-ID: <200504272010.j3RKANtA023374@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/PowerPC: PPC32ISelPattern.cpp updated: 1.78 -> 1.79 PPC64ISelPattern.cpp updated: 1.10 -> 1.11 --- Log message: Implement Value* tracking for loads and stores in the selection DAG. This enables one to use alias analysis in the backends. (TRUNK)Stores and (EXT|ZEXT|SEXT)Loads have an extra SDOperand which is a SrcValueSDNode which contains the Value*. Note that if the operation is introduced by the backend, it will still have the operand, but the value* will be null. --- Diffs of the changes: (+18 -18) PPC32ISelPattern.cpp | 22 +++++++++++----------- PPC64ISelPattern.cpp | 14 +++++++------- 2 files changed, 18 insertions(+), 18 deletions(-) Index: llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp diff -u llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp:1.78 llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp:1.79 --- llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp:1.78 Fri Apr 22 12:54:30 2005 +++ llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp Wed Apr 27 15:10:01 2005 @@ -164,7 +164,7 @@ } else { int FI = MFI->CreateFixedObject(4, ArgOffset+4); SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32); - argLo = DAG.getLoad(MVT::i32, DAG.getEntryNode(), FIN); + argLo = DAG.getLoad(MVT::i32, DAG.getEntryNode(), FIN, DAG.getSrcValue(NULL)); } // Build the outgoing arg thingy argt = DAG.getNode(ISD::BUILD_PAIR, MVT::i64, argLo, argHi); @@ -199,7 +199,7 @@ SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32); FIN = DAG.getNode(ISD::ADD, MVT::i32, FIN, DAG.getConstant(SubregOffset, MVT::i32)); - argt = newroot = DAG.getLoad(ObjectVT, DAG.getEntryNode(), FIN); + argt = newroot = DAG.getLoad(ObjectVT, DAG.getEntryNode(), FIN, DAG.getSrcValue(NULL)); } // Every 4 bytes of argument space consumes one of the GPRs available for @@ -229,7 +229,7 @@ MF.addLiveIn(GPR[GPR_idx]); SDOperand Val = DAG.getCopyFromReg(GPR[GPR_idx], MVT::i32, DAG.getRoot()); SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Val.getValue(1), - Val, FIN); + Val, FIN, DAG.getSrcValue(NULL)); MemOps.push_back(Store); // Increment the address by four for the next argument to store SDOperand PtrOff = DAG.getConstant(4, getPointerTy()); @@ -343,7 +343,7 @@ --GPR_remaining; } else { MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, - Args[i].first, PtrOff)); + Args[i].first, PtrOff, DAG.getSrcValue(NULL))); } ArgOffset += 4; break; @@ -365,11 +365,11 @@ SDOperand ConstFour = DAG.getConstant(4, getPointerTy()); PtrOff = DAG.getNode(ISD::ADD, MVT::i32, PtrOff, ConstFour); MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, - Lo, PtrOff)); + Lo, PtrOff, DAG.getSrcValue(NULL))); } } else { MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, - Args[i].first, PtrOff)); + Args[i].first, PtrOff, DAG.getSrcValue(NULL))); } ArgOffset += 8; break; @@ -380,11 +380,11 @@ --FPR_remaining; if (isVarArg) { SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Chain, - Args[i].first, PtrOff); + Args[i].first, PtrOff, DAG.getSrcValue(NULL)); MemOps.push_back(Store); // Float varargs are always shadowed in available integer registers if (GPR_remaining > 0) { - SDOperand Load = DAG.getLoad(MVT::i32, Store, PtrOff); + SDOperand Load = DAG.getLoad(MVT::i32, Store, PtrOff, DAG.getSrcValue(NULL)); MemOps.push_back(Load); args_to_use.push_back(Load); --GPR_remaining; @@ -392,7 +392,7 @@ if (GPR_remaining > 0 && MVT::f64 == ArgVT) { SDOperand ConstFour = DAG.getConstant(4, getPointerTy()); PtrOff = DAG.getNode(ISD::ADD, MVT::i32, PtrOff, ConstFour); - SDOperand Load = DAG.getLoad(MVT::i32, Store, PtrOff); + SDOperand Load = DAG.getLoad(MVT::i32, Store, PtrOff, DAG.getSrcValue(NULL)); MemOps.push_back(Load); args_to_use.push_back(Load); --GPR_remaining; @@ -412,7 +412,7 @@ } } else { MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, - Args[i].first, PtrOff)); + Args[i].first, PtrOff, DAG.getSrcValue(NULL))); } ArgOffset += (ArgVT == MVT::f32) ? 4 : 8; break; @@ -448,7 +448,7 @@ MVT::ValueType ArgVT = getValueType(ArgTy); SDOperand Result; if (!isVANext) { - Result = DAG.getLoad(ArgVT, DAG.getEntryNode(), VAList); + Result = DAG.getLoad(ArgVT, DAG.getEntryNode(), VAList, DAG.getSrcValue(NULL)); } else { unsigned Amt; if (ArgVT == MVT::i32 || ArgVT == MVT::f32) Index: llvm/lib/Target/PowerPC/PPC64ISelPattern.cpp diff -u llvm/lib/Target/PowerPC/PPC64ISelPattern.cpp:1.10 llvm/lib/Target/PowerPC/PPC64ISelPattern.cpp:1.11 --- llvm/lib/Target/PowerPC/PPC64ISelPattern.cpp:1.10 Fri Apr 22 12:54:30 2005 +++ llvm/lib/Target/PowerPC/PPC64ISelPattern.cpp Wed Apr 27 15:10:01 2005 @@ -176,7 +176,7 @@ SDOperand FIN = DAG.getFrameIndex(FI, MVT::i64); FIN = DAG.getNode(ISD::ADD, MVT::i64, FIN, DAG.getConstant(SubregOffset, MVT::i64)); - argt = newroot = DAG.getLoad(ObjectVT, DAG.getEntryNode(), FIN); + argt = newroot = DAG.getLoad(ObjectVT, DAG.getEntryNode(), FIN, DAG.getSrcValue(NULL)); } // Every 4 bytes of argument space consumes one of the GPRs available for @@ -204,7 +204,7 @@ BuildMI(&BB, PPC::IMPLICIT_DEF, 0, GPR[GPR_idx]); SDOperand Val = DAG.getCopyFromReg(GPR[GPR_idx], MVT::i64, DAG.getRoot()); SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Val.getValue(1), - Val, FIN); + Val, FIN, DAG.getSrcValue(NULL)); MemOps.push_back(Store); // Increment the address by eight for the next argument to store SDOperand PtrOff = DAG.getConstant(8, getPointerTy()); @@ -285,7 +285,7 @@ --GPR_remaining; } else { MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, - Args[i].first, PtrOff)); + Args[i].first, PtrOff, DAG.getSrcValue(NULL))); } ArgOffset += 8; break; @@ -296,11 +296,11 @@ --FPR_remaining; if (isVarArg) { SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Chain, - Args[i].first, PtrOff); + Args[i].first, PtrOff, DAG.getSrcValue(NULL)); MemOps.push_back(Store); // Float varargs are always shadowed in available integer registers if (GPR_remaining > 0) { - SDOperand Load = DAG.getLoad(MVT::i64, Store, PtrOff); + SDOperand Load = DAG.getLoad(MVT::i64, Store, PtrOff, DAG.getSrcValue(NULL)); MemOps.push_back(Load); args_to_use.push_back(Load); --GPR_remaining; @@ -315,7 +315,7 @@ } } else { MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, - Args[i].first, PtrOff)); + Args[i].first, PtrOff, DAG.getSrcValue(NULL))); } ArgOffset += 8; break; @@ -351,7 +351,7 @@ MVT::ValueType ArgVT = getValueType(ArgTy); SDOperand Result; if (!isVANext) { - Result = DAG.getLoad(ArgVT, DAG.getEntryNode(), VAList); + Result = DAG.getLoad(ArgVT, DAG.getEntryNode(), VAList, DAG.getSrcValue(NULL)); } else { Result = DAG.getNode(ISD::ADD, VAList.getValueType(), VAList, DAG.getConstant(8, VAList.getValueType())); From alenhar2 at cs.uiuc.edu Wed Apr 27 15:10:24 2005 From: alenhar2 at cs.uiuc.edu (Andrew Lenharth) Date: Wed, 27 Apr 2005 15:10:24 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/Alpha/AlphaISelPattern.cpp Message-ID: <200504272010.j3RKAOLd023381@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/Alpha: AlphaISelPattern.cpp updated: 1.102 -> 1.103 --- Log message: Implement Value* tracking for loads and stores in the selection DAG. This enables one to use alias analysis in the backends. (TRUNK)Stores and (EXT|ZEXT|SEXT)Loads have an extra SDOperand which is a SrcValueSDNode which contains the Value*. Note that if the operation is introduced by the backend, it will still have the operand, but the value* will be null. --- Diffs of the changes: (+3 -3) AlphaISelPattern.cpp | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) Index: llvm/lib/Target/Alpha/AlphaISelPattern.cpp diff -u llvm/lib/Target/Alpha/AlphaISelPattern.cpp:1.102 llvm/lib/Target/Alpha/AlphaISelPattern.cpp:1.103 --- llvm/lib/Target/Alpha/AlphaISelPattern.cpp:1.102 Fri Apr 22 12:50:14 2005 +++ llvm/lib/Target/Alpha/AlphaISelPattern.cpp Wed Apr 27 15:10:01 2005 @@ -229,7 +229,7 @@ //from this parameter SDOperand FIN = DAG.getFrameIndex(FI, MVT::i64); argt = newroot = DAG.getLoad(getValueType(I->getType()), - DAG.getEntryNode(), FIN); + DAG.getEntryNode(), FIN, DAG.getSrcValue(NULL)); } ++count; LS.push_back(newroot.getValue(1)); @@ -245,14 +245,14 @@ SDOperand argt = DAG.getCopyFromReg(Vreg, MVT::i64, Chain); int FI = MFI->CreateFixedObject(8, -8 * (6 - i)); SDOperand SDFI = DAG.getFrameIndex(FI, MVT::i64); - LS.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, argt, SDFI)); + LS.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, argt, SDFI, DAG.getSrcValue(NULL))); Vreg = MF.getSSARegMap()->createVirtualRegister(getRegClassFor(MVT::f64)); BuildMI(&BB, Alpha::CPYS, 2, Vreg).addReg(args_float[i]).addReg(args_float[i]); argt = DAG.getCopyFromReg(Vreg, MVT::f64, Chain); FI = MFI->CreateFixedObject(8, - 8 * (12 - i)); SDFI = DAG.getFrameIndex(FI, MVT::i64); - LS.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, argt, SDFI)); + LS.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, argt, SDFI, DAG.getSrcValue(NULL))); } // If the function takes variable number of arguments, make a frame index for From alenhar2 at cs.uiuc.edu Wed Apr 27 15:10:25 2005 From: alenhar2 at cs.uiuc.edu (Andrew Lenharth) Date: Wed, 27 Apr 2005 15:10:25 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86ISelPattern.cpp Message-ID: <200504272010.j3RKAPKQ023390@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86ISelPattern.cpp updated: 1.107 -> 1.108 --- Log message: Implement Value* tracking for loads and stores in the selection DAG. This enables one to use alias analysis in the backends. (TRUNK)Stores and (EXT|ZEXT|SEXT)Loads have an extra SDOperand which is a SrcValueSDNode which contains the Value*. Note that if the operation is introduced by the backend, it will still have the operand, but the value* will be null. --- Diffs of the changes: (+5 -5) X86ISelPattern.cpp | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) Index: llvm/lib/Target/X86/X86ISelPattern.cpp diff -u llvm/lib/Target/X86/X86ISelPattern.cpp:1.107 llvm/lib/Target/X86/X86ISelPattern.cpp:1.108 --- llvm/lib/Target/X86/X86ISelPattern.cpp:1.107 Thu Apr 21 18:38:14 2005 +++ llvm/lib/Target/X86/X86ISelPattern.cpp Wed Apr 27 15:10:01 2005 @@ -141,7 +141,7 @@ // dead loads. SDOperand ArgValue; if (!I->use_empty()) - ArgValue = DAG.getLoad(ObjectVT, DAG.getEntryNode(), FIN); + ArgValue = DAG.getLoad(ObjectVT, DAG.getEntryNode(), FIN, DAG.getSrcValue(NULL)); else { if (MVT::isInteger(ObjectVT)) ArgValue = DAG.getConstant(0, ObjectVT); @@ -239,13 +239,13 @@ case MVT::i32: case MVT::f32: Stores.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, - Args[i].first, PtrOff)); + Args[i].first, PtrOff, DAG.getSrcValue(NULL))); ArgOffset += 4; break; case MVT::i64: case MVT::f64: Stores.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, - Args[i].first, PtrOff)); + Args[i].first, PtrOff, DAG.getSrcValue(NULL))); ArgOffset += 8; break; } @@ -278,7 +278,7 @@ MVT::ValueType ArgVT = getValueType(ArgTy); SDOperand Result; if (!isVANext) { - Result = DAG.getLoad(ArgVT, DAG.getEntryNode(), VAList); + Result = DAG.getLoad(ArgVT, DAG.getEntryNode(), VAList, DAG.getSrcValue(NULL)); } else { unsigned Amt; if (ArgVT == MVT::i32) @@ -312,7 +312,7 @@ if (!isFrameAddress) // Just load the return address - Result = DAG.getLoad(MVT::i32, DAG.getEntryNode(), RetAddrFI); + Result = DAG.getLoad(MVT::i32, DAG.getEntryNode(), RetAddrFI, DAG.getSrcValue(NULL)); else Result = DAG.getNode(ISD::SUB, MVT::i32, RetAddrFI, DAG.getConstant(4, MVT::i32)); From lattner at cs.uiuc.edu Wed Apr 27 15:12:30 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 27 Apr 2005 15:12:30 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/PruneEH.cpp Message-ID: <200504272012.j3RKCUtX023429@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: PruneEH.cpp updated: 1.20 -> 1.21 --- Log message: remove 'statement with no effect' warning --- Diffs of the changes: (+1 -1) PruneEH.cpp | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/lib/Transforms/IPO/PruneEH.cpp diff -u llvm/lib/Transforms/IPO/PruneEH.cpp:1.20 llvm/lib/Transforms/IPO/PruneEH.cpp:1.21 --- llvm/lib/Transforms/IPO/PruneEH.cpp:1.20 Tue Apr 26 23:52:23 2005 +++ llvm/lib/Transforms/IPO/PruneEH.cpp Wed Apr 27 15:12:17 2005 @@ -170,7 +170,7 @@ MadeChange = true; } - for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; I) + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) if (CallInst *CI = dyn_cast(I++)) if (Function *Callee = CI->getCalledFunction()) if (DoesNotReturn.count(CG[Callee]) && !isa(I)) { From alenhar2 at cs.uiuc.edu Wed Apr 27 15:12:43 2005 From: alenhar2 at cs.uiuc.edu (Andrew Lenharth) Date: Wed, 27 Apr 2005 15:12:43 -0500 Subject: [llvm-commits] CVS: llvm-test/GenerateReport.pl Message-ID: <200504272012.j3RKChwE023441@apoc.cs.uiuc.edu> Changes in directory llvm-test: GenerateReport.pl updated: 1.26 -> 1.27 --- Log message: Cut 60-70% off of the file size of the html files. --- Diffs of the changes: (+5 -5) GenerateReport.pl | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) Index: llvm-test/GenerateReport.pl diff -u llvm-test/GenerateReport.pl:1.26 llvm-test/GenerateReport.pl:1.27 --- llvm-test/GenerateReport.pl:1.26 Sat Mar 26 18:37:59 2005 +++ llvm-test/GenerateReport.pl Wed Apr 27 15:12:30 2005 @@ -209,19 +209,19 @@ }; ""; } sub printLine { - print "\n"; +# print "\n"; } print "\n"; print "\n"; map { - print ""; + #print ""; $_ = "
    $_
    " if $_ ne "|"; printCell $_ } @Header; - print ""; - print "\n"; - print "" x (2*@Header+1); + #print ""; + print "\n"; + #print "" x (2*@Header+1); print "\n"; my $RowCount = 0; foreach $Row (@Values) { From reid at x10sys.com Wed Apr 27 16:29:32 2005 From: reid at x10sys.com (Reid Spencer) Date: Wed, 27 Apr 2005 16:29:32 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Message-ID: <200504272129.QAA19057@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: SimplifyLibCalls.cpp updated: 1.18 -> 1.19 --- Log message: Doxygenate. --- Diffs of the changes: (+71 -54) SimplifyLibCalls.cpp | 125 ++++++++++++++++++++++++++++----------------------- 1 files changed, 71 insertions(+), 54 deletions(-) Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.18 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.19 --- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.18 Wed Apr 27 12:46:54 2005 +++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Wed Apr 27 16:29:20 2005 @@ -37,23 +37,33 @@ Statistic<> SimplifiedLibCalls("simplify-libcalls", "Number of well-known library calls simplified"); -/// @brief The list of optimizations deriving from LibCallOptimization +// Forward declarations class LibCallOptimization; class SimplifyLibCalls; + +/// @brief The list of optimizations deriving from LibCallOptimization hash_map optlist; /// This class is the abstract base class for the set of optimizations that -/// corresponds to one library call. The SimplifyLibCall pass will call the +/// corresponds to one library call. The SimplifyLibCalls pass will call the /// ValidateCalledFunction method to ask the optimization if a given Function -/// is the kind that the optimization can handle. It will also call the -/// OptimizeCall method to perform, or attempt to perform, the optimization(s) -/// for the library call. Subclasses of this class are located toward the -/// end of this file. +/// is the kind that the optimization can handle. If the subclass returns true, +/// then SImplifyLibCalls will also call the OptimizeCall method to perform, +/// or attempt to perform, the optimization(s) for the library call. Otherwise, +/// OptimizeCall won't be called. Subclasses are responsible for providing the +/// name of the library call (strlen, strcpy, etc.) to the LibCallOptimization +/// constructor. This is used to efficiently select which call instructions to +/// optimize. The criteria for a "lib call" is "anything with well known +/// semantics", typically a library function that is defined by an international +/// standard. Because the semantics are well known, the optimizations can +/// generally short-circuit actually calling the function if there's a simpler +/// way (e.g. strlen(X) can be reduced to a constant if X is a constant global). /// @brief Base class for library call optimizations struct LibCallOptimization { - /// @brief Constructor that registers the optimization. The \p fname argument - /// must be the name of the library function being optimized by the subclass. + /// The \p fname argument must be the name of the library function being + /// optimized by the subclass. + /// @brief Constructor that registers the optimization. LibCallOptimization(const char * fname ) : func_name(fname) #ifndef NDEBUG @@ -61,22 +71,23 @@ , occurrences(stat_name.c_str(),"Number of calls simplified") #endif { - // Register this call optimizer + // Register this call optimizer in the optlist (a hash_map) optlist[func_name] = this; } - /// @brief Destructor - virtual ~LibCallOptimization() {} + /// @brief Deregister from the optlist + virtual ~LibCallOptimization() { optlist.erase(func_name); } /// The implementation of this function in subclasses should determine if /// \p F is suitable for the optimization. This method is called by - /// runOnModule to short circuit visiting all the call sites of such a - /// function if that function is not suitable in the first place. - /// If the called function is suitabe, this method should return true; + /// SimplifyLibCalls::runOnModule to short circuit visiting all the call + /// sites of such a function if that function is not suitable in the first + /// place. If the called function is suitabe, this method should return true; /// false, otherwise. This function should also perform any lazy /// initialization that the LibCallOptimization needs to do, if its to return /// true. This avoids doing initialization until the optimizer is actually /// going to be called upon to do some optimization. + /// @brief Determine if the function is suitable for optimization virtual bool ValidateCalledFunction( const Function* F, ///< The function that is the target of call sites SimplifyLibCalls& SLC ///< The pass object invoking us @@ -88,8 +99,6 @@ /// the call and (b) to perform the optimization. If an action is taken /// against ci, the subclass is responsible for returning true and ensuring /// that ci is erased from its parent. - /// @param ci the call instruction under consideration - /// @param f the function that ci calls. /// @brief Optimize a call, if possible. virtual bool OptimizeCall( CallInst* ci, ///< The call instruction that should be optimized. @@ -100,7 +109,8 @@ const char * getFunctionName() const { return func_name; } #ifndef NDEBUG - void occurred() { ++occurrences; } + /// @brief Called by SimplifyLibCalls to update the occurrences statistic. + void succeeded() { ++occurrences; } #endif private: @@ -111,23 +121,19 @@ #endif }; -/// This class is the base class for a set of small but important -/// optimizations of calls to well-known functions, such as those in the c -/// library. - /// This class is an LLVM Pass that applies each of the LibCallOptimization /// instances to all the call sites in a module, relatively efficiently. The /// purpose of this pass is to provide optimizations for calls to well-known /// functions with well-known semantics, such as those in the c library. The -/// class provides the basic infrastructure for handling runOnModule. -/// Whenever this pass finds a function call, it asks the subclasses to -/// validate the call by calling ValidateLibraryCall. If it is validated, then -/// the OptimizeCall method is called. +/// class provides the basic infrastructure for handling runOnModule. Whenever /// this pass finds a function call, it asks the appropriate optimizer to +/// validate the call (ValidateLibraryCall). If it is validated, then +/// the OptimizeCall method is also called. /// @brief A ModulePass for optimizing well-known function calls. struct SimplifyLibCalls : public ModulePass { /// We need some target data for accurate signature details that are /// target dependent. So we require target data in our AnalysisUsage. + /// @brief Require TargetData from AnalysisUsage. virtual void getAnalysisUsage(AnalysisUsage& Info) const { // Ask that the TargetData analysis be performed before us so we can use @@ -137,6 +143,7 @@ /// For this pass, process all of the function calls in the module, calling /// ValidateLibraryCall and OptimizeCall as appropriate. + /// @brief Run all the lib call optimizations on a Module. virtual bool runOnModule(Module &M) { reset(M); @@ -183,7 +190,7 @@ ++SimplifiedLibCalls; found_optimization = result = true; #ifndef NDEBUG - CO->occurred(); + CO->succeeded(); #endif } } @@ -230,10 +237,8 @@ return memcpy_func; } - /// @brief Compute length of constant string - bool getConstantStringLength(Value* V, uint64_t& len ); - private: + /// @brief Reset our cached data for a new Module void reset(Module& mod) { M = &mod; @@ -243,10 +248,10 @@ } private: - Function* memcpy_func; - Function* strlen_func; - Module* M; - TargetData* TD; + Function* memcpy_func; ///< Cached llvm.memcpy function + Function* strlen_func; ///< Cached strlen function + Module* M; ///< Cached Module + TargetData* TD; ///< Cached TargetData }; // Register the pass @@ -272,9 +277,8 @@ /// This LibCallOptimization will find instances of a call to "exit" that occurs /// within the "main" function and change it to a simple "ret" instruction with -/// the same value as passed to the exit function. It assumes that the -/// instructions after the call to exit(3) can be deleted since they are -/// unreachable anyway. +/// the same value passed to the exit function. When this is done, it splits the +/// basic block at the exit(3) call and deletes the call instruction. /// @brief Replace calls to exit in main with a simple return struct ExitInMainOptimization : public LibCallOptimization { @@ -335,16 +339,18 @@ /// This LibCallOptimization will simplify a call to the strcat library /// function. The simplification is possible only if the string being /// concatenated is a constant array or a constant expression that results in -/// a constant array. In this case, if the array is small, we can generate a -/// series of inline store instructions to effect the concatenation without -/// calling strcat. +/// a constant string. In this case we can replace it with strlen + llvm.memcpy +/// of the constant string. Both of these calls are further reduced, if possible +/// on subsequent passes. /// @brief Simplify the strcat library function. struct StrCatOptimization : public LibCallOptimization { public: + /// @brief Default constructor StrCatOptimization() : LibCallOptimization("strcat") {} public: + /// @breif Destructor virtual ~StrCatOptimization() {} /// @brief Make sure that the "strcat" function has the right prototype @@ -425,8 +431,8 @@ } } StrCatOptimizer; -/// This LibCallOptimization will simplify a call to the strcpy library function. -/// Several optimizations are possible: +/// This LibCallOptimization will simplify a call to the strcpy library +/// function. Two optimizations are possible: /// (1) If src and dest are the same and not volatile, just return dest /// (2) If the src is a constant then we can convert to llvm.memmove /// @brief Simplify the strcpy library function. @@ -514,9 +520,9 @@ } } StrCpyOptimizer; -/// This LibCallOptimization will simplify a call to the strlen library function by -/// replacing it with a constant value if the string provided to it is a -/// constant array. +/// This LibCallOptimization will simplify a call to the strlen library +/// function by replacing it with a constant value if the string provided to +/// it is a constant array. /// @brief Simplify the strlen library function. struct StrLenOptimization : public LibCallOptimization { @@ -549,16 +555,20 @@ } } StrLenOptimizer; -/// This LibCallOptimization will simplify a call to the memcpy library function by -/// expanding it out to a single store of size 0, 1, 2, 4, or 8 bytes depending -/// on the length of the string and the alignment. +/// This LibCallOptimization will simplify a call to the memcpy library +/// function by expanding it out to a single store of size 0, 1, 2, 4, or 8 +/// bytes depending on the length of the string and the alignment. Additional +/// optimizations are possible in code generation (sequence of immediate store) /// @brief Simplify the memcpy library function. struct MemCpyOptimization : public LibCallOptimization { + /// @brief Default Constructor MemCpyOptimization() : LibCallOptimization("llvm.memcpy") {} protected: + /// @brief Subclass Constructor MemCpyOptimization(const char* fname) : LibCallOptimization(fname) {} public: + /// @brief Destructor virtual ~MemCpyOptimization() {} /// @brief Make sure that the "memcpy" function has the right prototype @@ -620,19 +630,27 @@ } } MemCpyOptimizer; -/// This LibCallOptimization will simplify a call to the memmove library function. /// It is identical to MemCopyOptimization except for the name of the intrinsic. +/// This LibCallOptimization will simplify a call to the memmove library +/// function. It is identical to MemCopyOptimization except for the name of +/// the intrinsic. /// @brief Simplify the memmove library function. struct MemMoveOptimization : public MemCpyOptimization { + /// @brief Default Constructor MemMoveOptimization() : MemCpyOptimization("llvm.memmove") {} } MemMoveOptimizer; -/// A function to compute the length of a null-terminated string of integers. -/// This function can't rely on the size of the constant array because there -/// could be a null terminator in the middle of the array. We also have to -/// bail out if we find a non-integer constant initializer of one of the -/// elements or if there is no null-terminator. The logic below checks +/// A function to compute the length of a null-terminated constant array of +/// integers. This function can't rely on the size of the constant array +/// because there could be a null terminator in the middle of the array. +/// We also have to bail out if we find a non-integer constant initializer +/// of one of the elements or if there is no null-terminator. The logic +/// below checks each of these conditions and will return true only if all +/// conditions are met. In that case, the \p len parameter is set to the length +/// of the null-terminated string. If false is returned, the conditions were +/// not met and len is set to 0. +/// @brief Get the length of a constant string (null-terminated array). bool getConstantStringLength(Value* V, uint64_t& len ) { assert(V != 0 && "Invalid args to getConstantStringLength"); @@ -723,7 +741,6 @@ return true; // success! } - // TODO: Additional cases that we need to add to this file: // 1. memmove -> memcpy if src is a global constant array } From reid at x10sys.com Wed Apr 27 23:40:17 2005 From: reid at x10sys.com (Reid Spencer) Date: Wed, 27 Apr 2005 23:40:17 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Message-ID: <200504280440.XAA20949@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: SimplifyLibCalls.cpp updated: 1.19 -> 1.20 --- Log message: Document additional libcall transformations that need to be written. Help Wanted! There's a lot of them to write. --- Diffs of the changes: (+183 -2) SimplifyLibCalls.cpp | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 183 insertions(+), 2 deletions(-) Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.19 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.20 --- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.19 Wed Apr 27 16:29:20 2005 +++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Wed Apr 27 23:40:06 2005 @@ -741,6 +741,187 @@ return true; // success! } -// TODO: Additional cases that we need to add to this file: -// 1. memmove -> memcpy if src is a global constant array +// TODO: +// Additional cases that we need to add to this file: +// +// abs: +// * abs(cnst) -> cnst' +// +// atan: +// * atan(0.0) -> 0.0 +// * atan(1.0) -> pi/4 +// +// cbrt: +// * cbrt(constant) -> constant' +// * cbrt(expN(X)) -> expN(x/3) +// * cbrt(sqrt(x)) -> pow(x,1/6) +// * cbrt(sqrt(x)) -> pow(x,1/9) +// +// ceil, ceilf, ceill: +// * ceil(constant) -> constant' +// +// cos, cosf, cosl: +// * cos(0.0) -> 1.0 +// * cox(-x) -> cos(x) +// +// exp, expf, expl: +// * exp(0.0) -> 1.0 +// * exp(int) -> contant' +// * exp(log(x)) -> x +// +// fabs, fabsf, fabsl: +// * fabs(cnst) -> cnst' +// +// ffs, ffsl, ffsll: +// * ffs(cnst) -> cnst' +// +// floor, floorf, floorl: +// * floor(cnst) -> cnst' +// +// fprintf: +// * fprintf(file,fmt) -> fputs(fmt,file) +// (if fmt is constant and constains no % characters) +// * fprintf(file,"%s",str) -> fputs(orig,str) +// (only if the fprintf result is not used) +// * fprintf(file,"%c",chr) -> fputc(chr,file) +// +// fputs: (only if the result is not used) +// * fputs("",F) -> noop +// * fputs(s,F) -> fputc(s[0],F) (if s is constant and strlen(s) == 1) +// * fputs(s,F) -> fwrite(s, 1, len, F) (if s is constant and strlen(s) > 1) +// +// isascii: +// * isascii(c) -> ((c & ~0x7f) == 0) +// +// isdigit: +// * isdigit(c) -> (unsigned)(c) - '0' <= 9 +// +// log, logf, logl: +// * log(1.0) -> 0.0 +// * log(exp(x)) -> x +// * log(x**y) -> y*log(x) +// * log(exp(y)) -> y*log(e) +// * log(exp2(y)) -> y*log(2) +// * log(exp10(y)) -> y*log(10) +// * log(sqrt(x)) -> 0.5*log(x) +// * log(pow(x,y)) -> y*log(x) +// +// lround, lroundf, lroundl: +// * lround(cnst) -> cnst' +// +// memcmp: +// * memcmp(s1,s2,0) -> 0 +// * memcmp(x,x,l) -> 0 +// * memcmp(x,y,l) -> cnst +// (if all arguments are constant and strlen(x) <= l and strlen(y) <= l) +// * memcpy(x,y,1) -> *x - *y +// +// memcpy: +// * memcpy(d,s,0,a) -> d +// +// memmove: +// * memmove(d,s,l,a) -> memcpy(d,s,l,a) +// (if s is a global constant array) +// +// memset: +// * memset(s,c,0) -> noop +// * memset(s,c,n) -> store s, c +// (for n=1,2,4,8) +// +// pow, powf, powl: +// * pow(1.0,y) -> 1.0 +// * pow(x,0.0) -> 1.0 +// * pow(x,1.0) -> x +// * pow(x,-1.0) -> 1.0/x +// * pow(x,0.5) -> sqrt(x) +// * pow(cst1,cst2) -> const1**const2 +// * pow(exp(x),y) -> exp(x*y) +// * pow(sqrt(x),y) -> pow(x,y*0.5) +// * pow(pow(x,y),z)-> pow(x,y*z) +// +// puts: +// * puts("") -> fputc("\n",stdout) (how do we get "stdout"?) +// +// round, roundf, roundl: +// * round(cnst) -> cnst' +// +// signbit: +// * signbit(cnst) -> cnst' +// * signbit(nncst) -> 0 (if pstv is a non-negative constant) +// +// sin, sinf, sinl: +// * sin(0.0) -> 0.0 +// +// sprintf: +// * sprintf(dest,fmt) -> strcpy(dest,fmt) +// (if fmt is constant and constains no % characters) +// * sprintf(dest,"%s",orig) -> strcpy(dest,orig) +// (only if the sprintf result is not used) +// +// sqrt, sqrtf, sqrtl: +// * sqrt(cnst) -> cnst' +// * sqrt(expN(x)) -> expN(x*0.5) +// * sqrt(Nroot(x)) -> pow(x,1/(2*N)) +// * sqrt(pow(x,y)) -> pow(|x|,y*0.5) +// +// strchr, strrchr: +// * strchr(s,c) -> offset_of_in(c,s) +// (if c is a constant integer and s is a constant string) +// * strrchr(s,c) -> reverse_offset_of_in(c,s) +// (if c is a constant integer and s is a constant string) +// * strrchr(s1,0) -> strchr(s1,0) +// +// strcmp: +// * strcmp(x,x) -> 0 +// * strcmp(x,"") -> *x +// * strcmp("",x) -> *x +// * strcmp(x,y) -> cnst (if both x and y are constant strings) +// +// strncat: +// * strncat(x,y,0) -> x +// * strncat(x,y,0) -> x (if strlen(y) = 0) +// * strncat(x,y,l) -> strcat(x,y) (if y and l are constants an l > strlen(y)) +// +// strncmp: +// * strncmp(x,y,0) -> 0 +// * strncmp(x,x,l) -> 0 +// * strncmp(x,"",l) -> *x +// * strncmp("",x,l) -> *x +// * strncmp(x,y,1) -> *x - *y +// +// strncpy: +// * strncpy(d,s,0) -> d +// * strncpy(d,s,l) -> memcpy(d,s,l,1) +// (if s and l are constants) +// +// strpbrk: +// * strpbrk(s,a) -> offset_in_for(s,a) +// (if s and a are both constant strings) +// * strpbrk(s,"") -> 0 +// * strpbrk(s,a) -> strchr(s,a[0]) (if a is constant string of length 1) +// +// strspn, strcspn: +// * strspn(s,a) -> const_int (if both args are constant) +// * strspn("",a) -> 0 +// * strspn(s,"") -> 0 +// * strcspn(s,a) -> const_int (if both args are constant) +// * strcspn("",a) -> 0 +// * strcspn(s,"") -> strlen(a) +// +// strstr: +// * strstr(x,x) -> x +// * strstr(s1,s2) -> offset_of_s2_in(s1) +// (if s1 and s2 are constant strings) +// +// tan, tanf, tanl: +// * tan(0.0) -> 0.0 +// * tan(atan(x)) -> x +// +// toascii: +// * toascii(c) -> (c & 0x7f) +// +// trunc, truncf, truncl: +// * trunc(cnst) -> cnst' +// +// } From reid at x10sys.com Thu Apr 28 13:05:27 2005 From: reid at x10sys.com (Reid Spencer) Date: Thu, 28 Apr 2005 13:05:27 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Message-ID: <200504281805.NAA20454@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: SimplifyLibCalls.cpp updated: 1.20 -> 1.21 --- Log message: Remove from the TODO list those optimizations that are already handled by constant folding implemented in lib/Transforms/Utils/Local.cpp. --- Diffs of the changes: (+1 -29) SimplifyLibCalls.cpp | 30 +----------------------------- 1 files changed, 1 insertion(+), 29 deletions(-) Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.20 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.21 --- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.20 Wed Apr 27 23:40:06 2005 +++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Thu Apr 28 13:05:16 2005 @@ -744,40 +744,21 @@ // TODO: // Additional cases that we need to add to this file: // -// abs: -// * abs(cnst) -> cnst' -// -// atan: -// * atan(0.0) -> 0.0 -// * atan(1.0) -> pi/4 -// // cbrt: -// * cbrt(constant) -> constant' // * cbrt(expN(X)) -> expN(x/3) // * cbrt(sqrt(x)) -> pow(x,1/6) // * cbrt(sqrt(x)) -> pow(x,1/9) // -// ceil, ceilf, ceill: -// * ceil(constant) -> constant' -// // cos, cosf, cosl: -// * cos(0.0) -> 1.0 -// * cox(-x) -> cos(x) +// * cos(-x) -> cos(x) // // exp, expf, expl: -// * exp(0.0) -> 1.0 // * exp(int) -> contant' // * exp(log(x)) -> x // -// fabs, fabsf, fabsl: -// * fabs(cnst) -> cnst' -// // ffs, ffsl, ffsll: // * ffs(cnst) -> cnst' // -// floor, floorf, floorl: -// * floor(cnst) -> cnst' -// // fprintf: // * fprintf(file,fmt) -> fputs(fmt,file) // (if fmt is constant and constains no % characters) @@ -797,7 +778,6 @@ // * isdigit(c) -> (unsigned)(c) - '0' <= 9 // // log, logf, logl: -// * log(1.0) -> 0.0 // * log(exp(x)) -> x // * log(x**y) -> y*log(x) // * log(exp(y)) -> y*log(e) @@ -829,9 +809,6 @@ // (for n=1,2,4,8) // // pow, powf, powl: -// * pow(1.0,y) -> 1.0 -// * pow(x,0.0) -> 1.0 -// * pow(x,1.0) -> x // * pow(x,-1.0) -> 1.0/x // * pow(x,0.5) -> sqrt(x) // * pow(cst1,cst2) -> const1**const2 @@ -849,9 +826,6 @@ // * signbit(cnst) -> cnst' // * signbit(nncst) -> 0 (if pstv is a non-negative constant) // -// sin, sinf, sinl: -// * sin(0.0) -> 0.0 -// // sprintf: // * sprintf(dest,fmt) -> strcpy(dest,fmt) // (if fmt is constant and constains no % characters) @@ -859,7 +833,6 @@ // (only if the sprintf result is not used) // // sqrt, sqrtf, sqrtl: -// * sqrt(cnst) -> cnst' // * sqrt(expN(x)) -> expN(x*0.5) // * sqrt(Nroot(x)) -> pow(x,1/(2*N)) // * sqrt(pow(x,y)) -> pow(|x|,y*0.5) @@ -914,7 +887,6 @@ // (if s1 and s2 are constant strings) // // tan, tanf, tanl: -// * tan(0.0) -> 0.0 // * tan(atan(x)) -> x // // toascii: From lattner at cs.uiuc.edu Thu Apr 28 16:43:42 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu, 28 Apr 2005 16:43:42 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/CodeGen/SelectionDAGNodes.h Message-ID: <200504282143.j3SLhfnH013186@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/CodeGen: SelectionDAGNodes.h updated: 1.34 -> 1.35 --- Log message: Add FSQRT, FSIN, FCOS nodes, patch contributed by Morten Ofstad --- Diffs of the changes: (+3 -3) SelectionDAGNodes.h | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) Index: llvm/include/llvm/CodeGen/SelectionDAGNodes.h diff -u llvm/include/llvm/CodeGen/SelectionDAGNodes.h:1.34 llvm/include/llvm/CodeGen/SelectionDAGNodes.h:1.35 --- llvm/include/llvm/CodeGen/SelectionDAGNodes.h:1.34 Wed Apr 27 15:10:01 2005 +++ llvm/include/llvm/CodeGen/SelectionDAGNodes.h Thu Apr 28 16:43:25 2005 @@ -168,9 +168,9 @@ // FP_EXTEND - Extend a smaller FP type into a larger FP type. FP_EXTEND, - // FNEG, FABS - Perform unary floating point negation and absolute value - // operations. - FNEG, FABS, + // FNEG, FABS, FSQRT, FSIN, FCOS - Perform unary floating point negation, + // absolute value, square root, sine and cosine operations. + FNEG, FABS, FSQRT, FSIN, FCOS, // Other operators. LOAD and STORE have token chains as their first // operand, then the same operands as an LLVM load/store instruction. From lattner at cs.uiuc.edu Thu Apr 28 16:44:18 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu, 28 Apr 2005 16:44:18 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Message-ID: <200504282144.j3SLiI0V013211@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: SelectionDAG.cpp updated: 1.96 -> 1.97 --- Log message: Add FSQRT, FSIN, FCOS nodes, patch contributed by Morten Ofstad --- Diffs of the changes: (+4 -1) SelectionDAG.cpp | 5 ++++- 1 files changed, 4 insertions(+), 1 deletion(-) Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.96 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.97 --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.96 Wed Apr 27 15:10:01 2005 +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Thu Apr 28 16:44:03 2005 @@ -1568,6 +1568,9 @@ // Unary operators case ISD::FABS: return "fabs"; case ISD::FNEG: return "fneg"; + case ISD::FSQRT: return "fsqrt"; + case ISD::FSIN: return "fsin"; + case ISD::FCOS: return "fcos"; // Binary operators case ISD::ADD: return "add"; @@ -1593,7 +1596,7 @@ case ISD::SRA_PARTS: return "sra_parts"; case ISD::SRL_PARTS: return "srl_parts"; - // Conversion operators. + // Conversion operators. case ISD::SIGN_EXTEND: return "sign_extend"; case ISD::ZERO_EXTEND: return "zero_extend"; case ISD::SIGN_EXTEND_INREG: return "sign_extend_inreg"; From lattner at cs.uiuc.edu Thu Apr 28 16:44:46 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu, 28 Apr 2005 16:44:46 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Message-ID: <200504282144.j3SLikJk013238@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: LegalizeDAG.cpp updated: 1.91 -> 1.92 --- Log message: Legalize FSQRT, FSIN, FCOS nodes, patch contributed by Morten Ofstad --- Diffs of the changes: (+13 -0) LegalizeDAG.cpp | 13 +++++++++++++ 1 files changed, 13 insertions(+) Index: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.91 llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.92 --- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.91 Wed Apr 27 15:10:01 2005 +++ llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Thu Apr 28 16:44:33 2005 @@ -990,6 +990,9 @@ // Unary operators case ISD::FABS: case ISD::FNEG: + case ISD::FSQRT: + case ISD::FSIN: + case ISD::FCOS: Tmp1 = LegalizeOp(Node->getOperand(0)); switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) { case TargetLowering::Legal: @@ -1335,6 +1338,16 @@ // precision, and these operations don't modify precision at all. break; + case ISD::FSQRT: + case ISD::FSIN: + case ISD::FCOS: + Tmp1 = PromoteOp(Node->getOperand(0)); + assert(Tmp1.getValueType() == NVT); + Result = DAG.getNode(Node->getOpcode(), NVT, Tmp1); + if(NoExcessFPPrecision) + Result = DAG.getNode(ISD::FP_ROUND_INREG, NVT, Result, VT); + break; + case ISD::AND: case ISD::OR: case ISD::XOR: From lattner at cs.uiuc.edu Thu Apr 28 16:48:59 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu, 28 Apr 2005 16:48:59 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86ISelSimple.cpp Message-ID: <200504282148.j3SLmxUA013415@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86ISelSimple.cpp updated: 1.314 -> 1.315 --- Log message: Codegen fabs/fabsf as FABS. Patch contributed by Morten Ofstad --- Diffs of the changes: (+9 -0) X86ISelSimple.cpp | 9 +++++++++ 1 files changed, 9 insertions(+) Index: llvm/lib/Target/X86/X86ISelSimple.cpp diff -u llvm/lib/Target/X86/X86ISelSimple.cpp:1.314 llvm/lib/Target/X86/X86ISelSimple.cpp:1.315 --- llvm/lib/Target/X86/X86ISelSimple.cpp:1.314 Thu Apr 21 18:38:14 2005 +++ llvm/lib/Target/X86/X86ISelSimple.cpp Thu Apr 28 16:48:42 2005 @@ -1735,6 +1735,15 @@ if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) { visitIntrinsicCall(ID, CI); // Special intrinsics are not handled here return; + } else if (F->getName() == "fabs" || F->getName() == "fabsf") { + if (CI.getNumOperands() == 2 && // Basic sanity checks. + CI.getOperand(1)->getType()->isFloatingPoint() && + CI.getType() == CI.getOperand(1)->getType()) { + unsigned op1Reg = getReg(CI.getOperand(1)); + unsigned DestReg = getReg(CI); + BuildMI(BB, X86::FABS, 1, DestReg).addReg(op1Reg); + return; + } } // Emit a CALL instruction with PC-relative displacement. From lattner at cs.uiuc.edu Thu Apr 28 16:50:18 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu, 28 Apr 2005 16:50:18 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86InstrInfo.td Message-ID: <200504282150.j3SLoIWe013432@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86InstrInfo.td updated: 1.121 -> 1.122 --- Log message: Add some new X86 instrs, patch contributed by Morten Ofstad --- Diffs of the changes: (+6 -3) X86InstrInfo.td | 9 ++++++--- 1 files changed, 6 insertions(+), 3 deletions(-) Index: llvm/lib/Target/X86/X86InstrInfo.td diff -u llvm/lib/Target/X86/X86InstrInfo.td:1.121 llvm/lib/Target/X86/X86InstrInfo.td:1.122 --- llvm/lib/Target/X86/X86InstrInfo.td:1.121 Tue Apr 5 23:19:22 2005 +++ llvm/lib/Target/X86/X86InstrInfo.td Thu Apr 28 16:50:05 2005 @@ -1535,9 +1535,12 @@ // Unary operations... -def FCHS : FPI<0xE0, RawFrm, OneArgFPRW, (ops), "fchs">, D9; // f1 = fchs f2 -def FABS : FPI<0xE1, RawFrm, OneArgFPRW, (ops), "fabs">, D9; // f1 = fabs f2 -def FTST : FPI<0xE4, RawFrm, OneArgFP, (ops), "ftst">, D9; // ftst ST(0) +def FCHS : FPI<0xE0, RawFrm, OneArgFPRW, (ops), "fchs" >, D9; // f1 = fchs f2 +def FABS : FPI<0xE1, RawFrm, OneArgFPRW, (ops), "fabs" >, D9; // f1 = fabs f2 +def FSQRT : FPI<0xFA, RawFrm, OneArgFPRW, (ops), "fsqrt">, D9; // fsqrt ST(0) +def FSIN : FPI<0xFE, RawFrm, OneArgFPRW, (ops), "fsin" >, D9; // fsin ST(0) +def FCOS : FPI<0xFF, RawFrm, OneArgFPRW, (ops), "fcos" >, D9; // fcos ST(0) +def FTST : FPI<0xE4, RawFrm, OneArgFP , (ops), "ftst" >, D9; // ftst ST(0) // Binary arithmetic operations... class FPST0rInst o, dag ops, string asm> From lattner at cs.uiuc.edu Thu Apr 28 16:52:48 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu, 28 Apr 2005 16:52:48 -0500 Subject: [llvm-commits] CVS: llvm/lib/Analysis/BasicAliasAnalysis.cpp Message-ID: <200504282152.j3SLqmiN013550@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: BasicAliasAnalysis.cpp updated: 1.66 -> 1.67 --- Log message: These functions can set errno! --- Diffs of the changes: (+2 -2) BasicAliasAnalysis.cpp | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) Index: llvm/lib/Analysis/BasicAliasAnalysis.cpp diff -u llvm/lib/Analysis/BasicAliasAnalysis.cpp:1.66 llvm/lib/Analysis/BasicAliasAnalysis.cpp:1.67 --- llvm/lib/Analysis/BasicAliasAnalysis.cpp:1.66 Thu Apr 21 16:04:58 2005 +++ llvm/lib/Analysis/BasicAliasAnalysis.cpp Thu Apr 28 16:52:31 2005 @@ -709,10 +709,10 @@ "atan", "atanf", "atanl", "atan2", "atan2f", "atan2l", "cbrt", - "cos", "cosf", "cosl", "cosh", "coshf", "coshl", + "cos", "cosf", "cosl", "exp", "expf", "expl", "hypot", - "sin", "sinf", "sinl", "sinh", "sinhf", "sinhl", + "sin", "sinf", "sinl", "tan", "tanf", "tanl", "tanh", "tanhf", "tanhl", // ctype.h From lattner at cs.uiuc.edu Thu Apr 28 17:07:35 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu, 28 Apr 2005 17:07:35 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86ISelPattern.cpp Message-ID: <200504282207.j3SM7ZOk013766@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86ISelPattern.cpp updated: 1.108 -> 1.109 --- Log message: Add support for FSQRT node, patch contributed by Morten Ofstad --- Diffs of the changes: (+8 -4) X86ISelPattern.cpp | 12 ++++++++---- 1 files changed, 8 insertions(+), 4 deletions(-) Index: llvm/lib/Target/X86/X86ISelPattern.cpp diff -u llvm/lib/Target/X86/X86ISelPattern.cpp:1.108 llvm/lib/Target/X86/X86ISelPattern.cpp:1.109 --- llvm/lib/Target/X86/X86ISelPattern.cpp:1.108 Wed Apr 27 15:10:01 2005 +++ llvm/lib/Target/X86/X86ISelPattern.cpp Thu Apr 28 17:07:18 2005 @@ -1830,12 +1830,16 @@ return Result; case ISD::FABS: - Tmp1 = SelectExpr(Node->getOperand(0)); - BuildMI(BB, X86::FABS, 1, Result).addReg(Tmp1); - return Result; case ISD::FNEG: + case ISD::FSQRT: + assert(N.getValueType()==MVT::f64 && "Illegal type for this operation"); Tmp1 = SelectExpr(Node->getOperand(0)); - BuildMI(BB, X86::FCHS, 1, Result).addReg(Tmp1); + switch (N.getOpcode()) { + default: assert(0 && "Unreachable!"); + case ISD::FABS: BuildMI(BB, X86::FABS, 1, Result).addReg(Tmp1); break; + case ISD::FNEG: BuildMI(BB, X86::FCHS, 1, Result).addReg(Tmp1); break; + case ISD::FSQRT: BuildMI(BB, X86::FSQRT, 1, Result).addReg(Tmp1); break; + } return Result; case ISD::MULHU: From reid at x10sys.com Thu Apr 28 18:02:10 2005 From: reid at x10sys.com (Reid Spencer) Date: Thu, 28 Apr 2005 18:02:10 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/Local.cpp Message-ID: <200504282302.SAA22835@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: Local.cpp updated: 1.36 -> 1.37 --- Log message: * Add constant folding for additional floating point library calls such as sinh, cosh, etc. * Make the name comparisons for the fp libcalls a little more efficient by switching on the first character of the name before doing comparisons. --- Diffs of the changes: (+90 -26) Local.cpp | 116 ++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 files changed, 90 insertions(+), 26 deletions(-) Index: llvm/lib/Transforms/Utils/Local.cpp diff -u llvm/lib/Transforms/Utils/Local.cpp:1.36 llvm/lib/Transforms/Utils/Local.cpp:1.37 --- llvm/lib/Transforms/Utils/Local.cpp:1.36 Thu Apr 21 18:45:34 2005 +++ llvm/lib/Transforms/Utils/Local.cpp Thu Apr 28 18:01:59 2005 @@ -242,9 +242,29 @@ default: break; } - return Name == "sin" || Name == "cos" || Name == "tan" || Name == "sqrt" || - Name == "log" || Name == "log10" || Name == "exp" || Name == "pow" || - Name == "acos" || Name == "asin" || Name == "atan" || Name == "fmod"; + switch (Name[0]) + { + case 'a': + return Name == "acos" || Name == "asin" || Name == "atan" || + Name == "atan2"; + case 'c': + return Name == "ceil" || Name == "cos" || Name == "cosf" || + Name == "cosh"; + case 'e': + return Name == "exp"; + case 'f': + return Name == "fabs" || Name == "fmod" || Name == "floor"; + case 'l': + return Name == "log" || Name == "log10"; + case 'p': + return Name == "pow"; + case 's': + return Name == "sin" || Name == "sinh" || Name == "sqrt"; + case 't': + return Name == "tan" || Name == "tanh"; + default: + return false; + } } static Constant *ConstantFoldFP(double (*NativeFP)(double), double V, @@ -266,31 +286,63 @@ if (Operands.size() == 1) { if (ConstantFP *Op = dyn_cast(Operands[0])) { double V = Op->getValue(); - if (Name == "sin") - return ConstantFP::get(Ty, sin(V)); - else if (Name == "cos") - return ConstantFP::get(Ty, cos(V)); - else if (Name == "tan") - return ConstantFP::get(Ty, tan(V)); - else if (Name == "sqrt" && V >= 0) - return ConstantFP::get(Ty, sqrt(V)); - else if (Name == "exp") - return ConstantFP::get(Ty, exp(V)); - else if (Name == "log" && V > 0) - return ConstantFP::get(Ty, log(V)); - else if (Name == "log10") - return ConstantFoldFP(log10, V, Ty); - else if (Name == "acos") - return ConstantFoldFP(acos, V, Ty); - else if (Name == "asin") - return ConstantFoldFP(asin, V, Ty); - else if (Name == "atan") - return ConstantFP::get(Ty, atan(V)); + switch (Name[0]) + { + case 'a': + if (Name == "acos") + return ConstantFoldFP(acos, V, Ty); + else if (Name == "asin") + return ConstantFoldFP(asin, V, Ty); + else if (Name == "atan") + return ConstantFP::get(Ty, atan(V)); + break; + case 'c': + if (Name == "ceil") + return ConstantFoldFP(ceil, V, Ty); + else if (Name == "cos") + return ConstantFP::get(Ty, cos(V)); + else if (Name == "cosh") + return ConstantFP::get(Ty, cosh(V)); + break; + case 'e': + if (Name == "exp") + return ConstantFP::get(Ty, exp(V)); + break; + case 'f': + if (Name == "fabs") + return ConstantFP::get(Ty, fabs(V)); + else if (Name == "floor") + return ConstantFoldFP(floor, V, Ty); + break; + case 'l': + if (Name == "log" && V > 0) + return ConstantFP::get(Ty, log(V)); + else if (Name == "log10" && V > 0) + return ConstantFoldFP(log10, V, Ty); + break; + case 's': + if (Name == "sin") + return ConstantFP::get(Ty, sin(V)); + else if (Name == "sinh") + return ConstantFP::get(Ty, sinh(V)); + else if (Name == "sqrt" && V >= 0) + return ConstantFP::get(Ty, sqrt(V)); + break; + case 't': + if (Name == "tan") + return ConstantFP::get(Ty, tan(V)); + else if (Name == "tanh") + return ConstantFP::get(Ty, tanh(V)); + break; + default: + break; + } } } else if (Operands.size() == 2) { - if (ConstantFP *Op1 = dyn_cast(Operands[0])) + if (ConstantFP *Op1 = dyn_cast(Operands[0])) { + double Op1V = Op1->getValue(); if (ConstantFP *Op2 = dyn_cast(Operands[1])) { - double Op1V = Op1->getValue(), Op2V = Op2->getValue(); + double Op2V = Op2->getValue(); if (Name == "llvm.isunordered") return ConstantBool::get(IsNAN(Op1V) || IsNAN(Op2V)); @@ -305,8 +357,20 @@ double V = fmod(Op1V, Op2V); if (errno == 0) return ConstantFP::get(Ty, V); - } + } else if (Name == "atan2") + return ConstantFP::get(Ty, atan2(Op1V,Op2V)); } + else if (Name == "pow" && Op1V == 1.0) { + return ConstantFP::get(Ty,1.0); + } + } else if (ConstantFP* Op2 = dyn_cast(Operands[1])) { + double Op2V = Op2->getValue(); + if (Name == "pow") + if (Op2V == 0.0) + return ConstantFP::get(Ty,1.0); + else if (Op2V == 1.0) + return Operands[0]; + } } return 0; } From jeffc at jolt-lang.org Thu Apr 28 22:05:55 2005 From: jeffc at jolt-lang.org (Jeff Cohen) Date: Thu, 28 Apr 2005 22:05:55 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Message-ID: <200504290305.WAA24855@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: SimplifyLibCalls.cpp updated: 1.21 -> 1.22 --- Log message: Consistently use 'class' to silence VC++ --- Diffs of the changes: (+4 -2) SimplifyLibCalls.cpp | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.21 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.22 --- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.21 Thu Apr 28 13:05:16 2005 +++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Thu Apr 28 22:05:44 2005 @@ -59,8 +59,9 @@ /// generally short-circuit actually calling the function if there's a simpler /// way (e.g. strlen(X) can be reduced to a constant if X is a constant global). /// @brief Base class for library call optimizations -struct LibCallOptimization +class LibCallOptimization { +public: /// The \p fname argument must be the name of the library function being /// optimized by the subclass. /// @brief Constructor that registers the optimization. @@ -129,8 +130,9 @@ /// validate the call (ValidateLibraryCall). If it is validated, then /// the OptimizeCall method is also called. /// @brief A ModulePass for optimizing well-known function calls. -struct SimplifyLibCalls : public ModulePass +class SimplifyLibCalls : public ModulePass { +public: /// We need some target data for accurate signature details that are /// target dependent. So we require target data in our AnalysisUsage. /// @brief Require TargetData from AnalysisUsage. From reid at x10sys.com Fri Apr 29 00:47:16 2005 From: reid at x10sys.com (Reid Spencer) Date: Fri, 29 Apr 2005 00:47:16 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/SimplifyLibCalls/Pow.ll Message-ID: <200504290547.AAA25606@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/SimplifyLibCalls: Pow.ll added (r1.1) --- Log message: New test case for testing pow(3) math library optimizations. --- Diffs of the changes: (+18 -0) Pow.ll | 18 ++++++++++++++++++ 1 files changed, 18 insertions(+) Index: llvm/test/Regression/Transforms/SimplifyLibCalls/Pow.ll diff -c /dev/null llvm/test/Regression/Transforms/SimplifyLibCalls/Pow.ll:1.1 *** /dev/null Fri Apr 29 00:47:15 2005 --- llvm/test/Regression/Transforms/SimplifyLibCalls/Pow.ll Fri Apr 29 00:47:05 2005 *************** *** 0 **** --- 1,18 ---- + ; Test that the StrCatOptimizer works correctly + ; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | not grep 'pow' + + declare double %pow(double,double) + %fpstorage = global double 5.0 + + implementation ; Functions: + + int %main () { + %fpnum = load double* %fpstorage; + %one = call double %pow(double 1.0, double %fpnum) + %two = call double %pow(double %one, double 0.5) + %three = call double %pow(double %two, double 1.0) + %four = call double %pow(double %three, double -1.0) + %five = call double %pow(double %four, double 0.0) + %result = cast double %five to int + ret int %result + } From reid at x10sys.com Fri Apr 29 00:55:46 2005 From: reid at x10sys.com (Reid Spencer) Date: Fri, 29 Apr 2005 00:55:46 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/Local.cpp Message-ID: <200504290555.AAA25660@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: Local.cpp updated: 1.37 -> 1.38 --- Log message: Remove optimizations that don't require both operands to be constant. These are moved to simplify-libcalls pass. --- Diffs of the changes: (+0 -10) Local.cpp | 10 ---------- 1 files changed, 10 deletions(-) Index: llvm/lib/Transforms/Utils/Local.cpp diff -u llvm/lib/Transforms/Utils/Local.cpp:1.37 llvm/lib/Transforms/Utils/Local.cpp:1.38 --- llvm/lib/Transforms/Utils/Local.cpp:1.37 Thu Apr 28 18:01:59 2005 +++ llvm/lib/Transforms/Utils/Local.cpp Fri Apr 29 00:55:35 2005 @@ -360,16 +360,6 @@ } else if (Name == "atan2") return ConstantFP::get(Ty, atan2(Op1V,Op2V)); } - else if (Name == "pow" && Op1V == 1.0) { - return ConstantFP::get(Ty,1.0); - } - } else if (ConstantFP* Op2 = dyn_cast(Operands[1])) { - double Op2V = Op2->getValue(); - if (Name == "pow") - if (Op2V == 0.0) - return ConstantFP::get(Ty,1.0); - else if (Op2V == 1.0) - return Operands[0]; } } return 0; From reid at x10sys.com Fri Apr 29 01:01:39 2005 From: reid at x10sys.com (Reid Spencer) Date: Fri, 29 Apr 2005 01:01:39 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/SimplifyLibCalls/StrCpy.ll Message-ID: <200504290601.BAA25742@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/SimplifyLibCalls: StrCpy.ll added (r1.1) --- Log message: Add a testcase for optimizing the strcpy libcall. --- Diffs of the changes: (+24 -0) StrCpy.ll | 24 ++++++++++++++++++++++++ 1 files changed, 24 insertions(+) Index: llvm/test/Regression/Transforms/SimplifyLibCalls/StrCpy.ll diff -c /dev/null llvm/test/Regression/Transforms/SimplifyLibCalls/StrCpy.ll:1.1 *** /dev/null Fri Apr 29 01:01:38 2005 --- llvm/test/Regression/Transforms/SimplifyLibCalls/StrCpy.ll Fri Apr 29 01:01:28 2005 *************** *** 0 **** --- 1,24 ---- + ; Test that the StrCatOptimizer works correctly + ; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | not grep 'call.*strcat' + + declare sbyte* %strcpy(sbyte*,sbyte*) + declare int %puts(sbyte*) + %hello = constant [6 x sbyte] c"hello\00" + %null = constant [1 x sbyte] c"\00" + %null_hello = constant [7 x sbyte] c"\00hello\00" + + implementation ; Functions: + + int %main () { + %target = alloca [1024 x sbyte] + %arg1 = getelementptr [1024 x sbyte]* %target, int 0, int 0 + store sbyte 0, sbyte* %arg1 + %arg2 = getelementptr [6 x sbyte]* %hello, int 0, int 0 + %rslt1 = call sbyte* %strcpy(sbyte* %arg1, sbyte* %arg2) + %arg3 = getelementptr [1 x sbyte]* %null, int 0, int 0 + %rslt2 = call sbyte* %strcpy(sbyte* %rslt1, sbyte* %arg3) + %arg4 = getelementptr [7 x sbyte]* %null_hello, int 0, int 0 + %rslt3 = call sbyte* %strcpy(sbyte* %rslt2, sbyte* %arg4) + call int %puts(sbyte* %rslt3) + ret int 0 + } From reid at x10sys.com Fri Apr 29 02:19:14 2005 From: reid at x10sys.com (Reid Spencer) Date: Fri, 29 Apr 2005 02:19:14 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/SimplifyLibCalls/Puts.ll Message-ID: <200504290719.CAA26121@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/SimplifyLibCalls: Puts.ll added (r1.1) --- Log message: Add a test case for the puts libcall optimization. --- Diffs of the changes: (+16 -0) Puts.ll | 16 ++++++++++++++++ 1 files changed, 16 insertions(+) Index: llvm/test/Regression/Transforms/SimplifyLibCalls/Puts.ll diff -c /dev/null llvm/test/Regression/Transforms/SimplifyLibCalls/Puts.ll:1.1 *** /dev/null Fri Apr 29 02:19:10 2005 --- llvm/test/Regression/Transforms/SimplifyLibCalls/Puts.ll Fri Apr 29 02:19:00 2005 *************** *** 0 **** --- 1,16 ---- + ; Test that the StrCatOptimizer works correctly + ; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | not grep 'call.*fputc' + %struct._IO_FILE = type { int, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, %struct._IO_marker*, %struct._IO_FILE*, int, int, int, ushort, sbyte, [1 x sbyte], sbyte*, long, sbyte*, sbyte*, int, [52 x sbyte] } + %struct._IO_marker = type { %struct._IO_marker*, %struct._IO_FILE*, int } + %stdout = external global %struct._IO_FILE* ; <%struct._IO_FILE**> [#uses=1] + + implementation ; Functions: + + declare int %fputc(int, %struct._IO_FILE*) + + int %main() { + entry: + %tmp.1 = load %struct._IO_FILE** %stdout ; <%struct._IO_FILE*> [#uses=1] + %tmp.0 = call int %fputc( int 61, %struct._IO_FILE* %tmp.1 ) ; [#uses=0] + ret int 0 + } From reid at x10sys.com Fri Apr 29 03:36:47 2005 From: reid at x10sys.com (Reid Spencer) Date: Fri, 29 Apr 2005 03:36:47 -0500 Subject: [llvm-commits] CVS: llvm-test/MultiSource/Applications/siod/Makefile Message-ID: <200504290836.DAA13150@zion.cs.uiuc.edu> Changes in directory llvm-test/MultiSource/Applications/siod: Makefile updated: 1.7 -> 1.8 --- Log message: Enable this test. It requires libdl.so so we give it the -ldl flag. --- Diffs of the changes: (+1 -1) Makefile | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm-test/MultiSource/Applications/siod/Makefile diff -u llvm-test/MultiSource/Applications/siod/Makefile:1.7 llvm-test/MultiSource/Applications/siod/Makefile:1.8 --- llvm-test/MultiSource/Applications/siod/Makefile:1.7 Sat Jan 15 21:16:10 2005 +++ llvm-test/MultiSource/Applications/siod/Makefile Fri Apr 29 03:36:36 2005 @@ -1,7 +1,7 @@ LEVEL = ../../.. PROG = siod CPPFLAGS = -D__USE_MISC -D__USE_GNU -D__USE_SVID -D__USE_XOPEN_EXTENDED -D__USE_XOPEN -Dunix -LDFLAGS = -lm $(TOOLLINKOPTS) +LDFLAGS = -lm -ldl $(TOOLLINKOPTS) RUN_OPTIONS = -v1 $(PROJ_SRC_DIR)/test.scm From reid at x10sys.com Fri Apr 29 04:39:59 2005 From: reid at x10sys.com (Reid Spencer) Date: Fri, 29 Apr 2005 04:39:59 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Message-ID: <200504290939.EAA25158@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: SimplifyLibCalls.cpp updated: 1.22 -> 1.23 --- Log message: Implement the optimizations for "pow" and "fputs" library calls. --- Diffs of the changes: (+217 -17) SimplifyLibCalls.cpp | 234 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 217 insertions(+), 17 deletions(-) Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.22 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.23 --- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.22 Thu Apr 28 22:05:44 2005 +++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Fri Apr 29 04:39:47 2005 @@ -69,7 +69,8 @@ : func_name(fname) #ifndef NDEBUG , stat_name(std::string("simplify-libcalls:")+fname) - , occurrences(stat_name.c_str(),"Number of calls simplified") + , stat_desc(std::string("Number of ")+fname+"(...) calls simplified") + , occurrences(stat_name.c_str(),stat_desc.c_str()) #endif { // Register this call optimizer in the optlist (a hash_map) @@ -118,6 +119,7 @@ const char* func_name; ///< Name of the library call we optimize #ifndef NDEBUG std::string stat_name; ///< Holder for debug statistic name + std::string stat_desc; ///< Holder for debug statistic description Statistic<> occurrences; ///< debug statistic (-debug-only=simplify-libcalls) #endif }; @@ -203,10 +205,69 @@ } /// @brief Return the *current* module we're working on. - Module* getModule() { return M; } + Module* getModule() const { return M; } /// @brief Return the *current* target data for the module we're working on. - TargetData* getTargetData() { return TD; } + TargetData* getTargetData() const { return TD; } + + /// @brief Return the size_t type -- syntactic shortcut + const Type* getIntPtrType() const { return TD->getIntPtrType(); } + + /// @brief Return a Function* for the fputc libcall + Function* get_fputc() + { + if (!fputc_func) + { + std::vector args; + args.push_back(Type::IntTy); + const Type* FILE_type = M->getTypeByName("struct._IO_FILE"); + if (!FILE_type) + FILE_type = M->getTypeByName("struct._FILE"); + if (!FILE_type) + return 0; + args.push_back(PointerType::get(FILE_type)); + FunctionType* fputc_type = + FunctionType::get(Type::IntTy, args, false); + fputc_func = M->getOrInsertFunction("fputc",fputc_type); + } + return fputc_func; + } + + /// @brief Return a Function* for the fwrite libcall + Function* get_fwrite() + { + if (!fwrite_func) + { + std::vector args; + args.push_back(PointerType::get(Type::SByteTy)); + args.push_back(TD->getIntPtrType()); + args.push_back(TD->getIntPtrType()); + const Type* FILE_type = M->getTypeByName("struct._IO_FILE"); + if (!FILE_type) + FILE_type = M->getTypeByName("struct._FILE"); + if (!FILE_type) + return 0; + args.push_back(PointerType::get(FILE_type)); + FunctionType* fwrite_type = + FunctionType::get(TD->getIntPtrType(), args, false); + fwrite_func = M->getOrInsertFunction("fwrite",fwrite_type); + } + return fwrite_func; + } + + /// @brief Return a Function* for the sqrt libcall + Function* get_sqrt() + { + if (!sqrt_func) + { + std::vector args; + args.push_back(Type::DoubleTy); + FunctionType* sqrt_type = + FunctionType::get(Type::DoubleTy, args, false); + sqrt_func = M->getOrInsertFunction("sqrt",sqrt_type); + } + return sqrt_func; + } /// @brief Return a Function* for the strlen libcall Function* get_strlen() @@ -245,12 +306,18 @@ { M = &mod; TD = &getAnalysis(); + fputc_func = 0; + fwrite_func = 0; memcpy_func = 0; + sqrt_func = 0; strlen_func = 0; } private: + Function* fputc_func; ///< Cached fputc function + Function* fwrite_func; ///< Cached fwrite function Function* memcpy_func; ///< Cached llvm.memcpy function + Function* sqrt_func; ///< Cached sqrt function Function* strlen_func; ///< Cached strlen function Module* M; ///< Cached Module TargetData* TD; ///< Cached TargetData @@ -399,7 +466,6 @@ // terminator as well. len++; - // We need to find the end of the destination string. That's where the // memory is to be moved to. We just generate a call to strlen (further // optimized in another pass). Note that the SLC.get_strlen() call @@ -609,7 +675,7 @@ switch (len) { case 0: - // The memcpy is a no-op so just dump its call. + // memcpy(d,s,0,a) -> noop ci->eraseFromParent(); return true; case 1: castType = Type::SByteTy; break; @@ -643,6 +709,152 @@ } MemMoveOptimizer; +/// This LibCallOptimization will simplify calls to the "pow" library +/// function. It looks for cases where the result of pow is well known and +/// substitutes the appropriate value. +/// @brief Simplify the pow library function. +struct PowOptimization : public LibCallOptimization +{ +public: + /// @brief Default Constructor + PowOptimization() : LibCallOptimization("pow") {} + /// @brief Destructor + virtual ~PowOptimization() {} + + /// @brief Make sure that the "pow" function has the right prototype + virtual bool ValidateCalledFunction(const Function* f, SimplifyLibCalls& SLC) + { + // Just make sure this has 2 arguments + return (f->arg_size() == 2); + } + + /// @brief Perform the pow optimization. + virtual bool OptimizeCall(CallInst* ci, SimplifyLibCalls& SLC) + { + const Type *Ty = cast(ci->getOperand(0))->getReturnType(); + Value* base = ci->getOperand(1); + Value* expn = ci->getOperand(2); + if (ConstantFP *Op1 = dyn_cast(base)) { + double Op1V = Op1->getValue(); + if (Op1V == 1.0) + { + // pow(1.0,x) -> 1.0 + ci->replaceAllUsesWith(ConstantFP::get(Ty,1.0)); + ci->eraseFromParent(); + return true; + } + } + else if (ConstantFP* Op2 = dyn_cast(expn)) + { + double Op2V = Op2->getValue(); + if (Op2V == 0.0) + { + // pow(x,0.0) -> 1.0 + ci->replaceAllUsesWith(ConstantFP::get(Ty,1.0)); + ci->eraseFromParent(); + return true; + } + else if (Op2V == 0.5) + { + // pow(x,0.5) -> sqrt(x) + CallInst* sqrt_inst = new CallInst(SLC.get_sqrt(), base, + ci->getName()+".pow",ci); + ci->replaceAllUsesWith(sqrt_inst); + ci->eraseFromParent(); + return true; + } + else if (Op2V == 1.0) + { + // pow(x,1.0) -> x + ci->replaceAllUsesWith(base); + ci->eraseFromParent(); + return true; + } + else if (Op2V == -1.0) + { + // pow(x,-1.0) -> 1.0/x + BinaryOperator* div_inst= BinaryOperator::create(Instruction::Div, + ConstantFP::get(Ty,1.0), base, ci->getName()+".pow", ci); + ci->replaceAllUsesWith(div_inst); + ci->eraseFromParent(); + return true; + } + } + return false; // opt failed + } +} PowOptimizer; + +/// This LibCallOptimization will simplify calls to the "fputs" library +/// function. It looks for cases where the result of fputs is not used and the +/// operation can be reduced to something simpler. +/// @brief Simplify the pow library function. +struct PutsOptimization : public LibCallOptimization +{ +public: + /// @brief Default Constructor + PutsOptimization() : LibCallOptimization("fputs") {} + + /// @brief Destructor + virtual ~PutsOptimization() {} + + /// @brief Make sure that the "fputs" function has the right prototype + virtual bool ValidateCalledFunction(const Function* f, SimplifyLibCalls& SLC) + { + // Just make sure this has 2 arguments + return (f->arg_size() == 2); + } + + /// @brief Perform the fputs optimization. + virtual bool OptimizeCall(CallInst* ci, SimplifyLibCalls& SLC) + { + // If the result is used, none of these optimizations work + if (!ci->hasNUses(0)) + return false; + + // All the optimizations depend on the length of the first argument and the + // fact that it is a constant string array. Check that now + uint64_t len = 0; + if (!getConstantStringLength(ci->getOperand(1), len)) + return false; + + switch (len) + { + case 0: + // fputs("",F) -> noop + break; + case 1: + { + // fputs(s,F) -> fputc(s[0],F) (if s is constant and strlen(s) == 1) + Function* fputc_func = SLC.get_fputc(); + if (!fputc_func) + return false; + LoadInst* loadi = new LoadInst(ci->getOperand(1), + ci->getOperand(1)->getName()+".byte",ci); + CastInst* casti = new CastInst(loadi,Type::IntTy, + loadi->getName()+".int",ci); + new CallInst(fputc_func,casti,ci->getOperand(2),"",ci); + break; + } + default: + { + // fputs(s,F) -> fwrite(s,1,len,F) (if s is constant and strlen(s) > 1) + Function* fwrite_func = SLC.get_fwrite(); + if (!fwrite_func) + return false; + std::vector parms; + parms.push_back(ci->getOperand(1)); + parms.push_back(ConstantUInt::get(SLC.getIntPtrType(),len)); + parms.push_back(ConstantUInt::get(SLC.getIntPtrType(),1)); + parms.push_back(ci->getOperand(2)); + new CallInst(fwrite_func,parms,"",ci); + break; + } + } + ci->eraseFromParent(); + return true; // success + } +} PutsOptimizer; + /// A function to compute the length of a null-terminated constant array of /// integers. This function can't rely on the size of the constant array /// because there could be a null terminator in the middle of the array. @@ -755,7 +967,6 @@ // * cos(-x) -> cos(x) // // exp, expf, expl: -// * exp(int) -> contant' // * exp(log(x)) -> x // // ffs, ffsl, ffsll: @@ -768,11 +979,6 @@ // (only if the fprintf result is not used) // * fprintf(file,"%c",chr) -> fputc(chr,file) // -// fputs: (only if the result is not used) -// * fputs("",F) -> noop -// * fputs(s,F) -> fputc(s[0],F) (if s is constant and strlen(s) == 1) -// * fputs(s,F) -> fwrite(s, 1, len, F) (if s is constant and strlen(s) > 1) -// // isascii: // * isascii(c) -> ((c & ~0x7f) == 0) // @@ -798,9 +1004,6 @@ // (if all arguments are constant and strlen(x) <= l and strlen(y) <= l) // * memcpy(x,y,1) -> *x - *y // -// memcpy: -// * memcpy(d,s,0,a) -> d -// // memmove: // * memmove(d,s,l,a) -> memcpy(d,s,l,a) // (if s is a global constant array) @@ -811,9 +1014,6 @@ // (for n=1,2,4,8) // // pow, powf, powl: -// * pow(x,-1.0) -> 1.0/x -// * pow(x,0.5) -> sqrt(x) -// * pow(cst1,cst2) -> const1**const2 // * pow(exp(x),y) -> exp(x*y) // * pow(sqrt(x),y) -> pow(x,y*0.5) // * pow(pow(x,y),z)-> pow(x,y*z) From reid at x10sys.com Fri Apr 29 05:10:28 2005 From: reid at x10sys.com (Reid Spencer) Date: Fri, 29 Apr 2005 05:10:28 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/SimplifyLibCalls/Puts.ll Message-ID: <200504291010.FAA05809@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/SimplifyLibCalls: Puts.ll updated: 1.1 -> 1.2 --- Log message: Actually make this pass test something related to fputs. --- Diffs of the changes: (+16 -6) Puts.ll | 22 ++++++++++++++++------ 1 files changed, 16 insertions(+), 6 deletions(-) Index: llvm/test/Regression/Transforms/SimplifyLibCalls/Puts.ll diff -u llvm/test/Regression/Transforms/SimplifyLibCalls/Puts.ll:1.1 llvm/test/Regression/Transforms/SimplifyLibCalls/Puts.ll:1.2 --- llvm/test/Regression/Transforms/SimplifyLibCalls/Puts.ll:1.1 Fri Apr 29 02:19:00 2005 +++ llvm/test/Regression/Transforms/SimplifyLibCalls/Puts.ll Fri Apr 29 05:10:17 2005 @@ -1,16 +1,26 @@ ; Test that the StrCatOptimizer works correctly -; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | not grep 'call.*fputc' +; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | not grep 'call.*fputs' +; %struct._IO_FILE = type { int, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, %struct._IO_marker*, %struct._IO_FILE*, int, int, int, ushort, sbyte, [1 x sbyte], sbyte*, long, sbyte*, sbyte*, int, [52 x sbyte] } %struct._IO_marker = type { %struct._IO_marker*, %struct._IO_FILE*, int } %stdout = external global %struct._IO_FILE* ; <%struct._IO_FILE**> [#uses=1] -implementation ; Functions: +declare int %fputs(sbyte*, %struct._IO_FILE*) + +%empty = constant [1 x sbyte] c"\00" +%len1 = constant [2 x sbyte] c"A\00" +%long = constant [7 x sbyte] c"hello\0A\00" -declare int %fputc(int, %struct._IO_FILE*) +implementation ; Functions: int %main() { entry: - %tmp.1 = load %struct._IO_FILE** %stdout ; <%struct._IO_FILE*> [#uses=1] - %tmp.0 = call int %fputc( int 61, %struct._IO_FILE* %tmp.1 ) ; [#uses=0] - ret int 0 + %out = load %struct._IO_FILE** %stdout + %s1 = getelementptr [1 x sbyte]* %empty, int 0, int 0 + %s2 = getelementptr [2 x sbyte]* %len1, int 0, int 0 + %s3 = getelementptr [7 x sbyte]* %long, int 0, int 0 + %a = call int %fputs( sbyte* %s1, %struct._IO_FILE* %out ) + %b = call int %fputs( sbyte* %s2, %struct._IO_FILE* %out ) + %c = call int %fputs( sbyte* %s3, %struct._IO_FILE* %out ) + ret int 0 } From reid at x10sys.com Fri Apr 29 05:11:35 2005 From: reid at x10sys.com (Reid Spencer) Date: Fri, 29 Apr 2005 05:11:35 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/SimplifyLibCalls/Pow.ll Message-ID: <200504291011.FAA05918@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/SimplifyLibCalls: Pow.ll updated: 1.1 -> 1.2 --- Log message: Fix the success criteria for the test to make call instructions with "pow" not just any occurrence of "pow". --- Diffs of the changes: (+1 -1) Pow.ll | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/test/Regression/Transforms/SimplifyLibCalls/Pow.ll diff -u llvm/test/Regression/Transforms/SimplifyLibCalls/Pow.ll:1.1 llvm/test/Regression/Transforms/SimplifyLibCalls/Pow.ll:1.2 --- llvm/test/Regression/Transforms/SimplifyLibCalls/Pow.ll:1.1 Fri Apr 29 00:47:05 2005 +++ llvm/test/Regression/Transforms/SimplifyLibCalls/Pow.ll Fri Apr 29 05:11:23 2005 @@ -1,5 +1,5 @@ ; Test that the StrCatOptimizer works correctly -; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | not grep 'pow' +; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | not grep 'call.*pow' declare double %pow(double,double) %fpstorage = global double 5.0 From reid at x10sys.com Fri Apr 29 18:01:33 2005 From: reid at x10sys.com (Reid Spencer) Date: Fri, 29 Apr 2005 18:01:33 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/SimplifyLibCalls/Puts.ll Message-ID: <200504292301.SAA27321@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/SimplifyLibCalls: Puts.ll updated: 1.2 -> 1.3 --- Log message: Get the name of the pass right in the documentation. --- Diffs of the changes: (+1 -1) Puts.ll | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/test/Regression/Transforms/SimplifyLibCalls/Puts.ll diff -u llvm/test/Regression/Transforms/SimplifyLibCalls/Puts.ll:1.2 llvm/test/Regression/Transforms/SimplifyLibCalls/Puts.ll:1.3 --- llvm/test/Regression/Transforms/SimplifyLibCalls/Puts.ll:1.2 Fri Apr 29 05:10:17 2005 +++ llvm/test/Regression/Transforms/SimplifyLibCalls/Puts.ll Fri Apr 29 18:01:21 2005 @@ -1,4 +1,4 @@ -; Test that the StrCatOptimizer works correctly +; Test that the PutsCatOptimizer works correctly ; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | not grep 'call.*fputs' ; %struct._IO_FILE = type { int, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, sbyte*, %struct._IO_marker*, %struct._IO_FILE*, int, int, int, ushort, sbyte, [1 x sbyte], sbyte*, long, sbyte*, sbyte*, int, [52 x sbyte] } From reid at x10sys.com Fri Apr 29 18:02:26 2005 From: reid at x10sys.com (Reid Spencer) Date: Fri, 29 Apr 2005 18:02:26 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/SimplifyLibCalls/StrCpy.ll Message-ID: <200504292302.SAA27336@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/SimplifyLibCalls: StrCpy.ll updated: 1.1 -> 1.2 --- Log message: This is StrCpy, NOT StrCat! --- Diffs of the changes: (+2 -2) StrCpy.ll | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) Index: llvm/test/Regression/Transforms/SimplifyLibCalls/StrCpy.ll diff -u llvm/test/Regression/Transforms/SimplifyLibCalls/StrCpy.ll:1.1 llvm/test/Regression/Transforms/SimplifyLibCalls/StrCpy.ll:1.2 --- llvm/test/Regression/Transforms/SimplifyLibCalls/StrCpy.ll:1.1 Fri Apr 29 01:01:28 2005 +++ llvm/test/Regression/Transforms/SimplifyLibCalls/StrCpy.ll Fri Apr 29 18:02:15 2005 @@ -1,5 +1,5 @@ -; Test that the StrCatOptimizer works correctly -; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | not grep 'call.*strcat' +; Test that the StrCpyOptimizer works correctly +; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | not grep 'call.*strcpy' declare sbyte* %strcpy(sbyte*,sbyte*) declare int %puts(sbyte*) From reid at x10sys.com Fri Apr 29 19:52:15 2005 From: reid at x10sys.com (Reid Spencer) Date: Fri, 29 Apr 2005 19:52:15 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/SimplifyLibCalls/StrCmp.ll Message-ID: <200504300052.TAA27828@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/SimplifyLibCalls: StrCmp.ll added (r1.1) --- Log message: A new test case for the StrCmpOptimization in -simplify-libcalls. --- Diffs of the changes: (+26 -0) StrCmp.ll | 26 ++++++++++++++++++++++++++ 1 files changed, 26 insertions(+) Index: llvm/test/Regression/Transforms/SimplifyLibCalls/StrCmp.ll diff -c /dev/null llvm/test/Regression/Transforms/SimplifyLibCalls/StrCmp.ll:1.1 *** /dev/null Fri Apr 29 19:52:14 2005 --- llvm/test/Regression/Transforms/SimplifyLibCalls/StrCmp.ll Fri Apr 29 19:52:04 2005 *************** *** 0 **** --- 1,26 ---- + ; Test that the StrCmpOptimizer works correctly + ; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | not grep 'call.*strcmp' + + declare int %strcmp(sbyte*,sbyte*) + declare int %puts(sbyte*) + %hello = constant [6 x sbyte] c"hello\00" + %hell = constant [5 x sbyte] c"hell\00" + %null = constant [1 x sbyte] c"\00" + + implementation ; Functions: + + int %main () { + %hello_p = getelementptr [6 x sbyte]* %hello, int 0, int 0 + %hell_p = getelementptr [5 x sbyte]* %hell, int 0, int 0 + %null_p = getelementptr [1 x sbyte]* %null, int 0, int 0 + %temp1 = call int %strcmp(sbyte* %hello_p, sbyte* %hello_p) + %temp2 = call int %strcmp(sbyte* %null_p, sbyte* %null_p) + %temp3 = call int %strcmp(sbyte* %hello_p, sbyte* %null_p) + %temp4 = call int %strcmp(sbyte* %null_p, sbyte* %hello_p) + %temp5 = call int %strcmp(sbyte* %hell_p, sbyte* %hello_p) + %rslt1 = add int %temp1, %temp2 + %rslt2 = add int %rslt1, %temp3 + %rslt3 = add int %rslt2, %temp4 + %rslt4 = add int %rslt3, %temp5 + ret int %rslt4 + } From reid at x10sys.com Fri Apr 29 20:01:03 2005 From: reid at x10sys.com (Reid Spencer) Date: Fri, 29 Apr 2005 20:01:03 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/SimplifyLibCalls/ToAscii.ll Message-ID: <200504300101.UAA27908@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/SimplifyLibCalls: ToAscii.ll added (r1.1) --- Log message: A new test case for the ToAsciiOptimizer. --- Diffs of the changes: (+21 -0) ToAscii.ll | 21 +++++++++++++++++++++ 1 files changed, 21 insertions(+) Index: llvm/test/Regression/Transforms/SimplifyLibCalls/ToAscii.ll diff -c /dev/null llvm/test/Regression/Transforms/SimplifyLibCalls/ToAscii.ll:1.1 *** /dev/null Fri Apr 29 20:01:02 2005 --- llvm/test/Regression/Transforms/SimplifyLibCalls/ToAscii.ll Fri Apr 29 20:00:52 2005 *************** *** 0 **** --- 1,21 ---- + ; Test that the ToAsciiOptimizer works correctly + ; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | not grep 'call.*toascii' + + declare int %toascii(int) + + implementation ; Functions: + + int %main () { + %val1 = call int %toascii(int 1) + %val2 = call int %toascii(int 0) + %val3 = call int %toascii(int 127) + %val4 = call int %toascii(int 128) + %val5 = call int %toascii(int 255) + %val6 = call int %toascii(int 256) + %rslt1 = add int %val1, %val2 + %rslt2 = add int %val3, %val4 + %rslt3 = add int %val5, %val6 + %rslt4 = add int %rslt1, %rslt2 + %rslt5 = add int %rslt4, %rslt3 + ret int %rslt5 + } From reid at x10sys.com Fri Apr 29 22:06:47 2005 From: reid at x10sys.com (Reid Spencer) Date: Fri, 29 Apr 2005 22:06:47 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/SimplifyLibCalls/StrLen.ll Message-ID: <200504300306.WAA28249@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/SimplifyLibCalls: StrLen.ll updated: 1.2 -> 1.3 --- Log message: * Fix signed/unsigned usage problem * Rearrange for readability. --- Diffs of the changes: (+10 -9) StrLen.ll | 19 ++++++++++--------- 1 files changed, 10 insertions(+), 9 deletions(-) Index: llvm/test/Regression/Transforms/SimplifyLibCalls/StrLen.ll diff -u llvm/test/Regression/Transforms/SimplifyLibCalls/StrLen.ll:1.2 llvm/test/Regression/Transforms/SimplifyLibCalls/StrLen.ll:1.3 --- llvm/test/Regression/Transforms/SimplifyLibCalls/StrLen.ll:1.2 Tue Apr 26 14:04:46 2005 +++ llvm/test/Regression/Transforms/SimplifyLibCalls/StrLen.ll Fri Apr 29 22:06:36 2005 @@ -2,20 +2,21 @@ ; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | not grep 'call.*strlen' declare uint %strlen(sbyte*) -%hello = constant [6 x sbyte] c"hello\00" -%null = constant [1 x sbyte] c"\00" +%hello = constant [6 x sbyte] c"hello\00" +%null = constant [1 x sbyte] c"\00" %null_hello = constant [7 x sbyte] c"\00hello\00" implementation ; Functions: int %main () { - %hello_p = getelementptr [6 x sbyte]* %hello, int 0, int 0 - %hello_l = call uint %strlen(sbyte* %hello_p) - %null_p = getelementptr [1 x sbyte]* %null, int 0, int 0 - %null_l = call uint %strlen(sbyte* %null_p) + %hello_p = getelementptr [6 x sbyte]* %hello, int 0, int 0 + %null_p = getelementptr [1 x sbyte]* %null, int 0, int 0 %null_hello_p = getelementptr [7 x sbyte]* %null_hello, int 0, int 0 + %hello_l = call uint %strlen(sbyte* %hello_p) + %null_l = call uint %strlen(sbyte* %null_p) %null_hello_l = call uint %strlen(sbyte* %null_hello_p) - %sum1 = add int %hello_l, %null_l - %sum2 = add int %sum1, %null_hello_l - ret int %sum2 + %sum1 = add uint %hello_l, %null_l + %sum2 = add uint %sum1, %null_hello_l + %result = cast uint %sum2 to int + ret int %result } From reid at x10sys.com Fri Apr 29 22:18:05 2005 From: reid at x10sys.com (Reid Spencer) Date: Fri, 29 Apr 2005 22:18:05 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Message-ID: <200504300318.WAA28292@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: SimplifyLibCalls.cpp updated: 1.23 -> 1.24 --- Log message: * Don't depend on "guessing" what a FILE* is, just require that the actual type be obtained from a CallInst we're optimizing. * Make it possible for getConstantStringLength to return the ConstantArray that it extracts in case the content is needed by an Optimization. * Implement the strcmp optimization * Implement the toascii optimization This pass is now firing several to many times in the following MultiSource tests: Applications/Burg - 7 (strcat,strcpy) Applications/siod - 13 (strcat,strcpy,strlen) Applications/spiff - 120 (exit,fputs,strcat,strcpy,strlen) Applications/treecc - 66 (exit,fputs,strcat,strcpy) Applications/kimwitu++ - 34 (strcmp,strcpy,strlen) Applications/SPASS - 588 (exit,fputs,strcat,strcpy,strlen) --- Diffs of the changes: (+132 -21) SimplifyLibCalls.cpp | 153 ++++++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 132 insertions(+), 21 deletions(-) Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.23 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.24 --- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.23 Fri Apr 29 04:39:47 2005 +++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Fri Apr 29 22:17:54 2005 @@ -214,18 +214,13 @@ const Type* getIntPtrType() const { return TD->getIntPtrType(); } /// @brief Return a Function* for the fputc libcall - Function* get_fputc() + Function* get_fputc(const Type* FILEptr_type) { if (!fputc_func) { std::vector args; args.push_back(Type::IntTy); - const Type* FILE_type = M->getTypeByName("struct._IO_FILE"); - if (!FILE_type) - FILE_type = M->getTypeByName("struct._FILE"); - if (!FILE_type) - return 0; - args.push_back(PointerType::get(FILE_type)); + args.push_back(FILEptr_type); FunctionType* fputc_type = FunctionType::get(Type::IntTy, args, false); fputc_func = M->getOrInsertFunction("fputc",fputc_type); @@ -234,7 +229,7 @@ } /// @brief Return a Function* for the fwrite libcall - Function* get_fwrite() + Function* get_fwrite(const Type* FILEptr_type) { if (!fwrite_func) { @@ -242,12 +237,7 @@ args.push_back(PointerType::get(Type::SByteTy)); args.push_back(TD->getIntPtrType()); args.push_back(TD->getIntPtrType()); - const Type* FILE_type = M->getTypeByName("struct._IO_FILE"); - if (!FILE_type) - FILE_type = M->getTypeByName("struct._FILE"); - if (!FILE_type) - return 0; - args.push_back(PointerType::get(FILE_type)); + args.push_back(FILEptr_type); FunctionType* fwrite_type = FunctionType::get(TD->getIntPtrType(), args, false); fwrite_func = M->getOrInsertFunction("fwrite",fwrite_type); @@ -342,7 +332,7 @@ namespace { // Forward declare a utility function. -bool getConstantStringLength(Value* V, uint64_t& len ); +bool getConstantStringLength(Value* V, uint64_t& len, ConstantArray** A = 0 ); /// This LibCallOptimization will find instances of a call to "exit" that occurs /// within the "main" function and change it to a simple "ret" instruction with @@ -499,6 +489,93 @@ } } StrCatOptimizer; +/// This LibCallOptimization will simplify a call to the strcmp library +/// function. It optimizes out cases where one or both arguments are constant +/// and the result can be determined statically. +/// @brief Simplify the strcmp library function. +struct StrCmpOptimization : public LibCallOptimization +{ +public: + StrCmpOptimization() : LibCallOptimization("strcmp") {} + virtual ~StrCmpOptimization() {} + + /// @brief Make sure that the "strcpy" function has the right prototype + virtual bool ValidateCalledFunction(const Function* f, SimplifyLibCalls& SLC) + { + if (f->getReturnType() == Type::IntTy && f->arg_size() == 2) + return true; + return false; + } + + /// @brief Perform the strcpy optimization + virtual bool OptimizeCall(CallInst* ci, SimplifyLibCalls& SLC) + { + // First, check to see if src and destination are the same. If they are, + // then the optimization is to replace the CallInst with the destination + // because the call is a no-op. Note that this corresponds to the + // degenerate strcpy(X,X) case which should have "undefined" results + // according to the C specification. However, it occurs sometimes and + // we optimize it as a no-op. + Value* s1 = ci->getOperand(1); + Value* s2 = ci->getOperand(2); + if (s1 == s2) + { + // strcmp(x,x) -> 0 + ci->replaceAllUsesWith(ConstantInt::get(Type::IntTy,0)); + ci->eraseFromParent(); + return true; + } + + bool isstr_1 = false; + uint64_t len_1 = 0; + ConstantArray* A1; + if (getConstantStringLength(s1,len_1,&A1)) + { + isstr_1 = true; + if (len_1 == 0) + { + // strcmp("",x) -> *x + LoadInst* load = new LoadInst(s1,ci->getName()+".load",ci); + CastInst* cast = + new CastInst(load,Type::IntTy,ci->getName()+".int",ci); + ci->replaceAllUsesWith(cast); + ci->eraseFromParent(); + return true; + } + } + + bool isstr_2 = false; + uint64_t len_2 = 0; + ConstantArray* A2; + if (getConstantStringLength(s2,len_2,&A2)) + { + isstr_2 = true; + if (len_2 == 0) + { + // strcmp(x,"") -> *x + LoadInst* load = new LoadInst(s2,ci->getName()+".val",ci); + CastInst* cast = + new CastInst(load,Type::IntTy,ci->getName()+".int",ci); + ci->replaceAllUsesWith(cast); + ci->eraseFromParent(); + return true; + } + } + + if (isstr_1 && isstr_2) + { + // strcmp(x,y) -> cnst (if both x and y are constant strings) + std::string str1 = A1->getAsString(); + std::string str2 = A2->getAsString(); + int result = strcmp(str1.c_str(), str2.c_str()); + ci->replaceAllUsesWith(ConstantSInt::get(Type::IntTy,result)); + ci->eraseFromParent(); + return true; + } + return false; + } +} StrCmpOptimizer; + /// This LibCallOptimization will simplify a call to the strcpy library /// function. Two optimizations are possible: /// (1) If src and dest are the same and not volatile, just return dest @@ -825,7 +902,8 @@ case 1: { // fputs(s,F) -> fputc(s[0],F) (if s is constant and strlen(s) == 1) - Function* fputc_func = SLC.get_fputc(); + const Type* FILEptr_type = ci->getOperand(2)->getType(); + Function* fputc_func = SLC.get_fputc(FILEptr_type); if (!fputc_func) return false; LoadInst* loadi = new LoadInst(ci->getOperand(1), @@ -838,7 +916,8 @@ default: { // fputs(s,F) -> fwrite(s,1,len,F) (if s is constant and strlen(s) > 1) - Function* fwrite_func = SLC.get_fwrite(); + const Type* FILEptr_type = ci->getOperand(2)->getType(); + Function* fwrite_func = SLC.get_fwrite(FILEptr_type); if (!fwrite_func) return false; std::vector parms; @@ -855,6 +934,39 @@ } } PutsOptimizer; +/// This LibCallOptimization will simplify calls to the "toascii" library +/// function. It simply does the corresponding and operation to restrict the +/// range of values to the ASCII character set (0-127). +/// @brief Simplify the toascii library function. +struct ToAsciiOptimization : public LibCallOptimization +{ +public: + /// @brief Default Constructor + ToAsciiOptimization() : LibCallOptimization("toascii") {} + + /// @brief Destructor + virtual ~ToAsciiOptimization() {} + + /// @brief Make sure that the "fputs" function has the right prototype + virtual bool ValidateCalledFunction(const Function* f, SimplifyLibCalls& SLC) + { + // Just make sure this has 2 arguments + return (f->arg_size() == 1); + } + + /// @brief Perform the toascii optimization. + virtual bool OptimizeCall(CallInst* ci, SimplifyLibCalls& SLC) + { + // toascii(c) -> (c & 0x7f) + Value* chr = ci->getOperand(1); + BinaryOperator* and_inst = BinaryOperator::create(Instruction::And,chr, + ConstantInt::get(chr->getType(),0x7F),ci->getName()+".toascii",ci); + ci->replaceAllUsesWith(and_inst); + ci->eraseFromParent(); + return true; + } +} ToAsciiOptimizer; + /// A function to compute the length of a null-terminated constant array of /// integers. This function can't rely on the size of the constant array /// because there could be a null terminator in the middle of the array. @@ -865,7 +977,7 @@ /// of the null-terminated string. If false is returned, the conditions were /// not met and len is set to 0. /// @brief Get the length of a constant string (null-terminated array). -bool getConstantStringLength(Value* V, uint64_t& len ) +bool getConstantStringLength(Value* V, uint64_t& len, ConstantArray** CA ) { assert(V != 0 && "Invalid args to getConstantStringLength"); len = 0; // make sure we initialize this @@ -952,6 +1064,8 @@ // Subtract out the initial value from the length len -= start_idx; + if (CA) + *CA = A; return true; // success! } @@ -1091,9 +1205,6 @@ // tan, tanf, tanl: // * tan(atan(x)) -> x // -// toascii: -// * toascii(c) -> (c & 0x7f) -// // trunc, truncf, truncl: // * trunc(cnst) -> cnst' // From lattner at cs.uiuc.edu Fri Apr 29 22:43:57 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 29 Apr 2005 22:43:57 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Intrinsics.h Message-ID: <200504300343.j3U3huCq025470@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm: Intrinsics.h updated: 1.30 -> 1.31 --- Log message: Add llvm.sqrt intrinsic, patch contributed by Morten Ofstad --- Diffs of the changes: (+1 -0) Intrinsics.h | 1 + 1 files changed, 1 insertion(+) Index: llvm/include/llvm/Intrinsics.h diff -u llvm/include/llvm/Intrinsics.h:1.30 llvm/include/llvm/Intrinsics.h:1.31 --- llvm/include/llvm/Intrinsics.h:1.30 Thu Apr 21 15:11:51 2005 +++ llvm/include/llvm/Intrinsics.h Fri Apr 29 22:43:39 2005 @@ -63,6 +63,7 @@ // libm related functions. isunordered, // Return true if either argument is a NaN + sqrt, // Input/Output intrinsics. readport, From lattner at cs.uiuc.edu Fri Apr 29 22:44:06 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 29 Apr 2005 22:44:06 -0500 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Function.cpp Verifier.cpp Message-ID: <200504300344.j3U3i63k025484@apoc.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Function.cpp updated: 1.92 -> 1.93 Verifier.cpp updated: 1.130 -> 1.131 --- Log message: Add llvm.sqrt intrinsic, patch contributed by Morten Ofstad --- Diffs of the changes: (+11 -0) Function.cpp | 1 + Verifier.cpp | 10 ++++++++++ 2 files changed, 11 insertions(+) Index: llvm/lib/VMCore/Function.cpp diff -u llvm/lib/VMCore/Function.cpp:1.92 llvm/lib/VMCore/Function.cpp:1.93 --- llvm/lib/VMCore/Function.cpp:1.92 Thu Apr 21 18:46:51 2005 +++ llvm/lib/VMCore/Function.cpp Fri Apr 29 22:43:51 2005 @@ -245,6 +245,7 @@ if (getName() == "llvm.setjmp") return Intrinsic::setjmp; if (getName() == "llvm.sigsetjmp") return Intrinsic::sigsetjmp; if (getName() == "llvm.siglongjmp") return Intrinsic::siglongjmp; + if (getName() == "llvm.sqrt") return Intrinsic::sqrt; break; case 'v': if (getName() == "llvm.va_copy") return Intrinsic::vacopy; Index: llvm/lib/VMCore/Verifier.cpp diff -u llvm/lib/VMCore/Verifier.cpp:1.130 llvm/lib/VMCore/Verifier.cpp:1.131 --- llvm/lib/VMCore/Verifier.cpp:1.130 Thu Apr 21 18:46:51 2005 +++ llvm/lib/VMCore/Verifier.cpp Fri Apr 29 22:43:52 2005 @@ -723,6 +723,16 @@ NumArgs = 2; break; + case Intrinsic::sqrt: + Assert1(FT->getNumParams() == 1, + "Illegal # arguments for intrinsic function!", IF); + Assert1(FT->getParamType(0)->isFloatingPoint(), + "Argument is not a floating point type!", IF); + Assert1(FT->getReturnType() == FT->getParamType(0), + "Return type is not the same as argument type!", IF); + NumArgs = 1; + break; + case Intrinsic::setjmp: NumArgs = 1; break; case Intrinsic::longjmp: NumArgs = 2; break; case Intrinsic::sigsetjmp: NumArgs = 2; break; From lattner at cs.uiuc.edu Fri Apr 29 22:44:20 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 29 Apr 2005 22:44:20 -0500 Subject: [llvm-commits] CVS: llvm/lib/Analysis/BasicAliasAnalysis.cpp Message-ID: <200504300344.j3U3iKxN025495@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: BasicAliasAnalysis.cpp updated: 1.67 -> 1.68 --- Log message: Add llvm.sqrt intrinsic, patch contributed by Morten Ofstad --- Diffs of the changes: (+1 -1) BasicAliasAnalysis.cpp | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/lib/Analysis/BasicAliasAnalysis.cpp diff -u llvm/lib/Analysis/BasicAliasAnalysis.cpp:1.67 llvm/lib/Analysis/BasicAliasAnalysis.cpp:1.68 --- llvm/lib/Analysis/BasicAliasAnalysis.cpp:1.67 Thu Apr 28 16:52:31 2005 +++ llvm/lib/Analysis/BasicAliasAnalysis.cpp Fri Apr 29 22:44:07 2005 @@ -702,7 +702,7 @@ static const char *DoesntAccessMemoryTable[] = { // LLVM intrinsics: "llvm.frameaddress", "llvm.returnaddress", "llvm.readport", - "llvm.isunordered", + "llvm.isunordered", "llvm.sqrt", "abs", "labs", "llabs", "imaxabs", "fabs", "fabsf", "fabsl", "trunc", "truncf", "truncl", "ldexp", From lattner at cs.uiuc.edu Fri Apr 29 23:07:32 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 29 Apr 2005 23:07:32 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/CodeGen/Generic/intrinsics.ll Message-ID: <200504300407.j3U47WdM025665@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/CodeGen/Generic: intrinsics.ll added (r1.1) --- Log message: Add a test for llvm.sqrt --- Diffs of the changes: (+13 -0) intrinsics.ll | 13 +++++++++++++ 1 files changed, 13 insertions(+) Index: llvm/test/Regression/CodeGen/Generic/intrinsics.ll diff -c /dev/null llvm/test/Regression/CodeGen/Generic/intrinsics.ll:1.1 *** /dev/null Fri Apr 29 23:07:26 2005 --- llvm/test/Regression/CodeGen/Generic/intrinsics.ll Fri Apr 29 23:07:15 2005 *************** *** 0 **** --- 1,13 ---- + ; RUN: llvm-as < %s | llc + + + declare float %llvm.sqrt(float) + declare double %llvm.sqrt(double) + + + double %test_sqrt(float %F) { + %G = call float %llvm.sqrt(float %F) + %H = cast float %G to double + %I = call double %llvm.sqrt(double %H) + ret double %I + } From lattner at cs.uiuc.edu Fri Apr 29 23:08:04 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 29 Apr 2005 23:08:04 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IntrinsicLowering.cpp Message-ID: <200504300408.j3U484gi025679@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: IntrinsicLowering.cpp updated: 1.26 -> 1.27 --- Log message: Lower llvm.sqrt -> fsqrt/sqrt --- Diffs of the changes: (+17 -1) IntrinsicLowering.cpp | 18 +++++++++++++++++- 1 files changed, 17 insertions(+), 1 deletion(-) Index: llvm/lib/CodeGen/IntrinsicLowering.cpp diff -u llvm/lib/CodeGen/IntrinsicLowering.cpp:1.26 llvm/lib/CodeGen/IntrinsicLowering.cpp:1.27 --- llvm/lib/CodeGen/IntrinsicLowering.cpp:1.26 Thu Apr 21 17:33:33 2005 +++ llvm/lib/CodeGen/IntrinsicLowering.cpp Fri Apr 29 23:07:50 2005 @@ -110,8 +110,13 @@ case Intrinsic::isunordered: EnsureFunctionExists(M, "isunordered", I->arg_begin(), I->arg_end(), Type::BoolTy); break; + case Intrinsic::sqrt: + if(I->abegin()->getType() == Type::FloatTy) + EnsureFunctionExists(M, "sqrtf", I->arg_begin(), I->arg_end(), Type::FloatTy); + else + EnsureFunctionExists(M, "sqrt", I->arg_begin(), I->arg_end(), Type::DoubleTy); + break; } - } void DefaultIntrinsicLowering::LowerIntrinsicCall(CallInst *CI) { @@ -219,6 +224,17 @@ "isunordered", CI)); break; } + case Intrinsic::sqrt: { + static Function *sqrtFCache = 0; + static Function *sqrtfFCache = 0; + if(CI->getType() == Type::FloatTy) + ReplaceCallWith("sqrtf", CI, CI->op_begin()+1, CI->op_end(), + Type::FloatTy, sqrtfFCache); + else + ReplaceCallWith("sqrt", CI, CI->op_begin()+1, CI->op_end(), + Type::DoubleTy, sqrtFCache); + break; + } } assert(CI->use_empty() && From lattner at cs.uiuc.edu Fri Apr 29 23:09:53 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 29 Apr 2005 23:09:53 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Target/TargetOptions.h Message-ID: <200504300409.j3U49rrX025704@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Target: TargetOptions.h updated: 1.4 -> 1.5 --- Log message: Expose an option allowing unsafe math optimizations. Patch contributed by Morten Ofstad! --- Diffs of the changes: (+6 -0) TargetOptions.h | 6 ++++++ 1 files changed, 6 insertions(+) Index: llvm/include/llvm/Target/TargetOptions.h diff -u llvm/include/llvm/Target/TargetOptions.h:1.4 llvm/include/llvm/Target/TargetOptions.h:1.5 --- llvm/include/llvm/Target/TargetOptions.h:1.4 Thu Apr 21 15:53:44 2005 +++ llvm/include/llvm/Target/TargetOptions.h Fri Apr 29 23:09:37 2005 @@ -41,6 +41,12 @@ /// pattern ISel if available. extern int PatternISelTriState; + /// UnsafeFPMath - This flag is enabled when the + /// -enable-unsafe-fp-math flag is specified on the command line. When + /// this flag is off (the default), the code generator is not allowed to + /// produce results that are "less precise" than IEEE allows. This includes + /// use of X86 instructions like FSIN and FCOS instead of libcalls. + extern bool UnsafeFPMath; } // End llvm namespace #endif From lattner at cs.uiuc.edu Fri Apr 29 23:10:06 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 29 Apr 2005 23:10:06 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/TargetMachine.cpp Message-ID: <200504300410.j3U4A6pm025716@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target: TargetMachine.cpp updated: 1.37 -> 1.38 --- Log message: Expose an option allowing unsafe math optimizations. Patch contributed by Morten Ofstad! --- Diffs of the changes: (+6 -0) TargetMachine.cpp | 6 ++++++ 1 files changed, 6 insertions(+) Index: llvm/lib/Target/TargetMachine.cpp diff -u llvm/lib/Target/TargetMachine.cpp:1.37 llvm/lib/Target/TargetMachine.cpp:1.38 --- llvm/lib/Target/TargetMachine.cpp:1.37 Thu Apr 21 17:55:34 2005 +++ llvm/lib/Target/TargetMachine.cpp Fri Apr 29 23:09:52 2005 @@ -26,6 +26,7 @@ bool NoFramePointerElim; bool NoExcessFPPrecision; int PatternISelTriState; + bool UnsafeFPMath; }; namespace { cl::opt PrintCode("print-machineinstrs", @@ -46,6 +47,11 @@ cl::desc("sets the pattern ISel off(0), on(1), default(2)"), cl::location(PatternISelTriState), cl::init(2)); + cl::opt + EnableUnsafeFPMath("enable-unsafe-fp-math", + cl::desc("Enable optimizations that may decrease FP precision"), + cl::location(UnsafeFPMath), + cl::init(false)); }; //--------------------------------------------------------------------------- From lattner at cs.uiuc.edu Fri Apr 29 23:12:57 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 29 Apr 2005 23:12:57 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86ISelSimple.cpp Message-ID: <200504300412.j3U4Cvuq025833@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86ISelSimple.cpp updated: 1.315 -> 1.316 --- Log message: Add support for llvm.sqrt and sin/cos if unsafe math optimizations are enabled. --- Diffs of the changes: (+27 -0) X86ISelSimple.cpp | 27 +++++++++++++++++++++++++++ 1 files changed, 27 insertions(+) Index: llvm/lib/Target/X86/X86ISelSimple.cpp diff -u llvm/lib/Target/X86/X86ISelSimple.cpp:1.315 llvm/lib/Target/X86/X86ISelSimple.cpp:1.316 --- llvm/lib/Target/X86/X86ISelSimple.cpp:1.315 Thu Apr 28 16:48:42 2005 +++ llvm/lib/Target/X86/X86ISelSimple.cpp Fri Apr 29 23:12:40 2005 @@ -26,6 +26,7 @@ #include "llvm/CodeGen/SSARegMap.h" #include "llvm/Target/MRegisterInfo.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" #include "llvm/Support/GetElementPtrTypeIterator.h" #include "llvm/Support/InstVisitor.h" #include "llvm/ADT/Statistic.h" @@ -1744,6 +1745,25 @@ BuildMI(BB, X86::FABS, 1, DestReg).addReg(op1Reg); return; } + } else if (F->getName() == "sin" && UnsafeFPMath || F->getName() == "sinf") { + if (CI.getNumOperands() == 2 && // Basic sanity checks. + CI.getOperand(1)->getType()->isFloatingPoint() && + CI.getType() == CI.getOperand(1)->getType()) { + unsigned op1Reg = getReg(CI.getOperand(1)); + unsigned DestReg = getReg(CI); + BuildMI(BB, X86::FSIN, 1, DestReg).addReg(op1Reg); + return; + } + } + else if (F->getName() == "cos" && UnsafeFPMath || F->getName() == "cosf") { + if (CI.getNumOperands() == 2 && // Basic sanity checks. + CI.getOperand(1)->getType()->isFloatingPoint() && + CI.getType() == CI.getOperand(1)->getType()) { + unsigned op1Reg = getReg(CI.getOperand(1)); + unsigned DestReg = getReg(CI); + BuildMI(BB, X86::FCOS, 1, DestReg).addReg(op1Reg); + return; + } } // Emit a CALL instruction with PC-relative displacement. @@ -1780,6 +1800,7 @@ case Intrinsic::memcpy: case Intrinsic::memset: case Intrinsic::isunordered: + case Intrinsic::sqrt: case Intrinsic::readport: case Intrinsic::writeport: // We directly implement these intrinsics @@ -1860,6 +1881,12 @@ BuildMI(BB, X86::SETPr, 0, TmpReg2); return; + case Intrinsic::sqrt: + TmpReg1 = getReg(CI.getOperand(1)); + TmpReg2 = getReg(CI); + BuildMI(BB, X86::FSQRT, 1, TmpReg2).addReg(TmpReg1); + return; + case Intrinsic::memcpy: { assert(CI.getNumOperands() == 5 && "Illegal llvm.memcpy call!"); unsigned Align = 1; From lattner at cs.uiuc.edu Fri Apr 29 23:25:48 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 29 Apr 2005 23:25:48 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86ISelPattern.cpp Message-ID: <200504300425.j3U4PmOv027298@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86ISelPattern.cpp updated: 1.109 -> 1.110 --- Log message: Add support for FSIN/FCOS when unsafe math ops are enabled. Patch contributed by Morten Ofstad! --- Diffs of the changes: (+10 -0) X86ISelPattern.cpp | 10 ++++++++++ 1 files changed, 10 insertions(+) Index: llvm/lib/Target/X86/X86ISelPattern.cpp diff -u llvm/lib/Target/X86/X86ISelPattern.cpp:1.109 llvm/lib/Target/X86/X86ISelPattern.cpp:1.110 --- llvm/lib/Target/X86/X86ISelPattern.cpp:1.109 Thu Apr 28 17:07:18 2005 +++ llvm/lib/Target/X86/X86ISelPattern.cpp Fri Apr 29 23:25:35 2005 @@ -24,6 +24,7 @@ #include "llvm/CodeGen/SSARegMap.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetOptions.h" #include "llvm/Support/MathExtras.h" #include "llvm/ADT/Statistic.h" #include @@ -64,6 +65,11 @@ setOperationAction(ISD::SEXTLOAD , MVT::i1 , Expand); setOperationAction(ISD::SREM , MVT::f64 , Expand); + if (!UnsafeFPMath) { + setOperationAction(ISD::FSIN , MVT::f64 , Expand); + setOperationAction(ISD::FCOS , MVT::f64 , Expand); + } + // These should be promoted to a larger select which is supported. /**/ setOperationAction(ISD::SELECT , MVT::i1 , Promote); setOperationAction(ISD::SELECT , MVT::i8 , Promote); @@ -1831,6 +1837,8 @@ case ISD::FABS: case ISD::FNEG: + case ISD::FSIN: + case ISD::FCOS: case ISD::FSQRT: assert(N.getValueType()==MVT::f64 && "Illegal type for this operation"); Tmp1 = SelectExpr(Node->getOperand(0)); @@ -1839,6 +1847,8 @@ case ISD::FABS: BuildMI(BB, X86::FABS, 1, Result).addReg(Tmp1); break; case ISD::FNEG: BuildMI(BB, X86::FCHS, 1, Result).addReg(Tmp1); break; case ISD::FSQRT: BuildMI(BB, X86::FSQRT, 1, Result).addReg(Tmp1); break; + case ISD::FSIN: BuildMI(BB, X86::FSIN, 1, Result).addReg(Tmp1); break; + case ISD::FCOS: BuildMI(BB, X86::FCOS, 1, Result).addReg(Tmp1); break; } return Result; From lattner at cs.uiuc.edu Fri Apr 29 23:26:17 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 29 Apr 2005 23:26:17 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/Alpha/AlphaISelPattern.cpp Message-ID: <200504300426.j3U4QHOT027325@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/Alpha: AlphaISelPattern.cpp updated: 1.103 -> 1.104 --- Log message: This target doesn't support the FSIN/FCOS/FSQRT nodes yet --- Diffs of the changes: (+9 -1) AlphaISelPattern.cpp | 10 +++++++++- 1 files changed, 9 insertions(+), 1 deletion(-) Index: llvm/lib/Target/Alpha/AlphaISelPattern.cpp diff -u llvm/lib/Target/Alpha/AlphaISelPattern.cpp:1.103 llvm/lib/Target/Alpha/AlphaISelPattern.cpp:1.104 --- llvm/lib/Target/Alpha/AlphaISelPattern.cpp:1.103 Wed Apr 27 15:10:01 2005 +++ llvm/lib/Target/Alpha/AlphaISelPattern.cpp Fri Apr 29 23:26:03 2005 @@ -84,8 +84,16 @@ setOperationAction(ISD::MEMSET , MVT::Other, Expand); setOperationAction(ISD::MEMCPY , MVT::Other, Expand); + // We don't support sin/cos/sqrt + setOperationAction(ISD::FSIN , MVT::f64, Expand); + setOperationAction(ISD::FCOS , MVT::f64, Expand); + setOperationAction(ISD::FSQRT, MVT::f64, Expand); + setOperationAction(ISD::FSIN , MVT::f32, Expand); + setOperationAction(ISD::FCOS , MVT::f32, Expand); + setOperationAction(ISD::FSQRT, MVT::f32, Expand); + //Doesn't work yet - setOperationAction(ISD::SETCC , MVT::f32, Promote); + setOperationAction(ISD::SETCC, MVT::f32, Promote); computeRegisterProperties(); From lattner at cs.uiuc.edu Fri Apr 29 23:26:19 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 29 Apr 2005 23:26:19 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/IA64/IA64ISelPattern.cpp Message-ID: <200504300426.j3U4QJYI027331@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/IA64: IA64ISelPattern.cpp updated: 1.31 -> 1.32 --- Log message: This target doesn't support the FSIN/FCOS/FSQRT nodes yet --- Diffs of the changes: (+8 -0) IA64ISelPattern.cpp | 8 ++++++++ 1 files changed, 8 insertions(+) Index: llvm/lib/Target/IA64/IA64ISelPattern.cpp diff -u llvm/lib/Target/IA64/IA64ISelPattern.cpp:1.31 llvm/lib/Target/IA64/IA64ISelPattern.cpp:1.32 --- llvm/lib/Target/IA64/IA64ISelPattern.cpp:1.31 Wed Apr 27 15:10:01 2005 +++ llvm/lib/Target/IA64/IA64ISelPattern.cpp Fri Apr 29 23:26:05 2005 @@ -81,6 +81,14 @@ setOperationAction(ISD::MEMSET , MVT::Other, Expand); setOperationAction(ISD::MEMCPY , MVT::Other, Expand); + // We don't support sin/cos/sqrt + setOperationAction(ISD::FSIN , MVT::f64, Expand); + setOperationAction(ISD::FCOS , MVT::f64, Expand); + setOperationAction(ISD::FSQRT, MVT::f64, Expand); + setOperationAction(ISD::FSIN , MVT::f32, Expand); + setOperationAction(ISD::FCOS , MVT::f32, Expand); + setOperationAction(ISD::FSQRT, MVT::f32, Expand); + computeRegisterProperties(); addLegalFPImmediate(+0.0); From lattner at cs.uiuc.edu Fri Apr 29 23:26:20 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 29 Apr 2005 23:26:20 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp Message-ID: <200504300426.j3U4QKbI027337@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/PowerPC: PPC32ISelPattern.cpp updated: 1.79 -> 1.80 --- Log message: This target doesn't support the FSIN/FCOS/FSQRT nodes yet --- Diffs of the changes: (+8 -0) PPC32ISelPattern.cpp | 8 ++++++++ 1 files changed, 8 insertions(+) Index: llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp diff -u llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp:1.79 llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp:1.80 --- llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp:1.79 Wed Apr 27 15:10:01 2005 +++ llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp Fri Apr 29 23:26:06 2005 @@ -61,6 +61,14 @@ setOperationAction(ISD::SREM, MVT::i32, Expand); setOperationAction(ISD::UREM, MVT::i32, Expand); + // We don't support sin/cos/sqrt + setOperationAction(ISD::FSIN , MVT::f64, Expand); + setOperationAction(ISD::FCOS , MVT::f64, Expand); + setOperationAction(ISD::FSQRT, MVT::f64, Expand); + setOperationAction(ISD::FSIN , MVT::f32, Expand); + setOperationAction(ISD::FCOS , MVT::f32, Expand); + setOperationAction(ISD::FSQRT, MVT::f32, Expand); + setSetCCResultContents(ZeroOrOneSetCCResult); addLegalFPImmediate(+0.0); // Necessary for FSEL addLegalFPImmediate(-0.0); // From lattner at cs.uiuc.edu Fri Apr 29 23:27:10 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 29 Apr 2005 23:27:10 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/PowerPC/PPC64ISelPattern.cpp Message-ID: <200504300427.j3U4RAYe027460@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/PowerPC: PPC64ISelPattern.cpp updated: 1.11 -> 1.12 --- Log message: Doesn't support these nodes --- Diffs of the changes: (+8 -0) PPC64ISelPattern.cpp | 8 ++++++++ 1 files changed, 8 insertions(+) Index: llvm/lib/Target/PowerPC/PPC64ISelPattern.cpp diff -u llvm/lib/Target/PowerPC/PPC64ISelPattern.cpp:1.11 llvm/lib/Target/PowerPC/PPC64ISelPattern.cpp:1.12 --- llvm/lib/Target/PowerPC/PPC64ISelPattern.cpp:1.11 Wed Apr 27 15:10:01 2005 +++ llvm/lib/Target/PowerPC/PPC64ISelPattern.cpp Fri Apr 29 23:26:56 2005 @@ -52,6 +52,14 @@ setOperationAction(ISD::MEMSET, MVT::Other, Expand); setOperationAction(ISD::MEMCPY, MVT::Other, Expand); + // We don't support sin/cos/sqrt + setOperationAction(ISD::FSIN , MVT::f64, Expand); + setOperationAction(ISD::FCOS , MVT::f64, Expand); + setOperationAction(ISD::FSQRT, MVT::f64, Expand); + setOperationAction(ISD::FSIN , MVT::f32, Expand); + setOperationAction(ISD::FCOS , MVT::f32, Expand); + setOperationAction(ISD::FSQRT, MVT::f32, Expand); + // PPC 64 has i16 and i32 but no i8 (or i1) SEXTLOAD setOperationAction(ISD::SEXTLOAD, MVT::i1, Expand); setOperationAction(ISD::SEXTLOAD, MVT::i8, Expand); From lattner at cs.uiuc.edu Fri Apr 29 23:41:44 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 29 Apr 2005 23:41:44 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/CodeGen/Generic/intrinsics.ll Message-ID: <200504300441.j3U4fi1M028158@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/CodeGen/Generic: intrinsics.ll updated: 1.1 -> 1.2 --- Log message: add sin/cos tests --- Diffs of the changes: (+21 -3) intrinsics.ll | 24 +++++++++++++++++++++--- 1 files changed, 21 insertions(+), 3 deletions(-) Index: llvm/test/Regression/CodeGen/Generic/intrinsics.ll diff -u llvm/test/Regression/CodeGen/Generic/intrinsics.ll:1.1 llvm/test/Regression/CodeGen/Generic/intrinsics.ll:1.2 --- llvm/test/Regression/CodeGen/Generic/intrinsics.ll:1.1 Fri Apr 29 23:07:15 2005 +++ llvm/test/Regression/CodeGen/Generic/intrinsics.ll Fri Apr 29 23:41:27 2005 @@ -1,13 +1,31 @@ ; RUN: llvm-as < %s | llc - +;; SQRT declare float %llvm.sqrt(float) declare double %llvm.sqrt(double) - - double %test_sqrt(float %F) { %G = call float %llvm.sqrt(float %F) %H = cast float %G to double %I = call double %llvm.sqrt(double %H) ret double %I } + +; SIN +declare float %sinf(float) +declare double %sin(double) +double %test_sin(float %F) { + %G = call float %sinf(float %F) + %H = cast float %G to double + %I = call double %sin(double %H) + ret double %I +} + +; COS +declare float %cosf(float) +declare double %cos(double) +double %test_cos(float %F) { + %G = call float %cosf(float %F) + %H = cast float %G to double + %I = call double %cos(double %H) + ret double %I +} From lattner at cs.uiuc.edu Fri Apr 29 23:43:27 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 29 Apr 2005 23:43:27 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp SelectionDAGISel.cpp Message-ID: <200504300443.j3U4hRkC028177@apoc.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: LegalizeDAG.cpp updated: 1.92 -> 1.93 SelectionDAGISel.cpp updated: 1.44 -> 1.45 --- Log message: Codegen and legalize sin/cos/llvm.sqrt as FSIN/FCOS/FSQRT calls. This patch was contributed by Morten Ofstad, with some minor tweaks and bug fixes added by me. --- Diffs of the changes: (+53 -3) LegalizeDAG.cpp | 31 ++++++++++++++++++++++++++++--- SelectionDAGISel.cpp | 25 +++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 3 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.92 llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.93 --- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.92 Thu Apr 28 16:44:33 2005 +++ llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Fri Apr 29 23:43:14 2005 @@ -1003,12 +1003,15 @@ case TargetLowering::Custom: assert(0 && "Cannot promote/custom handle this yet!"); case TargetLowering::Expand: - if (Node->getOpcode() == ISD::FNEG) { + switch(Node->getOpcode()) { + case ISD::FNEG: { // Expand Y = FNEG(X) -> Y = SUB -0.0, X Tmp2 = DAG.getConstantFP(-0.0, Node->getValueType(0)); Result = LegalizeOp(DAG.getNode(ISD::SUB, Node->getValueType(0), Tmp2, Tmp1)); - } else if (Node->getOpcode() == ISD::FABS) { + break; + } + case ISD::FABS: { // Expand Y = FABS(X) -> Y = (X >u 0.0) ? X : fneg(X). MVT::ValueType VT = Node->getValueType(0); Tmp2 = DAG.getConstantFP(0.0, VT); @@ -1016,7 +1019,29 @@ Tmp3 = DAG.getNode(ISD::FNEG, VT, Tmp1); Result = DAG.getNode(ISD::SELECT, VT, Tmp2, Tmp1, Tmp3); Result = LegalizeOp(Result); - } else { + break; + } + case ISD::FSQRT: + case ISD::FSIN: + case ISD::FCOS: { + MVT::ValueType VT = Node->getValueType(0); + Type *T = VT == MVT::f32 ? Type::FloatTy : Type::DoubleTy; + const char *FnName = 0; + switch(Node->getOpcode()) { + case ISD::FSQRT: FnName = VT == MVT::f32 ? "sqrtf" : "sqrt"; break; + case ISD::FSIN: FnName = VT == MVT::f32 ? "sinf" : "sin"; break; + case ISD::FCOS: FnName = VT == MVT::f32 ? "cosf" : "cos"; break; + default: assert(0 && "Unreachable!"); + } + std::vector > Args; + Args.push_back(std::make_pair(Tmp1, T)); + std::pair CallResult = + TLI.LowerCallTo(DAG.getEntryNode(), T, false, + DAG.getExternalSymbol(FnName, VT), Args, DAG); + Result = LegalizeOp(CallResult.first); + break; + } + default: assert(0 && "Unreachable!"); } break; Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.44 llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.45 --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.44 Wed Apr 27 15:10:01 2005 +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Fri Apr 29 23:43:14 2005 @@ -656,6 +656,24 @@ return; } } + else if (F->getName() == "sin" || F->getName() == "sinf") { + if (I.getNumOperands() == 2 && // Basic sanity checks. + I.getOperand(1)->getType()->isFloatingPoint() && + I.getType() == I.getOperand(1)->getType()) { + SDOperand Tmp = getValue(I.getOperand(1)); + setValue(&I, DAG.getNode(ISD::FSIN, Tmp.getValueType(), Tmp)); + return; + } + } + else if (F->getName() == "cos" || F->getName() == "cosf") { + if (I.getNumOperands() == 2 && // Basic sanity checks. + I.getOperand(1)->getType()->isFloatingPoint() && + I.getType() == I.getOperand(1)->getType()) { + SDOperand Tmp = getValue(I.getOperand(1)); + setValue(&I, DAG.getNode(ISD::FCOS, Tmp.getValueType(), Tmp)); + return; + } + } break; case Intrinsic::vastart: visitVAStart(I); return; case Intrinsic::vaend: visitVAEnd(I); return; @@ -677,6 +695,13 @@ setValue(&I, DAG.getSetCC(ISD::SETUO, MVT::i1,getValue(I.getOperand(1)), getValue(I.getOperand(2)))); return; + + case Intrinsic::sqrt: + setValue(&I, DAG.getNode(ISD::FSQRT, + getValue(I.getOperand(1)).getValueType(), + getValue(I.getOperand(1)))); + return; + case Intrinsic::pcmarker: { SDOperand Num = getValue(I.getOperand(1)); DAG.setRoot(DAG.getNode(ISD::PCMARKER, MVT::Other, getRoot(), Num)); From lattner at cs.uiuc.edu Fri Apr 29 23:44:20 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 29 Apr 2005 23:44:20 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/Alpha/AlphaISelPattern.cpp Message-ID: <200504300444.j3U4iKoa028197@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/Alpha: AlphaISelPattern.cpp updated: 1.104 -> 1.105 --- Log message: Eliminate some random whitespace --- Diffs of the changes: (+1 -1) AlphaISelPattern.cpp | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/lib/Target/Alpha/AlphaISelPattern.cpp diff -u llvm/lib/Target/Alpha/AlphaISelPattern.cpp:1.104 llvm/lib/Target/Alpha/AlphaISelPattern.cpp:1.105 --- llvm/lib/Target/Alpha/AlphaISelPattern.cpp:1.104 Fri Apr 29 23:26:03 2005 +++ llvm/lib/Target/Alpha/AlphaISelPattern.cpp Fri Apr 29 23:44:07 2005 @@ -737,7 +737,7 @@ && (CN->isExactlyValue(+0.0) || CN->isExactlyValue(-0.0))) Tmp2 = Alpha::F31; else - Tmp2 = SelectExpr(N.getOperand(1)); + Tmp2 = SelectExpr(N.getOperand(1)); //Can only compare doubles, and dag won't promote for me if (SetCC->getOperand(0).getValueType() == MVT::f32) From reid at x10sys.com Sat Apr 30 01:45:58 2005 From: reid at x10sys.com (Reid Spencer) Date: Sat, 30 Apr 2005 01:45:58 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Message-ID: <200504300645.BAA28957@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: SimplifyLibCalls.cpp updated: 1.24 -> 1.25 --- Log message: Fix a comment that stated the wrong thing. --- Diffs of the changes: (+2 -5) SimplifyLibCalls.cpp | 7 ++----- 1 files changed, 2 insertions(+), 5 deletions(-) Index: llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp diff -u llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.24 llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.25 --- llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp:1.24 Fri Apr 29 22:17:54 2005 +++ llvm/lib/Transforms/IPO/SimplifyLibCalls.cpp Sat Apr 30 01:45:47 2005 @@ -511,11 +511,8 @@ virtual bool OptimizeCall(CallInst* ci, SimplifyLibCalls& SLC) { // First, check to see if src and destination are the same. If they are, - // then the optimization is to replace the CallInst with the destination - // because the call is a no-op. Note that this corresponds to the - // degenerate strcpy(X,X) case which should have "undefined" results - // according to the C specification. However, it occurs sometimes and - // we optimize it as a no-op. + // then the optimization is to replace the CallInst with a constant 0 + // because the call is a no-op. Value* s1 = ci->getOperand(1); Value* s2 = ci->getOperand(2); if (s1 == s2) From alkis at cs.uiuc.edu Sat Apr 30 02:13:42 2005 From: alkis at cs.uiuc.edu (Alkis Evlogimenos) Date: Sat, 30 Apr 2005 02:13:42 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IntrinsicLowering.cpp Message-ID: <200504300713.CAA29134@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: IntrinsicLowering.cpp updated: 1.27 -> 1.28 --- Log message: Do not use deprecated APIs --- Diffs of the changes: (+1 -1) IntrinsicLowering.cpp | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/lib/CodeGen/IntrinsicLowering.cpp diff -u llvm/lib/CodeGen/IntrinsicLowering.cpp:1.27 llvm/lib/CodeGen/IntrinsicLowering.cpp:1.28 --- llvm/lib/CodeGen/IntrinsicLowering.cpp:1.27 Fri Apr 29 23:07:50 2005 +++ llvm/lib/CodeGen/IntrinsicLowering.cpp Sat Apr 30 02:13:31 2005 @@ -111,7 +111,7 @@ EnsureFunctionExists(M, "isunordered", I->arg_begin(), I->arg_end(), Type::BoolTy); break; case Intrinsic::sqrt: - if(I->abegin()->getType() == Type::FloatTy) + if(I->arg_begin()->getType() == Type::FloatTy) EnsureFunctionExists(M, "sqrtf", I->arg_begin(), I->arg_end(), Type::FloatTy); else EnsureFunctionExists(M, "sqrt", I->arg_begin(), I->arg_end(), Type::DoubleTy); From alenhar2 at cs.uiuc.edu Sat Apr 30 09:19:30 2005 From: alenhar2 at cs.uiuc.edu (Andrew Lenharth) Date: Sat, 30 Apr 2005 09:19:30 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/Alpha/AlphaISelPattern.cpp Message-ID: <200504301419.j3UEJUDN031946@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/Alpha: AlphaISelPattern.cpp updated: 1.105 -> 1.106 --- Log message: I was sure I had thought about this and there was a reason it should work. But it is entirely possible I am just crazy. --- Diffs of the changes: (+8 -7) AlphaISelPattern.cpp | 15 ++++++++------- 1 files changed, 8 insertions(+), 7 deletions(-) Index: llvm/lib/Target/Alpha/AlphaISelPattern.cpp diff -u llvm/lib/Target/Alpha/AlphaISelPattern.cpp:1.105 llvm/lib/Target/Alpha/AlphaISelPattern.cpp:1.106 --- llvm/lib/Target/Alpha/AlphaISelPattern.cpp:1.105 Fri Apr 29 23:44:07 2005 +++ llvm/lib/Target/Alpha/AlphaISelPattern.cpp Sat Apr 30 09:19:13 2005 @@ -1199,13 +1199,14 @@ } } - if (DestType == MVT::f64 || DestType == MVT::f32 || - ( - (opcode == ISD::LOAD || opcode == ISD::CopyFromReg || - opcode == ISD::EXTLOAD) && - (N.getValue(0).getValueType() == MVT::f32 || - N.getValue(0).getValueType() == MVT::f64) - ) + if ((DestType == MVT::f64 || DestType == MVT::f32 || + ( + (opcode == ISD::LOAD || opcode == ISD::CopyFromReg || + opcode == ISD::EXTLOAD) && + (N.getValue(0).getValueType() == MVT::f32 || + N.getValue(0).getValueType() == MVT::f64) + )) + && opcode != ISD::CALL ) return SelectExprFP(N, Result); From tbrethou at cs.uiuc.edu Sat Apr 30 18:08:15 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Sat, 30 Apr 2005 18:08:15 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/SparcV9/ModuloScheduling/DependenceAnalyzer.cpp MSchedGraph.cpp MSchedGraph.h ModuloScheduling.cpp ModuloScheduling.h Message-ID: <200504302308.j3UN8FPV032476@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/SparcV9/ModuloScheduling: DependenceAnalyzer.cpp updated: 1.5 -> 1.6 MSchedGraph.cpp updated: 1.19 -> 1.20 MSchedGraph.h updated: 1.12 -> 1.13 ModuloScheduling.cpp updated: 1.48 -> 1.49 ModuloScheduling.h updated: 1.29 -> 1.30 --- Log message: Fixed bug in searchPath function for finding nodes between two recurrences. Changed dependence analyzer to only use dep distances of 2 or less. This is experimental. Changed MSchedGraph to be able to represent more then one BB (first steps). --- Diffs of the changes: (+214 -182) DependenceAnalyzer.cpp | 4 MSchedGraph.cpp | 323 +++++++++++++++++++++++++------------------------ MSchedGraph.h | 4 ModuloScheduling.cpp | 62 ++++++--- ModuloScheduling.h | 3 5 files changed, 214 insertions(+), 182 deletions(-) Index: llvm/lib/Target/SparcV9/ModuloScheduling/DependenceAnalyzer.cpp diff -u llvm/lib/Target/SparcV9/ModuloScheduling/DependenceAnalyzer.cpp:1.5 llvm/lib/Target/SparcV9/ModuloScheduling/DependenceAnalyzer.cpp:1.6 --- llvm/lib/Target/SparcV9/ModuloScheduling/DependenceAnalyzer.cpp:1.5 Fri Apr 22 01:32:48 2005 +++ llvm/lib/Target/SparcV9/ModuloScheduling/DependenceAnalyzer.cpp Sat Apr 30 18:07:58 2005 @@ -218,7 +218,9 @@ //Find constant index difference int diff = A1->getValue()->getRawValue() - A2->getValue()->getRawValue(); std::cerr << diff << "\n"; - + if(diff > 5) + diff = 2; + if(diff > 0) createDep(deps, valLoad, val2Load, srcBeforeDest, diff); Index: llvm/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.cpp diff -u llvm/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.cpp:1.19 llvm/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.cpp:1.20 --- llvm/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.cpp:1.19 Fri Apr 22 01:32:48 2005 +++ llvm/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.cpp Sat Apr 30 18:07:58 2005 @@ -153,13 +153,13 @@ std::map &ignoreInstrs, DependenceAnalyzer &DA, std::map &machineTollvm) - : BB(bb), Target(targ) { + : Target(targ) { //Make sure BB is not null, - assert(BB != NULL && "Basic Block is null"); - - //DEBUG(std::cerr << "Constructing graph for " << bb << "\n"); + assert(bb != NULL && "Basic Block is null"); + BBs.push_back(bb); + //Create nodes and edges for this BB buildNodesAndEdges(ignoreInstrs, DA, machineTollvm); @@ -170,7 +170,9 @@ //Copies the graph and keeps a map from old to new nodes MSchedGraph::MSchedGraph(const MSchedGraph &G, std::map &newNodes) - : BB(G.BB), Target(G.Target) { + : Target(G.Target) { + + BBs = G.BBs; std::map oldToNew; //Copy all nodes @@ -336,179 +338,184 @@ std::vector phiInstrs; unsigned index = 0; - //Loop over instructions in MBB and add nodes and edges - for (MachineBasicBlock::const_iterator MI = BB->begin(), e = BB->end(); - MI != e; ++MI) { - - //Ignore indvar instructions - if(ignoreInstrs.count(MI)) { - ++index; - continue; - } - - //Get each instruction of machine basic block, get the delay - //using the op code, create a new node for it, and add to the - //graph. - - MachineOpCode opCode = MI->getOpcode(); - int delay; + for(std::vector::iterator B = BBs.begin(), + BE = BBs.end(); B != BE; ++B) { + + const MachineBasicBlock *BB = *B; + //Loop over instructions in MBB and add nodes and edges + for (MachineBasicBlock::const_iterator MI = BB->begin(), e = BB->end(); + MI != e; ++MI) { + + //Ignore indvar instructions + if(ignoreInstrs.count(MI)) { + ++index; + continue; + } + + //Get each instruction of machine basic block, get the delay + //using the op code, create a new node for it, and add to the + //graph. + + MachineOpCode opCode = MI->getOpcode(); + int delay; + #if 0 // FIXME: LOOK INTO THIS - //Check if subsequent instructions can be issued before - //the result is ready, if so use min delay. - if(MTI->hasResultInterlock(MIopCode)) - delay = MTI->minLatency(MIopCode); - else + //Check if subsequent instructions can be issued before + //the result is ready, if so use min delay. + if(MTI->hasResultInterlock(MIopCode)) + delay = MTI->minLatency(MIopCode); + else #endif - //Get delay - delay = MTI->maxLatency(opCode); - - //Create new node for this machine instruction and add to the graph. - //Create only if not a nop - if(MTI->isNop(opCode)) - continue; - - //Sparc BE does not use PHI opcode, so assert on this case - assert(opCode != TargetInstrInfo::PHI && "Did not expect PHI opcode"); - - bool isBranch = false; - - //We want to flag the branch node to treat it special - if(MTI->isBranch(opCode)) - isBranch = true; - - //Node is created and added to the graph automatically - MSchedGraphNode *node = new MSchedGraphNode(MI, this, index, delay, - isBranch); - - DEBUG(std::cerr << "Created Node: " << *node << "\n"); - - //Check OpCode to keep track of memory operations to add memory - //dependencies later. - if(MTI->isLoad(opCode) || MTI->isStore(opCode)) - memInstructions.push_back(node); - - //Loop over all operands, and put them into the register number to - //graph node map for determining dependencies - //If an operands is a use/def, we have an anti dependence to itself - for(unsigned i=0; i < MI->getNumOperands(); ++i) { - //Get Operand - const MachineOperand &mOp = MI->getOperand(i); - - //Check if it has an allocated register - if(mOp.hasAllocatedReg()) { - int regNum = mOp.getReg(); - - if(regNum != SparcV9::g0) { - //Put into our map - regNumtoNodeMap[regNum].push_back(std::make_pair(i, node)); - } + //Get delay + delay = MTI->maxLatency(opCode); + + //Create new node for this machine instruction and add to the graph. + //Create only if not a nop + if(MTI->isNop(opCode)) continue; - } - - - //Add virtual registers dependencies - //Check if any exist in the value map already and create dependencies - //between them. - if(mOp.getType() == MachineOperand::MO_VirtualRegister - || mOp.getType() == MachineOperand::MO_CCRegister) { - - //Make sure virtual register value is not null - assert((mOp.getVRegValue() != NULL) && "Null value is defined"); - - //Check if this is a read operation in a phi node, if so DO NOT PROCESS - if(mOp.isUse() && (opCode == TargetInstrInfo::PHI)) { - DEBUG(std::cerr << "Read Operation in a PHI node\n"); + + //Sparc BE does not use PHI opcode, so assert on this case + assert(opCode != TargetInstrInfo::PHI && "Did not expect PHI opcode"); + + bool isBranch = false; + + //We want to flag the branch node to treat it special + if(MTI->isBranch(opCode)) + isBranch = true; + + //Node is created and added to the graph automatically + MSchedGraphNode *node = new MSchedGraphNode(MI, this, index, delay, + isBranch); + + DEBUG(std::cerr << "Created Node: " << *node << "\n"); + + //Check OpCode to keep track of memory operations to add memory + //dependencies later. + if(MTI->isLoad(opCode) || MTI->isStore(opCode)) + memInstructions.push_back(node); + + //Loop over all operands, and put them into the register number to + //graph node map for determining dependencies + //If an operands is a use/def, we have an anti dependence to itself + for(unsigned i=0; i < MI->getNumOperands(); ++i) { + //Get Operand + const MachineOperand &mOp = MI->getOperand(i); + + //Check if it has an allocated register + if(mOp.hasAllocatedReg()) { + int regNum = mOp.getReg(); + + if(regNum != SparcV9::g0) { + //Put into our map + regNumtoNodeMap[regNum].push_back(std::make_pair(i, node)); + } continue; } - - if (const Value* srcI = mOp.getVRegValue()) { - - //Find value in the map - std::map >::iterator V - = valuetoNodeMap.find(srcI); - //If there is something in the map already, add edges from - //those instructions - //to this one we are processing - if(V != valuetoNodeMap.end()) { - addValueEdges(V->second, node, mOp.isUse(), mOp.isDef(), phiInstrs); - //Add to value map - V->second.push_back(std::make_pair(i,node)); + //Add virtual registers dependencies + //Check if any exist in the value map already and create dependencies + //between them. + if(mOp.getType() == MachineOperand::MO_VirtualRegister + || mOp.getType() == MachineOperand::MO_CCRegister) { + + //Make sure virtual register value is not null + assert((mOp.getVRegValue() != NULL) && "Null value is defined"); + + //Check if this is a read operation in a phi node, if so DO NOT PROCESS + if(mOp.isUse() && (opCode == TargetInstrInfo::PHI)) { + DEBUG(std::cerr << "Read Operation in a PHI node\n"); + continue; + } + + if (const Value* srcI = mOp.getVRegValue()) { + + //Find value in the map + std::map >::iterator V + = valuetoNodeMap.find(srcI); + + //If there is something in the map already, add edges from + //those instructions + //to this one we are processing + if(V != valuetoNodeMap.end()) { + addValueEdges(V->second, node, mOp.isUse(), mOp.isDef(), phiInstrs); + + //Add to value map + V->second.push_back(std::make_pair(i,node)); + } + //Otherwise put it in the map + else + //Put into value map + valuetoNodeMap[mOp.getVRegValue()].push_back(std::make_pair(i, node)); } - //Otherwise put it in the map - else - //Put into value map - valuetoNodeMap[mOp.getVRegValue()].push_back(std::make_pair(i, node)); } } + ++index; } - ++index; - } - - //Loop over LLVM BB, examine phi instructions, and add them to our - //phiInstr list to process - const BasicBlock *llvm_bb = BB->getBasicBlock(); - for(BasicBlock::const_iterator I = llvm_bb->begin(), E = llvm_bb->end(); - I != E; ++I) { - if(const PHINode *PN = dyn_cast(I)) { - MachineCodeForInstruction & tempMvec = MachineCodeForInstruction::get(PN); - for (unsigned j = 0; j < tempMvec.size(); j++) { - if(!ignoreInstrs.count(tempMvec[j])) { - DEBUG(std::cerr << "Inserting phi instr into map: " << *tempMvec[j] << "\n"); - phiInstrs.push_back((MachineInstr*) tempMvec[j]); - } - } + + //Loop over LLVM BB, examine phi instructions, and add them to our + //phiInstr list to process + const BasicBlock *llvm_bb = BB->getBasicBlock(); + for(BasicBlock::const_iterator I = llvm_bb->begin(), E = llvm_bb->end(); + I != E; ++I) { + if(const PHINode *PN = dyn_cast(I)) { + MachineCodeForInstruction & tempMvec = MachineCodeForInstruction::get(PN); + for (unsigned j = 0; j < tempMvec.size(); j++) { + if(!ignoreInstrs.count(tempMvec[j])) { + DEBUG(std::cerr << "Inserting phi instr into map: " << *tempMvec[j] << "\n"); + phiInstrs.push_back((MachineInstr*) tempMvec[j]); + } + } + } + } - - } - - addMemEdges(memInstructions, DA, machineTollvm); - addMachRegEdges(regNumtoNodeMap); - - //Finally deal with PHI Nodes and Value* - for(std::vector::iterator I = phiInstrs.begin(), - E = phiInstrs.end(); I != E; ++I) { - - //Get Node for this instruction - std::map::iterator X; - X = find(*I); - - if(X == GraphMap.end()) - continue; - - MSchedGraphNode *node = X->second; - - DEBUG(std::cerr << "Adding ite diff edges for node: " << *node << "\n"); - - //Loop over operands for this instruction and add value edges - for(unsigned i=0; i < (*I)->getNumOperands(); ++i) { - //Get Operand - const MachineOperand &mOp = (*I)->getOperand(i); - if((mOp.getType() == MachineOperand::MO_VirtualRegister - || mOp.getType() == MachineOperand::MO_CCRegister) && mOp.isUse()) { - - //find the value in the map - if (const Value* srcI = mOp.getVRegValue()) { - - //Find value in the map - std::map >::iterator V + + addMemEdges(memInstructions, DA, machineTollvm); + addMachRegEdges(regNumtoNodeMap); + + //Finally deal with PHI Nodes and Value* + for(std::vector::iterator I = phiInstrs.begin(), + E = phiInstrs.end(); I != E; ++I) { + + //Get Node for this instruction + std::map::iterator X; + X = find(*I); + + if(X == GraphMap.end()) + continue; + + MSchedGraphNode *node = X->second; + + DEBUG(std::cerr << "Adding ite diff edges for node: " << *node << "\n"); + + //Loop over operands for this instruction and add value edges + for(unsigned i=0; i < (*I)->getNumOperands(); ++i) { + //Get Operand + const MachineOperand &mOp = (*I)->getOperand(i); + if((mOp.getType() == MachineOperand::MO_VirtualRegister + || mOp.getType() == MachineOperand::MO_CCRegister) && mOp.isUse()) { + + //find the value in the map + if (const Value* srcI = mOp.getVRegValue()) { + + //Find value in the map + std::map >::iterator V = valuetoNodeMap.find(srcI); - - //If there is something in the map already, add edges from - //those instructions - //to this one we are processing - if(V != valuetoNodeMap.end()) { - addValueEdges(V->second, node, mOp.isUse(), mOp.isDef(), - phiInstrs, 1); + + //If there is something in the map already, add edges from + //those instructions + //to this one we are processing + if(V != valuetoNodeMap.end()) { + addValueEdges(V->second, node, mOp.isUse(), mOp.isDef(), + phiInstrs, 1); + } } } } } } } - //Add dependencies for Value*s void MSchedGraph::addValueEdges(std::vector &NodesInMap, MSchedGraphNode *destNode, bool nodeIsUse, Index: llvm/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.h diff -u llvm/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.h:1.12 llvm/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.h:1.13 --- llvm/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.h:1.12 Fri Apr 22 01:32:48 2005 +++ llvm/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.h Sat Apr 30 18:07:58 2005 @@ -233,7 +233,7 @@ //Graph class to represent dependence graph class MSchedGraph { - const MachineBasicBlock *BB; //Machine basic block + std::vector BBs; //Machine basic block const TargetMachine &Target; //Target Machine //Nodes @@ -283,7 +283,7 @@ //Get Target or original machine basic block const TargetMachine* getTarget() { return &Target; } - const MachineBasicBlock* getBB() { return BB; } + std::vector getBBs() { return BBs; } }; Index: llvm/lib/Target/SparcV9/ModuloScheduling/ModuloScheduling.cpp diff -u llvm/lib/Target/SparcV9/ModuloScheduling/ModuloScheduling.cpp:1.48 llvm/lib/Target/SparcV9/ModuloScheduling/ModuloScheduling.cpp:1.49 --- llvm/lib/Target/SparcV9/ModuloScheduling/ModuloScheduling.cpp:1.48 Fri Apr 22 01:32:48 2005 +++ llvm/lib/Target/SparcV9/ModuloScheduling/ModuloScheduling.cpp Sat Apr 30 18:07:58 2005 @@ -1218,7 +1218,8 @@ void ModuloSchedulingPass::searchPath(MSchedGraphNode *node, std::vector &path, - std::set &nodesToAdd) { + std::set &nodesToAdd, + std::set &new_reccurrence) { //Push node onto the path path.push_back(node); @@ -1227,23 +1228,32 @@ for(MSchedGraphNode::succ_iterator S = node->succ_begin(), SE = node->succ_end(); S != SE; ++S) { - //If this node exists in a recurrence already in the partial order, then add all - //nodes in the path to the set of nodes to add - //Check if its already in our partial order, if not add it to the final vector + //Check if we should ignore this edge first + if(ignoreEdge(node,*S)) + continue; + + //check if successor is in this recurrence, we will get to it eventually + if(new_reccurrence.count(*S)) + continue; + + //If this node exists in a recurrence already in the partial + //order, then add all nodes in the path to the set of nodes to add + //Check if its already in our partial order, if not add it to the + //final vector + bool found = false; for(std::vector >::iterator PO = partialOrder.begin(), PE = partialOrder.end(); PO != PE; ++PO) { - //Check if we should ignore this edge first - if(ignoreEdge(node,*S)) - continue; - if(PO->count(*S)) { - nodesToAdd.insert(*S); - } - //terminate - else - searchPath(*S, path, nodesToAdd); + found = true; + break; } + } + + if(!found) { + nodesToAdd.insert(*S); + searchPath(*S, path, nodesToAdd, new_reccurrence); + } } //Pop Node off the path @@ -1344,7 +1354,7 @@ //Add nodes that connect this recurrence to recurrences in the partial path for(std::set::iterator N = new_recurrence.begin(), NE = new_recurrence.end(); N != NE; ++N) - searchPath(*N, path, nodesToAdd); + searchPath(*N, path, nodesToAdd, new_recurrence); //Add nodes to this recurrence if they are not already in the partial order for(std::set::iterator N = nodesToAdd.begin(), NE = nodesToAdd.end(); @@ -1723,8 +1733,10 @@ E = FinalNodeOrder.end(); I != E; ++I) { //CalculateEarly and Late start - int EarlyStart = -1; - int LateStart = 99999; //Set to something higher then we would ever expect (FIXME) + bool initialLSVal = false; + bool initialESVal = false; + int EarlyStart = 0; + int LateStart = 0; bool hasSucc = false; bool hasPred = false; bool sched; @@ -1751,7 +1763,12 @@ int ES_Temp = nodesByCycle->first + (*schedNode)->getLatency() - diff * II; DEBUG(std::cerr << "Diff: " << diff << " Cycle: " << nodesByCycle->first << "\n"); DEBUG(std::cerr << "Temp EarlyStart: " << ES_Temp << " Prev EarlyStart: " << EarlyStart << "\n"); - EarlyStart = std::max(EarlyStart, ES_Temp); + if(initialESVal) + EarlyStart = std::max(EarlyStart, ES_Temp); + else { + EarlyStart = ES_Temp; + initialESVal = true; + } hasPred = true; } if((*I)->isSuccessor(*schedNode)) { @@ -1759,7 +1776,12 @@ int LS_Temp = nodesByCycle->first - (*I)->getLatency() + diff * II; DEBUG(std::cerr << "Diff: " << diff << " Cycle: " << nodesByCycle->first << "\n"); DEBUG(std::cerr << "Temp LateStart: " << LS_Temp << " Prev LateStart: " << LateStart << "\n"); - LateStart = std::min(LateStart, LS_Temp); + if(initialLSVal) + LateStart = std::min(LateStart, LS_Temp); + else { + LateStart = LS_Temp; + initialLSVal = true; + } hasSucc = true; } } @@ -1772,7 +1794,7 @@ //Check if this node is a pred or succ to a branch, and restrict its placement //even though the branch is not in the schedule - int count = branches.size(); + /*int count = branches.size(); for(std::vector::iterator B = branches.begin(), BE = branches.end(); B != BE; ++B) { if((*I)->isPredecessor(*B)) { @@ -1794,7 +1816,7 @@ } count--; - } + }*/ //Check if the node has no pred or successors and set Early Start to its ASAP if(!hasSucc && !hasPred) Index: llvm/lib/Target/SparcV9/ModuloScheduling/ModuloScheduling.h diff -u llvm/lib/Target/SparcV9/ModuloScheduling/ModuloScheduling.h:1.29 llvm/lib/Target/SparcV9/ModuloScheduling/ModuloScheduling.h:1.30 --- llvm/lib/Target/SparcV9/ModuloScheduling/ModuloScheduling.h:1.29 Fri Apr 22 01:32:48 2005 +++ llvm/lib/Target/SparcV9/ModuloScheduling/ModuloScheduling.h Sat Apr 30 18:07:59 2005 @@ -113,7 +113,8 @@ void searchPath(MSchedGraphNode *node, std::vector &path, - std::set &nodesToAdd); + std::set &nodesToAdd, + std::set &new_reccurence); void pathToRecc(MSchedGraphNode *node, std::vector &path, From tbrethou at cs.uiuc.edu Sat Apr 30 20:26:09 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Sat, 30 Apr 2005 20:26:09 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.cpp MSchedGraph.h Message-ID: <200505010126.j411Q9S7032653@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/SparcV9/ModuloScheduling: MSchedGraph.cpp updated: 1.20 -> 1.21 MSchedGraph.h updated: 1.13 -> 1.14 --- Log message: Added extra constructor for superblocks. --- Diffs of the changes: (+28 -0) MSchedGraph.cpp | 22 ++++++++++++++++++++++ MSchedGraph.h | 6 ++++++ 2 files changed, 28 insertions(+) Index: llvm/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.cpp diff -u llvm/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.cpp:1.20 llvm/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.cpp:1.21 --- llvm/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.cpp:1.20 Sat Apr 30 18:07:58 2005 +++ llvm/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.cpp Sat Apr 30 20:25:53 2005 @@ -167,6 +167,28 @@ //addBranchEdges(); } +//Create a graph for a machine block. The ignoreInstrs map is so that +//we ignore instructions associated to the index variable since this +//is a special case in Modulo Scheduling. We only want to deal with +//the body of the loop. +MSchedGraph::MSchedGraph(std::vector &bbs, + const TargetMachine &targ, + std::map &ignoreInstrs, + DependenceAnalyzer &DA, + std::map &machineTollvm) + : BBs(bbs), Target(targ) { + + //Make sure there is at least one BB and it is not null, + assert(((bbs.size() >= 1) && bbs[1] != NULL) && "Basic Block is null"); + + //Create nodes and edges for this BB + buildNodesAndEdges(ignoreInstrs, DA, machineTollvm); + + //Experimental! + //addBranchEdges(); +} + + //Copies the graph and keeps a map from old to new nodes MSchedGraph::MSchedGraph(const MSchedGraph &G, std::map &newNodes) Index: llvm/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.h diff -u llvm/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.h:1.13 llvm/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.h:1.14 --- llvm/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.h:1.13 Sat Apr 30 18:07:58 2005 +++ llvm/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.h Sat Apr 30 20:25:53 2005 @@ -259,6 +259,12 @@ //Copy constructor with maps to link old nodes to new nodes MSchedGraph(const MSchedGraph &G, std::map &newNodes); + MSchedGraph(std::vector &bbs, + const TargetMachine &targ, + std::map &ignoreInstrs, + DependenceAnalyzer &DA, + std::map &machineTollvm); + //Print graph void print(std::ostream &os) const; From tbrethou at cs.uiuc.edu Sat Apr 30 20:27:59 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Sat, 30 Apr 2005 20:27:59 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/SparcV9/ModuloScheduling/ModuloSchedulingSuperBlock.cpp ModuloSchedulingSuperBlock.h Message-ID: <200505010127.j411RxEc032669@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Target/SparcV9/ModuloScheduling: ModuloSchedulingSuperBlock.cpp added (r1.1) ModuloSchedulingSuperBlock.h added (r1.1) --- Log message: SMS for superblocks. --- Diffs of the changes: (+379 -0) ModuloSchedulingSuperBlock.cpp | 282 +++++++++++++++++++++++++++++++++++++++++ ModuloSchedulingSuperBlock.h | 97 ++++++++++++++ 2 files changed, 379 insertions(+) Index: llvm/lib/Target/SparcV9/ModuloScheduling/ModuloSchedulingSuperBlock.cpp diff -c /dev/null llvm/lib/Target/SparcV9/ModuloScheduling/ModuloSchedulingSuperBlock.cpp:1.1 *** /dev/null Sat Apr 30 20:27:57 2005 --- llvm/lib/Target/SparcV9/ModuloScheduling/ModuloSchedulingSuperBlock.cpp Sat Apr 30 20:27:47 2005 *************** *** 0 **** --- 1,282 ---- + //===-- ModuloSchedulingSuperBlock.cpp - ModuloScheduling--------*- C++ -*-===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by the LLVM research group and is distributed under + // the University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + // + // This ModuloScheduling pass is based on the Swing Modulo Scheduling + // algorithm, but has been extended to support SuperBlocks (multiple + // basic block, single entry, multipl exit loops). + // + //===----------------------------------------------------------------------===// + + #define DEBUG_TYPE "ModuloSchedSB" + + #include "DependenceAnalyzer.h" + #include "ModuloSchedulingSuperBlock.h" + #include "llvm/ADT/Statistic.h" + #include "llvm/CodeGen/MachineFunction.h" + #include "llvm/CodeGen/Passes.h" + #include "llvm/Support/CFG.h" + #include "llvm/Support/Debug.h" + #include "llvm/Support/GraphWriter.h" + #include "llvm/Instructions.h" + #include "../MachineCodeForInstruction.h" + #include "../SparcV9RegisterInfo.h" + #include "../SparcV9Internals.h" + #include "../SparcV9TmpInstr.h" + #include + #include + + using namespace llvm; + /// Create ModuloSchedulingSBPass + /// + FunctionPass *llvm::createModuloSchedulingSBPass(TargetMachine & targ) { + DEBUG(std::cerr << "Created ModuloSchedulingSBPass\n"); + return new ModuloSchedulingSBPass(targ); + } + + //Graph Traits for printing out the dependence graph + template + static void WriteGraphToFile(std::ostream &O, const std::string &GraphName, + const GraphType >) { + std::string Filename = GraphName + ".dot"; + O << "Writing '" << Filename << "'..."; + std::ofstream F(Filename.c_str()); + + if (F.good()) + WriteGraph(F, GT); + else + O << " error opening file for writing!"; + O << "\n"; + }; + + namespace llvm { + Statistic<> NumLoops("moduloschedSB-numLoops", "Total Number of Loops"); + Statistic<> NumSB("moduloschedSB-numSuperBlocks", "Total Number of SuperBlocks"); + Statistic<> BBWithCalls("modulosched-BBCalls", "Basic Blocks rejected due to calls"); + Statistic<> BBWithCondMov("modulosched-loopCondMov", "Basic Blocks rejected due to conditional moves"); + bool ModuloSchedulingSBPass::runOnFunction(Function &F) { + bool Changed = false; + + //Get MachineFunction + MachineFunction &MF = MachineFunction::get(&F); + + //Get Loop Info & Dependence Anaysis info + LoopInfo &LI = getAnalysis(); + DependenceAnalyzer &DA = getAnalysis(); + + //Worklist of superblocks + std::vector > Worklist; + FindSuperBlocks(F, LI, Worklist); + + DEBUG(if(Worklist.size() == 0) std::cerr << "No superblocks in function to ModuloSchedule\n"); + + //Loop over worklist and ModuloSchedule each SuperBlock + for(std::vector >::iterator SB = Worklist.begin(), + SBE = Worklist.end(); SB != SBE; ++SB) { + + //Print out Superblock + DEBUG(std::cerr << "ModuloScheduling SB: \n"; + for(std::vector::const_iterator BI = SB->begin(), + BE = SB->end(); BI != BE; ++BI) { + (*BI)->print(std::cerr);}); + + if(!CreateDefMap(*SB)) { + defaultInst = 0; + defMap.clear(); + continue; + } + + MSchedGraph *MSG = new MSchedGraph(*SB, target, indVarInstrs[*SB], DA, + machineTollvm[*SB]); + + //Write Graph out to file + DEBUG(WriteGraphToFile(std::cerr, F.getName(), MSG)); + DEBUG(MSG->print(std::cerr)); + + } + return Changed; + + } + + void ModuloSchedulingSBPass::FindSuperBlocks(Function &F, LoopInfo &LI, + std::vector > &Worklist) { + + //Get MachineFunction + MachineFunction &MF = MachineFunction::get(&F); + + //Map of LLVM BB to machine BB + std::map bbMap; + + for (MachineFunction::iterator BI = MF.begin(); BI != MF.end(); ++BI) { + BasicBlock *llvmBB = (BasicBlock*) BI->getBasicBlock(); + assert(!bbMap.count(llvmBB) && "LLVM BB already in map!"); + bbMap[llvmBB] = &*BI; + } + + //Iterate over the loops, and find super blocks + for(LoopInfo::iterator LB = LI.begin(), LE = LI.end(); LB != LE; ++LB) { + Loop *L = *LB; + ++NumLoops; + + //If loop is not single entry, try the next one + if(!L->getLoopPreheader()) + continue; + + //Check size of this loop, we don't want SBB loops + if(L->getBlocks().size() == 1) + continue; + + //Check if this loop contains no sub loops + if(L->getSubLoops().size() == 0) { + + std::vector superBlock; + + //Get Loop Headers + BasicBlock *header = L->getHeader(); + + //Follow the header and make sure each BB only has one entry and is valid + BasicBlock *current = header; + assert(bbMap.count(current) && "LLVM BB must have corresponding Machine BB\n"); + MachineBasicBlock *currentMBB = bbMap[header]; + bool done = false; + bool success = true; + + while(!done) { + + if(MachineBBisValid(currentMBB)) { + + //Loop over successors of this BB, they should be in the loop block + //and be valid + BasicBlock *next = 0; + for(succ_iterator I = succ_begin(current), E = succ_end(current); + I != E; ++I) { + if(L->contains(*I)) { + if(!next) + next = *I; + else { + done = true; + success = false; + break; + } + } + } + if(success) { + superBlock.push_back(currentMBB); + if(next == header) + done = true; + else if(!next->getSinglePredecessor()) { + done = true; + success = false; + } + else { + //Check that the next BB only has one entry + current = next; + assert(bbMap.count(current) && "LLVM BB must have corresponding Machine BB"); + currentMBB = bbMap[current]; + } + } + } + else { + done = true; + success = false; + } + } + + if(success) { + ++NumSB; + Worklist.push_back(superBlock); + } + + } + + } + } + + /// This function checks if a Machine Basic Block is valid for modulo + /// scheduling. This means that it has no control flow (if/else or + /// calls) in the block. Currently ModuloScheduling only works on + /// single basic block loops. + bool ModuloSchedulingSBPass::MachineBBisValid(const MachineBasicBlock *BI) { + + //Check size of our basic block.. make sure we have more then just the terminator in it + if(BI->getBasicBlock()->size() == 1) + return false; + + //Get Target machine instruction info + const TargetInstrInfo *TMI = target.getInstrInfo(); + + //Check each instruction and look for calls, keep map to get index later + std::map indexMap; + + unsigned count = 0; + for(MachineBasicBlock::const_iterator I = BI->begin(), E = BI->end(); I != E; ++I) { + //Get opcode to check instruction type + MachineOpCode OC = I->getOpcode(); + + //Look for calls + if(TMI->isCall(OC)) { + ++BBWithCalls; + return false; + } + + //Look for conditional move + if(OC == V9::MOVRZr || OC == V9::MOVRZi || OC == V9::MOVRLEZr || OC == V9::MOVRLEZi + || OC == V9::MOVRLZr || OC == V9::MOVRLZi || OC == V9::MOVRNZr || OC == V9::MOVRNZi + || OC == V9::MOVRGZr || OC == V9::MOVRGZi || OC == V9::MOVRGEZr + || OC == V9::MOVRGEZi || OC == V9::MOVLEr || OC == V9::MOVLEi || OC == V9::MOVLEUr + || OC == V9::MOVLEUi || OC == V9::MOVFLEr || OC == V9::MOVFLEi + || OC == V9::MOVNEr || OC == V9::MOVNEi || OC == V9::MOVNEGr || OC == V9::MOVNEGi + || OC == V9::MOVFNEr || OC == V9::MOVFNEi) { + ++BBWithCondMov; + return false; + } + + indexMap[I] = count; + + if(TMI->isNop(OC)) + continue; + + ++count; + } + + return true; + } + } + + bool ModuloSchedulingSBPass::CreateDefMap(std::vector &SB) { + defaultInst = 0; + + for(std::vector::iterator BI = SB.begin(), + BE = SB.end(); BI != BE; ++BI) { + + for(MachineBasicBlock::const_iterator I = (*BI)->begin(), E = (*BI)->end(); I != E; ++I) { + for(unsigned opNum = 0; opNum < I->getNumOperands(); ++opNum) { + const MachineOperand &mOp = I->getOperand(opNum); + if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isDef()) { + + //assert if this is the second def we have seen + assert(!defMap.count(mOp.getVRegValue()) && "Def already in the map"); + defMap[mOp.getVRegValue()] = (MachineInstr*) &*I; + } + + //See if we can use this Value* as our defaultInst + if(!defaultInst && mOp.getType() == MachineOperand::MO_VirtualRegister) { + Value *V = mOp.getVRegValue(); + if(!isa(V) && !isa(V) && !isa(V) && !isa(V)) + defaultInst = (Instruction*) V; + } + } + } + } + + if(!defaultInst) + return false; + + return true; + + } Index: llvm/lib/Target/SparcV9/ModuloScheduling/ModuloSchedulingSuperBlock.h diff -c /dev/null llvm/lib/Target/SparcV9/ModuloScheduling/ModuloSchedulingSuperBlock.h:1.1 *** /dev/null Sat Apr 30 20:27:59 2005 --- llvm/lib/Target/SparcV9/ModuloScheduling/ModuloSchedulingSuperBlock.h Sat Apr 30 20:27:47 2005 *************** *** 0 **** --- 1,97 ---- + //===-- ModuloSchedulingSuperBlock.h -Swing Modulo Scheduling-----*- C++ -*-===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by the LLVM research group and is distributed under + // the University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + //Swing Modulo Scheduling done on Superblocks ( entry, multiple exit, + //multiple basic block loops). + // + //===----------------------------------------------------------------------===// + + #ifndef LLVM_MODULOSCHEDULINGSB_H + #define LLVM_MODULOSCHEDULINGSB_H + + #include "llvm/Analysis/LoopInfo.h" + #include "llvm/Function.h" + #include "llvm/Pass.h" + #include "llvm/CodeGen/MachineBasicBlock.h" + #include "MSSchedule.h" + #include "MSchedGraph.h" + + namespace llvm { + + //Struct to contain ModuloScheduling Specific Information for each node + struct MSNodeAttributes { + int ASAP; //Earliest time at which the opreation can be scheduled + int ALAP; //Latest time at which the operation can be scheduled. + int MOB; + int depth; + int height; + MSNodeAttributes(int asap=-1, int alap=-1, int mob=-1, + int d=-1, int h=-1) : ASAP(asap), ALAP(alap), + MOB(mob), depth(d), + height(h) {} + }; + + + typedef std::vector SuperBlock; + + class ModuloSchedulingSBPass : public FunctionPass { + const TargetMachine ⌖ + + //Map to hold Value* defs + std::map defMap; + + //Map to hold list of instructions associate to the induction var for each BB + std::map > indVarInstrs; + + //Map to hold machine to llvm instrs for each valid BB + std::map > machineTollvm; + + //LLVM Instruction we know we can add TmpInstructions to its MCFI + Instruction *defaultInst; + + //Map that holds node to node attribute information + std::map nodeToAttributesMap; + + //Map to hold all reccurrences + std::set > > recurrenceList; + + //Set of edges to ignore, stored as src node and index into vector of successors + std::set > edgesToIgnore; + + //Vector containing the partial order + std::vector > partialOrder; + + //Vector containing the final node order + std::vector FinalNodeOrder; + + //Schedule table, key is the cycle number and the vector is resource, node pairs + MSSchedule schedule; + + //Current initiation interval + int II; + + //Internal Functions + void FindSuperBlocks(Function &F, LoopInfo &LI, + std::vector > &Worklist); + bool MachineBBisValid(const MachineBasicBlock *B); + bool CreateDefMap(std::vector &SB); + + public: + ModuloSchedulingSBPass(TargetMachine &targ) : target(targ) {} + virtual bool runOnFunction(Function &F); + virtual const char* getPassName() const { return "ModuloScheduling-SuperBlock"; } + + + // getAnalysisUsage + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.addRequired(); + } + }; + } + #endif From lattner at cs.uiuc.edu Sat Apr 30 23:24:32 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat, 30 Apr 2005 23:24:32 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/InstCombine/load.ll Message-ID: <200505010424.j414OWuC001472@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/InstCombine: load.ll updated: 1.7 -> 1.8 --- Log message: add a new testcase --- Diffs of the changes: (+5 -0) load.ll | 5 +++++ 1 files changed, 5 insertions(+) Index: llvm/test/Regression/Transforms/InstCombine/load.ll diff -u llvm/test/Regression/Transforms/InstCombine/load.ll:1.7 llvm/test/Regression/Transforms/InstCombine/load.ll:1.8 --- llvm/test/Regression/Transforms/InstCombine/load.ll:1.7 Sun Sep 19 13:43:01 2004 +++ llvm/test/Regression/Transforms/InstCombine/load.ll Sat Apr 30 23:24:15 2005 @@ -54,3 +54,8 @@ ret int %tmp.3 } +int %test7(int %X) { + %V = getelementptr int* null, int %X + %R = load int* %V + ret int %R +} From lattner at cs.uiuc.edu Sat Apr 30 23:25:07 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat, 30 Apr 2005 23:25:07 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200505010425.j414P7Wj001486@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.331 -> 1.332 --- Log message: Check for volatile loads only once. Implement load.ll:test7 --- Diffs of the changes: (+35 -9) InstructionCombining.cpp | 44 +++++++++++++++++++++++++++++++++++--------- 1 files changed, 35 insertions(+), 9 deletions(-) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.331 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.332 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.331 Tue Apr 26 09:40:41 2005 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Sat Apr 30 23:24:53 2005 @@ -4750,13 +4750,34 @@ Instruction *InstCombiner::visitLoadInst(LoadInst &LI) { Value *Op = LI.getOperand(0); + // load (cast X) --> cast (load X) iff safe + if (CastInst *CI = dyn_cast(Op)) + if (Instruction *Res = InstCombineLoadCast(*this, LI)) + return Res; + + // None of the following transforms are legal for volatile loads. + if (LI.isVolatile()) return 0; + + if (GetElementPtrInst *GEPI = dyn_cast(Op)) + if (isa(GEPI->getOperand(0)) || + isa(GEPI->getOperand(0))) { + // Insert a new store to null instruction before the load to indicate + // that this code is not reachable. We do this instead of inserting + // an unreachable instruction directly because we cannot modify the + // CFG. + new StoreInst(UndefValue::get(LI.getType()), + Constant::getNullValue(Op->getType()), &LI); + return ReplaceInstUsesWith(LI, UndefValue::get(LI.getType())); + } + if (Constant *C = dyn_cast(Op)) { - if ((C->isNullValue() || isa(C)) && - !LI.isVolatile()) { // load null/undef -> undef + // load null/undef -> undef + if ((C->isNullValue() || isa(C))) { // Insert a new store to null instruction before the load to indicate that // this code is not reachable. We do this instead of inserting an // unreachable instruction directly because we cannot modify the CFG. - new StoreInst(UndefValue::get(LI.getType()), C, &LI); + new StoreInst(UndefValue::get(LI.getType()), + Constant::getNullValue(Op->getType()), &LI); return ReplaceInstUsesWith(LI, UndefValue::get(LI.getType())); } @@ -4772,18 +4793,23 @@ if (GV->isConstant() && !GV->isExternal()) if (Constant *V = GetGEPGlobalInitializer(GV->getInitializer(), CE)) return ReplaceInstUsesWith(LI, V); + if (CE->getOperand(0)->isNullValue()) { + // Insert a new store to null instruction before the load to indicate + // that this code is not reachable. We do this instead of inserting + // an unreachable instruction directly because we cannot modify the + // CFG. + new StoreInst(UndefValue::get(LI.getType()), + Constant::getNullValue(Op->getType()), &LI); + return ReplaceInstUsesWith(LI, UndefValue::get(LI.getType())); + } + } else if (CE->getOpcode() == Instruction::Cast) { if (Instruction *Res = InstCombineLoadCast(*this, LI)) return Res; } } - // load (cast X) --> cast (load X) iff safe - if (CastInst *CI = dyn_cast(Op)) - if (Instruction *Res = InstCombineLoadCast(*this, LI)) - return Res; - - if (!LI.isVolatile() && Op->hasOneUse()) { + if (Op->hasOneUse()) { // Change select and PHI nodes to select values instead of addresses: this // helps alias analysis out a lot, allows many others simplifications, and // exposes redundancy in the code. From lattner at cs.uiuc.edu Sat Apr 30 23:42:14 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat, 30 Apr 2005 23:42:14 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/InstCombine/getelementptr.ll Message-ID: <200505010442.j414gEVe001855@apoc.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/InstCombine: getelementptr.ll updated: 1.16 -> 1.17 --- Log message: new testcase --- Diffs of the changes: (+5 -0) getelementptr.ll | 5 +++++ 1 files changed, 5 insertions(+) Index: llvm/test/Regression/Transforms/InstCombine/getelementptr.ll diff -u llvm/test/Regression/Transforms/InstCombine/getelementptr.ll:1.16 llvm/test/Regression/Transforms/InstCombine/getelementptr.ll:1.17 --- llvm/test/Regression/Transforms/InstCombine/getelementptr.ll:1.16 Mon Apr 25 15:17:16 2005 +++ llvm/test/Regression/Transforms/InstCombine/getelementptr.ll Sat Apr 30 23:41:57 2005 @@ -66,3 +66,8 @@ ret bool %tmp.4 } +bool %test11({int,int} *%X) { + %P = getelementptr {int,int}* %X, int 0, uint 0 + %Q = seteq int* %P, null + ret bool %Q +} From lattner at cs.uiuc.edu Sat Apr 30 23:42:28 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sat, 30 Apr 2005 23:42:28 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200505010442.j414gSub001870@apoc.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.332 -> 1.333 --- Log message: Implement getelementptr.ll:test11 --- Diffs of the changes: (+16 -0) InstructionCombining.cpp | 16 ++++++++++++++++ 1 files changed, 16 insertions(+) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.332 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.333 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.332 Sat Apr 30 23:24:53 2005 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Sat Apr 30 23:42:15 2005 @@ -2879,6 +2879,22 @@ if (Constant *RHSC = dyn_cast(Op1)) { if (Instruction *LHSI = dyn_cast(Op0)) switch (LHSI->getOpcode()) { + case Instruction::GetElementPtr: + if (RHSC->isNullValue()) { + // Transform setcc GEP P, int 0, int 0, int 0, null -> setcc P, null + bool isAllZeros = true; + for (unsigned i = 1, e = LHSI->getNumOperands(); i != e; ++i) + if (!isa(LHSI->getOperand(i)) || + !cast(LHSI->getOperand(i))->isNullValue()) { + isAllZeros = false; + break; + } + if (isAllZeros) + return new SetCondInst(I.getOpcode(), LHSI->getOperand(0), + Constant::getNullValue(LHSI->getOperand(0)->getType())); + } + break; + case Instruction::PHI: if (Instruction *NV = FoldOpIntoPhi(I)) return NV; From tbrethou at cs.uiuc.edu Sun May 1 11:14:51 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Sun, 1 May 2005 11:14:51 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/CodeGen/Passes.h Message-ID: <200505011614.j41GEpO8008718@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/CodeGen: Passes.h updated: 1.19 -> 1.20 --- Log message: Adding ModuloSched SB. --- Diffs of the changes: (+3 -0) Passes.h | 3 +++ 1 files changed, 3 insertions(+) Index: llvm/include/llvm/CodeGen/Passes.h diff -u llvm/include/llvm/CodeGen/Passes.h:1.19 llvm/include/llvm/CodeGen/Passes.h:1.20 --- llvm/include/llvm/CodeGen/Passes.h:1.19 Thu Apr 21 15:38:00 2005 +++ llvm/include/llvm/CodeGen/Passes.h Sun May 1 11:14:34 2005 @@ -98,6 +98,9 @@ //createModuloSchedulingPass - Creates the Swing Modulo Scheduling Pass FunctionPass *createModuloSchedulingPass(TargetMachine & targ); + //createModuloSchedulingPass - Creates the Swing Modulo Scheduling Pass + FunctionPass *createModuloSchedulingSBPass(TargetMachine & targ); + } // End llvm namespace #endif From tbrethou at cs.uiuc.edu Sun May 1 11:22:58 2005 From: tbrethou at cs.uiuc.edu (Tanya Brethour) Date: Sun, 1 May 2005 11:22:58 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/LoopInfo.h Message-ID: <200505011622.j41GMwI5009801@apoc.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: LoopInfo.h updated: 1.45 -> 1.46 --- Log message: Add accessor method, --- Diffs of the changes: (+1 -0) LoopInfo.h | 1 + 1 files changed, 1 insertion(+) Index: llvm/include/llvm/Analysis/LoopInfo.h diff -u llvm/include/llvm/Analysis/LoopInfo.h:1.45 llvm/include/llvm/Analysis/LoopInfo.h:1.46 --- llvm/include/llvm/Analysis/LoopInfo.h:1.45 Thu Apr 21 15:16:32 2005 +++ llvm/include/llvm/Analysis/LoopInfo.h Sun May 1 11:22:41 2005 @@ -74,6 +74,7 @@ /// iterator/begin/end - Return the loops contained entirely within this loop. /// + const std::vector &getSubLoops() const { return SubLoops; } typedef std::vector::const_iterator iterator; iterator begin() const { return SubLoops.begin(); } iterator end() const { return SubLoops.end(); } From reid at x10sys.com Sun May 1 17:23:09 2005 From: reid at x10sys.com (Reid Spencer) Date: Sun, 1 May 2005 17:23:09 -0500 Subject: [llvm-commits] CVS: llvm/docs/LangRef.html Message-ID: <200505012223.RAA06852@zion.cs.uiuc.edu> Changes in directory llvm/docs: LangRef.html updated: 1.95 -> 1.96 --- Log message: Mention that arguments to functions must be first class types. --- Diffs of the changes: (+5 -4) LangRef.html | 9 +++++---- 1 files changed, 5 insertions(+), 4 deletions(-) Index: llvm/docs/LangRef.html diff -u llvm/docs/LangRef.html:1.95 llvm/docs/LangRef.html:1.96 --- llvm/docs/LangRef.html:1.95 Tue Apr 26 15:50:44 2005 +++ llvm/docs/LangRef.html Sun May 1 17:22:57 2005 @@ -2057,9 +2057,10 @@
  • 'function args': argument list whose types match the -function signature argument types. If the function signature -indicates the function accepts a variable number of arguments, the -extra arguments can be specified.

    + function signature argument types. All arguments must be of + first class type. If the function signature + indicates the function accepts a variable number of arguments, the extra + arguments can be specified.

  • Semantics:
    @@ -3055,7 +3056,7 @@ Chris Lattner
    The LLVM Compiler Infrastructure
    - Last modified: $Date: 2005/04/26 20:50:44 $ + Last modified: $Date: 2005/05/01 22:22:57 $ From duraid at octopus.com.au Sun May 1 22:02:16 2005 From: duraid at octopus.com.au (Duraid Madina) Date: Sun, 1 May 2005 22:02:16 -0500 Subject: [llvm-commits] CVS: llvm-www/testresults/index.html Message-ID: <200505020302.WAA08175@zion.cs.uiuc.edu> Changes in directory llvm-www/testresults: index.html updated: 1.34 -> 1.35 --- Log message: add new ia64 tester --- Diffs of the changes: (+3 -1) index.html | 4 +++- 1 files changed, 3 insertions(+), 1 deletion(-) Index: llvm-www/testresults/index.html diff -u llvm-www/testresults/index.html:1.34 llvm-www/testresults/index.html:1.35 --- llvm-www/testresults/index.html:1.34 Mon Mar 28 12:40:20 2005 +++ llvm-www/testresults/index.html Sun May 1 22:02:05 2005 @@ -33,9 +33,11 @@
  • Debian GNU/Linux unstable, dual Itanium2(tm) 1.5GHz -- debug build
  • + +
  • Debian GNU/Linux +unstable, dual Itanium 2 1.6GHz -- debug build
  • -

    PowerPC