annotate src/share/vm/c1/c1_RangeCheckElimination.cpp @ 8860:46f6f063b272

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