From d67705faaa526a31feab831ac1e5e15ee37880a1 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Mon, 11 Apr 2011 21:09:18 +0000 Subject: [PATCH] Look pass copies when determining whether hoisting would end up inserting more copies. rdar://9266679 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@129297 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineLICM.cpp | 25 +++++++++----- test/CodeGen/ARM/2011-04-11-MachineLICMBug.ll | 34 +++++++++++++++++++ 2 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 test/CodeGen/ARM/2011-04-11-MachineLICMBug.ll diff --git a/lib/CodeGen/MachineLICM.cpp b/lib/CodeGen/MachineLICM.cpp index 1c0f6ade856..b315702eef8 100644 --- a/lib/CodeGen/MachineLICM.cpp +++ b/lib/CodeGen/MachineLICM.cpp @@ -39,7 +39,6 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" - using namespace llvm; STATISTIC(NumHoisted, @@ -169,6 +168,10 @@ namespace { /// bool IsLoopInvariantInst(MachineInstr &I); + /// HasAnyPHIUse - Return true if the specified register is used by any + /// phi node. + bool HasAnyPHIUse(unsigned Reg) const; + /// HasHighOperandLatency - Compute operand latency between a def of 'Reg' /// and an use in the current loop, return true if the target considered /// it 'high'. @@ -758,18 +761,25 @@ bool MachineLICM::IsLoopInvariantInst(MachineInstr &I) { } -/// HasPHIUses - Return true if the specified register has any PHI use. -static bool HasPHIUses(unsigned Reg, MachineRegisterInfo *MRI) { +/// HasAnyPHIUse - Return true if the specified register is used by any +/// phi node. +bool MachineLICM::HasAnyPHIUse(unsigned Reg) const { for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(Reg), UE = MRI->use_end(); UI != UE; ++UI) { MachineInstr *UseMI = &*UI; if (UseMI->isPHI()) return true; + // Look pass copies as well. + if (UseMI->isCopy()) { + unsigned Def = UseMI->getOperand(0).getReg(); + if (TargetRegisterInfo::isVirtualRegister(Def) && + HasAnyPHIUse(Def)) + return true; + } } return false; } - /// HasHighOperandLatency - Compute operand latency between a def of 'Reg' /// and an use in the current loop, return true if the target considered /// it 'high'. @@ -976,14 +986,13 @@ bool MachineLICM::IsProfitableToHoist(MachineInstr &MI) { return false; } - // If result(s) of this instruction is used by PHIs, then don't hoist it. - // The presence of joins makes it difficult for current register allocator - // implementation to perform remat. + // If result(s) of this instruction is used by PHIs outside of the loop, then + // don't hoist it if the instruction because it will introduce an extra copy. for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI.getOperand(i); if (!MO.isReg() || !MO.isDef()) continue; - if (HasPHIUses(MO.getReg(), MRI)) + if (HasAnyPHIUse(MO.getReg())) return false; } diff --git a/test/CodeGen/ARM/2011-04-11-MachineLICMBug.ll b/test/CodeGen/ARM/2011-04-11-MachineLICMBug.ll new file mode 100644 index 00000000000..a9dd97182a4 --- /dev/null +++ b/test/CodeGen/ARM/2011-04-11-MachineLICMBug.ll @@ -0,0 +1,34 @@ +; RUN: llc < %s -mtriple=thumbv7-apple-darwin -mcpu=cortex-a8 | FileCheck %s + +; Overly aggressive LICM simply adds copies of constants +; rdar://9266679 + +define zeroext i1 @t(i32* nocapture %A, i32 %size, i32 %value) nounwind readonly ssp { +; CHECK: t: +entry: + br label %for.cond + +for.cond: + %0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ] + %cmp = icmp ult i32 %0, %size + br i1 %cmp, label %for.body, label %return + +for.body: +; CHECK: %for.body +; CHECK: movs r{{[0-9]+}}, #1 + %arrayidx = getelementptr i32* %A, i32 %0 + %tmp4 = load i32* %arrayidx, align 4 + %cmp6 = icmp eq i32 %tmp4, %value + br i1 %cmp6, label %return, label %for.inc + +; CHECK: %for.cond +; CHECK: movs r{{[0-9]+}}, #0 + +for.inc: + %inc = add i32 %0, 1 + br label %for.cond + +return: + %retval.0 = phi i1 [ true, %for.body ], [ false, %for.cond ] + ret i1 %retval.0 +} -- 2.34.1