[llvm] r365322 - [MIPS GlobalISel] Register bank select for G_STORE. Select i64 store

Petar Avramovic via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 8 07:36:36 PDT 2019


Author: petar.avramovic
Date: Mon Jul  8 07:36:36 2019
New Revision: 365322

URL: http://llvm.org/viewvc/llvm-project?rev=365322&view=rev
Log:
[MIPS GlobalISel] Register bank select for G_STORE. Select i64 store

Select gprb or fprb when stored value is defined by either:
 copy from physical register or
 instruction with only one mapping available for that def operand.

Store of integer s64 is handled with narrowScalar when mapping is applied,
produced artifacts are combined away. Manually set gprb to all register
operands of instructions created during narrowScalar.

Differential Revision: https://reviews.llvm.org/D64268

Added:
    llvm/trunk/test/CodeGen/Mips/GlobalISel/legalizer/store.mir
    llvm/trunk/test/CodeGen/Mips/GlobalISel/llvm-ir/store.ll
    llvm/trunk/test/CodeGen/Mips/GlobalISel/regbankselect/store.mir
Modified:
    llvm/trunk/lib/Target/Mips/MipsLegalizerInfo.cpp
    llvm/trunk/lib/Target/Mips/MipsRegisterBankInfo.cpp
    llvm/trunk/lib/Target/Mips/MipsRegisterBankInfo.h

Modified: llvm/trunk/lib/Target/Mips/MipsLegalizerInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsLegalizerInfo.cpp?rev=365322&r1=365321&r2=365322&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsLegalizerInfo.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MipsLegalizerInfo.cpp Mon Jul  8 07:36:36 2019
@@ -39,9 +39,13 @@ MipsLegalizerInfo::MipsLegalizerInfo(con
       .legalForTypesWithMemDesc({{s32, p0, 8, 8},
                                  {s32, p0, 16, 8},
                                  {s32, p0, 32, 8},
+                                 {s64, p0, 64, 8},
                                  {p0, p0, 32, 8}})
       .minScalar(0, s32);
 
+  getActionDefinitionsBuilder(G_MERGE_VALUES)
+     .legalFor({{s64, s32}});
+
   getActionDefinitionsBuilder({G_ZEXTLOAD, G_SEXTLOAD})
     .legalForTypesWithMemDesc({{s32, p0, 8, 8},
                                {s32, p0, 16, 8}})

Modified: llvm/trunk/lib/Target/Mips/MipsRegisterBankInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsRegisterBankInfo.cpp?rev=365322&r1=365321&r2=365322&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsRegisterBankInfo.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MipsRegisterBankInfo.cpp Mon Jul  8 07:36:36 2019
@@ -10,14 +10,15 @@
 /// \todo This should be generated by TableGen.
 //===----------------------------------------------------------------------===//
 
-#include "MipsInstrInfo.h"
 #include "MipsRegisterBankInfo.h"
+#include "MipsInstrInfo.h"
+#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
+#include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h"
+#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 
 #define GET_TARGET_REGBANK_IMPL
 
-#define DEBUG_TYPE "registerbankinfo"
-
 #include "MipsGenRegisterBank.inc"
 
 namespace llvm {
@@ -91,9 +92,169 @@ const RegisterBank &MipsRegisterBankInfo
   }
 }
 
