diff options
author | Fangrui Song <maskray@google.com> | 2020-01-28 21:18:29 -0800 |
---|---|---|
committer | Fangrui Song <maskray@google.com> | 2020-01-28 22:30:52 -0800 |
commit | bc15bf66dcca76cc06fe71fca35b74dc4d521021 (patch) | |
tree | 920f9508b55f3ae9786f86ab6948dea8be447e3b /llvm/lib/CodeGen/ReachingDefAnalysis.cpp | |
parent | 76843ba37f0b69c01a6bcc61123cadfec0164855 (diff) | |
download | llvm-bc15bf66dcca76cc06fe71fca35b74dc4d521021.zip llvm-bc15bf66dcca76cc06fe71fca35b74dc4d521021.tar.gz llvm-bc15bf66dcca76cc06fe71fca35b74dc4d521021.tar.bz2 |
[X86] matchAdd: don't fold a large offset into a %rip relative address
For `ret i64 add (i64 ptrtoint (i32* @foo to i64), i64 1701208431)`,
```
X86DAGToDAGISel::matchAdd
...
// AM.setBaseReg(CurDAG->getRegister(X86::RIP, MVT::i64));
if (!matchAddressRecursively(N.getOperand(0), AM, Depth+1) &&
// Try folding offset but fail; there is a symbolic displacement, so offset cannot be too large
!matchAddressRecursively(Handle.getValue().getOperand(1), AM, Depth+1))
return false;
...
// Try again after commuting the operands.
// AM.Disp = Val; foldOffsetIntoAddress() does not know there will be a symbolic displacement
if (!matchAddressRecursively(Handle.getValue().getOperand(1), AM, Depth+1) &&
// AM.setBaseReg(CurDAG->getRegister(X86::RIP, MVT::i64));
!matchAddressRecursively(Handle.getValue().getOperand(0), AM, Depth+1))
// Succeeded! Produced leaq sym+disp(%rip),...
return false;
```
`foldOffsetIntoAddress()` currently does not know there is a symbolic
displacement and can fold a large offset.
The produced `leaq sym+disp(%rip), %rax` instruction is relocated by
an R_X86_64_PC32. If disp is large and sym+disp-rip>=2**31, there
will be a relocation overflow.
This approach is still not elegant. Unfortunately the isRIPRelative
interface is a bit clumsy. I tried several solutions and eventually
picked this one.
Differential Revision: https://reviews.llvm.org/D73606
Diffstat (limited to 'llvm/lib/CodeGen/ReachingDefAnalysis.cpp')
0 files changed, 0 insertions, 0 deletions