@@ -598,6 +598,17 @@ static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC,
598598 return true ;
599599}
600600
601+ static inline Floating abs (InterpState &S, const Floating &In) {
602+ if (!In.isNegative ())
603+ return In;
604+
605+ Floating Output = S.allocFloat (In.getSemantics ());
606+ APFloat New = In.getAPFloat ();
607+ New.changeSign ();
608+ Output.copy (New);
609+ return Output;
610+ }
611+
601612// The C standard says "fabs raises no floating-point exceptions,
602613// even if x is a signaling NaN. The returned value is independent of
603614// the current rounding direction mode." Therefore constant folding can
@@ -606,16 +617,7 @@ static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC,
606617static bool interp__builtin_fabs (InterpState &S, CodePtr OpPC,
607618 const InterpFrame *Frame) {
608619 const Floating &Val = S.Stk .pop <Floating>();
609- APFloat F = Val.getAPFloat ();
610- if (!F.isNegative ()) {
611- S.Stk .push <Floating>(Val);
612- return true ;
613- }
614-
615- Floating Result = S.allocFloat (Val.getSemantics ());
616- F.changeSign ();
617- Result.copy (F);
618- S.Stk .push <Floating>(Result);
620+ S.Stk .push <Floating>(abs (S, Val));
619621 return true ;
620622}
621623
@@ -1686,6 +1688,57 @@ static bool interp__builtin_vector_reduce(InterpState &S, CodePtr OpPC,
16861688 return true ;
16871689}
16881690
1691+ static bool interp__builtin_elementwise_abs (InterpState &S, CodePtr OpPC,
1692+ const InterpFrame *Frame,
1693+ const CallExpr *Call,
1694+ unsigned BuiltinID) {
1695+ assert (Call->getNumArgs () == 1 );
1696+ QualType Ty = Call->getArg (0 )->getType ();
1697+ if (Ty->isIntegerType ()) {
1698+ PrimType ArgT = *S.getContext ().classify (Call->getArg (0 )->getType ());
1699+ APSInt Val = popToAPSInt (S.Stk , ArgT);
1700+
1701+ pushInteger (S, Val.abs (), Call->getType ());
1702+ return true ;
1703+ }
1704+
1705+ if (Ty->isFloatingType ()) {
1706+ Floating Val = S.Stk .pop <Floating>();
1707+ Floating Result = abs (S, Val);
1708+ S.Stk .push <Floating>(Result);
1709+ return true ;
1710+ }
1711+
1712+ // Otherwise, the argument must be a vector.
1713+ assert (Call->getArg (0 )->getType ()->isVectorType ());
1714+ const Pointer &Arg = S.Stk .pop <Pointer>();
1715+ assert (Arg.getFieldDesc ()->isPrimitiveArray ());
1716+ const Pointer &Dst = S.Stk .peek <Pointer>();
1717+ assert (Dst.getFieldDesc ()->isPrimitiveArray ());
1718+ assert (Arg.getFieldDesc ()->getNumElems () ==
1719+ Dst.getFieldDesc ()->getNumElems ());
1720+
1721+ QualType ElemType = Arg.getFieldDesc ()->getElemQualType ();
1722+ PrimType ElemT = *S.getContext ().classify (ElemType);
1723+ unsigned NumElems = Arg.getNumElems ();
1724+ // we can either have a vector of integer or a vector of floating point
1725+ for (unsigned I = 0 ; I != NumElems; ++I) {
1726+ if (ElemType->isIntegerType ()) {
1727+ INT_TYPE_SWITCH_NO_BOOL (ElemT, {
1728+ Dst.elem <T>(I) = T::from (static_cast <T>(
1729+ APSInt (Arg.elem <T>(I).toAPSInt ().abs (),
1730+ ElemType->isUnsignedIntegerOrEnumerationType ())));
1731+ });
1732+ } else {
1733+ Floating Val = Arg.elem <Floating>(I);
1734+ Dst.elem <Floating>(I) = abs (S, Val);
1735+ }
1736+ }
1737+ Dst.initializeAllElements ();
1738+
1739+ return true ;
1740+ }
1741+
16891742// / Can be called with an integer or vector as the first and only parameter.
16901743static bool interp__builtin_elementwise_popcount (InterpState &S, CodePtr OpPC,
16911744 const InterpFrame *Frame,
@@ -2774,6 +2827,9 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
27742827 return interp__builtin_elementwise_popcount (S, OpPC, Frame, Call,
27752828 BuiltinID);
27762829
2830+ case Builtin::BI__builtin_elementwise_abs:
2831+ return interp__builtin_elementwise_abs (S, OpPC, Frame, Call, BuiltinID);
2832+
27772833 case Builtin::BI__builtin_memcpy:
27782834 case Builtin::BImemcpy:
27792835 case Builtin::BI__builtin_wmemcpy:
0 commit comments