HomePhabricator

[mips] Fix 64-bit address loading in case of applying 32-bit mask to the result

Authored by atanasyan on Wed, Aug 28, 3:32 PM.

Description

[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

llvm-svn: 370268