FastISel support for exception-handling constructs.
authorDan Gohman <gohman@apple.com>
Tue, 14 Oct 2008 23:54:11 +0000 (23:54 +0000)
committerDan Gohman <gohman@apple.com>
Tue, 14 Oct 2008 23:54:11 +0000 (23:54 +0000)
 - Move the EH landing-pad code and adjust it so that it works
   with FastISel as well as with SDISel.
 - Add FastISel support for @llvm.eh.exception and
   @llvm.eh.selector.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@57539 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 8bf8827481ca24770f5fca8afa1a343cd1ab7136..71db9b580239433bbe720e944e7c27b05e39bc52 100644 (file)
 
 #include "llvm/BasicBlock.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallSet.h"
 #include "llvm/CodeGen/SelectionDAGNodes.h"
 
 namespace llvm {
 
 class AllocaInst;
 class ConstantFP;
+class Instruction;
 class MachineBasicBlock;
 class MachineConstantPool;
 class MachineFunction;
@@ -44,6 +46,9 @@ protected:
   DenseMap<const Value *, unsigned> &ValueMap;
   DenseMap<const BasicBlock *, MachineBasicBlock *> &MBBMap;
   DenseMap<const AllocaInst *, int> &StaticAllocaMap;
+#ifndef NDEBUG
+  SmallSet<Instruction*, 8> &CatchInfoLost;
+#endif
   MachineFunction &MF;
   MachineModuleInfo *MMI;
   MachineRegisterInfo &MRI;
@@ -108,7 +113,11 @@ protected:
            MachineModuleInfo *mmi,
            DenseMap<const Value *, unsigned> &vm,
            DenseMap<const BasicBlock *, MachineBasicBlock *> &bm,
-           DenseMap<const AllocaInst *, int> &am);
+           DenseMap<const AllocaInst *, int> &am
+#ifndef NDEBUG
+           , SmallSet<Instruction*, 8> &cil
+#endif
+           );
 
   /// FastEmit_r - This method is called by target-independent code
   /// to request that an instruction with the given type and opcode
index b091fc2ff978e69e0377bf781be160f36707ed98..d3e785b5fe739cb7aad1536ab41ba06e73c7161c 100644 (file)
@@ -30,6 +30,7 @@ namespace llvm {
   class MachineInstr;
   class MachineModuleInfo;
   class TargetLowering;
+  class TargetInstrInfo;
   class FunctionLoweringInfo;
   class HazardRecognizer;
   class GCFunctionInfo;
@@ -107,7 +108,8 @@ protected:
   
 private:
   void SelectAllBasicBlocks(Function &Fn, MachineFunction &MF,
-                            MachineModuleInfo *MMI);
+                            MachineModuleInfo *MMI,
+                            const TargetInstrInfo &TII);
   void FinishBasicBlock();
 
   void SelectBasicBlock(BasicBlock *LLVMBB,
index de45553c1a61559d8398ae35c082a47ac2e13158..c9ea40125f5ee24668c47e8aef5b76a480c88a12 100644 (file)
@@ -28,6 +28,7 @@
 #include "llvm/CodeGen/RuntimeLibcalls.h"
 #include "llvm/ADT/APFloat.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/STLExtras.h"
 #include <map>
 #include <vector>
@@ -1124,7 +1125,11 @@ public:
                  MachineModuleInfo *,
                  DenseMap<const Value *, unsigned> &,
                  DenseMap<const BasicBlock *, MachineBasicBlock *> &,
-                 DenseMap<const AllocaInst *, int> &) {
+                 DenseMap<const AllocaInst *, int> &
+#ifndef NDEBUG
+                 , SmallSet<Instruction*, 8> &CatchInfoLost
+#endif
+                 ) {
     return 0;
   }
 
index b12665b237aa67e088b5d2de54ed8bf26643b90a..404d613ac883371abda0eb8c21623f676724130d 100644 (file)
@@ -51,6 +51,7 @@
 #include "llvm/Target/TargetInstrInfo.h"
 #include "llvm/Target/TargetLowering.h"
 #include "llvm/Target/TargetMachine.h"
+#include "SelectionDAGBuild.h"
 using namespace llvm;
 
 unsigned FastISel::getRegForValue(Value *V) {
@@ -379,6 +380,66 @@ bool FastISel::SelectCall(User *I) {
     }
     return true;
   }
