Skip to content

Commit 487266d

Browse files
committed
[Clang] Enable constexpr handling for builtin elementwise fshl/fshr
1 parent 0810505 commit 487266d

File tree

4 files changed

+186
-2
lines changed

4 files changed

+186
-2
lines changed

clang/include/clang/Basic/Builtins.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1528,13 +1528,13 @@ def ElementwiseSubSat : Builtin {
15281528

15291529
def ElementwiseFshl : Builtin {
15301530
let Spellings = ["__builtin_elementwise_fshl"];
1531-
let Attributes = [NoThrow, Const, CustomTypeChecking];
1531+
let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr];
15321532
let Prototype = "void(...)";
15331533
}
15341534

15351535
def ElementwiseFshr : Builtin {
15361536
let Spellings = ["__builtin_elementwise_fshr"];
1537-
let Attributes = [NoThrow, Const, CustomTypeChecking];
1537+
let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr];
15381538
let Prototype = "void(...)";
15391539
}
15401540

clang/lib/AST/ByteCode/InterpBuiltin.cpp

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2813,7 +2813,83 @@ static bool interp__builtin_select(InterpState &S, CodePtr OpPC,
28132813
}
28142814
}
28152815
Dst.initializeAllElements();
2816+
return true;
2817+
}
2818+
2819+
static bool interp__builtin_elementwise_fsh(InterpState &S, CodePtr OpPC,
2820+
const CallExpr *Call,
2821+
unsigned BuiltinID) {
2822+
assert(Call->getNumArgs() == 3);
2823+
2824+
const QualType Arg1Type = Call->getArg(0)->getType();
2825+
const QualType Arg2Type = Call->getArg(1)->getType();
2826+
const QualType Arg3Type = Call->getArg(2)->getType();
2827+
2828+
// Non-vector integer types.
2829+
if (!Arg1Type->isVectorType()) {
2830+
assert(!Arg2Type->isVectorType());
2831+
assert(!Arg3Type->isVectorType());
2832+
2833+
APSInt Shift = popToAPSInt(
2834+
S.Stk, *S.getContext().classify(Call->getArg(2)->getType()));
2835+
APSInt Lo = popToAPSInt(
2836+
S.Stk, *S.getContext().classify(Call->getArg(1)->getType()));
2837+
APSInt Hi = popToAPSInt(
2838+
S.Stk, *S.getContext().classify(Call->getArg(0)->getType()));
2839+
APSInt Result;
2840+
if (BuiltinID == Builtin::BI__builtin_elementwise_fshl) {
2841+
Result = APSInt(llvm::APIntOps::fshl(Hi, Lo, Shift), Hi.isUnsigned());
2842+
} else if (BuiltinID == Builtin::BI__builtin_elementwise_fshr) {
2843+
Result = APSInt(llvm::APIntOps::fshr(Hi, Lo, Shift), Hi.isUnsigned());
2844+
} else {
2845+
llvm_unreachable("Wrong builtin ID");
2846+
}
2847+
pushInteger(S, Result, Call->getType());
2848+
return true;
2849+
}
2850+
2851+
// Vector type.
2852+
assert(Arg1Type->isVectorType() &&
2853+
Arg2Type->isVectorType() &&
2854+
Arg3Type->isVectorType());
2855+
2856+
const VectorType *VecT = Arg1Type->castAs<VectorType>();
2857+
PrimType ElemT = *S.getContext().classify(VecT->getElementType());
2858+
unsigned NumElems = VecT->getNumElements();
2859+
2860+
assert(VecT->getElementType() ==
2861+
Arg2Type->castAs<VectorType>()->getElementType() &&
2862+
VecT->getElementType() ==
2863+
Arg3Type->castAs<VectorType>()->getElementType());
2864+
assert(NumElems == Arg2Type->castAs<VectorType>()->getNumElements() &&
2865+
NumElems == Arg3Type->castAs<VectorType>()->getNumElements());
2866+
assert(VecT->getElementType()->isIntegralOrEnumerationType());
28162867

2868+
const Pointer &VecShift = S.Stk.pop<Pointer>();
2869+
const Pointer &VecLo = S.Stk.pop<Pointer>();
2870+
const Pointer &VecHi = S.Stk.pop<Pointer>();
2871+
const Pointer &Dst = S.Stk.peek<Pointer>();
2872+
for (unsigned I = 0; I != NumElems; ++I) {
2873+
APSInt Hi;
2874+
APSInt Lo;
2875+
APSInt Shift;
2876+
INT_TYPE_SWITCH_NO_BOOL(ElemT, {
2877+
Hi = VecHi.elem<T>(I).toAPSInt();
2878+
Lo = VecLo.elem<T>(I).toAPSInt();
2879+
Shift = VecShift.elem<T>(I).toAPSInt();
2880+
});
2881+
APSInt Result;
2882+
if (BuiltinID == Builtin::BI__builtin_elementwise_fshl) {
2883+
Result = APSInt(llvm::APIntOps::fshl(Hi, Lo, Shift), Hi.isUnsigned());
2884+
} else if (BuiltinID == Builtin::BI__builtin_elementwise_fshr) {
2885+
Result = APSInt(llvm::APIntOps::fshr(Hi, Lo, Shift), Hi.isUnsigned());
2886+
} else {
2887+
llvm_unreachable("Wrong builtin ID");
2888+
}
2889+
INT_TYPE_SWITCH_NO_BOOL(ElemT,
2890+
{ Dst.elem<T>(I) = static_cast<T>(Result); });
2891+
}
2892+
Dst.initializeAllElements();
28172893
return true;
28182894
}
28192895

