llvm.org GIT mirror llvm / e1cafb1
[SimplifyIndVar] Replace IVUsers with loop invariant whenever possible Differential Revision: https://reviews.llvm.org/D38415 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@315551 91177308-0d34-0410-b5e6-96231b3b80d8 Hongbin Zheng 2 years ago
5 changed file(s) with 150 addition(s) and 77 deletion(s). Raw diff Collapse all Expand all
2525 class LoopInfo;
2626 class PHINode;
2727 class ScalarEvolution;
28 class SCEVExpander;
2829
2930 /// Interface for visiting interesting IV users that are recognized but not
3031 /// simplified by this utility.
4647 /// by using ScalarEvolution to analyze the IV's recurrence.
4748 bool simplifyUsersOfIV(PHINode *CurrIV, ScalarEvolution *SE, DominatorTree *DT,
4849 LoopInfo *LI, SmallVectorImpl &Dead,
49 IVVisitor *V = nullptr);
50 SCEVExpander &Rewriter, IVVisitor *V = nullptr);
5051
5152 /// SimplifyLoopIVs - Simplify users of induction variables within this
5253 /// loop. This does not actually change or add IVs.
17581758 // Information about sign/zero extensions of CurrIV.
17591759 IndVarSimplifyVisitor Visitor(CurrIV, SE, TTI, DT);
17601760
1761 Changed |= simplifyUsersOfIV(CurrIV, SE, DT, LI, DeadInsts, &Visitor);
1761 Changed |=
1762 simplifyUsersOfIV(CurrIV, SE, DT, LI, DeadInsts, Rewriter, &Visitor);
17621763
17631764 if (Visitor.WI.WidestNativeType) {
17641765 WideIVs.push_back(Visitor.WI);
1818 #include "llvm/ADT/Statistic.h"
1919 #include "llvm/Analysis/LoopInfo.h"
2020 #include "llvm/Analysis/LoopPass.h"
21 #include "llvm/Analysis/ScalarEvolutionExpressions.h"
21 #include "llvm/Analysis/ScalarEvolutionExpander.h"
2222 #include "llvm/IR/DataLayout.h"
2323 #include "llvm/IR/Dominators.h"
2424 #include "llvm/IR/IRBuilder.h"
5454 LoopInfo *LI;
5555 ScalarEvolution *SE;
5656 DominatorTree *DT;
57
57 SCEVExpander &Rewriter;
5858 SmallVectorImpl &DeadInsts;
5959
6060 bool Changed;
6161
6262 public:
6363 SimplifyIndvar(Loop *Loop, ScalarEvolution *SE, DominatorTree *DT,
64 LoopInfo *LI, SmallVectorImpl &Dead)
65 : L(Loop), LI(LI), SE(SE), DT(DT), DeadInsts(Dead), Changed(false) {
64 LoopInfo *LI, SCEVExpander &Rewriter,
65 SmallVectorImpl &Dead)
66 : L(Loop), LI(LI), SE(SE), DT(DT), Rewriter(Rewriter), DeadInsts(Dead),
67 Changed(false) {
6668 assert(LI && "IV simplification requires LoopInfo");
6769 }
6870
7678 Value *foldIVUser(Instruction *UseInst, Instruction *IVOperand);
7779
7880 bool eliminateIdentitySCEV(Instruction *UseInst, Instruction *IVOperand);
79 bool foldConstantSCEV(Instruction *UseInst);
81 bool replaceIVUserWithLoopInvariant(Instruction *UseInst);
8082
8183 bool eliminateOverflowIntrinsic(CallInst *CI);
8284 bool eliminateIVUser(Instruction *UseInst, Instruction *IVOperand);
535537 return false;
536538 }
537539
538 /// Replace the UseInst with a constant if possible
539 bool SimplifyIndvar::foldConstantSCEV(Instruction *I) {
540 static Instruction *GetLoopInvariantInsertPosition(Loop *L, Instruction *Hint) {
541 if (auto *BB = L->getLoopPreheader())
542 return BB->getTerminator();
543
544 return Hint;
545 }
546
547 /// Replace the UseInst with a constant if possible.
548 bool SimplifyIndvar::replaceIVUserWithLoopInvariant(Instruction *I) {
540549 if (!SE->isSCEVable(I->getType()))
541550 return false;
542551
543552 // Get the symbolic expression for this instruction.
544553 const SCEV *S = SE->getSCEV(I);
545554
546 const Loop *L = LI->getLoopFor(I->getParent());
547 S = SE->getSCEVAtScope(S, L);
548 auto *C = dyn_cast(S);
549
550 if (!C)
551 return false;
552
553 Constant *V = C->getValue();
554 // The SCEV will have a different type than the instruction if the instruction
555 // has a pointer type. Skip the replacement
556 // TODO: Replace ConstantInt Zero by ConstantPointerNull
557 if (V->getType() != I->getType())
558 return false;
559
560 I->replaceAllUsesWith(V);
561 DEBUG(dbgs() << "INDVARS: Replace IV user: " << *I << " with constant: " << *C
562 << '\n');
555 if (!SE->isLoopInvariant(S, L))
556 return false;
557
558 // Do not generate something ridiculous even if S is loop invariant.
559 if (Rewriter.isHighCostExpansion(S, L, I))
560 return false;
561
562 auto *IP = GetLoopInvariantInsertPosition(L, I);
563 auto *Invariant = Rewriter.expandCodeFor(S, I->getType(), IP);
564
565 I->replaceAllUsesWith(Invariant);
566 DEBUG(dbgs() << "INDVARS: Replace IV user: " << *I
567 << " with loop invariant: " << *S << '\n');
563568 ++NumFoldedUser;
564569 Changed = true;
565570 DeadInsts.emplace_back(I);
701706
702707 /// Add all uses of Def to the current IV's worklist.
703708 static void pushIVUsers(
704 Instruction *Def,
709 Instruction *Def, Loop *L,
705710 SmallPtrSet &Simplified,
706711 SmallVectorImpl< std::pair > &SimpleIVUsers) {
707712
712717 // Also ensure unique worklist users.
713718 // If Def is a LoopPhi, it may not be in the Simplified set, so check for
714719 // self edges first.
715 if (UI != Def && Simplified.insert(UI).second)
716 SimpleIVUsers.push_back(std::make_pair(UI, Def));
720 if (UI == Def)
721 continue;
722
723 // Only change the current Loop, do not change the other parts (e.g. other
724 // Loops).
725 if (!L->contains(UI))
726 continue;
727
728 // Do not push the same instruction more than once.
729 if (!Simplified.insert(UI).second)
730 continue;
731
732 SimpleIVUsers.push_back(std::make_pair(UI, Def));
717733 }
718734 }
719735
763779 // Push users of the current LoopPhi. In rare cases, pushIVUsers may be
764780 // called multiple times for the same LoopPhi. This is the proper thing to
765781 // do for loop header phis that use each other.
766 pushIVUsers(CurrIV, Simplified, SimpleIVUsers);
782 pushIVUsers(CurrIV, L, Simplified, SimpleIVUsers);
767783
768784 while (!SimpleIVUsers.empty()) {
769785 std::pair UseOper =
773789 // Bypass back edges to avoid extra work.
774790 if (UseInst == CurrIV) continue;
775791
776 // Try to replace UseInst with a constant before any other simplifications
777 if (foldConstantSCEV(UseInst))
792 // Try to replace UseInst with a loop invariant before any other
793 // simplifications.
794 if (replaceIVUserWithLoopInvariant(UseInst))
778795 continue;
779796
780797 Instruction *IVOperand = UseOper.second;
790807 continue;
791808
792809 if (eliminateIVUser(UseOper.first, IVOperand)) {
793 pushIVUsers(IVOperand, Simplified, SimpleIVUsers);
810 pushIVUsers(IVOperand, L, Simplified, SimpleIVUsers);
794811 continue;
795812 }
796813
800817 (isa(BO) && strengthenRightShift(BO, IVOperand))) {
801818 // re-queue uses of the now modified binary operator and fall
802819 // through to the checks that remain.
803 pushIVUsers(IVOperand, Simplified, SimpleIVUsers);
820 pushIVUsers(IVOperand, L, Simplified, SimpleIVUsers);
804821 }
805822 }
806823
810827 continue;
811828 }
812829 if (isSimpleIVUser(UseOper.first, L, SE)) {
813 pushIVUsers(UseOper.first, Simplified, SimpleIVUsers);
830 pushIVUsers(UseOper.first, L, Simplified, SimpleIVUsers);
814831 }
815832 }
816833 }
823840 /// by using ScalarEvolution to analyze the IV's recurrence.
824841 bool simplifyUsersOfIV(PHINode *CurrIV, ScalarEvolution *SE, DominatorTree *DT,
825842 LoopInfo *LI, SmallVectorImpl &Dead,
826 IVVisitor *V) {
827 SimplifyIndvar SIV(LI->getLoopFor(CurrIV->getParent()), SE, DT, LI, Dead);
843 SCEVExpander &Rewriter, IVVisitor *V) {
844 SimplifyIndvar SIV(LI->getLoopFor(CurrIV->getParent()), SE, DT, LI, Rewriter,
845 Dead);
828846 SIV.simplifyUsers(CurrIV, V);
829847 return SIV.hasChanged();
830848 }
833851 /// loop. This does not actually change or add IVs.
834852 bool simplifyLoopIVs(Loop *L, ScalarEvolution *SE, DominatorTree *DT,
835853 LoopInfo *LI, SmallVectorImpl &Dead) {
854 SCEVExpander Rewriter(*SE, SE->getDataLayout(), "indvars");
855 #ifndef NDEBUG
856 Rewriter.setDebugType(DEBUG_TYPE);
857 #endif
836858 bool Changed = false;
837859 for (BasicBlock::iterator I = L->getHeader()->begin(); isa(I); ++I) {
838 Changed |= simplifyUsersOfIV(cast(I), SE, DT, LI, Dead);
860 Changed |= simplifyUsersOfIV(cast(I), SE, DT, LI, Dead, Rewriter);
839861 }
840862 return Changed;
841863 }
+0
-39
test/Transforms/IndVarSimplify/constant-fold-1.ll less more
None ; RUN: opt < %s -indvars -S | FileCheck %s
1
2 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
3 target triple = "x86_64-unknown-linux-gnu"
4
5 define void @test(i64* %arg) unnamed_addr align 2 {
6 bb:
7 switch i64 undef, label %bb1 [
8 ]
9
10 bb1: ; preds = %bb
11 br label %bb2
12
13 bb2: ; preds = %bb6, %bb1
14 %tmp = phi i64* [%arg, %bb1 ], [ %tmp7, %bb6 ]
15 switch i2 undef, label %bb6 [
16 i2 1, label %bb5
17 i2 -2, label %bb3
18 i2 -1, label %bb3
19 ]
20
21 bb3: ; preds = %bb2, %bb2
22 %tmp4 = call fastcc i32* @wobble(i64* nonnull %tmp, i32* null)
23 %tmp5 = load i32, i32* %tmp4 , align 8
24 br label %bb6
25
26 bb5: ; preds = %bb2
27 unreachable
28
29 bb6: ; preds = %bb3, %bb2
30 %tmp7 = load i64*, i64** undef, align 8
31 br label %bb2
32 }
33
34 declare i32* @wobble(i64*, i32* returned)
35
36 ; Should not fail when SCEV is fold to ConstantPointerNull
37 ; CHECK-LABEL: void @test
38 ; CHECK: load i32, i32* %{{[a-zA-Z$._0-9]+}}
0 ; RUN: opt < %s -indvars -S | FileCheck %s
1
2 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
3 target triple = "x86_64-unknown-linux-gnu"
4
5 @G = external global i32
6
7 define void @test0(i64* %arg) {
8 bb:
9 br label %bb2
10
11 bb2:
12 %tmp = phi i64* [%arg, %bb ], [ %tmp7, %bb2 ]
13 %tmp4 = call i32* @wobble(i64* nonnull %tmp, i32* null)
14 %tmp5 = load i32, i32* %tmp4, align 8
15 %tmp7 = load i64*, i64** undef, align 8
16 br label %bb2
17 }
18
19 ; CHECK-LABEL: void @test0
20 ; CHECK: load i32, i32* null
21
22 define void @test1(i64* %arg) {
23 bb:
24 br label %bb2
25
26 bb2:
27 %tmp = phi i64* [%arg, %bb ], [ %tmp7, %bb2 ]
28 %tmp4 = call i32* @wobble(i64* nonnull %tmp, i32* inttoptr (i64 4 to i32*))
29 %tmp5 = load i32, i32* %tmp4
30 %tmp7 = load i64*, i64** undef, align 8
31 br label %bb2
32 }
33
34 ; CHECK-LABEL: void @test1
35 ; CHECK: load i32, i32* inttoptr (i64 4 to i32*)
36
37 define void @test2(i64* %arg) {
38 bb:
39 br label %bb2
40
41 bb2:
42 %tmp = phi i64* [%arg, %bb ], [ %tmp7, %bb2 ]
43 %tmp4 = call i32* @wobble(i64* nonnull %tmp, i32* @G)
44 %tmp5 = load i32, i32* %tmp4
45 %tmp7 = load i64*, i64** undef, align 8
46 br label %bb2
47 }
48
49 ; CHECK-LABEL: void @test2
50 ; CHECK: load i32, i32* @G
51
52
53 define void @test3(i64* %arg, i32* %loop.invariant) {
54 bb:
55 br label %bb2
56
57 bb2:
58 %tmp = phi i64* [%arg, %bb ], [ %tmp7, %bb2 ]
59 %tmp4 = call i32* @wobble(i64* nonnull %tmp, i32* %loop.invariant)
60 %tmp5 = load i32, i32* %tmp4
61 %tmp7 = load i64*, i64** undef, align 8
62 br label %bb2
63 }
64
65 ; CHECK-LABEL: void @test3
66 ; CHECK: load i32, i32* %loop.invariant
67
68 define void @test4(i64* %arg, i32* %loop.invariant, i64 %N) {
69 bb:
70 br label %bb2
71
72 bb2:
73 %tmp = phi i64* [%arg, %bb ], [ %tmp7, %bb2 ]
74 %mul = mul nsw i64 %N, 64
75 %ptr = getelementptr inbounds i32, i32* %loop.invariant, i64 %mul
76 %tmp4 = call i32* @wobble(i64* nonnull %tmp, i32* %ptr)
77 %tmp5 = load i32, i32* %tmp4
78 %tmp7 = load i64*, i64** undef, align 8
79 br label %bb2
80 }
81
82 ; CHECK-LABEL: void @test4
83 ; CHECK: [[P:%[a-zA-Z$._0-9]+]] = getelementptr i32, i32* %loop.invariant
84 ; CHECK: phi
85 ; CHECK: load i32, i32* [[P]]
86
87 declare i32* @wobble(i64*, i32* returned)