+// Instructions where all register operands are floating point.
+static bool isFloatingPointOpcode(unsigned Opc) {
+  switch (Opc) {
+  case TargetOpcode::G_FCONSTANT:
+  case TargetOpcode::G_FADD:
+  case TargetOpcode::G_FSUB:
+  case TargetOpcode::G_FMUL:
+  case TargetOpcode::G_FDIV:
+  case TargetOpcode::G_FABS:
+  case TargetOpcode::G_FSQRT:
+  case TargetOpcode::G_FCEIL:
+  case TargetOpcode::G_FFLOOR:
+  case TargetOpcode::G_FPEXT:
+  case TargetOpcode::G_FPTRUNC:
+    return true;
+  default:
+    return false;
+  }
+}
+
+// Instructions where def operands are floating point registers.
+// Use operands are general purpose.
+static bool isFloatingPointOpcodeDef(unsigned Opc) {
+  switch (Opc) {
+  case TargetOpcode::G_SITOFP:
+  case TargetOpcode::G_UITOFP:
+  case Mips::MTC1:
+  case Mips::BuildPairF64:
+  case Mips::BuildPairF64_64:
+    return true;
+  default:
+    return isFloatingPointOpcode(Opc);
+  }
+}
+
+static bool isAmbiguous(unsigned Opc) {
+  switch (Opc) {
+  case TargetOpcode::G_LOAD:
+  case TargetOpcode::G_STORE:
+  case TargetOpcode::G_PHI:
+  case TargetOpcode::G_SELECT:
+    return true;
+  default:
+    return false;
+  }
+}
+
+void MipsRegisterBankInfo::AmbiguousRegDefUseContainer::addUseDef(
+    Register Reg, const MachineRegisterInfo &MRI) {
+  assert(!MRI.getType(Reg).isPointer() &&
+         "Pointers are gprb, they should not be considered as ambiguous.\n");
+  MachineInstr *DefMI = MRI.getVRegDef(Reg);
+  if (DefMI->getOpcode() == TargetOpcode::COPY &&
+      !TargetRegisterInfo::isPhysicalRegister(DefMI->getOperand(1).getReg()))
+    // Copies from non-physical registers are not supported.
+    return;
+
+  UseDefs.push_back(DefMI);
+}
+
+MipsRegisterBankInfo::AmbiguousRegDefUseContainer::AmbiguousRegDefUseContainer(
+    const MachineInstr *MI) {
+  assert(isAmbiguous(MI->getOpcode()) &&
+         "Not implemented for non Ambiguous opcode.\n");
+
+  const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
+
+  if (MI->getOpcode() == TargetOpcode::G_STORE)
+    addUseDef(MI->getOperand(0).getReg(), MRI);
+}
+
+bool MipsRegisterBankInfo::TypeInfoForMF::visit(const MachineInstr *MI) {
+  assert(isAmbiguous(MI->getOpcode()) && "Visiting non-Ambiguous opcode.\n");
+
+  startVisit(MI);
+  AmbiguousRegDefUseContainer DefUseContainer(MI);
+
+  // Visit instructions that DEFINE MI's USE operands.
+  if (visitAdjacentInstrs(MI, DefUseContainer.getUseDefs()))
+    return true;
+
+  return false;
+}
+
+bool MipsRegisterBankInfo::TypeInfoForMF::visitAdjacentInstrs(
+    const MachineInstr *MI, SmallVectorImpl<MachineInstr *> &AdjacentInstrs) {
+  while (!AdjacentInstrs.empty()) {
+    MachineInstr *AdjMI = AdjacentInstrs.pop_back_val();
+
+    if (isFloatingPointOpcodeDef(AdjMI->getOpcode())) {
+      setTypes(MI, InstType::FloatingPoint);
+      return true;
+    }
+
+    // Determine InstType from register bank of phys register that is
+    // use of this copy.
+    if (AdjMI->getOpcode() == TargetOpcode::COPY) {
+      setTypesAccordingToPhysicalRegister(MI, AdjMI, 1);
+      return true;
+    }
+
+    if (isAmbiguous(AdjMI->getOpcode())) {
+      // Chains of ambiguous instructions are not supported.
+      return false;
+    }
+
+    // Defaults to integer instruction. Includes G_MERGE_VALUES and
+    // G_UNMERGE_VALUES.
+    setTypes(MI, InstType::Integer);
+    return true;
+  }
+  return false;
+}
+
+void MipsRegisterBankInfo::TypeInfoForMF::setTypes(const MachineInstr *MI,
+                                                   InstType InstTy) {
+  changeRecordedTypeForInstr(MI, InstTy);
+}
+
+void MipsRegisterBankInfo::TypeInfoForMF::setTypesAccordingToPhysicalRegister(
+    const MachineInstr *MI, const MachineInstr *CopyInst, unsigned Op) {
+  assert((TargetRegisterInfo::isPhysicalRegister(
+             CopyInst->getOperand(Op).getReg())) &&
+         "Copies of non physical registers should not be considered here.\n");
+
+  const MachineFunction &MF = *CopyInst->getMF();
+  const MachineRegisterInfo &MRI = MF.getRegInfo();
+  const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
+  const RegisterBankInfo &RBI =
+      *CopyInst->getMF()->getSubtarget().getRegBankInfo();
+  const RegisterBank *Bank =
+      RBI.getRegBank(CopyInst->getOperand(Op).getReg(), MRI, TRI);
+
+  if (Bank == &Mips::FPRBRegBank)
+    setTypes(MI, InstType::FloatingPoint);
+  else if (Bank == &Mips::GPRBRegBank)
+    setTypes(MI, InstType::Integer);
+  else
+    llvm_unreachable("Unsupported register bank.\n");
+}
+
+MipsRegisterBankInfo::InstType
+MipsRegisterBankInfo::TypeInfoForMF::determineInstType(const MachineInstr *MI) {
+  visit(MI);
+  return getRecordedTypeForInstr(MI);
+}
+
+void MipsRegisterBankInfo::TypeInfoForMF::cleanupIfNewFunction(
+    llvm::StringRef FunctionName) {
+  if (MFName != FunctionName) {
+    MFName = FunctionName;
+    Types.clear();
+  }
+}
+
 const RegisterBankInfo::InstructionMapping &
 MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
 
