| // Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 |  | 
 | // VMOptions=--deterministic --optimization_counter_threshold=1 | 
 |  | 
 | // A phi can have Smi type but non-Smi bounds if it is dominated by a smi check | 
 | // which always deoptimizes. Test that bounds check generalizer guards against | 
 | // such situations. | 
 |  | 
 | @pragma('vm:prefer-inline') | 
 | int checkSmi(int a) => ~a; | 
 |  | 
 | @pragma('vm:prefer-inline') | 
 | bool lessThan(int x, int y) => x < y; | 
 |  | 
 | @pragma('vm:prefer-inline') | 
 | int accessArray(List<int> arr, int i) => arr[i]; | 
 |  | 
 | void problem(List<int> arr, int n, bool f) { | 
 |   final C = 0x7000000000000000; | 
 |   for (var i = C, j = 0; lessThan(i, n); i++, j++) { | 
 |     if (f) { | 
 |       // Produce CheckSmi against C. This CheckSmi will be | 
 |       // hoisted out of the loop turning phi for j into a Smi | 
 |       // Phi. | 
 |       checkSmi(C); | 
 |       accessArray(arr, j); // Produce array access with bounds check for arr. | 
 |     } | 
 |   } | 
 | } | 
 |  | 
 | void main() { | 
 |   // Prime type feedback in checkSmi and accessArray helpers. | 
 |   // Note: we need these to be in separate helpers because we need | 
 |   // problematic code to appear on a never executed code path. | 
 |   // (It would trigger throw/deopt if it is ever executed). | 
 |   checkSmi(0); | 
 |   accessArray([1], 0); | 
 |   lessThan(1, 1); | 
 |  | 
 |   // Trigger the issue. | 
 |   problem([], 1, false); | 
 | } |