diff --git a/llvm/include/llvm/MC/MCRegisterInfo.h b/llvm/include/llvm/MC/MCRegisterInfo.h index 73f29d0f521ed..164ef1ef44bbb 100644 --- a/llvm/include/llvm/MC/MCRegisterInfo.h +++ b/llvm/include/llvm/MC/MCRegisterInfo.h @@ -404,6 +404,11 @@ class MCRegisterInfo { /// be modelled, such as the top 16-bits of a 32-bit GPR. bool isArtificial(MCRegister RegNo) const { return get(RegNo).IsArtificial; } + /// Returns true when the given register unit is considered artificial. + /// Register units are considered artificial when at least one of the + /// root registers is artificial. + bool isArtificialRegUnit(MCRegUnit Unit) const; + /// Return the number of registers this target has (useful for /// sizing arrays holding per register information) unsigned getNumRegs() const { diff --git a/llvm/lib/CodeGen/LiveIntervals.cpp b/llvm/lib/CodeGen/LiveIntervals.cpp index a0b6bf445fa8a..f9ee6e4563f8d 100644 --- a/llvm/lib/CodeGen/LiveIntervals.cpp +++ b/llvm/lib/CodeGen/LiveIntervals.cpp @@ -730,7 +730,12 @@ void LiveIntervals::addKillFlags(const VirtRegMap *VRM) { // Find the regunit intervals for the assigned register. They may overlap // the virtual register live range, cancelling any kills. RU.clear(); - for (MCRegUnit Unit : TRI->regunits(PhysReg)) { + LaneBitmask ArtificialLanes; + for (MCRegUnitMaskIterator UI(PhysReg, TRI); UI.isValid(); ++UI) { + auto [Unit, Bitmask] = *UI; + // Record lane mask for all artificial RegUnits for this physreg. + if (TRI->isArtificialRegUnit(Unit)) + ArtificialLanes |= Bitmask; const LiveRange &RURange = getRegUnit(Unit); if (RURange.empty()) continue; @@ -782,7 +787,11 @@ void LiveIntervals::addKillFlags(const VirtRegMap *VRM) { LaneBitmask DefinedLanesMask; if (LI.hasSubRanges()) { // Compute a mask of lanes that are defined. - DefinedLanesMask = LaneBitmask::getNone(); + // Artificial regunits are not independently allocatable so the + // register allocator cannot have used them to represent any other + // values. That's why we mark them as 'defined' here, as this + // otherwise prevents kill flags from being added. + DefinedLanesMask = ArtificialLanes; for (const LiveInterval::SubRange &SR : LI.subranges()) for (const LiveRange::Segment &Segment : SR.segments) { if (Segment.start >= RI->end) diff --git a/llvm/lib/MC/MCRegisterInfo.cpp b/llvm/lib/MC/MCRegisterInfo.cpp index 178b1d21e5200..4a9bacdbc8fc4 100644 --- a/llvm/lib/MC/MCRegisterInfo.cpp +++ b/llvm/lib/MC/MCRegisterInfo.cpp @@ -220,3 +220,10 @@ bool MCRegisterInfo::regsOverlap(MCRegister RegA, MCRegister RegB) const { } while (*IA < *IB ? ++IA != EA : ++IB != EB); return false; } + +bool MCRegisterInfo::isArtificialRegUnit(unsigned Unit) const { + for (MCRegUnitRootIterator Root(Unit, this); Root.isValid(); ++Root) + if (isArtificial(*Root)) + return true; + return false; +} diff --git a/llvm/test/CodeGen/AArch64/arm64-addrmode.ll b/llvm/test/CodeGen/AArch64/arm64-addrmode.ll index bfef61abd8c12..f8695b62619c0 100644 --- a/llvm/test/CodeGen/AArch64/arm64-addrmode.ll +++ b/llvm/test/CodeGen/AArch64/arm64-addrmode.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc -mtriple=arm64-eabi < %s | FileCheck %s +; RUN: llc -aarch64-enable-subreg-liveness-tracking -mtriple=arm64-eabi < %s | FileCheck %s ; rdar://10232252 @object = external hidden global i64, section "__DATA, __objc_ivar", align 8 diff --git a/llvm/test/CodeGen/AArch64/nested-iv-regalloc.mir b/llvm/test/CodeGen/AArch64/nested-iv-regalloc.mir index 3bd8f83d27c2d..ff29c78b5a0ce 100644 --- a/llvm/test/CodeGen/AArch64/nested-iv-regalloc.mir +++ b/llvm/test/CodeGen/AArch64/nested-iv-regalloc.mir @@ -1,5 +1,5 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py -# RUN: llc -mtriple aarch64 --run-pass=greedy,virtregrewriter -verify-machineinstrs %s -o - | FileCheck %s +# RUN: llc -mtriple aarch64 -aarch64-enable-subreg-liveness-tracking --run-pass=greedy,virtregrewriter -verify-machineinstrs %s -o - | FileCheck %s # We should ideally not spill around any of the SUBSWri in the loop exit blocks (if.end and if.end27). @@ -219,7 +219,7 @@ body: | ; CHECK-NEXT: liveins: $w10, $w11, $x2, $x8 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: STRXui renamable $x8, %stack.1, 0 :: (store (s64) into %stack.1) - ; CHECK-NEXT: renamable $w9 = MOVi32imm 36, implicit-def $x9 + ; CHECK-NEXT: renamable $w9 = MOVi32imm 36 ; CHECK-NEXT: renamable $x8 = MADDXrrr killed renamable $x8, killed renamable $x9, $xzr ; CHECK-NEXT: renamable $x9 = MOVaddr target-flags(aarch64-page) @g, target-flags(aarch64-pageoff, aarch64-nc) @g ; CHECK-NEXT: renamable $w8 = LDRWroX killed renamable $x9, killed renamable $x8, 0, 0 :: (load (s32) from %ir.arrayidx9) @@ -244,7 +244,7 @@ body: | ; CHECK-NEXT: successors: %bb.5(0x50000000), %bb.8(0x30000000) ; CHECK-NEXT: liveins: $w10, $w11, $x2, $x12 ; CHECK-NEXT: {{ $}} - ; CHECK-NEXT: renamable $w8 = MOVi32imm 36, implicit-def $x8 + ; CHECK-NEXT: renamable $w8 = MOVi32imm 36 ; CHECK-NEXT: renamable $x8 = MADDXrrr renamable $x12, killed renamable $x8, $xzr ; CHECK-NEXT: renamable $x9 = MOVaddr target-flags(aarch64-page) @g, target-flags(aarch64-pageoff, aarch64-nc) @g ; CHECK-NEXT: renamable $w8 = LDRWroX killed renamable $x9, killed renamable $x8, 0, 0 :: (load (s32) from %ir.arrayidx14) diff --git a/llvm/test/CodeGen/AArch64/preserve_nonecc_varargs_darwin.ll b/llvm/test/CodeGen/AArch64/preserve_nonecc_varargs_darwin.ll index e227f14542cc1..2a77d4dd33fe5 100644 --- a/llvm/test/CodeGen/AArch64/preserve_nonecc_varargs_darwin.ll +++ b/llvm/test/CodeGen/AArch64/preserve_nonecc_varargs_darwin.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 -; RUN: llc -mtriple=aarch64-apple-darwin < %s | FileCheck %s +; RUN: llc -mtriple=aarch64-apple-darwin -aarch64-enable-subreg-liveness-tracking < %s | FileCheck %s define preserve_nonecc i32 @callee(i32 %a1, i32 %a2, i32 %a3, i32 %a4, i32 %a5, ...) nounwind noinline ssp { ; CHECK-LABEL: callee: @@ -27,12 +27,11 @@ define i32 @caller() nounwind ssp { ; CHECK-NEXT: sub sp, sp, #208 ; CHECK-NEXT: mov w8, #10 ; =0xa ; CHECK-NEXT: mov w9, #9 ; =0x9 -; CHECK-NEXT: mov w0, #1 ; =0x1 +; CHECK-NEXT: mov w10, #8 ; =0x8 ; CHECK-NEXT: stp x9, x8, [sp, #24] -; CHECK-NEXT: mov w8, #8 ; =0x8 -; CHECK-NEXT: mov w9, #6 ; =0x6 -; CHECK-NEXT: str x8, [sp, #16] ; CHECK-NEXT: mov w8, #7 ; =0x7 +; CHECK-NEXT: mov w9, #6 ; =0x6 +; CHECK-NEXT: mov w0, #1 ; =0x1 ; CHECK-NEXT: mov w1, #2 ; =0x2 ; CHECK-NEXT: mov w2, #3 ; =0x3 ; CHECK-NEXT: mov w3, #4 ; =0x4 @@ -47,7 +46,8 @@ define i32 @caller() nounwind ssp { ; CHECK-NEXT: stp x22, x21, [sp, #160] ; 16-byte Folded Spill ; CHECK-NEXT: stp x20, x19, [sp, #176] ; 16-byte Folded Spill ; CHECK-NEXT: stp x29, x30, [sp, #192] ; 16-byte Folded Spill -; CHECK-NEXT: stp x9, x8, [sp] +; CHECK-NEXT: stp x8, x10, [sp, #8] +; CHECK-NEXT: str x9, [sp] ; CHECK-NEXT: bl _callee ; CHECK-NEXT: ldp x29, x30, [sp, #192] ; 16-byte Folded Reload ; CHECK-NEXT: ldp x20, x19, [sp, #176] ; 16-byte Folded Reload