r217349 - Add __builtin_assume and __builtin_assume_aligned using @llvm.assume.

Richard Smith richard at metafoo.co.uk
Thu Oct 2 17:13:00 PDT 2014


On Thu, Oct 2, 2014 at 2:41 PM, Hal Finkel <hfinkel at anl.gov> wrote:

> ----- Original Message -----
> > From: "Richard Smith" <richard at metafoo.co.uk>
> > To: "Hal Finkel" <hfinkel at anl.gov>
> > Cc: "cfe commits" <cfe-commits at cs.uiuc.edu>
> > Sent: Monday, September 29, 2014 2:09:07 PM
> > Subject: Re: r217349 - Add __builtin_assume and __builtin_assume_aligned
> using @llvm.assume.
> >
> > On Thu, Sep 25, 2014 at 9:19 AM, Hal Finkel < hfinkel at anl.gov >
> > wrote:
> >
> >
> > ----- Original Message -----
> > > From: "Richard Smith" < richard at metafoo.co.uk >
> > > To: "Hal Finkel" < hfinkel at anl.gov >
> > > Cc: "cfe commits" < cfe-commits at cs.uiuc.edu >
> > > Sent: Wednesday, September 24, 2014 11:22:47 PM
> >
> >
> > > Subject: Re: r217349 - Add __builtin_assume and
> > > __builtin_assume_aligned using @llvm.assume.
> > >
> > >
> > >
> > >
> > >
> > >
> > > On Sun, Sep 7, 2014 at 3:58 PM, Hal Finkel < hfinkel at anl.gov >
> > > wrote:
> > >
> > >
> > > Author: hfinkel
> > > Date: Sun Sep 7 17:58:14 2014
> > > New Revision: 217349
> > >
> > > URL: http://llvm.org/viewvc/llvm-project?rev=217349&view=rev
> > > Log:
> > > Add __builtin_assume and __builtin_assume_aligned using
> > > @llvm.assume.
> > >
> > > This makes use of the recently-added @llvm.assume intrinsic to
> > > implement a
> > > __builtin_assume(bool) intrinsic (to provide additional information
> > > to the
> > > optimizer). This hooks up __assume in MS-compatibility mode to
> > > mirror
> > > __builtin_assume (the semantics have been intentionally kept
> > > compatible), and
> > > implements GCC's __builtin_assume_aligned as assume((p - o) & mask
> > > ==
> > > 0). LLVM
> > > now contains special logic to deal with assumptions of this form.
> > >
> > > Added:
> > > cfe/trunk/test/CodeGen/builtin-assume-aligned.c
> > > cfe/trunk/test/Sema/builtin-assume-aligned.c
> > > cfe/trunk/test/SemaCXX/builtin-assume-aligned-tmpl.cpp
> > > Modified:
> > > cfe/trunk/docs/LanguageExtensions.rst
> > > cfe/trunk/include/clang/Basic/Builtins.def
> > > cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> > > cfe/trunk/include/clang/Sema/Sema.h
> > > cfe/trunk/lib/AST/ExprConstant.cpp
> > > cfe/trunk/lib/CodeGen/CGBuiltin.cpp
> > > cfe/trunk/lib/CodeGen/CGExpr.cpp
> > > cfe/trunk/lib/CodeGen/CodeGenFunction.h
> > > cfe/trunk/lib/Sema/SemaChecking.cpp
> > > cfe/trunk/lib/Sema/SemaDeclAttr.cpp
> > > cfe/trunk/test/CodeGen/builtin-assume.c
> > > cfe/trunk/test/Sema/builtin-assume.c
> > >
> > > Modified: cfe/trunk/docs/LanguageExtensions.rst
> > > URL:
> > >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LanguageExtensions.rst?rev=217349&r1=217348&r2=217349&view=diff
> > >
> ==============================================================================
> > > --- cfe/trunk/docs/LanguageExtensions.rst (original)
> > > +++ cfe/trunk/docs/LanguageExtensions.rst Sun Sep 7 17:58:14 2014
> > > @@ -1228,8 +1228,9 @@ Builtin Functions
> > > Clang supports a number of builtin library functions with the same
> > > syntax as
> > > GCC, including things like ``__builtin_nan``,
> > > ``__builtin_constant_p``,
> > > ``__builtin_choose_expr``, ``__builtin_types_compatible_p``,
> > > -``__sync_fetch_and_add``, etc. In addition to the GCC builtins,
> > > Clang supports
> > > -a number of builtins that GCC does not, which are listed here.
> > > +``__builtin_assume_aligned``, ``__sync_fetch_and_add``, etc. In
> > > addition to
> > > +the GCC builtins, Clang supports a number of builtins that GCC
> > > does
> > > not, which
> > > +are listed here.
> > >
> > > Please note that Clang does not and will not support all of the GCC
> > > builtins
> > > for vector operations. Instead of using builtins, you should use
> > > the
> > > functions
> > > @@ -1239,6 +1240,42 @@ implemented directly in terms of :ref:`e
> > > <langext-vectors>` instead of builtins, in order to reduce the
> > > number
> > > of
> > > builtins that we need to implement.
> > >
> > > +``__builtin_assume``
> > > +------------------------------
> > > +
> > > +``__builtin_assume`` is used to provide the optimizer with a
> > > boolean
> > > +invariant that is defined to be true.
> > > +
> > > +**Syntax**:
> > > +
> > > +.. code-block:: c++
> > > +
> > > + __builtin_assume(bool)
> > > +
> > > +**Example of Use**:
> > > +
> > > +.. code-block:: c++
> > > +
> > > + int foo(int x) {
> > > + __builtin_assume(x != 0);
> > > +
> > > + // The optimizer may short-circuit this check using the
> > > invariant.
> > > + if (x == 0)
> > > + return do_something();
> > > +
> > > + return do_something_else();
> > > + }
> > > +
> > > +**Description**:
> > > +
> > > +The boolean argument to this function is defined to be true. The
> > > optimizer may
> > > +analyze the form of the expression provided as the argument and
> > > deduce from
> > > +that information used to optimize the program. If the condition is
> > > violated
> > > +during execution, the behavior is undefined. The argument itself
> > > is
> > > never
> > > +evaluated, so any side effects of the expression will be
> > > discarded.
> > > +
> > > +Query for this feature with ``__has_builtin(__builtin_assume)``.
> > > +
> > > ``__builtin_readcyclecounter``
> > > ------------------------------
> > >
> > >
> > > Modified: cfe/trunk/include/clang/Basic/Builtins.def
> > > URL:
> > >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Builtins.def?rev=217349&r1=217348&r2=217349&view=diff
> > >
> ==============================================================================
> > > --- cfe/trunk/include/clang/Basic/Builtins.def (original)
> > > +++ cfe/trunk/include/clang/Basic/Builtins.def Sun Sep 7 17:58:14
> > > 2014
> > > @@ -412,6 +412,7 @@ BUILTIN(__builtin_va_start, "vA.", "nt")
> > > BUILTIN(__builtin_va_end, "vA", "n")
> > > BUILTIN(__builtin_va_copy, "vAA", "n")
> > > BUILTIN(__builtin_stdarg_start, "vA.", "n")
> > > +BUILTIN(__builtin_assume_aligned, "v*vC*z.", "nc")
> > > BUILTIN(__builtin_bcmp, "iv*v*z", "n")
> > > BUILTIN(__builtin_bcopy, "vv*v*z", "n")
> > > BUILTIN(__builtin_bzero, "vv*z", "nF")
> > > @@ -1173,6 +1174,9 @@ LIBBUILTIN(_Block_object_dispose, "vvC*i
> > > // Annotation function
> > > BUILTIN(__builtin_annotation, "v.", "tn")
> > >
> > > +// Invariants
> > > +BUILTIN(__builtin_assume, "vb", "n")
> > > +
> > > // Multiprecision Arithmetic Builtins.
> > > BUILTIN(__builtin_addcb, "UcUcCUcCUcCUc*", "n")
> > > BUILTIN(__builtin_addcs, "UsUsCUsCUsCUs*", "n")
> > >
> > > Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> > > URL:
> > >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=217349&r1=217348&r2=217349&view=diff
> > >
> ==============================================================================
> > > --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> > > +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun Sep 7
> > > 17:58:14 2014
> > > @@ -451,7 +451,7 @@ def note_strncat_wrong_size : Note<
> > > "the terminating null byte">;
> > >
> > > def warn_assume_side_effects : Warning<
> > > - "the argument to __assume has side effects that will be
> > > discarded">,
> > > + "the argument to %0 has side effects that will be discarded">,
> > > InGroup<DiagGroup<"assume">>;
> > >
> > > /// main()
> > > @@ -2078,8 +2078,9 @@ def err_no_accessor_for_property : Error
> > > def error_cannot_find_suitable_accessor : Error<
> > > "cannot find suitable %select{getter|setter}0 for property %1">;
> > >
> > > -def err_attribute_aligned_not_power_of_two : Error<
> > > +def err_alignment_not_power_of_two : Error<
> > > "requested alignment is not a power of 2">;
> > > +
> > > def err_attribute_aligned_too_great : Error<
> > > "requested alignment must be %0 bytes or smaller">;
> > > def warn_redeclaration_without_attribute_prev_attribute_ignored :
> > > Warning<
> > >
> > > Modified: cfe/trunk/include/clang/Sema/Sema.h
> > > URL:
> > >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=217349&r1=217348&r2=217349&view=diff
> > >
> ==============================================================================
> > > --- cfe/trunk/include/clang/Sema/Sema.h (original)
> > > +++ cfe/trunk/include/clang/Sema/Sema.h Sun Sep 7 17:58:14 2014
> > > @@ -8375,6 +8375,7 @@ public:
> > > private:
> > > bool SemaBuiltinPrefetch(CallExpr *TheCall);
> > > bool SemaBuiltinAssume(CallExpr *TheCall);
> > > + bool SemaBuiltinAssumeAligned(CallExpr *TheCall);
> > > bool SemaBuiltinLongjmp(CallExpr *TheCall);
> > > ExprResult SemaBuiltinAtomicOverloaded(ExprResult TheCallResult);
> > > ExprResult SemaAtomicOpsOverloaded(ExprResult TheCallResult,
> > >
> > > Modified: cfe/trunk/lib/AST/ExprConstant.cpp
> > > URL:
> > >
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=217349&r1=217348&r2=217349&view=diff
> > >
> ==============================================================================
> > > --- cfe/trunk/lib/AST/ExprConstant.cpp (original)
> > > +++ cfe/trunk/lib/AST/ExprConstant.cpp Sun Sep 7 17:58:14 2014
> > > @@ -6092,6 +6092,7 @@ bool IntExprEvaluator::VisitCallExpr(con
> > > return Success(Operand, E);
> > > }
> > >
> > > + case Builtin::BI__builtin_assume_aligned:
> > > case Builtin::BI__builtin_expect:
> > > return Visit(E->getArg(0));
> > >
> > >
> > >
> > > We should evaluate (and discard) argument 1 and (if present)
> > > argument
> > > 2 here too, in case they have side-effects or are non-constant.
> >
> > Actually, I'm having trouble coming up with a test-case for this.
> >
> > First, argument 1 is restricted to being a constant integer, and I
> > don't think it can have side-effects. Maybe this is not quite right,
> > but currently we get:
> > error: argument to '__builtin_assume_aligned' must be a constant
> > integer
> > return __builtin_assume_aligned((int*) 0xfffff000, (++i, 16), i);
> > ^ ~~~~~~~~~
> >
> > For argument 2, this can have side effects, but even when the pointer
> > argument is constant, I don't see things being folded (and, thus, I
> > don't see side-effects as being dropped). For example:
> >
> > int foob() {
> > if (((int*) 0xfffff000) == (int*)0)
> > return 0;
> > else
> > return 1;
> > }
> >
> > produces (-O3 -mllvm -disable-llvm-optzns):
> >
> > define i32 @foob() #0 {
> > entry:
> > ret i32 1
> > }
> >
> > but this:
> >
> > int foo5(int i) {
> > if ((int*)__builtin_assume_aligned((int*) 0xfffff000, 16, i) ==
> > (int*)0)
> > return 0;
> > else
> > return 1;
> > }
> >
> > does not fold (and changing argument 2 from i to ++i does lead to a
> > dropped side effect). Maybe this related to the fact that
> > Expr::HasSideEffects always returns true for CallExprClass?
> >
> >
> > Try this (in C++11 onwards):
> >
> >
> > int n;
> > constexpr int *p = 0;
> > constexpr int k = __builtin_assume_aligned(p, 16, n = 5);
> >
> >
> > We should reject; I suspect we won't.
>
> But, as it turns out, we do:
>
> $ cat /tmp/bac.cpp
> int n;
> constexpr int *p = 0;
> constexpr int *k =  (int *) __builtin_assume_aligned(p, 16, n = 5);
>
> $ clang++ -std=c++11 -S -emit-llvm -o - /tmp/bac.cpp
> /tmp/bac.cpp:3:29: error: constexpr variable 'k' must be initialized by a
> constant expression
> constexpr int *k =  (int *) __builtin_assume_aligned(p, 16, n = 5);
>                     ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 1 error generated.
>
> >
> >
> > Hmm, also... should __builtin_assume* be non-constant when the
> > assumption does not hold? In C++11 we have a general rule that
> > undefined behavior is non-constant, and assumption failure seems
> > like it should be UB.
>
> Agreed, although it seems to be currently not an issue because it does not
> work regardless.


Oh, I see. It doesn't work because this code was added to the wrong place:

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL:
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=217349&r1=217348&r2=217349&view=diff
============================================================
==================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Sun Sep  7 17:58:14 2014
@@ -6092,6 +6092,7 @@ bool IntExprEvaluator::VisitCallExpr(con
     return Success(Operand, E);
   }

+  case Builtin::BI__builtin_assume_aligned:
   case Builtin::BI__builtin_expect:
     return Visit(E->getArg(0));

This is inside IntExprEvaluator, but a call to __builtin_assume_aligned
does not have integral type. Maybe revert this hunk?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20141002/acb0bcad/attachment.html>


More information about the cfe-commits mailing list