-
Notifications
You must be signed in to change notification settings - Fork 10.8k
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
Correctly set pointer bit for aggregate values in SelectionDAGBuilder to fix CCIfPtr #70554
base: main
Are you sure you want to change the base?
Correctly set pointer bit for aggregate values in SelectionDAGBuilder to fix CCIfPtr #70554
Conversation
There are failing tests (lld/test/ELF/lto/exclude-libs-libcall.ll and lld/test/ELF/lto/version-libcall.ll), but they do not contain pointer values and I don't see how they might be related. Could they be unrelated? |
Also, in TargetLoweringBase I found one case where an ArgFlags struct is built for output arguments. Here llvm-project/llvm/lib/CodeGen/TargetLoweringBase.cpp Lines 1711 to 1758 in 497b2eb
I am not sure whether this is intentional, or an omission. I could add it if desired, but I was not sure when this function is used, exactly. |
The isPointer field is a relatively new hack, most places probably were never updated to set it without a motivating example. It should be consistently respected. Ideally we would move all of this code to use LLT to ease the GlobalISel transition which would directly preserve the pointeriness. This version looks like it's mostly for FastISel. PPC seems to be using it for tail call eligibility checks, and AArch64 seems to use it to set one field in MachineFunctionInfo (which I think it could avoid) |
@@ -75,20 +75,23 @@ void ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL, Type *Ty, | |||
SmallVectorImpl<uint64_t> *FixedOffsets, | |||
uint64_t StartingOffset); | |||
|
|||
/// Variant of ComputeValueVTs that also produces the memory VTs. | |||
/// Variant of ComputeValueVTs that also produces the memory VTs and VT types. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't particularly like using a new output for the Types. The Types should be redundant with EVT (which sometimes do contain a Type* reference). The current hack unnaturally separates the pointer information in the ArgFlags. I believe you can always infer the pointer type from the underlying IR argument at the use point, although that will be really annoying for nested structs.
Long term we should have one of these that returns LLTs instead of EVT, that will preserve the pointer information.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@arsenm Thanks for the review! If I'm understanding the code correctly, EVTs do contain Type* references, but the EVT created for pointers in ComputeValueVTs is an integer type (MVT::getIntegerVT(DL.getPointerSizeInBits(AS))
). I don't see a way to easily use the LLVMTy in EVTs for this purpose, but I may very well be mistaken.
It is possible to remove this logic from ComputeValueVTs and have a separate function to flatten the IR type. But there is quite a number of cases where this needs to be done, and the logic is identical to the one in ComputeValueVTs. If you think it preferable to do this, I would be happy to implement it, but I just want to make sure I'm understanding you correctly.
I would also be happy to implement a ComputeValueVTs variant for LLTs if you're going to need that for other things anyway. I don't really know what the GlobalISel transition is though and how involved this would be.
I'm assuming returning booleans (true for pointers) rather than Type*s from ComputeValueVTs does not really make things better for you? This was suggested by phoebewang in the linked issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@arsenm If you have time, could you still have a look and let me know what approach you'd prefer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, the EVTs do unfortunately squash away the pointer types (because they also resolve to integer MVTs, the Type* is dropped). I meant more the other direction, would it work to change this to return the aggregate split Type s instead of the EVT? The client would then have a thin Type->EVT wrapper
a200429
to
efeef7b
Compare
✅ With the latest revision this PR passed the C/C++ code formatter. |
efeef7b
to
36d218b
Compare
if (Ty->isPointerTy()) { | ||
MyFlags.Flags.setPointer(); | ||
MyFlags.Flags.setPointerAddrSpace( | ||
cast<PointerType>(Ty)->getAddressSpace()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dyn_cast to PointerType instead of isPointerTy+cast (though I guess this is already pre-existing in the other cases)
@@ -75,20 +75,23 @@ void ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL, Type *Ty, | |||
SmallVectorImpl<uint64_t> *FixedOffsets, | |||
uint64_t StartingOffset); | |||
|
|||
/// Variant of ComputeValueVTs that also produces the memory VTs. | |||
/// Variant of ComputeValueVTs that also produces the memory VTs and VT types. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, the EVTs do unfortunately squash away the pointer types (because they also resolve to integer MVTs, the Type* is dropped). I meant more the other direction, would it work to change this to return the aggregate split Type s instead of the EVT? The client would then have a thin Type->EVT wrapper
See #70337 for discussion. There is a problem with the
CCIfPtr
check that can be used in calling conventions: it is not true for pointers in structs, as in:In this PR
ComputeValueVTs
is extended to optionally return value types. This is then used in SelectionDAGBuilder to set the pointer bit in ArgFlags appropriately.In #70337 (comment) it was suggested to extend
ComputeValueVTs
to return booleanIsPtr
s. I have opted to let it return*Type
s instead, which I believe is equally efficient, but is a little bit more general in case these types are needed elsewhere in the future. I'd be happy to change this of course.I tested this with the new calling convention I'm working on (see #70337). I am not sure about writing a test. On X86,
CCIfPtr
is only used in the C calling convention, to make sure that "Pointers are always passed in full 64-bit registers":llvm-project/llvm/lib/Target/X86/X86CallingConv.td
Lines 570 to 571 in 497b2eb
llvm-project/llvm/lib/Target/X86/X86CallingConv.cpp
Lines 333 to 341 in 497b2eb
It may be possible to use this to write a test, but I don't know what kind of IR would cause this rule to do anything meaningful: when would pointers not be passed in full 64-bit registers?
I am not that familiar with LLVM, so I apologize in advance for any and all problems with this PR.