Skip to content

Commit cde1912

Browse files
committed
[mips] Fix 64-bit address loading in case of applying 32-bit mask to the result
If result of 64-bit address loading combines with 32-bit mask, LLVM tries to optimize the code and remove "redundant" loading of upper 32-bits of the address. It leads to incorrect code on MIPS64 targets. MIPS backend creates the following chain of commands to load 64-bit address in the `MipsTargetLowering::getAddrNonPICSym64` method: ``` (add (shl (add (shl (add %highest(sym), %higher(sym)), 16), %hi(sym)), 16), %lo(%sym)) ``` If the mask presents, LLVM decides to optimize the chain of commands. It really does not make sense to load upper 32-bits because the 0x0fffffff mask anyway clears them. After removing redundant commands we get this chain: ``` (add (shl (%hi(sym), 16), %lo(%sym)) ``` There is no patterns matched `(MipsHi (i64 symbol))`. Due a bug in `SYM_32` predicate definition, backend incorrectly selects a pattern for a 32-bit symbols and uses the `lui` instruction for loading `%hi(sym)`. As a result we get incorrect set of instructions with unnecessary 16-bit left shifting: ``` lui at,0x0 R_MIPS_HI16 foo dsll at,at,0x10 daddiu at,at,0 R_MIPS_LO16 foo ``` This patch resolves two problems: - Fix `SYM_32/SYM_64` predicates to prevent selection of patterns dedicated to 32-bit symbols in case of using N64 ABI. - Add missed patterns for 64-bit symbols for `%hi/%lo`. Fix PR42736. Differential Revision: https://reviews.llvm.org/D66228 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@370268 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent f28b6a5 commit cde1912

File tree

6 files changed

+77
-12
lines changed

6 files changed

+77
-12
lines changed

lib/Target/Mips/Mips.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ class PredicateControl {
2525
list<Predicate> GPRPredicates = [];
2626
// Predicates for the PTR size such as IsPTR64bit
2727
list<Predicate> PTRPredicates = [];
28+
// Predicates for a symbol's size such as hasSym32.
29+
list<Predicate> SYMPredicates = [];
2830
// Predicates for the FGR size and layout such as IsFP64bit
2931
list<Predicate> FGRPredicates = [];
3032
// Predicates for the instruction group membership such as ISA's.
@@ -38,6 +40,7 @@ class PredicateControl {
3840
list<Predicate> Predicates = !listconcat(EncodingPredicates,
3941
GPRPredicates,
4042
PTRPredicates,
43+
SYMPredicates,
4144
FGRPredicates,
4245
InsnPredicates,
4346
HardFloatPredicate,

lib/Target/Mips/Mips64InstrInfo.td

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,20 @@ let AdditionalPredicates = [NotInMicroMips] in {
682682
(DADDiu GPR64:$hi, tjumptable:$lo)>, ISA_MIPS3, GPR_64, SYM_64;
683683
def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tconstpool:$lo))),
684684
(DADDiu GPR64:$hi, tconstpool:$lo)>, ISA_MIPS3, GPR_64, SYM_64;
685+
def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 texternalsym:$lo))),
686+
(DADDiu GPR64:$hi, texternalsym:$lo)>,
687+
ISA_MIPS3, GPR_64, SYM_64;
688+
689+
def : MipsPat<(MipsHi (i64 tglobaladdr:$in)),
690+
(DADDiu ZERO_64, tglobaladdr:$in)>, ISA_MIPS3, GPR_64, SYM_64;
691+
def : MipsPat<(MipsHi (i64 tblockaddress:$in)),
692+
(DADDiu ZERO_64, tblockaddress:$in)>, ISA_MIPS3, GPR_64, SYM_64;
693+
def : MipsPat<(MipsHi (i64 tjumptable:$in)),
694+
(DADDiu ZERO_64, tjumptable:$in)>, ISA_MIPS3, GPR_64, SYM_64;
695+
def : MipsPat<(MipsHi (i64 tconstpool:$in)),
696+
(DADDiu ZERO_64, tconstpool:$in)>, ISA_MIPS3, GPR_64, SYM_64;
697+
def : MipsPat<(MipsHi (i64 texternalsym:$in)),
698+
(DADDiu ZERO_64, texternalsym:$in)>, ISA_MIPS3, GPR_64, SYM_64;
685699

