Avoid generating dead code on frame enter/exit.
This includes stack operations and, on x86, call/pop to read PC.
bug=26997690
Rationale:
(1) If method is fully intrinsified, and makes no calls in slow
path or uses special input, no need to require current method.
(2) Invoke instructions with HasPcRelativeDexCache() generate code
that reads the PC (call/pop) on x86. However, if the invoke is
an intrinsic that is later replaced with actual code, this PC
reading code may be dead.
Example X86 (before/after):
0x0000108c: 83EC0C sub esp, 12
0x0000108f: 890424 mov [esp], eax <-- not needed
0x00001092: E800000000 call +0 (0x00001097)
0x00001097: 58 pop eax <-- dead code to read PC
0x00001098: F30FB8C1 popcnt eax, ecx
0x0000109c: F30FB8DA popcnt ebx, edx
0x000010a0: 03D8 add ebx, eax
0x000010a2: 89D8 mov eax, ebx
0x000010a4: 83C40C add esp, 12 <-- not needed
0x000010a7: C3 ret
0x0000103c: F30FB8C1 popcnt eax, ecx
0x00001040: F30FB8DA popcnt ebx, edx
0x00001044: 03D8 add ebx, eax
0x00001046: 89D8 mov eax, ebx
0x00001048: C3 ret
Example ARM64 (before/after):
0x0000103c: f81e0fe0 str x0, [sp, #-32]!
0x00001040: f9000ffe str lr, [sp, #24]
0x00001044: dac01020 clz x0, x1
0x00001048: f9400ffe ldr lr, [sp, #24]
0x0000104c: 910083ff add sp, sp, #0x20 (32)
0x00001050: d65f03c0 ret
0x0000103c: dac01020 clz x0, x1
0x00001040: d65f03c0 ret
Change-Id: I8377db80c9a901a08fff4624927cf4a6e585da0c
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index 967d156..af50363 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -543,8 +543,16 @@
DCHECK(CheckTypeConsistency(instruction));
LocationSummary* locations = instruction->GetLocations();
if (!instruction->IsSuspendCheckEntry()) {
- if (locations != nullptr && locations->CanCall()) {
- MarkNotLeaf();
+ if (locations != nullptr) {
+ if (locations->CanCall()) {
+ MarkNotLeaf();
+ } else if (locations->Intrinsified() &&
+ instruction->IsInvokeStaticOrDirect() &&
+ !instruction->AsInvokeStaticOrDirect()->HasCurrentMethodInput()) {
+ // A static method call that has been fully intrinsified, and cannot call on the slow
+ // path or refer to the current method directly, no longer needs current method.
+ return;
+ }
}
if (instruction->NeedsCurrentMethod()) {
SetRequiresCurrentMethod();