+  static TypeInfoForMF TI;
+
+  // Reset TI internal data when MF changes.
+  TI.cleanupIfNewFunction(MI.getMF()->getName());
+
   unsigned Opc = MI.getOpcode();
   const MachineFunction &MF = *MI.getParent()->getParent();
   const MachineRegisterInfo &MRI = MF.getRegInfo();
@@ -106,6 +267,8 @@ MipsRegisterBankInfo::getInstrMapping(co
 
   unsigned NumOperands = MI.getNumOperands();
   const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
+  unsigned MappingID = DefaultMappingID;
+  const unsigned CustomMappingID = 1;
 
   switch (Opc) {
   case G_TRUNC:
@@ -114,7 +277,6 @@ MipsRegisterBankInfo::getInstrMapping(co
   case G_MUL:
   case G_UMULH:
   case G_LOAD:
-  case G_STORE:
   case G_ZEXTLOAD:
   case G_SEXTLOAD:
   case G_GEP:
@@ -130,6 +292,36 @@ MipsRegisterBankInfo::getInstrMapping(co
   case G_UREM:
     OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx];
     break;
+  case G_STORE: {
+    unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
+    InstType InstTy = InstType::Integer;
+    if (!MRI.getType(MI.getOperand(0).getReg()).isPointer()) {
+      InstTy = TI.determineInstType(&MI);
+    }
+
+    if (InstTy == InstType::FloatingPoint) { // fprb
+      OperandsMapping =
+          getOperandsMapping({Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx]
+                                         : &Mips::ValueMappings[Mips::DPRIdx],
+                              &Mips::ValueMappings[Mips::GPRIdx]});
+      break;
+    } else { // gprb
+      OperandsMapping =
+          getOperandsMapping({Size <= 32 ? &Mips::ValueMappings[Mips::GPRIdx]
+                                         : &Mips::ValueMappings[Mips::DPRIdx],
+                              &Mips::ValueMappings[Mips::GPRIdx]});
+      if (Size == 64)
+        MappingID = CustomMappingID;
+    }
+    break;
+  }
+  case G_MERGE_VALUES: {
+    OperandsMapping = getOperandsMapping({&Mips::ValueMappings[Mips::DPRIdx],
+                                          &Mips::ValueMappings[Mips::GPRIdx],
+                                          &Mips::ValueMappings[Mips::GPRIdx]});
+    MappingID = CustomMappingID;
+    break;
+  }
   case G_FADD:
   case G_FSUB:
   case G_FMUL:
@@ -218,6 +410,73 @@ MipsRegisterBankInfo::getInstrMapping(co
     return getInvalidInstructionMapping();
   }
 
-  return getInstructionMapping(DefaultMappingID, /*Cost=*/1, OperandsMapping,
+  return getInstructionMapping(MappingID, /*Cost=*/1, OperandsMapping,
                                NumOperands);
 }
+
+using InstListTy = GISelWorkList<4>;
+namespace {
+class InstManager : public GISelChangeObserver {
+  InstListTy &InstList;
+
+public:
+  InstManager(InstListTy &Insts) : InstList(Insts) {}
+
+  void createdInstr(MachineInstr &MI) override { InstList.insert(&MI); }
+  void erasingInstr(MachineInstr &MI) override {}
+  void changingInstr(MachineInstr &MI) override {}
+  void changedInstr(MachineInstr &MI) override {}
+};
+} // end anonymous namespace
+
+/// Here we have to narrowScalar s64 operands to s32, combine away
+/// G_MERGE/G_UNMERGE and erase instructions that became dead in the process.
+/// We manually assign 32 bit gprb to register operands of all new instructions
+/// that got created in the process since they will not end up in RegBankSelect
+/// loop. Careful not to delete instruction after MI i.e. MI.getIterator()++.
+void MipsRegisterBankInfo::applyMappingImpl(
+    const OperandsMapper &OpdMapper) const {
+  MachineInstr &MI = OpdMapper.getMI();
+  InstListTy NewInstrs;
+  MachineIRBuilder B(MI);
+  MachineFunction *MF = MI.getMF();
+  MachineRegisterInfo &MRI = OpdMapper.getMRI();
+
+  InstManager NewInstrObserver(NewInstrs);
+  GISelObserverWrapper WrapperObserver(&NewInstrObserver);
+  LegalizerHelper Helper(*MF, WrapperObserver, B);
+  LegalizationArtifactCombiner ArtCombiner(
+      B, MF->getRegInfo(), *MF->getSubtarget().getLegalizerInfo());
+
+  switch (MI.getOpcode()) {
+  case TargetOpcode::G_STORE: {
+    Helper.narrowScalar(MI, 0, LLT::scalar(32));
+    // Handle new instructions.
+    while (!NewInstrs.empty()) {
+      MachineInstr *NewMI = NewInstrs.pop_back_val();
+      // This is new G_UNMERGE that was created during narrowScalar and will
+      // not be considered for regbank selection. RegBankSelect for mips
+      // visits/makes corresponding G_MERGE first. Combine them here.
+      if (NewMI->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) {
+        SmallVector<MachineInstr *, 2> DeadInstrs;
+        ArtCombiner.tryCombineMerges(*NewMI, DeadInstrs);
+        for (MachineInstr *DeadMI : DeadInstrs)
+          DeadMI->eraseFromParent();
+      } else
+        // Manually set register banks for all register operands to 32 bit gprb.
+        for (auto Op : NewMI->operands()) {
+          if (Op.isReg()) {
+            assert(MRI.getType(Op.getReg()).getSizeInBits() == 32 &&
+                   "Only 32 bit gprb is handled here.\n");
+            MRI.setRegBank(Op.getReg(), getRegBank(Mips::GPRBRegBankID));
+          }
+        }
+    }
+    return;
+  }
+  default:
+    break;
+  }
+
+  return applyDefaultMapping(OpdMapper);
+}

Modified: llvm/trunk/lib/Target/Mips/MipsRegisterBankInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsRegisterBankInfo.h?rev=365322&r1=365321&r2=365322&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsRegisterBankInfo.h (original)
+++ llvm/trunk/lib/Target/Mips/MipsRegisterBankInfo.h Mon Jul  8 07:36:36 2019
@@ -37,6 +37,82 @@ public:
 
   const InstructionMapping &
   getInstrMapping(const MachineInstr &MI) const override;
+
+  void applyMappingImpl(const OperandsMapper &OpdMapper) const override;
+
+private:
+  /// Some instructions are used with both floating point and integer operands.
+  /// We assign InstType to such instructions as it helps us to avoid cross bank
+  /// copies. InstType deppends on context.
+  enum InstType {
+    NotDetermined,
+    /// Connected with instruction that interprets 'bags of bits' as integers.
+    /// Select gprb to avoid cross bank copies.
+    Integer,
+    /// Connected with instruction that interprets 'bags of bits' as floating
+    /// point numbers. Select fprb to avoid cross bank copies.
+    FloatingPoint
+  };
+
+  /// Some generic instructions have operands that can be mapped to either fprb
+  /// or gprb e.g. for G_LOAD we consider only operand 0 as ambiguous, operand 1
+  /// is always gprb since it is a pointer.
+  /// This class provides container for MI's ambiguous:
+  /// UseDefs : MachineInstrs that define MI's ambiguous use operands.
+  class AmbiguousRegDefUseContainer {
+    SmallVector<MachineInstr *, 2> UseDefs;
+
+    void addUseDef(Register Reg, const MachineRegisterInfo &MRI);
+
+  public:
+    AmbiguousRegDefUseContainer(const MachineInstr *MI);
+    SmallVectorImpl<MachineInstr *> &getUseDefs() { return UseDefs; }
+  };
+
+  class TypeInfoForMF {
+    /// MachineFunction name is used to recognise when MF changes.
+    std::string MFName = "";
+    /// Recorded InstTypes for visited instructions.
+    DenseMap<const MachineInstr *, InstType> Types;
+
+    bool visit(const MachineInstr *MI);
+
+    /// Visit MI's adjacent UseDefs.
+    bool visitAdjacentInstrs(const MachineInstr *MI,
+                             SmallVectorImpl<MachineInstr *> &AdjacentInstrs);
+
+    void setTypes(const MachineInstr *MI, InstType ITy);
+
+    /// InstType for MI is determined, set it to InstType that corresponds to
+    /// physical regisiter that is operand number Op in CopyInst.
+    void setTypesAccordingToPhysicalRegister(const MachineInstr *MI,
+                                             const MachineInstr *CopyInst,
+                                             unsigned Op);
+
+    /// Set default values for MI in order to start visit.
+    void startVisit(const MachineInstr *MI) {
+      Types.try_emplace(MI, InstType::NotDetermined);
+    }
+
+    bool wasVisited(const MachineInstr *MI) const { return Types.count(MI); };
+
+    /// Returns recorded type for instruction.
+    const InstType &getRecordedTypeForInstr(const MachineInstr *MI) const {
+      assert(wasVisited(MI) && "Instruction was not visited!");
+      return Types.find(MI)->getSecond();
+    };
+
+    /// Change recorded type for instruction.
+    void changeRecordedTypeForInstr(const MachineInstr *MI, InstType InstTy) {
+      assert(wasVisited(MI) && "Instruction was not visited!");
+      Types.find(MI)->getSecond() = InstTy;
+    };
+
+  public:
+    InstType determineInstType(const MachineInstr *MI);
+
+    void cleanupIfNewFunction(llvm::StringRef FunctionName);
+  };
 };
 } // end namespace llvm
 #endif

