llvm.org GIT mirror llvm / f4dbee3
[SCEV] Do not visit nodes twice in containsConstantSomewhere This patch reworks the function that searches constants in Add and Mul SCEV expression chains so that now it does not visit a node more than once, and also renames this function for better correspondence between its implementation and semantics. Differential Revision: https://reviews.llvm.org/D35931 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@309367 91177308-0d34-0410-b5e6-96231b3b80d8 Max Kazantsev 2 years ago
2 changed file(s) with 97 addition(s) and 15 deletion(s). Raw diff Collapse all Expand all
26752675
26762676 /// Determine if any of the operands in this SCEV are a constant or if
26772677 /// any of the add or multiply expressions in this SCEV contain a constant.
2678 static bool containsConstantSomewhere(const SCEV *StartExpr) {
2679 SmallVector Ops;
2680 Ops.push_back(StartExpr);
2681 while (!Ops.empty()) {
2682 const SCEV *CurrentExpr = Ops.pop_back_val();
2683 if (isa(*CurrentExpr))
2684 return true;
2685
2686 if (isa(*CurrentExpr) || isa(*CurrentExpr)) {
2687 const auto *CurrentNAry = cast(CurrentExpr);
2688 Ops.append(CurrentNAry->op_begin(), CurrentNAry->op_end());
2689 }
2690 }
2691 return false;
2678 static bool containsConstantInAddMulChain(const SCEV *StartExpr) {
2679 struct FindConstantInAddMulChain {
2680 bool FoundConstant = false;
2681
2682 bool follow(const SCEV *S) {
2683 FoundConstant |= isa(S);
2684 return isa(S) || isa(S);
2685 }
2686 bool isDone() const {
2687 return FoundConstant;
2688 }
2689 };
2690
2691 FindConstantInAddMulChain F;
2692 SCEVTraversal ST(F);
2693 ST.visitAll(StartExpr);
2694 return F.FoundConstant;
26922695 }
26932696
26942697 /// Get a canonical multiply expression, or something simpler if possible.
27252728 // If any of Add's ops are Adds or Muls with a constant,
27262729 // apply this transformation as well.
27272730 if (Add->getNumOperands() == 2)
2728 if (containsConstantSomewhere(Add))
2731 // TODO: There are some cases where this transformation is not
2732 // profitable, for example:
2733 // Add = (C0 + X) * Y + Z.
2734 // Maybe the scope of this transformation should be narrowed down.
2735 if (containsConstantInAddMulChain(Add))
27292736 return getAddExpr(getMulExpr(LHSC, Add->getOperand(0),
27302737 SCEV::FlagAnyWrap, Depth + 1),
27312738 getMulExpr(LHSC, Add->getOperand(1),
0 ; RUN: opt -loop-unroll -loop-simplify -S < %s | FileCheck %s
1
2 ; This test is one of the tests of PR33494. Its compilation takes
3 ; excessive time if we don't mark visited nodes while looking for
4 ; constants in SCEV expression trees.
5
6 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
7 target triple = "x86_64-unknown-linux-gnu"
8
9 define void @test_01(i32* nocapture %a) local_unnamed_addr {
10
11 ; CHECK-LABEL: @test_01(
12
13 entry:
14 %arrayidx = getelementptr inbounds i32, i32* %a, i64 96
15 %arrayidx.promoted51 = load i32, i32* %arrayidx, align 1
16 br label %while.body
17
18 while.body: ; preds = %entry, %while.end29
19 %0 = phi i32 [ %arrayidx.promoted51, %entry ], [ %7, %while.end29 ]
20 %cmp46 = icmp eq i32 %0, 1
21 %conv47 = zext i1 %cmp46 to i32
22 %1 = add i32 %0, 1
23 %2 = icmp ult i32 %1, 3
24 %div48 = select i1 %2, i32 %0, i32 0
25 %cmp349 = icmp sgt i32 %div48, %conv47
26 br i1 %cmp349, label %while.body4.lr.ph, label %while.end29
27
28 while.body4.lr.ph: ; preds = %while.body
29 br label %while.body4
30
31 while.body4: ; preds = %while.body4.lr.ph, %while.end28
32 %3 = phi i32 [ %0, %while.body4.lr.ph ], [ %mul17.lcssa, %while.end28 ]
33 br label %while.body13
34
35 while.body13: ; preds = %while.body4, %while.end.split
36 %mul1745 = phi i32 [ %3, %while.body4 ], [ %mul17, %while.end.split ]
37 %4 = phi i32 [ 15872, %while.body4 ], [ %add, %while.end.split ]
38 %mul = mul nsw i32 %mul1745, %mul1745
39 %mul17 = mul nsw i32 %mul, %mul1745
40 %cmp22 = icmp eq i32 %4, %mul17
41 br i1 %cmp22, label %while.body13.split, label %while.end.split
42
43 while.body13.split: ; preds = %while.body13
44 br label %while.cond19
45
46 while.cond19: ; preds = %while.cond19, %while.body13.split
47 br label %while.cond19
48
49 while.end.split: ; preds = %while.body13
50 %add = shl nsw i32 %4, 1
51 %tobool12 = icmp eq i32 %add, 0
52 br i1 %tobool12, label %while.end28, label %while.body13
53
54 while.end28: ; preds = %while.end.split
55 %add.lcssa = phi i32 [ %add, %while.end.split ]
56 %mul17.lcssa = phi i32 [ %mul17, %while.end.split ]
57 %cmp = icmp eq i32 %mul17.lcssa, 1
58 %conv = zext i1 %cmp to i32
59 %5 = add i32 %mul17.lcssa, 1
60 %6 = icmp ult i32 %5, 3
61 %div = select i1 %6, i32 %mul17.lcssa, i32 0
62 %cmp3 = icmp sgt i32 %div, %conv
63 br i1 %cmp3, label %while.body4, label %while.cond1.while.end29_crit_edge
64
65 while.cond1.while.end29_crit_edge: ; preds = %while.end28
66 %.lcssa = phi i32 [ %mul17.lcssa, %while.end28 ]
67 %add.lcssa50.lcssa = phi i32 [ %add.lcssa, %while.end28 ]
68 store i32 %add.lcssa50.lcssa, i32* %a, align 4
69 br label %while.end29
70
71 while.end29: ; preds = %while.cond1.while.end29_crit_edge, %while.body
72 %7 = phi i32 [ %.lcssa, %while.cond1.while.end29_crit_edge ], [ %0, %while.body ]
73 br label %while.body
74 }