18
18
#include " clang/Basic/TargetBuiltins.h"
19
19
#include " clang/Basic/TargetInfo.h"
20
20
#include " llvm/ADT/StringExtras.h"
21
+ #include " llvm/Support/ErrorHandling.h"
21
22
#include " llvm/Support/SipHash.h"
22
23
23
24
namespace clang {
@@ -1673,6 +1674,12 @@ static bool interp__builtin_vector_reduce(InterpState &S, CodePtr OpPC,
1673
1674
(void )T::bitOr (Result, Elem, BitWidth, &Result);
1674
1675
} else if (ID == Builtin::BI__builtin_reduce_xor) {
1675
1676
(void )T::bitXor (Result, Elem, BitWidth, &Result);
1677
+ } else if (ID == Builtin::BI__builtin_reduce_min) {
1678
+ if (Elem < Result)
1679
+ Result = Elem;
1680
+ } else if (ID == Builtin::BI__builtin_reduce_max) {
1681
+ if (Elem > Result)
1682
+ Result = Elem;
1676
1683
} else {
1677
1684
llvm_unreachable (" Unhandled vector reduce builtin" );
1678
1685
}
@@ -1686,12 +1693,18 @@ static bool interp__builtin_vector_reduce(InterpState &S, CodePtr OpPC,
1686
1693
// / Can be called with an integer or vector as the first and only parameter.
1687
1694
static bool interp__builtin_elementwise_popcount (InterpState &S, CodePtr OpPC,
1688
1695
const InterpFrame *Frame,
1689
- const CallExpr *Call) {
1696
+ const CallExpr *Call,
1697
+ unsigned BuiltinID) {
1690
1698
assert (Call->getNumArgs () == 1 );
1691
1699
if (Call->getArg (0 )->getType ()->isIntegerType ()) {
1692
1700
PrimType ArgT = *S.getContext ().classify (Call->getArg (0 )->getType ());
1693
1701
APSInt Val = popToAPSInt (S.Stk , ArgT);
1694
- pushInteger (S, Val.popcount (), Call->getType ());
1702
+
1703
+ if (BuiltinID == Builtin::BI__builtin_elementwise_popcount) {
1704
+ pushInteger (S, Val.popcount (), Call->getType ());
1705
+ } else {
1706
+ pushInteger (S, Val.reverseBits (), Call->getType ());
1707
+ }
1695
1708
return true ;
1696
1709
}
1697
1710
// Otherwise, the argument must be a vector.
@@ -1710,8 +1723,13 @@ static bool interp__builtin_elementwise_popcount(InterpState &S, CodePtr OpPC,
1710
1723
// FIXME: Reading from uninitialized vector elements?
1711
1724
for (unsigned I = 0 ; I != NumElems; ++I) {
1712
1725
INT_TYPE_SWITCH_NO_BOOL (ElemT, {
1713
- Dst.atIndex (I).deref <T>() =
1714
- T::from (Arg.atIndex (I).deref <T>().toAPSInt ().popcount ());
1726
+ if (BuiltinID == Builtin::BI__builtin_elementwise_popcount) {
1727
+ Dst.atIndex (I).deref <T>() =
1728
+ T::from (Arg.atIndex (I).deref <T>().toAPSInt ().popcount ());
1729
+ } else {
1730
+ Dst.atIndex (I).deref <T>() = T::from (
1731
+ Arg.atIndex (I).deref <T>().toAPSInt ().reverseBits ().getZExtValue ());
1732
+ }
1715
1733
Dst.atIndex (I).initialize ();
1716
1734
});
1717
1735
}
@@ -2234,6 +2252,78 @@ static bool interp__builtin_is_within_lifetime(InterpState &S, CodePtr OpPC,
2234
2252
return true ;
2235
2253
}
2236
2254
2255
+ static bool interp__builtin_elementwise_sat (InterpState &S, CodePtr OpPC,
2256
+ const CallExpr *Call,
2257
+ unsigned BuiltinID) {
2258
+ Call->dumpColor ();
2259
+ assert (Call->getNumArgs () == 2 );
2260
+
2261
+ // Single integer case.
2262
+ if (!Call->getArg (0 )->getType ()->isVectorType ()) {
2263
+ assert (!Call->getArg (1 )->getType ()->isVectorType ());
2264
+ APSInt RHS = popToAPSInt (
2265
+ S.Stk , *S.getContext ().classify (Call->getArg (1 )->getType ()));
2266
+ APSInt LHS = popToAPSInt (
2267
+ S.Stk , *S.getContext ().classify (Call->getArg (0 )->getType ()));
2268
+ APInt Result;
2269
+ if (BuiltinID == Builtin::BI__builtin_elementwise_add_sat) {
2270
+ Result = LHS.isSigned () ? LHS.sadd_sat (RHS) : LHS.uadd_sat (RHS);
2271
+ } else if (BuiltinID == Builtin::BI__builtin_elementwise_sub_sat) {
2272
+ Result = LHS.isSigned () ? LHS.ssub_sat (RHS) : LHS.usub_sat (RHS);
2273
+ } else {
2274
+ llvm_unreachable (" Wrong builtin ID" );
2275
+ }
2276
+
2277
+ pushInteger (S, APSInt (Result, !LHS.isSigned ()), Call->getType ());
2278
+ return true ;
2279
+ }
2280
+
2281
+ // Vector case.
2282
+ assert (Call->getArg (0 )->getType ()->isVectorType () &&
2283
+ Call->getArg (1 )->getType ()->isVectorType ());
2284
+ const auto *VT = Call->getArg (0 )->getType ()->castAs <VectorType>();
2285
+ assert (VT->getElementType () ==
2286
+ Call->getArg (1 )->getType ()->castAs <VectorType>()->getElementType ());
2287
+ assert (VT->getNumElements () ==
2288
+ Call->getArg (1 )->getType ()->castAs <VectorType>()->getNumElements ());
2289
+ assert (VT->getElementType ()->isIntegralOrEnumerationType ());
2290
+
2291
+ const Pointer &RHS = S.Stk .pop <Pointer>();
2292
+ const Pointer &LHS = S.Stk .pop <Pointer>();
2293
+ const Pointer &Dst = S.Stk .peek <Pointer>();
2294
+ PrimType ElemT = *S.getContext ().classify (VT->getElementType ());
2295
+ unsigned NumElems = VT->getNumElements ();
2296
+ for (unsigned I = 0 ; I != NumElems; ++I) {
2297
+ APSInt Elem1;
2298
+ APSInt Elem2;
2299
+ INT_TYPE_SWITCH_NO_BOOL (ElemT, {
2300
+ Elem1 = LHS.atIndex (I).deref <T>().toAPSInt ();
2301
+ Elem2 = RHS.atIndex (I).deref <T>().toAPSInt ();
2302
+ });
2303
+
2304
+ APSInt Result;
2305
+ if (BuiltinID == Builtin::BI__builtin_elementwise_add_sat) {
2306
+ Result = APSInt (Elem1.isSigned () ? Elem1.sadd_sat (Elem2)
2307
+ : Elem1.uadd_sat (Elem2),
2308
+ Call->getType ()->isUnsignedIntegerOrEnumerationType ());
2309
+ } else if (BuiltinID == Builtin::BI__builtin_elementwise_sub_sat) {
2310
+ Result = APSInt (Elem1.isSigned () ? Elem1.ssub_sat (Elem2)
2311
+ : Elem1.usub_sat (Elem2),
2312
+ Call->getType ()->isUnsignedIntegerOrEnumerationType ());
2313
+ } else {
2314
+ llvm_unreachable (" Wrong builtin ID" );
2315
+ }
2316
+
2317
+ INT_TYPE_SWITCH_NO_BOOL (ElemT, {
2318
+ const Pointer &E = Dst.atIndex (I);
2319
+ E.deref <T>() = static_cast <T>(Result);
2320
+ E.initialize ();
2321
+ });
2322
+ }
2323
+
2324
+ return true ;
2325
+ }
2326
+
2237
2327
bool InterpretBuiltin (InterpState &S, CodePtr OpPC, const CallExpr *Call,
2238
2328
uint32_t BuiltinID) {
2239
2329
if (!S.getASTContext ().BuiltinInfo .isConstantEvaluated (BuiltinID))
@@ -2592,10 +2682,14 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
2592
2682
case Builtin::BI__builtin_reduce_and:
2593
2683
case Builtin::BI__builtin_reduce_or:
2594
2684
case Builtin::BI__builtin_reduce_xor:
2685
+ case Builtin::BI__builtin_reduce_min:
2686
+ case Builtin::BI__builtin_reduce_max:
2595
2687
return interp__builtin_vector_reduce (S, OpPC, Call, BuiltinID);
2596
2688
2597
2689
case Builtin::BI__builtin_elementwise_popcount:
2598
- return interp__builtin_elementwise_popcount (S, OpPC, Frame, Call);
2690
+ case Builtin::BI__builtin_elementwise_bitreverse:
2691
+ return interp__builtin_elementwise_popcount (S, OpPC, Frame, Call,
2692
+ BuiltinID);
2599
2693
2600
2694
case Builtin::BI__builtin_memcpy:
2601
2695
case Builtin::BImemcpy:
@@ -2633,6 +2727,10 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
2633
2727
case Builtin::BI__builtin_is_within_lifetime:
2634
2728
return interp__builtin_is_within_lifetime (S, OpPC, Call);
2635
2729
2730
+ case Builtin::BI__builtin_elementwise_add_sat:
2731
+ case Builtin::BI__builtin_elementwise_sub_sat:
2732
+ return interp__builtin_elementwise_sat (S, OpPC, Call, BuiltinID);
2733
+
2636
2734
default :
2637
2735
S.FFDiag (S.Current ->getLocation (OpPC),
2638
2736
diag::note_invalid_subexpr_in_const_expr)
0 commit comments