Added: llvm/trunk/test/CodeGen/Mips/GlobalISel/legalizer/store.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/GlobalISel/legalizer/store.mir?rev=365322&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/GlobalISel/legalizer/store.mir (added)
+++ llvm/trunk/test/CodeGen/Mips/GlobalISel/legalizer/store.mir Mon Jul  8 07:36:36 2019
@@ -0,0 +1,98 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
+--- |
+
+  define void @store_i32(i32* %ptr) { entry: ret void }
+  define void @store_i64(i64* %ptr) { entry: ret void }
+  define void @store_float(float* %ptr) { entry: ret void }
+  define void @store_double(double* %ptr) { entry: ret void }
+
+...
+---
+name:            store_i32
+alignment:       2
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $a0, $a1
+
+    ; MIPS32-LABEL: name: store_i32
+    ; MIPS32: liveins: $a0, $a1
+    ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0
+    ; MIPS32: [[COPY1:%[0-9]+]]:_(p0) = COPY $a1
+    ; MIPS32: G_STORE [[COPY]](s32), [[COPY1]](p0) :: (store 4 into %ir.ptr)
+    ; MIPS32: RetRA
+    %0:_(s32) = COPY $a0
+    %1:_(p0) = COPY $a1
+    G_STORE %0(s32), %1(p0) :: (store 4 into %ir.ptr)
+    RetRA
+
+...
+---
+name:            store_i64
+alignment:       2
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $a0, $a1, $a2
+
+    ; MIPS32-LABEL: name: store_i64
+    ; MIPS32: liveins: $a0, $a1, $a2
+    ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $a0
+    ; MIPS32: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1
+    ; MIPS32: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32)
+    ; MIPS32: [[COPY2:%[0-9]+]]:_(p0) = COPY $a2
+    ; MIPS32: G_STORE [[MV]](s64), [[COPY2]](p0) :: (store 8 into %ir.ptr)
+    ; MIPS32: RetRA
+    %2:_(s32) = COPY $a0
+    %3:_(s32) = COPY $a1
+    %0:_(s64) = G_MERGE_VALUES %2(s32), %3(s32)
+    %1:_(p0) = COPY $a2
+    G_STORE %0(s64), %1(p0) :: (store 8 into %ir.ptr)
+    RetRA
+
+...
+---
+name:            store_float
+alignment:       2
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $a1, $f12
+
+    ; MIPS32-LABEL: name: store_float
+    ; MIPS32: liveins: $a1, $f12
+    ; MIPS32: [[COPY:%[0-9]+]]:_(s32) = COPY $f12
+    ; MIPS32: [[COPY1:%[0-9]+]]:_(p0) = COPY $a1
+    ; MIPS32: G_STORE [[COPY]](s32), [[COPY1]](p0) :: (store 4 into %ir.ptr)
+    ; MIPS32: RetRA
+    %0:_(s32) = COPY $f12
+    %1:_(p0) = COPY $a1
+    G_STORE %0(s32), %1(p0) :: (store 4 into %ir.ptr)
+    RetRA
+
+...
+---
+name:            store_double
+alignment:       2
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $a2, $d6
+
+    ; MIPS32-LABEL: name: store_double
+    ; MIPS32: liveins: $a2, $d6
+    ; MIPS32: [[COPY:%[0-9]+]]:_(s64) = COPY $d6
+    ; MIPS32: [[COPY1:%[0-9]+]]:_(p0) = COPY $a2
+    ; MIPS32: G_STORE [[COPY]](s64), [[COPY1]](p0) :: (store 8 into %ir.ptr)
+    ; MIPS32: RetRA
+    %0:_(s64) = COPY $d6
+    %1:_(p0) = COPY $a2
+    G_STORE %0(s64), %1(p0) :: (store 8 into %ir.ptr)
+    RetRA
+
+...

