Index: llvm/trunk/include/llvm/Target/TargetRegisterInfo.h =================================================================== --- llvm/trunk/include/llvm/Target/TargetRegisterInfo.h +++ llvm/trunk/include/llvm/Target/TargetRegisterInfo.h @@ -495,6 +495,10 @@ /// used by register scavenger to determine what registers are free. virtual BitVector getReservedRegs(const MachineFunction &MF) const = 0; + /// Returns true if PhysReg is unallocatable and constant throughout the + /// function. Used by MachineRegisterInfo::isConstantPhysReg(). + virtual bool isConstantPhysReg(unsigned PhysReg) const { return false; } + /// Prior to adding the live-out mask to a stackmap or patchpoint /// instruction, provide the target the opportunity to adjust it (mainly to /// remove pseudo-registers that should be ignored). Index: llvm/trunk/lib/CodeGen/MachineRegisterInfo.cpp =================================================================== --- llvm/trunk/lib/CodeGen/MachineRegisterInfo.cpp +++ llvm/trunk/lib/CodeGen/MachineRegisterInfo.cpp @@ -468,9 +468,13 @@ const MachineFunction &MF) const { assert(TargetRegisterInfo::isPhysicalRegister(PhysReg)); + const TargetRegisterInfo *TRI = getTargetRegisterInfo(); + if (TRI->isConstantPhysReg(PhysReg)) + return true; + // Check if any overlapping register is modified, or allocatable so it may be // used later. - for (MCRegAliasIterator AI(PhysReg, getTargetRegisterInfo(), true); + for (MCRegAliasIterator AI(PhysReg, TRI, true); AI.isValid(); ++AI) if (!def_empty(*AI) || isAllocatable(*AI)) return false; Index: llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.h =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.h +++ llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.h @@ -62,6 +62,7 @@ CallingConv::ID) const; BitVector getReservedRegs(const MachineFunction &MF) const override; + bool isConstantPhysReg(unsigned PhysReg) const override; const TargetRegisterClass * getPointerRegClass(const MachineFunction &MF, unsigned Kind = 0) const override; Index: llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.cpp +++ llvm/trunk/lib/Target/AArch64/AArch64RegisterInfo.cpp @@ -167,6 +167,10 @@ return false; } +bool AArch64RegisterInfo::isConstantPhysReg(unsigned PhysReg) const { + return PhysReg == AArch64::WZR || PhysReg == AArch64::XZR; +} + const TargetRegisterClass * AArch64RegisterInfo::getPointerRegClass(const MachineFunction &MF, unsigned Kind) const { Index: llvm/trunk/test/CodeGen/MIR/AArch64/machine-sink-zr.mir =================================================================== --- llvm/trunk/test/CodeGen/MIR/AArch64/machine-sink-zr.mir +++ llvm/trunk/test/CodeGen/MIR/AArch64/machine-sink-zr.mir @@ -0,0 +1,48 @@ +# RUN: llc -mtriple=aarch64-none-linux-gnu -run-pass machine-sink -o - %s | FileCheck %s +--- | + define void @sinkwzr() { ret void } +... +--- +name: sinkwzr +tracksRegLiveness: true +registers: + - { id: 0, class: gpr32 } + - { id: 1, class: gpr32 } + - { id: 2, class: gpr32sp } + - { id: 3, class: gpr32 } + - { id: 4, class: gpr32 } +body: | + ; Check that WZR copy is sunk into the loop preheader. + ; CHECK-LABEL: name: sinkwzr + ; CHECK-LABEL: bb.0: + ; CHECK-NOT: COPY %wzr + bb.0: + successors: %bb.3, %bb.1 + liveins: %w0 + + %0 = COPY %w0 + %1 = COPY %wzr + CBZW %0, %bb.3 + + ; CHECK-LABEL: bb.1: + ; CHECK: COPY %wzr + + bb.1: + successors: %bb.2 + + B %bb.2 + + bb.2: + successors: %bb.3, %bb.2 + + %2 = PHI %0, %bb.1, %4, %bb.2 + %w0 = COPY %1 + %3 = SUBSWri %2, 1, 0, implicit-def dead %nzcv + %4 = COPY %3 + CBZW %3, %bb.3 + B %bb.2 + + bb.3: + RET_ReallyLR + +...