This is an archive of the discontinued LLVM Phabricator instance.

[AMDGPU] Simplify getNumFlatOffsetBits. NFC.
ClosedPublic

Authored by foad on Jan 3 2023, 5:04 AM.

Details

Summary

Previously we considered this field to be either N-bit unsigned or
N+1-bit signed, depending on the instruction. I think it's conceptually
simpler to say that the field is always N+1-bit signed, but some
instructions do not allow negative values.

Diff Detail

Event Timeline

foad created this revision.Jan 3 2023, 5:04 AM
Herald added a project: Restricted Project. · View Herald TranscriptJan 3 2023, 5:04 AM
foad requested review of this revision.Jan 3 2023, 5:04 AM
Herald added a project: Restricted Project. · View Herald TranscriptJan 3 2023, 5:04 AM
foad added reviewers: Restricted Project, matejam, piotr.Jan 3 2023, 5:05 AM
kosarev added inline comments.Jan 3 2023, 5:42 AM
llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
7968

Is this actually an improvement? Wouldn't it be conceptually simpler to pass FlatVariant and get the actual width and, if needed, signedness?

foad added a comment.Jan 3 2023, 6:07 AM

Is this actually an improvement?

I think so (of course!) because it simplifies getNumFlatOffsetBits without making its callers more complicated.

Wouldn't it be conceptually simpler to pass FlatVariant and get the actual width and, if needed, signedness?

Not sure what you mean by "actual width" here. I would not want to revert to getNumFlatOffsetBits returning different values for different flat variants on the same subtarget. But I suppose an additional patch to make getNumFlatOffsetBits return the "AllowNegative" flag as well as the field width might be an improvement.

arsenm added inline comments.Jan 3 2023, 6:35 AM
llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
7942

I don't really like the AllowNegative naming. SignBitIgnored?

llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
2507–2510

Can return ternary operator

By actual width I mean what can be passed to isIntN()/isUInt() without adjustments. The AllowNegative thing feels a bit alien to the ISA, effectively adding an extra concept while not eliminating the need for adjustments. Signedness, in contrast, looks rather natural and familiar, and if (Signed ? isIntN(...) : isUIntN(...)) is probably easier to understand than if (!isIntN(...) || (!AllowNegative && Op.getImm() < 0)).

foad added a comment.Jan 3 2023, 6:49 AM

The AllowNegative thing feels a bit alien to the ISA, effectively adding an extra concept while not eliminating the need for adjustments.

Then I think we simply disagree about which one is conceptually simpler.

llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
7942

I don't think "ignored" is right. In at least some cases (like hasNegativeScratchOffsetBug) it is definitely not ignored but leads to wrong behaviour.

Is this actually an improvement?

I think so (of course!) because it simplifies getNumFlatOffsetBits without making its callers more complicated.

I agree that it is a bit simpler to conceptualize it as a signed field with a common size, especially as we already have to think about the "negative scratch offset bug" for some "signed" versions of the field. At that point, might as well just say it is always a signed field, and negative values are sometimes illegal.

Wouldn't it be conceptually simpler to pass FlatVariant and get the actual width and, if needed, signedness?

Not sure what you mean by "actual width" here. I would not want to revert to getNumFlatOffsetBits returning different values for different flat variants on the same subtarget. But I suppose an additional patch to make getNumFlatOffsetBits return the "AllowNegative" flag as well as the field width might be an improvement.

+1 to returning AllowNegative from getNumFlatOffsetBits, especially with structured bindings making it less awkward:

auto [OffsetSize, AllowNegative] = AMDGPU::getNumFlatOffsetBits(getSTI(), TSFlags);
llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
4119
4120–4121

If the MSB is not always ignored, this comment should be updated/deleted

I agree that it is a bit simpler to conceptualize it as a signed field with a common size, especially as we already have to think about the "negative scratch offset bug" for some "signed" versions of the field. At that point, might as well just say it is always a signed field, and negative values are sometimes illegal.