Added: llvm/trunk/test/CodeGen/Mips/GlobalISel/llvm-ir/store.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/GlobalISel/llvm-ir/store.ll?rev=365322&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/GlobalISel/llvm-ir/store.ll (added)
+++ llvm/trunk/test/CodeGen/Mips/GlobalISel/llvm-ir/store.ll Mon Jul  8 07:36:36 2019
@@ -0,0 +1,27 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc  -O0 -mtriple=mipsel-linux-gnu -global-isel  -verify-machineinstrs %s -o -| FileCheck %s -check-prefixes=MIPS32
+
+define void @store_i32(i32 %val, i32* %ptr)  {
+; MIPS32-LABEL: store_i32:
+; MIPS32:       # %bb.0: # %entry
+; MIPS32-NEXT:    sw $4, 0($5)
+; MIPS32-NEXT:    jr $ra
+; MIPS32-NEXT:    nop
+entry:
+  store i32 %val, i32* %ptr
+  ret void
+}
+
+define void @store_i64(i64 %val, i64* %ptr)  {
+; MIPS32-LABEL: store_i64:
+; MIPS32:       # %bb.0: # %entry
+; MIPS32-NEXT:    sw $4, 0($6)
+; MIPS32-NEXT:    ori $1, $zero, 4
+; MIPS32-NEXT:    addu $1, $6, $1
+; MIPS32-NEXT:    sw $5, 0($1)
+; MIPS32-NEXT:    jr $ra
+; MIPS32-NEXT:    nop
+entry:
+  store i64 %val, i64* %ptr
+  ret void
+}

