From sabre at nondot.org Mon Jun 16 01:10:11 2008 From: sabre at nondot.org (Chris Lattner) Date: Mon, 16 Jun 2008 06:10:11 -0000 Subject: [llvm-commits] [llvm] r52299 - /llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Message-ID: <200806160610.m5G6ABYo020722@zion.cs.uiuc.edu> Author: lattner Date: Mon Jun 16 01:10:11 2008 New Revision: 52299 URL: http://llvm.org/viewvc/llvm-project?rev=52299&view=rev Log: Refactor basicaa's main alias function somethin' fierce. This fixes several minor bugs (such as returning noalias for comparisons between external weak functions an null) but is mostly a cleanup. Modified: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Modified: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp?rev=52299&r1=52298&r2=52299&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp (original) +++ llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Mon Jun 16 01:10:11 2008 @@ -143,7 +143,7 @@ /// a unique object or an argument, return it. This returns: /// Arguments, GlobalVariables, Functions, Allocas, Mallocs. static const Value *getUnderlyingObject(const Value *V) { - if (!isa(V->getType())) return 0; + if (!isa(V->getType())) return V; // If we are at some type of object, return it. GlobalValues and Allocations // have unique addresses. @@ -159,7 +159,7 @@ CE->getOpcode() == Instruction::GetElementPtr) return getUnderlyingObject(CE->getOperand(0)); } - return 0; + return V; } static const User *isGEP(const Value *V) { @@ -193,9 +193,9 @@ /// pointsToConstantMemory - Chase pointers until we find a (constant /// global) or not. bool BasicAliasAnalysis::pointsToConstantMemory(const Value *P) { - if (const Value *V = getUnderlyingObject(P)) - if (const GlobalVariable *GV = dyn_cast(V)) - return GV->isConstant(); + if (const GlobalVariable *GV = + dyn_cast(getUnderlyingObject(P))) + return GV->isConstant(); return false; } @@ -248,9 +248,19 @@ BasicAliasAnalysis::getModRefInfo(CallSite CS, Value *P, unsigned Size) { if (!isa(P)) { const Value *Object = getUnderlyingObject(P); + + // If this is a tail call and P points to a stack location, we know that + // the tail call cannot access or modify the local stack. + // We cannot exclude byval arguments here; these belong to the caller of + // the current function not to the current function, and a tail callee + // may reference them. + if (isa(Object)) + if (CallInst *CI = dyn_cast(CS.getInstruction())) + if (CI->isTailCall()) + return NoModRef; + // Allocations and byval arguments are "new" objects. - if (Object && - (isa(Object) || isa(Object))) { + if (isa(Object) || isa(Object)) { // Okay, the pointer is to a stack allocated (or effectively so, for // for noalias parameters) object. If the address of this object doesn't // escape from this function body to a callee, then we know that no @@ -263,23 +273,13 @@ for (CallSite::arg_iterator CI = CS.arg_begin(), CE = CS.arg_end(); CI != CE; ++CI) if (isa((*CI)->getType()) && - ( getUnderlyingObject(*CI) == P || - alias(cast(CI), ~0U, P, ~0U) != NoAlias) ) + (getUnderlyingObject(*CI) == P || + alias(cast(CI), ~0U, P, ~0U) != NoAlias)) passedAsArg = true; if (!passedAsArg) return NoModRef; } - - // If this is a tail call and P points to a stack location, we know that - // the tail call cannot access or modify the local stack. - // We cannot exclude byval arguments here; these belong to the caller of - // the current function not to the current function, and a tail callee - // may reference them. - if (isa(Object)) - if (CallInst *CI = dyn_cast(CS.getInstruction())) - if (CI->isTailCall()) - return NoModRef; } } @@ -287,6 +287,57 @@ return AliasAnalysis::getModRefInfo(CS, P, Size); } +/// isIdentifiedObject - Return true if this pointer refers to a distinct and +/// identifiable object. This returns true for: +/// Global Variables and Functions +/// Allocas and Mallocs +/// ByVal and NoAlias Arguments +/// +static bool isIdentifiedObject(const Value *V) { + if (isa(V) || isa(V)) + return true; + if (const Argument *A = dyn_cast(V)) + return A->hasNoAliasAttr() || A->hasByValAttr(); + return false; +} + +/// isKnownNonNull - Return true if we know that the specified value is never +/// null. +static bool isKnownNonNull(const Value *V) { + // Alloca never returns null, malloc might. + if (isa(V)) return true; + + // A byval argument is never null. + if (const Argument *A = dyn_cast(V)) + return A->hasByValAttr(); + + // Global values are not null unless extern weak. + if (const GlobalValue *GV = dyn_cast(V)) + return !GV->hasExternalWeakLinkage(); + return false; +} + +/// isObjectSmallerThan - Return true if we can prove that the object specified +/// by V is smaller than Size. +static bool isObjectSmallerThan(const Value *V, unsigned Size, + const TargetData &TD) { + const Type *AccessTy = 0; + if (const GlobalVariable *GV = dyn_cast(V)) + AccessTy = GV->getType()->getElementType(); + + if (const AllocationInst *AI = dyn_cast(V)) + if (!AI->isArrayAllocation()) + AccessTy = AI->getType()->getElementType(); + + if (const Argument *A = dyn_cast(V)) + if (A->hasByValAttr()) + AccessTy = cast(A->getType())->getElementType(); + + if (AccessTy && AccessTy->isSized()) + return TD.getABITypeSize(AccessTy) < Size; + return false; +} + // alias - Provide a bunch of ad-hoc rules to disambiguate in common cases, such // as array references. Note that this function is heavily tail recursive. // Hopefully we have a smart C++ compiler. :) @@ -319,92 +370,31 @@ const Value *O1 = getUnderlyingObject(V1); const Value *O2 = getUnderlyingObject(V2); - // Pointing at a discernible object? - if (O1) { - if (O2) { - if (const Argument *O1Arg = dyn_cast(O1)) { - // Incoming argument cannot alias locally allocated object! - if (isa(O2)) return NoAlias; - - // If they are two different objects, and one is a noalias argument - // then they do not alias. - if (O1 != O2 && O1Arg->hasNoAliasAttr()) - return NoAlias; - - // Byval arguments can't alias globals or other arguments. - if (O1 != O2 && O1Arg->hasByValAttr()) return NoAlias; - - // Otherwise, nothing is known... - } - - if (const Argument *O2Arg = dyn_cast(O2)) { - // Incoming argument cannot alias locally allocated object! - if (isa(O1)) return NoAlias; - - // If they are two different objects, and one is a noalias argument - // then they do not alias. - if (O1 != O2 && O2Arg->hasNoAliasAttr()) - return NoAlias; - - // Byval arguments can't alias globals or other arguments. - if (O1 != O2 && O2Arg->hasByValAttr()) return NoAlias; - - // Otherwise, nothing is known... - - } else if (O1 != O2 && !isa(O1)) { - // If they are two different objects, and neither is an argument, - // we know that we have no alias. - return NoAlias; - } - - // If they are the same object, they we can look at the indexes. If they - // index off of the object is the same for both pointers, they must alias. - // If they are provably different, they must not alias. Otherwise, we - // can't tell anything. - } - - // Unique values don't alias null, except non-byval arguments. - if (isa(V2)) { - if (const Argument *O1Arg = dyn_cast(O1)) { - if (O1Arg->hasByValAttr()) - return NoAlias; - } else { - return NoAlias; - } - } - - if (isa(O1) || - (isa(O1) && - !cast(O1)->isArrayAllocation())) - if (cast(O1->getType())->getElementType()->isSized()) { - // If the size of the other access is larger than the total size of the - // global/alloca/malloc, it cannot be accessing the global (it's - // undefined to load or store bytes before or after an object). - const Type *ElTy = cast(O1->getType())->getElementType(); - unsigned GlobalSize = getTargetData().getABITypeSize(ElTy); - if (GlobalSize < V2Size && V2Size != ~0U) - return NoAlias; - } - } - - if (O2) { - if (!isa(O2) && isa(V1)) - return NoAlias; // Unique values don't alias null - - if (isa(O2) || - (isa(O2) && - !cast(O2)->isArrayAllocation())) - if (cast(O2->getType())->getElementType()->isSized()) { - // If the size of the other access is larger than the total size of the - // global/alloca/malloc, it cannot be accessing the object (it's - // undefined to load or store bytes before or after an object). - const Type *ElTy = cast(O2->getType())->getElementType(); - unsigned GlobalSize = getTargetData().getABITypeSize(ElTy); - if (GlobalSize < V1Size && V1Size != ~0U) - return NoAlias; - } + if (O1 != O2) { + // If V1/V2 point to two different objects we know that we have no alias. + if (isIdentifiedObject(O1) && isIdentifiedObject(O2)) + return NoAlias; + + // Incoming argument cannot alias locally allocated object! + if ((isa(O1) && isa(O2)) || + (isa(O2) && isa(O1))) + return NoAlias; + + // Most objects can't alias null. + if ((isa(V2) && isKnownNonNull(O1)) || + (isa(V1) && isKnownNonNull(O2))) + return NoAlias; } - + + // If the size of one access is larger than the entire object on the other + // side, then we know such behavior is undefined and can assume no alias. + const TargetData &TD = getTargetData(); + if ((V1Size != ~0U && isObjectSmallerThan(O2, V1Size, TD)) || + (V2Size != ~0U && isObjectSmallerThan(O1, V2Size, TD))) + return NoAlias; + + + // If we have two gep instructions with must-alias'ing base pointers, figure // out if the indexes to the GEP tell us anything about the derived pointer. // Note that we also handle chains of getelementptr instructions as well as From resistor at mac.com Mon Jun 16 01:18:41 2008 From: resistor at mac.com (Owen Anderson) Date: Mon, 16 Jun 2008 06:18:41 -0000 Subject: [llvm-commits] [llvm] r52300 - /llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Message-ID: <200806160618.m5G6Igps021002@zion.cs.uiuc.edu> Author: resistor Date: Mon Jun 16 01:18:41 2008 New Revision: 52300 URL: http://llvm.org/viewvc/llvm-project?rev=52300&view=rev Log: Assign indices to empty basic blocks. This will be necessary for StrongPHIElimination in the near future. Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp?rev=52300&r1=52299&r2=52300&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp (original) +++ llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Mon Jun 16 01:18:41 2008 @@ -100,11 +100,14 @@ i2miMap_.push_back(I); MIIndex += InstrSlots::NUM; } - + + if (StartIdx == MIIndex) { + // Empty MBB + MIIndex += InstrSlots::NUM; + i2miMap_.push_back(0); + } // Set the MBB2IdxMap entry for this MBB. - MBB2IdxMap[MBB->getNumber()] = (StartIdx == MIIndex) - ? std::make_pair(StartIdx, StartIdx) // Empty MBB - : std::make_pair(StartIdx, MIIndex - 1); + MBB2IdxMap[MBB->getNumber()] = std::make_pair(StartIdx, MIIndex - 1); Idx2MBBMap.push_back(std::make_pair(StartIdx, MBB)); } std::sort(Idx2MBBMap.begin(), Idx2MBBMap.end(), Idx2MBBCompare()); @@ -661,6 +664,8 @@ MIIndex += InstrSlots::NUM; } + + if (MBB->begin() == miEnd) MIIndex += InstrSlots::NUM; // Empty MBB } } From sabre at nondot.org Mon Jun 16 01:19:11 2008 From: sabre at nondot.org (Chris Lattner) Date: Mon, 16 Jun 2008 06:19:11 -0000 Subject: [llvm-commits] [llvm] r52301 - in /llvm/trunk: lib/Analysis/BasicAliasAnalysis.cpp test/Analysis/BasicAA/no-escape-call.ll Message-ID: <200806160619.m5G6JBa7021035@zion.cs.uiuc.edu> Author: lattner Date: Mon Jun 16 01:19:11 2008 New Revision: 52301 URL: http://llvm.org/viewvc/llvm-project?rev=52301&view=rev Log: If we are checking to see if the result of a call aliases a pointer derived from a local allocation, if the local allocation never escapes, the pointers can't alias. This implements PR2436 Added: llvm/trunk/test/Analysis/BasicAA/no-escape-call.ll Modified: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Modified: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp?rev=52301&r1=52300&r2=52301&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp (original) +++ llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Mon Jun 16 01:19:11 2008 @@ -317,6 +317,18 @@ return false; } +/// isNonEscapingLocalObject - Return true if the pointer is to a function-local +/// object that never escapes from the function. +static bool isNonEscapingLocalObject(const Value *V) { + // If this is a local allocation or byval argument, check to see if it + // escapes. + if (isa(V) || + (isa(V) && cast(V)->hasByValAttr())) + return !AddressMightEscape(V); + return false; +} + + /// isObjectSmallerThan - Return true if we can prove that the object specified /// by V is smaller than Size. static bool isObjectSmallerThan(const Value *V, unsigned Size, @@ -393,7 +405,15 @@ (V2Size != ~0U && isObjectSmallerThan(O1, V2Size, TD))) return NoAlias; - + // If one pointer is the result of a call/invoke and the other is a + // non-escaping local object, then we know the object couldn't escape to a + // point where the call could return it. + if ((isa(O1) || isa(O1)) && + isNonEscapingLocalObject(O2)) + return NoAlias; + if ((isa(O2) || isa(O2)) && + isNonEscapingLocalObject(O1)) + return NoAlias; // If we have two gep instructions with must-alias'ing base pointers, figure // out if the indexes to the GEP tell us anything about the derived pointer. Added: llvm/trunk/test/Analysis/BasicAA/no-escape-call.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/BasicAA/no-escape-call.ll?rev=52301&view=auto ============================================================================== --- llvm/trunk/test/Analysis/BasicAA/no-escape-call.ll (added) +++ llvm/trunk/test/Analysis/BasicAA/no-escape-call.ll Mon Jun 16 01:19:11 2008 @@ -0,0 +1,23 @@ +; RUN: llvm-as < %s | opt -basicaa -gvn -instcombine | llvm-dis | grep {ret i1 true} +; PR2436 +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" +target triple = "i386-apple-darwin8" + +define i1 @foo(i32 %i) nounwind { +entry: + %arr = alloca [10 x i8*] ; <[10 x i8*]*> [#uses=1] + %tmp2 = call i8* @getPtr( ) nounwind ; [#uses=2] + %tmp4 = getelementptr [10 x i8*]* %arr, i32 0, i32 %i ; [#uses=2] + store i8* %tmp2, i8** %tmp4, align 4 + %tmp10 = getelementptr i8* %tmp2, i32 10 ; [#uses=1] + store i8 42, i8* %tmp10, align 1 + %tmp14 = load i8** %tmp4, align 4 ; [#uses=1] + %tmp16 = getelementptr i8* %tmp14, i32 10 ; [#uses=1] + %tmp17 = load i8* %tmp16, align 1 ; [#uses=1] + %tmp19 = icmp eq i8 %tmp17, 42 ; [#uses=1] + ret i1 %tmp19 +} + +declare i8* @getPtr() + +declare void @abort() noreturn nounwind From sabre at nondot.org Mon Jun 16 01:28:02 2008 From: sabre at nondot.org (Chris Lattner) Date: Mon, 16 Jun 2008 06:28:02 -0000 Subject: [llvm-commits] [llvm] r52302 - /llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Message-ID: <200806160628.m5G6S2De021307@zion.cs.uiuc.edu> Author: lattner Date: Mon Jun 16 01:28:01 2008 New Revision: 52302 URL: http://llvm.org/viewvc/llvm-project?rev=52302&view=rev Log: Other parts of this code treat noalias arguments as objects for the purposes of escape analysis. Modified: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Modified: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp?rev=52302&r1=52301&r2=52302&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp (original) +++ llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Mon Jun 16 01:28:01 2008 @@ -320,11 +320,15 @@ /// isNonEscapingLocalObject - Return true if the pointer is to a function-local /// object that never escapes from the function. static bool isNonEscapingLocalObject(const Value *V) { - // If this is a local allocation or byval argument, check to see if it - // escapes. - if (isa(V) || - (isa(V) && cast(V)->hasByValAttr())) + // If this is a local allocation, check to see if it escapes. + if (isa(V)) return !AddressMightEscape(V); + + // If this is an argument that corresponds to a byval or noalias argument, + // it can't escape either. + if (const Argument *A = dyn_cast(V)) + if (A->hasByValAttr() || A->hasNoAliasAttr()) + return !AddressMightEscape(V); return false; } From sabre at nondot.org Mon Jun 16 01:30:22 2008 From: sabre at nondot.org (Chris Lattner) Date: Mon, 16 Jun 2008 06:30:22 -0000 Subject: [llvm-commits] [llvm] r52303 - /llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Message-ID: <200806160630.m5G6UMww021402@zion.cs.uiuc.edu> Author: lattner Date: Mon Jun 16 01:30:22 2008 New Revision: 52303 URL: http://llvm.org/viewvc/llvm-project?rev=52303&view=rev Log: move a bunch of predicates up into their own section in this file, no other changes. Modified: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Modified: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp?rev=52303&r1=52302&r2=52303&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp (original) +++ llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Mon Jun 16 01:30:22 2008 @@ -32,6 +32,173 @@ #include using namespace llvm; +//===----------------------------------------------------------------------===// +// Useful predicates +//===----------------------------------------------------------------------===// + +// Determine if an AllocationInst instruction escapes from the function it is +// contained in. If it does not escape, there is no way for another function to +// mod/ref it. We do this by looking at its uses and determining if the uses +// can escape (recursively). +static bool AddressMightEscape(const Value *V) { + for (Value::use_const_iterator UI = V->use_begin(), E = V->use_end(); + UI != E; ++UI) { + const Instruction *I = cast(*UI); + switch (I->getOpcode()) { + case Instruction::Load: + break; //next use. + case Instruction::Store: + if (I->getOperand(0) == V) + return true; // Escapes if the pointer is stored. + break; // next use. + case Instruction::GetElementPtr: + if (AddressMightEscape(I)) + return true; + break; // next use. + case Instruction::BitCast: + if (AddressMightEscape(I)) + return true; + break; // next use + case Instruction::Ret: + // If returned, the address will escape to calling functions, but no + // callees could modify it. + break; // next use + case Instruction::Call: + // If the call is to a few known safe intrinsics, we know that it does + // not escape + if (!isa(I)) + return true; + break; // next use + default: + return true; + } + } + return false; +} + +/// getUnderlyingObject - This traverses the use chain to figure out what object +/// the specified value points to. If the value points to, or is derived from, +/// a unique object or an argument, return it. This returns: +/// Arguments, GlobalVariables, Functions, Allocas, Mallocs. +static const Value *getUnderlyingObject(const Value *V) { + if (!isa(V->getType())) return V; + + // If we are at some type of object, return it. GlobalValues and Allocations + // have unique addresses. + if (isa(V) || isa(V) || isa(V)) + return V; + + // Traverse through different addressing mechanisms... + if (const Instruction *I = dyn_cast(V)) { + if (isa(I) || isa(I)) + return getUnderlyingObject(I->getOperand(0)); + } else if (const ConstantExpr *CE = dyn_cast(V)) { + if (CE->getOpcode() == Instruction::BitCast || + CE->getOpcode() == Instruction::GetElementPtr) + return getUnderlyingObject(CE->getOperand(0)); + } + return V; +} + +static const User *isGEP(const Value *V) { + if (isa(V) || + (isa(V) && + cast(V)->getOpcode() == Instruction::GetElementPtr)) + return cast(V); + return 0; +} + +static const Value *GetGEPOperands(const Value *V, + SmallVector &GEPOps){ + assert(GEPOps.empty() && "Expect empty list to populate!"); + GEPOps.insert(GEPOps.end(), cast(V)->op_begin()+1, + cast(V)->op_end()); + + // Accumulate all of the chained indexes into the operand array + V = cast(V)->getOperand(0); + + while (const User *G = isGEP(V)) { + if (!isa(GEPOps[0]) || isa(GEPOps[0]) || + !cast(GEPOps[0])->isNullValue()) + break; // Don't handle folding arbitrary pointer offsets yet... + GEPOps.erase(GEPOps.begin()); // Drop the zero index + GEPOps.insert(GEPOps.begin(), G->op_begin()+1, G->op_end()); + V = G->getOperand(0); + } + return V; +} + +/// isIdentifiedObject - Return true if this pointer refers to a distinct and +/// identifiable object. This returns true for: +/// Global Variables and Functions +/// Allocas and Mallocs +/// ByVal and NoAlias Arguments +/// +static bool isIdentifiedObject(const Value *V) { + if (isa(V) || isa(V)) + return true; + if (const Argument *A = dyn_cast(V)) + return A->hasNoAliasAttr() || A->hasByValAttr(); + return false; +} + +/// isKnownNonNull - Return true if we know that the specified value is never +/// null. +static bool isKnownNonNull(const Value *V) { + // Alloca never returns null, malloc might. + if (isa(V)) return true; + + // A byval argument is never null. + if (const Argument *A = dyn_cast(V)) + return A->hasByValAttr(); + + // Global values are not null unless extern weak. + if (const GlobalValue *GV = dyn_cast(V)) + return !GV->hasExternalWeakLinkage(); + return false; +} + +/// isNonEscapingLocalObject - Return true if the pointer is to a function-local +/// object that never escapes from the function. +static bool isNonEscapingLocalObject(const Value *V) { + // If this is a local allocation, check to see if it escapes. + if (isa(V)) + return !AddressMightEscape(V); + + // If this is an argument that corresponds to a byval or noalias argument, + // it can't escape either. + if (const Argument *A = dyn_cast(V)) + if (A->hasByValAttr() || A->hasNoAliasAttr()) + return !AddressMightEscape(V); + return false; +} + + +/// isObjectSmallerThan - Return true if we can prove that the object specified +/// by V is smaller than Size. +static bool isObjectSmallerThan(const Value *V, unsigned Size, + const TargetData &TD) { + const Type *AccessTy = 0; + if (const GlobalVariable *GV = dyn_cast(V)) + AccessTy = GV->getType()->getElementType(); + + if (const AllocationInst *AI = dyn_cast(V)) + if (!AI->isArrayAllocation()) + AccessTy = AI->getType()->getElementType(); + + if (const Argument *A = dyn_cast(V)) + if (A->hasByValAttr()) + AccessTy = cast(A->getType())->getElementType(); + + if (AccessTy && AccessTy->isSized()) + return TD.getABITypeSize(AccessTy) < Size; + return false; +} + +//===----------------------------------------------------------------------===// +// NoAA Pass +//===----------------------------------------------------------------------===// + namespace { /// NoAA - This class implements the -no-aa pass, which always returns "I /// don't know" for alias queries. NoAA is unlike other alias analysis @@ -91,6 +258,10 @@ ImmutablePass *llvm::createNoAAPass() { return new NoAA(); } +//===----------------------------------------------------------------------===// +// BasicAA Pass +//===----------------------------------------------------------------------===// + namespace { /// BasicAliasAnalysis - This is the default alias analysis implementation. /// Because it doesn't chain to a previous alias analysis (like -no-aa), it @@ -138,57 +309,6 @@ return new BasicAliasAnalysis(); } -/// getUnderlyingObject - This traverses the use chain to figure out what object -/// the specified value points to. If the value points to, or is derived from, -/// a unique object or an argument, return it. This returns: -/// Arguments, GlobalVariables, Functions, Allocas, Mallocs. -static const Value *getUnderlyingObject(const Value *V) { - if (!isa(V->getType())) return V; - - // If we are at some type of object, return it. GlobalValues and Allocations - // have unique addresses. - if (isa(V) || isa(V) || isa(V)) - return V; - - // Traverse through different addressing mechanisms... - if (const Instruction *I = dyn_cast(V)) { - if (isa(I) || isa(I)) - return getUnderlyingObject(I->getOperand(0)); - } else if (const ConstantExpr *CE = dyn_cast(V)) { - if (CE->getOpcode() == Instruction::BitCast || - CE->getOpcode() == Instruction::GetElementPtr) - return getUnderlyingObject(CE->getOperand(0)); - } - return V; -} - -static const User *isGEP(const Value *V) { - if (isa(V) || - (isa(V) && - cast(V)->getOpcode() == Instruction::GetElementPtr)) - return cast(V); - return 0; -} - -static const Value *GetGEPOperands(const Value *V, - SmallVector &GEPOps){ - assert(GEPOps.empty() && "Expect empty list to populate!"); - GEPOps.insert(GEPOps.end(), cast(V)->op_begin()+1, - cast(V)->op_end()); - - // Accumulate all of the chained indexes into the operand array - V = cast(V)->getOperand(0); - - while (const User *G = isGEP(V)) { - if (!isa(GEPOps[0]) || isa(GEPOps[0]) || - !cast(GEPOps[0])->isNullValue()) - break; // Don't handle folding arbitrary pointer offsets yet... - GEPOps.erase(GEPOps.begin()); // Drop the zero index - GEPOps.insert(GEPOps.begin(), G->op_begin()+1, G->op_end()); - V = G->getOperand(0); - } - return V; -} /// pointsToConstantMemory - Chase pointers until we find a (constant /// global) or not. @@ -199,46 +319,6 @@ return false; } -// Determine if an AllocationInst instruction escapes from the function it is -// contained in. If it does not escape, there is no way for another function to -// mod/ref it. We do this by looking at its uses and determining if the uses -// can escape (recursively). -static bool AddressMightEscape(const Value *V) { - for (Value::use_const_iterator UI = V->use_begin(), E = V->use_end(); - UI != E; ++UI) { - const Instruction *I = cast(*UI); - switch (I->getOpcode()) { - case Instruction::Load: - break; //next use. - case Instruction::Store: - if (I->getOperand(0) == V) - return true; // Escapes if the pointer is stored. - break; // next use. - case Instruction::GetElementPtr: - if (AddressMightEscape(I)) - return true; - break; // next use. - case Instruction::BitCast: - if (AddressMightEscape(I)) - return true; - break; // next use - case Instruction::Ret: - // If returned, the address will escape to calling functions, but no - // callees could modify it. - break; // next use - case Instruction::Call: - // If the call is to a few known safe intrinsics, we know that it does - // not escape - if (!isa(I)) - return true; - break; // next use - default: - return true; - } - } - return false; -} - // getModRefInfo - Check to see if the specified callsite can clobber the // specified memory object. Since we only look at local properties of this // function, we really can't say much about this query. We do, however, use @@ -287,72 +367,6 @@ return AliasAnalysis::getModRefInfo(CS, P, Size); } -/// isIdentifiedObject - Return true if this pointer refers to a distinct and -/// identifiable object. This returns true for: -/// Global Variables and Functions -/// Allocas and Mallocs -/// ByVal and NoAlias Arguments -/// -static bool isIdentifiedObject(const Value *V) { - if (isa(V) || isa(V)) - return true; - if (const Argument *A = dyn_cast(V)) - return A->hasNoAliasAttr() || A->hasByValAttr(); - return false; -} - -/// isKnownNonNull - Return true if we know that the specified value is never -/// null. -static bool isKnownNonNull(const Value *V) { - // Alloca never returns null, malloc might. - if (isa(V)) return true; - - // A byval argument is never null. - if (const Argument *A = dyn_cast(V)) - return A->hasByValAttr(); - - // Global values are not null unless extern weak. - if (const GlobalValue *GV = dyn_cast(V)) - return !GV->hasExternalWeakLinkage(); - return false; -} - -/// isNonEscapingLocalObject - Return true if the pointer is to a function-local -/// object that never escapes from the function. -static bool isNonEscapingLocalObject(const Value *V) { - // If this is a local allocation, check to see if it escapes. - if (isa(V)) - return !AddressMightEscape(V); - - // If this is an argument that corresponds to a byval or noalias argument, - // it can't escape either. - if (const Argument *A = dyn_cast(V)) - if (A->hasByValAttr() || A->hasNoAliasAttr()) - return !AddressMightEscape(V); - return false; -} - - -/// isObjectSmallerThan - Return true if we can prove that the object specified -/// by V is smaller than Size. -static bool isObjectSmallerThan(const Value *V, unsigned Size, - const TargetData &TD) { - const Type *AccessTy = 0; - if (const GlobalVariable *GV = dyn_cast(V)) - AccessTy = GV->getType()->getElementType(); - - if (const AllocationInst *AI = dyn_cast(V)) - if (!AI->isArrayAllocation()) - AccessTy = AI->getType()->getElementType(); - - if (const Argument *A = dyn_cast(V)) - if (A->hasByValAttr()) - AccessTy = cast(A->getType())->getElementType(); - - if (AccessTy && AccessTy->isSized()) - return TD.getABITypeSize(AccessTy) < Size; - return false; -} // alias - Provide a bunch of ad-hoc rules to disambiguate in common cases, such // as array references. Note that this function is heavily tail recursive. From sabre at nondot.org Mon Jun 16 01:38:26 2008 From: sabre at nondot.org (Chris Lattner) Date: Mon, 16 Jun 2008 06:38:26 -0000 Subject: [llvm-commits] [llvm] r52304 - /llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Message-ID: <200806160638.m5G6cQxk021618@zion.cs.uiuc.edu> Author: lattner Date: Mon Jun 16 01:38:26 2008 New Revision: 52304 URL: http://llvm.org/viewvc/llvm-project?rev=52304&view=rev Log: simplify some code by using a helper function. This really really wants a 'nocapture' predicate. Modified: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Modified: llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp?rev=52304&r1=52303&r2=52304&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp (original) +++ llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp Mon Jun 16 01:38:26 2008 @@ -65,7 +65,8 @@ break; // next use case Instruction::Call: // If the call is to a few known safe intrinsics, we know that it does - // not escape + // not escape. + // TODO: Eventually just check the 'nocapture' attribute. if (!isa(I)) return true; break; // next use @@ -339,27 +340,20 @@ if (CI->isTailCall()) return NoModRef; - // Allocations and byval arguments are "new" objects. - if (isa(Object) || isa(Object)) { - // Okay, the pointer is to a stack allocated (or effectively so, for - // for noalias parameters) object. If the address of this object doesn't - // escape from this function body to a callee, then we know that no - // callees can mod/ref it unless they are actually passed it. - if (isa(Object) || - cast(Object)->hasByValAttr() || - cast(Object)->hasNoAliasAttr()) - if (!AddressMightEscape(Object)) { - bool passedAsArg = false; - for (CallSite::arg_iterator CI = CS.arg_begin(), CE = CS.arg_end(); - CI != CE; ++CI) - if (isa((*CI)->getType()) && - (getUnderlyingObject(*CI) == P || - alias(cast(CI), ~0U, P, ~0U) != NoAlias)) - passedAsArg = true; - - if (!passedAsArg) - return NoModRef; - } + // If the pointer is to a locally allocated object that does not escape, + // then the call can not mod/ref the pointer unless the call takes the + // argument without capturing it. + if (isNonEscapingLocalObject(Object)) { + bool passedAsArg = false; + // TODO: Eventually only check 'nocapture' arguments. + for (CallSite::arg_iterator CI = CS.arg_begin(), CE = CS.arg_end(); + CI != CE; ++CI) + if (isa((*CI)->getType()) && + alias(cast(CI), ~0U, P, ~0U) != NoAlias) + passedAsArg = true; + + if (!passedAsArg) + return NoModRef; } } From sabre at nondot.org Mon Jun 16 01:43:06 2008 From: sabre at nondot.org (Chris Lattner) Date: Mon, 16 Jun 2008 06:43:06 -0000 Subject: [llvm-commits] [llvm] r52305 - /llvm/trunk/include/llvm/Value.h Message-ID: <200806160643.m5G6h6dY021748@zion.cs.uiuc.edu> Author: lattner Date: Mon Jun 16 01:43:06 2008 New Revision: 52305 URL: http://llvm.org/viewvc/llvm-project?rev=52305&view=rev Log: add a const version of stripPointerCasts Modified: llvm/trunk/include/llvm/Value.h Modified: llvm/trunk/include/llvm/Value.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Value.h?rev=52305&r1=52304&r2=52305&view=diff ============================================================================== --- llvm/trunk/include/llvm/Value.h (original) +++ llvm/trunk/include/llvm/Value.h Mon Jun 16 01:43:06 2008 @@ -226,6 +226,9 @@ /// casts from the specified value, returning the original uncasted value. /// Note that the returned value is guaranteed to have pointer type. Value *stripPointerCasts(); + const Value *stripPointerCasts() const { + return const_cast(this)->stripPointerCasts(); + } }; inline std::ostream &operator<<(std::ostream &OS, const Value &V) { From resistor at mac.com Mon Jun 16 02:10:50 2008 From: resistor at mac.com (Owen Anderson) Date: Mon, 16 Jun 2008 07:10:50 -0000 Subject: [llvm-commits] [llvm] r52306 - /llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Message-ID: <200806160710.m5G7ApVd022583@zion.cs.uiuc.edu> Author: resistor Date: Mon Jun 16 02:10:49 2008 New Revision: 52306 URL: http://llvm.org/viewvc/llvm-project?rev=52306&view=rev Log: Make indexing empty basic blocks an option for the moment. Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp?rev=52306&r1=52305&r2=52306&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp (original) +++ llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Mon Jun 16 02:10:49 2008 @@ -44,6 +44,8 @@ cl::init(true), cl::Hidden); static cl::opt SplitLimit("split-limit", cl::init(-1), cl::Hidden); +static cl::opt EmptyBBIndex("empty-bb-index", + cl::init(false), cl::Hidden); STATISTIC(numIntervals, "Number of original intervals"); STATISTIC(numIntervalsAfter, "Number of intervals after coalescing"); @@ -100,15 +102,23 @@ i2miMap_.push_back(I); MIIndex += InstrSlots::NUM; } - - if (StartIdx == MIIndex) { - // Empty MBB - MIIndex += InstrSlots::NUM; - i2miMap_.push_back(0); - } + // Set the MBB2IdxMap entry for this MBB. - MBB2IdxMap[MBB->getNumber()] = std::make_pair(StartIdx, MIIndex - 1); - Idx2MBBMap.push_back(std::make_pair(StartIdx, MBB)); + if (!EmptyBBIndex) { + MBB2IdxMap[MBB->getNumber()] = (StartIdx == MIIndex) + ? std::make_pair(StartIdx, StartIdx) // Empty MBB + : std::make_pair(StartIdx, MIIndex - 1); + Idx2MBBMap.push_back(std::make_pair(StartIdx, MBB)); + } else { + if (StartIdx == MIIndex) { + // Empty MBB + MIIndex += InstrSlots::NUM; + i2miMap_.push_back(0); + } + + MBB2IdxMap[MBB->getNumber()] = std::make_pair(StartIdx, MIIndex - 1); + Idx2MBBMap.push_back(std::make_pair(StartIdx, MBB)); + } } std::sort(Idx2MBBMap.begin(), Idx2MBBMap.end(), Idx2MBBCompare()); @@ -665,7 +675,9 @@ MIIndex += InstrSlots::NUM; } - if (MBB->begin() == miEnd) MIIndex += InstrSlots::NUM; // Empty MBB + if (EmptyBBIndex) { + if (MBB->begin() == miEnd) MIIndex += InstrSlots::NUM; // Empty MBB + } } } From resistor at mac.com Mon Jun 16 02:17:13 2008 From: resistor at mac.com (Owen Anderson) Date: Mon, 16 Jun 2008 07:17:13 -0000 Subject: [llvm-commits] [test-suite] r52307 - /test-suite/trunk/Makefile.programs Message-ID: <200806160717.m5G7HDXm022813@zion.cs.uiuc.edu> Author: resistor Date: Mon Jun 16 02:17:11 2008 New Revision: 52307 URL: http://llvm.org/viewvc/llvm-project?rev=52307&view=rev Log: Enable empty BB indexing in LLC beta. Modified: test-suite/trunk/Makefile.programs Modified: test-suite/trunk/Makefile.programs URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/Makefile.programs?rev=52307&r1=52306&r2=52307&view=diff ============================================================================== --- test-suite/trunk/Makefile.programs (original) +++ test-suite/trunk/Makefile.programs Mon Jun 16 02:17:11 2008 @@ -205,7 +205,7 @@ endif#DISABLE_DIFFS ifeq ($(ARCH),PowerPC) -LLCBETAOPTION := -enable-sinking +LLCBETAOPTION := -enable-sinking -empty-bb-index #-machine-licm #--enable-tail-merge #--enable-ppc-preinc From evan.cheng at apple.com Mon Jun 16 02:33:11 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 16 Jun 2008 07:33:11 -0000 Subject: [llvm-commits] [llvm] r52308 - in /llvm/trunk: include/llvm/Target/TargetInstrInfo.h lib/CodeGen/TargetInstrInfoImpl.cpp lib/Target/PowerPC/PPCInstrInfo.cpp lib/Target/PowerPC/PPCInstrInfo.h lib/Target/X86/X86InstrInfo.cpp lib/Target/X86/X86InstrInfo.h Message-ID: <200806160733.m5G7XCoV023759@zion.cs.uiuc.edu> Author: evancheng Date: Mon Jun 16 02:33:11 2008 New Revision: 52308 URL: http://llvm.org/viewvc/llvm-project?rev=52308&view=rev Log: Add option to commuteInstruction() which forces it to create a new (commuted) instruction. Modified: llvm/trunk/include/llvm/Target/TargetInstrInfo.h llvm/trunk/lib/CodeGen/TargetInstrInfoImpl.cpp llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.cpp llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.h llvm/trunk/lib/Target/X86/X86InstrInfo.cpp llvm/trunk/lib/Target/X86/X86InstrInfo.h Modified: llvm/trunk/include/llvm/Target/TargetInstrInfo.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetInstrInfo.h?rev=52308&r1=52307&r2=52308&view=diff ============================================================================== --- llvm/trunk/include/llvm/Target/TargetInstrInfo.h (original) +++ llvm/trunk/include/llvm/Target/TargetInstrInfo.h Mon Jun 16 02:33:11 2008 @@ -155,7 +155,10 @@ /// return a new machine instruction. If an instruction cannot commute, it /// can also return null. /// - virtual MachineInstr *commuteInstruction(MachineInstr *MI) const = 0; + /// If NewMI is true, then a new machine instruction must be created. + /// + virtual MachineInstr *commuteInstruction(MachineInstr *MI, + bool NewMI = false) const = 0; /// CommuteChangesDestination - Return true if commuting the specified /// instruction will also changes the destination operand. Also return the @@ -411,7 +414,8 @@ TargetInstrInfoImpl(const TargetInstrDesc *desc, unsigned NumOpcodes) : TargetInstrInfo(desc, NumOpcodes) {} public: - virtual MachineInstr *commuteInstruction(MachineInstr *MI) const; + virtual MachineInstr *commuteInstruction(MachineInstr *MI, + bool NewMI = false) const; virtual bool CommuteChangesDestination(MachineInstr *MI, unsigned &OpIdx) const; virtual bool PredicateInstruction(MachineInstr *MI, Modified: llvm/trunk/lib/CodeGen/TargetInstrInfoImpl.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetInstrInfoImpl.cpp?rev=52308&r1=52307&r2=52308&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/TargetInstrInfoImpl.cpp (original) +++ llvm/trunk/lib/CodeGen/TargetInstrInfoImpl.cpp Mon Jun 16 02:33:11 2008 @@ -14,24 +14,39 @@ #include "llvm/Target/TargetInstrInfo.h" #include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" using namespace llvm; // commuteInstruction - The default implementation of this method just exchanges // operand 1 and 2. -MachineInstr *TargetInstrInfoImpl::commuteInstruction(MachineInstr *MI) const { +MachineInstr *TargetInstrInfoImpl::commuteInstruction(MachineInstr *MI, + bool NewMI) const { assert(MI->getOperand(1).isRegister() && MI->getOperand(2).isRegister() && "This only knows how to commute register operands so far"); unsigned Reg1 = MI->getOperand(1).getReg(); unsigned Reg2 = MI->getOperand(2).getReg(); bool Reg1IsKill = MI->getOperand(1).isKill(); bool Reg2IsKill = MI->getOperand(2).isKill(); + bool ChangeReg0 = false; if (MI->getOperand(0).getReg() == Reg1) { // Must be two address instruction! assert(MI->getDesc().getOperandConstraint(0, TOI::TIED_TO) && "Expecting a two-address instruction!"); Reg2IsKill = false; - MI->getOperand(0).setReg(Reg2); + ChangeReg0 = true; + } + + if (NewMI) { + // Create a new instruction. + unsigned Reg0 = ChangeReg0 ? Reg2 : MI->getOperand(0).getReg(); + bool Reg0IsDead = MI->getOperand(0).isDead(); + return BuildMI(MI->getDesc()).addReg(Reg0, true, false, false, Reg0IsDead) + .addReg(Reg2, false, false, Reg2IsKill) + .addReg(Reg1, false, false, Reg1IsKill); } + + if (ChangeReg0) + MI->getOperand(0).setReg(Reg2); MI->getOperand(2).setReg(Reg1); MI->getOperand(1).setReg(Reg2); MI->getOperand(2).setIsKill(Reg1IsKill); Modified: llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.cpp?rev=52308&r1=52307&r2=52308&view=diff ============================================================================== --- llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.cpp (original) +++ llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.cpp Mon Jun 16 02:33:11 2008 @@ -136,10 +136,11 @@ // commuteInstruction - We can commute rlwimi instructions, but only if the // rotate amt is zero. We also have to munge the immediates a bit. -MachineInstr *PPCInstrInfo::commuteInstruction(MachineInstr *MI) const { +MachineInstr * +PPCInstrInfo::commuteInstruction(MachineInstr *MI, bool NewMI) const { // Normal instructions can be commuted the obvious way. if (MI->getOpcode() != PPC::RLWIMI) - return TargetInstrInfoImpl::commuteInstruction(MI); + return TargetInstrInfoImpl::commuteInstruction(MI, NewMI); // Cannot commute if it has a non-zero rotate count. if (MI->getOperand(3).getImm() != 0) @@ -158,23 +159,40 @@ unsigned Reg2 = MI->getOperand(2).getReg(); bool Reg1IsKill = MI->getOperand(1).isKill(); bool Reg2IsKill = MI->getOperand(2).isKill(); + bool ChangeReg0 = false; // If machine instrs are no longer in two-address forms, update // destination register as well. if (Reg0 == Reg1) { // Must be two address instruction! assert(MI->getDesc().getOperandConstraint(0, TOI::TIED_TO) && "Expecting a two-address instruction!"); - MI->getOperand(0).setReg(Reg2); Reg2IsKill = false; + ChangeReg0 = true; + } + + // Masks. + unsigned MB = MI->getOperand(4).getImm(); + unsigned ME = MI->getOperand(5).getImm(); + + if (NewMI) { + // Create a new instruction. + unsigned Reg0 = ChangeReg0 ? Reg2 : MI->getOperand(0).getReg(); + bool Reg0IsDead = MI->getOperand(0).isDead(); + return BuildMI(MI->getDesc()).addReg(Reg0, true, false, false, Reg0IsDead) + .addReg(Reg2, false, false, Reg2IsKill) + .addReg(Reg1, false, false, Reg1IsKill) + .addImm((ME+1) & 31) + .addImm((MB-1) & 31); } + + if (ChangeReg0) + MI->getOperand(0).setReg(Reg2); MI->getOperand(2).setReg(Reg1); MI->getOperand(1).setReg(Reg2); MI->getOperand(2).setIsKill(Reg1IsKill); MI->getOperand(1).setIsKill(Reg2IsKill); // Swap the mask around. - unsigned MB = MI->getOperand(4).getImm(); - unsigned ME = MI->getOperand(5).getImm(); MI->getOperand(4).setImm((ME+1) & 31); MI->getOperand(5).setImm((MB-1) & 31); return MI; Modified: llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.h?rev=52308&r1=52307&r2=52308&view=diff ============================================================================== --- llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.h (original) +++ llvm/trunk/lib/Target/PowerPC/PPCInstrInfo.h Mon Jun 16 02:33:11 2008 @@ -96,7 +96,7 @@ // commuteInstruction - We can commute rlwimi instructions, but only if the // rotate amt is zero. We also have to munge the immediates a bit. - virtual MachineInstr *commuteInstruction(MachineInstr *MI) const; + virtual MachineInstr *commuteInstruction(MachineInstr *MI, bool NewMI) const; virtual void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const; Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.cpp?rev=52308&r1=52307&r2=52308&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrInfo.cpp (original) +++ llvm/trunk/lib/Target/X86/X86InstrInfo.cpp Mon Jun 16 02:33:11 2008 @@ -1146,7 +1146,8 @@ /// commuteInstruction - We have a few instructions that must be hacked on to /// commute them. /// -MachineInstr *X86InstrInfo::commuteInstruction(MachineInstr *MI) const { +MachineInstr * +X86InstrInfo::commuteInstruction(MachineInstr *MI, bool NewMI) const { switch (MI->getOpcode()) { case X86::SHRD16rri8: // A = SHRD16rri8 B, C, I -> A = SHLD16rri8 C, B, (16-I) case X86::SHLD16rri8: // A = SHLD16rri8 B, C, I -> A = SHRD16rri8 C, B, (16-I) @@ -1276,7 +1277,7 @@ // Fallthrough intended. } default: - return TargetInstrInfoImpl::commuteInstruction(MI); + return TargetInstrInfoImpl::commuteInstruction(MI, NewMI); } } Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.h?rev=52308&r1=52307&r2=52308&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrInfo.h (original) +++ llvm/trunk/lib/Target/X86/X86InstrInfo.h Mon Jun 16 02:33:11 2008 @@ -283,7 +283,7 @@ /// commuteInstruction - We have a few instructions that must be hacked on to /// commute them. /// - virtual MachineInstr *commuteInstruction(MachineInstr *MI) const; + virtual MachineInstr *commuteInstruction(MachineInstr *MI, bool NewMI) const; // Branch analysis. virtual bool isUnpredicatedTerminator(const MachineInstr* MI) const; From evan.cheng at apple.com Mon Jun 16 02:34:17 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 16 Jun 2008 07:34:17 -0000 Subject: [llvm-commits] [llvm] r52309 - /llvm/trunk/lib/CodeGen/VirtRegMap.cpp Message-ID: <200806160734.m5G7YHbe024215@zion.cs.uiuc.edu> Author: evancheng Date: Mon Jun 16 02:34:17 2008 New Revision: 52309 URL: http://llvm.org/viewvc/llvm-project?rev=52309&view=rev Log: Fix read after free found by valgrind. Modified: llvm/trunk/lib/CodeGen/VirtRegMap.cpp Modified: llvm/trunk/lib/CodeGen/VirtRegMap.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/VirtRegMap.cpp?rev=52309&r1=52308&r2=52309&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/VirtRegMap.cpp (original) +++ llvm/trunk/lib/CodeGen/VirtRegMap.cpp Mon Jun 16 02:34:17 2008 @@ -1026,19 +1026,15 @@ DefMI->getOperand(DefIdx).getReg() == SrcReg); // Now commute def instruction. - MachineInstr *CommutedMI = TII->commuteInstruction(DefMI); + MachineInstr *CommutedMI = TII->commuteInstruction(DefMI, true); if (!CommutedMI) return false; SmallVector Ops; Ops.push_back(NewDstIdx); MachineInstr *FoldedMI = TII->foldMemoryOperand(MF, CommutedMI, Ops, SS); - if (!FoldedMI) { - if (CommutedMI == DefMI) - TII->commuteInstruction(CommutedMI); - else - MBB.erase(CommutedMI); + delete CommutedMI; // Not needed since foldMemoryOperand returns new MI. + if (!FoldedMI) return false; - } VRM.addSpillSlotUse(SS, FoldedMI); VRM.virtFolded(VirtReg, FoldedMI, VirtRegMap::isRef); @@ -1052,17 +1048,16 @@ MII = MBB.insert(MII, FoldedMI); // Update MII to backtrack. // Delete all 3 old instructions. - InvalidateKills(MI, RegKills, KillOps); - VRM.RemoveMachineInstrFromMaps(&MI); - MBB.erase(&MI); - if (CommutedMI != DefMI) - MBB.erase(CommutedMI); - InvalidateKills(*DefMI, RegKills, KillOps); - VRM.RemoveMachineInstrFromMaps(DefMI); - MBB.erase(DefMI); InvalidateKills(*ReloadMI, RegKills, KillOps); VRM.RemoveMachineInstrFromMaps(ReloadMI); MBB.erase(ReloadMI); + InvalidateKills(*DefMI, RegKills, KillOps); + VRM.RemoveMachineInstrFromMaps(DefMI); + MBB.erase(DefMI); + InvalidateKills(MI, RegKills, KillOps); + VRM.RemoveMachineInstrFromMaps(&MI); + MBB.erase(&MI); + ++NumCommutes; return true; } From matthijs at stdin.nl Mon Jun 16 02:36:30 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Mon, 16 Jun 2008 09:36:30 +0200 Subject: [llvm-commits] [llvm] r52288 - in /llvm/trunk/lib/System: Path.cpp Unix/Path.inc Win32/Path.inc In-Reply-To: <200806151515.m5FFFJAV025930@zion.cs.uiuc.edu> References: <200806151515.m5FFFJAV025930@zion.cs.uiuc.edu> Message-ID: <20080616073630.GF2636@katherina.student.utwente.nl> Hi Argiris, why is the getSuffix code now duplicated for win32 and unix? Unless I'm very much mistaken, the code is identical. The old code was not duplicated (at least, you only removed one copy in your patch), so why must the new code be? Gr. Matthijs -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: Digital signature Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080616/a99061a6/attachment.bin From baldrick at free.fr Mon Jun 16 03:14:39 2008 From: baldrick at free.fr (Duncan Sands) Date: Mon, 16 Jun 2008 08:14:39 -0000 Subject: [llvm-commits] [llvm] r52310 - in /llvm/trunk: include/llvm/CodeGen/ValueTypes.h lib/CodeGen/SelectionDAG/DAGCombiner.cpp Message-ID: <200806160814.m5G8EdZh002648@zion.cs.uiuc.edu> Author: baldrick Date: Mon Jun 16 03:14:38 2008 New Revision: 52310 URL: http://llvm.org/viewvc/llvm-project?rev=52310&view=rev Log: Allow these transforms for types like i256 while still excluding types like i1 (not byte sized) and i120 (loading an i120 requires loading an i64, an i32, an i16 and an i8, which is expensive). Modified: llvm/trunk/include/llvm/CodeGen/ValueTypes.h llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Modified: llvm/trunk/include/llvm/CodeGen/ValueTypes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/ValueTypes.h?rev=52310&r1=52309&r2=52310&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/ValueTypes.h (original) +++ llvm/trunk/include/llvm/CodeGen/ValueTypes.h Mon Jun 16 03:14:38 2008 @@ -266,6 +266,12 @@ return (getSizeInBits() & 7) == 0; } + /// isRound - Return true if the size is a power-of-two number of bytes. + inline bool isRound() const { + unsigned BitSize = getSizeInBits(); + return BitSize >= 8 && !(BitSize & (BitSize - 1)); + } + /// bitsGT - Return true if this has more bits than VT. inline bool bitsGT(MVT VT) const { return getSizeInBits() > VT.getSizeInBits(); Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=52310&r1=52309&r2=52310&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Mon Jun 16 03:14:38 2008 @@ -1787,10 +1787,9 @@ EVT = MVT::getIntegerVT(ActiveBits); MVT LoadedVT = LN0->getMemoryVT(); - // Do not generate loads of extended integer types since these can be - // expensive (and would be wrong if the type is not byte sized). - if (EVT != MVT::Other && LoadedVT.bitsGT(EVT) && EVT.isSimple() && - EVT.isByteSized() && // Exclude MVT::i1, which is simple. + // Do not generate loads of non-round integer types since these can + // be expensive (and would be wrong if the type is not byte sized). + if (EVT != MVT::Other && LoadedVT.bitsGT(EVT) && EVT.isRound() && (!AfterLegalize || TLI.isLoadXLegal(ISD::ZEXTLOAD, EVT))) { MVT PtrType = N0.getOperand(1).getValueType(); // For big endian targets, we need to add an offset to the pointer to @@ -3187,10 +3186,9 @@ } } - // Do not generate loads of extended integer types since these can be - // expensive (and would be wrong if the type is not byte sized). - if (ISD::isNON_EXTLoad(N0.Val) && N0.hasOneUse() && VT.isSimple() && - VT.isByteSized() && // Exclude MVT::i1, which is simple. + // Do not generate loads of non-round integer types since these can + // be expensive (and would be wrong if the type is not byte sized). + if (ISD::isNON_EXTLoad(N0.Val) && N0.hasOneUse() && VT.isRound() && // Do not change the width of a volatile load. !cast(N0)->isVolatile()) { assert(N0.getValueType().getSizeInBits() > EVTBits && From akyrtzi at gmail.com Mon Jun 16 03:18:35 2008 From: akyrtzi at gmail.com (Argiris Kirtzidis) Date: Mon, 16 Jun 2008 01:18:35 -0700 Subject: [llvm-commits] [llvm] r52288 - in /llvm/trunk/lib/System: Path.cpp Unix/Path.inc Win32/Path.inc In-Reply-To: <20080616073630.GF2636@katherina.student.utwente.nl> References: <200806151515.m5FFFJAV025930@zion.cs.uiuc.edu> <20080616073630.GF2636@katherina.student.utwente.nl> Message-ID: <485621DB.8000008@gmail.com> Hi Matthijs, Matthijs Kooijman wrote: > why is the getSuffix code now duplicated for win32 and unix? Unless I'm very > much mistaken, the code is identical. The old code was not duplicated (at > least, you only removed one copy in your patch), so why must the new code be? > There are a couple of others that are also duplicated, like Path::getBasename(). I assumed that the convention is that if a method deals with directory separators, it is getting into platform implementation details and it should have separate platform implementations, even if the code turns out to be identical (currently the Win32 path implementation uses '/' as directory separator but it could as easily use '\' instead). Does this seem reasonable ? -Argiris From matthijs at stdin.nl Mon Jun 16 03:23:29 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Mon, 16 Jun 2008 10:23:29 +0200 Subject: [llvm-commits] [llvm] r52288 - in /llvm/trunk/lib/System: Path.cpp Unix/Path.inc Win32/Path.inc In-Reply-To: <485621DB.8000008@gmail.com> References: <200806151515.m5FFFJAV025930@zion.cs.uiuc.edu> <20080616073630.GF2636@katherina.student.utwente.nl> <485621DB.8000008@gmail.com> Message-ID: <20080616082329.GI2636@katherina.student.utwente.nl> Hi Argiris, > There are a couple of others that are also duplicated, like > Path::getBasename(). IMHO code duplication should be prevented as much as possible. You probably did well to make things consistent in this case, but perhaps we should wonder if we shouldn't prevent all of this duplication. > I assumed that the convention is that if a method deals with directory > separators, it is getting into platform implementation details and it should > have separate platform implementations, even if the code turns out to be > identical (currently the Win32 path implementation uses '/' as directory > separator but it could as easily use '\' instead). Wouldn't it be better to simply make the path separator configurable (ie, have a method that returns it?) Anyone with a better view of why things are like this that can comment? Gr. Matthijs -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: Digital signature Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080616/a2ef0685/attachment.bin From matthijs at stdin.nl Mon Jun 16 04:38:24 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Mon, 16 Jun 2008 09:38:24 -0000 Subject: [llvm-commits] [llvm] r52311 - in /llvm/trunk/test/FrontendC: 2003-08-21-WideString.c 2004-02-13-IllegalVararg.c 2006-09-18-fwrite-cast-crash.c 2007-09-05-ConstCtor.c 2007-09-28-PackedUnionMember.c Message-ID: <200806160938.m5G9cOeZ009708@zion.cs.uiuc.edu> Author: matthijs Date: Mon Jun 16 04:38:23 2008 New Revision: 52311 URL: http://llvm.org/viewvc/llvm-project?rev=52311&view=rev Log: Fix PR numbers, I accidentally switched two digits. Modified: llvm/trunk/test/FrontendC/2003-08-21-WideString.c llvm/trunk/test/FrontendC/2004-02-13-IllegalVararg.c llvm/trunk/test/FrontendC/2006-09-18-fwrite-cast-crash.c llvm/trunk/test/FrontendC/2007-09-05-ConstCtor.c llvm/trunk/test/FrontendC/2007-09-28-PackedUnionMember.c Modified: llvm/trunk/test/FrontendC/2003-08-21-WideString.c URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FrontendC/2003-08-21-WideString.c?rev=52311&r1=52310&r2=52311&view=diff ============================================================================== --- llvm/trunk/test/FrontendC/2003-08-21-WideString.c (original) +++ llvm/trunk/test/FrontendC/2003-08-21-WideString.c Mon Jun 16 04:38:23 2008 @@ -1,6 +1,6 @@ // RUN: %llvmgcc -S %s -o - | llvm-as -f -o /dev/null // XFAIL: * -// See PR2425 +// See PR2452 struct { int *name; Modified: llvm/trunk/test/FrontendC/2004-02-13-IllegalVararg.c URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FrontendC/2004-02-13-IllegalVararg.c?rev=52311&r1=52310&r2=52311&view=diff ============================================================================== --- llvm/trunk/test/FrontendC/2004-02-13-IllegalVararg.c (original) +++ llvm/trunk/test/FrontendC/2004-02-13-IllegalVararg.c Mon Jun 16 04:38:23 2008 @@ -1,6 +1,6 @@ // RUN: %llvmgcc -xc %s -w -c -o - | llc // XFAIL: * -// See PR2425 +// See PR2452 #include Modified: llvm/trunk/test/FrontendC/2006-09-18-fwrite-cast-crash.c URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FrontendC/2006-09-18-fwrite-cast-crash.c?rev=52311&r1=52310&r2=52311&view=diff ============================================================================== --- llvm/trunk/test/FrontendC/2006-09-18-fwrite-cast-crash.c (original) +++ llvm/trunk/test/FrontendC/2006-09-18-fwrite-cast-crash.c Mon Jun 16 04:38:23 2008 @@ -1,7 +1,7 @@ // RUN: %llvmgcc %s -S -o /dev/null // PR910 // XFAIL: * -// See PR2425 +// See PR2452 struct l_struct_2E_FILE { char x; }; unsigned fwrite(signed char *, unsigned , unsigned , signed char *); Modified: llvm/trunk/test/FrontendC/2007-09-05-ConstCtor.c URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FrontendC/2007-09-05-ConstCtor.c?rev=52311&r1=52310&r2=52311&view=diff ============================================================================== --- llvm/trunk/test/FrontendC/2007-09-05-ConstCtor.c (original) +++ llvm/trunk/test/FrontendC/2007-09-05-ConstCtor.c Mon Jun 16 04:38:23 2008 @@ -1,7 +1,7 @@ // RUN: %llvmgcc -xc -Os -c %s -o /dev/null // PR1641 // XFAIL: * -// See PR2425 +// See PR2452 struct A { unsigned long l; Modified: llvm/trunk/test/FrontendC/2007-09-28-PackedUnionMember.c URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FrontendC/2007-09-28-PackedUnionMember.c?rev=52311&r1=52310&r2=52311&view=diff ============================================================================== --- llvm/trunk/test/FrontendC/2007-09-28-PackedUnionMember.c (original) +++ llvm/trunk/test/FrontendC/2007-09-28-PackedUnionMember.c Mon Jun 16 04:38:23 2008 @@ -1,6 +1,6 @@ // RUN: %llvmgcc %s -S -o - // XFAIL: * -// See PR2425 +// See PR2452 #pragma pack(push, 2) struct H { From matthijs at stdin.nl Mon Jun 16 04:42:50 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Mon, 16 Jun 2008 11:42:50 +0200 Subject: [llvm-commits] XPASS's In-Reply-To: <236044CD-1D79-4187-BFE4-DEBBF723A74C@apple.com> References: <236044CD-1D79-4187-BFE4-DEBBF723A74C@apple.com> Message-ID: <20080616094250.GJ2636@katherina.student.utwente.nl> Hi Chris, These tests were failing for me, but as Dale also reported, they don't give warnings on darwin. I don't fully understand the testcases or warnings, so I can't really tell what the correct solution would be. > What is going on with these? I see some discussion in PR2452 about > warnings. However, warnings shouldn't affect tests in llvm/test unless the > run line for the test has -Werror on it or something. Recently, I changed the tester such that stderr output is interpreted as a failure. Though that's not strictly a good idea, I couldn't make TCL distinguish between stderr output and command line parse errors, and those last should really not be ignored. Still, it's probably a good idea to error out on stderr output, in a lot of cases this will mean trivial stuff needs to fixed, but it will also catch some cases of testcases that will stop working for whatever reason. Simply redirecting stderr to /dev/null will also restore the original behaviour and can be done on a per testcase basis. Gr. Matthijs -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: Digital signature Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080616/b1d07cd8/attachment.bin From akyrtzi at gmail.com Mon Jun 16 05:14:14 2008 From: akyrtzi at gmail.com (Argiris Kirtzidis) Date: Mon, 16 Jun 2008 10:14:14 -0000 Subject: [llvm-commits] [llvm] r52312 - /llvm/trunk/lib/System/Win32/Path.inc Message-ID: <200806161014.m5GAEGMb010798@zion.cs.uiuc.edu> Author: akirtzidis Date: Mon Jun 16 05:14:09 2008 New Revision: 52312 URL: http://llvm.org/viewvc/llvm-project?rev=52312&view=rev Log: Minor comment fix. Modified: llvm/trunk/lib/System/Win32/Path.inc Modified: llvm/trunk/lib/System/Win32/Path.inc URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/System/Win32/Path.inc?rev=52312&r1=52311&r2=52312&view=diff ============================================================================== --- llvm/trunk/lib/System/Win32/Path.inc (original) +++ llvm/trunk/lib/System/Win32/Path.inc Mon Jun 16 05:14:09 2008 @@ -1,4 +1,4 @@ -//===- llvm/System/Linux/Path.cpp - Linux Path Implementation ---*- C++ -*-===// +//===- llvm/System/Win32/Path.cpp - Win32 Path Implementation ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // From matthijs at stdin.nl Mon Jun 16 07:20:06 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Mon, 16 Jun 2008 12:20:06 -0000 Subject: [llvm-commits] [llvm] r52313 - /llvm/trunk/include/llvm/System/Program.h Message-ID: <200806161220.m5GCK7E2014515@zion.cs.uiuc.edu> Author: matthijs Date: Mon Jun 16 07:20:05 2008 New Revision: 52313 URL: http://llvm.org/viewvc/llvm-project?rev=52313&view=rev Log: Add comment. Modified: llvm/trunk/include/llvm/System/Program.h Modified: llvm/trunk/include/llvm/System/Program.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/System/Program.h?rev=52313&r1=52312&r2=52313&view=diff ============================================================================== --- llvm/trunk/include/llvm/System/Program.h (original) +++ llvm/trunk/include/llvm/System/Program.h Mon Jun 16 07:20:05 2008 @@ -65,6 +65,9 @@ ///< should have a size of at least three. If the pointer in the array ///< are not null, then the inferior process's stdin(0), stdout(1), ///< and stderr(2) will be redirected to the corresponding Paths. + ///< When an empty Path is passed in, the corresponding file + ///< descriptor will be disconnected (ie, /dev/null'd) in a portable + ///< way. unsigned secondsToWait = 0, ///< If non-zero, this specifies the amount ///< of time to wait for the child process to exit. If the time ///< expires, the child is killed and this call returns. If zero, From matthijs at stdin.nl Mon Jun 16 07:21:26 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Mon, 16 Jun 2008 12:21:26 -0000 Subject: [llvm-commits] [llvm] r52314 - /llvm/trunk/test/Transforms/DeadArgElim/2007-12-20-ParamAttrs.ll Message-ID: <200806161221.m5GCLQHV014582@zion.cs.uiuc.edu> Author: matthijs Date: Mon Jun 16 07:21:25 2008 New Revision: 52314 URL: http://llvm.org/viewvc/llvm-project?rev=52314&view=rev Log: Store the result of multiple identical run lines in a temporary file. Modified: llvm/trunk/test/Transforms/DeadArgElim/2007-12-20-ParamAttrs.ll Modified: llvm/trunk/test/Transforms/DeadArgElim/2007-12-20-ParamAttrs.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/DeadArgElim/2007-12-20-ParamAttrs.ll?rev=52314&r1=52313&r2=52314&view=diff ============================================================================== --- llvm/trunk/test/Transforms/DeadArgElim/2007-12-20-ParamAttrs.ll (original) +++ llvm/trunk/test/Transforms/DeadArgElim/2007-12-20-ParamAttrs.ll Mon Jun 16 07:21:25 2008 @@ -1,8 +1,9 @@ -; RUN: llvm-as < %s | opt -deadargelim | llvm-dis | grep nounwind | count 2 -; RUN: llvm-as < %s | opt -deadargelim | llvm-dis | grep signext | count 2 -; RUN: llvm-as < %s | opt -deadargelim | llvm-dis | not grep inreg -; RUN: llvm-as < %s | opt -deadargelim | llvm-dis | not grep zeroext -; RUN: llvm-as < %s | opt -deadargelim | llvm-dis | not grep byval +; RUN: llvm-as < %s | opt -deadargelim | llvm-dis > %t +; RUN: cat %t | grep nounwind | count 2 +; RUN: cat %t | grep signext | count 2 +; RUN: cat %t | not grep inreg +; RUN: cat %t | not grep zeroext +; RUN: cat %t | not grep byval %struct = type { } From matthijs at stdin.nl Mon Jun 16 07:48:21 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Mon, 16 Jun 2008 12:48:21 -0000 Subject: [llvm-commits] [llvm] r52315 - in /llvm/trunk: include/llvm/Analysis/ValueTracking.h lib/Analysis/ValueTracking.cpp lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200806161248.m5GCmM01015536@zion.cs.uiuc.edu> Author: matthijs Date: Mon Jun 16 07:48:21 2008 New Revision: 52315 URL: http://llvm.org/viewvc/llvm-project?rev=52315&view=rev Log: Move FindScalarValue from InstructionCombining.cpp to ValueTracking.cpp. While I'm at it, rename it to FindInsertedValue. The only functional change is that newly created instructions are no longer added to instcombine's worklist, but that is not really necessary anyway (and I'll commit some improvements next that will completely remove the need). Modified: llvm/trunk/include/llvm/Analysis/ValueTracking.h llvm/trunk/lib/Analysis/ValueTracking.cpp llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Modified: llvm/trunk/include/llvm/Analysis/ValueTracking.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ValueTracking.h?rev=52315&r1=52314&r2=52315&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/ValueTracking.h (original) +++ llvm/trunk/include/llvm/Analysis/ValueTracking.h Mon Jun 16 07:48:21 2008 @@ -17,6 +17,7 @@ namespace llvm { class Value; + class Instruction; class APInt; class TargetData; @@ -50,6 +51,14 @@ /// value is never equal to -0.0. /// bool CannotBeNegativeZero(const Value *V, unsigned Depth = 0); + + /// FindScalarValue - Given an aggregrate and an sequence of indices, see if the + /// scalar value indexed is already around as a register, for example if it were + /// inserted directly into the aggregrate. + Value *FindInsertedValue(Value *V, + const unsigned *idx_begin, + const unsigned *idx_end, + Instruction &InsertBefore); } // end namespace llvm #endif Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=52315&r1=52314&r2=52315&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ValueTracking.cpp (original) +++ llvm/trunk/lib/Analysis/ValueTracking.cpp Mon Jun 16 07:48:21 2008 @@ -755,3 +755,131 @@ return false; } +// This is the recursive version of BuildSubAggregate. It takes a few different +// arguments. Idxs is the index within the nested struct From that we are +// looking at now (which is of type IndexedType). IdxSkip is the number of +// indices from Idxs that should be left out when inserting into the resulting +// struct. To is the result struct built so far, new insertvalue instructions +// build on that. +Value *BuildSubAggregate(Value *From, Value* To, const Type *IndexedType, + SmallVector &Idxs, + unsigned IdxSkip, + Instruction &InsertBefore) { + const llvm::StructType *STy = llvm::dyn_cast(IndexedType); + if (STy) { + // General case, the type indexed by Idxs is a struct + for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { + // Process each struct element recursively + Idxs.push_back(i); + To = BuildSubAggregate(From, To, STy->getElementType(i), Idxs, IdxSkip, InsertBefore); + Idxs.pop_back(); + } + return To; + } else { + // Base case, the type indexed by SourceIdxs is not a struct + // Load the value from the nested struct into the sub struct (and skip + // IdxSkip indices when indexing the sub struct). + Instruction *V = llvm::ExtractValueInst::Create(From, Idxs.begin(), Idxs.end(), "tmp", &InsertBefore); + Instruction *Ins = llvm::InsertValueInst::Create(To, V, Idxs.begin() + IdxSkip, Idxs.end(), "tmp", &InsertBefore); + return Ins; + } +} + +// This helper takes a nested struct and extracts a part of it (which is again a +// struct) into a new value. For example, given the struct: +// { a, { b, { c, d }, e } } +// and the indices "1, 1" this returns +// { c, d }. +// +// It does this by inserting an extractvalue and insertvalue for each element in +// the resulting struct, as opposed to just inserting a single struct. This +// allows for later folding of these individual extractvalue instructions with +// insertvalue instructions that fill the nested struct. +// +// Any inserted instructions are inserted before InsertBefore +Value *BuildSubAggregate(Value *From, const unsigned *idx_begin, const unsigned *idx_end, Instruction &InsertBefore) { + const Type *IndexedType = ExtractValueInst::getIndexedType(From->getType(), idx_begin, idx_end); + Value *To = UndefValue::get(IndexedType); + SmallVector Idxs(idx_begin, idx_end); + unsigned IdxSkip = Idxs.size(); + + return BuildSubAggregate(From, To, IndexedType, Idxs, IdxSkip, InsertBefore); +} + +/// FindInsertedValue - Given an aggregrate and an sequence of indices, see if the +/// scalar value indexed is already around as a register, for example if it were +/// inserted directly into the aggregrate. +Value *llvm::FindInsertedValue(Value *V, const unsigned *idx_begin, + const unsigned *idx_end, Instruction &InsertBefore) { + // Nothing to index? Just return V then (this is useful at the end of our + // recursion) + if (idx_begin == idx_end) + return V; + // We have indices, so V should have an indexable type + assert((isa(V->getType()) || isa(V->getType())) + && "Not looking at a struct or array?"); + assert(ExtractValueInst::getIndexedType(V->getType(), idx_begin, idx_end) + && "Invalid indices for type?"); + const CompositeType *PTy = cast(V->getType()); + + if (isa(V)) + return UndefValue::get(ExtractValueInst::getIndexedType(PTy, + idx_begin, + idx_end)); + else if (isa(V)) + return Constant::getNullValue(ExtractValueInst::getIndexedType(PTy, + idx_begin, + idx_end)); + else if (Constant *C = dyn_cast(V)) { + if (isa(C) || isa(C)) + // Recursively process this constant + return FindInsertedValue(C->getOperand(*idx_begin), ++idx_begin, idx_end, InsertBefore); + } else if (InsertValueInst *I = dyn_cast(V)) { + // Loop the indices for the insertvalue instruction in parallel with the + // requested indices + const unsigned *req_idx = idx_begin; + for (const unsigned *i = I->idx_begin(), *e = I->idx_end(); i != e; ++i, ++req_idx) { + if (req_idx == idx_end) + // The requested index is a part of a nested aggregate. Handle this + // specially. + return BuildSubAggregate(V, idx_begin, req_idx, InsertBefore); + + // This insert value inserts something else than what we are looking for. + // See if the (aggregrate) value inserted into has the value we are + // looking for, then. + if (*req_idx != *i) + return FindInsertedValue(I->getAggregateOperand(), idx_begin, idx_end, InsertBefore); + } + // If we end up here, the indices of the insertvalue match with those + // requested (though possibly only partially). Now we recursively look at + // the inserted value, passing any remaining indices. + return FindInsertedValue(I->getInsertedValueOperand(), req_idx, idx_end, InsertBefore); + } else if (ExtractValueInst *I = dyn_cast(V)) { + // If we're extracting a value from an aggregrate that was extracted from + // something else, we can extract from that something else directly instead. + // However, we will need to chain I's indices with the requested indices. + + // Calculate the number of indices required + unsigned size = I->getNumIndices() + (idx_end - idx_begin); + // Allocate some space to put the new indices in + unsigned *new_begin = new unsigned[size]; + // Auto cleanup this array + std::auto_ptr newptr(new_begin); + // Start inserting at the beginning + unsigned *new_end = new_begin; + // Add indices from the extract value instruction + for (const unsigned *i = I->idx_begin(), *e = I->idx_end(); i != e; ++i, ++new_end) + *new_end = *i; + + // Add requested indices + for (const unsigned *i = idx_begin, *e = idx_end; i != e; ++i, ++new_end) + *new_end = *i; + + assert((unsigned)(new_end - new_begin) == size && "Number of indices added not correct?"); + + return FindInsertedValue(I->getAggregateOperand(), new_begin, new_end, InsertBefore); + } + // Otherwise, we don't know (such as, extracting from a function return value + // or load instruction) + return 0; +} Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=52315&r1=52314&r2=52315&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Mon Jun 16 07:48:21 2008 @@ -399,21 +399,6 @@ unsigned GetOrEnforceKnownAlignment(Value *V, unsigned PrefAlign = 0); - // visitExtractValue helpers - Value *FindScalarValue(Value *V, - const unsigned *idx_begin, - const unsigned *idx_end, - Instruction &InsertBefore); - Value *BuildSubAggregate(Value *From, - const unsigned *idx_begin, - const unsigned *idx_end, - Instruction &InsertBefore); - Value *BuildSubAggregate(Value *From, - Value* To, - const Type *IndexedType, - SmallVector &Idxs, - unsigned IdxSkip, - Instruction &InsertBefore); }; } @@ -10533,140 +10518,9 @@ return 0; } -// This is the recursive version of BuildSubAggregate. It takes a few different -// arguments. Idxs is the index within the nested struct From that we are -// looking at now (which is of type IndexedType). IdxSkip is the number of -// indices from Idxs that should be left out when inserting into the resulting -// struct. To is the result struct built so far, new insertvalue instructions -// build on that. -Value *InstCombiner::BuildSubAggregate(Value *From, Value* To, const Type *IndexedType, - SmallVector &Idxs, - unsigned IdxSkip, - Instruction &InsertBefore) { - const llvm::StructType *STy = llvm::dyn_cast(IndexedType); - if (STy) { - // General case, the type indexed by Idxs is a struct - for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { - // Process each struct element recursively - Idxs.push_back(i); - To = BuildSubAggregate(From, To, STy->getElementType(i), Idxs, IdxSkip, InsertBefore); - Idxs.pop_back(); - } - return To; - } else { - // Base case, the type indexed by SourceIdxs is not a struct - // Load the value from the nested struct into the sub struct (and skip - // IdxSkip indices when indexing the sub struct). - Instruction *V = llvm::ExtractValueInst::Create(From, Idxs.begin(), Idxs.end(), "tmp"); - InsertNewInstBefore(V, InsertBefore); - Instruction *Ins = llvm::InsertValueInst::Create(To, V, Idxs.begin() + IdxSkip, Idxs.end(), "tmp"); - InsertNewInstBefore(Ins, InsertBefore); - return Ins; - } -} - -// This helper takes a nested struct and extracts a part of it (which is again a -// struct) into a new value. For example, given the struct: -// { a, { b, { c, d }, e } } -// and the indices "1, 1" this returns -// { c, d }. -// -// It does this by inserting an extractvalue and insertvalue for each element in -// the resulting struct, as opposed to just inserting a single struct. This -// allows for later folding of these individual extractvalue instructions with -// insertvalue instructions that fill the nested struct. -// -// Any inserted instructions are inserted before InsertBefore -Value *InstCombiner::BuildSubAggregate(Value *From, const unsigned *idx_begin, const unsigned *idx_end, Instruction &InsertBefore) { - const Type *IndexedType = ExtractValueInst::getIndexedType(From->getType(), idx_begin, idx_end); - Value *To = UndefValue::get(IndexedType); - SmallVector Idxs(idx_begin, idx_end); - unsigned IdxSkip = Idxs.size(); - - return BuildSubAggregate(From, To, IndexedType, Idxs, IdxSkip, InsertBefore); -} - -/// FindScalarValue - Given an aggregrate and an sequence of indices, see if the -/// scalar value indexed is already around as a register, for example if it were -/// inserted directly into the aggregrate. -Value *InstCombiner::FindScalarValue(Value *V, const unsigned *idx_begin, - const unsigned *idx_end, Instruction &InsertBefore) { - // Nothing to index? Just return V then (this is useful at the end of our - // recursion) - if (idx_begin == idx_end) - return V; - // We have indices, so V should have an indexable type - assert((isa(V->getType()) || isa(V->getType())) - && "Not looking at a struct or array?"); - assert(ExtractValueInst::getIndexedType(V->getType(), idx_begin, idx_end) - && "Invalid indices for type?"); - const CompositeType *PTy = cast(V->getType()); - - if (isa(V)) - return UndefValue::get(ExtractValueInst::getIndexedType(PTy, - idx_begin, - idx_end)); - else if (isa(V)) - return Constant::getNullValue(ExtractValueInst::getIndexedType(PTy, - idx_begin, - idx_end)); - else if (Constant *C = dyn_cast(V)) { - if (isa(C) || isa(C)) - // Recursively process this constant - return FindScalarValue(C->getOperand(*idx_begin), ++idx_begin, idx_end, InsertBefore); - } else if (InsertValueInst *I = dyn_cast(V)) { - // Loop the indices for the insertvalue instruction in parallel with the - // requested indices - const unsigned *req_idx = idx_begin; - for (const unsigned *i = I->idx_begin(), *e = I->idx_end(); i != e; ++i, ++req_idx) { - if (req_idx == idx_end) - // The requested index is a part of a nested aggregate. Handle this - // specially. - return BuildSubAggregate(V, idx_begin, req_idx, InsertBefore); - - // This insert value inserts something else than what we are looking for. - // See if the (aggregrate) value inserted into has the value we are - // looking for, then. - if (*req_idx != *i) - return FindScalarValue(I->getAggregateOperand(), idx_begin, idx_end, InsertBefore); - } - // If we end up here, the indices of the insertvalue match with those - // requested (though possibly only partially). Now we recursively look at - // the inserted value, passing any remaining indices. - return FindScalarValue(I->getInsertedValueOperand(), req_idx, idx_end, InsertBefore); - } else if (ExtractValueInst *I = dyn_cast(V)) { - // If we're extracting a value from an aggregrate that was extracted from - // something else, we can extract from that something else directly instead. - // However, we will need to chain I's indices with the requested indices. - - // Calculate the number of indices required - unsigned size = I->getNumIndices() + (idx_end - idx_begin); - // Allocate some space to put the new indices in - unsigned *new_begin = new unsigned[size]; - // Auto cleanup this array - std::auto_ptr newptr(new_begin); - // Start inserting at the beginning - unsigned *new_end = new_begin; - // Add indices from the extract value instruction - for (const unsigned *i = I->idx_begin(), *e = I->idx_end(); i != e; ++i, ++new_end) - *new_end = *i; - - // Add requested indices - for (const unsigned *i = idx_begin, *e = idx_end; i != e; ++i, ++new_end) - *new_end = *i; - - assert((unsigned)(new_end - new_begin) == size && "Number of indices added not correct?"); - - return FindScalarValue(I->getAggregateOperand(), new_begin, new_end, InsertBefore); - } - // Otherwise, we don't know (such as, extracting from a function return value - // or load instruction) - return 0; -} - Instruction *InstCombiner::visitExtractValueInst(ExtractValueInst &EV) { // See if we are trying to extract a known value. If so, use that instead. - if (Value *Elt = FindScalarValue(EV.getOperand(0), EV.idx_begin(), EV.idx_end(), EV)) + if (Value *Elt = FindInsertedValue(EV.getOperand(0), EV.idx_begin(), EV.idx_end(), EV)) return ReplaceInstUsesWith(EV, Elt); // No changes From matthijs at stdin.nl Mon Jun 16 07:57:37 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Mon, 16 Jun 2008 12:57:37 -0000 Subject: [llvm-commits] [llvm] r52316 - in /llvm/trunk/lib: Analysis/ValueTracking.cpp Transforms/Scalar/InstructionCombining.cpp Message-ID: <200806161257.m5GCvb19015806@zion.cs.uiuc.edu> Author: matthijs Date: Mon Jun 16 07:57:37 2008 New Revision: 52316 URL: http://llvm.org/viewvc/llvm-project?rev=52316&view=rev Log: 80 column fixes. Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=52316&r1=52315&r2=52316&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ValueTracking.cpp (original) +++ llvm/trunk/lib/Analysis/ValueTracking.cpp Mon Jun 16 07:57:37 2008 @@ -771,7 +771,8 @@ for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { // Process each struct element recursively Idxs.push_back(i); - To = BuildSubAggregate(From, To, STy->getElementType(i), Idxs, IdxSkip, InsertBefore); + To = BuildSubAggregate(From, To, STy->getElementType(i), Idxs, IdxSkip, + InsertBefore); Idxs.pop_back(); } return To; @@ -779,8 +780,13 @@ // Base case, the type indexed by SourceIdxs is not a struct // Load the value from the nested struct into the sub struct (and skip // IdxSkip indices when indexing the sub struct). - Instruction *V = llvm::ExtractValueInst::Create(From, Idxs.begin(), Idxs.end(), "tmp", &InsertBefore); - Instruction *Ins = llvm::InsertValueInst::Create(To, V, Idxs.begin() + IdxSkip, Idxs.end(), "tmp", &InsertBefore); + Instruction *V = llvm::ExtractValueInst::Create(From, Idxs.begin(), + Idxs.end(), "tmp", + &InsertBefore); + Instruction *Ins = llvm::InsertValueInst::Create(To, V, + Idxs.begin() + IdxSkip, + Idxs.end(), "tmp", + &InsertBefore); return Ins; } } @@ -797,8 +803,11 @@ // insertvalue instructions that fill the nested struct. // // Any inserted instructions are inserted before InsertBefore -Value *BuildSubAggregate(Value *From, const unsigned *idx_begin, const unsigned *idx_end, Instruction &InsertBefore) { - const Type *IndexedType = ExtractValueInst::getIndexedType(From->getType(), idx_begin, idx_end); +Value *BuildSubAggregate(Value *From, const unsigned *idx_begin, + const unsigned *idx_end, Instruction &InsertBefore) { + const Type *IndexedType = ExtractValueInst::getIndexedType(From->getType(), + idx_begin, + idx_end); Value *To = UndefValue::get(IndexedType); SmallVector Idxs(idx_begin, idx_end); unsigned IdxSkip = Idxs.size(); @@ -806,9 +815,9 @@ return BuildSubAggregate(From, To, IndexedType, Idxs, IdxSkip, InsertBefore); } -/// FindInsertedValue - Given an aggregrate and an sequence of indices, see if the -/// scalar value indexed is already around as a register, for example if it were -/// inserted directly into the aggregrate. +/// FindInsertedValue - Given an aggregrate and an sequence of indices, see if +/// the scalar value indexed is already around as a register, for example if it +/// were inserted directly into the aggregrate. Value *llvm::FindInsertedValue(Value *V, const unsigned *idx_begin, const unsigned *idx_end, Instruction &InsertBefore) { // Nothing to index? Just return V then (this is useful at the end of our @@ -833,12 +842,14 @@ else if (Constant *C = dyn_cast(V)) { if (isa(C) || isa(C)) // Recursively process this constant - return FindInsertedValue(C->getOperand(*idx_begin), ++idx_begin, idx_end, InsertBefore); + return FindInsertedValue(C->getOperand(*idx_begin), ++idx_begin, idx_end, + InsertBefore); } else if (InsertValueInst *I = dyn_cast(V)) { // Loop the indices for the insertvalue instruction in parallel with the // requested indices const unsigned *req_idx = idx_begin; - for (const unsigned *i = I->idx_begin(), *e = I->idx_end(); i != e; ++i, ++req_idx) { + for (const unsigned *i = I->idx_begin(), *e = I->idx_end(); + i != e; ++i, ++req_idx) { if (req_idx == idx_end) // The requested index is a part of a nested aggregate. Handle this // specially. @@ -848,12 +859,14 @@ // See if the (aggregrate) value inserted into has the value we are // looking for, then. if (*req_idx != *i) - return FindInsertedValue(I->getAggregateOperand(), idx_begin, idx_end, InsertBefore); + return FindInsertedValue(I->getAggregateOperand(), idx_begin, idx_end, + InsertBefore); } // If we end up here, the indices of the insertvalue match with those // requested (though possibly only partially). Now we recursively look at // the inserted value, passing any remaining indices. - return FindInsertedValue(I->getInsertedValueOperand(), req_idx, idx_end, InsertBefore); + return FindInsertedValue(I->getInsertedValueOperand(), req_idx, idx_end, + InsertBefore); } else if (ExtractValueInst *I = dyn_cast(V)) { // If we're extracting a value from an aggregrate that was extracted from // something else, we can extract from that something else directly instead. @@ -868,16 +881,19 @@ // Start inserting at the beginning unsigned *new_end = new_begin; // Add indices from the extract value instruction - for (const unsigned *i = I->idx_begin(), *e = I->idx_end(); i != e; ++i, ++new_end) + for (const unsigned *i = I->idx_begin(), *e = I->idx_end(); + i != e; ++i, ++new_end) *new_end = *i; // Add requested indices for (const unsigned *i = idx_begin, *e = idx_end; i != e; ++i, ++new_end) *new_end = *i; - assert((unsigned)(new_end - new_begin) == size && "Number of indices added not correct?"); + assert((unsigned)(new_end - new_begin) == size + && "Number of indices added not correct?"); - return FindInsertedValue(I->getAggregateOperand(), new_begin, new_end, InsertBefore); + return FindInsertedValue(I->getAggregateOperand(), new_begin, new_end, + InsertBefore); } // Otherwise, we don't know (such as, extracting from a function return value // or load instruction) Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=52316&r1=52315&r2=52316&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Mon Jun 16 07:57:37 2008 @@ -10520,7 +10520,8 @@ Instruction *InstCombiner::visitExtractValueInst(ExtractValueInst &EV) { // See if we are trying to extract a known value. If so, use that instead. - if (Value *Elt = FindInsertedValue(EV.getOperand(0), EV.idx_begin(), EV.idx_end(), EV)) + if (Value *Elt = FindInsertedValue(EV.getOperand(0), EV.idx_begin(), + EV.idx_end(), EV)) return ReplaceInstUsesWith(EV, Elt); // No changes From matthijs at stdin.nl Mon Jun 16 08:03:44 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Mon, 16 Jun 2008 13:03:44 -0000 Subject: [llvm-commits] [llvm] r52317 - /llvm/trunk/test/Transforms/InstCombine/extractvalue.ll Message-ID: <200806161303.m5GD3iJq015983@zion.cs.uiuc.edu> Author: matthijs Date: Mon Jun 16 08:03:44 2008 New Revision: 52317 URL: http://llvm.org/viewvc/llvm-project?rev=52317&view=rev Log: Make testcase check for extractvalue instead of extractelement. Modified: llvm/trunk/test/Transforms/InstCombine/extractvalue.ll Modified: llvm/trunk/test/Transforms/InstCombine/extractvalue.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/extractvalue.ll?rev=52317&r1=52316&r2=52317&view=diff ============================================================================== --- llvm/trunk/test/Transforms/InstCombine/extractvalue.ll (original) +++ llvm/trunk/test/Transforms/InstCombine/extractvalue.ll Mon Jun 16 08:03:44 2008 @@ -1,4 +1,4 @@ -; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep extractelement +; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep extractvalue ; Instcombine should fold various combinations of insertvalue and extractvalue ; together From matthijs at stdin.nl Mon Jun 16 08:08:19 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Mon, 16 Jun 2008 15:08:19 +0200 Subject: [llvm-commits] [llvm] r52217 - in /llvm/trunk: lib/Transforms/Scalar/InstructionCombining.cpp test/Transforms/InstCombine/extractvalue.ll In-Reply-To: <314C0D33-E9A2-49BA-A2A4-E2C36C4509D3@apple.com> References: <200806111405.m5BE55rj002564@zion.cs.uiuc.edu> <314C0D33-E9A2-49BA-A2A4-E2C36C4509D3@apple.com> Message-ID: <20080616130819.GL2636@katherina.student.utwente.nl> Hi Dan, > The word "Scalar" here is a little confusing. Not only can it find > vectors (though vectors are scalars, for some uses of the word scalar), > but it also can find aggregates, if the indices don't lead all the way > to a leaf value. How about FindExtractedValue? I did the opposite, I renamed it to FindInsertedValue (since it looks for an insertvalue instruction). Agreed? I've also moved this function to ValueTracking.cpp, since I plan to reuse it in DeadArgElim. > It took me a bit of puzzling to figure out what BuildSubAggregate is > necessary. In many cases, it doesn't materially optimize the code, > since FindScalarValue knows how to dig through chains of > insertvalues and extractvalues, and it doesn't affect SelectionDAG- > using backends. But I think it does help expose portions of > struct values which are unneeded, which may be useful. Yeah, it allows for breaking up nested structs when parts of that struct are used as first class values. I'm currently slightly improving this part of the code, my next commit will have a nice example in the comments. > Here and in a few other places, watch out for going over 80 columns. Woops, fixed now. > It's not permitted to use auto_ptr with arrays, since it uses delete and > not delete[]. Can you change this code to use a SmartVector instead? Hmm, didn't know that. What exactly do you mean by SmartVector? Just std::vector? Does that guarantee that elements are consecutive? Or perhaps SmallVector (I think those will have consecutive elements by definition...) > > --- llvm/trunk/test/Transforms/InstCombine/extractvalue.ll (added) > This should be extractvalue, not extractelement. Woops again, fixed. Gr. Matthijs -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: Digital signature Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080616/2e47fef0/attachment.bin From matthijs at stdin.nl Mon Jun 16 08:13:08 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Mon, 16 Jun 2008 13:13:08 -0000 Subject: [llvm-commits] [llvm] r52318 - in /llvm/trunk: include/llvm/Analysis/ValueTracking.h lib/Analysis/ValueTracking.cpp lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200806161313.m5GDD8Nc016275@zion.cs.uiuc.edu> Author: matthijs Date: Mon Jun 16 08:13:08 2008 New Revision: 52318 URL: http://llvm.org/viewvc/llvm-project?rev=52318&view=rev Log: Pass around Instruction* instead of Instruction& in FindInsertedValue and friends. Modified: llvm/trunk/include/llvm/Analysis/ValueTracking.h llvm/trunk/lib/Analysis/ValueTracking.cpp llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Modified: llvm/trunk/include/llvm/Analysis/ValueTracking.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ValueTracking.h?rev=52318&r1=52317&r2=52318&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/ValueTracking.h (original) +++ llvm/trunk/include/llvm/Analysis/ValueTracking.h Mon Jun 16 08:13:08 2008 @@ -58,7 +58,7 @@ Value *FindInsertedValue(Value *V, const unsigned *idx_begin, const unsigned *idx_end, - Instruction &InsertBefore); + Instruction *InsertBefore); } // end namespace llvm #endif Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=52318&r1=52317&r2=52318&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ValueTracking.cpp (original) +++ llvm/trunk/lib/Analysis/ValueTracking.cpp Mon Jun 16 08:13:08 2008 @@ -764,7 +764,7 @@ Value *BuildSubAggregate(Value *From, Value* To, const Type *IndexedType, SmallVector &Idxs, unsigned IdxSkip, - Instruction &InsertBefore) { + Instruction *InsertBefore) { const llvm::StructType *STy = llvm::dyn_cast(IndexedType); if (STy) { // General case, the type indexed by Idxs is a struct @@ -782,11 +782,11 @@ // IdxSkip indices when indexing the sub struct). Instruction *V = llvm::ExtractValueInst::Create(From, Idxs.begin(), Idxs.end(), "tmp", - &InsertBefore); + InsertBefore); Instruction *Ins = llvm::InsertValueInst::Create(To, V, Idxs.begin() + IdxSkip, Idxs.end(), "tmp", - &InsertBefore); + InsertBefore); return Ins; } } @@ -804,7 +804,7 @@ // // Any inserted instructions are inserted before InsertBefore Value *BuildSubAggregate(Value *From, const unsigned *idx_begin, - const unsigned *idx_end, Instruction &InsertBefore) { + const unsigned *idx_end, Instruction *InsertBefore) { const Type *IndexedType = ExtractValueInst::getIndexedType(From->getType(), idx_begin, idx_end); @@ -819,7 +819,7 @@ /// the scalar value indexed is already around as a register, for example if it /// were inserted directly into the aggregrate. Value *llvm::FindInsertedValue(Value *V, const unsigned *idx_begin, - const unsigned *idx_end, Instruction &InsertBefore) { + const unsigned *idx_end, Instruction *InsertBefore) { // Nothing to index? Just return V then (this is useful at the end of our // recursion) if (idx_begin == idx_end) Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=52318&r1=52317&r2=52318&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Mon Jun 16 08:13:08 2008 @@ -10521,7 +10521,7 @@ Instruction *InstCombiner::visitExtractValueInst(ExtractValueInst &EV) { // See if we are trying to extract a known value. If so, use that instead. if (Value *Elt = FindInsertedValue(EV.getOperand(0), EV.idx_begin(), - EV.idx_end(), EV)) + EV.idx_end(), &EV)) return ReplaceInstUsesWith(EV, Elt); // No changes From matthijs at stdin.nl Mon Jun 16 08:28:31 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Mon, 16 Jun 2008 13:28:31 -0000 Subject: [llvm-commits] [llvm] r52319 - in /llvm/trunk: include/llvm/Analysis/ValueTracking.h lib/Analysis/ValueTracking.cpp Message-ID: <200806161328.m5GDSVWg016729@zion.cs.uiuc.edu> Author: matthijs Date: Mon Jun 16 08:28:31 2008 New Revision: 52319 URL: http://llvm.org/viewvc/llvm-project?rev=52319&view=rev Log: Make the InsertBefore argument to FindInsertedValue optional, so you can find an inserted value without modifying the code. Modified: llvm/trunk/include/llvm/Analysis/ValueTracking.h llvm/trunk/lib/Analysis/ValueTracking.cpp Modified: llvm/trunk/include/llvm/Analysis/ValueTracking.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ValueTracking.h?rev=52319&r1=52318&r2=52319&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/ValueTracking.h (original) +++ llvm/trunk/include/llvm/Analysis/ValueTracking.h Mon Jun 16 08:28:31 2008 @@ -55,10 +55,13 @@ /// FindScalarValue - Given an aggregrate and an sequence of indices, see if the /// scalar value indexed is already around as a register, for example if it were /// inserted directly into the aggregrate. + /// + /// If InsertBefore is not null, this function will duplicate (modified) + /// insertvalues when a part of a nested struct is extracted. Value *FindInsertedValue(Value *V, const unsigned *idx_begin, const unsigned *idx_end, - Instruction *InsertBefore); + Instruction *InsertBefore = 0); } // end namespace llvm #endif Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=52319&r1=52318&r2=52319&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ValueTracking.cpp (original) +++ llvm/trunk/lib/Analysis/ValueTracking.cpp Mon Jun 16 08:28:31 2008 @@ -805,6 +805,7 @@ // Any inserted instructions are inserted before InsertBefore Value *BuildSubAggregate(Value *From, const unsigned *idx_begin, const unsigned *idx_end, Instruction *InsertBefore) { + assert(InsertBefore && "Must have someplace to insert!"); const Type *IndexedType = ExtractValueInst::getIndexedType(From->getType(), idx_begin, idx_end); @@ -851,9 +852,13 @@ for (const unsigned *i = I->idx_begin(), *e = I->idx_end(); i != e; ++i, ++req_idx) { if (req_idx == idx_end) - // The requested index is a part of a nested aggregate. Handle this - // specially. - return BuildSubAggregate(V, idx_begin, req_idx, InsertBefore); + if (InsertBefore) + // The requested index is a part of a nested aggregate. Handle this + // specially. + return BuildSubAggregate(V, idx_begin, req_idx, InsertBefore); + else + // We can't handle this without inserting insertvalues + return 0; // This insert value inserts something else than what we are looking for. // See if the (aggregrate) value inserted into has the value we are From nicolas.geoffray at lip6.fr Mon Jun 16 09:04:24 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 16 Jun 2008 14:04:24 -0000 Subject: [llvm-commits] [vmkit] r52320 - /vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMSystemProperties.cpp Message-ID: <200806161404.m5GE4OOn017888@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jun 16 09:04:24 2008 New Revision: 52320 URL: http://llvm.org/viewvc/llvm-project?rev=52320&view=rev Log: os.version in Java is the OS release for uname. Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMSystemProperties.cpp Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMSystemProperties.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMSystemProperties.cpp?rev=52320&r1=52319&r2=52320&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMSystemProperties.cpp (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMSystemProperties.cpp Mon Jun 16 09:04:24 2008 @@ -37,7 +37,7 @@ uname(&infos); setProperty(vm, prop, "os.name", infos.sysname); setProperty(vm, prop, "os.arch", infos.machine); - setProperty(vm, prop, "os.version", infos.version); + setProperty(vm, prop, "os.version", infos.release); if (!strcmp(infos.machine, "ppc")) { setProperty(vm, prop, "gnu.cpu.endian","big"); } else { From nicolas.geoffray at lip6.fr Mon Jun 16 09:06:12 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 16 Jun 2008 14:06:12 -0000 Subject: [llvm-commits] [vmkit] r52321 - in /vmkit/trunk/lib/JnJVM: Classpath/ClasspathVMClass.cpp VMCore/JavaUpcalls.cpp VMCore/JavaUpcalls.h Message-ID: <200806161406.m5GE6CS2017953@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jun 16 09:06:11 2008 New Revision: 52321 URL: http://llvm.org/viewvc/llvm-project?rev=52321&view=rev Log: Add the getDeclaredAnnotations method, which returns an empty annotation array. This needs to be implemented. Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClass.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaUpcalls.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaUpcalls.h Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClass.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClass.cpp?rev=52321&r1=52320&r2=52321&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClass.cpp (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMClass.cpp Mon Jun 16 09:06:11 2008 @@ -417,4 +417,15 @@ JavaThread::throwException((JavaObject*)throwable); } +JNIEXPORT jobjectArray Java_java_lang_VMClass_getDeclaredAnnotations( +#ifdef NATIVE_JNI +JNIEnv *env, +jclass clazz, +#endif +jclass Cl) { + // TODO implement me + Jnjvm* vm = JavaThread::get()->isolate; + ArrayObject* res = ArrayObject::acons(0, Classpath::constructorArrayAnnotation, vm); + return (jobjectArray)res; +} } Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaUpcalls.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaUpcalls.cpp?rev=52321&r1=52320&r2=52321&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaUpcalls.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaUpcalls.cpp Mon Jun 16 09:06:11 2008 @@ -67,6 +67,7 @@ JavaMethod* Classpath::initConstructor; Class* Classpath::newConstructor; ClassArray* Classpath::constructorArrayClass; +ClassArray* Classpath::constructorArrayAnnotation; JavaField* Classpath::constructorSlot; JavaMethod* Classpath::initMethod; JavaMethod* Classpath::initField; @@ -247,6 +248,9 @@ constructorArrayClass = UPCALL_ARRAY_CLASS(vm, "java/lang/reflect/Constructor", 1); + + constructorArrayAnnotation = + UPCALL_ARRAY_CLASS(vm, "java/lang/annotation/Annotation", 1); constructorSlot = UPCALL_FIELD(vm, "java/lang/reflect/Constructor", "slot", "I", ACC_VIRTUAL); Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaUpcalls.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaUpcalls.h?rev=52321&r1=52320&r2=52321&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaUpcalls.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaUpcalls.h Mon Jun 16 09:06:11 2008 @@ -78,6 +78,7 @@ static JavaMethod* getCallingClassLoader; static JavaMethod* initConstructor; static ClassArray* constructorArrayClass; + static ClassArray* constructorArrayAnnotation; static Class* newConstructor; static JavaField* constructorSlot; static JavaMethod* initMethod; From nicolas.geoffray at lip6.fr Mon Jun 16 09:06:45 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 16 Jun 2008 14:06:45 -0000 Subject: [llvm-commits] [vmkit] r52322 - /vmkit/trunk/lib/JnJVM/Classpath/Classpath.cpp Message-ID: <200806161406.m5GE6jIO017999@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jun 16 09:06:44 2008 New Revision: 52322 URL: http://llvm.org/viewvc/llvm-project?rev=52322&view=rev Log: Implement compareAndSwapInt and compareAndSwapObject. Modified: vmkit/trunk/lib/JnJVM/Classpath/Classpath.cpp Modified: vmkit/trunk/lib/JnJVM/Classpath/Classpath.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/Classpath.cpp?rev=52322&r1=52321&r2=52322&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/Classpath.cpp (original) +++ vmkit/trunk/lib/JnJVM/Classpath/Classpath.cpp Mon Jun 16 09:06:44 2008 @@ -207,4 +207,30 @@ } +JNIEXPORT bool JNICALL Java_sun_misc_Unsafe_compareAndSwapInt( +#ifdef NATIVE_JNI + JNIEnv *env, +#endif + JavaObject* unsafe, JavaObject* obj, jlong offset, jint expect, jint update) { + + jint *ptr; + + ptr = (jint *) (((uint8 *) obj) + offset); + + return __sync_bool_compare_and_swap(ptr, expect, update); +} + +JNIEXPORT bool JNICALL Java_sun_misc_Unsafe_compareAndSwapObject( +#ifdef NATIVE_JNI + JNIEnv *env, +#endif + JavaObject* unsafe, JavaObject* obj, jlong offset, jobject expect, jobject update) { + + jobject *ptr; + + ptr = (jobject *) (((uint8 *) obj) + offset); + + return __sync_bool_compare_and_swap(ptr, expect, update); +} + } From nicolas.geoffray at lip6.fr Mon Jun 16 09:08:20 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 16 Jun 2008 14:08:20 -0000 Subject: [llvm-commits] [vmkit] r52323 - in /vmkit/trunk/lib/JnJVM/VMCore: JavaClass.h JavaMetaJIT.cpp Message-ID: <200806161408.m5GE8KBq018053@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jun 16 09:08:20 2008 New Revision: 52323 URL: http://llvm.org/viewvc/llvm-project?rev=52323&view=rev Log: Meta field accesses allocations require the class to be at least inClinit. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaClass.h vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaClass.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaClass.h?rev=52323&r1=52322&r2=52323&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaClass.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaClass.h Mon Jun 16 09:08:20 2008 @@ -475,14 +475,14 @@ #define GETVIRTUALFIELD(TYPE, TYPE_NAME) \ TYPE getVirtual##TYPE_NAME##Field(JavaObject* obj) { \ - assert(classDef->isReady()); \ + assert(*(classDef->getStatus()) >= inClinit); \ void* ptr = (void*)((uint64)obj + ptrOffset); \ return ((TYPE*)ptr)[0]; \ } #define GETSTATICFIELD(TYPE, TYPE_NAME) \ TYPE getStatic##TYPE_NAME##Field() { \ - assert(classDef->isReady()); \ + assert(*(classDef->getStatus()) >= inClinit); \ JavaObject* obj = classDef->staticInstance(); \ void* ptr = (void*)((uint64)obj + ptrOffset); \ return ((TYPE*)ptr)[0]; \ @@ -490,14 +490,14 @@ #define SETVIRTUALFIELD(TYPE, TYPE_NAME) \ void setVirtual##TYPE_NAME##Field(JavaObject* obj, TYPE val) { \ - assert(classDef->isReady()); \ + assert(*(classDef->getStatus()) >= inClinit); \ void* ptr = (void*)((uint64)obj + ptrOffset); \ ((TYPE*)ptr)[0] = val; \ } #define SETSTATICFIELD(TYPE, TYPE_NAME) \ void setStatic##TYPE_NAME##Field(TYPE val) { \ - assert(classDef->isReady()); \ + assert(*(classDef->getStatus()) >= inClinit); \ JavaObject* obj = classDef->staticInstance(); \ void* ptr = (void*)((uint64)obj + ptrOffset); \ ((TYPE*)ptr)[0] = val; \ Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp?rev=52323&r1=52322&r2=52323&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaMetaJIT.cpp Mon Jun 16 09:08:20 2008 @@ -50,7 +50,7 @@ JavaObject* Class::operator()(Jnjvm* vm) { - assert(isReady()); + assert(*getStatus() >= inClinit); return doNew(vm); } From nicolas.geoffray at lip6.fr Mon Jun 16 09:10:19 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 16 Jun 2008 14:10:19 -0000 Subject: [llvm-commits] [vmkit] r52324 - in /vmkit/trunk/lib/JnJVM/VMCore: JavaClass.cpp JnjvmModule.cpp JnjvmModule.h Message-ID: <200806161410.m5GEAKYG018140@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jun 16 09:10:19 2008 New Revision: 52324 URL: http://llvm.org/viewvc/llvm-project?rev=52324&view=rev Log: When a class is unloaded, remove it from the jnjvm module. Also, add a couple of asserts. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp vmkit/trunk/lib/JnJVM/VMCore/JnjvmModule.cpp vmkit/trunk/lib/JnJVM/VMCore/JnjvmModule.h Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp?rev=52324&r1=52323&r2=52324&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp Mon Jun 16 09:10:19 2008 @@ -82,6 +82,7 @@ void CommonClass::destroyer(size_t sz) { free(display); + isolate->TheModule->removeClass(this); } void Class::destroyer(size_t sz) { @@ -290,7 +291,7 @@ buf->write("static "); else buf->write("virtual "); - ((JavaMethod*)this)->getSignature()->tPrintBuf(buf); + ((JavaField*)this)->getSignature()->tPrintBuf(buf); buf->write(" "); classDef->print(buf); buf->write("::"); Modified: vmkit/trunk/lib/JnJVM/VMCore/JnjvmModule.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JnjvmModule.cpp?rev=52324&r1=52323&r2=52324&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JnjvmModule.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JnjvmModule.cpp Mon Jun 16 09:10:19 2008 @@ -15,6 +15,7 @@ #include "mvm/JIT.h" #include "JavaJIT.h" +#include "JavaThread.h" #include "JavaTypes.h" #include "Jnjvm.h" #include "JnjvmModule.h" @@ -177,8 +178,12 @@ if (meths == cl->virtualMethods.end()) { uint64 size = cl->virtualTableSize; VirtualTable* VT = (VirtualTable*)malloc(size * sizeof(void*)); + if (!VT) JavaThread::get()->isolate->outOfMemoryError(size * sizeof(void*)); if (cl->super) { Class* super = (Class*)cl->super; + assert(cl->virtualTableSize >= cl->super->virtualTableSize && + "Super VT bigger than own VT"); + assert(super->virtualVT && "Super does not have a VT!"); memcpy(VT, super->virtualVT, cl->super->virtualTableSize * sizeof(void*)); } else { memcpy(VT, JavaObject::VT, VT_SIZE); @@ -827,6 +832,38 @@ LCI->getStaticType(); } +void JnjvmModule::removeClass(CommonClass* cl) { + // Lock here because we may be called by a finalizer + // (even if currently single threaded). + llvm::MutexGuard locked(mvm::jit::executionEngine->lock); + classMap.erase(cl); + + for (CommonClass::field_iterator i = cl->virtualFields.begin(), + e = cl->virtualFields.end(); i!= e; ++i) { + JavaField* field = i->second; + fieldMap.erase(field); + } + + for (CommonClass::field_iterator i = cl->staticFields.begin(), + e = cl->staticFields.end(); i!= e; ++i) { + JavaField* field = i->second; + fieldMap.erase(field); + } + + for (CommonClass::method_iterator i = cl->virtualMethods.begin(), + e = cl->virtualMethods.end(); i!= e; ++i) { + JavaMethod* meth = i->second; + methodMap.erase(meth); + } + + for (CommonClass::method_iterator i = cl->staticMethods.begin(), + e = cl->staticMethods.end(); i!= e; ++i) { + JavaMethod* meth = i->second; + methodMap.erase(meth); + } + +} + LLVMCommonClassInfo* JnjvmModule::getClassInfo(CommonClass* cl) { class_iterator CI = classMap.find(cl); if (CI != classMap.end()) { Modified: vmkit/trunk/lib/JnJVM/VMCore/JnjvmModule.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JnjvmModule.h?rev=52324&r1=52323&r2=52324&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JnjvmModule.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JnjvmModule.h Mon Jun 16 09:10:19 2008 @@ -376,6 +376,8 @@ #ifdef SERVICE_VM LLVMServiceInfo* getServiceInfo(ServiceDomain*); #endif + + void removeClass(CommonClass*); explicit JnjvmModule(const std::string &ModuleID); void initialise(); From nicolas.geoffray at lip6.fr Mon Jun 16 09:11:18 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 16 Jun 2008 14:11:18 -0000 Subject: [llvm-commits] [vmkit] r52325 - /vmkit/trunk/lib/JnJVM/VMCore/JnjvmModuleProvider.cpp Message-ID: <200806161411.m5GEBIhQ018183@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jun 16 09:11:18 2008 New Revision: 52325 URL: http://llvm.org/viewvc/llvm-project?rev=52325&view=rev Log: Add asserts when updating a virtual table. Modified: vmkit/trunk/lib/JnJVM/VMCore/JnjvmModuleProvider.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/JnjvmModuleProvider.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JnjvmModuleProvider.cpp?rev=52325&r1=52324&r2=52325&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JnjvmModuleProvider.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JnjvmModuleProvider.cpp Mon Jun 16 09:11:18 2008 @@ -94,6 +94,10 @@ if (isVirtual(meth->access)) { LLVMMethodInfo* LMI = ((JnjvmModule*)TheModule)->getMethodInfo(meth); uint64_t offset = LMI->getOffset()->getZExtValue(); + assert(meth->classDef->isResolved() && "Class not resolved"); + assert(meth->classDef->virtualVT && "Class has no VT"); + assert(meth->classDef->virtualTableSize > offset && + "The method's offset is greater than the virtual table size"); ((void**)meth->classDef->virtualVT)[offset] = val; } From nicolas.geoffray at lip6.fr Mon Jun 16 09:12:28 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 16 Jun 2008 14:12:28 -0000 Subject: [llvm-commits] [vmkit] r52326 - /vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.cpp Message-ID: <200806161412.m5GECSN1018221@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jun 16 09:12:28 2008 New Revision: 52326 URL: http://llvm.org/viewvc/llvm-project?rev=52326&view=rev Log: Fix for buggy Java code in a method where only an exception is thrown, and something should have been returned. Also, use the changeType method when creating arguments. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.cpp?rev=52326&r1=52325&r2=52326&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.cpp Mon Jun 16 09:12:28 2008 @@ -756,6 +756,19 @@ beginSynchronize(); compileOpcodes(&compilingClass->bytes->elements[start], codeLen); + + // Fix a javac(?) bug where a method only throws an exception and des + // not return. + pred_iterator PI = pred_begin(endBlock); + pred_iterator PE = pred_end(endBlock); + if (PI == PE) { + Instruction* I = currentBlock->getTerminator(); + assert(isa(I) && "non terminator before buggy return"); + I->eraseFromParent(); + BranchInst::Create(endBlock, currentBlock); + endNode->addIncoming(Constant::getNullValue(returnType), + currentBlock); + } currentBlock = endBlock; if (isSynchro(compilingMethod->access)) @@ -793,8 +806,8 @@ else llvm::ReturnInst::Create(currentBlock); - pred_iterator PI = pred_begin(endExceptionBlock); - pred_iterator PE = pred_end(endExceptionBlock); + PI = pred_begin(endExceptionBlock); + PE = pred_end(endExceptionBlock); if (PI == PE) { endExceptionBlock->eraseFromParent(); } else { @@ -1346,15 +1359,8 @@ const Type* type = it->get(); if (tmp->getType() != type) { // int8 or int16 - if (type == Type::Int32Ty) { - if (func == AssessorDesc::dChar) { - tmp = new ZExtInst(tmp, type, "", currentBlock); - } else { - tmp = new SExtInst(tmp, type, "", currentBlock); - } - } else { - tmp = new TruncInst(tmp, type, "", currentBlock); - } + convertValue(tmp, type, currentBlock, + func == AssessorDesc::dChar || func == AssessorDesc::dBool); } args[i] = tmp; From nicolas.geoffray at lip6.fr Mon Jun 16 09:13:02 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 16 Jun 2008 14:13:02 -0000 Subject: [llvm-commits] [vmkit] r52327 - /vmkit/trunk/configure.ac Message-ID: <200806161413.m5GED2kZ018274@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jun 16 09:13:01 2008 New Revision: 52327 URL: http://llvm.org/viewvc/llvm-project?rev=52327&view=rev Log: Move to GNU Classpath 0.97.2 Modified: vmkit/trunk/configure.ac Modified: vmkit/trunk/configure.ac URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/configure.ac?rev=52327&r1=52326&r2=52327&view=diff ============================================================================== --- vmkit/trunk/configure.ac (original) +++ vmkit/trunk/configure.ac Mon Jun 16 09:13:01 2008 @@ -252,10 +252,10 @@ dnl ************************************************************************** AC_ARG_WITH(gnu-classpath-version, [AS_HELP_STRING(--with-gnu-classpath-version=something, - [GNU CLASSPATH VERSION (default is '0.97.1')])], + [GNU CLASSPATH VERSION (default is '0.97.2')])], [[gnuclasspathversion=$withval]], - [[ echo Using '0.97.1' as GNU CLASSPATH version. - gnuclasspathversion=0.97.1 + [[ echo Using '0.97.2' as GNU CLASSPATH version. + gnuclasspathversion=0.97.2 ]] ) gnuclasspathversionuvm=`echo $gnuclasspathversion | $SED s/\\\./-/` From matthijs at stdin.nl Mon Jun 16 09:13:47 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Mon, 16 Jun 2008 14:13:47 -0000 Subject: [llvm-commits] [llvm] r52328 - /llvm/trunk/lib/Analysis/ValueTracking.cpp Message-ID: <200806161413.m5GEDlqb018310@zion.cs.uiuc.edu> Author: matthijs Date: Mon Jun 16 09:13:46 2008 New Revision: 52328 URL: http://llvm.org/viewvc/llvm-project?rev=52328&view=rev Log: Make BuildSubAggregate use FindInsertedElement again to prevent it from inserting extractvalues. In particular, this prevents the insertion of extractvalues that can't be folded away later. Also add an example of when this stuff is needed. Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=52328&r1=52327&r2=52328&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ValueTracking.cpp (original) +++ llvm/trunk/lib/Analysis/ValueTracking.cpp Mon Jun 16 09:13:46 2008 @@ -767,28 +767,45 @@ Instruction *InsertBefore) { const llvm::StructType *STy = llvm::dyn_cast(IndexedType); if (STy) { + // Save the original To argument so we can modify it + Value *OrigTo = To; // General case, the type indexed by Idxs is a struct for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { // Process each struct element recursively Idxs.push_back(i); + Value *PrevTo = To; To = BuildSubAggregate(From, To, STy->getElementType(i), Idxs, IdxSkip, InsertBefore); Idxs.pop_back(); + if (!To) { + // Couldn't find any inserted value for this index? Cleanup + while (PrevTo != OrigTo) { + InsertValueInst* Del = cast(PrevTo); + PrevTo = Del->getAggregateOperand(); + Del->eraseFromParent(); + } + // Stop processing elements + break; + } } - return To; - } else { - // Base case, the type indexed by SourceIdxs is not a struct - // Load the value from the nested struct into the sub struct (and skip - // IdxSkip indices when indexing the sub struct). - Instruction *V = llvm::ExtractValueInst::Create(From, Idxs.begin(), - Idxs.end(), "tmp", - InsertBefore); - Instruction *Ins = llvm::InsertValueInst::Create(To, V, - Idxs.begin() + IdxSkip, - Idxs.end(), "tmp", - InsertBefore); - return Ins; + // If we succesfully found a value for each of our subaggregates + if (To) + return To; } + // Base case, the type indexed by SourceIdxs is not a struct, or not all of + // the struct's elements had a value that was inserted directly. In the latter + // case, perhaps we can't determine each of the subelements individually, but + // we might be able to find the complete struct somewhere. + + // Find the value that is at that particular spot + Value *V = FindInsertedValue(From, Idxs.begin(), Idxs.end()); + + if (!V) + return NULL; + + // Insert the value in the new (sub) aggregrate + return llvm::InsertValueInst::Create(To, V, Idxs.begin() + IdxSkip, + Idxs.end(), "tmp", InsertBefore); } // This helper takes a nested struct and extracts a part of it (which is again a @@ -797,12 +814,12 @@ // and the indices "1, 1" this returns // { c, d }. // -// It does this by inserting an extractvalue and insertvalue for each element in -// the resulting struct, as opposed to just inserting a single struct. This -// allows for later folding of these individual extractvalue instructions with -// insertvalue instructions that fill the nested struct. +// It does this by inserting an insertvalue for each element in the resulting +// struct, as opposed to just inserting a single struct. This will only work if +// each of the elements of the substruct are known (ie, inserted into From by an +// insertvalue instruction somewhere). // -// Any inserted instructions are inserted before InsertBefore +// All inserted insertvalue instructions are inserted before InsertBefore Value *BuildSubAggregate(Value *From, const unsigned *idx_begin, const unsigned *idx_end, Instruction *InsertBefore) { assert(InsertBefore && "Must have someplace to insert!"); @@ -819,6 +836,9 @@ /// FindInsertedValue - Given an aggregrate and an sequence of indices, see if /// the scalar value indexed is already around as a register, for example if it /// were inserted directly into the aggregrate. +/// +/// If InsertBefore is not null, this function will duplicate (modified) +/// insertvalues when a part of a nested struct is extracted. Value *llvm::FindInsertedValue(Value *V, const unsigned *idx_begin, const unsigned *idx_end, Instruction *InsertBefore) { // Nothing to index? Just return V then (this is useful at the end of our @@ -853,8 +873,16 @@ i != e; ++i, ++req_idx) { if (req_idx == idx_end) if (InsertBefore) - // The requested index is a part of a nested aggregate. Handle this - // specially. + // The requested index identifies a part of a nested aggregate. Handle + // this specially. For example, + // %A = insertvalue { i32, {i32, i32 } } undef, i32 10, 1, 0 + // %B = insertvalue { i32, {i32, i32 } } %A, i32 11, 1, 1 + // %C = extractvalue {i32, { i32, i32 } } %B, 1 + // This can be changed into + // %A = insertvalue {i32, i32 } undef, i32 10, 0 + // %C = insertvalue {i32, i32 } %A, i32 11, 1 + // which allows the unused 0,0 element from the nested struct to be + // removed. return BuildSubAggregate(V, idx_begin, req_idx, InsertBefore); else // We can't handle this without inserting insertvalues From matthijs at stdin.nl Mon Jun 16 10:37:38 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Mon, 16 Jun 2008 17:37:38 +0200 Subject: [llvm-commits] Dead argument elimination rewrite Message-ID: <20080616153738.GN2636@katherina.student.utwente.nl> Hi all, I set out to improve deadargelim a bit last week, in particular to allow it to look at individual return values instead of just looking at the returned struct as a whole. After some fiddling around with the old code, I decided that the existing structure was really unsuited for adaption, actually I suspect that looking at return values at all was a later hack-on in the first place. So, I ended up rewriting the whole thing. Where the old code used two iterations (one non-recursive and one recursive) to establish liveness, the new code uses only a single iteration, that works non-recursively. The pass now looks properly inside returned structs, but only at the first level (ie, not inside nested structs). I also have a "flatten return values" patch lying around somewhere, which might also become useful for this. Are people interested in this? The pass now also does not look inside functions that use old style multiple return instructions, but gracefully ignores those functions (which does have small regression, since it also does not remove dead arguments on such functions. However, this will be fixed once we stop using the old multiple return instructions). I've also unified the handling of return values and arguments, since essentially they should be processed in the same way. This is done by defining the RetOrArg struct, which can model either a return value or an argument. This also allows for easily putting RetOrArgs into containers. Liveness of values inspected so far is mainly maintained in the LiveValues set. Any value that is clearly live (either because it is used by a RetOrArg that we know to be live already or because it is used by some other instruction) is put into this set. Any value that is "MaybeLive", meaning that is used only as an argument or return value of which we don't know liveness yet, is tracked in the Uses multimap. Or rather, all of its uses are tracked and mapped to the value itself, so whenever a RetOrArg is marked live, any other RetToArg it uses can also be marked live immediately. When all instructions are processed, any values not marked live can be assumed to be dead and will be removed. By using a very explicit mapping between what is dependent on what exactly, the marking should be efficiently (the old code had to re-establish which argument it was supposed to check again, leading to extra looping). I've attached the patch, but since it changes most of the file, I've also attached the new file, which is probably easier to read. The only large part remaining from the old code is DeleteDeadVarargs, which is completely unmodified. Comments are welcome! Gr. Matthijs -------------- next part -------------- A non-text attachment was scrubbed... Name: deadarg.diff Type: text/x-diff Size: 42823 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080616/eb4770d0/attachment.bin -------------- next part -------------- A non-text attachment was scrubbed... Name: DeadArgumentElimination.cpp Type: text/x-c++src Size: 34673 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080616/eb4770d0/attachment-0001.bin -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: Digital signature Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080616/eb4770d0/attachment-0002.bin From gohman at apple.com Mon Jun 16 11:44:08 2008 From: gohman at apple.com (Dan Gohman) Date: Mon, 16 Jun 2008 09:44:08 -0700 (PDT) Subject: [llvm-commits] [llvm] r52217 - in /llvm/trunk: lib/Transforms/Scalar/InstructionCombining.cpp test/Transforms/InstCombine/extractvalue.ll In-Reply-To: <20080616130819.GL2636@katherina.student.utwente.nl> References: <200806111405.m5BE55rj002564@zion.cs.uiuc.edu> <314C0D33-E9A2-49BA-A2A4-E2C36C4509D3@apple.com> <20080616130819.GL2636@katherina.student.utwente.nl> Message-ID: <35990.76.220.41.203.1213634648.squirrel@webmail.apple.com> On Mon, June 16, 2008 6:08 am, Matthijs Kooijman wrote: >> It's not permitted to use auto_ptr with arrays, since it uses delete and >> not delete[]. Can you change this code to use a SmartVector instead? > Hmm, didn't know that. What exactly do you mean by SmartVector? Just > std::vector? Does that guarantee that elements are consecutive? Or perhaps > SmallVector (I think those will have consecutive elements by > definition...) Oops, I meant SmallVector. Both SmallVector and std::vector guarantee their elements are in contiguous memory. Dan From kremenek at apple.com Mon Jun 16 11:54:21 2008 From: kremenek at apple.com (Ted Kremenek) Date: Mon, 16 Jun 2008 09:54:21 -0700 Subject: [llvm-commits] [llvm] r52288 - in /llvm/trunk/lib/System: Path.cpp Unix/Path.inc Win32/Path.inc In-Reply-To: <20080616082329.GI2636@katherina.student.utwente.nl> References: <200806151515.m5FFFJAV025930@zion.cs.uiuc.edu> <20080616073630.GF2636@katherina.student.utwente.nl> <485621DB.8000008@gmail.com> <20080616082329.GI2636@katherina.student.utwente.nl> Message-ID: <513454B8-EF98-4B31-B48C-584A65C92608@apple.com> On Jun 16, 2008, at 1:23 AM, Matthijs Kooijman wrote: > Hi Argiris, > > >> There are a couple of others that are also duplicated, like >> Path::getBasename(). > IMHO code duplication should be prevented as much as possible. You > probably > did well to make things consistent in this case, but perhaps we > should wonder > if we shouldn't prevent all of this duplication. > >> I assumed that the convention is that if a method deals with >> directory >> separators, it is getting into platform implementation details and >> it should >> have separate platform implementations, even if the code turns out >> to be >> identical (currently the Win32 path implementation uses '/' as >> directory >> separator but it could as easily use '\' instead). > Wouldn't it be better to simply make the path separator configurable > (ie, have > a method that returns it?) > > Anyone with a better view of why things are like this that can > comment? I agree with Matthijs: I don't think there is any good reason for the code duplication. The duplication is probably just there because of laziness (I admit that I'm probably one of the culprits). We should definitely refactor the common parts so that the common code gets exercised, tested, and regularly maintained on more machines. From resistor at mac.com Mon Jun 16 11:58:24 2008 From: resistor at mac.com (Owen Anderson) Date: Mon, 16 Jun 2008 16:58:24 -0000 Subject: [llvm-commits] [llvm] r52329 - /llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Message-ID: <200806161658.m5GGwPE3023722@zion.cs.uiuc.edu> Author: resistor Date: Mon Jun 16 11:58:24 2008 New Revision: 52329 URL: http://llvm.org/viewvc/llvm-project?rev=52329&view=rev Log: Re-enable empty block indexing by default, since it doesn't seem to have any impact on code quality or compile time. Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp?rev=52329&r1=52328&r2=52329&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp (original) +++ llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Mon Jun 16 11:58:24 2008 @@ -44,8 +44,6 @@ cl::init(true), cl::Hidden); static cl::opt SplitLimit("split-limit", cl::init(-1), cl::Hidden); -static cl::opt EmptyBBIndex("empty-bb-index", - cl::init(false), cl::Hidden); STATISTIC(numIntervals, "Number of original intervals"); STATISTIC(numIntervalsAfter, "Number of intervals after coalescing"); @@ -102,23 +100,15 @@ i2miMap_.push_back(I); MIIndex += InstrSlots::NUM; } - - // Set the MBB2IdxMap entry for this MBB. - if (!EmptyBBIndex) { - MBB2IdxMap[MBB->getNumber()] = (StartIdx == MIIndex) - ? std::make_pair(StartIdx, StartIdx) // Empty MBB - : std::make_pair(StartIdx, MIIndex - 1); - Idx2MBBMap.push_back(std::make_pair(StartIdx, MBB)); - } else { - if (StartIdx == MIIndex) { - // Empty MBB - MIIndex += InstrSlots::NUM; - i2miMap_.push_back(0); - } - - MBB2IdxMap[MBB->getNumber()] = std::make_pair(StartIdx, MIIndex - 1); - Idx2MBBMap.push_back(std::make_pair(StartIdx, MBB)); + + if (StartIdx == MIIndex) { + // Empty MBB + MIIndex += InstrSlots::NUM; + i2miMap_.push_back(0); } + // Set the MBB2IdxMap entry for this MBB. + MBB2IdxMap[MBB->getNumber()] = std::make_pair(StartIdx, MIIndex - 1); + Idx2MBBMap.push_back(std::make_pair(StartIdx, MBB)); } std::sort(Idx2MBBMap.begin(), Idx2MBBMap.end(), Idx2MBBCompare()); @@ -675,9 +665,7 @@ MIIndex += InstrSlots::NUM; } - if (EmptyBBIndex) { - if (MBB->begin() == miEnd) MIIndex += InstrSlots::NUM; // Empty MBB - } + if (MBB->begin() == miEnd) MIIndex += InstrSlots::NUM; // Empty MBB } } From resistor at mac.com Mon Jun 16 11:59:23 2008 From: resistor at mac.com (Owen Anderson) Date: Mon, 16 Jun 2008 16:59:23 -0000 Subject: [llvm-commits] [test-suite] r52330 - /test-suite/trunk/Makefile.programs Message-ID: <200806161659.m5GGxNYh023790@zion.cs.uiuc.edu> Author: resistor Date: Mon Jun 16 11:59:23 2008 New Revision: 52330 URL: http://llvm.org/viewvc/llvm-project?rev=52330&view=rev Log: Remove empty block indexing from llc-beta. Modified: test-suite/trunk/Makefile.programs Modified: test-suite/trunk/Makefile.programs URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/Makefile.programs?rev=52330&r1=52329&r2=52330&view=diff ============================================================================== --- test-suite/trunk/Makefile.programs (original) +++ test-suite/trunk/Makefile.programs Mon Jun 16 11:59:23 2008 @@ -205,7 +205,7 @@ endif#DISABLE_DIFFS ifeq ($(ARCH),PowerPC) -LLCBETAOPTION := -enable-sinking -empty-bb-index +LLCBETAOPTION := -enable-sinking #-machine-licm #--enable-tail-merge #--enable-ppc-preinc From dalej at apple.com Mon Jun 16 12:03:00 2008 From: dalej at apple.com (Dale Johannesen) Date: Mon, 16 Jun 2008 17:03:00 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r52331 - /llvm-gcc-4.2/trunk/gcc/objc/objc-act.c Message-ID: <200806161703.m5GH30NE023904@zion.cs.uiuc.edu> Author: johannes Date: Mon Jun 16 12:03:00 2008 New Revision: 52331 URL: http://llvm.org/viewvc/llvm-project?rev=52331&view=rev Log: Fix a use-after-free bug in ObjC FE. Modified: llvm-gcc-4.2/trunk/gcc/objc/objc-act.c Modified: llvm-gcc-4.2/trunk/gcc/objc/objc-act.c URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/objc/objc-act.c?rev=52331&r1=52330&r2=52331&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/objc/objc-act.c (original) +++ llvm-gcc-4.2/trunk/gcc/objc/objc-act.c Mon Jun 16 12:03:00 2008 @@ -2383,6 +2383,7 @@ bool hasUnion, bytesSkipped; int num_nibbles = 0; bool first_nibble = true; + tree retval; if (!flag_objc_gc || !implementation_template) return NULL_TREE; @@ -2559,12 +2560,13 @@ } OUTPUT_LAYOUT_BYTE (0); /* null terminate string */ string = obstack_finish (&util_obstack); - obstack_free (&util_obstack, util_firstobj); /* if ivar_layout bitmap is all 1 bits (nothing skipped) then use NULL as final layout. */ - return (strong_ivar_layout && !bytesSkipped) + retval = (strong_ivar_layout && !bytesSkipped) ? NULL_TREE : add_objc_string (get_identifier (string), class_names); + obstack_free (&util_obstack, util_firstobj); + return retval; } /** From sabre at nondot.org Mon Jun 16 12:04:07 2008 From: sabre at nondot.org (Chris Lattner) Date: Mon, 16 Jun 2008 17:04:07 -0000 Subject: [llvm-commits] [llvm] r52332 - /llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp Message-ID: <200806161704.m5GH47CD023948@zion.cs.uiuc.edu> Author: lattner Date: Mon Jun 16 12:04:06 2008 New Revision: 52332 URL: http://llvm.org/viewvc/llvm-project?rev=52332&view=rev Log: Add support for icache invalidation on non-darwin ppc systems. Patch by Gary Benson! Modified: llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp Modified: llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp?rev=52332&r1=52331&r2=52332&view=diff ============================================================================== --- llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp (original) +++ llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp Mon Jun 16 12:04:06 2008 @@ -333,9 +333,26 @@ /// SyncICache - On PPC, the JIT emitted code must be explicitly refetched to /// ensure correct execution. static void SyncICache(const void *Addr, size_t len) { -#if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \ -defined(__APPLE__) +#if defined(__POWERPC__) || defined (__ppc__) || defined(_POWER) + +#ifdef __APPLE__ sys_icache_invalidate(Addr, len); +#elif defined(__GNUC__) + const size_t LineSize = 32; + + const intptr_t Mask = ~(LineSize - 1); + const intptr_t StartLine = ((intptr_t) Addr) & Mask; + const intptr_t EndLine = ((intptr_t) Addr + len + LineSize - 1) & Mask; + + for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize) + asm volatile("dcbf 0, %0" : : "r"(Line)); + asm volatile("sync"); + + for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize) + asm volatile("icbi 0, %0" : : "r"(Line)); + asm volatile("isync"); +#endif + #endif } From nicolas.geoffray at lip6.fr Mon Jun 16 12:09:08 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 16 Jun 2008 17:09:08 -0000 Subject: [llvm-commits] [vmkit] r52333 - in /vmkit/trunk/lib/JnJVM/VMCore: JavaInitialise.cpp JavaIsolate.cpp JavaString.cpp Jnjvm.cpp LockedMap.h VirtualTables.cpp Message-ID: <200806161709.m5GH98tJ024141@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jun 16 12:09:07 2008 New Revision: 52333 URL: http://llvm.org/viewvc/llvm-project?rev=52333&view=rev Log: Dot not GC-allocate strings, since they don't point to GC-allocated memory. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaIsolate.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaString.cpp vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp vmkit/trunk/lib/JnJVM/VMCore/LockedMap.h vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp?rev=52333&r1=52332&r2=52333&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp Mon Jun 16 12:09:07 2008 @@ -48,7 +48,6 @@ INIT(JavaThread); INIT(Jnjvm); INIT(ClassMap); - INIT(StringMap); INIT(StaticInstanceMap); INIT(DelegateeMap); INIT(JavaIsolate); Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaIsolate.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaIsolate.cpp?rev=52333&r1=52332&r2=52333&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaIsolate.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaIsolate.cpp Mon Jun 16 12:09:07 2008 @@ -468,7 +468,7 @@ // We copy so that bootstrap utf8 such as "" are unique isolate->hashUTF8 = new UTF8Map(); bootstrapVM->hashUTF8->copy(isolate->hashUTF8); - isolate->hashStr = vm_new(isolate, StringMap)(); + isolate->hashStr = new StringMap(); isolate->bootstrapClasses = callingVM->bootstrapClasses; isolate->javaTypes = new TypeMap(); isolate->globalRefsLock = mvm::Lock::allocNormal(); @@ -520,7 +520,7 @@ isolate->name = "bootstrapVM"; isolate->appClassLoader = 0; isolate->hashUTF8 = new UTF8Map(); - isolate->hashStr = vm_new(isolate, StringMap)(); + isolate->hashStr = new StringMap(); isolate->bootstrapClasses = vm_new(isolate, ClassMap)(); isolate->jniEnv = &JNI_JNIEnvTable; isolate->javavmEnv = &JNI_JavaVMTable; Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaString.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaString.cpp?rev=52333&r1=52332&r2=52333&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaString.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaString.cpp Mon Jun 16 12:09:07 2008 @@ -17,7 +17,11 @@ JavaString* JavaString::stringDup(const UTF8*& utf8, Jnjvm* vm) { - JavaString* res = (JavaString*)Classpath::newString->doNew(vm); + Class* cl = Classpath::newString; + JavaString* res = (JavaString*)malloc(cl->virtualSize); + ((void**)res)[0] = cl->virtualVT; + res->classOf = cl; + // no need to call the function // Classpath::initString->run(res, utf8, 0, utf8->size, true); res->value = utf8; Modified: vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp?rev=52333&r1=52332&r2=52333&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp Mon Jun 16 12:09:07 2008 @@ -809,6 +809,11 @@ GC->destroy(); delete GC; #endif + + delete hashUTF8; + delete hashStr; + delete javaTypes; + delete globalRefsLock; delete TheModuleProvider; } Modified: vmkit/trunk/lib/JnJVM/VMCore/LockedMap.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/LockedMap.h?rev=52333&r1=52332&r2=52333&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/LockedMap.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/LockedMap.h Mon Jun 16 12:09:07 2008 @@ -116,6 +116,13 @@ lock = mvm::Lock::allocNormal(); } + ~UTF8Map() { + delete lock; + for (iterator i = map.begin(), e = map.end(); i!= e; ++i) { + free((void*)i->second); + } + } + void copy(UTF8Map* newMap) { for (iterator i = map.begin(), e = map.end(); i!= e; ++i) { newMap->map.insert(*i); @@ -134,20 +141,48 @@ ClassMap() { lock = mvm::Lock::allocNormal(); } + + virtual void destroyer(size_t sz) { + delete lock; + } virtual void TRACER; }; -class StringMap : - public LockedMap { +class StringMap { public: - static VirtualTable* VT; + + mvm::Lock* lock; + typedef std::map::iterator iterator; + std::map map; + + typedef JavaString* (*funcCreate)(const UTF8*& V, Jnjvm *vm); StringMap() { - lock = mvm::Lock::allocRecursive(); + lock = mvm::Lock::allocNormal(); } - virtual void TRACER; + ~StringMap() { + delete lock; + for (iterator i = map.begin(), e = map.end(); i!= e; ++i) { + free(i->second); + } + } + + inline JavaString* lookupOrCreate(const UTF8*& V, Jnjvm *vm, funcCreate func) { + lock->lock(); + iterator End = map.end(); + iterator I = map.find(V); + if (I == End) { + JavaString* res = func(V, vm); + map.insert(std::make_pair(V, res)); + lock->unlock(); + return res; + } else { + lock->unlock(); + return I->second; + } + } }; class TypeMap { @@ -175,6 +210,13 @@ lock = mvm::Lock::allocRecursive(); } + ~TypeMap() { + for (iterator i = map.begin(), e = map.end(); i!= e; ++i) { + delete i->second; + } + delete lock; + } + }; class StaticInstanceMap : @@ -192,6 +234,7 @@ for (iterator i = map.begin(), e = map.end(); i!= e; ++i) { delete i->second; } + delete lock; } }; @@ -204,6 +247,10 @@ lock = mvm::Lock::allocNormal(); } + virtual void destroyer(size_t sz) { + delete lock; + } + virtual void TRACER; }; Modified: vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp?rev=52333&r1=52332&r2=52333&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp Mon Jun 16 12:09:07 2008 @@ -45,7 +45,6 @@ INIT(JavaThread); INIT(Jnjvm); INIT(ClassMap); - INIT(StringMap); INIT(StaticInstanceMap); INIT(JavaIsolate); INIT(DelegateeMap); @@ -134,7 +133,6 @@ void Jnjvm::TRACER { appClassLoader->MARK_AND_TRACE; - hashStr->MARK_AND_TRACE; bootstrapClasses->MARK_AND_TRACE; TRACE_VECTOR(JavaObject*, gc_allocator, globalRefs); #ifdef MULTIPLE_VM @@ -154,12 +152,6 @@ } } -void StringMap::TRACER { - for (iterator i = map.begin(), e = map.end(); i!= e; ++i) { - i->second->MARK_AND_TRACE; - } -} - void StaticInstanceMap::TRACER { for (iterator i = map.begin(), e = map.end(); i!= e; ++i) { i->second->second->MARK_AND_TRACE; From sabre at nondot.org Mon Jun 16 12:44:14 2008 From: sabre at nondot.org (Chris Lattner) Date: Mon, 16 Jun 2008 17:44:14 -0000 Subject: [llvm-commits] [llvm] r52335 - in /llvm/trunk: include/llvm/ExecutionEngine/ExecutionEngine.h lib/ExecutionEngine/JIT/Intercept.cpp Message-ID: <200806161744.m5GHiEG8025198@zion.cs.uiuc.edu> Author: lattner Date: Mon Jun 16 12:44:14 2008 New Revision: 52335 URL: http://llvm.org/viewvc/llvm-project?rev=52335&view=rev Log: Add a new flag that disables symbol lookup with dlsym when set. This allows a JIT client to completely control symbol lookup with the LazyFunctionCreator interface. Modified: llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h llvm/trunk/lib/ExecutionEngine/JIT/Intercept.cpp Modified: llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h?rev=52335&r1=52334&r2=52335&view=diff ============================================================================== --- llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h (original) +++ llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h Mon Jun 16 12:44:14 2008 @@ -65,6 +65,7 @@ const TargetData *TD; ExecutionEngineState state; bool LazyCompilationDisabled; + bool SymbolSearchingDisabled; protected: /// Modules - This is a list of ModuleProvider's that we are JIT'ing from. We @@ -243,13 +244,22 @@ } /// DisableLazyCompilation - If called, the JIT will abort if lazy compilation - // is ever attempted. - void DisableLazyCompilation() { - LazyCompilationDisabled = true; + /// is ever attempted. + void DisableLazyCompilation(bool Disabled = true) { + LazyCompilationDisabled = Disabled; } bool isLazyCompilationDisabled() const { return LazyCompilationDisabled; } + /// DisableSymbolSearching - If called, the JIT will not try to lookup unknown + /// symbols with dlsym. A client can still use InstallLazyFunctionCreator to + /// resolve symbols in a custom way. + void DisableSymbolSearching(bool Disabled = true) { + SymbolSearchingDisabled = Disabled; + } + bool isSymbolSearchingDisabled() const { + return SymbolSearchingDisabled; + } /// InstallLazyFunctionCreator - If an unknown function is needed, the Modified: llvm/trunk/lib/ExecutionEngine/JIT/Intercept.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/JIT/Intercept.cpp?rev=52335&r1=52334&r2=52335&view=diff ============================================================================== --- llvm/trunk/lib/ExecutionEngine/JIT/Intercept.cpp (original) +++ llvm/trunk/lib/ExecutionEngine/JIT/Intercept.cpp Mon Jun 16 12:44:14 2008 @@ -91,44 +91,46 @@ /// for resolving library symbols, not code generated symbols. /// void *JIT::getPointerToNamedFunction(const std::string &Name) { - // Check to see if this is one of the functions we want to intercept. Note, - // we cast to intptr_t here to silence a -pedantic warning that complains - // about casting a function pointer to a normal pointer. - if (Name == "exit") return (void*)(intptr_t)&jit_exit; - if (Name == "atexit") return (void*)(intptr_t)&jit_atexit; + if (!isSymbolSearchingDisabled()) { + // Check to see if this is one of the functions we want to intercept. Note, + // we cast to intptr_t here to silence a -pedantic warning that complains + // about casting a function pointer to a normal pointer. + if (Name == "exit") return (void*)(intptr_t)&jit_exit; + if (Name == "atexit") return (void*)(intptr_t)&jit_atexit; - const char *NameStr = Name.c_str(); - // If this is an asm specifier, skip the sentinal. - if (NameStr[0] == 1) ++NameStr; - - // If it's an external function, look it up in the process image... - void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr); - if (Ptr) return Ptr; - - // If it wasn't found and if it starts with an underscore ('_') character, and - // has an asm specifier, try again without the underscore. - if (Name[0] == 1 && NameStr[0] == '_') { - Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1); + const char *NameStr = Name.c_str(); + // If this is an asm specifier, skip the sentinal. + if (NameStr[0] == 1) ++NameStr; + + // If it's an external function, look it up in the process image... + void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr); if (Ptr) return Ptr; - } - - // darwin/ppc adds $LDBLStub suffixes to various symbols like printf. These - // are references to hidden visibility symbols that dlsym cannot resolve. If - // we have one of these, strip off $LDBLStub and try again. + + // If it wasn't found and if it starts with an underscore ('_') character, + // and has an asm specifier, try again without the underscore. + if (Name[0] == 1 && NameStr[0] == '_') { + Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1); + if (Ptr) return Ptr; + } + + // Darwin/PPC adds $LDBLStub suffixes to various symbols like printf. These + // are references to hidden visibility symbols that dlsym cannot resolve. + // If we have one of these, strip off $LDBLStub and try again. #if defined(__APPLE__) && defined(__ppc__) - if (Name.size() > 9 && Name[Name.size()-9] == '$' && - memcmp(&Name[Name.size()-8], "LDBLStub", 8) == 0) { - // First try turning $LDBLStub into $LDBL128. If that fails, strip it off. - // This mirrors logic in libSystemStubs.a. - std::string Prefix = std::string(Name.begin(), Name.end()-9); - if (void *Ptr = getPointerToNamedFunction(Prefix+"$LDBL128")) - return Ptr; - if (void *Ptr = getPointerToNamedFunction(Prefix)) - return Ptr; - } + if (Name.size() > 9 && Name[Name.size()-9] == '$' && + memcmp(&Name[Name.size()-8], "LDBLStub", 8) == 0) { + // First try turning $LDBLStub into $LDBL128. If that fails, strip it off. + // This mirrors logic in libSystemStubs.a. + std::string Prefix = std::string(Name.begin(), Name.end()-9); + if (void *Ptr = getPointerToNamedFunction(Prefix+"$LDBL128")) + return Ptr; + if (void *Ptr = getPointerToNamedFunction(Prefix)) + return Ptr; + } #endif + } - /// If a LazyFunctionCreator is installed, use it to get/create the function. + /// If a LazyFunctionCreator is installed, use it to get/create the function. if (LazyFunctionCreator) if (void *RP = LazyFunctionCreator(Name)) return RP; From sabre at nondot.org Mon Jun 16 13:11:40 2008 From: sabre at nondot.org (Chris Lattner) Date: Mon, 16 Jun 2008 18:11:40 -0000 Subject: [llvm-commits] [llvm] r52338 - /llvm/trunk/lib/Linker/LinkModules.cpp Message-ID: <200806161811.m5GIBekn026009@zion.cs.uiuc.edu> Author: lattner Date: Mon Jun 16 13:11:40 2008 New Revision: 52338 URL: http://llvm.org/viewvc/llvm-project?rev=52338&view=rev Log: simplify RecursiveResolveTypes and ResolveTypes by pulling the naming out of ResolveTypes into the one place that needs it. Modified: llvm/trunk/lib/Linker/LinkModules.cpp Modified: llvm/trunk/lib/Linker/LinkModules.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Linker/LinkModules.cpp?rev=52338&r1=52337&r2=52338&view=diff ============================================================================== --- llvm/trunk/lib/Linker/LinkModules.cpp (original) +++ llvm/trunk/lib/Linker/LinkModules.cpp Mon Jun 16 13:11:40 2008 @@ -52,7 +52,6 @@ // Inputs: // DestTy - The type to which we wish to resolve. // SrcTy - The original type which we want to resolve. -// Name - The name of the type. // // Outputs: // DestST - The symbol table in which the new type should be placed. @@ -62,7 +61,7 @@ // false - No errors. // static bool ResolveTypes(const Type *DestTy, const Type *SrcTy, - TypeSymbolTable *DestST, const std::string &Name) { + TypeSymbolTable *DestST) { if (DestTy == SrcTy) return false; // If already equal, noop // Does the type already exist in the module? @@ -76,8 +75,6 @@ if (DestTy) // Type _is_ in module, just opaque... const_cast(cast(DestTy)) ->refineAbstractTypeTo(SrcTy); - else if (!Name.empty()) - DestST->insert(Name, const_cast(SrcTy)); } return false; } @@ -94,8 +91,7 @@ // are compatible. static bool RecursiveResolveTypesI(const PATypeHolder &DestTy, const PATypeHolder &SrcTy, - TypeSymbolTable *DestST, - const std::string &Name, + TypeSymbolTable *DestST, std::vector > &Pointers) { const Type *SrcTyT = SrcTy.get(); const Type *DestTyT = DestTy.get(); @@ -103,7 +99,7 @@ // If we found our opaque type, resolve it now! if (isa(DestTyT) || isa(SrcTyT)) - return ResolveTypes(DestTyT, SrcTyT, DestST, Name); + return ResolveTypes(DestTyT, SrcTyT, DestST); // Two types cannot be resolved together if they are of different primitive // type. For example, we cannot resolve an int to a float. @@ -125,7 +121,7 @@ return true; for (unsigned i = 0, e = getFT(DestTy)->getNumContainedTypes(); i != e; ++i) if (RecursiveResolveTypesI(getFT(DestTy)->getContainedType(i), - getFT(SrcTy)->getContainedType(i), DestST, "", + getFT(SrcTy)->getContainedType(i), DestST, Pointers)) return true; return false; @@ -135,7 +131,7 @@ getST(SrcTy)->getNumContainedTypes()) return 1; for (unsigned i = 0, e = getST(DestTy)->getNumContainedTypes(); i != e; ++i) if (RecursiveResolveTypesI(getST(DestTy)->getContainedType(i), - getST(SrcTy)->getContainedType(i), DestST, "", + getST(SrcTy)->getContainedType(i), DestST, Pointers)) return true; return false; @@ -145,7 +141,7 @@ const ArrayType *SAT = cast(SrcTy.get()); if (DAT->getNumElements() != SAT->getNumElements()) return true; return RecursiveResolveTypesI(DAT->getElementType(), SAT->getElementType(), - DestST, "", Pointers); + DestST, Pointers); } case Type::PointerTyID: { // If this is a pointer type, check to see if we have already seen it. If @@ -162,7 +158,7 @@ bool Result = RecursiveResolveTypesI(cast(DestTy.get())->getElementType(), cast(SrcTy.get())->getElementType(), - DestST, "", Pointers); + DestST, Pointers); Pointers.pop_back(); return Result; } @@ -172,10 +168,9 @@ static bool RecursiveResolveTypes(const PATypeHolder &DestTy, const PATypeHolder &SrcTy, - TypeSymbolTable *DestST, - const std::string &Name){ + TypeSymbolTable *DestST){ std::vector > PointerTypes; - return RecursiveResolveTypesI(DestTy, SrcTy, DestST, Name, PointerTypes); + return RecursiveResolveTypesI(DestTy, SrcTy, DestST, PointerTypes); } @@ -203,7 +198,9 @@ // Check to see if this type name is already in the dest module... Type *Entry = DestST->lookup(Name); - if (ResolveTypes(Entry, RHS, DestST, Name)) { + if (Entry == 0 && !Name.empty()) + DestST->insert(Name, const_cast(RHS)); + else if (ResolveTypes(Entry, RHS, DestST)) { // They look different, save the types 'till later to resolve. DelayedTypesToResolve.push_back(Name); } @@ -219,7 +216,7 @@ const std::string &Name = DelayedTypesToResolve[i]; Type *T1 = SrcST->lookup(Name); Type *T2 = DestST->lookup(Name); - if (!ResolveTypes(T2, T1, DestST, Name)) { + if (!ResolveTypes(T2, T1, DestST)) { // We are making progress! DelayedTypesToResolve.erase(DelayedTypesToResolve.begin()+i); --i; @@ -235,7 +232,7 @@ PATypeHolder T1(SrcST->lookup(Name)); PATypeHolder T2(DestST->lookup(Name)); - if (!RecursiveResolveTypes(T2, T1, DestST, Name)) { + if (!RecursiveResolveTypes(T2, T1, DestST)) { // We are making progress! DelayedTypesToResolve.erase(DelayedTypesToResolve.begin()+i); @@ -463,7 +460,7 @@ if (DGV && DGV->getType() != SGV->getType()) // If types don't agree due to opaque types, try to resolve them. RecursiveResolveTypes(SGV->getType(), DGV->getType(), - &Dest->getTypeSymbolTable(), ""); + &Dest->getTypeSymbolTable()); } // Check to see if may have to link the global with the alias @@ -472,7 +469,7 @@ if (DGV && DGV->getType() != SGV->getType()) // If types don't agree due to opaque types, try to resolve them. RecursiveResolveTypes(SGV->getType(), DGV->getType(), - &Dest->getTypeSymbolTable(), ""); + &Dest->getTypeSymbolTable()); } if (DGV && DGV->hasInternalLinkage()) @@ -633,7 +630,7 @@ // If types don't agree due to opaque types, try to resolve them. if (DGV && DGV->getType() != SGA->getType()) if (RecursiveResolveTypes(SGA->getType(), DGV->getType(), - &Dest->getTypeSymbolTable(), "")) + &Dest->getTypeSymbolTable())) return Error(Err, "Alias Collision on '" + SGA->getName()+ "': aliases have different types"); } @@ -644,7 +641,7 @@ // If types don't agree due to opaque types, try to resolve them. if (DGV && DGV->getType() != SGA->getType()) if (RecursiveResolveTypes(SGA->getType(), DGV->getType(), - &Dest->getTypeSymbolTable(), "")) + &Dest->getTypeSymbolTable())) return Error(Err, "Alias Collision on '" + SGA->getName()+ "': aliases have different types"); } @@ -655,7 +652,7 @@ // If types don't agree due to opaque types, try to resolve them. if (DGV && DGV->getType() != SGA->getType()) if (RecursiveResolveTypes(SGA->getType(), DGV->getType(), - &Dest->getTypeSymbolTable(), "")) + &Dest->getTypeSymbolTable())) return Error(Err, "Alias Collision on '" + SGA->getName()+ "': aliases have different types"); } @@ -854,7 +851,7 @@ // If types don't agree because of opaque, try to resolve them. if (SF->getType() != DF->getType()) RecursiveResolveTypes(SF->getType(), DF->getType(), - &Dest->getTypeSymbolTable(), ""); + &Dest->getTypeSymbolTable()); // Check visibility, merging if a definition overrides a prototype. if (SF->getVisibility() != DF->getVisibility()) { From evan.cheng at apple.com Mon Jun 16 13:17:09 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 16 Jun 2008 18:17:09 -0000 Subject: [llvm-commits] [llvm] r52339 - /llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Message-ID: <200806161817.m5GIH9Qp026212@zion.cs.uiuc.edu> Author: evancheng Date: Mon Jun 16 13:17:09 2008 New Revision: 52339 URL: http://llvm.org/viewvc/llvm-project?rev=52339&view=rev Log: Iterating over SmallPtrSet is not deterministic. Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=52339&r1=52338&r2=52339&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Mon Jun 16 13:17:09 2008 @@ -136,7 +136,7 @@ /// DeadInsts - Keep track of instructions we may have made dead, so that /// we can remove them after we are done working. - SmallPtrSet DeadInsts; + std::set DeadInsts; /// TLI - Keep a pointer of a TargetLowering to consult for determining /// transformation profitability. @@ -192,7 +192,7 @@ void StrengthReduceStridedIVUsers(const SCEVHandle &Stride, IVUsersOfOneStride &Uses, Loop *L, bool isOnlyStride); - void DeleteTriviallyDeadInstructions(SmallPtrSet &Insts); + void DeleteTriviallyDeadInstructions(std::set &Insts); }; } @@ -226,7 +226,7 @@ /// specified set are trivially dead, delete them and see if this makes any of /// their operands subsequently dead. void LoopStrengthReduce:: -DeleteTriviallyDeadInstructions(SmallPtrSet &Insts) { +DeleteTriviallyDeadInstructions(std::set &Insts) { while (!Insts.empty()) { Instruction *I = *Insts.begin(); Insts.erase(I); @@ -378,7 +378,7 @@ /// should use the post-inc value). static bool IVUseShouldUsePostIncValue(Instruction *User, Instruction *IV, Loop *L, DominatorTree *DT, Pass *P, - SmallPtrSet &DeadInsts){ + std::set &DeadInsts){ // If the user is in the loop, use the preinc value. if (L->contains(User->getParent())) return false; @@ -546,7 +546,7 @@ void RewriteInstructionToUseNewBase(const SCEVHandle &NewBase, Instruction *InsertPt, SCEVExpander &Rewriter, Loop *L, Pass *P, - SmallPtrSet &DeadInsts); + std::set &DeadInsts); Value *InsertCodeForBaseAtPosition(const SCEVHandle &NewBase, SCEVExpander &Rewriter, @@ -612,7 +612,7 @@ void BasedUser::RewriteInstructionToUseNewBase(const SCEVHandle &NewBase, Instruction *NewBasePt, SCEVExpander &Rewriter, Loop *L, Pass *P, - SmallPtrSet &DeadInsts) { + std::set &DeadInsts) { if (!isa(Inst)) { // By default, insert code at the user instruction. BasicBlock::iterator InsertPt = Inst; From sabre at nondot.org Mon Jun 16 13:19:06 2008 From: sabre at nondot.org (Chris Lattner) Date: Mon, 16 Jun 2008 18:19:06 -0000 Subject: [llvm-commits] [llvm] r52340 - /llvm/trunk/lib/Linker/LinkModules.cpp Message-ID: <200806161819.m5GIJ62W026278@zion.cs.uiuc.edu> Author: lattner Date: Mon Jun 16 13:19:05 2008 New Revision: 52340 URL: http://llvm.org/viewvc/llvm-project?rev=52340&view=rev Log: Simplify ResolveTypes by pulling the null case out into the one client that cares and simplifying its control flow. Remove the DestST argument to ResolveTypes and RecursiveResolveTypes* which are dead now. Modified: llvm/trunk/lib/Linker/LinkModules.cpp Modified: llvm/trunk/lib/Linker/LinkModules.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Linker/LinkModules.cpp?rev=52340&r1=52339&r2=52340&view=diff ============================================================================== --- llvm/trunk/lib/Linker/LinkModules.cpp (original) +++ llvm/trunk/lib/Linker/LinkModules.cpp Mon Jun 16 13:19:05 2008 @@ -60,21 +60,17 @@ // true - There is an error and the types cannot yet be linked. // false - No errors. // -static bool ResolveTypes(const Type *DestTy, const Type *SrcTy, - TypeSymbolTable *DestST) { +static bool ResolveTypes(const Type *DestTy, const Type *SrcTy) { if (DestTy == SrcTy) return false; // If already equal, noop + assert(DestTy && SrcTy && "Can't handle null types"); - // Does the type already exist in the module? - if (DestTy && !isa(DestTy)) { // Yup, the type already exists... - if (const OpaqueType *OT = dyn_cast(SrcTy)) { - const_cast(OT)->refineAbstractTypeTo(DestTy); - } else { - return true; // Cannot link types... neither is opaque and not-equal - } - } else { // Type not in dest module. Add it now. - if (DestTy) // Type _is_ in module, just opaque... - const_cast(cast(DestTy)) - ->refineAbstractTypeTo(SrcTy); + if (const OpaqueType *OT = dyn_cast(DestTy)) { + // Type _is_ in module, just opaque... + const_cast(OT)->refineAbstractTypeTo(SrcTy); + } else if (const OpaqueType *OT = dyn_cast(SrcTy)) { + const_cast(OT)->refineAbstractTypeTo(DestTy); + } else { + return true; // Cannot link types... not-equal and neither is opaque. } return false; } @@ -91,7 +87,6 @@ // are compatible. static bool RecursiveResolveTypesI(const PATypeHolder &DestTy, const PATypeHolder &SrcTy, - TypeSymbolTable *DestST, std::vector > &Pointers) { const Type *SrcTyT = SrcTy.get(); const Type *DestTyT = DestTy.get(); @@ -99,7 +94,7 @@ // If we found our opaque type, resolve it now! if (isa(DestTyT) || isa(SrcTyT)) - return ResolveTypes(DestTyT, SrcTyT, DestST); + return ResolveTypes(DestTyT, SrcTyT); // Two types cannot be resolved together if they are of different primitive // type. For example, we cannot resolve an int to a float. @@ -121,8 +116,7 @@ return true; for (unsigned i = 0, e = getFT(DestTy)->getNumContainedTypes(); i != e; ++i) if (RecursiveResolveTypesI(getFT(DestTy)->getContainedType(i), - getFT(SrcTy)->getContainedType(i), DestST, - Pointers)) + getFT(SrcTy)->getContainedType(i), Pointers)) return true; return false; } @@ -131,8 +125,7 @@ getST(SrcTy)->getNumContainedTypes()) return 1; for (unsigned i = 0, e = getST(DestTy)->getNumContainedTypes(); i != e; ++i) if (RecursiveResolveTypesI(getST(DestTy)->getContainedType(i), - getST(SrcTy)->getContainedType(i), DestST, - Pointers)) + getST(SrcTy)->getContainedType(i), Pointers)) return true; return false; } @@ -141,7 +134,7 @@ const ArrayType *SAT = cast(SrcTy.get()); if (DAT->getNumElements() != SAT->getNumElements()) return true; return RecursiveResolveTypesI(DAT->getElementType(), SAT->getElementType(), - DestST, Pointers); + Pointers); } case Type::PointerTyID: { // If this is a pointer type, check to see if we have already seen it. If @@ -158,7 +151,7 @@ bool Result = RecursiveResolveTypesI(cast(DestTy.get())->getElementType(), cast(SrcTy.get())->getElementType(), - DestST, Pointers); + Pointers); Pointers.pop_back(); return Result; } @@ -167,10 +160,9 @@ } static bool RecursiveResolveTypes(const PATypeHolder &DestTy, - const PATypeHolder &SrcTy, - TypeSymbolTable *DestST){ + const PATypeHolder &SrcTy) { std::vector > PointerTypes; - return RecursiveResolveTypesI(DestTy, SrcTy, DestST, PointerTypes); + return RecursiveResolveTypesI(DestTy, SrcTy, PointerTypes); } @@ -195,12 +187,14 @@ const std::string &Name = TI->first; const Type *RHS = TI->second; - // Check to see if this type name is already in the dest module... + // Check to see if this type name is already in the dest module. Type *Entry = DestST->lookup(Name); - if (Entry == 0 && !Name.empty()) - DestST->insert(Name, const_cast(RHS)); - else if (ResolveTypes(Entry, RHS, DestST)) { + // If the name is just in the source module, bring it over to the dest. + if (Entry == 0) { + if (!Name.empty()) + DestST->insert(Name, const_cast(RHS)); + } else if (ResolveTypes(Entry, RHS)) { // They look different, save the types 'till later to resolve. DelayedTypesToResolve.push_back(Name); } @@ -216,7 +210,7 @@ const std::string &Name = DelayedTypesToResolve[i]; Type *T1 = SrcST->lookup(Name); Type *T2 = DestST->lookup(Name); - if (!ResolveTypes(T2, T1, DestST)) { + if (!ResolveTypes(T2, T1)) { // We are making progress! DelayedTypesToResolve.erase(DelayedTypesToResolve.begin()+i); --i; @@ -232,7 +226,7 @@ PATypeHolder T1(SrcST->lookup(Name)); PATypeHolder T2(DestST->lookup(Name)); - if (!RecursiveResolveTypes(T2, T1, DestST)) { + if (!RecursiveResolveTypes(T2, T1)) { // We are making progress! DelayedTypesToResolve.erase(DelayedTypesToResolve.begin()+i); @@ -459,8 +453,7 @@ DGV = Dest->getGlobalVariable(SGV->getName()); if (DGV && DGV->getType() != SGV->getType()) // If types don't agree due to opaque types, try to resolve them. - RecursiveResolveTypes(SGV->getType(), DGV->getType(), - &Dest->getTypeSymbolTable()); + RecursiveResolveTypes(SGV->getType(), DGV->getType()); } // Check to see if may have to link the global with the alias @@ -468,8 +461,7 @@ DGV = Dest->getNamedAlias(SGV->getName()); if (DGV && DGV->getType() != SGV->getType()) // If types don't agree due to opaque types, try to resolve them. - RecursiveResolveTypes(SGV->getType(), DGV->getType(), - &Dest->getTypeSymbolTable()); + RecursiveResolveTypes(SGV->getType(), DGV->getType()); } if (DGV && DGV->hasInternalLinkage()) @@ -629,8 +621,7 @@ // If types don't agree due to opaque types, try to resolve them. if (DGV && DGV->getType() != SGA->getType()) - if (RecursiveResolveTypes(SGA->getType(), DGV->getType(), - &Dest->getTypeSymbolTable())) + if (RecursiveResolveTypes(SGA->getType(), DGV->getType())) return Error(Err, "Alias Collision on '" + SGA->getName()+ "': aliases have different types"); } @@ -640,8 +631,7 @@ // If types don't agree due to opaque types, try to resolve them. if (DGV && DGV->getType() != SGA->getType()) - if (RecursiveResolveTypes(SGA->getType(), DGV->getType(), - &Dest->getTypeSymbolTable())) + if (RecursiveResolveTypes(SGA->getType(), DGV->getType())) return Error(Err, "Alias Collision on '" + SGA->getName()+ "': aliases have different types"); } @@ -651,8 +641,7 @@ // If types don't agree due to opaque types, try to resolve them. if (DGV && DGV->getType() != SGA->getType()) - if (RecursiveResolveTypes(SGA->getType(), DGV->getType(), - &Dest->getTypeSymbolTable())) + if (RecursiveResolveTypes(SGA->getType(), DGV->getType())) return Error(Err, "Alias Collision on '" + SGA->getName()+ "': aliases have different types"); } @@ -850,8 +839,7 @@ // If types don't agree because of opaque, try to resolve them. if (SF->getType() != DF->getType()) - RecursiveResolveTypes(SF->getType(), DF->getType(), - &Dest->getTypeSymbolTable()); + RecursiveResolveTypes(SF->getType(), DF->getType()); // Check visibility, merging if a definition overrides a prototype. if (SF->getVisibility() != DF->getVisibility()) { From clattner at apple.com Mon Jun 16 13:20:35 2008 From: clattner at apple.com (Chris Lattner) Date: Mon, 16 Jun 2008 11:20:35 -0700 Subject: [llvm-commits] [llvm] r52339 - /llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp In-Reply-To: <200806161817.m5GIH9Qp026212@zion.cs.uiuc.edu> References: <200806161817.m5GIH9Qp026212@zion.cs.uiuc.edu> Message-ID: On Jun 16, 2008, at 11:17 AM, Evan Cheng wrote: > Author: evancheng > Date: Mon Jun 16 13:17:09 2008 > New Revision: 52339 > > URL: http://llvm.org/viewvc/llvm-project?rev=52339&view=rev > Log: > Iterating over SmallPtrSet is not deterministic. Neither is iterating over std::set! What is the code trying to do? -Chris > > > Modified: > llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp > > Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=52339&r1=52338&r2=52339&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original) > +++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Mon Jun > 16 13:17:09 2008 > @@ -136,7 +136,7 @@ > > /// DeadInsts - Keep track of instructions we may have made > dead, so that > /// we can remove them after we are done working. > - SmallPtrSet DeadInsts; > + std::set DeadInsts; > > /// TLI - Keep a pointer of a TargetLowering to consult for > determining > /// transformation profitability. > @@ -192,7 +192,7 @@ > void StrengthReduceStridedIVUsers(const SCEVHandle &Stride, > IVUsersOfOneStride &Uses, > Loop *L, bool isOnlyStride); > - void DeleteTriviallyDeadInstructions(SmallPtrSet 16> &Insts); > + void DeleteTriviallyDeadInstructions(std::set > &Insts); > }; > } > > @@ -226,7 +226,7 @@ > /// specified set are trivially dead, delete them and see if this > makes any of > /// their operands subsequently dead. > void LoopStrengthReduce:: > -DeleteTriviallyDeadInstructions(SmallPtrSet > &Insts) { > +DeleteTriviallyDeadInstructions(std::set &Insts) { > while (!Insts.empty()) { > Instruction *I = *Insts.begin(); > Insts.erase(I); > @@ -378,7 +378,7 @@ > /// should use the post-inc value). > static bool IVUseShouldUsePostIncValue(Instruction *User, > Instruction *IV, > Loop *L, DominatorTree *DT, > Pass *P, > - SmallPtrSet > &DeadInsts){ > + std::set > &DeadInsts){ > // If the user is in the loop, use the preinc value. > if (L->contains(User->getParent())) return false; > > @@ -546,7 +546,7 @@ > void RewriteInstructionToUseNewBase(const SCEVHandle &NewBase, > Instruction *InsertPt, > SCEVExpander &Rewriter, Loop > *L, Pass *P, > - SmallPtrSet > &DeadInsts); > + std::set > &DeadInsts); > > Value *InsertCodeForBaseAtPosition(const SCEVHandle &NewBase, > SCEVExpander &Rewriter, > @@ -612,7 +612,7 @@ > void BasedUser::RewriteInstructionToUseNewBase(const SCEVHandle > &NewBase, > Instruction *NewBasePt, > SCEVExpander &Rewriter, Loop > *L, Pass *P, > - SmallPtrSet > &DeadInsts) { > + std::set > &DeadInsts) { > if (!isa(Inst)) { > // By default, insert code at the user instruction. > BasicBlock::iterator InsertPt = Inst; > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From sabre at nondot.org Mon Jun 16 13:27:53 2008 From: sabre at nondot.org (Chris Lattner) Date: Mon, 16 Jun 2008 18:27:53 -0000 Subject: [llvm-commits] [llvm] r52341 - /llvm/trunk/lib/Linker/LinkModules.cpp Message-ID: <200806161827.m5GIRrh7026566@zion.cs.uiuc.edu> Author: lattner Date: Mon Jun 16 13:27:53 2008 New Revision: 52341 URL: http://llvm.org/viewvc/llvm-project?rev=52341&view=rev Log: handle vectors. Any integers that got here would necessarily be different already. Modified: llvm/trunk/lib/Linker/LinkModules.cpp Modified: llvm/trunk/lib/Linker/LinkModules.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Linker/LinkModules.cpp?rev=52341&r1=52340&r2=52341&view=diff ============================================================================== --- llvm/trunk/lib/Linker/LinkModules.cpp (original) +++ llvm/trunk/lib/Linker/LinkModules.cpp Mon Jun 16 13:27:53 2008 @@ -102,12 +102,8 @@ // Otherwise, resolve the used type used by this derived type... switch (DestTyT->getTypeID()) { - case Type::IntegerTyID: { - if (cast(DestTyT)->getBitWidth() != - cast(SrcTyT)->getBitWidth()) - return true; - return false; - } + default: + return true; case Type::FunctionTyID: { if (cast(DestTyT)->isVarArg() != cast(SrcTyT)->isVarArg() || @@ -122,7 +118,8 @@ } case Type::StructTyID: { if (getST(DestTy)->getNumContainedTypes() != - getST(SrcTy)->getNumContainedTypes()) return 1; + getST(SrcTy)->getNumContainedTypes()) + return true; for (unsigned i = 0, e = getST(DestTy)->getNumContainedTypes(); i != e; ++i) if (RecursiveResolveTypesI(getST(DestTy)->getContainedType(i), getST(SrcTy)->getContainedType(i), Pointers)) @@ -136,6 +133,13 @@ return RecursiveResolveTypesI(DAT->getElementType(), SAT->getElementType(), Pointers); } + case Type::VectorTyID: { + const VectorType *DVT = cast(DestTy.get()); + const VectorType *SVT = cast(SrcTy.get()); + if (DVT->getNumElements() != SVT->getNumElements()) return true; + return RecursiveResolveTypesI(DVT->getElementType(), SVT->getElementType(), + Pointers); + } case Type::PointerTyID: { // If this is a pointer type, check to see if we have already seen it. If // so, we are in a recursive branch. Cut off the search now. We cannot use @@ -155,7 +159,6 @@ Pointers.pop_back(); return Result; } - default: assert(0 && "Unexpected type!"); return true; } } From asl at math.spbu.ru Mon Jun 16 13:33:21 2008 From: asl at math.spbu.ru (Anton Korobeynikov) Date: Mon, 16 Jun 2008 18:33:21 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r52342 - /llvm-gcc-4.2/trunk/gcc/genmodes.c Message-ID: <200806161833.m5GIXLcB026911@zion.cs.uiuc.edu> Author: asl Date: Mon Jun 16 13:33:21 2008 New Revision: 52342 URL: http://llvm.org/viewvc/llvm-project?rev=52342&view=rev Log: Workaround broken MS CRT Modified: llvm-gcc-4.2/trunk/gcc/genmodes.c Modified: llvm-gcc-4.2/trunk/gcc/genmodes.c URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/genmodes.c?rev=52342&r1=52341&r2=52342&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/genmodes.c (original) +++ llvm-gcc-4.2/trunk/gcc/genmodes.c Mon Jun 16 13:33:21 2008 @@ -785,11 +785,12 @@ /* Output routines. */ -#define tagged_printf(FMT, ARG, TAG) do { \ - int count_; \ - printf (" " FMT ",%n", ARG, &count_); \ - printf ("%*s/* %s */\n", 27 - count_, "", TAG); \ +/* LLVM LOCAL begin mainline */ +#define tagged_printf(FMT, ARG, TAG) do { \ + int count_ = printf (" " FMT ",", ARG); \ + printf ("%*s/* %s */\n", 27 - count_, "", TAG); \ } while (0) +/* LLVM LOCAL end mainline */ #define print_decl(TYPE, NAME, ASIZE) \ puts ("\nconst " TYPE " " NAME "[" ASIZE "] =\n{"); From gohman at apple.com Mon Jun 16 13:39:22 2008 From: gohman at apple.com (Dan Gohman) Date: Mon, 16 Jun 2008 11:39:22 -0700 Subject: [llvm-commits] [llvm] r52315 - in /llvm/trunk: include/llvm/Analysis/ValueTracking.h lib/Analysis/ValueTracking.cpp lib/Transforms/Scalar/InstructionCombining.cpp In-Reply-To: <200806161248.m5GCmM01015536@zion.cs.uiuc.edu> References: <200806161248.m5GCmM01015536@zion.cs.uiuc.edu> Message-ID: <9AAD6CC3-245D-4E11-85F0-EF126AF6B728@apple.com> Hi Matthijs, On Jun 16, 2008, at 5:48 AM, Matthijs Kooijman wrote: > + /// FindScalarValue - Given an aggregrate and an sequence of > indices, see if the > + /// scalar value indexed is already around as a register, for > example if it were > + /// inserted directly into the aggregrate. > + Value *FindInsertedValue(Value *V, > + const unsigned *idx_begin, > + const unsigned *idx_end, > + Instruction &InsertBefore); Well, there's no insertvalue instruction for a constant or an undef. I thought of the name FindExtractedValue because it returns the value that an extractvalue with the given arguments would extract. But if you prefer FindInsertedValue, please update the comment to mention that it does the useful thing for constants and undefs. Also, the comment here still says FindScalarValue, and it's now over 80 columns. Thanks, Dan From resistor at mac.com Mon Jun 16 14:32:41 2008 From: resistor at mac.com (Owen Anderson) Date: Mon, 16 Jun 2008 19:32:41 -0000 Subject: [llvm-commits] [llvm] r52345 - /llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Message-ID: <200806161932.m5GJWfuA028846@zion.cs.uiuc.edu> Author: resistor Date: Mon Jun 16 14:32:40 2008 New Revision: 52345 URL: http://llvm.org/viewvc/llvm-project?rev=52345&view=rev Log: Remove special case handling of empty MBBs now that we assign indices to them. Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp?rev=52345&r1=52344&r2=52345&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp (original) +++ llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Mon Jun 16 14:32:40 2008 @@ -365,14 +365,11 @@ // live interval. for (unsigned i = 0, e = vi.AliveBlocks.size(); i != e; ++i) { if (vi.AliveBlocks[i]) { - MachineBasicBlock *MBB = mf_->getBlockNumbered(i); - if (!MBB->empty()) { - LiveRange LR(getMBBStartIdx(i), - getInstructionIndex(&MBB->back()) + InstrSlots::NUM, - ValNo); - interval.addRange(LR); - DOUT << " +" << LR; - } + LiveRange LR(getMBBStartIdx(i), + getMBBEndIdx(i), + ValNo); + interval.addRange(LR); + DOUT << " +" << LR; } } From evan.cheng at apple.com Mon Jun 16 14:33:34 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 16 Jun 2008 12:33:34 -0700 Subject: [llvm-commits] [llvm] r52339 - /llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp In-Reply-To: References: <200806161817.m5GIH9Qp026212@zion.cs.uiuc.edu> Message-ID: On Jun 16, 2008, at 11:20 AM, Chris Lattner wrote: > > On Jun 16, 2008, at 11:17 AM, Evan Cheng wrote: > >> Author: evancheng >> Date: Mon Jun 16 13:17:09 2008 >> New Revision: 52339 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=52339&view=rev >> Log: >> Iterating over SmallPtrSet is not deterministic. > > Neither is iterating over std::set! What is the code trying to do? I thought std::set is ordered? It's visiting every "dead instruction" in the set and delete them if possible. It also insert operands of dead instructions into the set. Evan > > > -Chris > >> >> >> Modified: >> llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp >> >> Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=52339&r1=52338&r2=52339&view=diff >> >> = >> = >> = >> = >> = >> = >> = >> = >> = >> ===================================================================== >> --- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp >> (original) >> +++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Mon Jun >> 16 13:17:09 2008 >> @@ -136,7 +136,7 @@ >> >> /// DeadInsts - Keep track of instructions we may have made >> dead, so that >> /// we can remove them after we are done working. >> - SmallPtrSet DeadInsts; >> + std::set DeadInsts; >> >> /// TLI - Keep a pointer of a TargetLowering to consult for >> determining >> /// transformation profitability. >> @@ -192,7 +192,7 @@ >> void StrengthReduceStridedIVUsers(const SCEVHandle &Stride, >> IVUsersOfOneStride &Uses, >> Loop *L, bool isOnlyStride); >> - void DeleteTriviallyDeadInstructions(SmallPtrSet> 16> &Insts); >> + void DeleteTriviallyDeadInstructions(std::set >> &Insts); >> }; >> } >> >> @@ -226,7 +226,7 @@ >> /// specified set are trivially dead, delete them and see if this >> makes any of >> /// their operands subsequently dead. >> void LoopStrengthReduce:: >> -DeleteTriviallyDeadInstructions(SmallPtrSet >> &Insts) { >> +DeleteTriviallyDeadInstructions(std::set &Insts) { >> while (!Insts.empty()) { >> Instruction *I = *Insts.begin(); >> Insts.erase(I); >> @@ -378,7 +378,7 @@ >> /// should use the post-inc value). >> static bool IVUseShouldUsePostIncValue(Instruction *User, >> Instruction *IV, >> Loop *L, DominatorTree *DT, >> Pass *P, >> - SmallPtrSet >> &DeadInsts){ >> + std::set >> &DeadInsts){ >> // If the user is in the loop, use the preinc value. >> if (L->contains(User->getParent())) return false; >> >> @@ -546,7 +546,7 @@ >> void RewriteInstructionToUseNewBase(const SCEVHandle &NewBase, >> Instruction *InsertPt, >> SCEVExpander &Rewriter, Loop >> *L, Pass *P, >> - SmallPtrSet >> &DeadInsts); >> + std::set >> &DeadInsts); >> >> Value *InsertCodeForBaseAtPosition(const SCEVHandle &NewBase, >> SCEVExpander &Rewriter, >> @@ -612,7 +612,7 @@ >> void BasedUser::RewriteInstructionToUseNewBase(const SCEVHandle >> &NewBase, >> Instruction *NewBasePt, >> SCEVExpander &Rewriter, Loop >> *L, Pass *P, >> - SmallPtrSet >> &DeadInsts) { >> + std::set >> &DeadInsts) { >> if (!isa(Inst)) { >> // By default, insert code at the user instruction. >> BasicBlock::iterator InsertPt = Inst; >> >> >> _______________________________________________ >> llvm-commits mailing list >> llvm-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From sabre at nondot.org Mon Jun 16 14:48:09 2008 From: sabre at nondot.org (Chris Lattner) Date: Mon, 16 Jun 2008 19:48:09 -0000 Subject: [llvm-commits] [llvm] r52347 - /llvm/trunk/lib/Linker/LinkModules.cpp Message-ID: <200806161948.m5GJm9p0029416@zion.cs.uiuc.edu> Author: lattner Date: Mon Jun 16 14:48:08 2008 New Revision: 52347 URL: http://llvm.org/viewvc/llvm-project?rev=52347&view=rev Log: Apply a patch from Nathan Keynes, which speeds up llvm-link on the testcases in PR1860 from taking more than 1 hour (when I killed it) to taking 1s. Modified: llvm/trunk/lib/Linker/LinkModules.cpp Modified: llvm/trunk/lib/Linker/LinkModules.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Linker/LinkModules.cpp?rev=52347&r1=52346&r2=52347&view=diff ============================================================================== --- llvm/trunk/lib/Linker/LinkModules.cpp (original) +++ llvm/trunk/lib/Linker/LinkModules.cpp Mon Jun 16 14:48:08 2008 @@ -156,7 +156,6 @@ RecursiveResolveTypesI(cast(DestTy.get())->getElementType(), cast(SrcTy.get())->getElementType(), Pointers); - Pointers.pop_back(); return Result; } } From sabre at nondot.org Mon Jun 16 14:55:40 2008 From: sabre at nondot.org (Chris Lattner) Date: Mon, 16 Jun 2008 19:55:40 -0000 Subject: [llvm-commits] [llvm] r52350 - /llvm/trunk/lib/Linker/LinkModules.cpp Message-ID: <200806161955.m5GJteOP030006@zion.cs.uiuc.edu> Author: lattner Date: Mon Jun 16 14:55:40 2008 New Revision: 52350 URL: http://llvm.org/viewvc/llvm-project?rev=52350&view=rev Log: simplify some code. Modified: llvm/trunk/lib/Linker/LinkModules.cpp Modified: llvm/trunk/lib/Linker/LinkModules.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Linker/LinkModules.cpp?rev=52350&r1=52349&r2=52350&view=diff ============================================================================== --- llvm/trunk/lib/Linker/LinkModules.cpp (original) +++ llvm/trunk/lib/Linker/LinkModules.cpp Mon Jun 16 14:55:40 2008 @@ -75,13 +75,6 @@ return false; } -static const FunctionType *getFT(const PATypeHolder &TH) { - return cast(TH.get()); -} -static const StructType *getST(const PATypeHolder &TH) { - return cast(TH.get()); -} - // RecursiveResolveTypes - This is just like ResolveTypes, except that it // recurses down into derived types, merging the used types if the parent types // are compatible. @@ -105,24 +98,25 @@ default: return true; case Type::FunctionTyID: { - if (cast(DestTyT)->isVarArg() != - cast(SrcTyT)->isVarArg() || - cast(DestTyT)->getNumContainedTypes() != - cast(SrcTyT)->getNumContainedTypes()) + const FunctionType *DstFT = cast(DestTyT); + const FunctionType *SrcFT = cast(SrcTyT); + if (DstFT->isVarArg() != SrcFT->isVarArg() || + DstFT->getNumContainedTypes() != SrcFT->getNumContainedTypes()) return true; - for (unsigned i = 0, e = getFT(DestTy)->getNumContainedTypes(); i != e; ++i) - if (RecursiveResolveTypesI(getFT(DestTy)->getContainedType(i), - getFT(SrcTy)->getContainedType(i), Pointers)) + for (unsigned i = 0, e = DstFT->getNumContainedTypes(); i != e; ++i) + if (RecursiveResolveTypesI(DstFT->getContainedType(i), + SrcFT->getContainedType(i), Pointers)) return true; return false; } case Type::StructTyID: { - if (getST(DestTy)->getNumContainedTypes() != - getST(SrcTy)->getNumContainedTypes()) + const StructType *DstST = cast(DestTyT); + const StructType *SrcST = cast(SrcTyT); + if (DstST->getNumContainedTypes() != SrcST->getNumContainedTypes()) return true; - for (unsigned i = 0, e = getST(DestTy)->getNumContainedTypes(); i != e; ++i) - if (RecursiveResolveTypesI(getST(DestTy)->getContainedType(i), - getST(SrcTy)->getContainedType(i), Pointers)) + for (unsigned i = 0, e = DstST->getNumContainedTypes(); i != e; ++i) + if (RecursiveResolveTypesI(DstST->getContainedType(i), + SrcST->getContainedType(i), Pointers)) return true; return false; } @@ -141,6 +135,12 @@ Pointers); } case Type::PointerTyID: { + const PointerType *DstPT = cast(DestTy.get()); + const PointerType *SrcPT = cast(SrcTy.get()); + + if (DstPT->getAddressSpace() != SrcPT->getAddressSpace()) + return true; + // If this is a pointer type, check to see if we have already seen it. If // so, we are in a recursive branch. Cut off the search now. We cannot use // an associative container for this search, because the type pointers (keys @@ -152,11 +152,8 @@ // Otherwise, add the current pointers to the vector to stop recursion on // this pair. Pointers.push_back(std::make_pair(DestTyT, SrcTyT)); - bool Result = - RecursiveResolveTypesI(cast(DestTy.get())->getElementType(), - cast(SrcTy.get())->getElementType(), - Pointers); - return Result; + return RecursiveResolveTypesI(DstPT->getElementType(), + SrcPT->getElementType(), Pointers); } } } From clattner at apple.com Mon Jun 16 14:59:37 2008 From: clattner at apple.com (Chris Lattner) Date: Mon, 16 Jun 2008 12:59:37 -0700 Subject: [llvm-commits] [llvm] r52339 - /llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp In-Reply-To: References: <200806161817.m5GIH9Qp026212@zion.cs.uiuc.edu> Message-ID: <8AE36F88-83DF-4A14-900D-042D3C5B1C30@apple.com> On Jun 16, 2008, at 12:33 PM, Evan Cheng wrote: > > On Jun 16, 2008, at 11:20 AM, Chris Lattner wrote: > >> >> On Jun 16, 2008, at 11:17 AM, Evan Cheng wrote: >> >>> Author: evancheng >>> Date: Mon Jun 16 13:17:09 2008 >>> New Revision: 52339 >>> >>> URL: http://llvm.org/viewvc/llvm-project?rev=52339&view=rev >>> Log: >>> Iterating over SmallPtrSet is not deterministic. >> >> Neither is iterating over std::set! What is the code trying to do? > > I thought std::set is ordered? It's visiting every "dead instruction" > in the set and delete them if possible. It also insert operands of > dead instructions into the set. It is ordered by the pointer's address, which isn't stable across runs. Maybe you want a SetVector or just a vector? -Chris From sabre at nondot.org Mon Jun 16 15:03:01 2008 From: sabre at nondot.org (Chris Lattner) Date: Mon, 16 Jun 2008 20:03:01 -0000 Subject: [llvm-commits] [llvm] r52351 - /llvm/trunk/lib/Linker/LinkModules.cpp Message-ID: <200806162003.m5GK31ro030446@zion.cs.uiuc.edu> Author: lattner Date: Mon Jun 16 15:03:01 2008 New Revision: 52351 URL: http://llvm.org/viewvc/llvm-project?rev=52351&view=rev Log: bail out sooner if we have two concrete but different types. Modified: llvm/trunk/lib/Linker/LinkModules.cpp Modified: llvm/trunk/lib/Linker/LinkModules.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Linker/LinkModules.cpp?rev=52351&r1=52350&r2=52351&view=diff ============================================================================== --- llvm/trunk/lib/Linker/LinkModules.cpp (original) +++ llvm/trunk/lib/Linker/LinkModules.cpp Mon Jun 16 15:03:01 2008 @@ -93,6 +93,10 @@ // type. For example, we cannot resolve an int to a float. if (DestTyT->getTypeID() != SrcTyT->getTypeID()) return true; + // If neither type is abstract, then they really are just different types. + if (!DestTyT->isAbstract() && !SrcTyT->isAbstract()) + return true; + // Otherwise, resolve the used type used by this derived type... switch (DestTyT->getTypeID()) { default: From evan.cheng at apple.com Mon Jun 16 15:26:05 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 16 Jun 2008 20:26:05 -0000 Subject: [llvm-commits] [llvm] r52352 - /llvm/trunk/lib/Target/X86/X86InstrSSE.td Message-ID: <200806162026.m5GKQ71e031415@zion.cs.uiuc.edu> Author: evancheng Date: Mon Jun 16 15:25:59 2008 New Revision: 52352 URL: http://llvm.org/viewvc/llvm-project?rev=52352&view=rev Log: mpsadbw is commutable. Modified: llvm/trunk/lib/Target/X86/X86InstrSSE.td Modified: llvm/trunk/lib/Target/X86/X86InstrSSE.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrSSE.td?rev=52352&r1=52351&r2=52352&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrSSE.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrSSE.td Mon Jun 16 15:25:59 2008 @@ -3330,7 +3330,7 @@ defm DPPD : SS41I_binop_rmi_int<0x41, "dppd", int_x86_sse41_dppd, 1>; defm MPSADBW : SS41I_binop_rmi_int<0x42, "mpsadbw", - int_x86_sse41_mpsadbw, 0>; + int_x86_sse41_mpsadbw, 1>; /// SS41I_ternary_int - SSE 4.1 ternary operator From evan.cheng at apple.com Mon Jun 16 15:29:39 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 16 Jun 2008 20:29:39 -0000 Subject: [llvm-commits] [llvm] r52353 - in /llvm/trunk: include/llvm/Intrinsics.td include/llvm/IntrinsicsX86.td test/CodeGen/X86/commute-intrinsic.ll utils/TableGen/CodeGenDAGPatterns.cpp utils/TableGen/CodeGenDAGPatterns.h utils/TableGen/CodeGenIntrinsics.h utils/TableGen/CodeGenTarget.cpp Message-ID: <200806162029.m5GKTdpb031546@zion.cs.uiuc.edu> Author: evancheng Date: Mon Jun 16 15:29:38 2008 New Revision: 52353 URL: http://llvm.org/viewvc/llvm-project?rev=52353&view=rev Log: - Add "Commutative" property to intrinsics. This allows tblgen to generate the commuted variants for dagisel matching code. - Mark lots of X86 intrinsics as "Commutative" to allow load folding. Added: llvm/trunk/test/CodeGen/X86/commute-intrinsic.ll Modified: llvm/trunk/include/llvm/Intrinsics.td llvm/trunk/include/llvm/IntrinsicsX86.td llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h llvm/trunk/utils/TableGen/CodeGenIntrinsics.h llvm/trunk/utils/TableGen/CodeGenTarget.cpp Modified: llvm/trunk/include/llvm/Intrinsics.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Intrinsics.td?rev=52353&r1=52352&r2=52353&view=diff ============================================================================== --- llvm/trunk/include/llvm/Intrinsics.td (original) +++ llvm/trunk/include/llvm/Intrinsics.td Mon Jun 16 15:29:38 2008 @@ -48,6 +48,9 @@ // default if the intrinsic has no other Intr*Mem property. def IntrWriteMem : IntrinsicProperty; +// Commutative - This intrinsic is commutative: X op Y == Y op X. +def Commutative : IntrinsicProperty; + //===----------------------------------------------------------------------===// // Types used by intrinsics. //===----------------------------------------------------------------------===// Modified: llvm/trunk/include/llvm/IntrinsicsX86.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IntrinsicsX86.td?rev=52353&r1=52352&r2=52353&view=diff ============================================================================== --- llvm/trunk/include/llvm/IntrinsicsX86.td (original) +++ llvm/trunk/include/llvm/IntrinsicsX86.td Mon Jun 16 15:29:38 2008 @@ -19,13 +19,13 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse_add_ss : GCCBuiltin<"__builtin_ia32_addss">, Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, - llvm_v4f32_ty], [IntrNoMem]>; + llvm_v4f32_ty], [IntrNoMem, Commutative]>; def int_x86_sse_sub_ss : GCCBuiltin<"__builtin_ia32_subss">, Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; def int_x86_sse_mul_ss : GCCBuiltin<"__builtin_ia32_mulss">, Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, - llvm_v4f32_ty], [IntrNoMem]>; + llvm_v4f32_ty], [IntrNoMem, Commutative]>; def int_x86_sse_div_ss : GCCBuiltin<"__builtin_ia32_divss">, Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; @@ -176,13 +176,13 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse2_add_sd : GCCBuiltin<"__builtin_ia32_addsd">, Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, - llvm_v2f64_ty], [IntrNoMem]>; + llvm_v2f64_ty], [IntrNoMem, Commutative]>; def int_x86_sse2_sub_sd : GCCBuiltin<"__builtin_ia32_subsd">, Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; def int_x86_sse2_mul_sd : GCCBuiltin<"__builtin_ia32_mulsd">, Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, - llvm_v2f64_ty], [IntrNoMem]>; + llvm_v2f64_ty], [IntrNoMem, Commutative]>; def int_x86_sse2_div_sd : GCCBuiltin<"__builtin_ia32_divsd">, Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; @@ -256,16 +256,16 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse2_padds_b : GCCBuiltin<"__builtin_ia32_paddsb128">, Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, - llvm_v16i8_ty], [IntrNoMem]>; + llvm_v16i8_ty], [IntrNoMem, Commutative]>; def int_x86_sse2_padds_w : GCCBuiltin<"__builtin_ia32_paddsw128">, Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; + llvm_v8i16_ty], [IntrNoMem, Commutative]>; def int_x86_sse2_paddus_b : GCCBuiltin<"__builtin_ia32_paddusb128">, Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, - llvm_v16i8_ty], [IntrNoMem]>; + llvm_v16i8_ty], [IntrNoMem, Commutative]>; def int_x86_sse2_paddus_w : GCCBuiltin<"__builtin_ia32_paddusw128">, Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; + llvm_v8i16_ty], [IntrNoMem, Commutative]>; def int_x86_sse2_psubs_b : GCCBuiltin<"__builtin_ia32_psubsb128">, Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; @@ -280,37 +280,37 @@ llvm_v8i16_ty], [IntrNoMem]>; def int_x86_sse2_pmulhu_w : GCCBuiltin<"__builtin_ia32_pmulhuw128">, Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; + llvm_v8i16_ty], [IntrNoMem, Commutative]>; def int_x86_sse2_pmulh_w : GCCBuiltin<"__builtin_ia32_pmulhw128">, Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; + llvm_v8i16_ty], [IntrNoMem, Commutative]>; def int_x86_sse2_pmulu_dq : GCCBuiltin<"__builtin_ia32_pmuludq128">, Intrinsic<[llvm_v2i64_ty, llvm_v4i32_ty, - llvm_v4i32_ty], [IntrNoMem]>; + llvm_v4i32_ty], [IntrNoMem, Commutative]>; def int_x86_sse2_pmadd_wd : GCCBuiltin<"__builtin_ia32_pmaddwd128">, Intrinsic<[llvm_v4i32_ty, llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; + llvm_v8i16_ty], [IntrNoMem, Commutative]>; def int_x86_sse2_pavg_b : GCCBuiltin<"__builtin_ia32_pavgb128">, Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, - llvm_v16i8_ty], [IntrNoMem]>; + llvm_v16i8_ty], [IntrNoMem, Commutative]>; def int_x86_sse2_pavg_w : GCCBuiltin<"__builtin_ia32_pavgw128">, Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; + llvm_v8i16_ty], [IntrNoMem, Commutative]>; def int_x86_sse2_pmaxu_b : GCCBuiltin<"__builtin_ia32_pmaxub128">, Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, - llvm_v16i8_ty], [IntrNoMem]>; + llvm_v16i8_ty], [IntrNoMem, Commutative]>; def int_x86_sse2_pmaxs_w : GCCBuiltin<"__builtin_ia32_pmaxsw128">, Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; + llvm_v8i16_ty], [IntrNoMem, Commutative]>; def int_x86_sse2_pminu_b : GCCBuiltin<"__builtin_ia32_pminub128">, Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, - llvm_v16i8_ty], [IntrNoMem]>; + llvm_v16i8_ty], [IntrNoMem, Commutative]>; def int_x86_sse2_pmins_w : GCCBuiltin<"__builtin_ia32_pminsw128">, Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; + llvm_v8i16_ty], [IntrNoMem, Commutative]>; def int_x86_sse2_psad_bw : GCCBuiltin<"__builtin_ia32_psadbw128">, Intrinsic<[llvm_v2i64_ty, llvm_v16i8_ty, - llvm_v16i8_ty], [IntrNoMem]>; + llvm_v16i8_ty], [IntrNoMem, Commutative]>; } // Integer shift ops. @@ -553,24 +553,24 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_ssse3_phadd_w : GCCBuiltin<"__builtin_ia32_phaddw">, Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem]>; + llvm_v4i16_ty], [IntrNoMem, Commutative]>; def int_x86_ssse3_phadd_w_128 : GCCBuiltin<"__builtin_ia32_phaddw128">, Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; + llvm_v8i16_ty], [IntrNoMem, Commutative]>; def int_x86_ssse3_phadd_d : GCCBuiltin<"__builtin_ia32_phaddd">, Intrinsic<[llvm_v2i32_ty, llvm_v2i32_ty, - llvm_v2i32_ty], [IntrNoMem]>; + llvm_v2i32_ty], [IntrNoMem, Commutative]>; def int_x86_ssse3_phadd_d_128 : GCCBuiltin<"__builtin_ia32_phaddd128">, Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, - llvm_v4i32_ty], [IntrNoMem]>; + llvm_v4i32_ty], [IntrNoMem, Commutative]>; def int_x86_ssse3_phadd_sw : GCCBuiltin<"__builtin_ia32_phaddsw">, Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem]>; + llvm_v4i16_ty], [IntrNoMem, Commutative]>; def int_x86_ssse3_phadd_sw_128 : GCCBuiltin<"__builtin_ia32_phaddsw128">, Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, - llvm_v4i32_ty], [IntrNoMem]>; + llvm_v4i32_ty], [IntrNoMem, Commutative]>; def int_x86_ssse3_phsub_w : GCCBuiltin<"__builtin_ia32_phsubw">, Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, @@ -595,17 +595,17 @@ def int_x86_ssse3_pmadd_ub_sw : GCCBuiltin<"__builtin_ia32_pmaddubsw">, Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem]>; + llvm_v4i16_ty], [IntrNoMem, Commutative]>; def int_x86_ssse3_pmadd_ub_sw_128 : GCCBuiltin<"__builtin_ia32_pmaddubsw128">, Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; + llvm_v8i16_ty], [IntrNoMem, Commutative]>; def int_x86_ssse3_pmul_hr_sw : GCCBuiltin<"__builtin_ia32_pmulhrsw">, Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem]>; + llvm_v4i16_ty], [IntrNoMem, Commutative]>; def int_x86_ssse3_pmul_hr_sw_128 : GCCBuiltin<"__builtin_ia32_pmulhrsw128">, Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem]>; + llvm_v8i16_ty], [IntrNoMem, Commutative]>; } // Shuffle ops @@ -692,128 +692,170 @@ // Vector sign and zero extend let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse41_pmovsxbd : GCCBuiltin<"__builtin_ia32_pmovsxbd128">, - Intrinsic<[llvm_v4i32_ty, llvm_v16i8_ty]>; + Intrinsic<[llvm_v4i32_ty, llvm_v16i8_ty], + [IntrNoMem]>; def int_x86_sse41_pmovsxbq : GCCBuiltin<"__builtin_ia32_pmovsxbq128">, - Intrinsic<[llvm_v2i64_ty, llvm_v16i8_ty]>; + Intrinsic<[llvm_v2i64_ty, llvm_v16i8_ty], + [IntrNoMem]>; def int_x86_sse41_pmovsxbw : GCCBuiltin<"__builtin_ia32_pmovsxbw128">, - Intrinsic<[llvm_v8i16_ty, llvm_v16i8_ty]>; + Intrinsic<[llvm_v8i16_ty, llvm_v16i8_ty], + [IntrNoMem]>; def int_x86_sse41_pmovsxdq : GCCBuiltin<"__builtin_ia32_pmovsxdq128">, - Intrinsic<[llvm_v2i64_ty, llvm_v4i32_ty]>; + Intrinsic<[llvm_v2i64_ty, llvm_v4i32_ty], + [IntrNoMem]>; def int_x86_sse41_pmovsxwd : GCCBuiltin<"__builtin_ia32_pmovsxwd128">, - Intrinsic<[llvm_v4i32_ty, llvm_v8i16_ty]>; + Intrinsic<[llvm_v4i32_ty, llvm_v8i16_ty], + [IntrNoMem]>; def int_x86_sse41_pmovsxwq : GCCBuiltin<"__builtin_ia32_pmovsxwq128">, - Intrinsic<[llvm_v2i64_ty, llvm_v8i16_ty]>; + Intrinsic<[llvm_v2i64_ty, llvm_v8i16_ty], + [IntrNoMem]>; def int_x86_sse41_pmovzxbd : GCCBuiltin<"__builtin_ia32_pmovzxbd128">, - Intrinsic<[llvm_v4i32_ty, llvm_v16i8_ty]>; + Intrinsic<[llvm_v4i32_ty, llvm_v16i8_ty], + [IntrNoMem]>; def int_x86_sse41_pmovzxbq : GCCBuiltin<"__builtin_ia32_pmovzxbq128">, - Intrinsic<[llvm_v2i64_ty, llvm_v16i8_ty]>; + Intrinsic<[llvm_v2i64_ty, llvm_v16i8_ty], + [IntrNoMem]>; def int_x86_sse41_pmovzxbw : GCCBuiltin<"__builtin_ia32_pmovzxbw128">, - Intrinsic<[llvm_v8i16_ty, llvm_v16i8_ty]>; + Intrinsic<[llvm_v8i16_ty, llvm_v16i8_ty], + [IntrNoMem]>; def int_x86_sse41_pmovzxdq : GCCBuiltin<"__builtin_ia32_pmovzxdq128">, - Intrinsic<[llvm_v2i64_ty, llvm_v4i32_ty]>; + Intrinsic<[llvm_v2i64_ty, llvm_v4i32_ty], + [IntrNoMem]>; def int_x86_sse41_pmovzxwd : GCCBuiltin<"__builtin_ia32_pmovzxwd128">, - Intrinsic<[llvm_v4i32_ty, llvm_v8i16_ty]>; + Intrinsic<[llvm_v4i32_ty, llvm_v8i16_ty], + [IntrNoMem]>; def int_x86_sse41_pmovzxwq : GCCBuiltin<"__builtin_ia32_pmovzxwq128">, - Intrinsic<[llvm_v2i64_ty, llvm_v8i16_ty]>; + Intrinsic<[llvm_v2i64_ty, llvm_v8i16_ty], + [IntrNoMem]>; } // Vector min element let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse41_phminposuw : GCCBuiltin<"__builtin_ia32_phminposuw128">, - Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty]>; + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; } // Vector compare, min, max let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse41_pcmpeqq : GCCBuiltin<"__builtin_ia32_pcmpeqq">, - Intrinsic<[llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty]>; + Intrinsic<[llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem, Commutative]>; def int_x86_sse41_pmaxsb : GCCBuiltin<"__builtin_ia32_pmaxsb128">, - Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty]>; + Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem, Commutative]>; def int_x86_sse41_pmaxsd : GCCBuiltin<"__builtin_ia32_pmaxsd128">, - Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty]>; + Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem, Commutative]>; def int_x86_sse41_pmaxud : GCCBuiltin<"__builtin_ia32_pmaxud128">, - Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty]>; + Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem, Commutative]>; def int_x86_sse41_pmaxuw : GCCBuiltin<"__builtin_ia32_pmaxuw128">, - Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty]>; + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem, Commutative]>; def int_x86_sse41_pminsb : GCCBuiltin<"__builtin_ia32_pminsb128">, - Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty]>; + Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem, Commutative]>; def int_x86_sse41_pminsd : GCCBuiltin<"__builtin_ia32_pminsd128">, - Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty]>; + Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem, Commutative]>; def int_x86_sse41_pminud : GCCBuiltin<"__builtin_ia32_pminud128">, - Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty]>; + Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem, Commutative]>; def int_x86_sse41_pminuw : GCCBuiltin<"__builtin_ia32_pminuw128">, - Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty]>; + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem, Commutative]>; } // Vector pack let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse41_packusdw : GCCBuiltin<"__builtin_ia32_packusdw128">, - Intrinsic<[llvm_v8i16_ty, llvm_v4i32_ty, llvm_v4i32_ty]>; + Intrinsic<[llvm_v8i16_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; } // Vector multiply let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse41_pmuldq : GCCBuiltin<"__builtin_ia32_pmuldq128">, - Intrinsic<[llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty]>; + Intrinsic<[llvm_v2i64_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem, Commutative]>; def int_x86_sse41_pmulld : GCCBuiltin<"__builtin_ia32_pmulld128">, - Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty]>; + Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem, Commutative]>; } // Vector extract let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse41_pextrb : - Intrinsic<[llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty]>; + Intrinsic<[llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem]>; def int_x86_sse41_pextrd : - Intrinsic<[llvm_i32_ty, llvm_v4i32_ty, llvm_i32_ty]>; + Intrinsic<[llvm_i32_ty, llvm_v4i32_ty, llvm_i32_ty], + [IntrNoMem]>; def int_x86_sse41_pextrq : - Intrinsic<[llvm_i64_ty, llvm_v2i64_ty, llvm_i32_ty]>; + Intrinsic<[llvm_i64_ty, llvm_v2i64_ty, llvm_i32_ty], + [IntrNoMem]>; def int_x86_sse41_extractps : GCCBuiltin<"__builtin_ia32_extractps128">, - Intrinsic<[llvm_i32_ty, llvm_v4f32_ty, llvm_i32_ty]>; + Intrinsic<[llvm_i32_ty, llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem]>; } // Vector insert let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse41_pinsrb : GCCBuiltin<"__builtin_ia32_vec_set_v16qi">, - Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, llvm_i32_ty]>; + Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; def int_x86_sse41_pinsrd : GCCBuiltin<"__builtin_ia32_vec_set_v4si">, - Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty, llvm_i32_ty]>; + Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; def int_x86_sse41_pinsrq : GCCBuiltin<"__builtin_ia32_vec_set_v2di">, - Intrinsic<[llvm_v2i64_ty, llvm_v2i64_ty, llvm_i64_ty, llvm_i32_ty]>; + Intrinsic<[llvm_v2i64_ty, llvm_v2i64_ty, llvm_i64_ty, llvm_i32_ty], + [IntrNoMem]>; def int_x86_sse41_insertps : GCCBuiltin<"__builtin_ia32_insertps128">, - Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty]>; + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem]>; } // Vector blend let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse41_pblendvb : GCCBuiltin<"__builtin_ia32_pblendvb128">, - Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty]>; + Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; def int_x86_sse41_pblendw : GCCBuiltin<"__builtin_ia32_pblendw128">, - Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty]>; + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], + [IntrNoMem]>; def int_x86_sse41_blendpd : GCCBuiltin<"__builtin_ia32_blendpd">, - Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i32_ty]>; + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i32_ty], + [IntrNoMem]>; def int_x86_sse41_blendps : GCCBuiltin<"__builtin_ia32_blendps">, - Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty]>; + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem]>; def int_x86_sse41_blendvpd : GCCBuiltin<"__builtin_ia32_blendvpd">, - Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty]>; + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; def int_x86_sse41_blendvps : GCCBuiltin<"__builtin_ia32_blendvps">, - Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty]>; + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; } // Vector dot product let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse41_dppd : GCCBuiltin<"__builtin_ia32_dppd">, - Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i32_ty]>; + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i32_ty], + [IntrNoMem, Commutative]>; def int_x86_sse41_dpps : GCCBuiltin<"__builtin_ia32_dpps">, - Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty]>; + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem, Commutative]>; } // Vector sum of absolute differences let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse41_mpsadbw : GCCBuiltin<"__builtin_ia32_mpsadbw128">, - Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty]>; + Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem, Commutative]>; } -// Vector sum of absolute differences +// Cacheability support ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse41_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa">, Intrinsic<[llvm_v2i64_ty, llvm_ptr_ty], [IntrReadMem]>; @@ -836,17 +878,17 @@ // Addition def int_x86_mmx_padds_b : GCCBuiltin<"__builtin_ia32_paddsb">, Intrinsic<[llvm_v8i8_ty, llvm_v8i8_ty, - llvm_v8i8_ty], [IntrNoMem]>; + llvm_v8i8_ty], [IntrNoMem, Commutative]>; def int_x86_mmx_padds_w : GCCBuiltin<"__builtin_ia32_paddsw">, Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem]>; + llvm_v4i16_ty], [IntrNoMem, Commutative]>; def int_x86_mmx_paddus_b : GCCBuiltin<"__builtin_ia32_paddusb">, Intrinsic<[llvm_v8i8_ty, llvm_v8i8_ty, - llvm_v8i8_ty], [IntrNoMem]>; + llvm_v8i8_ty], [IntrNoMem, Commutative]>; def int_x86_mmx_paddus_w : GCCBuiltin<"__builtin_ia32_paddusw">, Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem]>; + llvm_v4i16_ty], [IntrNoMem, Commutative]>; // Subtraction def int_x86_mmx_psubs_b : GCCBuiltin<"__builtin_ia32_psubsb">, @@ -866,45 +908,45 @@ // Multiplication def int_x86_mmx_pmulh_w : GCCBuiltin<"__builtin_ia32_pmulhw">, Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem]>; + llvm_v4i16_ty], [IntrNoMem, Commutative]>; def int_x86_mmx_pmulhu_w : GCCBuiltin<"__builtin_ia32_pmulhuw">, Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem]>; + llvm_v4i16_ty], [IntrNoMem, Commutative]>; def int_x86_mmx_pmulu_dq : GCCBuiltin<"__builtin_ia32_pmuludq">, Intrinsic<[llvm_v2i32_ty, llvm_v2i32_ty, - llvm_v2i32_ty], [IntrNoMem]>; + llvm_v2i32_ty], [IntrNoMem, Commutative]>; def int_x86_mmx_pmadd_wd : GCCBuiltin<"__builtin_ia32_pmaddwd">, Intrinsic<[llvm_v2i32_ty, llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem]>; + llvm_v4i16_ty], [IntrNoMem, Commutative]>; // Averages def int_x86_mmx_pavg_b : GCCBuiltin<"__builtin_ia32_pavgb">, Intrinsic<[llvm_v8i8_ty, llvm_v8i8_ty, - llvm_v8i8_ty], [IntrNoMem]>; + llvm_v8i8_ty], [IntrNoMem, Commutative]>; def int_x86_mmx_pavg_w : GCCBuiltin<"__builtin_ia32_pavgw">, Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem]>; + llvm_v4i16_ty], [IntrNoMem, Commutative]>; // Maximum def int_x86_mmx_pmaxu_b : GCCBuiltin<"__builtin_ia32_pmaxub">, Intrinsic<[llvm_v8i8_ty, llvm_v8i8_ty, - llvm_v8i8_ty], [IntrNoMem]>; + llvm_v8i8_ty], [IntrNoMem, Commutative]>; def int_x86_mmx_pmaxs_w : GCCBuiltin<"__builtin_ia32_pmaxsw">, Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem]>; + llvm_v4i16_ty], [IntrNoMem, Commutative]>; // Minimum def int_x86_mmx_pminu_b : GCCBuiltin<"__builtin_ia32_pminub">, Intrinsic<[llvm_v8i8_ty, llvm_v8i8_ty, - llvm_v8i8_ty], [IntrNoMem]>; + llvm_v8i8_ty], [IntrNoMem, Commutative]>; def int_x86_mmx_pmins_w : GCCBuiltin<"__builtin_ia32_pminsw">, Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem]>; + llvm_v4i16_ty], [IntrNoMem, Commutative]>; // Packed sum of absolute differences def int_x86_mmx_psad_bw : GCCBuiltin<"__builtin_ia32_psadbw">, Intrinsic<[llvm_v4i16_ty, llvm_v8i8_ty, - llvm_v8i8_ty], [IntrNoMem]>; + llvm_v8i8_ty], [IntrNoMem, Commutative]>; } // Integer shift ops. Added: llvm/trunk/test/CodeGen/X86/commute-intrinsic.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/commute-intrinsic.ll?rev=52353&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/commute-intrinsic.ll (added) +++ llvm/trunk/test/CodeGen/X86/commute-intrinsic.ll Mon Jun 16 15:29:38 2008 @@ -0,0 +1,15 @@ +; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin -mattr=+sse2 -relocation-model=static | not grep movaps + + at a = external global <2 x i64> ; <<2 x i64>*> [#uses=1] + +define <2 x i64> @madd(<2 x i64> %b) nounwind { +entry: + %tmp2 = load <2 x i64>* @a, align 16 ; <<2 x i64>> [#uses=1] + %tmp6 = bitcast <2 x i64> %b to <8 x i16> ; <<8 x i16>> [#uses=1] + %tmp9 = bitcast <2 x i64> %tmp2 to <8 x i16> ; <<8 x i16>> [#uses=1] + %tmp11 = tail call <4 x i32> @llvm.x86.sse2.pmadd.wd( <8 x i16> %tmp9, <8 x i16> %tmp6 ) nounwind readnone ; <<4 x i32>> [#uses=1] + %tmp14 = bitcast <4 x i32> %tmp11 to <2 x i64> ; <<2 x i64>> [#uses=1] + ret <2 x i64> %tmp14 +} + +declare <4 x i32> @llvm.x86.sse2.pmadd.wd(<8 x i16>, <8 x i16>) nounwind readnone Modified: llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp?rev=52353&r1=52352&r2=52353&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp (original) +++ llvm/trunk/utils/TableGen/CodeGenDAGPatterns.cpp Mon Jun 16 15:29:38 2008 @@ -742,6 +742,15 @@ return &CDP.getIntrinsicInfo(IID); } +/// isCommutativeIntrinsic - Return true if the node corresponds to a +/// commutative intrinsic. +bool +TreePatternNode::isCommutativeIntrinsic(const CodeGenDAGPatterns &CDP) const { + if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) + return Int->isCommutative; + return false; +} + /// ApplyTypeConstraints - Apply all of the type constraints relevent to /// this node and its children in the tree. This returns true if it makes a @@ -999,11 +1008,13 @@ // If this node is a commutative operator, check that the LHS isn't an // immediate. const SDNodeInfo &NodeInfo = CDP.getSDNodeInfo(getOperator()); - if (NodeInfo.hasProperty(SDNPCommutative)) { + bool isCommIntrinsic = isCommutativeIntrinsic(CDP); + if (NodeInfo.hasProperty(SDNPCommutative) || isCommIntrinsic) { // Scan all of the operands of the node and make sure that only the last one // is a constant node, unless the RHS also is. if (!OnlyOnRHSOfCommutative(getChild(getNumChildren()-1))) { - for (unsigned i = 0, e = getNumChildren()-1; i != e; ++i) + bool Skip = isCommIntrinsic ? 1 : 0; // First operand is intrinsic id. + for (unsigned i = Skip, e = getNumChildren()-1; i != e; ++i) if (OnlyOnRHSOfCommutative(getChild(i))) { Reason="Immediate value must be on the RHS of commutative operators!"; return false; @@ -2250,8 +2261,10 @@ CombineChildVariants(N, ChildVariants, OutVariants, CDP, DepVars); // If this node is commutative, consider the commuted order. - if (NodeInfo.hasProperty(SDNPCommutative)) { - assert(N->getNumChildren()==2 &&"Commutative but doesn't have 2 children!"); + bool isCommIntrinsic = N->isCommutativeIntrinsic(CDP); + if (NodeInfo.hasProperty(SDNPCommutative) || isCommIntrinsic) { + assert((N->getNumChildren()==2 || isCommIntrinsic) && + "Commutative but doesn't have 2 children!"); // Don't count children which are actually register references. unsigned NC = 0; for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) { @@ -2265,7 +2278,20 @@ NC++; } // Consider the commuted order. - if (NC == 2) + if (isCommIntrinsic) { + // Commutative intrinsic. First operand is the intrinsic id, 2nd and 3rd + // operands are the commutative operands, and there might be more operands + // after those. + assert(NC >= 3 && + "Commutative intrinsic should have at least 3 childrean!"); + std::vector > Variants; + Variants.push_back(ChildVariants[0]); // Intrinsic id. + Variants.push_back(ChildVariants[2]); + Variants.push_back(ChildVariants[1]); + for (unsigned i = 3; i != NC; ++i) + Variants.push_back(ChildVariants[i]); + CombineChildVariants(N, Variants, OutVariants, CDP, DepVars); + } else if (NC == 2) CombineChildVariants(N, ChildVariants[1], ChildVariants[0], OutVariants, CDP, DepVars); } Modified: llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h?rev=52353&r1=52352&r2=52353&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h (original) +++ llvm/trunk/utils/TableGen/CodeGenDAGPatterns.h Mon Jun 16 15:29:38 2008 @@ -221,6 +221,10 @@ /// getIntrinsicInfo - If this node corresponds to an intrinsic, return the /// CodeGenIntrinsic information for it, otherwise return a null pointer. const CodeGenIntrinsic *getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const; + + /// isCommutativeIntrinsic - Return true if the node is an intrinsic which is + /// marked isCommutative. + bool isCommutativeIntrinsic(const CodeGenDAGPatterns &CDP) const; void print(std::ostream &OS) const; void dump() const; Modified: llvm/trunk/utils/TableGen/CodeGenIntrinsics.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenIntrinsics.h?rev=52353&r1=52352&r2=52353&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/CodeGenIntrinsics.h (original) +++ llvm/trunk/utils/TableGen/CodeGenIntrinsics.h Mon Jun 16 15:29:38 2008 @@ -49,6 +49,10 @@ // types. bool isOverloaded; + // isCommutative - True if the intrinsic is commutative. + // + bool isCommutative; + CodeGenIntrinsic(Record *R); }; Modified: llvm/trunk/utils/TableGen/CodeGenTarget.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenTarget.cpp?rev=52353&r1=52352&r2=52353&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/CodeGenTarget.cpp (original) +++ llvm/trunk/utils/TableGen/CodeGenTarget.cpp Mon Jun 16 15:29:38 2008 @@ -404,6 +404,7 @@ std::string DefName = R->getName(); ModRef = WriteMem; isOverloaded = false; + isCommutative = false; if (DefName.size() <= 4 || std::string(DefName.begin(), DefName.begin()+4) != "int_") @@ -469,6 +470,8 @@ ModRef = WriteArgMem; else if (Property->getName() == "IntrWriteMem") ModRef = WriteMem; + else if (Property->getName() == "Commutative") + isCommutative = true; else assert(0 && "Unknown property!"); } From gohman at apple.com Mon Jun 16 15:53:14 2008 From: gohman at apple.com (Dan Gohman) Date: Mon, 16 Jun 2008 13:53:14 -0700 Subject: [llvm-commits] [llvm] r52353 - in /llvm/trunk: include/llvm/Intrinsics.td include/llvm/IntrinsicsX86.td test/CodeGen/X86/commute-intrinsic.ll utils/TableGen/CodeGenDAGPatterns.cpp utils/TableGen/CodeGenDAGPatterns.h utils/TableGen/CodeGenIntrinsics.h utils/TableGen/CodeGenTarget.cpp In-Reply-To: <200806162029.m5GKTdpb031546@zion.cs.uiuc.edu> References: <200806162029.m5GKTdpb031546@zion.cs.uiuc.edu> Message-ID: On Jun 16, 2008, at 1:29 PM, Evan Cheng wrote: > // Integer shift ops. > @@ -553,24 +553,24 @@ > let TargetPrefix = "x86" in { // All intrinsics start with > "llvm.x86.". > def int_x86_ssse3_phadd_w : > GCCBuiltin<"__builtin_ia32_phaddw">, > Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, > - llvm_v4i16_ty], [IntrNoMem]>; > + llvm_v4i16_ty], [IntrNoMem, Commutative]>; > def int_x86_ssse3_phadd_w_128 : > GCCBuiltin<"__builtin_ia32_phaddw128">, > Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, > - llvm_v8i16_ty], [IntrNoMem]>; > + llvm_v8i16_ty], [IntrNoMem, Commutative]>; > > def int_x86_ssse3_phadd_d : > GCCBuiltin<"__builtin_ia32_phaddd">, > Intrinsic<[llvm_v2i32_ty, llvm_v2i32_ty, > - llvm_v2i32_ty], [IntrNoMem]>; > + llvm_v2i32_ty], [IntrNoMem, Commutative]>; > def int_x86_ssse3_phadd_d_128 : > GCCBuiltin<"__builtin_ia32_phaddd128">, > Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, > - llvm_v4i32_ty], [IntrNoMem]>; > + llvm_v4i32_ty], [IntrNoMem, Commutative]>; > > def int_x86_ssse3_phadd_sw : > GCCBuiltin<"__builtin_ia32_phaddsw">, > Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, > - llvm_v4i16_ty], [IntrNoMem]>; > + llvm_v4i16_ty], [IntrNoMem, Commutative]>; > def int_x86_ssse3_phadd_sw_128 : > GCCBuiltin<"__builtin_ia32_phaddsw128">, > Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, > - llvm_v4i32_ty], [IntrNoMem]>; > + llvm_v4i32_ty], [IntrNoMem, Commutative]>; Hi Evan, Horizontal-add instructions are not commutative. It looks like X86InstrSSE.td is mistaken about this too. Dan From nicolas.geoffray at lip6.fr Mon Jun 16 15:58:22 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 16 Jun 2008 20:58:22 -0000 Subject: [llvm-commits] [vmkit] r52355 - /vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMField.cpp Message-ID: <200806162058.m5GKwMeK032562@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jun 16 15:58:22 2008 New Revision: 52355 URL: http://llvm.org/viewvc/llvm-project?rev=52355&view=rev Log: Typo in setCharField. Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMField.cpp Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMField.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMField.cpp?rev=52355&r1=52354&r2=52355&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMField.cpp (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathVMField.cpp Mon Jun 16 15:58:22 2008 @@ -526,7 +526,7 @@ switch (ass->numId) { case CHAR_ID : return isStatic(field->access) ? - field->setStaticInt16Field((double)val) : + field->setStaticInt16Field((uint16)val) : field->setVirtualDoubleField((JavaObject*)obj, (uint16)val); case INT_ID : return isStatic(field->access) ? From nicolas.geoffray at lip6.fr Mon Jun 16 15:58:59 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 16 Jun 2008 20:58:59 -0000 Subject: [llvm-commits] [vmkit] r52356 - /vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp Message-ID: <200806162058.m5GKwx2g032588@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jun 16 15:58:59 2008 New Revision: 52356 URL: http://llvm.org/viewvc/llvm-project?rev=52356&view=rev Log: Add include. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp?rev=52356&r1=52355&r2=52356&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaRuntimeJIT.cpp Mon Jun 16 15:58:59 2008 @@ -8,6 +8,8 @@ // //===----------------------------------------------------------------------===// +#include + #include "mvm/JIT.h" #include "mvm/Threads/Thread.h" From sabre at nondot.org Mon Jun 16 16:00:18 2008 From: sabre at nondot.org (Chris Lattner) Date: Mon, 16 Jun 2008 21:00:18 -0000 Subject: [llvm-commits] [llvm] r52357 - /llvm/trunk/lib/Linker/LinkModules.cpp Message-ID: <200806162100.m5GL0JHZ032645@zion.cs.uiuc.edu> Author: lattner Date: Mon Jun 16 16:00:18 2008 New Revision: 52357 URL: http://llvm.org/viewvc/llvm-project?rev=52357&view=rev Log: use a real associative container for type association instead of using a vector with a linear search. This speeds up the linking testcase in PR1860 from 0.965s to 0.385s on my system. Modified: llvm/trunk/lib/Linker/LinkModules.cpp Modified: llvm/trunk/lib/Linker/LinkModules.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Linker/LinkModules.cpp?rev=52357&r1=52356&r2=52357&view=diff ============================================================================== --- llvm/trunk/lib/Linker/LinkModules.cpp (original) +++ llvm/trunk/lib/Linker/LinkModules.cpp Mon Jun 16 16:00:18 2008 @@ -26,6 +26,7 @@ #include "llvm/Assembly/Writer.h" #include "llvm/Support/Streams.h" #include "llvm/System/Path.h" +#include "llvm/ADT/DenseMap.h" #include using namespace llvm; @@ -75,12 +76,90 @@ return false; } +/// LinkerTypeMap - This implements a map of types that is stable +/// even if types are resolved/refined to other types. This is not a general +/// purpose map, it is specific to the linker's use. +namespace { +class LinkerTypeMap : public AbstractTypeUser { + typedef DenseMap TheMapTy; + TheMapTy TheMap; +public: + + LinkerTypeMap() { + for (DenseMap::iterator I = TheMap.begin(), + E = TheMap.end(); I != E; ++I) + I->first->removeAbstractTypeUser(this); + } + + /// lookup - Return the value for the specified type or null if it doesn't + /// exist. + const Type *lookup(const Type *Ty) const { + TheMapTy::const_iterator I = TheMap.find(Ty); + if (I != TheMap.end()) return I->second; + return 0; + } + + /// erase - Remove the specified type, returning true if it was in the set. + bool erase(const Type *Ty) { + if (!TheMap.erase(Ty)) + return false; + if (Ty->isAbstract()) + Ty->removeAbstractTypeUser(this); + return true; + } + + /// insert - This returns true if the pointer was new to the set, false if it + /// was already in the set. + bool insert(const Type *Src, const Type *Dst) { + if (!TheMap.insert(std::make_pair(Src, PATypeHolder(Dst)))) + return false; // Already in map. + if (Src->isAbstract()) + Src->addAbstractTypeUser(this); + return true; + } + +protected: + /// refineAbstractType - The callback method invoked when an abstract type is + /// resolved to another type. An object must override this method to update + /// its internal state to reference NewType instead of OldType. + /// + virtual void refineAbstractType(const DerivedType *OldTy, + const Type *NewTy) { + TheMapTy::iterator I = TheMap.find(OldTy); + const Type *DstTy = I->second; + + TheMap.erase(I); + if (OldTy->isAbstract()) + OldTy->removeAbstractTypeUser(this); + + // Don't reinsert into the map if the key is concrete now. + if (NewTy->isAbstract()) + insert(NewTy, DstTy); + } + + /// The other case which AbstractTypeUsers must be aware of is when a type + /// makes the transition from being abstract (where it has clients on it's + /// AbstractTypeUsers list) to concrete (where it does not). This method + /// notifies ATU's when this occurs for a type. + virtual void typeBecameConcrete(const DerivedType *AbsTy) { + TheMap.erase(AbsTy); + AbsTy->removeAbstractTypeUser(this); + } + + // for debugging... + virtual void dump() const { + cerr << "AbstractTypeSet!\n"; + } +}; +} + + // RecursiveResolveTypes - This is just like ResolveTypes, except that it // recurses down into derived types, merging the used types if the parent types // are compatible. static bool RecursiveResolveTypesI(const PATypeHolder &DestTy, const PATypeHolder &SrcTy, - std::vector > &Pointers) { + LinkerTypeMap &Pointers) { const Type *SrcTyT = SrcTy.get(); const Type *DestTyT = DestTy.get(); if (DestTyT == SrcTyT) return false; // If already equal, noop @@ -148,14 +227,21 @@ // If this is a pointer type, check to see if we have already seen it. If // so, we are in a recursive branch. Cut off the search now. We cannot use // an associative container for this search, because the type pointers (keys - // in the container) change whenever types get resolved... - for (unsigned i = 0, e = Pointers.size(); i != e; ++i) - if (Pointers[i].first == DestTy) - return Pointers[i].second != SrcTy; - + // in the container) change whenever types get resolved. + if (SrcPT->isAbstract()) + if (const Type *ExistingDestTy = Pointers.lookup(SrcPT)) + return ExistingDestTy != DstPT; + + if (DstPT->isAbstract()) + if (const Type *ExistingSrcTy = Pointers.lookup(DstPT)) + return ExistingSrcTy != SrcPT; + // Otherwise, add the current pointers to the vector to stop recursion on // this pair. - Pointers.push_back(std::make_pair(DestTyT, SrcTyT)); + if (DstPT->isAbstract()) + Pointers.insert(DstPT, SrcPT); + if (SrcPT->isAbstract()) + Pointers.insert(SrcPT, DstPT); return RecursiveResolveTypesI(DstPT->getElementType(), SrcPT->getElementType(), Pointers); } @@ -164,7 +250,7 @@ static bool RecursiveResolveTypes(const PATypeHolder &DestTy, const PATypeHolder &SrcTy) { - std::vector > PointerTypes; + LinkerTypeMap PointerTypes; return RecursiveResolveTypesI(DestTy, SrcTy, PointerTypes); } From nicolas.geoffray at lip6.fr Mon Jun 16 16:00:47 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Mon, 16 Jun 2008 21:00:47 -0000 Subject: [llvm-commits] [vmkit] r52358 - /vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.cpp Message-ID: <200806162100.m5GL0lEK032670@zion.cs.uiuc.edu> Author: geoffray Date: Mon Jun 16 16:00:47 2008 New Revision: 52358 URL: http://llvm.org/viewvc/llvm-project?rev=52358&view=rev Log: Correct buggy generated code (throwing an exception instead of return) when the return type is not void. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.cpp?rev=52358&r1=52357&r2=52358&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.cpp Mon Jun 16 16:00:47 2008 @@ -761,7 +761,7 @@ // not return. pred_iterator PI = pred_begin(endBlock); pred_iterator PE = pred_end(endBlock); - if (PI == PE) { + if (PI == PE && returnType != Type::VoidTy) { Instruction* I = currentBlock->getTerminator(); assert(isa(I) && "non terminator before buggy return"); I->eraseFromParent(); From ggreif at gmail.com Mon Jun 16 16:06:12 2008 From: ggreif at gmail.com (Gabor Greif) Date: Mon, 16 Jun 2008 21:06:12 -0000 Subject: [llvm-commits] [llvm] r52360 - in /llvm/trunk: docs/ProgrammersManual.html include/llvm/User.h Message-ID: <200806162106.m5GL6Csf000370@zion.cs.uiuc.edu> Author: ggreif Date: Mon Jun 16 16:06:12 2008 New Revision: 52360 URL: http://llvm.org/viewvc/llvm-project?rev=52360&view=rev Log: Move some documentation from the header file into ProgrammersManual. About to improve. Modified: llvm/trunk/docs/ProgrammersManual.html llvm/trunk/include/llvm/User.h Modified: llvm/trunk/docs/ProgrammersManual.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/ProgrammersManual.html?rev=52360&r1=52359&r2=52360&view=diff ============================================================================== --- llvm/trunk/docs/ProgrammersManual.html (original) +++ llvm/trunk/docs/ProgrammersManual.html Mon Jun 16 16:06:12 2008 @@ -138,7 +138,8 @@
  • The AbstractTypeUser Class
  • -
  • The ValueSymbolTable and TypeSymbolTable classes
  • +
  • The ValueSymbolTable and TypeSymbolTable classes
  • +
  • The User and owned Use classes' memory layout
  • The Core LLVM Class Hierarchy Reference @@ -173,7 +174,8 @@ @@ -2207,7 +2209,7 @@ by most clients. It should only be used when iteration over the symbol table names themselves are required, which is very special purpose. Note that not all LLVM -Values have names, and those without names (i.e. they have +Values have names, and those without names (i.e. they have an empty name) do not exist in the symbol table.

    @@ -2223,7 +2225,184 @@ - + + + +
    +

    The +User class provides a base for expressing the ownership of User +towards other +Values. The +Use helper class is employed to do the bookkeeping and facilitate O(1) +addition and removal.

    + +
    +   -----------------------------------------------------------------
    +   --- Interaction and relationship between User and Use objects ---
    +   -----------------------------------------------------------------
    +
    +
    +A subclass of User can choose between incorporating its Use objects
    +or refer to them out-of-line by means of a pointer. A mixed variant
    +(some Uses inline others hung off) is impractical and breaks the invariant
    +that the Use objects belonging to the same User form a contiguous array.
    +
    +We have 2 different layouts in the User (sub)classes:
    +
    +Layout a)
    +The Use object(s) are inside (resp. at fixed offset) of the User
    +object and there are a fixed number of them.
    +
    +Layout b)
    +The Use object(s) are referenced by a pointer to an
    +array from the User object and there may be a variable
    +number of them.
    +
    +Initially each layout will possess a direct pointer to the
    +start of the array of Uses. Though not mandatory for layout a),
    +we stick to this redundancy for the sake of simplicity.
    +The User object will also store the number of Use objects it
    +has. (Theoretically this information can also be calculated
    +given the scheme presented below.)
    +
    +Special forms of allocation operators (operator new)
    +will enforce the following memory layouts:
    +
    +
    +#  Layout a) will be modelled by prepending the User object
    +#  by the Use[] array.
    +#      
    +#      ...---.---.---.---.-------...
    +#        | P | P | P | P | User
    +#      '''---'---'---'---'-------'''
    +
    +
    +#  Layout b) will be modelled by pointing at the Use[] array.
    +#      
    +#      .-------...
    +#      | User
    +#      '-------'''
    +#          |
    +#          v
    +#          .---.---.---.---...
    +#          | P | P | P | P |
    +#          '---'---'---'---'''
    +
    +   (In the above figures 'P' stands for the Use** that
    +    is stored in each Use object in the member Use::Prev)
    +
    +
    +Since the Use objects will be deprived of the direct pointer to
    +their User objects, there must be a fast and exact method to
    +recover it. This is accomplished by the following scheme:
    +
    +A bit-encoding in the 2 LSBits of the Use::Prev will allow to find the
    +start of the User object:
    +
    +00 --> binary digit 0
    +01 --> binary digit 1
    +10 --> stop and calc (s)
    +11 --> full stop (S)
    +
    +Given a Use*, all we have to do is to walk till we get
    +a stop and we either have a User immediately behind or
    +we have to walk to the next stop picking up digits
    +and calculating the offset:
    +
    +.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.----------------
    +| 1 | s | 1 | 0 | 1 | 0 | s | 1 | 1 | 0 | s | 1 | 1 | s | 1 | S | User (or User*)
    +'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'----------------
    +    |+15                |+10            |+6         |+3     |+1
    +    |                   |               |           |       |__>
    +    |                   |               |           |__________>
    +    |                   |               |______________________>
    +    |                   |______________________________________>
    +    |__________________________________________________________>
    +
    +
    +Only the significant number of bits need to be stored between the
    +stops, so that the worst case is 20 memory accesses when there are
    +1000 Use objects.
    +
    +The following literate Haskell fragment demonstrates the concept:
    +
    +> import Test.QuickCheck
    +> 
    +> digits :: Int -> [Char] -> [Char]
    +> digits 0 acc = '0' : acc
    +> digits 1 acc = '1' : acc
    +> digits n acc = digits (n `div` 2) $ digits (n `mod` 2) acc
    +> 
    +> dist :: Int -> [Char] -> [Char]
    +> dist 0 [] = ['S']
    +> dist 0 acc = acc
    +> dist 1 acc = let r = dist 0 acc in 's' : digits (length r) r
    +> dist n acc = dist (n - 1) $ dist 1 acc
    +> 
    +> takeLast n ss = reverse $ take n $ reverse ss
    +> 
    +> test = takeLast 40 $ dist 20 []
    +> 
    +
    +Printing  gives: "1s100000s11010s10100s1111s1010s110s11s1S"
    +
    +The reverse algorithm computes the
    +length of the string just by examining
    +a certain prefix:
    +
    +> pref :: [Char] -> Int
    +> pref "S" = 1
    +> pref ('s':'1':rest) = decode 2 1 rest
    +> pref (_:rest) = 1 + pref rest
    +> 
    +> decode walk acc ('0':rest) = decode (walk + 1) (acc * 2) rest
    +> decode walk acc ('1':rest) = decode (walk + 1) (acc * 2 + 1) rest
    +> decode walk acc _ = walk + acc
    +> 
    +
    +Now, as expected, printing  gives 40.
    +
    +We can quickCheck this with following property:
    +
    +> testcase = dist 2000 []
    +> testcaseLength = length testcase
    +> 
    +> identityProp n = n > 0 && n <= testcaseLength ==> length arr == pref arr
    +>     where arr = takeLast n testcase
    +
    +As expected  gives:
    +
    +*Main> quickCheck identityProp
    +OK, passed 100 tests.
    +
    +Let's be a bit more exhaustive:
    +
    +> 
    +> deepCheck p = check (defaultConfig { configMaxTest = 500 }) p
    +> 
    +
    +And here is the result of :
    +
    +*Main> deepCheck identityProp
    +OK, passed 500 tests.
    +
    +
    +To maintain the invariant that the 2 LSBits of each Use** in Use
    +never change after being set up, setters of Use::Prev must re-tag the
    +new Use** on every modification. Accordingly getters must strip the
    +tag bits.
    +
    +For layout b) instead of the User we will find a pointer (User* with LSBit set).
    +Following this pointer brings us to the User. A portable trick will ensure
    +that the first bytes of User (if interpreted as a pointer) will never have
    +the LSBit set.
    +
    + +
    + + Modified: llvm/trunk/include/llvm/User.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/User.h?rev=52360&r1=52359&r2=52360&view=diff ============================================================================== --- llvm/trunk/include/llvm/User.h (original) +++ llvm/trunk/include/llvm/User.h Mon Jun 16 16:06:12 2008 @@ -23,171 +23,6 @@ namespace llvm { -/*============================================================================== - - - ----------------------------------------------------------------- - --- Interaction and relationship between User and Use objects --- - ----------------------------------------------------------------- - - -A subclass of User can choose between incorporating its Use objects -or refer to them out-of-line by means of a pointer. A mixed variant -(some Uses inline others hung off) is impractical and breaks the invariant -that the Use objects belonging to the same User form a contiguous array. - -We have 2 different layouts in the User (sub)classes: - -Layout a) -The Use object(s) are inside (resp. at fixed offset) of the User -object and there are a fixed number of them. - -Layout b) -The Use object(s) are referenced by a pointer to an -array from the User object and there may be a variable -number of them. - -Initially each layout will possess a direct pointer to the -start of the array of Uses. Though not mandatory for layout a), -we stick to this redundancy for the sake of simplicity. -The User object will also store the number of Use objects it -has. (Theoretically this information can also be calculated -given the scheme presented below.) - -Special forms of allocation operators (operator new) -will enforce the following memory layouts: - - -# Layout a) will be modelled by prepending the User object -# by the Use[] array. -# -# ...---.---.---.---.-------... -# | P | P | P | P | User -# '''---'---'---'---'-------''' - - -# Layout b) will be modelled by pointing at the Use[] array. -# -# .-------... -# | User -# '-------''' -# | -# v -# .---.---.---.---... -# | P | P | P | P | -# '---'---'---'---''' - - (In the above figures 'P' stands for the Use** that - is stored in each Use object in the member Use::Prev) - - -Since the Use objects will be deprived of the direct pointer to -their User objects, there must be a fast and exact method to -recover it. This is accomplished by the following scheme: - -A bit-encoding in the 2 LSBits of the Use::Prev will allow to find the -start of the User object: - -00 --> binary digit 0 -01 --> binary digit 1 -10 --> stop and calc (s) -11 --> full stop (S) - -Given a Use*, all we have to do is to walk till we get -a stop and we either have a User immediately behind or -we have to walk to the next stop picking up digits -and calculating the offset: - -.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---------------- -| 1 | s | 1 | 0 | 1 | 0 | s | 1 | 1 | 0 | s | 1 | 1 | s | 1 | S | User (or User*) -'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---------------- - |+15 |+10 |+6 |+3 |+1 - | | | | |__> - | | | |__________> - | | |______________________> - | |______________________________________> - |__________________________________________________________> - - -Only the significant number of bits need to be stored between the -stops, so that the worst case is 20 memory accesses when there are -1000 Use objects. - -The following literate Haskell fragment demonstrates the concept: - -> import Test.QuickCheck -> -> digits :: Int -> [Char] -> [Char] -> digits 0 acc = '0' : acc -> digits 1 acc = '1' : acc -> digits n acc = digits (n `div` 2) $ digits (n `mod` 2) acc -> -> dist :: Int -> [Char] -> [Char] -> dist 0 [] = ['S'] -> dist 0 acc = acc -> dist 1 acc = let r = dist 0 acc in 's' : digits (length r) r -> dist n acc = dist (n - 1) $ dist 1 acc -> -> takeLast n ss = reverse $ take n $ reverse ss -> -> test = takeLast 40 $ dist 20 [] -> - -Printing gives: "1s100000s11010s10100s1111s1010s110s11s1S" - -The reverse algorithm computes the -length of the string just by examining -a certain prefix: - -> pref :: [Char] -> Int -> pref "S" = 1 -> pref ('s':'1':rest) = decode 2 1 rest -> pref (_:rest) = 1 + pref rest -> -> decode walk acc ('0':rest) = decode (walk + 1) (acc * 2) rest -> decode walk acc ('1':rest) = decode (walk + 1) (acc * 2 + 1) rest -> decode walk acc _ = walk + acc -> - -Now, as expected, printing gives 40. - -We can quickCheck this with following property: - -> testcase = dist 2000 [] -> testcaseLength = length testcase -> -> identityProp n = n > 0 && n <= testcaseLength ==> length arr == pref arr -> where arr = takeLast n testcase - -As expected gives: - -*Main> quickCheck identityProp -OK, passed 100 tests. - -Let's be a bit more exhaustive: - -> -> deepCheck p = check (defaultConfig { configMaxTest = 500 }) p -> - -And here is the result of : - -*Main> deepCheck identityProp -OK, passed 500 tests. - - -To maintain the invariant that the 2 LSBits of each Use** in Use -never change after being set up, setters of Use::Prev must re-tag the -new Use** on every modification. Accordingly getters must strip the -tag bits. - -For layout b) instead of the User we will find a pointer (User* with LSBit set). -Following this pointer brings us to the User. A portable trick will ensure -that the first bytes of User (if interpreted as a pointer) will never have -the LSBit set. - -==============================================================================*/ - /// OperandTraits - Compile-time customization of /// operand-related allocators and accessors /// for use of the User class From evan.cheng at apple.com Mon Jun 16 16:08:17 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 16 Jun 2008 21:08:17 -0000 Subject: [llvm-commits] [llvm] r52361 - /llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Message-ID: <200806162108.m5GL8HVR000444@zion.cs.uiuc.edu> Author: evancheng Date: Mon Jun 16 16:08:17 2008 New Revision: 52361 URL: http://llvm.org/viewvc/llvm-project?rev=52361&view=rev Log: Switch over to SetVector to ensure same order of iterations do not vary across runs. Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=52361&r1=52360&r2=52361&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Mon Jun 16 16:08:17 2008 @@ -31,6 +31,7 @@ #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Local.h" #include "llvm/Target/TargetData.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/Debug.h" @@ -136,7 +137,7 @@ /// DeadInsts - Keep track of instructions we may have made dead, so that /// we can remove them after we are done working. - std::set DeadInsts; + SetVector DeadInsts; /// TLI - Keep a pointer of a TargetLowering to consult for determining /// transformation profitability. @@ -192,7 +193,7 @@ void StrengthReduceStridedIVUsers(const SCEVHandle &Stride, IVUsersOfOneStride &Uses, Loop *L, bool isOnlyStride); - void DeleteTriviallyDeadInstructions(std::set &Insts); + void DeleteTriviallyDeadInstructions(SetVector &Insts); }; } @@ -226,10 +227,10 @@ /// specified set are trivially dead, delete them and see if this makes any of /// their operands subsequently dead. void LoopStrengthReduce:: -DeleteTriviallyDeadInstructions(std::set &Insts) { +DeleteTriviallyDeadInstructions(SetVector &Insts) { while (!Insts.empty()) { - Instruction *I = *Insts.begin(); - Insts.erase(I); + Instruction *I = Insts.back(); + Insts.pop_back(); if (PHINode *PN = dyn_cast(I)) { // If all incoming values to the Phi are the same, we can replace the Phi @@ -378,7 +379,7 @@ /// should use the post-inc value). static bool IVUseShouldUsePostIncValue(Instruction *User, Instruction *IV, Loop *L, DominatorTree *DT, Pass *P, - std::set &DeadInsts){ + SetVector &DeadInsts){ // If the user is in the loop, use the preinc value. if (L->contains(User->getParent())) return false; @@ -546,7 +547,7 @@ void RewriteInstructionToUseNewBase(const SCEVHandle &NewBase, Instruction *InsertPt, SCEVExpander &Rewriter, Loop *L, Pass *P, - std::set &DeadInsts); + SetVector &DeadInsts); Value *InsertCodeForBaseAtPosition(const SCEVHandle &NewBase, SCEVExpander &Rewriter, @@ -612,7 +613,7 @@ void BasedUser::RewriteInstructionToUseNewBase(const SCEVHandle &NewBase, Instruction *NewBasePt, SCEVExpander &Rewriter, Loop *L, Pass *P, - std::set &DeadInsts) { + SetVector &DeadInsts) { if (!isa(Inst)) { // By default, insert code at the user instruction. BasicBlock::iterator InsertPt = Inst; From evan.cheng at apple.com Mon Jun 16 16:16:25 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 16 Jun 2008 21:16:25 -0000 Subject: [llvm-commits] [llvm] r52363 - in /llvm/trunk: include/llvm/IntrinsicsX86.td lib/Target/X86/X86InstrSSE.td Message-ID: <200806162116.m5GLGP5q000690@zion.cs.uiuc.edu> Author: evancheng Date: Mon Jun 16 16:16:24 2008 New Revision: 52363 URL: http://llvm.org/viewvc/llvm-project?rev=52363&view=rev Log: Horizontal-add instructions are not commutative. Modified: llvm/trunk/include/llvm/IntrinsicsX86.td llvm/trunk/lib/Target/X86/X86InstrSSE.td Modified: llvm/trunk/include/llvm/IntrinsicsX86.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IntrinsicsX86.td?rev=52363&r1=52362&r2=52363&view=diff ============================================================================== --- llvm/trunk/include/llvm/IntrinsicsX86.td (original) +++ llvm/trunk/include/llvm/IntrinsicsX86.td Mon Jun 16 16:16:24 2008 @@ -553,24 +553,24 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_ssse3_phadd_w : GCCBuiltin<"__builtin_ia32_phaddw">, Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem, Commutative]>; + llvm_v4i16_ty], [IntrNoMem]>; def int_x86_ssse3_phadd_w_128 : GCCBuiltin<"__builtin_ia32_phaddw128">, Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem, Commutative]>; + llvm_v8i16_ty], [IntrNoMem]>; def int_x86_ssse3_phadd_d : GCCBuiltin<"__builtin_ia32_phaddd">, Intrinsic<[llvm_v2i32_ty, llvm_v2i32_ty, - llvm_v2i32_ty], [IntrNoMem, Commutative]>; + llvm_v2i32_ty], [IntrNoMem]>; def int_x86_ssse3_phadd_d_128 : GCCBuiltin<"__builtin_ia32_phaddd128">, Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, - llvm_v4i32_ty], [IntrNoMem, Commutative]>; + llvm_v4i32_ty], [IntrNoMem]>; def int_x86_ssse3_phadd_sw : GCCBuiltin<"__builtin_ia32_phaddsw">, Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem, Commutative]>; + llvm_v4i16_ty], [IntrNoMem]>; def int_x86_ssse3_phadd_sw_128 : GCCBuiltin<"__builtin_ia32_phaddsw128">, Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, - llvm_v4i32_ty], [IntrNoMem, Commutative]>; + llvm_v4i32_ty], [IntrNoMem]>; def int_x86_ssse3_phsub_w : GCCBuiltin<"__builtin_ia32_phsubw">, Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, @@ -595,11 +595,14 @@ def int_x86_ssse3_pmadd_ub_sw : GCCBuiltin<"__builtin_ia32_pmaddubsw">, Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, - llvm_v4i16_ty], [IntrNoMem, Commutative]>; + llvm_v4i16_ty], [IntrNoMem]>; def int_x86_ssse3_pmadd_ub_sw_128 : GCCBuiltin<"__builtin_ia32_pmaddubsw128">, Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, - llvm_v8i16_ty], [IntrNoMem, Commutative]>; + llvm_v8i16_ty], [IntrNoMem]>; +} +// Packed multiply high with round and scale +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_ssse3_pmul_hr_sw : GCCBuiltin<"__builtin_ia32_pmulhrsw">, Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, llvm_v4i16_ty], [IntrNoMem, Commutative]>; Modified: llvm/trunk/lib/Target/X86/X86InstrSSE.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrSSE.td?rev=52363&r1=52362&r2=52363&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrSSE.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrSSE.td Mon Jun 16 16:16:24 2008 @@ -2745,13 +2745,13 @@ defm PHADDW : SS3I_binop_rm_int_16<0x01, "phaddw", int_x86_ssse3_phadd_w, - int_x86_ssse3_phadd_w_128, 1>; + int_x86_ssse3_phadd_w_128>; defm PHADDD : SS3I_binop_rm_int_32<0x02, "phaddd", int_x86_ssse3_phadd_d, - int_x86_ssse3_phadd_d_128, 1>; + int_x86_ssse3_phadd_d_128>; defm PHADDSW : SS3I_binop_rm_int_16<0x03, "phaddsw", int_x86_ssse3_phadd_sw, - int_x86_ssse3_phadd_sw_128, 1>; + int_x86_ssse3_phadd_sw_128>; defm PHSUBW : SS3I_binop_rm_int_16<0x05, "phsubw", int_x86_ssse3_phsub_w, int_x86_ssse3_phsub_w_128>; @@ -2763,7 +2763,7 @@ int_x86_ssse3_phsub_sw_128>; defm PMADDUBSW : SS3I_binop_rm_int_8 <0x04, "pmaddubsw", int_x86_ssse3_pmadd_ub_sw, - int_x86_ssse3_pmadd_ub_sw_128, 1>; + int_x86_ssse3_pmadd_ub_sw_128>; defm PMULHRSW : SS3I_binop_rm_int_16<0x0B, "pmulhrsw", int_x86_ssse3_pmul_hr_sw, int_x86_ssse3_pmul_hr_sw_128, 1>; From evan.cheng at apple.com Mon Jun 16 16:16:31 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 16 Jun 2008 14:16:31 -0700 Subject: [llvm-commits] [llvm] r52353 - in /llvm/trunk: include/llvm/Intrinsics.td include/llvm/IntrinsicsX86.td test/CodeGen/X86/commute-intrinsic.ll utils/TableGen/CodeGenDAGPatterns.cpp utils/TableGen/CodeGenDAGPatterns.h utils/TableGen/CodeGenIntrinsics.h utils/TableGen/CodeGenTarget.cpp In-Reply-To: References: <200806162029.m5GKTdpb031546@zion.cs.uiuc.edu> Message-ID: <74312B4F-9CFB-401E-AD6F-42CB54C174B2@apple.com> Fixed. Thanks. Evan On Jun 16, 2008, at 1:53 PM, Dan Gohman wrote: > > On Jun 16, 2008, at 1:29 PM, Evan Cheng wrote: >> // Integer shift ops. >> @@ -553,24 +553,24 @@ >> let TargetPrefix = "x86" in { // All intrinsics start with >> "llvm.x86.". >> def int_x86_ssse3_phadd_w : >> GCCBuiltin<"__builtin_ia32_phaddw">, >> Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, >> - llvm_v4i16_ty], [IntrNoMem]>; >> + llvm_v4i16_ty], [IntrNoMem, Commutative]>; >> def int_x86_ssse3_phadd_w_128 : >> GCCBuiltin<"__builtin_ia32_phaddw128">, >> Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, >> - llvm_v8i16_ty], [IntrNoMem]>; >> + llvm_v8i16_ty], [IntrNoMem, Commutative]>; >> >> def int_x86_ssse3_phadd_d : >> GCCBuiltin<"__builtin_ia32_phaddd">, >> Intrinsic<[llvm_v2i32_ty, llvm_v2i32_ty, >> - llvm_v2i32_ty], [IntrNoMem]>; >> + llvm_v2i32_ty], [IntrNoMem, Commutative]>; >> def int_x86_ssse3_phadd_d_128 : >> GCCBuiltin<"__builtin_ia32_phaddd128">, >> Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, >> - llvm_v4i32_ty], [IntrNoMem]>; >> + llvm_v4i32_ty], [IntrNoMem, Commutative]>; >> >> def int_x86_ssse3_phadd_sw : >> GCCBuiltin<"__builtin_ia32_phaddsw">, >> Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, >> - llvm_v4i16_ty], [IntrNoMem]>; >> + llvm_v4i16_ty], [IntrNoMem, Commutative]>; >> def int_x86_ssse3_phadd_sw_128 : >> GCCBuiltin<"__builtin_ia32_phaddsw128">, >> Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, >> - llvm_v4i32_ty], [IntrNoMem]>; >> + llvm_v4i32_ty], [IntrNoMem, Commutative]>; > > Hi Evan, > > Horizontal-add instructions are not commutative. It looks like > X86InstrSSE.td is mistaken about this too. > > Dan > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From sabre at nondot.org Mon Jun 16 16:17:12 2008 From: sabre at nondot.org (Chris Lattner) Date: Mon, 16 Jun 2008 21:17:12 -0000 Subject: [llvm-commits] [llvm] r52364 - /llvm/trunk/lib/Linker/LinkModules.cpp Message-ID: <200806162117.m5GLHDZu000745@zion.cs.uiuc.edu> Author: lattner Date: Mon Jun 16 16:17:12 2008 New Revision: 52364 URL: http://llvm.org/viewvc/llvm-project?rev=52364&view=rev Log: stop making PATypeHolder's so crazily. Modified: llvm/trunk/lib/Linker/LinkModules.cpp Modified: llvm/trunk/lib/Linker/LinkModules.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Linker/LinkModules.cpp?rev=52364&r1=52363&r2=52364&view=diff ============================================================================== --- llvm/trunk/lib/Linker/LinkModules.cpp (original) +++ llvm/trunk/lib/Linker/LinkModules.cpp Mon Jun 16 16:17:12 2008 @@ -157,69 +157,73 @@ // RecursiveResolveTypes - This is just like ResolveTypes, except that it // recurses down into derived types, merging the used types if the parent types // are compatible. -static bool RecursiveResolveTypesI(const PATypeHolder &DestTy, - const PATypeHolder &SrcTy, +static bool RecursiveResolveTypesI(const Type *DstTy, const Type *SrcTy, LinkerTypeMap &Pointers) { - const Type *SrcTyT = SrcTy.get(); - const Type *DestTyT = DestTy.get(); - if (DestTyT == SrcTyT) return false; // If already equal, noop + if (DstTy == SrcTy) return false; // If already equal, noop // If we found our opaque type, resolve it now! - if (isa(DestTyT) || isa(SrcTyT)) - return ResolveTypes(DestTyT, SrcTyT); + if (isa(DstTy) || isa(SrcTy)) + return ResolveTypes(DstTy, SrcTy); // Two types cannot be resolved together if they are of different primitive // type. For example, we cannot resolve an int to a float. - if (DestTyT->getTypeID() != SrcTyT->getTypeID()) return true; + if (DstTy->getTypeID() != SrcTy->getTypeID()) return true; // If neither type is abstract, then they really are just different types. - if (!DestTyT->isAbstract() && !SrcTyT->isAbstract()) + if (!DstTy->isAbstract() && !SrcTy->isAbstract()) return true; // Otherwise, resolve the used type used by this derived type... - switch (DestTyT->getTypeID()) { + switch (DstTy->getTypeID()) { default: return true; case Type::FunctionTyID: { - const FunctionType *DstFT = cast(DestTyT); - const FunctionType *SrcFT = cast(SrcTyT); + const FunctionType *DstFT = cast(DstTy); + const FunctionType *SrcFT = cast(SrcTy); if (DstFT->isVarArg() != SrcFT->isVarArg() || DstFT->getNumContainedTypes() != SrcFT->getNumContainedTypes()) return true; - for (unsigned i = 0, e = DstFT->getNumContainedTypes(); i != e; ++i) - if (RecursiveResolveTypesI(DstFT->getContainedType(i), - SrcFT->getContainedType(i), Pointers)) + + // Use TypeHolder's so recursive resolution won't break us. + PATypeHolder ST(SrcFT), DT(DstFT); + for (unsigned i = 0, e = DstFT->getNumContainedTypes(); i != e; ++i) { + const Type *SE = ST->getContainedType(i), *DE = DT->getContainedType(i); + if (SE != DE && RecursiveResolveTypesI(DE, SE, Pointers)) return true; + } return false; } case Type::StructTyID: { - const StructType *DstST = cast(DestTyT); - const StructType *SrcST = cast(SrcTyT); + const StructType *DstST = cast(DstTy); + const StructType *SrcST = cast(SrcTy); if (DstST->getNumContainedTypes() != SrcST->getNumContainedTypes()) return true; - for (unsigned i = 0, e = DstST->getNumContainedTypes(); i != e; ++i) - if (RecursiveResolveTypesI(DstST->getContainedType(i), - SrcST->getContainedType(i), Pointers)) + + PATypeHolder ST(SrcST), DT(DstST); + for (unsigned i = 0, e = DstST->getNumContainedTypes(); i != e; ++i) { + const Type *SE = ST->getContainedType(i), *DE = DT->getContainedType(i); + if (SE != DE && RecursiveResolveTypesI(DE, SE, Pointers)) return true; + } return false; } case Type::ArrayTyID: { - const ArrayType *DAT = cast(DestTy.get()); - const ArrayType *SAT = cast(SrcTy.get()); + const ArrayType *DAT = cast(DstTy); + const ArrayType *SAT = cast(SrcTy); if (DAT->getNumElements() != SAT->getNumElements()) return true; return RecursiveResolveTypesI(DAT->getElementType(), SAT->getElementType(), Pointers); } case Type::VectorTyID: { - const VectorType *DVT = cast(DestTy.get()); - const VectorType *SVT = cast(SrcTy.get()); + const VectorType *DVT = cast(DstTy); + const VectorType *SVT = cast(SrcTy); if (DVT->getNumElements() != SVT->getNumElements()) return true; return RecursiveResolveTypesI(DVT->getElementType(), SVT->getElementType(), Pointers); } case Type::PointerTyID: { - const PointerType *DstPT = cast(DestTy.get()); - const PointerType *SrcPT = cast(SrcTy.get()); + const PointerType *DstPT = cast(DstTy); + const PointerType *SrcPT = cast(SrcTy); if (DstPT->getAddressSpace() != SrcPT->getAddressSpace()) return true; @@ -235,21 +239,20 @@ if (DstPT->isAbstract()) if (const Type *ExistingSrcTy = Pointers.lookup(DstPT)) return ExistingSrcTy != SrcPT; - // Otherwise, add the current pointers to the vector to stop recursion on // this pair. if (DstPT->isAbstract()) Pointers.insert(DstPT, SrcPT); if (SrcPT->isAbstract()) Pointers.insert(SrcPT, DstPT); + return RecursiveResolveTypesI(DstPT->getElementType(), SrcPT->getElementType(), Pointers); } } } -static bool RecursiveResolveTypes(const PATypeHolder &DestTy, - const PATypeHolder &SrcTy) { +static bool RecursiveResolveTypes(const Type *DestTy, const Type *SrcTy) { LinkerTypeMap PointerTypes; return RecursiveResolveTypesI(DestTy, SrcTy, PointerTypes); } @@ -312,10 +315,7 @@ // two types: { int* } and { opaque* } for (unsigned i = 0, e = DelayedTypesToResolve.size(); i != e; ++i) { const std::string &Name = DelayedTypesToResolve[i]; - PATypeHolder T1(SrcST->lookup(Name)); - PATypeHolder T2(DestST->lookup(Name)); - - if (!RecursiveResolveTypes(T2, T1)) { + if (!RecursiveResolveTypes(SrcST->lookup(Name), DestST->lookup(Name))) { // We are making progress! DelayedTypesToResolve.erase(DelayedTypesToResolve.begin()+i); From sabre at nondot.org Mon Jun 16 16:20:58 2008 From: sabre at nondot.org (Chris Lattner) Date: Mon, 16 Jun 2008 21:20:58 -0000 Subject: [llvm-commits] [llvm] r52365 - /llvm/trunk/lib/VMCore/Type.cpp Message-ID: <200806162120.m5GLKxfJ000915@zion.cs.uiuc.edu> Author: lattner Date: Mon Jun 16 16:20:58 2008 New Revision: 52365 URL: http://llvm.org/viewvc/llvm-project?rev=52365&view=rev Log: switch TypeHasCycleThroughItself from using an std::set to using a SmallPtrSet, this speeds up the linking testcase in PR1860 by 44% (.379 -> 0.263) Modified: llvm/trunk/lib/VMCore/Type.cpp Modified: llvm/trunk/lib/VMCore/Type.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Type.cpp?rev=52365&r1=52364&r2=52365&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/Type.cpp (original) +++ llvm/trunk/lib/VMCore/Type.cpp Mon Jun 16 16:20:58 2008 @@ -717,11 +717,11 @@ // ever reach a non-abstract type, we know that we don't need to search the // subgraph. static bool AbstractTypeHasCycleThrough(const Type *TargetTy, const Type *CurTy, - std::set &VisitedTypes) { + SmallPtrSet &VisitedTypes) { if (TargetTy == CurTy) return true; if (!CurTy->isAbstract()) return false; - if (!VisitedTypes.insert(CurTy).second) + if (!VisitedTypes.insert(CurTy)) return false; // Already been here. for (Type::subtype_iterator I = CurTy->subtype_begin(), @@ -732,10 +732,10 @@ } static bool ConcreteTypeHasCycleThrough(const Type *TargetTy, const Type *CurTy, - std::set &VisitedTypes) { + SmallPtrSet &VisitedTypes) { if (TargetTy == CurTy) return true; - if (!VisitedTypes.insert(CurTy).second) + if (!VisitedTypes.insert(CurTy)) return false; // Already been here. for (Type::subtype_iterator I = CurTy->subtype_begin(), @@ -748,7 +748,7 @@ /// TypeHasCycleThroughItself - Return true if the specified type has a cycle /// back to itself. static bool TypeHasCycleThroughItself(const Type *Ty) { - std::set VisitedTypes; + SmallPtrSet VisitedTypes; if (Ty->isAbstract()) { // Optimized case for abstract types. for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end(); From kremenek at apple.com Mon Jun 16 16:41:45 2008 From: kremenek at apple.com (Ted Kremenek) Date: Mon, 16 Jun 2008 21:41:45 -0000 Subject: [llvm-commits] [llvm] r52368 - /llvm/tags/checker/checker-37/ Message-ID: <200806162141.m5GLfjfs001534@zion.cs.uiuc.edu> Author: kremenek Date: Mon Jun 16 16:41:45 2008 New Revision: 52368 URL: http://llvm.org/viewvc/llvm-project?rev=52368&view=rev Log: Tagging checker-37. Added: llvm/tags/checker/checker-37/ - copied from r52367, llvm/trunk/ From gohman at apple.com Mon Jun 16 16:42:36 2008 From: gohman at apple.com (Dan Gohman) Date: Mon, 16 Jun 2008 14:42:36 -0700 Subject: [llvm-commits] Dead argument elimination rewrite In-Reply-To: <20080616153738.GN2636@katherina.student.utwente.nl> References: <20080616153738.GN2636@katherina.student.utwente.nl> Message-ID: Hi Matthijs, I've read through this code and it looks good. See my comments below. On Jun 16, 2008, at 8:37 AM, Matthijs Kooijman wrote: > Hi all, > > I set out to improve deadargelim a bit last week, in particular to > allow it to > look at individual return values instead of just looking at the > returned > struct as a whole. > > After some fiddling around with the old code, I decided that the > existing > structure was really unsuited for adaption, actually I suspect that > looking at > return values at all was a later hack-on in the first place. > > So, I ended up rewriting the whole thing. Where the old code used two > iterations (one non-recursive and one recursive) to establish > liveness, the > new code uses only a single iteration, that works non-recursively. Ok. > > > The pass now looks properly inside returned structs, but only at the > first > level (ie, not inside nested structs). I also have a "flatten return > values" > patch lying around somewhere, which might also become useful for > this. Are > people interested in this? I don't think it's a high priority, but a "flatten return values" pass would be nice to have. > > > The pass now also does not look inside functions that use old style > multiple > return instructions, but gracefully ignores those functions (which > does have > small regression, since it also does not remove dead arguments on such > functions. However, this will be fixed once we stop using the old > multiple > return instructions). I'm going to be working on having LLVM auto-upgrade old-style multiple return values to struct returns next. That change will eliminate any regressions due to not handling them :-). > > > I've also unified the handling of return values and arguments, since > essentially they should be processed in the same way. This is done > by defining > the RetOrArg struct, which can model either a return value or an > argument. > This also allows for easily putting RetOrArgs into containers. > > Liveness of values inspected so far is mainly maintained in the > LiveValues > set. Any value that is clearly live (either because it is used by a > RetOrArg > that we know to be live already or because it is used by some other > instruction) is put into this set. > > Any value that is "MaybeLive", meaning that is used only as an > argument or > return value of which we don't know liveness yet, is tracked in the > Uses > multimap. Or rather, all of its uses are tracked and mapped to the > value > itself, so whenever a RetOrArg is marked live, any other RetToArg it > uses can > also be marked live immediately. > > When all instructions are processed, any values not marked live can > be assumed > to be dead and will be removed. > > By using a very explicit mapping between what is dependent on what > exactly, > the marking should be efficiently (the old code had to re-establish > which > argument it was supposed to check again, leading to extra looping). > > I've attached the patch, but since it changes most of the file, I've > also > attached the new file, which is probably easier to read. The only > large part > remaining from the old code is DeleteDeadVarargs, which is completely > unmodified. > > Comments are welcome! UseMap is a std::multimap that maps every argument and return value to every argument or return value that it "uses". That caught my eye as a potential scalability suspect. Have you done any testing on large inputs? The InspectedFunctions member variable looks redundant. Can it be removed? In MarkLive: UseMap::iterator Begin = Uses.lower_bound(RA); UseMap::iterator E = Uses.end(); UseMap::iterator I; for (I = Begin; I != E && I->first == RA; ++I) MarkLive(I->second); This would be a little simpler using Uses.upper_bound(RA). There are several instances of code like this: return Result; } else { Because of the return, it's not necessary to put the following code in a block under an else. Simplifying these, especially in SurveyUse, can make the code less nested and easier to read. Also, watch out for 80 columns :-). Thanks! Dan From isanbard at gmail.com Mon Jun 16 17:04:33 2008 From: isanbard at gmail.com (Bill Wendling) Date: Mon, 16 Jun 2008 15:04:33 -0700 Subject: [llvm-commits] [llvm] r52347 - /llvm/trunk/lib/Linker/LinkModules.cpp In-Reply-To: <200806161948.m5GJm9p0029416@zion.cs.uiuc.edu> References: <200806161948.m5GJm9p0029416@zion.cs.uiuc.edu> Message-ID: <16e5fdf90806161504k20eefb9at1a52b5f8055be437@mail.gmail.com> On Mon, Jun 16, 2008 at 12:48 PM, Chris Lattner wrote: > Author: lattner > Date: Mon Jun 16 14:48:08 2008 > New Revision: 52347 > > URL: http://llvm.org/viewvc/llvm-project?rev=52347&view=rev > Log: > Apply a patch from Nathan Keynes, which speeds up llvm-link on > the testcases in PR1860 from taking more than 1 hour (when I killed it) > to taking 1s. > Um...Wow! -bw > Modified: > llvm/trunk/lib/Linker/LinkModules.cpp > > Modified: llvm/trunk/lib/Linker/LinkModules.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Linker/LinkModules.cpp?rev=52347&r1=52346&r2=52347&view=diff > > ============================================================================== > --- llvm/trunk/lib/Linker/LinkModules.cpp (original) > +++ llvm/trunk/lib/Linker/LinkModules.cpp Mon Jun 16 14:48:08 2008 > @@ -156,7 +156,6 @@ > RecursiveResolveTypesI(cast(DestTy.get())->getElementType(), > cast(SrcTy.get())->getElementType(), > Pointers); > - Pointers.pop_back(); > return Result; > } > } > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > From gohman at apple.com Mon Jun 16 17:34:17 2008 From: gohman at apple.com (Dan Gohman) Date: Mon, 16 Jun 2008 22:34:17 -0000 Subject: [llvm-commits] [llvm] r52371 - in /llvm/trunk: lib/Transforms/Scalar/LoopStrengthReduce.cpp test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-0.ll test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-1.ll test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness.ll Message-ID: <200806162234.m5GMYHf2003266@zion.cs.uiuc.edu> Author: djg Date: Mon Jun 16 17:34:15 2008 New Revision: 52371 URL: http://llvm.org/viewvc/llvm-project?rev=52371&view=rev Log: Refine the change in r52258 for avoiding use-before-def conditions when changing the stride of a comparison so that it's slightly more precise, by having it scan the instruction list to determine if there is a use of the condition after the point where the condition will be inserted. Added: llvm/trunk/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-0.ll - copied, changed from r52370, llvm/trunk/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness.ll llvm/trunk/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-1.ll - copied, changed from r52370, llvm/trunk/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness.ll Removed: llvm/trunk/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness.ll Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=52371&r1=52370&r2=52371&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Mon Jun 16 17:34:15 2008 @@ -1530,15 +1530,6 @@ ICmpInst *LoopStrengthReduce::ChangeCompareStride(Loop *L, ICmpInst *Cond, IVStrideUse* &CondUse, const SCEVHandle* &CondStride) { - // Forgo this transformation if the condition has multiple uses. This is - // over-conservative, but simpler than alternatives. It guards against - // comparisons with a use that occurs earlier than the add instruction for the - // new stride index. See - // test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness.ll - // for an example of this situation. - if (!Cond->hasOneUse()) - return Cond; - if (StrideOrder.size() < 2 || IVUsesByStride[*CondStride].Users.size() != 1) return Cond; @@ -1653,6 +1644,18 @@ } } + // Forgo this transformation if it the increment happens to be + // unfortunately positioned after the condition, and the condition + // has multiple uses which prevent it from being moved immediately + // before the branch. See + // test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-*.ll + // for an example of this situation. + if (!Cond->hasOneUse()) + for (BasicBlock::iterator I = Cond, E = Cond->getParent()->end(); + I != E; ++I) + if (I == NewIncV) + return Cond; + if (NewCmpVal != CmpVal) { // Create a new compare instruction using new stride / iv. ICmpInst *OldCond = Cond; Copied: llvm/trunk/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-0.ll (from r52370, llvm/trunk/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness.ll) URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-0.ll?p2=llvm/trunk/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-0.ll&p1=llvm/trunk/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness.ll&r1=52370&r2=52371&rev=52371&view=diff ============================================================================== --- llvm/trunk/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness.ll (original) +++ llvm/trunk/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-0.ll Mon Jun 16 17:34:15 2008 @@ -1,7 +1,11 @@ -; RUN: llvm-as < %s | llc +; RUN: llvm-as < %s | llc --x86-asm-syntax=att | grep {cmpl \$4} target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" target triple = "x86_64-apple-darwin9" +; This is like change-compare-stride-trickiness-1.ll except the comparison +; happens before the relevant use, so the comparison stride can't be +; easily changed. + define void @foo() { entry: br label %loop Copied: llvm/trunk/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-1.ll (from r52370, llvm/trunk/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness.ll) URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-1.ll?p2=llvm/trunk/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-1.ll&p1=llvm/trunk/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness.ll&r1=52370&r2=52371&rev=52371&view=diff ============================================================================== --- llvm/trunk/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness.ll (original) +++ llvm/trunk/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-1.ll Mon Jun 16 17:34:15 2008 @@ -1,7 +1,11 @@ -; RUN: llvm-as < %s | llc +; RUN: llvm-as < %s | llc --x86-asm-syntax=att | grep {cmpl \$8} target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" target triple = "x86_64-apple-darwin9" +; This is like change-compare-stride-trickiness-0.ll except the comparison +; happens after the relevant use, so the comparison stride can be +; easily changed. + define void @foo() { entry: br label %loop @@ -9,10 +13,10 @@ loop: %indvar = phi i32 [ 0, %entry ], [ %i.2.0.us1534, %loop ] ; [#uses=1] %i.2.0.us1534 = add i32 %indvar, 1 ; [#uses=3] - %tmp611.us1535 = icmp eq i32 %i.2.0.us1534, 4 ; [#uses=2] - %tmp623.us1538 = select i1 %tmp611.us1535, i32 6, i32 0 ; [#uses=0] %tmp628.us1540 = shl i32 %i.2.0.us1534, 1 ; [#uses=1] %tmp645646647.us1547 = sext i32 %tmp628.us1540 to i64 ; [#uses=0] + %tmp611.us1535 = icmp eq i32 %i.2.0.us1534, 4 ; [#uses=2] + %tmp623.us1538 = select i1 %tmp611.us1535, i32 6, i32 0 ; [#uses=0] br i1 %tmp611.us1535, label %exit, label %loop exit: Removed: llvm/trunk/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness.ll?rev=52370&view=auto ============================================================================== --- llvm/trunk/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness.ll (original) +++ llvm/trunk/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness.ll (removed) @@ -1,20 +0,0 @@ -; RUN: llvm-as < %s | llc -target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" -target triple = "x86_64-apple-darwin9" - -define void @foo() { -entry: - br label %loop - -loop: - %indvar = phi i32 [ 0, %entry ], [ %i.2.0.us1534, %loop ] ; [#uses=1] - %i.2.0.us1534 = add i32 %indvar, 1 ; [#uses=3] - %tmp611.us1535 = icmp eq i32 %i.2.0.us1534, 4 ; [#uses=2] - %tmp623.us1538 = select i1 %tmp611.us1535, i32 6, i32 0 ; [#uses=0] - %tmp628.us1540 = shl i32 %i.2.0.us1534, 1 ; [#uses=1] - %tmp645646647.us1547 = sext i32 %tmp628.us1540 to i64 ; [#uses=0] - br i1 %tmp611.us1535, label %exit, label %loop - -exit: - ret void -} From evan.cheng at apple.com Mon Jun 16 17:52:53 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 16 Jun 2008 22:52:53 -0000 Subject: [llvm-commits] [llvm] r52373 - in /llvm/trunk: lib/CodeGen/LowerSubregs.cpp test/CodeGen/X86/2008-06-16-SubregsBug.ll Message-ID: <200806162252.m5GMqrj5003852@zion.cs.uiuc.edu> Author: evancheng Date: Mon Jun 16 17:52:53 2008 New Revision: 52373 URL: http://llvm.org/viewvc/llvm-project?rev=52373&view=rev Log: Do not issue identity copies. Added: llvm/trunk/test/CodeGen/X86/2008-06-16-SubregsBug.ll Modified: llvm/trunk/lib/CodeGen/LowerSubregs.cpp Modified: llvm/trunk/lib/CodeGen/LowerSubregs.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LowerSubregs.cpp?rev=52373&r1=52372&r2=52373&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/LowerSubregs.cpp (original) +++ llvm/trunk/lib/CodeGen/LowerSubregs.cpp Mon Jun 16 17:52:53 2008 @@ -108,15 +108,20 @@ DOUT << "subreg: CONVERTING: " << *MI; - // Insert sub-register copy - const TargetRegisterClass *TRC0 = TRI.getPhysicalRegisterRegClass(DstSubReg); - const TargetRegisterClass *TRC1 = TRI.getPhysicalRegisterRegClass(InsReg); - TII.copyRegToReg(*MBB, MI, DstSubReg, InsReg, TRC0, TRC1); + if (DstSubReg == InsReg) { + // No need to insert an identify copy instruction. + DOUT << "subreg: eliminated!"; + } else { + // Insert sub-register copy + const TargetRegisterClass *TRC0= TRI.getPhysicalRegisterRegClass(DstSubReg); + const TargetRegisterClass *TRC1= TRI.getPhysicalRegisterRegClass(InsReg); + TII.copyRegToReg(*MBB, MI, DstSubReg, InsReg, TRC0, TRC1); #ifndef NDEBUG - MachineBasicBlock::iterator dMI = MI; - DOUT << "subreg: " << *(--dMI); + MachineBasicBlock::iterator dMI = MI; + DOUT << "subreg: " << *(--dMI); #endif + } DOUT << "\n"; MBB->remove(MI); @@ -149,15 +154,19 @@ DOUT << "subreg: CONVERTING: " << *MI; - // Insert sub-register copy - const TargetRegisterClass *TRC0 = TRI.getPhysicalRegisterRegClass(DstSubReg); - const TargetRegisterClass *TRC1 = TRI.getPhysicalRegisterRegClass(InsReg); - TII.copyRegToReg(*MBB, MI, DstSubReg, InsReg, TRC0, TRC1); - + if (DstSubReg == InsReg) { + // No need to insert an identify copy instruction. + DOUT << "subreg: eliminated!"; + } else { + // Insert sub-register copy + const TargetRegisterClass *TRC0= TRI.getPhysicalRegisterRegClass(DstSubReg); + const TargetRegisterClass *TRC1= TRI.getPhysicalRegisterRegClass(InsReg); + TII.copyRegToReg(*MBB, MI, DstSubReg, InsReg, TRC0, TRC1); #ifndef NDEBUG - MachineBasicBlock::iterator dMI = MI; - DOUT << "subreg: " << *(--dMI); + MachineBasicBlock::iterator dMI = MI; + DOUT << "subreg: " << *(--dMI); #endif + } DOUT << "\n"; MBB->remove(MI); Added: llvm/trunk/test/CodeGen/X86/2008-06-16-SubregsBug.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2008-06-16-SubregsBug.ll?rev=52373&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/2008-06-16-SubregsBug.ll (added) +++ llvm/trunk/test/CodeGen/X86/2008-06-16-SubregsBug.ll Mon Jun 16 17:52:53 2008 @@ -0,0 +1,14 @@ +; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin | grep mov | count 4 + +define i16 @test(i16* %tmp179) nounwind { + %tmp180 = load i16* %tmp179, align 2 ; [#uses=2] + %tmp184 = and i16 %tmp180, -1024 ; [#uses=1] + %tmp186 = icmp eq i16 %tmp184, -32768 ; [#uses=1] + br i1 %tmp186, label %bb189, label %bb288 + +bb189: ; preds = %0 + ret i16 %tmp180 + +bb288: ; preds = %0 + ret i16 32 +} From sabre at nondot.org Mon Jun 16 18:06:51 2008 From: sabre at nondot.org (Chris Lattner) Date: Mon, 16 Jun 2008 23:06:51 -0000 Subject: [llvm-commits] [llvm] r52374 - /llvm/trunk/lib/Linker/LinkModules.cpp Message-ID: <200806162306.m5GN6pHw004256@zion.cs.uiuc.edu> Author: lattner Date: Mon Jun 16 18:06:51 2008 New Revision: 52374 URL: http://llvm.org/viewvc/llvm-project?rev=52374&view=rev Log: Add a missing ~ (dtor became ctor) which caused crashes on a bunch of stuff. Modified: llvm/trunk/lib/Linker/LinkModules.cpp Modified: llvm/trunk/lib/Linker/LinkModules.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Linker/LinkModules.cpp?rev=52374&r1=52373&r2=52374&view=diff ============================================================================== --- llvm/trunk/lib/Linker/LinkModules.cpp (original) +++ llvm/trunk/lib/Linker/LinkModules.cpp Mon Jun 16 18:06:51 2008 @@ -83,9 +83,12 @@ class LinkerTypeMap : public AbstractTypeUser { typedef DenseMap TheMapTy; TheMapTy TheMap; -public: - LinkerTypeMap() { + LinkerTypeMap(const LinkerTypeMap&); // DO NOT IMPLEMENT + void operator=(const LinkerTypeMap&); // DO NOT IMPLEMENT +public: + LinkerTypeMap() {} + ~LinkerTypeMap() { for (DenseMap::iterator I = TheMap.begin(), E = TheMap.end(); I != E; ++I) I->first->removeAbstractTypeUser(this); From evan.cheng at apple.com Mon Jun 16 21:01:23 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 17 Jun 2008 02:01:23 -0000 Subject: [llvm-commits] [llvm] r52377 - in /llvm/trunk/lib/Target/X86: X86ISelDAGToDAG.cpp X86ISelLowering.cpp Message-ID: <200806170201.m5H21N2U009669@zion.cs.uiuc.edu> Author: evancheng Date: Mon Jun 16 21:01:22 2008 New Revision: 52377 URL: http://llvm.org/viewvc/llvm-project?rev=52377&view=rev Log: Rather than avoiding to wrap ISD::DECLARE GV operand in X86ISD::Wrapper, simply handle it at dagisel time with x86 specific isel code. Modified: llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Modified: llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp?rev=52377&r1=52376&r2=52377&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp (original) +++ llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp Mon Jun 16 21:01:22 2008 @@ -1578,6 +1578,28 @@ return ResNode; break; } + + case ISD::DECLARE: { + // Handle DECLARE nodes here because the second operand may have been + // wrapped in X86ISD::Wrapper. + SDOperand Chain = Node->getOperand(0); + SDOperand N1 = Node->getOperand(1); + SDOperand N2 = Node->getOperand(2); + if (isa(N1) && + N2.getOpcode() == X86ISD::Wrapper && + isa(N2.getOperand(0))) { + int FI = cast(N1)->getIndex(); + GlobalValue *GV = + cast(N2.getOperand(0))->getGlobal(); + SDOperand Tmp1 = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); + SDOperand Tmp2 = CurDAG->getTargetGlobalAddress(GV, TLI.getPointerTy()); + AddToISelQueue(Chain); + SDOperand Ops[] = { Tmp1, Tmp2, Chain }; + return CurDAG->getTargetNode(TargetInstrInfo::DECLARE, + MVT::Other, Ops, 3); + } + break; + } } SDNode *ResNode = SelectCode(N); Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=52377&r1=52376&r2=52377&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Mon Jun 16 21:01:22 2008 @@ -4173,9 +4173,6 @@ X86TargetLowering::LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) { GlobalValue *GV = cast(Op)->getGlobal(); SDOperand Result = DAG.getTargetGlobalAddress(GV, getPointerTy()); - // If it's a debug information descriptor, don't mess with it. - if (DAG.isVerifiedDebugInfoDesc(Op)) - return Result; Result = DAG.getNode(X86ISD::Wrapper, getPointerTy(), Result); // With PIC, the address is actually $g + Offset. if (getTargetMachine().getRelocationModel() == Reloc::PIC_ && From baldrick at free.fr Mon Jun 16 22:24:14 2008 From: baldrick at free.fr (Duncan Sands) Date: Tue, 17 Jun 2008 03:24:14 -0000 Subject: [llvm-commits] [llvm] r52381 - /llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Message-ID: <200806170324.m5H3OFV0012107@zion.cs.uiuc.edu> Author: baldrick Date: Mon Jun 16 22:24:13 2008 New Revision: 52381 URL: http://llvm.org/viewvc/llvm-project?rev=52381&view=rev Log: Fix spelling. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp?rev=52381&r1=52380&r2=52381&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Mon Jun 16 22:24:13 2008 @@ -4283,7 +4283,7 @@ // Copy the output from the appropriate register. Find a register that // we can use. if (OpInfo.AssignedRegs.Regs.empty()) { - cerr << "Couldn't allocate output reg for contraint '" + cerr << "Couldn't allocate output reg for constraint '" << OpInfo.ConstraintCode << "'!\n"; exit(1); } From sabre at nondot.org Tue Jun 17 01:09:18 2008 From: sabre at nondot.org (Chris Lattner) Date: Tue, 17 Jun 2008 06:09:18 -0000 Subject: [llvm-commits] [llvm] r52383 - in /llvm/trunk: include/llvm/CodeGen/SelectionDAG.h include/llvm/CodeGen/SelectionDAGISel.h lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Message-ID: <200806170609.m5H69IjZ016785@zion.cs.uiuc.edu> Author: lattner Date: Tue Jun 17 01:09:18 2008 New Revision: 52383 URL: http://llvm.org/viewvc/llvm-project?rev=52383&view=rev Log: add a new -enable-value-prop flag for llcbeta, that enables propagation of value info (sign/zero ext info) from one MBB to another. This doesn't handle much right now because of two limitations: 1) only handles zext/sext, not random bit propagation (no assert exists for this) 2) doesn't handle phis. Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAG.h llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAG.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAG.h?rev=52383&r1=52382&r2=52383&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/SelectionDAG.h (original) +++ llvm/trunk/include/llvm/CodeGen/SelectionDAG.h Tue Jun 17 01:09:18 2008 @@ -31,6 +31,7 @@ class MachineModuleInfo; class MachineFunction; class MachineConstantPoolValue; + class FunctionLoweringInfo; /// SelectionDAG class - This is used to represent a portion of an LLVM function /// in a low-level Data Dependence DAG representation suitable for instruction @@ -46,6 +47,7 @@ class SelectionDAG { TargetLowering &TLI; MachineFunction &MF; + FunctionLoweringInfo &FLI; MachineModuleInfo *MMI; /// Root - The root of the entire DAG. EntryNode - The starting token. @@ -59,8 +61,9 @@ FoldingSet CSEMap; public: - SelectionDAG(TargetLowering &tli, MachineFunction &mf, MachineModuleInfo *mmi) - : TLI(tli), MF(mf), MMI(mmi) { + SelectionDAG(TargetLowering &tli, MachineFunction &mf, + FunctionLoweringInfo &fli, MachineModuleInfo *mmi) + : TLI(tli), MF(mf), FLI(fli), MMI(mmi) { EntryNode = Root = getNode(ISD::EntryToken, MVT::Other); } ~SelectionDAG(); @@ -68,6 +71,7 @@ MachineFunction &getMachineFunction() const { return MF; } const TargetMachine &getTarget() const; TargetLowering &getTargetLoweringInfo() const { return TLI; } + FunctionLoweringInfo &getFunctionLoweringInfo() const { return FLI; } MachineModuleInfo *getMachineModuleInfo() const { return MMI; } /// viewGraph - Pop up a GraphViz/gv window with the DAG rendered using 'dot'. Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h?rev=52383&r1=52382&r2=52383&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h (original) +++ llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h Tue Jun 17 01:09:18 2008 @@ -158,6 +158,7 @@ MachineBasicBlock *Default; BitTestInfo Cases; }; + protected: /// Pick a safe ordering and emit instructions for each target node in the /// graph. @@ -183,6 +184,8 @@ FunctionLoweringInfo &FuncInfo); void CodeGenAndEmitDAG(SelectionDAG &DAG); void LowerArguments(BasicBlock *BB, SelectionDAGLowering &SDL); + + void ComputeLiveOutVRegInfo(SelectionDAG &DAG); /// SwitchCases - Vector of CaseBlock structures used to communicate /// SwitchInst code generation information. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp?rev=52383&r1=52382&r2=52383&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Tue Jun 17 01:09:18 2008 @@ -48,6 +48,10 @@ #include using namespace llvm; +static cl::opt +EnableValueProp("enable-value-prop", cl::Hidden, cl::init(false)); + + #ifndef NDEBUG static cl::opt ViewISelDAGs("view-isel-dags", cl::Hidden, @@ -326,6 +330,16 @@ assert(R == 0 && "Already initialized this value register!"); return R = CreateRegForValue(V); } + + struct LiveOutInfo { + unsigned NumSignBits; + APInt KnownOne, KnownZero; + LiveOutInfo() : NumSignBits(0) {} + }; + + /// LiveOutRegInfo - Information about live out vregs, indexed by their + /// register number offset by 'FirstVirtualRegister'. + std::vector LiveOutRegInfo; }; } @@ -1748,12 +1762,11 @@ unsigned Reg, SelectionDAGISel::BitTestCase &B) { // Emit bit tests and jumps - SDOperand SwitchVal = DAG.getCopyFromReg(getControlRoot(), Reg, TLI.getPointerTy()); + SDOperand SwitchVal = DAG.getCopyFromReg(getControlRoot(), Reg, + TLI.getPointerTy()); - SDOperand AndOp = DAG.getNode(ISD::AND, TLI.getPointerTy(), - SwitchVal, - DAG.getConstant(B.Mask, - TLI.getPointerTy())); + SDOperand AndOp = DAG.getNode(ISD::AND, TLI.getPointerTy(), SwitchVal, + DAG.getConstant(B.Mask, TLI.getPointerTy())); SDOperand AndCmp = DAG.getSetCC(TLI.getSetCCResultType(AndOp), AndOp, DAG.getConstant(0, TLI.getPointerTy()), ISD::SETNE); @@ -3706,7 +3719,7 @@ /// this value and returns the result as a ValueVT value. This uses /// Chain/Flag as the input and updates them for the output Chain/Flag. /// If the Flag pointer is NULL, no flag is used. -SDOperand RegsForValue::getCopyFromRegs(SelectionDAG &DAG, +SDOperand RegsForValue::getCopyFromRegs(SelectionDAG &DAG, SDOperand &Chain, SDOperand *Flag) const { // Assemble the legal parts into the final values. @@ -3728,6 +3741,49 @@ *Flag = P.getValue(2); } Chain = P.getValue(1); + + // If the source register was virtual and if we know something about it, + // add an assert node. + if (TargetRegisterInfo::isVirtualRegister(Regs[Part+i]) && + RegisterVT.isInteger() && !RegisterVT.isVector()) { + unsigned SlotNo = Regs[Part+i]-TargetRegisterInfo::FirstVirtualRegister; + FunctionLoweringInfo &FLI = DAG.getFunctionLoweringInfo(); + if (FLI.LiveOutRegInfo.size() > SlotNo) { + FunctionLoweringInfo::LiveOutInfo &LOI = FLI.LiveOutRegInfo[SlotNo]; + + unsigned RegSize = RegisterVT.getSizeInBits(); + unsigned NumSignBits = LOI.NumSignBits; + unsigned NumZeroBits = LOI.KnownZero.countLeadingOnes(); + + // FIXME: We capture more information than the dag can represent. For + // now, just use the tightest assertzext/assertsext possible. + bool isSExt = true; + MVT FromVT(MVT::Other); + if (NumSignBits == RegSize) + isSExt = true, FromVT = MVT::i1; // ASSERT SEXT 1 + else if (NumZeroBits >= RegSize-1) + isSExt = false, FromVT = MVT::i1; // ASSERT ZEXT 1 + else if (NumSignBits > RegSize-8) + isSExt = true, FromVT = MVT::i8; // ASSERT SEXT 8 + else if (NumZeroBits >= RegSize-9) + isSExt = false, FromVT = MVT::i8; // ASSERT ZEXT 8 + else if (NumSignBits > RegSize-16) + isSExt = true, FromVT = MVT::i16; // ASSERT SEXT 16 + else if (NumZeroBits >= RegSize-17) + isSExt = false, FromVT = MVT::i16; // ASSERT ZEXT 16 + else if (NumSignBits > RegSize-32) + isSExt = true, FromVT = MVT::i32; // ASSERT SEXT 32 + else if (NumZeroBits >= RegSize-33) + isSExt = false, FromVT = MVT::i32; // ASSERT ZEXT 32 + + if (FromVT != MVT::Other) { + P = DAG.getNode(isSExt ? ISD::AssertSext : ISD::AssertZext, + RegisterVT, P, DAG.getValueType(FromVT)); + + } + } + } + Parts[Part+i] = P; } @@ -5218,6 +5274,61 @@ CheckDAGForTailCallsAndFixThem(DAG, TLI); } +void SelectionDAGISel::ComputeLiveOutVRegInfo(SelectionDAG &DAG) { + SmallPtrSet VisitedNodes; + SmallVector Worklist; + + Worklist.push_back(DAG.getRoot().Val); + + APInt Mask; + APInt KnownZero; + APInt KnownOne; + + while (!Worklist.empty()) { + SDNode *N = Worklist.back(); + Worklist.pop_back(); + + // If we've already seen this node, ignore it. + if (!VisitedNodes.insert(N)) + continue; + + // Otherwise, add all chain operands to the worklist. + for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) + if (N->getOperand(i).getValueType() == MVT::Other) + Worklist.push_back(N->getOperand(i).Val); + + // If this is a CopyToReg with a vreg dest, process it. + if (N->getOpcode() != ISD::CopyToReg) + continue; + + unsigned DestReg = cast(N->getOperand(1))->getReg(); + if (!TargetRegisterInfo::isVirtualRegister(DestReg)) + continue; + + // Ignore non-scalar or non-integer values. + SDOperand Src = N->getOperand(2); + MVT SrcVT = Src.getValueType(); + if (!SrcVT.isInteger() || SrcVT.isVector()) + continue; + + unsigned NumSignBits = DAG.ComputeNumSignBits(Src); + Mask = APInt::getAllOnesValue(SrcVT.getSizeInBits()); + DAG.ComputeMaskedBits(Src, Mask, KnownZero, KnownOne); + + // Only install this information if it tells us something. + if (NumSignBits != 1 || KnownZero != 0 || KnownOne != 0) { + DestReg -= TargetRegisterInfo::FirstVirtualRegister; + FunctionLoweringInfo &FLI = DAG.getFunctionLoweringInfo(); + if (DestReg >= FLI.LiveOutRegInfo.size()) + FLI.LiveOutRegInfo.resize(DestReg+1); + FunctionLoweringInfo::LiveOutInfo &LOI = FLI.LiveOutRegInfo[DestReg]; + LOI.NumSignBits = NumSignBits; + LOI.KnownOne = NumSignBits; + LOI.KnownZero = NumSignBits; + } + } +} + void SelectionDAGISel::CodeGenAndEmitDAG(SelectionDAG &DAG) { DOUT << "Lowered selection DAG:\n"; DEBUG(DAG.dump()); @@ -5246,6 +5357,9 @@ DEBUG(DAG.dump()); if (ViewISelDAGs) DAG.viewGraph(); + + if (EnableValueProp) // FIXME: Only do this if !fast. + ComputeLiveOutVRegInfo(DAG); // Third, instruction select all of the operations to machine code, adding the // code to the MachineBasicBlock. @@ -5259,7 +5373,8 @@ FunctionLoweringInfo &FuncInfo) { std::vector > PHINodesToUpdate; { - SelectionDAG DAG(TLI, MF, getAnalysisToUpdate()); + SelectionDAG DAG(TLI, MF, FuncInfo, + getAnalysisToUpdate()); CurDAG = &DAG; // First step, lower LLVM code to some DAG. This DAG may use operations and @@ -5293,7 +5408,8 @@ for (unsigned i = 0, e = BitTestCases.size(); i != e; ++i) { // Lower header first, if it wasn't already lowered if (!BitTestCases[i].Emitted) { - SelectionDAG HSDAG(TLI, MF, getAnalysisToUpdate()); + SelectionDAG HSDAG(TLI, MF, FuncInfo, + getAnalysisToUpdate()); CurDAG = &HSDAG; SelectionDAGLowering HSDL(HSDAG, TLI, *AA, FuncInfo, GCI); // Set the current basic block to the mbb we wish to insert the code into @@ -5306,7 +5422,8 @@ } for (unsigned j = 0, ej = BitTestCases[i].Cases.size(); j != ej; ++j) { - SelectionDAG BSDAG(TLI, MF, getAnalysisToUpdate()); + SelectionDAG BSDAG(TLI, MF, FuncInfo, + getAnalysisToUpdate()); CurDAG = &BSDAG; SelectionDAGLowering BSDL(BSDAG, TLI, *AA, FuncInfo, GCI); // Set the current basic block to the mbb we wish to insert the code into @@ -5363,7 +5480,8 @@ for (unsigned i = 0, e = JTCases.size(); i != e; ++i) { // Lower header first, if it wasn't already lowered if (!JTCases[i].first.Emitted) { - SelectionDAG HSDAG(TLI, MF, getAnalysisToUpdate()); + SelectionDAG HSDAG(TLI, MF, FuncInfo, + getAnalysisToUpdate()); CurDAG = &HSDAG; SelectionDAGLowering HSDL(HSDAG, TLI, *AA, FuncInfo, GCI); // Set the current basic block to the mbb we wish to insert the code into @@ -5375,7 +5493,8 @@ CodeGenAndEmitDAG(HSDAG); } - SelectionDAG JSDAG(TLI, MF, getAnalysisToUpdate()); + SelectionDAG JSDAG(TLI, MF, FuncInfo, + getAnalysisToUpdate()); CurDAG = &JSDAG; SelectionDAGLowering JSDL(JSDAG, TLI, *AA, FuncInfo, GCI); // Set the current basic block to the mbb we wish to insert the code into @@ -5423,7 +5542,8 @@ // If we generated any switch lowering information, build and codegen any // additional DAGs necessary. for (unsigned i = 0, e = SwitchCases.size(); i != e; ++i) { - SelectionDAG SDAG(TLI, MF, getAnalysisToUpdate()); + SelectionDAG SDAG(TLI, MF, FuncInfo, + getAnalysisToUpdate()); CurDAG = &SDAG; SelectionDAGLowering SDL(SDAG, TLI, *AA, FuncInfo, GCI); From matthijs at stdin.nl Tue Jun 17 03:24:39 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Tue, 17 Jun 2008 08:24:39 -0000 Subject: [llvm-commits] [llvm] r52390 - /llvm/trunk/lib/Analysis/ValueTracking.cpp Message-ID: <200806170824.m5H8OdH6031548@zion.cs.uiuc.edu> Author: matthijs Date: Tue Jun 17 03:24:37 2008 New Revision: 52390 URL: http://llvm.org/viewvc/llvm-project?rev=52390&view=rev Log: Use a SmallVector instead of an array, since auto_ptr doesn't handle arrays properly. Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=52390&r1=52389&r2=52390&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ValueTracking.cpp (original) +++ llvm/trunk/lib/Analysis/ValueTracking.cpp Tue Jun 17 03:24:37 2008 @@ -908,24 +908,21 @@ // Calculate the number of indices required unsigned size = I->getNumIndices() + (idx_end - idx_begin); // Allocate some space to put the new indices in - unsigned *new_begin = new unsigned[size]; - // Auto cleanup this array - std::auto_ptr newptr(new_begin); - // Start inserting at the beginning - unsigned *new_end = new_begin; + SmallVector Idxs; + Idxs.reserve(size); // Add indices from the extract value instruction for (const unsigned *i = I->idx_begin(), *e = I->idx_end(); - i != e; ++i, ++new_end) - *new_end = *i; + i != e; ++i) + Idxs.push_back(*i); // Add requested indices - for (const unsigned *i = idx_begin, *e = idx_end; i != e; ++i, ++new_end) - *new_end = *i; + for (const unsigned *i = idx_begin, *e = idx_end; i != e; ++i) + Idxs.push_back(*i); - assert((unsigned)(new_end - new_begin) == size + assert(Idxs.size() == size && "Number of indices added not correct?"); - return FindInsertedValue(I->getAggregateOperand(), new_begin, new_end, + return FindInsertedValue(I->getAggregateOperand(), Idxs.begin(), Idxs.end(), InsertBefore); } // Otherwise, we don't know (such as, extracting from a function return value From matthijs at stdin.nl Tue Jun 17 03:25:27 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Tue, 17 Jun 2008 10:25:27 +0200 Subject: [llvm-commits] [llvm] r52217 - in /llvm/trunk: lib/Transforms/Scalar/InstructionCombining.cpp test/Transforms/InstCombine/extractvalue.ll In-Reply-To: <35990.76.220.41.203.1213634648.squirrel@webmail.apple.com> References: <200806111405.m5BE55rj002564@zion.cs.uiuc.edu> <314C0D33-E9A2-49BA-A2A4-E2C36C4509D3@apple.com> <20080616130819.GL2636@katherina.student.utwente.nl> <35990.76.220.41.203.1213634648.squirrel@webmail.apple.com> Message-ID: <20080617082527.GA16202@katherina.student.utwente.nl> Hi Dan, > Oops, I meant SmallVector. Both SmallVector and std::vector guarantee > their elements are in contiguous memory. I changed it to use SmallVector now. Gr. Matthijs -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: Digital signature Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080617/9439014d/attachment.bin From matthijs at stdin.nl Tue Jun 17 03:26:32 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Tue, 17 Jun 2008 08:26:32 -0000 Subject: [llvm-commits] [llvm] r52391 - /llvm/trunk/include/llvm/Analysis/ValueTracking.h Message-ID: <200806170826.m5H8QWcV031639@zion.cs.uiuc.edu> Author: matthijs Date: Tue Jun 17 03:26:32 2008 New Revision: 52391 URL: http://llvm.org/viewvc/llvm-project?rev=52391&view=rev Log: 80 column fixes. Modified: llvm/trunk/include/llvm/Analysis/ValueTracking.h Modified: llvm/trunk/include/llvm/Analysis/ValueTracking.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ValueTracking.h?rev=52391&r1=52390&r2=52391&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/ValueTracking.h (original) +++ llvm/trunk/include/llvm/Analysis/ValueTracking.h Tue Jun 17 03:26:32 2008 @@ -52,9 +52,9 @@ /// bool CannotBeNegativeZero(const Value *V, unsigned Depth = 0); - /// FindScalarValue - Given an aggregrate and an sequence of indices, see if the - /// scalar value indexed is already around as a register, for example if it were - /// inserted directly into the aggregrate. + /// FindScalarValue - Given an aggregrate and an sequence of indices, see if + /// the scalar value indexed is already around as a register, for example if + /// it were inserted directly into the aggregrate. /// /// If InsertBefore is not null, this function will duplicate (modified) /// insertvalues when a part of a nested struct is extracted. From matthijs at stdin.nl Tue Jun 17 03:30:22 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Tue, 17 Jun 2008 10:30:22 +0200 Subject: [llvm-commits] [llvm] r52315 - in /llvm/trunk: include/llvm/Analysis/ValueTracking.h lib/Analysis/ValueTracking.cpp lib/Transforms/Scalar/InstructionCombining.cpp In-Reply-To: <9AAD6CC3-245D-4E11-85F0-EF126AF6B728@apple.com> References: <200806161248.m5GCmM01015536@zion.cs.uiuc.edu> <9AAD6CC3-245D-4E11-85F0-EF126AF6B728@apple.com> Message-ID: <20080617083022.GB16202@katherina.student.utwente.nl> Hi Dan, > Well, there's no insertvalue instruction for a constant or an undef. I > thought of the name FindExtractedValue because it returns the value that > an extractvalue with the given arguments would extract. Hmm, good point. How about FindValueAtIndices? > Also, the comment here still says FindScalarValue, and it's > now over 80 columns. Hmm, I had checked all my .cpp files for 80 column violations.. :-) Gr. Matthijs -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: Digital signature Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080617/94b710bd/attachment.bin From matthijs at stdin.nl Tue Jun 17 03:44:00 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Tue, 17 Jun 2008 10:44:00 +0200 Subject: [llvm-commits] Dead argument elimination rewrite In-Reply-To: References: <20080616153738.GN2636@katherina.student.utwente.nl> Message-ID: <20080617084400.GC16202@katherina.student.utwente.nl> Hi Dan, > I don't think it's a high priority, but a "flatten return values" pass > would be nice to have. I have one lying around that is general enough IIRC, I'll only have to pull it out of our local namespace into llvm :-) > I'm going to be working on having LLVM auto-upgrade old-style multiple > return values to struct returns next. That change will eliminate any > regressions due to not handling them :-). Ah, that sounds like a sound idea :-) > UseMap is a std::multimap that maps every argument and return value > to every argument or return value that it "uses". That caught my > eye as a potential scalability suspect. Have you done any testing > on large inputs? I've done some testing on the basictest.ll testcase, copied about a hundred times (in the same file). Execution times are very similar to the old version (around 43ms according to -time-passes). I've also did the same thing to a new testcase that has a lot of unused return values (parts of struct returns). Here, the new code needs over twice as much time, but that's mainly due to it removing stuff that the old code didn't. I also tried using a hash_multimap instead of a normal multimap, but that didn't seem to make much of a difference. Perhaps on even larger inputs, but I'll leave it at multimap for now since the hash version is non-standard. > The InspectedFunctions member variable looks redundant. Can it be > removed? I added it, to prevent infinite looping. When removing stuff from a function, a new function is created with the new function type. This variable helps to prevent the new function from being stripped as well. Alternatively, I could make a copy of the function list and iterate over that, which should have the same effect. > In MarkLive: > > UseMap::iterator Begin = Uses.lower_bound(RA); > UseMap::iterator E = Uses.end(); > UseMap::iterator I; > for (I = Begin; I != E && I->first == RA; ++I) > MarkLive(I->second); > > This would be a little simpler using Uses.upper_bound(RA). Yeah, but I reckoned that would require more traversing of the tree and hence be slower. I've now rewritten it to use equal_range instead, which is probably the best tradeoff between performance and simplicity (also, hash_multimap required this). > There are several instances of code like this: > > return Result; > } else { > > Because of the return, it's not necessary to put the following code > in a block under an else. Simplifying these, especially in SurveyUse, > can make the code less nested and easier to read. Done. Gr. Matthijs -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: Digital signature Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080617/de92238e/attachment.bin From nicolas.geoffray at lip6.fr Tue Jun 17 04:46:35 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 17 Jun 2008 09:46:35 -0000 Subject: [llvm-commits] [vmkit] r52392 - in /vmkit/trunk: include/mvm/ include/mvm/GC/ lib/JnJVM/VMCore/ lib/Mvm/ lib/Mvm/BoehmGC/ lib/Mvm/GCMmap2/ lib/N3/VMCore/ Message-ID: <200806170946.m5H9kaaI001989@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jun 17 04:46:35 2008 New Revision: 52392 URL: http://llvm.org/viewvc/llvm-project?rev=52392&view=rev Log: Use C++ destructors to finalize a GC-allocated object. Modified: vmkit/trunk/include/mvm/GC/GC.h vmkit/trunk/include/mvm/Object.h vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaClass.h vmkit/trunk/lib/JnJVM/VMCore/JavaIsolate.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaIsolate.h vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaObject.h vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h vmkit/trunk/lib/JnJVM/VMCore/LockedMap.h vmkit/trunk/lib/JnJVM/VMCore/ServiceDomain.cpp vmkit/trunk/lib/JnJVM/VMCore/ServiceDomain.h vmkit/trunk/lib/Mvm/BoehmGC/MvmGC.h vmkit/trunk/lib/Mvm/GCMmap2/gccollector.cpp vmkit/trunk/lib/Mvm/VTOffset.cpp vmkit/trunk/lib/N3/VMCore/VMThread.cpp vmkit/trunk/lib/N3/VMCore/VMThread.h vmkit/trunk/lib/N3/VMCore/VirtualMachine.cpp vmkit/trunk/lib/N3/VMCore/VirtualMachine.h Modified: vmkit/trunk/include/mvm/GC/GC.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/GC/GC.h?rev=52392&r1=52391&r2=52392&view=diff ============================================================================== --- vmkit/trunk/include/mvm/GC/GC.h (original) +++ vmkit/trunk/include/mvm/GC/GC.h Tue Jun 17 04:46:35 2008 @@ -20,7 +20,6 @@ class gcRoot { public: virtual ~gcRoot() {} - virtual void destroyer(size_t) {} #ifdef MULTIPLE_GC virtual void tracer(void* GC) {} #else @@ -28,10 +27,15 @@ #endif }; +typedef void (*destructor_t)(void*); + class gc_header { public: VirtualTable *_XXX_vt; inline gcRoot *_2gc() { return (gcRoot *)this; } + destructor_t getDestructor() { + return ((destructor_t*)(this->_XXX_vt))[0]; + } }; #endif Modified: vmkit/trunk/include/mvm/Object.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/include/mvm/Object.h?rev=52392&r1=52391&r2=52392&view=diff ============================================================================== --- vmkit/trunk/include/mvm/Object.h (original) +++ vmkit/trunk/include/mvm/Object.h Tue Jun 17 04:46:35 2008 @@ -19,12 +19,11 @@ #define VT_DESTRUCTOR_OFFSET 0 -#define VT_GC_DESTRUCTOR_OFFSET 1 -#define VT_DESTROYER_OFFSET 2 -#define VT_TRACER_OFFSET 3 -#define VT_PRINT_OFFSET 4 -#define VT_HASHCODE_OFFSET 5 -#define VT_SIZE 6 * sizeof(void*) +#define VT_OPERATOR_DELETE_OFFSET 1 +#define VT_TRACER_OFFSET 2 +#define VT_PRINT_OFFSET 3 +#define VT_HASHCODE_OFFSET 4 +#define VT_SIZE 5 * sizeof(void*) class PrintBuffer; @@ -51,10 +50,6 @@ /// char *printString(void) const; - /// destroyer - Default implementation of destroyer. Does nothing. - /// - virtual void destroyer(size_t) {} - /// tracer - Default implementation of tracer. Does nothing. /// virtual void TRACER {} Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp?rev=52392&r1=52391&r2=52392&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp Tue Jun 17 04:46:35 2008 @@ -80,13 +80,22 @@ return 0; } -void CommonClass::destroyer(size_t sz) { +CommonClass::~CommonClass() { free(display); - isolate->TheModule->removeClass(this); + if (isolate) + isolate->TheModule->removeClass(this); } -void Class::destroyer(size_t sz) { - CommonClass::destroyer(sz); +CommonClass::CommonClass() { + display = 0; + isolate = 0; +} + +Class::Class() { + ctpInfo = 0; +} + +Class::~Class() { for (std::vector::iterator i = attributs.begin(), e = attributs.end(); i!= e; ++i) { Attribut* cur = *i; Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaClass.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaClass.h?rev=52392&r1=52391&r2=52392&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaClass.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaClass.h Tue Jun 17 04:46:35 2008 @@ -265,17 +265,17 @@ } CommonClass(Jnjvm* vm, const UTF8* name, bool isArray); - /// Empty constructor for VT - CommonClass() {} static VirtualTable* VT; static JavaObject* jnjvmClassLoader; - virtual void destroyer(size_t sz); + + ~CommonClass(); + CommonClass(); + }; class ClassPrimitive : public CommonClass { public: - static VirtualTable* VT; ClassPrimitive(Jnjvm* vm, const UTF8* name); }; @@ -297,7 +297,9 @@ JavaObject* doNew(Jnjvm* vm); virtual void print(mvm::PrintBuffer *buf) const; virtual void TRACER; - virtual void destroyer(size_t sz); + + ~Class(); + Class(); JavaObject* operator()(Jnjvm* vm); @@ -314,8 +316,6 @@ void createStaticInstance(); #endif - /// Empty constructor for VT - Class() {} Class(Jnjvm* vm, const UTF8* name); }; Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaIsolate.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaIsolate.cpp?rev=52392&r1=52391&r2=52392&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaIsolate.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaIsolate.cpp Tue Jun 17 04:46:35 2008 @@ -539,7 +539,10 @@ return isolate; } -void JavaIsolate::destroyer(size_t sz) { - Jnjvm::destroyer(sz); +JavaIsolate::~JavaIsolate() { delete threadSystem; } + +JavaIsolate::JavaIsolate() { + threadSystem = 0; +} Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaIsolate.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaIsolate.h?rev=52392&r1=52391&r2=52392&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaIsolate.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaIsolate.h Tue Jun 17 04:46:35 2008 @@ -53,7 +53,8 @@ virtual void print(mvm::PrintBuffer* buf) const; virtual void TRACER; - virtual void destroyer(size_t sz); + ~JavaIsolate(); + JavaIsolate(); JavaObject* loadAppClassLoader(); void loadBootstrap(); Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp?rev=52392&r1=52391&r2=52392&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp Tue Jun 17 04:46:35 2008 @@ -243,13 +243,18 @@ } } -void LockObj::destroyer(size_t sz) { +LockObj::~LockObj() { if (varcond) delete varcond; delete lock; } +LockObj::LockObj() { + varcond = 0; + lock = 0; +} + #ifdef USE_GC_BOEHM -void JavaObject::destroyer(size_t sz) { +JavaObject::~JavaObject() { if (lockObj()) delete lockObj(); } #endif Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaObject.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaObject.h?rev=52392&r1=52391&r2=52392&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaObject.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaObject.h Tue Jun 17 04:46:35 2008 @@ -112,7 +112,8 @@ static VirtualTable* VT; virtual void print(mvm::PrintBuffer* buf) const; virtual void TRACER; - virtual void destroyer(size_t sz); + ~LockObj(); + LockObj(); }; @@ -206,7 +207,10 @@ virtual void TRACER; #ifdef USE_GC_BOEHM - virtual void destroyer(size_t sz); + ~JavaObject(); + JavaObject() { + lockObj = 0; + } #endif LockObj* lockObj() { Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp?rev=52392&r1=52391&r2=52392&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaThread.cpp Tue Jun 17 04:46:35 2008 @@ -30,7 +30,12 @@ javaThread->print(buf); } -void JavaThread::destroyer(size_t sz) { +JavaThread::~JavaThread() { delete lock; delete varcond; } + +JavaThread::JavaThread() { + lock = 0; + varcond = 0; +} Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h?rev=52392&r1=52391&r2=52392&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaThread.h Tue Jun 17 04:46:35 2008 @@ -48,7 +48,8 @@ virtual void print(mvm::PrintBuffer *buf) const; virtual void TRACER; - virtual void destroyer(size_t sz); + ~JavaThread(); + JavaThread(); void initialise(JavaObject* thread, Jnjvm* isolate) { this->javaThread = thread; Modified: vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp?rev=52392&r1=52391&r2=52392&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp Tue Jun 17 04:46:35 2008 @@ -804,7 +804,7 @@ } #endif -void Jnjvm::destroyer(size_t sz) { +Jnjvm::~Jnjvm() { #ifdef MULTIPLE_GC GC->destroy(); delete GC; @@ -816,4 +816,17 @@ delete globalRefsLock; delete TheModuleProvider; + delete TheModule; +} + +Jnjvm::Jnjvm() { +#ifdef MULTIPLE_GC + GC = 0; +#endif + hashUTF8 = 0; + hashStr = 0; + javaTypes = 0; + globalRefsLock = 0; + TheModuleProvider = 0; + TheModule = 0; } Modified: vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h?rev=52392&r1=52391&r2=52392&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h Tue Jun 17 04:46:35 2008 @@ -219,7 +219,8 @@ buf->write("Jnjvm<>"); } - virtual void destroyer(size_t sz); + ~Jnjvm(); + Jnjvm(); void addProperty(char* key, char* value); Modified: vmkit/trunk/lib/JnJVM/VMCore/LockedMap.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/LockedMap.h?rev=52392&r1=52391&r2=52392&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/LockedMap.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/LockedMap.h Tue Jun 17 04:46:35 2008 @@ -142,7 +142,7 @@ lock = mvm::Lock::allocNormal(); } - virtual void destroyer(size_t sz) { + ~ClassMap() { delete lock; } @@ -230,7 +230,7 @@ virtual void TRACER; - virtual void destroyer(size_t sz) { + ~StaticInstanceMap() { for (iterator i = map.begin(), e = map.end(); i!= e; ++i) { delete i->second; } @@ -247,7 +247,7 @@ lock = mvm::Lock::allocNormal(); } - virtual void destroyer(size_t sz) { + ~DelegateeMap() { delete lock; } Modified: vmkit/trunk/lib/JnJVM/VMCore/ServiceDomain.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/ServiceDomain.cpp?rev=52392&r1=52391&r2=52392&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/ServiceDomain.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/ServiceDomain.cpp Tue Jun 17 04:46:35 2008 @@ -30,8 +30,7 @@ JavaMethod* ServiceDomain::uninstallBundle; -void ServiceDomain::destroyer(size_t sz) { - Jnjvm::destroyer(sz); +ServiceDomain::~ServiceDomain() { delete lock; } Modified: vmkit/trunk/lib/JnJVM/VMCore/ServiceDomain.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/ServiceDomain.h?rev=52392&r1=52391&r2=52392&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/ServiceDomain.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/ServiceDomain.h Tue Jun 17 04:46:35 2008 @@ -35,7 +35,7 @@ virtual void print(mvm::PrintBuffer* buf) const; virtual void TRACER; - virtual void destroyer(size_t sz); + ~ServiceDomain(); static ServiceDomain* allocateService(JavaIsolate* callingVM); static void serviceError(ServiceDomain* error, const char* str); Modified: vmkit/trunk/lib/Mvm/BoehmGC/MvmGC.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/BoehmGC/MvmGC.h?rev=52392&r1=52391&r2=52392&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/BoehmGC/MvmGC.h (original) +++ vmkit/trunk/lib/Mvm/BoehmGC/MvmGC.h Tue Jun 17 04:46:35 2008 @@ -38,18 +38,14 @@ return (GC_size(res) - sizeof(gc_header)); } - static void my_destroyer(void * obj, void * unused){ - gc_header* res = (gc_header*)GC_base(obj); - if(res){ - res->_2gc()->destroyer(GC_size(res)); - } - } - void * operator new(size_t sz, VirtualTable *VT) { gc_header * res = (gc_header*) GC_MALLOC(sz + sizeof(gc_header)); res -> _XXX_vt= VT; - - GC_register_finalizer_no_order(res, my_destroyer, NULL, NULL, NULL); + + destructor_t dest = res->getDestructor(); + if (dest) + GC_register_finalizer_no_order(res, (void (*)(void*, void*))dest, NULL, + NULL, NULL); return res->_2gc(); } @@ -64,7 +60,6 @@ void * realloc(size_t n) { void * old = GC_base(this); gc_header * res = (gc_header*) GC_REALLOC(old, n + sizeof(gc_header)); - GC_register_finalizer(old, NULL, NULL, NULL, NULL); return res->_2gc(); } Modified: vmkit/trunk/lib/Mvm/GCMmap2/gccollector.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/GCMmap2/gccollector.cpp?rev=52392&r1=52391&r2=52392&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/GCMmap2/gccollector.cpp (original) +++ vmkit/trunk/lib/Mvm/GCMmap2/gccollector.cpp Tue Jun 17 04:46:35 2008 @@ -46,6 +46,8 @@ bool GCCollector::_enable_collection; #endif +typedef void (*destructor_t)(void*); + void GCCollector::do_collect() { //printf("----- do collect -----\n"); GCChunkNode *cur; @@ -93,7 +95,9 @@ register gc_header *c = cur->chunk(); next = cur->next(); - c->_2gc()->destroyer(real_nbb(cur)); + destructor_t dest = c->getDestructor(); + if (dest) + dest(c); //printf(" !!!! reject %p [%p]\n", cur->chunk()->_2gc(), cur); allocator->reject_chunk(cur); Modified: vmkit/trunk/lib/Mvm/VTOffset.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/VTOffset.cpp?rev=52392&r1=52391&r2=52392&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/VTOffset.cpp (original) +++ vmkit/trunk/lib/Mvm/VTOffset.cpp Tue Jun 17 04:46:35 2008 @@ -16,7 +16,6 @@ #include "mvm/PrintBuffer.h" #include "mvm/Threads/Thread.h" #include "mvm/Sigsegv.h" -#include "mvm/VMLet.h" class Toto : public mvm::Object { public: @@ -38,38 +37,34 @@ printf("in destroy!\n"); } - virtual ~Toto() { + ~Toto() { printf("in delete Toto!\n"); } }; -static void clearSignals(void) { - sys_signal(SIGINT, SIG_DFL); - sys_signal(SIGILL, SIG_DFL); -#if !defined(WIN32) - sys_signal(SIGIOT, SIG_DFL); - sys_signal(SIGBUS, SIG_DFL); -#endif - sys_signal(SIGSEGV, SIG_DFL); -} - +class Tata : public Toto { + public: + static VirtualTable* VT; + ~Tata() { + printf("in delete Tata!\n"); + } +}; VirtualTable* Toto::VT = 0; typedef void (*toto_t)(Toto* t); +VirtualTable* Tata::VT = 0; +typedef void (*tata_t)(Tata* t); + int main(int argc, char **argv, char **envp) { int base; - mvm::VMLet::initialise(); - mvm::Object::initialise(&base); - - initialiseVT(); - initialiseStatics(); + mvm::Object::initialise(); /*void* handle = sys_dlopen("libLisp.so", RTLD_LAZY | RTLD_GLOBAL); boot func = (boot)sys_dlsym(handle, "boot"); func(argc, argv, envp);*/ - + { Toto t; Toto::VT =((void**)(void*)&t)[0]; toto_t* ptr = (toto_t*)Toto::VT; @@ -80,8 +75,22 @@ ptr[3](&t); ptr[4](&t); ptr[5](&t); - - clearSignals(); +} +{ + Tata t; + Tata::VT =((void**)(void*)&t)[0]; + tata_t* ptr = (tata_t*)Tata::VT; + printf("ptr[0] = %d, ptr[1]= %d, ptr[2] = %d ptr[3] = %d ptr[4] = %d ptr[5] = %d\n", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]); + printf("Call des\n"); + ptr[0](&t); + printf("End\n"); + //ptr[1](&t); // This should be ~gc + ptr[2](&t); + ptr[3](&t); + ptr[4](&t); + ptr[5](&t); +} +Tata* t = gc_new(Tata)(); mvm::Thread::exit(0); return 0; Modified: vmkit/trunk/lib/N3/VMCore/VMThread.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/VMThread.cpp?rev=52392&r1=52391&r2=52392&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/VMThread.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/VMThread.cpp Tue Jun 17 04:46:35 2008 @@ -35,10 +35,14 @@ vmThread->print(buf); } -void VMThread::destroyer(size_t sz) { +VMThread::~VMThread() { delete perFunctionPasses; } +VMThread::VMThread() { + perFunctionPasses = 0; +} + VMThread* VMThread::get() { return (VMThread*)threadKey->get(); } Modified: vmkit/trunk/lib/N3/VMCore/VMThread.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/VMThread.h?rev=52392&r1=52391&r2=52392&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/VMThread.h (original) +++ vmkit/trunk/lib/N3/VMCore/VMThread.h Tue Jun 17 04:46:35 2008 @@ -45,7 +45,8 @@ virtual void print(mvm::PrintBuffer *buf); virtual void TRACER; - virtual void destroyer(size_t sz); + ~VMThread(); + VMThread(); static VMThread* get(); static VMThread* allocate(VMObject* thread, VirtualMachine* vm); Modified: vmkit/trunk/lib/N3/VMCore/VirtualMachine.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/VirtualMachine.cpp?rev=52392&r1=52391&r2=52392&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/VirtualMachine.cpp (original) +++ vmkit/trunk/lib/N3/VMCore/VirtualMachine.cpp Tue Jun 17 04:46:35 2008 @@ -151,7 +151,12 @@ error(name, fmt, ap); } -void VirtualMachine::destroyer(size_t sz) { +VirtualMachine::~VirtualMachine() { delete module; delete TheModuleProvider; } + +VirtualMachine::VirtualMachine() { + module = 0; + TheModuleProvider = 0; +} Modified: vmkit/trunk/lib/N3/VMCore/VirtualMachine.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/N3/VMCore/VirtualMachine.h?rev=52392&r1=52391&r2=52392&view=diff ============================================================================== --- vmkit/trunk/lib/N3/VMCore/VirtualMachine.h (original) +++ vmkit/trunk/lib/N3/VMCore/VirtualMachine.h Tue Jun 17 04:46:35 2008 @@ -115,7 +115,8 @@ buf->write("Virtual Machine<>"); } - virtual void destroyer(size_t sz); + ~VirtualMachine(); + VirtualMachine(); mvm::Lock* protectModule; FunctionMap* functions; From nicolas.geoffray at lip6.fr Tue Jun 17 05:06:41 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 17 Jun 2008 10:06:41 -0000 Subject: [llvm-commits] [vmkit] r52393 - /vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp Message-ID: <200806171006.m5HA6fPi002603@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jun 17 05:06:40 2008 New Revision: 52393 URL: http://llvm.org/viewvc/llvm-project?rev=52393&view=rev Log: The module provider takes ownership of the module, the Jnjvm class does not have to deallocate it. Modified: vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp?rev=52393&r1=52392&r2=52393&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp Tue Jun 17 05:06:40 2008 @@ -816,7 +816,6 @@ delete globalRefsLock; delete TheModuleProvider; - delete TheModule; } Jnjvm::Jnjvm() { @@ -828,5 +827,4 @@ javaTypes = 0; globalRefsLock = 0; TheModuleProvider = 0; - TheModule = 0; } From nicolas.geoffray at lip6.fr Tue Jun 17 05:07:21 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 17 Jun 2008 10:07:21 -0000 Subject: [llvm-commits] [vmkit] r52394 - /vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp Message-ID: <200806171007.m5HA7McN002631@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jun 17 05:07:21 2008 New Revision: 52394 URL: http://llvm.org/viewvc/llvm-project?rev=52394&view=rev Log: Fix Class and CommonClass memory leaks. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp?rev=52394&r1=52393&r2=52394&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaClass.cpp Tue Jun 17 05:07:21 2008 @@ -82,17 +82,24 @@ CommonClass::~CommonClass() { free(display); + free(virtualVT); if (isolate) isolate->TheModule->removeClass(this); + delete lockVar; + delete condVar; } CommonClass::CommonClass() { display = 0; isolate = 0; + lockVar = 0; + condVar = 0; + virtualVT = 0; } Class::Class() { ctpInfo = 0; + staticVT = 0; } Class::~Class() { @@ -127,6 +134,7 @@ } delete ctpInfo; + free(staticVT); } JavaField::~JavaField() { From nicolas.geoffray at lip6.fr Tue Jun 17 05:11:39 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 17 Jun 2008 10:11:39 -0000 Subject: [llvm-commits] [vmkit] r52395 - in /vmkit/trunk/lib/JnJVM/VMCore: JavaObject.cpp JavaObject.h Message-ID: <200806171011.m5HABdkU002772@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jun 17 05:11:39 2008 New Revision: 52395 URL: http://llvm.org/viewvc/llvm-project?rev=52395&view=rev Log: A default JavaObject does not have a destructor. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaObject.h Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp?rev=52395&r1=52394&r2=52395&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp Tue Jun 17 05:11:39 2008 @@ -252,9 +252,3 @@ varcond = 0; lock = 0; } - -#ifdef USE_GC_BOEHM -JavaObject::~JavaObject() { - if (lockObj()) delete lockObj(); -} -#endif Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaObject.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaObject.h?rev=52395&r1=52394&r2=52395&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaObject.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaObject.h Tue Jun 17 05:11:39 2008 @@ -206,13 +206,6 @@ virtual void print(mvm::PrintBuffer* buf) const; virtual void TRACER; -#ifdef USE_GC_BOEHM - ~JavaObject(); - JavaObject() { - lockObj = 0; - } -#endif - LockObj* lockObj() { if (lock & 0x80000000) { return (LockObj*)(lock << 1); From matthijs at stdin.nl Tue Jun 17 07:02:54 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Tue, 17 Jun 2008 12:02:54 -0000 Subject: [llvm-commits] [llvm] r52396 - in /llvm/trunk: lib/Transforms/IPO/IPConstantPropagation.cpp test/Transforms/IPConstantProp/return-constants.ll Message-ID: <200806171202.m5HC2tXA006123@zion.cs.uiuc.edu> Author: matthijs Date: Tue Jun 17 07:02:52 2008 New Revision: 52396 URL: http://llvm.org/viewvc/llvm-project?rev=52396&view=rev Log: Learn IPConstProp to look at individual return values and propagate them individually. Also learn IPConstProp how returning first class aggregates work, in addition to old style multiple return instructions. Modify the return-constants testscase to confirm this behaviour. Modified: llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp llvm/trunk/test/Transforms/IPConstantProp/return-constants.ll Modified: llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp?rev=52396&r1=52395&r2=52396&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp (original) +++ llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp Tue Jun 17 07:02:52 2008 @@ -21,6 +21,7 @@ #include "llvm/Instructions.h" #include "llvm/Module.h" #include "llvm/Pass.h" +#include "llvm/Analysis/ValueTracking.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/Compiler.h" #include "llvm/ADT/Statistic.h" @@ -140,9 +141,10 @@ } -// Check to see if this function returns a constant. If so, replace all callers -// that user the return value with the returned valued. If we can replace ALL -// callers, +// Check to see if this function returns one or more constants. If so, replace +// all callers that use those return values with the constant value. This will +// leave in the actual return values and instructions, but deadargelim will +// clean that up. bool IPCP::PropagateConstantReturn(Function &F) { if (F.getReturnType() == Type::VoidTy) return false; // No return value. @@ -156,48 +158,65 @@ SmallVector RetVals; const StructType *STy = dyn_cast(F.getReturnType()); if (STy) - RetVals.assign(STy->getNumElements(), 0); + for (unsigned i = 0, e = STy->getNumElements(); i < e; ++i) + RetVals.push_back(UndefValue::get(STy->getElementType(i))); else - RetVals.push_back(0); + RetVals.push_back(UndefValue::get(F.getReturnType())); + unsigned NumNonConstant = 0; for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { - assert(RetVals.size() == RI->getNumOperands() && - "Invalid ReturnInst operands!"); + // Return type does not match operand type, this is an old style multiple + // return + bool OldReturn = (F.getReturnType() != RI->getOperand(0)->getType()); + for (unsigned i = 0, e = RetVals.size(); i != e; ++i) { - if (isa(RI->getOperand(i))) - continue; // Ignore - Constant *C = dyn_cast(RI->getOperand(i)); - if (C == 0) - return false; // Does not return a constant. - + // Already found conflicting return values? Value *RV = RetVals[i]; - if (RV == 0) - RetVals[i] = C; - else if (RV != C) - return false; // Does not return the same constant. + if (!RV) + continue; + + // Find the returned value + Value *V; + if (!STy || OldReturn) + V = RI->getOperand(i); + else + V = FindInsertedValue(RI->getOperand(0), i); + + if (V) { + // Ignore undefs, we can change them into anything + if (isa(V)) + continue; + + // Try to see if all the rets return the same constant. + if (isa(V)) { + if (isa(RV)) { + // No value found yet? Try the current one. + RetVals[i] = V; + continue; + } + // Returning the same value? Good. + if (RV == V) + continue; + } + } + // Different or no known return value? Don't propagate this return + // value. + RetVals[i] = 0; + // All values non constant? Stop looking. + if (++NumNonConstant == RetVals.size()) + return false; } } - if (STy) { - for (unsigned i = 0, e = RetVals.size(); i < e; ++i) - if (RetVals[i] == 0) - RetVals[i] = UndefValue::get(STy->getElementType(i)); - } else { - assert(RetVals.size() == 1); - if (RetVals[0] == 0) - RetVals[0] = UndefValue::get(F.getReturnType()); - } - - // If we got here, the function returns a constant value. Loop over all - // users, replacing any uses of the return value with the returned constant. - bool ReplacedAllUsers = true; + // If we got here, the function returns at least one constant value. Loop + // over all users, replacing any uses of the return value with the returned + // constant. bool MadeChange = false; for (Value::use_iterator UI = F.use_begin(), E = F.use_end(); UI != E; ++UI) { // Make sure this is an invoke or call and that the use is for the callee. if (!(isa(*UI) || isa(*UI)) || UI.getOperandNo() != 0) { - ReplacedAllUsers = false; continue; } @@ -212,28 +231,32 @@ continue; } - while (!Call->use_empty()) { - GetResultInst *GR = cast(Call->use_back()); - GR->replaceAllUsesWith(RetVals[GR->getIndex()]); - GR->eraseFromParent(); - } - } - - // If we replace all users with the returned constant, and there can be no - // other callers of the function, replace the constant being returned in the - // function with an undef value. - if (ReplacedAllUsers && F.hasInternalLinkage()) { - for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { - if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { - for (unsigned i = 0, e = RetVals.size(); i < e; ++i) { - Value *RetVal = RetVals[i]; - if (isa(RetVal)) - continue; - Value *RV = UndefValue::get(RetVal->getType()); - if (RI->getOperand(i) != RV) { - RI->setOperand(i, RV); - MadeChange = true; - } + for (Value::use_iterator I = Call->use_begin(), E = Call->use_end(); + I != E;) { + Instruction *Ins = dyn_cast(*I); + + // Increment now, so we can remove the use + ++I; + + // Not an instruction? Ignore + if (!Ins) + continue; + + // Find the index of the retval to replace with + int index = -1; + if (GetResultInst *GR = dyn_cast(Ins)) + index = GR->getIndex(); + else if (ExtractValueInst *EV = dyn_cast(Ins)) + if (EV->hasIndices()) + index = *EV->idx_begin(); + + // If this use uses a specific return value, and we have a replacement, + // replace it. + if (index != -1) { + Value *New = RetVals[index]; + if (New) { + Ins->replaceAllUsesWith(New); + Ins->eraseFromParent(); } } } Modified: llvm/trunk/test/Transforms/IPConstantProp/return-constants.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/return-constants.ll?rev=52396&r1=52395&r2=52396&view=diff ============================================================================== --- llvm/trunk/test/Transforms/IPConstantProp/return-constants.ll (original) +++ llvm/trunk/test/Transforms/IPConstantProp/return-constants.ll Tue Jun 17 07:02:52 2008 @@ -1,20 +1,41 @@ -; RUN: llvm-as < %s | opt -ipconstprop | llvm-dis | grep {add i32 21, 21} +; RUN: llvm-as < %s | opt -ipconstprop | llvm-dis > %t +;; Check that the 21 constants got propagated properly +; RUN: cat %t | grep {%M = add i32 21, 21} +;; Check that the second return values didn't get propagated +; RUN: cat %t | grep {%N = add i32 %B, %D} -define internal {i32, i32} @foo(i1 %C) { - br i1 %C, label %T, label %F +define internal {i32, i32} @foo(i1 %Q) { + br i1 %Q, label %T, label %F T: ; preds = %0 - ret i32 21, i32 21 + ret i32 21, i32 22 F: ; preds = %0 - ret i32 21, i32 21 + ret i32 21, i32 23 } -define i32 @caller(i1 %C) { - %X = call {i32, i32} @foo( i1 %C ) +define internal {i32, i32} @bar(i1 %Q) { + %A = insertvalue { i32, i32 } undef, i32 21, 0 + br i1 %Q, label %T, label %F + +T: ; preds = %0 + %B = insertvalue { i32, i32 } %A, i32 22, 1 + ret { i32, i32 } %B + +F: ; preds = %0 + %C = insertvalue { i32, i32 } %A, i32 23, 1 + ret { i32, i32 } %C +} + +define { i32, i32 } @caller(i1 %Q) { + %X = call {i32, i32} @foo( i1 %Q ) %A = getresult {i32, i32} %X, 0 %B = getresult {i32, i32} %X, 1 - %Y = add i32 %A, %B - ret i32 %Y + %Y = call {i32, i32} @bar( i1 %Q ) + %C = extractvalue {i32, i32} %Y, 0 + %D = extractvalue {i32, i32} %Y, 1 + %M = add i32 %A, %C + %N = add i32 %B, %D + ret { i32, i32 } %X } From matthijs at stdin.nl Tue Jun 17 07:20:36 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Tue, 17 Jun 2008 12:20:36 -0000 Subject: [llvm-commits] [llvm] r52397 - /llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp Message-ID: <200806171220.m5HCKbc2006679@zion.cs.uiuc.edu> Author: matthijs Date: Tue Jun 17 07:20:24 2008 New Revision: 52397 URL: http://llvm.org/viewvc/llvm-project?rev=52397&view=rev Log: Learn IPConstProp to propagate arguments that are directly returned. Strictly speaking these are not constant values. However, when a function always returns one of its arguments, then from the point of view of each caller the return value is constant (or at least a known value) and can be replaced. Modified: llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp Modified: llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp?rev=52397&r1=52396&r2=52397&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp (original) +++ llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp Tue Jun 17 07:20:24 2008 @@ -145,6 +145,10 @@ // all callers that use those return values with the constant value. This will // leave in the actual return values and instructions, but deadargelim will // clean that up. +// +// Additionally if a function always returns one of its arguments directly, +// callers will be updated to use the value they pass in directly instead of +// using the return value. bool IPCP::PropagateConstantReturn(Function &F) { if (F.getReturnType() == Type::VoidTy) return false; // No return value. @@ -188,8 +192,8 @@ if (isa(V)) continue; - // Try to see if all the rets return the same constant. - if (isa(V)) { + // Try to see if all the rets return the same constant or argument. + if (isa(V) || isa(V)) { if (isa(RV)) { // No value found yet? Try the current one. RetVals[i] = V; @@ -255,6 +259,11 @@ if (index != -1) { Value *New = RetVals[index]; if (New) { + if (Argument *A = dyn_cast(New)) + // Was an argument returned? Then find the corresponding argument in + // the call instruction and use that. Add 1 to the argument number + // to skipp the first argument (the function itself). + New = Call->getOperand(A->getArgNo() + 1); Ins->replaceAllUsesWith(New); Ins->eraseFromParent(); } From matthijs at stdin.nl Tue Jun 17 08:54:33 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Tue, 17 Jun 2008 13:54:33 -0000 Subject: [llvm-commits] [llvm] r52401 - /llvm/trunk/include/llvm/Analysis/ValueTracking.h Message-ID: <200806171354.m5HDsXBD009677@zion.cs.uiuc.edu> Author: matthijs Date: Tue Jun 17 08:54:33 2008 New Revision: 52401 URL: http://llvm.org/viewvc/llvm-project?rev=52401&view=rev Log: Forgot to commit the ValueTracking header file along with r52396. Modified: llvm/trunk/include/llvm/Analysis/ValueTracking.h Modified: llvm/trunk/include/llvm/Analysis/ValueTracking.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ValueTracking.h?rev=52401&r1=52400&r2=52401&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/ValueTracking.h (original) +++ llvm/trunk/include/llvm/Analysis/ValueTracking.h Tue Jun 17 08:54:33 2008 @@ -62,6 +62,13 @@ const unsigned *idx_begin, const unsigned *idx_end, Instruction *InsertBefore = 0); + + /// This is a convenience wrapper for finding values indexed by a single index + /// only. + inline Value *FindInsertedValue(Value *V, const unsigned Idx, + Instruction *InsertBefore = 0) { + return FindInsertedValue(V, &Idx, &Idx + 1, InsertBefore); + } } // end namespace llvm #endif From nicolas.geoffray at lip6.fr Tue Jun 17 09:19:35 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 17 Jun 2008 14:19:35 -0000 Subject: [llvm-commits] [vmkit] r52404 - /vmkit/trunk/lib/Mvm/GCMmap2/gccollector.cpp Message-ID: <200806171419.m5HEJac7010438@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jun 17 09:19:35 2008 New Revision: 52404 URL: http://llvm.org/viewvc/llvm-project?rev=52404&view=rev Log: Unlock the allocation lock before finalization. Call finalization methods before freeing memory. Modified: vmkit/trunk/lib/Mvm/GCMmap2/gccollector.cpp Modified: vmkit/trunk/lib/Mvm/GCMmap2/gccollector.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/GCMmap2/gccollector.cpp?rev=52404&r1=52403&r2=52404&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/GCMmap2/gccollector.cpp (original) +++ vmkit/trunk/lib/Mvm/GCMmap2/gccollector.cpp Tue Jun 17 09:19:35 2008 @@ -81,12 +81,11 @@ finalizable.attrape(unused_nodes); status = stat_alloc; -#ifdef HAVE_PTHREAD - threads->collectionFinished(); -#endif + unlock(); + /* kill everyone */ - GCChunkNode *next; + GCChunkNode *next = 0; for(cur=finalizable.next(); cur!=&finalizable; cur=next) { #ifdef SERVICE_GC @@ -98,10 +97,20 @@ destructor_t dest = c->getDestructor(); if (dest) dest(c); - + } + + next = 0; + for(cur=finalizable.next(); cur!=&finalizable; cur=next) { //printf(" !!!! reject %p [%p]\n", cur->chunk()->_2gc(), cur); + next = cur->next(); allocator->reject_chunk(cur); } + + lock(); + +#ifdef HAVE_PTHREAD + threads->collectionFinished(); +#endif } void GCCollector::collect_unprotect() { From nicolas.geoffray at lip6.fr Tue Jun 17 09:24:45 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 17 Jun 2008 14:24:45 -0000 Subject: [llvm-commits] [vmkit] r52405 - in /vmkit/trunk/lib/JnJVM/VMCore: JavaObject.cpp VirtualTables.cpp Message-ID: <200806171424.m5HEOjdP010629@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jun 17 09:24:45 2008 New Revision: 52405 URL: http://llvm.org/viewvc/llvm-project?rev=52405&view=rev Log: LockObj are not GC-allocated anymore. This leads to memory leaks, but will help to implement LockObj hash tables. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp?rev=52405&r1=52404&r2=52405&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp Tue Jun 17 09:24:45 2008 @@ -73,11 +73,7 @@ } LockObj* LockObj::allocate() { -#ifdef USE_GC_BOEHM LockObj* res = new LockObj(); -#else - LockObj* res = vm_new(JavaThread::get()->isolate, LockObj)(); -#endif res->lock = mvm::Lock::allocRecursive(); res->varcond = 0; return res; Modified: vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp?rev=52405&r1=52404&r2=52405&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp Tue Jun 17 09:24:45 2008 @@ -111,7 +111,6 @@ void JavaObject::TRACER { classOf->MARK_AND_TRACE; - if (lockObj()) lockObj()->MARK_AND_TRACE; } #ifdef MULTIPLE_GC @@ -120,7 +119,6 @@ extern "C" void JavaObjectTracer(JavaObject* obj) { #endif obj->classOf->MARK_AND_TRACE; - if (obj->lockObj()) obj->lockObj()->MARK_AND_TRACE; } From nicolas.geoffray at lip6.fr Tue Jun 17 09:25:35 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 17 Jun 2008 14:25:35 -0000 Subject: [llvm-commits] [vmkit] r52406 - /vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.cpp Message-ID: <200806171425.m5HEPZrV010663@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jun 17 09:25:34 2008 New Revision: 52406 URL: http://llvm.org/viewvc/llvm-project?rev=52406&view=rev Log: Bugfixes for inline compile. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.cpp?rev=52406&r1=52405&r2=52406&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaJIT.cpp Tue Jun 17 09:25:34 2008 @@ -483,14 +483,19 @@ reader.seek(codeLen, Reader::SeekCur); - const FunctionType *funcType = llvmFunction->getFunctionType(); + LLVMMethodInfo* LMI = module->getMethodInfo(compilingMethod); + assert(LMI); + Function* func = LMI->getMethod(); + llvmFunction = parentFunction; + + const FunctionType *funcType = func->getFunctionType(); returnType = funcType->getReturnType(); endBlock = createBasicBlock("end"); llvmFunction = parentFunction; currentBlock = curBB; endExceptionBlock = 0; - + opcodeInfos = (Opinfo*)alloca(codeLen * sizeof(Opinfo)); memset(opcodeInfos, 0, codeLen * sizeof(Opinfo)); for (uint32 i = 0; i < codeLen; ++i) { @@ -531,10 +536,10 @@ if (cur == AssessorDesc::dLong){ new StoreInst(*i, longLocals[index], false, currentBlock); ++index; - } else if (AssessorDesc::dBool || cur == AssessorDesc::dChar) { + } else if (cur == AssessorDesc::dBool || cur == AssessorDesc::dChar) { new StoreInst(new ZExtInst(*i, Type::Int32Ty, "", currentBlock), intLocals[index], false, currentBlock); - } else if (AssessorDesc::dByte || cur == AssessorDesc::dShort) { + } else if (cur == AssessorDesc::dByte || cur == AssessorDesc::dShort) { new StoreInst(new SExtInst(*i, Type::Int32Ty, "", currentBlock), intLocals[index], false, currentBlock); } else if (cur == AssessorDesc::dInt) { From nicolas.geoffray at lip6.fr Tue Jun 17 09:26:15 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 17 Jun 2008 14:26:15 -0000 Subject: [llvm-commits] [vmkit] r52407 - in /vmkit/trunk/lib/JnJVM/VMCore: JavaInitialise.cpp Jnjvm.cpp Jnjvm.h JnjvmModule.cpp JnjvmModuleProvider.cpp JnjvmModuleProvider.h Message-ID: <200806171426.m5HEQFW0010699@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jun 17 09:26:15 2008 New Revision: 52407 URL: http://llvm.org/viewvc/llvm-project?rev=52407&view=rev Log: Implement Java object finalization. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h vmkit/trunk/lib/JnJVM/VMCore/JnjvmModule.cpp vmkit/trunk/lib/JnJVM/VMCore/JnjvmModuleProvider.cpp vmkit/trunk/lib/JnJVM/VMCore/JnjvmModuleProvider.h Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp?rev=52407&r1=52406&r2=52407&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp Tue Jun 17 09:26:15 2008 @@ -182,6 +182,7 @@ DEF_UTF8(log1p); DEF_UTF8(sinh); DEF_UTF8(tanh); + DEF_UTF8(finalize); #undef DEF_UTF8 Modified: vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp?rev=52407&r1=52406&r2=52407&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.cpp Tue Jun 17 09:26:15 2008 @@ -73,6 +73,7 @@ DEF_UTF8(log1p); DEF_UTF8(sinh); DEF_UTF8(tanh); + DEF_UTF8(finalize); #undef DEF_UTF8 Modified: vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h?rev=52407&r1=52406&r2=52407&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/Jnjvm.h Tue Jun 17 09:26:15 2008 @@ -174,6 +174,7 @@ static const UTF8* log1p; static const UTF8* sinh; static const UTF8* tanh; + static const UTF8* finalize; void analyseClasspathEnv(const char*); Modified: vmkit/trunk/lib/JnJVM/VMCore/JnjvmModule.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JnjvmModule.cpp?rev=52407&r1=52406&r2=52407&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JnjvmModule.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JnjvmModule.cpp Tue Jun 17 09:26:15 2008 @@ -191,22 +191,42 @@ return VT; } else { JavaMethod* meth = meths->second; - JavaMethod* parent = cl->super? - cl->super->lookupMethodDontThrow(meth->name, meth->type, false, true) : 0; - - uint64_t offset = 0; - if (!parent) { - offset = cl->virtualTableSize++; - meth->offset = offset; + VirtualTable* VT = 0; + if (meth->name->equals(Jnjvm::finalize)) { + VT = allocateVT(cl, ++meths); + meth->offset = 0; + Function* func = cl->isolate->TheModuleProvider->parseFunction(meth); + if (!cl->super) meth->canBeInlined = true; + Function::iterator BB = func->begin(); + BasicBlock::iterator I = BB->begin(); + if (isa(I)) { + ((void**)VT)[0] = 0; + } else { + ExecutionEngine* EE = mvm::jit::executionEngine; + // LLVM does not allow recursive compilation. Create the code now. + ((void**)VT)[0] = EE->getPointerToFunction(func); + } } else { - offset = parent->offset; - meth->offset = parent->offset; + + JavaMethod* parent = cl->super? + cl->super->lookupMethodDontThrow(meth->name, meth->type, false, true) : + 0; + + uint64_t offset = 0; + if (!parent) { + offset = cl->virtualTableSize++; + meth->offset = offset; + } else { + offset = parent->offset; + meth->offset = parent->offset; + } + VT = allocateVT(cl, ++meths); + LLVMMethodInfo* LMI = getMethodInfo(meth); + Function* func = LMI->getMethod(); + ExecutionEngine* EE = mvm::jit::executionEngine; + ((void**)VT)[offset] = EE->getPointerToFunctionOrStub(func); } - VirtualTable* VT = allocateVT(cl, ++meths); - LLVMMethodInfo* LMI = getMethodInfo(meth); - Function* func = LMI->getMethod(); - ExecutionEngine* EE = mvm::jit::executionEngine; - ((void**)VT)[offset] = EE->getPointerToFunctionOrStub(func); + return VT; } } @@ -249,7 +269,9 @@ } } #endif - + + + #ifdef WITH_TRACER LLVMClassInfo* LCI = (LLVMClassInfo*)getClassInfo(cl); const Type* type = stat ? LCI->getStaticType() : LCI->getVirtualType(); Modified: vmkit/trunk/lib/JnJVM/VMCore/JnjvmModuleProvider.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JnjvmModuleProvider.cpp?rev=52407&r1=52406&r2=52407&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JnjvmModuleProvider.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JnjvmModuleProvider.cpp Tue Jun 17 09:26:15 2008 @@ -105,6 +105,15 @@ } void* JnjvmModuleProvider::materializeFunction(JavaMethod* meth) { + Function* func = parseFunction(meth); + + void* res = mvm::jit::executionEngine->getPointerToGlobal(func); + mvm::Code* m = mvm::jit::getCodeFromPointer(res); + if (m) m->setMetaInfo(meth); + return res; +} + +Function* JnjvmModuleProvider::parseFunction(JavaMethod* meth) { LLVMMethodInfo* LMI = ((JnjvmModule*)TheModule)->getMethodInfo(meth); Function* func = LMI->getMethod(); if (func->hasNotBeenReadFromBitcode()) { @@ -122,11 +131,7 @@ mvm::jit::runPasses(func, perFunctionPasses); } } - - void* res = mvm::jit::executionEngine->getPointerToGlobal(func); - mvm::Code* m = mvm::jit::getCodeFromPointer(res); - if (m) m->setMetaInfo(meth); - return res; + return func; } llvm::Function* JnjvmModuleProvider::addCallback(Class* cl, uint32 index, Modified: vmkit/trunk/lib/JnJVM/VMCore/JnjvmModuleProvider.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JnjvmModuleProvider.h?rev=52407&r1=52406&r2=52407&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JnjvmModuleProvider.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JnjvmModuleProvider.h Tue Jun 17 09:26:15 2008 @@ -51,6 +51,7 @@ bool materializeFunction(Function *F, std::string *ErrInfo = 0); void* materializeFunction(JavaMethod* meth); + llvm::Function* parseFunction(JavaMethod* meth); Module* materializeModule(std::string *ErrInfo = 0) { return TheModule; } }; From baldrick at free.fr Tue Jun 17 09:27:01 2008 From: baldrick at free.fr (Duncan Sands) Date: Tue, 17 Jun 2008 14:27:01 -0000 Subject: [llvm-commits] [llvm] r52408 - in /llvm/trunk/lib/CodeGen/SelectionDAG: LegalizeFloatTypes.cpp LegalizeIntegerTypes.cpp LegalizeTypes.cpp LegalizeTypes.h LegalizeTypesExpand.cpp LegalizeTypesFloatToInt.cpp LegalizeTypesPromote.cpp LegalizeTypesScalarize.cpp LegalizeTypesSplit.cpp LegalizeVectorTypes.cpp Message-ID: <200806171427.m5HER2eh010747@zion.cs.uiuc.edu> Author: baldrick Date: Tue Jun 17 09:27:01 2008 New Revision: 52408 URL: http://llvm.org/viewvc/llvm-project?rev=52408&view=rev Log: Split type expansion into ExpandInteger and ExpandFloat rather than bundling them together. Rename FloatToInt to PromoteFloat (better, if not perfect). Reorganize files by types rather than by operations. Added: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp Removed: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesFloatToInt.cpp llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesScalarize.cpp llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h Added: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp?rev=52408&view=auto ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp (added) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp Tue Jun 17 09:27:01 2008 @@ -0,0 +1,452 @@ +//===-------- LegalizeFloatTypes.cpp - Legalization of float types --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements float type expansion and conversion of float types to +// integer types on behalf of LegalizeTypes. +// Converting to integer is the act of turning a computation in an illegal +// floating point type into a computation in an integer type of the same size. +// For example, turning f32 arithmetic into operations using i32. Also known as +// "soft float". The result is equivalent to bitcasting the float value to the +// integer type. +// Expansion is the act of changing a computation in an illegal type to be a +// computation in multiple registers of a smaller type. For example, +// implementing ppcf128 arithmetic in two f64 registers. +// +//===----------------------------------------------------------------------===// + +#include "LegalizeTypes.h" +#include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +using namespace llvm; + +/// GetFPLibCall - Return the right libcall for the given floating point type. +static RTLIB::Libcall GetFPLibCall(MVT VT, + RTLIB::Libcall Call_F32, + RTLIB::Libcall Call_F64, + RTLIB::Libcall Call_F80, + RTLIB::Libcall Call_PPCF128) { + return + VT == MVT::f32 ? Call_F32 : + VT == MVT::f64 ? Call_F64 : + VT == MVT::f80 ? Call_F80 : + VT == MVT::ppcf128 ? Call_PPCF128 : + RTLIB::UNKNOWN_LIBCALL; +} + +//===----------------------------------------------------------------------===// +// Result Float to Integer Conversion. +//===----------------------------------------------------------------------===// + +void DAGTypeLegalizer::PromoteFloatResult(SDNode *N, unsigned ResNo) { + DEBUG(cerr << "Promote float result " << ResNo << ": "; N->dump(&DAG); + cerr << "\n"); + SDOperand R = SDOperand(); + + // FIXME: Custom lowering for float-to-int? +#if 0 + // See if the target wants to custom convert this node to an integer. + if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == + TargetLowering::Custom) { + // If the target wants to, allow it to lower this itself. + if (SDNode *P = TLI.FloatToIntOperationResult(N, DAG)) { + // Everything that once used N now uses P. We are guaranteed that the + // result value types of N and the result value types of P match. + ReplaceNodeWith(N, P); + return; + } + } +#endif + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + cerr << "PromoteFloatResult #" << ResNo << ": "; + N->dump(&DAG); cerr << "\n"; +#endif + assert(0 && "Do not know how to convert the result of this operator!"); + abort(); + + case ISD::BIT_CONVERT: R = PromoteFloatRes_BIT_CONVERT(N); break; + case ISD::BUILD_PAIR: R = PromoteFloatRes_BUILD_PAIR(N); break; + case ISD::ConstantFP: + R = PromoteFloatRes_ConstantFP(cast(N)); + break; + case ISD::FCOPYSIGN: R = PromoteFloatRes_FCOPYSIGN(N); break; + case ISD::LOAD: R = PromoteFloatRes_LOAD(N); break; + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: R = PromoteFloatRes_XINT_TO_FP(N); break; + + case ISD::FADD: R = PromoteFloatRes_FADD(N); break; + case ISD::FMUL: R = PromoteFloatRes_FMUL(N); break; + case ISD::FSUB: R = PromoteFloatRes_FSUB(N); break; + } + + // If R is null, the sub-method took care of registering the result. + if (R.Val) + SetPromotedFloat(SDOperand(N, ResNo), R); +} + +SDOperand DAGTypeLegalizer::PromoteFloatRes_BIT_CONVERT(SDNode *N) { + return BitConvertToInteger(N->getOperand(0)); +} + +SDOperand DAGTypeLegalizer::PromoteFloatRes_BUILD_PAIR(SDNode *N) { + // Convert the inputs to integers, and build a new pair out of them. + return DAG.getNode(ISD::BUILD_PAIR, + TLI.getTypeToTransformTo(N->getValueType(0)), + BitConvertToInteger(N->getOperand(0)), + BitConvertToInteger(N->getOperand(1))); +} + +SDOperand DAGTypeLegalizer::PromoteFloatRes_ConstantFP(ConstantFPSDNode *N) { + return DAG.getConstant(N->getValueAPF().convertToAPInt(), + TLI.getTypeToTransformTo(N->getValueType(0))); +} + +SDOperand DAGTypeLegalizer::PromoteFloatRes_FADD(SDNode *N) { + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + SDOperand Ops[2] = { GetPromotedFloat(N->getOperand(0)), + GetPromotedFloat(N->getOperand(1)) }; + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::ADD_F32, + RTLIB::ADD_F64, + RTLIB::ADD_F80, + RTLIB::ADD_PPCF128), + NVT, Ops, 2, false/*sign irrelevant*/); +} + +SDOperand DAGTypeLegalizer::PromoteFloatRes_FCOPYSIGN(SDNode *N) { + SDOperand LHS = GetPromotedFloat(N->getOperand(0)); + SDOperand RHS = BitConvertToInteger(N->getOperand(1)); + + MVT LVT = LHS.getValueType(); + MVT RVT = RHS.getValueType(); + + unsigned LSize = LVT.getSizeInBits(); + unsigned RSize = RVT.getSizeInBits(); + + // First get the sign bit of second operand. + SDOperand SignBit = DAG.getNode(ISD::SHL, RVT, DAG.getConstant(1, RVT), + DAG.getConstant(RSize - 1, + TLI.getShiftAmountTy())); + SignBit = DAG.getNode(ISD::AND, RVT, RHS, SignBit); + + // Shift right or sign-extend it if the two operands have different types. + int SizeDiff = RVT.getSizeInBits() - LVT.getSizeInBits(); + if (SizeDiff > 0) { + SignBit = DAG.getNode(ISD::SRL, RVT, SignBit, + DAG.getConstant(SizeDiff, TLI.getShiftAmountTy())); + SignBit = DAG.getNode(ISD::TRUNCATE, LVT, SignBit); + } else if (SizeDiff < 0) { + SignBit = DAG.getNode(ISD::ANY_EXTEND, LVT, SignBit); + SignBit = DAG.getNode(ISD::SHL, LVT, SignBit, + DAG.getConstant(-SizeDiff, TLI.getShiftAmountTy())); + } + + // Clear the sign bit of the first operand. + SDOperand Mask = DAG.getNode(ISD::SHL, LVT, DAG.getConstant(1, LVT), + DAG.getConstant(LSize - 1, + TLI.getShiftAmountTy())); + Mask = DAG.getNode(ISD::SUB, LVT, Mask, DAG.getConstant(1, LVT)); + LHS = DAG.getNode(ISD::AND, LVT, LHS, Mask); + + // Or the value with the sign bit. + return DAG.getNode(ISD::OR, LVT, LHS, SignBit); +} + +SDOperand DAGTypeLegalizer::PromoteFloatRes_FMUL(SDNode *N) { + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + SDOperand Ops[2] = { GetPromotedFloat(N->getOperand(0)), + GetPromotedFloat(N->getOperand(1)) }; + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::MUL_F32, + RTLIB::MUL_F64, + RTLIB::MUL_F80, + RTLIB::MUL_PPCF128), + NVT, Ops, 2, false/*sign irrelevant*/); +} + +SDOperand DAGTypeLegalizer::PromoteFloatRes_FSUB(SDNode *N) { + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + SDOperand Ops[2] = { GetPromotedFloat(N->getOperand(0)), + GetPromotedFloat(N->getOperand(1)) }; + return MakeLibCall(GetFPLibCall(N->getValueType(0), + RTLIB::SUB_F32, + RTLIB::SUB_F64, + RTLIB::SUB_F80, + RTLIB::SUB_PPCF128), + NVT, Ops, 2, false/*sign irrelevant*/); +} + +SDOperand DAGTypeLegalizer::PromoteFloatRes_LOAD(SDNode *N) { + LoadSDNode *L = cast(N); + MVT VT = N->getValueType(0); + MVT NVT = TLI.getTypeToTransformTo(VT); + + if (L->getExtensionType() == ISD::NON_EXTLOAD) + return DAG.getLoad(L->getAddressingMode(), L->getExtensionType(), + NVT, L->getChain(), L->getBasePtr(), L->getOffset(), + L->getSrcValue(), L->getSrcValueOffset(), NVT, + L->isVolatile(), L->getAlignment()); + + // Do a non-extending load followed by FP_EXTEND. + SDOperand NL = DAG.getLoad(L->getAddressingMode(), ISD::NON_EXTLOAD, + L->getMemoryVT(), L->getChain(), + L->getBasePtr(), L->getOffset(), + L->getSrcValue(), L->getSrcValueOffset(), + L->getMemoryVT(), + L->isVolatile(), L->getAlignment()); + return BitConvertToInteger(DAG.getNode(ISD::FP_EXTEND, VT, NL)); +} + +SDOperand DAGTypeLegalizer::PromoteFloatRes_XINT_TO_FP(SDNode *N) { + bool isSigned = N->getOpcode() == ISD::SINT_TO_FP; + MVT DestVT = N->getValueType(0); + SDOperand Op = N->getOperand(0); + + if (Op.getValueType() == MVT::i32) { + // simple 32-bit [signed|unsigned] integer to float/double expansion + + // Get the stack frame index of a 8 byte buffer. + SDOperand StackSlot = DAG.CreateStackTemporary(MVT::f64); + + // word offset constant for Hi/Lo address computation + SDOperand Offset = + DAG.getConstant(MVT(MVT::i32).getSizeInBits() / 8, + TLI.getPointerTy()); + // set up Hi and Lo (into buffer) address based on endian + SDOperand Hi = StackSlot; + SDOperand Lo = DAG.getNode(ISD::ADD, TLI.getPointerTy(), StackSlot, Offset); + if (TLI.isLittleEndian()) + std::swap(Hi, Lo); + + // if signed map to unsigned space + SDOperand OpMapped; + if (isSigned) { + // constant used to invert sign bit (signed to unsigned mapping) + SDOperand SignBit = DAG.getConstant(0x80000000u, MVT::i32); + OpMapped = DAG.getNode(ISD::XOR, MVT::i32, Op, SignBit); + } else { + OpMapped = Op; + } + // store the lo of the constructed double - based on integer input + SDOperand Store1 = DAG.getStore(DAG.getEntryNode(), + OpMapped, Lo, NULL, 0); + // initial hi portion of constructed double + SDOperand InitialHi = DAG.getConstant(0x43300000u, MVT::i32); + // store the hi of the constructed double - biased exponent + SDOperand Store2=DAG.getStore(Store1, InitialHi, Hi, NULL, 0); + // load the constructed double + SDOperand Load = DAG.getLoad(MVT::f64, Store2, StackSlot, NULL, 0); + // FP constant to bias correct the final result + SDOperand Bias = DAG.getConstantFP(isSigned ? + BitsToDouble(0x4330000080000000ULL) + : BitsToDouble(0x4330000000000000ULL), + MVT::f64); + // subtract the bias + SDOperand Sub = DAG.getNode(ISD::FSUB, MVT::f64, Load, Bias); + // final result + SDOperand Result; + // handle final rounding + if (DestVT == MVT::f64) { + // do nothing + Result = Sub; + } else if (DestVT.bitsLT(MVT::f64)) { + Result = DAG.getNode(ISD::FP_ROUND, DestVT, Sub, + DAG.getIntPtrConstant(0)); + } else if (DestVT.bitsGT(MVT::f64)) { + Result = DAG.getNode(ISD::FP_EXTEND, DestVT, Sub); + } + return BitConvertToInteger(Result); + } + assert(!isSigned && "Legalize cannot Expand SINT_TO_FP for i64 yet"); + SDOperand Tmp1 = DAG.getNode(ISD::SINT_TO_FP, DestVT, Op); + + SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultType(Op), Op, + DAG.getConstant(0, Op.getValueType()), + ISD::SETLT); + SDOperand Zero = DAG.getIntPtrConstant(0), Four = DAG.getIntPtrConstant(4); + SDOperand CstOffset = DAG.getNode(ISD::SELECT, Zero.getValueType(), + SignSet, Four, Zero); + + // If the sign bit of the integer is set, the large number will be treated + // as a negative number. To counteract this, the dynamic code adds an + // offset depending on the data type. + uint64_t FF; + switch (Op.getValueType().getSimpleVT()) { + default: assert(0 && "Unsupported integer type!"); + case MVT::i8 : FF = 0x43800000ULL; break; // 2^8 (as a float) + case MVT::i16: FF = 0x47800000ULL; break; // 2^16 (as a float) + case MVT::i32: FF = 0x4F800000ULL; break; // 2^32 (as a float) + case MVT::i64: FF = 0x5F800000ULL; break; // 2^64 (as a float) + } + if (TLI.isLittleEndian()) FF <<= 32; + static Constant *FudgeFactor = ConstantInt::get(Type::Int64Ty, FF); + + SDOperand CPIdx = DAG.getConstantPool(FudgeFactor, TLI.getPointerTy()); + CPIdx = DAG.getNode(ISD::ADD, TLI.getPointerTy(), CPIdx, CstOffset); + SDOperand FudgeInReg; + if (DestVT == MVT::f32) + FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx, + PseudoSourceValue::getConstantPool(), 0); + else { + FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, DestVT, + DAG.getEntryNode(), CPIdx, + PseudoSourceValue::getConstantPool(), 0, + MVT::f32); + } + + return BitConvertToInteger(DAG.getNode(ISD::FADD, DestVT, Tmp1, FudgeInReg)); +} + + +//===----------------------------------------------------------------------===// +// Operand Float to Integer Conversion.. +//===----------------------------------------------------------------------===// + +bool DAGTypeLegalizer::PromoteFloatOperand(SDNode *N, unsigned OpNo) { + DEBUG(cerr << "Promote float operand " << OpNo << ": "; N->dump(&DAG); + cerr << "\n"); + SDOperand Res(0, 0); + + // FIXME: Custom lowering for float-to-int? +#if 0 + if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType()) + == TargetLowering::Custom) + Res = TLI.LowerOperation(SDOperand(N, 0), DAG); +#endif + + if (Res.Val == 0) { + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + cerr << "PromoteFloatOperand Op #" << OpNo << ": "; + N->dump(&DAG); cerr << "\n"; +#endif + assert(0 && "Do not know how to convert this operator's operand!"); + abort(); + + case ISD::BIT_CONVERT: Res = PromoteFloatOp_BIT_CONVERT(N); break; + } + } + + // If the result is null, the sub-method took care of registering results etc. + if (!Res.Val) return false; + + // If the result is N, the sub-method updated N in place. Check to see if any + // operands are new, and if so, mark them. + if (Res.Val == N) { + // Mark N as new and remark N and its operands. This allows us to correctly + // revisit N if it needs another step of promotion and allows us to visit + // any new operands to N. + ReanalyzeNode(N); + return true; + } + + assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && + "Invalid operand expansion"); + + ReplaceValueWith(SDOperand(N, 0), Res); + return false; +} + +SDOperand DAGTypeLegalizer::PromoteFloatOp_BIT_CONVERT(SDNode *N) { + return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), + GetPromotedFloat(N->getOperand(0))); +} + + +//===----------------------------------------------------------------------===// +// Float Result Expansion +//===----------------------------------------------------------------------===// + +/// ExpandFloatResult - This method is called when the specified result of the +/// specified node is found to need expansion. At this point, the node may also +/// have invalid operands or may have other results that need promotion, we just +/// know that (at least) one result needs expansion. +void DAGTypeLegalizer::ExpandFloatResult(SDNode *N, unsigned ResNo) { + DEBUG(cerr << "Expand float result: "; N->dump(&DAG); cerr << "\n"); + SDOperand Lo, Hi; + Lo = Hi = SDOperand(); + + // See if the target wants to custom expand this node. + if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == + TargetLowering::Custom) { + // If the target wants to, allow it to lower this itself. + if (SDNode *P = TLI.ExpandOperationResult(N, DAG)) { + // Everything that once used N now uses P. We are guaranteed that the + // result value types of N and the result value types of P match. + ReplaceNodeWith(N, P); + return; + } + } + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + cerr << "ExpandFloatResult #" << ResNo << ": "; + N->dump(&DAG); cerr << "\n"; +#endif + assert(0 && "Do not know how to expand the result of this operator!"); + abort(); + } + + // If Lo/Hi is null, the sub-method took care of registering results etc. + if (Lo.Val) + SetExpandedFloat(SDOperand(N, ResNo), Lo, Hi); +} + + +//===----------------------------------------------------------------------===// +// Float Operand Expansion +//===----------------------------------------------------------------------===// + +/// ExpandFloatOperand - This method is called when the specified operand of the +/// specified node is found to need expansion. At this point, all of the result +/// types of the node are known to be legal, but other operands of the node may +/// need promotion or expansion as well as the specified one. +bool DAGTypeLegalizer::ExpandFloatOperand(SDNode *N, unsigned OpNo) { + DEBUG(cerr << "Expand float operand: "; N->dump(&DAG); cerr << "\n"); + SDOperand Res(0, 0); + + if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType()) + == TargetLowering::Custom) + Res = TLI.LowerOperation(SDOperand(N, 0), DAG); + + if (Res.Val == 0) { + switch (N->getOpcode()) { + default: + #ifndef NDEBUG + cerr << "ExpandFloatOperand Op #" << OpNo << ": "; + N->dump(&DAG); cerr << "\n"; + #endif + assert(0 && "Do not know how to expand this operator's operand!"); + abort(); + } + } + + // If the result is null, the sub-method took care of registering results etc. + if (!Res.Val) return false; + // If the result is N, the sub-method updated N in place. Check to see if any + // operands are new, and if so, mark them. + if (Res.Val == N) { + // Mark N as new and remark N and its operands. This allows us to correctly + // revisit N if it needs another step of expansion and allows us to visit + // any new operands to N. + ReanalyzeNode(N); + return true; + } + + assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && + "Invalid operand expansion"); + + ReplaceValueWith(SDOperand(N, 0), Res); + return false; +} Added: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp?rev=52408&view=auto ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp (added) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp Tue Jun 17 09:27:01 2008 @@ -0,0 +1,2174 @@ +//===----- LegalizeIntegerTypes.cpp - Legalization of integer types -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements integer type expansion and promotion for LegalizeTypes. +// Promotion is the act of changing a computation in an illegal type into a +// computation in a larger type. For example, implementing i8 arithmetic in an +// i32 register (often needed on powerpc). +// Expansion is the act of changing a computation in an illegal type into a +// computation in multiple registers of a smaller type. For example, +// implementing i64 arithmetic in two i32 registers (often needed on 32-bit +// targets). +// +//===----------------------------------------------------------------------===// + +#include "LegalizeTypes.h" +#include "llvm/Constants.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Integer Result Promotion +//===----------------------------------------------------------------------===// + +/// PromoteIntegerResult - This method is called when a result of a node is +/// found to be in need of promotion to a larger type. At this point, the node +/// may also have invalid operands or may have other results that need +/// expansion, we just know that (at least) one result needs promotion. +void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) { + DEBUG(cerr << "Promote integer result: "; N->dump(&DAG); cerr << "\n"); + SDOperand Result = SDOperand(); + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + cerr << "PromoteIntegerResult #" << ResNo << ": "; + N->dump(&DAG); cerr << "\n"; +#endif + assert(0 && "Do not know how to promote this operator!"); + abort(); + case ISD::UNDEF: Result = PromoteIntRes_UNDEF(N); break; + case ISD::Constant: Result = PromoteIntRes_Constant(N); break; + + case ISD::TRUNCATE: Result = PromoteIntRes_TRUNCATE(N); break; + case ISD::SIGN_EXTEND: + case ISD::ZERO_EXTEND: + case ISD::ANY_EXTEND: Result = PromoteIntRes_INT_EXTEND(N); break; + case ISD::FP_ROUND: Result = PromoteIntRes_FP_ROUND(N); break; + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: Result = PromoteIntRes_FP_TO_XINT(N); break; + case ISD::SETCC: Result = PromoteIntRes_SETCC(N); break; + case ISD::LOAD: Result = PromoteIntRes_LOAD(cast(N)); break; + case ISD::BUILD_PAIR: Result = PromoteIntRes_BUILD_PAIR(N); break; + case ISD::BIT_CONVERT: Result = PromoteIntRes_BIT_CONVERT(N); break; + + case ISD::AND: + case ISD::OR: + case ISD::XOR: + case ISD::ADD: + case ISD::SUB: + case ISD::MUL: Result = PromoteIntRes_SimpleIntBinOp(N); break; + + case ISD::SDIV: + case ISD::SREM: Result = PromoteIntRes_SDIV(N); break; + + case ISD::UDIV: + case ISD::UREM: Result = PromoteIntRes_UDIV(N); break; + + case ISD::SHL: Result = PromoteIntRes_SHL(N); break; + case ISD::SRA: Result = PromoteIntRes_SRA(N); break; + case ISD::SRL: Result = PromoteIntRes_SRL(N); break; + + case ISD::SELECT: Result = PromoteIntRes_SELECT(N); break; + case ISD::SELECT_CC: Result = PromoteIntRes_SELECT_CC(N); break; + + case ISD::CTLZ: Result = PromoteIntRes_CTLZ(N); break; + case ISD::CTPOP: Result = PromoteIntRes_CTPOP(N); break; + case ISD::CTTZ: Result = PromoteIntRes_CTTZ(N); break; + + case ISD::EXTRACT_VECTOR_ELT: + Result = PromoteIntRes_EXTRACT_VECTOR_ELT(N); + break; + } + + // If Result is null, the sub-method took care of registering the result. + if (Result.Val) + SetPromotedInteger(SDOperand(N, ResNo), Result); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_UNDEF(SDNode *N) { + return DAG.getNode(ISD::UNDEF, TLI.getTypeToTransformTo(N->getValueType(0))); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_Constant(SDNode *N) { + MVT VT = N->getValueType(0); + // Zero extend things like i1, sign extend everything else. It shouldn't + // matter in theory which one we pick, but this tends to give better code? + unsigned Opc = VT.isByteSized() ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND; + SDOperand Result = DAG.getNode(Opc, TLI.getTypeToTransformTo(VT), + SDOperand(N, 0)); + assert(isa(Result) && "Didn't constant fold ext?"); + return Result; +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_TRUNCATE(SDNode *N) { + SDOperand Res; + + switch (getTypeAction(N->getOperand(0).getValueType())) { + default: assert(0 && "Unknown type action!"); + case Legal: + case ExpandInteger: + Res = N->getOperand(0); + break; + case PromoteInteger: + Res = GetPromotedInteger(N->getOperand(0)); + break; + } + + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + assert(Res.getValueType().getSizeInBits() >= NVT.getSizeInBits() && + "Truncation doesn't make sense!"); + if (Res.getValueType() == NVT) + return Res; + + // Truncate to NVT instead of VT + return DAG.getNode(ISD::TRUNCATE, NVT, Res); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_INT_EXTEND(SDNode *N) { + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + + if (getTypeAction(N->getOperand(0).getValueType()) == PromoteInteger) { + SDOperand Res = GetPromotedInteger(N->getOperand(0)); + assert(Res.getValueType().getSizeInBits() <= NVT.getSizeInBits() && + "Extension doesn't make sense!"); + + // If the result and operand types are the same after promotion, simplify + // to an in-register extension. + if (NVT == Res.getValueType()) { + // The high bits are not guaranteed to be anything. Insert an extend. + if (N->getOpcode() == ISD::SIGN_EXTEND) + return DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Res, + DAG.getValueType(N->getOperand(0).getValueType())); + if (N->getOpcode() == ISD::ZERO_EXTEND) + return DAG.getZeroExtendInReg(Res, N->getOperand(0).getValueType()); + assert(N->getOpcode() == ISD::ANY_EXTEND && "Unknown integer extension!"); + return Res; + } + } + + // Otherwise, just extend the original operand all the way to the larger type. + return DAG.getNode(N->getOpcode(), NVT, N->getOperand(0)); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_FP_ROUND(SDNode *N) { + // NOTE: Assumes input is legal. + if (N->getConstantOperandVal(1) == 0) + return DAG.getNode(ISD::FP_ROUND_INREG, N->getOperand(0).getValueType(), + N->getOperand(0), DAG.getValueType(N->getValueType(0))); + // If the precision discard isn't needed, just return the operand unrounded. + return N->getOperand(0); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_FP_TO_XINT(SDNode *N) { + unsigned NewOpc = N->getOpcode(); + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + + // If we're promoting a UINT to a larger size, check to see if the new node + // will be legal. If it isn't, check to see if FP_TO_SINT is legal, since + // we can use that instead. This allows us to generate better code for + // FP_TO_UINT for small destination sizes on targets where FP_TO_UINT is not + // legal, such as PowerPC. + if (N->getOpcode() == ISD::FP_TO_UINT) { + if (!TLI.isOperationLegal(ISD::FP_TO_UINT, NVT) && + (TLI.isOperationLegal(ISD::FP_TO_SINT, NVT) || + TLI.getOperationAction(ISD::FP_TO_SINT, NVT)==TargetLowering::Custom)) + NewOpc = ISD::FP_TO_SINT; + } + + return DAG.getNode(NewOpc, NVT, N->getOperand(0)); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_SETCC(SDNode *N) { + assert(isTypeLegal(TLI.getSetCCResultType(N->getOperand(0))) + && "SetCC type is not legal??"); + return DAG.getNode(ISD::SETCC, TLI.getSetCCResultType(N->getOperand(0)), + N->getOperand(0), N->getOperand(1), N->getOperand(2)); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_LOAD(LoadSDNode *N) { + // FIXME: Add support for indexed loads. + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + ISD::LoadExtType ExtType = + ISD::isNON_EXTLoad(N) ? ISD::EXTLOAD : N->getExtensionType(); + SDOperand Res = DAG.getExtLoad(ExtType, NVT, N->getChain(), N->getBasePtr(), + N->getSrcValue(), N->getSrcValueOffset(), + N->getMemoryVT(), N->isVolatile(), + N->getAlignment()); + + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDOperand(N, 1), Res.getValue(1)); + return Res; +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_BUILD_PAIR(SDNode *N) { + // The pair element type may be legal, or may not promote to the same type as + // the result, for example i14 = BUILD_PAIR (i7, i7). Handle all cases. + return DAG.getNode(ISD::ANY_EXTEND, + TLI.getTypeToTransformTo(N->getValueType(0)), + JoinIntegers(N->getOperand(0), N->getOperand(1))); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_BIT_CONVERT(SDNode *N) { + SDOperand InOp = N->getOperand(0); + MVT InVT = InOp.getValueType(); + MVT NInVT = TLI.getTypeToTransformTo(InVT); + MVT OutVT = TLI.getTypeToTransformTo(N->getValueType(0)); + + switch (getTypeAction(InVT)) { + default: + assert(false && "Unknown type action!"); + break; + case Legal: + break; + case PromoteInteger: + if (OutVT.getSizeInBits() == NInVT.getSizeInBits()) + // The input promotes to the same size. Convert the promoted value. + return DAG.getNode(ISD::BIT_CONVERT, OutVT, GetPromotedInteger(InOp)); + break; + case PromoteFloat: + // Promote the integer operand by hand. + return DAG.getNode(ISD::ANY_EXTEND, OutVT, GetPromotedFloat(InOp)); + case ExpandInteger: + case ExpandFloat: + break; + case Scalarize: + // Convert the element to an integer and promote it by hand. + return DAG.getNode(ISD::ANY_EXTEND, OutVT, + BitConvertToInteger(GetScalarizedVector(InOp))); + case Split: + // For example, i32 = BIT_CONVERT v2i16 on alpha. Convert the split + // pieces of the input into integers and reassemble in the final type. + SDOperand Lo, Hi; + GetSplitVector(N->getOperand(0), Lo, Hi); + Lo = BitConvertToInteger(Lo); + Hi = BitConvertToInteger(Hi); + + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + InOp = DAG.getNode(ISD::ANY_EXTEND, + MVT::getIntegerVT(OutVT.getSizeInBits()), + JoinIntegers(Lo, Hi)); + return DAG.getNode(ISD::BIT_CONVERT, OutVT, InOp); + } + + // Otherwise, lower the bit-convert to a store/load from the stack, then + // promote the load. + SDOperand Op = CreateStackStoreLoad(InOp, N->getValueType(0)); + return PromoteIntRes_LOAD(cast(Op.Val)); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_SimpleIntBinOp(SDNode *N) { + // The input may have strange things in the top bits of the registers, but + // these operations don't care. They may have weird bits going out, but + // that too is okay if they are integer operations. + SDOperand LHS = GetPromotedInteger(N->getOperand(0)); + SDOperand RHS = GetPromotedInteger(N->getOperand(1)); + return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_SDIV(SDNode *N) { + // Sign extend the input. + SDOperand LHS = GetPromotedInteger(N->getOperand(0)); + SDOperand RHS = GetPromotedInteger(N->getOperand(1)); + MVT VT = N->getValueType(0); + LHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, LHS.getValueType(), LHS, + DAG.getValueType(VT)); + RHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, RHS.getValueType(), RHS, + DAG.getValueType(VT)); + + return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_UDIV(SDNode *N) { + // Zero extend the input. + SDOperand LHS = GetPromotedInteger(N->getOperand(0)); + SDOperand RHS = GetPromotedInteger(N->getOperand(1)); + MVT VT = N->getValueType(0); + LHS = DAG.getZeroExtendInReg(LHS, VT); + RHS = DAG.getZeroExtendInReg(RHS, VT); + + return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_SHL(SDNode *N) { + return DAG.getNode(ISD::SHL, TLI.getTypeToTransformTo(N->getValueType(0)), + GetPromotedInteger(N->getOperand(0)), N->getOperand(1)); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_SRA(SDNode *N) { + // The input value must be properly sign extended. + MVT VT = N->getValueType(0); + MVT NVT = TLI.getTypeToTransformTo(VT); + SDOperand Res = GetPromotedInteger(N->getOperand(0)); + Res = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Res, DAG.getValueType(VT)); + return DAG.getNode(ISD::SRA, NVT, Res, N->getOperand(1)); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_SRL(SDNode *N) { + // The input value must be properly zero extended. + MVT VT = N->getValueType(0); + MVT NVT = TLI.getTypeToTransformTo(VT); + SDOperand Res = ZExtPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::SRL, NVT, Res, N->getOperand(1)); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_SELECT(SDNode *N) { + SDOperand LHS = GetPromotedInteger(N->getOperand(1)); + SDOperand RHS = GetPromotedInteger(N->getOperand(2)); + return DAG.getNode(ISD::SELECT, LHS.getValueType(), N->getOperand(0),LHS,RHS); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_SELECT_CC(SDNode *N) { + SDOperand LHS = GetPromotedInteger(N->getOperand(2)); + SDOperand RHS = GetPromotedInteger(N->getOperand(3)); + return DAG.getNode(ISD::SELECT_CC, LHS.getValueType(), N->getOperand(0), + N->getOperand(1), LHS, RHS, N->getOperand(4)); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_CTLZ(SDNode *N) { + SDOperand Op = GetPromotedInteger(N->getOperand(0)); + MVT OVT = N->getValueType(0); + MVT NVT = Op.getValueType(); + // Zero extend to the promoted type and do the count there. + Op = DAG.getNode(ISD::CTLZ, NVT, DAG.getZeroExtendInReg(Op, OVT)); + // Subtract off the extra leading bits in the bigger type. + return DAG.getNode(ISD::SUB, NVT, Op, + DAG.getConstant(NVT.getSizeInBits() - + OVT.getSizeInBits(), NVT)); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_CTPOP(SDNode *N) { + SDOperand Op = GetPromotedInteger(N->getOperand(0)); + MVT OVT = N->getValueType(0); + MVT NVT = Op.getValueType(); + // Zero extend to the promoted type and do the count there. + return DAG.getNode(ISD::CTPOP, NVT, DAG.getZeroExtendInReg(Op, OVT)); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_CTTZ(SDNode *N) { + SDOperand Op = GetPromotedInteger(N->getOperand(0)); + MVT OVT = N->getValueType(0); + MVT NVT = Op.getValueType(); + // The count is the same in the promoted type except if the original + // value was zero. This can be handled by setting the bit just off + // the top of the original type. + Op = DAG.getNode(ISD::OR, NVT, Op, + // FIXME: Do this using an APINT constant. + DAG.getConstant(1UL << OVT.getSizeInBits(), NVT)); + return DAG.getNode(ISD::CTTZ, NVT, Op); +} + +SDOperand DAGTypeLegalizer::PromoteIntRes_EXTRACT_VECTOR_ELT(SDNode *N) { + MVT OldVT = N->getValueType(0); + SDOperand OldVec = N->getOperand(0); + unsigned OldElts = OldVec.getValueType().getVectorNumElements(); + + if (OldElts == 1) { + assert(!isTypeLegal(OldVec.getValueType()) && + "Legal one-element vector of a type needing promotion!"); + // It is tempting to follow GetScalarizedVector by a call to + // GetPromotedInteger, but this would be wrong because the + // scalarized value may not yet have been processed. + return DAG.getNode(ISD::ANY_EXTEND, TLI.getTypeToTransformTo(OldVT), + GetScalarizedVector(OldVec)); + } + + // Convert to a vector half as long with an element type of twice the width, + // for example <4 x i16> -> <2 x i32>. + assert(!(OldElts & 1) && "Odd length vectors not supported!"); + MVT NewVT = MVT::getIntegerVT(2 * OldVT.getSizeInBits()); + assert(OldVT.isSimple() && NewVT.isSimple()); + + SDOperand NewVec = DAG.getNode(ISD::BIT_CONVERT, + MVT::getVectorVT(NewVT, OldElts / 2), + OldVec); + + // Extract the element at OldIdx / 2 from the new vector. + SDOperand OldIdx = N->getOperand(1); + SDOperand NewIdx = DAG.getNode(ISD::SRL, OldIdx.getValueType(), OldIdx, + DAG.getConstant(1, TLI.getShiftAmountTy())); + SDOperand Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, NewIdx); + + // Select the appropriate half of the element: Lo if OldIdx was even, + // Hi if it was odd. + SDOperand Lo = Elt; + SDOperand Hi = DAG.getNode(ISD::SRL, NewVT, Elt, + DAG.getConstant(OldVT.getSizeInBits(), + TLI.getShiftAmountTy())); + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + SDOperand Odd = DAG.getNode(ISD::AND, OldIdx.getValueType(), OldIdx, + DAG.getConstant(1, TLI.getShiftAmountTy())); + return DAG.getNode(ISD::SELECT, NewVT, Odd, Hi, Lo); +} + +//===----------------------------------------------------------------------===// +// Integer Operand Promotion +//===----------------------------------------------------------------------===// + +/// PromoteIntegerOperand - This method is called when the specified operand of +/// the specified node is found to need promotion. At this point, all of the +/// result types of the node are known to be legal, but other operands of the +/// node may need promotion or expansion as well as the specified one. +bool DAGTypeLegalizer::PromoteIntegerOperand(SDNode *N, unsigned OpNo) { + DEBUG(cerr << "Promote integer operand: "; N->dump(&DAG); cerr << "\n"); + SDOperand Res; + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + cerr << "PromoteIntegerOperand Op #" << OpNo << ": "; + N->dump(&DAG); cerr << "\n"; +#endif + assert(0 && "Do not know how to promote this operator's operand!"); + abort(); + + case ISD::ANY_EXTEND: Res = PromoteIntOp_ANY_EXTEND(N); break; + case ISD::ZERO_EXTEND: Res = PromoteIntOp_ZERO_EXTEND(N); break; + case ISD::SIGN_EXTEND: Res = PromoteIntOp_SIGN_EXTEND(N); break; + case ISD::TRUNCATE: Res = PromoteIntOp_TRUNCATE(N); break; + case ISD::FP_EXTEND: Res = PromoteIntOp_FP_EXTEND(N); break; + case ISD::FP_ROUND: Res = PromoteIntOp_FP_ROUND(N); break; + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: Res = PromoteIntOp_INT_TO_FP(N); break; + case ISD::BUILD_PAIR: Res = PromoteIntOp_BUILD_PAIR(N); break; + + case ISD::SELECT: Res = PromoteIntOp_SELECT(N, OpNo); break; + case ISD::BRCOND: Res = PromoteIntOp_BRCOND(N, OpNo); break; + case ISD::BR_CC: Res = PromoteIntOp_BR_CC(N, OpNo); break; + case ISD::SETCC: Res = PromoteIntOp_SETCC(N, OpNo); break; + + case ISD::STORE: Res = PromoteIntOp_STORE(cast(N), + OpNo); break; + + case ISD::BUILD_VECTOR: Res = PromoteIntOp_BUILD_VECTOR(N); break; + case ISD::INSERT_VECTOR_ELT: + Res = PromoteIntOp_INSERT_VECTOR_ELT(N, OpNo); + break; + + case ISD::MEMBARRIER: Res = PromoteIntOp_MEMBARRIER(N); break; + } + + // If the result is null, the sub-method took care of registering results etc. + if (!Res.Val) return false; + // If the result is N, the sub-method updated N in place. + if (Res.Val == N) { + // Mark N as new and remark N and its operands. This allows us to correctly + // revisit N if it needs another step of promotion and allows us to visit + // any new operands to N. + ReanalyzeNode(N); + return true; + } + + assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && + "Invalid operand expansion"); + + ReplaceValueWith(SDOperand(N, 0), Res); + return false; +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_ANY_EXTEND(SDNode *N) { + SDOperand Op = GetPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::ANY_EXTEND, N->getValueType(0), Op); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_ZERO_EXTEND(SDNode *N) { + SDOperand Op = GetPromotedInteger(N->getOperand(0)); + Op = DAG.getNode(ISD::ANY_EXTEND, N->getValueType(0), Op); + return DAG.getZeroExtendInReg(Op, N->getOperand(0).getValueType()); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_SIGN_EXTEND(SDNode *N) { + SDOperand Op = GetPromotedInteger(N->getOperand(0)); + Op = DAG.getNode(ISD::ANY_EXTEND, N->getValueType(0), Op); + return DAG.getNode(ISD::SIGN_EXTEND_INREG, Op.getValueType(), + Op, DAG.getValueType(N->getOperand(0).getValueType())); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_TRUNCATE(SDNode *N) { + SDOperand Op = GetPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::TRUNCATE, N->getValueType(0), Op); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_FP_EXTEND(SDNode *N) { + SDOperand Op = GetPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::FP_EXTEND, N->getValueType(0), Op); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_FP_ROUND(SDNode *N) { + SDOperand Op = GetPromotedInteger(N->getOperand(0)); + return DAG.getNode(ISD::FP_ROUND, N->getValueType(0), Op, + DAG.getIntPtrConstant(0)); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_INT_TO_FP(SDNode *N) { + SDOperand In = GetPromotedInteger(N->getOperand(0)); + MVT OpVT = N->getOperand(0).getValueType(); + if (N->getOpcode() == ISD::UINT_TO_FP) + In = DAG.getZeroExtendInReg(In, OpVT); + else + In = DAG.getNode(ISD::SIGN_EXTEND_INREG, In.getValueType(), + In, DAG.getValueType(OpVT)); + + return DAG.UpdateNodeOperands(SDOperand(N, 0), In); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_BUILD_PAIR(SDNode *N) { + // Since the result type is legal, the operands must promote to it. + MVT OVT = N->getOperand(0).getValueType(); + SDOperand Lo = GetPromotedInteger(N->getOperand(0)); + SDOperand Hi = GetPromotedInteger(N->getOperand(1)); + assert(Lo.getValueType() == N->getValueType(0) && "Operand over promoted?"); + + Lo = DAG.getZeroExtendInReg(Lo, OVT); + Hi = DAG.getNode(ISD::SHL, N->getValueType(0), Hi, + DAG.getConstant(OVT.getSizeInBits(), + TLI.getShiftAmountTy())); + return DAG.getNode(ISD::OR, N->getValueType(0), Lo, Hi); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_SELECT(SDNode *N, unsigned OpNo) { + assert(OpNo == 0 && "Only know how to promote condition"); + SDOperand Cond = GetPromotedInteger(N->getOperand(0)); // Promote condition. + + // The top bits of the promoted condition are not necessarily zero, ensure + // that the value is properly zero extended. + unsigned BitWidth = Cond.getValueSizeInBits(); + if (!DAG.MaskedValueIsZero(Cond, + APInt::getHighBitsSet(BitWidth, BitWidth-1))) + Cond = DAG.getZeroExtendInReg(Cond, MVT::i1); + + // The chain (Op#0) and basic block destination (Op#2) are always legal types. + return DAG.UpdateNodeOperands(SDOperand(N, 0), Cond, N->getOperand(1), + N->getOperand(2)); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_BRCOND(SDNode *N, unsigned OpNo) { + assert(OpNo == 1 && "only know how to promote condition"); + SDOperand Cond = GetPromotedInteger(N->getOperand(1)); // Promote condition. + + // The top bits of the promoted condition are not necessarily zero, ensure + // that the value is properly zero extended. + unsigned BitWidth = Cond.getValueSizeInBits(); + if (!DAG.MaskedValueIsZero(Cond, + APInt::getHighBitsSet(BitWidth, BitWidth-1))) + Cond = DAG.getZeroExtendInReg(Cond, MVT::i1); + + // The chain (Op#0) and basic block destination (Op#2) are always legal types. + return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), Cond, + N->getOperand(2)); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_BR_CC(SDNode *N, unsigned OpNo) { + assert(OpNo == 2 && "Don't know how to promote this operand"); + + SDOperand LHS = N->getOperand(2); + SDOperand RHS = N->getOperand(3); + PromoteSetCCOperands(LHS, RHS, cast(N->getOperand(1))->get()); + + // The chain (Op#0), CC (#1) and basic block destination (Op#4) are always + // legal types. + return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), + N->getOperand(1), LHS, RHS, N->getOperand(4)); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_SETCC(SDNode *N, unsigned OpNo) { + assert(OpNo == 0 && "Don't know how to promote this operand"); + + SDOperand LHS = N->getOperand(0); + SDOperand RHS = N->getOperand(1); + PromoteSetCCOperands(LHS, RHS, cast(N->getOperand(2))->get()); + + // The CC (#2) is always legal. + return DAG.UpdateNodeOperands(SDOperand(N, 0), LHS, RHS, N->getOperand(2)); +} + +/// PromoteSetCCOperands - Promote the operands of a comparison. This code is +/// shared among BR_CC, SELECT_CC, and SETCC handlers. +void DAGTypeLegalizer::PromoteSetCCOperands(SDOperand &NewLHS,SDOperand &NewRHS, + ISD::CondCode CCCode) { + MVT VT = NewLHS.getValueType(); + + // Get the promoted values. + NewLHS = GetPromotedInteger(NewLHS); + NewRHS = GetPromotedInteger(NewRHS); + + // If this is an FP compare, the operands have already been extended. + if (!NewLHS.getValueType().isInteger()) + return; + + // Otherwise, we have to insert explicit sign or zero extends. Note + // that we could insert sign extends for ALL conditions, but zero extend + // is cheaper on many machines (an AND instead of two shifts), so prefer + // it. + switch (CCCode) { + default: assert(0 && "Unknown integer comparison!"); + case ISD::SETEQ: + case ISD::SETNE: + case ISD::SETUGE: + case ISD::SETUGT: + case ISD::SETULE: + case ISD::SETULT: + // ALL of these operations will work if we either sign or zero extend + // the operands (including the unsigned comparisons!). Zero extend is + // usually a simpler/cheaper operation, so prefer it. + NewLHS = DAG.getZeroExtendInReg(NewLHS, VT); + NewRHS = DAG.getZeroExtendInReg(NewRHS, VT); + return; + case ISD::SETGE: + case ISD::SETGT: + case ISD::SETLT: + case ISD::SETLE: + NewLHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, NewLHS.getValueType(), NewLHS, + DAG.getValueType(VT)); + NewRHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, NewRHS.getValueType(), NewRHS, + DAG.getValueType(VT)); + return; + } +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_STORE(StoreSDNode *N, unsigned OpNo){ + // FIXME: Add support for indexed stores. + SDOperand Ch = N->getChain(), Ptr = N->getBasePtr(); + int SVOffset = N->getSrcValueOffset(); + unsigned Alignment = N->getAlignment(); + bool isVolatile = N->isVolatile(); + + SDOperand Val = GetPromotedInteger(N->getValue()); // Get promoted value. + + assert(!N->isTruncatingStore() && "Cannot promote this store operand!"); + + // Truncate the value and store the result. + return DAG.getTruncStore(Ch, Val, Ptr, N->getSrcValue(), + SVOffset, N->getMemoryVT(), + isVolatile, Alignment); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_BUILD_VECTOR(SDNode *N) { + // The vector type is legal but the element type is not. This implies + // that the vector is a power-of-two in length and that the element + // type does not have a strange size (eg: it is not i1). + MVT VecVT = N->getValueType(0); + unsigned NumElts = VecVT.getVectorNumElements(); + assert(!(NumElts & 1) && "Legal vector of one illegal element?"); + + // Build a vector of half the length out of elements of twice the bitwidth. + // For example <4 x i16> -> <2 x i32>. + MVT OldVT = N->getOperand(0).getValueType(); + MVT NewVT = MVT::getIntegerVT(2 * OldVT.getSizeInBits()); + assert(OldVT.isSimple() && NewVT.isSimple()); + + std::vector NewElts; + NewElts.reserve(NumElts/2); + + for (unsigned i = 0; i < NumElts; i += 2) { + // Combine two successive elements into one promoted element. + SDOperand Lo = N->getOperand(i); + SDOperand Hi = N->getOperand(i+1); + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + NewElts.push_back(JoinIntegers(Lo, Hi)); + } + + SDOperand NewVec = DAG.getNode(ISD::BUILD_VECTOR, + MVT::getVectorVT(NewVT, NewElts.size()), + &NewElts[0], NewElts.size()); + + // Convert the new vector to the old vector type. + return DAG.getNode(ISD::BIT_CONVERT, VecVT, NewVec); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_INSERT_VECTOR_ELT(SDNode *N, + unsigned OpNo) { + if (OpNo == 1) { + // Promote the inserted value. This is valid because the type does not + // have to match the vector element type. + + // Check that any extra bits introduced will be truncated away. + assert(N->getOperand(1).getValueType().getSizeInBits() >= + N->getValueType(0).getVectorElementType().getSizeInBits() && + "Type of inserted value narrower than vector element type!"); + return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), + GetPromotedInteger(N->getOperand(1)), + N->getOperand(2)); + } + + assert(OpNo == 2 && "Different operand and result vector types?"); + + // Promote the index. + SDOperand Idx = N->getOperand(2); + Idx = DAG.getZeroExtendInReg(GetPromotedInteger(Idx), Idx.getValueType()); + return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), + N->getOperand(1), Idx); +} + +SDOperand DAGTypeLegalizer::PromoteIntOp_MEMBARRIER(SDNode *N) { + SDOperand NewOps[6]; + NewOps[0] = N->getOperand(0); + for (unsigned i = 1; i < array_lengthof(NewOps); ++i) { + SDOperand Flag = GetPromotedInteger(N->getOperand(i)); + NewOps[i] = DAG.getZeroExtendInReg(Flag, MVT::i1); + } + return DAG.UpdateNodeOperands(SDOperand (N, 0), NewOps, + array_lengthof(NewOps)); +} + + +//===----------------------------------------------------------------------===// +// Integer Result Expansion +//===----------------------------------------------------------------------===// + +/// ExpandIntegerResult - This method is called when the specified result of the +/// specified node is found to need expansion. At this point, the node may also +/// have invalid operands or may have other results that need promotion, we just +/// know that (at least) one result needs expansion. +void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) { + DEBUG(cerr << "Expand integer result: "; N->dump(&DAG); cerr << "\n"); + SDOperand Lo, Hi; + Lo = Hi = SDOperand(); + + // See if the target wants to custom expand this node. + if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == + TargetLowering::Custom) { + // If the target wants to, allow it to lower this itself. + if (SDNode *P = TLI.ExpandOperationResult(N, DAG)) { + // Everything that once used N now uses P. We are guaranteed that the + // result value types of N and the result value types of P match. + ReplaceNodeWith(N, P); + return; + } + } + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + cerr << "ExpandIntegerResult #" << ResNo << ": "; + N->dump(&DAG); cerr << "\n"; +#endif + assert(0&&"Do not know how to expand the result of this operator!"); + abort(); + + case ISD::UNDEF: ExpandIntRes_UNDEF(N, Lo, Hi); break; + case ISD::Constant: ExpandIntRes_Constant(N, Lo, Hi); break; + case ISD::BUILD_PAIR: ExpandIntRes_BUILD_PAIR(N, Lo, Hi); break; + case ISD::MERGE_VALUES: ExpandIntRes_MERGE_VALUES(N, Lo, Hi); break; + case ISD::ANY_EXTEND: ExpandIntRes_ANY_EXTEND(N, Lo, Hi); break; + case ISD::ZERO_EXTEND: ExpandIntRes_ZERO_EXTEND(N, Lo, Hi); break; + case ISD::SIGN_EXTEND: ExpandIntRes_SIGN_EXTEND(N, Lo, Hi); break; + case ISD::AssertZext: ExpandIntRes_AssertZext(N, Lo, Hi); break; + case ISD::TRUNCATE: ExpandIntRes_TRUNCATE(N, Lo, Hi); break; + case ISD::BIT_CONVERT: ExpandIntRes_BIT_CONVERT(N, Lo, Hi); break; + case ISD::SIGN_EXTEND_INREG: ExpandIntRes_SIGN_EXTEND_INREG(N, Lo, Hi); break; + case ISD::FP_TO_SINT: ExpandIntRes_FP_TO_SINT(N, Lo, Hi); break; + case ISD::FP_TO_UINT: ExpandIntRes_FP_TO_UINT(N, Lo, Hi); break; + case ISD::LOAD: ExpandIntRes_LOAD(cast(N), Lo, Hi); break; + + case ISD::AND: + case ISD::OR: + case ISD::XOR: ExpandIntRes_Logical(N, Lo, Hi); break; + case ISD::BSWAP: ExpandIntRes_BSWAP(N, Lo, Hi); break; + case ISD::ADD: + case ISD::SUB: ExpandIntRes_ADDSUB(N, Lo, Hi); break; + case ISD::ADDC: + case ISD::SUBC: ExpandIntRes_ADDSUBC(N, Lo, Hi); break; + case ISD::ADDE: + case ISD::SUBE: ExpandIntRes_ADDSUBE(N, Lo, Hi); break; + case ISD::SELECT: ExpandIntRes_SELECT(N, Lo, Hi); break; + case ISD::SELECT_CC: ExpandIntRes_SELECT_CC(N, Lo, Hi); break; + case ISD::MUL: ExpandIntRes_MUL(N, Lo, Hi); break; + case ISD::SDIV: ExpandIntRes_SDIV(N, Lo, Hi); break; + case ISD::SREM: ExpandIntRes_SREM(N, Lo, Hi); break; + case ISD::UDIV: ExpandIntRes_UDIV(N, Lo, Hi); break; + case ISD::UREM: ExpandIntRes_UREM(N, Lo, Hi); break; + case ISD::SHL: + case ISD::SRA: + case ISD::SRL: ExpandIntRes_Shift(N, Lo, Hi); break; + + case ISD::CTLZ: ExpandIntRes_CTLZ(N, Lo, Hi); break; + case ISD::CTPOP: ExpandIntRes_CTPOP(N, Lo, Hi); break; + case ISD::CTTZ: ExpandIntRes_CTTZ(N, Lo, Hi); break; + + case ISD::EXTRACT_VECTOR_ELT: + ExpandIntRes_EXTRACT_VECTOR_ELT(N, Lo, Hi); + break; + } + + // If Lo/Hi is null, the sub-method took care of registering results etc. + if (Lo.Val) + SetExpandedInteger(SDOperand(N, ResNo), Lo, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_UNDEF(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + Lo = Hi = DAG.getNode(ISD::UNDEF, NVT); +} + +void DAGTypeLegalizer::ExpandIntRes_Constant(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + unsigned NBitWidth = NVT.getSizeInBits(); + const APInt &Cst = cast(N)->getAPIntValue(); + Lo = DAG.getConstant(APInt(Cst).trunc(NBitWidth), NVT); + Hi = DAG.getConstant(Cst.lshr(NBitWidth).trunc(NBitWidth), NVT); +} + +void DAGTypeLegalizer::ExpandIntRes_BUILD_PAIR(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + // Return the operands. + Lo = N->getOperand(0); + Hi = N->getOperand(1); +} + +void DAGTypeLegalizer::ExpandIntRes_MERGE_VALUES(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + // A MERGE_VALUES node can produce any number of values. We know that the + // first illegal one needs to be expanded into Lo/Hi. + unsigned i; + + // The string of legal results gets turns into the input operands, which have + // the same type. + for (i = 0; isTypeLegal(N->getValueType(i)); ++i) + ReplaceValueWith(SDOperand(N, i), SDOperand(N->getOperand(i))); + + // The first illegal result must be the one that needs to be expanded. + GetExpandedInteger(N->getOperand(i), Lo, Hi); + + // Legalize the rest of the results into the input operands whether they are + // legal or not. + unsigned e = N->getNumValues(); + for (++i; i != e; ++i) + ReplaceValueWith(SDOperand(N, i), SDOperand(N->getOperand(i))); +} + +void DAGTypeLegalizer::ExpandIntRes_ANY_EXTEND(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + SDOperand Op = N->getOperand(0); + if (Op.getValueType().bitsLE(NVT)) { + // The low part is any extension of the input (which degenerates to a copy). + Lo = DAG.getNode(ISD::ANY_EXTEND, NVT, Op); + Hi = DAG.getNode(ISD::UNDEF, NVT); // The high part is undefined. + } else { + // For example, extension of an i48 to an i64. The operand type necessarily + // promotes to the result type, so will end up being expanded too. + assert(getTypeAction(Op.getValueType()) == PromoteInteger && + "Only know how to promote this result!"); + SDOperand Res = GetPromotedInteger(Op); + assert(Res.getValueType() == N->getValueType(0) && + "Operand over promoted?"); + // Split the promoted operand. This will simplify when it is expanded. + SplitInteger(Res, Lo, Hi); + } +} + +void DAGTypeLegalizer::ExpandIntRes_ZERO_EXTEND(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + SDOperand Op = N->getOperand(0); + if (Op.getValueType().bitsLE(NVT)) { + // The low part is zero extension of the input (which degenerates to a copy). + Lo = DAG.getNode(ISD::ZERO_EXTEND, NVT, N->getOperand(0)); + Hi = DAG.getConstant(0, NVT); // The high part is just a zero. + } else { + // For example, extension of an i48 to an i64. The operand type necessarily + // promotes to the result type, so will end up being expanded too. + assert(getTypeAction(Op.getValueType()) == PromoteInteger && + "Only know how to promote this result!"); + SDOperand Res = GetPromotedInteger(Op); + assert(Res.getValueType() == N->getValueType(0) && + "Operand over promoted?"); + // Split the promoted operand. This will simplify when it is expanded. + SplitInteger(Res, Lo, Hi); + unsigned ExcessBits = + Op.getValueType().getSizeInBits() - NVT.getSizeInBits(); + Hi = DAG.getZeroExtendInReg(Hi, MVT::getIntegerVT(ExcessBits)); + } +} + +void DAGTypeLegalizer::ExpandIntRes_SIGN_EXTEND(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + SDOperand Op = N->getOperand(0); + if (Op.getValueType().bitsLE(NVT)) { + // The low part is sign extension of the input (which degenerates to a copy). + Lo = DAG.getNode(ISD::SIGN_EXTEND, NVT, N->getOperand(0)); + // The high part is obtained by SRA'ing all but one of the bits of low part. + unsigned LoSize = NVT.getSizeInBits(); + Hi = DAG.getNode(ISD::SRA, NVT, Lo, + DAG.getConstant(LoSize-1, TLI.getShiftAmountTy())); + } else { + // For example, extension of an i48 to an i64. The operand type necessarily + // promotes to the result type, so will end up being expanded too. + assert(getTypeAction(Op.getValueType()) == PromoteInteger && + "Only know how to promote this result!"); + SDOperand Res = GetPromotedInteger(Op); + assert(Res.getValueType() == N->getValueType(0) && + "Operand over promoted?"); + // Split the promoted operand. This will simplify when it is expanded. + SplitInteger(Res, Lo, Hi); + unsigned ExcessBits = + Op.getValueType().getSizeInBits() - NVT.getSizeInBits(); + Hi = DAG.getNode(ISD::SIGN_EXTEND_INREG, Hi.getValueType(), Hi, + DAG.getValueType(MVT::getIntegerVT(ExcessBits))); + } +} + +void DAGTypeLegalizer::ExpandIntRes_AssertZext(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + GetExpandedInteger(N->getOperand(0), Lo, Hi); + MVT NVT = Lo.getValueType(); + MVT EVT = cast(N->getOperand(1))->getVT(); + unsigned NVTBits = NVT.getSizeInBits(); + unsigned EVTBits = EVT.getSizeInBits(); + + if (NVTBits < EVTBits) { + Hi = DAG.getNode(ISD::AssertZext, NVT, Hi, + DAG.getValueType(MVT::getIntegerVT(EVTBits - NVTBits))); + } else { + Lo = DAG.getNode(ISD::AssertZext, NVT, Lo, DAG.getValueType(EVT)); + // The high part must be zero, make it explicit. + Hi = DAG.getConstant(0, NVT); + } +} + +void DAGTypeLegalizer::ExpandIntRes_TRUNCATE(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + Lo = DAG.getNode(ISD::TRUNCATE, NVT, N->getOperand(0)); + Hi = DAG.getNode(ISD::SRL, N->getOperand(0).getValueType(), N->getOperand(0), + DAG.getConstant(NVT.getSizeInBits(), + TLI.getShiftAmountTy())); + Hi = DAG.getNode(ISD::TRUNCATE, NVT, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_BIT_CONVERT(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + SDOperand InOp = N->getOperand(0); + MVT InVT = InOp.getValueType(); + + // Handle some special cases efficiently. + switch (getTypeAction(InVT)) { + default: + assert(false && "Unknown type action!"); + case Legal: + case PromoteInteger: + break; + case PromoteFloat: + // Convert the integer operand instead. + SplitInteger(GetPromotedFloat(InOp), Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); + return; + case ExpandInteger: + // Convert the expanded pieces of the input. + GetExpandedInteger(InOp, Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); + return; + case ExpandFloat: + // Convert the expanded pieces of the input. + GetExpandedFloat(InOp, Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); + return; + case Split: + // Convert the split parts of the input if it was split in two. + GetSplitVector(InOp, Lo, Hi); + if (Lo.getValueType() == Hi.getValueType()) { + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); + return; + } + break; + case Scalarize: + // Convert the element instead. + SplitInteger(BitConvertToInteger(GetScalarizedVector(InOp)), Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); + return; + } + + // Lower the bit-convert to a store/load from the stack, then expand the load. + SDOperand Op = CreateStackStoreLoad(InOp, N->getValueType(0)); + ExpandIntRes_LOAD(cast(Op.Val), Lo, Hi); +} + +void DAGTypeLegalizer:: +ExpandIntRes_SIGN_EXTEND_INREG(SDNode *N, SDOperand &Lo, SDOperand &Hi) { + GetExpandedInteger(N->getOperand(0), Lo, Hi); + MVT EVT = cast(N->getOperand(1))->getVT(); + + if (EVT.bitsLE(Lo.getValueType())) { + // sext_inreg the low part if needed. + Lo = DAG.getNode(ISD::SIGN_EXTEND_INREG, Lo.getValueType(), Lo, + N->getOperand(1)); + + // The high part gets the sign extension from the lo-part. This handles + // things like sextinreg V:i64 from i8. + Hi = DAG.getNode(ISD::SRA, Hi.getValueType(), Lo, + DAG.getConstant(Hi.getValueType().getSizeInBits()-1, + TLI.getShiftAmountTy())); + } else { + // For example, extension of an i48 to an i64. Leave the low part alone, + // sext_inreg the high part. + unsigned ExcessBits = + EVT.getSizeInBits() - Lo.getValueType().getSizeInBits(); + Hi = DAG.getNode(ISD::SIGN_EXTEND_INREG, Hi.getValueType(), Hi, + DAG.getValueType(MVT::getIntegerVT(ExcessBits))); + } +} + +void DAGTypeLegalizer::ExpandIntRes_FP_TO_SINT(SDNode *N, SDOperand &Lo, + SDOperand &Hi) { + MVT VT = N->getValueType(0); + SDOperand Op = N->getOperand(0); + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + if (VT == MVT::i64) { + if (Op.getValueType() == MVT::f32) + LC = RTLIB::FPTOSINT_F32_I64; + else if (Op.getValueType() == MVT::f64) + LC = RTLIB::FPTOSINT_F64_I64; + else if (Op.getValueType() == MVT::f80) + LC = RTLIB::FPTOSINT_F80_I64; + else if (Op.getValueType() == MVT::ppcf128) + LC = RTLIB::FPTOSINT_PPCF128_I64; + } else if (VT == MVT::i128) { + if (Op.getValueType() == MVT::f32) + LC = RTLIB::FPTOSINT_F32_I128; + else if (Op.getValueType() == MVT::f64) + LC = RTLIB::FPTOSINT_F64_I128; + else if (Op.getValueType() == MVT::f80) + LC = RTLIB::FPTOSINT_F80_I128; + else if (Op.getValueType() == MVT::ppcf128) + LC = RTLIB::FPTOSINT_PPCF128_I128; + } else { + assert(0 && "Unexpected fp-to-sint conversion!"); + } + SplitInteger(MakeLibCall(LC, VT, &Op, 1, true/*sign irrelevant*/), Lo, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_FP_TO_UINT(SDNode *N, SDOperand &Lo, + SDOperand &Hi) { + MVT VT = N->getValueType(0); + SDOperand Op = N->getOperand(0); + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + if (VT == MVT::i64) { + if (Op.getValueType() == MVT::f32) + LC = RTLIB::FPTOUINT_F32_I64; + else if (Op.getValueType() == MVT::f64) + LC = RTLIB::FPTOUINT_F64_I64; + else if (Op.getValueType() == MVT::f80) + LC = RTLIB::FPTOUINT_F80_I64; + else if (Op.getValueType() == MVT::ppcf128) + LC = RTLIB::FPTOUINT_PPCF128_I64; + } else if (VT == MVT::i128) { + if (Op.getValueType() == MVT::f32) + LC = RTLIB::FPTOUINT_F32_I128; + else if (Op.getValueType() == MVT::f64) + LC = RTLIB::FPTOUINT_F64_I128; + else if (Op.getValueType() == MVT::f80) + LC = RTLIB::FPTOUINT_F80_I128; + else if (Op.getValueType() == MVT::ppcf128) + LC = RTLIB::FPTOUINT_PPCF128_I128; + } else { + assert(0 && "Unexpected fp-to-uint conversion!"); + } + SplitInteger(MakeLibCall(LC, VT, &Op, 1, false/*sign irrelevant*/), Lo, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_LOAD(LoadSDNode *N, + SDOperand &Lo, SDOperand &Hi) { + // FIXME: Add support for indexed loads. + MVT VT = N->getValueType(0); + MVT NVT = TLI.getTypeToTransformTo(VT); + SDOperand Ch = N->getChain(); // Legalize the chain. + SDOperand Ptr = N->getBasePtr(); // Legalize the pointer. + ISD::LoadExtType ExtType = N->getExtensionType(); + int SVOffset = N->getSrcValueOffset(); + unsigned Alignment = N->getAlignment(); + bool isVolatile = N->isVolatile(); + + assert(!(NVT.getSizeInBits() & 7) && "Expanded type not byte sized!"); + + if (ExtType == ISD::NON_EXTLOAD) { + Lo = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset, + isVolatile, Alignment); + // Increment the pointer to the other half. + unsigned IncrementSize = NVT.getSizeInBits()/8; + Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + Hi = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset+IncrementSize, + isVolatile, MinAlign(Alignment, IncrementSize)); + + // Build a factor node to remember that this load is independent of the + // other one. + Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1), + Hi.getValue(1)); + + // Handle endianness of the load. + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + } else if (N->getMemoryVT().bitsLE(NVT)) { + MVT EVT = N->getMemoryVT(); + + Lo = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(), SVOffset, EVT, + isVolatile, Alignment); + + // Remember the chain. + Ch = Lo.getValue(1); + + if (ExtType == ISD::SEXTLOAD) { + // The high part is obtained by SRA'ing all but one of the bits of the + // lo part. + unsigned LoSize = Lo.getValueType().getSizeInBits(); + Hi = DAG.getNode(ISD::SRA, NVT, Lo, + DAG.getConstant(LoSize-1, TLI.getShiftAmountTy())); + } else if (ExtType == ISD::ZEXTLOAD) { + // The high part is just a zero. + Hi = DAG.getConstant(0, NVT); + } else { + assert(ExtType == ISD::EXTLOAD && "Unknown extload!"); + // The high part is undefined. + Hi = DAG.getNode(ISD::UNDEF, NVT); + } + } else if (TLI.isLittleEndian()) { + // Little-endian - low bits are at low addresses. + Lo = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset, + isVolatile, Alignment); + + unsigned ExcessBits = + N->getMemoryVT().getSizeInBits() - NVT.getSizeInBits(); + MVT NEVT = MVT::getIntegerVT(ExcessBits); + + // Increment the pointer to the other half. + unsigned IncrementSize = NVT.getSizeInBits()/8; + Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + Hi = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(), + SVOffset+IncrementSize, NEVT, + isVolatile, MinAlign(Alignment, IncrementSize)); + + // Build a factor node to remember that this load is independent of the + // other one. + Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1), + Hi.getValue(1)); + } else { + // Big-endian - high bits are at low addresses. Favor aligned loads at + // the cost of some bit-fiddling. + MVT EVT = N->getMemoryVT(); + unsigned EBytes = EVT.getStoreSizeInBits()/8; + unsigned IncrementSize = NVT.getSizeInBits()/8; + unsigned ExcessBits = (EBytes - IncrementSize)*8; + + // Load both the high bits and maybe some of the low bits. + Hi = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(), SVOffset, + MVT::getIntegerVT(EVT.getSizeInBits() - ExcessBits), + isVolatile, Alignment); + + // Increment the pointer to the other half. + Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + // Load the rest of the low bits. + Lo = DAG.getExtLoad(ISD::ZEXTLOAD, NVT, Ch, Ptr, N->getSrcValue(), + SVOffset+IncrementSize, + MVT::getIntegerVT(ExcessBits), + isVolatile, MinAlign(Alignment, IncrementSize)); + + // Build a factor node to remember that this load is independent of the + // other one. + Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1), + Hi.getValue(1)); + + if (ExcessBits < NVT.getSizeInBits()) { + // Transfer low bits from the bottom of Hi to the top of Lo. + Lo = DAG.getNode(ISD::OR, NVT, Lo, + DAG.getNode(ISD::SHL, NVT, Hi, + DAG.getConstant(ExcessBits, + TLI.getShiftAmountTy()))); + // Move high bits to the right position in Hi. + Hi = DAG.getNode(ExtType == ISD::SEXTLOAD ? ISD::SRA : ISD::SRL, NVT, Hi, + DAG.getConstant(NVT.getSizeInBits() - ExcessBits, + TLI.getShiftAmountTy())); + } + } + + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDOperand(N, 1), Ch); +} + +void DAGTypeLegalizer::ExpandIntRes_Logical(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + SDOperand LL, LH, RL, RH; + GetExpandedInteger(N->getOperand(0), LL, LH); + GetExpandedInteger(N->getOperand(1), RL, RH); + Lo = DAG.getNode(N->getOpcode(), LL.getValueType(), LL, RL); + Hi = DAG.getNode(N->getOpcode(), LL.getValueType(), LH, RH); +} + +void DAGTypeLegalizer::ExpandIntRes_BSWAP(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + GetExpandedInteger(N->getOperand(0), Hi, Lo); // Note swapped operands. + Lo = DAG.getNode(ISD::BSWAP, Lo.getValueType(), Lo); + Hi = DAG.getNode(ISD::BSWAP, Hi.getValueType(), Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_SELECT(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + SDOperand LL, LH, RL, RH; + GetExpandedInteger(N->getOperand(1), LL, LH); + GetExpandedInteger(N->getOperand(2), RL, RH); + Lo = DAG.getNode(ISD::SELECT, LL.getValueType(), N->getOperand(0), LL, RL); + Hi = DAG.getNode(ISD::SELECT, LL.getValueType(), N->getOperand(0), LH, RH); +} + +void DAGTypeLegalizer::ExpandIntRes_SELECT_CC(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + SDOperand LL, LH, RL, RH; + GetExpandedInteger(N->getOperand(2), LL, LH); + GetExpandedInteger(N->getOperand(3), RL, RH); + Lo = DAG.getNode(ISD::SELECT_CC, LL.getValueType(), N->getOperand(0), + N->getOperand(1), LL, RL, N->getOperand(4)); + Hi = DAG.getNode(ISD::SELECT_CC, LL.getValueType(), N->getOperand(0), + N->getOperand(1), LH, RH, N->getOperand(4)); +} + +void DAGTypeLegalizer::ExpandIntRes_ADDSUB(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + // Expand the subcomponents. + SDOperand LHSL, LHSH, RHSL, RHSH; + GetExpandedInteger(N->getOperand(0), LHSL, LHSH); + GetExpandedInteger(N->getOperand(1), RHSL, RHSH); + SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag); + SDOperand LoOps[2] = { LHSL, RHSL }; + SDOperand HiOps[3] = { LHSH, RHSH }; + + if (N->getOpcode() == ISD::ADD) { + Lo = DAG.getNode(ISD::ADDC, VTList, LoOps, 2); + HiOps[2] = Lo.getValue(1); + Hi = DAG.getNode(ISD::ADDE, VTList, HiOps, 3); + } else { + Lo = DAG.getNode(ISD::SUBC, VTList, LoOps, 2); + HiOps[2] = Lo.getValue(1); + Hi = DAG.getNode(ISD::SUBE, VTList, HiOps, 3); + } +} + +void DAGTypeLegalizer::ExpandIntRes_ADDSUBC(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + // Expand the subcomponents. + SDOperand LHSL, LHSH, RHSL, RHSH; + GetExpandedInteger(N->getOperand(0), LHSL, LHSH); + GetExpandedInteger(N->getOperand(1), RHSL, RHSH); + SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag); + SDOperand LoOps[2] = { LHSL, RHSL }; + SDOperand HiOps[3] = { LHSH, RHSH }; + + if (N->getOpcode() == ISD::ADDC) { + Lo = DAG.getNode(ISD::ADDC, VTList, LoOps, 2); + HiOps[2] = Lo.getValue(1); + Hi = DAG.getNode(ISD::ADDE, VTList, HiOps, 3); + } else { + Lo = DAG.getNode(ISD::SUBC, VTList, LoOps, 2); + HiOps[2] = Lo.getValue(1); + Hi = DAG.getNode(ISD::SUBE, VTList, HiOps, 3); + } + + // Legalized the flag result - switch anything that used the old flag to + // use the new one. + ReplaceValueWith(SDOperand(N, 1), Hi.getValue(1)); +} + +void DAGTypeLegalizer::ExpandIntRes_ADDSUBE(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + // Expand the subcomponents. + SDOperand LHSL, LHSH, RHSL, RHSH; + GetExpandedInteger(N->getOperand(0), LHSL, LHSH); + GetExpandedInteger(N->getOperand(1), RHSL, RHSH); + SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag); + SDOperand LoOps[3] = { LHSL, RHSL, N->getOperand(2) }; + SDOperand HiOps[3] = { LHSH, RHSH }; + + Lo = DAG.getNode(N->getOpcode(), VTList, LoOps, 3); + HiOps[2] = Lo.getValue(1); + Hi = DAG.getNode(N->getOpcode(), VTList, HiOps, 3); + + // Legalized the flag result - switch anything that used the old flag to + // use the new one. + ReplaceValueWith(SDOperand(N, 1), Hi.getValue(1)); +} + +void DAGTypeLegalizer::ExpandIntRes_MUL(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + MVT VT = N->getValueType(0); + MVT NVT = TLI.getTypeToTransformTo(VT); + + bool HasMULHS = TLI.isOperationLegal(ISD::MULHS, NVT); + bool HasMULHU = TLI.isOperationLegal(ISD::MULHU, NVT); + bool HasSMUL_LOHI = TLI.isOperationLegal(ISD::SMUL_LOHI, NVT); + bool HasUMUL_LOHI = TLI.isOperationLegal(ISD::UMUL_LOHI, NVT); + if (HasMULHU || HasMULHS || HasUMUL_LOHI || HasSMUL_LOHI) { + SDOperand LL, LH, RL, RH; + GetExpandedInteger(N->getOperand(0), LL, LH); + GetExpandedInteger(N->getOperand(1), RL, RH); + unsigned OuterBitSize = VT.getSizeInBits(); + unsigned BitSize = NVT.getSizeInBits(); + unsigned LHSSB = DAG.ComputeNumSignBits(N->getOperand(0)); + unsigned RHSSB = DAG.ComputeNumSignBits(N->getOperand(1)); + + if (DAG.MaskedValueIsZero(N->getOperand(0), + APInt::getHighBitsSet(OuterBitSize, LHSSB)) && + DAG.MaskedValueIsZero(N->getOperand(1), + APInt::getHighBitsSet(OuterBitSize, RHSSB))) { + // The inputs are both zero-extended. + if (HasUMUL_LOHI) { + // We can emit a umul_lohi. + Lo = DAG.getNode(ISD::UMUL_LOHI, DAG.getVTList(NVT, NVT), LL, RL); + Hi = SDOperand(Lo.Val, 1); + return; + } + if (HasMULHU) { + // We can emit a mulhu+mul. + Lo = DAG.getNode(ISD::MUL, NVT, LL, RL); + Hi = DAG.getNode(ISD::MULHU, NVT, LL, RL); + return; + } + } + if (LHSSB > BitSize && RHSSB > BitSize) { + // The input values are both sign-extended. + if (HasSMUL_LOHI) { + // We can emit a smul_lohi. + Lo = DAG.getNode(ISD::SMUL_LOHI, DAG.getVTList(NVT, NVT), LL, RL); + Hi = SDOperand(Lo.Val, 1); + return; + } + if (HasMULHS) { + // We can emit a mulhs+mul. + Lo = DAG.getNode(ISD::MUL, NVT, LL, RL); + Hi = DAG.getNode(ISD::MULHS, NVT, LL, RL); + return; + } + } + if (HasUMUL_LOHI) { + // Lo,Hi = umul LHS, RHS. + SDOperand UMulLOHI = DAG.getNode(ISD::UMUL_LOHI, + DAG.getVTList(NVT, NVT), LL, RL); + Lo = UMulLOHI; + Hi = UMulLOHI.getValue(1); + RH = DAG.getNode(ISD::MUL, NVT, LL, RH); + LH = DAG.getNode(ISD::MUL, NVT, LH, RL); + Hi = DAG.getNode(ISD::ADD, NVT, Hi, RH); + Hi = DAG.getNode(ISD::ADD, NVT, Hi, LH); + return; + } + } + + // If nothing else, we can make a libcall. + SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) }; + SplitInteger(MakeLibCall(RTLIB::MUL_I64, VT, Ops, 2, true/*sign irrelevant*/), + Lo, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_SDIV(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + assert(N->getValueType(0) == MVT::i64 && "Unsupported sdiv!"); + SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) }; + SplitInteger(MakeLibCall(RTLIB::SDIV_I64, N->getValueType(0), Ops, 2, true), + Lo, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_SREM(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + assert(N->getValueType(0) == MVT::i64 && "Unsupported srem!"); + SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) }; + SplitInteger(MakeLibCall(RTLIB::SREM_I64, N->getValueType(0), Ops, 2, true), + Lo, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_UDIV(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + assert(N->getValueType(0) == MVT::i64 && "Unsupported udiv!"); + SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) }; + SplitInteger(MakeLibCall(RTLIB::UDIV_I64, N->getValueType(0), Ops, 2, false), + Lo, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_UREM(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + assert(N->getValueType(0) == MVT::i64 && "Unsupported urem!"); + SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) }; + SplitInteger(MakeLibCall(RTLIB::UREM_I64, N->getValueType(0), Ops, 2, false), + Lo, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_Shift(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + MVT VT = N->getValueType(0); + + // If we can emit an efficient shift operation, do so now. Check to see if + // the RHS is a constant. + if (ConstantSDNode *CN = dyn_cast(N->getOperand(1))) + return ExpandShiftByConstant(N, CN->getValue(), Lo, Hi); + + // If we can determine that the high bit of the shift is zero or one, even if + // the low bits are variable, emit this shift in an optimized form. + if (ExpandShiftWithKnownAmountBit(N, Lo, Hi)) + return; + + // If this target supports shift_PARTS, use it. First, map to the _PARTS opc. + unsigned PartsOpc; + if (N->getOpcode() == ISD::SHL) { + PartsOpc = ISD::SHL_PARTS; + } else if (N->getOpcode() == ISD::SRL) { + PartsOpc = ISD::SRL_PARTS; + } else { + assert(N->getOpcode() == ISD::SRA && "Unknown shift!"); + PartsOpc = ISD::SRA_PARTS; + } + + // Next check to see if the target supports this SHL_PARTS operation or if it + // will custom expand it. + MVT NVT = TLI.getTypeToTransformTo(VT); + TargetLowering::LegalizeAction Action = TLI.getOperationAction(PartsOpc, NVT); + if ((Action == TargetLowering::Legal && TLI.isTypeLegal(NVT)) || + Action == TargetLowering::Custom) { + // Expand the subcomponents. + SDOperand LHSL, LHSH; + GetExpandedInteger(N->getOperand(0), LHSL, LHSH); + + SDOperand Ops[] = { LHSL, LHSH, N->getOperand(1) }; + MVT VT = LHSL.getValueType(); + Lo = DAG.getNode(PartsOpc, DAG.getNodeValueTypes(VT, VT), 2, Ops, 3); + Hi = Lo.getValue(1); + return; + } + + // Otherwise, emit a libcall. + assert(VT == MVT::i64 && "Unsupported shift!"); + + RTLIB::Libcall LC; + bool isSigned; + if (N->getOpcode() == ISD::SHL) { + LC = RTLIB::SHL_I64; + isSigned = false; /*sign irrelevant*/ + } else if (N->getOpcode() == ISD::SRL) { + LC = RTLIB::SRL_I64; + isSigned = false; + } else { + assert(N->getOpcode() == ISD::SRA && "Unknown shift!"); + LC = RTLIB::SRA_I64; + isSigned = true; + } + + SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) }; + SplitInteger(MakeLibCall(LC, VT, Ops, 2, isSigned), Lo, Hi); +} + +void DAGTypeLegalizer::ExpandIntRes_CTLZ(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + // ctlz (HiLo) -> Hi != 0 ? ctlz(Hi) : (ctlz(Lo)+32) + GetExpandedInteger(N->getOperand(0), Lo, Hi); + MVT NVT = Lo.getValueType(); + + SDOperand HiNotZero = DAG.getSetCC(TLI.getSetCCResultType(Hi), Hi, + DAG.getConstant(0, NVT), ISD::SETNE); + + SDOperand LoLZ = DAG.getNode(ISD::CTLZ, NVT, Lo); + SDOperand HiLZ = DAG.getNode(ISD::CTLZ, NVT, Hi); + + Lo = DAG.getNode(ISD::SELECT, NVT, HiNotZero, HiLZ, + DAG.getNode(ISD::ADD, NVT, LoLZ, + DAG.getConstant(NVT.getSizeInBits(), NVT))); + Hi = DAG.getConstant(0, NVT); +} + +void DAGTypeLegalizer::ExpandIntRes_CTPOP(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + // ctpop(HiLo) -> ctpop(Hi)+ctpop(Lo) + GetExpandedInteger(N->getOperand(0), Lo, Hi); + MVT NVT = Lo.getValueType(); + Lo = DAG.getNode(ISD::ADD, NVT, DAG.getNode(ISD::CTPOP, NVT, Lo), + DAG.getNode(ISD::CTPOP, NVT, Hi)); + Hi = DAG.getConstant(0, NVT); +} + +void DAGTypeLegalizer::ExpandIntRes_CTTZ(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + // cttz (HiLo) -> Lo != 0 ? cttz(Lo) : (cttz(Hi)+32) + GetExpandedInteger(N->getOperand(0), Lo, Hi); + MVT NVT = Lo.getValueType(); + + SDOperand LoNotZero = DAG.getSetCC(TLI.getSetCCResultType(Lo), Lo, + DAG.getConstant(0, NVT), ISD::SETNE); + + SDOperand LoLZ = DAG.getNode(ISD::CTTZ, NVT, Lo); + SDOperand HiLZ = DAG.getNode(ISD::CTTZ, NVT, Hi); + + Lo = DAG.getNode(ISD::SELECT, NVT, LoNotZero, LoLZ, + DAG.getNode(ISD::ADD, NVT, HiLZ, + DAG.getConstant(NVT.getSizeInBits(), NVT))); + Hi = DAG.getConstant(0, NVT); +} + +void DAGTypeLegalizer::ExpandIntRes_EXTRACT_VECTOR_ELT(SDNode *N, + SDOperand &Lo, + SDOperand &Hi) { + SDOperand OldVec = N->getOperand(0); + unsigned OldElts = OldVec.getValueType().getVectorNumElements(); + + // Convert to a vector of the expanded element type, for example + // <2 x i64> -> <4 x i32>. + MVT OldVT = N->getValueType(0); + MVT NewVT = TLI.getTypeToTransformTo(OldVT); + assert(OldVT.getSizeInBits() == 2 * NewVT.getSizeInBits() && + "Do not know how to handle this expansion!"); + + SDOperand NewVec = DAG.getNode(ISD::BIT_CONVERT, + MVT::getVectorVT(NewVT, 2*OldElts), + OldVec); + + // Extract the elements at 2 * Idx and 2 * Idx + 1 from the new vector. + SDOperand Idx = N->getOperand(1); + + // Make sure the type of Idx is big enough to hold the new values. + if (Idx.getValueType().bitsLT(TLI.getPointerTy())) + Idx = DAG.getNode(ISD::ZERO_EXTEND, TLI.getPointerTy(), Idx); + + Idx = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx, Idx); + Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, Idx); + + Idx = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx, + DAG.getConstant(1, Idx.getValueType())); + Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, Idx); + + if (TLI.isBigEndian()) + std::swap(Lo, Hi); +} + +/// ExpandShiftByConstant - N is a shift by a value that needs to be expanded, +/// and the shift amount is a constant 'Amt'. Expand the operation. +void DAGTypeLegalizer::ExpandShiftByConstant(SDNode *N, unsigned Amt, + SDOperand &Lo, SDOperand &Hi) { + // Expand the incoming operand to be shifted, so that we have its parts + SDOperand InL, InH; + GetExpandedInteger(N->getOperand(0), InL, InH); + + MVT NVT = InL.getValueType(); + unsigned VTBits = N->getValueType(0).getSizeInBits(); + unsigned NVTBits = NVT.getSizeInBits(); + MVT ShTy = N->getOperand(1).getValueType(); + + if (N->getOpcode() == ISD::SHL) { + if (Amt > VTBits) { + Lo = Hi = DAG.getConstant(0, NVT); + } else if (Amt > NVTBits) { + Lo = DAG.getConstant(0, NVT); + Hi = DAG.getNode(ISD::SHL, NVT, InL, DAG.getConstant(Amt-NVTBits,ShTy)); + } else if (Amt == NVTBits) { + Lo = DAG.getConstant(0, NVT); + Hi = InL; + } else { + Lo = DAG.getNode(ISD::SHL, NVT, InL, DAG.getConstant(Amt, ShTy)); + Hi = DAG.getNode(ISD::OR, NVT, + DAG.getNode(ISD::SHL, NVT, InH, + DAG.getConstant(Amt, ShTy)), + DAG.getNode(ISD::SRL, NVT, InL, + DAG.getConstant(NVTBits-Amt, ShTy))); + } + return; + } + + if (N->getOpcode() == ISD::SRL) { + if (Amt > VTBits) { + Lo = DAG.getConstant(0, NVT); + Hi = DAG.getConstant(0, NVT); + } else if (Amt > NVTBits) { + Lo = DAG.getNode(ISD::SRL, NVT, InH, DAG.getConstant(Amt-NVTBits,ShTy)); + Hi = DAG.getConstant(0, NVT); + } else if (Amt == NVTBits) { + Lo = InH; + Hi = DAG.getConstant(0, NVT); + } else { + Lo = DAG.getNode(ISD::OR, NVT, + DAG.getNode(ISD::SRL, NVT, InL, + DAG.getConstant(Amt, ShTy)), + DAG.getNode(ISD::SHL, NVT, InH, + DAG.getConstant(NVTBits-Amt, ShTy))); + Hi = DAG.getNode(ISD::SRL, NVT, InH, DAG.getConstant(Amt, ShTy)); + } + return; + } + + assert(N->getOpcode() == ISD::SRA && "Unknown shift!"); + if (Amt > VTBits) { + Hi = Lo = DAG.getNode(ISD::SRA, NVT, InH, + DAG.getConstant(NVTBits-1, ShTy)); + } else if (Amt > NVTBits) { + Lo = DAG.getNode(ISD::SRA, NVT, InH, + DAG.getConstant(Amt-NVTBits, ShTy)); + Hi = DAG.getNode(ISD::SRA, NVT, InH, + DAG.getConstant(NVTBits-1, ShTy)); + } else if (Amt == NVTBits) { + Lo = InH; + Hi = DAG.getNode(ISD::SRA, NVT, InH, + DAG.getConstant(NVTBits-1, ShTy)); + } else { + Lo = DAG.getNode(ISD::OR, NVT, + DAG.getNode(ISD::SRL, NVT, InL, + DAG.getConstant(Amt, ShTy)), + DAG.getNode(ISD::SHL, NVT, InH, + DAG.getConstant(NVTBits-Amt, ShTy))); + Hi = DAG.getNode(ISD::SRA, NVT, InH, DAG.getConstant(Amt, ShTy)); + } +} + +/// ExpandShiftWithKnownAmountBit - Try to determine whether we can simplify +/// this shift based on knowledge of the high bit of the shift amount. If we +/// can tell this, we know that it is >= 32 or < 32, without knowing the actual +/// shift amount. +bool DAGTypeLegalizer:: +ExpandShiftWithKnownAmountBit(SDNode *N, SDOperand &Lo, SDOperand &Hi) { + SDOperand Amt = N->getOperand(1); + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + MVT ShTy = Amt.getValueType(); + unsigned ShBits = ShTy.getSizeInBits(); + unsigned NVTBits = NVT.getSizeInBits(); + assert(isPowerOf2_32(NVTBits) && + "Expanded integer type size not a power of two!"); + + APInt HighBitMask = APInt::getHighBitsSet(ShBits, ShBits - Log2_32(NVTBits)); + APInt KnownZero, KnownOne; + DAG.ComputeMaskedBits(N->getOperand(1), HighBitMask, KnownZero, KnownOne); + + // If we don't know anything about the high bits, exit. + if (((KnownZero|KnownOne) & HighBitMask) == 0) + return false; + + // Get the incoming operand to be shifted. + SDOperand InL, InH; + GetExpandedInteger(N->getOperand(0), InL, InH); + + // If we know that any of the high bits of the shift amount are one, then we + // can do this as a couple of simple shifts. + if (KnownOne.intersects(HighBitMask)) { + // Mask out the high bit, which we know is set. + Amt = DAG.getNode(ISD::AND, ShTy, Amt, + DAG.getConstant(~HighBitMask, ShTy)); + + switch (N->getOpcode()) { + default: assert(0 && "Unknown shift"); + case ISD::SHL: + Lo = DAG.getConstant(0, NVT); // Low part is zero. + Hi = DAG.getNode(ISD::SHL, NVT, InL, Amt); // High part from Lo part. + return true; + case ISD::SRL: + Hi = DAG.getConstant(0, NVT); // Hi part is zero. + Lo = DAG.getNode(ISD::SRL, NVT, InH, Amt); // Lo part from Hi part. + return true; + case ISD::SRA: + Hi = DAG.getNode(ISD::SRA, NVT, InH, // Sign extend high part. + DAG.getConstant(NVTBits-1, ShTy)); + Lo = DAG.getNode(ISD::SRA, NVT, InH, Amt); // Lo part from Hi part. + return true; + } + } + + // If we know that all of the high bits of the shift amount are zero, then we + // can do this as a couple of simple shifts. + if ((KnownZero & HighBitMask) == HighBitMask) { + // Compute 32-amt. + SDOperand Amt2 = DAG.getNode(ISD::SUB, ShTy, + DAG.getConstant(NVTBits, ShTy), + Amt); + unsigned Op1, Op2; + switch (N->getOpcode()) { + default: assert(0 && "Unknown shift"); + case ISD::SHL: Op1 = ISD::SHL; Op2 = ISD::SRL; break; + case ISD::SRL: + case ISD::SRA: Op1 = ISD::SRL; Op2 = ISD::SHL; break; + } + + Lo = DAG.getNode(N->getOpcode(), NVT, InL, Amt); + Hi = DAG.getNode(ISD::OR, NVT, + DAG.getNode(Op1, NVT, InH, Amt), + DAG.getNode(Op2, NVT, InL, Amt2)); + return true; + } + + return false; +} + + +//===----------------------------------------------------------------------===// +// Integer Operand Expansion +//===----------------------------------------------------------------------===// + +/// ExpandIntegerOperand - This method is called when the specified operand of +/// the specified node is found to need expansion. At this point, all of the +/// result types of the node are known to be legal, but other operands of the +/// node may need promotion or expansion as well as the specified one. +bool DAGTypeLegalizer::ExpandIntegerOperand(SDNode *N, unsigned OpNo) { + DEBUG(cerr << "Expand integer operand: "; N->dump(&DAG); cerr << "\n"); + SDOperand Res(0, 0); + + if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType()) + == TargetLowering::Custom) + Res = TLI.LowerOperation(SDOperand(N, 0), DAG); + + if (Res.Val == 0) { + switch (N->getOpcode()) { + default: + #ifndef NDEBUG + cerr << "ExpandIntegerOperand Op #" << OpNo << ": "; + N->dump(&DAG); cerr << "\n"; + #endif + assert(0 && "Do not know how to expand this operator's operand!"); + abort(); + + case ISD::TRUNCATE: Res = ExpandIntOp_TRUNCATE(N); break; + case ISD::BIT_CONVERT: Res = ExpandIntOp_BIT_CONVERT(N); break; + + case ISD::SINT_TO_FP: + Res = ExpandIntOp_SINT_TO_FP(N->getOperand(0), N->getValueType(0)); + break; + case ISD::UINT_TO_FP: + Res = ExpandIntOp_UINT_TO_FP(N->getOperand(0), N->getValueType(0)); + break; + case ISD::EXTRACT_ELEMENT: Res = ExpandIntOp_EXTRACT_ELEMENT(N); break; + + case ISD::BR_CC: Res = ExpandIntOp_BR_CC(N); break; + case ISD::SETCC: Res = ExpandIntOp_SETCC(N); break; + + case ISD::STORE: + Res = ExpandIntOp_STORE(cast(N), OpNo); + break; + + case ISD::BUILD_VECTOR: Res = ExpandIntOp_BUILD_VECTOR(N); break; + } + } + + // If the result is null, the sub-method took care of registering results etc. + if (!Res.Val) return false; + // If the result is N, the sub-method updated N in place. Check to see if any + // operands are new, and if so, mark them. + if (Res.Val == N) { + // Mark N as new and remark N and its operands. This allows us to correctly + // revisit N if it needs another step of expansion and allows us to visit + // any new operands to N. + ReanalyzeNode(N); + return true; + } + + assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && + "Invalid operand expansion"); + + ReplaceValueWith(SDOperand(N, 0), Res); + return false; +} + +SDOperand DAGTypeLegalizer::ExpandIntOp_TRUNCATE(SDNode *N) { + SDOperand InL, InH; + GetExpandedInteger(N->getOperand(0), InL, InH); + // Just truncate the low part of the source. + return DAG.getNode(ISD::TRUNCATE, N->getValueType(0), InL); +} + +SDOperand DAGTypeLegalizer::ExpandIntOp_BIT_CONVERT(SDNode *N) { + if (N->getValueType(0).isVector()) { + // An illegal integer type is being converted to a legal vector type. + // Make a two element vector out of the expanded parts and convert that + // instead, but only if the new vector type is legal (otherwise there + // is no point, and it might create expansion loops). For example, on + // x86 this turns v1i64 = BIT_CONVERT i64 into v1i64 = BIT_CONVERT v2i32. + MVT OVT = N->getOperand(0).getValueType(); + MVT NVT = MVT::getVectorVT(TLI.getTypeToTransformTo(OVT), 2); + + if (isTypeLegal(NVT)) { + SDOperand Parts[2]; + GetExpandedInteger(N->getOperand(0), Parts[0], Parts[1]); + + if (TLI.isBigEndian()) + std::swap(Parts[0], Parts[1]); + + SDOperand Vec = DAG.getNode(ISD::BUILD_VECTOR, NVT, Parts, 2); + return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Vec); + } + } + + // Otherwise, store to a temporary and load out again as the new type. + return CreateStackStoreLoad(N->getOperand(0), N->getValueType(0)); +} + +SDOperand DAGTypeLegalizer::ExpandIntOp_SINT_TO_FP(SDOperand Source, + MVT DestTy) { + // We know the destination is legal, but that the input needs to be expanded. + MVT SourceVT = Source.getValueType(); + + // Check to see if the target has a custom way to lower this. If so, use it. + switch (TLI.getOperationAction(ISD::SINT_TO_FP, SourceVT)) { + default: assert(0 && "This action not implemented for this operation!"); + case TargetLowering::Legal: + case TargetLowering::Expand: + break; // This case is handled below. + case TargetLowering::Custom: + SDOperand NV = TLI.LowerOperation(DAG.getNode(ISD::SINT_TO_FP, DestTy, + Source), DAG); + if (NV.Val) return NV; + break; // The target lowered this. + } + + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + if (SourceVT == MVT::i64) { + if (DestTy == MVT::f32) + LC = RTLIB::SINTTOFP_I64_F32; + else { + assert(DestTy == MVT::f64 && "Unknown fp value type!"); + LC = RTLIB::SINTTOFP_I64_F64; + } + } else if (SourceVT == MVT::i128) { + if (DestTy == MVT::f32) + LC = RTLIB::SINTTOFP_I128_F32; + else if (DestTy == MVT::f64) + LC = RTLIB::SINTTOFP_I128_F64; + else if (DestTy == MVT::f80) + LC = RTLIB::SINTTOFP_I128_F80; + else { + assert(DestTy == MVT::ppcf128 && "Unknown fp value type!"); + LC = RTLIB::SINTTOFP_I128_PPCF128; + } + } else { + assert(0 && "Unknown int value type!"); + } + + assert(LC != RTLIB::UNKNOWN_LIBCALL && + "Don't know how to expand this SINT_TO_FP!"); + return MakeLibCall(LC, DestTy, &Source, 1, true); +} + +SDOperand DAGTypeLegalizer::ExpandIntOp_UINT_TO_FP(SDOperand Source, + MVT DestTy) { + // We know the destination is legal, but that the input needs to be expanded. + assert(getTypeAction(Source.getValueType()) == ExpandInteger && + "This is not an expansion!"); + + // If this is unsigned, and not supported, first perform the conversion to + // signed, then adjust the result if the sign bit is set. + SDOperand SignedConv = ExpandIntOp_SINT_TO_FP(Source, DestTy); + + // The 64-bit value loaded will be incorrectly if the 'sign bit' of the + // incoming integer is set. To handle this, we dynamically test to see if + // it is set, and, if so, add a fudge factor. + SDOperand Lo, Hi; + GetExpandedInteger(Source, Lo, Hi); + + SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultType(Hi), Hi, + DAG.getConstant(0, Hi.getValueType()), + ISD::SETLT); + SDOperand Zero = DAG.getIntPtrConstant(0), Four = DAG.getIntPtrConstant(4); + SDOperand CstOffset = DAG.getNode(ISD::SELECT, Zero.getValueType(), + SignSet, Four, Zero); + uint64_t FF = 0x5f800000ULL; + if (TLI.isLittleEndian()) FF <<= 32; + Constant *FudgeFactor = ConstantInt::get((Type*)Type::Int64Ty, FF); + + SDOperand CPIdx = DAG.getConstantPool(FudgeFactor, TLI.getPointerTy()); + CPIdx = DAG.getNode(ISD::ADD, TLI.getPointerTy(), CPIdx, CstOffset); + SDOperand FudgeInReg; + if (DestTy == MVT::f32) + FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx, NULL, 0); + else if (DestTy.bitsGT(MVT::f32)) + // FIXME: Avoid the extend by construction the right constantpool? + FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, DestTy, DAG.getEntryNode(), + CPIdx, NULL, 0, MVT::f32); + else + assert(0 && "Unexpected conversion"); + + return DAG.getNode(ISD::FADD, DestTy, SignedConv, FudgeInReg); +} + +SDOperand DAGTypeLegalizer::ExpandIntOp_EXTRACT_ELEMENT(SDNode *N) { + SDOperand Lo, Hi; + GetExpandedInteger(N->getOperand(0), Lo, Hi); + return cast(N->getOperand(1))->getValue() ? Hi : Lo; +} + +SDOperand DAGTypeLegalizer::ExpandIntOp_BR_CC(SDNode *N) { + SDOperand NewLHS = N->getOperand(2), NewRHS = N->getOperand(3); + ISD::CondCode CCCode = cast(N->getOperand(1))->get(); + ExpandSetCCOperands(NewLHS, NewRHS, CCCode); + + // If ExpandSetCCOperands returned a scalar, we need to compare the result + // against zero to select between true and false values. + if (NewRHS.Val == 0) { + NewRHS = DAG.getConstant(0, NewLHS.getValueType()); + CCCode = ISD::SETNE; + } + + // Update N to have the operands specified. + return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), + DAG.getCondCode(CCCode), NewLHS, NewRHS, + N->getOperand(4)); +} + +SDOperand DAGTypeLegalizer::ExpandIntOp_SETCC(SDNode *N) { + SDOperand NewLHS = N->getOperand(0), NewRHS = N->getOperand(1); + ISD::CondCode CCCode = cast(N->getOperand(2))->get(); + ExpandSetCCOperands(NewLHS, NewRHS, CCCode); + + // If ExpandSetCCOperands returned a scalar, use it. + if (NewRHS.Val == 0) return NewLHS; + + // Otherwise, update N to have the operands specified. + return DAG.UpdateNodeOperands(SDOperand(N, 0), NewLHS, NewRHS, + DAG.getCondCode(CCCode)); +} + +/// ExpandSetCCOperands - Expand the operands of a comparison. This code is +/// shared among BR_CC, SELECT_CC, and SETCC handlers. +void DAGTypeLegalizer::ExpandSetCCOperands(SDOperand &NewLHS, SDOperand &NewRHS, + ISD::CondCode &CCCode) { + SDOperand LHSLo, LHSHi, RHSLo, RHSHi; + GetExpandedInteger(NewLHS, LHSLo, LHSHi); + GetExpandedInteger(NewRHS, RHSLo, RHSHi); + + MVT VT = NewLHS.getValueType(); + if (VT == MVT::ppcf128) { + // FIXME: This generated code sucks. We want to generate + // FCMP crN, hi1, hi2 + // BNE crN, L: + // FCMP crN, lo1, lo2 + // The following can be improved, but not that much. + SDOperand Tmp1, Tmp2, Tmp3; + Tmp1 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, ISD::SETEQ); + Tmp2 = DAG.getSetCC(TLI.getSetCCResultType(LHSLo), LHSLo, RHSLo, CCCode); + Tmp3 = DAG.getNode(ISD::AND, Tmp1.getValueType(), Tmp1, Tmp2); + Tmp1 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, ISD::SETNE); + Tmp2 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, CCCode); + Tmp1 = DAG.getNode(ISD::AND, Tmp1.getValueType(), Tmp1, Tmp2); + NewLHS = DAG.getNode(ISD::OR, Tmp1.getValueType(), Tmp1, Tmp3); + NewRHS = SDOperand(); // LHS is the result, not a compare. + return; + } + + if (CCCode == ISD::SETEQ || CCCode == ISD::SETNE) { + if (RHSLo == RHSHi) + if (ConstantSDNode *RHSCST = dyn_cast(RHSLo)) + if (RHSCST->isAllOnesValue()) { + // Equality comparison to -1. + NewLHS = DAG.getNode(ISD::AND, LHSLo.getValueType(), LHSLo, LHSHi); + NewRHS = RHSLo; + return; + } + + NewLHS = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSLo, RHSLo); + NewRHS = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSHi, RHSHi); + NewLHS = DAG.getNode(ISD::OR, NewLHS.getValueType(), NewLHS, NewRHS); + NewRHS = DAG.getConstant(0, NewLHS.getValueType()); + return; + } + + // If this is a comparison of the sign bit, just look at the top part. + // X > -1, x < 0 + if (ConstantSDNode *CST = dyn_cast(NewRHS)) + if ((CCCode == ISD::SETLT && CST->isNullValue()) || // X < 0 + (CCCode == ISD::SETGT && CST->isAllOnesValue())) { // X > -1 + NewLHS = LHSHi; + NewRHS = RHSHi; + return; + } + + // FIXME: This generated code sucks. + ISD::CondCode LowCC; + switch (CCCode) { + default: assert(0 && "Unknown integer setcc!"); + case ISD::SETLT: + case ISD::SETULT: LowCC = ISD::SETULT; break; + case ISD::SETGT: + case ISD::SETUGT: LowCC = ISD::SETUGT; break; + case ISD::SETLE: + case ISD::SETULE: LowCC = ISD::SETULE; break; + case ISD::SETGE: + case ISD::SETUGE: LowCC = ISD::SETUGE; break; + } + + // Tmp1 = lo(op1) < lo(op2) // Always unsigned comparison + // Tmp2 = hi(op1) < hi(op2) // Signedness depends on operands + // dest = hi(op1) == hi(op2) ? Tmp1 : Tmp2; + + // NOTE: on targets without efficient SELECT of bools, we can always use + // this identity: (B1 ? B2 : B3) --> (B1 & B2)|(!B1&B3) + TargetLowering::DAGCombinerInfo DagCombineInfo(DAG, false, true, NULL); + SDOperand Tmp1, Tmp2; + Tmp1 = TLI.SimplifySetCC(TLI.getSetCCResultType(LHSLo), LHSLo, RHSLo, LowCC, + false, DagCombineInfo); + if (!Tmp1.Val) + Tmp1 = DAG.getSetCC(TLI.getSetCCResultType(LHSLo), LHSLo, RHSLo, LowCC); + Tmp2 = TLI.SimplifySetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, + CCCode, false, DagCombineInfo); + if (!Tmp2.Val) + Tmp2 = DAG.getNode(ISD::SETCC, TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, + DAG.getCondCode(CCCode)); + + ConstantSDNode *Tmp1C = dyn_cast(Tmp1.Val); + ConstantSDNode *Tmp2C = dyn_cast(Tmp2.Val); + if ((Tmp1C && Tmp1C->isNullValue()) || + (Tmp2C && Tmp2C->isNullValue() && + (CCCode == ISD::SETLE || CCCode == ISD::SETGE || + CCCode == ISD::SETUGE || CCCode == ISD::SETULE)) || + (Tmp2C && Tmp2C->getAPIntValue() == 1 && + (CCCode == ISD::SETLT || CCCode == ISD::SETGT || + CCCode == ISD::SETUGT || CCCode == ISD::SETULT))) { + // low part is known false, returns high part. + // For LE / GE, if high part is known false, ignore the low part. + // For LT / GT, if high part is known true, ignore the low part. + NewLHS = Tmp2; + NewRHS = SDOperand(); + return; + } + + NewLHS = TLI.SimplifySetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, + ISD::SETEQ, false, DagCombineInfo); + if (!NewLHS.Val) + NewLHS = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, + ISD::SETEQ); + NewLHS = DAG.getNode(ISD::SELECT, Tmp1.getValueType(), + NewLHS, Tmp1, Tmp2); + NewRHS = SDOperand(); +} + +SDOperand DAGTypeLegalizer::ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo) { + // FIXME: Add support for indexed stores. + assert(OpNo == 1 && "Can only expand the stored value so far"); + + MVT VT = N->getOperand(1).getValueType(); + MVT NVT = TLI.getTypeToTransformTo(VT); + SDOperand Ch = N->getChain(); + SDOperand Ptr = N->getBasePtr(); + int SVOffset = N->getSrcValueOffset(); + unsigned Alignment = N->getAlignment(); + bool isVolatile = N->isVolatile(); + SDOperand Lo, Hi; + + assert(!(NVT.getSizeInBits() & 7) && "Expanded type not byte sized!"); + + if (!N->isTruncatingStore()) { + unsigned IncrementSize = 0; + GetExpandedInteger(N->getValue(), Lo, Hi); + IncrementSize = Hi.getValueType().getSizeInBits()/8; + + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(), + SVOffset, isVolatile, Alignment); + + Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + assert(isTypeLegal(Ptr.getValueType()) && "Pointers must be legal!"); + Hi = DAG.getStore(Ch, Hi, Ptr, N->getSrcValue(), SVOffset+IncrementSize, + isVolatile, MinAlign(Alignment, IncrementSize)); + return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi); + } else if (N->getMemoryVT().bitsLE(NVT)) { + GetExpandedInteger(N->getValue(), Lo, Hi); + return DAG.getTruncStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset, + N->getMemoryVT(), isVolatile, Alignment); + } else if (TLI.isLittleEndian()) { + // Little-endian - low bits are at low addresses. + GetExpandedInteger(N->getValue(), Lo, Hi); + + Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset, + isVolatile, Alignment); + + unsigned ExcessBits = + N->getMemoryVT().getSizeInBits() - NVT.getSizeInBits(); + MVT NEVT = MVT::getIntegerVT(ExcessBits); + + // Increment the pointer to the other half. + unsigned IncrementSize = NVT.getSizeInBits()/8; + Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + Hi = DAG.getTruncStore(Ch, Hi, Ptr, N->getSrcValue(), + SVOffset+IncrementSize, NEVT, + isVolatile, MinAlign(Alignment, IncrementSize)); + return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi); + } else { + // Big-endian - high bits are at low addresses. Favor aligned stores at + // the cost of some bit-fiddling. + GetExpandedInteger(N->getValue(), Lo, Hi); + + MVT EVT = N->getMemoryVT(); + unsigned EBytes = EVT.getStoreSizeInBits()/8; + unsigned IncrementSize = NVT.getSizeInBits()/8; + unsigned ExcessBits = (EBytes - IncrementSize)*8; + MVT HiVT = MVT::getIntegerVT(EVT.getSizeInBits() - ExcessBits); + + if (ExcessBits < NVT.getSizeInBits()) { + // Transfer high bits from the top of Lo to the bottom of Hi. + Hi = DAG.getNode(ISD::SHL, NVT, Hi, + DAG.getConstant(NVT.getSizeInBits() - ExcessBits, + TLI.getShiftAmountTy())); + Hi = DAG.getNode(ISD::OR, NVT, Hi, + DAG.getNode(ISD::SRL, NVT, Lo, + DAG.getConstant(ExcessBits, + TLI.getShiftAmountTy()))); + } + + // Store both the high bits and maybe some of the low bits. + Hi = DAG.getTruncStore(Ch, Hi, Ptr, N->getSrcValue(), + SVOffset, HiVT, isVolatile, Alignment); + + // Increment the pointer to the other half. + Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + // Store the lowest ExcessBits bits in the second half. + Lo = DAG.getTruncStore(Ch, Lo, Ptr, N->getSrcValue(), + SVOffset+IncrementSize, + MVT::getIntegerVT(ExcessBits), + isVolatile, MinAlign(Alignment, IncrementSize)); + return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi); + } +} + +SDOperand DAGTypeLegalizer::ExpandIntOp_BUILD_VECTOR(SDNode *N) { + // The vector type is legal but the element type needs expansion. + MVT VecVT = N->getValueType(0); + unsigned NumElts = VecVT.getVectorNumElements(); + MVT OldVT = N->getOperand(0).getValueType(); + MVT NewVT = TLI.getTypeToTransformTo(OldVT); + + assert(OldVT.getSizeInBits() == 2 * NewVT.getSizeInBits() && + "Do not know how to expand this operand!"); + + // Build a vector of twice the length out of the expanded elements. + // For example <2 x i64> -> <4 x i32>. + std::vector NewElts; + NewElts.reserve(NumElts*2); + + for (unsigned i = 0; i < NumElts; ++i) { + SDOperand Lo, Hi; + GetExpandedInteger(N->getOperand(i), Lo, Hi); + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + NewElts.push_back(Lo); + NewElts.push_back(Hi); + } + + SDOperand NewVec = DAG.getNode(ISD::BUILD_VECTOR, + MVT::getVectorVT(NewVT, NewElts.size()), + &NewElts[0], NewElts.size()); + + // Convert the new vector to the old vector type. + return DAG.getNode(ISD::BIT_CONVERT, VecVT, NewVec); +} Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp?rev=52408&r1=52407&r2=52408&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp Tue Jun 17 09:27:01 2008 @@ -42,7 +42,7 @@ // The root of the dag may dangle to deleted nodes until the type legalizer is // done. Set it to null to avoid confusion. DAG.setRoot(SDOperand()); - + // Walk all nodes in the graph, assigning them a NodeID of 'ReadyToProcess' // (and remembering them) if they are leaves and assigning 'NewNode' if // non-leaves. @@ -55,14 +55,14 @@ I->setNodeId(NewNode); } } - + // Now that we have a set of nodes to process, handle them all. while (!Worklist.empty()) { SDNode *N = Worklist.back(); Worklist.pop_back(); assert(N->getNodeId() == ReadyToProcess && "Node should be ready if on worklist!"); - + // Scan the values produced by the node, checking to see if any result // types are illegal. unsigned i = 0; @@ -74,14 +74,17 @@ assert(false && "Unknown action!"); case Legal: break; - case Promote: - PromoteResult(N, i); + case PromoteInteger: + PromoteIntegerResult(N, i); goto NodeDone; - case Expand: - ExpandResult(N, i); + case ExpandInteger: + ExpandIntegerResult(N, i); goto NodeDone; - case FloatToInt: - FloatToIntResult(N, i); + case PromoteFloat: + PromoteFloatResult(N, i); + goto NodeDone; + case ExpandFloat: + ExpandFloatResult(N, i); goto NodeDone; case Scalarize: ScalarizeResult(N, i); @@ -104,14 +107,17 @@ assert(false && "Unknown action!"); case Legal: continue; - case Promote: - NeedsRevisit = PromoteOperand(N, i); + case PromoteInteger: + NeedsRevisit = PromoteIntegerOperand(N, i); + break; + case ExpandInteger: + NeedsRevisit = ExpandIntegerOperand(N, i); break; - case Expand: - NeedsRevisit = ExpandOperand(N, i); + case PromoteFloat: + NeedsRevisit = PromoteFloatOperand(N, i); break; - case FloatToInt: - NeedsRevisit = FloatToIntOperand(N, i); + case ExpandFloat: + NeedsRevisit = ExpandFloatOperand(N, i); break; case Scalarize: NeedsRevisit = ScalarizeOperand(N, i); @@ -126,7 +132,7 @@ // If the node needs revisiting, don't add all users to the worklist etc. if (NeedsRevisit) continue; - + if (i == NumOperands) DEBUG(cerr << "Legally typed node: "; N->dump(&DAG); cerr << "\n"); } @@ -135,37 +141,37 @@ // If we reach here, the node was processed, potentially creating new nodes. // Mark it as processed and add its users to the worklist as appropriate. N->setNodeId(Processed); - + for (SDNode::use_iterator UI = N->use_begin(), E = N->use_end(); UI != E; ++UI) { SDNode *User = UI->getUser(); int NodeID = User->getNodeId(); assert(NodeID != ReadyToProcess && NodeID != Processed && "Invalid node id for user of unprocessed node!"); - + // This node has two options: it can either be a new node or its Node ID // may be a count of the number of operands it has that are not ready. if (NodeID > 0) { User->setNodeId(NodeID-1); - + // If this was the last use it was waiting on, add it to the ready list. if (NodeID-1 == ReadyToProcess) Worklist.push_back(User); continue; } - + // Otherwise, this node is new: this is the first operand of it that // became ready. Its new NodeID is the number of operands it has minus 1 // (as this node is now processed). assert(NodeID == NewNode && "Unknown node ID!"); User->setNodeId(User->getNumOperands()-1); - + // If the node only has a single operand, it is now ready. if (User->getNumOperands() == 1) Worklist.push_back(User); } } - + // If the root changed (e.g. it was a dead load, update the root). DAG.setRoot(Dummy.getValue()); @@ -315,8 +321,8 @@ NodeUpdateListener NUL(*this); DAG.ReplaceAllUsesOfValueWith(From, To, &NUL); - // The old node may still be present in a map like ExpandedNodes or - // PromotedNodes. Inform maps about the replacement. + // The old node may still be present in a map like ExpandedIntegers or + // PromotedIntegers. Inform maps about the replacement. NoteReplacement(From, To); } @@ -336,8 +342,8 @@ NodeUpdateListener NUL(*this); DAG.ReplaceAllUsesWith(From, To, &NUL); - // The old node may still be present in a map like ExpandedNodes or - // PromotedNodes. Inform maps about the replacement. + // The old node may still be present in a map like ExpandedIntegers or + // PromotedIntegers. Inform maps about the replacement. for (unsigned i = 0, e = From->getNumValues(); i != e; ++i) { assert(From->getValueType(i) == To->getValueType(i) && "Node results don't match"); @@ -380,29 +386,38 @@ I->second = Replacement; } - for (DenseMap::iterator I = PromotedNodes.begin(), - E = PromotedNodes.end(); I != E; ++I) { + for (DenseMap::iterator I = PromotedIntegers.begin(), + E = PromotedIntegers.end(); I != E; ++I) { assert(I->first != N); if (I->second == N) I->second = Replacement; } - for (DenseMap::iterator I = FloatToIntedNodes.begin(), - E = FloatToIntedNodes.end(); I != E; ++I) { + for (DenseMap::iterator I = PromotedFloats.begin(), + E = PromotedFloats.end(); I != E; ++I) { assert(I->first != N); if (I->second == N) I->second = Replacement; } - for (DenseMap::iterator I = ScalarizedNodes.begin(), - E = ScalarizedNodes.end(); I != E; ++I) { + for (DenseMap::iterator I = ScalarizedVectors.begin(), + E = ScalarizedVectors.end(); I != E; ++I) { assert(I->first != N); if (I->second == N) I->second = Replacement; } for (DenseMap >::iterator - I = ExpandedNodes.begin(), E = ExpandedNodes.end(); I != E; ++I) { + I = ExpandedIntegers.begin(), E = ExpandedIntegers.end(); I != E; ++I){ + assert(I->first != N); + if (I->second.first == N) + I->second.first = Replacement; + if (I->second.second == N) + I->second.second = Replacement; + } + + for (DenseMap >::iterator + I = ExpandedFloats.begin(), E = ExpandedFloats.end(); I != E; ++I) { assert(I->first != N); if (I->second.first == N) I->second.first = Replacement; @@ -411,7 +426,7 @@ } for (DenseMap >::iterator - I = SplitNodes.begin(), E = SplitNodes.end(); I != E; ++I) { + I = SplitVectors.begin(), E = SplitVectors.end(); I != E; ++I) { assert(I->first != N); if (I->second.first == N) I->second.first = Replacement; @@ -422,36 +437,62 @@ } -void DAGTypeLegalizer::SetPromotedOp(SDOperand Op, SDOperand Result) { +void DAGTypeLegalizer::SetPromotedInteger(SDOperand Op, SDOperand Result) { ExpungeNode(Result); AnalyzeNewNode(Result.Val); - SDOperand &OpEntry = PromotedNodes[Op]; + SDOperand &OpEntry = PromotedIntegers[Op]; assert(OpEntry.Val == 0 && "Node is already promoted!"); OpEntry = Result; } -void DAGTypeLegalizer::SetIntegerOp(SDOperand Op, SDOperand Result) { +void DAGTypeLegalizer::SetPromotedFloat(SDOperand Op, SDOperand Result) { ExpungeNode(Result); AnalyzeNewNode(Result.Val); - SDOperand &OpEntry = FloatToIntedNodes[Op]; + SDOperand &OpEntry = PromotedFloats[Op]; assert(OpEntry.Val == 0 && "Node is already converted to integer!"); OpEntry = Result; } -void DAGTypeLegalizer::SetScalarizedOp(SDOperand Op, SDOperand Result) { +void DAGTypeLegalizer::SetScalarizedVector(SDOperand Op, SDOperand Result) { ExpungeNode(Result); AnalyzeNewNode(Result.Val); - SDOperand &OpEntry = ScalarizedNodes[Op]; + SDOperand &OpEntry = ScalarizedVectors[Op]; assert(OpEntry.Val == 0 && "Node is already scalarized!"); OpEntry = Result; } -void DAGTypeLegalizer::GetExpandedOp(SDOperand Op, SDOperand &Lo, - SDOperand &Hi) { - std::pair &Entry = ExpandedNodes[Op]; +void DAGTypeLegalizer::GetExpandedInteger(SDOperand Op, SDOperand &Lo, + SDOperand &Hi) { + std::pair &Entry = ExpandedIntegers[Op]; + RemapNode(Entry.first); + RemapNode(Entry.second); + assert(Entry.first.Val && "Operand isn't expanded"); + Lo = Entry.first; + Hi = Entry.second; +} + +void DAGTypeLegalizer::SetExpandedInteger(SDOperand Op, SDOperand Lo, + SDOperand Hi) { + ExpungeNode(Lo); + ExpungeNode(Hi); + + // Lo/Hi may have been newly allocated, if so, add nodeid's as relevant. + AnalyzeNewNode(Lo.Val); + AnalyzeNewNode(Hi.Val); + + // Remember that this is the result of the node. + std::pair &Entry = ExpandedIntegers[Op]; + assert(Entry.first.Val == 0 && "Node already expanded"); + Entry.first = Lo; + Entry.second = Hi; +} + +void DAGTypeLegalizer::GetExpandedFloat(SDOperand Op, SDOperand &Lo, + SDOperand &Hi) { + std::pair &Entry = ExpandedFloats[Op]; RemapNode(Entry.first); RemapNode(Entry.second); assert(Entry.first.Val && "Operand isn't expanded"); @@ -459,7 +500,8 @@ Hi = Entry.second; } -void DAGTypeLegalizer::SetExpandedOp(SDOperand Op, SDOperand Lo, SDOperand Hi) { +void DAGTypeLegalizer::SetExpandedFloat(SDOperand Op, SDOperand Lo, + SDOperand Hi) { ExpungeNode(Lo); ExpungeNode(Hi); @@ -468,14 +510,15 @@ AnalyzeNewNode(Hi.Val); // Remember that this is the result of the node. - std::pair &Entry = ExpandedNodes[Op]; + std::pair &Entry = ExpandedFloats[Op]; assert(Entry.first.Val == 0 && "Node already expanded"); Entry.first = Lo; Entry.second = Hi; } -void DAGTypeLegalizer::GetSplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi) { - std::pair &Entry = SplitNodes[Op]; +void DAGTypeLegalizer::GetSplitVector(SDOperand Op, SDOperand &Lo, + SDOperand &Hi) { + std::pair &Entry = SplitVectors[Op]; RemapNode(Entry.first); RemapNode(Entry.second); assert(Entry.first.Val && "Operand isn't split"); @@ -483,7 +526,8 @@ Hi = Entry.second; } -void DAGTypeLegalizer::SetSplitOp(SDOperand Op, SDOperand Lo, SDOperand Hi) { +void DAGTypeLegalizer::SetSplitVector(SDOperand Op, SDOperand Lo, + SDOperand Hi) { ExpungeNode(Lo); ExpungeNode(Hi); @@ -492,7 +536,7 @@ AnalyzeNewNode(Hi.Val); // Remember that this is the result of the node. - std::pair &Entry = SplitNodes[Op]; + std::pair &Entry = SplitVectors[Op]; assert(Entry.first.Val == 0 && "Node already split"); Entry.first = Lo; Entry.second = Hi; @@ -505,11 +549,11 @@ return DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerVT(BitWidth), Op); } -SDOperand DAGTypeLegalizer::CreateStackStoreLoad(SDOperand Op, +SDOperand DAGTypeLegalizer::CreateStackStoreLoad(SDOperand Op, MVT DestVT) { // Create the stack frame object. SDOperand FIPtr = DAG.CreateStackTemporary(DestVT); - + // Emit a store to the stack slot. SDOperand Store = DAG.getStore(DAG.getEntryNode(), Op, FIPtr, NULL, 0); // Result is a load from the stack slot. @@ -605,6 +649,6 @@ /// the graph. void SelectionDAG::LegalizeTypes() { if (ViewLegalizeTypesDAGs) viewGraph(); - + DAGTypeLegalizer(*this).run(); } Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h?rev=52408&r1=52407&r2=52408&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h Tue Jun 17 09:27:01 2008 @@ -47,31 +47,32 @@ /// ReadyToProcess - All operands have been processed, so this node is ready /// to be handled. ReadyToProcess = 0, - + /// NewNode - This is a new node that was created in the process of /// legalizing some other node. NewNode = -1, - + /// Processed - This is a node that has already been processed. Processed = -2 - + // 1+ - This is a node which has this many unlegalized operands. }; private: enum LegalizeAction { - Legal, // The target natively supports this type. - Promote, // This type should be executed in a larger type. - Expand, // This type should be split into two types of half the size. - FloatToInt, // Convert a floating point type to an integer of the same size. - Scalarize, // Replace this one-element vector type with its element type. - Split // This vector type should be split into smaller vectors. + Legal, // The target natively supports this type. + PromoteInteger, // Replace this integer type with a larger one. + ExpandInteger, // Split this integer type into two of half the size. + PromoteFloat, // Convert this float type to a same size integer type. + ExpandFloat, // Split this float type into two of half the size. + Scalarize, // Replace this one-element vector type with its element type. + Split // This vector type should be split into smaller vectors. }; /// ValueTypeActions - This is a bitvector that contains two bits for each /// simple value type, where the two bits correspond to the LegalizeAction /// enum from TargetLowering. This can be queried with "getTypeAction(VT)". TargetLowering::ValueTypeActionImpl ValueTypeActions; - + /// getTypeAction - Return how we should legalize values of this type, either /// it is already legal, or we need to promote it to a larger integer type, or /// we need to expand it into multiple registers of a smaller integer type, or @@ -84,16 +85,19 @@ case TargetLowering::Legal: return Legal; case TargetLowering::Promote: - return Promote; + return PromoteInteger; case TargetLowering::Expand: // Expand can mean // 1) split scalar in half, 2) convert a float to an integer, // 3) scalarize a single-element vector, 4) split a vector in two. if (!VT.isVector()) { - if (VT.getSizeInBits() == TLI.getTypeToTransformTo(VT).getSizeInBits()) - return FloatToInt; + if (VT.isInteger()) + return ExpandInteger; + else if (VT.getSizeInBits() == + TLI.getTypeToTransformTo(VT).getSizeInBits()) + return PromoteFloat; else - return Expand; + return ExpandFloat; } else if (VT.getVectorNumElements() == 1) { return Scalarize; } else { @@ -107,26 +111,30 @@ return ValueTypeActions.getTypeAction(VT) == TargetLowering::Legal; } - /// PromotedNodes - For nodes that are below legal width, this map indicates - /// what promoted value to use. - DenseMap PromotedNodes; - - /// ExpandedNodes - For nodes that need to be expanded this map indicates - /// which operands are the expanded version of the input. - DenseMap > ExpandedNodes; + /// PromotedIntegers - For integer nodes that are below legal width, this map + /// indicates what promoted value to use. + DenseMap PromotedIntegers; + + /// ExpandedIntegers - For integer nodes that need to be expanded this map + /// indicates which operands are the expanded version of the input. + DenseMap > ExpandedIntegers; - /// FloatToIntedNodes - For floating point nodes converted to integers of + /// PromotedFloats - For floating point nodes converted to integers of /// the same size, this map indicates the converted value to use. - DenseMap FloatToIntedNodes; + DenseMap PromotedFloats; + + /// ExpandedFloats - For float nodes that need to be expanded this map + /// indicates which operands are the expanded version of the input. + DenseMap > ExpandedFloats; - /// ScalarizedNodes - For nodes that are <1 x ty>, this map indicates the + /// ScalarizedVectors - For nodes that are <1 x ty>, this map indicates the /// scalar value of type 'ty' to use. - DenseMap ScalarizedNodes; + DenseMap ScalarizedVectors; - /// SplitNodes - For nodes that need to be split this map indicates + /// SplitVectors - For nodes that need to be split this map indicates /// which operands are the expanded version of the input. - DenseMap > SplitNodes; - + DenseMap > SplitVectors; + /// ReplacedNodes - For nodes that have been replaced with another, /// indicates the replacement node to use. DenseMap ReplacedNodes; @@ -135,17 +143,17 @@ /// pushed onto this worklist, all operands of a node must have already been /// processed. SmallVector Worklist; - + public: explicit DAGTypeLegalizer(SelectionDAG &dag) : TLI(dag.getTargetLoweringInfo()), DAG(dag), ValueTypeActions(TLI.getValueTypeActions()) { assert(MVT::LAST_VALUETYPE <= 32 && "Too many value types for ValueTypeActions to hold!"); - } - + } + void run(); - + /// ReanalyzeNode - Recompute the NodeID and correct processed operands /// for the specified node, adding it to the worklist if ready. void ReanalyzeNode(SDNode *N) { @@ -183,174 +191,186 @@ SDOperand Index); //===--------------------------------------------------------------------===// - // Promotion Support: LegalizeTypesPromote.cpp + // Integer Promotion Support: LegalizeIntegerTypes.cpp //===--------------------------------------------------------------------===// - - SDOperand GetPromotedOp(SDOperand Op) { - SDOperand &PromotedOp = PromotedNodes[Op]; + + SDOperand GetPromotedInteger(SDOperand Op) { + SDOperand &PromotedOp = PromotedIntegers[Op]; RemapNode(PromotedOp); assert(PromotedOp.Val && "Operand wasn't promoted?"); return PromotedOp; } - void SetPromotedOp(SDOperand Op, SDOperand Result); - - /// GetPromotedZExtOp - Get a promoted operand and zero extend it to the final - /// size. - SDOperand GetPromotedZExtOp(SDOperand Op) { + void SetPromotedInteger(SDOperand Op, SDOperand Result); + + /// ZExtPromotedInteger - Get a promoted operand and zero extend it to the + /// final size. + SDOperand ZExtPromotedInteger(SDOperand Op) { MVT OldVT = Op.getValueType(); - Op = GetPromotedOp(Op); + Op = GetPromotedInteger(Op); return DAG.getZeroExtendInReg(Op, OldVT); - } - - // Result Promotion. - void PromoteResult(SDNode *N, unsigned ResNo); - SDOperand PromoteResult_BIT_CONVERT(SDNode *N); - SDOperand PromoteResult_BUILD_PAIR(SDNode *N); - SDOperand PromoteResult_Constant(SDNode *N); - SDOperand PromoteResult_CTLZ(SDNode *N); - SDOperand PromoteResult_CTPOP(SDNode *N); - SDOperand PromoteResult_CTTZ(SDNode *N); - SDOperand PromoteResult_EXTRACT_VECTOR_ELT(SDNode *N); - SDOperand PromoteResult_FP_ROUND(SDNode *N); - SDOperand PromoteResult_FP_TO_XINT(SDNode *N); - SDOperand PromoteResult_INT_EXTEND(SDNode *N); - SDOperand PromoteResult_LOAD(LoadSDNode *N); - SDOperand PromoteResult_SDIV(SDNode *N); - SDOperand PromoteResult_SELECT (SDNode *N); - SDOperand PromoteResult_SELECT_CC(SDNode *N); - SDOperand PromoteResult_SETCC(SDNode *N); - SDOperand PromoteResult_SHL(SDNode *N); - SDOperand PromoteResult_SimpleIntBinOp(SDNode *N); - SDOperand PromoteResult_SRA(SDNode *N); - SDOperand PromoteResult_SRL(SDNode *N); - SDOperand PromoteResult_TRUNCATE(SDNode *N); - SDOperand PromoteResult_UDIV(SDNode *N); - SDOperand PromoteResult_UNDEF(SDNode *N); - - // Operand Promotion. - bool PromoteOperand(SDNode *N, unsigned OperandNo); - SDOperand PromoteOperand_ANY_EXTEND(SDNode *N); - SDOperand PromoteOperand_BUILD_PAIR(SDNode *N); - SDOperand PromoteOperand_BR_CC(SDNode *N, unsigned OpNo); - SDOperand PromoteOperand_BRCOND(SDNode *N, unsigned OpNo); - SDOperand PromoteOperand_BUILD_VECTOR(SDNode *N); - SDOperand PromoteOperand_FP_EXTEND(SDNode *N); - SDOperand PromoteOperand_FP_ROUND(SDNode *N); - SDOperand PromoteOperand_INT_TO_FP(SDNode *N); - SDOperand PromoteOperand_INSERT_VECTOR_ELT(SDNode *N, unsigned OpNo); - SDOperand PromoteOperand_MEMBARRIER(SDNode *N); - SDOperand PromoteOperand_RET(SDNode *N, unsigned OpNo); - SDOperand PromoteOperand_SELECT(SDNode *N, unsigned OpNo); - SDOperand PromoteOperand_SETCC(SDNode *N, unsigned OpNo); - SDOperand PromoteOperand_SIGN_EXTEND(SDNode *N); - SDOperand PromoteOperand_STORE(StoreSDNode *N, unsigned OpNo); - SDOperand PromoteOperand_TRUNCATE(SDNode *N); - SDOperand PromoteOperand_ZERO_EXTEND(SDNode *N); + } + + // Integer Result Promotion. + void PromoteIntegerResult(SDNode *N, unsigned ResNo); + SDOperand PromoteIntRes_BIT_CONVERT(SDNode *N); + SDOperand PromoteIntRes_BUILD_PAIR(SDNode *N); + SDOperand PromoteIntRes_Constant(SDNode *N); + SDOperand PromoteIntRes_CTLZ(SDNode *N); + SDOperand PromoteIntRes_CTPOP(SDNode *N); + SDOperand PromoteIntRes_CTTZ(SDNode *N); + SDOperand PromoteIntRes_EXTRACT_VECTOR_ELT(SDNode *N); + SDOperand PromoteIntRes_FP_ROUND(SDNode *N); + SDOperand PromoteIntRes_FP_TO_XINT(SDNode *N); + SDOperand PromoteIntRes_INT_EXTEND(SDNode *N); + SDOperand PromoteIntRes_LOAD(LoadSDNode *N); + SDOperand PromoteIntRes_SDIV(SDNode *N); + SDOperand PromoteIntRes_SELECT (SDNode *N); + SDOperand PromoteIntRes_SELECT_CC(SDNode *N); + SDOperand PromoteIntRes_SETCC(SDNode *N); + SDOperand PromoteIntRes_SHL(SDNode *N); + SDOperand PromoteIntRes_SimpleIntBinOp(SDNode *N); + SDOperand PromoteIntRes_SRA(SDNode *N); + SDOperand PromoteIntRes_SRL(SDNode *N); + SDOperand PromoteIntRes_TRUNCATE(SDNode *N); + SDOperand PromoteIntRes_UDIV(SDNode *N); + SDOperand PromoteIntRes_UNDEF(SDNode *N); + + // Integer Operand Promotion. + bool PromoteIntegerOperand(SDNode *N, unsigned OperandNo); + SDOperand PromoteIntOp_ANY_EXTEND(SDNode *N); + SDOperand PromoteIntOp_BUILD_PAIR(SDNode *N); + SDOperand PromoteIntOp_BR_CC(SDNode *N, unsigned OpNo); + SDOperand PromoteIntOp_BRCOND(SDNode *N, unsigned OpNo); + SDOperand PromoteIntOp_BUILD_VECTOR(SDNode *N); + SDOperand PromoteIntOp_FP_EXTEND(SDNode *N); + SDOperand PromoteIntOp_FP_ROUND(SDNode *N); + SDOperand PromoteIntOp_INT_TO_FP(SDNode *N); + SDOperand PromoteIntOp_INSERT_VECTOR_ELT(SDNode *N, unsigned OpNo); + SDOperand PromoteIntOp_MEMBARRIER(SDNode *N); + SDOperand PromoteIntOp_SELECT(SDNode *N, unsigned OpNo); + SDOperand PromoteIntOp_SETCC(SDNode *N, unsigned OpNo); + SDOperand PromoteIntOp_SIGN_EXTEND(SDNode *N); + SDOperand PromoteIntOp_STORE(StoreSDNode *N, unsigned OpNo); + SDOperand PromoteIntOp_TRUNCATE(SDNode *N); + SDOperand PromoteIntOp_ZERO_EXTEND(SDNode *N); void PromoteSetCCOperands(SDOperand &LHS,SDOperand &RHS, ISD::CondCode Code); //===--------------------------------------------------------------------===// - // Expansion Support: LegalizeTypesExpand.cpp + // Integer Expansion Support: LegalizeIntegerTypes.cpp //===--------------------------------------------------------------------===// - - void GetExpandedOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi); - void SetExpandedOp(SDOperand Op, SDOperand Lo, SDOperand Hi); - - // Result Expansion. - void ExpandResult(SDNode *N, unsigned ResNo); - void ExpandResult_ANY_EXTEND (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_AssertZext (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_BIT_CONVERT(SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_BUILD_PAIR (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_Constant (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_CTLZ (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_CTPOP (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_CTTZ (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_EXTRACT_VECTOR_ELT(SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_LOAD (LoadSDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_MERGE_VALUES(SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_SIGN_EXTEND(SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_SIGN_EXTEND_INREG(SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_TRUNCATE (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_UNDEF (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_ZERO_EXTEND(SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_FP_TO_SINT (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_FP_TO_UINT (SDNode *N, SDOperand &Lo, SDOperand &Hi); - - void ExpandResult_Logical (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_BSWAP (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_ADDSUB (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_ADDSUBC (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_ADDSUBE (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_SELECT (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_SELECT_CC (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_MUL (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_SDIV (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_SREM (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_UDIV (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_UREM (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandResult_Shift (SDNode *N, SDOperand &Lo, SDOperand &Hi); - - void ExpandShiftByConstant(SDNode *N, unsigned Amt, + + void GetExpandedInteger(SDOperand Op, SDOperand &Lo, SDOperand &Hi); + void SetExpandedInteger(SDOperand Op, SDOperand Lo, SDOperand Hi); + + // Integer Result Expansion. + void ExpandIntegerResult(SDNode *N, unsigned ResNo); + void ExpandIntRes_ANY_EXTEND (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_AssertZext (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_BIT_CONVERT (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_BUILD_PAIR (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_Constant (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_CTLZ (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_CTPOP (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_CTTZ (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_EXTRACT_VECTOR_ELT(SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_LOAD (LoadSDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_MERGE_VALUES (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_SIGN_EXTEND (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_SIGN_EXTEND_INREG (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_TRUNCATE (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_UNDEF (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_ZERO_EXTEND (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_FP_TO_SINT (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_FP_TO_UINT (SDNode *N, SDOperand &Lo, SDOperand &Hi); + + void ExpandIntRes_Logical (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_BSWAP (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_ADDSUB (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_ADDSUBC (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_ADDSUBE (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_SELECT (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_SELECT_CC (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_MUL (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_SDIV (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_SREM (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_UDIV (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_UREM (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandIntRes_Shift (SDNode *N, SDOperand &Lo, SDOperand &Hi); + + void ExpandShiftByConstant(SDNode *N, unsigned Amt, SDOperand &Lo, SDOperand &Hi); bool ExpandShiftWithKnownAmountBit(SDNode *N, SDOperand &Lo, SDOperand &Hi); - // Operand Expansion. - bool ExpandOperand(SDNode *N, unsigned OperandNo); - SDOperand ExpandOperand_BIT_CONVERT(SDNode *N); - SDOperand ExpandOperand_BR_CC(SDNode *N); - SDOperand ExpandOperand_BUILD_VECTOR(SDNode *N); - SDOperand ExpandOperand_EXTRACT_ELEMENT(SDNode *N); - SDOperand ExpandOperand_SETCC(SDNode *N); - SDOperand ExpandOperand_SINT_TO_FP(SDOperand Source, MVT DestTy); - SDOperand ExpandOperand_STORE(StoreSDNode *N, unsigned OpNo); - SDOperand ExpandOperand_TRUNCATE(SDNode *N); - SDOperand ExpandOperand_UINT_TO_FP(SDOperand Source, MVT DestTy); + // Integer Operand Expansion. + bool ExpandIntegerOperand(SDNode *N, unsigned OperandNo); + SDOperand ExpandIntOp_BIT_CONVERT(SDNode *N); + SDOperand ExpandIntOp_BR_CC(SDNode *N); + SDOperand ExpandIntOp_BUILD_VECTOR(SDNode *N); + SDOperand ExpandIntOp_EXTRACT_ELEMENT(SDNode *N); + SDOperand ExpandIntOp_SETCC(SDNode *N); + SDOperand ExpandIntOp_SINT_TO_FP(SDOperand Source, MVT DestTy); + SDOperand ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo); + SDOperand ExpandIntOp_TRUNCATE(SDNode *N); + SDOperand ExpandIntOp_UINT_TO_FP(SDOperand Source, MVT DestTy); void ExpandSetCCOperands(SDOperand &NewLHS, SDOperand &NewRHS, ISD::CondCode &CCCode); - + //===--------------------------------------------------------------------===// - // Float to Integer Conversion Support: LegalizeTypesFloatToInt.cpp + // Float to Integer Conversion Support: LegalizeFloatTypes.cpp //===--------------------------------------------------------------------===// - SDOperand GetIntegerOp(SDOperand Op) { - SDOperand &IntegerOp = FloatToIntedNodes[Op]; - RemapNode(IntegerOp); - assert(IntegerOp.Val && "Operand wasn't converted to integer?"); - return IntegerOp; + SDOperand GetPromotedFloat(SDOperand Op) { + SDOperand &PromotedOp = PromotedFloats[Op]; + RemapNode(PromotedOp); + assert(PromotedOp.Val && "Operand wasn't converted to integer?"); + return PromotedOp; } - void SetIntegerOp(SDOperand Op, SDOperand Result); + void SetPromotedFloat(SDOperand Op, SDOperand Result); // Result Float to Integer Conversion. - void FloatToIntResult(SDNode *N, unsigned OpNo); - SDOperand FloatToIntRes_BIT_CONVERT(SDNode *N); - SDOperand FloatToIntRes_BUILD_PAIR(SDNode *N); - SDOperand FloatToIntRes_ConstantFP(ConstantFPSDNode *N); - SDOperand FloatToIntRes_FADD(SDNode *N); - SDOperand FloatToIntRes_FCOPYSIGN(SDNode *N); - SDOperand FloatToIntRes_FMUL(SDNode *N); - SDOperand FloatToIntRes_FSUB(SDNode *N); - SDOperand FloatToIntRes_LOAD(SDNode *N); - SDOperand FloatToIntRes_XINT_TO_FP(SDNode *N); + void PromoteFloatResult(SDNode *N, unsigned OpNo); + SDOperand PromoteFloatRes_BIT_CONVERT(SDNode *N); + SDOperand PromoteFloatRes_BUILD_PAIR(SDNode *N); + SDOperand PromoteFloatRes_ConstantFP(ConstantFPSDNode *N); + SDOperand PromoteFloatRes_FADD(SDNode *N); + SDOperand PromoteFloatRes_FCOPYSIGN(SDNode *N); + SDOperand PromoteFloatRes_FMUL(SDNode *N); + SDOperand PromoteFloatRes_FSUB(SDNode *N); + SDOperand PromoteFloatRes_LOAD(SDNode *N); + SDOperand PromoteFloatRes_XINT_TO_FP(SDNode *N); // Operand Float to Integer Conversion. - bool FloatToIntOperand(SDNode *N, unsigned OpNo); - SDOperand FloatToIntOp_BIT_CONVERT(SDNode *N); + bool PromoteFloatOperand(SDNode *N, unsigned OpNo); + SDOperand PromoteFloatOp_BIT_CONVERT(SDNode *N); + + //===--------------------------------------------------------------------===// + // Float Expansion Support: LegalizeFloatTypes.cpp + //===--------------------------------------------------------------------===// + + void GetExpandedFloat(SDOperand Op, SDOperand &Lo, SDOperand &Hi); + void SetExpandedFloat(SDOperand Op, SDOperand Lo, SDOperand Hi); + + // Float Result Expansion. + void ExpandFloatResult(SDNode *N, unsigned ResNo); + + // Float Operand Expansion. + bool ExpandFloatOperand(SDNode *N, unsigned OperandNo); //===--------------------------------------------------------------------===// - // Scalarization Support: LegalizeTypesScalarize.cpp + // Scalarization Support: LegalizeVectorTypes.cpp //===--------------------------------------------------------------------===// - - SDOperand GetScalarizedOp(SDOperand Op) { - SDOperand &ScalarOp = ScalarizedNodes[Op]; - RemapNode(ScalarOp); - assert(ScalarOp.Val && "Operand wasn't scalarized?"); - return ScalarOp; + + SDOperand GetScalarizedVector(SDOperand Op) { + SDOperand &ScalarizedOp = ScalarizedVectors[Op]; + RemapNode(ScalarizedOp); + assert(ScalarizedOp.Val && "Operand wasn't scalarized?"); + return ScalarizedOp; } - void SetScalarizedOp(SDOperand Op, SDOperand Result); - - // Result Vector Scalarization: <1 x ty> -> ty. + void SetScalarizedVector(SDOperand Op, SDOperand Result); + + // Vector Result Scalarization: <1 x ty> -> ty. void ScalarizeResult(SDNode *N, unsigned OpNo); SDOperand ScalarizeRes_BinOp(SDNode *N); SDOperand ScalarizeRes_UnaryOp(SDNode *N); @@ -363,20 +383,20 @@ SDOperand ScalarizeRes_UNDEF(SDNode *N); SDOperand ScalarizeRes_VECTOR_SHUFFLE(SDNode *N); - // Operand Vector Scalarization: <1 x ty> -> ty. + // Vector Operand Scalarization: <1 x ty> -> ty. bool ScalarizeOperand(SDNode *N, unsigned OpNo); SDOperand ScalarizeOp_BIT_CONVERT(SDNode *N); SDOperand ScalarizeOp_EXTRACT_VECTOR_ELT(SDNode *N); SDOperand ScalarizeOp_STORE(StoreSDNode *N, unsigned OpNo); //===--------------------------------------------------------------------===// - // Vector Splitting Support: LegalizeTypesSplit.cpp + // Vector Splitting Support: LegalizeVectorTypes.cpp //===--------------------------------------------------------------------===// - - void GetSplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi); - void SetSplitOp(SDOperand Op, SDOperand Lo, SDOperand Hi); - - // Result Vector Splitting: <128 x ty> -> 2 x <64 x ty>. + + void GetSplitVector(SDOperand Op, SDOperand &Lo, SDOperand &Hi); + void SetSplitVector(SDOperand Op, SDOperand Lo, SDOperand Hi); + + // Vector Result Splitting: <128 x ty> -> 2 x <64 x ty>. void SplitResult(SDNode *N, unsigned OpNo); void SplitRes_UNDEF(SDNode *N, SDOperand &Lo, SDOperand &Hi); @@ -392,8 +412,8 @@ void SplitRes_BinOp(SDNode *N, SDOperand &Lo, SDOperand &Hi); void SplitRes_FPOWI(SDNode *N, SDOperand &Lo, SDOperand &Hi); void SplitRes_SELECT(SDNode *N, SDOperand &Lo, SDOperand &Hi); - - // Operand Vector Splitting: <128 x ty> -> 2 x <64 x ty>. + + // Vector Operand Splitting: <128 x ty> -> 2 x <64 x ty>. bool SplitOperand(SDNode *N, unsigned OpNo); SDOperand SplitOp_BIT_CONVERT(SDNode *N); Removed: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp?rev=52407&view=auto ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp (removed) @@ -1,1465 +0,0 @@ -//===-- LegalizeTypesExpand.cpp - Expansion for LegalizeTypes -------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements expansion support for LegalizeTypes. Expansion is the -// act of changing a computation in an invalid type to be a computation in -// multiple registers of a smaller type. For example, implementing i64 -// arithmetic in two i32 registers (as is often needed on 32-bit targets, for -// example). -// -//===----------------------------------------------------------------------===// - -#include "LegalizeTypes.h" -#include "llvm/Constants.h" -using namespace llvm; - -//===----------------------------------------------------------------------===// -// Result Expansion -//===----------------------------------------------------------------------===// - -/// ExpandResult - This method is called when the specified result of the -/// specified node is found to need expansion. At this point, the node may also -/// have invalid operands or may have other results that need promotion, we just -/// know that (at least) one result needs expansion. -void DAGTypeLegalizer::ExpandResult(SDNode *N, unsigned ResNo) { - DEBUG(cerr << "Expand node result: "; N->dump(&DAG); cerr << "\n"); - SDOperand Lo, Hi; - Lo = Hi = SDOperand(); - - // See if the target wants to custom expand this node. - if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == - TargetLowering::Custom) { - // If the target wants to, allow it to lower this itself. - if (SDNode *P = TLI.ExpandOperationResult(N, DAG)) { - // Everything that once used N now uses P. We are guaranteed that the - // result value types of N and the result value types of P match. - ReplaceNodeWith(N, P); - return; - } - } - - switch (N->getOpcode()) { - default: -#ifndef NDEBUG - cerr << "ExpandResult #" << ResNo << ": "; - N->dump(&DAG); cerr << "\n"; -#endif - assert(0 && "Do not know how to expand the result of this operator!"); - abort(); - - case ISD::UNDEF: ExpandResult_UNDEF(N, Lo, Hi); break; - case ISD::Constant: ExpandResult_Constant(N, Lo, Hi); break; - case ISD::BUILD_PAIR: ExpandResult_BUILD_PAIR(N, Lo, Hi); break; - case ISD::MERGE_VALUES: ExpandResult_MERGE_VALUES(N, Lo, Hi); break; - case ISD::ANY_EXTEND: ExpandResult_ANY_EXTEND(N, Lo, Hi); break; - case ISD::ZERO_EXTEND: ExpandResult_ZERO_EXTEND(N, Lo, Hi); break; - case ISD::SIGN_EXTEND: ExpandResult_SIGN_EXTEND(N, Lo, Hi); break; - case ISD::AssertZext: ExpandResult_AssertZext(N, Lo, Hi); break; - case ISD::TRUNCATE: ExpandResult_TRUNCATE(N, Lo, Hi); break; - case ISD::BIT_CONVERT: ExpandResult_BIT_CONVERT(N, Lo, Hi); break; - case ISD::SIGN_EXTEND_INREG: ExpandResult_SIGN_EXTEND_INREG(N, Lo, Hi); break; - case ISD::FP_TO_SINT: ExpandResult_FP_TO_SINT(N, Lo, Hi); break; - case ISD::FP_TO_UINT: ExpandResult_FP_TO_UINT(N, Lo, Hi); break; - case ISD::LOAD: ExpandResult_LOAD(cast(N), Lo, Hi); break; - - case ISD::AND: - case ISD::OR: - case ISD::XOR: ExpandResult_Logical(N, Lo, Hi); break; - case ISD::BSWAP: ExpandResult_BSWAP(N, Lo, Hi); break; - case ISD::ADD: - case ISD::SUB: ExpandResult_ADDSUB(N, Lo, Hi); break; - case ISD::ADDC: - case ISD::SUBC: ExpandResult_ADDSUBC(N, Lo, Hi); break; - case ISD::ADDE: - case ISD::SUBE: ExpandResult_ADDSUBE(N, Lo, Hi); break; - case ISD::SELECT: ExpandResult_SELECT(N, Lo, Hi); break; - case ISD::SELECT_CC: ExpandResult_SELECT_CC(N, Lo, Hi); break; - case ISD::MUL: ExpandResult_MUL(N, Lo, Hi); break; - case ISD::SDIV: ExpandResult_SDIV(N, Lo, Hi); break; - case ISD::SREM: ExpandResult_SREM(N, Lo, Hi); break; - case ISD::UDIV: ExpandResult_UDIV(N, Lo, Hi); break; - case ISD::UREM: ExpandResult_UREM(N, Lo, Hi); break; - case ISD::SHL: - case ISD::SRA: - case ISD::SRL: ExpandResult_Shift(N, Lo, Hi); break; - - case ISD::CTLZ: ExpandResult_CTLZ(N, Lo, Hi); break; - case ISD::CTPOP: ExpandResult_CTPOP(N, Lo, Hi); break; - case ISD::CTTZ: ExpandResult_CTTZ(N, Lo, Hi); break; - - case ISD::EXTRACT_VECTOR_ELT: - ExpandResult_EXTRACT_VECTOR_ELT(N, Lo, Hi); - break; - } - - // If Lo/Hi is null, the sub-method took care of registering results etc. - if (Lo.Val) - SetExpandedOp(SDOperand(N, ResNo), Lo, Hi); -} - -void DAGTypeLegalizer::ExpandResult_UNDEF(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - Lo = Hi = DAG.getNode(ISD::UNDEF, NVT); -} - -void DAGTypeLegalizer::ExpandResult_Constant(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - unsigned NBitWidth = NVT.getSizeInBits(); - const APInt &Cst = cast(N)->getAPIntValue(); - Lo = DAG.getConstant(APInt(Cst).trunc(NBitWidth), NVT); - Hi = DAG.getConstant(Cst.lshr(NBitWidth).trunc(NBitWidth), NVT); -} - -void DAGTypeLegalizer::ExpandResult_BUILD_PAIR(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - // Return the operands. - Lo = N->getOperand(0); - Hi = N->getOperand(1); -} - -void DAGTypeLegalizer::ExpandResult_MERGE_VALUES(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - // A MERGE_VALUES node can produce any number of values. We know that the - // first illegal one needs to be expanded into Lo/Hi. - unsigned i; - - // The string of legal results gets turns into the input operands, which have - // the same type. - for (i = 0; isTypeLegal(N->getValueType(i)); ++i) - ReplaceValueWith(SDOperand(N, i), SDOperand(N->getOperand(i))); - - // The first illegal result must be the one that needs to be expanded. - GetExpandedOp(N->getOperand(i), Lo, Hi); - - // Legalize the rest of the results into the input operands whether they are - // legal or not. - unsigned e = N->getNumValues(); - for (++i; i != e; ++i) - ReplaceValueWith(SDOperand(N, i), SDOperand(N->getOperand(i))); -} - -void DAGTypeLegalizer::ExpandResult_ANY_EXTEND(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - SDOperand Op = N->getOperand(0); - if (Op.getValueType().bitsLE(NVT)) { - // The low part is any extension of the input (which degenerates to a copy). - Lo = DAG.getNode(ISD::ANY_EXTEND, NVT, Op); - Hi = DAG.getNode(ISD::UNDEF, NVT); // The high part is undefined. - } else { - // For example, extension of an i48 to an i64. The operand type necessarily - // promotes to the result type, so will end up being expanded too. - assert(getTypeAction(Op.getValueType()) == Promote && - "Only know how to promote this result!"); - SDOperand Res = GetPromotedOp(Op); - assert(Res.getValueType() == N->getValueType(0) && - "Operand over promoted?"); - // Split the promoted operand. This will simplify when it is expanded. - SplitInteger(Res, Lo, Hi); - } -} - -void DAGTypeLegalizer::ExpandResult_ZERO_EXTEND(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - SDOperand Op = N->getOperand(0); - if (Op.getValueType().bitsLE(NVT)) { - // The low part is zero extension of the input (which degenerates to a copy). - Lo = DAG.getNode(ISD::ZERO_EXTEND, NVT, N->getOperand(0)); - Hi = DAG.getConstant(0, NVT); // The high part is just a zero. - } else { - // For example, extension of an i48 to an i64. The operand type necessarily - // promotes to the result type, so will end up being expanded too. - assert(getTypeAction(Op.getValueType()) == Promote && - "Only know how to promote this result!"); - SDOperand Res = GetPromotedOp(Op); - assert(Res.getValueType() == N->getValueType(0) && - "Operand over promoted?"); - // Split the promoted operand. This will simplify when it is expanded. - SplitInteger(Res, Lo, Hi); - unsigned ExcessBits = - Op.getValueType().getSizeInBits() - NVT.getSizeInBits(); - Hi = DAG.getZeroExtendInReg(Hi, MVT::getIntegerVT(ExcessBits)); - } -} - -void DAGTypeLegalizer::ExpandResult_SIGN_EXTEND(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - SDOperand Op = N->getOperand(0); - if (Op.getValueType().bitsLE(NVT)) { - // The low part is sign extension of the input (which degenerates to a copy). - Lo = DAG.getNode(ISD::SIGN_EXTEND, NVT, N->getOperand(0)); - // The high part is obtained by SRA'ing all but one of the bits of low part. - unsigned LoSize = NVT.getSizeInBits(); - Hi = DAG.getNode(ISD::SRA, NVT, Lo, - DAG.getConstant(LoSize-1, TLI.getShiftAmountTy())); - } else { - // For example, extension of an i48 to an i64. The operand type necessarily - // promotes to the result type, so will end up being expanded too. - assert(getTypeAction(Op.getValueType()) == Promote && - "Only know how to promote this result!"); - SDOperand Res = GetPromotedOp(Op); - assert(Res.getValueType() == N->getValueType(0) && - "Operand over promoted?"); - // Split the promoted operand. This will simplify when it is expanded. - SplitInteger(Res, Lo, Hi); - unsigned ExcessBits = - Op.getValueType().getSizeInBits() - NVT.getSizeInBits(); - Hi = DAG.getNode(ISD::SIGN_EXTEND_INREG, Hi.getValueType(), Hi, - DAG.getValueType(MVT::getIntegerVT(ExcessBits))); - } -} - -void DAGTypeLegalizer::ExpandResult_AssertZext(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - GetExpandedOp(N->getOperand(0), Lo, Hi); - MVT NVT = Lo.getValueType(); - MVT EVT = cast(N->getOperand(1))->getVT(); - unsigned NVTBits = NVT.getSizeInBits(); - unsigned EVTBits = EVT.getSizeInBits(); - - if (NVTBits < EVTBits) { - Hi = DAG.getNode(ISD::AssertZext, NVT, Hi, - DAG.getValueType(MVT::getIntegerVT(EVTBits - NVTBits))); - } else { - Lo = DAG.getNode(ISD::AssertZext, NVT, Lo, DAG.getValueType(EVT)); - // The high part must be zero, make it explicit. - Hi = DAG.getConstant(0, NVT); - } -} - -void DAGTypeLegalizer::ExpandResult_TRUNCATE(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - Lo = DAG.getNode(ISD::TRUNCATE, NVT, N->getOperand(0)); - Hi = DAG.getNode(ISD::SRL, N->getOperand(0).getValueType(), N->getOperand(0), - DAG.getConstant(NVT.getSizeInBits(), - TLI.getShiftAmountTy())); - Hi = DAG.getNode(ISD::TRUNCATE, NVT, Hi); -} - -void DAGTypeLegalizer::ExpandResult_BIT_CONVERT(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - SDOperand InOp = N->getOperand(0); - MVT InVT = InOp.getValueType(); - - // Handle some special cases efficiently. - switch (getTypeAction(InVT)) { - default: - assert(false && "Unknown type action!"); - case Legal: - case Promote: - break; - case Expand: - // Convert the expanded pieces of the input. - GetExpandedOp(InOp, Lo, Hi); - Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); - Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); - return; - case FloatToInt: - // Convert the integer operand instead. - SplitInteger(GetIntegerOp(InOp), Lo, Hi); - Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); - Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); - return; - case Split: - // Convert the split parts of the input if it was split in two. - GetSplitOp(InOp, Lo, Hi); - if (Lo.getValueType() == Hi.getValueType()) { - if (TLI.isBigEndian()) - std::swap(Lo, Hi); - Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); - Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); - return; - } - break; - case Scalarize: - // Convert the element instead. - SplitInteger(BitConvertToInteger(GetScalarizedOp(InOp)), Lo, Hi); - Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); - Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); - return; - } - - // Lower the bit-convert to a store/load from the stack, then expand the load. - SDOperand Op = CreateStackStoreLoad(InOp, N->getValueType(0)); - ExpandResult_LOAD(cast(Op.Val), Lo, Hi); -} - -void DAGTypeLegalizer:: -ExpandResult_SIGN_EXTEND_INREG(SDNode *N, SDOperand &Lo, SDOperand &Hi) { - GetExpandedOp(N->getOperand(0), Lo, Hi); - MVT EVT = cast(N->getOperand(1))->getVT(); - - if (EVT.bitsLE(Lo.getValueType())) { - // sext_inreg the low part if needed. - Lo = DAG.getNode(ISD::SIGN_EXTEND_INREG, Lo.getValueType(), Lo, - N->getOperand(1)); - - // The high part gets the sign extension from the lo-part. This handles - // things like sextinreg V:i64 from i8. - Hi = DAG.getNode(ISD::SRA, Hi.getValueType(), Lo, - DAG.getConstant(Hi.getValueType().getSizeInBits()-1, - TLI.getShiftAmountTy())); - } else { - // For example, extension of an i48 to an i64. Leave the low part alone, - // sext_inreg the high part. - unsigned ExcessBits = - EVT.getSizeInBits() - Lo.getValueType().getSizeInBits(); - Hi = DAG.getNode(ISD::SIGN_EXTEND_INREG, Hi.getValueType(), Hi, - DAG.getValueType(MVT::getIntegerVT(ExcessBits))); - } -} - -void DAGTypeLegalizer::ExpandResult_FP_TO_SINT(SDNode *N, SDOperand &Lo, - SDOperand &Hi) { - MVT VT = N->getValueType(0); - SDOperand Op = N->getOperand(0); - RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; - if (VT == MVT::i64) { - if (Op.getValueType() == MVT::f32) - LC = RTLIB::FPTOSINT_F32_I64; - else if (Op.getValueType() == MVT::f64) - LC = RTLIB::FPTOSINT_F64_I64; - else if (Op.getValueType() == MVT::f80) - LC = RTLIB::FPTOSINT_F80_I64; - else if (Op.getValueType() == MVT::ppcf128) - LC = RTLIB::FPTOSINT_PPCF128_I64; - } else if (VT == MVT::i128) { - if (Op.getValueType() == MVT::f32) - LC = RTLIB::FPTOSINT_F32_I128; - else if (Op.getValueType() == MVT::f64) - LC = RTLIB::FPTOSINT_F64_I128; - else if (Op.getValueType() == MVT::f80) - LC = RTLIB::FPTOSINT_F80_I128; - else if (Op.getValueType() == MVT::ppcf128) - LC = RTLIB::FPTOSINT_PPCF128_I128; - } else { - assert(0 && "Unexpected fp-to-sint conversion!"); - } - SplitInteger(MakeLibCall(LC, VT, &Op, 1, true/*sign irrelevant*/), Lo, Hi); -} - -void DAGTypeLegalizer::ExpandResult_FP_TO_UINT(SDNode *N, SDOperand &Lo, - SDOperand &Hi) { - MVT VT = N->getValueType(0); - SDOperand Op = N->getOperand(0); - RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; - if (VT == MVT::i64) { - if (Op.getValueType() == MVT::f32) - LC = RTLIB::FPTOUINT_F32_I64; - else if (Op.getValueType() == MVT::f64) - LC = RTLIB::FPTOUINT_F64_I64; - else if (Op.getValueType() == MVT::f80) - LC = RTLIB::FPTOUINT_F80_I64; - else if (Op.getValueType() == MVT::ppcf128) - LC = RTLIB::FPTOUINT_PPCF128_I64; - } else if (VT == MVT::i128) { - if (Op.getValueType() == MVT::f32) - LC = RTLIB::FPTOUINT_F32_I128; - else if (Op.getValueType() == MVT::f64) - LC = RTLIB::FPTOUINT_F64_I128; - else if (Op.getValueType() == MVT::f80) - LC = RTLIB::FPTOUINT_F80_I128; - else if (Op.getValueType() == MVT::ppcf128) - LC = RTLIB::FPTOUINT_PPCF128_I128; - } else { - assert(0 && "Unexpected fp-to-uint conversion!"); - } - SplitInteger(MakeLibCall(LC, VT, &Op, 1, false/*sign irrelevant*/), Lo, Hi); -} - -void DAGTypeLegalizer::ExpandResult_LOAD(LoadSDNode *N, - SDOperand &Lo, SDOperand &Hi) { - // FIXME: Add support for indexed loads. - MVT VT = N->getValueType(0); - MVT NVT = TLI.getTypeToTransformTo(VT); - SDOperand Ch = N->getChain(); // Legalize the chain. - SDOperand Ptr = N->getBasePtr(); // Legalize the pointer. - ISD::LoadExtType ExtType = N->getExtensionType(); - int SVOffset = N->getSrcValueOffset(); - unsigned Alignment = N->getAlignment(); - bool isVolatile = N->isVolatile(); - - assert(!(NVT.getSizeInBits() & 7) && "Expanded type not byte sized!"); - - if (ExtType == ISD::NON_EXTLOAD) { - Lo = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset, - isVolatile, Alignment); - // Increment the pointer to the other half. - unsigned IncrementSize = NVT.getSizeInBits()/8; - Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, - DAG.getIntPtrConstant(IncrementSize)); - Hi = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset+IncrementSize, - isVolatile, MinAlign(Alignment, IncrementSize)); - - // Build a factor node to remember that this load is independent of the - // other one. - Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1), - Hi.getValue(1)); - - // Handle endianness of the load. - if (TLI.isBigEndian()) - std::swap(Lo, Hi); - } else if (N->getMemoryVT().bitsLE(NVT)) { - MVT EVT = N->getMemoryVT(); - - Lo = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(), SVOffset, EVT, - isVolatile, Alignment); - - // Remember the chain. - Ch = Lo.getValue(1); - - if (ExtType == ISD::SEXTLOAD) { - // The high part is obtained by SRA'ing all but one of the bits of the - // lo part. - unsigned LoSize = Lo.getValueType().getSizeInBits(); - Hi = DAG.getNode(ISD::SRA, NVT, Lo, - DAG.getConstant(LoSize-1, TLI.getShiftAmountTy())); - } else if (ExtType == ISD::ZEXTLOAD) { - // The high part is just a zero. - Hi = DAG.getConstant(0, NVT); - } else { - assert(ExtType == ISD::EXTLOAD && "Unknown extload!"); - // The high part is undefined. - Hi = DAG.getNode(ISD::UNDEF, NVT); - } - } else if (TLI.isLittleEndian()) { - // Little-endian - low bits are at low addresses. - Lo = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset, - isVolatile, Alignment); - - unsigned ExcessBits = - N->getMemoryVT().getSizeInBits() - NVT.getSizeInBits(); - MVT NEVT = MVT::getIntegerVT(ExcessBits); - - // Increment the pointer to the other half. - unsigned IncrementSize = NVT.getSizeInBits()/8; - Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, - DAG.getIntPtrConstant(IncrementSize)); - Hi = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(), - SVOffset+IncrementSize, NEVT, - isVolatile, MinAlign(Alignment, IncrementSize)); - - // Build a factor node to remember that this load is independent of the - // other one. - Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1), - Hi.getValue(1)); - } else { - // Big-endian - high bits are at low addresses. Favor aligned loads at - // the cost of some bit-fiddling. - MVT EVT = N->getMemoryVT(); - unsigned EBytes = EVT.getStoreSizeInBits()/8; - unsigned IncrementSize = NVT.getSizeInBits()/8; - unsigned ExcessBits = (EBytes - IncrementSize)*8; - - // Load both the high bits and maybe some of the low bits. - Hi = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(), SVOffset, - MVT::getIntegerVT(EVT.getSizeInBits() - ExcessBits), - isVolatile, Alignment); - - // Increment the pointer to the other half. - Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, - DAG.getIntPtrConstant(IncrementSize)); - // Load the rest of the low bits. - Lo = DAG.getExtLoad(ISD::ZEXTLOAD, NVT, Ch, Ptr, N->getSrcValue(), - SVOffset+IncrementSize, - MVT::getIntegerVT(ExcessBits), - isVolatile, MinAlign(Alignment, IncrementSize)); - - // Build a factor node to remember that this load is independent of the - // other one. - Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1), - Hi.getValue(1)); - - if (ExcessBits < NVT.getSizeInBits()) { - // Transfer low bits from the bottom of Hi to the top of Lo. - Lo = DAG.getNode(ISD::OR, NVT, Lo, - DAG.getNode(ISD::SHL, NVT, Hi, - DAG.getConstant(ExcessBits, - TLI.getShiftAmountTy()))); - // Move high bits to the right position in Hi. - Hi = DAG.getNode(ExtType == ISD::SEXTLOAD ? ISD::SRA : ISD::SRL, NVT, Hi, - DAG.getConstant(NVT.getSizeInBits() - ExcessBits, - TLI.getShiftAmountTy())); - } - } - - // Legalized the chain result - switch anything that used the old chain to - // use the new one. - ReplaceValueWith(SDOperand(N, 1), Ch); -} - -void DAGTypeLegalizer::ExpandResult_Logical(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - SDOperand LL, LH, RL, RH; - GetExpandedOp(N->getOperand(0), LL, LH); - GetExpandedOp(N->getOperand(1), RL, RH); - Lo = DAG.getNode(N->getOpcode(), LL.getValueType(), LL, RL); - Hi = DAG.getNode(N->getOpcode(), LL.getValueType(), LH, RH); -} - -void DAGTypeLegalizer::ExpandResult_BSWAP(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - GetExpandedOp(N->getOperand(0), Hi, Lo); // Note swapped operands. - Lo = DAG.getNode(ISD::BSWAP, Lo.getValueType(), Lo); - Hi = DAG.getNode(ISD::BSWAP, Hi.getValueType(), Hi); -} - -void DAGTypeLegalizer::ExpandResult_SELECT(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - SDOperand LL, LH, RL, RH; - GetExpandedOp(N->getOperand(1), LL, LH); - GetExpandedOp(N->getOperand(2), RL, RH); - Lo = DAG.getNode(ISD::SELECT, LL.getValueType(), N->getOperand(0), LL, RL); - Hi = DAG.getNode(ISD::SELECT, LL.getValueType(), N->getOperand(0), LH, RH); -} - -void DAGTypeLegalizer::ExpandResult_SELECT_CC(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - SDOperand LL, LH, RL, RH; - GetExpandedOp(N->getOperand(2), LL, LH); - GetExpandedOp(N->getOperand(3), RL, RH); - Lo = DAG.getNode(ISD::SELECT_CC, LL.getValueType(), N->getOperand(0), - N->getOperand(1), LL, RL, N->getOperand(4)); - Hi = DAG.getNode(ISD::SELECT_CC, LL.getValueType(), N->getOperand(0), - N->getOperand(1), LH, RH, N->getOperand(4)); -} - -void DAGTypeLegalizer::ExpandResult_ADDSUB(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - // Expand the subcomponents. - SDOperand LHSL, LHSH, RHSL, RHSH; - GetExpandedOp(N->getOperand(0), LHSL, LHSH); - GetExpandedOp(N->getOperand(1), RHSL, RHSH); - SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag); - SDOperand LoOps[2] = { LHSL, RHSL }; - SDOperand HiOps[3] = { LHSH, RHSH }; - - if (N->getOpcode() == ISD::ADD) { - Lo = DAG.getNode(ISD::ADDC, VTList, LoOps, 2); - HiOps[2] = Lo.getValue(1); - Hi = DAG.getNode(ISD::ADDE, VTList, HiOps, 3); - } else { - Lo = DAG.getNode(ISD::SUBC, VTList, LoOps, 2); - HiOps[2] = Lo.getValue(1); - Hi = DAG.getNode(ISD::SUBE, VTList, HiOps, 3); - } -} - -void DAGTypeLegalizer::ExpandResult_ADDSUBC(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - // Expand the subcomponents. - SDOperand LHSL, LHSH, RHSL, RHSH; - GetExpandedOp(N->getOperand(0), LHSL, LHSH); - GetExpandedOp(N->getOperand(1), RHSL, RHSH); - SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag); - SDOperand LoOps[2] = { LHSL, RHSL }; - SDOperand HiOps[3] = { LHSH, RHSH }; - - if (N->getOpcode() == ISD::ADDC) { - Lo = DAG.getNode(ISD::ADDC, VTList, LoOps, 2); - HiOps[2] = Lo.getValue(1); - Hi = DAG.getNode(ISD::ADDE, VTList, HiOps, 3); - } else { - Lo = DAG.getNode(ISD::SUBC, VTList, LoOps, 2); - HiOps[2] = Lo.getValue(1); - Hi = DAG.getNode(ISD::SUBE, VTList, HiOps, 3); - } - - // Legalized the flag result - switch anything that used the old flag to - // use the new one. - ReplaceValueWith(SDOperand(N, 1), Hi.getValue(1)); -} - -void DAGTypeLegalizer::ExpandResult_ADDSUBE(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - // Expand the subcomponents. - SDOperand LHSL, LHSH, RHSL, RHSH; - GetExpandedOp(N->getOperand(0), LHSL, LHSH); - GetExpandedOp(N->getOperand(1), RHSL, RHSH); - SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag); - SDOperand LoOps[3] = { LHSL, RHSL, N->getOperand(2) }; - SDOperand HiOps[3] = { LHSH, RHSH }; - - Lo = DAG.getNode(N->getOpcode(), VTList, LoOps, 3); - HiOps[2] = Lo.getValue(1); - Hi = DAG.getNode(N->getOpcode(), VTList, HiOps, 3); - - // Legalized the flag result - switch anything that used the old flag to - // use the new one. - ReplaceValueWith(SDOperand(N, 1), Hi.getValue(1)); -} - -void DAGTypeLegalizer::ExpandResult_MUL(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - MVT VT = N->getValueType(0); - MVT NVT = TLI.getTypeToTransformTo(VT); - - bool HasMULHS = TLI.isOperationLegal(ISD::MULHS, NVT); - bool HasMULHU = TLI.isOperationLegal(ISD::MULHU, NVT); - bool HasSMUL_LOHI = TLI.isOperationLegal(ISD::SMUL_LOHI, NVT); - bool HasUMUL_LOHI = TLI.isOperationLegal(ISD::UMUL_LOHI, NVT); - if (HasMULHU || HasMULHS || HasUMUL_LOHI || HasSMUL_LOHI) { - SDOperand LL, LH, RL, RH; - GetExpandedOp(N->getOperand(0), LL, LH); - GetExpandedOp(N->getOperand(1), RL, RH); - unsigned OuterBitSize = VT.getSizeInBits(); - unsigned BitSize = NVT.getSizeInBits(); - unsigned LHSSB = DAG.ComputeNumSignBits(N->getOperand(0)); - unsigned RHSSB = DAG.ComputeNumSignBits(N->getOperand(1)); - - if (DAG.MaskedValueIsZero(N->getOperand(0), - APInt::getHighBitsSet(OuterBitSize, LHSSB)) && - DAG.MaskedValueIsZero(N->getOperand(1), - APInt::getHighBitsSet(OuterBitSize, RHSSB))) { - // The inputs are both zero-extended. - if (HasUMUL_LOHI) { - // We can emit a umul_lohi. - Lo = DAG.getNode(ISD::UMUL_LOHI, DAG.getVTList(NVT, NVT), LL, RL); - Hi = SDOperand(Lo.Val, 1); - return; - } - if (HasMULHU) { - // We can emit a mulhu+mul. - Lo = DAG.getNode(ISD::MUL, NVT, LL, RL); - Hi = DAG.getNode(ISD::MULHU, NVT, LL, RL); - return; - } - } - if (LHSSB > BitSize && RHSSB > BitSize) { - // The input values are both sign-extended. - if (HasSMUL_LOHI) { - // We can emit a smul_lohi. - Lo = DAG.getNode(ISD::SMUL_LOHI, DAG.getVTList(NVT, NVT), LL, RL); - Hi = SDOperand(Lo.Val, 1); - return; - } - if (HasMULHS) { - // We can emit a mulhs+mul. - Lo = DAG.getNode(ISD::MUL, NVT, LL, RL); - Hi = DAG.getNode(ISD::MULHS, NVT, LL, RL); - return; - } - } - if (HasUMUL_LOHI) { - // Lo,Hi = umul LHS, RHS. - SDOperand UMulLOHI = DAG.getNode(ISD::UMUL_LOHI, - DAG.getVTList(NVT, NVT), LL, RL); - Lo = UMulLOHI; - Hi = UMulLOHI.getValue(1); - RH = DAG.getNode(ISD::MUL, NVT, LL, RH); - LH = DAG.getNode(ISD::MUL, NVT, LH, RL); - Hi = DAG.getNode(ISD::ADD, NVT, Hi, RH); - Hi = DAG.getNode(ISD::ADD, NVT, Hi, LH); - return; - } - } - - // If nothing else, we can make a libcall. - SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) }; - SplitInteger(MakeLibCall(RTLIB::MUL_I64, VT, Ops, 2, true/*sign irrelevant*/), - Lo, Hi); -} - -void DAGTypeLegalizer::ExpandResult_SDIV(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - assert(N->getValueType(0) == MVT::i64 && "Unsupported sdiv!"); - SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) }; - SplitInteger(MakeLibCall(RTLIB::SDIV_I64, N->getValueType(0), Ops, 2, true), - Lo, Hi); -} - -void DAGTypeLegalizer::ExpandResult_SREM(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - assert(N->getValueType(0) == MVT::i64 && "Unsupported srem!"); - SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) }; - SplitInteger(MakeLibCall(RTLIB::SREM_I64, N->getValueType(0), Ops, 2, true), - Lo, Hi); -} - -void DAGTypeLegalizer::ExpandResult_UDIV(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - assert(N->getValueType(0) == MVT::i64 && "Unsupported udiv!"); - SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) }; - SplitInteger(MakeLibCall(RTLIB::UDIV_I64, N->getValueType(0), Ops, 2, false), - Lo, Hi); -} - -void DAGTypeLegalizer::ExpandResult_UREM(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - assert(N->getValueType(0) == MVT::i64 && "Unsupported urem!"); - SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) }; - SplitInteger(MakeLibCall(RTLIB::UREM_I64, N->getValueType(0), Ops, 2, false), - Lo, Hi); -} - -void DAGTypeLegalizer::ExpandResult_Shift(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - MVT VT = N->getValueType(0); - - // If we can emit an efficient shift operation, do so now. Check to see if - // the RHS is a constant. - if (ConstantSDNode *CN = dyn_cast(N->getOperand(1))) - return ExpandShiftByConstant(N, CN->getValue(), Lo, Hi); - - // If we can determine that the high bit of the shift is zero or one, even if - // the low bits are variable, emit this shift in an optimized form. - if (ExpandShiftWithKnownAmountBit(N, Lo, Hi)) - return; - - // If this target supports shift_PARTS, use it. First, map to the _PARTS opc. - unsigned PartsOpc; - if (N->getOpcode() == ISD::SHL) { - PartsOpc = ISD::SHL_PARTS; - } else if (N->getOpcode() == ISD::SRL) { - PartsOpc = ISD::SRL_PARTS; - } else { - assert(N->getOpcode() == ISD::SRA && "Unknown shift!"); - PartsOpc = ISD::SRA_PARTS; - } - - // Next check to see if the target supports this SHL_PARTS operation or if it - // will custom expand it. - MVT NVT = TLI.getTypeToTransformTo(VT); - TargetLowering::LegalizeAction Action = TLI.getOperationAction(PartsOpc, NVT); - if ((Action == TargetLowering::Legal && TLI.isTypeLegal(NVT)) || - Action == TargetLowering::Custom) { - // Expand the subcomponents. - SDOperand LHSL, LHSH; - GetExpandedOp(N->getOperand(0), LHSL, LHSH); - - SDOperand Ops[] = { LHSL, LHSH, N->getOperand(1) }; - MVT VT = LHSL.getValueType(); - Lo = DAG.getNode(PartsOpc, DAG.getNodeValueTypes(VT, VT), 2, Ops, 3); - Hi = Lo.getValue(1); - return; - } - - // Otherwise, emit a libcall. - assert(VT == MVT::i64 && "Unsupported shift!"); - - RTLIB::Libcall LC; - bool isSigned; - if (N->getOpcode() == ISD::SHL) { - LC = RTLIB::SHL_I64; - isSigned = false; /*sign irrelevant*/ - } else if (N->getOpcode() == ISD::SRL) { - LC = RTLIB::SRL_I64; - isSigned = false; - } else { - assert(N->getOpcode() == ISD::SRA && "Unknown shift!"); - LC = RTLIB::SRA_I64; - isSigned = true; - } - - SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) }; - SplitInteger(MakeLibCall(LC, VT, Ops, 2, isSigned), Lo, Hi); -} - -void DAGTypeLegalizer::ExpandResult_CTLZ(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - // ctlz (HiLo) -> Hi != 0 ? ctlz(Hi) : (ctlz(Lo)+32) - GetExpandedOp(N->getOperand(0), Lo, Hi); - MVT NVT = Lo.getValueType(); - - SDOperand HiNotZero = DAG.getSetCC(TLI.getSetCCResultType(Hi), Hi, - DAG.getConstant(0, NVT), ISD::SETNE); - - SDOperand LoLZ = DAG.getNode(ISD::CTLZ, NVT, Lo); - SDOperand HiLZ = DAG.getNode(ISD::CTLZ, NVT, Hi); - - Lo = DAG.getNode(ISD::SELECT, NVT, HiNotZero, HiLZ, - DAG.getNode(ISD::ADD, NVT, LoLZ, - DAG.getConstant(NVT.getSizeInBits(), NVT))); - Hi = DAG.getConstant(0, NVT); -} - -void DAGTypeLegalizer::ExpandResult_CTPOP(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - // ctpop(HiLo) -> ctpop(Hi)+ctpop(Lo) - GetExpandedOp(N->getOperand(0), Lo, Hi); - MVT NVT = Lo.getValueType(); - Lo = DAG.getNode(ISD::ADD, NVT, DAG.getNode(ISD::CTPOP, NVT, Lo), - DAG.getNode(ISD::CTPOP, NVT, Hi)); - Hi = DAG.getConstant(0, NVT); -} - -void DAGTypeLegalizer::ExpandResult_CTTZ(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - // cttz (HiLo) -> Lo != 0 ? cttz(Lo) : (cttz(Hi)+32) - GetExpandedOp(N->getOperand(0), Lo, Hi); - MVT NVT = Lo.getValueType(); - - SDOperand LoNotZero = DAG.getSetCC(TLI.getSetCCResultType(Lo), Lo, - DAG.getConstant(0, NVT), ISD::SETNE); - - SDOperand LoLZ = DAG.getNode(ISD::CTTZ, NVT, Lo); - SDOperand HiLZ = DAG.getNode(ISD::CTTZ, NVT, Hi); - - Lo = DAG.getNode(ISD::SELECT, NVT, LoNotZero, LoLZ, - DAG.getNode(ISD::ADD, NVT, HiLZ, - DAG.getConstant(NVT.getSizeInBits(), NVT))); - Hi = DAG.getConstant(0, NVT); -} - -void DAGTypeLegalizer::ExpandResult_EXTRACT_VECTOR_ELT(SDNode *N, - SDOperand &Lo, - SDOperand &Hi) { - SDOperand OldVec = N->getOperand(0); - unsigned OldElts = OldVec.getValueType().getVectorNumElements(); - - // Convert to a vector of the expanded element type, for example - // <2 x i64> -> <4 x i32>. - MVT OldVT = N->getValueType(0); - MVT NewVT = TLI.getTypeToTransformTo(OldVT); - assert(OldVT.getSizeInBits() == 2 * NewVT.getSizeInBits() && - "Do not know how to handle this expansion!"); - - SDOperand NewVec = DAG.getNode(ISD::BIT_CONVERT, - MVT::getVectorVT(NewVT, 2*OldElts), - OldVec); - - // Extract the elements at 2 * Idx and 2 * Idx + 1 from the new vector. - SDOperand Idx = N->getOperand(1); - - // Make sure the type of Idx is big enough to hold the new values. - if (Idx.getValueType().bitsLT(TLI.getPointerTy())) - Idx = DAG.getNode(ISD::ZERO_EXTEND, TLI.getPointerTy(), Idx); - - Idx = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx, Idx); - Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, Idx); - - Idx = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx, - DAG.getConstant(1, Idx.getValueType())); - Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, Idx); - - if (TLI.isBigEndian()) - std::swap(Lo, Hi); -} - -/// ExpandShiftByConstant - N is a shift by a value that needs to be expanded, -/// and the shift amount is a constant 'Amt'. Expand the operation. -void DAGTypeLegalizer::ExpandShiftByConstant(SDNode *N, unsigned Amt, - SDOperand &Lo, SDOperand &Hi) { - // Expand the incoming operand to be shifted, so that we have its parts - SDOperand InL, InH; - GetExpandedOp(N->getOperand(0), InL, InH); - - MVT NVT = InL.getValueType(); - unsigned VTBits = N->getValueType(0).getSizeInBits(); - unsigned NVTBits = NVT.getSizeInBits(); - MVT ShTy = N->getOperand(1).getValueType(); - - if (N->getOpcode() == ISD::SHL) { - if (Amt > VTBits) { - Lo = Hi = DAG.getConstant(0, NVT); - } else if (Amt > NVTBits) { - Lo = DAG.getConstant(0, NVT); - Hi = DAG.getNode(ISD::SHL, NVT, InL, DAG.getConstant(Amt-NVTBits,ShTy)); - } else if (Amt == NVTBits) { - Lo = DAG.getConstant(0, NVT); - Hi = InL; - } else { - Lo = DAG.getNode(ISD::SHL, NVT, InL, DAG.getConstant(Amt, ShTy)); - Hi = DAG.getNode(ISD::OR, NVT, - DAG.getNode(ISD::SHL, NVT, InH, - DAG.getConstant(Amt, ShTy)), - DAG.getNode(ISD::SRL, NVT, InL, - DAG.getConstant(NVTBits-Amt, ShTy))); - } - return; - } - - if (N->getOpcode() == ISD::SRL) { - if (Amt > VTBits) { - Lo = DAG.getConstant(0, NVT); - Hi = DAG.getConstant(0, NVT); - } else if (Amt > NVTBits) { - Lo = DAG.getNode(ISD::SRL, NVT, InH, DAG.getConstant(Amt-NVTBits,ShTy)); - Hi = DAG.getConstant(0, NVT); - } else if (Amt == NVTBits) { - Lo = InH; - Hi = DAG.getConstant(0, NVT); - } else { - Lo = DAG.getNode(ISD::OR, NVT, - DAG.getNode(ISD::SRL, NVT, InL, - DAG.getConstant(Amt, ShTy)), - DAG.getNode(ISD::SHL, NVT, InH, - DAG.getConstant(NVTBits-Amt, ShTy))); - Hi = DAG.getNode(ISD::SRL, NVT, InH, DAG.getConstant(Amt, ShTy)); - } - return; - } - - assert(N->getOpcode() == ISD::SRA && "Unknown shift!"); - if (Amt > VTBits) { - Hi = Lo = DAG.getNode(ISD::SRA, NVT, InH, - DAG.getConstant(NVTBits-1, ShTy)); - } else if (Amt > NVTBits) { - Lo = DAG.getNode(ISD::SRA, NVT, InH, - DAG.getConstant(Amt-NVTBits, ShTy)); - Hi = DAG.getNode(ISD::SRA, NVT, InH, - DAG.getConstant(NVTBits-1, ShTy)); - } else if (Amt == NVTBits) { - Lo = InH; - Hi = DAG.getNode(ISD::SRA, NVT, InH, - DAG.getConstant(NVTBits-1, ShTy)); - } else { - Lo = DAG.getNode(ISD::OR, NVT, - DAG.getNode(ISD::SRL, NVT, InL, - DAG.getConstant(Amt, ShTy)), - DAG.getNode(ISD::SHL, NVT, InH, - DAG.getConstant(NVTBits-Amt, ShTy))); - Hi = DAG.getNode(ISD::SRA, NVT, InH, DAG.getConstant(Amt, ShTy)); - } -} - -/// ExpandShiftWithKnownAmountBit - Try to determine whether we can simplify -/// this shift based on knowledge of the high bit of the shift amount. If we -/// can tell this, we know that it is >= 32 or < 32, without knowing the actual -/// shift amount. -bool DAGTypeLegalizer:: -ExpandShiftWithKnownAmountBit(SDNode *N, SDOperand &Lo, SDOperand &Hi) { - SDOperand Amt = N->getOperand(1); - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - MVT ShTy = Amt.getValueType(); - unsigned ShBits = ShTy.getSizeInBits(); - unsigned NVTBits = NVT.getSizeInBits(); - assert(isPowerOf2_32(NVTBits) && - "Expanded integer type size not a power of two!"); - - APInt HighBitMask = APInt::getHighBitsSet(ShBits, ShBits - Log2_32(NVTBits)); - APInt KnownZero, KnownOne; - DAG.ComputeMaskedBits(N->getOperand(1), HighBitMask, KnownZero, KnownOne); - - // If we don't know anything about the high bits, exit. - if (((KnownZero|KnownOne) & HighBitMask) == 0) - return false; - - // Get the incoming operand to be shifted. - SDOperand InL, InH; - GetExpandedOp(N->getOperand(0), InL, InH); - - // If we know that any of the high bits of the shift amount are one, then we - // can do this as a couple of simple shifts. - if (KnownOne.intersects(HighBitMask)) { - // Mask out the high bit, which we know is set. - Amt = DAG.getNode(ISD::AND, ShTy, Amt, - DAG.getConstant(~HighBitMask, ShTy)); - - switch (N->getOpcode()) { - default: assert(0 && "Unknown shift"); - case ISD::SHL: - Lo = DAG.getConstant(0, NVT); // Low part is zero. - Hi = DAG.getNode(ISD::SHL, NVT, InL, Amt); // High part from Lo part. - return true; - case ISD::SRL: - Hi = DAG.getConstant(0, NVT); // Hi part is zero. - Lo = DAG.getNode(ISD::SRL, NVT, InH, Amt); // Lo part from Hi part. - return true; - case ISD::SRA: - Hi = DAG.getNode(ISD::SRA, NVT, InH, // Sign extend high part. - DAG.getConstant(NVTBits-1, ShTy)); - Lo = DAG.getNode(ISD::SRA, NVT, InH, Amt); // Lo part from Hi part. - return true; - } - } - - // If we know that all of the high bits of the shift amount are zero, then we - // can do this as a couple of simple shifts. - if ((KnownZero & HighBitMask) == HighBitMask) { - // Compute 32-amt. - SDOperand Amt2 = DAG.getNode(ISD::SUB, ShTy, - DAG.getConstant(NVTBits, ShTy), - Amt); - unsigned Op1, Op2; - switch (N->getOpcode()) { - default: assert(0 && "Unknown shift"); - case ISD::SHL: Op1 = ISD::SHL; Op2 = ISD::SRL; break; - case ISD::SRL: - case ISD::SRA: Op1 = ISD::SRL; Op2 = ISD::SHL; break; - } - - Lo = DAG.getNode(N->getOpcode(), NVT, InL, Amt); - Hi = DAG.getNode(ISD::OR, NVT, - DAG.getNode(Op1, NVT, InH, Amt), - DAG.getNode(Op2, NVT, InL, Amt2)); - return true; - } - - return false; -} - - -//===----------------------------------------------------------------------===// -// Operand Expansion -//===----------------------------------------------------------------------===// - -/// ExpandOperand - This method is called when the specified operand of the -/// specified node is found to need expansion. At this point, all of the result -/// types of the node are known to be legal, but other operands of the node may -/// need promotion or expansion as well as the specified one. -bool DAGTypeLegalizer::ExpandOperand(SDNode *N, unsigned OpNo) { - DEBUG(cerr << "Expand node operand: "; N->dump(&DAG); cerr << "\n"); - SDOperand Res(0, 0); - - if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType()) - == TargetLowering::Custom) - Res = TLI.LowerOperation(SDOperand(N, 0), DAG); - - if (Res.Val == 0) { - switch (N->getOpcode()) { - default: - #ifndef NDEBUG - cerr << "ExpandOperand Op #" << OpNo << ": "; - N->dump(&DAG); cerr << "\n"; - #endif - assert(0 && "Do not know how to expand this operator's operand!"); - abort(); - - case ISD::TRUNCATE: Res = ExpandOperand_TRUNCATE(N); break; - case ISD::BIT_CONVERT: Res = ExpandOperand_BIT_CONVERT(N); break; - - case ISD::SINT_TO_FP: - Res = ExpandOperand_SINT_TO_FP(N->getOperand(0), N->getValueType(0)); - break; - case ISD::UINT_TO_FP: - Res = ExpandOperand_UINT_TO_FP(N->getOperand(0), N->getValueType(0)); - break; - case ISD::EXTRACT_ELEMENT: Res = ExpandOperand_EXTRACT_ELEMENT(N); break; - - case ISD::BR_CC: Res = ExpandOperand_BR_CC(N); break; - case ISD::SETCC: Res = ExpandOperand_SETCC(N); break; - - case ISD::STORE: - Res = ExpandOperand_STORE(cast(N), OpNo); - break; - - case ISD::BUILD_VECTOR: Res = ExpandOperand_BUILD_VECTOR(N); break; - } - } - - // If the result is null, the sub-method took care of registering results etc. - if (!Res.Val) return false; - // If the result is N, the sub-method updated N in place. Check to see if any - // operands are new, and if so, mark them. - if (Res.Val == N) { - // Mark N as new and remark N and its operands. This allows us to correctly - // revisit N if it needs another step of promotion and allows us to visit - // any new operands to N. - ReanalyzeNode(N); - return true; - } - - assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && - "Invalid operand expansion"); - - ReplaceValueWith(SDOperand(N, 0), Res); - return false; -} - -SDOperand DAGTypeLegalizer::ExpandOperand_TRUNCATE(SDNode *N) { - SDOperand InL, InH; - GetExpandedOp(N->getOperand(0), InL, InH); - // Just truncate the low part of the source. - return DAG.getNode(ISD::TRUNCATE, N->getValueType(0), InL); -} - -SDOperand DAGTypeLegalizer::ExpandOperand_BIT_CONVERT(SDNode *N) { - if (N->getValueType(0).isVector()) { - // An illegal integer type is being converted to a legal vector type. - // Make a two element vector out of the expanded parts and convert that - // instead, but only if the new vector type is legal (otherwise there - // is no point, and it might create expansion loops). For example, on - // x86 this turns v1i64 = BIT_CONVERT i64 into v1i64 = BIT_CONVERT v2i32. - MVT OVT = N->getOperand(0).getValueType(); - MVT NVT = MVT::getVectorVT(TLI.getTypeToTransformTo(OVT), 2); - - if (isTypeLegal(NVT)) { - SDOperand Parts[2]; - GetExpandedOp(N->getOperand(0), Parts[0], Parts[1]); - - if (TLI.isBigEndian()) - std::swap(Parts[0], Parts[1]); - - SDOperand Vec = DAG.getNode(ISD::BUILD_VECTOR, NVT, Parts, 2); - return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Vec); - } - } - - // Otherwise, store to a temporary and load out again as the new type. - return CreateStackStoreLoad(N->getOperand(0), N->getValueType(0)); -} - -SDOperand DAGTypeLegalizer::ExpandOperand_SINT_TO_FP(SDOperand Source, - MVT DestTy) { - // We know the destination is legal, but that the input needs to be expanded. - MVT SourceVT = Source.getValueType(); - - // Check to see if the target has a custom way to lower this. If so, use it. - switch (TLI.getOperationAction(ISD::SINT_TO_FP, SourceVT)) { - default: assert(0 && "This action not implemented for this operation!"); - case TargetLowering::Legal: - case TargetLowering::Expand: - break; // This case is handled below. - case TargetLowering::Custom: - SDOperand NV = TLI.LowerOperation(DAG.getNode(ISD::SINT_TO_FP, DestTy, - Source), DAG); - if (NV.Val) return NV; - break; // The target lowered this. - } - - RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; - if (SourceVT == MVT::i64) { - if (DestTy == MVT::f32) - LC = RTLIB::SINTTOFP_I64_F32; - else { - assert(DestTy == MVT::f64 && "Unknown fp value type!"); - LC = RTLIB::SINTTOFP_I64_F64; - } - } else if (SourceVT == MVT::i128) { - if (DestTy == MVT::f32) - LC = RTLIB::SINTTOFP_I128_F32; - else if (DestTy == MVT::f64) - LC = RTLIB::SINTTOFP_I128_F64; - else if (DestTy == MVT::f80) - LC = RTLIB::SINTTOFP_I128_F80; - else { - assert(DestTy == MVT::ppcf128 && "Unknown fp value type!"); - LC = RTLIB::SINTTOFP_I128_PPCF128; - } - } else { - assert(0 && "Unknown int value type!"); - } - - assert(LC != RTLIB::UNKNOWN_LIBCALL && - "Don't know how to expand this SINT_TO_FP!"); - return MakeLibCall(LC, DestTy, &Source, 1, true); -} - -SDOperand DAGTypeLegalizer::ExpandOperand_UINT_TO_FP(SDOperand Source, - MVT DestTy) { - // We know the destination is legal, but that the input needs to be expanded. - assert(getTypeAction(Source.getValueType()) == Expand && - "This is not an expansion!"); - - // If this is unsigned, and not supported, first perform the conversion to - // signed, then adjust the result if the sign bit is set. - SDOperand SignedConv = ExpandOperand_SINT_TO_FP(Source, DestTy); - - // The 64-bit value loaded will be incorrectly if the 'sign bit' of the - // incoming integer is set. To handle this, we dynamically test to see if - // it is set, and, if so, add a fudge factor. - SDOperand Lo, Hi; - GetExpandedOp(Source, Lo, Hi); - - SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultType(Hi), Hi, - DAG.getConstant(0, Hi.getValueType()), - ISD::SETLT); - SDOperand Zero = DAG.getIntPtrConstant(0), Four = DAG.getIntPtrConstant(4); - SDOperand CstOffset = DAG.getNode(ISD::SELECT, Zero.getValueType(), - SignSet, Four, Zero); - uint64_t FF = 0x5f800000ULL; - if (TLI.isLittleEndian()) FF <<= 32; - Constant *FudgeFactor = ConstantInt::get((Type*)Type::Int64Ty, FF); - - SDOperand CPIdx = DAG.getConstantPool(FudgeFactor, TLI.getPointerTy()); - CPIdx = DAG.getNode(ISD::ADD, TLI.getPointerTy(), CPIdx, CstOffset); - SDOperand FudgeInReg; - if (DestTy == MVT::f32) - FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx, NULL, 0); - else if (DestTy.bitsGT(MVT::f32)) - // FIXME: Avoid the extend by construction the right constantpool? - FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, DestTy, DAG.getEntryNode(), - CPIdx, NULL, 0, MVT::f32); - else - assert(0 && "Unexpected conversion"); - - return DAG.getNode(ISD::FADD, DestTy, SignedConv, FudgeInReg); -} - -SDOperand DAGTypeLegalizer::ExpandOperand_EXTRACT_ELEMENT(SDNode *N) { - SDOperand Lo, Hi; - GetExpandedOp(N->getOperand(0), Lo, Hi); - return cast(N->getOperand(1))->getValue() ? Hi : Lo; -} - -SDOperand DAGTypeLegalizer::ExpandOperand_BR_CC(SDNode *N) { - SDOperand NewLHS = N->getOperand(2), NewRHS = N->getOperand(3); - ISD::CondCode CCCode = cast(N->getOperand(1))->get(); - ExpandSetCCOperands(NewLHS, NewRHS, CCCode); - - // If ExpandSetCCOperands returned a scalar, we need to compare the result - // against zero to select between true and false values. - if (NewRHS.Val == 0) { - NewRHS = DAG.getConstant(0, NewLHS.getValueType()); - CCCode = ISD::SETNE; - } - - // Update N to have the operands specified. - return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), - DAG.getCondCode(CCCode), NewLHS, NewRHS, - N->getOperand(4)); -} - -SDOperand DAGTypeLegalizer::ExpandOperand_SETCC(SDNode *N) { - SDOperand NewLHS = N->getOperand(0), NewRHS = N->getOperand(1); - ISD::CondCode CCCode = cast(N->getOperand(2))->get(); - ExpandSetCCOperands(NewLHS, NewRHS, CCCode); - - // If ExpandSetCCOperands returned a scalar, use it. - if (NewRHS.Val == 0) return NewLHS; - - // Otherwise, update N to have the operands specified. - return DAG.UpdateNodeOperands(SDOperand(N, 0), NewLHS, NewRHS, - DAG.getCondCode(CCCode)); -} - -/// ExpandSetCCOperands - Expand the operands of a comparison. This code is -/// shared among BR_CC, SELECT_CC, and SETCC handlers. -void DAGTypeLegalizer::ExpandSetCCOperands(SDOperand &NewLHS, SDOperand &NewRHS, - ISD::CondCode &CCCode) { - SDOperand LHSLo, LHSHi, RHSLo, RHSHi; - GetExpandedOp(NewLHS, LHSLo, LHSHi); - GetExpandedOp(NewRHS, RHSLo, RHSHi); - - MVT VT = NewLHS.getValueType(); - if (VT == MVT::ppcf128) { - // FIXME: This generated code sucks. We want to generate - // FCMP crN, hi1, hi2 - // BNE crN, L: - // FCMP crN, lo1, lo2 - // The following can be improved, but not that much. - SDOperand Tmp1, Tmp2, Tmp3; - Tmp1 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, ISD::SETEQ); - Tmp2 = DAG.getSetCC(TLI.getSetCCResultType(LHSLo), LHSLo, RHSLo, CCCode); - Tmp3 = DAG.getNode(ISD::AND, Tmp1.getValueType(), Tmp1, Tmp2); - Tmp1 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, ISD::SETNE); - Tmp2 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, CCCode); - Tmp1 = DAG.getNode(ISD::AND, Tmp1.getValueType(), Tmp1, Tmp2); - NewLHS = DAG.getNode(ISD::OR, Tmp1.getValueType(), Tmp1, Tmp3); - NewRHS = SDOperand(); // LHS is the result, not a compare. - return; - } - - if (CCCode == ISD::SETEQ || CCCode == ISD::SETNE) { - if (RHSLo == RHSHi) - if (ConstantSDNode *RHSCST = dyn_cast(RHSLo)) - if (RHSCST->isAllOnesValue()) { - // Equality comparison to -1. - NewLHS = DAG.getNode(ISD::AND, LHSLo.getValueType(), LHSLo, LHSHi); - NewRHS = RHSLo; - return; - } - - NewLHS = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSLo, RHSLo); - NewRHS = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSHi, RHSHi); - NewLHS = DAG.getNode(ISD::OR, NewLHS.getValueType(), NewLHS, NewRHS); - NewRHS = DAG.getConstant(0, NewLHS.getValueType()); - return; - } - - // If this is a comparison of the sign bit, just look at the top part. - // X > -1, x < 0 - if (ConstantSDNode *CST = dyn_cast(NewRHS)) - if ((CCCode == ISD::SETLT && CST->isNullValue()) || // X < 0 - (CCCode == ISD::SETGT && CST->isAllOnesValue())) { // X > -1 - NewLHS = LHSHi; - NewRHS = RHSHi; - return; - } - - // FIXME: This generated code sucks. - ISD::CondCode LowCC; - switch (CCCode) { - default: assert(0 && "Unknown integer setcc!"); - case ISD::SETLT: - case ISD::SETULT: LowCC = ISD::SETULT; break; - case ISD::SETGT: - case ISD::SETUGT: LowCC = ISD::SETUGT; break; - case ISD::SETLE: - case ISD::SETULE: LowCC = ISD::SETULE; break; - case ISD::SETGE: - case ISD::SETUGE: LowCC = ISD::SETUGE; break; - } - - // Tmp1 = lo(op1) < lo(op2) // Always unsigned comparison - // Tmp2 = hi(op1) < hi(op2) // Signedness depends on operands - // dest = hi(op1) == hi(op2) ? Tmp1 : Tmp2; - - // NOTE: on targets without efficient SELECT of bools, we can always use - // this identity: (B1 ? B2 : B3) --> (B1 & B2)|(!B1&B3) - TargetLowering::DAGCombinerInfo DagCombineInfo(DAG, false, true, NULL); - SDOperand Tmp1, Tmp2; - Tmp1 = TLI.SimplifySetCC(TLI.getSetCCResultType(LHSLo), LHSLo, RHSLo, LowCC, - false, DagCombineInfo); - if (!Tmp1.Val) - Tmp1 = DAG.getSetCC(TLI.getSetCCResultType(LHSLo), LHSLo, RHSLo, LowCC); - Tmp2 = TLI.SimplifySetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, - CCCode, false, DagCombineInfo); - if (!Tmp2.Val) - Tmp2 = DAG.getNode(ISD::SETCC, TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, - DAG.getCondCode(CCCode)); - - ConstantSDNode *Tmp1C = dyn_cast(Tmp1.Val); - ConstantSDNode *Tmp2C = dyn_cast(Tmp2.Val); - if ((Tmp1C && Tmp1C->isNullValue()) || - (Tmp2C && Tmp2C->isNullValue() && - (CCCode == ISD::SETLE || CCCode == ISD::SETGE || - CCCode == ISD::SETUGE || CCCode == ISD::SETULE)) || - (Tmp2C && Tmp2C->getAPIntValue() == 1 && - (CCCode == ISD::SETLT || CCCode == ISD::SETGT || - CCCode == ISD::SETUGT || CCCode == ISD::SETULT))) { - // low part is known false, returns high part. - // For LE / GE, if high part is known false, ignore the low part. - // For LT / GT, if high part is known true, ignore the low part. - NewLHS = Tmp2; - NewRHS = SDOperand(); - return; - } - - NewLHS = TLI.SimplifySetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, - ISD::SETEQ, false, DagCombineInfo); - if (!NewLHS.Val) - NewLHS = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, - ISD::SETEQ); - NewLHS = DAG.getNode(ISD::SELECT, Tmp1.getValueType(), - NewLHS, Tmp1, Tmp2); - NewRHS = SDOperand(); -} - -SDOperand DAGTypeLegalizer::ExpandOperand_STORE(StoreSDNode *N, unsigned OpNo) { - // FIXME: Add support for indexed stores. - assert(OpNo == 1 && "Can only expand the stored value so far"); - - MVT VT = N->getOperand(1).getValueType(); - MVT NVT = TLI.getTypeToTransformTo(VT); - SDOperand Ch = N->getChain(); - SDOperand Ptr = N->getBasePtr(); - int SVOffset = N->getSrcValueOffset(); - unsigned Alignment = N->getAlignment(); - bool isVolatile = N->isVolatile(); - SDOperand Lo, Hi; - - assert(!(NVT.getSizeInBits() & 7) && "Expanded type not byte sized!"); - - if (!N->isTruncatingStore()) { - unsigned IncrementSize = 0; - GetExpandedOp(N->getValue(), Lo, Hi); - IncrementSize = Hi.getValueType().getSizeInBits()/8; - - if (TLI.isBigEndian()) - std::swap(Lo, Hi); - - Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(), - SVOffset, isVolatile, Alignment); - - Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, - DAG.getIntPtrConstant(IncrementSize)); - assert(isTypeLegal(Ptr.getValueType()) && "Pointers must be legal!"); - Hi = DAG.getStore(Ch, Hi, Ptr, N->getSrcValue(), SVOffset+IncrementSize, - isVolatile, MinAlign(Alignment, IncrementSize)); - return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi); - } else if (N->getMemoryVT().bitsLE(NVT)) { - GetExpandedOp(N->getValue(), Lo, Hi); - return DAG.getTruncStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset, - N->getMemoryVT(), isVolatile, Alignment); - } else if (TLI.isLittleEndian()) { - // Little-endian - low bits are at low addresses. - GetExpandedOp(N->getValue(), Lo, Hi); - - Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset, - isVolatile, Alignment); - - unsigned ExcessBits = - N->getMemoryVT().getSizeInBits() - NVT.getSizeInBits(); - MVT NEVT = MVT::getIntegerVT(ExcessBits); - - // Increment the pointer to the other half. - unsigned IncrementSize = NVT.getSizeInBits()/8; - Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, - DAG.getIntPtrConstant(IncrementSize)); - Hi = DAG.getTruncStore(Ch, Hi, Ptr, N->getSrcValue(), - SVOffset+IncrementSize, NEVT, - isVolatile, MinAlign(Alignment, IncrementSize)); - return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi); - } else { - // Big-endian - high bits are at low addresses. Favor aligned stores at - // the cost of some bit-fiddling. - GetExpandedOp(N->getValue(), Lo, Hi); - - MVT EVT = N->getMemoryVT(); - unsigned EBytes = EVT.getStoreSizeInBits()/8; - unsigned IncrementSize = NVT.getSizeInBits()/8; - unsigned ExcessBits = (EBytes - IncrementSize)*8; - MVT HiVT = MVT::getIntegerVT(EVT.getSizeInBits() - ExcessBits); - - if (ExcessBits < NVT.getSizeInBits()) { - // Transfer high bits from the top of Lo to the bottom of Hi. - Hi = DAG.getNode(ISD::SHL, NVT, Hi, - DAG.getConstant(NVT.getSizeInBits() - ExcessBits, - TLI.getShiftAmountTy())); - Hi = DAG.getNode(ISD::OR, NVT, Hi, - DAG.getNode(ISD::SRL, NVT, Lo, - DAG.getConstant(ExcessBits, - TLI.getShiftAmountTy()))); - } - - // Store both the high bits and maybe some of the low bits. - Hi = DAG.getTruncStore(Ch, Hi, Ptr, N->getSrcValue(), - SVOffset, HiVT, isVolatile, Alignment); - - // Increment the pointer to the other half. - Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, - DAG.getIntPtrConstant(IncrementSize)); - // Store the lowest ExcessBits bits in the second half. - Lo = DAG.getTruncStore(Ch, Lo, Ptr, N->getSrcValue(), - SVOffset+IncrementSize, - MVT::getIntegerVT(ExcessBits), - isVolatile, MinAlign(Alignment, IncrementSize)); - return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi); - } -} - -SDOperand DAGTypeLegalizer::ExpandOperand_BUILD_VECTOR(SDNode *N) { - // The vector type is legal but the element type needs expansion. - MVT VecVT = N->getValueType(0); - unsigned NumElts = VecVT.getVectorNumElements(); - MVT OldVT = N->getOperand(0).getValueType(); - MVT NewVT = TLI.getTypeToTransformTo(OldVT); - - assert(OldVT.getSizeInBits() == 2 * NewVT.getSizeInBits() && - "Do not know how to expand this operand!"); - - // Build a vector of twice the length out of the expanded elements. - // For example <2 x i64> -> <4 x i32>. - std::vector NewElts; - NewElts.reserve(NumElts*2); - - for (unsigned i = 0; i < NumElts; ++i) { - SDOperand Lo, Hi; - GetExpandedOp(N->getOperand(i), Lo, Hi); - if (TLI.isBigEndian()) - std::swap(Lo, Hi); - NewElts.push_back(Lo); - NewElts.push_back(Hi); - } - - SDOperand NewVec = DAG.getNode(ISD::BUILD_VECTOR, - MVT::getVectorVT(NewVT, NewElts.size()), - &NewElts[0], NewElts.size()); - - // Convert the new vector to the old vector type. - return DAG.getNode(ISD::BIT_CONVERT, VecVT, NewVec); -} Removed: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesFloatToInt.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesFloatToInt.cpp?rev=52407&view=auto ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesFloatToInt.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesFloatToInt.cpp (removed) @@ -1,357 +0,0 @@ -//===-- LegalizeTypesFloatToInt.cpp - LegalizeTypes float to int support --===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements float to integer conversion for LegalizeTypes. This -// is the act of turning a computation in an invalid floating point type into -// a computation in an integer type of the same size. For example, turning -// f32 arithmetic into operations using i32. Also known as "soft float". -// The result is equivalent to bitcasting the float value to the integer type. -// -//===----------------------------------------------------------------------===// - -#include "llvm/CodeGen/PseudoSourceValue.h" -#include "llvm/DerivedTypes.h" -#include "LegalizeTypes.h" -using namespace llvm; - -/// GetFPLibCall - Return the right libcall for the given floating point type. -static RTLIB::Libcall GetFPLibCall(MVT VT, - RTLIB::Libcall Call_F32, - RTLIB::Libcall Call_F64, - RTLIB::Libcall Call_F80, - RTLIB::Libcall Call_PPCF128) { - return - VT == MVT::f32 ? Call_F32 : - VT == MVT::f64 ? Call_F64 : - VT == MVT::f80 ? Call_F80 : - VT == MVT::ppcf128 ? Call_PPCF128 : - RTLIB::UNKNOWN_LIBCALL; -} - -//===----------------------------------------------------------------------===// -// Result Float to Integer Conversion. -//===----------------------------------------------------------------------===// - -void DAGTypeLegalizer::FloatToIntResult(SDNode *N, unsigned ResNo) { - DEBUG(cerr << "FloatToInt node result " << ResNo << ": "; N->dump(&DAG); - cerr << "\n"); - SDOperand R = SDOperand(); - - // FIXME: Custom lowering for float-to-int? -#if 0 - // See if the target wants to custom convert this node to an integer. - if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == - TargetLowering::Custom) { - // If the target wants to, allow it to lower this itself. - if (SDNode *P = TLI.FloatToIntOperationResult(N, DAG)) { - // Everything that once used N now uses P. We are guaranteed that the - // result value types of N and the result value types of P match. - ReplaceNodeWith(N, P); - return; - } - } -#endif - - switch (N->getOpcode()) { - default: -#ifndef NDEBUG - cerr << "FloatToIntResult #" << ResNo << ": "; - N->dump(&DAG); cerr << "\n"; -#endif - assert(0 && "Do not know how to convert the result of this operator!"); - abort(); - - case ISD::BIT_CONVERT: R = FloatToIntRes_BIT_CONVERT(N); break; - case ISD::BUILD_PAIR: R = FloatToIntRes_BUILD_PAIR(N); break; - case ISD::ConstantFP: - R = FloatToIntRes_ConstantFP(cast(N)); - break; - case ISD::FCOPYSIGN: R = FloatToIntRes_FCOPYSIGN(N); break; - case ISD::LOAD: R = FloatToIntRes_LOAD(N); break; - case ISD::SINT_TO_FP: - case ISD::UINT_TO_FP: R = FloatToIntRes_XINT_TO_FP(N); break; - - case ISD::FADD: R = FloatToIntRes_FADD(N); break; - case ISD::FMUL: R = FloatToIntRes_FMUL(N); break; - case ISD::FSUB: R = FloatToIntRes_FSUB(N); break; - } - - // If R is null, the sub-method took care of registering the result. - if (R.Val) - SetIntegerOp(SDOperand(N, ResNo), R); -} - -SDOperand DAGTypeLegalizer::FloatToIntRes_BIT_CONVERT(SDNode *N) { - return BitConvertToInteger(N->getOperand(0)); -} - -SDOperand DAGTypeLegalizer::FloatToIntRes_BUILD_PAIR(SDNode *N) { - // Convert the inputs to integers, and build a new pair out of them. - return DAG.getNode(ISD::BUILD_PAIR, - TLI.getTypeToTransformTo(N->getValueType(0)), - BitConvertToInteger(N->getOperand(0)), - BitConvertToInteger(N->getOperand(1))); -} - -SDOperand DAGTypeLegalizer::FloatToIntRes_ConstantFP(ConstantFPSDNode *N) { - return DAG.getConstant(N->getValueAPF().convertToAPInt(), - TLI.getTypeToTransformTo(N->getValueType(0))); -} - -SDOperand DAGTypeLegalizer::FloatToIntRes_FADD(SDNode *N) { - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - SDOperand Ops[2] = { GetIntegerOp(N->getOperand(0)), - GetIntegerOp(N->getOperand(1)) }; - return MakeLibCall(GetFPLibCall(N->getValueType(0), - RTLIB::ADD_F32, - RTLIB::ADD_F64, - RTLIB::ADD_F80, - RTLIB::ADD_PPCF128), - NVT, Ops, 2, false/*sign irrelevant*/); -} - -SDOperand DAGTypeLegalizer::FloatToIntRes_FCOPYSIGN(SDNode *N) { - SDOperand LHS = GetIntegerOp(N->getOperand(0)); - SDOperand RHS = BitConvertToInteger(N->getOperand(1)); - - MVT LVT = LHS.getValueType(); - MVT RVT = RHS.getValueType(); - - unsigned LSize = LVT.getSizeInBits(); - unsigned RSize = RVT.getSizeInBits(); - - // First get the sign bit of second operand. - SDOperand SignBit = DAG.getNode(ISD::SHL, RVT, DAG.getConstant(1, RVT), - DAG.getConstant(RSize - 1, - TLI.getShiftAmountTy())); - SignBit = DAG.getNode(ISD::AND, RVT, RHS, SignBit); - - // Shift right or sign-extend it if the two operands have different types. - int SizeDiff = RVT.getSizeInBits() - LVT.getSizeInBits(); - if (SizeDiff > 0) { - SignBit = DAG.getNode(ISD::SRL, RVT, SignBit, - DAG.getConstant(SizeDiff, TLI.getShiftAmountTy())); - SignBit = DAG.getNode(ISD::TRUNCATE, LVT, SignBit); - } else if (SizeDiff < 0) { - SignBit = DAG.getNode(ISD::ANY_EXTEND, LVT, SignBit); - SignBit = DAG.getNode(ISD::SHL, LVT, SignBit, - DAG.getConstant(-SizeDiff, TLI.getShiftAmountTy())); - } - - // Clear the sign bit of the first operand. - SDOperand Mask = DAG.getNode(ISD::SHL, LVT, DAG.getConstant(1, LVT), - DAG.getConstant(LSize - 1, - TLI.getShiftAmountTy())); - Mask = DAG.getNode(ISD::SUB, LVT, Mask, DAG.getConstant(1, LVT)); - LHS = DAG.getNode(ISD::AND, LVT, LHS, Mask); - - // Or the value with the sign bit. - return DAG.getNode(ISD::OR, LVT, LHS, SignBit); -} - -SDOperand DAGTypeLegalizer::FloatToIntRes_FMUL(SDNode *N) { - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - SDOperand Ops[2] = { GetIntegerOp(N->getOperand(0)), - GetIntegerOp(N->getOperand(1)) }; - return MakeLibCall(GetFPLibCall(N->getValueType(0), - RTLIB::MUL_F32, - RTLIB::MUL_F64, - RTLIB::MUL_F80, - RTLIB::MUL_PPCF128), - NVT, Ops, 2, false/*sign irrelevant*/); -} - -SDOperand DAGTypeLegalizer::FloatToIntRes_FSUB(SDNode *N) { - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - SDOperand Ops[2] = { GetIntegerOp(N->getOperand(0)), - GetIntegerOp(N->getOperand(1)) }; - return MakeLibCall(GetFPLibCall(N->getValueType(0), - RTLIB::SUB_F32, - RTLIB::SUB_F64, - RTLIB::SUB_F80, - RTLIB::SUB_PPCF128), - NVT, Ops, 2, false/*sign irrelevant*/); -} - -SDOperand DAGTypeLegalizer::FloatToIntRes_LOAD(SDNode *N) { - LoadSDNode *L = cast(N); - MVT VT = N->getValueType(0); - MVT NVT = TLI.getTypeToTransformTo(VT); - - if (L->getExtensionType() == ISD::NON_EXTLOAD) - return DAG.getLoad(L->getAddressingMode(), L->getExtensionType(), - NVT, L->getChain(), L->getBasePtr(), L->getOffset(), - L->getSrcValue(), L->getSrcValueOffset(), NVT, - L->isVolatile(), L->getAlignment()); - - // Do a non-extending load followed by FP_EXTEND. - SDOperand NL = DAG.getLoad(L->getAddressingMode(), ISD::NON_EXTLOAD, - L->getMemoryVT(), L->getChain(), - L->getBasePtr(), L->getOffset(), - L->getSrcValue(), L->getSrcValueOffset(), - L->getMemoryVT(), - L->isVolatile(), L->getAlignment()); - return BitConvertToInteger(DAG.getNode(ISD::FP_EXTEND, VT, NL)); -} - -SDOperand DAGTypeLegalizer::FloatToIntRes_XINT_TO_FP(SDNode *N) { - bool isSigned = N->getOpcode() == ISD::SINT_TO_FP; - MVT DestVT = N->getValueType(0); - SDOperand Op = N->getOperand(0); - - if (Op.getValueType() == MVT::i32) { - // simple 32-bit [signed|unsigned] integer to float/double expansion - - // Get the stack frame index of a 8 byte buffer. - SDOperand StackSlot = DAG.CreateStackTemporary(MVT::f64); - - // word offset constant for Hi/Lo address computation - SDOperand Offset = - DAG.getConstant(MVT(MVT::i32).getSizeInBits() / 8, - TLI.getPointerTy()); - // set up Hi and Lo (into buffer) address based on endian - SDOperand Hi = StackSlot; - SDOperand Lo = DAG.getNode(ISD::ADD, TLI.getPointerTy(), StackSlot, Offset); - if (TLI.isLittleEndian()) - std::swap(Hi, Lo); - - // if signed map to unsigned space - SDOperand OpMapped; - if (isSigned) { - // constant used to invert sign bit (signed to unsigned mapping) - SDOperand SignBit = DAG.getConstant(0x80000000u, MVT::i32); - OpMapped = DAG.getNode(ISD::XOR, MVT::i32, Op, SignBit); - } else { - OpMapped = Op; - } - // store the lo of the constructed double - based on integer input - SDOperand Store1 = DAG.getStore(DAG.getEntryNode(), - OpMapped, Lo, NULL, 0); - // initial hi portion of constructed double - SDOperand InitialHi = DAG.getConstant(0x43300000u, MVT::i32); - // store the hi of the constructed double - biased exponent - SDOperand Store2=DAG.getStore(Store1, InitialHi, Hi, NULL, 0); - // load the constructed double - SDOperand Load = DAG.getLoad(MVT::f64, Store2, StackSlot, NULL, 0); - // FP constant to bias correct the final result - SDOperand Bias = DAG.getConstantFP(isSigned ? - BitsToDouble(0x4330000080000000ULL) - : BitsToDouble(0x4330000000000000ULL), - MVT::f64); - // subtract the bias - SDOperand Sub = DAG.getNode(ISD::FSUB, MVT::f64, Load, Bias); - // final result - SDOperand Result; - // handle final rounding - if (DestVT == MVT::f64) { - // do nothing - Result = Sub; - } else if (DestVT.bitsLT(MVT::f64)) { - Result = DAG.getNode(ISD::FP_ROUND, DestVT, Sub, - DAG.getIntPtrConstant(0)); - } else if (DestVT.bitsGT(MVT::f64)) { - Result = DAG.getNode(ISD::FP_EXTEND, DestVT, Sub); - } - return BitConvertToInteger(Result); - } - assert(!isSigned && "Legalize cannot Expand SINT_TO_FP for i64 yet"); - SDOperand Tmp1 = DAG.getNode(ISD::SINT_TO_FP, DestVT, Op); - - SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultType(Op), Op, - DAG.getConstant(0, Op.getValueType()), - ISD::SETLT); - SDOperand Zero = DAG.getIntPtrConstant(0), Four = DAG.getIntPtrConstant(4); - SDOperand CstOffset = DAG.getNode(ISD::SELECT, Zero.getValueType(), - SignSet, Four, Zero); - - // If the sign bit of the integer is set, the large number will be treated - // as a negative number. To counteract this, the dynamic code adds an - // offset depending on the data type. - uint64_t FF; - switch (Op.getValueType().getSimpleVT()) { - default: assert(0 && "Unsupported integer type!"); - case MVT::i8 : FF = 0x43800000ULL; break; // 2^8 (as a float) - case MVT::i16: FF = 0x47800000ULL; break; // 2^16 (as a float) - case MVT::i32: FF = 0x4F800000ULL; break; // 2^32 (as a float) - case MVT::i64: FF = 0x5F800000ULL; break; // 2^64 (as a float) - } - if (TLI.isLittleEndian()) FF <<= 32; - static Constant *FudgeFactor = ConstantInt::get(Type::Int64Ty, FF); - - SDOperand CPIdx = DAG.getConstantPool(FudgeFactor, TLI.getPointerTy()); - CPIdx = DAG.getNode(ISD::ADD, TLI.getPointerTy(), CPIdx, CstOffset); - SDOperand FudgeInReg; - if (DestVT == MVT::f32) - FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx, - PseudoSourceValue::getConstantPool(), 0); - else { - FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, DestVT, - DAG.getEntryNode(), CPIdx, - PseudoSourceValue::getConstantPool(), 0, - MVT::f32); - } - - return BitConvertToInteger(DAG.getNode(ISD::FADD, DestVT, Tmp1, FudgeInReg)); -} - - -//===----------------------------------------------------------------------===// -// Operand Float to Integer Conversion.. -//===----------------------------------------------------------------------===// - -bool DAGTypeLegalizer::FloatToIntOperand(SDNode *N, unsigned OpNo) { - DEBUG(cerr << "FloatToInt node operand " << OpNo << ": "; N->dump(&DAG); - cerr << "\n"); - SDOperand Res(0, 0); - - // FIXME: Custom lowering for float-to-int? -#if 0 - if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType()) - == TargetLowering::Custom) - Res = TLI.LowerOperation(SDOperand(N, 0), DAG); -#endif - - if (Res.Val == 0) { - switch (N->getOpcode()) { - default: -#ifndef NDEBUG - cerr << "FloatToIntOperand Op #" << OpNo << ": "; - N->dump(&DAG); cerr << "\n"; -#endif - assert(0 && "Do not know how to convert this operator's operand!"); - abort(); - - case ISD::BIT_CONVERT: Res = FloatToIntOp_BIT_CONVERT(N); break; - } - } - - // If the result is null, the sub-method took care of registering results etc. - if (!Res.Val) return false; - - // If the result is N, the sub-method updated N in place. Check to see if any - // operands are new, and if so, mark them. - if (Res.Val == N) { - // Mark N as new and remark N and its operands. This allows us to correctly - // revisit N if it needs another step of promotion and allows us to visit - // any new operands to N. - ReanalyzeNode(N); - return true; - } - - assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && - "Invalid operand expansion"); - - ReplaceValueWith(SDOperand(N, 0), Res); - return false; -} - -SDOperand DAGTypeLegalizer::FloatToIntOp_BIT_CONVERT(SDNode *N) { - return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), - GetIntegerOp(N->getOperand(0))); -} Removed: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp?rev=52407&view=auto ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp (removed) @@ -1,748 +0,0 @@ -//===-- LegalizeTypesPromote.cpp - Promotion for LegalizeTypes ------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements promotion support for LegalizeTypes. Promotion is the -// act of changing a computation in an invalid type to be a computation in a -// larger type. For example, implementing i8 arithmetic in an i32 register (as -// is often needed on powerpc for example). -// -//===----------------------------------------------------------------------===// - -#include "LegalizeTypes.h" -using namespace llvm; - -//===----------------------------------------------------------------------===// -// Result Promotion -//===----------------------------------------------------------------------===// - -/// PromoteResult - This method is called when a result of a node is found to be -/// in need of promotion to a larger type. At this point, the node may also -/// have invalid operands or may have other results that need expansion, we just -/// know that (at least) one result needs promotion. -void DAGTypeLegalizer::PromoteResult(SDNode *N, unsigned ResNo) { - DEBUG(cerr << "Promote node result: "; N->dump(&DAG); cerr << "\n"); - SDOperand Result = SDOperand(); - - switch (N->getOpcode()) { - default: -#ifndef NDEBUG - cerr << "PromoteResult #" << ResNo << ": "; - N->dump(&DAG); cerr << "\n"; -#endif - assert(0 && "Do not know how to promote this operator!"); - abort(); - case ISD::UNDEF: Result = PromoteResult_UNDEF(N); break; - case ISD::Constant: Result = PromoteResult_Constant(N); break; - - case ISD::TRUNCATE: Result = PromoteResult_TRUNCATE(N); break; - case ISD::SIGN_EXTEND: - case ISD::ZERO_EXTEND: - case ISD::ANY_EXTEND: Result = PromoteResult_INT_EXTEND(N); break; - case ISD::FP_ROUND: Result = PromoteResult_FP_ROUND(N); break; - case ISD::FP_TO_SINT: - case ISD::FP_TO_UINT: Result = PromoteResult_FP_TO_XINT(N); break; - case ISD::SETCC: Result = PromoteResult_SETCC(N); break; - case ISD::LOAD: Result = PromoteResult_LOAD(cast(N)); break; - case ISD::BUILD_PAIR: Result = PromoteResult_BUILD_PAIR(N); break; - case ISD::BIT_CONVERT: Result = PromoteResult_BIT_CONVERT(N); break; - - case ISD::AND: - case ISD::OR: - case ISD::XOR: - case ISD::ADD: - case ISD::SUB: - case ISD::MUL: Result = PromoteResult_SimpleIntBinOp(N); break; - - case ISD::SDIV: - case ISD::SREM: Result = PromoteResult_SDIV(N); break; - - case ISD::UDIV: - case ISD::UREM: Result = PromoteResult_UDIV(N); break; - - case ISD::SHL: Result = PromoteResult_SHL(N); break; - case ISD::SRA: Result = PromoteResult_SRA(N); break; - case ISD::SRL: Result = PromoteResult_SRL(N); break; - - case ISD::SELECT: Result = PromoteResult_SELECT(N); break; - case ISD::SELECT_CC: Result = PromoteResult_SELECT_CC(N); break; - - case ISD::CTLZ: Result = PromoteResult_CTLZ(N); break; - case ISD::CTPOP: Result = PromoteResult_CTPOP(N); break; - case ISD::CTTZ: Result = PromoteResult_CTTZ(N); break; - - case ISD::EXTRACT_VECTOR_ELT: - Result = PromoteResult_EXTRACT_VECTOR_ELT(N); - break; - } - - // If Result is null, the sub-method took care of registering the result. - if (Result.Val) - SetPromotedOp(SDOperand(N, ResNo), Result); -} - -SDOperand DAGTypeLegalizer::PromoteResult_UNDEF(SDNode *N) { - return DAG.getNode(ISD::UNDEF, TLI.getTypeToTransformTo(N->getValueType(0))); -} - -SDOperand DAGTypeLegalizer::PromoteResult_Constant(SDNode *N) { - MVT VT = N->getValueType(0); - // Zero extend things like i1, sign extend everything else. It shouldn't - // matter in theory which one we pick, but this tends to give better code? - unsigned Opc = VT.isByteSized() ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND; - SDOperand Result = DAG.getNode(Opc, TLI.getTypeToTransformTo(VT), - SDOperand(N, 0)); - assert(isa(Result) && "Didn't constant fold ext?"); - return Result; -} - -SDOperand DAGTypeLegalizer::PromoteResult_TRUNCATE(SDNode *N) { - SDOperand Res; - - switch (getTypeAction(N->getOperand(0).getValueType())) { - default: assert(0 && "Unknown type action!"); - case Legal: - case Expand: - Res = N->getOperand(0); - break; - case Promote: - Res = GetPromotedOp(N->getOperand(0)); - break; - } - - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - assert(Res.getValueType().getSizeInBits() >= NVT.getSizeInBits() && - "Truncation doesn't make sense!"); - if (Res.getValueType() == NVT) - return Res; - - // Truncate to NVT instead of VT - return DAG.getNode(ISD::TRUNCATE, NVT, Res); -} - -SDOperand DAGTypeLegalizer::PromoteResult_INT_EXTEND(SDNode *N) { - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - - if (getTypeAction(N->getOperand(0).getValueType()) == Promote) { - SDOperand Res = GetPromotedOp(N->getOperand(0)); - assert(Res.getValueType().getSizeInBits() <= NVT.getSizeInBits() && - "Extension doesn't make sense!"); - - // If the result and operand types are the same after promotion, simplify - // to an in-register extension. - if (NVT == Res.getValueType()) { - // The high bits are not guaranteed to be anything. Insert an extend. - if (N->getOpcode() == ISD::SIGN_EXTEND) - return DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Res, - DAG.getValueType(N->getOperand(0).getValueType())); - if (N->getOpcode() == ISD::ZERO_EXTEND) - return DAG.getZeroExtendInReg(Res, N->getOperand(0).getValueType()); - assert(N->getOpcode() == ISD::ANY_EXTEND && "Unknown integer extension!"); - return Res; - } - } - - // Otherwise, just extend the original operand all the way to the larger type. - return DAG.getNode(N->getOpcode(), NVT, N->getOperand(0)); -} - -SDOperand DAGTypeLegalizer::PromoteResult_FP_ROUND(SDNode *N) { - // NOTE: Assumes input is legal. - if (N->getConstantOperandVal(1) == 0) - return DAG.getNode(ISD::FP_ROUND_INREG, N->getOperand(0).getValueType(), - N->getOperand(0), DAG.getValueType(N->getValueType(0))); - // If the precision discard isn't needed, just return the operand unrounded. - return N->getOperand(0); -} - -SDOperand DAGTypeLegalizer::PromoteResult_FP_TO_XINT(SDNode *N) { - SDOperand Op = N->getOperand(0); - // If the operand needed to be promoted, do so now. - if (getTypeAction(Op.getValueType()) == Promote) - // The input result is prerounded, so we don't have to do anything special. - Op = GetPromotedOp(Op); - - unsigned NewOpc = N->getOpcode(); - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - - // If we're promoting a UINT to a larger size, check to see if the new node - // will be legal. If it isn't, check to see if FP_TO_SINT is legal, since - // we can use that instead. This allows us to generate better code for - // FP_TO_UINT for small destination sizes on targets where FP_TO_UINT is not - // legal, such as PowerPC. - if (N->getOpcode() == ISD::FP_TO_UINT) { - if (!TLI.isOperationLegal(ISD::FP_TO_UINT, NVT) && - (TLI.isOperationLegal(ISD::FP_TO_SINT, NVT) || - TLI.getOperationAction(ISD::FP_TO_SINT, NVT)==TargetLowering::Custom)) - NewOpc = ISD::FP_TO_SINT; - } - - return DAG.getNode(NewOpc, NVT, Op); -} - -SDOperand DAGTypeLegalizer::PromoteResult_SETCC(SDNode *N) { - assert(isTypeLegal(TLI.getSetCCResultType(N->getOperand(0))) - && "SetCC type is not legal??"); - return DAG.getNode(ISD::SETCC, TLI.getSetCCResultType(N->getOperand(0)), - N->getOperand(0), N->getOperand(1), N->getOperand(2)); -} - -SDOperand DAGTypeLegalizer::PromoteResult_LOAD(LoadSDNode *N) { - // FIXME: Add support for indexed loads. - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - ISD::LoadExtType ExtType = - ISD::isNON_EXTLoad(N) ? ISD::EXTLOAD : N->getExtensionType(); - SDOperand Res = DAG.getExtLoad(ExtType, NVT, N->getChain(), N->getBasePtr(), - N->getSrcValue(), N->getSrcValueOffset(), - N->getMemoryVT(), N->isVolatile(), - N->getAlignment()); - - // Legalized the chain result - switch anything that used the old chain to - // use the new one. - ReplaceValueWith(SDOperand(N, 1), Res.getValue(1)); - return Res; -} - -SDOperand DAGTypeLegalizer::PromoteResult_BUILD_PAIR(SDNode *N) { - // The pair element type may be legal, or may not promote to the same type as - // the result, for example i14 = BUILD_PAIR (i7, i7). Handle all cases. - return DAG.getNode(ISD::ANY_EXTEND, - TLI.getTypeToTransformTo(N->getValueType(0)), - JoinIntegers(N->getOperand(0), N->getOperand(1))); -} - -SDOperand DAGTypeLegalizer::PromoteResult_BIT_CONVERT(SDNode *N) { - SDOperand InOp = N->getOperand(0); - MVT InVT = InOp.getValueType(); - MVT NInVT = TLI.getTypeToTransformTo(InVT); - MVT OutVT = TLI.getTypeToTransformTo(N->getValueType(0)); - - switch (getTypeAction(InVT)) { - default: - assert(false && "Unknown type action!"); - break; - case Legal: - break; - case Promote: - if (OutVT.getSizeInBits() == NInVT.getSizeInBits()) - // The input promotes to the same size. Convert the promoted value. - return DAG.getNode(ISD::BIT_CONVERT, OutVT, GetPromotedOp(InOp)); - break; - case Expand: - break; - case FloatToInt: - // Promote the integer operand by hand. - return DAG.getNode(ISD::ANY_EXTEND, OutVT, GetIntegerOp(InOp)); - case Scalarize: - // Convert the element to an integer and promote it by hand. - return DAG.getNode(ISD::ANY_EXTEND, OutVT, - BitConvertToInteger(GetScalarizedOp(InOp))); - case Split: - // For example, i32 = BIT_CONVERT v2i16 on alpha. Convert the split - // pieces of the input into integers and reassemble in the final type. - SDOperand Lo, Hi; - GetSplitOp(N->getOperand(0), Lo, Hi); - Lo = BitConvertToInteger(Lo); - Hi = BitConvertToInteger(Hi); - - if (TLI.isBigEndian()) - std::swap(Lo, Hi); - - InOp = DAG.getNode(ISD::ANY_EXTEND, - MVT::getIntegerVT(OutVT.getSizeInBits()), - JoinIntegers(Lo, Hi)); - return DAG.getNode(ISD::BIT_CONVERT, OutVT, InOp); - } - - // Otherwise, lower the bit-convert to a store/load from the stack, then - // promote the load. - SDOperand Op = CreateStackStoreLoad(InOp, N->getValueType(0)); - return PromoteResult_LOAD(cast(Op.Val)); -} - -SDOperand DAGTypeLegalizer::PromoteResult_SimpleIntBinOp(SDNode *N) { - // The input may have strange things in the top bits of the registers, but - // these operations don't care. They may have weird bits going out, but - // that too is okay if they are integer operations. - SDOperand LHS = GetPromotedOp(N->getOperand(0)); - SDOperand RHS = GetPromotedOp(N->getOperand(1)); - return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS); -} - -SDOperand DAGTypeLegalizer::PromoteResult_SDIV(SDNode *N) { - // Sign extend the input. - SDOperand LHS = GetPromotedOp(N->getOperand(0)); - SDOperand RHS = GetPromotedOp(N->getOperand(1)); - MVT VT = N->getValueType(0); - LHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, LHS.getValueType(), LHS, - DAG.getValueType(VT)); - RHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, RHS.getValueType(), RHS, - DAG.getValueType(VT)); - - return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS); -} - -SDOperand DAGTypeLegalizer::PromoteResult_UDIV(SDNode *N) { - // Zero extend the input. - SDOperand LHS = GetPromotedOp(N->getOperand(0)); - SDOperand RHS = GetPromotedOp(N->getOperand(1)); - MVT VT = N->getValueType(0); - LHS = DAG.getZeroExtendInReg(LHS, VT); - RHS = DAG.getZeroExtendInReg(RHS, VT); - - return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS); -} - -SDOperand DAGTypeLegalizer::PromoteResult_SHL(SDNode *N) { - return DAG.getNode(ISD::SHL, TLI.getTypeToTransformTo(N->getValueType(0)), - GetPromotedOp(N->getOperand(0)), N->getOperand(1)); -} - -SDOperand DAGTypeLegalizer::PromoteResult_SRA(SDNode *N) { - // The input value must be properly sign extended. - MVT VT = N->getValueType(0); - MVT NVT = TLI.getTypeToTransformTo(VT); - SDOperand Res = GetPromotedOp(N->getOperand(0)); - Res = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Res, DAG.getValueType(VT)); - return DAG.getNode(ISD::SRA, NVT, Res, N->getOperand(1)); -} - -SDOperand DAGTypeLegalizer::PromoteResult_SRL(SDNode *N) { - // The input value must be properly zero extended. - MVT VT = N->getValueType(0); - MVT NVT = TLI.getTypeToTransformTo(VT); - SDOperand Res = GetPromotedZExtOp(N->getOperand(0)); - return DAG.getNode(ISD::SRL, NVT, Res, N->getOperand(1)); -} - -SDOperand DAGTypeLegalizer::PromoteResult_SELECT(SDNode *N) { - SDOperand LHS = GetPromotedOp(N->getOperand(1)); - SDOperand RHS = GetPromotedOp(N->getOperand(2)); - return DAG.getNode(ISD::SELECT, LHS.getValueType(), N->getOperand(0),LHS,RHS); -} - -SDOperand DAGTypeLegalizer::PromoteResult_SELECT_CC(SDNode *N) { - SDOperand LHS = GetPromotedOp(N->getOperand(2)); - SDOperand RHS = GetPromotedOp(N->getOperand(3)); - return DAG.getNode(ISD::SELECT_CC, LHS.getValueType(), N->getOperand(0), - N->getOperand(1), LHS, RHS, N->getOperand(4)); -} - -SDOperand DAGTypeLegalizer::PromoteResult_CTLZ(SDNode *N) { - SDOperand Op = GetPromotedOp(N->getOperand(0)); - MVT OVT = N->getValueType(0); - MVT NVT = Op.getValueType(); - // Zero extend to the promoted type and do the count there. - Op = DAG.getNode(ISD::CTLZ, NVT, DAG.getZeroExtendInReg(Op, OVT)); - // Subtract off the extra leading bits in the bigger type. - return DAG.getNode(ISD::SUB, NVT, Op, - DAG.getConstant(NVT.getSizeInBits() - - OVT.getSizeInBits(), NVT)); -} - -SDOperand DAGTypeLegalizer::PromoteResult_CTPOP(SDNode *N) { - SDOperand Op = GetPromotedOp(N->getOperand(0)); - MVT OVT = N->getValueType(0); - MVT NVT = Op.getValueType(); - // Zero extend to the promoted type and do the count there. - return DAG.getNode(ISD::CTPOP, NVT, DAG.getZeroExtendInReg(Op, OVT)); -} - -SDOperand DAGTypeLegalizer::PromoteResult_CTTZ(SDNode *N) { - SDOperand Op = GetPromotedOp(N->getOperand(0)); - MVT OVT = N->getValueType(0); - MVT NVT = Op.getValueType(); - // The count is the same in the promoted type except if the original - // value was zero. This can be handled by setting the bit just off - // the top of the original type. - Op = DAG.getNode(ISD::OR, NVT, Op, - // FIXME: Do this using an APINT constant. - DAG.getConstant(1UL << OVT.getSizeInBits(), NVT)); - return DAG.getNode(ISD::CTTZ, NVT, Op); -} - -SDOperand DAGTypeLegalizer::PromoteResult_EXTRACT_VECTOR_ELT(SDNode *N) { - MVT OldVT = N->getValueType(0); - SDOperand OldVec = N->getOperand(0); - unsigned OldElts = OldVec.getValueType().getVectorNumElements(); - - if (OldElts == 1) { - assert(!isTypeLegal(OldVec.getValueType()) && - "Legal one-element vector of a type needing promotion!"); - // It is tempting to follow GetScalarizedOp by a call to GetPromotedOp, - // but this would be wrong because the scalarized value may not yet have - // been processed. - return DAG.getNode(ISD::ANY_EXTEND, TLI.getTypeToTransformTo(OldVT), - GetScalarizedOp(OldVec)); - } - - // Convert to a vector half as long with an element type of twice the width, - // for example <4 x i16> -> <2 x i32>. - assert(!(OldElts & 1) && "Odd length vectors not supported!"); - MVT NewVT = MVT::getIntegerVT(2 * OldVT.getSizeInBits()); - assert(OldVT.isSimple() && NewVT.isSimple()); - - SDOperand NewVec = DAG.getNode(ISD::BIT_CONVERT, - MVT::getVectorVT(NewVT, OldElts / 2), - OldVec); - - // Extract the element at OldIdx / 2 from the new vector. - SDOperand OldIdx = N->getOperand(1); - SDOperand NewIdx = DAG.getNode(ISD::SRL, OldIdx.getValueType(), OldIdx, - DAG.getConstant(1, TLI.getShiftAmountTy())); - SDOperand Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, NewIdx); - - // Select the appropriate half of the element: Lo if OldIdx was even, - // Hi if it was odd. - SDOperand Lo = Elt; - SDOperand Hi = DAG.getNode(ISD::SRL, NewVT, Elt, - DAG.getConstant(OldVT.getSizeInBits(), - TLI.getShiftAmountTy())); - if (TLI.isBigEndian()) - std::swap(Lo, Hi); - - SDOperand Odd = DAG.getNode(ISD::AND, OldIdx.getValueType(), OldIdx, - DAG.getConstant(1, TLI.getShiftAmountTy())); - return DAG.getNode(ISD::SELECT, NewVT, Odd, Hi, Lo); -} - -//===----------------------------------------------------------------------===// -// Operand Promotion -//===----------------------------------------------------------------------===// - -/// PromoteOperand - This method is called when the specified operand of the -/// specified node is found to need promotion. At this point, all of the result -/// types of the node are known to be legal, but other operands of the node may -/// need promotion or expansion as well as the specified one. -bool DAGTypeLegalizer::PromoteOperand(SDNode *N, unsigned OpNo) { - DEBUG(cerr << "Promote node operand: "; N->dump(&DAG); cerr << "\n"); - SDOperand Res; - switch (N->getOpcode()) { - default: -#ifndef NDEBUG - cerr << "PromoteOperand Op #" << OpNo << ": "; - N->dump(&DAG); cerr << "\n"; -#endif - assert(0 && "Do not know how to promote this operator's operand!"); - abort(); - - case ISD::ANY_EXTEND: Res = PromoteOperand_ANY_EXTEND(N); break; - case ISD::ZERO_EXTEND: Res = PromoteOperand_ZERO_EXTEND(N); break; - case ISD::SIGN_EXTEND: Res = PromoteOperand_SIGN_EXTEND(N); break; - case ISD::TRUNCATE: Res = PromoteOperand_TRUNCATE(N); break; - case ISD::FP_EXTEND: Res = PromoteOperand_FP_EXTEND(N); break; - case ISD::FP_ROUND: Res = PromoteOperand_FP_ROUND(N); break; - case ISD::SINT_TO_FP: - case ISD::UINT_TO_FP: Res = PromoteOperand_INT_TO_FP(N); break; - case ISD::BUILD_PAIR: Res = PromoteOperand_BUILD_PAIR(N); break; - - case ISD::SELECT: Res = PromoteOperand_SELECT(N, OpNo); break; - case ISD::BRCOND: Res = PromoteOperand_BRCOND(N, OpNo); break; - case ISD::BR_CC: Res = PromoteOperand_BR_CC(N, OpNo); break; - case ISD::SETCC: Res = PromoteOperand_SETCC(N, OpNo); break; - - case ISD::STORE: Res = PromoteOperand_STORE(cast(N), - OpNo); break; - - case ISD::BUILD_VECTOR: Res = PromoteOperand_BUILD_VECTOR(N); break; - case ISD::INSERT_VECTOR_ELT: - Res = PromoteOperand_INSERT_VECTOR_ELT(N, OpNo); - break; - - case ISD::RET: Res = PromoteOperand_RET(N, OpNo); break; - - case ISD::MEMBARRIER: Res = PromoteOperand_MEMBARRIER(N); break; - } - - // If the result is null, the sub-method took care of registering results etc. - if (!Res.Val) return false; - // If the result is N, the sub-method updated N in place. - if (Res.Val == N) { - // Mark N as new and remark N and its operands. This allows us to correctly - // revisit N if it needs another step of promotion and allows us to visit - // any new operands to N. - ReanalyzeNode(N); - return true; - } - - assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && - "Invalid operand expansion"); - - ReplaceValueWith(SDOperand(N, 0), Res); - return false; -} - -SDOperand DAGTypeLegalizer::PromoteOperand_ANY_EXTEND(SDNode *N) { - SDOperand Op = GetPromotedOp(N->getOperand(0)); - return DAG.getNode(ISD::ANY_EXTEND, N->getValueType(0), Op); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_ZERO_EXTEND(SDNode *N) { - SDOperand Op = GetPromotedOp(N->getOperand(0)); - Op = DAG.getNode(ISD::ANY_EXTEND, N->getValueType(0), Op); - return DAG.getZeroExtendInReg(Op, N->getOperand(0).getValueType()); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_SIGN_EXTEND(SDNode *N) { - SDOperand Op = GetPromotedOp(N->getOperand(0)); - Op = DAG.getNode(ISD::ANY_EXTEND, N->getValueType(0), Op); - return DAG.getNode(ISD::SIGN_EXTEND_INREG, Op.getValueType(), - Op, DAG.getValueType(N->getOperand(0).getValueType())); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_TRUNCATE(SDNode *N) { - SDOperand Op = GetPromotedOp(N->getOperand(0)); - return DAG.getNode(ISD::TRUNCATE, N->getValueType(0), Op); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_FP_EXTEND(SDNode *N) { - SDOperand Op = GetPromotedOp(N->getOperand(0)); - return DAG.getNode(ISD::FP_EXTEND, N->getValueType(0), Op); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_FP_ROUND(SDNode *N) { - SDOperand Op = GetPromotedOp(N->getOperand(0)); - return DAG.getNode(ISD::FP_ROUND, N->getValueType(0), Op, - DAG.getIntPtrConstant(0)); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_INT_TO_FP(SDNode *N) { - SDOperand In = GetPromotedOp(N->getOperand(0)); - MVT OpVT = N->getOperand(0).getValueType(); - if (N->getOpcode() == ISD::UINT_TO_FP) - In = DAG.getZeroExtendInReg(In, OpVT); - else - In = DAG.getNode(ISD::SIGN_EXTEND_INREG, In.getValueType(), - In, DAG.getValueType(OpVT)); - - return DAG.UpdateNodeOperands(SDOperand(N, 0), In); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_BUILD_PAIR(SDNode *N) { - // Since the result type is legal, the operands must promote to it. - MVT OVT = N->getOperand(0).getValueType(); - SDOperand Lo = GetPromotedOp(N->getOperand(0)); - SDOperand Hi = GetPromotedOp(N->getOperand(1)); - assert(Lo.getValueType() == N->getValueType(0) && "Operand over promoted?"); - - Lo = DAG.getZeroExtendInReg(Lo, OVT); - Hi = DAG.getNode(ISD::SHL, N->getValueType(0), Hi, - DAG.getConstant(OVT.getSizeInBits(), - TLI.getShiftAmountTy())); - return DAG.getNode(ISD::OR, N->getValueType(0), Lo, Hi); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_SELECT(SDNode *N, unsigned OpNo) { - assert(OpNo == 0 && "Only know how to promote condition"); - SDOperand Cond = GetPromotedOp(N->getOperand(0)); // Promote the condition. - - // The top bits of the promoted condition are not necessarily zero, ensure - // that the value is properly zero extended. - unsigned BitWidth = Cond.getValueSizeInBits(); - if (!DAG.MaskedValueIsZero(Cond, - APInt::getHighBitsSet(BitWidth, BitWidth-1))) - Cond = DAG.getZeroExtendInReg(Cond, MVT::i1); - - // The chain (Op#0) and basic block destination (Op#2) are always legal types. - return DAG.UpdateNodeOperands(SDOperand(N, 0), Cond, N->getOperand(1), - N->getOperand(2)); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_BRCOND(SDNode *N, unsigned OpNo) { - assert(OpNo == 1 && "only know how to promote condition"); - SDOperand Cond = GetPromotedOp(N->getOperand(1)); // Promote the condition. - - // The top bits of the promoted condition are not necessarily zero, ensure - // that the value is properly zero extended. - unsigned BitWidth = Cond.getValueSizeInBits(); - if (!DAG.MaskedValueIsZero(Cond, - APInt::getHighBitsSet(BitWidth, BitWidth-1))) - Cond = DAG.getZeroExtendInReg(Cond, MVT::i1); - - // The chain (Op#0) and basic block destination (Op#2) are always legal types. - return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), Cond, - N->getOperand(2)); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_BR_CC(SDNode *N, unsigned OpNo) { - assert(OpNo == 2 && "Don't know how to promote this operand"); - - SDOperand LHS = N->getOperand(2); - SDOperand RHS = N->getOperand(3); - PromoteSetCCOperands(LHS, RHS, cast(N->getOperand(1))->get()); - - // The chain (Op#0), CC (#1) and basic block destination (Op#4) are always - // legal types. - return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), - N->getOperand(1), LHS, RHS, N->getOperand(4)); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_SETCC(SDNode *N, unsigned OpNo) { - assert(OpNo == 0 && "Don't know how to promote this operand"); - - SDOperand LHS = N->getOperand(0); - SDOperand RHS = N->getOperand(1); - PromoteSetCCOperands(LHS, RHS, cast(N->getOperand(2))->get()); - - // The CC (#2) is always legal. - return DAG.UpdateNodeOperands(SDOperand(N, 0), LHS, RHS, N->getOperand(2)); -} - -/// PromoteSetCCOperands - Promote the operands of a comparison. This code is -/// shared among BR_CC, SELECT_CC, and SETCC handlers. -void DAGTypeLegalizer::PromoteSetCCOperands(SDOperand &NewLHS,SDOperand &NewRHS, - ISD::CondCode CCCode) { - MVT VT = NewLHS.getValueType(); - - // Get the promoted values. - NewLHS = GetPromotedOp(NewLHS); - NewRHS = GetPromotedOp(NewRHS); - - // If this is an FP compare, the operands have already been extended. - if (!NewLHS.getValueType().isInteger()) - return; - - // Otherwise, we have to insert explicit sign or zero extends. Note - // that we could insert sign extends for ALL conditions, but zero extend - // is cheaper on many machines (an AND instead of two shifts), so prefer - // it. - switch (CCCode) { - default: assert(0 && "Unknown integer comparison!"); - case ISD::SETEQ: - case ISD::SETNE: - case ISD::SETUGE: - case ISD::SETUGT: - case ISD::SETULE: - case ISD::SETULT: - // ALL of these operations will work if we either sign or zero extend - // the operands (including the unsigned comparisons!). Zero extend is - // usually a simpler/cheaper operation, so prefer it. - NewLHS = DAG.getZeroExtendInReg(NewLHS, VT); - NewRHS = DAG.getZeroExtendInReg(NewRHS, VT); - return; - case ISD::SETGE: - case ISD::SETGT: - case ISD::SETLT: - case ISD::SETLE: - NewLHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, NewLHS.getValueType(), NewLHS, - DAG.getValueType(VT)); - NewRHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, NewRHS.getValueType(), NewRHS, - DAG.getValueType(VT)); - return; - } -} - -SDOperand DAGTypeLegalizer::PromoteOperand_STORE(StoreSDNode *N, unsigned OpNo){ - // FIXME: Add support for indexed stores. - SDOperand Ch = N->getChain(), Ptr = N->getBasePtr(); - int SVOffset = N->getSrcValueOffset(); - unsigned Alignment = N->getAlignment(); - bool isVolatile = N->isVolatile(); - - SDOperand Val = GetPromotedOp(N->getValue()); // Get promoted value. - - assert(!N->isTruncatingStore() && "Cannot promote this store operand!"); - - // Truncate the value and store the result. - return DAG.getTruncStore(Ch, Val, Ptr, N->getSrcValue(), - SVOffset, N->getMemoryVT(), - isVolatile, Alignment); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_BUILD_VECTOR(SDNode *N) { - // The vector type is legal but the element type is not. This implies - // that the vector is a power-of-two in length and that the element - // type does not have a strange size (eg: it is not i1). - MVT VecVT = N->getValueType(0); - unsigned NumElts = VecVT.getVectorNumElements(); - assert(!(NumElts & 1) && "Legal vector of one illegal element?"); - - // Build a vector of half the length out of elements of twice the bitwidth. - // For example <4 x i16> -> <2 x i32>. - MVT OldVT = N->getOperand(0).getValueType(); - MVT NewVT = MVT::getIntegerVT(2 * OldVT.getSizeInBits()); - assert(OldVT.isSimple() && NewVT.isSimple()); - - std::vector NewElts; - NewElts.reserve(NumElts/2); - - for (unsigned i = 0; i < NumElts; i += 2) { - // Combine two successive elements into one promoted element. - SDOperand Lo = N->getOperand(i); - SDOperand Hi = N->getOperand(i+1); - if (TLI.isBigEndian()) - std::swap(Lo, Hi); - NewElts.push_back(JoinIntegers(Lo, Hi)); - } - - SDOperand NewVec = DAG.getNode(ISD::BUILD_VECTOR, - MVT::getVectorVT(NewVT, NewElts.size()), - &NewElts[0], NewElts.size()); - - // Convert the new vector to the old vector type. - return DAG.getNode(ISD::BIT_CONVERT, VecVT, NewVec); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_INSERT_VECTOR_ELT(SDNode *N, - unsigned OpNo) { - if (OpNo == 1) { - // Promote the inserted value. This is valid because the type does not - // have to match the vector element type. - - // Check that any extra bits introduced will be truncated away. - assert(N->getOperand(1).getValueType().getSizeInBits() >= - N->getValueType(0).getVectorElementType().getSizeInBits() && - "Type of inserted value narrower than vector element type!"); - return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), - GetPromotedOp(N->getOperand(1)), - N->getOperand(2)); - } - - assert(OpNo == 2 && "Different operand and result vector types?"); - - // Promote the index. - SDOperand Idx = N->getOperand(2); - Idx = DAG.getZeroExtendInReg(GetPromotedOp(Idx), Idx.getValueType()); - return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), - N->getOperand(1), Idx); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_RET(SDNode *N, unsigned OpNo) { - assert(!(OpNo & 1) && "Return values should be legally typed!"); - assert((N->getNumOperands() & 1) && "Wrong number of operands!"); - - // It's a flag. Promote all the flags in one hit, as an optimization. - SmallVector NewValues(N->getNumOperands()); - NewValues[0] = N->getOperand(0); // The chain - for (unsigned i = 1, e = N->getNumOperands(); i < e; i += 2) { - // The return value. - NewValues[i] = N->getOperand(i); - - // The flag. - SDOperand Flag = N->getOperand(i + 1); - if (getTypeAction(Flag.getValueType()) == Promote) - // The promoted value may have rubbish in the new bits, but that - // doesn't matter because those bits aren't queried anyway. - Flag = GetPromotedOp(Flag); - NewValues[i + 1] = Flag; - } - - return DAG.UpdateNodeOperands(SDOperand (N, 0), - &NewValues[0], NewValues.size()); -} - -SDOperand DAGTypeLegalizer::PromoteOperand_MEMBARRIER(SDNode *N) { - SDOperand NewOps[6]; - NewOps[0] = N->getOperand(0); - for (unsigned i = 1; i < array_lengthof(NewOps); ++i) { - SDOperand Flag = GetPromotedOp(N->getOperand(i)); - NewOps[i] = DAG.getZeroExtendInReg(Flag, MVT::i1); - } - return DAG.UpdateNodeOperands(SDOperand (N, 0), NewOps, - array_lengthof(NewOps)); -} Removed: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesScalarize.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesScalarize.cpp?rev=52407&view=auto ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesScalarize.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesScalarize.cpp (removed) @@ -1,233 +0,0 @@ -//===-- LegalizeTypesScalarize.cpp - Scalarization for LegalizeTypes ------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements scalarization support for LegalizeTypes. Scalarization -// is the act of changing a computation in an invalid single-element vector type -// to be a computation in its scalar element type. For example, implementing -// <1 x f32> arithmetic in a scalar f32 register. This is needed as a base case -// when scalarizing vector arithmetic like <4 x f32>, which eventually -// decomposes to scalars if the target doesn't support v4f32 or v2f32 types. -// -//===----------------------------------------------------------------------===// - -#include "LegalizeTypes.h" -using namespace llvm; - -//===----------------------------------------------------------------------===// -// Result Vector Scalarization: <1 x ty> -> ty. -//===----------------------------------------------------------------------===// - -void DAGTypeLegalizer::ScalarizeResult(SDNode *N, unsigned ResNo) { - DEBUG(cerr << "Scalarize node result " << ResNo << ": "; N->dump(&DAG); - cerr << "\n"); - SDOperand R = SDOperand(); - - // FIXME: Custom lowering for scalarization? -#if 0 - // See if the target wants to custom expand this node. - if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == - TargetLowering::Custom) { - // If the target wants to, allow it to lower this itself. - if (SDNode *P = TLI.ExpandOperationResult(N, DAG)) { - // Everything that once used N now uses P. We are guaranteed that the - // result value types of N and the result value types of P match. - ReplaceNodeWith(N, P); - return; - } - } -#endif - - switch (N->getOpcode()) { - default: -#ifndef NDEBUG - cerr << "ScalarizeResult #" << ResNo << ": "; - N->dump(&DAG); cerr << "\n"; -#endif - assert(0 && "Do not know how to scalarize the result of this operator!"); - abort(); - - case ISD::UNDEF: R = ScalarizeRes_UNDEF(N); break; - case ISD::LOAD: R = ScalarizeRes_LOAD(cast(N)); break; - case ISD::ADD: - case ISD::FADD: - case ISD::SUB: - case ISD::FSUB: - case ISD::MUL: - case ISD::FMUL: - case ISD::SDIV: - case ISD::UDIV: - case ISD::FDIV: - case ISD::SREM: - case ISD::UREM: - case ISD::FREM: - case ISD::FPOW: - case ISD::AND: - case ISD::OR: - case ISD::XOR: R = ScalarizeRes_BinOp(N); break; - case ISD::FNEG: - case ISD::FABS: - case ISD::FSQRT: - case ISD::FSIN: - case ISD::FCOS: R = ScalarizeRes_UnaryOp(N); break; - case ISD::FPOWI: R = ScalarizeRes_FPOWI(N); break; - case ISD::BUILD_VECTOR: R = N->getOperand(0); break; - case ISD::INSERT_VECTOR_ELT: R = ScalarizeRes_INSERT_VECTOR_ELT(N); break; - case ISD::VECTOR_SHUFFLE: R = ScalarizeRes_VECTOR_SHUFFLE(N); break; - case ISD::BIT_CONVERT: R = ScalarizeRes_BIT_CONVERT(N); break; - case ISD::SELECT: R = ScalarizeRes_SELECT(N); break; - } - - // If R is null, the sub-method took care of registering the result. - if (R.Val) - SetScalarizedOp(SDOperand(N, ResNo), R); -} - -SDOperand DAGTypeLegalizer::ScalarizeRes_UNDEF(SDNode *N) { - return DAG.getNode(ISD::UNDEF, N->getValueType(0).getVectorElementType()); -} - -SDOperand DAGTypeLegalizer::ScalarizeRes_LOAD(LoadSDNode *N) { - // FIXME: Add support for indexed loads. - SDOperand Result = DAG.getLoad(N->getValueType(0).getVectorElementType(), - N->getChain(), N->getBasePtr(), - N->getSrcValue(), N->getSrcValueOffset(), - N->isVolatile(), N->getAlignment()); - - // Legalized the chain result - switch anything that used the old chain to - // use the new one. - ReplaceValueWith(SDOperand(N, 1), Result.getValue(1)); - return Result; -} - -SDOperand DAGTypeLegalizer::ScalarizeRes_BinOp(SDNode *N) { - SDOperand LHS = GetScalarizedOp(N->getOperand(0)); - SDOperand RHS = GetScalarizedOp(N->getOperand(1)); - return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS); -} - -SDOperand DAGTypeLegalizer::ScalarizeRes_UnaryOp(SDNode *N) { - SDOperand Op = GetScalarizedOp(N->getOperand(0)); - return DAG.getNode(N->getOpcode(), Op.getValueType(), Op); -} - -SDOperand DAGTypeLegalizer::ScalarizeRes_FPOWI(SDNode *N) { - SDOperand Op = GetScalarizedOp(N->getOperand(0)); - return DAG.getNode(ISD::FPOWI, Op.getValueType(), Op, N->getOperand(1)); -} - -SDOperand DAGTypeLegalizer::ScalarizeRes_INSERT_VECTOR_ELT(SDNode *N) { - // The value to insert may have a wider type than the vector element type, - // so be sure to truncate it to the element type if necessary. - SDOperand Op = N->getOperand(1); - MVT EltVT = N->getValueType(0).getVectorElementType(); - if (Op.getValueType().bitsGT(EltVT)) - Op = DAG.getNode(ISD::TRUNCATE, EltVT, Op); - assert(Op.getValueType() == EltVT && "Invalid type for inserted value!"); - return Op; -} - -SDOperand DAGTypeLegalizer::ScalarizeRes_VECTOR_SHUFFLE(SDNode *N) { - // Figure out if the scalar is the LHS or RHS and return it. - SDOperand EltNum = N->getOperand(2).getOperand(0); - unsigned Op = cast(EltNum)->getValue() != 0; - return GetScalarizedOp(N->getOperand(Op)); -} - -SDOperand DAGTypeLegalizer::ScalarizeRes_BIT_CONVERT(SDNode *N) { - MVT NewVT = N->getValueType(0).getVectorElementType(); - return DAG.getNode(ISD::BIT_CONVERT, NewVT, N->getOperand(0)); -} - -SDOperand DAGTypeLegalizer::ScalarizeRes_SELECT(SDNode *N) { - SDOperand LHS = GetScalarizedOp(N->getOperand(1)); - return DAG.getNode(ISD::SELECT, LHS.getValueType(), N->getOperand(0), LHS, - GetScalarizedOp(N->getOperand(2))); -} - - -//===----------------------------------------------------------------------===// -// Operand Vector Scalarization <1 x ty> -> ty. -//===----------------------------------------------------------------------===// - -bool DAGTypeLegalizer::ScalarizeOperand(SDNode *N, unsigned OpNo) { - DEBUG(cerr << "Scalarize node operand " << OpNo << ": "; N->dump(&DAG); - cerr << "\n"); - SDOperand Res(0, 0); - - // FIXME: Should we support custom lowering for scalarization? -#if 0 - if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == - TargetLowering::Custom) - Res = TLI.LowerOperation(SDOperand(N, 0), DAG); -#endif - - if (Res.Val == 0) { - switch (N->getOpcode()) { - default: -#ifndef NDEBUG - cerr << "ScalarizeOperand Op #" << OpNo << ": "; - N->dump(&DAG); cerr << "\n"; -#endif - assert(0 && "Do not know how to scalarize this operator's operand!"); - abort(); - - case ISD::BIT_CONVERT: - Res = ScalarizeOp_BIT_CONVERT(N); break; - - case ISD::EXTRACT_VECTOR_ELT: - Res = ScalarizeOp_EXTRACT_VECTOR_ELT(N); break; - - case ISD::STORE: - Res = ScalarizeOp_STORE(cast(N), OpNo); break; - } - } - - // If the result is null, the sub-method took care of registering results etc. - if (!Res.Val) return false; - - // If the result is N, the sub-method updated N in place. Check to see if any - // operands are new, and if so, mark them. - if (Res.Val == N) { - // Mark N as new and remark N and its operands. This allows us to correctly - // revisit N if it needs another step of promotion and allows us to visit - // any new operands to N. - ReanalyzeNode(N); - return true; - } - - assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && - "Invalid operand expansion"); - - ReplaceValueWith(SDOperand(N, 0), Res); - return false; -} - -/// ScalarizeOp_BIT_CONVERT - If the value to convert is a vector that needs -/// to be scalarized, it must be <1 x ty>. Convert the element instead. -SDOperand DAGTypeLegalizer::ScalarizeOp_BIT_CONVERT(SDNode *N) { - SDOperand Elt = GetScalarizedOp(N->getOperand(0)); - return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Elt); -} - -/// ScalarizeOp_EXTRACT_VECTOR_ELT - If the input is a vector that needs to be -/// scalarized, it must be <1 x ty>, so just return the element, ignoring the -/// index. -SDOperand DAGTypeLegalizer::ScalarizeOp_EXTRACT_VECTOR_ELT(SDNode *N) { - return GetScalarizedOp(N->getOperand(0)); -} - -/// ScalarizeOp_STORE - If the value to store is a vector that needs to be -/// scalarized, it must be <1 x ty>. Just store the element. -SDOperand DAGTypeLegalizer::ScalarizeOp_STORE(StoreSDNode *N, unsigned OpNo) { - // FIXME: Add support for indexed stores. - assert(OpNo == 1 && "Do not know how to scalarize this operand!"); - return DAG.getStore(N->getChain(), GetScalarizedOp(N->getOperand(1)), - N->getBasePtr(), N->getSrcValue(), N->getSrcValueOffset(), - N->isVolatile(), N->getAlignment()); -} Removed: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp?rev=52407&view=auto ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp (removed) @@ -1,582 +0,0 @@ -//===-- LegalizeTypesSplit.cpp - Vector Splitting for LegalizeTypes -------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements vector splitting support for LegalizeTypes. Vector -// splitting is the act of changing a computation in an invalid vector type to -// be a computation in multiple vectors of a smaller type. For example, -// implementing <128 x f32> operations in terms of two <64 x f32> operations. -// -//===----------------------------------------------------------------------===// - -#include "LegalizeTypes.h" -using namespace llvm; - -/// GetSplitDestVTs - Compute the VTs needed for the low/hi parts of a vector -/// type that needs to be split. This handles non-power of two vectors. -static void GetSplitDestVTs(MVT InVT, MVT &Lo, MVT &Hi) { - MVT NewEltVT = InVT.getVectorElementType(); - unsigned NumElements = InVT.getVectorNumElements(); - if ((NumElements & (NumElements-1)) == 0) { // Simple power of two vector. - NumElements >>= 1; - Lo = Hi = MVT::getVectorVT(NewEltVT, NumElements); - } else { // Non-power-of-two vectors. - unsigned NewNumElts_Lo = 1 << Log2_32(NumElements); - unsigned NewNumElts_Hi = NumElements - NewNumElts_Lo; - Lo = MVT::getVectorVT(NewEltVT, NewNumElts_Lo); - Hi = MVT::getVectorVT(NewEltVT, NewNumElts_Hi); - } -} - - -//===----------------------------------------------------------------------===// -// Result Vector Splitting -//===----------------------------------------------------------------------===// - -/// SplitResult - This method is called when the specified result of the -/// specified node is found to need vector splitting. At this point, the node -/// may also have invalid operands or may have other results that need -/// legalization, we just know that (at least) one result needs vector -/// splitting. -void DAGTypeLegalizer::SplitResult(SDNode *N, unsigned ResNo) { - DEBUG(cerr << "Split node result: "; N->dump(&DAG); cerr << "\n"); - SDOperand Lo, Hi; - -#if 0 - // See if the target wants to custom expand this node. - if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == - TargetLowering::Custom) { - // If the target wants to, allow it to lower this itself. - if (SDNode *P = TLI.ExpandOperationResult(N, DAG)) { - // Everything that once used N now uses P. We are guaranteed that the - // result value types of N and the result value types of P match. - ReplaceNodeWith(N, P); - return; - } - } -#endif - - switch (N->getOpcode()) { - default: -#ifndef NDEBUG - cerr << "SplitResult #" << ResNo << ": "; - N->dump(&DAG); cerr << "\n"; -#endif - assert(0 && "Do not know how to split the result of this operator!"); - abort(); - - case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break; - case ISD::LOAD: SplitRes_LOAD(cast(N), Lo, Hi); break; - case ISD::BUILD_PAIR: SplitRes_BUILD_PAIR(N, Lo, Hi); break; - case ISD::INSERT_VECTOR_ELT:SplitRes_INSERT_VECTOR_ELT(N, Lo, Hi); break; - case ISD::VECTOR_SHUFFLE: SplitRes_VECTOR_SHUFFLE(N, Lo, Hi); break; - case ISD::BUILD_VECTOR: SplitRes_BUILD_VECTOR(N, Lo, Hi); break; - case ISD::CONCAT_VECTORS: SplitRes_CONCAT_VECTORS(N, Lo, Hi); break; - case ISD::BIT_CONVERT: SplitRes_BIT_CONVERT(N, Lo, Hi); break; - case ISD::CTTZ: - case ISD::CTLZ: - case ISD::CTPOP: - case ISD::FNEG: - case ISD::FABS: - case ISD::FSQRT: - case ISD::FSIN: - case ISD::FCOS: - case ISD::FP_TO_SINT: - case ISD::FP_TO_UINT: - case ISD::SINT_TO_FP: - case ISD::UINT_TO_FP: SplitRes_UnOp(N, Lo, Hi); break; - case ISD::ADD: - case ISD::SUB: - case ISD::MUL: - case ISD::FADD: - case ISD::FSUB: - case ISD::FMUL: - case ISD::SDIV: - case ISD::UDIV: - case ISD::FDIV: - case ISD::FPOW: - case ISD::AND: - case ISD::OR: - case ISD::XOR: - case ISD::UREM: - case ISD::SREM: - case ISD::FREM: SplitRes_BinOp(N, Lo, Hi); break; - case ISD::FPOWI: SplitRes_FPOWI(N, Lo, Hi); break; - case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break; - } - - // If Lo/Hi is null, the sub-method took care of registering results etc. - if (Lo.Val) - SetSplitOp(SDOperand(N, ResNo), Lo, Hi); -} - -void DAGTypeLegalizer::SplitRes_UNDEF(SDNode *N, SDOperand &Lo, SDOperand &Hi) { - MVT LoVT, HiVT; - GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); - - Lo = DAG.getNode(ISD::UNDEF, LoVT); - Hi = DAG.getNode(ISD::UNDEF, HiVT); -} - -void DAGTypeLegalizer::SplitRes_LOAD(LoadSDNode *LD, - SDOperand &Lo, SDOperand &Hi) { - // FIXME: Add support for indexed loads. - MVT LoVT, HiVT; - GetSplitDestVTs(LD->getValueType(0), LoVT, HiVT); - - SDOperand Ch = LD->getChain(); - SDOperand Ptr = LD->getBasePtr(); - const Value *SV = LD->getSrcValue(); - int SVOffset = LD->getSrcValueOffset(); - unsigned Alignment = LD->getAlignment(); - bool isVolatile = LD->isVolatile(); - - Lo = DAG.getLoad(LoVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment); - unsigned IncrementSize = LoVT.getSizeInBits()/8; - Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, - DAG.getIntPtrConstant(IncrementSize)); - SVOffset += IncrementSize; - Alignment = MinAlign(Alignment, IncrementSize); - Hi = DAG.getLoad(HiVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment); - - // Build a factor node to remember that this load is independent of the - // other one. - SDOperand TF = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1), - Hi.getValue(1)); - - // Legalized the chain result - switch anything that used the old chain to - // use the new one. - ReplaceValueWith(SDOperand(LD, 1), TF); -} - -void DAGTypeLegalizer::SplitRes_BUILD_PAIR(SDNode *N, SDOperand &Lo, - SDOperand &Hi) { - Lo = N->getOperand(0); - Hi = N->getOperand(1); -} - -void DAGTypeLegalizer::SplitRes_INSERT_VECTOR_ELT(SDNode *N, SDOperand &Lo, - SDOperand &Hi) { - SDOperand Vec = N->getOperand(0); - SDOperand Elt = N->getOperand(1); - SDOperand Idx = N->getOperand(2); - GetSplitOp(Vec, Lo, Hi); - - if (ConstantSDNode *CIdx = dyn_cast(Idx)) { - unsigned IdxVal = CIdx->getValue(); - unsigned LoNumElts = Lo.getValueType().getVectorNumElements(); - if (IdxVal < LoNumElts) - Lo = DAG.getNode(ISD::INSERT_VECTOR_ELT, Lo.getValueType(), Lo, Elt, Idx); - else - Hi = DAG.getNode(ISD::INSERT_VECTOR_ELT, Hi.getValueType(), Hi, Elt, - DAG.getIntPtrConstant(IdxVal - LoNumElts)); - return; - } - - // Spill the vector to the stack. - MVT VecVT = Vec.getValueType(); - SDOperand StackPtr = DAG.CreateStackTemporary(VecVT); - SDOperand Store = DAG.getStore(DAG.getEntryNode(), Vec, StackPtr, NULL, 0); - - // Store the new element. - SDOperand EltPtr = GetVectorElementPointer(StackPtr, - VecVT.getVectorElementType(), Idx); - Store = DAG.getStore(Store, Elt, EltPtr, NULL, 0); - - // Reload the vector from the stack. - SDOperand Load = DAG.getLoad(VecVT, Store, StackPtr, NULL, 0); - - // Split it. - SplitRes_LOAD(cast(Load.Val), Lo, Hi); -} - -void DAGTypeLegalizer::SplitRes_VECTOR_SHUFFLE(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - // Build the low part. - SDOperand Mask = N->getOperand(2); - SmallVector Ops; - MVT LoVT, HiVT; - GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); - MVT EltVT = LoVT.getVectorElementType(); - unsigned LoNumElts = LoVT.getVectorNumElements(); - unsigned NumElements = Mask.getNumOperands(); - - // Insert all of the elements from the input that are needed. We use - // buildvector of extractelement here because the input vectors will have - // to be legalized, so this makes the code simpler. - for (unsigned i = 0; i != LoNumElts; ++i) { - unsigned Idx = cast(Mask.getOperand(i))->getValue(); - SDOperand InVec = N->getOperand(0); - if (Idx >= NumElements) { - InVec = N->getOperand(1); - Idx -= NumElements; - } - Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EltVT, InVec, - DAG.getIntPtrConstant(Idx))); - } - Lo = DAG.getNode(ISD::BUILD_VECTOR, LoVT, &Ops[0], Ops.size()); - Ops.clear(); - - for (unsigned i = LoNumElts; i != NumElements; ++i) { - unsigned Idx = cast(Mask.getOperand(i))->getValue(); - SDOperand InVec = N->getOperand(0); - if (Idx >= NumElements) { - InVec = N->getOperand(1); - Idx -= NumElements; - } - Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EltVT, InVec, - DAG.getIntPtrConstant(Idx))); - } - Hi = DAG.getNode(ISD::BUILD_VECTOR, HiVT, &Ops[0], Ops.size()); -} - -void DAGTypeLegalizer::SplitRes_BUILD_VECTOR(SDNode *N, SDOperand &Lo, - SDOperand &Hi) { - MVT LoVT, HiVT; - GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); - unsigned LoNumElts = LoVT.getVectorNumElements(); - SmallVector LoOps(N->op_begin(), N->op_begin()+LoNumElts); - Lo = DAG.getNode(ISD::BUILD_VECTOR, LoVT, &LoOps[0], LoOps.size()); - - SmallVector HiOps(N->op_begin()+LoNumElts, N->op_end()); - Hi = DAG.getNode(ISD::BUILD_VECTOR, HiVT, &HiOps[0], HiOps.size()); -} - -void DAGTypeLegalizer::SplitRes_CONCAT_VECTORS(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - // FIXME: Handle non-power-of-two vectors? - unsigned NumSubvectors = N->getNumOperands() / 2; - if (NumSubvectors == 1) { - Lo = N->getOperand(0); - Hi = N->getOperand(1); - return; - } - - MVT LoVT, HiVT; - GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); - - SmallVector LoOps(N->op_begin(), N->op_begin()+NumSubvectors); - Lo = DAG.getNode(ISD::CONCAT_VECTORS, LoVT, &LoOps[0], LoOps.size()); - - SmallVector HiOps(N->op_begin()+NumSubvectors, N->op_end()); - Hi = DAG.getNode(ISD::CONCAT_VECTORS, HiVT, &HiOps[0], HiOps.size()); -} - -void DAGTypeLegalizer::SplitRes_BIT_CONVERT(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - // We know the result is a vector. The input may be either a vector or a - // scalar value. - MVT LoVT, HiVT; - GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); - - SDOperand InOp = N->getOperand(0); - MVT InVT = InOp.getValueType(); - - // Handle some special cases efficiently. - switch (getTypeAction(InVT)) { - default: - assert(false && "Unknown type action!"); - case Legal: - case FloatToInt: - case Promote: - case Scalarize: - break; - case Expand: - // A scalar to vector conversion, where the scalar needs expansion. - // If the vector is being split in two then we can just convert the - // expanded pieces. - if (LoVT == HiVT) { - GetExpandedOp(InOp, Lo, Hi); - if (TLI.isBigEndian()) - std::swap(Lo, Hi); - Lo = DAG.getNode(ISD::BIT_CONVERT, LoVT, Lo); - Hi = DAG.getNode(ISD::BIT_CONVERT, HiVT, Hi); - return; - } - break; - case Split: - // If the input is a vector that needs to be split, convert each split - // piece of the input now. - GetSplitOp(InOp, Lo, Hi); - Lo = DAG.getNode(ISD::BIT_CONVERT, LoVT, Lo); - Hi = DAG.getNode(ISD::BIT_CONVERT, HiVT, Hi); - return; - } - - // In the general case, convert the input to an integer and split it by hand. - MVT LoIntVT = MVT::getIntegerVT(LoVT.getSizeInBits()); - MVT HiIntVT = MVT::getIntegerVT(HiVT.getSizeInBits()); - if (TLI.isBigEndian()) - std::swap(LoIntVT, HiIntVT); - - SplitInteger(BitConvertToInteger(InOp), LoIntVT, HiIntVT, Lo, Hi); - - if (TLI.isBigEndian()) - std::swap(Lo, Hi); - Lo = DAG.getNode(ISD::BIT_CONVERT, LoVT, Lo); - Hi = DAG.getNode(ISD::BIT_CONVERT, HiVT, Hi); -} - -void DAGTypeLegalizer::SplitRes_BinOp(SDNode *N, SDOperand &Lo, SDOperand &Hi) { - SDOperand LHSLo, LHSHi; - GetSplitOp(N->getOperand(0), LHSLo, LHSHi); - SDOperand RHSLo, RHSHi; - GetSplitOp(N->getOperand(1), RHSLo, RHSHi); - - Lo = DAG.getNode(N->getOpcode(), LHSLo.getValueType(), LHSLo, RHSLo); - Hi = DAG.getNode(N->getOpcode(), LHSHi.getValueType(), LHSHi, RHSHi); -} - -void DAGTypeLegalizer::SplitRes_UnOp(SDNode *N, SDOperand &Lo, SDOperand &Hi) { - // Get the dest types. This doesn't always match input types, e.g. int_to_fp. - MVT LoVT, HiVT; - GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); - - GetSplitOp(N->getOperand(0), Lo, Hi); - Lo = DAG.getNode(N->getOpcode(), LoVT, Lo); - Hi = DAG.getNode(N->getOpcode(), HiVT, Hi); -} - -void DAGTypeLegalizer::SplitRes_FPOWI(SDNode *N, SDOperand &Lo, SDOperand &Hi) { - GetSplitOp(N->getOperand(0), Lo, Hi); - Lo = DAG.getNode(ISD::FPOWI, Lo.getValueType(), Lo, N->getOperand(1)); - Hi = DAG.getNode(ISD::FPOWI, Lo.getValueType(), Hi, N->getOperand(1)); -} - - -void DAGTypeLegalizer::SplitRes_SELECT(SDNode *N, SDOperand &Lo, SDOperand &Hi){ - SDOperand LL, LH, RL, RH; - GetSplitOp(N->getOperand(1), LL, LH); - GetSplitOp(N->getOperand(2), RL, RH); - - SDOperand Cond = N->getOperand(0); - Lo = DAG.getNode(ISD::SELECT, LL.getValueType(), Cond, LL, RL); - Hi = DAG.getNode(ISD::SELECT, LH.getValueType(), Cond, LH, RH); -} - - -//===----------------------------------------------------------------------===// -// Operand Vector Splitting -//===----------------------------------------------------------------------===// - -/// SplitOperand - This method is called when the specified operand of the -/// specified node is found to need vector splitting. At this point, all of the -/// result types of the node are known to be legal, but other operands of the -/// node may need legalization as well as the specified one. -bool DAGTypeLegalizer::SplitOperand(SDNode *N, unsigned OpNo) { - DEBUG(cerr << "Split node operand: "; N->dump(&DAG); cerr << "\n"); - SDOperand Res(0, 0); - -#if 0 - if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == - TargetLowering::Custom) - Res = TLI.LowerOperation(SDOperand(N, 0), DAG); -#endif - - if (Res.Val == 0) { - switch (N->getOpcode()) { - default: -#ifndef NDEBUG - cerr << "SplitOperand Op #" << OpNo << ": "; - N->dump(&DAG); cerr << "\n"; -#endif - assert(0 && "Do not know how to split this operator's operand!"); - abort(); - case ISD::STORE: Res = SplitOp_STORE(cast(N), OpNo); break; - case ISD::RET: Res = SplitOp_RET(N, OpNo); break; - - case ISD::BIT_CONVERT: Res = SplitOp_BIT_CONVERT(N); break; - - case ISD::EXTRACT_VECTOR_ELT: Res = SplitOp_EXTRACT_VECTOR_ELT(N); break; - case ISD::EXTRACT_SUBVECTOR: Res = SplitOp_EXTRACT_SUBVECTOR(N); break; - case ISD::VECTOR_SHUFFLE: Res = SplitOp_VECTOR_SHUFFLE(N, OpNo); break; - } - } - - // If the result is null, the sub-method took care of registering results etc. - if (!Res.Val) return false; - - // If the result is N, the sub-method updated N in place. Check to see if any - // operands are new, and if so, mark them. - if (Res.Val == N) { - // Mark N as new and remark N and its operands. This allows us to correctly - // revisit N if it needs another step of promotion and allows us to visit - // any new operands to N. - ReanalyzeNode(N); - return true; - } - - assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && - "Invalid operand expansion"); - - ReplaceValueWith(SDOperand(N, 0), Res); - return false; -} - -SDOperand DAGTypeLegalizer::SplitOp_STORE(StoreSDNode *N, unsigned OpNo) { - // FIXME: Add support for indexed stores. - assert(OpNo == 1 && "Can only split the stored value"); - - SDOperand Ch = N->getChain(); - SDOperand Ptr = N->getBasePtr(); - int SVOffset = N->getSrcValueOffset(); - unsigned Alignment = N->getAlignment(); - bool isVol = N->isVolatile(); - SDOperand Lo, Hi; - GetSplitOp(N->getOperand(1), Lo, Hi); - - unsigned IncrementSize = Lo.getValueType().getSizeInBits()/8; - - Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset, isVol, Alignment); - - // Increment the pointer to the other half. - Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, - DAG.getIntPtrConstant(IncrementSize)); - - Hi = DAG.getStore(Ch, Hi, Ptr, N->getSrcValue(), SVOffset+IncrementSize, - isVol, MinAlign(Alignment, IncrementSize)); - return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi); -} - -SDOperand DAGTypeLegalizer::SplitOp_RET(SDNode *N, unsigned OpNo) { - assert(N->getNumOperands() == 3 &&"Can only handle ret of one vector so far"); - // FIXME: Returns of gcc generic vectors larger than a legal vector - // type should be returned by reference! - SDOperand Lo, Hi; - GetSplitOp(N->getOperand(1), Lo, Hi); - - SDOperand Chain = N->getOperand(0); // The chain. - SDOperand Sign = N->getOperand(2); // Signness - - return DAG.getNode(ISD::RET, MVT::Other, Chain, Lo, Sign, Hi, Sign); -} - -SDOperand DAGTypeLegalizer::SplitOp_BIT_CONVERT(SDNode *N) { - // For example, i64 = BIT_CONVERT v4i16 on alpha. Typically the vector will - // end up being split all the way down to individual components. Convert the - // split pieces into integers and reassemble. - SDOperand Lo, Hi; - GetSplitOp(N->getOperand(0), Lo, Hi); - Lo = BitConvertToInteger(Lo); - Hi = BitConvertToInteger(Hi); - - if (TLI.isBigEndian()) - std::swap(Lo, Hi); - - return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), - JoinIntegers(Lo, Hi)); -} - -SDOperand DAGTypeLegalizer::SplitOp_EXTRACT_VECTOR_ELT(SDNode *N) { - SDOperand Vec = N->getOperand(0); - SDOperand Idx = N->getOperand(1); - MVT VecVT = Vec.getValueType(); - - if (isa(Idx)) { - uint64_t IdxVal = cast(Idx)->getValue(); - assert(IdxVal < VecVT.getVectorNumElements() && "Invalid vector index!"); - - SDOperand Lo, Hi; - GetSplitOp(Vec, Lo, Hi); - - uint64_t LoElts = Lo.getValueType().getVectorNumElements(); - - if (IdxVal < LoElts) - return DAG.UpdateNodeOperands(SDOperand(N, 0), Lo, Idx); - else - return DAG.UpdateNodeOperands(SDOperand(N, 0), Hi, - DAG.getConstant(IdxVal - LoElts, - Idx.getValueType())); - } - - // Store the vector to the stack. - MVT EltVT = VecVT.getVectorElementType(); - SDOperand StackPtr = DAG.CreateStackTemporary(VecVT); - SDOperand Store = DAG.getStore(DAG.getEntryNode(), Vec, StackPtr, NULL, 0); - - // Load back the required element. - StackPtr = GetVectorElementPointer(StackPtr, EltVT, Idx); - return DAG.getLoad(EltVT, Store, StackPtr, NULL, 0); -} - -SDOperand DAGTypeLegalizer::SplitOp_EXTRACT_SUBVECTOR(SDNode *N) { - // We know that the extracted result type is legal. For now, assume the index - // is a constant. - MVT SubVT = N->getValueType(0); - SDOperand Idx = N->getOperand(1); - SDOperand Lo, Hi; - GetSplitOp(N->getOperand(0), Lo, Hi); - - uint64_t LoElts = Lo.getValueType().getVectorNumElements(); - uint64_t IdxVal = cast(Idx)->getValue(); - - if (IdxVal < LoElts) { - assert(IdxVal + SubVT.getVectorNumElements() <= LoElts && - "Extracted subvector crosses vector split!"); - return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SubVT, Lo, Idx); - } else { - return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SubVT, Hi, - DAG.getConstant(IdxVal - LoElts, Idx.getValueType())); - } -} - -SDOperand DAGTypeLegalizer::SplitOp_VECTOR_SHUFFLE(SDNode *N, unsigned OpNo) { - assert(OpNo == 2 && "Shuffle source type differs from result type?"); - SDOperand Mask = N->getOperand(2); - unsigned MaskLength = Mask.getValueType().getVectorNumElements(); - unsigned LargestMaskEntryPlusOne = 2 * MaskLength; - unsigned MinimumBitWidth = Log2_32_Ceil(LargestMaskEntryPlusOne); - - // Look for a legal vector type to place the mask values in. - // Note that there may not be *any* legal vector-of-integer - // type for which the element type is legal! - for (MVT::SimpleValueType EltVT = MVT::FIRST_INTEGER_VALUETYPE; - EltVT <= MVT::LAST_INTEGER_VALUETYPE; - // Integer values types are consecutively numbered. Exploit this. - EltVT = MVT::SimpleValueType(EltVT + 1)) { - - // Is the element type big enough to hold the values? - if (MVT(EltVT).getSizeInBits() < MinimumBitWidth) - // Nope. - continue; - - // Is the vector type legal? - MVT VecVT = MVT::getVectorVT(EltVT, MaskLength); - if (!isTypeLegal(VecVT)) - // Nope. - continue; - - // If the element type is not legal, find a larger legal type to use for - // the BUILD_VECTOR operands. This is an ugly hack, but seems to work! - // FIXME: The real solution is to change VECTOR_SHUFFLE into a variadic - // node where the shuffle mask is a list of integer operands, #2 .. #2+n. - for (MVT::SimpleValueType OpVT = EltVT; OpVT <= MVT::LAST_INTEGER_VALUETYPE; - // Integer values types are consecutively numbered. Exploit this. - OpVT = MVT::SimpleValueType(OpVT + 1)) { - if (!isTypeLegal(OpVT)) - continue; - - // Success! Rebuild the vector using the legal types. - SmallVector Ops(MaskLength); - for (unsigned i = 0; i < MaskLength; ++i) { - uint64_t Idx = - cast(Mask.getOperand(i))->getValue(); - Ops[i] = DAG.getConstant(Idx, OpVT); - } - return DAG.UpdateNodeOperands(SDOperand(N,0), - N->getOperand(0), N->getOperand(1), - DAG.getNode(ISD::BUILD_VECTOR, - VecVT, &Ops[0], Ops.size())); - } - - // Continuing is pointless - failure is certain. - break; - } - assert(false && "Failed to find an appropriate mask type!"); - return SDOperand(N, 0); -} Added: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp?rev=52408&view=auto ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp (added) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp Tue Jun 17 09:27:01 2008 @@ -0,0 +1,806 @@ +//===------- LegalizeVectorTypes.cpp - Legalization of vector types -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file performs vector type splitting and scalarization for LegalizeTypes. +// Scalarization is the act of changing a computation in an illegal one-element +// vector type to be a computation in its scalar element type. For example, +// implementing <1 x f32> arithmetic in a scalar f32 register. This is needed +// as a base case when scalarizing vector arithmetic like <4 x f32>, which +// eventually decomposes to scalars if the target doesn't support v4f32 or v2f32 +// types. +// Splitting is the act of changing a computation in an invalid vector type to +// be a computation in multiple vectors of a smaller type. For example, +// implementing <128 x f32> operations in terms of two <64 x f32> operations. +// +//===----------------------------------------------------------------------===// + +#include "LegalizeTypes.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Result Vector Scalarization: <1 x ty> -> ty. +//===----------------------------------------------------------------------===// + +void DAGTypeLegalizer::ScalarizeResult(SDNode *N, unsigned ResNo) { + DEBUG(cerr << "Scalarize node result " << ResNo << ": "; N->dump(&DAG); + cerr << "\n"); + SDOperand R = SDOperand(); + + // FIXME: Custom lowering for scalarization? +#if 0 + // See if the target wants to custom expand this node. + if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == + TargetLowering::Custom) { + // If the target wants to, allow it to lower this itself. + if (SDNode *P = TLI.ExpandOperationResult(N, DAG)) { + // Everything that once used N now uses P. We are guaranteed that the + // result value types of N and the result value types of P match. + ReplaceNodeWith(N, P); + return; + } + } +#endif + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + cerr << "ScalarizeResult #" << ResNo << ": "; + N->dump(&DAG); cerr << "\n"; +#endif + assert(0 && "Do not know how to scalarize the result of this operator!"); + abort(); + + case ISD::UNDEF: R = ScalarizeRes_UNDEF(N); break; + case ISD::LOAD: R = ScalarizeRes_LOAD(cast(N)); break; + case ISD::ADD: + case ISD::FADD: + case ISD::SUB: + case ISD::FSUB: + case ISD::MUL: + case ISD::FMUL: + case ISD::SDIV: + case ISD::UDIV: + case ISD::FDIV: + case ISD::SREM: + case ISD::UREM: + case ISD::FREM: + case ISD::FPOW: + case ISD::AND: + case ISD::OR: + case ISD::XOR: R = ScalarizeRes_BinOp(N); break; + case ISD::FNEG: + case ISD::FABS: + case ISD::FSQRT: + case ISD::FSIN: + case ISD::FCOS: R = ScalarizeRes_UnaryOp(N); break; + case ISD::FPOWI: R = ScalarizeRes_FPOWI(N); break; + case ISD::BUILD_VECTOR: R = N->getOperand(0); break; + case ISD::INSERT_VECTOR_ELT: R = ScalarizeRes_INSERT_VECTOR_ELT(N); break; + case ISD::VECTOR_SHUFFLE: R = ScalarizeRes_VECTOR_SHUFFLE(N); break; + case ISD::BIT_CONVERT: R = ScalarizeRes_BIT_CONVERT(N); break; + case ISD::SELECT: R = ScalarizeRes_SELECT(N); break; + } + + // If R is null, the sub-method took care of registering the result. + if (R.Val) + SetScalarizedVector(SDOperand(N, ResNo), R); +} + +SDOperand DAGTypeLegalizer::ScalarizeRes_UNDEF(SDNode *N) { + return DAG.getNode(ISD::UNDEF, N->getValueType(0).getVectorElementType()); +} + +SDOperand DAGTypeLegalizer::ScalarizeRes_LOAD(LoadSDNode *N) { + // FIXME: Add support for indexed loads. + SDOperand Result = DAG.getLoad(N->getValueType(0).getVectorElementType(), + N->getChain(), N->getBasePtr(), + N->getSrcValue(), N->getSrcValueOffset(), + N->isVolatile(), N->getAlignment()); + + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDOperand(N, 1), Result.getValue(1)); + return Result; +} + +SDOperand DAGTypeLegalizer::ScalarizeRes_BinOp(SDNode *N) { + SDOperand LHS = GetScalarizedVector(N->getOperand(0)); + SDOperand RHS = GetScalarizedVector(N->getOperand(1)); + return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS); +} + +SDOperand DAGTypeLegalizer::ScalarizeRes_UnaryOp(SDNode *N) { + SDOperand Op = GetScalarizedVector(N->getOperand(0)); + return DAG.getNode(N->getOpcode(), Op.getValueType(), Op); +} + +SDOperand DAGTypeLegalizer::ScalarizeRes_FPOWI(SDNode *N) { + SDOperand Op = GetScalarizedVector(N->getOperand(0)); + return DAG.getNode(ISD::FPOWI, Op.getValueType(), Op, N->getOperand(1)); +} + +SDOperand DAGTypeLegalizer::ScalarizeRes_INSERT_VECTOR_ELT(SDNode *N) { + // The value to insert may have a wider type than the vector element type, + // so be sure to truncate it to the element type if necessary. + SDOperand Op = N->getOperand(1); + MVT EltVT = N->getValueType(0).getVectorElementType(); + if (Op.getValueType().bitsGT(EltVT)) + Op = DAG.getNode(ISD::TRUNCATE, EltVT, Op); + assert(Op.getValueType() == EltVT && "Invalid type for inserted value!"); + return Op; +} + +SDOperand DAGTypeLegalizer::ScalarizeRes_VECTOR_SHUFFLE(SDNode *N) { + // Figure out if the scalar is the LHS or RHS and return it. + SDOperand EltNum = N->getOperand(2).getOperand(0); + unsigned Op = cast(EltNum)->getValue() != 0; + return GetScalarizedVector(N->getOperand(Op)); +} + +SDOperand DAGTypeLegalizer::ScalarizeRes_BIT_CONVERT(SDNode *N) { + MVT NewVT = N->getValueType(0).getVectorElementType(); + return DAG.getNode(ISD::BIT_CONVERT, NewVT, N->getOperand(0)); +} + +SDOperand DAGTypeLegalizer::ScalarizeRes_SELECT(SDNode *N) { + SDOperand LHS = GetScalarizedVector(N->getOperand(1)); + return DAG.getNode(ISD::SELECT, LHS.getValueType(), N->getOperand(0), LHS, + GetScalarizedVector(N->getOperand(2))); +} + + +//===----------------------------------------------------------------------===// +// Operand Vector Scalarization <1 x ty> -> ty. +//===----------------------------------------------------------------------===// + +bool DAGTypeLegalizer::ScalarizeOperand(SDNode *N, unsigned OpNo) { + DEBUG(cerr << "Scalarize node operand " << OpNo << ": "; N->dump(&DAG); + cerr << "\n"); + SDOperand Res(0, 0); + + // FIXME: Should we support custom lowering for scalarization? +#if 0 + if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == + TargetLowering::Custom) + Res = TLI.LowerOperation(SDOperand(N, 0), DAG); +#endif + + if (Res.Val == 0) { + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + cerr << "ScalarizeOperand Op #" << OpNo << ": "; + N->dump(&DAG); cerr << "\n"; +#endif + assert(0 && "Do not know how to scalarize this operator's operand!"); + abort(); + + case ISD::BIT_CONVERT: + Res = ScalarizeOp_BIT_CONVERT(N); break; + + case ISD::EXTRACT_VECTOR_ELT: + Res = ScalarizeOp_EXTRACT_VECTOR_ELT(N); break; + + case ISD::STORE: + Res = ScalarizeOp_STORE(cast(N), OpNo); break; + } + } + + // If the result is null, the sub-method took care of registering results etc. + if (!Res.Val) return false; + + // If the result is N, the sub-method updated N in place. Check to see if any + // operands are new, and if so, mark them. + if (Res.Val == N) { + // Mark N as new and remark N and its operands. This allows us to correctly + // revisit N if it needs another step of promotion and allows us to visit + // any new operands to N. + ReanalyzeNode(N); + return true; + } + + assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && + "Invalid operand expansion"); + + ReplaceValueWith(SDOperand(N, 0), Res); + return false; +} + +/// ScalarizeOp_BIT_CONVERT - If the value to convert is a vector that needs +/// to be scalarized, it must be <1 x ty>. Convert the element instead. +SDOperand DAGTypeLegalizer::ScalarizeOp_BIT_CONVERT(SDNode *N) { + SDOperand Elt = GetScalarizedVector(N->getOperand(0)); + return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Elt); +} + +/// ScalarizeOp_EXTRACT_VECTOR_ELT - If the input is a vector that needs to be +/// scalarized, it must be <1 x ty>, so just return the element, ignoring the +/// index. +SDOperand DAGTypeLegalizer::ScalarizeOp_EXTRACT_VECTOR_ELT(SDNode *N) { + return GetScalarizedVector(N->getOperand(0)); +} + +/// ScalarizeOp_STORE - If the value to store is a vector that needs to be +/// scalarized, it must be <1 x ty>. Just store the element. +SDOperand DAGTypeLegalizer::ScalarizeOp_STORE(StoreSDNode *N, unsigned OpNo) { + // FIXME: Add support for indexed stores. + assert(OpNo == 1 && "Do not know how to scalarize this operand!"); + return DAG.getStore(N->getChain(), GetScalarizedVector(N->getOperand(1)), + N->getBasePtr(), N->getSrcValue(), N->getSrcValueOffset(), + N->isVolatile(), N->getAlignment()); +} + + +/// GetSplitDestVTs - Compute the VTs needed for the low/hi parts of a vector +/// type that needs to be split. This handles non-power of two vectors. +static void GetSplitDestVTs(MVT InVT, MVT &Lo, MVT &Hi) { + MVT NewEltVT = InVT.getVectorElementType(); + unsigned NumElements = InVT.getVectorNumElements(); + if ((NumElements & (NumElements-1)) == 0) { // Simple power of two vector. + NumElements >>= 1; + Lo = Hi = MVT::getVectorVT(NewEltVT, NumElements); + } else { // Non-power-of-two vectors. + unsigned NewNumElts_Lo = 1 << Log2_32(NumElements); + unsigned NewNumElts_Hi = NumElements - NewNumElts_Lo; + Lo = MVT::getVectorVT(NewEltVT, NewNumElts_Lo); + Hi = MVT::getVectorVT(NewEltVT, NewNumElts_Hi); + } +} + + +//===----------------------------------------------------------------------===// +// Result Vector Splitting +//===----------------------------------------------------------------------===// + +/// SplitResult - This method is called when the specified result of the +/// specified node is found to need vector splitting. At this point, the node +/// may also have invalid operands or may have other results that need +/// legalization, we just know that (at least) one result needs vector +/// splitting. +void DAGTypeLegalizer::SplitResult(SDNode *N, unsigned ResNo) { + DEBUG(cerr << "Split node result: "; N->dump(&DAG); cerr << "\n"); + SDOperand Lo, Hi; + +#if 0 + // See if the target wants to custom expand this node. + if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == + TargetLowering::Custom) { + // If the target wants to, allow it to lower this itself. + if (SDNode *P = TLI.ExpandOperationResult(N, DAG)) { + // Everything that once used N now uses P. We are guaranteed that the + // result value types of N and the result value types of P match. + ReplaceNodeWith(N, P); + return; + } + } +#endif + + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + cerr << "SplitResult #" << ResNo << ": "; + N->dump(&DAG); cerr << "\n"; +#endif + assert(0 && "Do not know how to split the result of this operator!"); + abort(); + + case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break; + case ISD::LOAD: SplitRes_LOAD(cast(N), Lo, Hi); break; + case ISD::BUILD_PAIR: SplitRes_BUILD_PAIR(N, Lo, Hi); break; + case ISD::INSERT_VECTOR_ELT:SplitRes_INSERT_VECTOR_ELT(N, Lo, Hi); break; + case ISD::VECTOR_SHUFFLE: SplitRes_VECTOR_SHUFFLE(N, Lo, Hi); break; + case ISD::BUILD_VECTOR: SplitRes_BUILD_VECTOR(N, Lo, Hi); break; + case ISD::CONCAT_VECTORS: SplitRes_CONCAT_VECTORS(N, Lo, Hi); break; + case ISD::BIT_CONVERT: SplitRes_BIT_CONVERT(N, Lo, Hi); break; + case ISD::CTTZ: + case ISD::CTLZ: + case ISD::CTPOP: + case ISD::FNEG: + case ISD::FABS: + case ISD::FSQRT: + case ISD::FSIN: + case ISD::FCOS: + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: SplitRes_UnOp(N, Lo, Hi); break; + case ISD::ADD: + case ISD::SUB: + case ISD::MUL: + case ISD::FADD: + case ISD::FSUB: + case ISD::FMUL: + case ISD::SDIV: + case ISD::UDIV: + case ISD::FDIV: + case ISD::FPOW: + case ISD::AND: + case ISD::OR: + case ISD::XOR: + case ISD::UREM: + case ISD::SREM: + case ISD::FREM: SplitRes_BinOp(N, Lo, Hi); break; + case ISD::FPOWI: SplitRes_FPOWI(N, Lo, Hi); break; + case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break; + } + + // If Lo/Hi is null, the sub-method took care of registering results etc. + if (Lo.Val) + SetSplitVector(SDOperand(N, ResNo), Lo, Hi); +} + +void DAGTypeLegalizer::SplitRes_UNDEF(SDNode *N, SDOperand &Lo, SDOperand &Hi) { + MVT LoVT, HiVT; + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + + Lo = DAG.getNode(ISD::UNDEF, LoVT); + Hi = DAG.getNode(ISD::UNDEF, HiVT); +} + +void DAGTypeLegalizer::SplitRes_LOAD(LoadSDNode *LD, + SDOperand &Lo, SDOperand &Hi) { + // FIXME: Add support for indexed loads. + MVT LoVT, HiVT; + GetSplitDestVTs(LD->getValueType(0), LoVT, HiVT); + + SDOperand Ch = LD->getChain(); + SDOperand Ptr = LD->getBasePtr(); + const Value *SV = LD->getSrcValue(); + int SVOffset = LD->getSrcValueOffset(); + unsigned Alignment = LD->getAlignment(); + bool isVolatile = LD->isVolatile(); + + Lo = DAG.getLoad(LoVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment); + unsigned IncrementSize = LoVT.getSizeInBits()/8; + Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + SVOffset += IncrementSize; + Alignment = MinAlign(Alignment, IncrementSize); + Hi = DAG.getLoad(HiVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment); + + // Build a factor node to remember that this load is independent of the + // other one. + SDOperand TF = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1), + Hi.getValue(1)); + + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDOperand(LD, 1), TF); +} + +void DAGTypeLegalizer::SplitRes_BUILD_PAIR(SDNode *N, SDOperand &Lo, + SDOperand &Hi) { + Lo = N->getOperand(0); + Hi = N->getOperand(1); +} + +void DAGTypeLegalizer::SplitRes_INSERT_VECTOR_ELT(SDNode *N, SDOperand &Lo, + SDOperand &Hi) { + SDOperand Vec = N->getOperand(0); + SDOperand Elt = N->getOperand(1); + SDOperand Idx = N->getOperand(2); + GetSplitVector(Vec, Lo, Hi); + + if (ConstantSDNode *CIdx = dyn_cast(Idx)) { + unsigned IdxVal = CIdx->getValue(); + unsigned LoNumElts = Lo.getValueType().getVectorNumElements(); + if (IdxVal < LoNumElts) + Lo = DAG.getNode(ISD::INSERT_VECTOR_ELT, Lo.getValueType(), Lo, Elt, Idx); + else + Hi = DAG.getNode(ISD::INSERT_VECTOR_ELT, Hi.getValueType(), Hi, Elt, + DAG.getIntPtrConstant(IdxVal - LoNumElts)); + return; + } + + // Spill the vector to the stack. + MVT VecVT = Vec.getValueType(); + SDOperand StackPtr = DAG.CreateStackTemporary(VecVT); + SDOperand Store = DAG.getStore(DAG.getEntryNode(), Vec, StackPtr, NULL, 0); + + // Store the new element. + SDOperand EltPtr = GetVectorElementPointer(StackPtr, + VecVT.getVectorElementType(), Idx); + Store = DAG.getStore(Store, Elt, EltPtr, NULL, 0); + + // Reload the vector from the stack. + SDOperand Load = DAG.getLoad(VecVT, Store, StackPtr, NULL, 0); + + // Split it. + SplitRes_LOAD(cast(Load.Val), Lo, Hi); +} + +void DAGTypeLegalizer::SplitRes_VECTOR_SHUFFLE(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + // Build the low part. + SDOperand Mask = N->getOperand(2); + SmallVector Ops; + MVT LoVT, HiVT; + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + MVT EltVT = LoVT.getVectorElementType(); + unsigned LoNumElts = LoVT.getVectorNumElements(); + unsigned NumElements = Mask.getNumOperands(); + + // Insert all of the elements from the input that are needed. We use + // buildvector of extractelement here because the input vectors will have + // to be legalized, so this makes the code simpler. + for (unsigned i = 0; i != LoNumElts; ++i) { + unsigned Idx = cast(Mask.getOperand(i))->getValue(); + SDOperand InVec = N->getOperand(0); + if (Idx >= NumElements) { + InVec = N->getOperand(1); + Idx -= NumElements; + } + Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EltVT, InVec, + DAG.getIntPtrConstant(Idx))); + } + Lo = DAG.getNode(ISD::BUILD_VECTOR, LoVT, &Ops[0], Ops.size()); + Ops.clear(); + + for (unsigned i = LoNumElts; i != NumElements; ++i) { + unsigned Idx = cast(Mask.getOperand(i))->getValue(); + SDOperand InVec = N->getOperand(0); + if (Idx >= NumElements) { + InVec = N->getOperand(1); + Idx -= NumElements; + } + Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EltVT, InVec, + DAG.getIntPtrConstant(Idx))); + } + Hi = DAG.getNode(ISD::BUILD_VECTOR, HiVT, &Ops[0], Ops.size()); +} + +void DAGTypeLegalizer::SplitRes_BUILD_VECTOR(SDNode *N, SDOperand &Lo, + SDOperand &Hi) { + MVT LoVT, HiVT; + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + unsigned LoNumElts = LoVT.getVectorNumElements(); + SmallVector LoOps(N->op_begin(), N->op_begin()+LoNumElts); + Lo = DAG.getNode(ISD::BUILD_VECTOR, LoVT, &LoOps[0], LoOps.size()); + + SmallVector HiOps(N->op_begin()+LoNumElts, N->op_end()); + Hi = DAG.getNode(ISD::BUILD_VECTOR, HiVT, &HiOps[0], HiOps.size()); +} + +void DAGTypeLegalizer::SplitRes_CONCAT_VECTORS(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + // FIXME: Handle non-power-of-two vectors? + unsigned NumSubvectors = N->getNumOperands() / 2; + if (NumSubvectors == 1) { + Lo = N->getOperand(0); + Hi = N->getOperand(1); + return; + } + + MVT LoVT, HiVT; + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + + SmallVector LoOps(N->op_begin(), N->op_begin()+NumSubvectors); + Lo = DAG.getNode(ISD::CONCAT_VECTORS, LoVT, &LoOps[0], LoOps.size()); + + SmallVector HiOps(N->op_begin()+NumSubvectors, N->op_end()); + Hi = DAG.getNode(ISD::CONCAT_VECTORS, HiVT, &HiOps[0], HiOps.size()); +} + +void DAGTypeLegalizer::SplitRes_BIT_CONVERT(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + // We know the result is a vector. The input may be either a vector or a + // scalar value. + MVT LoVT, HiVT; + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + + SDOperand InOp = N->getOperand(0); + MVT InVT = InOp.getValueType(); + + // Handle some special cases efficiently. + switch (getTypeAction(InVT)) { + default: + assert(false && "Unknown type action!"); + case Legal: + case PromoteInteger: + case PromoteFloat: + case Scalarize: + break; + case ExpandInteger: + case ExpandFloat: + // A scalar to vector conversion, where the scalar needs expansion. + // If the vector is being split in two then we can just convert the + // expanded pieces. + if (LoVT == HiVT) { + if (InVT.isInteger()) + GetExpandedInteger(InOp, Lo, Hi); + else + GetExpandedFloat(InOp, Lo, Hi); + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, LoVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, HiVT, Hi); + return; + } + break; + case Split: + // If the input is a vector that needs to be split, convert each split + // piece of the input now. + GetSplitVector(InOp, Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, LoVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, HiVT, Hi); + return; + } + + // In the general case, convert the input to an integer and split it by hand. + MVT LoIntVT = MVT::getIntegerVT(LoVT.getSizeInBits()); + MVT HiIntVT = MVT::getIntegerVT(HiVT.getSizeInBits()); + if (TLI.isBigEndian()) + std::swap(LoIntVT, HiIntVT); + + SplitInteger(BitConvertToInteger(InOp), LoIntVT, HiIntVT, Lo, Hi); + + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, LoVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, HiVT, Hi); +} + +void DAGTypeLegalizer::SplitRes_BinOp(SDNode *N, SDOperand &Lo, SDOperand &Hi) { + SDOperand LHSLo, LHSHi; + GetSplitVector(N->getOperand(0), LHSLo, LHSHi); + SDOperand RHSLo, RHSHi; + GetSplitVector(N->getOperand(1), RHSLo, RHSHi); + + Lo = DAG.getNode(N->getOpcode(), LHSLo.getValueType(), LHSLo, RHSLo); + Hi = DAG.getNode(N->getOpcode(), LHSHi.getValueType(), LHSHi, RHSHi); +} + +void DAGTypeLegalizer::SplitRes_UnOp(SDNode *N, SDOperand &Lo, SDOperand &Hi) { + // Get the dest types. This doesn't always match input types, e.g. int_to_fp. + MVT LoVT, HiVT; + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + + GetSplitVector(N->getOperand(0), Lo, Hi); + Lo = DAG.getNode(N->getOpcode(), LoVT, Lo); + Hi = DAG.getNode(N->getOpcode(), HiVT, Hi); +} + +void DAGTypeLegalizer::SplitRes_FPOWI(SDNode *N, SDOperand &Lo, SDOperand &Hi) { + GetSplitVector(N->getOperand(0), Lo, Hi); + Lo = DAG.getNode(ISD::FPOWI, Lo.getValueType(), Lo, N->getOperand(1)); + Hi = DAG.getNode(ISD::FPOWI, Lo.getValueType(), Hi, N->getOperand(1)); +} + + +void DAGTypeLegalizer::SplitRes_SELECT(SDNode *N, SDOperand &Lo, SDOperand &Hi){ + SDOperand LL, LH, RL, RH; + GetSplitVector(N->getOperand(1), LL, LH); + GetSplitVector(N->getOperand(2), RL, RH); + + SDOperand Cond = N->getOperand(0); + Lo = DAG.getNode(ISD::SELECT, LL.getValueType(), Cond, LL, RL); + Hi = DAG.getNode(ISD::SELECT, LH.getValueType(), Cond, LH, RH); +} + + +//===----------------------------------------------------------------------===// +// Operand Vector Splitting +//===----------------------------------------------------------------------===// + +/// SplitOperand - This method is called when the specified operand of the +/// specified node is found to need vector splitting. At this point, all of the +/// result types of the node are known to be legal, but other operands of the +/// node may need legalization as well as the specified one. +bool DAGTypeLegalizer::SplitOperand(SDNode *N, unsigned OpNo) { + DEBUG(cerr << "Split node operand: "; N->dump(&DAG); cerr << "\n"); + SDOperand Res(0, 0); + +#if 0 + if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == + TargetLowering::Custom) + Res = TLI.LowerOperation(SDOperand(N, 0), DAG); +#endif + + if (Res.Val == 0) { + switch (N->getOpcode()) { + default: +#ifndef NDEBUG + cerr << "SplitOperand Op #" << OpNo << ": "; + N->dump(&DAG); cerr << "\n"; +#endif + assert(0 && "Do not know how to split this operator's operand!"); + abort(); + case ISD::STORE: Res = SplitOp_STORE(cast(N), OpNo); break; + case ISD::RET: Res = SplitOp_RET(N, OpNo); break; + + case ISD::BIT_CONVERT: Res = SplitOp_BIT_CONVERT(N); break; + + case ISD::EXTRACT_VECTOR_ELT: Res = SplitOp_EXTRACT_VECTOR_ELT(N); break; + case ISD::EXTRACT_SUBVECTOR: Res = SplitOp_EXTRACT_SUBVECTOR(N); break; + case ISD::VECTOR_SHUFFLE: Res = SplitOp_VECTOR_SHUFFLE(N, OpNo); break; + } + } + + // If the result is null, the sub-method took care of registering results etc. + if (!Res.Val) return false; + + // If the result is N, the sub-method updated N in place. Check to see if any + // operands are new, and if so, mark them. + if (Res.Val == N) { + // Mark N as new and remark N and its operands. This allows us to correctly + // revisit N if it needs another step of promotion and allows us to visit + // any new operands to N. + ReanalyzeNode(N); + return true; + } + + assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && + "Invalid operand expansion"); + + ReplaceValueWith(SDOperand(N, 0), Res); + return false; +} + +SDOperand DAGTypeLegalizer::SplitOp_STORE(StoreSDNode *N, unsigned OpNo) { + // FIXME: Add support for indexed stores. + assert(OpNo == 1 && "Can only split the stored value"); + + SDOperand Ch = N->getChain(); + SDOperand Ptr = N->getBasePtr(); + int SVOffset = N->getSrcValueOffset(); + unsigned Alignment = N->getAlignment(); + bool isVol = N->isVolatile(); + SDOperand Lo, Hi; + GetSplitVector(N->getOperand(1), Lo, Hi); + + unsigned IncrementSize = Lo.getValueType().getSizeInBits()/8; + + Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset, isVol, Alignment); + + // Increment the pointer to the other half. + Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + + Hi = DAG.getStore(Ch, Hi, Ptr, N->getSrcValue(), SVOffset+IncrementSize, + isVol, MinAlign(Alignment, IncrementSize)); + return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi); +} + +SDOperand DAGTypeLegalizer::SplitOp_RET(SDNode *N, unsigned OpNo) { + assert(N->getNumOperands() == 3 &&"Can only handle ret of one vector so far"); + // FIXME: Returns of gcc generic vectors larger than a legal vector + // type should be returned by reference! + SDOperand Lo, Hi; + GetSplitVector(N->getOperand(1), Lo, Hi); + + SDOperand Chain = N->getOperand(0); // The chain. + SDOperand Sign = N->getOperand(2); // Signness + + return DAG.getNode(ISD::RET, MVT::Other, Chain, Lo, Sign, Hi, Sign); +} + +SDOperand DAGTypeLegalizer::SplitOp_BIT_CONVERT(SDNode *N) { + // For example, i64 = BIT_CONVERT v4i16 on alpha. Typically the vector will + // end up being split all the way down to individual components. Convert the + // split pieces into integers and reassemble. + SDOperand Lo, Hi; + GetSplitVector(N->getOperand(0), Lo, Hi); + Lo = BitConvertToInteger(Lo); + Hi = BitConvertToInteger(Hi); + + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), + JoinIntegers(Lo, Hi)); +} + +SDOperand DAGTypeLegalizer::SplitOp_EXTRACT_VECTOR_ELT(SDNode *N) { + SDOperand Vec = N->getOperand(0); + SDOperand Idx = N->getOperand(1); + MVT VecVT = Vec.getValueType(); + + if (isa(Idx)) { + uint64_t IdxVal = cast(Idx)->getValue(); + assert(IdxVal < VecVT.getVectorNumElements() && "Invalid vector index!"); + + SDOperand Lo, Hi; + GetSplitVector(Vec, Lo, Hi); + + uint64_t LoElts = Lo.getValueType().getVectorNumElements(); + + if (IdxVal < LoElts) + return DAG.UpdateNodeOperands(SDOperand(N, 0), Lo, Idx); + else + return DAG.UpdateNodeOperands(SDOperand(N, 0), Hi, + DAG.getConstant(IdxVal - LoElts, + Idx.getValueType())); + } + + // Store the vector to the stack. + MVT EltVT = VecVT.getVectorElementType(); + SDOperand StackPtr = DAG.CreateStackTemporary(VecVT); + SDOperand Store = DAG.getStore(DAG.getEntryNode(), Vec, StackPtr, NULL, 0); + + // Load back the required element. + StackPtr = GetVectorElementPointer(StackPtr, EltVT, Idx); + return DAG.getLoad(EltVT, Store, StackPtr, NULL, 0); +} + +SDOperand DAGTypeLegalizer::SplitOp_EXTRACT_SUBVECTOR(SDNode *N) { + // We know that the extracted result type is legal. For now, assume the index + // is a constant. + MVT SubVT = N->getValueType(0); + SDOperand Idx = N->getOperand(1); + SDOperand Lo, Hi; + GetSplitVector(N->getOperand(0), Lo, Hi); + + uint64_t LoElts = Lo.getValueType().getVectorNumElements(); + uint64_t IdxVal = cast(Idx)->getValue(); + + if (IdxVal < LoElts) { + assert(IdxVal + SubVT.getVectorNumElements() <= LoElts && + "Extracted subvector crosses vector split!"); + return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SubVT, Lo, Idx); + } else { + return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SubVT, Hi, + DAG.getConstant(IdxVal - LoElts, Idx.getValueType())); + } +} + +SDOperand DAGTypeLegalizer::SplitOp_VECTOR_SHUFFLE(SDNode *N, unsigned OpNo) { + assert(OpNo == 2 && "Shuffle source type differs from result type?"); + SDOperand Mask = N->getOperand(2); + unsigned MaskLength = Mask.getValueType().getVectorNumElements(); + unsigned LargestMaskEntryPlusOne = 2 * MaskLength; + unsigned MinimumBitWidth = Log2_32_Ceil(LargestMaskEntryPlusOne); + + // Look for a legal vector type to place the mask values in. + // Note that there may not be *any* legal vector-of-integer + // type for which the element type is legal! + for (MVT::SimpleValueType EltVT = MVT::FIRST_INTEGER_VALUETYPE; + EltVT <= MVT::LAST_INTEGER_VALUETYPE; + // Integer values types are consecutively numbered. Exploit this. + EltVT = MVT::SimpleValueType(EltVT + 1)) { + + // Is the element type big enough to hold the values? + if (MVT(EltVT).getSizeInBits() < MinimumBitWidth) + // Nope. + continue; + + // Is the vector type legal? + MVT VecVT = MVT::getVectorVT(EltVT, MaskLength); + if (!isTypeLegal(VecVT)) + // Nope. + continue; + + // If the element type is not legal, find a larger legal type to use for + // the BUILD_VECTOR operands. This is an ugly hack, but seems to work! + // FIXME: The real solution is to change VECTOR_SHUFFLE into a variadic + // node where the shuffle mask is a list of integer operands, #2 .. #2+n. + for (MVT::SimpleValueType OpVT = EltVT; OpVT <= MVT::LAST_INTEGER_VALUETYPE; + // Integer values types are consecutively numbered. Exploit this. + OpVT = MVT::SimpleValueType(OpVT + 1)) { + if (!isTypeLegal(OpVT)) + continue; + + // Success! Rebuild the vector using the legal types. + SmallVector Ops(MaskLength); + for (unsigned i = 0; i < MaskLength; ++i) { + uint64_t Idx = + cast(Mask.getOperand(i))->getValue(); + Ops[i] = DAG.getConstant(Idx, OpVT); + } + return DAG.UpdateNodeOperands(SDOperand(N,0), + N->getOperand(0), N->getOperand(1), + DAG.getNode(ISD::BUILD_VECTOR, + VecVT, &Ops[0], Ops.size())); + } + + // Continuing is pointless - failure is certain. + break; + } + assert(false && "Failed to find an appropriate mask type!"); + return SDOperand(N, 0); +} From nicolas.geoffray at lip6.fr Tue Jun 17 09:35:30 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 17 Jun 2008 14:35:30 -0000 Subject: [llvm-commits] [vmkit] r52409 - in /vmkit/trunk/lib/JnJVM/VMCore: JavaInitialise.cpp JavaObject.cpp JavaObject.h VirtualTables.cpp Message-ID: <200806171435.m5HEZVfU011111@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jun 17 09:35:30 2008 New Revision: 52409 URL: http://llvm.org/viewvc/llvm-project?rev=52409&view=rev Log: Remove code where LockObj was supposed to be GC-allocated. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaObject.h vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp?rev=52409&r1=52408&r2=52409&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp Tue Jun 17 09:35:30 2008 @@ -44,7 +44,6 @@ INIT(CommonClass); INIT(Class); INIT(ClassArray); - INIT(LockObj); INIT(JavaThread); INIT(Jnjvm); INIT(ClassMap); Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp?rev=52409&r1=52408&r2=52409&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaObject.cpp Tue Jun 17 09:35:30 2008 @@ -68,10 +68,6 @@ } } -void LockObj::print(mvm::PrintBuffer* buf) const { - buf->write("Lock<>"); -} - LockObj* LockObj::allocate() { LockObj* res = new LockObj(); res->lock = mvm::Lock::allocRecursive(); Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaObject.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaObject.h?rev=52409&r1=52408&r2=52409&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaObject.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaObject.h Tue Jun 17 09:35:30 2008 @@ -58,7 +58,7 @@ /// LockObj - This class represents a Java monitor. /// -class LockObj : public mvm::Object { +class LockObj { friend class JavaObject; @@ -109,9 +109,6 @@ } public: - static VirtualTable* VT; - virtual void print(mvm::PrintBuffer* buf) const; - virtual void TRACER; ~LockObj(); LockObj(); }; Modified: vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp?rev=52409&r1=52408&r2=52409&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp Tue Jun 17 09:35:30 2008 @@ -40,7 +40,6 @@ INIT(CommonClass); INIT(Class); INIT(ClassArray); - INIT(LockObj); INIT(JavaObject); INIT(JavaThread); INIT(Jnjvm); @@ -56,7 +55,6 @@ void ArrayObject::TRACER { classOf->MARK_AND_TRACE; - if (lockObj()) lockObj()->MARK_AND_TRACE; for (sint32 i = 0; i < size; i++) { if (elements[i]) elements[i]->MARK_AND_TRACE; } @@ -64,8 +62,6 @@ #define ARRAYTRACER(name) \ void name::TRACER { \ - if (lockObj()) \ - lockObj()->MARK_AND_TRACE; \ } @@ -106,9 +102,6 @@ CommonClass::PARENT_TRACER; } -void LockObj::TRACER { -} - void JavaObject::TRACER { classOf->MARK_AND_TRACE; } From nicolas.geoffray at lip6.fr Tue Jun 17 10:40:31 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 17 Jun 2008 15:40:31 -0000 Subject: [llvm-commits] [vmkit] r52410 - in /vmkit/trunk/lib/JnJVM: Classpath/ClasspathConstructor.cpp Classpath/ClasspathMethod.cpp VMCore/JavaArray.cpp VMCore/JavaArray.h VMCore/JavaInitialise.cpp VMCore/Jni.cpp VMCore/VirtualTables.cpp Message-ID: <200806171540.m5HFeVZo013180@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jun 17 10:40:30 2008 New Revision: 52410 URL: http://llvm.org/viewvc/llvm-project?rev=52410&view=rev Log: Simplify array code. JavaObject, JavaArray and ArrayObject do not have destructors anymore. Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathConstructor.cpp vmkit/trunk/lib/JnJVM/Classpath/ClasspathMethod.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaArray.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaArray.h vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp vmkit/trunk/lib/JnJVM/VMCore/Jni.cpp vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathConstructor.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathConstructor.cpp?rev=52410&r1=52409&r2=52410&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathConstructor.cpp (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathConstructor.cpp Tue Jun 17 10:40:30 2008 @@ -54,7 +54,7 @@ jclass Clazz, jint _meth) { JavaMethod* meth = (JavaMethod*)_meth; - ArrayObject* args = (ArrayObject*)_args; + JavaArray* args = (JavaArray*)_args; sint32 nbArgs = args ? args->size : 0; sint32 size = meth->getSignature()->args.size(); Jnjvm* vm = JavaThread::get()->isolate; @@ -69,10 +69,10 @@ cl->initialiseClass(); JavaObject* res = cl->doNew(vm); - + JavaObject** ptr = (JavaObject**)(void*)(args->elements); for (std::vector::iterator i = meth->getSignature()->args.begin(), e = meth->getSignature()->args.end(); i != e; ++i, ++index) { - NativeUtil::decapsulePrimitive(vm, buf, args->at(index), *i); + NativeUtil::decapsulePrimitive(vm, buf, ptr[index], *i); } JavaObject* excp = 0; Modified: vmkit/trunk/lib/JnJVM/Classpath/ClasspathMethod.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/Classpath/ClasspathMethod.cpp?rev=52410&r1=52409&r2=52410&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/Classpath/ClasspathMethod.cpp (original) +++ vmkit/trunk/lib/JnJVM/Classpath/ClasspathMethod.cpp Tue Jun 17 10:40:30 2008 @@ -63,7 +63,7 @@ jobject Meth, jobject _obj, jobject _args, jclass Cl, jint _meth) { JavaMethod* meth = (JavaMethod*)_meth; - ArrayObject* args = (ArrayObject*)_args; + JavaArray* args = (JavaArray*)_args; sint32 nbArgs = args ? args->size : 0; sint32 size = meth->getSignature()->args.size(); Jnjvm* vm = JavaThread::get()->isolate; @@ -86,10 +86,10 @@ cl->initialiseClass(); } - + JavaObject** ptr = (JavaObject**)(void*)(args->elements); for (std::vector::iterator i = meth->getSignature()->args.begin(), e = meth->getSignature()->args.end(); i != e; ++i, ++index) { - NativeUtil::decapsulePrimitive(vm, buf, args->at(index), *i); + NativeUtil::decapsulePrimitive(vm, buf, ptr[index], *i); } JavaObject* exc = 0; Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaArray.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaArray.cpp?rev=52410&r1=52409&r2=52410&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaArray.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaArray.cpp Tue Jun 17 10:40:30 2008 @@ -46,147 +46,48 @@ extern "C" void outOfMemoryError(sint32 val); #ifndef MULTIPLE_VM -#define ACONS(name, elmt, primSize) \ +#define ACONS(name, elmt, primSize, VT) \ name *name::acons(sint32 n, ClassArray* atype, Jnjvm* vm) { \ if (n < 0) \ negativeArraySizeException(n); \ else if (n > JavaArray::MaxArraySize) \ outOfMemoryError(n); \ name* res = (name*) \ - (Object*) operator new(sizeof(name) + n * primSize, name::VT); \ + (Object*) operator new(sizeof(name) + n * primSize, VT); \ res->initialise(atype); \ res->size = n; \ return res; \ } #else -#define ACONS(name, elmt, primSize) \ +#define ACONS(name, elmt, primSize, VT) \ name *name::acons(sint32 n, ClassArray* atype, Jnjvm* vm) { \ if (n < 0) \ negativeArraySizeException(n); \ else if (n > JavaArray::MaxArraySize) \ outOfMemoryError(n); \ name* res = (name*) \ - (Object*) vm->allocateObject(sizeof(name) + n * primSize, name::VT); \ + (Object*) vm->allocateObject(sizeof(name) + n * primSize, VT); \ res->initialise(atype); \ res->size = n; \ return res; \ } #endif -#define AT(name, elmt) \ - elmt name::at(sint32 offset) const { \ - if (offset >= size) \ - JavaThread::get()->isolate->indexOutOfBounds(this, offset); \ - return elements[offset]; \ - } \ - void name::setAt(sint32 offset, elmt value) { \ - if (offset >= size) \ - JavaThread::get()->isolate->indexOutOfBounds(this, offset); \ - elements[offset] = value; \ - } - -#define ARRAYCLASS(name, elmt, size) \ - ACONS(name, elmt, size) \ - AT(name, elmt) \ - -ARRAYCLASS(ArrayUInt8, uint8, 1) -ARRAYCLASS(ArraySInt8, sint8, 1) -ARRAYCLASS(ArrayUInt16, uint16, 2) -ARRAYCLASS(ArraySInt16, sint16, 2) -ARRAYCLASS(ArrayUInt32, uint32, 4) -ARRAYCLASS(ArraySInt32, sint32, 4) -ARRAYCLASS(ArrayLong, sint64, 8) -ARRAYCLASS(ArrayFloat, float, 4) -ARRAYCLASS(ArrayDouble, double, 8) -ARRAYCLASS(ArrayObject, JavaObject*, sizeof(JavaObject*)) +ACONS(ArrayUInt8, uint8, 1, JavaArray::VT) +ACONS(ArraySInt8, sint8, 1, JavaArray::VT) +ACONS(ArrayUInt16, uint16, 2, JavaArray::VT) +ACONS(ArraySInt16, sint16, 2, JavaArray::VT) +ACONS(ArrayUInt32, uint32, 4, JavaArray::VT) +ACONS(ArraySInt32, sint32, 4, JavaArray::VT) +ACONS(ArrayLong, sint64, 8, JavaArray::VT) +ACONS(ArrayFloat, float, 4, JavaArray::VT) +ACONS(ArrayDouble, double, 8, JavaArray::VT) +ACONS(ArrayObject, JavaObject*, sizeof(JavaObject*), ArrayObject::VT) #undef ARRAYCLASS #undef ACONS -#undef AT -void ArrayUInt8::print(mvm::PrintBuffer *buf) const { - buf->write("Array<"); - for (int i = 0; i < size; i++) { - buf->writeS4(elements[i]); - buf->write(" "); - } - buf->write(">"); -} - -void ArraySInt8::print(mvm::PrintBuffer *buf) const { - buf->write("Array<"); - for (int i = 0; i < size; i++) { - buf->writeS4(elements[i]); - buf->write(" "); - } - buf->write(">"); -} - -void ArraySInt16::print(mvm::PrintBuffer *buf) const { - buf->write("Array<"); - for (int i = 0; i < size; i++) { - buf->writeS4(elements[i]); - buf->write(" "); - } - buf->write(">"); -} - -void ArrayUInt32::print(mvm::PrintBuffer *buf) const { - buf->write("Array<"); - for (int i = 0; i < size; i++) { - buf->writeS4(elements[i]); - buf->write(" "); - } - buf->write(">"); -} - -void ArraySInt32::print(mvm::PrintBuffer *buf) const { - buf->write("Array<"); - for (int i = 0; i < size; i++) { - buf->writeS4(elements[i]); - buf->write(" "); - } - buf->write(">"); -} - -void ArrayLong::print(mvm::PrintBuffer *buf) const { - buf->write("Array<"); - for (int i = 0; i < size; i++) { - buf->writeS8(elements[i]); - buf->write(" "); - } - buf->write(">"); -} - -void ArrayFloat::print(mvm::PrintBuffer *buf) const { - buf->write("Array<"); - for (int i = 0; i < size; i++) { - buf->writeFP(elements[i]); - buf->write(" "); - } - buf->write(">"); -} - -void ArrayDouble::print(mvm::PrintBuffer *buf) const { - buf->write("Array<"); - for (int i = 0; i < size; i++) { - buf->writeFP(elements[i]); - buf->write(" "); - } - buf->write(">"); -} - -void ArrayObject::print(mvm::PrintBuffer *buf) const { - buf->write("Array<"); - for (int i = 0; i < size; i++) { - buf->writeObj(elements[i]); - buf->write(" "); - } - buf->write(">"); -} - - -void ArrayUInt16::print(mvm::PrintBuffer* buf) const { +void UTF8::print(mvm::PrintBuffer* buf) const { for (int i = 0; i < size; i++) buf->writeChar((char)elements[i]); } Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaArray.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaArray.h?rev=52410&r1=52409&r2=52410&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaArray.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaArray.h Tue Jun 17 10:40:30 2008 @@ -23,10 +23,17 @@ class JavaObject; class Jnjvm; -class JavaArray : public JavaObject { +template +class TJavaArray : public JavaObject { public: sint32 size; - void* elements[0]; + T elements[0]; +}; + +class JavaArray : public TJavaArray { +public: + static VirtualTable *VT; + static const sint32 MaxArraySize; static const unsigned int T_BOOLEAN; static const unsigned int T_CHAR; @@ -47,20 +54,16 @@ static ClassArray* ofFloat; static ClassArray* ofDouble; static ClassArray* ofObject; + + virtual void TRACER; + }; -#define ARRAYCLASS(name, elmt) \ -class name : public JavaObject { \ -public: \ - static VirtualTable* VT; \ - sint32 size; \ - elmt elements[0]; \ - static name *acons(sint32 n, ClassArray* cl, Jnjvm* vm); \ - elmt at(sint32) const; \ - void setAt(sint32, elmt); \ - virtual void print(mvm::PrintBuffer* buf) const; \ - virtual void TRACER; \ -} +#define ARRAYCLASS(name, elmt) \ + class name : public TJavaArray { \ + public: \ + static name* acons(sint32 n, ClassArray* cl, Jnjvm* vm); \ + }; ARRAYCLASS(ArrayUInt8, uint8); ARRAYCLASS(ArraySInt8, sint8); @@ -71,10 +74,16 @@ ARRAYCLASS(ArrayLong, sint64); ARRAYCLASS(ArrayFloat, float); ARRAYCLASS(ArrayDouble, double); -ARRAYCLASS(ArrayObject, JavaObject*); #undef ARRAYCLASS +class ArrayObject : public TJavaArray { +public: + static VirtualTable *VT; + static ArrayObject* acons(sint32 n, ClassArray* cl, Jnjvm* vm); + virtual void TRACER; +}; + class UTF8 : public ArrayUInt16 { public: @@ -102,6 +111,8 @@ else return !memcmp(elements, other->elements, size * sizeof(uint16)); } #endif + + virtual void print(mvm::PrintBuffer* buf) const; }; } // end namespace jnjvm Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp?rev=52410&r1=52409&r2=52410&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp Tue Jun 17 10:40:30 2008 @@ -59,18 +59,11 @@ X fake; \ void* V = ((void**)(void*)(&fake))[0]; \ X::VT = (VirtualTable*)malloc(12 * sizeof(void*) + VT_SIZE); \ + ((void**)X::VT)[0] = 0; \ memcpy(X::VT, V, VT_SIZE); } INIT(JavaObject); - INIT(ArrayUInt8); - INIT(ArraySInt8); - INIT(ArrayUInt16); - INIT(ArraySInt16); - INIT(ArrayUInt32); - INIT(ArraySInt32); - INIT(ArrayLong); - INIT(ArrayFloat); - INIT(ArrayDouble); + INIT(JavaArray); INIT(ArrayObject); #undef INIT } Modified: vmkit/trunk/lib/JnJVM/VMCore/Jni.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/Jni.cpp?rev=52410&r1=52409&r2=52410&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/Jni.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/Jni.cpp Tue Jun 17 10:40:30 2008 @@ -1642,8 +1642,11 @@ jobject GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index) { BEGIN_EXCEPTION - return (jobject)((ArrayObject*)array)->at(index); - + ArrayObject* JA = (ArrayObject*)array; + if (index >= JA->size) + JavaThread::get()->isolate->indexOutOfBounds(JA, index); + return (jobject)JA->elements[index]; + END_EXCEPTION return 0; @@ -1655,7 +1658,10 @@ BEGIN_EXCEPTION - ((ArrayObject*)array)->setAt(index, (JavaObject*)val); + ArrayObject* JA = (ArrayObject*)array; + if (index >= JA->size) + JavaThread::get()->isolate->indexOutOfBounds(JA, index); + JA->elements[index] = (JavaObject*)val; END_EXCEPTION } Modified: vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp?rev=52410&r1=52409&r2=52410&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/VirtualTables.cpp Tue Jun 17 10:40:30 2008 @@ -12,11 +12,9 @@ #include "JavaArray.h" #include "JavaCache.h" #include "JavaClass.h" -#include "JavaConstantPool.h" #include "JavaIsolate.h" #include "JavaObject.h" #include "JavaThread.h" -#include "JavaTypes.h" #include "Jnjvm.h" #include "LockedMap.h" #ifdef SERVICE_VM @@ -27,15 +25,7 @@ #define INIT(X) VirtualTable* X::VT = 0 - INIT(ArrayUInt8); - INIT(ArraySInt8); - INIT(ArrayUInt16); - INIT(ArraySInt16); - INIT(ArrayUInt32); - INIT(ArraySInt32); - INIT(ArrayLong); - INIT(ArrayFloat); - INIT(ArrayDouble); + INIT(JavaArray); INIT(ArrayObject); INIT(CommonClass); INIT(Class); @@ -60,23 +50,7 @@ } } -#define ARRAYTRACER(name) \ - void name::TRACER { \ - } - - -ARRAYTRACER(ArrayUInt8); -ARRAYTRACER(ArraySInt8); -ARRAYTRACER(ArrayUInt16); -ARRAYTRACER(ArraySInt16); -ARRAYTRACER(ArrayUInt32); -ARRAYTRACER(ArraySInt32); -ARRAYTRACER(ArrayLong); -ARRAYTRACER(ArrayFloat); -ARRAYTRACER(ArrayDouble); - -#undef ARRAYTRACER - +void JavaArray::TRACER {} #define TRACE_VECTOR(type,alloc,name) { \ for (std::vector >::iterator i = name.begin(), \ From matthijs at stdin.nl Tue Jun 17 10:54:53 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Tue, 17 Jun 2008 17:54:53 +0200 Subject: [llvm-commits] Dead argument elimination rewrite In-Reply-To: <20080617084400.GC16202@katherina.student.utwente.nl> References: <20080616153738.GN2636@katherina.student.utwente.nl> <20080617084400.GC16202@katherina.student.utwente.nl> Message-ID: <20080617155453.GF16202@katherina.student.utwente.nl> Hi Dan, here's the updated version of the patch, only minor changes were made. I also added my testcase. If you have no other objections, I will commit this tomorrow. Gr. Matthijs -------------- next part -------------- A non-text attachment was scrubbed... Name: deadarg.diff Type: text/x-diff Size: 44644 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080617/fb1923a5/attachment.bin -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: Digital signature Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080617/fb1923a5/attachment-0001.bin From baldrick at free.fr Tue Jun 17 10:55:30 2008 From: baldrick at free.fr (Duncan Sands) Date: Tue, 17 Jun 2008 15:55:30 -0000 Subject: [llvm-commits] [llvm] r52411 - /llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200806171555.m5HFtVes013599@zion.cs.uiuc.edu> Author: baldrick Date: Tue Jun 17 10:55:30 2008 New Revision: 52411 URL: http://llvm.org/viewvc/llvm-project?rev=52411&view=rev Log: Fix typo that changed the logic to something wrong. Spotted by Nick Lewycky. Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=52411&r1=52410&r2=52411&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Tue Jun 17 10:55:30 2008 @@ -8783,7 +8783,7 @@ // Conversion is ok if changing from one pointer type to another or from // a pointer to an integer of the same size. !((isa(OldRetTy) || OldRetTy == TD->getIntPtrType()) && - isa(NewRetTy) || NewRetTy == TD->getIntPtrType())) + (isa(NewRetTy) || NewRetTy == TD->getIntPtrType()))) return false; // Cannot transform this return value. if (!Caller->use_empty() && From nicolas.geoffray at lip6.fr Tue Jun 17 11:30:12 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 17 Jun 2008 16:30:12 -0000 Subject: [llvm-commits] [vmkit] r52412 - in /vmkit/trunk/lib/JnJVM/VMCore: JavaArray.cpp JavaArray.h LockedMap.h Message-ID: <200806171630.m5HGUCYg014842@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jun 17 11:30:12 2008 New Revision: 52412 URL: http://llvm.org/viewvc/llvm-project?rev=52412&view=rev Log: Custom allocation of UTF8. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaArray.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaArray.h vmkit/trunk/lib/JnJVM/VMCore/LockedMap.h Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaArray.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaArray.cpp?rev=52412&r1=52411&r2=52412&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaArray.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaArray.cpp Tue Jun 17 11:30:12 2008 @@ -150,14 +150,17 @@ return buf; } +void* UTF8::operator new(size_t sz, sint32 size) { + return malloc(sz + size * sizeof(uint16)); +} + const UTF8* UTF8::acons(sint32 n, ClassArray* cl, Jnjvm* vm) { if (n < 0) negativeArraySizeException(n); else if (n > JavaArray::MaxArraySize) outOfMemoryError(n); - UTF8* res = (UTF8*) malloc(sizeof(UTF8) + n * sizeof(uint16)); - ((void**)res)[0] = ArrayUInt16::VT; + UTF8* res = new (n) UTF8(); res->initialise(cl); res->size = n; - return (const UTF8*)res; + return (const UTF8*)res; } Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaArray.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaArray.h?rev=52412&r1=52411&r2=52412&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaArray.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaArray.h Tue Jun 17 11:30:12 2008 @@ -113,6 +113,7 @@ #endif virtual void print(mvm::PrintBuffer* buf) const; + void* operator new(size_t sz, sint32 size); }; } // end namespace jnjvm Modified: vmkit/trunk/lib/JnJVM/VMCore/LockedMap.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/LockedMap.h?rev=52412&r1=52411&r2=52412&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/LockedMap.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/LockedMap.h Tue Jun 17 11:30:12 2008 @@ -119,7 +119,7 @@ ~UTF8Map() { delete lock; for (iterator i = map.begin(), e = map.end(); i!= e; ++i) { - free((void*)i->second); + delete(i->second); } } From nicolas.geoffray at lip6.fr Tue Jun 17 11:34:17 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Tue, 17 Jun 2008 16:34:17 -0000 Subject: [llvm-commits] [vmkit] r52413 - in /vmkit/trunk/lib/JnJVM/VMCore: JavaArray.cpp JavaArray.h Message-ID: <200806171634.m5HGYHJj014956@zion.cs.uiuc.edu> Author: geoffray Date: Tue Jun 17 11:34:17 2008 New Revision: 52413 URL: http://llvm.org/viewvc/llvm-project?rev=52413&view=rev Log: Custom deallocation of UTF8. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaArray.cpp vmkit/trunk/lib/JnJVM/VMCore/JavaArray.h Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaArray.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaArray.cpp?rev=52413&r1=52412&r2=52413&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaArray.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaArray.cpp Tue Jun 17 11:34:17 2008 @@ -154,6 +154,10 @@ return malloc(sz + size * sizeof(uint16)); } +void UTF8::operator delete(void* obj) { + free(obj); +} + const UTF8* UTF8::acons(sint32 n, ClassArray* cl, Jnjvm* vm) { if (n < 0) negativeArraySizeException(n); Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaArray.h URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaArray.h?rev=52413&r1=52412&r2=52413&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaArray.h (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaArray.h Tue Jun 17 11:34:17 2008 @@ -114,6 +114,7 @@ virtual void print(mvm::PrintBuffer* buf) const; void* operator new(size_t sz, sint32 size); + void operator delete(void* obj); }; } // end namespace jnjvm From evan.cheng at apple.com Tue Jun 17 11:49:02 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 17 Jun 2008 16:49:02 -0000 Subject: [llvm-commits] [llvm] r52414 - /llvm/trunk/lib/ExecutionEngine/ExecutionEngine.cpp Message-ID: <200806171649.m5HGn2Uu015377@zion.cs.uiuc.edu> Author: evancheng Date: Tue Jun 17 11:49:02 2008 New Revision: 52414 URL: http://llvm.org/viewvc/llvm-project?rev=52414&view=rev Log: Don't forget to initialize SymbolSearchingDisabled. Modified: llvm/trunk/lib/ExecutionEngine/ExecutionEngine.cpp Modified: llvm/trunk/lib/ExecutionEngine/ExecutionEngine.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/ExecutionEngine.cpp?rev=52414&r1=52413&r2=52414&view=diff ============================================================================== --- llvm/trunk/lib/ExecutionEngine/ExecutionEngine.cpp (original) +++ llvm/trunk/lib/ExecutionEngine/ExecutionEngine.cpp Tue Jun 17 11:49:02 2008 @@ -40,6 +40,7 @@ ExecutionEngine::ExecutionEngine(ModuleProvider *P) : LazyFunctionCreator(0) { LazyCompilationDisabled = false; + SymbolSearchingDisabled = false; Modules.push_back(P); assert(P && "ModuleProvider is null?"); } From sabre at nondot.org Tue Jun 17 12:06:44 2008 From: sabre at nondot.org (Chris Lattner) Date: Tue, 17 Jun 2008 17:06:44 -0000 Subject: [llvm-commits] [llvm] r52415 - /llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp Message-ID: <200806171706.m5HH6i6b015863@zion.cs.uiuc.edu> Author: lattner Date: Tue Jun 17 12:06:43 2008 New Revision: 52415 URL: http://llvm.org/viewvc/llvm-project?rev=52415&view=rev Log: revert recent patch which is causing widespread breakage. Modified: llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp Modified: llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp?rev=52415&r1=52414&r2=52415&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp (original) +++ llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp Tue Jun 17 12:06:43 2008 @@ -21,7 +21,6 @@ #include "llvm/Instructions.h" #include "llvm/Module.h" #include "llvm/Pass.h" -#include "llvm/Analysis/ValueTracking.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/Compiler.h" #include "llvm/ADT/Statistic.h" @@ -141,14 +140,9 @@ } -// Check to see if this function returns one or more constants. If so, replace -// all callers that use those return values with the constant value. This will -// leave in the actual return values and instructions, but deadargelim will -// clean that up. -// -// Additionally if a function always returns one of its arguments directly, -// callers will be updated to use the value they pass in directly instead of -// using the return value. +// Check to see if this function returns a constant. If so, replace all callers +// that user the return value with the returned valued. If we can replace ALL +// callers, bool IPCP::PropagateConstantReturn(Function &F) { if (F.getReturnType() == Type::VoidTy) return false; // No return value. @@ -162,65 +156,48 @@ SmallVector RetVals; const StructType *STy = dyn_cast(F.getReturnType()); if (STy) - for (unsigned i = 0, e = STy->getNumElements(); i < e; ++i) - RetVals.push_back(UndefValue::get(STy->getElementType(i))); + RetVals.assign(STy->getNumElements(), 0); else - RetVals.push_back(UndefValue::get(F.getReturnType())); + RetVals.push_back(0); - unsigned NumNonConstant = 0; for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { - // Return type does not match operand type, this is an old style multiple - // return - bool OldReturn = (F.getReturnType() != RI->getOperand(0)->getType()); - + assert(RetVals.size() == RI->getNumOperands() && + "Invalid ReturnInst operands!"); for (unsigned i = 0, e = RetVals.size(); i != e; ++i) { - // Already found conflicting return values? + if (isa(RI->getOperand(i))) + continue; // Ignore + Constant *C = dyn_cast(RI->getOperand(i)); + if (C == 0) + return false; // Does not return a constant. + Value *RV = RetVals[i]; - if (!RV) - continue; - - // Find the returned value - Value *V; - if (!STy || OldReturn) - V = RI->getOperand(i); - else - V = FindInsertedValue(RI->getOperand(0), i); - - if (V) { - // Ignore undefs, we can change them into anything - if (isa(V)) - continue; - - // Try to see if all the rets return the same constant or argument. - if (isa(V) || isa(V)) { - if (isa(RV)) { - // No value found yet? Try the current one. - RetVals[i] = V; - continue; - } - // Returning the same value? Good. - if (RV == V) - continue; - } - } - // Different or no known return value? Don't propagate this return - // value. - RetVals[i] = 0; - // All values non constant? Stop looking. - if (++NumNonConstant == RetVals.size()) - return false; + if (RV == 0) + RetVals[i] = C; + else if (RV != C) + return false; // Does not return the same constant. } } - // If we got here, the function returns at least one constant value. Loop - // over all users, replacing any uses of the return value with the returned - // constant. + if (STy) { + for (unsigned i = 0, e = RetVals.size(); i < e; ++i) + if (RetVals[i] == 0) + RetVals[i] = UndefValue::get(STy->getElementType(i)); + } else { + assert(RetVals.size() == 1); + if (RetVals[0] == 0) + RetVals[0] = UndefValue::get(F.getReturnType()); + } + + // If we got here, the function returns a constant value. Loop over all + // users, replacing any uses of the return value with the returned constant. + bool ReplacedAllUsers = true; bool MadeChange = false; for (Value::use_iterator UI = F.use_begin(), E = F.use_end(); UI != E; ++UI) { // Make sure this is an invoke or call and that the use is for the callee. if (!(isa(*UI) || isa(*UI)) || UI.getOperandNo() != 0) { + ReplacedAllUsers = false; continue; } @@ -235,37 +212,28 @@ continue; } - for (Value::use_iterator I = Call->use_begin(), E = Call->use_end(); - I != E;) { - Instruction *Ins = dyn_cast(*I); - - // Increment now, so we can remove the use - ++I; - - // Not an instruction? Ignore - if (!Ins) - continue; - - // Find the index of the retval to replace with - int index = -1; - if (GetResultInst *GR = dyn_cast(Ins)) - index = GR->getIndex(); - else if (ExtractValueInst *EV = dyn_cast(Ins)) - if (EV->hasIndices()) - index = *EV->idx_begin(); - - // If this use uses a specific return value, and we have a replacement, - // replace it. - if (index != -1) { - Value *New = RetVals[index]; - if (New) { - if (Argument *A = dyn_cast(New)) - // Was an argument returned? Then find the corresponding argument in - // the call instruction and use that. Add 1 to the argument number - // to skipp the first argument (the function itself). - New = Call->getOperand(A->getArgNo() + 1); - Ins->replaceAllUsesWith(New); - Ins->eraseFromParent(); + while (!Call->use_empty()) { + GetResultInst *GR = cast(Call->use_back()); + GR->replaceAllUsesWith(RetVals[GR->getIndex()]); + GR->eraseFromParent(); + } + } + + // If we replace all users with the returned constant, and there can be no + // other callers of the function, replace the constant being returned in the + // function with an undef value. + if (ReplacedAllUsers && F.hasInternalLinkage()) { + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { + if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { + for (unsigned i = 0, e = RetVals.size(); i < e; ++i) { + Value *RetVal = RetVals[i]; + if (isa(RetVal)) + continue; + Value *RV = UndefValue::get(RetVal->getType()); + if (RI->getOperand(i) != RV) { + RI->setOperand(i, RV); + MadeChange = true; + } } } } From clattner at apple.com Tue Jun 17 12:07:53 2008 From: clattner at apple.com (Chris Lattner) Date: Tue, 17 Jun 2008 10:07:53 -0700 Subject: [llvm-commits] [llvm] r52415 - /llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp In-Reply-To: <200806171706.m5HH6i6b015863@zion.cs.uiuc.edu> References: <200806171706.m5HH6i6b015863@zion.cs.uiuc.edu> Message-ID: On Jun 17, 2008, at 10:06 AM, Chris Lattner wrote: > Author: lattner > Date: Tue Jun 17 12:06:43 2008 > New Revision: 52415 > > URL: http://llvm.org/viewvc/llvm-project?rev=52415&view=rev > Log: > revert recent patch which is causing widespread breakage. Here's a testcase: $ opt -ipconstprop bugpoint-reduced-simplified.bc -------------- next part -------------- A non-text attachment was scrubbed... Name: bugpoint-reduced-simplified.bc Type: application/octet-stream Size: 632 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080617/107521ce/attachment.obj From sabre at nondot.org Tue Jun 17 12:15:16 2008 From: sabre at nondot.org (Chris Lattner) Date: Tue, 17 Jun 2008 17:15:16 -0000 Subject: [llvm-commits] [test-suite] r52416 - /test-suite/trunk/Makefile.programs Message-ID: <200806171715.m5HHFGnR016094@zion.cs.uiuc.edu> Author: lattner Date: Tue Jun 17 12:15:16 2008 New Revision: 52416 URL: http://llvm.org/viewvc/llvm-project?rev=52416&view=rev Log: forgot to commit this last night :( Modified: test-suite/trunk/Makefile.programs Modified: test-suite/trunk/Makefile.programs URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/Makefile.programs?rev=52416&r1=52415&r2=52416&view=diff ============================================================================== --- test-suite/trunk/Makefile.programs (original) +++ test-suite/trunk/Makefile.programs Tue Jun 17 12:15:16 2008 @@ -219,7 +219,8 @@ LLCBETAOPTION := -sched=simple endif ifeq ($(ARCH),x86) -LLCBETAOPTION := -enable-sinking +LLCBETAOPTION := -enable-value-prop +#-enable-sinking #-schedule-livein-copies #-machine-licm #-new-coalescer-heuristic=true From asl at math.spbu.ru Tue Jun 17 12:30:05 2008 From: asl at math.spbu.ru (Anton Korobeynikov) Date: Tue, 17 Jun 2008 17:30:05 -0000 Subject: [llvm-commits] [llvm] r52418 - in /llvm/trunk: include/llvm/Target/TargetJITInfo.h lib/ExecutionEngine/JIT/JITEmitter.cpp lib/Target/PowerPC/PPCCodeEmitter.cpp lib/Target/PowerPC/PPCJITInfo.cpp lib/Target/PowerPC/PPCJITInfo.h Message-ID: <200806171730.m5HHU5k5016503@zion.cs.uiuc.edu> Author: asl Date: Tue Jun 17 12:30:05 2008 New Revision: 52418 URL: http://llvm.org/viewvc/llvm-project?rev=52418&view=rev Log: Provide generic hooks for icache invalidation. Add PPC implementation. Patch by Gary Benson! Modified: llvm/trunk/include/llvm/Target/TargetJITInfo.h llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp llvm/trunk/lib/Target/PowerPC/PPCCodeEmitter.cpp llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp llvm/trunk/lib/Target/PowerPC/PPCJITInfo.h Modified: llvm/trunk/include/llvm/Target/TargetJITInfo.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetJITInfo.h?rev=52418&r1=52417&r2=52418&view=diff ============================================================================== --- llvm/trunk/include/llvm/Target/TargetJITInfo.h (original) +++ llvm/trunk/include/llvm/Target/TargetJITInfo.h Tue Jun 17 12:30:05 2008 @@ -94,6 +94,11 @@ assert(NumRelocs == 0 && "This target does not have relocations!"); } + /// InvalidateInstructionCache - Before the JIT can run a block of code + // that has been emitted it must invalidate the instruction cache on some + // platforms. + virtual void InvalidateInstructionCache(const void *Addr, unsigned len) {} + /// needsGOT - Allows a target to specify that it would like the // JIT to manage a GOT for it. bool needsGOT() const { return useGOT; } Modified: llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp?rev=52418&r1=52417&r2=52418&view=diff ============================================================================== --- llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp (original) +++ llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp Tue Jun 17 12:30:05 2008 @@ -145,20 +145,6 @@ JITResolver *JITResolver::TheJITResolver = 0; -#if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \ - defined(__APPLE__) -extern "C" void sys_icache_invalidate(const void *Addr, size_t len); -#endif - -/// synchronizeICache - On some targets, the JIT emitted code must be -/// explicitly refetched to ensure correct execution. -static void synchronizeICache(const void *Addr, size_t len) { -#if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \ - defined(__APPLE__) - sys_icache_invalidate(Addr, len); -#endif -} - /// getFunctionStub - This returns a pointer to a function stub, creating /// one on demand as needed. void *JITResolver::getFunctionStub(Function *F) { @@ -756,7 +742,7 @@ } // Invalidate the icache if necessary. - synchronizeICache(FnStart, FnEnd-FnStart); + TheJIT->getJITInfo().InvalidateInstructionCache(FnStart, FnEnd-FnStart); // Add it to the JIT symbol table if the host wants it. AddFunctionToSymbolTable(F.getFunction()->getNameStart(), Modified: llvm/trunk/lib/Target/PowerPC/PPCCodeEmitter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCCodeEmitter.cpp?rev=52418&r1=52417&r2=52418&view=diff ============================================================================== --- llvm/trunk/lib/Target/PowerPC/PPCCodeEmitter.cpp (original) +++ llvm/trunk/lib/Target/PowerPC/PPCCodeEmitter.cpp Tue Jun 17 12:30:05 2008 @@ -80,10 +80,6 @@ return new PPCCodeEmitter(TM, MCE); } -#ifdef __APPLE__ -extern "C" void sys_icache_invalidate(const void *Addr, size_t len); -#endif - bool PPCCodeEmitter::runOnMachineFunction(MachineFunction &MF) { assert((MF.getTarget().getRelocationModel() != Reloc::Default || MF.getTarget().getRelocationModel() != Reloc::Static) && Modified: llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp?rev=52418&r1=52417&r2=52418&view=diff ============================================================================== --- llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp (original) +++ llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp Tue Jun 17 12:30:05 2008 @@ -330,12 +330,9 @@ extern "C" void sys_icache_invalidate(const void *Addr, size_t len); #endif -/// SyncICache - On PPC, the JIT emitted code must be explicitly refetched to -/// ensure correct execution. -static void SyncICache(const void *Addr, size_t len) { -#if defined(__POWERPC__) || defined (__ppc__) || defined(_POWER) - -#ifdef __APPLE__ +void PPCJITInfo::InvalidateInstructionCache(const void *Addr, unsigned len) { +#if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \ +defined(__APPLE__) sys_icache_invalidate(Addr, len); #elif defined(__GNUC__) const size_t LineSize = 32; @@ -352,8 +349,6 @@ asm volatile("icbi 0, %0" : : "r"(Line)); asm volatile("isync"); #endif - -#endif } void *PPCJITInfo::emitFunctionStub(const Function* F, void *Fn, @@ -372,7 +367,7 @@ MCE.emitWordBE(0); MCE.emitWordBE(0); EmitBranchToAt(Addr, (intptr_t)Fn, false, is64Bit); - SyncICache((void*)Addr, 7*4); + InvalidateInstructionCache((void*)Addr, 7*4); return MCE.finishFunctionStub(F); } @@ -400,7 +395,7 @@ MCE.emitWordBE(0); MCE.emitWordBE(0); EmitBranchToAt(BranchAddr, (intptr_t)Fn, true, is64Bit); - SyncICache((void*)Addr, 10*4); + InvalidateInstructionCache((void*)Addr, 10*4); return MCE.finishFunctionStub(F); } Modified: llvm/trunk/lib/Target/PowerPC/PPCJITInfo.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCJITInfo.h?rev=52418&r1=52417&r2=52418&view=diff ============================================================================== --- llvm/trunk/lib/Target/PowerPC/PPCJITInfo.h (original) +++ llvm/trunk/lib/Target/PowerPC/PPCJITInfo.h Tue Jun 17 12:30:05 2008 @@ -41,6 +41,11 @@ /// code. /// virtual void replaceMachineCodeForFunction(void *Old, void *New); + + /// InvalidateInstructionCache - Before the JIT can run a block of code + // that has been emitted it must invalidate the instruction cache on some + // platforms. + virtual void InvalidateInstructionCache(const void *Addr, unsigned len); }; } From clattner at apple.com Tue Jun 17 12:35:54 2008 From: clattner at apple.com (Chris Lattner) Date: Tue, 17 Jun 2008 10:35:54 -0700 Subject: [llvm-commits] [llvm] r52418 - in /llvm/trunk: include/llvm/Target/TargetJITInfo.h lib/ExecutionEngine/JIT/JITEmitter.cpp lib/Target/PowerPC/PPCCodeEmitter.cpp lib/Target/PowerPC/PPCJITInfo.cpp lib/Target/PowerPC/PPCJITInfo.h In-Reply-To: <200806171730.m5HHU5k5016503@zion.cs.uiuc.edu> References: <200806171730.m5HHU5k5016503@zion.cs.uiuc.edu> Message-ID: <68FA2859-6C1A-48A5-8756-2DD4BFEADB87@apple.com> On Jun 17, 2008, at 10:30 AM, Anton Korobeynikov wrote: > URL: http://llvm.org/viewvc/llvm-project?rev=52418&view=rev > Log: > Provide generic hooks for icache invalidation. Add PPC implementation. > Patch by Gary Benson! Shouldn't this be a function in libsystem? -Chris > > > Modified: > llvm/trunk/include/llvm/Target/TargetJITInfo.h > llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp > llvm/trunk/lib/Target/PowerPC/PPCCodeEmitter.cpp > llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp > llvm/trunk/lib/Target/PowerPC/PPCJITInfo.h > > Modified: llvm/trunk/include/llvm/Target/TargetJITInfo.h > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetJITInfo.h?rev=52418&r1=52417&r2=52418&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/trunk/include/llvm/Target/TargetJITInfo.h (original) > +++ llvm/trunk/include/llvm/Target/TargetJITInfo.h Tue Jun 17 > 12:30:05 2008 > @@ -94,6 +94,11 @@ > assert(NumRelocs == 0 && "This target does not have > relocations!"); > } > > + /// InvalidateInstructionCache - Before the JIT can run a block > of code > + // that has been emitted it must invalidate the instruction > cache on some > + // platforms. > + virtual void InvalidateInstructionCache(const void *Addr, > unsigned len) {} > + > /// needsGOT - Allows a target to specify that it would like the > // JIT to manage a GOT for it. > bool needsGOT() const { return useGOT; } > > Modified: llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp?rev=52418&r1=52417&r2=52418&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp (original) > +++ llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp Tue Jun 17 > 12:30:05 2008 > @@ -145,20 +145,6 @@ > > JITResolver *JITResolver::TheJITResolver = 0; > > -#if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) > && \ > - defined(__APPLE__) > -extern "C" void sys_icache_invalidate(const void *Addr, size_t len); > -#endif > - > -/// synchronizeICache - On some targets, the JIT emitted code must be > -/// explicitly refetched to ensure correct execution. > -static void synchronizeICache(const void *Addr, size_t len) { > -#if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) > && \ > - defined(__APPLE__) > - sys_icache_invalidate(Addr, len); > -#endif > -} > - > /// getFunctionStub - This returns a pointer to a function stub, > creating > /// one on demand as needed. > void *JITResolver::getFunctionStub(Function *F) { > @@ -756,7 +742,7 @@ > } > > // Invalidate the icache if necessary. > - synchronizeICache(FnStart, FnEnd-FnStart); > + TheJIT->getJITInfo().InvalidateInstructionCache(FnStart, FnEnd- > FnStart); > > // Add it to the JIT symbol table if the host wants it. > AddFunctionToSymbolTable(F.getFunction()->getNameStart(), > > Modified: llvm/trunk/lib/Target/PowerPC/PPCCodeEmitter.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCCodeEmitter.cpp?rev=52418&r1=52417&r2=52418&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/trunk/lib/Target/PowerPC/PPCCodeEmitter.cpp (original) > +++ llvm/trunk/lib/Target/PowerPC/PPCCodeEmitter.cpp Tue Jun 17 > 12:30:05 2008 > @@ -80,10 +80,6 @@ > return new PPCCodeEmitter(TM, MCE); > } > > -#ifdef __APPLE__ > -extern "C" void sys_icache_invalidate(const void *Addr, size_t len); > -#endif > - > bool PPCCodeEmitter::runOnMachineFunction(MachineFunction &MF) { > assert((MF.getTarget().getRelocationModel() != Reloc::Default || > MF.getTarget().getRelocationModel() != Reloc::Static) && > > Modified: llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp?rev=52418&r1=52417&r2=52418&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp (original) > +++ llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp Tue Jun 17 12:30:05 > 2008 > @@ -330,12 +330,9 @@ > extern "C" void sys_icache_invalidate(const void *Addr, size_t len); > #endif > > -/// SyncICache - On PPC, the JIT emitted code must be explicitly > refetched to > -/// ensure correct execution. > -static void SyncICache(const void *Addr, size_t len) { > -#if defined(__POWERPC__) || defined (__ppc__) || defined(_POWER) > - > -#ifdef __APPLE__ > +void PPCJITInfo::InvalidateInstructionCache(const void *Addr, > unsigned len) { > +#if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) > && \ > +defined(__APPLE__) > sys_icache_invalidate(Addr, len); > #elif defined(__GNUC__) > const size_t LineSize = 32; > @@ -352,8 +349,6 @@ > asm volatile("icbi 0, %0" : : "r"(Line)); > asm volatile("isync"); > #endif > - > -#endif > } > > void *PPCJITInfo::emitFunctionStub(const Function* F, void *Fn, > @@ -372,7 +367,7 @@ > MCE.emitWordBE(0); > MCE.emitWordBE(0); > EmitBranchToAt(Addr, (intptr_t)Fn, false, is64Bit); > - SyncICache((void*)Addr, 7*4); > + InvalidateInstructionCache((void*)Addr, 7*4); > return MCE.finishFunctionStub(F); > } > > @@ -400,7 +395,7 @@ > MCE.emitWordBE(0); > MCE.emitWordBE(0); > EmitBranchToAt(BranchAddr, (intptr_t)Fn, true, is64Bit); > - SyncICache((void*)Addr, 10*4); > + InvalidateInstructionCache((void*)Addr, 10*4); > return MCE.finishFunctionStub(F); > } > > > Modified: llvm/trunk/lib/Target/PowerPC/PPCJITInfo.h > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCJITInfo.h?rev=52418&r1=52417&r2=52418&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/trunk/lib/Target/PowerPC/PPCJITInfo.h (original) > +++ llvm/trunk/lib/Target/PowerPC/PPCJITInfo.h Tue Jun 17 12:30:05 > 2008 > @@ -41,6 +41,11 @@ > /// code. > /// > virtual void replaceMachineCodeForFunction(void *Old, void *New); > + > + /// InvalidateInstructionCache - Before the JIT can run a block > of code > + // that has been emitted it must invalidate the instruction > cache on some > + // platforms. > + virtual void InvalidateInstructionCache(const void *Addr, > unsigned len); > }; > } > > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From asl at math.spbu.ru Tue Jun 17 12:38:31 2008 From: asl at math.spbu.ru (Anton Korobeynikov) Date: Tue, 17 Jun 2008 17:38:31 -0000 Subject: [llvm-commits] [llvm] r52419 - /llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp Message-ID: <200806171738.m5HHcVkH016748@zion.cs.uiuc.edu> Author: asl Date: Tue Jun 17 12:38:31 2008 New Revision: 52419 URL: http://llvm.org/viewvc/llvm-project?rev=52419&view=rev Log: Unbreak non-PPC builds Modified: llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp Modified: llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp?rev=52419&r1=52418&r2=52419&view=diff ============================================================================== --- llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp (original) +++ llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp Tue Jun 17 12:38:31 2008 @@ -331,12 +331,12 @@ #endif void PPCJITInfo::InvalidateInstructionCache(const void *Addr, unsigned len) { -#if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \ -defined(__APPLE__) +#if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) +# if defined(__APPLE__) sys_icache_invalidate(Addr, len); -#elif defined(__GNUC__) +# elif defined(__GNUC__) const size_t LineSize = 32; - + const intptr_t Mask = ~(LineSize - 1); const intptr_t StartLine = ((intptr_t) Addr) & Mask; const intptr_t EndLine = ((intptr_t) Addr + len + LineSize - 1) & Mask; @@ -348,6 +348,7 @@ for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize) asm volatile("icbi 0, %0" : : "r"(Line)); asm volatile("isync"); +# endif #endif } From asl at math.spbu.ru Tue Jun 17 12:57:43 2008 From: asl at math.spbu.ru (Anton Korobeynikov) Date: Tue, 17 Jun 2008 17:57:43 -0000 Subject: [llvm-commits] [llvm] r52420 - /llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp Message-ID: <200806171757.m5HHvhAZ017406@zion.cs.uiuc.edu> Author: asl Date: Tue Jun 17 12:57:43 2008 New Revision: 52420 URL: http://llvm.org/viewvc/llvm-project?rev=52420&view=rev Log: Add one more 'magic' define :) Modified: llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp Modified: llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp?rev=52420&r1=52419&r2=52420&view=diff ============================================================================== --- llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp (original) +++ llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp Tue Jun 17 12:57:43 2008 @@ -331,7 +331,8 @@ #endif void PPCJITInfo::InvalidateInstructionCache(const void *Addr, unsigned len) { -#if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) +#if (defined(__POWERPC__) || defined (__ppc__) || \ + defined(_POWER) || defined(_ARCH_PPC)) # if defined(__APPLE__) sys_icache_invalidate(Addr, len); # elif defined(__GNUC__) From evan.cheng at apple.com Tue Jun 17 12:59:16 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 17 Jun 2008 17:59:16 -0000 Subject: [llvm-commits] [llvm] r52421 - /llvm/trunk/lib/CodeGen/LowerSubregs.cpp Message-ID: <200806171759.m5HHxG9H017459@zion.cs.uiuc.edu> Author: evancheng Date: Tue Jun 17 12:59:16 2008 New Revision: 52421 URL: http://llvm.org/viewvc/llvm-project?rev=52421&view=rev Log: It's not safe to remove SUBREG_TO_REG that looks like identity copies, e.g. movl %eax, %eax on x86-64 actually does a zero-extend. Modified: llvm/trunk/lib/CodeGen/LowerSubregs.cpp Modified: llvm/trunk/lib/CodeGen/LowerSubregs.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LowerSubregs.cpp?rev=52421&r1=52420&r2=52421&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/LowerSubregs.cpp (original) +++ llvm/trunk/lib/CodeGen/LowerSubregs.cpp Tue Jun 17 12:59:16 2008 @@ -108,20 +108,15 @@ DOUT << "subreg: CONVERTING: " << *MI; - if (DstSubReg == InsReg) { - // No need to insert an identify copy instruction. - DOUT << "subreg: eliminated!"; - } else { - // Insert sub-register copy - const TargetRegisterClass *TRC0= TRI.getPhysicalRegisterRegClass(DstSubReg); - const TargetRegisterClass *TRC1= TRI.getPhysicalRegisterRegClass(InsReg); - TII.copyRegToReg(*MBB, MI, DstSubReg, InsReg, TRC0, TRC1); + // Insert sub-register copy + const TargetRegisterClass *TRC0= TRI.getPhysicalRegisterRegClass(DstSubReg); + const TargetRegisterClass *TRC1= TRI.getPhysicalRegisterRegClass(InsReg); + TII.copyRegToReg(*MBB, MI, DstSubReg, InsReg, TRC0, TRC1); #ifndef NDEBUG - MachineBasicBlock::iterator dMI = MI; - DOUT << "subreg: " << *(--dMI); + MachineBasicBlock::iterator dMI = MI; + DOUT << "subreg: " << *(--dMI); #endif - } DOUT << "\n"; MBB->remove(MI); From resistor at mac.com Tue Jun 17 13:07:43 2008 From: resistor at mac.com (Owen Anderson) Date: Tue, 17 Jun 2008 18:07:43 -0000 Subject: [llvm-commits] [llvm] r52423 - /llvm/trunk/include/llvm/ADT/DenseMap.h Message-ID: <200806171807.m5HI7hum017759@zion.cs.uiuc.edu> Author: resistor Date: Tue Jun 17 13:07:43 2008 New Revision: 52423 URL: http://llvm.org/viewvc/llvm-project?rev=52423&view=rev Log: Fix use of placement new to actually use an address. Modified: llvm/trunk/include/llvm/ADT/DenseMap.h Modified: llvm/trunk/include/llvm/ADT/DenseMap.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/DenseMap.h?rev=52423&r1=52422&r2=52423&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/DenseMap.h (original) +++ llvm/trunk/include/llvm/ADT/DenseMap.h Tue Jun 17 13:07:43 2008 @@ -218,7 +218,7 @@ memcpy(Buckets, other.Buckets, other.NumBuckets * sizeof(BucketT)); else for (size_t i = 0; i < other.NumBuckets; ++i) { - new (Buckets[i].first) KeyT(other.Buckets[i].first); + new (&Buckets[i].first) KeyT(other.Buckets[i].first); if (!KeyInfoT::isEqual(Buckets[i].first, getEmptyKey()) && !KeyInfoT::isEqual(Buckets[i].first, getTombstoneKey())) new (&Buckets[i].second) ValueT(other.Buckets[i].second); From clattner at apple.com Tue Jun 17 13:16:05 2008 From: clattner at apple.com (Chris Lattner) Date: Tue, 17 Jun 2008 11:16:05 -0700 Subject: [llvm-commits] [llvm] r52421 - /llvm/trunk/lib/CodeGen/LowerSubregs.cpp In-Reply-To: <200806171759.m5HHxG9H017459@zion.cs.uiuc.edu> References: <200806171759.m5HHxG9H017459@zion.cs.uiuc.edu> Message-ID: On Jun 17, 2008, at 10:59 AM, Evan Cheng wrote: > Author: evancheng > Date: Tue Jun 17 12:59:16 2008 > New Revision: 52421 > > URL: http://llvm.org/viewvc/llvm-project?rev=52421&view=rev > Log: > It's not safe to remove SUBREG_TO_REG that looks like identity > copies, e.g. movl %eax, %eax on x86-64 actually does a zero-extend. It sounds like we need a "movl %eax, %eax" that is a copy, and a separate "movl %eax, %eax" machine instr that is a zeroextend. -Chris From resistor at mac.com Tue Jun 17 13:29:27 2008 From: resistor at mac.com (Owen Anderson) Date: Tue, 17 Jun 2008 18:29:27 -0000 Subject: [llvm-commits] [llvm] r52424 - in /llvm/trunk: include/llvm/Instruction.h lib/VMCore/Instruction.cpp Message-ID: <200806171829.m5HITRFt018482@zion.cs.uiuc.edu> Author: resistor Date: Tue Jun 17 13:29:27 2008 New Revision: 52424 URL: http://llvm.org/viewvc/llvm-project?rev=52424&view=rev Log: Add an insertBefore method for attaching previously unattached instructions, such as those created by clone(), to a basic block. Modified: llvm/trunk/include/llvm/Instruction.h llvm/trunk/lib/VMCore/Instruction.cpp Modified: llvm/trunk/include/llvm/Instruction.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Instruction.h?rev=52424&r1=52423&r2=52424&view=diff ============================================================================== --- llvm/trunk/include/llvm/Instruction.h (original) +++ llvm/trunk/include/llvm/Instruction.h Tue Jun 17 13:29:27 2008 @@ -102,6 +102,10 @@ /// void eraseFromParent(); + /// insertBefore - Insert an unlinked instructions into a basic block + /// immediately before the specified instruction. + void insertBefore(Instruction *InsertPos); + /// moveBefore - Unlink this instruction from its current basic block and /// insert it into the basic block that MovePos lives in, right before /// MovePos. Modified: llvm/trunk/lib/VMCore/Instruction.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Instruction.cpp?rev=52424&r1=52423&r2=52424&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/Instruction.cpp (original) +++ llvm/trunk/lib/VMCore/Instruction.cpp Tue Jun 17 13:29:27 2008 @@ -68,6 +68,12 @@ getParent()->getInstList().erase(this); } +/// insertBefore - Insert an unlinked instructions into a basic block +/// immediately before the specified instruction. +void Instruction::insertBefore(Instruction *InsertPos) { + InsertPos->getParent()->getInstList().insert(InsertPos, this); +} + /// moveBefore - Unlink this instruction from its current basic block and /// insert it into the basic block that MovePos lives in, right before /// MovePos. From kremenek at apple.com Tue Jun 17 14:12:43 2008 From: kremenek at apple.com (Ted Kremenek) Date: Tue, 17 Jun 2008 19:12:43 -0000 Subject: [llvm-commits] [llvm] r52425 - /llvm/trunk/lib/Support/FoldingSet.cpp Message-ID: <200806171912.m5HJChIF019942@zion.cs.uiuc.edu> Author: kremenek Date: Tue Jun 17 14:12:43 2008 New Revision: 52425 URL: http://llvm.org/viewvc/llvm-project?rev=52425&view=rev Log: Consistently set "Buckets[NumBuckets] = reinterpret_cast(-1)" throughout FoldingSet.cpp. Modified: llvm/trunk/lib/Support/FoldingSet.cpp Modified: llvm/trunk/lib/Support/FoldingSet.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/FoldingSet.cpp?rev=52425&r1=52424&r2=52425&view=diff ============================================================================== --- llvm/trunk/lib/Support/FoldingSet.cpp (original) +++ llvm/trunk/lib/Support/FoldingSet.cpp Tue Jun 17 14:12:43 2008 @@ -170,7 +170,7 @@ memset(Buckets, 0, NumBuckets*sizeof(void*)); // Set the very last bucket to be a non-null "pointer". - Buckets[NumBuckets] = reinterpret_cast(-2); + Buckets[NumBuckets] = reinterpret_cast(-1); } FoldingSetImpl::~FoldingSetImpl() { delete [] Buckets; From kremenek at apple.com Tue Jun 17 14:14:40 2008 From: kremenek at apple.com (Ted Kremenek) Date: Tue, 17 Jun 2008 19:14:40 -0000 Subject: [llvm-commits] [llvm] r52427 - /llvm/tags/checker/checker-38/ Message-ID: <200806171914.m5HJEe0V020031@zion.cs.uiuc.edu> Author: kremenek Date: Tue Jun 17 14:14:40 2008 New Revision: 52427 URL: http://llvm.org/viewvc/llvm-project?rev=52427&view=rev Log: Tagging checker-38. Added: llvm/tags/checker/checker-38/ - copied from r52426, llvm/trunk/ From evan.cheng at apple.com Tue Jun 17 14:24:56 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 17 Jun 2008 12:24:56 -0700 Subject: [llvm-commits] [llvm] r52421 - /llvm/trunk/lib/CodeGen/LowerSubregs.cpp In-Reply-To: References: <200806171759.m5HHxG9H017459@zion.cs.uiuc.edu> Message-ID: <280ED457-8CD9-4C1C-9B77-62BAF0F2A634@apple.com> Right. However, the current implementation separates SUBREG_TO_REG from INSERT_SUBREG. The later is allowed to be coalesced away, but not the former. For now, we'll use this distinction to determine whether it's possible to remove (what looks like) the identity copy. Evan On Jun 17, 2008, at 11:16 AM, Chris Lattner wrote: > > On Jun 17, 2008, at 10:59 AM, Evan Cheng wrote: > >> Author: evancheng >> Date: Tue Jun 17 12:59:16 2008 >> New Revision: 52421 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=52421&view=rev >> Log: >> It's not safe to remove SUBREG_TO_REG that looks like identity >> copies, e.g. movl %eax, %eax on x86-64 actually does a zero-extend. > > It sounds like we need a "movl %eax, %eax" that is a copy, and a > separate "movl %eax, %eax" machine instr that is a zeroextend. > > -Chris > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From clattner at apple.com Tue Jun 17 15:00:22 2008 From: clattner at apple.com (Chris Lattner) Date: Tue, 17 Jun 2008 13:00:22 -0700 Subject: [llvm-commits] [llvm] r52421 - /llvm/trunk/lib/CodeGen/LowerSubregs.cpp In-Reply-To: <280ED457-8CD9-4C1C-9B77-62BAF0F2A634@apple.com> References: <200806171759.m5HHxG9H017459@zion.cs.uiuc.edu> <280ED457-8CD9-4C1C-9B77-62BAF0F2A634@apple.com> Message-ID: <32F0DA38-BB52-4A49-AA45-CE601566A033@apple.com> On Jun 17, 2008, at 12:24 PM, Evan Cheng wrote: > Right. However, the current implementation separates SUBREG_TO_REG > from INSERT_SUBREG. The later is allowed to be coalesced away, but not > the former. For now, we'll use this distinction to determine whether > it's possible to remove (what looks like) the identity copy. Ok! -chris From evan.cheng at apple.com Tue Jun 17 15:11:16 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 17 Jun 2008 20:11:16 -0000 Subject: [llvm-commits] [llvm] r52430 - /llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp Message-ID: <200806172011.m5HKBHif021961@zion.cs.uiuc.edu> Author: evancheng Date: Tue Jun 17 15:11:16 2008 New Revision: 52430 URL: http://llvm.org/viewvc/llvm-project?rev=52430&view=rev Log: When extending a liveinterval by commuting, don't throw away the live ranges that are not affected. Modified: llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp Modified: llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp?rev=52430&r1=52429&r2=52430&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp (original) +++ llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp Tue Jun 17 15:11:16 2008 @@ -381,10 +381,21 @@ // simply extend BLR if CopyMI doesn't end the range. DOUT << "\nExtending: "; IntB.print(DOUT, tri_); - IntB.removeValNo(BValNo); + // Remove val#'s defined by copies that will be coalesced away. for (unsigned i = 0, e = BDeadValNos.size(); i != e; ++i) IntB.removeValNo(BDeadValNos[i]); - VNInfo *ValNo = IntB.getNextValue(AValNo->def, 0, li_->getVNInfoAllocator()); + + // Extend BValNo by merging in IntA live ranges of AValNo. Val# definition + // is updated. Kills are also updated. + VNInfo *ValNo = BValNo; + ValNo->def = AValNo->def; + ValNo->copy = NULL; + for (unsigned j = 0, ee = ValNo->kills.size(); j != ee; ++j) { + unsigned Kill = ValNo->kills[j]; + if (Kill != BLR->end) + BKills.push_back(Kill); + } + ValNo->kills.clear(); for (LiveInterval::iterator AI = IntA.begin(), AE = IntA.end(); AI != AE; ++AI) { if (AI->valno != AValNo) continue; From evan.cheng at apple.com Tue Jun 17 15:13:36 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 17 Jun 2008 20:13:36 -0000 Subject: [llvm-commits] [llvm] r52431 - /llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Message-ID: <200806172013.m5HKDap4022108@zion.cs.uiuc.edu> Author: evancheng Date: Tue Jun 17 15:13:36 2008 New Revision: 52431 URL: http://llvm.org/viewvc/llvm-project?rev=52431&view=rev Log: Live-through live interval is [mbb start, mbb end+1]. Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp?rev=52431&r1=52430&r2=52431&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp (original) +++ llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Tue Jun 17 15:13:36 2008 @@ -366,7 +366,7 @@ for (unsigned i = 0, e = vi.AliveBlocks.size(); i != e; ++i) { if (vi.AliveBlocks[i]) { LiveRange LR(getMBBStartIdx(i), - getMBBEndIdx(i), + getMBBEndIdx(i)+1, // MBB ends at -1. ValNo); interval.addRange(LR); DOUT << " +" << LR; From gohman at apple.com Tue Jun 17 16:07:56 2008 From: gohman at apple.com (Dan Gohman) Date: Tue, 17 Jun 2008 21:07:56 -0000 Subject: [llvm-commits] [llvm] r52432 - /llvm/trunk/lib/VMCore/Instructions.cpp Message-ID: <200806172107.m5HL7u3n024125@zion.cs.uiuc.edu> Author: djg Date: Tue Jun 17 16:07:55 2008 New Revision: 52432 URL: http://llvm.org/viewvc/llvm-project?rev=52432&view=rev Log: Implement the ExtractValueInst::getIndexedType that accepts one index value. Modified: llvm/trunk/lib/VMCore/Instructions.cpp Modified: llvm/trunk/lib/VMCore/Instructions.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Instructions.cpp?rev=52432&r1=52431&r2=52432&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/Instructions.cpp (original) +++ llvm/trunk/lib/VMCore/Instructions.cpp Tue Jun 17 16:07:55 2008 @@ -1460,6 +1460,12 @@ return CurIdx == NumIdx ? Agg : 0; } +const Type* ExtractValueInst::getIndexedType(const Type *Agg, + const unsigned Idx) { + const unsigned Idxs[1] = { Idx }; + return getIndexedType(Agg, &Idxs[0], 1); +} + ExtractValueInst::ExtractValueInst(Value *Agg, unsigned Idx, const std::string &Name, From resistor at mac.com Tue Jun 17 17:27:06 2008 From: resistor at mac.com (Owen Anderson) Date: Tue, 17 Jun 2008 22:27:06 -0000 Subject: [llvm-commits] [llvm] r52433 - /llvm/trunk/lib/Transforms/Scalar/GVN.cpp Message-ID: <200806172227.m5HMR6An026754@zion.cs.uiuc.edu> Author: resistor Date: Tue Jun 17 17:27:06 2008 New Revision: 52433 URL: http://llvm.org/viewvc/llvm-project?rev=52433&view=rev Log: We don't want to find dependencies within the same block in this case. It leads to incorrect results because we're detecting something at or after the call we're querying on. Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=52433&r1=52432&r2=52433&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Tue Jun 17 17:27:06 2008 @@ -492,7 +492,7 @@ return nextValueNumber++; } else if (I->second != MemoryDependenceAnalysis::NonLocal) { - if (DT->dominates(I->first, C->getParent())) { + if (DT->properlyDominates(I->first, C->getParent())) { if (CallInst* CD = dyn_cast(I->second)) cdep = CD; else { From jlerouge at apple.com Tue Jun 17 17:38:01 2008 From: jlerouge at apple.com (Julien Lerouge) Date: Tue, 17 Jun 2008 15:38:01 -0700 Subject: [llvm-commits] [llvm] r52377 - in /llvm/trunk/lib/Target/X86: X86ISelDAGToDAG.cpp X86ISelLowering.cpp In-Reply-To: <200806170201.m5H21N2U009669@zion.cs.uiuc.edu> References: <200806170201.m5H21N2U009669@zion.cs.uiuc.edu> Message-ID: <20080617223801.GA18540@pom.apple.com> Hello Evan, This patch seems to break llvm-gcc. Using the build_gcc script (builds the "Apple way"), I get a native i686 compiler that seems to have problem with -g option: t.c: int main () { int i = 0; return i; } $ ./gcc -g -o t t.c Cannot yet select llvm.dbg.declare: 0x41b0bee0: ch = declare 0x41b0baf0, 0x41b0be10, 0x41b0c440t.c:5: internal compiler error: Abort trap Please submit a full bug report, with preprocessed source if appropriate. See for instructions. I guess it has to do with the change in X86ISelLowering.cpp below ? Thanks, Julien On Tue, Jun 17, 2008 at 02:01:23AM +0000, Evan Cheng wrote: > Author: evancheng > Date: Mon Jun 16 21:01:22 2008 > New Revision: 52377 > > URL: http://llvm.org/viewvc/llvm-project?rev=52377&view=rev > Log: > Rather than avoiding to wrap ISD::DECLARE GV operand in X86ISD::Wrapper, simply handle it at dagisel time with x86 specific isel code. > > Modified: > llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp > llvm/trunk/lib/Target/X86/X86ISelLowering.cpp > > Modified: llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp?rev=52377&r1=52376&r2=52377&view=diff > > ============================================================================== > --- llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp (original) > +++ llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp Mon Jun 16 21:01:22 2008 > @@ -1578,6 +1578,28 @@ > return ResNode; > break; > } > + > + case ISD::DECLARE: { > + // Handle DECLARE nodes here because the second operand may have been > + // wrapped in X86ISD::Wrapper. > + SDOperand Chain = Node->getOperand(0); > + SDOperand N1 = Node->getOperand(1); > + SDOperand N2 = Node->getOperand(2); > + if (isa(N1) && > + N2.getOpcode() == X86ISD::Wrapper && > + isa(N2.getOperand(0))) { > + int FI = cast(N1)->getIndex(); > + GlobalValue *GV = > + cast(N2.getOperand(0))->getGlobal(); > + SDOperand Tmp1 = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); > + SDOperand Tmp2 = CurDAG->getTargetGlobalAddress(GV, TLI.getPointerTy()); > + AddToISelQueue(Chain); > + SDOperand Ops[] = { Tmp1, Tmp2, Chain }; > + return CurDAG->getTargetNode(TargetInstrInfo::DECLARE, > + MVT::Other, Ops, 3); > + } > + break; > + } > } > > SDNode *ResNode = SelectCode(N); > > Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=52377&r1=52376&r2=52377&view=diff > > ============================================================================== > --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) > +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Mon Jun 16 21:01:22 2008 > @@ -4173,9 +4173,6 @@ > X86TargetLowering::LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) { > GlobalValue *GV = cast(Op)->getGlobal(); > SDOperand Result = DAG.getTargetGlobalAddress(GV, getPointerTy()); > - // If it's a debug information descriptor, don't mess with it. > - if (DAG.isVerifiedDebugInfoDesc(Op)) > - return Result; > Result = DAG.getNode(X86ISD::Wrapper, getPointerTy(), Result); > // With PIC, the address is actually $g + Offset. > if (getTargetMachine().getRelocationModel() == Reloc::PIC_ && > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits -- Julien Lerouge PGP Key Id: 0xB1964A62 PGP Fingerprint: 392D 4BAD DB8B CE7F 4E5F FA3C 62DB 4AA7 B196 4A62 PGP Public Key from: keyserver.pgp.com From gohman at apple.com Tue Jun 17 18:25:49 2008 From: gohman at apple.com (Dan Gohman) Date: Tue, 17 Jun 2008 23:25:49 -0000 Subject: [llvm-commits] [llvm] r52434 - /llvm/trunk/lib/VMCore/Instructions.cpp Message-ID: <200806172325.m5HNPna8028752@zion.cs.uiuc.edu> Author: djg Date: Tue Jun 17 18:25:49 2008 New Revision: 52434 URL: http://llvm.org/viewvc/llvm-project?rev=52434&view=rev Log: In InsertValueInst's copy ctor, actually copy the operands. Modified: llvm/trunk/lib/VMCore/Instructions.cpp Modified: llvm/trunk/lib/VMCore/Instructions.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Instructions.cpp?rev=52434&r1=52433&r2=52434&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/Instructions.cpp (original) +++ llvm/trunk/lib/VMCore/Instructions.cpp Tue Jun 17 18:25:49 2008 @@ -1385,6 +1385,8 @@ : Instruction(IVI.getType(), InsertValue, OperandTraits::op_begin(this), 2), Indices(IVI.Indices) { + Op<0>() = IVI.getOperand(0); + Op<1>() = IVI.getOperand(1); } InsertValueInst::InsertValueInst(Value *Agg, From gohman at apple.com Tue Jun 17 18:38:43 2008 From: gohman at apple.com (Dan Gohman) Date: Tue, 17 Jun 2008 23:38:43 -0000 Subject: [llvm-commits] [llvm] r52435 - in /llvm/trunk: include/llvm/AutoUpgrade.h lib/VMCore/AutoUpgrade.cpp Message-ID: <200806172338.m5HNchbO029105@zion.cs.uiuc.edu> Author: djg Date: Tue Jun 17 18:38:43 2008 New Revision: 52435 URL: http://llvm.org/viewvc/llvm-project?rev=52435&view=rev Log: Auto-upgrade code for multiple-value return statements. This code isn't actually called yet. Modified: llvm/trunk/include/llvm/AutoUpgrade.h llvm/trunk/lib/VMCore/AutoUpgrade.cpp Modified: llvm/trunk/include/llvm/AutoUpgrade.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/AutoUpgrade.h?rev=52435&r1=52434&r2=52435&view=diff ============================================================================== --- llvm/trunk/include/llvm/AutoUpgrade.h (original) +++ llvm/trunk/include/llvm/AutoUpgrade.h Tue Jun 17 18:38:43 2008 @@ -35,6 +35,12 @@ /// so that it can update all calls to the old function. void UpgradeCallsToIntrinsic(Function* F); + /// This is an auto-upgrade hook for mutiple-value return statements. + /// This function auto-upgrades all such return statements in the given + /// function to use aggregate return values built with insertvalue + /// instructions. + void UpgradeMultipleReturnValues(Function *F); + } // End llvm namespace #endif Modified: llvm/trunk/lib/VMCore/AutoUpgrade.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/AutoUpgrade.cpp?rev=52435&r1=52434&r2=52435&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/AutoUpgrade.cpp (original) +++ llvm/trunk/lib/VMCore/AutoUpgrade.cpp Tue Jun 17 18:38:43 2008 @@ -391,3 +391,27 @@ } } +/// This is an auto-upgrade hook for mutiple-value return statements. +/// This function auto-upgrades all such return statements in the given +/// function to use aggregate return values built with insertvalue +/// instructions. +void llvm::UpgradeMultipleReturnValues(Function *CurrentFunction) { + for (Function::iterator I = CurrentFunction->begin(), + E = CurrentFunction->end(); I != E; ++I) { + BasicBlock *BB = I; + if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { + unsigned NumVals = RI->getNumOperands(); + if (NumVals > 1) { + std::vector Types(NumVals); + for (unsigned i = 0; i != NumVals; ++i) + Types[i] = RI->getOperand(i)->getType(); + const Type *ReturnType = StructType::get(Types); + Value *RV = UndefValue::get(ReturnType); + for (unsigned i = 0; i != NumVals; ++i) + RV = InsertValueInst::Create(RV, RI->getOperand(i), i, "mrv", RI); + ReturnInst::Create(RV, RI); + RI->eraseFromParent(); + } + } + } +} From dalej at apple.com Tue Jun 17 18:39:43 2008 From: dalej at apple.com (Dale Johannesen) Date: Tue, 17 Jun 2008 23:39:43 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r52436 - in /llvm-gcc-4.2/trunk/gcc: config/i386/llvm-i386-target.h config/i386/llvm-i386.cpp llvm-abi.h llvm-convert.cpp llvm-internal.h llvm-types.cpp Message-ID: <200806172339.m5HNdhW1029148@zion.cs.uiuc.edu> Author: johannes Date: Tue Jun 17 18:39:43 2008 New Revision: 52436 URL: http://llvm.org/viewvc/llvm-project?rev=52436&view=rev Log: X86-64 ABI. Handle returning structs like { struct {}x[4]; double y; } where the 1st word is allocated but not returned. Modified: llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386-target.h llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386.cpp llvm-gcc-4.2/trunk/gcc/llvm-abi.h llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp llvm-gcc-4.2/trunk/gcc/llvm-internal.h llvm-gcc-4.2/trunk/gcc/llvm-types.cpp Modified: llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386-target.h URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386-target.h?rev=52436&r1=52435&r2=52436&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386-target.h (original) +++ llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386-target.h Tue Jun 17 18:39:43 2008 @@ -116,10 +116,11 @@ /* LLVM_SCALAR_TYPE_FOR_STRUCT_RETURN - Return LLVM Type if X can be returned as a scalar, otherwise return NULL. */ -#define LLVM_SCALAR_TYPE_FOR_STRUCT_RETURN(X) \ - llvm_x86_scalar_type_for_struct_return(X) +#define LLVM_SCALAR_TYPE_FOR_STRUCT_RETURN(X, Y) \ + llvm_x86_scalar_type_for_struct_return((X), (Y)) -extern const Type *llvm_x86_scalar_type_for_struct_return(tree type); +extern const Type *llvm_x86_scalar_type_for_struct_return(tree type, + unsigned *Offset); /* LLVM_AGGR_TYPE_FOR_STRUCT_RETURN - Return LLVM Type if X can be returned as an aggregate, otherwise return NULL. */ Modified: llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386.cpp URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386.cpp?rev=52436&r1=52435&r2=52436&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/config/i386/llvm-i386.cpp Tue Jun 17 18:39:43 2008 @@ -941,17 +941,6 @@ if (llvm_x86_should_not_return_complex_in_memory(TreeType)) return true; - // FIXME: llvm x86-64 code generator is not able to handle return {i8, float} - bool foundInt = false; - unsigned STyElements = STy->getNumElements(); - for (unsigned i = 0; i < STyElements; ++i) { - const Type *ETy = STy->getElementType(i); - if (const ArrayType *ATy = dyn_cast(ETy)) - ETy = ATy->getElementType(); - if (ETy->isInteger()) - foundInt = true; - } - // Let gcc specific routine answer the question. enum x86_64_reg_class Class[MAX_CLASSES]; enum machine_mode Mode = ix86_getNaturalModeForType(TreeType); @@ -959,12 +948,15 @@ if (NumClasses == 0) return false; - if (NumClasses == 1 && foundInt) - return false; - if (NumClasses == 1 && (Class[0] == X86_64_INTEGERSI_CLASS || Class[0] == X86_64_INTEGER_CLASS)) - // This will fit in one i32 register. + // This will fit in one i64 register. + return false; + + if (NumClasses == 2 && + (Class[0] == X86_64_NO_CLASS || Class[1] == X86_64_NO_CLASS)) + // One word is padding which is not passed at all; treat this as returning + // the scalar type of the other word. return false; // Otherwise, use of multiple value return is OK. @@ -973,7 +965,8 @@ // llvm_x86_scalar_type_for_struct_return - Return LLVM type if TYPE // can be returned as a scalar, otherwise return NULL. -const Type *llvm_x86_scalar_type_for_struct_return(tree type) { +const Type *llvm_x86_scalar_type_for_struct_return(tree type, unsigned *Offset) { + *Offset = 0; const Type *Ty = ConvertType(type); unsigned Size = getTargetData().getABITypeSize(Ty); if (Size == 0) @@ -989,13 +982,67 @@ if (llvm_suitable_multiple_ret_value_type(Ty, type)) return NULL; - if (Size <= 8) - return Type::Int64Ty; - else if (Size <= 16) - return IntegerType::get(128); - else if (Size <= 32) - return IntegerType::get(256); + if (TARGET_64BIT) { + // This logic relies on llvm_suitable_multiple_ret_value_type to have + // removed anything not expected here. + enum x86_64_reg_class Class[MAX_CLASSES]; + enum machine_mode Mode = ix86_getNaturalModeForType(type); + int NumClasses = ix86_ClassifyArgument(Mode, type, Class, 0); + if (NumClasses == 0) + return Type::Int64Ty; + if (NumClasses == 1) { + if (Class[0] == X86_64_INTEGERSI_CLASS || + Class[0] == X86_64_INTEGER_CLASS) { + // one int register + HOST_WIDE_INT Bytes = + (Mode == BLKmode) ? int_size_in_bytes(type) : + (int) GET_MODE_SIZE(Mode); + if (Bytes>4) + return Type::Int64Ty; + else if (Bytes>2) + return Type::Int32Ty; + else if (Bytes>1) + return Type::Int16Ty; + else + return Type::Int8Ty; + } + assert(0 && "Unexpected type!"); + } + if (NumClasses == 2) { + if (Class[1] == X86_64_NO_CLASS) { + if (Class[0] == X86_64_INTEGER_CLASS || + Class[0] == X86_64_NO_CLASS || + Class[0] == X86_64_INTEGERSI_CLASS) + return Type::Int64Ty; + else if (Class[0] == X86_64_SSE_CLASS || Class[0] == X86_64_SSEDF_CLASS) + return Type::DoubleTy; + else if (Class[0] == X86_64_SSESF_CLASS) + return Type::FloatTy; + assert(0 && "Unexpected type!"); + } + if (Class[0] == X86_64_NO_CLASS) { + *Offset = 8; + if (Class[1] == X86_64_INTEGERSI_CLASS || + Class[1] == X86_64_INTEGER_CLASS) + return Type::Int64Ty; + else if (Class[1] == X86_64_SSE_CLASS || Class[1] == X86_64_SSEDF_CLASS) + return Type::DoubleTy; + else if (Class[1] == X86_64_SSESF_CLASS) + return Type::FloatTy; + assert(0 && "Unexpected type!"); + } + assert(0 && "Unexpected type!"); + } + assert(0 && "Unexpected type!"); + } else { + if (Size <= 8) + return Type::Int64Ty; + else if (Size <= 16) + return IntegerType::get(128); + else if (Size <= 32) + return IntegerType::get(256); + } return NULL; } Modified: llvm-gcc-4.2/trunk/gcc/llvm-abi.h URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-abi.h?rev=52436&r1=52435&r2=52436&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-abi.h (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-abi.h Tue Jun 17 18:39:43 2008 @@ -57,8 +57,10 @@ /// HandleAggregateResultAsScalar - This callback is invoked if the function /// returns an aggregate value by bit converting it to the specified scalar - /// type and returning that. - void HandleAggregateResultAsScalar(const Type *ScalarTy) {} + /// type and returning that. The bit conversion should start at byte Offset + /// within the struct, and ScalarTy is not necessarily big enough to cover + /// the entire struct. + void HandleAggregateResultAsScalar(const Type *ScalarTy, unsigned Offset=0) {} /// HandleAggregateResultAsAggregate - This callback is invoked if the function /// returns an aggregate value using multiple return values. @@ -197,9 +199,10 @@ // getLLVMScalarTypeForStructReturn - Return LLVM Type if TY can be // returned as a scalar, otherwise return NULL. This is the default // target independent implementation. -static const Type* getLLVMScalarTypeForStructReturn(tree type) { +static const Type* getLLVMScalarTypeForStructReturn(tree type, unsigned *Offset) { const Type *Ty = ConvertType(type); unsigned Size = getTargetData().getABITypeSize(Ty); + *Offset = 0; if (Size == 0) return Type::VoidTy; else if (Size == 1) @@ -309,8 +312,8 @@ // LLVM_SCALAR_TYPE_FOR_STRUCT_RETURN - Return LLVM Type if X can be // returned as a scalar, otherwise return NULL. #ifndef LLVM_SCALAR_TYPE_FOR_STRUCT_RETURN -#define LLVM_SCALAR_TYPE_FOR_STRUCT_RETURN(X) \ - getLLVMScalarTypeForStructReturn(X) +#define LLVM_SCALAR_TYPE_FOR_STRUCT_RETURN(X, Y) \ + getLLVMScalarTypeForStructReturn((X), (Y)) #endif // LLVM_AGGR_TYPE_FOR_STRUCT_RETURN - Return LLVM Type if X can be @@ -351,6 +354,7 @@ /// on the client that indicate how its pieces should be handled. This /// handles things like returning structures via hidden parameters. void HandleReturnType(tree type, tree fn, bool isBuiltin) { + unsigned Offset = 0; const Type *Ty = ConvertType(type); if (Ty->getTypeID() == Type::VectorTyID) { // Vector handling is weird on x86. In particular builtin and @@ -378,8 +382,9 @@ // aggregate. if (const Type *AggrTy = LLVM_AGGR_TYPE_FOR_STRUCT_RETURN(type)) C.HandleAggregateResultAsAggregate(AggrTy); - else if (const Type* ScalarTy = LLVM_SCALAR_TYPE_FOR_STRUCT_RETURN(type)) - C.HandleAggregateResultAsScalar(ScalarTy); + else if (const Type* ScalarTy = + LLVM_SCALAR_TYPE_FOR_STRUCT_RETURN(type, &Offset)) + C.HandleAggregateResultAsScalar(ScalarTy, Offset); else { assert(0 && "Unable to determine how to return this aggregate!"); abort(); Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp?rev=52436&r1=52435&r2=52436&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Tue Jun 17 18:39:43 2008 @@ -350,6 +350,7 @@ FnDecl = fndecl; Fn = 0; ReturnBB = UnwindBB = 0; + ReturnOffset = 0; if (TheDebugInfo) { expanded_location Location = expand_location(DECL_SOURCE_LOCATION (fndecl)); @@ -427,10 +428,11 @@ IRBuilder Builder; std::vector LocStack; std::vector NameStack; + unsigned Offset; FunctionPrologArgumentConversion(tree FnDecl, Function::arg_iterator &ai, const IRBuilder &B) - : FunctionDecl(FnDecl), AI(ai), Builder(B) {} + : FunctionDecl(FnDecl), AI(ai), Builder(B), Offset(0) {} void setName(const std::string &Name) { NameStack.push_back(Name); @@ -520,6 +522,10 @@ abort(); } + void HandleAggregateResultAsScalar(const Type *ScalarTy, unsigned Offset=0) { + this->Offset = Offset; + } + void EnterField(unsigned FieldNo, const llvm::Type *StructTy) { NameStack.push_back(NameStack.back()+"."+utostr(FieldNo)); @@ -696,6 +702,8 @@ // Handle the DECL_RESULT. ABIConverter.HandleReturnType(TREE_TYPE(TREE_TYPE(FnDecl)), FnDecl, DECL_BUILT_IN(FnDecl)); + // Remember this for use by FinishFunctionBody. + TheTreeToLLVM->ReturnOffset = Client.Offset; // Prepend the static chain (if any) to the list of arguments. tree Args = static_chain ? static_chain : DECL_ARGUMENTS(FnDecl); @@ -805,10 +813,16 @@ RetVals.push_back(E); } } else { - // Otherwise, this aggregate result must be something that is returned in - // a scalar register for this target. We must bit convert the aggregate - // to the specified scalar type, which we do by casting the pointer and - // loading. + // Otherwise, this aggregate result must be something that is returned + // in a scalar register for this target. We must bit convert the + // aggregate to the specified scalar type, which we do by casting the + // pointer and loading. The load does not necessarily start at the + // beginning of the aggregate (x86-64). + if (ReturnOffset) { + RetVal = BitCastToType(RetVal, PointerType::getUnqual(Type::Int8Ty)); + RetVal = Builder.CreateGEP(RetVal, + ConstantInt::get(TD.getIntPtrType(), ReturnOffset), "tmp"); + } RetVal = BitCastToType(RetVal, PointerType::getUnqual(Fn->getReturnType())); RetVal = Builder.CreateLoad(RetVal, "retval"); @@ -2383,6 +2397,7 @@ MemRef RetBuf; bool isShadowRet; bool isAggrRet; + unsigned Offset; FunctionCallArgumentConversion(SmallVector &ops, const FunctionType *FnTy, @@ -2391,7 +2406,7 @@ IRBuilder &b) : CallOperands(ops), FTy(FnTy), DestLoc(destloc), useReturnSlot(ReturnSlotOpt), Builder(b), isShadowRet(false), - isAggrRet(false) { } + isAggrRet(false), Offset(0) { } // Push the address of an argument. void pushAddress(Value *Loc) { @@ -2472,12 +2487,13 @@ /// HandleAggregateResultAsScalar - This callback is invoked if the function /// returns an aggregate value by bit converting it to the specified scalar /// type and returning that. - void HandleAggregateResultAsScalar(const Type *ScalarTy) { - // There is nothing to do here. + void HandleAggregateResultAsScalar(const Type *ScalarTy, + unsigned Offset = 0) { + this->Offset = Offset; } - /// HandleAggregateResultAsAggregate - This callback is invoked if the function - /// returns an aggregate value using multiple return values. + /// HandleAggregateResultAsAggregate - This callback is invoked if the + /// function returns an aggregate value using multiple return values. void HandleAggregateResultAsAggregate(const Type *AggrTy) { // There is nothing to do here. isAggrRet = true; @@ -2734,12 +2750,18 @@ // the current target specifies that the aggregate be returned in scalar // registers even though it is an aggregate. We must bitconvert the scalar // to the destination aggregate type. We do this by casting the DestLoc - // pointer and storing into it. + // pointer and storing into it. The store does not necessarily start at the + // beginning of the aggregate (x86-64). if (!DestLoc) return Call; // Normal scalar return. - Value *Ptr = BitCastToType(DestLoc->Ptr, - PointerType::getUnqual(Call->getType())); + Value *Ptr = DestLoc->Ptr; + if (Client.Offset) { + Ptr = BitCastToType(Ptr, PointerType::getUnqual(Type::Int8Ty)); + Ptr = Builder.CreateGEP(Ptr, + ConstantInt::get(TD.getIntPtrType(), Client.Offset), "tmp"); + } + Ptr = BitCastToType(Ptr, PointerType::getUnqual(Call->getType())); StoreInst *St = Builder.CreateStore(Call, Ptr, DestLoc->Volatile); St->setAlignment(DestLoc->Alignment); return 0; Modified: llvm-gcc-4.2/trunk/gcc/llvm-internal.h URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-internal.h?rev=52436&r1=52435&r2=52436&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-internal.h (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-internal.h Tue Jun 17 18:39:43 2008 @@ -274,6 +274,7 @@ Function *Fn; BasicBlock *ReturnBB; BasicBlock *UnwindBB; + unsigned ReturnOffset; // State that changes as the function is emitted. Modified: llvm-gcc-4.2/trunk/gcc/llvm-types.cpp URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-types.cpp?rev=52436&r1=52435&r2=52436&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-types.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-types.cpp Tue Jun 17 18:39:43 2008 @@ -936,10 +936,11 @@ unsigned &CallingConv; bool isShadowRet; bool KNRPromotion; + unsigned Offset; public: FunctionTypeConversion(PATypeHolder &retty, std::vector &AT, unsigned &CC, bool KNR) - : RetTy(retty), ArgTypes(AT), CallingConv(CC), KNRPromotion(KNR) { + : RetTy(retty), ArgTypes(AT), CallingConv(CC), KNRPromotion(KNR), Offset(0) { CallingConv = CallingConv::C; isShadowRet = false; } @@ -955,8 +956,9 @@ /// HandleAggregateResultAsScalar - This callback is invoked if the function /// returns an aggregate value by bit converting it to the specified scalar /// type and returning that. - void HandleAggregateResultAsScalar(const Type *ScalarTy) { + void HandleAggregateResultAsScalar(const Type *ScalarTy, unsigned Offset=0) { RetTy = ScalarTy; + this->Offset = Offset; } /// HandleAggregateResultAsAggregate - This callback is invoked if the function From dpatel at apple.com Tue Jun 17 21:12:10 2008 From: dpatel at apple.com (Devang Patel) Date: Wed, 18 Jun 2008 02:12:10 -0000 Subject: [llvm-commits] [llvm] r52437 - /llvm/trunk/include/llvm/Analysis/Dominators.h Message-ID: <200806180212.m5I2CAtC001097@zion.cs.uiuc.edu> Author: dpatel Date: Tue Jun 17 21:12:09 2008 New Revision: 52437 URL: http://llvm.org/viewvc/llvm-project?rev=52437&view=rev Log: Check empty dominance frontier. Modified: llvm/trunk/include/llvm/Analysis/Dominators.h Modified: llvm/trunk/include/llvm/Analysis/Dominators.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/Dominators.h?rev=52437&r1=52436&r2=52437&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/Dominators.h (original) +++ llvm/trunk/include/llvm/Analysis/Dominators.h Tue Jun 17 21:12:09 2008 @@ -944,6 +944,9 @@ // itself is not member of NewBB's dominance frontier. DominanceFrontier::iterator NewDFI = find(NewBB); DominanceFrontier::iterator DFI = find(BB); + // If BB was an entry block then its frontier is empty. + if (DFI == end()) + return; DominanceFrontier::DomSetType BBSet = DFI->second; for (DominanceFrontier::DomSetType::iterator BBSetI = BBSet.begin(), BBSetE = BBSet.end(); BBSetI != BBSetE; ++BBSetI) { From dpatel at apple.com Tue Jun 17 21:16:39 2008 From: dpatel at apple.com (Devang Patel) Date: Wed, 18 Jun 2008 02:16:39 -0000 Subject: [llvm-commits] [llvm] r52438 - in /llvm/trunk: lib/Transforms/Scalar/LoopUnswitch.cpp test/Transforms/LoopUnswitch/2008-06-17-DomFrontier.ll Message-ID: <200806180216.m5I2Gd2h001224@zion.cs.uiuc.edu> Author: dpatel Date: Tue Jun 17 21:16:38 2008 New Revision: 52438 URL: http://llvm.org/viewvc/llvm-project?rev=52438&view=rev Log: Preserve dominance frontier while trivially unswitching loop. Added: llvm/trunk/test/Transforms/LoopUnswitch/2008-06-17-DomFrontier.ll Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp?rev=52438&r1=52437&r2=52438&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp Tue Jun 17 21:16:38 2008 @@ -610,6 +610,23 @@ DT->changeImmediateDominator(NewExit, OrigPH); DT->changeImmediateDominator(NewPH, OrigPH); } + + if (DF) { + // NewExit is now part of NewPH and Loop Header's dominance + // frontier. + DominanceFrontier::iterator DFI = DF->find(NewPH); + if (DFI != DF->end()) + DF->addToFrontier(DFI, NewExit); + DFI = DF->find(L->getHeader()); + DF->addToFrontier(DFI, NewExit); + + // ExitBlock does not have successors then NewExit is part of + // its dominance frontier. + if (succ_begin(ExitBlock) == succ_end(ExitBlock)) { + DFI = DF->find(ExitBlock); + DF->addToFrontier(DFI, NewExit); + } + } LPM->deleteSimpleAnalysisValue(OrigPH->getTerminator(), L); OrigPH->getTerminator()->eraseFromParent(); Added: llvm/trunk/test/Transforms/LoopUnswitch/2008-06-17-DomFrontier.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnswitch/2008-06-17-DomFrontier.ll?rev=52438&view=auto ============================================================================== --- llvm/trunk/test/Transforms/LoopUnswitch/2008-06-17-DomFrontier.ll (added) +++ llvm/trunk/test/Transforms/LoopUnswitch/2008-06-17-DomFrontier.ll Tue Jun 17 21:16:38 2008 @@ -0,0 +1,22 @@ +; RUN: llvm-as < %s | opt -licm -loop-unswitch -disable-output + at g_56 = external global i16 ; [#uses=2] + +define i32 @func_67(i32 %p_68, i8 signext %p_69, i8 signext %p_71) nounwind { +entry: + br label %bb +bb: ; preds = %bb44, %entry + br label %bb3 +bb3: ; preds = %bb36, %bb + %bothcond = or i1 false, false ; [#uses=1] + br i1 %bothcond, label %bb29, label %bb19 +bb19: ; preds = %bb3 + br i1 false, label %bb36, label %bb29 +bb29: ; preds = %bb19, %bb3 + ret i32 0 +bb36: ; preds = %bb19 + store i16 0, i16* @g_56, align 2 + br i1 false, label %bb44, label %bb3 +bb44: ; preds = %bb44, %bb36 + %tmp46 = load i16* @g_56, align 2 ; [#uses=0] + br i1 false, label %bb, label %bb44 +} From evan.cheng at apple.com Tue Jun 17 21:48:27 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Wed, 18 Jun 2008 02:48:27 -0000 Subject: [llvm-commits] [llvm] r52439 - /llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp Message-ID: <200806180248.m5I2mRPa002112@zion.cs.uiuc.edu> Author: evancheng Date: Tue Jun 17 21:48:27 2008 New Revision: 52439 URL: http://llvm.org/viewvc/llvm-project?rev=52439&view=rev Log: Unbreak DECLARE isel in pic mode. Modified: llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp Modified: llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp?rev=52439&r1=52438&r2=52439&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp (original) +++ llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp Tue Jun 17 21:48:27 2008 @@ -1585,10 +1585,14 @@ SDOperand Chain = Node->getOperand(0); SDOperand N1 = Node->getOperand(1); SDOperand N2 = Node->getOperand(2); - if (isa(N1) && - N2.getOpcode() == X86ISD::Wrapper && + if (!isa(N1)) + break; + int FI = cast(N1)->getIndex(); + if (N2.getOpcode() == ISD::ADD && + N2.getOperand(0).getOpcode() == X86ISD::GlobalBaseReg) + N2 = N2.getOperand(1); + if (N2.getOpcode() == X86ISD::Wrapper && isa(N2.getOperand(0))) { - int FI = cast(N1)->getIndex(); GlobalValue *GV = cast(N2.getOperand(0))->getGlobal(); SDOperand Tmp1 = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy()); From evan.cheng at apple.com Tue Jun 17 21:48:38 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 17 Jun 2008 19:48:38 -0700 Subject: [llvm-commits] [llvm] r52377 - in /llvm/trunk/lib/Target/X86: X86ISelDAGToDAG.cpp X86ISelLowering.cpp In-Reply-To: <20080617223801.GA18540@pom.apple.com> References: <200806170201.m5H21N2U009669@zion.cs.uiuc.edu> <20080617223801.GA18540@pom.apple.com> Message-ID: Oops. This is fixed. Evan On Jun 17, 2008, at 3:38 PM, Julien Lerouge wrote: > Hello Evan, > > This patch seems to break llvm-gcc. Using the build_gcc script (builds > the "Apple way"), I get a native i686 compiler that seems to have > problem with -g option: > > t.c: > int main () > { > int i = 0; > return i; > } > > $ ./gcc -g -o t t.c > Cannot yet select llvm.dbg.declare: 0x41b0bee0: ch = declare > 0x41b0baf0, 0x41b0be10, 0x41b0c440t.c:5: internal compiler error: > Abort trap > Please submit a full bug report, > with preprocessed source if appropriate. > See for instructions. > > I guess it has to do with the change in X86ISelLowering.cpp below ? > > Thanks, > Julien > > On Tue, Jun 17, 2008 at 02:01:23AM +0000, Evan Cheng wrote: >> Author: evancheng >> Date: Mon Jun 16 21:01:22 2008 >> New Revision: 52377 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=52377&view=rev >> Log: >> Rather than avoiding to wrap ISD::DECLARE GV operand in >> X86ISD::Wrapper, simply handle it at dagisel time with x86 specific >> isel code. >> >> Modified: >> llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp >> llvm/trunk/lib/Target/X86/X86ISelLowering.cpp >> >> Modified: llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp?rev=52377&r1=52376&r2=52377&view=diff >> >> = >> = >> = >> = >> = >> = >> = >> = >> = >> ===================================================================== >> --- llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp (original) >> +++ llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp Mon Jun 16 >> 21:01:22 2008 >> @@ -1578,6 +1578,28 @@ >> return ResNode; >> break; >> } >> + >> + case ISD::DECLARE: { >> + // Handle DECLARE nodes here because the second operand may >> have been >> + // wrapped in X86ISD::Wrapper. >> + SDOperand Chain = Node->getOperand(0); >> + SDOperand N1 = Node->getOperand(1); >> + SDOperand N2 = Node->getOperand(2); >> + if (isa(N1) && >> + N2.getOpcode() == X86ISD::Wrapper && >> + isa(N2.getOperand(0))) { >> + int FI = cast(N1)->getIndex(); >> + GlobalValue *GV = >> + cast(N2.getOperand(0))->getGlobal(); >> + SDOperand Tmp1 = CurDAG->getTargetFrameIndex(FI, >> TLI.getPointerTy()); >> + SDOperand Tmp2 = CurDAG->getTargetGlobalAddress(GV, >> TLI.getPointerTy()); >> + AddToISelQueue(Chain); >> + SDOperand Ops[] = { Tmp1, Tmp2, Chain }; >> + return CurDAG->getTargetNode(TargetInstrInfo::DECLARE, >> + MVT::Other, Ops, 3); >> + } >> + break; >> + } >> } >> >> SDNode *ResNode = SelectCode(N); >> >> Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=52377&r1=52376&r2=52377&view=diff >> >> = >> = >> = >> = >> = >> = >> = >> = >> = >> ===================================================================== >> --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) >> +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Mon Jun 16 >> 21:01:22 2008 >> @@ -4173,9 +4173,6 @@ >> X86TargetLowering::LowerGlobalAddress(SDOperand Op, SelectionDAG >> &DAG) { >> GlobalValue *GV = cast(Op)->getGlobal(); >> SDOperand Result = DAG.getTargetGlobalAddress(GV, getPointerTy()); >> - // If it's a debug information descriptor, don't mess with it. >> - if (DAG.isVerifiedDebugInfoDesc(Op)) >> - return Result; >> Result = DAG.getNode(X86ISD::Wrapper, getPointerTy(), Result); >> // With PIC, the address is actually $g + Offset. >> if (getTargetMachine().getRelocationModel() == Reloc::PIC_ && >> >> >> _______________________________________________ >> llvm-commits mailing list >> llvm-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > -- > Julien Lerouge > PGP Key Id: 0xB1964A62 > PGP Fingerprint: 392D 4BAD DB8B CE7F 4E5F FA3C 62DB 4AA7 B196 4A62 > PGP Public Key from: keyserver.pgp.com From sabre at nondot.org Tue Jun 17 23:00:49 2008 From: sabre at nondot.org (Chris Lattner) Date: Wed, 18 Jun 2008 04:00:49 -0000 Subject: [llvm-commits] [llvm] r52440 - in /llvm/trunk: lib/Transforms/Scalar/InstructionCombining.cpp test/Transforms/InstCombine/sext-misc.ll Message-ID: <200806180400.m5I40oUk004226@zion.cs.uiuc.edu> Author: lattner Date: Tue Jun 17 23:00:49 2008 New Revision: 52440 URL: http://llvm.org/viewvc/llvm-project?rev=52440&view=rev Log: make truncate/sext elimination capable of changing phi's. This implements rdar://6013816 and the testcase in Transforms/InstCombine/sext-misc.ll. Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp llvm/trunk/test/Transforms/InstCombine/sext-misc.ll Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=52440&r1=52439&r2=52440&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Tue Jun 17 23:00:49 2008 @@ -6838,6 +6838,16 @@ /// /// This is a truncation operation if Ty is smaller than V->getType(), or an /// extension operation if Ty is larger. +/// +/// If CastOpc is a truncation, then Ty will be a type smaller than V. We +/// should return true if trunc(V) can be computed by computing V in the smaller +/// type. If V is an instruction, then trunc(inst(x,y)) can be computed as +/// inst(trunc(x),trunc(y)), which only makes sense if x and y can be +/// efficiently truncated. +/// +/// If CastOpc is a sext or zext, we are asking if the low bits of the value can +/// bit computed in a larger type, which is then and'd or sext_in_reg'd to get +/// the final result. bool InstCombiner::CanEvaluateInDifferentType(Value *V, const IntegerType *Ty, unsigned CastOpc, int &NumCastsRemoved) { @@ -6858,7 +6868,7 @@ // If the first operand is itself a cast, and is eliminable, do not count // this as an eliminable cast. We would prefer to eliminate those two // casts first. - if (!isa(I->getOperand(0))) + if (!isa(I->getOperand(0)) && I->hasOneUse()) ++NumCastsRemoved; return true; } @@ -6923,8 +6933,17 @@ // of casts in the input. if (I->getOpcode() == CastOpc) return true; - break; + + case Instruction::PHI: { + // We can change a phi if we can change all operands. + PHINode *PN = cast(I); + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + if (!CanEvaluateInDifferentType(PN->getIncomingValue(i), Ty, CastOpc, + NumCastsRemoved)) + return false; + return true; + } default: // TODO: Can handle more cases here. break; @@ -6957,7 +6976,7 @@ Value *LHS = EvaluateInDifferentType(I->getOperand(0), Ty, isSigned); Value *RHS = EvaluateInDifferentType(I->getOperand(1), Ty, isSigned); Res = BinaryOperator::Create((Instruction::BinaryOps)I->getOpcode(), - LHS, RHS, I->getName()); + LHS, RHS); break; } case Instruction::Trunc: @@ -6969,16 +6988,27 @@ if (I->getOperand(0)->getType() == Ty) return I->getOperand(0); - // Otherwise, must be the same type of case, so just reinsert a new one. + // Otherwise, must be the same type of cast, so just reinsert a new one. Res = CastInst::Create(cast(I)->getOpcode(), I->getOperand(0), - Ty, I->getName()); + Ty); break; + case Instruction::PHI: { + PHINode *OPN = cast(I); + PHINode *NPN = PHINode::Create(Ty); + for (unsigned i = 0, e = OPN->getNumIncomingValues(); i != e; ++i) { + Value *V =EvaluateInDifferentType(OPN->getIncomingValue(i), Ty, isSigned); + NPN->addIncoming(V, OPN->getIncomingBlock(i)); + } + Res = NPN; + break; + } default: // TODO: Can handle more cases here. assert(0 && "Unreachable!"); break; } + Res->takeName(I); return InsertNewInstBefore(Res, *I); } Modified: llvm/trunk/test/Transforms/InstCombine/sext-misc.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/sext-misc.ll?rev=52440&r1=52439&r2=52440&view=diff ============================================================================== --- llvm/trunk/test/Transforms/InstCombine/sext-misc.ll (original) +++ llvm/trunk/test/Transforms/InstCombine/sext-misc.ll Tue Jun 17 23:00:49 2008 @@ -1,6 +1,4 @@ ; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep sext -; RUN: llvm-as < %s | llc -march=x86-64 | not grep movslq -; RUN: llvm-as < %s | llc -march=x86 | not grep sar declare i32 @llvm.ctpop.i32(i32) declare i32 @llvm.ctlz.i32(i32) @@ -50,3 +48,18 @@ %n = sext i16 %s to i32 ret i32 %n } + +; rdar://6013816 +define i16 @test(i16 %t, i1 %cond) nounwind { +entry: + br i1 %cond, label %T, label %F +T: + %t2 = sext i16 %t to i32 + br label %F + +F: + %V = phi i32 [%t2, %T], [42, %entry] + %W = trunc i32 %V to i16 + ret i16 %W +} + From sabre at nondot.org Tue Jun 17 23:03:23 2008 From: sabre at nondot.org (Chris Lattner) Date: Wed, 18 Jun 2008 04:03:23 -0000 Subject: [llvm-commits] [llvm] r52441 - /llvm/trunk/test/Transforms/IPConstantProp/return-constants.ll Message-ID: <200806180403.m5I43N4k004304@zion.cs.uiuc.edu> Author: lattner Date: Tue Jun 17 23:03:23 2008 New Revision: 52441 URL: http://llvm.org/viewvc/llvm-project?rev=52441&view=rev Log: temporarily revert this testcase since its patch was reverted. Modified: llvm/trunk/test/Transforms/IPConstantProp/return-constants.ll Modified: llvm/trunk/test/Transforms/IPConstantProp/return-constants.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/return-constants.ll?rev=52441&r1=52440&r2=52441&view=diff ============================================================================== --- llvm/trunk/test/Transforms/IPConstantProp/return-constants.ll (original) +++ llvm/trunk/test/Transforms/IPConstantProp/return-constants.ll Tue Jun 17 23:03:23 2008 @@ -1,41 +1,20 @@ -; RUN: llvm-as < %s | opt -ipconstprop | llvm-dis > %t -;; Check that the 21 constants got propagated properly -; RUN: cat %t | grep {%M = add i32 21, 21} -;; Check that the second return values didn't get propagated -; RUN: cat %t | grep {%N = add i32 %B, %D} +; RUN: llvm-as < %s | opt -ipconstprop | llvm-dis | grep {add i32 21, 21} -define internal {i32, i32} @foo(i1 %Q) { - br i1 %Q, label %T, label %F +define internal {i32, i32} @foo(i1 %C) { + br i1 %C, label %T, label %F T: ; preds = %0 - ret i32 21, i32 22 + ret i32 21, i32 21 F: ; preds = %0 - ret i32 21, i32 23 + ret i32 21, i32 21 } -define internal {i32, i32} @bar(i1 %Q) { - %A = insertvalue { i32, i32 } undef, i32 21, 0 - br i1 %Q, label %T, label %F - -T: ; preds = %0 - %B = insertvalue { i32, i32 } %A, i32 22, 1 - ret { i32, i32 } %B - -F: ; preds = %0 - %C = insertvalue { i32, i32 } %A, i32 23, 1 - ret { i32, i32 } %C -} - -define { i32, i32 } @caller(i1 %Q) { - %X = call {i32, i32} @foo( i1 %Q ) +define i32 @caller(i1 %C) { + %X = call {i32, i32} @foo( i1 %C ) %A = getresult {i32, i32} %X, 0 %B = getresult {i32, i32} %X, 1 - %Y = call {i32, i32} @bar( i1 %Q ) - %C = extractvalue {i32, i32} %Y, 0 - %D = extractvalue {i32, i32} %Y, 1 - %M = add i32 %A, %C - %N = add i32 %B, %D - ret { i32, i32 } %X + %Y = add i32 %A, %B + ret i32 %Y } From clattner at apple.com Tue Jun 17 23:05:57 2008 From: clattner at apple.com (Chris Lattner) Date: Tue, 17 Jun 2008 21:05:57 -0700 Subject: [llvm-commits] [llvm] r52432 - /llvm/trunk/lib/VMCore/Instructions.cpp In-Reply-To: <200806172107.m5HL7u3n024125@zion.cs.uiuc.edu> References: <200806172107.m5HL7u3n024125@zion.cs.uiuc.edu> Message-ID: <7CCE9A6A-F595-4A22-B366-D30627AA0274@apple.com> On Jun 17, 2008, at 2:07 PM, Dan Gohman wrote: > URL: http://llvm.org/viewvc/llvm-project?rev=52432&view=rev > Log: > Implement the ExtractValueInst::getIndexedType that accepts one > index value. Hey Dan: > +const Type* ExtractValueInst::getIndexedType(const Type *Agg, > + const unsigned Idx) { How about just "unsigned Idx". > > + const unsigned Idxs[1] = { Idx }; > + return getIndexedType(Agg, &Idxs[0], 1); Why not just: > + return getIndexedType(Agg, &Idx, 1); -Chris From sabre at nondot.org Tue Jun 17 23:33:21 2008 From: sabre at nondot.org (Chris Lattner) Date: Wed, 18 Jun 2008 04:33:21 -0000 Subject: [llvm-commits] [llvm] r52442 - in /llvm/trunk: lib/Transforms/Scalar/InstructionCombining.cpp test/Transforms/InstCombine/bswap-fold.ll Message-ID: <200806180433.m5I4XL48005145@zion.cs.uiuc.edu> Author: lattner Date: Tue Jun 17 23:33:20 2008 New Revision: 52442 URL: http://llvm.org/viewvc/llvm-project?rev=52442&view=rev Log: implement some simple bswap optimizations, rdar://5992453 Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp llvm/trunk/test/Transforms/InstCombine/bswap-fold.ll Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=52442&r1=52441&r2=52442&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Tue Jun 17 23:33:20 2008 @@ -1304,6 +1304,46 @@ KnownZero = APInt::getHighBitsSet(BitWidth, Leaders) & DemandedMask; break; } + case Instruction::Call: + if (IntrinsicInst *II = dyn_cast(I)) { + switch (II->getIntrinsicID()) { + default: break; + case Intrinsic::bswap: { + // If the only bits demanded come from one byte of the bswap result, + // just shift the input byte into position to eliminate the bswap. + unsigned NLZ = DemandedMask.countLeadingZeros(); + unsigned NTZ = DemandedMask.countTrailingZeros(); + + // Round NTZ down to the next byte. If we have 11 trailing zeros, then + // we need all the bits down to bit 8. Likewise, round NLZ. If we + // have 14 leading zeros, round to 8. + NLZ &= ~7; + NTZ &= ~7; + // If we need exactly one byte, we can do this transformation. + if (BitWidth-NLZ-NTZ == 8) { + unsigned ResultBit = NTZ; + unsigned InputBit = BitWidth-NTZ-8; + + // Replace this with either a left or right shift to get the byte into + // the right place. + Instruction *NewVal; + if (InputBit > ResultBit) + NewVal = BinaryOperator::CreateLShr(I->getOperand(1), + ConstantInt::get(I->getType(), InputBit-ResultBit)); + else + NewVal = BinaryOperator::CreateShl(I->getOperand(1), + ConstantInt::get(I->getType(), ResultBit-InputBit)); + NewVal->takeName(I); + InsertNewInstBefore(NewVal, *I); + return UpdateValueUsesWith(I, NewVal); + } + + // TODO: Could compute known zero/one bits based on the input. + break; + } + } + } + break; } // If the client is only demanding bits that we know, return the known @@ -8533,144 +8573,150 @@ } if (Changed) return II; - } else { - switch (II->getIntrinsicID()) { - default: break; - case Intrinsic::ppc_altivec_lvx: - case Intrinsic::ppc_altivec_lvxl: - case Intrinsic::x86_sse_loadu_ps: - case Intrinsic::x86_sse2_loadu_pd: - case Intrinsic::x86_sse2_loadu_dq: - // Turn PPC lvx -> load if the pointer is known aligned. - // Turn X86 loadups -> load if the pointer is known aligned. - if (GetOrEnforceKnownAlignment(II->getOperand(1), 16) >= 16) { - Value *Ptr = InsertBitCastBefore(II->getOperand(1), - PointerType::getUnqual(II->getType()), - CI); - return new LoadInst(Ptr); - } - break; - case Intrinsic::ppc_altivec_stvx: - case Intrinsic::ppc_altivec_stvxl: - // Turn stvx -> store if the pointer is known aligned. - if (GetOrEnforceKnownAlignment(II->getOperand(2), 16) >= 16) { - const Type *OpPtrTy = - PointerType::getUnqual(II->getOperand(1)->getType()); - Value *Ptr = InsertBitCastBefore(II->getOperand(2), OpPtrTy, CI); - return new StoreInst(II->getOperand(1), Ptr); - } - break; - case Intrinsic::x86_sse_storeu_ps: - case Intrinsic::x86_sse2_storeu_pd: - case Intrinsic::x86_sse2_storeu_dq: - case Intrinsic::x86_sse2_storel_dq: - // Turn X86 storeu -> store if the pointer is known aligned. - if (GetOrEnforceKnownAlignment(II->getOperand(1), 16) >= 16) { - const Type *OpPtrTy = - PointerType::getUnqual(II->getOperand(2)->getType()); - Value *Ptr = InsertBitCastBefore(II->getOperand(1), OpPtrTy, CI); - return new StoreInst(II->getOperand(2), Ptr); - } - break; - - case Intrinsic::x86_sse_cvttss2si: { - // These intrinsics only demands the 0th element of its input vector. If - // we can simplify the input based on that, do so now. - uint64_t UndefElts; - if (Value *V = SimplifyDemandedVectorElts(II->getOperand(1), 1, - UndefElts)) { - II->setOperand(1, V); - return II; - } - break; + } + + switch (II->getIntrinsicID()) { + default: break; + case Intrinsic::bswap: + // bswap(bswap(x)) -> x + if (IntrinsicInst *Operand = dyn_cast(II->getOperand(1))) + if (Operand->getIntrinsicID() == Intrinsic::bswap) + return ReplaceInstUsesWith(CI, Operand->getOperand(1)); + break; + case Intrinsic::ppc_altivec_lvx: + case Intrinsic::ppc_altivec_lvxl: + case Intrinsic::x86_sse_loadu_ps: + case Intrinsic::x86_sse2_loadu_pd: + case Intrinsic::x86_sse2_loadu_dq: + // Turn PPC lvx -> load if the pointer is known aligned. + // Turn X86 loadups -> load if the pointer is known aligned. + if (GetOrEnforceKnownAlignment(II->getOperand(1), 16) >= 16) { + Value *Ptr = InsertBitCastBefore(II->getOperand(1), + PointerType::getUnqual(II->getType()), + CI); + return new LoadInst(Ptr); + } + break; + case Intrinsic::ppc_altivec_stvx: + case Intrinsic::ppc_altivec_stvxl: + // Turn stvx -> store if the pointer is known aligned. + if (GetOrEnforceKnownAlignment(II->getOperand(2), 16) >= 16) { + const Type *OpPtrTy = + PointerType::getUnqual(II->getOperand(1)->getType()); + Value *Ptr = InsertBitCastBefore(II->getOperand(2), OpPtrTy, CI); + return new StoreInst(II->getOperand(1), Ptr); + } + break; + case Intrinsic::x86_sse_storeu_ps: + case Intrinsic::x86_sse2_storeu_pd: + case Intrinsic::x86_sse2_storeu_dq: + case Intrinsic::x86_sse2_storel_dq: + // Turn X86 storeu -> store if the pointer is known aligned. + if (GetOrEnforceKnownAlignment(II->getOperand(1), 16) >= 16) { + const Type *OpPtrTy = + PointerType::getUnqual(II->getOperand(2)->getType()); + Value *Ptr = InsertBitCastBefore(II->getOperand(1), OpPtrTy, CI); + return new StoreInst(II->getOperand(2), Ptr); } + break; + + case Intrinsic::x86_sse_cvttss2si: { + // These intrinsics only demands the 0th element of its input vector. If + // we can simplify the input based on that, do so now. + uint64_t UndefElts; + if (Value *V = SimplifyDemandedVectorElts(II->getOperand(1), 1, + UndefElts)) { + II->setOperand(1, V); + return II; + } + break; + } + + case Intrinsic::ppc_altivec_vperm: + // Turn vperm(V1,V2,mask) -> shuffle(V1,V2,mask) if mask is a constant. + if (ConstantVector *Mask = dyn_cast(II->getOperand(3))) { + assert(Mask->getNumOperands() == 16 && "Bad type for intrinsic!"); + + // Check that all of the elements are integer constants or undefs. + bool AllEltsOk = true; + for (unsigned i = 0; i != 16; ++i) { + if (!isa(Mask->getOperand(i)) && + !isa(Mask->getOperand(i))) { + AllEltsOk = false; + break; + } + } - case Intrinsic::ppc_altivec_vperm: - // Turn vperm(V1,V2,mask) -> shuffle(V1,V2,mask) if mask is a constant. - if (ConstantVector *Mask = dyn_cast(II->getOperand(3))) { - assert(Mask->getNumOperands() == 16 && "Bad type for intrinsic!"); + if (AllEltsOk) { + // Cast the input vectors to byte vectors. + Value *Op0 =InsertBitCastBefore(II->getOperand(1),Mask->getType(),CI); + Value *Op1 =InsertBitCastBefore(II->getOperand(2),Mask->getType(),CI); + Value *Result = UndefValue::get(Op0->getType()); + + // Only extract each element once. + Value *ExtractedElts[32]; + memset(ExtractedElts, 0, sizeof(ExtractedElts)); - // Check that all of the elements are integer constants or undefs. - bool AllEltsOk = true; for (unsigned i = 0; i != 16; ++i) { - if (!isa(Mask->getOperand(i)) && - !isa(Mask->getOperand(i))) { - AllEltsOk = false; - break; - } - } - - if (AllEltsOk) { - // Cast the input vectors to byte vectors. - Value *Op0 =InsertBitCastBefore(II->getOperand(1),Mask->getType(),CI); - Value *Op1 =InsertBitCastBefore(II->getOperand(2),Mask->getType(),CI); - Value *Result = UndefValue::get(Op0->getType()); - - // Only extract each element once. - Value *ExtractedElts[32]; - memset(ExtractedElts, 0, sizeof(ExtractedElts)); - - for (unsigned i = 0; i != 16; ++i) { - if (isa(Mask->getOperand(i))) - continue; - unsigned Idx=cast(Mask->getOperand(i))->getZExtValue(); - Idx &= 31; // Match the hardware behavior. - - if (ExtractedElts[Idx] == 0) { - Instruction *Elt = - new ExtractElementInst(Idx < 16 ? Op0 : Op1, Idx&15, "tmp"); - InsertNewInstBefore(Elt, CI); - ExtractedElts[Idx] = Elt; - } + if (isa(Mask->getOperand(i))) + continue; + unsigned Idx=cast(Mask->getOperand(i))->getZExtValue(); + Idx &= 31; // Match the hardware behavior. - // Insert this value into the result vector. - Result = InsertElementInst::Create(Result, ExtractedElts[Idx], - i, "tmp"); - InsertNewInstBefore(cast(Result), CI); + if (ExtractedElts[Idx] == 0) { + Instruction *Elt = + new ExtractElementInst(Idx < 16 ? Op0 : Op1, Idx&15, "tmp"); + InsertNewInstBefore(Elt, CI); + ExtractedElts[Idx] = Elt; } - return CastInst::Create(Instruction::BitCast, Result, CI.getType()); + + // Insert this value into the result vector. + Result = InsertElementInst::Create(Result, ExtractedElts[Idx], + i, "tmp"); + InsertNewInstBefore(cast(Result), CI); } + return CastInst::Create(Instruction::BitCast, Result, CI.getType()); } - break; + } + break; - case Intrinsic::stackrestore: { - // If the save is right next to the restore, remove the restore. This can - // happen when variable allocas are DCE'd. - if (IntrinsicInst *SS = dyn_cast(II->getOperand(1))) { - if (SS->getIntrinsicID() == Intrinsic::stacksave) { - BasicBlock::iterator BI = SS; - if (&*++BI == II) - return EraseInstFromFunction(CI); - } + case Intrinsic::stackrestore: { + // If the save is right next to the restore, remove the restore. This can + // happen when variable allocas are DCE'd. + if (IntrinsicInst *SS = dyn_cast(II->getOperand(1))) { + if (SS->getIntrinsicID() == Intrinsic::stacksave) { + BasicBlock::iterator BI = SS; + if (&*++BI == II) + return EraseInstFromFunction(CI); } - - // Scan down this block to see if there is another stack restore in the - // same block without an intervening call/alloca. - BasicBlock::iterator BI = II; - TerminatorInst *TI = II->getParent()->getTerminator(); - bool CannotRemove = false; - for (++BI; &*BI != TI; ++BI) { - if (isa(BI)) { + } + + // Scan down this block to see if there is another stack restore in the + // same block without an intervening call/alloca. + BasicBlock::iterator BI = II; + TerminatorInst *TI = II->getParent()->getTerminator(); + bool CannotRemove = false; + for (++BI; &*BI != TI; ++BI) { + if (isa(BI)) { + CannotRemove = true; + break; + } + if (isa(BI)) { + if (!isa(BI)) { CannotRemove = true; break; } - if (isa(BI)) { - if (!isa(BI)) { - CannotRemove = true; - break; - } - // If there is a stackrestore below this one, remove this one. - return EraseInstFromFunction(CI); - } - } - - // If the stack restore is in a return/unwind block and if there are no - // allocas or calls between the restore and the return, nuke the restore. - if (!CannotRemove && (isa(TI) || isa(TI))) + // If there is a stackrestore below this one, remove this one. return EraseInstFromFunction(CI); - break; - } + } } + + // If the stack restore is in a return/unwind block and if there are no + // allocas or calls between the restore and the return, nuke the restore. + if (!CannotRemove && (isa(TI) || isa(TI))) + return EraseInstFromFunction(CI); + break; + } } return visitCallSite(II); Modified: llvm/trunk/test/Transforms/InstCombine/bswap-fold.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/bswap-fold.ll?rev=52442&r1=52441&r2=52442&view=diff ============================================================================== --- llvm/trunk/test/Transforms/InstCombine/bswap-fold.ll (original) +++ llvm/trunk/test/Transforms/InstCombine/bswap-fold.ll Tue Jun 17 23:33:20 2008 @@ -1,7 +1,5 @@ -; RUN: llvm-as < %s | opt -instcombine | llvm-dis | \ -; RUN: grep ret | count 3 -; RUN: llvm-as < %s | opt -instcombine | llvm-dis | \ -; RUN: not grep call.*bswap +; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep ret | count 6 +; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep call.*bswap define i1 @test1(i16 %tmp2) { %tmp10 = call i16 @llvm.bswap.i16( i16 %tmp2 ) ; [#uses=1] @@ -27,3 +25,28 @@ declare i16 @llvm.bswap.i16(i16) +; rdar://5992453 +; A & 255 +define i32 @test4(i32 %a) nounwind { +entry: + %tmp2 = tail call i32 @llvm.bswap.i32( i32 %a ) + %tmp4 = lshr i32 %tmp2, 24 + ret i32 %tmp4 +} + +; A +define i32 @test5(i32 %a) nounwind { +entry: + %tmp2 = tail call i32 @llvm.bswap.i32( i32 %a ) + %tmp4 = tail call i32 @llvm.bswap.i32( i32 %tmp2 ) + ret i32 %tmp4 +} + +; a >> 24 +define i32 @test6(i32 %a) nounwind { +entry: + %tmp2 = tail call i32 @llvm.bswap.i32( i32 %a ) + %tmp4 = and i32 %tmp2, 255 + ret i32 %tmp4 +} + From kremenek at apple.com Wed Jun 18 00:34:51 2008 From: kremenek at apple.com (Ted Kremenek) Date: Wed, 18 Jun 2008 05:34:51 -0000 Subject: [llvm-commits] [llvm] r52444 - /llvm/tags/checker/checker-39/ Message-ID: <200806180534.m5I5YpX3006969@zion.cs.uiuc.edu> Author: kremenek Date: Wed Jun 18 00:34:51 2008 New Revision: 52444 URL: http://llvm.org/viewvc/llvm-project?rev=52444&view=rev Log: Tagging checker-39. Added: llvm/tags/checker/checker-39/ - copied from r52443, llvm/trunk/ From isanbard at gmail.com Wed Jun 18 01:35:30 2008 From: isanbard at gmail.com (Bill Wendling) Date: Wed, 18 Jun 2008 06:35:30 -0000 Subject: [llvm-commits] [llvm] r52447 - in /llvm/trunk/tools/lto2: LTOCodeGenerator.cpp LTOModule.cpp Message-ID: <200806180635.m5I6ZUwX009372@zion.cs.uiuc.edu> Author: void Date: Wed Jun 18 01:35:30 2008 New Revision: 52447 URL: http://llvm.org/viewvc/llvm-project?rev=52447&view=rev Log: If compiling for PPC on an i386 box, the LTO wouldn't get the altivec (and other) feature information. The workaround is inelegant and could be cleaned up if this information were available some other way (say, in the IR). Modified: llvm/trunk/tools/lto2/LTOCodeGenerator.cpp llvm/trunk/tools/lto2/LTOModule.cpp Modified: llvm/trunk/tools/lto2/LTOCodeGenerator.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lto2/LTOCodeGenerator.cpp?rev=52447&r1=52446&r2=52447&view=diff ============================================================================== --- llvm/trunk/tools/lto2/LTOCodeGenerator.cpp (original) +++ llvm/trunk/tools/lto2/LTOCodeGenerator.cpp Wed Jun 18 01:35:30 2008 @@ -32,6 +32,7 @@ #include "llvm/Analysis/Verifier.h" #include "llvm/Analysis/LoadValueNumbering.h" #include "llvm/CodeGen/FileWriters.h" +#include "llvm/Target/SubtargetFeature.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" @@ -261,8 +262,24 @@ *mergedModule, errMsg); if ( march == NULL ) return true; - std::string features; - _target = march->CtorFn(*mergedModule, features); + + // construct LTModule, hand over ownership of module and target + // + // FIXME: This is an inelegant way of specifying the features of a + // subtarget. It would be better if we could encode this information + // into the IR. See . + SubtargetFeatures Features; + std::string FeatureStr; + std::string TargetTriple = _linker.getModule()->getTargetTriple(); + + if (strncmp(TargetTriple.c_str(), "powerpc-apple-", 14) == 0) { + Features.AddFeature("altivec", true); + } else if (strncmp(TargetTriple.c_str(), "powerpc64-apple-", 16) == 0) { + Features.AddFeature("64bit", true); + Features.AddFeature("altivec", true); + } + + _target = march->CtorFn(*mergedModule, Features.getString()); } return false; } @@ -302,7 +319,6 @@ } } - /// Optimize merged modules using various IPO passes bool LTOCodeGenerator::generateAssemblyCode(std::ostream& out, std::string& errMsg) { @@ -360,12 +376,9 @@ // function pointers. When this happens, we often have to resolve varargs // calls, etc, so let instcombine do this. passes.add(createInstructionCombiningPass()); - - passes.add(createFunctionInliningPass()); // Inline small functions - - passes.add(createPruneEHPass()); // Remove dead EH info - - passes.add(createGlobalDCEPass()); // Remove dead functions + passes.add(createFunctionInliningPass()); // Inline small functions + passes.add(createPruneEHPass()); // Remove dead EH info + passes.add(createGlobalDCEPass()); // Remove dead functions // If we didn't decide to inline a function, check to see if we can // transform it to pass arguments by value instead of by reference. @@ -377,16 +390,14 @@ passes.add(createScalarReplAggregatesPass()); // Break up allocas // Run a few AA driven optimizations here and now, to cleanup the code. - passes.add(createGlobalsModRefPass()); // IP alias analysis - - passes.add(createLICMPass()); // Hoist loop invariants - passes.add(createGVNPass()); // Remove common subexprs - passes.add(createMemCpyOptPass()); // Remove dead memcpy's + passes.add(createGlobalsModRefPass()); // IP alias analysis + passes.add(createLICMPass()); // Hoist loop invariants + passes.add(createGVNPass()); // Remove common subexprs + passes.add(createMemCpyOptPass()); // Remove dead memcpy's passes.add(createDeadStoreEliminationPass()); // Nuke dead stores // Cleanup and simplify the code after the scalar optimizations. passes.add(createInstructionCombiningPass()); - passes.add(createJumpThreadingPass()); // Thread jumps. // Delete basic blocks, which optimization passes may have killed... @@ -431,13 +442,13 @@ // Run the code generator, and write assembly file codeGenPasses->doInitialization(); - for (Module::iterator it = mergedModule->begin(), - e = mergedModule->end(); it != e; ++it) { - if (!it->isDeclaration()) - codeGenPasses->run(*it); - } - codeGenPasses->doFinalization(); + for (Module::iterator + it = mergedModule->begin(), e = mergedModule->end(); it != e; ++it) + if (!it->isDeclaration()) + codeGenPasses->run(*it); + + codeGenPasses->doFinalization(); return false; // success } Modified: llvm/trunk/tools/lto2/LTOModule.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lto2/LTOModule.cpp?rev=52447&r1=52446&r2=52447&view=diff ============================================================================== --- llvm/trunk/tools/lto2/LTOModule.cpp (original) +++ llvm/trunk/tools/lto2/LTOModule.cpp Wed Jun 18 01:35:30 2008 @@ -24,11 +24,11 @@ #include "llvm/Support/MathExtras.h" #include "llvm/System/Path.h" #include "llvm/System/Process.h" +#include "llvm/Target/SubtargetFeature.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetMachineRegistry.h" #include "llvm/Target/TargetAsmInfo.h" - #include using namespace llvm; @@ -125,11 +125,27 @@ // find machine architecture for this module const TargetMachineRegistry::entry* march = TargetMachineRegistry::getClosestStaticTargetForModule(*m, errMsg); + if ( march == NULL ) return NULL; + // construct LTModule, hand over ownership of module and target - std::string features; - TargetMachine* target = march->CtorFn(*m, features); + // + // FIXME: This is an inelegant way of specifying the features of a + // subtarget. It would be better if we could encode this information into + // the IR. See . + SubtargetFeatures Features; + std::string FeatureStr; + const char *TargetTriple = m->getTargetTriple().c_str(); + + if (strncmp(TargetTriple, "powerpc-apple-", 14) == 0) { + Features.AddFeature("altivec", true); + } else if (strncmp(TargetTriple, "powerpc64-apple-", 16) == 0) { + Features.AddFeature("64bit", true); + Features.AddFeature("altivec", true); + } + + TargetMachine* target = march->CtorFn(*m, Features.getString()); return new LTOModule(m.take(), target); } From isanbard at gmail.com Wed Jun 18 01:37:10 2008 From: isanbard at gmail.com (Bill Wendling) Date: Wed, 18 Jun 2008 06:37:10 -0000 Subject: [llvm-commits] [llvm] r52448 - /llvm/tags/Apple/llvmCore-2049/ Message-ID: <200806180637.m5I6bAUP009498@zion.cs.uiuc.edu> Author: void Date: Wed Jun 18 01:37:09 2008 New Revision: 52448 URL: http://llvm.org/viewvc/llvm-project?rev=52448&view=rev Log: Creating llvmCore-2049 branch Added: llvm/tags/Apple/llvmCore-2049/ - copied from r52447, llvm/trunk/ From isanbard at gmail.com Wed Jun 18 01:37:16 2008 From: isanbard at gmail.com (Bill Wendling) Date: Wed, 18 Jun 2008 06:37:16 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r52449 - /llvm-gcc-4.2/tags/Apple/llvmgcc42-2049/ Message-ID: <200806180637.m5I6bGEg009511@zion.cs.uiuc.edu> Author: void Date: Wed Jun 18 01:37:15 2008 New Revision: 52449 URL: http://llvm.org/viewvc/llvm-project?rev=52449&view=rev Log: Creating llvmgcc42-2049 branch Added: llvm-gcc-4.2/tags/Apple/llvmgcc42-2049/ - copied from r52448, llvm-gcc-4.2/trunk/ From evan.cheng at apple.com Wed Jun 18 02:47:29 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Wed, 18 Jun 2008 07:47:29 -0000 Subject: [llvm-commits] [llvm] r52450 - /llvm/trunk/lib/CodeGen/VirtRegMap.cpp Message-ID: <200806180747.m5I7lTx3018320@zion.cs.uiuc.edu> Author: evancheng Date: Wed Jun 18 02:47:28 2008 New Revision: 52450 URL: http://llvm.org/viewvc/llvm-project?rev=52450&view=rev Log: Cosmetic. Modified: llvm/trunk/lib/CodeGen/VirtRegMap.cpp Modified: llvm/trunk/lib/CodeGen/VirtRegMap.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/VirtRegMap.cpp?rev=52450&r1=52449&r2=52450&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/VirtRegMap.cpp (original) +++ llvm/trunk/lib/CodeGen/VirtRegMap.cpp Wed Jun 18 02:47:28 2008 @@ -37,7 +37,7 @@ using namespace llvm; STATISTIC(NumSpills , "Number of register spills"); -STATISTIC(NumPSpills ,"Number of physical register spills"); +STATISTIC(NumPSpills , "Number of physical register spills"); STATISTIC(NumReMats , "Number of re-materialization"); STATISTIC(NumDRM , "Number of re-materializable defs elided"); STATISTIC(NumStores , "Number of stores added"); From evan.cheng at apple.com Wed Jun 18 02:47:55 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Wed, 18 Jun 2008 07:47:55 -0000 Subject: [llvm-commits] [llvm] r52451 - /llvm/trunk/include/llvm/CodeGen/MachineRegisterInfo.h Message-ID: <200806180747.m5I7ltvV018654@zion.cs.uiuc.edu> Author: evancheng Date: Wed Jun 18 02:47:55 2008 New Revision: 52451 URL: http://llvm.org/viewvc/llvm-project?rev=52451&view=rev Log: Add MachineRegisterInfo::use_empty. Modified: llvm/trunk/include/llvm/CodeGen/MachineRegisterInfo.h Modified: llvm/trunk/include/llvm/CodeGen/MachineRegisterInfo.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineRegisterInfo.h?rev=52451&r1=52450&r2=52451&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/MachineRegisterInfo.h (original) +++ llvm/trunk/include/llvm/CodeGen/MachineRegisterInfo.h Wed Jun 18 02:47:55 2008 @@ -90,6 +90,10 @@ } static use_iterator use_end() { return use_iterator(0); } + /// use_empty - Return true if there are no instructions using the specified + /// register. + bool use_empty(unsigned RegNo) const { return use_begin(RegNo) == use_end(); } + /// replaceRegWith - Replace all instances of FromReg with ToReg in the /// machine function. This is like llvm-level X->replaceAllUsesWith(Y), From evan.cheng at apple.com Wed Jun 18 02:49:14 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Wed, 18 Jun 2008 07:49:14 -0000 Subject: [llvm-commits] [llvm] r52452 - /llvm/trunk/lib/CodeGen/TwoAddressInstructionPass.cpp Message-ID: <200806180749.m5I7nEdZ019212@zion.cs.uiuc.edu> Author: evancheng Date: Wed Jun 18 02:49:14 2008 New Revision: 52452 URL: http://llvm.org/viewvc/llvm-project?rev=52452&view=rev Log: Complete support for two-address pass rematerialization. Now *almost* always a win. Modified: llvm/trunk/lib/CodeGen/TwoAddressInstructionPass.cpp Modified: llvm/trunk/lib/CodeGen/TwoAddressInstructionPass.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TwoAddressInstructionPass.cpp?rev=52452&r1=52451&r2=52452&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/TwoAddressInstructionPass.cpp (original) +++ llvm/trunk/lib/CodeGen/TwoAddressInstructionPass.cpp Wed Jun 18 02:49:14 2008 @@ -40,6 +40,8 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/STLExtras.h" @@ -49,9 +51,10 @@ STATISTIC(NumCommuted , "Number of instructions commuted to coalesce"); STATISTIC(NumConvertedTo3Addr, "Number of instructions promoted to 3-address"); STATISTIC(Num3AddrSunk, "Number of 3-address instructions sunk"); +STATISTIC(NumReMats, "Number of instructions re-materialized"); static cl::opt -EnableReMat("2-addr-remat", cl::init(false), cl::Hidden, +EnableReMat("two-addr-remat", cl::init(false), cl::Hidden, cl::desc("Two-addr conversion should remat when possible.")); namespace { @@ -65,6 +68,12 @@ bool Sink3AddrInstruction(MachineBasicBlock *MBB, MachineInstr *MI, unsigned Reg, MachineBasicBlock::iterator OldPos); + + bool isSafeToReMat(unsigned DstReg, MachineInstr *MI); + bool isProfitableToReMat(unsigned Reg, const TargetRegisterClass *RC, + MachineInstr *MI, unsigned Loc, + MachineInstr *DefMI, MachineBasicBlock *MBB, + DenseMap &DistanceMap); public: static char ID; // Pass identification, replacement for typeid TwoAddressInstructionPass() : MachineFunctionPass((intptr_t)&ID) {} @@ -93,7 +102,6 @@ /// three-address instruction to avoid clobbering a register. Try to sink it /// past the instruction that would kill the above mentioned register to reduce /// register pressure. -/// bool TwoAddressInstructionPass::Sink3AddrInstruction(MachineBasicBlock *MBB, MachineInstr *MI, unsigned SavedReg, MachineBasicBlock::iterator OldPos) { @@ -127,7 +135,6 @@ // Find the instruction that kills SavedReg. MachineInstr *KillMI = NULL; - for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(SavedReg), UE = MRI->use_end(); UI != UE; ++UI) { MachineOperand &UseMO = UI.getOperand(); @@ -144,15 +151,18 @@ // position and the kill use, then it's not safe to sink it. // // FIXME: This can be sped up if there is an easy way to query whether an - // instruction if before or after another instruction. Then we can use + // instruction is before or after another instruction. Then we can use // MachineRegisterInfo def / use instead. MachineOperand *KillMO = NULL; MachineBasicBlock::iterator KillPos = KillMI; ++KillPos; + unsigned NumVisited = 0; for (MachineBasicBlock::iterator I = next(OldPos); I != KillPos; ++I) { MachineInstr *OtherMI = I; - + if (NumVisited > 30) // FIXME: Arbitrary limit to reduce compile time cost. + return false; + ++NumVisited; for (unsigned i = 0, e = OtherMI->getNumOperands(); i != e; ++i) { MachineOperand &MO = OtherMI->getOperand(i); if (!MO.isRegister()) @@ -165,8 +175,8 @@ if (MO.isKill()) { if (OtherMI == KillMI && MOReg == SavedReg) - // Save the operand that kills the register. We want unset the kill - // marker is we can sink MI past it. + // Save the operand that kills the register. We want to unset the kill + // marker if we can sink MI past it. KillMO = &MO; else if (UseRegs.count(MOReg)) // One of the uses is killed before the destination. @@ -191,6 +201,80 @@ return true; } +/// isSafeToReMat - Return true if it's safe to rematerialize the specified +/// instruction which defined the specified register instead of copying it. +bool +TwoAddressInstructionPass::isSafeToReMat(unsigned DstReg, MachineInstr *MI) { + const TargetInstrDesc &TID = MI->getDesc(); + if (!TID.isAsCheapAsAMove()) + return false; + bool SawStore = false; + if (!MI->isSafeToMove(TII, SawStore)) + return false; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isRegister()) + continue; + // FIXME: For now, do not remat any instruction with register operands. + // Later on, we can loosen the restriction is the register operands have + // not been modified between the def and use. Note, this is different from + // MachineSink because the code in no longer in two-address form (at least + // partially). + if (MO.isUse()) + return false; + else if (!MO.isDead() && MO.getReg() != DstReg) + return false; + } + return true; +} + +/// isTwoAddrUse - Return true if the specified MI is using the specified +/// register as a two-address operand. +static bool isTwoAddrUse(MachineInstr *UseMI, unsigned Reg) { + const TargetInstrDesc &TID = UseMI->getDesc(); + for (unsigned i = 0, e = TID.getNumOperands(); i != e; ++i) { + MachineOperand &MO = UseMI->getOperand(i); + if (MO.getReg() == Reg && + (MO.isDef() || TID.getOperandConstraint(i, TOI::TIED_TO) != -1)) + // Earlier use is a two-address one. + return true; + } + return false; +} + +/// isProfitableToReMat - Return true if the heuristics determines it is likely +/// to be profitable to re-materialize the definition of Reg rather than copy +/// the register. +bool +TwoAddressInstructionPass::isProfitableToReMat(unsigned Reg, + const TargetRegisterClass *RC, + MachineInstr *MI, unsigned Loc, + MachineInstr *DefMI, MachineBasicBlock *MBB, + DenseMap &DistanceMap) { + if (DefMI->getParent() != MBB) + return true; + // If earlier uses in MBB are not two-address uses, then don't remat. + bool OtherUse = false; + for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(Reg), + UE = MRI->use_end(); UI != UE; ++UI) { + MachineOperand &UseMO = UI.getOperand(); + if (!UseMO.isUse()) + continue; + MachineInstr *UseMI = UseMO.getParent(); + if (UseMI->getParent() != MBB) + continue; + DenseMap::iterator DI = DistanceMap.find(UseMI); + if (DI != DistanceMap.end() && DI->second == Loc) + continue; // Current use. + OtherUse = true; + // There is at least one other use in the MBB that will clobber the + // register. + if (isTwoAddrUse(UseMI, Reg)) + return true; + } + return !OtherUse; +} + /// runOnMachineFunction - Reduce two-address instructions to two operands. /// bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &MF) { @@ -206,16 +290,25 @@ DOUT << "********** REWRITING TWO-ADDR INSTRS **********\n"; DOUT << "********** Function: " << MF.getFunction()->getName() << '\n'; - SmallPtrSet ReMattedInstrs; + // ReMatRegs - Keep track of the registers whose def's are remat'ed. + BitVector ReMatRegs; + ReMatRegs.resize(MRI->getLastVirtReg()+1); + + // DistanceMap - Keep track the distance of a MI from the start of the + // current basic block. + DenseMap DistanceMap; for (MachineFunction::iterator mbbi = MF.begin(), mbbe = MF.end(); mbbi != mbbe; ++mbbi) { + unsigned Dist = 0; + DistanceMap.clear(); for (MachineBasicBlock::iterator mi = mbbi->begin(), me = mbbi->end(); mi != me; ) { MachineBasicBlock::iterator nmi = next(mi); const TargetInstrDesc &TID = mi->getDesc(); bool FirstTied = true; + DistanceMap.insert(std::make_pair(mi, ++Dist)); for (unsigned si = 1, e = TID.getNumOperands(); si < e; ++si) { int ti = TID.getOperandConstraint(si, TOI::TIED_TO); if (ti == -1) @@ -284,6 +377,7 @@ mbbi->insert(mi, NewMI); // Insert the new inst mbbi->erase(mi); // Nuke the old inst. mi = NewMI; + DistanceMap.insert(std::make_pair(NewMI, Dist)); } ++NumCommuted; @@ -303,21 +397,23 @@ assert(TID.getOperandConstraint(i, TOI::TIED_TO) == -1); #endif - if (MachineInstr *New=TII->convertToThreeAddress(mbbi, mi, *LV)) { + MachineInstr *NewMI = TII->convertToThreeAddress(mbbi, mi, *LV); + if (NewMI) { DOUT << "2addr: CONVERTING 2-ADDR: " << *mi; - DOUT << "2addr: TO 3-ADDR: " << *New; + DOUT << "2addr: TO 3-ADDR: " << *NewMI; bool Sunk = false; - if (New->findRegisterUseOperand(regB, false, TRI)) + if (NewMI->findRegisterUseOperand(regB, false, TRI)) // FIXME: Temporary workaround. If the new instruction doesn't // uses regB, convertToThreeAddress must have created more // then one instruction. - Sunk = Sink3AddrInstruction(mbbi, New, regB, mi); + Sunk = Sink3AddrInstruction(mbbi, NewMI, regB, mi); mbbi->erase(mi); // Nuke the old inst. if (!Sunk) { - mi = New; + DistanceMap.insert(std::make_pair(NewMI, Dist)); + mi = NewMI; nmi = next(mi); } @@ -328,17 +424,17 @@ } InstructionRearranged: - const TargetRegisterClass* rc = MF.getRegInfo().getRegClass(regA); - MachineInstr *Orig = MRI->getVRegDef(regB); - const TargetInstrDesc &OrigTID = Orig->getDesc(); - bool SawStore = false; - - if (EnableReMat && Orig && Orig->isSafeToMove(TII, SawStore) && - OrigTID.isAsCheapAsAMove() && !OrigTID.mayLoad() && - !OrigTID.isSimpleLoad()) { - DEBUG(cerr << "2addr: REMATTING : " << *Orig << "\n"); - TII->reMaterialize(*mbbi, mi, regA, Orig); - ReMattedInstrs.insert(Orig); + const TargetRegisterClass* rc = MRI->getRegClass(regA); + MachineInstr *DefMI = MRI->getVRegDef(regB); + // If it's safe and profitable, remat the definition instead of + // copying it. + if (EnableReMat && DefMI && + isSafeToReMat(regB, DefMI) && + isProfitableToReMat(regB, rc, mi, Dist, DefMI, mbbi,DistanceMap)){ + DEBUG(cerr << "2addr: REMATTING : " << *DefMI << "\n"); + TII->reMaterialize(*mbbi, mi, regA, DefMI); + ReMatRegs.set(regB); + ++NumReMats; } else { TII->copyRegToReg(*mbbi, mi, regA, regB, rc, rc); } @@ -378,33 +474,16 @@ } if (EnableReMat) { - // Check to see if the instructions that we rematerialized are now dead. If - // they are, expunge them here. - SmallPtrSet::iterator I = ReMattedInstrs.begin(); - SmallPtrSet::iterator E = ReMattedInstrs.end(); - - for (; I != E; ++I) { - MachineInstr *MI = *I; - bool InstrDead = true; - - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - const MachineOperand &MO = MI->getOperand(i); - if (!MO.isRegister()) - continue; - unsigned MOReg = MO.getReg(); - - if (!MOReg || !MO.isDef() || (MO.isImplicit() && MO.isDead())) - continue; - - if (MRI->use_begin(MOReg) != MRI->use_end()) { - InstrDead = false; - break; - } + // Some remat'ed instructions are dead. + int VReg = ReMatRegs.find_first(); + while (VReg != -1) { + if (MRI->use_empty(VReg)) { + MachineInstr *DefMI = MRI->getVRegDef(VReg); + DefMI->eraseFromParent(); } - - if (InstrDead) - MI->eraseFromParent(); + VReg = ReMatRegs.find_next(VReg); } + } return MadeChange; From matthijs at stdin.nl Wed Jun 18 03:09:27 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Wed, 18 Jun 2008 08:09:27 -0000 Subject: [llvm-commits] [llvm] r52453 - in /llvm/trunk: lib/Transforms/IPO/IPConstantPropagation.cpp test/Transforms/IPConstantProp/return-constants.ll Message-ID: <200806180809.m5I89RFi023297@zion.cs.uiuc.edu> Author: matthijs Date: Wed Jun 18 03:09:27 2008 New Revision: 52453 URL: http://llvm.org/viewvc/llvm-project?rev=52453&view=rev Log: Reapply r52396, it was unrelated to the breakage (that was caused by r52397, my commit after this). Modified: llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp llvm/trunk/test/Transforms/IPConstantProp/return-constants.ll Modified: llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp?rev=52453&r1=52452&r2=52453&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp (original) +++ llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp Wed Jun 18 03:09:27 2008 @@ -21,6 +21,7 @@ #include "llvm/Instructions.h" #include "llvm/Module.h" #include "llvm/Pass.h" +#include "llvm/Analysis/ValueTracking.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/Compiler.h" #include "llvm/ADT/Statistic.h" @@ -140,9 +141,10 @@ } -// Check to see if this function returns a constant. If so, replace all callers -// that user the return value with the returned valued. If we can replace ALL -// callers, +// Check to see if this function returns one or more constants. If so, replace +// all callers that use those return values with the constant value. This will +// leave in the actual return values and instructions, but deadargelim will +// clean that up. bool IPCP::PropagateConstantReturn(Function &F) { if (F.getReturnType() == Type::VoidTy) return false; // No return value. @@ -156,48 +158,65 @@ SmallVector RetVals; const StructType *STy = dyn_cast(F.getReturnType()); if (STy) - RetVals.assign(STy->getNumElements(), 0); + for (unsigned i = 0, e = STy->getNumElements(); i < e; ++i) + RetVals.push_back(UndefValue::get(STy->getElementType(i))); else - RetVals.push_back(0); + RetVals.push_back(UndefValue::get(F.getReturnType())); + unsigned NumNonConstant = 0; for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { - assert(RetVals.size() == RI->getNumOperands() && - "Invalid ReturnInst operands!"); + // Return type does not match operand type, this is an old style multiple + // return + bool OldReturn = (F.getReturnType() != RI->getOperand(0)->getType()); + for (unsigned i = 0, e = RetVals.size(); i != e; ++i) { - if (isa(RI->getOperand(i))) - continue; // Ignore - Constant *C = dyn_cast(RI->getOperand(i)); - if (C == 0) - return false; // Does not return a constant. - + // Already found conflicting return values? Value *RV = RetVals[i]; - if (RV == 0) - RetVals[i] = C; - else if (RV != C) - return false; // Does not return the same constant. + if (!RV) + continue; + + // Find the returned value + Value *V; + if (!STy || OldReturn) + V = RI->getOperand(i); + else + V = FindInsertedValue(RI->getOperand(0), i); + + if (V) { + // Ignore undefs, we can change them into anything + if (isa(V)) + continue; + + // Try to see if all the rets return the same constant. + if (isa(V)) { + if (isa(RV)) { + // No value found yet? Try the current one. + RetVals[i] = V; + continue; + } + // Returning the same value? Good. + if (RV == V) + continue; + } + } + // Different or no known return value? Don't propagate this return + // value. + RetVals[i] = 0; + // All values non constant? Stop looking. + if (++NumNonConstant == RetVals.size()) + return false; } } - if (STy) { - for (unsigned i = 0, e = RetVals.size(); i < e; ++i) - if (RetVals[i] == 0) - RetVals[i] = UndefValue::get(STy->getElementType(i)); - } else { - assert(RetVals.size() == 1); - if (RetVals[0] == 0) - RetVals[0] = UndefValue::get(F.getReturnType()); - } - - // If we got here, the function returns a constant value. Loop over all - // users, replacing any uses of the return value with the returned constant. - bool ReplacedAllUsers = true; + // If we got here, the function returns at least one constant value. Loop + // over all users, replacing any uses of the return value with the returned + // constant. bool MadeChange = false; for (Value::use_iterator UI = F.use_begin(), E = F.use_end(); UI != E; ++UI) { // Make sure this is an invoke or call and that the use is for the callee. if (!(isa(*UI) || isa(*UI)) || UI.getOperandNo() != 0) { - ReplacedAllUsers = false; continue; } @@ -212,28 +231,32 @@ continue; } - while (!Call->use_empty()) { - GetResultInst *GR = cast(Call->use_back()); - GR->replaceAllUsesWith(RetVals[GR->getIndex()]); - GR->eraseFromParent(); - } - } - - // If we replace all users with the returned constant, and there can be no - // other callers of the function, replace the constant being returned in the - // function with an undef value. - if (ReplacedAllUsers && F.hasInternalLinkage()) { - for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { - if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { - for (unsigned i = 0, e = RetVals.size(); i < e; ++i) { - Value *RetVal = RetVals[i]; - if (isa(RetVal)) - continue; - Value *RV = UndefValue::get(RetVal->getType()); - if (RI->getOperand(i) != RV) { - RI->setOperand(i, RV); - MadeChange = true; - } + for (Value::use_iterator I = Call->use_begin(), E = Call->use_end(); + I != E;) { + Instruction *Ins = dyn_cast(*I); + + // Increment now, so we can remove the use + ++I; + + // Not an instruction? Ignore + if (!Ins) + continue; + + // Find the index of the retval to replace with + int index = -1; + if (GetResultInst *GR = dyn_cast(Ins)) + index = GR->getIndex(); + else if (ExtractValueInst *EV = dyn_cast(Ins)) + if (EV->hasIndices()) + index = *EV->idx_begin(); + + // If this use uses a specific return value, and we have a replacement, + // replace it. + if (index != -1) { + Value *New = RetVals[index]; + if (New) { + Ins->replaceAllUsesWith(New); + Ins->eraseFromParent(); } } } Modified: llvm/trunk/test/Transforms/IPConstantProp/return-constants.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/return-constants.ll?rev=52453&r1=52452&r2=52453&view=diff ============================================================================== --- llvm/trunk/test/Transforms/IPConstantProp/return-constants.ll (original) +++ llvm/trunk/test/Transforms/IPConstantProp/return-constants.ll Wed Jun 18 03:09:27 2008 @@ -1,20 +1,41 @@ -; RUN: llvm-as < %s | opt -ipconstprop | llvm-dis | grep {add i32 21, 21} +; RUN: llvm-as < %s | opt -ipconstprop | llvm-dis > %t +;; Check that the 21 constants got propagated properly +; RUN: cat %t | grep {%M = add i32 21, 21} +;; Check that the second return values didn't get propagated +; RUN: cat %t | grep {%N = add i32 %B, %D} -define internal {i32, i32} @foo(i1 %C) { - br i1 %C, label %T, label %F +define internal {i32, i32} @foo(i1 %Q) { + br i1 %Q, label %T, label %F T: ; preds = %0 - ret i32 21, i32 21 + ret i32 21, i32 22 F: ; preds = %0 - ret i32 21, i32 21 + ret i32 21, i32 23 } -define i32 @caller(i1 %C) { - %X = call {i32, i32} @foo( i1 %C ) +define internal {i32, i32} @bar(i1 %Q) { + %A = insertvalue { i32, i32 } undef, i32 21, 0 + br i1 %Q, label %T, label %F + +T: ; preds = %0 + %B = insertvalue { i32, i32 } %A, i32 22, 1 + ret { i32, i32 } %B + +F: ; preds = %0 + %C = insertvalue { i32, i32 } %A, i32 23, 1 + ret { i32, i32 } %C +} + +define { i32, i32 } @caller(i1 %Q) { + %X = call {i32, i32} @foo( i1 %Q ) %A = getresult {i32, i32} %X, 0 %B = getresult {i32, i32} %X, 1 - %Y = add i32 %A, %B - ret i32 %Y + %Y = call {i32, i32} @bar( i1 %Q ) + %C = extractvalue {i32, i32} %Y, 0 + %D = extractvalue {i32, i32} %Y, 1 + %M = add i32 %A, %C + %N = add i32 %B, %D + ret { i32, i32 } %X } From evan.cheng at apple.com Wed Jun 18 03:13:07 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Wed, 18 Jun 2008 08:13:07 -0000 Subject: [llvm-commits] [llvm] r52454 - /llvm/trunk/lib/Target/X86/X86InstrInfo.td Message-ID: <200806180813.m5I8D7qK023472@zion.cs.uiuc.edu> Author: evancheng Date: Wed Jun 18 03:13:07 2008 New Revision: 52454 URL: http://llvm.org/viewvc/llvm-project?rev=52454&view=rev Log: XOR32rr, etc. are not AsCheapAsMove, but MOV32ri, etc. are. Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.td Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=52454&r1=52453&r2=52454&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrInfo.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrInfo.td Wed Jun 18 03:13:07 2008 @@ -578,7 +578,7 @@ def MOV32rr : I<0x89, MRMDestReg, (outs GR32:$dst), (ins GR32:$src), "mov{l}\t{$src, $dst|$dst, $src}", []>; } -let isReMaterializable = 1 in { +let isReMaterializable = 1, isAsCheapAsAMove = 1 in { def MOV8ri : Ii8 <0xB0, AddRegFrm, (outs GR8 :$dst), (ins i8imm :$src), "mov{b}\t{$src, $dst|$dst, $src}", [(set GR8:$dst, imm:$src)]>; @@ -1312,8 +1312,7 @@ } // isTwoAddress = 0 -let isAsCheapAsAMove = 1, - isCommutable = 1 in { // X = XOR Y, Z --> X = XOR Z, Y +let isCommutable = 1 in { // X = XOR Y, Z --> X = XOR Z, Y def XOR8rr : I<0x30, MRMDestReg, (outs GR8 :$dst), (ins GR8 :$src1, GR8 :$src2), "xor{b}\t{$src2, $dst|$dst, $src2}", @@ -1326,7 +1325,7 @@ (outs GR32:$dst), (ins GR32:$src1, GR32:$src2), "xor{l}\t{$src2, $dst|$dst, $src2}", [(set GR32:$dst, (xor GR32:$src1, GR32:$src2))]>; -} // isAsCheapAsAMove = 1, isCommutable = 1 +} // isCommutable = 1 def XOR8rm : I<0x32, MRMSrcMem , (outs GR8 :$dst), (ins GR8:$src1, i8mem :$src2), From matthijs at stdin.nl Wed Jun 18 03:30:37 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Wed, 18 Jun 2008 08:30:37 -0000 Subject: [llvm-commits] [llvm] r52455 - in /llvm/trunk: lib/Transforms/IPO/IPConstantPropagation.cpp test/Transforms/IPConstantProp/return-argument.ll Message-ID: <200806180830.m5I8UblJ024060@zion.cs.uiuc.edu> Author: matthijs Date: Wed Jun 18 03:30:37 2008 New Revision: 52455 URL: http://llvm.org/viewvc/llvm-project?rev=52455&view=rev Log: Reapply r52397 (make IPConstProp promote returned arguments), but fixed this time. Sorry for the trouble! This time, also add a testcase, which I should have done in the first place... Added: llvm/trunk/test/Transforms/IPConstantProp/return-argument.ll Modified: llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp Modified: llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp?rev=52455&r1=52454&r2=52455&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp (original) +++ llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp Wed Jun 18 03:30:37 2008 @@ -145,6 +145,10 @@ // all callers that use those return values with the constant value. This will // leave in the actual return values and instructions, but deadargelim will // clean that up. +// +// Additionally if a function always returns one of its arguments directly, +// callers will be updated to use the value they pass in directly instead of +// using the return value. bool IPCP::PropagateConstantReturn(Function &F) { if (F.getReturnType() == Type::VoidTy) return false; // No return value. @@ -188,8 +192,8 @@ if (isa(V)) continue; - // Try to see if all the rets return the same constant. - if (isa(V)) { + // Try to see if all the rets return the same constant or argument. + if (isa(V) || isa(V)) { if (isa(RV)) { // No value found yet? Try the current one. RetVals[i] = V; @@ -227,7 +231,13 @@ MadeChange = true; if (STy == 0) { - Call->replaceAllUsesWith(RetVals[0]); + Value* New = RetVals[0]; + if (Argument *A = dyn_cast(New)) + // Was an argument returned? Then find the corresponding argument in + // the call instruction and use that. Add 1 to the argument number + // to skip the first argument (the function itself). + New = Call->getOperand(A->getArgNo() + 1); + Call->replaceAllUsesWith(New); continue; } @@ -255,6 +265,11 @@ if (index != -1) { Value *New = RetVals[index]; if (New) { + if (Argument *A = dyn_cast(New)) + // Was an argument returned? Then find the corresponding argument in + // the call instruction and use that. Add 1 to the argument number + // to skip the first argument (the function itself). + New = Call->getOperand(A->getArgNo() + 1); Ins->replaceAllUsesWith(New); Ins->eraseFromParent(); } Added: llvm/trunk/test/Transforms/IPConstantProp/return-argument.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/return-argument.ll?rev=52455&view=auto ============================================================================== --- llvm/trunk/test/Transforms/IPConstantProp/return-argument.ll (added) +++ llvm/trunk/test/Transforms/IPConstantProp/return-argument.ll Wed Jun 18 03:30:37 2008 @@ -0,0 +1,46 @@ +; RUN: llvm-as < %s | opt -ipconstprop | llvm-dis > %t +; RUN: cat %t | grep {store i32 %Z, i32\\* %Q} +; RUN: cat %t | grep {add i32 1, 3} + +;; This function returns its second argument on all return statements +define internal i32* @incdec(i1 %C, i32* %V) { + %X = load i32* %V + br i1 %C, label %T, label %F + +T: ; preds = %0 + %X1 = add i32 %X, 1 + store i32 %X1, i32* %V + ret i32* %V + +F: ; preds = %0 + %X2 = sub i32 %X, 1 + store i32 %X2, i32* %V + ret i32* %V +} + +;; This function returns its first argument as a part of a multiple return +;; value +define internal { i32, i32 } @foo(i32 %A, i32 %B) { + %X = add i32 %A, %B + %Y = insertvalue { i32, i32 } undef, i32 %A, 0 + %Z = insertvalue { i32, i32 } %Y, i32 %X, 1 + ret { i32, i32 } %Z +} + +define void @caller(i1 %C) { + %Q = alloca i32 + ;; Call incdec to see if %W is properly replaced by %Q + %W = call i32* @incdec(i1 %C, i32* %Q ) ; [#uses=1] + ;; Call @foo twice, to prevent the arguments from propagating into the + ;; function (so we can check the returned argument is properly + ;; propagated per-caller). + %S1 = call { i32, i32 } @foo(i32 1, i32 2); + %X1 = extractvalue { i32, i32 } %S1, 0 + %S2 = call { i32, i32 } @foo(i32 3, i32 4); + %X2 = extractvalue { i32, i32 } %S2, 0 + ;; Do some stuff with the returned values which we can grep for + %Z = add i32 %X1, %X2 + store i32 %Z, i32* %W + ret void +} + From nicolas.geoffray at lip6.fr Wed Jun 18 05:41:02 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Wed, 18 Jun 2008 10:41:02 -0000 Subject: [llvm-commits] [vmkit] r52456 - in /vmkit/trunk/lib: JnJVM/VMCore/JavaIsolate.cpp JnJVM/VMCore/JnjvmModuleProvider.cpp Mvm/EscapeAnalysis.cpp Message-ID: <200806181041.m5IAf4IB028936@zion.cs.uiuc.edu> Author: geoffray Date: Wed Jun 18 05:40:54 2008 New Revision: 52456 URL: http://llvm.org/viewvc/llvm-project?rev=52456&view=rev Log: Re-enable escape analysis, loop passes and predicate simplifier pass. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaIsolate.cpp vmkit/trunk/lib/JnJVM/VMCore/JnjvmModuleProvider.cpp vmkit/trunk/lib/Mvm/EscapeAnalysis.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaIsolate.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaIsolate.cpp?rev=52456&r1=52455&r2=52456&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaIsolate.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaIsolate.cpp Wed Jun 18 05:40:54 2008 @@ -504,8 +504,8 @@ isolate->analyseClasspathEnv(isolate->bootClasspathEnv); isolate->TheModule = new JnjvmModule("Bootstrap JnJVM"); - isolate->TheModuleProvider = new JnjvmModuleProvider(isolate->TheModule); isolate->TheModule->initialise(); + isolate->TheModuleProvider = new JnjvmModuleProvider(isolate->TheModule); isolate->bootstrapThread = vm_new(isolate, JavaThread)(); isolate->bootstrapThread->initialise(0, isolate); Modified: vmkit/trunk/lib/JnJVM/VMCore/JnjvmModuleProvider.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JnjvmModuleProvider.cpp?rev=52456&r1=52455&r2=52456&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JnjvmModuleProvider.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JnjvmModuleProvider.cpp Wed Jun 18 05:40:54 2008 @@ -160,7 +160,7 @@ namespace mvm { - llvm::FunctionPass* createEscapeAnalysisPass(llvm::Function*, llvm::Function*); + llvm::FunctionPass* createEscapeAnalysisPass(llvm::Function*); llvm::FunctionPass* createLowerConstantCallsPass(); } @@ -190,20 +190,22 @@ addPass(PM, createTailCallEliminationPass()); // Eliminate tail calls addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs + addPass(PM, createPredicateSimplifierPass()); addPass(PM, createReassociatePass()); // Reassociate expressions - //addPass(PM, createLoopRotatePass()); + addPass(PM, createLoopRotatePass()); addPass(PM, createLICMPass()); // Hoist loop invariants - //addPass(PM, createLoopUnswitchPass()); // Unswitch loops. - //addPass(PM, createLoopIndexSplitPass()); // Index split loops. - //addPass(PM, createIndVarSimplifyPass()); // Canonicalize indvars - //addPass(PM, createLoopDeletionPass()); // Delete dead loops - //addPass(PM, createLoopUnrollPass()); // Unroll small loops*/ + addPass(PM, createLoopUnswitchPass()); // Unswitch loops. + addPass(PM, createLoopIndexSplitPass()); // Index split loops. + addPass(PM, createIndVarSimplifyPass()); // Canonicalize indvars + addPass(PM, createLoopDeletionPass()); // Delete dead loops + addPass(PM, createLoopUnrollPass()); // Unroll small loops*/ addPass(PM, createInstructionCombiningPass()); // Clean up after the unroller addPass(PM, createGVNPass()); // Remove redundancies addPass(PM, createMemCpyOptPass()); // Remove memcpy / form memset addPass(PM, createSCCPPass()); // Constant prop with SCCP + addPass(PM, mvm::createEscapeAnalysisPass(JnjvmModule::JavaObjectAllocateFunction)); addPass(PM, mvm::createLowerConstantCallsPass()); addPass(PM, createGVNPass()); // Remove redundancies Modified: vmkit/trunk/lib/Mvm/EscapeAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/EscapeAnalysis.cpp?rev=52456&r1=52455&r2=52456&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/EscapeAnalysis.cpp (original) +++ vmkit/trunk/lib/Mvm/EscapeAnalysis.cpp Wed Jun 18 05:40:54 2008 @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// +#include "llvm/Constants.h" #include "llvm/Pass.h" #include "llvm/Function.h" #include "llvm/Instructions.h" @@ -16,6 +17,9 @@ #include +#undef DOUT +#define DOUT llvm::cout + using namespace llvm; namespace { @@ -23,17 +27,15 @@ class VISIBILITY_HIDDEN EscapeAnalysis : public FunctionPass { public: static char ID; - EscapeAnalysis(Function* alloc = 0, Function* init = 0) : + EscapeAnalysis(Function* alloc = 0) : FunctionPass((intptr_t)&ID) { Allocator = alloc; - Initialize = init; } virtual bool runOnFunction(Function &F); private: Function* Allocator; - Function* Initialize; - bool processMalloc(Instruction* I); + bool processMalloc(Instruction* I, Value* Size, Value* VT); }; char EscapeAnalysis::ID = 0; RegisterPass X("EscapeAnalysis", "Escape Analysis Pass"); @@ -43,16 +45,16 @@ for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; BI++) { BasicBlock *Cur = BI; - for (BasicBlock::iterator II = Cur->begin(), IE = Cur->end(); II != IE; - II++) { + for (BasicBlock::iterator II = Cur->begin(), IE = Cur->end(); II != IE;) { Instruction *I = II; + II++; if (CallInst *CI = dyn_cast(I)) { if (CI->getOperand(0) == Allocator) { - Changed |= processMalloc(CI); + Changed |= processMalloc(CI, CI->getOperand(1), CI->getOperand(2)); } } else if (InvokeInst *CI = dyn_cast(I)) { if (CI->getOperand(0) == Allocator) { - Changed |= processMalloc(CI); + Changed |= processMalloc(CI, CI->getOperand(3), CI->getOperand(4)); } } } @@ -101,46 +103,33 @@ return false; } -bool EscapeAnalysis::processMalloc(Instruction* I) { +bool EscapeAnalysis::processMalloc(Instruction* I, Value* Size, Value* VT) { Instruction* Alloc = I; - Value::use_iterator UI = I->use_begin(), UE = I->use_end(), Last = I->use_begin(); - while (UI != UE) { Last = UI; UI++;} - - if (BitCastInst *BCI = dyn_cast(Last)) { - I = BCI; - } - std::map visited; - if (!(escapes(Alloc, visited))) { - AllocaInst* AI = new AllocaInst(I->getType()->getContainedType(0), "", Alloc); - BitCastInst* BI = new BitCastInst(AI, Alloc->getType(), "", Alloc); - std::vector Args; - if (isa(Alloc)) { - Args.push_back(Alloc->getOperand(1)); - } else { - Args.push_back(Alloc->getOperand(3)); // skip unwind and normal BB - } - Args.push_back(BI); - Instruction* CI; - if (isa(Alloc)) { - CI = CallInst::Create(Initialize, Args.begin(), Args.end(), "", Alloc); - } else { - CI = InvokeInst::Create(Initialize, ((InvokeInst*)Alloc)->getNormalDest(), - ((InvokeInst*)Alloc)->getUnwindDest(), Args.begin(), - Args.end(), "", Alloc->getParent()); + ConstantExpr* CE = dyn_cast(VT); + if (CE) { + ConstantInt* C = (ConstantInt*)CE->getOperand(0); + VirtualTable* Table = (VirtualTable*)C->getZExtValue(); + // If the class has a finalize method, do not stack allocate the object + if (!((void**)Table)[0]) { + std::map visited; + if (!(escapes(Alloc, visited))) { + AllocaInst* AI = new AllocaInst(Type::Int8Ty, Size, "", Alloc); + BitCastInst* BI = new BitCastInst(AI, Alloc->getType(), "", Alloc); + DOUT << "escape" << Alloc->getParent()->getParent()->getName() << "\n"; + Alloc->replaceAllUsesWith(BI); + Alloc->eraseFromParent(); + return true; + } } - DOUT << "escape" << Alloc->getParent()->getParent()->getName() << "\n"; - Alloc->replaceAllUsesWith(CI); - Alloc->eraseFromParent(); - return true; } return false; } } namespace mvm { -FunctionPass* createEscapeAnalysisPass(llvm::Function* alloc, llvm::Function* init) { +FunctionPass* createEscapeAnalysisPass(llvm::Function* alloc) { - return new EscapeAnalysis(alloc, init); + return new EscapeAnalysis(alloc); } } From nicolas.geoffray at lip6.fr Wed Jun 18 05:42:34 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Wed, 18 Jun 2008 10:42:34 -0000 Subject: [llvm-commits] [vmkit] r52457 - /vmkit/trunk/lib/Mvm/EscapeAnalysis.cpp Message-ID: <200806181042.m5IAgYaJ028986@zion.cs.uiuc.edu> Author: geoffray Date: Wed Jun 18 05:42:32 2008 New Revision: 52457 URL: http://llvm.org/viewvc/llvm-project?rev=52457&view=rev Log: Remove debugging. Modified: vmkit/trunk/lib/Mvm/EscapeAnalysis.cpp Modified: vmkit/trunk/lib/Mvm/EscapeAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/EscapeAnalysis.cpp?rev=52457&r1=52456&r2=52457&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/EscapeAnalysis.cpp (original) +++ vmkit/trunk/lib/Mvm/EscapeAnalysis.cpp Wed Jun 18 05:42:32 2008 @@ -17,9 +17,6 @@ #include -#undef DOUT -#define DOUT llvm::cout - using namespace llvm; namespace { From nicolas.geoffray at lip6.fr Wed Jun 18 05:44:50 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Wed, 18 Jun 2008 10:44:50 -0000 Subject: [llvm-commits] [vmkit] r52458 - /vmkit/trunk/lib/Mvm/EscapeAnalysis.cpp Message-ID: <200806181044.m5IAiomF029078@zion.cs.uiuc.edu> Author: geoffray Date: Wed Jun 18 05:44:48 2008 New Revision: 52458 URL: http://llvm.org/viewvc/llvm-project?rev=52458&view=rev Log: Fix include. Modified: vmkit/trunk/lib/Mvm/EscapeAnalysis.cpp Modified: vmkit/trunk/lib/Mvm/EscapeAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/EscapeAnalysis.cpp?rev=52458&r1=52457&r2=52458&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/EscapeAnalysis.cpp (original) +++ vmkit/trunk/lib/Mvm/EscapeAnalysis.cpp Wed Jun 18 05:44:48 2008 @@ -17,6 +17,8 @@ #include +#include "mvm/GC/GC.h" + using namespace llvm; namespace { From matthijs at stdin.nl Wed Jun 18 06:13:06 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Wed, 18 Jun 2008 11:13:06 -0000 Subject: [llvm-commits] [llvm] r52459 - in /llvm/trunk: lib/Transforms/IPO/DeadArgumentElimination.cpp test/Transforms/DeadArgElim/multdeadretval.ll Message-ID: <200806181113.m5IBD8Mc029979@zion.cs.uiuc.edu> Author: matthijs Date: Wed Jun 18 06:12:53 2008 New Revision: 52459 URL: http://llvm.org/viewvc/llvm-project?rev=52459&view=rev Log: Rewrite the DeadArgumentElimination pass, to use a more explicit tracking of dependencies between return values and/or arguments. Also make the handling of arguments and return values the same. The pass now looks properly inside returned structs, but only at the first level (ie, not inside nested structs). Also add a testcase for testing various variations of (multiple) dead rerturn values. Added: llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll Modified: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Modified: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp?rev=52459&r1=52458&r2=52459&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp (original) +++ llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Wed Jun 18 06:12:53 2008 @@ -10,10 +10,10 @@ // This pass deletes dead arguments from internal functions. Dead argument // elimination removes arguments which are directly dead, as well as arguments // only passed into function calls as dead arguments of other functions. This -// pass also deletes dead arguments in a similar way. +// pass also deletes dead return values in a similar way. // // This pass is often useful as a cleanup pass to run after aggressive -// interprocedural passes, which add possibly-dead arguments. +// interprocedural passes, which add possibly-dead arguments or return values. // //===----------------------------------------------------------------------===// @@ -42,40 +42,66 @@ /// DAE - The dead argument elimination pass. /// class VISIBILITY_HIDDEN DAE : public ModulePass { + public: + + /// Struct that represent either a (part of a) return value or a function + /// argument. Used so that arguments and return values can be used + /// interchangably. + struct RetOrArg { + RetOrArg(const Function* F, unsigned Idx, bool IsArg) : F(F), Idx(Idx), IsArg(IsArg) {} + const Function *F; + unsigned Idx; + bool IsArg; + + /// Make RetOrArg comparable, so we can put it into a map + bool operator<(const RetOrArg &O) const { + if (F != O.F) + return F < O.F; + else if (Idx != O.Idx) + return Idx < O.Idx; + else + return IsArg < O.IsArg; + } + }; + /// Liveness enum - During our initial pass over the program, we determine /// that things are either definately alive, definately dead, or in need of /// interprocedural analysis (MaybeLive). /// enum Liveness { Live, MaybeLive, Dead }; - /// LiveArguments, MaybeLiveArguments, DeadArguments - These sets contain - /// all of the arguments in the program. The Dead set contains arguments - /// which are completely dead (never used in the function). The MaybeLive - /// set contains arguments which are only passed into other function calls, - /// thus may be live and may be dead. The Live set contains arguments which - /// are known to be alive. - /// - std::set DeadArguments, MaybeLiveArguments, LiveArguments; - - /// DeadRetVal, MaybeLiveRetVal, LifeRetVal - These sets contain all of the - /// functions in the program. The Dead set contains functions whose return - /// value is known to be dead. The MaybeLive set contains functions whose - /// return values are only used by return instructions, and the Live set - /// contains functions whose return values are used, functions that are - /// external, and functions that already return void. - /// - std::set DeadRetVal, MaybeLiveRetVal, LiveRetVal; - - /// InstructionsToInspect - As we mark arguments and return values - /// MaybeLive, we keep track of which instructions could make the values - /// live here. Once the entire program has had the return value and - /// arguments analyzed, this set is scanned to promote the MaybeLive objects - /// to be Live if they really are used. - std::vector InstructionsToInspect; - - /// CallSites - Keep track of the call sites of functions that have - /// MaybeLive arguments or return values. - std::multimap CallSites; + /// Convenience wrapper + RetOrArg CreateRet(const Function *F, unsigned Idx) { return RetOrArg(F, Idx, false); } + /// Convenience wrapper + RetOrArg CreateArg(const Function *F, unsigned Idx) { return RetOrArg(F, Idx, true); } + + typedef std::multimap UseMap; + /// This map maps a return value or argument to all return values or + /// arguments it uses. + /// For example (indices are left out for clarity): + /// - Uses[ret F] = ret G + /// This means that F calls G, and F returns the value returned by G. + /// - Uses[arg F] = ret G + /// This means that some function calls G and passes its result as an + /// argument to F. + /// - Uses[ret F] = arg F + /// This means that F returns one of its own arguments. + /// - Uses[arg F] = arg G + /// This means that G calls F and passes one of its own (G's) arguments + /// directly to F. + UseMap Uses; + + typedef std::set LiveSet; + + /// This set contains all values that have been determined to be live + LiveSet LiveValues; + + typedef SmallVector UseVector; + + /// This is the set of functions that have been inspected. Since LiveValues + /// keeps a list of live values for inspected functions only, this way we + /// can prevent uninspected functions becoming completely dead. + std::set InspectedFunctions; public: static char ID; // Pass identification, replacement for typeid @@ -85,20 +111,19 @@ virtual bool ShouldHackArguments() const { return false; } private: - Liveness getArgumentLiveness(const Argument &A); - bool isMaybeLiveArgumentNowLive(Argument *Arg); - + Liveness IsMaybeLive(RetOrArg Use, UseVector &MaybeLiveUses); + Liveness SurveyUse(Value::use_iterator U, UseVector &MaybeLiveUses, unsigned RetValNum = 0); + Liveness SurveyUses(Value *V, UseVector &MaybeLiveUses); + + void SurveyFunction(Function &F); + void MarkValue(const RetOrArg &RA, Liveness L, const UseVector &MaybeLiveUses); + void MarkLive(RetOrArg RA); + bool RemoveDeadStuffFromFunction(Function *F); bool DeleteDeadVarargs(Function &Fn); - void SurveyFunction(Function &Fn); - - void MarkArgumentLive(Argument *Arg); - void MarkRetValLive(Function *F); - void MarkReturnInstArgumentLive(ReturnInst *RI); - - void RemoveDeadArgumentsFromFunction(Function *F); }; } + char DAE::ID = 0; static RegisterPass X("deadargelim", "Dead Argument Elimination"); @@ -155,7 +180,7 @@ // remove the "..." and adjust all the calls. // Start by computing a new prototype for the function, which is the same as - // the old function, but has fewer arguments. + // the old function, but doesn't have isVarArg set. const FunctionType *FTy = Fn.getFunctionType(); std::vector Params(FTy->param_begin(), FTy->param_end()); FunctionType *NFTy = FunctionType::get(FTy->getReturnType(), Params, false); @@ -233,57 +258,110 @@ return true; } +/// Convenience function that returns the number of return values. It returns 0 +/// for void functions and 1 for functions not returning a struct. It returns +/// the number of struct elements for functions returning a struct. +static unsigned NumRetVals(const Function *F) { + if (F->getReturnType() == Type::VoidTy) + return 0; + else if (const StructType *STy = dyn_cast(F->getReturnType())) + return STy->getNumElements(); + else + return 1; +} -static inline bool CallPassesValueThoughVararg(Instruction *Call, - const Value *Arg) { - CallSite CS = CallSite::get(Call); - const Type *CalledValueTy = CS.getCalledValue()->getType(); - const Type *FTy = cast(CalledValueTy)->getElementType(); - unsigned NumFixedArgs = cast(FTy)->getNumParams(); - for (CallSite::arg_iterator AI = CS.arg_begin()+NumFixedArgs; - AI != CS.arg_end(); ++AI) - if (AI->get() == Arg) - return true; - return false; -} - -// getArgumentLiveness - Inspect an argument, determining if is known Live -// (used in a computation), MaybeLive (only passed as an argument to a call), or -// Dead (not used). -DAE::Liveness DAE::getArgumentLiveness(const Argument &A) { - const Function *F = A.getParent(); - - // If this is the return value of a struct function, it's not really dead. - if (F->hasStructRetAttr() && &*(F->arg_begin()) == &A) +/// IsMaybeAlive - This checks Use for liveness. If Use is live, returns Live, +/// else returns MaybeLive. Also, adds Use to MaybeLiveUses in the latter case. +DAE::Liveness DAE::IsMaybeLive(RetOrArg Use, UseVector &MaybeLiveUses) { + // We're live if our use is already marked as live + if (LiveValues.count(Use)) return Live; - - if (A.use_empty()) // First check, directly dead? - return Dead; - // Scan through all of the uses, looking for non-argument passing uses. - for (Value::use_const_iterator I = A.use_begin(), E = A.use_end(); I!=E;++I) { - // Return instructions do not immediately effect liveness. - if (isa(*I)) - continue; - - CallSite CS = CallSite::get(const_cast(*I)); - if (!CS.getInstruction()) { - // If its used by something that is not a call or invoke, it's alive! - return Live; - } - // If it's an indirect call, mark it alive... - Function *Callee = CS.getCalledFunction(); - if (!Callee) return Live; - - // Check to see if it's passed through a va_arg area: if so, we cannot - // remove it. - if (CallPassesValueThoughVararg(CS.getInstruction(), &A)) - return Live; // If passed through va_arg area, we cannot remove it - } + // We're maybe live otherwise, but remember that we must become live if + // Use becomes live. + MaybeLiveUses.push_back(Use); + return MaybeLive; +} + - return MaybeLive; // It must be used, but only as argument to a function +/// SurveyUse - This looks at a single use of an argument or return value +/// and determines if it should be alive or not. Adds this use to MaybeLiveUses +/// if it causes the used value to become MaybeAlive. +/// +/// RetValNum is the return value number to use when this use is used in a +/// return instruction. This is used in the recursion, you should always leave +/// it at 0. +DAE::Liveness DAE::SurveyUse(Value::use_iterator U, UseVector &MaybeLiveUses, unsigned RetValNum) { + Value *V = *U; + if (ReturnInst *RI = dyn_cast(V)) { + // The value is returned from another function. It's only live when the + // caller's return value is live + RetOrArg Use = CreateRet(RI->getParent()->getParent(), RetValNum); + // We might be live, depending on the liveness of Use + return IsMaybeLive(Use, MaybeLiveUses); + } + if (InsertValueInst *IV = dyn_cast(V)) { + if (U.getOperandNo() != InsertValueInst::getAggregateOperandIndex() && IV->hasIndices()) + // The use we are examining is inserted into an aggregate. Our liveness + // depends on all uses of that aggregate, but if it is used as a return + // value, only index at which we were inserted counts. + RetValNum = *IV->idx_begin(); + + // Note that if we are used as the aggregate operand to the insertvalue, + // we don't change RetValNum, but do survey all our uses. + + Liveness Result = Dead; + for (Value::use_iterator I = IV->use_begin(), + E = V->use_end(); I != E; ++I) { + Result = SurveyUse(I, MaybeLiveUses, RetValNum); + if (Result == Live) + break; + } + return Result; + } + CallSite CS = CallSite::get(V); + if (CS.getInstruction()) { + Function *F = CS.getCalledFunction(); + if (F) { + // Used in a direct call + + // Check for vararg. Do - 1 to skip the first operand to call (the + // function itself). + if (U.getOperandNo() - 1 >= F->getFunctionType()->getNumParams()) + // The value is passed in through a vararg! Must be live. + return Live; + + // Value passed to a normal call. It's only live when the corresponding + // argument (operand number - 1 to skip the function pointer operand) to + // the called function turns out live + RetOrArg Use = CreateArg(F, U.getOperandNo() - 1); + return IsMaybeLive(Use, MaybeLiveUses); + } else { + // Used in any other way? Value must be live. + return Live; + } + } + // Used in any other way? Value must be live. + return Live; } +/// SurveyUses - This looks at all the uses of the given return value +/// (possibly a partial return value from a function returning a struct). +/// Returns the Liveness deduced from the uses of this value. +/// +/// Adds all uses that cause the result to be MaybeLive to MaybeLiveRetUses. +DAE::Liveness DAE::SurveyUses(Value *V, UseVector &MaybeLiveUses) { + // Assume it's dead (which will only hold if there are no uses at all..) + Liveness Result = Dead; + // Check each use + for (Value::use_iterator I = V->use_begin(), + E = V->use_end(); I != E; ++I) { + Result = SurveyUse(I, MaybeLiveUses); + if (Result == Live) + break; + } + return Result; +} // SurveyFunction - This performs the initial survey of the specified function, // checking out whether or not it uses any of its incoming arguments or whether @@ -294,13 +372,36 @@ // well as arguments to functions which have their "address taken". // void DAE::SurveyFunction(Function &F) { + InspectedFunctions.insert(&F); bool FunctionIntrinsicallyLive = false; - Liveness RetValLiveness = F.getReturnType() == Type::VoidTy ? Live : Dead; - - if (!F.hasInternalLinkage() && - (!ShouldHackArguments() || F.isIntrinsic())) + unsigned RetCount = NumRetVals(&F); + // Assume all return values are dead + typedef SmallVector RetVals; + RetVals RetValLiveness(RetCount, Dead); + + // These vectors maps each return value to the uses that make it MaybeLive, so + // we can add those to the MaybeLiveRetVals list if the return value + // really turns out to be MaybeLive. Initializes to RetCount empty vectors + typedef SmallVector RetUses; + // Intialized to a list of RetCount empty lists + RetUses MaybeLiveRetUses(RetCount); + + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + if (ReturnInst *RI = dyn_cast(BB->getTerminator())) + if (RI->getNumOperands() != 0 && RI->getOperand(0)->getType() != F.getFunctionType()->getReturnType()) { + // We don't support old style multiple return values + FunctionIntrinsicallyLive = true; + break; + } + if (!F.hasInternalLinkage() && (!ShouldHackArguments() || F.isIntrinsic())) FunctionIntrinsicallyLive = true; - else + if (!FunctionIntrinsicallyLive) { + DOUT << "DAE - Inspecting callers for fn: " << F.getName() << "\n"; + // Keep track of the number of live retvals, so we can skip checks once all + // of them turn out to be live. + unsigned NumLiveRetVals = 0; + const Type *STy = dyn_cast(F.getReturnType()); + // Loop all uses of the function for (Value::use_iterator I = F.use_begin(), E = F.use_end(); I != E; ++I) { // If the function is PASSED IN as an argument, its address has been taken if (I.getOperandNo() != 0) { @@ -315,191 +416,138 @@ FunctionIntrinsicallyLive = true; break; } - - // Check to see if the return value is used... - if (RetValLiveness != Live) - for (Value::use_iterator I = TheCall->use_begin(), - E = TheCall->use_end(); I != E; ++I) - if (isa(cast(*I))) { - RetValLiveness = MaybeLive; - } else if (isa(cast(*I)) || - isa(cast(*I))) { - if (CallPassesValueThoughVararg(cast(*I), TheCall) || - !CallSite::get(cast(*I)).getCalledFunction()) { - RetValLiveness = Live; - break; + + // If we end up here, we are looking at a direct call to our function. + + // Now, check how our return value(s) is/are used in this caller. Don't + // bother checking return values if all of them are live already + if (NumLiveRetVals != RetCount) { + if (STy) { + // Check all uses of the return value + for (Value::use_iterator I = TheCall->use_begin(), + E = TheCall->use_end(); I != E; ++I) { + ExtractValueInst *Ext = dyn_cast(*I); + if (Ext && Ext->hasIndices()) { + // This use uses a part of our return value, survey the uses of that + // part and store the results for this index only. + unsigned Idx = *Ext->idx_begin(); + if (RetValLiveness[Idx] != Live) { + RetValLiveness[Idx] = SurveyUses(Ext, MaybeLiveRetUses[Idx]); + if (RetValLiveness[Idx] == Live) + NumLiveRetVals++; + } } else { - RetValLiveness = MaybeLive; + // Used by something else than extractvalue. Mark all + // return values as live. + for (unsigned i = 0; i != RetCount; ++i ) + RetValLiveness[i] = Live; + NumLiveRetVals = RetCount; + break; } - } else { - RetValLiveness = Live; - break; } + } else { + // Single return value + RetValLiveness[0] = SurveyUses(TheCall, MaybeLiveRetUses[0]); + if (RetValLiveness[0] == Live) + NumLiveRetVals = RetCount; + } + } } - + } if (FunctionIntrinsicallyLive) { - DOUT << " Intrinsically live fn: " << F.getName() << "\n"; + DOUT << "DAE - Intrinsically live fn: " << F.getName() << "\n"; + // Mark all arguments as live + unsigned i = 0; for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end(); - AI != E; ++AI) - LiveArguments.insert(AI); - LiveRetVal.insert(&F); + AI != E; ++AI, ++i) + MarkLive(CreateArg(&F, i)); + // Mark all return values as live + i = 0; + for (unsigned i = 0, e = RetValLiveness.size(); i != e; ++i) + MarkLive(CreateRet(&F, i)); return; } - - switch (RetValLiveness) { - case Live: LiveRetVal.insert(&F); break; - case MaybeLive: MaybeLiveRetVal.insert(&F); break; - case Dead: DeadRetVal.insert(&F); break; + + // Now we've inspected all callers, record the liveness of our return values. + for (unsigned i = 0, e = RetValLiveness.size(); i != e; ++i) { + RetOrArg Ret = CreateRet(&F, i); + // Mark the result down + MarkValue(Ret, RetValLiveness[i], MaybeLiveRetUses[i]); + } + DOUT << "DAE - Inspecting args for fn: " << F.getName() << "\n"; + + // Now, check all of our arguments + unsigned i = 0; + UseVector MaybeLiveArgUses; + for (Function::arg_iterator AI = F.arg_begin(), + E = F.arg_end(); AI != E; ++AI, ++i) { + // See what the effect of this use is (recording any uses that cause + // MaybeLive in MaybeLiveArgUses) + Liveness Result = SurveyUses(AI, MaybeLiveArgUses); + RetOrArg Arg = CreateArg(&F, i); + // Mark the result down + MarkValue(Arg, Result, MaybeLiveArgUses); + // Clear the vector again for the next iteration + MaybeLiveArgUses.clear(); } +} - DOUT << " Inspecting args for fn: " << F.getName() << "\n"; - - // If it is not intrinsically alive, we know that all users of the - // function are call sites. Mark all of the arguments live which are - // directly used, and keep track of all of the call sites of this function - // if there are any arguments we assume that are dead. - // - bool AnyMaybeLiveArgs = false; - for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end(); - AI != E; ++AI) - switch (getArgumentLiveness(*AI)) { - case Live: - DOUT << " Arg live by use: " << AI->getName() << "\n"; - LiveArguments.insert(AI); - break; - case Dead: - DOUT << " Arg definitely dead: " << AI->getName() <<"\n"; - DeadArguments.insert(AI); - break; +/// MarkValue - This function marks the liveness of RA depending on L. If L is +/// MaybeLive, it also records any uses in MaybeLiveUses such that RA will be +/// marked live if any use in MaybeLiveUses gets marked live later on. +void DAE::MarkValue(const RetOrArg &RA, Liveness L, const UseVector &MaybeLiveUses) { + switch (L) { + case Live: MarkLive(RA); break; case MaybeLive: - DOUT << " Arg only passed to calls: " << AI->getName() << "\n"; - AnyMaybeLiveArgs = true; - MaybeLiveArguments.insert(AI); + { + // Note any uses of this value, so this return value can be + // marked live whenever one of the uses becomes live. + UseMap::iterator Where = Uses.begin(); + for (UseVector::const_iterator UI = MaybeLiveUses.begin(), + UE = MaybeLiveUses.end(); UI != UE; ++UI) + Where = Uses.insert(Where, UseMap::value_type(*UI, RA)); break; } - - // If there are any "MaybeLive" arguments, we need to check callees of - // this function when/if they become alive. Record which functions are - // callees... - if (AnyMaybeLiveArgs || RetValLiveness == MaybeLive) - for (Value::use_iterator I = F.use_begin(), E = F.use_end(); - I != E; ++I) { - if (AnyMaybeLiveArgs) - CallSites.insert(std::make_pair(&F, CallSite::get(*I))); - - if (RetValLiveness == MaybeLive) - for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); - UI != E; ++UI) - InstructionsToInspect.push_back(cast(*UI)); - } -} - -// isMaybeLiveArgumentNowLive - Check to see if Arg is alive. At this point, we -// know that the only uses of Arg are to be passed in as an argument to a -// function call or return. Check to see if the formal argument passed in is in -// the LiveArguments set. If so, return true. -// -bool DAE::isMaybeLiveArgumentNowLive(Argument *Arg) { - for (Value::use_iterator I = Arg->use_begin(), E = Arg->use_end(); I!=E; ++I){ - if (isa(*I)) { - if (LiveRetVal.count(Arg->getParent())) return true; - continue; - } - - CallSite CS = CallSite::get(*I); - - // We know that this can only be used for direct calls... - Function *Callee = CS.getCalledFunction(); - - // Loop over all of the arguments (because Arg may be passed into the call - // multiple times) and check to see if any are now alive... - CallSite::arg_iterator CSAI = CS.arg_begin(); - for (Function::arg_iterator AI = Callee->arg_begin(), E = Callee->arg_end(); - AI != E; ++AI, ++CSAI) - // If this is the argument we are looking for, check to see if it's alive - if (*CSAI == Arg && LiveArguments.count(AI)) - return true; - } - return false; -} - -/// MarkArgumentLive - The MaybeLive argument 'Arg' is now known to be alive. -/// Mark it live in the specified sets and recursively mark arguments in callers -/// live that are needed to pass in a value. -/// -void DAE::MarkArgumentLive(Argument *Arg) { - std::set::iterator It = MaybeLiveArguments.lower_bound(Arg); - if (It == MaybeLiveArguments.end() || *It != Arg) return; - - DOUT << " MaybeLive argument now live: " << Arg->getName() <<"\n"; - MaybeLiveArguments.erase(It); - LiveArguments.insert(Arg); - - // Loop over all of the call sites of the function, making any arguments - // passed in to provide a value for this argument live as necessary. - // - Function *Fn = Arg->getParent(); - unsigned ArgNo = std::distance(Fn->arg_begin(), Function::arg_iterator(Arg)); - - std::multimap::iterator I = CallSites.lower_bound(Fn); - for (; I != CallSites.end() && I->first == Fn; ++I) { - CallSite CS = I->second; - Value *ArgVal = *(CS.arg_begin()+ArgNo); - if (Argument *ActualArg = dyn_cast(ArgVal)) { - MarkArgumentLive(ActualArg); - } else { - // If the value passed in at this call site is a return value computed by - // some other call site, make sure to mark the return value at the other - // call site as being needed. - CallSite ArgCS = CallSite::get(ArgVal); - if (ArgCS.getInstruction()) - if (Function *Fn = ArgCS.getCalledFunction()) - MarkRetValLive(Fn); - } + case Dead: break; } } -/// MarkArgumentLive - The MaybeLive return value for the specified function is -/// now known to be alive. Propagate this fact to the return instructions which -/// produce it. -void DAE::MarkRetValLive(Function *F) { - assert(F && "Shame shame, we can't have null pointers here!"); - - // Check to see if we already knew it was live - std::set::iterator I = MaybeLiveRetVal.lower_bound(F); - if (I == MaybeLiveRetVal.end() || *I != F) return; // It's already alive! - - DOUT << " MaybeLive retval now live: " << F->getName() << "\n"; +/// MarkLive - Mark the given return value or argument as live. Additionally, +/// mark any values that are used by this value (according to Uses) live as +/// well. +void DAE::MarkLive(RetOrArg RA) { + if (!LiveValues.insert(RA).second) + return; // We were already marked Live - MaybeLiveRetVal.erase(I); - LiveRetVal.insert(F); // It is now known to be live! + if (RA.IsArg) + DOUT << "DAE - Marking argument " << RA.Idx << " to function " << RA.F->getNameStart() << " live\n"; + else + DOUT << "DAE - Marking return value " << RA.Idx << " of function " << RA.F->getNameStart() << " live\n"; - // Loop over all of the functions, noticing that the return value is now live. - for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) - if (ReturnInst *RI = dyn_cast(BB->getTerminator())) - MarkReturnInstArgumentLive(RI); + std::pair Range = Uses.equal_range(RA); + UseMap::iterator E = Range.second; + UseMap::iterator I = Range.first; + for (; I != E; ++I) + MarkLive(I->second); + // Erase RA from the Uses map (from the lower bound to wherever we ended up + // after the loop). + Uses.erase(Range.first, Range.second); } -void DAE::MarkReturnInstArgumentLive(ReturnInst *RI) { - Value *Op = RI->getOperand(0); - if (Argument *A = dyn_cast(Op)) { - MarkArgumentLive(A); - } else if (CallInst *CI = dyn_cast(Op)) { - if (Function *F = CI->getCalledFunction()) - MarkRetValLive(F); - } else if (InvokeInst *II = dyn_cast(Op)) { - if (Function *F = II->getCalledFunction()) - MarkRetValLive(F); - } -} - -// RemoveDeadArgumentsFromFunction - We know that F has dead arguments, as +// RemoveDeadStuffFromFunction - Remove any arguments and return values from F +// that are not in LiveValues. This function is a noop for any Function created +// by this function before, or any function that was not inspected for liveness. // specified by the DeadArguments list. Transform the function and all of the // callees of the function to not have these arguments. // -void DAE::RemoveDeadArgumentsFromFunction(Function *F) { +bool DAE::RemoveDeadStuffFromFunction(Function *F) { + // Don't process functions we didn't inspect (such as external functions, or + // functions that we've newly created). + if (!InspectedFunctions.count(F)) + return false; + // Start by computing a new prototype for the function, which is the same as - // the old function, but has fewer arguments. + // the old function, but has fewer arguments and a different return type. const FunctionType *FTy = F->getFunctionType(); std::vector Params; @@ -510,28 +558,78 @@ // The existing function return attributes. ParameterAttributes RAttrs = PAL.getParamAttrs(0); - // Make the function return void if the return value is dead. + + // Find out the new return value + const Type *RetTy = FTy->getReturnType(); - if (DeadRetVal.count(F)) { - RetTy = Type::VoidTy; - RAttrs &= ~ParamAttr::typeIncompatible(RetTy); - DeadRetVal.erase(F); - } - + const Type *NRetTy; + unsigned RetCount = NumRetVals(F); + // -1 means unused, other numbers are the new index + SmallVector NewRetIdxs(RetCount, -1); + std::vector RetTypes; + if (RetTy != Type::VoidTy) { + const StructType *STy = dyn_cast(RetTy); + if (STy) + // Look at each of the original return values individually + for (unsigned i = 0; i != RetCount; ++i) { + RetOrArg Ret = CreateRet(F, i); + if (LiveValues.erase(Ret)) { + RetTypes.push_back(STy->getElementType(i)); + NewRetIdxs[i] = RetTypes.size() - 1; + } else { + ++NumRetValsEliminated; + DOUT << "DAE - Removing return value " << i << " from " << F->getNameStart() << "\n"; + } + } + else + // We used to return a single value + if (LiveValues.erase(CreateRet(F, 0))) { + RetTypes.push_back(RetTy); + NewRetIdxs[0] = 0; + } else { + DOUT << "DAE - Removing return value from " << F->getNameStart() << "\n"; + ++NumRetValsEliminated; + } + if (RetTypes.size() == 0) + // No return types? Make it void + NRetTy = Type::VoidTy; + else if (RetTypes.size() == 1) + // One return type? Just a simple value then + NRetTy = RetTypes.front(); + else + // More return types? Return a struct with them + NRetTy = StructType::get(RetTypes); + } else { + NRetTy = Type::VoidTy; + } + + // Remove any incompatible attributes + RAttrs &= ~ParamAttr::typeIncompatible(NRetTy); if (RAttrs) ParamAttrsVec.push_back(ParamAttrsWithIndex::get(0, RAttrs)); - + + // Remember which arguments are still alive + SmallVector ArgAlive(FTy->getNumParams(), false); // Construct the new parameter list from non-dead arguments. Also construct - // a new set of parameter attributes to correspond. - unsigned index = 1; - for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; - ++I, ++index) - if (!DeadArguments.count(I)) { + // a new set of parameter attributes to correspond. Skip the first parameter + // attribute, since that belongs to the return value. + unsigned i = 0; + for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); + I != E; ++I, ++i) { + RetOrArg Arg = CreateArg(F, i); + if (LiveValues.erase(Arg)) { Params.push_back(I->getType()); + ArgAlive[i] = true; - if (ParameterAttributes Attrs = PAL.getParamAttrs(index)) + // Get the original parameter attributes (skipping the first one, that is + // for the return value + if (ParameterAttributes Attrs = PAL.getParamAttrs(i + 1)) ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Params.size(), Attrs)); + } else { + ++NumArgumentsEliminated; + DOUT << "DAE - Removing argument " << i << " (" << I->getNameStart() << ") from " << F->getNameStart() << "\n"; } + } // Reconstruct the ParamAttrsList based on the vector we constructed. PAListPtr NewPAL = PAListPtr::get(ParamAttrsVec.begin(), ParamAttrsVec.end()); @@ -546,7 +644,11 @@ } // Create the new function type based on the recomputed parameters. - FunctionType *NFTy = FunctionType::get(RetTy, Params, FTy->isVarArg()); + FunctionType *NFTy = FunctionType::get(NRetTy, Params, FTy->isVarArg()); + + // No change? + if (NFTy == FTy) + return false; // Create the new function body and insert it into the module... Function *NF = Function::Create(NFTy, F->getLinkage()); @@ -572,14 +674,17 @@ if (RAttrs) ParamAttrsVec.push_back(ParamAttrsWithIndex::get(0, RAttrs)); - // Loop over the operands, deleting dead ones... - CallSite::arg_iterator AI = CS.arg_begin(); - index = 1; - for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); - I != E; ++I, ++AI, ++index) - if (!DeadArguments.count(I)) { // Remove operands for dead arguments - Args.push_back(*AI); - if (ParameterAttributes Attrs = CallPAL.getParamAttrs(index)) + // Declare these outside of the loops, so we can reuse them for the second + // loop, which loops the varargs + CallSite::arg_iterator I = CS.arg_begin(); + unsigned i = 0; + // Loop over those operands, corresponding to the normal arguments to the + // original function, and add those that are still alive. + for (unsigned e = FTy->getNumParams(); i != e; ++I, ++i) + if (ArgAlive[i]) { + Args.push_back(*I); + // Get original parameter attributes, but skip return attributes + if (ParameterAttributes Attrs = CallPAL.getParamAttrs(i + 1)) ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Args.size(), Attrs)); } @@ -587,9 +692,9 @@ Args.push_back(UndefValue::get(Type::Int32Ty)); // Push any varargs arguments on the list. Don't forget their attributes. - for (; AI != CS.arg_end(); ++AI) { - Args.push_back(*AI); - if (ParameterAttributes Attrs = CallPAL.getParamAttrs(index++)) + for (CallSite::arg_iterator E = CS.arg_end(); I != E; ++I, ++i) { + Args.push_back(*I); + if (ParameterAttributes Attrs = CallPAL.getParamAttrs(i + 1)) ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Args.size(), Attrs)); } @@ -614,8 +719,45 @@ if (!Call->use_empty()) { if (New->getType() == Type::VoidTy) + // Our return value was unused, replace by null for now, uses will get + // removed later on Call->replaceAllUsesWith(Constant::getNullValue(Call->getType())); - else { + else if (isa(RetTy)) { + // The original return value was a struct, update all uses (which are + // all extractvalue instructions). + for (Value::use_iterator I = Call->use_begin(), E = Call->use_end(); + I != E;) { + assert(isa(*I) && "Return value not only used by extractvalue?"); + ExtractValueInst *EV = cast(*I); + // Increment now, since we're about to throw away this use. + ++I; + assert(EV->hasIndices() && "Return value used by extractvalue without indices?"); + unsigned Idx = *EV->idx_begin(); + if (NewRetIdxs[Idx] != -1) { + if (RetTypes.size() > 1) { + // We're still returning a struct, create a new extractvalue + // instruction with the first index updated + std::vector NewIdxs(EV->idx_begin(), EV->idx_end()); + NewIdxs[0] = NewRetIdxs[Idx]; + Value *NEV = ExtractValueInst::Create(New, NewIdxs.begin(), NewIdxs.end(), "retval", EV); + EV->replaceAllUsesWith(NEV); + EV->eraseFromParent(); + } else { + // We are now only returning a simple value, remove the + // extractvalue + EV->replaceAllUsesWith(New); + EV->eraseFromParent(); + } + } else { + // Value unused, replace uses by null for now, they will get removed + // later on + EV->replaceAllUsesWith(Constant::getNullValue(EV->getType())); + EV->eraseFromParent(); + } + } + New->takeName(Call); + } else { + // The original function had a single return value Call->replaceAllUsesWith(New); New->takeName(Call); } @@ -632,13 +774,11 @@ NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList()); // Loop over the argument list, transfering uses of the old arguments over to - // the new arguments, also transfering over the names as well. While we're at - // it, remove the dead arguments from the DeadArguments list. - // + // the new arguments, also transfering over the names as well. + i = 0; for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(), - I2 = NF->arg_begin(); - I != E; ++I) - if (!DeadArguments.count(I)) { + I2 = NF->arg_begin(); I != E; ++I, ++i) + if (ArgAlive[i]) { // If this is a live argument, move the name and users over to the new // version. I->replaceAllUsesWith(I2); @@ -646,10 +786,8 @@ ++I2; } else { // If this argument is dead, replace any uses of it with null constants - // (these are guaranteed to only be operands to call instructions which - // will later be simplified). + // (these are guaranteed to become unused later on) I->replaceAllUsesWith(Constant::getNullValue(I->getType())); - DeadArguments.erase(I); } // If we change the return value of the function we must rewrite any return @@ -657,12 +795,45 @@ if (F->getReturnType() != NF->getReturnType()) for (Function::iterator BB = NF->begin(), E = NF->end(); BB != E; ++BB) if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { - ReturnInst::Create(0, RI); + Value *RetVal; + + if (NFTy->getReturnType() == Type::VoidTy) { + RetVal = 0; + } else { + assert (isa(RetTy)); + // The original return value was a struct, insert + // extractvalue/insertvalue chains to extract only the values we need + // to return and insert them into our new result. + // This does generate messy code, but we'll let it to instcombine to + // clean that up + Value *OldRet = RI->getOperand(0); + // Start out building up our return value from undef + RetVal = llvm::UndefValue::get(NRetTy); + for (unsigned i = 0; i != RetCount; ++i) + if (NewRetIdxs[i] != -1) { + ExtractValueInst *EV = ExtractValueInst::Create(OldRet, i, "newret", RI); + if (RetTypes.size() > 1) { + // We're still returning a struct, so reinsert the value into + // our new return value at the new index + + RetVal = InsertValueInst::Create(RetVal, EV, NewRetIdxs[i], "oldret"); + } else { + // We are now only returning a simple value, so just return the + // extracted value + RetVal = EV; + } + } + } + // Replace the return instruction with one returning the new return + // value (possibly 0 if we became void). + ReturnInst::Create(RetVal, RI); BB->getInstList().erase(RI); } // Now that the old function is dead, delete it. F->eraseFromParent(); + + return true; } bool DAE::runOnModule(Module &M) { @@ -677,7 +848,7 @@ if (F.getFunctionType()->isVarArg()) Changed |= DeleteDeadVarargs(F); } - + // Second phase:loop through the module, determining which arguments are live. // We assume all arguments are dead unless proven otherwise (allowing us to // determine that dead arguments passed into recursive functions are dead). @@ -686,85 +857,14 @@ for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) SurveyFunction(*I); - // Loop over the instructions to inspect, propagating liveness among arguments - // and return values which are MaybeLive. - while (!InstructionsToInspect.empty()) { - Instruction *I = InstructionsToInspect.back(); - InstructionsToInspect.pop_back(); - - if (ReturnInst *RI = dyn_cast(I)) { - // For return instructions, we just have to check to see if the return - // value for the current function is known now to be alive. If so, any - // arguments used by it are now alive, and any call instruction return - // value is alive as well. - if (LiveRetVal.count(RI->getParent()->getParent())) - MarkReturnInstArgumentLive(RI); - - } else { - CallSite CS = CallSite::get(I); - assert(CS.getInstruction() && "Unknown instruction for the I2I list!"); - - Function *Callee = CS.getCalledFunction(); - - // If we found a call or invoke instruction on this list, that means that - // an argument of the function is a call instruction. If the argument is - // live, then the return value of the called instruction is now live. - // - CallSite::arg_iterator AI = CS.arg_begin(); // ActualIterator - for (Function::arg_iterator FI = Callee->arg_begin(), - E = Callee->arg_end(); FI != E; ++AI, ++FI) { - // If this argument is another call... - CallSite ArgCS = CallSite::get(*AI); - if (ArgCS.getInstruction() && LiveArguments.count(FI)) - if (Function *Callee = ArgCS.getCalledFunction()) - MarkRetValLive(Callee); - } - } + // Now, remove all dead arguments and return values from each function in + // turn + for (Module::iterator I = M.begin(), E = M.end(); I != E; ) { + // Increment now, because the function will probably get removed (ie + // replaced by a new one) + Function *F = I++; + Changed |= RemoveDeadStuffFromFunction(F); } - // Now we loop over all of the MaybeLive arguments, promoting them to be live - // arguments if one of the calls that uses the arguments to the calls they are - // passed into requires them to be live. Of course this could make other - // arguments live, so process callers recursively. - // - // Because elements can be removed from the MaybeLiveArguments set, copy it to - // a temporary vector. - // - std::vector TmpArgList(MaybeLiveArguments.begin(), - MaybeLiveArguments.end()); - for (unsigned i = 0, e = TmpArgList.size(); i != e; ++i) { - Argument *MLA = TmpArgList[i]; - if (MaybeLiveArguments.count(MLA) && - isMaybeLiveArgumentNowLive(MLA)) - MarkArgumentLive(MLA); - } - - // Recover memory early... - CallSites.clear(); - - // At this point, we know that all arguments in DeadArguments and - // MaybeLiveArguments are dead. If the two sets are empty, there is nothing - // to do. - if (MaybeLiveArguments.empty() && DeadArguments.empty() && - MaybeLiveRetVal.empty() && DeadRetVal.empty()) - return Changed; - - // Otherwise, compact into one set, and start eliminating the arguments from - // the functions. - DeadArguments.insert(MaybeLiveArguments.begin(), MaybeLiveArguments.end()); - MaybeLiveArguments.clear(); - DeadRetVal.insert(MaybeLiveRetVal.begin(), MaybeLiveRetVal.end()); - MaybeLiveRetVal.clear(); - - LiveArguments.clear(); - LiveRetVal.clear(); - - NumArgumentsEliminated += DeadArguments.size(); - NumRetValsEliminated += DeadRetVal.size(); - while (!DeadArguments.empty()) - RemoveDeadArgumentsFromFunction((*DeadArguments.begin())->getParent()); - - while (!DeadRetVal.empty()) - RemoveDeadArgumentsFromFunction(*DeadRetVal.begin()); - return true; + return Changed; } Added: llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll?rev=52459&view=auto ============================================================================== --- llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll (added) +++ llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll Wed Jun 18 06:12:53 2008 @@ -0,0 +1,39 @@ +; This test sees if return values (and arguments) are properly removed when they +; are unused. All unused values are typed i16, so we can easily check. We also +; run instcombine to fold insert/extractvalue chains and we run dce to clean up +; any remaining dead stuff. +; RUN: llvm-as < %s | opt -deadargelim -instcombine -dce | llvm-dis | not grep i16 + +define internal {i16, i32} @test(i16 %DEADARG) { + %A = insertvalue {i16,i32} undef, i16 1, 0 + %B = insertvalue {i16,i32} %A, i32 1001, 1 + ret {i16,i32} %B +} + +define internal {i32, i16} @test2() { + %DEAD = call i16 @test4() + %A = insertvalue {i32,i16} undef, i32 1, 0 + %B = insertvalue {i32,i16} %A, i16 %DEAD, 1 + ret {i32,i16} %B +} + +define internal i32 @test3(i16 %A) { + %ret = call {i16, i32} @test( i16 %A ) ; [#uses=0] + %DEAD = extractvalue {i16, i32} %ret, 0 + %LIVE = extractvalue {i16, i32} %ret, 1 + ret i32 %LIVE +} + +define internal i16 @test4() { + ret i16 0 +} + +define i32 @main() { + %ret = call {i32, i16} @test2() ; [#uses=1] + %LIVE = extractvalue {i32, i16} %ret, 0 + %DEAD = extractvalue {i32, i16} %ret, 1 + %Y = add i32 %LIVE, -123 ; [#uses=1] + %LIVE2 = call i32 @test3(i16 %DEAD) ; [#uses=1] + %Z = add i32 %LIVE2, %Y ; [#uses=1] + ret i32 %Z +} From ggreif at gmail.com Wed Jun 18 08:44:59 2008 From: ggreif at gmail.com (Gabor Greif) Date: Wed, 18 Jun 2008 13:44:59 -0000 Subject: [llvm-commits] [llvm] r52460 - /llvm/trunk/docs/ProgrammersManual.html Message-ID: <200806181345.m5IDj0MW002851@zion.cs.uiuc.edu> Author: ggreif Date: Wed Jun 18 08:44:57 2008 New Revision: 52460 URL: http://llvm.org/viewvc/llvm-project?rev=52460&view=rev Log: prettify, no semantic changes Modified: llvm/trunk/docs/ProgrammersManual.html Modified: llvm/trunk/docs/ProgrammersManual.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/ProgrammersManual.html?rev=52460&r1=52459&r2=52460&view=diff ============================================================================== --- llvm/trunk/docs/ProgrammersManual.html (original) +++ llvm/trunk/docs/ProgrammersManual.html Wed Jun 18 08:44:57 2008 @@ -2235,82 +2235,96 @@ User class provides a base for expressing the ownership of User towards other Values. The -Use helper class is employed to do the bookkeeping and facilitate O(1) +Use helper class is employed to do the bookkeeping and to facilitate O(1) addition and removal.

    -
    -   -----------------------------------------------------------------
    -   --- Interaction and relationship between User and Use objects ---
    -   -----------------------------------------------------------------
    -
    +
    +
     
    -A subclass of User can choose between incorporating its Use objects
    +
    +

    +A subclass of User can choose between incorporating its Use objects or refer to them out-of-line by means of a pointer. A mixed variant -(some Uses inline others hung off) is impractical and breaks the invariant -that the Use objects belonging to the same User form a contiguous array. - -We have 2 different layouts in the User (sub)classes: - -Layout a) -The Use object(s) are inside (resp. at fixed offset) of the User -object and there are a fixed number of them. - -Layout b) -The Use object(s) are referenced by a pointer to an -array from the User object and there may be a variable -number of them. +(some Uses inline others hung off) is impractical and breaks the invariant +that the Use objects belonging to the same User form a contiguous array. +

    +
    +

    +We have 2 different layouts in the User (sub)classes: +

      +
    • Layout a) +The Use object(s) are inside (resp. at fixed offset) of the User +object and there are a fixed number of them.

      + +
    • Layout b) +The Use object(s) are referenced by a pointer to an +array from the User object and there may be a variable +number of them.

      +
    +

    Initially each layout will possess a direct pointer to the -start of the array of Uses. Though not mandatory for layout a), +start of the array of Uses. Though not mandatory for layout a), we stick to this redundancy for the sake of simplicity. -The User object will also store the number of Use objects it +The User object will also store the number of Use objects it has. (Theoretically this information can also be calculated -given the scheme presented below.) - -Special forms of allocation operators (operator new) -will enforce the following memory layouts: - - -# Layout a) will be modelled by prepending the User object -# by the Use[] array. -# -# ...---.---.---.---.-------... -# | P | P | P | P | User -# '''---'---'---'---'-------''' - - -# Layout b) will be modelled by pointing at the Use[] array. -# -# .-------... -# | User -# '-------''' -# | -# v -# .---.---.---.---... -# | P | P | P | P | -# '---'---'---'---''' +given the scheme presented below.)

    +

    +Special forms of allocation operators (operator new) +will enforce the following memory layouts:

    - (In the above figures 'P' stands for the Use** that - is stored in each Use object in the member Use::Prev) +
      +
    • Layout a) will be modelled by prepending the User object by the Use[] array.

      +
      +...---.---.---.---.-------...
      +  | P | P | P | P | User
      +'''---'---'---'---'-------'''
      +
      -Since the Use objects will be deprived of the direct pointer to -their User objects, there must be a fast and exact method to -recover it. This is accomplished by the following scheme: +
    • Layout b) will be modelled by pointing at the Use[] array.

      +
      +.-------...
      +| User
      +'-------'''
      +    |
      +    v
      +    .---.---.---.---...
      +    | P | P | P | P |
      +    '---'---'---'---'''
      +
      +
    +(In the above figures 'P' stands for the Use** that + is stored in each Use object in the member Use::Prev) -A bit-encoding in the 2 LSBits of the Use::Prev will allow to find the -start of the User object: + + -00 --> binary digit 0 -01 --> binary digit 1 -10 --> stop and calc (s) -11 --> full stop (S) +
    +

    +Since the Use objects will be deprived of the direct pointer to +their User objects, there must be a fast and exact method to +recover it. This is accomplished by the following scheme:

    +
    -Given a Use*, all we have to do is to walk till we get -a stop and we either have a User immediately behind or +A bit-encoding in the 2 LSBits (least significant bits) of the Use::Prev will allow to find the +start of the User object: +
      +
    • 00 —> binary digit 0
    • +
    • 01 —> binary digit 1
    • +
    • 10 —> stop and calculate (s)
    • +
    • 11 —> full stop (S)
    • +
    +

    +Given a Use*, all we have to do is to walk till we get +a stop and we either have a User immediately behind or we have to walk to the next stop picking up digits -and calculating the offset: - +and calculating the offset:

    +
     .---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.---.----------------
     | 1 | s | 1 | 0 | 1 | 0 | s | 1 | 1 | 0 | s | 1 | 1 | s | 1 | S | User (or User*)
     '---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'---'----------------
    @@ -2320,14 +2334,24 @@
         |                   |               |______________________>
         |                   |______________________________________>
         |__________________________________________________________>
    -
    -
    +
    +

    Only the significant number of bits need to be stored between the -stops, so that the worst case is 20 memory accesses when there are -1000 Use objects. +stops, so that the worst case is 20 memory accesses when there are +1000 Use objects associated with a User.

    + + + -The following literate Haskell fragment demonstrates the concept: +
    +

    +The following literate Haskell fragment demonstrates the concept:

    +
    +
    +
     > import Test.QuickCheck
     > 
     > digits :: Int -> [Char] -> [Char]
    @@ -2345,13 +2369,16 @@
     > 
     > test = takeLast 40 $ dist 20 []
     > 
    +
    +
    +

    +Printing <test> gives: "1s100000s11010s10100s1111s1010s110s11s1S"

    +

    +The reverse algorithm computes the length of the string just by examining +a certain prefix:

    -Printing gives: "1s100000s11010s10100s1111s1010s110s11s1S" - -The reverse algorithm computes the -length of the string just by examining -a certain prefix: - +
    +
     > pref :: [Char] -> Int
     > pref "S" = 1
     > pref ('s':'1':rest) = decode 2 1 rest
    @@ -2361,44 +2388,63 @@
     > decode walk acc ('1':rest) = decode (walk + 1) (acc * 2 + 1) rest
     > decode walk acc _ = walk + acc
     > 
    +
    +
    +

    +Now, as expected, printing <pref test> gives 40.

    +

    +We can quickCheck this with following property:

    -Now, as expected, printing gives 40. - -We can quickCheck this with following property: - +
    +
     > testcase = dist 2000 []
     > testcaseLength = length testcase
     > 
     > identityProp n = n > 0 && n <= testcaseLength ==> length arr == pref arr
     >     where arr = takeLast n testcase
    +> 
    +
    +
    +

    +As expected <quickCheck identityProp> gives:

    -As expected gives: - +
     *Main> quickCheck identityProp
     OK, passed 100 tests.
    +
    +

    +Let's be a bit more exhaustive:

    -Let's be a bit more exhaustive: - +
    +
     > 
     > deepCheck p = check (defaultConfig { configMaxTest = 500 }) p
     > 
    +
    +
    +

    +And here is the result of <deepCheck identityProp>:

    -And here is the result of : - +
     *Main> deepCheck identityProp
     OK, passed 500 tests.
    +
    + + -To maintain the invariant that the 2 LSBits of each Use** in Use -never change after being set up, setters of Use::Prev must re-tag the -new Use** on every modification. Accordingly getters must strip the -tag bits. - -For layout b) instead of the User we will find a pointer (User* with LSBit set). -Following this pointer brings us to the User. A portable trick will ensure -that the first bytes of User (if interpreted as a pointer) will never have -the LSBit set. -
    +

    +To maintain the invariant that the 2 LSBits of each Use** in Use +never change after being set up, setters of Use::Prev must re-tag the +new Use** on every modification. Accordingly getters must strip the +tag bits.

    +

    +For layout b) instead of the User we will find a pointer (User* with LSBit set). +Following this pointer brings us to the User. A portable trick will ensure +that the first bytes of User (if interpreted as a pointer) will never have +the LSBit set.

    From ggreif at gmail.com Wed Jun 18 09:05:31 2008 From: ggreif at gmail.com (Gabor Greif) Date: Wed, 18 Jun 2008 14:05:31 -0000 Subject: [llvm-commits] [llvm] r52461 - /llvm/trunk/docs/ProgrammersManual.html Message-ID: <200806181405.m5IE5VcJ003596@zion.cs.uiuc.edu> Author: ggreif Date: Wed Jun 18 09:05:31 2008 New Revision: 52461 URL: http://llvm.org/viewvc/llvm-project?rev=52461&view=rev Log: fix validator warning Modified: llvm/trunk/docs/ProgrammersManual.html Modified: llvm/trunk/docs/ProgrammersManual.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/ProgrammersManual.html?rev=52461&r1=52460&r2=52461&view=diff ============================================================================== --- llvm/trunk/docs/ProgrammersManual.html (original) +++ llvm/trunk/docs/ProgrammersManual.html Wed Jun 18 09:05:31 2008 @@ -3411,7 +3411,7 @@ Valid CSS! Valid HTML 4.01! + src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Strict"> Dinakar Dhurjati and Chris Lattner
    From nicolas.geoffray at lip6.fr Wed Jun 18 10:32:49 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Wed, 18 Jun 2008 15:32:49 -0000 Subject: [llvm-commits] [vmkit] r52462 - /vmkit/trunk/lib/Mvm/EscapeAnalysis.cpp Message-ID: <200806181532.m5IFWnD0006342@zion.cs.uiuc.edu> Author: geoffray Date: Wed Jun 18 10:32:49 2008 New Revision: 52462 URL: http://llvm.org/viewvc/llvm-project?rev=52462&view=rev Log: Also remember which PHINodes we already visited. Modified: vmkit/trunk/lib/Mvm/EscapeAnalysis.cpp Modified: vmkit/trunk/lib/Mvm/EscapeAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/Mvm/EscapeAnalysis.cpp?rev=52462&r1=52461&r2=52462&view=diff ============================================================================== --- vmkit/trunk/lib/Mvm/EscapeAnalysis.cpp (original) +++ vmkit/trunk/lib/Mvm/EscapeAnalysis.cpp Wed Jun 18 10:32:49 2008 @@ -64,7 +64,7 @@ -static bool escapes(Instruction* Ins, std::map& visited) { +static bool escapes(Instruction* Ins, std::map& visited) { for (Value::use_iterator I = Ins->use_begin(), E = Ins->use_end(); I != E; ++I) { if (Instruction* II = dyn_cast(I)) { @@ -93,7 +93,10 @@ } else if (dyn_cast(II)) return true; else if (dyn_cast(II)) { - if (escapes(II, visited)) return true; + if (!visited[II]) { + visited[II] = true; + if (escapes(II, visited)) return true; + } } } else { return true; @@ -111,7 +114,7 @@ VirtualTable* Table = (VirtualTable*)C->getZExtValue(); // If the class has a finalize method, do not stack allocate the object if (!((void**)Table)[0]) { - std::map visited; + std::map visited; if (!(escapes(Alloc, visited))) { AllocaInst* AI = new AllocaInst(Type::Int8Ty, Size, "", Alloc); BitCastInst* BI = new BitCastInst(AI, Alloc->getType(), "", Alloc); From gohman at apple.com Wed Jun 18 11:14:18 2008 From: gohman at apple.com (Dan Gohman) Date: Wed, 18 Jun 2008 09:14:18 -0700 (PDT) Subject: [llvm-commits] [llvm] r52440 - in /llvm/trunk: lib/Transforms/Scalar/InstructionCombining.cpp test/Transforms/InstCombine/sext-misc.ll In-Reply-To: <200806180400.m5I40oUk004226@zion.cs.uiuc.edu> References: <200806180400.m5I40oUk004226@zion.cs.uiuc.edu> Message-ID: <47183.76.220.41.203.1213805658.squirrel@webmail.apple.com> Hi Chris sext-misc.ll now fails with three sext instructions that aren't being eliminated that previously were. Can you investigate? Thanks, Dan On Tue, June 17, 2008 9:00 pm, Chris Lattner wrote: > Author: lattner > Date: Tue Jun 17 23:00:49 2008 > New Revision: 52440 > > URL: http://llvm.org/viewvc/llvm-project?rev=52440&view=rev > Log: > make truncate/sext elimination capable of changing phi's. This > implements rdar://6013816 and the testcase in > Transforms/InstCombine/sext-misc.ll. > > Modified: > llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp > llvm/trunk/test/Transforms/InstCombine/sext-misc.ll > > Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp > URL: > http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=52440&r1=52439&r2=52440&view=diff > > ============================================================================== > --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original) > +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Tue Jun 17 > 23:00:49 2008 > @@ -6838,6 +6838,16 @@ > /// > /// This is a truncation operation if Ty is smaller than V->getType(), or > an > /// extension operation if Ty is larger. > +/// > +/// If CastOpc is a truncation, then Ty will be a type smaller than V. > We > +/// should return true if trunc(V) can be computed by computing V in the > smaller > +/// type. If V is an instruction, then trunc(inst(x,y)) can be computed > as > +/// inst(trunc(x),trunc(y)), which only makes sense if x and y can be > +/// efficiently truncated. > +/// > +/// If CastOpc is a sext or zext, we are asking if the low bits of the > value can > +/// bit computed in a larger type, which is then and'd or sext_in_reg'd > to get > +/// the final result. > bool InstCombiner::CanEvaluateInDifferentType(Value *V, const IntegerType > *Ty, > unsigned CastOpc, > int &NumCastsRemoved) { > @@ -6858,7 +6868,7 @@ > // If the first operand is itself a cast, and is eliminable, do not > count > // this as an eliminable cast. We would prefer to eliminate those > two > // casts first. > - if (!isa(I->getOperand(0))) > + if (!isa(I->getOperand(0)) && I->hasOneUse()) > ++NumCastsRemoved; > return true; > } > @@ -6923,8 +6933,17 @@ > // of casts in the input. > if (I->getOpcode() == CastOpc) > return true; > - > break; > + > + case Instruction::PHI: { > + // We can change a phi if we can change all operands. > + PHINode *PN = cast(I); > + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) > + if (!CanEvaluateInDifferentType(PN->getIncomingValue(i), Ty, > CastOpc, > + NumCastsRemoved)) > + return false; > + return true; > + } > default: > // TODO: Can handle more cases here. > break; > @@ -6957,7 +6976,7 @@ > Value *LHS = EvaluateInDifferentType(I->getOperand(0), Ty, isSigned); > Value *RHS = EvaluateInDifferentType(I->getOperand(1), Ty, isSigned); > Res = BinaryOperator::Create((Instruction::BinaryOps)I->getOpcode(), > - LHS, RHS, I->getName()); > + LHS, RHS); > break; > } > case Instruction::Trunc: > @@ -6969,16 +6988,27 @@ > if (I->getOperand(0)->getType() == Ty) > return I->getOperand(0); > > - // Otherwise, must be the same type of case, so just reinsert a new > one. > + // Otherwise, must be the same type of cast, so just reinsert a new > one. > Res = CastInst::Create(cast(I)->getOpcode(), > I->getOperand(0), > - Ty, I->getName()); > + Ty); > break; > + case Instruction::PHI: { > + PHINode *OPN = cast(I); > + PHINode *NPN = PHINode::Create(Ty); > + for (unsigned i = 0, e = OPN->getNumIncomingValues(); i != e; ++i) { > + Value *V =EvaluateInDifferentType(OPN->getIncomingValue(i), Ty, > isSigned); > + NPN->addIncoming(V, OPN->getIncomingBlock(i)); > + } > + Res = NPN; > + break; > + } > default: > // TODO: Can handle more cases here. > assert(0 && "Unreachable!"); > break; > } > > + Res->takeName(I); > return InsertNewInstBefore(Res, *I); > } > > > Modified: llvm/trunk/test/Transforms/InstCombine/sext-misc.ll > URL: > http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/sext-misc.ll?rev=52440&r1=52439&r2=52440&view=diff > > ============================================================================== > --- llvm/trunk/test/Transforms/InstCombine/sext-misc.ll (original) > +++ llvm/trunk/test/Transforms/InstCombine/sext-misc.ll Tue Jun 17 > 23:00:49 2008 > @@ -1,6 +1,4 @@ > ; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep sext > -; RUN: llvm-as < %s | llc -march=x86-64 | not grep movslq > -; RUN: llvm-as < %s | llc -march=x86 | not grep sar > > declare i32 @llvm.ctpop.i32(i32) > declare i32 @llvm.ctlz.i32(i32) > @@ -50,3 +48,18 @@ > %n = sext i16 %s to i32 > ret i32 %n > } > + > +; rdar://6013816 > +define i16 @test(i16 %t, i1 %cond) nounwind { > +entry: > + br i1 %cond, label %T, label %F > +T: > + %t2 = sext i16 %t to i32 > + br label %F > + > +F: > + %V = phi i32 [%t2, %T], [42, %entry] > + %W = trunc i32 %V to i16 > + ret i16 %W > +} > + > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > From gohman at apple.com Wed Jun 18 11:20:33 2008 From: gohman at apple.com (Dan Gohman) Date: Wed, 18 Jun 2008 09:20:33 -0700 (PDT) Subject: [llvm-commits] [llvm] r52454 - /llvm/trunk/lib/Target/X86/X86InstrInfo.td In-Reply-To: <200806180813.m5I8D7qK023472@zion.cs.uiuc.edu> References: <200806180813.m5I8D7qK023472@zion.cs.uiuc.edu> Message-ID: <59843.76.220.41.203.1213806033.squirrel@webmail.apple.com> On Wed, June 18, 2008 1:13 am, Evan Cheng wrote: > Author: evancheng > Date: Wed Jun 18 03:13:07 2008 > New Revision: 52454 > > URL: http://llvm.org/viewvc/llvm-project?rev=52454&view=rev > Log: > XOR32rr, etc. are not AsCheapAsMove, but MOV32ri, etc. are. MOV32ri is 5 bytes of encoding, while MOV32rr is 2 bytes. Is MOV32ri really "as cheap"? Also, please update the AsCheapAsMove usage in X86Instr64-bit.td too. Thanks, Dan From gohman at apple.com Wed Jun 18 11:23:07 2008 From: gohman at apple.com (Dan Gohman) Date: Wed, 18 Jun 2008 16:23:07 -0000 Subject: [llvm-commits] [llvm] r52463 - in /llvm/trunk: include/llvm/Analysis/ScalarEvolution.h lib/Analysis/ScalarEvolution.cpp lib/Analysis/ScalarEvolutionExpander.cpp lib/Transforms/Scalar/LoopStrengthReduce.cpp Message-ID: <200806181623.m5IGN8NB008165@zion.cs.uiuc.edu> Author: djg Date: Wed Jun 18 11:23:07 2008 New Revision: 52463 URL: http://llvm.org/viewvc/llvm-project?rev=52463&view=rev Log: Move LSR's private isZero function to a public SCEV member function, and make use of it in several places. Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolution.h llvm/trunk/lib/Analysis/ScalarEvolution.cpp llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolution.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolution.h?rev=52463&r1=52462&r2=52463&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/ScalarEvolution.h (original) +++ llvm/trunk/include/llvm/Analysis/ScalarEvolution.h Wed Jun 18 11:23:07 2008 @@ -81,6 +81,10 @@ /// uint32_t getBitWidth() const; + /// isZero - Return true if the expression is a constant zero. + /// + bool isZero() const; + /// replaceSymbolicValuesWithConcrete - If this SCEV internally references /// the symbolic value "Sym", construct and return a new SCEV that produces /// the same value, but which uses the concrete value Conc instead of the Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=52463&r1=52462&r2=52463&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original) +++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Wed Jun 18 11:23:07 2008 @@ -132,6 +132,12 @@ return 0; } +bool SCEV::isZero() const { + if (const SCEVConstant *SC = dyn_cast(this)) + return SC->getValue()->isZero(); + return false; +} + SCEVCouldNotCompute::SCEVCouldNotCompute() : SCEV(scCouldNotCompute) {} @@ -1136,11 +1142,10 @@ const Loop *L) { if (Operands.size() == 1) return Operands[0]; - if (SCEVConstant *StepC = dyn_cast(Operands.back())) - if (StepC->getValue()->isZero()) { - Operands.pop_back(); - return getAddRecExpr(Operands, L); // { X,+,0 } --> X - } + if (Operands.back()->isZero()) { + Operands.pop_back(); + return getAddRecExpr(Operands, L); // { X,+,0 } --> X + } SCEVAddRecExpr *&Result = (*SCEVAddRecExprs)[std::make_pair(L, std::vector(Operands.begin(), @@ -2583,9 +2588,8 @@ // value at this index. When solving for "X*X != 5", for example, we // should not accept a root of 2. SCEVHandle Val = AddRec->evaluateAtIteration(R1, SE); - if (SCEVConstant *EvalVal = dyn_cast(Val)) - if (EvalVal->getValue()->isZero()) - return R1; // We found a quadratic root! + if (Val->isZero()) + return R1; // We found a quadratic root! } } } Modified: llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp?rev=52463&r1=52462&r2=52463&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp (original) +++ llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp Wed Jun 18 11:23:07 2008 @@ -126,8 +126,7 @@ assert(Ty->isInteger() && "Cannot expand fp recurrences yet!"); // {X,+,F} --> X + {0,+,F} - if (!isa(S->getStart()) || - !cast(S->getStart())->getValue()->isZero()) { + if (!S->getStart()->isZero()) { Value *Start = expand(S->getStart()); std::vector NewOps(S->op_begin(), S->op_end()); NewOps[0] = SE.getIntegerSCEV(0, Ty); Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=52463&r1=52462&r2=52463&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Wed Jun 18 11:23:07 2008 @@ -586,9 +586,8 @@ } // If there is no immediate value, skip the next part. - if (SCEVConstant *SC = dyn_cast(Imm)) - if (SC->getValue()->isZero()) - return Rewriter.expandCodeFor(NewBase, BaseInsertPt); + if (Imm->isZero()) + return Rewriter.expandCodeFor(NewBase, BaseInsertPt); Value *Base = Rewriter.expandCodeFor(NewBase, BaseInsertPt); @@ -891,8 +890,7 @@ SeparateSubExprs(SubExprs, SARE->getOperand(0), SE); } - } else if (!isa(Expr) || - !cast(Expr)->getValue()->isZero()) { + } else if (!Expr->isZero()) { // Do not add zero. SubExprs.push_back(Expr); } @@ -979,14 +977,6 @@ return Result; } -/// isZero - returns true if the scalar evolution expression is zero. -/// -static bool isZero(const SCEVHandle &V) { - if (const SCEVConstant *SC = dyn_cast(V)) - return SC->getValue()->isZero(); - return false; -} - /// ValidStride - Check whether the given Scale is valid for all loads and /// stores in UsersToProcess. /// @@ -1009,7 +999,7 @@ TargetLowering::AddrMode AM; if (SCEVConstant *SC = dyn_cast(UsersToProcess[i].Imm)) AM.BaseOffs = SC->getValue()->getSExtValue(); - AM.HasBaseReg = HasBaseReg || !isZero(UsersToProcess[i].Base); + AM.HasBaseReg = HasBaseReg || !UsersToProcess[i].Base->isZero(); AM.Scale = Scale; // If load[imm+r*scale] is illegal, bail out. @@ -1069,7 +1059,7 @@ IE = SI->second.IVs.end(); II != IE; ++II) // FIXME: Only handle base == 0 for now. // Only reuse previous IV if it would not require a type conversion. - if (isZero(II->Base) && + if (II->Base->isZero() && !RequiresTypeConversion(II->Base->getType(), Ty)) { IV = *II; return Scale; @@ -1233,7 +1223,7 @@ // their value in a register and add it in for each use. This will take up // a register operand, which potentially restricts what stride values are // valid. - bool HaveCommonExprs = !isZero(CommonExprs); + bool HaveCommonExprs = !CommonExprs->isZero(); // If all uses are addresses, check if it is possible to reuse an IV with a // stride that is a factor of this stride. And that the multiple is a number @@ -1629,7 +1619,7 @@ // Avoid rewriting the compare instruction with an iv of new stride // if it's likely the new stride uses will be rewritten using the if (AllUsesAreAddresses && - ValidStride(!isZero(CommonExprs), Scale, UsersToProcess)) { + ValidStride(!CommonExprs->isZero(), Scale, UsersToProcess)) { NewCmpVal = CmpVal; continue; } From gohman at apple.com Wed Jun 18 11:37:11 2008 From: gohman at apple.com (Dan Gohman) Date: Wed, 18 Jun 2008 16:37:11 -0000 Subject: [llvm-commits] [llvm] r52464 - in /llvm/trunk: include/llvm/Analysis/ScalarEvolutionExpander.h lib/Analysis/ScalarEvolutionExpander.cpp Message-ID: <200806181637.m5IGbBRu008571@zion.cs.uiuc.edu> Author: djg Date: Wed Jun 18 11:37:11 2008 New Revision: 52464 URL: http://llvm.org/viewvc/llvm-project?rev=52464&view=rev Log: Move SCEVExpander::visitAddExpr out-of-line. Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h?rev=52464&r1=52463&r2=52464&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h (original) +++ llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h Wed Jun 18 11:37:11 2008 @@ -111,15 +111,7 @@ return CastInst::CreateSExtOrBitCast(V, S->getType(), "tmp.", InsertPt); } - Value *visitAddExpr(SCEVAddExpr *S) { - Value *V = expand(S->getOperand(S->getNumOperands()-1)); - - // Emit a bunch of add instructions - for (int i = S->getNumOperands()-2; i >= 0; --i) - V = InsertBinop(Instruction::Add, V, expand(S->getOperand(i)), - InsertPt); - return V; - } + Value *visitAddExpr(SCEVAddExpr *S); Value *visitMulExpr(SCEVMulExpr *S); Modified: llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp?rev=52464&r1=52463&r2=52464&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp (original) +++ llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp Wed Jun 18 11:37:11 2008 @@ -99,6 +99,16 @@ return BinaryOperator::Create(Opcode, LHS, RHS, "tmp", InsertPt); } +Value *SCEVExpander::visitAddExpr(SCEVAddExpr *S) { + Value *V = expand(S->getOperand(S->getNumOperands()-1)); + + // Emit a bunch of add instructions + for (int i = S->getNumOperands()-2; i >= 0; --i) + V = InsertBinop(Instruction::Add, V, expand(S->getOperand(i)), + InsertPt); + return V; +} + Value *SCEVExpander::visitMulExpr(SCEVMulExpr *S) { int FirstOp = 0; // Set if we should emit a subtract. if (SCEVConstant *SC = dyn_cast(S->getOperand(0))) From clattner at apple.com Wed Jun 18 12:23:30 2008 From: clattner at apple.com (Chris Lattner) Date: Wed, 18 Jun 2008 10:23:30 -0700 Subject: [llvm-commits] [llvm] r52440 - in /llvm/trunk: lib/Transforms/Scalar/InstructionCombining.cpp test/Transforms/InstCombine/sext-misc.ll In-Reply-To: <47183.76.220.41.203.1213805658.squirrel@webmail.apple.com> References: <200806180400.m5I40oUk004226@zion.cs.uiuc.edu> <47183.76.220.41.203.1213805658.squirrel@webmail.apple.com> Message-ID: <80B4FE5A-3816-4B3E-81B6-857AB3E78AE2@apple.com> Will do, sorry for the breakage! On Jun 18, 2008, at 9:14 AM, Dan Gohman wrote: > Hi Chris > > sext-misc.ll now fails with three sext instructions that aren't > being eliminated that previously were. Can you investigate? > > Thanks, > > Dan > > On Tue, June 17, 2008 9:00 pm, Chris Lattner wrote: >> Author: lattner >> Date: Tue Jun 17 23:00:49 2008 >> New Revision: 52440 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=52440&view=rev >> Log: >> make truncate/sext elimination capable of changing phi's. This >> implements rdar://6013816 and the testcase in >> Transforms/InstCombine/sext-misc.ll. >> >> Modified: >> llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp >> llvm/trunk/test/Transforms/InstCombine/sext-misc.ll >> >> Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp >> URL: >> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=52440&r1=52439&r2=52440&view=diff >> >> = >> = >> = >> = >> = >> = >> = >> = >> = >> ===================================================================== >> --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp >> (original) >> +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Tue >> Jun 17 >> 23:00:49 2008 >> @@ -6838,6 +6838,16 @@ >> /// >> /// This is a truncation operation if Ty is smaller than V- >> >getType(), or >> an >> /// extension operation if Ty is larger. >> +/// >> +/// If CastOpc is a truncation, then Ty will be a type smaller >> than V. >> We >> +/// should return true if trunc(V) can be computed by computing V >> in the >> smaller >> +/// type. If V is an instruction, then trunc(inst(x,y)) can be >> computed >> as >> +/// inst(trunc(x),trunc(y)), which only makes sense if x and y can >> be >> +/// efficiently truncated. >> +/// >> +/// If CastOpc is a sext or zext, we are asking if the low bits of >> the >> value can >> +/// bit computed in a larger type, which is then and'd or >> sext_in_reg'd >> to get >> +/// the final result. >> bool InstCombiner::CanEvaluateInDifferentType(Value *V, const >> IntegerType >> *Ty, >> unsigned CastOpc, >> int &NumCastsRemoved) { >> @@ -6858,7 +6868,7 @@ >> // If the first operand is itself a cast, and is eliminable, >> do not >> count >> // this as an eliminable cast. We would prefer to eliminate >> those >> two >> // casts first. >> - if (!isa(I->getOperand(0))) >> + if (!isa(I->getOperand(0)) && I->hasOneUse()) >> ++NumCastsRemoved; >> return true; >> } >> @@ -6923,8 +6933,17 @@ >> // of casts in the input. >> if (I->getOpcode() == CastOpc) >> return true; >> - >> break; >> + >> + case Instruction::PHI: { >> + // We can change a phi if we can change all operands. >> + PHINode *PN = cast(I); >> + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; + >> +i) >> + if (!CanEvaluateInDifferentType(PN->getIncomingValue(i), Ty, >> CastOpc, >> + NumCastsRemoved)) >> + return false; >> + return true; >> + } >> default: >> // TODO: Can handle more cases here. >> break; >> @@ -6957,7 +6976,7 @@ >> Value *LHS = EvaluateInDifferentType(I->getOperand(0), Ty, >> isSigned); >> Value *RHS = EvaluateInDifferentType(I->getOperand(1), Ty, >> isSigned); >> Res = BinaryOperator::Create((Instruction::BinaryOps)I- >> >getOpcode(), >> - LHS, RHS, I->getName()); >> + LHS, RHS); >> break; >> } >> case Instruction::Trunc: >> @@ -6969,16 +6988,27 @@ >> if (I->getOperand(0)->getType() == Ty) >> return I->getOperand(0); >> >> - // Otherwise, must be the same type of case, so just reinsert >> a new >> one. >> + // Otherwise, must be the same type of cast, so just reinsert >> a new >> one. >> Res = CastInst::Create(cast(I)->getOpcode(), >> I->getOperand(0), >> - Ty, I->getName()); >> + Ty); >> break; >> + case Instruction::PHI: { >> + PHINode *OPN = cast(I); >> + PHINode *NPN = PHINode::Create(Ty); >> + for (unsigned i = 0, e = OPN->getNumIncomingValues(); i != e; + >> +i) { >> + Value *V =EvaluateInDifferentType(OPN->getIncomingValue(i), >> Ty, >> isSigned); >> + NPN->addIncoming(V, OPN->getIncomingBlock(i)); >> + } >> + Res = NPN; >> + break; >> + } >> default: >> // TODO: Can handle more cases here. >> assert(0 && "Unreachable!"); >> break; >> } >> >> + Res->takeName(I); >> return InsertNewInstBefore(Res, *I); >> } >> >> >> Modified: llvm/trunk/test/Transforms/InstCombine/sext-misc.ll >> URL: >> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/sext-misc.ll?rev=52440&r1=52439&r2=52440&view=diff >> >> = >> = >> = >> = >> = >> = >> = >> = >> = >> ===================================================================== >> --- llvm/trunk/test/Transforms/InstCombine/sext-misc.ll (original) >> +++ llvm/trunk/test/Transforms/InstCombine/sext-misc.ll Tue Jun 17 >> 23:00:49 2008 >> @@ -1,6 +1,4 @@ >> ; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep sext >> -; RUN: llvm-as < %s | llc -march=x86-64 | not grep movslq >> -; RUN: llvm-as < %s | llc -march=x86 | not grep sar >> >> declare i32 @llvm.ctpop.i32(i32) >> declare i32 @llvm.ctlz.i32(i32) >> @@ -50,3 +48,18 @@ >> %n = sext i16 %s to i32 >> ret i32 %n >> } >> + >> +; rdar://6013816 >> +define i16 @test(i16 %t, i1 %cond) nounwind { >> +entry: >> + br i1 %cond, label %T, label %F >> +T: >> + %t2 = sext i16 %t to i32 >> + br label %F >> + >> +F: >> + %V = phi i32 [%t2, %T], [42, %entry] >> + %W = trunc i32 %V to i16 >> + ret i16 %W >> +} >> + >> >> >> _______________________________________________ >> llvm-commits mailing list >> llvm-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits >> > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From resistor at mac.com Wed Jun 18 12:30:10 2008 From: resistor at mac.com (Owen Anderson) Date: Wed, 18 Jun 2008 10:30:10 -0700 Subject: [llvm-commits] [llvm] r52459 - in /llvm/trunk: lib/Transforms/IPO/DeadArgumentElimination.cpp test/Transforms/DeadArgElim/multdeadretval.ll In-Reply-To: <200806181113.m5IBD8Mc029979@zion.cs.uiuc.edu> References: <200806181113.m5IBD8Mc029979@zion.cs.uiuc.edu> Message-ID: Matthijs, This patch causes either an infinite loop or a massive slowdown when optimizing MultiSource/Applications/SPASS, and possibly others as well. I'm reverting it for now. In the future, please run llvm-test on at least MultiSource/ before committing a large change like this. --Owen On Jun 18, 2008, at 4:13 AM, Matthijs Kooijman wrote: > Author: matthijs > Date: Wed Jun 18 06:12:53 2008 > New Revision: 52459 > > URL: http://llvm.org/viewvc/llvm-project?rev=52459&view=rev > Log: > Rewrite the DeadArgumentElimination pass, to use a more explicit > tracking of > dependencies between return values and/or arguments. Also make the > handling of > arguments and return values the same. > > The pass now looks properly inside returned structs, but only at the > first > level (ie, not inside nested structs). > > Also add a testcase for testing various variations of (multiple) > dead rerturn > values. > > Added: > llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll > Modified: > llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp > > Modified: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp?rev=52459&r1=52458&r2=52459&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp > (original) > +++ llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Wed > Jun 18 06:12:53 2008 > @@ -10,10 +10,10 @@ > // This pass deletes dead arguments from internal functions. Dead > argument > // elimination removes arguments which are directly dead, as well as > arguments > // only passed into function calls as dead arguments of other > functions. This > -// pass also deletes dead arguments in a similar way. > +// pass also deletes dead return values in a similar way. > // > // This pass is often useful as a cleanup pass to run after aggressive > -// interprocedural passes, which add possibly-dead arguments. > +// interprocedural passes, which add possibly-dead arguments or > return values. > // > // > = > = > = > ----------------------------------------------------------------------= > ==// > > @@ -42,40 +42,66 @@ > /// DAE - The dead argument elimination pass. > /// > class VISIBILITY_HIDDEN DAE : public ModulePass { > + public: > + > + /// Struct that represent either a (part of a) return value or > a function > + /// argument. Used so that arguments and return values can be > used > + /// interchangably. > + struct RetOrArg { > + RetOrArg(const Function* F, unsigned Idx, bool IsArg) : F(F), > Idx(Idx), IsArg(IsArg) {} > + const Function *F; > + unsigned Idx; > + bool IsArg; > + > + /// Make RetOrArg comparable, so we can put it into a map > + bool operator<(const RetOrArg &O) const { > + if (F != O.F) > + return F < O.F; > + else if (Idx != O.Idx) > + return Idx < O.Idx; > + else > + return IsArg < O.IsArg; > + } > + }; > + > /// Liveness enum - During our initial pass over the program, we > determine > /// that things are either definately alive, definately dead, or > in need of > /// interprocedural analysis (MaybeLive). > /// > enum Liveness { Live, MaybeLive, Dead }; > > - /// LiveArguments, MaybeLiveArguments, DeadArguments - These > sets contain > - /// all of the arguments in the program. The Dead set contains > arguments > - /// which are completely dead (never used in the function). > The MaybeLive > - /// set contains arguments which are only passed into other > function calls, > - /// thus may be live and may be dead. The Live set contains > arguments which > - /// are known to be alive. > - /// > - std::set DeadArguments, MaybeLiveArguments, > LiveArguments; > - > - /// DeadRetVal, MaybeLiveRetVal, LifeRetVal - These sets > contain all of the > - /// functions in the program. The Dead set contains functions > whose return > - /// value is known to be dead. The MaybeLive set contains > functions whose > - /// return values are only used by return instructions, and the > Live set > - /// contains functions whose return values are used, functions > that are > - /// external, and functions that already return void. > - /// > - std::set DeadRetVal, MaybeLiveRetVal, LiveRetVal; > - > - /// InstructionsToInspect - As we mark arguments and return > values > - /// MaybeLive, we keep track of which instructions could make > the values > - /// live here. Once the entire program has had the return > value and > - /// arguments analyzed, this set is scanned to promote the > MaybeLive objects > - /// to be Live if they really are used. > - std::vector InstructionsToInspect; > - > - /// CallSites - Keep track of the call sites of functions that > have > - /// MaybeLive arguments or return values. > - std::multimap CallSites; > + /// Convenience wrapper > + RetOrArg CreateRet(const Function *F, unsigned Idx) { return > RetOrArg(F, Idx, false); } > + /// Convenience wrapper > + RetOrArg CreateArg(const Function *F, unsigned Idx) { return > RetOrArg(F, Idx, true); } > + > + typedef std::multimap UseMap; > + /// This map maps a return value or argument to all return > values or > + /// arguments it uses. > + /// For example (indices are left out for clarity): > + /// - Uses[ret F] = ret G > + /// This means that F calls G, and F returns the value > returned by G. > + /// - Uses[arg F] = ret G > + /// This means that some function calls G and passes its > result as an > + /// argument to F. > + /// - Uses[ret F] = arg F > + /// This means that F returns one of its own arguments. > + /// - Uses[arg F] = arg G > + /// This means that G calls F and passes one of its own > (G's) arguments > + /// directly to F. > + UseMap Uses; > + > + typedef std::set LiveSet; > + > + /// This set contains all values that have been determined to > be live > + LiveSet LiveValues; > + > + typedef SmallVector UseVector; > + > + /// This is the set of functions that have been inspected. > Since LiveValues > + /// keeps a list of live values for inspected functions only, > this way we > + /// can prevent uninspected functions becoming completely dead. > + std::set InspectedFunctions; > > public: > static char ID; // Pass identification, replacement for typeid > @@ -85,20 +111,19 @@ > virtual bool ShouldHackArguments() const { return false; } > > private: > - Liveness getArgumentLiveness(const Argument &A); > - bool isMaybeLiveArgumentNowLive(Argument *Arg); > - > + Liveness IsMaybeLive(RetOrArg Use, UseVector &MaybeLiveUses); > + Liveness SurveyUse(Value::use_iterator U, UseVector > &MaybeLiveUses, unsigned RetValNum = 0); > + Liveness SurveyUses(Value *V, UseVector &MaybeLiveUses); > + > + void SurveyFunction(Function &F); > + void MarkValue(const RetOrArg &RA, Liveness L, const UseVector > &MaybeLiveUses); > + void MarkLive(RetOrArg RA); > + bool RemoveDeadStuffFromFunction(Function *F); > bool DeleteDeadVarargs(Function &Fn); > - void SurveyFunction(Function &Fn); > - > - void MarkArgumentLive(Argument *Arg); > - void MarkRetValLive(Function *F); > - void MarkReturnInstArgumentLive(ReturnInst *RI); > - > - void RemoveDeadArgumentsFromFunction(Function *F); > }; > } > > + > char DAE::ID = 0; > static RegisterPass > X("deadargelim", "Dead Argument Elimination"); > @@ -155,7 +180,7 @@ > // remove the "..." and adjust all the calls. > > // Start by computing a new prototype for the function, which is > the same as > - // the old function, but has fewer arguments. > + // the old function, but doesn't have isVarArg set. > const FunctionType *FTy = Fn.getFunctionType(); > std::vector Params(FTy->param_begin(), FTy- > >param_end()); > FunctionType *NFTy = FunctionType::get(FTy->getReturnType(), > Params, false); > @@ -233,57 +258,110 @@ > return true; > } > > +/// Convenience function that returns the number of return values. > It returns 0 > +/// for void functions and 1 for functions not returning a struct. > It returns > +/// the number of struct elements for functions returning a struct. > +static unsigned NumRetVals(const Function *F) { > + if (F->getReturnType() == Type::VoidTy) > + return 0; > + else if (const StructType *STy = dyn_cast(F- > >getReturnType())) > + return STy->getNumElements(); > + else > + return 1; > +} > > -static inline bool CallPassesValueThoughVararg(Instruction *Call, > - const Value *Arg) { > - CallSite CS = CallSite::get(Call); > - const Type *CalledValueTy = CS.getCalledValue()->getType(); > - const Type *FTy = cast(CalledValueTy)- > >getElementType(); > - unsigned NumFixedArgs = cast(FTy)->getNumParams(); > - for (CallSite::arg_iterator AI = CS.arg_begin()+NumFixedArgs; > - AI != CS.arg_end(); ++AI) > - if (AI->get() == Arg) > - return true; > - return false; > -} > - > -// getArgumentLiveness - Inspect an argument, determining if is > known Live > -// (used in a computation), MaybeLive (only passed as an argument > to a call), or > -// Dead (not used). > -DAE::Liveness DAE::getArgumentLiveness(const Argument &A) { > - const Function *F = A.getParent(); > - > - // If this is the return value of a struct function, it's not > really dead. > - if (F->hasStructRetAttr() && &*(F->arg_begin()) == &A) > +/// IsMaybeAlive - This checks Use for liveness. If Use is live, > returns Live, > +/// else returns MaybeLive. Also, adds Use to MaybeLiveUses in the > latter case. > +DAE::Liveness DAE::IsMaybeLive(RetOrArg Use, UseVector > &MaybeLiveUses) { > + // We're live if our use is already marked as live > + if (LiveValues.count(Use)) > return Live; > - > - if (A.use_empty()) // First check, directly dead? > - return Dead; > > - // Scan through all of the uses, looking for non-argument passing > uses. > - for (Value::use_const_iterator I = A.use_begin(), E = > A.use_end(); I!=E;++I) { > - // Return instructions do not immediately effect liveness. > - if (isa(*I)) > - continue; > - > - CallSite CS = CallSite::get(const_cast(*I)); > - if (!CS.getInstruction()) { > - // If its used by something that is not a call or invoke, > it's alive! > - return Live; > - } > - // If it's an indirect call, mark it alive... > - Function *Callee = CS.getCalledFunction(); > - if (!Callee) return Live; > - > - // Check to see if it's passed through a va_arg area: if so, we > cannot > - // remove it. > - if (CallPassesValueThoughVararg(CS.getInstruction(), &A)) > - return Live; // If passed through va_arg area, we cannot > remove it > - } > + // We're maybe live otherwise, but remember that we must become > live if > + // Use becomes live. > + MaybeLiveUses.push_back(Use); > + return MaybeLive; > +} > + > > - return MaybeLive; // It must be used, but only as argument to a > function > +/// SurveyUse - This looks at a single use of an argument or return > value > +/// and determines if it should be alive or not. Adds this use to > MaybeLiveUses > +/// if it causes the used value to become MaybeAlive. > +/// > +/// RetValNum is the return value number to use when this use is > used in a > +/// return instruction. This is used in the recursion, you should > always leave > +/// it at 0. > +DAE::Liveness DAE::SurveyUse(Value::use_iterator U, UseVector > &MaybeLiveUses, unsigned RetValNum) { > + Value *V = *U; > + if (ReturnInst *RI = dyn_cast(V)) { > + // The value is returned from another function. It's only > live when the > + // caller's return value is live > + RetOrArg Use = CreateRet(RI->getParent()->getParent(), > RetValNum); > + // We might be live, depending on the liveness of Use > + return IsMaybeLive(Use, MaybeLiveUses); > + } > + if (InsertValueInst *IV = dyn_cast(V)) { > + if (U.getOperandNo() != > InsertValueInst::getAggregateOperandIndex() && IV->hasIndices()) > + // The use we are examining is inserted into an aggregate. > Our liveness > + // depends on all uses of that aggregate, but if it is used > as a return > + // value, only index at which we were inserted counts. > + RetValNum = *IV->idx_begin(); > + > + // Note that if we are used as the aggregate operand to the > insertvalue, > + // we don't change RetValNum, but do survey all our uses. > + > + Liveness Result = Dead; > + for (Value::use_iterator I = IV->use_begin(), > + E = V->use_end(); I != E; ++I) { > + Result = SurveyUse(I, MaybeLiveUses, RetValNum); > + if (Result == Live) > + break; > + } > + return Result; > + } > + CallSite CS = CallSite::get(V); > + if (CS.getInstruction()) { > + Function *F = CS.getCalledFunction(); > + if (F) { > + // Used in a direct call > + > + // Check for vararg. Do - 1 to skip the first operand to > call (the > + // function itself). > + if (U.getOperandNo() - 1 >= F->getFunctionType()- > >getNumParams()) > + // The value is passed in through a vararg! Must be live. > + return Live; > + > + // Value passed to a normal call. It's only live when the > corresponding > + // argument (operand number - 1 to skip the function > pointer operand) to > + // the called function turns out live > + RetOrArg Use = CreateArg(F, U.getOperandNo() - 1); > + return IsMaybeLive(Use, MaybeLiveUses); > + } else { > + // Used in any other way? Value must be live. > + return Live; > + } > + } > + // Used in any other way? Value must be live. > + return Live; > } > > +/// SurveyUses - This looks at all the uses of the given return value > +/// (possibly a partial return value from a function returning a > struct). > +/// Returns the Liveness deduced from the uses of this value. > +/// > +/// Adds all uses that cause the result to be MaybeLive to > MaybeLiveRetUses. > +DAE::Liveness DAE::SurveyUses(Value *V, UseVector &MaybeLiveUses) { > + // Assume it's dead (which will only hold if there are no uses at > all..) > + Liveness Result = Dead; > + // Check each use > + for (Value::use_iterator I = V->use_begin(), > + E = V->use_end(); I != E; ++I) { > + Result = SurveyUse(I, MaybeLiveUses); > + if (Result == Live) > + break; > + } > + return Result; > +} > > // SurveyFunction - This performs the initial survey of the > specified function, > // checking out whether or not it uses any of its incoming arguments > or whether > @@ -294,13 +372,36 @@ > // well as arguments to functions which have their "address taken". > // > void DAE::SurveyFunction(Function &F) { > + InspectedFunctions.insert(&F); > bool FunctionIntrinsicallyLive = false; > - Liveness RetValLiveness = F.getReturnType() == Type::VoidTy ? > Live : Dead; > - > - if (!F.hasInternalLinkage() && > - (!ShouldHackArguments() || F.isIntrinsic())) > + unsigned RetCount = NumRetVals(&F); > + // Assume all return values are dead > + typedef SmallVector RetVals; > + RetVals RetValLiveness(RetCount, Dead); > + > + // These vectors maps each return value to the uses that make it > MaybeLive, so > + // we can add those to the MaybeLiveRetVals list if the return > value > + // really turns out to be MaybeLive. Initializes to RetCount > empty vectors > + typedef SmallVector RetUses; > + // Intialized to a list of RetCount empty lists > + RetUses MaybeLiveRetUses(RetCount); > + > + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) > + if (ReturnInst *RI = dyn_cast(BB->getTerminator())) > + if (RI->getNumOperands() != 0 && RI->getOperand(0)- > >getType() != F.getFunctionType()->getReturnType()) { > + // We don't support old style multiple return values > + FunctionIntrinsicallyLive = true; > + break; > + } > + if (!F.hasInternalLinkage() && (!ShouldHackArguments() || > F.isIntrinsic())) > FunctionIntrinsicallyLive = true; > - else > + if (!FunctionIntrinsicallyLive) { > + DOUT << "DAE - Inspecting callers for fn: " << F.getName() << > "\n"; > + // Keep track of the number of live retvals, so we can skip > checks once all > + // of them turn out to be live. > + unsigned NumLiveRetVals = 0; > + const Type *STy = dyn_cast(F.getReturnType()); > + // Loop all uses of the function > for (Value::use_iterator I = F.use_begin(), E = F.use_end(); I ! > = E; ++I) { > // If the function is PASSED IN as an argument, its address > has been taken > if (I.getOperandNo() != 0) { > @@ -315,191 +416,138 @@ > FunctionIntrinsicallyLive = true; > break; > } > - > - // Check to see if the return value is used... > - if (RetValLiveness != Live) > - for (Value::use_iterator I = TheCall->use_begin(), > - E = TheCall->use_end(); I != E; ++I) > - if (isa(cast(*I))) { > - RetValLiveness = MaybeLive; > - } else if (isa(cast(*I)) || > - isa(cast(*I))) { > - if (CallPassesValueThoughVararg(cast(*I), > TheCall) || > - ! > CallSite::get(cast(*I)).getCalledFunction()) { > - RetValLiveness = Live; > - break; > + > + // If we end up here, we are looking at a direct call to our > function. > + > + // Now, check how our return value(s) is/are used in this > caller. Don't > + // bother checking return values if all of them are live > already > + if (NumLiveRetVals != RetCount) { > + if (STy) { > + // Check all uses of the return value > + for (Value::use_iterator I = TheCall->use_begin(), > + E = TheCall->use_end(); I != E; ++I) { > + ExtractValueInst *Ext = dyn_cast(*I); > + if (Ext && Ext->hasIndices()) { > + // This use uses a part of our return value, survey > the uses of that > + // part and store the results for this index only. > + unsigned Idx = *Ext->idx_begin(); > + if (RetValLiveness[Idx] != Live) { > + RetValLiveness[Idx] = SurveyUses(Ext, > MaybeLiveRetUses[Idx]); > + if (RetValLiveness[Idx] == Live) > + NumLiveRetVals++; > + } > } else { > - RetValLiveness = MaybeLive; > + // Used by something else than extractvalue. Mark all > + // return values as live. > + for (unsigned i = 0; i != RetCount; ++i ) > + RetValLiveness[i] = Live; > + NumLiveRetVals = RetCount; > + break; > } > - } else { > - RetValLiveness = Live; > - break; > } > + } else { > + // Single return value > + RetValLiveness[0] = SurveyUses(TheCall, > MaybeLiveRetUses[0]); > + if (RetValLiveness[0] == Live) > + NumLiveRetVals = RetCount; > + } > + } > } > - > + } > if (FunctionIntrinsicallyLive) { > - DOUT << " Intrinsically live fn: " << F.getName() << "\n"; > + DOUT << "DAE - Intrinsically live fn: " << F.getName() << "\n"; > + // Mark all arguments as live > + unsigned i = 0; > for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end(); > - AI != E; ++AI) > - LiveArguments.insert(AI); > - LiveRetVal.insert(&F); > + AI != E; ++AI, ++i) > + MarkLive(CreateArg(&F, i)); > + // Mark all return values as live > + i = 0; > + for (unsigned i = 0, e = RetValLiveness.size(); i != e; ++i) > + MarkLive(CreateRet(&F, i)); > return; > } > - > - switch (RetValLiveness) { > - case Live: LiveRetVal.insert(&F); break; > - case MaybeLive: MaybeLiveRetVal.insert(&F); break; > - case Dead: DeadRetVal.insert(&F); break; > + > + // Now we've inspected all callers, record the liveness of our > return values. > + for (unsigned i = 0, e = RetValLiveness.size(); i != e; ++i) { > + RetOrArg Ret = CreateRet(&F, i); > + // Mark the result down > + MarkValue(Ret, RetValLiveness[i], MaybeLiveRetUses[i]); > + } > + DOUT << "DAE - Inspecting args for fn: " << F.getName() << "\n"; > + > + // Now, check all of our arguments > + unsigned i = 0; > + UseVector MaybeLiveArgUses; > + for (Function::arg_iterator AI = F.arg_begin(), > + E = F.arg_end(); AI != E; ++AI, ++i) { > + // See what the effect of this use is (recording any uses that > cause > + // MaybeLive in MaybeLiveArgUses) > + Liveness Result = SurveyUses(AI, MaybeLiveArgUses); > + RetOrArg Arg = CreateArg(&F, i); > + // Mark the result down > + MarkValue(Arg, Result, MaybeLiveArgUses); > + // Clear the vector again for the next iteration > + MaybeLiveArgUses.clear(); > } > +} > > - DOUT << " Inspecting args for fn: " << F.getName() << "\n"; > - > - // If it is not intrinsically alive, we know that all users of the > - // function are call sites. Mark all of the arguments live which > are > - // directly used, and keep track of all of the call sites of this > function > - // if there are any arguments we assume that are dead. > - // > - bool AnyMaybeLiveArgs = false; > - for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end(); > - AI != E; ++AI) > - switch (getArgumentLiveness(*AI)) { > - case Live: > - DOUT << " Arg live by use: " << AI->getName() << "\n"; > - LiveArguments.insert(AI); > - break; > - case Dead: > - DOUT << " Arg definitely dead: " << AI->getName() <<"\n"; > - DeadArguments.insert(AI); > - break; > +/// MarkValue - This function marks the liveness of RA depending on > L. If L is > +/// MaybeLive, it also records any uses in MaybeLiveUses such that > RA will be > +/// marked live if any use in MaybeLiveUses gets marked live later > on. > +void DAE::MarkValue(const RetOrArg &RA, Liveness L, const UseVector > &MaybeLiveUses) { > + switch (L) { > + case Live: MarkLive(RA); break; > case MaybeLive: > - DOUT << " Arg only passed to calls: " << AI->getName() << > "\n"; > - AnyMaybeLiveArgs = true; > - MaybeLiveArguments.insert(AI); > + { > + // Note any uses of this value, so this return value can be > + // marked live whenever one of the uses becomes live. > + UseMap::iterator Where = Uses.begin(); > + for (UseVector::const_iterator UI = MaybeLiveUses.begin(), > + UE = MaybeLiveUses.end(); UI != UE; ++UI) > + Where = Uses.insert(Where, UseMap::value_type(*UI, RA)); > break; > } > - > - // If there are any "MaybeLive" arguments, we need to check > callees of > - // this function when/if they become alive. Record which > functions are > - // callees... > - if (AnyMaybeLiveArgs || RetValLiveness == MaybeLive) > - for (Value::use_iterator I = F.use_begin(), E = F.use_end(); > - I != E; ++I) { > - if (AnyMaybeLiveArgs) > - CallSites.insert(std::make_pair(&F, CallSite::get(*I))); > - > - if (RetValLiveness == MaybeLive) > - for (Value::use_iterator UI = I->use_begin(), E = I- > >use_end(); > - UI != E; ++UI) > - InstructionsToInspect.push_back(cast(*UI)); > - } > -} > - > -// isMaybeLiveArgumentNowLive - Check to see if Arg is alive. At > this point, we > -// know that the only uses of Arg are to be passed in as an > argument to a > -// function call or return. Check to see if the formal argument > passed in is in > -// the LiveArguments set. If so, return true. > -// > -bool DAE::isMaybeLiveArgumentNowLive(Argument *Arg) { > - for (Value::use_iterator I = Arg->use_begin(), E = Arg- > >use_end(); I!=E; ++I){ > - if (isa(*I)) { > - if (LiveRetVal.count(Arg->getParent())) return true; > - continue; > - } > - > - CallSite CS = CallSite::get(*I); > - > - // We know that this can only be used for direct calls... > - Function *Callee = CS.getCalledFunction(); > - > - // Loop over all of the arguments (because Arg may be passed > into the call > - // multiple times) and check to see if any are now alive... > - CallSite::arg_iterator CSAI = CS.arg_begin(); > - for (Function::arg_iterator AI = Callee->arg_begin(), E = > Callee->arg_end(); > - AI != E; ++AI, ++CSAI) > - // If this is the argument we are looking for, check to see > if it's alive > - if (*CSAI == Arg && LiveArguments.count(AI)) > - return true; > - } > - return false; > -} > - > -/// MarkArgumentLive - The MaybeLive argument 'Arg' is now known to > be alive. > -/// Mark it live in the specified sets and recursively mark > arguments in callers > -/// live that are needed to pass in a value. > -/// > -void DAE::MarkArgumentLive(Argument *Arg) { > - std::set::iterator It = > MaybeLiveArguments.lower_bound(Arg); > - if (It == MaybeLiveArguments.end() || *It != Arg) return; > - > - DOUT << " MaybeLive argument now live: " << Arg->getName() <<"\n"; > - MaybeLiveArguments.erase(It); > - LiveArguments.insert(Arg); > - > - // Loop over all of the call sites of the function, making any > arguments > - // passed in to provide a value for this argument live as > necessary. > - // > - Function *Fn = Arg->getParent(); > - unsigned ArgNo = std::distance(Fn->arg_begin(), > Function::arg_iterator(Arg)); > - > - std::multimap::iterator I = > CallSites.lower_bound(Fn); > - for (; I != CallSites.end() && I->first == Fn; ++I) { > - CallSite CS = I->second; > - Value *ArgVal = *(CS.arg_begin()+ArgNo); > - if (Argument *ActualArg = dyn_cast(ArgVal)) { > - MarkArgumentLive(ActualArg); > - } else { > - // If the value passed in at this call site is a return value > computed by > - // some other call site, make sure to mark the return value > at the other > - // call site as being needed. > - CallSite ArgCS = CallSite::get(ArgVal); > - if (ArgCS.getInstruction()) > - if (Function *Fn = ArgCS.getCalledFunction()) > - MarkRetValLive(Fn); > - } > + case Dead: break; > } > } > > -/// MarkArgumentLive - The MaybeLive return value for the specified > function is > -/// now known to be alive. Propagate this fact to the return > instructions which > -/// produce it. > -void DAE::MarkRetValLive(Function *F) { > - assert(F && "Shame shame, we can't have null pointers here!"); > - > - // Check to see if we already knew it was live > - std::set::iterator I = MaybeLiveRetVal.lower_bound(F); > - if (I == MaybeLiveRetVal.end() || *I != F) return; // It's > already alive! > - > - DOUT << " MaybeLive retval now live: " << F->getName() << "\n"; > +/// MarkLive - Mark the given return value or argument as live. > Additionally, > +/// mark any values that are used by this value (according to Uses) > live as > +/// well. > +void DAE::MarkLive(RetOrArg RA) { > + if (!LiveValues.insert(RA).second) > + return; // We were already marked Live > > - MaybeLiveRetVal.erase(I); > - LiveRetVal.insert(F); // It is now known to be live! > + if (RA.IsArg) > + DOUT << "DAE - Marking argument " << RA.Idx << " to function " > << RA.F->getNameStart() << " live\n"; > + else > + DOUT << "DAE - Marking return value " << RA.Idx << " of > function " << RA.F->getNameStart() << " live\n"; > > - // Loop over all of the functions, noticing that the return value > is now live. > - for (Function::iterator BB = F->begin(), E = F->end(); BB != E; + > +BB) > - if (ReturnInst *RI = dyn_cast(BB->getTerminator())) > - MarkReturnInstArgumentLive(RI); > + std::pair Range = > Uses.equal_range(RA); > + UseMap::iterator E = Range.second; > + UseMap::iterator I = Range.first; > + for (; I != E; ++I) > + MarkLive(I->second); > + // Erase RA from the Uses map (from the lower bound to wherever > we ended up > + // after the loop). > + Uses.erase(Range.first, Range.second); > } > > -void DAE::MarkReturnInstArgumentLive(ReturnInst *RI) { > - Value *Op = RI->getOperand(0); > - if (Argument *A = dyn_cast(Op)) { > - MarkArgumentLive(A); > - } else if (CallInst *CI = dyn_cast(Op)) { > - if (Function *F = CI->getCalledFunction()) > - MarkRetValLive(F); > - } else if (InvokeInst *II = dyn_cast(Op)) { > - if (Function *F = II->getCalledFunction()) > - MarkRetValLive(F); > - } > -} > - > -// RemoveDeadArgumentsFromFunction - We know that F has dead > arguments, as > +// RemoveDeadStuffFromFunction - Remove any arguments and return > values from F > +// that are not in LiveValues. This function is a noop for any > Function created > +// by this function before, or any function that was not inspected > for liveness. > // specified by the DeadArguments list. Transform the function and > all of the > // callees of the function to not have these arguments. > // > -void DAE::RemoveDeadArgumentsFromFunction(Function *F) { > +bool DAE::RemoveDeadStuffFromFunction(Function *F) { > + // Don't process functions we didn't inspect (such as external > functions, or > + // functions that we've newly created). > + if (!InspectedFunctions.count(F)) > + return false; > + > // Start by computing a new prototype for the function, which is > the same as > - // the old function, but has fewer arguments. > + // the old function, but has fewer arguments and a different > return type. > const FunctionType *FTy = F->getFunctionType(); > std::vector Params; > > @@ -510,28 +558,78 @@ > // The existing function return attributes. > ParameterAttributes RAttrs = PAL.getParamAttrs(0); > > - // Make the function return void if the return value is dead. > + > + // Find out the new return value > + > const Type *RetTy = FTy->getReturnType(); > - if (DeadRetVal.count(F)) { > - RetTy = Type::VoidTy; > - RAttrs &= ~ParamAttr::typeIncompatible(RetTy); > - DeadRetVal.erase(F); > - } > - > + const Type *NRetTy; > + unsigned RetCount = NumRetVals(F); > + // -1 means unused, other numbers are the new index > + SmallVector NewRetIdxs(RetCount, -1); > + std::vector RetTypes; > + if (RetTy != Type::VoidTy) { > + const StructType *STy = dyn_cast(RetTy); > + if (STy) > + // Look at each of the original return values individually > + for (unsigned i = 0; i != RetCount; ++i) { > + RetOrArg Ret = CreateRet(F, i); > + if (LiveValues.erase(Ret)) { > + RetTypes.push_back(STy->getElementType(i)); > + NewRetIdxs[i] = RetTypes.size() - 1; > + } else { > + ++NumRetValsEliminated; > + DOUT << "DAE - Removing return value " << i << " from " << > F->getNameStart() << "\n"; > + } > + } > + else > + // We used to return a single value > + if (LiveValues.erase(CreateRet(F, 0))) { > + RetTypes.push_back(RetTy); > + NewRetIdxs[0] = 0; > + } else { > + DOUT << "DAE - Removing return value from " << F- > >getNameStart() << "\n"; > + ++NumRetValsEliminated; > + } > + if (RetTypes.size() == 0) > + // No return types? Make it void > + NRetTy = Type::VoidTy; > + else if (RetTypes.size() == 1) > + // One return type? Just a simple value then > + NRetTy = RetTypes.front(); > + else > + // More return types? Return a struct with them > + NRetTy = StructType::get(RetTypes); > + } else { > + NRetTy = Type::VoidTy; > + } > + > + // Remove any incompatible attributes > + RAttrs &= ~ParamAttr::typeIncompatible(NRetTy); > if (RAttrs) > ParamAttrsVec.push_back(ParamAttrsWithIndex::get(0, RAttrs)); > - > + > + // Remember which arguments are still alive > + SmallVector ArgAlive(FTy->getNumParams(), false); > // Construct the new parameter list from non-dead arguments. Also > construct > - // a new set of parameter attributes to correspond. > - unsigned index = 1; > - for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); > I != E; > - ++I, ++index) > - if (!DeadArguments.count(I)) { > + // a new set of parameter attributes to correspond. Skip the > first parameter > + // attribute, since that belongs to the return value. > + unsigned i = 0; > + for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); > + I != E; ++I, ++i) { > + RetOrArg Arg = CreateArg(F, i); > + if (LiveValues.erase(Arg)) { > Params.push_back(I->getType()); > + ArgAlive[i] = true; > > - if (ParameterAttributes Attrs = PAL.getParamAttrs(index)) > + // Get the original parameter attributes (skipping the first > one, that is > + // for the return value > + if (ParameterAttributes Attrs = PAL.getParamAttrs(i + 1)) > > ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Params.size(), > Attrs)); > + } else { > + ++NumArgumentsEliminated; > + DOUT << "DAE - Removing argument " << i << " (" << I- > >getNameStart() << ") from " << F->getNameStart() << "\n"; > } > + } > > // Reconstruct the ParamAttrsList based on the vector we > constructed. > PAListPtr NewPAL = PAListPtr::get(ParamAttrsVec.begin(), > ParamAttrsVec.end()); > @@ -546,7 +644,11 @@ > } > > // Create the new function type based on the recomputed parameters. > - FunctionType *NFTy = FunctionType::get(RetTy, Params, FTy- > >isVarArg()); > + FunctionType *NFTy = FunctionType::get(NRetTy, Params, FTy- > >isVarArg()); > + > + // No change? > + if (NFTy == FTy) > + return false; > > // Create the new function body and insert it into the module... > Function *NF = Function::Create(NFTy, F->getLinkage()); > @@ -572,14 +674,17 @@ > if (RAttrs) > ParamAttrsVec.push_back(ParamAttrsWithIndex::get(0, RAttrs)); > > - // Loop over the operands, deleting dead ones... > - CallSite::arg_iterator AI = CS.arg_begin(); > - index = 1; > - for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); > - I != E; ++I, ++AI, ++index) > - if (!DeadArguments.count(I)) { // Remove operands for dead > arguments > - Args.push_back(*AI); > - if (ParameterAttributes Attrs = CallPAL.getParamAttrs(index)) > + // Declare these outside of the loops, so we can reuse them for > the second > + // loop, which loops the varargs > + CallSite::arg_iterator I = CS.arg_begin(); > + unsigned i = 0; > + // Loop over those operands, corresponding to the normal > arguments to the > + // original function, and add those that are still alive. > + for (unsigned e = FTy->getNumParams(); i != e; ++I, ++i) > + if (ArgAlive[i]) { > + Args.push_back(*I); > + // Get original parameter attributes, but skip return > attributes > + if (ParameterAttributes Attrs = CallPAL.getParamAttrs(i + 1)) > > ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Args.size(), Attrs)); > } > > @@ -587,9 +692,9 @@ > Args.push_back(UndefValue::get(Type::Int32Ty)); > > // Push any varargs arguments on the list. Don't forget their > attributes. > - for (; AI != CS.arg_end(); ++AI) { > - Args.push_back(*AI); > - if (ParameterAttributes Attrs = CallPAL.getParamAttrs(index++)) > + for (CallSite::arg_iterator E = CS.arg_end(); I != E; ++I, ++i) { > + Args.push_back(*I); > + if (ParameterAttributes Attrs = CallPAL.getParamAttrs(i + 1)) > > ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Args.size(), Attrs)); > } > > @@ -614,8 +719,45 @@ > > if (!Call->use_empty()) { > if (New->getType() == Type::VoidTy) > + // Our return value was unused, replace by null for now, > uses will get > + // removed later on > Call->replaceAllUsesWith(Constant::getNullValue(Call- > >getType())); > - else { > + else if (isa(RetTy)) { > + // The original return value was a struct, update all uses > (which are > + // all extractvalue instructions). > + for (Value::use_iterator I = Call->use_begin(), E = Call- > >use_end(); > + I != E;) { > + assert(isa(*I) && "Return value not > only used by extractvalue?"); > + ExtractValueInst *EV = cast(*I); > + // Increment now, since we're about to throw away this use. > + ++I; > + assert(EV->hasIndices() && "Return value used by > extractvalue without indices?"); > + unsigned Idx = *EV->idx_begin(); > + if (NewRetIdxs[Idx] != -1) { > + if (RetTypes.size() > 1) { > + // We're still returning a struct, create a new > extractvalue > + // instruction with the first index updated > + std::vector NewIdxs(EV->idx_begin(), EV- > >idx_end()); > + NewIdxs[0] = NewRetIdxs[Idx]; > + Value *NEV = ExtractValueInst::Create(New, > NewIdxs.begin(), NewIdxs.end(), "retval", EV); > + EV->replaceAllUsesWith(NEV); > + EV->eraseFromParent(); > + } else { > + // We are now only returning a simple value, remove the > + // extractvalue > + EV->replaceAllUsesWith(New); > + EV->eraseFromParent(); > + } > + } else { > + // Value unused, replace uses by null for now, they > will get removed > + // later on > + EV->replaceAllUsesWith(Constant::getNullValue(EV- > >getType())); > + EV->eraseFromParent(); > + } > + } > + New->takeName(Call); > + } else { > + // The original function had a single return value > Call->replaceAllUsesWith(New); > New->takeName(Call); > } > @@ -632,13 +774,11 @@ > NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList()); > > // Loop over the argument list, transfering uses of the old > arguments over to > - // the new arguments, also transfering over the names as well. > While we're at > - // it, remove the dead arguments from the DeadArguments list. > - // > + // the new arguments, also transfering over the names as well. > + i = 0; > for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(), > - I2 = NF->arg_begin(); > - I != E; ++I) > - if (!DeadArguments.count(I)) { > + I2 = NF->arg_begin(); I != E; ++I, ++i) > + if (ArgAlive[i]) { > // If this is a live argument, move the name and users over to > the new > // version. > I->replaceAllUsesWith(I2); > @@ -646,10 +786,8 @@ > ++I2; > } else { > // If this argument is dead, replace any uses of it with null > constants > - // (these are guaranteed to only be operands to call > instructions which > - // will later be simplified). > + // (these are guaranteed to become unused later on) > I->replaceAllUsesWith(Constant::getNullValue(I->getType())); > - DeadArguments.erase(I); > } > > // If we change the return value of the function we must rewrite > any return > @@ -657,12 +795,45 @@ > if (F->getReturnType() != NF->getReturnType()) > for (Function::iterator BB = NF->begin(), E = NF->end(); BB != > E; ++BB) > if (ReturnInst *RI = dyn_cast(BB- > >getTerminator())) { > - ReturnInst::Create(0, RI); > + Value *RetVal; > + > + if (NFTy->getReturnType() == Type::VoidTy) { > + RetVal = 0; > + } else { > + assert (isa(RetTy)); > + // The original return value was a struct, insert > + // extractvalue/insertvalue chains to extract only the > values we need > + // to return and insert them into our new result. > + // This does generate messy code, but we'll let it to > instcombine to > + // clean that up > + Value *OldRet = RI->getOperand(0); > + // Start out building up our return value from undef > + RetVal = llvm::UndefValue::get(NRetTy); > + for (unsigned i = 0; i != RetCount; ++i) > + if (NewRetIdxs[i] != -1) { > + ExtractValueInst *EV = > ExtractValueInst::Create(OldRet, i, "newret", RI); > + if (RetTypes.size() > 1) { > + // We're still returning a struct, so reinsert the > value into > + // our new return value at the new index > + > + RetVal = InsertValueInst::Create(RetVal, EV, > NewRetIdxs[i], "oldret"); > + } else { > + // We are now only returning a simple value, so > just return the > + // extracted value > + RetVal = EV; > + } > + } > + } > + // Replace the return instruction with one returning the > new return > + // value (possibly 0 if we became void). > + ReturnInst::Create(RetVal, RI); > BB->getInstList().erase(RI); > } > > // Now that the old function is dead, delete it. > F->eraseFromParent(); > + > + return true; > } > > bool DAE::runOnModule(Module &M) { > @@ -677,7 +848,7 @@ > if (F.getFunctionType()->isVarArg()) > Changed |= DeleteDeadVarargs(F); > } > - > + > // Second phase:loop through the module, determining which > arguments are live. > // We assume all arguments are dead unless proven otherwise > (allowing us to > // determine that dead arguments passed into recursive functions > are dead). > @@ -686,85 +857,14 @@ > for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) > SurveyFunction(*I); > > - // Loop over the instructions to inspect, propagating liveness > among arguments > - // and return values which are MaybeLive. > - while (!InstructionsToInspect.empty()) { > - Instruction *I = InstructionsToInspect.back(); > - InstructionsToInspect.pop_back(); > - > - if (ReturnInst *RI = dyn_cast(I)) { > - // For return instructions, we just have to check to see if > the return > - // value for the current function is known now to be alive. > If so, any > - // arguments used by it are now alive, and any call > instruction return > - // value is alive as well. > - if (LiveRetVal.count(RI->getParent()->getParent())) > - MarkReturnInstArgumentLive(RI); > - > - } else { > - CallSite CS = CallSite::get(I); > - assert(CS.getInstruction() && "Unknown instruction for the > I2I list!"); > - > - Function *Callee = CS.getCalledFunction(); > - > - // If we found a call or invoke instruction on this list, > that means that > - // an argument of the function is a call instruction. If the > argument is > - // live, then the return value of the called instruction is > now live. > - // > - CallSite::arg_iterator AI = CS.arg_begin(); // ActualIterator > - for (Function::arg_iterator FI = Callee->arg_begin(), > - E = Callee->arg_end(); FI != E; ++AI, ++FI) { > - // If this argument is another call... > - CallSite ArgCS = CallSite::get(*AI); > - if (ArgCS.getInstruction() && LiveArguments.count(FI)) > - if (Function *Callee = ArgCS.getCalledFunction()) > - MarkRetValLive(Callee); > - } > - } > + // Now, remove all dead arguments and return values from each > function in > + // turn > + for (Module::iterator I = M.begin(), E = M.end(); I != E; ) { > + // Increment now, because the function will probably get > removed (ie > + // replaced by a new one) > + Function *F = I++; > + Changed |= RemoveDeadStuffFromFunction(F); > } > > - // Now we loop over all of the MaybeLive arguments, promoting > them to be live > - // arguments if one of the calls that uses the arguments to the > calls they are > - // passed into requires them to be live. Of course this could > make other > - // arguments live, so process callers recursively. > - // > - // Because elements can be removed from the MaybeLiveArguments > set, copy it to > - // a temporary vector. > - // > - std::vector TmpArgList(MaybeLiveArguments.begin(), > - MaybeLiveArguments.end()); > - for (unsigned i = 0, e = TmpArgList.size(); i != e; ++i) { > - Argument *MLA = TmpArgList[i]; > - if (MaybeLiveArguments.count(MLA) && > - isMaybeLiveArgumentNowLive(MLA)) > - MarkArgumentLive(MLA); > - } > - > - // Recover memory early... > - CallSites.clear(); > - > - // At this point, we know that all arguments in DeadArguments and > - // MaybeLiveArguments are dead. If the two sets are empty, there > is nothing > - // to do. > - if (MaybeLiveArguments.empty() && DeadArguments.empty() && > - MaybeLiveRetVal.empty() && DeadRetVal.empty()) > - return Changed; > - > - // Otherwise, compact into one set, and start eliminating the > arguments from > - // the functions. > - DeadArguments.insert(MaybeLiveArguments.begin(), > MaybeLiveArguments.end()); > - MaybeLiveArguments.clear(); > - DeadRetVal.insert(MaybeLiveRetVal.begin(), MaybeLiveRetVal.end()); > - MaybeLiveRetVal.clear(); > - > - LiveArguments.clear(); > - LiveRetVal.clear(); > - > - NumArgumentsEliminated += DeadArguments.size(); > - NumRetValsEliminated += DeadRetVal.size(); > - while (!DeadArguments.empty()) > - RemoveDeadArgumentsFromFunction((*DeadArguments.begin())- > >getParent()); > - > - while (!DeadRetVal.empty()) > - RemoveDeadArgumentsFromFunction(*DeadRetVal.begin()); > - return true; > + return Changed; > } > > Added: llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll?rev=52459&view=auto > > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll (added) > +++ llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll Wed Jun > 18 06:12:53 2008 > @@ -0,0 +1,39 @@ > +; This test sees if return values (and arguments) are properly > removed when they > +; are unused. All unused values are typed i16, so we can easily > check. We also > +; run instcombine to fold insert/extractvalue chains and we run dce > to clean up > +; any remaining dead stuff. > +; RUN: llvm-as < %s | opt -deadargelim -instcombine -dce | llvm-dis > | not grep i16 > + > +define internal {i16, i32} @test(i16 %DEADARG) { > + %A = insertvalue {i16,i32} undef, i16 1, 0 > + %B = insertvalue {i16,i32} %A, i32 1001, 1 > + ret {i16,i32} %B > +} > + > +define internal {i32, i16} @test2() { > + %DEAD = call i16 @test4() > + %A = insertvalue {i32,i16} undef, i32 1, 0 > + %B = insertvalue {i32,i16} %A, i16 %DEAD, 1 > + ret {i32,i16} %B > +} > + > +define internal i32 @test3(i16 %A) { > + %ret = call {i16, i32} @test( i16 %A ) ; > [#uses=0] > + %DEAD = extractvalue {i16, i32} %ret, 0 > + %LIVE = extractvalue {i16, i32} %ret, 1 > + ret i32 %LIVE > +} > + > +define internal i16 @test4() { > + ret i16 0 > +} > + > +define i32 @main() { > + %ret = call {i32, i16} @test2() ; > [#uses=1] > + %LIVE = extractvalue {i32, i16} %ret, 0 > + %DEAD = extractvalue {i32, i16} %ret, 1 > + %Y = add i32 %LIVE, -123 ; [#uses=1] > + %LIVE2 = call i32 @test3(i16 %DEAD) ; > [#uses=1] > + %Z = add i32 %LIVE2, %Y ; [#uses=1] > + ret i32 %Z > +} > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From resistor at mac.com Wed Jun 18 12:32:17 2008 From: resistor at mac.com (Owen Anderson) Date: Wed, 18 Jun 2008 17:32:17 -0000 Subject: [llvm-commits] [llvm] r52465 - /llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Message-ID: <200806181732.m5IHWHcu010170@zion.cs.uiuc.edu> Author: resistor Date: Wed Jun 18 12:32:16 2008 New Revision: 52465 URL: http://llvm.org/viewvc/llvm-project?rev=52465&view=rev Log: Revert r52459, which was causing an infinite loop or massive slowdown on MultiSource/Applications/SPASS, and possibly others as well. Please reapply once this is fixed. Modified: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Modified: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp?rev=52465&r1=52464&r2=52465&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp (original) +++ llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Wed Jun 18 12:32:16 2008 @@ -10,10 +10,10 @@ // This pass deletes dead arguments from internal functions. Dead argument // elimination removes arguments which are directly dead, as well as arguments // only passed into function calls as dead arguments of other functions. This -// pass also deletes dead return values in a similar way. +// pass also deletes dead arguments in a similar way. // // This pass is often useful as a cleanup pass to run after aggressive -// interprocedural passes, which add possibly-dead arguments or return values. +// interprocedural passes, which add possibly-dead arguments. // //===----------------------------------------------------------------------===// @@ -42,66 +42,40 @@ /// DAE - The dead argument elimination pass. /// class VISIBILITY_HIDDEN DAE : public ModulePass { - public: - - /// Struct that represent either a (part of a) return value or a function - /// argument. Used so that arguments and return values can be used - /// interchangably. - struct RetOrArg { - RetOrArg(const Function* F, unsigned Idx, bool IsArg) : F(F), Idx(Idx), IsArg(IsArg) {} - const Function *F; - unsigned Idx; - bool IsArg; - - /// Make RetOrArg comparable, so we can put it into a map - bool operator<(const RetOrArg &O) const { - if (F != O.F) - return F < O.F; - else if (Idx != O.Idx) - return Idx < O.Idx; - else - return IsArg < O.IsArg; - } - }; - /// Liveness enum - During our initial pass over the program, we determine /// that things are either definately alive, definately dead, or in need of /// interprocedural analysis (MaybeLive). /// enum Liveness { Live, MaybeLive, Dead }; - /// Convenience wrapper - RetOrArg CreateRet(const Function *F, unsigned Idx) { return RetOrArg(F, Idx, false); } - /// Convenience wrapper - RetOrArg CreateArg(const Function *F, unsigned Idx) { return RetOrArg(F, Idx, true); } - - typedef std::multimap UseMap; - /// This map maps a return value or argument to all return values or - /// arguments it uses. - /// For example (indices are left out for clarity): - /// - Uses[ret F] = ret G - /// This means that F calls G, and F returns the value returned by G. - /// - Uses[arg F] = ret G - /// This means that some function calls G and passes its result as an - /// argument to F. - /// - Uses[ret F] = arg F - /// This means that F returns one of its own arguments. - /// - Uses[arg F] = arg G - /// This means that G calls F and passes one of its own (G's) arguments - /// directly to F. - UseMap Uses; - - typedef std::set LiveSet; - - /// This set contains all values that have been determined to be live - LiveSet LiveValues; - - typedef SmallVector UseVector; - - /// This is the set of functions that have been inspected. Since LiveValues - /// keeps a list of live values for inspected functions only, this way we - /// can prevent uninspected functions becoming completely dead. - std::set InspectedFunctions; + /// LiveArguments, MaybeLiveArguments, DeadArguments - These sets contain + /// all of the arguments in the program. The Dead set contains arguments + /// which are completely dead (never used in the function). The MaybeLive + /// set contains arguments which are only passed into other function calls, + /// thus may be live and may be dead. The Live set contains arguments which + /// are known to be alive. + /// + std::set DeadArguments, MaybeLiveArguments, LiveArguments; + + /// DeadRetVal, MaybeLiveRetVal, LifeRetVal - These sets contain all of the + /// functions in the program. The Dead set contains functions whose return + /// value is known to be dead. The MaybeLive set contains functions whose + /// return values are only used by return instructions, and the Live set + /// contains functions whose return values are used, functions that are + /// external, and functions that already return void. + /// + std::set DeadRetVal, MaybeLiveRetVal, LiveRetVal; + + /// InstructionsToInspect - As we mark arguments and return values + /// MaybeLive, we keep track of which instructions could make the values + /// live here. Once the entire program has had the return value and + /// arguments analyzed, this set is scanned to promote the MaybeLive objects + /// to be Live if they really are used. + std::vector InstructionsToInspect; + + /// CallSites - Keep track of the call sites of functions that have + /// MaybeLive arguments or return values. + std::multimap CallSites; public: static char ID; // Pass identification, replacement for typeid @@ -111,19 +85,20 @@ virtual bool ShouldHackArguments() const { return false; } private: - Liveness IsMaybeLive(RetOrArg Use, UseVector &MaybeLiveUses); - Liveness SurveyUse(Value::use_iterator U, UseVector &MaybeLiveUses, unsigned RetValNum = 0); - Liveness SurveyUses(Value *V, UseVector &MaybeLiveUses); - - void SurveyFunction(Function &F); - void MarkValue(const RetOrArg &RA, Liveness L, const UseVector &MaybeLiveUses); - void MarkLive(RetOrArg RA); - bool RemoveDeadStuffFromFunction(Function *F); + Liveness getArgumentLiveness(const Argument &A); + bool isMaybeLiveArgumentNowLive(Argument *Arg); + bool DeleteDeadVarargs(Function &Fn); + void SurveyFunction(Function &Fn); + + void MarkArgumentLive(Argument *Arg); + void MarkRetValLive(Function *F); + void MarkReturnInstArgumentLive(ReturnInst *RI); + + void RemoveDeadArgumentsFromFunction(Function *F); }; } - char DAE::ID = 0; static RegisterPass X("deadargelim", "Dead Argument Elimination"); @@ -180,7 +155,7 @@ // remove the "..." and adjust all the calls. // Start by computing a new prototype for the function, which is the same as - // the old function, but doesn't have isVarArg set. + // the old function, but has fewer arguments. const FunctionType *FTy = Fn.getFunctionType(); std::vector Params(FTy->param_begin(), FTy->param_end()); FunctionType *NFTy = FunctionType::get(FTy->getReturnType(), Params, false); @@ -258,110 +233,57 @@ return true; } -/// Convenience function that returns the number of return values. It returns 0 -/// for void functions and 1 for functions not returning a struct. It returns -/// the number of struct elements for functions returning a struct. -static unsigned NumRetVals(const Function *F) { - if (F->getReturnType() == Type::VoidTy) - return 0; - else if (const StructType *STy = dyn_cast(F->getReturnType())) - return STy->getNumElements(); - else - return 1; -} -/// IsMaybeAlive - This checks Use for liveness. If Use is live, returns Live, -/// else returns MaybeLive. Also, adds Use to MaybeLiveUses in the latter case. -DAE::Liveness DAE::IsMaybeLive(RetOrArg Use, UseVector &MaybeLiveUses) { - // We're live if our use is already marked as live - if (LiveValues.count(Use)) +static inline bool CallPassesValueThoughVararg(Instruction *Call, + const Value *Arg) { + CallSite CS = CallSite::get(Call); + const Type *CalledValueTy = CS.getCalledValue()->getType(); + const Type *FTy = cast(CalledValueTy)->getElementType(); + unsigned NumFixedArgs = cast(FTy)->getNumParams(); + for (CallSite::arg_iterator AI = CS.arg_begin()+NumFixedArgs; + AI != CS.arg_end(); ++AI) + if (AI->get() == Arg) + return true; + return false; +} + +// getArgumentLiveness - Inspect an argument, determining if is known Live +// (used in a computation), MaybeLive (only passed as an argument to a call), or +// Dead (not used). +DAE::Liveness DAE::getArgumentLiveness(const Argument &A) { + const Function *F = A.getParent(); + + // If this is the return value of a struct function, it's not really dead. + if (F->hasStructRetAttr() && &*(F->arg_begin()) == &A) return Live; + + if (A.use_empty()) // First check, directly dead? + return Dead; - // We're maybe live otherwise, but remember that we must become live if - // Use becomes live. - MaybeLiveUses.push_back(Use); - return MaybeLive; -} - - -/// SurveyUse - This looks at a single use of an argument or return value -/// and determines if it should be alive or not. Adds this use to MaybeLiveUses -/// if it causes the used value to become MaybeAlive. -/// -/// RetValNum is the return value number to use when this use is used in a -/// return instruction. This is used in the recursion, you should always leave -/// it at 0. -DAE::Liveness DAE::SurveyUse(Value::use_iterator U, UseVector &MaybeLiveUses, unsigned RetValNum) { - Value *V = *U; - if (ReturnInst *RI = dyn_cast(V)) { - // The value is returned from another function. It's only live when the - // caller's return value is live - RetOrArg Use = CreateRet(RI->getParent()->getParent(), RetValNum); - // We might be live, depending on the liveness of Use - return IsMaybeLive(Use, MaybeLiveUses); - } - if (InsertValueInst *IV = dyn_cast(V)) { - if (U.getOperandNo() != InsertValueInst::getAggregateOperandIndex() && IV->hasIndices()) - // The use we are examining is inserted into an aggregate. Our liveness - // depends on all uses of that aggregate, but if it is used as a return - // value, only index at which we were inserted counts. - RetValNum = *IV->idx_begin(); + // Scan through all of the uses, looking for non-argument passing uses. + for (Value::use_const_iterator I = A.use_begin(), E = A.use_end(); I!=E;++I) { + // Return instructions do not immediately effect liveness. + if (isa(*I)) + continue; + + CallSite CS = CallSite::get(const_cast(*I)); + if (!CS.getInstruction()) { + // If its used by something that is not a call or invoke, it's alive! + return Live; + } + // If it's an indirect call, mark it alive... + Function *Callee = CS.getCalledFunction(); + if (!Callee) return Live; + + // Check to see if it's passed through a va_arg area: if so, we cannot + // remove it. + if (CallPassesValueThoughVararg(CS.getInstruction(), &A)) + return Live; // If passed through va_arg area, we cannot remove it + } - // Note that if we are used as the aggregate operand to the insertvalue, - // we don't change RetValNum, but do survey all our uses. - - Liveness Result = Dead; - for (Value::use_iterator I = IV->use_begin(), - E = V->use_end(); I != E; ++I) { - Result = SurveyUse(I, MaybeLiveUses, RetValNum); - if (Result == Live) - break; - } - return Result; - } - CallSite CS = CallSite::get(V); - if (CS.getInstruction()) { - Function *F = CS.getCalledFunction(); - if (F) { - // Used in a direct call - - // Check for vararg. Do - 1 to skip the first operand to call (the - // function itself). - if (U.getOperandNo() - 1 >= F->getFunctionType()->getNumParams()) - // The value is passed in through a vararg! Must be live. - return Live; - - // Value passed to a normal call. It's only live when the corresponding - // argument (operand number - 1 to skip the function pointer operand) to - // the called function turns out live - RetOrArg Use = CreateArg(F, U.getOperandNo() - 1); - return IsMaybeLive(Use, MaybeLiveUses); - } else { - // Used in any other way? Value must be live. - return Live; - } - } - // Used in any other way? Value must be live. - return Live; + return MaybeLive; // It must be used, but only as argument to a function } -/// SurveyUses - This looks at all the uses of the given return value -/// (possibly a partial return value from a function returning a struct). -/// Returns the Liveness deduced from the uses of this value. -/// -/// Adds all uses that cause the result to be MaybeLive to MaybeLiveRetUses. -DAE::Liveness DAE::SurveyUses(Value *V, UseVector &MaybeLiveUses) { - // Assume it's dead (which will only hold if there are no uses at all..) - Liveness Result = Dead; - // Check each use - for (Value::use_iterator I = V->use_begin(), - E = V->use_end(); I != E; ++I) { - Result = SurveyUse(I, MaybeLiveUses); - if (Result == Live) - break; - } - return Result; -} // SurveyFunction - This performs the initial survey of the specified function, // checking out whether or not it uses any of its incoming arguments or whether @@ -372,36 +294,13 @@ // well as arguments to functions which have their "address taken". // void DAE::SurveyFunction(Function &F) { - InspectedFunctions.insert(&F); bool FunctionIntrinsicallyLive = false; - unsigned RetCount = NumRetVals(&F); - // Assume all return values are dead - typedef SmallVector RetVals; - RetVals RetValLiveness(RetCount, Dead); - - // These vectors maps each return value to the uses that make it MaybeLive, so - // we can add those to the MaybeLiveRetVals list if the return value - // really turns out to be MaybeLive. Initializes to RetCount empty vectors - typedef SmallVector RetUses; - // Intialized to a list of RetCount empty lists - RetUses MaybeLiveRetUses(RetCount); - - for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) - if (ReturnInst *RI = dyn_cast(BB->getTerminator())) - if (RI->getNumOperands() != 0 && RI->getOperand(0)->getType() != F.getFunctionType()->getReturnType()) { - // We don't support old style multiple return values - FunctionIntrinsicallyLive = true; - break; - } - if (!F.hasInternalLinkage() && (!ShouldHackArguments() || F.isIntrinsic())) + Liveness RetValLiveness = F.getReturnType() == Type::VoidTy ? Live : Dead; + + if (!F.hasInternalLinkage() && + (!ShouldHackArguments() || F.isIntrinsic())) FunctionIntrinsicallyLive = true; - if (!FunctionIntrinsicallyLive) { - DOUT << "DAE - Inspecting callers for fn: " << F.getName() << "\n"; - // Keep track of the number of live retvals, so we can skip checks once all - // of them turn out to be live. - unsigned NumLiveRetVals = 0; - const Type *STy = dyn_cast(F.getReturnType()); - // Loop all uses of the function + else for (Value::use_iterator I = F.use_begin(), E = F.use_end(); I != E; ++I) { // If the function is PASSED IN as an argument, its address has been taken if (I.getOperandNo() != 0) { @@ -416,138 +315,191 @@ FunctionIntrinsicallyLive = true; break; } - - // If we end up here, we are looking at a direct call to our function. - - // Now, check how our return value(s) is/are used in this caller. Don't - // bother checking return values if all of them are live already - if (NumLiveRetVals != RetCount) { - if (STy) { - // Check all uses of the return value - for (Value::use_iterator I = TheCall->use_begin(), - E = TheCall->use_end(); I != E; ++I) { - ExtractValueInst *Ext = dyn_cast(*I); - if (Ext && Ext->hasIndices()) { - // This use uses a part of our return value, survey the uses of that - // part and store the results for this index only. - unsigned Idx = *Ext->idx_begin(); - if (RetValLiveness[Idx] != Live) { - RetValLiveness[Idx] = SurveyUses(Ext, MaybeLiveRetUses[Idx]); - if (RetValLiveness[Idx] == Live) - NumLiveRetVals++; - } - } else { - // Used by something else than extractvalue. Mark all - // return values as live. - for (unsigned i = 0; i != RetCount; ++i ) - RetValLiveness[i] = Live; - NumLiveRetVals = RetCount; + + // Check to see if the return value is used... + if (RetValLiveness != Live) + for (Value::use_iterator I = TheCall->use_begin(), + E = TheCall->use_end(); I != E; ++I) + if (isa(cast(*I))) { + RetValLiveness = MaybeLive; + } else if (isa(cast(*I)) || + isa(cast(*I))) { + if (CallPassesValueThoughVararg(cast(*I), TheCall) || + !CallSite::get(cast(*I)).getCalledFunction()) { + RetValLiveness = Live; break; + } else { + RetValLiveness = MaybeLive; } + } else { + RetValLiveness = Live; + break; } - } else { - // Single return value - RetValLiveness[0] = SurveyUses(TheCall, MaybeLiveRetUses[0]); - if (RetValLiveness[0] == Live) - NumLiveRetVals = RetCount; - } - } } - } + if (FunctionIntrinsicallyLive) { - DOUT << "DAE - Intrinsically live fn: " << F.getName() << "\n"; - // Mark all arguments as live - unsigned i = 0; + DOUT << " Intrinsically live fn: " << F.getName() << "\n"; for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end(); - AI != E; ++AI, ++i) - MarkLive(CreateArg(&F, i)); - // Mark all return values as live - i = 0; - for (unsigned i = 0, e = RetValLiveness.size(); i != e; ++i) - MarkLive(CreateRet(&F, i)); + AI != E; ++AI) + LiveArguments.insert(AI); + LiveRetVal.insert(&F); return; } - - // Now we've inspected all callers, record the liveness of our return values. - for (unsigned i = 0, e = RetValLiveness.size(); i != e; ++i) { - RetOrArg Ret = CreateRet(&F, i); - // Mark the result down - MarkValue(Ret, RetValLiveness[i], MaybeLiveRetUses[i]); - } - DOUT << "DAE - Inspecting args for fn: " << F.getName() << "\n"; - - // Now, check all of our arguments - unsigned i = 0; - UseVector MaybeLiveArgUses; - for (Function::arg_iterator AI = F.arg_begin(), - E = F.arg_end(); AI != E; ++AI, ++i) { - // See what the effect of this use is (recording any uses that cause - // MaybeLive in MaybeLiveArgUses) - Liveness Result = SurveyUses(AI, MaybeLiveArgUses); - RetOrArg Arg = CreateArg(&F, i); - // Mark the result down - MarkValue(Arg, Result, MaybeLiveArgUses); - // Clear the vector again for the next iteration - MaybeLiveArgUses.clear(); + + switch (RetValLiveness) { + case Live: LiveRetVal.insert(&F); break; + case MaybeLive: MaybeLiveRetVal.insert(&F); break; + case Dead: DeadRetVal.insert(&F); break; } -} -/// MarkValue - This function marks the liveness of RA depending on L. If L is -/// MaybeLive, it also records any uses in MaybeLiveUses such that RA will be -/// marked live if any use in MaybeLiveUses gets marked live later on. -void DAE::MarkValue(const RetOrArg &RA, Liveness L, const UseVector &MaybeLiveUses) { - switch (L) { - case Live: MarkLive(RA); break; + DOUT << " Inspecting args for fn: " << F.getName() << "\n"; + + // If it is not intrinsically alive, we know that all users of the + // function are call sites. Mark all of the arguments live which are + // directly used, and keep track of all of the call sites of this function + // if there are any arguments we assume that are dead. + // + bool AnyMaybeLiveArgs = false; + for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end(); + AI != E; ++AI) + switch (getArgumentLiveness(*AI)) { + case Live: + DOUT << " Arg live by use: " << AI->getName() << "\n"; + LiveArguments.insert(AI); + break; + case Dead: + DOUT << " Arg definitely dead: " << AI->getName() <<"\n"; + DeadArguments.insert(AI); + break; case MaybeLive: - { - // Note any uses of this value, so this return value can be - // marked live whenever one of the uses becomes live. - UseMap::iterator Where = Uses.begin(); - for (UseVector::const_iterator UI = MaybeLiveUses.begin(), - UE = MaybeLiveUses.end(); UI != UE; ++UI) - Where = Uses.insert(Where, UseMap::value_type(*UI, RA)); + DOUT << " Arg only passed to calls: " << AI->getName() << "\n"; + AnyMaybeLiveArgs = true; + MaybeLiveArguments.insert(AI); break; } - case Dead: break; + + // If there are any "MaybeLive" arguments, we need to check callees of + // this function when/if they become alive. Record which functions are + // callees... + if (AnyMaybeLiveArgs || RetValLiveness == MaybeLive) + for (Value::use_iterator I = F.use_begin(), E = F.use_end(); + I != E; ++I) { + if (AnyMaybeLiveArgs) + CallSites.insert(std::make_pair(&F, CallSite::get(*I))); + + if (RetValLiveness == MaybeLive) + for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); + UI != E; ++UI) + InstructionsToInspect.push_back(cast(*UI)); + } +} + +// isMaybeLiveArgumentNowLive - Check to see if Arg is alive. At this point, we +// know that the only uses of Arg are to be passed in as an argument to a +// function call or return. Check to see if the formal argument passed in is in +// the LiveArguments set. If so, return true. +// +bool DAE::isMaybeLiveArgumentNowLive(Argument *Arg) { + for (Value::use_iterator I = Arg->use_begin(), E = Arg->use_end(); I!=E; ++I){ + if (isa(*I)) { + if (LiveRetVal.count(Arg->getParent())) return true; + continue; + } + + CallSite CS = CallSite::get(*I); + + // We know that this can only be used for direct calls... + Function *Callee = CS.getCalledFunction(); + + // Loop over all of the arguments (because Arg may be passed into the call + // multiple times) and check to see if any are now alive... + CallSite::arg_iterator CSAI = CS.arg_begin(); + for (Function::arg_iterator AI = Callee->arg_begin(), E = Callee->arg_end(); + AI != E; ++AI, ++CSAI) + // If this is the argument we are looking for, check to see if it's alive + if (*CSAI == Arg && LiveArguments.count(AI)) + return true; + } + return false; +} + +/// MarkArgumentLive - The MaybeLive argument 'Arg' is now known to be alive. +/// Mark it live in the specified sets and recursively mark arguments in callers +/// live that are needed to pass in a value. +/// +void DAE::MarkArgumentLive(Argument *Arg) { + std::set::iterator It = MaybeLiveArguments.lower_bound(Arg); + if (It == MaybeLiveArguments.end() || *It != Arg) return; + + DOUT << " MaybeLive argument now live: " << Arg->getName() <<"\n"; + MaybeLiveArguments.erase(It); + LiveArguments.insert(Arg); + + // Loop over all of the call sites of the function, making any arguments + // passed in to provide a value for this argument live as necessary. + // + Function *Fn = Arg->getParent(); + unsigned ArgNo = std::distance(Fn->arg_begin(), Function::arg_iterator(Arg)); + + std::multimap::iterator I = CallSites.lower_bound(Fn); + for (; I != CallSites.end() && I->first == Fn; ++I) { + CallSite CS = I->second; + Value *ArgVal = *(CS.arg_begin()+ArgNo); + if (Argument *ActualArg = dyn_cast(ArgVal)) { + MarkArgumentLive(ActualArg); + } else { + // If the value passed in at this call site is a return value computed by + // some other call site, make sure to mark the return value at the other + // call site as being needed. + CallSite ArgCS = CallSite::get(ArgVal); + if (ArgCS.getInstruction()) + if (Function *Fn = ArgCS.getCalledFunction()) + MarkRetValLive(Fn); + } } } -/// MarkLive - Mark the given return value or argument as live. Additionally, -/// mark any values that are used by this value (according to Uses) live as -/// well. -void DAE::MarkLive(RetOrArg RA) { - if (!LiveValues.insert(RA).second) - return; // We were already marked Live +/// MarkArgumentLive - The MaybeLive return value for the specified function is +/// now known to be alive. Propagate this fact to the return instructions which +/// produce it. +void DAE::MarkRetValLive(Function *F) { + assert(F && "Shame shame, we can't have null pointers here!"); - if (RA.IsArg) - DOUT << "DAE - Marking argument " << RA.Idx << " to function " << RA.F->getNameStart() << " live\n"; - else - DOUT << "DAE - Marking return value " << RA.Idx << " of function " << RA.F->getNameStart() << " live\n"; + // Check to see if we already knew it was live + std::set::iterator I = MaybeLiveRetVal.lower_bound(F); + if (I == MaybeLiveRetVal.end() || *I != F) return; // It's already alive! + + DOUT << " MaybeLive retval now live: " << F->getName() << "\n"; - std::pair Range = Uses.equal_range(RA); - UseMap::iterator E = Range.second; - UseMap::iterator I = Range.first; - for (; I != E; ++I) - MarkLive(I->second); - // Erase RA from the Uses map (from the lower bound to wherever we ended up - // after the loop). - Uses.erase(Range.first, Range.second); + MaybeLiveRetVal.erase(I); + LiveRetVal.insert(F); // It is now known to be live! + + // Loop over all of the functions, noticing that the return value is now live. + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) + if (ReturnInst *RI = dyn_cast(BB->getTerminator())) + MarkReturnInstArgumentLive(RI); } -// RemoveDeadStuffFromFunction - Remove any arguments and return values from F -// that are not in LiveValues. This function is a noop for any Function created -// by this function before, or any function that was not inspected for liveness. +void DAE::MarkReturnInstArgumentLive(ReturnInst *RI) { + Value *Op = RI->getOperand(0); + if (Argument *A = dyn_cast(Op)) { + MarkArgumentLive(A); + } else if (CallInst *CI = dyn_cast(Op)) { + if (Function *F = CI->getCalledFunction()) + MarkRetValLive(F); + } else if (InvokeInst *II = dyn_cast(Op)) { + if (Function *F = II->getCalledFunction()) + MarkRetValLive(F); + } +} + +// RemoveDeadArgumentsFromFunction - We know that F has dead arguments, as // specified by the DeadArguments list. Transform the function and all of the // callees of the function to not have these arguments. // -bool DAE::RemoveDeadStuffFromFunction(Function *F) { - // Don't process functions we didn't inspect (such as external functions, or - // functions that we've newly created). - if (!InspectedFunctions.count(F)) - return false; - +void DAE::RemoveDeadArgumentsFromFunction(Function *F) { // Start by computing a new prototype for the function, which is the same as - // the old function, but has fewer arguments and a different return type. + // the old function, but has fewer arguments. const FunctionType *FTy = F->getFunctionType(); std::vector Params; @@ -558,78 +510,28 @@ // The existing function return attributes. ParameterAttributes RAttrs = PAL.getParamAttrs(0); - - // Find out the new return value - + // Make the function return void if the return value is dead. const Type *RetTy = FTy->getReturnType(); - const Type *NRetTy; - unsigned RetCount = NumRetVals(F); - // -1 means unused, other numbers are the new index - SmallVector NewRetIdxs(RetCount, -1); - std::vector RetTypes; - if (RetTy != Type::VoidTy) { - const StructType *STy = dyn_cast(RetTy); - if (STy) - // Look at each of the original return values individually - for (unsigned i = 0; i != RetCount; ++i) { - RetOrArg Ret = CreateRet(F, i); - if (LiveValues.erase(Ret)) { - RetTypes.push_back(STy->getElementType(i)); - NewRetIdxs[i] = RetTypes.size() - 1; - } else { - ++NumRetValsEliminated; - DOUT << "DAE - Removing return value " << i << " from " << F->getNameStart() << "\n"; - } - } - else - // We used to return a single value - if (LiveValues.erase(CreateRet(F, 0))) { - RetTypes.push_back(RetTy); - NewRetIdxs[0] = 0; - } else { - DOUT << "DAE - Removing return value from " << F->getNameStart() << "\n"; - ++NumRetValsEliminated; - } - if (RetTypes.size() == 0) - // No return types? Make it void - NRetTy = Type::VoidTy; - else if (RetTypes.size() == 1) - // One return type? Just a simple value then - NRetTy = RetTypes.front(); - else - // More return types? Return a struct with them - NRetTy = StructType::get(RetTypes); - } else { - NRetTy = Type::VoidTy; - } - - // Remove any incompatible attributes - RAttrs &= ~ParamAttr::typeIncompatible(NRetTy); + if (DeadRetVal.count(F)) { + RetTy = Type::VoidTy; + RAttrs &= ~ParamAttr::typeIncompatible(RetTy); + DeadRetVal.erase(F); + } + if (RAttrs) ParamAttrsVec.push_back(ParamAttrsWithIndex::get(0, RAttrs)); - - // Remember which arguments are still alive - SmallVector ArgAlive(FTy->getNumParams(), false); + // Construct the new parameter list from non-dead arguments. Also construct - // a new set of parameter attributes to correspond. Skip the first parameter - // attribute, since that belongs to the return value. - unsigned i = 0; - for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); - I != E; ++I, ++i) { - RetOrArg Arg = CreateArg(F, i); - if (LiveValues.erase(Arg)) { + // a new set of parameter attributes to correspond. + unsigned index = 1; + for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; + ++I, ++index) + if (!DeadArguments.count(I)) { Params.push_back(I->getType()); - ArgAlive[i] = true; - // Get the original parameter attributes (skipping the first one, that is - // for the return value - if (ParameterAttributes Attrs = PAL.getParamAttrs(i + 1)) + if (ParameterAttributes Attrs = PAL.getParamAttrs(index)) ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Params.size(), Attrs)); - } else { - ++NumArgumentsEliminated; - DOUT << "DAE - Removing argument " << i << " (" << I->getNameStart() << ") from " << F->getNameStart() << "\n"; } - } // Reconstruct the ParamAttrsList based on the vector we constructed. PAListPtr NewPAL = PAListPtr::get(ParamAttrsVec.begin(), ParamAttrsVec.end()); @@ -644,11 +546,7 @@ } // Create the new function type based on the recomputed parameters. - FunctionType *NFTy = FunctionType::get(NRetTy, Params, FTy->isVarArg()); - - // No change? - if (NFTy == FTy) - return false; + FunctionType *NFTy = FunctionType::get(RetTy, Params, FTy->isVarArg()); // Create the new function body and insert it into the module... Function *NF = Function::Create(NFTy, F->getLinkage()); @@ -674,17 +572,14 @@ if (RAttrs) ParamAttrsVec.push_back(ParamAttrsWithIndex::get(0, RAttrs)); - // Declare these outside of the loops, so we can reuse them for the second - // loop, which loops the varargs - CallSite::arg_iterator I = CS.arg_begin(); - unsigned i = 0; - // Loop over those operands, corresponding to the normal arguments to the - // original function, and add those that are still alive. - for (unsigned e = FTy->getNumParams(); i != e; ++I, ++i) - if (ArgAlive[i]) { - Args.push_back(*I); - // Get original parameter attributes, but skip return attributes - if (ParameterAttributes Attrs = CallPAL.getParamAttrs(i + 1)) + // Loop over the operands, deleting dead ones... + CallSite::arg_iterator AI = CS.arg_begin(); + index = 1; + for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); + I != E; ++I, ++AI, ++index) + if (!DeadArguments.count(I)) { // Remove operands for dead arguments + Args.push_back(*AI); + if (ParameterAttributes Attrs = CallPAL.getParamAttrs(index)) ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Args.size(), Attrs)); } @@ -692,9 +587,9 @@ Args.push_back(UndefValue::get(Type::Int32Ty)); // Push any varargs arguments on the list. Don't forget their attributes. - for (CallSite::arg_iterator E = CS.arg_end(); I != E; ++I, ++i) { - Args.push_back(*I); - if (ParameterAttributes Attrs = CallPAL.getParamAttrs(i + 1)) + for (; AI != CS.arg_end(); ++AI) { + Args.push_back(*AI); + if (ParameterAttributes Attrs = CallPAL.getParamAttrs(index++)) ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Args.size(), Attrs)); } @@ -719,45 +614,8 @@ if (!Call->use_empty()) { if (New->getType() == Type::VoidTy) - // Our return value was unused, replace by null for now, uses will get - // removed later on Call->replaceAllUsesWith(Constant::getNullValue(Call->getType())); - else if (isa(RetTy)) { - // The original return value was a struct, update all uses (which are - // all extractvalue instructions). - for (Value::use_iterator I = Call->use_begin(), E = Call->use_end(); - I != E;) { - assert(isa(*I) && "Return value not only used by extractvalue?"); - ExtractValueInst *EV = cast(*I); - // Increment now, since we're about to throw away this use. - ++I; - assert(EV->hasIndices() && "Return value used by extractvalue without indices?"); - unsigned Idx = *EV->idx_begin(); - if (NewRetIdxs[Idx] != -1) { - if (RetTypes.size() > 1) { - // We're still returning a struct, create a new extractvalue - // instruction with the first index updated - std::vector NewIdxs(EV->idx_begin(), EV->idx_end()); - NewIdxs[0] = NewRetIdxs[Idx]; - Value *NEV = ExtractValueInst::Create(New, NewIdxs.begin(), NewIdxs.end(), "retval", EV); - EV->replaceAllUsesWith(NEV); - EV->eraseFromParent(); - } else { - // We are now only returning a simple value, remove the - // extractvalue - EV->replaceAllUsesWith(New); - EV->eraseFromParent(); - } - } else { - // Value unused, replace uses by null for now, they will get removed - // later on - EV->replaceAllUsesWith(Constant::getNullValue(EV->getType())); - EV->eraseFromParent(); - } - } - New->takeName(Call); - } else { - // The original function had a single return value + else { Call->replaceAllUsesWith(New); New->takeName(Call); } @@ -774,11 +632,13 @@ NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList()); // Loop over the argument list, transfering uses of the old arguments over to - // the new arguments, also transfering over the names as well. - i = 0; + // the new arguments, also transfering over the names as well. While we're at + // it, remove the dead arguments from the DeadArguments list. + // for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(), - I2 = NF->arg_begin(); I != E; ++I, ++i) - if (ArgAlive[i]) { + I2 = NF->arg_begin(); + I != E; ++I) + if (!DeadArguments.count(I)) { // If this is a live argument, move the name and users over to the new // version. I->replaceAllUsesWith(I2); @@ -786,8 +646,10 @@ ++I2; } else { // If this argument is dead, replace any uses of it with null constants - // (these are guaranteed to become unused later on) + // (these are guaranteed to only be operands to call instructions which + // will later be simplified). I->replaceAllUsesWith(Constant::getNullValue(I->getType())); + DeadArguments.erase(I); } // If we change the return value of the function we must rewrite any return @@ -795,45 +657,12 @@ if (F->getReturnType() != NF->getReturnType()) for (Function::iterator BB = NF->begin(), E = NF->end(); BB != E; ++BB) if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { - Value *RetVal; - - if (NFTy->getReturnType() == Type::VoidTy) { - RetVal = 0; - } else { - assert (isa(RetTy)); - // The original return value was a struct, insert - // extractvalue/insertvalue chains to extract only the values we need - // to return and insert them into our new result. - // This does generate messy code, but we'll let it to instcombine to - // clean that up - Value *OldRet = RI->getOperand(0); - // Start out building up our return value from undef - RetVal = llvm::UndefValue::get(NRetTy); - for (unsigned i = 0; i != RetCount; ++i) - if (NewRetIdxs[i] != -1) { - ExtractValueInst *EV = ExtractValueInst::Create(OldRet, i, "newret", RI); - if (RetTypes.size() > 1) { - // We're still returning a struct, so reinsert the value into - // our new return value at the new index - - RetVal = InsertValueInst::Create(RetVal, EV, NewRetIdxs[i], "oldret"); - } else { - // We are now only returning a simple value, so just return the - // extracted value - RetVal = EV; - } - } - } - // Replace the return instruction with one returning the new return - // value (possibly 0 if we became void). - ReturnInst::Create(RetVal, RI); + ReturnInst::Create(0, RI); BB->getInstList().erase(RI); } // Now that the old function is dead, delete it. F->eraseFromParent(); - - return true; } bool DAE::runOnModule(Module &M) { @@ -848,7 +677,7 @@ if (F.getFunctionType()->isVarArg()) Changed |= DeleteDeadVarargs(F); } - + // Second phase:loop through the module, determining which arguments are live. // We assume all arguments are dead unless proven otherwise (allowing us to // determine that dead arguments passed into recursive functions are dead). @@ -857,14 +686,85 @@ for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) SurveyFunction(*I); - // Now, remove all dead arguments and return values from each function in - // turn - for (Module::iterator I = M.begin(), E = M.end(); I != E; ) { - // Increment now, because the function will probably get removed (ie - // replaced by a new one) - Function *F = I++; - Changed |= RemoveDeadStuffFromFunction(F); + // Loop over the instructions to inspect, propagating liveness among arguments + // and return values which are MaybeLive. + while (!InstructionsToInspect.empty()) { + Instruction *I = InstructionsToInspect.back(); + InstructionsToInspect.pop_back(); + + if (ReturnInst *RI = dyn_cast(I)) { + // For return instructions, we just have to check to see if the return + // value for the current function is known now to be alive. If so, any + // arguments used by it are now alive, and any call instruction return + // value is alive as well. + if (LiveRetVal.count(RI->getParent()->getParent())) + MarkReturnInstArgumentLive(RI); + + } else { + CallSite CS = CallSite::get(I); + assert(CS.getInstruction() && "Unknown instruction for the I2I list!"); + + Function *Callee = CS.getCalledFunction(); + + // If we found a call or invoke instruction on this list, that means that + // an argument of the function is a call instruction. If the argument is + // live, then the return value of the called instruction is now live. + // + CallSite::arg_iterator AI = CS.arg_begin(); // ActualIterator + for (Function::arg_iterator FI = Callee->arg_begin(), + E = Callee->arg_end(); FI != E; ++AI, ++FI) { + // If this argument is another call... + CallSite ArgCS = CallSite::get(*AI); + if (ArgCS.getInstruction() && LiveArguments.count(FI)) + if (Function *Callee = ArgCS.getCalledFunction()) + MarkRetValLive(Callee); + } + } } - return Changed; + // Now we loop over all of the MaybeLive arguments, promoting them to be live + // arguments if one of the calls that uses the arguments to the calls they are + // passed into requires them to be live. Of course this could make other + // arguments live, so process callers recursively. + // + // Because elements can be removed from the MaybeLiveArguments set, copy it to + // a temporary vector. + // + std::vector TmpArgList(MaybeLiveArguments.begin(), + MaybeLiveArguments.end()); + for (unsigned i = 0, e = TmpArgList.size(); i != e; ++i) { + Argument *MLA = TmpArgList[i]; + if (MaybeLiveArguments.count(MLA) && + isMaybeLiveArgumentNowLive(MLA)) + MarkArgumentLive(MLA); + } + + // Recover memory early... + CallSites.clear(); + + // At this point, we know that all arguments in DeadArguments and + // MaybeLiveArguments are dead. If the two sets are empty, there is nothing + // to do. + if (MaybeLiveArguments.empty() && DeadArguments.empty() && + MaybeLiveRetVal.empty() && DeadRetVal.empty()) + return Changed; + + // Otherwise, compact into one set, and start eliminating the arguments from + // the functions. + DeadArguments.insert(MaybeLiveArguments.begin(), MaybeLiveArguments.end()); + MaybeLiveArguments.clear(); + DeadRetVal.insert(MaybeLiveRetVal.begin(), MaybeLiveRetVal.end()); + MaybeLiveRetVal.clear(); + + LiveArguments.clear(); + LiveRetVal.clear(); + + NumArgumentsEliminated += DeadArguments.size(); + NumRetValsEliminated += DeadRetVal.size(); + while (!DeadArguments.empty()) + RemoveDeadArgumentsFromFunction((*DeadArguments.begin())->getParent()); + + while (!DeadRetVal.empty()) + RemoveDeadArgumentsFromFunction(*DeadRetVal.begin()); + return true; } From clattner at apple.com Wed Jun 18 12:49:30 2008 From: clattner at apple.com (Chris Lattner) Date: Wed, 18 Jun 2008 10:49:30 -0700 Subject: [llvm-commits] Regression with -ipconstprop References: Message-ID: <4800F036-0318-4459-88EB-3F2DBAA9D58D@apple.com> ipconstprop is crashing when compiling 447.dealII. Matthijs, can you please investigate? $ opt bugpoint-reduced-simplified.bc -ipconstprop -------------- next part -------------- A non-text attachment was scrubbed... Name: bugpoint-reduced-simplified.bc Type: application/octet-stream Size: 6700 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080618/e66dcd6e/attachment.obj -------------- next part -------------- -Chris From evan.cheng at apple.com Wed Jun 18 12:54:24 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Wed, 18 Jun 2008 10:54:24 -0700 Subject: [llvm-commits] [llvm] r52454 - /llvm/trunk/lib/Target/X86/X86InstrInfo.td In-Reply-To: <59843.76.220.41.203.1213806033.squirrel@webmail.apple.com> References: <200806180813.m5I8D7qK023472@zion.cs.uiuc.edu> <59843.76.220.41.203.1213806033.squirrel@webmail.apple.com> Message-ID: On Jun 18, 2008, at 9:20 AM, Dan Gohman wrote: > On Wed, June 18, 2008 1:13 am, Evan Cheng wrote: >> Author: evancheng >> Date: Wed Jun 18 03:13:07 2008 >> New Revision: 52454 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=52454&view=rev >> Log: >> XOR32rr, etc. are not AsCheapAsMove, but MOV32ri, etc. are. > > MOV32ri is 5 bytes of encoding, while MOV32rr is 2 bytes. > Is MOV32ri really "as cheap"? Don't blame me for the name. :-) It's AsFastAsMove. > > > Also, please update the AsCheapAsMove usage in X86Instr64-bit.td > too. Will do. Evan > > > Thanks, > > Dan > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From clattner at apple.com Wed Jun 18 13:01:23 2008 From: clattner at apple.com (Chris Lattner) Date: Wed, 18 Jun 2008 11:01:23 -0700 Subject: [llvm-commits] [llvm] r52454 - /llvm/trunk/lib/Target/X86/X86InstrInfo.td In-Reply-To: References: <200806180813.m5I8D7qK023472@zion.cs.uiuc.edu> <59843.76.220.41.203.1213806033.squirrel@webmail.apple.com> Message-ID: <7B978918-F5CF-43AB-838A-0DA9E5A166E1@apple.com> On Jun 18, 2008, at 10:54 AM, Evan Cheng wrote: > > On Jun 18, 2008, at 9:20 AM, Dan Gohman wrote: > >> On Wed, June 18, 2008 1:13 am, Evan Cheng wrote: >>> Author: evancheng >>> Date: Wed Jun 18 03:13:07 2008 >>> New Revision: 52454 >>> >>> URL: http://llvm.org/viewvc/llvm-project?rev=52454&view=rev >>> Log: >>> XOR32rr, etc. are not AsCheapAsMove, but MOV32ri, etc. are. >> >> MOV32ri is 5 bytes of encoding, while MOV32rr is 2 bytes. >> Is MOV32ri really "as cheap"? > > Don't blame me for the name. :-) It's AsFastAsMove. Cheapness should eventually be predicated on "optimize for size" I guess. However, remember that we're often avoiding spill/restore code when we use this, so it will probably be smaller too. -Chris From sabre at nondot.org Wed Jun 18 13:11:55 2008 From: sabre at nondot.org (Chris Lattner) Date: Wed, 18 Jun 2008 18:11:55 -0000 Subject: [llvm-commits] [llvm] r52466 - /llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200806181811.m5IIBuUR011551@zion.cs.uiuc.edu> Author: lattner Date: Wed Jun 18 13:11:55 2008 New Revision: 52466 URL: http://llvm.org/viewvc/llvm-project?rev=52466&view=rev Log: Fix the regressions on sext-misc.ll my patch yesterday caused. Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=52466&r1=52465&r2=52466&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Wed Jun 18 13:11:55 2008 @@ -1343,6 +1343,7 @@ } } } + ComputeMaskedBits(V, DemandedMask, RHSKnownZero, RHSKnownOne, Depth); break; } From gohman at apple.com Wed Jun 18 13:42:14 2008 From: gohman at apple.com (Dan Gohman) Date: Wed, 18 Jun 2008 18:42:14 -0000 Subject: [llvm-commits] [llvm] r52467 - /llvm/trunk/docs/LangRef.html Message-ID: <200806181842.m5IIgEtR013077@zion.cs.uiuc.edu> Author: djg Date: Wed Jun 18 13:42:13 2008 New Revision: 52467 URL: http://llvm.org/viewvc/llvm-project?rev=52467&view=rev Log: Fix a missing comma spotted by Bram Geron. Modified: llvm/trunk/docs/LangRef.html Modified: llvm/trunk/docs/LangRef.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.html?rev=52467&r1=52466&r2=52467&view=diff ============================================================================== --- llvm/trunk/docs/LangRef.html (original) +++ llvm/trunk/docs/LangRef.html Wed Jun 18 13:42:13 2008 @@ -1045,7 +1045,7 @@ integer, floating point, pointer, - vector + vector, structure, array, label. From akyrtzi at gmail.com Wed Jun 18 14:27:38 2008 From: akyrtzi at gmail.com (Argiris Kirtzidis) Date: Wed, 18 Jun 2008 19:27:38 -0000 Subject: [llvm-commits] [llvm] r52468 - /llvm/trunk/lib/CodeGen/DwarfWriter.cpp Message-ID: <200806181927.m5IJRcWm014901@zion.cs.uiuc.edu> Author: akirtzidis Date: Wed Jun 18 14:27:37 2008 New Revision: 52468 URL: http://llvm.org/viewvc/llvm-project?rev=52468&view=rev Log: Fix the source line debug information for the Windows platform. According to DWARF-2 specification, the line information is provided through an offset in the .debug_line section. Replace the label reference that is used with a section offset. Modified: llvm/trunk/lib/CodeGen/DwarfWriter.cpp Modified: llvm/trunk/lib/CodeGen/DwarfWriter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/DwarfWriter.cpp?rev=52468&r1=52467&r2=52468&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/DwarfWriter.cpp (original) +++ llvm/trunk/lib/CodeGen/DwarfWriter.cpp Wed Jun 18 14:27:37 2008 @@ -296,6 +296,7 @@ isString, isLabel, isAsIsLabel, + isSectionOffset, isDelta, isEntry, isBlock @@ -505,6 +506,56 @@ }; //===----------------------------------------------------------------------===// +/// DIESectionOffset - A section offset DIE. +// +class DIESectionOffset : public DIEValue { +public: + const DWLabel Label; + const DWLabel Section; + bool IsEH : 1; + bool UseSet : 1; + + DIESectionOffset(const DWLabel &Lab, const DWLabel &Sec, + bool isEH = false, bool useSet = true) + : DIEValue(isSectionOffset), Label(Lab), Section(Sec), + IsEH(isEH), UseSet(useSet) {} + + // Implement isa/cast/dyncast. + static bool classof(const DIESectionOffset *) { return true; } + static bool classof(const DIEValue *D) { return D->Type == isSectionOffset; } + + /// EmitValue - Emit section offset. + /// + virtual void EmitValue(DwarfDebug &DD, unsigned Form); + + /// SizeOf - Determine size of section offset value in bytes. + /// + virtual unsigned SizeOf(const DwarfDebug &DD, unsigned Form) const; + + /// Profile - Used to gather unique data for the value folding set. + /// + static void Profile(FoldingSetNodeID &ID, const DWLabel &Label, + const DWLabel &Section) { + ID.AddInteger(isSectionOffset); + Label.Profile(ID); + Section.Profile(ID); + // IsEH and UseSet are specific to the Label/Section that we will emit + // the offset for; so Label/Section are enough for uniqueness. + } + virtual void Profile(FoldingSetNodeID &ID) { Profile(ID, Label, Section); } + +#ifndef NDEBUG + virtual void print(std::ostream &O) { + O << "Off: "; + Label.print(O); + O << "-"; + Section.print(O); + O << "-" << IsEH << "-" << UseSet; + } +#endif +}; + +//===----------------------------------------------------------------------===// /// DIEDelta - A simple label difference DIE. /// class DIEDelta : public DIEValue { @@ -1275,6 +1326,24 @@ Die->AddValue(Attribute, Form, Value); } + /// AddSectionOffset - Add a section offset label attribute data and value. + /// + void AddSectionOffset(DIE *Die, unsigned Attribute, unsigned Form, + const DWLabel &Label, const DWLabel &Section, + bool isEH = false, bool useSet = true) { + FoldingSetNodeID ID; + DIESectionOffset::Profile(ID, Label, Section); + void *Where; + DIEValue *Value = ValuesSet.FindNodeOrInsertPos(ID, Where); + if (!Value) { + Value = new DIESectionOffset(Label, Section, isEH, useSet); + ValuesSet.InsertNode(Value, Where); + Values.push_back(Value); + } + + Die->AddValue(Attribute, Form, Value); + } + /// AddDelta - Add a label delta attribute data and value. /// void AddDelta(DIE *Die, unsigned Attribute, unsigned Form, @@ -1714,11 +1783,8 @@ CompileUnit *NewCompileUnit(CompileUnitDesc *UnitDesc, unsigned ID) { // Construct debug information entry. DIE *Die = new DIE(DW_TAG_compile_unit); - if (TAI->isAbsoluteDebugSectionOffsets()) - AddLabel(Die, DW_AT_stmt_list, DW_FORM_data4, DWLabel("section_line", 0)); - else - AddDelta(Die, DW_AT_stmt_list, DW_FORM_data4, DWLabel("section_line", 0), - DWLabel("section_line", 0)); + AddSectionOffset(Die, DW_AT_stmt_list, DW_FORM_data4, + DWLabel("section_line", 0), DWLabel("section_line", 0), false); AddString(Die, DW_AT_producer, DW_FORM_string, UnitDesc->getProducer()); AddUInt (Die, DW_AT_language, DW_FORM_data1, UnitDesc->getLanguage()); AddString(Die, DW_AT_name, DW_FORM_string, UnitDesc->getFileName()); @@ -3617,6 +3683,23 @@ /// EmitValue - Emit delta value. /// +void DIESectionOffset::EmitValue(DwarfDebug &DD, unsigned Form) { + bool IsSmall = Form == DW_FORM_data4; + DD.EmitSectionOffset(Label.Tag, Section.Tag, + Label.Number, Section.Number, IsSmall, IsEH, UseSet); +} + +/// SizeOf - Determine size of delta value in bytes. +/// +unsigned DIESectionOffset::SizeOf(const DwarfDebug &DD, unsigned Form) const { + if (Form == DW_FORM_data4) return 4; + return DD.getTargetData()->getPointerSize(); +} + +//===----------------------------------------------------------------------===// + +/// EmitValue - Emit delta value. +/// void DIEDelta::EmitValue(DwarfDebug &DD, unsigned Form) { bool IsSmall = Form == DW_FORM_data4; DD.EmitDifference(LabelHi, LabelLo, IsSmall); From nicolas.geoffray at lip6.fr Wed Jun 18 16:11:58 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Wed, 18 Jun 2008 21:11:58 -0000 Subject: [llvm-commits] [vmkit] r52469 - /vmkit/trunk/autogen.sh Message-ID: <200806182111.m5ILBwfh018572@zion.cs.uiuc.edu> Author: geoffray Date: Wed Jun 18 16:11:58 2008 New Revision: 52469 URL: http://llvm.org/viewvc/llvm-project?rev=52469&view=rev Log: Use bash instead of sh. Suggested by bgeron! Modified: vmkit/trunk/autogen.sh Modified: vmkit/trunk/autogen.sh URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/autogen.sh?rev=52469&r1=52468&r2=52469&view=diff ============================================================================== --- vmkit/trunk/autogen.sh (original) +++ vmkit/trunk/autogen.sh Wed Jun 18 16:11:58 2008 @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # autogen processing function do_autogen() From isanbard at gmail.com Wed Jun 18 16:39:02 2008 From: isanbard at gmail.com (Bill Wendling) Date: Wed, 18 Jun 2008 21:39:02 -0000 Subject: [llvm-commits] [llvm] r52470 - in /llvm/trunk/tools/lto2: LTOCodeGenerator.cpp LTOModule.cpp LTOModule.h Message-ID: <200806182139.m5ILd2vB019318@zion.cs.uiuc.edu> Author: void Date: Wed Jun 18 16:39:02 2008 New Revision: 52470 URL: http://llvm.org/viewvc/llvm-project?rev=52470&view=rev Log: Refactor the way to get a string containing the features of the target. Modified: llvm/trunk/tools/lto2/LTOCodeGenerator.cpp llvm/trunk/tools/lto2/LTOModule.cpp llvm/trunk/tools/lto2/LTOModule.h Modified: llvm/trunk/tools/lto2/LTOCodeGenerator.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lto2/LTOCodeGenerator.cpp?rev=52470&r1=52469&r2=52470&view=diff ============================================================================== --- llvm/trunk/tools/lto2/LTOCodeGenerator.cpp (original) +++ llvm/trunk/tools/lto2/LTOCodeGenerator.cpp Wed Jun 18 16:39:02 2008 @@ -264,22 +264,9 @@ return true; // construct LTModule, hand over ownership of module and target - // - // FIXME: This is an inelegant way of specifying the features of a - // subtarget. It would be better if we could encode this information - // into the IR. See . - SubtargetFeatures Features; - std::string FeatureStr; - std::string TargetTriple = _linker.getModule()->getTargetTriple(); - - if (strncmp(TargetTriple.c_str(), "powerpc-apple-", 14) == 0) { - Features.AddFeature("altivec", true); - } else if (strncmp(TargetTriple.c_str(), "powerpc64-apple-", 16) == 0) { - Features.AddFeature("64bit", true); - Features.AddFeature("altivec", true); - } - - _target = march->CtorFn(*mergedModule, Features.getString()); + std::string FeatureStr = + getFeatureString(_linker.getModule()->getTargetTriple().c_str()); + _target = march->CtorFn(*mergedModule, FeatureStr.c_str()); } return false; } Modified: llvm/trunk/tools/lto2/LTOModule.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lto2/LTOModule.cpp?rev=52470&r1=52469&r2=52470&view=diff ============================================================================== --- llvm/trunk/tools/lto2/LTOModule.cpp (original) +++ llvm/trunk/tools/lto2/LTOModule.cpp Wed Jun 18 16:39:02 2008 @@ -116,6 +116,25 @@ return makeLTOModule(buffer.get(), errMsg); } +/// getFeatureString - Return a string listing the features associated with the +/// target triple. +/// +/// FIXME: This is an inelegant way of specifying the features of a +/// subtarget. It would be better if we could encode this information into the +/// IR. See . +std::string getFeatureString(const char *TargetTriple) { + SubtargetFeatures Features; + + if (strncmp(TargetTriple, "powerpc-apple-", 14) == 0) { + Features.AddFeature("altivec", true); + } else if (strncmp(TargetTriple, "powerpc64-apple-", 16) == 0) { + Features.AddFeature("64bit", true); + Features.AddFeature("altivec", true); + } + + return Features.getString(); +} + LTOModule* LTOModule::makeLTOModule(MemoryBuffer* buffer, std::string& errMsg) { // parse bitcode buffer @@ -130,22 +149,8 @@ return NULL; // construct LTModule, hand over ownership of module and target - // - // FIXME: This is an inelegant way of specifying the features of a - // subtarget. It would be better if we could encode this information into - // the IR. See . - SubtargetFeatures Features; - std::string FeatureStr; - const char *TargetTriple = m->getTargetTriple().c_str(); - - if (strncmp(TargetTriple, "powerpc-apple-", 14) == 0) { - Features.AddFeature("altivec", true); - } else if (strncmp(TargetTriple, "powerpc64-apple-", 16) == 0) { - Features.AddFeature("64bit", true); - Features.AddFeature("altivec", true); - } - - TargetMachine* target = march->CtorFn(*m, Features.getString()); + std::string FeatureStr = getFeatureString(m->getTargetTriple().c_str()); + TargetMachine* target = march->CtorFn(*m, FeatureStr); return new LTOModule(m.take(), target); } Modified: llvm/trunk/tools/lto2/LTOModule.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lto2/LTOModule.h?rev=52470&r1=52469&r2=52470&view=diff ============================================================================== --- llvm/trunk/tools/lto2/LTOModule.h (original) +++ llvm/trunk/tools/lto2/LTOModule.h Wed Jun 18 16:39:02 2008 @@ -99,5 +99,7 @@ StringSet _undefines; }; +extern std::string getFeatureString(const char *TargetTriple); + #endif // LTO_MODULE_H From resistor at mac.com Wed Jun 18 16:41:49 2008 From: resistor at mac.com (Owen Anderson) Date: Wed, 18 Jun 2008 21:41:49 -0000 Subject: [llvm-commits] [llvm] r52471 - in /llvm/trunk: lib/Transforms/Scalar/GVN.cpp test/Transforms/GVN/local-pre.ll Message-ID: <200806182141.m5ILfoeJ019404@zion.cs.uiuc.edu> Author: resistor Date: Wed Jun 18 16:41:49 2008 New Revision: 52471 URL: http://llvm.org/viewvc/llvm-project?rev=52471&view=rev Log: Add local PRE to GVN. This only operates in cases where it would not increase code size, namely when the instantiated expression would only need to be created in one predecessor. Added: llvm/trunk/test/Transforms/GVN/local-pre.ll Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=52471&r1=52470&r2=52471&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Wed Jun 18 16:41:49 2008 @@ -25,10 +25,8 @@ #include "llvm/Value.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DepthFirstIterator.h" -#include "llvm/ADT/ScopedHashTable.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/SparseBitVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/AliasAnalysis.h" @@ -40,6 +38,7 @@ STATISTIC(NumGVNInstr, "Number of instructions deleted"); STATISTIC(NumGVNLoad, "Number of loads deleted"); +STATISTIC(NumGVNPRE, "Number of instructions PRE'd"); //===----------------------------------------------------------------------===// // ValueTable Class @@ -414,6 +413,11 @@ // ValueTable External Functions //===----------------------------------------------------------------------===// +/// add - Insert a value into the table with a specified value number. +void ValueTable::add(Value* V, uint32_t num) { + valueNumbering.insert(std::make_pair(V, num)); +} + /// lookup_or_add - Returns the value number for the specified value, assigning /// it a new number if it did not have one before. uint32_t ValueTable::lookup_or_add(Value* V) { @@ -675,7 +679,7 @@ template<> struct DenseMapInfo { static inline uint32_t getEmptyKey() { return ~0; } static inline uint32_t getTombstoneKey() { return ~0 - 1; } - static unsigned getHashValue(const uint32_t& Val) { return Val; } + static unsigned getHashValue(const uint32_t& Val) { return Val * 37; } static bool isPod() { return true; } static bool isEqual(const uint32_t& LHS, const uint32_t& RHS) { return LHS == RHS; @@ -683,9 +687,6 @@ }; } -typedef ScopedHashTable ValueNumberMap; -typedef ScopedHashTableScope ValueNumberScope; - namespace { class VISIBILITY_HIDDEN GVN : public FunctionPass { @@ -696,9 +697,7 @@ private: ValueTable VN; - - DenseMap availableOut; - ValueNumberMap BaseMap; + DenseMap > localAvail; typedef DenseMap > PhiMapType; PhiMapType phiMap; @@ -728,10 +727,11 @@ Value *GetValueForBlock(BasicBlock *BB, LoadInst* orig, DenseMap &Phis, bool top_level = false); - void dump(DenseMap& d); + void dump(DenseMap& d); bool iterateOnFunction(Function &F); Value* CollapsePhi(PHINode* p); bool isSafeReplacement(PHINode* p, Instruction* inst); + bool performPRE(Function& F); }; char GVN::ID = 0; @@ -743,13 +743,11 @@ static RegisterPass X("gvn", "Global Value Numbering"); -void GVN::dump(DenseMap& d) { +void GVN::dump(DenseMap& d) { printf("{\n"); - for (DenseMap::iterator I = d.begin(), + for (DenseMap::iterator I = d.begin(), E = d.end(); I != E; ++I) { - if (I->second == MemoryDependenceAnalysis::None) - printf("None\n"); - else + printf("%d\n", I->first); I->second->dump(); } printf("}\n"); @@ -1010,15 +1008,25 @@ bool GVN::processInstruction(Instruction *I, DenseMap &lastSeenLoad, SmallVectorImpl &toErase) { - if (LoadInst* L = dyn_cast(I)) - return processLoad(L, lastSeenLoad, toErase); + if (LoadInst* L = dyn_cast(I)) { + bool changed = processLoad(L, lastSeenLoad, toErase); + + if (!changed) { + unsigned num = VN.lookup_or_add(L); + localAvail[I->getParent()].insert(std::make_pair(num, L)); + } + + return changed; + } + + unsigned num = VN.lookup_or_add(I); // Allocations are always uniquely numbered, so we can save time and memory // by fast failing them. - if (isa(I)) + if (isa(I)) { + localAvail[I->getParent()].insert(std::make_pair(num, I)); return false; - - unsigned num = VN.lookup_or_add(I); + } // Collapse PHI nodes if (PHINode* p = dyn_cast(I)) { @@ -1032,10 +1040,12 @@ p->replaceAllUsesWith(constVal); toErase.push_back(p); + } else { + localAvail[I->getParent()].insert(std::make_pair(num, I)); } // Perform value-number based elimination - } else if (BaseMap.begin(num) != BaseMap.end()) { - Value* repl = *BaseMap.begin(num); + } else if (localAvail[I->getParent()].count(num)) { + Value* repl = localAvail[I->getParent()][num]; // Remove it! MemoryDependenceAnalysis& MD = getAnalysis(); @@ -1046,7 +1056,7 @@ toErase.push_back(I); return true; } else if (!I->isTerminator()) { - BaseMap.insert(num, I); + localAvail[I->getParent()].insert(std::make_pair(num, I)); } return false; @@ -1074,12 +1084,15 @@ bool GVN::processBlock(DomTreeNode* DTN) { BasicBlock* BB = DTN->getBlock(); - ValueNumberScope NewScope(BaseMap); SmallVector toErase; DenseMap lastSeenLoad; bool changed_function = false; - + + if (DTN->getIDom()) + localAvail.insert(std::make_pair(BB, + localAvail[DTN->getIDom()->getBlock()])); + for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE;) { changed_function |= processInstruction(BI, lastSeenLoad, toErase); @@ -1108,21 +1121,146 @@ toErase.clear(); } - for (DomTreeNode::iterator I = DTN->begin(), E = DTN->end(); I != E; ++I) - changed_function |= processBlock(*I); - return changed_function; } +/// performPRE - Perform a purely local form of PRE that looks for diamond +/// control flow patterns and attempts to perform simple PRE at the join point. +bool GVN::performPRE(Function& F) { + bool changed = false; + for (df_iterator DI = df_begin(&F.getEntryBlock()), + DE = df_end(&F.getEntryBlock()); DI != DE; ++DI) { + BasicBlock* CurrentBlock = *DI; + + // Nothing to PRE in the entry block. + if (CurrentBlock == &F.getEntryBlock()) continue; + + for (BasicBlock::iterator BI = CurrentBlock->begin(), + BE = CurrentBlock->end(); BI != BE; ) { + if (isa(BI) || isa(BI) || + isa(BI) || isa(BI) || + isa(BI) || isa(BI)) { + BI++; + continue; + } + + uint32_t valno = VN.lookup(BI); + + // Look for the predecessors for PRE opportunities. We're + // only trying to solve the basic diamond case, where + // a value is computed in the successor and one predecessor, + // but not the other. We also explicitly disallow cases + // where the successor is its own predecessor, because they're + // more complicated to get right. + unsigned numWith = 0; + unsigned numWithout = 0; + BasicBlock* PREPred = 0; + for (pred_iterator PI = pred_begin(CurrentBlock), + PE = pred_end(CurrentBlock); PI != PE; ++PI) { + // We're not interested in PRE where the block is its + // own predecessor. + if (*PI == CurrentBlock) + numWithout = 2; + + if (!localAvail[*PI].count(valno)) { + PREPred = *PI; + numWithout++; + } else if (localAvail[*PI][valno] == BI) { + numWithout = 2; + } else { + numWith++; + } + } + + // Don't do PRE when it might increase code size, i.e. when + // we would need to insert instructions in more than one pred. + if (numWithout != 1 || numWith == 0) { + BI++; + continue; + } + + // Instantiate the expression the in predecessor that lacked it. + // Because we are going top-down through the block, all value numbers + // will be available in the predecessor by the time we need them. Any + // that weren't original present will have been instantiated earlier + // in this loop. + Instruction* PREInstr = BI->clone(); + bool success = true; + for (unsigned i = 0; i < BI->getNumOperands(); ++i) { + Value* op = BI->getOperand(i); + if (isa(op) || isa(op) || isa(op)) + PREInstr->setOperand(i, op); + else if (!localAvail[PREPred].count(VN.lookup(op))) { + success = false; + break; + } else + PREInstr->setOperand(i, localAvail[PREPred][VN.lookup(op)]); + } + + // Fail out if we encounter an operand that is not available in + // the PRE predecessor. This is typically because of loads which + // are not value numbered precisely. + if (!success) { + delete PREInstr; + BI++; + continue; + } + + PREInstr->insertBefore(PREPred->getTerminator()); + PREInstr->setName(BI->getName() + ".pre"); + VN.add(PREInstr, valno); + NumGVNPRE++; + + // Update the availability map to include the new instruction. + localAvail[PREPred].insert(std::make_pair(valno, PREInstr)); + + // Create a PHI to make the value available in this block. + PHINode* Phi = PHINode::Create(BI->getType(), + BI->getName() + ".pre-phi", + CurrentBlock->begin()); + for (pred_iterator PI = pred_begin(CurrentBlock), + PE = pred_end(CurrentBlock); PI != PE; ++PI) + Phi->addIncoming(localAvail[*PI][valno], *PI); + + VN.add(Phi, valno); + + // The newly created PHI completely replaces the old instruction, + // so we need to update the maps to reflect this. + for (DenseMap >::iterator + UI = localAvail.begin(), UE = localAvail.end(); UI != UE; ++UI) + for (DenseMap::iterator UUI = UI->second.begin(), + UUE = UI->second.end(); UUI != UUE; ++UUI) + if (UUI->second == BI) + UUI->second = Phi; + + BI->replaceAllUsesWith(Phi); + + Instruction* erase = BI; + BI++; + erase->eraseFromParent(); + + changed = true; + } + } + + return changed; +} + // GVN::iterateOnFunction - Executes one iteration of GVN bool GVN::iterateOnFunction(Function &F) { // Clean out global sets from any previous functions VN.clear(); - availableOut.clear(); + localAvail.clear(); phiMap.clear(); DominatorTree &DT = getAnalysis(); // Top-down walk of the dominator tree - return processBlock(DT.getRootNode()); + bool changed = false; + for (df_iterator DI = df_begin(DT.getRootNode()), + DE = df_end(DT.getRootNode()); DI != DE; ++DI) + changed |= processBlock(*DI); + + changed |= performPRE(F); + return changed; } Added: llvm/trunk/test/Transforms/GVN/local-pre.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GVN/local-pre.ll?rev=52471&view=auto ============================================================================== --- llvm/trunk/test/Transforms/GVN/local-pre.ll (added) +++ llvm/trunk/test/Transforms/GVN/local-pre.ll Wed Jun 18 16:41:49 2008 @@ -0,0 +1,18 @@ +; RUN: llvm-as < %s | opt -gvn | llvm-dis | grep {b.pre} + +define i32 @main(i32 %p) { +block1: + + br i1 true, label %block2, label %block3 + +block2: + %a = add i32 %p, 1 + br label %block4 + +block3: + br label %block4 + +block4: + %b = add i32 %p, 1 + ret i32 %b +} From resistor at mac.com Wed Jun 18 16:59:01 2008 From: resistor at mac.com (Owen Anderson) Date: Wed, 18 Jun 2008 21:59:01 -0000 Subject: [llvm-commits] [llvm] r52472 - /llvm/trunk/lib/Transforms/Scalar/GVN.cpp Message-ID: <200806182159.m5ILx1Wi019964@zion.cs.uiuc.edu> Author: resistor Date: Wed Jun 18 16:59:00 2008 New Revision: 52472 URL: http://llvm.org/viewvc/llvm-project?rev=52472&view=rev Log: Add support for extractvalue and insertvalue instructions in GVN. Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=52472&r1=52471&r2=52472&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Wed Jun 18 16:59:00 2008 @@ -59,7 +59,7 @@ SHUFFLE, SELECT, TRUNC, ZEXT, SEXT, FPTOUI, FPTOSI, UITOFP, SITOFP, FPTRUNC, FPEXT, PTRTOINT, INTTOPTR, BITCAST, GEP, CALL, CONSTANT, - EMPTY, TOMBSTONE }; + EXTRACTVALUE, INSERTVALUE, EMPTY, TOMBSTONE }; ExpressionOpcode opcode; const Type* type; @@ -150,6 +150,8 @@ Expression create_expression(GetElementPtrInst* G); Expression create_expression(CallInst* C); Expression create_expression(Constant* C); + Expression create_expression(InsertValueInst* I); + Expression create_expression(ExtractValueInst* I); public: ValueTable() : nextValueNumber(1) { } uint32_t lookup_or_add(Value* V); @@ -284,6 +286,40 @@ } } +Expression ValueTable::create_expression(InsertValueInst* I) { + Expression e; + + e.type = I->getType(); + e.firstVN = lookup_or_add(I->getOperand(0)); + e.secondVN = lookup_or_add(I->getOperand(1)); + e.thirdVN = 0; + e.function = 0; + e.opcode = Expression::INSERTVALUE; + + for (InsertValueInst::op_iterator OI = I->op_begin()+2, + OE = I->op_end(); OI != OE; ++OI) + e.varargs.push_back(lookup_or_add(I)); + + return e; +} + +Expression ValueTable::create_expression(ExtractValueInst* I) { + Expression e; + + e.type = I->getType(); + e.firstVN = lookup_or_add(I->getOperand(0)); + e.secondVN = lookup_or_add(I->getOperand(1)); + e.thirdVN = 0; + e.function = 0; + e.opcode = Expression::EXTRACTVALUE; + + for (InsertValueInst::op_iterator OI = I->op_begin()+2, + OE = I->op_end(); OI != OE; ++OI) + e.varargs.push_back(lookup_or_add(I)); + + return e; +} + Expression ValueTable::create_expression(CallInst* C) { Expression e; @@ -541,6 +577,32 @@ valueNumbering.insert(std::make_pair(V, nextValueNumber)); return nextValueNumber++; } + } else if (InsertValueInst* II = dyn_cast(V)) { + Expression e = create_expression(II); + + DenseMap::iterator EI = expressionNumbering.find(e); + if (EI != expressionNumbering.end()) { + valueNumbering.insert(std::make_pair(V, EI->second)); + return EI->second; + } else { + expressionNumbering.insert(std::make_pair(e, nextValueNumber)); + valueNumbering.insert(std::make_pair(V, nextValueNumber)); + + return nextValueNumber++; + } + } else if (ExtractValueInst* E = dyn_cast(V)) { + Expression e = create_expression(E); + + DenseMap::iterator EI = expressionNumbering.find(e); + if (EI != expressionNumbering.end()) { + valueNumbering.insert(std::make_pair(V, EI->second)); + return EI->second; + } else { + expressionNumbering.insert(std::make_pair(e, nextValueNumber)); + valueNumbering.insert(std::make_pair(V, nextValueNumber)); + + return nextValueNumber++; + } } else if (BinaryOperator* BO = dyn_cast(V)) { Expression e = create_expression(BO); From resistor at mac.com Wed Jun 18 17:37:32 2008 From: resistor at mac.com (Owen Anderson) Date: Wed, 18 Jun 2008 22:37:32 -0000 Subject: [llvm-commits] [llvm] r52473 - /llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll Message-ID: <200806182237.m5IMbWdg021153@zion.cs.uiuc.edu> Author: resistor Date: Wed Jun 18 17:37:31 2008 New Revision: 52473 URL: http://llvm.org/viewvc/llvm-project?rev=52473&view=rev Log: Remove this test until the corresponding patch is reapplied because it's causing make check to crash for some people. Removed: llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll Removed: llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll?rev=52472&view=auto ============================================================================== --- llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll (original) +++ llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll (removed) @@ -1,39 +0,0 @@ -; This test sees if return values (and arguments) are properly removed when they -; are unused. All unused values are typed i16, so we can easily check. We also -; run instcombine to fold insert/extractvalue chains and we run dce to clean up -; any remaining dead stuff. -; RUN: llvm-as < %s | opt -deadargelim -instcombine -dce | llvm-dis | not grep i16 - -define internal {i16, i32} @test(i16 %DEADARG) { - %A = insertvalue {i16,i32} undef, i16 1, 0 - %B = insertvalue {i16,i32} %A, i32 1001, 1 - ret {i16,i32} %B -} - -define internal {i32, i16} @test2() { - %DEAD = call i16 @test4() - %A = insertvalue {i32,i16} undef, i32 1, 0 - %B = insertvalue {i32,i16} %A, i16 %DEAD, 1 - ret {i32,i16} %B -} - -define internal i32 @test3(i16 %A) { - %ret = call {i16, i32} @test( i16 %A ) ; [#uses=0] - %DEAD = extractvalue {i16, i32} %ret, 0 - %LIVE = extractvalue {i16, i32} %ret, 1 - ret i32 %LIVE -} - -define internal i16 @test4() { - ret i16 0 -} - -define i32 @main() { - %ret = call {i32, i16} @test2() ; [#uses=1] - %LIVE = extractvalue {i32, i16} %ret, 0 - %DEAD = extractvalue {i32, i16} %ret, 1 - %Y = add i32 %LIVE, -123 ; [#uses=1] - %LIVE2 = call i32 @test3(i16 %DEAD) ; [#uses=1] - %Z = add i32 %LIVE2, %Y ; [#uses=1] - ret i32 %Z -} From isanbard at gmail.com Wed Jun 18 18:55:07 2008 From: isanbard at gmail.com (Bill Wendling) Date: Wed, 18 Jun 2008 23:55:07 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r52474 - in /llvm-gcc-4.2/trunk/gcc: llvm-backend.cpp llvm-debug.cpp llvm-debug.h Message-ID: <200806182355.m5INt8uD024189@zion.cs.uiuc.edu> Author: void Date: Wed Jun 18 18:55:07 2008 New Revision: 52474 URL: http://llvm.org/viewvc/llvm-project?rev=52474&view=rev Log: The module was being deleted before the debug info was finished with it. This happened when PCH files are involved. Have the TheDebugInfo object take possession of the TheModule object so that it won't get deleted accidentally. Modified: llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp llvm-gcc-4.2/trunk/gcc/llvm-debug.h Modified: llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp?rev=52474&r1=52473&r2=52474&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp Wed Jun 18 18:55:07 2008 @@ -203,6 +203,7 @@ RegisterRegAlloc::setDefault(createLocalRegisterAllocator); if (!optimize && debug_info_level > DINFO_LEVEL_NONE) + // TheDebugInfo is taking ownership of TheModule. TheDebugInfo = new DebugInfo(TheModule); } @@ -224,9 +225,10 @@ /// Read bytecode from PCH file. Initialize TheModule and setup /// LTypes vector. void llvm_pch_read(const unsigned char *Buffer, unsigned Size) { - std::string ModuleName = TheModule->getModuleIdentifier(); - if (TheModule) + + // Don't delete the module if the debug info isn't done with it yet. + if (!TheDebugInfo || TheDebugInfo->getModule() != TheModule) delete TheModule; clearTargetBuiltinCache(); Modified: llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp?rev=52474&r1=52473&r2=52474&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp Wed Jun 18 18:55:07 2008 @@ -225,6 +225,10 @@ SR.setModule(M); } +DebugInfo::~DebugInfo() { + delete M; +} + /// getValueFor - Return a llvm representation for a given debug information /// descriptor. Value *DebugInfo::getValueFor(DebugInfoDesc *DD) { Modified: llvm-gcc-4.2/trunk/gcc/llvm-debug.h URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-debug.h?rev=52474&r1=52473&r2=52474&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-debug.h (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-debug.h Wed Jun 18 18:55:07 2008 @@ -77,10 +77,12 @@ public: DebugInfo(Module *m); - + ~DebugInfo(); + // Accessors. void setLocationFile(const char *FullPath) { CurFullPath = FullPath; } void setLocationLine(int LineNo) { CurLineNo = LineNo; } + const Module *getModule() const { return M; } /// getValueFor - Return a llvm representation for a given debug information /// descriptor. From resistor at mac.com Wed Jun 18 19:10:49 2008 From: resistor at mac.com (Owen Anderson) Date: Thu, 19 Jun 2008 00:10:49 -0000 Subject: [llvm-commits] [llvm] r52475 - /llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Message-ID: <200806190010.m5J0AnH1024680@zion.cs.uiuc.edu> Author: resistor Date: Wed Jun 18 19:10:49 2008 New Revision: 52475 URL: http://llvm.org/viewvc/llvm-project?rev=52475&view=rev Log: Insert empty slots into the instruction numbering in live intervals, so that we can more easily add new instructions. Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp?rev=52475&r1=52474&r2=52475&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp (original) +++ llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Wed Jun 18 19:10:49 2008 @@ -78,6 +78,7 @@ void LiveIntervals::computeNumbering() { Index2MiMap OldI2MI = i2miMap_; + std::vector OldI2MBB = Idx2MBBMap; Idx2MBBMap.clear(); MBB2IdxMap.clear(); @@ -93,19 +94,22 @@ MBB != E; ++MBB) { unsigned StartIdx = MIIndex; + // Insert an empty slot at the beginning of each block. + MIIndex += InstrSlots::NUM; + i2miMap_.push_back(0); + for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E; ++I) { bool inserted = mi2iMap_.insert(std::make_pair(I, MIIndex)).second; assert(inserted && "multiple MachineInstr -> index mappings"); i2miMap_.push_back(I); MIIndex += InstrSlots::NUM; - } - - if (StartIdx == MIIndex) { - // Empty MBB + + // Insert an empty slot after every instruction. MIIndex += InstrSlots::NUM; i2miMap_.push_back(0); } + // Set the MBB2IdxMap entry for this MBB. MBB2IdxMap[MBB->getNumber()] = std::make_pair(StartIdx, MIIndex - 1); Idx2MBBMap.push_back(std::make_pair(StartIdx, MBB)); @@ -113,90 +117,82 @@ std::sort(Idx2MBBMap.begin(), Idx2MBBMap.end(), Idx2MBBCompare()); if (!OldI2MI.empty()) - for (iterator I = begin(), E = end(); I != E; ++I) - for (LiveInterval::iterator LI = I->second.begin(), LE = I->second.end(); - LI != LE; ++LI) { + for (iterator OI = begin(), OE = end(); OI != OE; ++OI) + for (LiveInterval::iterator LI = OI->second.begin(), + LE = OI->second.end(); LI != LE; ++LI) { // Remap the start index of the live range to the corresponding new // number, or our best guess at what it _should_ correspond to if the // original instruction has been erased. This is either the following // instruction or its predecessor. + unsigned index = LI->start / InstrSlots::NUM; unsigned offset = LI->start % InstrSlots::NUM; - if (OldI2MI[LI->start / InstrSlots::NUM]) - LI->start = mi2iMap_[OldI2MI[LI->start / InstrSlots::NUM]] + offset; - else { - unsigned i = 0; - MachineInstr* newInstr = 0; - do { - newInstr = OldI2MI[LI->start / InstrSlots::NUM + i]; - i++; - } while (!newInstr); + if (offset == InstrSlots::LOAD) { + std::vector::const_iterator I = + std::lower_bound(OldI2MBB.begin(), OldI2MBB.end(), index); + // Take the pair containing the index + std::vector::const_iterator J = + ((I != OldI2MBB.end() && I->first > index) || + (I == OldI2MBB.end() && OldI2MBB.size()>0)) ? (I-1): I; - if (mi2iMap_[newInstr] == - MBB2IdxMap[newInstr->getParent()->getNumber()].first) - LI->start = mi2iMap_[newInstr]; - else - LI->start = mi2iMap_[newInstr] - InstrSlots::NUM + offset; + LI->start = getMBBStartIdx(J->second); + } else { + LI->start = mi2iMap_[OldI2MI[index]] + offset; } // Remap the ending index in the same way that we remapped the start, // except for the final step where we always map to the immediately // following instruction. - if (LI->end / InstrSlots::NUM < OldI2MI.size()) { - offset = LI->end % InstrSlots::NUM; - if (OldI2MI[LI->end / InstrSlots::NUM]) - LI->end = mi2iMap_[OldI2MI[LI->end / InstrSlots::NUM]] + offset; - else { - unsigned i = 0; - MachineInstr* newInstr = 0; - do { - newInstr = OldI2MI[LI->end / InstrSlots::NUM + i]; - i++; - } while (!newInstr); - - LI->end = mi2iMap_[newInstr]; - } + index = LI->end / InstrSlots::NUM; + offset = LI->end % InstrSlots::NUM; + if (offset == InstrSlots::STORE) { + std::vector::const_iterator I = + std::lower_bound(OldI2MBB.begin(), OldI2MBB.end(), index); + // Take the pair containing the index + std::vector::const_iterator J = + ((I != OldI2MBB.end() && I->first > index) || + (I == OldI2MBB.end() && OldI2MBB.size()>0)) ? (I-1): I; + + LI->start = getMBBEndIdx(J->second); } else { - LI->end = i2miMap_.size() * InstrSlots::NUM; + LI->end = mi2iMap_[OldI2MI[index]] + offset; } // Remap the VNInfo def index, which works the same as the // start indices above. VNInfo* vni = LI->valno; + index = vni->def / InstrSlots::NUM; offset = vni->def % InstrSlots::NUM; - if (OldI2MI[vni->def / InstrSlots::NUM]) - vni->def = mi2iMap_[OldI2MI[vni->def / InstrSlots::NUM]] + offset; - else { - unsigned i = 0; - MachineInstr* newInstr = 0; - do { - newInstr = OldI2MI[vni->def / InstrSlots::NUM + i]; - i++; - } while (!newInstr); + if (offset == InstrSlots::LOAD) { + std::vector::const_iterator I = + std::lower_bound(OldI2MBB.begin(), OldI2MBB.end(), index); + // Take the pair containing the index + std::vector::const_iterator J = + ((I != OldI2MBB.end() && I->first > index) || + (I == OldI2MBB.end() && OldI2MBB.size()>0)) ? (I-1): I; - if (mi2iMap_[newInstr] == - MBB2IdxMap[newInstr->getParent()->getNumber()].first) - vni->def = mi2iMap_[newInstr]; - else - vni->def = mi2iMap_[newInstr] - InstrSlots::NUM + offset; + vni->def = getMBBStartIdx(J->second); + + } else { + vni->def = mi2iMap_[OldI2MI[index]] + offset; } // Remap the VNInfo kill indices, which works the same as // the end indices above. for (size_t i = 0; i < vni->kills.size(); ++i) { + index = vni->kills[i] / InstrSlots::NUM; offset = vni->kills[i] % InstrSlots::NUM; - if (OldI2MI[vni->kills[i] / InstrSlots::NUM]) - vni->kills[i] = mi2iMap_[OldI2MI[vni->kills[i] / InstrSlots::NUM]] + - offset; - else { - unsigned e = 0; - MachineInstr* newInstr = 0; - do { - newInstr = OldI2MI[vni->kills[i] / InstrSlots::NUM + e]; - e++; - } while (!newInstr); - - vni->kills[i] = mi2iMap_[newInstr]; + if (OldI2MI[vni->kills[i] / InstrSlots::NUM]) { + std::vector::const_iterator I = + std::lower_bound(OldI2MBB.begin(), OldI2MBB.end(), index); + // Take the pair containing the index + std::vector::const_iterator J = + ((I != OldI2MBB.end() && I->first > index) || + (I == OldI2MBB.end() && OldI2MBB.size()>0)) ? (I-1): I; + + vni->kills[i] = getMBBEndIdx(J->second); + } else { + vni->kills[i] = mi2iMap_[OldI2MI[index]] + offset; } } } @@ -354,9 +350,7 @@ // of the defining block, potentially live across some blocks, then is // live into some number of blocks, but gets killed. Start by adding a // range that goes from this definition to the end of the defining block. - LiveRange NewLR(defIndex, - getInstructionIndex(&mbb->back()) + InstrSlots::NUM, - ValNo); + LiveRange NewLR(defIndex, getMBBEndIdx(mbb), ValNo); DOUT << " +" << NewLR; interval.addRange(NewLR); @@ -476,7 +470,7 @@ CopyMI = mi; ValNo = interval.getNextValue(defIndex, CopyMI, VNInfoAllocator); - unsigned killIndex = getInstructionIndex(&mbb->back()) + InstrSlots::NUM; + unsigned killIndex = getMBBEndIdx(mbb) + 1; LiveRange LR(defIndex, killIndex, ValNo); interval.addRange(LR); interval.addKill(ValNo, killIndex); @@ -513,8 +507,10 @@ // If it is not dead on definition, it must be killed by a // subsequent instruction. Hence its interval is: // [defSlot(def), useSlot(kill)+1) + baseIndex += InstrSlots::NUM; while (++mi != MBB->end()) { - baseIndex += InstrSlots::NUM; + while (getInstructionFromIndex(baseIndex) == 0) + baseIndex += InstrSlots::NUM; if (mi->killsRegister(interval.reg, tri_)) { DOUT << " killed"; end = getUseIndex(baseIndex) + 1; @@ -528,6 +524,8 @@ end = getDefIndex(start) + 1; goto exit; } + + baseIndex += InstrSlots::NUM; } // The only case we should have a dead physreg here without a killing or @@ -599,6 +597,8 @@ } baseIndex += InstrSlots::NUM; + while (getInstructionFromIndex(baseIndex) == 0) + baseIndex += InstrSlots::NUM; ++mi; } @@ -630,6 +630,12 @@ << ((Value*)mf_->getFunction())->getName() << '\n'; // Track the index of the current machine instr. unsigned MIIndex = 0; + + // Skip over empty initial indices. + while (MIIndex / InstrSlots::NUM < i2miMap_.size() && + getInstructionFromIndex(MIIndex) == 0) + MIIndex += InstrSlots::NUM; + for (MachineFunction::iterator MBBI = mf_->begin(), E = mf_->end(); MBBI != E; ++MBBI) { MachineBasicBlock *MBB = MBBI; @@ -660,9 +666,12 @@ } MIIndex += InstrSlots::NUM; + + // Skip over empty indices. + while (MIIndex / InstrSlots::NUM < i2miMap_.size() && + getInstructionFromIndex(MIIndex) == 0) + MIIndex += InstrSlots::NUM; } - - if (MBB->begin() == miEnd) MIIndex += InstrSlots::NUM; // Empty MBB } } From isanbard at gmail.com Wed Jun 18 19:18:40 2008 From: isanbard at gmail.com (Bill Wendling) Date: Thu, 19 Jun 2008 00:18:40 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r52476 - in /llvm-gcc-4.2/trunk/gcc: llvm-backend.cpp llvm-debug.cpp llvm-debug.h Message-ID: <200806190018.m5J0IeqP024925@zion.cs.uiuc.edu> Author: void Date: Wed Jun 18 19:18:40 2008 New Revision: 52476 URL: http://llvm.org/viewvc/llvm-project?rev=52476&view=rev Log: Better fix for the memory smasher. Delete and recreate the TheDebugInfo object when deleting and recreating the TheModule object. Modified: llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp llvm-gcc-4.2/trunk/gcc/llvm-debug.h Modified: llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp?rev=52476&r1=52475&r2=52476&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp Wed Jun 18 19:18:40 2008 @@ -203,7 +203,6 @@ RegisterRegAlloc::setDefault(createLocalRegisterAllocator); if (!optimize && debug_info_level > DINFO_LEVEL_NONE) - // TheDebugInfo is taking ownership of TheModule. TheDebugInfo = new DebugInfo(TheModule); } @@ -227,9 +226,8 @@ void llvm_pch_read(const unsigned char *Buffer, unsigned Size) { std::string ModuleName = TheModule->getModuleIdentifier(); - // Don't delete the module if the debug info isn't done with it yet. - if (!TheDebugInfo || TheDebugInfo->getModule() != TheModule) - delete TheModule; + delete TheModule; + delete TheDebugInfo; clearTargetBuiltinCache(); @@ -238,6 +236,7 @@ std::string ErrMsg; TheModule = ParseBitcodeFile(MB, &ErrMsg); + TheDebugInfo = new DebugInfo(TheModule); delete MB; if (!TheModule) { Modified: llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp?rev=52476&r1=52475&r2=52476&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp Wed Jun 18 19:18:40 2008 @@ -225,10 +225,6 @@ SR.setModule(M); } -DebugInfo::~DebugInfo() { - delete M; -} - /// getValueFor - Return a llvm representation for a given debug information /// descriptor. Value *DebugInfo::getValueFor(DebugInfoDesc *DD) { Modified: llvm-gcc-4.2/trunk/gcc/llvm-debug.h URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-debug.h?rev=52476&r1=52475&r2=52476&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-debug.h (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-debug.h Wed Jun 18 19:18:40 2008 @@ -77,12 +77,10 @@ public: DebugInfo(Module *m); - ~DebugInfo(); // Accessors. void setLocationFile(const char *FullPath) { CurFullPath = FullPath; } void setLocationLine(int LineNo) { CurLineNo = LineNo; } - const Module *getModule() const { return M; } /// getValueFor - Return a llvm representation for a given debug information /// descriptor. From evan.cheng at apple.com Wed Jun 18 19:38:48 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Wed, 18 Jun 2008 17:38:48 -0700 Subject: [llvm-commits] [llvm] r52475 - /llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp In-Reply-To: <200806190010.m5J0AnH1024680@zion.cs.uiuc.edu> References: <200806190010.m5J0AnH1024680@zion.cs.uiuc.edu> Message-ID: <547EDD60-9405-4707-A40F-82AC435CB4D1@apple.com> On Jun 18, 2008, at 5:10 PM, Owen Anderson wrote: > Author: resistor > Date: Wed Jun 18 19:10:49 2008 > New Revision: 52475 > > URL: http://llvm.org/viewvc/llvm-project?rev=52475&view=rev > Log: > Insert empty slots into the instruction numbering in live intervals, > so that we can more easily > add new instructions. > > Modified: > llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp > > Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp?rev=52475&r1=52474&r2=52475&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp (original) > +++ llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Wed Jun 18 > 19:10:49 2008 > @@ -78,6 +78,7 @@ > > void LiveIntervals::computeNumbering() { > Index2MiMap OldI2MI = i2miMap_; > + std::vector OldI2MBB = Idx2MBBMap; > > Idx2MBBMap.clear(); > MBB2IdxMap.clear(); > @@ -93,19 +94,22 @@ > MBB != E; ++MBB) { > unsigned StartIdx = MIIndex; > > + // Insert an empty slot at the beginning of each block. > + MIIndex += InstrSlots::NUM; > + i2miMap_.push_back(0); > + > for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); > I != E; ++I) { > bool inserted = mi2iMap_.insert(std::make_pair(I, > MIIndex)).second; > assert(inserted && "multiple MachineInstr -> index mappings"); > i2miMap_.push_back(I); > MIIndex += InstrSlots::NUM; > - } > - > - if (StartIdx == MIIndex) { > - // Empty MBB > + > + // Insert an empty slot after every instruction. > MIIndex += InstrSlots::NUM; > i2miMap_.push_back(0); > } > + > // Set the MBB2IdxMap entry for this MBB. > MBB2IdxMap[MBB->getNumber()] = std::make_pair(StartIdx, MIIndex > - 1); > Idx2MBBMap.push_back(std::make_pair(StartIdx, MBB)); > @@ -113,90 +117,82 @@ > std::sort(Idx2MBBMap.begin(), Idx2MBBMap.end(), Idx2MBBCompare()); > > if (!OldI2MI.empty()) > - for (iterator I = begin(), E = end(); I != E; ++I) > - for (LiveInterval::iterator LI = I->second.begin(), LE = I- > >second.end(); > - LI != LE; ++LI) { > + for (iterator OI = begin(), OE = end(); OI != OE; ++OI) > + for (LiveInterval::iterator LI = OI->second.begin(), > + LE = OI->second.end(); LI != LE; ++LI) { > > // Remap the start index of the live range to the > corresponding new > // number, or our best guess at what it _should_ correspond > to if the > // original instruction has been erased. This is either the > following > // instruction or its predecessor. > + unsigned index = LI->start / InstrSlots::NUM; > unsigned offset = LI->start % InstrSlots::NUM; > - if (OldI2MI[LI->start / InstrSlots::NUM]) > - LI->start = mi2iMap_[OldI2MI[LI->start / > InstrSlots::NUM]] + offset; > - else { > - unsigned i = 0; > - MachineInstr* newInstr = 0; > - do { > - newInstr = OldI2MI[LI->start / InstrSlots::NUM + i]; > - i++; > - } while (!newInstr); > + if (offset == InstrSlots::LOAD) { > + std::vector::const_iterator I = > + std::lower_bound(OldI2MBB.begin(), > OldI2MBB.end(), index); > + // Take the pair containing the index > + std::vector::const_iterator J = > + ((I != OldI2MBB.end() && I->first > index) || > + (I == OldI2MBB.end() && OldI2MBB.size()>0)) ? > (I-1): I; I have hard time following this. The code was so easy to understand before! :-) Can you factor these 6-7 lines out and add a bit of comments? I see it's used at at least two places. Thanks. Evan > > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From gohman at apple.com Wed Jun 18 19:55:53 2008 From: gohman at apple.com (Dan Gohman) Date: Wed, 18 Jun 2008 17:55:53 -0700 Subject: [llvm-commits] [llvm] r52459 - in /llvm/trunk: lib/Transforms/IPO/DeadArgumentElimination.cpp test/Transforms/DeadArgElim/multdeadretval.ll In-Reply-To: <200806181113.m5IBD8Mc029979@zion.cs.uiuc.edu> References: <200806181113.m5IBD8Mc029979@zion.cs.uiuc.edu> Message-ID: On Jun 18, 2008, at 4:13 AM, Matthijs Kooijman wrote: > +/// MarkLive - Mark the given return value or argument as live. > Additionally, > +/// mark any values that are used by this value (according to Uses) > live as > +/// well. > +void DAE::MarkLive(RetOrArg RA) { > + if (!LiveValues.insert(RA).second) > + return; // We were already marked Live > > + if (RA.IsArg) > + DOUT << "DAE - Marking argument " << RA.Idx << " to function " > << RA.F->getNameStart() << " live\n"; > + else > + DOUT << "DAE - Marking return value " << RA.Idx << " of > function " << RA.F->getNameStart() << " live\n"; > > + std::pair Range = > Uses.equal_range(RA); > + UseMap::iterator E = Range.second; > + UseMap::iterator I = Range.first; > + for (; I != E; ++I) > + MarkLive(I->second); > + // Erase RA from the Uses map (from the lower bound to wherever > we ended up > + // after the loop). > + Uses.erase(Range.first, Range.second); > } I investigated this a little and found the subtle bug in this bit of code that's triggering the infinite looping behavior. The erase call is invalidating the Range.second iterator in a MarkLive call earlier in the recursion. I guess your original code which used lower_bound and just tested the key at each iteration was a better approach after all, and I shouldn't have suggested you change it :-}. Dan From evan.cheng at apple.com Wed Jun 18 20:16:17 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Thu, 19 Jun 2008 01:16:17 -0000 Subject: [llvm-commits] [llvm] r52477 - in /llvm/trunk: include/llvm/CodeGen/LiveIntervalAnalysis.h include/llvm/CodeGen/MachineRegisterInfo.h lib/CodeGen/LiveIntervalAnalysis.cpp Message-ID: <200806190116.m5J1GHD9026546@zion.cs.uiuc.edu> Author: evancheng Date: Wed Jun 18 20:16:17 2008 New Revision: 52477 URL: http://llvm.org/viewvc/llvm-project?rev=52477&view=rev Log: Minor spiller tweak to unfavor reload into load/store instructions. Modified: llvm/trunk/include/llvm/CodeGen/LiveIntervalAnalysis.h llvm/trunk/include/llvm/CodeGen/MachineRegisterInfo.h llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Modified: llvm/trunk/include/llvm/CodeGen/LiveIntervalAnalysis.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/LiveIntervalAnalysis.h?rev=52477&r1=52476&r2=52477&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/LiveIntervalAnalysis.h (original) +++ llvm/trunk/include/llvm/CodeGen/LiveIntervalAnalysis.h Wed Jun 18 20:16:17 2008 @@ -121,8 +121,12 @@ return getBaseIndex(index) + InstrSlots::STORE; } - static float getSpillWeight(bool isDef, bool isUse, unsigned loopDepth) { - return (isDef + isUse) * powf(10.0F, (float)loopDepth); + static float getSpillWeight(bool isDef, bool isUse, bool isMem, + unsigned loopDepth) { + float Weight = isDef; + if (isUse) + Weight += isMem ? 1.2f : 1.0f; + return Weight * powf(10.0F, (float)loopDepth); } typedef Reg2IntervalMap::iterator iterator; Modified: llvm/trunk/include/llvm/CodeGen/MachineRegisterInfo.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineRegisterInfo.h?rev=52477&r1=52476&r2=52477&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/MachineRegisterInfo.h (original) +++ llvm/trunk/include/llvm/CodeGen/MachineRegisterInfo.h Wed Jun 18 20:16:17 2008 @@ -135,6 +135,13 @@ assert(Reg < VRegInfo.size() && "Invalid vreg!"); return VRegInfo[Reg].first; } + + /// setRegClass - Set the register class of the specified virtual register. + void setRegClass(unsigned Reg, const TargetRegisterClass *RC) { + Reg -= TargetRegisterInfo::FirstVirtualRegister; + assert(Reg < VRegInfo.size() && "Invalid vreg!"); + VRegInfo[Reg].first = RC; + } /// createVirtualRegister - Create and return a new virtual register in the /// function with the specified register class. Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp?rev=52477&r1=52476&r2=52477&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp (original) +++ llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Wed Jun 18 20:16:17 2008 @@ -988,6 +988,7 @@ unsigned loopDepth = loopInfo->getLoopDepth(MBB); bool CanFold = false; RestartInstruction: + bool isMem = MI->getDesc().mayLoad() || MI->getDesc().mayStore(); for (unsigned i = 0; i != MI->getNumOperands(); ++i) { MachineOperand& mop = MI->getOperand(i); if (!mop.isRegister()) @@ -1055,7 +1056,7 @@ } // Update stack slot spill weight if we are splitting. - float Weight = getSpillWeight(HasDef, HasUse, loopDepth); + float Weight = getSpillWeight(HasDef, HasUse, isMem, loopDepth); if (!TrySplit) SSWeight += Weight; @@ -1248,6 +1249,7 @@ bool MIHasUse = rwi.HasUse; bool MIHasDef = rwi.HasDef; MachineInstr *MI = rwi.MI; + bool isMem = MI->getDesc().mayLoad() || MI->getDesc().mayStore(); // If MI def and/or use the same register multiple times, then there // are multiple entries. unsigned NumUses = MIHasUse; @@ -1395,7 +1397,7 @@ // Update spill weight. unsigned loopDepth = loopInfo->getLoopDepth(MBB); - nI.weight += getSpillWeight(HasDef, HasUse, loopDepth); + nI.weight += getSpillWeight(HasDef, HasUse, isMem, loopDepth); } if (NewVReg && TrySplit && AllCanFold) { @@ -1637,6 +1639,7 @@ LiveInterval &nI = getOrCreateInterval(VReg); bool isReMat = vrm.isReMaterialized(VReg); MachineInstr *MI = getInstructionFromIndex(index); + bool isMem = MI->getDesc().mayLoad() || MI->getDesc().mayStore(); bool CanFold = false; bool FoundUse = false; Ops.clear(); @@ -1689,7 +1692,7 @@ // Update spill slot weight. if (!isReMat) - SSWeight += getSpillWeight(true, false, loopDepth); + SSWeight += getSpillWeight(true, false, isMem, loopDepth); } Id = SpillMBBs.find_next(Id); } @@ -1709,6 +1712,7 @@ LiveInterval &nI = getOrCreateInterval(VReg); bool isReMat = vrm.isReMaterialized(VReg); MachineInstr *MI = getInstructionFromIndex(index); + bool isMem = MI->getDesc().mayLoad() || MI->getDesc().mayStore(); bool CanFold = false; Ops.clear(); if (restores[i].canFold) { @@ -1762,7 +1766,7 @@ // Update spill slot weight. if (!isReMat) - SSWeight += getSpillWeight(false, true, loopDepth); + SSWeight += getSpillWeight(false, true, isMem, loopDepth); } Id = RestoreMBBs.find_next(Id); } From evan.cheng at apple.com Wed Jun 18 20:21:02 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Thu, 19 Jun 2008 01:21:02 -0000 Subject: [llvm-commits] [llvm] r52478 - in /llvm/trunk/lib/Target: Mips/MipsAsmPrinter.cpp PIC16/PIC16AsmPrinter.cpp Message-ID: <200806190121.m5J1L2Dd026688@zion.cs.uiuc.edu> Author: evancheng Date: Wed Jun 18 20:21:02 2008 New Revision: 52478 URL: http://llvm.org/viewvc/llvm-project?rev=52478&view=rev Log: Unneeded include's. Modified: llvm/trunk/lib/Target/Mips/MipsAsmPrinter.cpp llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp Modified: llvm/trunk/lib/Target/Mips/MipsAsmPrinter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsAsmPrinter.cpp?rev=52478&r1=52477&r2=52478&view=diff ============================================================================== --- llvm/trunk/lib/Target/Mips/MipsAsmPrinter.cpp (original) +++ llvm/trunk/lib/Target/Mips/MipsAsmPrinter.cpp Wed Jun 18 20:21:02 2008 @@ -32,7 +32,6 @@ #include "llvm/Target/TargetOptions.h" #include "llvm/Support/Mangler.h" #include "llvm/ADT/Statistic.h" -#include "llvm/ADT/SetVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/CommandLine.h" Modified: llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp?rev=52478&r1=52477&r2=52478&view=diff ============================================================================== --- llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp (original) +++ llvm/trunk/lib/Target/PIC16/PIC16AsmPrinter.cpp Wed Jun 18 20:21:02 2008 @@ -20,7 +20,6 @@ #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Module.h" -#include "llvm/ADT/SetVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" #include "llvm/CodeGen/AsmPrinter.h" From evan.cheng at apple.com Wed Jun 18 20:21:27 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Thu, 19 Jun 2008 01:21:27 -0000 Subject: [llvm-commits] [llvm] r52479 - /llvm/trunk/lib/CodeGen/PHIElimination.cpp Message-ID: <200806190121.m5J1LRNo026720@zion.cs.uiuc.edu> Author: evancheng Date: Wed Jun 18 20:21:26 2008 New Revision: 52479 URL: http://llvm.org/viewvc/llvm-project?rev=52479&view=rev Log: Cosmetic changes. Modified: llvm/trunk/lib/CodeGen/PHIElimination.cpp Modified: llvm/trunk/lib/CodeGen/PHIElimination.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PHIElimination.cpp?rev=52479&r1=52478&r2=52479&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/PHIElimination.cpp (original) +++ llvm/trunk/lib/CodeGen/PHIElimination.cpp Wed Jun 18 20:21:26 2008 @@ -97,7 +97,7 @@ E = ImpDefs.end(); I != E; ++I) { MachineInstr *DefMI = *I; unsigned DefReg = DefMI->getOperand(0).getReg(); - if (MRI->use_begin(DefReg) == MRI->use_end()) + if (MRI->use_empty(DefReg)) DefMI->eraseFromParent(); } @@ -127,8 +127,10 @@ return true; } +/// isSourceDefinedByImplicitDef - Return true if all sources of the phi node +/// are implicit_def's. static bool isSourceDefinedByImplicitDef(const MachineInstr *MPhi, - const MachineRegisterInfo *MRI) { + const MachineRegisterInfo *MRI) { for (unsigned i = 1; i != MPhi->getNumOperands(); i += 2) { unsigned SrcReg = MPhi->getOperand(i).getReg(); const MachineInstr *DefMI = MRI->getVRegDef(SrcReg); @@ -229,7 +231,7 @@ // Find a safe location to insert the copy, this may be the first terminator // in the block (or end()). MachineBasicBlock::iterator InsertPos = opBlock.getFirstTerminator(); - + // Insert the copy. TII->copyRegToReg(opBlock, InsertPos, IncomingReg, SrcReg, RC, RC); From evan.cheng at apple.com Wed Jun 18 20:39:21 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Thu, 19 Jun 2008 01:39:21 -0000 Subject: [llvm-commits] [llvm] r52480 - in /llvm/trunk/lib/CodeGen: SimpleRegisterCoalescing.cpp SimpleRegisterCoalescing.h Message-ID: <200806190139.m5J1dL3e027217@zion.cs.uiuc.edu> Author: evancheng Date: Wed Jun 18 20:39:21 2008 New Revision: 52480 URL: http://llvm.org/viewvc/llvm-project?rev=52480&view=rev Log: Coalesce copy from one register class to a sub register class. e.g. X86::MOV16to16_. Modified: llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.h Modified: llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp?rev=52480&r1=52479&r2=52480&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp (original) +++ llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp Wed Jun 18 20:39:21 2008 @@ -35,6 +35,7 @@ using namespace llvm; STATISTIC(numJoins , "Number of interval joins performed"); +STATISTIC(numSubJoins , "Number of subclass joins performed"); STATISTIC(numCommutes , "Number of instruction commuting performed"); STATISTIC(numExtends , "Number of copies extended"); STATISTIC(numPeep , "Number of identity moves eliminated after coalescing"); @@ -48,8 +49,13 @@ static cl::opt NewHeuristic("new-coalescer-heuristic", - cl::desc("Use new coalescer heuristic"), - cl::init(false)); + cl::desc("Use new coalescer heuristic"), + cl::init(false), cl::Hidden); + +static cl::opt +CrossClassJoin("join-subclass-copies", + cl::desc("Coalesce copies to sub- register class"), + cl::init(false), cl::Hidden); static RegisterPass X("simple-register-coalescing", "Simple Register Coalescing"); @@ -818,6 +824,41 @@ return 0; } +/// isProfitableToCoalesceToSubRC - Given that register class of DstReg is +/// a subset of the register class of SrcReg, return true if it's profitable +/// to coalesce the two registers. +bool +SimpleRegisterCoalescing::isProfitableToCoalesceToSubRC(unsigned SrcReg, + unsigned DstReg, + MachineBasicBlock *MBB){ + if (!CrossClassJoin) + return false; + + // First let's make sure all uses are in the same MBB. + for (MachineRegisterInfo::reg_iterator RI = mri_->reg_begin(SrcReg), + RE = mri_->reg_end(); RI != RE; ++RI) { + MachineInstr &MI = *RI; + if (MI.getParent() != MBB) + return false; + } + for (MachineRegisterInfo::reg_iterator RI = mri_->reg_begin(DstReg), + RE = mri_->reg_end(); RI != RE; ++RI) { + MachineInstr &MI = *RI; + if (MI.getParent() != MBB) + return false; + } + + // Then make sure the intervals are *short*. + LiveInterval &SrcInt = li_->getInterval(SrcReg); + LiveInterval &DstInt = li_->getInterval(DstReg); + unsigned SrcSize = SrcInt.getSize() / InstrSlots::NUM; + unsigned DstSize = DstInt.getSize() / InstrSlots::NUM; + const TargetRegisterClass *RC = mri_->getRegClass(DstReg); + unsigned Threshold = allocatableRCRegs_[RC].count() * 2; + return (SrcSize + DstSize) <= Threshold; +} + + /// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, /// which are the src/dst of the copy instruction CopyMI. This returns true /// if the copy was successfully coalesced away. If it is not currently @@ -878,6 +919,9 @@ return false; // Not coalescable. } + // Should be non-null only when coalescing to a sub-register class. + const TargetRegisterClass *SubRC = NULL; + MachineBasicBlock *CopyMBB = CopyMI->getParent(); unsigned RealDstReg = 0; unsigned RealSrcReg = 0; if (isExtSubReg || isInsSubReg) { @@ -952,7 +996,8 @@ unsigned OldSubIdx = isExtSubReg ? CopyMI->getOperand(0).getSubReg() : CopyMI->getOperand(2).getSubReg(); if (OldSubIdx) { - if (OldSubIdx == SubIdx && !differingRegisterClasses(SrcReg, DstReg)) + if (OldSubIdx == SubIdx && + !differingRegisterClasses(SrcReg, DstReg, SubRC)) // r1024<2> = EXTRACT_SUBREG r1025, 2. Then r1024 has already been // coalesced to a larger register so the subreg indices cancel out. // Also check if the other larger register is of the same register @@ -986,7 +1031,7 @@ } } } - } else if (differingRegisterClasses(SrcReg, DstReg)) { + } else if (differingRegisterClasses(SrcReg, DstReg, SubRC)) { // FIXME: What if the resul of a EXTRACT_SUBREG is then coalesced // with another? If it's the resulting destination register, then // the subidx must be propagated to uses (but only those defined @@ -994,14 +1039,16 @@ // register, it should be safe because register is assumed to have // the register class of the super-register. - // If they are not of the same register class, we cannot join them. - DOUT << "\tSrc/Dest are different register classes.\n"; - // Allow the coalescer to try again in case either side gets coalesced to - // a physical register that's compatible with the other side. e.g. - // r1024 = MOV32to32_ r1025 - // but later r1024 is assigned EAX then r1025 may be coalesced with EAX. - Again = true; // May be possible to coalesce later. - return false; + if (!SubRC || !isProfitableToCoalesceToSubRC(SrcReg, DstReg, CopyMBB)) { + // If they are not of the same register class, we cannot join them. + DOUT << "\tSrc/Dest are different register classes.\n"; + // Allow the coalescer to try again in case either side gets coalesced to + // a physical register that's compatible with the other side. e.g. + // r1024 = MOV32to32_ r1025 + // but later r1024 is assigned EAX then r1025 may be coalesced with EAX. + Again = true; // May be possible to coalesce later. + return false; + } } LiveInterval &SrcInt = li_->getInterval(SrcReg); @@ -1132,6 +1179,13 @@ } } + // Coalescing to a virtual register that is of a sub-register class of the + // other. Make sure the resulting register is set to the right register class. + if (SubRC) { + mri_->setRegClass(DstReg, SubRC); + ++numSubJoins; + } + if (NewHeuristic) { // Add all copies that define val# in the source interval into the queue. for (LiveInterval::const_vni_iterator i = ResSrcInt->vni_begin(), @@ -1144,7 +1198,7 @@ if (CopyMI && JoinedCopies.count(CopyMI) == 0 && tii_->isMoveInstr(*CopyMI, NewSrcReg, NewDstReg)) { - unsigned LoopDepth = loopInfo->getLoopDepth(CopyMI->getParent()); + unsigned LoopDepth = loopInfo->getLoopDepth(CopyMBB); JoinQueue->push(CopyRec(CopyMI, LoopDepth, isBackEdgeCopy(CopyMI, DstReg))); } @@ -1875,9 +1929,13 @@ } /// Return true if the two specified registers belong to different register -/// classes. The registers may be either phys or virt regs. -bool SimpleRegisterCoalescing::differingRegisterClasses(unsigned RegA, - unsigned RegB) const { +/// classes. The registers may be either phys or virt regs. In the +/// case where both registers are virtual registers, it would also returns +/// true by reference the RegB register class in SubRC if it is a subset of +/// RegA's register class. +bool +SimpleRegisterCoalescing::differingRegisterClasses(unsigned RegA, unsigned RegB, + const TargetRegisterClass *&SubRC) const { // Get the register classes for the first reg. if (TargetRegisterInfo::isPhysicalRegister(RegA)) { @@ -1887,11 +1945,15 @@ } // Compare against the regclass for the second reg. - const TargetRegisterClass *RegClass = mri_->getRegClass(RegA); - if (TargetRegisterInfo::isVirtualRegister(RegB)) - return RegClass != mri_->getRegClass(RegB); - else - return !RegClass->contains(RegB); + const TargetRegisterClass *RegClassA = mri_->getRegClass(RegA); + if (TargetRegisterInfo::isVirtualRegister(RegB)) { + const TargetRegisterClass *RegClassB = mri_->getRegClass(RegB); + if (RegClassA == RegClassB) + return false; + SubRC = (RegClassA->hasSubClass(RegClassB)) ? RegClassB : NULL; + return true; + } + return !RegClassA->contains(RegB); } /// lastRegisterUse - Returns the last use of the specific register between @@ -2083,6 +2145,7 @@ mii = mbbi->erase(mii); ++numPeep; } else if (!isMove || !TurnCopyIntoImpDef(mii, mbb, DstReg, SrcReg)) { + bool isMem = mii->getDesc().mayLoad() || mii->getDesc().mayStore(); SmallSet UniqueUses; for (unsigned i = 0, e = mii->getNumOperands(); i != e; ++i) { const MachineOperand &mop = mii->getOperand(i); @@ -2095,7 +2158,7 @@ continue; LiveInterval &RegInt = li_->getInterval(reg); RegInt.weight += - li_->getSpillWeight(mop.isDef(), mop.isUse(), loopDepth); + li_->getSpillWeight(mop.isDef(), mop.isUse(), isMem, loopDepth); UniqueUses.insert(reg); } } Modified: llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.h?rev=52480&r1=52479&r2=52480&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.h (original) +++ llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.h Wed Jun 18 20:39:21 2008 @@ -165,9 +165,13 @@ /// joins them and returns true. bool SimpleJoin(LiveInterval &LHS, LiveInterval &RHS); - /// Return true if the two specified registers belong to different - /// register classes. The registers may be either phys or virt regs. - bool differingRegisterClasses(unsigned RegA, unsigned RegB) const; + /// Return true if the two specified registers belong to different register + /// classes. The registers may be either phys or virt regs. In the + /// case where both registers are virtual registers, it would also returns + /// true by reference the RegB register class in SubRC if it is a subset of + /// RegA's register class. + bool differingRegisterClasses(unsigned RegA, unsigned RegB, + const TargetRegisterClass *&SubRC) const; /// AdjustCopiesBackFrom - We found a non-trivially-coalescable copy. If @@ -205,6 +209,12 @@ /// identity copies so they will be removed. void RemoveCopiesFromValNo(LiveInterval &li, VNInfo *VNI); + /// isProfitableToCoalesceToSubRC - Given that register class of DstReg is + /// a subset of the register class of SrcReg, return true if it's profitable + /// to coalesce the two registers. + bool isProfitableToCoalesceToSubRC(unsigned SrcReg, unsigned DstReg, + MachineBasicBlock *MBB); + /// RangeIsDefinedByCopyFromReg - Return true if the specified live range of /// the specified live interval is defined by a copy from the specified /// register. From gohman at apple.com Wed Jun 18 20:39:46 2008 From: gohman at apple.com (Dan Gohman) Date: Wed, 18 Jun 2008 18:39:46 -0700 Subject: [llvm-commits] Dead argument elimination rewrite In-Reply-To: <20080617084400.GC16202@katherina.student.utwente.nl> References: <20080616153738.GN2636@katherina.student.utwente.nl> <20080617084400.GC16202@katherina.student.utwente.nl> Message-ID: <01FEB911-9233-424C-9242-091FC0E135DC@apple.com> On Jun 17, 2008, at 1:44 AM, Matthijs Kooijman wrote: > Hi Dan, > >> I don't think it's a high priority, but a "flatten return values" >> pass >> would be nice to have. > I have one lying around that is general enough IIRC, I'll only have > to pull it > out of our local namespace into llvm :-) Cool, thanks! > > >> >> UseMap is a std::multimap that maps every argument and return value >> to every argument or return value that it "uses". That caught my >> eye as a potential scalability suspect. Have you done any testing >> on large inputs? > I've done some testing on the basictest.ll testcase, copied about a > hundred > times (in the same file). Execution times are very similar to the > old version > (around 43ms according to -time-passes). I've also did the same > thing to a new > testcase that has a lot of unused return values (parts of struct > returns). > Here, the new code needs over twice as much time, but that's mainly > due to it > removing stuff that the old code didn't. > > I also tried using a hash_multimap instead of a normal multimap, but > that > didn't seem to make much of a difference. Perhaps on even larger > inputs, but > I'll leave it at multimap for now since the hash version is non- > standard. Ok. Would you mind taking a look at timings on MultiSource/Applications/kimwitu++ also? > > >> The InspectedFunctions member variable looks redundant. Can it be >> removed? > I added it, to prevent infinite looping. When removing stuff from a > function, > a new function is created with the new function type. This variable > helps to > prevent the new function from being stripped as well. > > Alternatively, I could make a copy of the function list and iterate > over that, > which should have the same effect. When DAE creates a new function, it inserts the function into the list in the position of the old function, so as far as I can tell DAE shouldn't ever end up calling RemoveDeadStuffFromFunction on one of the new functions. Dan From evan.cheng at apple.com Wed Jun 18 20:45:02 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Wed, 18 Jun 2008 18:45:02 -0700 Subject: [llvm-commits] [llvm] r52475 - /llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp In-Reply-To: <200806190010.m5J0AnH1024680@zion.cs.uiuc.edu> References: <200806190010.m5J0AnH1024680@zion.cs.uiuc.edu> Message-ID: Hi Owen, This is breaking a bunch of dejagnu tests. I'll back it out for now. Please fix. Evan On Jun 18, 2008, at 5:10 PM, Owen Anderson wrote: > Author: resistor > Date: Wed Jun 18 19:10:49 2008 > New Revision: 52475 > > URL: http://llvm.org/viewvc/llvm-project?rev=52475&view=rev > Log: > Insert empty slots into the instruction numbering in live intervals, > so that we can more easily > add new instructions. > > Modified: > llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp > > Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp?rev=52475&r1=52474&r2=52475&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp (original) > +++ llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Wed Jun 18 > 19:10:49 2008 > @@ -78,6 +78,7 @@ > > void LiveIntervals::computeNumbering() { > Index2MiMap OldI2MI = i2miMap_; > + std::vector OldI2MBB = Idx2MBBMap; > > Idx2MBBMap.clear(); > MBB2IdxMap.clear(); > @@ -93,19 +94,22 @@ > MBB != E; ++MBB) { > unsigned StartIdx = MIIndex; > > + // Insert an empty slot at the beginning of each block. > + MIIndex += InstrSlots::NUM; > + i2miMap_.push_back(0); > + > for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); > I != E; ++I) { > bool inserted = mi2iMap_.insert(std::make_pair(I, > MIIndex)).second; > assert(inserted && "multiple MachineInstr -> index mappings"); > i2miMap_.push_back(I); > MIIndex += InstrSlots::NUM; > - } > - > - if (StartIdx == MIIndex) { > - // Empty MBB > + > + // Insert an empty slot after every instruction. > MIIndex += InstrSlots::NUM; > i2miMap_.push_back(0); > } > + > // Set the MBB2IdxMap entry for this MBB. > MBB2IdxMap[MBB->getNumber()] = std::make_pair(StartIdx, MIIndex > - 1); > Idx2MBBMap.push_back(std::make_pair(StartIdx, MBB)); > @@ -113,90 +117,82 @@ > std::sort(Idx2MBBMap.begin(), Idx2MBBMap.end(), Idx2MBBCompare()); > > if (!OldI2MI.empty()) > - for (iterator I = begin(), E = end(); I != E; ++I) > - for (LiveInterval::iterator LI = I->second.begin(), LE = I- > >second.end(); > - LI != LE; ++LI) { > + for (iterator OI = begin(), OE = end(); OI != OE; ++OI) > + for (LiveInterval::iterator LI = OI->second.begin(), > + LE = OI->second.end(); LI != LE; ++LI) { > > // Remap the start index of the live range to the > corresponding new > // number, or our best guess at what it _should_ correspond > to if the > // original instruction has been erased. This is either the > following > // instruction or its predecessor. > + unsigned index = LI->start / InstrSlots::NUM; > unsigned offset = LI->start % InstrSlots::NUM; > - if (OldI2MI[LI->start / InstrSlots::NUM]) > - LI->start = mi2iMap_[OldI2MI[LI->start / > InstrSlots::NUM]] + offset; > - else { > - unsigned i = 0; > - MachineInstr* newInstr = 0; > - do { > - newInstr = OldI2MI[LI->start / InstrSlots::NUM + i]; > - i++; > - } while (!newInstr); > + if (offset == InstrSlots::LOAD) { > + std::vector::const_iterator I = > + std::lower_bound(OldI2MBB.begin(), > OldI2MBB.end(), index); > + // Take the pair containing the index > + std::vector::const_iterator J = > + ((I != OldI2MBB.end() && I->first > index) || > + (I == OldI2MBB.end() && OldI2MBB.size()>0)) ? > (I-1): I; > > - if (mi2iMap_[newInstr] == > - MBB2IdxMap[newInstr->getParent()->getNumber()].first) > - LI->start = mi2iMap_[newInstr]; > - else > - LI->start = mi2iMap_[newInstr] - InstrSlots::NUM + > offset; > + LI->start = getMBBStartIdx(J->second); > + } else { > + LI->start = mi2iMap_[OldI2MI[index]] + offset; > } > > // Remap the ending index in the same way that we remapped > the start, > // except for the final step where we always map to the > immediately > // following instruction. > - if (LI->end / InstrSlots::NUM < OldI2MI.size()) { > - offset = LI->end % InstrSlots::NUM; > - if (OldI2MI[LI->end / InstrSlots::NUM]) > - LI->end = mi2iMap_[OldI2MI[LI->end / InstrSlots::NUM]] > + offset; > - else { > - unsigned i = 0; > - MachineInstr* newInstr = 0; > - do { > - newInstr = OldI2MI[LI->end / InstrSlots::NUM + i]; > - i++; > - } while (!newInstr); > - > - LI->end = mi2iMap_[newInstr]; > - } > + index = LI->end / InstrSlots::NUM; > + offset = LI->end % InstrSlots::NUM; > + if (offset == InstrSlots::STORE) { > + std::vector::const_iterator I = > + std::lower_bound(OldI2MBB.begin(), > OldI2MBB.end(), index); > + // Take the pair containing the index > + std::vector::const_iterator J = > + ((I != OldI2MBB.end() && I->first > index) || > + (I == OldI2MBB.end() && OldI2MBB.size()>0)) ? > (I-1): I; > + > + LI->start = getMBBEndIdx(J->second); > } else { > - LI->end = i2miMap_.size() * InstrSlots::NUM; > + LI->end = mi2iMap_[OldI2MI[index]] + offset; > } > > // Remap the VNInfo def index, which works the same as the > // start indices above. > VNInfo* vni = LI->valno; > + index = vni->def / InstrSlots::NUM; > offset = vni->def % InstrSlots::NUM; > - if (OldI2MI[vni->def / InstrSlots::NUM]) > - vni->def = mi2iMap_[OldI2MI[vni->def / InstrSlots::NUM]] > + offset; > - else { > - unsigned i = 0; > - MachineInstr* newInstr = 0; > - do { > - newInstr = OldI2MI[vni->def / InstrSlots::NUM + i]; > - i++; > - } while (!newInstr); > + if (offset == InstrSlots::LOAD) { > + std::vector::const_iterator I = > + std::lower_bound(OldI2MBB.begin(), > OldI2MBB.end(), index); > + // Take the pair containing the index > + std::vector::const_iterator J = > + ((I != OldI2MBB.end() && I->first > index) || > + (I == OldI2MBB.end() && OldI2MBB.size()>0)) ? > (I-1): I; > > - if (mi2iMap_[newInstr] == > - MBB2IdxMap[newInstr->getParent()->getNumber()].first) > - vni->def = mi2iMap_[newInstr]; > - else > - vni->def = mi2iMap_[newInstr] - InstrSlots::NUM + offset; > + vni->def = getMBBStartIdx(J->second); > + > + } else { > + vni->def = mi2iMap_[OldI2MI[index]] + offset; > } > > // Remap the VNInfo kill indices, which works the same as > // the end indices above. > for (size_t i = 0; i < vni->kills.size(); ++i) { > + index = vni->kills[i] / InstrSlots::NUM; > offset = vni->kills[i] % InstrSlots::NUM; > - if (OldI2MI[vni->kills[i] / InstrSlots::NUM]) > - vni->kills[i] = mi2iMap_[OldI2MI[vni->kills[i] / > InstrSlots::NUM]] + > - offset; > - else { > - unsigned e = 0; > - MachineInstr* newInstr = 0; > - do { > - newInstr = OldI2MI[vni->kills[i] / InstrSlots::NUM + > e]; > - e++; > - } while (!newInstr); > - > - vni->kills[i] = mi2iMap_[newInstr]; > + if (OldI2MI[vni->kills[i] / InstrSlots::NUM]) { > + std::vector::const_iterator I = > + std::lower_bound(OldI2MBB.begin(), > OldI2MBB.end(), index); > + // Take the pair containing the index > + std::vector::const_iterator J = > + ((I != OldI2MBB.end() && I->first > index) || > + (I == OldI2MBB.end() && OldI2MBB.size()>0)) ? > (I-1): I; > + > + vni->kills[i] = getMBBEndIdx(J->second); > + } else { > + vni->kills[i] = mi2iMap_[OldI2MI[index]] + offset; > } > } > } > @@ -354,9 +350,7 @@ > // of the defining block, potentially live across some blocks, > then is > // live into some number of blocks, but gets killed. Start by > adding a > // range that goes from this definition to the end of the > defining block. > - LiveRange NewLR(defIndex, > - getInstructionIndex(&mbb->back()) + > InstrSlots::NUM, > - ValNo); > + LiveRange NewLR(defIndex, getMBBEndIdx(mbb), ValNo); > DOUT << " +" << NewLR; > interval.addRange(NewLR); > > @@ -476,7 +470,7 @@ > CopyMI = mi; > ValNo = interval.getNextValue(defIndex, CopyMI, > VNInfoAllocator); > > - unsigned killIndex = getInstructionIndex(&mbb->back()) + > InstrSlots::NUM; > + unsigned killIndex = getMBBEndIdx(mbb) + 1; > LiveRange LR(defIndex, killIndex, ValNo); > interval.addRange(LR); > interval.addKill(ValNo, killIndex); > @@ -513,8 +507,10 @@ > // If it is not dead on definition, it must be killed by a > // subsequent instruction. Hence its interval is: > // [defSlot(def), useSlot(kill)+1) > + baseIndex += InstrSlots::NUM; > while (++mi != MBB->end()) { > - baseIndex += InstrSlots::NUM; > + while (getInstructionFromIndex(baseIndex) == 0) > + baseIndex += InstrSlots::NUM; > if (mi->killsRegister(interval.reg, tri_)) { > DOUT << " killed"; > end = getUseIndex(baseIndex) + 1; > @@ -528,6 +524,8 @@ > end = getDefIndex(start) + 1; > goto exit; > } > + > + baseIndex += InstrSlots::NUM; > } > > // The only case we should have a dead physreg here without a > killing or > @@ -599,6 +597,8 @@ > } > > baseIndex += InstrSlots::NUM; > + while (getInstructionFromIndex(baseIndex) == 0) > + baseIndex += InstrSlots::NUM; > ++mi; > } > > @@ -630,6 +630,12 @@ > << ((Value*)mf_->getFunction())->getName() << '\n'; > // Track the index of the current machine instr. > unsigned MIIndex = 0; > + > + // Skip over empty initial indices. > + while (MIIndex / InstrSlots::NUM < i2miMap_.size() && > + getInstructionFromIndex(MIIndex) == 0) > + MIIndex += InstrSlots::NUM; > + > for (MachineFunction::iterator MBBI = mf_->begin(), E = mf_->end(); > MBBI != E; ++MBBI) { > MachineBasicBlock *MBB = MBBI; > @@ -660,9 +666,12 @@ > } > > MIIndex += InstrSlots::NUM; > + > + // Skip over empty indices. > + while (MIIndex / InstrSlots::NUM < i2miMap_.size() && > + getInstructionFromIndex(MIIndex) == 0) > + MIIndex += InstrSlots::NUM; > } > - > - if (MBB->begin() == miEnd) MIIndex += InstrSlots::NUM; // Empty > MBB > } > } > > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From evan.cheng at apple.com Wed Jun 18 20:46:43 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Thu, 19 Jun 2008 01:46:43 -0000 Subject: [llvm-commits] [llvm] r52481 - /llvm/trunk/test/CodeGen/X86/2006-05-11-InstrSched.ll Message-ID: <200806190146.m5J1kide027430@zion.cs.uiuc.edu> Author: evancheng Date: Wed Jun 18 20:46:43 2008 New Revision: 52481 URL: http://llvm.org/viewvc/llvm-project?rev=52481&view=rev Log: This got better. Modified: llvm/trunk/test/CodeGen/X86/2006-05-11-InstrSched.ll Modified: llvm/trunk/test/CodeGen/X86/2006-05-11-InstrSched.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2006-05-11-InstrSched.ll?rev=52481&r1=52480&r2=52481&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/2006-05-11-InstrSched.ll (original) +++ llvm/trunk/test/CodeGen/X86/2006-05-11-InstrSched.ll Wed Jun 18 20:46:43 2008 @@ -1,5 +1,5 @@ ; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 -stats -realign-stack=0 |&\ -; RUN: grep {asm-printer} | grep 32 +; RUN: grep {asm-printer} | grep 31 target datalayout = "e-p:32:32" define void @foo(i32* %mc, i32* %bp, i32* %ms, i32* %xmb, i32* %mpp, i32* %tpmm, i32* %ip, i32* %tpim, i32* %dpp, i32* %tpdm, i32* %bpi, i32 %M) nounwind { From evan.cheng at apple.com Wed Jun 18 20:50:14 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Thu, 19 Jun 2008 01:50:14 -0000 Subject: [llvm-commits] [llvm] r52482 - /llvm/trunk/test/CodeGen/X86/2008-03-18-CoalescerBug.ll Message-ID: <200806190150.m5J1oEZU027565@zion.cs.uiuc.edu> Author: evancheng Date: Wed Jun 18 20:50:13 2008 New Revision: 52482 URL: http://llvm.org/viewvc/llvm-project?rev=52482&view=rev Log: This also got better (55 - 51 instructions). But doing one more re-materialization. Modified: llvm/trunk/test/CodeGen/X86/2008-03-18-CoalescerBug.ll Modified: llvm/trunk/test/CodeGen/X86/2008-03-18-CoalescerBug.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2008-03-18-CoalescerBug.ll?rev=52482&r1=52481&r2=52482&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/2008-03-18-CoalescerBug.ll (original) +++ llvm/trunk/test/CodeGen/X86/2008-03-18-CoalescerBug.ll Wed Jun 18 20:50:13 2008 @@ -1,5 +1,5 @@ ; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin -mattr=+sse2 -disable-fp-elim | grep movss | count 1 -; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin -mattr=+sse2 -disable-fp-elim -stats |& grep {Number of re-materialization} | grep 1 +; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin -mattr=+sse2 -disable-fp-elim -stats |& grep {Number of re-materialization} | grep 2 %struct..0objc_object = type opaque %struct.OhBoy = type { } From evan.cheng at apple.com Wed Jun 18 20:50:24 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Thu, 19 Jun 2008 01:50:24 -0000 Subject: [llvm-commits] [llvm] r52483 - /llvm/trunk/test/CodeGen/X86/subclass-coalesce.ll Message-ID: <200806190150.m5J1oOaK027579@zion.cs.uiuc.edu> Author: evancheng Date: Wed Jun 18 20:50:24 2008 New Revision: 52483 URL: http://llvm.org/viewvc/llvm-project?rev=52483&view=rev Log: New test case. Added: llvm/trunk/test/CodeGen/X86/subclass-coalesce.ll Added: llvm/trunk/test/CodeGen/X86/subclass-coalesce.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/subclass-coalesce.ll?rev=52483&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/subclass-coalesce.ll (added) +++ llvm/trunk/test/CodeGen/X86/subclass-coalesce.ll Wed Jun 18 20:50:24 2008 @@ -0,0 +1,17 @@ +; RUN: llvm-as < %s | llc -march=x86 -join-subclass-copies -stats |& grep {Number of subclass joins performed} + + at mem.6 = external global i64 ; [#uses=1] + +define i64 @attachFunc() nounwind { +entry: + %tmp64.i = add i64 0, 72 ; [#uses=1] + %tmp68.i = load i64* @mem.6, align 8 ; [#uses=1] + %tmp70.i = icmp sgt i64 %tmp64.i, %tmp68.i ; [#uses=1] + br i1 %tmp70.i, label %bb73.i, label %bb116 + +bb73.i: ; preds = %entry + br label %bb116 + +bb116: ; preds = %bb73.i, %entry + ret i64 %tmp68.i +} From isanbard at gmail.com Wed Jun 18 21:32:40 2008 From: isanbard at gmail.com (Bill Wendling) Date: Thu, 19 Jun 2008 02:32:40 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r52484 - /llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp Message-ID: <200806190232.m5J2Wee4028802@zion.cs.uiuc.edu> Author: void Date: Wed Jun 18 21:32:39 2008 New Revision: 52484 URL: http://llvm.org/viewvc/llvm-project?rev=52484&view=rev Log: Build the new TheDebugInfo object conditionally (just as when it was created). Modified: llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp Modified: llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp?rev=52484&r1=52483&r2=52484&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp Wed Jun 18 21:32:39 2008 @@ -236,9 +236,11 @@ std::string ErrMsg; TheModule = ParseBitcodeFile(MB, &ErrMsg); - TheDebugInfo = new DebugInfo(TheModule); delete MB; + if (!optimize && debug_info_level > DINFO_LEVEL_NONE) + TheDebugInfo = new DebugInfo(TheModule); + if (!TheModule) { cerr << "Error reading bytecodes from PCH file\n"; cerr << ErrMsg << "\n"; From matthijs.kooijman at inter-actief.net Wed Jun 18 05:16:25 2008 From: matthijs.kooijman at inter-actief.net (Matthijs Kooijman - Inter-Actief) Date: Wed, 18 Jun 2008 12:16:25 +0200 Subject: [llvm-commits] [llvm] r52442 - in /llvm/trunk: lib/Transforms/Scalar/InstructionCombining.cpp test/Transforms/InstCombine/bswap-fold.ll In-Reply-To: <200806180433.m5I4XL48005145@zion.cs.uiuc.edu> References: <200806180433.m5I4XL48005145@zion.cs.uiuc.edu> Message-ID: <20080618101625.GN16202@katherina.student.utwente.nl> Hi Chris, > implement some simple bswap optimizations, rdar://5992453 This patch breaks the Transforms/InstCombine/sext-misc.ll testcase for me. Running /home/kooijman/src/llvm-trunk/test/Transforms/InstCombine/dg.exp ... FAIL: /home/kooijman/src/llvm-trunk/test/Transforms/InstCombine/sext-misc.ll Failed with exit(1) at line 1 while running: llvm-as < /home/kooijman/src/llvm-trunk/test/Transforms/InstCombine/sext-misc.ll | opt -instcombine | llvm-dis | not grep sext %s = sext i32 %t to i64 ; [#uses=1] %s = sext i32 %t to i64 ; [#uses=1] %s = sext i32 %t to i64 ; [#uses=1] child process exited abnormally Gr. Matthijs -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: Digital signature Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080618/0e0992da/attachment.bin From matthijs.kooijman at inter-actief.net Wed Jun 18 06:08:19 2008 From: matthijs.kooijman at inter-actief.net (Matthijs Kooijman - Inter-Actief) Date: Wed, 18 Jun 2008 13:08:19 +0200 Subject: [llvm-commits] [llvm] r52415 - /llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp In-Reply-To: <200806171706.m5HH6i6b015863@zion.cs.uiuc.edu> References: <200806171706.m5HH6i6b015863@zion.cs.uiuc.edu> Message-ID: <20080618110819.GO16202@katherina.student.utwente.nl> Hi Chris, > revert recent patch which is causing widespread breakage. This should be fixed now, I forgot to handle a case (which didn't appear in my adhoc testcases..). I've also added a testcase this time :-) Sorry for the noise! Gr. Matthijs -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: Digital signature Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080618/c844e3f9/attachment.bin From resistor at mac.com Thu Jun 19 00:29:34 2008 From: resistor at mac.com (Owen Anderson) Date: Thu, 19 Jun 2008 05:29:34 -0000 Subject: [llvm-commits] [llvm] r52485 - /llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Message-ID: <200806190529.m5J5TYNo001336@zion.cs.uiuc.edu> Author: resistor Date: Thu Jun 19 00:29:34 2008 New Revision: 52485 URL: http://llvm.org/viewvc/llvm-project?rev=52485&view=rev Log: Revert my last patch, which was causing regression test failures. Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp?rev=52485&r1=52484&r2=52485&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp (original) +++ llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Thu Jun 19 00:29:34 2008 @@ -78,7 +78,6 @@ void LiveIntervals::computeNumbering() { Index2MiMap OldI2MI = i2miMap_; - std::vector OldI2MBB = Idx2MBBMap; Idx2MBBMap.clear(); MBB2IdxMap.clear(); @@ -94,22 +93,19 @@ MBB != E; ++MBB) { unsigned StartIdx = MIIndex; - // Insert an empty slot at the beginning of each block. - MIIndex += InstrSlots::NUM; - i2miMap_.push_back(0); - for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E; ++I) { bool inserted = mi2iMap_.insert(std::make_pair(I, MIIndex)).second; assert(inserted && "multiple MachineInstr -> index mappings"); i2miMap_.push_back(I); MIIndex += InstrSlots::NUM; - - // Insert an empty slot after every instruction. + } + + if (StartIdx == MIIndex) { + // Empty MBB MIIndex += InstrSlots::NUM; i2miMap_.push_back(0); } - // Set the MBB2IdxMap entry for this MBB. MBB2IdxMap[MBB->getNumber()] = std::make_pair(StartIdx, MIIndex - 1); Idx2MBBMap.push_back(std::make_pair(StartIdx, MBB)); @@ -117,82 +113,90 @@ std::sort(Idx2MBBMap.begin(), Idx2MBBMap.end(), Idx2MBBCompare()); if (!OldI2MI.empty()) - for (iterator OI = begin(), OE = end(); OI != OE; ++OI) - for (LiveInterval::iterator LI = OI->second.begin(), - LE = OI->second.end(); LI != LE; ++LI) { + for (iterator I = begin(), E = end(); I != E; ++I) + for (LiveInterval::iterator LI = I->second.begin(), LE = I->second.end(); + LI != LE; ++LI) { // Remap the start index of the live range to the corresponding new // number, or our best guess at what it _should_ correspond to if the // original instruction has been erased. This is either the following // instruction or its predecessor. - unsigned index = LI->start / InstrSlots::NUM; unsigned offset = LI->start % InstrSlots::NUM; - if (offset == InstrSlots::LOAD) { - std::vector::const_iterator I = - std::lower_bound(OldI2MBB.begin(), OldI2MBB.end(), index); - // Take the pair containing the index - std::vector::const_iterator J = - ((I != OldI2MBB.end() && I->first > index) || - (I == OldI2MBB.end() && OldI2MBB.size()>0)) ? (I-1): I; + if (OldI2MI[LI->start / InstrSlots::NUM]) + LI->start = mi2iMap_[OldI2MI[LI->start / InstrSlots::NUM]] + offset; + else { + unsigned i = 0; + MachineInstr* newInstr = 0; + do { + newInstr = OldI2MI[LI->start / InstrSlots::NUM + i]; + i++; + } while (!newInstr); - LI->start = getMBBStartIdx(J->second); - } else { - LI->start = mi2iMap_[OldI2MI[index]] + offset; + if (mi2iMap_[newInstr] == + MBB2IdxMap[newInstr->getParent()->getNumber()].first) + LI->start = mi2iMap_[newInstr]; + else + LI->start = mi2iMap_[newInstr] - InstrSlots::NUM + offset; } // Remap the ending index in the same way that we remapped the start, // except for the final step where we always map to the immediately // following instruction. - index = LI->end / InstrSlots::NUM; - offset = LI->end % InstrSlots::NUM; - if (offset == InstrSlots::STORE) { - std::vector::const_iterator I = - std::lower_bound(OldI2MBB.begin(), OldI2MBB.end(), index); - // Take the pair containing the index - std::vector::const_iterator J = - ((I != OldI2MBB.end() && I->first > index) || - (I == OldI2MBB.end() && OldI2MBB.size()>0)) ? (I-1): I; - - LI->start = getMBBEndIdx(J->second); + if (LI->end / InstrSlots::NUM < OldI2MI.size()) { + offset = LI->end % InstrSlots::NUM; + if (OldI2MI[LI->end / InstrSlots::NUM]) + LI->end = mi2iMap_[OldI2MI[LI->end / InstrSlots::NUM]] + offset; + else { + unsigned i = 0; + MachineInstr* newInstr = 0; + do { + newInstr = OldI2MI[LI->end / InstrSlots::NUM + i]; + i++; + } while (!newInstr); + + LI->end = mi2iMap_[newInstr]; + } } else { - LI->end = mi2iMap_[OldI2MI[index]] + offset; + LI->end = i2miMap_.size() * InstrSlots::NUM; } // Remap the VNInfo def index, which works the same as the // start indices above. VNInfo* vni = LI->valno; - index = vni->def / InstrSlots::NUM; offset = vni->def % InstrSlots::NUM; - if (offset == InstrSlots::LOAD) { - std::vector::const_iterator I = - std::lower_bound(OldI2MBB.begin(), OldI2MBB.end(), index); - // Take the pair containing the index - std::vector::const_iterator J = - ((I != OldI2MBB.end() && I->first > index) || - (I == OldI2MBB.end() && OldI2MBB.size()>0)) ? (I-1): I; - - vni->def = getMBBStartIdx(J->second); + if (OldI2MI[vni->def / InstrSlots::NUM]) + vni->def = mi2iMap_[OldI2MI[vni->def / InstrSlots::NUM]] + offset; + else { + unsigned i = 0; + MachineInstr* newInstr = 0; + do { + newInstr = OldI2MI[vni->def / InstrSlots::NUM + i]; + i++; + } while (!newInstr); - } else { - vni->def = mi2iMap_[OldI2MI[index]] + offset; + if (mi2iMap_[newInstr] == + MBB2IdxMap[newInstr->getParent()->getNumber()].first) + vni->def = mi2iMap_[newInstr]; + else + vni->def = mi2iMap_[newInstr] - InstrSlots::NUM + offset; } // Remap the VNInfo kill indices, which works the same as // the end indices above. for (size_t i = 0; i < vni->kills.size(); ++i) { - index = vni->kills[i] / InstrSlots::NUM; offset = vni->kills[i] % InstrSlots::NUM; - if (OldI2MI[vni->kills[i] / InstrSlots::NUM]) { - std::vector::const_iterator I = - std::lower_bound(OldI2MBB.begin(), OldI2MBB.end(), index); - // Take the pair containing the index - std::vector::const_iterator J = - ((I != OldI2MBB.end() && I->first > index) || - (I == OldI2MBB.end() && OldI2MBB.size()>0)) ? (I-1): I; - - vni->kills[i] = getMBBEndIdx(J->second); - } else { - vni->kills[i] = mi2iMap_[OldI2MI[index]] + offset; + if (OldI2MI[vni->kills[i] / InstrSlots::NUM]) + vni->kills[i] = mi2iMap_[OldI2MI[vni->kills[i] / InstrSlots::NUM]] + + offset; + else { + unsigned e = 0; + MachineInstr* newInstr = 0; + do { + newInstr = OldI2MI[vni->kills[i] / InstrSlots::NUM + e]; + e++; + } while (!newInstr); + + vni->kills[i] = mi2iMap_[newInstr]; } } } @@ -350,7 +354,9 @@ // of the defining block, potentially live across some blocks, then is // live into some number of blocks, but gets killed. Start by adding a // range that goes from this definition to the end of the defining block. - LiveRange NewLR(defIndex, getMBBEndIdx(mbb), ValNo); + LiveRange NewLR(defIndex, + getInstructionIndex(&mbb->back()) + InstrSlots::NUM, + ValNo); DOUT << " +" << NewLR; interval.addRange(NewLR); @@ -470,7 +476,7 @@ CopyMI = mi; ValNo = interval.getNextValue(defIndex, CopyMI, VNInfoAllocator); - unsigned killIndex = getMBBEndIdx(mbb) + 1; + unsigned killIndex = getInstructionIndex(&mbb->back()) + InstrSlots::NUM; LiveRange LR(defIndex, killIndex, ValNo); interval.addRange(LR); interval.addKill(ValNo, killIndex); @@ -507,10 +513,8 @@ // If it is not dead on definition, it must be killed by a // subsequent instruction. Hence its interval is: // [defSlot(def), useSlot(kill)+1) - baseIndex += InstrSlots::NUM; while (++mi != MBB->end()) { - while (getInstructionFromIndex(baseIndex) == 0) - baseIndex += InstrSlots::NUM; + baseIndex += InstrSlots::NUM; if (mi->killsRegister(interval.reg, tri_)) { DOUT << " killed"; end = getUseIndex(baseIndex) + 1; @@ -524,8 +528,6 @@ end = getDefIndex(start) + 1; goto exit; } - - baseIndex += InstrSlots::NUM; } // The only case we should have a dead physreg here without a killing or @@ -597,8 +599,6 @@ } baseIndex += InstrSlots::NUM; - while (getInstructionFromIndex(baseIndex) == 0) - baseIndex += InstrSlots::NUM; ++mi; } @@ -630,12 +630,6 @@ << ((Value*)mf_->getFunction())->getName() << '\n'; // Track the index of the current machine instr. unsigned MIIndex = 0; - - // Skip over empty initial indices. - while (MIIndex / InstrSlots::NUM < i2miMap_.size() && - getInstructionFromIndex(MIIndex) == 0) - MIIndex += InstrSlots::NUM; - for (MachineFunction::iterator MBBI = mf_->begin(), E = mf_->end(); MBBI != E; ++MBBI) { MachineBasicBlock *MBB = MBBI; @@ -666,12 +660,9 @@ } MIIndex += InstrSlots::NUM; - - // Skip over empty indices. - while (MIIndex / InstrSlots::NUM < i2miMap_.size() && - getInstructionFromIndex(MIIndex) == 0) - MIIndex += InstrSlots::NUM; } + + if (MBB->begin() == miEnd) MIIndex += InstrSlots::NUM; // Empty MBB } } From clattner at apple.com Thu Jun 19 00:57:42 2008 From: clattner at apple.com (Chris Lattner) Date: Wed, 18 Jun 2008 22:57:42 -0700 Subject: [llvm-commits] [llvm] r52442 - in /llvm/trunk: lib/Transforms/Scalar/InstructionCombining.cpp test/Transforms/InstCombine/bswap-fold.ll In-Reply-To: <20080618101625.GN16202@katherina.student.utwente.nl> References: <200806180433.m5I4XL48005145@zion.cs.uiuc.edu> <20080618101625.GN16202@katherina.student.utwente.nl> Message-ID: <99A29F10-0B67-439B-A31D-2099E3AE6AC2@apple.com> On Jun 18, 2008, at 3:16 AM, Matthijs Kooijman - Inter-Actief wrote: > Hi Chris, > >> implement some simple bswap optimizations, rdar://5992453 > This patch breaks the Transforms/InstCombine/sext-misc.ll testcase > for me. > > Running /home/kooijman/src/llvm-trunk/test/Transforms/InstCombine/ > dg.exp ... > FAIL: /home/kooijman/src/llvm-trunk/test/Transforms/InstCombine/sext- > misc.ll > Failed with exit(1) at line 1 > while running: llvm-as < /home/kooijman/src/llvm-trunk/test/ > Transforms/InstCombine/sext-misc.ll | opt -instcombine | llvm-dis | > not grep sext > %s = sext i32 %t to i64 ; [#uses=1] > %s = sext i32 %t to i64 ; [#uses=1] > %s = sext i32 %t to i64 ; [#uses=1] > child process exited abnormally This should be fixed, can you please verify they still fail with mainline? -Chris From eli.friedman at gmail.com Thu Jun 19 01:09:51 2008 From: eli.friedman at gmail.com (Eli Friedman) Date: Thu, 19 Jun 2008 06:09:51 -0000 Subject: [llvm-commits] [llvm] r52486 - in /llvm/trunk: lib/Target/X86/X86ISelLowering.cpp test/CodeGen/X86/2008-06-18-BadShuffle.ll Message-ID: <200806190609.m5J69qHx002547@zion.cs.uiuc.edu> Author: efriedma Date: Thu Jun 19 01:09:51 2008 New Revision: 52486 URL: http://llvm.org/viewvc/llvm-project?rev=52486&view=rev Log: Fix a bug with <8 x i16> shuffle lowering on X86 where parts of the shuffle could be skipped. The check is invalid because the loop index i doesn't correspond to the element actually inserted. The correct check is already done a few lines earlier, for whether the element is already in the right spot, so this shouldn't have any effect on the codegen for code that was already correct. Added: llvm/trunk/test/CodeGen/X86/2008-06-18-BadShuffle.ll Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=52486&r1=52485&r2=52486&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Thu Jun 19 01:09:51 2008 @@ -3445,8 +3445,6 @@ continue; SDOperand Elt = MaskElts[i]; unsigned EltIdx = cast(Elt)->getValue(); - if (EltIdx == i) - continue; SDOperand ExtOp = (EltIdx < 8) ? DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i16, V1, DAG.getConstant(EltIdx, PtrVT)) Added: llvm/trunk/test/CodeGen/X86/2008-06-18-BadShuffle.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2008-06-18-BadShuffle.ll?rev=52486&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/2008-06-18-BadShuffle.ll (added) +++ llvm/trunk/test/CodeGen/X86/2008-06-18-BadShuffle.ll Thu Jun 19 01:09:51 2008 @@ -0,0 +1,10 @@ +; RUN: llvm-as < %s | llc -march=x86 -mcpu=i386 -mattr=+sse2 | grep pinsrw + +; Test to make sure we actually insert the bottom element of the vector +define <8 x i16> @a(<8 x i16> %a) nounwind { +entry: + shufflevector <8 x i16> %a, <8 x i16> zeroinitializer, <8 x i32> < i32 0, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8 > + %add = add <8 x i16> %0, %a + ret <8 x i16> %add +} + From evan.cheng at apple.com Thu Jun 19 01:17:19 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Thu, 19 Jun 2008 06:17:19 -0000 Subject: [llvm-commits] [llvm] r52487 - /llvm/trunk/lib/CodeGen/TwoAddressInstructionPass.cpp Message-ID: <200806190617.m5J6HJ4G002836@zion.cs.uiuc.edu> Author: evancheng Date: Thu Jun 19 01:17:19 2008 New Revision: 52487 URL: http://llvm.org/viewvc/llvm-project?rev=52487&view=rev Log: Missed a check. Modified: llvm/trunk/lib/CodeGen/TwoAddressInstructionPass.cpp Modified: llvm/trunk/lib/CodeGen/TwoAddressInstructionPass.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TwoAddressInstructionPass.cpp?rev=52487&r1=52486&r2=52487&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/TwoAddressInstructionPass.cpp (original) +++ llvm/trunk/lib/CodeGen/TwoAddressInstructionPass.cpp Thu Jun 19 01:17:19 2008 @@ -234,7 +234,7 @@ const TargetInstrDesc &TID = UseMI->getDesc(); for (unsigned i = 0, e = TID.getNumOperands(); i != e; ++i) { MachineOperand &MO = UseMI->getOperand(i); - if (MO.getReg() == Reg && + if (MO.isRegister() && MO.getReg() == Reg && (MO.isDef() || TID.getOperandConstraint(i, TOI::TIED_TO) != -1)) // Earlier use is a two-address one. return true; From evan.cheng at apple.com Thu Jun 19 01:26:48 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Wed, 18 Jun 2008 23:26:48 -0700 Subject: [llvm-commits] [llvm] r52472 - /llvm/trunk/lib/Transforms/Scalar/GVN.cpp In-Reply-To: <200806182159.m5ILx1Wi019964@zion.cs.uiuc.edu> References: <200806182159.m5ILx1Wi019964@zion.cs.uiuc.edu> Message-ID: Hi Owen, This broke povray. Can you fix? /Users/echeng/LLVM/llvm/Release/bin/opt -std-compile-opts -time-passes -info-output-file=/Volumes/Vadar/LLVM/llvm/projects/llvm-test/External/ Povray/Output/povray.linked.bc.info Output/povray.linked.rbc -o Outp\ ut/povray.linked.bc -f Assertion failed: (getType() == V->getType() && "All operands to PHI node must be the same type as the PHI node!"), function addIncoming, file /Users/echeng/LLVM/llvm/include/llvm/Instructions.h, line 1914. 0 opt 0x0039c1cc _ZN4llvm3sys18RemoveFileOnSignalERKNS0_4PathEPSs + 844^@ 1 libSystem.B.dylib 0x9232209b _sigtramp + 43^@ 2 ??? 0xffffffff 0x0 + 4294967295^@ 3 libSystem.B.dylib 0x9239aec2 raise + 26^@ 4 libSystem.B.dylib 0x923aa47f abort + 73^@ 5 libSystem.B.dylib 0x9239c063 __assert_rtn + 101^@ 6 opt 0x00093de2 _ZN4llvm7PHINode11addIncomingEPNS_5ValueEPNS_10BasicBlockE + 386^@ 7 opt 0x000683b5 _ZN4llvm8df_beginIPNS_15DomTreeNodeBaseINS_10BasicBlockEEEEENS_11df_iteratorIT_NS_11SmallPtrSetIPNS_11GraphTraitsIS6_E8NodeTypeELj8EEELb0ES9_EERKS6_ + 6565^@ 8 opt 0x00072310 _ZN4llvm13createGVNPassEv + 22624^@ 9 opt 0x000727af _ZN4llvm13createGVNPassEv + 23807^@ 10 opt 0x00331ae6 _ZN4llvm13FPPassManager13runOnFunctionERNS_8FunctionE + 518^@ 11 opt 0x0020e612 _ZN49_GLOBAL__N_CallGraphSCCPass .cpp_00000000_62117D2D13CGPassManager11runOnModuleERN4llvm6ModuleE + 1250^@ 12 opt 0x00332561 _ZN4llvm13MPPassManager11runOnModuleERNS_6ModuleE + 369^@ 13 opt 0x00332974 _ZN4llvm15PassManagerImpl3runERNS_6ModuleE + 132^@ 14 opt 0x003329eb _ZN4llvm11PassManager3runERNS_6ModuleE + 27^@ 15 opt 0x00008b87 main + 2583^@ 16 opt 0x00002196 start + 54^@ Evan On Jun 18, 2008, at 2:59 PM, Owen Anderson wrote: > Author: resistor > Date: Wed Jun 18 16:59:00 2008 > New Revision: 52472 > > URL: http://llvm.org/viewvc/llvm-project?rev=52472&view=rev > Log: > Add support for extractvalue and insertvalue instructions in GVN. > > Modified: > llvm/trunk/lib/Transforms/Scalar/GVN.cpp > > Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=52472&r1=52471&r2=52472&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original) > +++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Wed Jun 18 16:59:00 2008 > @@ -59,7 +59,7 @@ > SHUFFLE, SELECT, TRUNC, ZEXT, SEXT, > FPTOUI, > FPTOSI, UITOFP, SITOFP, FPTRUNC, FPEXT, > PTRTOINT, INTTOPTR, BITCAST, GEP, CALL, > CONSTANT, > - EMPTY, TOMBSTONE }; > + EXTRACTVALUE, INSERTVALUE, EMPTY, > TOMBSTONE }; > > ExpressionOpcode opcode; > const Type* type; > @@ -150,6 +150,8 @@ > Expression create_expression(GetElementPtrInst* G); > Expression create_expression(CallInst* C); > Expression create_expression(Constant* C); > + Expression create_expression(InsertValueInst* I); > + Expression create_expression(ExtractValueInst* I); > public: > ValueTable() : nextValueNumber(1) { } > uint32_t lookup_or_add(Value* V); > @@ -284,6 +286,40 @@ > } > } > > +Expression ValueTable::create_expression(InsertValueInst* I) { > + Expression e; > + > + e.type = I->getType(); > + e.firstVN = lookup_or_add(I->getOperand(0)); > + e.secondVN = lookup_or_add(I->getOperand(1)); > + e.thirdVN = 0; > + e.function = 0; > + e.opcode = Expression::INSERTVALUE; > + > + for (InsertValueInst::op_iterator OI = I->op_begin()+2, > + OE = I->op_end(); OI != OE; ++OI) > + e.varargs.push_back(lookup_or_add(I)); > + > + return e; > +} > + > +Expression ValueTable::create_expression(ExtractValueInst* I) { > + Expression e; > + > + e.type = I->getType(); > + e.firstVN = lookup_or_add(I->getOperand(0)); > + e.secondVN = lookup_or_add(I->getOperand(1)); > + e.thirdVN = 0; > + e.function = 0; > + e.opcode = Expression::EXTRACTVALUE; > + > + for (InsertValueInst::op_iterator OI = I->op_begin()+2, > + OE = I->op_end(); OI != OE; ++OI) > + e.varargs.push_back(lookup_or_add(I)); > + > + return e; > +} > + > Expression ValueTable::create_expression(CallInst* C) { > Expression e; > > @@ -541,6 +577,32 @@ > valueNumbering.insert(std::make_pair(V, nextValueNumber)); > return nextValueNumber++; > } > + } else if (InsertValueInst* II = dyn_cast(V)) { > + Expression e = create_expression(II); > + > + DenseMap::iterator EI = > expressionNumbering.find(e); > + if (EI != expressionNumbering.end()) { > + valueNumbering.insert(std::make_pair(V, EI->second)); > + return EI->second; > + } else { > + expressionNumbering.insert(std::make_pair(e, nextValueNumber)); > + valueNumbering.insert(std::make_pair(V, nextValueNumber)); > + > + return nextValueNumber++; > + } > + } else if (ExtractValueInst* E = dyn_cast(V)) { > + Expression e = create_expression(E); > + > + DenseMap::iterator EI = > expressionNumbering.find(e); > + if (EI != expressionNumbering.end()) { > + valueNumbering.insert(std::make_pair(V, EI->second)); > + return EI->second; > + } else { > + expressionNumbering.insert(std::make_pair(e, nextValueNumber)); > + valueNumbering.insert(std::make_pair(V, nextValueNumber)); > + > + return nextValueNumber++; > + } > } else if (BinaryOperator* BO = dyn_cast(V)) { > Expression e = create_expression(BO); > > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From matthijs at stdin.nl Thu Jun 19 02:26:54 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Thu, 19 Jun 2008 09:26:54 +0200 Subject: [llvm-commits] [llvm] r52442 - in /llvm/trunk: lib/Transforms/Scalar/InstructionCombining.cpp test/Transforms/InstCombine/bswap-fold.ll In-Reply-To: <99A29F10-0B67-439B-A31D-2099E3AE6AC2@apple.com> References: <200806180433.m5I4XL48005145@zion.cs.uiuc.edu> <20080618101625.GN16202@katherina.student.utwente.nl> <99A29F10-0B67-439B-A31D-2099E3AE6AC2@apple.com> Message-ID: <20080619072654.GP16202@katherina.student.utwente.nl> Hi Chris, > This should be fixed, can you please verify they still fail with > mainline? I'm no longer seeing the errors, thanks! Gr. Matthijs -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: Digital signature Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080619/34a7c12a/attachment.bin From matthijs at stdin.nl Thu Jun 19 02:30:59 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Thu, 19 Jun 2008 09:30:59 +0200 Subject: [llvm-commits] [vmkit] r52469 - /vmkit/trunk/autogen.sh In-Reply-To: <200806182111.m5ILBwfh018572@zion.cs.uiuc.edu> References: <200806182111.m5ILBwfh018572@zion.cs.uiuc.edu> Message-ID: <20080619073059.GQ16202@katherina.student.utwente.nl> Hi Nicolas, > -#!/bin/sh > +#!/bin/bash Isn't this extremely unportable? I think the right approach for requiring bash is using #!/usr/bin/env bash since bash can be all over the place (such as in /usr/local/bin for the BSD's). Isn't it possible to make the script sh compliant instead? Gr. Matthijs -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: Digital signature Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080619/63fb5b2c/attachment.bin From resistor at mac.com Thu Jun 19 02:34:38 2008 From: resistor at mac.com (Owen Anderson) Date: Thu, 19 Jun 2008 00:34:38 -0700 Subject: [llvm-commits] [llvm] r52472 - /llvm/trunk/lib/Transforms/Scalar/GVN.cpp In-Reply-To: References: <200806182159.m5ILx1Wi019964@zion.cs.uiuc.edu> Message-ID: <23460115-EF25-4DC7-A6F5-EDEBFEC50F5F@mac.com> Evan, Could you send me a bugpoint reduction? I don't have povray setup on my machine. --Owen On Jun 18, 2008, at 11:26 PM, Evan Cheng wrote: > Hi Owen, > > This broke povray. Can you fix? > > /Users/echeng/LLVM/llvm/Release/bin/opt -std-compile-opts -time-passes > -info-output-file=/Volumes/Vadar/LLVM/llvm/projects/llvm-test/ > External/ > Povray/Output/povray.linked.bc.info Output/povray.linked.rbc -o > Outp\ > ut/povray.linked.bc -f > Assertion failed: (getType() == V->getType() && "All operands to PHI > node must be the same type as the PHI node!"), function addIncoming, > file /Users/echeng/LLVM/llvm/include/llvm/Instructions.h, line 1914. > 0 opt 0x0039c1cc > _ZN4llvm3sys18RemoveFileOnSignalERKNS0_4PathEPSs + 844^@ > 1 libSystem.B.dylib 0x9232209b _sigtramp + 43^@ > 2 ??? 0xffffffff 0x0 + 4294967295^@ > 3 libSystem.B.dylib 0x9239aec2 raise + 26^@ > 4 libSystem.B.dylib 0x923aa47f abort + 73^@ > 5 libSystem.B.dylib 0x9239c063 __assert_rtn + > 101^@ > 6 opt 0x00093de2 > _ZN4llvm7PHINode11addIncomingEPNS_5ValueEPNS_10BasicBlockE + 386^@ > 7 opt 0x000683b5 > _ZN4llvm8df_beginIPNS_15DomTreeNodeBaseINS_10BasicBlockEEEEENS_11df_iteratorIT_NS_11SmallPtrSetIPNS_11GraphTraitsIS6_E8NodeTypeELj8EEELb0ES9_EERKS6_ > + 6565^@ > 8 opt 0x00072310 > _ZN4llvm13createGVNPassEv + 22624^@ > 9 opt 0x000727af > _ZN4llvm13createGVNPassEv + 23807^@ > 10 opt 0x00331ae6 > _ZN4llvm13FPPassManager13runOnFunctionERNS_8FunctionE + 518^@ > 11 opt 0x0020e612 > _ZN49_GLOBAL__N_CallGraphSCCPass > .cpp_00000000_62117D2D13CGPassManager11runOnModuleERN4llvm6ModuleE + > 1250^@ > 12 opt 0x00332561 > _ZN4llvm13MPPassManager11runOnModuleERNS_6ModuleE + 369^@ > 13 opt 0x00332974 > _ZN4llvm15PassManagerImpl3runERNS_6ModuleE + 132^@ > 14 opt 0x003329eb > _ZN4llvm11PassManager3runERNS_6ModuleE + 27^@ > 15 opt 0x00008b87 main + 2583^@ > 16 opt 0x00002196 start + 54^@ > > Evan > > On Jun 18, 2008, at 2:59 PM, Owen Anderson wrote: > >> Author: resistor >> Date: Wed Jun 18 16:59:00 2008 >> New Revision: 52472 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=52472&view=rev >> Log: >> Add support for extractvalue and insertvalue instructions in GVN. >> >> Modified: >> llvm/trunk/lib/Transforms/Scalar/GVN.cpp >> >> Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=52472&r1=52471&r2=52472&view=diff >> >> = >> = >> = >> = >> = >> = >> = >> = >> = >> ===================================================================== >> --- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original) >> +++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Wed Jun 18 16:59:00 2008 >> @@ -59,7 +59,7 @@ >> SHUFFLE, SELECT, TRUNC, ZEXT, SEXT, >> FPTOUI, >> FPTOSI, UITOFP, SITOFP, FPTRUNC, FPEXT, >> PTRTOINT, INTTOPTR, BITCAST, GEP, CALL, >> CONSTANT, >> - EMPTY, TOMBSTONE }; >> + EXTRACTVALUE, INSERTVALUE, EMPTY, >> TOMBSTONE }; >> >> ExpressionOpcode opcode; >> const Type* type; >> @@ -150,6 +150,8 @@ >> Expression create_expression(GetElementPtrInst* G); >> Expression create_expression(CallInst* C); >> Expression create_expression(Constant* C); >> + Expression create_expression(InsertValueInst* I); >> + Expression create_expression(ExtractValueInst* I); >> public: >> ValueTable() : nextValueNumber(1) { } >> uint32_t lookup_or_add(Value* V); >> @@ -284,6 +286,40 @@ >> } >> } >> >> +Expression ValueTable::create_expression(InsertValueInst* I) { >> + Expression e; >> + >> + e.type = I->getType(); >> + e.firstVN = lookup_or_add(I->getOperand(0)); >> + e.secondVN = lookup_or_add(I->getOperand(1)); >> + e.thirdVN = 0; >> + e.function = 0; >> + e.opcode = Expression::INSERTVALUE; >> + >> + for (InsertValueInst::op_iterator OI = I->op_begin()+2, >> + OE = I->op_end(); OI != OE; ++OI) >> + e.varargs.push_back(lookup_or_add(I)); >> + >> + return e; >> +} >> + >> +Expression ValueTable::create_expression(ExtractValueInst* I) { >> + Expression e; >> + >> + e.type = I->getType(); >> + e.firstVN = lookup_or_add(I->getOperand(0)); >> + e.secondVN = lookup_or_add(I->getOperand(1)); >> + e.thirdVN = 0; >> + e.function = 0; >> + e.opcode = Expression::EXTRACTVALUE; >> + >> + for (InsertValueInst::op_iterator OI = I->op_begin()+2, >> + OE = I->op_end(); OI != OE; ++OI) >> + e.varargs.push_back(lookup_or_add(I)); >> + >> + return e; >> +} >> + >> Expression ValueTable::create_expression(CallInst* C) { >> Expression e; >> >> @@ -541,6 +577,32 @@ >> valueNumbering.insert(std::make_pair(V, nextValueNumber)); >> return nextValueNumber++; >> } >> + } else if (InsertValueInst* II = dyn_cast(V)) { >> + Expression e = create_expression(II); >> + >> + DenseMap::iterator EI = >> expressionNumbering.find(e); >> + if (EI != expressionNumbering.end()) { >> + valueNumbering.insert(std::make_pair(V, EI->second)); >> + return EI->second; >> + } else { >> + expressionNumbering.insert(std::make_pair(e, >> nextValueNumber)); >> + valueNumbering.insert(std::make_pair(V, nextValueNumber)); >> + >> + return nextValueNumber++; >> + } >> + } else if (ExtractValueInst* E = dyn_cast(V)) { >> + Expression e = create_expression(E); >> + >> + DenseMap::iterator EI = >> expressionNumbering.find(e); >> + if (EI != expressionNumbering.end()) { >> + valueNumbering.insert(std::make_pair(V, EI->second)); >> + return EI->second; >> + } else { >> + expressionNumbering.insert(std::make_pair(e, >> nextValueNumber)); >> + valueNumbering.insert(std::make_pair(V, nextValueNumber)); >> + >> + return nextValueNumber++; >> + } >> } else if (BinaryOperator* BO = dyn_cast(V)) { >> Expression e = create_expression(BO); >> >> >> >> _______________________________________________ >> llvm-commits mailing list >> llvm-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 4260 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080619/ffd8f82a/attachment.bin From matthijs at stdin.nl Thu Jun 19 02:38:06 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Thu, 19 Jun 2008 09:38:06 +0200 Subject: [llvm-commits] [llvm] r52472 - /llvm/trunk/lib/Transforms/Scalar/GVN.cpp In-Reply-To: <200806182159.m5ILx1Wi019964@zion.cs.uiuc.edu> References: <200806182159.m5ILx1Wi019964@zion.cs.uiuc.edu> Message-ID: <20080619073806.GR16202@katherina.student.utwente.nl> Hi Owen, > + e.type = I->getType(); > + e.firstVN = lookup_or_add(I->getOperand(0)); > + e.secondVN = lookup_or_add(I->getOperand(1)); > + e.thirdVN = 0; > + e.function = 0; > + e.opcode = Expression::INSERTVALUE; > + > + for (InsertValueInst::op_iterator OI = I->op_begin()+2, > + OE = I->op_end(); OI != OE; ++OI) > + e.varargs.push_back(lookup_or_add(I)); What is this last loop supposed to do? It seems like you're trying to iterate the index arguments of the instruction, but those are not operands (ie, not Value*s). If you want to loop them, you should use idx_begin/end instead. Also, you're looking up "I" in the loop body, ignoring the OI iterator. Is that intentional? > + for (InsertValueInst::op_iterator OI = I->op_begin()+2, > + OE = I->op_end(); OI != OE; ++OI) > + e.varargs.push_back(lookup_or_add(I)); The same question goes for ExtractValue here. Additionally, you'r using op_begin() + 2, while extractvalue has only one operand. I think this might be causing the crash Evan reported. Gr. Matthijs -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: Digital signature Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080619/1494e321/attachment.bin From baldrick at free.fr Thu Jun 19 03:47:32 2008 From: baldrick at free.fr (Duncan Sands) Date: Thu, 19 Jun 2008 08:47:32 -0000 Subject: [llvm-commits] [llvm] r52488 - in /llvm/trunk: lib/Analysis/ValueTracking.cpp tools/llvm-stub/llvm-stub.c Message-ID: <200806190847.m5J8lWbw018190@zion.cs.uiuc.edu> Author: baldrick Date: Thu Jun 19 03:47:31 2008 New Revision: 52488 URL: http://llvm.org/viewvc/llvm-project?rev=52488&view=rev Log: Fix some warnings reported by gcc-4.3. Hopefully this still compiles on windows - I can't test! Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp llvm/trunk/tools/llvm-stub/llvm-stub.c Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=52488&r1=52487&r2=52488&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ValueTracking.cpp (original) +++ llvm/trunk/lib/Analysis/ValueTracking.cpp Thu Jun 19 03:47:31 2008 @@ -871,7 +871,7 @@ const unsigned *req_idx = idx_begin; for (const unsigned *i = I->idx_begin(), *e = I->idx_end(); i != e; ++i, ++req_idx) { - if (req_idx == idx_end) + if (req_idx == idx_end) { if (InsertBefore) // The requested index identifies a part of a nested aggregate. Handle // this specially. For example, @@ -887,6 +887,7 @@ else // We can't handle this without inserting insertvalues return 0; + } // This insert value inserts something else than what we are looking for. // See if the (aggregrate) value inserted into has the value we are Modified: llvm/trunk/tools/llvm-stub/llvm-stub.c URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-stub/llvm-stub.c?rev=52488&r1=52487&r2=52488&view=diff ============================================================================== --- llvm/trunk/tools/llvm-stub/llvm-stub.c (original) +++ llvm/trunk/tools/llvm-stub/llvm-stub.c Thu Jun 19 03:47:31 2008 @@ -38,7 +38,6 @@ int main(int argc, char** argv) { const char *Interp = getenv("LLVMINTERP"); const char **Args; - int len; if (Interp == 0) Interp = "lli"; /* Set up the command line options to pass to the JIT. */ @@ -47,12 +46,14 @@ Args[0] = Interp; #ifdef LLVM_ON_WIN32 - len = strlen(argv[0]); - if (len < 4 || strcmp(argv[0] + len - 4, ".exe") != 0) { - /* .exe suffix is stripped off of argv[0] if the executable was run on the - * command line without one. Put it back on. - */ - argv[0] = strcat(strcpy((char*)malloc(len + 5), argv[0]), ".exe"); + { + int len = strlen(argv[0]); + if (len < 4 || strcmp(argv[0] + len - 4, ".exe") != 0) { + /* .exe suffix is stripped off of argv[0] if the executable was run on the + * command line without one. Put it back on. + */ + argv[0] = strcat(strcpy((char*)malloc(len + 5), argv[0]), ".exe"); + } } #endif From matthijs at stdin.nl Thu Jun 19 03:53:24 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Thu, 19 Jun 2008 08:53:24 -0000 Subject: [llvm-commits] [llvm] r52489 - /llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp Message-ID: <200806190853.m5J8rP7H018392@zion.cs.uiuc.edu> Author: matthijs Date: Thu Jun 19 03:53:24 2008 New Revision: 52489 URL: http://llvm.org/viewvc/llvm-project?rev=52489&view=rev Log: Use a CallSite to find the nth argument of a call/invoke instruction instead of using getOperand() directly. This makes things work with invoke instructions as well. Modified: llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp Modified: llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp?rev=52489&r1=52488&r2=52489&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp (original) +++ llvm/trunk/lib/Transforms/IPO/IPConstantPropagation.cpp Thu Jun 19 03:53:24 2008 @@ -218,13 +218,15 @@ // constant. bool MadeChange = false; for (Value::use_iterator UI = F.use_begin(), E = F.use_end(); UI != E; ++UI) { - // Make sure this is an invoke or call and that the use is for the callee. - if (!(isa(*UI) || isa(*UI)) || - UI.getOperandNo() != 0) { + CallSite CS = CallSite::get(*UI); + Instruction* Call = CS.getInstruction(); + + // Not a call instruction or a call instruction that's not calling F + // directly? + if (!Call || UI.getOperandNo() != 0) continue; - } - Instruction *Call = cast(*UI); + // Call result not used? if (Call->use_empty()) continue; @@ -234,9 +236,8 @@ Value* New = RetVals[0]; if (Argument *A = dyn_cast(New)) // Was an argument returned? Then find the corresponding argument in - // the call instruction and use that. Add 1 to the argument number - // to skip the first argument (the function itself). - New = Call->getOperand(A->getArgNo() + 1); + // the call instruction and use that. + New = CS.getArgument(A->getArgNo()); Call->replaceAllUsesWith(New); continue; } @@ -267,9 +268,8 @@ if (New) { if (Argument *A = dyn_cast(New)) // Was an argument returned? Then find the corresponding argument in - // the call instruction and use that. Add 1 to the argument number - // to skip the first argument (the function itself). - New = Call->getOperand(A->getArgNo() + 1); + // the call instruction and use that. + New = CS.getArgument(A->getArgNo()); Ins->replaceAllUsesWith(New); Ins->eraseFromParent(); } From nicolas.geoffray at lip6.fr Thu Jun 19 03:58:36 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Thu, 19 Jun 2008 08:58:36 -0000 Subject: [llvm-commits] [vmkit] r52490 - /vmkit/trunk/autogen.sh Message-ID: <200806190858.m5J8wal2018616@zion.cs.uiuc.edu> Author: geoffray Date: Thu Jun 19 03:58:36 2008 New Revision: 52490 URL: http://llvm.org/viewvc/llvm-project?rev=52490&view=rev Log: Clean up script. It just needs sh. Modified: vmkit/trunk/autogen.sh Modified: vmkit/trunk/autogen.sh URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/autogen.sh?rev=52490&r1=52489&r2=52490&view=diff ============================================================================== --- vmkit/trunk/autogen.sh (original) +++ vmkit/trunk/autogen.sh Thu Jun 19 03:58:36 2008 @@ -1,18 +1,4 @@ -#!/bin/bash - -# autogen processing -function do_autogen() -{ - autoreconf -vfi - #aclocal - #libtoolize --force - #autoheader - #automake -a - #autoconf -} - -do_autogen - -#autoreconf +#!/bin/sh +autoreconf -vfi From nicolas.geoffray at lip6.fr Thu Jun 19 04:00:45 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Thu, 19 Jun 2008 11:00:45 +0200 Subject: [llvm-commits] [vmkit] r52469 - /vmkit/trunk/autogen.sh In-Reply-To: <20080619073059.GQ16202@katherina.student.utwente.nl> References: <200806182111.m5ILBwfh018572@zion.cs.uiuc.edu> <20080619073059.GQ16202@katherina.student.utwente.nl> Message-ID: <485A203D.1090404@lip6.fr> Thanks Matthijs for pointing this. I made the script sh compliant. Nicolas Matthijs Kooijman wrote: > Hi Nicolas, > > >> -#!/bin/sh >> +#!/bin/bash >> > Isn't this extremely unportable? I think the right approach for requiring > bash is using > #!/usr/bin/env bash > > since bash can be all over the place (such as in /usr/local/bin for the > BSD's). > > Isn't it possible to make the script sh compliant instead? > > Gr. > > Matthijs > > ------------------------------------------------------------------------ > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > From matthijs at stdin.nl Thu Jun 19 04:27:45 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Thu, 19 Jun 2008 09:27:45 -0000 Subject: [llvm-commits] [llvm] r52491 - in /llvm/trunk/test/Transforms/IPConstantProp: return-argument.ll return-constant.ll Message-ID: <200806190927.m5J9RjX0020279@zion.cs.uiuc.edu> Author: matthijs Date: Thu Jun 19 04:27:44 2008 New Revision: 52491 URL: http://llvm.org/viewvc/llvm-project?rev=52491&view=rev Log: Modify some ipconstprop tests to also test with invokes. Modified: llvm/trunk/test/Transforms/IPConstantProp/return-argument.ll llvm/trunk/test/Transforms/IPConstantProp/return-constant.ll Modified: llvm/trunk/test/Transforms/IPConstantProp/return-argument.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/return-argument.ll?rev=52491&r1=52490&r2=52491&view=diff ============================================================================== --- llvm/trunk/test/Transforms/IPConstantProp/return-argument.ll (original) +++ llvm/trunk/test/Transforms/IPConstantProp/return-argument.ll Thu Jun 19 04:27:44 2008 @@ -36,11 +36,14 @@ ;; propagated per-caller). %S1 = call { i32, i32 } @foo(i32 1, i32 2); %X1 = extractvalue { i32, i32 } %S1, 0 - %S2 = call { i32, i32 } @foo(i32 3, i32 4); + %S2 = invoke { i32, i32 } @foo(i32 3, i32 4) to label %OK unwind label %RET; +OK: %X2 = extractvalue { i32, i32 } %S2, 0 ;; Do some stuff with the returned values which we can grep for %Z = add i32 %X1, %X2 store i32 %Z, i32* %W + br label %RET +RET: ret void } Modified: llvm/trunk/test/Transforms/IPConstantProp/return-constant.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IPConstantProp/return-constant.ll?rev=52491&r1=52490&r2=52491&view=diff ============================================================================== --- llvm/trunk/test/Transforms/IPConstantProp/return-constant.ll (original) +++ llvm/trunk/test/Transforms/IPConstantProp/return-constant.ll Thu Jun 19 04:27:44 2008 @@ -1,5 +1,5 @@ ; RUN: llvm-as < %s | opt -ipconstprop -instcombine | \ -; RUN: llvm-dis | grep {ret i1 true} +; RUN: llvm-dis | grep {ret i1 true} | count 2 define internal i32 @foo(i1 %C) { br i1 %C, label %T, label %F @@ -16,3 +16,11 @@ ret i1 %Y } +define i1 @invokecaller(i1 %C) { + %X = invoke i32 @foo( i1 %C ) to label %OK unwind label %FAIL ; [#uses=1] +OK: + %Y = icmp ne i32 %X, 0 ; [#uses=1] + ret i1 %Y +FAIL: + ret i1 false +} From matthijs at stdin.nl Thu Jun 19 04:30:21 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Thu, 19 Jun 2008 11:30:21 +0200 Subject: [llvm-commits] Regression with -ipconstprop In-Reply-To: <4800F036-0318-4459-88EB-3F2DBAA9D58D@apple.com> References: <4800F036-0318-4459-88EB-3F2DBAA9D58D@apple.com> Message-ID: <20080619093021.GV16202@katherina.student.utwente.nl> Hi Chris, > ipconstprop is crashing when compiling 447.dealII. Matthijs, can you > please investigate? I fixed this problem. Turns out the label operands of an invoke instruction come before the function arguments (which makes sense coming to think about it, but is a bit unexpected and inconsistent with the assembly notation). I'm now using a CallSite to abstract from this. I've also changed a few tests to test invoke as well as call. Gr. Matthijs -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: Digital signature Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080619/8a13f4b4/attachment.bin From matthijs at stdin.nl Thu Jun 19 10:59:30 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Thu, 19 Jun 2008 17:59:30 +0200 Subject: [llvm-commits] [llvm] r52459 - in /llvm/trunk: lib/Transforms/IPO/DeadArgumentElimination.cpp test/Transforms/DeadArgElim/multdeadretval.ll In-Reply-To: References: <200806181113.m5IBD8Mc029979@zion.cs.uiuc.edu> Message-ID: <20080619155930.GB3816@katherina.student.utwente.nl> Hi Dan, > I investigated this a little and found the subtle bug in this > bit of code that's triggering the infinite looping behavior. > The erase call is invalidating the Range.second iterator in > a MarkLive call earlier in the recursion. I guess your > original code which used lower_bound and just tested the > key at each iteration was a better approach after all, and I > shouldn't have suggested you change it :-}. Ah, right. I've indeed reverted to the old code, which helps in the SPAS testcase. I'm currently running a full test-suite, I'll have results in the morning. Gr. Matthijs -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: Digital signature Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080619/91f0ad9e/attachment.bin From gohman at apple.com Thu Jun 19 11:16:06 2008 From: gohman at apple.com (Dan Gohman) Date: Thu, 19 Jun 2008 16:16:06 -0000 Subject: [llvm-commits] [llvm] r52492 - /llvm/trunk/include/llvm/ParameterAttributes.h Message-ID: <200806191616.m5JGG7YE032698@zion.cs.uiuc.edu> Author: djg Date: Thu Jun 19 11:16:06 2008 New Revision: 52492 URL: http://llvm.org/viewvc/llvm-project?rev=52492&view=rev Log: The inline keyword goes before the return type. This fixes a compiler warning. Modified: llvm/trunk/include/llvm/ParameterAttributes.h Modified: llvm/trunk/include/llvm/ParameterAttributes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ParameterAttributes.h?rev=52492&r1=52491&r2=52492&view=diff ============================================================================== --- llvm/trunk/include/llvm/ParameterAttributes.h (original) +++ llvm/trunk/include/llvm/ParameterAttributes.h Thu Jun 19 11:16:06 2008 @@ -68,7 +68,7 @@ /// This turns an int alignment (a power of 2, normally) into the /// form used internally in ParameterAttributes. -ParamAttr::Attributes inline constructAlignmentFromInt(unsigned i) { +inline ParamAttr::Attributes constructAlignmentFromInt(unsigned i) { return (i << 16); } From m.kooijman at student.utwente.nl Thu Jun 19 10:56:22 2008 From: m.kooijman at student.utwente.nl (Matthijs Kooijman) Date: Thu, 19 Jun 2008 17:56:22 +0200 Subject: [llvm-commits] Dead argument elimination rewrite In-Reply-To: <01FEB911-9233-424C-9242-091FC0E135DC@apple.com> References: <20080616153738.GN2636@katherina.student.utwente.nl> <20080617084400.GC16202@katherina.student.utwente.nl> <01FEB911-9233-424C-9242-091FC0E135DC@apple.com> Message-ID: <20080619155622.GA3816@katherina.student.utwente.nl> > Ok. Would you mind taking a look at timings on > MultiSource/Applications/kimwitu++ also? Are you particularly interested in timings? It seems that this testcase actually fails to compile due to some older bug. I just tested this with the old DAE code, which also shows problems (but a somewhat different problem it seems). Anyway, the problem is the ExtraArgHack. This code makes sure that a vararg will never have all of its arguments removed by inserting a dummy argument if all if its arguments are dead. According to the comments, this is to make cbe happy. However, the code would also change vararg functions that had no parameters to start with. In the old code this would also happen if the return value was dead, in the new code this would happen on every function (including externals..). I've now modified the code to only apply the extraarghack on functions that were not already argumentless, there is a small chance of this breaking cbe output for bc files containing argumentless vararg functions (but that was the same for the old code, with the exception of those functions with dead return values). Also, I've added a quick return path to RemoveStuffFromFunction for external functions (that saves iterating all arguments and return values, which are by definition live, only to find that the new function type would be the same as the old). As for the timings, IIRC (I'm away from work atm) the fixed version runs just as fast as the original code. > When DAE creates a new function, it inserts the function into the list in > the position of the old function, so as far as I can tell DAE shouldn't > ever end up calling RemoveDeadStuffFromFunction on one of the new functions. Ah right, I missed that detail when I copied that part of the old code :-) I've updated this. Gr. Matthijs From resistor at mac.com Thu Jun 19 12:15:58 2008 From: resistor at mac.com (Owen Anderson) Date: Thu, 19 Jun 2008 17:15:58 -0000 Subject: [llvm-commits] [llvm] r52493 - /llvm/trunk/include/llvm/Instructions.h Message-ID: <200806191715.m5JHFwfW002268@zion.cs.uiuc.edu> Author: resistor Date: Thu Jun 19 12:15:57 2008 New Revision: 52493 URL: http://llvm.org/viewvc/llvm-project?rev=52493&view=rev Log: Add an idx_iterator to the insertvalue and extractvalue instructions. Modified: llvm/trunk/include/llvm/Instructions.h Modified: llvm/trunk/include/llvm/Instructions.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Instructions.h?rev=52493&r1=52492&r2=52493&view=diff ============================================================================== --- llvm/trunk/include/llvm/Instructions.h (original) +++ llvm/trunk/include/llvm/Instructions.h Thu Jun 19 12:15:57 2008 @@ -1586,8 +1586,9 @@ } static const Type *getIndexedType(const Type *Ptr, unsigned Idx); - inline const unsigned *idx_begin() const { return Indices.begin(); } - inline const unsigned *idx_end() const { return Indices.end(); } + typedef const unsigned* idx_iterator; + inline idx_iterator idx_begin() const { return Indices.begin(); } + inline idx_iterator idx_end() const { return Indices.end(); } Value *getAggregateOperand() { return getOperand(0); @@ -1747,8 +1748,9 @@ return reinterpret_cast(Instruction::getType()); } - inline const unsigned *idx_begin() const { return Indices.begin(); } - inline const unsigned *idx_end() const { return Indices.end(); } + typedef const unsigned* idx_iterator; + inline idx_iterator idx_begin() const { return Indices.begin(); } + inline idx_iterator idx_end() const { return Indices.end(); } Value *getAggregateOperand() { return getOperand(0); From gohman at apple.com Thu Jun 19 12:18:39 2008 From: gohman at apple.com (Dan Gohman) Date: Thu, 19 Jun 2008 17:18:39 -0000 Subject: [llvm-commits] [llvm] r52494 - /llvm/trunk/lib/Transforms/Utils/DemoteRegToStack.cpp Message-ID: <200806191718.m5JHIdMq002523@zion.cs.uiuc.edu> Author: djg Date: Thu Jun 19 12:18:39 2008 New Revision: 52494 URL: http://llvm.org/viewvc/llvm-project?rev=52494&view=rev Log: Delete dead code. Modified: llvm/trunk/lib/Transforms/Utils/DemoteRegToStack.cpp Modified: llvm/trunk/lib/Transforms/Utils/DemoteRegToStack.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/DemoteRegToStack.cpp?rev=52494&r1=52493&r2=52494&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Utils/DemoteRegToStack.cpp (original) +++ llvm/trunk/lib/Transforms/Utils/DemoteRegToStack.cpp Thu Jun 19 12:18:39 2008 @@ -134,10 +134,6 @@ } // Insert load in place of the phi and replace all uses. - BasicBlock::iterator InsertPt; - for (InsertPt = P->getParent()->getInstList().begin(); - isa(InsertPt); ++InsertPt) - ; /*noop */ Value *V = new LoadInst(Slot, P->getName()+".reload", P); P->replaceAllUsesWith(V); From gohman at apple.com Thu Jun 19 12:22:30 2008 From: gohman at apple.com (Dan Gohman) Date: Thu, 19 Jun 2008 17:22:30 -0000 Subject: [llvm-commits] [llvm] r52495 - /llvm/trunk/lib/CodeGen/BranchFolding.cpp Message-ID: <200806191722.m5JHMUMp002757@zion.cs.uiuc.edu> Author: djg Date: Thu Jun 19 12:22:29 2008 New Revision: 52495 URL: http://llvm.org/viewvc/llvm-project?rev=52495&view=rev Log: Use the transferSuccessors helper function. Modified: llvm/trunk/lib/CodeGen/BranchFolding.cpp Modified: llvm/trunk/lib/CodeGen/BranchFolding.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/BranchFolding.cpp?rev=52495&r1=52494&r2=52495&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/BranchFolding.cpp (original) +++ llvm/trunk/lib/CodeGen/BranchFolding.cpp Thu Jun 19 12:22:29 2008 @@ -381,11 +381,7 @@ CurMBB.getParent()->getBasicBlockList().insert(++MBBI, NewMBB); // Move all the successors of this block to the specified block. - while (!CurMBB.succ_empty()) { - MachineBasicBlock *S = *(CurMBB.succ_end()-1); - NewMBB->addSuccessor(S); - CurMBB.removeSuccessor(S); - } + NewMBB->transferSuccessors(&CurMBB); // Add an edge from CurMBB to NewMBB for the fall-through. CurMBB.addSuccessor(NewMBB); From resistor at mac.com Thu Jun 19 12:25:39 2008 From: resistor at mac.com (Owen Anderson) Date: Thu, 19 Jun 2008 17:25:39 -0000 Subject: [llvm-commits] [llvm] r52496 - /llvm/trunk/lib/Transforms/Scalar/GVN.cpp Message-ID: <200806191725.m5JHPdQE002851@zion.cs.uiuc.edu> Author: resistor Date: Thu Jun 19 12:25:39 2008 New Revision: 52496 URL: http://llvm.org/viewvc/llvm-project?rev=52496&view=rev Log: Revert support for insertvalue and extractvalue instructions for the moment. GVN expects that all inputs which to an instruction fall somewhere in the value hierarchy, which isn't true for these. Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=52496&r1=52495&r2=52496&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Thu Jun 19 12:25:39 2008 @@ -59,7 +59,7 @@ SHUFFLE, SELECT, TRUNC, ZEXT, SEXT, FPTOUI, FPTOSI, UITOFP, SITOFP, FPTRUNC, FPEXT, PTRTOINT, INTTOPTR, BITCAST, GEP, CALL, CONSTANT, - EXTRACTVALUE, INSERTVALUE, EMPTY, TOMBSTONE }; + EMPTY, TOMBSTONE }; ExpressionOpcode opcode; const Type* type; @@ -150,8 +150,6 @@ Expression create_expression(GetElementPtrInst* G); Expression create_expression(CallInst* C); Expression create_expression(Constant* C); - Expression create_expression(InsertValueInst* I); - Expression create_expression(ExtractValueInst* I); public: ValueTable() : nextValueNumber(1) { } uint32_t lookup_or_add(Value* V); @@ -286,40 +284,6 @@ } } -Expression ValueTable::create_expression(InsertValueInst* I) { - Expression e; - - e.type = I->getType(); - e.firstVN = lookup_or_add(I->getOperand(0)); - e.secondVN = lookup_or_add(I->getOperand(1)); - e.thirdVN = 0; - e.function = 0; - e.opcode = Expression::INSERTVALUE; - - for (InsertValueInst::op_iterator OI = I->op_begin()+2, - OE = I->op_end(); OI != OE; ++OI) - e.varargs.push_back(lookup_or_add(I)); - - return e; -} - -Expression ValueTable::create_expression(ExtractValueInst* I) { - Expression e; - - e.type = I->getType(); - e.firstVN = lookup_or_add(I->getOperand(0)); - e.secondVN = lookup_or_add(I->getOperand(1)); - e.thirdVN = 0; - e.function = 0; - e.opcode = Expression::EXTRACTVALUE; - - for (InsertValueInst::op_iterator OI = I->op_begin()+2, - OE = I->op_end(); OI != OE; ++OI) - e.varargs.push_back(lookup_or_add(I)); - - return e; -} - Expression ValueTable::create_expression(CallInst* C) { Expression e; @@ -577,32 +541,6 @@ valueNumbering.insert(std::make_pair(V, nextValueNumber)); return nextValueNumber++; } - } else if (InsertValueInst* II = dyn_cast(V)) { - Expression e = create_expression(II); - - DenseMap::iterator EI = expressionNumbering.find(e); - if (EI != expressionNumbering.end()) { - valueNumbering.insert(std::make_pair(V, EI->second)); - return EI->second; - } else { - expressionNumbering.insert(std::make_pair(e, nextValueNumber)); - valueNumbering.insert(std::make_pair(V, nextValueNumber)); - - return nextValueNumber++; - } - } else if (ExtractValueInst* E = dyn_cast(V)) { - Expression e = create_expression(E); - - DenseMap::iterator EI = expressionNumbering.find(e); - if (EI != expressionNumbering.end()) { - valueNumbering.insert(std::make_pair(V, EI->second)); - return EI->second; - } else { - expressionNumbering.insert(std::make_pair(e, nextValueNumber)); - valueNumbering.insert(std::make_pair(V, nextValueNumber)); - - return nextValueNumber++; - } } else if (BinaryOperator* BO = dyn_cast(V)) { Expression e = create_expression(BO); From gohman at apple.com Thu Jun 19 12:37:26 2008 From: gohman at apple.com (Dan Gohman) Date: Thu, 19 Jun 2008 17:37:26 -0000 Subject: [llvm-commits] [llvm] r52497 - /llvm/trunk/lib/Transforms/Scalar/LoopRotation.cpp Message-ID: <200806191737.m5JHbQZp003172@zion.cs.uiuc.edu> Author: djg Date: Thu Jun 19 12:37:25 2008 New Revision: 52497 URL: http://llvm.org/viewvc/llvm-project?rev=52497&view=rev Log: Avoid using BasicBlock::getInstList directly in a few places. Modified: llvm/trunk/lib/Transforms/Scalar/LoopRotation.cpp Modified: llvm/trunk/lib/Transforms/Scalar/LoopRotation.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopRotation.cpp?rev=52497&r1=52496&r2=52497&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopRotation.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopRotation.cpp Thu Jun 19 12:37:25 2008 @@ -164,7 +164,7 @@ // Check size of original header and reject // loop if it is very big. - if (OrigHeader->getInstList().size() > MAX_HEADER_SIZE) + if (OrigHeader->size() > MAX_HEADER_SIZE) return false; // Now, this loop is suitable for rotation. @@ -208,10 +208,10 @@ // Create new PHI node with two incoming values for NewHeader. // One incoming value is from OrigLatch (through OrigHeader) and // second incoming value is from original pre-header. - PHINode *NH = PHINode::Create(In->getType(), In->getName()); + PHINode *NH = PHINode::Create(In->getType(), In->getName(), + NewHeader->begin()); NH->addIncoming(PN->getIncomingValueForBlock(OrigLatch), OrigHeader); NH->addIncoming(NPV, OrigPreHeader); - NewHeader->getInstList().push_front(NH); // "In" can be replaced by NH at various places. LoopHeaderInfo.push_back(RenameData(In, NPV, NH)); @@ -272,10 +272,10 @@ } } } else { - PHINode *PN = PHINode::Create(In->getType(), In->getName()); + PHINode *PN = PHINode::Create(In->getType(), In->getName(), + NewHeader->begin()); PN->addIncoming(In, OrigHeader); PN->addIncoming(C, OrigPreHeader); - NewHeader->getInstList().push_front(PN); NewHeaderReplacement = PN; } } @@ -358,10 +358,10 @@ } else { // Used outside Exit block. Create a new PHI node from exit block // to receive value from ne new header ane pre header. - PHINode *PN = PHINode::Create(U->getType(), U->getName()); + PHINode *PN = PHINode::Create(U->getType(), U->getName(), + Exit->begin()); PN->addIncoming(ILoopHeaderInfo.PreHeader, OrigPreHeader); PN->addIncoming(OldPhi, OrigHeader); - Exit->getInstList().push_front(PN); U->replaceUsesOfWith(OldPhi, PN); } } @@ -583,14 +583,15 @@ BasicBlock::iterator I = Exit->begin(), E = Exit->end(); PHINode *PN = NULL; for (; (PN = dyn_cast(I)); ++I) { - PHINode *NewPN = PHINode::Create(PN->getType(), PN->getName()); unsigned N = PN->getNumIncomingValues(); for (unsigned index = 0; index < N; ++index) if (PN->getIncomingBlock(index) == NExit) { + PHINode *NewPN = PHINode::Create(PN->getType(), PN->getName(), + NExit->begin()); NewPN->addIncoming(PN->getIncomingValue(index), L->getLoopLatch()); PN->setIncomingValue(index, NewPN); PN->setIncomingBlock(index, NExit); - NExit->getInstList().push_front(NewPN); + break; } } From gohman at apple.com Thu Jun 19 12:47:47 2008 From: gohman at apple.com (Dan Gohman) Date: Thu, 19 Jun 2008 17:47:47 -0000 Subject: [llvm-commits] [llvm] r52498 - /llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200806191747.m5JHllMU003473@zion.cs.uiuc.edu> Author: djg Date: Thu Jun 19 12:47:47 2008 New Revision: 52498 URL: http://llvm.org/viewvc/llvm-project?rev=52498&view=rev Log: Use Instruction::moveBefore instead of manipulating the instruction list directly. Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=52498&r1=52497&r2=52498&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Thu Jun 19 12:47:47 2008 @@ -1672,9 +1672,8 @@ } Root.replaceAllUsesWith(TmpLHSI); // Users now use TmpLHSI TmpLHSI->setOperand(1, &Root); // TmpLHSI now uses the root - TmpLHSI->getParent()->getInstList().remove(TmpLHSI); BasicBlock::iterator ARI = &Root; ++ARI; - BB->getInstList().insert(ARI, TmpLHSI); // Move TmpLHSI to after Root + TmpLHSI->moveBefore(ARI); // Move TmpLHSI to after Root ARI = Root; // Now propagate the ExtraOperand down the chain of instructions until we @@ -1683,8 +1682,7 @@ Instruction *NextLHSI = cast(TmpLHSI->getOperand(0)); // Move the instruction to immediately before the chain we are // constructing to avoid breaking dominance properties. - NextLHSI->getParent()->getInstList().remove(NextLHSI); - BB->getInstList().insert(ARI, NextLHSI); + NextLHSI->moveBefore(ARI); ARI = NextLHSI; Value *NextOp = NextLHSI->getOperand(1); From resistor at mac.com Thu Jun 19 12:53:26 2008 From: resistor at mac.com (Owen Anderson) Date: Thu, 19 Jun 2008 17:53:26 -0000 Subject: [llvm-commits] [llvm] r52499 - /llvm/trunk/lib/Transforms/Scalar/GVN.cpp Message-ID: <200806191753.m5JHrQiO003634@zion.cs.uiuc.edu> Author: resistor Date: Thu Jun 19 12:53:26 2008 New Revision: 52499 URL: http://llvm.org/viewvc/llvm-project?rev=52499&view=rev Log: Be sure to remove values from the value numbering table after we delete them. This fixes a failure on povray. Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=52499&r1=52498&r2=52499&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Thu Jun 19 12:53:26 2008 @@ -1234,6 +1234,7 @@ UUI->second = Phi; BI->replaceAllUsesWith(Phi); + VN.erase(BI); Instruction* erase = BI; BI++; From gohman at apple.com Thu Jun 19 12:53:32 2008 From: gohman at apple.com (Dan Gohman) Date: Thu, 19 Jun 2008 17:53:32 -0000 Subject: [llvm-commits] [llvm] r52500 - /llvm/trunk/lib/Transforms/IPO/LowerSetJmp.cpp Message-ID: <200806191753.m5JHrWoT003649@zion.cs.uiuc.edu> Author: djg Date: Thu Jun 19 12:53:32 2008 New Revision: 52500 URL: http://llvm.org/viewvc/llvm-project?rev=52500&view=rev Log: Use the common API for adding instructions to basic blocks instead of using BasicBlock::getInstList. Modified: llvm/trunk/lib/Transforms/IPO/LowerSetJmp.cpp Modified: llvm/trunk/lib/Transforms/IPO/LowerSetJmp.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/LowerSetJmp.cpp?rev=52500&r1=52499&r2=52500&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/IPO/LowerSetJmp.cpp (original) +++ llvm/trunk/lib/Transforms/IPO/LowerSetJmp.cpp Thu Jun 19 12:53:32 2008 @@ -341,29 +341,25 @@ if (SwitchValMap[Func].first) return SwitchValMap[Func]; BasicBlock* LongJmpPre = BasicBlock::Create("LongJmpBlkPre", Func); - BasicBlock::InstListType& LongJmpPreIL = LongJmpPre->getInstList(); // Keep track of the preliminary basic block for some of the other // transformations. PrelimBBMap[Func] = LongJmpPre; // Grab the exception. - CallInst* Cond = CallInst::Create(IsLJException, "IsLJExcept"); - LongJmpPreIL.push_back(Cond); + CallInst* Cond = CallInst::Create(IsLJException, "IsLJExcept", LongJmpPre); // The "decision basic block" gets the number associated with the // setjmp call returning to switch on and the value returned by // longjmp. BasicBlock* DecisionBB = BasicBlock::Create("LJDecisionBB", Func); - BasicBlock::InstListType& DecisionBBIL = DecisionBB->getInstList(); BranchInst::Create(DecisionBB, Rethrow, Cond, LongJmpPre); // Fill in the "decision" basic block. - CallInst* LJVal = CallInst::Create(GetLJValue, "LJVal"); - DecisionBBIL.push_back(LJVal); - CallInst* SJNum = CallInst::Create(TryCatchLJ, GetSetJmpMap(Func), "SJNum"); - DecisionBBIL.push_back(SJNum); + CallInst* LJVal = CallInst::Create(GetLJValue, "LJVal", DecisionBB); + CallInst* SJNum = CallInst::Create(TryCatchLJ, GetSetJmpMap(Func), "SJNum", + DecisionBB); SwitchInst* SI = SwitchInst::Create(SJNum, Rethrow, 0, DecisionBB); return SwitchValMap[Func] = SwitchValuePair(SI, LJVal); @@ -508,12 +504,11 @@ Function* Func = BB->getParent(); BasicBlock* NewExceptBB = BasicBlock::Create("InvokeExcept", Func); - BasicBlock::InstListType& InstList = NewExceptBB->getInstList(); // If this is a longjmp exception, then branch to the preliminary BB of // the longjmp exception handling. Otherwise, go to the old exception. - CallInst* IsLJExcept = CallInst::Create(IsLJException, "IsLJExcept"); - InstList.push_back(IsLJExcept); + CallInst* IsLJExcept = CallInst::Create(IsLJException, "IsLJExcept", + NewExceptBB); BranchInst::Create(PrelimBBMap[Func], ExceptBB, IsLJExcept, NewExceptBB); From isanbard at gmail.com Thu Jun 19 13:00:44 2008 From: isanbard at gmail.com (Bill Wendling) Date: Thu, 19 Jun 2008 18:00:44 -0000 Subject: [llvm-commits] [llvm] r52502 - /llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200806191800.m5JI0iTD003852@zion.cs.uiuc.edu> Author: void Date: Thu Jun 19 13:00:44 2008 New Revision: 52502 URL: http://llvm.org/viewvc/llvm-project?rev=52502&view=rev Log: Remove dead code causing a warning. Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=52502&r1=52501&r2=52502&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Thu Jun 19 13:00:44 2008 @@ -1655,8 +1655,6 @@ // If the functor wants to apply the optimization to the RHS of LHSI, // reassociate the expression from ((? op A) op B) to (? op (A op B)) if (ShouldApply) { - BasicBlock *BB = Root.getParent(); - // Now all of the instructions are in the current basic block, go ahead // and perform the reassociation. Instruction *TmpLHSI = cast(Root.getOperand(0)); From espindola at google.com Thu Jun 19 14:06:51 2008 From: espindola at google.com (Rafael Espindola) Date: Thu, 19 Jun 2008 15:06:51 -0400 Subject: [llvm-commits] [llvm-gcc][patch] Use LDFLAGS from configure In-Reply-To: <38a0d8450806191201q40baa907v21db90192331235c@mail.gmail.com> References: <38a0d8450806191201q40baa907v21db90192331235c@mail.gmail.com> Message-ID: <38a0d8450806191206y6b5de2fex56d18e2a63872afd@mail.gmail.com> Correct list now. Sorry. 2008/6/19 Rafael Espindola : > The attached patch permits setting the LDFLAGS variable in the call to > configure. This is the behavior of configure on gcc trunk. Not sure > why llvm-gcc is different. > > This is necessary for building llvm-gcc in cases where some libraries > are in strange places: > > CPPFLAGS="-I/foo/include" LDFLAGS="-L/foo/lib" configure .... > > Cheers, > -- > Rafael Avila de Espindola > > Google Ireland Ltd. > Gordon House > Barrow Street > Dublin 4 > Ireland > > Registered in Dublin, Ireland > Registration Number: 368047 > -- Rafael Avila de Espindola Google Ireland Ltd. Gordon House Barrow Street Dublin 4 Ireland Registered in Dublin, Ireland Registration Number: 368047 From resistor at mac.com Thu Jun 19 14:54:19 2008 From: resistor at mac.com (Owen Anderson) Date: Thu, 19 Jun 2008 19:54:19 -0000 Subject: [llvm-commits] [llvm] r52505 - /llvm/trunk/lib/Transforms/Scalar/GVN.cpp Message-ID: <200806191954.m5JJsJkO007751@zion.cs.uiuc.edu> Author: resistor Date: Thu Jun 19 14:54:19 2008 New Revision: 52505 URL: http://llvm.org/viewvc/llvm-project?rev=52505&view=rev Log: PRE requires that critical edges be split. Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=52505&r1=52504&r2=52505&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Thu Jun 19 14:54:19 2008 @@ -34,6 +34,7 @@ #include "llvm/Support/CFG.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" using namespace llvm; STATISTIC(NumGVNInstr, "Number of instructions deleted"); @@ -1128,6 +1129,7 @@ /// control flow patterns and attempts to perform simple PRE at the join point. bool GVN::performPRE(Function& F) { bool changed = false; + SmallVector, 4> toSplit; for (df_iterator DI = df_begin(&F.getEntryBlock()), DE = df_end(&F.getEntryBlock()); DI != DE; ++DI) { BasicBlock* CurrentBlock = *DI; @@ -1179,6 +1181,24 @@ continue; } + // We can't do PRE safely on a critical edge, so instead we schedule + // the edge to be split and perform the PRE the next time we iterate + // on the function. + unsigned succNum = 0; + for (unsigned i = 0, e = PREPred->getTerminator()->getNumSuccessors(); + i != e; ++i) + if (PREPred->getTerminator()->getSuccessor(i) == PREPred) { + succNum = i; + break; + } + + if (isCriticalEdge(PREPred->getTerminator(), succNum)) { + toSplit.push_back(std::make_pair(PREPred->getTerminator(), succNum)); + changed = true; + BI++; + continue; + } + // Instantiate the expression the in predecessor that lacked it. // Because we are going top-down through the block, all value numbers // will be available in the predecessor by the time we need them. Any @@ -1244,6 +1264,10 @@ } } + for (SmallVector, 4>::iterator + I = toSplit.begin(), E = toSplit.end(); I != E; ++I) + SplitCriticalEdge(I->first, I->second, this); + return changed; } From resistor at mac.com Thu Jun 19 14:57:25 2008 From: resistor at mac.com (Owen Anderson) Date: Thu, 19 Jun 2008 19:57:25 -0000 Subject: [llvm-commits] [llvm] r52506 - /llvm/trunk/lib/Transforms/Scalar/GVN.cpp Message-ID: <200806191957.m5JJvPZS007845@zion.cs.uiuc.edu> Author: resistor Date: Thu Jun 19 14:57:25 2008 New Revision: 52506 URL: http://llvm.org/viewvc/llvm-project?rev=52506&view=rev Log: Add a hidden -disable-pre flag for testing purposes. This should be removed once benchmarking is completed. Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=52506&r1=52505&r2=52506&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Thu Jun 19 14:57:25 2008 @@ -32,6 +32,7 @@ #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/MemoryDependenceAnalysis.h" #include "llvm/Support/CFG.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" @@ -41,6 +42,9 @@ STATISTIC(NumGVNLoad, "Number of loads deleted"); STATISTIC(NumGVNPRE, "Number of instructions PRE'd"); +static cl::opt DisablePRE("disable-pre", + cl::init(false), cl::Hidden); + //===----------------------------------------------------------------------===// // ValueTable Class //===----------------------------------------------------------------------===// @@ -1285,7 +1289,9 @@ for (df_iterator DI = df_begin(DT.getRootNode()), DE = df_end(DT.getRootNode()); DI != DE; ++DI) changed |= processBlock(*DI); - - changed |= performPRE(F); + + if (!DisablePRE) + changed |= performPRE(F); + return changed; } From gohman at apple.com Thu Jun 19 16:57:17 2008 From: gohman at apple.com (Dan Gohman) Date: Thu, 19 Jun 2008 14:57:17 -0700 Subject: [llvm-commits] Dead argument elimination rewrite In-Reply-To: <20080619155622.GA3816@katherina.student.utwente.nl> References: <20080616153738.GN2636@katherina.student.utwente.nl> <20080617084400.GC16202@katherina.student.utwente.nl> <01FEB911-9233-424C-9242-091FC0E135DC@apple.com> <20080619155622.GA3816@katherina.student.utwente.nl> Message-ID: <01832B5C-3190-4B8D-8DE3-DA0EC96B9258@apple.com> On Jun 19, 2008, at 8:56 AM, Matthijs Kooijman wrote: >> Ok. Would you mind taking a look at timings on >> MultiSource/Applications/kimwitu++ also? > Are you particularly interested in timings? It seems that this > testcase > actually fails to compile due to some older bug. I just tested this > with the > old DAE code, which also shows problems (but a somewhat different > problem it > seems). > > > Anyway, the problem is the ExtraArgHack. This code makes sure that a > vararg > will never have all of its arguments removed by inserting a dummy > argument if > all if its arguments are dead. According to the comments, this is to > make cbe > happy. However, the code would also change vararg functions that had > no > parameters to start with. > > In the old code this would also happen if the return value was dead, > in the > new code this would happen on every function (including > externals..). I've now > modified the code to only apply the extraarghack on functions that > were not > already argumentless, there is a small chance of this breaking cbe > output for > bc files containing argumentless vararg functions (but that was the > same for > the old code, with the exception of those functions with dead return > values). Ok. > > > Also, I've added a quick return path to RemoveStuffFromFunction for > external > functions (that saves iterating all arguments and return values, > which are by > definition live, only to find that the new function type would be > the same as > the old). > > As for the timings, IIRC (I'm away from work atm) the fixed version > runs just > as fast as the original code. Ok. I mainly just wanted to get a sense of compile time on some non-trivial real-world code. The STL associative containers have a mixed reputation around here.. Thanks, Dan From evan.cheng at apple.com Thu Jun 19 17:01:11 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Thu, 19 Jun 2008 22:01:11 -0000 Subject: [llvm-commits] [llvm] r52508 - in /llvm/trunk: lib/CodeGen/SelectionDAG/LegalizeDAG.cpp test/CodeGen/PowerPC/2008-06-19-LegalizerCrash.ll Message-ID: <200806192201.m5JM1BwZ011284@zion.cs.uiuc.edu> Author: evancheng Date: Thu Jun 19 17:01:11 2008 New Revision: 52508 URL: http://llvm.org/viewvc/llvm-project?rev=52508&view=rev Log: ISD::UNDEF should be expanded recursively / iteratively. Added: llvm/trunk/test/CodeGen/PowerPC/2008-06-19-LegalizerCrash.ll Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp?rev=52508&r1=52507&r2=52508&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Thu Jun 19 17:01:11 2008 @@ -5832,7 +5832,6 @@ Lo = ExpandEXTRACT_VECTOR_ELT(Op); return ExpandOp(Lo, Lo, Hi); case ISD::UNDEF: - NVT = TLI.getTypeToExpandTo(VT); Lo = DAG.getNode(ISD::UNDEF, NVT); Hi = DAG.getNode(ISD::UNDEF, NVT); break; Added: llvm/trunk/test/CodeGen/PowerPC/2008-06-19-LegalizerCrash.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/2008-06-19-LegalizerCrash.ll?rev=52508&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/PowerPC/2008-06-19-LegalizerCrash.ll (added) +++ llvm/trunk/test/CodeGen/PowerPC/2008-06-19-LegalizerCrash.ll Thu Jun 19 17:01:11 2008 @@ -0,0 +1,6 @@ +; RUN: llvm-as < %s | llc -march=ppc32 + +define void @t() nounwind { + call void null( ppc_fp128 undef ) + unreachable +} From kremenek at apple.com Thu Jun 19 18:05:07 2008 From: kremenek at apple.com (Ted Kremenek) Date: Thu, 19 Jun 2008 23:05:07 -0000 Subject: [llvm-commits] [llvm] r52509 - /llvm/tags/checker/checker-40/ Message-ID: <200806192305.m5JN575c013200@zion.cs.uiuc.edu> Author: kremenek Date: Thu Jun 19 18:05:07 2008 New Revision: 52509 URL: http://llvm.org/viewvc/llvm-project?rev=52509&view=rev Log: Tagging checker-40. Added: llvm/tags/checker/checker-40/ - copied from r52508, llvm/trunk/ From rafael.espindola at gmail.com Thu Jun 19 18:30:12 2008 From: rafael.espindola at gmail.com (Rafael Espindola) Date: Thu, 19 Jun 2008 23:30:12 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r52513 - /llvm-gcc-4.2/trunk/Makefile.in Message-ID: <200806192330.m5JNUDAn014019@zion.cs.uiuc.edu> Author: rafael Date: Thu Jun 19 18:30:12 2008 New Revision: 52513 URL: http://llvm.org/viewvc/llvm-project?rev=52513&view=rev Log: use LDFLAGS passed to configure Modified: llvm-gcc-4.2/trunk/Makefile.in Modified: llvm-gcc-4.2/trunk/Makefile.in URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/Makefile.in?rev=52513&r1=52512&r2=52513&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/Makefile.in (original) +++ llvm-gcc-4.2/trunk/Makefile.in Thu Jun 19 18:30:12 2008 @@ -288,7 +288,7 @@ WINDRES = @WINDRES@ CFLAGS = @CFLAGS@ -LDFLAGS = +LDFLAGS = @LDFLAGS@ LIBCFLAGS = $(CFLAGS) CXXFLAGS = @CXXFLAGS@ LIBCXXFLAGS = $(CXXFLAGS) -fno-implicit-templates From gohman at apple.com Thu Jun 19 19:47:44 2008 From: gohman at apple.com (Dan Gohman) Date: Fri, 20 Jun 2008 00:47:44 -0000 Subject: [llvm-commits] [llvm] r52514 - /llvm/trunk/lib/VMCore/Instructions.cpp Message-ID: <200806200047.m5K0lioT016088@zion.cs.uiuc.edu> Author: djg Date: Thu Jun 19 19:47:44 2008 New Revision: 52514 URL: http://llvm.org/viewvc/llvm-project?rev=52514&view=rev Log: Simplify this code. Thanks Chris! Modified: llvm/trunk/lib/VMCore/Instructions.cpp Modified: llvm/trunk/lib/VMCore/Instructions.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Instructions.cpp?rev=52514&r1=52513&r2=52514&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/Instructions.cpp (original) +++ llvm/trunk/lib/VMCore/Instructions.cpp Thu Jun 19 19:47:44 2008 @@ -1463,9 +1463,8 @@ } const Type* ExtractValueInst::getIndexedType(const Type *Agg, - const unsigned Idx) { - const unsigned Idxs[1] = { Idx }; - return getIndexedType(Agg, &Idxs[0], 1); + unsigned Idx) { + return getIndexedType(Agg, &Idx, 1); } ExtractValueInst::ExtractValueInst(Value *Agg, From gohman at apple.com Thu Jun 19 19:49:21 2008 From: gohman at apple.com (Dan Gohman) Date: Fri, 20 Jun 2008 00:49:21 -0000 Subject: [llvm-commits] [llvm] r52515 - /llvm/trunk/include/llvm/Analysis/ValueTracking.h Message-ID: <200806200049.m5K0nLW3016146@zion.cs.uiuc.edu> Author: djg Date: Thu Jun 19 19:49:21 2008 New Revision: 52515 URL: http://llvm.org/viewvc/llvm-project?rev=52515&view=rev Log: It's invalid to take the one-past-the-end address of a non-array object. Modified: llvm/trunk/include/llvm/Analysis/ValueTracking.h Modified: llvm/trunk/include/llvm/Analysis/ValueTracking.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ValueTracking.h?rev=52515&r1=52514&r2=52515&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/ValueTracking.h (original) +++ llvm/trunk/include/llvm/Analysis/ValueTracking.h Thu Jun 19 19:49:21 2008 @@ -67,7 +67,8 @@ /// only. inline Value *FindInsertedValue(Value *V, const unsigned Idx, Instruction *InsertBefore = 0) { - return FindInsertedValue(V, &Idx, &Idx + 1, InsertBefore); + const unsigned Idxs[1] = { Idx }; + return FindInsertedValue(V, &Idxs[0], &Idxs[1], InsertBefore); } } // end namespace llvm From gohman at apple.com Thu Jun 19 19:53:00 2008 From: gohman at apple.com (Dan Gohman) Date: Fri, 20 Jun 2008 00:53:00 -0000 Subject: [llvm-commits] [llvm] r52516 - /llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Message-ID: <200806200053.m5K0r1nq016334@zion.cs.uiuc.edu> Author: djg Date: Thu Jun 19 19:53:00 2008 New Revision: 52516 URL: http://llvm.org/viewvc/llvm-project?rev=52516&view=rev Log: Simplify the ComputeLinearIndex logic and fix a few bugs. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp?rev=52516&r1=52515&r2=52516&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Thu Jun 19 19:53:00 2008 @@ -100,37 +100,31 @@ const unsigned *IndicesEnd, unsigned CurIndex = 0) { // Base case: We're done. - if (Indices == IndicesEnd) + if (Indices && Indices == IndicesEnd) return CurIndex; - // Otherwise we need to recurse. A non-negative value is used to - // indicate the final result value; a negative value carries the - // complemented position to continue the search. - CurIndex = ~CurIndex; - // Given a struct type, recursively traverse the elements. if (const StructType *STy = dyn_cast(Ty)) { - for (StructType::element_iterator EI = STy->element_begin(), + for (StructType::element_iterator EB = STy->element_begin(), + EI = EB, EE = STy->element_end(); EI != EE; ++EI) { - CurIndex = ComputeLinearIndex(TLI, *EI, Indices+1, IndicesEnd, - ~CurIndex); - if ((int)CurIndex >= 0) - return CurIndex; + if (Indices && *Indices == unsigned(EI - EB)) + return ComputeLinearIndex(TLI, *EI, Indices+1, IndicesEnd, CurIndex); + CurIndex = ComputeLinearIndex(TLI, *EI, 0, 0, CurIndex); } } // Given an array type, recursively traverse the elements. else if (const ArrayType *ATy = dyn_cast(Ty)) { const Type *EltTy = ATy->getElementType(); for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) { - CurIndex = ComputeLinearIndex(TLI, EltTy, Indices+1, IndicesEnd, - ~CurIndex); - if ((int)CurIndex >= 0) - return CurIndex; + if (Indices && *Indices == i) + return ComputeLinearIndex(TLI, EltTy, Indices+1, IndicesEnd, CurIndex); + CurIndex = ComputeLinearIndex(TLI, EltTy, 0, 0, CurIndex); } } // We haven't found the type we're looking for, so keep searching. - return CurIndex; + return CurIndex + 1; } /// ComputeValueVTs - Given an LLVM IR type, compute a sequence of From gohman at apple.com Thu Jun 19 19:54:19 2008 From: gohman at apple.com (Dan Gohman) Date: Fri, 20 Jun 2008 00:54:19 -0000 Subject: [llvm-commits] [llvm] r52517 - /llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Message-ID: <200806200054.m5K0sJE4016382@zion.cs.uiuc.edu> Author: djg Date: Thu Jun 19 19:54:19 2008 New Revision: 52517 URL: http://llvm.org/viewvc/llvm-project?rev=52517&view=rev Log: Fix the index calculations for the extractvalue lowering code. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp?rev=52517&r1=52516&r2=52517&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Thu Jun 19 19:54:19 2008 @@ -2739,8 +2739,8 @@ // Copy out the selected value(s). for (unsigned i = LinearIndex; i != LinearIndex + NumValValues; ++i) Values[i - LinearIndex] = - OutOfUndef ? DAG.getNode(ISD::UNDEF, Agg.Val->getValueType(i)) : - SDOperand(Agg.Val, Agg.ResNo + i - LinearIndex); + OutOfUndef ? DAG.getNode(ISD::UNDEF, Agg.Val->getValueType(Agg.ResNo + i)) : + SDOperand(Agg.Val, Agg.ResNo + i); setValue(&I, DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(&ValValueVTs[0], NumValValues), From evan.cheng at apple.com Thu Jun 19 20:01:07 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Fri, 20 Jun 2008 01:01:07 -0000 Subject: [llvm-commits] [llvm] r52518 - /llvm/trunk/lib/Transforms/Scalar/GVN.cpp Message-ID: <200806200101.m5K117IN016568@zion.cs.uiuc.edu> Author: evancheng Date: Thu Jun 19 20:01:07 2008 New Revision: 52518 URL: http://llvm.org/viewvc/llvm-project?rev=52518&view=rev Log: Disable PRE for now. It seems to be breaking llvm-gcc bootstrapping. Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=52518&r1=52517&r2=52518&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Thu Jun 19 20:01:07 2008 @@ -42,7 +42,7 @@ STATISTIC(NumGVNLoad, "Number of loads deleted"); STATISTIC(NumGVNPRE, "Number of instructions PRE'd"); -static cl::opt DisablePRE("disable-pre", +static cl::opt EnablePRE("enable-pre", cl::init(false), cl::Hidden); //===----------------------------------------------------------------------===// @@ -1290,7 +1290,7 @@ DE = df_end(DT.getRootNode()); DI != DE; ++DI) changed |= processBlock(*DI); - if (!DisablePRE) + if (!EnablePRE) changed |= performPRE(F); return changed; From gohman at apple.com Thu Jun 19 20:03:44 2008 From: gohman at apple.com (Dan Gohman) Date: Fri, 20 Jun 2008 01:03:44 -0000 Subject: [llvm-commits] [llvm] r52519 - /llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp Message-ID: <200806200103.m5K13ixZ016641@zion.cs.uiuc.edu> Author: djg Date: Thu Jun 19 20:03:44 2008 New Revision: 52519 URL: http://llvm.org/viewvc/llvm-project?rev=52519&view=rev Log: Teach InlineFunction how to differentiate between multiple-value return statements and aggregate returns so that it handles both correctly. Modified: llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp Modified: llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp?rev=52519&r1=52518&r2=52519&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp (original) +++ llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp Thu Jun 19 20:03:44 2008 @@ -443,8 +443,9 @@ // uses of the returned value. if (!TheCall->use_empty()) { ReturnInst *R = Returns[0]; - if (isa(TheCall->getType())) { - // Multiple return values. + if (isa(TheCall->getType()) && + TheCall->getType() != R->getOperand(0)->getType()) { + // Multiple-value return statements. while (!TheCall->use_empty()) { GetResultInst *GR = cast(TheCall->use_back()); Value *RV = R->getOperand(GR->getIndex()); @@ -509,6 +510,13 @@ // any users of the original call/invoke instruction. const Type *RTy = CalledFunc->getReturnType(); const StructType *STy = dyn_cast(RTy); + + // We do special handling for multiple-value return statements. If this is + // a plain aggregate return, don't do the special handling. + if (!Returns.empty() && Returns[0]->getNumOperands() != 0 && + Returns[0]->getOperand(0)->getType() == STy) + STy = 0; + if (Returns.size() > 1 || STy) { // The PHI node should go at the front of the new basic block to merge all // possible incoming values. From gohman at apple.com Thu Jun 19 20:15:44 2008 From: gohman at apple.com (Dan Gohman) Date: Fri, 20 Jun 2008 01:15:44 -0000 Subject: [llvm-commits] [llvm] r52520 - /llvm/trunk/lib/Transforms/Scalar/SCCP.cpp Message-ID: <200806200115.m5K1FjhV016990@zion.cs.uiuc.edu> Author: djg Date: Thu Jun 19 20:15:44 2008 New Revision: 52520 URL: http://llvm.org/viewvc/llvm-project?rev=52520&view=rev Log: Teach SCCP about insertvalue and extractvalue, and about propagating constants across aggregate return values when insertvalue and extractvalue are used. Modified: llvm/trunk/lib/Transforms/Scalar/SCCP.cpp Modified: llvm/trunk/lib/Transforms/Scalar/SCCP.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SCCP.cpp?rev=52520&r1=52519&r2=52520&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/SCCP.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/SCCP.cpp Thu Jun 19 20:15:44 2008 @@ -29,6 +29,7 @@ #include "llvm/Instructions.h" #include "llvm/Pass.h" #include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Analysis/ValueTracking.h" #include "llvm/Transforms/Utils/Local.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/Compiler.h" @@ -390,6 +391,8 @@ void visitExtractElementInst(ExtractElementInst &I); void visitInsertElementInst(InsertElementInst &I); void visitShuffleVectorInst(ShuffleVectorInst &I); + void visitExtractValueInst(ExtractValueInst &EVI); + void visitInsertValueInst(InsertValueInst &IVI); // Instructions that cannot be folded away... void visitStoreInst (Instruction &I); @@ -630,6 +633,17 @@ if (It == TrackedMultipleRetVals.end()) break; mergeInValue(It->second, F, getValueState(I.getOperand(i))); } + } else if (!TrackedMultipleRetVals.empty() && + I.getNumOperands() == 1 && + isa(I.getOperand(0)->getType())) { + for (unsigned i = 0, e = I.getOperand(0)->getType()->getNumContainedTypes(); + i != e; ++i) { + std::map, LatticeVal>::iterator + It = TrackedMultipleRetVals.find(std::make_pair(F, i)); + if (It == TrackedMultipleRetVals.end()) break; + Value *Val = FindInsertedValue(I.getOperand(0), i); + mergeInValue(It->second, F, getValueState(Val)); + } } } @@ -690,6 +704,75 @@ // handling. } +void SCCPSolver::visitExtractValueInst(ExtractValueInst &EVI) { + Value *Aggr = EVI.getOperand(0); + + // If the operand to the getresult is an undef, the result is undef. + if (isa(Aggr)) + return; + + // Currently only handle single-index extractvalues. + if (EVI.getNumIndices() != 1) { + markOverdefined(&EVI); + return; + } + + Function *F = 0; + if (CallInst *CI = dyn_cast(Aggr)) + F = CI->getCalledFunction(); + else if (InvokeInst *II = dyn_cast(Aggr)) + F = II->getCalledFunction(); + + // TODO: If IPSCCP resolves the callee of this function, we could propagate a + // result back! + if (F == 0 || TrackedMultipleRetVals.empty()) { + markOverdefined(&EVI); + return; + } + + // See if we are tracking the result of the callee. + std::map, LatticeVal>::iterator + It = TrackedMultipleRetVals.find(std::make_pair(F, *EVI.idx_begin())); + + // If not tracking this function (for example, it is a declaration) just move + // to overdefined. + if (It == TrackedMultipleRetVals.end()) { + markOverdefined(&EVI); + return; + } + + // Otherwise, the value will be merged in here as a result of CallSite + // handling. +} + +void SCCPSolver::visitInsertValueInst(InsertValueInst &IVI) { + Value *Aggr = IVI.getOperand(0); + Value *Val = IVI.getOperand(1); + + // If the operand to the getresult is an undef, the result is undef. + if (isa(Aggr)) + return; + + // Currently only handle single-index insertvalues. + if (IVI.getNumIndices() != 1) { + markOverdefined(&IVI); + return; + } + + // See if we are tracking the result of the callee. + Function *F = IVI.getParent()->getParent(); + std::map, LatticeVal>::iterator + It = TrackedMultipleRetVals.find(std::make_pair(F, *IVI.idx_begin())); + + // Merge in the inserted member value. + if (It != TrackedMultipleRetVals.end()) + mergeInValue(It->second, F, getValueState(Val)); + + // Mark the aggregate result of the IVI overdefined; any tracking that we do will + // be done on the individual member values. + markOverdefined(&IVI); +} + void SCCPSolver::visitSelectInst(SelectInst &I) { LatticeVal &CondValue = getValueState(I.getCondition()); if (CondValue.isUndefined()) @@ -1149,17 +1232,11 @@ } // If this is a single/zero retval case, see if we're tracking the function. - const StructType *RetSTy = dyn_cast(I->getType()); - if (RetSTy == 0) { - // Check to see if we're tracking this callee, if not, handle it in the - // common path above. - DenseMap::iterator TFRVI = TrackedRetVals.find(F); - if (TFRVI == TrackedRetVals.end()) - goto CallOverdefined; - + DenseMap::iterator TFRVI = TrackedRetVals.find(F); + if (TFRVI != TrackedRetVals.end()) { // If so, propagate the return value of the callee into this call result. mergeInValue(I, TFRVI->second); - } else { + } else if (isa(I->getType())) { // Check to see if we're tracking this callee, if not, handle it in the // common path above. std::map, LatticeVal>::iterator @@ -1168,13 +1245,30 @@ goto CallOverdefined; // If we are tracking this callee, propagate the return values of the call - // into this call site. We do this by walking all the getresult uses. + // into this call site. We do this by walking all the uses. Single-index + // ExtractValueInst uses can be tracked; anything more complicated is + // currently handled conservatively. for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E; ++UI) { - GetResultInst *GRI = cast(*UI); - mergeInValue(GRI, - TrackedMultipleRetVals[std::make_pair(F, GRI->getIndex())]); + if (GetResultInst *GRI = dyn_cast(*UI)) { + mergeInValue(GRI, + TrackedMultipleRetVals[std::make_pair(F, GRI->getIndex())]); + continue; + } + if (ExtractValueInst *EVI = dyn_cast(*UI)) { + if (EVI->getNumIndices() == 1) { + mergeInValue(EVI, + TrackedMultipleRetVals[std::make_pair(F, *EVI->idx_begin())]); + continue; + } + } + // The aggregate value is used in a way not handled here. Assume nothing. + markOverdefined(*UI); } + } else { + // Otherwise we're not tracking this callee, so handle it in the + // common path above. + goto CallOverdefined; } // Finally, if this is the first call to the function hit, mark its entry From resistor at mac.com Thu Jun 19 20:15:47 2008 From: resistor at mac.com (Owen Anderson) Date: Fri, 20 Jun 2008 01:15:47 -0000 Subject: [llvm-commits] [llvm] r52521 - /llvm/trunk/lib/Transforms/Scalar/GVN.cpp Message-ID: <200806200115.m5K1FllR017003@zion.cs.uiuc.edu> Author: resistor Date: Thu Jun 19 20:15:47 2008 New Revision: 52521 URL: http://llvm.org/viewvc/llvm-project?rev=52521&view=rev Log: Change around the data structures used to store availability sets, resulting in a GVN+PRE that is faster that GVN alone was before. Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=52521&r1=52520&r2=52521&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Thu Jun 19 20:15:47 2008 @@ -693,6 +693,15 @@ } namespace { + struct VISIBILITY_HIDDEN ValueNumberScope { + ValueNumberScope* parent; + DenseMap table; + + ValueNumberScope(ValueNumberScope* p) : parent(p) { } + }; +} + +namespace { class VISIBILITY_HIDDEN GVN : public FunctionPass { bool runOnFunction(Function &F); @@ -702,7 +711,7 @@ private: ValueTable VN; - DenseMap > localAvail; + DenseMap localAvail; typedef DenseMap > PhiMapType; PhiMapType phiMap; @@ -737,6 +746,7 @@ Value* CollapsePhi(PHINode* p); bool isSafeReplacement(PHINode* p, Instruction* inst); bool performPRE(Function& F); + Value* lookupNumber(BasicBlock* BB, uint32_t num); }; char GVN::ID = 0; @@ -1008,6 +1018,20 @@ return deletedLoad; } +Value* GVN::lookupNumber(BasicBlock* BB, uint32_t num) { + ValueNumberScope* locals = localAvail[BB]; + + while (locals) { + DenseMap::iterator I = locals->table.find(num); + if (I != locals->table.end()) + return I->second; + else + locals = locals->parent; + } + + return 0; +} + /// processInstruction - When calculating availability, handle an instruction /// by inserting it into the appropriate sets bool GVN::processInstruction(Instruction *I, @@ -1018,7 +1042,7 @@ if (!changed) { unsigned num = VN.lookup_or_add(L); - localAvail[I->getParent()].insert(std::make_pair(num, L)); + localAvail[I->getParent()]->table.insert(std::make_pair(num, L)); } return changed; @@ -1029,7 +1053,7 @@ // Allocations are always uniquely numbered, so we can save time and memory // by fast failing them. if (isa(I)) { - localAvail[I->getParent()].insert(std::make_pair(num, I)); + localAvail[I->getParent()]->table.insert(std::make_pair(num, I)); return false; } @@ -1046,12 +1070,10 @@ p->replaceAllUsesWith(constVal); toErase.push_back(p); } else { - localAvail[I->getParent()].insert(std::make_pair(num, I)); + localAvail[I->getParent()]->table.insert(std::make_pair(num, I)); } // Perform value-number based elimination - } else if (localAvail[I->getParent()].count(num)) { - Value* repl = localAvail[I->getParent()][num]; - + } else if (Value* repl = lookupNumber(I->getParent(), num)) { // Remove it! MemoryDependenceAnalysis& MD = getAnalysis(); MD.removeInstruction(I); @@ -1061,7 +1083,7 @@ toErase.push_back(I); return true; } else if (!I->isTerminator()) { - localAvail[I->getParent()].insert(std::make_pair(num, I)); + localAvail[I->getParent()]->table.insert(std::make_pair(num, I)); } return false; @@ -1095,8 +1117,10 @@ bool changed_function = false; if (DTN->getIDom()) - localAvail.insert(std::make_pair(BB, - localAvail[DTN->getIDom()->getBlock()])); + localAvail[BB] = + new ValueNumberScope(localAvail[DTN->getIDom()->getBlock()]); + else + localAvail[BB] = new ValueNumberScope(0); for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE;) { @@ -1161,19 +1185,29 @@ unsigned numWith = 0; unsigned numWithout = 0; BasicBlock* PREPred = 0; + DenseMap predMap; for (pred_iterator PI = pred_begin(CurrentBlock), PE = pred_end(CurrentBlock); PI != PE; ++PI) { // We're not interested in PRE where the block is its - // own predecessor. - if (*PI == CurrentBlock) + // own predecessor, on in blocks with predecessors + // that are not reachable. + if (*PI == CurrentBlock) { numWithout = 2; - - if (!localAvail[*PI].count(valno)) { + break; + } else if (!localAvail.count(*PI)) { + numWithout = 2; + break; + } + + DenseMap::iterator predV = + localAvail[*PI]->table.find(valno); + if (predV == localAvail[*PI]->table.end()) { PREPred = *PI; numWithout++; - } else if (localAvail[*PI][valno] == BI) { + } else if (predV->second == BI) { numWithout = 2; } else { + predMap[*PI] = predV->second; numWith++; } } @@ -1214,11 +1248,11 @@ Value* op = BI->getOperand(i); if (isa(op) || isa(op) || isa(op)) PREInstr->setOperand(i, op); - else if (!localAvail[PREPred].count(VN.lookup(op))) { + else if (!lookupNumber(PREPred, VN.lookup(op))) { success = false; break; } else - PREInstr->setOperand(i, localAvail[PREPred][VN.lookup(op)]); + PREInstr->setOperand(i, lookupNumber(PREPred, VN.lookup(op))); } // Fail out if we encounter an operand that is not available in @@ -1232,11 +1266,12 @@ PREInstr->insertBefore(PREPred->getTerminator()); PREInstr->setName(BI->getName() + ".pre"); + predMap[PREPred] = PREInstr; VN.add(PREInstr, valno); NumGVNPRE++; // Update the availability map to include the new instruction. - localAvail[PREPred].insert(std::make_pair(valno, PREInstr)); + localAvail[PREPred]->table.insert(std::make_pair(valno, PREInstr)); // Create a PHI to make the value available in this block. PHINode* Phi = PHINode::Create(BI->getType(), @@ -1244,18 +1279,17 @@ CurrentBlock->begin()); for (pred_iterator PI = pred_begin(CurrentBlock), PE = pred_end(CurrentBlock); PI != PE; ++PI) - Phi->addIncoming(localAvail[*PI][valno], *PI); + Phi->addIncoming(predMap[*PI], *PI); VN.add(Phi, valno); // The newly created PHI completely replaces the old instruction, // so we need to update the maps to reflect this. - for (DenseMap >::iterator - UI = localAvail.begin(), UE = localAvail.end(); UI != UE; ++UI) - for (DenseMap::iterator UUI = UI->second.begin(), - UUE = UI->second.end(); UUI != UUE; ++UUI) - if (UUI->second == BI) - UUI->second = Phi; + DomTreeNode* DTN = getAnalysis()[CurrentBlock]; + for (DomTreeNode::iterator UI = DTN->begin(), UE = DTN->end(); + UI != UE; ++UI) + localAvail[(*UI)->getBlock()]->table[valno] = Phi; + localAvail[CurrentBlock]->table[valno] = Phi; BI->replaceAllUsesWith(Phi); VN.erase(BI); @@ -1279,9 +1313,13 @@ bool GVN::iterateOnFunction(Function &F) { // Clean out global sets from any previous functions VN.clear(); - localAvail.clear(); phiMap.clear(); + for (DenseMap::iterator + I = localAvail.begin(), E = localAvail.end(); I != E; ++I) + delete I->second; + localAvail.clear(); + DominatorTree &DT = getAnalysis(); // Top-down walk of the dominator tree From wangmp at apple.com Thu Jun 19 20:19:07 2008 From: wangmp at apple.com (Mon P Wang) Date: Thu, 19 Jun 2008 18:19:07 -0700 Subject: [llvm-commits] atomics memoperands patch Message-ID: <5EAD215D-D32D-4C78-8020-E17D5179A72A@apple.com> Hi, Like loads/stores, atomics touches memory and should have an associated MemOperand with the operation. The following patch creates an abstract class MemSDNode that all nodes which have an associated MemOperand need to inherit to. It also creates a new property SDNPMemOperand that indicates that a node touches memory and has an associated MemOperand.If you have any comments, please let me know. Thanks, -- Mon Ping -------------- next part -------------- A non-text attachment was scrubbed... Name: memop.patch Type: application/octet-stream Size: 21530 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080619/7f5d51b5/attachment.obj From gohman at apple.com Thu Jun 19 20:29:26 2008 From: gohman at apple.com (Dan Gohman) Date: Fri, 20 Jun 2008 01:29:26 -0000 Subject: [llvm-commits] [llvm] r52522 - /llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Message-ID: <200806200129.m5K1TRd4017506@zion.cs.uiuc.edu> Author: djg Date: Thu Jun 19 20:29:26 2008 New Revision: 52522 URL: http://llvm.org/viewvc/llvm-project?rev=52522&view=rev Log: Teach ReturnInst lowering about aggregate return values. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp?rev=52522&r1=52521&r2=52522&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Thu Jun 19 20:29:26 2008 @@ -1270,32 +1270,38 @@ NewValues.push_back(getControlRoot()); for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) { SDOperand RetOp = getValue(I.getOperand(i)); - MVT VT = RetOp.getValueType(); - // FIXME: C calling convention requires the return type to be promoted to - // at least 32-bit. But this is not necessary for non-C calling conventions. - if (VT.isInteger()) { - MVT MinVT = TLI.getRegisterType(MVT::i32); - if (VT.bitsLT(MinVT)) - VT = MinVT; - } - - unsigned NumParts = TLI.getNumRegisters(VT); - MVT PartVT = TLI.getRegisterType(VT); - SmallVector Parts(NumParts); - ISD::NodeType ExtendKind = ISD::ANY_EXTEND; - - const Function *F = I.getParent()->getParent(); - if (F->paramHasAttr(0, ParamAttr::SExt)) - ExtendKind = ISD::SIGN_EXTEND; - else if (F->paramHasAttr(0, ParamAttr::ZExt)) - ExtendKind = ISD::ZERO_EXTEND; - - getCopyToParts(DAG, RetOp, &Parts[0], NumParts, PartVT, ExtendKind); - - for (unsigned i = 0; i < NumParts; ++i) { - NewValues.push_back(Parts[i]); - NewValues.push_back(DAG.getArgFlags(ISD::ArgFlagsTy())); + SmallVector ValueVTs; + ComputeValueVTs(TLI, I.getOperand(i)->getType(), ValueVTs); + for (unsigned j = 0, f = ValueVTs.size(); j != f; ++j) { + MVT VT = ValueVTs[j]; + + // FIXME: C calling convention requires the return type to be promoted to + // at least 32-bit. But this is not necessary for non-C calling conventions. + if (VT.isInteger()) { + MVT MinVT = TLI.getRegisterType(MVT::i32); + if (VT.bitsLT(MinVT)) + VT = MinVT; + } + + unsigned NumParts = TLI.getNumRegisters(VT); + MVT PartVT = TLI.getRegisterType(VT); + SmallVector Parts(NumParts); + ISD::NodeType ExtendKind = ISD::ANY_EXTEND; + + const Function *F = I.getParent()->getParent(); + if (F->paramHasAttr(0, ParamAttr::SExt)) + ExtendKind = ISD::SIGN_EXTEND; + else if (F->paramHasAttr(0, ParamAttr::ZExt)) + ExtendKind = ISD::ZERO_EXTEND; + + getCopyToParts(DAG, SDOperand(RetOp.Val, RetOp.ResNo + j), + &Parts[0], NumParts, PartVT, ExtendKind); + + for (unsigned i = 0; i < NumParts; ++i) { + NewValues.push_back(Parts[i]); + NewValues.push_back(DAG.getArgFlags(ISD::ArgFlagsTy())); + } } } DAG.setRoot(DAG.getNode(ISD::RET, MVT::Other, From gordonhenriksen at mac.com Thu Jun 19 21:16:11 2008 From: gordonhenriksen at mac.com (Gordon Henriksen) Date: Fri, 20 Jun 2008 02:16:11 -0000 Subject: [llvm-commits] [llvm] r52523 - in /llvm/trunk: include/llvm-c/ExecutionEngine.h lib/ExecutionEngine/ExecutionEngineBindings.cpp Message-ID: <200806200216.m5K2GBwU018814@zion.cs.uiuc.edu> Author: gordon Date: Thu Jun 19 21:16:11 2008 New Revision: 52523 URL: http://llvm.org/viewvc/llvm-project?rev=52523&view=rev Log: Add C binding for ExecutionEngine::addGlobalMapping. Modified: llvm/trunk/include/llvm-c/ExecutionEngine.h llvm/trunk/lib/ExecutionEngine/ExecutionEngineBindings.cpp Modified: llvm/trunk/include/llvm-c/ExecutionEngine.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm-c/ExecutionEngine.h?rev=52523&r1=52522&r2=52523&view=diff ============================================================================== --- llvm/trunk/include/llvm-c/ExecutionEngine.h (original) +++ llvm/trunk/include/llvm-c/ExecutionEngine.h Thu Jun 19 21:16:11 2008 @@ -91,6 +91,9 @@ LLVMTargetDataRef LLVMGetExecutionEngineTargetData(LLVMExecutionEngineRef EE); +void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, + void* Addr); + #ifdef __cplusplus } Modified: llvm/trunk/lib/ExecutionEngine/ExecutionEngineBindings.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/ExecutionEngineBindings.cpp?rev=52523&r1=52522&r2=52523&view=diff ============================================================================== --- llvm/trunk/lib/ExecutionEngine/ExecutionEngineBindings.cpp (original) +++ llvm/trunk/lib/ExecutionEngine/ExecutionEngineBindings.cpp Thu Jun 19 21:16:11 2008 @@ -192,3 +192,8 @@ LLVMTargetDataRef LLVMGetExecutionEngineTargetData(LLVMExecutionEngineRef EE) { return wrap(unwrap(EE)->getTargetData()); } + +void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, + void* Addr) { + unwrap(EE)->addGlobalMapping(unwrap(Global), Addr); +} From evan.cheng at apple.com Thu Jun 19 23:44:22 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Thu, 19 Jun 2008 21:44:22 -0700 Subject: [llvm-commits] [llvm] r52521 - /llvm/trunk/lib/Transforms/Scalar/GVN.cpp In-Reply-To: <200806200115.m5K1FllR017003@zion.cs.uiuc.edu> References: <200806200115.m5K1FllR017003@zion.cs.uiuc.edu> Message-ID: Very nice. Thanks Owen. Here is one nitpick: if (DTN->getIDom()) - localAvail.insert(std::make_pair(BB, - localAvail[DTN->getIDom()->getBlock()])); + localAvail[BB] = + new ValueNumberScope(localAvail[DTN->getIDom()- >getBlock()]); + else + localAvail[BB] = new ValueNumberScope(0); How about? ValueNumberScope* p = DTN->getIDom() ? localAvail[DTN->getIDom()- >getBlock()] : 0; localAvail[BB] = p; Evan On Jun 19, 2008, at 6:15 PM, Owen Anderson wrote: > Author: resistor > Date: Thu Jun 19 20:15:47 2008 > New Revision: 52521 > > URL: http://llvm.org/viewvc/llvm-project?rev=52521&view=rev > Log: > Change around the data structures used to store availability sets, > resulting in a GVN+PRE that is faster that GVN alone was before. > > Modified: > llvm/trunk/lib/Transforms/Scalar/GVN.cpp > > Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=52521&r1=52520&r2=52521&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original) > +++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Thu Jun 19 20:15:47 2008 > @@ -693,6 +693,15 @@ > } > > namespace { > + struct VISIBILITY_HIDDEN ValueNumberScope { > + ValueNumberScope* parent; > + DenseMap table; > + > + ValueNumberScope(ValueNumberScope* p) : parent(p) { } > + }; > +} > + > +namespace { > > class VISIBILITY_HIDDEN GVN : public FunctionPass { > bool runOnFunction(Function &F); > @@ -702,7 +711,7 @@ > > private: > ValueTable VN; > - DenseMap > localAvail; > + DenseMap localAvail; > > typedef DenseMap > > PhiMapType; > PhiMapType phiMap; > @@ -737,6 +746,7 @@ > Value* CollapsePhi(PHINode* p); > bool isSafeReplacement(PHINode* p, Instruction* inst); > bool performPRE(Function& F); > + Value* lookupNumber(BasicBlock* BB, uint32_t num); > }; > > char GVN::ID = 0; > @@ -1008,6 +1018,20 @@ > return deletedLoad; > } > > +Value* GVN::lookupNumber(BasicBlock* BB, uint32_t num) { > + ValueNumberScope* locals = localAvail[BB]; > + > + while (locals) { > + DenseMap::iterator I = locals->table.find(num); > + if (I != locals->table.end()) > + return I->second; > + else > + locals = locals->parent; > + } > + > + return 0; > +} > + > /// processInstruction - When calculating availability, handle an > instruction > /// by inserting it into the appropriate sets > bool GVN::processInstruction(Instruction *I, > @@ -1018,7 +1042,7 @@ > > if (!changed) { > unsigned num = VN.lookup_or_add(L); > - localAvail[I->getParent()].insert(std::make_pair(num, L)); > + localAvail[I->getParent()]->table.insert(std::make_pair(num, > L)); > } > > return changed; > @@ -1029,7 +1053,7 @@ > // Allocations are always uniquely numbered, so we can save time > and memory > // by fast failing them. > if (isa(I)) { > - localAvail[I->getParent()].insert(std::make_pair(num, I)); > + localAvail[I->getParent()]->table.insert(std::make_pair(num, I)); > return false; > } > > @@ -1046,12 +1070,10 @@ > p->replaceAllUsesWith(constVal); > toErase.push_back(p); > } else { > - localAvail[I->getParent()].insert(std::make_pair(num, I)); > + localAvail[I->getParent()]->table.insert(std::make_pair(num, > I)); > } > // Perform value-number based elimination > - } else if (localAvail[I->getParent()].count(num)) { > - Value* repl = localAvail[I->getParent()][num]; > - > + } else if (Value* repl = lookupNumber(I->getParent(), num)) { > // Remove it! > MemoryDependenceAnalysis& MD = > getAnalysis(); > MD.removeInstruction(I); > @@ -1061,7 +1083,7 @@ > toErase.push_back(I); > return true; > } else if (!I->isTerminator()) { > - localAvail[I->getParent()].insert(std::make_pair(num, I)); > + localAvail[I->getParent()]->table.insert(std::make_pair(num, I)); > } > > return false; > @@ -1095,8 +1117,10 @@ > bool changed_function = false; > > if (DTN->getIDom()) > - localAvail.insert(std::make_pair(BB, > - localAvail[DTN->getIDom()->getBlock()])); > + localAvail[BB] = > + new ValueNumberScope(localAvail[DTN->getIDom()- > >getBlock()]); > + else > + localAvail[BB] = new ValueNumberScope(0); > > for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); > BI != BE;) { > @@ -1161,19 +1185,29 @@ > unsigned numWith = 0; > unsigned numWithout = 0; > BasicBlock* PREPred = 0; > + DenseMap predMap; > for (pred_iterator PI = pred_begin(CurrentBlock), > PE = pred_end(CurrentBlock); PI != PE; ++PI) { > // We're not interested in PRE where the block is its > - // own predecessor. > - if (*PI == CurrentBlock) > + // own predecessor, on in blocks with predecessors > + // that are not reachable. > + if (*PI == CurrentBlock) { > numWithout = 2; > - > - if (!localAvail[*PI].count(valno)) { > + break; > + } else if (!localAvail.count(*PI)) { > + numWithout = 2; > + break; > + } > + > + DenseMap::iterator predV = > + localAvail[*PI]- > >table.find(valno); > + if (predV == localAvail[*PI]->table.end()) { > PREPred = *PI; > numWithout++; > - } else if (localAvail[*PI][valno] == BI) { > + } else if (predV->second == BI) { > numWithout = 2; > } else { > + predMap[*PI] = predV->second; > numWith++; > } > } > @@ -1214,11 +1248,11 @@ > Value* op = BI->getOperand(i); > if (isa(op) || isa(op) || > isa(op)) > PREInstr->setOperand(i, op); > - else if (!localAvail[PREPred].count(VN.lookup(op))) { > + else if (!lookupNumber(PREPred, VN.lookup(op))) { > success = false; > break; > } else > - PREInstr->setOperand(i, localAvail[PREPred] > [VN.lookup(op)]); > + PREInstr->setOperand(i, lookupNumber(PREPred, > VN.lookup(op))); > } > > // Fail out if we encounter an operand that is not available in > @@ -1232,11 +1266,12 @@ > > PREInstr->insertBefore(PREPred->getTerminator()); > PREInstr->setName(BI->getName() + ".pre"); > + predMap[PREPred] = PREInstr; > VN.add(PREInstr, valno); > NumGVNPRE++; > > // Update the availability map to include the new instruction. > - localAvail[PREPred].insert(std::make_pair(valno, PREInstr)); > + localAvail[PREPred]->table.insert(std::make_pair(valno, > PREInstr)); > > // Create a PHI to make the value available in this block. > PHINode* Phi = PHINode::Create(BI->getType(), > @@ -1244,18 +1279,17 @@ > CurrentBlock->begin()); > for (pred_iterator PI = pred_begin(CurrentBlock), > PE = pred_end(CurrentBlock); PI != PE; ++PI) > - Phi->addIncoming(localAvail[*PI][valno], *PI); > + Phi->addIncoming(predMap[*PI], *PI); > > VN.add(Phi, valno); > > // The newly created PHI completely replaces the old > instruction, > // so we need to update the maps to reflect this. > - for (DenseMap > >::iterator > - UI = localAvail.begin(), UE = localAvail.end(); UI != > UE; ++UI) > - for (DenseMap::iterator UUI = UI- > >second.begin(), > - UUE = UI->second.end(); UUI != UUE; ++UUI) > - if (UUI->second == BI) > - UUI->second = Phi; > + DomTreeNode* DTN = getAnalysis()[CurrentBlock]; > + for (DomTreeNode::iterator UI = DTN->begin(), UE = DTN->end(); > + UI != UE; ++UI) > + localAvail[(*UI)->getBlock()]->table[valno] = Phi; > + localAvail[CurrentBlock]->table[valno] = Phi; > > BI->replaceAllUsesWith(Phi); > VN.erase(BI); > @@ -1279,9 +1313,13 @@ > bool GVN::iterateOnFunction(Function &F) { > // Clean out global sets from any previous functions > VN.clear(); > - localAvail.clear(); > phiMap.clear(); > > + for (DenseMap::iterator > + I = localAvail.begin(), E = localAvail.end(); I != E; ++I) > + delete I->second; > + localAvail.clear(); > + > DominatorTree &DT = getAnalysis(); > > // Top-down walk of the dominator tree > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080619/720b378b/attachment.html From sabre at nondot.org Fri Jun 20 00:03:19 2008 From: sabre at nondot.org (Chris Lattner) Date: Fri, 20 Jun 2008 05:03:19 -0000 Subject: [llvm-commits] [llvm] r52524 - /llvm/trunk/docs/ProgrammersManual.html Message-ID: <200806200503.m5K53Jf8023419@zion.cs.uiuc.edu> Author: lattner Date: Fri Jun 20 00:03:17 2008 New Revision: 52524 URL: http://llvm.org/viewvc/llvm-project?rev=52524&view=rev Log: Fix typo, fix suggested by Nicholas Olsen Modified: llvm/trunk/docs/ProgrammersManual.html Modified: llvm/trunk/docs/ProgrammersManual.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/ProgrammersManual.html?rev=52524&r1=52523&r2=52524&view=diff ============================================================================== --- llvm/trunk/docs/ProgrammersManual.html (original) +++ llvm/trunk/docs/ProgrammersManual.html Fri Jun 20 00:03:17 2008 @@ -333,7 +333,7 @@
    cast<>:

    The cast<> operator is a "checked cast" operation. It - converts a pointer or reference from a base class to a derived cast, causing + converts a pointer or reference from a base class to a derived class, causing an assertion failure if it is not really an instance of the right type. This should be used in cases where you have some information that makes you believe that something is of the right type. An example of the isa<> From sabre at nondot.org Fri Jun 20 00:12:57 2008 From: sabre at nondot.org (Chris Lattner) Date: Fri, 20 Jun 2008 05:12:57 -0000 Subject: [llvm-commits] [llvm] r52525 - in /llvm/trunk: lib/Transforms/Scalar/InstructionCombining.cpp test/Transforms/InstCombine/2008-06-19-UncondLoad.ll Message-ID: <200806200512.m5K5CvuE023731@zion.cs.uiuc.edu> Author: lattner Date: Fri Jun 20 00:12:56 2008 New Revision: 52525 URL: http://llvm.org/viewvc/llvm-project?rev=52525&view=rev Log: Fix PR2471, which is a bug involving an invalid promotion from a conditional load. Added: llvm/trunk/test/Transforms/InstCombine/2008-06-19-UncondLoad.ll Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=52525&r1=52524&r2=52525&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Fri Jun 20 00:12:56 2008 @@ -10062,10 +10062,16 @@ while (BBI != E) { --BBI; + // If we see a free or a call (which might do a free) the pointer could be + // marked invalid. + if (isa(BBI) || isa(BBI)) + return false; + if (LoadInst *LI = dyn_cast(BBI)) { if (LI->getOperand(0) == V) return true; - } else if (StoreInst *SI = dyn_cast(BBI)) + } else if (StoreInst *SI = dyn_cast(BBI)) { if (SI->getOperand(1) == V) return true; + } } return false; Added: llvm/trunk/test/Transforms/InstCombine/2008-06-19-UncondLoad.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2008-06-19-UncondLoad.ll?rev=52525&view=auto ============================================================================== --- llvm/trunk/test/Transforms/InstCombine/2008-06-19-UncondLoad.ll (added) +++ llvm/trunk/test/Transforms/InstCombine/2008-06-19-UncondLoad.ll Fri Jun 20 00:12:56 2008 @@ -0,0 +1,16 @@ +; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep load | count 3 +; PR2471 + +declare i32 @x(i32*) +define i32 @b(i32* %a, i32* %b) { +entry: + %tmp1 = load i32* %a + %tmp3 = load i32* %b + %add = add i32 %tmp1, %tmp3 + %call = call i32 @x( i32* %a ) + %tobool = icmp ne i32 %add, 0 + ; not safe to turn into an uncond load + %cond = select i1 %tobool, i32* %b, i32* %a + %tmp8 = load i32* %cond + ret i32 %tmp8 +} From sabre at nondot.org Fri Jun 20 00:28:56 2008 From: sabre at nondot.org (Chris Lattner) Date: Fri, 20 Jun 2008 05:28:56 -0000 Subject: [llvm-commits] [llvm] r52526 - /llvm/trunk/test/FrontendC/2007-09-28-PackedUnionMember.c Message-ID: <200806200528.m5K5Sueo024213@zion.cs.uiuc.edu> Author: lattner Date: Fri Jun 20 00:28:56 2008 New Revision: 52526 URL: http://llvm.org/viewvc/llvm-project?rev=52526&view=rev Log: fix a warning. Modified: llvm/trunk/test/FrontendC/2007-09-28-PackedUnionMember.c Modified: llvm/trunk/test/FrontendC/2007-09-28-PackedUnionMember.c URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FrontendC/2007-09-28-PackedUnionMember.c?rev=52526&r1=52525&r2=52526&view=diff ============================================================================== --- llvm/trunk/test/FrontendC/2007-09-28-PackedUnionMember.c (original) +++ llvm/trunk/test/FrontendC/2007-09-28-PackedUnionMember.c Fri Jun 20 00:28:56 2008 @@ -1,6 +1,4 @@ // RUN: %llvmgcc %s -S -o - -// XFAIL: * -// See PR2452 #pragma pack(push, 2) struct H { @@ -28,12 +26,12 @@ static long hndlr() { - struct H cmd = { 4, 'fart' }; + struct H cmd = { 4, 412 }; return 0; } void foo(void *inWindow) { static const struct E events[] = { - { 'cmds', 1 } + { 123124, 1 } }; bork(hndlr, events); } From sabre at nondot.org Fri Jun 20 00:29:39 2008 From: sabre at nondot.org (Chris Lattner) Date: Fri, 20 Jun 2008 05:29:39 -0000 Subject: [llvm-commits] [llvm] r52527 - in /llvm/trunk: lib/Linker/LinkModules.cpp test/Linker/2008-06-13-LinkOnceRedefinition.ll test/Linker/redefinition.ll Message-ID: <200806200529.m5K5Td0G024245@zion.cs.uiuc.edu> Author: lattner Date: Fri Jun 20 00:29:39 2008 New Revision: 52527 URL: http://llvm.org/viewvc/llvm-project?rev=52527&view=rev Log: Fix an error handling redefinition of linkonce functions where the types differ. Patch by Nathan Keynes! Added: llvm/trunk/test/Linker/2008-06-13-LinkOnceRedefinition.ll Modified: llvm/trunk/lib/Linker/LinkModules.cpp llvm/trunk/test/Linker/redefinition.ll Modified: llvm/trunk/lib/Linker/LinkModules.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Linker/LinkModules.cpp?rev=52527&r1=52526&r2=52527&view=diff ============================================================================== --- llvm/trunk/lib/Linker/LinkModules.cpp (original) +++ llvm/trunk/lib/Linker/LinkModules.cpp Fri Jun 20 00:29:39 2008 @@ -897,6 +897,7 @@ const Function *SF = I; // SrcFunction Function *DF = 0; + Value *MappedDF; // If this function is internal or has no name, it doesn't participate in // linkage. @@ -973,19 +974,14 @@ // Remember this mapping so uses in the source module get remapped // later by RemapOperand. ValueMap[SF] = NewDF; - } else if (SF->isDeclaration()) { - // We have two functions of the same name but different type and the - // source is a declaration while the destination is not. Any use of - // the source must be mapped to the destination, with a cast. - ValueMap[SF] = ConstantExpr::getBitCast(DF, SF->getType()); + continue; } else { - // We have two functions of the same name but different types and they - // are both definitions. This is an error. - return Error(Err, "Function '" + DF->getName() + "' defined as both '" + - ToStr(SF->getFunctionType(), Src) + "' and '" + - ToStr(DF->getFunctionType(), Dest) + "'"); + // We have two functions of the same name but different type. Any use + // of the source must be mapped to the destination, with a cast. + MappedDF = ConstantExpr::getBitCast(DF, SF->getType()); } - continue; + } else { + MappedDF = DF; } if (SF->isDeclaration()) { @@ -993,11 +989,11 @@ // the declarations, we aren't adding anything. if (SF->hasDLLImportLinkage()) { if (DF->isDeclaration()) { - ValueMap[SF] = DF; + ValueMap[SF] = MappedDF; DF->setLinkage(SF->getLinkage()); } } else { - ValueMap[SF] = DF; + ValueMap[SF] = MappedDF; } continue; } @@ -1005,7 +1001,7 @@ // If DF is external but SF is not, link the external functions, update // linkage qualifiers. if (DF->isDeclaration() && !DF->hasDLLImportLinkage()) { - ValueMap.insert(std::make_pair(SF, DF)); + ValueMap.insert(std::make_pair(SF, MappedDF)); DF->setLinkage(SF->getLinkage()); continue; } @@ -1013,7 +1009,7 @@ // At this point we know that DF has LinkOnce, Weak, or External* linkage. if (SF->hasWeakLinkage() || SF->hasLinkOnceLinkage() || SF->hasCommonLinkage()) { - ValueMap[SF] = DF; + ValueMap[SF] = MappedDF; // Linkonce+Weak = Weak // *+External Weak = * @@ -1027,7 +1023,7 @@ if (DF->hasWeakLinkage() || DF->hasLinkOnceLinkage() || DF->hasCommonLinkage()) { // At this point we know that SF has LinkOnce or External* linkage. - ValueMap[SF] = DF; + ValueMap[SF] = MappedDF; // If the source function has stronger linkage than the destination, // its body and linkage should override ours. @@ -1106,10 +1102,10 @@ // go for (Module::iterator SF = Src->begin(), E = Src->end(); SF != E; ++SF) { if (!SF->isDeclaration()) { // No body if function is external - Function *DF = cast(ValueMap[SF]); // Destination function + Function *DF = dyn_cast(ValueMap[SF]); // Destination function // DF not external SF external? - if (DF->isDeclaration()) + if (DF && DF->isDeclaration()) // Only provide the function body if there isn't one already. if (LinkFunctionBody(DF, SF, ValueMap, Err)) return true; Added: llvm/trunk/test/Linker/2008-06-13-LinkOnceRedefinition.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/2008-06-13-LinkOnceRedefinition.ll?rev=52527&view=auto ============================================================================== --- llvm/trunk/test/Linker/2008-06-13-LinkOnceRedefinition.ll (added) +++ llvm/trunk/test/Linker/2008-06-13-LinkOnceRedefinition.ll Fri Jun 20 00:29:39 2008 @@ -0,0 +1,8 @@ +; Test linking two functions with different prototypes and two globals +; in different modules. +; RUN: llvm-as %s -o %t.foo1.bc -f +; RUN: llvm-as %s -o %t.foo2.bc -f +; RUN: echo {define linkonce void @foo(i32 %x) { ret void }} | llvm-as -o %t.foo3.bc -f +; RUN: llvm-link %t.foo1.bc %t.foo2.bc | llvm-dis +; RUN: llvm-link %t.foo1.bc %t.foo3.bc | llvm-dis +define linkonce void @foo() { ret void } Modified: llvm/trunk/test/Linker/redefinition.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/redefinition.ll?rev=52527&r1=52526&r2=52527&view=diff ============================================================================== --- llvm/trunk/test/Linker/redefinition.ll (original) +++ llvm/trunk/test/Linker/redefinition.ll Fri Jun 20 00:29:39 2008 @@ -6,5 +6,5 @@ ; RUN: not llvm-link %t.foo1.bc %t.foo2.bc -o %t.bc |& \ ; RUN: grep {Function is already defined} ; RUN: not llvm-link %t.foo1.bc %t.foo3.bc -o %t.bc |& \ -; RUN: grep {Function 'foo' defined as both} +; RUN: grep {Function is already defined} define void @foo() { ret void } From sabre at nondot.org Fri Jun 20 00:31:05 2008 From: sabre at nondot.org (Chris Lattner) Date: Fri, 20 Jun 2008 05:31:05 -0000 Subject: [llvm-commits] [llvm] r52528 - /llvm/trunk/test/FrontendC/2007-09-05-ConstCtor.c Message-ID: <200806200531.m5K5V5eL024302@zion.cs.uiuc.edu> Author: lattner Date: Fri Jun 20 00:31:04 2008 New Revision: 52528 URL: http://llvm.org/viewvc/llvm-project?rev=52528&view=rev Log: Fix a warning. Modified: llvm/trunk/test/FrontendC/2007-09-05-ConstCtor.c Modified: llvm/trunk/test/FrontendC/2007-09-05-ConstCtor.c URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FrontendC/2007-09-05-ConstCtor.c?rev=52528&r1=52527&r2=52528&view=diff ============================================================================== --- llvm/trunk/test/FrontendC/2007-09-05-ConstCtor.c (original) +++ llvm/trunk/test/FrontendC/2007-09-05-ConstCtor.c Fri Jun 20 00:31:04 2008 @@ -1,7 +1,5 @@ // RUN: %llvmgcc -xc -Os -c %s -o /dev/null // PR1641 -// XFAIL: * -// See PR2452 struct A { unsigned long l; @@ -10,7 +8,7 @@ void bar(struct A *a); void bork() { - const unsigned long vcgt = 'vcgt'; + const unsigned long vcgt = 1234; struct A a = { vcgt }; bar(&a); } From sabre at nondot.org Fri Jun 20 00:33:29 2008 From: sabre at nondot.org (Chris Lattner) Date: Fri, 20 Jun 2008 05:33:29 -0000 Subject: [llvm-commits] [llvm] r52529 - /llvm/trunk/test/FrontendC/2003-08-21-WideString.c Message-ID: <200806200533.m5K5XTQW024374@zion.cs.uiuc.edu> Author: lattner Date: Fri Jun 20 00:33:29 2008 New Revision: 52529 URL: http://llvm.org/viewvc/llvm-project?rev=52529&view=rev Log: Fix a warning, closing PR2452 Modified: llvm/trunk/test/FrontendC/2003-08-21-WideString.c Modified: llvm/trunk/test/FrontendC/2003-08-21-WideString.c URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FrontendC/2003-08-21-WideString.c?rev=52529&r1=52528&r2=52529&view=diff ============================================================================== --- llvm/trunk/test/FrontendC/2003-08-21-WideString.c (original) +++ llvm/trunk/test/FrontendC/2003-08-21-WideString.c Fri Jun 20 00:33:29 2008 @@ -1,7 +1,7 @@ // RUN: %llvmgcc -S %s -o - | llvm-as -f -o /dev/null -// XFAIL: * -// See PR2452 + +#include struct { - int *name; + wchar_t *name; } syms = { L"NUL" }; From sabre at nondot.org Fri Jun 20 00:35:58 2008 From: sabre at nondot.org (Chris Lattner) Date: Fri, 20 Jun 2008 05:35:58 -0000 Subject: [llvm-commits] [llvm] r52530 - in /llvm/trunk/win32: Analysis/ Archive/ AsmParser/ Bitcode/ CBackend/ CodeGen/ Configure/ ExecutionEngine/ Fibonacci/ Linker/ Support/ System/ TableGen/ Target/ Transforms/ VMCore/ bugpoint/ llc/ lli/ llvm-ar/ llvm-as/ llvm-bcanalyzer/ llvm-dis/ llvm-ld/ llvm-link/ llvm-nm/ llvm-prof/ llvm-ranlib/ opt/ x86/ Message-ID: <200806200535.m5K5ZxFX024511@zion.cs.uiuc.edu> Author: lattner Date: Fri Jun 20 00:35:58 2008 New Revision: 52530 URL: http://llvm.org/viewvc/llvm-project?rev=52530&view=rev Log: "Just a small update for the project files for adding a missing preprocessor definition for VS2005 (without SP1). It suppress the (bogus) M$ deprecated warning." Patch by C?dric Venet! Modified: llvm/trunk/win32/Analysis/Analysis.vcproj llvm/trunk/win32/Archive/Archive.vcproj llvm/trunk/win32/AsmParser/AsmParser.vcproj llvm/trunk/win32/Bitcode/Bitcode.vcproj llvm/trunk/win32/CBackend/CBackend.vcproj llvm/trunk/win32/CodeGen/CodeGen.vcproj llvm/trunk/win32/Configure/Configure.vcproj llvm/trunk/win32/ExecutionEngine/ExecutionEngine.vcproj llvm/trunk/win32/Fibonacci/Fibonacci.vcproj llvm/trunk/win32/Linker/Linker.vcproj llvm/trunk/win32/Support/Support.vcproj llvm/trunk/win32/System/System.vcproj llvm/trunk/win32/TableGen/TableGen.vcproj llvm/trunk/win32/Target/Target.vcproj llvm/trunk/win32/Transforms/Transforms.vcproj llvm/trunk/win32/VMCore/VMCore.vcproj llvm/trunk/win32/bugpoint/bugpoint.vcproj llvm/trunk/win32/llc/llc.vcproj llvm/trunk/win32/lli/lli.vcproj llvm/trunk/win32/llvm-ar/llvm-ar.vcproj llvm/trunk/win32/llvm-as/llvm-as.vcproj llvm/trunk/win32/llvm-bcanalyzer/llvm-bcanalyzer.vcproj llvm/trunk/win32/llvm-dis/llvm-dis.vcproj llvm/trunk/win32/llvm-ld/llvm-ld.vcproj llvm/trunk/win32/llvm-link/llvm-link.vcproj llvm/trunk/win32/llvm-nm/llvm-nm.vcproj llvm/trunk/win32/llvm-prof/llvm-prof.vcproj llvm/trunk/win32/llvm-ranlib/llvm-ranlib.vcproj llvm/trunk/win32/opt/opt.vcproj llvm/trunk/win32/x86/x86.vcproj Modified: llvm/trunk/win32/Analysis/Analysis.vcproj URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/win32/Analysis/Analysis.vcproj?rev=52530&r1=52529&r2=52530&view=diff ============================================================================== --- llvm/trunk/win32/Analysis/Analysis.vcproj (original) +++ llvm/trunk/win32/Analysis/Analysis.vcproj Fri Jun 20 00:35:58 2008 @@ -22,7 +22,7 @@ OutputDirectory="$(SolutionDir)\bin\$(PlatformName)\$(ConfigurationName)" IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" ConfigurationType="4" - InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops;..\common.vsprops" CharacterSet="2" > Modified: llvm/trunk/win32/ExecutionEngine/ExecutionEngine.vcproj URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/win32/ExecutionEngine/ExecutionEngine.vcproj?rev=52530&r1=52529&r2=52530&view=diff ============================================================================== --- llvm/trunk/win32/ExecutionEngine/ExecutionEngine.vcproj (original) +++ llvm/trunk/win32/ExecutionEngine/ExecutionEngine.vcproj Fri Jun 20 00:35:58 2008 @@ -22,7 +22,7 @@ OutputDirectory="$(SolutionDir)\bin\$(PlatformName)\$(ConfigurationName)" IntermediateDirectory="$(PlatformName)\$(ConfigurationName)" ConfigurationType="4" - InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops" + InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops;..\common.vsprops" CharacterSet="2" > References: <5EAD215D-D32D-4C78-8020-E17D5179A72A@apple.com> Message-ID: Thanks Mon Ping. Some comments: + N->getOpcode() == ISD::ATOMIC_LCS || + N->getOpcode() == ISD::ATOMIC_LAS || + N->getOpcode() == ISD::ATOMIC_SWAP || + N->getOpcode() == ISD::ATOMIC_LSS || + N->getOpcode() == ISD::ATOMIC_LOAD_AND || + N->getOpcode() == ISD::ATOMIC_LOAD_OR || + N->getOpcode() == ISD::ATOMIC_LOAD_XOR || Does it make sense to take this opportunity to rename lcs, las, and lss? + //! PtrVal - Value of address that we are going to do an atomic update How about "Value of atomically updated address"? + const Value* PtrVal; Since this is basically the same as LSBaseSDNode SrcValue, how about move it to the common base class MemSDNode? + + //! Align - Alignment of memory location in bytes. + unsigned Align; Alignment instead of Align. + + //! IsVol - True if the store is volatile. + bool IsVol; IsVolatile instead of IsVol. But do we need these? Isn't it always volatile given it's an atomic operation? Again, LSBaseSDNode has these fields as well. Perhaps move them up? + // Check if the atomic references a frame index + const FrameIndexSDNode *FI = + dyn_cast(getBasePtr().Val); + if (!getBasePtrValue() && FI) I am not quite sure why it's necessary to check getBasePtrValue()? + return MachineMemOperand(PseudoSourceValue::getFixedStack(), Flags, + FI->getIndex(), Size, getAlignment()); + else + return MachineMemOperand(getBasePtrValue(), Flags, 0, Size, getAlignment()); +} Also, don't forget to update AddNodeIDNode() and SDNode::dump() in SelectionDAG.cpp. Thanks, Evan On Jun 19, 2008, at 6:19 PM, Mon P Wang wrote: > Hi, > > Like loads/stores, atomics touches memory and should have an > associated MemOperand with the operation. The following patch > creates an abstract class MemSDNode that all nodes which have an > associated MemOperand need to inherit to. It also creates a new > property SDNPMemOperand that indicates that a node touches memory > and has an associated MemOperand.If you have any comments, please > let me know. > > Thanks, > -- Mon Ping > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From evan.cheng at apple.com Fri Jun 20 02:28:50 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Fri, 20 Jun 2008 00:28:50 -0700 Subject: [llvm-commits] atomics memoperands patch In-Reply-To: References: <5EAD215D-D32D-4C78-8020-E17D5179A72A@apple.com> Message-ID: Questions for everyone. I've just noticed something in SelectionDAG.cpp: SDNode *SelectionDAG::FindModifiedNodeSlot(SDNode *N, SDOperandPtr Ops,unsigned NumOps, void *&InsertPos) { ... FoldingSetNodeID ID; AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops, NumOps); if (const LoadSDNode *LD = dyn_cast(N)) { ID.AddInteger(LD->getAddressingMode()); ID.AddInteger(LD->getExtensionType()); ID.AddInteger(LD->getMemoryVT().getRawBits()); ID.AddInteger(LD->getAlignment()); ID.AddInteger(LD->isVolatile()); } else if (const StoreSDNode *ST = dyn_cast(N)) { ID.AddInteger(ST->getAddressingMode()); ID.AddInteger(ST->isTruncatingStore()); ID.AddInteger(ST->getMemoryVT().getRawBits()); ID.AddInteger(ST->getAlignment()); ID.AddInteger(ST->isVolatile()); } Do we need the if () else if? AddNodeIDNode has already added those fields to the FoldingSetNodeId. Also, do we want to cse nodes that are volatile? Evan On Jun 20, 2008, at 12:11 AM, Evan Cheng wrote: > Thanks Mon Ping. Some comments: > > + N->getOpcode() == ISD::ATOMIC_LCS || > + N->getOpcode() == ISD::ATOMIC_LAS || > + N->getOpcode() == ISD::ATOMIC_SWAP || > + N->getOpcode() == ISD::ATOMIC_LSS || > + N->getOpcode() == ISD::ATOMIC_LOAD_AND || > + N->getOpcode() == ISD::ATOMIC_LOAD_OR || > + N->getOpcode() == ISD::ATOMIC_LOAD_XOR || > > Does it make sense to take this opportunity to rename lcs, las, and > lss? > > + //! PtrVal - Value of address that we are going to do an atomic > update > How about "Value of atomically updated address"? > > + const Value* PtrVal; > > Since this is basically the same as LSBaseSDNode SrcValue, how about > move it to the common base class MemSDNode? > > + > + //! Align - Alignment of memory location in bytes. > + unsigned Align; > > Alignment instead of Align. > > + > + //! IsVol - True if the store is volatile. > + bool IsVol; > > IsVolatile instead of IsVol. But do we need these? Isn't it always > volatile given it's an atomic operation? > > Again, LSBaseSDNode has these fields as well. Perhaps move them up? > > + // Check if the atomic references a frame index > + const FrameIndexSDNode *FI = > + dyn_cast(getBasePtr().Val); > + if (!getBasePtrValue() && FI) > > I am not quite sure why it's necessary to check getBasePtrValue()? > > > + return MachineMemOperand(PseudoSourceValue::getFixedStack(), > Flags, > + FI->getIndex(), Size, getAlignment()); > + else > + return MachineMemOperand(getBasePtrValue(), Flags, 0, Size, > getAlignment()); > +} > > Also, don't forget to update AddNodeIDNode() and SDNode::dump() in > SelectionDAG.cpp. > > Thanks, > > Evan > > On Jun 19, 2008, at 6:19 PM, Mon P Wang wrote: > >> Hi, >> >> Like loads/stores, atomics touches memory and should have an >> associated MemOperand with the operation. The following patch >> creates an abstract class MemSDNode that all nodes which have an >> associated MemOperand need to inherit to. It also creates a new >> property SDNPMemOperand that indicates that a node touches memory >> and has an associated MemOperand.If you have any comments, please >> let me know. >> >> Thanks, >> -- Mon Ping >> >> _______________________________________________ >> llvm-commits mailing list >> llvm-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From matthijs at stdin.nl Fri Jun 20 02:57:50 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Fri, 20 Jun 2008 09:57:50 +0200 Subject: [llvm-commits] [llvm] r52520 - /llvm/trunk/lib/Transforms/Scalar/SCCP.cpp In-Reply-To: <200806200115.m5K1FjhV016990@zion.cs.uiuc.edu> References: <200806200115.m5K1FjhV016990@zion.cs.uiuc.edu> Message-ID: <20080620075750.GC3816@katherina.student.utwente.nl> Hi Dan, good to see SCCP now knows about insert/extractvalue, that means I can remove my local hack to suppress its warnings :-) Yet, isn't the handling it does now (mainly tracking return values) a duplicate effort with IPConstProp? Or does SCCP do other things that make it more useful than IPCP for this stuff? > +void SCCPSolver::visitExtractValueInst(ExtractValueInst &EVI) { > + Value *Aggr = EVI.getOperand(0); You'd better use getAggregateOperand() for that? > + > + // If the operand to the getresult is an undef, the result is undef. > + if (isa(Aggr)) > + return; > + > + // Currently only handle single-index extractvalues. > + if (EVI.getNumIndices() != 1) { > + markOverdefined(&EVI); > + return; > + } > + > + Function *F = 0; > + if (CallInst *CI = dyn_cast(Aggr)) > + F = CI->getCalledFunction(); > + else if (InvokeInst *II = dyn_cast(Aggr)) > + F = II->getCalledFunction(); > + > + // TODO: If IPSCCP resolves the callee of this function, we could propagate a > + // result back! What do you mean by this? Are you considering the case where you visit the extractvalue instruction on the result before the insertvalue instruction for the return value? > +void SCCPSolver::visitInsertValueInst(InsertValueInst &IVI) { > + Value *Aggr = IVI.getOperand(0); Again, you should use getAggregateOperand(). > + Value *Val = IVI.getOperand(1); And getInsertedValueOperand() here. > + // If the operand to the getresult is an undef, the result is undef. That should be insertvalue, not getresult? > + if (isa(Aggr)) > + return; > + > + // Currently only handle single-index insertvalues. > + if (IVI.getNumIndices() != 1) { > + markOverdefined(&IVI); > + return; > + } > + > + // See if we are tracking the result of the callee. > + Function *F = IVI.getParent()->getParent(); > + std::map, LatticeVal>::iterator > + It = TrackedMultipleRetVals.find(std::make_pair(F, *IVI.idx_begin())); > + > + // Merge in the inserted member value. > + if (It != TrackedMultipleRetVals.end()) > + mergeInValue(It->second, F, getValueState(Val)); > + > + // Mark the aggregate result of the IVI overdefined; any tracking that we do will > + // be done on the individual member values. > + markOverdefined(&IVI); > +} From looking at this code, it seems that you are assuming that all insertvalue instructions are used to build return values. From the looks of it, I could fool SCCP into propagting the wrong constant, though I don't really know how SCPP works. > + // The aggregate value is used in a way not handled here. Assume nothing. > + markOverdefined(*UI); Shouldn't that be return value isntead of aggregate value? Gr. Matthijs -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: Digital signature Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080620/11c7568a/attachment.bin From resistor at mac.com Fri Jun 20 03:59:15 2008 From: resistor at mac.com (Owen Anderson) Date: Fri, 20 Jun 2008 08:59:15 -0000 Subject: [llvm-commits] [llvm] r52531 - /llvm/trunk/lib/Transforms/Scalar/GVN.cpp Message-ID: <200806200859.m5K8xFA7008639@zion.cs.uiuc.edu> Author: resistor Date: Fri Jun 20 03:59:13 2008 New Revision: 52531 URL: http://llvm.org/viewvc/llvm-project?rev=52531&view=rev Log: Really disable PRE. Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=52531&r1=52530&r2=52531&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Fri Jun 20 03:59:13 2008 @@ -1328,7 +1328,7 @@ DE = df_end(DT.getRootNode()); DI != DE; ++DI) changed |= processBlock(*DI); - if (!EnablePRE) + if (EnablePRE) changed |= performPRE(F); return changed; From matthijs at stdin.nl Fri Jun 20 04:18:48 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Fri, 20 Jun 2008 11:18:48 +0200 Subject: [llvm-commits] Dead argument elimination rewrite In-Reply-To: <01832B5C-3190-4B8D-8DE3-DA0EC96B9258@apple.com> References: <20080616153738.GN2636@katherina.student.utwente.nl> <20080617084400.GC16202@katherina.student.utwente.nl> <01FEB911-9233-424C-9242-091FC0E135DC@apple.com> <20080619155622.GA3816@katherina.student.utwente.nl> <01832B5C-3190-4B8D-8DE3-DA0EC96B9258@apple.com> Message-ID: <20080620091848.GD3816@katherina.student.utwente.nl> > Ok. I mainly just wanted to get a sense of compile time on some > non-trivial real-world code. The STL associative containers have > a mixed reputation around here.. From looking at the full llvm-test suite, it seems that compile times are not drastically different. On average, I think they might have improved by a few percent. I've also found no other broken compilation after fixing my patch. I was having some trouble with the archie test, but it seems some other commit from the last two or three days broke that. From some investigation, it seems that there is some inline asm that cbe emits wrongly. I've added a comment to PR802 about this. Gr. Matthijs -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 189 bytes Desc: Digital signature Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080620/1d896bba/attachment.bin From matthijs at stdin.nl Fri Jun 20 04:36:17 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Fri, 20 Jun 2008 09:36:17 -0000 Subject: [llvm-commits] [llvm] r52532 - in /llvm/trunk: lib/Transforms/IPO/DeadArgumentElimination.cpp test/Transforms/DeadArgElim/multdeadretval.ll Message-ID: <200806200936.m5K9aIZR010499@zion.cs.uiuc.edu> Author: matthijs Date: Fri Jun 20 04:36:16 2008 New Revision: 52532 URL: http://llvm.org/viewvc/llvm-project?rev=52532&view=rev Log: Recommit r52459, rewriting of the dead argument elimination pass. This is a fixed version that no longer uses multimap::equal_range, which resulted in a pointer invalidation problem. Also, DAE::InspectedFunctions was not really necessary, so it got removed. Lastly, this version no longer applies the extra arg hack on functions who did not have any arguments to start with. Added: llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll - copied unchanged from r52459, llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll Modified: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Modified: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp?rev=52532&r1=52531&r2=52532&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp (original) +++ llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Fri Jun 20 04:36:16 2008 @@ -10,10 +10,10 @@ // This pass deletes dead arguments from internal functions. Dead argument // elimination removes arguments which are directly dead, as well as arguments // only passed into function calls as dead arguments of other functions. This -// pass also deletes dead arguments in a similar way. +// pass also deletes dead return values in a similar way. // // This pass is often useful as a cleanup pass to run after aggressive -// interprocedural passes, which add possibly-dead arguments. +// interprocedural passes, which add possibly-dead arguments or return values. // //===----------------------------------------------------------------------===// @@ -42,40 +42,66 @@ /// DAE - The dead argument elimination pass. /// class VISIBILITY_HIDDEN DAE : public ModulePass { + public: + + /// Struct that represent either a (part of a) return value or a function + /// argument. Used so that arguments and return values can be used + /// interchangably. + struct RetOrArg { + RetOrArg(const Function* F, unsigned Idx, bool IsArg) : F(F), Idx(Idx), IsArg(IsArg) {} + const Function *F; + unsigned Idx; + bool IsArg; + + /// Make RetOrArg comparable, so we can put it into a map + bool operator<(const RetOrArg &O) const { + if (F != O.F) + return F < O.F; + else if (Idx != O.Idx) + return Idx < O.Idx; + else + return IsArg < O.IsArg; + } + + /// Make RetOrArg comparable, so we can easily iterate the multimap + bool operator==(const RetOrArg &O) const { + return F == O.F && Idx == O.Idx && IsArg == O.IsArg; + } + }; + /// Liveness enum - During our initial pass over the program, we determine /// that things are either definately alive, definately dead, or in need of /// interprocedural analysis (MaybeLive). /// enum Liveness { Live, MaybeLive, Dead }; - /// LiveArguments, MaybeLiveArguments, DeadArguments - These sets contain - /// all of the arguments in the program. The Dead set contains arguments - /// which are completely dead (never used in the function). The MaybeLive - /// set contains arguments which are only passed into other function calls, - /// thus may be live and may be dead. The Live set contains arguments which - /// are known to be alive. - /// - std::set DeadArguments, MaybeLiveArguments, LiveArguments; - - /// DeadRetVal, MaybeLiveRetVal, LifeRetVal - These sets contain all of the - /// functions in the program. The Dead set contains functions whose return - /// value is known to be dead. The MaybeLive set contains functions whose - /// return values are only used by return instructions, and the Live set - /// contains functions whose return values are used, functions that are - /// external, and functions that already return void. - /// - std::set DeadRetVal, MaybeLiveRetVal, LiveRetVal; - - /// InstructionsToInspect - As we mark arguments and return values - /// MaybeLive, we keep track of which instructions could make the values - /// live here. Once the entire program has had the return value and - /// arguments analyzed, this set is scanned to promote the MaybeLive objects - /// to be Live if they really are used. - std::vector InstructionsToInspect; - - /// CallSites - Keep track of the call sites of functions that have - /// MaybeLive arguments or return values. - std::multimap CallSites; + /// Convenience wrapper + RetOrArg CreateRet(const Function *F, unsigned Idx) { return RetOrArg(F, Idx, false); } + /// Convenience wrapper + RetOrArg CreateArg(const Function *F, unsigned Idx) { return RetOrArg(F, Idx, true); } + + typedef std::multimap UseMap; + /// This map maps a return value or argument to all return values or + /// arguments it uses. + /// For example (indices are left out for clarity): + /// - Uses[ret F] = ret G + /// This means that F calls G, and F returns the value returned by G. + /// - Uses[arg F] = ret G + /// This means that some function calls G and passes its result as an + /// argument to F. + /// - Uses[ret F] = arg F + /// This means that F returns one of its own arguments. + /// - Uses[arg F] = arg G + /// This means that G calls F and passes one of its own (G's) arguments + /// directly to F. + UseMap Uses; + + typedef std::set LiveSet; + + /// This set contains all values that have been determined to be live + LiveSet LiveValues; + + typedef SmallVector UseVector; public: static char ID; // Pass identification, replacement for typeid @@ -85,20 +111,19 @@ virtual bool ShouldHackArguments() const { return false; } private: - Liveness getArgumentLiveness(const Argument &A); - bool isMaybeLiveArgumentNowLive(Argument *Arg); - + Liveness IsMaybeLive(RetOrArg Use, UseVector &MaybeLiveUses); + Liveness SurveyUse(Value::use_iterator U, UseVector &MaybeLiveUses, unsigned RetValNum = 0); + Liveness SurveyUses(Value *V, UseVector &MaybeLiveUses); + + void SurveyFunction(Function &F); + void MarkValue(const RetOrArg &RA, Liveness L, const UseVector &MaybeLiveUses); + void MarkLive(RetOrArg RA); + bool RemoveDeadStuffFromFunction(Function *F); bool DeleteDeadVarargs(Function &Fn); - void SurveyFunction(Function &Fn); - - void MarkArgumentLive(Argument *Arg); - void MarkRetValLive(Function *F); - void MarkReturnInstArgumentLive(ReturnInst *RI); - - void RemoveDeadArgumentsFromFunction(Function *F); }; } + char DAE::ID = 0; static RegisterPass X("deadargelim", "Dead Argument Elimination"); @@ -155,7 +180,7 @@ // remove the "..." and adjust all the calls. // Start by computing a new prototype for the function, which is the same as - // the old function, but has fewer arguments. + // the old function, but doesn't have isVarArg set. const FunctionType *FTy = Fn.getFunctionType(); std::vector Params(FTy->param_begin(), FTy->param_end()); FunctionType *NFTy = FunctionType::get(FTy->getReturnType(), Params, false); @@ -233,57 +258,110 @@ return true; } +/// Convenience function that returns the number of return values. It returns 0 +/// for void functions and 1 for functions not returning a struct. It returns +/// the number of struct elements for functions returning a struct. +static unsigned NumRetVals(const Function *F) { + if (F->getReturnType() == Type::VoidTy) + return 0; + else if (const StructType *STy = dyn_cast(F->getReturnType())) + return STy->getNumElements(); + else + return 1; +} -static inline bool CallPassesValueThoughVararg(Instruction *Call, - const Value *Arg) { - CallSite CS = CallSite::get(Call); - const Type *CalledValueTy = CS.getCalledValue()->getType(); - const Type *FTy = cast(CalledValueTy)->getElementType(); - unsigned NumFixedArgs = cast(FTy)->getNumParams(); - for (CallSite::arg_iterator AI = CS.arg_begin()+NumFixedArgs; - AI != CS.arg_end(); ++AI) - if (AI->get() == Arg) - return true; - return false; -} - -// getArgumentLiveness - Inspect an argument, determining if is known Live -// (used in a computation), MaybeLive (only passed as an argument to a call), or -// Dead (not used). -DAE::Liveness DAE::getArgumentLiveness(const Argument &A) { - const Function *F = A.getParent(); - - // If this is the return value of a struct function, it's not really dead. - if (F->hasStructRetAttr() && &*(F->arg_begin()) == &A) +/// IsMaybeAlive - This checks Use for liveness. If Use is live, returns Live, +/// else returns MaybeLive. Also, adds Use to MaybeLiveUses in the latter case. +DAE::Liveness DAE::IsMaybeLive(RetOrArg Use, UseVector &MaybeLiveUses) { + // We're live if our use is already marked as live + if (LiveValues.count(Use)) return Live; - - if (A.use_empty()) // First check, directly dead? - return Dead; - // Scan through all of the uses, looking for non-argument passing uses. - for (Value::use_const_iterator I = A.use_begin(), E = A.use_end(); I!=E;++I) { - // Return instructions do not immediately effect liveness. - if (isa(*I)) - continue; - - CallSite CS = CallSite::get(const_cast(*I)); - if (!CS.getInstruction()) { - // If its used by something that is not a call or invoke, it's alive! - return Live; - } - // If it's an indirect call, mark it alive... - Function *Callee = CS.getCalledFunction(); - if (!Callee) return Live; - - // Check to see if it's passed through a va_arg area: if so, we cannot - // remove it. - if (CallPassesValueThoughVararg(CS.getInstruction(), &A)) - return Live; // If passed through va_arg area, we cannot remove it - } + // We're maybe live otherwise, but remember that we must become live if + // Use becomes live. + MaybeLiveUses.push_back(Use); + return MaybeLive; +} + + +/// SurveyUse - This looks at a single use of an argument or return value +/// and determines if it should be alive or not. Adds this use to MaybeLiveUses +/// if it causes the used value to become MaybeAlive. +/// +/// RetValNum is the return value number to use when this use is used in a +/// return instruction. This is used in the recursion, you should always leave +/// it at 0. +DAE::Liveness DAE::SurveyUse(Value::use_iterator U, UseVector &MaybeLiveUses, unsigned RetValNum) { + Value *V = *U; + if (ReturnInst *RI = dyn_cast(V)) { + // The value is returned from another function. It's only live when the + // caller's return value is live + RetOrArg Use = CreateRet(RI->getParent()->getParent(), RetValNum); + // We might be live, depending on the liveness of Use + return IsMaybeLive(Use, MaybeLiveUses); + } + if (InsertValueInst *IV = dyn_cast(V)) { + if (U.getOperandNo() != InsertValueInst::getAggregateOperandIndex() && IV->hasIndices()) + // The use we are examining is inserted into an aggregate. Our liveness + // depends on all uses of that aggregate, but if it is used as a return + // value, only index at which we were inserted counts. + RetValNum = *IV->idx_begin(); - return MaybeLive; // It must be used, but only as argument to a function + // Note that if we are used as the aggregate operand to the insertvalue, + // we don't change RetValNum, but do survey all our uses. + + Liveness Result = Dead; + for (Value::use_iterator I = IV->use_begin(), + E = V->use_end(); I != E; ++I) { + Result = SurveyUse(I, MaybeLiveUses, RetValNum); + if (Result == Live) + break; + } + return Result; + } + CallSite CS = CallSite::get(V); + if (CS.getInstruction()) { + Function *F = CS.getCalledFunction(); + if (F) { + // Used in a direct call + + // Check for vararg. Do - 1 to skip the first operand to call (the + // function itself). + if (U.getOperandNo() - 1 >= F->getFunctionType()->getNumParams()) + // The value is passed in through a vararg! Must be live. + return Live; + + // Value passed to a normal call. It's only live when the corresponding + // argument (operand number - 1 to skip the function pointer operand) to + // the called function turns out live + RetOrArg Use = CreateArg(F, U.getOperandNo() - 1); + return IsMaybeLive(Use, MaybeLiveUses); + } else { + // Used in any other way? Value must be live. + return Live; + } + } + // Used in any other way? Value must be live. + return Live; } +/// SurveyUses - This looks at all the uses of the given return value +/// (possibly a partial return value from a function returning a struct). +/// Returns the Liveness deduced from the uses of this value. +/// +/// Adds all uses that cause the result to be MaybeLive to MaybeLiveRetUses. +DAE::Liveness DAE::SurveyUses(Value *V, UseVector &MaybeLiveUses) { + // Assume it's dead (which will only hold if there are no uses at all..) + Liveness Result = Dead; + // Check each use + for (Value::use_iterator I = V->use_begin(), + E = V->use_end(); I != E; ++I) { + Result = SurveyUse(I, MaybeLiveUses); + if (Result == Live) + break; + } + return Result; +} // SurveyFunction - This performs the initial survey of the specified function, // checking out whether or not it uses any of its incoming arguments or whether @@ -295,12 +373,36 @@ // void DAE::SurveyFunction(Function &F) { bool FunctionIntrinsicallyLive = false; - Liveness RetValLiveness = F.getReturnType() == Type::VoidTy ? Live : Dead; + unsigned RetCount = NumRetVals(&F); + // Assume all return values are dead + typedef SmallVector RetVals; + RetVals RetValLiveness(RetCount, Dead); + + // These vectors maps each return value to the uses that make it MaybeLive, so + // we can add those to the MaybeLiveRetVals list if the return value + // really turns out to be MaybeLive. Initializes to RetCount empty vectors + typedef SmallVector RetUses; + // Intialized to a list of RetCount empty lists + RetUses MaybeLiveRetUses(RetCount); + + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + if (ReturnInst *RI = dyn_cast(BB->getTerminator())) + if (RI->getNumOperands() != 0 && RI->getOperand(0)->getType() != F.getFunctionType()->getReturnType()) { + // We don't support old style multiple return values + FunctionIntrinsicallyLive = true; + break; + } - if (!F.hasInternalLinkage() && - (!ShouldHackArguments() || F.isIntrinsic())) + if (!F.hasInternalLinkage() && (!ShouldHackArguments() || F.isIntrinsic())) FunctionIntrinsicallyLive = true; - else + + if (!FunctionIntrinsicallyLive) { + DOUT << "DAE - Inspecting callers for fn: " << F.getName() << "\n"; + // Keep track of the number of live retvals, so we can skip checks once all + // of them turn out to be live. + unsigned NumLiveRetVals = 0; + const Type *STy = dyn_cast(F.getReturnType()); + // Loop all uses of the function for (Value::use_iterator I = F.use_begin(), E = F.use_end(); I != E; ++I) { // If the function is PASSED IN as an argument, its address has been taken if (I.getOperandNo() != 0) { @@ -315,191 +417,141 @@ FunctionIntrinsicallyLive = true; break; } - - // Check to see if the return value is used... - if (RetValLiveness != Live) - for (Value::use_iterator I = TheCall->use_begin(), - E = TheCall->use_end(); I != E; ++I) - if (isa(cast(*I))) { - RetValLiveness = MaybeLive; - } else if (isa(cast(*I)) || - isa(cast(*I))) { - if (CallPassesValueThoughVararg(cast(*I), TheCall) || - !CallSite::get(cast(*I)).getCalledFunction()) { - RetValLiveness = Live; - break; + + // If we end up here, we are looking at a direct call to our function. + + // Now, check how our return value(s) is/are used in this caller. Don't + // bother checking return values if all of them are live already + if (NumLiveRetVals != RetCount) { + if (STy) { + // Check all uses of the return value + for (Value::use_iterator I = TheCall->use_begin(), + E = TheCall->use_end(); I != E; ++I) { + ExtractValueInst *Ext = dyn_cast(*I); + if (Ext && Ext->hasIndices()) { + // This use uses a part of our return value, survey the uses of that + // part and store the results for this index only. + unsigned Idx = *Ext->idx_begin(); + if (RetValLiveness[Idx] != Live) { + RetValLiveness[Idx] = SurveyUses(Ext, MaybeLiveRetUses[Idx]); + if (RetValLiveness[Idx] == Live) + NumLiveRetVals++; + } } else { - RetValLiveness = MaybeLive; + // Used by something else than extractvalue. Mark all + // return values as live. + for (unsigned i = 0; i != RetCount; ++i ) + RetValLiveness[i] = Live; + NumLiveRetVals = RetCount; + break; } - } else { - RetValLiveness = Live; - break; } + } else { + // Single return value + RetValLiveness[0] = SurveyUses(TheCall, MaybeLiveRetUses[0]); + if (RetValLiveness[0] == Live) + NumLiveRetVals = RetCount; + } + } } - + } if (FunctionIntrinsicallyLive) { - DOUT << " Intrinsically live fn: " << F.getName() << "\n"; + DOUT << "DAE - Intrinsically live fn: " << F.getName() << "\n"; + // Mark all arguments as live + unsigned i = 0; for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end(); - AI != E; ++AI) - LiveArguments.insert(AI); - LiveRetVal.insert(&F); + AI != E; ++AI, ++i) + MarkLive(CreateArg(&F, i)); + // Mark all return values as live + i = 0; + for (unsigned i = 0, e = RetValLiveness.size(); i != e; ++i) + MarkLive(CreateRet(&F, i)); return; } - - switch (RetValLiveness) { - case Live: LiveRetVal.insert(&F); break; - case MaybeLive: MaybeLiveRetVal.insert(&F); break; - case Dead: DeadRetVal.insert(&F); break; + + // Now we've inspected all callers, record the liveness of our return values. + for (unsigned i = 0, e = RetValLiveness.size(); i != e; ++i) { + RetOrArg Ret = CreateRet(&F, i); + // Mark the result down + MarkValue(Ret, RetValLiveness[i], MaybeLiveRetUses[i]); + } + DOUT << "DAE - Inspecting args for fn: " << F.getName() << "\n"; + + // Now, check all of our arguments + unsigned i = 0; + UseVector MaybeLiveArgUses; + for (Function::arg_iterator AI = F.arg_begin(), + E = F.arg_end(); AI != E; ++AI, ++i) { + // See what the effect of this use is (recording any uses that cause + // MaybeLive in MaybeLiveArgUses) + Liveness Result = SurveyUses(AI, MaybeLiveArgUses); + RetOrArg Arg = CreateArg(&F, i); + // Mark the result down + MarkValue(Arg, Result, MaybeLiveArgUses); + // Clear the vector again for the next iteration + MaybeLiveArgUses.clear(); } +} - DOUT << " Inspecting args for fn: " << F.getName() << "\n"; - - // If it is not intrinsically alive, we know that all users of the - // function are call sites. Mark all of the arguments live which are - // directly used, and keep track of all of the call sites of this function - // if there are any arguments we assume that are dead. - // - bool AnyMaybeLiveArgs = false; - for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end(); - AI != E; ++AI) - switch (getArgumentLiveness(*AI)) { - case Live: - DOUT << " Arg live by use: " << AI->getName() << "\n"; - LiveArguments.insert(AI); - break; - case Dead: - DOUT << " Arg definitely dead: " << AI->getName() <<"\n"; - DeadArguments.insert(AI); - break; +/// MarkValue - This function marks the liveness of RA depending on L. If L is +/// MaybeLive, it also records any uses in MaybeLiveUses such that RA will be +/// marked live if any use in MaybeLiveUses gets marked live later on. +void DAE::MarkValue(const RetOrArg &RA, Liveness L, const UseVector &MaybeLiveUses) { + switch (L) { + case Live: MarkLive(RA); break; case MaybeLive: - DOUT << " Arg only passed to calls: " << AI->getName() << "\n"; - AnyMaybeLiveArgs = true; - MaybeLiveArguments.insert(AI); + { + // Note any uses of this value, so this return value can be + // marked live whenever one of the uses becomes live. + UseMap::iterator Where = Uses.begin(); + for (UseVector::const_iterator UI = MaybeLiveUses.begin(), + UE = MaybeLiveUses.end(); UI != UE; ++UI) + Where = Uses.insert(Where, UseMap::value_type(*UI, RA)); break; } - - // If there are any "MaybeLive" arguments, we need to check callees of - // this function when/if they become alive. Record which functions are - // callees... - if (AnyMaybeLiveArgs || RetValLiveness == MaybeLive) - for (Value::use_iterator I = F.use_begin(), E = F.use_end(); - I != E; ++I) { - if (AnyMaybeLiveArgs) - CallSites.insert(std::make_pair(&F, CallSite::get(*I))); - - if (RetValLiveness == MaybeLive) - for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); - UI != E; ++UI) - InstructionsToInspect.push_back(cast(*UI)); - } -} - -// isMaybeLiveArgumentNowLive - Check to see if Arg is alive. At this point, we -// know that the only uses of Arg are to be passed in as an argument to a -// function call or return. Check to see if the formal argument passed in is in -// the LiveArguments set. If so, return true. -// -bool DAE::isMaybeLiveArgumentNowLive(Argument *Arg) { - for (Value::use_iterator I = Arg->use_begin(), E = Arg->use_end(); I!=E; ++I){ - if (isa(*I)) { - if (LiveRetVal.count(Arg->getParent())) return true; - continue; - } - - CallSite CS = CallSite::get(*I); - - // We know that this can only be used for direct calls... - Function *Callee = CS.getCalledFunction(); - - // Loop over all of the arguments (because Arg may be passed into the call - // multiple times) and check to see if any are now alive... - CallSite::arg_iterator CSAI = CS.arg_begin(); - for (Function::arg_iterator AI = Callee->arg_begin(), E = Callee->arg_end(); - AI != E; ++AI, ++CSAI) - // If this is the argument we are looking for, check to see if it's alive - if (*CSAI == Arg && LiveArguments.count(AI)) - return true; - } - return false; -} - -/// MarkArgumentLive - The MaybeLive argument 'Arg' is now known to be alive. -/// Mark it live in the specified sets and recursively mark arguments in callers -/// live that are needed to pass in a value. -/// -void DAE::MarkArgumentLive(Argument *Arg) { - std::set::iterator It = MaybeLiveArguments.lower_bound(Arg); - if (It == MaybeLiveArguments.end() || *It != Arg) return; - - DOUT << " MaybeLive argument now live: " << Arg->getName() <<"\n"; - MaybeLiveArguments.erase(It); - LiveArguments.insert(Arg); - - // Loop over all of the call sites of the function, making any arguments - // passed in to provide a value for this argument live as necessary. - // - Function *Fn = Arg->getParent(); - unsigned ArgNo = std::distance(Fn->arg_begin(), Function::arg_iterator(Arg)); - - std::multimap::iterator I = CallSites.lower_bound(Fn); - for (; I != CallSites.end() && I->first == Fn; ++I) { - CallSite CS = I->second; - Value *ArgVal = *(CS.arg_begin()+ArgNo); - if (Argument *ActualArg = dyn_cast(ArgVal)) { - MarkArgumentLive(ActualArg); - } else { - // If the value passed in at this call site is a return value computed by - // some other call site, make sure to mark the return value at the other - // call site as being needed. - CallSite ArgCS = CallSite::get(ArgVal); - if (ArgCS.getInstruction()) - if (Function *Fn = ArgCS.getCalledFunction()) - MarkRetValLive(Fn); - } + case Dead: break; } } -/// MarkArgumentLive - The MaybeLive return value for the specified function is -/// now known to be alive. Propagate this fact to the return instructions which -/// produce it. -void DAE::MarkRetValLive(Function *F) { - assert(F && "Shame shame, we can't have null pointers here!"); - - // Check to see if we already knew it was live - std::set::iterator I = MaybeLiveRetVal.lower_bound(F); - if (I == MaybeLiveRetVal.end() || *I != F) return; // It's already alive! - - DOUT << " MaybeLive retval now live: " << F->getName() << "\n"; - - MaybeLiveRetVal.erase(I); - LiveRetVal.insert(F); // It is now known to be live! +/// MarkLive - Mark the given return value or argument as live. Additionally, +/// mark any values that are used by this value (according to Uses) live as +/// well. +void DAE::MarkLive(RetOrArg RA) { + if (!LiveValues.insert(RA).second) + return; // We were already marked Live - // Loop over all of the functions, noticing that the return value is now live. - for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) - if (ReturnInst *RI = dyn_cast(BB->getTerminator())) - MarkReturnInstArgumentLive(RI); -} - -void DAE::MarkReturnInstArgumentLive(ReturnInst *RI) { - Value *Op = RI->getOperand(0); - if (Argument *A = dyn_cast(Op)) { - MarkArgumentLive(A); - } else if (CallInst *CI = dyn_cast(Op)) { - if (Function *F = CI->getCalledFunction()) - MarkRetValLive(F); - } else if (InvokeInst *II = dyn_cast(Op)) { - if (Function *F = II->getCalledFunction()) - MarkRetValLive(F); - } -} + if (RA.IsArg) + DOUT << "DAE - Marking argument " << RA.Idx << " to function " << RA.F->getNameStart() << " live\n"; + else + DOUT << "DAE - Marking return value " << RA.Idx << " of function " << RA.F->getNameStart() << " live\n"; -// RemoveDeadArgumentsFromFunction - We know that F has dead arguments, as + // We don't use upper_bound (or equal_range) here, because our recursive call + // to ourselves is likely to mark the upper_bound (which is the first value + // not belonging to RA) to become erased and the iterator invalidated. + UseMap::iterator Begin = Uses.lower_bound(RA); + UseMap::iterator E = Uses.end(); + UseMap::iterator I; + for (I = Begin; I != E && I->first == RA; ++I) + MarkLive(I->second); + + // Erase RA from the Uses map (from the lower bound to wherever we ended up + // after the loop). + Uses.erase(Begin, I); +} + +// RemoveDeadStuffFromFunction - Remove any arguments and return values from F +// that are not in LiveValues. This function is a noop for any Function created +// by this function before, or any function that was not inspected for liveness. // specified by the DeadArguments list. Transform the function and all of the // callees of the function to not have these arguments. // -void DAE::RemoveDeadArgumentsFromFunction(Function *F) { +bool DAE::RemoveDeadStuffFromFunction(Function *F) { + // Quick exit path for external functions + if (!F->hasInternalLinkage() && (!ShouldHackArguments() || F->isIntrinsic())) + return false; + // Start by computing a new prototype for the function, which is the same as - // the old function, but has fewer arguments. + // the old function, but has fewer arguments and a different return type. const FunctionType *FTy = F->getFunctionType(); std::vector Params; @@ -510,28 +562,78 @@ // The existing function return attributes. ParameterAttributes RAttrs = PAL.getParamAttrs(0); - // Make the function return void if the return value is dead. + + // Find out the new return value + const Type *RetTy = FTy->getReturnType(); - if (DeadRetVal.count(F)) { - RetTy = Type::VoidTy; - RAttrs &= ~ParamAttr::typeIncompatible(RetTy); - DeadRetVal.erase(F); - } - + const Type *NRetTy; + unsigned RetCount = NumRetVals(F); + // -1 means unused, other numbers are the new index + SmallVector NewRetIdxs(RetCount, -1); + std::vector RetTypes; + if (RetTy != Type::VoidTy) { + const StructType *STy = dyn_cast(RetTy); + if (STy) + // Look at each of the original return values individually + for (unsigned i = 0; i != RetCount; ++i) { + RetOrArg Ret = CreateRet(F, i); + if (LiveValues.erase(Ret)) { + RetTypes.push_back(STy->getElementType(i)); + NewRetIdxs[i] = RetTypes.size() - 1; + } else { + ++NumRetValsEliminated; + DOUT << "DAE - Removing return value " << i << " from " << F->getNameStart() << "\n"; + } + } + else + // We used to return a single value + if (LiveValues.erase(CreateRet(F, 0))) { + RetTypes.push_back(RetTy); + NewRetIdxs[0] = 0; + } else { + DOUT << "DAE - Removing return value from " << F->getNameStart() << "\n"; + ++NumRetValsEliminated; + } + if (RetTypes.size() == 0) + // No return types? Make it void + NRetTy = Type::VoidTy; + else if (RetTypes.size() == 1) + // One return type? Just a simple value then + NRetTy = RetTypes.front(); + else + // More return types? Return a struct with them + NRetTy = StructType::get(RetTypes); + } else { + NRetTy = Type::VoidTy; + } + + // Remove any incompatible attributes + RAttrs &= ~ParamAttr::typeIncompatible(NRetTy); if (RAttrs) ParamAttrsVec.push_back(ParamAttrsWithIndex::get(0, RAttrs)); - + + // Remember which arguments are still alive + SmallVector ArgAlive(FTy->getNumParams(), false); // Construct the new parameter list from non-dead arguments. Also construct - // a new set of parameter attributes to correspond. - unsigned index = 1; - for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; - ++I, ++index) - if (!DeadArguments.count(I)) { + // a new set of parameter attributes to correspond. Skip the first parameter + // attribute, since that belongs to the return value. + unsigned i = 0; + for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); + I != E; ++I, ++i) { + RetOrArg Arg = CreateArg(F, i); + if (LiveValues.erase(Arg)) { Params.push_back(I->getType()); + ArgAlive[i] = true; - if (ParameterAttributes Attrs = PAL.getParamAttrs(index)) + // Get the original parameter attributes (skipping the first one, that is + // for the return value + if (ParameterAttributes Attrs = PAL.getParamAttrs(i + 1)) ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Params.size(), Attrs)); + } else { + ++NumArgumentsEliminated; + DOUT << "DAE - Removing argument " << i << " (" << I->getNameStart() << ") from " << F->getNameStart() << "\n"; } + } // Reconstruct the ParamAttrsList based on the vector we constructed. PAListPtr NewPAL = PAListPtr::get(ParamAttrsVec.begin(), ParamAttrsVec.end()); @@ -539,19 +641,28 @@ // Work around LLVM bug PR56: the CWriter cannot emit varargs functions which // have zero fixed arguments. // + // Not that we apply this hack for a vararg fuction that does not have any + // arguments anymore, but did have them before (so don't bother fixing + // functions that were already broken wrt CWriter). bool ExtraArgHack = false; - if (Params.empty() && FTy->isVarArg()) { + if (Params.empty() && FTy->isVarArg() && FTy->getNumParams() != 0) { ExtraArgHack = true; Params.push_back(Type::Int32Ty); } // Create the new function type based on the recomputed parameters. - FunctionType *NFTy = FunctionType::get(RetTy, Params, FTy->isVarArg()); + FunctionType *NFTy = FunctionType::get(NRetTy, Params, FTy->isVarArg()); + + // No change? + if (NFTy == FTy) + return false; // Create the new function body and insert it into the module... Function *NF = Function::Create(NFTy, F->getLinkage()); NF->copyAttributesFrom(F); NF->setParamAttrs(NewPAL); + // Insert the new function before the old function, so we won't be processing + // it again F->getParent()->getFunctionList().insert(F, NF); NF->takeName(F); @@ -562,6 +673,11 @@ while (!F->use_empty()) { CallSite CS = CallSite::get(F->use_back()); Instruction *Call = CS.getInstruction(); + if (!Call) { + DOUT << "Old: " << *FTy << "\n"; + DOUT << "New: " << *NFTy << "\n"; + } + ParamAttrsVec.clear(); const PAListPtr &CallPAL = CS.getParamAttrs(); @@ -572,14 +688,17 @@ if (RAttrs) ParamAttrsVec.push_back(ParamAttrsWithIndex::get(0, RAttrs)); - // Loop over the operands, deleting dead ones... - CallSite::arg_iterator AI = CS.arg_begin(); - index = 1; - for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); - I != E; ++I, ++AI, ++index) - if (!DeadArguments.count(I)) { // Remove operands for dead arguments - Args.push_back(*AI); - if (ParameterAttributes Attrs = CallPAL.getParamAttrs(index)) + // Declare these outside of the loops, so we can reuse them for the second + // loop, which loops the varargs + CallSite::arg_iterator I = CS.arg_begin(); + unsigned i = 0; + // Loop over those operands, corresponding to the normal arguments to the + // original function, and add those that are still alive. + for (unsigned e = FTy->getNumParams(); i != e; ++I, ++i) + if (ArgAlive[i]) { + Args.push_back(*I); + // Get original parameter attributes, but skip return attributes + if (ParameterAttributes Attrs = CallPAL.getParamAttrs(i + 1)) ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Args.size(), Attrs)); } @@ -587,9 +706,9 @@ Args.push_back(UndefValue::get(Type::Int32Ty)); // Push any varargs arguments on the list. Don't forget their attributes. - for (; AI != CS.arg_end(); ++AI) { - Args.push_back(*AI); - if (ParameterAttributes Attrs = CallPAL.getParamAttrs(index++)) + for (CallSite::arg_iterator E = CS.arg_end(); I != E; ++I, ++i) { + Args.push_back(*I); + if (ParameterAttributes Attrs = CallPAL.getParamAttrs(i + 1)) ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Args.size(), Attrs)); } @@ -614,8 +733,45 @@ if (!Call->use_empty()) { if (New->getType() == Type::VoidTy) + // Our return value was unused, replace by null for now, uses will get + // removed later on Call->replaceAllUsesWith(Constant::getNullValue(Call->getType())); - else { + else if (isa(RetTy)) { + // The original return value was a struct, update all uses (which are + // all extractvalue instructions). + for (Value::use_iterator I = Call->use_begin(), E = Call->use_end(); + I != E;) { + assert(isa(*I) && "Return value not only used by extractvalue?"); + ExtractValueInst *EV = cast(*I); + // Increment now, since we're about to throw away this use. + ++I; + assert(EV->hasIndices() && "Return value used by extractvalue without indices?"); + unsigned Idx = *EV->idx_begin(); + if (NewRetIdxs[Idx] != -1) { + if (RetTypes.size() > 1) { + // We're still returning a struct, create a new extractvalue + // instruction with the first index updated + std::vector NewIdxs(EV->idx_begin(), EV->idx_end()); + NewIdxs[0] = NewRetIdxs[Idx]; + Value *NEV = ExtractValueInst::Create(New, NewIdxs.begin(), NewIdxs.end(), "retval", EV); + EV->replaceAllUsesWith(NEV); + EV->eraseFromParent(); + } else { + // We are now only returning a simple value, remove the + // extractvalue + EV->replaceAllUsesWith(New); + EV->eraseFromParent(); + } + } else { + // Value unused, replace uses by null for now, they will get removed + // later on + EV->replaceAllUsesWith(Constant::getNullValue(EV->getType())); + EV->eraseFromParent(); + } + } + New->takeName(Call); + } else { + // The original function had a single return value Call->replaceAllUsesWith(New); New->takeName(Call); } @@ -632,13 +788,11 @@ NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList()); // Loop over the argument list, transfering uses of the old arguments over to - // the new arguments, also transfering over the names as well. While we're at - // it, remove the dead arguments from the DeadArguments list. - // + // the new arguments, also transfering over the names as well. + i = 0; for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(), - I2 = NF->arg_begin(); - I != E; ++I) - if (!DeadArguments.count(I)) { + I2 = NF->arg_begin(); I != E; ++I, ++i) + if (ArgAlive[i]) { // If this is a live argument, move the name and users over to the new // version. I->replaceAllUsesWith(I2); @@ -646,10 +800,8 @@ ++I2; } else { // If this argument is dead, replace any uses of it with null constants - // (these are guaranteed to only be operands to call instructions which - // will later be simplified). + // (these are guaranteed to become unused later on) I->replaceAllUsesWith(Constant::getNullValue(I->getType())); - DeadArguments.erase(I); } // If we change the return value of the function we must rewrite any return @@ -657,12 +809,45 @@ if (F->getReturnType() != NF->getReturnType()) for (Function::iterator BB = NF->begin(), E = NF->end(); BB != E; ++BB) if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { - ReturnInst::Create(0, RI); + Value *RetVal; + + if (NFTy->getReturnType() == Type::VoidTy) { + RetVal = 0; + } else { + assert (isa(RetTy)); + // The original return value was a struct, insert + // extractvalue/insertvalue chains to extract only the values we need + // to return and insert them into our new result. + // This does generate messy code, but we'll let it to instcombine to + // clean that up + Value *OldRet = RI->getOperand(0); + // Start out building up our return value from undef + RetVal = llvm::UndefValue::get(NRetTy); + for (unsigned i = 0; i != RetCount; ++i) + if (NewRetIdxs[i] != -1) { + ExtractValueInst *EV = ExtractValueInst::Create(OldRet, i, "newret", RI); + if (RetTypes.size() > 1) { + // We're still returning a struct, so reinsert the value into + // our new return value at the new index + + RetVal = InsertValueInst::Create(RetVal, EV, NewRetIdxs[i], "oldret"); + } else { + // We are now only returning a simple value, so just return the + // extracted value + RetVal = EV; + } + } + } + // Replace the return instruction with one returning the new return + // value (possibly 0 if we became void). + ReturnInst::Create(RetVal, RI); BB->getInstList().erase(RI); } // Now that the old function is dead, delete it. F->eraseFromParent(); + + return true; } bool DAE::runOnModule(Module &M) { @@ -677,7 +862,7 @@ if (F.getFunctionType()->isVarArg()) Changed |= DeleteDeadVarargs(F); } - + // Second phase:loop through the module, determining which arguments are live. // We assume all arguments are dead unless proven otherwise (allowing us to // determine that dead arguments passed into recursive functions are dead). @@ -686,85 +871,14 @@ for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) SurveyFunction(*I); - // Loop over the instructions to inspect, propagating liveness among arguments - // and return values which are MaybeLive. - while (!InstructionsToInspect.empty()) { - Instruction *I = InstructionsToInspect.back(); - InstructionsToInspect.pop_back(); - - if (ReturnInst *RI = dyn_cast(I)) { - // For return instructions, we just have to check to see if the return - // value for the current function is known now to be alive. If so, any - // arguments used by it are now alive, and any call instruction return - // value is alive as well. - if (LiveRetVal.count(RI->getParent()->getParent())) - MarkReturnInstArgumentLive(RI); - - } else { - CallSite CS = CallSite::get(I); - assert(CS.getInstruction() && "Unknown instruction for the I2I list!"); - - Function *Callee = CS.getCalledFunction(); - - // If we found a call or invoke instruction on this list, that means that - // an argument of the function is a call instruction. If the argument is - // live, then the return value of the called instruction is now live. - // - CallSite::arg_iterator AI = CS.arg_begin(); // ActualIterator - for (Function::arg_iterator FI = Callee->arg_begin(), - E = Callee->arg_end(); FI != E; ++AI, ++FI) { - // If this argument is another call... - CallSite ArgCS = CallSite::get(*AI); - if (ArgCS.getInstruction() && LiveArguments.count(FI)) - if (Function *Callee = ArgCS.getCalledFunction()) - MarkRetValLive(Callee); - } - } + // Now, remove all dead arguments and return values from each function in + // turn + for (Module::iterator I = M.begin(), E = M.end(); I != E; ) { + // Increment now, because the function will probably get removed (ie + // replaced by a new one) + Function *F = I++; + Changed |= RemoveDeadStuffFromFunction(F); } - // Now we loop over all of the MaybeLive arguments, promoting them to be live - // arguments if one of the calls that uses the arguments to the calls they are - // passed into requires them to be live. Of course this could make other - // arguments live, so process callers recursively. - // - // Because elements can be removed from the MaybeLiveArguments set, copy it to - // a temporary vector. - // - std::vector TmpArgList(MaybeLiveArguments.begin(), - MaybeLiveArguments.end()); - for (unsigned i = 0, e = TmpArgList.size(); i != e; ++i) { - Argument *MLA = TmpArgList[i]; - if (MaybeLiveArguments.count(MLA) && - isMaybeLiveArgumentNowLive(MLA)) - MarkArgumentLive(MLA); - } - - // Recover memory early... - CallSites.clear(); - - // At this point, we know that all arguments in DeadArguments and - // MaybeLiveArguments are dead. If the two sets are empty, there is nothing - // to do. - if (MaybeLiveArguments.empty() && DeadArguments.empty() && - MaybeLiveRetVal.empty() && DeadRetVal.empty()) - return Changed; - - // Otherwise, compact into one set, and start eliminating the arguments from - // the functions. - DeadArguments.insert(MaybeLiveArguments.begin(), MaybeLiveArguments.end()); - MaybeLiveArguments.clear(); - DeadRetVal.insert(MaybeLiveRetVal.begin(), MaybeLiveRetVal.end()); - MaybeLiveRetVal.clear(); - - LiveArguments.clear(); - LiveRetVal.clear(); - - NumArgumentsEliminated += DeadArguments.size(); - NumRetValsEliminated += DeadRetVal.size(); - while (!DeadArguments.empty()) - RemoveDeadArgumentsFromFunction((*DeadArguments.begin())->getParent()); - - while (!DeadRetVal.empty()) - RemoveDeadArgumentsFromFunction(*DeadRetVal.begin()); - return true; + return Changed; } From matthijs at stdin.nl Fri Jun 20 05:24:37 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Fri, 20 Jun 2008 10:24:37 -0000 Subject: [llvm-commits] [test-suite] r52533 - /test-suite/trunk/HTMLColDiff.pl Message-ID: <200806201024.m5KAOeKW011900@zion.cs.uiuc.edu> Author: matthijs Date: Fri Jun 20 05:24:30 2008 New Revision: 52533 URL: http://llvm.org/viewvc/llvm-project?rev=52533&view=rev Log: Make HTMLColDiff properly show differences for non-numeric fields, it used to output the original value twice. Make HTMLColDiff mark tests that compiled before but are now failing with "FAIL" and highlight them. Modified: test-suite/trunk/HTMLColDiff.pl Modified: test-suite/trunk/HTMLColDiff.pl URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/HTMLColDiff.pl?rev=52533&r1=52532&r2=52533&view=diff ============================================================================== --- test-suite/trunk/HTMLColDiff.pl (original) +++ test-suite/trunk/HTMLColDiff.pl Fri Jun 20 05:24:30 2008 @@ -161,10 +161,17 @@ } } elsif ($Field ne $FieldComp) { - # Always show but never highlight changes in non-numeric - # fields $Show = 1; - $Field = "$FieldComp => $FieldComp"; + # Specially handle tests that are failing to compile but were not + # doing so previously + if ($Field eq "*") { + $Highlight = 1; + $Colour = "red"; + $Field = "FAIL"; + } + # Always show but never highlight other changes in non-numeric + # fields + $Field = "$FieldComp => $Field"; } } # Remove spaces, we don't want wrapping inside cells From nicolas.geoffray at lip6.fr Fri Jun 20 06:02:07 2008 From: nicolas.geoffray at lip6.fr (Nicolas Geoffray) Date: Fri, 20 Jun 2008 11:02:07 -0000 Subject: [llvm-commits] [vmkit] r52534 - /vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp Message-ID: <200806201102.m5KB28jv012976@zion.cs.uiuc.edu> Author: geoffray Date: Fri Jun 20 06:01:57 2008 New Revision: 52534 URL: http://llvm.org/viewvc/llvm-project?rev=52534&view=rev Log: Set the destructor to zero after copying the VT. Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp Modified: vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp URL: http://llvm.org/viewvc/llvm-project/vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp?rev=52534&r1=52533&r2=52534&view=diff ============================================================================== --- vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp (original) +++ vmkit/trunk/lib/JnJVM/VMCore/JavaInitialise.cpp Fri Jun 20 06:01:57 2008 @@ -59,8 +59,8 @@ X fake; \ void* V = ((void**)(void*)(&fake))[0]; \ X::VT = (VirtualTable*)malloc(12 * sizeof(void*) + VT_SIZE); \ - ((void**)X::VT)[0] = 0; \ - memcpy(X::VT, V, VT_SIZE); } + memcpy(X::VT, V, VT_SIZE); \ + ((void**)X::VT)[0] = 0; } INIT(JavaObject); INIT(JavaArray); From matthijs at stdin.nl Fri Jun 20 09:03:35 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Fri, 20 Jun 2008 14:03:35 -0000 Subject: [llvm-commits] [llvm] r52535 - /llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Message-ID: <200806201403.m5KE3ZgX021411@zion.cs.uiuc.edu> Author: matthijs Date: Fri Jun 20 09:03:35 2008 New Revision: 52535 URL: http://llvm.org/viewvc/llvm-project?rev=52535&view=rev Log: Remove debug output. Modified: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Modified: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp?rev=52535&r1=52534&r2=52535&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp (original) +++ llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Fri Jun 20 09:03:35 2008 @@ -673,10 +673,6 @@ while (!F->use_empty()) { CallSite CS = CallSite::get(F->use_back()); Instruction *Call = CS.getInstruction(); - if (!Call) { - DOUT << "Old: " << *FTy << "\n"; - DOUT << "New: " << *NFTy << "\n"; - } ParamAttrsVec.clear(); const PAListPtr &CallPAL = CS.getParamAttrs(); From matthijs at stdin.nl Fri Jun 20 09:28:52 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Fri, 20 Jun 2008 14:28:52 -0000 Subject: [llvm-commits] [llvm] r52536 - /llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Message-ID: <200806201428.m5KESq75022488@zion.cs.uiuc.edu> Author: matthijs Date: Fri Jun 20 09:28:52 2008 New Revision: 52536 URL: http://llvm.org/viewvc/llvm-project?rev=52536&view=rev Log: Explicitely track if any arguments or return values were removed in DeadArgumentElimination and assert that the function type does not change if nothing was changed. This should catch subtle changes in function type that are not intended. Modified: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Modified: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp?rev=52536&r1=52535&r2=52536&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp (original) +++ llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Fri Jun 20 09:28:52 2008 @@ -568,6 +568,8 @@ const Type *RetTy = FTy->getReturnType(); const Type *NRetTy; unsigned RetCount = NumRetVals(F); + // Explicitely track if anything changed, for debugging + bool Changed = false; // -1 means unused, other numbers are the new index SmallVector NewRetIdxs(RetCount, -1); std::vector RetTypes; @@ -582,7 +584,8 @@ NewRetIdxs[i] = RetTypes.size() - 1; } else { ++NumRetValsEliminated; - DOUT << "DAE - Removing return value " << i << " from " << F->getNameStart() << "\n"; + DOUT << "DAE - Removing return value " << i << " from " << F->getNameStart() << "\n"; + Changed = true; } } else @@ -593,6 +596,7 @@ } else { DOUT << "DAE - Removing return value from " << F->getNameStart() << "\n"; ++NumRetValsEliminated; + Changed = true; } if (RetTypes.size() == 0) // No return types? Make it void @@ -632,6 +636,7 @@ } else { ++NumArgumentsEliminated; DOUT << "DAE - Removing argument " << i << " (" << I->getNameStart() << ") from " << F->getNameStart() << "\n"; + Changed = true; } } @@ -657,6 +662,10 @@ if (NFTy == FTy) return false; + // The function type is only allowed to be different if we actually left out + // an argument or return value + assert(Changed && "Function type changed while no arguments or retrurn values were removed!"); + // Create the new function body and insert it into the module... Function *NF = Function::Create(NFTy, F->getLinkage()); NF->copyAttributesFrom(F); From matthijs at stdin.nl Fri Jun 20 10:16:45 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Fri, 20 Jun 2008 15:16:45 -0000 Subject: [llvm-commits] [llvm] r52537 - /llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Message-ID: <200806201516.m5KFGkRv024435@zion.cs.uiuc.edu> Author: matthijs Date: Fri Jun 20 10:16:45 2008 New Revision: 52537 URL: http://llvm.org/viewvc/llvm-project?rev=52537&view=rev Log: Don't let DeadArgElimination change the return type ({} into void and {T} into T) when no return values are actually dead. Modified: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Modified: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp?rev=52537&r1=52536&r2=52537&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp (original) +++ llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Fri Jun 20 10:16:45 2008 @@ -598,15 +598,21 @@ ++NumRetValsEliminated; Changed = true; } - if (RetTypes.size() == 0) - // No return types? Make it void - NRetTy = Type::VoidTy; + if (RetTypes.size() > 1 || (STy && STy->getNumElements() == RetTypes.size())) + // More than one return type? Return a struct with them. Also, if we used + // to return a struct and didn't change the number of return values, + // return a struct again. This prevents chaning {something} into something + // and {} into void. + // Make the new struct packed if we used to return a packed struct + // already. + NRetTy = StructType::get(RetTypes, STy->isPacked()); else if (RetTypes.size() == 1) - // One return type? Just a simple value then + // One return type? Just a simple value then, but only if we didn't use to + // return a struct with that simple value before. NRetTy = RetTypes.front(); - else - // More return types? Return a struct with them - NRetTy = StructType::get(RetTypes); + else if (RetTypes.size() == 0) + // No return types? Make it void, but only if we didn't use to return {} + NRetTy = Type::VoidTy; } else { NRetTy = Type::VoidTy; } From matthijs at stdin.nl Fri Jun 20 10:25:43 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Fri, 20 Jun 2008 15:25:43 -0000 Subject: [llvm-commits] [llvm] r52538 - /llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Message-ID: <200806201525.m5KFPhWe024845@zion.cs.uiuc.edu> Author: matthijs Date: Fri Jun 20 10:25:43 2008 New Revision: 52538 URL: http://llvm.org/viewvc/llvm-project?rev=52538&view=rev Log: Don't let DeadArgumentElimination attempt to update callers when the return type wasn't changed. Modified: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Modified: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp?rev=52538&r1=52537&r2=52538&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp (original) +++ llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Fri Jun 20 10:25:43 2008 @@ -743,11 +743,18 @@ Args.clear(); if (!Call->use_empty()) { - if (New->getType() == Type::VoidTy) - // Our return value was unused, replace by null for now, uses will get - // removed later on + if (New->getType() == Call->getType()) { + // Return type not changed? Just replace users then + Call->replaceAllUsesWith(New); + New->takeName(Call); + } else if (New->getType() == Type::VoidTy) { + // Our return value has uses, but they will get removed later on. + // Replace by null for now. Call->replaceAllUsesWith(Constant::getNullValue(Call->getType())); - else if (isa(RetTy)) { + } else { + assert(isa(RetTy) && "Return type changed, but not into a" + "void. The old return type must have" + "been a struct!"); // The original return value was a struct, update all uses (which are // all extractvalue instructions). for (Value::use_iterator I = Call->use_begin(), E = Call->use_end(); @@ -781,11 +788,7 @@ } } New->takeName(Call); - } else { - // The original function had a single return value - Call->replaceAllUsesWith(New); - New->takeName(Call); - } + } } // Finally, remove the old call from the program, reducing the use-count of From matthijs at stdin.nl Fri Jun 20 10:34:07 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Fri, 20 Jun 2008 15:34:07 -0000 Subject: [llvm-commits] [llvm] r52539 - /llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Message-ID: <200806201534.m5KFY72l025486@zion.cs.uiuc.edu> Author: matthijs Date: Fri Jun 20 10:34:07 2008 New Revision: 52539 URL: http://llvm.org/viewvc/llvm-project?rev=52539&view=rev Log: 80 column and trailing whitespace fixes. Modified: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Modified: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp?rev=52539&r1=52538&r2=52539&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp (original) +++ llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Fri Jun 20 10:34:07 2008 @@ -48,11 +48,12 @@ /// argument. Used so that arguments and return values can be used /// interchangably. struct RetOrArg { - RetOrArg(const Function* F, unsigned Idx, bool IsArg) : F(F), Idx(Idx), IsArg(IsArg) {} + RetOrArg(const Function* F, unsigned Idx, bool IsArg) : F(F), Idx(Idx), + IsArg(IsArg) {} const Function *F; unsigned Idx; bool IsArg; - + /// Make RetOrArg comparable, so we can put it into a map bool operator<(const RetOrArg &O) const { if (F != O.F) @@ -68,7 +69,7 @@ return F == O.F && Idx == O.Idx && IsArg == O.IsArg; } }; - + /// Liveness enum - During our initial pass over the program, we determine /// that things are either definately alive, definately dead, or in need of /// interprocedural analysis (MaybeLive). @@ -76,13 +77,17 @@ enum Liveness { Live, MaybeLive, Dead }; /// Convenience wrapper - RetOrArg CreateRet(const Function *F, unsigned Idx) { return RetOrArg(F, Idx, false); } + RetOrArg CreateRet(const Function *F, unsigned Idx) { + return RetOrArg(F, Idx, false); + } /// Convenience wrapper - RetOrArg CreateArg(const Function *F, unsigned Idx) { return RetOrArg(F, Idx, true); } + RetOrArg CreateArg(const Function *F, unsigned Idx) { + return RetOrArg(F, Idx, true); + } typedef std::multimap UseMap; /// This map maps a return value or argument to all return values or - /// arguments it uses. + /// arguments it uses. /// For example (indices are left out for clarity): /// - Uses[ret F] = ret G /// This means that F calls G, and F returns the value returned by G. @@ -100,7 +105,7 @@ /// This set contains all values that have been determined to be live LiveSet LiveValues; - + typedef SmallVector UseVector; public: @@ -112,11 +117,13 @@ private: Liveness IsMaybeLive(RetOrArg Use, UseVector &MaybeLiveUses); - Liveness SurveyUse(Value::use_iterator U, UseVector &MaybeLiveUses, unsigned RetValNum = 0); + Liveness SurveyUse(Value::use_iterator U, UseVector &MaybeLiveUses, + unsigned RetValNum = 0); Liveness SurveyUses(Value *V, UseVector &MaybeLiveUses); void SurveyFunction(Function &F); - void MarkValue(const RetOrArg &RA, Liveness L, const UseVector &MaybeLiveUses); + void MarkValue(const RetOrArg &RA, Liveness L, + const UseVector &MaybeLiveUses); void MarkLive(RetOrArg RA); bool RemoveDeadStuffFromFunction(Function *F); bool DeleteDeadVarargs(Function &Fn); @@ -291,7 +298,8 @@ /// RetValNum is the return value number to use when this use is used in a /// return instruction. This is used in the recursion, you should always leave /// it at 0. -DAE::Liveness DAE::SurveyUse(Value::use_iterator U, UseVector &MaybeLiveUses, unsigned RetValNum) { +DAE::Liveness DAE::SurveyUse(Value::use_iterator U, UseVector &MaybeLiveUses, + unsigned RetValNum) { Value *V = *U; if (ReturnInst *RI = dyn_cast(V)) { // The value is returned from another function. It's only live when the @@ -299,9 +307,10 @@ RetOrArg Use = CreateRet(RI->getParent()->getParent(), RetValNum); // We might be live, depending on the liveness of Use return IsMaybeLive(Use, MaybeLiveUses); - } + } if (InsertValueInst *IV = dyn_cast(V)) { - if (U.getOperandNo() != InsertValueInst::getAggregateOperandIndex() && IV->hasIndices()) + if (U.getOperandNo() != InsertValueInst::getAggregateOperandIndex() + && IV->hasIndices()) // The use we are examining is inserted into an aggregate. Our liveness // depends on all uses of that aggregate, but if it is used as a return // value, only index at which we were inserted counts. @@ -309,7 +318,7 @@ // Note that if we are used as the aggregate operand to the insertvalue, // we don't change RetValNum, but do survey all our uses. - + Liveness Result = Dead; for (Value::use_iterator I = IV->use_begin(), E = V->use_end(); I != E; ++I) { @@ -324,7 +333,7 @@ Function *F = CS.getCalledFunction(); if (F) { // Used in a direct call - + // Check for vararg. Do - 1 to skip the first operand to call (the // function itself). if (U.getOperandNo() - 1 >= F->getFunctionType()->getNumParams()) @@ -384,10 +393,11 @@ typedef SmallVector RetUses; // Intialized to a list of RetCount empty lists RetUses MaybeLiveRetUses(RetCount); - + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) if (ReturnInst *RI = dyn_cast(BB->getTerminator())) - if (RI->getNumOperands() != 0 && RI->getOperand(0)->getType() != F.getFunctionType()->getReturnType()) { + if (RI->getNumOperands() != 0 && RI->getOperand(0)->getType() + != F.getFunctionType()->getReturnType()) { // We don't support old style multiple return values FunctionIntrinsicallyLive = true; break; @@ -417,20 +427,20 @@ FunctionIntrinsicallyLive = true; break; } - + // If we end up here, we are looking at a direct call to our function. - + // Now, check how our return value(s) is/are used in this caller. Don't // bother checking return values if all of them are live already - if (NumLiveRetVals != RetCount) { + if (NumLiveRetVals != RetCount) { if (STy) { // Check all uses of the return value for (Value::use_iterator I = TheCall->use_begin(), E = TheCall->use_end(); I != E; ++I) { ExtractValueInst *Ext = dyn_cast(*I); if (Ext && Ext->hasIndices()) { - // This use uses a part of our return value, survey the uses of that - // part and store the results for this index only. + // This use uses a part of our return value, survey the uses of + // that part and store the results for this index only. unsigned Idx = *Ext->idx_begin(); if (RetValLiveness[Idx] != Live) { RetValLiveness[Idx] = SurveyUses(Ext, MaybeLiveRetUses[Idx]); @@ -468,7 +478,7 @@ MarkLive(CreateRet(&F, i)); return; } - + // Now we've inspected all callers, record the liveness of our return values. for (unsigned i = 0, e = RetValLiveness.size(); i != e; ++i) { RetOrArg Ret = CreateRet(&F, i); @@ -480,7 +490,7 @@ // Now, check all of our arguments unsigned i = 0; UseVector MaybeLiveArgUses; - for (Function::arg_iterator AI = F.arg_begin(), + for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end(); AI != E; ++AI, ++i) { // See what the effect of this use is (recording any uses that cause // MaybeLive in MaybeLiveArgUses) @@ -496,7 +506,8 @@ /// MarkValue - This function marks the liveness of RA depending on L. If L is /// MaybeLive, it also records any uses in MaybeLiveUses such that RA will be /// marked live if any use in MaybeLiveUses gets marked live later on. -void DAE::MarkValue(const RetOrArg &RA, Liveness L, const UseVector &MaybeLiveUses) { +void DAE::MarkValue(const RetOrArg &RA, Liveness L, + const UseVector &MaybeLiveUses) { switch (L) { case Live: MarkLive(RA); break; case MaybeLive: @@ -504,7 +515,7 @@ // Note any uses of this value, so this return value can be // marked live whenever one of the uses becomes live. UseMap::iterator Where = Uses.begin(); - for (UseVector::const_iterator UI = MaybeLiveUses.begin(), + for (UseVector::const_iterator UI = MaybeLiveUses.begin(), UE = MaybeLiveUses.end(); UI != UE; ++UI) Where = Uses.insert(Where, UseMap::value_type(*UI, RA)); break; @@ -521,9 +532,11 @@ return; // We were already marked Live if (RA.IsArg) - DOUT << "DAE - Marking argument " << RA.Idx << " to function " << RA.F->getNameStart() << " live\n"; + DOUT << "DAE - Marking argument " << RA.Idx << " to function " + << RA.F->getNameStart() << " live\n"; else - DOUT << "DAE - Marking return value " << RA.Idx << " of function " << RA.F->getNameStart() << " live\n"; + DOUT << "DAE - Marking return value " << RA.Idx << " of function " + << RA.F->getNameStart() << " live\n"; // We don't use upper_bound (or equal_range) here, because our recursive call // to ourselves is likely to mark the upper_bound (which is the first value @@ -562,9 +575,9 @@ // The existing function return attributes. ParameterAttributes RAttrs = PAL.getParamAttrs(0); - + // Find out the new return value - + const Type *RetTy = FTy->getReturnType(); const Type *NRetTy; unsigned RetCount = NumRetVals(F); @@ -584,7 +597,8 @@ NewRetIdxs[i] = RetTypes.size() - 1; } else { ++NumRetValsEliminated; - DOUT << "DAE - Removing return value " << i << " from " << F->getNameStart() << "\n"; + DOUT << "DAE - Removing return value " << i << " from " + << F->getNameStart() << "\n"; Changed = true; } } @@ -594,17 +608,18 @@ RetTypes.push_back(RetTy); NewRetIdxs[0] = 0; } else { - DOUT << "DAE - Removing return value from " << F->getNameStart() << "\n"; + DOUT << "DAE - Removing return value from " << F->getNameStart() + << "\n"; ++NumRetValsEliminated; Changed = true; - } - if (RetTypes.size() > 1 || (STy && STy->getNumElements() == RetTypes.size())) + } + if (RetTypes.size() > 1 || STy && STy->getNumElements() == RetTypes.size()) // More than one return type? Return a struct with them. Also, if we used // to return a struct and didn't change the number of return values, // return a struct again. This prevents chaning {something} into something // and {} into void. // Make the new struct packed if we used to return a packed struct - // already. + // already. NRetTy = StructType::get(RetTypes, STy->isPacked()); else if (RetTypes.size() == 1) // One return type? Just a simple value then, but only if we didn't use to @@ -616,12 +631,12 @@ } else { NRetTy = Type::VoidTy; } - + // Remove any incompatible attributes RAttrs &= ~ParamAttr::typeIncompatible(NRetTy); if (RAttrs) ParamAttrsVec.push_back(ParamAttrsWithIndex::get(0, RAttrs)); - + // Remember which arguments are still alive SmallVector ArgAlive(FTy->getNumParams(), false); // Construct the new parameter list from non-dead arguments. Also construct @@ -634,14 +649,15 @@ if (LiveValues.erase(Arg)) { Params.push_back(I->getType()); ArgAlive[i] = true; - + // Get the original parameter attributes (skipping the first one, that is // for the return value if (ParameterAttributes Attrs = PAL.getParamAttrs(i + 1)) ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Params.size(), Attrs)); } else { ++NumArgumentsEliminated; - DOUT << "DAE - Removing argument " << i << " (" << I->getNameStart() << ") from " << F->getNameStart() << "\n"; + DOUT << "DAE - Removing argument " << i << " (" << I->getNameStart() + << ") from " << F->getNameStart() << "\n"; Changed = true; } } @@ -663,14 +679,15 @@ // Create the new function type based on the recomputed parameters. FunctionType *NFTy = FunctionType::get(NRetTy, Params, FTy->isVarArg()); - + // No change? if (NFTy == FTy) return false; // The function type is only allowed to be different if we actually left out // an argument or return value - assert(Changed && "Function type changed while no arguments or retrurn values were removed!"); + assert(Changed && "Function type changed while no arguments or retrurn values" + "were removed!"); // Create the new function body and insert it into the module... Function *NF = Function::Create(NFTy, F->getLinkage()); @@ -702,7 +719,7 @@ // Declare these outside of the loops, so we can reuse them for the second // loop, which loops the varargs CallSite::arg_iterator I = CS.arg_begin(); - unsigned i = 0; + unsigned i = 0; // Loop over those operands, corresponding to the normal arguments to the // original function, and add those that are still alive. for (unsigned e = FTy->getNumParams(); i != e; ++I, ++i) @@ -759,11 +776,13 @@ // all extractvalue instructions). for (Value::use_iterator I = Call->use_begin(), E = Call->use_end(); I != E;) { - assert(isa(*I) && "Return value not only used by extractvalue?"); + assert(isa(*I) && "Return value not only used by" + "extractvalue?"); ExtractValueInst *EV = cast(*I); // Increment now, since we're about to throw away this use. ++I; - assert(EV->hasIndices() && "Return value used by extractvalue without indices?"); + assert(EV->hasIndices() && "Return value used by extractvalue without" + "indices?"); unsigned Idx = *EV->idx_begin(); if (NewRetIdxs[Idx] != -1) { if (RetTypes.size() > 1) { @@ -771,7 +790,9 @@ // instruction with the first index updated std::vector NewIdxs(EV->idx_begin(), EV->idx_end()); NewIdxs[0] = NewRetIdxs[Idx]; - Value *NEV = ExtractValueInst::Create(New, NewIdxs.begin(), NewIdxs.end(), "retval", EV); + Value *NEV = ExtractValueInst::Create(New, NewIdxs.begin(), + NewIdxs.end(), "retval", + EV); EV->replaceAllUsesWith(NEV); EV->eraseFromParent(); } else { @@ -788,7 +809,7 @@ } } New->takeName(Call); - } + } } // Finally, remove the old call from the program, reducing the use-count of @@ -839,19 +860,21 @@ RetVal = llvm::UndefValue::get(NRetTy); for (unsigned i = 0; i != RetCount; ++i) if (NewRetIdxs[i] != -1) { - ExtractValueInst *EV = ExtractValueInst::Create(OldRet, i, "newret", RI); + ExtractValueInst *EV = ExtractValueInst::Create(OldRet, i, + "newret", RI); if (RetTypes.size() > 1) { // We're still returning a struct, so reinsert the value into // our new return value at the new index - RetVal = InsertValueInst::Create(RetVal, EV, NewRetIdxs[i], "oldret"); + RetVal = InsertValueInst::Create(RetVal, EV, NewRetIdxs[i], + "oldret"); } else { // We are now only returning a simple value, so just return the // extracted value RetVal = EV; } - } - } + } + } // Replace the return instruction with one returning the new return // value (possibly 0 if we became void). ReturnInst::Create(RetVal, RI); From matthijs at stdin.nl Fri Jun 20 10:38:22 2008 From: matthijs at stdin.nl (Matthijs Kooijman) Date: Fri, 20 Jun 2008 15:38:22 -0000 Subject: [llvm-commits] [llvm] r52540 - /llvm/trunk/test/Transforms/DeadArgElim/keepalive.ll Message-ID: <200806201538.m5KFcNbb025693@zion.cs.uiuc.edu> Author: matthijs Date: Fri Jun 20 10:38:22 2008 New Revision: 52540 URL: http://llvm.org/viewvc/llvm-project?rev=52540&view=rev Log: Add testcase that checks that DeadArgElim doesn't touch stuff it shouldn't touch. Added: llvm/trunk/test/Transforms/DeadArgElim/keepalive.ll Added: llvm/trunk/test/Transforms/DeadArgElim/keepalive.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/DeadArgElim/keepalive.ll?rev=52540&view=auto ============================================================================== --- llvm/trunk/test/Transforms/DeadArgElim/keepalive.ll (added) +++ llvm/trunk/test/Transforms/DeadArgElim/keepalive.ll Fri Jun 20 10:38:22 2008 @@ -0,0 +1,36 @@ +; RUN: llvm-as < %s | opt -deadargelim | llvm-dis > %t +; RUN: cat %t | grep {define internal \{ \} @test} +; RUN: cat %t | grep {define internal \{ i32 \} @test} +; RUN: cat %t | grep {define internal \<\{ i32, i32 \}\> @test} + +; Check if the pass doesn't modify anything that doesn't need changing. We feed +; an unused argument to each function to lure it into changing _something_ about +; the function and then changing to much. + + +; This checks if the struct retval isn't changed into a void +define internal { } @test(i32 %DEADARG1) { + ret { } { } +} + +; This checks if the struct retval isn't removed +define internal {i32} @test1(i32 %DEADARG1) { + ret { i32 } { i32 1 } +} + +; This checks if the struct doesn't get non-packed +define internal <{ i32, i32 }> @test2(i32 %DEADARG1) { + ret <{ i32, i32 }> <{ i32 1, i32 2 }> +} + +; We use this external function to make sure the return values don't become dead +declare void @user({ }, { i32 }, <{ i32, i32 }>) + +define void @caller() { + %A = call { } @test(i32 0) + %B = call { i32 } @test1(i32 1) + %C = call <{ i32, i32 }> @test2(i32 2) + call void @user({ } %A, { i32 } %B, <{ i32, i32 }> %C) + ret void +} + From gohman at apple.com Fri Jun 20 11:03:16 2008 From: gohman at apple.com (Dan Gohman) Date: Fri, 20 Jun 2008 16:03:16 -0000 Subject: [llvm-commits] [llvm] r52541 - /llvm/trunk/include/llvm/CodeGen/SelectionDAG.h Message-ID: <200806201603.m5KG3GnK026601@zion.cs.uiuc.edu> Author: djg Date: Fri Jun 20 11:03:16 2008 New Revision: 52541 URL: http://llvm.org/viewvc/llvm-project?rev=52541&view=rev Log: Add an allnodes_size method. Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAG.h Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAG.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAG.h?rev=52541&r1=52540&r2=52541&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/SelectionDAG.h (original) +++ llvm/trunk/include/llvm/CodeGen/SelectionDAG.h Fri Jun 20 11:03:16 2008 @@ -104,6 +104,7 @@ typedef ilist::iterator allnodes_iterator; allnodes_iterator allnodes_begin() { return AllNodes.begin(); } allnodes_iterator allnodes_end() { return AllNodes.end(); } + ilist::size_type allnodes_size() const { return AllNodes.size(); } /// getRoot - Return the root tag of the SelectionDAG. /// From monping at apple.com Fri Jun 20 11:30:06 2008 From: monping at apple.com (Mon P Wang) Date: Fri, 20 Jun 2008 09:30:06 -0700 Subject: [llvm-commits] atomics memoperands patch In-Reply-To: References: <5EAD215D-D32D-4C78-8020-E17D5179A72A@apple.com> Message-ID: <2FBBC83F-5CEB-456E-8101-E64987C4BEF1@apple.com> Hi Evan, On Jun 20, 2008, at 12:11 AM, Evan Cheng wrote: > Thanks Mon Ping. Some comments: > > + N->getOpcode() == ISD::ATOMIC_LCS || > + N->getOpcode() == ISD::ATOMIC_LAS || > + N->getOpcode() == ISD::ATOMIC_SWAP || > + N->getOpcode() == ISD::ATOMIC_LSS || > + N->getOpcode() == ISD::ATOMIC_LOAD_AND || > + N->getOpcode() == ISD::ATOMIC_LOAD_OR || > + N->getOpcode() == ISD::ATOMIC_LOAD_XOR || > > Does it make sense to take this opportunity to rename lcs, las, and > lss? > I heard the same comment from Andrew and I think it makes sense. How about the following ATOMIC_LCS => ATOMIC_CMP_SWAP ATOMIC_LAS => ATOMIC_LOAD_ADD ATOMIC_LSS => ATOMIC_LOAD_SUB This would make the names more consistent. > + //! PtrVal - Value of address that we are going to do an atomic > update > How about "Value of atomically updated address"? > > + const Value* PtrVal; > > Since this is basically the same as LSBaseSDNode SrcValue, how about > move it to the common base class MemSDNode? You are right. We should move what is common up as much as possible. > + > + //! Align - Alignment of memory location in bytes. > + unsigned Align; > > Alignment instead of Align. > Yep, shows me for getting lazy in typing :-> > + > + //! IsVol - True if the store is volatile. > + bool IsVol; > > IsVolatile instead of IsVol. But do we need these? Isn't it always > volatile given it's an atomic operation? > I think the standard definition is that all these operations are volatile and acts like a memory barrier. The atomics should always return true for this function for volatile. > Again, LSBaseSDNode has these fields as well. Perhaps move them up? > > + // Check if the atomic references a frame index > + const FrameIndexSDNode *FI = > + dyn_cast(getBasePtr().Val); > + if (!getBasePtrValue() && FI) > > I am not quite sure why it's necessary to check getBasePtrValue()? > My assumption when I read the code for LSBaseSDNode that if the getBasePtrValue exist, we should use getBasePtrValue because it will give more precise information for the location we are accessing (index into a location in the FrameIndex). If this is not true, then it is not necessary. > > + return MachineMemOperand(PseudoSourceValue::getFixedStack(), > Flags, > + FI->getIndex(), Size, getAlignment()); > + else > + return MachineMemOperand(getBasePtrValue(), Flags, 0, Size, > getAlignment()); > +} > > Also, don't forget to update AddNodeIDNode() and SDNode::dump() in > SelectionDAG.cpp. I totally forgot about that. Thanks for the reminder. -- Mon Ping > Thanks, > > Evan > > On Jun 19, 2008, at 6:19 PM, Mon P Wang wrote: > >> Hi, >> >> Like loads/stores, atomics touches memory and should have an >> associated MemOperand with the operation. The following patch >> creates an abstract class MemSDNode that all nodes which have an >> associated MemOperand need to inherit to. It also creates a new >> property SDNPMemOperand that indicates that a node touches memory >> and has an associated MemOperand.If you have any comments, please >> let me know. >> >> Thanks, >> -- Mon Ping >> >> _______________________________________________ >> llvm-commits mailing list >> llvm-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From gohman at apple.com Fri Jun 20 11:39:44 2008 From: gohman at apple.com (Dan Gohman) Date: Fri, 20 Jun 2008 16:39:44 -0000 Subject: [llvm-commits] [llvm] r52542 - /llvm/trunk/lib/Transforms/Scalar/SCCP.cpp Message-ID: <200806201639.m5KGdiKC028053@zion.cs.uiuc.edu> Author: djg Date: Fri Jun 20 11:39:44 2008 New Revision: 52542 URL: http://llvm.org/viewvc/llvm-project?rev=52542&view=rev Log: Fix the conditions under which SCCP should examine insertvalue instructions. Thanks to Matthijs Kooijman for pointing this out! Modified: llvm/trunk/lib/Transforms/Scalar/SCCP.cpp Modified: llvm/trunk/lib/Transforms/Scalar/SCCP.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SCCP.cpp?rev=52542&r1=52541&r2=52542&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/SCCP.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/SCCP.cpp Fri Jun 20 11:39:44 2008 @@ -750,7 +750,7 @@ Value *Val = IVI.getOperand(1); // If the operand to the getresult is an undef, the result is undef. - if (isa(Aggr)) + if (isa(Aggr) && isa(Val)) return; // Currently only handle single-index insertvalues. @@ -758,6 +758,23 @@ markOverdefined(&IVI); return; } + + // Currently only handle insertvalue instructions that are in a single-use + // chain that builds up a return value. + for (const InsertValueInst *TmpIVI = &IVI; ; ) { + if (!TmpIVI->hasOneUse()) { + markOverdefined(&IVI); + return; + } + const Value *V = *TmpIVI->use_begin(); + if (isa(V)) + break; + TmpIVI = dyn_cast(V); + if (!TmpIVI) { + markOverdefined(&IVI); + return; + } + } // See if we are tracking the result of the callee. Function *F = IVI.getParent()->getParent(); From monping at apple.com Fri Jun 20 11:40:54 2008 From: monping at apple.com (Mon P Wang) Date: Fri, 20 Jun 2008 09:40:54 -0700 Subject: [llvm-commits] atomics memoperands patch In-Reply-To: References: <5EAD215D-D32D-4C78-8020-E17D5179A72A@apple.com> Message-ID: <855FB51F-F2D0-4E04-93E6-D3EBA8C74D52@apple.com> On Jun 20, 2008, at 12:28 AM, Evan Cheng wrote: > Questions for everyone. I've just noticed something in > SelectionDAG.cpp: > > SDNode *SelectionDAG::FindModifiedNodeSlot(SDNode *N, > SDOperandPtr Ops,unsigned > NumOps, > void *&InsertPos) { > ... > > FoldingSetNodeID ID; > AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops, NumOps); > > if (const LoadSDNode *LD = dyn_cast(N)) { > ID.AddInteger(LD->getAddressingMode()); > ID.AddInteger(LD->getExtensionType()); > ID.AddInteger(LD->getMemoryVT().getRawBits()); > ID.AddInteger(LD->getAlignment()); > ID.AddInteger(LD->isVolatile()); > } else if (const StoreSDNode *ST = dyn_cast(N)) { > ID.AddInteger(ST->getAddressingMode()); > ID.AddInteger(ST->isTruncatingStore()); > ID.AddInteger(ST->getMemoryVT().getRawBits()); > ID.AddInteger(ST->getAlignment()); > ID.AddInteger(ST->isVolatile()); > } > > Do we need the if () else if? AddNodeIDNode has already added those > fields to the FoldingSetNodeId. > Looking at the code, it does seem wrong to add the fields twice. > Also, do we want to cse nodes that are volatile? > If the CSE can prove that no needed side effects are produced, it can do so. In general though, I would shy away from doing so as it might not be easy to prove that is the case. -- Mon Ping > Evan > From gohman at apple.com Fri Jun 20 11:41:18 2008 From: gohman at apple.com (Dan Gohman) Date: Fri, 20 Jun 2008 16:41:18 -0000 Subject: [llvm-commits] [llvm] r52543 - /llvm/trunk/lib/Transforms/Scalar/SCCP.cpp Message-ID: <200806201641.m5KGfIFD028121@zion.cs.uiuc.edu> Author: djg Date: Fri Jun 20 11:41:17 2008 New Revision: 52543 URL: http://llvm.org/viewvc/llvm-project?rev=52543&view=rev Log: Tidy up some commments and use the getAggregateOperand and getInsertedValueOperand accessors. Thanks Matthijs! Modified: llvm/trunk/lib/Transforms/Scalar/SCCP.cpp Modified: llvm/trunk/lib/Transforms/Scalar/SCCP.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SCCP.cpp?rev=52543&r1=52542&r2=52543&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/SCCP.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/SCCP.cpp Fri Jun 20 11:41:17 2008 @@ -705,9 +705,9 @@ } void SCCPSolver::visitExtractValueInst(ExtractValueInst &EVI) { - Value *Aggr = EVI.getOperand(0); + Value *Aggr = EVI.getAggregateOperand(); - // If the operand to the getresult is an undef, the result is undef. + // If the operand to the extractvalue is an undef, the result is undef. if (isa(Aggr)) return; @@ -746,10 +746,10 @@ } void SCCPSolver::visitInsertValueInst(InsertValueInst &IVI) { - Value *Aggr = IVI.getOperand(0); - Value *Val = IVI.getOperand(1); + Value *Aggr = IVI.getAggregateOperand(); + Value *Val = IVI.getInsertedValueOperand(); - // If the operand to the getresult is an undef, the result is undef. + // If the operands to the insertvalue are undef, the result is undef. if (isa(Aggr) && isa(Val)) return; @@ -785,8 +785,8 @@ if (It != TrackedMultipleRetVals.end()) mergeInValue(It->second, F, getValueState(Val)); - // Mark the aggregate result of the IVI overdefined; any tracking that we do will - // be done on the individual member values. + // Mark the aggregate result of the IVI overdefined; any tracking that we do + // will be done on the individual member values. markOverdefined(&IVI); } @@ -1269,13 +1269,13 @@ UI != E; ++UI) { if (GetResultInst *GRI = dyn_cast(*UI)) { mergeInValue(GRI, - TrackedMultipleRetVals[std::make_pair(F, GRI->getIndex())]); + TrackedMultipleRetVals[std::make_pair(F, GRI->getIndex())]); continue; } if (ExtractValueInst *EVI = dyn_cast(*UI)) { if (EVI->getNumIndices() == 1) { mergeInValue(EVI, - TrackedMultipleRetVals[std::make_pair(F, *EVI->idx_begin())]); + TrackedMultipleRetVals[std::make_pair(F, *EVI->idx_begin())]); continue; } } From gohman at apple.com Fri Jun 20 12:11:32 2008 From: gohman at apple.com (Dan Gohman) Date: Fri, 20 Jun 2008 17:11:32 -0000 Subject: [llvm-commits] [llvm] r52544 - /llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp Message-ID: <200806201711.m5KHBWdH029400@zion.cs.uiuc.edu> Author: djg Date: Fri Jun 20 12:11:32 2008 New Revision: 52544 URL: http://llvm.org/viewvc/llvm-project?rev=52544&view=rev Log: Clean up a use of std::distance. Modified: llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp Modified: llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp?rev=52544&r1=52543&r2=52544&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp (original) +++ llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp Fri Jun 20 12:11:32 2008 @@ -229,8 +229,7 @@ { // Scope to destroy ValueMap after cloning. DenseMap ValueMap; - assert(std::distance(CalledFunc->arg_begin(), CalledFunc->arg_end()) == - std::distance(CS.arg_begin(), CS.arg_end()) && + assert(CalledFunc->arg_size() == CS.arg_size() && "No varargs calls can be inlined!"); // Calculate the vector of arguments to pass into the function cloner, which From gohman at apple.com Fri Jun 20 12:15:19 2008 From: gohman at apple.com (Dan Gohman) Date: Fri, 20 Jun 2008 17:15:19 -0000 Subject: [llvm-commits] [llvm] r52545 - in /llvm/trunk/lib/CodeGen/SelectionDAG: LegalizeDAG.cpp ScheduleDAG.cpp Message-ID: <200806201715.m5KHFKJj029568@zion.cs.uiuc.edu> Author: djg Date: Fri Jun 20 12:15:19 2008 New Revision: 52545 URL: http://llvm.org/viewvc/llvm-project?rev=52545&view=rev Log: Clean up some uses of std::distance, now that we have allnodes_size. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp?rev=52545&r1=52544&r2=52545&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Fri Jun 20 12:15:19 2008 @@ -313,8 +313,7 @@ } assert(Order.size() == Visited.size() && - Order.size() == - (unsigned)std::distance(DAG.allnodes_begin(), DAG.allnodes_end()) && + Order.size() == DAG.allnodes_size() && "Error: DAG is cyclic!"); } Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp?rev=52545&r1=52544&r2=52545&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp Fri Jun 20 12:15:19 2008 @@ -97,7 +97,7 @@ // Reserve entries in the vector for each of the SUnits we are creating. This // ensure that reallocation of the vector won't happen, so SUnit*'s won't get // invalidated. - SUnits.reserve(std::distance(DAG.allnodes_begin(), DAG.allnodes_end())); + SUnits.reserve(DAG.allnodes_size()); for (SelectionDAG::allnodes_iterator NI = DAG.allnodes_begin(), E = DAG.allnodes_end(); NI != E; ++NI) { @@ -105,7 +105,7 @@ continue; // If this node has already been processed, stop now. - if (SUnitMap[NI].size()) continue; + if (!SUnitMap[NI].empty()) continue; SUnit *NodeSUnit = NewSUnit(NI); From baldrick at free.fr Fri Jun 20 12:48:22 2008 From: baldrick at free.fr (Duncan Sands) Date: Fri, 20 Jun 2008 19:48:22 +0200 Subject: [llvm-commits] [llvm] r52536 - /llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp In-Reply-To: <200806201428.m5KESq75022488@zion.cs.uiuc.edu> References: <200806201428.m5KESq75022488@zion.cs.uiuc.edu> Message-ID: <200806201948.22726.baldrick@free.fr> Hi, > + // Explicitely track if anything changed, for debugging Explicitely -> Explicitly Missing full stop at end of comment. > + // The function type is only allowed to be different if we actually left out > + // an argument or return value Missing full stop at end of comment. > + assert(Changed && "Function type changed while no arguments or retrurn values were removed!"); retrurn -> return Ciao, Duncan. From baldrick at free.fr Fri Jun 20 12:49:55 2008 From: baldrick at free.fr (Duncan Sands) Date: Fri, 20 Jun 2008 17:49:55 -0000 Subject: [llvm-commits] [llvm] r52546 - in /llvm/trunk/lib/CodeGen/SelectionDAG: LegalizeFloatTypes.cpp LegalizeIntegerTypes.cpp LegalizeTypes.cpp LegalizeTypes.h LegalizeVectorTypes.cpp Message-ID: <200806201749.m5KHnt8N030894@zion.cs.uiuc.edu> Author: baldrick Date: Fri Jun 20 12:49:55 2008 New Revision: 52546 URL: http://llvm.org/viewvc/llvm-project?rev=52546&view=rev Log: Rename the operation of turning a float type into an integer of the same type. Before it was "promotion", but this is confusing because it is quite different to promotion of integers. Call it "softening" instead, inspired by "soft float". Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp?rev=52546&r1=52545&r2=52546&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp Fri Jun 20 12:49:55 2008 @@ -7,13 +7,12 @@ // //===----------------------------------------------------------------------===// // -// This file implements float type expansion and conversion of float types to -// integer types on behalf of LegalizeTypes. -// Converting to integer is the act of turning a computation in an illegal -// floating point type into a computation in an integer type of the same size. -// For example, turning f32 arithmetic into operations using i32. Also known as -// "soft float". The result is equivalent to bitcasting the float value to the -// integer type. +// This file implements float type expansion and softening for LegalizeTypes. +// Softening is the act of turning a computation in an illegal floating point +// type into a computation in an integer type of the same size; also known as +// "soft float". For example, turning f32 arithmetic into operations using i32. +// The resulting integer value is the same as what you would get by performing +// the floating point operation and bitcasting the result to the integer type. // Expansion is the act of changing a computation in an illegal type to be a // computation in multiple registers of a smaller type. For example, // implementing ppcf128 arithmetic in two f64 registers. @@ -44,8 +43,8 @@ // Result Float to Integer Conversion. //===----------------------------------------------------------------------===// -void DAGTypeLegalizer::PromoteFloatResult(SDNode *N, unsigned ResNo) { - DEBUG(cerr << "Promote float result " << ResNo << ": "; N->dump(&DAG); +void DAGTypeLegalizer::SoftenFloatResult(SDNode *N, unsigned ResNo) { + DEBUG(cerr << "Soften float result " << ResNo << ": "; N->dump(&DAG); cerr << "\n"); SDOperand R = SDOperand(); @@ -67,37 +66,37 @@ switch (N->getOpcode()) { default: #ifndef NDEBUG - cerr << "PromoteFloatResult #" << ResNo << ": "; + cerr << "SoftenFloatResult #" << ResNo << ": "; N->dump(&DAG); cerr << "\n"; #endif assert(0 && "Do not know how to convert the result of this operator!"); abort(); - case ISD::BIT_CONVERT: R = PromoteFloatRes_BIT_CONVERT(N); break; - case ISD::BUILD_PAIR: R = PromoteFloatRes_BUILD_PAIR(N); break; + case ISD::BIT_CONVERT: R = SoftenFloatRes_BIT_CONVERT(N); break; + case ISD::BUILD_PAIR: R = SoftenFloatRes_BUILD_PAIR(N); break; case ISD::ConstantFP: - R = PromoteFloatRes_ConstantFP(cast(N)); + R = SoftenFloatRes_ConstantFP(cast(N)); break; - case ISD::FCOPYSIGN: R = PromoteFloatRes_FCOPYSIGN(N); break; - case ISD::LOAD: R = PromoteFloatRes_LOAD(N); break; + case ISD::FCOPYSIGN: R = SoftenFloatRes_FCOPYSIGN(N); break; + case ISD::LOAD: R = SoftenFloatRes_LOAD(N); break; case ISD::SINT_TO_FP: - case ISD::UINT_TO_FP: R = PromoteFloatRes_XINT_TO_FP(N); break; + case ISD::UINT_TO_FP: R = SoftenFloatRes_XINT_TO_FP(N); break; - case ISD::FADD: R = PromoteFloatRes_FADD(N); break; - case ISD::FMUL: R = PromoteFloatRes_FMUL(N); break; - case ISD::FSUB: R = PromoteFloatRes_FSUB(N); break; + case ISD::FADD: R = SoftenFloatRes_FADD(N); break; + case ISD::FMUL: R = SoftenFloatRes_FMUL(N); break; + case ISD::FSUB: R = SoftenFloatRes_FSUB(N); break; } // If R is null, the sub-method took care of registering the result. if (R.Val) - SetPromotedFloat(SDOperand(N, ResNo), R); + SetSoftenedFloat(SDOperand(N, ResNo), R); } -SDOperand DAGTypeLegalizer::PromoteFloatRes_BIT_CONVERT(SDNode *N) { +SDOperand DAGTypeLegalizer::SoftenFloatRes_BIT_CONVERT(SDNode *N) { return BitConvertToInteger(N->getOperand(0)); } -SDOperand DAGTypeLegalizer::PromoteFloatRes_BUILD_PAIR(SDNode *N) { +SDOperand DAGTypeLegalizer::SoftenFloatRes_BUILD_PAIR(SDNode *N) { // Convert the inputs to integers, and build a new pair out of them. return DAG.getNode(ISD::BUILD_PAIR, TLI.getTypeToTransformTo(N->getValueType(0)), @@ -105,15 +104,15 @@ BitConvertToInteger(N->getOperand(1))); } -SDOperand DAGTypeLegalizer::PromoteFloatRes_ConstantFP(ConstantFPSDNode *N) { +SDOperand DAGTypeLegalizer::SoftenFloatRes_ConstantFP(ConstantFPSDNode *N) { return DAG.getConstant(N->getValueAPF().convertToAPInt(), TLI.getTypeToTransformTo(N->getValueType(0))); } -SDOperand DAGTypeLegalizer::PromoteFloatRes_FADD(SDNode *N) { +SDOperand DAGTypeLegalizer::SoftenFloatRes_FADD(SDNode *N) { MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - SDOperand Ops[2] = { GetPromotedFloat(N->getOperand(0)), - GetPromotedFloat(N->getOperand(1)) }; + SDOperand Ops[2] = { GetSoftenedFloat(N->getOperand(0)), + GetSoftenedFloat(N->getOperand(1)) }; return MakeLibCall(GetFPLibCall(N->getValueType(0), RTLIB::ADD_F32, RTLIB::ADD_F64, @@ -122,8 +121,8 @@ NVT, Ops, 2, false/*sign irrelevant*/); } -SDOperand DAGTypeLegalizer::PromoteFloatRes_FCOPYSIGN(SDNode *N) { - SDOperand LHS = GetPromotedFloat(N->getOperand(0)); +SDOperand DAGTypeLegalizer::SoftenFloatRes_FCOPYSIGN(SDNode *N) { + SDOperand LHS = GetSoftenedFloat(N->getOperand(0)); SDOperand RHS = BitConvertToInteger(N->getOperand(1)); MVT LVT = LHS.getValueType(); @@ -161,10 +160,10 @@ return DAG.getNode(ISD::OR, LVT, LHS, SignBit); } -SDOperand DAGTypeLegalizer::PromoteFloatRes_FMUL(SDNode *N) { +SDOperand DAGTypeLegalizer::SoftenFloatRes_FMUL(SDNode *N) { MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - SDOperand Ops[2] = { GetPromotedFloat(N->getOperand(0)), - GetPromotedFloat(N->getOperand(1)) }; + SDOperand Ops[2] = { GetSoftenedFloat(N->getOperand(0)), + GetSoftenedFloat(N->getOperand(1)) }; return MakeLibCall(GetFPLibCall(N->getValueType(0), RTLIB::MUL_F32, RTLIB::MUL_F64, @@ -173,10 +172,10 @@ NVT, Ops, 2, false/*sign irrelevant*/); } -SDOperand DAGTypeLegalizer::PromoteFloatRes_FSUB(SDNode *N) { +SDOperand DAGTypeLegalizer::SoftenFloatRes_FSUB(SDNode *N) { MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - SDOperand Ops[2] = { GetPromotedFloat(N->getOperand(0)), - GetPromotedFloat(N->getOperand(1)) }; + SDOperand Ops[2] = { GetSoftenedFloat(N->getOperand(0)), + GetSoftenedFloat(N->getOperand(1)) }; return MakeLibCall(GetFPLibCall(N->getValueType(0), RTLIB::SUB_F32, RTLIB::SUB_F64, @@ -185,7 +184,7 @@ NVT, Ops, 2, false/*sign irrelevant*/); } -SDOperand DAGTypeLegalizer::PromoteFloatRes_LOAD(SDNode *N) { +SDOperand DAGTypeLegalizer::SoftenFloatRes_LOAD(SDNode *N) { LoadSDNode *L = cast(N); MVT VT = N->getValueType(0); MVT NVT = TLI.getTypeToTransformTo(VT); @@ -206,7 +205,7 @@ return BitConvertToInteger(DAG.getNode(ISD::FP_EXTEND, VT, NL)); } -SDOperand DAGTypeLegalizer::PromoteFloatRes_XINT_TO_FP(SDNode *N) { +SDOperand DAGTypeLegalizer::SoftenFloatRes_XINT_TO_FP(SDNode *N) { bool isSigned = N->getOpcode() == ISD::SINT_TO_FP; MVT DestVT = N->getValueType(0); SDOperand Op = N->getOperand(0); @@ -311,8 +310,8 @@ // Operand Float to Integer Conversion.. //===----------------------------------------------------------------------===// -bool DAGTypeLegalizer::PromoteFloatOperand(SDNode *N, unsigned OpNo) { - DEBUG(cerr << "Promote float operand " << OpNo << ": "; N->dump(&DAG); +bool DAGTypeLegalizer::SoftenFloatOperand(SDNode *N, unsigned OpNo) { + DEBUG(cerr << "Soften float operand " << OpNo << ": "; N->dump(&DAG); cerr << "\n"); SDOperand Res(0, 0); @@ -327,13 +326,13 @@ switch (N->getOpcode()) { default: #ifndef NDEBUG - cerr << "PromoteFloatOperand Op #" << OpNo << ": "; + cerr << "SoftenFloatOperand Op #" << OpNo << ": "; N->dump(&DAG); cerr << "\n"; #endif assert(0 && "Do not know how to convert this operator's operand!"); abort(); - case ISD::BIT_CONVERT: Res = PromoteFloatOp_BIT_CONVERT(N); break; + case ISD::BIT_CONVERT: Res = SoftenFloatOp_BIT_CONVERT(N); break; } } @@ -357,9 +356,9 @@ return false; } -SDOperand DAGTypeLegalizer::PromoteFloatOp_BIT_CONVERT(SDNode *N) { +SDOperand DAGTypeLegalizer::SoftenFloatOp_BIT_CONVERT(SDNode *N) { return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), - GetPromotedFloat(N->getOperand(0))); + GetSoftenedFloat(N->getOperand(0))); } Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp?rev=52546&r1=52545&r2=52546&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp Fri Jun 20 12:49:55 2008 @@ -232,9 +232,9 @@ // The input promotes to the same size. Convert the promoted value. return DAG.getNode(ISD::BIT_CONVERT, OutVT, GetPromotedInteger(InOp)); break; - case PromoteFloat: + case SoftenFloat: // Promote the integer operand by hand. - return DAG.getNode(ISD::ANY_EXTEND, OutVT, GetPromotedFloat(InOp)); + return DAG.getNode(ISD::ANY_EXTEND, OutVT, GetSoftenedFloat(InOp)); case ExpandInteger: case ExpandFloat: break; @@ -963,9 +963,9 @@ case Legal: case PromoteInteger: break; - case PromoteFloat: + case SoftenFloat: // Convert the integer operand instead. - SplitInteger(GetPromotedFloat(InOp), Lo, Hi); + SplitInteger(GetSoftenedFloat(InOp), Lo, Hi); Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); return; Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp?rev=52546&r1=52545&r2=52546&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp Fri Jun 20 12:49:55 2008 @@ -80,8 +80,8 @@ case ExpandInteger: ExpandIntegerResult(N, i); goto NodeDone; - case PromoteFloat: - PromoteFloatResult(N, i); + case SoftenFloat: + SoftenFloatResult(N, i); goto NodeDone; case ExpandFloat: ExpandFloatResult(N, i); @@ -113,8 +113,8 @@ case ExpandInteger: NeedsRevisit = ExpandIntegerOperand(N, i); break; - case PromoteFloat: - NeedsRevisit = PromoteFloatOperand(N, i); + case SoftenFloat: + NeedsRevisit = SoftenFloatOperand(N, i); break; case ExpandFloat: NeedsRevisit = ExpandFloatOperand(N, i); @@ -393,8 +393,8 @@ I->second = Replacement; } - for (DenseMap::iterator I = PromotedFloats.begin(), - E = PromotedFloats.end(); I != E; ++I) { + for (DenseMap::iterator I = SoftenedFloats.begin(), + E = SoftenedFloats.end(); I != E; ++I) { assert(I->first != N); if (I->second == N) I->second = Replacement; @@ -446,11 +446,11 @@ OpEntry = Result; } -void DAGTypeLegalizer::SetPromotedFloat(SDOperand Op, SDOperand Result) { +void DAGTypeLegalizer::SetSoftenedFloat(SDOperand Op, SDOperand Result) { ExpungeNode(Result); AnalyzeNewNode(Result.Val); - SDOperand &OpEntry = PromotedFloats[Op]; + SDOperand &OpEntry = SoftenedFloats[Op]; assert(OpEntry.Val == 0 && "Node is already converted to integer!"); OpEntry = Result; } Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h?rev=52546&r1=52545&r2=52546&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h Fri Jun 20 12:49:55 2008 @@ -62,7 +62,7 @@ Legal, // The target natively supports this type. PromoteInteger, // Replace this integer type with a larger one. ExpandInteger, // Split this integer type into two of half the size. - PromoteFloat, // Convert this float type to a same size integer type. + SoftenFloat, // Convert this float type to a same size integer type. ExpandFloat, // Split this float type into two of half the size. Scalarize, // Replace this one-element vector type with its element type. Split // This vector type should be split into smaller vectors. @@ -95,7 +95,7 @@ return ExpandInteger; else if (VT.getSizeInBits() == TLI.getTypeToTransformTo(VT).getSizeInBits()) - return PromoteFloat; + return SoftenFloat; else return ExpandFloat; } else if (VT.getVectorNumElements() == 1) { @@ -119,9 +119,9 @@ /// indicates which operands are the expanded version of the input. DenseMap > ExpandedIntegers; - /// PromotedFloats - For floating point nodes converted to integers of + /// SoftenedFloats - For floating point nodes converted to integers of /// the same size, this map indicates the converted value to use. - DenseMap PromotedFloats; + DenseMap SoftenedFloats; /// ExpandedFloats - For float nodes that need to be expanded this map /// indicates which operands are the expanded version of the input. @@ -321,29 +321,29 @@ // Float to Integer Conversion Support: LegalizeFloatTypes.cpp //===--------------------------------------------------------------------===// - SDOperand GetPromotedFloat(SDOperand Op) { - SDOperand &PromotedOp = PromotedFloats[Op]; - RemapNode(PromotedOp); - assert(PromotedOp.Val && "Operand wasn't converted to integer?"); - return PromotedOp; + SDOperand GetSoftenedFloat(SDOperand Op) { + SDOperand &SoftenedOp = SoftenedFloats[Op]; + RemapNode(SoftenedOp); + assert(SoftenedOp.Val && "Operand wasn't converted to integer?"); + return SoftenedOp; } - void SetPromotedFloat(SDOperand Op, SDOperand Result); + void SetSoftenedFloat(SDOperand Op, SDOperand Result); // Result Float to Integer Conversion. - void PromoteFloatResult(SDNode *N, unsigned OpNo); - SDOperand PromoteFloatRes_BIT_CONVERT(SDNode *N); - SDOperand PromoteFloatRes_BUILD_PAIR(SDNode *N); - SDOperand PromoteFloatRes_ConstantFP(ConstantFPSDNode *N); - SDOperand PromoteFloatRes_FADD(SDNode *N); - SDOperand PromoteFloatRes_FCOPYSIGN(SDNode *N); - SDOperand PromoteFloatRes_FMUL(SDNode *N); - SDOperand PromoteFloatRes_FSUB(SDNode *N); - SDOperand PromoteFloatRes_LOAD(SDNode *N); - SDOperand PromoteFloatRes_XINT_TO_FP(SDNode *N); + void SoftenFloatResult(SDNode *N, unsigned OpNo); + SDOperand SoftenFloatRes_BIT_CONVERT(SDNode *N); + SDOperand SoftenFloatRes_BUILD_PAIR(SDNode *N); + SDOperand SoftenFloatRes_ConstantFP(ConstantFPSDNode *N); + SDOperand SoftenFloatRes_FADD(SDNode *N); + SDOperand SoftenFloatRes_FCOPYSIGN(SDNode *N); + SDOperand SoftenFloatRes_FMUL(SDNode *N); + SDOperand SoftenFloatRes_FSUB(SDNode *N); + SDOperand SoftenFloatRes_LOAD(SDNode *N); + SDOperand SoftenFloatRes_XINT_TO_FP(SDNode *N); // Operand Float to Integer Conversion. - bool PromoteFloatOperand(SDNode *N, unsigned OpNo); - SDOperand PromoteFloatOp_BIT_CONVERT(SDNode *N); + bool SoftenFloatOperand(SDNode *N, unsigned OpNo); + SDOperand SoftenFloatOp_BIT_CONVERT(SDNode *N); //===--------------------------------------------------------------------===// // Float Expansion Support: LegalizeFloatTypes.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp?rev=52546&r1=52545&r2=52546&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp Fri Jun 20 12:49:55 2008 @@ -503,7 +503,7 @@ assert(false && "Unknown type action!"); case Legal: case PromoteInteger: - case PromoteFloat: + case SoftenFloat: case Scalarize: break; case ExpandInteger: From baldrick at free.fr Fri Jun 20 13:34:30 2008 From: baldrick at free.fr (Duncan Sands) Date: Fri, 20 Jun 2008 18:34:30 -0000 Subject: [llvm-commits] [llvm] r52547 - /llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h Message-ID: <200806201834.m5KIYUec000497@zion.cs.uiuc.edu> Author: baldrick Date: Fri Jun 20 13:34:30 2008 New Revision: 52547 URL: http://llvm.org/viewvc/llvm-project?rev=52547&view=rev Log: Add some methods for querying the nature of a store, like the methods for loads (and neaten those up a bit while there). Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h?rev=52547&r1=52546&r2=52547&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h (original) +++ llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h Fri Jun 20 13:34:30 2008 @@ -2143,60 +2143,71 @@ /// isNormalLoad - Returns true if the specified node is a non-extending /// and unindexed load. inline bool isNormalLoad(const SDNode *N) { - if (N->getOpcode() != ISD::LOAD) - return false; - const LoadSDNode *Ld = cast(N); - return Ld->getExtensionType() == ISD::NON_EXTLOAD && + const LoadSDNode *Ld = dyn_cast(N); + return Ld && Ld->getExtensionType() == ISD::NON_EXTLOAD && Ld->getAddressingMode() == ISD::UNINDEXED; } /// isNON_EXTLoad - Returns true if the specified node is a non-extending /// load. inline bool isNON_EXTLoad(const SDNode *N) { - return N->getOpcode() == ISD::LOAD && + return isa(N) && cast(N)->getExtensionType() == ISD::NON_EXTLOAD; } /// isEXTLoad - Returns true if the specified node is a EXTLOAD. /// inline bool isEXTLoad(const SDNode *N) { - return N->getOpcode() == ISD::LOAD && + return isa(N) && cast(N)->getExtensionType() == ISD::EXTLOAD; } /// isSEXTLoad - Returns true if the specified node is a SEXTLOAD. /// inline bool isSEXTLoad(const SDNode *N) { - return N->getOpcode() == ISD::LOAD && + return isa(N) && cast(N)->getExtensionType() == ISD::SEXTLOAD; } /// isZEXTLoad - Returns true if the specified node is a ZEXTLOAD. /// inline bool isZEXTLoad(const SDNode *N) { - return N->getOpcode() == ISD::LOAD && + return isa(N) && cast(N)->getExtensionType() == ISD::ZEXTLOAD; } - /// isUNINDEXEDLoad - Returns true if the specified node is a unindexed load. + /// isUNINDEXEDLoad - Returns true if the specified node is an unindexed load. /// inline bool isUNINDEXEDLoad(const SDNode *N) { - return N->getOpcode() == ISD::LOAD && + return isa(N) && cast(N)->getAddressingMode() == ISD::UNINDEXED; } + /// isNormalStore - Returns true if the specified node is a non-truncating + /// and unindexed store. + inline bool isNormalStore(const SDNode *N) { + const StoreSDNode *St = dyn_cast(N); + return St && !St->isTruncatingStore() && + St->getAddressingMode() == ISD::UNINDEXED; + } + /// isNON_TRUNCStore - Returns true if the specified node is a non-truncating /// store. inline bool isNON_TRUNCStore(const SDNode *N) { - return N->getOpcode() == ISD::STORE && - !cast(N)->isTruncatingStore(); + return isa(N) && !cast(N)->isTruncatingStore(); } /// isTRUNCStore - Returns true if the specified node is a truncating /// store. inline bool isTRUNCStore(const SDNode *N) { - return N->getOpcode() == ISD::STORE && - cast(N)->isTruncatingStore(); + return isa(N) && cast(N)->isTruncatingStore(); + } + + /// isUNINDEXEDStore - Returns true if the specified node is an + /// unindexed store. + inline bool isUNINDEXEDStore(const SDNode *N) { + return isa(N) && + cast(N)->getAddressingMode() == ISD::UNINDEXED; } } From baldrick at free.fr Fri Jun 20 13:39:50 2008 From: baldrick at free.fr (Duncan Sands) Date: Fri, 20 Jun 2008 20:39:50 +0200 Subject: [llvm-commits] [llvm] r52537 - /llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp In-Reply-To: <200806201516.m5KFGkRv024435@zion.cs.uiuc.edu> References: <200806201516.m5KFGkRv024435@zion.cs.uiuc.edu> Message-ID: <200806202039.51266.baldrick@free.fr> Hi, > + // return a struct again. This prevents chaning {something} into something chaning -> changing > + // No return types? Make it void, but only if we didn't use to return {} Missing full stop at end of comment. Ciao, Duncan. From baldrick at free.fr Fri Jun 20 13:40:51 2008 From: baldrick at free.fr (Duncan Sands) Date: Fri, 20 Jun 2008 18:40:51 -0000 Subject: [llvm-commits] [llvm] r52548 - in /llvm/trunk/lib/CodeGen/SelectionDAG: LegalizeFloatTypes.cpp LegalizeIntegerTypes.cpp LegalizeTypes.cpp LegalizeTypes.h LegalizeTypesGeneric.cpp LegalizeVectorTypes.cpp Message-ID: <200806201840.m5KIepHm000685@zion.cs.uiuc.edu> Author: baldrick Date: Fri Jun 20 13:40:50 2008 New Revision: 52548 URL: http://llvm.org/viewvc/llvm-project?rev=52548&view=rev Log: Share some code that is common between integer and float expansion (and sometimes vector splitting too). Added: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp?rev=52548&r1=52547&r2=52548&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp Fri Jun 20 13:40:50 2008 @@ -14,7 +14,7 @@ // The resulting integer value is the same as what you would get by performing // the floating point operation and bitcasting the result to the integer type. // Expansion is the act of changing a computation in an illegal type to be a -// computation in multiple registers of a smaller type. For example, +// computation in two identical registers of a smaller type. For example, // implementing ppcf128 arithmetic in two f64 registers. // //===----------------------------------------------------------------------===// @@ -395,6 +395,15 @@ #endif assert(0 && "Do not know how to expand the result of this operator!"); abort(); + + case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, Lo, Hi); break; + case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break; + case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break; + case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break; + + case ISD::BIT_CONVERT: ExpandRes_BIT_CONVERT(N, Lo, Hi); break; + case ISD::BUILD_PAIR: ExpandRes_BUILD_PAIR(N, Lo, Hi); break; + case ISD::EXTRACT_VECTOR_ELT: ExpandRes_EXTRACT_VECTOR_ELT(N, Lo, Hi); break; } // If Lo/Hi is null, the sub-method took care of registering results etc. @@ -428,6 +437,10 @@ #endif assert(0 && "Do not know how to expand this operator's operand!"); abort(); + + case ISD::BIT_CONVERT: Res = ExpandOp_BIT_CONVERT(N); break; + case ISD::BUILD_VECTOR: Res = ExpandOp_BUILD_VECTOR(N); break; + case ISD::EXTRACT_ELEMENT: Res = ExpandOp_EXTRACT_ELEMENT(N); break; } } Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp?rev=52548&r1=52547&r2=52548&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp Fri Jun 20 13:40:50 2008 @@ -12,7 +12,7 @@ // computation in a larger type. For example, implementing i8 arithmetic in an // i32 register (often needed on powerpc). // Expansion is the act of changing a computation in an illegal type into a -// computation in multiple registers of a smaller type. For example, +// computation in two identical registers of a smaller type. For example, // implementing i64 arithmetic in two i32 registers (often needed on 32-bit // targets). // @@ -753,19 +753,24 @@ cerr << "ExpandIntegerResult #" << ResNo << ": "; N->dump(&DAG); cerr << "\n"; #endif - assert(0&&"Do not know how to expand the result of this operator!"); + assert(0 && "Do not know how to expand the result of this operator!"); abort(); - case ISD::UNDEF: ExpandIntRes_UNDEF(N, Lo, Hi); break; + case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, Lo, Hi); break; + case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break; + case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break; + case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break; + + case ISD::BIT_CONVERT: ExpandRes_BIT_CONVERT(N, Lo, Hi); break; + case ISD::BUILD_PAIR: ExpandRes_BUILD_PAIR(N, Lo, Hi); break; + case ISD::EXTRACT_VECTOR_ELT: ExpandRes_EXTRACT_VECTOR_ELT(N, Lo, Hi); break; + case ISD::Constant: ExpandIntRes_Constant(N, Lo, Hi); break; - case ISD::BUILD_PAIR: ExpandIntRes_BUILD_PAIR(N, Lo, Hi); break; - case ISD::MERGE_VALUES: ExpandIntRes_MERGE_VALUES(N, Lo, Hi); break; case ISD::ANY_EXTEND: ExpandIntRes_ANY_EXTEND(N, Lo, Hi); break; case ISD::ZERO_EXTEND: ExpandIntRes_ZERO_EXTEND(N, Lo, Hi); break; case ISD::SIGN_EXTEND: ExpandIntRes_SIGN_EXTEND(N, Lo, Hi); break; case ISD::AssertZext: ExpandIntRes_AssertZext(N, Lo, Hi); break; case ISD::TRUNCATE: ExpandIntRes_TRUNCATE(N, Lo, Hi); break; - case ISD::BIT_CONVERT: ExpandIntRes_BIT_CONVERT(N, Lo, Hi); break; case ISD::SIGN_EXTEND_INREG: ExpandIntRes_SIGN_EXTEND_INREG(N, Lo, Hi); break; case ISD::FP_TO_SINT: ExpandIntRes_FP_TO_SINT(N, Lo, Hi); break; case ISD::FP_TO_UINT: ExpandIntRes_FP_TO_UINT(N, Lo, Hi); break; @@ -781,8 +786,6 @@ case ISD::SUBC: ExpandIntRes_ADDSUBC(N, Lo, Hi); break; case ISD::ADDE: case ISD::SUBE: ExpandIntRes_ADDSUBE(N, Lo, Hi); break; - case ISD::SELECT: ExpandIntRes_SELECT(N, Lo, Hi); break; - case ISD::SELECT_CC: ExpandIntRes_SELECT_CC(N, Lo, Hi); break; case ISD::MUL: ExpandIntRes_MUL(N, Lo, Hi); break; case ISD::SDIV: ExpandIntRes_SDIV(N, Lo, Hi); break; case ISD::SREM: ExpandIntRes_SREM(N, Lo, Hi); break; @@ -795,10 +798,6 @@ case ISD::CTLZ: ExpandIntRes_CTLZ(N, Lo, Hi); break; case ISD::CTPOP: ExpandIntRes_CTPOP(N, Lo, Hi); break; case ISD::CTTZ: ExpandIntRes_CTTZ(N, Lo, Hi); break; - - case ISD::EXTRACT_VECTOR_ELT: - ExpandIntRes_EXTRACT_VECTOR_ELT(N, Lo, Hi); - break; } // If Lo/Hi is null, the sub-method took care of registering results etc. @@ -806,12 +805,6 @@ SetExpandedInteger(SDOperand(N, ResNo), Lo, Hi); } -void DAGTypeLegalizer::ExpandIntRes_UNDEF(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - Lo = Hi = DAG.getNode(ISD::UNDEF, NVT); -} - void DAGTypeLegalizer::ExpandIntRes_Constant(SDNode *N, SDOperand &Lo, SDOperand &Hi) { MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); @@ -821,34 +814,6 @@ Hi = DAG.getConstant(Cst.lshr(NBitWidth).trunc(NBitWidth), NVT); } -void DAGTypeLegalizer::ExpandIntRes_BUILD_PAIR(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - // Return the operands. - Lo = N->getOperand(0); - Hi = N->getOperand(1); -} - -void DAGTypeLegalizer::ExpandIntRes_MERGE_VALUES(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - // A MERGE_VALUES node can produce any number of values. We know that the - // first illegal one needs to be expanded into Lo/Hi. - unsigned i; - - // The string of legal results gets turns into the input operands, which have - // the same type. - for (i = 0; isTypeLegal(N->getValueType(i)); ++i) - ReplaceValueWith(SDOperand(N, i), SDOperand(N->getOperand(i))); - - // The first illegal result must be the one that needs to be expanded. - GetExpandedInteger(N->getOperand(i), Lo, Hi); - - // Legalize the rest of the results into the input operands whether they are - // legal or not. - unsigned e = N->getNumValues(); - for (++i; i != e; ++i) - ReplaceValueWith(SDOperand(N, i), SDOperand(N->getOperand(i))); -} - void DAGTypeLegalizer::ExpandIntRes_ANY_EXTEND(SDNode *N, SDOperand &Lo, SDOperand &Hi) { MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); @@ -950,61 +915,6 @@ Hi = DAG.getNode(ISD::TRUNCATE, NVT, Hi); } -void DAGTypeLegalizer::ExpandIntRes_BIT_CONVERT(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - SDOperand InOp = N->getOperand(0); - MVT InVT = InOp.getValueType(); - - // Handle some special cases efficiently. - switch (getTypeAction(InVT)) { - default: - assert(false && "Unknown type action!"); - case Legal: - case PromoteInteger: - break; - case SoftenFloat: - // Convert the integer operand instead. - SplitInteger(GetSoftenedFloat(InOp), Lo, Hi); - Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); - Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); - return; - case ExpandInteger: - // Convert the expanded pieces of the input. - GetExpandedInteger(InOp, Lo, Hi); - Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); - Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); - return; - case ExpandFloat: - // Convert the expanded pieces of the input. - GetExpandedFloat(InOp, Lo, Hi); - Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); - Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); - return; - case Split: - // Convert the split parts of the input if it was split in two. - GetSplitVector(InOp, Lo, Hi); - if (Lo.getValueType() == Hi.getValueType()) { - if (TLI.isBigEndian()) - std::swap(Lo, Hi); - Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); - Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); - return; - } - break; - case Scalarize: - // Convert the element instead. - SplitInteger(BitConvertToInteger(GetScalarizedVector(InOp)), Lo, Hi); - Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); - Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); - return; - } - - // Lower the bit-convert to a store/load from the stack, then expand the load. - SDOperand Op = CreateStackStoreLoad(InOp, N->getValueType(0)); - ExpandIntRes_LOAD(cast(Op.Val), Lo, Hi); -} - void DAGTypeLegalizer:: ExpandIntRes_SIGN_EXTEND_INREG(SDNode *N, SDOperand &Lo, SDOperand &Hi) { GetExpandedInteger(N->getOperand(0), Lo, Hi); @@ -1090,7 +1000,13 @@ void DAGTypeLegalizer::ExpandIntRes_LOAD(LoadSDNode *N, SDOperand &Lo, SDOperand &Hi) { - // FIXME: Add support for indexed loads. + if (ISD::isNON_EXTLoad(N)) { + ExpandRes_NON_EXTLOAD(N, Lo, Hi); + return; + } + + assert(ISD::isUNINDEXEDLoad(N) && "Indexed load during type legalization!"); + MVT VT = N->getValueType(0); MVT NVT = TLI.getTypeToTransformTo(VT); SDOperand Ch = N->getChain(); // Legalize the chain. @@ -1100,27 +1016,9 @@ unsigned Alignment = N->getAlignment(); bool isVolatile = N->isVolatile(); - assert(!(NVT.getSizeInBits() & 7) && "Expanded type not byte sized!"); - - if (ExtType == ISD::NON_EXTLOAD) { - Lo = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset, - isVolatile, Alignment); - // Increment the pointer to the other half. - unsigned IncrementSize = NVT.getSizeInBits()/8; - Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, - DAG.getIntPtrConstant(IncrementSize)); - Hi = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset+IncrementSize, - isVolatile, MinAlign(Alignment, IncrementSize)); + assert(NVT.isByteSized() && "Expanded type not byte sized!"); - // Build a factor node to remember that this load is independent of the - // other one. - Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1), - Hi.getValue(1)); - - // Handle endianness of the load. - if (TLI.isBigEndian()) - std::swap(Lo, Hi); - } else if (N->getMemoryVT().bitsLE(NVT)) { + if (N->getMemoryVT().bitsLE(NVT)) { MVT EVT = N->getMemoryVT(); Lo = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(), SVOffset, EVT, @@ -1225,26 +1123,6 @@ Hi = DAG.getNode(ISD::BSWAP, Hi.getValueType(), Hi); } -void DAGTypeLegalizer::ExpandIntRes_SELECT(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - SDOperand LL, LH, RL, RH; - GetExpandedInteger(N->getOperand(1), LL, LH); - GetExpandedInteger(N->getOperand(2), RL, RH); - Lo = DAG.getNode(ISD::SELECT, LL.getValueType(), N->getOperand(0), LL, RL); - Hi = DAG.getNode(ISD::SELECT, LL.getValueType(), N->getOperand(0), LH, RH); -} - -void DAGTypeLegalizer::ExpandIntRes_SELECT_CC(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - SDOperand LL, LH, RL, RH; - GetExpandedInteger(N->getOperand(2), LL, LH); - GetExpandedInteger(N->getOperand(3), RL, RH); - Lo = DAG.getNode(ISD::SELECT_CC, LL.getValueType(), N->getOperand(0), - N->getOperand(1), LL, RL, N->getOperand(4)); - Hi = DAG.getNode(ISD::SELECT_CC, LL.getValueType(), N->getOperand(0), - N->getOperand(1), LH, RH, N->getOperand(4)); -} - void DAGTypeLegalizer::ExpandIntRes_ADDSUB(SDNode *N, SDOperand &Lo, SDOperand &Hi) { // Expand the subcomponents. @@ -1522,41 +1400,6 @@ Hi = DAG.getConstant(0, NVT); } -void DAGTypeLegalizer::ExpandIntRes_EXTRACT_VECTOR_ELT(SDNode *N, - SDOperand &Lo, - SDOperand &Hi) { - SDOperand OldVec = N->getOperand(0); - unsigned OldElts = OldVec.getValueType().getVectorNumElements(); - - // Convert to a vector of the expanded element type, for example - // <2 x i64> -> <4 x i32>. - MVT OldVT = N->getValueType(0); - MVT NewVT = TLI.getTypeToTransformTo(OldVT); - assert(OldVT.getSizeInBits() == 2 * NewVT.getSizeInBits() && - "Do not know how to handle this expansion!"); - - SDOperand NewVec = DAG.getNode(ISD::BIT_CONVERT, - MVT::getVectorVT(NewVT, 2*OldElts), - OldVec); - - // Extract the elements at 2 * Idx and 2 * Idx + 1 from the new vector. - SDOperand Idx = N->getOperand(1); - - // Make sure the type of Idx is big enough to hold the new values. - if (Idx.getValueType().bitsLT(TLI.getPointerTy())) - Idx = DAG.getNode(ISD::ZERO_EXTEND, TLI.getPointerTy(), Idx); - - Idx = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx, Idx); - Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, Idx); - - Idx = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx, - DAG.getConstant(1, Idx.getValueType())); - Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, Idx); - - if (TLI.isBigEndian()) - std::swap(Lo, Hi); -} - /// ExpandShiftByConstant - N is a shift by a value that needs to be expanded, /// and the shift amount is a constant 'Amt'. Expand the operation. void DAGTypeLegalizer::ExpandShiftByConstant(SDNode *N, unsigned Amt, @@ -1737,8 +1580,11 @@ assert(0 && "Do not know how to expand this operator's operand!"); abort(); + case ISD::BUILD_VECTOR: Res = ExpandOp_BUILD_VECTOR(N); break; + case ISD::BIT_CONVERT: Res = ExpandOp_BIT_CONVERT(N); break; + case ISD::EXTRACT_ELEMENT: Res = ExpandOp_EXTRACT_ELEMENT(N); break; + case ISD::TRUNCATE: Res = ExpandIntOp_TRUNCATE(N); break; - case ISD::BIT_CONVERT: Res = ExpandIntOp_BIT_CONVERT(N); break; case ISD::SINT_TO_FP: Res = ExpandIntOp_SINT_TO_FP(N->getOperand(0), N->getValueType(0)); @@ -1746,7 +1592,6 @@ case ISD::UINT_TO_FP: Res = ExpandIntOp_UINT_TO_FP(N->getOperand(0), N->getValueType(0)); break; - case ISD::EXTRACT_ELEMENT: Res = ExpandIntOp_EXTRACT_ELEMENT(N); break; case ISD::BR_CC: Res = ExpandIntOp_BR_CC(N); break; case ISD::SETCC: Res = ExpandIntOp_SETCC(N); break; @@ -1754,8 +1599,6 @@ case ISD::STORE: Res = ExpandIntOp_STORE(cast(N), OpNo); break; - - case ISD::BUILD_VECTOR: Res = ExpandIntOp_BUILD_VECTOR(N); break; } } @@ -1785,32 +1628,6 @@ return DAG.getNode(ISD::TRUNCATE, N->getValueType(0), InL); } -SDOperand DAGTypeLegalizer::ExpandIntOp_BIT_CONVERT(SDNode *N) { - if (N->getValueType(0).isVector()) { - // An illegal integer type is being converted to a legal vector type. - // Make a two element vector out of the expanded parts and convert that - // instead, but only if the new vector type is legal (otherwise there - // is no point, and it might create expansion loops). For example, on - // x86 this turns v1i64 = BIT_CONVERT i64 into v1i64 = BIT_CONVERT v2i32. - MVT OVT = N->getOperand(0).getValueType(); - MVT NVT = MVT::getVectorVT(TLI.getTypeToTransformTo(OVT), 2); - - if (isTypeLegal(NVT)) { - SDOperand Parts[2]; - GetExpandedInteger(N->getOperand(0), Parts[0], Parts[1]); - - if (TLI.isBigEndian()) - std::swap(Parts[0], Parts[1]); - - SDOperand Vec = DAG.getNode(ISD::BUILD_VECTOR, NVT, Parts, 2); - return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Vec); - } - } - - // Otherwise, store to a temporary and load out again as the new type. - return CreateStackStoreLoad(N->getOperand(0), N->getValueType(0)); -} - SDOperand DAGTypeLegalizer::ExpandIntOp_SINT_TO_FP(SDOperand Source, MVT DestTy) { // We know the destination is legal, but that the input needs to be expanded. @@ -1898,12 +1715,6 @@ return DAG.getNode(ISD::FADD, DestTy, SignedConv, FudgeInReg); } -SDOperand DAGTypeLegalizer::ExpandIntOp_EXTRACT_ELEMENT(SDNode *N) { - SDOperand Lo, Hi; - GetExpandedInteger(N->getOperand(0), Lo, Hi); - return cast(N->getOperand(1))->getValue() ? Hi : Lo; -} - SDOperand DAGTypeLegalizer::ExpandIntOp_BR_CC(SDNode *N) { SDOperand NewLHS = N->getOperand(2), NewRHS = N->getOperand(3); ISD::CondCode CCCode = cast(N->getOperand(1))->get(); @@ -2049,7 +1860,10 @@ } SDOperand DAGTypeLegalizer::ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo) { - // FIXME: Add support for indexed stores. + if (ISD::isNON_TRUNCStore(N)) + return ExpandOp_NON_TRUNCStore(N, OpNo); + + assert(ISD::isUNINDEXEDStore(N) && "Indexed store during type legalization!"); assert(OpNo == 1 && "Can only expand the stored value so far"); MVT VT = N->getOperand(1).getValueType(); @@ -2063,24 +1877,7 @@ assert(!(NVT.getSizeInBits() & 7) && "Expanded type not byte sized!"); - if (!N->isTruncatingStore()) { - unsigned IncrementSize = 0; - GetExpandedInteger(N->getValue(), Lo, Hi); - IncrementSize = Hi.getValueType().getSizeInBits()/8; - - if (TLI.isBigEndian()) - std::swap(Lo, Hi); - - Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(), - SVOffset, isVolatile, Alignment); - - Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, - DAG.getIntPtrConstant(IncrementSize)); - assert(isTypeLegal(Ptr.getValueType()) && "Pointers must be legal!"); - Hi = DAG.getStore(Ch, Hi, Ptr, N->getSrcValue(), SVOffset+IncrementSize, - isVolatile, MinAlign(Alignment, IncrementSize)); - return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi); - } else if (N->getMemoryVT().bitsLE(NVT)) { + if (N->getMemoryVT().bitsLE(NVT)) { GetExpandedInteger(N->getValue(), Lo, Hi); return DAG.getTruncStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset, N->getMemoryVT(), isVolatile, Alignment); @@ -2140,35 +1937,3 @@ return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi); } } - -SDOperand DAGTypeLegalizer::ExpandIntOp_BUILD_VECTOR(SDNode *N) { - // The vector type is legal but the element type needs expansion. - MVT VecVT = N->getValueType(0); - unsigned NumElts = VecVT.getVectorNumElements(); - MVT OldVT = N->getOperand(0).getValueType(); - MVT NewVT = TLI.getTypeToTransformTo(OldVT); - - assert(OldVT.getSizeInBits() == 2 * NewVT.getSizeInBits() && - "Do not know how to expand this operand!"); - - // Build a vector of twice the length out of the expanded elements. - // For example <2 x i64> -> <4 x i32>. - std::vector NewElts; - NewElts.reserve(NumElts*2); - - for (unsigned i = 0; i < NumElts; ++i) { - SDOperand Lo, Hi; - GetExpandedInteger(N->getOperand(i), Lo, Hi); - if (TLI.isBigEndian()) - std::swap(Lo, Hi); - NewElts.push_back(Lo); - NewElts.push_back(Hi); - } - - SDOperand NewVec = DAG.getNode(ISD::BUILD_VECTOR, - MVT::getVectorVT(NewVT, NewElts.size()), - &NewElts[0], NewElts.size()); - - // Convert the new vector to the old vector type. - return DAG.getNode(ISD::BIT_CONVERT, VecVT, NewVec); -} Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp?rev=52548&r1=52547&r2=52548&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp Fri Jun 20 13:40:50 2008 @@ -543,6 +543,10 @@ } +//===----------------------------------------------------------------------===// +// Utilities. +//===----------------------------------------------------------------------===// + /// BitConvertToInteger - Convert to an integer of the same size. SDOperand DAGTypeLegalizer::BitConvertToInteger(SDOperand Op) { unsigned BitWidth = Op.getValueType().getSizeInBits(); @@ -637,6 +641,26 @@ return DAG.getNode(ISD::ADD, Index.getValueType(), Index, VecPtr); } +/// GetSplitDestVTs - Compute the VTs needed for the low/hi parts of a type +/// which is split into two not necessarily identical pieces. +void DAGTypeLegalizer::GetSplitDestVTs(MVT InVT, MVT &LoVT, MVT &HiVT) { + if (!InVT.isVector()) { + LoVT = HiVT = TLI.getTypeToTransformTo(InVT); + } else { + MVT NewEltVT = InVT.getVectorElementType(); + unsigned NumElements = InVT.getVectorNumElements(); + if ((NumElements & (NumElements-1)) == 0) { // Simple power of two vector. + NumElements >>= 1; + LoVT = HiVT = MVT::getVectorVT(NewEltVT, NumElements); + } else { // Non-power-of-two vectors. + unsigned NewNumElts_Lo = 1 << Log2_32(NumElements); + unsigned NewNumElts_Hi = NumElements - NewNumElts_Lo; + LoVT = MVT::getVectorVT(NewEltVT, NewNumElts_Lo); + HiVT = MVT::getVectorVT(NewEltVT, NewNumElts_Hi); + } + } +} + //===----------------------------------------------------------------------===// // Entry Point Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h?rev=52548&r1=52547&r2=52548&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h Fri Jun 20 13:40:50 2008 @@ -267,19 +267,14 @@ void ExpandIntegerResult(SDNode *N, unsigned ResNo); void ExpandIntRes_ANY_EXTEND (SDNode *N, SDOperand &Lo, SDOperand &Hi); void ExpandIntRes_AssertZext (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandIntRes_BIT_CONVERT (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandIntRes_BUILD_PAIR (SDNode *N, SDOperand &Lo, SDOperand &Hi); void ExpandIntRes_Constant (SDNode *N, SDOperand &Lo, SDOperand &Hi); void ExpandIntRes_CTLZ (SDNode *N, SDOperand &Lo, SDOperand &Hi); void ExpandIntRes_CTPOP (SDNode *N, SDOperand &Lo, SDOperand &Hi); void ExpandIntRes_CTTZ (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandIntRes_EXTRACT_VECTOR_ELT(SDNode *N, SDOperand &Lo, SDOperand &Hi); void ExpandIntRes_LOAD (LoadSDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandIntRes_MERGE_VALUES (SDNode *N, SDOperand &Lo, SDOperand &Hi); void ExpandIntRes_SIGN_EXTEND (SDNode *N, SDOperand &Lo, SDOperand &Hi); void ExpandIntRes_SIGN_EXTEND_INREG (SDNode *N, SDOperand &Lo, SDOperand &Hi); void ExpandIntRes_TRUNCATE (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandIntRes_UNDEF (SDNode *N, SDOperand &Lo, SDOperand &Hi); void ExpandIntRes_ZERO_EXTEND (SDNode *N, SDOperand &Lo, SDOperand &Hi); void ExpandIntRes_FP_TO_SINT (SDNode *N, SDOperand &Lo, SDOperand &Hi); void ExpandIntRes_FP_TO_UINT (SDNode *N, SDOperand &Lo, SDOperand &Hi); @@ -289,8 +284,6 @@ void ExpandIntRes_ADDSUB (SDNode *N, SDOperand &Lo, SDOperand &Hi); void ExpandIntRes_ADDSUBC (SDNode *N, SDOperand &Lo, SDOperand &Hi); void ExpandIntRes_ADDSUBE (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandIntRes_SELECT (SDNode *N, SDOperand &Lo, SDOperand &Hi); - void ExpandIntRes_SELECT_CC (SDNode *N, SDOperand &Lo, SDOperand &Hi); void ExpandIntRes_MUL (SDNode *N, SDOperand &Lo, SDOperand &Hi); void ExpandIntRes_SDIV (SDNode *N, SDOperand &Lo, SDOperand &Hi); void ExpandIntRes_SREM (SDNode *N, SDOperand &Lo, SDOperand &Hi); @@ -372,22 +365,22 @@ // Vector Result Scalarization: <1 x ty> -> ty. void ScalarizeResult(SDNode *N, unsigned OpNo); - SDOperand ScalarizeRes_BinOp(SDNode *N); - SDOperand ScalarizeRes_UnaryOp(SDNode *N); + SDOperand ScalarizeVecRes_BinOp(SDNode *N); + SDOperand ScalarizeVecRes_UnaryOp(SDNode *N); - SDOperand ScalarizeRes_BIT_CONVERT(SDNode *N); - SDOperand ScalarizeRes_FPOWI(SDNode *N); - SDOperand ScalarizeRes_INSERT_VECTOR_ELT(SDNode *N); - SDOperand ScalarizeRes_LOAD(LoadSDNode *N); - SDOperand ScalarizeRes_SELECT(SDNode *N); - SDOperand ScalarizeRes_UNDEF(SDNode *N); - SDOperand ScalarizeRes_VECTOR_SHUFFLE(SDNode *N); + SDOperand ScalarizeVecRes_BIT_CONVERT(SDNode *N); + SDOperand ScalarizeVecRes_FPOWI(SDNode *N); + SDOperand ScalarizeVecRes_INSERT_VECTOR_ELT(SDNode *N); + SDOperand ScalarizeVecRes_LOAD(LoadSDNode *N); + SDOperand ScalarizeVecRes_SELECT(SDNode *N); + SDOperand ScalarizeVecRes_UNDEF(SDNode *N); + SDOperand ScalarizeVecRes_VECTOR_SHUFFLE(SDNode *N); // Vector Operand Scalarization: <1 x ty> -> ty. bool ScalarizeOperand(SDNode *N, unsigned OpNo); - SDOperand ScalarizeOp_BIT_CONVERT(SDNode *N); - SDOperand ScalarizeOp_EXTRACT_VECTOR_ELT(SDNode *N); - SDOperand ScalarizeOp_STORE(StoreSDNode *N, unsigned OpNo); + SDOperand ScalarizeVecOp_BIT_CONVERT(SDNode *N); + SDOperand ScalarizeVecOp_EXTRACT_VECTOR_ELT(SDNode *N); + SDOperand ScalarizeVecOp_STORE(StoreSDNode *N, unsigned OpNo); //===--------------------------------------------------------------------===// // Vector Splitting Support: LegalizeVectorTypes.cpp @@ -399,29 +392,85 @@ // Vector Result Splitting: <128 x ty> -> 2 x <64 x ty>. void SplitResult(SDNode *N, unsigned OpNo); - void SplitRes_UNDEF(SDNode *N, SDOperand &Lo, SDOperand &Hi); - void SplitRes_LOAD(LoadSDNode *N, SDOperand &Lo, SDOperand &Hi); - void SplitRes_BUILD_PAIR(SDNode *N, SDOperand &Lo, SDOperand &Hi); - void SplitRes_INSERT_VECTOR_ELT(SDNode *N, SDOperand &Lo, SDOperand &Hi); - void SplitRes_VECTOR_SHUFFLE(SDNode *N, SDOperand &Lo, SDOperand &Hi); - - void SplitRes_BUILD_VECTOR(SDNode *N, SDOperand &Lo, SDOperand &Hi); - void SplitRes_CONCAT_VECTORS(SDNode *N, SDOperand &Lo, SDOperand &Hi); - void SplitRes_BIT_CONVERT(SDNode *N, SDOperand &Lo, SDOperand &Hi); - void SplitRes_UnOp(SDNode *N, SDOperand &Lo, SDOperand &Hi); - void SplitRes_BinOp(SDNode *N, SDOperand &Lo, SDOperand &Hi); - void SplitRes_FPOWI(SDNode *N, SDOperand &Lo, SDOperand &Hi); - void SplitRes_SELECT(SDNode *N, SDOperand &Lo, SDOperand &Hi); + void SplitVecRes_UNDEF(SDNode *N, SDOperand &Lo, SDOperand &Hi); + void SplitVecRes_LOAD(LoadSDNode *N, SDOperand &Lo, SDOperand &Hi); + void SplitVecRes_BUILD_PAIR(SDNode *N, SDOperand &Lo, SDOperand &Hi); + void SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDOperand &Lo, SDOperand &Hi); + void SplitVecRes_VECTOR_SHUFFLE(SDNode *N, SDOperand &Lo, SDOperand &Hi); + + void SplitVecRes_BUILD_VECTOR(SDNode *N, SDOperand &Lo, SDOperand &Hi); + void SplitVecRes_CONCAT_VECTORS(SDNode *N, SDOperand &Lo, SDOperand &Hi); + void SplitVecRes_BIT_CONVERT(SDNode *N, SDOperand &Lo, SDOperand &Hi); + void SplitVecRes_UnOp(SDNode *N, SDOperand &Lo, SDOperand &Hi); + void SplitVecRes_BinOp(SDNode *N, SDOperand &Lo, SDOperand &Hi); + void SplitVecRes_FPOWI(SDNode *N, SDOperand &Lo, SDOperand &Hi); + void SplitVecRes_SELECT(SDNode *N, SDOperand &Lo, SDOperand &Hi); // Vector Operand Splitting: <128 x ty> -> 2 x <64 x ty>. bool SplitOperand(SDNode *N, unsigned OpNo); - SDOperand SplitOp_BIT_CONVERT(SDNode *N); - SDOperand SplitOp_EXTRACT_SUBVECTOR(SDNode *N); - SDOperand SplitOp_EXTRACT_VECTOR_ELT(SDNode *N); - SDOperand SplitOp_RET(SDNode *N, unsigned OpNo); - SDOperand SplitOp_STORE(StoreSDNode *N, unsigned OpNo); - SDOperand SplitOp_VECTOR_SHUFFLE(SDNode *N, unsigned OpNo); + SDOperand SplitVecOp_BIT_CONVERT(SDNode *N); + SDOperand SplitVecOp_EXTRACT_SUBVECTOR(SDNode *N); + SDOperand SplitVecOp_EXTRACT_VECTOR_ELT(SDNode *N); + SDOperand SplitVecOp_RET(SDNode *N, unsigned OpNo); + SDOperand SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo); + SDOperand SplitVecOp_VECTOR_SHUFFLE(SDNode *N, unsigned OpNo); + + //===--------------------------------------------------------------------===// + // Generic Splitting: LegalizeTypesGeneric.cpp + //===--------------------------------------------------------------------===// + + // Legalization methods which only use that the illegal type is split into two + // not necessarily identical types. As such they can be used for splitting + // vectors and expanding integers and floats. + + void GetSplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi) { + if (Op.getValueType().isVector()) + GetSplitVector(Op, Lo, Hi); + else if (Op.getValueType().isInteger()) + GetExpandedInteger(Op, Lo, Hi); + else + GetExpandedFloat(Op, Lo, Hi); + } + + /// GetSplitDestVTs - Compute the VTs needed for the low/hi parts of a type + /// which is split (or expanded) into two not necessarily identical pieces. + void GetSplitDestVTs(MVT InVT, MVT &LoVT, MVT &HiVT); + + // Generic Result Splitting. + void SplitRes_MERGE_VALUES(SDNode *N, SDOperand &Lo, SDOperand &Hi); + void SplitRes_SELECT (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void SplitRes_SELECT_CC (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void SplitRes_UNDEF (SDNode *N, SDOperand &Lo, SDOperand &Hi); + + //===--------------------------------------------------------------------===// + // Generic Expansion: LegalizeTypesGeneric.cpp + //===--------------------------------------------------------------------===// + + // Legalization methods which only use that the illegal type is split into two + // identical types of half the size, and that the Lo/Hi part is stored first + // in memory on little/big-endian machines, followed by the Hi/Lo part. As + // such they can be used for expanding integers and floats. + + void GetExpandedOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi) { + if (Op.getValueType().isInteger()) + GetExpandedInteger(Op, Lo, Hi); + else + GetExpandedFloat(Op, Lo, Hi); + } + + // Generic Result Expansion. + void ExpandRes_BIT_CONVERT (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandRes_BUILD_PAIR (SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandRes_EXTRACT_VECTOR_ELT(SDNode *N, SDOperand &Lo, SDOperand &Hi); + void ExpandRes_NON_EXTLOAD (SDNode *N, SDOperand &Lo, SDOperand &Hi); + + // Generic Operand Expansion. + SDOperand ExpandOp_BIT_CONVERT (SDNode *N); + SDOperand ExpandOp_BUILD_VECTOR (SDNode *N); + SDOperand ExpandOp_EXTRACT_ELEMENT(SDNode *N); + SDOperand ExpandOp_NON_TRUNCStore (SDNode *N, unsigned OpNo); + }; } // end namespace llvm. Added: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp?rev=52548&view=auto ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp (added) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp Fri Jun 20 13:40:50 2008 @@ -0,0 +1,318 @@ +//===-------- LegalizeTypesGeneric.cpp - Generic type legalization --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements generic type expansion and splitting for LegalizeTypes. +// The routines here perform legalization when the details of the type (such as +// whether it is an integer or a float) do not matter. +// Expansion is the act of changing a computation in an illegal type to be a +// computation in two identical registers of a smaller type. +// Splitting is the act of changing a computation in an illegal type to be a +// computation in two not necessarily identical registers of a smaller type. +// +//===----------------------------------------------------------------------===// + +#include "LegalizeTypes.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Generic Result Expansion. +//===----------------------------------------------------------------------===// + +// These routines assume that the Lo/Hi part is stored first in memory on +// little/big-endian machines, followed by the Hi/Lo part. This means that +// they cannot be used as is on vectors, for which Lo is always stored first. + +void DAGTypeLegalizer::ExpandRes_BIT_CONVERT(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + SDOperand InOp = N->getOperand(0); + MVT InVT = InOp.getValueType(); + + // Handle some special cases efficiently. + switch (getTypeAction(InVT)) { + default: + assert(false && "Unknown type action!"); + case Legal: + case PromoteInteger: + break; + case SoftenFloat: + // Convert the integer operand instead. + SplitInteger(GetSoftenedFloat(InOp), Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); + return; + case ExpandInteger: + case ExpandFloat: + // Convert the expanded pieces of the input. + GetExpandedOp(InOp, Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); + return; + case Split: + // Convert the split parts of the input if it was split in two. + GetSplitVector(InOp, Lo, Hi); + if (Lo.getValueType() == Hi.getValueType()) { + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); + return; + } + break; + case Scalarize: + // Convert the element instead. + SplitInteger(BitConvertToInteger(GetScalarizedVector(InOp)), Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); + return; + } + + // Lower the bit-convert to a store/load from the stack, then expand the load. + SDOperand Op = CreateStackStoreLoad(InOp, N->getValueType(0)); + ExpandRes_NON_EXTLOAD(Op.Val, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandRes_BUILD_PAIR(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + // Return the operands. + Lo = N->getOperand(0); + Hi = N->getOperand(1); +} + +void DAGTypeLegalizer::ExpandRes_EXTRACT_VECTOR_ELT(SDNode *N, + SDOperand &Lo, + SDOperand &Hi) { + SDOperand OldVec = N->getOperand(0); + unsigned OldElts = OldVec.getValueType().getVectorNumElements(); + + // Convert to a vector of the expanded element type, for example + // <3 x i64> -> <6 x i32>. + MVT OldVT = N->getValueType(0); + MVT NewVT = TLI.getTypeToTransformTo(OldVT); + + SDOperand NewVec = DAG.getNode(ISD::BIT_CONVERT, + MVT::getVectorVT(NewVT, 2*OldElts), + OldVec); + + // Extract the elements at 2 * Idx and 2 * Idx + 1 from the new vector. + SDOperand Idx = N->getOperand(1); + + // Make sure the type of Idx is big enough to hold the new values. + if (Idx.getValueType().bitsLT(TLI.getPointerTy())) + Idx = DAG.getNode(ISD::ZERO_EXTEND, TLI.getPointerTy(), Idx); + + Idx = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx, Idx); + Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, Idx); + + Idx = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx, + DAG.getConstant(1, Idx.getValueType())); + Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, Idx); + + if (TLI.isBigEndian()) + std::swap(Lo, Hi); +} + +void DAGTypeLegalizer::ExpandRes_NON_EXTLOAD(SDNode *N, SDOperand &Lo, + SDOperand &Hi) { + assert(ISD::isNON_EXTLoad(N) && "This routine is not for extending loads!"); + assert(ISD::isUNINDEXEDLoad(N) && "Indexed load during type legalization!"); + + LoadSDNode *LD = cast(N); + MVT NVT = TLI.getTypeToTransformTo(LD->getValueType(0)); + SDOperand Chain = LD->getChain(); + SDOperand Ptr = LD->getBasePtr(); + int SVOffset = LD->getSrcValueOffset(); + unsigned Alignment = LD->getAlignment(); + bool isVolatile = LD->isVolatile(); + + assert(NVT.isByteSized() && "Expanded type not byte sized!"); + + Lo = DAG.getLoad(NVT, Chain, Ptr, LD->getSrcValue(), SVOffset, + isVolatile, Alignment); + + // Increment the pointer to the other half. + unsigned IncrementSize = NVT.getSizeInBits() / 8; + Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + Hi = DAG.getLoad(NVT, Chain, Ptr, LD->getSrcValue(), SVOffset+IncrementSize, + isVolatile, MinAlign(Alignment, IncrementSize)); + + // Build a factor node to remember that this load is independent of the + // other one. + Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1), + Hi.getValue(1)); + + // Handle endianness of the load. + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + // Modified the chain - switch anything that used the old chain to use + // the new one. + ReplaceValueWith(SDOperand(N, 1), Chain); +} + +//===--------------------------------------------------------------------===// +// Generic Operand Expansion. +//===--------------------------------------------------------------------===// + +SDOperand DAGTypeLegalizer::ExpandOp_BIT_CONVERT(SDNode *N) { + if (N->getValueType(0).isVector()) { + // An illegal expanding type is being converted to a legal vector type. + // Make a two element vector out of the expanded parts and convert that + // instead, but only if the new vector type is legal (otherwise there + // is no point, and it might create expansion loops). For example, on + // x86 this turns v1i64 = BIT_CONVERT i64 into v1i64 = BIT_CONVERT v2i32. + MVT OVT = N->getOperand(0).getValueType(); + MVT NVT = MVT::getVectorVT(TLI.getTypeToTransformTo(OVT), 2); + + if (isTypeLegal(NVT)) { + SDOperand Parts[2]; + GetExpandedOp(N->getOperand(0), Parts[0], Parts[1]); + + if (TLI.isBigEndian()) + std::swap(Parts[0], Parts[1]); + + SDOperand Vec = DAG.getNode(ISD::BUILD_VECTOR, NVT, Parts, 2); + return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Vec); + } + } + + // Otherwise, store to a temporary and load out again as the new type. + return CreateStackStoreLoad(N->getOperand(0), N->getValueType(0)); +} + +SDOperand DAGTypeLegalizer::ExpandOp_BUILD_VECTOR(SDNode *N) { + // The vector type is legal but the element type needs expansion. + MVT VecVT = N->getValueType(0); + unsigned NumElts = VecVT.getVectorNumElements(); + MVT OldVT = N->getOperand(0).getValueType(); + MVT NewVT = TLI.getTypeToTransformTo(OldVT); + + // Build a vector of twice the length out of the expanded elements. + // For example <3 x i64> -> <6 x i32>. + std::vector NewElts; + NewElts.reserve(NumElts*2); + + for (unsigned i = 0; i < NumElts; ++i) { + SDOperand Lo, Hi; + GetExpandedOp(N->getOperand(i), Lo, Hi); + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + NewElts.push_back(Lo); + NewElts.push_back(Hi); + } + + SDOperand NewVec = DAG.getNode(ISD::BUILD_VECTOR, + MVT::getVectorVT(NewVT, NewElts.size()), + &NewElts[0], NewElts.size()); + + // Convert the new vector to the old vector type. + return DAG.getNode(ISD::BIT_CONVERT, VecVT, NewVec); +} + +SDOperand DAGTypeLegalizer::ExpandOp_EXTRACT_ELEMENT(SDNode *N) { + SDOperand Lo, Hi; + GetExpandedOp(N->getOperand(0), Lo, Hi); + return cast(N->getOperand(1))->getValue() ? Hi : Lo; +} + +SDOperand DAGTypeLegalizer::ExpandOp_NON_TRUNCStore(SDNode *N, unsigned OpNo) { + assert(ISD::isNON_TRUNCStore(N) && "This routine not for truncating stores!"); + assert(ISD::isUNINDEXEDStore(N) && "Indexed store during type legalization!"); + assert(OpNo == 1 && "Can only expand the stored value so far"); + + StoreSDNode *St = cast(N); + MVT NVT = TLI.getTypeToTransformTo(St->getValue().getValueType()); + SDOperand Chain = St->getChain(); + SDOperand Ptr = St->getBasePtr(); + int SVOffset = St->getSrcValueOffset(); + unsigned Alignment = St->getAlignment(); + bool isVolatile = St->isVolatile(); + + assert(NVT.isByteSized() && "Expanded type not byte sized!"); + unsigned IncrementSize = NVT.getSizeInBits() / 8; + + SDOperand Lo, Hi; + GetExpandedOp(St->getValue(), Lo, Hi); + + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + Lo = DAG.getStore(Chain, Lo, Ptr, St->getSrcValue(), SVOffset, + isVolatile, Alignment); + + Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, + DAG.getIntPtrConstant(IncrementSize)); + assert(isTypeLegal(Ptr.getValueType()) && "Pointers must be legal!"); + Hi = DAG.getStore(Chain, Hi, Ptr, St->getSrcValue(), SVOffset + IncrementSize, + isVolatile, MinAlign(Alignment, IncrementSize)); + + return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi); +} + + +//===--------------------------------------------------------------------===// +// Generic Result Splitting. +//===--------------------------------------------------------------------===// + +// Be careful to make no assumptions about which of Lo/Hi is stored first in +// memory (for vectors it is always Lo first followed by Hi in the following +// bytes; for integers and floats it is Lo first if and only if the machine is +// little-endian). + +void DAGTypeLegalizer::SplitRes_MERGE_VALUES(SDNode *N, + SDOperand &Lo, SDOperand &Hi) { + // A MERGE_VALUES node can produce any number of values. We know that the + // first illegal one needs to be expanded into Lo/Hi. + unsigned i; + + // The string of legal results gets turns into the input operands, which have + // the same type. + for (i = 0; isTypeLegal(N->getValueType(i)); ++i) + ReplaceValueWith(SDOperand(N, i), SDOperand(N->getOperand(i))); + + // The first illegal result must be the one that needs to be expanded. + GetSplitOp(N->getOperand(i), Lo, Hi); + + // Legalize the rest of the results into the input operands whether they are + // legal or not. + unsigned e = N->getNumValues(); + for (++i; i != e; ++i) + ReplaceValueWith(SDOperand(N, i), SDOperand(N->getOperand(i))); +} + +void DAGTypeLegalizer::SplitRes_SELECT(SDNode *N, SDOperand &Lo, + SDOperand &Hi) { + SDOperand LL, LH, RL, RH; + GetSplitOp(N->getOperand(1), LL, LH); + GetSplitOp(N->getOperand(2), RL, RH); + + SDOperand Cond = N->getOperand(0); + Lo = DAG.getNode(ISD::SELECT, LL.getValueType(), Cond, LL, RL); + Hi = DAG.getNode(ISD::SELECT, LH.getValueType(), Cond, LH, RH); +} + +void DAGTypeLegalizer::SplitRes_SELECT_CC(SDNode *N, SDOperand &Lo, + SDOperand &Hi) { + SDOperand LL, LH, RL, RH; + GetSplitOp(N->getOperand(2), LL, LH); + GetSplitOp(N->getOperand(3), RL, RH); + + Lo = DAG.getNode(ISD::SELECT_CC, LL.getValueType(), N->getOperand(0), + N->getOperand(1), LL, RL, N->getOperand(4)); + Hi = DAG.getNode(ISD::SELECT_CC, LH.getValueType(), N->getOperand(0), + N->getOperand(1), LH, RH, N->getOperand(4)); +} + +void DAGTypeLegalizer::SplitRes_UNDEF(SDNode *N, SDOperand &Lo, SDOperand &Hi) { + MVT LoVT, HiVT; + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + Lo = DAG.getNode(ISD::UNDEF, LoVT); + Hi = DAG.getNode(ISD::UNDEF, HiVT); +} Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp?rev=52548&r1=52547&r2=52548&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp Fri Jun 20 13:40:50 2008 @@ -56,8 +56,9 @@ assert(0 && "Do not know how to scalarize the result of this operator!"); abort(); - case ISD::UNDEF: R = ScalarizeRes_UNDEF(N); break; - case ISD::LOAD: R = ScalarizeRes_LOAD(cast(N)); break; + case ISD::UNDEF: R = ScalarizeVecRes_UNDEF(N); break; + case ISD::LOAD: R = ScalarizeVecRes_LOAD(cast(N)); break; + case ISD::ADD: case ISD::FADD: case ISD::SUB: @@ -73,18 +74,20 @@ case ISD::FPOW: case ISD::AND: case ISD::OR: - case ISD::XOR: R = ScalarizeRes_BinOp(N); break; + case ISD::XOR: R = ScalarizeVecRes_BinOp(N); break; + case ISD::FNEG: case ISD::FABS: case ISD::FSQRT: case ISD::FSIN: - case ISD::FCOS: R = ScalarizeRes_UnaryOp(N); break; - case ISD::FPOWI: R = ScalarizeRes_FPOWI(N); break; + case ISD::FCOS: R = ScalarizeVecRes_UnaryOp(N); break; + + case ISD::FPOWI: R = ScalarizeVecRes_FPOWI(N); break; case ISD::BUILD_VECTOR: R = N->getOperand(0); break; - case ISD::INSERT_VECTOR_ELT: R = ScalarizeRes_INSERT_VECTOR_ELT(N); break; - case ISD::VECTOR_SHUFFLE: R = ScalarizeRes_VECTOR_SHUFFLE(N); break; - case ISD::BIT_CONVERT: R = ScalarizeRes_BIT_CONVERT(N); break; - case ISD::SELECT: R = ScalarizeRes_SELECT(N); break; + case ISD::INSERT_VECTOR_ELT: R = ScalarizeVecRes_INSERT_VECTOR_ELT(N); break; + case ISD::VECTOR_SHUFFLE: R = ScalarizeVecRes_VECTOR_SHUFFLE(N); break; + case ISD::BIT_CONVERT: R = ScalarizeVecRes_BIT_CONVERT(N); break; + case ISD::SELECT: R = ScalarizeVecRes_SELECT(N); break; } // If R is null, the sub-method took care of registering the result. @@ -92,11 +95,11 @@ SetScalarizedVector(SDOperand(N, ResNo), R); } -SDOperand DAGTypeLegalizer::ScalarizeRes_UNDEF(SDNode *N) { +SDOperand DAGTypeLegalizer::ScalarizeVecRes_UNDEF(SDNode *N) { return DAG.getNode(ISD::UNDEF, N->getValueType(0).getVectorElementType()); } -SDOperand DAGTypeLegalizer::ScalarizeRes_LOAD(LoadSDNode *N) { +SDOperand DAGTypeLegalizer::ScalarizeVecRes_LOAD(LoadSDNode *N) { // FIXME: Add support for indexed loads. SDOperand Result = DAG.getLoad(N->getValueType(0).getVectorElementType(), N->getChain(), N->getBasePtr(), @@ -109,23 +112,23 @@ return Result; } -SDOperand DAGTypeLegalizer::ScalarizeRes_BinOp(SDNode *N) { +SDOperand DAGTypeLegalizer::ScalarizeVecRes_BinOp(SDNode *N) { SDOperand LHS = GetScalarizedVector(N->getOperand(0)); SDOperand RHS = GetScalarizedVector(N->getOperand(1)); return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS); } -SDOperand DAGTypeLegalizer::ScalarizeRes_UnaryOp(SDNode *N) { +SDOperand DAGTypeLegalizer::ScalarizeVecRes_UnaryOp(SDNode *N) { SDOperand Op = GetScalarizedVector(N->getOperand(0)); return DAG.getNode(N->getOpcode(), Op.getValueType(), Op); } -SDOperand DAGTypeLegalizer::ScalarizeRes_FPOWI(SDNode *N) { +SDOperand DAGTypeLegalizer::ScalarizeVecRes_FPOWI(SDNode *N) { SDOperand Op = GetScalarizedVector(N->getOperand(0)); return DAG.getNode(ISD::FPOWI, Op.getValueType(), Op, N->getOperand(1)); } -SDOperand DAGTypeLegalizer::ScalarizeRes_INSERT_VECTOR_ELT(SDNode *N) { +SDOperand DAGTypeLegalizer::ScalarizeVecRes_INSERT_VECTOR_ELT(SDNode *N) { // The value to insert may have a wider type than the vector element type, // so be sure to truncate it to the element type if necessary. SDOperand Op = N->getOperand(1); @@ -136,19 +139,19 @@ return Op; } -SDOperand DAGTypeLegalizer::ScalarizeRes_VECTOR_SHUFFLE(SDNode *N) { +SDOperand DAGTypeLegalizer::ScalarizeVecRes_VECTOR_SHUFFLE(SDNode *N) { // Figure out if the scalar is the LHS or RHS and return it. SDOperand EltNum = N->getOperand(2).getOperand(0); unsigned Op = cast(EltNum)->getValue() != 0; return GetScalarizedVector(N->getOperand(Op)); } -SDOperand DAGTypeLegalizer::ScalarizeRes_BIT_CONVERT(SDNode *N) { +SDOperand DAGTypeLegalizer::ScalarizeVecRes_BIT_CONVERT(SDNode *N) { MVT NewVT = N->getValueType(0).getVectorElementType(); return DAG.getNode(ISD::BIT_CONVERT, NewVT, N->getOperand(0)); } -SDOperand DAGTypeLegalizer::ScalarizeRes_SELECT(SDNode *N) { +SDOperand DAGTypeLegalizer::ScalarizeVecRes_SELECT(SDNode *N) { SDOperand LHS = GetScalarizedVector(N->getOperand(1)); return DAG.getNode(ISD::SELECT, LHS.getValueType(), N->getOperand(0), LHS, GetScalarizedVector(N->getOperand(2))); @@ -182,13 +185,13 @@ abort(); case ISD::BIT_CONVERT: - Res = ScalarizeOp_BIT_CONVERT(N); break; + Res = ScalarizeVecOp_BIT_CONVERT(N); break; case ISD::EXTRACT_VECTOR_ELT: - Res = ScalarizeOp_EXTRACT_VECTOR_ELT(N); break; + Res = ScalarizeVecOp_EXTRACT_VECTOR_ELT(N); break; case ISD::STORE: - Res = ScalarizeOp_STORE(cast(N), OpNo); break; + Res = ScalarizeVecOp_STORE(cast(N), OpNo); break; } } @@ -212,23 +215,23 @@ return false; } -/// ScalarizeOp_BIT_CONVERT - If the value to convert is a vector that needs +/// ScalarizeVecOp_BIT_CONVERT - If the value to convert is a vector that needs /// to be scalarized, it must be <1 x ty>. Convert the element instead. -SDOperand DAGTypeLegalizer::ScalarizeOp_BIT_CONVERT(SDNode *N) { +SDOperand DAGTypeLegalizer::ScalarizeVecOp_BIT_CONVERT(SDNode *N) { SDOperand Elt = GetScalarizedVector(N->getOperand(0)); return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Elt); } -/// ScalarizeOp_EXTRACT_VECTOR_ELT - If the input is a vector that needs to be -/// scalarized, it must be <1 x ty>, so just return the element, ignoring the +/// ScalarizeVecOp_EXTRACT_VECTOR_ELT - If the input is a vector that needs to +/// be scalarized, it must be <1 x ty>, so just return the element, ignoring the /// index. -SDOperand DAGTypeLegalizer::ScalarizeOp_EXTRACT_VECTOR_ELT(SDNode *N) { +SDOperand DAGTypeLegalizer::ScalarizeVecOp_EXTRACT_VECTOR_ELT(SDNode *N) { return GetScalarizedVector(N->getOperand(0)); } -/// ScalarizeOp_STORE - If the value to store is a vector that needs to be +/// ScalarizeVecOp_STORE - If the value to store is a vector that needs to be /// scalarized, it must be <1 x ty>. Just store the element. -SDOperand DAGTypeLegalizer::ScalarizeOp_STORE(StoreSDNode *N, unsigned OpNo) { +SDOperand DAGTypeLegalizer::ScalarizeVecOp_STORE(StoreSDNode *N, unsigned OpNo){ // FIXME: Add support for indexed stores. assert(OpNo == 1 && "Do not know how to scalarize this operand!"); return DAG.getStore(N->getChain(), GetScalarizedVector(N->getOperand(1)), @@ -237,23 +240,6 @@ } -/// GetSplitDestVTs - Compute the VTs needed for the low/hi parts of a vector -/// type that needs to be split. This handles non-power of two vectors. -static void GetSplitDestVTs(MVT InVT, MVT &Lo, MVT &Hi) { - MVT NewEltVT = InVT.getVectorElementType(); - unsigned NumElements = InVT.getVectorNumElements(); - if ((NumElements & (NumElements-1)) == 0) { // Simple power of two vector. - NumElements >>= 1; - Lo = Hi = MVT::getVectorVT(NewEltVT, NumElements); - } else { // Non-power-of-two vectors. - unsigned NewNumElts_Lo = 1 << Log2_32(NumElements); - unsigned NewNumElts_Hi = NumElements - NewNumElts_Lo; - Lo = MVT::getVectorVT(NewEltVT, NewNumElts_Lo); - Hi = MVT::getVectorVT(NewEltVT, NewNumElts_Hi); - } -} - - //===----------------------------------------------------------------------===// // Result Vector Splitting //===----------------------------------------------------------------------===// @@ -290,14 +276,20 @@ assert(0 && "Do not know how to split the result of this operator!"); abort(); - case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break; - case ISD::LOAD: SplitRes_LOAD(cast(N), Lo, Hi); break; - case ISD::BUILD_PAIR: SplitRes_BUILD_PAIR(N, Lo, Hi); break; - case ISD::INSERT_VECTOR_ELT:SplitRes_INSERT_VECTOR_ELT(N, Lo, Hi); break; - case ISD::VECTOR_SHUFFLE: SplitRes_VECTOR_SHUFFLE(N, Lo, Hi); break; - case ISD::BUILD_VECTOR: SplitRes_BUILD_VECTOR(N, Lo, Hi); break; - case ISD::CONCAT_VECTORS: SplitRes_CONCAT_VECTORS(N, Lo, Hi); break; - case ISD::BIT_CONVERT: SplitRes_BIT_CONVERT(N, Lo, Hi); break; + case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, Lo, Hi); break; + case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break; + case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break; + case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break; + + case ISD::LOAD: + SplitVecRes_LOAD(cast(N), Lo, Hi); + break; + case ISD::BUILD_PAIR: SplitVecRes_BUILD_PAIR(N, Lo, Hi); break; + case ISD::INSERT_VECTOR_ELT:SplitVecRes_INSERT_VECTOR_ELT(N, Lo, Hi); break; + case ISD::VECTOR_SHUFFLE: SplitVecRes_VECTOR_SHUFFLE(N, Lo, Hi); break; + case ISD::BUILD_VECTOR: SplitVecRes_BUILD_VECTOR(N, Lo, Hi); break; + case ISD::CONCAT_VECTORS: SplitVecRes_CONCAT_VECTORS(N, Lo, Hi); break; + case ISD::BIT_CONVERT: SplitVecRes_BIT_CONVERT(N, Lo, Hi); break; case ISD::CTTZ: case ISD::CTLZ: case ISD::CTPOP: @@ -309,7 +301,7 @@ case ISD::FP_TO_SINT: case ISD::FP_TO_UINT: case ISD::SINT_TO_FP: - case ISD::UINT_TO_FP: SplitRes_UnOp(N, Lo, Hi); break; + case ISD::UINT_TO_FP: SplitVecRes_UnOp(N, Lo, Hi); break; case ISD::ADD: case ISD::SUB: case ISD::MUL: @@ -325,9 +317,8 @@ case ISD::XOR: case ISD::UREM: case ISD::SREM: - case ISD::FREM: SplitRes_BinOp(N, Lo, Hi); break; - case ISD::FPOWI: SplitRes_FPOWI(N, Lo, Hi); break; - case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break; + case ISD::FREM: SplitVecRes_BinOp(N, Lo, Hi); break; + case ISD::FPOWI: SplitVecRes_FPOWI(N, Lo, Hi); break; } // If Lo/Hi is null, the sub-method took care of registering results etc. @@ -335,16 +326,8 @@ SetSplitVector(SDOperand(N, ResNo), Lo, Hi); } -void DAGTypeLegalizer::SplitRes_UNDEF(SDNode *N, SDOperand &Lo, SDOperand &Hi) { - MVT LoVT, HiVT; - GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); - - Lo = DAG.getNode(ISD::UNDEF, LoVT); - Hi = DAG.getNode(ISD::UNDEF, HiVT); -} - -void DAGTypeLegalizer::SplitRes_LOAD(LoadSDNode *LD, - SDOperand &Lo, SDOperand &Hi) { +void DAGTypeLegalizer::SplitVecRes_LOAD(LoadSDNode *LD, SDOperand &Lo, + SDOperand &Hi) { // FIXME: Add support for indexed loads. MVT LoVT, HiVT; GetSplitDestVTs(LD->getValueType(0), LoVT, HiVT); @@ -374,14 +357,19 @@ ReplaceValueWith(SDOperand(LD, 1), TF); } -void DAGTypeLegalizer::SplitRes_BUILD_PAIR(SDNode *N, SDOperand &Lo, - SDOperand &Hi) { +void DAGTypeLegalizer::SplitVecRes_BUILD_PAIR(SDNode *N, SDOperand &Lo, + SDOperand &Hi) { +#ifndef NDEBUG + MVT LoVT, HiVT; + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + assert(LoVT == HiVT && "Non-power-of-two vectors not supported!"); +#endif Lo = N->getOperand(0); Hi = N->getOperand(1); } -void DAGTypeLegalizer::SplitRes_INSERT_VECTOR_ELT(SDNode *N, SDOperand &Lo, - SDOperand &Hi) { +void DAGTypeLegalizer::SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDOperand &Lo, + SDOperand &Hi) { SDOperand Vec = N->getOperand(0); SDOperand Elt = N->getOperand(1); SDOperand Idx = N->getOperand(2); @@ -412,11 +400,11 @@ SDOperand Load = DAG.getLoad(VecVT, Store, StackPtr, NULL, 0); // Split it. - SplitRes_LOAD(cast(Load.Val), Lo, Hi); + SplitVecRes_LOAD(cast(Load.Val), Lo, Hi); } -void DAGTypeLegalizer::SplitRes_VECTOR_SHUFFLE(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { +void DAGTypeLegalizer::SplitVecRes_VECTOR_SHUFFLE(SDNode *N, SDOperand &Lo, + SDOperand &Hi) { // Build the low part. SDOperand Mask = N->getOperand(2); SmallVector Ops; @@ -455,8 +443,8 @@ Hi = DAG.getNode(ISD::BUILD_VECTOR, HiVT, &Ops[0], Ops.size()); } -void DAGTypeLegalizer::SplitRes_BUILD_VECTOR(SDNode *N, SDOperand &Lo, - SDOperand &Hi) { +void DAGTypeLegalizer::SplitVecRes_BUILD_VECTOR(SDNode *N, SDOperand &Lo, + SDOperand &Hi) { MVT LoVT, HiVT; GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); unsigned LoNumElts = LoVT.getVectorNumElements(); @@ -467,8 +455,8 @@ Hi = DAG.getNode(ISD::BUILD_VECTOR, HiVT, &HiOps[0], HiOps.size()); } -void DAGTypeLegalizer::SplitRes_CONCAT_VECTORS(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { +void DAGTypeLegalizer::SplitVecRes_CONCAT_VECTORS(SDNode *N, SDOperand &Lo, + SDOperand &Hi) { // FIXME: Handle non-power-of-two vectors? unsigned NumSubvectors = N->getNumOperands() / 2; if (NumSubvectors == 1) { @@ -487,8 +475,8 @@ Hi = DAG.getNode(ISD::CONCAT_VECTORS, HiVT, &HiOps[0], HiOps.size()); } -void DAGTypeLegalizer::SplitRes_BIT_CONVERT(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { +void DAGTypeLegalizer::SplitVecRes_BIT_CONVERT(SDNode *N, SDOperand &Lo, + SDOperand &Hi) { // We know the result is a vector. The input may be either a vector or a // scalar value. MVT LoVT, HiVT; @@ -512,10 +500,7 @@ // If the vector is being split in two then we can just convert the // expanded pieces. if (LoVT == HiVT) { - if (InVT.isInteger()) - GetExpandedInteger(InOp, Lo, Hi); - else - GetExpandedFloat(InOp, Lo, Hi); + GetExpandedOp(InOp, Lo, Hi); if (TLI.isBigEndian()) std::swap(Lo, Hi); Lo = DAG.getNode(ISD::BIT_CONVERT, LoVT, Lo); @@ -546,7 +531,8 @@ Hi = DAG.getNode(ISD::BIT_CONVERT, HiVT, Hi); } -void DAGTypeLegalizer::SplitRes_BinOp(SDNode *N, SDOperand &Lo, SDOperand &Hi) { +void DAGTypeLegalizer::SplitVecRes_BinOp(SDNode *N, SDOperand &Lo, + SDOperand &Hi) { SDOperand LHSLo, LHSHi; GetSplitVector(N->getOperand(0), LHSLo, LHSHi); SDOperand RHSLo, RHSHi; @@ -556,7 +542,8 @@ Hi = DAG.getNode(N->getOpcode(), LHSHi.getValueType(), LHSHi, RHSHi); } -void DAGTypeLegalizer::SplitRes_UnOp(SDNode *N, SDOperand &Lo, SDOperand &Hi) { +void DAGTypeLegalizer::SplitVecRes_UnOp(SDNode *N, SDOperand &Lo, + SDOperand &Hi) { // Get the dest types. This doesn't always match input types, e.g. int_to_fp. MVT LoVT, HiVT; GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); @@ -566,24 +553,14 @@ Hi = DAG.getNode(N->getOpcode(), HiVT, Hi); } -void DAGTypeLegalizer::SplitRes_FPOWI(SDNode *N, SDOperand &Lo, SDOperand &Hi) { +void DAGTypeLegalizer::SplitVecRes_FPOWI(SDNode *N, SDOperand &Lo, + SDOperand &Hi) { GetSplitVector(N->getOperand(0), Lo, Hi); Lo = DAG.getNode(ISD::FPOWI, Lo.getValueType(), Lo, N->getOperand(1)); Hi = DAG.getNode(ISD::FPOWI, Lo.getValueType(), Hi, N->getOperand(1)); } -void DAGTypeLegalizer::SplitRes_SELECT(SDNode *N, SDOperand &Lo, SDOperand &Hi){ - SDOperand LL, LH, RL, RH; - GetSplitVector(N->getOperand(1), LL, LH); - GetSplitVector(N->getOperand(2), RL, RH); - - SDOperand Cond = N->getOperand(0); - Lo = DAG.getNode(ISD::SELECT, LL.getValueType(), Cond, LL, RL); - Hi = DAG.getNode(ISD::SELECT, LH.getValueType(), Cond, LH, RH); -} - - //===----------------------------------------------------------------------===// // Operand Vector Splitting //===----------------------------------------------------------------------===// @@ -611,14 +588,16 @@ #endif assert(0 && "Do not know how to split this operator's operand!"); abort(); - case ISD::STORE: Res = SplitOp_STORE(cast(N), OpNo); break; - case ISD::RET: Res = SplitOp_RET(N, OpNo); break; + case ISD::STORE: Res = SplitVecOp_STORE(cast(N), OpNo); break; + case ISD::RET: Res = SplitVecOp_RET(N, OpNo); break; - case ISD::BIT_CONVERT: Res = SplitOp_BIT_CONVERT(N); break; + case ISD::BIT_CONVERT: Res = SplitVecOp_BIT_CONVERT(N); break; - case ISD::EXTRACT_VECTOR_ELT: Res = SplitOp_EXTRACT_VECTOR_ELT(N); break; - case ISD::EXTRACT_SUBVECTOR: Res = SplitOp_EXTRACT_SUBVECTOR(N); break; - case ISD::VECTOR_SHUFFLE: Res = SplitOp_VECTOR_SHUFFLE(N, OpNo); break; + case ISD::EXTRACT_VECTOR_ELT: Res = SplitVecOp_EXTRACT_VECTOR_ELT(N); break; + case ISD::EXTRACT_SUBVECTOR: Res = SplitVecOp_EXTRACT_SUBVECTOR(N); break; + case ISD::VECTOR_SHUFFLE: + Res = SplitVecOp_VECTOR_SHUFFLE(N, OpNo); + break; } } @@ -642,7 +621,7 @@ return false; } -SDOperand DAGTypeLegalizer::SplitOp_STORE(StoreSDNode *N, unsigned OpNo) { +SDOperand DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) { // FIXME: Add support for indexed stores. assert(OpNo == 1 && "Can only split the stored value"); @@ -667,7 +646,7 @@ return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi); } -SDOperand DAGTypeLegalizer::SplitOp_RET(SDNode *N, unsigned OpNo) { +SDOperand DAGTypeLegalizer::SplitVecOp_RET(SDNode *N, unsigned OpNo) { assert(N->getNumOperands() == 3 &&"Can only handle ret of one vector so far"); // FIXME: Returns of gcc generic vectors larger than a legal vector // type should be returned by reference! @@ -680,7 +659,7 @@ return DAG.getNode(ISD::RET, MVT::Other, Chain, Lo, Sign, Hi, Sign); } -SDOperand DAGTypeLegalizer::SplitOp_BIT_CONVERT(SDNode *N) { +SDOperand DAGTypeLegalizer::SplitVecOp_BIT_CONVERT(SDNode *N) { // For example, i64 = BIT_CONVERT v4i16 on alpha. Typically the vector will // end up being split all the way down to individual components. Convert the // split pieces into integers and reassemble. @@ -696,7 +675,7 @@ JoinIntegers(Lo, Hi)); } -SDOperand DAGTypeLegalizer::SplitOp_EXTRACT_VECTOR_ELT(SDNode *N) { +SDOperand DAGTypeLegalizer::SplitVecOp_EXTRACT_VECTOR_ELT(SDNode *N) { SDOperand Vec = N->getOperand(0); SDOperand Idx = N->getOperand(1); MVT VecVT = Vec.getValueType(); @@ -728,7 +707,7 @@ return DAG.getLoad(EltVT, Store, StackPtr, NULL, 0); } -SDOperand DAGTypeLegalizer::SplitOp_EXTRACT_SUBVECTOR(SDNode *N) { +SDOperand DAGTypeLegalizer::SplitVecOp_EXTRACT_SUBVECTOR(SDNode *N) { // We know that the extracted result type is legal. For now, assume the index // is a constant. MVT SubVT = N->getValueType(0); @@ -749,7 +728,7 @@ } } -SDOperand DAGTypeLegalizer::SplitOp_VECTOR_SHUFFLE(SDNode *N, unsigned OpNo) { +SDOperand DAGTypeLegalizer::SplitVecOp_VECTOR_SHUFFLE(SDNode *N, unsigned OpNo){ assert(OpNo == 2 && "Shuffle source type differs from result type?"); SDOperand Mask = N->getOperand(2); unsigned MaskLength = Mask.getValueType().getVectorNumElements(); From baldrick at free.fr Fri Jun 20 13:47:21 2008 From: baldrick at free.fr (Duncan Sands) Date: Fri, 20 Jun 2008 20:47:21 +0200 Subject: [llvm-commits] [llvm] r52546 - in /llvm/trunk/lib/CodeGen/SelectionDAG: LegalizeFloatTypes.cpp LegalizeIntegerTypes.cpp LegalizeTypes.cpp LegalizeTypes.h LegalizeVectorTypes.cpp In-Reply-To: <200806201749.m5KHnt8N030894@zion.cs.uiuc.edu> References: <200806201749.m5KHnt8N030894@zion.cs.uiuc.edu> Message-ID: <200806202047.21933.baldrick@free.fr> > Rename the operation of turning a float type into an > integer of the same type. This should read: into an integer of the same size. Sorry about that, Duncan. From evan.cheng at apple.com Fri Jun 20 14:26:28 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Fri, 20 Jun 2008 12:26:28 -0700 Subject: [llvm-commits] atomics memoperands patch In-Reply-To: <2FBBC83F-5CEB-456E-8101-E64987C4BEF1@apple.com> References: <5EAD215D-D32D-4C78-8020-E17D5179A72A@apple.com> <2FBBC83F-5CEB-456E-8101-E64987C4BEF1@apple.com> Message-ID: <343994E7-B22F-4585-9424-4319A65924BE@apple.com> On Jun 20, 2008, at 9:30 AM, Mon P Wang wrote: > Hi Evan, > On Jun 20, 2008, at 12:11 AM, Evan Cheng wrote: > >> Thanks Mon Ping. Some comments: >> >> + N->getOpcode() == ISD::ATOMIC_LCS || >> + N->getOpcode() == ISD::ATOMIC_LAS || >> + N->getOpcode() == ISD::ATOMIC_SWAP || >> + N->getOpcode() == ISD::ATOMIC_LSS || >> + N->getOpcode() == ISD::ATOMIC_LOAD_AND || >> + N->getOpcode() == ISD::ATOMIC_LOAD_OR || >> + N->getOpcode() == ISD::ATOMIC_LOAD_XOR || >> >> Does it make sense to take this opportunity to rename lcs, las, and >> lss? >> > > I heard the same comment from Andrew and I think it makes sense. How > about the following > ATOMIC_LCS => ATOMIC_CMP_SWAP > ATOMIC_LAS => ATOMIC_LOAD_ADD > ATOMIC_LSS => ATOMIC_LOAD_SUB Yes! > > > This would make the names more consistent. > >> + //! PtrVal - Value of address that we are going to do an atomic >> update >> How about "Value of atomically updated address"? >> >> + const Value* PtrVal; >> >> Since this is basically the same as LSBaseSDNode SrcValue, how about >> move it to the common base class MemSDNode? > > You are right. We should move what is common up as much as possible. > >> + >> + //! Align - Alignment of memory location in bytes. >> + unsigned Align; >> >> Alignment instead of Align. >> > > Yep, shows me for getting lazy in typing :-> I am just looking for consistency. :-) > > >> + >> + //! IsVol - True if the store is volatile. >> + bool IsVol; >> >> IsVolatile instead of IsVol. But do we need these? Isn't it always >> volatile given it's an atomic operation? >> > > I think the standard definition is that all these operations are > volatile and acts like a memory barrier. The atomics should always > return true for this function for volatile. Right. So we don't need the field but the isVolatile() predicate should return true? > > >> Again, LSBaseSDNode has these fields as well. Perhaps move them up? >> >> + // Check if the atomic references a frame index >> + const FrameIndexSDNode *FI = >> + dyn_cast(getBasePtr().Val); >> + if (!getBasePtrValue() && FI) >> >> I am not quite sure why it's necessary to check getBasePtrValue()? >> > > My assumption when I read the code for LSBaseSDNode that if the > getBasePtrValue exist, we should use getBasePtrValue because it will > give more precise information for the location we are accessing (index > into a location in the FrameIndex). If this is not true, then it is > not necessary. Hrm. You are probably right. Evan > > >> >> + return MachineMemOperand(PseudoSourceValue::getFixedStack(), >> Flags, >> + FI->getIndex(), Size, getAlignment()); >> + else >> + return MachineMemOperand(getBasePtrValue(), Flags, 0, Size, >> getAlignment()); >> +} >> >> Also, don't forget to update AddNodeIDNode() and SDNode::dump() in >> SelectionDAG.cpp. > > > I totally forgot about that. Thanks for the reminder. > > > -- Mon Ping > >> Thanks, >> >> Evan >> >> On Jun 19, 2008, at 6:19 PM, Mon P Wang wrote: >> >>> Hi, >>> >>> Like loads/stores, atomics touches memory and should have an >>> associated MemOperand with the operation. The following patch >>> creates an abstract class MemSDNode that all nodes which have an >>> associated MemOperand need to inherit to. It also creates a new >>> property SDNPMemOperand that indicates that a node touches memory >>> and has an associated MemOperand.If you have any comments, please >>> let me know. >>> >>> Thanks, >>> -- Mon Ping >>> >>> _______________________________________________ >>> llvm-commits mailing list >>> llvm-commits at cs.uiuc.edu >>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits >> >> _______________________________________________ >> llvm-commits mailing list >> llvm-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From evan.cheng at apple.com Fri Jun 20 14:27:33 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Fri, 20 Jun 2008 12:27:33 -0700 Subject: [llvm-commits] atomics memoperands patch In-Reply-To: <855FB51F-F2D0-4E04-93E6-D3EBA8C74D52@apple.com> References: <5EAD215D-D32D-4C78-8020-E17D5179A72A@apple.com> <855FB51F-F2D0-4E04-93E6-D3EBA8C74D52@apple.com> Message-ID: On Jun 20, 2008, at 9:40 AM, Mon P Wang wrote: > > > > On Jun 20, 2008, at 12:28 AM, Evan Cheng wrote: > >> Questions for everyone. I've just noticed something in >> SelectionDAG.cpp: >> >> SDNode *SelectionDAG::FindModifiedNodeSlot(SDNode *N, >> SDOperandPtr Ops,unsigned >> NumOps, >> void *&InsertPos) { >> ... >> >> FoldingSetNodeID ID; >> AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops, NumOps); >> >> if (const LoadSDNode *LD = dyn_cast(N)) { >> ID.AddInteger(LD->getAddressingMode()); >> ID.AddInteger(LD->getExtensionType()); >> ID.AddInteger(LD->getMemoryVT().getRawBits()); >> ID.AddInteger(LD->getAlignment()); >> ID.AddInteger(LD->isVolatile()); >> } else if (const StoreSDNode *ST = dyn_cast(N)) { >> ID.AddInteger(ST->getAddressingMode()); >> ID.AddInteger(ST->isTruncatingStore()); >> ID.AddInteger(ST->getMemoryVT().getRawBits()); >> ID.AddInteger(ST->getAlignment()); >> ID.AddInteger(ST->isVolatile()); >> } >> >> Do we need the if () else if? AddNodeIDNode has already added those >> fields to the FoldingSetNodeId. >> > > Looking at the code, it does seem wrong to add the fields twice. I think so too. Chris? > > >> Also, do we want to cse nodes that are volatile? >> > > If the CSE can prove that no needed side effects are produced, it can > do so. In general though, I would shy away from doing so as it might > not be easy to prove that is the case. Right. Evan > > > -- Mon Ping > >> Evan >> > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From resistor at mac.com Fri Jun 20 15:05:17 2008 From: resistor at mac.com (Owen Anderson) Date: Fri, 20 Jun 2008 20:05:17 -0000 Subject: [llvm-commits] [llvm] r52549 - /llvm/trunk/tools/llvmc/ Message-ID: <200806202005.m5KK5H9B004620@zion.cs.uiuc.edu> Author: resistor Date: Fri Jun 20 15:05:17 2008 New Revision: 52549 URL: http://llvm.org/viewvc/llvm-project?rev=52549&view=rev Log: Remove empty directory. Removed: llvm/trunk/tools/llvmc/ From resistor at mac.com Fri Jun 20 15:05:57 2008 From: resistor at mac.com (Owen Anderson) Date: Fri, 20 Jun 2008 20:05:57 -0000 Subject: [llvm-commits] [llvm] r52550 - /llvm/trunk/LICENSE.TXT Message-ID: <200806202005.m5KK5w4N004674@zion.cs.uiuc.edu> Author: resistor Date: Fri Jun 20 15:05:57 2008 New Revision: 52550 URL: http://llvm.org/viewvc/llvm-project?rev=52550&view=rev Log: llvmc doesn't exist anymore, and llvmc2 doesn't have a special license file. Modified: llvm/trunk/LICENSE.TXT Modified: llvm/trunk/LICENSE.TXT URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/LICENSE.TXT?rev=52550&r1=52549&r2=52550&view=diff ============================================================================== --- llvm/trunk/LICENSE.TXT (original) +++ llvm/trunk/LICENSE.TXT Fri Jun 20 15:05:57 2008 @@ -62,7 +62,6 @@ Program Directory ------- --------- System Library llvm/lib/System -Compiler Driver llvm/tools/llvmc Autoconf llvm/autoconf llvm/projects/ModuleMaker/autoconf llvm/projects/sample/autoconf From clattner at apple.com Fri Jun 20 15:16:19 2008 From: clattner at apple.com (Chris Lattner) Date: Fri, 20 Jun 2008 13:16:19 -0700 Subject: [llvm-commits] atomics memoperands patch In-Reply-To: References: <5EAD215D-D32D-4C78-8020-E17D5179A72A@apple.com> <855FB51F-F2D0-4E04-93E6-D3EBA8C74D52@apple.com> Message-ID: >>> ID.AddInteger(LD->getAddressingMode()); >>> ID.AddInteger(LD->getExtensionType()); >>> ID.AddInteger(LD->getMemoryVT().getRawBits()); >>> ID.AddInteger(LD->getAlignment()); >>> ID.AddInteger(LD->isVolatile()); >>> } else if (const StoreSDNode *ST = dyn_cast(N)) { >>> ID.AddInteger(ST->getAddressingMode()); >>> ID.AddInteger(ST->isTruncatingStore()); >>> ID.AddInteger(ST->getMemoryVT().getRawBits()); >>> ID.AddInteger(ST->getAlignment()); >>> ID.AddInteger(ST->isVolatile()); >>> } >>> >>> Do we need the if () else if? AddNodeIDNode has already added those >>> fields to the FoldingSetNodeId. >>> >> >> Looking at the code, it does seem wrong to add the fields twice. > > I think so too. Chris? Yeah you're right, that is bogus. Please make sure that all the places that are dealing with loads/stores are putting the same number of values into the folding set though: if this is changed other places may need changes as well. Great catch, -Chris From monping at apple.com Fri Jun 20 15:27:59 2008 From: monping at apple.com (Mon P Wang) Date: Fri, 20 Jun 2008 13:27:59 -0700 Subject: [llvm-commits] atomics memoperands patch In-Reply-To: <343994E7-B22F-4585-9424-4319A65924BE@apple.com> References: <5EAD215D-D32D-4C78-8020-E17D5179A72A@apple.com> <2FBBC83F-5CEB-456E-8101-E64987C4BEF1@apple.com> <343994E7-B22F-4585-9424-4319A65924BE@apple.com> Message-ID: <43DE760D-5485-4CB8-A2EE-13DDBA45D1A7@apple.com> That right. The field will be removed and the function on the atomic will always return true. -- Mon Ping On Jun 20, 2008, at 12:26 PM, Evan Cheng wrote: > [Deleted Text] >> >>> + >>> + //! IsVol - True if the store is volatile. >>> + bool IsVol; >>> >>> IsVolatile instead of IsVol. But do we need these? Isn't it always >>> volatile given it's an atomic operation? >>> >> >> I think the standard definition is that all these operations are >> volatile and acts like a memory barrier. The atomics should always >> return true for this function for volatile. > > Right. So we don't need the field but the isVolatile() predicate > should return true? > >> >> >>> Again, LSBaseSDNode has these fields as well. Perhaps move them up? >>> >>> + // Check if the atomic references a frame index >>> + const FrameIndexSDNode *FI = >>> + dyn_cast(getBasePtr().Val); >>> + if (!getBasePtrValue() && FI) >>> >>> I am not quite sure why it's necessary to check getBasePtrValue()? >>> >> >> My assumption when I read the code for LSBaseSDNode that if the >> getBasePtrValue exist, we should use getBasePtrValue because it will >> give more precise information for the location we are accessing >> (index >> into a location in the FrameIndex). If this is not true, then it is >> not necessary. > > Hrm. You are probably right. > > Evan >> >> >>> >>> + return MachineMemOperand(PseudoSourceValue::getFixedStack(), >>> Flags, >>> + FI->getIndex(), Size, getAlignment()); >>> + else >>> + return MachineMemOperand(getBasePtrValue(), Flags, 0, Size, >>> getAlignment()); >>> +} >>> >>> Also, don't forget to update AddNodeIDNode() and SDNode::dump() in >>> SelectionDAG.cpp. >> >> >> I totally forgot about that. Thanks for the reminder. >> >> >> -- Mon Ping >> >>> Thanks, >>> >>> Evan >>> >>> On Jun 19, 2008, at 6:19 PM, Mon P Wang wrote: >>> >>>> Hi, >>>> >>>> Like loads/stores, atomics touches memory and should have an >>>> associated MemOperand with the operation. The following patch >>>> creates an abstract class MemSDNode that all nodes which have an >>>> associated MemOperand need to inherit to. It also creates a new >>>> property SDNPMemOperand that indicates that a node touches memory >>>> and has an associated MemOperand.If you have any comments, please >>>> let me know. >>>> >>>> Thanks, >>>> -- Mon Ping >>>> >>>> _______________________________________________ >>>> llvm-commits mailing list >>>> llvm-commits at cs.uiuc.edu >>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits >>> >>> _______________________________________________ >>> llvm-commits mailing list >>> llvm-commits at cs.uiuc.edu >>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits >> >> _______________________________________________ >> llvm-commits mailing list >> llvm-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From clattner at apple.com Fri Jun 20 15:42:15 2008 From: clattner at apple.com (Chris Lattner) Date: Fri, 20 Jun 2008 13:42:15 -0700 Subject: [llvm-commits] [llvm] r51668 - in /llvm/trunk: lib/Transforms/Scalar/ADCE.cpp test/Transforms/ADCE/2003-12-19-MergeReturn.ll test/Transforms/ADCE/dead-phi-edge.ll In-Reply-To: <200805290845.m4T8jDlo020433@zion.cs.uiuc.edu> References: <200805290845.m4T8jDlo020433@zion.cs.uiuc.edu> Message-ID: <3CDE774B-999C-4CBD-9C89-A42D3217F301@apple.com> On May 29, 2008, at 1:45 AM, Owen Anderson wrote: > Author: resistor > Date: Thu May 29 03:45:13 2008 > New Revision: 51668 > > URL: http://llvm.org/viewvc/llvm-project?rev=51668&view=rev > Log: > Replace the old ADCE implementation with a new one that more simply > solves > the one case that ADCE catches that normal DCE doesn't: non- > induction variable > loop computations. The new implementation is significantly simpler than the old one :). Some thoughts: It is reasonable to make these large in-place structures: SmallPtrSet alive; std::vector worklist; I'd suggest 1024 and a smallvector<1024> for the worklist. // The inverse of the live set is the dead set. These are those instructions // which have no side effects and do not influence the control flow or return // value of the function, and may therefore be deleted safely. SmallPtrSet dead; There is no need for this to be a set, just use a vector. Why not the worklist? :) Otherwise, looks great Owen, thanks! -chris From sabre at nondot.org Fri Jun 20 15:50:49 2008 From: sabre at nondot.org (Chris Lattner) Date: Fri, 20 Jun 2008 20:50:49 -0000 Subject: [llvm-commits] [llvm] r52551 - /llvm/trunk/docs/LangRef.html Message-ID: <200806202050.m5KKonoK006900@zion.cs.uiuc.edu> Author: lattner Date: Fri Jun 20 15:50:48 2008 New Revision: 52551 URL: http://llvm.org/viewvc/llvm-project?rev=52551&view=rev Log: integer types are not primitive, they are derived. Modified: llvm/trunk/docs/LangRef.html Modified: llvm/trunk/docs/LangRef.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.html?rev=52551&r1=52550&r2=52551&view=diff ============================================================================== --- llvm/trunk/docs/LangRef.html (original) +++ llvm/trunk/docs/LangRef.html Fri Jun 20 15:50:48 2008 @@ -1055,7 +1055,6 @@ primitive label, void, - integer, floating point. From evan.cheng at apple.com Fri Jun 20 16:45:17 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Fri, 20 Jun 2008 21:45:17 -0000 Subject: [llvm-commits] [llvm] r52554 - /llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp Message-ID: <200806202145.m5KLjHvq009300@zion.cs.uiuc.edu> Author: evancheng Date: Fri Jun 20 16:45:16 2008 New Revision: 52554 URL: http://llvm.org/viewvc/llvm-project?rev=52554&view=rev Log: Enhanced heuristic to determine the *best* register to spill. Instead of picking the register with the lowest spill weight. Consider (up to) 2 additional registers with spill weights that are close to the lowest spill weight. The one with fewest defs and uses that conflicts with the current interval (weighted by loop depth) is the spill candidate. This is not always a win, but there are much more wins than loses and wins tend to be more noticeable. Modified: llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp Modified: llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp?rev=52554&r1=52553&r2=52554&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp (original) +++ llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp Fri Jun 20 16:45:16 2008 @@ -43,6 +43,11 @@ STATISTIC(NumBacktracks, "Number of times we had to backtrack"); STATISTIC(NumCoalesce, "Number of copies coalesced"); +static cl::opt +NewHeuristic("new-spilling-heuristic", + cl::desc("Use new spilling heuristic"), + cl::init(false), cl::Hidden); + static RegisterRegAlloc linearscanRegAlloc("linearscan", " linear scan register allocator", createLinearScanRegisterAllocator); @@ -62,6 +67,7 @@ std::map OneClassForEachPhysReg; MachineFunction* mf_; + MachineRegisterInfo* mri_; const TargetMachine* tm_; const TargetRegisterInfo* tri_; const TargetInstrInfo* tii_; @@ -136,6 +142,15 @@ /// is available, or spill. void assignRegOrStackSlotAtInterval(LiveInterval* cur); + /// findIntervalsToSpill - Determine the intervals to spill for the + /// specified interval. It's passed the physical registers whose spill + /// weight is the lowest among all the registers whose live intervals + /// conflict with the interval. + void findIntervalsToSpill(LiveInterval *cur, + std::vector > &Candidates, + unsigned NumCands, + SmallVector &SpillIntervals); + /// attemptTrivialCoalescing - If a simple interval is defined by a copy, /// try allocate the definition the same register as the source register /// if the register is not defined during live time of the interval. This @@ -259,6 +274,7 @@ bool RALinScan::runOnMachineFunction(MachineFunction &fn) { mf_ = &fn; + mri_ = &fn.getRegInfo(); tm_ = &fn.getTarget(); tri_ = tm_->getRegisterInfo(); tii_ = tm_->getInstrInfo(); @@ -534,6 +550,107 @@ SI.MergeRangesInAsValue(RI, VNI); } +/// getConflictWeight - Return the number of conflicts between cur +/// live interval and defs and uses of Reg weighted by loop depthes. +static float getConflictWeight(LiveInterval *cur, unsigned Reg, + LiveIntervals *li_, + MachineRegisterInfo *mri_, + const MachineLoopInfo *loopInfo) { + float Conflicts = 0; + for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(Reg), + E = mri_->reg_end(); I != E; ++I) { + MachineInstr *MI = &*I; + if (cur->liveAt(li_->getInstructionIndex(MI))) { + unsigned loopDepth = loopInfo->getLoopDepth(MI->getParent()); + Conflicts += powf(10.0f, (float)loopDepth); + } + } + return Conflicts; +} + +/// findIntervalsToSpill - Determine the intervals to spill for the +/// specified interval. It's passed the physical registers whose spill +/// weight is the lowest among all the registers whose live intervals +/// conflict with the interval. +void RALinScan::findIntervalsToSpill(LiveInterval *cur, + std::vector > &Candidates, + unsigned NumCands, + SmallVector &SpillIntervals) { + // We have figured out the *best* register to spill. But there are other + // registers that are pretty good as well (spill weight within 3%). Spill + // the one that has fewest defs and uses that conflict with cur. + float Conflicts[3] = { 0.0f, 0.0f, 0.0f }; + SmallVector SLIs[3]; + + DOUT << "\tConsidering " << NumCands << " candidates: "; + DEBUG(for (unsigned i = 0; i != NumCands; ++i) + DOUT << tri_->getName(Candidates[i].first) << " "; + DOUT << "\n";); + + // Calculate the number of conflicts of each candidate. + for (IntervalPtrs::iterator i = active_.begin(); i != active_.end(); ++i) { + unsigned Reg = i->first->reg; + unsigned PhysReg = vrm_->getPhys(Reg); + if (!cur->overlapsFrom(*i->first, i->second)) + continue; + for (unsigned j = 0; j < NumCands; ++j) { + unsigned Candidate = Candidates[j].first; + if (tri_->regsOverlap(PhysReg, Candidate)) { + if (NumCands > 1) + Conflicts[j] += getConflictWeight(cur, Reg, li_, mri_, loopInfo); + SLIs[j].push_back(i->first); + } + } + } + + for (IntervalPtrs::iterator i = inactive_.begin(); i != inactive_.end(); ++i){ + unsigned Reg = i->first->reg; + unsigned PhysReg = vrm_->getPhys(Reg); + if (!cur->overlapsFrom(*i->first, i->second-1)) + continue; + for (unsigned j = 0; j < NumCands; ++j) { + unsigned Candidate = Candidates[j].first; + if (tri_->regsOverlap(PhysReg, Candidate)) { + if (NumCands > 1) + Conflicts[j] += getConflictWeight(cur, Reg, li_, mri_, loopInfo); + SLIs[j].push_back(i->first); + } + } + } + + // Which is the best candidate? + unsigned BestCandidate = 0; + float MinConflicts = Conflicts[0]; + for (unsigned i = 1; i != NumCands; ++i) { + if (Conflicts[i] < MinConflicts) { + BestCandidate = i; + MinConflicts = Conflicts[i]; + } + } + + std::copy(SLIs[BestCandidate].begin(), SLIs[BestCandidate].end(), + std::back_inserter(SpillIntervals)); +} + +namespace { + struct WeightCompare { + typedef std::pair RegWeightPair; + bool operator()(const RegWeightPair &LHS, const RegWeightPair &RHS) const { + return LHS.second < RHS.second; + } + }; +} + +static bool weightsAreClose(float w1, float w2) { + if (!NewHeuristic) + return false; + + float diff = w1 - w2; + if (diff <= 0.02f) // Within 0.02f + return true; + return (diff / w2) <= 0.05f; // Within 5%. +} + /// assignRegOrStackSlotAtInterval - assign a register if one is available, or /// spill. void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur) @@ -682,7 +799,7 @@ DOUT << "no free registers\n"; // Compile the spill weights into an array that is better for scanning. - std::vector SpillWeights(tri_->getNumRegs(), 0.0); + std::vector SpillWeights(tri_->getNumRegs(), 0.0f); for (std::vector >::iterator I = SpillWeightsToAdd.begin(), E = SpillWeightsToAdd.end(); I != E; ++I) updateSpillWeights(SpillWeights, I->first, I->second, tri_); @@ -701,44 +818,56 @@ // Find a register to spill. float minWeight = HUGE_VALF; - unsigned minReg = cur->preference; // Try the preferred register first. - + unsigned minReg = 0; /*cur->preference*/; // Try the preferred register first. + + bool Found = false; + std::vector > RegsWeights; if (!minReg || SpillWeights[minReg] == HUGE_VALF) for (TargetRegisterClass::iterator i = RC->allocation_order_begin(*mf_), e = RC->allocation_order_end(*mf_); i != e; ++i) { unsigned reg = *i; - if (minWeight > SpillWeights[reg]) { - minWeight = SpillWeights[reg]; - minReg = reg; - } + float regWeight = SpillWeights[reg]; + if (minWeight > regWeight) + Found = true; + RegsWeights.push_back(std::make_pair(reg, regWeight)); } // If we didn't find a register that is spillable, try aliases? - if (!minReg) { + if (!Found) { for (TargetRegisterClass::iterator i = RC->allocation_order_begin(*mf_), e = RC->allocation_order_end(*mf_); i != e; ++i) { unsigned reg = *i; // No need to worry about if the alias register size < regsize of RC. // We are going to spill all registers that alias it anyway. - for (const unsigned* as = tri_->getAliasSet(reg); *as; ++as) { - if (minWeight > SpillWeights[*as]) { - minWeight = SpillWeights[*as]; - minReg = *as; - } - } + for (const unsigned* as = tri_->getAliasSet(reg); *as; ++as) + RegsWeights.push_back(std::make_pair(*as, SpillWeights[*as])); } + } + // Sort all potential spill candidates by weight. + std::sort(RegsWeights.begin(), RegsWeights.end(), WeightCompare()); + minReg = RegsWeights[0].first; + minWeight = RegsWeights[0].second; + if (minWeight == HUGE_VALF) { // All registers must have inf weight. Just grab one! - if (!minReg) { - minReg = BestPhysReg ? BestPhysReg : *RC->allocation_order_begin(*mf_); - if (cur->weight == HUGE_VALF || cur->getSize() == 1) - // Spill a physical register around defs and uses. - li_->spillPhysRegAroundRegDefsUses(*cur, minReg, *vrm_); - } + minReg = BestPhysReg ? BestPhysReg : *RC->allocation_order_begin(*mf_); + if (cur->weight == HUGE_VALF || cur->getSize() == 1) + // Spill a physical register around defs and uses. + li_->spillPhysRegAroundRegDefsUses(*cur, minReg, *vrm_); + } + + // Find up to 3 registers to consider as spill candidates. + unsigned LastCandidate = RegsWeights.size() >= 3 ? 3 : 1; + while (LastCandidate > 1) { + if (weightsAreClose(RegsWeights[LastCandidate-1].second, minWeight)) + break; + --LastCandidate; } - - DOUT << "\t\tregister with min weight: " - << tri_->getName(minReg) << " (" << minWeight << ")\n"; + + DOUT << "\t\tregister(s) with min weight(s): "; + DEBUG(for (unsigned i = 0; i != LastCandidate; ++i) + DOUT << tri_->getName(RegsWeights[i].first) + << " (" << RegsWeights[i].second << ")\n"); // if the current has the minimum weight, we need to spill it and // add any added intervals back to unhandled, and restart @@ -767,60 +896,41 @@ // should go back right in the front of the list unhandled_.push(cur); - // otherwise we spill all intervals aliasing the register with - // minimum weight, rollback to the interval with the earliest - // start point and let the linear scan algorithm run again - std::vector added; assert(TargetRegisterInfo::isPhysicalRegister(minReg) && "did not choose a register to spill?"); - BitVector toSpill(tri_->getNumRegs()); - // We are going to spill minReg and all its aliases. - toSpill[minReg] = true; - for (const unsigned* as = tri_->getAliasSet(minReg); *as; ++as) - toSpill[*as] = true; + // We spill all intervals aliasing the register with + // minimum weight, rollback to the interval with the earliest + // start point and let the linear scan algorithm run again + SmallVector spillIs; + + // Determine which intervals have to be spilled. + findIntervalsToSpill(cur, RegsWeights, LastCandidate, spillIs); + + // Set of spilled vregs (used later to rollback properly) + SmallSet spilled; - // the earliest start of a spilled interval indicates up to where + // The earliest start of a Spilled interval indicates up to where // in handled we need to roll back unsigned earliestStart = cur->beginNumber(); - // set of spilled vregs (used later to rollback properly) - SmallSet spilled; - - // spill live intervals of virtual regs mapped to the physical register we + // Spill live intervals of virtual regs mapped to the physical register we // want to clear (and its aliases). We only spill those that overlap with the // current interval as the rest do not affect its allocation. we also keep // track of the earliest start of all spilled live intervals since this will // mark our rollback point. - for (IntervalPtrs::iterator i = active_.begin(); i != active_.end(); ++i) { - unsigned reg = i->first->reg; - if (//TargetRegisterInfo::isVirtualRegister(reg) && - toSpill[vrm_->getPhys(reg)] && - cur->overlapsFrom(*i->first, i->second)) { - DOUT << "\t\t\tspilling(a): " << *i->first << '\n'; - earliestStart = std::min(earliestStart, i->first->beginNumber()); - float SSWeight; - std::vector newIs = - li_->addIntervalsForSpills(*i->first, loopInfo, *vrm_, SSWeight); - addStackInterval(i->first, ls_, li_, SSWeight, *vrm_); - std::copy(newIs.begin(), newIs.end(), std::back_inserter(added)); - spilled.insert(reg); - } - } - for (IntervalPtrs::iterator i = inactive_.begin(); i != inactive_.end(); ++i){ - unsigned reg = i->first->reg; - if (//TargetRegisterInfo::isVirtualRegister(reg) && - toSpill[vrm_->getPhys(reg)] && - cur->overlapsFrom(*i->first, i->second-1)) { - DOUT << "\t\t\tspilling(i): " << *i->first << '\n'; - earliestStart = std::min(earliestStart, i->first->beginNumber()); - float SSWeight; - std::vector newIs = - li_->addIntervalsForSpills(*i->first, loopInfo, *vrm_, SSWeight); - addStackInterval(i->first, ls_, li_, SSWeight, *vrm_); - std::copy(newIs.begin(), newIs.end(), std::back_inserter(added)); - spilled.insert(reg); - } + std::vector added; + while (!spillIs.empty()) { + LiveInterval *sli = spillIs.back(); + spillIs.pop_back(); + DOUT << "\t\t\tspilling(a): " << *sli << '\n'; + earliestStart = std::min(earliestStart, sli->beginNumber()); + float SSWeight; + std::vector newIs = + li_->addIntervalsForSpills(*sli, loopInfo, *vrm_, SSWeight); + addStackInterval(sli, ls_, li_, SSWeight, *vrm_); + std::copy(newIs.begin(), newIs.end(), std::back_inserter(added)); + spilled.insert(sli->reg); } DOUT << "\t\trolling back to: " << earliestStart << '\n'; From kremenek at apple.com Fri Jun 20 16:46:51 2008 From: kremenek at apple.com (Ted Kremenek) Date: Fri, 20 Jun 2008 21:46:51 -0000 Subject: [llvm-commits] [llvm] r52557 - /llvm/tags/checker/checker-41/ Message-ID: <200806202146.m5KLkpSN009400@zion.cs.uiuc.edu> Author: kremenek Date: Fri Jun 20 16:46:50 2008 New Revision: 52557 URL: http://llvm.org/viewvc/llvm-project?rev=52557&view=rev Log: Tagging checker-41. Added: llvm/tags/checker/checker-41/ - copied from r52556, llvm/trunk/ From kremenek at apple.com Fri Jun 20 16:56:06 2008 From: kremenek at apple.com (Ted Kremenek) Date: Fri, 20 Jun 2008 21:56:06 -0000 Subject: [llvm-commits] [llvm] r52561 - /llvm/tags/checker/checker-42/ Message-ID: <200806202156.m5KLu6NO009882@zion.cs.uiuc.edu> Author: kremenek Date: Fri Jun 20 16:56:06 2008 New Revision: 52561 URL: http://llvm.org/viewvc/llvm-project?rev=52561&view=rev Log: Tagging checker-42. Added: llvm/tags/checker/checker-42/ - copied from r52560, llvm/trunk/ From kremenek at apple.com Fri Jun 20 17:19:13 2008 From: kremenek at apple.com (Ted Kremenek) Date: Fri, 20 Jun 2008 22:19:13 -0000 Subject: [llvm-commits] [llvm] r52564 - in /llvm/trunk/win32: CodeGen/CodeGen.vcproj common.vsprops Message-ID: <200806202219.m5KMJEJn011221@zion.cs.uiuc.edu> Author: kremenek Date: Fri Jun 20 17:19:12 2008 New Revision: 52564 URL: http://llvm.org/viewvc/llvm-project?rev=52564&view=rev Log: Updated VS build system. Patch provided by Cedric Venet: http://lists.cs.uiuc.edu/pipermail/llvmdev/2008-June/015446.html Added: llvm/trunk/win32/common.vsprops Modified: llvm/trunk/win32/CodeGen/CodeGen.vcproj Modified: llvm/trunk/win32/CodeGen/CodeGen.vcproj URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/win32/CodeGen/CodeGen.vcproj?rev=52564&r1=52563&r2=52564&view=diff ============================================================================== --- llvm/trunk/win32/CodeGen/CodeGen.vcproj (original) +++ llvm/trunk/win32/CodeGen/CodeGen.vcproj Fri Jun 20 17:19:12 2008 @@ -516,27 +516,23 @@ > - - + + + From kremenek at apple.com Fri Jun 20 18:14:07 2008 From: kremenek at apple.com (Ted Kremenek) Date: Fri, 20 Jun 2008 23:14:07 -0000 Subject: [llvm-commits] [llvm] r52566 - /llvm/tags/checker/checker-43/ Message-ID: <200806202314.m5KNE7Lc013254@zion.cs.uiuc.edu> Author: kremenek Date: Fri Jun 20 18:14:07 2008 New Revision: 52566 URL: http://llvm.org/viewvc/llvm-project?rev=52566&view=rev Log: Tagging checker-43. Added: llvm/tags/checker/checker-43/ - copied from r52565, llvm/trunk/ From evan.cheng at apple.com Fri Jun 20 19:24:15 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Fri, 20 Jun 2008 17:24:15 -0700 Subject: [llvm-commits] [llvm] r52532 - in /llvm/trunk: lib/Transforms/IPO/DeadArgumentElimination.cpp test/Transforms/DeadArgElim/multdeadretval.ll In-Reply-To: <200806200936.m5K9aIZR010499@zion.cs.uiuc.edu> References: <200806200936.m5K9aIZR010499@zion.cs.uiuc.edu> Message-ID: <0E696BD0-C25F-48E3-811D-E8C6745961AA@apple.com> Hi Matthijs, This breaks llvm-gcc bootstrapping. Looks like it miscompiles gcc driver: > /Volumes/SandBox/NightlyTest/llvm-gcc.obj/./gcc/xgcc -B/Volumes/ > SandBox/NightlyTest/llvm-gcc.obj/./gcc/ -B/Volumes/SandBox/ > NightlyTest/llvm-gcc.install/powerpc-apple-darwin9.2.2/bin/ -B/ > Volumes/SandBox/NightlyTest/llvm-gcc.install/powerpc-apple- > darwin9.2.2/lib/ -isystem /Volumes/SandBox/NightlyTest/llvm- > gcc.install/powerpc-apple-darwin9.2.2/include -isystem /Volumes/ > SandBox/NightlyTest/llvm-gcc.install/powerpc-apple-darwin9.2.2/sys- > include -O2 -g -O2 -DIN_GCC -W -Wall -Wwrite-strings -Wstrict- > prototypes -Wmissing-prototypes -Wold-style-definition -isystem ./ > include -I. -I. -I../../llvm-gcc.src/gcc -I../../llvm-gcc.src/gcc/. > -I../../llvm-gcc.src/gcc/../include -I./../intl -I../../llvm-gcc.src/ > gcc/../libcpp/include -I../../llvm-gcc.src/gcc/../libdecnumber -I../ > libdecnumber -I/Volumes/SandBox/NightlyTest/llvm.obj/include -I/ > Volumes/SandBox/NightlyTest/llvm.src/include -mlongcall \ > -c ../../llvm-gcc.src/gcc/config/darwin-crt2.c -o crt2.o > xgcc: error trying to exec 'cc1': execvp: No such file or directory > make[3]: *** [crt2.o] Error 1 > make[3]: *** Waiting for unfinished jobs.... > rm fsf-funding.pod gcov.pod gfdl.pod cpp.pod gpl.pod gcc.pod > make[2]: *** [all-stage2-gcc] Error 2 > make[1]: *** [stage2-bubble] Error 2 > make: *** [all] Error 2 I'll back it out for now. Please take a look. Thanks, Evan On Jun 20, 2008, at 2:36 AM, Matthijs Kooijman wrote: > Author: matthijs > Date: Fri Jun 20 04:36:16 2008 > New Revision: 52532 > > URL: http://llvm.org/viewvc/llvm-project?rev=52532&view=rev > Log: > Recommit r52459, rewriting of the dead argument elimination pass. > > This is a fixed version that no longer uses multimap::equal_range, > which > resulted in a pointer invalidation problem. > > Also, DAE::InspectedFunctions was not really necessary, so it got > removed. > > Lastly, this version no longer applies the extra arg hack on > functions who did > not have any arguments to start with. > > Added: > llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll > - copied unchanged from r52459, llvm/trunk/test/Transforms/ > DeadArgElim/multdeadretval.ll > Modified: > llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp > > Modified: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp?rev=52532&r1=52531&r2=52532&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp > (original) > +++ llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Fri > Jun 20 04:36:16 2008 > @@ -10,10 +10,10 @@ > // This pass deletes dead arguments from internal functions. Dead > argument > // elimination removes arguments which are directly dead, as well as > arguments > // only passed into function calls as dead arguments of other > functions. This > -// pass also deletes dead arguments in a similar way. > +// pass also deletes dead return values in a similar way. > // > // This pass is often useful as a cleanup pass to run after aggressive > -// interprocedural passes, which add possibly-dead arguments. > +// interprocedural passes, which add possibly-dead arguments or > return values. > // > // > = > = > = > ----------------------------------------------------------------------= > ==// > > @@ -42,40 +42,66 @@ > /// DAE - The dead argument elimination pass. > /// > class VISIBILITY_HIDDEN DAE : public ModulePass { > + public: > + > + /// Struct that represent either a (part of a) return value or > a function > + /// argument. Used so that arguments and return values can be > used > + /// interchangably. > + struct RetOrArg { > + RetOrArg(const Function* F, unsigned Idx, bool IsArg) : F(F), > Idx(Idx), IsArg(IsArg) {} > + const Function *F; > + unsigned Idx; > + bool IsArg; > + > + /// Make RetOrArg comparable, so we can put it into a map > + bool operator<(const RetOrArg &O) const { > + if (F != O.F) > + return F < O.F; > + else if (Idx != O.Idx) > + return Idx < O.Idx; > + else > + return IsArg < O.IsArg; > + } > + > + /// Make RetOrArg comparable, so we can easily iterate the > multimap > + bool operator==(const RetOrArg &O) const { > + return F == O.F && Idx == O.Idx && IsArg == O.IsArg; > + } > + }; > + > /// Liveness enum - During our initial pass over the program, we > determine > /// that things are either definately alive, definately dead, or > in need of > /// interprocedural analysis (MaybeLive). > /// > enum Liveness { Live, MaybeLive, Dead }; > > - /// LiveArguments, MaybeLiveArguments, DeadArguments - These > sets contain > - /// all of the arguments in the program. The Dead set contains > arguments > - /// which are completely dead (never used in the function). > The MaybeLive > - /// set contains arguments which are only passed into other > function calls, > - /// thus may be live and may be dead. The Live set contains > arguments which > - /// are known to be alive. > - /// > - std::set DeadArguments, MaybeLiveArguments, > LiveArguments; > - > - /// DeadRetVal, MaybeLiveRetVal, LifeRetVal - These sets > contain all of the > - /// functions in the program. The Dead set contains functions > whose return > - /// value is known to be dead. The MaybeLive set contains > functions whose > - /// return values are only used by return instructions, and the > Live set > - /// contains functions whose return values are used, functions > that are > - /// external, and functions that already return void. > - /// > - std::set DeadRetVal, MaybeLiveRetVal, LiveRetVal; > - > - /// InstructionsToInspect - As we mark arguments and return > values > - /// MaybeLive, we keep track of which instructions could make > the values > - /// live here. Once the entire program has had the return > value and > - /// arguments analyzed, this set is scanned to promote the > MaybeLive objects > - /// to be Live if they really are used. > - std::vector InstructionsToInspect; > - > - /// CallSites - Keep track of the call sites of functions that > have > - /// MaybeLive arguments or return values. > - std::multimap CallSites; > + /// Convenience wrapper > + RetOrArg CreateRet(const Function *F, unsigned Idx) { return > RetOrArg(F, Idx, false); } > + /// Convenience wrapper > + RetOrArg CreateArg(const Function *F, unsigned Idx) { return > RetOrArg(F, Idx, true); } > + > + typedef std::multimap UseMap; > + /// This map maps a return value or argument to all return > values or > + /// arguments it uses. > + /// For example (indices are left out for clarity): > + /// - Uses[ret F] = ret G > + /// This means that F calls G, and F returns the value > returned by G. > + /// - Uses[arg F] = ret G > + /// This means that some function calls G and passes its > result as an > + /// argument to F. > + /// - Uses[ret F] = arg F > + /// This means that F returns one of its own arguments. > + /// - Uses[arg F] = arg G > + /// This means that G calls F and passes one of its own > (G's) arguments > + /// directly to F. > + UseMap Uses; > + > + typedef std::set LiveSet; > + > + /// This set contains all values that have been determined to > be live > + LiveSet LiveValues; > + > + typedef SmallVector UseVector; > > public: > static char ID; // Pass identification, replacement for typeid > @@ -85,20 +111,19 @@ > virtual bool ShouldHackArguments() const { return false; } > > private: > - Liveness getArgumentLiveness(const Argument &A); > - bool isMaybeLiveArgumentNowLive(Argument *Arg); > - > + Liveness IsMaybeLive(RetOrArg Use, UseVector &MaybeLiveUses); > + Liveness SurveyUse(Value::use_iterator U, UseVector > &MaybeLiveUses, unsigned RetValNum = 0); > + Liveness SurveyUses(Value *V, UseVector &MaybeLiveUses); > + > + void SurveyFunction(Function &F); > + void MarkValue(const RetOrArg &RA, Liveness L, const UseVector > &MaybeLiveUses); > + void MarkLive(RetOrArg RA); > + bool RemoveDeadStuffFromFunction(Function *F); > bool DeleteDeadVarargs(Function &Fn); > - void SurveyFunction(Function &Fn); > - > - void MarkArgumentLive(Argument *Arg); > - void MarkRetValLive(Function *F); > - void MarkReturnInstArgumentLive(ReturnInst *RI); > - > - void RemoveDeadArgumentsFromFunction(Function *F); > }; > } > > + > char DAE::ID = 0; > static RegisterPass > X("deadargelim", "Dead Argument Elimination"); > @@ -155,7 +180,7 @@ > // remove the "..." and adjust all the calls. > > // Start by computing a new prototype for the function, which is > the same as > - // the old function, but has fewer arguments. > + // the old function, but doesn't have isVarArg set. > const FunctionType *FTy = Fn.getFunctionType(); > std::vector Params(FTy->param_begin(), FTy- > >param_end()); > FunctionType *NFTy = FunctionType::get(FTy->getReturnType(), > Params, false); > @@ -233,57 +258,110 @@ > return true; > } > > +/// Convenience function that returns the number of return values. > It returns 0 > +/// for void functions and 1 for functions not returning a struct. > It returns > +/// the number of struct elements for functions returning a struct. > +static unsigned NumRetVals(const Function *F) { > + if (F->getReturnType() == Type::VoidTy) > + return 0; > + else if (const StructType *STy = dyn_cast(F- > >getReturnType())) > + return STy->getNumElements(); > + else > + return 1; > +} > > -static inline bool CallPassesValueThoughVararg(Instruction *Call, > - const Value *Arg) { > - CallSite CS = CallSite::get(Call); > - const Type *CalledValueTy = CS.getCalledValue()->getType(); > - const Type *FTy = cast(CalledValueTy)- > >getElementType(); > - unsigned NumFixedArgs = cast(FTy)->getNumParams(); > - for (CallSite::arg_iterator AI = CS.arg_begin()+NumFixedArgs; > - AI != CS.arg_end(); ++AI) > - if (AI->get() == Arg) > - return true; > - return false; > -} > - > -// getArgumentLiveness - Inspect an argument, determining if is > known Live > -// (used in a computation), MaybeLive (only passed as an argument > to a call), or > -// Dead (not used). > -DAE::Liveness DAE::getArgumentLiveness(const Argument &A) { > - const Function *F = A.getParent(); > - > - // If this is the return value of a struct function, it's not > really dead. > - if (F->hasStructRetAttr() && &*(F->arg_begin()) == &A) > +/// IsMaybeAlive - This checks Use for liveness. If Use is live, > returns Live, > +/// else returns MaybeLive. Also, adds Use to MaybeLiveUses in the > latter case. > +DAE::Liveness DAE::IsMaybeLive(RetOrArg Use, UseVector > &MaybeLiveUses) { > + // We're live if our use is already marked as live > + if (LiveValues.count(Use)) > return Live; > - > - if (A.use_empty()) // First check, directly dead? > - return Dead; > > - // Scan through all of the uses, looking for non-argument passing > uses. > - for (Value::use_const_iterator I = A.use_begin(), E = > A.use_end(); I!=E;++I) { > - // Return instructions do not immediately effect liveness. > - if (isa(*I)) > - continue; > - > - CallSite CS = CallSite::get(const_cast(*I)); > - if (!CS.getInstruction()) { > - // If its used by something that is not a call or invoke, > it's alive! > - return Live; > - } > - // If it's an indirect call, mark it alive... > - Function *Callee = CS.getCalledFunction(); > - if (!Callee) return Live; > - > - // Check to see if it's passed through a va_arg area: if so, we > cannot > - // remove it. > - if (CallPassesValueThoughVararg(CS.getInstruction(), &A)) > - return Live; // If passed through va_arg area, we cannot > remove it > - } > + // We're maybe live otherwise, but remember that we must become > live if > + // Use becomes live. > + MaybeLiveUses.push_back(Use); > + return MaybeLive; > +} > + > + > +/// SurveyUse - This looks at a single use of an argument or return > value > +/// and determines if it should be alive or not. Adds this use to > MaybeLiveUses > +/// if it causes the used value to become MaybeAlive. > +/// > +/// RetValNum is the return value number to use when this use is > used in a > +/// return instruction. This is used in the recursion, you should > always leave > +/// it at 0. > +DAE::Liveness DAE::SurveyUse(Value::use_iterator U, UseVector > &MaybeLiveUses, unsigned RetValNum) { > + Value *V = *U; > + if (ReturnInst *RI = dyn_cast(V)) { > + // The value is returned from another function. It's only > live when the > + // caller's return value is live > + RetOrArg Use = CreateRet(RI->getParent()->getParent(), > RetValNum); > + // We might be live, depending on the liveness of Use > + return IsMaybeLive(Use, MaybeLiveUses); > + } > + if (InsertValueInst *IV = dyn_cast(V)) { > + if (U.getOperandNo() != > InsertValueInst::getAggregateOperandIndex() && IV->hasIndices()) > + // The use we are examining is inserted into an aggregate. > Our liveness > + // depends on all uses of that aggregate, but if it is used > as a return > + // value, only index at which we were inserted counts. > + RetValNum = *IV->idx_begin(); > > - return MaybeLive; // It must be used, but only as argument to a > function > + // Note that if we are used as the aggregate operand to the > insertvalue, > + // we don't change RetValNum, but do survey all our uses. > + > + Liveness Result = Dead; > + for (Value::use_iterator I = IV->use_begin(), > + E = V->use_end(); I != E; ++I) { > + Result = SurveyUse(I, MaybeLiveUses, RetValNum); > + if (Result == Live) > + break; > + } > + return Result; > + } > + CallSite CS = CallSite::get(V); > + if (CS.getInstruction()) { > + Function *F = CS.getCalledFunction(); > + if (F) { > + // Used in a direct call > + > + // Check for vararg. Do - 1 to skip the first operand to > call (the > + // function itself). > + if (U.getOperandNo() - 1 >= F->getFunctionType()- > >getNumParams()) > + // The value is passed in through a vararg! Must be live. > + return Live; > + > + // Value passed to a normal call. It's only live when the > corresponding > + // argument (operand number - 1 to skip the function > pointer operand) to > + // the called function turns out live > + RetOrArg Use = CreateArg(F, U.getOperandNo() - 1); > + return IsMaybeLive(Use, MaybeLiveUses); > + } else { > + // Used in any other way? Value must be live. > + return Live; > + } > + } > + // Used in any other way? Value must be live. > + return Live; > } > > +/// SurveyUses - This looks at all the uses of the given return value > +/// (possibly a partial return value from a function returning a > struct). > +/// Returns the Liveness deduced from the uses of this value. > +/// > +/// Adds all uses that cause the result to be MaybeLive to > MaybeLiveRetUses. > +DAE::Liveness DAE::SurveyUses(Value *V, UseVector &MaybeLiveUses) { > + // Assume it's dead (which will only hold if there are no uses at > all..) > + Liveness Result = Dead; > + // Check each use > + for (Value::use_iterator I = V->use_begin(), > + E = V->use_end(); I != E; ++I) { > + Result = SurveyUse(I, MaybeLiveUses); > + if (Result == Live) > + break; > + } > + return Result; > +} > > // SurveyFunction - This performs the initial survey of the > specified function, > // checking out whether or not it uses any of its incoming arguments > or whether > @@ -295,12 +373,36 @@ > // > void DAE::SurveyFunction(Function &F) { > bool FunctionIntrinsicallyLive = false; > - Liveness RetValLiveness = F.getReturnType() == Type::VoidTy ? > Live : Dead; > + unsigned RetCount = NumRetVals(&F); > + // Assume all return values are dead > + typedef SmallVector RetVals; > + RetVals RetValLiveness(RetCount, Dead); > + > + // These vectors maps each return value to the uses that make it > MaybeLive, so > + // we can add those to the MaybeLiveRetVals list if the return > value > + // really turns out to be MaybeLive. Initializes to RetCount > empty vectors > + typedef SmallVector RetUses; > + // Intialized to a list of RetCount empty lists > + RetUses MaybeLiveRetUses(RetCount); > + > + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) > + if (ReturnInst *RI = dyn_cast(BB->getTerminator())) > + if (RI->getNumOperands() != 0 && RI->getOperand(0)- > >getType() != F.getFunctionType()->getReturnType()) { > + // We don't support old style multiple return values > + FunctionIntrinsicallyLive = true; > + break; > + } > > - if (!F.hasInternalLinkage() && > - (!ShouldHackArguments() || F.isIntrinsic())) > + if (!F.hasInternalLinkage() && (!ShouldHackArguments() || > F.isIntrinsic())) > FunctionIntrinsicallyLive = true; > - else > + > + if (!FunctionIntrinsicallyLive) { > + DOUT << "DAE - Inspecting callers for fn: " << F.getName() << > "\n"; > + // Keep track of the number of live retvals, so we can skip > checks once all > + // of them turn out to be live. > + unsigned NumLiveRetVals = 0; > + const Type *STy = dyn_cast(F.getReturnType()); > + // Loop all uses of the function > for (Value::use_iterator I = F.use_begin(), E = F.use_end(); I ! > = E; ++I) { > // If the function is PASSED IN as an argument, its address > has been taken > if (I.getOperandNo() != 0) { > @@ -315,191 +417,141 @@ > FunctionIntrinsicallyLive = true; > break; > } > - > - // Check to see if the return value is used... > - if (RetValLiveness != Live) > - for (Value::use_iterator I = TheCall->use_begin(), > - E = TheCall->use_end(); I != E; ++I) > - if (isa(cast(*I))) { > - RetValLiveness = MaybeLive; > - } else if (isa(cast(*I)) || > - isa(cast(*I))) { > - if (CallPassesValueThoughVararg(cast(*I), > TheCall) || > - ! > CallSite::get(cast(*I)).getCalledFunction()) { > - RetValLiveness = Live; > - break; > + > + // If we end up here, we are looking at a direct call to our > function. > + > + // Now, check how our return value(s) is/are used in this > caller. Don't > + // bother checking return values if all of them are live > already > + if (NumLiveRetVals != RetCount) { > + if (STy) { > + // Check all uses of the return value > + for (Value::use_iterator I = TheCall->use_begin(), > + E = TheCall->use_end(); I != E; ++I) { > + ExtractValueInst *Ext = dyn_cast(*I); > + if (Ext && Ext->hasIndices()) { > + // This use uses a part of our return value, survey > the uses of that > + // part and store the results for this index only. > + unsigned Idx = *Ext->idx_begin(); > + if (RetValLiveness[Idx] != Live) { > + RetValLiveness[Idx] = SurveyUses(Ext, > MaybeLiveRetUses[Idx]); > + if (RetValLiveness[Idx] == Live) > + NumLiveRetVals++; > + } > } else { > - RetValLiveness = MaybeLive; > + // Used by something else than extractvalue. Mark all > + // return values as live. > + for (unsigned i = 0; i != RetCount; ++i ) > + RetValLiveness[i] = Live; > + NumLiveRetVals = RetCount; > + break; > } > - } else { > - RetValLiveness = Live; > - break; > } > + } else { > + // Single return value > + RetValLiveness[0] = SurveyUses(TheCall, > MaybeLiveRetUses[0]); > + if (RetValLiveness[0] == Live) > + NumLiveRetVals = RetCount; > + } > + } > } > - > + } > if (FunctionIntrinsicallyLive) { > - DOUT << " Intrinsically live fn: " << F.getName() << "\n"; > + DOUT << "DAE - Intrinsically live fn: " << F.getName() << "\n"; > + // Mark all arguments as live > + unsigned i = 0; > for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end(); > - AI != E; ++AI) > - LiveArguments.insert(AI); > - LiveRetVal.insert(&F); > + AI != E; ++AI, ++i) > + MarkLive(CreateArg(&F, i)); > + // Mark all return values as live > + i = 0; > + for (unsigned i = 0, e = RetValLiveness.size(); i != e; ++i) > + MarkLive(CreateRet(&F, i)); > return; > } > - > - switch (RetValLiveness) { > - case Live: LiveRetVal.insert(&F); break; > - case MaybeLive: MaybeLiveRetVal.insert(&F); break; > - case Dead: DeadRetVal.insert(&F); break; > + > + // Now we've inspected all callers, record the liveness of our > return values. > + for (unsigned i = 0, e = RetValLiveness.size(); i != e; ++i) { > + RetOrArg Ret = CreateRet(&F, i); > + // Mark the result down > + MarkValue(Ret, RetValLiveness[i], MaybeLiveRetUses[i]); > + } > + DOUT << "DAE - Inspecting args for fn: " << F.getName() << "\n"; > + > + // Now, check all of our arguments > + unsigned i = 0; > + UseVector MaybeLiveArgUses; > + for (Function::arg_iterator AI = F.arg_begin(), > + E = F.arg_end(); AI != E; ++AI, ++i) { > + // See what the effect of this use is (recording any uses that > cause > + // MaybeLive in MaybeLiveArgUses) > + Liveness Result = SurveyUses(AI, MaybeLiveArgUses); > + RetOrArg Arg = CreateArg(&F, i); > + // Mark the result down > + MarkValue(Arg, Result, MaybeLiveArgUses); > + // Clear the vector again for the next iteration > + MaybeLiveArgUses.clear(); > } > +} > > - DOUT << " Inspecting args for fn: " << F.getName() << "\n"; > - > - // If it is not intrinsically alive, we know that all users of the > - // function are call sites. Mark all of the arguments live which > are > - // directly used, and keep track of all of the call sites of this > function > - // if there are any arguments we assume that are dead. > - // > - bool AnyMaybeLiveArgs = false; > - for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end(); > - AI != E; ++AI) > - switch (getArgumentLiveness(*AI)) { > - case Live: > - DOUT << " Arg live by use: " << AI->getName() << "\n"; > - LiveArguments.insert(AI); > - break; > - case Dead: > - DOUT << " Arg definitely dead: " << AI->getName() <<"\n"; > - DeadArguments.insert(AI); > - break; > +/// MarkValue - This function marks the liveness of RA depending on > L. If L is > +/// MaybeLive, it also records any uses in MaybeLiveUses such that > RA will be > +/// marked live if any use in MaybeLiveUses gets marked live later > on. > +void DAE::MarkValue(const RetOrArg &RA, Liveness L, const UseVector > &MaybeLiveUses) { > + switch (L) { > + case Live: MarkLive(RA); break; > case MaybeLive: > - DOUT << " Arg only passed to calls: " << AI->getName() << > "\n"; > - AnyMaybeLiveArgs = true; > - MaybeLiveArguments.insert(AI); > + { > + // Note any uses of this value, so this return value can be > + // marked live whenever one of the uses becomes live. > + UseMap::iterator Where = Uses.begin(); > + for (UseVector::const_iterator UI = MaybeLiveUses.begin(), > + UE = MaybeLiveUses.end(); UI != UE; ++UI) > + Where = Uses.insert(Where, UseMap::value_type(*UI, RA)); > break; > } > - > - // If there are any "MaybeLive" arguments, we need to check > callees of > - // this function when/if they become alive. Record which > functions are > - // callees... > - if (AnyMaybeLiveArgs || RetValLiveness == MaybeLive) > - for (Value::use_iterator I = F.use_begin(), E = F.use_end(); > - I != E; ++I) { > - if (AnyMaybeLiveArgs) > - CallSites.insert(std::make_pair(&F, CallSite::get(*I))); > - > - if (RetValLiveness == MaybeLive) > - for (Value::use_iterator UI = I->use_begin(), E = I- > >use_end(); > - UI != E; ++UI) > - InstructionsToInspect.push_back(cast(*UI)); > - } > -} > - > -// isMaybeLiveArgumentNowLive - Check to see if Arg is alive. At > this point, we > -// know that the only uses of Arg are to be passed in as an > argument to a > -// function call or return. Check to see if the formal argument > passed in is in > -// the LiveArguments set. If so, return true. > -// > -bool DAE::isMaybeLiveArgumentNowLive(Argument *Arg) { > - for (Value::use_iterator I = Arg->use_begin(), E = Arg- > >use_end(); I!=E; ++I){ > - if (isa(*I)) { > - if (LiveRetVal.count(Arg->getParent())) return true; > - continue; > - } > - > - CallSite CS = CallSite::get(*I); > - > - // We know that this can only be used for direct calls... > - Function *Callee = CS.getCalledFunction(); > - > - // Loop over all of the arguments (because Arg may be passed > into the call > - // multiple times) and check to see if any are now alive... > - CallSite::arg_iterator CSAI = CS.arg_begin(); > - for (Function::arg_iterator AI = Callee->arg_begin(), E = > Callee->arg_end(); > - AI != E; ++AI, ++CSAI) > - // If this is the argument we are looking for, check to see > if it's alive > - if (*CSAI == Arg && LiveArguments.count(AI)) > - return true; > - } > - return false; > -} > - > -/// MarkArgumentLive - The MaybeLive argument 'Arg' is now known to > be alive. > -/// Mark it live in the specified sets and recursively mark > arguments in callers > -/// live that are needed to pass in a value. > -/// > -void DAE::MarkArgumentLive(Argument *Arg) { > - std::set::iterator It = > MaybeLiveArguments.lower_bound(Arg); > - if (It == MaybeLiveArguments.end() || *It != Arg) return; > - > - DOUT << " MaybeLive argument now live: " << Arg->getName() <<"\n"; > - MaybeLiveArguments.erase(It); > - LiveArguments.insert(Arg); > - > - // Loop over all of the call sites of the function, making any > arguments > - // passed in to provide a value for this argument live as > necessary. > - // > - Function *Fn = Arg->getParent(); > - unsigned ArgNo = std::distance(Fn->arg_begin(), > Function::arg_iterator(Arg)); > - > - std::multimap::iterator I = > CallSites.lower_bound(Fn); > - for (; I != CallSites.end() && I->first == Fn; ++I) { > - CallSite CS = I->second; > - Value *ArgVal = *(CS.arg_begin()+ArgNo); > - if (Argument *ActualArg = dyn_cast(ArgVal)) { > - MarkArgumentLive(ActualArg); > - } else { > - // If the value passed in at this call site is a return value > computed by > - // some other call site, make sure to mark the return value > at the other > - // call site as being needed. > - CallSite ArgCS = CallSite::get(ArgVal); > - if (ArgCS.getInstruction()) > - if (Function *Fn = ArgCS.getCalledFunction()) > - MarkRetValLive(Fn); > - } > + case Dead: break; > } > } > > -/// MarkArgumentLive - The MaybeLive return value for the specified > function is > -/// now known to be alive. Propagate this fact to the return > instructions which > -/// produce it. > -void DAE::MarkRetValLive(Function *F) { > - assert(F && "Shame shame, we can't have null pointers here!"); > - > - // Check to see if we already knew it was live > - std::set::iterator I = MaybeLiveRetVal.lower_bound(F); > - if (I == MaybeLiveRetVal.end() || *I != F) return; // It's > already alive! > - > - DOUT << " MaybeLive retval now live: " << F->getName() << "\n"; > - > - MaybeLiveRetVal.erase(I); > - LiveRetVal.insert(F); // It is now known to be live! > +/// MarkLive - Mark the given return value or argument as live. > Additionally, > +/// mark any values that are used by this value (according to Uses) > live as > +/// well. > +void DAE::MarkLive(RetOrArg RA) { > + if (!LiveValues.insert(RA).second) > + return; // We were already marked Live > > - // Loop over all of the functions, noticing that the return value > is now live. > - for (Function::iterator BB = F->begin(), E = F->end(); BB != E; + > +BB) > - if (ReturnInst *RI = dyn_cast(BB->getTerminator())) > - MarkReturnInstArgumentLive(RI); > -} > - > -void DAE::MarkReturnInstArgumentLive(ReturnInst *RI) { > - Value *Op = RI->getOperand(0); > - if (Argument *A = dyn_cast(Op)) { > - MarkArgumentLive(A); > - } else if (CallInst *CI = dyn_cast(Op)) { > - if (Function *F = CI->getCalledFunction()) > - MarkRetValLive(F); > - } else if (InvokeInst *II = dyn_cast(Op)) { > - if (Function *F = II->getCalledFunction()) > - MarkRetValLive(F); > - } > -} > + if (RA.IsArg) > + DOUT << "DAE - Marking argument " << RA.Idx << " to function " > << RA.F->getNameStart() << " live\n"; > + else > + DOUT << "DAE - Marking return value " << RA.Idx << " of > function " << RA.F->getNameStart() << " live\n"; > > -// RemoveDeadArgumentsFromFunction - We know that F has dead > arguments, as > + // We don't use upper_bound (or equal_range) here, because our > recursive call > + // to ourselves is likely to mark the upper_bound (which is the > first value > + // not belonging to RA) to become erased and the iterator > invalidated. > + UseMap::iterator Begin = Uses.lower_bound(RA); > + UseMap::iterator E = Uses.end(); > + UseMap::iterator I; > + for (I = Begin; I != E && I->first == RA; ++I) > + MarkLive(I->second); > + > + // Erase RA from the Uses map (from the lower bound to wherever > we ended up > + // after the loop). > + Uses.erase(Begin, I); > +} > + > +// RemoveDeadStuffFromFunction - Remove any arguments and return > values from F > +// that are not in LiveValues. This function is a noop for any > Function created > +// by this function before, or any function that was not inspected > for liveness. > // specified by the DeadArguments list. Transform the function and > all of the > // callees of the function to not have these arguments. > // > -void DAE::RemoveDeadArgumentsFromFunction(Function *F) { > +bool DAE::RemoveDeadStuffFromFunction(Function *F) { > + // Quick exit path for external functions > + if (!F->hasInternalLinkage() && (!ShouldHackArguments() || F- > >isIntrinsic())) > + return false; > + > // Start by computing a new prototype for the function, which is > the same as > - // the old function, but has fewer arguments. > + // the old function, but has fewer arguments and a different > return type. > const FunctionType *FTy = F->getFunctionType(); > std::vector Params; > > @@ -510,28 +562,78 @@ > // The existing function return attributes. > ParameterAttributes RAttrs = PAL.getParamAttrs(0); > > - // Make the function return void if the return value is dead. > + > + // Find out the new return value > + > const Type *RetTy = FTy->getReturnType(); > - if (DeadRetVal.count(F)) { > - RetTy = Type::VoidTy; > - RAttrs &= ~ParamAttr::typeIncompatible(RetTy); > - DeadRetVal.erase(F); > - } > - > + const Type *NRetTy; > + unsigned RetCount = NumRetVals(F); > + // -1 means unused, other numbers are the new index > + SmallVector NewRetIdxs(RetCount, -1); > + std::vector RetTypes; > + if (RetTy != Type::VoidTy) { > + const StructType *STy = dyn_cast(RetTy); > + if (STy) > + // Look at each of the original return values individually > + for (unsigned i = 0; i != RetCount; ++i) { > + RetOrArg Ret = CreateRet(F, i); > + if (LiveValues.erase(Ret)) { > + RetTypes.push_back(STy->getElementType(i)); > + NewRetIdxs[i] = RetTypes.size() - 1; > + } else { > + ++NumRetValsEliminated; > + DOUT << "DAE - Removing return value " << i << " from " << > F->getNameStart() << "\n"; > + } > + } > + else > + // We used to return a single value > + if (LiveValues.erase(CreateRet(F, 0))) { > + RetTypes.push_back(RetTy); > + NewRetIdxs[0] = 0; > + } else { > + DOUT << "DAE - Removing return value from " << F- > >getNameStart() << "\n"; > + ++NumRetValsEliminated; > + } > + if (RetTypes.size() == 0) > + // No return types? Make it void > + NRetTy = Type::VoidTy; > + else if (RetTypes.size() == 1) > + // One return type? Just a simple value then > + NRetTy = RetTypes.front(); > + else > + // More return types? Return a struct with them > + NRetTy = StructType::get(RetTypes); > + } else { > + NRetTy = Type::VoidTy; > + } > + > + // Remove any incompatible attributes > + RAttrs &= ~ParamAttr::typeIncompatible(NRetTy); > if (RAttrs) > ParamAttrsVec.push_back(ParamAttrsWithIndex::get(0, RAttrs)); > - > + > + // Remember which arguments are still alive > + SmallVector ArgAlive(FTy->getNumParams(), false); > // Construct the new parameter list from non-dead arguments. Also > construct > - // a new set of parameter attributes to correspond. > - unsigned index = 1; > - for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); > I != E; > - ++I, ++index) > - if (!DeadArguments.count(I)) { > + // a new set of parameter attributes to correspond. Skip the > first parameter > + // attribute, since that belongs to the return value. > + unsigned i = 0; > + for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); > + I != E; ++I, ++i) { > + RetOrArg Arg = CreateArg(F, i); > + if (LiveValues.erase(Arg)) { > Params.push_back(I->getType()); > + ArgAlive[i] = true; > > - if (ParameterAttributes Attrs = PAL.getParamAttrs(index)) > + // Get the original parameter attributes (skipping the first > one, that is > + // for the return value > + if (ParameterAttributes Attrs = PAL.getParamAttrs(i + 1)) > > ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Params.size(), > Attrs)); > + } else { > + ++NumArgumentsEliminated; > + DOUT << "DAE - Removing argument " << i << " (" << I- > >getNameStart() << ") from " << F->getNameStart() << "\n"; > } > + } > > // Reconstruct the ParamAttrsList based on the vector we > constructed. > PAListPtr NewPAL = PAListPtr::get(ParamAttrsVec.begin(), > ParamAttrsVec.end()); > @@ -539,19 +641,28 @@ > // Work around LLVM bug PR56: the CWriter cannot emit varargs > functions which > // have zero fixed arguments. > // > + // Not that we apply this hack for a vararg fuction that does not > have any > + // arguments anymore, but did have them before (so don't bother > fixing > + // functions that were already broken wrt CWriter). > bool ExtraArgHack = false; > - if (Params.empty() && FTy->isVarArg()) { > + if (Params.empty() && FTy->isVarArg() && FTy->getNumParams() != > 0) { > ExtraArgHack = true; > Params.push_back(Type::Int32Ty); > } > > // Create the new function type based on the recomputed parameters. > - FunctionType *NFTy = FunctionType::get(RetTy, Params, FTy- > >isVarArg()); > + FunctionType *NFTy = FunctionType::get(NRetTy, Params, FTy- > >isVarArg()); > + > + // No change? > + if (NFTy == FTy) > + return false; > > // Create the new function body and insert it into the module... > Function *NF = Function::Create(NFTy, F->getLinkage()); > NF->copyAttributesFrom(F); > NF->setParamAttrs(NewPAL); > + // Insert the new function before the old function, so we won't > be processing > + // it again > F->getParent()->getFunctionList().insert(F, NF); > NF->takeName(F); > > @@ -562,6 +673,11 @@ > while (!F->use_empty()) { > CallSite CS = CallSite::get(F->use_back()); > Instruction *Call = CS.getInstruction(); > + if (!Call) { > + DOUT << "Old: " << *FTy << "\n"; > + DOUT << "New: " << *NFTy << "\n"; > + } > + > ParamAttrsVec.clear(); > const PAListPtr &CallPAL = CS.getParamAttrs(); > > @@ -572,14 +688,17 @@ > if (RAttrs) > ParamAttrsVec.push_back(ParamAttrsWithIndex::get(0, RAttrs)); > > - // Loop over the operands, deleting dead ones... > - CallSite::arg_iterator AI = CS.arg_begin(); > - index = 1; > - for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); > - I != E; ++I, ++AI, ++index) > - if (!DeadArguments.count(I)) { // Remove operands for dead > arguments > - Args.push_back(*AI); > - if (ParameterAttributes Attrs = CallPAL.getParamAttrs(index)) > + // Declare these outside of the loops, so we can reuse them for > the second > + // loop, which loops the varargs > + CallSite::arg_iterator I = CS.arg_begin(); > + unsigned i = 0; > + // Loop over those operands, corresponding to the normal > arguments to the > + // original function, and add those that are still alive. > + for (unsigned e = FTy->getNumParams(); i != e; ++I, ++i) > + if (ArgAlive[i]) { > + Args.push_back(*I); > + // Get original parameter attributes, but skip return > attributes > + if (ParameterAttributes Attrs = CallPAL.getParamAttrs(i + 1)) > > ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Args.size(), Attrs)); > } > > @@ -587,9 +706,9 @@ > Args.push_back(UndefValue::get(Type::Int32Ty)); > > // Push any varargs arguments on the list. Don't forget their > attributes. > - for (; AI != CS.arg_end(); ++AI) { > - Args.push_back(*AI); > - if (ParameterAttributes Attrs = CallPAL.getParamAttrs(index++)) > + for (CallSite::arg_iterator E = CS.arg_end(); I != E; ++I, ++i) { > + Args.push_back(*I); > + if (ParameterAttributes Attrs = CallPAL.getParamAttrs(i + 1)) > > ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Args.size(), Attrs)); > } > > @@ -614,8 +733,45 @@ > > if (!Call->use_empty()) { > if (New->getType() == Type::VoidTy) > + // Our return value was unused, replace by null for now, > uses will get > + // removed later on > Call->replaceAllUsesWith(Constant::getNullValue(Call- > >getType())); > - else { > + else if (isa(RetTy)) { > + // The original return value was a struct, update all uses > (which are > + // all extractvalue instructions). > + for (Value::use_iterator I = Call->use_begin(), E = Call- > >use_end(); > + I != E;) { > + assert(isa(*I) && "Return value not > only used by extractvalue?"); > + ExtractValueInst *EV = cast(*I); > + // Increment now, since we're about to throw away this use. > + ++I; > + assert(EV->hasIndices() && "Return value used by > extractvalue without indices?"); > + unsigned Idx = *EV->idx_begin(); > + if (NewRetIdxs[Idx] != -1) { > + if (RetTypes.size() > 1) { > + // We're still returning a struct, create a new > extractvalue > + // instruction with the first index updated > + std::vector NewIdxs(EV->idx_begin(), EV- > >idx_end()); > + NewIdxs[0] = NewRetIdxs[Idx]; > + Value *NEV = ExtractValueInst::Create(New, > NewIdxs.begin(), NewIdxs.end(), "retval", EV); > + EV->replaceAllUsesWith(NEV); > + EV->eraseFromParent(); > + } else { > + // We are now only returning a simple value, remove the > + // extractvalue > + EV->replaceAllUsesWith(New); > + EV->eraseFromParent(); > + } > + } else { > + // Value unused, replace uses by null for now, they > will get removed > + // later on > + EV->replaceAllUsesWith(Constant::getNullValue(EV- > >getType())); > + EV->eraseFromParent(); > + } > + } > + New->takeName(Call); > + } else { > + // The original function had a single return value > Call->replaceAllUsesWith(New); > New->takeName(Call); > } > @@ -632,13 +788,11 @@ > NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList()); > > // Loop over the argument list, transfering uses of the old > arguments over to > - // the new arguments, also transfering over the names as well. > While we're at > - // it, remove the dead arguments from the DeadArguments list. > - // > + // the new arguments, also transfering over the names as well. > + i = 0; > for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(), > - I2 = NF->arg_begin(); > - I != E; ++I) > - if (!DeadArguments.count(I)) { > + I2 = NF->arg_begin(); I != E; ++I, ++i) > + if (ArgAlive[i]) { > // If this is a live argument, move the name and users over to > the new > // version. > I->replaceAllUsesWith(I2); > @@ -646,10 +800,8 @@ > ++I2; > } else { > // If this argument is dead, replace any uses of it with null > constants > - // (these are guaranteed to only be operands to call > instructions which > - // will later be simplified). > + // (these are guaranteed to become unused later on) > I->replaceAllUsesWith(Constant::getNullValue(I->getType())); > - DeadArguments.erase(I); > } > > // If we change the return value of the function we must rewrite > any return > @@ -657,12 +809,45 @@ > if (F->getReturnType() != NF->getReturnType()) > for (Function::iterator BB = NF->begin(), E = NF->end(); BB != > E; ++BB) > if (ReturnInst *RI = dyn_cast(BB- > >getTerminator())) { > - ReturnInst::Create(0, RI); > + Value *RetVal; > + > + if (NFTy->getReturnType() == Type::VoidTy) { > + RetVal = 0; > + } else { > + assert (isa(RetTy)); > + // The original return value was a struct, insert > + // extractvalue/insertvalue chains to extract only the > values we need > + // to return and insert them into our new result. > + // This does generate messy code, but we'll let it to > instcombine to > + // clean that up > + Value *OldRet = RI->getOperand(0); > + // Start out building up our return value from undef > + RetVal = llvm::UndefValue::get(NRetTy); > + for (unsigned i = 0; i != RetCount; ++i) > + if (NewRetIdxs[i] != -1) { > + ExtractValueInst *EV = > ExtractValueInst::Create(OldRet, i, "newret", RI); > + if (RetTypes.size() > 1) { > + // We're still returning a struct, so reinsert the > value into > + // our new return value at the new index > + > + RetVal = InsertValueInst::Create(RetVal, EV, > NewRetIdxs[i], "oldret"); > + } else { > + // We are now only returning a simple value, so > just return the > + // extracted value > + RetVal = EV; > + } > + } > + } > + // Replace the return instruction with one returning the > new return > + // value (possibly 0 if we became void). > + ReturnInst::Create(RetVal, RI); > BB->getInstList().erase(RI); > } > > // Now that the old function is dead, delete it. > F->eraseFromParent(); > + > + return true; > } > > bool DAE::runOnModule(Module &M) { > @@ -677,7 +862,7 @@ > if (F.getFunctionType()->isVarArg()) > Changed |= DeleteDeadVarargs(F); > } > - > + > // Second phase:loop through the module, determining which > arguments are live. > // We assume all arguments are dead unless proven otherwise > (allowing us to > // determine that dead arguments passed into recursive functions > are dead). > @@ -686,85 +871,14 @@ > for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) > SurveyFunction(*I); > > - // Loop over the instructions to inspect, propagating liveness > among arguments > - // and return values which are MaybeLive. > - while (!InstructionsToInspect.empty()) { > - Instruction *I = InstructionsToInspect.back(); > - InstructionsToInspect.pop_back(); > - > - if (ReturnInst *RI = dyn_cast(I)) { > - // For return instructions, we just have to check to see if > the return > - // value for the current function is known now to be alive. > If so, any > - // arguments used by it are now alive, and any call > instruction return > - // value is alive as well. > - if (LiveRetVal.count(RI->getParent()->getParent())) > - MarkReturnInstArgumentLive(RI); > - > - } else { > - CallSite CS = CallSite::get(I); > - assert(CS.getInstruction() && "Unknown instruction for the > I2I list!"); > - > - Function *Callee = CS.getCalledFunction(); > - > - // If we found a call or invoke instruction on this list, > that means that > - // an argument of the function is a call instruction. If the > argument is > - // live, then the return value of the called instruction is > now live. > - // > - CallSite::arg_iterator AI = CS.arg_begin(); // ActualIterator > - for (Function::arg_iterator FI = Callee->arg_begin(), > - E = Callee->arg_end(); FI != E; ++AI, ++FI) { > - // If this argument is another call... > - CallSite ArgCS = CallSite::get(*AI); > - if (ArgCS.getInstruction() && LiveArguments.count(FI)) > - if (Function *Callee = ArgCS.getCalledFunction()) > - MarkRetValLive(Callee); > - } > - } > + // Now, remove all dead arguments and return values from each > function in > + // turn > + for (Module::iterator I = M.begin(), E = M.end(); I != E; ) { > + // Increment now, because the function will probably get > removed (ie > + // replaced by a new one) > + Function *F = I++; > + Changed |= RemoveDeadStuffFromFunction(F); > } > > - // Now we loop over all of the MaybeLive arguments, promoting > them to be live > - // arguments if one of the calls that uses the arguments to the > calls they are > - // passed into requires them to be live. Of course this could > make other > - // arguments live, so process callers recursively. > - // > - // Because elements can be removed from the MaybeLiveArguments > set, copy it to > - // a temporary vector. > - // > - std::vector TmpArgList(MaybeLiveArguments.begin(), > - MaybeLiveArguments.end()); > - for (unsigned i = 0, e = TmpArgList.size(); i != e; ++i) { > - Argument *MLA = TmpArgList[i]; > - if (MaybeLiveArguments.count(MLA) && > - isMaybeLiveArgumentNowLive(MLA)) > - MarkArgumentLive(MLA); > - } > - > - // Recover memory early... > - CallSites.clear(); > - > - // At this point, we know that all arguments in DeadArguments and > - // MaybeLiveArguments are dead. If the two sets are empty, there > is nothing > - // to do. > - if (MaybeLiveArguments.empty() && DeadArguments.empty() && > - MaybeLiveRetVal.empty() && DeadRetVal.empty()) > - return Changed; > - > - // Otherwise, compact into one set, and start eliminating the > arguments from > - // the functions. > - DeadArguments.insert(MaybeLiveArguments.begin(), > MaybeLiveArguments.end()); > - MaybeLiveArguments.clear(); > - DeadRetVal.insert(MaybeLiveRetVal.begin(), MaybeLiveRetVal.end()); > - MaybeLiveRetVal.clear(); > - > - LiveArguments.clear(); > - LiveRetVal.clear(); > - > - NumArgumentsEliminated += DeadArguments.size(); > - NumRetValsEliminated += DeadRetVal.size(); > - while (!DeadArguments.empty()) > - RemoveDeadArgumentsFromFunction((*DeadArguments.begin())- > >getParent()); > - > - while (!DeadRetVal.empty()) > - RemoveDeadArgumentsFromFunction(*DeadRetVal.begin()); > - return true; > + return Changed; > } > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080620/3472e98a/attachment.html From evan.cheng at apple.com Fri Jun 20 19:31:44 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Sat, 21 Jun 2008 00:31:44 -0000 Subject: [llvm-commits] [llvm] r52570 - in /llvm/trunk: lib/Transforms/IPO/DeadArgumentElimination.cpp test/Transforms/DeadArgElim/multdeadretval.ll Message-ID: <200806210031.m5L0ViZS016180@zion.cs.uiuc.edu> Author: evancheng Date: Fri Jun 20 19:31:44 2008 New Revision: 52570 URL: http://llvm.org/viewvc/llvm-project?rev=52570&view=rev Log: Back out Matthijs' DAE patches. It's miscompiling gcc driver. Modified: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll Modified: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp?rev=52570&r1=52569&r2=52570&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp (original) +++ llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp Fri Jun 20 19:31:44 2008 @@ -10,10 +10,10 @@ // This pass deletes dead arguments from internal functions. Dead argument // elimination removes arguments which are directly dead, as well as arguments // only passed into function calls as dead arguments of other functions. This -// pass also deletes dead return values in a similar way. +// pass also deletes dead arguments in a similar way. // // This pass is often useful as a cleanup pass to run after aggressive -// interprocedural passes, which add possibly-dead arguments or return values. +// interprocedural passes, which add possibly-dead arguments. // //===----------------------------------------------------------------------===// @@ -42,71 +42,40 @@ /// DAE - The dead argument elimination pass. /// class VISIBILITY_HIDDEN DAE : public ModulePass { - public: - - /// Struct that represent either a (part of a) return value or a function - /// argument. Used so that arguments and return values can be used - /// interchangably. - struct RetOrArg { - RetOrArg(const Function* F, unsigned Idx, bool IsArg) : F(F), Idx(Idx), - IsArg(IsArg) {} - const Function *F; - unsigned Idx; - bool IsArg; - - /// Make RetOrArg comparable, so we can put it into a map - bool operator<(const RetOrArg &O) const { - if (F != O.F) - return F < O.F; - else if (Idx != O.Idx) - return Idx < O.Idx; - else - return IsArg < O.IsArg; - } - - /// Make RetOrArg comparable, so we can easily iterate the multimap - bool operator==(const RetOrArg &O) const { - return F == O.F && Idx == O.Idx && IsArg == O.IsArg; - } - }; - /// Liveness enum - During our initial pass over the program, we determine /// that things are either definately alive, definately dead, or in need of /// interprocedural analysis (MaybeLive). /// enum Liveness { Live, MaybeLive, Dead }; - /// Convenience wrapper - RetOrArg CreateRet(const Function *F, unsigned Idx) { - return RetOrArg(F, Idx, false); - } - /// Convenience wrapper - RetOrArg CreateArg(const Function *F, unsigned Idx) { - return RetOrArg(F, Idx, true); - } - - typedef std::multimap UseMap; - /// This map maps a return value or argument to all return values or - /// arguments it uses. - /// For example (indices are left out for clarity): - /// - Uses[ret F] = ret G - /// This means that F calls G, and F returns the value returned by G. - /// - Uses[arg F] = ret G - /// This means that some function calls G and passes its result as an - /// argument to F. - /// - Uses[ret F] = arg F - /// This means that F returns one of its own arguments. - /// - Uses[arg F] = arg G - /// This means that G calls F and passes one of its own (G's) arguments - /// directly to F. - UseMap Uses; - - typedef std::set LiveSet; + /// LiveArguments, MaybeLiveArguments, DeadArguments - These sets contain + /// all of the arguments in the program. The Dead set contains arguments + /// which are completely dead (never used in the function). The MaybeLive + /// set contains arguments which are only passed into other function calls, + /// thus may be live and may be dead. The Live set contains arguments which + /// are known to be alive. + /// + std::set DeadArguments, MaybeLiveArguments, LiveArguments; - /// This set contains all values that have been determined to be live - LiveSet LiveValues; + /// DeadRetVal, MaybeLiveRetVal, LifeRetVal - These sets contain all of the + /// functions in the program. The Dead set contains functions whose return + /// value is known to be dead. The MaybeLive set contains functions whose + /// return values are only used by return instructions, and the Live set + /// contains functions whose return values are used, functions that are + /// external, and functions that already return void. + /// + std::set DeadRetVal, MaybeLiveRetVal, LiveRetVal; - typedef SmallVector UseVector; + /// InstructionsToInspect - As we mark arguments and return values + /// MaybeLive, we keep track of which instructions could make the values + /// live here. Once the entire program has had the return value and + /// arguments analyzed, this set is scanned to promote the MaybeLive objects + /// to be Live if they really are used. + std::vector InstructionsToInspect; + + /// CallSites - Keep track of the call sites of functions that have + /// MaybeLive arguments or return values. + std::multimap CallSites; public: static char ID; // Pass identification, replacement for typeid @@ -116,21 +85,20 @@ virtual bool ShouldHackArguments() const { return false; } private: - Liveness IsMaybeLive(RetOrArg Use, UseVector &MaybeLiveUses); - Liveness SurveyUse(Value::use_iterator U, UseVector &MaybeLiveUses, - unsigned RetValNum = 0); - Liveness SurveyUses(Value *V, UseVector &MaybeLiveUses); - - void SurveyFunction(Function &F); - void MarkValue(const RetOrArg &RA, Liveness L, - const UseVector &MaybeLiveUses); - void MarkLive(RetOrArg RA); - bool RemoveDeadStuffFromFunction(Function *F); + Liveness getArgumentLiveness(const Argument &A); + bool isMaybeLiveArgumentNowLive(Argument *Arg); + bool DeleteDeadVarargs(Function &Fn); + void SurveyFunction(Function &Fn); + + void MarkArgumentLive(Argument *Arg); + void MarkRetValLive(Function *F); + void MarkReturnInstArgumentLive(ReturnInst *RI); + + void RemoveDeadArgumentsFromFunction(Function *F); }; } - char DAE::ID = 0; static RegisterPass X("deadargelim", "Dead Argument Elimination"); @@ -187,7 +155,7 @@ // remove the "..." and adjust all the calls. // Start by computing a new prototype for the function, which is the same as - // the old function, but doesn't have isVarArg set. + // the old function, but has fewer arguments. const FunctionType *FTy = Fn.getFunctionType(); std::vector Params(FTy->param_begin(), FTy->param_end()); FunctionType *NFTy = FunctionType::get(FTy->getReturnType(), Params, false); @@ -265,113 +233,58 @@ return true; } -/// Convenience function that returns the number of return values. It returns 0 -/// for void functions and 1 for functions not returning a struct. It returns -/// the number of struct elements for functions returning a struct. -static unsigned NumRetVals(const Function *F) { - if (F->getReturnType() == Type::VoidTy) - return 0; - else if (const StructType *STy = dyn_cast(F->getReturnType())) - return STy->getNumElements(); - else - return 1; -} -/// IsMaybeAlive - This checks Use for liveness. If Use is live, returns Live, -/// else returns MaybeLive. Also, adds Use to MaybeLiveUses in the latter case. -DAE::Liveness DAE::IsMaybeLive(RetOrArg Use, UseVector &MaybeLiveUses) { - // We're live if our use is already marked as live - if (LiveValues.count(Use)) +static inline bool CallPassesValueThoughVararg(Instruction *Call, + const Value *Arg) { + CallSite CS = CallSite::get(Call); + const Type *CalledValueTy = CS.getCalledValue()->getType(); + const Type *FTy = cast(CalledValueTy)->getElementType(); + unsigned NumFixedArgs = cast(FTy)->getNumParams(); + for (CallSite::arg_iterator AI = CS.arg_begin()+NumFixedArgs; + AI != CS.arg_end(); ++AI) + if (AI->get() == Arg) + return true; + return false; +} + +// getArgumentLiveness - Inspect an argument, determining if is known Live +// (used in a computation), MaybeLive (only passed as an argument to a call), or +// Dead (not used). +DAE::Liveness DAE::getArgumentLiveness(const Argument &A) { + const Function *F = A.getParent(); + + // If this is the return value of a struct function, it's not really dead. + if (F->hasStructRetAttr() && &*(F->arg_begin()) == &A) return Live; + + if (A.use_empty()) // First check, directly dead? + return Dead; + + // Scan through all of the uses, looking for non-argument passing uses. + for (Value::use_const_iterator I = A.use_begin(), E = A.use_end(); I!=E;++I) { + // Return instructions do not immediately effect liveness. + if (isa(*I)) + continue; + + CallSite CS = CallSite::get(const_cast(*I)); + if (!CS.getInstruction()) { + // If its used by something that is not a call or invoke, it's alive! + return Live; + } + // If it's an indirect call, mark it alive... + Function *Callee = CS.getCalledFunction(); + if (!Callee) return Live; + + // Check to see if it's passed through a va_arg area: if so, we cannot + // remove it. + if (CallPassesValueThoughVararg(CS.getInstruction(), &A)) + return Live; // If passed through va_arg area, we cannot remove it + } - // We're maybe live otherwise, but remember that we must become live if - // Use becomes live. - MaybeLiveUses.push_back(Use); - return MaybeLive; + return MaybeLive; // It must be used, but only as argument to a function } -/// SurveyUse - This looks at a single use of an argument or return value -/// and determines if it should be alive or not. Adds this use to MaybeLiveUses -/// if it causes the used value to become MaybeAlive. -/// -/// RetValNum is the return value number to use when this use is used in a -/// return instruction. This is used in the recursion, you should always leave -/// it at 0. -DAE::Liveness DAE::SurveyUse(Value::use_iterator U, UseVector &MaybeLiveUses, - unsigned RetValNum) { - Value *V = *U; - if (ReturnInst *RI = dyn_cast(V)) { - // The value is returned from another function. It's only live when the - // caller's return value is live - RetOrArg Use = CreateRet(RI->getParent()->getParent(), RetValNum); - // We might be live, depending on the liveness of Use - return IsMaybeLive(Use, MaybeLiveUses); - } - if (InsertValueInst *IV = dyn_cast(V)) { - if (U.getOperandNo() != InsertValueInst::getAggregateOperandIndex() - && IV->hasIndices()) - // The use we are examining is inserted into an aggregate. Our liveness - // depends on all uses of that aggregate, but if it is used as a return - // value, only index at which we were inserted counts. - RetValNum = *IV->idx_begin(); - - // Note that if we are used as the aggregate operand to the insertvalue, - // we don't change RetValNum, but do survey all our uses. - - Liveness Result = Dead; - for (Value::use_iterator I = IV->use_begin(), - E = V->use_end(); I != E; ++I) { - Result = SurveyUse(I, MaybeLiveUses, RetValNum); - if (Result == Live) - break; - } - return Result; - } - CallSite CS = CallSite::get(V); - if (CS.getInstruction()) { - Function *F = CS.getCalledFunction(); - if (F) { - // Used in a direct call - - // Check for vararg. Do - 1 to skip the first operand to call (the - // function itself). - if (U.getOperandNo() - 1 >= F->getFunctionType()->getNumParams()) - // The value is passed in through a vararg! Must be live. - return Live; - - // Value passed to a normal call. It's only live when the corresponding - // argument (operand number - 1 to skip the function pointer operand) to - // the called function turns out live - RetOrArg Use = CreateArg(F, U.getOperandNo() - 1); - return IsMaybeLive(Use, MaybeLiveUses); - } else { - // Used in any other way? Value must be live. - return Live; - } - } - // Used in any other way? Value must be live. - return Live; -} - -/// SurveyUses - This looks at all the uses of the given return value -/// (possibly a partial return value from a function returning a struct). -/// Returns the Liveness deduced from the uses of this value. -/// -/// Adds all uses that cause the result to be MaybeLive to MaybeLiveRetUses. -DAE::Liveness DAE::SurveyUses(Value *V, UseVector &MaybeLiveUses) { - // Assume it's dead (which will only hold if there are no uses at all..) - Liveness Result = Dead; - // Check each use - for (Value::use_iterator I = V->use_begin(), - E = V->use_end(); I != E; ++I) { - Result = SurveyUse(I, MaybeLiveUses); - if (Result == Live) - break; - } - return Result; -} - // SurveyFunction - This performs the initial survey of the specified function, // checking out whether or not it uses any of its incoming arguments or whether // any callers use the return value. This fills in the @@ -382,37 +295,12 @@ // void DAE::SurveyFunction(Function &F) { bool FunctionIntrinsicallyLive = false; - unsigned RetCount = NumRetVals(&F); - // Assume all return values are dead - typedef SmallVector RetVals; - RetVals RetValLiveness(RetCount, Dead); - - // These vectors maps each return value to the uses that make it MaybeLive, so - // we can add those to the MaybeLiveRetVals list if the return value - // really turns out to be MaybeLive. Initializes to RetCount empty vectors - typedef SmallVector RetUses; - // Intialized to a list of RetCount empty lists - RetUses MaybeLiveRetUses(RetCount); + Liveness RetValLiveness = F.getReturnType() == Type::VoidTy ? Live : Dead; - for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) - if (ReturnInst *RI = dyn_cast(BB->getTerminator())) - if (RI->getNumOperands() != 0 && RI->getOperand(0)->getType() - != F.getFunctionType()->getReturnType()) { - // We don't support old style multiple return values - FunctionIntrinsicallyLive = true; - break; - } - - if (!F.hasInternalLinkage() && (!ShouldHackArguments() || F.isIntrinsic())) + if (!F.hasInternalLinkage() && + (!ShouldHackArguments() || F.isIntrinsic())) FunctionIntrinsicallyLive = true; - - if (!FunctionIntrinsicallyLive) { - DOUT << "DAE - Inspecting callers for fn: " << F.getName() << "\n"; - // Keep track of the number of live retvals, so we can skip checks once all - // of them turn out to be live. - unsigned NumLiveRetVals = 0; - const Type *STy = dyn_cast(F.getReturnType()); - // Loop all uses of the function + else for (Value::use_iterator I = F.use_begin(), E = F.use_end(); I != E; ++I) { // If the function is PASSED IN as an argument, its address has been taken if (I.getOperandNo() != 0) { @@ -428,143 +316,190 @@ break; } - // If we end up here, we are looking at a direct call to our function. - - // Now, check how our return value(s) is/are used in this caller. Don't - // bother checking return values if all of them are live already - if (NumLiveRetVals != RetCount) { - if (STy) { - // Check all uses of the return value - for (Value::use_iterator I = TheCall->use_begin(), - E = TheCall->use_end(); I != E; ++I) { - ExtractValueInst *Ext = dyn_cast(*I); - if (Ext && Ext->hasIndices()) { - // This use uses a part of our return value, survey the uses of - // that part and store the results for this index only. - unsigned Idx = *Ext->idx_begin(); - if (RetValLiveness[Idx] != Live) { - RetValLiveness[Idx] = SurveyUses(Ext, MaybeLiveRetUses[Idx]); - if (RetValLiveness[Idx] == Live) - NumLiveRetVals++; - } - } else { - // Used by something else than extractvalue. Mark all - // return values as live. - for (unsigned i = 0; i != RetCount; ++i ) - RetValLiveness[i] = Live; - NumLiveRetVals = RetCount; + // Check to see if the return value is used... + if (RetValLiveness != Live) + for (Value::use_iterator I = TheCall->use_begin(), + E = TheCall->use_end(); I != E; ++I) + if (isa(cast(*I))) { + RetValLiveness = MaybeLive; + } else if (isa(cast(*I)) || + isa(cast(*I))) { + if (CallPassesValueThoughVararg(cast(*I), TheCall) || + !CallSite::get(cast(*I)).getCalledFunction()) { + RetValLiveness = Live; break; + } else { + RetValLiveness = MaybeLive; } + } else { + RetValLiveness = Live; + break; } - } else { - // Single return value - RetValLiveness[0] = SurveyUses(TheCall, MaybeLiveRetUses[0]); - if (RetValLiveness[0] == Live) - NumLiveRetVals = RetCount; - } - } } - } + if (FunctionIntrinsicallyLive) { - DOUT << "DAE - Intrinsically live fn: " << F.getName() << "\n"; - // Mark all arguments as live - unsigned i = 0; + DOUT << " Intrinsically live fn: " << F.getName() << "\n"; for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end(); - AI != E; ++AI, ++i) - MarkLive(CreateArg(&F, i)); - // Mark all return values as live - i = 0; - for (unsigned i = 0, e = RetValLiveness.size(); i != e; ++i) - MarkLive(CreateRet(&F, i)); + AI != E; ++AI) + LiveArguments.insert(AI); + LiveRetVal.insert(&F); return; } - // Now we've inspected all callers, record the liveness of our return values. - for (unsigned i = 0, e = RetValLiveness.size(); i != e; ++i) { - RetOrArg Ret = CreateRet(&F, i); - // Mark the result down - MarkValue(Ret, RetValLiveness[i], MaybeLiveRetUses[i]); - } - DOUT << "DAE - Inspecting args for fn: " << F.getName() << "\n"; - - // Now, check all of our arguments - unsigned i = 0; - UseVector MaybeLiveArgUses; - for (Function::arg_iterator AI = F.arg_begin(), - E = F.arg_end(); AI != E; ++AI, ++i) { - // See what the effect of this use is (recording any uses that cause - // MaybeLive in MaybeLiveArgUses) - Liveness Result = SurveyUses(AI, MaybeLiveArgUses); - RetOrArg Arg = CreateArg(&F, i); - // Mark the result down - MarkValue(Arg, Result, MaybeLiveArgUses); - // Clear the vector again for the next iteration - MaybeLiveArgUses.clear(); + switch (RetValLiveness) { + case Live: LiveRetVal.insert(&F); break; + case MaybeLive: MaybeLiveRetVal.insert(&F); break; + case Dead: DeadRetVal.insert(&F); break; } -} -/// MarkValue - This function marks the liveness of RA depending on L. If L is -/// MaybeLive, it also records any uses in MaybeLiveUses such that RA will be -/// marked live if any use in MaybeLiveUses gets marked live later on. -void DAE::MarkValue(const RetOrArg &RA, Liveness L, - const UseVector &MaybeLiveUses) { - switch (L) { - case Live: MarkLive(RA); break; + DOUT << " Inspecting args for fn: " << F.getName() << "\n"; + + // If it is not intrinsically alive, we know that all users of the + // function are call sites. Mark all of the arguments live which are + // directly used, and keep track of all of the call sites of this function + // if there are any arguments we assume that are dead. + // + bool AnyMaybeLiveArgs = false; + for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end(); + AI != E; ++AI) + switch (getArgumentLiveness(*AI)) { + case Live: + DOUT << " Arg live by use: " << AI->getName() << "\n"; + LiveArguments.insert(AI); + break; + case Dead: + DOUT << " Arg definitely dead: " << AI->getName() <<"\n"; + DeadArguments.insert(AI); + break; case MaybeLive: - { - // Note any uses of this value, so this return value can be - // marked live whenever one of the uses becomes live. - UseMap::iterator Where = Uses.begin(); - for (UseVector::const_iterator UI = MaybeLiveUses.begin(), - UE = MaybeLiveUses.end(); UI != UE; ++UI) - Where = Uses.insert(Where, UseMap::value_type(*UI, RA)); + DOUT << " Arg only passed to calls: " << AI->getName() << "\n"; + AnyMaybeLiveArgs = true; + MaybeLiveArguments.insert(AI); break; } - case Dead: break; + + // If there are any "MaybeLive" arguments, we need to check callees of + // this function when/if they become alive. Record which functions are + // callees... + if (AnyMaybeLiveArgs || RetValLiveness == MaybeLive) + for (Value::use_iterator I = F.use_begin(), E = F.use_end(); + I != E; ++I) { + if (AnyMaybeLiveArgs) + CallSites.insert(std::make_pair(&F, CallSite::get(*I))); + + if (RetValLiveness == MaybeLive) + for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); + UI != E; ++UI) + InstructionsToInspect.push_back(cast(*UI)); + } +} + +// isMaybeLiveArgumentNowLive - Check to see if Arg is alive. At this point, we +// know that the only uses of Arg are to be passed in as an argument to a +// function call or return. Check to see if the formal argument passed in is in +// the LiveArguments set. If so, return true. +// +bool DAE::isMaybeLiveArgumentNowLive(Argument *Arg) { + for (Value::use_iterator I = Arg->use_begin(), E = Arg->use_end(); I!=E; ++I){ + if (isa(*I)) { + if (LiveRetVal.count(Arg->getParent())) return true; + continue; + } + + CallSite CS = CallSite::get(*I); + + // We know that this can only be used for direct calls... + Function *Callee = CS.getCalledFunction(); + + // Loop over all of the arguments (because Arg may be passed into the call + // multiple times) and check to see if any are now alive... + CallSite::arg_iterator CSAI = CS.arg_begin(); + for (Function::arg_iterator AI = Callee->arg_begin(), E = Callee->arg_end(); + AI != E; ++AI, ++CSAI) + // If this is the argument we are looking for, check to see if it's alive + if (*CSAI == Arg && LiveArguments.count(AI)) + return true; + } + return false; +} + +/// MarkArgumentLive - The MaybeLive argument 'Arg' is now known to be alive. +/// Mark it live in the specified sets and recursively mark arguments in callers +/// live that are needed to pass in a value. +/// +void DAE::MarkArgumentLive(Argument *Arg) { + std::set::iterator It = MaybeLiveArguments.lower_bound(Arg); + if (It == MaybeLiveArguments.end() || *It != Arg) return; + + DOUT << " MaybeLive argument now live: " << Arg->getName() <<"\n"; + MaybeLiveArguments.erase(It); + LiveArguments.insert(Arg); + + // Loop over all of the call sites of the function, making any arguments + // passed in to provide a value for this argument live as necessary. + // + Function *Fn = Arg->getParent(); + unsigned ArgNo = std::distance(Fn->arg_begin(), Function::arg_iterator(Arg)); + + std::multimap::iterator I = CallSites.lower_bound(Fn); + for (; I != CallSites.end() && I->first == Fn; ++I) { + CallSite CS = I->second; + Value *ArgVal = *(CS.arg_begin()+ArgNo); + if (Argument *ActualArg = dyn_cast(ArgVal)) { + MarkArgumentLive(ActualArg); + } else { + // If the value passed in at this call site is a return value computed by + // some other call site, make sure to mark the return value at the other + // call site as being needed. + CallSite ArgCS = CallSite::get(ArgVal); + if (ArgCS.getInstruction()) + if (Function *Fn = ArgCS.getCalledFunction()) + MarkRetValLive(Fn); + } } } -/// MarkLive - Mark the given return value or argument as live. Additionally, -/// mark any values that are used by this value (according to Uses) live as -/// well. -void DAE::MarkLive(RetOrArg RA) { - if (!LiveValues.insert(RA).second) - return; // We were already marked Live +/// MarkArgumentLive - The MaybeLive return value for the specified function is +/// now known to be alive. Propagate this fact to the return instructions which +/// produce it. +void DAE::MarkRetValLive(Function *F) { + assert(F && "Shame shame, we can't have null pointers here!"); - if (RA.IsArg) - DOUT << "DAE - Marking argument " << RA.Idx << " to function " - << RA.F->getNameStart() << " live\n"; - else - DOUT << "DAE - Marking return value " << RA.Idx << " of function " - << RA.F->getNameStart() << " live\n"; + // Check to see if we already knew it was live + std::set::iterator I = MaybeLiveRetVal.lower_bound(F); + if (I == MaybeLiveRetVal.end() || *I != F) return; // It's already alive! + + DOUT << " MaybeLive retval now live: " << F->getName() << "\n"; + + MaybeLiveRetVal.erase(I); + LiveRetVal.insert(F); // It is now known to be live! + + // Loop over all of the functions, noticing that the return value is now live. + for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) + if (ReturnInst *RI = dyn_cast(BB->getTerminator())) + MarkReturnInstArgumentLive(RI); +} - // We don't use upper_bound (or equal_range) here, because our recursive call - // to ourselves is likely to mark the upper_bound (which is the first value - // not belonging to RA) to become erased and the iterator invalidated. - UseMap::iterator Begin = Uses.lower_bound(RA); - UseMap::iterator E = Uses.end(); - UseMap::iterator I; - for (I = Begin; I != E && I->first == RA; ++I) - MarkLive(I->second); - - // Erase RA from the Uses map (from the lower bound to wherever we ended up - // after the loop). - Uses.erase(Begin, I); -} - -// RemoveDeadStuffFromFunction - Remove any arguments and return values from F -// that are not in LiveValues. This function is a noop for any Function created -// by this function before, or any function that was not inspected for liveness. +void DAE::MarkReturnInstArgumentLive(ReturnInst *RI) { + Value *Op = RI->getOperand(0); + if (Argument *A = dyn_cast(Op)) { + MarkArgumentLive(A); + } else if (CallInst *CI = dyn_cast(Op)) { + if (Function *F = CI->getCalledFunction()) + MarkRetValLive(F); + } else if (InvokeInst *II = dyn_cast(Op)) { + if (Function *F = II->getCalledFunction()) + MarkRetValLive(F); + } +} + +// RemoveDeadArgumentsFromFunction - We know that F has dead arguments, as // specified by the DeadArguments list. Transform the function and all of the // callees of the function to not have these arguments. // -bool DAE::RemoveDeadStuffFromFunction(Function *F) { - // Quick exit path for external functions - if (!F->hasInternalLinkage() && (!ShouldHackArguments() || F->isIntrinsic())) - return false; - +void DAE::RemoveDeadArgumentsFromFunction(Function *F) { // Start by computing a new prototype for the function, which is the same as - // the old function, but has fewer arguments and a different return type. + // the old function, but has fewer arguments. const FunctionType *FTy = F->getFunctionType(); std::vector Params; @@ -575,92 +510,28 @@ // The existing function return attributes. ParameterAttributes RAttrs = PAL.getParamAttrs(0); - - // Find out the new return value - + // Make the function return void if the return value is dead. const Type *RetTy = FTy->getReturnType(); - const Type *NRetTy; - unsigned RetCount = NumRetVals(F); - // Explicitely track if anything changed, for debugging - bool Changed = false; - // -1 means unused, other numbers are the new index - SmallVector NewRetIdxs(RetCount, -1); - std::vector RetTypes; - if (RetTy != Type::VoidTy) { - const StructType *STy = dyn_cast(RetTy); - if (STy) - // Look at each of the original return values individually - for (unsigned i = 0; i != RetCount; ++i) { - RetOrArg Ret = CreateRet(F, i); - if (LiveValues.erase(Ret)) { - RetTypes.push_back(STy->getElementType(i)); - NewRetIdxs[i] = RetTypes.size() - 1; - } else { - ++NumRetValsEliminated; - DOUT << "DAE - Removing return value " << i << " from " - << F->getNameStart() << "\n"; - Changed = true; - } - } - else - // We used to return a single value - if (LiveValues.erase(CreateRet(F, 0))) { - RetTypes.push_back(RetTy); - NewRetIdxs[0] = 0; - } else { - DOUT << "DAE - Removing return value from " << F->getNameStart() - << "\n"; - ++NumRetValsEliminated; - Changed = true; - } - if (RetTypes.size() > 1 || STy && STy->getNumElements() == RetTypes.size()) - // More than one return type? Return a struct with them. Also, if we used - // to return a struct and didn't change the number of return values, - // return a struct again. This prevents chaning {something} into something - // and {} into void. - // Make the new struct packed if we used to return a packed struct - // already. - NRetTy = StructType::get(RetTypes, STy->isPacked()); - else if (RetTypes.size() == 1) - // One return type? Just a simple value then, but only if we didn't use to - // return a struct with that simple value before. - NRetTy = RetTypes.front(); - else if (RetTypes.size() == 0) - // No return types? Make it void, but only if we didn't use to return {} - NRetTy = Type::VoidTy; - } else { - NRetTy = Type::VoidTy; + if (DeadRetVal.count(F)) { + RetTy = Type::VoidTy; + RAttrs &= ~ParamAttr::typeIncompatible(RetTy); + DeadRetVal.erase(F); } - // Remove any incompatible attributes - RAttrs &= ~ParamAttr::typeIncompatible(NRetTy); if (RAttrs) ParamAttrsVec.push_back(ParamAttrsWithIndex::get(0, RAttrs)); - // Remember which arguments are still alive - SmallVector ArgAlive(FTy->getNumParams(), false); // Construct the new parameter list from non-dead arguments. Also construct - // a new set of parameter attributes to correspond. Skip the first parameter - // attribute, since that belongs to the return value. - unsigned i = 0; - for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); - I != E; ++I, ++i) { - RetOrArg Arg = CreateArg(F, i); - if (LiveValues.erase(Arg)) { + // a new set of parameter attributes to correspond. + unsigned index = 1; + for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; + ++I, ++index) + if (!DeadArguments.count(I)) { Params.push_back(I->getType()); - ArgAlive[i] = true; - - // Get the original parameter attributes (skipping the first one, that is - // for the return value - if (ParameterAttributes Attrs = PAL.getParamAttrs(i + 1)) + + if (ParameterAttributes Attrs = PAL.getParamAttrs(index)) ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Params.size(), Attrs)); - } else { - ++NumArgumentsEliminated; - DOUT << "DAE - Removing argument " << i << " (" << I->getNameStart() - << ") from " << F->getNameStart() << "\n"; - Changed = true; } - } // Reconstruct the ParamAttrsList based on the vector we constructed. PAListPtr NewPAL = PAListPtr::get(ParamAttrsVec.begin(), ParamAttrsVec.end()); @@ -668,33 +539,19 @@ // Work around LLVM bug PR56: the CWriter cannot emit varargs functions which // have zero fixed arguments. // - // Not that we apply this hack for a vararg fuction that does not have any - // arguments anymore, but did have them before (so don't bother fixing - // functions that were already broken wrt CWriter). bool ExtraArgHack = false; - if (Params.empty() && FTy->isVarArg() && FTy->getNumParams() != 0) { + if (Params.empty() && FTy->isVarArg()) { ExtraArgHack = true; Params.push_back(Type::Int32Ty); } // Create the new function type based on the recomputed parameters. - FunctionType *NFTy = FunctionType::get(NRetTy, Params, FTy->isVarArg()); - - // No change? - if (NFTy == FTy) - return false; - - // The function type is only allowed to be different if we actually left out - // an argument or return value - assert(Changed && "Function type changed while no arguments or retrurn values" - "were removed!"); + FunctionType *NFTy = FunctionType::get(RetTy, Params, FTy->isVarArg()); // Create the new function body and insert it into the module... Function *NF = Function::Create(NFTy, F->getLinkage()); NF->copyAttributesFrom(F); NF->setParamAttrs(NewPAL); - // Insert the new function before the old function, so we won't be processing - // it again F->getParent()->getFunctionList().insert(F, NF); NF->takeName(F); @@ -705,7 +562,6 @@ while (!F->use_empty()) { CallSite CS = CallSite::get(F->use_back()); Instruction *Call = CS.getInstruction(); - ParamAttrsVec.clear(); const PAListPtr &CallPAL = CS.getParamAttrs(); @@ -716,17 +572,14 @@ if (RAttrs) ParamAttrsVec.push_back(ParamAttrsWithIndex::get(0, RAttrs)); - // Declare these outside of the loops, so we can reuse them for the second - // loop, which loops the varargs - CallSite::arg_iterator I = CS.arg_begin(); - unsigned i = 0; - // Loop over those operands, corresponding to the normal arguments to the - // original function, and add those that are still alive. - for (unsigned e = FTy->getNumParams(); i != e; ++I, ++i) - if (ArgAlive[i]) { - Args.push_back(*I); - // Get original parameter attributes, but skip return attributes - if (ParameterAttributes Attrs = CallPAL.getParamAttrs(i + 1)) + // Loop over the operands, deleting dead ones... + CallSite::arg_iterator AI = CS.arg_begin(); + index = 1; + for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); + I != E; ++I, ++AI, ++index) + if (!DeadArguments.count(I)) { // Remove operands for dead arguments + Args.push_back(*AI); + if (ParameterAttributes Attrs = CallPAL.getParamAttrs(index)) ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Args.size(), Attrs)); } @@ -734,9 +587,9 @@ Args.push_back(UndefValue::get(Type::Int32Ty)); // Push any varargs arguments on the list. Don't forget their attributes. - for (CallSite::arg_iterator E = CS.arg_end(); I != E; ++I, ++i) { - Args.push_back(*I); - if (ParameterAttributes Attrs = CallPAL.getParamAttrs(i + 1)) + for (; AI != CS.arg_end(); ++AI) { + Args.push_back(*AI); + if (ParameterAttributes Attrs = CallPAL.getParamAttrs(index++)) ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Args.size(), Attrs)); } @@ -760,54 +613,10 @@ Args.clear(); if (!Call->use_empty()) { - if (New->getType() == Call->getType()) { - // Return type not changed? Just replace users then - Call->replaceAllUsesWith(New); - New->takeName(Call); - } else if (New->getType() == Type::VoidTy) { - // Our return value has uses, but they will get removed later on. - // Replace by null for now. + if (New->getType() == Type::VoidTy) Call->replaceAllUsesWith(Constant::getNullValue(Call->getType())); - } else { - assert(isa(RetTy) && "Return type changed, but not into a" - "void. The old return type must have" - "been a struct!"); - // The original return value was a struct, update all uses (which are - // all extractvalue instructions). - for (Value::use_iterator I = Call->use_begin(), E = Call->use_end(); - I != E;) { - assert(isa(*I) && "Return value not only used by" - "extractvalue?"); - ExtractValueInst *EV = cast(*I); - // Increment now, since we're about to throw away this use. - ++I; - assert(EV->hasIndices() && "Return value used by extractvalue without" - "indices?"); - unsigned Idx = *EV->idx_begin(); - if (NewRetIdxs[Idx] != -1) { - if (RetTypes.size() > 1) { - // We're still returning a struct, create a new extractvalue - // instruction with the first index updated - std::vector NewIdxs(EV->idx_begin(), EV->idx_end()); - NewIdxs[0] = NewRetIdxs[Idx]; - Value *NEV = ExtractValueInst::Create(New, NewIdxs.begin(), - NewIdxs.end(), "retval", - EV); - EV->replaceAllUsesWith(NEV); - EV->eraseFromParent(); - } else { - // We are now only returning a simple value, remove the - // extractvalue - EV->replaceAllUsesWith(New); - EV->eraseFromParent(); - } - } else { - // Value unused, replace uses by null for now, they will get removed - // later on - EV->replaceAllUsesWith(Constant::getNullValue(EV->getType())); - EV->eraseFromParent(); - } - } + else { + Call->replaceAllUsesWith(New); New->takeName(Call); } } @@ -823,11 +632,13 @@ NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList()); // Loop over the argument list, transfering uses of the old arguments over to - // the new arguments, also transfering over the names as well. - i = 0; + // the new arguments, also transfering over the names as well. While we're at + // it, remove the dead arguments from the DeadArguments list. + // for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(), - I2 = NF->arg_begin(); I != E; ++I, ++i) - if (ArgAlive[i]) { + I2 = NF->arg_begin(); + I != E; ++I) + if (!DeadArguments.count(I)) { // If this is a live argument, move the name and users over to the new // version. I->replaceAllUsesWith(I2); @@ -835,8 +646,10 @@ ++I2; } else { // If this argument is dead, replace any uses of it with null constants - // (these are guaranteed to become unused later on) + // (these are guaranteed to only be operands to call instructions which + // will later be simplified). I->replaceAllUsesWith(Constant::getNullValue(I->getType())); + DeadArguments.erase(I); } // If we change the return value of the function we must rewrite any return @@ -844,47 +657,12 @@ if (F->getReturnType() != NF->getReturnType()) for (Function::iterator BB = NF->begin(), E = NF->end(); BB != E; ++BB) if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { - Value *RetVal; - - if (NFTy->getReturnType() == Type::VoidTy) { - RetVal = 0; - } else { - assert (isa(RetTy)); - // The original return value was a struct, insert - // extractvalue/insertvalue chains to extract only the values we need - // to return and insert them into our new result. - // This does generate messy code, but we'll let it to instcombine to - // clean that up - Value *OldRet = RI->getOperand(0); - // Start out building up our return value from undef - RetVal = llvm::UndefValue::get(NRetTy); - for (unsigned i = 0; i != RetCount; ++i) - if (NewRetIdxs[i] != -1) { - ExtractValueInst *EV = ExtractValueInst::Create(OldRet, i, - "newret", RI); - if (RetTypes.size() > 1) { - // We're still returning a struct, so reinsert the value into - // our new return value at the new index - - RetVal = InsertValueInst::Create(RetVal, EV, NewRetIdxs[i], - "oldret"); - } else { - // We are now only returning a simple value, so just return the - // extracted value - RetVal = EV; - } - } - } - // Replace the return instruction with one returning the new return - // value (possibly 0 if we became void). - ReturnInst::Create(RetVal, RI); + ReturnInst::Create(0, RI); BB->getInstList().erase(RI); } // Now that the old function is dead, delete it. F->eraseFromParent(); - - return true; } bool DAE::runOnModule(Module &M) { @@ -899,7 +677,7 @@ if (F.getFunctionType()->isVarArg()) Changed |= DeleteDeadVarargs(F); } - + // Second phase:loop through the module, determining which arguments are live. // We assume all arguments are dead unless proven otherwise (allowing us to // determine that dead arguments passed into recursive functions are dead). @@ -908,14 +686,85 @@ for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) SurveyFunction(*I); - // Now, remove all dead arguments and return values from each function in - // turn - for (Module::iterator I = M.begin(), E = M.end(); I != E; ) { - // Increment now, because the function will probably get removed (ie - // replaced by a new one) - Function *F = I++; - Changed |= RemoveDeadStuffFromFunction(F); + // Loop over the instructions to inspect, propagating liveness among arguments + // and return values which are MaybeLive. + while (!InstructionsToInspect.empty()) { + Instruction *I = InstructionsToInspect.back(); + InstructionsToInspect.pop_back(); + + if (ReturnInst *RI = dyn_cast(I)) { + // For return instructions, we just have to check to see if the return + // value for the current function is known now to be alive. If so, any + // arguments used by it are now alive, and any call instruction return + // value is alive as well. + if (LiveRetVal.count(RI->getParent()->getParent())) + MarkReturnInstArgumentLive(RI); + + } else { + CallSite CS = CallSite::get(I); + assert(CS.getInstruction() && "Unknown instruction for the I2I list!"); + + Function *Callee = CS.getCalledFunction(); + + // If we found a call or invoke instruction on this list, that means that + // an argument of the function is a call instruction. If the argument is + // live, then the return value of the called instruction is now live. + // + CallSite::arg_iterator AI = CS.arg_begin(); // ActualIterator + for (Function::arg_iterator FI = Callee->arg_begin(), + E = Callee->arg_end(); FI != E; ++AI, ++FI) { + // If this argument is another call... + CallSite ArgCS = CallSite::get(*AI); + if (ArgCS.getInstruction() && LiveArguments.count(FI)) + if (Function *Callee = ArgCS.getCalledFunction()) + MarkRetValLive(Callee); + } + } } - return Changed; + // Now we loop over all of the MaybeLive arguments, promoting them to be live + // arguments if one of the calls that uses the arguments to the calls they are + // passed into requires them to be live. Of course this could make other + // arguments live, so process callers recursively. + // + // Because elements can be removed from the MaybeLiveArguments set, copy it to + // a temporary vector. + // + std::vector TmpArgList(MaybeLiveArguments.begin(), + MaybeLiveArguments.end()); + for (unsigned i = 0, e = TmpArgList.size(); i != e; ++i) { + Argument *MLA = TmpArgList[i]; + if (MaybeLiveArguments.count(MLA) && + isMaybeLiveArgumentNowLive(MLA)) + MarkArgumentLive(MLA); + } + + // Recover memory early... + CallSites.clear(); + + // At this point, we know that all arguments in DeadArguments and + // MaybeLiveArguments are dead. If the two sets are empty, there is nothing + // to do. + if (MaybeLiveArguments.empty() && DeadArguments.empty() && + MaybeLiveRetVal.empty() && DeadRetVal.empty()) + return Changed; + + // Otherwise, compact into one set, and start eliminating the arguments from + // the functions. + DeadArguments.insert(MaybeLiveArguments.begin(), MaybeLiveArguments.end()); + MaybeLiveArguments.clear(); + DeadRetVal.insert(MaybeLiveRetVal.begin(), MaybeLiveRetVal.end()); + MaybeLiveRetVal.clear(); + + LiveArguments.clear(); + LiveRetVal.clear(); + + NumArgumentsEliminated += DeadArguments.size(); + NumRetValsEliminated += DeadRetVal.size(); + while (!DeadArguments.empty()) + RemoveDeadArgumentsFromFunction((*DeadArguments.begin())->getParent()); + + while (!DeadRetVal.empty()) + RemoveDeadArgumentsFromFunction(*DeadRetVal.begin()); + return true; } Modified: llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll?rev=52570&r1=52569&r2=52570&view=diff ============================================================================== --- llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll (original) +++ llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll Fri Jun 20 19:31:44 2008 @@ -1,39 +0,0 @@ -; This test sees if return values (and arguments) are properly removed when they -; are unused. All unused values are typed i16, so we can easily check. We also -; run instcombine to fold insert/extractvalue chains and we run dce to clean up -; any remaining dead stuff. -; RUN: llvm-as < %s | opt -deadargelim -instcombine -dce | llvm-dis | not grep i16 - -define internal {i16, i32} @test(i16 %DEADARG) { - %A = insertvalue {i16,i32} undef, i16 1, 0 - %B = insertvalue {i16,i32} %A, i32 1001, 1 - ret {i16,i32} %B -} - -define internal {i32, i16} @test2() { - %DEAD = call i16 @test4() - %A = insertvalue {i32,i16} undef, i32 1, 0 - %B = insertvalue {i32,i16} %A, i16 %DEAD, 1 - ret {i32,i16} %B -} - -define internal i32 @test3(i16 %A) { - %ret = call {i16, i32} @test( i16 %A ) ; [#uses=0] - %DEAD = extractvalue {i16, i32} %ret, 0 - %LIVE = extractvalue {i16, i32} %ret, 1 - ret i32 %LIVE -} - -define internal i16 @test4() { - ret i16 0 -} - -define i32 @main() { - %ret = call {i32, i16} @test2() ; [#uses=1] - %LIVE = extractvalue {i32, i16} %ret, 0 - %DEAD = extractvalue {i32, i16} %ret, 1 - %Y = add i32 %LIVE, -123 ; [#uses=1] - %LIVE2 = call i32 @test3(i16 %DEAD) ; [#uses=1] - %Z = add i32 %LIVE2, %Y ; [#uses=1] - ret i32 %Z -} From gohman at apple.com Fri Jun 20 20:08:22 2008 From: gohman at apple.com (Dan Gohman) Date: Sat, 21 Jun 2008 01:08:22 -0000 Subject: [llvm-commits] [llvm] r52571 - /llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp Message-ID: <200806210108.m5L18N1C017543@zion.cs.uiuc.edu> Author: djg Date: Fri Jun 20 20:08:22 2008 New Revision: 52571 URL: http://llvm.org/viewvc/llvm-project?rev=52571&view=rev Log: Simplify some template parameterization. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp?rev=52571&r1=52570&r2=52571&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp Fri Jun 20 20:08:22 2008 @@ -1324,9 +1324,8 @@ } }; - template class VISIBILITY_HIDDEN BURegReductionPriorityQueue - : public RegReductionPriorityQueue { + : public RegReductionPriorityQueue { // SUnitMap SDNode to SUnit mapping (n -> n). DenseMap > *SUnitMap; @@ -1412,9 +1411,8 @@ }; - template class VISIBILITY_HIDDEN TDRegReductionPriorityQueue - : public RegReductionPriorityQueue { + : public RegReductionPriorityQueue { // SUnitMap SDNode to SUnit mapping (n -> n). DenseMap > *SUnitMap; @@ -1551,8 +1549,8 @@ return (left->NodeQueueId > right->NodeQueueId); } -template bool -BURegReductionPriorityQueue::canClobber(const SUnit *SU, const SUnit *Op) { +bool +BURegReductionPriorityQueue::canClobber(const SUnit *SU, const SUnit *Op) { if (SU->isTwoAddress) { unsigned Opc = SU->Node->getTargetOpcode(); const TargetInstrDesc &TID = TII->get(Opc); @@ -1619,8 +1617,7 @@ /// one that has a CopyToReg use (more likely to be a loop induction update). /// If both are two-address, but one is commutable while the other is not /// commutable, favor the one that's not commutable. -template -void BURegReductionPriorityQueue::AddPseudoTwoAddrDeps() { +void BURegReductionPriorityQueue::AddPseudoTwoAddrDeps() { for (unsigned i = 0, e = SUnits->size(); i != e; ++i) { SUnit *SU = (SUnit *)&((*SUnits)[i]); if (!SU->isTwoAddress) @@ -1681,8 +1678,7 @@ /// CalcNodeSethiUllmanNumber - Priority is the Sethi Ullman number. /// Smaller number is the higher priority. -template -unsigned BURegReductionPriorityQueue:: +unsigned BURegReductionPriorityQueue:: CalcNodeSethiUllmanNumber(const SUnit *SU) { unsigned &SethiUllmanNumber = SethiUllmanNumbers[SU->NodeNum]; if (SethiUllmanNumber != 0) @@ -1711,8 +1707,7 @@ /// CalculateSethiUllmanNumbers - Calculate Sethi-Ullman numbers of all /// scheduling units. -template -void BURegReductionPriorityQueue::CalculateSethiUllmanNumbers() { +void BURegReductionPriorityQueue::CalculateSethiUllmanNumbers() { SethiUllmanNumbers.assign(SUnits->size(), 0); for (unsigned i = 0, e = SUnits->size(); i != e; ++i) @@ -1784,8 +1779,7 @@ /// CalcNodeSethiUllmanNumber - Priority is the Sethi Ullman number. /// Smaller number is the higher priority. -template -unsigned TDRegReductionPriorityQueue:: +unsigned TDRegReductionPriorityQueue:: CalcNodeSethiUllmanNumber(const SUnit *SU) { unsigned &SethiUllmanNumber = SethiUllmanNumbers[SU->NodeNum]; if (SethiUllmanNumber != 0) @@ -1825,8 +1819,7 @@ /// CalculateSethiUllmanNumbers - Calculate Sethi-Ullman numbers of all /// scheduling units. -template -void TDRegReductionPriorityQueue::CalculateSethiUllmanNumbers() { +void TDRegReductionPriorityQueue::CalculateSethiUllmanNumbers() { SethiUllmanNumbers.assign(SUnits->size(), 0); for (unsigned i = 0, e = SUnits->size(); i != e; ++i) @@ -1843,8 +1836,8 @@ const TargetInstrInfo *TII = DAG->getTarget().getInstrInfo(); const TargetRegisterInfo *TRI = DAG->getTarget().getRegisterInfo(); - BURegReductionPriorityQueue *priorityQueue = - new BURegReductionPriorityQueue(TII, TRI); + BURegReductionPriorityQueue *priorityQueue = + new BURegReductionPriorityQueue(TII, TRI); ScheduleDAGRRList * scheduleDAG = new ScheduleDAGRRList(*DAG, BB, DAG->getTarget(), true, priorityQueue); @@ -1856,6 +1849,6 @@ SelectionDAG *DAG, MachineBasicBlock *BB) { return new ScheduleDAGRRList(*DAG, BB, DAG->getTarget(), false, - new TDRegReductionPriorityQueue()); + new TDRegReductionPriorityQueue()); } From evan.cheng at apple.com Sat Jun 21 01:45:55 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Sat, 21 Jun 2008 06:45:55 -0000 Subject: [llvm-commits] [llvm] r52572 - in /llvm/trunk: include/llvm/CodeGen/LiveIntervalAnalysis.h lib/CodeGen/LiveIntervalAnalysis.cpp lib/CodeGen/SimpleRegisterCoalescing.cpp test/CodeGen/X86/2006-05-11-InstrSched.ll test/CodeGen/X86/2007-11-14-Coalescer-Bug.ll test/CodeGen/X86/2008-03-18-CoalescerBug.ll Message-ID: <200806210645.m5L6jthn028691@zion.cs.uiuc.edu> Author: evancheng Date: Sat Jun 21 01:45:54 2008 New Revision: 52572 URL: http://llvm.org/viewvc/llvm-project?rev=52572&view=rev Log: Undo spill weight tweak. Need to investigate the performance regressions. Modified: llvm/trunk/include/llvm/CodeGen/LiveIntervalAnalysis.h llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp llvm/trunk/test/CodeGen/X86/2006-05-11-InstrSched.ll llvm/trunk/test/CodeGen/X86/2007-11-14-Coalescer-Bug.ll llvm/trunk/test/CodeGen/X86/2008-03-18-CoalescerBug.ll Modified: llvm/trunk/include/llvm/CodeGen/LiveIntervalAnalysis.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/LiveIntervalAnalysis.h?rev=52572&r1=52571&r2=52572&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/LiveIntervalAnalysis.h (original) +++ llvm/trunk/include/llvm/CodeGen/LiveIntervalAnalysis.h Sat Jun 21 01:45:54 2008 @@ -121,12 +121,8 @@ return getBaseIndex(index) + InstrSlots::STORE; } - static float getSpillWeight(bool isDef, bool isUse, bool isMem, - unsigned loopDepth) { - float Weight = isDef; - if (isUse) - Weight += isMem ? 1.2f : 1.0f; - return Weight * powf(10.0F, (float)loopDepth); + static float getSpillWeight(bool isDef, bool isUse, unsigned loopDepth) { + return (isDef + isUse) * powf(10.0F, (float)loopDepth); } typedef Reg2IntervalMap::iterator iterator; Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp?rev=52572&r1=52571&r2=52572&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp (original) +++ llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Sat Jun 21 01:45:54 2008 @@ -979,7 +979,6 @@ unsigned loopDepth = loopInfo->getLoopDepth(MBB); bool CanFold = false; RestartInstruction: - bool isMem = MI->getDesc().mayLoad() || MI->getDesc().mayStore(); for (unsigned i = 0; i != MI->getNumOperands(); ++i) { MachineOperand& mop = MI->getOperand(i); if (!mop.isRegister()) @@ -1047,7 +1046,7 @@ } // Update stack slot spill weight if we are splitting. - float Weight = getSpillWeight(HasDef, HasUse, isMem, loopDepth); + float Weight = getSpillWeight(HasDef, HasUse, loopDepth); if (!TrySplit) SSWeight += Weight; @@ -1240,7 +1239,6 @@ bool MIHasUse = rwi.HasUse; bool MIHasDef = rwi.HasDef; MachineInstr *MI = rwi.MI; - bool isMem = MI->getDesc().mayLoad() || MI->getDesc().mayStore(); // If MI def and/or use the same register multiple times, then there // are multiple entries. unsigned NumUses = MIHasUse; @@ -1388,7 +1386,7 @@ // Update spill weight. unsigned loopDepth = loopInfo->getLoopDepth(MBB); - nI.weight += getSpillWeight(HasDef, HasUse, isMem, loopDepth); + nI.weight += getSpillWeight(HasDef, HasUse, loopDepth); } if (NewVReg && TrySplit && AllCanFold) { @@ -1630,7 +1628,6 @@ LiveInterval &nI = getOrCreateInterval(VReg); bool isReMat = vrm.isReMaterialized(VReg); MachineInstr *MI = getInstructionFromIndex(index); - bool isMem = MI->getDesc().mayLoad() || MI->getDesc().mayStore(); bool CanFold = false; bool FoundUse = false; Ops.clear(); @@ -1683,7 +1680,7 @@ // Update spill slot weight. if (!isReMat) - SSWeight += getSpillWeight(true, false, isMem, loopDepth); + SSWeight += getSpillWeight(true, false, loopDepth); } Id = SpillMBBs.find_next(Id); } @@ -1703,7 +1700,6 @@ LiveInterval &nI = getOrCreateInterval(VReg); bool isReMat = vrm.isReMaterialized(VReg); MachineInstr *MI = getInstructionFromIndex(index); - bool isMem = MI->getDesc().mayLoad() || MI->getDesc().mayStore(); bool CanFold = false; Ops.clear(); if (restores[i].canFold) { @@ -1757,7 +1753,7 @@ // Update spill slot weight. if (!isReMat) - SSWeight += getSpillWeight(false, true, isMem, loopDepth); + SSWeight += getSpillWeight(false, true, loopDepth); } Id = RestoreMBBs.find_next(Id); } Modified: llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp?rev=52572&r1=52571&r2=52572&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp (original) +++ llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp Sat Jun 21 01:45:54 2008 @@ -2145,7 +2145,6 @@ mii = mbbi->erase(mii); ++numPeep; } else if (!isMove || !TurnCopyIntoImpDef(mii, mbb, DstReg, SrcReg)) { - bool isMem = mii->getDesc().mayLoad() || mii->getDesc().mayStore(); SmallSet UniqueUses; for (unsigned i = 0, e = mii->getNumOperands(); i != e; ++i) { const MachineOperand &mop = mii->getOperand(i); @@ -2158,7 +2157,7 @@ continue; LiveInterval &RegInt = li_->getInterval(reg); RegInt.weight += - li_->getSpillWeight(mop.isDef(), mop.isUse(), isMem, loopDepth); + li_->getSpillWeight(mop.isDef(), mop.isUse(), loopDepth); UniqueUses.insert(reg); } } Modified: llvm/trunk/test/CodeGen/X86/2006-05-11-InstrSched.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2006-05-11-InstrSched.ll?rev=52572&r1=52571&r2=52572&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/2006-05-11-InstrSched.ll (original) +++ llvm/trunk/test/CodeGen/X86/2006-05-11-InstrSched.ll Sat Jun 21 01:45:54 2008 @@ -1,5 +1,5 @@ ; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 -stats -realign-stack=0 |&\ -; RUN: grep {asm-printer} | grep 31 +; RUN: grep {asm-printer} | grep 32 target datalayout = "e-p:32:32" define void @foo(i32* %mc, i32* %bp, i32* %ms, i32* %xmb, i32* %mpp, i32* %tpmm, i32* %ip, i32* %tpim, i32* %dpp, i32* %tpdm, i32* %bpi, i32 %M) nounwind { Modified: llvm/trunk/test/CodeGen/X86/2007-11-14-Coalescer-Bug.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2007-11-14-Coalescer-Bug.ll?rev=52572&r1=52571&r2=52572&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/2007-11-14-Coalescer-Bug.ll (original) +++ llvm/trunk/test/CodeGen/X86/2007-11-14-Coalescer-Bug.ll Sat Jun 21 01:45:54 2008 @@ -1,4 +1,4 @@ -; RUN: llvm-as < %s | llc -march=x86 -x86-asm-syntax=att | grep movl | count 4 +; RUN: llvm-as < %s | llc -march=x86 -x86-asm-syntax=att | grep movl | count 2 %struct.double_int = type { i64, i64 } %struct.tree_common = type <{ i8, [3 x i8] }> Modified: llvm/trunk/test/CodeGen/X86/2008-03-18-CoalescerBug.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2008-03-18-CoalescerBug.ll?rev=52572&r1=52571&r2=52572&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/2008-03-18-CoalescerBug.ll (original) +++ llvm/trunk/test/CodeGen/X86/2008-03-18-CoalescerBug.ll Sat Jun 21 01:45:54 2008 @@ -1,5 +1,5 @@ ; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin -mattr=+sse2 -disable-fp-elim | grep movss | count 1 -; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin -mattr=+sse2 -disable-fp-elim -stats |& grep {Number of re-materialization} | grep 2 +; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin -mattr=+sse2 -disable-fp-elim -stats |& grep {Number of re-materialization} | grep 1 %struct..0objc_object = type opaque %struct.OhBoy = type { } From evan.cheng at apple.com Sat Jun 21 02:20:36 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Sat, 21 Jun 2008 07:20:36 -0000 Subject: [llvm-commits] [test-suite] r52573 - /test-suite/trunk/Makefile.programs Message-ID: <200806210720.m5L7KaKG029997@zion.cs.uiuc.edu> Author: evancheng Date: Sat Jun 21 02:20:36 2008 New Revision: 52573 URL: http://llvm.org/viewvc/llvm-project?rev=52573&view=rev Log: Test new spilling heuristic. Modified: test-suite/trunk/Makefile.programs Modified: test-suite/trunk/Makefile.programs URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/Makefile.programs?rev=52573&r1=52572&r2=52573&view=diff ============================================================================== --- test-suite/trunk/Makefile.programs (original) +++ test-suite/trunk/Makefile.programs Sat Jun 21 02:20:36 2008 @@ -219,7 +219,9 @@ LLCBETAOPTION := -sched=simple endif ifeq ($(ARCH),x86) -LLCBETAOPTION := -enable-value-prop +LLCBETAOPTION := -new-spilling-heuristic +#-two-addr-remat +#-enable-value-prop #-enable-sinking #-schedule-livein-copies #-machine-licm From evan.cheng at apple.com Sat Jun 21 02:26:53 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Sat, 21 Jun 2008 07:26:53 -0000 Subject: [llvm-commits] [llvm] r52574 - /llvm/trunk/lib/Transforms/Scalar/GVN.cpp Message-ID: <200806210726.m5L7QriK030187@zion.cs.uiuc.edu> Author: evancheng Date: Sat Jun 21 02:26:53 2008 New Revision: 52574 URL: http://llvm.org/viewvc/llvm-project?rev=52574&view=rev Log: Enable PRE. Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=52574&r1=52573&r2=52574&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Sat Jun 21 02:26:53 2008 @@ -43,7 +43,7 @@ STATISTIC(NumGVNPRE, "Number of instructions PRE'd"); static cl::opt EnablePRE("enable-pre", - cl::init(false), cl::Hidden); + cl::init(true), cl::Hidden); //===----------------------------------------------------------------------===// // ValueTable Class From resistor at mac.com Sat Jun 21 02:38:10 2008 From: resistor at mac.com (Owen Anderson) Date: Sat, 21 Jun 2008 00:38:10 -0700 Subject: [llvm-commits] [llvm] r52574 - /llvm/trunk/lib/Transforms/Scalar/GVN.cpp In-Reply-To: <200806210726.m5L7QriK030187@zion.cs.uiuc.edu> References: <200806210726.m5L7QriK030187@zion.cs.uiuc.edu> Message-ID: <44B48C8A-D7A7-41F4-A173-1B083BF5A6E4@mac.com> I thought there were still outstanding bootstrap issues with this? --Owen On Jun 21, 2008, at 12:26 AM, Evan Cheng wrote: > Author: evancheng > Date: Sat Jun 21 02:26:53 2008 > New Revision: 52574 > > URL: http://llvm.org/viewvc/llvm-project?rev=52574&view=rev > Log: > Enable PRE. > > Modified: > llvm/trunk/lib/Transforms/Scalar/GVN.cpp > > Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=52574&r1=52573&r2=52574&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original) > +++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Sat Jun 21 02:26:53 2008 > @@ -43,7 +43,7 @@ > STATISTIC(NumGVNPRE, "Number of instructions PRE'd"); > > static cl::opt EnablePRE("enable-pre", > - cl::init(false), cl::Hidden); > + cl::init(true), cl::Hidden); > > // > = > = > = > ----------------------------------------------------------------------= > ==// > // ValueTable Class > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 4260 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080621/4c0863a1/attachment.bin From evan.cheng at apple.com Sat Jun 21 02:59:05 2008 From: evan.cheng at apple.com (Evan Cheng) Date: Sat, 21 Jun 2008 00:59:05 -0700 Subject: [llvm-commits] [llvm] r52574 - /llvm/trunk/lib/Transforms/Scalar/GVN.cpp In-Reply-To: <44B48C8A-D7A7-41F4-A173-1B083BF5A6E4@mac.com> References: <200806210726.m5L7QriK030187@zion.cs.uiuc.edu> <44B48C8A-D7A7-41F4-A173-1B083BF5A6E4@mac.com> Message-ID: <0820B6DF-13CB-45A2-8133-E3F460790E1E@apple.com> I'm not sure. If you think it can break the build, please turn it off. Thanks, Evan On Jun 21, 2008, at 12:38 AM, Owen Anderson wrote: > I thought there were still outstanding bootstrap issues with this? > > --Owen > > On Jun 21, 2008, at 12:26 AM, Evan Cheng wrote: > >> Author: evancheng >> Date: Sat Jun 21 02:26:53 2008 >> New Revision: 52574 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=52574&view=rev >> Log: >> Enable PRE. >> >> Modified: >> llvm/trunk/lib/Transforms/Scalar/GVN.cpp >> >> Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=52574&r1=52573&r2=52574&view=diff >> >> = >> = >> = >> = >> = >> = >> = >> = >> === >> =================================================================== >> --- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original) >> +++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Sat Jun 21 02:26:53 2008 >> @@ -43,7 +43,7 @@ >> STATISTIC(NumGVNPRE, "Number of instructions PRE'd"); >> >> static cl::opt EnablePRE("enable-pre", >> - cl::init(false), cl::Hidden); >> + cl::init(true), cl::Hidden); >> >> // >> === >> --- >> ------------------------------------------------------------------- >> ===// >> // ValueTable Class >> >> >> _______________________________________________ >> llvm-commits mailing list >> llvm-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From gohman at apple.com Sat Jun 21 10:52:52 2008 From: gohman at apple.com (Dan Gohman) Date: Sat, 21 Jun 2008 15:52:52 -0000 Subject: [llvm-commits] [llvm] r52576 - in /llvm/trunk: include/llvm/CodeGen/ScheduleDAG.h lib/CodeGen/SelectionDAG/ScheduleDAG.cpp lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp Message-ID: <200806211552.m5LFqqG4026488@zion.cs.uiuc.edu> Author: djg Date: Sat Jun 21 10:52:51 2008 New Revision: 52576 URL: http://llvm.org/viewvc/llvm-project?rev=52576&view=rev Log: Change ScheduleDAG's SUnitMap from DenseMap > to DenseMap, and adjust the way cloned SUnit nodes are handled so that only the original node needs to be in the map. This speeds up llc on 447.dealII.llvm.bc by about 2%. Modified: llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp Modified: llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h?rev=52576&r1=52575&r2=52576&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h (original) +++ llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h Sat Jun 21 10:52:51 2008 @@ -95,8 +95,8 @@ struct SUnit { SDNode *Node; // Representative node. SmallVector FlaggedNodes;// All nodes flagged to Node. - unsigned InstanceNo; // Instance#. One SDNode can be multiple - // SUnit due to cloning. + SUnit *OrigNode; // If not this, the node from which + // this node was cloned. // Preds/Succs - The SUnits before/after us in the graph. The boolean value // is true if the edge is a token chain edge, false if it is a value edge. @@ -129,7 +129,7 @@ const TargetRegisterClass *CopySrcRC; SUnit(SDNode *node, unsigned nodenum) - : Node(node), InstanceNo(0), NodeNum(nodenum), NodeQueueId(0), Latency(0), + : Node(node), OrigNode(0), NodeNum(nodenum), NodeQueueId(0), Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0), isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false), isPending(false), isAvailable(false), isScheduled(false), @@ -215,7 +215,7 @@ public: virtual ~SchedulingPriorityQueue() {} - virtual void initNodes(DenseMap > &SUMap, + virtual void initNodes(DenseMap &SUMap, std::vector &SUnits) = 0; virtual void addNode(const SUnit *SU) = 0; virtual void updateNode(const SUnit *SU) = 0; @@ -251,8 +251,7 @@ MachineConstantPool *ConstPool; // Target constant pool std::vector Sequence; // The schedule. Null SUnit*'s // represent noop instructions. - DenseMap > SUnitMap; - // SDNode to SUnit mapping (n -> n). + DenseMap SUnitMap; // SDNode to SUnit mapping (n -> n). std::vector SUnits; // The scheduling units. SmallSet CommuteSet; // Nodes that should be commuted. @@ -291,6 +290,7 @@ /// SUnit *NewSUnit(SDNode *N) { SUnits.push_back(SUnit(N, (unsigned)SUnits.size())); + SUnits.back().OrigNode = &SUnits.back(); return &SUnits.back(); } @@ -331,7 +331,7 @@ /// VRBaseMap contains, for each already emitted node, the first virtual /// register number for the results of the node. /// - void EmitNode(SDNode *Node, unsigned InstNo, + void EmitNode(SDNode *Node, bool IsClone, DenseMap &VRBaseMap); /// EmitNoop - Emit a noop instruction. @@ -370,7 +370,7 @@ /// EmitCopyFromReg - Generate machine code for an CopyFromReg node or an /// implicit physical register output. - void EmitCopyFromReg(SDNode *Node, unsigned ResNo, unsigned InstNo, + void EmitCopyFromReg(SDNode *Node, unsigned ResNo, bool IsClone, unsigned SrcReg, DenseMap &VRBaseMap); Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp?rev=52576&r1=52575&r2=52576&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp Sat Jun 21 10:52:51 2008 @@ -79,13 +79,12 @@ SUnit *ScheduleDAG::Clone(SUnit *Old) { SUnit *SU = NewSUnit(Old->Node); + SU->OrigNode = Old->OrigNode; SU->FlaggedNodes = Old->FlaggedNodes; - SU->InstanceNo = SUnitMap[Old->Node].size(); SU->Latency = Old->Latency; SU->isTwoAddress = Old->isTwoAddress; SU->isCommutable = Old->isCommutable; SU->hasPhysRegDefs = Old->hasPhysRegDefs; - SUnitMap[Old->Node].push_back(SU); return SU; } @@ -105,7 +104,7 @@ continue; // If this node has already been processed, stop now. - if (!SUnitMap[NI].empty()) continue; + if (SUnitMap.count(NI)) continue; SUnit *NodeSUnit = NewSUnit(NI); @@ -120,7 +119,9 @@ do { N = N->getOperand(N->getNumOperands()-1).Val; NodeSUnit->FlaggedNodes.push_back(N); - SUnitMap[N].push_back(NodeSUnit); + bool isNew = SUnitMap.insert(std::make_pair(N, NodeSUnit)); + isNew = isNew; + assert(isNew && "Node already inserted!"); } while (N->getNumOperands() && N->getOperand(N->getNumOperands()-1).getValueType()== MVT::Flag); std::reverse(NodeSUnit->FlaggedNodes.begin(), @@ -140,7 +141,9 @@ if (FlagVal.isOperandOf(UI->getUser())) { HasFlagUse = true; NodeSUnit->FlaggedNodes.push_back(N); - SUnitMap[N].push_back(NodeSUnit); + bool isNew = SUnitMap.insert(std::make_pair(N, NodeSUnit)); + isNew = isNew; + assert(isNew && "Node already inserted!"); N = UI->getUser(); break; } @@ -150,7 +153,9 @@ // Now all flagged nodes are in FlaggedNodes and N is the bottom-most node. // Update the SUnit NodeSUnit->Node = N; - SUnitMap[N].push_back(NodeSUnit); + bool isNew = SUnitMap.insert(std::make_pair(N, NodeSUnit)); + isNew = isNew; + assert(isNew && "Node already inserted!"); ComputeLatency(NodeSUnit); } @@ -187,7 +192,7 @@ for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { SDNode *OpN = N->getOperand(i).Val; if (isPassiveNode(OpN)) continue; // Not scheduled. - SUnit *OpSU = SUnitMap[OpN].front(); + SUnit *OpSU = SUnitMap[OpN]; assert(OpSU && "Node has no SUnit!"); if (OpSU == SU) continue; // In the same group. @@ -399,12 +404,12 @@ } void ScheduleDAG::EmitCopyFromReg(SDNode *Node, unsigned ResNo, - unsigned InstanceNo, unsigned SrcReg, + bool IsClone, unsigned SrcReg, DenseMap &VRBaseMap) { unsigned VRBase = 0; if (TargetRegisterInfo::isVirtualRegister(SrcReg)) { // Just use the input register directly! - if (InstanceNo > 0) + if (IsClone) VRBaseMap.erase(SDOperand(Node, ResNo)); bool isNew = VRBaseMap.insert(std::make_pair(SDOperand(Node,ResNo),SrcReg)); isNew = isNew; // Silence compiler warning. @@ -463,7 +468,7 @@ TII->copyRegToReg(*BB, BB->end(), VRBase, SrcReg, DstRC, SrcRC); } - if (InstanceNo > 0) + if (IsClone) VRBaseMap.erase(SDOperand(Node, ResNo)); bool isNew = VRBaseMap.insert(std::make_pair(SDOperand(Node,ResNo), VRBase)); isNew = isNew; // Silence compiler warning. @@ -783,7 +788,7 @@ /// EmitNode - Generate machine code for an node and needed dependencies. /// -void ScheduleDAG::EmitNode(SDNode *Node, unsigned InstanceNo, +void ScheduleDAG::EmitNode(SDNode *Node, bool IsClone, DenseMap &VRBaseMap) { // If machine instruction if (Node->isTargetOpcode()) { @@ -858,7 +863,7 @@ for (unsigned i = II.getNumDefs(); i < NumResults; ++i) { unsigned Reg = II.getImplicitDefs()[i - II.getNumDefs()]; if (Node->hasAnyUseOfValue(i)) - EmitCopyFromReg(Node, i, InstanceNo, Reg, VRBaseMap); + EmitCopyFromReg(Node, i, IsClone, Reg, VRBaseMap); } } } else { @@ -906,7 +911,7 @@ } case ISD::CopyFromReg: { unsigned SrcReg = cast(Node->getOperand(1))->getReg(); - EmitCopyFromReg(Node, 0, InstanceNo, SrcReg, VRBaseMap); + EmitCopyFromReg(Node, 0, IsClone, SrcReg, VRBaseMap); break; } case ISD::INLINEASM: { @@ -1118,11 +1123,11 @@ continue; } for (unsigned j = 0, ee = SU->FlaggedNodes.size(); j != ee; ++j) - EmitNode(SU->FlaggedNodes[j], SU->InstanceNo, VRBaseMap); + EmitNode(SU->FlaggedNodes[j], SU->OrigNode != SU, VRBaseMap); if (!SU->Node) EmitCrossRCCopy(SU, CopyVRBaseMap); else - EmitNode(SU->Node, SU->InstanceNo, VRBaseMap); + EmitNode(SU->Node, SU->OrigNode != SU, VRBaseMap); } if (isEntryBB && SchedLiveInCopies) Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp?rev=52576&r1=52575&r2=52576&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp Sat Jun 21 10:52:51 2008 @@ -177,6 +177,7 @@ // While Available queue is not empty, grab the node with the highest // priority. If it is not ready put it back. Schedule the node. std::vector NotReady; + Sequence.reserve(SUnits.size()); while (!AvailableQueue->empty() || !PendingQueue.empty()) { // Check to see if any of the pending instructions are ready to issue. If // so, add them to the available queue. @@ -319,7 +320,7 @@ LatencyPriorityQueue() : Queue(latency_sort(this)) { } - void initNodes(DenseMap > &sumap, + void initNodes(DenseMap &sumap, std::vector &sunits) { SUnits = &sunits; // Calculate node priorities. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp?rev=52576&r1=52575&r2=52576&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp Sat Jun 21 10:52:51 2008 @@ -254,7 +254,7 @@ continue; SDNode *OpN = SU->Node->getOperand(j).Val; - SUnit *OpSU = isPassiveNode(OpN) ? NULL : SUnitMap[OpN][SU->InstanceNo]; + SUnit *OpSU = isPassiveNode(OpN) ? NULL : SUnitMap[OpN]; if (OpSU && OperandSeen.count(OpSU) == 1) { // Ok, so SU is not the last use of OpSU, but SU is two-address so // it will clobber OpSU. Try to commute SU if no other source operands @@ -263,7 +263,7 @@ for (unsigned k = 0; k < NumOps; ++k) { if (k != j) { OpN = SU->Node->getOperand(k).Val; - OpSU = isPassiveNode(OpN) ? NULL : SUnitMap[OpN][SU->InstanceNo]; + OpSU = isPassiveNode(OpN) ? NULL : SUnitMap[OpN]; if (OpSU && OperandSeen.count(OpSU) == 1) { DoCommute = false; break; @@ -282,7 +282,7 @@ for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); I != E; ++I) { if (!I->isCtrl) - OperandSeen.insert(I->Dep); + OperandSeen.insert(I->Dep->OrigNode); } } } @@ -660,7 +660,7 @@ } if (TryUnfold) { - SmallVector NewNodes; + SmallVector NewNodes; if (!TII->unfoldMemoryOperand(DAG, N, NewNodes)) return NULL; @@ -677,7 +677,10 @@ SDOperand(LoadNode, 1)); SUnit *NewSU = CreateNewSUnit(N); - SUnitMap[N].push_back(NewSU); + bool isNew = SUnitMap.insert(std::make_pair(N, NewSU)); + isNew = isNew; + assert(isNew && "Node already inserted!"); + const TargetInstrDesc &TID = TII->get(N->getTargetOpcode()); for (unsigned i = 0; i != TID.getNumOperands(); ++i) { if (TID.getOperandConstraint(i, TOI::TIED_TO) != -1) { @@ -697,14 +700,15 @@ // but it has different alignment or volatileness. bool isNewLoad = true; SUnit *LoadSU; - DenseMap >::iterator SMI = - SUnitMap.find(LoadNode); + DenseMap::iterator SMI = SUnitMap.find(LoadNode); if (SMI != SUnitMap.end()) { - LoadSU = SMI->second.front(); + LoadSU = SMI->second; isNewLoad = false; } else { LoadSU = CreateNewSUnit(LoadNode); - SUnitMap[LoadNode].push_back(LoadSU); + bool isNew = SUnitMap.insert(std::make_pair(LoadNode, LoadSU)); + isNew = isNew; + assert(isNew && "Node already inserted!"); LoadSU->Depth = SU->Depth; LoadSU->Height = SU->Height; @@ -943,7 +947,7 @@ unsigned CurCycle = 0; // Add root to Available queue. if (!SUnits.empty()) { - SUnit *RootSU = SUnitMap[DAG.getRoot().Val].front(); + SUnit *RootSU = SUnitMap[DAG.getRoot().Val]; assert(RootSU->Succs.empty() && "Graph root shouldn't have successors!"); RootSU->isAvailable = true; AvailableQueue->push(RootSU); @@ -952,6 +956,7 @@ // While Available queue is not empty, grab the node with the highest // priority. If it is not ready put it back. Schedule the node. SmallVector NotReady; + Sequence.reserve(SUnits.size()); while (!AvailableQueue->empty()) { bool Delayed = false; DenseMap > LRegsMap; @@ -1174,6 +1179,7 @@ // While Available queue is not empty, grab the node with the highest // priority. If it is not ready put it back. Schedule the node. std::vector NotReady; + Sequence.reserve(SUnits.size()); while (!AvailableQueue->empty()) { SUnit *CurSU = AvailableQueue->pop(); while (CurSU && CurSU->CycleBound > CurCycle) { @@ -1277,7 +1283,7 @@ RegReductionPriorityQueue() : Queue(SF(this)), currentQueueId(0) {} - virtual void initNodes(DenseMap > &sumap, + virtual void initNodes(DenseMap &sumap, std::vector &sunits) {} virtual void addNode(const SUnit *SU) {} @@ -1327,7 +1333,7 @@ class VISIBILITY_HIDDEN BURegReductionPriorityQueue : public RegReductionPriorityQueue { // SUnitMap SDNode to SUnit mapping (n -> n). - DenseMap > *SUnitMap; + DenseMap *SUnitMap; // SUnits - The SUnits for the current graph. const std::vector *SUnits; @@ -1343,7 +1349,7 @@ const TargetRegisterInfo *tri) : TII(tii), TRI(tri), scheduleDAG(NULL) {} - void initNodes(DenseMap > &sumap, + void initNodes(DenseMap &sumap, std::vector &sunits) { SUnitMap = &sumap; SUnits = &sunits; @@ -1414,7 +1420,7 @@ class VISIBILITY_HIDDEN TDRegReductionPriorityQueue : public RegReductionPriorityQueue { // SUnitMap SDNode to SUnit mapping (n -> n). - DenseMap > *SUnitMap; + DenseMap *SUnitMap; // SUnits - The SUnits for the current graph. const std::vector *SUnits; @@ -1425,7 +1431,7 @@ public: TDRegReductionPriorityQueue() {} - void initNodes(DenseMap > &sumap, + void initNodes(DenseMap &sumap, std::vector &sunits) { SUnitMap = &sumap; SUnits = &sunits; @@ -1560,7 +1566,7 @@ if (TID.getOperandConstraint(i+NumRes, TOI::TIED_TO) != -1) { SDNode *DU = SU->Node->getOperand(i).Val; if ((*SUnitMap).find(DU) != (*SUnitMap).end() && - Op == (*SUnitMap)[DU][SU->InstanceNo]) + Op->OrigNode == (*SUnitMap)[DU]) return true; } } @@ -1636,7 +1642,7 @@ SDNode *DU = SU->Node->getOperand(j).Val; if ((*SUnitMap).find(DU) == (*SUnitMap).end()) continue; - SUnit *DUSU = (*SUnitMap)[DU][SU->InstanceNo]; + SUnit *DUSU = (*SUnitMap)[DU]; if (!DUSU) continue; for (SUnit::succ_iterator I = DUSU->Succs.begin(),E = DUSU->Succs.end(); I != E; ++I) { Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp?rev=52576&r1=52575&r2=52576&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp Sat Jun 21 10:52:51 2008 @@ -303,7 +303,7 @@ GW.emitSimpleNode(0, "plaintext=circle", "GraphRoot"); if (G->DAG.getRoot().Val && G->SUnitMap.find(G->DAG.getRoot().Val) != G->SUnitMap.end()) - GW.emitEdge(0, -1, G->SUnitMap[G->DAG.getRoot().Val].front(), -1, ""); + GW.emitEdge(0, -1, G->SUnitMap[G->DAG.getRoot().Val], -1, ""); } }; } From baldrick at free.fr Sat Jun 21 12:00:47 2008 From: baldrick at free.fr (Duncan Sands) Date: Sat, 21 Jun 2008 17:00:47 -0000 Subject: [llvm-commits] [llvm] r52577 - in /llvm/trunk: lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp lib/CodeGen/SelectionDAG/LegalizeTypes.h test/CodeGen/PowerPC/2008-06-21-F128LoadStore.ll Message-ID: <200806211700.m5LH0ljt028837@zion.cs.uiuc.edu> Author: baldrick Date: Sat Jun 21 12:00:47 2008 New Revision: 52577 URL: http://llvm.org/viewvc/llvm-project?rev=52577&view=rev Log: Support for load/store of expanded float types. I don't know if a truncating store is possible here, but added support for it anyway. Added: llvm/trunk/test/CodeGen/PowerPC/2008-06-21-F128LoadStore.ll Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp?rev=52577&r1=52576&r2=52577&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp Sat Jun 21 12:00:47 2008 @@ -404,6 +404,8 @@ case ISD::BIT_CONVERT: ExpandRes_BIT_CONVERT(N, Lo, Hi); break; case ISD::BUILD_PAIR: ExpandRes_BUILD_PAIR(N, Lo, Hi); break; case ISD::EXTRACT_VECTOR_ELT: ExpandRes_EXTRACT_VECTOR_ELT(N, Lo, Hi); break; + + case ISD::LOAD: ExpandFloatRes_LOAD(N, Lo, Hi); break; } // If Lo/Hi is null, the sub-method took care of registering results etc. @@ -411,6 +413,38 @@ SetExpandedFloat(SDOperand(N, ResNo), Lo, Hi); } +void DAGTypeLegalizer::ExpandFloatRes_LOAD(SDNode *N, SDOperand &Lo, + SDOperand &Hi) { + if (ISD::isNON_EXTLoad(N)) { + ExpandRes_NON_EXTLOAD(N, Lo, Hi); + return; + } + + assert(ISD::isUNINDEXEDLoad(N) && "Indexed load during type legalization!"); + LoadSDNode *LD = cast(N); + SDOperand Chain = LD->getChain(); + SDOperand Ptr = LD->getBasePtr(); + + MVT NVT = TLI.getTypeToTransformTo(LD->getValueType(0)); + assert(NVT.isByteSized() && "Expanded type not byte sized!"); + assert(LD->getMemoryVT().bitsLE(NVT) && "Float type not round?"); + + Lo = DAG.getExtLoad(LD->getExtensionType(), NVT, Chain, Ptr, + LD->getSrcValue(), LD->getSrcValueOffset(), + LD->getMemoryVT(), + LD->isVolatile(), LD->getAlignment()); + + // Remember the chain. + Chain = Lo.getValue(1); + + // The high part is undefined. + Hi = DAG.getNode(ISD::UNDEF, NVT); + + // Modified the chain - switch anything that used the old chain to use the + // new one. + ReplaceValueWith(SDOperand(LD, 1), Chain); +} + //===----------------------------------------------------------------------===// // Float Operand Expansion @@ -441,6 +475,10 @@ case ISD::BIT_CONVERT: Res = ExpandOp_BIT_CONVERT(N); break; case ISD::BUILD_VECTOR: Res = ExpandOp_BUILD_VECTOR(N); break; case ISD::EXTRACT_ELEMENT: Res = ExpandOp_EXTRACT_ELEMENT(N); break; + + case ISD::STORE: + Res = ExpandFloatOp_STORE(cast(N), OpNo); + break; } } @@ -462,3 +500,27 @@ ReplaceValueWith(SDOperand(N, 0), Res); return false; } + +SDOperand DAGTypeLegalizer::ExpandFloatOp_STORE(SDNode *N, unsigned OpNo) { + if (ISD::isNON_TRUNCStore(N)) + return ExpandOp_NON_TRUNCStore(N, OpNo); + + assert(ISD::isUNINDEXEDStore(N) && "Indexed store during type legalization!"); + assert(OpNo == 1 && "Can only expand the stored value so far"); + StoreSDNode *ST = cast(N); + + SDOperand Chain = ST->getChain(); + SDOperand Ptr = ST->getBasePtr(); + + MVT NVT = TLI.getTypeToTransformTo(ST->getValue().getValueType()); + assert(NVT.isByteSized() && "Expanded type not byte sized!"); + assert(ST->getMemoryVT().bitsLE(NVT) && "Float type not round?"); + + SDOperand Lo, Hi; + GetExpandedOp(ST->getValue(), Lo, Hi); + + return DAG.getTruncStore(Chain, Lo, Ptr, + ST->getSrcValue(), ST->getSrcValueOffset(), + ST->getMemoryVT(), + ST->isVolatile(), ST->getAlignment()); +} Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp?rev=52577&r1=52576&r2=52577&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp Sat Jun 21 12:00:47 2008 @@ -1875,7 +1875,7 @@ bool isVolatile = N->isVolatile(); SDOperand Lo, Hi; - assert(!(NVT.getSizeInBits() & 7) && "Expanded type not byte sized!"); + assert(NVT.isByteSized() && "Expanded type not byte sized!"); if (N->getMemoryVT().bitsLE(NVT)) { GetExpandedInteger(N->getValue(), Lo, Hi); Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h?rev=52577&r1=52576&r2=52577&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h Sat Jun 21 12:00:47 2008 @@ -347,9 +347,11 @@ // Float Result Expansion. void ExpandFloatResult(SDNode *N, unsigned ResNo); + void ExpandFloatRes_LOAD(SDNode *N, SDOperand &Lo, SDOperand &Hi); // Float Operand Expansion. bool ExpandFloatOperand(SDNode *N, unsigned OperandNo); + SDOperand ExpandFloatOp_STORE(SDNode *N, unsigned OpNo); //===--------------------------------------------------------------------===// // Scalarization Support: LegalizeVectorTypes.cpp Added: llvm/trunk/test/CodeGen/PowerPC/2008-06-21-F128LoadStore.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/2008-06-21-F128LoadStore.ll?rev=52577&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/PowerPC/2008-06-21-F128LoadStore.ll (added) +++ llvm/trunk/test/CodeGen/PowerPC/2008-06-21-F128LoadStore.ll Sat Jun 21 12:00:47 2008 @@ -0,0 +1,10 @@ +; RUN: llvm-as < %s | llc -march=ppc32 + + at g = external global ppc_fp128 + at h = external global ppc_fp128 + +define void @f() { + %tmp = load ppc_fp128* @g + store ppc_fp128 %tmp, ppc_fp128* @h + ret void +} From gohman at apple.com Sat Jun 21 13:35:25 2008 From: gohman at apple.com (Dan Gohman) Date: Sat, 21 Jun 2008 18:35:25 -0000 Subject: [llvm-commits] [llvm] r52582 - in /llvm/trunk: include/llvm/ADT/PriorityQueue.h include/llvm/CodeGen/ScheduleDAG.h lib/CodeGen/SelectionDAG/ScheduleDAG.cpp lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp Message-ID: <200806211835.m5LIZPjU032353@zion.cs.uiuc.edu> Author: djg Date: Sat Jun 21 13:35:25 2008 New Revision: 52582 URL: http://llvm.org/viewvc/llvm-project?rev=52582&view=rev Log: Add a priority queue class, which is a wrapper around std::priority_queue and provides fairly efficient removal of arbitrary elements. Switch ScheduleDAGRRList from std::set to this new priority queue. Added: llvm/trunk/include/llvm/ADT/PriorityQueue.h Modified: llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp Added: llvm/trunk/include/llvm/ADT/PriorityQueue.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/PriorityQueue.h?rev=52582&view=auto ============================================================================== --- llvm/trunk/include/llvm/ADT/PriorityQueue.h (added) +++ llvm/trunk/include/llvm/ADT/PriorityQueue.h Sat Jun 21 13:35:25 2008 @@ -0,0 +1,77 @@ +//===- llvm/ADT/PriorityQueue.h - Priority queues ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the PriorityQueue class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_PRIORITY_QUEUE_H +#define LLVM_ADT_PRIORITY_QUEUE_H + +#include + +namespace llvm { + +/// PriorityQueue - This class behaves like std::priority_queue and +/// provides a few additional convenience functions. +/// +template, + class Compare = std::less > +class PriorityQueue : public std::priority_queue { +public: + explicit PriorityQueue(const Compare &compare = Compare(), + const Sequence &sequence = Sequence()) + : std::priority_queue(compare, sequence) + {} + + template + PriorityQueue(Iterator begin, Iterator end, + const Compare &compare = Compare(), + const Sequence &sequence = Sequence()) + : std::priority_queue(begin, end, compare, sequence) + {} + + /// erase_one - Erase one element from the queue, regardless of its + /// position. This operation performs a linear search to find an element + /// equal to t, but then uses all logarithmic-time algorithms to do + /// the erase operation. + /// + void erase_one(const T &t) { + // Linear-search to find the element. + typename Sequence::size_type i = + std::find(this->c.begin(), this->c.end(), t) - this->c.begin(); + + // Logarithmic-time heap bubble-up. + while (i != 0) { + typename Sequence::size_type parent = (i - 1) / 2; + std::swap(this->c[i], this->c[parent]); + i = parent; + } + + // The element we want to remove is now at the root, so we can use + // priority_queue's plain pop to remove it. + this->pop(); + } + + /// reheapify - If an element in the queue has changed in a way that + /// affects its standing in the comparison function, the queue's + /// internal state becomes invalid. Calling reheapify() resets the + /// queue's state, making it valid again. This operation has time + /// complexity proportional to the number of elements in the queue, + /// so don't plan to use it a lot. + /// + void reheapify() { + std::make_heap(this->c.begin(), this->c.end(), this->comp); + } +}; + +} // End llvm namespace + +#endif Modified: llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h?rev=52582&r1=52581&r2=52582&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h (original) +++ llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h Sat Jun 21 13:35:25 2008 @@ -17,7 +17,6 @@ #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/SelectionDAG.h" -#include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/SmallSet.h" Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp?rev=52582&r1=52581&r2=52582&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp Sat Jun 21 13:35:25 2008 @@ -14,7 +14,6 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "pre-RA-sched" -#include "llvm/Constants.h" #include "llvm/Type.h" #include "llvm/CodeGen/ScheduleDAG.h" #include "llvm/CodeGen/MachineConstantPool.h" Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp?rev=52582&r1=52581&r2=52582&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp Sat Jun 21 13:35:25 2008 @@ -24,12 +24,13 @@ #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Compiler.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/PriorityQueue.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/STLExtras.h" #include -#include #include "llvm/Support/CommandLine.h" using namespace llvm; @@ -1276,7 +1277,7 @@ template class VISIBILITY_HIDDEN RegReductionPriorityQueue : public SchedulingPriorityQueue { - std::set Queue; + PriorityQueue, SF> Queue; unsigned currentQueueId; public: @@ -1303,7 +1304,7 @@ void push(SUnit *U) { assert(!U->NodeQueueId && "Node in the queue already"); U->NodeQueueId = ++currentQueueId; - Queue.insert(U); + Queue.push(U); } void push_all(const std::vector &Nodes) { @@ -1313,19 +1314,16 @@ SUnit *pop() { if (empty()) return NULL; - typename std::set::iterator i = prior(Queue.end()); - SUnit *V = *i; - Queue.erase(i); + SUnit *V = Queue.top(); + Queue.pop(); V->NodeQueueId = 0; return V; } void remove(SUnit *SU) { assert(!Queue.empty() && "Queue is empty!"); - size_t RemovedNum = Queue.erase(SU); - RemovedNum = RemovedNum; // Silence compiler warning. - assert(RemovedNum > 0 && "Not in queue!"); - assert(RemovedNum == 1 && "Multiple times in the queue!"); + assert(SU->NodeQueueId != 0 && "Not in queue!"); + Queue.erase_one(SU); SU->NodeQueueId = 0; } }; From gohman at apple.com Sat Jun 21 14:18:17 2008 From: gohman at apple.com (Dan Gohman) Date: Sat, 21 Jun 2008 19:18:17 -0000 Subject: [llvm-commits] [llvm] r52583 - in /llvm/trunk: include/llvm/CodeGen/ScheduleDAG.h lib/CodeGen/SelectionDAG/ScheduleDAG.cpp lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp Message-ID: <200806211918.m5LJIIfc001482@zion.cs.uiuc.edu> Author: djg Date: Sat Jun 21 14:18:17 2008 New Revision: 52583 URL: http://llvm.org/viewvc/llvm-project?rev=52583&view=rev Log: Remove ScheduleDAG's SUnitMap altogether. Instead, use SDNode's NodeId field, which is otherwise unused after instruction selection, as an index into the SUnit array. Modified: llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp Modified: llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h?rev=52583&r1=52582&r2=52583&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h (original) +++ llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h Sat Jun 21 14:18:17 2008 @@ -214,8 +214,7 @@ public: virtual ~SchedulingPriorityQueue() {} - virtual void initNodes(DenseMap &SUMap, - std::vector &SUnits) = 0; + virtual void initNodes(std::vector &SUnits) = 0; virtual void addNode(const SUnit *SU) = 0; virtual void updateNode(const SUnit *SU) = 0; virtual void releaseState() = 0; @@ -250,7 +249,6 @@ MachineConstantPool *ConstPool; // Target constant pool std::vector Sequence; // The schedule. Null SUnit*'s // represent noop instructions. - DenseMap SUnitMap; // SDNode to SUnit mapping (n -> n). std::vector SUnits; // The scheduling units. SmallSet CommuteSet; // Nodes that should be commuted. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp?rev=52583&r1=52582&r2=52583&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp Sat Jun 21 14:18:17 2008 @@ -97,13 +97,20 @@ // invalidated. SUnits.reserve(DAG.allnodes_size()); + // During scheduling, the NodeId field of SDNode is used to map SDNodes + // to their associated SUnits by holding SUnits table indices. A value + // of -1 means the SDNode does not yet have an associated SUnit. + for (SelectionDAG::allnodes_iterator NI = DAG.allnodes_begin(), + E = DAG.allnodes_end(); NI != E; ++NI) + NI->setNodeId(-1); + for (SelectionDAG::allnodes_iterator NI = DAG.allnodes_begin(), E = DAG.allnodes_end(); NI != E; ++NI) { if (isPassiveNode(NI)) // Leaf node, e.g. a TargetImmediate. continue; // If this node has already been processed, stop now. - if (SUnitMap.count(NI)) continue; + if (NI->getNodeId() != -1) continue; SUnit *NodeSUnit = NewSUnit(NI); @@ -118,9 +125,8 @@ do { N = N->getOperand(N->getNumOperands()-1).Val; NodeSUnit->FlaggedNodes.push_back(N); - bool isNew = SUnitMap.insert(std::make_pair(N, NodeSUnit)); - isNew = isNew; - assert(isNew && "Node already inserted!"); + assert(N->getNodeId() == -1 && "Node already inserted!"); + N->setNodeId(NodeSUnit->NodeNum); } while (N->getNumOperands() && N->getOperand(N->getNumOperands()-1).getValueType()== MVT::Flag); std::reverse(NodeSUnit->FlaggedNodes.begin(), @@ -140,9 +146,8 @@ if (FlagVal.isOperandOf(UI->getUser())) { HasFlagUse = true; NodeSUnit->FlaggedNodes.push_back(N); - bool isNew = SUnitMap.insert(std::make_pair(N, NodeSUnit)); - isNew = isNew; - assert(isNew && "Node already inserted!"); + assert(N->getNodeId() == -1 && "Node already inserted!"); + N->setNodeId(NodeSUnit->NodeNum); N = UI->getUser(); break; } @@ -152,9 +157,8 @@ // Now all flagged nodes are in FlaggedNodes and N is the bottom-most node. // Update the SUnit NodeSUnit->Node = N; - bool isNew = SUnitMap.insert(std::make_pair(N, NodeSUnit)); - isNew = isNew; - assert(isNew && "Node already inserted!"); + assert(N->getNodeId() == -1 && "Node already inserted!"); + N->setNodeId(NodeSUnit->NodeNum); ComputeLatency(NodeSUnit); } @@ -191,7 +195,7 @@ for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { SDNode *OpN = N->getOperand(i).Val; if (isPassiveNode(OpN)) continue; // Not scheduled. - SUnit *OpSU = SUnitMap[OpN]; + SUnit *OpSU = &SUnits[OpN->getNodeId()]; assert(OpSU && "Node has no SUnit!"); if (OpSU == SU) continue; // In the same group. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp?rev=52583&r1=52582&r2=52583&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp Sat Jun 21 14:18:17 2008 @@ -94,7 +94,7 @@ // Build scheduling units. BuildSchedUnits(); - AvailableQueue->initNodes(SUnitMap, SUnits); + AvailableQueue->initNodes(SUnits); ListScheduleTopDown(); @@ -320,8 +320,7 @@ LatencyPriorityQueue() : Queue(latency_sort(this)) { } - void initNodes(DenseMap &sumap, - std::vector &sunits) { + void initNodes(std::vector &sunits) { SUnits = &sunits; // Calculate node priorities. CalculatePriorities(); Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp?rev=52583&r1=52582&r2=52583&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp Sat Jun 21 14:18:17 2008 @@ -216,7 +216,7 @@ CalculateHeights(); InitDAGTopologicalSorting(); - AvailableQueue->initNodes(SUnitMap, SUnits); + AvailableQueue->initNodes(SUnits); // Execute the actual scheduling loop Top-Down or Bottom-Up as appropriate. if (isBottomUp) @@ -255,7 +255,7 @@ continue; SDNode *OpN = SU->Node->getOperand(j).Val; - SUnit *OpSU = isPassiveNode(OpN) ? NULL : SUnitMap[OpN]; + SUnit *OpSU = isPassiveNode(OpN) ? NULL : &SUnits[OpN->getNodeId()]; if (OpSU && OperandSeen.count(OpSU) == 1) { // Ok, so SU is not the last use of OpSU, but SU is two-address so // it will clobber OpSU. Try to commute SU if no other source operands @@ -264,7 +264,7 @@ for (unsigned k = 0; k < NumOps; ++k) { if (k != j) { OpN = SU->Node->getOperand(k).Val; - OpSU = isPassiveNode(OpN) ? NULL : SUnitMap[OpN]; + OpSU = isPassiveNode(OpN) ? NULL : &SUnits[OpN->getNodeId()]; if (OpSU && OperandSeen.count(OpSU) == 1) { DoCommute = false; break; @@ -678,9 +678,8 @@ SDOperand(LoadNode, 1)); SUnit *NewSU = CreateNewSUnit(N); - bool isNew = SUnitMap.insert(std::make_pair(N, NewSU)); - isNew = isNew; - assert(isNew && "Node already inserted!"); + assert(N->getNodeId() == -1 && "Node already inserted!"); + N->setNodeId(NewSU->NodeNum); const TargetInstrDesc &TID = TII->get(N->getTargetOpcode()); for (unsigned i = 0; i != TID.getNumOperands(); ++i) { @@ -701,15 +700,12 @@ // but it has different alignment or volatileness. bool isNewLoad = true; SUnit *LoadSU; - DenseMap::iterator SMI = SUnitMap.find(LoadNode); - if (SMI != SUnitMap.end()) { - LoadSU = SMI->second; + if (LoadNode->getNodeId() != -1) { + LoadSU = &SUnits[LoadNode->getNodeId()]; isNewLoad = false; } else { LoadSU = CreateNewSUnit(LoadNode); - bool isNew = SUnitMap.insert(std::make_pair(LoadNode, LoadSU)); - isNew = isNew; - assert(isNew && "Node already inserted!"); + LoadNode->setNodeId(LoadSU->NodeNum); LoadSU->Depth = SU->Depth; LoadSU->Height = SU->Height; @@ -948,7 +944,7 @@ unsigned CurCycle = 0; // Add root to Available queue. if (!SUnits.empty()) { - SUnit *RootSU = SUnitMap[DAG.getRoot().Val]; + SUnit *RootSU = &SUnits[DAG.getRoot().Val->getNodeId()]; assert(RootSU->Succs.empty() && "Graph root shouldn't have successors!"); RootSU->isAvailable = true; AvailableQueue->push(RootSU); @@ -1284,8 +1280,7 @@ RegReductionPriorityQueue() : Queue(SF(this)), currentQueueId(0) {} - virtual void initNodes(DenseMap &sumap, - std::vector &sunits) {} + virtual void initNodes(std::vector &sunits) {} virtual void addNode(const SUnit *SU) {} @@ -1330,9 +1325,6 @@ class VISIBILITY_HIDDEN BURegReductionPriorityQueue : public RegReductionPriorityQueue { - // SUnitMap SDNode to SUnit mapping (n -> n). - DenseMap *SUnitMap; - // SUnits - The SUnits for the current graph. const std::vector *SUnits; @@ -1347,9 +1339,7 @@ const TargetRegisterInfo *tri) : TII(tii), TRI(tri), scheduleDAG(NULL) {} - void initNodes(DenseMap &sumap, - std::vector &sunits) { - SUnitMap = &sumap; + void initNodes(std::vector &sunits) { SUnits = &sunits; // Add pseudo dependency edges for two-address nodes. AddPseudoTwoAddrDeps(); @@ -1417,9 +1407,6 @@ class VISIBILITY_HIDDEN TDRegReductionPriorityQueue : public RegReductionPriorityQueue { - // SUnitMap SDNode to SUnit mapping (n -> n). - DenseMap *SUnitMap; - // SUnits - The SUnits for the current graph. const std::vector *SUnits; @@ -1429,9 +1416,7 @@ public: TDRegReductionPriorityQueue() {} - void initNodes(DenseMap &sumap, - std::vector &sunits) { - SUnitMap = &sumap; + void initNodes(std::vector &sunits) { SUnits = &sunits; // Calculate node priorities. CalculateSethiUllmanNumbers(); @@ -1563,8 +1548,8 @@ for (unsigned i = 0; i != NumOps; ++i) { if (TID.getOperandConstraint(i+NumRes, TOI::TIED_TO) != -1) { SDNode *DU = SU->Node->getOperand(i).Val; - if ((*SUnitMap).find(DU) != (*SUnitMap).end() && - Op->OrigNode == (*SUnitMap)[DU]) + if (DU->getNodeId() != -1 && + Op->OrigNode == &(*SUnits)[DU->getNodeId()]) return true; } } @@ -1638,12 +1623,12 @@ for (unsigned j = 0; j != NumOps; ++j) { if (TID.getOperandConstraint(j+NumRes, TOI::TIED_TO) != -1) { SDNode *DU = SU->Node->getOperand(j).Val; - if ((*SUnitMap).find(DU) == (*SUnitMap).end()) + if (DU->getNodeId() == -1) continue; - SUnit *DUSU = (*SUnitMap)[DU]; + const SUnit *DUSU = &(*SUnits)[DU->getNodeId()]; if (!DUSU) continue; - for (SUnit::succ_iterator I = DUSU->Succs.begin(),E = DUSU->Succs.end(); - I != E; ++I) { + for (SUnit::const_succ_iterator I = DUSU->Succs.begin(), + E = DUSU->Succs.end(); I != E; ++I) { if (I->isCtrl) continue; SUnit *SuccSU = I->Dep; if (SuccSU == SU) Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp?rev=52583&r1=52582&r2=52583&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp Sat Jun 21 14:18:17 2008 @@ -301,9 +301,9 @@ static void addCustomGraphFeatures(ScheduleDAG *G, GraphWriter &GW) { GW.emitSimpleNode(0, "plaintext=circle", "GraphRoot"); - if (G->DAG.getRoot().Val && - G->SUnitMap.find(G->DAG.getRoot().Val) != G->SUnitMap.end()) - GW.emitEdge(0, -1, G->SUnitMap[G->DAG.getRoot().Val], -1, ""); + const SDNode *N = G->DAG.getRoot().Val; + if (N && N->getNodeId() != -1) + GW.emitEdge(0, -1, &G->SUnits[N->getNodeId()], -1, ""); } }; } From gohman at apple.com Sat Jun 21 14:26:15 2008 From: gohman at apple.com (Dan Gohman) Date: Sat, 21 Jun 2008 19:26:15 -0000 Subject: [llvm-commits] [llvm] r52584 - /llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h Message-ID: <200806211926.m5LJQGIQ001762@zion.cs.uiuc.edu> Author: djg Date: Sat Jun 21 14:26:15 2008 New Revision: 52584 URL: http://llvm.org/viewvc/llvm-project?rev=52584&view=rev Log: Reorder some fields in SDNode. This avoids padding, reducings its size from 80 to 72 on 64-bit hosts. Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h?rev=52584&r1=52583&r2=52584&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h (original) +++ llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h Sat Jun 21 14:26:15 2008 @@ -1051,17 +1051,17 @@ /// NumOperands/NumValues - The number of entries in the Operand/Value list. unsigned short NumOperands, NumValues; - /// Prev/Next pointers - These pointers form the linked list of of the - /// AllNodes list in the current DAG. - SDNode *Prev, *Next; - friend struct ilist_traits; - /// UsesSize - The size of the uses list. unsigned UsesSize; /// Uses - List of uses for this SDNode. SDUse *Uses; + /// Prev/Next pointers - These pointers form the linked list of of the + /// AllNodes list in the current DAG. + SDNode *Prev, *Next; + friend struct ilist_traits; + /// addUse - add SDUse to the list of uses. void addUse(SDUse &U) { U.addToList(&Uses); } From gohman at apple.com Sat Jun 21 14:34:57 2008 From: gohman at apple.com (Dan Gohman) Date: Sat, 21 Jun 2008 19:34:57 -0000 Subject: [llvm-commits] [llvm] r52585 - /llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp Message-ID: <200806211934.m5LJYvBj002094@zion.cs.uiuc.edu> Author: djg Date: Sat Jun 21 14:34:57 2008 New Revision: 52585 URL: http://llvm.org/viewvc/llvm-project?rev=52585&view=rev Log: Remove a redundant return. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp?rev=52585&r1=52584&r2=52585&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp Sat Jun 21 14:34:57 2008 @@ -214,8 +214,6 @@ // Remove MainNode from FlaggedNodes again. SU->FlaggedNodes.pop_back(); } - - return; } void ScheduleDAG::ComputeLatency(SUnit *SU) { From sabre at nondot.org Sat Jun 21 14:47:03 2008 From: sabre at nondot.org (Chris Lattner) Date: Sat, 21 Jun 2008 19:47:03 -0000 Subject: [llvm-commits] [llvm] r52587 - in /llvm/trunk/lib/VMCore: Pass.cpp Type.cpp Value.cpp Message-ID: <200806211947.m5LJl3x9002494@zion.cs.uiuc.edu> Author: lattner Date: Sat Jun 21 14:47:03 2008 New Revision: 52587 URL: http://llvm.org/viewvc/llvm-project?rev=52587&view=rev Log: fix some warnings when assertions are disabled. Modified: llvm/trunk/lib/VMCore/Pass.cpp llvm/trunk/lib/VMCore/Type.cpp llvm/trunk/lib/VMCore/Value.cpp Modified: llvm/trunk/lib/VMCore/Pass.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Pass.cpp?rev=52587&r1=52586&r2=52587&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/Pass.cpp (original) +++ llvm/trunk/lib/VMCore/Pass.cpp Sat Jun 21 14:47:03 2008 @@ -146,7 +146,7 @@ void RegisterPass(const PassInfo &PI) { bool Inserted = PassInfoMap.insert(std::make_pair(PI.getTypeInfo(),&PI)).second; - assert(Inserted && "Pass registered multiple times!"); + assert(Inserted && "Pass registered multiple times!"); Inserted=Inserted; } void UnregisterPass(const PassInfo &PI) { Modified: llvm/trunk/lib/VMCore/Type.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Type.cpp?rev=52587&r1=52586&r2=52587&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/Type.cpp (original) +++ llvm/trunk/lib/VMCore/Type.cpp Sat Jun 21 14:47:03 2008 @@ -901,7 +901,7 @@ // The old record is now out-of-date, because one of the children has been // updated. Remove the obsolete entry from the map. unsigned NumErased = Map.erase(ValType::get(Ty)); - assert(NumErased && "Element not found!"); + assert(NumErased && "Element not found!"); NumErased = NumErased; // Remember the structural hash for the type before we start hacking on it, // in case we need it later. @@ -1426,7 +1426,7 @@ while (!AbstractTypeUsers.empty() && NewTy != this) { AbstractTypeUser *User = AbstractTypeUsers.back(); - unsigned OldSize = AbstractTypeUsers.size(); + unsigned OldSize = AbstractTypeUsers.size(); OldSize=OldSize; #ifdef DEBUG_MERGE_TYPES DOUT << " REFINING user " << OldSize-1 << "[" << (void*)User << "] of abstract type [" << (void*)this << " " @@ -1453,7 +1453,7 @@ DOUT << "typeIsREFINED type: " << (void*)this << " " << *this << "\n"; #endif - unsigned OldSize = AbstractTypeUsers.size(); + unsigned OldSize = AbstractTypeUsers.size(); OldSize=OldSize; while (!AbstractTypeUsers.empty()) { AbstractTypeUser *ATU = AbstractTypeUsers.back(); ATU->typeBecameConcrete(this); Modified: llvm/trunk/lib/VMCore/Value.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Value.cpp?rev=52587&r1=52586&r2=52587&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/Value.cpp (original) +++ llvm/trunk/lib/VMCore/Value.cpp Sat Jun 21 14:47:03 2008 @@ -264,7 +264,7 @@ // Get V's ST, this should always succed, because V has a name. ValueSymbolTable *VST; bool Failure = getSymTab(V, VST); - assert(!Failure && "V has a name, so it should have a ST!"); + assert(!Failure && "V has a name, so it should have a ST!"); Failure=Failure; // If these values are both in the same symtab, we can do this very fast. // This works even if both values have no symtab yet. From sabre at nondot.org Sat Jun 21 14:47:44 2008 From: sabre at nondot.org (Chris Lattner) Date: Sat, 21 Jun 2008 19:47:44 -0000 Subject: [llvm-commits] [llvm] r52588 - /llvm/trunk/lib/Bitcode/Reader/Deserialize.cpp Message-ID: <200806211947.m5LJli6g002524@zion.cs.uiuc.edu> Author: lattner Date: Sat Jun 21 14:47:44 2008 New Revision: 52588 URL: http://llvm.org/viewvc/llvm-project?rev=52588&view=rev Log: fix warning when assertion disabled. Modified: llvm/trunk/lib/Bitcode/Reader/Deserialize.cpp Modified: llvm/trunk/lib/Bitcode/Reader/Deserialize.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/Deserialize.cpp?rev=52588&r1=52587&r2=52588&view=diff ============================================================================== --- llvm/trunk/lib/Bitcode/Reader/Deserialize.cpp (original) +++ llvm/trunk/lib/Bitcode/Reader/Deserialize.cpp Sat Jun 21 14:47:44 2008 @@ -85,7 +85,7 @@ case bitc::END_BLOCK: { bool x = Stream.ReadBlockEnd(); - assert (!x && "Error at block end."); + assert(!x && "Error at block end."); x=x; BlockStack.pop_back(); continue; } From sabre at nondot.org Sat Jun 21 14:48:22 2008 From: sabre at nondot.org (Chris Lattner) Date: Sat, 21 Jun 2008 19:48:22 -0000 Subject: [llvm-commits] [llvm] r52589 - /llvm/trunk/lib/Analysis/IntervalPartition.cpp Message-ID: <200806211948.m5LJmMkL002560@zion.cs.uiuc.edu> Author: lattner Date: Sat Jun 21 14:48:22 2008 New Revision: 52589 URL: http://llvm.org/viewvc/llvm-project?rev=52589&view=rev Log: fix warning when assertions disabled. Modified: llvm/trunk/lib/Analysis/IntervalPartition.cpp Modified: llvm/trunk/lib/Analysis/IntervalPartition.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/IntervalPartition.cpp?rev=52589&r1=52588&r2=52589&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/IntervalPartition.cpp (original) +++ llvm/trunk/lib/Analysis/IntervalPartition.cpp Sat Jun 21 14:48:22 2008 @@ -91,8 +91,7 @@ // IntervalPartition::IntervalPartition(IntervalPartition &IP, bool) : FunctionPass((intptr_t) &ID) { - Interval *FunctionStart = IP.getRootInterval(); - assert(FunctionStart && "Cannot operate on empty IntervalPartitions!"); + assert(IP.getRootInterval() && "Cannot operate on empty IntervalPartitions!"); // Pass false to intervals_begin because we take ownership of it's memory interval_part_interval_iterator I = intervals_begin(IP, false); From sabre at nondot.org Sat Jun 21 14:49:01 2008 From: sabre at nondot.org (Chris Lattner) Date: Sat, 21 Jun 2008 19:49:01 -0000 Subject: [llvm-commits] [llvm] r52590 - /llvm/trunk/lib/Transforms/Utils/DemoteRegToStack.cpp Message-ID: <200806211949.m5LJn1ct002598@zion.cs.uiuc.edu> Author: lattner Date: Sat Jun 21 14:49:01 2008 New Revision: 52590 URL: http://llvm.org/viewvc/llvm-project?rev=52590&view=rev Log: Fix warning when assertions disabled. Modified: llvm/trunk/lib/Transforms/Utils/DemoteRegToStack.cpp Modified: llvm/trunk/lib/Transforms/Utils/DemoteRegToStack.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/DemoteRegToStack.cpp?rev=52590&r1=52589&r2=52590&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Utils/DemoteRegToStack.cpp (original) +++ llvm/trunk/lib/Transforms/Utils/DemoteRegToStack.cpp Sat Jun 21 14:49:01 2008 @@ -127,7 +127,7 @@ for (unsigned i = 0, e = P->getNumIncomingValues(); i < e; ++i) { if (InvokeInst *II = dyn_cast(P->getIncomingValue(i))) { assert(II->getParent() != P->getIncomingBlock(i) && - "Invoke edge not supported yet"); + "Invoke edge not supported yet"); II=II; } new StoreInst(P->getIncomingValue(i), Slot, P->getIncomingBlock(i)->getTerminator()); From baldrick at free.fr Sat Jun 21 15:03:15 2008 From: baldrick at free.fr (Duncan Sands) Date: Sat, 21 Jun 2008 20:03:15 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r52591 - /llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Message-ID: <200806212003.m5LK3F25003012@zion.cs.uiuc.edu> Author: baldrick Date: Sat Jun 21 15:03:15 2008 New Revision: 52591 URL: http://llvm.org/viewvc/llvm-project?rev=52591&view=rev Log: Don't name values pointlessly, for example calling them "tmp". Removing all uses of the name "tmp" reduces the size of the sqlite3 bitcode by 30% and speeds up compile time by more than 10% at -O0 (the effect is much less pronounced at -O1 and higher). Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp?rev=52591&r1=52590&r2=52591&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Sat Jun 21 15:03:15 2008 @@ -408,7 +408,7 @@ assert (RealSize == 0 && "The target should handle this argument!"); // This cast only involves pointers, therefore BitCast. - Loc = Builder.CreateBitCast(Loc, PointerType::getUnqual(LLVMTy), "tmp"); + Loc = Builder.CreateBitCast(Loc, PointerType::getUnqual(LLVMTy)); Builder.CreateStore(ArgVal, Loc); } @@ -495,7 +495,7 @@ if (isa(ArgVal->getType()) && isa(LLVMTy)) { // If this is GCC being sloppy about pointer types, insert a bitcast. // See PR1083 for an example. - ArgVal = Builder.CreateBitCast(ArgVal, LLVMTy, "tmp"); + ArgVal = Builder.CreateBitCast(ArgVal, LLVMTy); } else if (ArgVal->getType() == Type::DoubleTy) { // If this is a K&R float parameter, it got promoted to double. Insert // the truncation to float now. @@ -531,9 +531,9 @@ Value *Loc = LocStack.back(); // This cast only involves pointers, therefore BitCast. - Loc = Builder.CreateBitCast(Loc, PointerType::getUnqual(StructTy), "tmp"); + Loc = Builder.CreateBitCast(Loc, PointerType::getUnqual(StructTy)); - Loc = Builder.CreateStructGEP(Loc, FieldNo, "tmp"); + Loc = Builder.CreateStructGEP(Loc, FieldNo); LocStack.push_back(Loc); } void ExitField() { @@ -820,8 +820,8 @@ // beginning of the aggregate (x86-64). if (ReturnOffset) { RetVal = BitCastToType(RetVal, PointerType::getUnqual(Type::Int8Ty)); - RetVal = Builder.CreateGEP(RetVal, - ConstantInt::get(TD.getIntPtrType(), ReturnOffset), "tmp"); + RetVal = Builder.CreateGEP(RetVal, + ConstantInt::get(TD.getIntPtrType(), ReturnOffset)); } RetVal = BitCastToType(RetVal, PointerType::getUnqual(Fn->getReturnType())); @@ -1322,7 +1322,7 @@ unsigned Alignment = std::min(DestLoc.Alignment, SrcLoc.Alignment); if (ElTy->isSingleValueType()) { - LoadInst *V = Builder.CreateLoad(SrcLoc.Ptr, SrcLoc.Volatile, "tmp"); + LoadInst *V = Builder.CreateLoad(SrcLoc.Ptr, SrcLoc.Volatile); StoreInst *S = Builder.CreateStore(V, DestLoc.Ptr, DestLoc.Volatile); V->setAlignment(Alignment); S->setAlignment(Alignment); @@ -1331,8 +1331,8 @@ for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { if (gccType && isPaddingElement(gccType, i)) continue; - Value *DElPtr = Builder.CreateStructGEP(DestLoc.Ptr, i, "tmp"); - Value *SElPtr = Builder.CreateStructGEP(SrcLoc.Ptr, i, "tmp"); + Value *DElPtr = Builder.CreateStructGEP(DestLoc.Ptr, i); + Value *SElPtr = Builder.CreateStructGEP(SrcLoc.Ptr, i); unsigned Align = MinAlign(Alignment, SL->getElementOffset(i)); CopyAggregate(MemRef(DElPtr, Align, DestLoc.Volatile), MemRef(SElPtr, Align, SrcLoc.Volatile), @@ -1342,8 +1342,8 @@ const ArrayType *ATy = cast(ElTy); unsigned EltSize = getTargetData().getABITypeSize(ATy->getElementType()); for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) { - Value *DElPtr = Builder.CreateStructGEP(DestLoc.Ptr, i, "tmp"); - Value *SElPtr = Builder.CreateStructGEP(SrcLoc.Ptr, i, "tmp"); + Value *DElPtr = Builder.CreateStructGEP(DestLoc.Ptr, i); + Value *SElPtr = Builder.CreateStructGEP(SrcLoc.Ptr, i); unsigned Align = MinAlign(Alignment, i * EltSize); CopyAggregate(MemRef(DElPtr, Align, DestLoc.Volatile), MemRef(SElPtr, Align, SrcLoc.Volatile), @@ -1413,7 +1413,7 @@ } else if (const StructType *STy = dyn_cast(ElTy)) { const StructLayout *SL = getTargetData().getStructLayout(STy); for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { - Value *Ptr = Builder.CreateStructGEP(DestLoc.Ptr, i, "tmp"); + Value *Ptr = Builder.CreateStructGEP(DestLoc.Ptr, i); unsigned Alignment = MinAlign(DestLoc.Alignment, SL->getElementOffset(i)); ZeroAggregate(MemRef(Ptr, Alignment, DestLoc.Volatile), Builder); } @@ -1421,7 +1421,7 @@ const ArrayType *ATy = cast(ElTy); unsigned EltSize = getTargetData().getABITypeSize(ATy->getElementType()); for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) { - Value *Ptr = Builder.CreateStructGEP(DestLoc.Ptr, i, "tmp"); + Value *Ptr = Builder.CreateStructGEP(DestLoc.Ptr, i); unsigned Alignment = MinAlign(DestLoc.Alignment, i * EltSize); ZeroAggregate(MemRef(Ptr, Alignment, DestLoc.Volatile), Builder); } @@ -1512,7 +1512,7 @@ // The idea is that it's a pointer to type "Value" // which is opaque* but the routine expects i8** and i8*. const PointerType *Ty = PointerType::getUnqual(Type::Int8Ty); - V = Builder.CreateBitCast(V, PointerType::getUnqual(Ty), "tmp"); + V = Builder.CreateBitCast(V, PointerType::getUnqual(Ty)); Value *Ops[2] = { V, @@ -1669,7 +1669,7 @@ else if (TREE_CODE(decl) == RESULT_DECL) Name = "retval"; else - Name = "tmp"; + Name = ""; // Insert an alloca for this variable. AllocaInst *AI; @@ -1882,8 +1882,8 @@ } } else { // The range is too big to add to the switch - emit an "if". - Value *Diff = Builder.CreateSub(SwitchExp, LowC, "tmp"); - Value *Cond = Builder.CreateICmpULE(Diff, ConstantInt::get(Range), "tmp"); + Value *Diff = Builder.CreateSub(SwitchExp, LowC); + Value *Cond = Builder.CreateICmpULE(Diff, ConstantInt::get(Range)); BasicBlock *False_Block = BasicBlock::Create("case_false"); Builder.CreateCondBr(Cond, Dest, False_Block); EmitBlock(False_Block); @@ -2078,11 +2078,11 @@ } else if (RegionKind < 0) { // Filter - the result of a filter selection will be a negative index if // there is a match. - Value *Select = Builder.CreateLoad(ExceptionSelectorValue, "tmp"); + Value *Select = Builder.CreateLoad(ExceptionSelectorValue); // Compare with the filter action value. Value *Zero = ConstantInt::get(Select->getType(), 0); - Value *Compare = Builder.CreateICmpSLT(Select, Zero, "tmp"); + Value *Compare = Builder.CreateICmpSLT(Select, Zero); // Branch on the compare. BasicBlock *NoFilterBB = BasicBlock::Create("nofilter"); @@ -2099,12 +2099,12 @@ // Call get eh type id. Value *TypeID = Builder.CreateCall(FuncEHGetTypeID, TType, "eh_typeid"); - Value *Select = Builder.CreateLoad(ExceptionSelectorValue, "tmp"); + Value *Select = Builder.CreateLoad(ExceptionSelectorValue); // Compare with the exception selector. - Value *Compare = Builder.CreateICmpEQ(Select, TypeID, "tmp"); + Value *Compare = Builder.CreateICmpEQ(Select, TypeID); - Cond = Cond ? Builder.CreateOr(Cond, Compare, "tmp") : Compare; + Cond = Cond ? Builder.CreateOr(Cond, Compare) : Compare; } BasicBlock *NoCatchBB = NULL; @@ -2223,7 +2223,7 @@ if (!DestLoc) { // Scalar value: emit a load. Value *Ptr = BitCastToType(LV.Ptr, PointerType::getUnqual(Ty)); - LoadInst *LI = Builder.CreateLoad(Ptr, isVolatile, "tmp"); + LoadInst *LI = Builder.CreateLoad(Ptr, isVolatile); LI->setAlignment(Alignment); return LI; } else { @@ -2259,9 +2259,9 @@ ThisLastBitPlusOne = LV.BitStart+LV.BitSize; Value *Ptr = Index ? - Builder.CreateGEP(LV.Ptr, ConstantInt::get(Type::Int32Ty, Index), - "tmp") : LV.Ptr; - LoadInst *LI = Builder.CreateLoad(Ptr, isVolatile, "tmp"); + Builder.CreateGEP(LV.Ptr, ConstantInt::get(Type::Int32Ty, Index)) : + LV.Ptr; + LoadInst *LI = Builder.CreateLoad(Ptr, isVolatile); LI->setAlignment(Alignment); Value *Val = LI; @@ -2280,7 +2280,7 @@ if (FirstBitInVal+BitsInVal != ValSizeInBits) { Value *ShAmt = ConstantInt::get(ValTy, ValSizeInBits-(FirstBitInVal+BitsInVal)); - Val = Builder.CreateShl(Val, ShAmt, "tmp"); + Val = Builder.CreateShl(Val, ShAmt); } // Shift right required? @@ -2288,14 +2288,13 @@ bool AddSignBits = !TYPE_UNSIGNED(TREE_TYPE(exp)) && !Result; Value *ShAmt = ConstantInt::get(ValTy, ValSizeInBits-BitsInVal); Val = AddSignBits ? - Builder.CreateAShr(Val, ShAmt, "tmp") : - Builder.CreateLShr(Val, ShAmt, "tmp"); + Builder.CreateAShr(Val, ShAmt) : Builder.CreateLShr(Val, ShAmt); } if (Result) { Value *ShAmt = ConstantInt::get(ValTy, BitsInVal); - Result = Builder.CreateShl(Result, ShAmt, "tmp"); - Result = Builder.CreateOr(Result, Val, "tmp"); + Result = Builder.CreateShl(Result, ShAmt); + Result = Builder.CreateOr(Result, Val); } else { Result = Val; } @@ -2440,7 +2439,7 @@ Value *Loc = LocStack.back(); if (Loc) { // An address. Convert to the right type and load the value out. - Loc = Builder.CreateBitCast(Loc, PointerType::getUnqual(Ty), "tmp"); + Loc = Builder.CreateBitCast(Loc, PointerType::getUnqual(Ty)); return Builder.CreateLoad(Loc, "val"); } else { // A value - just return it. @@ -2573,7 +2572,7 @@ /// (of type PtrTy) to the argument is passed rather than the argument itself. void HandleByInvisibleReferenceArgument(const llvm::Type *PtrTy, tree type){ Value *Loc = getAddress(); - Loc = Builder.CreateBitCast(Loc, PtrTy, "tmp"); + Loc = Builder.CreateBitCast(Loc, PtrTy); CallOperands.push_back(Loc); } @@ -2591,7 +2590,7 @@ /// LLVM Struct, StructTy is the LLVM type of the struct we are entering. void EnterField(unsigned FieldNo, const llvm::Type *StructTy) { Value *Loc = getAddress(); - Loc = Builder.CreateBitCast(Loc, PointerType::getUnqual(StructTy), "tmp"); + Loc = Builder.CreateBitCast(Loc, PointerType::getUnqual(StructTy)); pushAddress(Builder.CreateStructGEP(Loc, FieldNo, "elt")); } void ExitField() { @@ -2737,8 +2736,6 @@ if (Call->getType() == Type::VoidTy) return 0; - Call->setName("tmp"); - if (Client.isAggrReturn()) { Value *Dest = BitCastToType(DestLoc->Ptr, PointerType::getUnqual(Call->getType())); @@ -2758,8 +2755,8 @@ Value *Ptr = DestLoc->Ptr; if (Client.Offset) { Ptr = BitCastToType(Ptr, PointerType::getUnqual(Type::Int8Ty)); - Ptr = Builder.CreateGEP(Ptr, - ConstantInt::get(TD.getIntPtrType(), Client.Offset), "tmp"); + Ptr = Builder.CreateGEP(Ptr, + ConstantInt::get(TD.getIntPtrType(), Client.Offset)); } Ptr = BitCastToType(Ptr, PointerType::getUnqual(Call->getType())); StoreInst *St = Builder.CreateStore(Call, Ptr, DestLoc->Volatile); @@ -2937,9 +2934,9 @@ ThisLastBitPlusOne = LV.BitStart+LV.BitSize; Value *Ptr = Index ? - Builder.CreateGEP(LV.Ptr, ConstantInt::get(Type::Int32Ty, Index), - "tmp") : LV.Ptr; - LoadInst *LI = Builder.CreateLoad(Ptr, isVolatile, "tmp"); + Builder.CreateGEP(LV.Ptr, ConstantInt::get(Type::Int32Ty, Index)) : + LV.Ptr; + LoadInst *LI = Builder.CreateLoad(Ptr, isVolatile); LI->setAlignment(Alignment); Value *OldVal = LI; Value *NewVal = BitSource; @@ -2955,7 +2952,7 @@ // If not storing into the zero'th bit, shift the Src value to the left. if (FirstBitInVal) { Value *ShAmt = ConstantInt::get(ValTy, FirstBitInVal); - NewVal = Builder.CreateShl(NewVal, ShAmt, "tmp"); + NewVal = Builder.CreateShl(NewVal, ShAmt); } // Next, if this doesn't touch the top bit, mask out any bits that shouldn't @@ -2965,21 +2962,21 @@ Mask = ConstantExpr::getTruncOrBitCast(Mask, ValTy); if (FirstBitInVal+BitsInVal != ValSizeInBits) - NewVal = Builder.CreateAnd(NewVal, Mask, "tmp"); + NewVal = Builder.CreateAnd(NewVal, Mask); // Next, mask out the bits this bit-field should include from the old value. Mask = ConstantExpr::getNot(Mask); - OldVal = Builder.CreateAnd(OldVal, Mask, "tmp"); + OldVal = Builder.CreateAnd(OldVal, Mask); // Finally, merge the two together and store it. - NewVal = Builder.CreateOr(OldVal, NewVal, "tmp"); + NewVal = Builder.CreateOr(OldVal, NewVal); StoreInst *SI = Builder.CreateStore(NewVal, Ptr, isVolatile); SI->setAlignment(Alignment); if (I + 1 < Strides) { Value *ShAmt = ConstantInt::get(ValTy, BitsInVal); - BitSource = Builder.CreateLShr(BitSource, ShAmt, "tmp"); + BitSource = Builder.CreateLShr(BitSource, ShAmt); } } @@ -3081,8 +3078,7 @@ // Target holds the temporary created above. const Type *ExpTy = ConvertType(TREE_TYPE(exp)); return Builder.CreateLoad(BitCastToType(Target.Ptr, - PointerType::getUnqual(ExpTy)), - "tmp"); + PointerType::getUnqual(ExpTy))); } if (DestLoc) { @@ -3106,29 +3102,29 @@ // bitcast'able. This supports things like v_c_e(foo*, float). if (isa(OpVal->getType())) { if (isa(DestTy)) // ptr->ptr is a simple bitcast. - return Builder.CreateBitCast(OpVal, DestTy, "tmp"); + return Builder.CreateBitCast(OpVal, DestTy); // Otherwise, ptrtoint to intptr_t first. - OpVal = Builder.CreatePtrToInt(OpVal, TD.getIntPtrType(), "tmp"); + OpVal = Builder.CreatePtrToInt(OpVal, TD.getIntPtrType()); } // If the destination type is a pointer, use inttoptr. if (isa(DestTy)) - return Builder.CreateIntToPtr(OpVal, DestTy, "tmp"); + return Builder.CreateIntToPtr(OpVal, DestTy); // Otherwise, use a bitcast. - return Builder.CreateBitCast(OpVal, DestTy, "tmp"); + return Builder.CreateBitCast(OpVal, DestTy); } Value *TreeToLLVM::EmitNEGATE_EXPR(tree exp, const MemRef *DestLoc) { if (!DestLoc) { Value *V = Emit(TREE_OPERAND(exp, 0), 0); if (!isa(V->getType())) - return Builder.CreateNeg(V, "tmp"); + return Builder.CreateNeg(V); // GCC allows NEGATE_EXPR on pointers as well. Cast to int, negate, cast // back. V = CastToAnyType(V, false, TD.getIntPtrType(), false); - V = Builder.CreateNeg(V, "tmp"); + V = Builder.CreateNeg(V); return CastToType(Instruction::IntToPtr, V, ConvertType(TREE_TYPE(exp))); } @@ -3141,8 +3137,8 @@ // Handle complex numbers: -(a+ib) = -a + i*-b Value *R, *I; EmitLoadFromComplex(R, I, Tmp); - R = Builder.CreateNeg(R, "tmp"); - I = Builder.CreateNeg(I, "tmp"); + R = Builder.CreateNeg(R); + I = Builder.CreateNeg(I); EmitStoreToComplex(*DestLoc, R, I); return 0; } @@ -3158,7 +3154,7 @@ // Handle complex numbers: ~(a+ib) = a + i*-b Value *R, *I; EmitLoadFromComplex(R, I, Tmp); - I = Builder.CreateNeg(I, "tmp"); + I = Builder.CreateNeg(I); EmitStoreToComplex(*DestLoc, R, I); return 0; } @@ -3224,15 +3220,14 @@ ICmpInst::Predicate(TYPE_UNSIGNED(Op0Ty) ? UIOpc : SIOpc); // Get the compare instructions - Value *Result = Builder.CreateICmp(pred, LHS, RHS, "tmp"); + Value *Result = Builder.CreateICmp(pred, LHS, RHS); // The GCC type is probably an int, not a bool. return CastToUIntType(Result, ConvertType(TREE_TYPE(exp))); } // Handle floating point comparisons, if we get here. - Value *Result = Builder.CreateFCmp(FCmpInst::Predicate(FPPred), - LHS, RHS, "tmp"); + Value *Result = Builder.CreateFCmp(FCmpInst::Predicate(FPPred), LHS, RHS); // The GCC type is probably an int, not a bool. return CastToUIntType(Result, ConvertType(TREE_TYPE(exp))); @@ -3261,7 +3256,7 @@ LHS = CastToAnyType(LHS, LHSIsSigned, Ty, TyIsSigned); RHS = CastToAnyType(RHS, RHSIsSigned, Ty, TyIsSigned); - return Builder.CreateBinOp((Instruction::BinaryOps)Opc, LHS, RHS, "tmp"); + return Builder.CreateBinOp((Instruction::BinaryOps)Opc, LHS, RHS); } /// EmitPtrBinOp - Handle binary expressions involving pointers, e.g. "P+4". @@ -3294,7 +3289,7 @@ if (Opc == Instruction::Sub) EltOffset = -EltOffset; Constant *C = ConstantInt::get(Type::Int64Ty, EltOffset); - Value *V = Builder.CreateGEP(LHS, C, "tmp"); + Value *V = Builder.CreateGEP(LHS, C); return BitCastToType(V, ConvertType(TREE_TYPE(exp))); } } @@ -3308,7 +3303,7 @@ bool RHSIsSigned = !TYPE_UNSIGNED(TREE_TYPE(TREE_OPERAND(exp, 1))); LHS = CastToAnyType(LHS, LHSIsSigned, IntPtrTy, false); RHS = CastToAnyType(RHS, RHSIsSigned, IntPtrTy, false); - Value *V = Builder.CreateBinOp((Instruction::BinaryOps)Opc, LHS, RHS, "tmp"); + Value *V = Builder.CreateBinOp((Instruction::BinaryOps)Opc, LHS, RHS); return CastToType(Instruction::IntToPtr, V, ConvertType(TREE_TYPE(exp))); } @@ -3326,7 +3321,7 @@ RHS = Builder.CreateICmpNE(RHS, Constant::getNullValue(RHS->getType()), "toBool"); - Value *Res = Builder.CreateBinOp((Instruction::BinaryOps)Opc, LHS, RHS,"tmp"); + Value *Res = Builder.CreateBinOp((Instruction::BinaryOps)Opc, LHS, RHS); return CastToType(Instruction::ZExt, Res, ConvertType(TREE_TYPE(exp))); } @@ -3342,7 +3337,7 @@ RHS = Builder.CreateIntCast(RHS, LHS->getType(), false, (RHS->getName()+".cast").c_str()); - return Builder.CreateBinOp((Instruction::BinaryOps)Opc, LHS, RHS, "tmp"); + return Builder.CreateBinOp((Instruction::BinaryOps)Opc, LHS, RHS); } Value *TreeToLLVM::EmitRotateOp(tree exp, unsigned Opc1, unsigned Opc2) { @@ -3356,13 +3351,12 @@ ConstantInt::get(In->getType(), In->getType()->getPrimitiveSizeInBits()); // Do the two shifts. - Value *V1 = Builder.CreateBinOp((Instruction::BinaryOps)Opc1, In, Amt, "tmp"); - Value *OtherShift = Builder.CreateSub(TypeSize, Amt, "tmp"); - Value *V2 = Builder.CreateBinOp((Instruction::BinaryOps)Opc2, In, - OtherShift, "tmp"); + Value *V1 = Builder.CreateBinOp((Instruction::BinaryOps)Opc1, In, Amt); + Value *OtherShift = Builder.CreateSub(TypeSize, Amt); + Value *V2 = Builder.CreateBinOp((Instruction::BinaryOps)Opc2, In, OtherShift); // Or the two together to return them. - Value *Merge = Builder.CreateOr(V1, V2, "tmp"); + Value *Merge = Builder.CreateOr(V1, V2); return CastToUIntType(Merge, ConvertType(TREE_TYPE(exp))); } @@ -3387,11 +3381,11 @@ Value *Compare; if (LHS->getType()->isFloatingPoint()) - Compare = Builder.CreateFCmp(FCmpInst::Predicate(FPPred), LHS, RHS, "tmp"); + Compare = Builder.CreateFCmp(FCmpInst::Predicate(FPPred), LHS, RHS); else if TYPE_UNSIGNED(TREE_TYPE(TREE_OPERAND(exp, 0))) - Compare = Builder.CreateICmp(ICmpInst::Predicate(UIPred), LHS, RHS, "tmp"); + Compare = Builder.CreateICmp(ICmpInst::Predicate(UIPred), LHS, RHS); else - Compare = Builder.CreateICmp(ICmpInst::Predicate(SIPred), LHS, RHS, "tmp"); + Compare = Builder.CreateICmp(ICmpInst::Predicate(SIPred), LHS, RHS); return Builder.CreateSelect(Compare, LHS, RHS, TREE_CODE(exp) == MAX_EXPR ? "max" : "min"); @@ -3413,7 +3407,7 @@ // Create an ashr instruction, by the log of the division amount. Value *LHS = Emit(TREE_OPERAND(exp, 0), 0); return Builder.CreateAShr(LHS, ConstantInt::get(LHS->getType(), - Log2_64(IntValue)),"tmp"); + Log2_64(IntValue))); } } @@ -3440,17 +3434,17 @@ // The two possible values for Mod. Value *Rem = Builder.CreateSRem(LHS, RHS, "rem"); - Value *RemPlusRHS = Builder.CreateAdd(Rem, RHS, "tmp"); + Value *RemPlusRHS = Builder.CreateAdd(Rem, RHS); // HaveSameSign: (LHS >= 0) == (RHS >= 0). - Value *LHSIsPositive = Builder.CreateICmpSGE(LHS, Zero, "tmp"); - Value *RHSIsPositive = Builder.CreateICmpSGE(RHS, Zero, "tmp"); - Value *HaveSameSign = Builder.CreateICmpEQ(LHSIsPositive,RHSIsPositive,"tmp"); + Value *LHSIsPositive = Builder.CreateICmpSGE(LHS, Zero); + Value *RHSIsPositive = Builder.CreateICmpSGE(RHS, Zero); + Value *HaveSameSign = Builder.CreateICmpEQ(LHSIsPositive,RHSIsPositive); // RHS exactly divides LHS iff Rem is zero. - Value *RemIsZero = Builder.CreateICmpEQ(Rem, Zero, "tmp"); + Value *RemIsZero = Builder.CreateICmpEQ(Rem, Zero); - Value *SameAsRem = Builder.CreateOr(HaveSameSign, RemIsZero, "tmp"); + Value *SameAsRem = Builder.CreateOr(HaveSameSign, RemIsZero); return Builder.CreateSelect(SameAsRem, Rem, RemPlusRHS, "mod"); } @@ -3482,26 +3476,25 @@ // Quick quiz question: what value is returned for INT_MIN CDiv -1? // Determine the signs of LHS and RHS, and whether they have the same sign. - Value *LHSIsPositive = Builder.CreateICmpSGE(LHS, Zero, "tmp"); - Value *RHSIsPositive = Builder.CreateICmpSGE(RHS, Zero, "tmp"); - Value *HaveSameSign = Builder.CreateICmpEQ(LHSIsPositive, RHSIsPositive, - "tmp"); + Value *LHSIsPositive = Builder.CreateICmpSGE(LHS, Zero); + Value *RHSIsPositive = Builder.CreateICmpSGE(RHS, Zero); + Value *HaveSameSign = Builder.CreateICmpEQ(LHSIsPositive, RHSIsPositive); // Offset equals 1 if LHS and RHS have the same sign and LHS is not zero. - Value *LHSNotZero = Builder.CreateICmpNE(LHS, Zero, "tmp"); - Value *OffsetOne = Builder.CreateAnd(HaveSameSign, LHSNotZero, "tmp"); + Value *LHSNotZero = Builder.CreateICmpNE(LHS, Zero); + Value *OffsetOne = Builder.CreateAnd(HaveSameSign, LHSNotZero); // ... otherwise it is 0. - Value *Offset = Builder.CreateSelect(OffsetOne, One, Zero, "tmp"); + Value *Offset = Builder.CreateSelect(OffsetOne, One, Zero); // Calculate Sign(RHS) ... - Value *SignRHS = Builder.CreateSelect(RHSIsPositive, One, MinusOne, "tmp"); + Value *SignRHS = Builder.CreateSelect(RHSIsPositive, One, MinusOne); // ... and Sign(RHS) * Offset Value *SignedOffset = CastToType(Instruction::SExt, OffsetOne, Ty); - SignedOffset = Builder.CreateAnd(SignRHS, SignedOffset, "tmp"); + SignedOffset = Builder.CreateAnd(SignRHS, SignedOffset); // Return CDiv = (LHS - Sign(RHS) * Offset) Div RHS + Offset. - Value *CDiv = Builder.CreateSub(LHS, SignedOffset, "tmp"); - CDiv = Builder.CreateSDiv(CDiv, RHS, "tmp"); + Value *CDiv = Builder.CreateSub(LHS, SignedOffset); + CDiv = Builder.CreateSDiv(CDiv, RHS); return Builder.CreateAdd(CDiv, Offset, "cdiv"); } @@ -3511,12 +3504,12 @@ // as long as LHS is non-zero. // Offset is 1 if LHS is non-zero, 0 otherwise. - Value *LHSNotZero = Builder.CreateICmpNE(LHS, Zero, "tmp"); - Value *Offset = Builder.CreateSelect(LHSNotZero, One, Zero, "tmp"); + Value *LHSNotZero = Builder.CreateICmpNE(LHS, Zero); + Value *Offset = Builder.CreateSelect(LHSNotZero, One, Zero); // Return CDiv = (LHS - Offset) Div RHS + Offset. - Value *CDiv = Builder.CreateSub(LHS, Offset, "tmp"); - CDiv = Builder.CreateUDiv(CDiv, RHS, "tmp"); + Value *CDiv = Builder.CreateSub(LHS, Offset); + CDiv = Builder.CreateUDiv(CDiv, RHS); return Builder.CreateAdd(CDiv, Offset, "cdiv"); } @@ -3552,28 +3545,27 @@ // Quick quiz question: what value is returned for INT_MIN RDiv -1? // Determine the signs of LHS and RHS, and whether they have the same sign. - Value *LHSIsPositive = Builder.CreateICmpSGE(LHS, Zero, "tmp"); - Value *RHSIsPositive = Builder.CreateICmpSGE(RHS, Zero, "tmp"); - Value *HaveSameSign = Builder.CreateICmpEQ(LHSIsPositive, RHSIsPositive, - "tmp"); + Value *LHSIsPositive = Builder.CreateICmpSGE(LHS, Zero); + Value *RHSIsPositive = Builder.CreateICmpSGE(RHS, Zero); + Value *HaveSameSign = Builder.CreateICmpEQ(LHSIsPositive, RHSIsPositive); // Calculate |LHS| ... - Value *MinusLHS = Builder.CreateNeg(LHS, "tmp"); + Value *MinusLHS = Builder.CreateNeg(LHS); Value *AbsLHS = Builder.CreateSelect(LHSIsPositive, LHS, MinusLHS, (LHS->getNameStr()+".abs").c_str()); // ... and |RHS| - Value *MinusRHS = Builder.CreateNeg(RHS, "tmp"); + Value *MinusRHS = Builder.CreateNeg(RHS); Value *AbsRHS = Builder.CreateSelect(RHSIsPositive, RHS, MinusRHS, (RHS->getNameStr()+".abs").c_str()); // Calculate AbsRDiv = (|LHS| + (|RHS| UDiv 2)) UDiv |RHS|. - Value *HalfAbsRHS = Builder.CreateUDiv(AbsRHS, Two, "tmp"); - Value *Numerator = Builder.CreateAdd(AbsLHS, HalfAbsRHS, "tmp"); - Value *AbsRDiv = Builder.CreateUDiv(Numerator, AbsRHS, "tmp"); + Value *HalfAbsRHS = Builder.CreateUDiv(AbsRHS, Two); + Value *Numerator = Builder.CreateAdd(AbsLHS, HalfAbsRHS); + Value *AbsRDiv = Builder.CreateUDiv(Numerator, AbsRHS); // Return AbsRDiv or -AbsRDiv according to whether LHS and RHS have the // same sign or not. - Value *MinusAbsRDiv = Builder.CreateNeg(AbsRDiv, "tmp"); + Value *MinusAbsRDiv = Builder.CreateNeg(AbsRDiv); return Builder.CreateSelect(HaveSameSign, AbsRDiv, MinusAbsRDiv, "rdiv"); } @@ -3587,18 +3579,18 @@ // if it occurred. // Usually the numerator is LHS + (RHS Div 2); calculate this. - Value *HalfRHS = Builder.CreateUDiv(RHS, Two, "tmp"); - Value *Numerator = Builder.CreateAdd(LHS, HalfRHS, "tmp"); + Value *HalfRHS = Builder.CreateUDiv(RHS, Two); + Value *Numerator = Builder.CreateAdd(LHS, HalfRHS); // Did the calculation overflow? - Value *Overflowed = Builder.CreateICmpULT(Numerator, HalfRHS, "tmp"); + Value *Overflowed = Builder.CreateICmpULT(Numerator, HalfRHS); // If so, use (LHS + (RHS Div 2)) - RHS for the numerator instead. - Value *AltNumerator = Builder.CreateSub(Numerator, RHS, "tmp"); - Numerator = Builder.CreateSelect(Overflowed, AltNumerator, Numerator, "tmp"); + Value *AltNumerator = Builder.CreateSub(Numerator, RHS); + Numerator = Builder.CreateSelect(Overflowed, AltNumerator, Numerator); // Quotient = Numerator / RHS. - Value *Quotient = Builder.CreateUDiv(Numerator, RHS, "tmp"); + Value *Quotient = Builder.CreateUDiv(Numerator, RHS); // Return Quotient unless we overflowed, in which case return Quotient + 1. return Builder.CreateAdd(Quotient, CastToUIntType(Overflowed, Ty), "rdiv"); @@ -3673,7 +3665,7 @@ const char *Name = extractRegisterName(decl); InlineAsm *IA = InlineAsm::get(FTy, "", "={"+std::string(Name)+"}", false); - CallInst *Call = Builder.CreateCall(IA, "tmp"); + CallInst *Call = Builder.CreateCall(IA); Call->setDoesNotThrow(); return Call; } @@ -4021,8 +4013,7 @@ TySize == 32 || TySize == 64) { LLVMTy = IntegerType::get(TySize); Op = Builder.CreateLoad(BitCastToType(LV.Ptr, - PointerType::getUnqual(LLVMTy)), - "tmp"); + PointerType::getUnqual(LLVMTy))); } else { // Otherwise, emit our value as a lvalue and let the codegen deal with // it. @@ -4171,8 +4162,7 @@ for (unsigned i = 0, e = Ops.size(); i != e; ++i) Result = Builder.CreateInsertElement(Result, Ops[i], - ConstantInt::get(Type::Int32Ty, i), - "tmp"); + ConstantInt::get(Type::Int32Ty, i)); return Result; } @@ -4221,8 +4211,7 @@ va_end(VA); // Turn this into the appropriate shuffle operation. - return Builder.CreateShuffleVector(InVec1, InVec2, ConstantVector::get(Idxs), - "tmp"); + return Builder.CreateShuffleVector(InVec1, InVec2, ConstantVector::get(Idxs)); } //===----------------------------------------------------------------------===// @@ -4379,7 +4368,7 @@ Value *Amt = Emit(TREE_VALUE(TREE_OPERAND(exp, 1)), 0); EmitBuiltinUnaryIntOp(Amt, Result, Intrinsic::ctpop); Result = Builder.CreateBinOp(Instruction::And, Result, - ConstantInt::get(Result->getType(), 1), "tmp"); + ConstantInt::get(Result->getType(), 1)); return true; } case BUILT_IN_POPCOUNT: // These GCC builtins always return int. @@ -4422,19 +4411,18 @@ // the ffs, but should ignore the return type of ffs. Value *Amt = Emit(TREE_VALUE(TREE_OPERAND(exp, 1)), 0); EmitBuiltinUnaryIntOp(Amt, Result, Intrinsic::cttz); - Result = Builder.CreateAdd(Result, ConstantInt::get(Result->getType(), 1), - "tmp"); + Result = Builder.CreateAdd(Result, ConstantInt::get(Result->getType(), 1)); Value *Cond = - Builder.CreateICmpEQ(Amt, Constant::getNullValue(Amt->getType()), "tmp"); + Builder.CreateICmpEQ(Amt, Constant::getNullValue(Amt->getType())); Result = Builder.CreateSelect(Cond, Constant::getNullValue(Result->getType()), - Result, "tmp"); + Result); return true; } case BUILT_IN_FLT_ROUNDS: { - Result = Builder.CreateCall(Intrinsic::getDeclaration(TheModule, - Intrinsic::flt_rounds), - "tmp"); + Result = + Builder.CreateCall(Intrinsic::getDeclaration(TheModule, + Intrinsic::flt_rounds)); Result = BitCastToType(Result, ConvertType(TREE_TYPE(exp))); return true; } @@ -4876,7 +4864,7 @@ // most intrinsics, but is needed for ctpop, cttz, ctlz. const Type *Ty = InVal->getType(); Result = Builder.CreateCall(Intrinsic::getDeclaration(TheModule, Id, &Ty, 1), - InVal, "tmp"); + InVal); return true; } @@ -4896,7 +4884,7 @@ return Builder.CreateCall(cast( TheModule->getOrInsertFunction(Name, Amt->getType(), Amt->getType(), NULL)), - Amt, "tmp"); + Amt); } Value *TreeToLLVM::EmitBuiltinSQRT(tree exp) { @@ -4906,7 +4894,7 @@ return Builder.CreateCall(Intrinsic::getDeclaration(TheModule, Intrinsic::sqrt, &Ty, 1), - Amt, "tmp"); + Amt); } Value *TreeToLLVM::EmitBuiltinPOWI(tree exp) { @@ -4924,7 +4912,7 @@ Args.push_back(Pow); return Builder.CreateCall(Intrinsic::getDeclaration(TheModule, Intrinsic::powi, &Ty, 1), - Args.begin(), Args.end(), "tmp"); + Args.begin(), Args.end()); } @@ -5069,8 +5057,7 @@ Intrinsic::ID IID = !isFrame ? Intrinsic::returnaddress : Intrinsic::frameaddress; - Result = Builder.CreateCall(Intrinsic::getDeclaration(TheModule, IID), - Level, "tmp"); + Result = Builder.CreateCall(Intrinsic::getDeclaration(TheModule, IID), Level); Result = BitCastToType(Result, ConvertType(TREE_TYPE(exp))); return true; } @@ -5114,8 +5101,7 @@ return false; Result = Builder.CreateCall(Intrinsic::getDeclaration(TheModule, - Intrinsic::stacksave), - "tmp"); + Intrinsic::stacksave)); return true; } @@ -5205,7 +5191,7 @@ Value *Offset = Emit(TREE_VALUE(arglist), 0); Value *Handler = Emit(TREE_VALUE(TREE_CHAIN(arglist)), 0); - Offset = Builder.CreateIntCast(Offset, Type::Int32Ty, true, "tmp"); + Offset = Builder.CreateIntCast(Offset, Type::Int32Ty, true); Handler = BitCastToType(Handler, PointerType::getUnqual(Type::Int8Ty)); SmallVector Args; @@ -5259,20 +5245,20 @@ Size = ConstantInt::get(Type::Int8Ty, size); Idx = ConstantInt::get(Type::Int32Ty, rnum); - Builder.CreateStore(Size, Builder.CreateGEP(Addr, Idx, "tmp"), false); + Builder.CreateStore(Size, Builder.CreateGEP(Addr, Idx), false); } } if (!wrote_return_column) { Size = ConstantInt::get(Type::Int8Ty, GET_MODE_SIZE (Pmode)); Idx = ConstantInt::get(Type::Int32Ty, DWARF_FRAME_RETURN_COLUMN); - Builder.CreateStore(Size, Builder.CreateGEP(Addr, Idx, "tmp"), false); + Builder.CreateStore(Size, Builder.CreateGEP(Addr, Idx), false); } #ifdef DWARF_ALT_FRAME_RETURN_COLUMN Size = ConstantInt::get(Type::Int8Ty, GET_MODE_SIZE (Pmode)); Idx = ConstantInt::get(Type::Int32Ty, DWARF_ALT_FRAME_RETURN_COLUMN); - Builder.CreateStore(Size, Builder.CreateGEP(Addr, Idx, "tmp"), false); + Builder.CreateStore(Size, Builder.CreateGEP(Addr, Idx), false); #endif #endif /* DWARF2_UNWIND_INFO */ @@ -5312,7 +5298,7 @@ return false; Value *Amt = Emit(TREE_VALUE(arglist), 0); Amt = CastToSIntType(Amt, Type::Int32Ty); - Result = Builder.CreateAlloca(Type::Int8Ty, Amt, "tmp"); + Result = Builder.CreateAlloca(Type::Int8Ty, Amt); return true; } @@ -5493,30 +5479,30 @@ DSTi = Builder.CreateSub(LHSi, RHSi, "tmpi"); break; case MULT_EXPR: { // (a+ib) * (c+id) = (ac-bd) + i(ad+cb) - Value *Tmp1 = Builder.CreateMul(LHSr, RHSr, "tmp"); // a*c - Value *Tmp2 = Builder.CreateMul(LHSi, RHSi, "tmp"); // b*d - DSTr = Builder.CreateSub(Tmp1, Tmp2, "tmp"); // ac-bd - - Value *Tmp3 = Builder.CreateMul(LHSr, RHSi, "tmp"); // a*d - Value *Tmp4 = Builder.CreateMul(RHSr, LHSi, "tmp"); // c*b - DSTi = Builder.CreateAdd(Tmp3, Tmp4, "tmp"); // ad+cb + Value *Tmp1 = Builder.CreateMul(LHSr, RHSr); // a*c + Value *Tmp2 = Builder.CreateMul(LHSi, RHSi); // b*d + DSTr = Builder.CreateSub(Tmp1, Tmp2); // ac-bd + + Value *Tmp3 = Builder.CreateMul(LHSr, RHSi); // a*d + Value *Tmp4 = Builder.CreateMul(RHSr, LHSi); // c*b + DSTi = Builder.CreateAdd(Tmp3, Tmp4); // ad+cb break; } case RDIV_EXPR: { // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) - Value *Tmp1 = Builder.CreateMul(LHSr, RHSr, "tmp"); // a*c - Value *Tmp2 = Builder.CreateMul(LHSi, RHSi, "tmp"); // b*d - Value *Tmp3 = Builder.CreateAdd(Tmp1, Tmp2, "tmp"); // ac+bd - - Value *Tmp4 = Builder.CreateMul(RHSr, RHSr, "tmp"); // c*c - Value *Tmp5 = Builder.CreateMul(RHSi, RHSi, "tmp"); // d*d - Value *Tmp6 = Builder.CreateAdd(Tmp4, Tmp5, "tmp"); // cc+dd + Value *Tmp1 = Builder.CreateMul(LHSr, RHSr); // a*c + Value *Tmp2 = Builder.CreateMul(LHSi, RHSi); // b*d + Value *Tmp3 = Builder.CreateAdd(Tmp1, Tmp2); // ac+bd + + Value *Tmp4 = Builder.CreateMul(RHSr, RHSr); // c*c + Value *Tmp5 = Builder.CreateMul(RHSi, RHSi); // d*d + Value *Tmp6 = Builder.CreateAdd(Tmp4, Tmp5); // cc+dd // FIXME: What about integer complex? - DSTr = Builder.CreateFDiv(Tmp3, Tmp6, "tmp"); + DSTr = Builder.CreateFDiv(Tmp3, Tmp6); - Value *Tmp7 = Builder.CreateMul(LHSi, RHSr, "tmp"); // b*c - Value *Tmp8 = Builder.CreateMul(LHSr, RHSi, "tmp"); // a*d - Value *Tmp9 = Builder.CreateSub(Tmp7, Tmp8, "tmp"); // bc-ad - DSTi = Builder.CreateFDiv(Tmp9, Tmp6, "tmp"); + Value *Tmp7 = Builder.CreateMul(LHSi, RHSr); // b*c + Value *Tmp8 = Builder.CreateMul(LHSr, RHSi); // a*d + Value *Tmp9 = Builder.CreateSub(Tmp7, Tmp8); // bc-ad + DSTi = Builder.CreateFDiv(Tmp9, Tmp6); break; } case EQ_EXPR: // (a+ib) == (c+id) = (a == c) & (b == d) @@ -5527,7 +5513,7 @@ DSTr = Builder.CreateICmpEQ(LHSr, RHSr, "tmpr"); DSTi = Builder.CreateICmpEQ(LHSi, RHSi, "tmpi"); } - return Builder.CreateAnd(DSTr, DSTi, "tmp"); + return Builder.CreateAnd(DSTr, DSTi); case NE_EXPR: // (a+ib) != (c+id) = (a != c) | (b != d) if (LHSr->getType()->isFloatingPoint()) { DSTr = Builder.CreateFCmpUNE(LHSr, RHSr, "tmpr"); @@ -5536,7 +5522,7 @@ DSTr = Builder.CreateICmpNE(LHSr, RHSr, "tmpr"); DSTi = Builder.CreateICmpNE(LHSi, RHSi, "tmpi"); } - return Builder.CreateOr(DSTr, DSTi, "tmp"); + return Builder.CreateOr(DSTr, DSTi); } EmitStoreToComplex(*DestLoc, DSTr, DSTi); @@ -5667,7 +5653,7 @@ // If this is an index into an LLVM array, codegen as a GEP. if (isArrayCompatible(ArrayType)) { Value *Idxs[2] = { ConstantInt::get(Type::Int32Ty, 0), IndexVal }; - Value *Ptr = Builder.CreateGEP(ArrayAddr, Idxs, Idxs + 2, "tmp"); + Value *Ptr = Builder.CreateGEP(ArrayAddr, Idxs, Idxs + 2); return BitCastToType(Ptr, PointerType::getUnqual(ConvertType(TREE_TYPE(exp)))); } @@ -5676,7 +5662,7 @@ if (isSequentialCompatible(ArrayType)) { const Type *PtrElementTy = PointerType::getUnqual(ConvertType(ElementType)); ArrayAddr = BitCastToType(ArrayAddr, PtrElementTy); - Value *Ptr = Builder.CreateGEP(ArrayAddr, IndexVal, "tmp"); + Value *Ptr = Builder.CreateGEP(ArrayAddr, IndexVal); return BitCastToType(Ptr, PointerType::getUnqual(ConvertType(TREE_TYPE(exp)))); } @@ -5687,12 +5673,12 @@ ArrayAddr = BitCastToType(ArrayAddr, PointerType::getUnqual(Type::Int8Ty)); if (VOID_TYPE_P(TREE_TYPE(ArrayType))) - return Builder.CreateGEP(ArrayAddr, IndexVal, "tmp"); + return Builder.CreateGEP(ArrayAddr, IndexVal); Value *TypeSize = Emit(array_ref_element_size(exp), 0); TypeSize = CastToUIntType(TypeSize, IntPtrTy); - IndexVal = Builder.CreateMul(IndexVal, TypeSize, "tmp"); - Value *Ptr = Builder.CreateGEP(ArrayAddr, IndexVal, "tmp"); + IndexVal = Builder.CreateMul(IndexVal, TypeSize); + Value *Ptr = Builder.CreateGEP(ArrayAddr, IndexVal); return BitCastToType(Ptr, PointerType::getUnqual(ConvertType(TREE_TYPE(exp)))); } @@ -5752,7 +5738,7 @@ unsigned int MemberIndex = GetFieldIndex(FieldDecl); assert(MemberIndex < StructTy->getNumContainedTypes() && "Field Idx out of range!"); - FieldPtr = Builder.CreateStructGEP(StructAddrLV.Ptr, MemberIndex, "tmp"); + FieldPtr = Builder.CreateStructGEP(StructAddrLV.Ptr, MemberIndex); // Now that we did an offset from the start of the struct, subtract off // the offset from BitStart. @@ -5769,13 +5755,13 @@ unsigned ByteOffset = BitStart/8; if (ByteOffset > 0) { Offset = Builder.CreateAdd(Offset, - ConstantInt::get(Offset->getType(), ByteOffset), "tmp"); + ConstantInt::get(Offset->getType(), ByteOffset)); BitStart -= ByteOffset*8; } Value *Ptr = CastToType(Instruction::PtrToInt, StructAddrLV.Ptr, Offset->getType()); - Ptr = Builder.CreateAdd(Ptr, Offset, "tmp"); + Ptr = Builder.CreateAdd(Ptr, Offset); FieldPtr = CastToType(Instruction::IntToPtr, Ptr, PointerType::getUnqual(FieldTy)); } @@ -5846,7 +5832,7 @@ Constant *Offset = ConstantInt::get(TD.getIntPtrType(), ByteOffset); FieldPtr = CastToType(Instruction::PtrToInt, FieldPtr, Offset->getType()); - FieldPtr = Builder.CreateAdd(FieldPtr, Offset, "tmp"); + FieldPtr = Builder.CreateAdd(FieldPtr, Offset); FieldPtr = CastToType(Instruction::IntToPtr, FieldPtr, PointerType::getUnqual(FieldTy)); @@ -5900,8 +5886,7 @@ // than this. e.g. check out when compiling unwind-dw2-fde-darwin.c. Ptr.Ptr = BitCastToType(Ptr.Ptr, PointerType::getUnqual(ValTy)); Ptr.Ptr = Builder.CreateGEP(Ptr.Ptr, - ConstantInt::get(Type::Int32Ty, UnitOffset), - "tmp"); + ConstantInt::get(Type::Int32Ty, UnitOffset)); BitStart -= UnitOffset*ValueSizeInBits; } @@ -5916,7 +5901,7 @@ LValue TreeToLLVM::EmitLV_XXXXPART_EXPR(tree exp, unsigned Idx) { LValue Ptr = EmitLV(TREE_OPERAND(exp, 0)); assert(!Ptr.isBitfield() && "BIT_FIELD_REF operands cannot be bitfields!"); - return LValue(Builder.CreateStructGEP(Ptr.Ptr, Idx, "tmp")); + return LValue(Builder.CreateStructGEP(Ptr.Ptr, Idx)); } LValue TreeToLLVM::EmitLV_VIEW_CONVERT_EXPR(tree exp) { From gohman at apple.com Sat Jun 21 15:17:03 2008 From: gohman at apple.com (Dan Gohman) Date: Sat, 21 Jun 2008 20:17:03 -0000 Subject: [llvm-commits] [llvm] r52592 - in /llvm/trunk/lib: ExecutionEngine/JIT/JITMemoryManager.cpp System/Mutex.cpp Message-ID: <200806212017.m5LKH3IP003490@zion.cs.uiuc.edu> Author: djg Date: Sat Jun 21 15:17:03 2008 New Revision: 52592 URL: http://llvm.org/viewvc/llvm-project?rev=52592&view=rev Log: Use static_cast instead of reinterpret_cast for casting void*. Modified: llvm/trunk/lib/ExecutionEngine/JIT/JITMemoryManager.cpp llvm/trunk/lib/System/Mutex.cpp Modified: llvm/trunk/lib/ExecutionEngine/JIT/JITMemoryManager.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/JIT/JITMemoryManager.cpp?rev=52592&r1=52591&r2=52592&view=diff ============================================================================== --- llvm/trunk/lib/ExecutionEngine/JIT/JITMemoryManager.cpp (original) +++ llvm/trunk/lib/ExecutionEngine/JIT/JITMemoryManager.cpp Sat Jun 21 15:17:03 2008 @@ -369,7 +369,7 @@ // Allocate a 16M block of memory for functions. sys::MemoryBlock MemBlock = getNewMemoryBlock(16 << 20); - unsigned char *MemBase = reinterpret_cast(MemBlock.base()); + unsigned char *MemBase = static_cast(MemBlock.base()); // Allocate stubs backwards from the base, allocate functions forward // from the base. Modified: llvm/trunk/lib/System/Mutex.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/System/Mutex.cpp?rev=52592&r1=52591&r2=52592&view=diff ============================================================================== --- llvm/trunk/lib/System/Mutex.cpp (original) +++ llvm/trunk/lib/System/Mutex.cpp Sat Jun 21 15:17:03 2008 @@ -98,7 +98,7 @@ { if (pthread_enabled) { - pthread_mutex_t* mutex = reinterpret_cast(data_); + pthread_mutex_t* mutex = static_cast(data_); assert(mutex != 0); pthread_mutex_destroy(mutex); assert(mutex != 0); @@ -110,7 +110,7 @@ { if (pthread_enabled) { - pthread_mutex_t* mutex = reinterpret_cast(data_); + pthread_mutex_t* mutex = static_cast(data_); assert(mutex != 0); int errorcode = pthread_mutex_lock(mutex); @@ -124,7 +124,7 @@ { if (pthread_enabled) { - pthread_mutex_t* mutex = reinterpret_cast(data_); + pthread_mutex_t* mutex = static_cast(data_); assert(mutex != 0); int errorcode = pthread_mutex_unlock(mutex); @@ -138,7 +138,7 @@ { if (pthread_enabled) { - pthread_mutex_t* mutex = reinterpret_cast(data_); + pthread_mutex_t* mutex = static_cast(data_); assert(mutex != 0); int errorcode = pthread_mutex_trylock(mutex); From gohman at apple.com Sat Jun 21 15:21:19 2008 From: gohman at apple.com (Dan Gohman) Date: Sat, 21 Jun 2008 20:21:19 -0000 Subject: [llvm-commits] [llvm] r52594 - in /llvm/trunk/lib/Target: Alpha/AlphaISelLowering.cpp PowerPC/PPCISelLowering.cpp Sparc/SparcISelLowering.cpp Message-ID: <200806212021.m5LKLKMi003686@zion.cs.uiuc.edu> Author: djg Date: Sat Jun 21 15:21:19 2008 New Revision: 52594 URL: http://llvm.org/viewvc/llvm-project?rev=52594&view=rev Log: Use MachineBasicBlock::transferSuccessors. Modified: llvm/trunk/lib/Target/Alpha/AlphaISelLowering.cpp llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp Modified: llvm/trunk/lib/Target/Alpha/AlphaISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Alpha/AlphaISelLowering.cpp?rev=52594&r1=52593&r2=52594&view=diff ============================================================================== --- llvm/trunk/lib/Target/Alpha/AlphaISelLowering.cpp (original) +++ llvm/trunk/lib/Target/Alpha/AlphaISelLowering.cpp Sat Jun 21 15:21:19 2008 @@ -662,11 +662,7 @@ MachineBasicBlock *llscMBB = new MachineBasicBlock(LLVM_BB); MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB); - for(MachineBasicBlock::succ_iterator i = thisMBB->succ_begin(), - e = thisMBB->succ_end(); i != e; ++i) - sinkMBB->addSuccessor(*i); - while(!thisMBB->succ_empty()) - thisMBB->removeSuccessor(thisMBB->succ_begin()); + sinkMBB->transferSuccessors(thisMBB); MachineFunction *F = BB->getParent(); F->getBasicBlockList().insert(It, llscMBB); Modified: llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp?rev=52594&r1=52593&r2=52594&view=diff ============================================================================== --- llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp (original) +++ llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp Sat Jun 21 15:21:19 2008 @@ -4018,15 +4018,10 @@ MachineFunction *F = BB->getParent(); F->getBasicBlockList().insert(It, copy0MBB); F->getBasicBlockList().insert(It, sinkMBB); - // Update machine-CFG edges by first adding all successors of the current + // Update machine-CFG edges by transferring all successors of the current // block to the new block which will contain the Phi node for the select. - for(MachineBasicBlock::succ_iterator i = BB->succ_begin(), - e = BB->succ_end(); i != e; ++i) - sinkMBB->addSuccessor(*i); - // Next, remove all successors of the current block, and add the true - // and fallthrough blocks as its successors. - while(!BB->succ_empty()) - BB->removeSuccessor(BB->succ_begin()); + sinkMBB->transferSuccessors(BB); + // Next, add the true and fallthrough blocks as its successors. BB->addSuccessor(copy0MBB); BB->addSuccessor(sinkMBB); Modified: llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp?rev=52594&r1=52593&r2=52594&view=diff ============================================================================== --- llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp (original) +++ llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp Sat Jun 21 15:21:19 2008 @@ -920,15 +920,10 @@ MachineFunction *F = BB->getParent(); F->getBasicBlockList().insert(It, copy0MBB); F->getBasicBlockList().insert(It, sinkMBB); - // Update machine-CFG edges by first adding all successors of the current + // Update machine-CFG edges by transferring all successors of the current // block to the new block which will contain the Phi node for the select. - for(MachineBasicBlock::succ_iterator i = BB->succ_begin(), - e = BB->succ_end(); i != e; ++i) - sinkMBB->addSuccessor(*i); - // Next, remove all successors of the current block, and add the true - // and fallthrough blocks as its successors. - while(!BB->succ_empty()) - BB->removeSuccessor(BB->succ_begin()); + sinkMBB->transferSuccessors(BB); + // Next, add the true and fallthrough blocks as its successors. BB->addSuccessor(copy0MBB); BB->addSuccessor(sinkMBB); From baldrick at free.fr Sat Jun 21 15:22:59 2008 From: baldrick at free.fr (Duncan Sands) Date: Sat, 21 Jun 2008 20:22:59 -0000 Subject: [llvm-commits] [llvm] r52595 - /llvm/trunk/test/lib/llvm.exp Message-ID: <200806212022.m5LKMx9N003757@zion.cs.uiuc.edu> Author: baldrick Date: Sat Jun 21 15:22:58 2008 New Revision: 52595 URL: http://llvm.org/viewvc/llvm-project?rev=52595&view=rev Log: Turn off llvm-gcc warnings when running "make check". Modified: llvm/trunk/test/lib/llvm.exp Modified: llvm/trunk/test/lib/llvm.exp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/lib/llvm.exp?rev=52595&r1=52594&r2=52595&view=diff ============================================================================== --- llvm/trunk/test/lib/llvm.exp (original) +++ llvm/trunk/test/lib/llvm.exp Sat Jun 21 15:22:58 2008 @@ -57,9 +57,9 @@ #replace %prcontext with prcontext.tcl (Must replace before %p) regsub -all {%prcontext} $new_line $prcontext new_line #replace %llvmgcc with actual path to llvmgcc - regsub -all {%llvmgcc} $new_line "$llvmgcc -emit-llvm" new_line + regsub -all {%llvmgcc} $new_line "$llvmgcc -emit-llvm -w" new_line #replace %llvmgxx with actual path to llvmg++ - regsub -all {%llvmgxx} $new_line "$llvmgxx -emit-llvm" new_line + regsub -all {%llvmgxx} $new_line "$llvmgxx -emit-llvm -w" new_line #replace %compile_cxx with C++ compilation command regsub -all {%compile_cxx} $new_line "$compile_cxx" new_line #replace %compile_c with C compilation command From baldrick at free.fr Sat Jun 21 15:26:51 2008 From: baldrick at free.fr (Duncan Sands) Date: Sat, 21 Jun 2008 20:26:51 -0000 Subject: [llvm-commits] [llvm] r52596 - /llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll Message-ID: <200806212026.m5LKQpZ6003904@zion.cs.uiuc.edu> Author: baldrick Date: Sat Jun 21 15:26:50 2008 New Revision: 52596 URL: http://llvm.org/viewvc/llvm-project?rev=52596&view=rev Log: This file is empty. Removed: llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll Removed: llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/DeadArgElim/multdeadretval.ll?rev=52595&view=auto ============================================================================== (empty) From gohman at apple.com Sat Jun 21 17:00:55 2008 From: gohman at apple.com (Dan Gohman) Date: Sat, 21 Jun 2008 22:00:55 -0000 Subject: [llvm-commits] [llvm] r52600 - in /llvm/trunk/lib: CodeGen/DwarfWriter.cpp ExecutionEngine/JIT/JITDwarfEmitter.cpp Message-ID: <200806212200.m5LM0tqs007302@zion.cs.uiuc.edu> Author: djg Date: Sat Jun 21 17:00:54 2008 New Revision: 52600 URL: http://llvm.org/viewvc/llvm-project?rev=52600&view=rev Log: Use back() instead of [size()-1]. Modified: llvm/trunk/lib/CodeGen/DwarfWriter.cpp llvm/trunk/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp Modified: llvm/trunk/lib/CodeGen/DwarfWriter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/DwarfWriter.cpp?rev=52600&r1=52599&r2=52600&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/DwarfWriter.cpp (original) +++ llvm/trunk/lib/CodeGen/DwarfWriter.cpp Sat Jun 21 17:00:54 2008 @@ -3304,7 +3304,7 @@ // Try to merge with the previous call-site. if (PreviousIsInvoke) { - CallSiteEntry &Prev = CallSites[CallSites.size()-1]; + CallSiteEntry &Prev = CallSites.back(); if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { // Extend the range of the previous entry. Prev.EndLabel = Site.EndLabel; Modified: llvm/trunk/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp?rev=52600&r1=52599&r2=52600&view=diff ============================================================================== --- llvm/trunk/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp (original) +++ llvm/trunk/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp Sat Jun 21 17:00:54 2008 @@ -364,7 +364,7 @@ // Try to merge with the previous call-site. if (CallSites.size()) { - CallSiteEntry &Prev = CallSites[CallSites.size()-1]; + CallSiteEntry &Prev = CallSites.back(); if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { // Extend the range of the previous entry. Prev.EndLabel = Site.EndLabel; @@ -979,7 +979,7 @@ // Try to merge with the previous call-site. if (CallSites.size()) { - CallSiteEntry &Prev = CallSites[CallSites.size()-1]; + CallSiteEntry &Prev = CallSites.back(); if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { // Extend the range of the previous entry. Prev.EndLabel = Site.EndLabel; From gohman at apple.com Sat Jun 21 17:02:15 2008 From: gohman at apple.com (Dan Gohman) Date: Sat, 21 Jun 2008 22:02:15 -0000 Subject: [llvm-commits] [llvm] r52601 - /llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Message-ID: <200806212202.m5LM2FxV007352@zion.cs.uiuc.edu> Author: djg Date: Sat Jun 21 17:02:15 2008 New Revision: 52601 URL: http://llvm.org/viewvc/llvm-project?rev=52601&view=rev Log: Use clear() to zero an existing APInt. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=52601&r1=52600&r2=52601&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Sat Jun 21 17:02:15 2008 @@ -1406,7 +1406,7 @@ case ISD::CTPOP: { unsigned LowBits = Log2_32(BitWidth)+1; KnownZero = APInt::getHighBitsSet(BitWidth, BitWidth - LowBits); - KnownOne = APInt(BitWidth, 0); + KnownOne.clear(); return; } case ISD::LOAD: { From gohman at apple.com Sat Jun 21 17:03:13 2008 From: gohman at apple.com (Dan Gohman) Date: Sat, 21 Jun 2008 22:03:13 -0000 Subject: [llvm-commits] [llvm] r52602 - /llvm/trunk/lib/Support/APInt.cpp Message-ID: <200806212203.m5LM3Dut007388@zion.cs.uiuc.edu> Author: djg Date: Sat Jun 21 17:03:12 2008 New Revision: 52602 URL: http://llvm.org/viewvc/llvm-project?rev=52602&view=rev Log: Avoid creating a redundant zero APInt. Modified: llvm/trunk/lib/Support/APInt.cpp Modified: llvm/trunk/lib/Support/APInt.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/APInt.cpp?rev=52602&r1=52601&r2=52602&view=diff ============================================================================== --- llvm/trunk/lib/Support/APInt.cpp (original) +++ llvm/trunk/lib/Support/APInt.cpp Sat Jun 21 17:03:12 2008 @@ -2048,7 +2048,7 @@ result = "-"; insert_at = 1; } - if (tmp == APInt(tmp.getBitWidth(), 0)) + if (tmp == zero) result = "0"; else while (tmp.ne(zero)) { APInt APdigit(1,0); From gohman at apple.com Sat Jun 21 17:05:24 2008 From: gohman at apple.com (Dan Gohman) Date: Sat, 21 Jun 2008 22:05:24 -0000 Subject: [llvm-commits] [llvm] r52603 - /llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp Message-ID: <200806212205.m5LM5OBR007460@zion.cs.uiuc.edu> Author: djg Date: Sat Jun 21 17:05:24 2008 New Revision: 52603 URL: http://llvm.org/viewvc/llvm-project?rev=52603&view=rev Log: canClobberPhysRegDefs shouldn't called without checking hasPhysRegDefs; check this with an assert. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp?rev=52603&r1=52602&r2=52603&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp Sat Jun 21 17:05:24 2008 @@ -1572,15 +1572,14 @@ } /// canClobberPhysRegDefs - True if SU would clobber one of SuccSU's -/// physical register def. +/// physical register defs. static bool canClobberPhysRegDefs(SUnit *SuccSU, SUnit *SU, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI) { SDNode *N = SuccSU->Node; unsigned NumDefs = TII->get(N->getTargetOpcode()).getNumDefs(); const unsigned *ImpDefs = TII->get(N->getTargetOpcode()).getImplicitDefs(); - if (!ImpDefs) - return false; + assert(ImpDefs && "Caller should check hasPhysRegDefs"); const unsigned *SUImpDefs = TII->get(SU->Node->getTargetOpcode()).getImplicitDefs(); if (!SUImpDefs) From gohman at apple.com Sat Jun 21 17:06:07 2008 From: gohman at apple.com (Dan Gohman) Date: Sat, 21 Jun 2008 22:06:07 -0000 Subject: [llvm-commits] [llvm] r52604 - /llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Message-ID: <200806212206.m5LM67t0007485@zion.cs.uiuc.edu> Author: djg Date: Sat Jun 21 17:06:07 2008 New Revision: 52604 URL: http://llvm.org/viewvc/llvm-project?rev=52604&view=rev Log: Simplify some getNode calls. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=52604&r1=52603&r2=52604&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Sat Jun 21 17:06:07 2008 @@ -1058,8 +1058,7 @@ // canonicalize constant to RHS. if (N0C && !N1C) { - SDOperand Ops[] = { N1, N0 }; - return DAG.getNode(ISD::ADDC, N->getVTList(), Ops, 2); + return DAG.getNode(ISD::ADDC, N->getVTList(), N1, N0); } // fold (addc x, 0) -> x + no carry out @@ -1095,14 +1094,12 @@ // canonicalize constant to RHS if (N0C && !N1C) { - SDOperand Ops[] = { N1, N0, CarryIn }; - return DAG.getNode(ISD::ADDE, N->getVTList(), Ops, 3); + return DAG.getNode(ISD::ADDE, N->getVTList(), N1, N0, CarryIn); } // fold (adde x, y, false) -> (addc x, y) if (CarryIn.getOpcode() == ISD::CARRY_FALSE) { - SDOperand Ops[] = { N1, N0 }; - return DAG.getNode(ISD::ADDC, N->getVTList(), Ops, 2); + return DAG.getNode(ISD::ADDC, N->getVTList(), N1, N0); } return SDOperand(); From gohman at apple.com Sat Jun 21 17:06:55 2008 From: gohman at apple.com (Dan Gohman) Date: Sat, 21 Jun 2008 22:06:55 -0000 Subject: [llvm-commits] [llvm] r52605 - /llvm/trunk/lib/VMCore/Core.cpp Message-ID: <200806212206.m5LM6tst007518@zion.cs.uiuc.edu> Author: djg Date: Sat Jun 21 17:06:54 2008 New Revision: 52605 URL: http://llvm.org/viewvc/llvm-project?rev=52605&view=rev Log: Use Function's arg_size() and size() methods. Modified: llvm/trunk/lib/VMCore/Core.cpp Modified: llvm/trunk/lib/VMCore/Core.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Core.cpp?rev=52605&r1=52604&r2=52605&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/Core.cpp (original) +++ llvm/trunk/lib/VMCore/Core.cpp Sat Jun 21 17:06:54 2008 @@ -741,7 +741,7 @@ unsigned LLVMCountParams(LLVMValueRef FnRef) { // This function is strictly redundant to // LLVMCountParamTypes(LLVMGetElementType(LLVMTypeOf(FnRef))) - return unwrap(FnRef)->getArgumentList().size(); + return unwrap(FnRef)->arg_size(); } void LLVMGetParams(LLVMValueRef FnRef, LLVMValueRef *ParamRefs) { @@ -826,7 +826,7 @@ } unsigned LLVMCountBasicBlocks(LLVMValueRef FnRef) { - return unwrap(FnRef)->getBasicBlockList().size(); + return unwrap(FnRef)->size(); } void LLVMGetBasicBlocks(LLVMValueRef FnRef, LLVMBasicBlockRef *BasicBlocksRefs){ From gohman at apple.com Sat Jun 21 17:08:46 2008 From: gohman at apple.com (Dan Gohman) Date: Sat, 21 Jun 2008 22:08:46 -0000 Subject: [llvm-commits] [llvm] r52606 - in /llvm/trunk/lib/Transforms: IPO/LowerSetJmp.cpp IPO/RaiseAllocations.cpp Scalar/ConstantProp.cpp Scalar/GCSE.cpp Utils/CodeExtractor.cpp Utils/InlineFunction.cpp Utils/Local.cpp Message-ID: <200806212208.m5LM8kfh007618@zion.cs.uiuc.edu> Author: djg Date: Sat Jun 21 17:08:46 2008 New Revision: 52606 URL: http://llvm.org/viewvc/llvm-project?rev=52606&view=rev Log: Use Instruction::eraseFromParent(). Modified: llvm/trunk/lib/Transforms/IPO/LowerSetJmp.cpp llvm/trunk/lib/Transforms/IPO/RaiseAllocations.cpp llvm/trunk/lib/Transforms/Scalar/ConstantProp.cpp llvm/trunk/lib/Transforms/Scalar/GCSE.cpp llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp llvm/trunk/lib/Transforms/Utils/Local.cpp Modified: llvm/trunk/lib/Transforms/IPO/LowerSetJmp.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/LowerSetJmp.cpp?rev=52606&r1=52605&r2=52606&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/IPO/LowerSetJmp.cpp (original) +++ llvm/trunk/lib/Transforms/IPO/LowerSetJmp.cpp Sat Jun 21 17:08:46 2008 @@ -440,7 +440,7 @@ // Replace all uses of this instruction with the PHI node created by // the eradication of setjmp. Inst->replaceAllUsesWith(PHI); - Inst->getParent()->getInstList().erase(Inst); + Inst->eraseFromParent(); ++SetJmpsTransformed; } @@ -478,10 +478,10 @@ // Replace the old call inst with the invoke inst and remove the call. CI.replaceAllUsesWith(II); - CI.getParent()->getInstList().erase(&CI); + CI.eraseFromParent(); // The old terminator is useless now that we have the invoke inst. - Term->getParent()->getInstList().erase(Term); + Term->eraseFromParent(); ++CallsTransformed; } Modified: llvm/trunk/lib/Transforms/IPO/RaiseAllocations.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/RaiseAllocations.cpp?rev=52606&r1=52605&r2=52606&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/IPO/RaiseAllocations.cpp (original) +++ llvm/trunk/lib/Transforms/IPO/RaiseAllocations.cpp Sat Jun 21 17:08:46 2008 @@ -177,7 +177,7 @@ BranchInst::Create(II->getNormalDest(), I); // Delete the old call site - MI->getParent()->getInstList().erase(I); + I->eraseFromParent(); Changed = true; ++NumRaised; } Modified: llvm/trunk/lib/Transforms/Scalar/ConstantProp.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ConstantProp.cpp?rev=52606&r1=52605&r2=52606&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/ConstantProp.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/ConstantProp.cpp Sat Jun 21 17:08:46 2008 @@ -79,7 +79,7 @@ // Remove the dead instruction. WorkList.erase(I); - I->getParent()->getInstList().erase(I); + I->eraseFromParent(); // We made a change to the function... Changed = true; Modified: llvm/trunk/lib/Transforms/Scalar/GCSE.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GCSE.cpp?rev=52606&r1=52605&r2=52606&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/GCSE.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/GCSE.cpp Sat Jun 21 17:08:46 2008 @@ -201,5 +201,5 @@ } // Erase the instruction from the program. - I->getParent()->getInstList().erase(I); + I->eraseFromParent(); } Modified: llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp?rev=52606&r1=52605&r2=52606&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp (original) +++ llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp Sat Jun 21 17:08:46 2008 @@ -550,18 +550,18 @@ ReturnInst::Create(Constant::getNullValue(OldFnRetTy), TheSwitch); } - TheSwitch->getParent()->getInstList().erase(TheSwitch); + TheSwitch->eraseFromParent(); break; case 1: // Only a single destination, change the switch into an unconditional // branch. BranchInst::Create(TheSwitch->getSuccessor(1), TheSwitch); - TheSwitch->getParent()->getInstList().erase(TheSwitch); + TheSwitch->eraseFromParent(); break; case 2: BranchInst::Create(TheSwitch->getSuccessor(1), TheSwitch->getSuccessor(2), call, TheSwitch); - TheSwitch->getParent()->getInstList().erase(TheSwitch); + TheSwitch->eraseFromParent(); break; default: // Otherwise, make the default destination of the switch instruction be one Modified: llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp?rev=52606&r1=52605&r2=52606&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp (original) +++ llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp Sat Jun 21 17:08:46 2008 @@ -119,7 +119,7 @@ BranchInst::Create(InvokeDest, UI); // Delete the unwind instruction! - UI->getParent()->getInstList().pop_back(); + UI->eraseFromParent(); // Update any PHI nodes in the exceptional block to indicate that // there is now a new entry in them. @@ -455,10 +455,10 @@ TheCall->replaceAllUsesWith(R->getReturnValue()); } // Since we are now done with the Call/Invoke, we can delete it. - TheCall->getParent()->getInstList().erase(TheCall); + TheCall->eraseFromParent(); // Since we are now done with the return instruction, delete it also. - Returns[0]->getParent()->getInstList().erase(Returns[0]); + Returns[0]->eraseFromParent(); // We are now done with the inlining. return true; Modified: llvm/trunk/lib/Transforms/Utils/Local.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/Local.cpp?rev=52606&r1=52605&r2=52606&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Utils/Local.cpp (original) +++ llvm/trunk/lib/Transforms/Utils/Local.cpp Sat Jun 21 17:08:46 2008 @@ -159,7 +159,7 @@ BranchInst::Create(SI->getSuccessor(1), SI->getSuccessor(0), Cond, SI); // Delete the old switch... - SI->getParent()->getInstList().erase(SI); + SI->eraseFromParent(); return true; } } From eli.friedman at gmail.com Sat Jun 21 18:36:13 2008 From: eli.friedman at gmail.com (Eli Friedman) Date: Sat, 21 Jun 2008 23:36:13 -0000 Subject: [llvm-commits] [llvm] r52608 - in /llvm/trunk: lib/Transforms/Scalar/InstructionCombining.cpp test/Transforms/InstCombine/2008-06-21-CompareMiscomp.ll Message-ID: <200806212336.m5LNaDpN010351@zion.cs.uiuc.edu> Author: efriedma Date: Sat Jun 21 18:36:13 2008 New Revision: 52608 URL: http://llvm.org/viewvc/llvm-project?rev=52608&view=rev Log: Fix for PR2479: correctly optimize expressions like (a > 13) & (a == 15). See also PR1800, which is about the signed case. Added: llvm/trunk/test/Transforms/InstCombine/2008-06-21-CompareMiscomp.ll Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=52608&r1=52607&r2=52608&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Sat Jun 21 18:36:13 2008 @@ -3691,8 +3691,7 @@ case ICmpInst::ICMP_UGT: switch (RHSCC) { default: assert(0 && "Unknown integer condition code!"); - case ICmpInst::ICMP_EQ: // (X u> 13 & X == 15) -> X > 13 - return ReplaceInstUsesWith(I, LHS); + case ICmpInst::ICMP_EQ: // (X u> 13 & X == 15) -> X == 15 case ICmpInst::ICMP_UGT: // (X u> 13 & X u> 15) -> X u> 15 return ReplaceInstUsesWith(I, RHS); case ICmpInst::ICMP_SGT: // (X u> 13 & X s> 15) -> no change Added: llvm/trunk/test/Transforms/InstCombine/2008-06-21-CompareMiscomp.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2008-06-21-CompareMiscomp.ll?rev=52608&view=auto ============================================================================== --- llvm/trunk/test/Transforms/InstCombine/2008-06-21-CompareMiscomp.ll (added) +++ llvm/trunk/test/Transforms/InstCombine/2008-06-21-CompareMiscomp.ll Sat Jun 21 18:36:13 2008 @@ -0,0 +1,11 @@ +; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep {icmp eq i32 %In, 15} +; PR2479 +; (See also PR1800.) + +define i1 @test(i32 %In) { + %c1 = icmp ugt i32 %In, 13 + %c2 = icmp eq i32 %In, 15 + %V = and i1 %c1, %c2 + ret i1 %V +} + From clattner at apple.com Sun Jun 22 00:47:28 2008 From: clattner at apple.com (Chris Lattner) Date: Sat, 21 Jun 2008 22:47:28 -0700 Subject: [llvm-commits] [llvm] r52546 - in /llvm/trunk/lib/CodeGen/SelectionDAG: LegalizeFloatTypes.cpp LegalizeIntegerTypes.cpp LegalizeTypes.cpp LegalizeTypes.h LegalizeVectorTypes.cpp In-Reply-To: <200806201749.m5KHnt8N030894@zion.cs.uiuc.edu> References: <200806201749.m5KHnt8N030894@zion.cs.uiuc.edu> Message-ID: <91BF88C9-98D0-44AF-A21F-B3E6C0C22ED5@apple.com> On Jun 20, 2008, at 10:49 AM, Duncan Sands wrote: > Author: baldrick > Date: Fri Jun 20 12:49:55 2008 > New Revision: 52546 > > URL: http://llvm.org/viewvc/llvm-project?rev=52546&view=rev > Log: > Rename the operation of turning a float type into an > integer of the same type. Before it was "promotion", > but this is confusing because it is quite different > to promotion of integers. Call it "softening" instead, > inspired by "soft float". "soften" is awesome :) -Chris From baldrick at free.fr Sun Jun 22 02:30:11 2008 From: baldrick at free.fr (Duncan Sands) Date: Sun, 22 Jun 2008 09:30:11 +0200 Subject: [llvm-commits] [llvm] r52604 - /llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp In-Reply-To: <200806212206.m5LM67t0007485@zion.cs.uiuc.edu> References: <200806212206.m5LM67t0007485@zion.cs.uiuc.edu> Message-ID: <200806220930.11349.baldrick@free.fr> Hi Dan, > if (N0C && !N1C) { > - SDOperand Ops[] = { N1, N0 }; > - return DAG.getNode(ISD::ADDC, N->getVTList(), Ops, 2); > + return DAG.getNode(ISD::ADDC, N->getVTList(), N1, N0); > } you could drop the braces now that this is only one line. Likewise for the others. Ciao, Duncan. From baldrick at free.fr Sun Jun 22 04:42:18 2008 From: baldrick at free.fr (Duncan Sands) Date: Sun, 22 Jun 2008 09:42:18 -0000 Subject: [llvm-commits] [llvm] r52610 - /llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Message-ID: <200806220942.m5M9gJhd000754@zion.cs.uiuc.edu> Author: baldrick Date: Sun Jun 22 04:42:16 2008 New Revision: 52610 URL: http://llvm.org/viewvc/llvm-project?rev=52610&view=rev Log: Make custom lowering of ADD work correctly. This fixes PR2476; patch by Richard Osborne. The same problem exists for a bunch of other operators, but I'm ignoring this because they will be automagically fixed when the new LegalizeTypes infrastructure lands, since it already solves this problem centrally. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp?rev=52610&r1=52609&r2=52610&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Sun Jun 22 04:42:16 2008 @@ -6374,9 +6374,9 @@ // If the target wants to custom expand this, let them. if (TLI.getOperationAction(Node->getOpcode(), VT) == TargetLowering::Custom) { - Op = TLI.LowerOperation(Op, DAG); - if (Op.Val) { - ExpandOp(Op, Lo, Hi); + SDOperand Result = TLI.LowerOperation(Op, DAG); + if (Result.Val) { + ExpandOp(Result, Lo, Hi); break; } } From sabre at nondot.org Sun Jun 22 12:46:21 2008 From: sabre at nondot.org (Chris Lattner) Date: Sun, 22 Jun 2008 17:46:21 -0000 Subject: [llvm-commits] [llvm] r52611 - in /llvm/trunk: lib/Transforms/Scalar/ScalarReplAggregates.cpp test/Transforms/ScalarRepl/2008-06-22-LargeArray.ll Message-ID: <200806221746.m5MHkMPk019159@zion.cs.uiuc.edu> Author: lattner Date: Sun Jun 22 12:46:21 2008 New Revision: 52611 URL: http://llvm.org/viewvc/llvm-project?rev=52611&view=rev Log: Fix PR2369 by making scalarrepl more careful about promoting structures. Its default threshold is to promote things that are smaller than 128 bytes, which is sane. However, it is not sane to do this for things that turn into 128 *registers*. Add a cap on the number of registers introduced, defaulting to 128/4=32. Added: llvm/trunk/test/Transforms/ScalarRepl/2008-06-22-LargeArray.ll Modified: llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Modified: llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp?rev=52611&r1=52610&r2=52611&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Sun Jun 22 12:46:21 2008 @@ -178,6 +178,14 @@ return Changed; } +/// getNumSAElements - Return the number of elements in the specific struct or +/// array. +static uint64_t getNumSAElements(const Type *T) { + if (const StructType *ST = dyn_cast(T)) + return ST->getNumElements(); + return cast(T)->getNumElements(); +} + // performScalarRepl - This algorithm is a simple worklist driven algorithm, // which runs on all of the malloc/alloca instructions in the function, removing // them if they are only used by getelementptr instructions. @@ -224,7 +232,10 @@ (isa(AI->getAllocatedType()) || isa(AI->getAllocatedType())) && AI->getAllocatedType()->isSized() && - TD.getABITypeSize(AI->getAllocatedType()) < SRThreshold) { + // Do not promote any struct whose size is larger than "128" bytes. + TD.getABITypeSize(AI->getAllocatedType()) < SRThreshold && + // Do not promote any struct into more than "32" separate vars. + getNumSAElements(AI->getAllocatedType()) < SRThreshold/4) { // Check that all of the users of the allocation are capable of being // transformed. switch (isSafeAllocaToScalarRepl(AI)) { @@ -672,11 +683,9 @@ // If this is a memcpy/memmove, emit a GEP of the other element address. Value *OtherElt = 0; if (OtherPtr) { - Value *Idx[2]; - Idx[0] = Zero; - Idx[1] = ConstantInt::get(Type::Int32Ty, i); + Value *Idx[2] = { Zero, ConstantInt::get(Type::Int32Ty, i) }; OtherElt = GetElementPtrInst::Create(OtherPtr, Idx, Idx + 2, - OtherPtr->getNameStr()+"."+utostr(i), + OtherPtr->getNameStr()+"."+utostr(i), MI); } Added: llvm/trunk/test/Transforms/ScalarRepl/2008-06-22-LargeArray.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ScalarRepl/2008-06-22-LargeArray.ll?rev=52611&view=auto ============================================================================== --- llvm/trunk/test/Transforms/ScalarRepl/2008-06-22-LargeArray.ll (added) +++ llvm/trunk/test/Transforms/ScalarRepl/2008-06-22-LargeArray.ll Sun Jun 22 12:46:21 2008 @@ -0,0 +1,18 @@ +; RUN: llvm-as < %s | opt -scalarrepl | llvm-dis | grep {call.*mem} +; PR2369 + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" +target triple = "i386-apple-darwin8" + +define void @memtest1(i8* %dst, i8* %src) nounwind { +entry: + %temp = alloca [100 x i8] ; <[100 x i8]*> [#uses=2] + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + %temp1 = bitcast [100 x i8]* %temp to i8* ; [#uses=1] + call void @llvm.memcpy.i32( i8* %temp1, i8* %src, i32 100, i32 1 ) + %temp3 = bitcast [100 x i8]* %temp to i8* ; [#uses=1] + call void @llvm.memcpy.i32( i8* %dst, i8* %temp3, i32 100, i32 1 ) + ret void +} + +declare void @llvm.memcpy.i32(i8*, i8*, i32, i32) nounwind From clattner at apple.com Sun Jun 22 13:00:51 2008 From: clattner at apple.com (Chris Lattner) Date: Sun, 22 Jun 2008 11:00:51 -0700 Subject: [llvm-commits] [llvm] r51806 - in /llvm/trunk: docs/LangRef.html include/llvm/Constants.h include/llvm/DerivedTypes.h include/llvm/Instructions.h lib/AsmParser/llvmAsmParser.cpp.cvs lib/AsmParser/llvmAsmParser.h.cvs lib/AsmParser/llvmAsmParser.y lib/AsmParser/llvmAsmParser.y.cvs lib/Bitcode/Reader/BitcodeReader.cpp lib/Bitcode/Writer/BitcodeWriter.cpp lib/VMCore/Constants.cpp lib/VMCore/Instructions.cpp lib/VMCore/Type.cpp test/Assembler/insertextractvalue.ll In-Reply-To: <200805310058.m4V0wNwU011642@zion.cs.uiuc.edu> References: <200805310058.m4V0wNwU011642@zion.cs.uiuc.edu> Message-ID: On May 30, 2008, at 5:58 PM, Dan Gohman wrote: > URL: http://llvm.org/viewvc/llvm-project?rev=51806&view=rev > Log: > IR, bitcode reader, bitcode writer, and asmparser changes to > insertvalue and extractvalue to use constant indices instead of > Value* indices. And begin updating LangRef.html. You guys are making awesome progress, some thoughts: Are insertvalue/extractvalue valid as constant expressions? If so, langref should be updated and it would be good to see that they encode into the bc file correctly. If we can *guarantee* that they are always folded away by the constant folding, then I'm fine with saying that they are not allowed as constant exprs. In the insertvalue section, you have this syntax: = insertvalue , , ; yields > but this example: %result = insertvalue {i32, float} %agg, 1, 0 should the example be: %result = insertvalue {i32, float} %agg, i32 1, 0 > +++ llvm/trunk/include/llvm/Constants.h Fri May 30 19:58:22 2008 > public: > // Static methods to construct a ConstantExpr of different kinds. > Note that > @@ -656,6 +657,10 @@ > /// @brief Return true if this is a compare constant expression > bool isCompare() const; > > + /// @brief Return true if this is an insertvalue or extractvalue > expression, > + /// and the getIndices() method may be used. > + bool hasIndices() const; > + > + /// getIndices - Assert that this is an insertvalue or exactvalue > + /// expression and return the list of indices. > + const SmallVector &getIndices() const; Is there ever a case where insert/extract value can't be constant folded? > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/trunk/include/llvm/Instructions.h (original) > +++ llvm/trunk/include/llvm/Instructions.h Fri May 30 19:58:22 2008 > @@ -22,6 +22,7 @@ > #include "llvm/DerivedTypes.h" > #include "llvm/ParameterAttributes.h" > #include "llvm/BasicBlock.h" > +#include "llvm/ADT/SmallVector.h" > > namespace llvm { > > @@ -1518,9 +1519,11 @@ > /// element value from an aggregate value. > /// > class ExtractValueInst : public Instruction { > + SmallVector Indices; The indices of an instruction are fixed when the instruction is created. Would it be reasonable to just make this be a new unsigned[]'d array instead of a smallvector? > @@ -1563,9 +1567,9 @@ > > if (NumIdx > 0) > // This requires that the iterator points to contiguous memory. > - return getIndexedType(Ptr, (Value *const *)&*IdxBegin, NumIdx); > + return getIndexedType(Ptr, (const unsigned *)&*IdxBegin, > NumIdx); Is this cast needed? It seems that it could paper over serious bugs. > @@ -1575,55 +1579,53 @@ > /// Constructors - These two constructors are convenience methods > because one > /// and two index extractvalue instructions are so common. > - ExtractValueInst(Value *Agg, Value *Idx, const std::string &Name > = "", > + ExtractValueInst(Value *Agg, unsigned Idx, const std::string > &Name = "", > Instruction *InsertBefore = 0); > - ExtractValueInst(Value *Agg, Value *Idx, > + ExtractValueInst(Value *Agg, unsigned Idx, > const std::string &Name, BasicBlock *InsertAtEnd); Since the ctors are private, who are they a convenience for? It seems that the ::Create methods are the things that should exist, but extra constructors aren't need. > public: > + // allocate space for exactly two operands > + void *operator new(size_t s) { > + return User::operator new(s, 1); > + } Plz update comment. > @@ -1733,9 +1729,12 @@ > /// value into an aggregate value. > /// > class InsertValueInst : public Instruction { > + SmallVector Indices; The above all applies to InsertValueInst as well. > +++ llvm/trunk/lib/VMCore/Constants.cpp Fri May 30 19:58:22 2008 > @@ -537,15 +537,23 @@ > /// Constants.cpp, and is used behind the scenes to implement > /// extractvalue constant exprs. > class VISIBILITY_HIDDEN ExtractValueConstantExpr : public > ConstantExpr { Can't Extract/InsertValue always be constant folded? If so, there is no reason to be able to represent them. > @@ -718,6 +703,21 @@ > return getOpcode() == Instruction::ICmp || getOpcode() == > Instruction::FCmp; > } > > +bool ConstantExpr::hasIndices() const { > + return getOpcode() == Instruction::ExtractValue || > + getOpcode() == Instruction::InsertValue; > +} > + > +const SmallVector &ConstantExpr::getIndices() const { > + if (const ExtractValueConstantExpr *EVCE = > + dyn_cast(this)) > + return EVCE->Indices; > + if (const InsertValueConstantExpr *IVCE = > + dyn_cast(this)) > + return IVCE->Indices; > + assert(0 && "ConstantExpr does not have indices!"); > +} Eliminating them also allows these methods to go away. If you choose to keep them, please change getindices to be: .. > + return cast(this)->Indices; eliminating the assert(0) > > + assert(OpNo == 0 && "ExtractaValue has only one operand!"); > + const SmallVector Indices = getIndices(); No need to copy the vector here. > > + return > + ConstantExpr::getExtractValue(Op, &Indices[0], Indices.size()); > } > + case Instruction::InsertValue: { > + const SmallVector Indices = getIndices(); likewise. > > + return ConstantExpr::getInsertValue(Ops[0], Ops[1], > + &Indices[0], Indices.size()); > + } > + case Instruction::ExtractValue: { > + const SmallVector Indices = getIndices(); likewise. -Chris -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20080622/bfc04bce/attachment.html From gohman at apple.com Sun Jun 22 14:09:18 2008 From: gohman at apple.com (Dan Gohman) Date: Sun, 22 Jun 2008 19:09:18 -0000 Subject: [llvm-commits] [llvm] r52612 - in /llvm/trunk: include/llvm/Analysis/ScalarEvolutionExpander.h lib/Analysis/ScalarEvolutionExpander.cpp Message-ID: <200806221909.m5MJ9IHx021669@zion.cs.uiuc.edu> Author: djg Date: Sun Jun 22 14:09:18 2008 New Revision: 52612 URL: http://llvm.org/viewvc/llvm-project?rev=52612&view=rev Log: Move a few more SCEVExpander methods out-of-line. Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h?rev=52612&r1=52611&r2=52612&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h (original) +++ llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h Sun Jun 22 14:09:18 2008 @@ -75,11 +75,7 @@ /// expandCodeFor - Insert code to directly compute the specified SCEV /// expression into the program. The inserted code is inserted into the /// specified block. - Value *expandCodeFor(SCEVHandle SH, Instruction *IP) { - // Expand the code for this SCEV. - this->InsertPt = IP; - return expand(SH); - } + Value *expandCodeFor(SCEVHandle SH, Instruction *IP); /// InsertCastOfTo - Insert a cast of V to the specified type, doing what /// we can to share the casts. @@ -96,20 +92,11 @@ return S->getValue(); } - Value *visitTruncateExpr(SCEVTruncateExpr *S) { - Value *V = expand(S->getOperand()); - return CastInst::CreateTruncOrBitCast(V, S->getType(), "tmp.", InsertPt); - } + Value *visitTruncateExpr(SCEVTruncateExpr *S); - Value *visitZeroExtendExpr(SCEVZeroExtendExpr *S) { - Value *V = expand(S->getOperand()); - return CastInst::CreateZExtOrBitCast(V, S->getType(), "tmp.", InsertPt); - } + Value *visitZeroExtendExpr(SCEVZeroExtendExpr *S); - Value *visitSignExtendExpr(SCEVSignExtendExpr *S) { - Value *V = expand(S->getOperand()); - return CastInst::CreateSExtOrBitCast(V, S->getType(), "tmp.", InsertPt); - } + Value *visitSignExtendExpr(SCEVSignExtendExpr *S); Value *visitAddExpr(SCEVAddExpr *S); Modified: llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp?rev=52612&r1=52611&r2=52612&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp (original) +++ llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp Sun Jun 22 14:09:18 2008 @@ -226,6 +226,21 @@ return expand(V); } +Value *SCEVExpander::visitTruncateExpr(SCEVTruncateExpr *S) { + Value *V = expand(S->getOperand()); + return CastInst::createTruncOrBitCast(V, S->getType(), "tmp.", InsertPt); +} + +Value *SCEVExpander::visitZeroExtendExpr(SCEVZeroExtendExpr *S) { + Value *V = expand(S->getOperand()); + return CastInst::createZExtOrBitCast(V, S->getType(), "tmp.", InsertPt); +} + +Value *SCEVExpander::visitSignExtendExpr(SCEVSignExtendExpr *S) { + Value *V = expand(S->getOperand()); + return CastInst::createSExtOrBitCast(V, S->getType(), "tmp.", InsertPt); +} + Value *SCEVExpander::visitSMaxExpr(SCEVSMaxExpr *S) { Value *LHS = expand(S->getOperand(0)); for (unsigned i = 1; i < S->getNumOperands(); ++i) { @@ -246,6 +261,12 @@ return LHS; } +Value *SCEVExpander::expandCodeFor(SCEVHandle SH, Instruction *IP) { + // Expand the code for this SCEV. + this->InsertPt = IP; + return expand(SH); +} + Value *SCEVExpander::expand(SCEV *S) { // Check to see if we already expanded this. std::map::iterator I = InsertedExpressions.find(S); From gohman at apple.com Sun Jun 22 14:21:26 2008 From: gohman at apple.com (Dan Gohman) Date: Sun, 22 Jun 2008 19:21:26 -0000 Subject: [llvm-commits] [llvm] r52613 - in /llvm/trunk/lib/Target: CellSPU/SPUISelLowering.cpp PowerPC/PPCISelLowering.cpp X86/X86ISelLowering.cpp X86/X86TargetMachine.cpp Message-ID: <200806221921.m5MJLQSb022007@zion.cs.uiuc.edu> Author: djg Date: Sun Jun 22 14:21:26 2008 New Revision: 52613 URL: http://llvm.org/viewvc/llvm-project?rev=52613&view=rev Log: Remove unnecessary #includes. Modified: llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp llvm/trunk/lib/Target/X86/X86ISelLowering.cpp llvm/trunk/lib/Target/X86/X86TargetMachine.cpp Modified: llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp?rev=52613&r1=52612&r2=52613&view=diff ============================================================================== --- llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp (original) +++ llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp Sun Jun 22 14:21:26 2008 @@ -16,7 +16,6 @@ #include "SPUTargetMachine.h" #include "SPUFrameInfo.h" #include "llvm/ADT/VectorExtras.h" -#include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" Modified: llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp?rev=52613&r1=52612&r2=52613&view=diff ============================================================================== --- llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp (original) +++ llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp Sun Jun 22 14:21:26 2008 @@ -18,7 +18,6 @@ #include "PPCPerfectShuffle.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/VectorExtras.h" -#include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=52613&r1=52612&r2=52613&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Sun Jun 22 14:21:26 2008 @@ -25,7 +25,6 @@ #include "llvm/Intrinsics.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/VectorExtras.h" -#include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" Modified: llvm/trunk/lib/Target/X86/X86TargetMachine.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86TargetMachine.cpp?rev=52613&r1=52612&r2=52613&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86TargetMachine.cpp (original) +++ llvm/trunk/lib/Target/X86/X86TargetMachine.cpp Sun Jun 22 14:21:26 2008 @@ -20,7 +20,6 @@ #include "llvm/CodeGen/Passes.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetMachineRegistry.h" -#include "llvm/Transforms/Scalar.h" using namespace llvm; /// X86TargetMachineModule - Note that this is used on hosts that cannot link From gohman at apple.com Sun Jun 22 14:23:09 2008 From: gohman at apple.com (Dan Gohman) Date: Sun, 22 Jun 2008 19:23:09 -0000 Subject: [llvm-commits] [llvm] r52614 - in /llvm/trunk: include/llvm/Analysis/ScalarEvolutionExpressions.h lib/Analysis/ScalarEvolutionExpander.cpp Message-ID: <200806221923.m5MJN9wX022067@zion.cs.uiuc.edu> Author: djg Date: Sun Jun 22 14:23:09 2008 New Revision: 52614 URL: http://llvm.org/viewvc/llvm-project?rev=52614&view=rev Log: Use SCEVAddRecExpr::isAffine. Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h?rev=52614&r1=52613&r2=52614&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h (original) +++ llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpressions.h Sun Jun 22 14:23:09 2008 @@ -407,7 +407,7 @@ /// indicating how much this expression steps by. If this is a polynomial /// of degree N, it returns a chrec of degree N-1. SCEVHandle getStepRecurrence(ScalarEvolution &SE) const { - if (getNumOperands() == 2) return getOperand(1); + if (isAffine()) return getOperand(1); return SE.getAddRecExpr(std::vector(op_begin()+1,op_end()), getLoop()); } Modified: llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp?rev=52614&r1=52613&r2=52614&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp (original) +++ llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp Sun Jun 22 14:23:09 2008 @@ -147,7 +147,7 @@ } // {0,+,1} --> Insert a canonical induction variable into the loop! - if (S->getNumOperands() == 2 && + if (S->isAffine() && S->getOperand(1) == SE.getIntegerSCEV(1, Ty)) { // Create and insert the PHI node for the induction variable in the // specified loop. @@ -178,7 +178,7 @@ Value *I = getOrInsertCanonicalInductionVariable(L, Ty); // If this is a simple linear addrec, emit it now as a special case. - if (S->getNumOperands() == 2) { // {0,+,F} --> i*F + if (S->isAffine()) { // {0,+,F} --> i*F Value *F = expand(S->getOperand(1)); // IF the step is by one, just return the inserted IV. From gohman at apple.com Sun Jun 22 14:56:46 2008 From: gohman at apple.com (Dan Gohman) Date: Sun, 22 Jun 2008 19:56:46 -0000 Subject: [llvm-commits] [llvm] r52615 - /llvm/trunk/lib/Analysis/ScalarEvolution.cpp Message-ID: <200806221956.m5MJukV7023236@zion.cs.uiuc.edu> Author: djg Date: Sun Jun 22 14:56:46 2008 New Revision: 52615 URL: http://llvm.org/viewvc/llvm-project?rev=52615&view=rev Log: Generalize createSCEV to be able to form SCEV expressions from ConstantExprs. Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=52615&r1=52614&r2=52615&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original) +++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Sun Jun 22 14:56:46 2008 @@ -1704,118 +1704,125 @@ if (!isa(V->getType())) return SE.getUnknown(V); - if (Instruction *I = dyn_cast(V)) { - switch (I->getOpcode()) { - case Instruction::Add: - return SE.getAddExpr(getSCEV(I->getOperand(0)), - getSCEV(I->getOperand(1))); - case Instruction::Mul: - return SE.getMulExpr(getSCEV(I->getOperand(0)), - getSCEV(I->getOperand(1))); - case Instruction::UDiv: - return SE.getUDivExpr(getSCEV(I->getOperand(0)), - getSCEV(I->getOperand(1))); - case Instruction::Sub: - return SE.getMinusSCEV(getSCEV(I->getOperand(0)), - getSCEV(I->getOperand(1))); - case Instruction::Or: - // If the RHS of the Or is a constant, we may have something like: - // X*4+1 which got turned into X*4|1. Handle this as an Add so loop - // optimizations will transparently handle this case. - // - // In order for this transformation to be safe, the LHS must be of the - // form X*(2^n) and the Or constant must be less than 2^n. - if (ConstantInt *CI = dyn_cast(I->getOperand(1))) { - SCEVHandle LHS = getSCEV(I->getOperand(0)); - const APInt &CIVal = CI->getValue(); - if (GetMinTrailingZeros(LHS) >= - (CIVal.getBitWidth() - CIVal.countLeadingZeros())) - return SE.getAddExpr(LHS, getSCEV(I->getOperand(1))); - } - break; - case Instruction::Xor: - // If the RHS of the xor is a signbit, then this is just an add. - // Instcombine turns add of signbit into xor as a strength reduction step. - if (ConstantInt *CI = dyn_cast(I->getOperand(1))) { - if (CI->getValue().isSignBit()) - return SE.getAddExpr(getSCEV(I->getOperand(0)), - getSCEV(I->getOperand(1))); - else if (CI->isAllOnesValue()) - return SE.getNotSCEV(getSCEV(I->getOperand(0))); - } - break; + unsigned Opcode = Instruction::UserOp1; + if (Instruction *I = dyn_cast(V)) + Opcode = I->getOpcode(); + else if (ConstantExpr *CE = dyn_cast(V)) + Opcode = CE->getOpcode(); + else + return SE.getUnknown(V); - case Instruction::Shl: - // Turn shift left of a constant amount into a multiply. - if (ConstantInt *SA = dyn_cast(I->getOperand(1))) { - uint32_t BitWidth = cast(V->getType())->getBitWidth(); - Constant *X = ConstantInt::get( - APInt(BitWidth, 1).shl(SA->getLimitedValue(BitWidth))); - return SE.getMulExpr(getSCEV(I->getOperand(0)), getSCEV(X)); - } - break; + User *U = cast(V); + switch (Opcode) { + case Instruction::Add: + return SE.getAddExpr(getSCEV(U->getOperand(0)), + getSCEV(U->getOperand(1))); + case Instruction::Mul: + return SE.getMulExpr(getSCEV(U->getOperand(0)), + getSCEV(U->getOperand(1))); + case Instruction::UDiv: + return SE.getUDivExpr(getSCEV(U->getOperand(0)), + getSCEV(U->getOperand(1))); + case Instruction::Sub: + return SE.getMinusSCEV(getSCEV(U->getOperand(0)), + getSCEV(U->getOperand(1))); + case Instruction::Or: + // If the RHS of the Or is a constant, we may have something like: + // X*4+1 which got turned into X*4|1. Handle this as an Add so loop + // optimizations will transparently handle this case. + // + // In order for this transformation to be safe, the LHS must be of the + // form X*(2^n) and the Or constant must be less than 2^n. + if (ConstantInt *CI = dyn_cast(U->getOperand(1))) { + SCEVHandle LHS = getSCEV(U->getOperand(0)); + const APInt &CIVal = CI->getValue(); + if (GetMinTrailingZeros(LHS) >= + (CIVal.getBitWidth() - CIVal.countLeadingZeros())) + return SE.getAddExpr(LHS, getSCEV(U->getOperand(1))); + } + break; + case Instruction::Xor: + // If the RHS of the xor is a signbit, then this is just an add. + // Instcombine turns add of signbit into xor as a strength reduction step. + if (ConstantInt *CI = dyn_cast(U->getOperand(1))) { + if (CI->getValue().isSignBit()) + return SE.getAddExpr(getSCEV(U->getOperand(0)), + getSCEV(U->getOperand(1))); + else if (CI->isAllOnesValue()) + return SE.getNotSCEV(getSCEV(U->getOperand(0))); + } + break; - case Instruction::Trunc: - return SE.getTruncateExpr(getSCEV(I->getOperand(0)), I->getType()); + case Instruction::Shl: + // Turn shift left of a constant amount into a multiply. + if (ConstantInt *SA = dyn_cast(U->getOperand(1))) { + uint32_t BitWidth = cast(V->getType())->getBitWidth(); + Constant *X = ConstantInt::get( + APInt(BitWidth, 1).shl(SA->getLimitedValue(BitWidth))); + return SE.getMulExpr(getSCEV(U->getOperand(0)), getSCEV(X)); + } + break; - case Instruction::ZExt: - return SE.getZeroExtendExpr(getSCEV(I->getOperand(0)), I->getType()); + case Instruction::Trunc: + return SE.getTruncateExpr(getSCEV(U->getOperand(0)), U->getType()); - case Instruction::SExt: - return SE.getSignExtendExpr(getSCEV(I->getOperand(0)), I->getType()); - - case Instruction::BitCast: - // BitCasts are no-op casts so we just eliminate the cast. - if (I->getType()->isInteger() && - I->getOperand(0)->getType()->isInteger()) - return getSCEV(I->getOperand(0)); - break; - - case Instruction::PHI: - return createNodeForPHI(cast(I)); - - case Instruction::Select: - // This could be a smax or umax that was lowered earlier. - // Try to recover it. - if (ICmpInst *ICI = dyn_cast(I->getOperand(0))) { - Value *LHS = ICI->getOperand(0); - Value *RHS = ICI->getOperand(1); - switch (ICI->getPredicate()) { - case ICmpInst::ICMP_SLT: - case ICmpInst::ICMP_SLE: - std::swap(LHS, RHS); - // fall through - case ICmpInst::ICMP_SGT: - case ICmpInst::ICMP_SGE: - if (LHS == I->getOperand(1) && RHS == I->getOperand(2)) - return SE.getSMaxExpr(getSCEV(LHS), getSCEV(RHS)); - else if (LHS == I->getOperand(2) && RHS == I->getOperand(1)) - // -smax(-x, -y) == smin(x, y). - return SE.getNegativeSCEV(SE.getSMaxExpr( - SE.getNegativeSCEV(getSCEV(LHS)), - SE.getNegativeSCEV(getSCEV(RHS)))); - break; - case ICmpInst::ICMP_ULT: - case ICmpInst::ICMP_ULE: - std::swap(LHS, RHS); - // fall through - case ICmpInst::ICMP_UGT: - case ICmpInst::ICMP_UGE: - if (LHS == I->getOperand(1) && RHS == I->getOperand(2)) - return SE.getUMaxExpr(getSCEV(LHS), getSCEV(RHS)); - else if (LHS == I->getOperand(2) && RHS == I->getOperand(1)) - // ~umax(~x, ~y) == umin(x, y) - return SE.getNotSCEV(SE.getUMaxExpr(SE.getNotSCEV(getSCEV(LHS)), - SE.getNotSCEV(getSCEV(RHS)))); - break; - default: - break; - } - } + case Instruction::ZExt: + return SE.getZeroExtendExpr(getSCEV(U->getOperand(0)), U->getType()); + + case Instruction::SExt: + return SE.getSignExtendExpr(getSCEV(U->getOperand(0)), U->getType()); + + case Instruction::BitCast: + // BitCasts are no-op casts so we just eliminate the cast. + if (U->getType()->isInteger() && + U->getOperand(0)->getType()->isInteger()) + return getSCEV(U->getOperand(0)); + break; + + case Instruction::PHI: + return createNodeForPHI(cast(U)); - default: // We cannot analyze this expression. - break; + case Instruction::Select: + // This could be a smax or umax that was lowered earlier. + // Try to recover it. + if (ICmpInst *ICI = dyn_cast(U->getOperand(0))) { + Value *LHS = ICI->getOperand(0); + Value *RHS = ICI->getOperand(1); + switch (ICI->getPredicate()) { + case ICmpInst::ICMP_SLT: + case ICmpInst::ICMP_SLE: + std::swap(LHS, RHS); + // fall through + case ICmpInst::ICMP_SGT: + case ICmpInst::ICMP_SGE: + if (LHS == U->getOperand(1) && RHS == U->getOperand(2)) + return SE.getSMaxExpr(getSCEV(LHS), getSCEV(RHS)); + else if (LHS == U->getOperand(2) && RHS == U->getOperand(1)) + // -smax(-x, -y) == smin(x, y). + return SE.getNegativeSCEV(SE.getSMaxExpr( + SE.getNegativeSCEV(getSCEV(LHS)), + SE.getNegativeSCEV(getSCEV(RHS)))); + break; + case ICmpInst::ICMP_ULT: + case ICmpInst::ICMP_ULE: + std::swap(LHS, RHS); + // fall through + case ICmpInst::ICMP_UGT: + case ICmpInst::ICMP_UGE: + if (LHS == U->getOperand(1) && RHS == U->getOperand(2)) + return SE.getUMaxExpr(getSCEV(LHS), getSCEV(RHS)); + else if (LHS == U->getOperand(2) && RHS == U->getOperand(1)) + // ~umax(~x, ~y) == umin(x, y) + return SE.getNotSCEV(SE.getUMaxExpr(SE.getNotSCEV(getSCEV(LHS)), + SE.getNotSCEV(getSCEV(RHS)))); + break; + default: + break; + } } + + default: // We cannot analyze this expression. + break; } return SE.getUnknown(V); From gohman at apple.com Sun Jun 22 15:18:59 2008 From: gohman at apple.com (Dan Gohman) Date: Sun, 22 Jun 2008 20:18:59 -0000 Subject: [llvm-commits] [llvm] r52616 - in /llvm/trunk/lib/Transforms: Scalar/IndVarSimplify.cpp Scalar/LICM.cpp Scalar/LoopUnroll.cpp Utils/LoopSimplify.cpp Message-ID: <200806222018.m5MKIxJL023905@zion.cs.uiuc.edu> Author: djg Date: Sun Jun 22 15:18:58 2008 New Revision: 52616 URL: http://llvm.org/viewvc/llvm-project?rev=52616&view=rev Log: Use Loop::block_iterator. Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp llvm/trunk/lib/Transforms/Scalar/LICM.cpp llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=52616&r1=52615&r2=52616&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Sun Jun 22 15:18:58 2008 @@ -574,9 +574,10 @@ #if 0 // Now replace all derived expressions in the loop body with simpler // expressions. - for (unsigned i = 0, e = L->getBlocks().size(); i != e; ++i) - if (LI->getLoopFor(L->getBlocks()[i]) == L) { // Not in a subloop... - BasicBlock *BB = L->getBlocks()[i]; + for (LoopInfo::block_iterator I = L->block_begin(), E = L->block_end(); + I != E; ++I) { + BasicBlock *BB = *I; + if (LI->getLoopFor(BB) == L) { // Not in a subloop... for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) if (I->getType()->isInteger() && // Is an integer instruction !I->use_empty() && @@ -593,6 +594,7 @@ } } } + } #endif DeleteTriviallyDeadInstructions(DeadInsts); Modified: llvm/trunk/lib/Transforms/Scalar/LICM.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LICM.cpp?rev=52616&r1=52615&r2=52616&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LICM.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LICM.cpp Sun Jun 22 15:18:58 2008 @@ -258,10 +258,12 @@ // Because subloops have already been incorporated into AST, we skip blocks in // subloops. // - for (std::vector::const_iterator I = L->getBlocks().begin(), - E = L->getBlocks().end(); I != E; ++I) - if (LI->getLoopFor(*I) == L) // Ignore blocks in subloops... - CurAST->add(**I); // Incorporate the specified basic block + for (Loop::block_iterator I = L->block_begin(), E = L->block_end(); + I != E; ++I) { + BasicBlock *BB = *I; + if (LI->getLoopFor(BB) == L) // Ignore blocks in subloops... + CurAST->add(*BB); // Incorporate the specified basic block + } // We want to visit all of the instructions in this loop... that are not parts // of our subloops (they have already had their invariants hoisted out of @@ -698,12 +700,11 @@ // Scan the basic blocks in the loop, replacing uses of our pointers with // uses of the allocas in question. // - const std::vector &LoopBBs = CurLoop->getBlocks(); - for (std::vector::const_iterator I = LoopBBs.begin(), - E = LoopBBs.end(); I != E; ++I) { + for (Loop::block_iterator I = CurLoop->block_begin(), + E = CurLoop->block_end(); I != E; ++I) { + BasicBlock *BB = *I; // Rewrite all loads and stores in the block of the pointer... - for (BasicBlock::iterator II = (*I)->begin(), E = (*I)->end(); - II != E; ++II) { + for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; ++II) { if (LoadInst *L = dyn_cast(II)) { std::map::iterator I = ValueToAllocaMap.find(L->getOperand(0)); Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp?rev=52616&r1=52615&r2=52616&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopUnroll.cpp Sun Jun 22 15:18:58 2008 @@ -67,8 +67,9 @@ /// ApproximateLoopSize - Approximate the size of the loop. static unsigned ApproximateLoopSize(const Loop *L) { unsigned Size = 0; - for (unsigned i = 0, e = L->getBlocks().size(); i != e; ++i) { - BasicBlock *BB = L->getBlocks()[i]; + for (Loop::block_iterator I = L->block_begin(), E = L->block_end(); + I != E; ++I) { + BasicBlock *BB = *I; Instruction *Term = BB->getTerminator(); for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { if (isa(I) && BB == L->getHeader()) { Modified: llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp?rev=52616&r1=52615&r2=52616&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp (original) +++ llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp Sun Jun 22 15:18:58 2008 @@ -460,8 +460,9 @@ // L is now a subloop of our outer loop. NewOuter->addChildLoop(L); - for (unsigned i = 0, e = L->getBlocks().size(); i != e; ++i) - NewOuter->addBlockEntry(L->getBlocks()[i]); + for (Loop::block_iterator I = L->block_begin(), E = L->block_end(); + I != E; ++I) + NewOuter->addBlockEntry(*I); // Determine which blocks should stay in L and which should be moved out to // the Outer loop now. From gohman at apple.com Sun Jun 22 15:44:02 2008 From: gohman at apple.com (Dan Gohman) Date: Sun, 22 Jun 2008 20:44:02 -0000 Subject: [llvm-commits] [llvm] r52617 - in /llvm/trunk: lib/Transforms/Scalar/LoopStrengthReduce.cpp test/Transforms/LoopStrengthReduce/dead-phi.ll Message-ID: <200806222044.m5MKi2FV024786@zion.cs.uiuc.edu> Author: djg Date: Sun Jun 22 15:44:02 2008 New Revision: 52617 URL: http://llvm.org/viewvc/llvm-project?rev=52617&view=rev Log: Improve LSR's dead-phi detection to handle use-def cycles with more than two nodes. Added: llvm/trunk/test/Transforms/LoopStrengthReduce/dead-phi.ll Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=52617&r1=52616&r2=52617&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Sun Jun 22 15:44:02 2008 @@ -1810,31 +1810,28 @@ DeleteTriviallyDeadInstructions(DeadInsts); BasicBlock::iterator I = L->getHeader()->begin(); - PHINode *PN; - while ((PN = dyn_cast(I))) { - ++I; // Preincrement iterator to avoid invalidating it when deleting PN. - - // At this point, we know that we have killed one or more GEP - // instructions. It is worth checking to see if the cann indvar is also - // dead, so that we can remove it as well. The requirements for the cann - // indvar to be considered dead are: - // 1. the cann indvar has one use - // 2. the use is an add instruction - // 3. the add has one use - // 4. the add is used by the cann indvar - // If all four cases above are true, then we can remove both the add and - // the cann indvar. + while (PHINode *PN = dyn_cast(I++)) { + // At this point, we know that we have killed one or more IV users. + // It is worth checking to see if the cann indvar is also + // dead, so that we can remove it as well. + // + // We can remove a PHI if it is on a cycle in the def-use graph + // where each node in the cycle has degree one, i.e. only one use, + // and is an instruction with no side effects. + // // FIXME: this needs to eliminate an induction variable even if it's being // compared against some value to decide loop termination. if (PN->hasOneUse()) { - Instruction *BO = dyn_cast(*PN->use_begin()); - if (BO && (isa(BO) || isa(BO))) { - if (BO->hasOneUse() && PN == *(BO->use_begin())) { - DeadInsts.insert(BO); - // Break the cycle, then delete the PHI. + for (Instruction *J = dyn_cast(*PN->use_begin()); + J && J->hasOneUse() && !J->mayWriteToMemory(); + J = dyn_cast(*J->use_begin())) { + // If we find the original PHI, we've discovered a cycle. + if (J == PN) { + // Break the cycle and mark the PHI for deletion. SE->deleteValueFromRecords(PN); PN->replaceAllUsesWith(UndefValue::get(PN->getType())); - PN->eraseFromParent(); + DeadInsts.insert(PN); + break; } } } Added: llvm/trunk/test/Transforms/LoopStrengthReduce/dead-phi.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopStrengthReduce/dead-phi.ll?rev=52617&view=auto ============================================================================== --- llvm/trunk/test/Transforms/LoopStrengthReduce/dead-phi.ll (added) +++ llvm/trunk/test/Transforms/LoopStrengthReduce/dead-phi.ll Sun Jun 22 15:44:02 2008 @@ -0,0 +1,21 @@ +; RUN: llvm-as < %s | opt -loop-reduce | llvm-dis | grep phi | count 1 + +define void @foo(i32 %n) { +entry: + br label %loop + +loop: + %i = phi i32 [ 0, %entry ], [ %i.next, %loop ] + + ; These three instructions form an isolated cycle and can be deleted. + %j = phi i32 [ 0, %entry ], [ %j.y, %loop ] + %j.x = add i32 %j, 1 + %j.y = mul i32 %j.x, 2 + + %i.next = add i32 %i, 1 + %c = icmp ne i32 %i.next, %n + br i1 %c, label %loop, label %exit + +exit: + ret void +}