686700
def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tglobaladdr:$lo))),
687701
(DADDiu GPR64:$hi, tglobaladdr:$lo)>, ISA_MIPS3, GPR_64, SYM_64;
@@ -692,6 +706,23 @@ let AdditionalPredicates = [NotInMicroMips] in {
692706
(DADDiu GPR64:$hi, tjumptable:$lo)>, ISA_MIPS3, GPR_64, SYM_64;
693707
def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tconstpool:$lo))),
694708
(DADDiu GPR64:$hi, tconstpool:$lo)>, ISA_MIPS3, GPR_64, SYM_64;
709+
def : MipsPat<(add GPR64:$hi, (MipsHi (i64 texternalsym:$lo))),
710+
(DADDiu GPR64:$hi, texternalsym:$lo)>,
711+
ISA_MIPS3, GPR_64, SYM_64;
712+
713+
def : MipsPat<(MipsLo (i64 tglobaladdr:$in)),
714+
(DADDiu ZERO_64, tglobaladdr:$in)>, ISA_MIPS3, GPR_64, SYM_64;
715+
def : MipsPat<(MipsLo (i64 tblockaddress:$in)),
716+
(DADDiu ZERO_64, tblockaddress:$in)>, ISA_MIPS3, GPR_64, SYM_64;
717+
def : MipsPat<(MipsLo (i64 tjumptable:$in)),
718+
(DADDiu ZERO_64, tjumptable:$in)>, ISA_MIPS3, GPR_64, SYM_64;
719+
def : MipsPat<(MipsLo (i64 tconstpool:$in)),
720+
(DADDiu ZERO_64, tconstpool:$in)>, ISA_MIPS3, GPR_64, SYM_64;
721+
def : MipsPat<(MipsLo (i64 tglobaltlsaddr:$in)),
722+
(DADDiu ZERO_64, tglobaltlsaddr:$in)>,
723+
ISA_MIPS3, GPR_64, SYM_64;
724+
def : MipsPat<(MipsLo (i64 texternalsym:$in)),
725+
(DADDiu ZERO_64, texternalsym:$in)>, ISA_MIPS3, GPR_64, SYM_64;
695726

696727
def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tglobaladdr:$lo))),
697728
(DADDiu GPR64:$hi, tglobaladdr:$lo)>, ISA_MIPS3, GPR_64, SYM_64;
@@ -705,6 +736,9 @@ let AdditionalPredicates = [NotInMicroMips] in {
705736
def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tglobaltlsaddr:$lo))),
706737
(DADDiu GPR64:$hi, tglobaltlsaddr:$lo)>, ISA_MIPS3, GPR_64,
707738
SYM_64;
739+
def : MipsPat<(add GPR64:$hi, (MipsLo (i64 texternalsym:$lo))),
740+
(DADDiu GPR64:$hi, texternalsym:$lo)>,
741+
ISA_MIPS3, GPR_64, SYM_64;
708742
}
709743

710744
// gp_rel relocs

lib/Target/Mips/MipsInstrInfo.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,9 @@ def HasCnMips : Predicate<"Subtarget->hasCnMips()">,
211211
AssemblerPredicate<"FeatureCnMips">;
212212
def NotCnMips : Predicate<"!Subtarget->hasCnMips()">,
213213
AssemblerPredicate<"!FeatureCnMips">;
214-
def IsSym32 : Predicate<"Subtarget->HasSym32()">,
214+
def IsSym32 : Predicate<"Subtarget->hasSym32()">,
215215
AssemblerPredicate<"FeatureSym32">;
216-
def IsSym64 : Predicate<"!Subtarget->HasSym32()">,
216+
def IsSym64 : Predicate<"!Subtarget->hasSym32()">,
217217
AssemblerPredicate<"!FeatureSym32">;
218218
def IsN64 : Predicate<"Subtarget->isABI_N64()">;
219219
def IsNotN64 : Predicate<"!Subtarget->isABI_N64()">;

