From 8d2fb8809f1814e114c70a2e1bba2e4ea7413f27 Mon Sep 17 00:00:00 2001 From: Simon Atanasyan Date: Fri, 23 Aug 2019 13:36:24 +0000 Subject: [PATCH] [mips] Reduce number of instructions used for loading a global symbol's value Now `lw/sw $reg, sym+offset` pseudo instructions for global symbol `sym` are lowering into the following three instructions. ``` lw $reg, %got(symbol)($gp) addiu $reg, $reg, offset lw/sw $reg, 0($reg) ``` It's possible to reduce the number of instructions by taking the offset in account in the final `lw/sw` command. This patch implements that optimization. ``` lw $reg, %got(symbol)($gp) lw/sw $reg, offset($reg) ``` Differential Revision: https://reviews.llvm.org/D66553 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@369756 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 18 ++++++++--- test/MC/Mips/mips-expansions.s | 34 ++++++++++----------- test/MC/Mips/mips64-expansions.s | 28 ++++++++--------- 3 files changed, 41 insertions(+), 39 deletions(-) diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 09dc73b061e..5e5f7279093 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -3655,17 +3655,25 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, if (inPicMode()) { // FIXME: // a) Fix lw/sw $reg, symbol($reg) instruction expanding. - // b) If expression includes offset (sym + number), do not - // encode the offset into a relocation. Take it in account - // in the last load/store instruction. // c) Check that immediates of R_MIPS_GOT16/R_MIPS_LO16 relocations // do not exceed 16-bit. // d) Use R_MIPS_GOT_PAGE/R_MIPS_GOT_OFST relocations instead // of R_MIPS_GOT_DISP in appropriate cases to reduce number // of GOT entries. - loadAndAddSymbolAddress(OffsetOp.getExpr(), TmpReg, Mips::NoRegister, + MCValue Res; + if (!OffsetOp.getExpr()->evaluateAsRelocatable(Res, nullptr, nullptr)) { + Error(IDLoc, "expected relocatable expression"); + return; + } + if (Res.getSymB() != nullptr) { + Error(IDLoc, "expected relocatable expression with only one symbol"); + return; + } + + loadAndAddSymbolAddress(Res.getSymA(), TmpReg, Mips::NoRegister, !ABI.ArePtrs64bit(), IDLoc, Out, STI); - TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, 0, IDLoc, STI); + TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, Res.getConstant(), IDLoc, + STI); } else { const MCExpr *ExprOffset = OffsetOp.getExpr(); MCOperand LoOperand = MCOperand::createExpr( diff --git a/test/MC/Mips/mips-expansions.s b/test/MC/Mips/mips-expansions.s index cd5002cfca7..240e06868d4 100644 --- a/test/MC/Mips/mips-expansions.s +++ b/test/MC/Mips/mips-expansions.s @@ -122,17 +122,17 @@ # CHECK-LE: sw $10, 0($1) # encoding: [0x00,0x00,0x2a,0xac] lw $8, 1f+8 -# CHECK-LE: lw $8, %got(($tmp0)+8)($gp) # encoding: [A,A,0x88,0x8f] -# CHECK-LE: # fixup A - offset: 0, value: %got(($tmp0)+8), kind: fixup_Mips_GOT -# CHECK-LE: addiu $8, $8, %lo(($tmp0)+8) # encoding: [A,A,0x08,0x25] -# CHECK-LE: # fixup A - offset: 0, value: %lo(($tmp0)+8), kind: fixup_Mips_LO16 -# CHECK-LE: lw $8, 0($8) # encoding: [0x00,0x00,0x08,0x8d] +# CHECK-LE: lw $8, %got($tmp0)($gp) # encoding: [A,A,0x88,0x8f] +# CHECK-LE-NEXT: # fixup A - offset: 0, value: %got($tmp0), kind: fixup_Mips_GOT +# CHECK-LE-NEXT: addiu $8, $8, %lo($tmp0) # encoding: [A,A,0x08,0x25] +# CHECK-LE-NEXT: # fixup A - offset: 0, value: %lo($tmp0), kind: fixup_Mips_LO16 +# CHECK-LE-NEXT: lw $8, 8($8) # encoding: [0x08,0x00,0x08,0x8d] sw $8, 1f+8 -# CHECK-LE: lw $1, %got(($tmp0)+8)($gp) # encoding: [A,A,0x81,0x8f] -# CHECK-LE: # fixup A - offset: 0, value: %got(($tmp0)+8), kind: fixup_Mips_GOT -# CHECK-LE: addiu $1, $1, %lo(($tmp0)+8) # encoding: [A,A,0x21,0x24] -# CHECK-LE: # fixup A - offset: 0, value: %lo(($tmp0)+8), kind: fixup_Mips_LO16 -# CHECK-LE: sw $8, 0($1) # encoding: [0x00,0x00,0x28,0xac] +# CHECK-LE: lw $1, %got($tmp0)($gp) # encoding: [A,A,0x81,0x8f] +# CHECK-LE-NEXT: # fixup A - offset: 0, value: %got($tmp0), kind: fixup_Mips_GOT +# CHECK-LE-NEXT: addiu $1, $1, %lo($tmp0) # encoding: [A,A,0x21,0x24] +# CHECK-LE-NEXT: # fixup A - offset: 0, value: %lo($tmp0), kind: fixup_Mips_LO16 +# CHECK-LE-NEXT: sw $8, 8($1) # encoding: [0x08,0x00,0x28,0xac] lw $10, 655483($4) # CHECK-LE: lui $10, 10 # encoding: [0x0a,0x00,0x0a,0x3c] @@ -144,15 +144,13 @@ # CHECK-LE: sw $10, -7616($1) # encoding: [0x40,0xe2,0x2a,0xac] lw $8, symbol+8 -# CHECK-LE: lw $8, %got(symbol)($gp) # encoding: [A,A,0x88,0x8f] -# CHECK-LE: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT -# CHECK-LE: addiu $8, $8, 8 # encoding: [0x08,0x00,0x08,0x25] -# CHECK-LE: lw $8, 0($8) # encoding: [0x00,0x00,0x08,0x8d] +# CHECK-LE: lw $8, %got(symbol)($gp) # encoding: [A,A,0x88,0x8f] +# CHECK-LE-NEXT: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT +# CHECK-LE-NEXT: lw $8, 8($8) # encoding: [0x08,0x00,0x08,0x8d] sw $8, symbol+8 -# CHECK-LE: lw $1, %got(symbol)($gp) # encoding: [A,A,0x81,0x8f] -# CHECK-LE: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT -# CHECK-LE: addiu $1, $1, 8 # encoding: [0x08,0x00,0x21,0x24] -# CHECK-LE: sw $8, 0($1) # encoding: [0x00,0x00,0x28,0xac] +# CHECK-LE: lw $1, %got(symbol)($gp) # encoding: [A,A,0x81,0x8f] +# CHECK-LE-NEXT: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT +# CHECK-LE-NEXT: sw $8, 8($1) # encoding: [0x08,0x00,0x28,0xac] ldc1 $f0, symbol # CHECK-LE: lw $1, %got(symbol)($gp) # encoding: [A,A,0x81,0x8f] diff --git a/test/MC/Mips/mips64-expansions.s b/test/MC/Mips/mips64-expansions.s index 4c24379f2dd..5689c9ad8c9 100644 --- a/test/MC/Mips/mips64-expansions.s +++ b/test/MC/Mips/mips64-expansions.s @@ -481,15 +481,13 @@ sym: # CHECK: sw $10, 0($1) # encoding: [0x00,0x00,0x2a,0xac] lw $8, sym+8 -# CHECK: ld $8, %got_disp(sym)($gp) # encoding: [A,A,0x88,0xdf] -# CHECK: # fixup A - offset: 0, value: %got_disp(sym), kind: fixup_Mips_GOT_DISP -# CHECK: daddiu $8, $8, 8 # encoding: [0x08,0x00,0x08,0x65] -# CHECK: lw $8, 0($8) # encoding: [0x00,0x00,0x08,0x8d] +# CHECK: ld $8, %got_disp(sym)($gp) # encoding: [A,A,0x88,0xdf] +# CHECK-NEXT: # fixup A - offset: 0, value: %got_disp(sym), kind: fixup_Mips_GOT_DISP +# CHECK-NEXT: lw $8, 8($8) # encoding: [0x08,0x00,0x08,0x8d] sw $8, sym+8 -# CHECK: ld $1, %got_disp(sym)($gp) # encoding: [A,A,0x81,0xdf] -# CHECK: # fixup A - offset: 0, value: %got_disp(sym), kind: fixup_Mips_GOT_DISP -# CHECK: daddiu $1, $1, 8 # encoding: [0x08,0x00,0x21,0x64] -# CHECK: sw $8, 0($1) # encoding: [0x00,0x00,0x28,0xac] +# CHECK: ld $1, %got_disp(sym)($gp) # encoding: [A,A,0x81,0xdf] +# CHECK-NEXT: # fixup A - offset: 0, value: %got_disp(sym), kind: fixup_Mips_GOT_DISP +# CHECK-NEXT: sw $8, 8($1) # encoding: [0x08,0x00,0x28,0xac] lw $10, 655483($4) # CHECK: lui $10, 10 # encoding: [0x0a,0x00,0x0a,0x3c] @@ -501,15 +499,13 @@ sym: # CHECK: sw $10, -7616($1) # encoding: [0x40,0xe2,0x2a,0xac] lw $8, symbol+8 -# CHECK: ld $8, %got_disp(symbol)($gp) # encoding: [A,A,0x88,0xdf] -# CHECK: # fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP -# CHECK: daddiu $8, $8, 8 # encoding: [0x08,0x00,0x08,0x65] -# CHECK: lw $8, 0($8) # encoding: [0x00,0x00,0x08,0x8d] +# CHECK: ld $8, %got_disp(symbol)($gp) # encoding: [A,A,0x88,0xdf] +# CHECK-NEXT: # fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP +# CHECK-NEXT: lw $8, 8($8) # encoding: [0x08,0x00,0x08,0x8d] sw $8, symbol+8 -# CHECK: ld $1, %got_disp(symbol)($gp) # encoding: [A,A,0x81,0xdf] -# CHECK: # fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP -# CHECK: daddiu $1, $1, 8 # encoding: [0x08,0x00,0x21,0x64] -# CHECK: sw $8, 0($1) # encoding: [0x00,0x00,0x28,0xac] +# CHECK: ld $1, %got_disp(symbol)($gp) # encoding: [A,A,0x81,0xdf] +# CHECK-NEXT: # fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP +# CHECK-NEXT: sw $8, 8($1) # encoding: [0x08,0x00,0x28,0xac] ldc1 $f0, symbol # CHECK: ld $1, %got_disp(symbol)($gp) # encoding: [A,A,0x81,0xdf] -- 2.40.0