This is an archive of the discontinued LLVM Phabricator instance.

[X86] matchAdd: don't fold a large offset into a %rip relative address
ClosedPublic

Authored by MaskRay on Jan 28 2020, 10:13 PM.

Details

Summary

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.

Diff Detail

Event Timeline

MaskRay created this revision.Jan 28 2020, 10:13 PM
Herald added a project: Restricted Project. · View Herald TranscriptJan 28 2020, 10:13 PM

Unit tests: pass. 62283 tests passed, 0 failed and 827 were skipped.

clang-tidy: pass.

clang-format: fail. Please format your changes with clang-format by running git-clang-format HEAD^ or applying this patch.

Build artifacts: diff.json, clang-tidy.txt, clang-format.patch, CMakeCache.txt, console-log.txt, test-results.xml

Pre-merge checks is in beta. Report issue. Please join beta or enable it for your project.

MaskRay updated this revision to Diff 241052.Jan 28 2020, 10:24 PM

Update description

MaskRay updated this revision to Diff 241054.Jan 28 2020, 10:28 PM
MaskRay retitled this revision from [X86] matchAdd: don't fold large displacements to [X86] matchAdd: don't fold a large offset into a %rip relative address.
MaskRay edited the summary of this revision. (Show Details)

Update title

This revision was not accepted when it landed; it landed in state Needs Review.Jan 28 2020, 10:34 PM
This revision was automatically updated to reflect the committed changes.

Unit tests: pass. 62283 tests passed, 0 failed and 827 were skipped.

clang-tidy: pass.

clang-format: fail. Please format your changes with clang-format by running git-clang-format HEAD^ or applying this patch.

Build artifacts: diff.json, clang-tidy.txt, clang-format.patch, CMakeCache.txt, console-log.txt, test-results.xml

Pre-merge checks is in beta. Report issue. Please join beta or enable it for your project.

Unit tests: pass. 62283 tests passed, 0 failed and 827 were skipped.

clang-tidy: pass.

clang-format: fail. Please format your changes with clang-format by running git-clang-format HEAD^ or applying this patch.

Build artifacts: diff.json, clang-tidy.txt, clang-format.patch, CMakeCache.txt, console-log.txt, test-results.xml

Pre-merge checks is in beta. Report issue. Please join beta or enable it for your project.

Unit tests: pass. 62283 tests passed, 0 failed and 827 were skipped.

clang-tidy: pass.

clang-format: fail. Please format your changes with clang-format by running git-clang-format HEAD^ or applying this patch.

Build artifacts: diff.json, clang-tidy.txt, clang-format.patch, CMakeCache.txt, console-log.txt, test-results.xml

Pre-merge checks is in beta. Report issue. Please join beta or enable it for your project.

absl/hash/internal/hash.h takes the address of a static variable absl::hash_internal::CityHashState::kSeed:

ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t Seed() {
  return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(kSeed));
}
static const void* const kSeed;

With certain LTO optimizations, the address can be added to a large constant 1701208431. It is similar to ret i64 add (i64 ptrtoint (i32* @foo to i64), i64 1701208431).
Before this patch, we could produce an instruction like leaq kSeed+1701208431(%rip), %rax. At the linking stage, it is an R_X86_64_PC32 relocation overflow if kSeed-rip+1701208431 >= 0x80000000. This means kSeed-rip cannot be larger than 0x80000000-1701208431=0x1a999e91. This upper bound is not large, and some large programs can exceed the bound.