Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -1092,6 +1092,11 @@ && (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() && Index: lib/Target/Mips/MicroMipsInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsInstrInfo.td +++ lib/Target/Mips/MicroMipsInstrInfo.td @@ -47,9 +47,15 @@ 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 @@ 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 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 @@ 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>; Index: lib/Target/Mips/MipsRegisterInfo.h =================================================================== --- lib/Target/Mips/MipsRegisterInfo.h +++ 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 Index: lib/Target/Mips/MipsRegisterInfo.cpp =================================================================== --- lib/Target/Mips/MipsRegisterInfo.cpp +++ lib/Target/Mips/MipsRegisterInfo.cpp @@ -50,13 +50,19 @@ 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 Index: lib/Target/Mips/MipsRegisterInfo.td =================================================================== --- lib/Target/Mips/MipsRegisterInfo.td +++ lib/Target/Mips/MipsRegisterInfo.td @@ -453,6 +453,13 @@ 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; Index: test/CodeGen/Mips/micromips-addiu.ll =================================================================== --- test/CodeGen/Mips/micromips-addiu.ll +++ 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