@@ -3279,6 +3355,10 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
32793355
case X86::BI__builtin_ia32_selectpd_512:
32803356
return interp__builtin_select(S, OpPC, Call);
32813357

3358+
case Builtin::BI__builtin_elementwise_fshl:
3359+
case Builtin::BI__builtin_elementwise_fshr:
3360+
return interp__builtin_elementwise_fsh(S, OpPC, Call, BuiltinID);
3361+
32823362
default:
32833363
S.FFDiag(S.Current->getLocation(OpPC),
32843364
diag::note_invalid_subexpr_in_const_expr)

clang/lib/AST/ExprConstant.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11941,6 +11941,40 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
1194111941
}
1194211942
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
1194311943
}
11944+
11945+
case Builtin::BI__builtin_elementwise_fshl:
11946+
case Builtin::BI__builtin_elementwise_fshr: {
11947+
APValue SourceHi, SourceLo, SourceShift;
11948+
if (!EvaluateAsRValue(Info, E->getArg(0), SourceHi) ||
11949+
!EvaluateAsRValue(Info, E->getArg(1), SourceLo) ||
11950+
!EvaluateAsRValue(Info, E->getArg(2), SourceShift))
11951+
return false;
11952+
11953+
QualType DestEltTy = E->getType()->castAs<VectorType>()->getElementType();
11954+
11955+
if (!DestEltTy->isIntegerType())
11956+
return false;
11957+
11958+
unsigned SourceLen = SourceHi.getVectorLength();
11959+
SmallVector<APValue> ResultElements;
11960+
ResultElements.reserve(SourceLen);
11961+
11962+
for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
11963+
APSInt Hi = SourceHi.getVectorElt(EltNum).getInt();
11964+
APSInt Lo = SourceLo.getVectorElt(EltNum).getInt();
11965+
APSInt Shift = SourceShift.getVectorElt(EltNum).getInt();
11966+
switch (E->getBuiltinCallee()) {
11967+
case Builtin::BI__builtin_elementwise_fshl:
11968+
ResultElements.push_back(APValue(APSInt(llvm::APIntOps::fshl(Hi, Lo, Shift), Hi.isUnsigned())));
11969+
break;
11970+
case Builtin::BI__builtin_elementwise_fshr:
11971+
ResultElements.push_back(APValue(APSInt(llvm::APIntOps::fshr(Hi, Lo, Shift), Hi.isUnsigned())));
11972+
break;
11973+
}
11974+
}
11975+
11976+
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
11977+
}
1194411978
}
1194511979
}
1194611980

@@ -13879,6 +13913,28 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
1387913913
APInt Result = std::min(LHS, RHS);
1388013914
return Success(APSInt(Result, !LHS.isSigned()), E);
1388113915
}
13916+
case Builtin::BI__builtin_elementwise_fshl:
13917+
case Builtin::BI__builtin_elementwise_fshr: {
13918+
if (!E->getArg(0)->isPRValue() ||
13919+
!E->getArg(1)->isPRValue() ||
13920+
!E->getArg(2)->isPRValue())
13921+
return false;
13922+
APSInt Hi, Lo, Shift;
13923+
if (!EvaluateInteger(E->getArg(0), Hi, Info) ||
13924+
!EvaluateInteger(E->getArg(1), Lo, Info) ||
13925+
!EvaluateInteger(E->getArg(2), Shift, Info))
13926+
return false;
13927+
switch (BuiltinOp) {
13928+
case Builtin::BI__builtin_elementwise_fshl: {
13929+
APSInt Result(llvm::APIntOps::fshl(Hi, Lo, Shift), Hi.isUnsigned());
13930+
return Success(Result, E);
13931+
}
13932+
case Builtin::BI__builtin_elementwise_fshr: {
13933+
APSInt Result(llvm::APIntOps::fshr(Hi, Lo, Shift), Hi.isUnsigned());
13934+
return Success(Result, E);
13935+
}
13936+
}
13937+
}
1388213938
case Builtin::BIstrlen:
1388313939
case Builtin::BIwcslen:
1388413940
// A call to strlen is not a constant expression.

