1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 import java.util.Arrays; 18 19 // 20 // Test on array parameters with or without potential aliasing. 21 // 22 public class Main { 23 24 // 25 // Cross-over on parameters with potential aliasing on parameters. 26 // The arrays a and b may point to the same memory, which (without 27 // further runtime tests) prevents hoisting the seemingly invariant 28 // array reference. 29 // 30 31 /// CHECK-START: void Main.CrossOverLoop1(int[], int[]) licm (before) 32 /// CHECK-DAG: ArraySet loop:none 33 /// CHECK-DAG: ArrayGet loop:{{B\d+}} 34 /// CHECK-DAG: ArraySet loop:{{B\d+}} 35 // 36 /// CHECK-START: void Main.CrossOverLoop1(int[], int[]) licm (after) 37 /// CHECK-DAG: ArraySet loop:none 38 /// CHECK-DAG: ArrayGet loop:{{B\d+}} 39 /// CHECK-DAG: ArraySet loop:{{B\d+}} CrossOverLoop1(int a[], int b[])40 private static void CrossOverLoop1(int a[], int b[]) { 41 b[20] = 99; 42 for (int i = 0; i < a.length; i++) { 43 a[i] = b[20] - 7; 44 } 45 } 46 47 /// CHECK-START: void Main.CrossOverLoop2(float[], float[]) licm (before) 48 /// CHECK-DAG: ArraySet loop:none 49 /// CHECK-DAG: ArrayGet loop:{{B\d+}} 50 /// CHECK-DAG: ArraySet loop:{{B\d+}} 51 // 52 /// CHECK-START: void Main.CrossOverLoop2(float[], float[]) licm (after) 53 /// CHECK-DAG: ArraySet loop:none 54 /// CHECK-DAG: ArrayGet loop:{{B\d+}} 55 /// CHECK-DAG: ArraySet loop:{{B\d+}} CrossOverLoop2(float a[], float b[])56 private static void CrossOverLoop2(float a[], float b[]) { 57 b[20] = 99; 58 for (int i = 0; i < a.length; i++) { 59 a[i] = b[20] - 7; 60 } 61 } 62 63 /// CHECK-START: void Main.CrossOverLoop3(long[], long[]) licm (before) 64 /// CHECK-DAG: ArraySet loop:none 65 /// CHECK-DAG: ArrayGet loop:{{B\d+}} 66 /// CHECK-DAG: ArraySet loop:{{B\d+}} 67 // 68 /// CHECK-START: void Main.CrossOverLoop3(long[], long[]) licm (after) 69 /// CHECK-DAG: ArraySet loop:none 70 /// CHECK-DAG: ArrayGet loop:{{B\d+}} 71 /// CHECK-DAG: ArraySet loop:{{B\d+}} CrossOverLoop3(long a[], long b[])72 private static void CrossOverLoop3(long a[], long b[]) { 73 b[20] = 99; 74 for (int i = 0; i < a.length; i++) { 75 a[i] = b[20] - 7; 76 } 77 } 78 79 /// CHECK-START: void Main.CrossOverLoop4(double[], double[]) licm (before) 80 /// CHECK-DAG: ArraySet loop:none 81 /// CHECK-DAG: ArrayGet loop:{{B\d+}} 82 /// CHECK-DAG: ArraySet loop:{{B\d+}} 83 // 84 /// CHECK-START: void Main.CrossOverLoop4(double[], double[]) licm (after) 85 /// CHECK-DAG: ArraySet loop:none 86 /// CHECK-DAG: ArrayGet loop:{{B\d+}} 87 /// CHECK-DAG: ArraySet loop:{{B\d+}} CrossOverLoop4(double a[], double b[])88 private static void CrossOverLoop4(double a[], double b[]) { 89 b[20] = 99; 90 for (int i = 0; i < a.length; i++) { 91 a[i] = b[20] - 7; 92 } 93 } 94 95 // 96 // False cross-over on parameters. Parameters have same width (which used to 97 // cause a false type aliasing in an older version of the compiler), but since 98 // the types are different cannot be aliased. Thus, the invariant array 99 // reference can be hoisted. 100 // 101 102 /// CHECK-START: void Main.FalseCrossOverLoop1(int[], float[]) licm (before) 103 /// CHECK-DAG: ArraySet loop:none 104 /// CHECK-DAG: ArrayGet loop:{{B\d+}} 105 /// CHECK-DAG: ArraySet loop:{{B\d+}} 106 // 107 /// CHECK-START: void Main.FalseCrossOverLoop1(int[], float[]) licm (after) 108 /// CHECK-DAG: ArraySet loop:none 109 /// CHECK-DAG: ArrayGet loop:none 110 /// CHECK-DAG: ArraySet loop:{{B\d+}} FalseCrossOverLoop1(int a[], float b[])111 private static void FalseCrossOverLoop1(int a[], float b[]) { 112 b[20] = -99; 113 for (int i = 0; i < a.length; i++) { 114 a[i] = (int) b[20] - 7; 115 } 116 } 117 118 /// CHECK-START: void Main.FalseCrossOverLoop2(float[], int[]) licm (before) 119 /// CHECK-DAG: ArraySet loop:none 120 /// CHECK-DAG: ArrayGet loop:{{B\d+}} 121 /// CHECK-DAG: ArraySet loop:{{B\d+}} 122 // 123 /// CHECK-START: void Main.FalseCrossOverLoop2(float[], int[]) licm (after) 124 /// CHECK-DAG: ArraySet loop:none 125 /// CHECK-DAG: ArrayGet loop:none 126 /// CHECK-DAG: ArraySet loop:{{B\d+}} FalseCrossOverLoop2(float a[], int b[])127 private static void FalseCrossOverLoop2(float a[], int b[]) { 128 b[20] = -99; 129 for (int i = 0; i < a.length; i++) { 130 a[i] = b[20] - 7; 131 } 132 } 133 134 /// CHECK-START: void Main.FalseCrossOverLoop3(long[], double[]) licm (before) 135 /// CHECK-DAG: ArraySet loop:none 136 /// CHECK-DAG: ArrayGet loop:{{B\d+}} 137 /// CHECK-DAG: ArraySet loop:{{B\d+}} 138 // 139 /// CHECK-START: void Main.FalseCrossOverLoop3(long[], double[]) licm (after) 140 /// CHECK-DAG: ArraySet loop:none 141 /// CHECK-DAG: ArrayGet loop:none 142 /// CHECK-DAG: ArraySet loop:{{B\d+}} FalseCrossOverLoop3(long a[], double b[])143 private static void FalseCrossOverLoop3(long a[], double b[]) { 144 b[20] = -99; 145 for (int i = 0; i < a.length; i++) { 146 a[i] = (long) b[20] - 7; 147 } 148 } 149 150 /// CHECK-START: void Main.FalseCrossOverLoop4(double[], long[]) licm (before) 151 /// CHECK-DAG: ArraySet loop:none 152 /// CHECK-DAG: ArrayGet loop:{{B\d+}} 153 /// CHECK-DAG: ArraySet loop:{{B\d+}} 154 // 155 /// CHECK-START: void Main.FalseCrossOverLoop4(double[], long[]) licm (after) 156 /// CHECK-DAG: ArraySet loop:none 157 /// CHECK-DAG: ArrayGet loop:none 158 /// CHECK-DAG: ArraySet loop:{{B\d+}} FalseCrossOverLoop4(double a[], long b[])159 private static void FalseCrossOverLoop4(double a[], long b[]) { 160 b[20] = -99; 161 for (int i = 0; i < a.length; i++) { 162 a[i] = b[20] - 7; 163 } 164 } 165 166 // 167 // Main driver and testers. 168 // 169 main(String[] args)170 public static void main(String[] args) { 171 int[] aI = new int[100]; 172 float[] aF = new float[100]; 173 long[] aJ = new long[100]; 174 double[] aD = new double[100]; 175 176 // Type I. 177 CrossOverLoop1(aI, aI); 178 for (int i = 0; i < aI.length; i++) { 179 expectEquals(i <= 20 ? 92 : 85, aI[i]); 180 } 181 // Type F. 182 CrossOverLoop2(aF, aF); 183 for (int i = 0; i < aF.length; i++) { 184 expectEquals(i <= 20 ? 92 : 85, aF[i]); 185 } 186 // Type J. 187 CrossOverLoop3(aJ, aJ); 188 for (int i = 0; i < aJ.length; i++) { 189 expectEquals(i <= 20 ? 92 : 85, aJ[i]); 190 } 191 // Type D. 192 CrossOverLoop4(aD, aD); 193 for (int i = 0; i < aD.length; i++) { 194 expectEquals(i <= 20 ? 92 : 85, aD[i]); 195 } 196 197 // Type I vs F. 198 FalseCrossOverLoop1(aI, aF); 199 for (int i = 0; i < aI.length; i++) { 200 expectEquals(-106, aI[i]); 201 } 202 // Type F vs I. 203 FalseCrossOverLoop2(aF, aI); 204 for (int i = 0; i < aF.length; i++) { 205 expectEquals(-106, aF[i]); 206 } 207 // Type J vs D. 208 FalseCrossOverLoop3(aJ, aD); 209 for (int i = 0; i < aJ.length; i++) { 210 expectEquals(-106, aJ[i]); 211 } 212 // Type D vs J. 213 FalseCrossOverLoop4(aD, aJ); 214 for (int i = 0; i < aD.length; i++) { 215 expectEquals(-106, aD[i]); 216 } 217 218 // Real-world example where incorrect type assignment could introduce a bug. 219 // The library sorting algorithm is heavy on array reads and writes, and 220 // assigning the wrong J/D type to one of these would introduce errors. 221 for (int i = 0; i < aD.length; i++) { 222 aD[i] = aD.length - i - 1; 223 } 224 Arrays.sort(aD); 225 for (int i = 0; i < aD.length; i++) { 226 expectEquals((double) i, aD[i]); 227 } 228 229 System.out.println("passed"); 230 } 231 expectEquals(int expected, int result)232 private static void expectEquals(int expected, int result) { 233 if (expected != result) { 234 throw new Error("Expected: " + expected + ", found: " + result); 235 } 236 } 237 expectEquals(long expected, long result)238 private static void expectEquals(long expected, long result) { 239 if (expected != result) { 240 throw new Error("Expected: " + expected + ", found: " + result); 241 } 242 } 243 expectEquals(float expected, float result)244 private static void expectEquals(float expected, float result) { 245 if (expected != result) { 246 throw new Error("Expected: " + expected + ", found: " + result); 247 } 248 } 249 expectEquals(double expected, double result)250 private static void expectEquals(double expected, double result) { 251 if (expected != result) { 252 throw new Error("Expected: " + expected + ", found: " + result); 253 } 254 } 255 } 256