This is an archive of the discontinued LLVM Phabricator instance.

[OpaquePtr] Introduce option to force all pointers to be opaque pointers
ClosedPublic

Authored by aeubanks on Jun 1 2021, 9:38 PM.

Details

Summary

We don't want to start updating tests to use opaque pointers until we're
close to the opaque pointer transition. However, before the transition
we want to run tests as if pointers are opaque pointers to see if there
are any crashes.

At some point when we have a flag to only create opaque pointers in the
bitcode and textual IR readers, and when we have fixed all places that
try to read a pointee type, this flag will be useless. However, until
then, this can help us find issues more easily.

Since the cl::opt is read into LLVMContext, we need to make sure
LLVMContext is created after cl::ParseCommandLineOptions().

Previously ValueEnumerator would visit the value types of global values
via the pointer type, but with opaque pointers we have to manually visit
the value type.

Diff Detail

Event Timeline

aeubanks created this revision.Jun 1 2021, 9:38 PM
aeubanks requested review of this revision.Jun 1 2021, 9:38 PM
Herald added a project: Restricted Project. · View Herald TranscriptJun 1 2021, 9:38 PM
dblaikie added inline comments.Jun 2 2021, 9:25 AM
llvm/lib/Bitcode/Writer/ValueEnumerator.cpp
367–385

Looks like maybe only one of these code changes is tested - perhaps the test should be expanded to have an example of each of these to exercise each fix here? (maybe in separate patches)

llvm/test/Other/force-opaque-ptrs.ll
6–8

