mirror of
https://github.com/RPCS3/llvm.git
synced 2024-11-28 14:10:55 +00:00
Make fast scheduler handle asm clobbers correctly.
PR 7882. Follows suggestion by Amaury Pouly, thanks. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@111306 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
5dad73cec8
commit
6cf64a631a
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#define DEBUG_TYPE "pre-RA-sched"
|
#define DEBUG_TYPE "pre-RA-sched"
|
||||||
#include "ScheduleDAGSDNodes.h"
|
#include "ScheduleDAGSDNodes.h"
|
||||||
|
#include "llvm/InlineAsm.h"
|
||||||
#include "llvm/CodeGen/SchedulerRegistry.h"
|
#include "llvm/CodeGen/SchedulerRegistry.h"
|
||||||
#include "llvm/CodeGen/SelectionDAGISel.h"
|
#include "llvm/CodeGen/SelectionDAGISel.h"
|
||||||
#include "llvm/Target/TargetRegisterInfo.h"
|
#include "llvm/Target/TargetRegisterInfo.h"
|
||||||
@ -432,6 +433,30 @@ static EVT getPhysicalRegisterVT(SDNode *N, unsigned Reg,
|
|||||||
return N->getValueType(NumRes);
|
return N->getValueType(NumRes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// CheckForLiveRegDef - Return true and update live register vector if the
|
||||||
|
/// specified register def of the specified SUnit clobbers any "live" registers.
|
||||||
|
static bool CheckForLiveRegDef(SUnit *SU, unsigned Reg,
|
||||||
|
std::vector<SUnit*> &LiveRegDefs,
|
||||||
|
SmallSet<unsigned, 4> &RegAdded,
|
||||||
|
SmallVector<unsigned, 4> &LRegs,
|
||||||
|
const TargetRegisterInfo *TRI) {
|
||||||
|
bool Added = false;
|
||||||
|
if (LiveRegDefs[Reg] && LiveRegDefs[Reg] != SU) {
|
||||||
|
if (RegAdded.insert(Reg)) {
|
||||||
|
LRegs.push_back(Reg);
|
||||||
|
Added = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const unsigned *Alias = TRI->getAliasSet(Reg); *Alias; ++Alias)
|
||||||
|
if (LiveRegDefs[*Alias] && LiveRegDefs[*Alias] != SU) {
|
||||||
|
if (RegAdded.insert(*Alias)) {
|
||||||
|
LRegs.push_back(*Alias);
|
||||||
|
Added = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Added;
|
||||||
|
}
|
||||||
|
|
||||||
/// DelayForLiveRegsBottomUp - Returns true if it is necessary to delay
|
/// DelayForLiveRegsBottomUp - Returns true if it is necessary to delay
|
||||||
/// scheduling of the given node to satisfy live physical register dependencies.
|
/// scheduling of the given node to satisfy live physical register dependencies.
|
||||||
/// If the specific node is the last one that's available to schedule, do
|
/// If the specific node is the last one that's available to schedule, do
|
||||||
@ -446,37 +471,44 @@ bool ScheduleDAGFast::DelayForLiveRegsBottomUp(SUnit *SU,
|
|||||||
for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
|
for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
|
||||||
I != E; ++I) {
|
I != E; ++I) {
|
||||||
if (I->isAssignedRegDep()) {
|
if (I->isAssignedRegDep()) {
|
||||||
unsigned Reg = I->getReg();
|
CheckForLiveRegDef(I->getSUnit(), I->getReg(), LiveRegDefs,
|
||||||
if (LiveRegDefs[Reg] && LiveRegDefs[Reg] != I->getSUnit()) {
|
RegAdded, LRegs, TRI);
|
||||||
if (RegAdded.insert(Reg))
|
|
||||||
LRegs.push_back(Reg);
|
|
||||||
}
|
|
||||||
for (const unsigned *Alias = TRI->getAliasSet(Reg);
|
|
||||||
*Alias; ++Alias)
|
|
||||||
if (LiveRegDefs[*Alias] && LiveRegDefs[*Alias] != I->getSUnit()) {
|
|
||||||
if (RegAdded.insert(*Alias))
|
|
||||||
LRegs.push_back(*Alias);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (SDNode *Node = SU->getNode(); Node; Node = Node->getFlaggedNode()) {
|
for (SDNode *Node = SU->getNode(); Node; Node = Node->getFlaggedNode()) {
|
||||||
|
if (Node->getOpcode() == ISD::INLINEASM) {
|
||||||
|
// Inline asm can clobber physical defs.
|
||||||
|
unsigned NumOps = Node->getNumOperands();
|
||||||
|
if (Node->getOperand(NumOps-1).getValueType() == MVT::Flag)
|
||||||
|
--NumOps; // Ignore the flag operand.
|
||||||
|
|
||||||
|
for (unsigned i = InlineAsm::Op_FirstOperand; i != NumOps;) {
|
||||||
|
unsigned Flags =
|
||||||
|
cast<ConstantSDNode>(Node->getOperand(i))->getZExtValue();
|
||||||
|
unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);
|
||||||
|
|
||||||
|
++i; // Skip the ID value.
|
||||||
|
if (InlineAsm::isRegDefKind(Flags) ||
|
||||||
|
InlineAsm::isRegDefEarlyClobberKind(Flags)) {
|
||||||
|
// Check for def of register or earlyclobber register.
|
||||||
|
for (; NumVals; --NumVals, ++i) {
|
||||||
|
unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg();
|
||||||
|
if (TargetRegisterInfo::isPhysicalRegister(Reg))
|
||||||
|
CheckForLiveRegDef(SU, Reg, LiveRegDefs, RegAdded, LRegs, TRI);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
i += NumVals;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!Node->isMachineOpcode())
|
if (!Node->isMachineOpcode())
|
||||||
continue;
|
continue;
|
||||||
const TargetInstrDesc &TID = TII->get(Node->getMachineOpcode());
|
const TargetInstrDesc &TID = TII->get(Node->getMachineOpcode());
|
||||||
if (!TID.ImplicitDefs)
|
if (!TID.ImplicitDefs)
|
||||||
continue;
|
continue;
|
||||||
for (const unsigned *Reg = TID.ImplicitDefs; *Reg; ++Reg) {
|
for (const unsigned *Reg = TID.ImplicitDefs; *Reg; ++Reg) {
|
||||||
if (LiveRegDefs[*Reg] && LiveRegDefs[*Reg] != SU) {
|
CheckForLiveRegDef(SU, *Reg, LiveRegDefs, RegAdded, LRegs, TRI);
|
||||||
if (RegAdded.insert(*Reg))
|
|
||||||
LRegs.push_back(*Reg);
|
|
||||||
}
|
|
||||||
for (const unsigned *Alias = TRI->getAliasSet(*Reg);
|
|
||||||
*Alias; ++Alias)
|
|
||||||
if (LiveRegDefs[*Alias] && LiveRegDefs[*Alias] != SU) {
|
|
||||||
if (RegAdded.insert(*Alias))
|
|
||||||
LRegs.push_back(*Alias);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return !LRegs.empty();
|
return !LRegs.empty();
|
||||||
|
17
test/CodeGen/X86/pr7882.ll
Normal file
17
test/CodeGen/X86/pr7882.ll
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
; RUN: llc < %s -march=x86 -mtriple=i686-apple-darwin -pre-RA-sched=fast \
|
||||||
|
; RUN: | FileCheck %s
|
||||||
|
; make sure scheduler honors the flags clobber. PR 7882.
|
||||||
|
|
||||||
|
define i32 @main(i32 %argc, i8** %argv) nounwind
|
||||||
|
{
|
||||||
|
entry:
|
||||||
|
; CHECK: InlineAsm End
|
||||||
|
; CHECK: cmpl
|
||||||
|
%res = icmp slt i32 1, %argc
|
||||||
|
%tmp = call i32 asm sideeffect alignstack
|
||||||
|
"push $$0
|
||||||
|
popf
|
||||||
|
mov $$13, $0", "=r,r,~{memory},~{flags}" (i1 %res)
|
||||||
|
%ret = select i1 %res, i32 %tmp, i32 42
|
||||||
|
ret i32 %ret
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user