This is an archive of the discontinued LLVM Phabricator instance.

Replace uint64_t representation of Features with FeatureBitset (std::bitset) in a few more places
ClosedPublic

Authored by rs on Jun 18 2015, 9:49 AM.

Details

Summary

This patch replaces uses of uint64_t to represent target features with FeatureBitset in a few places where it hasn't been replaced.

Diff Detail

Event Timeline

rs updated this revision to Diff 27942.Jun 18 2015, 9:49 AM
rs retitled this revision from to Replace uint64_t representation of Features with FeatureBitset (std::bitset) in a few more places.
rs updated this object.
rs edited the test plan for this revision. (Show Details)
rs added a subscriber: Unknown Object (MLST).
mkuper edited edge metadata.Jun 20 2015, 9:00 AM

Thanks!

I originally only converted the subtarget features, but not the available features, since, at least on x86, only a small subset of subtarget features actually participate in that, so it didn't look like it was running out. There's was no good reason for that, though.

Anyway, lgtm with a couple of nits.

lib/Target/X86/AsmParser/X86AsmParser.cpp
2626

Can probably remove the comment. :-)

utils/TableGen/AsmMatcherEmitter.cpp
2257

I'm not sure we need to make this take a bitset.
It's supposed to take a single feature value, right?

With the previous interface, a uint64_t stood for both a single value and a set, but now the two are different. We can still use a uint64_t for a single value, however, it's just that it's now an ordinal number instead of a bit.

rs added a comment.Jun 22 2015, 3:46 AM

Thanks for the review Michael.

lib/Target/X86/AsmParser/X86AsmParser.cpp
2626

Will do :)

utils/TableGen/AsmMatcherEmitter.cpp
2257

The call sites of this function have always passed a bitset, here is a snippet of the previous code that was calling this function:

uint64_t Mask = 1;
for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
  if (ErrorInfo & Mask) {
    Msg += " ";
    Msg += getSubtargetFeatureName(ErrorInfo & Mask);
  }
  Mask <<= 1;
}

If it's supposed to take the bit position then shouldn't there be another variable to keep count on which bit they're currently on in the loop (e.g. 'int BitPos = 0') and pass that variable to 'getSubtargetFeatureName' ?

Maybe it would be good to change the name of the argument to 'Feature' instead of having it as 'Val' to make it more clear.

mkuper added inline comments.Jun 22 2015, 4:13 AM
utils/TableGen/AsmMatcherEmitter.cpp
2257

Well, it's not really passing a bitset.
I mean, it is passing a bitset, but it's passing a bitset with a single bit set - since that's what Mask is.
In any case, the function definitely doesn't expect anything else. E.g. this is what we have for x86:

static const char *getSubtargetFeatureName(uint64_t Val) {
  switch(Val) {
  case Feature_HasAVX512: return "AVX-512 ISA";
  case Feature_HasCDI: return "AVX-512 CD ISA";
  case Feature_HasPFI: return "AVX-512 PF ISA";
  case Feature_HasERI: return "AVX-512 ER ISA";
  case Feature_HasDQI: return "AVX-512 DQ ISA";
  case Feature_HasBWI: return "AVX-512 BW ISA";
  case Feature_HasVLX: return "AVX-512 VL ISA";
  case Feature_Not64BitMode: return "Not 64-bit mode";
  case Feature_In64BitMode: return "64-bit mode";
  case Feature_In16BitMode: return "16-bit mode";
  case Feature_Not16BitMode: return "Not 16-bit mode";
  case Feature_In32BitMode: return "32-bit mode";
  default: return "(unknown)";
  }
}

I think you can just rewrite the caller loop as something like (I'm not sure I don't have any off-by-ones here):

for (unsigned i = 0; i < ErrorInfo.size(); ++i) {
  if (ErrorInfo[i]) {
    Msg += " ";
    Msg += getSubtargetFeatureName(Mask);
  }
}

And, yes, changing the name from Val to Feature is probably a good idea.

rs added inline comments.Jun 22 2015, 5:01 AM
utils/TableGen/AsmMatcherEmitter.cpp
2257

