annotate src/share/vm/c1/c1_RangeCheckElimination.cpp @ 17467:55fb97c4c58d hs25-b65

8029233: Update copyright year to match last edit in jdk8 hotspot repository for 2013 Summary: Copyright year updated for files modified during 2013 Reviewed-by: twisti, iveresov
author mikael
date Tue, 24 Dec 2013 11:48:39 -0800
parents 6a3629cf7075
children 4ca6dc0799b6 78bbf4d43a14
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 /*
17467
55fb97c4c58d 8029233: Update copyright year to match last edit in jdk8 hotspot repository for 2013
mikael
parents: 10140
diff changeset
2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
8860
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) {
10140
6a3629cf7075 8011771: runThese crashed with EAV
roland
parents: 8869
diff changeset
462 for (int i = 0; i < indices.length(); i++) {
8860
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 }
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 if (list_constant.length() > 1) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
537 AccessIndexed *first = list_constant.at(0);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
538 Instruction *insert_position = first->prev();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
539 ValueStack *state = first->state_before();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
540 // Load max Constant
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
541 Constant *constant = new Constant(new IntConstant(max_constant));
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
542 NOT_PRODUCT(constant->set_printable_bci(first->printable_bci()));
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
543 insert_position = insert_position->insert_after(constant);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
544 Instruction *compare_instr = constant;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
545 Value length_instr = first->length();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
546 if (!length_instr) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
547 ArrayLength *length = new ArrayLength(array, state->copy());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
548 length->set_exception_state(length->state_before());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
549 length->set_flag(Instruction::DeoptimizeOnException, true);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
550 insert_position = insert_position->insert_after_same_bci(length);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
551 length_instr = length;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
552 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
553 // Compare for greater or equal to array length
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
554 insert_position = predicate(compare_instr, Instruction::geq, length_instr, state, insert_position);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
555 for (int j = 0; j<list_constant.length(); j++) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
556 AccessIndexed *ai = list_constant.at(j);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
557 remove_range_check(ai);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
558 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
559 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
560 }
10140
6a3629cf7075 8011771: runThese crashed with EAV
roland
parents: 8869
diff changeset
561
6a3629cf7075 8011771: runThese crashed with EAV
roland
parents: 8869
diff changeset
562 // Clear data structures for next array
6a3629cf7075 8011771: runThese crashed with EAV
roland
parents: 8869
diff changeset
563 for (int i = 0; i < indices.length(); i++) {
6a3629cf7075 8011771: runThese crashed with EAV
roland
parents: 8869
diff changeset
564 Instruction *index_instruction = indices.at(i);
6a3629cf7075 8011771: runThese crashed with EAV
roland
parents: 8869
diff changeset
565 _access_indexed_info[index_instruction->id()] = NULL;
6a3629cf7075 8011771: runThese crashed with EAV
roland
parents: 8869
diff changeset
566 }
6a3629cf7075 8011771: runThese crashed with EAV
roland
parents: 8869
diff changeset
567 indices.clear();
8860
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
568 }
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
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
571 bool RangeCheckEliminator::set_process_block_flags(BlockBegin *block) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
572 Instruction *cur = block;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
573 bool process = false;
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 while (cur) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
576 process |= (cur->as_AccessIndexed() != NULL);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
577 cur = cur->next();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
578 }
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 BlockList *dominates = block->dominates();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
581 for (int i=0; i<dominates->length(); i++) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
582 BlockBegin *next = dominates->at(i);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
583 process |= set_process_block_flags(next);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
584 }
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 if (!process) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
587 block->set(BlockBegin::donot_eliminate_range_checks);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
588 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
589 return process;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
590 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
591
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
592 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
593 bool upper_check = true;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
594 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
595 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
596 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
597 assert(array_instr, "Array instruction must exist");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
598 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
599 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
600
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
601 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
602 // static check
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
603 if (upper >= 0) return false; // would always trigger a deopt:
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
604 // array_length + x >= array_length, x >= 0 is always true
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
605 upper_check = false;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
606 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
607 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
608 if (lower > 0) return false;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
609 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
610 // No upper check required -> skip
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
611 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
612 // upper_instr is object means that the upper bound is the length
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
613 // of the upper_instr.
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
614 return false;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
615 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
616 return true;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
617 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
618
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
619 Instruction* RangeCheckEliminator::insert_after(Instruction* insert_position, Instruction* instr, int bci) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
620 if (bci != -1) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
621 NOT_PRODUCT(instr->set_printable_bci(bci));
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
622 return insert_position->insert_after(instr);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
623 } else {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
624 return insert_position->insert_after_same_bci(instr);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
625 }
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(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
629 RangeCheckPredicate *deoptimize = new RangeCheckPredicate(left, cond, true, right, state->copy());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
630 return insert_after(insert_position, deoptimize, bci);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
631 }
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 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
634 Constant *const_instr = new Constant(new IntConstant(constant));
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
635 insert_position = insert_after(insert_position, const_instr, bci);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
636 return predicate(instr, cond, const_instr, state, insert_position);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
637 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
638
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
639 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
640 Constant *constant = new Constant(new IntConstant(left_const));
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
641 insert_position = insert_after(insert_position, constant, bci);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
642 ArithmeticOp *ao = new ArithmeticOp(Bytecodes::_iadd, constant, left, false, NULL);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
643 insert_position = insert_position->insert_after_same_bci(ao);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
644 return predicate(ao, cond, right, state, insert_position);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
645 }
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 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
648 Constant *const_instr = new Constant(new IntConstant(constant));
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
649 insert_position = insert_after(insert_position, const_instr, bci);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
650 return predicate_add(left, left_const, cond, const_instr, state, insert_position);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
651 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
652
8869
d595e8ddadd9 8010934: assert failure in c1_LinearScan.cpp: "asumption: non-Constant instructions have only virtual operands"
roland
parents: 8860
diff changeset
653 // Insert deoptimization
8860
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
654 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
655 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
656 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
657
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
658 int bci = NOT_PRODUCT(ai->printable_bci()) PRODUCT_ONLY(-1);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
659 if (lower_instr) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
660 assert(!lower_instr->type()->as_ObjectType(), "Must not be object type");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
661 if (lower == 0) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
662 // Compare for less than 0
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
663 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
664 } else if (lower > 0) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
665 // Compare for smaller 0
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
666 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
667 } else {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
668 assert(lower < 0, "");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
669 // Add 1
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
670 lower++;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
671 lower = -lower;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
672 // Compare for smaller or equal 0
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
673 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
674 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
675 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
676
8869
d595e8ddadd9 8010934: assert failure in c1_LinearScan.cpp: "asumption: non-Constant instructions have only virtual operands"
roland
parents: 8860
diff changeset
677 // No upper check required -> skip
d595e8ddadd9 8010934: assert failure in c1_LinearScan.cpp: "asumption: non-Constant instructions have only virtual operands"
roland
parents: 8860
diff changeset
678 if (!upper_check) return;
d595e8ddadd9 8010934: assert failure in c1_LinearScan.cpp: "asumption: non-Constant instructions have only virtual operands"
roland
parents: 8860
diff changeset
679
8860
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
680 // We need to know length of array
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
681 if (!length_instr) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
682 // Load length if necessary
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
683 ArrayLength *length = new ArrayLength(array_instr, state->copy());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
684 NOT_PRODUCT(length->set_printable_bci(ai->printable_bci()));
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
685 length->set_exception_state(length->state_before());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
686 length->set_flag(Instruction::DeoptimizeOnException, true);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
687 insert_position = insert_position->insert_after(length);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
688 length_instr = length;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
689 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
690
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
691 if (!upper_instr) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
692 // Compare for geq array.length
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
693 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
694 } else {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
695 if (upper_instr->type()->as_ObjectType()) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
696 assert(state, "must not be null");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
697 assert(upper_instr != array_instr, "should be");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
698 ArrayLength *length = new ArrayLength(upper_instr, state->copy());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
699 NOT_PRODUCT(length->set_printable_bci(ai->printable_bci()));
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
700 length->set_flag(Instruction::DeoptimizeOnException, true);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
701 length->set_exception_state(length->state_before());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
702 insert_position = insert_position->insert_after(length);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
703 upper_instr = length;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
704 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
705 assert(upper_instr->type()->as_IntType(), "Must not be object type!");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
706
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
707 if (upper == 0) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
708 // Compare for geq array.length
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
709 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
710 } else if (upper < 0) {
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(upper_instr, upper, Instruction::geq, length_instr, state, insert_position, bci);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
713 } else {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
714 assert(upper > 0, "");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
715 upper = -upper;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
716 // Compare for geq array.length
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
717 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
718 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
719 }
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
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
722 // Add if condition
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
723 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
724 if (y->as_Constant()) return;
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 int const_value = 0;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
727 Value instr_value = x;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
728 Constant *c = x->as_Constant();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
729 ArithmeticOp *ao = x->as_ArithmeticOp();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
730
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
731 if (c != NULL) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
732 const_value = c->type()->as_IntConstant()->value();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
733 instr_value = NULL;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
734 } 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
735 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
736 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
737 c = ao->x()->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->y();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
741 } else {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
742 c = ao->y()->as_Constant();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
743 if (c != NULL) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
744 const_value = c->type()->as_IntConstant()->value();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
745 instr_value = ao->x();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
746 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
747 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
748 if (ao->op() == Bytecodes::_isub) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
749 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
750 if (const_value > min_jint) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
751 const_value = -const_value;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
752 } else {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
753 const_value = 0;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
754 instr_value = x;
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 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
758
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
759 update_bound(pushed, y, condition, instr_value, const_value);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
760 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
761
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
762 // Process If
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
763 void RangeCheckEliminator::process_if(IntegerStack &pushed, BlockBegin *block, If *cond) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
764 // 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
765 if ((cond->tsux() == block || cond->fsux() == block) && cond->tsux() != cond->fsux()) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
766 Instruction::Condition condition = cond->cond();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
767 if (cond->fsux() == block) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
768 condition = Instruction::negate(condition);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
769 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
770 Value x = cond->x();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
771 Value y = cond->y();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
772 if (x->type()->as_IntType() && y->type()->as_IntType()) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
773 add_if_condition(pushed, y, x, condition);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
774 add_if_condition(pushed, x, y, Instruction::mirror(condition));
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
775 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
776 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
777 }
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 // Process access indexed
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
780 void RangeCheckEliminator::process_access_indexed(BlockBegin *loop_header, BlockBegin *block, AccessIndexed *ai) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
781 TRACE_RANGE_CHECK_ELIMINATION(
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
782 tty->fill_to(block->dominator_depth()*2)
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
783 );
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
784 TRACE_RANGE_CHECK_ELIMINATION(
8869
d595e8ddadd9 8010934: assert failure in c1_LinearScan.cpp: "asumption: non-Constant instructions have only virtual operands"
roland
parents: 8860
diff changeset
785 tty->print_cr("Access indexed: index=%d length=%d", ai->index()->id(), (ai->length() != NULL ? ai->length()->id() :-1 ))
8860
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
786 );
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
787
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
788 if (ai->check_flag(Instruction::NeedsRangeCheckFlag)) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
789 Bound *index_bound = get_bound(ai->index());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
790 if (!index_bound->has_lower() || !index_bound->has_upper()) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
791 TRACE_RANGE_CHECK_ELIMINATION(
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
792 tty->fill_to(block->dominator_depth()*2);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
793 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
794 );
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
795 return;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
796 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
797
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
798 Bound *array_bound;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
799 if (ai->length()) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
800 array_bound = get_bound(ai->length());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
801 } else {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
802 array_bound = get_bound(ai->array());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
803 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
804
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
805 if (in_array_bound(index_bound, ai->array()) ||
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
806 (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
807 TRACE_RANGE_CHECK_ELIMINATION(
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
808 tty->fill_to(block->dominator_depth()*2);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
809 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
810 );
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 remove_range_check(ai);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
813 } else if (_optimistic && loop_header) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
814 assert(ai->array(), "Array must not be null!");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
815 assert(ai->index(), "Index must not be null!");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
816
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
817 // Array instruction
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
818 Instruction *array_instr = ai->array();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
819 if (!loop_invariant(loop_header, array_instr)) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
820 TRACE_RANGE_CHECK_ELIMINATION(
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
821 tty->fill_to(block->dominator_depth()*2);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
822 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
823 );
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
824 return;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
825 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
826
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
827 // Lower instruction
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
828 Value index_instr = ai->index();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
829 Value lower_instr = index_bound->lower_instr();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
830 if (!loop_invariant(loop_header, lower_instr)) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
831 TRACE_RANGE_CHECK_ELIMINATION(
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
832 tty->fill_to(block->dominator_depth()*2);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
833 tty->print_cr("Lower instruction %d not loop invariant!", lower_instr->id())
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
834 );
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
835 return;
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 if (!lower_instr && index_bound->lower() < 0) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
838 TRACE_RANGE_CHECK_ELIMINATION(
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
839 tty->fill_to(block->dominator_depth()*2);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
840 tty->print_cr("Lower bound smaller than 0 (%d)!", index_bound->lower())
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
841 );
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
842 return;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
843 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
844
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
845 // Upper instruction
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
846 Value upper_instr = index_bound->upper_instr();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
847 if (!loop_invariant(loop_header, upper_instr)) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
848 TRACE_RANGE_CHECK_ELIMINATION(
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
849 tty->fill_to(block->dominator_depth()*2);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
850 tty->print_cr("Upper instruction %d not loop invariant!", upper_instr->id())
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
851 );
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
852 return;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
853 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
854
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
855 // Length instruction
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
856 Value length_instr = ai->length();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
857 if (!loop_invariant(loop_header, length_instr)) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
858 // Generate length instruction yourself!
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
859 length_instr = NULL;
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 TRACE_RANGE_CHECK_ELIMINATION(
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
863 tty->fill_to(block->dominator_depth()*2);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
864 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
865 );
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
866
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
867 BlockBegin *pred_block = loop_header->dominator();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
868 assert(pred_block != NULL, "Every loop header has a dominator!");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
869 BlockEnd *pred_block_end = pred_block->end();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
870 Instruction *insert_position = pred_block_end->prev();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
871 ValueStack *state = pred_block_end->state_before();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
872 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
873 assert(state, "State must not be null");
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 // Add deoptimization to dominator of loop header
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
876 TRACE_RANGE_CHECK_ELIMINATION(
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
877 tty->fill_to(block->dominator_depth()*2);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
878 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
879 );
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 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
882 TRACE_RANGE_CHECK_ELIMINATION(
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
883 tty->fill_to(block->dominator_depth()*2);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
884 tty->print_cr("Could not eliminate because of static analysis!")
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 return;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
887 }
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 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
890
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
891 // Finally remove the range check!
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
892 remove_range_check(ai);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
893 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
894 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
895 }
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 void RangeCheckEliminator::remove_range_check(AccessIndexed *ai) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
898 ai->set_flag(Instruction::NeedsRangeCheckFlag, false);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
899 // no range check, no need for the length instruction anymore
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
900 ai->clear_length();
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 TRACE_RANGE_CHECK_ELIMINATION(
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
903 tty->fill_to(ai->dominator_depth()*2);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
904 tty->print_cr("Range check for instruction %d eliminated!", ai->id());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
905 );
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
906
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
907 ASSERT_RANGE_CHECK_ELIMINATION(
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
908 Value array_length = ai->length();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
909 if (!array_length) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
910 array_length = ai->array();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
911 assert(array_length->type()->as_ObjectType(), "Has to be object type!");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
912 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
913 int cur_constant = -1;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
914 Value cur_value = array_length;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
915 if (cur_value->type()->as_IntConstant()) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
916 cur_constant += cur_value->type()->as_IntConstant()->value();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
917 cur_value = NULL;
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 Bound *new_index_bound = new Bound(0, NULL, cur_constant, cur_value);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
920 add_assertions(new_index_bound, ai->index(), ai);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
921 );
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
922 }
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 // 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
925 void RangeCheckEliminator::calc_bounds(BlockBegin *block, BlockBegin *loop_header) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
926 // Ensures a valid loop_header
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
927 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
928
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
929 // Tracing output
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
930 TRACE_RANGE_CHECK_ELIMINATION(
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
931 tty->fill_to(block->dominator_depth()*2);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
932 tty->print_cr("Block B%d", block->block_id());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
933 );
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
934
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
935 // Pushed stack for conditions
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
936 IntegerStack pushed;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
937 // Process If
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
938 BlockBegin *parent = block->dominator();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
939 if (parent != NULL) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
940 If *cond = parent->end()->as_If();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
941 if (cond != NULL) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
942 process_if(pushed, block, cond);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
943 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
944 }
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 // Interate over current block
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
947 InstructionList arrays;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
948 AccessIndexedList accessIndexed;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
949 Instruction *cur = block;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
950
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
951 while (cur) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
952 // Ensure cur wasn't inserted during the elimination
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
953 if (cur->id() < this->_bounds.length()) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
954 // Process only if it is an access indexed instruction
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
955 AccessIndexed *ai = cur->as_AccessIndexed();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
956 if (ai != NULL) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
957 process_access_indexed(loop_header, block, ai);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
958 accessIndexed.append(ai);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
959 if (!arrays.contains(ai->array())) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
960 arrays.append(ai->array());
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 Bound *b = get_bound(ai->index());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
963 if (!b->lower_instr()) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
964 // Lower bound is constant
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
965 update_bound(pushed, ai->index(), Instruction::geq, NULL, 0);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
966 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
967 if (!b->has_upper()) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
968 if (ai->length() && ai->length()->type()->as_IntConstant()) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
969 int value = ai->length()->type()->as_IntConstant()->value();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
970 update_bound(pushed, ai->index(), Instruction::lss, NULL, value);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
971 } else {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
972 // Has no upper bound
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
973 Instruction *instr = ai->length();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
974 if (instr != NULL) instr = ai->array();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
975 update_bound(pushed, ai->index(), Instruction::lss, instr, 0);
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 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
979 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
980 cur = cur->next();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
981 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
982
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
983 // Output current condition stack
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
984 TRACE_RANGE_CHECK_ELIMINATION(dump_condition_stack(block));
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
985
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
986 // Do in block motion of range checks
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
987 in_block_motion(block, accessIndexed, arrays);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
988
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
989 // Call all dominated blocks
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
990 for (int i=0; i<block->dominates()->length(); i++) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
991 BlockBegin *next = block->dominates()->at(i);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
992 if (!next->is_set(BlockBegin::donot_eliminate_range_checks)) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
993 // if current block is a loop header and:
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
994 // - next block belongs to the same loop
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
995 // or
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
996 // - next block belongs to an inner loop
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
997 // then current block is the loop header for next block
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
998 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
999 calc_bounds(next, block);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1000 } else {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1001 calc_bounds(next, loop_header);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1002 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1003 }
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 // Reset stack
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1007 for (int i=0; i<pushed.length(); i++) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1008 _bounds[pushed[i]]->pop();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1009 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1010 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1011
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1012 #ifndef PRODUCT
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1013 // Dump condition stack
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1014 void RangeCheckEliminator::dump_condition_stack(BlockBegin *block) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1015 for (int i=0; i<_ir->linear_scan_order()->length(); i++) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1016 BlockBegin *cur_block = _ir->linear_scan_order()->at(i);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1017 Instruction *instr = cur_block;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1018 for_each_phi_fun(cur_block, phi,
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1019 BoundStack *bound_stack = _bounds.at(phi->id());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1020 if (bound_stack && bound_stack->length() > 0) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1021 Bound *bound = bound_stack->top();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1022 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
1023 TRACE_RANGE_CHECK_ELIMINATION(tty->fill_to(2*block->dominator_depth());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1024 tty->print("i%d", phi->id());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1025 tty->print(": ");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1026 bound->print();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1027 tty->print_cr("");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1028 );
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1029 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1030 });
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1031
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1032 while (!instr->as_BlockEnd()) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1033 if (instr->id() < _bounds.length()) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1034 BoundStack *bound_stack = _bounds.at(instr->id());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1035 if (bound_stack && bound_stack->length() > 0) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1036 Bound *bound = bound_stack->top();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1037 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
1038 TRACE_RANGE_CHECK_ELIMINATION(tty->fill_to(2*block->dominator_depth());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1039 tty->print("i%d", instr->id());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1040 tty->print(": ");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1041 bound->print();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1042 tty->print_cr("");
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 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1047 instr = instr->next();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1048 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1049 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1050 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1051 #endif
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 // Verification or the IR
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1054 RangeCheckEliminator::Verification::Verification(IR *ir) : _used(BlockBegin::number_of_blocks(), false) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1055 this->_ir = ir;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1056 ir->iterate_linear_scan_order(this);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1057 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1058
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1059 // Verify this block
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1060 void RangeCheckEliminator::Verification::block_do(BlockBegin *block) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1061 If *cond = block->end()->as_If();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1062 // Watch out: tsux and fsux can be the same!
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1063 if (block->number_of_sux() > 1) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1064 for (int i=0; i<block->number_of_sux(); i++) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1065 BlockBegin *sux = block->sux_at(i);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1066 BlockBegin *pred = NULL;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1067 for (int j=0; j<sux->number_of_preds(); j++) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1068 BlockBegin *cur = sux->pred_at(j);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1069 assert(cur != NULL, "Predecessor must not be null");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1070 if (!pred) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1071 pred = cur;
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 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
1074 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1075 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
1076 assert(sux->pred_at(0) == block, "Wrong successor");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1077 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1078 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1079
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1080 BlockBegin *dominator = block->dominator();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1081 if (dominator) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1082 assert(block != _ir->start(), "Start block must not have a dominator!");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1083 assert(can_reach(dominator, block), "Dominator can't reach his block !");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1084 assert(can_reach(_ir->start(), dominator), "Dominator is unreachable !");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1085 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
1086 BlockList *all_blocks = _ir->linear_scan_order();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1087 for (int i=0; i<all_blocks->length(); i++) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1088 BlockBegin *cur = all_blocks->at(i);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1089 if (cur != dominator && cur != block) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1090 assert(can_reach(dominator, block, cur), "There has to be another dominator!");
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 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1093 } else {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1094 assert(block == _ir->start(), "Only start block must not have a dominator");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1095 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1096
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1097 if (block->is_set(BlockBegin::linear_scan_loop_header_flag)) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1098 int loop_index = block->loop_index();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1099 BlockList *all_blocks = _ir->linear_scan_order();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1100 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
1101 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
1102 // Sometimes, the backbranch comes from an exception handler. In
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1103 // this case, loop indexes/loop depths may not appear correct.
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1104 bool loop_through_xhandler = false;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1105 for (int i = 0; i < block->number_of_exception_handlers(); i++) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1106 BlockBegin *xhandler = block->exception_handler_at(i);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1107 for (int j = 0; j < block->number_of_preds(); j++) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1108 if (dominates(xhandler, block->pred_at(j)) || xhandler == block->pred_at(j)) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1109 loop_through_xhandler = true;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1110 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1111 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1112 }
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 for (int i=0; i<block->number_of_sux(); i++) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1115 BlockBegin *sux = block->sux_at(i);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1116 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
1117 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
1118 }
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 for (int i=0; i<all_blocks->length(); i++) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1121 BlockBegin *cur = all_blocks->at(i);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1122 if (cur->loop_index() == loop_index && cur != block) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1123 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
1124 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1125 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1126 }
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 Instruction *cur = block;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1129 while (cur) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1130 assert(cur->block() == block, "Block begin has to be set correctly!");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1131 cur = cur->next();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1132 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1133 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1134
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1135 // Loop header must dominate all loop blocks
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1136 bool RangeCheckEliminator::Verification::dominates(BlockBegin *dominator, BlockBegin *block) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1137 BlockBegin *cur = block->dominator();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1138 while (cur && cur != dominator) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1139 cur = cur->dominator();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1140 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1141 return cur == dominator;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1142 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1143
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1144 // 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
1145 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
1146 if (start == end) return start != dont_use;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1147 // Simple BSF from start to end
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1148 // BlockBeginList _current;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1149 for (int i=0; i<_used.length(); i++) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1150 _used[i] = false;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1151 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1152 _current.truncate(0);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1153 _successors.truncate(0);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1154 if (start != dont_use) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1155 _current.push(start);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1156 _used[start->block_id()] = true;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1157 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1158
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1159 // BlockBeginList _successors;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1160 while (_current.length() > 0) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1161 BlockBegin *cur = _current.pop();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1162 // Add exception handlers to list
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1163 for (int i=0; i<cur->number_of_exception_handlers(); i++) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1164 BlockBegin *xhandler = cur->exception_handler_at(i);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1165 _successors.push(xhandler);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1166 // Add exception handlers of _successors to list
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1167 for (int j=0; j<xhandler->number_of_exception_handlers(); j++) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1168 BlockBegin *sux_xhandler = xhandler->exception_handler_at(j);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1169 _successors.push(sux_xhandler);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1170 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1171 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1172 // Add normal _successors to list
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1173 for (int i=0; i<cur->number_of_sux(); i++) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1174 BlockBegin *sux = cur->sux_at(i);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1175 _successors.push(sux);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1176 // Add exception handlers of _successors to list
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1177 for (int j=0; j<sux->number_of_exception_handlers(); j++) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1178 BlockBegin *xhandler = sux->exception_handler_at(j);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1179 _successors.push(xhandler);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1180 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1181 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1182 for (int i=0; i<_successors.length(); i++) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1183 BlockBegin *sux = _successors[i];
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1184 assert(sux != NULL, "Successor must not be NULL!");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1185 if (sux == end) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1186 return true;
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 if (sux != dont_use && !_used[sux->block_id()]) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1189 _used[sux->block_id()] = true;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1190 _current.push(sux);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1191 }
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 _successors.truncate(0);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1194 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1195
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1196 return false;
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
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1199 // Bound
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1200 RangeCheckEliminator::Bound::~Bound() {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1201 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1202
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1203 // Bound constructor
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1204 RangeCheckEliminator::Bound::Bound() {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1205 init();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1206 this->_lower = min_jint;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1207 this->_upper = max_jint;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1208 this->_lower_instr = NULL;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1209 this->_upper_instr = NULL;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1210 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1211
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1212 // Bound constructor
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1213 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
1214 init();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1215 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
1216 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
1217 this->_lower = lower;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1218 this->_upper = upper;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1219 this->_lower_instr = lower_instr;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1220 this->_upper_instr = upper_instr;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1221 }
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 // Bound constructor
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1224 RangeCheckEliminator::Bound::Bound(Instruction::Condition cond, Value v, int constant) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1225 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
1226 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
1227
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1228 init();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1229 if (cond == Instruction::eql) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1230 _lower = constant;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1231 _lower_instr = v;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1232 _upper = constant;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1233 _upper_instr = v;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1234 } else if (cond == Instruction::neq) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1235 _lower = min_jint;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1236 _upper = max_jint;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1237 _lower_instr = NULL;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1238 _upper_instr = NULL;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1239 if (v == NULL) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1240 if (constant == min_jint) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1241 _lower++;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1242 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1243 if (constant == max_jint) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1244 _upper--;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1245 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1246 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1247 } else if (cond == Instruction::geq) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1248 _lower = constant;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1249 _lower_instr = v;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1250 _upper = max_jint;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1251 _upper_instr = NULL;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1252 } else if (cond == Instruction::leq) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1253 _lower = min_jint;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1254 _lower_instr = NULL;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1255 _upper = constant;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1256 _upper_instr = v;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1257 } else {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1258 ShouldNotReachHere();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1259 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1260 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1261
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1262 // Set lower
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1263 void RangeCheckEliminator::Bound::set_lower(int value, Value v) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1264 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
1265 this->_lower = value;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1266 this->_lower_instr = v;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1267 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1268
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1269 // Set upper
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1270 void RangeCheckEliminator::Bound::set_upper(int value, Value v) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1271 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
1272 this->_upper = value;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1273 this->_upper_instr = v;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1274 }
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 // Add constant -> no overflow may occur
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1277 void RangeCheckEliminator::Bound::add_constant(int value) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1278 this->_lower += value;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1279 this->_upper += value;
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
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1282 // Init
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1283 void RangeCheckEliminator::Bound::init() {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1284 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1285
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1286 // or
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1287 void RangeCheckEliminator::Bound::or_op(Bound *b) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1288 // Watch out, bound is not guaranteed not to overflow!
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1289 // Update lower bound
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1290 if (_lower_instr != b->_lower_instr || (_lower_instr && _lower != b->_lower)) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1291 _lower_instr = NULL;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1292 _lower = min_jint;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1293 } else {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1294 _lower = MIN2(_lower, b->_lower);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1295 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1296 // Update upper bound
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1297 if (_upper_instr != b->_upper_instr || (_upper_instr && _upper != b->_upper)) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1298 _upper_instr = NULL;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1299 _upper = max_jint;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1300 } else {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1301 _upper = MAX2(_upper, b->_upper);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1302 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1303 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1304
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1305 // and
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1306 void RangeCheckEliminator::Bound::and_op(Bound *b) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1307 // Update lower bound
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1308 if (_lower_instr == b->_lower_instr) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1309 _lower = MAX2(_lower, b->_lower);
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 (b->has_lower()) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1312 bool set = true;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1313 if (_lower_instr != NULL && b->_lower_instr != NULL) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1314 set = (_lower_instr->dominator_depth() > b->_lower_instr->dominator_depth());
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 if (set) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1317 _lower = b->_lower;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1318 _lower_instr = b->_lower_instr;
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 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1321 // Update upper bound
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1322 if (_upper_instr == b->_upper_instr) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1323 _upper = MIN2(_upper, b->_upper);
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 (b->has_upper()) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1326 bool set = true;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1327 if (_upper_instr != NULL && b->_upper_instr != NULL) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1328 set = (_upper_instr->dominator_depth() > b->_upper_instr->dominator_depth());
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 if (set) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1331 _upper = b->_upper;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1332 _upper_instr = b->_upper_instr;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1333 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1334 }
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 // has_upper
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1338 bool RangeCheckEliminator::Bound::has_upper() {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1339 return _upper_instr != NULL || _upper < max_jint;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1340 }
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 // is_smaller
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1343 bool RangeCheckEliminator::Bound::is_smaller(Bound *b) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1344 if (b->_lower_instr != _upper_instr) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1345 return false;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1346 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1347 return _upper < b->_lower;
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 // has_lower
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1351 bool RangeCheckEliminator::Bound::has_lower() {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1352 return _lower_instr != NULL || _lower > min_jint;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1353 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1354
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1355 // in_array_bound
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1356 bool RangeCheckEliminator::in_array_bound(Bound *bound, Value array){
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1357 if (!bound) return false;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1358 assert(array != NULL, "Must not be null!");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1359 assert(bound != NULL, "Must not be null!");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1360 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
1361 ArrayLength *len = bound->upper_instr()->as_ArrayLength();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1362 if (bound->upper_instr() == array || (len != NULL && len->array() == array)) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1363 return true;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1364 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1365 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1366 return false;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1367 }
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 // remove_lower
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1370 void RangeCheckEliminator::Bound::remove_lower() {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1371 _lower = min_jint;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1372 _lower_instr = NULL;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1373 }
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 // remove_upper
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1376 void RangeCheckEliminator::Bound::remove_upper() {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1377 _upper = max_jint;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1378 _upper_instr = NULL;
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 // upper
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1382 int RangeCheckEliminator::Bound::upper() {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1383 return _upper;
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 // lower
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1387 int RangeCheckEliminator::Bound::lower() {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1388 return _lower;
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 // upper_instr
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1392 Value RangeCheckEliminator::Bound::upper_instr() {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1393 return _upper_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 // lower_instr
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1397 Value RangeCheckEliminator::Bound::lower_instr() {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1398 return _lower_instr;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1399 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1400
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1401 // print
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1402 void RangeCheckEliminator::Bound::print() {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1403 tty->print("");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1404 if (this->_lower_instr || this->_lower != min_jint) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1405 if (this->_lower_instr) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1406 tty->print("i%d", this->_lower_instr->id());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1407 if (this->_lower > 0) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1408 tty->print("+%d", _lower);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1409 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1410 if (this->_lower < 0) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1411 tty->print("%d", _lower);
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 } else {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1414 tty->print("%d", _lower);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1415 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1416 tty->print(" <= ");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1417 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1418 tty->print("x");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1419 if (this->_upper_instr || this->_upper != max_jint) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1420 tty->print(" <= ");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1421 if (this->_upper_instr) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1422 tty->print("i%d", this->_upper_instr->id());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1423 if (this->_upper > 0) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1424 tty->print("+%d", _upper);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1425 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1426 if (this->_upper < 0) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1427 tty->print("%d", _upper);
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 } else {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1430 tty->print("%d", _upper);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1431 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1432 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1433 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1434
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1435 // Copy
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1436 RangeCheckEliminator::Bound *RangeCheckEliminator::Bound::copy() {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1437 Bound *b = new Bound();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1438 b->_lower = _lower;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1439 b->_lower_instr = _lower_instr;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1440 b->_upper = _upper;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1441 b->_upper_instr = _upper_instr;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1442 return b;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1443 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1444
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1445 #ifdef ASSERT
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1446 // Add assertion
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1447 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
1448 Instruction *result = position;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1449 Instruction *compare_with = NULL;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1450 ValueStack *state = position->state_before();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1451 if (position->as_BlockEnd() && !position->as_Goto()) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1452 state = position->as_BlockEnd()->state_before();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1453 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1454 Instruction *instruction_before = position->prev();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1455 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
1456 instruction_before = instruction_before->prev();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1457 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1458 result = instruction_before;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1459 // Load constant only if needed
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1460 Constant *constant = NULL;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1461 if (i != 0 || !instr) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1462 constant = new Constant(new IntConstant(i));
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1463 NOT_PRODUCT(constant->set_printable_bci(position->printable_bci()));
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1464 result = result->insert_after(constant);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1465 compare_with = constant;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1466 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1467
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1468 if (instr) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1469 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
1470 compare_with = instr;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1471 // Load array length if necessary
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1472 Instruction *op = instr;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1473 if (instr->type()->as_ObjectType()) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1474 assert(state, "must not be null");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1475 ArrayLength *length = new ArrayLength(instr, state->copy());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1476 NOT_PRODUCT(length->set_printable_bci(position->printable_bci()));
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1477 length->set_exception_state(length->state_before());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1478 result = result->insert_after(length);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1479 op = length;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1480 compare_with = length;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1481 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1482 // Add operation only if necessary
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1483 if (constant) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1484 ArithmeticOp *ao = new ArithmeticOp(Bytecodes::_iadd, constant, op, false, NULL);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1485 NOT_PRODUCT(ao->set_printable_bci(position->printable_bci()));
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1486 result = result->insert_after(ao);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1487 compare_with = ao;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1488 // TODO: Check that add operation does not overflow!
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1489 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1490 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1491 assert(compare_with != NULL, "You have to compare with something!");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1492 assert(instruction != NULL, "Instruction must not be null!");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1493
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1494 if (instruction->type()->as_ObjectType()) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1495 // Load array length if necessary
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1496 Instruction *op = instruction;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1497 assert(state, "must not be null");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1498 ArrayLength *length = new ArrayLength(instruction, state->copy());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1499 length->set_exception_state(length->state_before());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1500 NOT_PRODUCT(length->set_printable_bci(position->printable_bci()));
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1501 result = result->insert_after(length);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1502 instruction = length;
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 Assert *assert = new Assert(instruction, cond, false, compare_with);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1506 NOT_PRODUCT(assert->set_printable_bci(position->printable_bci()));
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1507 result->insert_after(assert);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1508 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1509
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1510 // Add assertions
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1511 void RangeCheckEliminator::add_assertions(Bound *bound, Instruction *instruction, Instruction *position) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1512 // Add lower bound assertion
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1513 if (bound->has_lower()) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1514 bound->add_assertion(instruction, position, bound->lower(), bound->lower_instr(), Instruction::geq);
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 // Add upper bound assertion
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1517 if (bound->has_upper()) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1518 bound->add_assertion(instruction, position, bound->upper(), bound->upper_instr(), Instruction::leq);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1519 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1520 }
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1521 #endif
46f6f063b272 7153771: array bound check elimination for c1
roland
parents:
diff changeset
1522