mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-29 15:04:57 +00:00
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:
parent
220f6a3b14
commit
e5d7c0d111
@ -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)) {
|
||||
|
@ -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* }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user