[llvm-dev] Semantics for non-byte-sized stores? (or whenever "store size in bits" is different than "size in bits")

Eli Friedman via llvm-dev llvm-dev at lists.llvm.org
Fri May 17 12:08:55 PDT 2019


Comments inline

> -----Original Message-----
> From: llvm-dev <llvm-dev-bounces at lists.llvm.org> On Behalf Of Björn
> Pettersson A via llvm-dev
> Sent: Friday, May 17, 2019 7:34 AM
> To: llvm-dev at lists.llvm.org
> Subject: [EXT] [llvm-dev] Semantics for non-byte-sized stores? (or whenever
> "store size in bits" is different than "size in bits")
> 
> Assume that I have LLVM IR for a union between two types that are mapped to
> i32 and i19.
> And then I have two overlapping stores to this union such as:
> 
>   %u = alloca %union
>   %u32 = bitcast %union* %u to i32*
>   %u19 = bitcast %union* %u to i19*
>   store i32 -1, i32* %u32
>   store i19  0, i19* %u19
>   %result = load i32, i32* %u32
> 
> How many bits are guaranteed to be zero in %result?

According to LangRef, 19.  In practice, 24.

> How many bits are guaranteed to be one in %result?

8.

> To be more specific:
> 
>  a) Is the i19 store defined as only writing 19 bits (even if store size is larger, so it
> will become a load-modify-write after legalization)?

Loads and stores only operate on a whole number of bytes, determined by getTypeStoreSize.  So 24 bits are stored, and no bits are loaded.
 
>  b) Is the i19 store defined as touching 24 bits, so we get 5 bits that are
> undefined (or always zero-extended/sign-extended)?

LangRef says the 5 bits are determined by the target: an i19 load is only defined if the value was constructed using an i19 store.  But in practice, SelectionDAG legalization always zero-extends stores, and loads assume the value is zero-extended.

>   %u = alloca %union
>   %u32 = bitcast %union* %u to i32*
>   %u19 = bitcast %union* %u to i19*
>   %u16 = bitcast %union* %u to i16*
>   store i19  0, i19* %u19
>   store i16 -1, i16* %u16
>   %result = load i32, i32* %u32

The first store stores three bytes, the second store stores two bytes, the load loads four bytes.  So there's one byte of data from the first store, and two bytes from the second.

> Yet another question is if the i19 value is guaranteed to be placed in the least
> significant end of the 3 bytes that are tainted by the store?

IIRC, this isn't formally specified in LangRef, but in practice an i19 is laid out as if it were zero-extended to i24.  I'd suggest bailing out of any transform that would care, though.

I've been considering formalizing the current SelectionDAG behavior in LangRef, but I haven't written a patch.

-Eli


More information about the llvm-dev mailing list