1/*
2 * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#if ENABLE(B3_JIT)
29
30#include "AirBasicBlock.h"
31#include "AirCFG.h"
32#include "AirCode.h"
33#include "AirInstInlines.h"
34#include "AirStackSlot.h"
35#include "AirTmpInlines.h"
36#include <wtf/IndexMap.h>
37
38namespace JSC { namespace B3 { namespace Air {
39
40template<typename Adapter>
41struct LivenessAdapter {
42 typedef Air::CFG CFG;
43
44 typedef Vector<unsigned, 4> ActionsList;
45
46 struct Actions {
47 Actions() { }
48
49 ActionsList use;
50 ActionsList def;
51 };
52
53 typedef Vector<Actions, 0, UnsafeVectorOverflow> ActionsForBoundary;
54
55 LivenessAdapter(Code& code)
56 : code(code)
57 , actions(code.size())
58 {
59 }
60
61 Adapter& adapter()
62 {
63 return *static_cast<Adapter*>(this);
64 }
65
66 void prepareToCompute()
67 {
68 for (BasicBlock* block : code) {
69 ActionsForBoundary& actionsForBoundary = actions[block];
70 actionsForBoundary.resize(block->size() + 1);
71
72 for (size_t instIndex = block->size(); instIndex--;) {
73 Inst& inst = block->at(instIndex);
74 inst.forEach<typename Adapter::Thing>(
75 [&] (typename Adapter::Thing& thing, Arg::Role role, Bank bank, Width) {
76 if (!Adapter::acceptsBank(bank) || !Adapter::acceptsRole(role))
77 return;
78
79 unsigned index = adapter().valueToIndex(thing);
80
81 if (Arg::isEarlyUse(role))
82 actionsForBoundary[instIndex].use.appendIfNotContains(index);
83 if (Arg::isEarlyDef(role))
84 actionsForBoundary[instIndex].def.appendIfNotContains(index);
85 if (Arg::isLateUse(role))
86 actionsForBoundary[instIndex + 1].use.appendIfNotContains(index);
87 if (Arg::isLateDef(role))
88 actionsForBoundary[instIndex + 1].def.appendIfNotContains(index);
89 });
90 }
91 }
92 }
93
94 Actions& actionsAt(BasicBlock* block, unsigned instBoundaryIndex)
95 {
96 return actions[block][instBoundaryIndex];
97 }
98
99 unsigned blockSize(BasicBlock* block)
100 {
101 return block->size();
102 }
103
104 template<typename Func>
105 void forEachUse(BasicBlock* block, size_t instBoundaryIndex, const Func& func)
106 {
107 for (unsigned index : actionsAt(block, instBoundaryIndex).use)
108 func(index);
109 }
110
111 template<typename Func>
112 void forEachDef(BasicBlock* block, size_t instBoundaryIndex, const Func& func)
113 {
114 for (unsigned index : actionsAt(block, instBoundaryIndex).def)
115 func(index);
116 }
117
118 Code& code;
119 IndexMap<BasicBlock*, ActionsForBoundary> actions;
120};
121
122template<Bank adapterBank, Arg::Temperature minimumTemperature = Arg::Cold>
123struct TmpLivenessAdapter : LivenessAdapter<TmpLivenessAdapter<adapterBank, minimumTemperature>> {
124 typedef LivenessAdapter<TmpLivenessAdapter<adapterBank, minimumTemperature>> Base;
125
126 static constexpr const char* name = "TmpLiveness";
127 typedef Tmp Thing;
128
129 TmpLivenessAdapter(Code& code)
130 : Base(code)
131 {
132 }
133
134 unsigned numIndices()
135 {
136 return Tmp::absoluteIndexEnd(Base::code, adapterBank);
137 }
138 static bool acceptsBank(Bank bank) { return bank == adapterBank; }
139 static bool acceptsRole(Arg::Role role) { return Arg::temperature(role) >= minimumTemperature; }
140 static unsigned valueToIndex(Tmp tmp) { return AbsoluteTmpMapper<adapterBank>::absoluteIndex(tmp); }
141 static Tmp indexToValue(unsigned index) { return AbsoluteTmpMapper<adapterBank>::tmpFromAbsoluteIndex(index); }
142};
143
144struct UnifiedTmpLivenessAdapter : LivenessAdapter<UnifiedTmpLivenessAdapter> {
145 typedef LivenessAdapter<UnifiedTmpLivenessAdapter> Base;
146
147 static constexpr const char* name = "UnifiedTmpLiveness";
148
149 typedef Tmp Thing;
150
151 UnifiedTmpLivenessAdapter(Code& code)
152 : Base(code)
153 {
154 }
155
156 unsigned numIndices()
157 {
158 return Tmp::linearIndexEnd(code);
159 }
160
161 static bool acceptsBank(Bank) { return true; }
162 static bool acceptsRole(Arg::Role) { return true; }
163 unsigned valueToIndex(Tmp tmp) { return tmp.linearlyIndexed(code).index(); }
164 Tmp indexToValue(unsigned index) { return Tmp::tmpForLinearIndex(code, index); }
165};
166
167struct StackSlotLivenessAdapter : LivenessAdapter<StackSlotLivenessAdapter> {
168 static constexpr const char* name = "StackSlotLiveness";
169 typedef StackSlot* Thing;
170
171 StackSlotLivenessAdapter(Code& code)
172 : LivenessAdapter(code)
173 {
174 }
175
176 unsigned numIndices()
177 {
178 return code.stackSlots().size();
179 }
180 static bool acceptsBank(Bank) { return true; }
181 static bool acceptsRole(Arg::Role) { return true; }
182 static unsigned valueToIndex(StackSlot* stackSlot) { return stackSlot->index(); }
183 StackSlot* indexToValue(unsigned index) { return code.stackSlots()[index]; }
184};
185
186} } } // namespace JSC::B3::Air
187
188#endif // ENABLE(B3_JIT)
189
190