[RFC] Using i8 for boolean return types and arguments.

With the optimization patch I emailed, clang compiles

bool f(bool *x) {
  return *x;
}

to

define zeroext i1 @_Z1fPb(i8* nocapture %x) nounwind uwtable readonly {
entry:
%0 = load i8* %x, align 1, !tbaa !0, !range !3
%tobool = icmp ne i8 %0, 0
ret i1 %tobool
}

Which I think is the perfect IL if we are going to return an i1.
Unfortunately, this still codegens to

       cmpb $0, (%rdi)
       setne %al
       ret

One way to fix this is to implement
http://nondot.org/sabre/LLVMNotes/ExtendedIntegerResults.txt. The
attached patch does it for boolean types only. The result is that the
IL (after the optimizer simplify it) becomes

define i8 @_Z1fPb(i8* nocapture %x) nounwind readonly optsize {
entry:
  %0 = load i8* %x, align 1, !tbaa !0, !range !3
  ret i8 %0
}

and the assembly is

  movb (%rdi), %al
  ret

What is lost is that anything using the function has no way to know
that the lest significant byte can only be 0 or 1. This is easier to
see with a boolean argument. Currently clang compiles

int f(bool x) {
  return x;
}

to

define i32 @_Z1fb(i1 zeroext %x) nounwind readnone optsize {
entry:
  %conv = zext i1 %x to i32
  ret i32 %conv
}

which codegens to

  movzbl %dil, %eax
  ret

With this patch we regress to

define i32 @_Z1fb(i8 %x.coerce) nounwind readnone optsize {
entry:
  %0 = and i8 %x.coerce, 1
  %conv = zext i8 %0 to i32
  ret i32 %conv
}

and

  andl $1, %edi
  movl %edi, %eax
  ret

How should we handle this? The proposal on LLVMNotes is to have an
attribute of the form "zext_from(i8)", which requires extending what
parameter attributes are. Another option is allowing metadata on
parameters, in which case we would be able to just use the new range
metadata.

Has anyone tried adding metadata to parameters before?

Cheers,
Rafael

t.patch (965 Bytes)