diff --git a/llvm/lib/CodeGen/CriticalAntiDepBreaker.cpp b/llvm/lib/CodeGen/CriticalAntiDepBreaker.cpp --- a/llvm/lib/CodeGen/CriticalAntiDepBreaker.cpp +++ b/llvm/lib/CodeGen/CriticalAntiDepBreaker.cpp @@ -212,6 +212,21 @@ if (Classes[Reg] != reinterpret_cast(-1)) RegRefs.insert(std::make_pair(Reg, &MO)); + if (MO.isUse() && Special) { + if (!KeepRegs.test(Reg)) { + for (MCSubRegIterator SubRegs(Reg, TRI, /*IncludeSelf=*/true); + SubRegs.isValid(); ++SubRegs) + KeepRegs.set(*SubRegs); + } + } + } + + for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) { + const MachineOperand &MO = MI.getOperand(I); + if (!MO.isReg()) continue; + Register Reg = MO.getReg(); + if (!Reg.isValid()) + continue; // If this reg is tied and live (Classes[Reg] is set to -1), we can't change // it or any of its sub or super regs. We need to use KeepRegs to mark the // reg because not all uses of the same reg within an instruction are @@ -222,7 +237,7 @@ // of a register? In the above 'xor' example, the uses of %eax are undef, so // earlier instructions could still replace %eax even though the 'xor' // itself can't be changed. - if (MI.isRegTiedToUseOperand(i) && + if (MI.isRegTiedToUseOperand(I) && Classes[Reg] == reinterpret_cast(-1)) { for (MCSubRegIterator SubRegs(Reg, TRI, /*IncludeSelf=*/true); SubRegs.isValid(); ++SubRegs) { @@ -233,14 +248,6 @@ KeepRegs.set(*SuperRegs); } } - - if (MO.isUse() && Special) { - if (!KeepRegs.test(Reg)) { - for (MCSubRegIterator SubRegs(Reg, TRI, /*IncludeSelf=*/true); - SubRegs.isValid(); ++SubRegs) - KeepRegs.set(*SubRegs); - } - } } } diff --git a/llvm/test/CodeGen/X86/tied-depbreak.mir b/llvm/test/CodeGen/X86/tied-depbreak.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/tied-depbreak.mir @@ -0,0 +1,64 @@ +# RUN: llc -mtriple=x86_64-unknown-linux-gnu -mcpu=slm -run-pass post-RA-sched -o - %s | FileCheck %s +# +# Verify that the critical antidependence breaker does not partially +# replace tied operands + +--- | + + define void @main() { ret void } + +... +--- +# CHECK-LABEL: main +name: main +alignment: 16 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +registers: [] +liveins: + - { reg: '$edi', virtual-reg: '' } + - { reg: '$esi', virtual-reg: '' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 1 + adjustsStack: false + hasCalls: false + stackProtector: '' + maxCallFrameSize: 0 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + localFrameSize: 0 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: [] +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: {} +body: | + bb.0: + liveins: $edi, $esi + + $eax = MOV32rr $esi + $eax = LEA64_32r $rdi, 1, $rsi, 0, $noreg + $edi = MOV32rr $esi + $esi = MOV32ri 4 + ; Verify that XOR is untouched by the dependency breaker + ; CHECK: $esi = XOR32rr undef $esi, undef $esi, implicit-def dead $eflags, implicit-def $rsi + $esi = XOR32rr undef $esi, undef $esi, implicit-def dead $eflags, implicit-def $rsi + RETQ killed $eax + +...