This is an archive of the discontinued LLVM Phabricator instance.

CodeGen: Fix address space of global variable
ClosedPublic

Authored by yaxunl on Jun 2 2017, 10:33 AM.

Details

Summary

Certain targets (e.g. amdgcn) require global variable to stay in global or constant address
space. In C or C++ global variables are emitted in the default (generic) address space.
This patch introduces virtual functions TargetCodeGenInfo::getGlobalVarAddressSpace
and TargetInfo::getConstantAddressSpace to handle this in a general approach.

It only affects IR generated for amdgcn target.

Diff Detail

Repository
rL LLVM

Event Timeline

yaxunl created this revision.Jun 2 2017, 10:33 AM
rjmccall added inline comments.Jun 2 2017, 11:28 AM
lib/CodeGen/CGExpr.cpp
360 ↗(On Diff #101235)

This is not an appropriate place to stick target-specific code. You should add a target hook that returns the address space into which to allocate constant temporaries, with the requirement that the target must not return an address space which cannot be lifted into LangAS::Default. For some configurations this may not be possible (e.g. OpenCL C++?), so the hook should return an Optional<unsigned> so that a None return will disable the optimization.

And you should go ahead and lift the pointer here if necessary.

You may have to make createReferenceTemporary return whether it constant-emitted the temporary initializer.

yaxunl updated this revision to Diff 102204.Jun 12 2017, 10:58 AM
yaxunl marked an inline comment as done.

Add TargetInfo::getTargetConstantAddressSpace.

rjmccall added inline comments.Jun 20 2017, 9:19 AM
include/clang/Basic/TargetInfo.h
959 ↗(On Diff #102204)

"Return an AST address space which can be used opportunistically for constant global memory. It must be possible to convert pointers into this address space to LangAS::Default. If no such address space exists, this may return None, and such optimizations will be disabled."

lib/CodeGen/CGExpr.cpp
357 ↗(On Diff #102204)

This isn't the right logic. Part of what I was saying before is that this optimization isn't obviously supportable on all targets. You should call getTargetConstantAddressSpace() and then only try to do this optimization if it doesn't return None.

For parity, the default implementation should return 0.

449 ↗(On Diff #102204)

Every time you're tempted to use getPointerCast, you should instead be using the target hook to lift the pointer into the right address space.

yaxunl marked 3 inline comments as done.Jun 20 2017, 11:51 AM
yaxunl added inline comments.
include/clang/Basic/TargetInfo.h
959 ↗(On Diff #102204)

I will change it. Also I think getConstantAddressSpace may be a better name since we will return AST addr space.

lib/CodeGen/CGExpr.cpp
449 ↗(On Diff #102204)

I am going to fix it. However this seems not the right place to do the addr space cast. I am going to do it in createReferenceTemporary instead.

yaxunl updated this revision to Diff 103613.Jun 22 2017, 12:00 PM
yaxunl marked 2 inline comments as done.

Revised by John's comments.

rjmccall added inline comments.Jun 22 2017, 9:08 PM
include/clang/Basic/TargetInfo.h
969 ↗(On Diff #103613)

I'm not sure this really needs to exist.

959 ↗(On Diff #102204)

Sorry, I typo'ed my original suggestion. "pointers in this address space".

lib/CodeGen/CGBlocks.cpp
1144 ↗(On Diff #103613)

You used VoidPtrTy above.

lib/CodeGen/CGExpr.cpp
342 ↗(On Diff #103613)

Why are you passing the TargetCodeGenInfo down separately when it can be easily reacquired from the CodeGenFunction?

Oh, it looks like getTargetHooks() is private; there's no reason for that, just make it public.

372 ↗(On Diff #103613)

GV->getValueType()->getPointerTo(...)

lib/CodeGen/CodeGenModule.cpp
2549 ↗(On Diff #103613)

This does not seem like a very useful assertion.

2554 ↗(On Diff #103613)

I would expect this to be the general rule for all language modes. Why is OpenCL an exception?

It looks to me like GetGlobalVarAddressSpace is only ever called with a possibly-null D by GetOrCreateLLVMGlobal, which is only called with a null D by CreateRuntimeVariable. I expect that every call to CreateRuntimeVariable will probably need to be audited if it's going to suddenly start returning pointers that aren't in the default address space, and we'll probably end up needing some very different behavior at that point. So for now, let's just move the LanguageExpected case out to the one call site that uses it.

I do like the simplification of just taking the declaration instead of taking that and an address space.

2571 ↗(On Diff #103613)

It's impossible for K to be LanguageExpected here, you already checked it above.

2578 ↗(On Diff #103613)

Okay, I think I see what you're trying to do here: when you compile normal (i.e. non-OpenCL) code for your target, you want to implicitly change where global variables are allocated by default, then translate the pointer into LangAS::Default. It's essentially the global-variable equivalent of what we're already doing with stack pointers.

The right way to do this is to make a hook on the TargetCodeGenInfo like getASTAllocaAddressSpace() which allows the target to override the address space for a global on a case-by-case basis. You can then do whatever target-specific logic you need there, and you won't need to introduce getGlobalAddressSpace() on TargetInfo. The default implementation, of course, will just return D->getType().getAddressSpace().

lib/CodeGen/TargetInfo.cpp
7418 ↗(On Diff #103613)

You have a couple things in this patch that just touch your target and are basically unrelated to the rest of your logic. Please split those into a separate patch.

yaxunl marked 12 inline comments as done.Jul 5 2017, 11:10 AM
yaxunl added inline comments.
include/clang/Basic/TargetInfo.h
969 ↗(On Diff #103613)

Removed.

lib/CodeGen/CGBlocks.cpp
1144 ↗(On Diff #103613)

They are different fields with different types.

lib/CodeGen/CodeGenModule.cpp
2549 ↗(On Diff #103613)

This checks global variable has valid address space. If a global variable having private or generic address space is passed to backend, it may cause issues difficult to debug. This assertion helps to detect the issue early.

2554 ↗(On Diff #103613)

For OpenCL, TargetFavored and LanguageExpected are the same, i.e. global. For C++, TargetFavored is globa, but LanguageExpected is Default.

Done.

2578 ↗(On Diff #103613)

Done.

I am wondering if I should just move the whole function to TargetCodeGenInfo::getGlobalVarAddressSpace, which seems cleaner.

lib/CodeGen/TargetInfo.cpp
7418 ↗(On Diff #103613)

Done.

yaxunl updated this revision to Diff 105310.Jul 5 2017, 11:20 AM
yaxunl marked 6 inline comments as done.
yaxunl retitled this revision from [AMDGPU] Fix address space of global variable to CodeGen: Fix address space of global variable.
yaxunl edited the summary of this revision. (Show Details)

Revised by John's comments.

rjmccall edited edge metadata.Jul 6 2017, 5:14 PM

Looks great, thanks! Just a few minor changes.

lib/CodeGen/CGBlocks.cpp
1144 ↗(On Diff #103613)

They're both the isa field of a block object. The difference is just between allocating the block globally and allocating it on the stack.

lib/CodeGen/TargetInfo.h
237 ↗(On Diff #105310)

The CGM is conventionally the first argument.

262 ↗(On Diff #105310)

This should probably take the CGM for completeness.

yaxunl marked 4 inline comments as done.Jul 7 2017, 7:43 AM
yaxunl added inline comments.
lib/CodeGen/CGBlocks.cpp
1144 ↗(On Diff #103613)

You are right, actually they should both be VoidPtrPtrTy to match the type of getNSConcreteGlobalBlock() and getNSConcreteStackBlock().

Fixed.

lib/CodeGen/TargetInfo.h
237 ↗(On Diff #105310)

done

262 ↗(On Diff #105310)

done.

yaxunl updated this revision to Diff 105644.Jul 7 2017, 7:46 AM
yaxunl marked 3 inline comments as done.

Revised by John's comments.

rjmccall accepted this revision.Jul 7 2017, 12:13 PM

Great, thanks! LGTM.

This revision is now accepted and ready to land.Jul 7 2017, 12:13 PM
This revision was automatically updated to reflect the committed changes.
mehdi_amini added inline comments.
cfe/trunk/lib/CodeGen/CodeGenModule.cpp
3759

Coverity reports:

>>>     CID 1377397:  Null pointer dereferences  (REVERSE_INULL)
>>>     Null-checking "VD" suggests that it may be null, but it has already been dereferenced on all paths leading to the check.

Can you look into this?