This is an archive of the discontinued LLVM Phabricator instance.

[x86] Fix nasty bug in the x86 backend that is essentially impossible to hit from IR but creates a minefield for MI passes.
ClosedPublic

Authored by chandlerc on Jan 31 2018, 4:36 AM.

Details

Summary

The x86 backend has fairly powerful logic to try and fold loads that
feed register operands to instructions into a memory operand on the
instruction. This is almost always a good thing, but there are specific
relocated loads that are only allowed to appear in specific
instructions. Notably, R_X86_64_GOTTPOFF is only allowed in movq and
addq. This patch blocks folding of memory operands using this
relocation unless the target is in fact addq.

The particular relocation indicates why we simply don't hit this under
normal circumstances. This relocation is only used for TLS, and it gets
used in very specific ways in conjunction with %fs-relative addressing.
The result is that loads using this relocation are essentially never
eligible for folding into an instruction's memory operands. Unless, of
course, you have an MI pass that inserts usage of such a load. I have
exactly such an MI pass and was greeted by truly mysterious miscompiles
where the linker replaced my instruction with a completely garbage byte
sequence. Go team.

This is the only such relocation I'm aware of in x86, but there may be
others that need to be similarly restricted.

Fixes PR36165.

Note, I have no real idea how I *should* be testing this or *should* be
implementing this. It is essentially a stab in the dark. Please feel free to
suggest more effective ways to test, implement, or otherwise go about this.

Diff Detail

Repository
rL LLVM

Event Timeline

chandlerc created this revision.Jan 31 2018, 4:36 AM
probinson added inline comments.
llvm/test/CodeGen/X86/bad-tls-fold.mir
19 ↗(On Diff #132141)

Drive-by nit: You don't need the poorly named -LABEL suffix (it doesn't actually identify labels).

41 ↗(On Diff #132141)

No need for -LABEL here.

chandlerc added inline comments.Jan 31 2018, 11:14 AM
llvm/test/CodeGen/X86/bad-tls-fold.mir
19 ↗(On Diff #132141)

I don't understand...

My understanding of CHECK-LABEL is that it partitions the CHECK-reported errors so that its easier to understand them. I want that partition to hook on the label or rather than the orq instruction, or some other use of the word or, so it seems reasonable to include the suffix of :? In IR tests we routinely do CHECK-LABLE: @foo( to ensure we don't match a function by the name of @foo.bar.

41 ↗(On Diff #132141)

As above, I'm not imagining that this is *necessary*, but it seems good hygiene to separate out the blocks of checks.

(Also, thanks for review on my first ever usage of MIR! I have so little idea of what I'm doing with it....)

probinson added inline comments.Jan 31 2018, 11:36 AM
llvm/test/CodeGen/X86/bad-tls-fold.mir
19 ↗(On Diff #132141)

Oh, I didn't notice the other CHECK lines. Duh.
Please make all the CHECK lines use consistent indentation and comment characters to accommodate the eyesight-challenged. :-P

chandlerc added inline comments.Jan 31 2018, 1:35 PM
llvm/test/CodeGen/X86/bad-tls-fold.mir
19 ↗(On Diff #132141)

I would actually love to do this. However, I'm worried that I actually *need* this format... at least, the existing MIR test I cargo culted from had this. I really agree with you, as it took me forever to even find the CHECKs in that test!

Anyways, I'll experiment to see if I can get something more readable and still go through the MIR testing layer.

chandlerc updated this revision to Diff 133169.Feb 7 2018, 1:06 AM

Update to tidy up MIR and reflect a syntax change.

Ping, love to get a review on the actual functionality here....

llvm/test/CodeGen/X86/bad-tls-fold.mir
19 ↗(On Diff #132141)

So, I did the experimentation and now (with some helpful pointers from folks on IRC) I understand why this can't be done.

The CHECK-LABEL entries are YAML comments. But the actual CHECK-NOT entries I want are inside a YAML multi-line scalar and thus cannot use the YAML comment syntax and instead must use a comment syntax recognized by the MIR parser for the multi-line scalar. That's why we node to switch to ; in the middle.

I have out-dented them as much as I can to make them visually distinct, but I can't do that all the way because YAML multiline scalars are identified via their indent.

probinson added inline comments.Feb 7 2018, 1:29 PM
llvm/test/CodeGen/X86/bad-tls-fold.mir
19 ↗(On Diff #132141)

Syntactically significant whitespace, feh. Even COBOL doesn't do that anymore.
Okay, I really appreciate the effort, thanks!

This revision was not accepted when it landed; it landed in state Needs Review.Feb 7 2018, 4:01 PM
This revision was automatically updated to reflect the committed changes.