diff options
Diffstat (limited to 'lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp')
| -rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 157 | 
1 files changed, 106 insertions, 51 deletions
| diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index bdf57e805842..18f6997ef83c 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -11,6 +11,7 @@  //  //===----------------------------------------------------------------------===// +#include "llvm/CodeGen/SelectionDAGISel.h"  #include "ScheduleDAGSDNodes.h"  #include "SelectionDAGBuilder.h"  #include "llvm/ADT/APInt.h" @@ -26,7 +27,7 @@  #include "llvm/Analysis/AliasAnalysis.h"  #include "llvm/Analysis/BranchProbabilityInfo.h"  #include "llvm/Analysis/CFG.h" -#include "llvm/Analysis/OptimizationDiagnosticInfo.h" +#include "llvm/Analysis/OptimizationRemarkEmitter.h"  #include "llvm/Analysis/TargetLibraryInfo.h"  #include "llvm/CodeGen/FastISel.h"  #include "llvm/CodeGen/FunctionLoweringInfo.h" @@ -45,9 +46,12 @@  #include "llvm/CodeGen/MachineValueType.h"  #include "llvm/CodeGen/SchedulerRegistry.h"  #include "llvm/CodeGen/SelectionDAG.h" -#include "llvm/CodeGen/SelectionDAGISel.h"  #include "llvm/CodeGen/SelectionDAGNodes.h"  #include "llvm/CodeGen/StackProtector.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/CodeGen/TargetLowering.h" +#include "llvm/CodeGen/TargetRegisterInfo.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h"  #include "llvm/CodeGen/ValueTypes.h"  #include "llvm/IR/BasicBlock.h"  #include "llvm/IR/Constants.h" @@ -80,13 +84,9 @@  #include "llvm/Support/KnownBits.h"  #include "llvm/Support/Timer.h"  #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetInstrInfo.h"  #include "llvm/Target/TargetIntrinsicInfo.h" -#include "llvm/Target/TargetLowering.h"  #include "llvm/Target/TargetMachine.h"  #include "llvm/Target/TargetOptions.h" -#include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/Target/TargetSubtargetInfo.h"  #include "llvm/Transforms/Utils/BasicBlockUtils.h"  #include <algorithm>  #include <cassert> @@ -212,7 +212,7 @@ namespace llvm {        IS.OptLevel = NewOptLevel;        IS.TM.setOptLevel(NewOptLevel);        DEBUG(dbgs() << "\nChanging optimization level for Function " -            << IS.MF->getFunction()->getName() << "\n"); +            << IS.MF->getFunction().getName() << "\n");        DEBUG(dbgs() << "\tBefore: -O" << SavedOptLevel              << " ; After: -O" << NewOptLevel << "\n");        SavedFastISel = IS.TM.Options.EnableFastISel; @@ -228,7 +228,7 @@ namespace llvm {        if (IS.OptLevel == SavedOptLevel)          return;        DEBUG(dbgs() << "\nRestoring optimization level for Function " -            << IS.MF->getFunction()->getName() << "\n"); +            << IS.MF->getFunction().getName() << "\n");        DEBUG(dbgs() << "\tBefore: -O" << IS.OptLevel              << " ; After: -O" << SavedOptLevel << "\n");        IS.OptLevel = SavedOptLevel; @@ -384,7 +384,7 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) {    assert((!EnableFastISelAbort || TM.Options.EnableFastISel) &&           "-fast-isel-abort > 0 requires -fast-isel"); -  const Function &Fn = *mf.getFunction(); +  const Function &Fn = mf.getFunction();    MF = &mf;    // Reset the target options before resetting the optimization @@ -414,7 +414,7 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) {    SplitCriticalSideEffectEdges(const_cast<Function &>(Fn), DT, LI); -  CurDAG->init(*MF, *ORE); +  CurDAG->init(*MF, *ORE, this);    FuncInfo->set(Fn, *MF, CurDAG);    // Now get the optional analyzes if we want to. @@ -494,10 +494,9 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) {    DenseMap<unsigned, unsigned> LiveInMap;    if (!FuncInfo->ArgDbgValues.empty()) -    for (MachineRegisterInfo::livein_iterator LI = RegInfo->livein_begin(), -           E = RegInfo->livein_end(); LI != E; ++LI) -      if (LI->second) -        LiveInMap.insert(std::make_pair(LI->first, LI->second)); +    for (std::pair<unsigned, unsigned> LI : RegInfo->liveins()) +      if (LI.second) +        LiveInMap.insert(LI);    // Insert DBG_VALUE instructions for function arguments to the entry block.    for (unsigned i = 0, e = FuncInfo->ArgDbgValues.size(); i != e; ++i) { @@ -529,12 +528,14 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) {        const MDNode *Expr = MI->getDebugExpression();        DebugLoc DL = MI->getDebugLoc();        bool IsIndirect = MI->isIndirectDebugValue(); -      unsigned Offset = IsIndirect ? MI->getOperand(1).getImm() : 0; +      if (IsIndirect) +        assert(MI->getOperand(1).getImm() == 0 && +               "DBG_VALUE with nonzero offset");        assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) &&               "Expected inlined-at fields to agree");        // Def is never a terminator here, so it is ok to increment InsertPos.        BuildMI(*EntryMBB, ++InsertPos, DL, TII->get(TargetOpcode::DBG_VALUE), -              IsIndirect, LDI->second, Offset, Variable, Expr); +              IsIndirect, LDI->second, Variable, Expr);        // If this vreg is directly copied into an exported register then        // that COPY instructions also need DBG_VALUE, if it is the only @@ -556,7 +557,7 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) {          // declared, rather than whatever is attached to CopyUseMI.          MachineInstr *NewMI =              BuildMI(*MF, DL, TII->get(TargetOpcode::DBG_VALUE), IsIndirect, -                    CopyUseMI->getOperand(0).getReg(), Offset, Variable, Expr); +                    CopyUseMI->getOperand(0).getReg(), Variable, Expr);          MachineBasicBlock::iterator Pos = CopyUseMI;          EntryMBB->insertAfter(Pos, NewMI);        } @@ -644,6 +645,9 @@ static void reportFastISelFailure(MachineFunction &MF,  void SelectionDAGISel::SelectBasicBlock(BasicBlock::const_iterator Begin,                                          BasicBlock::const_iterator End,                                          bool &HadTailCall) { +  // Allow creating illegal types during DAG building for the basic block. +  CurDAG->NewNodesMustHaveLegalTypes = false; +    // Lower the instructions. If a call is emitted as a tail call, cease emitting    // nodes for this block.    for (BasicBlock::const_iterator I = Begin; I != End && !SDB->HasTailCall; ++I) { @@ -726,8 +730,9 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {      BlockName =          (MF->getName() + ":" + FuncInfo->MBB->getBasicBlock()->getName()).str();    } -  DEBUG(dbgs() << "Initial selection DAG: BB#" << BlockNumber -        << " '" << BlockName << "'\n"; CurDAG->dump()); +  DEBUG(dbgs() << "Initial selection DAG: " << printMBBReference(*FuncInfo->MBB) +               << " '" << BlockName << "'\n"; +        CurDAG->dump());    if (ViewDAGCombine1 && MatchFilterBB)      CurDAG->viewGraph("dag-combine1 input for " + BlockName); @@ -739,8 +744,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {      CurDAG->Combine(BeforeLegalizeTypes, AA, OptLevel);    } -  DEBUG(dbgs() << "Optimized lowered selection DAG: BB#" << BlockNumber -        << " '" << BlockName << "'\n"; CurDAG->dump()); +  DEBUG(dbgs() << "Optimized lowered selection DAG: " +               << printMBBReference(*FuncInfo->MBB) << " '" << BlockName +               << "'\n"; +        CurDAG->dump());    // Second step, hack on the DAG until it only uses operations and types that    // the target supports. @@ -754,8 +761,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {      Changed = CurDAG->LegalizeTypes();    } -  DEBUG(dbgs() << "Type-legalized selection DAG: BB#" << BlockNumber -        << " '" << BlockName << "'\n"; CurDAG->dump()); +  DEBUG(dbgs() << "Type-legalized selection DAG: " +               << printMBBReference(*FuncInfo->MBB) << " '" << BlockName +               << "'\n"; +        CurDAG->dump());    // Only allow creation of legal node types.    CurDAG->NewNodesMustHaveLegalTypes = true; @@ -771,8 +780,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {        CurDAG->Combine(AfterLegalizeTypes, AA, OptLevel);      } -    DEBUG(dbgs() << "Optimized type-legalized selection DAG: BB#" << BlockNumber -          << " '" << BlockName << "'\n"; CurDAG->dump()); +    DEBUG(dbgs() << "Optimized type-legalized selection DAG: " +                 << printMBBReference(*FuncInfo->MBB) << " '" << BlockName +                 << "'\n"; +          CurDAG->dump());    }    { @@ -782,8 +793,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {    }    if (Changed) { -    DEBUG(dbgs() << "Vector-legalized selection DAG: BB#" << BlockNumber -          << " '" << BlockName << "'\n"; CurDAG->dump()); +    DEBUG(dbgs() << "Vector-legalized selection DAG: " +                 << printMBBReference(*FuncInfo->MBB) << " '" << BlockName +                 << "'\n"; +          CurDAG->dump());      {        NamedRegionTimer T("legalize_types2", "Type Legalization 2", GroupName, @@ -791,8 +804,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {        CurDAG->LegalizeTypes();      } -    DEBUG(dbgs() << "Vector/type-legalized selection DAG: BB#" << BlockNumber -          << " '" << BlockName << "'\n"; CurDAG->dump()); +    DEBUG(dbgs() << "Vector/type-legalized selection DAG: " +                 << printMBBReference(*FuncInfo->MBB) << " '" << BlockName +                 << "'\n"; +          CurDAG->dump());      if (ViewDAGCombineLT && MatchFilterBB)        CurDAG->viewGraph("dag-combine-lv input for " + BlockName); @@ -804,8 +819,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {        CurDAG->Combine(AfterLegalizeVectorOps, AA, OptLevel);      } -    DEBUG(dbgs() << "Optimized vector-legalized selection DAG: BB#" -          << BlockNumber << " '" << BlockName << "'\n"; CurDAG->dump()); +    DEBUG(dbgs() << "Optimized vector-legalized selection DAG: " +                 << printMBBReference(*FuncInfo->MBB) << " '" << BlockName +                 << "'\n"; +          CurDAG->dump());    }    if (ViewLegalizeDAGs && MatchFilterBB) @@ -817,8 +834,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {      CurDAG->Legalize();    } -  DEBUG(dbgs() << "Legalized selection DAG: BB#" << BlockNumber -        << " '" << BlockName << "'\n"; CurDAG->dump()); +  DEBUG(dbgs() << "Legalized selection DAG: " +               << printMBBReference(*FuncInfo->MBB) << " '" << BlockName +               << "'\n"; +        CurDAG->dump());    if (ViewDAGCombine2 && MatchFilterBB)      CurDAG->viewGraph("dag-combine2 input for " + BlockName); @@ -830,8 +849,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {      CurDAG->Combine(AfterLegalizeDAG, AA, OptLevel);    } -  DEBUG(dbgs() << "Optimized legalized selection DAG: BB#" << BlockNumber -        << " '" << BlockName << "'\n"; CurDAG->dump()); +  DEBUG(dbgs() << "Optimized legalized selection DAG: " +               << printMBBReference(*FuncInfo->MBB) << " '" << BlockName +               << "'\n"; +        CurDAG->dump());    if (OptLevel != CodeGenOpt::None)      ComputeLiveOutVRegInfo(); @@ -847,8 +868,10 @@ void SelectionDAGISel::CodeGenAndEmitDAG() {      DoInstructionSelection();    } -  DEBUG(dbgs() << "Selected selection DAG: BB#" << BlockNumber -        << " '" << BlockName << "'\n"; CurDAG->dump()); +  DEBUG(dbgs() << "Selected selection DAG: " +               << printMBBReference(*FuncInfo->MBB) << " '" << BlockName +               << "'\n"; +        CurDAG->dump());    if (ViewSchedDAGs && MatchFilterBB)      CurDAG->viewGraph("scheduler input for " + BlockName); @@ -915,9 +938,9 @@ public:  } // end anonymous namespace  void SelectionDAGISel::DoInstructionSelection() { -  DEBUG(dbgs() << "===== Instruction selection begins: BB#" -        << FuncInfo->MBB->getNumber() -        << " '" << FuncInfo->MBB->getName() << "'\n"); +  DEBUG(dbgs() << "===== Instruction selection begins: " +               << printMBBReference(*FuncInfo->MBB) << " '" +               << FuncInfo->MBB->getName() << "'\n");    PreprocessISelDAG(); @@ -1138,7 +1161,7 @@ static void processDbgDeclares(FunctionLoweringInfo *FuncInfo) {        // Look through casts and constant offset GEPs. These mostly come from        // inalloca. -      APInt Offset(DL.getPointerSizeInBits(0), 0); +      APInt Offset(DL.getTypeSizeInBits(Address->getType()), 0);        Address = Address->stripAndAccumulateInBoundsConstantOffsets(DL, Offset);        // Check if the variable is a static alloca or a byval or inalloca @@ -1177,12 +1200,7 @@ static void propagateSwiftErrorVRegs(FunctionLoweringInfo *FuncInfo) {    // For each machine basic block in reverse post order.    ReversePostOrderTraversal<MachineFunction *> RPOT(FuncInfo->MF); -  for (ReversePostOrderTraversal<MachineFunction *>::rpo_iterator -           It = RPOT.begin(), -           E = RPOT.end(); -       It != E; ++It) { -    MachineBasicBlock *MBB = *It; - +  for (MachineBasicBlock *MBB : RPOT) {      // For each swifterror value in the function.      for(const auto *SwiftErrorVal : FuncInfo->SwiftErrorVals) {        auto Key = std::make_pair(MBB, SwiftErrorVal); @@ -1253,6 +1271,8 @@ static void propagateSwiftErrorVRegs(FunctionLoweringInfo *FuncInfo) {        // If we don't need a phi create a copy to the upward exposed vreg.        if (!needPHI) {          assert(UpwardsUse); +        assert(!VRegs.empty() && +               "No predecessors?  Is the Calling Convention correct?");          unsigned DestReg = UUseVReg;          BuildMI(*MBB, MBB->getFirstNonPHI(), DLoc, TII->get(TargetOpcode::COPY),                  DestReg) @@ -1282,10 +1302,10 @@ static void propagateSwiftErrorVRegs(FunctionLoweringInfo *FuncInfo) {    }  } -void preassignSwiftErrorRegs(const TargetLowering *TLI, -                             FunctionLoweringInfo *FuncInfo, -                             BasicBlock::const_iterator Begin, -                             BasicBlock::const_iterator End) { +static void preassignSwiftErrorRegs(const TargetLowering *TLI, +                                    FunctionLoweringInfo *FuncInfo, +                                    BasicBlock::const_iterator Begin, +                                    BasicBlock::const_iterator End) {    if (!TLI->supportSwiftError() || FuncInfo->SwiftErrorVals.empty())      return; @@ -2774,6 +2794,12 @@ static unsigned IsPredicateKnownToFail(const unsigned char *Table,      Result = !::CheckType(Table, Index, N, SDISel.TLI,                            SDISel.CurDAG->getDataLayout());      return Index; +  case SelectionDAGISel::OPC_CheckTypeRes: { +    unsigned Res = Table[Index++]; +    Result = !::CheckType(Table, Index, N.getValue(Res), SDISel.TLI, +                          SDISel.CurDAG->getDataLayout()); +    return Index; +  }    case SelectionDAGISel::OPC_CheckChild0Type:    case SelectionDAGISel::OPC_CheckChild1Type:    case SelectionDAGISel::OPC_CheckChild2Type: @@ -2906,6 +2932,7 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,    case ISD::CopyFromReg:    case ISD::CopyToReg:    case ISD::EH_LABEL: +  case ISD::ANNOTATION_LABEL:    case ISD::LIFETIME_START:    case ISD::LIFETIME_END:      NodeToMatch->setNodeId(-1); // Mark selected. @@ -3175,6 +3202,14 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,          break;        continue; +    case OPC_CheckTypeRes: { +      unsigned Res = MatcherTable[MatcherIndex++]; +      if (!::CheckType(MatcherTable, MatcherIndex, N.getValue(Res), TLI, +                       CurDAG->getDataLayout())) +        break; +      continue; +    } +      case OPC_SwitchOpcode: {        unsigned CurNodeOpcode = N.getOpcode();        unsigned SwitchStart = MatcherIndex-1; (void)SwitchStart; @@ -3548,6 +3583,7 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,                 "NodeToMatch was removed partway through selection");          SelectionDAG::DAGNodeDeletedListener NDL(*CurDAG, [&](SDNode *N,                                                                SDNode *E) { +          CurDAG->salvageDebugInfo(*N);            auto &Chain = ChainNodesMatched;            assert((!E || !is_contained(Chain, N)) &&                   "Chain node replaced during MorphNode"); @@ -3725,6 +3761,25 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,    }  } +bool SelectionDAGISel::isOrEquivalentToAdd(const SDNode *N) const { +  assert(N->getOpcode() == ISD::OR && "Unexpected opcode"); +  auto *C = dyn_cast<ConstantSDNode>(N->getOperand(1)); +  if (!C) +    return false; + +  // Detect when "or" is used to add an offset to a stack object. +  if (auto *FN = dyn_cast<FrameIndexSDNode>(N->getOperand(0))) { +    MachineFrameInfo &MFI = MF->getFrameInfo(); +    unsigned A = MFI.getObjectAlignment(FN->getIndex()); +    assert(isPowerOf2_32(A) && "Unexpected alignment"); +    int32_t Off = C->getSExtValue(); +    // If the alleged offset fits in the zero bits guaranteed by +    // the alignment, then this or is really an add. +    return (Off >= 0) && (((A - 1) & Off) == unsigned(Off)); +  } +  return false; +} +  void SelectionDAGISel::CannotYetSelect(SDNode *N) {    std::string msg;    raw_string_ostream Msg(msg); | 
