diff options
-rw-r--r-- | compiler/optimizing/loop_optimization.cc | 24 | ||||
-rw-r--r-- | test/651-checker-simd-minmax/src/ByteSimdMinMax.java | 46 | ||||
-rw-r--r-- | test/651-checker-simd-minmax/src/ShortSimdMinMax.java | 46 | ||||
-rw-r--r-- | test/679-checker-minmax/src/Main.java | 84 |
4 files changed, 198 insertions, 2 deletions
diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc index 71e24de141..b41b659083 100644 --- a/compiler/optimizing/loop_optimization.cc +++ b/compiler/optimizing/loop_optimization.cc @@ -153,6 +153,18 @@ static bool IsSignExtensionAndGet(HInstruction* instruction, return false; } } + // A MIN-MAX on narrower operands qualifies as well + // (returning the operator itself). + if (instruction->IsMin() || instruction->IsMax()) { + HBinaryOperation* min_max = instruction->AsBinaryOperation(); + DCHECK(min_max->GetType() == DataType::Type::kInt32 || + min_max->GetType() == DataType::Type::kInt64); + if (IsSignExtensionAndGet(min_max->InputAt(0), type, operand) && + IsSignExtensionAndGet(min_max->InputAt(1), type, operand)) { + *operand = min_max; + return true; + } + } return false; } @@ -216,6 +228,18 @@ static bool IsZeroExtensionAndGet(HInstruction* instruction, return false; } } + // A MIN-MAX on narrower operands qualifies as well + // (returning the operator itself). + if (instruction->IsMin() || instruction->IsMax()) { + HBinaryOperation* min_max = instruction->AsBinaryOperation(); + DCHECK(min_max->GetType() == DataType::Type::kInt32 || + min_max->GetType() == DataType::Type::kInt64); + if (IsZeroExtensionAndGet(min_max->InputAt(0), type, operand) && + IsZeroExtensionAndGet(min_max->InputAt(1), type, operand)) { + *operand = min_max; + return true; + } + } return false; } diff --git a/test/651-checker-simd-minmax/src/ByteSimdMinMax.java b/test/651-checker-simd-minmax/src/ByteSimdMinMax.java index b9954947f7..8dacd5d51e 100644 --- a/test/651-checker-simd-minmax/src/ByteSimdMinMax.java +++ b/test/651-checker-simd-minmax/src/ByteSimdMinMax.java @@ -129,7 +129,7 @@ public class ByteSimdMinMax { /// CHECK-DAG: <<Cnv:b\d+>> TypeConversion [<<Min>>] loop:<<Loop>> outer_loop:none /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>> outer_loop:none // - /// CHECK-START-{ARM64,MIPS64}: void ByteSimdMinMax.doitMin100(byte[], byte[]) loop_optimization (after) + /// CHECK-START-{ARM,ARM64,MIPS64}: void ByteSimdMinMax.doitMin100(byte[], byte[]) loop_optimization (after) /// CHECK-DAG: <<I100:i\d+>> IntConstant 100 loop:none /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<I100>>] loop:none /// CHECK-DAG: <<Get:d\d+>> VecLoad loop:<<Loop:B\d+>> outer_loop:none @@ -142,6 +142,38 @@ public class ByteSimdMinMax { } } + /// CHECK-START-{ARM,ARM64,MIPS64}: void ByteSimdMinMax.doitMinMax(byte[], byte[]) loop_optimization (after) + /// CHECK-DAG: <<I11:i\d+>> IntConstant -11 loop:none + /// CHECK-DAG: <<I23:i\d+>> IntConstant 23 loop:none + /// CHECK-DAG: <<Rpl1:d\d+>> VecReplicateScalar [<<I23>>] loop:none + /// CHECK-DAG: <<Rpl2:d\d+>> VecReplicateScalar [<<I11>>] loop:none + /// CHECK-DAG: <<Get:d\d+>> VecLoad loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Min:d\d+>> VecMin [<<Get>>,<<Rpl1>>] packed_type:Int8 loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Max:d\d+>> VecMax [<<Min>>,<<Rpl2>>] packed_type:Int8 loop:<<Loop>> outer_loop:none + /// CHECK-DAG: VecStore [{{l\d+}},{{i\d+}},<<Max>>] loop:<<Loop>> outer_loop:none + private static void doitMinMax(byte[] x, byte[] y) { + int n = Math.min(x.length, y.length); + for (int i = 0; i < n; i++) { + x[i] = (byte) Math.max(-11, Math.min(y[i], 23)); + } + } + + /// CHECK-START-{ARM,ARM64,MIPS64}: void ByteSimdMinMax.doitMinMaxUnsigned(byte[], byte[]) loop_optimization (after) + /// CHECK-DAG: <<I11:i\d+>> IntConstant 11 loop:none + /// CHECK-DAG: <<I23:i\d+>> IntConstant 23 loop:none + /// CHECK-DAG: <<Rpl1:d\d+>> VecReplicateScalar [<<I23>>] loop:none + /// CHECK-DAG: <<Rpl2:d\d+>> VecReplicateScalar [<<I11>>] loop:none + /// CHECK-DAG: <<Get:d\d+>> VecLoad loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Min:d\d+>> VecMin [<<Get>>,<<Rpl1>>] packed_type:Uint8 loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Max:d\d+>> VecMax [<<Min>>,<<Rpl2>>] packed_type:Uint8 loop:<<Loop>> outer_loop:none + /// CHECK-DAG: VecStore [{{l\d+}},{{i\d+}},<<Max>>] loop:<<Loop>> outer_loop:none + private static void doitMinMaxUnsigned(byte[] x, byte[] y) { + int n = Math.min(x.length, y.length); + for (int i = 0; i < n; i++) { + x[i] = (byte) Math.max(11, Math.min(y[i] & 0xff, 23)); + } + } + public static void main() { // Initialize cross-values for all possible values. int total = 256 * 256; @@ -184,6 +216,18 @@ public class ByteSimdMinMax { byte expected = (byte) Math.min(y[i], 100); expectEquals(expected, x[i]); } + doitMinMax(x, y); + for (int i = 0; i < total; i++) { + int s = y[i]; + byte expected = (byte) (s < -11 ? -11 : (s > 23 ? 23 : s)); + expectEquals(expected, x[i]); + } + doitMinMaxUnsigned(x, y); + for (int i = 0; i < total; i++) { + int u = y[i] & 0xff; + byte expected = (byte) (u < 11 ? 11 : (u > 23 ? 23 : u)); + expectEquals(expected, x[i]); + } System.out.println("ByteSimdMinMax passed"); } diff --git a/test/651-checker-simd-minmax/src/ShortSimdMinMax.java b/test/651-checker-simd-minmax/src/ShortSimdMinMax.java index aae78914d8..9075d8007c 100644 --- a/test/651-checker-simd-minmax/src/ShortSimdMinMax.java +++ b/test/651-checker-simd-minmax/src/ShortSimdMinMax.java @@ -129,7 +129,7 @@ public class ShortSimdMinMax { /// CHECK-DAG: <<Cnv:s\d+>> TypeConversion [<<Min>>] loop:<<Loop>> outer_loop:none /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>> outer_loop:none // - /// CHECK-START-{ARM64,MIPS64}: void ShortSimdMinMax.doitMin100(short[], short[]) loop_optimization (after) + /// CHECK-START-{ARM,ARM64,MIPS64}: void ShortSimdMinMax.doitMin100(short[], short[]) loop_optimization (after) /// CHECK-DAG: <<I100:i\d+>> IntConstant 100 loop:none /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<I100>>] loop:none /// CHECK-DAG: <<Get:d\d+>> VecLoad loop:<<Loop:B\d+>> outer_loop:none @@ -142,6 +142,38 @@ public class ShortSimdMinMax { } } + /// CHECK-START-{ARM,ARM64,MIPS64}: void ShortSimdMinMax.doitMinMax(short[], short[]) loop_optimization (after) + /// CHECK-DAG: <<I11:i\d+>> IntConstant -1111 loop:none + /// CHECK-DAG: <<I23:i\d+>> IntConstant 2323 loop:none + /// CHECK-DAG: <<Rpl1:d\d+>> VecReplicateScalar [<<I23>>] loop:none + /// CHECK-DAG: <<Rpl2:d\d+>> VecReplicateScalar [<<I11>>] loop:none + /// CHECK-DAG: <<Get:d\d+>> VecLoad loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Min:d\d+>> VecMin [<<Get>>,<<Rpl1>>] packed_type:Int16 loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Max:d\d+>> VecMax [<<Min>>,<<Rpl2>>] packed_type:Int16 loop:<<Loop>> outer_loop:none + /// CHECK-DAG: VecStore [{{l\d+}},{{i\d+}},<<Max>>] loop:<<Loop>> outer_loop:none + private static void doitMinMax(short[] x, short[] y) { + int n = Math.min(x.length, y.length); + for (int i = 0; i < n; i++) { + x[i] = (short) Math.max(-1111, Math.min(y[i], 2323)); + } + } + + /// CHECK-START-{ARM,ARM64,MIPS64}: void ShortSimdMinMax.doitMinMaxUnsigned(short[], short[]) loop_optimization (after) + /// CHECK-DAG: <<I11:i\d+>> IntConstant 1111 loop:none + /// CHECK-DAG: <<I23:i\d+>> IntConstant 2323 loop:none + /// CHECK-DAG: <<Rpl1:d\d+>> VecReplicateScalar [<<I23>>] loop:none + /// CHECK-DAG: <<Rpl2:d\d+>> VecReplicateScalar [<<I11>>] loop:none + /// CHECK-DAG: <<Get:d\d+>> VecLoad loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: <<Min:d\d+>> VecMin [<<Get>>,<<Rpl1>>] packed_type:Uint16 loop:<<Loop>> outer_loop:none + /// CHECK-DAG: <<Max:d\d+>> VecMax [<<Min>>,<<Rpl2>>] packed_type:Uint16 loop:<<Loop>> outer_loop:none + /// CHECK-DAG: VecStore [{{l\d+}},{{i\d+}},<<Max>>] loop:<<Loop>> outer_loop:none + private static void doitMinMaxUnsigned(short[] x, short[] y) { + int n = Math.min(x.length, y.length); + for (int i = 0; i < n; i++) { + x[i] = (short) Math.max(1111, Math.min(y[i] & 0xffff, 2323)); + } + } + public static void main() { short[] interesting = { (short) 0x0000, (short) 0x0001, (short) 0x007f, @@ -198,6 +230,18 @@ public class ShortSimdMinMax { short expected = (short) Math.min(y[i], 100); expectEquals(expected, x[i]); } + doitMinMax(x, y); + for (int i = 0; i < total; i++) { + int s = y[i]; + short expected = (short) (s < -1111 ? -1111 : (s > 2323 ? 2323 : s)); + expectEquals(expected, x[i]); + } + doitMinMaxUnsigned(x, y); + for (int i = 0; i < total; i++) { + int u = y[i] & 0xffff; + short expected = (short) (u < 1111 ? 1111 : (u > 2323 ? 2323 : u)); + expectEquals(expected, x[i]); + } System.out.println("ShortSimdMinMax passed"); } diff --git a/test/679-checker-minmax/src/Main.java b/test/679-checker-minmax/src/Main.java index 4f0261c0a3..e330a5370e 100644 --- a/test/679-checker-minmax/src/Main.java +++ b/test/679-checker-minmax/src/Main.java @@ -20,6 +20,82 @@ public class Main { // + // Direct intrinsics. + // + + /// CHECK-START: int Main.minI(int) instruction_simplifier (before) + /// CHECK-DAG: <<Par:i\d+>> ParameterValue + /// CHECK-DAG: <<Con:i\d+>> IntConstant 20 + /// CHECK-DAG: <<Min:i\d+>> InvokeStaticOrDirect [<<Par>>,<<Con>>] intrinsic:MathMinIntInt + /// CHECK-DAG: Return [<<Min>>] + // + /// CHECK-START: int Main.minI(int) instruction_simplifier (after) + /// CHECK-DAG: <<Par:i\d+>> ParameterValue + /// CHECK-DAG: <<Con:i\d+>> IntConstant 20 + /// CHECK-DAG: <<Min:i\d+>> Min [<<Par>>,<<Con>>] + /// CHECK-DAG: Return [<<Min>>] + // + /// CHECK-START: int Main.minI(int) instruction_simplifier (after) + /// CHECK-NOT: InvokeStaticOrDirect + public static int minI(int a) { + return Math.min(a, 20); + } + + /// CHECK-START: long Main.minL(long) instruction_simplifier (before) + /// CHECK-DAG: <<Par:j\d+>> ParameterValue + /// CHECK-DAG: <<Con:j\d+>> LongConstant 20 + /// CHECK-DAG: <<Min:j\d+>> InvokeStaticOrDirect [<<Par>>,<<Con>>] intrinsic:MathMinLongLong + /// CHECK-DAG: Return [<<Min>>] + // + /// CHECK-START: long Main.minL(long) instruction_simplifier (after) + /// CHECK-DAG: <<Par:j\d+>> ParameterValue + /// CHECK-DAG: <<Con:j\d+>> LongConstant 20 + /// CHECK-DAG: <<Min:j\d+>> Min [<<Par>>,<<Con>>] + /// CHECK-DAG: Return [<<Min>>] + // + /// CHECK-START: long Main.minL(long) instruction_simplifier (after) + /// CHECK-NOT: InvokeStaticOrDirect + public static long minL(long a) { + return Math.min(a, 20L); + } + + /// CHECK-START: int Main.maxI(int) instruction_simplifier (before) + /// CHECK-DAG: <<Par:i\d+>> ParameterValue + /// CHECK-DAG: <<Con:i\d+>> IntConstant 20 + /// CHECK-DAG: <<Max:i\d+>> InvokeStaticOrDirect [<<Par>>,<<Con>>] intrinsic:MathMaxIntInt + /// CHECK-DAG: Return [<<Max>>] + // + /// CHECK-START: int Main.maxI(int) instruction_simplifier (after) + /// CHECK-DAG: <<Par:i\d+>> ParameterValue + /// CHECK-DAG: <<Con:i\d+>> IntConstant 20 + /// CHECK-DAG: <<Max:i\d+>> Max [<<Par>>,<<Con>>] + /// CHECK-DAG: Return [<<Max>>] + // + /// CHECK-START: int Main.maxI(int) instruction_simplifier (after) + /// CHECK-NOT: InvokeStaticOrDirect + public static int maxI(int a) { + return Math.max(a, 20); + } + + /// CHECK-START: long Main.maxL(long) instruction_simplifier (before) + /// CHECK-DAG: <<Par:j\d+>> ParameterValue + /// CHECK-DAG: <<Con:j\d+>> LongConstant 20 + /// CHECK-DAG: <<Max:j\d+>> InvokeStaticOrDirect [<<Par>>,<<Con>>] intrinsic:MathMaxLongLong + /// CHECK-DAG: Return [<<Max>>] + // + /// CHECK-START: long Main.maxL(long) instruction_simplifier (after) + /// CHECK-DAG: <<Par:j\d+>> ParameterValue + /// CHECK-DAG: <<Con:j\d+>> LongConstant 20 + /// CHECK-DAG: <<Max:j\d+>> Max [<<Par>>,<<Con>>] + /// CHECK-DAG: Return [<<Max>>] + // + /// CHECK-START: long Main.maxL(long) instruction_simplifier (after) + /// CHECK-NOT: InvokeStaticOrDirect + public static long maxL(long a) { + return Math.max(a, 20L); + } + + // // Different types. // @@ -343,6 +419,14 @@ public class Main { public static void main(String[] args) { // Types. + expectEquals(10, minI(10)); + expectEquals(20, minI(25)); + expectEquals(10L, minL(10L)); + expectEquals(20L, minL(25L)); + expectEquals(20, maxI(10)); + expectEquals(25, maxI(25)); + expectEquals(20L, maxL(10L)); + expectEquals(25L, maxL(25L)); expectEquals(10, min1(10, 20)); expectEquals(10, min2(10, 20)); expectEquals(10, min3(10, 20)); |