clang/test/Sema/constant-builtins-vector.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -961,3 +961,51 @@ static_assert(fmaDouble1[3] == 26.0);
961961
constexpr float fmaArray[] = {2.0f, 2.0f, 2.0f, 2.0f};
962962
constexpr float fmaResult = __builtin_elementwise_fma(fmaArray[1], fmaArray[2], fmaArray[3]);
963963
static_assert(fmaResult == 6.0f, "");
964+
965+
static_assert(__builtin_elementwise_fshl((unsigned char)255, (unsigned char)0, (unsigned char)8) == (unsigned char)255);
966+
static_assert(__builtin_elementwise_fshl((char)127, (char)0, (char)8) == (char)127);
967+
static_assert(__builtin_elementwise_fshl((unsigned char)0, (unsigned char)255, (unsigned char)8) == (unsigned char)0);
968+
static_assert(__builtin_elementwise_fshl((char)0, (char)127, (char)8) == (char)0);
969+
static_assert(__builtin_elementwise_fshr((unsigned char)255, (unsigned char)0, (unsigned char)8) == (unsigned char)0);
970+
static_assert(__builtin_elementwise_fshr((char)127, (char)0, (char)8) == (char)0);
971+
static_assert(__builtin_elementwise_fshr((unsigned char)0, (unsigned char)255, (unsigned char)8) == (unsigned char)255);
972+
static_assert(__builtin_elementwise_fshr((char)0, (char)127, (char)8) == (char)127);
973+
static_assert(__builtin_elementwise_fshl((unsigned int)4294967295, (unsigned int)0, (unsigned int)32) == (unsigned int)4294967295);
974+
static_assert(__builtin_elementwise_fshl((int)2147483647, (int)0, (int)32) == (int)2147483647);
975+
static_assert(__builtin_elementwise_fshl((unsigned int)0, (unsigned int)4294967295, (unsigned int)32) == (unsigned int)0);
976+
static_assert(__builtin_elementwise_fshl((int)0, (int)2147483647, (int)32) == (int)0);
977+
static_assert(__builtin_elementwise_fshr((unsigned int)4294967295, (unsigned int)0, (unsigned int)32) == (unsigned int)0);
978+
static_assert(__builtin_elementwise_fshr((int)2147483647, (int)0, (int)32) == (int)0);
979+
static_assert(__builtin_elementwise_fshr((unsigned int)0, (unsigned int)4294967295, (unsigned int)32) == (unsigned int)4294967295);
980+
static_assert(__builtin_elementwise_fshr((int)0, (int)2147483647, (int)32) == (int)2147483647);
981+
static_assert(__builtin_elementwise_fshl((unsigned long long)18446744073709551615ULL, (unsigned long long)0, (unsigned long long)64) == (unsigned long long)18446744073709551615ULL);
982+
static_assert(__builtin_elementwise_fshl((long long)9223372036854775807, (long long)0, (long long)64) == (long long)9223372036854775807);
983+
static_assert(__builtin_elementwise_fshl((unsigned long long)0, (unsigned long long)18446744073709551615ULL, (unsigned long long)64) == (unsigned long long)0);
984+
static_assert(__builtin_elementwise_fshl((long long)0, (long long)9223372036854775807, (long long)64) == (long long)0);
985+
static_assert(__builtin_elementwise_fshr((unsigned long long)18446744073709551615ULL, (unsigned long long)0, (unsigned long long)64) == (unsigned long long)0);
986+
static_assert(__builtin_elementwise_fshr((long long)9223372036854775807, (long long)0, (long long)64) == (long long)0);
987+
static_assert(__builtin_elementwise_fshr((unsigned long long)0, (unsigned long long)18446744073709551615ULL, (unsigned long long)64) == (unsigned long long)18446744073709551615ULL);
988+
static_assert(__builtin_elementwise_fshr((long long)0, (long long)9223372036854775807, (long long)64) == (long long)9223372036854775807);
989+
//
990+
static_assert(__builtin_elementwise_fshl((short) 1, (short) 2, (short) 3) == (short)8);
991+
static_assert(__builtin_elementwise_fshl((short) 2, (short) 1, (short) 3) == (short)16);
992+
static_assert(__builtin_elementwise_fshl(1, 2 , 2) == 4);
993+
static_assert(__builtin_elementwise_fshl(2L, 1L , 2L) == 8L);
994+
static_assert(__builtin_elementwise_fshr((unsigned char)1, (unsigned char)2, (unsigned char)3) == (unsigned char)32);
995+
//
996+
constexpr vector4uchar v4s_fshl_var =
997+
__builtin_elementwise_fshl((vector4uchar){255, 15, 0, 2},
998+
(vector4uchar){0, 15, 255, 1},
999+
(vector4uchar){15, 11, 8, 3});
1000+
static_assert(v4s_fshl_var[0] == 128);
1001+
static_assert(v4s_fshl_var[1] == 120);
1002+
static_assert(v4s_fshl_var[2] == 0);
1003+
static_assert(v4s_fshl_var[3] == 16);
1004+
constexpr vector4uchar v4s_fshr_var =
1005+
__builtin_elementwise_fshr((vector4uchar){255, 15, 0, 1},
1006+
(vector4uchar){0, 15, 255, 2},
1007+
(vector4uchar){15, 11, 8, 3});
1008+
static_assert(v4s_fshr_var[0] == 254);
1009+
static_assert(v4s_fshr_var[1] == 225);
1010+
static_assert(v4s_fshr_var[2] == 255);
1011+
static_assert(v4s_fshr_var[3] == 32);

0 commit comments

Comments
 (0)