[lld] [lld][ELF] Fix a corner case of elf::getLoongArchPageDelta (PR #71907)

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 22 11:21:07 PST 2023


MaskRay wrote:

> I made a brute force algorithm:
> 
> ```python
> def uintptr_t(x):
>     return x & ((1 << 64) - 1)
> 
> def ptrdiff_t(x):
>     x = uintptr_t(x)
>     if x & (1 << 63):
>         x = (1 << 64) - x
>     return x
> 
> def pcalau12i(pc, imm):
>     assert(imm in range(-0x80000, 0x80000))
>     return uintptr_t(pc + (imm << 12)) & ~0xfff
> 
> def simm(width, bits):
>     assert(bits >= 0 and bits < (1 << width))
>     return bits - ((1 << width) if bits & (1 << (width - 1)) else 0)
> 
> def reloc(dest, pc):
>     lo12 = dest & 0xfff
>     a1_first_val = uintptr_t(simm(12, lo12))
> 
>     for hi20 in range(-0x80000, 0x80000):
>         a0 = pcalau12i(pc, hi20)
>         # We need to insert something into a1[32..] to make a0 + a1 = dest,
>         # i. e. a1 = dest - a0.
>         want_a1 = uintptr_t(dest - a0)
>         if (want_a1 & 0xffffffff) != (a1_first_val & 0xffffffff):
>             continue
> 
>         lo20 = (want_a1 >> 32) & 0xfffff
>         hi12 = (want_a1 >> 52) & 0xfff
>         return (lo12, hi20 & 0xfffff, lo20, hi12)
> 
>     raise Exception("should not be reachable")
> 
> def test(dest, pc):
>     reloc(dest, pc)
>     lo12, hi20, lo20, hi12 = reloc(dest, pc)
>     a0 = pcalau12i(pc, simm(20, hi20))
>     a1 = uintptr_t(simm(12, lo12))
>     a1 &= ~(0xffffffff << 32)
>     a1 |= lo20 << 32
>     a1 |= hi12 << 52
>     assert(uintptr_t(a1 + a0) == dest)
> 
> test(0xfffffffffffff8ee, 0x8ee)
> test(0, 0x80000ffc)
> test(0, 0x80001000)
> ```
> 
> Now I need to optimize `for hi20 in range(-0x80000, 0x80000):` line, limiting hi20 into one or two possible values.

I like using a program to enumerate all the interesting bits. We should figure out a concise program to compute the offset and avoid the special cases (like in the current patch):
```
  if (result == 0xfff'fffff'fffff'000 && negativeA) // special case
    return 0xfff'fffff'00000'000;
```

We should have a description how the new code does its job and a concise proof as the comment.

https://github.com/llvm/llvm-project/pull/71907


More information about the llvm-commits mailing list