Bug Summary

File:jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp
Warning:line 132, column 15
Value stored to 'block' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name c1_RangeCheckElimination.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mthread-model posix -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/libjvm/objs/precompiled -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D _GNU_SOURCE -D _REENTRANT -D LIBC=gnu -D LINUX -D VM_LITTLE_ENDIAN -D _LP64=1 -D ASSERT -D CHECK_UNHANDLED_OOPS -D TARGET_ARCH_x86 -D INCLUDE_SUFFIX_OS=_linux -D INCLUDE_SUFFIX_CPU=_x86 -D INCLUDE_SUFFIX_COMPILER=_gcc -D TARGET_COMPILER_gcc -D AMD64 -D HOTSPOT_LIB_ARCH="amd64" -D COMPILER1 -D COMPILER2 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc/adfiles -I /home/daniel/Projects/java/jdk/src/hotspot/share -I /home/daniel/Projects/java/jdk/src/hotspot/os/linux -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix -I /home/daniel/Projects/java/jdk/src/hotspot/cpu/x86 -I /home/daniel/Projects/java/jdk/src/hotspot/os_cpu/linux_x86 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc -I /home/daniel/Projects/java/jdk/src/hotspot/share/precompiled -I /home/daniel/Projects/java/jdk/src/hotspot/share/include -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix/include -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base/linux -I /home/daniel/Projects/java/jdk/src/java.base/share/native/libjimage -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc/adfiles -I /home/daniel/Projects/java/jdk/src/hotspot/share -I /home/daniel/Projects/java/jdk/src/hotspot/os/linux -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix -I /home/daniel/Projects/java/jdk/src/hotspot/cpu/x86 -I /home/daniel/Projects/java/jdk/src/hotspot/os_cpu/linux_x86 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/hotspot/variant-server/gensrc -D _FORTIFY_SOURCE=2 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/x86_64-linux-gnu/c++/7.5.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/7.5.0/../../../../include/c++/7.5.0/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-format-zero-length -Wno-unused-parameter -Wno-unused -Wno-parentheses -Wno-comment -Wno-unknown-pragmas -Wno-address -Wno-delete-non-virtual-dtor -Wno-char-subscripts -Wno-array-bounds -Wno-int-in-bool-context -Wno-ignored-qualifiers -Wno-missing-field-initializers -Wno-implicit-fallthrough -Wno-empty-body -Wno-strict-overflow -Wno-sequence-point -Wno-maybe-uninitialized -Wno-misleading-indentation -Wno-cast-function-type -Wno-shift-negative-value -std=c++14 -fdeprecated-macro -fdebug-compilation-dir /home/daniel/Projects/java/jdk/make/hotspot -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -stack-protector 1 -fno-rtti -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/daniel/Projects/java/scan/2021-12-21-193737-8510-1 -x c++ /home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp
1/*
2 * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25#include "precompiled.hpp"
26#include "c1/c1_ValueStack.hpp"
27#include "c1/c1_RangeCheckElimination.hpp"
28#include "c1/c1_IR.hpp"
29#include "c1/c1_Canonicalizer.hpp"
30#include "c1/c1_ValueMap.hpp"
31#include "ci/ciMethodData.hpp"
32#include "runtime/deoptimization.hpp"
33#ifdef ASSERT1
34#include "utilities/bitMap.inline.hpp"
35#endif
36
37// Macros for the Trace and the Assertion flag
38#ifdef ASSERT1
39#define TRACE_RANGE_CHECK_ELIMINATION(code)if (TraceRangeCheckElimination) { code; } if (TraceRangeCheckElimination) { code; }
40#define ASSERT_RANGE_CHECK_ELIMINATION(code)if (AssertRangeCheckElimination) { code; } if (AssertRangeCheckElimination) { code; }
41#define TRACE_OR_ASSERT_RANGE_CHECK_ELIMINATION(code)if (TraceRangeCheckElimination || AssertRangeCheckElimination
) { code; }
if (TraceRangeCheckElimination || AssertRangeCheckElimination) { code; }
42#else
43#define TRACE_RANGE_CHECK_ELIMINATION(code)if (TraceRangeCheckElimination) { code; }
44#define ASSERT_RANGE_CHECK_ELIMINATION(code)if (AssertRangeCheckElimination) { code; }
45#define TRACE_OR_ASSERT_RANGE_CHECK_ELIMINATION(code)if (TraceRangeCheckElimination || AssertRangeCheckElimination
) { code; }
46#endif
47
48// Entry point for the optimization
49void RangeCheckElimination::eliminate(IR *ir) {
50 bool do_elimination = ir->compilation()->has_access_indexed();
51 ASSERT_RANGE_CHECK_ELIMINATION(do_elimination = true)if (AssertRangeCheckElimination) { do_elimination = true; };
52 if (do_elimination) {
53 RangeCheckEliminator rce(ir);
54 }
55}
56
57// Constructor
58RangeCheckEliminator::RangeCheckEliminator(IR *ir) :
59 _bounds(Instruction::number_of_instructions(), Instruction::number_of_instructions(), NULL__null),
60 _access_indexed_info(Instruction::number_of_instructions(), Instruction::number_of_instructions(), NULL__null)
61{
62 _visitor.set_range_check_eliminator(this);
63 _ir = ir;
64 _number_of_instructions = Instruction::number_of_instructions();
65 _optimistic = ir->compilation()->is_optimistic();
66
67 TRACE_RANGE_CHECK_ELIMINATION(if (TraceRangeCheckElimination) { tty->cr(); tty->print_cr
("Range check elimination"); ir->method()->print_name(tty
); tty->cr();; }
68 tty->cr();if (TraceRangeCheckElimination) { tty->cr(); tty->print_cr
("Range check elimination"); ir->method()->print_name(tty
); tty->cr();; }
69 tty->print_cr("Range check elimination");if (TraceRangeCheckElimination) { tty->cr(); tty->print_cr
("Range check elimination"); ir->method()->print_name(tty
); tty->cr();; }
70 ir->method()->print_name(tty);if (TraceRangeCheckElimination) { tty->cr(); tty->print_cr
("Range check elimination"); ir->method()->print_name(tty
); tty->cr();; }
71 tty->cr();if (TraceRangeCheckElimination) { tty->cr(); tty->print_cr
("Range check elimination"); ir->method()->print_name(tty
); tty->cr();; }
72 )if (TraceRangeCheckElimination) { tty->cr(); tty->print_cr
("Range check elimination"); ir->method()->print_name(tty
); tty->cr();; }
;
73
74 TRACE_RANGE_CHECK_ELIMINATION(if (TraceRangeCheckElimination) { tty->print_cr("optimistic=%d"
, (int)_optimistic);; }
75 tty->print_cr("optimistic=%d", (int)_optimistic);if (TraceRangeCheckElimination) { tty->print_cr("optimistic=%d"
, (int)_optimistic);; }
76 )if (TraceRangeCheckElimination) { tty->print_cr("optimistic=%d"
, (int)_optimistic);; }
;
77
78#ifdef ASSERT1
79 // Verifies several conditions that must be true on the IR-input. Only used for debugging purposes.
80 TRACE_RANGE_CHECK_ELIMINATION(if (TraceRangeCheckElimination) { tty->print_cr("Verification of IR . . ."
);; }
81 tty->print_cr("Verification of IR . . .");if (TraceRangeCheckElimination) { tty->print_cr("Verification of IR . . ."
);; }
82 )if (TraceRangeCheckElimination) { tty->print_cr("Verification of IR . . ."
);; }
;
83 Verification verification(ir);
84#endif
85
86 // Set process block flags
87 // Optimization so a blocks is only processed if it contains an access indexed instruction or if
88 // one of its children in the dominator tree contains an access indexed instruction.
89 set_process_block_flags(ir->start());
90
91 // Pass over instructions in the dominator tree
92 TRACE_RANGE_CHECK_ELIMINATION(if (TraceRangeCheckElimination) { tty->print_cr("Starting pass over dominator tree . . ."
); }
93 tty->print_cr("Starting pass over dominator tree . . .")if (TraceRangeCheckElimination) { tty->print_cr("Starting pass over dominator tree . . ."
); }
94 )if (TraceRangeCheckElimination) { tty->print_cr("Starting pass over dominator tree . . ."
); }
;
95 calc_bounds(ir->start(), NULL__null);
96
97 TRACE_RANGE_CHECK_ELIMINATION(if (TraceRangeCheckElimination) { tty->print_cr("Finished!"
); }
98 tty->print_cr("Finished!")if (TraceRangeCheckElimination) { tty->print_cr("Finished!"
); }
99 )if (TraceRangeCheckElimination) { tty->print_cr("Finished!"
); }
;
100}
101
102// Instruction specific work for some instructions
103// Constant
104void RangeCheckEliminator::Visitor::do_Constant(Constant *c) {
105 IntConstant *ic = c->type()->as_IntConstant();
106 if (ic != NULL__null) {
107 int value = ic->value();
108 _bound = new Bound(value, NULL__null, value, NULL__null);
109 }
110}
111
112// LogicOp
113void RangeCheckEliminator::Visitor::do_LogicOp(LogicOp *lo) {
114 if (lo->type()->as_IntType() && lo->op() == Bytecodes::_iand && (lo->x()->as_Constant() || lo->y()->as_Constant())) {
115 int constant = 0;
116 Constant *c = lo->x()->as_Constant();
117 if (c != NULL__null) {
118 constant = c->type()->as_IntConstant()->value();
119 } else {
120 constant = lo->y()->as_Constant()->type()->as_IntConstant()->value();
121 }
122 if (constant >= 0) {
123 _bound = new Bound(0, NULL__null, constant, NULL__null);
124 }
125 }
126}
127
128// Phi
129void RangeCheckEliminator::Visitor::do_Phi(Phi *phi) {
130 if (!phi->type()->as_IntType() && !phi->type()->as_ObjectType()) return;
131
132 BlockBegin *block = phi->block();
Value stored to 'block' during its initialization is never read
133 int op_count = phi->operand_count();
134 bool has_upper = true;
135 bool has_lower = true;
136 assert(phi, "Phi must not be null")do { if (!(phi)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 136, "assert(" "phi" ") failed", "Phi must not be null"); ::
breakpoint(); } } while (0)
;
137 Bound *bound = NULL__null;
138
139 // TODO: support more difficult phis
140 for (int i=0; i<op_count; i++) {
141 Value v = phi->operand_at(i);
142
143 if (v == phi) continue;
144
145 // Check if instruction is connected with phi itself
146 Op2 *op2 = v->as_Op2();
147 if (op2 != NULL__null) {
148 Value x = op2->x();
149 Value y = op2->y();
150 if ((x == phi || y == phi)) {
151 Value other = x;
152 if (other == phi) {
153 other = y;
154 }
155 ArithmeticOp *ao = v->as_ArithmeticOp();
156 if (ao != NULL__null && ao->op() == Bytecodes::_iadd) {
157 assert(ao->op() == Bytecodes::_iadd, "Has to be add!")do { if (!(ao->op() == Bytecodes::_iadd)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 157, "assert(" "ao->op() == Bytecodes::_iadd" ") failed"
, "Has to be add!"); ::breakpoint(); } } while (0)
;
158 if (ao->type()->as_IntType()) {
159 Constant *c = other->as_Constant();
160 if (c != NULL__null) {
161 assert(c->type()->as_IntConstant(), "Constant has to be of type integer")do { if (!(c->type()->as_IntConstant())) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 161, "assert(" "c->type()->as_IntConstant()" ") failed"
, "Constant has to be of type integer"); ::breakpoint(); } } while
(0)
;
162 int value = c->type()->as_IntConstant()->value();
163 if (value == 1) {
164 has_upper = false;
165 } else if (value > 1) {
166 // Overflow not guaranteed
167 has_upper = false;
168 has_lower = false;
169 } else if (value < 0) {
170 has_lower = false;
171 }
172 continue;
173 }
174 }
175 }
176 }
177 }
178
179 // No connection -> new bound
180 Bound *v_bound = _rce->get_bound(v);
181 Bound *cur_bound;
182 int cur_constant = 0;
183 Value cur_value = v;
184
185 if (v->type()->as_IntConstant()) {
186 cur_constant = v->type()->as_IntConstant()->value();
187 cur_value = NULL__null;
188 }
189 if (!v_bound->has_upper() || !v_bound->has_lower()) {
190 cur_bound = new Bound(cur_constant, cur_value, cur_constant, cur_value);
191 } else {
192 cur_bound = v_bound;
193 }
194 if (cur_bound) {
195 if (!bound) {
196 bound = cur_bound->copy();
197 } else {
198 bound->or_op(cur_bound);
199 }
200 } else {
201 // No bound!
202 bound = NULL__null;
203 break;
204 }
205 }
206
207 if (bound) {
208 if (!has_upper) {
209 bound->remove_upper();
210 }
211 if (!has_lower) {
212 bound->remove_lower();
213 }
214 _bound = bound;
215 } else {
216 _bound = new Bound();
217 }
218}
219
220
221// ArithmeticOp
222void RangeCheckEliminator::Visitor::do_ArithmeticOp(ArithmeticOp *ao) {
223 Value x = ao->x();
224 Value y = ao->y();
225
226 if (ao->op() == Bytecodes::_irem) {
227 Bound* x_bound = _rce->get_bound(x);
228 Bound* y_bound = _rce->get_bound(y);
229 if (x_bound->lower() >= 0 && x_bound->lower_instr() == NULL__null && y->as_ArrayLength() != NULL__null) {
230 _bound = new Bound(0, NULL__null, -1, y);
231 } else if (y->type()->as_IntConstant() && y->type()->as_IntConstant()->value() != 0) {
232 // The binary % operator is said to yield the remainder of its operands from an implied division; the
233 // left-hand operand is the dividend and the right-hand operand is the divisor.
234 //
235 // % operator follows from this rule that the result of the remainder operation can be negative only
236 // if the dividend is negative, and can be positive only if the dividend is positive. Moreover, the
237 // magnitude of the result is always less than the magnitude of the divisor(See JLS 15.17.3).
238 //
239 // So if y is a constant integer and not equal to 0, then we can deduce the bound of remainder operation:
240 // x % -y ==> [0, y - 1] Apply RCE
241 // x % y ==> [0, y - 1] Apply RCE
242 // -x % y ==> [-y + 1, 0]
243 // -x % -y ==> [-y + 1, 0]
244 if (x_bound->has_lower() && x_bound->lower() >= 0) {
245 _bound = new Bound(0, NULL__null, y->type()->as_IntConstant()->value() - 1, NULL__null);
246 } else {
247 _bound = new Bound();
248 }
249 } else {
250 _bound = new Bound();
251 }
252 } else if (!x->as_Constant() || !y->as_Constant()) {
253 assert(!x->as_Constant() || !y->as_Constant(), "One of the operands must be non-constant!")do { if (!(!x->as_Constant() || !y->as_Constant())) { (
*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 253, "assert(" "!x->as_Constant() || !y->as_Constant()"
") failed", "One of the operands must be non-constant!"); ::
breakpoint(); } } while (0)
;
254 if (((x->as_Constant() || y->as_Constant()) && (ao->op() == Bytecodes::_iadd)) || (y->as_Constant() && ao->op() == Bytecodes::_isub)) {
255 assert(ao->op() == Bytecodes::_iadd || ao->op() == Bytecodes::_isub, "Operand must be iadd or isub")do { if (!(ao->op() == Bytecodes::_iadd || ao->op() == Bytecodes
::_isub)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 255, "assert(" "ao->op() == Bytecodes::_iadd || ao->op() == Bytecodes::_isub"
") failed", "Operand must be iadd or isub"); ::breakpoint();
} } while (0)
;
256
257 if (y->as_Constant()) {
258 Value tmp = x;
259 x = y;
260 y = tmp;
261 }
262 assert(x->as_Constant()->type()->as_IntConstant(), "Constant must be int constant!")do { if (!(x->as_Constant()->type()->as_IntConstant(
))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 262, "assert(" "x->as_Constant()->type()->as_IntConstant()"
") failed", "Constant must be int constant!"); ::breakpoint(
); } } while (0)
;
263
264 // Constant now in x
265 int const_value = x->as_Constant()->type()->as_IntConstant()->value();
266 if (ao->op() == Bytecodes::_iadd || const_value != min_jint) {
267 if (ao->op() == Bytecodes::_isub) {
268 const_value = -const_value;
269 }
270
271 Bound * bound = _rce->get_bound(y);
272 if (bound->has_upper() && bound->has_lower()) {
273 int new_lower = bound->lower() + const_value;
274 jlong new_lowerl = ((jlong)bound->lower()) + const_value;
275 int new_upper = bound->upper() + const_value;
276 jlong new_upperl = ((jlong)bound->upper()) + const_value;
277
278 if (((jlong)new_lower) == new_lowerl && ((jlong)new_upper == new_upperl)) {
279 Bound *newBound = new Bound(new_lower, bound->lower_instr(), new_upper, bound->upper_instr());
280 _bound = newBound;
281 } else {
282 // overflow
283 _bound = new Bound();
284 }
285 } else {
286 _bound = new Bound();
287 }
288 } else {
289 _bound = new Bound();
290 }
291 } else {
292 Bound *bound = _rce->get_bound(x);
293 if (ao->op() == Bytecodes::_isub) {
294 if (bound->lower_instr() == y) {
295 _bound = new Bound(Instruction::geq, NULL__null, bound->lower());
296 } else {
297 _bound = new Bound();
298 }
299 } else {
300 _bound = new Bound();
301 }
302 }
303 }
304}
305
306// IfOp
307void RangeCheckEliminator::Visitor::do_IfOp(IfOp *ifOp)
308{
309 if (ifOp->tval()->type()->as_IntConstant() && ifOp->fval()->type()->as_IntConstant()) {
310 int min = ifOp->tval()->type()->as_IntConstant()->value();
311 int max = ifOp->fval()->type()->as_IntConstant()->value();
312 if (min > max) {
313 // min ^= max ^= min ^= max;
314 int tmp = min;
315 min = max;
316 max = tmp;
317 }
318 _bound = new Bound(min, NULL__null, max, NULL__null);
319 }
320}
321
322// Get bound. Returns the current bound on Value v. Normally this is the topmost element on the bound stack.
323RangeCheckEliminator::Bound *RangeCheckEliminator::get_bound(Value v) {
324 // Wrong type or NULL -> No bound
325 if (!v || (!v->type()->as_IntType() && !v->type()->as_ObjectType())) return NULL__null;
326
327 if (!_bounds.at(v->id())) {
328 // First (default) bound is calculated
329 // Create BoundStack
330 _bounds.at_put(v->id(), new BoundStack());
331 _visitor.clear_bound();
332 Value visit_value = v;
333 visit_value->visit(&_visitor);
334 Bound *bound = _visitor.bound();
335 if (bound) {
336 _bounds.at(v->id())->push(bound);
337 }
338 if (_bounds.at(v->id())->length() == 0) {
339 assert(!(v->as_Constant() && v->type()->as_IntConstant()), "constants not handled here")do { if (!(!(v->as_Constant() && v->type()->
as_IntConstant()))) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 339, "assert(" "!(v->as_Constant() && v->type()->as_IntConstant())"
") failed", "constants not handled here"); ::breakpoint(); }
} while (0)
;
340 _bounds.at(v->id())->push(new Bound());
341 }
342 } else if (_bounds.at(v->id())->length() == 0) {
343 // To avoid endless loops, bound is currently in calculation -> nothing known about it
344 return new Bound();
345 }
346
347 // Return bound
348 return _bounds.at(v->id())->top();
349}
350
351// Update bound
352void RangeCheckEliminator::update_bound(IntegerStack &pushed, Value v, Instruction::Condition cond, Value value, int constant) {
353 if (cond == Instruction::gtr) {
354 cond = Instruction::geq;
355 constant++;
356 } else if (cond == Instruction::lss) {
357 cond = Instruction::leq;
358 constant--;
359 }
360 Bound *bound = new Bound(cond, value, constant);
361 update_bound(pushed, v, bound);
362}
363
364// Checks for loop invariance. Returns true if the instruction is outside of the loop which is identified by loop_header.
365bool RangeCheckEliminator::loop_invariant(BlockBegin *loop_header, Instruction *instruction) {
366 assert(loop_header, "Loop header must not be null!")do { if (!(loop_header)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 366, "assert(" "loop_header" ") failed", "Loop header must not be null!"
); ::breakpoint(); } } while (0)
;
367 if (!instruction) return true;
368 return instruction->dominator_depth() < loop_header->dominator_depth();
369}
370
371// Update bound. Pushes a new bound onto the stack. Tries to do a conjunction with the current bound.
372void RangeCheckEliminator::update_bound(IntegerStack &pushed, Value v, Bound *bound) {
373 if (v->as_Constant()) {
374 // No bound update for constants
375 return;
376 }
377 if (!_bounds.at(v->id())) {
378 get_bound(v);
379 assert(_bounds.at(v->id()), "Now Stack must exist")do { if (!(_bounds.at(v->id()))) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 379, "assert(" "_bounds.at(v->id())" ") failed", "Now Stack must exist"
); ::breakpoint(); } } while (0)
;
380 }
381 Bound *top = NULL__null;
382 if (_bounds.at(v->id())->length() > 0) {
383 top = _bounds.at(v->id())->top();
384 }
385 if (top) {
386 bound->and_op(top);
387 }
388 _bounds.at(v->id())->push(bound);
389 pushed.append(v->id());
390}
391
392// Add instruction + idx for in block motion
393void RangeCheckEliminator::add_access_indexed_info(InstructionList &indices, int idx, Value instruction, AccessIndexed *ai) {
394 int id = instruction->id();
395 AccessIndexedInfo *aii = _access_indexed_info.at(id);
396 if (aii == NULL__null) {
397 aii = new AccessIndexedInfo();
398 _access_indexed_info.at_put(id, aii);
399 indices.append(instruction);
400 aii->_min = idx;
401 aii->_max = idx;
402 aii->_list = new AccessIndexedList();
403 } else if (idx >= aii->_min && idx <= aii->_max) {
404 remove_range_check(ai);
405 return;
406 }
407 aii->_min = MIN2(aii->_min, idx);
408 aii->_max = MAX2(aii->_max, idx);
409 aii->_list->append(ai);
410}
411
412// In block motion. Tries to reorder checks in order to reduce some of them.
413// Example:
414// a[i] = 0;
415// a[i+2] = 0;
416// a[i+1] = 0;
417// In this example the check for a[i+1] would be considered as unnecessary during the first iteration.
418// After this i is only checked once for i >= 0 and i+2 < a.length before the first array access. If this
419// check fails, deoptimization is called.
420void RangeCheckEliminator::in_block_motion(BlockBegin *block, AccessIndexedList &accessIndexed, InstructionList &arrays) {
421 InstructionList indices;
422
423 // Now iterate over all arrays
424 for (int i=0; i<arrays.length(); i++) {
425 int max_constant = -1;
426 AccessIndexedList list_constant;
427 Value array = arrays.at(i);
428
429 // For all AccessIndexed-instructions in this block concerning the current array.
430 for(int j=0; j<accessIndexed.length(); j++) {
431 AccessIndexed *ai = accessIndexed.at(j);
432 if (ai->array() != array || !ai->check_flag(Instruction::NeedsRangeCheckFlag)) continue;
433
434 Value index = ai->index();
435 Constant *c = index->as_Constant();
436 if (c != NULL__null) {
437 int constant_value = c->type()->as_IntConstant()->value();
438 if (constant_value >= 0) {
439 if (constant_value <= max_constant) {
440 // No range check needed for this
441 remove_range_check(ai);
442 } else {
443 max_constant = constant_value;
444 list_constant.append(ai);
445 }
446 }
447 } else {
448 int last_integer = 0;
449 Instruction *last_instruction = index;
450 int base = 0;
451 ArithmeticOp *ao = index->as_ArithmeticOp();
452
453 while (ao != NULL__null && (ao->x()->as_Constant() || ao->y()->as_Constant()) && (ao->op() == Bytecodes::_iadd || ao->op() == Bytecodes::_isub)) {
454 c = ao->y()->as_Constant();
455 Instruction *other = ao->x();
456 if (!c && ao->op() == Bytecodes::_iadd) {
457 c = ao->x()->as_Constant();
458 other = ao->y();
459 }
460
461 if (c) {
462 int value = c->type()->as_IntConstant()->value();
463 if (value != min_jint) {
464 if (ao->op() == Bytecodes::_isub) {
465 value = -value;
466 }
467 base += value;
468 last_integer = base;
469 last_instruction = other;
470 }
471 index = other;
472 } else {
473 break;
474 }
475 ao = index->as_ArithmeticOp();
476 }
477 add_access_indexed_info(indices, last_integer, last_instruction, ai);
478 }
479 }
480
481 // Iterate over all different indices
482 if (_optimistic) {
483 for (int i = 0; i < indices.length(); i++) {
484 Instruction *index_instruction = indices.at(i);
485 AccessIndexedInfo *info = _access_indexed_info.at(index_instruction->id());
486 assert(info != NULL, "Info must not be null")do { if (!(info != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 486, "assert(" "info != __null" ") failed", "Info must not be null"
); ::breakpoint(); } } while (0)
;
487
488 // if idx < 0, max > 0, max + idx may fall between 0 and
489 // length-1 and if min < 0, min + idx may overflow and be >=
490 // 0. The predicate wouldn't trigger but some accesses could
491 // be with a negative index. This test guarantees that for the
492 // min and max value that are kept the predicate can't let
493 // some incorrect accesses happen.
494 bool range_cond = (info->_max < 0 || info->_max + min_jint <= info->_min);
495
496 // Generate code only if more than 2 range checks can be eliminated because of that.
497 // 2 because at least 2 comparisons are done
498 if (info->_list->length() > 2 && range_cond) {
499 AccessIndexed *first = info->_list->at(0);
500 Instruction *insert_position = first->prev();
501 assert(insert_position->next() == first, "prev was calculated")do { if (!(insert_position->next() == first)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 501, "assert(" "insert_position->next() == first" ") failed"
, "prev was calculated"); ::breakpoint(); } } while (0)
;
502 ValueStack *state = first->state_before();
503
504 // Load min Constant
505 Constant *min_constant = NULL__null;
506 if (info->_min != 0) {
507 min_constant = new Constant(new IntConstant(info->_min));
508 NOT_PRODUCT(min_constant->set_printable_bci(first->printable_bci()))min_constant->set_printable_bci(first->printable_bci());
509 insert_position = insert_position->insert_after(min_constant);
510 }
511
512 // Load max Constant
513 Constant *max_constant = NULL__null;
514 if (info->_max != 0) {
515 max_constant = new Constant(new IntConstant(info->_max));
516 NOT_PRODUCT(max_constant->set_printable_bci(first->printable_bci()))max_constant->set_printable_bci(first->printable_bci());
517 insert_position = insert_position->insert_after(max_constant);
518 }
519
520 // Load array length
521 Value length_instr = first->length();
522 if (!length_instr) {
523 ArrayLength *length = new ArrayLength(array, first->state_before()->copy());
524 length->set_exception_state(length->state_before());
525 length->set_flag(Instruction::DeoptimizeOnException, true);
526 insert_position = insert_position->insert_after_same_bci(length);
527 length_instr = length;
528 }
529
530 // Calculate lower bound
531 Instruction *lower_compare = index_instruction;
532 if (min_constant) {
533 ArithmeticOp *ao = new ArithmeticOp(Bytecodes::_iadd, min_constant, lower_compare, NULL__null);
534 insert_position = insert_position->insert_after_same_bci(ao);
535 lower_compare = ao;
536 }
537
538 // Calculate upper bound
539 Instruction *upper_compare = index_instruction;
540 if (max_constant) {
541 ArithmeticOp *ao = new ArithmeticOp(Bytecodes::_iadd, max_constant, upper_compare, NULL__null);
542 insert_position = insert_position->insert_after_same_bci(ao);
543 upper_compare = ao;
544 }
545
546 // Trick with unsigned compare is done
547 int bci = NOT_PRODUCT(first->printable_bci())first->printable_bci() PRODUCT_ONLY(-1);
548 insert_position = predicate(upper_compare, Instruction::aeq, length_instr, state, insert_position, bci);
549 insert_position = predicate_cmp_with_const(lower_compare, Instruction::leq, -1, state, insert_position);
550 for (int j = 0; j<info->_list->length(); j++) {
551 AccessIndexed *ai = info->_list->at(j);
552 remove_range_check(ai);
553 }
554 }
555 }
556
557 if (list_constant.length() > 1) {
558 AccessIndexed *first = list_constant.at(0);
559 Instruction *insert_position = first->prev();
560 ValueStack *state = first->state_before();
561 // Load max Constant
562 Constant *constant = new Constant(new IntConstant(max_constant));
563 NOT_PRODUCT(constant->set_printable_bci(first->printable_bci()))constant->set_printable_bci(first->printable_bci());
564 insert_position = insert_position->insert_after(constant);
565 Instruction *compare_instr = constant;
566 Value length_instr = first->length();
567 if (!length_instr) {
568 ArrayLength *length = new ArrayLength(array, state->copy());
569 length->set_exception_state(length->state_before());
570 length->set_flag(Instruction::DeoptimizeOnException, true);
571 insert_position = insert_position->insert_after_same_bci(length);
572 length_instr = length;
573 }
574 // Compare for greater or equal to array length
575 insert_position = predicate(compare_instr, Instruction::geq, length_instr, state, insert_position);
576 for (int j = 0; j<list_constant.length(); j++) {
577 AccessIndexed *ai = list_constant.at(j);
578 remove_range_check(ai);
579 }
580 }
581 }
582
583 // Clear data structures for next array
584 for (int i = 0; i < indices.length(); i++) {
585 Instruction *index_instruction = indices.at(i);
586 _access_indexed_info.at_put(index_instruction->id(), NULL__null);
587 }
588 indices.clear();
589 }
590}
591
592bool RangeCheckEliminator::set_process_block_flags(BlockBegin *block) {
593 Instruction *cur = block;
594 bool process = false;
595
596 while (cur) {
597 process |= (cur->as_AccessIndexed() != NULL__null);
598 cur = cur->next();
599 }
600
601 BlockList *dominates = block->dominates();
602 for (int i=0; i<dominates->length(); i++) {
603 BlockBegin *next = dominates->at(i);
604 process |= set_process_block_flags(next);
605 }
606
607 if (!process) {
608 block->set(BlockBegin::donot_eliminate_range_checks);
609 }
610 return process;
611}
612
613bool RangeCheckEliminator::is_ok_for_deoptimization(Instruction *insert_position, Instruction *array_instr, Instruction *length_instr, Instruction *lower_instr, int lower, Instruction *upper_instr, int upper) {
614 bool upper_check = true;
615 assert(lower_instr || lower >= 0, "If no lower_instr present, lower must be greater 0")do { if (!(lower_instr || lower >= 0)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 615, "assert(" "lower_instr || lower >= 0" ") failed", "If no lower_instr present, lower must be greater 0"
); ::breakpoint(); } } while (0)
;
616 assert(!lower_instr || lower_instr->dominator_depth() <= insert_position->dominator_depth(), "Dominator depth must be smaller")do { if (!(!lower_instr || lower_instr->dominator_depth() <=
insert_position->dominator_depth())) { (*g_assert_poison)
= 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 616, "assert(" "!lower_instr || lower_instr->dominator_depth() <= insert_position->dominator_depth()"
") failed", "Dominator depth must be smaller"); ::breakpoint
(); } } while (0)
;
617 assert(!upper_instr || upper_instr->dominator_depth() <= insert_position->dominator_depth(), "Dominator depth must be smaller")do { if (!(!upper_instr || upper_instr->dominator_depth() <=
insert_position->dominator_depth())) { (*g_assert_poison)
= 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 617, "assert(" "!upper_instr || upper_instr->dominator_depth() <= insert_position->dominator_depth()"
") failed", "Dominator depth must be smaller"); ::breakpoint
(); } } while (0)
;
618 assert(array_instr, "Array instruction must exist")do { if (!(array_instr)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 618, "assert(" "array_instr" ") failed", "Array instruction must exist"
); ::breakpoint(); } } while (0)
;
619 assert(array_instr->dominator_depth() <= insert_position->dominator_depth(), "Dominator depth must be smaller")do { if (!(array_instr->dominator_depth() <= insert_position
->dominator_depth())) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 619, "assert(" "array_instr->dominator_depth() <= insert_position->dominator_depth()"
") failed", "Dominator depth must be smaller"); ::breakpoint
(); } } while (0)
;
620 assert(!length_instr || length_instr->dominator_depth() <= insert_position->dominator_depth(), "Dominator depth must be smaller")do { if (!(!length_instr || length_instr->dominator_depth(
) <= insert_position->dominator_depth())) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 620, "assert(" "!length_instr || length_instr->dominator_depth() <= insert_position->dominator_depth()"
") failed", "Dominator depth must be smaller"); ::breakpoint
(); } } while (0)
;
621
622 if (upper_instr && upper_instr->as_ArrayLength() && upper_instr->as_ArrayLength()->array() == array_instr) {
623 // static check
624 if (upper >= 0) return false; // would always trigger a deopt:
625 // array_length + x >= array_length, x >= 0 is always true
626 upper_check = false;
627 }
628 if (lower_instr && lower_instr->as_ArrayLength() && lower_instr->as_ArrayLength()->array() == array_instr) {
629 if (lower > 0) return false;
630 }
631 // No upper check required -> skip
632 if (upper_check && upper_instr && upper_instr->type()->as_ObjectType() && upper_instr == array_instr) {
633 // upper_instr is object means that the upper bound is the length
634 // of the upper_instr.
635 return false;
636 }
637 return true;
638}
639
640Instruction* RangeCheckEliminator::insert_after(Instruction* insert_position, Instruction* instr, int bci) {
641 if (bci != -1) {
642 NOT_PRODUCT(instr->set_printable_bci(bci))instr->set_printable_bci(bci);
643 return insert_position->insert_after(instr);
644 } else {
645 return insert_position->insert_after_same_bci(instr);
646 }
647}
648
649Instruction* RangeCheckEliminator::predicate(Instruction* left, Instruction::Condition cond, Instruction* right, ValueStack* state, Instruction *insert_position, int bci) {
650 RangeCheckPredicate *deoptimize = new RangeCheckPredicate(left, cond, true, right, state->copy());
651 return insert_after(insert_position, deoptimize, bci);
652}
653
654Instruction* RangeCheckEliminator::predicate_cmp_with_const(Instruction* instr, Instruction::Condition cond, int constant, ValueStack* state, Instruction *insert_position, int bci) {
655 Constant *const_instr = new Constant(new IntConstant(constant));
656 insert_position = insert_after(insert_position, const_instr, bci);
657 return predicate(instr, cond, const_instr, state, insert_position);
658}
659
660Instruction* RangeCheckEliminator::predicate_add(Instruction* left, int left_const, Instruction::Condition cond, Instruction* right, ValueStack* state, Instruction *insert_position, int bci) {
661 Constant *constant = new Constant(new IntConstant(left_const));
662 insert_position = insert_after(insert_position, constant, bci);
663 ArithmeticOp *ao = new ArithmeticOp(Bytecodes::_iadd, constant, left, NULL__null);
664 insert_position = insert_position->insert_after_same_bci(ao);
665 return predicate(ao, cond, right, state, insert_position);
666}
667
668Instruction* RangeCheckEliminator::predicate_add_cmp_with_const(Instruction* left, int left_const, Instruction::Condition cond, int constant, ValueStack* state, Instruction *insert_position, int bci) {
669 Constant *const_instr = new Constant(new IntConstant(constant));
670 insert_position = insert_after(insert_position, const_instr, bci);
671 return predicate_add(left, left_const, cond, const_instr, state, insert_position);
672}
673
674// Insert deoptimization
675void RangeCheckEliminator::insert_deoptimization(ValueStack *state, Instruction *insert_position, Instruction *array_instr, Instruction *length_instr, Instruction *lower_instr, int lower, Instruction *upper_instr, int upper, AccessIndexed *ai) {
676 assert(is_ok_for_deoptimization(insert_position, array_instr, length_instr, lower_instr, lower, upper_instr, upper), "should have been tested before")do { if (!(is_ok_for_deoptimization(insert_position, array_instr
, length_instr, lower_instr, lower, upper_instr, upper))) { (
*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 676, "assert(" "is_ok_for_deoptimization(insert_position, array_instr, length_instr, lower_instr, lower, upper_instr, upper)"
") failed", "should have been tested before"); ::breakpoint(
); } } while (0)
;
677 bool upper_check = !(upper_instr && upper_instr->as_ArrayLength() && upper_instr->as_ArrayLength()->array() == array_instr);
678
679 int bci = NOT_PRODUCT(ai->printable_bci())ai->printable_bci() PRODUCT_ONLY(-1);
680 if (lower_instr) {
681 assert(!lower_instr->type()->as_ObjectType(), "Must not be object type")do { if (!(!lower_instr->type()->as_ObjectType())) { (*
g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 681, "assert(" "!lower_instr->type()->as_ObjectType()"
") failed", "Must not be object type"); ::breakpoint(); } } while
(0)
;
682 if (lower == 0) {
683 // Compare for less than 0
684 insert_position = predicate_cmp_with_const(lower_instr, Instruction::lss, 0, state, insert_position, bci);
685 } else if (lower > 0) {
686 // Compare for smaller 0
687 insert_position = predicate_add_cmp_with_const(lower_instr, lower, Instruction::lss, 0, state, insert_position, bci);
688 } else {
689 assert(lower < 0, "")do { if (!(lower < 0)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 689, "assert(" "lower < 0" ") failed", ""); ::breakpoint
(); } } while (0)
;
690 // Add 1
691 lower++;
692 lower = -lower;
693 // Compare for smaller or equal 0
694 insert_position = predicate_cmp_with_const(lower_instr, Instruction::leq, lower, state, insert_position, bci);
695 }
696 }
697
698 // No upper check required -> skip
699 if (!upper_check) return;
700
701 // We need to know length of array
702 if (!length_instr) {
703 // Load length if necessary
704 ArrayLength *length = new ArrayLength(array_instr, state->copy());
705 NOT_PRODUCT(length->set_printable_bci(ai->printable_bci()))length->set_printable_bci(ai->printable_bci());
706 length->set_exception_state(length->state_before());
707 length->set_flag(Instruction::DeoptimizeOnException, true);
708 insert_position = insert_position->insert_after(length);
709 length_instr = length;
710 }
711
712 if (!upper_instr) {
713 // Compare for geq array.length
714 insert_position = predicate_cmp_with_const(length_instr, Instruction::leq, upper, state, insert_position, bci);
715 } else {
716 if (upper_instr->type()->as_ObjectType()) {
717 assert(state, "must not be null")do { if (!(state)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 717, "assert(" "state" ") failed", "must not be null"); ::breakpoint
(); } } while (0)
;
718 assert(upper_instr != array_instr, "should be")do { if (!(upper_instr != array_instr)) { (*g_assert_poison) =
'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 718, "assert(" "upper_instr != array_instr" ") failed", "should be"
); ::breakpoint(); } } while (0)
;
719 ArrayLength *length = new ArrayLength(upper_instr, state->copy());
720 NOT_PRODUCT(length->set_printable_bci(ai->printable_bci()))length->set_printable_bci(ai->printable_bci());
721 length->set_flag(Instruction::DeoptimizeOnException, true);
722 length->set_exception_state(length->state_before());
723 insert_position = insert_position->insert_after(length);
724 upper_instr = length;
725 }
726 assert(upper_instr->type()->as_IntType(), "Must not be object type!")do { if (!(upper_instr->type()->as_IntType())) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 726, "assert(" "upper_instr->type()->as_IntType()" ") failed"
, "Must not be object type!"); ::breakpoint(); } } while (0)
;
727
728 if (upper == 0) {
729 // Compare for geq array.length
730 insert_position = predicate(upper_instr, Instruction::geq, length_instr, state, insert_position, bci);
731 } else if (upper < 0) {
732 // Compare for geq array.length
733 insert_position = predicate_add(upper_instr, upper, Instruction::geq, length_instr, state, insert_position, bci);
734 } else {
735 assert(upper > 0, "")do { if (!(upper > 0)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 735, "assert(" "upper > 0" ") failed", ""); ::breakpoint
(); } } while (0)
;
736 upper = -upper;
737 // Compare for geq array.length
738 insert_position = predicate_add(length_instr, upper, Instruction::leq, upper_instr, state, insert_position, bci);
739 }
740 }
741}
742
743// Add if condition
744void RangeCheckEliminator::add_if_condition(IntegerStack &pushed, Value x, Value y, Instruction::Condition condition) {
745 if (y->as_Constant()) return;
746
747 int const_value = 0;
748 Value instr_value = x;
749 Constant *c = x->as_Constant();
750 ArithmeticOp *ao = x->as_ArithmeticOp();
751
752 if (c != NULL__null) {
753 const_value = c->type()->as_IntConstant()->value();
754 instr_value = NULL__null;
755 } else if (ao != NULL__null && (!ao->x()->as_Constant() || !ao->y()->as_Constant()) && ((ao->op() == Bytecodes::_isub && ao->y()->as_Constant()) || ao->op() == Bytecodes::_iadd)) {
756 assert(!ao->x()->as_Constant() || !ao->y()->as_Constant(), "At least one operator must be non-constant!")do { if (!(!ao->x()->as_Constant() || !ao->y()->as_Constant
())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 756, "assert(" "!ao->x()->as_Constant() || !ao->y()->as_Constant()"
") failed", "At least one operator must be non-constant!"); ::
breakpoint(); } } while (0)
;
757 assert(ao->op() == Bytecodes::_isub || ao->op() == Bytecodes::_iadd, "Operation has to be add or sub!")do { if (!(ao->op() == Bytecodes::_isub || ao->op() == Bytecodes
::_iadd)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 757, "assert(" "ao->op() == Bytecodes::_isub || ao->op() == Bytecodes::_iadd"
") failed", "Operation has to be add or sub!"); ::breakpoint
(); } } while (0)
;
758 c = ao->x()->as_Constant();
759 if (c != NULL__null) {
760 const_value = c->type()->as_IntConstant()->value();
761 instr_value = ao->y();
762 } else {
763 c = ao->y()->as_Constant();
764 if (c != NULL__null) {
765 const_value = c->type()->as_IntConstant()->value();
766 instr_value = ao->x();
767 }
768 }
769 if (ao->op() == Bytecodes::_isub) {
770 assert(ao->y()->as_Constant(), "1 - x not supported, only x - 1 is valid!")do { if (!(ao->y()->as_Constant())) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 770, "assert(" "ao->y()->as_Constant()" ") failed", "1 - x not supported, only x - 1 is valid!"
); ::breakpoint(); } } while (0)
;
771 if (const_value > min_jint) {
772 const_value = -const_value;
773 } else {
774 const_value = 0;
775 instr_value = x;
776 }
777 }
778 }
779
780 update_bound(pushed, y, condition, instr_value, const_value);
781}
782
783// Process If
784void RangeCheckEliminator::process_if(IntegerStack &pushed, BlockBegin *block, If *cond) {
785 // Only if we are direct true / false successor and NOT both ! (even this may occur)
786 if ((cond->tsux() == block || cond->fsux() == block) && cond->tsux() != cond->fsux()) {
787 Instruction::Condition condition = cond->cond();
788 if (cond->fsux() == block) {
789 condition = Instruction::negate(condition);
790 }
791 Value x = cond->x();
792 Value y = cond->y();
793 if (x->type()->as_IntType() && y->type()->as_IntType()) {
794 add_if_condition(pushed, y, x, condition);
795 add_if_condition(pushed, x, y, Instruction::mirror(condition));
796 }
797 }
798}
799
800// Process access indexed
801void RangeCheckEliminator::process_access_indexed(BlockBegin *loop_header, BlockBegin *block, AccessIndexed *ai) {
802 TRACE_RANGE_CHECK_ELIMINATION(if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); }
803 tty->fill_to(block->dominator_depth()*2)if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); }
804 )if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); }
;
805 TRACE_RANGE_CHECK_ELIMINATION(if (TraceRangeCheckElimination) { tty->print_cr("Access indexed: index=%d length=%d"
, ai->index()->id(), (ai->length() != __null ? ai->
length()->id() :-1 )); }
806 tty->print_cr("Access indexed: index=%d length=%d", ai->index()->id(), (ai->length() != NULL ? ai->length()->id() :-1 ))if (TraceRangeCheckElimination) { tty->print_cr("Access indexed: index=%d length=%d"
, ai->index()->id(), (ai->length() != __null ? ai->
length()->id() :-1 )); }
807 )if (TraceRangeCheckElimination) { tty->print_cr("Access indexed: index=%d length=%d"
, ai->index()->id(), (ai->length() != __null ? ai->
length()->id() :-1 )); }
;
808
809 if (ai->check_flag(Instruction::NeedsRangeCheckFlag)) {
810 Bound *index_bound = get_bound(ai->index());
811 if (!index_bound->has_lower() || !index_bound->has_upper()) {
812 TRACE_RANGE_CHECK_ELIMINATION(if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Index instruction %d has no lower and/or no upper bound!"
, ai->index()->id()); }
813 tty->fill_to(block->dominator_depth()*2);if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Index instruction %d has no lower and/or no upper bound!"
, ai->index()->id()); }
814 tty->print_cr("Index instruction %d has no lower and/or no upper bound!", ai->index()->id())if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Index instruction %d has no lower and/or no upper bound!"
, ai->index()->id()); }
815 )if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Index instruction %d has no lower and/or no upper bound!"
, ai->index()->id()); }
;
816 return;
817 }
818
819 Bound *array_bound;
820 if (ai->length()) {
821 array_bound = get_bound(ai->length());
822 } else {
823 array_bound = get_bound(ai->array());
824 }
825
826 TRACE_RANGE_CHECK_ELIMINATION(if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print("Index bound: "); index_bound->print(
); tty->print(", Array bound: "); array_bound->print();
tty->cr();; }
827 tty->fill_to(block->dominator_depth()*2);if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print("Index bound: "); index_bound->print(
); tty->print(", Array bound: "); array_bound->print();
tty->cr();; }
828 tty->print("Index bound: ");if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print("Index bound: "); index_bound->print(
); tty->print(", Array bound: "); array_bound->print();
tty->cr();; }
829 index_bound->print();if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print("Index bound: "); index_bound->print(
); tty->print(", Array bound: "); array_bound->print();
tty->cr();; }
830 tty->print(", Array bound: ");if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print("Index bound: "); index_bound->print(
); tty->print(", Array bound: "); array_bound->print();
tty->cr();; }
831 array_bound->print();if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print("Index bound: "); index_bound->print(
); tty->print(", Array bound: "); array_bound->print();
tty->cr();; }
832 tty->cr();if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print("Index bound: "); index_bound->print(
); tty->print(", Array bound: "); array_bound->print();
tty->cr();; }
833 )if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print("Index bound: "); index_bound->print(
); tty->print(", Array bound: "); array_bound->print();
tty->cr();; }
;
834
835 if (in_array_bound(index_bound, ai->array()) ||
836 (index_bound && array_bound && index_bound->is_smaller(array_bound) && !index_bound->lower_instr() && index_bound->lower() >= 0)) {
837 TRACE_RANGE_CHECK_ELIMINATION(if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Bounds check for instruction %d in block B%d can be fully eliminated!"
, ai->id(), ai->block()->block_id()); }
838 tty->fill_to(block->dominator_depth()*2);if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Bounds check for instruction %d in block B%d can be fully eliminated!"
, ai->id(), ai->block()->block_id()); }
839 tty->print_cr("Bounds check for instruction %d in block B%d can be fully eliminated!", ai->id(), ai->block()->block_id())if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Bounds check for instruction %d in block B%d can be fully eliminated!"
, ai->id(), ai->block()->block_id()); }
840 )if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Bounds check for instruction %d in block B%d can be fully eliminated!"
, ai->id(), ai->block()->block_id()); }
;
841
842 remove_range_check(ai);
843 } else if (_optimistic && loop_header) {
844 assert(ai->array(), "Array must not be null!")do { if (!(ai->array())) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 844, "assert(" "ai->array()" ") failed", "Array must not be null!"
); ::breakpoint(); } } while (0)
;
845 assert(ai->index(), "Index must not be null!")do { if (!(ai->index())) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 845, "assert(" "ai->index()" ") failed", "Index must not be null!"
); ::breakpoint(); } } while (0)
;
846
847 // Array instruction
848 Instruction *array_instr = ai->array();
849 if (!loop_invariant(loop_header, array_instr)) {
850 TRACE_RANGE_CHECK_ELIMINATION(if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Array %d is not loop invariant to header B%d"
, ai->array()->id(), loop_header->block_id()); }
851 tty->fill_to(block->dominator_depth()*2);if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Array %d is not loop invariant to header B%d"
, ai->array()->id(), loop_header->block_id()); }
852 tty->print_cr("Array %d is not loop invariant to header B%d", ai->array()->id(), loop_header->block_id())if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Array %d is not loop invariant to header B%d"
, ai->array()->id(), loop_header->block_id()); }
853 )if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Array %d is not loop invariant to header B%d"
, ai->array()->id(), loop_header->block_id()); }
;
854 return;
855 }
856
857 // Lower instruction
858 Value index_instr = ai->index();
859 Value lower_instr = index_bound->lower_instr();
860 if (!loop_invariant(loop_header, lower_instr)) {
861 TRACE_RANGE_CHECK_ELIMINATION(if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Lower instruction %d not loop invariant!"
, lower_instr->id()); }
862 tty->fill_to(block->dominator_depth()*2);if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Lower instruction %d not loop invariant!"
, lower_instr->id()); }
863 tty->print_cr("Lower instruction %d not loop invariant!", lower_instr->id())if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Lower instruction %d not loop invariant!"
, lower_instr->id()); }
864 )if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Lower instruction %d not loop invariant!"
, lower_instr->id()); }
;
865 return;
866 }
867 if (!lower_instr && index_bound->lower() < 0) {
868 TRACE_RANGE_CHECK_ELIMINATION(if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Lower bound smaller than 0 (%d)!", index_bound
->lower()); }
869 tty->fill_to(block->dominator_depth()*2);if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Lower bound smaller than 0 (%d)!", index_bound
->lower()); }
870 tty->print_cr("Lower bound smaller than 0 (%d)!", index_bound->lower())if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Lower bound smaller than 0 (%d)!", index_bound
->lower()); }
871 )if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Lower bound smaller than 0 (%d)!", index_bound
->lower()); }
;
872 return;
873 }
874
875 // Upper instruction
876 Value upper_instr = index_bound->upper_instr();
877 if (!loop_invariant(loop_header, upper_instr)) {
878 TRACE_RANGE_CHECK_ELIMINATION(if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Upper instruction %d not loop invariant!"
, upper_instr->id()); }
879 tty->fill_to(block->dominator_depth()*2);if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Upper instruction %d not loop invariant!"
, upper_instr->id()); }
880 tty->print_cr("Upper instruction %d not loop invariant!", upper_instr->id())if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Upper instruction %d not loop invariant!"
, upper_instr->id()); }
881 )if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Upper instruction %d not loop invariant!"
, upper_instr->id()); }
;
882 return;
883 }
884
885 // Length instruction
886 Value length_instr = ai->length();
887 if (!loop_invariant(loop_header, length_instr)) {
888 // Generate length instruction yourself!
889 length_instr = NULL__null;
890 }
891
892 TRACE_RANGE_CHECK_ELIMINATION(if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("LOOP INVARIANT access indexed %d found in block B%d!"
, ai->id(), ai->block()->block_id()); }
893 tty->fill_to(block->dominator_depth()*2);if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("LOOP INVARIANT access indexed %d found in block B%d!"
, ai->id(), ai->block()->block_id()); }
894 tty->print_cr("LOOP INVARIANT access indexed %d found in block B%d!", ai->id(), ai->block()->block_id())if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("LOOP INVARIANT access indexed %d found in block B%d!"
, ai->id(), ai->block()->block_id()); }
895 )if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("LOOP INVARIANT access indexed %d found in block B%d!"
, ai->id(), ai->block()->block_id()); }
;
896
897 BlockBegin *pred_block = loop_header->dominator();
898 assert(pred_block != NULL, "Every loop header has a dominator!")do { if (!(pred_block != __null)) { (*g_assert_poison) = 'X';
; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 898, "assert(" "pred_block != __null" ") failed", "Every loop header has a dominator!"
); ::breakpoint(); } } while (0)
;
899 BlockEnd *pred_block_end = pred_block->end();
900 Instruction *insert_position = pred_block_end->prev();
901 ValueStack *state = pred_block_end->state_before();
902 if (pred_block_end->as_Goto() && state == NULL__null) state = pred_block_end->state();
903 assert(state, "State must not be null")do { if (!(state)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 903, "assert(" "state" ") failed", "State must not be null"
); ::breakpoint(); } } while (0)
;
904
905 // Add deoptimization to dominator of loop header
906 TRACE_RANGE_CHECK_ELIMINATION(if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Inserting deopt at bci %d in block B%d!"
, state->bci(), insert_position->block()->block_id()
); }
907 tty->fill_to(block->dominator_depth()*2);if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Inserting deopt at bci %d in block B%d!"
, state->bci(), insert_position->block()->block_id()
); }
908 tty->print_cr("Inserting deopt at bci %d in block B%d!", state->bci(), insert_position->block()->block_id())if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Inserting deopt at bci %d in block B%d!"
, state->bci(), insert_position->block()->block_id()
); }
909 )if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Inserting deopt at bci %d in block B%d!"
, state->bci(), insert_position->block()->block_id()
); }
;
910
911 if (!is_ok_for_deoptimization(insert_position, array_instr, length_instr, lower_instr, index_bound->lower(), upper_instr, index_bound->upper())) {
912 TRACE_RANGE_CHECK_ELIMINATION(if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Could not eliminate because of static analysis!"
); }
913 tty->fill_to(block->dominator_depth()*2);if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Could not eliminate because of static analysis!"
); }
914 tty->print_cr("Could not eliminate because of static analysis!")if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Could not eliminate because of static analysis!"
); }
915 )if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Could not eliminate because of static analysis!"
); }
;
916 return;
917 }
918
919 insert_deoptimization(state, insert_position, array_instr, length_instr, lower_instr, index_bound->lower(), upper_instr, index_bound->upper(), ai);
920
921 // Finally remove the range check!
922 remove_range_check(ai);
923 }
924 }
925}
926
927void RangeCheckEliminator::remove_range_check(AccessIndexed *ai) {
928 ai->set_flag(Instruction::NeedsRangeCheckFlag, false);
929 // no range check, no need for the length instruction anymore
930 ai->clear_length();
931
932 TRACE_RANGE_CHECK_ELIMINATION(if (TraceRangeCheckElimination) { tty->fill_to(ai->dominator_depth
()*2); tty->print_cr("Range check for instruction %d eliminated!"
, ai->id());; }
933 tty->fill_to(ai->dominator_depth()*2);if (TraceRangeCheckElimination) { tty->fill_to(ai->dominator_depth
()*2); tty->print_cr("Range check for instruction %d eliminated!"
, ai->id());; }
934 tty->print_cr("Range check for instruction %d eliminated!", ai->id());if (TraceRangeCheckElimination) { tty->fill_to(ai->dominator_depth
()*2); tty->print_cr("Range check for instruction %d eliminated!"
, ai->id());; }
935 )if (TraceRangeCheckElimination) { tty->fill_to(ai->dominator_depth
()*2); tty->print_cr("Range check for instruction %d eliminated!"
, ai->id());; }
;
936
937 ASSERT_RANGE_CHECK_ELIMINATION(if (AssertRangeCheckElimination) { Value array_length = ai->
length(); if (!array_length) { array_length = ai->array();
do { if (!(array_length->type()->as_ObjectType())) { (
*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 941, "assert(" "array_length->type()->as_ObjectType()"
") failed", "Has to be object type!"); ::breakpoint(); } } while
(0); } int cur_constant = -1; Value cur_value = array_length
; if (cur_value->type()->as_IntConstant()) { cur_constant
+= cur_value->type()->as_IntConstant()->value(); cur_value
= __null; } Bound *new_index_bound = new Bound(0, __null, cur_constant
, cur_value); add_assertions(new_index_bound, ai->index(),
ai);; }
938 Value array_length = ai->length();if (AssertRangeCheckElimination) { Value array_length = ai->
length(); if (!array_length) { array_length = ai->array();
do { if (!(array_length->type()->as_ObjectType())) { (
*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 941, "assert(" "array_length->type()->as_ObjectType()"
") failed", "Has to be object type!"); ::breakpoint(); } } while
(0); } int cur_constant = -1; Value cur_value = array_length
; if (cur_value->type()->as_IntConstant()) { cur_constant
+= cur_value->type()->as_IntConstant()->value(); cur_value
= __null; } Bound *new_index_bound = new Bound(0, __null, cur_constant
, cur_value); add_assertions(new_index_bound, ai->index(),
ai);; }
939 if (!array_length) {if (AssertRangeCheckElimination) { Value array_length = ai->
length(); if (!array_length) { array_length = ai->array();
do { if (!(array_length->type()->as_ObjectType())) { (
*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 941, "assert(" "array_length->type()->as_ObjectType()"
") failed", "Has to be object type!"); ::breakpoint(); } } while
(0); } int cur_constant = -1; Value cur_value = array_length
; if (cur_value->type()->as_IntConstant()) { cur_constant
+= cur_value->type()->as_IntConstant()->value(); cur_value
= __null; } Bound *new_index_bound = new Bound(0, __null, cur_constant
, cur_value); add_assertions(new_index_bound, ai->index(),
ai);; }
940 array_length = ai->array();if (AssertRangeCheckElimination) { Value array_length = ai->
length(); if (!array_length) { array_length = ai->array();
do { if (!(array_length->type()->as_ObjectType())) { (
*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 941, "assert(" "array_length->type()->as_ObjectType()"
") failed", "Has to be object type!"); ::breakpoint(); } } while
(0); } int cur_constant = -1; Value cur_value = array_length
; if (cur_value->type()->as_IntConstant()) { cur_constant
+= cur_value->type()->as_IntConstant()->value(); cur_value
= __null; } Bound *new_index_bound = new Bound(0, __null, cur_constant
, cur_value); add_assertions(new_index_bound, ai->index(),
ai);; }
941 assert(array_length->type()->as_ObjectType(), "Has to be object type!");if (AssertRangeCheckElimination) { Value array_length = ai->
length(); if (!array_length) { array_length = ai->array();
do { if (!(array_length->type()->as_ObjectType())) { (
*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 941, "assert(" "array_length->type()->as_ObjectType()"
") failed", "Has to be object type!"); ::breakpoint(); } } while
(0); } int cur_constant = -1; Value cur_value = array_length
; if (cur_value->type()->as_IntConstant()) { cur_constant
+= cur_value->type()->as_IntConstant()->value(); cur_value
= __null; } Bound *new_index_bound = new Bound(0, __null, cur_constant
, cur_value); add_assertions(new_index_bound, ai->index(),
ai);; }
942 }if (AssertRangeCheckElimination) { Value array_length = ai->
length(); if (!array_length) { array_length = ai->array();
do { if (!(array_length->type()->as_ObjectType())) { (
*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 941, "assert(" "array_length->type()->as_ObjectType()"
") failed", "Has to be object type!"); ::breakpoint(); } } while
(0); } int cur_constant = -1; Value cur_value = array_length
; if (cur_value->type()->as_IntConstant()) { cur_constant
+= cur_value->type()->as_IntConstant()->value(); cur_value
= __null; } Bound *new_index_bound = new Bound(0, __null, cur_constant
, cur_value); add_assertions(new_index_bound, ai->index(),
ai);; }
943 int cur_constant = -1;if (AssertRangeCheckElimination) { Value array_length = ai->
length(); if (!array_length) { array_length = ai->array();
do { if (!(array_length->type()->as_ObjectType())) { (
*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 941, "assert(" "array_length->type()->as_ObjectType()"
") failed", "Has to be object type!"); ::breakpoint(); } } while
(0); } int cur_constant = -1; Value cur_value = array_length
; if (cur_value->type()->as_IntConstant()) { cur_constant
+= cur_value->type()->as_IntConstant()->value(); cur_value
= __null; } Bound *new_index_bound = new Bound(0, __null, cur_constant
, cur_value); add_assertions(new_index_bound, ai->index(),
ai);; }
944 Value cur_value = array_length;if (AssertRangeCheckElimination) { Value array_length = ai->
length(); if (!array_length) { array_length = ai->array();
do { if (!(array_length->type()->as_ObjectType())) { (
*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 941, "assert(" "array_length->type()->as_ObjectType()"
") failed", "Has to be object type!"); ::breakpoint(); } } while
(0); } int cur_constant = -1; Value cur_value = array_length
; if (cur_value->type()->as_IntConstant()) { cur_constant
+= cur_value->type()->as_IntConstant()->value(); cur_value
= __null; } Bound *new_index_bound = new Bound(0, __null, cur_constant
, cur_value); add_assertions(new_index_bound, ai->index(),
ai);; }
945 if (cur_value->type()->as_IntConstant()) {if (AssertRangeCheckElimination) { Value array_length = ai->
length(); if (!array_length) { array_length = ai->array();
do { if (!(array_length->type()->as_ObjectType())) { (
*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 941, "assert(" "array_length->type()->as_ObjectType()"
") failed", "Has to be object type!"); ::breakpoint(); } } while
(0); } int cur_constant = -1; Value cur_value = array_length
; if (cur_value->type()->as_IntConstant()) { cur_constant
+= cur_value->type()->as_IntConstant()->value(); cur_value
= __null; } Bound *new_index_bound = new Bound(0, __null, cur_constant
, cur_value); add_assertions(new_index_bound, ai->index(),
ai);; }
946 cur_constant += cur_value->type()->as_IntConstant()->value();if (AssertRangeCheckElimination) { Value array_length = ai->
length(); if (!array_length) { array_length = ai->array();
do { if (!(array_length->type()->as_ObjectType())) { (
*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 941, "assert(" "array_length->type()->as_ObjectType()"
") failed", "Has to be object type!"); ::breakpoint(); } } while
(0); } int cur_constant = -1; Value cur_value = array_length
; if (cur_value->type()->as_IntConstant()) { cur_constant
+= cur_value->type()->as_IntConstant()->value(); cur_value
= __null; } Bound *new_index_bound = new Bound(0, __null, cur_constant
, cur_value); add_assertions(new_index_bound, ai->index(),
ai);; }
947 cur_value = NULL;if (AssertRangeCheckElimination) { Value array_length = ai->
length(); if (!array_length) { array_length = ai->array();
do { if (!(array_length->type()->as_ObjectType())) { (
*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 941, "assert(" "array_length->type()->as_ObjectType()"
") failed", "Has to be object type!"); ::breakpoint(); } } while
(0); } int cur_constant = -1; Value cur_value = array_length
; if (cur_value->type()->as_IntConstant()) { cur_constant
+= cur_value->type()->as_IntConstant()->value(); cur_value
= __null; } Bound *new_index_bound = new Bound(0, __null, cur_constant
, cur_value); add_assertions(new_index_bound, ai->index(),
ai);; }
948 }if (AssertRangeCheckElimination) { Value array_length = ai->
length(); if (!array_length) { array_length = ai->array();
do { if (!(array_length->type()->as_ObjectType())) { (
*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 941, "assert(" "array_length->type()->as_ObjectType()"
") failed", "Has to be object type!"); ::breakpoint(); } } while
(0); } int cur_constant = -1; Value cur_value = array_length
; if (cur_value->type()->as_IntConstant()) { cur_constant
+= cur_value->type()->as_IntConstant()->value(); cur_value
= __null; } Bound *new_index_bound = new Bound(0, __null, cur_constant
, cur_value); add_assertions(new_index_bound, ai->index(),
ai);; }
949 Bound *new_index_bound = new Bound(0, NULL, cur_constant, cur_value);if (AssertRangeCheckElimination) { Value array_length = ai->
length(); if (!array_length) { array_length = ai->array();
do { if (!(array_length->type()->as_ObjectType())) { (
*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 941, "assert(" "array_length->type()->as_ObjectType()"
") failed", "Has to be object type!"); ::breakpoint(); } } while
(0); } int cur_constant = -1; Value cur_value = array_length
; if (cur_value->type()->as_IntConstant()) { cur_constant
+= cur_value->type()->as_IntConstant()->value(); cur_value
= __null; } Bound *new_index_bound = new Bound(0, __null, cur_constant
, cur_value); add_assertions(new_index_bound, ai->index(),
ai);; }
950 add_assertions(new_index_bound, ai->index(), ai);if (AssertRangeCheckElimination) { Value array_length = ai->
length(); if (!array_length) { array_length = ai->array();
do { if (!(array_length->type()->as_ObjectType())) { (
*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 941, "assert(" "array_length->type()->as_ObjectType()"
") failed", "Has to be object type!"); ::breakpoint(); } } while
(0); } int cur_constant = -1; Value cur_value = array_length
; if (cur_value->type()->as_IntConstant()) { cur_constant
+= cur_value->type()->as_IntConstant()->value(); cur_value
= __null; } Bound *new_index_bound = new Bound(0, __null, cur_constant
, cur_value); add_assertions(new_index_bound, ai->index(),
ai);; }
951 )if (AssertRangeCheckElimination) { Value array_length = ai->
length(); if (!array_length) { array_length = ai->array();
do { if (!(array_length->type()->as_ObjectType())) { (
*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 941, "assert(" "array_length->type()->as_ObjectType()"
") failed", "Has to be object type!"); ::breakpoint(); } } while
(0); } int cur_constant = -1; Value cur_value = array_length
; if (cur_value->type()->as_IntConstant()) { cur_constant
+= cur_value->type()->as_IntConstant()->value(); cur_value
= __null; } Bound *new_index_bound = new Bound(0, __null, cur_constant
, cur_value); add_assertions(new_index_bound, ai->index(),
ai);; }
;
952}
953
954// Calculate bounds for instruction in this block and children blocks in the dominator tree
955void RangeCheckEliminator::calc_bounds(BlockBegin *block, BlockBegin *loop_header) {
956 // Ensures a valid loop_header
957 assert(!loop_header || loop_header->is_set(BlockBegin::linear_scan_loop_header_flag), "Loop header has to be real !")do { if (!(!loop_header || loop_header->is_set(BlockBegin::
linear_scan_loop_header_flag))) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 957, "assert(" "!loop_header || loop_header->is_set(BlockBegin::linear_scan_loop_header_flag)"
") failed", "Loop header has to be real !"); ::breakpoint();
} } while (0)
;
958
959 // Tracing output
960 TRACE_RANGE_CHECK_ELIMINATION(if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Block B%d", block->block_id());; }
961 tty->fill_to(block->dominator_depth()*2);if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Block B%d", block->block_id());; }
962 tty->print_cr("Block B%d", block->block_id());if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Block B%d", block->block_id());; }
963 )if (TraceRangeCheckElimination) { tty->fill_to(block->dominator_depth
()*2); tty->print_cr("Block B%d", block->block_id());; }
;
964
965 // Pushed stack for conditions
966 IntegerStack pushed;
967 // Process If
968 BlockBegin *parent = block->dominator();
969 if (parent != NULL__null) {
970 If *cond = parent->end()->as_If();
971 if (cond != NULL__null) {
972 process_if(pushed, block, cond);
973 }
974 }
975
976 // Interate over current block
977 InstructionList arrays;
978 AccessIndexedList accessIndexed;
979 Instruction *cur = block;
980
981 while (cur) {
982 // Ensure cur wasn't inserted during the elimination
983 if (cur->id() < this->_bounds.length()) {
984 // Process only if it is an access indexed instruction
985 AccessIndexed *ai = cur->as_AccessIndexed();
986 if (ai != NULL__null) {
987 process_access_indexed(loop_header, block, ai);
988 accessIndexed.append(ai);
989 if (!arrays.contains(ai->array())) {
990 arrays.append(ai->array());
991 }
992 Bound *b = get_bound(ai->index());
993 if (!b->lower_instr()) {
994 // Lower bound is constant
995 update_bound(pushed, ai->index(), Instruction::geq, NULL__null, 0);
996 }
997 if (!b->has_upper()) {
998 if (ai->length() && ai->length()->type()->as_IntConstant()) {
999 int value = ai->length()->type()->as_IntConstant()->value();
1000 update_bound(pushed, ai->index(), Instruction::lss, NULL__null, value);
1001 } else {
1002 // Has no upper bound
1003 Instruction *instr = ai->length();
1004 if (instr == NULL__null) instr = ai->array();
1005 update_bound(pushed, ai->index(), Instruction::lss, instr, 0);
1006 }
1007 }
1008 }
1009 }
1010 cur = cur->next();
1011 }
1012
1013 // Output current condition stack
1014 TRACE_RANGE_CHECK_ELIMINATION(dump_condition_stack(block))if (TraceRangeCheckElimination) { dump_condition_stack(block)
; }
;
1015
1016 // Do in block motion of range checks
1017 in_block_motion(block, accessIndexed, arrays);
1018
1019 // Call all dominated blocks
1020 for (int i=0; i<block->dominates()->length(); i++) {
1021 BlockBegin *next = block->dominates()->at(i);
1022 if (!next->is_set(BlockBegin::donot_eliminate_range_checks)) {
1023 // if current block is a loop header and:
1024 // - next block belongs to the same loop
1025 // or
1026 // - next block belongs to an inner loop
1027 // then current block is the loop header for next block
1028 if (block->is_set(BlockBegin::linear_scan_loop_header_flag) && (block->loop_index() == next->loop_index() || next->loop_depth() > block->loop_depth())) {
1029 calc_bounds(next, block);
1030 } else {
1031 calc_bounds(next, loop_header);
1032 }
1033 }
1034 }
1035
1036 // Reset stack
1037 for (int i=0; i<pushed.length(); i++) {
1038 _bounds.at(pushed.at(i))->pop();
1039 }
1040}
1041
1042#ifndef PRODUCT
1043// Dump condition stack
1044void RangeCheckEliminator::dump_condition_stack(BlockBegin *block) {
1045 for (int i=0; i<_ir->linear_scan_order()->length(); i++) {
1046 BlockBegin *cur_block = _ir->linear_scan_order()->at(i);
1047 Instruction *instr = cur_block;
1048 for_each_phi_fun(cur_block, phi,{ int cur_index; ValueStack* cur_state = cur_block->state(
); Value value; { int temp__1060 = cur_state->stack_size()
; for (cur_index = 0; cur_index < temp__1060 && (value
= cur_state->stack_at(cur_index), true); cur_index += value
->type()->size()) { Phi* phi = value->as_Phi(); if (
phi != __null && phi->block() == cur_block) { BoundStack
*bound_stack = _bounds.at(phi->id()); if (bound_stack &&
bound_stack->length() > 0) { Bound *bound = bound_stack
->top(); if ((bound->has_lower() || bound->has_upper
()) && (bound->lower_instr() != phi || bound->upper_instr
() != phi || bound->lower() != 0 || bound->upper() != 0
)) { if (TraceRangeCheckElimination) { tty->fill_to(2*block
->dominator_depth()); tty->print("i%d", phi->id()); tty
->print(": "); bound->print(); tty->cr();; }; } }; }
} } { int temp__1060 = cur_state->locals_size(); for (cur_index
= 0; cur_index < temp__1060 && (value = cur_state
->local_at(cur_index), true); cur_index += (value == __null
|| value->type()->is_illegal() ? 1 : value->type()->
size())) if (value != __null) { Phi* phi = value->as_Phi()
; if (phi != __null && phi->block() == cur_block) {
BoundStack *bound_stack = _bounds.at(phi->id()); if (bound_stack
&& bound_stack->length() > 0) { Bound *bound =
bound_stack->top(); if ((bound->has_lower() || bound->
has_upper()) && (bound->lower_instr() != phi || bound
->upper_instr() != phi || bound->lower() != 0 || bound->
upper() != 0)) { if (TraceRangeCheckElimination) { tty->fill_to
(2*block->dominator_depth()); tty->print("i%d", phi->
id()); tty->print(": "); bound->print(); tty->cr();;
}; } }; } } } }
1049 BoundStack *bound_stack = _bounds.at(phi->id());{ int cur_index; ValueStack* cur_state = cur_block->state(
); Value value; { int temp__1060 = cur_state->stack_size()
; for (cur_index = 0; cur_index < temp__1060 && (value
= cur_state->stack_at(cur_index), true); cur_index += value
->type()->size()) { Phi* phi = value->as_Phi(); if (
phi != __null && phi->block() == cur_block) { BoundStack
*bound_stack = _bounds.at(phi->id()); if (bound_stack &&
bound_stack->length() > 0) { Bound *bound = bound_stack
->top(); if ((bound->has_lower() || bound->has_upper
()) && (bound->lower_instr() != phi || bound->upper_instr
() != phi || bound->lower() != 0 || bound->upper() != 0
)) { if (TraceRangeCheckElimination) { tty->fill_to(2*block
->dominator_depth()); tty->print("i%d", phi->id()); tty
->print(": "); bound->print(); tty->cr();; }; } }; }
} } { int temp__1060 = cur_state->locals_size(); for (cur_index
= 0; cur_index < temp__1060 && (value = cur_state
->local_at(cur_index), true); cur_index += (value == __null
|| value->type()->is_illegal() ? 1 : value->type()->
size())) if (value != __null) { Phi* phi = value->as_Phi()
; if (phi != __null && phi->block() == cur_block) {
BoundStack *bound_stack = _bounds.at(phi->id()); if (bound_stack
&& bound_stack->length() > 0) { Bound *bound =
bound_stack->top(); if ((bound->has_lower() || bound->
has_upper()) && (bound->lower_instr() != phi || bound
->upper_instr() != phi || bound->lower() != 0 || bound->
upper() != 0)) { if (TraceRangeCheckElimination) { tty->fill_to
(2*block->dominator_depth()); tty->print("i%d", phi->
id()); tty->print(": "); bound->print(); tty->cr();;
}; } }; } } } }
1050 if (bound_stack && bound_stack->length() > 0) {{ int cur_index; ValueStack* cur_state = cur_block->state(
); Value value; { int temp__1060 = cur_state->stack_size()
; for (cur_index = 0; cur_index < temp__1060 && (value
= cur_state->stack_at(cur_index), true); cur_index += value
->type()->size()) { Phi* phi = value->as_Phi(); if (
phi != __null && phi->block() == cur_block) { BoundStack
*bound_stack = _bounds.at(phi->id()); if (bound_stack &&
bound_stack->length() > 0) { Bound *bound = bound_stack
->top(); if ((bound->has_lower() || bound->has_upper
()) && (bound->lower_instr() != phi || bound->upper_instr
() != phi || bound->lower() != 0 || bound->upper() != 0
)) { if (TraceRangeCheckElimination) { tty->fill_to(2*block
->dominator_depth()); tty->print("i%d", phi->id()); tty
->print(": "); bound->print(); tty->cr();; }; } }; }
} } { int temp__1060 = cur_state->locals_size(); for (cur_index
= 0; cur_index < temp__1060 && (value = cur_state
->local_at(cur_index), true); cur_index += (value == __null
|| value->type()->is_illegal() ? 1 : value->type()->
size())) if (value != __null) { Phi* phi = value->as_Phi()
; if (phi != __null && phi->block() == cur_block) {
BoundStack *bound_stack = _bounds.at(phi->id()); if (bound_stack
&& bound_stack->length() > 0) { Bound *bound =
bound_stack->top(); if ((bound->has_lower() || bound->
has_upper()) && (bound->lower_instr() != phi || bound
->upper_instr() != phi || bound->lower() != 0 || bound->
upper() != 0)) { if (TraceRangeCheckElimination) { tty->fill_to
(2*block->dominator_depth()); tty->print("i%d", phi->
id()); tty->print(": "); bound->print(); tty->cr();;
}; } }; } } } }
1051 Bound *bound = bound_stack->top();{ int cur_index; ValueStack* cur_state = cur_block->state(
); Value value; { int temp__1060 = cur_state->stack_size()
; for (cur_index = 0; cur_index < temp__1060 && (value
= cur_state->stack_at(cur_index), true); cur_index += value
->type()->size()) { Phi* phi = value->as_Phi(); if (
phi != __null && phi->block() == cur_block) { BoundStack
*bound_stack = _bounds.at(phi->id()); if (bound_stack &&
bound_stack->length() > 0) { Bound *bound = bound_stack
->top(); if ((bound->has_lower() || bound->has_upper
()) && (bound->lower_instr() != phi || bound->upper_instr
() != phi || bound->lower() != 0 || bound->upper() != 0
)) { if (TraceRangeCheckElimination) { tty->fill_to(2*block
->dominator_depth()); tty->print("i%d", phi->id()); tty
->print(": "); bound->print(); tty->cr();; }; } }; }
} } { int temp__1060 = cur_state->locals_size(); for (cur_index
= 0; cur_index < temp__1060 && (value = cur_state
->local_at(cur_index), true); cur_index += (value == __null
|| value->type()->is_illegal() ? 1 : value->type()->
size())) if (value != __null) { Phi* phi = value->as_Phi()
; if (phi != __null && phi->block() == cur_block) {
BoundStack *bound_stack = _bounds.at(phi->id()); if (bound_stack
&& bound_stack->length() > 0) { Bound *bound =
bound_stack->top(); if ((bound->has_lower() || bound->
has_upper()) && (bound->lower_instr() != phi || bound
->upper_instr() != phi || bound->lower() != 0 || bound->
upper() != 0)) { if (TraceRangeCheckElimination) { tty->fill_to
(2*block->dominator_depth()); tty->print("i%d", phi->
id()); tty->print(": "); bound->print(); tty->cr();;
}; } }; } } } }
1052 if ((bound->has_lower() || bound->has_upper()) && (bound->lower_instr() != phi || bound->upper_instr() != phi || bound->lower() != 0 || bound->upper() != 0)) {{ int cur_index; ValueStack* cur_state = cur_block->state(
); Value value; { int temp__1060 = cur_state->stack_size()
; for (cur_index = 0; cur_index < temp__1060 && (value
= cur_state->stack_at(cur_index), true); cur_index += value
->type()->size()) { Phi* phi = value->as_Phi(); if (
phi != __null && phi->block() == cur_block) { BoundStack
*bound_stack = _bounds.at(phi->id()); if (bound_stack &&
bound_stack->length() > 0) { Bound *bound = bound_stack
->top(); if ((bound->has_lower() || bound->has_upper
()) && (bound->lower_instr() != phi || bound->upper_instr
() != phi || bound->lower() != 0 || bound->upper() != 0
)) { if (TraceRangeCheckElimination) { tty->fill_to(2*block
->dominator_depth()); tty->print("i%d", phi->id()); tty
->print(": "); bound->print(); tty->cr();; }; } }; }
} } { int temp__1060 = cur_state->locals_size(); for (cur_index
= 0; cur_index < temp__1060 && (value = cur_state
->local_at(cur_index), true); cur_index += (value == __null
|| value->type()->is_illegal() ? 1 : value->type()->
size())) if (value != __null) { Phi* phi = value->as_Phi()
; if (phi != __null && phi->block() == cur_block) {
BoundStack *bound_stack = _bounds.at(phi->id()); if (bound_stack
&& bound_stack->length() > 0) { Bound *bound =
bound_stack->top(); if ((bound->has_lower() || bound->
has_upper()) && (bound->lower_instr() != phi || bound
->upper_instr() != phi || bound->lower() != 0 || bound->
upper() != 0)) { if (TraceRangeCheckElimination) { tty->fill_to
(2*block->dominator_depth()); tty->print("i%d", phi->
id()); tty->print(": "); bound->print(); tty->cr();;
}; } }; } } } }
1053 TRACE_RANGE_CHECK_ELIMINATION(tty->fill_to(2*block->dominator_depth());{ int cur_index; ValueStack* cur_state = cur_block->state(
); Value value; { int temp__1060 = cur_state->stack_size()
; for (cur_index = 0; cur_index < temp__1060 && (value
= cur_state->stack_at(cur_index), true); cur_index += value
->type()->size()) { Phi* phi = value->as_Phi(); if (
phi != __null && phi->block() == cur_block) { BoundStack
*bound_stack = _bounds.at(phi->id()); if (bound_stack &&
bound_stack->length() > 0) { Bound *bound = bound_stack
->top(); if ((bound->has_lower() || bound->has_upper
()) && (bound->lower_instr() != phi || bound->upper_instr
() != phi || bound->lower() != 0 || bound->upper() != 0
)) { if (TraceRangeCheckElimination) { tty->fill_to(2*block
->dominator_depth()); tty->print("i%d", phi->id()); tty
->print(": "); bound->print(); tty->cr();; }; } }; }
} } { int temp__1060 = cur_state->locals_size(); for (cur_index
= 0; cur_index < temp__1060 && (value = cur_state
->local_at(cur_index), true); cur_index += (value == __null
|| value->type()->is_illegal() ? 1 : value->type()->
size())) if (value != __null) { Phi* phi = value->as_Phi()
; if (phi != __null && phi->block() == cur_block) {
BoundStack *bound_stack = _bounds.at(phi->id()); if (bound_stack
&& bound_stack->length() > 0) { Bound *bound =
bound_stack->top(); if ((bound->has_lower() || bound->
has_upper()) && (bound->lower_instr() != phi || bound
->upper_instr() != phi || bound->lower() != 0 || bound->
upper() != 0)) { if (TraceRangeCheckElimination) { tty->fill_to
(2*block->dominator_depth()); tty->print("i%d", phi->
id()); tty->print(": "); bound->print(); tty->cr();;
}; } }; } } } }
1054 tty->print("i%d", phi->id());{ int cur_index; ValueStack* cur_state = cur_block->state(
); Value value; { int temp__1060 = cur_state->stack_size()
; for (cur_index = 0; cur_index < temp__1060 && (value
= cur_state->stack_at(cur_index), true); cur_index += value
->type()->size()) { Phi* phi = value->as_Phi(); if (
phi != __null && phi->block() == cur_block) { BoundStack
*bound_stack = _bounds.at(phi->id()); if (bound_stack &&
bound_stack->length() > 0) { Bound *bound = bound_stack
->top(); if ((bound->has_lower() || bound->has_upper
()) && (bound->lower_instr() != phi || bound->upper_instr
() != phi || bound->lower() != 0 || bound->upper() != 0
)) { if (TraceRangeCheckElimination) { tty->fill_to(2*block
->dominator_depth()); tty->print("i%d", phi->id()); tty
->print(": "); bound->print(); tty->cr();; }; } }; }
} } { int temp__1060 = cur_state->locals_size(); for (cur_index
= 0; cur_index < temp__1060 && (value = cur_state
->local_at(cur_index), true); cur_index += (value == __null
|| value->type()->is_illegal() ? 1 : value->type()->
size())) if (value != __null) { Phi* phi = value->as_Phi()
; if (phi != __null && phi->block() == cur_block) {
BoundStack *bound_stack = _bounds.at(phi->id()); if (bound_stack
&& bound_stack->length() > 0) { Bound *bound =
bound_stack->top(); if ((bound->has_lower() || bound->
has_upper()) && (bound->lower_instr() != phi || bound
->upper_instr() != phi || bound->lower() != 0 || bound->
upper() != 0)) { if (TraceRangeCheckElimination) { tty->fill_to
(2*block->dominator_depth()); tty->print("i%d", phi->
id()); tty->print(": "); bound->print(); tty->cr();;
}; } }; } } } }
1055 tty->print(": ");{ int cur_index; ValueStack* cur_state = cur_block->state(
); Value value; { int temp__1060 = cur_state->stack_size()
; for (cur_index = 0; cur_index < temp__1060 && (value
= cur_state->stack_at(cur_index), true); cur_index += value
->type()->size()) { Phi* phi = value->as_Phi(); if (
phi != __null && phi->block() == cur_block) { BoundStack
*bound_stack = _bounds.at(phi->id()); if (bound_stack &&
bound_stack->length() > 0) { Bound *bound = bound_stack
->top(); if ((bound->has_lower() || bound->has_upper
()) && (bound->lower_instr() != phi || bound->upper_instr
() != phi || bound->lower() != 0 || bound->upper() != 0
)) { if (TraceRangeCheckElimination) { tty->fill_to(2*block
->dominator_depth()); tty->print("i%d", phi->id()); tty
->print(": "); bound->print(); tty->cr();; }; } }; }
} } { int temp__1060 = cur_state->locals_size(); for (cur_index
= 0; cur_index < temp__1060 && (value = cur_state
->local_at(cur_index), true); cur_index += (value == __null
|| value->type()->is_illegal() ? 1 : value->type()->
size())) if (value != __null) { Phi* phi = value->as_Phi()
; if (phi != __null && phi->block() == cur_block) {
BoundStack *bound_stack = _bounds.at(phi->id()); if (bound_stack
&& bound_stack->length() > 0) { Bound *bound =
bound_stack->top(); if ((bound->has_lower() || bound->
has_upper()) && (bound->lower_instr() != phi || bound
->upper_instr() != phi || bound->lower() != 0 || bound->
upper() != 0)) { if (TraceRangeCheckElimination) { tty->fill_to
(2*block->dominator_depth()); tty->print("i%d", phi->
id()); tty->print(": "); bound->print(); tty->cr();;
}; } }; } } } }
1056 bound->print();{ int cur_index; ValueStack* cur_state = cur_block->state(
); Value value; { int temp__1060 = cur_state->stack_size()
; for (cur_index = 0; cur_index < temp__1060 && (value
= cur_state->stack_at(cur_index), true); cur_index += value
->type()->size()) { Phi* phi = value->as_Phi(); if (
phi != __null && phi->block() == cur_block) { BoundStack
*bound_stack = _bounds.at(phi->id()); if (bound_stack &&
bound_stack->length() > 0) { Bound *bound = bound_stack
->top(); if ((bound->has_lower() || bound->has_upper
()) && (bound->lower_instr() != phi || bound->upper_instr
() != phi || bound->lower() != 0 || bound->upper() != 0
)) { if (TraceRangeCheckElimination) { tty->fill_to(2*block
->dominator_depth()); tty->print("i%d", phi->id()); tty
->print(": "); bound->print(); tty->cr();; }; } }; }
} } { int temp__1060 = cur_state->locals_size(); for (cur_index
= 0; cur_index < temp__1060 && (value = cur_state
->local_at(cur_index), true); cur_index += (value == __null
|| value->type()->is_illegal() ? 1 : value->type()->
size())) if (value != __null) { Phi* phi = value->as_Phi()
; if (phi != __null && phi->block() == cur_block) {
BoundStack *bound_stack = _bounds.at(phi->id()); if (bound_stack
&& bound_stack->length() > 0) { Bound *bound =
bound_stack->top(); if ((bound->has_lower() || bound->
has_upper()) && (bound->lower_instr() != phi || bound
->upper_instr() != phi || bound->lower() != 0 || bound->
upper() != 0)) { if (TraceRangeCheckElimination) { tty->fill_to
(2*block->dominator_depth()); tty->print("i%d", phi->
id()); tty->print(": "); bound->print(); tty->cr();;
}; } }; } } } }
1057 tty->cr();{ int cur_index; ValueStack* cur_state = cur_block->state(
); Value value; { int temp__1060 = cur_state->stack_size()
; for (cur_index = 0; cur_index < temp__1060 && (value
= cur_state->stack_at(cur_index), true); cur_index += value
->type()->size()) { Phi* phi = value->as_Phi(); if (
phi != __null && phi->block() == cur_block) { BoundStack
*bound_stack = _bounds.at(phi->id()); if (bound_stack &&
bound_stack->length() > 0) { Bound *bound = bound_stack
->top(); if ((bound->has_lower() || bound->has_upper
()) && (bound->lower_instr() != phi || bound->upper_instr
() != phi || bound->lower() != 0 || bound->upper() != 0
)) { if (TraceRangeCheckElimination) { tty->fill_to(2*block
->dominator_depth()); tty->print("i%d", phi->id()); tty
->print(": "); bound->print(); tty->cr();; }; } }; }
} } { int temp__1060 = cur_state->locals_size(); for (cur_index
= 0; cur_index < temp__1060 && (value = cur_state
->local_at(cur_index), true); cur_index += (value == __null
|| value->type()->is_illegal() ? 1 : value->type()->
size())) if (value != __null) { Phi* phi = value->as_Phi()
; if (phi != __null && phi->block() == cur_block) {
BoundStack *bound_stack = _bounds.at(phi->id()); if (bound_stack
&& bound_stack->length() > 0) { Bound *bound =
bound_stack->top(); if ((bound->has_lower() || bound->
has_upper()) && (bound->lower_instr() != phi || bound
->upper_instr() != phi || bound->lower() != 0 || bound->
upper() != 0)) { if (TraceRangeCheckElimination) { tty->fill_to
(2*block->dominator_depth()); tty->print("i%d", phi->
id()); tty->print(": "); bound->print(); tty->cr();;
}; } }; } } } }
1058 );{ int cur_index; ValueStack* cur_state = cur_block->state(
); Value value; { int temp__1060 = cur_state->stack_size()
; for (cur_index = 0; cur_index < temp__1060 && (value
= cur_state->stack_at(cur_index), true); cur_index += value
->type()->size()) { Phi* phi = value->as_Phi(); if (
phi != __null && phi->block() == cur_block) { BoundStack
*bound_stack = _bounds.at(phi->id()); if (bound_stack &&
bound_stack->length() > 0) { Bound *bound = bound_stack
->top(); if ((bound->has_lower() || bound->has_upper
()) && (bound->lower_instr() != phi || bound->upper_instr
() != phi || bound->lower() != 0 || bound->upper() != 0
)) { if (TraceRangeCheckElimination) { tty->fill_to(2*block
->dominator_depth()); tty->print("i%d", phi->id()); tty
->print(": "); bound->print(); tty->cr();; }; } }; }
} } { int temp__1060 = cur_state->locals_size(); for (cur_index
= 0; cur_index < temp__1060 && (value = cur_state
->local_at(cur_index), true); cur_index += (value == __null
|| value->type()->is_illegal() ? 1 : value->type()->
size())) if (value != __null) { Phi* phi = value->as_Phi()
; if (phi != __null && phi->block() == cur_block) {
BoundStack *bound_stack = _bounds.at(phi->id()); if (bound_stack
&& bound_stack->length() > 0) { Bound *bound =
bound_stack->top(); if ((bound->has_lower() || bound->
has_upper()) && (bound->lower_instr() != phi || bound
->upper_instr() != phi || bound->lower() != 0 || bound->
upper() != 0)) { if (TraceRangeCheckElimination) { tty->fill_to
(2*block->dominator_depth()); tty->print("i%d", phi->
id()); tty->print(": "); bound->print(); tty->cr();;
}; } }; } } } }
1059 }{ int cur_index; ValueStack* cur_state = cur_block->state(
); Value value; { int temp__1060 = cur_state->stack_size()
; for (cur_index = 0; cur_index < temp__1060 && (value
= cur_state->stack_at(cur_index), true); cur_index += value
->type()->size()) { Phi* phi = value->as_Phi(); if (
phi != __null && phi->block() == cur_block) { BoundStack
*bound_stack = _bounds.at(phi->id()); if (bound_stack &&
bound_stack->length() > 0) { Bound *bound = bound_stack
->top(); if ((bound->has_lower() || bound->has_upper
()) && (bound->lower_instr() != phi || bound->upper_instr
() != phi || bound->lower() != 0 || bound->upper() != 0
)) { if (TraceRangeCheckElimination) { tty->fill_to(2*block
->dominator_depth()); tty->print("i%d", phi->id()); tty
->print(": "); bound->print(); tty->cr();; }; } }; }
} } { int temp__1060 = cur_state->locals_size(); for (cur_index
= 0; cur_index < temp__1060 && (value = cur_state
->local_at(cur_index), true); cur_index += (value == __null
|| value->type()->is_illegal() ? 1 : value->type()->
size())) if (value != __null) { Phi* phi = value->as_Phi()
; if (phi != __null && phi->block() == cur_block) {
BoundStack *bound_stack = _bounds.at(phi->id()); if (bound_stack
&& bound_stack->length() > 0) { Bound *bound =
bound_stack->top(); if ((bound->has_lower() || bound->
has_upper()) && (bound->lower_instr() != phi || bound
->upper_instr() != phi || bound->lower() != 0 || bound->
upper() != 0)) { if (TraceRangeCheckElimination) { tty->fill_to
(2*block->dominator_depth()); tty->print("i%d", phi->
id()); tty->print(": "); bound->print(); tty->cr();;
}; } }; } } } }
1060 }){ int cur_index; ValueStack* cur_state = cur_block->state(
); Value value; { int temp__1060 = cur_state->stack_size()
; for (cur_index = 0; cur_index < temp__1060 && (value
= cur_state->stack_at(cur_index), true); cur_index += value
->type()->size()) { Phi* phi = value->as_Phi(); if (
phi != __null && phi->block() == cur_block) { BoundStack
*bound_stack = _bounds.at(phi->id()); if (bound_stack &&
bound_stack->length() > 0) { Bound *bound = bound_stack
->top(); if ((bound->has_lower() || bound->has_upper
()) && (bound->lower_instr() != phi || bound->upper_instr
() != phi || bound->lower() != 0 || bound->upper() != 0
)) { if (TraceRangeCheckElimination) { tty->fill_to(2*block
->dominator_depth()); tty->print("i%d", phi->id()); tty
->print(": "); bound->print(); tty->cr();; }; } }; }
} } { int temp__1060 = cur_state->locals_size(); for (cur_index
= 0; cur_index < temp__1060 && (value = cur_state
->local_at(cur_index), true); cur_index += (value == __null
|| value->type()->is_illegal() ? 1 : value->type()->
size())) if (value != __null) { Phi* phi = value->as_Phi()
; if (phi != __null && phi->block() == cur_block) {
BoundStack *bound_stack = _bounds.at(phi->id()); if (bound_stack
&& bound_stack->length() > 0) { Bound *bound =
bound_stack->top(); if ((bound->has_lower() || bound->
has_upper()) && (bound->lower_instr() != phi || bound
->upper_instr() != phi || bound->lower() != 0 || bound->
upper() != 0)) { if (TraceRangeCheckElimination) { tty->fill_to
(2*block->dominator_depth()); tty->print("i%d", phi->
id()); tty->print(": "); bound->print(); tty->cr();;
}; } }; } } } }
;
1061
1062 while (!instr->as_BlockEnd()) {
1063 if (instr->id() < _bounds.length()) {
1064 BoundStack *bound_stack = _bounds.at(instr->id());
1065 if (bound_stack && bound_stack->length() > 0) {
1066 Bound *bound = bound_stack->top();
1067 if ((bound->has_lower() || bound->has_upper()) && (bound->lower_instr() != instr || bound->upper_instr() != instr || bound->lower() != 0 || bound->upper() != 0)) {
1068 TRACE_RANGE_CHECK_ELIMINATION(tty->fill_to(2*block->dominator_depth());if (TraceRangeCheckElimination) { tty->fill_to(2*block->
dominator_depth()); tty->print("i%d", instr->id()); tty
->print(": "); bound->print(); tty->cr();; }
1069 tty->print("i%d", instr->id());if (TraceRangeCheckElimination) { tty->fill_to(2*block->
dominator_depth()); tty->print("i%d", instr->id()); tty
->print(": "); bound->print(); tty->cr();; }
1070 tty->print(": ");if (TraceRangeCheckElimination) { tty->fill_to(2*block->
dominator_depth()); tty->print("i%d", instr->id()); tty
->print(": "); bound->print(); tty->cr();; }
1071 bound->print();if (TraceRangeCheckElimination) { tty->fill_to(2*block->
dominator_depth()); tty->print("i%d", instr->id()); tty
->print(": "); bound->print(); tty->cr();; }
1072 tty->cr();if (TraceRangeCheckElimination) { tty->fill_to(2*block->
dominator_depth()); tty->print("i%d", instr->id()); tty
->print(": "); bound->print(); tty->cr();; }
1073 )if (TraceRangeCheckElimination) { tty->fill_to(2*block->
dominator_depth()); tty->print("i%d", instr->id()); tty
->print(": "); bound->print(); tty->cr();; }
;
1074 }
1075 }
1076 }
1077 instr = instr->next();
1078 }
1079 }
1080}
1081#endif
1082
1083#ifdef ASSERT1
1084// Verification or the IR
1085RangeCheckEliminator::Verification::Verification(IR *ir) : _used(BlockBegin::number_of_blocks(), BlockBegin::number_of_blocks(), false) {
1086 this->_ir = ir;
1087 ir->iterate_linear_scan_order(this);
1088}
1089
1090// Verify this block
1091void RangeCheckEliminator::Verification::block_do(BlockBegin *block) {
1092 If *cond = block->end()->as_If();
1093 // Watch out: tsux and fsux can be the same!
1094 if (block->number_of_sux() > 1) {
1095 for (int i=0; i<block->number_of_sux(); i++) {
1096 BlockBegin *sux = block->sux_at(i);
1097 BlockBegin *pred = NULL__null;
1098 for (int j=0; j<sux->number_of_preds(); j++) {
1099 BlockBegin *cur = sux->pred_at(j);
1100 assert(cur != NULL, "Predecessor must not be null")do { if (!(cur != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1100, "assert(" "cur != __null" ") failed", "Predecessor must not be null"
); ::breakpoint(); } } while (0)
;
1101 if (!pred) {
1102 pred = cur;
1103 }
1104 assert(cur == pred, "Block must not have more than one predecessor if its predecessor has more than one successor")do { if (!(cur == pred)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1104, "assert(" "cur == pred" ") failed", "Block must not have more than one predecessor if its predecessor has more than one successor"
); ::breakpoint(); } } while (0)
;
1105 }
1106 assert(sux->number_of_preds() >= 1, "Block must have at least one predecessor")do { if (!(sux->number_of_preds() >= 1)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1106, "assert(" "sux->number_of_preds() >= 1" ") failed"
, "Block must have at least one predecessor"); ::breakpoint()
; } } while (0)
;
1107 assert(sux->pred_at(0) == block, "Wrong successor")do { if (!(sux->pred_at(0) == block)) { (*g_assert_poison)
= 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1107, "assert(" "sux->pred_at(0) == block" ") failed", "Wrong successor"
); ::breakpoint(); } } while (0)
;
1108 }
1109 }
1110
1111 BlockBegin *dominator = block->dominator();
1112 if (dominator) {
1113 assert(block != _ir->start(), "Start block must not have a dominator!")do { if (!(block != _ir->start())) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1113, "assert(" "block != _ir->start()" ") failed", "Start block must not have a dominator!"
); ::breakpoint(); } } while (0)
;
1114 assert(can_reach(dominator, block), "Dominator can't reach his block !")do { if (!(can_reach(dominator, block))) { (*g_assert_poison)
= 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1114, "assert(" "can_reach(dominator, block)" ") failed", "Dominator can't reach his block !"
); ::breakpoint(); } } while (0)
;
1115 assert(can_reach(_ir->start(), dominator), "Dominator is unreachable !")do { if (!(can_reach(_ir->start(), dominator))) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1115, "assert(" "can_reach(_ir->start(), dominator)" ") failed"
, "Dominator is unreachable !"); ::breakpoint(); } } while (0
)
;
1116 assert(!can_reach(_ir->start(), block, dominator), "Wrong dominator ! Block can be reached anyway !")do { if (!(!can_reach(_ir->start(), block, dominator))) { (
*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1116, "assert(" "!can_reach(_ir->start(), block, dominator)"
") failed", "Wrong dominator ! Block can be reached anyway !"
); ::breakpoint(); } } while (0)
;
1117 BlockList *all_blocks = _ir->linear_scan_order();
1118 for (int i=0; i<all_blocks->length(); i++) {
1119 BlockBegin *cur = all_blocks->at(i);
1120 if (cur != dominator && cur != block) {
1121 assert(can_reach(dominator, block, cur), "There has to be another dominator!")do { if (!(can_reach(dominator, block, cur))) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1121, "assert(" "can_reach(dominator, block, cur)" ") failed"
, "There has to be another dominator!"); ::breakpoint(); } } while
(0)
;
1122 }
1123 }
1124 } else {
1125 assert(block == _ir->start(), "Only start block must not have a dominator")do { if (!(block == _ir->start())) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1125, "assert(" "block == _ir->start()" ") failed", "Only start block must not have a dominator"
); ::breakpoint(); } } while (0)
;
1126 }
1127
1128 if (block->is_set(BlockBegin::linear_scan_loop_header_flag)) {
1129 int loop_index = block->loop_index();
1130 BlockList *all_blocks = _ir->linear_scan_order();
1131 assert(block->number_of_preds() >= 1, "Block must have at least one predecessor")do { if (!(block->number_of_preds() >= 1)) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1131, "assert(" "block->number_of_preds() >= 1" ") failed"
, "Block must have at least one predecessor"); ::breakpoint()
; } } while (0)
;
1132 assert(!block->is_set(BlockBegin::exception_entry_flag), "Loop header must not be exception handler!")do { if (!(!block->is_set(BlockBegin::exception_entry_flag
))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1132, "assert(" "!block->is_set(BlockBegin::exception_entry_flag)"
") failed", "Loop header must not be exception handler!"); ::
breakpoint(); } } while (0)
;
1133
1134 bool loop_through_xhandler = false;
1135 for (int i=0; i<block->number_of_sux(); i++) {
1136 BlockBegin *sux = block->sux_at(i);
1137 if (!loop_through_xhandler) {
1138 if (sux->loop_depth() == block->loop_depth() && sux->loop_index() != block->loop_index()) {
1139 loop_through_xhandler = is_backbranch_from_xhandler(block);
1140 assert(loop_through_xhandler, "Loop indices have to be the same if same depths but no backbranch from xhandler")do { if (!(loop_through_xhandler)) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1140, "assert(" "loop_through_xhandler" ") failed", "Loop indices have to be the same if same depths but no backbranch from xhandler"
); ::breakpoint(); } } while (0)
;
1141 }
1142 }
1143 assert(sux->loop_depth() == block->loop_depth() || sux->loop_index() != block->loop_index(), "Loop index has to be different")do { if (!(sux->loop_depth() == block->loop_depth() || sux
->loop_index() != block->loop_index())) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1143, "assert(" "sux->loop_depth() == block->loop_depth() || sux->loop_index() != block->loop_index()"
") failed", "Loop index has to be different"); ::breakpoint(
); } } while (0)
;
1144 }
1145
1146 for (int i=0; i<all_blocks->length(); i++) {
1147 BlockBegin *cur = all_blocks->at(i);
1148 if (cur->loop_index() == loop_index && cur != block) {
1149 assert(dominates(block->dominator(), cur), "Dominator of loop header must dominate all loop blocks")do { if (!(dominates(block->dominator(), cur))) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1149, "assert(" "dominates(block->dominator(), cur)" ") failed"
, "Dominator of loop header must dominate all loop blocks"); ::
breakpoint(); } } while (0)
;
1150 }
1151 }
1152 }
1153
1154 Instruction *cur = block;
1155 while (cur) {
1156 assert(cur->block() == block, "Block begin has to be set correctly!")do { if (!(cur->block() == block)) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1156, "assert(" "cur->block() == block" ") failed", "Block begin has to be set correctly!"
); ::breakpoint(); } } while (0)
;
1157 cur = cur->next();
1158 }
1159}
1160
1161// Called when a successor of a block has the same loop depth but a different loop index. This can happen if a backbranch comes from
1162// an exception handler of a loop head block, for example, when a loop is only executed once on the non-exceptional path but is
1163// repeated in case of an exception. In this case, the edge block->sux is not critical and was not split before.
1164// Check if there is such a backbranch from an xhandler of 'block'.
1165bool RangeCheckEliminator::Verification::is_backbranch_from_xhandler(BlockBegin* block) {
1166 for (int i = 0; i < block->number_of_exception_handlers(); i++) {
1167 BlockBegin *xhandler = block->exception_handler_at(i);
1168 for (int j = 0; j < block->number_of_preds(); j++) {
1169 if (dominates(xhandler, block->pred_at(j)) || xhandler == block->pred_at(j)) {
1170 return true;
1171 }
1172 }
1173 }
1174
1175 // In case of nested xhandlers, we need to walk through the loop (and all blocks belonging to exception handlers)
1176 // to find an xhandler of 'block'.
1177 if (block->number_of_exception_handlers() > 0) {
1178 for (int i = 0; i < block->number_of_preds(); i++) {
1179 BlockBegin* pred = block->pred_at(i);
1180 if (pred->loop_index() == block->loop_index()) {
1181 // Only check blocks that belong to the loop
1182 // Do a BFS to find an xhandler block of 'block' starting from 'pred'
1183 ResourceMark rm;
1184 ResourceBitMap visited(BlockBegin::number_of_blocks());
1185 BlockBeginList list;
1186 list.push(pred);
1187 while (!list.is_empty()) {
1188 BlockBegin* next = list.pop();
1189 if (!visited.at(next->block_id())) {
1190 visited.set_bit(next->block_id());
1191 for (int j = 0; j < block->number_of_exception_handlers(); j++) {
1192 if (next == block->exception_handler_at(j)) {
1193 return true;
1194 }
1195 }
1196 for (int j = 0; j < next->number_of_preds(); j++) {
1197 if (next->pred_at(j) != block) {
1198 list.push(next->pred_at(j));
1199 }
1200 }
1201 }
1202 }
1203 }
1204 }
1205 }
1206 return false;
1207}
1208
1209// Loop header must dominate all loop blocks
1210bool RangeCheckEliminator::Verification::dominates(BlockBegin *dominator, BlockBegin *block) {
1211 BlockBegin *cur = block->dominator();
1212 while (cur && cur != dominator) {
1213 cur = cur->dominator();
1214 }
1215 return cur == dominator;
1216}
1217
1218// Try to reach Block end beginning in Block start and not using Block dont_use
1219bool RangeCheckEliminator::Verification::can_reach(BlockBegin *start, BlockBegin *end, BlockBegin *dont_use /* = NULL */) {
1220 if (start == end) return start != dont_use;
1221 // Simple BSF from start to end
1222 // BlockBeginList _current;
1223 for (int i=0; i < _used.length(); i++) {
1224 _used.at_put(i, false);
1225 }
1226 _current.trunc_to(0);
1227 _successors.trunc_to(0);
1228 if (start != dont_use) {
1229 _current.push(start);
1230 _used.at_put(start->block_id(), true);
1231 }
1232
1233 // BlockBeginList _successors;
1234 while (_current.length() > 0) {
1235 BlockBegin *cur = _current.pop();
1236 // Add exception handlers to list
1237 for (int i=0; i<cur->number_of_exception_handlers(); i++) {
1238 BlockBegin *xhandler = cur->exception_handler_at(i);
1239 _successors.push(xhandler);
1240 // Add exception handlers of _successors to list
1241 for (int j=0; j<xhandler->number_of_exception_handlers(); j++) {
1242 BlockBegin *sux_xhandler = xhandler->exception_handler_at(j);
1243 _successors.push(sux_xhandler);
1244 }
1245 }
1246 // Add normal _successors to list
1247 for (int i=0; i<cur->number_of_sux(); i++) {
1248 BlockBegin *sux = cur->sux_at(i);
1249 _successors.push(sux);
1250 // Add exception handlers of _successors to list
1251 for (int j=0; j<sux->number_of_exception_handlers(); j++) {
1252 BlockBegin *xhandler = sux->exception_handler_at(j);
1253 _successors.push(xhandler);
1254 }
1255 }
1256 for (int i=0; i<_successors.length(); i++) {
1257 BlockBegin *sux = _successors.at(i);
1258 assert(sux != NULL, "Successor must not be NULL!")do { if (!(sux != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1258, "assert(" "sux != __null" ") failed", "Successor must not be NULL!"
); ::breakpoint(); } } while (0)
;
1259 if (sux == end) {
1260 return true;
1261 }
1262 if (sux != dont_use && !_used.at(sux->block_id())) {
1263 _used.at_put(sux->block_id(), true);
1264 _current.push(sux);
1265 }
1266 }
1267 _successors.trunc_to(0);
1268 }
1269
1270 return false;
1271}
1272#endif // ASSERT
1273
1274// Bound
1275RangeCheckEliminator::Bound::~Bound() {
1276}
1277
1278// Bound constructor
1279RangeCheckEliminator::Bound::Bound() {
1280 this->_lower = min_jint;
1281 this->_upper = max_jint;
1282 this->_lower_instr = NULL__null;
1283 this->_upper_instr = NULL__null;
1284}
1285
1286// Bound constructor
1287RangeCheckEliminator::Bound::Bound(int lower, Value lower_instr, int upper, Value upper_instr) {
1288 assert(!lower_instr || !lower_instr->as_Constant() || !lower_instr->type()->as_IntConstant(), "Must not be constant!")do { if (!(!lower_instr || !lower_instr->as_Constant() || !
lower_instr->type()->as_IntConstant())) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1288, "assert(" "!lower_instr || !lower_instr->as_Constant() || !lower_instr->type()->as_IntConstant()"
") failed", "Must not be constant!"); ::breakpoint(); } } while
(0)
;
1289 assert(!upper_instr || !upper_instr->as_Constant() || !upper_instr->type()->as_IntConstant(), "Must not be constant!")do { if (!(!upper_instr || !upper_instr->as_Constant() || !
upper_instr->type()->as_IntConstant())) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1289, "assert(" "!upper_instr || !upper_instr->as_Constant() || !upper_instr->type()->as_IntConstant()"
") failed", "Must not be constant!"); ::breakpoint(); } } while
(0)
;
1290 this->_lower = lower;
1291 this->_upper = upper;
1292 this->_lower_instr = lower_instr;
1293 this->_upper_instr = upper_instr;
1294}
1295
1296// Bound constructor
1297RangeCheckEliminator::Bound::Bound(Instruction::Condition cond, Value v, int constant) {
1298 assert(!v || (v->type() && (v->type()->as_IntType() || v->type()->as_ObjectType())), "Type must be array or integer!")do { if (!(!v || (v->type() && (v->type()->as_IntType
() || v->type()->as_ObjectType())))) { (*g_assert_poison
) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1298, "assert(" "!v || (v->type() && (v->type()->as_IntType() || v->type()->as_ObjectType()))"
") failed", "Type must be array or integer!"); ::breakpoint(
); } } while (0)
;
1299 assert(!v || !v->as_Constant() || !v->type()->as_IntConstant(), "Must not be constant!")do { if (!(!v || !v->as_Constant() || !v->type()->as_IntConstant
())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1299, "assert(" "!v || !v->as_Constant() || !v->type()->as_IntConstant()"
") failed", "Must not be constant!"); ::breakpoint(); } } while
(0)
;
1300
1301 if (cond == Instruction::eql) {
1302 _lower = constant;
1303 _lower_instr = v;
1304 _upper = constant;
1305 _upper_instr = v;
1306 } else if (cond == Instruction::neq) {
1307 _lower = min_jint;
1308 _upper = max_jint;
1309 _lower_instr = NULL__null;
1310 _upper_instr = NULL__null;
1311 if (v == NULL__null) {
1312 if (constant == min_jint) {
1313 _lower++;
1314 }
1315 if (constant == max_jint) {
1316 _upper--;
1317 }
1318 }
1319 } else if (cond == Instruction::geq) {
1320 _lower = constant;
1321 _lower_instr = v;
1322 _upper = max_jint;
1323 _upper_instr = NULL__null;
1324 } else if (cond == Instruction::leq) {
1325 _lower = min_jint;
1326 _lower_instr = NULL__null;
1327 _upper = constant;
1328 _upper_instr = v;
1329 } else {
1330 ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here(
"/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1330); ::breakpoint(); } while (0)
;
1331 }
1332}
1333
1334// Set lower
1335void RangeCheckEliminator::Bound::set_lower(int value, Value v) {
1336 assert(!v || !v->as_Constant() || !v->type()->as_IntConstant(), "Must not be constant!")do { if (!(!v || !v->as_Constant() || !v->type()->as_IntConstant
())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1336, "assert(" "!v || !v->as_Constant() || !v->type()->as_IntConstant()"
") failed", "Must not be constant!"); ::breakpoint(); } } while
(0)
;
1337 this->_lower = value;
1338 this->_lower_instr = v;
1339}
1340
1341// Set upper
1342void RangeCheckEliminator::Bound::set_upper(int value, Value v) {
1343 assert(!v || !v->as_Constant() || !v->type()->as_IntConstant(), "Must not be constant!")do { if (!(!v || !v->as_Constant() || !v->type()->as_IntConstant
())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1343, "assert(" "!v || !v->as_Constant() || !v->type()->as_IntConstant()"
") failed", "Must not be constant!"); ::breakpoint(); } } while
(0)
;
1344 this->_upper = value;
1345 this->_upper_instr = v;
1346}
1347
1348// Add constant -> no overflow may occur
1349void RangeCheckEliminator::Bound::add_constant(int value) {
1350 this->_lower += value;
1351 this->_upper += value;
1352}
1353
1354// or
1355void RangeCheckEliminator::Bound::or_op(Bound *b) {
1356 // Watch out, bound is not guaranteed not to overflow!
1357 // Update lower bound
1358 if (_lower_instr != b->_lower_instr || (_lower_instr && _lower != b->_lower)) {
1359 _lower_instr = NULL__null;
1360 _lower = min_jint;
1361 } else {
1362 _lower = MIN2(_lower, b->_lower);
1363 }
1364 // Update upper bound
1365 if (_upper_instr != b->_upper_instr || (_upper_instr && _upper != b->_upper)) {
1366 _upper_instr = NULL__null;
1367 _upper = max_jint;
1368 } else {
1369 _upper = MAX2(_upper, b->_upper);
1370 }
1371}
1372
1373// and
1374void RangeCheckEliminator::Bound::and_op(Bound *b) {
1375 // Update lower bound
1376 if (_lower_instr == b->_lower_instr) {
1377 _lower = MAX2(_lower, b->_lower);
1378 }
1379 if (b->has_lower()) {
1380 bool set = true;
1381 if (_lower_instr != NULL__null && b->_lower_instr != NULL__null) {
1382 set = (_lower_instr->dominator_depth() > b->_lower_instr->dominator_depth());
1383 }
1384 if (set) {
1385 _lower = b->_lower;
1386 _lower_instr = b->_lower_instr;
1387 }
1388 }
1389 // Update upper bound
1390 if (_upper_instr == b->_upper_instr) {
1391 _upper = MIN2(_upper, b->_upper);
1392 }
1393 if (b->has_upper()) {
1394 bool set = true;
1395 if (_upper_instr != NULL__null && b->_upper_instr != NULL__null) {
1396 set = (_upper_instr->dominator_depth() > b->_upper_instr->dominator_depth());
1397 }
1398 if (set) {
1399 _upper = b->_upper;
1400 _upper_instr = b->_upper_instr;
1401 }
1402 }
1403}
1404
1405// has_upper
1406bool RangeCheckEliminator::Bound::has_upper() {
1407 return _upper_instr != NULL__null || _upper < max_jint;
1408}
1409
1410// is_smaller
1411bool RangeCheckEliminator::Bound::is_smaller(Bound *b) {
1412 if (b->_lower_instr != _upper_instr) {
1413 return false;
1414 }
1415 return _upper < b->_lower;
1416}
1417
1418// has_lower
1419bool RangeCheckEliminator::Bound::has_lower() {
1420 return _lower_instr != NULL__null || _lower > min_jint;
1421}
1422
1423// in_array_bound
1424bool RangeCheckEliminator::in_array_bound(Bound *bound, Value array){
1425 if (!bound) return false;
1426 assert(array != NULL, "Must not be null!")do { if (!(array != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1426, "assert(" "array != __null" ") failed", "Must not be null!"
); ::breakpoint(); } } while (0)
;
1427 assert(bound != NULL, "Must not be null!")do { if (!(bound != __null)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1427, "assert(" "bound != __null" ") failed", "Must not be null!"
); ::breakpoint(); } } while (0)
;
1428 if (bound->lower() >=0 && bound->lower_instr() == NULL__null && bound->upper() < 0 && bound->upper_instr() != NULL__null) {
1429 ArrayLength *len = bound->upper_instr()->as_ArrayLength();
1430 if (bound->upper_instr() == array || (len != NULL__null && len->array() == array)) {
1431 return true;
1432 }
1433 }
1434 return false;
1435}
1436
1437// remove_lower
1438void RangeCheckEliminator::Bound::remove_lower() {
1439 _lower = min_jint;
1440 _lower_instr = NULL__null;
1441}
1442
1443// remove_upper
1444void RangeCheckEliminator::Bound::remove_upper() {
1445 _upper = max_jint;
1446 _upper_instr = NULL__null;
1447}
1448
1449// upper
1450int RangeCheckEliminator::Bound::upper() {
1451 return _upper;
1452}
1453
1454// lower
1455int RangeCheckEliminator::Bound::lower() {
1456 return _lower;
1457}
1458
1459// upper_instr
1460Value RangeCheckEliminator::Bound::upper_instr() {
1461 return _upper_instr;
1462}
1463
1464// lower_instr
1465Value RangeCheckEliminator::Bound::lower_instr() {
1466 return _lower_instr;
1467}
1468
1469// print
1470void RangeCheckEliminator::Bound::print() {
1471 tty->print("%s", "");
1472 if (this->_lower_instr || this->_lower != min_jint) {
1473 if (this->_lower_instr) {
1474 tty->print("i%d", this->_lower_instr->id());
1475 if (this->_lower > 0) {
1476 tty->print("+%d", _lower);
1477 }
1478 if (this->_lower < 0) {
1479 tty->print("%d", _lower);
1480 }
1481 } else {
1482 tty->print("%d", _lower);
1483 }
1484 tty->print(" <= ");
1485 }
1486 tty->print("x");
1487 if (this->_upper_instr || this->_upper != max_jint) {
1488 tty->print(" <= ");
1489 if (this->_upper_instr) {
1490 tty->print("i%d", this->_upper_instr->id());
1491 if (this->_upper > 0) {
1492 tty->print("+%d", _upper);
1493 }
1494 if (this->_upper < 0) {
1495 tty->print("%d", _upper);
1496 }
1497 } else {
1498 tty->print("%d", _upper);
1499 }
1500 }
1501}
1502
1503// Copy
1504RangeCheckEliminator::Bound *RangeCheckEliminator::Bound::copy() {
1505 Bound *b = new Bound();
1506 b->_lower = _lower;
1507 b->_lower_instr = _lower_instr;
1508 b->_upper = _upper;
1509 b->_upper_instr = _upper_instr;
1510 return b;
1511}
1512
1513#ifdef ASSERT1
1514// Add assertion
1515void RangeCheckEliminator::Bound::add_assertion(Instruction *instruction, Instruction *position, int i, Value instr, Instruction::Condition cond) {
1516 Instruction *result = position;
1517 Instruction *compare_with = NULL__null;
1518 ValueStack *state = position->state_before();
1519 if (position->as_BlockEnd() && !position->as_Goto()) {
1520 state = position->as_BlockEnd()->state_before();
1521 }
1522 Instruction *instruction_before = position->prev();
1523 if (position->as_Return() && Compilation::current()->method()->is_synchronized() && instruction_before->as_MonitorExit()) {
1524 instruction_before = instruction_before->prev();
1525 }
1526 result = instruction_before;
1527 // Load constant only if needed
1528 Constant *constant = NULL__null;
1529 if (i != 0 || !instr) {
1530 constant = new Constant(new IntConstant(i));
1531 NOT_PRODUCT(constant->set_printable_bci(position->printable_bci()))constant->set_printable_bci(position->printable_bci());
1532 result = result->insert_after(constant);
1533 compare_with = constant;
1534 }
1535
1536 if (instr) {
1537 assert(instr->type()->as_ObjectType() || instr->type()->as_IntType(), "Type must be array or integer!")do { if (!(instr->type()->as_ObjectType() || instr->
type()->as_IntType())) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1537, "assert(" "instr->type()->as_ObjectType() || instr->type()->as_IntType()"
") failed", "Type must be array or integer!"); ::breakpoint(
); } } while (0)
;
1538 compare_with = instr;
1539 // Load array length if necessary
1540 Instruction *op = instr;
1541 if (instr->type()->as_ObjectType()) {
1542 assert(state, "must not be null")do { if (!(state)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1542, "assert(" "state" ") failed", "must not be null"); ::
breakpoint(); } } while (0)
;
1543 ArrayLength *length = new ArrayLength(instr, state->copy());
1544 NOT_PRODUCT(length->set_printable_bci(position->printable_bci()))length->set_printable_bci(position->printable_bci());
1545 length->set_exception_state(length->state_before());
1546 result = result->insert_after(length);
1547 op = length;
1548 compare_with = length;
1549 }
1550 // Add operation only if necessary
1551 if (constant) {
1552 ArithmeticOp *ao = new ArithmeticOp(Bytecodes::_iadd, constant, op, NULL__null);
1553 NOT_PRODUCT(ao->set_printable_bci(position->printable_bci()))ao->set_printable_bci(position->printable_bci());
1554 result = result->insert_after(ao);
1555 compare_with = ao;
1556 // TODO: Check that add operation does not overflow!
1557 }
1558 }
1559 assert(compare_with != NULL, "You have to compare with something!")do { if (!(compare_with != __null)) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1559, "assert(" "compare_with != __null" ") failed", "You have to compare with something!"
); ::breakpoint(); } } while (0)
;
1560 assert(instruction != NULL, "Instruction must not be null!")do { if (!(instruction != __null)) { (*g_assert_poison) = 'X'
;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1560, "assert(" "instruction != __null" ") failed", "Instruction must not be null!"
); ::breakpoint(); } } while (0)
;
1561
1562 if (instruction->type()->as_ObjectType()) {
1563 // Load array length if necessary
1564 Instruction *op = instruction;
1565 assert(state, "must not be null")do { if (!(state)) { (*g_assert_poison) = 'X';; report_vm_error
("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_RangeCheckElimination.cpp"
, 1565, "assert(" "state" ") failed", "must not be null"); ::
breakpoint(); } } while (0)
;
1566 ArrayLength *length = new ArrayLength(instruction, state->copy());
1567 length->set_exception_state(length->state_before());
1568 NOT_PRODUCT(length->set_printable_bci(position->printable_bci()))length->set_printable_bci(position->printable_bci());
1569 result = result->insert_after(length);
1570 instruction = length;
1571 }
1572
1573 Assert *assert = new Assert(instruction, cond, false, compare_with);
1574 NOT_PRODUCT(assert->set_printable_bci(position->printable_bci()))assert->set_printable_bci(position->printable_bci());
1575 result->insert_after(assert);
1576}
1577
1578// Add assertions
1579void RangeCheckEliminator::add_assertions(Bound *bound, Instruction *instruction, Instruction *position) {
1580 // Add lower bound assertion
1581 if (bound->has_lower()) {
1582 bound->add_assertion(instruction, position, bound->lower(), bound->lower_instr(), Instruction::geq);
1583 }
1584 // Add upper bound assertion
1585 if (bound->has_upper()) {
1586 bound->add_assertion(instruction, position, bound->upper(), bound->upper_instr(), Instruction::leq);
1587 }
1588}
1589#endif