From 6f2dd7ebcf5225bb98594c3504ded9a46c7ed11a Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Fri, 28 Oct 2011 03:45:11 +0000 Subject: LFTR should avoid a type mismatch with null pointer IVs. Fixes rdar://10359193 Indvar LinearFunctionTestReplace assertion git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@143183 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/IndVarSimplify.cpp | 34 +++++++------ .../IndVarSimplify/2011-10-27-lftrnull.ll | 59 ++++++++++++++++++++++ 2 files changed, 77 insertions(+), 16 deletions(-) create mode 100644 test/Transforms/IndVarSimplify/2011-10-27-lftrnull.ll diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp index 874a135..dce7f87 100644 --- a/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -1558,8 +1558,7 @@ LinearFunctionTestReplace(Loop *L, } // For unit stride, IVLimit = Start + BECount with 2's complement overflow. - // So for, non-zero start compute the IVLimit here. - bool isPtrIV = false; + // So for non-zero start compute the IVLimit here. Type *CmpTy = CntTy; const SCEVAddRecExpr *AR = dyn_cast(SE->getSCEV(IndVar)); assert(AR && AR->getLoop() == L && AR->isAffine() && "bad loop counter"); @@ -1571,8 +1570,7 @@ LinearFunctionTestReplace(Loop *L, // Note that for without EnableIVRewrite, we never run SCEVExpander on a // pointer type, because we must preserve the existing GEPs. Instead we // directly generate a GEP later. - if (IVInit->getType()->isPointerTy()) { - isPtrIV = true; + if (CmpIndVar->getType()->isPointerTy()) { CmpTy = SE->getEffectiveSCEVType(IVInit->getType()); IVLimit = SE->getTruncateOrSignExtend(IVLimit, CmpTy); } @@ -1590,21 +1588,25 @@ LinearFunctionTestReplace(Loop *L, assert(SE->isLoopInvariant(IVLimit, L) && "Computed iteration count is not loop invariant!"); + assert( !IVLimit->getType()->isPointerTy() && + "Should not expand pointer types" ); Value *ExitCnt = Rewriter.expandCodeFor(IVLimit, CmpTy, BI); // Create a gep for IVInit + IVLimit from on an existing pointer base. - assert(isPtrIV == IndVar->getType()->isPointerTy() && - "IndVar type must match IVInit type"); - if (isPtrIV) { - Value *IVStart = IndVar->getIncomingValueForBlock(L->getLoopPreheader()); - assert(AR->getStart() == SE->getSCEV(IVStart) && "bad loop counter"); - assert(SE->getSizeOfExpr( - cast(IVStart->getType())->getElementType())->isOne() - && "unit stride pointer IV must be i8*"); - - Builder.SetInsertPoint(L->getLoopPreheader()->getTerminator()); - ExitCnt = Builder.CreateGEP(IVStart, ExitCnt, "lftr.limit"); - Builder.SetInsertPoint(BI); + // + // In the presence of null pointer values, the SCEV expression may be an + // integer type while the IV is a pointer type. Ensure that the compare + // operands are always the same type by checking the IV type here. + if (CmpIndVar->getType()->isPointerTy()) { + Value *IVStart = IndVar->getIncomingValueForBlock(L->getLoopPreheader()); + assert(AR->getStart() == SE->getSCEV(IVStart) && "bad loop counter"); + assert(SE->getSizeOfExpr( + cast(IVStart->getType())->getElementType())->isOne() + && "unit stride pointer IV must be i8*"); + + Builder.SetInsertPoint(L->getLoopPreheader()->getTerminator()); + ExitCnt = Builder.CreateGEP(IVStart, ExitCnt, "lftr.limit"); + Builder.SetInsertPoint(BI); } // Insert a new icmp_ne or icmp_eq instruction before the branch. diff --git a/test/Transforms/IndVarSimplify/2011-10-27-lftrnull.ll b/test/Transforms/IndVarSimplify/2011-10-27-lftrnull.ll new file mode 100644 index 0000000..76c90e0 --- /dev/null +++ b/test/Transforms/IndVarSimplify/2011-10-27-lftrnull.ll @@ -0,0 +1,59 @@ +; RUN: opt < %s -indvars -S | FileCheck %s +; rdar://10359193: assert "IndVar type must match IVInit type" + +target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:32:64-v128:32:128-a0:0:32-n32-S32" +target triple = "thumbv7-apple-darwin" + +; CHECK: @test +; CHECK: if.end.i126: +; CHECK: %exitcond = icmp ne i8* %incdec.ptr.i, getelementptr (i8* null, i32 undef) +define void @test() nounwind { +entry: + br label %while.cond + +while.cond: + br i1 undef, label %while.end, label %while.body + +while.body: ; preds = %while.cond + br i1 undef, label %if.then165, label %while.cond + +if.then165: ; preds = %while.body + br i1 undef, label %while.cond, label %for.body.lr.ph.i81 + +for.body.lr.ph.i81: ; preds = %if.then165 + br label %for.body.i86 + +for.body.i86: ; preds = %for.end.i129, %for.body.lr.ph.i81 + %cmp196.i = icmp ult i32 0, undef + br i1 %cmp196.i, label %for.body21.lr.ph.i, label %for.end.i129 + +for.body21.lr.ph.i: ; preds = %for.body.i86 + br label %for.body21.i + +for.body21.i: + %destYPixelPtr.010.i = phi i8* [ null, %for.body21.lr.ph.i ], [ %incdec.ptr.i, %if.end.i126 ] + %x.09.i = phi i32 [ 0, %for.body21.lr.ph.i ], [ %inc.i125, %if.end.i126 ] + br i1 undef, label %if.end.i126, label %if.else.i124 + +if.else.i124: ; preds = %for.body21.i + store i8 undef, i8* %destYPixelPtr.010.i, align 1 + br label %if.end.i126 + +if.end.i126: ; preds = %if.else.i124, %for.body21.i + %incdec.ptr.i = getelementptr inbounds i8* %destYPixelPtr.010.i, i32 1 + %inc.i125 = add i32 %x.09.i, 1 + %cmp19.i = icmp ult i32 %inc.i125, undef + br i1 %cmp19.i, label %for.body21.i, label %for.end.i129 + +for.end.i129: ; preds = %if.end.i126, %for.body.i86 + br i1 undef, label %for.body.i86, label %while.cond + +while.end: ; preds = %while.cond + br label %bail + +bail: ; preds = %while.end, %lor.lhs.false44, %lor.lhs.false41, %if.end29, %if.end + unreachable + +return: ; preds = %lor.lhs.false20, %lor.lhs.false12, %lor.lhs.false, %entry + ret void +} -- cgit v1.1