+  case Intrinsic::eh_exception: {
+    MVT VT = TLI.getValueType(I->getType());
+    switch (TLI.getOperationAction(ISD::EXCEPTIONADDR, VT)) {
+    default: break;
+    case TargetLowering::Expand: {
+      if (!MBB->isLandingPad()) {
+        // FIXME: Mark exception register as live in.  Hack for PR1508.
+        unsigned Reg = TLI.getExceptionAddressRegister();
+        if (Reg) MBB->addLiveIn(Reg);
+      }
+      unsigned Reg = TLI.getExceptionAddressRegister();
+      const TargetRegisterClass *RC = TLI.getRegClassFor(VT);
+      unsigned ResultReg = createResultReg(RC);
+      bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg,
+                                           Reg, RC, RC);
+      assert(InsertedCopy && "Can't copy address registers!");
+      UpdateValueMap(I, ResultReg);
+      return true;
+    }
+    }
+    break;
+  }
+  case Intrinsic::eh_selector_i32:
+  case Intrinsic::eh_selector_i64: {
+    MVT VT = TLI.getValueType(I->getType());
+    switch (TLI.getOperationAction(ISD::EHSELECTION, VT)) {
+    default: break;
+    case TargetLowering::Expand: {
+      MVT VT = (IID == Intrinsic::eh_selector_i32 ?
+                           MVT::i32 : MVT::i64);
+
+      if (MMI) {
+        if (MBB->isLandingPad())
+          AddCatchInfo(*cast<CallInst>(I), MMI, MBB);
+        else {
+#ifndef NDEBUG
+          CatchInfoLost.insert(cast<CallInst>(I));
+#endif
+          // FIXME: Mark exception selector register as live in.  Hack for PR1508.
+          unsigned Reg = TLI.getExceptionSelectorRegister();
+          if (Reg) MBB->addLiveIn(Reg);
+        }
+
+        unsigned Reg = TLI.getExceptionSelectorRegister();
+        const TargetRegisterClass *RC = TLI.getRegClassFor(VT);
+        unsigned ResultReg = createResultReg(RC);
+        bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg,
+                                             Reg, RC, RC);
+        assert(InsertedCopy && "Can't copy address registers!");
+        UpdateValueMap(I, ResultReg);
+      } else {
+        unsigned ResultReg =
+          getRegForValue(Constant::getNullValue(I->getType()));
+        UpdateValueMap(I, ResultReg);
+      }
+      return true;
+    }
+    }
+    break;
+  }
   }
   return false;
 }
@@ -607,11 +668,18 @@ FastISel::FastISel(MachineFunction &mf,
                    MachineModuleInfo *mmi,
                    DenseMap<const Value *, unsigned> &vm,
                    DenseMap<const BasicBlock *, MachineBasicBlock *> &bm,
-                   DenseMap<const AllocaInst *, int> &am)
+                   DenseMap<const AllocaInst *, int> &am
+#ifndef NDEBUG
+                   , SmallSet<Instruction*, 8> &cil
+#endif
+                   )
   : MBB(0),
     ValueMap(vm),
     MBBMap(bm),
     StaticAllocaMap(am),
+#ifndef NDEBUG
+    CatchInfoLost(cil),
+#endif
     MF(mf),
     MMI(mmi),
     MRI(MF.getRegInfo()),
