diff options
| author | Chris Lattner <sabre@nondot.org> | 2005-01-07 07:46:32 +0000 | 
|---|---|---|
| committer | Chris Lattner <sabre@nondot.org> | 2005-01-07 07:46:32 +0000 | 
| commit | 061a1ea9e3817bbf75fb83596ec7f848251f32f5 (patch) | |
| tree | f805ff2c74b9f4376291911925352ea641a959c3 | |
| parent | 56cc54f416915613273fddbc0836cb5c75543a87 (diff) | |
| download | bcm5719-llvm-061a1ea9e3817bbf75fb83596ec7f848251f32f5.tar.gz bcm5719-llvm-061a1ea9e3817bbf75fb83596ec7f848251f32f5.zip | |
Complete rewrite of the SelectionDAG class.
llvm-svn: 19327
| -rw-r--r-- | llvm/include/llvm/CodeGen/SelectionDAG.h | 425 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 864 | 
2 files changed, 864 insertions, 425 deletions
| diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h index 796ee135350..ce5deecf38f 100644 --- a/llvm/include/llvm/CodeGen/SelectionDAG.h +++ b/llvm/include/llvm/CodeGen/SelectionDAG.h @@ -1,4 +1,4 @@ -//===-- llvm/CodeGen/SelectionDAG.h - InstSelection DAG Rep. ----*- C++ -*-===// +//===-- llvm/CodeGen/SelectionDAG.h - InstSelection DAG ---------*- C++ -*-===//  //   //                     The LLVM Compiler Infrastructure  // @@ -7,364 +7,151 @@  //   //===----------------------------------------------------------------------===//  //  -// This file declares the SelectionDAG class, which is used to represent an LLVM -// function in a low-level representation suitable for instruction selection. -// This DAG is constructed as the first step of instruction selection in order -// to allow implementation of machine specific optimizations and code -// simplifications. -// -// The representation used by the SelectionDAG is a target-independent -// representation, which is loosly modeled after the GCC RTL representation, but -// is significantly simpler. +// This file declares the SelectionDAG class, and transitively defines the +// SDNode class and subclasses.  //     //===----------------------------------------------------------------------===//  #ifndef LLVM_CODEGEN_SELECTIONDAG_H  #define LLVM_CODEGEN_SELECTIONDAG_H -#include "llvm/CodeGen/ValueTypes.h" -#include "llvm/Support/DataTypes.h" +#include "llvm/CodeGen/SelectionDAGNodes.h"  #include <map> -#include <vector> -#include <cassert> +#include <string> // FIXME remove eventually, turning map into const char* map.  namespace llvm { - -class Value; -class Type; -class Instruction; -class CallInst; -class BasicBlock; -class MachineBasicBlock; -class MachineFunction; -class TargetMachine; -class SelectionDAGNode; -class SelectionDAGBlock; -class SelectionDAGBuilder; -class SelectionDAGTargetBuilder; - -/// ISD namespace - This namespace contains an enum which represents all of the -/// SelectionDAG node types and value types. +  class TargetLowering; +  class TargetMachine; +  class MachineFunction; + +/// SelectionDAG class - This is used to represent a portion of an LLVM function +/// in a low-level Data Dependence DAG representation suitable for instruction +/// selection.  This DAG is constructed as the first step of instruction +/// selection in order to allow implementation of machine specific optimizations +/// and code simplifications. +/// +/// The representation used by the SelectionDAG is a target-independent +/// representation, which has some similarities to the GCC RTL representation, +/// but is significantly more simple, powerful, and is a graph form instead of a +/// linear form.  /// -namespace ISD { -  enum NodeType { -    // ChainNode nodes are used to sequence operations within a basic block -    // which cannot be reordered (such as loads, stores, calls, etc). -    // BlockChainNodes are used to connect the DAG's for different basic blocks -    // into one big DAG. -    ChainNode, BlockChainNode, - -    // ProtoNodes are nodes that are only half way constructed. -    ProtoNode, - -    // Leaf nodes -    Constant, FrameIndex, BasicBlock, - -    // Simple binary arithmetic operators -    Plus, Minus, Times, SDiv, UDiv, SRem, URem, - -    // Bitwise operators -    And, Or, Xor, - -    // Comparisons -    SetEQ, SetNE, SetLT, SetLE, SetGT, SetGE, - -    // Control flow instructions -    Br, BrCond, Switch, Ret, RetVoid, - -    // Other operators -    Load, Store, PHI, Call, - -    // Unknown operators, of a specified arity -    Unspec1, Unspec2 -  }; -} -  class SelectionDAG { -  friend class SelectionDAGBuilder; -  MachineFunction &F;    const TargetMachine &TM; -  MVT::ValueType PointerType;    // The ValueType the target uses for pointers +  MachineFunction &MF; -  // ValueMap - The SelectionDAGNode for each LLVM value in the function. -  std::map<const Value*, SelectionDAGNode*> ValueMap; - -  // BlockMap - The MachineBasicBlock created for each LLVM BasicBlock -  std::map<const BasicBlock*, MachineBasicBlock*> BlockMap; - -  // Root - The root of the entire DAG -  SelectionDAGNode *Root; +  // Root - The root of the entire DAG.  EntryNode - The starting token. +  SDOperand Root, EntryNode;    // AllNodes - All of the nodes in the DAG -  std::vector<SelectionDAGNode*> AllNodes; +  std::vector<SDNode*> AllNodes; + +  // Maps to auto-CSE operations. +  std::map<std::pair<unsigned, std::pair<SDOperand, MVT::ValueType> >, +           SDNode *> UnaryOps; +  std::map<std::pair<unsigned, std::pair<SDOperand, SDOperand> >, +           SDNode *> BinaryOps; + +  std::map<std::pair<std::pair<SDOperand, SDOperand>, ISD::CondCode>, +           SetCCSDNode*> SetCCs; + +  std::map<std::pair<SDOperand, std::pair<SDOperand, MVT::ValueType> >, +           SDNode *> Loads; + +  std::map<const GlobalValue*, SDNode*> GlobalValues; +  std::map<std::pair<uint64_t, MVT::ValueType>, SDNode*> Constants; +  std::map<std::pair<double, MVT::ValueType>, SDNode*> ConstantFPs; +  std::map<int, SDNode*> FrameIndices; +  std::map<unsigned, SDNode*> ConstantPoolIndices; +  std::map<MachineBasicBlock *, SDNode*> BBNodes; +  std::map<std::string, SDNode*> ExternalSymbols;  public: -  /// SelectionDAG constructor - Build a SelectionDAG for the specified -  /// function.  Implemented in DAGBuilder.cpp -  /// -  SelectionDAG(MachineFunction &F, const TargetMachine &TM, -               SelectionDAGTargetBuilder &SDTB); +  SelectionDAG(const TargetMachine &tm, MachineFunction &mf) : TM(tm), MF(mf) { +    EntryNode = Root = getNode(ISD::EntryToken, MVT::Other); +  }    ~SelectionDAG(); -  /// getValueType - Return the ValueType for the specified LLVM type.  This -  /// method works on all scalar LLVM types. -  /// -  MVT::ValueType getValueType(const Type *Ty) const; - -  /// getRoot - Return the root of the current SelectionDAG. -  /// -  SelectionDAGNode *getRoot() const { return Root; } +  MachineFunction &getMachineFunction() const { return MF; } +  const TargetMachine &getTarget() { return TM; } -  /// getMachineFunction - Return the MachineFunction object that this -  /// SelectionDAG corresponds to. +  /// getRoot - Return the root tag of the SelectionDAG.    /// -  MachineFunction &getMachineFunction() const { return F; } +  const SDOperand &getRoot() const { return Root; } -  //===--------------------------------------------------------------------===// -  // Addition and updating methods -  // +  /// getEntryNode - Return the token chain corresponding to the entry of the +  /// function. +  const SDOperand &getEntryNode() const { return EntryNode; } -  /// addNode - Add the specified node to the SelectionDAG so that it will be -  /// deleted when the DAG is... +  /// setRoot - Set the current root tag of the SelectionDAG.    /// -  SelectionDAGNode *addNode(SelectionDAGNode *N) { -    AllNodes.push_back(N); -    return N; -  } +  const SDOperand &setRoot(SDOperand N) { return Root = N; } -  /// addNodeForValue - Add the specified node to the SelectionDAG so that it -  /// will be deleted when the DAG is... and update the value map to indicate -  /// that the specified DAG node computes the value.  Note that it is an error -  /// to specify multiple DAG nodes that compute the same value. +  /// Legalize - This transforms the SelectionDAG into a SelectionDAG that is +  /// compatible with the target instruction selector, as indicated by the +  /// TargetLowering object.    /// -  SelectionDAGNode *addNodeForValue(SelectionDAGNode *N, const Value *V) { -    assert(ValueMap.count(V) == 0 && "Value already has a DAG node!"); -    return addNode(ValueMap[V] = N); +  /// Note that this is an involved process that may invalidate pointers into +  /// the graph. +  void Legalize(TargetLowering &TLI); + +  SDOperand getConstant(uint64_t Val, MVT::ValueType VT); +  SDOperand getConstantFP(double Val, MVT::ValueType VT); +  SDOperand getGlobalAddress(const GlobalValue *GV, MVT::ValueType VT); +  SDOperand getFrameIndex(int FI, MVT::ValueType VT); +  SDOperand getConstantPool(unsigned CPIdx, MVT::ValueType VT); +  SDOperand getBasicBlock(MachineBasicBlock *MBB); +  SDOperand getExternalSymbol(const char *Sym, MVT::ValueType VT); + +  SDOperand getCopyToReg(SDOperand Chain, SDOperand N, unsigned VReg) { +    // Note: these are auto-CSE'd because the caller doesn't make requests that +    // could cause duplicates to occur. +    SDNode *NN = new CopyRegSDNode(Chain, N, VReg); +    AllNodes.push_back(NN); +    return SDOperand(NN, 0);    } -  void dump() const; -private: -  void addInstructionToDAG(const Instruction &I, const BasicBlock &BB); -}; - - -/// SelectionDAGReducedValue - During the reducer pass we need the ability to -/// add an arbitrary (but usually 1 or 0) number of arbitrarily sized values to -/// the selection DAG.  Because of this, we represent these values as a singly -/// linked list of values attached to the DAGNode.  We end up putting the -/// arbitrary state for the value in subclasses of this node. -/// -/// Note that this class does not have a virtual dtor, this is because we know -/// that the subclasses will not hold state that needs to be destroyed. -/// -class SelectionDAGReducedValue { -  unsigned Code; -  SelectionDAGReducedValue *Next; -public: -  SelectionDAGReducedValue(unsigned C) : Code(C), Next(0) {} - -  /// getValueCode - Return the code for this reducer value... -  /// -  unsigned getValueCode() const { return Code; } -   -  /// getNext - Return the next value in the list -  /// -  const SelectionDAGReducedValue *getNext() const { return Next; } -  void setNext(SelectionDAGReducedValue *N) { Next = N; } - -  SelectionDAGReducedValue *getNext() { return Next; } -}; - - - -/// SelectionDAGNode - Represents one node in the selection DAG. -/// -class SelectionDAGNode { -  std::vector<SelectionDAGNode*> Uses; -  ISD::NodeType  NodeType; -  MVT::ValueType ValueType; -  MachineBasicBlock *BB; -  SelectionDAGReducedValue *ValList; - -  /// Costs - Each pair of elements of 'Costs' contains the cost of producing -  /// the value with the target specific slot number and the production number -  /// to use to produce it.  A zero value for the production number indicates -  /// that the cost has not yet been computed. -  unsigned *Costs; -public: -  SelectionDAGNode(ISD::NodeType NT, MVT::ValueType VT, -                   MachineBasicBlock *bb = 0)  -    : NodeType(NT), ValueType(VT), BB(bb), ValList(0), Costs(0) {} - -  SelectionDAGNode(ISD::NodeType NT, MVT::ValueType VT, MachineBasicBlock *bb, -                   SelectionDAGNode *N) -    : NodeType(NT), ValueType(VT), BB(bb), ValList(0), Costs(0) { -    assert(NT != ISD::ProtoNode && "Cannot specify uses for a protonode!"); -    Uses.reserve(1); Uses.push_back(N); -  } -  SelectionDAGNode(ISD::NodeType NT, MVT::ValueType VT, MachineBasicBlock *bb, -                   SelectionDAGNode *N1, SelectionDAGNode *N2) -    : NodeType(NT), ValueType(VT), BB(bb), ValList(0), Costs(0) { -    assert(NT != ISD::ProtoNode && "Cannot specify uses for a protonode!"); -    Uses.reserve(2); Uses.push_back(N1); Uses.push_back(N2); -  } -  SelectionDAGNode(ISD::NodeType NT, MVT::ValueType VT, MachineBasicBlock *bb, -                   SelectionDAGNode *N1, SelectionDAGNode *N2, -                   SelectionDAGNode *N3) -    : NodeType(NT), ValueType(VT), BB(bb), ValList(0), Costs(0) { -    assert(NT != ISD::ProtoNode && "Cannot specify uses for a protonode!"); -    Uses.reserve(3); Uses.push_back(N1); Uses.push_back(N2); Uses.push_back(N3); -  } - -  ~SelectionDAGNode() { delete [] Costs; delete ValList; } - -  void setNode(ISD::NodeType NT, MachineBasicBlock *bb) { -    assert(NodeType == ISD::ProtoNode && NT != ISD::ProtoNode); -    NodeType = NT; BB = bb; -  } -  void setNode(ISD::NodeType NT, MachineBasicBlock *bb, SelectionDAGNode *N) { -    assert(NodeType == ISD::ProtoNode && NT != ISD::ProtoNode); -    NodeType = NT; BB = bb; Uses.reserve(1); Uses.push_back(N); -  } -  void setNode(ISD::NodeType NT, MachineBasicBlock *bb,  -               SelectionDAGNode *N1, SelectionDAGNode *N2) { -    assert(NodeType == ISD::ProtoNode && NT != ISD::ProtoNode); -    NodeType = NT; BB = bb; -    Uses.reserve(1); Uses.push_back(N1); Uses.push_back(N2); +  SDOperand getCopyFromReg(unsigned VReg, MVT::ValueType VT) { +    // Note: These nodes are auto-CSE'd by the caller of this method. +    SDNode *NN = new CopyRegSDNode(VReg, VT); +    AllNodes.push_back(NN); +    return SDOperand(NN, 0);    } -  //===--------------------------------------------------------------------===// -  //  Accessors -  // -  ISD::NodeType  getNodeType()  const { return NodeType; } -  MVT::ValueType getValueType() const { return ValueType; } -  MachineBasicBlock *getBB() const { return BB; } - -  SelectionDAGNode *getUse(unsigned Num) { -    assert(Num < Uses.size() && "Invalid child # of SelectionDAGNode!"); -    return Uses[Num]; -  } - -  template<class Type> -  Type *getValue(unsigned Code) const { -    SelectionDAGReducedValue *Vals = ValList; -    while (1) { -      assert(Vals && "Code does not exist in this list!"); -      if (Vals->getValueCode() == Code) -        return (Type*)Vals; -      Vals = Vals->getNext(); -    } -  } - -  template<class Type> -  Type *hasValue(unsigned Code) const { -    SelectionDAGReducedValue *Vals = ValList; -    while (Vals) { -      if (Vals->getValueCode() == Code) -        return (Type*)Vals; -      Vals = Vals->getNext(); -    } -    return false; -  } - -  void addValue(SelectionDAGReducedValue *New) { -    assert(New->getNext() == 0); -    New->setNext(ValList); -    ValList = New; +  /// getCall - Note that this destroys the vector of RetVals passed in. +  /// +  SDNode *getCall(std::vector<MVT::ValueType> &RetVals, SDOperand Chain, +                  SDOperand Callee) { +    SDNode *NN = new SDNode(ISD::CALL, Chain, Callee); +    NN->setValueTypes(RetVals); +    AllNodes.push_back(NN); +    return NN;    } -  //===--------------------------------------------------------------------===// -  // Utility methods used by the pattern matching instruction selector -  // +  SDOperand getSetCC(ISD::CondCode, SDOperand LHS, SDOperand RHS); -  /// getPatternFor - Return the pattern selected to compute the specified slot, -  /// or zero if there is no pattern yet. +  /// getNode - Gets or creates the specified node.    /// -  unsigned getPatternFor(unsigned Slot) const { -    return Costs ? Costs[Slot*2] : 0; -  } - -  /// getCostFor - Return the cost to compute the value corresponding to Slot. +  SDOperand getNode(unsigned Opcode, MVT::ValueType VT); +  SDOperand getNode(unsigned Opcode, MVT::ValueType VT, SDOperand N); +  SDOperand getNode(unsigned Opcode, MVT::ValueType VT, +                    SDOperand N1, SDOperand N2); +  SDOperand getNode(unsigned Opcode, MVT::ValueType VT, +                    SDOperand N1, SDOperand N2, SDOperand N3); +  SDOperand getNode(unsigned Opcode, MVT::ValueType VT, +                    std::vector<SDOperand> &Children); + +  /// getLoad - Loads are not normal binary operators: their result type is not +  /// determined by their operands, and they produce a value AND a token chain.    /// -  unsigned getCostFor(unsigned Slot) const { -    return Costs ? Costs[Slot*2+1] : 0; -  } +  SDOperand getLoad(MVT::ValueType VT, SDOperand Chain, SDOperand Ptr); -  /// setPatternCostFor - Sets the pattern and the cost for the specified slot -  /// to the specified values.  This allocates the Costs vector if necessary, so -  /// you must specify the maximum number of slots that may be used. -  /// -  void setPatternCostFor(unsigned Slot, unsigned Pattern, unsigned Cost, -                         unsigned NumSlots) { -    if (Costs == 0) { -      Costs = new unsigned[NumSlots*2]; -      for (unsigned i = 0; i != NumSlots*2; ++i) Costs[i] = 0; -    } -    Costs[Slot*2] = Pattern; -    Costs[Slot*2+1] = Cost; +  void replaceAllUsesWith(SDOperand Old, SDOperand New) { +    assert(Old != New && "RAUW self!"); +    assert(0 && "Unimplemented!");    }    void dump() const; -private: -  void printit(unsigned Offset, unsigned &LastID, -               std::map<const SelectionDAGNode*, unsigned> &NodeIDs) const;  }; - -/// SelectionDAGTargetBuilder - This class must be implemented by the target, to -/// indicate how to perform the extremely target-specific tasks of building DAG -/// nodes to represent the calling convention used by the target. -/// -struct SelectionDAGTargetBuilder { -  /// expandArguments - This method is called once by the SelectionDAG -  /// construction mechanisms to add DAG nodes for each formal argument to the -  /// current function.  If any of the incoming arguments lives on the stack, -  /// this method should also create the stack slots for the arguments as -  /// necessary. -  virtual void expandArguments(SelectionDAG &SD) = 0; - -  /// expandCall - This method is called once per function call by the -  /// SelectionDAG construction algorithm.  It must add DAG nodes to the -  /// SelectionDAG specified to perform that call. -  virtual void expandCall(SelectionDAG &SD, CallInst &CI) = 0; -}; - -namespace ISD { -  enum {   // Builtin Slot numbers -    Constant_i1_Slot, -    Constant_i8_Slot, -    Constant_i16_Slot, -    Constant_i32_Slot, -    Constant_i64_Slot, -    Constant_f32_Slot, -    Constant_f64_Slot, - -    FrameIndex_i32_Slot, -    FrameIndex_i64_Slot, -    BasicBlock_i32_Slot, -    BasicBlock_i64_Slot, -    NumBuiltinSlots -  };  } -template<typename ValType, unsigned NodeCode> -struct ReducedValue : public SelectionDAGReducedValue { -  ReducedValue(const ValType &V) : SelectionDAGReducedValue(NodeCode), Val(V) {} -  ValType Val; -}; - -typedef ReducedValue<int, ISD::FrameIndex_i32_Slot > ReducedValue_FrameIndex_i32; -typedef ReducedValue<int, ISD::FrameIndex_i64_Slot > ReducedValue_FrameIndex_i64; -typedef ReducedValue<MachineBasicBlock*, ISD::BasicBlock_i32_Slot > ReducedValue_BasicBlock_i32; -typedef ReducedValue<MachineBasicBlock*, ISD::BasicBlock_i64_Slot > ReducedValue_BasicBlock_i64; - -typedef ReducedValue<bool          , ISD::Constant_i1_Slot > ReducedValue_Constant_i1; -typedef ReducedValue<unsigned char , ISD::Constant_i8_Slot > ReducedValue_Constant_i8; -typedef ReducedValue<unsigned short, ISD::Constant_i16_Slot> ReducedValue_Constant_i16; -typedef ReducedValue<unsigned      , ISD::Constant_i32_Slot> ReducedValue_Constant_i32; -typedef ReducedValue<uint64_t      , ISD::Constant_i64_Slot> ReducedValue_Constant_i64; -typedef ReducedValue<float         , ISD::Constant_f32_Slot> ReducedValue_Constant_f32; -typedef ReducedValue<double        , ISD::Constant_f64_Slot> ReducedValue_Constant_f64; - -} // End llvm namespace -  #endif diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index acf3daa32f5..f02bdcd95b1 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -1,4 +1,4 @@ -//===-- SelectionDAG.cpp - Implement the SelectionDAG* classes ------------===// +//===-- SelectionDAG.cpp - Implement the SelectionDAG data structures -----===//  //   //                     The LLVM Compiler Infrastructure  // @@ -7,125 +7,777 @@  //   //===----------------------------------------------------------------------===//  // -// This file implements the SelectionDAG* classes, which are used to perform -// DAG-based instruction selection in a target-specific manner. +// This implements the SelectionDAG class.  //  //===----------------------------------------------------------------------===//  #include "llvm/CodeGen/SelectionDAG.h" -#include "llvm/Type.h" +#include "llvm/Constants.h" +#include "llvm/GlobalValue.h" +#include "llvm/Assembly/Writer.h" +#include "llvm/CodeGen/MachineBasicBlock.h"  #include <iostream> - +#include <cmath>  using namespace llvm; +/// getSetCCSwappedOperands - Return the operation corresponding to (Y op X) +/// when given the operation for (X op Y). +ISD::CondCode ISD::getSetCCSwappedOperands(ISD::CondCode Operation) { +  // To perform this operation, we just need to swap the L and G bits of the +  // operation. +  unsigned OldL = (Operation >> 2) & 1; +  unsigned OldG = (Operation >> 1) & 1; +  return ISD::CondCode((Operation & ~6) |  // Keep the N, U, E bits +                       (OldL << 1) |       // New G bit +                       (OldG << 2));        // New L bit. +} + +/// getSetCCInverse - Return the operation corresponding to !(X op Y), where +/// 'op' is a valid SetCC operation. +ISD::CondCode ISD::getSetCCInverse(ISD::CondCode Op, bool isInteger) { +  unsigned Operation = Op; +  if (isInteger) +    Operation ^= 7;   // Flip L, G, E bits, but not U. +  else +    Operation ^= 15;  // Flip all of the condition bits. +  if (Operation > ISD::SETTRUE2) +    Operation &= ~8;     // Don't let N and U bits get set. +  return ISD::CondCode(Operation); +} + + +/// isSignedOp - For an integer comparison, return 1 if the comparison is a +/// signed operation and 2 if the result is an unsigned comparison.  Return zero +/// if the operation does not depend on the sign of the input (setne and seteq). +static int isSignedOp(ISD::CondCode Opcode) { +  switch (Opcode) { +  default: assert(0 && "Illegal integer setcc operation!"); +  case ISD::SETEQ: +  case ISD::SETNE: return 0; +  case ISD::SETLT: +  case ISD::SETLE: +  case ISD::SETGT: +  case ISD::SETGE: return 1; +  case ISD::SETULT: +  case ISD::SETULE: +  case ISD::SETUGT: +  case ISD::SETUGE: return 2; +  } +} + +/// getSetCCOrOperation - Return the result of a logical OR between different +/// comparisons of identical values: ((X op1 Y) | (X op2 Y)).  This function +/// returns SETCC_INVALID if it is not possible to represent the resultant +/// comparison. +ISD::CondCode ISD::getSetCCOrOperation(ISD::CondCode Op1, ISD::CondCode Op2, +                                       bool isInteger) { +  if (isInteger && (isSignedOp(Op1) | isSignedOp(Op2)) == 3) +    // Cannot fold a signed integer setcc with an unsigned integer setcc. +    return ISD::SETCC_INVALID; +   +  unsigned Op = Op1 | Op2;  // Combine all of the condition bits. +   +  // If the N and U bits get set then the resultant comparison DOES suddenly +  // care about orderedness, and is true when ordered. +  if (Op > ISD::SETTRUE2) +    Op &= ~16;     // Clear the N bit. +  return ISD::CondCode(Op); +} + +/// getSetCCAndOperation - Return the result of a logical AND between different +/// comparisons of identical values: ((X op1 Y) & (X op2 Y)).  This +/// function returns zero if it is not possible to represent the resultant +/// comparison. +ISD::CondCode ISD::getSetCCAndOperation(ISD::CondCode Op1, ISD::CondCode Op2, +                                        bool isInteger) { +  if (isInteger && (isSignedOp(Op1) | isSignedOp(Op2)) == 3) +    // Cannot fold a signed setcc with an unsigned setcc. +    return ISD::SETCC_INVALID;  + +  // Combine all of the condition bits. +  return ISD::CondCode(Op1 & Op2); +} +  SelectionDAG::~SelectionDAG() {    for (unsigned i = 0, e = AllNodes.size(); i != e; ++i)      delete AllNodes[i];  } +SDOperand SelectionDAG::getConstant(uint64_t Val, MVT::ValueType VT) { +  assert(MVT::isInteger(VT) && "Cannot create FP integer constant!"); +  // Mask out any bits that are not valid for this constant. +  Val &= (1ULL << MVT::getSizeInBits(VT)) - 1; -/// dump - Print out the current Selection DAG... -void SelectionDAG::dump() const { -  Root->dump();  // Print from the root... +  SDNode *&N = Constants[std::make_pair(Val, VT)]; +  if (N) return SDOperand(N, 0); +  N = new ConstantSDNode(Val, VT); +  AllNodes.push_back(N); +  return SDOperand(N, 0);  } -/// getValueType - Return the ValueType for the specified LLVM type.  This -/// method works on all scalar LLVM types. +SDOperand SelectionDAG::getConstantFP(double Val, MVT::ValueType VT) { +  assert(MVT::isFloatingPoint(VT) && "Cannot create integer FP constant!"); +  if (VT == MVT::f32) +    Val = (float)Val;  // Mask out extra precision. + +  SDNode *&N = ConstantFPs[std::make_pair(Val, VT)]; +  if (N) return SDOperand(N, 0); +  N = new ConstantFPSDNode(Val, VT); +  AllNodes.push_back(N); +  return SDOperand(N, 0); +} + + + +SDOperand SelectionDAG::getGlobalAddress(const GlobalValue *GV, +                                         MVT::ValueType VT) { +  SDNode *&N = GlobalValues[GV]; +  if (N) return SDOperand(N, 0); +  N = new GlobalAddressSDNode(GV,VT); +  AllNodes.push_back(N); +  return SDOperand(N, 0); +} + +SDOperand SelectionDAG::getFrameIndex(int FI, MVT::ValueType VT) { +  SDNode *&N = FrameIndices[FI]; +  if (N) return SDOperand(N, 0); +  N = new FrameIndexSDNode(FI, VT); +  AllNodes.push_back(N); +  return SDOperand(N, 0); +} + +SDOperand SelectionDAG::getConstantPool(unsigned CPIdx, MVT::ValueType VT) { +  SDNode *N = ConstantPoolIndices[CPIdx]; +  if (N) return SDOperand(N, 0); +  N = new ConstantPoolSDNode(CPIdx, VT); +  AllNodes.push_back(N); +  return SDOperand(N, 0); +} + +SDOperand SelectionDAG::getBasicBlock(MachineBasicBlock *MBB) { +  SDNode *&N = BBNodes[MBB]; +  if (N) return SDOperand(N, 0); +  N = new BasicBlockSDNode(MBB); +  AllNodes.push_back(N); +  return SDOperand(N, 0); +} + +SDOperand SelectionDAG::getExternalSymbol(const char *Sym, MVT::ValueType VT) { +  SDNode *&N = ExternalSymbols[Sym]; +  if (N) return SDOperand(N, 0); +  N = new ExternalSymbolSDNode(Sym, VT); +  AllNodes.push_back(N); +  return SDOperand(N, 0); +} + +SDOperand SelectionDAG::getSetCC(ISD::CondCode Cond, SDOperand N1, +                                 SDOperand N2) { +  // These setcc operations always fold. +  switch (Cond) { +  default: break; +  case ISD::SETFALSE: +  case ISD::SETFALSE2: return getConstant(0, MVT::i1); +  case ISD::SETTRUE: +  case ISD::SETTRUE2:  return getConstant(1, MVT::i1); +  } + +  if (ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1.Val)) +    if (ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2.Val)) { +      uint64_t C1 = N1C->getValue(), C2 = N2C->getValue(); +       +      // Sign extend the operands if required +      if (ISD::isSignedIntSetCC(Cond)) { +        C1 = N1C->getSignExtended(); +        C2 = N2C->getSignExtended(); +      } + +      switch (Cond) { +      default: assert(0 && "Unknown integer setcc!"); +      case ISD::SETEQ:  return getConstant(C1 == C2, MVT::i1); +      case ISD::SETNE:  return getConstant(C1 != C2, MVT::i1); +      case ISD::SETULT: return getConstant(C1 <  C2, MVT::i1); +      case ISD::SETUGT: return getConstant(C1 >  C2, MVT::i1); +      case ISD::SETULE: return getConstant(C1 <= C2, MVT::i1); +      case ISD::SETUGE: return getConstant(C1 >= C2, MVT::i1); +      case ISD::SETLT:  return getConstant((int64_t)C1 < (int64_t)C2, MVT::i1); +      case ISD::SETGT:  return getConstant((int64_t)C1 < (int64_t)C2, MVT::i1); +      case ISD::SETLE:  return getConstant((int64_t)C1 < (int64_t)C2, MVT::i1); +      case ISD::SETGE:  return getConstant((int64_t)C1 < (int64_t)C2, MVT::i1); +      } +    } else { +      // Ensure that the constant occurs on the RHS. +      Cond = ISD::getSetCCSwappedOperands(Cond); +      std::swap(N1, N2); +    } + +  if (ConstantFPSDNode *N1C = dyn_cast<ConstantFPSDNode>(N1.Val)) +    if (ConstantFPSDNode *N2C = dyn_cast<ConstantFPSDNode>(N2.Val)) { +      double C1 = N1C->getValue(), C2 = N2C->getValue(); +       +      switch (Cond) { +      default: break; // FIXME: Implement the rest of these! +      case ISD::SETEQ:  return getConstant(C1 == C2, MVT::i1); +      case ISD::SETNE:  return getConstant(C1 != C2, MVT::i1); +      case ISD::SETLT:  return getConstant((int64_t)C1 < (int64_t)C2, MVT::i1); +      case ISD::SETGT:  return getConstant((int64_t)C1 < (int64_t)C2, MVT::i1); +      case ISD::SETLE:  return getConstant((int64_t)C1 < (int64_t)C2, MVT::i1); +      case ISD::SETGE:  return getConstant((int64_t)C1 < (int64_t)C2, MVT::i1); +      } +    } else { +      // Ensure that the constant occurs on the RHS. +      Cond = ISD::getSetCCSwappedOperands(Cond); +      std::swap(N1, N2); +    } + +  if (N1 == N2) { +    // We can always fold X == Y for integer setcc's. +    if (MVT::isInteger(N1.getValueType())) +      return getConstant(ISD::isTrueWhenEqual(Cond), MVT::i1); +    unsigned UOF = ISD::getUnorderedFlavor(Cond); +    if (UOF == 2)   // FP operators that are undefined on NaNs. +      return getConstant(ISD::isTrueWhenEqual(Cond), MVT::i1); +    if (UOF == ISD::isTrueWhenEqual(Cond)) +      return getConstant(UOF, MVT::i1); +    // Otherwise, we can't fold it.  However, we can simplify it to SETUO/SETO +    // if it is not already. +    Cond = UOF == 0 ? ISD::SETUO : ISD::SETO; +  } + + +  SetCCSDNode *&N = SetCCs[std::make_pair(std::make_pair(N1, N2), Cond)]; +  if (N) return SDOperand(N, 0); +  N = new SetCCSDNode(Cond, N1, N2); +  AllNodes.push_back(N); +  return SDOperand(N, 0); +} + + + +/// getNode - Gets or creates the specified node.  /// -MVT::ValueType SelectionDAG::getValueType(const Type *Ty) const { -  switch (Ty->getTypeID()) { -  case Type::VoidTyID: assert(0 && "Void type object in getValueType!"); -  default: assert(0 && "Unknown type in DAGBuilder!\n"); -  case Type::BoolTyID:    return MVT::i1; -  case Type::SByteTyID: -  case Type::UByteTyID:   return MVT::i8; -  case Type::ShortTyID: -  case Type::UShortTyID:  return MVT::i16; -  case Type::IntTyID: -  case Type::UIntTyID:    return MVT::i32; -  case Type::LongTyID: -  case Type::ULongTyID:   return MVT::i64; -  case Type::FloatTyID:   return MVT::f32; -  case Type::DoubleTyID:  return MVT::f64; -  case Type::LabelTyID: -  case Type::PointerTyID: return PointerType; -  } -} - -void SelectionDAGNode::dump() const { -  // Print out the DAG in post-order -  std::map<const SelectionDAGNode*, unsigned> NodeIDs; -  unsigned ID = 0; -  printit(0, ID, NodeIDs); -} - -void SelectionDAGNode::printit(unsigned Offset, unsigned &LastID, -                               std::map<const SelectionDAGNode*, -                                        unsigned> &NodeIDs) const { -  if (!NodeIDs.count(this)) { -    // Emit all of the uses first... -    for (unsigned i = 0, e = Uses.size(); i != e; ++i) -      Uses[i]->printit(Offset+1, LastID, NodeIDs); - -    NodeIDs[this] = LastID++; - -    std::cerr << std::string(Offset, ' ') << "#" << LastID-1 << " "; -  } else { -    // Node has already been emitted... -    std::cerr << std::string(Offset, ' ') << "#" << NodeIDs[this] << " "; -  } - -  switch (ValueType) { -  case MVT::isVoid: std::cerr << "V:"; break; -  case MVT::i1:   std::cerr << "i1:"; break; -  case MVT::i8:   std::cerr << "i8:"; break; -  case MVT::i16:  std::cerr << "i16:"; break; -  case MVT::i32:  std::cerr << "i32:"; break; -  case MVT::i64:  std::cerr << "i64:"; break; -  case MVT::f32:  std::cerr << "f32:"; break; -  case MVT::f64:  std::cerr << "f64:"; break; -  default: assert(0 && "Invalid node ValueType!"); -  } -  switch (NodeType) { -  case ISD::ChainNode:      std::cerr << "ChainNode"; break; -  case ISD::BlockChainNode: std::cerr << "BlockChainNode"; break; -  case ISD::ProtoNode:      std::cerr << "ProtoNode"; break; - -  case ISD::Constant:       std::cerr << "Constant"; break; -  case ISD::FrameIndex:     std::cerr << "FrameIndex"; break; -  case ISD::BasicBlock:     std::cerr << "BasicBlock"; break; - -  case ISD::Plus:           std::cerr << "Plus"; break; -  case ISD::Minus:          std::cerr << "Minus"; break; -  case ISD::Times:          std::cerr << "Times"; break; -  case ISD::SDiv:           std::cerr << "SDiv"; break; -  case ISD::UDiv:           std::cerr << "UDiv"; break; -  case ISD::SRem:           std::cerr << "SRem"; break; -  case ISD::URem:           std::cerr << "URem"; break; -  case ISD::And:            std::cerr << "And"; break; -  case ISD::Or:             std::cerr << "Or"; break; -  case ISD::Xor:            std::cerr << "Xor"; break; - -  case ISD::SetEQ:          std::cerr << "SetEQ"; break; -  case ISD::SetNE:          std::cerr << "SetNE"; break; -  case ISD::SetLT:          std::cerr << "SetLT"; break; -  case ISD::SetLE:          std::cerr << "SetLE"; break; -  case ISD::SetGT:          std::cerr << "SetGT"; break; -  case ISD::SetGE:          std::cerr << "SetGE"; break; - -  case ISD::Br:             std::cerr << "Br"; break; -  case ISD::BrCond:         std::cerr << "BrCond"; break; -  case ISD::Switch:         std::cerr << "Switch"; break; -  case ISD::Ret:            std::cerr << "Ret"; break; -  case ISD::RetVoid:        std::cerr << "RetVoid"; break; -  case ISD::Load:           std::cerr << "Load"; break; -  case ISD::Store:          std::cerr << "Store"; break; -  case ISD::PHI:            std::cerr << "PHI"; break; -  case ISD::Call:           std::cerr << "Call"; break; - -  case ISD::Unspec1:        std::cerr << "Unspec1"; break; -  case ISD::Unspec2:        std::cerr << "Unspec2"; break; -  } - -  std::cerr << "\n"; +SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT) { +  SDNode *N = new SDNode(Opcode, VT); +  AllNodes.push_back(N); +  return SDOperand(N, 0); +} + +static const Type *getTypeFor(MVT::ValueType VT) { +  switch (VT) { +  default: assert(0 && "Unknown MVT!"); +  case MVT::i1: return Type::BoolTy; +  case MVT::i8: return Type::UByteTy; +  case MVT::i16: return Type::UShortTy; +  case MVT::i32: return Type::UIntTy; +  case MVT::i64: return Type::ULongTy; +  case MVT::f32: return Type::FloatTy; +  case MVT::f64: return Type::DoubleTy; +  } +} + +SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, +                                SDOperand Operand) { +  if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Operand.Val)) { +    uint64_t Val = C->getValue(); +    switch (Opcode) { +    default: break; +    case ISD::SIGN_EXTEND: return getConstant(C->getSignExtended(), VT); +    case ISD::ZERO_EXTEND: return getConstant(Val, VT); +    case ISD::TRUNCATE:    return getConstant(Val, VT); +    } +  } + +  if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(Operand.Val)) +    switch (Opcode) { +    case ISD::FP_ROUND: +    case ISD::FP_EXTEND: +      return getConstantFP(C->getValue(), VT); +    } + +  unsigned OpOpcode = Operand.Val->getOpcode(); +  switch (Opcode) { +  case ISD::SIGN_EXTEND: +    if (Operand.getValueType() == VT) return Operand;   // noop extension +    if (OpOpcode == ISD::SIGN_EXTEND || OpOpcode == ISD::ZERO_EXTEND) +      return getNode(OpOpcode, VT, Operand.Val->getOperand(0)); +    break; +  case ISD::ZERO_EXTEND: +    if (Operand.getValueType() == VT) return Operand;   // noop extension +    if (OpOpcode == ISD::SIGN_EXTEND || OpOpcode == ISD::ZERO_EXTEND) +      return getNode(OpOpcode, VT, Operand.Val->getOperand(0)); +    break; +  case ISD::TRUNCATE: +    if (Operand.getValueType() == VT) return Operand;   // noop truncate +    if (OpOpcode == ISD::TRUNCATE) +      return getNode(ISD::TRUNCATE, VT, Operand.Val->getOperand(0)); +    break; +  } + +  SDNode *&N = UnaryOps[std::make_pair(Opcode, std::make_pair(Operand, VT))]; +  if (N) return SDOperand(N, 0); +  N = new SDNode(Opcode, Operand); +  N->setValueTypes(VT); +  AllNodes.push_back(N); +  return SDOperand(N, 0); +} + +static bool isCommutativeBinOp(unsigned Opcode) { +  switch (Opcode) { +  case ISD::ADD: +  case ISD::MUL: +  case ISD::AND: +  case ISD::OR: +  case ISD::XOR: return true; +  default: return false; // FIXME: Need commutative info for user ops! +  } +} + +static bool isAssociativeBinOp(unsigned Opcode) { +  switch (Opcode) { +  case ISD::ADD: +  case ISD::MUL: +  case ISD::AND: +  case ISD::OR: +  case ISD::XOR: return true; +  default: return false; // FIXME: Need associative info for user ops! +  } +} + +static unsigned ExactLog2(uint64_t Val) { +  unsigned Count = 0; +  while (Val != 1) { +    Val >>= 1; +    ++Count; +  } +  return Count;  } + +// isInvertibleForFree - Return true if there is no cost to emitting the logical +// inverse of this node. +static bool isInvertibleForFree(SDOperand N) { +  if (isa<ConstantSDNode>(N.Val)) return true; +  if (isa<SetCCSDNode>(N.Val) && N.Val->hasOneUse()) +    return true; +  return false;   +} + + +SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, +                                SDOperand N1, SDOperand N2) { +  ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1.Val); +  ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2.Val); +  if (N1C) { +    if (N2C) { +      uint64_t C1 = N1C->getValue(), C2 = N2C->getValue(); +      switch (Opcode) { +      case ISD::ADD: return getConstant(C1 + C2, VT); +      case ISD::SUB: return getConstant(C1 - C2, VT); +      case ISD::MUL: return getConstant(C1 * C2, VT); +      case ISD::UDIV: +        if (C2) return getConstant(C1 / C2, VT); +        break; +      case ISD::UREM : +        if (C2) return getConstant(C1 % C2, VT); +        break; +      case ISD::SDIV : +        if (C2) return getConstant(N1C->getSignExtended() / +                                   N2C->getSignExtended(), VT); +        break; +      case ISD::SREM : +        if (C2) return getConstant(N1C->getSignExtended() % +                                   N2C->getSignExtended(), VT); +        break; +      case ISD::AND  : return getConstant(C1 & C2, VT); +      case ISD::OR   : return getConstant(C1 | C2, VT); +      case ISD::XOR  : return getConstant(C1 ^ C2, VT); +      default: break; +      } + +    } else {      // Cannonicalize constant to RHS if commutative +      if (isCommutativeBinOp(Opcode)) { +        std::swap(N1C, N2C); +        std::swap(N1, N2); +      } +    } +  } + +  if (N2C) { +    uint64_t C2 = N2C->getValue(); + +    switch (Opcode) { +    case ISD::ADD: +      if (!C2) return N1;         // add X, 0 -> X +      break; +    case ISD::SUB: +      if (!C2) return N1;         // sub X, 0 -> X +      break; +    case ISD::MUL: +      if (!C2) return N2;         // mul X, 0 -> 0 +      if (N2C->isAllOnesValue()) // mul X, -1 -> 0-X +        return getNode(ISD::SUB, VT, getConstant(0, VT), N1); + +      // FIXME: This should only be done if the target supports shift +      // operations. +      if ((C2 & C2-1) == 0) { +        SDOperand ShAmt = getConstant(ExactLog2(C2), MVT::i8); +        return getNode(ISD::SHL, VT, N1, ShAmt); +      } +      break; + +    case ISD::UDIV: +      // FIXME: This should only be done if the target supports shift +      // operations. +      if ((C2 & C2-1) == 0 && C2) { +        SDOperand ShAmt = getConstant(ExactLog2(C2), MVT::i8); +        return getNode(ISD::SRL, VT, N1, ShAmt); +      } +      break; + +    case ISD::AND: +      if (!C2) return N2;         // X and 0 -> 0 +      if (N2C->isAllOnesValue()) +	return N1;                // X and -1 -> X +      break; +    case ISD::OR: +      if (!C2)return N1;          // X or 0 -> X +      if (N2C->isAllOnesValue()) +	return N2;                // X or -1 -> -1 +      break; +    case ISD::XOR: +      if (!C2) return N1;        // X xor 0 -> X +      if (N2C->isAllOnesValue()) { +        if (SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(N1.Val)){ +          // !(X op Y) -> (X !op Y) +          bool isInteger = MVT::isInteger(SetCC->getOperand(0).getValueType()); +          return getSetCC(ISD::getSetCCInverse(SetCC->getCondition(),isInteger), +                          SetCC->getOperand(0), SetCC->getOperand(1)); +        } else if (N1.getOpcode() == ISD::AND || N1.getOpcode() == ISD::OR) { +          SDNode *Op = N1.Val; +          // !(X or Y) -> (!X and !Y) iff X or Y are freely invertible +          // !(X and Y) -> (!X or !Y) iff X or Y are freely invertible +          SDOperand LHS = Op->getOperand(0), RHS = Op->getOperand(1); +          if (isInvertibleForFree(RHS) || isInvertibleForFree(LHS)) { +            LHS = getNode(ISD::XOR, VT, LHS, N2);  // RHS = ~LHS +            RHS = getNode(ISD::XOR, VT, RHS, N2);  // RHS = ~RHS +            if (Op->getOpcode() == ISD::AND) +              return getNode(ISD::OR, VT, LHS, RHS); +            return getNode(ISD::AND, VT, LHS, RHS); +          } +        } +	// X xor -1 -> not(x)  ? +      } +      break; +    } + +    // Reassociate ((X op C1) op C2) if possible. +    if (N1.getOpcode() == Opcode && isAssociativeBinOp(Opcode)) +      if (ConstantSDNode *N3C = dyn_cast<ConstantSDNode>(N1.Val->getOperand(1))) +        return getNode(Opcode, VT, N3C->getOperand(0), +                       getNode(Opcode, VT, N2, N1.Val->getOperand(1))); +  } + +  ConstantFPSDNode *N1CFP = dyn_cast<ConstantFPSDNode>(N1.Val); +  ConstantFPSDNode *N2CFP = dyn_cast<ConstantFPSDNode>(N2.Val); +  if (N1CFP) +    if (N2CFP) { +      double C1 = N1CFP->getValue(), C2 = N2CFP->getValue(); +      switch (Opcode) { +      case ISD::ADD: return getConstantFP(C1 + C2, VT); +      case ISD::SUB: return getConstantFP(C1 - C2, VT); +      case ISD::MUL: return getConstantFP(C1 * C2, VT); +      case ISD::SDIV: +        if (C2) return getConstantFP(C1 / C2, VT); +        break; +      case ISD::SREM : +        if (C2) return getConstantFP(fmod(C1, C2), VT); +        break; +      default: break; +      } + +    } else {      // Cannonicalize constant to RHS if commutative +      if (isCommutativeBinOp(Opcode)) { +        std::swap(N1CFP, N2CFP); +        std::swap(N1, N2); +      } +    } + +  // Finally, fold operations that do not require constants. +  switch (Opcode) { +  case ISD::AND: +  case ISD::OR: +    if (SetCCSDNode *LHS = dyn_cast<SetCCSDNode>(N1.Val)) +      if (SetCCSDNode *RHS = dyn_cast<SetCCSDNode>(N2.Val)) { +        SDOperand LL = LHS->getOperand(0), RL = RHS->getOperand(0); +        SDOperand LR = LHS->getOperand(1), RR = RHS->getOperand(1); +        ISD::CondCode Op2 = RHS->getCondition(); + +        // (X op1 Y) | (Y op2 X) -> (X op1 Y) | (X swapop2 Y) +        if (LL == RR && LR == RL) { +          Op2 = ISD::getSetCCSwappedOperands(Op2); +          goto MatchedBackwards; +        } +       +        if (LL == RL && LR == RR) { +        MatchedBackwards: +          ISD::CondCode Result; +          bool isInteger = MVT::isInteger(LL.getValueType()); +          if (Opcode == ISD::OR) +            Result = ISD::getSetCCOrOperation(LHS->getCondition(), Op2, +                                              isInteger); +          else +            Result = ISD::getSetCCAndOperation(LHS->getCondition(), Op2, +                                               isInteger); +          if (Result != ISD::SETCC_INVALID) +            return getSetCC(Result, LL, LR); +        } +      } +    break; +  case ISD::XOR: +    if (N1 == N2) return getConstant(0, VT);  // xor X, Y -> 0 +    break; +  } + +  SDNode *&N = BinaryOps[std::make_pair(Opcode, std::make_pair(N1, N2))]; +  if (N) return SDOperand(N, 0); +  N = new SDNode(Opcode, N1, N2); +  N->setValueTypes(VT); + +  AllNodes.push_back(N); +  return SDOperand(N, 0); +} + +SDOperand SelectionDAG::getLoad(MVT::ValueType VT, +                                SDOperand Chain, SDOperand Ptr) { +  SDNode *&N = Loads[std::make_pair(Ptr, std::make_pair(Chain, VT))]; +  if (N) return SDOperand(N, 0); +  N = new SDNode(ISD::LOAD, Chain, Ptr); + +  // Loads have a token chain. +  N->setValueTypes(VT, MVT::Other); +  AllNodes.push_back(N); +  return SDOperand(N, 0); +} + + +SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, +                                SDOperand N1, SDOperand N2, SDOperand N3) { +  // Perform various simplifications. +  ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1.Val); +  ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2.Val); +  ConstantSDNode *N3C = dyn_cast<ConstantSDNode>(N3.Val); +  switch (Opcode) { +  case ISD::SELECT: +    if (N1C) +      if (N1C->getValue()) +        return N2;             // select true, X, Y -> X +      else  +        return N3;             // select false, X, Y -> Y + +    if (N2 == N3) return N2;   // select C, X, X -> X + +    if (VT == MVT::i1) {  // Boolean SELECT +      if (N2C) { +        if (N3C) { +          if (N2C->getValue()) // select C, 1, 0 -> C +            return N1; +          return getNode(ISD::XOR, VT, N1, N3); // select C, 0, 1 -> ~C +        } + +        if (N2C->getValue())   // select C, 1, X -> C | X +          return getNode(ISD::OR, VT, N1, N3); +        else                   // select C, 0, X -> ~C & X +          return getNode(ISD::AND, VT, +                         getNode(ISD::XOR, N1.getValueType(), N1, +                                 getConstant(1, N1.getValueType())), N3); +      } else if (N3C) { +        if (N3C->getValue())   // select C, X, 1 -> ~C | X +          return getNode(ISD::OR, VT, +                         getNode(ISD::XOR, N1.getValueType(), N1, +                                 getConstant(1, N1.getValueType())), N2); +        else                   // select C, X, 0 -> C & X +          return getNode(ISD::AND, VT, N1, N2); +      } +    } + +    break; +  } + +  SDNode *N = new SDNode(Opcode, N1, N2, N3); +  switch (Opcode) { +  default:  +    N->setValueTypes(VT); +    break; +  case ISD::DYNAMIC_STACKALLOC: // DYNAMIC_STACKALLOC produces pointer and chain +    N->setValueTypes(VT, MVT::Other); +    break; +  } + +  // FIXME: memoize NODES +  AllNodes.push_back(N); +  return SDOperand(N, 0); +} + +SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, +                                std::vector<SDOperand> &Children) { +  switch (Children.size()) { +  case 0: return getNode(Opcode, VT); +  case 1: return getNode(Opcode, VT, Children[0]); +  case 2: return getNode(Opcode, VT, Children[0], Children[1]); +  case 3: return getNode(Opcode, VT, Children[0], Children[1], Children[2]); +  default: +    // FIXME: MEMOIZE!! +    SDNode *N = new SDNode(Opcode, Children); +    N->setValueTypes(VT); +    AllNodes.push_back(N); +    return SDOperand(N, 0); +  } +} + + + +void SDNode::dump() const { +  std::cerr << (void*)this << ": "; + +  for (unsigned i = 0, e = getNumValues(); i != e; ++i) { +    if (i) std::cerr << ","; +    switch (getValueType(i)) { +    default: assert(0 && "Unknown value type!"); +    case MVT::i1:    std::cerr << "i1"; break; +    case MVT::i8:    std::cerr << "i8"; break; +    case MVT::i16:   std::cerr << "i16"; break; +    case MVT::i32:   std::cerr << "i32"; break; +    case MVT::i64:   std::cerr << "i64"; break; +    case MVT::f32:   std::cerr << "f32"; break; +    case MVT::f64:   std::cerr << "f64"; break; +    case MVT::Other: std::cerr << "ch"; break; +    } +  } +  std::cerr << " = "; + +  switch (getOpcode()) { +  default: std::cerr << "<<Unknown>>"; break; +  case ISD::EntryToken:    std::cerr << "EntryToken"; break; +  case ISD::Constant:      std::cerr << "Constant"; break; +  case ISD::ConstantFP:    std::cerr << "ConstantFP"; break; +  case ISD::GlobalAddress: std::cerr << "GlobalAddress"; break; +  case ISD::FrameIndex:    std::cerr << "FrameIndex"; break; +  case ISD::BasicBlock:    std::cerr << "BasicBlock"; break; +  case ISD::ExternalSymbol: std::cerr << "ExternalSymbol"; break; +  case ISD::ConstantPool:  std::cerr << "ConstantPoolIndex"; break; +  case ISD::CopyToReg:     std::cerr << "CopyToReg"; break; +  case ISD::CopyFromReg:   std::cerr << "CopyFromReg"; break; + +  case ISD::ADD:    std::cerr << "add"; break; +  case ISD::SUB:    std::cerr << "sub"; break; +  case ISD::MUL:    std::cerr << "mul"; break; +  case ISD::SDIV:   std::cerr << "sdiv"; break; +  case ISD::UDIV:   std::cerr << "udiv"; break; +  case ISD::SREM:   std::cerr << "srem"; break; +  case ISD::UREM:   std::cerr << "urem"; break; +  case ISD::AND:    std::cerr << "and"; break; +  case ISD::OR:     std::cerr << "or"; break; +  case ISD::XOR:    std::cerr << "xor"; break; +  case ISD::SHL:    std::cerr << "shl"; break; +  case ISD::SRA:    std::cerr << "sra"; break; +  case ISD::SRL:    std::cerr << "srl"; break; + +  case ISD::SETCC:  std::cerr << "setcc"; break; +  case ISD::SELECT: std::cerr << "select"; break; +  case ISD::ADDC:   std::cerr << "addc"; break; +  case ISD::SUBB:   std::cerr << "subb"; break; + +    // Conversion operators. +  case ISD::SIGN_EXTEND: std::cerr << "sign_extend"; break; +  case ISD::ZERO_EXTEND: std::cerr << "zero_extend"; break; +  case ISD::TRUNCATE:    std::cerr << "truncate"; break; +  case ISD::FP_ROUND:    std::cerr << "fp_round"; break; +  case ISD::FP_EXTEND:   std::cerr << "fp_extend"; break; + +    // Control flow instructions +  case ISD::BR:      std::cerr << "br"; break; +  case ISD::BRCOND:  std::cerr << "brcond"; break; +  case ISD::RET:     std::cerr << "ret"; break; +  case ISD::CALL:    std::cerr << "call"; break; +  case ISD::ADJCALLSTACKDOWN:  std::cerr << "adjcallstackdown"; break; +  case ISD::ADJCALLSTACKUP:    std::cerr << "adjcallstackup"; break; + +    // Other operators +  case ISD::LOAD:    std::cerr << "load"; break; +  case ISD::STORE:   std::cerr << "store"; break; +  case ISD::DYNAMIC_STACKALLOC: std::cerr << "dynamic_stackalloc"; break; +  case ISD::EXTRACT_ELEMENT: std::cerr << "extract_element"; break; +  case ISD::BUILD_PAIR: std::cerr << "build_pair"; break; +  } + +  std::cerr << " "; +  for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { +    if (i) std::cerr << ", "; +    std::cerr << (void*)getOperand(i).Val; +    if (unsigned RN = getOperand(i).ResNo) +      std::cerr << ":" << RN; +  } + +  if (const ConstantSDNode *CSDN = dyn_cast<ConstantSDNode>(this)) { +    std::cerr << "<" << CSDN->getValue() << ">"; +  } else if (const ConstantFPSDNode *CSDN = dyn_cast<ConstantFPSDNode>(this)) { +    std::cerr << "<" << CSDN->getValue() << ">"; +  } else if (const GlobalAddressSDNode *GADN =  +             dyn_cast<GlobalAddressSDNode>(this)) { +    std::cerr << "<"; +    WriteAsOperand(std::cerr, GADN->getGlobal()) << ">"; +  } else if (const FrameIndexSDNode *FIDN = +	     dyn_cast<FrameIndexSDNode>(this)) { +    std::cerr << "<" << FIDN->getIndex() << ">"; +  } else if (const ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(this)){ +    std::cerr << "<" << CP->getIndex() << ">"; +  } else if (const BasicBlockSDNode *BBDN =  +	     dyn_cast<BasicBlockSDNode>(this)) { +    std::cerr << "<"; +    const Value *LBB = (const Value*)BBDN->getBasicBlock()->getBasicBlock(); +    if (LBB) +      std::cerr << LBB->getName() << " "; +    std::cerr << (const void*)BBDN->getBasicBlock() << ">"; +  } else if (const CopyRegSDNode *C2V = dyn_cast<CopyRegSDNode>(this)) { +    std::cerr << "<reg #" << C2V->getReg() << ">"; +  } else if (const ExternalSymbolSDNode *ES = +             dyn_cast<ExternalSymbolSDNode>(this)) { +    std::cerr << "'" << ES->getSymbol() << "'"; +  } else if (const SetCCSDNode *SetCC = dyn_cast<SetCCSDNode>(this)) { +    std::cerr << " - condition = "; +    switch (SetCC->getCondition()) { +    default: assert(0 && "Unknown setcc condition!"); +    case ISD::SETOEQ:  std::cerr << "setoeq"; break; +    case ISD::SETOGT:  std::cerr << "setogt"; break; +    case ISD::SETOGE:  std::cerr << "setoge"; break; +    case ISD::SETOLT:  std::cerr << "setolt"; break; +    case ISD::SETOLE:  std::cerr << "setole"; break; +    case ISD::SETONE:  std::cerr << "setone"; break; +       +    case ISD::SETO:    std::cerr << "seto";  break; +    case ISD::SETUO:   std::cerr << "setuo"; break; +    case ISD::SETUEQ:  std::cerr << "setue"; break; +    case ISD::SETUGT:  std::cerr << "setugt"; break; +    case ISD::SETUGE:  std::cerr << "setuge"; break; +    case ISD::SETULT:  std::cerr << "setult"; break; +    case ISD::SETULE:  std::cerr << "setule"; break; +    case ISD::SETUNE:  std::cerr << "setune"; break; +       +    case ISD::SETEQ:   std::cerr << "seteq"; break; +    case ISD::SETGT:   std::cerr << "setgt"; break; +    case ISD::SETGE:   std::cerr << "setge"; break; +    case ISD::SETLT:   std::cerr << "setlt"; break; +    case ISD::SETLE:   std::cerr << "setle"; break; +    case ISD::SETNE:   std::cerr << "setne"; break; +    } +  } + +} + +void SelectionDAG::dump() const { +  std::cerr << "SelectionDAG has " << AllNodes.size() << " nodes:"; +  for (unsigned i = 0, e = AllNodes.size(); i != e; ++i) { +    std::cerr << "\n  "; +    AllNodes[i]->dump(); +  } +  std::cerr << "\n\n"; +} + | 

