HexagonVectorLoopCarriedReuse.h
4.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//===- HexagonVectorLoopCarriedReuse.h ------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This pass removes the computation of provably redundant expressions that have
// been computed earlier in a previous iteration. It relies on the use of PHIs
// to identify loop carried dependences. This is scalar replacement for vector
// types.
//
//-----------------------------------------------------------------------------
// Motivation: Consider the case where we have the following loop structure.
//
// Loop:
// t0 = a[i];
// t1 = f(t0);
// t2 = g(t1);
// ...
// t3 = a[i+1];
// t4 = f(t3);
// t5 = g(t4);
// t6 = op(t2, t5)
// cond_branch <Loop>
//
// This can be converted to
// t00 = a[0];
// t10 = f(t00);
// t20 = g(t10);
// Loop:
// t2 = t20;
// t3 = a[i+1];
// t4 = f(t3);
// t5 = g(t4);
// t6 = op(t2, t5)
// t20 = t5
// cond_branch <Loop>
//
// SROA does a good job of reusing a[i+1] as a[i] in the next iteration.
// Such a loop comes to this pass in the following form.
//
// LoopPreheader:
// X0 = a[0];
// Loop:
// X2 = PHI<(X0, LoopPreheader), (X1, Loop)>
// t1 = f(X2) <-- I1
// t2 = g(t1)
// ...
// X1 = a[i+1]
// t4 = f(X1) <-- I2
// t5 = g(t4)
// t6 = op(t2, t5)
// cond_branch <Loop>
//
// In this pass, we look for PHIs such as X2 whose incoming values come only
// from the Loop Preheader and over the backedge and additionaly, both these
// values are the results of the same operation in terms of opcode. We call such
// a PHI node a dependence chain or DepChain. In this case, the dependence of X2
// over X1 is carried over only one iteration and so the DepChain is only one
// PHI node long.
//
// Then, we traverse the uses of the PHI (X2) and the uses of the value of the
// PHI coming over the backedge (X1). We stop at the first pair of such users
// I1 (of X2) and I2 (of X1) that meet the following conditions.
// 1. I1 and I2 are the same operation, but with different operands.
// 2. X2 and X1 are used at the same operand number in the two instructions.
// 3. All other operands Op1 of I1 and Op2 of I2 are also such that there is a
// a DepChain from Op1 to Op2 of the same length as that between X2 and X1.
//
// We then make the following transformation
// LoopPreheader:
// X0 = a[0];
// Y0 = f(X0);
// Loop:
// X2 = PHI<(X0, LoopPreheader), (X1, Loop)>
// Y2 = PHI<(Y0, LoopPreheader), (t4, Loop)>
// t1 = f(X2) <-- Will be removed by DCE.
// t2 = g(Y2)
// ...
// X1 = a[i+1]
// t4 = f(X1)
// t5 = g(t4)
// t6 = op(t2, t5)
// cond_branch <Loop>
//
// We proceed until we cannot find any more such instructions I1 and I2.
//
// --- DepChains & Loop carried dependences ---
// Consider a single basic block loop such as
//
// LoopPreheader:
// X0 = ...
// Y0 = ...
// Loop:
// X2 = PHI<(X0, LoopPreheader), (X1, Loop)>
// Y2 = PHI<(Y0, LoopPreheader), (X2, Loop)>
// ...
// X1 = ...
// ...
// cond_branch <Loop>
//
// Then there is a dependence between X2 and X1 that goes back one iteration,
// i.e. X1 is used as X2 in the very next iteration. We represent this as a
// DepChain from X2 to X1 (X2->X1).
// Similarly, there is a dependence between Y2 and X1 that goes back two
// iterations. X1 is used as Y2 two iterations after it is computed. This is
// represented by a DepChain as (Y2->X2->X1).
//
// A DepChain has the following properties.
// 1. Num of edges in DepChain = Number of Instructions in DepChain = Number of
// iterations of carried dependence + 1.
// 2. All instructions in the DepChain except the last are PHIs.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONVLCR_H
#define LLVM_LIB_TARGET_HEXAGON_HEXAGONVLCR_H
#include "llvm/Transforms/Scalar/LoopPassManager.h"
namespace llvm {
class Loop;
/// Hexagon Vector Loop Carried Reuse Pass
struct HexagonVectorLoopCarriedReusePass
: public PassInfoMixin<HexagonVectorLoopCarriedReusePass> {
HexagonVectorLoopCarriedReusePass() {}
/// Run pass over the Loop.
PreservedAnalyses run(Loop &L, LoopAnalysisManager &LAM,
LoopStandardAnalysisResults &AR, LPMUpdater &U);
};
} // end namespace llvm
#endif // LLVM_LIB_TARGET_HEXAGON_HEXAGONVLCR_H