[llvm] r294182 - [mips] dla expansion without the at register

Simon Dardis via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 6 04:43:47 PST 2017


Author: sdardis
Date: Mon Feb  6 06:43:46 2017
New Revision: 294182

URL: http://llvm.org/viewvc/llvm-project?rev=294182&view=rev
Log:
[mips] dla expansion without the at register

Previously only the superscalar scheduled expansion of the dla macro for
MIPS64 was implemented. If assembler temporary register is not available
and the optional source register is not the destination register, synthesize
the address using the naive solution of adds and shifts.

This partially resolves PR/30383.

Thanks to Sean Bruno for reporting the issue!

Reviewers: slthakur, seanbruno

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


Modified:
    llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
    llvm/trunk/test/MC/Mips/macro-dla.s

Modified: llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp?rev=294182&r1=294181&r2=294182&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp Mon Feb  6 06:43:46 2017
@@ -361,6 +361,8 @@ class MipsAsmParser : public MCTargetAsm
   /// This should be used in pseudo-instruction expansions which need AT.
   unsigned getATReg(SMLoc Loc);
 
+  bool canUseATReg();
+
   bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
                           const MCSubtargetInfo *STI);
 
@@ -2706,20 +2708,24 @@ bool MipsAsmParser::loadAndAddSymbolAddr
 
   // This is the 64-bit symbol address expansion.
   if (ABI.ArePtrs64bit() && isGP64bit()) {
-    // We always need AT for the 64-bit expansion.
-    // If it is not available we exit.
-    unsigned ATReg = getATReg(IDLoc);
-    if (!ATReg)
-      return true;
+    // We need AT for the 64-bit expansion in the cases where the optional
+    // source register is the destination register and for the superscalar
+    // scheduled form.
+    //
+    // If it is not available we exit if the destination is the same as the
+    // source register.
 
     const MipsMCExpr *HighestExpr =
         MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
     const MipsMCExpr *HigherExpr =
         MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
 
-    if (UseSrcReg &&
-        getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
-                                                               SrcReg)) {
+    bool RdRegIsRsReg =
+        getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg);
+
+    if (canUseATReg() && UseSrcReg && RdRegIsRsReg) {
+      unsigned ATReg = getATReg(IDLoc);
+
       // If $rs is the same as $rd:
       // (d)la $rd, sym($rd) => lui    $at, %highest(sym)
       //                        daddiu $at, $at, %higher(sym)
@@ -2741,29 +2747,65 @@ bool MipsAsmParser::loadAndAddSymbolAddr
       TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
 
       return false;
-    }
+    } else if (canUseATReg() && !RdRegIsRsReg) {
+      unsigned ATReg = getATReg(IDLoc);
 
-    // Otherwise, if the $rs is different from $rd or if $rs isn't specified:
-    // (d)la $rd, sym/sym($rs) => lui    $rd, %highest(sym)
-    //                            lui    $at, %hi(sym)
-    //                            daddiu $rd, $rd, %higher(sym)
-    //                            daddiu $at, $at, %lo(sym)
-    //                            dsll32 $rd, $rd, 0
-    //                            daddu  $rd, $rd, $at
-    //                            (daddu  $rd, $rd, $rs)
-    TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
-                STI);
-    TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
-    TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
-                 MCOperand::createExpr(HigherExpr), IDLoc, STI);
-    TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
-                 IDLoc, STI);
-    TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
-    TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
-    if (UseSrcReg)
-      TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
+      // If the $rs is different from $rd or if $rs isn't specified and we
+      // have $at available:
+      // (d)la $rd, sym/sym($rs) => lui    $rd, %highest(sym)
+      //                            lui    $at, %hi(sym)
+      //                            daddiu $rd, $rd, %higher(sym)
+      //                            daddiu $at, $at, %lo(sym)
+      //                            dsll32 $rd, $rd, 0
+      //                            daddu  $rd, $rd, $at
+      //                            (daddu  $rd, $rd, $rs)
+      //
+      // Which is preferred for superscalar issue.
+      TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
+                  STI);
+      TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
+      TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
+                   MCOperand::createExpr(HigherExpr), IDLoc, STI);
+      TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
+                   IDLoc, STI);
+      TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
+      TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
+      if (UseSrcReg)
+        TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
 
