This is an archive of the discontinued LLVM Phabricator instance.

Normalize the features string in SubtargetFeatures::getFeatureBits
Needs ReviewPublic

Authored by tyomitch on Dec 23 2015, 7:17 AM.

Details

Summary

Currently, specifying a feature string such as +fullfp16,-fp-armv8,+fp-armv8,+neon
leads to fullfp16 being disabled (transitively by -fp-armv8, and not re-enabled
by +fp-armv8).

It would be far more natural to make +fullfp16,-fp-armv8,+fp-armv8,+neon
equivalent to +fullfp16,+neon, matching the intuitive arithmetic and/or set-theory rules.

Note that this still doesn't make feature strings commutative:
e.g. +fullfp16,+fp-armv8,-fp-armv8,+neon would still disable fullfp16.

While there, this patch also changes SubtargetFeatures::ToggleFeature and
SubtargetFeatures::ApplyFeatureFlag to be static, so that MCSubtargetInfo
doesn't need to instantiate SubtargetFeatures for nothing.

Diff Detail

Event Timeline

tyomitch updated this revision to Diff 43536.Dec 23 2015, 7:17 AM
tyomitch retitled this revision from to Normalize the features string in SubtargetFeatures::getFeatureBits.
tyomitch updated this object.
tyomitch added reviewers: mkuper, john.brawn, echristo.
tyomitch added a subscriber: llvm-commits.
mkuper edited edge metadata.Dec 30 2015, 2:00 AM

The changes to SubtargetFeatures::ToggleFeature and SubtargetFeatures::ApplyFeatureFlag LGTM, thanks for making them.

As to the actual patch, I'm not sure whether normalizing like this is really the desired behavior or not.
I'm not against it, as such, but I'd like to hear Eric's opinion.

echristo edited edge metadata.Jan 4 2016, 3:10 PM

Hi,

Couple of things:

a) could you split this out? I agree that the changes to SubtargetFeatures::ToggleFeature and SubtargetFeatures::ApplyFeatureFlag look good and should be committed, but separately since the rest should have some discussion.

b) I agree with the overall notion of this, that said, I think this might be the wrong way to achieve it. How are you getting the feature strings that you're showing here? If you've got a feature that is transitively enabled or disabled by another feature then you've got a set and not a feature and it should probably be split accordingly and not just based on command line option. I think knowing the answer to my first question will show how to proceed here though.

-eric

tyomitch updated this revision to Diff 43980.Jan 5 2016, 3:39 AM
tyomitch edited edge metadata.

Thank you Michael and Eric for your comments!
I've now committed the non-controversial changes as r256823.

How are you getting the feature strings that you're showing here?

We have a sort of testing script which runs LLVM with different
combinations of enabled features, pasting together chunks of
feature strings, each such chunk enabling a different subset
of test cases.

The existing implementation of getFeatureBits lets us "cancel out"
a +feature in a later chunk by appending a -feature; but
it doesn't allow to cancel out a -feature, which is what my
patch tries to achieve.

Ping?

Ping again

I think canceling out may be the wrong way here.

There's a chain of thought here that changes in the middle, let's go through how I was thinking and then rethinking:

Seeing this string:

+fullfp16,-fp-armv8,+fp-armv8,+neon

and knowing that fp-armv8 is a "lower level" fp than fullfp16 I'd expect that at the end we'd have fp-armv8 and neon turned on. Similarly to how if you passed the x86 equivalent on the command line:

-msse4.2 -mno-sse2 -msse3

on the command line and get:

"target-features"="+fxsr,+mmx,+sse,+sse2,+sse3,-aes,-avx,-avx2,-avx512bw,-avx512cd,-avx512dq,-avx512er,-avx512f,-avx512pf,-avx512vl,-f16c,-fma,-fma4,-pclmul,-sha,-sse4.1,-sse4.2,-sse4a,-ssse3,-xop,-xsave,-xsaveopt"

which turns off everything sse2 and below and then turns on eveything up to sse3.

OK, that almost makes sense, however:

As a side, but important, note: I was going to use -mno-sse3 -msse3 as part of this example. It appears that the front end currently will take that as a last one wins and ignore the -mno-sse3. What would happen in your testcase if it were -, -, +? Last one wins?

