[llvm-commits] [llvm] r55746 - in /llvm/trunk: include/llvm/CodeGen/FastISel.h include/llvm/CodeGen/SelectionDAGISel.h include/llvm/Target/TargetLowering.h lib/CodeGen/SelectionDAG/FastISel.cpp lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp lib/Target/X86/X86FastISel.cpp lib/Target/X86/X86ISelLowering.cpp lib/Target/X86/X86ISelLowering.h

Dan Gohman gohman at apple.com
Wed Sep 3 16:12:08 PDT 2008


Author: djg
Date: Wed Sep  3 18:12:08 2008
New Revision: 55746

URL: http://llvm.org/viewvc/llvm-project?rev=55746&view=rev
Log:
Create HandlePHINodesInSuccessorBlocksFast, a version of
HandlePHINodesInSuccessorBlocks that works FastISel-style. This
allows PHI nodes to be updated correctly while using FastISel.

This also involves some code reorganization; ValueMap and
MBBMap are now members of the FastISel class, so they needn't
be passed around explicitly anymore. Also, SelectInstructions
is changed to SelectInstruction, and only does one instruction
at a time.

Modified:
    llvm/trunk/include/llvm/CodeGen/FastISel.h
    llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h
    llvm/trunk/include/llvm/Target/TargetLowering.h
    llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
    llvm/trunk/lib/Target/X86/X86FastISel.cpp
    llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
    llvm/trunk/lib/Target/X86/X86ISelLowering.h

Modified: llvm/trunk/include/llvm/CodeGen/FastISel.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/FastISel.h?rev=55746&r1=55745&r2=55746&view=diff

==============================================================================
--- llvm/trunk/include/llvm/CodeGen/FastISel.h (original)
+++ llvm/trunk/include/llvm/CodeGen/FastISel.h Wed Sep  3 18:12:08 2008
@@ -36,6 +36,8 @@
 class FastISel {
 protected:
   MachineBasicBlock *MBB;
+  DenseMap<const Value *, unsigned> &ValueMap;
+  DenseMap<const BasicBlock *, MachineBasicBlock *> &MBBMap;
   MachineFunction &MF;
   MachineRegisterInfo &MRI;
   const TargetMachine &TM;
@@ -44,17 +46,18 @@
   const TargetLowering &TLI;
 
 public:
-  /// SelectInstructions - Do "fast" instruction selection over the
-  /// LLVM IR instructions in the range [Begin, N) where N is either
-  /// End or the first unsupported instruction. Return N.
-  /// ValueMap is filled in with a mapping of LLVM IR Values to
-  /// virtual register numbers. MBB is a block to which to append
-  /// the generated MachineInstrs.
-  BasicBlock::iterator
-  SelectInstructions(BasicBlock::iterator Begin, BasicBlock::iterator End,
-                     DenseMap<const Value *, unsigned> &ValueMap,
-                     DenseMap<const BasicBlock *, MachineBasicBlock *> &MBBMap,
-                     MachineBasicBlock *MBB);
+  /// setCurrentBlock - Set the current block, to which generated
+  /// machine instructions will be appended.
+  ///
+  void setCurrentBlock(MachineBasicBlock *mbb) {
+    MBB = mbb;
+  }
+
+  /// SelectInstruction - Do "fast" instruction selection for the given
+  /// LLVM IR instruction, and append generated machine instructions to
+  /// the current block. Return true if selection was successful.
+  ///
+  bool SelectInstruction(Instruction *I);
 
   /// TargetSelectInstruction - This method is called by target-independent
   /// code when the normal FastISel process fails to select an instruction.
@@ -62,15 +65,18 @@
   /// fit into FastISel's framework. It returns true if it was successful.
   ///
   virtual bool
-  TargetSelectInstruction(Instruction *I,
-                          DenseMap<const Value *, unsigned> &ValueMap,
-                      DenseMap<const BasicBlock *, MachineBasicBlock *> &MBBMap,
-                          MachineBasicBlock *MBB) = 0;
+  TargetSelectInstruction(Instruction *I) = 0;
+
+  /// getRegForValue - Create a virtual register and arrange for it to
+  /// be assigned the value for the given LLVM value.
+  unsigned getRegForValue(Value *V);
 
   virtual ~FastISel();
 
 protected:
-  explicit FastISel(MachineFunction &mf);
+  FastISel(MachineFunction &mf,
+           DenseMap<const Value *, unsigned> &vm,
+           DenseMap<const BasicBlock *, MachineBasicBlock *> &bm);
 
   /// FastEmit_r - This method is called by target-independent code
   /// to request that an instruction with the given type and opcode
@@ -208,26 +214,18 @@
   /// from a specified index of a superregister.
   unsigned FastEmitInst_extractsubreg(unsigned Op0, uint32_t Idx);
 
-  unsigned getRegForValue(Value *V,
-                          DenseMap<const Value*, unsigned> &ValueMap);
-
-  void UpdateValueMap(Instruction* I, unsigned Reg, 
-                      DenseMap<const Value*, unsigned> &ValueMap);
+  void UpdateValueMap(Instruction* I, unsigned Reg);
 
   unsigned createResultReg(const TargetRegisterClass *RC);
 
 private:
-  bool SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode,
-                      DenseMap<const Value*, unsigned> &ValueMap);
+  bool SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode);
 
