[LLVMdev] Use-list order assembly declarations for PR20515

Duncan P. N. Exon Smith dexonsmith at apple.com
Tue Aug 5 16:36:37 PDT 2014


I'm now looking at implementing `-preserve-ll-use-list-order` (PR20515)
to preserve use-list order when round-tripping to assembly -- the
counterpart to `-preserve-bc-use-list-order`.

After a quick look at `LLParser` and `AssemblyWriter`, I believe we can
use the same technique as for bitcode.  In particular, we can predict in
`AssemblyWriter` how use-lists will look in the `LLParser` and write out
use-list-order directives to be processed as they're seen.

There are a couple of bike sheds to paint.

Use-list-order directives
=========================

A use-list order directive needs to reference a `Value` with users and
describe how to reorder it.  Here's my proposed syntax:

    uselistorder <ty> <value>, { <order-indexes> }

Example assembly
----------------

Following is a simple module with some examples.  For demonstration
purposes, I've given a directive to every value that has multiple users.

    @global = global i32 7
    @alias = alias i32* @global
    @global2 = global i32* @global

    define void @foo(i32 %arg1, i32 %arg2) {
    entry:
      %call1 = call i32 @bar(i32 %arg1)
      %call2 = call i32 @bar(i32 %arg2)
      %cmp = icmp lt i32 %call1, %call2
      br i1 %cmp, label %0, label %named

    ; <label %0>:
      %loaded = load i32* @global
      %sum = add i32 %loaded, %arg1
      %product = mul i32 %sum, 7
      br label %named

    named:
      %val = phi i32 [ %arg1, %named ], [ %product, %0 ]
      ret %val

    ; local uselistorders for @foo
      uselistorder i32 %arg1, { 1, 0, 2 }
      uselistorder label %0, { 2, 0, 1 }
      uselistorder label %named, { 1, 0 }
    }
    declare i32 @bar(i32);

    ; global uselistorders
    uselistorder i32* @global, { 1, 2, 0 }
    uselistorder i32 7, { 1, 0 }
    uselistorder i32 (i32) @bar, { 1, 0 }

Semantics
---------

I propose using the same semantics as in the bitcode.  The order-indexes
are assigned to each `Use` in order, then the `Use`s are sorted
according to their indexes.  The directives would be applied immediately
on parse.

Failure conditions
==================

There are a few ways that a `uselistorder` can fail:

  - Referenced value is not yet defined.
  - Referenced value has the wrong type.
  - Referenced value has the wrong number of uses.
  - Order indexes form a no-op (already in order).

Should these failures be warnings or errors?  I think they should all be
errors.  This makes it more difficult to hand-modify assembly with
`uselistorder` directives, but if someone is modifying the assembly they
should strip out the `uselistorder` directives anyway.

Use-lists of basic blocks that escape
=====================================

Typical basic blocks sort their use-lists via `uselistorder` directives
at function scope.  The example above shows a couple of those.

However, basic blocks whose addresses are taken via `blockaddress`
expressions need special treatment because `LLParser` won't have seen
all the uses by the end of the function definition.  Their
`uselistorder` directives need to be after the last `Use` has been
parsed.

I propose the following syntax for non-local directives for basic
blocks:

    uselistorderbb @function, %block, { <order-indexes> }

For example:

    uselistorderbb @foo, %bb, { 0, 1, 5, 3, 2, 4 }
    uselistorderbb @foo, %12, { 0, 1, 5, 3, 2, 4 }




More information about the llvm-dev mailing list