Just to confirm you want the function to be changed back to how it was originally to accept a uint64_t type?

I think you can just rewrite the caller loop as something like (I'm not sure I don't have any off-by-ones here):

OK.

mkuper added inline comments.Jun 22 2015, 5:07 AM
utils/TableGen/AsmMatcherEmitter.cpp
2257

Yes.

I just don't see why it should take a set - I think that's confusing, since the pre-condition would have to be that this set has only one bit on.
But if you have a good reason for it to take a set, I'm ok with that too.

rs updated this revision to Diff 28221.Jun 23 2015, 4:40 AM
rs removed reviewers: jmolloy, john.brawn, rengolin.

Hi Michael,

I've made the changes, please could you have another look?

Thanks,
Ranjeet

Hm. I've read the patch more carefully, and I'm actually somewhat confused now.

Each target has two enumerations:

  1. SubtargetFeatureFlag - this is used, I think, only by the AsmParser, and has elements that look like Feature_HasAVX512.

This one still lives in a regular bitfield, not a bitset, so the elements of the enum are of them form "1 << C".
If I'm not mistaken, ComputeAvailableFeatures() returns a set of these values.

  1. A nameless enum used everywhere else, which has elements that look like X86::FeatureAVX512.

I've changed this enum in my original patch, and now these are ordinal values (1, 2, 3... etc.), instead of powers of 2.

Now, it looks like what you did was to change everything that used bitfields containing SubtargetFeatureFlag to use a FeatureBitset instead. But the values themselves are still powers of 2, so you are still bound by the limits of the underlying type.

Is that right? If it is, then what is the goal of this patch?
If not, then I misunderstood the patch. Could you explain again what it's trying to achieve?

rs added a comment.Jun 23 2015, 8:39 AM

Hm. I've read the patch more carefully, and I'm actually somewhat confused now.

Each target has two enumerations:

  1. SubtargetFeatureFlag - this is used, I think, only by the AsmParser, and has elements that look like Feature_HasAVX512.

This one still lives in a regular bitfield, not a bitset, so the elements of the enum are of them form "1 << C".
If I'm not mistaken, ComputeAvailableFeatures() returns a set of these values.

  1. A nameless enum used everywhere else, which has elements that look like X86::FeatureAVX512.

I've changed this enum in my original patch, and now these are ordinal values (1, 2, 3... etc.), instead of powers of 2.

Now, it looks like what you did was to change everything that used bitfields containing SubtargetFeatureFlag to use a FeatureBitset instead. But the values themselves are still powers of 2, so you are still bound by the limits of the underlying type.

Is that right? If it is, then what is the goal of this patch?

I missed the fact that the SubtargetFeatureFlags enums are still powers of 2, I should have changed it so that they are ordinal numbers the same way you did it in your original patch because it's possible that the enum list could grow to >64 entries.

Thanks,
Ranjeet

rs updated this revision to Diff 28465.Jun 25 2015, 8:00 AM

Hi Michael,

I've update the patch so that SubtargetFeatureFlags enums are ordinal numbers rather than powers of 2. Please could you review the patch?

Thanks,
Ranjeet

Ok, this looks right - with a couple of new nits. :-)

lib/Target/ARM/AsmParser/ARMAsmParser.cpp
9919

Extra space here?

lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
804–805

Are you sure about the "-1"?
(Then again, I don't understand why the original -1 was there either...)

lib/Target/X86/AsmParser/X86AsmParser.cpp
2549–2551

Same as above re -1.

rs updated this revision to Diff 28667.Jun 29 2015, 7:21 AM

Hi Michael,

Extra space here?

Nice spot, I've removed it.

Are you sure about the "-1"?
(Then again, I don't understand why the original -1 was there either...)

No, I'm not sure about it, it was inherited from the previous code. I can't find a reason as to why it was there so I've removed it.

Thanks,
Ranjeet

mkuper accepted this revision.Jun 30 2015, 1:07 AM
mkuper edited edge metadata.

LGTM

This revision is now accepted and ready to land.Jun 30 2015, 1:07 AM
This revision was automatically updated to reflect the committed changes.