PreRA scheduler should avoid cloning compares.

Added canClobberReachingPhysRegUse() to handle a particular pattern in
which a two-address instruction could be forced to interfere with
EFLAGS, causing a compare to be unnecessarilly cloned.
Fixes rdar://problem/5875261

llvm-svn: 138924
This commit is contained in:
Andrew Trick 2011-09-01 00:54:31 +00:00
parent 220f6a3b14
commit e5d7c0d111
2 changed files with 44 additions and 2 deletions

View File

@ -2621,6 +2621,39 @@ bool RegReductionPQBase::canClobber(const SUnit *SU, const SUnit *Op) {
return false;
}
/// canClobberReachingPhysRegUse - True if SU would clobber one of it's
/// successor's explicit physregs whose definition can reach DepSU.
/// i.e. DepSU should not be scheduled above SU.
static bool canClobberReachingPhysRegUse(const SUnit *DepSU, const SUnit *SU,
ScheduleDAGRRList *scheduleDAG,
const TargetInstrInfo *TII,
const TargetRegisterInfo *TRI) {
const unsigned *ImpDefs
= TII->get(SU->getNode()->getMachineOpcode()).getImplicitDefs();
if(!ImpDefs)
return false;
for (SUnit::const_succ_iterator SI = SU->Succs.begin(), SE = SU->Succs.end();
SI != SE; ++SI) {
SUnit *SuccSU = SI->getSUnit();
for (SUnit::const_pred_iterator PI = SuccSU->Preds.begin(),
PE = SuccSU->Preds.end(); PI != PE; ++PI) {
if (!PI->isAssignedRegDep())
continue;
for (const unsigned *ImpDef = ImpDefs; *ImpDef; ++ImpDef) {
// Return true if SU clobbers this physical register use and the
// definition of the register reaches from DepSU. IsReachable queries a
// topological forward sort of the DAG (following the successors).
if (TRI->regsOverlap(*ImpDef, PI->getReg()) &&
scheduleDAG->IsReachable(DepSU, PI->getSUnit()))
return true;
}
}
}
return false;
}
/// canClobberPhysRegDefs - True if SU would clobber one of SuccSU's
/// physical register defs.
static bool canClobberPhysRegDefs(const SUnit *SuccSU, const SUnit *SU,
@ -2837,7 +2870,8 @@ void RegReductionPQBase::AddPseudoTwoAddrDeps() {
SuccOpc == TargetOpcode::INSERT_SUBREG ||
SuccOpc == TargetOpcode::SUBREG_TO_REG)
continue;
if ((!canClobber(SuccSU, DUSU) ||
if (!canClobberReachingPhysRegUse(SuccSU, SU, scheduleDAG, TII, TRI) &&
(!canClobber(SuccSU, DUSU) ||
(isLiveOut && !hasOnlyLiveOutUses(SuccSU)) ||
(!SU->isCommutable && SuccSU->isCommutable)) &&
!scheduleDAG->IsReachable(SuccSU, SU)) {

View File

@ -1,4 +1,12 @@
; RUN: llc < %s -march=x86 | not grep pushf
; RUN: llc < %s -march=x86 | FileCheck %s
;
; Test scheduling a multi-use compare. We should neither spill flags
; nor clone the compare.
; CHECK: cmp
; CHECK-NOT: pushf
; CHECK: cmov
; CHECK-NOT: cmp
; CHECK: cmov
%struct.indexentry = type { i32, i8*, i8*, i8*, i8*, i8* }