[llvm-dev] [RFC] arm64_32: upstreaming ILP32 support for AArch64

Eli Friedman via llvm-dev llvm-dev at lists.llvm.org
Thu Jan 31 11:48:03 PST 2019


Comments inline

> -----Original Message-----
> From: llvm-dev <llvm-dev-bounces at lists.llvm.org> On Behalf Of Tim Northover
> via llvm-dev
> Sent: Thursday, January 31, 2019 7:06 AM
> To: LLVM Developers Mailing List <llvm-dev at lists.llvm.org>
> Subject: [EXT] [llvm-dev] [RFC] arm64_32: upstreaming ILP32 support for
> AArch64
> 
> CodeGenPrepare:
> ---------------
> 
> We teach CodeGenPrepare to sink GEPs as GEPs, and preserve the
> inbounds marker. This is the only way they can possibly be exposed to
> SDAG at the basic block level.

Isn't addr-sink-using-gep already a thing?

> 
> Pointers are still 64-bits, tricked ya!
> ---------------------------------------
> 
> The next question was how to expose these GEPs to the SDAG.
> 
> I first considered adding an ISD::GEP or an "inbounds" flag to
> ISD::ADD. These would solve the first issue above, but not the second.
> 
> So the proposed solution is to allow pointers to have different
> in-memory and in-DAG types, and specifically keep an i64 pointer in
> the DAG on arm64_32. This immediately guarantees that (valid) pointers
> will have their high bits zeroed, and just by creating the DAG we make
> explicit the sign-extensions described by GEP semantics.
> 
> Addressing-modes can then be used with no change to the actual C++
> code in AArch64 that selects them.
> 
> There are two possible disadvantages though. First, since pointers are
> 64-bits, they will consume 64-bit spill slots and potentially bloat
> the stack. It's unclear how much of an issue that is in practice.
> 
> Second is the intrusiveness. On the plus side it's less intrusive than
> ISD::GEP would be, but it still involves changes in some fairly
> obscure bits of DAG -- often found when things broke rather than by
> careful planning.

Did you consider modeling this with address spaces?  LLVM already has robust support for address spaces with different pointer sizes, and you probably want to expose support for 64-bit pointers anyway.

> Arrays
> ------
> 
> We're translating armv7k bitcode to arm64_32, and the result has to be
> compatible with code that is compiled directly to arm64_32.
> 
> The biggest barrier here was small structs. They generally get passed
> in registers, possibly with alignment requirements.
> 
>     struct { int arr[2] }; goes in [rN,rN+1] or in xN.
>     struct { uint64_t val; } goes in [rN,rN+1] (starting even), or xN
> 
> So we need a way to signal in IR that two values should be combined
> into a single x-register when compiled for arm64_32. We chose LLVM
> arrays for the job. So, unlike all other targets, the following two
> functions will behave differently in arm64_32:
> 
>     void @foo([2 x i32] %x0)      ; Two i32s combined into 64-bit x0 register
>     void @foo(i32 %w0, i32 %w1)   ; First i32 in w0, second in w1

I'm not sure I follow the difference between [2 x i32] and i64: if they both go into a single register, why do you need both?  Or is this necessary to support your automatic translation pass?

-Eli


More information about the llvm-dev mailing list