Coverage Report

Created: 2018-09-23 16:00

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/include/llvm/CodeGen/PBQP/ReductionRules.h
Line
Count
Source (jump to first uncovered line)
1
//===- ReductionRules.h - Reduction Rules -----------------------*- C++ -*-===//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
//
10
// Reduction Rules.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#ifndef LLVM_CODEGEN_PBQP_REDUCTIONRULES_H
15
#define LLVM_CODEGEN_PBQP_REDUCTIONRULES_H
16
17
#include "Graph.h"
18
#include "Math.h"
19
#include "Solution.h"
20
#include <cassert>
21
#include <limits>
22
23
namespace llvm {
24
namespace PBQP {
25
26
  /// Reduce a node of degree one.
27
  ///
28
  /// Propagate costs from the given node, which must be of degree one, to its
29
  /// neighbor. Notify the problem domain.
30
  template <typename GraphT>
31
17
  void applyR1(GraphT &G, typename GraphT::NodeId NId) {
32
17
    using NodeId = typename GraphT::NodeId;
33
17
    using EdgeId = typename GraphT::EdgeId;
34
17
    using Vector = typename GraphT::Vector;
35
17
    using Matrix = typename GraphT::Matrix;
36
17
    using RawVector = typename GraphT::RawVector;
37
17
38
17
    assert(G.getNodeDegree(NId) == 1 &&
39
17
           "R1 applied to node with degree != 1.");
40
17
41
17
    EdgeId EId = *G.adjEdgeIds(NId).begin();
42
17
    NodeId MId = G.getEdgeOtherNodeId(EId, NId);
43
17
44
17
    const Matrix &ECosts = G.getEdgeCosts(EId);
45
17
    const Vector &XCosts = G.getNodeCosts(NId);
46
17
    RawVector YCosts = G.getNodeCosts(MId);
47
17
48
17
    // Duplicate a little to avoid transposing matrices.
49
17
    if (NId == G.getEdgeNode1Id(EId)) {
50
192
      for (unsigned j = 0; j < YCosts.getLength(); 
++j186
) {
51
186
        PBQPNum Min = ECosts[0][j] + XCosts[0];
52
5.85k
        for (unsigned i = 1; i < XCosts.getLength(); 
++i5.66k
) {
53
5.66k
          PBQPNum C = ECosts[i][j] + XCosts[i];
54
5.66k
          if (C < Min)
55
242
            Min = C;
56
5.66k
        }
57
186
        YCosts[j] += Min;
58
186
      }
59
11
    } else {
60
316
      for (unsigned i = 0; i < YCosts.getLength(); 
++i305
) {
61
305
        PBQPNum Min = ECosts[i][0] + XCosts[0];
62
9.52k
        for (unsigned j = 1; j < XCosts.getLength(); 
++j9.22k
) {
63
9.22k
          PBQPNum C = ECosts[i][j] + XCosts[j];
64
9.22k
          if (C < Min)
65
305
            Min = C;
66
9.22k
        }
67
305
        YCosts[i] += Min;
68
305
      }
69
11
    }
70
17
    G.setNodeCosts(MId, YCosts);
71
17
    G.disconnectEdge(EId, MId);
72
17
  }
73
74
  template <typename GraphT>
75
35
  void applyR2(GraphT &G, typename GraphT::NodeId NId) {
76
35
    using NodeId = typename GraphT::NodeId;
77
35
    using EdgeId = typename GraphT::EdgeId;
78
35
    using Vector = typename GraphT::Vector;
79
35
    using Matrix = typename GraphT::Matrix;
80
35
    using RawMatrix = typename GraphT::RawMatrix;
81
35
82
35
    assert(G.getNodeDegree(NId) == 2 &&
83
35
           "R2 applied to node with degree != 2.");
84
35
85
35
    const Vector &XCosts = G.getNodeCosts(NId);
86
35
87
35
    typename GraphT::AdjEdgeItr AEItr = G.adjEdgeIds(NId).begin();
88
35
    EdgeId YXEId = *AEItr,
89
35
           ZXEId = *(++AEItr);
90
35
91
35
    NodeId YNId = G.getEdgeOtherNodeId(YXEId, NId),
92
35
           ZNId = G.getEdgeOtherNodeId(ZXEId, NId);
93
35
94
35
    bool FlipEdge1 = (G.getEdgeNode1Id(YXEId) == NId),
95
35
         FlipEdge2 = (G.getEdgeNode1Id(ZXEId) == NId);
96
35
97
35
    const Matrix *YXECosts = FlipEdge1 ?
98
6
      new Matrix(G.getEdgeCosts(YXEId).transpose()) :
99
35
      
&G.getEdgeCosts(YXEId)29
;
100
35
101
35
    const Matrix *ZXECosts = FlipEdge2 ?
102
21
      new Matrix(G.getEdgeCosts(ZXEId).transpose()) :
103
35
      
&G.getEdgeCosts(ZXEId)14
;
104
35
105
35
    unsigned XLen = XCosts.getLength(),
106
35
      YLen = YXECosts->getRows(),
107
35
      ZLen = ZXECosts->getRows();
108
35
109
35
    RawMatrix Delta(YLen, ZLen);
110
35
111
1.12k
    for (unsigned i = 0; i < YLen; 
++i1.09k
) {
112
36.3k
      for (unsigned j = 0; j < ZLen; 
++j35.2k
) {
113
35.2k
        PBQPNum Min = (*YXECosts)[i][0] + (*ZXECosts)[j][0] + XCosts[0];
114
1.14M
        for (unsigned k = 1; k < XLen; 
++k1.11M
) {
115
1.11M
          PBQPNum C = (*YXECosts)[i][k] + (*ZXECosts)[j][k] + XCosts[k];
116
1.11M
          if (C < Min) {
117
39.3k
            Min = C;
118
39.3k
          }
119
1.11M
        }
120
35.2k
        Delta[i][j] = Min;
121
35.2k
      }
122
1.09k
    }
123
35
124
35
    if (FlipEdge1)
125
6
      delete YXECosts;
126
35
127
35
    if (FlipEdge2)
128
21
      delete ZXECosts;
129
35
130
35
    EdgeId YZEId = G.findEdge(YNId, ZNId);
131
35
132
35
    if (YZEId == G.invalidEdgeId()) {
133
0
      YZEId = G.addEdge(YNId, ZNId, Delta);
134
35
    } else {
135
35
      const Matrix &YZECosts = G.getEdgeCosts(YZEId);
136
35
      if (YNId == G.getEdgeNode1Id(YZEId)) {
137
33
        G.updateEdgeCosts(YZEId, Delta + YZECosts);
138
33
      } else {
139
2
        G.updateEdgeCosts(YZEId, Delta.transpose() + YZECosts);
140
2
      }
141
35
    }
142
35
143
35
    G.disconnectEdge(YXEId, YNId);
144
35
    G.disconnectEdge(ZXEId, ZNId);
145
35
146
35
    // TODO: Try to normalize newly added/modified edge.
147
35
  }
148
149
#ifndef NDEBUG
150
  // Does this Cost vector have any register options ?
151
  template <typename VectorT>
152
  bool hasRegisterOptions(const VectorT &V) {
153
    unsigned VL = V.getLength();
154
155
    // An empty or spill only cost vector does not provide any register option.
156
    if (VL <= 1)
157
      return false;
158
159
    // If there are registers in the cost vector, but all of them have infinite
160
    // costs, then ... there is no available register.
161
    for (unsigned i = 1; i < VL; ++i)
162
      if (V[i] != std::numeric_limits<PBQP::PBQPNum>::infinity())
163
        return true;
164
165
    return false;
166
  }
167
#endif
168
169
  // Find a solution to a fully reduced graph by backpropagation.
170
  //
171
  // Given a graph and a reduction order, pop each node from the reduction
172
  // order and greedily compute a minimum solution based on the node costs, and
173
  // the dependent costs due to previously solved nodes.
174
  //
175
  // Note - This does not return the graph to its original (pre-reduction)
176
  //        state: the existing solvers destructively alter the node and edge
177
  //        costs. Given that, the backpropagate function doesn't attempt to
178
  //        replace the edges either, but leaves the graph in its reduced
179
  //        state.
180
  template <typename GraphT, typename StackT>
181
8
  Solution backpropagate(GraphT& G, StackT stack) {
182
8
    using NodeId = GraphBase::NodeId;
183
8
    using Matrix = typename GraphT::Matrix;
184
8
    using RawVector = typename GraphT::RawVector;
185
8
186
8
    Solution s;
187
8
188
161
    while (!stack.empty()) {
189
153
      NodeId NId = stack.back();
190
153
      stack.pop_back();
191
153
192
153
      RawVector v = G.getNodeCosts(NId);
193
153
194
153
#ifndef NDEBUG
195
153
      // Although a conservatively allocatable node can be allocated to a register,
196
153
      // spilling it may provide a lower cost solution. Assert here that spilling
197
153
      // is done by choice, not because there were no register available.
198
153
      if (G.getNodeMetadata(NId).wasConservativelyAllocatable())
199
153
        assert(hasRegisterOptions(v) && "A conservatively allocatable node "
200
153
                                        "must have available register options");
201
153
#endif
202
153
203
561
      for (auto EId : G.adjEdgeIds(NId)) {
204
561
        const Matrix& edgeCosts = G.getEdgeCosts(EId);
205
561
        if (NId == G.getEdgeNode1Id(EId)) {
206
167
          NodeId mId = G.getEdgeNode2Id(EId);
207
167
          v += edgeCosts.getColAsVector(s.getSelection(mId));
208
394
        } else {
209
394
          NodeId mId = G.getEdgeNode1Id(EId);
210
394
          v += edgeCosts.getRowAsVector(s.getSelection(mId));
211
394
        }
212
561
      }
213
153
214
153
      s.setSelection(NId, v.minIndex());
215
153
    }
216
8
217
8
    return s;
218
8
  }
219
220
} // end namespace PBQP
221
} // end namespace llvm
222
223
#endif // LLVM_CODEGEN_PBQP_REDUCTIONRULES_H