From da1c0f6889abf20ea440be2d76f1b75dae49dbbe Mon Sep 17 00:00:00 2001 From: Philip Reames Date: Wed, 3 Jul 2019 20:03:46 +0000 Subject: [PATCH] [LFTR] Use SCEVExpander for the pointer limit case instead of manual IR gen As noted in the test change, this is not trivially NFC, but all of the changes in output are cases where the SCEVExpander form is more canonical/optimal than the hand generation. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@365075 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/IndVarSimplify.cpp | 15 +++++---------- test/Transforms/IndVarSimplify/2011-11-01-lftrptr.ll | 8 ++++---- .../IndVarSimplify/lftr-address-space-pointers.ll | 6 ++---- test/Transforms/IndVarSimplify/lftr-dead-ivs.ll | 6 +++--- test/Transforms/IndVarSimplify/lftr-pr41998.ll | 4 ++-- test/Transforms/IndVarSimplify/lftr-reuse.ll | 7 +++---- 6 files changed, 19 insertions(+), 27 deletions(-) diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp index 84a94027b0a..1031916797e 100644 --- a/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -2329,21 +2329,17 @@ static Value *genLoopLimit(PHINode *IndVar, BasicBlock *ExitingBB, // Expand the code for the iteration count. assert(SE->isLoopInvariant(IVOffset, L) && "Computed iteration count is not loop invariant!"); - BranchInst *BI = cast(ExitingBB->getTerminator()); - Value *GEPOffset = Rewriter.expandCodeFor(IVOffset, OfsTy, BI); - Value *GEPBase = IndVar->getIncomingValueForBlock(L->getLoopPreheader()); - assert(AR->getStart() == SE->getSCEV(GEPBase) && "bad loop counter"); // We could handle pointer IVs other than i8*, but we need to compensate for // gep index scaling. assert(SE->getSizeOfExpr(IntegerType::getInt64Ty(IndVar->getContext()), - cast(GEPBase->getType()) + cast(IndVar->getType()) ->getElementType())->isOne() && "unit stride pointer IV must be i8*"); - IRBuilder<> Builder(L->getLoopPreheader()->getTerminator()); - return Builder.CreateGEP(GEPBase->getType()->getPointerElementType(), - GEPBase, GEPOffset, "lftr.limit"); + const SCEV *IVLimit = SE->getAddExpr(IVInit, IVOffset); + BranchInst *BI = cast(ExitingBB->getTerminator()); + return Rewriter.expandCodeFor(IVLimit, IndVar->getType(), BI); } else { // In any other case, convert both IVInit and ExitCount to integers before // comparing. This may result in SCEV expansion of pointers, but in practice @@ -2379,8 +2375,6 @@ static Value *genLoopLimit(PHINode *IndVar, BasicBlock *ExitingBB, IVLimit = SE->getAddExpr(IVLimit, SE->getOne(IVLimit->getType())); // Expand the code for the iteration count. - BranchInst *BI = cast(ExitingBB->getTerminator()); - IRBuilder<> Builder(BI); assert(SE->isLoopInvariant(IVLimit, L) && "Computed iteration count is not loop invariant!"); // Ensure that we generate the same type as IndVar, or a smaller integer @@ -2388,6 +2382,7 @@ static Value *genLoopLimit(PHINode *IndVar, BasicBlock *ExitingBB, // SCEV expression (IVInit) for a pointer type IV value (IndVar). Type *LimitTy = ExitCount->getType()->isPointerTy() ? IndVar->getType() : ExitCount->getType(); + BranchInst *BI = cast(ExitingBB->getTerminator()); return Rewriter.expandCodeFor(IVLimit, LimitTy, BI); } } diff --git a/test/Transforms/IndVarSimplify/2011-11-01-lftrptr.ll b/test/Transforms/IndVarSimplify/2011-11-01-lftrptr.ll index 48c8925b5ad..e1ef6bd6635 100644 --- a/test/Transforms/IndVarSimplify/2011-11-01-lftrptr.ll +++ b/test/Transforms/IndVarSimplify/2011-11-01-lftrptr.ll @@ -150,13 +150,13 @@ define i8 @testnullptrint(i8* %buf, i8* %end) nounwind { ; PTR64-NEXT: [[TMP2:%.*]] = sub i32 [[TMP1]], [[BI]] ; PTR64-NEXT: [[TMP3:%.*]] = zext i32 [[TMP2]] to i64 ; PTR64-NEXT: [[TMP4:%.*]] = add nuw nsw i64 [[TMP3]], 1 -; PTR64-NEXT: [[LFTR_LIMIT:%.*]] = getelementptr i8, i8* null, i64 [[TMP4]] +; PTR64-NEXT: [[TMP5:%.*]] = inttoptr i64 [[TMP4]] to i8* ; PTR64-NEXT: br label [[LOOP:%.*]] ; PTR64: loop: ; PTR64-NEXT: [[P_01_US_US:%.*]] = phi i8* [ null, [[PREHEADER]] ], [ [[GEP:%.*]], [[LOOP]] ] ; PTR64-NEXT: [[GEP]] = getelementptr inbounds i8, i8* [[P_01_US_US]], i64 1 ; PTR64-NEXT: [[SNEXT:%.*]] = load i8, i8* [[GEP]] -; PTR64-NEXT: [[EXITCOND:%.*]] = icmp ne i8* [[GEP]], [[LFTR_LIMIT]] +; PTR64-NEXT: [[EXITCOND:%.*]] = icmp ne i8* [[GEP]], [[TMP5]] ; PTR64-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] ; PTR64: exit.loopexit: ; PTR64-NEXT: [[SNEXT_LCSSA:%.*]] = phi i8 [ [[SNEXT]], [[LOOP]] ] @@ -171,16 +171,16 @@ define i8 @testnullptrint(i8* %buf, i8* %end) nounwind { ; PTR32-NEXT: [[BI:%.*]] = ptrtoint i8* [[BUF:%.*]] to i32 ; PTR32-NEXT: [[EI:%.*]] = ptrtoint i8* [[END:%.*]] to i32 ; PTR32-NEXT: [[CNT:%.*]] = sub i32 [[EI]], [[BI]] +; PTR32-NEXT: [[CNT1:%.*]] = inttoptr i32 [[CNT]] to i8* ; PTR32-NEXT: [[GUARD:%.*]] = icmp ult i32 0, [[CNT]] ; PTR32-NEXT: br i1 [[GUARD]], label [[PREHEADER:%.*]], label [[EXIT:%.*]] ; PTR32: preheader: -; PTR32-NEXT: [[LFTR_LIMIT:%.*]] = getelementptr i8, i8* null, i32 [[CNT]] ; PTR32-NEXT: br label [[LOOP:%.*]] ; PTR32: loop: ; PTR32-NEXT: [[P_01_US_US:%.*]] = phi i8* [ null, [[PREHEADER]] ], [ [[GEP:%.*]], [[LOOP]] ] ; PTR32-NEXT: [[GEP]] = getelementptr inbounds i8, i8* [[P_01_US_US]], i64 1 ; PTR32-NEXT: [[SNEXT:%.*]] = load i8, i8* [[GEP]] -; PTR32-NEXT: [[EXITCOND:%.*]] = icmp ne i8* [[GEP]], [[LFTR_LIMIT]] +; PTR32-NEXT: [[EXITCOND:%.*]] = icmp ne i8* [[GEP]], [[CNT1]] ; PTR32-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] ; PTR32: exit.loopexit: ; PTR32-NEXT: [[SNEXT_LCSSA:%.*]] = phi i8 [ [[SNEXT]], [[LOOP]] ] diff --git a/test/Transforms/IndVarSimplify/lftr-address-space-pointers.ll b/test/Transforms/IndVarSimplify/lftr-address-space-pointers.ll index 3291930fc58..e77d4bc300f 100644 --- a/test/Transforms/IndVarSimplify/lftr-address-space-pointers.ll +++ b/test/Transforms/IndVarSimplify/lftr-address-space-pointers.ll @@ -11,7 +11,6 @@ define void @ptriv_as2(i8 addrspace(2)* %base, i32 %n) nounwind { ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8 addrspace(2)* [[BASE]], [[ADD_PTR]] ; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]] ; CHECK: for.body.preheader: -; CHECK-NEXT: [[LFTR_LIMIT:%.*]] = getelementptr i8, i8 addrspace(2)* [[BASE]], i8 [[IDX_TRUNC]] ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: ; CHECK-NEXT: [[P_02:%.*]] = phi i8 addrspace(2)* [ [[INCDEC_PTR:%.*]], [[FOR_BODY]] ], [ [[BASE]], [[FOR_BODY_PREHEADER]] ] @@ -20,7 +19,7 @@ define void @ptriv_as2(i8 addrspace(2)* %base, i32 %n) nounwind { ; CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i8 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]] ; CHECK-NEXT: store i8 [[SUB_PTR_SUB]], i8 addrspace(2)* [[P_02]] ; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds i8, i8 addrspace(2)* [[P_02]], i32 1 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i8 addrspace(2)* [[INCDEC_PTR]], [[LFTR_LIMIT]] +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i8 addrspace(2)* [[INCDEC_PTR]], [[ADD_PTR]] ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]] ; CHECK: for.end.loopexit: ; CHECK-NEXT: br label [[FOR_END]] @@ -58,7 +57,6 @@ define void @ptriv_as3(i8 addrspace(3)* %base, i32 %n) nounwind { ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8 addrspace(3)* [[BASE]], [[ADD_PTR]] ; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]] ; CHECK: for.body.preheader: -; CHECK-NEXT: [[LFTR_LIMIT:%.*]] = getelementptr i8, i8 addrspace(3)* [[BASE]], i16 [[IDX_TRUNC]] ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: ; CHECK-NEXT: [[P_02:%.*]] = phi i8 addrspace(3)* [ [[INCDEC_PTR:%.*]], [[FOR_BODY]] ], [ [[BASE]], [[FOR_BODY_PREHEADER]] ] @@ -68,7 +66,7 @@ define void @ptriv_as3(i8 addrspace(3)* %base, i32 %n) nounwind { ; CHECK-NEXT: [[CONV:%.*]] = trunc i16 [[SUB_PTR_SUB]] to i8 ; CHECK-NEXT: store i8 [[CONV]], i8 addrspace(3)* [[P_02]] ; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds i8, i8 addrspace(3)* [[P_02]], i32 1 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i8 addrspace(3)* [[INCDEC_PTR]], [[LFTR_LIMIT]] +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i8 addrspace(3)* [[INCDEC_PTR]], [[ADD_PTR]] ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]] ; CHECK: for.end.loopexit: ; CHECK-NEXT: br label [[FOR_END]] diff --git a/test/Transforms/IndVarSimplify/lftr-dead-ivs.ll b/test/Transforms/IndVarSimplify/lftr-dead-ivs.ll index b538ec0b15e..5ef6b4a6e78 100644 --- a/test/Transforms/IndVarSimplify/lftr-dead-ivs.ll +++ b/test/Transforms/IndVarSimplify/lftr-dead-ivs.ll @@ -112,7 +112,7 @@ define void @dom_store_preinc() #0 { ; CHECK-NEXT: [[P_0:%.*]] = phi i8* [ getelementptr inbounds ([240 x i8], [240 x i8]* @data, i64 0, i64 0), [[ENTRY:%.*]] ], [ [[TMP3:%.*]], [[LOOP]] ] ; CHECK-NEXT: store volatile i8 0, i8* [[P_0]] ; CHECK-NEXT: [[TMP3]] = getelementptr inbounds i8, i8* [[P_0]], i64 1 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i8* [[P_0]], getelementptr (i8, i8* getelementptr inbounds ([240 x i8], [240 x i8]* @data, i64 0, i64 0), i64 245) +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i8* [[P_0]], getelementptr ([240 x i8], [240 x i8]* @data, i64 1, i64 5) ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: ; CHECK-NEXT: ret void @@ -141,7 +141,7 @@ define void @dom_store_postinc() #0 { ; CHECK-NEXT: [[P_0:%.*]] = phi i8* [ getelementptr inbounds ([240 x i8], [240 x i8]* @data, i64 0, i64 0), [[ENTRY:%.*]] ], [ [[TMP3:%.*]], [[LOOP]] ] ; CHECK-NEXT: [[TMP3]] = getelementptr inbounds i8, i8* [[P_0]], i64 1 ; CHECK-NEXT: store volatile i8 0, i8* [[TMP3]] -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i8* [[TMP3]], getelementptr (i8, i8* getelementptr inbounds ([240 x i8], [240 x i8]* @data, i64 0, i64 0), i64 246) +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i8* [[TMP3]], getelementptr ([240 x i8], [240 x i8]* @data, i64 1, i64 6) ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: ; CHECK-NEXT: ret void @@ -170,7 +170,7 @@ define i8 @dom_load() #0 { ; CHECK-NEXT: [[P_0:%.*]] = phi i8* [ getelementptr inbounds ([240 x i8], [240 x i8]* @data, i64 0, i64 0), [[ENTRY:%.*]] ], [ [[TMP3:%.*]], [[LOOP]] ] ; CHECK-NEXT: [[TMP3]] = getelementptr inbounds i8, i8* [[P_0]], i64 1 ; CHECK-NEXT: [[V:%.*]] = load i8, i8* [[TMP3]] -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i8* [[TMP3]], getelementptr (i8, i8* getelementptr inbounds ([240 x i8], [240 x i8]* @data, i64 0, i64 0), i64 246) +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i8* [[TMP3]], getelementptr ([240 x i8], [240 x i8]* @data, i64 1, i64 6) ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: ; CHECK-NEXT: [[V_LCSSA:%.*]] = phi i8 [ [[V]], [[LOOP]] ] diff --git a/test/Transforms/IndVarSimplify/lftr-pr41998.ll b/test/Transforms/IndVarSimplify/lftr-pr41998.ll index 6ec5a2d8d8e..471254ac42c 100644 --- a/test/Transforms/IndVarSimplify/lftr-pr41998.ll +++ b/test/Transforms/IndVarSimplify/lftr-pr41998.ll @@ -45,13 +45,13 @@ define void @test_ptr(i32 %start) { ; CHECK-NEXT: [[TMP1:%.*]] = sub i3 -1, [[TMP0]] ; CHECK-NEXT: [[TMP2:%.*]] = zext i3 [[TMP1]] to i64 ; CHECK-NEXT: [[TMP3:%.*]] = add nuw nsw i64 [[TMP2]], 1 -; CHECK-NEXT: [[LFTR_LIMIT:%.*]] = getelementptr i8, i8* getelementptr inbounds ([256 x i8], [256 x i8]* @data, i64 0, i64 0), i64 [[TMP3]] +; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr [256 x i8], [256 x i8]* @data, i64 0, i64 [[TMP3]] ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[P:%.*]] = phi i8* [ getelementptr inbounds ([256 x i8], [256 x i8]* @data, i64 0, i64 0), [[ENTRY:%.*]] ], [ [[P_INC:%.*]], [[LOOP]] ] ; CHECK-NEXT: [[P_INC]] = getelementptr inbounds i8, i8* [[P]], i64 1 ; CHECK-NEXT: store volatile i8 0, i8* [[P_INC]] -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i8* [[P_INC]], [[LFTR_LIMIT]] +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i8* [[P_INC]], [[SCEVGEP]] ; CHECK-NEXT: br i1 [[EXITCOND]], label [[END:%.*]], label [[LOOP]] ; CHECK: end: ; CHECK-NEXT: ret void diff --git a/test/Transforms/IndVarSimplify/lftr-reuse.ll b/test/Transforms/IndVarSimplify/lftr-reuse.ll index c14b452dfa2..14ae9738696 100644 --- a/test/Transforms/IndVarSimplify/lftr-reuse.ll +++ b/test/Transforms/IndVarSimplify/lftr-reuse.ll @@ -20,7 +20,6 @@ define void @ptriv(i8* %base, i32 %n) nounwind { ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8* [[BASE]], [[ADD_PTR]] ; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]] ; CHECK: for.body.preheader: -; CHECK-NEXT: [[LFTR_LIMIT:%.*]] = getelementptr i8, i8* [[BASE]], i64 [[IDX_EXT]] ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: ; CHECK-NEXT: [[P_02:%.*]] = phi i8* [ [[INCDEC_PTR:%.*]], [[FOR_BODY]] ], [ [[BASE]], [[FOR_BODY_PREHEADER]] ] @@ -30,7 +29,7 @@ define void @ptriv(i8* %base, i32 %n) nounwind { ; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[SUB_PTR_SUB]] to i8 ; CHECK-NEXT: store i8 [[CONV]], i8* [[P_02]] ; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds i8, i8* [[P_02]], i32 1 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i8* [[INCDEC_PTR]], [[LFTR_LIMIT]] +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i8* [[INCDEC_PTR]], [[ADD_PTR]] ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]] ; CHECK: for.end.loopexit: ; CHECK-NEXT: br label [[FOR_END]] @@ -303,13 +302,13 @@ define void @aryptriv([256 x i8]* %base, i32 %n) nounwind { ; CHECK-NEXT: br i1 [[CMP_PH]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] ; CHECK: loop.preheader: ; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[N]] to i64 -; CHECK-NEXT: [[LFTR_LIMIT:%.*]] = getelementptr i8, i8* [[IVSTART]], i64 [[TMP0]] +; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr [256 x i8], [256 x i8]* [[BASE]], i64 0, i64 [[TMP0]] ; CHECK-NEXT: br label [[LOOP:%.*]] ; CHECK: loop: ; CHECK-NEXT: [[APTR:%.*]] = phi i8* [ [[INCDEC_PTR:%.*]], [[LOOP]] ], [ [[IVSTART]], [[LOOP_PREHEADER]] ] ; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds i8, i8* [[APTR]], i32 1 ; CHECK-NEXT: store i8 3, i8* [[APTR]] -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i8* [[INCDEC_PTR]], [[LFTR_LIMIT]] +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i8* [[INCDEC_PTR]], [[SCEVGEP]] ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] ; CHECK: exit.loopexit: ; CHECK-NEXT: br label [[EXIT]] -- 2.11.0