The advantage of the original code is that it encapsulates (apart from the signedness and bug-handling bits, sadly) these specifics in a single place, getNumFlatOffsetBits(), whereas the proposed version effectively lets them leak to the surrounding logic. So on generating the error particularly the new code translates the signed non-negatives back to the precision-and-signedness representation.

foad added a comment.Jan 4 2023, 3:47 AM

So on generating the error particularly the new code translates the signed non-negatives back to the precision-and-signedness representation.

I only did that to make the patch NFC including the text of error messages. Really I'd prefer to reword the error message too, to something like "expected an N-bit signed offset" or "expected a non-negative N-bit signed offset".

llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
4120–4121

In the absence of hardware bugs this might be true; I really don't know. I will see if I can find some good documentation.

OTOH it is not a very useful comment for us, since the compiler never needs to rely on the bit being "ignored and forced to zero".

"expected a non-negative N-bit signed offset"

Might be worth ruminating on whether that would be an improvement as well before moving forward with this patch, on which, apart from noting that silicon-level bugs are probably not the best reasoning for user-exposed conceptual models, I've decided to have no opinion. :)

Things to take into consideration: that the offset bug will retire at some point and the chance for the hardware to support other offset representations in the future.

I agree that it is a bit simpler to conceptualize it as a signed field with a common size, especially as we already have to think about the "negative scratch offset bug" for some "signed" versions of the field. At that point, might as well just say it is always a signed field, and negative values are sometimes illegal.

The advantage of the original code is that it encapsulates (apart from the signedness and bug-handling bits, sadly) these specifics in a single place, getNumFlatOffsetBits(), whereas the proposed version effectively lets them leak to the surrounding logic. So on generating the error particularly the new code translates the signed non-negatives back to the precision-and-signedness representation.

I'm not sure I follow the argument here, as the only thing being encapsulated is the field size as a function of the signedness, but you immediately say the signedness is sadly not encapsulated. What is being encapsulated more completely in the old version?

"expected a non-negative N-bit signed offset"

Might be worth ruminating on whether that would be an improvement as well before moving forward with this patch, on which, apart from noting that silicon-level bugs are probably not the best reasoning for user-exposed conceptual models, I've decided to have no opinion. :)

Things to take into consideration: that the offset bug will retire at some point and the chance for the hardware to support other offset representations in the future.

I think this is the most compelling argument for leaving things as they are, along with the fact that anything we change here adds a small gap between the compiler writer/user's model and the model that the hardware specs document.

I agree that it is a bit simpler to conceptualize it as a signed field with a common size, especially as we already have to think about the "negative scratch offset bug" for some "signed" versions of the field. At that point, might as well just say it is always a signed field, and negative values are sometimes illegal.

The advantage of the original code is that it encapsulates (apart from the signedness and bug-handling bits, sadly) these specifics in a single place, getNumFlatOffsetBits(), whereas the proposed version effectively lets them leak to the surrounding logic. So on generating the error particularly the new code translates the signed non-negatives back to the precision-and-signedness representation.

I'm not sure I follow the argument here, as the only thing being encapsulated is the field size as a function of the signedness, but you immediately say the signedness is sadly not encapsulated. What is being encapsulated more completely in the old version?

"expected a non-negative N-bit signed offset"

Might be worth ruminating on whether that would be an improvement as well before moving forward with this patch, on which, apart from noting that silicon-level bugs are probably not the best reasoning for user-exposed conceptual models, I've decided to have no opinion. :)

Things to take into consideration: that the offset bug will retire at some point and the chance for the hardware to support other offset representations in the future.

I think this is the most compelling argument for leaving things as they are, along with the fact that anything we change here adds a small gap between the compiler writer/user's model and the model that the hardware specs document.

Also, just to clarify, even in light of the arguments against it I still vote for the change being made.

scott.linder accepted this revision.Jan 11 2023, 11:25 AM

LGTM

I'm open to renaming things, but I think AllowNegative is at least as clear as anything I can think of.

This revision is now accepted and ready to land.Jan 11 2023, 11:25 AM
This revision was automatically updated to reflect the committed changes.