[mips][microMIPS] Implement CodeGen support for SW16 and LW16 instructions
authorZoran Jovanovic <zoran.jovanovic@imgtec.com>
Wed, 4 Feb 2015 15:43:17 +0000 (15:43 +0000)
committerZoran Jovanovic <zoran.jovanovic@imgtec.com>
Wed, 4 Feb 2015 15:43:17 +0000 (15:43 +0000)
Differential Revision: http://reviews.llvm.org/D6581

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228149 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/Mips/MicroMipsInstrInfo.td
lib/Target/Mips/MipsISelDAGToDAG.cpp
lib/Target/Mips/MipsISelDAGToDAG.h
lib/Target/Mips/MipsInstrInfo.td
lib/Target/Mips/MipsSEISelDAGToDAG.cpp
lib/Target/Mips/MipsSEISelDAGToDAG.h
test/CodeGen/Mips/longbranch.ll
test/CodeGen/Mips/micromips-sw-lw-16.ll [new file with mode: 0644]

index e03cad30b41d42140f58404025501c30f379071d..eed21a44b55e9294c9d8d00b4e15d8f0e10c7b0b 100644 (file)
@@ -1,4 +1,5 @@
 def addrimm12 : ComplexPattern<iPTR, 2, "selectIntAddrMM", [frameindex]>;
+def addrimm4lsl2 : ComplexPattern<iPTR, 2, "selectIntAddrLSL2MM", [frameindex]>;
 
 def simm4 : Operand<i32> {
   let DecoderMethod = "DecodeSimm4";
@@ -65,7 +66,7 @@ def MicroMipsMemGPRMM16AsmOperand : AsmOperandClass {
 
 class mem_mm_4_generic : Operand<i32> {
   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 GPRMM16:$src, immZExt2Shift:$imm),
 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 233bb0c8ef12c761a015d77b1a0864b8136ca42b..21fc8ce2d58293e2326ec590eb386743c453acfd 100644 (file)
@@ -95,6 +95,12 @@ bool MipsDAGToDAGISel::selectIntAddrMM(SDValue Addr, SDValue &Base,
   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 5378497c015ba944e0c0c364a2246430e85e6f6a..6b72877e9ee47e5ba63b61542ba9f6fe9d3a7c64 100644 (file)
@@ -73,6 +73,9 @@ private:
   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 ae2223a58559cc9fb02e026045b8486a3e358c3a..38a1d03eb024edc53c6d2694e9479b57556629c7 100644 (file)
@@ -1192,11 +1192,15 @@ def LBu : Load<"lbu", GPR32Opnd, zextloadi8, II_LBU, addrDefault>, MMRel,
 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 = []<Predicate>, // FIXME: Lack of HasStdEnc is probably a bug
@@ -1211,6 +1215,7 @@ def SWR : StoreLeftRight<"swr", MipsSWR, GPR32Opnd, II_SWR>, LW_FM<0x2e>,
           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 @@ let DecoderNamespace = "COP3_" in {
   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 @@ def : MipsPat<(bswap GPR32:$rt), (ROTR (WSBH GPR32:$rt), 16)>;
 let AddedComplexity = 40 in {
   def : LoadRegImmPat<LBu, i32, zextloadi8>;
   def : LoadRegImmPat<LH, i32, sextloadi16>;
+  let AdditionalPredicates = [NotInMicroMips] in {
   def : LoadRegImmPat<LW, i32, load>;
+  }
 }
 
 //===----------------------------------------------------------------------===//
index 075b067ea2485263e35d48154f59056c9c489fae..ae45bbdb708752cfe5f92621a4278111a1cba607 100644 (file)
@@ -407,6 +407,31 @@ bool MipsSEDAGToDAGISel::selectIntAddrMM(SDValue Addr, SDValue &Base,
     selectAddrDefault(Addr, Base, Offset);
 }
 
+bool MipsSEDAGToDAGISel::selectIntAddrLSL2MM(SDValue Addr, SDValue &Base,
+                                             SDValue &Offset) const {
+  if (selectAddrFrameIndexOffset(Addr, Base, Offset, 7)) {
+    if (dyn_cast<FrameIndexSDNode>(Base))
+      return false;
+    else {
+      ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Offset);
+      if (CN) {
+        unsigned CnstOff = CN->getZExtValue();
+        if (CnstOff == (CnstOff & 0x3c))
+          return true;
+      }
+
+      return false;
+    }
+  }
+
+  // For all other cases where "lw" would be selected, don't select "lw16"
+  // because it would result in additional instructions to prepare operands.
+  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 2e11fa7282a771c7ed7d3c0a3ebf0132915d2b36..2d24eb43e303ef62e532573d0b454376d740c97f 100644 (file)
@@ -65,6 +65,9 @@ private:
   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 ad0235eb0af43cfe991be68690bde13c5393b9a3..821ced8e7b83391fd04ba43af4184c6e6650c694 100644 (file)
@@ -124,7 +124,7 @@ end:
 ; 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
diff --git a/test/CodeGen/Mips/micromips-sw-lw-16.ll b/test/CodeGen/Mips/micromips-sw-lw-16.ll
new file mode 100644 (file)
index 0000000..bc09554
--- /dev/null
@@ -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]+}})