diff options
Diffstat (limited to 'llvm/lib/Target')
| -rw-r--r-- | llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp | 162 | ||||
| -rw-r--r-- | llvm/lib/Target/AArch64/AArch64InstructionSelector.h | 39 | ||||
| -rw-r--r-- | llvm/lib/Target/AArch64/AArch64Subtarget.cpp | 5 | ||||
| -rw-r--r-- | llvm/lib/Target/AArch64/AArch64Subtarget.h | 1 | ||||
| -rw-r--r-- | llvm/lib/Target/AArch64/AArch64TargetMachine.cpp | 22 | ||||
| -rw-r--r-- | llvm/lib/Target/AArch64/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp | 5 | 
7 files changed, 233 insertions, 2 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp new file mode 100644 index 00000000000..6899950c263 --- /dev/null +++ b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp @@ -0,0 +1,162 @@ +//===- AArch64InstructionSelector.cpp ----------------------------*- C++ -*-==// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This file implements the targeting of the InstructionSelector class for +/// AArch64. +/// \todo This should be generated by TableGen. +//===----------------------------------------------------------------------===// + +#include "AArch64InstructionSelector.h" +#include "AArch64InstrInfo.h" +#include "AArch64RegisterBankInfo.h" +#include "AArch64RegisterInfo.h" +#include "AArch64Subtarget.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/IR/Type.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +#define DEBUG_TYPE "aarch64-isel" + +using namespace llvm; + +#ifndef LLVM_BUILD_GLOBAL_ISEL +#error "You shouldn't build this" +#endif + +AArch64InstructionSelector::AArch64InstructionSelector( +    const AArch64Subtarget &STI, const AArch64RegisterBankInfo &RBI) +    : InstructionSelector(), TII(*STI.getInstrInfo()), +      TRI(*STI.getRegisterInfo()), RBI(RBI) {} + +/// Select the AArch64 opcode for the basic binary operation \p GenericOpc +/// (such as G_OR or G_ADD), appropriate for the register bank \p RegBankID +/// and of size \p OpSize. +/// \returns \p GenericOpc if the combination is unsupported. +static unsigned selectBinaryOp(unsigned GenericOpc, unsigned RegBankID, +                               unsigned OpSize) { +  switch (RegBankID) { +  case AArch64::GPRRegBankID: +    switch (OpSize) { +    case 32: +      switch (GenericOpc) { +      case TargetOpcode::G_OR: +        return AArch64::ORRWrr; +      case TargetOpcode::G_ADD: +        return AArch64::ADDWrr; +      default: +        return GenericOpc; +      } +    case 64: +      switch (GenericOpc) { +      case TargetOpcode::G_OR: +        return AArch64::ORRXrr; +      case TargetOpcode::G_ADD: +        return AArch64::ADDXrr; +      default: +        return GenericOpc; +      } +    } +  }; +  return GenericOpc; +} + +bool AArch64InstructionSelector::select(MachineInstr &I) const { +  assert(I.getParent() && "Instruction should be in a basic block!"); +  assert(I.getParent()->getParent() && "Instruction should be in a function!"); + +  MachineBasicBlock &MBB = *I.getParent(); +  MachineFunction &MF = *MBB.getParent(); +  MachineRegisterInfo &MRI = MF.getRegInfo(); + +  // FIXME: Is there *really* nothing to be done here?  This assumes that +  // no upstream pass introduces things like generic vreg on copies or +  // target-specific instructions. +  // We should document (and verify) that assumption. +  if (!isPreISelGenericOpcode(I.getOpcode())) +    return true; + +  if (I.getNumOperands() != I.getNumExplicitOperands()) { +    DEBUG(dbgs() << "Generic instruction has unexpected implicit operands\n"); +    return false; +  } + +  LLT Ty = I.getType(); +  assert(Ty.isValid() && "Generic instruction doesn't have a type"); + +  // FIXME: Support unsized instructions (e.g., G_BR). +  if (!Ty.isSized()) { +    DEBUG(dbgs() << "Unsized generic instructions are unsupported\n"); +    return false; +  } + +  // The size (in bits) of the operation, or 0 for the label type. +  const unsigned OpSize = Ty.getSizeInBits(); + +  switch (I.getOpcode()) { +  case TargetOpcode::G_OR: +  case TargetOpcode::G_ADD: { +    DEBUG(dbgs() << "AArch64: Selecting: binop\n"); + +    // Reject the various things we don't support yet. +    { +      const RegisterBank *PrevOpBank = nullptr; +      for (auto &MO : I.operands()) { +        // FIXME: Support non-register operands. +        if (!MO.isReg()) { +          DEBUG(dbgs() << "Generic inst non-reg operands are unsupported\n"); +          return false; +        } + +        // FIXME: Can generic operations have physical registers operands? If +        // so, this will need to be taught about that, and we'll need to get the +        // bank out of the minimal class for the register. +        // Either way, this needs to be documented (and possibly verified). +        if (!TargetRegisterInfo::isVirtualRegister(MO.getReg())) { +          DEBUG(dbgs() << "Generic inst has physical register operand\n"); +          return false; +        } + +        const RegisterBank *OpBank = RBI.getRegBank(MO.getReg(), MRI, TRI); +        if (!OpBank) { +          DEBUG(dbgs() << "Generic register has no bank or class\n"); +          return false; +        } + +        if (PrevOpBank && OpBank != PrevOpBank) { +          DEBUG(dbgs() << "Generic inst operands have different banks\n"); +          return false; +        } +        PrevOpBank = OpBank; +      } +    } + +    const unsigned DefReg = I.getOperand(0).getReg(); +    const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI); + +    const unsigned NewOpc = selectBinaryOp(I.getOpcode(), RB.getID(), OpSize); +    if (NewOpc == I.getOpcode()) +      return false; + +    I.setDesc(TII.get(NewOpc)); +    // FIXME: Should the type be always reset in setDesc? +    I.setType(LLT()); + +    // Now that we selected an opcode, we need to constrain the register +    // operands to use appropriate classes. +    return constrainSelectedInstRegOperands(I, TII, TRI, RBI); +  } +  } + +  return false; +} diff --git a/llvm/lib/Target/AArch64/AArch64InstructionSelector.h b/llvm/lib/Target/AArch64/AArch64InstructionSelector.h new file mode 100644 index 00000000000..8b9a90d7f2f --- /dev/null +++ b/llvm/lib/Target/AArch64/AArch64InstructionSelector.h @@ -0,0 +1,39 @@ +//===- AArch64InstructionSelector --------------------------------*- C++ -*-==// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This file declares the targeting of the InstructionSelector class for +/// AArch64. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_AARCH64_AARCH64INSTRUCTIONSELECTOR_H +#define LLVM_LIB_TARGET_AARCH64_AARCH64INSTRUCTIONSELECTOR_H + +#include "llvm/CodeGen/GlobalISel/InstructionSelector.h" + +namespace llvm { +class AArch64InstrInfo; +class AArch64RegisterBankInfo; +class AArch64RegisterInfo; +class AArch64Subtarget; + +class AArch64InstructionSelector : public InstructionSelector { +public: +  AArch64InstructionSelector(const AArch64Subtarget &STI, +                             const AArch64RegisterBankInfo &RBI); + +  virtual bool select(MachineInstr &I) const override; + +private: +  const AArch64InstrInfo &TII; +  const AArch64RegisterInfo &TRI; +  const AArch64RegisterBankInfo &RBI; +}; + +} // End llvm namespace. +#endif diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp index 9ec3b164243..d257e81a952 100644 --- a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp @@ -98,6 +98,11 @@ const CallLowering *AArch64Subtarget::getCallLowering() const {    return GISel->getCallLowering();  } +const InstructionSelector *AArch64Subtarget::getInstructionSelector() const { +  assert(GISel && "Access to GlobalISel APIs not set"); +  return GISel->getInstructionSelector(); +} +  const MachineLegalizer *AArch64Subtarget::getMachineLegalizer() const {    assert(GISel && "Access to GlobalISel APIs not set");    return GISel->getMachineLegalizer(); diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.h b/llvm/lib/Target/AArch64/AArch64Subtarget.h index e4bafa4d79d..ee07fec2e75 100644 --- a/llvm/lib/Target/AArch64/AArch64Subtarget.h +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.h @@ -147,6 +147,7 @@ public:      return &getInstrInfo()->getRegisterInfo();    }    const CallLowering *getCallLowering() const override; +  const InstructionSelector *getInstructionSelector() const override;    const MachineLegalizer *getMachineLegalizer() const override;    const RegisterBankInfo *getRegBankInfo() const override;    const Triple &getTargetTriple() const { return TargetTriple; } diff --git a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp index 6107e6c94db..7ee07efbc88 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp @@ -12,12 +12,14 @@  #include "AArch64.h"  #include "AArch64CallLowering.h" +#include "AArch64InstructionSelector.h"  #include "AArch64MachineLegalizer.h"  #include "AArch64RegisterBankInfo.h"  #include "AArch64TargetMachine.h"  #include "AArch64TargetObjectFile.h"  #include "AArch64TargetTransformInfo.h"  #include "llvm/CodeGen/GlobalISel/IRTranslator.h" +#include "llvm/CodeGen/GlobalISel/InstructionSelect.h"  #include "llvm/CodeGen/GlobalISel/MachineLegalizePass.h"  #include "llvm/CodeGen/GlobalISel/RegBankSelect.h"  #include "llvm/CodeGen/Passes.h" @@ -198,11 +200,15 @@ AArch64TargetMachine::~AArch64TargetMachine() {}  namespace {  struct AArch64GISelActualAccessor : public GISelAccessor {    std::unique_ptr<CallLowering> CallLoweringInfo; +  std::unique_ptr<InstructionSelector> InstSelector;    std::unique_ptr<MachineLegalizer> Legalizer;    std::unique_ptr<RegisterBankInfo> RegBankInfo;    const CallLowering *getCallLowering() const override {      return CallLoweringInfo.get();    } +  const InstructionSelector *getInstructionSelector() const override { +    return InstSelector.get(); +  }    const class MachineLegalizer *getMachineLegalizer() const override {      return Legalizer.get();    } @@ -241,8 +247,15 @@ AArch64TargetMachine::getSubtargetImpl(const Function &F) const {      GISel->CallLoweringInfo.reset(          new AArch64CallLowering(*I->getTargetLowering()));      GISel->Legalizer.reset(new AArch64MachineLegalizer()); -    GISel->RegBankInfo.reset( -        new AArch64RegisterBankInfo(*I->getRegisterInfo())); + +    auto *RBI = new AArch64RegisterBankInfo(*I->getRegisterInfo()); + +    // FIXME: At this point, we can't rely on Subtarget having RBI. +    // It's awkward to mix passing RBI and the Subtarget; should we pass +    // TII/TRI as well? +    GISel->InstSelector.reset(new AArch64InstructionSelector(*I, *RBI)); + +    GISel->RegBankInfo.reset(RBI);  #endif      I->setGISelAccessor(*GISel);    } @@ -286,6 +299,7 @@ public:    bool addIRTranslator() override;    bool addLegalizeMachineIR() override;    bool addRegBankSelect() override; +  bool addGlobalInstructionSelect() override;  #endif    bool addILPOpts() override;    void addPreRegAlloc() override; @@ -391,6 +405,10 @@ bool AArch64PassConfig::addRegBankSelect() {    addPass(new RegBankSelect());    return false;  } +bool AArch64PassConfig::addGlobalInstructionSelect() { +  addPass(new InstructionSelect()); +  return false; +}  #endif  bool AArch64PassConfig::addILPOpts() { diff --git a/llvm/lib/Target/AArch64/CMakeLists.txt b/llvm/lib/Target/AArch64/CMakeLists.txt index 9944a068243..89cfaa763a0 100644 --- a/llvm/lib/Target/AArch64/CMakeLists.txt +++ b/llvm/lib/Target/AArch64/CMakeLists.txt @@ -19,6 +19,7 @@ add_public_tablegen_target(AArch64CommonTableGen)  # List of all GlobalISel files.  set(GLOBAL_ISEL_FILES        AArch64CallLowering.cpp +      AArch64InstructionSelector.cpp        AArch64MachineLegalizer.cpp        AArch64RegisterBankInfo.cpp        ) diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp index 9affa2e003d..c0c69d85eeb 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp @@ -317,6 +317,7 @@ public:    bool addIRTranslator() override;    bool addLegalizeMachineIR() override;    bool addRegBankSelect() override; +  bool addGlobalInstructionSelect() override;  #endif    void addFastRegAlloc(FunctionPass *RegAllocPass) override;    void addOptimizedRegAlloc(FunctionPass *RegAllocPass) override; @@ -528,6 +529,10 @@ bool GCNPassConfig::addLegalizeMachineIR() {  bool GCNPassConfig::addRegBankSelect() {    return false;  } + +bool GCNPassConfig::addGlobalInstructionSelect() { +  return false; +}  #endif  void GCNPassConfig::addPreRegAlloc() {  | 