-    return false;
+      return false;
+    } else if (!canUseATReg() && !RdRegIsRsReg) {
+      // Otherwise, synthesize the address in the destination register
+      // serially:
+      // (d)la $rd, sym/sym($rs) => lui    $rd, %highest(sym)
+      //                            daddiu $rd, $rd, %higher(sym)
+      //                            dsll   $rd, $rd, 16
+      //                            daddiu $rd, $rd, %hi(sym)
+      //                            dsll   $rd, $rd, 16
+      //                            daddiu $rd, $rd, %lo(sym)
+      TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
+                  STI);
+      TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
+                   MCOperand::createExpr(HigherExpr), IDLoc, STI);
+      TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
+      TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
+                   MCOperand::createExpr(HiExpr), IDLoc, STI);
+      TOut.emitRRI(Mips::DSLL, DstReg, DstReg, 16, IDLoc, STI);
+      TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
+                   MCOperand::createExpr(LoExpr), IDLoc, STI);
+      if (UseSrcReg)
+        TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
+
+      return false;
+    } else {
+      // We have a case where SrcReg == DstReg and we don't have $at
+      // available. We can't expand this case, so error out appropriately.
+      assert(SrcReg == DstReg && !canUseATReg() &&
+             "Could have expanded dla but didn't?");
+      reportParseError(IDLoc,
+                     "pseudo-instruction requires $at, which is not available");
+      return true;
+    }
   }
 
   // And now, the 32-bit symbol address expansion:
@@ -4650,6 +4692,10 @@ int MipsAsmParser::matchMSA128CtrlRegist
   return CC;
 }
 
