[llvm-commits] [llvm] r60608 - in /llvm/trunk: lib/Target/X86/X86ISelLowering.cpp lib/Target/X86/X86Subtarget.cpp lib/Transforms/Scalar/LoopStrengthReduce.cpp test/CodeGen/X86/loop-strength-reduce-2.ll test/CodeGen/X86/loop-strength-reduce-3.ll test/CodeGen/X86/loop-strength-reduce.ll
Evan Cheng
evan.cheng at apple.com
Fri Dec 5 13:52:11 PST 2008
You forgot changes to X86Subtarget.h?
Evan
On Dec 5, 2008, at 1:47 PM, Dale Johannesen wrote:
> Author: johannes
> Date: Fri Dec 5 15:47:27 2008
> New Revision: 60608
>
> URL: http://llvm.org/viewvc/llvm-project?rev=60608&view=rev
> Log:
> Make LoopStrengthReduce smarter about hoisting things out of
> loops when they can be subsumed into addressing modes.
>
> Change X86 addressing mode check to realize that
> some PIC references need an extra register.
> (I believe this is correct for Linux, if not, I'm sure
> someone will tell me.)
>
>
> Added:
> llvm/trunk/test/CodeGen/X86/loop-strength-reduce-2.ll
> llvm/trunk/test/CodeGen/X86/loop-strength-reduce-3.ll
> Modified:
> llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
> llvm/trunk/lib/Target/X86/X86Subtarget.cpp
> llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp
> llvm/trunk/test/CodeGen/X86/loop-strength-reduce.ll
>
> Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=60608&r1=60607&r2=60608&view=diff
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Fri Dec 5
> 15:47:27 2008
> @@ -6463,6 +6463,10 @@
> // We can only fold this if we don't need an extra load.
> if (Subtarget->GVRequiresExtraLoad(AM.BaseGV,
> getTargetMachine(), false))
> return false;
> + // If BaseGV requires a register, we cannot also have a BaseReg.
> + if (Subtarget->GVRequiresRegister(AM.BaseGV,
> getTargetMachine(), false) &&
> + AM.HasBaseReg)
> + return false;
>
> // X86-64 only supports addr of globals in small code model.
> if (Subtarget->is64Bit()) {
>
> Modified: llvm/trunk/lib/Target/X86/X86Subtarget.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Subtarget.cpp?rev=60608&r1=60607&r2=60608&view=diff
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- llvm/trunk/lib/Target/X86/X86Subtarget.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86Subtarget.cpp Fri Dec 5 15:47:27
> 2008
> @@ -59,7 +59,23 @@
> return (GV->hasDLLImportLinkage());
> }
> }
> -
> + return false;
> +}
> +
> +/// True if accessing the GV requires a register. This is a
> superset of the
> +/// cases where GVRequiresExtraLoad is true. Some variations of
> PIC require
> +/// a register, but not an extra load.
> +bool X86Subtarget::GVRequiresRegister(const GlobalValue *GV,
> + const TargetMachine& TM,
> + bool isDirectCall) const
> +{
> + if (GVRequiresExtraLoad(GV, TM, isDirectCall))
> + return true;
> + // Code below here need only consider cases where
> GVRequiresExtraLoad
> + // returns false.
> + if (TM.getRelocationModel() == Reloc::PIC_)
> + return !isDirectCall &&
> + (GV->hasInternalLinkage() || GV->hasExternalLinkage());
> return false;
> }
>
>
> Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=60608&r1=60607&r2=60608&view=diff
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Fri Dec
> 5 15:47:27 2008
> @@ -444,7 +444,33 @@
> return true;
> }
>
> -
> +/// isAddress - Returns true if the specified instruction is using
> the
> +/// specified value as an address.
> +static bool isAddressUse(Instruction *Inst, Value *OperandVal) {
> + bool isAddress = isa<LoadInst>(Inst);
> + if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
> + if (SI->getOperand(1) == OperandVal)
> + isAddress = true;
> + } else if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Inst)) {
> + // Addressing modes can also be folded into prefetches and a
> variety
> + // of intrinsics.
> + switch (II->getIntrinsicID()) {
> + default: break;
> + case Intrinsic::prefetch:
> + case Intrinsic::x86_sse2_loadu_dq:
> + case Intrinsic::x86_sse2_loadu_pd:
> + case Intrinsic::x86_sse_loadu_ps:
> + case Intrinsic::x86_sse_storeu_ps:
> + case Intrinsic::x86_sse2_storeu_pd:
> + case Intrinsic::x86_sse2_storeu_dq:
> + case Intrinsic::x86_sse2_storel_dq:
> + if (II->getOperand(1) == OperandVal)
> + isAddress = true;
> + break;
> + }
> + }
> + return isAddress;
> +}
>
> /// AddUsersIfInteresting - Inspect the specified instruction. If
> it is a
> /// reducible SCEV, recursively add its users to the IVUsesByStride
> set and
> @@ -731,15 +757,16 @@
> }
>
>
> -/// isTargetConstant - Return true if the following can be
> referenced by the
> -/// immediate field of a target instruction.
> -static bool isTargetConstant(const SCEVHandle &V, const Type *UseTy,
> - const TargetLowering *TLI) {
> +/// fitsInAddressMode - Return true if V can be subsumed within an
> addressing
> +/// mode, and does not need to be put in a register first.
> +static bool fitsInAddressMode(const SCEVHandle &V, const Type *UseTy,
> + const TargetLowering *TLI, bool
> HasBaseReg) {
> if (SCEVConstant *SC = dyn_cast<SCEVConstant>(V)) {
> int64_t VC = SC->getValue()->getSExtValue();
> if (TLI) {
> TargetLowering::AddrMode AM;
> AM.BaseOffs = VC;
> + AM.HasBaseReg = HasBaseReg;
> return TLI->isLegalAddressingMode(AM, UseTy);
> } else {
> // Defaults to PPC. PPC allows a sign-extended 16-bit
> immediate field.
> @@ -754,6 +781,7 @@
> if (GlobalValue *GV = dyn_cast<GlobalValue>(Op0)) {
> TargetLowering::AddrMode AM;
> AM.BaseGV = GV;
> + AM.HasBaseReg = HasBaseReg;
> return TLI->isLegalAddressingMode(AM, UseTy);
> }
> }
> @@ -846,7 +874,7 @@
> return;
> } else if (SCEVMulExpr *SME = dyn_cast<SCEVMulExpr>(Val)) {
> // Transform "8 * (4 + v)" -> "32 + 8*V" if "32" fits in the
> immed field.
> - if (isAddress && isTargetConstant(SME->getOperand(0), UseTy,
> TLI) &&
> + if (isAddress && fitsInAddressMode(SME->getOperand(0), UseTy,
> TLI, false) &&
> SME->getNumOperands() == 2 && SME->isLoopInvariant(L)) {
>
> SCEVHandle SubImm = SE->getIntegerSCEV(0, Val->getType());
> @@ -859,7 +887,7 @@
> // Scale SubImm up by "8". If the result is a target
> constant, we are
> // good.
> SubImm = SE->getMulExpr(SubImm, SME->getOperand(0));
> - if (isTargetConstant(SubImm, UseTy, TLI)) {
> + if (fitsInAddressMode(SubImm, UseTy, TLI, false)) {
> // Accumulate the immediate.
> Imm = SE->getAddExpr(Imm, SubImm);
>
> @@ -873,7 +901,7 @@
>
> // Loop-variant expressions must stay in the immediate field of the
> // expression.
> - if ((isAddress && isTargetConstant(Val, UseTy, TLI)) ||
> + if ((isAddress && fitsInAddressMode(Val, UseTy, TLI, false)) ||
> !Val->isLoopInvariant(L)) {
> Imm = SE->getAddExpr(Imm, Val);
> Val = SE->getIntegerSCEV(0, Val->getType());
> @@ -912,21 +940,28 @@
> }
> }
>
> -
> -/// RemoveCommonExpressionsFromUseBases - Look through all of the
> uses in Bases,
> -/// removing any common subexpressions from it. Anything truly
> common is
> -/// removed, accumulated, and returned. This looks for things like
> (a+b+c) and
> +// This is logically local to the following function, but C++ says
> we have
> +// to make it file scope.
> +struct SubExprUseData { unsigned Count; bool notAllUsesAreFree; };
> +
> +/// RemoveCommonExpressionsFromUseBases - Look through all of the
> Bases of all
> +/// the Uses, removing any common subexpressions, except that if
> all such
> +/// subexpressions can be folded into an addressing mode for all
> uses inside
> +/// the loop (this case is referred to as "free" in comments
> herein) we do
> +/// not remove anything. This looks for things like (a+b+c) and
> /// (a+c+d) and computes the common (a+c) subexpression. The common
> expression
> /// is *removed* from the Bases and returned.
> static SCEVHandle
> RemoveCommonExpressionsFromUseBases(std::vector<BasedUser> &Uses,
> - ScalarEvolution *SE, Loop *L) {
> + ScalarEvolution *SE, Loop *L,
> + const TargetLowering *TLI) {
> unsigned NumUses = Uses.size();
>
> // Only one use? This is a very common case, so we handle it
> specially and
> // cheaply.
> SCEVHandle Zero = SE->getIntegerSCEV(0, Uses[0].Base->getType());
> SCEVHandle Result = Zero;
> + SCEVHandle FreeResult = Zero;
> if (NumUses == 1) {
> // If the use is inside the loop, use its base, regardless of
> what it is:
> // it is clearly shared across all the IV's. If the use is
> outside the loop
> @@ -939,7 +974,10 @@
>
> // To find common subexpressions, count how many of Uses use each
> expression.
> // If any subexpressions are used Uses.size() times, they are
> common.
> - std::map<SCEVHandle, unsigned> SubExpressionUseCounts;
> + // Also track whether all uses of each expression can be moved
> into an
> + // an addressing mode "for free"; such expressions are left
> within the loop.
> + // struct SubExprUseData { unsigned Count; bool
> notAllUsesAreFree; };
> + std::map<SCEVHandle, SubExprUseData> SubExpressionUseData;
>
> // UniqueSubExprs - Keep track of all of the subexpressions we see
> in the
> // order we see them.
> @@ -962,31 +1000,89 @@
> // CSEs we can find.
> if (Uses[i].Base == Zero) return Zero;
>
> + // If this use is as an address we may be able to put CSEs in
> the addressing
> + // mode rather than hoisting them.
> + bool isAddrUse = isAddressUse(Uses[i].Inst,
> Uses[i].OperandValToReplace);
> + // We may need the UseTy below, but only when isAddrUse, so
> compute it
> + // only in that case.
> + const Type *UseTy = 0;
> + if (isAddrUse) {
> + UseTy = Uses[i].Inst->getType();
> + if (StoreInst *SI = dyn_cast<StoreInst>(Uses[i].Inst))
> + UseTy = SI->getOperand(0)->getType();
> + }
> +
> // Split the expression into subexprs.
> SeparateSubExprs(SubExprs, Uses[i].Base, SE);
> - // Add one to SubExpressionUseCounts for each subexpr present.
> - for (unsigned j = 0, e = SubExprs.size(); j != e; ++j)
> - if (++SubExpressionUseCounts[SubExprs[j]] == 1)
> + // Add one to SubExpressionUseData.Count for each subexpr
> present, and
> + // if the subexpr is not a valid immediate within an addressing
> mode use,
> + // set SubExpressionUseData.notAllUsesAreFree. We definitely
> want to
> + // hoist these out of the loop (if they are common to all uses).
> + for (unsigned j = 0, e = SubExprs.size(); j != e; ++j) {
> + if (++SubExpressionUseData[SubExprs[j]].Count == 1)
> UniqueSubExprs.push_back(SubExprs[j]);
> + if (!isAddrUse || !fitsInAddressMode(SubExprs[j], UseTy, TLI,
> false))
> + SubExpressionUseData[SubExprs[j]].notAllUsesAreFree = true;
> + }
> SubExprs.clear();
> }
>
> // Now that we know how many times each is used, build Result.
> Iterate over
> // UniqueSubexprs so that we have a stable ordering.
> for (unsigned i = 0, e = UniqueSubExprs.size(); i != e; ++i) {
> - std::map<SCEVHandle, unsigned>::iterator I =
> - SubExpressionUseCounts.find(UniqueSubExprs[i]);
> - assert(I != SubExpressionUseCounts.end() && "Entry not found?");
> - if (I->second == NumUsesInsideLoop) // Found CSE!
> - Result = SE->getAddExpr(Result, I->first);
> - else
> - // Remove non-cse's from SubExpressionUseCounts.
> - SubExpressionUseCounts.erase(I);
> + std::map<SCEVHandle, SubExprUseData>::iterator I =
> + SubExpressionUseData.find(UniqueSubExprs[i]);
> + assert(I != SubExpressionUseData.end() && "Entry not found?");
> + if (I->second.Count == NumUsesInsideLoop) { // Found CSE!
> + if (I->second.notAllUsesAreFree)
> + Result = SE->getAddExpr(Result, I->first);
> + else
> + FreeResult = SE->getAddExpr(FreeResult, I->first);
> + } else
> + // Remove non-cse's from SubExpressionUseData.
> + SubExpressionUseData.erase(I);
> + }
> +
> + if (FreeResult != Zero) {
> + // We have some subexpressions that can be subsumed into
> addressing
> + // modes in every use inside the loop. However, it's possible
> that
> + // there are so many of them that the combined FreeResult cannot
> + // be subsumed, or that the target cannot handle both a
> FreeResult
> + // and a Result in the same instruction (for example because it
> would
> + // require too many registers). Check this.
> + for (unsigned i=0; i<NumUses; ++i) {
> + if (!L->contains(Uses[i].Inst->getParent()))
> + continue;
> + // We know this is an addressing mode use; if there are any
> uses that
> + // are not, FreeResult would be Zero.
> + const Type *UseTy = Uses[i].Inst->getType();
> + if (StoreInst *SI = dyn_cast<StoreInst>(Uses[i].Inst))
> + UseTy = SI->getOperand(0)->getType();
> + if (!fitsInAddressMode(FreeResult, UseTy, TLI, Result!=Zero)) {
> + // FIXME: could split up FreeResult into pieces here, some
> hoisted
> + // and some not. Doesn't seem worth it for now.
> + Result = SE->getAddExpr(Result, FreeResult);
> + FreeResult = Zero;
> + break;
> + }
> + }
> }
> -
> +
> // If we found no CSE's, return now.
> if (Result == Zero) return Result;
>
> + // If we still have a FreeResult, remove its subexpressions from
> + // SubExpressionUseData. This means they will remain in the use
> Bases.
> + if (FreeResult != Zero) {
> + SeparateSubExprs(SubExprs, FreeResult, SE);
> + for (unsigned j = 0, e = SubExprs.size(); j != e; ++j) {
> + std::map<SCEVHandle, SubExprUseData>::iterator I =
> + SubExpressionUseData.find(SubExprs[j]);
> + SubExpressionUseData.erase(I);
> + }
> + SubExprs.clear();
> + }
> +
> // Otherwise, remove all of the CSE's we found from each of the
> base values.
> for (unsigned i = 0; i != NumUses; ++i) {
> // Uses outside the loop don't necessarily include the common
> base, but
> @@ -1003,7 +1099,7 @@
>
> // Remove any common subexpressions.
> for (unsigned j = 0, e = SubExprs.size(); j != e; ++j)
> - if (SubExpressionUseCounts.count(SubExprs[j])) {
> + if (SubExpressionUseData.count(SubExprs[j])) {
> SubExprs.erase(SubExprs.begin()+j);
> --j; --e;
> }
> @@ -1131,34 +1227,6 @@
> return SC->getValue()->getValue().isNegative();
> }
>
> -/// isAddress - Returns true if the specified instruction is using
> the
> -/// specified value as an address.
> -static bool isAddressUse(Instruction *Inst, Value *OperandVal) {
> - bool isAddress = isa<LoadInst>(Inst);
> - if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
> - if (SI->getOperand(1) == OperandVal)
> - isAddress = true;
> - } else if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Inst)) {
> - // Addressing modes can also be folded into prefetches and a
> variety
> - // of intrinsics.
> - switch (II->getIntrinsicID()) {
> - default: break;
> - case Intrinsic::prefetch:
> - case Intrinsic::x86_sse2_loadu_dq:
> - case Intrinsic::x86_sse2_loadu_pd:
> - case Intrinsic::x86_sse_loadu_ps:
> - case Intrinsic::x86_sse_storeu_ps:
> - case Intrinsic::x86_sse2_storeu_pd:
> - case Intrinsic::x86_sse2_storeu_dq:
> - case Intrinsic::x86_sse2_storel_dq:
> - if (II->getOperand(1) == OperandVal)
> - isAddress = true;
> - break;
> - }
> - }
> - return isAddress;
> -}
> -
> // CollectIVUsers - Transform our list of users and offsets to a bit
> more
> // complex table. In this new vector, each 'BasedUser' contains
> 'Base', the base
> // of the strided accesses, as well as the old information from
> Uses. We
> @@ -1190,7 +1258,7 @@
> // "A+B"), emit it to the preheader, then remove the expression
> from the
> // UsersToProcess base values.
> SCEVHandle CommonExprs =
> - RemoveCommonExpressionsFromUseBases(UsersToProcess, SE, L);
> + RemoveCommonExpressionsFromUseBases(UsersToProcess, SE, L, TLI);
>
> // Next, figure out what we can represent in the immediate fields of
> // instructions. If we can represent anything there, move it to
> the imm
> @@ -1347,7 +1415,8 @@
> Constant *C = dyn_cast<Constant>(CommonBaseV);
> if (!C ||
> (!C->isNullValue() &&
> - !isTargetConstant(SE->getUnknown(CommonBaseV), ReplacedTy,
> TLI)))
> + !fitsInAddressMode(SE->getUnknown(CommonBaseV), ReplacedTy,
> + TLI, false)))
> // We want the common base emitted into the preheader! This is
> just
> // using cast as a copy so BitCast (no-op cast) is appropriate
> CommonBaseV = new BitCastInst(CommonBaseV, CommonBaseV-
> >getType(),
> @@ -1403,7 +1472,8 @@
> // this by forcing a BitCast (noop cast) to be inserted into the
> preheader
> // in this case.
> if (Constant *C = dyn_cast<Constant>(BaseV)) {
> - if (!C->isNullValue() && !isTargetConstant(Base, ReplacedTy,
> TLI)) {
> + if (!C->isNullValue() && !fitsInAddressMode(Base, ReplacedTy,
> + TLI, false)) {
> // We want this constant emitted into the preheader! This is
> just
> // using cast as a copy so BitCast (no-op cast) is appropriate
> BaseV = new BitCastInst(BaseV, BaseV->getType(),
> "preheaderinsert",
>
> Added: llvm/trunk/test/CodeGen/X86/loop-strength-reduce-2.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/loop-strength-reduce-2.ll?rev=60608&view=auto
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- llvm/trunk/test/CodeGen/X86/loop-strength-reduce-2.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/loop-strength-reduce-2.ll Fri Dec 5
> 15:47:27 2008
> @@ -0,0 +1,30 @@
> +; RUN: llvm-as < %s | llc -march=x86 -relocation-model=pic | \
> +; RUN: grep {A-} | count 1
> +;
> +; Make sure the common loop invariant A is hoisted up to preheader,
> +; since too many registers are needed to subsume it into the
> addressing modes.
> +
> + at A = global [16 x [16 x i32]] zeroinitializer, align 32 ; <[16 x
> [16 x i32]]*> [#uses=2]
> +
> +define void @test(i32 %row, i32 %N.in) nounwind {
> +entry:
> + %N = bitcast i32 %N.in to i32 ; <i32> [#uses=1]
> + %tmp5 = icmp sgt i32 %N.in, 0 ; <i1> [#uses=1]
> + br i1 %tmp5, label %cond_true, label %return
> +
> +cond_true: ; preds = %cond_true, %entry
> + %indvar = phi i32 [ 0, %entry ], [ %indvar.next, %cond_true ] ;
> <i32> [#uses=2]
> + %i.0.0 = bitcast i32 %indvar to i32 ; <i32> [#uses=2]
> + %tmp2 = add i32 %i.0.0, 1 ; <i32> [#uses=1]
> + %tmp = getelementptr [16 x [16 x i32]]* @A, i32 0, i32 %row, i32
> %tmp2 ; <i32*> [#uses=1]
> + store i32 4, i32* %tmp
> + %tmp5.upgrd.1 = add i32 %i.0.0, 2 ; <i32> [#uses=1]
> + %tmp7 = getelementptr [16 x [16 x i32]]* @A, i32 0, i32 %row, i32
> %tmp5.upgrd.1 ; <i32*> [#uses=1]
> + store i32 5, i32* %tmp7
> + %indvar.next = add i32 %indvar, 1 ; <i32> [#uses=2]
> + %exitcond = icmp eq i32 %indvar.next, %N ; <i1> [#uses=1]
> + br i1 %exitcond, label %return, label %cond_true
> +
> +return: ; preds = %cond_true, %entry
> + ret void
> +}
>
> Added: llvm/trunk/test/CodeGen/X86/loop-strength-reduce-3.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/loop-strength-reduce-3.ll?rev=60608&view=auto
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- llvm/trunk/test/CodeGen/X86/loop-strength-reduce-3.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/loop-strength-reduce-3.ll Fri Dec 5
> 15:47:27 2008
> @@ -0,0 +1,30 @@
> +; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin -relocation-
> model=dynamic-no-pic | \
> +; RUN: grep {A+} | count 2
> +;
> +; Make sure the common loop invariant A is not hoisted up to
> preheader,
> +; since it can be subsumed it into the addressing modes.
> +
> + at A = global [16 x [16 x i32]] zeroinitializer, align 32 ; <[16 x
> [16 x i32]]*> [#uses=2]
> +
> +define void @test(i32 %row, i32 %N.in) nounwind {
> +entry:
> + %N = bitcast i32 %N.in to i32 ; <i32> [#uses=1]
> + %tmp5 = icmp sgt i32 %N.in, 0 ; <i1> [#uses=1]
> + br i1 %tmp5, label %cond_true, label %return
> +
> +cond_true: ; preds = %cond_true, %entry
> + %indvar = phi i32 [ 0, %entry ], [ %indvar.next, %cond_true ] ;
> <i32> [#uses=2]
> + %i.0.0 = bitcast i32 %indvar to i32 ; <i32> [#uses=2]
> + %tmp2 = add i32 %i.0.0, 1 ; <i32> [#uses=1]
> + %tmp = getelementptr [16 x [16 x i32]]* @A, i32 0, i32 %row, i32
> %tmp2 ; <i32*> [#uses=1]
> + store i32 4, i32* %tmp
> + %tmp5.upgrd.1 = add i32 %i.0.0, 2 ; <i32> [#uses=1]
> + %tmp7 = getelementptr [16 x [16 x i32]]* @A, i32 0, i32 %row, i32
> %tmp5.upgrd.1 ; <i32*> [#uses=1]
> + store i32 5, i32* %tmp7
> + %indvar.next = add i32 %indvar, 1 ; <i32> [#uses=2]
> + %exitcond = icmp eq i32 %indvar.next, %N ; <i1> [#uses=1]
> + br i1 %exitcond, label %return, label %cond_true
> +
> +return: ; preds = %cond_true, %entry
> + ret void
> +}
>
> Modified: llvm/trunk/test/CodeGen/X86/loop-strength-reduce.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/loop-strength-reduce.ll?rev=60608&r1=60607&r2=60608&view=diff
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- llvm/trunk/test/CodeGen/X86/loop-strength-reduce.ll (original)
> +++ llvm/trunk/test/CodeGen/X86/loop-strength-reduce.ll Fri Dec 5
> 15:47:27 2008
> @@ -1,7 +1,8 @@
> -; RUN: llvm-as < %s | llc -march=x86 | \
> -; RUN: grep {A(} | count 1
> +; RUN: llvm-as < %s | llc -march=x86 -relocation-model=static | \
> +; RUN: grep {A+} | count 2
> ;
> -; Make sure the common loop invariant _A(reg) is hoisted up to
> preheader.
> +; Make sure the common loop invariant A is not hoisted up to
> preheader,
> +; since it can be subsumed into the addressing mode in all uses.
>
> @A = internal global [16 x [16 x i32]] zeroinitializer, align 32 ;
> <[16 x [16 x i32]]*> [#uses=2]
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list