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,ARM64}: void HaddOther.test_no_hadd_sum_casted_plus_const(short[], short[], short[]) loop_optimization (after) 103 /// CHECK: VecAdd 104 /// CHECK: VecHalvingAdd test_no_hadd_sum_casted_plus_const(short[] a, short[] b, short[] out)105 private static void test_no_hadd_sum_casted_plus_const(short[] a, short[] b, short[] out) { 106 int min_length = Math.min(out.length, Math.min(a.length, b.length)); 107 for (int i = 0; i < min_length; i++) { 108 out[i] = (short) (((short) (a[i] + b[i]) + 1) >> 1); 109 } 110 } 111 main()112 public static void main() { 113 short[] sA = new short[M]; 114 short[] sB = new short[M]; 115 short[] sOut = new short[M]; 116 int[] iA = new int[M]; 117 int[] iB = new int[M]; 118 int[] iOut = new int[M]; 119 120 // Some interesting values. 121 short[] interesting = { 122 (short) 0x0000, 123 (short) 0x0001, 124 (short) 0x0002, 125 (short) 0x1234, 126 (short) 0x8000, 127 (short) 0x8001, 128 (short) 0x7fff, 129 (short) 0xffff 130 }; 131 // Initialize cross-values to test all cases, and also 132 // set up some extra values to exercise the cleanup loop. 133 for (int i = 0; i < M; i++) { 134 sA[i] = (short) i; 135 sB[i] = interesting[i & 7]; 136 iA[i] = i; 137 iB[i] = interesting[i & 7]; 138 } 139 140 test_no_hadd_short2short(sA, sOut); 141 for (int i = 0; i < M; i++) { 142 short e = (short) (sA[i] >> 1); 143 expectEquals(e, sOut[i]); 144 } 145 test_no_hadd_short2short_logical(sA, sOut); 146 for (int i = 0; i < M; i++) { 147 short e = (short) (sA[i] >>> 1); 148 expectEquals(e, sOut[i]); 149 } 150 test_no_hadd_int2short(iA, sOut); 151 for (int i = 0; i < M; i++) { 152 short e = (short) (iA[i] >> 1); 153 expectEquals(e, sOut[i]); 154 } 155 test_no_hadd_int2int(iA, iOut); 156 for (int i = 0; i < M; i++) { 157 int e = iA[i] >> 1; 158 expectEquals(e, iOut[i]); 159 } 160 test_no_hadd_sum_casted(sA, sB, sOut); 161 for (int i = 0; i < M; i++) { 162 short e = (short) (((short) (sA[i] + sB[i])) >> 1); 163 expectEquals(e, sOut[i]); 164 } 165 test_no_hadd_sum_casted_ints(iA, iB, iOut); 166 for (int i = 0; i < M; i++) { 167 int e = (short) ((short) (iA[i] + iB[i]) >> 1); 168 expectEquals(e, iOut[i]); 169 } 170 test_no_hadd_sum_casted_plus_const(sA, sB, sOut); 171 for (int i = 0; i < M; i++) { 172 short e = (short) (((short) (sA[i] + sB[i]) + 1) >> 1); 173 expectEquals(e, sOut[i]); 174 } 175 176 System.out.println("HaddOther passed"); 177 } 178 expectEquals(int expected, int result)179 private static void expectEquals(int expected, int result) { 180 if (expected != result) { 181 throw new Error("Expected: " + expected + ", found: " + result); 182 } 183 } 184 } 185