From f688cf78d69da5088e13175b8e20bc993e0ac81e Mon Sep 17 00:00:00 2001 From: Mitch Bodart Date: Thu, 26 May 2016 23:08:52 +0000 Subject: [PATCH] [CodeGen] Fix problem with X86 byte registers in CriticalAntiDepBreaker CriticalAntiDepBreaker was not correctly tracking defs of the high X86 byte registers, leading to incorrect use of a busy register to break an antidependence. Fixes pr27681, and its duplicates pr27580, pr27804. Differential Revision: http://reviews.llvm.org/D20456 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@270935 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CriticalAntiDepBreaker.cpp | 10 ++-- test/CodeGen/X86/pr27681.mir | 87 ++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 4 deletions(-) create mode 100644 test/CodeGen/X86/pr27681.mir diff --git a/lib/CodeGen/CriticalAntiDepBreaker.cpp b/lib/CodeGen/CriticalAntiDepBreaker.cpp index d693af4a0a2..a0189a172bf 100644 --- a/lib/CodeGen/CriticalAntiDepBreaker.cpp +++ b/lib/CodeGen/CriticalAntiDepBreaker.cpp @@ -260,22 +260,24 @@ void CriticalAntiDepBreaker::ScanInstruction(MachineInstr &MI, unsigned Count) { if (Reg == 0) continue; if (!MO.isDef()) continue; - // If we've already marked this reg as unchangeable, carry on. - if (KeepRegs.test(Reg)) continue; - // Ignore two-addr defs. if (MI.isRegTiedToUseOperand(i)) continue; + // If we've already marked this reg as unchangeable, don't remove + // it or any of its subregs from KeepRegs. + bool Keep = KeepRegs.test(Reg); + // For the reg itself and all subregs: update the def to current; // reset the kill state, any restrictions, and references. for (MCSubRegIterator SRI(Reg, TRI, true); SRI.isValid(); ++SRI) { unsigned SubregReg = *SRI; DefIndices[SubregReg] = Count; KillIndices[SubregReg] = ~0u; - KeepRegs.reset(SubregReg); Classes[SubregReg] = nullptr; RegRefs.erase(SubregReg); + if (!Keep) + KeepRegs.reset(SubregReg); } // Conservatively mark super-registers as unusable. for (MCSuperRegIterator SR(Reg, TRI); SR.isValid(); ++SR) diff --git a/test/CodeGen/X86/pr27681.mir b/test/CodeGen/X86/pr27681.mir new file mode 100644 index 00000000000..0043ac1d417 --- /dev/null +++ b/test/CodeGen/X86/pr27681.mir @@ -0,0 +1,87 @@ +# RUN: llc -mtriple=i386-unknown-linux-gnu -mcpu=slm -run-pass post-RA-sched -o /dev/null %s 2>&1 | FileCheck %s +# +# Verify that the critical antidependence breaker does not consider +# a high byte register as available as a replacement register +# in a certain context. +--- | + + define void @main() { ret void } + +... +--- +# CHECK-LABEL: main +name: main +allVRegsAllocated: true +tracksRegLiveness: true +frameInfo: + stackSize: 52 +fixedStack: + - { id: 0, type: spill-slot, offset: -20, size: 4, alignment: 4, callee-saved-register: '%esi' } + - { id: 1, type: spill-slot, offset: -16, size: 4, alignment: 4, callee-saved-register: '%edi' } + - { id: 2, type: spill-slot, offset: -12, size: 4, alignment: 4, callee-saved-register: '%ebx' } + - { id: 3, type: spill-slot, offset: -8, size: 4, alignment: 4, callee-saved-register: '%ebp' } +stack: + - { id: 0, type: spill-slot, offset: -53, size: 1, alignment: 1 } + - { id: 1, type: spill-slot, offset: -48, size: 4, alignment: 4 } + - { id: 2, type: spill-slot, offset: -32, size: 4, alignment: 4 } +body: | + bb.0: + successors: %bb.1 + liveins: %ebp, %ebx, %edi, %esi + + frame-setup PUSH32r killed %ebp, implicit-def %esp, implicit %esp + frame-setup PUSH32r killed %ebx, implicit-def %esp, implicit %esp + frame-setup PUSH32r killed %edi, implicit-def %esp, implicit %esp + frame-setup PUSH32r killed %esi, implicit-def %esp, implicit %esp + %esp = frame-setup SUB32ri8 %esp, 36, implicit-def dead %eflags + %eax = MOV32ri 1 + %ebp = MOV32ri 2 + %ebx = MOV32ri 3 + %ecx = MOV32ri 4 + %edi = MOV32ri 5 + %edx = MOV32ri 6 + + bb.1: + successors: %bb.3, %bb.2 + liveins: %eax, %ebp, %ebx, %ecx, %edi, %edx + + %ebp = SHR32rCL killed %ebp, implicit-def dead %eflags, implicit %cl + %ebp = XOR32rr killed %ebp, killed %ebx, implicit-def dead %eflags + TEST32rr %edx, %edx, implicit-def %eflags + %cl = SETNEr implicit %eflags + ; This %bl def is antidependent on the above use of %ebx + %bl = MOV8rm %esp, 1, _, 3, _ ; :: (load 1 from %stack.0) + %cl = OR8rr killed %cl, %bl, implicit-def dead %eflags + %esi = MOVZX32rr8 killed %cl + %esi = ADD32rr killed %esi, killed %edi, implicit-def dead %eflags + %ecx = MOV32rm %esp, 1, _, 24, _ ; :: (load 4 from %stack.2) + %edx = SAR32rCL killed %edx, implicit-def dead %eflags, implicit %cl + TEST32rr killed %edx, %edx, implicit-def %eflags + %cl = SETNEr implicit %eflags + ; Verify that removal of the %bl antidependence does not use %ch + ; as a replacement register. + ; CHECK: %cl = AND8rr %cl, killed %b + %cl = AND8rr killed %cl, killed %bl, implicit-def dead %eflags + CMP32ri8 %ebp, -1, implicit-def %eflags + %edx = MOV32ri 0 + JE_1 %bb.3, implicit %eflags + + bb.2: + successors: %bb.3 + liveins: %cl, %eax, %ebp, %esi + + OR32mr %esp, 1, _, 8, _, killed %eax, implicit-def %eflags ; :: (store 4 into %stack.1) + %dl = SETNEr implicit %eflags, implicit-def %edx + + bb.3: + liveins: %cl, %ebp, %edx, %esi + + %eax = XOR32rr undef %eax, undef %eax, implicit-def dead %eflags + %esp = ADD32ri8 %esp, 36, implicit-def dead %eflags + %esi = POP32r implicit-def %esp, implicit %esp + %edi = POP32r implicit-def %esp, implicit %esp + %ebx = POP32r implicit-def %esp, implicit %esp + %ebp = POP32r implicit-def %esp, implicit %esp + RET 0, %eax + +... -- 2.11.0