+bool MipsAsmParser::canUseATReg() {
+  return AssemblerOptions.back()->getATRegIndex() != 0;
+}
+
 unsigned MipsAsmParser::getATReg(SMLoc Loc) {
   unsigned ATIndex = AssemblerOptions.back()->getATRegIndex();
   if (ATIndex == 0) {

Modified: llvm/trunk/test/MC/Mips/macro-dla.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Mips/macro-dla.s?rev=294182&r1=294181&r2=294182&view=diff
==============================================================================
--- llvm/trunk/test/MC/Mips/macro-dla.s (original)
+++ llvm/trunk/test/MC/Mips/macro-dla.s Mon Feb  6 06:43:46 2017
@@ -702,6 +702,54 @@ dla $5, extern_sym+8($5) # CHECK: lui $1
                          # CHECK: daddiu $1, $1, %lo(extern_sym+8)     # encoding: [0x64,0x21,A,A]
                          # CHECK:                                      # fixup A - offset: 0, value: %lo(extern_sym+8), kind: fixup_Mips_LO16
                          # CHECK: daddu   $5, $1, $5                   # encoding: [0x00,0x25,0x28,0x2d]
+.set noat
+dla $5, extern_sym       # CHECK: lui $5, %highest(extern_sym)         # encoding: [0x3c,0x05,A,A]
+                         # CHECK:                                      # fixup A - offset: 0, value: %highest(extern_sym), kind: fixup_Mips_HIGHEST
+                         # CHECK: daddiu  $5, $5, %higher(extern_sym)  # encoding: [0x64,0xa5,A,A]
+                         # CHECK:                                      # fixup A - offset: 0, value: %higher(extern_sym), kind: fixup_Mips_HIGHER
+                         # CHECK: dsll  $5, $5, 16                     # encoding: [0x00,0x05,0x2c,0x38]
+                         # CHECK: daddiu  $5, $5, %hi(extern_sym)      # encoding: [0x64,0xa5,A,A]
+                         # CHECK:                                      # fixup A - offset: 0, value: %hi(extern_sym), kind: fixup_Mips_HI16
+                         # CHECK: dsll  $5, $5, 16                     # encoding: [0x00,0x05,0x2c,0x38]
+                         # CHECK: daddiu  $5, $5, %lo(extern_sym)      # encoding: [0x64,0xa5,A,A]
+                         # CHECK:                                      # fixup A - offset: 0, value: %lo(extern_sym), kind: fixup_Mips_LO16
+
+dla $5, extern_sym+8     # CHECK: lui $5, %highest(extern_sym+8)        # encoding: [0x3c,0x05,A,A]
+                         # CHECK:                                       # fixup A - offset: 0, value: %highest(extern_sym+8), kind: fixup_Mips_HIGHEST
+                         # CHECK: daddiu  $5, $5, %higher(extern_sym+8) # encoding: [0x64,0xa5,A,A]
+                         # CHECK:                                       # fixup A - offset: 0, value: %higher(extern_sym+8), kind: fixup_Mips_HIGHER
+                         # CHECK: dsll  $5, $5, 16                      # encoding: [0x00,0x05,0x2c,0x38]
+                         # CHECK: daddiu  $5, $5, %hi(extern_sym+8)     # encoding: [0x64,0xa5,A,A]
+                         # CHECK:                                       # fixup A - offset: 0, value: %hi(extern_sym+8), kind: fixup_Mips_HI16
+                         # CHECK: dsll  $5, $5, 16                      # encoding: [0x00,0x05,0x2c,0x38]
+                         # CHECK: daddiu  $5, $5, %lo(extern_sym+8)     # encoding: [0x64,0xa5,A,A]
+                         # CHECK:                                       # fixup A - offset: 0, value: %lo(extern_sym+8), kind: fixup_Mips_LO16
+
+dla $5, extern_sym($6)   # CHECK: lui $5, %highest(extern_sym)          # encoding: [0x3c,0x05,A,A]
+                         # CHECK:                                       # fixup A - offset: 0, value: %highest(extern_sym), kind: fixup_Mips_HIGHEST
+                         # CHECK: daddiu  $5, $5, %higher(extern_sym)   # encoding: [0x64,0xa5,A,A]
+                         # CHECK:                                       # fixup A - offset: 0, value: %higher(extern_sym), kind: fixup_Mips_HIGHER
+                         # CHECK: dsll  $5, $5, 16                      # encoding: [0x00,0x05,0x2c,0x38]
+                         # CHECK: daddiu  $5, $5, %hi(extern_sym)       # encoding: [0x64,0xa5,A,A]
+                         # CHECK:                                       # fixup A - offset: 0, value: %hi(extern_sym), kind: fixup_Mips_HI16
+                         # CHECK: dsll  $5, $5, 16                      # encoding: [0x00,0x05,0x2c,0x38]
+                         # CHECK: daddiu  $5, $5, %lo(extern_sym)       # encoding: [0x64,0xa5,A,A]
+                         # CHECK:                                       # fixup A - offset: 0, value: %lo(extern_sym), kind: fixup_Mips_LO16
+                         # CHECK: daddu $5, $5, $6                      # encoding: [0x00,0xa6,0x28,0x2d]
+
+dla $4, extern_sym+8($6) # CHECK: lui $4, %highest(extern_sym+8)        # encoding: [0x3c,0x04,A,A]
+                         # CHECK:                                       # fixup A - offset: 0, value: %highest(extern_sym+8), kind: fixup_Mips_HIGHEST
+                         # CHECK: daddiu  $4, $4, %higher(extern_sym+8) # encoding: [0x64,0x84,A,A]
+                         # CHECK:                                       # fixup A - offset: 0, value: %higher(extern_sym+8), kind: fixup_Mips_HIGHER
+                         # CHECK: dsll  $4, $4, 16                      # encoding: [0x00,0x04,0x24,0x38]
+                         # CHECK: daddiu  $4, $4, %hi(extern_sym+8)     # encoding: [0x64,0x84,A,A]
+                         # CHECK:                                       # fixup A - offset: 0, value: %hi(extern_sym+8), kind: fixup_Mips_HI16
+                         # CHECK: dsll  $4, $4, 16                      # encoding: [0x00,0x04,0x24,0x38]
+                         # CHECK: daddiu  $4, $4, %lo(extern_sym+8)     # encoding: [0x64,0x84,A,A]
+                         # CHECK:                                       # fixup A - offset: 0, value: %lo(extern_sym+8), kind: fixup_Mips_LO16
+                         # CHECK: daddu $4, $4, $6                      # encoding: [0x00,0x86,0x20,0x2d]
+
+.set at
 
 .option pic2
 #dla $5, symbol




More information about the llvm-commits mailing list