Do we want last one wins here? Do we want all pairs to be merged and the one that's not a pair gone? Before we handle earlier ones? Ultimately I think we might want to assume that canonicalization has happened before we get to this point, i.e. maybe even disallow attribute strings that turn off features that were explicitly turned on earlier (not implicitly mind).

At any rate, thoughts?

:)

-eric

Thank you Eric for your detailed comments!

Do I understand correctly that this is your main concern:

OK, that almost makes sense, however:

As a side, but important, note: I was going to use -mno-sse3 -msse3 as part of this example. It appears that the front end currently will take that as a last one wins and ignore the -mno-sse3. What would happen in your testcase if it were -, -, +? Last one wins?

Do we want last one wins here? Do we want all pairs to be merged and the one that's not a pair gone? Before we handle earlier ones? Ultimately I think we might want to assume that canonicalization has happened before we get to this point, i.e. maybe even disallow attribute strings that turn off features that were explicitly turned on earlier (not implicitly mind).

That's correct, my patch keeps the existing "last one wins" handling: "+sse3,+sse3,-sse3" would (still) be treated identically to "-sse3".
The only case where "last one wins" doesn't currently apply, is when a super-feature is disabled by disabling a sub-feature, but isn't reenabled afterwards.
In other words, "+fullfp16,-fp-armv8,+fp-armv8" isn't currently equivalent to "+fullfp16,+fp-armv8".
My patch would fix this inconsistency, so that "last one wins" would apply universally.

My patch would fix this inconsistency, so that "last one wins" would apply universally.

Ping?

My patch would fix this inconsistency, so that "last one wins" would apply universally.

Ping?

Ping again

My patch would fix this inconsistency, so that "last one wins" would apply universally.

Ping?

Ping again

Thank you Eric for your detailed comments!

Do I understand correctly that this is your main concern:

OK, that almost makes sense, however:

As a side, but important, note: I was going to use -mno-sse3 -msse3 as part of this example. It appears that the front end currently will take that as a last one wins and ignore the -mno-sse3. What would happen in your testcase if it were -, -, +? Last one wins?

Do we want last one wins here? Do we want all pairs to be merged and the one that's not a pair gone? Before we handle earlier ones? Ultimately I think we might want to assume that canonicalization has happened before we get to this point, i.e. maybe even disallow attribute strings that turn off features that were explicitly turned on earlier (not implicitly mind).

That's correct, my patch keeps the existing "last one wins" handling: "+sse3,+sse3,-sse3" would (still) be treated identically to "-sse3".
The only case where "last one wins" doesn't currently apply, is when a super-feature is disabled by disabling a sub-feature, but isn't reenabled afterwards.
In other words, "+fullfp16,-fp-armv8,+fp-armv8" isn't currently equivalent to "+fullfp16,+fp-armv8".
My patch would fix this inconsistency, so that "last one wins" would apply universally.

I'm still uncertain we want to do this in the backend. I seem to recall you wanting to do this for a reason, but searching my email can't find it. Why can't we rely/assert/verify that the list of features in the list is complete and non-contradictory rather than coping with "garbage" in the backend. This seems like something the front-end, or whatever is generating IR, should handle.

I'm still uncertain we want to do this in the backend. I seem to recall you wanting to do this for a reason, but searching my email can't find it.

How are you getting the feature strings that you're showing here?

We have a sort of testing script which runs LLVM with different
combinations of enabled features, pasting together chunks of
feature strings, each such chunk enabling a different subset
of test cases.

The existing implementation of getFeatureBits lets us "cancel out"
a +feature in a later chunk by appending a -feature; but
it doesn't allow to cancel out a -feature, which is what my
patch tries to achieve.

Why can't we rely/assert/verify that the list of features in the list is complete and non-contradictory rather than coping with "garbage" in the backend. This seems like something the front-end, or whatever is generating IR, should handle.

Pre-parsing the feature string to "sanitize" it is certainly a possibility; my preference for doing this in SubtargetFeatures::getFeatureBits was to reuse the existing feature string parser, and avoid code duplication.

I mean basically not allowing the use that you're trying for there. Any duplications or changes aren't going to matter.

Also, FWIW, any subtarget feature that isn't isolated really isn't good. I.e. you should have to explicitly turn on both fp-armv8 and fullfp16 if you want both enabled.

-eric

mkuper resigned from this revision.Jun 6 2016, 4:48 PM
mkuper removed a reviewer: mkuper.
john.brawn resigned from this revision.May 12 2020, 6:39 AM