This is an archive of the discontinued LLVM Phabricator instance.

[AIX] "aligned" attribute does not decrease alignment
ClosedPublic

Authored by stevewan on Aug 3 2021, 1:03 PM.

Details

Summary

The "aligned" attribute can only increase the alignment of a struct, or struct member, unless it's used together with the "packed" attribute, or used as a part of a typedef, in which case, the "aligned" attribute can both increase and decrease alignment.

That said, we expect:

  1. "aligned" attribute alone: does not interfere with the alignment upgrade instrumented by the AIX "power" alignment rule,
  2. "aligned" attribute + typedef: overrides any computed alignment,
  3. "aligned" attribute + "packed" attribute: overrides any computed alignment.

The old implementation achieved 2 and 3, but didn't get 1 right, in that any field marked attribute "aligned" would not go through the alignment upgrade.

Diff Detail

Event Timeline

stevewan requested review of this revision.Aug 3 2021, 1:03 PM
stevewan created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptAug 3 2021, 1:03 PM
Herald added a subscriber: cfe-commits. · View Herald Transcript
stevewan updated this revision to Diff 363860.Aug 3 2021, 1:16 PM

Attr 'packed' is already taken into account in ABIAlign/PreferredAlign

stevewan updated this revision to Diff 363870.Aug 3 2021, 1:33 PM

Fix incomplete diff, please discard last update.

sfertile added inline comments.Aug 4 2021, 10:06 AM
clang/test/Layout/aix-alignof-align-and-pack-attr.cpp
11

Minor nit: I think the other test can live in this file, highlighting the difference between the 2 cases is nice. Also I think we should add a typedef test in here as well.

stevewan updated this revision to Diff 364186.Aug 4 2021, 10:47 AM

Merge tests into one file

stevewan marked an inline comment as done.Aug 4 2021, 11:20 AM
stevewan added inline comments.
clang/test/Layout/aix-alignof-align-and-pack-attr.cpp
11

Merged the tests as suggested. We have the typedef coverage in aix-power-alignment-typedef.cpp and aix-power-alignment-typedef2.cpp, not sure if want to merge those as well.

Thanks Steven, LGTM.

clang/test/Layout/aix-alignof-align-and-pack-attr.cpp
11

No need to merge those as well.

stevewan updated this revision to Diff 364350.Aug 4 2021, 10:40 PM
stevewan marked an inline comment as done.

Fix the same problem in field layout.

stevewan updated this revision to Diff 364359.Aug 4 2021, 10:56 PM

Add test cases

stevewan planned changes to this revision.Aug 6 2021, 11:22 AM

The query portion has been split out as https://reviews.llvm.org/D107598, which needs to be cleaned out from this patch. The record layout part also needs update as we uncover more problems with the current implementation.

stevewan updated this revision to Diff 366051.Aug 12 2021, 11:24 AM

Rebase to latest main

stevewan edited the summary of this revision. (Show Details)Aug 18 2021, 1:03 PM
stevewan added reviewers: eli.friedman, jyknight.
stevewan updated this revision to Diff 367312.Aug 18 2021, 1:10 PM

Fields marked attribute "aligned" and "packed" don't need to go through alignment upgrade

rjmccall added inline comments.Aug 18 2021, 2:36 PM
clang/lib/AST/RecordLayoutBuilder.cpp
1975

Okay, so first off, the comment and variable names here make this sound very general when in fact this computation is only relevant to the AIX alignment upgrade logic. Also, please do not introduce new variables with broad scope named things like Ty that are actually referring to a very specific type and not, say, the unadulterated type of the field.

It seems to me that the right way to think about this is that, while the AIX power alignment upgrade considers whether field type alignment is "required", it uses a different condition than the standard rule when making that decision. It's important to understand what that rule is exactly, and we can't see that from the current test cases. In particular, attributes on fields that define structs inline actually end up applying to both the field and the struct, which confounds unrelated issues. Consider:

struct __attribute__((packed, aligned(2))) SS {
  double d;
};

struct S {
  // Neither the field nor the struct are packed, but the field type is.
  // Do we apply the alignment upgrade to S or not?
  struct SS s;
};

Regardless, I don't think this check for a typedef works; it's bypassing quite a bit of recursive logic for computing whether type alignment is required. For example, you could have an explicitly aligned typedef of an array type, and you'll lose that typedef here.

stevewan updated this revision to Diff 367833.Aug 20 2021, 10:49 AM

Address comments about the check

stevewan added inline comments.Aug 20 2021, 10:58 AM
clang/lib/AST/RecordLayoutBuilder.cpp
1975

Thanks for the review.

the comment and variable names here make this sound very general when in fact this computation is only relevant to the AIX alignment upgrade logic.

Moved the variable declarations back to the AIX alignment upgrade logic.

