[ARM64] Teach the ARM64DeadRegisterDefinition pass to respect implicit-defs.

When rematerializing through truncates, the coalescer may produce instructions
with dead defs, but live implicit-defs of subregs:
E.g.
  %X1<def,dead> = MOVi64imm 2, %W1<imp-def>; %X1:GPR64, %W1:GPR32

These instructions are live, and their definitions should not be rewritten.

Fixes <rdar://problem/16492408>



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205565 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Lang Hames 2014-04-03 20:51:08 +00:00
parent 2383986964
commit 89218827c8
2 changed files with 53 additions and 0 deletions

View File

@ -27,6 +27,8 @@ STATISTIC(NumDeadDefsReplaced, "Number of dead definitions replaced");
namespace {
class ARM64DeadRegisterDefinitions : public MachineFunctionPass {
private:
const TargetRegisterInfo *TRI;
bool implicitlyDefinesSubReg(unsigned Reg, const MachineInstr *MI);
bool processMachineBasicBlock(MachineBasicBlock *MBB);
public:
@ -45,6 +47,19 @@ public:
char ARM64DeadRegisterDefinitions::ID = 0;
} // end anonymous namespace
bool ARM64DeadRegisterDefinitions::implicitlyDefinesSubReg(
unsigned Reg,
const MachineInstr *MI) {
for (unsigned i = MI->getNumExplicitOperands(), e = MI->getNumOperands();
i != e; ++i) {
const MachineOperand &MO = MI->getOperand(i);
if (MO.isReg() && MO.isDef())
if (TRI->isSubRegister(Reg, MO.getReg()))
return true;
}
return false;
}
bool
ARM64DeadRegisterDefinitions::processMachineBasicBlock(MachineBasicBlock *MBB) {
bool Changed = false;
@ -62,6 +77,11 @@ ARM64DeadRegisterDefinitions::processMachineBasicBlock(MachineBasicBlock *MBB) {
DEBUG(dbgs() << " Ignoring, def is tied operand.\n");
continue;
}
// Don't change the register if there's an implicit def of a subreg.
if (implicitlyDefinesSubReg(MO.getReg(), MI)) {
DEBUG(dbgs() << " Ignoring, implicitly defines subregister.\n");
continue;
}
// Make sure the instruction take a register class that contains
// the zero register and replace it if so.
unsigned NewReg;
@ -90,6 +110,7 @@ ARM64DeadRegisterDefinitions::processMachineBasicBlock(MachineBasicBlock *MBB) {
// register. Replace that register with the zero register when possible.
bool ARM64DeadRegisterDefinitions::runOnMachineFunction(MachineFunction &mf) {
MachineFunction *MF = &mf;
TRI = MF->getTarget().getRegisterInfo();
bool Changed = false;
DEBUG(dbgs() << "***** ARM64DeadRegisterDefinitions *****\n");

View File

@ -0,0 +1,32 @@
; RUN: llc -mtriple="arm64-apple-ios" < %s | FileCheck %s
;
; Check that the dead register definition pass is considering implicit defs.
; When rematerializing through truncates, the coalescer may produce instructions
; with dead defs, but live implicit-defs of subregs:
; E.g. %X1<def, dead> = MOVi64imm 2, %W1<imp-def>; %X1:GPR64, %W1:GPR32
; These instructions are live, and their definitions should not be rewritten.
;
; <rdar://problem/16492408>
define void @testcase() {
; CHECK: testcase:
; CHECK-NOT: orr xzr, xzr, #0x2
bb1:
%tmp1 = tail call float @ceilf(float 2.000000e+00)
%tmp2 = fptoui float %tmp1 to i64
br i1 undef, label %bb2, label %bb3
bb2:
tail call void @foo()
br label %bb3
bb3:
%tmp3 = trunc i64 %tmp2 to i32
tail call void @bar(i32 %tmp3)
ret void
}
declare void @foo()
declare void @bar(i32)
declare float @ceilf(float) nounwind readnone