diff options
-rw-r--r-- | compiler/optimizing/intrinsics_arm64.cc | 162 | ||||
-rw-r--r-- | runtime/mirror/string-inl.h | 9 | ||||
-rw-r--r-- | runtime/mirror/string.h | 4 | ||||
-rw-r--r-- | test/021-string2/src/Main.java | 263 | ||||
-rw-r--r-- | test/536-checker-intrinsic-optimization/src/Main.java | 6 |
5 files changed, 399 insertions, 45 deletions
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc index 1047d3beb6..86e54294ae 100644 --- a/compiler/optimizing/intrinsics_arm64.cc +++ b/compiler/optimizing/intrinsics_arm64.cc @@ -23,7 +23,7 @@ #include "entrypoints/quick/quick_entrypoints.h" #include "intrinsics.h" #include "mirror/array-inl.h" -#include "mirror/string.h" +#include "mirror/string-inl.h" #include "thread.h" #include "utils/arm64/assembler_arm64.h" @@ -1450,16 +1450,47 @@ void IntrinsicCodeGeneratorARM64::VisitStringCompareTo(HInvoke* invoke) { } } +// The cut off for unrolling the loop in String.equals() intrinsic for const strings. +// The normal loop plus the pre-header is 9 instructions without string compression and 12 +// instructions with string compression. We can compare up to 8 bytes in 4 instructions +// (LDR+LDR+CMP+BNE) and up to 16 bytes in 5 instructions (LDP+LDP+CMP+CCMP+BNE). Allow up +// to 10 instructions for the unrolled loop. +constexpr size_t kShortConstStringEqualsCutoffInBytes = 32; + +static const char* GetConstString(HInstruction* candidate, uint32_t* utf16_length) { + if (candidate->IsLoadString()) { + HLoadString* load_string = candidate->AsLoadString(); + const DexFile& dex_file = load_string->GetDexFile(); + return dex_file.StringDataAndUtf16LengthByIdx(load_string->GetStringIndex(), utf16_length); + } + return nullptr; +} + void IntrinsicLocationsBuilderARM64::VisitStringEquals(HInvoke* invoke) { LocationSummary* locations = new (arena_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified); locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RequiresRegister()); - // Temporary registers to store lengths of strings and for calculations. - locations->AddTemp(Location::RequiresRegister()); - locations->AddTemp(Location::RequiresRegister()); + // For the generic implementation and for long const strings we need a temporary. + // We do not need it for short const strings, up to 8 bytes, see code generation below. + uint32_t const_string_length = 0u; + const char* const_string = GetConstString(invoke->InputAt(0), &const_string_length); + if (const_string == nullptr) { + const_string = GetConstString(invoke->InputAt(1), &const_string_length); + } + bool is_compressed = + mirror::kUseStringCompression && + const_string != nullptr && + mirror::String::DexFileStringAllASCII(const_string, const_string_length); + if (const_string == nullptr || const_string_length > (is_compressed ? 8u : 4u)) { + locations->AddTemp(Location::RequiresRegister()); + } + + // TODO: If the String.equals() is used only for an immediately following HIf, we can + // mark it as emitted-at-use-site and emit branches directly to the appropriate blocks. + // Then we shall need an extra temporary register instead of the output register. locations->SetOut(Location::RequiresRegister(), Location::kOutputOverlap); } @@ -1473,8 +1504,7 @@ void IntrinsicCodeGeneratorARM64::VisitStringEquals(HInvoke* invoke) { UseScratchRegisterScope scratch_scope(masm); Register temp = scratch_scope.AcquireW(); - Register temp1 = WRegisterFrom(locations->GetTemp(0)); - Register temp2 = WRegisterFrom(locations->GetTemp(1)); + Register temp1 = scratch_scope.AcquireW(); vixl::aarch64::Label loop; vixl::aarch64::Label end; @@ -1510,46 +1540,98 @@ void IntrinsicCodeGeneratorARM64::VisitStringEquals(HInvoke* invoke) { __ B(&return_false, ne); } - // Load `count` fields of this and argument strings. - __ Ldr(temp, MemOperand(str.X(), count_offset)); - __ Ldr(temp1, MemOperand(arg.X(), count_offset)); - // Check if `count` fields are equal, return false if they're not. - // Also compares the compression style, if differs return false. - __ Cmp(temp, temp1); - __ B(&return_false, ne); - // Return true if both strings are empty. Even with string compression `count == 0` means empty. - static_assert(static_cast<uint32_t>(mirror::StringCompressionFlag::kCompressed) == 0u, - "Expecting 0=compressed, 1=uncompressed"); - __ Cbz(temp, &return_true); + // Check if one of the inputs is a const string. Do not special-case both strings + // being const, such cases should be handled by constant folding if needed. + uint32_t const_string_length = 0u; + const char* const_string = GetConstString(invoke->InputAt(0), &const_string_length); + if (const_string == nullptr) { + const_string = GetConstString(invoke->InputAt(1), &const_string_length); + if (const_string != nullptr) { + std::swap(str, arg); // Make sure the const string is in `str`. + } + } + bool is_compressed = + mirror::kUseStringCompression && + const_string != nullptr && + mirror::String::DexFileStringAllASCII(const_string, const_string_length); + + if (const_string != nullptr) { + // Load `count` field of the argument string and check if it matches the const string. + // Also compares the compression style, if differs return false. + __ Ldr(temp, MemOperand(arg.X(), count_offset)); + __ Cmp(temp, Operand(mirror::String::GetFlaggedCount(const_string_length, is_compressed))); + __ B(&return_false, ne); + } else { + // Load `count` fields of this and argument strings. + __ Ldr(temp, MemOperand(str.X(), count_offset)); + __ Ldr(temp1, MemOperand(arg.X(), count_offset)); + // Check if `count` fields are equal, return false if they're not. + // Also compares the compression style, if differs return false. + __ Cmp(temp, temp1); + __ B(&return_false, ne); + } // Assertions that must hold in order to compare strings 8 bytes at a time. DCHECK_ALIGNED(value_offset, 8); static_assert(IsAligned<8>(kObjectAlignment), "String of odd length is not zero padded"); - if (mirror::kUseStringCompression) { - // For string compression, calculate the number of bytes to compare (not chars). - // This could in theory exceed INT32_MAX, so treat temp as unsigned. - __ Lsr(temp, temp, 1u); // Extract length. - __ And(temp1, temp1, Operand(1)); // Extract compression flag. - __ Lsl(temp, temp, temp1); // Calculate number of bytes to compare. - } - - // Store offset of string value in preparation for comparison loop - __ Mov(temp1, value_offset); + if (const_string != nullptr && + const_string_length < (is_compressed ? kShortConstStringEqualsCutoffInBytes + : kShortConstStringEqualsCutoffInBytes / 2u)) { + // Load and compare the contents. Though we know the contents of the short const string + // at compile time, materializing constants may be more code than loading from memory. + int32_t offset = value_offset; + size_t remaining_bytes = + RoundUp(is_compressed ? const_string_length : const_string_length * 2u, 8u); + temp = temp.X(); + temp1 = temp1.X(); + while (remaining_bytes > 8u) { + Register temp2 = XRegisterFrom(locations->GetTemp(0)); + __ Ldp(temp, temp1, MemOperand(str.X(), offset)); + __ Ldp(temp2, out, MemOperand(arg.X(), offset)); + __ Cmp(temp, temp2); + __ Ccmp(temp1, out, NoFlag, eq); + __ B(&return_false, ne); + offset += 2u * sizeof(uint64_t); + remaining_bytes -= 2u * sizeof(uint64_t); + } + if (remaining_bytes != 0u) { + __ Ldr(temp, MemOperand(str.X(), offset)); + __ Ldr(temp1, MemOperand(arg.X(), offset)); + __ Cmp(temp, temp1); + __ B(&return_false, ne); + } + } else { + // Return true if both strings are empty. Even with string compression `count == 0` means empty. + static_assert(static_cast<uint32_t>(mirror::StringCompressionFlag::kCompressed) == 0u, + "Expecting 0=compressed, 1=uncompressed"); + __ Cbz(temp, &return_true); + + if (mirror::kUseStringCompression) { + // For string compression, calculate the number of bytes to compare (not chars). + // This could in theory exceed INT32_MAX, so treat temp as unsigned. + __ And(temp1, temp, Operand(1)); // Extract compression flag. + __ Lsr(temp, temp, 1u); // Extract length. + __ Lsl(temp, temp, temp1); // Calculate number of bytes to compare. + } - temp1 = temp1.X(); - temp2 = temp2.X(); - // Loop to compare strings 8 bytes at a time starting at the front of the string. - // Ok to do this because strings are zero-padded to kObjectAlignment. - __ Bind(&loop); - __ Ldr(out, MemOperand(str.X(), temp1)); - __ Ldr(temp2, MemOperand(arg.X(), temp1)); - __ Add(temp1, temp1, Operand(sizeof(uint64_t))); - __ Cmp(out, temp2); - __ B(&return_false, ne); - // With string compression, we have compared 8 bytes, otherwise 4 chars. - __ Sub(temp, temp, Operand(mirror::kUseStringCompression ? 8 : 4), SetFlags); - __ B(&loop, hi); + // Store offset of string value in preparation for comparison loop + __ Mov(temp1, value_offset); + + temp1 = temp1.X(); + Register temp2 = XRegisterFrom(locations->GetTemp(0)); + // Loop to compare strings 8 bytes at a time starting at the front of the string. + // Ok to do this because strings are zero-padded to kObjectAlignment. + __ Bind(&loop); + __ Ldr(out, MemOperand(str.X(), temp1)); + __ Ldr(temp2, MemOperand(arg.X(), temp1)); + __ Add(temp1, temp1, Operand(sizeof(uint64_t))); + __ Cmp(out, temp2); + __ B(&return_false, ne); + // With string compression, we have compared 8 bytes, otherwise 4 chars. + __ Sub(temp, temp, Operand(mirror::kUseStringCompression ? 8 : 4), SetFlags); + __ B(&loop, hi); + } // Return true and exit the function. // If loop does not result in returning false, we return true. diff --git a/runtime/mirror/string-inl.h b/runtime/mirror/string-inl.h index 9b8445dc9e..c2407d7772 100644 --- a/runtime/mirror/string-inl.h +++ b/runtime/mirror/string-inl.h @@ -308,7 +308,7 @@ inline int32_t String::GetHashCode() { } template<typename MemoryType> -bool String::AllASCII(const MemoryType* const chars, const int length) { +inline bool String::AllASCII(const MemoryType* chars, const int length) { static_assert(std::is_unsigned<MemoryType>::value, "Expecting unsigned MemoryType"); for (int i = 0; i < length; ++i) { // Valid ASCII characters are in range 1..0x7f. Zero is not considered ASCII @@ -320,6 +320,13 @@ bool String::AllASCII(const MemoryType* const chars, const int length) { return true; } +inline bool String::DexFileStringAllASCII(const char* chars, const int length) { + // For strings from the dex file we just need to check that + // the terminating character is at the right position. + DCHECK_EQ(AllASCII(reinterpret_cast<const uint8_t*>(chars), length), chars[length] == 0); + return chars[length] == 0; +} + } // namespace mirror } // namespace art diff --git a/runtime/mirror/string.h b/runtime/mirror/string.h index 409c6c2896..38f6dd4b6f 100644 --- a/runtime/mirror/string.h +++ b/runtime/mirror/string.h @@ -184,7 +184,9 @@ class MANAGED String FINAL : public Object { bool IsValueNull() REQUIRES_SHARED(Locks::mutator_lock_); template<typename MemoryType> - static bool AllASCII(const MemoryType* const chars, const int length); + static bool AllASCII(const MemoryType* chars, const int length); + + static bool DexFileStringAllASCII(const char* chars, const int length); ALWAYS_INLINE static bool IsCompressed(int32_t count) { return GetCompressionFlagFromCount(count) == StringCompressionFlag::kCompressed; diff --git a/test/021-string2/src/Main.java b/test/021-string2/src/Main.java index df0a3ddf48..5a43a4f23f 100644 --- a/test/021-string2/src/Main.java +++ b/test/021-string2/src/Main.java @@ -117,6 +117,9 @@ public class Main { " " + $noinline$equals(s0_3, s0_1) + " " + $noinline$equals(s0_3, s0_2) + " " + $noinline$equals(s0_3, s0_3)); + + testEqualsConstString(); + testConstStringEquals(); } public static void testCompareToAndEquals() { @@ -539,6 +542,266 @@ public class Main { } } + public static void testEqualsConstString() { + Assert.assertTrue($noinline$equalsConstString0("")); + Assert.assertFalse($noinline$equalsConstString0("1")); + + Assert.assertTrue($noinline$equalsConstString7("0123456")); + Assert.assertFalse($noinline$equalsConstString7("012345")); + Assert.assertFalse($noinline$equalsConstString7("01234567")); + Assert.assertFalse($noinline$equalsConstString7("012345x")); + Assert.assertFalse($noinline$equalsConstString7("012345\u0440")); + + Assert.assertTrue($noinline$equalsConstString14("01234567890123")); + Assert.assertFalse($noinline$equalsConstString14("0123456789012")); + Assert.assertFalse($noinline$equalsConstString14("012345678901234")); + Assert.assertFalse($noinline$equalsConstString14("0123456789012x")); + Assert.assertFalse($noinline$equalsConstString14("0123456789012\u0440")); + + Assert.assertTrue($noinline$equalsConstString24("012345678901234567890123")); + Assert.assertFalse($noinline$equalsConstString24("01234567890123456789012")); + Assert.assertFalse($noinline$equalsConstString24("0123456789012345678901234")); + Assert.assertFalse($noinline$equalsConstString24("01234567890123456789012x")); + Assert.assertFalse($noinline$equalsConstString24("01234567890123456789012\u0440")); + + Assert.assertTrue($noinline$equalsConstString29("01234567890123456789012345678")); + Assert.assertFalse($noinline$equalsConstString29("0123456789012345678901234567")); + Assert.assertFalse($noinline$equalsConstString29("012345678901234567890123456789")); + Assert.assertFalse($noinline$equalsConstString29("0123456789012345678901234567x")); + Assert.assertFalse($noinline$equalsConstString29("0123456789012345678901234567\u0440")); + + Assert.assertTrue($noinline$equalsConstString35("01234567890123456789012345678901234")); + Assert.assertFalse($noinline$equalsConstString35("0123456789012345678901234567890123")); + Assert.assertFalse($noinline$equalsConstString35("012345678901234567890123456789012345")); + Assert.assertFalse($noinline$equalsConstString35("0123456789012345678901234567890123x")); + Assert.assertFalse( + $noinline$equalsConstString35("0123456789012345678901234567890123\u0440")); + + Assert.assertTrue($noinline$equalsConstNonAsciiString7("\u0440123456")); + Assert.assertFalse($noinline$equalsConstNonAsciiString7("\u044012345")); + Assert.assertFalse($noinline$equalsConstNonAsciiString7("\u04401234567")); + Assert.assertFalse($noinline$equalsConstNonAsciiString7("\u044012345x")); + Assert.assertFalse($noinline$equalsConstNonAsciiString7("0123456")); + + Assert.assertTrue($noinline$equalsConstNonAsciiString14("\u04401234567890123")); + Assert.assertFalse($noinline$equalsConstNonAsciiString14("\u0440123456789012")); + Assert.assertFalse($noinline$equalsConstNonAsciiString14("\u044012345678901234")); + Assert.assertFalse($noinline$equalsConstNonAsciiString14("\u0440123456789012x")); + Assert.assertFalse($noinline$equalsConstNonAsciiString14("01234567890123")); + + Assert.assertTrue($noinline$equalsConstNonAsciiString24("\u044012345678901234567890123")); + Assert.assertFalse($noinline$equalsConstNonAsciiString24("\u04401234567890123456789012")); + Assert.assertFalse($noinline$equalsConstNonAsciiString24("\u0440123456789012345678901234")); + Assert.assertFalse($noinline$equalsConstNonAsciiString24("\u04401234567890123456789012x")); + Assert.assertFalse($noinline$equalsConstNonAsciiString24("\012345678901234567890123")); + + Assert.assertTrue( + $noinline$equalsConstNonAsciiString29("\u04401234567890123456789012345678")); + Assert.assertFalse( + $noinline$equalsConstNonAsciiString29("\u0440123456789012345678901234567")); + Assert.assertFalse( + $noinline$equalsConstNonAsciiString29("\u044012345678901234567890123456789")); + Assert.assertFalse( + $noinline$equalsConstNonAsciiString29("\u0440123456789012345678901234567x")); + Assert.assertFalse($noinline$equalsConstNonAsciiString29("01234567890123456789012345678")); + + Assert.assertTrue( + $noinline$equalsConstNonAsciiString35("\u04401234567890123456789012345678901234")); + Assert.assertFalse( + $noinline$equalsConstNonAsciiString35("\u0440123456789012345678901234567890123")); + Assert.assertFalse( + $noinline$equalsConstNonAsciiString35("\u044012345678901234567890123456789012345")); + Assert.assertFalse( + $noinline$equalsConstNonAsciiString35("\u0440123456789012345678901234567890123x")); + Assert.assertFalse( + $noinline$equalsConstNonAsciiString35("01234567890123456789012345678901234")); + } + + public static void testConstStringEquals() { + Assert.assertTrue($noinline$constString0Equals("")); + Assert.assertFalse($noinline$constString0Equals("1")); + + Assert.assertTrue($noinline$constString7Equals("0123456")); + Assert.assertFalse($noinline$constString7Equals("012345")); + Assert.assertFalse($noinline$constString7Equals("01234567")); + Assert.assertFalse($noinline$constString7Equals("012345x")); + Assert.assertFalse($noinline$constString7Equals("012345\u0440")); + + Assert.assertTrue($noinline$constString14Equals("01234567890123")); + Assert.assertFalse($noinline$constString14Equals("0123456789012")); + Assert.assertFalse($noinline$constString14Equals("012345678901234")); + Assert.assertFalse($noinline$constString14Equals("0123456789012x")); + Assert.assertFalse($noinline$constString14Equals("0123456789012\u0440")); + + Assert.assertTrue($noinline$constString24Equals("012345678901234567890123")); + Assert.assertFalse($noinline$constString24Equals("01234567890123456789012")); + Assert.assertFalse($noinline$constString24Equals("0123456789012345678901234")); + Assert.assertFalse($noinline$constString24Equals("01234567890123456789012x")); + Assert.assertFalse($noinline$constString24Equals("01234567890123456789012\u0440")); + + Assert.assertTrue($noinline$constString29Equals("01234567890123456789012345678")); + Assert.assertFalse($noinline$constString29Equals("0123456789012345678901234567")); + Assert.assertFalse($noinline$constString29Equals("012345678901234567890123456789")); + Assert.assertFalse($noinline$constString29Equals("0123456789012345678901234567x")); + Assert.assertFalse($noinline$constString29Equals("0123456789012345678901234567\u0440")); + + Assert.assertTrue($noinline$constString35Equals("01234567890123456789012345678901234")); + Assert.assertFalse($noinline$constString35Equals("0123456789012345678901234567890123")); + Assert.assertFalse($noinline$constString35Equals("012345678901234567890123456789012345")); + Assert.assertFalse($noinline$constString35Equals("0123456789012345678901234567890123x")); + Assert.assertFalse( + $noinline$constString35Equals("0123456789012345678901234567890123\u0040")); + + Assert.assertTrue($noinline$constNonAsciiString7Equals("\u0440123456")); + Assert.assertFalse($noinline$constNonAsciiString7Equals("\u044012345")); + Assert.assertFalse($noinline$constNonAsciiString7Equals("\u04401234567")); + Assert.assertFalse($noinline$constNonAsciiString7Equals("\u044012345x")); + Assert.assertFalse($noinline$constNonAsciiString7Equals("0123456")); + + Assert.assertTrue($noinline$constNonAsciiString14Equals("\u04401234567890123")); + Assert.assertFalse($noinline$constNonAsciiString14Equals("\u0440123456789012")); + Assert.assertFalse($noinline$constNonAsciiString14Equals("\u044012345678901234")); + Assert.assertFalse($noinline$constNonAsciiString14Equals("\u0440123456789012x")); + Assert.assertFalse($noinline$constNonAsciiString14Equals("01234567890123")); + + Assert.assertTrue($noinline$constNonAsciiString24Equals("\u044012345678901234567890123")); + Assert.assertFalse($noinline$constNonAsciiString24Equals("\u04401234567890123456789012")); + Assert.assertFalse($noinline$constNonAsciiString24Equals("\u0440123456789012345678901234")); + Assert.assertFalse($noinline$constNonAsciiString24Equals("\u04401234567890123456789012x")); + Assert.assertFalse($noinline$constNonAsciiString24Equals("\012345678901234567890123")); + + Assert.assertTrue( + $noinline$constNonAsciiString29Equals("\u04401234567890123456789012345678")); + Assert.assertFalse( + $noinline$constNonAsciiString29Equals("\u0440123456789012345678901234567")); + Assert.assertFalse( + $noinline$constNonAsciiString29Equals("\u044012345678901234567890123456789")); + Assert.assertFalse( + $noinline$constNonAsciiString29Equals("\u0440123456789012345678901234567x")); + Assert.assertFalse($noinline$constNonAsciiString29Equals("01234567890123456789012345678")); + + Assert.assertTrue( + $noinline$constNonAsciiString35Equals("\u04401234567890123456789012345678901234")); + Assert.assertFalse( + $noinline$constNonAsciiString35Equals("\u0440123456789012345678901234567890123")); + Assert.assertFalse( + $noinline$constNonAsciiString35Equals("\u044012345678901234567890123456789012345")); + Assert.assertFalse( + $noinline$constNonAsciiString35Equals("\u0440123456789012345678901234567890123x")); + Assert.assertFalse( + $noinline$constNonAsciiString35Equals("01234567890123456789012345678901234")); + } + + public static boolean $noinline$equalsConstString0(String s) { + if (doThrow) { throw new Error(); } + return s.equals(""); + } + + public static boolean $noinline$equalsConstString7(String s) { + if (doThrow) { throw new Error(); } + return s.equals("0123456"); + } + + public static boolean $noinline$equalsConstString14(String s) { + if (doThrow) { throw new Error(); } + return s.equals("01234567890123"); + } + + public static boolean $noinline$equalsConstString24(String s) { + if (doThrow) { throw new Error(); } + return s.equals("012345678901234567890123"); + } + + public static boolean $noinline$equalsConstString29(String s) { + if (doThrow) { throw new Error(); } + return s.equals("01234567890123456789012345678"); + } + + public static boolean $noinline$equalsConstString35(String s) { + if (doThrow) { throw new Error(); } + return s.equals("01234567890123456789012345678901234"); + } + + public static boolean $noinline$equalsConstNonAsciiString7(String s) { + if (doThrow) { throw new Error(); } + return s.equals("\u0440123456"); + } + + public static boolean $noinline$equalsConstNonAsciiString14(String s) { + if (doThrow) { throw new Error(); } + return s.equals("\u04401234567890123"); + } + + public static boolean $noinline$equalsConstNonAsciiString24(String s) { + if (doThrow) { throw new Error(); } + return s.equals("\u044012345678901234567890123"); + } + + public static boolean $noinline$equalsConstNonAsciiString29(String s) { + if (doThrow) { throw new Error(); } + return s.equals("\u04401234567890123456789012345678"); + } + + public static boolean $noinline$equalsConstNonAsciiString35(String s) { + if (doThrow) { throw new Error(); } + return s.equals("\u04401234567890123456789012345678901234"); + } + + public static boolean $noinline$constString0Equals(String s) { + if (doThrow) { throw new Error(); } + return s.equals(""); + } + + public static boolean $noinline$constString7Equals(String s) { + if (doThrow) { throw new Error(); } + return "0123456".equals(s); + } + + public static boolean $noinline$constString14Equals(String s) { + if (doThrow) { throw new Error(); } + return "01234567890123".equals(s); + } + + public static boolean $noinline$constString24Equals(String s) { + if (doThrow) { throw new Error(); } + return "012345678901234567890123".equals(s); + } + + public static boolean $noinline$constString29Equals(String s) { + if (doThrow) { throw new Error(); } + return "01234567890123456789012345678".equals(s); + } + + public static boolean $noinline$constString35Equals(String s) { + if (doThrow) { throw new Error(); } + return "01234567890123456789012345678901234".equals(s); + } + + public static boolean $noinline$constNonAsciiString7Equals(String s) { + if (doThrow) { throw new Error(); } + return "\u0440123456".equals(s); + } + + public static boolean $noinline$constNonAsciiString14Equals(String s) { + if (doThrow) { throw new Error(); } + return "\u04401234567890123".equals(s); + } + + public static boolean $noinline$constNonAsciiString24Equals(String s) { + if (doThrow) { throw new Error(); } + return "\u044012345678901234567890123".equals(s); + } + + public static boolean $noinline$constNonAsciiString29Equals(String s) { + if (doThrow) { throw new Error(); } + return "\u04401234567890123456789012345678".equals(s); + } + + public static boolean $noinline$constNonAsciiString35Equals(String s) { + if (doThrow) { throw new Error(); } + return "\u04401234567890123456789012345678901234".equals(s); + } + public static int $noinline$compareTo(String lhs, String rhs) { if (doThrow) { throw new Error(); } return lhs.compareTo(rhs); diff --git a/test/536-checker-intrinsic-optimization/src/Main.java b/test/536-checker-intrinsic-optimization/src/Main.java index ed7524c7ad..52f3f84406 100644 --- a/test/536-checker-intrinsic-optimization/src/Main.java +++ b/test/536-checker-intrinsic-optimization/src/Main.java @@ -329,7 +329,7 @@ public class Main { /// CHECK-NOT: cbz // Terminate the scope for the CHECK-NOT search at the reference or length comparison, // whichever comes first. - /// CHECK: cmp {{w.*,}} {{w.*}} + /// CHECK: cmp {{w.*,}} {{w.*|#.*}} public static boolean stringArgumentNotNull(Object obj) { obj.getClass(); return "foo".equals(obj); @@ -380,10 +380,10 @@ public class Main { // so repeat the check twice. /// CHECK-NOT: ldr {{w\d+}}, [{{x\d+}}] /// CHECK-NOT: ldr {{w\d+}}, [{{x\d+}}, #0] - /// CHECK: cmp {{w\d+}}, {{w\d+}} + /// CHECK: cmp {{w\d+}}, {{w\d+|#.*}} /// CHECK-NOT: ldr {{w\d+}}, [{{x\d+}}] /// CHECK-NOT: ldr {{w\d+}}, [{{x\d+}}, #0] - /// CHECK: cmp {{w\d+}}, {{w\d+}} + /// CHECK: cmp {{w\d+}}, {{w\d+|#.*}} public static boolean stringArgumentIsString() { return "foo".equals(myString); } |