1f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik/* 2f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik * Copyright (C) 2017 The Android Open Source Project 3f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik * 4f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik * Licensed under the Apache License, Version 2.0 (the "License"); 5f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik * you may not use this file except in compliance with the License. 6f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik * You may obtain a copy of the License at 7f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik * 8f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik * http://www.apache.org/licenses/LICENSE-2.0 9f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik * 10f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik * Unless required by applicable law or agreed to in writing, software 11f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik * distributed under the License is distributed on an "AS IS" BASIS, 12f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik * See the License for the specific language governing permissions and 14f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik * limitations under the License. 15f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik */ 16f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik 17f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik/** 18f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik * Tests for halving-add idiomatic vectorization. 19f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik * 20f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik * Alternative version expressed with logical shift right 21f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik * in the higher precision (has no impact on idiom). 22f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik */ 23f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bikpublic class Main { 24f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik 25f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik private static final int N = 64 * 1024; 26f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik private static final int M = N + 31; 27f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik 28f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik static char[] sB1 = new char[M]; 29f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik static char[] sB2 = new char[M]; 30f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik static char[] sBo = new char[M]; 31f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik 32f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-START: void Main.halving_add_unsigned(char[], char[], char[]) loop_optimization (before) 33f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<I1:i\d+>> IntConstant 1 loop:none 34f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 35f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Get1:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none 36f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Get2:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none 37f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Add:i\d+>> Add [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none 38f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<UShr:i\d+>> UShr [<<Add>>,<<I1>>] loop:<<Loop>> outer_loop:none 39f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Cnv:c\d+>> TypeConversion [<<UShr>>] loop:<<Loop>> outer_loop:none 40f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>> outer_loop:none 41f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik // 429cb7fe4daf872fd0cb312489af263ebc622033a8Aart Bik /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.halving_add_unsigned(char[], char[], char[]) loop_optimization (after) 438c6c3575668831c752820ba4174b07ee407f7a4fAart Bik /// CHECK-DAG: <<Get1:d\d+>> VecLoad loop:<<Loop:B\d+>> outer_loop:none 448c6c3575668831c752820ba4174b07ee407f7a4fAart Bik /// CHECK-DAG: <<Get2:d\d+>> VecLoad loop:<<Loop>> outer_loop:none 45d5d2f2ce627aa0f6920d7ae05197abd1a396e035Vladimir Marko /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none 468c6c3575668831c752820ba4174b07ee407f7a4fAart Bik /// CHECK-DAG: VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>> outer_loop:none 47f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik private static void halving_add_unsigned(char[] b1, char[] b2, char[] bo) { 48f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik int min_length = Math.min(bo.length, Math.min(b1.length, b2.length)); 49f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik for (int i = 0; i < min_length; i++) { 50f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik bo[i] = (char) ((b1[i] + b2[i]) >>> 1); 51f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik } 52f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik } 53f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik 5461b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-START: void Main.halving_add_also_unsigned(char[], char[], char[]) instruction_simplifier (before) 55f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<I1:i\d+>> IntConstant 1 loop:none 56f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<IMAX:i\d+>> IntConstant 65535 loop:none 57f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 58f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Get1:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none 59f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Get2:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none 60f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<And1:i\d+>> And [<<Get1>>,<<IMAX>>] loop:<<Loop>> outer_loop:none 61f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<And2:i\d+>> And [<<Get2>>,<<IMAX>>] loop:<<Loop>> outer_loop:none 62f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Add:i\d+>> Add [<<And1>>,<<And2>>] loop:<<Loop>> outer_loop:none 63f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<UShr:i\d+>> UShr [<<Add>>,<<I1>>] loop:<<Loop>> outer_loop:none 64f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Cnv:c\d+>> TypeConversion [<<UShr>>] loop:<<Loop>> outer_loop:none 6561b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: ArraySet [{{l\d+}},{{i\d+}},<<Cnv>>] loop:<<Loop>> outer_loop:none 6661b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko // 6761b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-START: void Main.halving_add_also_unsigned(char[], char[], char[]) loop_optimization (before) 6861b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: <<I1:i\d+>> IntConstant 1 loop:none 6961b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: <<IMAX:i\d+>> IntConstant 65535 loop:none 7061b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 7161b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: <<Get1:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none 7261b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: <<Get2:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none 7361b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: <<Add:i\d+>> Add [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none 7461b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: <<UShr:i\d+>> UShr [<<Add>>,<<I1>>] loop:<<Loop>> outer_loop:none 7561b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: <<Cnv:c\d+>> TypeConversion [<<UShr>>] loop:<<Loop>> outer_loop:none 76f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>> outer_loop:none 77f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik // 789cb7fe4daf872fd0cb312489af263ebc622033a8Aart Bik /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.halving_add_also_unsigned(char[], char[], char[]) loop_optimization (after) 798c6c3575668831c752820ba4174b07ee407f7a4fAart Bik /// CHECK-DAG: <<Get1:d\d+>> VecLoad loop:<<Loop:B\d+>> outer_loop:none 808c6c3575668831c752820ba4174b07ee407f7a4fAart Bik /// CHECK-DAG: <<Get2:d\d+>> VecLoad loop:<<Loop>> outer_loop:none 81d5d2f2ce627aa0f6920d7ae05197abd1a396e035Vladimir Marko /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none 828c6c3575668831c752820ba4174b07ee407f7a4fAart Bik /// CHECK-DAG: VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>> outer_loop:none 8319680d3655433e98582983ed0a6d44d6b4822951Goran Jakovljevic // 84f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik // Note: HAnd has no impact (already a zero extension). 85f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik // 86f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik private static void halving_add_also_unsigned(char[] b1, char[] b2, char[] bo) { 87f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik int min_length = Math.min(bo.length, Math.min(b1.length, b2.length)); 88f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik for (int i = 0; i < min_length; i++) { 89f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik bo[i] = (char) (((b1[i] & 0xffff) + (b2[i] & 0xffff)) >>> 1); 90f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik } 91f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik } 92f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik 93f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-START: void Main.rounding_halving_add_unsigned(char[], char[], char[]) loop_optimization (before) 94f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<I1:i\d+>> IntConstant 1 loop:none 95f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 96f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Get1:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none 97f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Get2:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none 98f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Add1:i\d+>> Add [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none 99f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Add2:i\d+>> Add [<<Add1>>,<<I1>>] loop:<<Loop>> outer_loop:none 100f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<UShr:i\d+>> UShr [<<Add2>>,<<I1>>] loop:<<Loop>> outer_loop:none 101f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Cnv:c\d+>> TypeConversion [<<UShr>>] loop:<<Loop>> outer_loop:none 102f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>> outer_loop:none 103f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik // 1049cb7fe4daf872fd0cb312489af263ebc622033a8Aart Bik /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.rounding_halving_add_unsigned(char[], char[], char[]) loop_optimization (after) 1058c6c3575668831c752820ba4174b07ee407f7a4fAart Bik /// CHECK-DAG: <<Get1:d\d+>> VecLoad loop:<<Loop:B\d+>> outer_loop:none 1068c6c3575668831c752820ba4174b07ee407f7a4fAart Bik /// CHECK-DAG: <<Get2:d\d+>> VecLoad loop:<<Loop>> outer_loop:none 107d5d2f2ce627aa0f6920d7ae05197abd1a396e035Vladimir Marko /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:true loop:<<Loop>> outer_loop:none 1088c6c3575668831c752820ba4174b07ee407f7a4fAart Bik /// CHECK-DAG: VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>> outer_loop:none 109f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik private static void rounding_halving_add_unsigned(char[] b1, char[] b2, char[] bo) { 110f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik int min_length = Math.min(bo.length, Math.min(b1.length, b2.length)); 111f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik for (int i = 0; i < min_length; i++) { 112f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik bo[i] = (char) ((b1[i] + b2[i] + 1) >>> 1); 113f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik } 114f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik } 115f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik 11661b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-START: void Main.rounding_halving_add_also_unsigned(char[], char[], char[]) instruction_simplifier (before) 117f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<I1:i\d+>> IntConstant 1 loop:none 118f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<IMAX:i\d+>> IntConstant 65535 loop:none 119f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 120f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Get1:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none 121f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Get2:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none 122f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<And1:i\d+>> And [<<Get1>>,<<IMAX>>] loop:<<Loop>> outer_loop:none 123f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<And2:i\d+>> And [<<Get2>>,<<IMAX>>] loop:<<Loop>> outer_loop:none 124f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Add1:i\d+>> Add [<<And1>>,<<And2>>] loop:<<Loop>> outer_loop:none 125f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Add2:i\d+>> Add [<<Add1>>,<<I1>>] loop:<<Loop>> outer_loop:none 126f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<UShr:i\d+>> UShr [<<Add2>>,<<I1>>] loop:<<Loop>> outer_loop:none 127f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Cnv:c\d+>> TypeConversion [<<UShr>>] loop:<<Loop>> outer_loop:none 12861b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: ArraySet [{{l\d+}},{{i\d+}},<<Cnv>>] loop:<<Loop>> outer_loop:none 12961b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko // 13061b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-START: void Main.rounding_halving_add_also_unsigned(char[], char[], char[]) loop_optimization (before) 13161b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: <<I1:i\d+>> IntConstant 1 loop:none 13261b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 13361b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: <<Get1:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none 13461b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: <<Get2:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none 13561b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: <<Add1:i\d+>> Add [<<Get1>>,<<Get2>>] loop:<<Loop>> outer_loop:none 13661b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: <<Add2:i\d+>> Add [<<Add1>>,<<I1>>] loop:<<Loop>> outer_loop:none 13761b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: <<UShr:i\d+>> UShr [<<Add2>>,<<I1>>] loop:<<Loop>> outer_loop:none 13861b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: <<Cnv:c\d+>> TypeConversion [<<UShr>>] loop:<<Loop>> outer_loop:none 139f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>> outer_loop:none 140f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik // 1419cb7fe4daf872fd0cb312489af263ebc622033a8Aart Bik /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.rounding_halving_add_also_unsigned(char[], char[], char[]) loop_optimization (after) 1428c6c3575668831c752820ba4174b07ee407f7a4fAart Bik /// CHECK-DAG: <<Get1:d\d+>> VecLoad loop:<<Loop:B\d+>> outer_loop:none 1438c6c3575668831c752820ba4174b07ee407f7a4fAart Bik /// CHECK-DAG: <<Get2:d\d+>> VecLoad loop:<<Loop>> outer_loop:none 144d5d2f2ce627aa0f6920d7ae05197abd1a396e035Vladimir Marko /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:true loop:<<Loop>> outer_loop:none 1458c6c3575668831c752820ba4174b07ee407f7a4fAart Bik /// CHECK-DAG: VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>> outer_loop:none 14619680d3655433e98582983ed0a6d44d6b4822951Goran Jakovljevic // 147f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik // Note: HAnd has no impact (already a zero extension). 148f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik // 149f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik private static void rounding_halving_add_also_unsigned(char[] b1, char[] b2, char[] bo) { 150f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik int min_length = Math.min(bo.length, Math.min(b1.length, b2.length)); 151f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik for (int i = 0; i < min_length; i++) { 152f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik bo[i] = (char) (((b1[i] & 0xffff) + (b2[i] & 0xffff) + 1) >>> 1); 153f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik } 154f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik } 155f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik 156f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-START: void Main.halving_add_unsigned_constant(char[], char[]) loop_optimization (before) 157f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<I1:i\d+>> IntConstant 1 loop:none 158f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535 loop:none 159f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 160f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Get:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none 161f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Add:i\d+>> Add [<<Get>>,<<UMAX>>] loop:<<Loop>> outer_loop:none 162f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<UShr:i\d+>> UShr [<<Add>>,<<I1>>] loop:<<Loop>> outer_loop:none 163f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Cnv:c\d+>> TypeConversion [<<UShr>>] loop:<<Loop>> outer_loop:none 164f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>> outer_loop:none 165f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik // 1669cb7fe4daf872fd0cb312489af263ebc622033a8Aart Bik /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.halving_add_unsigned_constant(char[], char[]) loop_optimization (after) 1678c6c3575668831c752820ba4174b07ee407f7a4fAart Bik /// CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535 loop:none 1688c6c3575668831c752820ba4174b07ee407f7a4fAart Bik /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<UMAX>>] loop:none 1698c6c3575668831c752820ba4174b07ee407f7a4fAart Bik /// CHECK-DAG: <<Get:d\d+>> VecLoad loop:<<Loop:B\d+>> outer_loop:none 170d5d2f2ce627aa0f6920d7ae05197abd1a396e035Vladimir Marko /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none 1718c6c3575668831c752820ba4174b07ee407f7a4fAart Bik /// CHECK-DAG: VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>> outer_loop:none 172f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik private static void halving_add_unsigned_constant(char[] b1, char[] bo) { 173f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik int min_length = Math.min(bo.length, b1.length); 174f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik for (int i = 0; i < min_length; i++) { 175f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik bo[i] = (char) ((b1[i] + 0xffff) >>> 1); 176f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik } 177f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik } 178f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik 17961b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-START: void Main.halving_add_also_unsigned_constant(char[], char[]) instruction_simplifier (before) 180f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<I1:i\d+>> IntConstant 1 loop:none 181f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535 loop:none 182f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 183f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Get:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none 184f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<And:i\d+>> And [<<Get>>,<<UMAX>>] loop:<<Loop>> outer_loop:none 185f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Add:i\d+>> Add [<<And>>,<<UMAX>>] loop:<<Loop>> outer_loop:none 186f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<UShr:i\d+>> UShr [<<Add>>,<<I1>>] loop:<<Loop>> outer_loop:none 187f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: <<Cnv:c\d+>> TypeConversion [<<UShr>>] loop:<<Loop>> outer_loop:none 18861b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: ArraySet [{{l\d+}},{{i\d+}},<<Cnv>>] loop:<<Loop>> outer_loop:none 18961b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko // 19061b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-START: void Main.halving_add_also_unsigned_constant(char[], char[]) loop_optimization (before) 19161b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: <<I1:i\d+>> IntConstant 1 loop:none 19261b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535 loop:none 19361b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none 19461b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: <<Get:c\d+>> ArrayGet loop:<<Loop>> outer_loop:none 19561b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: <<Add:i\d+>> Add [<<Get>>,<<UMAX>>] loop:<<Loop>> outer_loop:none 19661b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: <<UShr:i\d+>> UShr [<<Add>>,<<I1>>] loop:<<Loop>> outer_loop:none 19761b922847403ac0e74b6477114c81a28ac2e01a0Vladimir Marko /// CHECK-DAG: <<Cnv:c\d+>> TypeConversion [<<UShr>>] loop:<<Loop>> outer_loop:none 198f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>> outer_loop:none 199f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik // 2009cb7fe4daf872fd0cb312489af263ebc622033a8Aart Bik /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.halving_add_also_unsigned_constant(char[], char[]) loop_optimization (after) 2018c6c3575668831c752820ba4174b07ee407f7a4fAart Bik /// CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535 loop:none 2028c6c3575668831c752820ba4174b07ee407f7a4fAart Bik /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<UMAX>>] loop:none 2038c6c3575668831c752820ba4174b07ee407f7a4fAart Bik /// CHECK-DAG: <<Get:d\d+>> VecLoad loop:<<Loop:B\d+>> outer_loop:none 204d5d2f2ce627aa0f6920d7ae05197abd1a396e035Vladimir Marko /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none 2058c6c3575668831c752820ba4174b07ee407f7a4fAart Bik /// CHECK-DAG: VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>> outer_loop:none 20619680d3655433e98582983ed0a6d44d6b4822951Goran Jakovljevic // 207f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik // Note: HAnd has no impact (already a zero extension). 208f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik // 209f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik private static void halving_add_also_unsigned_constant(char[] b1, char[] bo) { 210f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik int min_length = Math.min(bo.length, b1.length); 211f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik for (int i = 0; i < min_length; i++) { 212f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik bo[i] = (char) (((b1[i] & 0xffff) + 0xffff) >>> 1); 213f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik } 214f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik } 215f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik 216f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik public static void main(String[] args) { 217f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik // Some interesting values. 218f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik char[] interesting = { 219f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik (char) 0x0000, 220f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik (char) 0x0001, 221f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik (char) 0x0002, 222f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik (char) 0x1234, 223f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik (char) 0x8000, 224f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik (char) 0x8001, 225f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik (char) 0x7fff, 226f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik (char) 0xffff 227f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik }; 228f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik // Initialize cross-values to test all cases, and also 229f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik // set up some extra values to exercise the cleanup loop. 230f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik for (int i = 0; i < M; i++) { 231f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik sB1[i] = (char) i; 232f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik sB2[i] = interesting[i & 7]; 233f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik } 234f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik 235f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik // Test halving add idioms. Note that the expected result is computed 236f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik // with the arithmetic >> to demonstrate the computed narrower result 237f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik // does not depend on the wider >> or >>>. 238f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik halving_add_unsigned(sB1, sB2, sBo); 239f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik for (int i = 0; i < M; i++) { 240f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik char e = (char) ((sB1[i] + sB2[i]) >> 1); 241f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik expectEquals(e, sBo[i]); 242f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik } 243f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik halving_add_also_unsigned(sB1, sB2, sBo); 244f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik for (int i = 0; i < M; i++) { 245f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik char e = (char) ((sB1[i] + sB2[i]) >> 1); 246f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik expectEquals(e, sBo[i]); 247f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik } 248f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik rounding_halving_add_unsigned(sB1, sB2, sBo); 249f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik for (int i = 0; i < M; i++) { 250f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik char e = (char) ((sB1[i] + sB2[i] + 1) >> 1); 251f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik expectEquals(e, sBo[i]); 252f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik } 253f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik rounding_halving_add_also_unsigned(sB1, sB2, sBo); 254f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik for (int i = 0; i < M; i++) { 255f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik char e = (char) ((sB1[i] + sB2[i] + 1) >> 1); 256f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik expectEquals(e, sBo[i]); 257f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik } 258f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik halving_add_unsigned_constant(sB1, sBo); 259f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik for (int i = 0; i < M; i++) { 260f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik char e = (char) ((sB1[i] + 0xffff) >> 1); 261f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik expectEquals(e, sBo[i]); 262f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik } 263f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik halving_add_also_unsigned_constant(sB1, sBo); 264f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik for (int i = 0; i < M; i++) { 265f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik char e = (char) ((sB1[i] + 0xffff) >> 1); 266f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik expectEquals(e, sBo[i]); 267f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik } 268f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik 269f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik System.out.println("passed"); 270f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik } 271f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik 272f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik private static void expectEquals(int expected, int result) { 273f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik if (expected != result) { 274f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik throw new Error("Expected: " + expected + ", found: " + result); 275f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik } 276f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik } 277f3e61ee363fe7f82ef56704f06d753e2034a67ddAart Bik} 278