[LLVMdev] Question on equivalence of pointer types

Sanjoy Das sanjoy at playingwithpointers.com
Mon Dec 8 18:12:48 PST 2014


In the example that you gave, the difference is between

  load i32 addrspace(0)* null
and
  load i32 addrspace(1)* null

(that the first one is UB, while the second one may be well-defined).

But my question is different, it is that are the following two different:

  load i32 addrspace(0)* addrspace(0)* %p0
  load i32 addrspace(1)* addrspace(0)* %p1

if %p0 == %p1 (because they're bitcasts of each other or something --
note that you don't need an addrspacecast to go from "i32
addrspace(1)* addrspace(0)*" to "i32 addrspace(0)* addrspace(0)*").

They are different in the type system because one of them produces an
"i32 addrspace(0)*" while the other produces an "i32 addrspace(1)*",
so in general they cannot be substituted by each other, but there are
edge cases as in the example I started this thread with.

In other words: the semantics of a load or store depend on the address
space of the pointer operand.  But in case the *value* we're storing
is also a pointer, does the semantics depend on the value's address
space to?

I suspect the answer is no, but I may be missing something here and
wish to confirm.

-- Sanjoy


On Mon, Dec 8, 2014 at 5:33 PM, Pete Cooper <peter_cooper at apple.com> wrote:
>
> On Dec 8, 2014, at 5:12 PM, Sanjoy Das <sanjoy at playingwithpointers.com>
> wrote:
>
> Partially answering my own question, in general these are not
> equivalent because LLVM allows for pointers in different address
> spaces to have different sizes.  However, are they equivalent if
> pointers in addrspace(1) have the same size as pointers in
> addrspace(0)?
>
> In other words, assuming pointers have the same size irrespective of
> address spaces, is storing / loading an (not storing into / loading
> from) addrspace(1)* allowed to do something semantically different
> than storing / loading an addrspace(0)*?
>
> It is yeah.  For example, this code is in InstCombine where we assume that
> loading null is undefined, but only for addrspace(0).  Whether other address
> spaces trap or give undefined behaviour on loading null is target dependent.
>
> Thanks,
> Pete
>
> // load(gep null, ...) -> unreachable
>   if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(Op)) {
>     const Value *GEPI0 = GEPI->getOperand(0);
>     // TODO: Consider a target hook for valid address spaces for this xform.
>     if (isa<ConstantPointerNull>(GEPI0) && GEPI->getPointerAddressSpace() ==
> 0){
>       // Insert a new store to null instruction before the load to indicate
>       // that this code is not reachable.  We do this instead of inserting
>       // an unreachable instruction directly because we cannot modify the
>       // CFG.
>       new StoreInst(UndefValue::get(LI.getType()),
>                     Constant::getNullValue(Op->getType()), &LI);
>       return ReplaceInstUsesWith(LI, UndefValue::get(LI.getType()));
>     }
>   }
>
>
> Thanks,
> -- Sanjoy
>
> On Thu, Dec 4, 2014 at 10:09 PM, Sanjoy Das
> <sanjoy at playingwithpointers.com> wrote:
>
> Is copy.0 semantically equivalent to copy.1 in the following example?
>
> define void @copy.0(i8 addrspace(1)* addrspace(1)* %src, i8
> addrspace(1)* addrspace(1)* %dst) {
> entry:
>  %val = load i8 addrspace(1)* addrspace(1)* %src
>  store i8 addrspace(1)* %val, i8 addrspace(1)* addrspace(1)* %dst
>  ret void
> }
>
> define void @copy.1(i8 addrspace(1)* addrspace(1)* %src, i8
> addrspace(1)* addrspace(1)* %dst) {
> entry:
>  %src.cast = bitcast i8 addrspace(1)* addrspace(1)* %src to i8*
> addrspace(1)*
>  %dst.cast = bitcast i8 addrspace(1)* addrspace(1)* %dst to i8*
> addrspace(1)*
>
>  %val = load i8* addrspace(1)* %src.cast
>  store i8* %val, i8* addrspace(1)* %dst.cast
>  ret void
> }
>
> -- Sanjoy
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
>



More information about the llvm-dev mailing list