Would this still exercise the desired codepath if the function was void() instead of ptr(ptr)? (if I'm understanding correctly, the interesting issue is that the type of f itself becomes an opaque pointer - so, oh, you need /some/ interesting type in the function type that would be missed, yeah? What about void(i32) would that still reveal the issue/validate the fix?)

I ask because it might be more clear which pointer type becoming opaque is the interesting one?

dexonsmith added inline comments.Jun 2 2021, 11:55 AM
llvm/lib/IR/Type.cpp
688–689

I wonder if this would be better to thread through as a bool set on the LLVMContext during construction:

if (!EltTy->getContext().supportsTypedPointers())
  return get(EltTy->getcontext(), AddressSpace);

Might make it easier to reason about / access elsewhere. (Could still have the command-line option control that...)

llvm/test/Other/force-opaque-ptrs.ll
2

Can you explain why this test uses --force-opaque-pointers? I feel like this test would be more clear if the textual IR actually matched the IR under test (i.e., if it used ptr)... also, then the textual IR won't need to be updated later when typed pointers are removed. But maybe there's some limitation you're working around?

aeubanks updated this revision to Diff 349594.Jun 3 2021, 9:53 AM

only touch functions in ValueEnumerator
move ForceOpaquePointers to LLVMContextImpl (this doesn't currently work in some tools since LLVMContext is created before parsing command line opts)

aeubanks edited the summary of this revision. (Show Details)Jun 3 2021, 9:54 AM
aeubanks added inline comments.Jun 3 2021, 9:56 AM
llvm/lib/Bitcode/Writer/ValueEnumerator.cpp
367–385

sure, I can start with just functions

llvm/lib/IR/Type.cpp
688–689

I was worried that looking at a cl::opt for every call to PointerType::get() could be noticeable perf wise, adding it to LLVMContext(Impl) would mostly fix that.
However, I tried this approach, turns out in many tools, the LLVMContext is created before parsing command line options. I think this flag makes sense as a global flag, not a per-tool flag that requires calling something like LLVMContext::setForceOpaquePointers().
I could go around and fix all the tools to create an LLVMContext after parsing command line options.

llvm/test/Other/force-opaque-ptrs.ll
2

I assumed that at some point we were going to update all tests from type * to ptr. I think there was a discussion long ago about this but it was never really resolved. We should probably raise this question on llvm-dev.

6–8

this patch is definitely mixing two things, forcing all pointers to be opaque, and the ValueEnumerator stuff

I'm trying to add a test to make sure that we get out a ptr from something that was originally i32*.
I can make @f only have one visible pointer type:

define void @f(i32* %a) {
  ret void
}

would turn into

define void @f(ptr %a) {
  ret void
}

validating this change.

But just testing that doesn't work due to the ValueEnumerator issues introduced by the flag, which is only reproducible with the flag turned on. So if we want to properly test this we need to combine the two patches.

As for what function types cause the crash, even void() causes a crash. But that doesn't show that the flag is working as expected since there's no i32* anywhere.

dblaikie added inline comments.Jun 3 2021, 7:49 PM
llvm/test/Other/force-opaque-ptrs.ll
2

Hmm, I might just end up adding more confusion to this thread, but I'm not sure how your answer, @aeubanks applies to @dexonsmith's question - perhaps you could rephrase?

My understanding of @dexonsmith's question, combined with what @aeubanks has mentioned elsewhere in the review:

--force-opaque-pointers is needed because this test is intended to test that functionality/flag, including the fix in the bitcode reader for the types of functions.

But it might be that this could be separated - the flag could be added and tested purely with IR reading/writing, showing a pointer type going from typed to opaque through the IR roundtrip?

Then separately a commit that shows the bitcode change/fix?

(not sure that explains all of @dexonsmith's questions)

nikic accepted this revision.Jun 24 2021, 2:13 AM
nikic added a subscriber: nikic.

Assuming there are no problems moving the command line parsing for opt, this LGTM.

Separating testing for the one-line value enumerator change does not seem particularly valuable.

This revision is now accepted and ready to land.Jun 24 2021, 2:13 AM
aeubanks added a reviewer: Restricted Project.Jun 24 2021, 8:16 AM
aeubanks updated this revision to Diff 354265.Jun 24 2021, 8:39 AM

move some LLVMContext after command line parsing

aeubanks edited the summary of this revision. (Show Details)Jun 24 2021, 8:39 AM
aeubanks added inline comments.Jun 24 2021, 8:47 AM
llvm/test/Other/force-opaque-ptrs.ll
2

I read @dexonsmith's question as "are we actually eventually going to update all llvm tests off of type * into ptr, which my answer is "yes".

Regarding can we separate the --force-opaque-pointers change and the bitcode change, I believe the answer is no. We need some global or function to show the change, and all of those will require some bitcode change because the type of the global/function is now an opaque pointer, so we have to look at the value type of the global/function.

(Apologies for disappearing; I was out for a bit, and then lost track of this review.)

llvm/lib/IR/Type.cpp
688–689

I could go around and fix all the tools to create an LLVMContext after parsing command line options.

Maybe this would be the right thing to do, but I'm fine with not going that far for now if you think it's error-prone.

There were really two suggestions above:

  1. Centralize access to the cl::opt via LLVMContext
  2. Read the cl::opt only once, during construction of LLVMContext

WDYT of #1 on its own for now? (I.e., use EltTy->getContext().supportsTypedPointers() here, but that just reads the cl::opt.)

(Personally I'm not too worried about perf of this access/call... my intuition is that the branch would be well-predicted, and there's also a DenseMap lookup to hide behind. Of course I could be wrong though.)

llvm/test/Other/force-opaque-ptrs.ll
2

Sorry for any confusion here.

Taking a fresh look, I see how this tests --force-opaque-pointers when reading textual IR, but there's no coverage for reading bitcode. WDYT of this?

; RUN: llvm-as --force-opaque-pointers < %s | llvm-dis | FileCheck %s
; RUN: llvm-as < %s | llvm-dis --force-opaque-pointers | FileCheck %s
llvm/tools/llvm-as/llvm-as.cpp
120

Probably better to leave these moves of LLVMContext out of this patch -- could be committed separately as an NFC prep-commit ("Moving LLVMContext so that cl::opt can control defaults") if you end up reading the cl::opt during construction.

dexonsmith accepted this revision.Jun 24 2021, 12:23 PM

This LGTM, once you add the RUN line for llvm-dis I suggested in the last comment. It's up to you whether to split out the changes for moving the LLVMContext construction after command-line parsing into a prep commit... there could be an argument for keeping it together as well.

llvm/lib/IR/Type.cpp
688–689

Looking again, it looks like you've already done this (#1 and #2)... not sure what I was reading before, thinking you hadn't done this yet :/.

aeubanks updated this revision to Diff 354344.Jun 24 2021, 1:28 PM

add llvm-dis --force-opaque-pointers test

It's hard to test the LLVMContext moves without this patch, I'd rather keep it here.

llvm/lib/IR/Type.cpp
688–689

Yeah I originally did #1, and now am doing #2.

This revision was landed with ongoing or failed builds.Jun 24 2021, 1:32 PM
This revision was automatically updated to reflect the committed changes.