diff options
| -rw-r--r-- | llvm/include/llvm/CodeGen/ScheduleDAG.h | 9 | ||||
| -rw-r--r-- | llvm/include/llvm/CodeGen/ScheduleDAGSDNodes.h | 5 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp | 1 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp | 118 | ||||
| -rw-r--r-- | llvm/test/CodeGen/X86/2009-01-16-SchedulerBug.ll | 50 | 
5 files changed, 121 insertions, 62 deletions
diff --git a/llvm/include/llvm/CodeGen/ScheduleDAG.h b/llvm/include/llvm/CodeGen/ScheduleDAG.h index 3fb266e0185..d82edae600c 100644 --- a/llvm/include/llvm/CodeGen/ScheduleDAG.h +++ b/llvm/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/llvm/include/llvm/CodeGen/ScheduleDAGSDNodes.h b/llvm/include/llvm/CodeGen/ScheduleDAGSDNodes.h index 7d62b35ee53..52cf4eb998b 100644 --- a/llvm/include/llvm/CodeGen/ScheduleDAGSDNodes.h +++ b/llvm/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/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp index 468fd8d4dad..e2c1e285ea4 100644 --- a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp +++ b/llvm/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/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp index 282b53363ef..7bb9bc20c01 100644 --- a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp +++ b/llvm/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/llvm/test/CodeGen/X86/2009-01-16-SchedulerBug.ll b/llvm/test/CodeGen/X86/2009-01-16-SchedulerBug.ll new file mode 100644 index 00000000000..ff20dc1e300 --- /dev/null +++ b/llvm/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 +}  | 

