mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-14 07:31:47 +00:00
[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:
parent
2383986964
commit
89218827c8
@ -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");
|
||||
|
||||
|
32
test/CodeGen/ARM64/dead-register-def-bug.ll
Normal file
32
test/CodeGen/ARM64/dead-register-def-bug.ll
Normal 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
|
Loading…
Reference in New Issue
Block a user