From: Evan Cheng Date: Fri, 16 Jan 2009 20:57:18 +0000 (+0000) Subject: CreateVirtualRegisters does trivial copy coalescing. If a node def is used by a singl... X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=e57187cbe321a286f6a7f409a7badd1ae4e4642c;p=oota-llvm.git 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 --- diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index 3fb266e0185..d82edae600c 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 7d62b35ee53..52cf4eb998b 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 &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 &VRBaseMap); void CreateVirtualRegisters(SDNode *Node, MachineInstr *MI, const TargetInstrDesc &II, bool IsClone, + bool IsCloned, DenseMap &VRBaseMap); /// BuildSchedUnits, AddSchedEdges - Helper functions for BuildSchedGraph. diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp index 468fd8d4dad..e2c1e285ea4 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 282b53363ef..7bb9bc20c01 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 &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(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(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 &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(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(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 &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(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 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 00000000000..ff20dc1e300 --- /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 ; [#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 ; [#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 ; [#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 ; [#uses=2] + %intAddOverflow = extractvalue { i32, i1 } %0, 1 ; [#uses=1] + %toint56 = ashr i32 %intAdd, 1 ; [#uses=1] + %toFP57 = sitofp i32 %toint56 to 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 ] ; [#uses=0] + unreachable + +FailedVerify: ; preds = %NextVerify42, %prologue + ret %XXV* null + +rematerializeAdd: ; preds = %kjsNumberLiteral.exit + %rematerializedInt = sub i32 %intAdd, 0 ; [#uses=0] + ret %XXV* null + +handle_exception: ; preds = %label + ret %XXV* undef +}