diff options
-rw-r--r-- | compiler/optimizing/intrinsics_mips.cc | 24 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics_mips64.cc | 23 | ||||
-rw-r--r-- | test/536-checker-intrinsic-optimization/src/Main.java | 31 |
3 files changed, 59 insertions, 19 deletions
diff --git a/compiler/optimizing/intrinsics_mips.cc b/compiler/optimizing/intrinsics_mips.cc index 64a68403e9..5999677536 100644 --- a/compiler/optimizing/intrinsics_mips.cc +++ b/compiler/optimizing/intrinsics_mips.cc @@ -1989,20 +1989,24 @@ void IntrinsicCodeGeneratorMIPS::VisitStringEquals(HInvoke* invoke) { __ LoadConst32(out, 1); return; } - - // Check if input is null, return false if it is. - __ Beqz(arg, &return_false); + StringEqualsOptimizations optimizations(invoke); + if (!optimizations.GetArgumentNotNull()) { + // Check if input is null, return false if it is. + __ Beqz(arg, &return_false); + } // Reference equality check, return true if same reference. __ Beq(str, arg, &return_true); - // Instanceof check for the argument by comparing class fields. - // All string objects must have the same type since String cannot be subclassed. - // Receiver must be a string object, so its class field is equal to all strings' class fields. - // If the argument is a string object, its class field must be equal to receiver's class field. - __ Lw(temp1, str, class_offset); - __ Lw(temp2, arg, class_offset); - __ Bne(temp1, temp2, &return_false); + if (!optimizations.GetArgumentIsString()) { + // Instanceof check for the argument by comparing class fields. + // All string objects must have the same type since String cannot be subclassed. + // Receiver must be a string object, so its class field is equal to all strings' class fields. + // If the argument is a string object, its class field must be equal to receiver's class field. + __ Lw(temp1, str, class_offset); + __ Lw(temp2, arg, class_offset); + __ Bne(temp1, temp2, &return_false); + } // Load `count` fields of this and argument strings. __ Lw(temp1, str, count_offset); diff --git a/compiler/optimizing/intrinsics_mips64.cc b/compiler/optimizing/intrinsics_mips64.cc index 3888828722..10da5c23af 100644 --- a/compiler/optimizing/intrinsics_mips64.cc +++ b/compiler/optimizing/intrinsics_mips64.cc @@ -1593,19 +1593,24 @@ void IntrinsicCodeGeneratorMIPS64::VisitStringEquals(HInvoke* invoke) { return; } - // Check if input is null, return false if it is. - __ Beqzc(arg, &return_false); + StringEqualsOptimizations optimizations(invoke); + if (!optimizations.GetArgumentNotNull()) { + // Check if input is null, return false if it is. + __ Beqzc(arg, &return_false); + } // Reference equality check, return true if same reference. __ Beqc(str, arg, &return_true); - // Instanceof check for the argument by comparing class fields. - // All string objects must have the same type since String cannot be subclassed. - // Receiver must be a string object, so its class field is equal to all strings' class fields. - // If the argument is a string object, its class field must be equal to receiver's class field. - __ Lw(temp1, str, class_offset); - __ Lw(temp2, arg, class_offset); - __ Bnec(temp1, temp2, &return_false); + if (!optimizations.GetArgumentIsString()) { + // Instanceof check for the argument by comparing class fields. + // All string objects must have the same type since String cannot be subclassed. + // Receiver must be a string object, so its class field is equal to all strings' class fields. + // If the argument is a string object, its class field must be equal to receiver's class field. + __ Lw(temp1, str, class_offset); + __ Lw(temp2, arg, class_offset); + __ Bnec(temp1, temp2, &return_false); + } // Load `count` fields of this and argument strings. __ Lw(temp1, str, count_offset); diff --git a/test/536-checker-intrinsic-optimization/src/Main.java b/test/536-checker-intrinsic-optimization/src/Main.java index 52f3f84406..e395e283e0 100644 --- a/test/536-checker-intrinsic-optimization/src/Main.java +++ b/test/536-checker-intrinsic-optimization/src/Main.java @@ -330,6 +330,21 @@ public class Main { // Terminate the scope for the CHECK-NOT search at the reference or length comparison, // whichever comes first. /// CHECK: cmp {{w.*,}} {{w.*|#.*}} + + /// CHECK-START-MIPS: boolean Main.stringArgumentNotNull(java.lang.Object) disassembly (after) + /// CHECK: InvokeVirtual {{.*\.equals.*}} intrinsic:StringEquals + /// CHECK-NOT: beq r0, + /// CHECK-NOT: beqz + /// CHECK-NOT: beqzc + // Terminate the scope for the CHECK-NOT search at the class field or length comparison, + // whichever comes first. + /// CHECK: lw + + /// CHECK-START-MIPS64: boolean Main.stringArgumentNotNull(java.lang.Object) disassembly (after) + /// CHECK: InvokeVirtual {{.*\.equals.*}} intrinsic:StringEquals + /// CHECK-NOT: beqzc + // Terminate the scope for the CHECK-NOT search at the reference comparison. + /// CHECK: beqc public static boolean stringArgumentNotNull(Object obj) { obj.getClass(); return "foo".equals(obj); @@ -384,6 +399,22 @@ public class Main { /// CHECK-NOT: ldr {{w\d+}}, [{{x\d+}}] /// CHECK-NOT: ldr {{w\d+}}, [{{x\d+}}, #0] /// CHECK: cmp {{w\d+}}, {{w\d+|#.*}} + + // Test is brittle as it depends on the class offset being 0. + /// CHECK-START-MIPS: boolean Main.stringArgumentIsString() disassembly (after) + /// CHECK: InvokeVirtual intrinsic:StringEquals + /// CHECK: beq{{(zc)?}} + // Check that we don't try to compare the classes. + /// CHECK-NOT: lw {{r\d+}}, +0({{r\d+}}) + /// CHECK: bne{{c?}} + + // Test is brittle as it depends on the class offset being 0. + /// CHECK-START-MIPS64: boolean Main.stringArgumentIsString() disassembly (after) + /// CHECK: InvokeVirtual intrinsic:StringEquals + /// CHECK: beqzc + // Check that we don't try to compare the classes. + /// CHECK-NOT: lw {{r\d+}}, +0({{r\d+}}) + /// CHECK: bnec public static boolean stringArgumentIsString() { return "foo".equals(myString); } |