It's important to understand what that rule is exactly, and we can't see that from the current test cases.

Updated the test cases accordingly.

For example, you could have an explicitly aligned typedef of an array type, and you'll lose that typedef here.

Updated the check to examine the immediate type rather than the base element type, this should take care of the array-type considerations.

stevewan updated this revision to Diff 367875.Aug 20 2021, 1:03 PM

De-Morgan-ize if condition for readability

rjmccall added inline comments.Aug 23 2021, 7:51 PM
clang/lib/AST/RecordLayoutBuilder.cpp
1975

No, I'm not sure that's quite correct, either, because you might have an array of an explicitly aligned typedef. You might need to do a recursive examination of the type the same way that getTypeInfo would, except I guess not recursing into records.

I assume you verified that the behavior in your new test cases matches the behavior of some existing AIX compiler? For our general edification, what compiler(s) are you testing against?

I've found that extracting very complex conditions into a function (perhaps a lambda if it's inconvenient to have it separately-declared) can be useful.

stevewan updated this revision to Diff 368702.Aug 25 2021, 12:12 PM

Add recursive check for typedef

stevewan marked 2 inline comments as done.Aug 25 2021, 12:29 PM
stevewan added inline comments.
clang/lib/AST/RecordLayoutBuilder.cpp
1975

Added a lambda function that mimics getTypeInfo to do the recursive check. If this looks about right in direction, I'm also going to memorize known types' typedef-ness in a map for faster lookup.

Yes, the behaviour was verified, and matches the behaviour of XL 16.1 on AIX.

stevewan updated this revision to Diff 368716.Aug 25 2021, 1:40 PM
stevewan marked an inline comment as done.

Avoid unannotated fall-through between cases

rjmccall added inline comments.Aug 27 2021, 12:24 AM
clang/lib/AST/RecordLayoutBuilder.cpp
1997

Hah. The knot-tying here is really cute, but I think either just make it a static function somewhere in the file, or make it iterative instead of recursive.

...actually, I think it would be better to just make the computation in getTypeInfo preserve more information. Make TypeInfo carry a three-valued enum instead of an AlignIsRequired flag:

enum class AlignRequirement {
  /// The alignment was not explicit in code.
  None,

  /// The alignment comes from an alignment attribute on a typedef.
  RequiredByTypedef,

  /// The alignment comes from an alignment attribute on a record type.
  RequiredByRecord,
};

You can add a method on TypeInfo to ask if the alignment is required for any reason and make all the existing clients use that instead.

stevewan updated this revision to Diff 369157.Aug 27 2021, 12:05 PM

Make TypeInfo carry more information about "aligned" attribute

stevewan marked an inline comment as done.Aug 27 2021, 12:19 PM
stevewan added inline comments.
clang/lib/AST/RecordLayoutBuilder.cpp
1997

Good idea. I had thought about a similar approach but was afraid that the change may get too pervasive. I think it turned out fine. I'm now debating whether I should split this whole bool-to-enum change into a separate patch, any preference?

Thanks, style suggestion aside, this looks great. Would you mind doing the TypeInfo change in a separate patch? The functional change for AIX can be a really small improvement on top of that.

clang/include/clang/AST/ASTContext.h
167 ↗(On Diff #369157)

We've been calling things like this FooKind for a while. FooType is pretty problematic in a compiler where we have a lot of type representations. I think there are a few grandfathered exceptions, but still, let's call it AlignRequirementKind.

stevewan updated this revision to Diff 369163.Aug 27 2021, 12:45 PM
stevewan marked an inline comment as done.

Cleanup the condition check

stevewan updated this revision to Diff 369177.Aug 27 2021, 1:53 PM

Fix missing "&&"

Please add me to the review for the other patch and I'll approve it pretty quickly, and then we can get back to this one.

Please add me to the review for the other patch and I'll approve it pretty quickly, and then we can get back to this one.

Sorry for the delay. Posted https://reviews.llvm.org/D108858, once that's in I'll rebase.

stevewan updated this revision to Diff 369293.Aug 28 2021, 5:01 PM

Adapt to new TypeInfo design

Thanks, this looks a lot cleaner. Minor requests only.

rjmccall added inline comments.Aug 28 2021, 8:25 PM
clang/lib/AST/RecordLayoutBuilder.cpp
1975

Somehow my requests didn't make it through. Please name this lambda something AIX-specific, and please clarify in a comment that we can ignore enum alignment sources because the alignment upgrade only applies to floating-point types.

stevewan updated this revision to Diff 369319.Aug 29 2021, 7:15 AM

Rename lambda and add comments

rjmccall accepted this revision.Aug 29 2021, 11:12 AM

Thanks, LGTM!

This revision is now accepted and ready to land.Aug 29 2021, 11:12 AM
This revision was automatically updated to reflect the committed changes.