From 43d2886cca0f683724637679e0fc9bc50511dce3 Mon Sep 17 00:00:00 2001 From: Daniel Sanders Date: Mon, 9 May 2016 13:38:25 +0000 Subject: [PATCH] [mips][micromips] Make getPointerRegClass() result depend on the instruction. Summary: Previously, it returned the GPR16MMRegClass for all instructions which was incorrect for instructions like lwsp/lwgp and unnecesarily restricted the permitted registers for instructions like lw32. This fixes quite a few of the -verify-machineinstrs errors reported in PR27458. I've only added -verify-machineinstrs to one test in this change since I understand there is a plan to enable the verifier by default. Reviewers: hvarga, zbuljan, zoran.jovanovic, sdardis Subscribers: dsanders, llvm-commits, sdardis Differential Revision: http://reviews.llvm.org/D19873 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@268918 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 5 ++++ lib/Target/Mips/MicroMipsInstrInfo.td | 26 ++++++++++++++++----- lib/Target/Mips/MipsRegisterInfo.cpp | 20 ++++++++++------ lib/Target/Mips/MipsRegisterInfo.h | 12 ++++++++++ lib/Target/Mips/MipsRegisterInfo.td | 7 ++++++ test/CodeGen/Mips/micromips-addiu.ll | 2 +- 6 files changed, 58 insertions(+), 14 deletions(-) diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index bff46886dc7..02922bccccf 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -1092,6 +1092,11 @@ public: && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP); } + template bool isMemWithSimmWordAlignedOffsetGP() const { + return isMem() && isConstantMemOff() && isInt(getConstantMemOff()) + && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx() + && (getMemBase()->getGPR32Reg() == Mips::GP); + } template bool isScaledUImm() const { return isConstantImm() && diff --git a/lib/Target/Mips/MicroMipsInstrInfo.td b/lib/Target/Mips/MicroMipsInstrInfo.td index d552109b75a..35f5138701c 100644 --- a/lib/Target/Mips/MicroMipsInstrInfo.td +++ b/lib/Target/Mips/MicroMipsInstrInfo.td @@ -47,9 +47,15 @@ def MicroMipsMemGPRMM16AsmOperand : AsmOperandClass { let PredicateMethod = "isMemWithGRPMM16Base"; } +// Define the classes of pointers used by microMIPS. +// The numbers must match those in MipsRegisterInfo::MipsPtrClass. +def ptr_gpr16mm_rc : PointerLikeRegClass<1>; +def ptr_sp_rc : PointerLikeRegClass<2>; +def ptr_gp_rc : PointerLikeRegClass<3>; + class mem_mm_4_generic : Operand { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops ptr_rc, simm4); + let MIOperandInfo = (ops ptr_gpr16mm_rc, simm4); let OperandType = "OPERAND_MEMORY"; let ParserMatchClass = MicroMipsMemGPRMM16AsmOperand; } @@ -73,18 +79,26 @@ def MicroMipsMemSPAsmOperand : AsmOperandClass { let PredicateMethod = "isMemWithUimmWordAlignedOffsetSP<7>"; } +def MicroMipsMemGPAsmOperand : AsmOperandClass { + let Name = "MicroMipsMemGP"; + let RenderMethod = "addMemOperands"; + let ParserMethod = "parseMemOperand"; + let PredicateMethod = "isMemWithSimmWordAlignedOffsetGP<9>"; +} + def mem_mm_sp_imm5_lsl2 : Operand { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops ptr_rc:$base, simm5:$offset); + let MIOperandInfo = (ops ptr_sp_rc:$base, simm5:$offset); let OperandType = "OPERAND_MEMORY"; let ParserMatchClass = MicroMipsMemSPAsmOperand; let EncoderMethod = "getMemEncodingMMSPImm5Lsl2"; } -def mem_mm_gp_imm7_lsl2 : Operand { +def mem_mm_gp_simm7_lsl2 : Operand { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops GPRMM16:$base, simm7_lsl2:$offset); + let MIOperandInfo = (ops ptr_gp_rc:$base, simm7_lsl2:$offset); let OperandType = "OPERAND_MEMORY"; + let ParserMatchClass = MicroMipsMemGPAsmOperand; let EncoderMethod = "getMemEncodingMMGPImm7Lsl2"; } @@ -122,7 +136,7 @@ def MipsMemUimm4AsmOperand : AsmOperandClass { def mem_mm_4sp : Operand { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops ptr_rc, uimm8); + let MIOperandInfo = (ops ptr_sp_rc, uimm8); let EncoderMethod = "getMemEncodingMMImm4sp"; let ParserMatchClass = MipsMemUimm4AsmOperand; let OperandType = "OPERAND_MEMORY"; @@ -618,7 +632,7 @@ def SH16_MM : StoreMM16<"sh16", GPRMM16OpndZero, GPRMM16Opnd, truncstorei16, LOAD_STORE_FM_MM16<0x2a>; def SW16_MM : StoreMM16<"sw16", GPRMM16OpndZero, GPRMM16Opnd, store, II_SW, mem_mm_4_lsl2>, LOAD_STORE_FM_MM16<0x3a>; -def LWGP_MM : LoadGPMM16<"lw", GPRMM16Opnd, II_LW, mem_mm_gp_imm7_lsl2>, +def LWGP_MM : LoadGPMM16<"lw", GPRMM16Opnd, II_LW, mem_mm_gp_simm7_lsl2>, LOAD_GP_FM_MM16<0x19>; def LWSP_MM : LoadSPMM16<"lw", GPR32Opnd, II_LW, mem_mm_sp_imm5_lsl2>, LOAD_STORE_SP_FM_MM16<0x12>; diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp index 452400e5684..6981dd91cb8 100644 --- a/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/lib/Target/Mips/MipsRegisterInfo.cpp @@ -50,13 +50,19 @@ const TargetRegisterClass * MipsRegisterInfo::getPointerRegClass(const MachineFunction &MF, unsigned Kind) const { MipsABIInfo ABI = MF.getSubtarget().getABI(); - bool inMicroMips = MF.getSubtarget().inMicroMipsMode(); - - return ABI.ArePtrs64bit() ? - inMicroMips ? - &Mips::GPRMM16_64RegClass : &Mips::GPR64RegClass - : inMicroMips ? - &Mips::GPRMM16RegClass : &Mips::GPR32RegClass; + MipsPtrClass PtrClassKind = static_cast(Kind); + + switch (PtrClassKind) { + case MipsPtrClass::Default: + return ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; + case MipsPtrClass::GPR16MM: + return ABI.ArePtrs64bit() ? &Mips::GPRMM16_64RegClass + : &Mips::GPRMM16RegClass; + case MipsPtrClass::StackPointer: + return ABI.ArePtrs64bit() ? &Mips::SP64RegClass : &Mips::SP32RegClass; + case MipsPtrClass::GlobalPointer: + return ABI.ArePtrs64bit() ? &Mips::GP64RegClass : &Mips::GP32RegClass; + } } unsigned diff --git a/lib/Target/Mips/MipsRegisterInfo.h b/lib/Target/Mips/MipsRegisterInfo.h index 286fe8e3255..32f835e8310 100644 --- a/lib/Target/Mips/MipsRegisterInfo.h +++ b/lib/Target/Mips/MipsRegisterInfo.h @@ -23,6 +23,18 @@ namespace llvm { class MipsRegisterInfo : public MipsGenRegisterInfo { public: + enum class MipsPtrClass { + /// The default register class for integer values. + Default = 0, + /// The subset of registers permitted in certain microMIPS instructions + /// such as lw16. + GPR16MM = 1, + /// The stack pointer only. + StackPointer = 2, + /// The global pointer only. + GlobalPointer = 3, + }; + MipsRegisterInfo(); /// Get PIC indirect call register diff --git a/lib/Target/Mips/MipsRegisterInfo.td b/lib/Target/Mips/MipsRegisterInfo.td index 939debcd956..cfce7c8e653 100644 --- a/lib/Target/Mips/MipsRegisterInfo.td +++ b/lib/Target/Mips/MipsRegisterInfo.td @@ -453,6 +453,13 @@ def COP2 : RegisterClass<"Mips", [i32], 32, (sequence "COP2%u", 0, 31)>, def COP3 : RegisterClass<"Mips", [i32], 32, (sequence "COP3%u", 0, 31)>, Unallocatable; +// Stack pointer and global pointer classes for instructions that are limited +// to a single register such as lwgp/lwsp in microMIPS. +def SP32 : RegisterClass<"Mips", [i32], 32, (add SP)>, Unallocatable; +def SP64 : RegisterClass<"Mips", [i64], 64, (add SP_64)>, Unallocatable; +def GP32 : RegisterClass<"Mips", [i32], 32, (add GP)>, Unallocatable; +def GP64 : RegisterClass<"Mips", [i64], 64, (add GP_64)>, Unallocatable; + // Octeon multiplier and product registers def OCTEON_MPL : RegisterClass<"Mips", [i64], 64, (add MPL0, MPL1, MPL2)>, Unallocatable; diff --git a/test/CodeGen/Mips/micromips-addiu.ll b/test/CodeGen/Mips/micromips-addiu.ll index e0743c9c088..84ebc4349e1 100644 --- a/test/CodeGen/Mips/micromips-addiu.ll +++ b/test/CodeGen/Mips/micromips-addiu.ll @@ -1,4 +1,4 @@ -; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=+micromips \ +; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=+micromips -verify-machineinstrs \ ; RUN: -relocation-model=pic -O3 < %s | FileCheck %s @x = global i32 65504, align 4 -- 2.50.1