index 6e9b2885a8fbcb74e8cae03f6efa63f3f62757ff..fb5619cc49ccaec8da3f14534096af857e8eb678 100644 (file)
@@ -314,7 +314,7 @@ bool SelectionDAGISel::runOnFunction(Function &Fn) {
       // Mark landing pad.
       FuncInfo->MBBMap[Invoke->getSuccessor(1)]->setIsLandingPad();
 
-  SelectAllBasicBlocks(Fn, MF, MMI);
+  SelectAllBasicBlocks(Fn, MF, MMI, TII);
 
   // If the first basic block in the function has live ins that need to be
   // copied into vregs, emit the copies into the top of the block before
@@ -452,48 +452,6 @@ void SelectionDAGISel::SelectBasicBlock(BasicBlock *LLVMBB,
                                         BasicBlock::iterator End) {
   SDL->setCurrentBasicBlock(BB);
 
-  MachineModuleInfo *MMI = CurDAG->getMachineModuleInfo();
-
-  if (MMI && BB->isLandingPad()) {
-    // Add a label to mark the beginning of the landing pad.  Deletion of the
-    // landing pad can thus be detected via the MachineModuleInfo.
-    unsigned LabelID = MMI->addLandingPad(BB);
-    CurDAG->setRoot(CurDAG->getLabel(ISD::EH_LABEL,
-                                     CurDAG->getEntryNode(), LabelID));
-
-    // Mark exception register as live in.
-    unsigned Reg = TLI.getExceptionAddressRegister();
-    if (Reg) BB->addLiveIn(Reg);
-
-    // Mark exception selector register as live in.
-    Reg = TLI.getExceptionSelectorRegister();
-    if (Reg) BB->addLiveIn(Reg);
-
-    // FIXME: Hack around an exception handling flaw (PR1508): the personality
-    // function and list of typeids logically belong to the invoke (or, if you
-    // like, the basic block containing the invoke), and need to be associated
-    // with it in the dwarf exception handling tables.  Currently however the
-    // information is provided by an intrinsic (eh.selector) that can be moved
-    // to unexpected places by the optimizers: if the unwind edge is critical,
-    // then breaking it can result in the intrinsics being in the successor of
-    // the landing pad, not the landing pad itself.  This results in exceptions
-    // not being caught because no typeids are associated with the invoke.
-    // This may not be the only way things can go wrong, but it is the only way
-    // we try to work around for the moment.
-    BranchInst *Br = dyn_cast<BranchInst>(LLVMBB->getTerminator());
-
-    if (Br && Br->isUnconditional()) { // Critical edge?
-      BasicBlock::iterator I, E;
-      for (I = LLVMBB->begin(), E = --LLVMBB->end(); I != E; ++I)
-        if (isa<EHSelectorInst>(I))
-          break;
-
-      if (I == E)
-        // No catch info found - try to extract some from the successor.
-        copyCatchInfo(Br->getSuccessor(0), LLVMBB, MMI, *FuncInfo);
-    }
-  }
-
   // Lower all of the non-terminator instructions.
   for (BasicBlock::iterator I = Begin; I != End; ++I)
     if (!isa<TerminatorInst>(I))
@@ -708,14 +666,19 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {
 }  
 
 void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF,
-                                            MachineModuleInfo *MMI) {
+                                            MachineModuleInfo *MMI,
+                                            const TargetInstrInfo &TII) {
   // Initialize the Fast-ISel state, if needed.
   FastISel *FastIS = 0;
   if (EnableFastISel)
     FastIS = TLI.createFastISel(*FuncInfo->MF, MMI,
                                 FuncInfo->ValueMap,
                                 FuncInfo->MBBMap,
-                                FuncInfo->StaticAllocaMap);
+                                FuncInfo->StaticAllocaMap
+#ifndef NDEBUG
+                                , FuncInfo->CatchInfoLost
+#endif
+                                );
 
   // Iterate over all basic blocks in the function.
   for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) {
@@ -746,9 +709,49 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF,
       }
     }
 
+    if (MMI && BB->isLandingPad()) {
+      // Add a label to mark the beginning of the landing pad.  Deletion of the
+      // landing pad can thus be detected via the MachineModuleInfo.
+      unsigned LabelID = MMI->addLandingPad(BB);
+
+      const TargetInstrDesc &II = TII.get(TargetInstrInfo::EH_LABEL);
+      BuildMI(BB, II).addImm(LabelID);
+
+      // Mark exception register as live in.
+      unsigned Reg = TLI.getExceptionAddressRegister();
+      if (Reg) BB->addLiveIn(Reg);
+
+      // Mark exception selector register as live in.
+      Reg = TLI.getExceptionSelectorRegister();
+      if (Reg) BB->addLiveIn(Reg);
+
+      // FIXME: Hack around an exception handling flaw (PR1508): the personality
+      // function and list of typeids logically belong to the invoke (or, if you
+      // like, the basic block containing the invoke), and need to be associated
+      // with it in the dwarf exception handling tables.  Currently however the
+      // information is provided by an intrinsic (eh.selector) that can be moved
+      // to unexpected places by the optimizers: if the unwind edge is critical,
+      // then breaking it can result in the intrinsics being in the successor of
+      // the landing pad, not the landing pad itself.  This results in exceptions
+      // not being caught because no typeids are associated with the invoke.
+      // This may not be the only way things can go wrong, but it is the only way
+      // we try to work around for the moment.
+      BranchInst *Br = dyn_cast<BranchInst>(LLVMBB->getTerminator());
+
+      if (Br && Br->isUnconditional()) { // Critical edge?
+        BasicBlock::iterator I, E;
+        for (I = LLVMBB->begin(), E = --LLVMBB->end(); I != E; ++I)
+          if (isa<EHSelectorInst>(I))
+            break;
+
+        if (I == E)
+          // No catch info found - try to extract some from the successor.
+          copyCatchInfo(Br->getSuccessor(0), LLVMBB, MMI, *FuncInfo);
+      }
+    }
+
     // Before doing SelectionDAG ISel, see if FastISel has been requested.
