Mercurial > hg > truffle
comparison src/share/vm/opto/loopTransform.cpp @ 1303:c047da02984c
6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
Reviewed-by: kvn
author | never |
---|---|
date | Wed, 17 Mar 2010 16:40:25 -0700 |
parents | 336c6c200f5f |
children | c18cbe5936b8 |
comparison
equal
deleted
inserted
replaced
1302:2484f4d6a54e | 1303:c047da02984c |
---|---|
1 /* | 1 /* |
2 * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. | 2 * Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
2086 // (2) stride*scale < 0 | 2086 // (2) stride*scale < 0 |
2087 // max(scale*i + offset) = scale*init + offset | 2087 // max(scale*i + offset) = scale*init + offset |
2088 BoolNode* PhaseIdealLoop::rc_predicate(Node* ctrl, | 2088 BoolNode* PhaseIdealLoop::rc_predicate(Node* ctrl, |
2089 int scale, Node* offset, | 2089 int scale, Node* offset, |
2090 Node* init, Node* limit, Node* stride, | 2090 Node* init, Node* limit, Node* stride, |
2091 Node* range) { | 2091 Node* range, bool upper) { |
2092 DEBUG_ONLY(ttyLocker ttyl); | |
2093 if (TraceLoopPredicate) tty->print("rc_predicate "); | |
2094 | |
2092 Node* max_idx_expr = init; | 2095 Node* max_idx_expr = init; |
2093 int stride_con = stride->get_int(); | 2096 int stride_con = stride->get_int(); |
2094 if ((stride_con > 0) == (scale > 0)) { | 2097 if ((stride_con > 0) == (scale > 0) == upper) { |
2095 max_idx_expr = new (C, 3) SubINode(limit, stride); | 2098 max_idx_expr = new (C, 3) SubINode(limit, stride); |
2096 register_new_node(max_idx_expr, ctrl); | 2099 register_new_node(max_idx_expr, ctrl); |
2100 if (TraceLoopPredicate) tty->print("(limit - stride) "); | |
2101 } else { | |
2102 if (TraceLoopPredicate) tty->print("init "); | |
2097 } | 2103 } |
2098 | 2104 |
2099 if (scale != 1) { | 2105 if (scale != 1) { |
2100 ConNode* con_scale = _igvn.intcon(scale); | 2106 ConNode* con_scale = _igvn.intcon(scale); |
2101 max_idx_expr = new (C, 3) MulINode(max_idx_expr, con_scale); | 2107 max_idx_expr = new (C, 3) MulINode(max_idx_expr, con_scale); |
2102 register_new_node(max_idx_expr, ctrl); | 2108 register_new_node(max_idx_expr, ctrl); |
2109 if (TraceLoopPredicate) tty->print("* %d ", scale); | |
2103 } | 2110 } |
2104 | 2111 |
2105 if (offset && (!offset->is_Con() || offset->get_int() != 0)){ | 2112 if (offset && (!offset->is_Con() || offset->get_int() != 0)){ |
2106 max_idx_expr = new (C, 3) AddINode(max_idx_expr, offset); | 2113 max_idx_expr = new (C, 3) AddINode(max_idx_expr, offset); |
2107 register_new_node(max_idx_expr, ctrl); | 2114 register_new_node(max_idx_expr, ctrl); |
2115 if (TraceLoopPredicate) | |
2116 if (offset->is_Con()) tty->print("+ %d ", offset->get_int()); | |
2117 else tty->print("+ offset "); | |
2108 } | 2118 } |
2109 | 2119 |
2110 CmpUNode* cmp = new (C, 3) CmpUNode(max_idx_expr, range); | 2120 CmpUNode* cmp = new (C, 3) CmpUNode(max_idx_expr, range); |
2111 register_new_node(cmp, ctrl); | 2121 register_new_node(cmp, ctrl); |
2112 BoolNode* bol = new (C, 2) BoolNode(cmp, BoolTest::lt); | 2122 BoolNode* bol = new (C, 2) BoolNode(cmp, BoolTest::lt); |
2113 register_new_node(bol, ctrl); | 2123 register_new_node(bol, ctrl); |
2124 | |
2125 if (TraceLoopPredicate) tty->print_cr("<u range"); | |
2114 return bol; | 2126 return bol; |
2115 } | 2127 } |
2116 | 2128 |
2117 //------------------------------ loop_predication_impl-------------------------- | 2129 //------------------------------ loop_predication_impl-------------------------- |
2118 // Insert loop predicates for null checks and range checks | 2130 // Insert loop predicates for null checks and range checks |
2185 | 2197 |
2186 bool hoisted = false; // true if at least one proj is promoted | 2198 bool hoisted = false; // true if at least one proj is promoted |
2187 while (if_proj_list.size() > 0) { | 2199 while (if_proj_list.size() > 0) { |
2188 // Following are changed to nonnull when a predicate can be hoisted | 2200 // Following are changed to nonnull when a predicate can be hoisted |
2189 ProjNode* new_predicate_proj = NULL; | 2201 ProjNode* new_predicate_proj = NULL; |
2190 BoolNode* new_predicate_bol = NULL; | |
2191 | 2202 |
2192 ProjNode* proj = if_proj_list.pop()->as_Proj(); | 2203 ProjNode* proj = if_proj_list.pop()->as_Proj(); |
2193 IfNode* iff = proj->in(0)->as_If(); | 2204 IfNode* iff = proj->in(0)->as_If(); |
2194 | 2205 |
2195 if (!is_uncommon_trap_if_pattern(proj)) { | 2206 if (!is_uncommon_trap_if_pattern(proj)) { |
2216 BoolNode* bol = test->as_Bool(); | 2227 BoolNode* bol = test->as_Bool(); |
2217 if (invar.is_invariant(bol)) { | 2228 if (invar.is_invariant(bol)) { |
2218 // Invariant test | 2229 // Invariant test |
2219 new_predicate_proj = create_new_if_for_predicate(predicate_proj); | 2230 new_predicate_proj = create_new_if_for_predicate(predicate_proj); |
2220 Node* ctrl = new_predicate_proj->in(0)->as_If()->in(0); | 2231 Node* ctrl = new_predicate_proj->in(0)->as_If()->in(0); |
2221 new_predicate_bol = invar.clone(bol, ctrl)->as_Bool(); | 2232 BoolNode* new_predicate_bol = invar.clone(bol, ctrl)->as_Bool(); |
2222 if (TraceLoopPredicate) tty->print("invariant"); | 2233 |
2234 // Negate test if necessary | |
2235 bool negated = false; | |
2236 if (proj->_con != predicate_proj->_con) { | |
2237 new_predicate_bol = new (C, 2) BoolNode(new_predicate_bol->in(1), new_predicate_bol->_test.negate()); | |
2238 register_new_node(new_predicate_bol, ctrl); | |
2239 negated = true; | |
2240 } | |
2241 IfNode* new_predicate_iff = new_predicate_proj->in(0)->as_If(); | |
2242 _igvn.hash_delete(new_predicate_iff); | |
2243 new_predicate_iff->set_req(1, new_predicate_bol); | |
2244 if (TraceLoopPredicate) tty->print_cr("invariant if%s: %d", negated ? " negated" : "", new_predicate_iff->_idx); | |
2245 | |
2223 } else if (cl != NULL && loop->is_range_check_if(iff, this, invar)) { | 2246 } else if (cl != NULL && loop->is_range_check_if(iff, this, invar)) { |
2224 // Range check (only for counted loops) | 2247 assert(proj->_con == predicate_proj->_con, "must match"); |
2225 new_predicate_proj = create_new_if_for_predicate(predicate_proj); | 2248 |
2226 Node *ctrl = new_predicate_proj->in(0)->as_If()->in(0); | 2249 // Range check for counted loops |
2227 const Node* cmp = bol->in(1)->as_Cmp(); | 2250 const Node* cmp = bol->in(1)->as_Cmp(); |
2228 Node* idx = cmp->in(1); | 2251 Node* idx = cmp->in(1); |
2229 assert(!invar.is_invariant(idx), "index is variant"); | 2252 assert(!invar.is_invariant(idx), "index is variant"); |
2230 assert(cmp->in(2)->Opcode() == Op_LoadRange, "must be"); | 2253 assert(cmp->in(2)->Opcode() == Op_LoadRange, "must be"); |
2231 LoadRangeNode* ld_rng = (LoadRangeNode*)cmp->in(2); // LoadRangeNode | 2254 Node* ld_rng = cmp->in(2); // LoadRangeNode |
2232 assert(invar.is_invariant(ld_rng), "load range must be invariant"); | 2255 assert(invar.is_invariant(ld_rng), "load range must be invariant"); |
2233 ld_rng = (LoadRangeNode*)invar.clone(ld_rng, ctrl); | |
2234 int scale = 1; | 2256 int scale = 1; |
2235 Node* offset = zero; | 2257 Node* offset = zero; |
2236 bool ok = is_scaled_iv_plus_offset(idx, cl->phi(), &scale, &offset); | 2258 bool ok = is_scaled_iv_plus_offset(idx, cl->phi(), &scale, &offset); |
2237 assert(ok, "must be index expression"); | 2259 assert(ok, "must be index expression"); |
2260 | |
2261 Node* init = cl->init_trip(); | |
2262 Node* limit = cl->limit(); | |
2263 Node* stride = cl->stride(); | |
2264 | |
2265 // Build if's for the upper and lower bound tests. The | |
2266 // lower_bound test will dominate the upper bound test and all | |
2267 // cloned or created nodes will use the lower bound test as | |
2268 // their declared control. | |
2269 ProjNode* lower_bound_proj = create_new_if_for_predicate(predicate_proj); | |
2270 ProjNode* upper_bound_proj = create_new_if_for_predicate(predicate_proj); | |
2271 assert(upper_bound_proj->in(0)->as_If()->in(0) == lower_bound_proj, "should dominate"); | |
2272 Node *ctrl = lower_bound_proj->in(0)->as_If()->in(0); | |
2273 | |
2274 // Perform cloning to keep Invariance state correct since the | |
2275 // late schedule will place invariant things in the loop. | |
2276 ld_rng = invar.clone(ld_rng, ctrl); | |
2238 if (offset && offset != zero) { | 2277 if (offset && offset != zero) { |
2239 assert(invar.is_invariant(offset), "offset must be loop invariant"); | 2278 assert(invar.is_invariant(offset), "offset must be loop invariant"); |
2240 offset = invar.clone(offset, ctrl); | 2279 offset = invar.clone(offset, ctrl); |
2241 } | 2280 } |
2242 Node* init = cl->init_trip(); | 2281 |
2243 Node* limit = cl->limit(); | 2282 // Test the lower bound |
2244 Node* stride = cl->stride(); | 2283 Node* lower_bound_bol = rc_predicate(ctrl, scale, offset, init, limit, stride, ld_rng, false); |
2245 new_predicate_bol = rc_predicate(ctrl, scale, offset, init, limit, stride, ld_rng); | 2284 IfNode* lower_bound_iff = lower_bound_proj->in(0)->as_If(); |
2246 if (TraceLoopPredicate) tty->print("range check"); | 2285 _igvn.hash_delete(lower_bound_iff); |
2247 } | 2286 lower_bound_iff->set_req(1, lower_bound_bol); |
2248 | 2287 if (TraceLoopPredicate) tty->print_cr("lower bound check if: %d", lower_bound_iff->_idx); |
2249 if (new_predicate_proj == NULL) { | 2288 |
2289 // Test the upper bound | |
2290 Node* upper_bound_bol = rc_predicate(ctrl, scale, offset, init, limit, stride, ld_rng, true); | |
2291 IfNode* upper_bound_iff = upper_bound_proj->in(0)->as_If(); | |
2292 _igvn.hash_delete(upper_bound_iff); | |
2293 upper_bound_iff->set_req(1, upper_bound_bol); | |
2294 if (TraceLoopPredicate) tty->print_cr("upper bound check if: %d", lower_bound_iff->_idx); | |
2295 | |
2296 // Fall through into rest of the clean up code which will move | |
2297 // any dependent nodes onto the upper bound test. | |
2298 new_predicate_proj = upper_bound_proj; | |
2299 } else { | |
2250 // The other proj of the "iff" is a uncommon trap projection, and we can assume | 2300 // The other proj of the "iff" is a uncommon trap projection, and we can assume |
2251 // the other proj will not be executed ("executed" means uct raised). | 2301 // the other proj will not be executed ("executed" means uct raised). |
2252 continue; | 2302 continue; |
2253 } else { | 2303 } |
2254 // Success - attach condition (new_predicate_bol) to predicate if | 2304 |
2255 invar.map_ctrl(proj, new_predicate_proj); // so that invariance test can be appropriate | 2305 // Success - attach condition (new_predicate_bol) to predicate if |
2256 IfNode* new_iff = new_predicate_proj->in(0)->as_If(); | 2306 invar.map_ctrl(proj, new_predicate_proj); // so that invariance test can be appropriate |
2257 | 2307 |
2258 // Negate test if necessary | 2308 // Eliminate the old if in the loop body |
2259 if (proj->_con != predicate_proj->_con) { | 2309 _igvn.hash_delete(iff); |
2260 new_predicate_bol = new (C, 2) BoolNode(new_predicate_bol->in(1), new_predicate_bol->_test.negate()); | 2310 iff->set_req(1, proj->is_IfFalse() ? cond_false : cond_true); |
2261 register_new_node(new_predicate_bol, new_iff->in(0)); | 2311 |
2262 if (TraceLoopPredicate) tty->print_cr(" if negated: %d", iff->_idx); | 2312 Node* ctrl = new_predicate_proj; // new control |
2263 } else { | 2313 ProjNode* dp = proj; // old control |
2264 if (TraceLoopPredicate) tty->print_cr(" if: %d", iff->_idx); | 2314 assert(get_loop(dp) == loop, "guaranteed at the time of collecting proj"); |
2265 } | 2315 // Find nodes (depends only on the test) off the surviving projection; |
2266 | 2316 // move them outside the loop with the control of proj_clone |
2267 _igvn.hash_delete(new_iff); | 2317 for (DUIterator_Fast imax, i = dp->fast_outs(imax); i < imax; i++) { |
2268 new_iff->set_req(1, new_predicate_bol); | 2318 Node* cd = dp->fast_out(i); // Control-dependent node |
2269 | 2319 if (cd->depends_only_on_test()) { |
2270 _igvn.hash_delete(iff); | 2320 assert(cd->in(0) == dp, ""); |
2271 iff->set_req(1, proj->is_IfFalse() ? cond_false : cond_true); | 2321 _igvn.hash_delete(cd); |
2272 | 2322 cd->set_req(0, ctrl); // ctrl, not NULL |
2273 Node* ctrl = new_predicate_proj; // new control | 2323 set_early_ctrl(cd); |
2274 ProjNode* dp = proj; // old control | 2324 _igvn._worklist.push(cd); |
2275 assert(get_loop(dp) == loop, "guarenteed at the time of collecting proj"); | 2325 IdealLoopTree *new_loop = get_loop(get_ctrl(cd)); |
2276 // Find nodes (depends only on the test) off the surviving projection; | 2326 if (new_loop != loop) { |
2277 // move them outside the loop with the control of proj_clone | 2327 if (!loop->_child) loop->_body.yank(cd); |
2278 for (DUIterator_Fast imax, i = dp->fast_outs(imax); i < imax; i++) { | 2328 if (!new_loop->_child ) new_loop->_body.push(cd); |
2279 Node* cd = dp->fast_out(i); // Control-dependent node | |
2280 if (cd->depends_only_on_test()) { | |
2281 assert(cd->in(0) == dp, ""); | |
2282 _igvn.hash_delete(cd); | |
2283 cd->set_req(0, ctrl); // ctrl, not NULL | |
2284 set_early_ctrl(cd); | |
2285 _igvn._worklist.push(cd); | |
2286 IdealLoopTree *new_loop = get_loop(get_ctrl(cd)); | |
2287 if (new_loop != loop) { | |
2288 if (!loop->_child) loop->_body.yank(cd); | |
2289 if (!new_loop->_child ) new_loop->_body.push(cd); | |
2290 } | |
2291 --i; | |
2292 --imax; | |
2293 } | 2329 } |
2294 } | 2330 --i; |
2295 | 2331 --imax; |
2296 hoisted = true; | 2332 } |
2297 C->set_major_progress(); | 2333 } |
2298 } | 2334 |
2335 hoisted = true; | |
2336 C->set_major_progress(); | |
2299 } // end while | 2337 } // end while |
2300 | 2338 |
2301 #ifndef PRODUCT | 2339 #ifndef PRODUCT |
2302 // report that the loop predication has been actually performed | 2340 // report that the loop predication has been actually performed |
2303 // for this loop | 2341 // for this loop |
2304 if (TraceLoopPredicate && hoisted) { | 2342 if (TraceLoopPredicate && hoisted) { |
2305 tty->print("Loop Predication Performed:"); | 2343 tty->print("Loop Predication Performed:"); |
2306 loop->dump_head(); | 2344 loop->dump_head(); |
2307 } | 2345 } |
2308 #endif | 2346 #endif |
2309 | 2347 |
2310 return hoisted; | 2348 return hoisted; |
2311 } | 2349 } |
2312 | 2350 |