diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -2016,7 +2016,8 @@ For example, ``0b10000110`` rotated left by 11 becomes ``0b00110100``. The shift value is treated as an unsigned amount modulo the size of the arguments. Both arguments and the result have the bitwidth specified -by the name of the builtin. +by the name of the builtin. These builtins can be used within constant +expressions. ``__builtin_rotateright`` ------------------------- @@ -2048,7 +2049,8 @@ For example, ``0b10000110`` rotated right by 3 becomes ``0b11010000``. The shift value is treated as an unsigned amount modulo the size of the arguments. Both arguments and the result have the bitwidth specified -by the name of the builtin. +by the name of the builtin. These builtins can be used within constant +expressions. ``__builtin_unreachable`` ------------------------- diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -56,7 +56,13 @@ Non-comprehensive list of changes in this release ------------------------------------------------- -- ... +- The builtin intrinsics ``__builtin_rotateleft8``, ``__builtin_rotateleft16``, + ``__builtin_rotateleft32`` and ``__builtin_rotateleft64`` may now be used + within constant expressions. + +- The builtin intrinsics ``__builtin_rotateright8``, ``__builtin_rotateright16``, + ``__builtin_rotateright32`` and ``__builtin_rotateright64`` may now be used + within constant expressions. New Compiler Flags ------------------ diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -11347,6 +11347,30 @@ return Success(Val.countPopulation(), E); } + case Builtin::BI__builtin_rotateleft8: + case Builtin::BI__builtin_rotateleft16: + case Builtin::BI__builtin_rotateleft32: + case Builtin::BI__builtin_rotateleft64: { + APSInt Val, Amt; + if (!EvaluateInteger(E->getArg(0), Val, Info) || + !EvaluateInteger(E->getArg(1), Amt, Info)) + return false; + + return Success(Val.rotl(Amt.urem(Val.getBitWidth())), E); + } + + case Builtin::BI__builtin_rotateright8: + case Builtin::BI__builtin_rotateright16: + case Builtin::BI__builtin_rotateright32: + case Builtin::BI__builtin_rotateright64: { + APSInt Val, Amt; + if (!EvaluateInteger(E->getArg(0), Val, Info) || + !EvaluateInteger(E->getArg(1), Amt, Info)) + return false; + + return Success(Val.rotr(Amt.urem(Val.getBitWidth())), E); + } + case Builtin::BIstrlen: case Builtin::BIwcslen: // A call to strlen is not a constant expression. diff --git a/clang/test/Sema/constant-builtins-2.c b/clang/test/Sema/constant-builtins-2.c --- a/clang/test/Sema/constant-builtins-2.c +++ b/clang/test/Sema/constant-builtins-2.c @@ -169,6 +169,16 @@ char parity9[__builtin_parityl(1L << (BITSIZE(long) - 1)) == 1 ? 1 : -1]; char parity10[__builtin_parityll(1LL << (BITSIZE(long long) - 1)) == 1 ? 1 : -1]; +char rotateleft1[__builtin_rotateleft8(0x01, 5) == 0x20 ? 1 : -1]; +char rotateleft2[__builtin_rotateleft16(0x3210, 11) == 0x8190 ? 1 : -1]; +char rotateleft2[__builtin_rotateleft32(0x76543210, 22) == 0x841D950C ? 1 : -1]; +char rotateleft2[__builtin_rotateleft64(0xFEDCBA9876543210ULL, 55) == 0x87F6E5D4C3B2A19ULL ? 1 : -1]; + +char rotateright1[__builtin_rotateright8(0x01, 5) == 0x08 ? 1 : -1]; +char rotateright2[__builtin_rotateright16(0x3210, 11) == 0x4206 ? 1 : -1]; +char rotateright2[__builtin_rotateright32(0x76543210, 22) == 0x50C841D9 ? 1 : -1]; +char rotateright2[__builtin_rotateright64(0xFEDCBA9876543210ULL, 55) == 0xB97530ECA86421FDULL ? 1 : -1]; + char ffs1[__builtin_ffs(0) == 0 ? 1 : -1]; char ffs2[__builtin_ffs(1) == 1 ? 1 : -1]; char ffs3[__builtin_ffs(0xfbe71) == 1 ? 1 : -1];