diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/include/llvm/CodeGen/FunctionLoweringInfo.h | 3 | ||||
| -rw-r--r-- | llvm/include/llvm/Target/TargetLowering.h | 23 | ||||
| -rw-r--r-- | llvm/include/llvm/Target/TargetRegisterInfo.h | 5 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 37 | 
4 files changed, 67 insertions, 1 deletions
diff --git a/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h b/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h index bd8da736c16..09a9991912d 100644 --- a/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/llvm/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -62,6 +62,9 @@ public:    /// registers.    bool CanLowerReturn; +  /// True if part of the CSRs will be handled via explicit copies. +  bool SplitCSR; +    /// DemoteRegister - if CanLowerReturn is false, DemoteRegister is a vreg    /// allocated to hold a pointer to the hidden sret parameter.    unsigned DemoteRegister; diff --git a/llvm/include/llvm/Target/TargetLowering.h b/llvm/include/llvm/Target/TargetLowering.h index f7152565f91..a105917958d 100644 --- a/llvm/include/llvm/Target/TargetLowering.h +++ b/llvm/include/llvm/Target/TargetLowering.h @@ -2263,6 +2263,29 @@ public:      return false;    } +  /// Return true if the target supports that a subset of CSRs for the given +  /// calling convention is handled explicitly via copies. +  virtual bool supportSplitCSR(CallingConv::ID CC) const { +    return false; +  } + +  /// Perform necessary initialization to handle a subset of CSRs explicitly +  /// via copies. This function is called at the beginning of instruction +  /// selection. +  virtual void initializeSplitCSR(MachineBasicBlock *Entry) const { +    llvm_unreachable("Not Implemented"); +  } + +  /// Insert explicit copies in entry and exit blocks. We copy a subset of +  /// CSRs to virtual registers in the entry block, and copy them back to +  /// physical registers in the exit blocks. This function is called at the end +  /// of instruction selection. +  virtual void insertCopiesSplitCSR( +      MachineBasicBlock *Entry, +      const SmallVectorImpl<MachineBasicBlock *> &Exits) const { +    llvm_unreachable("Not Implemented"); +  } +    //===--------------------------------------------------------------------===//    // Lowering methods - These methods must be implemented by targets so that    // the SelectionDAGBuilder code knows how to lower these. diff --git a/llvm/include/llvm/Target/TargetRegisterInfo.h b/llvm/include/llvm/Target/TargetRegisterInfo.h index 414255edb23..ffd510440b0 100644 --- a/llvm/include/llvm/Target/TargetRegisterInfo.h +++ b/llvm/include/llvm/Target/TargetRegisterInfo.h @@ -426,6 +426,11 @@ public:    virtual const MCPhysReg*    getCalleeSavedRegs(const MachineFunction *MF) const = 0; +  virtual const MCPhysReg* +  getCalleeSavedRegsViaCopy(const MachineFunction *MF) const { +    return nullptr; +  } +    /// Return a mask of call-preserved registers for the given calling convention    /// on the current function. The mask should include all call-preserved    /// aliases. This is used by the register allocator to determine which diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index f6c5d90f47a..5f3e4a02341 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -467,15 +467,50 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) {    MF->setHasInlineAsm(false); +  FuncInfo->SplitCSR = false; +  SmallVector<MachineBasicBlock*, 4> Returns; + +  // We split CSR if the target supports it for the given calling convention +  // and the function has only return exits. +  if (TLI->supportSplitCSR(Fn.getCallingConv())) { +    FuncInfo->SplitCSR = true; + +    // Collect all the return blocks. +    for (const BasicBlock &BB : Fn) { +      if (!succ_empty(&BB)) +        continue; + +      const TerminatorInst *Term = BB.getTerminator(); +      if (isa<UnreachableInst>(Term)) +        continue; +      if (isa<ReturnInst>(Term)) { +        Returns.push_back(FuncInfo->MBBMap[&BB]); +        continue; +      } + +      // Bail out if the exit block is not Return nor Unreachable. +      FuncInfo->SplitCSR = false; +      break; +    } +  } + +  MachineBasicBlock *EntryMBB = &MF->front(); +  if (FuncInfo->SplitCSR) +    // This performs initialization so lowering for SplitCSR will be correct. +    TLI->initializeSplitCSR(EntryMBB); +    SelectAllBasicBlocks(Fn);    // 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    // emitting the code for the block. -  MachineBasicBlock *EntryMBB = &MF->front();    const TargetRegisterInfo &TRI = *MF->getSubtarget().getRegisterInfo();    RegInfo->EmitLiveInCopies(EntryMBB, TRI, *TII); +  // Insert copies in the entry block and the return blocks. +  if (FuncInfo->SplitCSR) +    TLI->insertCopiesSplitCSR(EntryMBB, Returns); +    DenseMap<unsigned, unsigned> LiveInMap;    if (!FuncInfo->ArgDbgValues.empty())      for (MachineRegisterInfo::livein_iterator LI = RegInfo->livein_begin(),  | 