-  bool SelectGetElementPtr(Instruction *I,
-                           DenseMap<const Value*, unsigned> &ValueMap);
+  bool SelectGetElementPtr(Instruction *I);
 
-  bool SelectBitCast(Instruction *I,
-                     DenseMap<const Value*, unsigned> &ValueMap);
+  bool SelectBitCast(Instruction *I);
   
-  bool SelectCast(Instruction *I, ISD::NodeType Opcode,
-                  DenseMap<const Value*, unsigned> &ValueMap);                  
+  bool SelectCast(Instruction *I, ISD::NodeType Opcode);
 };
 
 }

Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h?rev=55746&r1=55745&r2=55746&view=diff

==============================================================================
--- llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h (original)
+++ llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h Wed Sep  3 18:12:08 2008
@@ -21,6 +21,7 @@
 #include "llvm/CodeGen/SelectionDAG.h"
 
 namespace llvm {
+  class FastISel;
   class SelectionDAGLowering;
   class SDValue;
   class MachineRegisterInfo;
@@ -118,6 +119,8 @@
 
   void HandlePHINodesInSuccessorBlocks(BasicBlock *LLVMBB);
 
+  bool HandlePHINodesInSuccessorBlocksFast(BasicBlock *LLVMBB, FastISel *F);
+
   /// Pick a safe ordering for instructions for each target node in the
   /// graph.
   ScheduleDAG *Schedule();

Modified: llvm/trunk/include/llvm/Target/TargetLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetLowering.h?rev=55746&r1=55745&r2=55746&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Target/TargetLowering.h (original)
+++ llvm/trunk/include/llvm/Target/TargetLowering.h Wed Sep  3 18:12:08 2008
@@ -27,6 +27,7 @@
 #include "llvm/CodeGen/SelectionDAGNodes.h"
 #include "llvm/CodeGen/RuntimeLibcalls.h"
 #include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/STLExtras.h"
 #include <map>
 #include <vector>
@@ -1116,7 +1117,12 @@
 
   /// createFastISel - This method returns a target specific FastISel object,
   /// or null if the target does not support "fast" ISel.
-  virtual FastISel *createFastISel(MachineFunction &) { return 0; }
+  virtual FastISel *
+  createFastISel(MachineFunction &,
+                 DenseMap<const Value *, unsigned> &,
+                 DenseMap<const BasicBlock *, MachineBasicBlock *> &) {
+    return 0;
+  }
 
   //===--------------------------------------------------------------------===//
   // Inline Asm Support hooks

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp?rev=55746&r1=55745&r2=55746&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp Wed Sep  3 18:12:08 2008
@@ -25,8 +25,7 @@
 // tracking what uses they dominate.  Non-constants, however, already
 // have the SSA def-doms-use requirement enforced, so we can cache their
 // computations.
-unsigned FastISel::getRegForValue(Value *V,
-                                  DenseMap<const Value*, unsigned> &ValueMap) {
+unsigned FastISel::getRegForValue(Value *V) {
   if (ValueMap.count(V))
     return ValueMap[V];
 
@@ -78,8 +77,7 @@
 /// NOTE: This is only necessary because we might select a block that uses
 /// a value before we select the block that defines the value.  It might be
 /// possible to fix this by selecting blocks in reverse postorder.
-void FastISel::UpdateValueMap(Instruction* I, unsigned Reg, 
-                              DenseMap<const Value*, unsigned> &ValueMap) {
+void FastISel::UpdateValueMap(Instruction* I, unsigned Reg) {
   if (!ValueMap.count(I))
     ValueMap[I] = Reg;
   else
@@ -90,8 +88,7 @@
 /// SelectBinaryOp - Select and emit code for a binary operator instruction,
 /// which has an opcode which directly corresponds to the given ISD opcode.
 ///
-bool FastISel::SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode,
-                              DenseMap<const Value*, unsigned> &ValueMap) {
+bool FastISel::SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode) {
   MVT VT = MVT::getMVT(I->getType(), /*HandleUnknown=*/true);
   if (VT == MVT::Other || !VT.isSimple())
     // Unhandled type. Halt "fast" selection and bail.
@@ -103,7 +100,7 @@
   if (!TLI.isTypeLegal(VT))
     return false;
 
-  unsigned Op0 = getRegForValue(I->getOperand(0), ValueMap);
+  unsigned Op0 = getRegForValue(I->getOperand(0));
   if (Op0 == 0)
     // Unhandled operand. Halt "fast" selection and bail.
     return false;
@@ -114,7 +111,7 @@
                                      ISDOpcode, Op0, CI->getZExtValue());
     if (ResultReg != 0) {
       // We successfully emitted code for the given LLVM Instruction.
-      UpdateValueMap(I, ResultReg, ValueMap);
+      UpdateValueMap(I, ResultReg);
       return true;
     }
   }
@@ -125,12 +122,12 @@
                                      ISDOpcode, Op0, CF);
     if (ResultReg != 0) {
       // We successfully emitted code for the given LLVM Instruction.
-      UpdateValueMap(I, ResultReg, ValueMap);
+      UpdateValueMap(I, ResultReg);
       return true;
     }
   }
 
-  unsigned Op1 = getRegForValue(I->getOperand(1), ValueMap);
+  unsigned Op1 = getRegForValue(I->getOperand(1));
   if (Op1 == 0)
     // Unhandled operand. Halt "fast" selection and bail.
     return false;
@@ -144,13 +141,12 @@
     return false;
 
   // We successfully emitted code for the given LLVM Instruction.
-  UpdateValueMap(I, ResultReg, ValueMap);
+  UpdateValueMap(I, ResultReg);
   return true;
 }
 
