[llvm-dev] [RFC] ASM Goto With Output Constraints

Bill Wendling via llvm-dev llvm-dev at lists.llvm.org
Thu Jun 27 11:07:55 PDT 2019


[Adding the correct cfe-dev mailing list address.]

On Thu, Jun 27, 2019 at 11:06 AM Bill Wendling <isanbard at gmail.com> wrote:

> Now that ASM goto support has landed, Nick Desaulniers and I wrote up a
> document describing how to expand clang's implementation of ASM goto to
> support output constraints. The work *should* be straight-forward, but as
> always will need to be verified to work. Below is a copy of our whitepaper.
> Please take a look and offer any comments you have.
>
> Share and enjoy!
> -bw
> Overview
>
> Support for asm goto
> <https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html> with output
> constraints is a feature that the Linux community is interested in having. Adding
> this new feature should give Clang a higher profile in the Linux community:
>
>
>    -
>
>    It demonstrates the Clang community's commitment to supporting Linux.
>    -
>
>    Developers are likely to adopt it on their own, which means they will
>    need to use Clang in some fashion, either as a complete replacement for or
>    in addition to GCC.
>
> Current state
>
> Clang's implementation of asm goto converts this code:
>
> int vogon(unsigned a, unsigned b) {
>   asm goto("poetry %0, %1" : : "r"(a), "r"(b) : : error);
>   return a + b;
>
> error:
>   return -1;
> }
>
> into the following LLVM IR:
>
> define i32 @vogon(i32 %a, i32 %b) {
> entry:
>   callbr void asm sideeffect "poetry $0, $1", "r,r,X"
>       (i32 %a, i32 %b, i8* blockaddress(@vogon, %return))
>           to label %asm.fallthrough [label %return]
>
> asm.fallthrough:
>   %add = add i32 %b, %a
>   br label %return
>
> return:
>   %retval.0 = phi i32 [ %add, %asm.fallthrough ], [ -1, %entry ]
>   ret i32 %retval.0
> }
>
> Our proposal won't change LLVM's current behavior–i.e. a callbr without a
> return value will act in the same way as the current implementation.
> Proposal
>
> GCC restricts asm goto from having output constraints due to limitations
> in its internal representation–i.e. GCC's control transfer instructions
> cannot have outputs. For example:
>
> int vogon(int a, int b) {
>   asm goto("poetry %0, %1" : "=r"(a), "=r"(b) : : : error);
>   return a + b;
>
> error:
>   return -1;
> }
>
> currently fails to compile in GCC with the following error:
>
> <source>: In function 'vogon':
> <source>:2:29: error: expected ':' before string constant
>   2 |   asm goto("poetry %0, %1" : "=r"(a), "=r"(b) : : : error);
>     |                         ^~~~~
>     |                         :
>
>
>
> ToT Clang matches GCC's behavior:
>
> <source>:2:30: error: 'asm goto' cannot have output constraints
>   asm goto("poetry %0, %1" : "=r"(a), "=r"(b) : : : error);
>
> However, LLVM doesn't restrict control transfer instructions from having
> outputs (e.g. the invoke instruction
> <https://llvm.org/docs/LangRef.html#invoke-instruction>). We propose
> changing LLVM's callbr instruction
> <https://llvm.org/docs/LangRef.html#callbr-instruction> to allow return
> values, similar to how LLVM's implementation of inline assembly (via the
> call instruction <https://llvm.org/docs/LangRef.html#call-instruction>)
> allows return values. Since there can potentially be zero to many output
> constraints, callbr would now return an aggregate which contains an
> element for each output constraint.  These values would then be extracted
> via extractvalue. With our proposal, the above C example will be
> converted to LLVM IR like this:
>
> define i32 @vogon(i32 %a, i32 %b) {
> entry:
>   %0 = callbr { i32, i32 } asm sideeffect "poetry $0, $1", "=r,=r,X"
>       (i8* blockaddress(@vogon, %error))
>           to label %asm.fallthrough [label %error]
>
>
> asm.fallthrough:
>   %asmresult.a = extractvalue { i32, i32 } %0, 0
>   %asmresult.b = extractvalue { i32, i32 } %0, 1
>   %result = add i32 %asmresult.a, %asmresult.b
>   ret i32 %result
>
> error:
>   ret i32 -1
> }
>
> Note that unlike the invoke instruction, callbr's return values are
> assumed valid on all branches. The assumption is that the programmer
> knows what their inline assembly is doing and where its output constraints
> are valid. If the value isn't valid on a particular branch but is used
> there anyway, then the result is a poison value. (Also, if a callbr's
> return values affect a branch, it will be handled similarly to the invoke
> instruction's implementation.) Here's an example of how this would work:
>
> int vogon(int a, int b) {
>   asm goto("poetry %0, %1" : "=r"(a), "=r"(b) : : : error);
>   if (a == 42)
>     return 42 * b;
>   return a + b;
>
> error:
>   return b - 42;
> }
>
> generates the following LLVM IR:
>
> define i32 @vogon(i32 %a, i32 %b) {
> entry:
>   %0 = callbr { i32, i32 } asm sideeffect "poetry $0, $1", "=r,=r,X"
>       (i8* blockaddress(@vogon, %error))
>           to label %asm.fallthrough [label %error]
>
> asm.fallthrough:
>   %asmresult.a = extractvalue { i32, i32 } %0, 0
>   %tobool = icmp eq i32 %asmresult.a, 42
>   br i1 %tobool, label %if.true, label %if.false
>
> if.true:
>   %asmresult.b = extractvalue { i32, i32 } %0, 1
>   %mul = mul i32 42, %asmresult.b
>   ret i32 %mul
>
> if.false:
>   %asmresult.a.1 = extractvalue { i32, i32 } %0, 0
>   %asmresult.b.1 = extractvalue { i32, i32 } %0, 1
>   %result = add i32 %asmresult.a.1, %asmresult.b.1
>   ret i32 %result
>
> error:
>   %asmresult.b.error = extractvalue { i32, i32 } %0, 1
>   %error.result = sub i32 %asmresult.b.error, 42
>   ret i32 %error.result
> }
> Implementation
>
> Because LLVM's invoke instruction is a terminating instruction that may
> have return values, we can use it as a template for callbr's changes. The
> new functionality lies mostly in modifying Clang's front-end. In
> particular, we need to do the following:
>
>
>    -
>
>    Remove all error checks restricting asm goto from returning values, and
>    -
>
>    Generate the extractvalue instructions on callbr's branches.
>
>
> LLVM's middle- and back-ends need to be audited to ensure there are no
> restrictions on callbr returning a value. We expect all passes to Just
> Work™ without modifications, but of course will be verified.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190627/2c45cc04/attachment-0001.html>


More information about the llvm-dev mailing list