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