mirror of
https://github.com/RPCS3/llvm.git
synced 2024-11-28 14:10:55 +00:00
Fix a serious X86 instruction selection bug. In
X86DAGToDAGISel::PreprocessISelDAG(), isel is moving load inside callseq_start / callseq_end so it can be folded into a call. This can create a cycle in the DAG when the call is glued to a copytoreg. We have been lucky this hasn't caused too many issues because the pre-ra scheduler has special handling of call sequences. However, it has caused a crash in a specific tailcall case. rdar://12393897 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165072 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
394820b8e1
commit
2b87e06d26
@ -362,7 +362,7 @@ X86DAGToDAGISel::IsProfitableToFold(SDValue N, SDNode *U, SDNode *Root) const {
|
||||
/// MoveBelowCallOrigChain - Replace the original chain operand of the call with
|
||||
/// load's chain operand and move load below the call's chain operand.
|
||||
static void MoveBelowOrigChain(SelectionDAG *CurDAG, SDValue Load,
|
||||
SDValue Call, SDValue OrigChain) {
|
||||
SDValue Call, SDValue OrigChain) {
|
||||
SmallVector<SDValue, 8> Ops;
|
||||
SDValue Chain = OrigChain.getOperand(0);
|
||||
if (Chain.getNode() == Load.getNode())
|
||||
@ -386,11 +386,22 @@ static void MoveBelowOrigChain(SelectionDAG *CurDAG, SDValue Load,
|
||||
CurDAG->UpdateNodeOperands(OrigChain.getNode(), &Ops[0], Ops.size());
|
||||
CurDAG->UpdateNodeOperands(Load.getNode(), Call.getOperand(0),
|
||||
Load.getOperand(1), Load.getOperand(2));
|
||||
|
||||
bool IsGlued = Call.getOperand(0).getNode()->getGluedUser() == Call.getNode();
|
||||
unsigned NumOps = Call.getNode()->getNumOperands();
|
||||
Ops.clear();
|
||||
Ops.push_back(SDValue(Load.getNode(), 1));
|
||||
for (unsigned i = 1, e = Call.getNode()->getNumOperands(); i != e; ++i)
|
||||
for (unsigned i = 1, e = NumOps; i != e; ++i)
|
||||
Ops.push_back(Call.getOperand(i));
|
||||
CurDAG->UpdateNodeOperands(Call.getNode(), &Ops[0], Ops.size());
|
||||
if (!IsGlued)
|
||||
CurDAG->UpdateNodeOperands(Call.getNode(), &Ops[0], NumOps);
|
||||
else
|
||||
// If call's chain was glued to the call (tailcall), and now the load
|
||||
// is moved between them. Remove the glue to avoid a cycle (where the
|
||||
// call is glued to its old chain and the load is using the old chain
|
||||
// as its new chain).
|
||||
CurDAG->MorphNodeTo(Call.getNode(), Call.getOpcode(),
|
||||
Call.getNode()->getVTList(), &Ops[0], NumOps-1);
|
||||
}
|
||||
|
||||
/// isCalleeLoad - Return true if call address is a load and it can be
|
||||
|
16
test/CodeGen/X86/2012-10-02-DAGCycle.ll
Normal file
16
test/CodeGen/X86/2012-10-02-DAGCycle.ll
Normal file
@ -0,0 +1,16 @@
|
||||
; RUN: llc -mtriple=i386-apple-macosx -relocation-model=pic < %s
|
||||
; rdar://12393897
|
||||
|
||||
%TRp = type { i32, %TRH*, i32, i32 }
|
||||
%TRH = type { i8*, i8*, i8*, i8*, {}* }
|
||||
|
||||
define i32 @t(%TRp* inreg %rp) nounwind optsize ssp {
|
||||
entry:
|
||||
%handler = getelementptr inbounds %TRp* %rp, i32 0, i32 1
|
||||
%0 = load %TRH** %handler, align 4
|
||||
%sync = getelementptr inbounds %TRH* %0, i32 0, i32 4
|
||||
%sync12 = load {}** %sync, align 4
|
||||
%1 = bitcast {}* %sync12 to i32 (%TRp*)*
|
||||
%call = tail call i32 %1(%TRp* inreg %rp) nounwind optsize
|
||||
ret i32 %call
|
||||
}
|
Loading…
Reference in New Issue
Block a user