test/CodeGen/Mips/indirect-jump-hazard/long-calls.ll

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,20 +74,18 @@ define void @caller() {
7474
; N64-NEXT: daddiu $25, $1, %lo(callee)
7575
; N64-NEXT: jalr.hb $25
7676
; N64-NEXT: nop
77-
; N64-NEXT: daddiu $1, $zero, %higher(memset)
78-
; N64-NEXT: lui $2, %highest(memset)
79-
; N64-NEXT: daddu $1, $2, $1
80-
; N64-NEXT: dsll $1, $1, 16
81-
; N64-NEXT: lui $2, %hi(memset)
82-
; N64-NEXT: daddu $1, $1, $2
83-
; N64-NEXT: dsll $1, $1, 16
84-
; N64-NEXT: daddiu $25, $1, %lo(memset)
8577
; N64-NEXT: lui $1, %highest(val)
8678
; N64-NEXT: daddiu $1, $1, %higher(val)
8779
; N64-NEXT: dsll $1, $1, 16
8880
; N64-NEXT: daddiu $1, $1, %hi(val)
8981
; N64-NEXT: dsll $1, $1, 16
82+
; N64-NEXT: lui $2, %highest(memset)
9083
; N64-NEXT: daddiu $4, $1, %lo(val)
84+
; N64-NEXT: daddiu $1, $2, %higher(memset)
85+
; N64-NEXT: dsll $1, $1, 16
86+
; N64-NEXT: daddiu $1, $1, %hi(memset)
87+
; N64-NEXT: dsll $1, $1, 16
88+
; N64-NEXT: daddiu $25, $1, %lo(memset)
9189
; N64-NEXT: daddiu $5, $zero, 0
9290
; N64-NEXT: jalr.hb $25
9391
; N64-NEXT: daddiu $6, $zero, 80

test/CodeGen/Mips/long-calls.ll

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,11 @@ define void @caller() {
4343
; ON64: daddiu $25, $1, %lo(callee)
4444
; ON64: jalr $25
4545

46-
; ON64: daddiu $1, $zero, %higher(memset)
4746
; ON64: lui $2, %highest(memset)
48-
; ON64: lui $2, %hi(memset)
47+
; ON64: daddiu $1, $2, %higher(memset)
48+
; ON64: dsll $1, $1, 16
49+
; ON64: daddiu $1, $1, %hi(memset)
50+
; ON64: dsll $1, $1, 16
4951
; ON64: daddiu $25, $1, %lo(memset)
5052
; ON64: jalr $25
5153

test/CodeGen/Mips/pr42736.ll

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
; RUN: llc -mtriple=mips64-linux-gnuabi64 \
2+
; RUN: -relocation-model=pic < %s | FileCheck %s -check-prefix=PIC
3+
; RUN: llc -mtriple=mips64-linux-gnuabi64 \
4+
; RUN: -relocation-model=static < %s | FileCheck %s -check-prefix=STATIC
5+
6+
define void @bar1() nounwind {
7+
entry:
8+
; PIC: lui $[[R0:[0-9]+]], 4095
9+
; PIC-NEXT: ori $[[R0]], $[[R0]], 65535
10+
; PIC-NEXT: ld $[[R1:[0-9]+]], %got_disp(foo)(${{[0-9]+}})
11+
; PIC-NEXT: and $[[R1]], $[[R1]], $[[R0]]
12+
; PIC-NEXT: sd $[[R1]]
13+
14+
; STATIC: lui $[[R0:[0-9]+]], 4095
15+
; STATIC-NEXT: ori $[[R0]], $[[R0]], 65535
16+
; STATIC-NEXT: daddiu $[[R1:[0-9]+]], $zero, %hi(foo)
17+
; STATIC-NEXT: dsll $[[R1]], $[[R1]], 16
18+
; STATIC-NEXT: daddiu $[[R1]], $[[R1]], %lo(foo)
19+
; STATIC-NEXT: and $[[R0]], $[[R1]], $[[R0]]
20+
; STATIC-NEXT: sd $[[R0]]
21+
22+
%val = alloca i64, align 8
23+
store i64 and (i64 ptrtoint (void ()* @foo to i64), i64 268435455), i64* %val, align 8
24+
%0 = load i64, i64* %val, align 8
25+
ret void
26+
}
27+
28+
declare void @foo()

0 commit comments

Comments
 (0)