summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLang Hames <lhames@gmail.com>2014-04-03 20:51:08 +0000
committerLang Hames <lhames@gmail.com>2014-04-03 20:51:08 +0000
commitcb74fa696b2df7b59a3cd1f73600096ee32a60a9 (patch)
treef23e2aef401ad60d5c871b83b8a2855ca13ea897
parent69fcde8b0acb7ca46c057c4df00ffbfd7ad0d1cf (diff)
downloadbcm5719-llvm-cb74fa696b2df7b59a3cd1f73600096ee32a60a9.tar.gz
bcm5719-llvm-cb74fa696b2df7b59a3cd1f73600096ee32a60a9.zip
[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> llvm-svn: 205565
-rw-r--r--llvm/lib/Target/ARM64/ARM64DeadRegisterDefinitionsPass.cpp21
-rw-r--r--llvm/test/CodeGen/ARM64/dead-register-def-bug.ll32
2 files changed, 53 insertions, 0 deletions
diff --git a/llvm/lib/Target/ARM64/ARM64DeadRegisterDefinitionsPass.cpp b/llvm/lib/Target/ARM64/ARM64DeadRegisterDefinitionsPass.cpp
index 3e410e51bee..f85dbaa806f 100644
--- a/llvm/lib/Target/ARM64/ARM64DeadRegisterDefinitionsPass.cpp
+++ b/llvm/lib/Target/ARM64/ARM64DeadRegisterDefinitionsPass.cpp
@@ -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");
diff --git a/llvm/test/CodeGen/ARM64/dead-register-def-bug.ll b/llvm/test/CodeGen/ARM64/dead-register-def-bug.ll
new file mode 100644
index 00000000000..1bbcf50ba73
--- /dev/null
+++ b/llvm/test/CodeGen/ARM64/dead-register-def-bug.ll
@@ -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
OpenPOWER on IntegriCloud