Ejemplo n.º 1
0
bool PPCCTRLoops::runOnMachineFunction(MachineFunction &MF) {
  DEBUG(dbgs() << "********* PPC CTR Loops *********\n");

  bool Changed = false;

  // get the loop information
  MLI = &getAnalysis<MachineLoopInfo>();
  // get the register information
  MRI = &MF.getRegInfo();
  // the target specific instructio info.
  TII = MF.getTarget().getInstrInfo();

  for (MachineLoopInfo::iterator I = MLI->begin(), E = MLI->end();
       I != E; ++I) {
    MachineLoop *L = *I;
    if (!L->getParentLoop()) {
      Changed |= convertToCTRLoop(L);
    }
  }

  return Changed;
}
Ejemplo n.º 2
0
void WebAssemblyFrameLowering::emitEpilogue(MachineFunction &MF,
                                            MachineBasicBlock &MBB) const {
  auto &MFI = MF.getFrameInfo();
  uint64_t StackSize = MFI.getStackSize();
  if (!needsSP(MF, MFI) || !needsSPWriteback(MF, MFI)) return;
  const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
  auto &MRI = MF.getRegInfo();
  auto InsertPt = MBB.getFirstTerminator();
  DebugLoc DL;

  if (InsertPt != MBB.end())
    DL = InsertPt->getDebugLoc();

  // Restore the stack pointer. If we had fixed-size locals, add the offset
  // subtracted in the prolog.
  unsigned SPReg = 0;
  MachineBasicBlock::iterator InsertAddr = InsertPt;
  if (hasBP(MF)) {
    auto FI = MF.getInfo<WebAssemblyFunctionInfo>();
    SPReg = FI->getBasePointerVreg();
  } else if (StackSize) {
    const TargetRegisterClass *PtrRC =
        MRI.getTargetRegisterInfo()->getPointerRegClass(MF);
    unsigned OffsetReg = MRI.createVirtualRegister(PtrRC);
    InsertAddr =
        BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), OffsetReg)
            .addImm(StackSize);
    // In the epilog we don't need to write the result back to the SP32 physreg
    // because it won't be used again. We can use a stackified register instead.
    SPReg = MRI.createVirtualRegister(PtrRC);
    BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::ADD_I32), SPReg)
        .addReg(hasFP(MF) ? WebAssembly::FP32 : WebAssembly::SP32)
        .addReg(OffsetReg);
  } else {
    SPReg = hasFP(MF) ? WebAssembly::FP32 : WebAssembly::SP32;
  }

  writeSPToMemory(SPReg, MF, MBB, InsertAddr, InsertPt, DL);
}
Ejemplo n.º 3
0
bool SIFixWWMLiveness::runOnMachineFunction(MachineFunction &MF) {
  bool Modified = false;

  // This doesn't actually need LiveIntervals, but we can preserve them.
  LIS = getAnalysisIfAvailable<LiveIntervals>();

  const SISubtarget &ST = MF.getSubtarget<SISubtarget>();
  const SIInstrInfo *TII = ST.getInstrInfo();

  TRI = &TII->getRegisterInfo();
  MRI = &MF.getRegInfo();

  for (MachineBasicBlock &MBB : MF) {
    for (MachineInstr &MI : MBB) {
      if (MI.getOpcode() == AMDGPU::EXIT_WWM) {
        Modified |= runOnWWMInstruction(MI);
      }
    }
  }

  return Modified;
}
Ejemplo n.º 4
0
bool HexagonGenPredicate::runOnMachineFunction(MachineFunction &MF) {
    TII = MF.getSubtarget<HexagonSubtarget>().getInstrInfo();
    TRI = MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
    MRI = &MF.getRegInfo();
    PredGPRs.clear();
    PUsers.clear();
    G2P.clear();

    bool Changed = false;
    collectPredicateGPR(MF);
    for (SetOfReg::iterator I = PredGPRs.begin(), E = PredGPRs.end(); I != E; ++I)
        processPredicateGPR(*I);

    bool Again;
    do {
        Again = false;
        VectOfInst Processed, Copy;

        typedef VectOfInst::iterator iterator;
        Copy = PUsers;
        for (iterator I = Copy.begin(), E = Copy.end(); I != E; ++I) {
            MachineInstr *MI = *I;
            bool Done = convertToPredForm(MI);
            if (Done) {
                Processed.insert(MI);
                Again = true;
            }
        }
        Changed |= Again;

        auto Done = [Processed] (MachineInstr *MI) -> bool {
            return Processed.count(MI);
        };
        PUsers.remove_if(Done);
    } while (Again);

    Changed |= eliminatePredCopies(MF);
    return Changed;
}
Ejemplo n.º 5
0
void MIRPrinter::print(const MachineFunction &MF) {
  initRegisterMaskIds(MF);

  yaml::MachineFunction YamlMF;
  YamlMF.Name = MF.getName();
  YamlMF.Alignment = MF.getAlignment();
  YamlMF.ExposesReturnsTwice = MF.exposesReturnsTwice();

  YamlMF.Legalized = MF.getProperties().hasProperty(
      MachineFunctionProperties::Property::Legalized);
  YamlMF.RegBankSelected = MF.getProperties().hasProperty(
      MachineFunctionProperties::Property::RegBankSelected);
  YamlMF.Selected = MF.getProperties().hasProperty(
      MachineFunctionProperties::Property::Selected);

  convert(YamlMF, MF.getRegInfo(), MF.getSubtarget().getRegisterInfo());
  ModuleSlotTracker MST(MF.getFunction()->getParent());
  MST.incorporateFunction(*MF.getFunction());
  convert(MST, YamlMF.FrameInfo, MF.getFrameInfo());
  convertStackObjects(YamlMF, MF, MST);
  if (const auto *ConstantPool = MF.getConstantPool())
    convert(YamlMF, *ConstantPool);
  if (const auto *JumpTableInfo = MF.getJumpTableInfo())
    convert(MST, YamlMF.JumpTableInfo, *JumpTableInfo);
  raw_string_ostream StrOS(YamlMF.Body.Value.Value);
  bool IsNewlineNeeded = false;
  for (const auto &MBB : MF) {
    if (IsNewlineNeeded)
      StrOS << "\n";
    MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping)
        .print(MBB);
    IsNewlineNeeded = true;
  }
  StrOS.flush();
  yaml::Output Out(OS);
  if (!SimplifyMIR)
      Out.setWriteDefaultValues(true);
  Out << YamlMF;
}
Ejemplo n.º 6
0
bool llvm::PHIElimination::runOnMachineFunction(MachineFunction &MF) {
  MRI = &MF.getRegInfo();

  bool Changed = false;

  // Split critical edges to help the coalescer
  if (LiveVariables *LV = getAnalysisIfAvailable<LiveVariables>()) {
    MachineLoopInfo *MLI = getAnalysisIfAvailable<MachineLoopInfo>();
    for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
      Changed |= SplitPHIEdges(MF, *I, *LV, MLI);
  }

  // Populate VRegPHIUseCount
  analyzePHINodes(MF);

  // Eliminate PHI instructions by inserting copies into predecessor blocks.
  for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
    Changed |= EliminatePHINodes(MF, *I);

  // Remove dead IMPLICIT_DEF instructions.
  for (SmallPtrSet<MachineInstr*, 4>::iterator I = ImpDefs.begin(),
         E = ImpDefs.end(); I != E; ++I) {
    MachineInstr *DefMI = *I;
    unsigned DefReg = DefMI->getOperand(0).getReg();
    if (MRI->use_nodbg_empty(DefReg))
      DefMI->eraseFromParent();
  }

  // Clean up the lowered PHI instructions.
  for (LoweredPHIMap::iterator I = LoweredPHIs.begin(), E = LoweredPHIs.end();
       I != E; ++I)
    MF.DeleteMachineInstr(I->first);

  LoweredPHIs.clear();
  ImpDefs.clear();
  VRegPHIUseCount.clear();

  return Changed;
}
Ejemplo n.º 7
0
bool IRTranslator::runOnMachineFunction(MachineFunction &MF) {
  const Function &F = *MF.getFunction();
  if (F.empty())
    return false;
  CLI = MF.getSubtarget().getCallLowering();
  MIRBuilder.setMF(MF);
  MRI = &MF.getRegInfo();
  // Setup the arguments.
  MachineBasicBlock &MBB = getOrCreateBB(F.front());
  MIRBuilder.setMBB(MBB);
  SmallVector<unsigned, 8> VRegArgs;
  for (const Argument &Arg: F.args())
    VRegArgs.push_back(getOrCreateVReg(Arg));
  bool Succeeded =
      CLI->lowerFormalArguments(MIRBuilder, F.getArgumentList(), VRegArgs);
  if (!Succeeded)
    report_fatal_error("Unable to lower arguments");

  for (const BasicBlock &BB: F) {
    MachineBasicBlock &MBB = getOrCreateBB(BB);
    // Set the insertion point of all the following translations to
    // the end of this basic block.
    MIRBuilder.setMBB(MBB);
    for (const Instruction &Inst: BB) {
      bool Succeeded = translate(Inst);
      if (!Succeeded) {
        DEBUG(dbgs() << "Cannot translate: " << Inst << '\n');
        report_fatal_error("Unable to translate instruction");
      }
    }
  }

  // Now that the MachineFrameInfo has been configured, no further changes to
  // the reserved registers are possible.
  MRI->freezeReservedRegs(MF);

  return false;
}
Ejemplo n.º 8
0
bool X86CallFrameOptimization::runOnMachineFunction(MachineFunction &MF) {
  STI = &MF.getSubtarget<X86Subtarget>();
  TII = STI->getInstrInfo();
  TFL = STI->getFrameLowering();
  MRI = &MF.getRegInfo();

  const X86RegisterInfo &RegInfo =
      *static_cast<const X86RegisterInfo *>(STI->getRegisterInfo());
  SlotSize = RegInfo.getSlotSize();
  assert(isPowerOf2_32(SlotSize) && "Expect power of 2 stack slot size");
  Log2SlotSize = Log2_32(SlotSize);

  if (!isLegal(MF))
    return false;

  unsigned FrameSetupOpcode = TII->getCallFrameSetupOpcode();

  bool Changed = false;

  ContextVector CallSeqVector;

  for (auto &MBB : MF)
    for (auto &MI : MBB)
      if (MI.getOpcode() == FrameSetupOpcode) {
        CallContext Context;
        collectCallInfo(MF, MBB, MI, Context);
        CallSeqVector.push_back(Context);
      }

  if (!isProfitable(MF, CallSeqVector))
    return false;

  for (auto CC : CallSeqVector)
    if (CC.UsePush)
      Changed |= adjustCallSequence(MF, CC);

  return Changed;
}
Ejemplo n.º 9
0
bool HexagonEarlyIfConversion::runOnMachineFunction(MachineFunction &MF) {
  if (skipFunction(*MF.getFunction()))
    return false;

  auto &ST = MF.getSubtarget<HexagonSubtarget>();
  HII = ST.getInstrInfo();
  TRI = ST.getRegisterInfo();
  MFN = &MF;
  MRI = &MF.getRegInfo();
  MDT = &getAnalysis<MachineDominatorTree>();
  MLI = &getAnalysis<MachineLoopInfo>();
  MBPI = EnableHexagonBP ? &getAnalysis<MachineBranchProbabilityInfo>() :
    nullptr;

  Deleted.clear();
  bool Changed = false;

  for (MachineLoopInfo::iterator I = MLI->begin(), E = MLI->end(); I != E; ++I)
    Changed |= visitLoop(*I);
  Changed |= visitLoop(nullptr);

  return Changed;
}
Ejemplo n.º 10
0
static void writeSPToMemory(unsigned SrcReg, MachineFunction &MF,
                            MachineBasicBlock &MBB,
                            MachineBasicBlock::iterator &InsertAddr,
                            MachineBasicBlock::iterator &InsertStore,
                            DebugLoc DL) {
  auto *SPSymbol = MF.createExternalSymbolName("__stack_pointer");
  unsigned SPAddr =
      MF.getRegInfo().createVirtualRegister(&WebAssembly::I32RegClass);
  const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();

  BuildMI(MBB, InsertAddr, DL, TII->get(WebAssembly::CONST_I32), SPAddr)
      .addExternalSymbol(SPSymbol);
  auto *MMO = new MachineMemOperand(MachinePointerInfo(),
                                    MachineMemOperand::MOStore, 4, 4);
  BuildMI(MBB, InsertStore, DL, TII->get(WebAssembly::STORE_I32),
          SrcReg)
      .addImm(0)
      .addReg(SPAddr)
      .addImm(2)  // p2align
      .addReg(SrcReg)
      .addMemOperand(MMO);
  MF.getInfo<WebAssemblyFunctionInfo>()->stackifyVReg(SPAddr);
}
Ejemplo n.º 11
0
bool ARMBaseRegisterInfo::canRealignStack(const MachineFunction &MF) const {
  const MachineRegisterInfo *MRI = &MF.getRegInfo();
  const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
  // We can't realign the stack if:
  // 1. Dynamic stack realignment is explicitly disabled,
  // 2. This is a Thumb1 function (it's not useful, so we don't bother), or
  // 3. There are VLAs in the function and the base pointer is disabled.
  if (!MF.getTarget().Options.RealignStack)
    return false;
  if (AFI->isThumb1OnlyFunction())
    return false;
  // Stack realignment requires a frame pointer.  If we already started
  // register allocation with frame pointer elimination, it is too late now.
  if (!MRI->canReserveReg(FramePtr))
    return false;
  // We may also need a base pointer if there are dynamic allocas or stack
  // pointer adjustments around calls.
  if (MF.getTarget().getFrameLowering()->hasReservedCallFrame(MF))
    return true;
  // A base pointer is required and allowed.  Check that it isn't too late to
  // reserve it.
  return MRI->canReserveReg(BasePtr);
}
Ejemplo n.º 12
0
bool SILoadStoreOptimizer::runOnMachineFunction(MachineFunction &MF) {
  if (skipFunction(*MF.getFunction()))
    return false;

  const SISubtarget &STM = MF.getSubtarget<SISubtarget>();
  if (!STM.loadStoreOptEnabled())
    return false;

  TII = STM.getInstrInfo();
  TRI = &TII->getRegisterInfo();

  MRI = &MF.getRegInfo();
  AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();

  DEBUG(dbgs() << "Running SILoadStoreOptimizer\n");

  bool Modified = false;

  for (MachineBasicBlock &MBB : MF)
    Modified |= optimizeBlock(MBB);

  return Modified;
}
Ejemplo n.º 13
0
bool SIFixSGPRLiveRanges::runOnMachineFunction(MachineFunction &MF) {
  MachineRegisterInfo &MRI = MF.getRegInfo();
  const SIRegisterInfo *TRI = static_cast<const SIRegisterInfo *>(
      MF.getTarget().getRegisterInfo());
  LiveIntervals *LIS = &getAnalysis<LiveIntervals>();

  for (MachineFunction::iterator BI = MF.begin(), BE = MF.end();
                                                  BI != BE; ++BI) {

    MachineBasicBlock &MBB = *BI;
    for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
                                                      I != E; ++I) {
      MachineInstr &MI = *I;
      MachineOperand *ExecUse = MI.findRegisterUseOperand(AMDGPU::EXEC);
      if (ExecUse)
        continue;

      for (const MachineOperand &Def : MI.operands()) {
        if (!Def.isReg() || !Def.isDef() ||!TargetRegisterInfo::isVirtualRegister(Def.getReg()))
          continue;

        const TargetRegisterClass *RC = MRI.getRegClass(Def.getReg());

        if (!TRI->isSGPRClass(RC))
          continue;
        LiveInterval &LI = LIS->getInterval(Def.getReg());
        for (unsigned i = 0, e = LI.size() - 1; i != e; ++i) {
          LiveRange::Segment &Seg = LI.segments[i];
          LiveRange::Segment &Next = LI.segments[i + 1];
          Seg.end = Next.start;
        }
      }
    }
  }

  return false;
}
Ejemplo n.º 14
0
bool A15SDOptimizer::runOnMachineFunction(MachineFunction &Fn) {
  if (skipFunction(*Fn.getFunction()))
    return false;

  const ARMSubtarget &STI = Fn.getSubtarget<ARMSubtarget>();
  // Since the A15SDOptimizer pass can insert VDUP instructions, it can only be
  // enabled when NEON is available.
  if (!(STI.isCortexA15() && STI.hasNEON()))
    return false;
  TII = STI.getInstrInfo();
  TRI = STI.getRegisterInfo();
  MRI = &Fn.getRegInfo();
  bool Modified = false;

  DEBUG(dbgs() << "Running on function " << Fn.getName()<< "\n");

  DeadInstr.clear();
  Replacements.clear();

  for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
       ++MFI) {

    for (MachineBasicBlock::iterator MI = MFI->begin(), ME = MFI->end();
      MI != ME;) {
      Modified |= runOnInstruction(MI++);
    }

  }

  for (std::set<MachineInstr *>::iterator I = DeadInstr.begin(),
                                            E = DeadInstr.end();
                                            I != E; ++I) {
    (*I)->eraseFromParent();
  }

  return Modified;
}
Ejemplo n.º 15
0
// FIXME: Insert waits listed in Table 4.2 "Required User-Inserted Wait States"
// around other non-memory instructions.
bool SIInsertWaits::runOnMachineFunction(MachineFunction &MF) {
    bool Changes = false;

    TII = static_cast<const SIInstrInfo *>(MF.getSubtarget().getInstrInfo());
    TRI =
        static_cast<const SIRegisterInfo *>(MF.getSubtarget().getRegisterInfo());

    MRI = &MF.getRegInfo();

    WaitedOn = ZeroCounts;
    LastIssued = ZeroCounts;
    LastOpcodeType = OTHER;

    memset(&UsedRegs, 0, sizeof(UsedRegs));
    memset(&DefinedRegs, 0, sizeof(DefinedRegs));

    for (MachineFunction::iterator BI = MF.begin(), BE = MF.end();
            BI != BE; ++BI) {

        MachineBasicBlock &MBB = *BI;
        for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
                I != E; ++I) {

            // Wait for everything before a barrier.
            if (I->getOpcode() == AMDGPU::S_BARRIER)
                Changes |= insertWait(MBB, I, LastIssued);
            else
                Changes |= insertWait(MBB, I, handleOperands(*I));
            pushInstruction(MBB, I);
        }

        // Wait for everything at the end of the MBB
        Changes |= insertWait(MBB, MBB.getFirstTerminator(), LastIssued);
    }

    return Changes;
}
Ejemplo n.º 16
0
bool WebAssemblyPeephole::runOnMachineFunction(MachineFunction &MF) {
  bool Changed = false;

  MachineRegisterInfo &MRI = MF.getRegInfo();
  WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();

  for (auto &MBB : MF)
    for (auto &MI : MBB)
      switch (MI.getOpcode()) {
      default:
        break;
      case WebAssembly::STORE8_I32:
      case WebAssembly::STORE16_I32:
      case WebAssembly::STORE8_I64:
      case WebAssembly::STORE16_I64:
      case WebAssembly::STORE32_I64:
      case WebAssembly::STORE_F32:
      case WebAssembly::STORE_F64:
      case WebAssembly::STORE_I32:
      case WebAssembly::STORE_I64: {
        // Store instructions return their value operand. If we ended up using
        // the same register for both, replace it with a dead def so that it
        // can use $discard instead.
        MachineOperand &MO = MI.getOperand(0);
        unsigned OldReg = MO.getReg();
        if (OldReg == MI.getOperand(2).getReg()) {
          unsigned NewReg = MRI.createVirtualRegister(MRI.getRegClass(OldReg));
          MO.setReg(NewReg);
          MO.setIsDead();
          MFI.stackifyVReg(NewReg);
          MFI.addWAReg(NewReg, WebAssemblyFunctionInfo::UnusedReg);
        }
      }
      }

  return Changed;
}
Ejemplo n.º 17
0
void
ARMBaseRegisterInfo::updateRegAllocHint(unsigned Reg, unsigned NewReg,
                                        MachineFunction &MF) const {
  MachineRegisterInfo *MRI = &MF.getRegInfo();
  std::pair<unsigned, unsigned> Hint = MRI->getRegAllocationHint(Reg);
  if ((Hint.first == (unsigned)ARMRI::RegPairOdd ||
       Hint.first == (unsigned)ARMRI::RegPairEven) &&
      TargetRegisterInfo::isVirtualRegister(Hint.second)) {
    // If 'Reg' is one of the even / odd register pair and it's now changed
    // (e.g. coalesced) into a different register. The other register of the
    // pair allocation hint must be updated to reflect the relationship
    // change.
    unsigned OtherReg = Hint.second;
    Hint = MRI->getRegAllocationHint(OtherReg);
    // Make sure the pair has not already divorced.
    if (Hint.second == Reg) {
      MRI->setRegAllocationHint(OtherReg, Hint.first, NewReg);
      if (TargetRegisterInfo::isVirtualRegister(NewReg))
        MRI->setRegAllocationHint(NewReg,
            Hint.first == (unsigned)ARMRI::RegPairOdd ? ARMRI::RegPairEven
            : ARMRI::RegPairOdd, OtherReg);
    }
  }
}
Ejemplo n.º 18
0
void MipsFrameLowering::
processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
                                     RegScavenger *RS) const {
  MachineRegisterInfo& MRI = MF.getRegInfo();
  unsigned RA = STI.isABI_N64() ? Mips::RA_64 : Mips::RA;
  unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP;

  // FIXME: remove this code if register allocator can correctly mark
  //        $fp and $ra used or unused.

  // Mark $fp and $ra as used or unused.
  if (hasFP(MF))
    MRI.setPhysRegUsed(FP);

  // The register allocator might determine $ra is used after seeing 
  // instruction "jr $ra", but we do not want PrologEpilogInserter to insert
  // instructions to save/restore $ra unless there is a function call.
  // To correct this, $ra is explicitly marked unused if there is no
  // function call.
  if (MF.getFrameInfo()->hasCalls())
    MRI.setPhysRegUsed(RA);
  else
    MRI.setPhysRegUnused(RA);
}
Ejemplo n.º 19
0
void SIRegisterInfo::materializeFrameBaseRegister(MachineBasicBlock *MBB,
                                                  unsigned BaseReg,
                                                  int FrameIdx,
                                                  int64_t Offset) const {
  MachineBasicBlock::iterator Ins = MBB->begin();
  DebugLoc DL; // Defaults to "unknown"

  if (Ins != MBB->end())
    DL = Ins->getDebugLoc();

  MachineFunction *MF = MBB->getParent();
  const SISubtarget &Subtarget = MF->getSubtarget<SISubtarget>();
  const SIInstrInfo *TII = Subtarget.getInstrInfo();

  if (Offset == 0) {
    BuildMI(*MBB, Ins, DL, TII->get(AMDGPU::V_MOV_B32_e32), BaseReg)
      .addFrameIndex(FrameIdx);
    return;
  }

  MachineRegisterInfo &MRI = MF->getRegInfo();
  unsigned UnusedCarry = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
  unsigned OffsetReg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);

  unsigned FIReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);

  BuildMI(*MBB, Ins, DL, TII->get(AMDGPU::S_MOV_B32), OffsetReg)
    .addImm(Offset);
  BuildMI(*MBB, Ins, DL, TII->get(AMDGPU::V_MOV_B32_e32), FIReg)
    .addFrameIndex(FrameIdx);

  BuildMI(*MBB, Ins, DL, TII->get(AMDGPU::V_ADD_I32_e64), BaseReg)
    .addReg(UnusedCarry, RegState::Define | RegState::Dead)
    .addReg(OffsetReg, RegState::Kill)
    .addReg(FIReg);
}
Ejemplo n.º 20
0
bool VirtRegMap::runOnMachineFunction(MachineFunction &mf) {
  MRI = &mf.getRegInfo();
  TII = mf.getTarget().getInstrInfo();
  TRI = mf.getTarget().getRegisterInfo();
  MF = &mf;

  ReMatId = MAX_STACK_SLOT+1;
  LowSpillSlot = HighSpillSlot = NO_STACK_SLOT;
  
  Virt2PhysMap.clear();
  Virt2StackSlotMap.clear();
  Virt2ReMatIdMap.clear();
  Virt2SplitMap.clear();
  Virt2SplitKillMap.clear();
  ReMatMap.clear();
  ImplicitDefed.clear();
  SpillSlotToUsesMap.clear();
  MI2VirtMap.clear();
  SpillPt2VirtMap.clear();
  RestorePt2VirtMap.clear();
  EmergencySpillMap.clear();
  EmergencySpillSlots.clear();
  
  SpillSlotToUsesMap.resize(8);
  ImplicitDefed.resize(MF->getRegInfo().getNumVirtRegs());

  allocatableRCRegs.clear();
  for (TargetRegisterInfo::regclass_iterator I = TRI->regclass_begin(),
         E = TRI->regclass_end(); I != E; ++I)
    allocatableRCRegs.insert(std::make_pair(*I,
                                            TRI->getAllocatableSet(mf, *I)));

  grow();
  
  return false;
}
Ejemplo n.º 21
0
bool AArch64ConditionOptimizer::runOnMachineFunction(MachineFunction &MF) {
  DEBUG(dbgs() << "********** AArch64 Conditional Compares **********\n"
               << "********** Function: " << MF.getName() << '\n');
  TII = MF.getSubtarget().getInstrInfo();
  DomTree = &getAnalysis<MachineDominatorTree>();
  MRI = &MF.getRegInfo();

  bool Changed = false;

  // Visit blocks in dominator tree pre-order. The pre-order enables multiple
  // cmp-conversions from the same head block.
  // Note that updateDomTree() modifies the children of the DomTree node
  // currently being visited. The df_iterator supports that; it doesn't look at
  // child_begin() / child_end() until after a node has been visited.
  for (MachineDomTreeNode *I : depth_first(DomTree)) {
    MachineBasicBlock *HBB = I->getBlock();

    SmallVector<MachineOperand, 4> HeadCond;
    MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
    if (TII->AnalyzeBranch(*HBB, TBB, FBB, HeadCond)) {
      continue;
    }

    // Equivalence check is to skip loops.
    if (!TBB || TBB == HBB) {
      continue;
    }

    SmallVector<MachineOperand, 4> TrueCond;
    MachineBasicBlock *TBB_TBB = nullptr, *TBB_FBB = nullptr;
    if (TII->AnalyzeBranch(*TBB, TBB_TBB, TBB_FBB, TrueCond)) {
      continue;
    }

    MachineInstr *HeadCmpMI = findSuitableCompare(HBB);
    if (!HeadCmpMI) {
      continue;
    }

    MachineInstr *TrueCmpMI = findSuitableCompare(TBB);
    if (!TrueCmpMI) {
      continue;
    }

    AArch64CC::CondCode HeadCmp;
    if (HeadCond.empty() || !parseCond(HeadCond, HeadCmp)) {
      continue;
    }

    AArch64CC::CondCode TrueCmp;
    if (TrueCond.empty() || !parseCond(TrueCond, TrueCmp)) {
      continue;
    }

    const int HeadImm = (int)HeadCmpMI->getOperand(2).getImm();
    const int TrueImm = (int)TrueCmpMI->getOperand(2).getImm();

    DEBUG(dbgs() << "Head branch:\n");
    DEBUG(dbgs() << "\tcondition: "
          << AArch64CC::getCondCodeName(HeadCmp) << '\n');
    DEBUG(dbgs() << "\timmediate: " << HeadImm << '\n');

    DEBUG(dbgs() << "True branch:\n");
    DEBUG(dbgs() << "\tcondition: "
          << AArch64CC::getCondCodeName(TrueCmp) << '\n');
    DEBUG(dbgs() << "\timmediate: " << TrueImm << '\n');

    if (((HeadCmp == AArch64CC::GT && TrueCmp == AArch64CC::LT) ||
         (HeadCmp == AArch64CC::LT && TrueCmp == AArch64CC::GT)) &&
        std::abs(TrueImm - HeadImm) == 2) {
      // This branch transforms machine instructions that correspond to
      //
      // 1) (a > {TrueImm} && ...) || (a < {HeadImm} && ...)
      // 2) (a < {TrueImm} && ...) || (a > {HeadImm} && ...)
      //
      // into
      //
      // 1) (a >= {NewImm} && ...) || (a <= {NewImm} && ...)
      // 2) (a <= {NewImm} && ...) || (a >= {NewImm} && ...)

      CmpInfo HeadCmpInfo = adjustCmp(HeadCmpMI, HeadCmp);
      CmpInfo TrueCmpInfo = adjustCmp(TrueCmpMI, TrueCmp);
      if (std::get<0>(HeadCmpInfo) == std::get<0>(TrueCmpInfo) &&
          std::get<1>(HeadCmpInfo) == std::get<1>(TrueCmpInfo)) {
        modifyCmp(HeadCmpMI, HeadCmpInfo);
        modifyCmp(TrueCmpMI, TrueCmpInfo);
        Changed = true;
      }
    } else if (((HeadCmp == AArch64CC::GT && TrueCmp == AArch64CC::GT) ||
                (HeadCmp == AArch64CC::LT && TrueCmp == AArch64CC::LT)) &&
                std::abs(TrueImm - HeadImm) == 1) {
      // This branch transforms machine instructions that correspond to
      //
      // 1) (a > {TrueImm} && ...) || (a > {HeadImm} && ...)
      // 2) (a < {TrueImm} && ...) || (a < {HeadImm} && ...)
      //
      // into
      //
      // 1) (a <= {NewImm} && ...) || (a >  {NewImm} && ...)
      // 2) (a <  {NewImm} && ...) || (a >= {NewImm} && ...)

      // GT -> GE transformation increases immediate value, so picking the
      // smaller one; LT -> LE decreases immediate value so invert the choice.
      bool adjustHeadCond = (HeadImm < TrueImm);
      if (HeadCmp == AArch64CC::LT) {
          adjustHeadCond = !adjustHeadCond;
      }

      if (adjustHeadCond) {
        Changed |= adjustTo(HeadCmpMI, HeadCmp, TrueCmpMI, TrueImm);
      } else {
        Changed |= adjustTo(TrueCmpMI, TrueCmp, HeadCmpMI, HeadImm);
      }
    }
    // Other transformation cases almost never occur due to generation of < or >
    // comparisons instead of <= and >=.
  }

  return Changed;
}
Ejemplo n.º 22
0
MachineBasicBlock*
MSP430TargetLowering::EmitShiftInstr(MachineInstr *MI,
                                     MachineBasicBlock *BB) const {
  MachineFunction *F = BB->getParent();
  MachineRegisterInfo &RI = F->getRegInfo();
  DebugLoc dl = MI->getDebugLoc();
  const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo();

  unsigned Opc;
  const TargetRegisterClass * RC;
  switch (MI->getOpcode()) {
  default:
    assert(0 && "Invalid shift opcode!");
  case MSP430::Shl8:
   Opc = MSP430::SHL8r1;
   RC = MSP430::GR8RegisterClass;
   break;
  case MSP430::Shl16:
   Opc = MSP430::SHL16r1;
   RC = MSP430::GR16RegisterClass;
   break;
  case MSP430::Sra8:
   Opc = MSP430::SAR8r1;
   RC = MSP430::GR8RegisterClass;
   break;
  case MSP430::Sra16:
   Opc = MSP430::SAR16r1;
   RC = MSP430::GR16RegisterClass;
   break;
  case MSP430::Srl8:
   Opc = MSP430::SAR8r1c;
   RC = MSP430::GR8RegisterClass;
   break;
  case MSP430::Srl16:
   Opc = MSP430::SAR16r1c;
   RC = MSP430::GR16RegisterClass;
   break;
  }

  const BasicBlock *LLVM_BB = BB->getBasicBlock();
  MachineFunction::iterator I = BB;
  ++I;

  // Create loop block
  MachineBasicBlock *LoopBB = F->CreateMachineBasicBlock(LLVM_BB);
  MachineBasicBlock *RemBB  = F->CreateMachineBasicBlock(LLVM_BB);

  F->insert(I, LoopBB);
  F->insert(I, RemBB);

  // Update machine-CFG edges by transferring all successors of the current
  // block to the block containing instructions after shift.
  RemBB->splice(RemBB->begin(), BB,
                llvm::next(MachineBasicBlock::iterator(MI)),
                BB->end());
  RemBB->transferSuccessorsAndUpdatePHIs(BB);

  // Add adges BB => LoopBB => RemBB, BB => RemBB, LoopBB => LoopBB
  BB->addSuccessor(LoopBB);
  BB->addSuccessor(RemBB);
  LoopBB->addSuccessor(RemBB);
  LoopBB->addSuccessor(LoopBB);

  unsigned ShiftAmtReg = RI.createVirtualRegister(MSP430::GR8RegisterClass);
  unsigned ShiftAmtReg2 = RI.createVirtualRegister(MSP430::GR8RegisterClass);
  unsigned ShiftReg = RI.createVirtualRegister(RC);
  unsigned ShiftReg2 = RI.createVirtualRegister(RC);
  unsigned ShiftAmtSrcReg = MI->getOperand(2).getReg();
  unsigned SrcReg = MI->getOperand(1).getReg();
  unsigned DstReg = MI->getOperand(0).getReg();

  // BB:
  // cmp 0, N
  // je RemBB
  BuildMI(BB, dl, TII.get(MSP430::CMP8ri))
    .addReg(ShiftAmtSrcReg).addImm(0);
  BuildMI(BB, dl, TII.get(MSP430::JCC))
    .addMBB(RemBB)
    .addImm(MSP430CC::COND_E);

  // LoopBB:
  // ShiftReg = phi [%SrcReg, BB], [%ShiftReg2, LoopBB]
  // ShiftAmt = phi [%N, BB],      [%ShiftAmt2, LoopBB]
  // ShiftReg2 = shift ShiftReg
  // ShiftAmt2 = ShiftAmt - 1;
  BuildMI(LoopBB, dl, TII.get(MSP430::PHI), ShiftReg)
    .addReg(SrcReg).addMBB(BB)
    .addReg(ShiftReg2).addMBB(LoopBB);
  BuildMI(LoopBB, dl, TII.get(MSP430::PHI), ShiftAmtReg)
    .addReg(ShiftAmtSrcReg).addMBB(BB)
    .addReg(ShiftAmtReg2).addMBB(LoopBB);
  BuildMI(LoopBB, dl, TII.get(Opc), ShiftReg2)
    .addReg(ShiftReg);
  BuildMI(LoopBB, dl, TII.get(MSP430::SUB8ri), ShiftAmtReg2)
    .addReg(ShiftAmtReg).addImm(1);
  BuildMI(LoopBB, dl, TII.get(MSP430::JCC))
    .addMBB(LoopBB)
    .addImm(MSP430CC::COND_NE);

  // RemBB:
  // DestReg = phi [%SrcReg, BB], [%ShiftReg, LoopBB]
  BuildMI(*RemBB, RemBB->begin(), dl, TII.get(MSP430::PHI), DstReg)
    .addReg(SrcReg).addMBB(BB)
    .addReg(ShiftReg2).addMBB(LoopBB);

  MI->eraseFromParent();   // The pseudo instruction is gone now.
  return RemBB;
}
Ejemplo n.º 23
0
static void assignCalleeSavedSpillSlots(MachineFunction &F,
                                        const BitVector &SavedRegs,
                                        unsigned &MinCSFrameIndex,
                                        unsigned &MaxCSFrameIndex) {
  if (SavedRegs.empty())
    return;

  const TargetRegisterInfo *RegInfo = F.getSubtarget().getRegisterInfo();
  const MCPhysReg *CSRegs = F.getRegInfo().getCalleeSavedRegs();

  std::vector<CalleeSavedInfo> CSI;
  for (unsigned i = 0; CSRegs[i]; ++i) {
    unsigned Reg = CSRegs[i];
    if (SavedRegs.test(Reg))
      CSI.push_back(CalleeSavedInfo(Reg));
  }

  const TargetFrameLowering *TFI = F.getSubtarget().getFrameLowering();
  MachineFrameInfo &MFI = F.getFrameInfo();
  if (!TFI->assignCalleeSavedSpillSlots(F, RegInfo, CSI)) {
    // If target doesn't implement this, use generic code.

    if (CSI.empty())
      return; // Early exit if no callee saved registers are modified!

    unsigned NumFixedSpillSlots;
    const TargetFrameLowering::SpillSlot *FixedSpillSlots =
        TFI->getCalleeSavedSpillSlots(NumFixedSpillSlots);

    // Now that we know which registers need to be saved and restored, allocate
    // stack slots for them.
    for (auto &CS : CSI) {
      unsigned Reg = CS.getReg();
      const TargetRegisterClass *RC = RegInfo->getMinimalPhysRegClass(Reg);

      int FrameIdx;
      if (RegInfo->hasReservedSpillSlot(F, Reg, FrameIdx)) {
        CS.setFrameIdx(FrameIdx);
        continue;
      }

      // Check to see if this physreg must be spilled to a particular stack slot
      // on this target.
      const TargetFrameLowering::SpillSlot *FixedSlot = FixedSpillSlots;
      while (FixedSlot != FixedSpillSlots + NumFixedSpillSlots &&
             FixedSlot->Reg != Reg)
        ++FixedSlot;

      unsigned Size = RegInfo->getSpillSize(*RC);
      if (FixedSlot == FixedSpillSlots + NumFixedSpillSlots) {
        // Nope, just spill it anywhere convenient.
        unsigned Align = RegInfo->getSpillAlignment(*RC);
        unsigned StackAlign = TFI->getStackAlignment();

        // We may not be able to satisfy the desired alignment specification of
        // the TargetRegisterClass if the stack alignment is smaller. Use the
        // min.
        Align = std::min(Align, StackAlign);
        FrameIdx = MFI.CreateStackObject(Size, Align, true);
        if ((unsigned)FrameIdx < MinCSFrameIndex) MinCSFrameIndex = FrameIdx;
        if ((unsigned)FrameIdx > MaxCSFrameIndex) MaxCSFrameIndex = FrameIdx;
      } else {
        // Spill it to the stack where we must.
        FrameIdx = MFI.CreateFixedSpillStackObject(Size, FixedSlot->Offset);
      }

      CS.setFrameIdx(FrameIdx);
    }
  }

  MFI.setCalleeSavedInfo(CSI);
}
Ejemplo n.º 24
0
/// runOnMachineFunction - Insert prolog/epilog code and replace abstract
/// frame indexes with appropriate references.
///
bool PEI::runOnMachineFunction(MachineFunction &Fn) {
  if (!SpillCalleeSavedRegisters) {
    const TargetMachine &TM = Fn.getTarget();
    if (!TM.usesPhysRegsForPEI()) {
      SpillCalleeSavedRegisters = [](MachineFunction &, RegScavenger *,
                                     unsigned &, unsigned &, const MBBVector &,
                                     const MBBVector &) {};
      ScavengeFrameVirtualRegs = [](MachineFunction &, RegScavenger &) {};
    } else {
      SpillCalleeSavedRegisters = doSpillCalleeSavedRegs;
      ScavengeFrameVirtualRegs = scavengeFrameVirtualRegs;
      UsesCalleeSaves = true;
    }
  }

  const Function* F = Fn.getFunction();
  const TargetRegisterInfo *TRI = Fn.getSubtarget().getRegisterInfo();
  const TargetFrameLowering *TFI = Fn.getSubtarget().getFrameLowering();

  RS = TRI->requiresRegisterScavenging(Fn) ? new RegScavenger() : nullptr;
  FrameIndexVirtualScavenging = TRI->requiresFrameIndexScavenging(Fn);
  FrameIndexEliminationScavenging = (RS && !FrameIndexVirtualScavenging) ||
    TRI->requiresFrameIndexReplacementScavenging(Fn);
  ORE = &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE();

  // Calculate the MaxCallFrameSize and AdjustsStack variables for the
  // function's frame information. Also eliminates call frame pseudo
  // instructions.
  calculateCallFrameInfo(Fn);

  // Determine placement of CSR spill/restore code and prolog/epilog code:
  // place all spills in the entry block, all restores in return blocks.
  calculateSaveRestoreBlocks(Fn);

  // Handle CSR spilling and restoring, for targets that need it.
  SpillCalleeSavedRegisters(Fn, RS, MinCSFrameIndex, MaxCSFrameIndex,
                            SaveBlocks, RestoreBlocks);

  // Allow the target machine to make final modifications to the function
  // before the frame layout is finalized.
  TFI->processFunctionBeforeFrameFinalized(Fn, RS);

  // Calculate actual frame offsets for all abstract stack objects...
  calculateFrameObjectOffsets(Fn);

  // Add prolog and epilog code to the function.  This function is required
  // to align the stack frame as necessary for any stack variables or
  // called functions.  Because of this, calculateCalleeSavedRegisters()
  // must be called before this function in order to set the AdjustsStack
  // and MaxCallFrameSize variables.
  if (!F->hasFnAttribute(Attribute::Naked))
    insertPrologEpilogCode(Fn);

  // Replace all MO_FrameIndex operands with physical register references
  // and actual offsets.
  //
  replaceFrameIndices(Fn);

  // If register scavenging is needed, as we've enabled doing it as a
  // post-pass, scavenge the virtual registers that frame index elimination
  // inserted.
  if (TRI->requiresRegisterScavenging(Fn) && FrameIndexVirtualScavenging) {
      ScavengeFrameVirtualRegs(Fn, *RS);

      // Clear any vregs created by virtual scavenging.
      Fn.getRegInfo().clearVirtRegs();
  }

  // Warn on stack size when we exceeds the given limit.
  MachineFrameInfo &MFI = Fn.getFrameInfo();
  uint64_t StackSize = MFI.getStackSize();
  if (WarnStackSize.getNumOccurrences() > 0 && WarnStackSize < StackSize) {
    DiagnosticInfoStackSize DiagStackSize(*F, StackSize);
    F->getContext().diagnose(DiagStackSize);
  }

  delete RS;
  SaveBlocks.clear();
  RestoreBlocks.clear();
  MFI.setSavePoint(nullptr);
  MFI.setRestorePoint(nullptr);
  return true;
}
Ejemplo n.º 25
0
void MipsSEDAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) {
  MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();

  if (!MipsFI->globalBaseRegSet())
    return;

  MachineBasicBlock &MBB = MF.front();
  MachineBasicBlock::iterator I = MBB.begin();
  MachineRegisterInfo &RegInfo = MF.getRegInfo();
  const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
  DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
  unsigned V0, V1, GlobalBaseReg = MipsFI->getGlobalBaseReg();
  const TargetRegisterClass *RC;

  if (Subtarget.isABI_N64())
    RC = (const TargetRegisterClass*)&Mips::GPR64RegClass;
  else
    RC = (const TargetRegisterClass*)&Mips::GPR32RegClass;

  V0 = RegInfo.createVirtualRegister(RC);
  V1 = RegInfo.createVirtualRegister(RC);

  if (Subtarget.isABI_N64()) {
    MF.getRegInfo().addLiveIn(Mips::T9_64);
    MBB.addLiveIn(Mips::T9_64);

    // lui $v0, %hi(%neg(%gp_rel(fname)))
    // daddu $v1, $v0, $t9
    // daddiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname)))
    const GlobalValue *FName = MF.getFunction();
    BuildMI(MBB, I, DL, TII.get(Mips::LUi64), V0)
      .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI);
    BuildMI(MBB, I, DL, TII.get(Mips::DADDu), V1).addReg(V0)
      .addReg(Mips::T9_64);
    BuildMI(MBB, I, DL, TII.get(Mips::DADDiu), GlobalBaseReg).addReg(V1)
      .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO);
    return;
  }

  if (MF.getTarget().getRelocationModel() == Reloc::Static) {
    // Set global register to __gnu_local_gp.
    //
    // lui   $v0, %hi(__gnu_local_gp)
    // addiu $globalbasereg, $v0, %lo(__gnu_local_gp)
    BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0)
      .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_HI);
    BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V0)
      .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_LO);
    return;
  }

  MF.getRegInfo().addLiveIn(Mips::T9);
  MBB.addLiveIn(Mips::T9);

  if (Subtarget.isABI_N32()) {
    // lui $v0, %hi(%neg(%gp_rel(fname)))
    // addu $v1, $v0, $t9
    // addiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname)))
    const GlobalValue *FName = MF.getFunction();
    BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0)
      .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI);
    BuildMI(MBB, I, DL, TII.get(Mips::ADDu), V1).addReg(V0).addReg(Mips::T9);
    BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V1)
      .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO);
    return;
  }

  assert(Subtarget.isABI_O32());

  // For O32 ABI, the following instruction sequence is emitted to initialize
  // the global base register:
  //
  //  0. lui   $2, %hi(_gp_disp)
  //  1. addiu $2, $2, %lo(_gp_disp)
  //  2. addu  $globalbasereg, $2, $t9
  //
  // We emit only the last instruction here.
  //
  // GNU linker requires that the first two instructions appear at the beginning
  // of a function and no instructions be inserted before or between them.
  // The two instructions are emitted during lowering to MC layer in order to
  // avoid any reordering.
  //
  // Register $2 (Mips::V0) is added to the list of live-in registers to ensure
  // the value instruction 1 (addiu) defines is valid when instruction 2 (addu)
  // reads it.
  MF.getRegInfo().addLiveIn(Mips::V0);
  MBB.addLiveIn(Mips::V0);
  BuildMI(MBB, I, DL, TII.get(Mips::ADDu), GlobalBaseReg)
    .addReg(Mips::V0).addReg(Mips::T9);
}
Ejemplo n.º 26
0
bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) {
  auto It = Functions.find(MF.getName());
  if (It == Functions.end())
    return error(Twine("no machine function information for function '") +
                 MF.getName() + "' in the MIR file");
  // TODO: Recreate the machine function.
  const yaml::MachineFunction &YamlMF = *It->getValue();
  if (YamlMF.Alignment)
    MF.setAlignment(YamlMF.Alignment);
  MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice);
  MF.setHasInlineAsm(YamlMF.HasInlineAsm);
  if (YamlMF.AllVRegsAllocated)
    MF.getProperties().set(MachineFunctionProperties::Property::AllVRegsAllocated);
  PerFunctionMIParsingState PFS(MF, SM, IRSlots);
  if (initializeRegisterInfo(PFS, YamlMF))
    return true;
  if (!YamlMF.Constants.empty()) {
    auto *ConstantPool = MF.getConstantPool();
    assert(ConstantPool && "Constant pool must be created");
    if (initializeConstantPool(PFS, *ConstantPool, YamlMF))
      return true;
  }

  StringRef BlockStr = YamlMF.Body.Value.Value;
  SMDiagnostic Error;
  SourceMgr BlockSM;
  BlockSM.AddNewSourceBuffer(
      MemoryBuffer::getMemBuffer(BlockStr, "",/*RequiresNullTerminator=*/false),
      SMLoc());
  PFS.SM = &BlockSM;
  if (parseMachineBasicBlockDefinitions(PFS, BlockStr, Error)) {
    reportDiagnostic(
        diagFromBlockStringDiag(Error, YamlMF.Body.Value.SourceRange));
    return true;
  }
  PFS.SM = &SM;

  if (MF.empty())
    return error(Twine("machine function '") + Twine(MF.getName()) +
                 "' requires at least one machine basic block in its body");
  // Initialize the frame information after creating all the MBBs so that the
  // MBB references in the frame information can be resolved.
  if (initializeFrameInfo(PFS, YamlMF))
    return true;
  // Initialize the jump table after creating all the MBBs so that the MBB
  // references can be resolved.
  if (!YamlMF.JumpTableInfo.Entries.empty() &&
      initializeJumpTableInfo(PFS, YamlMF.JumpTableInfo))
    return true;
  // Parse the machine instructions after creating all of the MBBs so that the
  // parser can resolve the MBB references.
  StringRef InsnStr = YamlMF.Body.Value.Value;
  SourceMgr InsnSM;
  InsnSM.AddNewSourceBuffer(
      MemoryBuffer::getMemBuffer(InsnStr, "", /*RequiresNullTerminator=*/false),
      SMLoc());
  PFS.SM = &InsnSM;
  if (parseMachineInstructions(PFS, InsnStr, Error)) {
    reportDiagnostic(
        diagFromBlockStringDiag(Error, YamlMF.Body.Value.SourceRange));
    return true;
  }
  PFS.SM = &SM;

  inferRegisterInfo(PFS, YamlMF);
  // FIXME: This is a temporary workaround until the reserved registers can be
  // serialized.
  MF.getRegInfo().freezeReservedRegs(MF);
  MF.verify();
  return false;
}
bool AMDGPUInstructionSelector::selectSMRD(MachineInstr &I,
                                           ArrayRef<GEPInfo> AddrInfo) const {

  if (!I.hasOneMemOperand())
    return false;

  if ((*I.memoperands_begin())->getAddrSpace() != AMDGPUAS::CONSTANT_ADDRESS &&
      (*I.memoperands_begin())->getAddrSpace() != AMDGPUAS::CONSTANT_ADDRESS_32BIT)
    return false;

  if (!isInstrUniform(I))
    return false;

  if (hasVgprParts(AddrInfo))
    return false;

  MachineBasicBlock *BB = I.getParent();
  MachineFunction *MF = BB->getParent();
  const GCNSubtarget &Subtarget = MF->getSubtarget<GCNSubtarget>();
  MachineRegisterInfo &MRI = MF->getRegInfo();
  unsigned DstReg = I.getOperand(0).getReg();
  const DebugLoc &DL = I.getDebugLoc();
  unsigned Opcode;
  unsigned LoadSize = RBI.getSizeInBits(DstReg, MRI, TRI);

  if (!AddrInfo.empty() && AddrInfo[0].SgprParts.size() == 1) {

    const GEPInfo &GEPInfo = AddrInfo[0];

    unsigned PtrReg = GEPInfo.SgprParts[0];
    int64_t EncodedImm = AMDGPU::getSMRDEncodedOffset(Subtarget, GEPInfo.Imm);
    if (AMDGPU::isLegalSMRDImmOffset(Subtarget, GEPInfo.Imm)) {
      Opcode = getSmrdOpcode(AMDGPU::S_LOAD_DWORD_IMM, LoadSize);

      MachineInstr *SMRD = BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg)
                                 .addReg(PtrReg)
                                 .addImm(EncodedImm)
                                 .addImm(0); // glc
      return constrainSelectedInstRegOperands(*SMRD, TII, TRI, RBI);
    }

    if (Subtarget.getGeneration() == AMDGPUSubtarget::SEA_ISLANDS &&
        isUInt<32>(EncodedImm)) {
      Opcode = getSmrdOpcode(AMDGPU::S_LOAD_DWORD_IMM_ci, LoadSize);
      MachineInstr *SMRD = BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg)
                                   .addReg(PtrReg)
                                   .addImm(EncodedImm)
                                   .addImm(0); // glc
      return constrainSelectedInstRegOperands(*SMRD, TII, TRI, RBI);
    }

    if (isUInt<32>(GEPInfo.Imm)) {
      Opcode = getSmrdOpcode(AMDGPU::S_LOAD_DWORD_SGPR, LoadSize);
      unsigned OffsetReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
      BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_MOV_B32), OffsetReg)
              .addImm(GEPInfo.Imm);

      MachineInstr *SMRD = BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg)
                                   .addReg(PtrReg)
                                   .addReg(OffsetReg)
                                   .addImm(0); // glc
      return constrainSelectedInstRegOperands(*SMRD, TII, TRI, RBI);
    }
  }

  unsigned PtrReg = I.getOperand(1).getReg();
  Opcode = getSmrdOpcode(AMDGPU::S_LOAD_DWORD_IMM, LoadSize);
  MachineInstr *SMRD = BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg)
                               .addReg(PtrReg)
                               .addImm(0)
                               .addImm(0); // glc
  return constrainSelectedInstRegOperands(*SMRD, TII, TRI, RBI);
}
bool AMDGPUInstructionSelector::selectG_CONSTANT(MachineInstr &I) const {
  MachineBasicBlock *BB = I.getParent();
  MachineFunction *MF = BB->getParent();
  MachineRegisterInfo &MRI = MF->getRegInfo();
  MachineOperand &ImmOp = I.getOperand(1);

  // The AMDGPU backend only supports Imm operands and not CImm or FPImm.
  if (ImmOp.isFPImm()) {
    const APInt &Imm = ImmOp.getFPImm()->getValueAPF().bitcastToAPInt();
    ImmOp.ChangeToImmediate(Imm.getZExtValue());
  } else if (ImmOp.isCImm()) {
    ImmOp.ChangeToImmediate(ImmOp.getCImm()->getZExtValue());
  }

  unsigned DstReg = I.getOperand(0).getReg();
  unsigned Size;
  bool IsSgpr;
  const RegisterBank *RB = MRI.getRegBankOrNull(I.getOperand(0).getReg());
  if (RB) {
    IsSgpr = RB->getID() == AMDGPU::SGPRRegBankID;
    Size = MRI.getType(DstReg).getSizeInBits();
  } else {
    const TargetRegisterClass *RC = TRI.getRegClassForReg(MRI, DstReg);
    IsSgpr = TRI.isSGPRClass(RC);
    Size = TRI.getRegSizeInBits(*RC);
  }

  if (Size != 32 && Size != 64)
    return false;

  unsigned Opcode = IsSgpr ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
  if (Size == 32) {
    I.setDesc(TII.get(Opcode));
    I.addImplicitDefUseOperands(*MF);
    return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
  }

  DebugLoc DL = I.getDebugLoc();
  const TargetRegisterClass *RC = IsSgpr ? &AMDGPU::SReg_32_XM0RegClass :
                                           &AMDGPU::VGPR_32RegClass;
  unsigned LoReg = MRI.createVirtualRegister(RC);
  unsigned HiReg = MRI.createVirtualRegister(RC);
  const APInt &Imm = APInt(Size, I.getOperand(1).getImm());

  BuildMI(*BB, &I, DL, TII.get(Opcode), LoReg)
          .addImm(Imm.trunc(32).getZExtValue());

  BuildMI(*BB, &I, DL, TII.get(Opcode), HiReg)
          .addImm(Imm.ashr(32).getZExtValue());

  const MachineInstr *RS =
      BuildMI(*BB, &I, DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
              .addReg(LoReg)
              .addImm(AMDGPU::sub0)
              .addReg(HiReg)
              .addImm(AMDGPU::sub1);

  // We can't call constrainSelectedInstRegOperands here, because it doesn't
  // work for target independent opcodes
  I.eraseFromParent();
  const TargetRegisterClass *DstRC =
      TRI.getConstrainedRegClassForOperand(RS->getOperand(0), MRI);
  if (!DstRC)
    return true;
  return RBI.constrainGenericRegister(DstReg, *DstRC, MRI);
}
Ejemplo n.º 29
0
LegalizerHelper::LegalizerHelper(MachineFunction &MF)
    : MRI(MF.getRegInfo()), LI(*MF.getSubtarget().getLegalizerInfo()) {
  MIRBuilder.setMF(MF);
}
Ejemplo n.º 30
0
/// calculateCalleeSavedRegisters - Scan the function for modified callee saved
/// registers.
void PEI::calculateCalleeSavedRegisters(MachineFunction &Fn) {
  const TargetRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo();
  const TargetFrameLowering *TFI = Fn.getTarget().getFrameLowering();
  MachineFrameInfo *MFI = Fn.getFrameInfo();

  // Get the callee saved register list...
  const unsigned *CSRegs = RegInfo->getCalleeSavedRegs(&Fn);

  // These are used to keep track the callee-save area. Initialize them.
  MinCSFrameIndex = INT_MAX;
  MaxCSFrameIndex = 0;

  // Early exit for targets which have no callee saved registers.
  if (CSRegs == 0 || CSRegs[0] == 0)
    return;

  // In Naked functions we aren't going to save any registers.
  if (Fn.getFunction()->hasFnAttr(Attribute::Naked))
    return;

  std::vector<CalleeSavedInfo> CSI;
  for (unsigned i = 0; CSRegs[i]; ++i) {
    unsigned Reg = CSRegs[i];
    if (Fn.getRegInfo().isPhysRegUsed(Reg)) {
      // If the reg is modified, save it!
      CSI.push_back(CalleeSavedInfo(Reg));
    } else {
      for (const unsigned *AliasSet = RegInfo->getAliasSet(Reg);
           *AliasSet; ++AliasSet) {  // Check alias registers too.
        if (Fn.getRegInfo().isPhysRegUsed(*AliasSet)) {
          CSI.push_back(CalleeSavedInfo(Reg));
          break;
        }
      }
    }
  }

  if (CSI.empty())
    return;   // Early exit if no callee saved registers are modified!

  unsigned NumFixedSpillSlots;
  const TargetFrameLowering::SpillSlot *FixedSpillSlots =
    TFI->getCalleeSavedSpillSlots(NumFixedSpillSlots);

  // Now that we know which registers need to be saved and restored, allocate
  // stack slots for them.
  for (std::vector<CalleeSavedInfo>::iterator
         I = CSI.begin(), E = CSI.end(); I != E; ++I) {
    unsigned Reg = I->getReg();
    const TargetRegisterClass *RC = RegInfo->getMinimalPhysRegClass(Reg);

    int FrameIdx;
    if (RegInfo->hasReservedSpillSlot(Fn, Reg, FrameIdx)) {
      I->setFrameIdx(FrameIdx);
      continue;
    }

    // Check to see if this physreg must be spilled to a particular stack slot
    // on this target.
    const TargetFrameLowering::SpillSlot *FixedSlot = FixedSpillSlots;
    while (FixedSlot != FixedSpillSlots+NumFixedSpillSlots &&
           FixedSlot->Reg != Reg)
      ++FixedSlot;

    if (FixedSlot == FixedSpillSlots + NumFixedSpillSlots) {
      // Nope, just spill it anywhere convenient.
      unsigned Align = RC->getAlignment();
      unsigned StackAlign = TFI->getStackAlignment();

      // We may not be able to satisfy the desired alignment specification of
      // the TargetRegisterClass if the stack alignment is smaller. Use the
      // min.
      Align = std::min(Align, StackAlign);
      FrameIdx = MFI->CreateStackObject(RC->getSize(), Align, true);
      if ((unsigned)FrameIdx < MinCSFrameIndex) MinCSFrameIndex = FrameIdx;
      if ((unsigned)FrameIdx > MaxCSFrameIndex) MaxCSFrameIndex = FrameIdx;
    } else {
      // Spill it to the stack where we must.
      FrameIdx = MFI->CreateFixedObject(RC->getSize(), FixedSlot->Offset, true);
    }

    I->setFrameIdx(FrameIdx);
  }

  MFI->setCalleeSavedInfo(CSI);
}