The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / hydrogen-uint32-analysis.cc @ f230a1cf

History | View | Annotate | Download (8.32 KB)

1
// Copyright 2013 the V8 project authors. All rights reserved.
2
// Redistribution and use in source and binary forms, with or without
3
// modification, are permitted provided that the following conditions are
4
// met:
5
//
6
//     * Redistributions of source code must retain the above copyright
7
//       notice, this list of conditions and the following disclaimer.
8
//     * Redistributions in binary form must reproduce the above
9
//       copyright notice, this list of conditions and the following
10
//       disclaimer in the documentation and/or other materials provided
11
//       with the distribution.
12
//     * Neither the name of Google Inc. nor the names of its
13
//       contributors may be used to endorse or promote products derived
14
//       from this software without specific prior written permission.
15
//
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27

    
28
#include "hydrogen-uint32-analysis.h"
29

    
30
namespace v8 {
31
namespace internal {
32

    
33

    
34
bool HUint32AnalysisPhase::IsSafeUint32Use(HValue* val, HValue* use) {
35
  // Operations that operate on bits are safe.
36
  if (use->IsBitwise() || use->IsShl() || use->IsSar() || use->IsShr()) {
37
    return true;
38
  } else if (use->IsSimulate()) {
39
    // Deoptimization has special support for uint32.
40
    return true;
41
  } else if (use->IsChange()) {
42
    // Conversions have special support for uint32.
43
    // This ASSERT guards that the conversion in question is actually
44
    // implemented. Do not extend the whitelist without adding
45
    // support to LChunkBuilder::DoChange().
46
    ASSERT(HChange::cast(use)->to().IsDouble() ||
47
           HChange::cast(use)->to().IsSmi() ||
48
           HChange::cast(use)->to().IsTagged());
49
    return true;
50
  } else if (use->IsStoreKeyed()) {
51
    HStoreKeyed* store = HStoreKeyed::cast(use);
52
    if (store->is_external()) {
53
      // Storing a value into an external integer array is a bit level
54
      // operation.
55
      if (store->value() == val) {
56
        // Clamping or a conversion to double should have beed inserted.
57
        ASSERT(store->elements_kind() != EXTERNAL_PIXEL_ELEMENTS);
58
        ASSERT(store->elements_kind() != EXTERNAL_FLOAT_ELEMENTS);
59
        ASSERT(store->elements_kind() != EXTERNAL_DOUBLE_ELEMENTS);
60
        return true;
61
      }
62
    }
63
  }
64

    
65
  return false;
66
}
67

    
68

    
69
// Iterate over all uses and verify that they are uint32 safe: either don't
70
// distinguish between int32 and uint32 due to their bitwise nature or
71
// have special support for uint32 values.
72
// Encountered phis are optimistically treated as safe uint32 uses,
73
// marked with kUint32 flag and collected in the phis_ list. A separate
74
// pass will be performed later by UnmarkUnsafePhis to clear kUint32 from
75
// phis that are not actually uint32-safe (it requires fix point iteration).
76
bool HUint32AnalysisPhase::Uint32UsesAreSafe(HValue* uint32val) {
77
  bool collect_phi_uses = false;
78
  for (HUseIterator it(uint32val->uses()); !it.Done(); it.Advance()) {
79
    HValue* use = it.value();
80

    
81
    if (use->IsPhi()) {
82
      if (!use->CheckFlag(HInstruction::kUint32)) {
83
        // There is a phi use of this value from a phi that is not yet
84
        // collected in phis_ array. Separate pass is required.
85
        collect_phi_uses = true;
86
      }
87

    
88
      // Optimistically treat phis as uint32 safe.
89
      continue;
90
    }
91

    
92
    if (!IsSafeUint32Use(uint32val, use)) {
93
      return false;
94
    }
95
  }
96

    
97
  if (collect_phi_uses) {
98
    for (HUseIterator it(uint32val->uses()); !it.Done(); it.Advance()) {
99
      HValue* use = it.value();
100

    
101
      // There is a phi use of this value from a phi that is not yet
102
      // collected in phis_ array. Separate pass is required.
103
      if (use->IsPhi() && !use->CheckFlag(HInstruction::kUint32)) {
104
        use->SetFlag(HInstruction::kUint32);
105
        phis_.Add(HPhi::cast(use), zone());
106
      }
107
    }
108
  }
109

    
110
  return true;
111
}
112

    
113

    
114
// Check if all operands to the given phi are marked with kUint32 flag.
115
bool HUint32AnalysisPhase::CheckPhiOperands(HPhi* phi) {
116
  if (!phi->CheckFlag(HInstruction::kUint32)) {
117
    // This phi is not uint32 safe. No need to check operands.
118
    return false;
119
  }
120

    
121
  for (int j = 0; j < phi->OperandCount(); j++) {
122
    HValue* operand = phi->OperandAt(j);
123
    if (!operand->CheckFlag(HInstruction::kUint32)) {
124
      // Lazily mark constants that fit into uint32 range with kUint32 flag.
125
      if (operand->IsInteger32Constant() &&
126
          operand->GetInteger32Constant() >= 0) {
127
        operand->SetFlag(HInstruction::kUint32);
128
        continue;
129
      }
130

    
131
      // This phi is not safe, some operands are not uint32 values.
132
      return false;
133
    }
134
  }
135

    
136
  return true;
137
}
138

    
139

    
140
// Remove kUint32 flag from the phi itself and its operands. If any operand
141
// was a phi marked with kUint32 place it into a worklist for
142
// transitive clearing of kUint32 flag.
143
void HUint32AnalysisPhase::UnmarkPhi(HPhi* phi, ZoneList<HPhi*>* worklist) {
144
  phi->ClearFlag(HInstruction::kUint32);
145
  for (int j = 0; j < phi->OperandCount(); j++) {
146
    HValue* operand = phi->OperandAt(j);
147
    if (operand->CheckFlag(HInstruction::kUint32)) {
148
      operand->ClearFlag(HInstruction::kUint32);
149
      if (operand->IsPhi()) {
150
        worklist->Add(HPhi::cast(operand), zone());
151
      }
152
    }
153
  }
154
}
155

    
156

    
157
void HUint32AnalysisPhase::UnmarkUnsafePhis() {
158
  // No phis were collected. Nothing to do.
159
  if (phis_.length() == 0) return;
160

    
161
  // Worklist used to transitively clear kUint32 from phis that
162
  // are used as arguments to other phis.
163
  ZoneList<HPhi*> worklist(phis_.length(), zone());
164

    
165
  // Phi can be used as a uint32 value if and only if
166
  // all its operands are uint32 values and all its
167
  // uses are uint32 safe.
168

    
169
  // Iterate over collected phis and unmark those that
170
  // are unsafe. When unmarking phi unmark its operands
171
  // and add it to the worklist if it is a phi as well.
172
  // Phis that are still marked as safe are shifted down
173
  // so that all safe phis form a prefix of the phis_ array.
174
  int phi_count = 0;
175
  for (int i = 0; i < phis_.length(); i++) {
176
    HPhi* phi = phis_[i];
177

    
178
    if (CheckPhiOperands(phi) && Uint32UsesAreSafe(phi)) {
179
      phis_[phi_count++] = phi;
180
    } else {
181
      UnmarkPhi(phi, &worklist);
182
    }
183
  }
184

    
185
  // Now phis array contains only those phis that have safe
186
  // non-phi uses. Start transitively clearing kUint32 flag
187
  // from phi operands of discovered non-safe phis until
188
  // only safe phis are left.
189
  while (!worklist.is_empty())  {
190
    while (!worklist.is_empty()) {
191
      HPhi* phi = worklist.RemoveLast();
192
      UnmarkPhi(phi, &worklist);
193
    }
194

    
195
    // Check if any operands to safe phis were unmarked
196
    // turning a safe phi into unsafe. The same value
197
    // can flow into several phis.
198
    int new_phi_count = 0;
199
    for (int i = 0; i < phi_count; i++) {
200
      HPhi* phi = phis_[i];
201

    
202
      if (CheckPhiOperands(phi)) {
203
        phis_[new_phi_count++] = phi;
204
      } else {
205
        UnmarkPhi(phi, &worklist);
206
      }
207
    }
208
    phi_count = new_phi_count;
209
  }
210
}
211

    
212

    
213
void HUint32AnalysisPhase::Run() {
214
  if (!graph()->has_uint32_instructions()) return;
215

    
216
  ZoneList<HInstruction*>* uint32_instructions = graph()->uint32_instructions();
217
  for (int i = 0; i < uint32_instructions->length(); ++i) {
218
    // Analyze instruction and mark it with kUint32 if all
219
    // its uses are uint32 safe.
220
    HInstruction* current = uint32_instructions->at(i);
221
    if (current->IsLinked() &&
222
        current->representation().IsInteger32() &&
223
        Uint32UsesAreSafe(current)) {
224
      current->SetFlag(HInstruction::kUint32);
225
    }
226
  }
227

    
228
  // Some phis might have been optimistically marked with kUint32 flag.
229
  // Remove this flag from those phis that are unsafe and propagate
230
  // this information transitively potentially clearing kUint32 flag
231
  // from some non-phi operations that are used as operands to unsafe phis.
232
  UnmarkUnsafePhis();
233
}
234

    
235

    
236
} }  // namespace v8::internal