Index: lib/Target/Mips/MicroMipsInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsInstrInfo.td +++ lib/Target/Mips/MicroMipsInstrInfo.td @@ -1,4 +1,5 @@ def addrimm12 : ComplexPattern; +def addrimm4lsl2 : ComplexPattern; def simm4 : Operand { let DecoderMethod = "DecodeSimm4"; @@ -65,7 +66,7 @@ class mem_mm_4_generic : Operand { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops ptr_rc, simm4); + let MIOperandInfo = (ops GPRMM16, simm4); let OperandType = "OPERAND_MEMORY"; let ParserMatchClass = MicroMipsMemGPRMM16AsmOperand; } @@ -879,6 +880,16 @@ def : MipsPat<(srl GPR32:$src, immZExt5:$imm), (SRL_MM GPR32:$src, immZExt5:$imm)>; +def : MipsPat<(store GPRMM16:$src, addrimm4lsl2:$addr), + (SW16_MM GPRMM16:$src, addrimm4lsl2:$addr)>; +def : MipsPat<(store GPR32:$src, addr:$addr), + (SW_MM GPR32:$src, addr:$addr)>; + +def : MipsPat<(load addrimm4lsl2:$addr), + (LW16_MM addrimm4lsl2:$addr)>; +def : MipsPat<(load addr:$addr), + (LW_MM addr:$addr)>; + //===----------------------------------------------------------------------===// // MicroMips instruction aliases //===----------------------------------------------------------------------===// Index: lib/Target/Mips/MipsISelDAGToDAG.h =================================================================== --- lib/Target/Mips/MipsISelDAGToDAG.h +++ lib/Target/Mips/MipsISelDAGToDAG.h @@ -73,6 +73,9 @@ virtual bool selectIntAddrMM(SDValue Addr, SDValue &Base, SDValue &Offset) const; + virtual bool selectIntAddrLSL2MM(SDValue Addr, SDValue &Base, + SDValue &Offset) const; + /// Match addr+simm10 and addr virtual bool selectIntAddrMSA(SDValue Addr, SDValue &Base, SDValue &Offset) const; Index: lib/Target/Mips/MipsISelDAGToDAG.cpp =================================================================== --- lib/Target/Mips/MipsISelDAGToDAG.cpp +++ lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -95,6 +95,12 @@ return false; } +bool MipsDAGToDAGISel::selectIntAddrLSL2MM(SDValue Addr, SDValue &Base, + SDValue &Offset) const { + llvm_unreachable("Unimplemented function."); + return false; +} + bool MipsDAGToDAGISel::selectIntAddrMSA(SDValue Addr, SDValue &Base, SDValue &Offset) const { llvm_unreachable("Unimplemented function."); Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -1192,11 +1192,15 @@ def LH : Load<"lh", GPR32Opnd, sextloadi16, II_LH, addrDefault>, MMRel, LW_FM<0x21>; def LHu : Load<"lhu", GPR32Opnd, zextloadi16, II_LHU>, MMRel, LW_FM<0x25>; +let AdditionalPredicates = [NotInMicroMips] in { def LW : Load<"lw", GPR32Opnd, load, II_LW, addrDefault>, MMRel, LW_FM<0x23>; +} def SB : Store<"sb", GPR32Opnd, truncstorei8, II_SB>, MMRel, LW_FM<0x28>; def SH : Store<"sh", GPR32Opnd, truncstorei16, II_SH>, MMRel, LW_FM<0x29>; +let AdditionalPredicates = [NotInMicroMips] in { def SW : Store<"sw", GPR32Opnd, store, II_SW>, MMRel, LW_FM<0x2b>; +} /// load/store left/right let EncodingPredicates = [], // FIXME: Lack of HasStdEnc is probably a bug @@ -1211,6 +1215,7 @@ ISA_MIPS1_NOT_32R6_64R6; } +let AdditionalPredicates = [NotInMicroMips] in { // COP2 Memory Instructions def LWC2 : LW_FT2<"lwc2", COP2Opnd, NoItinerary, load>, LW_FM<0x32>, ISA_MIPS1_NOT_32R6_64R6; @@ -1230,6 +1235,7 @@ def SDC3 : SW_FT3<"sdc3", COP3Opnd, NoItinerary, store>, LW_FM<0x3f>, ISA_MIPS2; } +} def SYNC : MMRel, SYNC_FT<"sync">, SYNC_FM, ISA_MIPS32; def SYNCI : MMRel, SYNCI_FT<"synci">, SYNCI_FM, ISA_MIPS32R2; @@ -1858,7 +1864,9 @@ let AddedComplexity = 40 in { def : LoadRegImmPat; def : LoadRegImmPat; + let AdditionalPredicates = [NotInMicroMips] in { def : LoadRegImmPat; + } } //===----------------------------------------------------------------------===// Index: lib/Target/Mips/MipsSEISelDAGToDAG.h =================================================================== --- lib/Target/Mips/MipsSEISelDAGToDAG.h +++ lib/Target/Mips/MipsSEISelDAGToDAG.h @@ -65,6 +65,9 @@ bool selectIntAddrMM(SDValue Addr, SDValue &Base, SDValue &Offset) const override; + bool selectIntAddrLSL2MM(SDValue Addr, SDValue &Base, + SDValue &Offset) const override; + bool selectIntAddrMSA(SDValue Addr, SDValue &Base, SDValue &Offset) const override; Index: lib/Target/Mips/MipsSEISelDAGToDAG.cpp =================================================================== --- lib/Target/Mips/MipsSEISelDAGToDAG.cpp +++ lib/Target/Mips/MipsSEISelDAGToDAG.cpp @@ -407,6 +407,29 @@ selectAddrDefault(Addr, Base, Offset); } +bool MipsSEDAGToDAGISel::selectIntAddrLSL2MM(SDValue Addr, SDValue &Base, + SDValue &Offset) const { + if (selectAddrFrameIndexOffset(Addr, Base, Offset, 7)) { + if (dyn_cast(Base)) + return false; + else { + ConstantSDNode *CN = dyn_cast(Offset); + if (CN) { + unsigned CnstOff = CN->getZExtValue(); + if (CnstOff == (CnstOff & 0x3c)) + return true; + } + + return false; + } + } + + if (selectAddrRegImm(Addr, Base, Offset)) + return false; + + return selectAddrDefault(Addr, Base, Offset); +} + bool MipsSEDAGToDAGISel::selectIntAddrMSA(SDValue Addr, SDValue &Base, SDValue &Offset) const { if (selectAddrRegImm10(Addr, Base, Offset)) Index: test/CodeGen/Mips/longbranch.ll =================================================================== --- test/CodeGen/Mips/longbranch.ll +++ test/CodeGen/Mips/longbranch.ll @@ -124,7 +124,7 @@ ; MICROMIPS: $[[BB0]]: ; MICROMIPS: lw $[[R1:[0-9]+]], %got(x)($[[GP]]) ; MICROMIPS: li16 $[[R2:[0-9]+]], 1 -; MICROMIPS: sw $[[R2]], 0($[[R1]]) +; MICROMIPS: sw16 $[[R2]], 0($[[R1]]) ; MICROMIPS: $[[BB2]]: ; MICROMIPS: jr $ra ; MICROMIPS: nop Index: test/CodeGen/Mips/micromips-sw-lw-16.ll =================================================================== --- /dev/null +++ test/CodeGen/Mips/micromips-sw-lw-16.ll @@ -0,0 +1,27 @@ +; RUN: llc %s -march=mipsel -mattr=micromips -filetype=asm \ +; RUN: -relocation-model=pic -O3 -o - | FileCheck %s + +; Function Attrs: noinline nounwind +define void @bar(i32* %p) #0 { +entry: + %p.addr = alloca i32*, align 4 + store i32* %p, i32** %p.addr, align 4 + %0 = load i32** %p.addr, align 4 + %1 = load i32* %0, align 4 + %add = add nsw i32 7, %1 + %2 = load i32** %p.addr, align 4 + store i32 %add, i32* %2, align 4 + %3 = load i32** %p.addr, align 4 + %add.ptr = getelementptr inbounds i32* %3, i32 1 + %4 = load i32* %add.ptr, align 4 + %add1 = add nsw i32 7, %4 + %5 = load i32** %p.addr, align 4 + %add.ptr2 = getelementptr inbounds i32* %5, i32 1 + store i32 %add1, i32* %add.ptr2, align 4 + ret void +} + +; CHECK: lw16 ${{[0-9]+}}, 0($4) +; CHECK: sw16 ${{[0-9]+}}, 0($4) +; CHECK: lw16 ${{[0-9]+}}, 4(${{[0-9]+}}) +; CHECK: sw16 ${{[0-9]+}}, 4(${{[0-9]+}})