diff options
Diffstat (limited to 'test/2047-checker-const-string-length')
5 files changed, 271 insertions, 0 deletions
diff --git a/test/2047-checker-const-string-length/Android.bp b/test/2047-checker-const-string-length/Android.bp new file mode 100644 index 0000000000..41cbfd3b8a --- /dev/null +++ b/test/2047-checker-const-string-length/Android.bp @@ -0,0 +1,43 @@ +// Generated by `regen-test-files`. Do not edit manually. + +// Build rules for ART run-test `2047-checker-const-string-length`. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "art_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["art_license"], +} + +// Test's Dex code. +java_test { + name: "art-run-test-2047-checker-const-string-length", + defaults: ["art-run-test-defaults"], + test_config_template: ":art-run-test-target-template", + srcs: ["src/**/*.java"], + data: [ + ":art-run-test-2047-checker-const-string-length-expected-stdout", + ":art-run-test-2047-checker-const-string-length-expected-stderr", + ], + // Include the Java source files in the test's artifacts, to make Checker assertions + // available to the TradeFed test runner. + include_srcs: true, +} + +// Test's expected standard output. +genrule { + name: "art-run-test-2047-checker-const-string-length-expected-stdout", + out: ["art-run-test-2047-checker-const-string-length-expected-stdout.txt"], + srcs: ["expected-stdout.txt"], + cmd: "cp -f $(in) $(out)", +} + +// Test's expected standard error. +genrule { + name: "art-run-test-2047-checker-const-string-length-expected-stderr", + out: ["art-run-test-2047-checker-const-string-length-expected-stderr.txt"], + srcs: ["expected-stderr.txt"], + cmd: "cp -f $(in) $(out)", +} diff --git a/test/2047-checker-const-string-length/expected-stderr.txt b/test/2047-checker-const-string-length/expected-stderr.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/2047-checker-const-string-length/expected-stderr.txt diff --git a/test/2047-checker-const-string-length/expected-stdout.txt b/test/2047-checker-const-string-length/expected-stdout.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/2047-checker-const-string-length/expected-stdout.txt diff --git a/test/2047-checker-const-string-length/info.txt b/test/2047-checker-const-string-length/info.txt new file mode 100644 index 0000000000..61e987f8fb --- /dev/null +++ b/test/2047-checker-const-string-length/info.txt @@ -0,0 +1 @@ +Tests that we optimize String's length()/isEmpty() for constant strings. diff --git a/test/2047-checker-const-string-length/src/Main.java b/test/2047-checker-const-string-length/src/Main.java new file mode 100644 index 0000000000..0130943cda --- /dev/null +++ b/test/2047-checker-const-string-length/src/Main.java @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2023 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. + */ + +// Note that the empty string is present in the BootImage but the other one is a BSS string. We are +// testing both AOT LoadString kinds. + +public class Main { + public static void main(String[] args) { + $noinline$testLength(); + $noinline$testIsEmpty(); + } + + private static void $noinline$testLength() { + assertEquals(0, $noinline$testLengthEmptyString()); + assertEquals(0, $noinline$testLengthEmptyStringWithInline()); + assertEquals(32, $noinline$testLengthBssString()); + assertEquals(32, $noinline$testLengthBssStringWithInline()); + } + + /// CHECK-START: int Main.$noinline$testLengthEmptyString() constant_folding (before) + /// CHECK: LoadString load_kind:BootImageRelRo + /// CHECK: <<Length:i\d+>> ArrayLength + /// CHECK: Return [<<Length>>] + + /// CHECK-START: int Main.$noinline$testLengthEmptyString() constant_folding (after) + /// CHECK: <<Const0:i\d+>> IntConstant 0 + /// CHECK: Return [<<Const0>>] + + /// CHECK-START: int Main.$noinline$testLengthEmptyString() dead_code_elimination$initial (after) + /// CHECK-NOT: LoadString + + /// CHECK-START: int Main.$noinline$testLengthEmptyString() dead_code_elimination$initial (after) + /// CHECK-NOT: ArrayLength + private static int $noinline$testLengthEmptyString() { + String str = ""; + return str.length(); + } + + /// CHECK-START: int Main.$noinline$testLengthEmptyStringWithInline() constant_folding$after_inlining (before) + /// CHECK: LoadString load_kind:BootImageRelRo + /// CHECK: <<Length:i\d+>> ArrayLength + /// CHECK: Return [<<Length>>] + + /// CHECK-START: int Main.$noinline$testLengthEmptyStringWithInline() constant_folding$after_inlining (after) + /// CHECK: <<Const0:i\d+>> IntConstant 0 + /// CHECK: Return [<<Const0>>] + + /// CHECK-START: int Main.$noinline$testLengthEmptyStringWithInline() dead_code_elimination$after_inlining (after) + /// CHECK-NOT: LoadString + + /// CHECK-START: int Main.$noinline$testLengthEmptyStringWithInline() dead_code_elimination$after_inlining (after) + /// CHECK-NOT: ArrayLength + private static int $noinline$testLengthEmptyStringWithInline() { + String str = ""; + return $inline$returnLength(str); + } + + /// CHECK-START: int Main.$noinline$testLengthBssString() constant_folding (before) + /// CHECK: LoadString load_kind:BssEntry + /// CHECK: <<Length:i\d+>> ArrayLength + /// CHECK: Return [<<Length>>] + + /// CHECK-START: int Main.$noinline$testLengthBssString() constant_folding (after) + /// CHECK: <<Const32:i\d+>> IntConstant 32 + /// CHECK: Return [<<Const32>>] + + // We don't remove LoadString load_kind:BssEntry even if they have no uses, since IsRemovable() + // returns false for them. + /// CHECK-START: int Main.$noinline$testLengthBssString() dead_code_elimination$initial (after) + /// CHECK: LoadString load_kind:BssEntry + + /// CHECK-START: int Main.$noinline$testLengthBssString() dead_code_elimination$initial (after) + /// CHECK-NOT: ArrayLength + private static int $noinline$testLengthBssString() { + String str = "2047-checker-const-string-length"; + return str.length(); + } + + /// CHECK-START: int Main.$noinline$testLengthBssStringWithInline() constant_folding$after_inlining (before) + /// CHECK: LoadString load_kind:BssEntry + /// CHECK: <<Length:i\d+>> ArrayLength + /// CHECK: Return [<<Length>>] + + /// CHECK-START: int Main.$noinline$testLengthBssStringWithInline() constant_folding$after_inlining (after) + /// CHECK: <<Const32:i\d+>> IntConstant 32 + /// CHECK: Return [<<Const32>>] + + // We don't remove LoadString load_kind:BssEntry even if they have no uses, since IsRemovable() + // returns false for them. + /// CHECK-START: int Main.$noinline$testLengthBssStringWithInline() dead_code_elimination$after_inlining (after) + /// CHECK: LoadString load_kind:BssEntry + + /// CHECK-START: int Main.$noinline$testLengthBssStringWithInline() dead_code_elimination$after_inlining (after) + /// CHECK-NOT: ArrayLength + private static int $noinline$testLengthBssStringWithInline() { + String str = "2047-checker-const-string-length"; + return $inline$returnLength(str); + } + + private static int $inline$returnLength(String str) { + return str.length(); + } + + private static void $noinline$testIsEmpty() { + assertEquals(true, $noinline$testIsEmptyEmptyString()); + assertEquals(true, $noinline$testIsEmptyEmptyStringWithInline()); + assertEquals(false, $noinline$testIsEmptyBssString()); + assertEquals(false, $noinline$testIsEmptyBssStringWithInline()); + } + + /// CHECK-START: boolean Main.$noinline$testIsEmptyEmptyString() constant_folding (before) + /// CHECK: <<Const0:i\d+>> IntConstant 0 + /// CHECK: LoadString load_kind:BootImageRelRo + /// CHECK: <<Length:i\d+>> ArrayLength + /// CHECK: <<Eq:z\d+>> Equal [<<Length>>,<<Const0>>] + /// CHECK: Return [<<Eq>>] + + /// CHECK-START: boolean Main.$noinline$testIsEmptyEmptyString() constant_folding (after) + /// CHECK: <<Const1:i\d+>> IntConstant 1 + /// CHECK: Return [<<Const1>>] + + /// CHECK-START: boolean Main.$noinline$testIsEmptyEmptyString() dead_code_elimination$initial (after) + /// CHECK-NOT: LoadString + + /// CHECK-START: boolean Main.$noinline$testIsEmptyEmptyString() dead_code_elimination$initial (after) + /// CHECK-NOT: ArrayLength + private static boolean $noinline$testIsEmptyEmptyString() { + String str = ""; + return str.isEmpty(); + } + + /// CHECK-START: boolean Main.$noinline$testIsEmptyEmptyStringWithInline() constant_folding$after_inlining (before) + /// CHECK: <<Const0:i\d+>> IntConstant 0 + /// CHECK: LoadString load_kind:BootImageRelRo + /// CHECK: <<Length:i\d+>> ArrayLength + /// CHECK: <<Eq:z\d+>> Equal [<<Length>>,<<Const0>>] + /// CHECK: Return [<<Eq>>] + + /// CHECK-START: boolean Main.$noinline$testIsEmptyEmptyStringWithInline() constant_folding$after_inlining (after) + /// CHECK: <<Const1:i\d+>> IntConstant 1 + /// CHECK: Return [<<Const1>>] + + /// CHECK-START: boolean Main.$noinline$testIsEmptyEmptyStringWithInline() dead_code_elimination$after_inlining (after) + /// CHECK-NOT: LoadString + + /// CHECK-START: boolean Main.$noinline$testIsEmptyEmptyStringWithInline() dead_code_elimination$after_inlining (after) + /// CHECK-NOT: ArrayLength + private static boolean $noinline$testIsEmptyEmptyStringWithInline() { + String str = ""; + return $inline$returnIsEmpty(str); + } + + /// CHECK-START: boolean Main.$noinline$testIsEmptyBssString() constant_folding (before) + /// CHECK: <<Const0:i\d+>> IntConstant 0 + /// CHECK: LoadString load_kind:BssEntry + /// CHECK: <<Length:i\d+>> ArrayLength + /// CHECK: <<Eq:z\d+>> Equal [<<Length>>,<<Const0>>] + /// CHECK: Return [<<Eq>>] + + /// CHECK-START: boolean Main.$noinline$testIsEmptyBssString() constant_folding (after) + /// CHECK: <<Const0:i\d+>> IntConstant 0 + /// CHECK: Return [<<Const0>>] + + // We don't remove LoadString load_kind:BssEntry even if they have no uses, since IsRemovable() + // returns false for them. + /// CHECK-START: boolean Main.$noinline$testIsEmptyBssString() dead_code_elimination$initial (after) + /// CHECK: LoadString load_kind:BssEntry + + /// CHECK-START: boolean Main.$noinline$testIsEmptyBssString() dead_code_elimination$initial (after) + /// CHECK-NOT: ArrayLength + private static boolean $noinline$testIsEmptyBssString() { + String str = "2047-checker-const-string-length"; + return str.isEmpty(); + } + + /// CHECK-START: boolean Main.$noinline$testIsEmptyBssStringWithInline() constant_folding$after_inlining (before) + /// CHECK: <<Const0:i\d+>> IntConstant 0 + /// CHECK: LoadString load_kind:BssEntry + /// CHECK: <<Length:i\d+>> ArrayLength + /// CHECK: <<Eq:z\d+>> Equal [<<Length>>,<<Const0>>] + /// CHECK: Return [<<Eq>>] + + /// CHECK-START: boolean Main.$noinline$testIsEmptyBssStringWithInline() constant_folding$after_inlining (after) + /// CHECK: <<Const0:i\d+>> IntConstant 0 + /// CHECK: Return [<<Const0>>] + + // We don't remove LoadString load_kind:BssEntry even if they have no uses, since IsRemovable() + // returns false for them. + /// CHECK-START: boolean Main.$noinline$testIsEmptyBssStringWithInline() dead_code_elimination$after_inlining (after) + /// CHECK: LoadString load_kind:BssEntry + + /// CHECK-START: boolean Main.$noinline$testIsEmptyBssStringWithInline() dead_code_elimination$after_inlining (after) + /// CHECK-NOT: ArrayLength + private static boolean $noinline$testIsEmptyBssStringWithInline() { + String str = "2047-checker-const-string-length"; + return $inline$returnIsEmpty(str); + } + + private static boolean $inline$returnIsEmpty(String str) { + return str.isEmpty(); + } + + static void assertEquals(int expected, int actual) { + if (expected != actual) { + throw new AssertionError("Expected " + expected + " got " + actual); + } + } + + static void assertEquals(boolean expected, boolean actual) { + if (expected != actual) { + throw new AssertionError("Expected " + expected + " got " + actual); + } + } +} |