summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2009-01-16 20:57:18 +0000
committerEvan Cheng <evan.cheng@apple.com>2009-01-16 20:57:18 +0000
commite57187cbe321a286f6a7f409a7badd1ae4e4642c (patch)
tree8395fea43586e2ee3e8630576c9a9bbd2cd2c5b3
parenta21a8607e4d35c9e6d6ed276689e84651e602231 (diff)
downloadllvm-e57187cbe321a286f6a7f409a7badd1ae4e4642c.tar.gz
llvm-e57187cbe321a286f6a7f409a7badd1ae4e4642c.tar.bz2
llvm-e57187cbe321a286f6a7f409a7badd1ae4e4642c.tar.xz
CreateVirtualRegisters does trivial copy coalescing. If a node def is used by a single CopyToReg, it reuses the virtual register assigned to the CopyToReg. This won't work for SDNode that is a clone or is itself cloned. Disable this optimization for those nodes or it can end up with non-SSA machine instructions.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@62356 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/CodeGen/ScheduleDAG.h9
-rw-r--r--include/llvm/CodeGen/ScheduleDAGSDNodes.h5
-rw-r--r--lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp1
-rw-r--r--lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp118
-rw-r--r--test/CodeGen/X86/2009-01-16-SchedulerBug.ll50
5 files changed, 121 insertions, 62 deletions
diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h
index 3fb266e018..d82edae600 100644
--- a/include/llvm/CodeGen/ScheduleDAG.h
+++ b/include/llvm/CodeGen/ScheduleDAG.h
@@ -250,6 +250,7 @@ namespace llvm {
bool isAvailable : 1; // True once available.
bool isScheduled : 1; // True once scheduled.
bool isScheduleHigh : 1; // True if preferable to schedule high.
+ bool isCloned : 1; // True if this node has been cloned.
private:
bool isDepthCurrent : 1; // True if Depth is current.
bool isHeightCurrent : 1; // True if Height is current.
@@ -266,8 +267,8 @@ namespace llvm {
Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0),
isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false),
isPending(false), isAvailable(false), isScheduled(false),
- isScheduleHigh(false), isDepthCurrent(false), isHeightCurrent(false),
- Depth(0), Height(0),
+ isScheduleHigh(false), isCloned(false),
+ isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0),
CopyDstRC(NULL), CopySrcRC(NULL) {}
/// SUnit - Construct an SUnit for post-regalloc scheduling to represent
@@ -277,8 +278,8 @@ namespace llvm {
Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0),
isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false),
isPending(false), isAvailable(false), isScheduled(false),
- isScheduleHigh(false), isDepthCurrent(false), isHeightCurrent(false),
- Depth(0), Height(0),
+ isScheduleHigh(false), isCloned(false),
+ isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0),
CopyDstRC(NULL), CopySrcRC(NULL) {}
/// setNode - Assign the representative SDNode for this SUnit.
diff --git a/include/llvm/CodeGen/ScheduleDAGSDNodes.h b/include/llvm/CodeGen/ScheduleDAGSDNodes.h
index 7d62b35ee5..52cf4eb998 100644
--- a/include/llvm/CodeGen/ScheduleDAGSDNodes.h
+++ b/include/llvm/CodeGen/ScheduleDAGSDNodes.h
@@ -107,7 +107,7 @@ namespace llvm {
/// VRBaseMap contains, for each already emitted node, the first virtual
/// register number for the results of the node.
///
- void EmitNode(SDNode *Node, bool IsClone,
+ void EmitNode(SDNode *Node, bool IsClone, bool HasClone,
DenseMap<SDValue, unsigned> &VRBaseMap);
virtual MachineBasicBlock *EmitSchedule();
@@ -144,11 +144,12 @@ namespace llvm {
/// EmitCopyFromReg - Generate machine code for an CopyFromReg node or an
/// implicit physical register output.
void EmitCopyFromReg(SDNode *Node, unsigned ResNo, bool IsClone,
- unsigned SrcReg,
+ bool IsCloned, unsigned SrcReg,
DenseMap<SDValue, unsigned> &VRBaseMap);
void CreateVirtualRegisters(SDNode *Node, MachineInstr *MI,
const TargetInstrDesc &II, bool IsClone,
+ bool IsCloned,
DenseMap<SDValue, unsigned> &VRBaseMap);
/// BuildSchedUnits, AddSchedEdges - Helper functions for BuildSchedGraph.
diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
index 468fd8d4da..e2c1e285ea 100644
--- a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
+++ b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
@@ -33,6 +33,7 @@ SUnit *ScheduleDAGSDNodes::Clone(SUnit *Old) {
SU->isTwoAddress = Old->isTwoAddress;
SU->isCommutable = Old->isCommutable;
SU->hasPhysRegDefs = Old->hasPhysRegDefs;
+ Old->isCloned = true;
return SU;
}
diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp
index 282b53363e..7bb9bc20c0 100644
--- a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp
+++ b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp
@@ -46,7 +46,8 @@ getInstrOperandRegClass(const TargetRegisterInfo *TRI,
/// EmitCopyFromReg - Generate machine code for an CopyFromReg node or an
/// implicit physical register output.
void ScheduleDAGSDNodes::EmitCopyFromReg(SDNode *Node, unsigned ResNo,
- bool IsClone, unsigned SrcReg,
+ bool IsClone, bool IsCloned,
+ unsigned SrcReg,
DenseMap<SDValue, unsigned> &VRBaseMap) {
unsigned VRBase = 0;
if (TargetRegisterInfo::isVirtualRegister(SrcReg)) {
@@ -64,44 +65,45 @@ void ScheduleDAGSDNodes::EmitCopyFromReg(SDNode *Node, unsigned ResNo,
// the CopyToReg'd destination register instead of creating a new vreg.
bool MatchReg = true;
const TargetRegisterClass *UseRC = NULL;
- for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
- UI != E; ++UI) {
- SDNode *User = *UI;
- bool Match = true;
- if (User->getOpcode() == ISD::CopyToReg &&
- User->getOperand(2).getNode() == Node &&
- User->getOperand(2).getResNo() == ResNo) {
- unsigned DestReg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
- if (TargetRegisterInfo::isVirtualRegister(DestReg)) {
- VRBase = DestReg;
- Match = false;
- } else if (DestReg != SrcReg)
- Match = false;
- } else {
- for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i) {
- SDValue Op = User->getOperand(i);
- if (Op.getNode() != Node || Op.getResNo() != ResNo)
- continue;
- MVT VT = Node->getValueType(Op.getResNo());
- if (VT == MVT::Other || VT == MVT::Flag)
- continue;
- Match = false;
- if (User->isMachineOpcode()) {
- const TargetInstrDesc &II = TII->get(User->getMachineOpcode());
- const TargetRegisterClass *RC =
- getInstrOperandRegClass(TRI,TII,II,i+II.getNumDefs());
- if (!UseRC)
- UseRC = RC;
- else if (RC)
- assert(UseRC == RC &&
- "Multiple uses expecting different register classes!");
+ if (!IsClone && !IsCloned)
+ for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
+ UI != E; ++UI) {
+ SDNode *User = *UI;
+ bool Match = true;
+ if (User->getOpcode() == ISD::CopyToReg &&
+ User->getOperand(2).getNode() == Node &&
+ User->getOperand(2).getResNo() == ResNo) {
+ unsigned DestReg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
+ if (TargetRegisterInfo::isVirtualRegister(DestReg)) {
+ VRBase = DestReg;
+ Match = false;
+ } else if (DestReg != SrcReg)
+ Match = false;
+ } else {
+ for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i) {
+ SDValue Op = User->getOperand(i);
+ if (Op.getNode() != Node || Op.getResNo() != ResNo)
+ continue;
+ MVT VT = Node->getValueType(Op.getResNo());
+ if (VT == MVT::Other || VT == MVT::Flag)
+ continue;
+ Match = false;
+ if (User->isMachineOpcode()) {
+ const TargetInstrDesc &II = TII->get(User->getMachineOpcode());
+ const TargetRegisterClass *RC =
+ getInstrOperandRegClass(TRI,TII,II,i+II.getNumDefs());
+ if (!UseRC)
+ UseRC = RC;
+ else if (RC)
+ assert(UseRC == RC &&
+ "Multiple uses expecting different register classes!");
+ }
}
}
+ MatchReg &= Match;
+ if (VRBase)
+ break;
}
- MatchReg &= Match;
- if (VRBase)
- break;
- }
MVT VT = Node->getValueType(ResNo);
const TargetRegisterClass *SrcRC = 0, *DstRC = 0;
@@ -157,7 +159,8 @@ unsigned ScheduleDAGSDNodes::getDstOfOnlyCopyToRegUse(SDNode *Node,
}
void ScheduleDAGSDNodes::CreateVirtualRegisters(SDNode *Node, MachineInstr *MI,
- const TargetInstrDesc &II, bool IsClone,
+ const TargetInstrDesc &II,
+ bool IsClone, bool IsCloned,
DenseMap<SDValue, unsigned> &VRBaseMap) {
assert(Node->getMachineOpcode() != TargetInstrInfo::IMPLICIT_DEF &&
"IMPLICIT_DEF should have been handled as a special case elsewhere!");
@@ -167,20 +170,22 @@ void ScheduleDAGSDNodes::CreateVirtualRegisters(SDNode *Node, MachineInstr *MI,
// is a vreg, use the CopyToReg'd destination register instead of creating
// a new vreg.
unsigned VRBase = 0;
- for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
- UI != E; ++UI) {
- SDNode *User = *UI;
- if (User->getOpcode() == ISD::CopyToReg &&
- User->getOperand(2).getNode() == Node &&
- User->getOperand(2).getResNo() == i) {
- unsigned Reg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
- if (TargetRegisterInfo::isVirtualRegister(Reg)) {
- VRBase = Reg;
- MI->addOperand(MachineOperand::CreateReg(Reg, true));
- break;
+
+ if (!IsClone && !IsCloned)
+ for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
+ UI != E; ++UI) {
+ SDNode *User = *UI;
+ if (User->getOpcode() == ISD::CopyToReg &&
+ User->getOperand(2).getNode() == Node &&
+ User->getOperand(2).getResNo() == i) {
+ unsigned Reg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
+ if (TargetRegisterInfo::isVirtualRegister(Reg)) {
+ VRBase = Reg;
+ MI->addOperand(MachineOperand::CreateReg(Reg, true));
+ break;
+ }
}
}
- }
// Create the result registers for this node and add the result regs to
// the machine instruction.
@@ -452,7 +457,7 @@ void ScheduleDAGSDNodes::EmitSubregNode(SDNode *Node,
/// EmitNode - Generate machine code for an node and needed dependencies.
///
-void ScheduleDAGSDNodes::EmitNode(SDNode *Node, bool IsClone,
+void ScheduleDAGSDNodes::EmitNode(SDNode *Node, bool IsClone, bool IsCloned,
DenseMap<SDValue, unsigned> &VRBaseMap) {
// If machine instruction
if (Node->isMachineOpcode()) {
@@ -489,7 +494,7 @@ void ScheduleDAGSDNodes::EmitNode(SDNode *Node, bool IsClone,
// Add result register values for things that are defined by this
// instruction.
if (NumResults)
- CreateVirtualRegisters(Node, MI, II, IsClone, VRBaseMap);
+ CreateVirtualRegisters(Node, MI, II, IsClone, IsCloned, VRBaseMap);
// Emit all of the actual operands of this instruction, adding them to the
// instruction as appropriate.
@@ -512,7 +517,7 @@ void ScheduleDAGSDNodes::EmitNode(SDNode *Node, bool IsClone,
for (unsigned i = II.getNumDefs(); i < NumResults; ++i) {
unsigned Reg = II.getImplicitDefs()[i - II.getNumDefs()];
if (Node->hasAnyUseOfValue(i))
- EmitCopyFromReg(Node, i, IsClone, Reg, VRBaseMap);
+ EmitCopyFromReg(Node, i, IsClone, IsCloned, Reg, VRBaseMap);
}
}
return;
@@ -559,7 +564,7 @@ void ScheduleDAGSDNodes::EmitNode(SDNode *Node, bool IsClone,
}
case ISD::CopyFromReg: {
unsigned SrcReg = cast<RegisterSDNode>(Node->getOperand(1))->getReg();
- EmitCopyFromReg(Node, 0, IsClone, SrcReg, VRBaseMap);
+ EmitCopyFromReg(Node, 0, IsClone, IsCloned, SrcReg, VRBaseMap);
break;
}
case ISD::INLINEASM: {
@@ -636,13 +641,14 @@ MachineBasicBlock *ScheduleDAGSDNodes::EmitSchedule() {
}
SmallVector<SDNode *, 4> FlaggedNodes;
- for (SDNode *N = SU->getNode()->getFlaggedNode(); N; N = N->getFlaggedNode())
+ for (SDNode *N = SU->getNode()->getFlaggedNode(); N;
+ N = N->getFlaggedNode())
FlaggedNodes.push_back(N);
while (!FlaggedNodes.empty()) {
- EmitNode(FlaggedNodes.back(), SU->OrigNode != SU, VRBaseMap);
+ EmitNode(FlaggedNodes.back(), SU->OrigNode != SU, SU->isCloned,VRBaseMap);
FlaggedNodes.pop_back();
}
- EmitNode(SU->getNode(), SU->OrigNode != SU, VRBaseMap);
+ EmitNode(SU->getNode(), SU->OrigNode != SU, SU->isCloned, VRBaseMap);
}
return BB;
diff --git a/test/CodeGen/X86/2009-01-16-SchedulerBug.ll b/test/CodeGen/X86/2009-01-16-SchedulerBug.ll
new file mode 100644
index 0000000000..ff20dc1e30
--- /dev/null
+++ b/test/CodeGen/X86/2009-01-16-SchedulerBug.ll
@@ -0,0 +1,50 @@
+; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin
+; rdar://6501631
+
+ %CF = type { %Register }
+ %XXV = type { i32 (...)** }
+ %Register = type { %"struct.XXC::BCFs", i32 }
+ %"struct.XXC::BCFs" = type { i32 }
+
+declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32) nounwind
+
+define fastcc %XXV* @bar(%CF* %call_frame, %XXV** %exception) nounwind {
+prologue:
+ %param_x = load %XXV** null ; <%XXV*> [#uses=1]
+ %unique_1.i = ptrtoint %XXV* %param_x to i1 ; <i1> [#uses=1]
+ br i1 %unique_1.i, label %NextVerify42, label %FailedVerify
+
+NextVerify42: ; preds = %prologue
+ %param_y = load %XXV** null ; <%XXV*> [#uses=1]
+ %unique_1.i58 = ptrtoint %XXV* %param_y to i1 ; <i1> [#uses=1]
+ br i1 %unique_1.i58, label %function_setup.cont, label %FailedVerify
+
+function_setup.cont: ; preds = %NextVerify42
+ br i1 false, label %label13, label %label
+
+label: ; preds = %function_setup.cont
+ %has_exn = icmp eq %XXV* null, null ; <i1> [#uses=1]
+ br i1 %has_exn, label %kjsNumberLiteral.exit, label %handle_exception
+
+kjsNumberLiteral.exit: ; preds = %label
+ %0 = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 0, i32 0) ; <{ i32, i1 }> [#uses=2]
+ %intAdd = extractvalue { i32, i1 } %0, 0 ; <i32> [#uses=2]
+ %intAddOverflow = extractvalue { i32, i1 } %0, 1 ; <i1> [#uses=1]
+ %toint56 = ashr i32 %intAdd, 1 ; <i32> [#uses=1]
+ %toFP57 = sitofp i32 %toint56 to double ; <double> [#uses=1]
+ br i1 %intAddOverflow, label %rematerializeAdd, label %label13
+
+label13: ; preds = %kjsNumberLiteral.exit, %function_setup.cont
+ %var_lr1.0 = phi double [ %toFP57, %kjsNumberLiteral.exit ], [ 0.000000e+00, %function_setup.cont ] ; <double> [#uses=0]
+ unreachable
+
+FailedVerify: ; preds = %NextVerify42, %prologue
+ ret %XXV* null
+
+rematerializeAdd: ; preds = %kjsNumberLiteral.exit
+ %rematerializedInt = sub i32 %intAdd, 0 ; <i32> [#uses=0]
+ ret %XXV* null
+
+handle_exception: ; preds = %label
+ ret %XXV* undef
+}