-    // FastISel doesn't support EH landing pads, which require special handling.
-    if (FastIS && !SuppressFastISel && !BB->isLandingPad()) {
+    if (FastIS && !SuppressFastISel) {
       // Emit code for any incoming arguments. This must happen before
       // beginning FastISel on the entry block.
       if (LLVMBB == &Fn.getEntryBlock()) {
index 2ce78eccef08b812e720fd1ebb6674926cfbbf81..d734db56c8a931855dfea007209f2519273cbdff 100644 (file)
@@ -52,8 +52,16 @@ public:
                        MachineModuleInfo *mmi,
                        DenseMap<const Value *, unsigned> &vm,
                        DenseMap<const BasicBlock *, MachineBasicBlock *> &bm,
-                       DenseMap<const AllocaInst *, int> &am)
-    : FastISel(mf, mmi, vm, bm, am) {
+                       DenseMap<const AllocaInst *, int> &am
+#ifndef NDEBUG
+                       , SmallSet<Instruction*, 8> &cil
+#endif
+                       )
+    : FastISel(mf, mmi, vm, bm, am
+#ifndef NDEBUG
+               , cil
+#endif
+               ) {
     Subtarget = &TM.getSubtarget<X86Subtarget>();
     StackPtr = Subtarget->is64Bit() ? X86::RSP : X86::ESP;
     X86ScalarSSEf64 = Subtarget->hasSSE2();
@@ -1391,7 +1399,15 @@ namespace llvm {
                         MachineModuleInfo *mmi,
                         DenseMap<const Value *, unsigned> &vm,
                         DenseMap<const BasicBlock *, MachineBasicBlock *> &bm,
-                        DenseMap<const AllocaInst *, int> &am) {
-    return new X86FastISel(mf, mmi, vm, bm, am);
+                        DenseMap<const AllocaInst *, int> &am
+#ifndef NDEBUG
+                        , SmallSet<Instruction*, 8> &cil
+#endif
+                        ) {
+    return new X86FastISel(mf, mmi, vm, bm, am
+#ifndef NDEBUG
+                           , cil
+#endif
+                           );
   }
 }
index 19b94dfe0959b580d0e0a1747a81ce8a358572df..1841de2dc874deacf78a1d8eb2d653aee321bbe4 100644 (file)
@@ -1884,9 +1884,16 @@ X86TargetLowering::createFastISel(MachineFunction &mf,
                                   DenseMap<const Value *, unsigned> &vm,
                                   DenseMap<const BasicBlock *,
                                            MachineBasicBlock *> &bm,
-                                  DenseMap<const AllocaInst *, int> &am) {
-                                         
-  return X86::createFastISel(mf, mmo, vm, bm, am);
+                                  DenseMap<const AllocaInst *, int> &am
+#ifndef NDEBUG
+                                  , SmallSet<Instruction*, 8> &cil
+#endif
+                                  ) {
+  return X86::createFastISel(mf, mmo, vm, bm, am
+#ifndef NDEBUG
+                             , cil
+#endif
+                             );
 }
 
 
index 56223d5eebd4e9eb3371a99c942ab360c3923329..b3d165432ff1dcbca3f5c7a20b2de503f70274b2 100644 (file)
@@ -493,7 +493,11 @@ namespace llvm {
                    MachineModuleInfo *mmi,
                    DenseMap<const Value *, unsigned> &,
                    DenseMap<const BasicBlock *, MachineBasicBlock *> &,
-                   DenseMap<const AllocaInst *, int> &);
+                   DenseMap<const AllocaInst *, int> &
+#ifndef NDEBUG
+                   , SmallSet<Instruction*, 8> &
+#endif
+                   );
     
   private:
     /// Subtarget - Keep a pointer to the X86Subtarget around so that we can
@@ -638,7 +642,11 @@ namespace llvm {
                            MachineModuleInfo *mmi,
                            DenseMap<const Value *, unsigned> &,
                            DenseMap<const BasicBlock *, MachineBasicBlock *> &,
-                           DenseMap<const AllocaInst *, int> &);
+                           DenseMap<const AllocaInst *, int> &
+#ifndef NDEBUG
+                           , SmallSet<Instruction*, 8> &
+#endif
+                           );
   }
 }