Skip to content

Commit

Permalink
[clang] constexpr built-in reduce min/max function. (llvm#120866)
Browse files Browse the repository at this point in the history
Part of llvm#51787.

This patch adds constexpr support for the built-in reduce min/max
function.
  • Loading branch information
c8ef authored Dec 23, 2024
1 parent 34d55df commit dd577c0
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 7 deletions.
7 changes: 4 additions & 3 deletions clang/docs/LanguageExtensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -736,9 +736,10 @@ at the end to the next power of 2.

These reductions support both fixed-sized and scalable vector types.

The integer reduction intrinsics, including ``__builtin_reduce_add``,
``__builtin_reduce_mul``, ``__builtin_reduce_and``, ``__builtin_reduce_or``,
and ``__builtin_reduce_xor``, can be called in a ``constexpr`` context.
The integer reduction intrinsics, including ``__builtin_reduce_max``,
``__builtin_reduce_min``, ``__builtin_reduce_add``, ``__builtin_reduce_mul``,
``__builtin_reduce_and``, ``__builtin_reduce_or``, and ``__builtin_reduce_xor``,
can be called in a ``constexpr`` context.

Example:

Expand Down
3 changes: 2 additions & 1 deletion clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,8 @@ Non-comprehensive list of changes in this release
``__builtin_reduce_mul``, ``__builtin_reduce_and``, ``__builtin_reduce_or``,
``__builtin_reduce_xor``, ``__builtin_elementwise_popcount``,
``__builtin_elementwise_bitreverse``, ``__builtin_elementwise_add_sat``,
``__builtin_elementwise_sub_sat``.
``__builtin_elementwise_sub_sat``, ``__builtin_reduce_min`` (For integral element type),
``__builtin_reduce_max`` (For integral element type).

- Clang now rejects ``_BitInt`` matrix element types if the bit width is less than ``CHAR_WIDTH`` or
not a power of two, matching preexisting behaviour for vector types.
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Basic/Builtins.td
Original file line number Diff line number Diff line change
Expand Up @@ -1462,13 +1462,13 @@ def ElementwiseSubSat : Builtin {

def ReduceMax : Builtin {
let Spellings = ["__builtin_reduce_max"];
let Attributes = [NoThrow, Const, CustomTypeChecking];
let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr];
let Prototype = "void(...)";
}

def ReduceMin : Builtin {
let Spellings = ["__builtin_reduce_min"];
let Attributes = [NoThrow, Const, CustomTypeChecking];
let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr];
let Prototype = "void(...)";
}

Expand Down
12 changes: 11 additions & 1 deletion clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13604,7 +13604,9 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
case Builtin::BI__builtin_reduce_mul:
case Builtin::BI__builtin_reduce_and:
case Builtin::BI__builtin_reduce_or:
case Builtin::BI__builtin_reduce_xor: {
case Builtin::BI__builtin_reduce_xor:
case Builtin::BI__builtin_reduce_min:
case Builtin::BI__builtin_reduce_max: {
APValue Source;
if (!EvaluateAsRValue(Info, E->getArg(0), Source))
return false;
Expand Down Expand Up @@ -13641,6 +13643,14 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
Reduced ^= Source.getVectorElt(EltNum).getInt();
break;
}
case Builtin::BI__builtin_reduce_min: {
Reduced = std::min(Reduced, Source.getVectorElt(EltNum).getInt());
break;
}
case Builtin::BI__builtin_reduce_max: {
Reduced = std::max(Reduced, Source.getVectorElt(EltNum).getInt());
break;
}
}
}

Expand Down
15 changes: 15 additions & 0 deletions clang/test/Sema/constant_builtins_vector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,21 @@ static_assert(__builtin_reduce_xor((vector4long){(long long)0x1111111111111111L,
static_assert(__builtin_reduce_xor((vector4uint){0x11111111U, 0x22222222U, 0x44444444U, 0x88888888U}) == 0xFFFFFFFFU);
static_assert(__builtin_reduce_xor((vector4ulong){0x1111111111111111UL, 0x2222222222222222UL, 0x4444444444444444UL, 0x8888888888888888UL}) == 0xFFFFFFFFFFFFFFFFUL);

static_assert(__builtin_reduce_min((vector4char){}) == 0);
static_assert(__builtin_reduce_min((vector4char){(char)0x11, (char)0x22, (char)0x44, (char)0x88}) == (char)0x88);
static_assert(__builtin_reduce_min((vector4short){(short)0x1111, (short)0x2222, (short)0x4444, (short)0x8888}) == (short)0x8888);
static_assert(__builtin_reduce_min((vector4int){(int)0x11111111, (int)0x22222222, (int)0x44444444, (int)0x88888888}) == (int)0x88888888);
static_assert(__builtin_reduce_min((vector4long){(long long)0x1111111111111111L, (long long)0x2222222222222222L, (long long)0x4444444444444444L, (long long)0x8888888888888888L}) == (long long)0x8888888888888888L);
static_assert(__builtin_reduce_min((vector4uint){0x11111111U, 0x22222222U, 0x44444444U, 0x88888888U}) == 0x11111111U);
static_assert(__builtin_reduce_min((vector4ulong){0x1111111111111111UL, 0x2222222222222222UL, 0x4444444444444444UL, 0x8888888888888888UL}) == 0x1111111111111111UL);
static_assert(__builtin_reduce_max((vector4char){}) == 0);
static_assert(__builtin_reduce_max((vector4char){(char)0x11, (char)0x22, (char)0x44, (char)0x88}) == (char)0x44);
static_assert(__builtin_reduce_max((vector4short){(short)0x1111, (short)0x2222, (short)0x4444, (short)0x8888}) == (short)0x4444);
static_assert(__builtin_reduce_max((vector4int){(int)0x11111111, (int)0x22222222, (int)0x44444444, (int)0x88888888}) == (int)0x44444444);
static_assert(__builtin_reduce_max((vector4long){(long long)0x1111111111111111L, (long long)0x2222222222222222L, (long long)0x4444444444444444L, (long long)0x8888888888888888L}) == (long long)0x4444444444444444L);
static_assert(__builtin_reduce_max((vector4uint){0x11111111U, 0x22222222U, 0x44444444U, 0x88888888U}) == 0x88888888U);
static_assert(__builtin_reduce_max((vector4ulong){0x1111111111111111UL, 0x2222222222222222UL, 0x4444444444444444UL, 0x8888888888888888UL}) == 0x8888888888888888UL);

static_assert(__builtin_bit_cast(unsigned, __builtin_elementwise_popcount((vector4char){1, 2, 3, 4})) == (LITTLE_END ? 0x01020101 : 0x01010201));
static_assert(__builtin_bit_cast(unsigned long long, __builtin_elementwise_popcount((vector4short){0, 0x0F0F, ~0, ~0x0F0F})) == (LITTLE_END ? 0x0008001000080000 : 0x0000000800100008));
static_assert(__builtin_reduce_add(__builtin_elementwise_popcount((vector4int){1, 2, 3, 4})) == 5);
Expand Down

0 comments on commit dd577c0

Please sign in to comment.