[LLVMdev] [RFC] Proposal to make LLVM-IR endian agnostic

Török Edwin edwintorok at gmail.com
Mon Oct 3 14:00:18 PDT 2011


On 10/03/2011 09:36 PM, Villmow, Micah wrote:
> One of the projects I am working on with others is to make LLVM-IR endian agnostic.
> 
>  
> 
> So, I am sending out this proposal for feedback to the LLVM community. I’ve attached
> 
> pretty version of the proposal in PDF format and pasted a 80-column safe text version
> 
> below.
> 
>  
> 
> A second smaller set could be:
> 
> declare <type> @llvm.portable.load.<type>(<type>* ptr, i32 alignment,
> 
> i1 host, i1 littleEndian, i1 atomic, i1 volatile,
> 
> i1 nontemporal, i1 singlethread)
> 
>  
> 
> declare void @llvm.portable.store.<type>(<type> data, <type>* ptr,
> 
> i32 alignment, i1 host, i1 littleEndian, i1 atomic, i1 volatile,
> 
> i1 nontemporal, i1 singlethread)

FWIW here is another way to do it (which is approximately what ClamAV does currently) by introducing just one intrinsic:
declare i1 @llvm.is_bigendian()

The advantage is that you can implement htonl() and ntohl() like functionality without using a temporary memory location.
Actually I think having the 2 intrinsics you suggest and the is_bigendian() intrinsic would be optimal:
you can use your 2 intrinsics for initial codegen, and mem2reg can transform it to is_bigendian().

For load/store:
<type> %val = load <type>* %ptr
<type> %sval = bswap.i<type> %val
%result = <type> select @llvm.is_bigendian(), %val, %sval

For htonl():
<type> %sval = bswap.i<type> %val
%result = <type> select @llvm.is_bigendian(), %val, %sval

(store is similar, byteswap before the store)

At bytecode JIT time / assembly emission time @llvm.is_bigendian() is a known constant, and constant propagation is
used to throw away the unwanted code path, so it becomes either:

<type> %result = load <type>* %ptr

or

<type> %val = load <type>* %ptr
<type> %result = bswap.i<type> %val

Best regards,
--Edwin



More information about the llvm-dev mailing list