This is an archive of the discontinued LLVM Phabricator instance.

[SystemZ] Don't emit PC-relative memory accesses to unaligned (packed) symbols.
ClosedPublic

Authored by jonpa on Sep 11 2020, 6:25 AM.

Details

Summary

In the presence of packed structures (#pragma pack(1)) where elements are referenced through pointers, there will be stores/loads with alignment values matching the default alignments for the element types while the elements are in fact unaligned. Strictly speaking this is incorrect source code, but is unfortunately part of existing code and therefore now addressed.

This patch improves the pattern predicate for PC-relative loads and stores by not only checking the alignment value of the instruction, but also making sure that the symbol (and element) itself is aligned.

Fixes https://bugs.llvm.org/show_bug.cgi?id=44405

Diff Detail

Event Timeline

jonpa created this revision.Sep 11 2020, 6:25 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 11 2020, 6:25 AM
Herald added a subscriber: hiraditya. · View Herald Transcript
jonpa requested review of this revision.Sep 11 2020, 6:25 AM
uweigand added inline comments.Sep 11 2020, 7:04 AM
llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
1472

I don't think we need to check PCREL here, that should already be handled by the pattern (and has nothing to do with alignment, really).

1476

Well, there could still be an unaligned offset. I think this check needs to be done after the offset check.

jonpa updated this revision to Diff 293448.Sep 22 2020, 7:02 AM

Updated per review (see inline comments).

llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
1472

I see it as needed because TableGen emits the code in SystemZGenDAGISel.inc in such a way that storeLoadIsAligned() is called before selectPCRelAddress(). That means that a lot of different addresses other than PCREL will show up, which needs to be filtered away.

1476

It seems that a load from CP is not a GlobalAddress, but there should still the possibility of an immediate offset reflected in the MMO. I added a check for this.

It seems safest to check both these offsets independently when they are present.

uweigand added inline comments.Sep 28 2020, 9:26 AM
llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
1472

I still don't understand why this "needs to be filtered away" here. Why can't this routine simply return true/false depending on whether the argument is aligned, no matter what operand it gets?

1476

OK.

1496

You check for the GA == nullptr case above, don't we need to check this here as well?

1502

Maybe the whole thing would be a bit clearer if you grouped the tests by category, e.g. first to all tests on the MemAccess itself, followed by tests on the MMO, followed by tests on the GA/GV? That might also eliminate duplicate nullptr checks.

jonpa updated this revision to Diff 294918.Sep 29 2020, 2:57 AM

Updated per review.

Checking a GlobalAddress without an explicit check for a PCREL_ BasePtr is now done instead by assuming that this will always be in the first operand of BasePtr. Not sure if this is better... Perhaps better to either assume that all GlobalAddress nodes are lowered with a PCREL_ node (call isPCRel()), or maybe check *all* operands of BasePtr for a GlobalAddress?

llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
1472

My idea was to keep it simple by making a function for just the PCRel loads/stores since they are the only ones that have the alignment requirement.

The PCREL_ nodes make it natural to treat these accesses separately from other accesses.

I suppose returning "false" if it is not a PCREL_ node is not very logical, so I can try to avoid this check instead...

1502

OK, I'll try that

uweigand accepted this revision.Sep 29 2020, 4:31 AM

LGTM now, thanks!

This revision is now accepted and ready to land.Sep 29 2020, 4:31 AM