949 lines
39 KiB
Java
949 lines
39 KiB
Java
/*
|
|
* Copyright (C) 2020 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
public class RemTest {
|
|
private static void expectEquals(int expected, int result) {
|
|
if (expected != result) {
|
|
throw new Error("Expected: " + expected + ", found: " + result);
|
|
}
|
|
}
|
|
|
|
private static void expectEquals(long expected, long result) {
|
|
if (expected != result) {
|
|
throw new Error("Expected: " + expected + ", found: " + result);
|
|
}
|
|
}
|
|
|
|
public static void main() {
|
|
remInt();
|
|
remLong();
|
|
}
|
|
|
|
private static void remInt() {
|
|
expectEquals(0, $noinline$IntRemBy18(0));
|
|
expectEquals(1, $noinline$IntRemBy18(1));
|
|
expectEquals(-1, $noinline$IntRemBy18(-1));
|
|
expectEquals(0, $noinline$IntRemBy18(18));
|
|
expectEquals(0, $noinline$IntRemBy18(-18));
|
|
expectEquals(11, $noinline$IntRemBy18(65));
|
|
expectEquals(-11, $noinline$IntRemBy18(-65));
|
|
|
|
expectEquals(0, $noinline$IntALenRemBy18(new int[0]));
|
|
expectEquals(1, $noinline$IntALenRemBy18(new int[1]));
|
|
expectEquals(0, $noinline$IntALenRemBy18(new int[18]));
|
|
expectEquals(11, $noinline$IntALenRemBy18(new int[65]));
|
|
|
|
expectEquals(0, $noinline$IntRemByMinus18(0));
|
|
expectEquals(1, $noinline$IntRemByMinus18(1));
|
|
expectEquals(-1, $noinline$IntRemByMinus18(-1));
|
|
expectEquals(0, $noinline$IntRemByMinus18(18));
|
|
expectEquals(0, $noinline$IntRemByMinus18(-18));
|
|
expectEquals(11, $noinline$IntRemByMinus18(65));
|
|
expectEquals(-11, $noinline$IntRemByMinus18(-65));
|
|
|
|
expectEquals(0, $noinline$IntRemBy7(0));
|
|
expectEquals(1, $noinline$IntRemBy7(1));
|
|
expectEquals(-1, $noinline$IntRemBy7(-1));
|
|
expectEquals(0, $noinline$IntRemBy7(7));
|
|
expectEquals(0, $noinline$IntRemBy7(-7));
|
|
expectEquals(1, $noinline$IntRemBy7(22));
|
|
expectEquals(-1, $noinline$IntRemBy7(-22));
|
|
|
|
expectEquals(0, $noinline$IntALenRemBy7(new int[0]));
|
|
expectEquals(1, $noinline$IntALenRemBy7(new int[1]));
|
|
expectEquals(0, $noinline$IntALenRemBy7(new int[7]));
|
|
expectEquals(1, $noinline$IntALenRemBy7(new int[22]));
|
|
|
|
expectEquals(0, $noinline$IntRemByMinus7(0));
|
|
expectEquals(1, $noinline$IntRemByMinus7(1));
|
|
expectEquals(-1, $noinline$IntRemByMinus7(-1));
|
|
expectEquals(0, $noinline$IntRemByMinus7(7));
|
|
expectEquals(0, $noinline$IntRemByMinus7(-7));
|
|
expectEquals(1, $noinline$IntRemByMinus7(22));
|
|
expectEquals(-1, $noinline$IntRemByMinus7(-22));
|
|
|
|
expectEquals(0, $noinline$IntRemBy6(0));
|
|
expectEquals(1, $noinline$IntRemBy6(1));
|
|
expectEquals(-1, $noinline$IntRemBy6(-1));
|
|
expectEquals(0, $noinline$IntRemBy6(6));
|
|
expectEquals(0, $noinline$IntRemBy6(-6));
|
|
expectEquals(1, $noinline$IntRemBy6(19));
|
|
expectEquals(-1, $noinline$IntRemBy6(-19));
|
|
|
|
expectEquals(0, $noinline$IntALenRemBy6(new int[0]));
|
|
expectEquals(1, $noinline$IntALenRemBy6(new int[1]));
|
|
expectEquals(0, $noinline$IntALenRemBy6(new int[6]));
|
|
expectEquals(1, $noinline$IntALenRemBy6(new int[19]));
|
|
|
|
expectEquals(0, $noinline$IntRemByMinus6(0));
|
|
expectEquals(1, $noinline$IntRemByMinus6(1));
|
|
expectEquals(-1, $noinline$IntRemByMinus6(-1));
|
|
expectEquals(0, $noinline$IntRemByMinus6(6));
|
|
expectEquals(0, $noinline$IntRemByMinus6(-6));
|
|
expectEquals(1, $noinline$IntRemByMinus6(19));
|
|
expectEquals(-1, $noinline$IntRemByMinus6(-19));
|
|
|
|
expectEquals(1, $noinline$UnsignedIntRem01(13));
|
|
expectEquals(1, $noinline$UnsignedIntRem02(13));
|
|
expectEquals(1, $noinline$UnsignedIntRem03(13));
|
|
expectEquals(1, $noinline$UnsignedIntRem04(13));
|
|
expectEquals(1, $noinline$UnsignedIntRem05(101));
|
|
expectEquals(11, $noinline$UnsignedIntRem06(101));
|
|
|
|
expectEquals(-1, $noinline$SignedIntRem01(-13));
|
|
expectEquals(-1, $noinline$SignedIntRem02(-13));
|
|
expectEquals(1, $noinline$SignedIntRem03(-13));
|
|
expectEquals(1, $noinline$SignedIntRem04(-13, true));
|
|
expectEquals(0, $noinline$SignedIntRem05(-12, 0,-13));
|
|
expectEquals(-1, $noinline$SignedIntRem06(-13));
|
|
}
|
|
|
|
// A test case to check that 'lsr' and 'asr' are combined into one 'asr'.
|
|
// For divisor 18 seen in an MP3 decoding workload there is no need
|
|
// to correct the result of get_high(dividend * magic). So there are no
|
|
// instructions between 'lsr' and 'asr'. In such a case they can be combined
|
|
// into one 'asr'.
|
|
//
|
|
/// CHECK-START-ARM64: int RemTest.$noinline$IntRemBy18(int) disassembly (after)
|
|
/// CHECK: asr x{{\d+}}, x{{\d+}}, #34
|
|
/// CHECK-NEXT: add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
|
|
/// CHECK-NEXT: mov w{{\d+}}, #0x12
|
|
/// CHECK-NEXT: msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
|
|
private static int $noinline$IntRemBy18(int v) {
|
|
int r = v % 18;
|
|
return r;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is not generated for a non-negative
|
|
// dividend and a positive divisor.
|
|
//
|
|
/// CHECK-START-ARM: int RemTest.$noinline$IntALenRemBy18(int[]) disassembly (after)
|
|
/// CHECK: smull r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
/// CHECK-NEXT: lsr{{s?}} r{{\d+}}, #2
|
|
/// CHECK-NEXT: mov{{s?}} r{{\d+}}, #18
|
|
/// CHECK-NEXT: mls r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
//
|
|
/// CHECK-START-ARM64: int RemTest.$noinline$IntALenRemBy18(int[]) disassembly (after)
|
|
/// CHECK: lsr x{{\d+}}, x{{\d+}}, #34
|
|
/// CHECK-NEXT: mov w{{\d+}}, #0x12
|
|
/// CHECK-NEXT: msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
|
|
private static int $noinline$IntALenRemBy18(int[] arr) {
|
|
int r = arr.length % 18;
|
|
return r;
|
|
}
|
|
|
|
// A test case to check that 'lsr' and 'asr' are combined into one 'asr'.
|
|
// Divisor -18 has the same property as divisor 18: no need to correct the
|
|
// result of get_high(dividend * magic). So there are no
|
|
// instructions between 'lsr' and 'asr'. In such a case they can be combined
|
|
// into one 'asr'.
|
|
//
|
|
/// CHECK-START-ARM64: int RemTest.$noinline$IntRemByMinus18(int) disassembly (after)
|
|
/// CHECK: asr x{{\d+}}, x{{\d+}}, #34
|
|
/// CHECK-NEXT: add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
|
|
/// CHECK-NEXT: mov w{{\d+}}, #0xffffffee
|
|
/// CHECK-NEXT: msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
|
|
private static int $noinline$IntRemByMinus18(int v) {
|
|
int r = v % -18;
|
|
return r;
|
|
}
|
|
|
|
// A test case to check that 'lsr' and 'add' are combined into one 'adds'.
|
|
// For divisor 7 seen in the core library the result of get_high(dividend * magic)
|
|
// must be corrected by the 'add' instruction.
|
|
//
|
|
// The test case also checks 'add' and 'add_shift' are optimized into 'adds' and 'cinc'.
|
|
//
|
|
/// CHECK-START-ARM64: int RemTest.$noinline$IntRemBy7(int) disassembly (after)
|
|
/// CHECK: adds x{{\d+}}, x{{\d+}}, x{{\d+}}, lsl #32
|
|
/// CHECK-NEXT: asr x{{\d+}}, x{{\d+}}, #34
|
|
/// CHECK-NEXT: cinc w{{\d+}}, w{{\d+}}, mi
|
|
/// CHECK-NEXT: mov w{{\d+}}, #0x7
|
|
/// CHECK-NEXT: msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
|
|
private static int $noinline$IntRemBy7(int v) {
|
|
int r = v % 7;
|
|
return r;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is not generated for a non-negative
|
|
// dividend and a positive divisor.
|
|
//
|
|
/// CHECK-START-ARM: int RemTest.$noinline$IntALenRemBy7(int[]) disassembly (after)
|
|
/// CHECK: smull r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
/// CHECK-NEXT: add{{s?}} r{{\d+}}, r{{\d+}}
|
|
/// CHECK-NEXT: lsr{{s?}} r{{\d+}}, #2
|
|
/// CHECK-NEXT: mov{{s?}} r{{\d+}}, #7
|
|
/// CHECK-NEXT: mls r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
//
|
|
/// CHECK-START-ARM64: int RemTest.$noinline$IntALenRemBy7(int[]) disassembly (after)
|
|
/// CHECK: lsr x{{\d+}}, x{{\d+}}, #34
|
|
/// CHECK-NEXT: mov w{{\d+}}, #0x7
|
|
/// CHECK-NEXT: msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
|
|
private static int $noinline$IntALenRemBy7(int[] arr) {
|
|
int r = arr.length % 7;
|
|
return r;
|
|
}
|
|
|
|
// A test case to check that 'lsr' and 'add' are combined into one 'adds'.
|
|
// Divisor -7 has the same property as divisor 7: the result of get_high(dividend * magic)
|
|
// must be corrected. In this case it is a 'sub' instruction.
|
|
//
|
|
// The test case also checks 'sub' and 'add_shift' are optimized into 'subs' and 'cinc'.
|
|
//
|
|
/// CHECK-START-ARM64: int RemTest.$noinline$IntRemByMinus7(int) disassembly (after)
|
|
/// CHECK: subs x{{\d+}}, x{{\d+}}, x{{\d+}}, lsl #32
|
|
/// CHECK-NEXT: asr x{{\d+}}, x{{\d+}}, #34
|
|
/// CHECK-NEXT: cinc w{{\d+}}, w{{\d+}}, mi
|
|
/// CHECK-NEXT: mov w{{\d+}}, #0xfffffff9
|
|
/// CHECK-NEXT: msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
|
|
private static int $noinline$IntRemByMinus7(int v) {
|
|
int r = v % -7;
|
|
return r;
|
|
}
|
|
|
|
// A test case to check that 'asr' is used to get the high 32 bits of the result of
|
|
// 'dividend * magic'.
|
|
// For divisor 6 seen in the core library there is no need to correct the result of
|
|
// get_high(dividend * magic). Also there is no 'asr' before the final 'add' instruction
|
|
// which uses only the high 32 bits of the result. In such a case 'asr' getting the high
|
|
// 32 bits can be used as well.
|
|
//
|
|
/// CHECK-START-ARM64: int RemTest.$noinline$IntRemBy6(int) disassembly (after)
|
|
/// CHECK: asr x{{\d+}}, x{{\d+}}, #32
|
|
/// CHECK-NEXT: add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
|
|
/// CHECK-NEXT: mov w{{\d+}}, #0x6
|
|
/// CHECK-NEXT: msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
|
|
private static int $noinline$IntRemBy6(int v) {
|
|
int r = v % 6;
|
|
return r;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is not generated for a non-negative
|
|
// dividend and a positive divisor.
|
|
//
|
|
/// CHECK-START-ARM: int RemTest.$noinline$IntALenRemBy6(int[]) disassembly (after)
|
|
/// CHECK: smull r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
/// CHECK-NEXT: mov{{s?}} r{{\d+}}, #6
|
|
/// CHECK-NEXT: mls r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
//
|
|
/// CHECK-START-ARM64: int RemTest.$noinline$IntALenRemBy6(int[]) disassembly (after)
|
|
/// CHECK: lsr x{{\d+}}, x{{\d+}}, #32
|
|
/// CHECK-NEXT: mov w{{\d+}}, #0x6
|
|
/// CHECK-NEXT: msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
|
|
private static int $noinline$IntALenRemBy6(int[] arr) {
|
|
int r = arr.length % 6;
|
|
return r;
|
|
}
|
|
|
|
// A test case to check that 'asr' is used to get the high 32 bits of the result of
|
|
// 'dividend * magic'.
|
|
// Divisor -6 has the same property as divisor 6: no need to correct the result of
|
|
// get_high(dividend * magic) and no 'asr' before the final 'add' instruction
|
|
// which uses only the high 32 bits of the result. In such a case 'asr' getting the high
|
|
// 32 bits can be used as well.
|
|
//
|
|
/// CHECK-START-ARM64: int RemTest.$noinline$IntRemByMinus6(int) disassembly (after)
|
|
/// CHECK: asr x{{\d+}}, x{{\d+}}, #32
|
|
/// CHECK-NEXT: add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
|
|
/// CHECK-NEXT: mov w{{\d+}}, #0xfffffffa
|
|
/// CHECK-NEXT: msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
|
|
private static int $noinline$IntRemByMinus6(int v) {
|
|
int r = v % -6;
|
|
return r;
|
|
}
|
|
|
|
private static int $noinline$Negate(int v) {
|
|
return -v;
|
|
}
|
|
|
|
private static int $noinline$Decrement(int v) {
|
|
return v - 1;
|
|
}
|
|
|
|
private static int $noinline$Increment(int v) {
|
|
return v + 1;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is not generated for a non-negative
|
|
// dividend and a positive divisor.
|
|
//
|
|
/// CHECK-START-ARM: int RemTest.$noinline$UnsignedIntRem01(int) disassembly (after)
|
|
/// CHECK: smull r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
/// CHECK-NEXT: mov{{s?}} r{{\d+}}, #6
|
|
/// CHECK-NEXT: mls r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
//
|
|
/// CHECK-START-ARM64: int RemTest.$noinline$UnsignedIntRem01(int) disassembly (after)
|
|
/// CHECK: lsr x{{\d+}}, x{{\d+}}, #32
|
|
/// CHECK-NEXT: mov w{{\d+}}, #0x6
|
|
/// CHECK-NEXT: msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
|
|
private static int $noinline$UnsignedIntRem01(int v) {
|
|
int c = 0;
|
|
if (v > 0) {
|
|
c = v % 6;
|
|
} else {
|
|
c = $noinline$Negate(v); // This is to prevent from using Select.
|
|
}
|
|
return c;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is not generated for a non-negative
|
|
// dividend and a positive divisor.
|
|
//
|
|
/// CHECK-START-ARM: int RemTest.$noinline$UnsignedIntRem02(int) disassembly (after)
|
|
/// CHECK: smull r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
/// CHECK-NEXT: mov{{s?}} r{{\d+}}, #6
|
|
/// CHECK-NEXT: mls r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
//
|
|
/// CHECK-START-ARM64: int RemTest.$noinline$UnsignedIntRem02(int) disassembly (after)
|
|
/// CHECK: lsr x{{\d+}}, x{{\d+}}, #32
|
|
/// CHECK-NEXT: mov w{{\d+}}, #0x6
|
|
/// CHECK-NEXT: msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
|
|
private static int $noinline$UnsignedIntRem02(int v) {
|
|
int c = 0;
|
|
if (0 < v) {
|
|
c = v % 6;
|
|
} else {
|
|
c = $noinline$Negate(v); // This is to prevent from using Select.
|
|
}
|
|
return c;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is not generated for a non-negative
|
|
// dividend and a positive divisor.
|
|
//
|
|
/// CHECK-START-ARM: int RemTest.$noinline$UnsignedIntRem03(int) disassembly (after)
|
|
/// CHECK: smull r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
/// CHECK-NEXT: mov{{s?}} r{{\d+}}, #6
|
|
/// CHECK-NEXT: mls r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
//
|
|
/// CHECK-START-ARM64: int RemTest.$noinline$UnsignedIntRem03(int) disassembly (after)
|
|
/// CHECK: lsr x{{\d+}}, x{{\d+}}, #32
|
|
/// CHECK-NEXT: mov w{{\d+}}, #0x6
|
|
/// CHECK-NEXT: msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
|
|
private static int $noinline$UnsignedIntRem03(int v) {
|
|
int c = 0;
|
|
if (v >= 0) {
|
|
c = v % 6;
|
|
} else {
|
|
c = $noinline$Negate(v); // This is to prevent from using Select.
|
|
}
|
|
return c;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is not generated for a non-negative
|
|
// dividend and a positive divisor.
|
|
//
|
|
/// CHECK-START-ARM: int RemTest.$noinline$UnsignedIntRem04(int) disassembly (after)
|
|
/// CHECK: smull r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
/// CHECK-NEXT: mov{{s?}} r{{\d+}}, #6
|
|
/// CHECK-NEXT: mls r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
//
|
|
/// CHECK-START-ARM64: int RemTest.$noinline$UnsignedIntRem04(int) disassembly (after)
|
|
/// CHECK: lsr x{{\d+}}, x{{\d+}}, #32
|
|
/// CHECK-NEXT: mov w{{\d+}}, #0x6
|
|
/// CHECK-NEXT: msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
|
|
private static int $noinline$UnsignedIntRem04(int v) {
|
|
int c = 0;
|
|
if (0 <= v) {
|
|
c = v % 6;
|
|
} else {
|
|
c = $noinline$Negate(v); // This is to prevent from using Select.
|
|
}
|
|
return c;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is not generated for a non-negative
|
|
// dividend and a positive divisor.
|
|
//
|
|
/// CHECK-START-ARM: int RemTest.$noinline$UnsignedIntRem05(int) disassembly (after)
|
|
/// CHECK: smull r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
/// CHECK-NEXT: lsr{{s?}} r{{\d+}}, #2
|
|
/// CHECK-NEXT: mov{{s?}} r{{\d+}}, #10
|
|
/// CHECK-NEXT: mls r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
//
|
|
/// CHECK-START-ARM64: int RemTest.$noinline$UnsignedIntRem05(int) disassembly (after)
|
|
/// CHECK: lsr x{{\d+}}, x{{\d+}}, #34
|
|
/// CHECK-NEXT: mov w{{\d+}}, #0xa
|
|
/// CHECK-NEXT: msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
|
|
private static int $noinline$UnsignedIntRem05(int v) {
|
|
int c = 0;
|
|
for(; v > 100; ++c) {
|
|
v %= 10;
|
|
}
|
|
return c;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is not generated for a non-negative
|
|
// dividend and a positive divisor.
|
|
//
|
|
/// CHECK-START-ARM: int RemTest.$noinline$UnsignedIntRem06(int) disassembly (after)
|
|
/// CHECK: smull r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
/// CHECK-NEXT: lsr{{s?}} r{{\d+}}, r{{\d+}}, #2
|
|
/// CHECK: mls r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
//
|
|
/// CHECK-START-ARM64: int RemTest.$noinline$UnsignedIntRem06(int) disassembly (after)
|
|
/// CHECK: smull x{{\d+}}, w{{\d+}}, w{{\d+}}
|
|
/// CHECK-NEXT: lsr x{{\d+}}, x{{\d+}}, #34
|
|
/// CHECK: msub w{{\d+}}, w{{\d+}}, w{{\d+}}, w{{\d+}}
|
|
private static int $noinline$UnsignedIntRem06(int v) {
|
|
if (v < 10) {
|
|
v = $noinline$Negate(v); // This is to prevent from using Select.
|
|
} else {
|
|
v = (v % 10) + (v / 10);
|
|
}
|
|
return v;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is generated for a negative
|
|
// dividend and a positive divisor.
|
|
//
|
|
/// CHECK-START-ARM: int RemTest.$noinline$SignedIntRem01(int) disassembly (after)
|
|
/// CHECK: smull r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
/// CHECK-NEXT: sub r{{\d+}}, r{{\d+}}, asr #31
|
|
/// CHECK-NEXT: mov{{s?}} r{{\d+}}, #6
|
|
/// CHECK-NEXT: mls r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
//
|
|
/// CHECK-START-ARM64: int RemTest.$noinline$SignedIntRem01(int) disassembly (after)
|
|
/// CHECK: asr x{{\d+}}, x{{\d+}}, #32
|
|
/// CHECK-NEXT: add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
|
|
private static int $noinline$SignedIntRem01(int v) {
|
|
int c = 0;
|
|
if (v < 0) {
|
|
c = v % 6;
|
|
} else {
|
|
c = $noinline$Decrement(v); // This is to prevent from using Select.
|
|
}
|
|
return c;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is generated for a negative
|
|
// dividend and a positive divisor.
|
|
//
|
|
/// CHECK-START-ARM: int RemTest.$noinline$SignedIntRem02(int) disassembly (after)
|
|
/// CHECK: smull r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
/// CHECK-NEXT: sub r{{\d+}}, r{{\d+}}, asr #31
|
|
/// CHECK-NEXT: mov{{s?}} r{{\d+}}, #6
|
|
/// CHECK-NEXT: mls r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
//
|
|
/// CHECK-START-ARM64: int RemTest.$noinline$SignedIntRem02(int) disassembly (after)
|
|
/// CHECK: asr x{{\d+}}, x{{\d+}}, #32
|
|
/// CHECK-NEXT: add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
|
|
private static int $noinline$SignedIntRem02(int v) {
|
|
int c = 0;
|
|
if (v <= 0) {
|
|
c = v % 6;
|
|
} else {
|
|
c = $noinline$Decrement(v); // This is to prevent from using Select.
|
|
}
|
|
return c;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is generated for signed division.
|
|
//
|
|
/// CHECK-START-ARM: int RemTest.$noinline$SignedIntRem03(int) disassembly (after)
|
|
/// CHECK: smull r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
/// CHECK-NEXT: sub r{{\d+}}, r{{\d+}}, asr #31
|
|
/// CHECK-NEXT: mov{{s?}} r{{\d+}}, #6
|
|
/// CHECK-NEXT: mls r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
//
|
|
/// CHECK-START-ARM64: int RemTest.$noinline$SignedIntRem03(int) disassembly (after)
|
|
/// CHECK: asr x{{\d+}}, x{{\d+}}, #32
|
|
/// CHECK-NEXT: add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
|
|
private static int $noinline$SignedIntRem03(int v) {
|
|
boolean positive = (v > 0);
|
|
int c = v % 6;
|
|
if (!positive) {
|
|
c = $noinline$Negate(c); // This is to prevent from using Select.
|
|
}
|
|
return c;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is generated for signed division.
|
|
//
|
|
/// CHECK-START-ARM: int RemTest.$noinline$SignedIntRem04(int, boolean) disassembly (after)
|
|
/// CHECK: smull r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
/// CHECK-NEXT: sub r{{\d+}}, r{{\d+}}, asr #31
|
|
/// CHECK-NEXT: mov{{s?}} r{{\d+}}, #6
|
|
/// CHECK-NEXT: mls r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
//
|
|
/// CHECK-START-ARM64: int RemTest.$noinline$SignedIntRem04(int, boolean) disassembly (after)
|
|
/// CHECK: asr x{{\d+}}, x{{\d+}}, #32
|
|
/// CHECK-NEXT: add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
|
|
private static int $noinline$SignedIntRem04(int v, boolean apply_rem) {
|
|
int c = 0;
|
|
boolean positive = (v > 0);
|
|
if (apply_rem) {
|
|
c = v % 6;
|
|
} else {
|
|
c = $noinline$Decrement(v); // This is to prevent from using Select.
|
|
}
|
|
if (!positive) {
|
|
c = $noinline$Negate(c); // This is to prevent from using Select.
|
|
}
|
|
return c;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is generated for signed division.
|
|
//
|
|
/// CHECK-START-ARM: int RemTest.$noinline$SignedIntRem05(int, int, int) disassembly (after)
|
|
/// CHECK: smull r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
/// CHECK-NEXT: sub r{{\d+}}, r{{\d+}}, asr #31
|
|
/// CHECK-NEXT: mov{{s?}} r{{\d+}}, #6
|
|
/// CHECK-NEXT: mls r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
//
|
|
/// CHECK-START-ARM64: int RemTest.$noinline$SignedIntRem05(int, int, int) disassembly (after)
|
|
/// CHECK: asr x{{\d+}}, x{{\d+}}, #32
|
|
/// CHECK-NEXT: add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
|
|
private static int $noinline$SignedIntRem05(int v, int a, int b) {
|
|
int c = 0;
|
|
|
|
if (v < a)
|
|
c = $noinline$Increment(c); // This is to prevent from using Select.
|
|
|
|
if (b < a)
|
|
c = $noinline$Increment(c); // This is to prevent from using Select.
|
|
|
|
if (v > b) {
|
|
c = v % 6;
|
|
} else {
|
|
c = $noinline$Increment(c); // This is to prevent from using Select.
|
|
}
|
|
|
|
return c;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is generated for signed division.
|
|
//
|
|
/// CHECK-START-ARM: int RemTest.$noinline$SignedIntRem06(int) disassembly (after)
|
|
/// CHECK: smull r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
/// CHECK-NEXT: sub r{{\d+}}, r{{\d+}}, asr #31
|
|
/// CHECK-NEXT: mov{{s?}} r{{\d+}}, #6
|
|
/// CHECK-NEXT: mls r{{\d+}}, r{{\d+}}, r{{\d+}}, r{{\d+}}
|
|
//
|
|
/// CHECK-START-ARM64: int RemTest.$noinline$SignedIntRem06(int) disassembly (after)
|
|
/// CHECK: asr x{{\d+}}, x{{\d+}}, #32
|
|
/// CHECK-NEXT: add w{{\d+}}, w{{\d+}}, w{{\d+}}, lsr #31
|
|
private static int $noinline$SignedIntRem06(int v) {
|
|
int c = v % 6;
|
|
|
|
if (v > 0) {
|
|
c = $noinline$Negate(c); // This is to prevent from using Select.
|
|
}
|
|
|
|
return c;
|
|
}
|
|
|
|
private static void remLong() {
|
|
expectEquals(0L, $noinline$LongRemBy18(0L));
|
|
expectEquals(1L, $noinline$LongRemBy18(1L));
|
|
expectEquals(-1L, $noinline$LongRemBy18(-1L));
|
|
expectEquals(0L, $noinline$LongRemBy18(18L));
|
|
expectEquals(0L, $noinline$LongRemBy18(-18L));
|
|
expectEquals(11L, $noinline$LongRemBy18(65L));
|
|
expectEquals(-11L, $noinline$LongRemBy18(-65L));
|
|
|
|
expectEquals(0L, $noinline$LongRemByMinus18(0L));
|
|
expectEquals(1L, $noinline$LongRemByMinus18(1L));
|
|
expectEquals(-1L, $noinline$LongRemByMinus18(-1L));
|
|
expectEquals(0L, $noinline$LongRemByMinus18(18L));
|
|
expectEquals(0L, $noinline$LongRemByMinus18(-18L));
|
|
expectEquals(11L, $noinline$LongRemByMinus18(65L));
|
|
expectEquals(-11L, $noinline$LongRemByMinus18(-65L));
|
|
|
|
expectEquals(0L, $noinline$LongRemBy7(0L));
|
|
expectEquals(1L, $noinline$LongRemBy7(1L));
|
|
expectEquals(-1L, $noinline$LongRemBy7(-1L));
|
|
expectEquals(0L, $noinline$LongRemBy7(7L));
|
|
expectEquals(0L, $noinline$LongRemBy7(-7L));
|
|
expectEquals(1L, $noinline$LongRemBy7(22L));
|
|
expectEquals(-1L, $noinline$LongRemBy7(-22L));
|
|
|
|
expectEquals(0L, $noinline$LongRemByMinus7(0L));
|
|
expectEquals(1L, $noinline$LongRemByMinus7(1L));
|
|
expectEquals(-1L, $noinline$LongRemByMinus7(-1L));
|
|
expectEquals(0L, $noinline$LongRemByMinus7(7L));
|
|
expectEquals(0L, $noinline$LongRemByMinus7(-7L));
|
|
expectEquals(1L, $noinline$LongRemByMinus7(22L));
|
|
expectEquals(-1L, $noinline$LongRemByMinus7(-22L));
|
|
|
|
expectEquals(0L, $noinline$LongRemBy6(0L));
|
|
expectEquals(1L, $noinline$LongRemBy6(1L));
|
|
expectEquals(-1L, $noinline$LongRemBy6(-1L));
|
|
expectEquals(0L, $noinline$LongRemBy6(6L));
|
|
expectEquals(0L, $noinline$LongRemBy6(-6L));
|
|
expectEquals(1L, $noinline$LongRemBy6(19L));
|
|
expectEquals(-1L, $noinline$LongRemBy6(-19L));
|
|
|
|
expectEquals(0L, $noinline$LongRemByMinus6(0L));
|
|
expectEquals(1L, $noinline$LongRemByMinus6(1L));
|
|
expectEquals(-1L, $noinline$LongRemByMinus6(-1L));
|
|
expectEquals(0L, $noinline$LongRemByMinus6(6L));
|
|
expectEquals(0L, $noinline$LongRemByMinus6(-6L));
|
|
expectEquals(1L, $noinline$LongRemByMinus6(19L));
|
|
expectEquals(-1L, $noinline$LongRemByMinus6(-19L));
|
|
|
|
expectEquals(0L, $noinline$LongRemBy100(0L));
|
|
expectEquals(1L, $noinline$LongRemBy100(1L));
|
|
expectEquals(-1L, $noinline$LongRemBy100(-1L));
|
|
expectEquals(0L, $noinline$LongRemBy100(100L));
|
|
expectEquals(0L, $noinline$LongRemBy100(-100L));
|
|
expectEquals(1L, $noinline$LongRemBy100(101L));
|
|
expectEquals(-1L, $noinline$LongRemBy100(-101L));
|
|
|
|
expectEquals(0L, $noinline$LongRemByMinus100(0L));
|
|
expectEquals(1L, $noinline$LongRemByMinus100(1L));
|
|
expectEquals(-1L, $noinline$LongRemByMinus100(-1L));
|
|
expectEquals(0L, $noinline$LongRemByMinus100(100L));
|
|
expectEquals(0L, $noinline$LongRemByMinus100(-100L));
|
|
expectEquals(1L, $noinline$LongRemByMinus100(101L));
|
|
expectEquals(-1L, $noinline$LongRemByMinus100(-101L));
|
|
|
|
expectEquals(1L, $noinline$UnsignedLongRem01(13L));
|
|
expectEquals(1L, $noinline$UnsignedLongRem02(13L));
|
|
expectEquals(1L, $noinline$UnsignedLongRem03(13L));
|
|
expectEquals(1L, $noinline$UnsignedLongRem04(13L));
|
|
expectEquals(1L, $noinline$UnsignedLongRem05(101L));
|
|
expectEquals(11L, $noinline$UnsignedLongRem06(101L));
|
|
|
|
expectEquals(-1L, $noinline$SignedLongRem01(-13L));
|
|
expectEquals(-1L, $noinline$SignedLongRem02(-13L));
|
|
expectEquals(1L, $noinline$SignedLongRem03(-13L));
|
|
expectEquals(1L, $noinline$SignedLongRem04(-13L, true));
|
|
expectEquals(0L, $noinline$SignedLongRem05(-12L, 0L,-13L));
|
|
expectEquals(-1L, $noinline$SignedLongRem06(-13L));
|
|
}
|
|
|
|
// Test cases for Int64 HDiv/HRem to check that optimizations implemented for Int32 are not
|
|
// used for Int64. The same divisors 18, -18, 7, -7, 6 and -6 are used.
|
|
|
|
/// CHECK-START-ARM64: long RemTest.$noinline$LongRemBy18(long) disassembly (after)
|
|
/// CHECK: smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
/// CHECK-NEXT: add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
|
|
/// CHECK-NEXT: mov x{{\d+}}, #0x12
|
|
/// CHECK-NEXT: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
private static long $noinline$LongRemBy18(long v) {
|
|
long r = v % 18L;
|
|
return r;
|
|
}
|
|
|
|
/// CHECK-START-ARM64: long RemTest.$noinline$LongRemByMinus18(long) disassembly (after)
|
|
/// CHECK: smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
/// CHECK-NEXT: add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
|
|
/// CHECK-NEXT: mov x{{\d+}}, #0xffffffffffffffee
|
|
/// CHECK-NEXT: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
private static long $noinline$LongRemByMinus18(long v) {
|
|
long r = v % -18L;
|
|
return r;
|
|
}
|
|
|
|
/// CHECK-START-ARM64: long RemTest.$noinline$LongRemBy7(long) disassembly (after)
|
|
/// CHECK: smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
/// CHECK-NEXT: asr x{{\d+}}, x{{\d+}}, #1
|
|
/// CHECK-NEXT: add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
|
|
/// CHECK-NEXT: mov x{{\d+}}, #0x7
|
|
/// CHECK-NEXT: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
private static long $noinline$LongRemBy7(long v) {
|
|
long r = v % 7L;
|
|
return r;
|
|
}
|
|
|
|
/// CHECK-START-ARM64: long RemTest.$noinline$LongRemByMinus7(long) disassembly (after)
|
|
/// CHECK: smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
/// CHECK-NEXT: asr x{{\d+}}, x{{\d+}}, #1
|
|
/// CHECK-NEXT: add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
|
|
/// CHECK-NEXT: mov x{{\d+}}, #0xfffffffffffffff9
|
|
/// CHECK-NEXT: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
private static long $noinline$LongRemByMinus7(long v) {
|
|
long r = v % -7L;
|
|
return r;
|
|
}
|
|
|
|
/// CHECK-START-ARM64: long RemTest.$noinline$LongRemBy6(long) disassembly (after)
|
|
/// CHECK: smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
/// CHECK-NEXT: add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
|
|
/// CHECK-NEXT: mov x{{\d+}}, #0x6
|
|
/// CHECK-NEXT: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
private static long $noinline$LongRemBy6(long v) {
|
|
long r = v % 6L;
|
|
return r;
|
|
}
|
|
|
|
/// CHECK-START-ARM64: long RemTest.$noinline$LongRemByMinus6(long) disassembly (after)
|
|
/// CHECK: smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
/// CHECK-NEXT: add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
|
|
/// CHECK-NEXT: mov x{{\d+}}, #0xfffffffffffffffa
|
|
/// CHECK-NEXT: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
private static long $noinline$LongRemByMinus6(long v) {
|
|
long r = v % -6L;
|
|
return r;
|
|
}
|
|
|
|
// A test to check 'add' and 'add_shift' are optimized into 'adds' and 'cinc'.
|
|
//
|
|
/// CHECK-START-ARM64: long RemTest.$noinline$LongRemBy100(long) disassembly (after)
|
|
/// CHECK: smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
/// CHECK-NEXT: adds x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
/// CHECK-NEXT: asr x{{\d+}}, x{{\d+}}, #6
|
|
/// CHECK-NEXT: cinc x{{\d+}}, x{{\d+}}, mi
|
|
/// CHECK-NEXT: mov x{{\d+}}, #0x64
|
|
/// CHECK-NEXT: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
private static long $noinline$LongRemBy100(long v) {
|
|
long r = v % 100L;
|
|
return r;
|
|
}
|
|
|
|
// A test to check 'sub' and 'add_shift' are optimized into 'subs' and 'cinc'.
|
|
//
|
|
/// CHECK-START-ARM64: long RemTest.$noinline$LongRemByMinus100(long) disassembly (after)
|
|
/// CHECK: smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
/// CHECK-NEXT: subs x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
/// CHECK-NEXT: asr x{{\d+}}, x{{\d+}}, #6
|
|
/// CHECK-NEXT: cinc x{{\d+}}, x{{\d+}}, mi
|
|
/// CHECK-NEXT: mov x{{\d+}}, #0xffffffffffffff9c
|
|
/// CHECK-NEXT: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
private static long $noinline$LongRemByMinus100(long v) {
|
|
long r = v % -100L;
|
|
return r;
|
|
}
|
|
|
|
private static long $noinline$Negate(long v) {
|
|
return -v;
|
|
}
|
|
|
|
private static long $noinline$Decrement(long v) {
|
|
return v - 1;
|
|
}
|
|
|
|
private static long $noinline$Increment(long v) {
|
|
return v + 1;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is not generated for a non-negative
|
|
// dividend and a positive divisor.
|
|
//
|
|
/// CHECK-START-ARM64: long RemTest.$noinline$UnsignedLongRem01(long) disassembly (after)
|
|
/// CHECK: smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
/// CHECK-NEXT: mov x{{\d+}}, #0x6
|
|
/// CHECK-NEXT: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
private static long $noinline$UnsignedLongRem01(long v) {
|
|
long c = 0;
|
|
if (v > 0) {
|
|
c = v % 6;
|
|
} else {
|
|
c = $noinline$Negate(v); // This is to prevent from using Select.
|
|
}
|
|
return c;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is not generated for a non-negative
|
|
// dividend and a positive divisor.
|
|
//
|
|
/// CHECK-START-ARM64: long RemTest.$noinline$UnsignedLongRem02(long) disassembly (after)
|
|
/// CHECK: smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
/// CHECK-NEXT: mov x{{\d+}}, #0x6
|
|
/// CHECK-NEXT: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
private static long $noinline$UnsignedLongRem02(long v) {
|
|
long c = 0;
|
|
if (0 < v) {
|
|
c = v % 6;
|
|
} else {
|
|
c = $noinline$Negate(v); // This is to prevent from using Select.
|
|
}
|
|
return c;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is not generated for a non-negative
|
|
// dividend and a positive divisor.
|
|
//
|
|
/// CHECK-START-ARM64: long RemTest.$noinline$UnsignedLongRem03(long) disassembly (after)
|
|
/// CHECK: smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
/// CHECK-NEXT: mov x{{\d+}}, #0x6
|
|
/// CHECK-NEXT: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
private static long $noinline$UnsignedLongRem03(long v) {
|
|
long c = 0;
|
|
if (v >= 0) {
|
|
c = v % 6;
|
|
} else {
|
|
c = $noinline$Negate(v); // This is to prevent from using Select.
|
|
}
|
|
return c;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is not generated for a non-negative
|
|
// dividend and a positive divisor.
|
|
//
|
|
/// CHECK-START-ARM64: long RemTest.$noinline$UnsignedLongRem04(long) disassembly (after)
|
|
/// CHECK: smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
/// CHECK-NEXT: mov x{{\d+}}, #0x6
|
|
/// CHECK-NEXT: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
private static long $noinline$UnsignedLongRem04(long v) {
|
|
long c = 0;
|
|
if (0 <= v) {
|
|
c = v % 6;
|
|
} else {
|
|
c = $noinline$Negate(v); // This is to prevent from using Select.
|
|
}
|
|
return c;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is not generated for a non-negative
|
|
// dividend and a positive divisor.
|
|
//
|
|
/// CHECK-START-ARM64: long RemTest.$noinline$UnsignedLongRem05(long) disassembly (after)
|
|
/// CHECK: smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
/// CHECK-NEXT: lsr x{{\d+}}, x{{\d+}}, #2
|
|
/// CHECK-NEXT: mov x{{\d+}}, #0xa
|
|
/// CHECK-NEXT: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
private static long $noinline$UnsignedLongRem05(long v) {
|
|
long c = 0;
|
|
for(; v > 100; ++c) {
|
|
v %= 10;
|
|
}
|
|
return c;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is not generated for a non-negative
|
|
// dividend and a positive divisor.
|
|
//
|
|
/// CHECK-START-ARM64: long RemTest.$noinline$UnsignedLongRem06(long) disassembly (after)
|
|
/// CHECK: smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
/// CHECK-NEXT: lsr x{{\d+}}, x{{\d+}}, #2
|
|
/// CHECK: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
private static long $noinline$UnsignedLongRem06(long v) {
|
|
if (v < 10) {
|
|
v = $noinline$Negate(v); // This is to prevent from using Select.
|
|
} else {
|
|
v = (v % 10) + (v / 10);
|
|
}
|
|
return v;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is generated for a negative
|
|
// dividend and a positive divisor.
|
|
//
|
|
/// CHECK-START-ARM64: long RemTest.$noinline$SignedLongRem01(long) disassembly (after)
|
|
/// CHECK: smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
/// CHECK-NEXT: add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
|
|
/// CHECK-NEXT: mov x{{\d+}}, #0x6
|
|
/// CHECK-NEXT: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
private static long $noinline$SignedLongRem01(long v) {
|
|
long c = 0;
|
|
if (v < 0) {
|
|
c = v % 6;
|
|
} else {
|
|
c = $noinline$Decrement(v); // This is to prevent from using Select.
|
|
}
|
|
return c;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is generated for a negative
|
|
// dividend and a positive divisor.
|
|
//
|
|
/// CHECK-START-ARM64: long RemTest.$noinline$SignedLongRem02(long) disassembly (after)
|
|
/// CHECK: smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
/// CHECK-NEXT: add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
|
|
/// CHECK-NEXT: mov x{{\d+}}, #0x6
|
|
/// CHECK-NEXT: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
private static long $noinline$SignedLongRem02(long v) {
|
|
long c = 0;
|
|
if (v <= 0) {
|
|
c = v % 6;
|
|
} else {
|
|
c = $noinline$Decrement(v); // This is to prevent from using Select.
|
|
}
|
|
return c;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is generated for signed division.
|
|
//
|
|
/// CHECK-START-ARM64: long RemTest.$noinline$SignedLongRem03(long) disassembly (after)
|
|
/// CHECK: smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
/// CHECK-NEXT: add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
|
|
/// CHECK-NEXT: mov x{{\d+}}, #0x6
|
|
/// CHECK-NEXT: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
private static long $noinline$SignedLongRem03(long v) {
|
|
boolean positive = (v > 0);
|
|
long c = v % 6;
|
|
if (!positive) {
|
|
c = $noinline$Negate(c); // This is to prevent from using Select.
|
|
}
|
|
return c;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is generated for signed division.
|
|
//
|
|
/// CHECK-START-ARM64: long RemTest.$noinline$SignedLongRem04(long, boolean) disassembly (after)
|
|
/// CHECK: smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
/// CHECK-NEXT: add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
|
|
/// CHECK-NEXT: mov x{{\d+}}, #0x6
|
|
/// CHECK-NEXT: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
private static long $noinline$SignedLongRem04(long v, boolean apply_rem) {
|
|
long c = 0;
|
|
boolean positive = (v > 0);
|
|
if (apply_rem) {
|
|
c = v % 6;
|
|
} else {
|
|
c = $noinline$Decrement(v); // This is to prevent from using Select.
|
|
}
|
|
if (!positive) {
|
|
c = $noinline$Negate(c); // This is to prevent from using Select.
|
|
}
|
|
return c;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is generated for signed division.
|
|
//
|
|
/// CHECK-START-ARM64: long RemTest.$noinline$SignedLongRem05(long, long, long) disassembly (after)
|
|
/// CHECK: smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
/// CHECK-NEXT: add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
|
|
/// CHECK-NEXT: mov x{{\d+}}, #0x6
|
|
/// CHECK-NEXT: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
private static long $noinline$SignedLongRem05(long v, long a, long b) {
|
|
long c = 0;
|
|
|
|
if (v < a)
|
|
c = $noinline$Increment(c); // This is to prevent from using Select.
|
|
|
|
if (b < a)
|
|
c = $noinline$Increment(c); // This is to prevent from using Select.
|
|
|
|
if (v > b) {
|
|
c = v % 6;
|
|
} else {
|
|
c = $noinline$Increment(c); // This is to prevent from using Select.
|
|
}
|
|
|
|
return c;
|
|
}
|
|
|
|
// A test case to check that a correcting 'add' is generated for signed division.
|
|
//
|
|
/// CHECK-START-ARM64: long RemTest.$noinline$SignedLongRem06(long) disassembly (after)
|
|
/// CHECK: smulh x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
/// CHECK-NEXT: add x{{\d+}}, x{{\d+}}, x{{\d+}}, lsr #63
|
|
/// CHECK-NEXT: mov x{{\d+}}, #0x6
|
|
/// CHECK-NEXT: msub x{{\d+}}, x{{\d+}}, x{{\d+}}, x{{\d+}}
|
|
private static long $noinline$SignedLongRem06(long v) {
|
|
long c = v % 6;
|
|
|
|
if (v > 0) {
|
|
c = $noinline$Negate(c); // This is to prevent from using Select.
|
|
}
|
|
|
|
return c;
|
|
}
|
|
}
|