mirror of
https://github.com/RPCS3/llvm.git
synced 2024-11-24 20:30:06 +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"
|
||||
#include "ScheduleDAGSDNodes.h"
|
||||
#include "llvm/InlineAsm.h"
|
||||
#include "llvm/CodeGen/SchedulerRegistry.h"
|
||||
#include "llvm/CodeGen/SelectionDAGISel.h"
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
@ -432,6 +433,30 @@ static EVT getPhysicalRegisterVT(SDNode *N, unsigned Reg,
|
||||
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
|
||||
/// 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
|
||||
@ -446,37 +471,44 @@ bool ScheduleDAGFast::DelayForLiveRegsBottomUp(SUnit *SU,
|
||||
for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
|
||||
I != E; ++I) {
|
||||
if (I->isAssignedRegDep()) {
|
||||
unsigned Reg = I->getReg();
|
||||
if (LiveRegDefs[Reg] && LiveRegDefs[Reg] != I->getSUnit()) {
|
||||
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);
|
||||
}
|
||||
CheckForLiveRegDef(I->getSUnit(), I->getReg(), LiveRegDefs,
|
||||
RegAdded, LRegs, TRI);
|
||||
}
|
||||
}
|
||||
|
||||
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())
|
||||
continue;
|
||||
const TargetInstrDesc &TID = TII->get(Node->getMachineOpcode());
|
||||
if (!TID.ImplicitDefs)
|
||||
continue;
|
||||
for (const unsigned *Reg = TID.ImplicitDefs; *Reg; ++Reg) {
|
||||
if (LiveRegDefs[*Reg] && LiveRegDefs[*Reg] != SU) {
|
||||
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);
|
||||
}
|
||||
CheckForLiveRegDef(SU, *Reg, LiveRegDefs, RegAdded, LRegs, TRI);
|
||||
}
|
||||
}
|
||||
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