-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[CodeGen] Make LoadExtActions address-space aware #162407
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 4 commits
99e87a3
ebcf9ba
5091372
8f51e32
63a5187
113ba86
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1472,27 +1472,38 @@ class LLVM_ABI TargetLoweringBase { | |
| /// Return how this load with extension should be treated: either it is legal, | ||
| /// needs to be promoted to a larger size, needs to be expanded to some other | ||
| /// code sequence, or the target has a custom expander for it. | ||
| LegalizeAction getLoadExtAction(unsigned ExtType, EVT ValVT, | ||
| EVT MemVT) const { | ||
| if (ValVT.isExtended() || MemVT.isExtended()) return Expand; | ||
| unsigned ValI = (unsigned) ValVT.getSimpleVT().SimpleTy; | ||
| unsigned MemI = (unsigned) MemVT.getSimpleVT().SimpleTy; | ||
| LegalizeAction getLoadExtAction(unsigned ExtType, EVT ValVT, EVT MemVT, | ||
| unsigned AddrSpace) const { | ||
|
Comment on lines
+1475
to
+1476
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is too narrowly targeted at ext loads - really we need to know the address space for the legality of all loads (and stores). This has been a big DAG pain point since always (e.g., #90714). Every memory instruction legality query should be a function of the types, address space, and alignment. std::map probably isn't the right way to encode this information either. In GlobalISel you have a chain of arbitrary legalization predicates that can check the address space.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah. The idea was to get it worked out for loads, then move on to (at least) truncating stores. But yeah, they all share the same fundamental flaw
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I noticed that in GISel. That's actually exactly why I started #157161. If not a map, then it seems that maybe getLoadExtAction and the likes should just be a virtual hook? Defaults to Legal, and we just move any exceptions into code in each target? Though that seems like a step backwards... Did you have something particular in mind?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was thinking something like:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So "Custom" is now overloaded to either mean conditionally legal, or actually custom lowered? Could be worse I suppose... Do you have any thoughts on combining That way Custom and Legal remain distinct, there's still a data-driven API for simple existing cases, and we open the doors to more complex predicates. Not quite as elegant as GISel, but an improvement over the status-quo? |
||
| if (ValVT.isExtended() || MemVT.isExtended()) | ||
| return Expand; | ||
| unsigned ValI = (unsigned)ValVT.getSimpleVT().SimpleTy; | ||
| unsigned MemI = (unsigned)MemVT.getSimpleVT().SimpleTy; | ||
| assert(ExtType < ISD::LAST_LOADEXT_TYPE && ValI < MVT::VALUETYPE_SIZE && | ||
| MemI < MVT::VALUETYPE_SIZE && "Table isn't big enough!"); | ||
| unsigned Shift = 4 * ExtType; | ||
|
|
||
| uint64_t OverrideKey = ((uint64_t)(ValI & 0xFF) << 40) | | ||
| ((uint64_t)(MemI & 0xFF) << 32) | | ||
| (uint64_t)AddrSpace; | ||
|
|
||
| if (LoadExtActionOverrides.count(OverrideKey)) { | ||
| return (LegalizeAction)((LoadExtActionOverrides.at(OverrideKey) >> Shift) & 0xf); | ||
| } | ||
| return (LegalizeAction)((LoadExtActions[ValI][MemI] >> Shift) & 0xf); | ||
| } | ||
|
|
||
| /// Return true if the specified load with extension is legal on this target. | ||
| bool isLoadExtLegal(unsigned ExtType, EVT ValVT, EVT MemVT) const { | ||
| return getLoadExtAction(ExtType, ValVT, MemVT) == Legal; | ||
| bool isLoadExtLegal(unsigned ExtType, EVT ValVT, EVT MemVT, | ||
| unsigned AddrSpace) const { | ||
| return getLoadExtAction(ExtType, ValVT, MemVT, AddrSpace) == Legal; | ||
| } | ||
|
|
||
| /// Return true if the specified load with extension is legal or custom | ||
| /// on this target. | ||
| bool isLoadExtLegalOrCustom(unsigned ExtType, EVT ValVT, EVT MemVT) const { | ||
| return getLoadExtAction(ExtType, ValVT, MemVT) == Legal || | ||
| getLoadExtAction(ExtType, ValVT, MemVT) == Custom; | ||
| bool isLoadExtLegalOrCustom(unsigned ExtType, EVT ValVT, EVT MemVT, | ||
| unsigned AddrSpace) const { | ||
| return getLoadExtAction(ExtType, ValVT, MemVT, AddrSpace) == Legal || | ||
| getLoadExtAction(ExtType, ValVT, MemVT, AddrSpace) == Custom; | ||
| } | ||
|
|
||
| /// Same as getLoadExtAction, but for atomic loads. | ||
|
|
@@ -2634,23 +2645,38 @@ class LLVM_ABI TargetLoweringBase { | |
| /// Indicate that the specified load with extension does not work with the | ||
| /// specified type and indicate what to do about it. | ||
| void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, | ||
| LegalizeAction Action) { | ||
| LegalizeAction Action, unsigned AddrSpace = ~0) { | ||
| assert(ExtType < ISD::LAST_LOADEXT_TYPE && ValVT.isValid() && | ||
| MemVT.isValid() && "Table isn't big enough!"); | ||
| assert((unsigned)Action < 0x10 && "too many bits for bitfield array"); | ||
|
|
||
| unsigned Shift = 4 * ExtType; | ||
| LoadExtActions[ValVT.SimpleTy][MemVT.SimpleTy] &= ~((uint16_t)0xF << Shift); | ||
| LoadExtActions[ValVT.SimpleTy][MemVT.SimpleTy] |= (uint16_t)Action << Shift; | ||
|
|
||
| if (AddrSpace == ~((unsigned)0)) { | ||
| LoadExtActions[ValVT.SimpleTy][MemVT.SimpleTy] &= | ||
| ~((uint16_t)0xF << Shift); | ||
| LoadExtActions[ValVT.SimpleTy][MemVT.SimpleTy] |= (uint16_t)Action | ||
| << Shift; | ||
| } else { | ||
| uint64_t OverrideKey = ((uint64_t)(ValVT.SimpleTy & 0xFF) << 40) | | ||
| ((uint64_t)(MemVT.SimpleTy & 0xFF) << 32) | | ||
| (uint64_t)AddrSpace; | ||
| uint16_t &OverrideVal = LoadExtActionOverrides[OverrideKey]; | ||
|
|
||
| OverrideVal &= ~((uint16_t)0xF << Shift); | ||
| OverrideVal |= (uint16_t)Action << Shift; | ||
| } | ||
| } | ||
| void setLoadExtAction(ArrayRef<unsigned> ExtTypes, MVT ValVT, MVT MemVT, | ||
| LegalizeAction Action) { | ||
| LegalizeAction Action, unsigned AddrSpace = ~0) { | ||
| for (auto ExtType : ExtTypes) | ||
| setLoadExtAction(ExtType, ValVT, MemVT, Action); | ||
| setLoadExtAction(ExtType, ValVT, MemVT, Action, AddrSpace); | ||
| } | ||
| void setLoadExtAction(ArrayRef<unsigned> ExtTypes, MVT ValVT, | ||
| ArrayRef<MVT> MemVTs, LegalizeAction Action) { | ||
| ArrayRef<MVT> MemVTs, LegalizeAction Action, | ||
| unsigned AddrSpace = ~0) { | ||
| for (auto MemVT : MemVTs) | ||
| setLoadExtAction(ExtTypes, ValVT, MemVT, Action); | ||
| setLoadExtAction(ExtTypes, ValVT, MemVT, Action, AddrSpace); | ||
| } | ||
|
|
||
| /// Let target indicate that an extending atomic load of the specified type | ||
|
|
@@ -3126,7 +3152,7 @@ class LLVM_ABI TargetLoweringBase { | |
| LType = ISD::SEXTLOAD; | ||
| } | ||
|
|
||
| return isLoadExtLegal(LType, VT, LoadVT); | ||
| return isLoadExtLegal(LType, VT, LoadVT, Load->getPointerAddressSpace()); | ||
| } | ||
|
|
||
| /// Return true if any actual instruction that defines a value of type FromTy | ||
|
|
@@ -3753,8 +3779,11 @@ class LLVM_ABI TargetLoweringBase { | |
| /// For each load extension type and each value type, keep a LegalizeAction | ||
| /// that indicates how instruction selection should deal with a load of a | ||
| /// specific value type and extension type. Uses 4-bits to store the action | ||
| /// for each of the 4 load ext types. | ||
| /// for each of the 4 load ext types. These actions can be specified for each | ||
| /// address space. | ||
| uint16_t LoadExtActions[MVT::VALUETYPE_SIZE][MVT::VALUETYPE_SIZE]; | ||
| using LoadExtActionOverrideMap = std::map<uint64_t, uint16_t>; | ||
| LoadExtActionOverrideMap LoadExtActionOverrides; | ||
|
|
||
| /// Similar to LoadExtActions, but for atomic loads. Only Legal or Expand | ||
| /// (default) values are supported. | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.