1 /* 2 * Copyright (C) 2020 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 public class HaddOther { 18 private static final int N = 2 * 1024; 19 private static final int M = N + 31; 20 21 // Should be just shift right, not halving add. 22 // 23 /// CHECK-START-{ARM,ARM64}: void HaddOther.test_no_hadd_short2short(short[], short[]) loop_optimization (after) 24 /// CHECK: VecShr 25 26 /// CHECK-START-{ARM,ARM64}: void HaddOther.test_no_hadd_short2short(short[], short[]) loop_optimization (after) 27 /// CHECK-NOT: VecHalvingAdd test_no_hadd_short2short(short[] a, short[] out)28 private static void test_no_hadd_short2short(short[] a, short[] out) { 29 int min_length = Math.min(out.length, a.length); 30 for (int i = 0; i < min_length; i++) { 31 out[i] = (short) (a[i] >> 1); 32 } 33 } 34 35 // This loop is not vectorized: shift right with a signed type is not supported. 36 // 37 /// CHECK-START-{ARM,ARM64}: void HaddOther.test_no_hadd_short2short_logical(short[], short[]) loop_optimization (after) 38 /// CHECK-NOT: VecLoad 39 /// CHECK-NOT: VecHalvingAdd test_no_hadd_short2short_logical(short[] a, short[] out)40 private static void test_no_hadd_short2short_logical(short[] a, short[] out) { 41 int min_length = Math.min(out.length, a.length); 42 for (int i = 0; i < min_length; i++) { 43 out[i] = (short) (a[i] >>> 1); 44 } 45 } 46 47 // This loop is not vectorized: mismatched packed type size. 48 // 49 /// CHECK-START-{ARM,ARM64}: void HaddOther.test_no_hadd_int2short(int[], short[]) loop_optimization (after) 50 /// CHECK-NOT: VecLoad 51 /// CHECK-NOT: VecHalvingAdd test_no_hadd_int2short(int[] a, short[] out)52 private static void test_no_hadd_int2short(int[] a, short[] out) { 53 int min_length = Math.min(out.length, a.length); 54 for (int i = 0; i < min_length; i++) { 55 out[i] = (short) (a[i] >> 1); 56 } 57 } 58 59 // Should be just shift right, not halving add. 60 // 61 /// CHECK-START-{ARM,ARM64}: void HaddOther.test_no_hadd_int2int(int[], int[]) loop_optimization (after) 62 /// CHECK: VecShr 63 64 /// CHECK-START-{ARM,ARM64}: void HaddOther.test_no_hadd_int2int(int[], int[]) loop_optimization (after) 65 /// CHECK-NOT: VecHalvingAdd test_no_hadd_int2int(int[] a, int[] out)66 private static void test_no_hadd_int2int(int[] a, int[] out) { 67 int min_length = Math.min(out.length, a.length); 68 for (int i = 0; i < min_length; i++) { 69 out[i] = a[i] >> 1; 70 } 71 } 72 73 // Should be just add and shift right, not halving add. 74 // 75 /// CHECK-START-{ARM,ARM64}: void HaddOther.test_no_hadd_sum_casted(short[], short[], short[]) loop_optimization (after) 76 /// CHECK: VecAdd 77 /// CHECK: VecShr 78 79 /// CHECK-START-{ARM,ARM64}: void HaddOther.test_no_hadd_sum_casted(short[], short[], short[]) loop_optimization (after) 80 /// CHECK-NOT: VecHalvingAdd test_no_hadd_sum_casted(short[] a, short[] b, short[] out)81 private static void test_no_hadd_sum_casted(short[] a, short[] b, short[] out) { 82 int min_length = Math.min(out.length, Math.min(a.length, b.length)); 83 for (int i = 0; i < min_length; i++) { 84 out[i] = (short) (((short) (a[i] + b[i])) >> 1); 85 } 86 } 87 88 // This loop is not vectorized: mismatched packed type size. 89 // 90 /// CHECK-START-{ARM,ARM64}: void HaddOther.test_no_hadd_sum_casted_ints(int[], int[], int[]) loop_optimization (after) 91 /// CHECK-NOT: VecLoad 92 /// CHECK-NOT: VecHalvingAdd test_no_hadd_sum_casted_ints(int[] a, int[] b, int[] out)93 private static void test_no_hadd_sum_casted_ints(int[] a, int[] b, int[] out) { 94 int min_length = Math.min(out.length, Math.min(a.length, b.length)); 95 for (int i = 0; i < min_length; i++) { 96 out[i] = (short) ((short) (a[i] + b[i]) >> 1); 97 } 98 } 99 100 // Should be an add, followed by a halving add. 101 // 102 /// CHECK-START-ARM: void HaddOther.test_no_hadd_sum_casted_plus_const(short[], short[], short[]) loop_optimization (after) 103 /// CHECK: VecAdd 104 /// CHECK: VecHalvingAdd 105 // 106 /// CHECK-START-ARM64: void HaddOther.test_no_hadd_sum_casted_plus_const(short[], short[], short[]) loop_optimization (after) 107 /// CHECK-IF: hasIsaFeature("sve") 108 // 109 // HalvingAdd idiom is not supported for SVE. 110 /// CHECK-NOT: VecHalvingAdd 111 // 112 /// CHECK-ELSE: 113 // 114 /// CHECK: VecAdd 115 /// CHECK: VecHalvingAdd 116 // 117 /// CHECK-FI: test_no_hadd_sum_casted_plus_const(short[] a, short[] b, short[] out)118 private static void test_no_hadd_sum_casted_plus_const(short[] a, short[] b, short[] out) { 119 int min_length = Math.min(out.length, Math.min(a.length, b.length)); 120 for (int i = 0; i < min_length; i++) { 121 out[i] = (short) (((short) (a[i] + b[i]) + 1) >> 1); 122 } 123 } 124 main()125 public static void main() { 126 short[] sA = new short[M]; 127 short[] sB = new short[M]; 128 short[] sOut = new short[M]; 129 int[] iA = new int[M]; 130 int[] iB = new int[M]; 131 int[] iOut = new int[M]; 132 133 // Some interesting values. 134 short[] interesting = { 135 (short) 0x0000, 136 (short) 0x0001, 137 (short) 0x0002, 138 (short) 0x1234, 139 (short) 0x8000, 140 (short) 0x8001, 141 (short) 0x7fff, 142 (short) 0xffff 143 }; 144 // Initialize cross-values to test all cases, and also 145 // set up some extra values to exercise the cleanup loop. 146 for (int i = 0; i < M; i++) { 147 sA[i] = (short) i; 148 sB[i] = interesting[i & 7]; 149 iA[i] = i; 150 iB[i] = interesting[i & 7]; 151 } 152 153 test_no_hadd_short2short(sA, sOut); 154 for (int i = 0; i < M; i++) { 155 short e = (short) (sA[i] >> 1); 156 expectEquals(e, sOut[i]); 157 } 158 test_no_hadd_short2short_logical(sA, sOut); 159 for (int i = 0; i < M; i++) { 160 short e = (short) (sA[i] >>> 1); 161 expectEquals(e, sOut[i]); 162 } 163 test_no_hadd_int2short(iA, sOut); 164 for (int i = 0; i < M; i++) { 165 short e = (short) (iA[i] >> 1); 166 expectEquals(e, sOut[i]); 167 } 168 test_no_hadd_int2int(iA, iOut); 169 for (int i = 0; i < M; i++) { 170 int e = iA[i] >> 1; 171 expectEquals(e, iOut[i]); 172 } 173 test_no_hadd_sum_casted(sA, sB, sOut); 174 for (int i = 0; i < M; i++) { 175 short e = (short) (((short) (sA[i] + sB[i])) >> 1); 176 expectEquals(e, sOut[i]); 177 } 178 test_no_hadd_sum_casted_ints(iA, iB, iOut); 179 for (int i = 0; i < M; i++) { 180 int e = (short) ((short) (iA[i] + iB[i]) >> 1); 181 expectEquals(e, iOut[i]); 182 } 183 test_no_hadd_sum_casted_plus_const(sA, sB, sOut); 184 for (int i = 0; i < M; i++) { 185 short e = (short) (((short) (sA[i] + sB[i]) + 1) >> 1); 186 expectEquals(e, sOut[i]); 187 } 188 189 System.out.println("HaddOther passed"); 190 } 191 expectEquals(int expected, int result)192 private static void expectEquals(int expected, int result) { 193 if (expected != result) { 194 throw new Error("Expected: " + expected + ", found: " + result); 195 } 196 } 197 } 198