-bool FastISel::SelectGetElementPtr(Instruction *I,
-                                   DenseMap<const Value*, unsigned> &ValueMap) {
-  unsigned N = getRegForValue(I->getOperand(0), ValueMap);
+bool FastISel::SelectGetElementPtr(Instruction *I) {
+  unsigned N = getRegForValue(I->getOperand(0));
   if (N == 0)
     // Unhandled operand. Halt "fast" selection and bail.
     return false;
@@ -190,7 +186,7 @@
       
       // N = N + Idx * ElementSize;
       uint64_t ElementSize = TD.getABITypeSize(Ty);
-      unsigned IdxN = getRegForValue(Idx, ValueMap);
+      unsigned IdxN = getRegForValue(Idx);
       if (IdxN == 0)
         // Unhandled operand. Halt "fast" selection and bail.
         return false;
@@ -220,12 +216,11 @@
   }
 
   // We successfully emitted code for the given LLVM Instruction.
-  UpdateValueMap(I, N, ValueMap);
+  UpdateValueMap(I, N);
   return true;
 }
 
-bool FastISel::SelectCast(Instruction *I, ISD::NodeType Opcode,
-                          DenseMap<const Value*, unsigned> &ValueMap) {
+bool FastISel::SelectCast(Instruction *I, ISD::NodeType Opcode) {
   MVT SrcVT = TLI.getValueType(I->getOperand(0)->getType());
   MVT DstVT = TLI.getValueType(I->getType());
     
@@ -235,7 +230,7 @@
     // Unhandled type. Halt "fast" selection and bail.
     return false;
     
-  unsigned InputReg = getRegForValue(I->getOperand(0), ValueMap);
+  unsigned InputReg = getRegForValue(I->getOperand(0));
   if (!InputReg)
     // Unhandled operand.  Halt "fast" selection and bail.
     return false;
@@ -247,18 +242,17 @@
   if (!ResultReg)
     return false;
     
-  UpdateValueMap(I, ResultReg, ValueMap);
+  UpdateValueMap(I, ResultReg);
   return true;
 }
 
-bool FastISel::SelectBitCast(Instruction *I,
-                             DenseMap<const Value*, unsigned> &ValueMap) {
+bool FastISel::SelectBitCast(Instruction *I) {
   // If the bitcast doesn't change the type, just use the operand value.
   if (I->getType() == I->getOperand(0)->getType()) {
-    unsigned Reg = getRegForValue(I->getOperand(0), ValueMap);
+    unsigned Reg = getRegForValue(I->getOperand(0));
     if (Reg == 0)
       return false;
-    UpdateValueMap(I, Reg, ValueMap);
+    UpdateValueMap(I, Reg);
     return true;
   }
 
@@ -272,7 +266,7 @@
     // Unhandled type. Halt "fast" selection and bail.
     return false;
   
-  unsigned Op0 = getRegForValue(I->getOperand(0), ValueMap);
+  unsigned Op0 = getRegForValue(I->getOperand(0));
   if (Op0 == 0)
     // Unhandled operand. Halt "fast" selection and bail.
     return false;
@@ -298,143 +292,124 @@
   if (!ResultReg)
     return false;
   
-  UpdateValueMap(I, ResultReg, ValueMap);
+  UpdateValueMap(I, ResultReg);
   return true;
 }
 
-BasicBlock::iterator
-FastISel::SelectInstructions(BasicBlock::iterator Begin,
-                             BasicBlock::iterator End,
-                             DenseMap<const Value*, unsigned> &ValueMap,
-                             DenseMap<const BasicBlock*,
-                                      MachineBasicBlock *> &MBBMap,
-                             MachineBasicBlock *mbb) {
-  MBB = mbb;
-  BasicBlock::iterator I = Begin;
-
-  for (; I != End; ++I) {
-    switch (I->getOpcode()) {
-    case Instruction::Add: {
-      ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FADD : ISD::ADD;
-      if (!SelectBinaryOp(I, Opc, ValueMap))  return I; break;
-    }
-    case Instruction::Sub: {
-      ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FSUB : ISD::SUB;
-      if (!SelectBinaryOp(I, Opc, ValueMap))  return I; break;
-    }
-    case Instruction::Mul: {
-      ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FMUL : ISD::MUL;
-      if (!SelectBinaryOp(I, Opc, ValueMap))  return I; break;
-    }
-    case Instruction::SDiv:
-      if (!SelectBinaryOp(I, ISD::SDIV, ValueMap)) return I; break;
-    case Instruction::UDiv:
-      if (!SelectBinaryOp(I, ISD::UDIV, ValueMap)) return I; break;
-    case Instruction::FDiv:
-      if (!SelectBinaryOp(I, ISD::FDIV, ValueMap)) return I; break;
-    case Instruction::SRem:
-      if (!SelectBinaryOp(I, ISD::SREM, ValueMap)) return I; break;
-    case Instruction::URem:
-      if (!SelectBinaryOp(I, ISD::UREM, ValueMap)) return I; break;
-    case Instruction::FRem:
-      if (!SelectBinaryOp(I, ISD::FREM, ValueMap)) return I; break;
-    case Instruction::Shl:
-      if (!SelectBinaryOp(I, ISD::SHL, ValueMap)) return I; break;
-    case Instruction::LShr:
-      if (!SelectBinaryOp(I, ISD::SRL, ValueMap)) return I; break;
-    case Instruction::AShr:
-      if (!SelectBinaryOp(I, ISD::SRA, ValueMap)) return I; break;
-    case Instruction::And:
-      if (!SelectBinaryOp(I, ISD::AND, ValueMap)) return I; break;
-    case Instruction::Or:
-      if (!SelectBinaryOp(I, ISD::OR, ValueMap)) return I; break;
-    case Instruction::Xor:
-      if (!SelectBinaryOp(I, ISD::XOR, ValueMap)) return I; break;
-
-    case Instruction::GetElementPtr:
-      if (!SelectGetElementPtr(I, ValueMap)) return I;
-      break;
-
-    case Instruction::Br: {
-      BranchInst *BI = cast<BranchInst>(I);
-
-      if (BI->isUnconditional()) {
-        MachineFunction::iterator NextMBB =
-           next(MachineFunction::iterator(MBB));
-        BasicBlock *LLVMSucc = BI->getSuccessor(0);
-        MachineBasicBlock *MSucc = MBBMap[LLVMSucc];
-
-        if (NextMBB != MF.end() && MSucc == NextMBB) {
-          // The unconditional fall-through case, which needs no instructions.
-        } else {
-          // The unconditional branch case.
-          TII.InsertBranch(*MBB, MSucc, NULL, SmallVector<MachineOperand, 0>());
-        }
-        MBB->addSuccessor(MSucc);
-        break;
-      }
-
-      // Conditional branches are not handed yet.
-      // Halt "fast" selection and bail.
-      return I;
-    }
-
-    case Instruction::PHI:
-      // PHI nodes are already emitted.
-      break;
-      
-    case Instruction::BitCast:
-      if (!SelectBitCast(I, ValueMap)) return I; break;
+bool
+FastISel::SelectInstruction(Instruction *I) {
+  switch (I->getOpcode()) {
+  case Instruction::Add: {
+    ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FADD : ISD::ADD;
+    return SelectBinaryOp(I, Opc);
+  }
+  case Instruction::Sub: {
+    ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FSUB : ISD::SUB;
+    return SelectBinaryOp(I, Opc);
+  }
+  case Instruction::Mul: {
+    ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FMUL : ISD::MUL;
+    return SelectBinaryOp(I, Opc);
+  }
+  case Instruction::SDiv:
+    return SelectBinaryOp(I, ISD::SDIV);
+  case Instruction::UDiv:
+    return SelectBinaryOp(I, ISD::UDIV);
+  case Instruction::FDiv:
+    return SelectBinaryOp(I, ISD::FDIV);
+  case Instruction::SRem:
+    return SelectBinaryOp(I, ISD::SREM);
+  case Instruction::URem:
+    return SelectBinaryOp(I, ISD::UREM);
+  case Instruction::FRem:
+    return SelectBinaryOp(I, ISD::FREM);
+  case Instruction::Shl:
+    return SelectBinaryOp(I, ISD::SHL);
+  case Instruction::LShr:
+    return SelectBinaryOp(I, ISD::SRL);
+  case Instruction::AShr:
+    return SelectBinaryOp(I, ISD::SRA);
+  case Instruction::And:
+    return SelectBinaryOp(I, ISD::AND);
+  case Instruction::Or:
+    return SelectBinaryOp(I, ISD::OR);
+  case Instruction::Xor:
+    return SelectBinaryOp(I, ISD::XOR);
+
+  case Instruction::GetElementPtr:
+    return SelectGetElementPtr(I);
+
+  case Instruction::Br: {
+    BranchInst *BI = cast<BranchInst>(I);
+
+    if (BI->isUnconditional()) {
+      MachineFunction::iterator NextMBB =
+         next(MachineFunction::iterator(MBB));
+      BasicBlock *LLVMSucc = BI->getSuccessor(0);
+      MachineBasicBlock *MSucc = MBBMap[LLVMSucc];
 
-    case Instruction::FPToSI:
-      if (!SelectCast(I, ISD::FP_TO_SINT, ValueMap)) return I; 
-      break;
-    case Instruction::ZExt:
-      if (!SelectCast(I, ISD::ZERO_EXTEND, ValueMap)) return I;
-      break;
-    case Instruction::SExt:
-      if (!SelectCast(I, ISD::SIGN_EXTEND, ValueMap)) return I;
-      break;
-    case Instruction::Trunc:
-      if (!SelectCast(I, ISD::TRUNCATE, ValueMap)) return I;
-      break;
-    case Instruction::SIToFP:
-      if (!SelectCast(I, ISD::SINT_TO_FP, ValueMap)) return I;
-      break;
-
-    case Instruction::IntToPtr: // Deliberate fall-through.
-    case Instruction::PtrToInt: {
-      MVT SrcVT = TLI.getValueType(I->getOperand(0)->getType());
-      MVT DstVT = TLI.getValueType(I->getType());
-      if (SrcVT.getSimpleVT() == DstVT.getSimpleVT()) {
-        if (ValueMap[I->getOperand(0)]) {
-          UpdateValueMap(I, ValueMap[I->getOperand(0)], ValueMap);
-          break;
-        } else
-          // Unhandled operand
-          return I;
-      } else if (DstVT.bitsGT(SrcVT)) {
-        if (!SelectCast(I, ISD::ZERO_EXTEND, ValueMap)) return I;
-        break;
+      if (NextMBB != MF.end() && MSucc == NextMBB) {
+        // The unconditional fall-through case, which needs no instructions.
       } else {
-        // TODO: Handle SrcVT > DstVT, where truncation is needed.
-        return I;
+        // The unconditional branch case.
+        TII.InsertBranch(*MBB, MSucc, NULL, SmallVector<MachineOperand, 0>());
       }
+      MBB->addSuccessor(MSucc);
+      return true;
     }
-    
-    default:
-      // Unhandled instruction. Halt "fast" selection and bail.
-      return I;
-    }
+
+    // Conditional branches are not handed yet.
+    // Halt "fast" selection and bail.
+    return false;
   }
 
-  return I;
+  case Instruction::PHI:
+    // PHI nodes are already emitted.
+    return true;
+    
+  case Instruction::BitCast:
+    return SelectBitCast(I);
+
+  case Instruction::FPToSI:
+    return SelectCast(I, ISD::FP_TO_SINT);
+  case Instruction::ZExt:
+    return SelectCast(I, ISD::ZERO_EXTEND);
+  case Instruction::SExt:
+    return SelectCast(I, ISD::SIGN_EXTEND);
+  case Instruction::Trunc:
+    return SelectCast(I, ISD::TRUNCATE);
+  case Instruction::SIToFP:
+    return SelectCast(I, ISD::SINT_TO_FP);
+
+  case Instruction::IntToPtr: // Deliberate fall-through.
+  case Instruction::PtrToInt: {
+    MVT SrcVT = TLI.getValueType(I->getOperand(0)->getType());
+    MVT DstVT = TLI.getValueType(I->getType());
+    if (DstVT.bitsGT(SrcVT))
+      return SelectCast(I, ISD::ZERO_EXTEND);
+    if (DstVT.bitsLT(SrcVT))
+      return SelectCast(I, ISD::TRUNCATE);
+    unsigned Reg = getRegForValue(I->getOperand(0));
+    if (Reg == 0) return false;
+    UpdateValueMap(I, Reg);
+    return true;
+  }
+  
+  default:
+    // Unhandled instruction. Halt "fast" selection and bail.
+    return false;
+  }
 }
 
-FastISel::FastISel(MachineFunction &mf)
-  : MF(mf),
-    MRI(mf.getRegInfo()),
-    TM(mf.getTarget()),
+FastISel::FastISel(MachineFunction &mf,
+                   DenseMap<const Value *, unsigned> &vm,
+                   DenseMap<const BasicBlock *, MachineBasicBlock *> &bm)
+  : MBB(0),
+    ValueMap(vm),
+    MBBMap(bm),
+    MF(mf),
+    MRI(MF.getRegInfo()),
+    TM(MF.getTarget()),
     TD(*TM.getTargetData()),
     TII(*TM.getInstrInfo()),
     TLI(*TM.getTargetLowering()) {

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp?rev=55746&r1=55745&r2=55746&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp Wed Sep  3 18:12:08 2008
@@ -4757,9 +4757,64 @@
     }
   }
   SDL->ConstantsOut.clear();
-
-  // Lower the terminator after the copies are emitted.
-  SDL->visit(*LLVMBB->getTerminator());
 }
 
+/// This is the Fast-ISel version of HandlePHINodesInSuccessorBlocks. It only
+/// supports legal types, and it emits MachineInstrs directly instead of
+/// creating SelectionDAG nodes.
+///
+bool
+SelectionDAGISel::HandlePHINodesInSuccessorBlocksFast(BasicBlock *LLVMBB,
+                                                      FastISel *F) {
+  TerminatorInst *TI = LLVMBB->getTerminator();
+
+  SmallPtrSet<MachineBasicBlock *, 4> SuccsHandled;
+  unsigned OrigNumPHINodesToUpdate = SDL->PHINodesToUpdate.size();
+
+  // Check successor nodes' PHI nodes that expect a constant to be available
+  // from this block.
+  for (unsigned succ = 0, e = TI->getNumSuccessors(); succ != e; ++succ) {
+    BasicBlock *SuccBB = TI->getSuccessor(succ);
+    if (!isa<PHINode>(SuccBB->begin())) continue;
+    MachineBasicBlock *SuccMBB = FuncInfo->MBBMap[SuccBB];
+    
+    // If this terminator has multiple identical successors (common for
+    // switches), only handle each succ once.
+    if (!SuccsHandled.insert(SuccMBB)) continue;
+    
+    MachineBasicBlock::iterator MBBI = SuccMBB->begin();
+    PHINode *PN;
+
+    // At this point we know that there is a 1-1 correspondence between LLVM PHI
+    // nodes and Machine PHI nodes, but the incoming operands have not been
+    // emitted yet.
+    for (BasicBlock::iterator I = SuccBB->begin();
+         (PN = dyn_cast<PHINode>(I)); ++I) {
+      // Ignore dead phi's.
+      if (PN->use_empty()) continue;
+
+      // Only handle legal types. Two interesting things to note here. First,
+      // by bailing out early, we may leave behind some dead instructions,
+      // since SelectionDAG's HandlePHINodesInSuccessorBlocks will insert its
+      // own moves. Second, this check is necessary becuase FastISel doesn't
+      // use CreateRegForValue to create registers, so it always creates
+      // exactly one register for each non-void instruction.
+      MVT VT = TLI.getValueType(PN->getType(), /*AllowUnknown=*/true);
+      if (VT == MVT::Other || !TLI.isTypeLegal(VT)) {
+        SDL->PHINodesToUpdate.resize(OrigNumPHINodesToUpdate);
+        return false;
+      }
 
+      Value *PHIOp = PN->getIncomingValueForBlock(LLVMBB);
+
+      unsigned Reg = F->getRegForValue(PHIOp);
+      if (Reg == 0) {
+        SDL->PHINodesToUpdate.resize(OrigNumPHINodesToUpdate);
+        return false;
+      }
+      SDL->PHINodesToUpdate.push_back(std::make_pair(MBBI++, Reg));
+    }
+  }
+
+  return true;
+}

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp?rev=55746&r1=55745&r2=55746&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Wed Sep  3 18:12:08 2008
@@ -408,8 +408,12 @@
     }
 
   // Handle PHI nodes in successor blocks.
-  if (End == LLVMBB->end())
+  if (End == LLVMBB->end()) {
     HandlePHINodesInSuccessorBlocks(LLVMBB);
+
+    // Lower the terminator after the copies are emitted.
+    SDL->visit(*LLVMBB->getTerminator());
+  }
     
   // Make sure the root of the DAG is up-to-date.
   CurDAG->setRoot(SDL->getControlRoot());
@@ -606,8 +610,9 @@
     BasicBlock *LLVMBB = &*I;
     BB = FuncInfo->MBBMap[LLVMBB];
 
-    BasicBlock::iterator Begin = LLVMBB->begin();
-    BasicBlock::iterator End = LLVMBB->end();
+    BasicBlock::iterator const Begin = LLVMBB->begin();
+    BasicBlock::iterator const End = LLVMBB->end();
+    BasicBlock::iterator I = Begin;
 
     // Lower any arguments needed in this block if this is the entry block.
     if (LLVMBB == &Fn.getEntryBlock())
@@ -616,7 +621,8 @@
     // Before doing SelectionDAG ISel, see if FastISel has been requested.
     // FastISel doesn't support EH landing pads, which require special handling.
     if (EnableFastISel && !BB->isLandingPad()) {
-      if (FastISel *F = TLI.createFastISel(*FuncInfo->MF)) {
+      if (FastISel *F = TLI.createFastISel(*FuncInfo->MF, FuncInfo->ValueMap,
+                                           FuncInfo->MBBMap)) {
         // Emit code for any incoming arguments. This must happen before
         // beginning FastISel on the entry block.
         if (LLVMBB == &Fn.getEntryBlock()) {
@@ -624,45 +630,51 @@
           CodeGenAndEmitDAG();
           SDL->clear();
         }
+        F->setCurrentBlock(BB);
         // Do FastISel on as many instructions as possible.
-        while (Begin != End) {
-          Begin = F->SelectInstructions(Begin, End, FuncInfo->ValueMap,
-                                        FuncInfo->MBBMap, BB);
+        for (; I != End; ++I) {
+          // Just before the terminator instruction, insert instructions to
+          // feed PHI nodes in successor blocks.
+          if (isa<TerminatorInst>(I))
+            if (!HandlePHINodesInSuccessorBlocksFast(LLVMBB, F)) {
+              if (DisableFastISelAbort)
+                break;
+#ifndef NDEBUG
+              I->dump();
+#endif  
+              assert(0 && "FastISel didn't handle a PHI in a successor");
+            }
 
-          // If the "fast" selector selected the entire block, we're done.
-          if (Begin == End)
-            break;
+          // First try normal tablegen-generated "fast" selection.
+          if (F->SelectInstruction(I))
+            continue;
 
           // Next, try calling the target to attempt to handle the instruction.
-          if (F->TargetSelectInstruction(Begin, FuncInfo->ValueMap,
-                                         FuncInfo->MBBMap, BB)) {
-            ++Begin;
+          if (F->TargetSelectInstruction(I))
             continue;
-          }
 
-          // Handle certain instructions as single-LLVM-Instruction blocks.
-          if (isa<CallInst>(Begin) || isa<LoadInst>(Begin) ||
-              isa<StoreInst>(Begin)) {
-            if (Begin->getType() != Type::VoidTy) {
-              unsigned &R = FuncInfo->ValueMap[Begin];
+          // Then handle certain instructions as single-LLVM-Instruction blocks.
+          if (isa<CallInst>(I) || isa<LoadInst>(I) ||
+              isa<StoreInst>(I)) {
+            if (I->getType() != Type::VoidTy) {
+              unsigned &R = FuncInfo->ValueMap[I];
               if (!R)
-                R = FuncInfo->CreateRegForValue(Begin);
+                R = FuncInfo->CreateRegForValue(I);
             }
 
-            SelectBasicBlock(LLVMBB, Begin, next(Begin));
-            ++Begin;
+            SelectBasicBlock(LLVMBB, I, next(I));
             continue;
           }
 
           if (!DisableFastISelAbort &&
               // For now, don't abort on non-conditional-branch terminators.
-              (!isa<TerminatorInst>(Begin) ||
-               (isa<BranchInst>(Begin) &&
-                cast<BranchInst>(Begin)->isUnconditional()))) {
+              (!isa<TerminatorInst>(I) ||
+               (isa<BranchInst>(I) &&
+                cast<BranchInst>(I)->isUnconditional()))) {
             // The "fast" selector couldn't handle something and bailed.
             // For the purpose of debugging, just abort.
 #ifndef NDEBUG
-            Begin->dump();
+            I->dump();
 #endif
             assert(0 && "FastISel didn't select the entire block");
           }
@@ -674,12 +686,9 @@
 
     // Run SelectionDAG instruction selection on the remainder of the block
     // not handled by FastISel. If FastISel is not run, this is the entire
-    // block. If FastISel is run and happens to handle all of the
-    // LLVM Instructions in the block, [Begin,End) will be an empty range,
-    // but we still need to run this so that
-    // HandlePHINodesInSuccessorBlocks is called and any resulting code
-    // is emitted.
-    SelectBasicBlock(LLVMBB, Begin, End);
+    // block.
+    if (I != End)
+      SelectBasicBlock(LLVMBB, I, End);
 
     FinishBasicBlock();
   }

Modified: llvm/trunk/lib/Target/X86/X86FastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86FastISel.cpp?rev=55746&r1=55745&r2=55746&view=diff

==============================================================================
--- llvm/trunk/lib/Target/X86/X86FastISel.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86FastISel.cpp Wed Sep  3 18:12:08 2008
@@ -30,34 +30,27 @@
   const X86Subtarget *Subtarget;
     
 public:
-  explicit X86FastISel(MachineFunction &mf) : FastISel(mf) {
+  explicit X86FastISel(MachineFunction &mf,
+                       DenseMap<const Value *, unsigned> &vm,
+                       DenseMap<const BasicBlock *, MachineBasicBlock *> &bm)
+    : FastISel(mf, vm, bm) {
     Subtarget = &TM.getSubtarget<X86Subtarget>();
   }
 
-  virtual bool
-    TargetSelectInstruction(Instruction *I,
-                            DenseMap<const Value *, unsigned> &ValueMap,
-                      DenseMap<const BasicBlock *, MachineBasicBlock *> &MBBMap,
-                            MachineBasicBlock *MBB);
+  virtual bool TargetSelectInstruction(Instruction *I);
 
 #include "X86GenFastISel.inc"
 
 private:
-  bool X86SelectConstAddr(Value *V,
-                          DenseMap<const Value *, unsigned> &ValueMap,
-                          MachineBasicBlock *MBB, unsigned &Op0);
-
-  bool X86SelectLoad(Instruction *I,
-                     DenseMap<const Value *, unsigned> &ValueMap,
-                     MachineBasicBlock *MBB);
+  bool X86SelectConstAddr(Value *V, unsigned &Op0);
+
+  bool X86SelectLoad(Instruction *I);
 };
 
 /// X86SelectConstAddr - Select and emit code to materialize constant address.
 /// 
 bool X86FastISel::X86SelectConstAddr(Value *V,
-                                    DenseMap<const Value *, unsigned> &ValueMap,
-                                    MachineBasicBlock *MBB,
-                                    unsigned &Op0) {
+                                     unsigned &Op0) {
   // FIXME: Only GlobalAddress for now.
   GlobalValue *GV = dyn_cast<GlobalValue>(V);
   if (!GV)
@@ -84,9 +77,7 @@
 
 /// X86SelectLoad - Select and emit code to implement load instructions.
 ///
-bool X86FastISel::X86SelectLoad(Instruction *I,
-                                DenseMap<const Value *, unsigned> &ValueMap,
-                                MachineBasicBlock *MBB)  {
+bool X86FastISel::X86SelectLoad(Instruction *I)  {
   MVT VT = MVT::getMVT(I->getType(), /*HandleUnknown=*/true);
   if (VT == MVT::Other || !VT.isSimple())
     // Unhandled type. Halt "fast" selection and bail.
@@ -102,10 +93,10 @@
     return false;
 
   Value *V = I->getOperand(0);
-  unsigned Op0 = getRegForValue(V, ValueMap);
+  unsigned Op0 = getRegForValue(V);
   if (Op0 == 0) {
     // Handle constant load address.
-    if (!isa<Constant>(V) || !X86SelectConstAddr(V, ValueMap, MBB, Op0))
+    if (!isa<Constant>(V) || !X86SelectConstAddr(V, Op0))
       // Unhandled operand. Halt "fast" selection and bail.
       return false;    
   }
@@ -164,27 +155,26 @@
   else
     AM.GV = cast<GlobalValue>(V);
   addFullAddress(BuildMI(MBB, TII.get(Opc), ResultReg), AM);
-  UpdateValueMap(I, ResultReg, ValueMap);
+  UpdateValueMap(I, ResultReg);
   return true;
 }
 
 
 bool
-X86FastISel::TargetSelectInstruction(Instruction *I,
-                                  DenseMap<const Value *, unsigned> &ValueMap,
-                      DenseMap<const BasicBlock *, MachineBasicBlock *> &MBBMap,
-                                  MachineBasicBlock *MBB)  {
+X86FastISel::TargetSelectInstruction(Instruction *I)  {
   switch (I->getOpcode()) {
   default: break;
   case Instruction::Load:
-    return X86SelectLoad(I, ValueMap, MBB);
+    return X86SelectLoad(I);
   }
 
   return false;
 }
 
 namespace llvm {
-  llvm::FastISel *X86::createFastISel(MachineFunction &mf) {
-    return new X86FastISel(mf);
+  llvm::FastISel *X86::createFastISel(MachineFunction &mf,
+                        DenseMap<const Value *, unsigned> &vm,
+                        DenseMap<const BasicBlock *, MachineBasicBlock *> &bm) {
+    return new X86FastISel(mf, vm, bm);
   }
 }

Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=55746&r1=55745&r2=55746&view=diff

==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Wed Sep  3 18:12:08 2008
@@ -1879,8 +1879,12 @@
   return false;
 }
 
-FastISel *X86TargetLowering::createFastISel(MachineFunction &mf) {
-  return X86::createFastISel(mf);
+FastISel *
+X86TargetLowering::createFastISel(MachineFunction &mf,
+                                  DenseMap<const Value *, unsigned> &vm,
+                                  DenseMap<const BasicBlock *,
+                                           MachineBasicBlock *> &bm) {
+  return X86::createFastISel(mf, vm, bm);
 }
 
 

Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.h?rev=55746&r1=55745&r2=55746&view=diff

==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.h (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.h Wed Sep  3 18:12:08 2008
@@ -470,7 +470,10 @@
 
     /// createFastISel - This method returns a target specific FastISel object,
     /// or null if the target does not support "fast" ISel.
-    virtual FastISel *createFastISel(MachineFunction &mf);
+    virtual FastISel *
+    createFastISel(MachineFunction &mf,
+                   DenseMap<const Value *, unsigned> &,
+                   DenseMap<const BasicBlock *, MachineBasicBlock *> &);
     
   private:
     /// Subtarget - Keep a pointer to the X86Subtarget around so that we can
@@ -598,7 +601,9 @@
   };
 
   namespace X86 {
-    FastISel *createFastISel(MachineFunction &mf);
+    FastISel *createFastISel(MachineFunction &mf,
+                           DenseMap<const Value *, unsigned> &,
+                           DenseMap<const BasicBlock *, MachineBasicBlock *> &);
   }
 }
 





More information about the llvm-commits mailing list