@@ -1695,32 +1695,71 @@ static bool interp__builtin_vector_reduce(InterpState &S, CodePtr OpPC,
16951695 assert (Arg.getFieldDesc ()->isPrimitiveArray ());
16961696
16971697 unsigned ID = Func->getBuiltinID ();
1698- if (ID == Builtin::BI__builtin_reduce_add) {
1699- QualType ElemType = Arg.getFieldDesc ()->getElemQualType ();
1700- assert (Call->getType () == ElemType);
1701- PrimType ElemT = *S.getContext ().classify (ElemType);
1702- unsigned NumElems = Arg.getNumElems ();
1703-
1704- INT_TYPE_SWITCH (ElemT, {
1705- T Sum = Arg.atIndex (0 ).deref <T>();
1706- unsigned BitWidth = Sum.bitWidth ();
1707- for (unsigned I = 1 ; I != NumElems; ++I) {
1708- T Elem = Arg.atIndex (I).deref <T>();
1709- if (T::add (Sum, Elem, BitWidth, &Sum)) {
1698+ QualType ElemType = Arg.getFieldDesc ()->getElemQualType ();
1699+ assert (Call->getType () == ElemType);
1700+ PrimType ElemT = *S.getContext ().classify (ElemType);
1701+ unsigned NumElems = Arg.getNumElems ();
1702+
1703+ INT_TYPE_SWITCH_NO_BOOL (ElemT, {
1704+ T Result = Arg.atIndex (0 ).deref <T>();
1705+ unsigned BitWidth = Result.bitWidth ();
1706+ for (unsigned I = 1 ; I != NumElems; ++I) {
1707+ T Elem = Arg.atIndex (I).deref <T>();
1708+ T PrevResult = Result;
1709+
1710+ if (ID == Builtin::BI__builtin_reduce_add) {
1711+ if (T::add (Result, Elem, BitWidth, &Result)) {
17101712 unsigned OverflowBits = BitWidth + 1 ;
1711- (void )handleOverflow (
1712- S, OpPC,
1713- (Sum. toAPSInt (OverflowBits) + Elem.toAPSInt (OverflowBits)));
1713+ (void )handleOverflow (S, OpPC,
1714+ (PrevResult. toAPSInt (OverflowBits) +
1715+ Elem.toAPSInt (OverflowBits)));
17141716 return false ;
17151717 }
1718+ } else if (ID == Builtin::BI__builtin_reduce_mul) {
1719+ if (T::mul (Result, Elem, BitWidth, &Result)) {
1720+ unsigned OverflowBits = BitWidth * 2 ;
1721+ (void )handleOverflow (S, OpPC,
1722+ (PrevResult.toAPSInt (OverflowBits) *
1723+ Elem.toAPSInt (OverflowBits)));
1724+ return false ;
1725+ }
1726+
1727+ } else if (ID == Builtin::BI__builtin_reduce_and) {
1728+ (void )T::bitAnd (Result, Elem, BitWidth, &Result);
1729+ } else {
1730+ llvm_unreachable (" Unhandled vector reduce builtin" );
17161731 }
1717- pushInteger (S, Sum, Call->getType ());
1718- });
1732+ }
1733+ pushInteger (S, Result, Call->getType ());
1734+ });
17191735
1736+ return true ;
1737+ }
1738+
1739+ static bool interp__builtin_memcpy (InterpState &S, CodePtr OpPC,
1740+ const InterpFrame *Frame,
1741+ const Function *Func, const CallExpr *Call) {
1742+ assert (Call->getNumArgs () == 3 );
1743+ Pointer DestPtr = getParam<Pointer>(Frame, 0 );
1744+ const Pointer &SrcPtr = getParam<Pointer>(Frame, 1 );
1745+ const APSInt &Size =
1746+ peekToAPSInt (S.Stk , *S.getContext ().classify (Call->getArg (2 )));
1747+ assert (!Size.isSigned () && " memcpy and friends take an unsigned size" );
1748+
1749+ if (DestPtr.isDummy () || SrcPtr.isDummy ())
1750+ return false ;
1751+
1752+ // If the size is zero, we treat this as always being a valid no-op.
1753+ if (Size.isZero ()) {
1754+ S.Stk .push <Pointer>(DestPtr);
17201755 return true ;
17211756 }
17221757
1723- llvm_unreachable (" Unsupported vector reduce builtin" );
1758+ if (!DoBitCastPtr (S, OpPC, SrcPtr, DestPtr))
1759+ return false ;
1760+
1761+ S.Stk .push <Pointer>(DestPtr);
1762+ return true ;
17241763}
17251764
17261765bool InterpretBuiltin (InterpState &S, CodePtr OpPC, const Function *F,
@@ -2169,10 +2208,17 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
21692208 break ;
21702209
21712210 case Builtin::BI__builtin_reduce_add:
2211+ case Builtin::BI__builtin_reduce_mul:
2212+ case Builtin::BI__builtin_reduce_and:
21722213 if (!interp__builtin_vector_reduce (S, OpPC, Frame, F, Call))
21732214 return false ;
21742215 break ;
21752216
2217+ case Builtin::BI__builtin_memcpy:
2218+ if (!interp__builtin_memcpy (S, OpPC, Frame, F, Call))
2219+ return false ;
2220+ break ;
2221+
21762222 default :
21772223 S.FFDiag (S.Current ->getLocation (OpPC),
21782224 diag::note_invalid_subexpr_in_const_expr)
0 commit comments