Added: llvm/trunk/test/CodeGen/Mips/GlobalISel/regbankselect/store.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/GlobalISel/regbankselect/store.mir?rev=365322&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/GlobalISel/regbankselect/store.mir (added)
+++ llvm/trunk/test/CodeGen/Mips/GlobalISel/regbankselect/store.mir Mon Jul  8 07:36:36 2019
@@ -0,0 +1,100 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=regbankselect -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
+--- |
+
+  define void @store_i32(i32* %ptr) { entry: ret void }
+  define void @store_i64(i64* %ptr) { entry: ret void }
+  define void @store_float(float* %ptr) { entry: ret void }
+  define void @store_double(double* %ptr) { entry: ret void }
+
+...
+---
+name:            store_i32
+alignment:       2
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $a0, $a1
+
+    ; MIPS32-LABEL: name: store_i32
+    ; MIPS32: liveins: $a0, $a1
+    ; MIPS32: [[COPY:%[0-9]+]]:gprb(s32) = COPY $a0
+    ; MIPS32: [[COPY1:%[0-9]+]]:gprb(p0) = COPY $a1
+    ; MIPS32: G_STORE [[COPY]](s32), [[COPY1]](p0) :: (store 4 into %ir.ptr)
+    ; MIPS32: RetRA
+    %0:_(s32) = COPY $a0
+    %1:_(p0) = COPY $a1
+    G_STORE %0(s32), %1(p0) :: (store 4 into %ir.ptr)
+    RetRA
+
+...
+---
+name:            store_i64
+alignment:       2
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $a0, $a1, $a2
+
+    ; MIPS32-LABEL: name: store_i64
+    ; MIPS32: liveins: $a0, $a1, $a2
+    ; MIPS32: [[COPY:%[0-9]+]]:gprb(s32) = COPY $a0
+    ; MIPS32: [[COPY1:%[0-9]+]]:gprb(s32) = COPY $a1
+    ; MIPS32: [[COPY2:%[0-9]+]]:gprb(p0) = COPY $a2
+    ; MIPS32: G_STORE [[COPY]](s32), [[COPY2]](p0) :: (store 4 into %ir.ptr, align 8)
+    ; MIPS32: [[C:%[0-9]+]]:gprb(s32) = G_CONSTANT i32 4
+    ; MIPS32: [[GEP:%[0-9]+]]:gprb(p0) = G_GEP [[COPY2]], [[C]](s32)
+    ; MIPS32: G_STORE [[COPY1]](s32), [[GEP]](p0) :: (store 4 into %ir.ptr + 4, align 8)
+    ; MIPS32: RetRA
+    %2:_(s32) = COPY $a0
+    %3:_(s32) = COPY $a1
+    %0:_(s64) = G_MERGE_VALUES %2(s32), %3(s32)
+    %1:_(p0) = COPY $a2
+    G_STORE %0(s64), %1(p0) :: (store 8 into %ir.ptr)
+    RetRA
+
+...
+---
+name:            store_float
+alignment:       2
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $a1, $f12
+
+    ; MIPS32-LABEL: name: store_float
+    ; MIPS32: liveins: $a1, $f12
+    ; MIPS32: [[COPY:%[0-9]+]]:fprb(s32) = COPY $f12
+    ; MIPS32: [[COPY1:%[0-9]+]]:gprb(p0) = COPY $a1
+    ; MIPS32: G_STORE [[COPY]](s32), [[COPY1]](p0) :: (store 4 into %ir.ptr)
+    ; MIPS32: RetRA
+    %0:_(s32) = COPY $f12
+    %1:_(p0) = COPY $a1
+    G_STORE %0(s32), %1(p0) :: (store 4 into %ir.ptr)
+    RetRA
+
+...
+---
+name:            store_double
+alignment:       2
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $a2, $d6
+
+    ; MIPS32-LABEL: name: store_double
+    ; MIPS32: liveins: $a2, $d6
+    ; MIPS32: [[COPY:%[0-9]+]]:fprb(s64) = COPY $d6
+    ; MIPS32: [[COPY1:%[0-9]+]]:gprb(p0) = COPY $a2
+    ; MIPS32: G_STORE [[COPY]](s64), [[COPY1]](p0) :: (store 8 into %ir.ptr)
+    ; MIPS32: RetRA
+    %0:_(s64) = COPY $d6
+    %1:_(p0) = COPY $a2
+    G_STORE %0(s64), %1(p0) :: (store 8 into %ir.ptr)
+    RetRA
+
+...




More information about the llvm-commits mailing list