Complete rewrite of the SelectionDAG class.
authorChris Lattner <sabre@nondot.org>
Fri, 7 Jan 2005 07:46:32 +0000 (07:46 +0000)
committerChris Lattner <sabre@nondot.org>
Fri, 7 Jan 2005 07:46:32 +0000 (07:46 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19327 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/SelectionDAG.h
lib/CodeGen/SelectionDAG/SelectionDAG.cpp

index 796ee1353502f81ce6d68a3e67d004fdf076c8a6..ce5deecf38f31b558a7bca46c9c024dc0edbbc77 100644 (file)
@@ -1,4 +1,4 @@
-//===-- llvm/CodeGen/SelectionDAG.h - InstSelection DAG Rep. ----*- C++ -*-===//
+//===-- llvm/CodeGen/SelectionDAG.h - InstSelection DAG ---------*- C++ -*-===//
 // 
 //                     The LLVM Compiler Infrastructure
 //
 // 
 //===----------------------------------------------------------------------===//
 // 
-// 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
index acf3daa32f579408da86b88525182fa0849f1b32..f02bdcd95b1dae68936ce0db99336c279b407820 100644 (file)
@@ -1,4 +1,4 @@
-//===-- SelectionDAG.cpp - Implement the SelectionDAG* classes ------------===//
+//===-- SelectionDAG.cpp - Implement the SelectionDAG data structures -----===//
 // 
 //                     The LLVM Compiler Infrastructure
 //
 // 
 //===----------------------------------------------------------------------===//
 //
-// 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";
+}
+