llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) <details> <summary>Changes</summary> Instead of just peek()ing the values when evaluating the builtins and later classify()ing all the call args once again to remove them, just do it while evaluating. This saves quite a bit of code. --- Patch is 62.36 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/142832.diff 1 Files Affected: - (modified) clang/lib/AST/ByteCode/InterpBuiltin.cpp (+258-458) ``````````diff diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 89c626dd3cee8..9a3cf4f8a3309 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -41,25 +41,12 @@ static bool isNoopBuiltin(unsigned ID) { return false; } -static unsigned callArgSize(const InterpState &S, const CallExpr *C) { - unsigned O = 0; - - for (const Expr *E : C->arguments()) { - O += align(primSize(*S.getContext().classify(E))); - } - - return O; +static void discard(InterpStack &Stk, PrimType T) { + TYPE_SWITCH(T, { Stk.discard<T>(); }); } -/// Peek an integer value from the stack into an APSInt. -static APSInt peekToAPSInt(InterpStack &Stk, PrimType T, size_t Offset = 0) { - if (Offset == 0) - Offset = align(primSize(T)); - - APSInt R; - INT_TYPE_SWITCH(T, R = Stk.peek<T>(Offset).toAPSInt()); - - return R; +static APSInt popToAPSInt(InterpStack &Stk, PrimType T) { + INT_TYPE_SWITCH(T, return Stk.pop<T>().toAPSInt()); } /// Pushes \p Val on the stack as the type given by \p QT. @@ -94,68 +81,12 @@ static void pushInteger(InterpState &S, T Val, QualType QT) { QT); } -static void assignInteger(Pointer &Dest, PrimType ValueT, const APSInt &Value) { +static void assignInteger(const Pointer &Dest, PrimType ValueT, + const APSInt &Value) { INT_TYPE_SWITCH_NO_BOOL( ValueT, { Dest.deref<T>() = T::from(static_cast<T>(Value)); }); } -template <PrimType Name, class V = typename PrimConv<Name>::T> -static bool retBI(InterpState &S, const CallExpr *Call, unsigned BuiltinID) { - // The return value of the function is already on the stack. - // Remove it, get rid of all the arguments and add it back. - const V &Val = S.Stk.pop<V>(); - if (!Context::isUnevaluatedBuiltin(BuiltinID)) { - for (int32_t I = Call->getNumArgs() - 1; I >= 0; --I) { - const Expr *A = Call->getArg(I); - PrimType Ty = S.getContext().classify(A).value_or(PT_Ptr); - TYPE_SWITCH(Ty, S.Stk.discard<T>()); - } - } - S.Stk.push<V>(Val); - return true; -} - -static bool retPrimValue(InterpState &S, CodePtr OpPC, - std::optional<PrimType> &T, const CallExpr *Call, - unsigned BuiltinID) { - if (isNoopBuiltin(BuiltinID)) - return true; - - if (!T) { - if (!Context::isUnevaluatedBuiltin(BuiltinID)) { - for (int32_t I = Call->getNumArgs() - 1; I >= 0; --I) { - const Expr *A = Call->getArg(I); - PrimType Ty = S.getContext().classify(A).value_or(PT_Ptr); - TYPE_SWITCH(Ty, S.Stk.discard<T>()); - } - } - - return true; - } - -#define RET_CASE(X) \ - case X: \ - return retBI<X>(S, Call, BuiltinID); - switch (*T) { - RET_CASE(PT_Ptr); - RET_CASE(PT_Float); - RET_CASE(PT_Bool); - RET_CASE(PT_Sint8); - RET_CASE(PT_Uint8); - RET_CASE(PT_Sint16); - RET_CASE(PT_Uint16); - RET_CASE(PT_Sint32); - RET_CASE(PT_Uint32); - RET_CASE(PT_Sint64); - RET_CASE(PT_Uint64); - RET_CASE(PT_IntAP); - RET_CASE(PT_IntAPS); - default: - llvm_unreachable("Unsupported return type for builtin function"); - } -#undef RET_CASE -} - static QualType getElemType(const Pointer &P) { const Descriptor *Desc = P.getFieldDesc(); QualType T = Desc->getType(); @@ -214,27 +145,30 @@ static bool interp__builtin_is_constant_evaluated(InterpState &S, CodePtr OpPC, return true; } +// __builtin_assume(int) +static bool interp__builtin_assume(InterpState &S, CodePtr OpPC, + const InterpFrame *Frame, + const CallExpr *Call) { + assert(Call->getNumArgs() == 1); + discard(S.Stk, *S.getContext().classify(Call->getArg(0))); + return true; +} + static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned ID) { - unsigned LimitSize = - Call->getNumArgs() == 2 - ? 0 - : align(primSize(*S.getContext().classify(Call->getArg(2)))); - const Pointer &A = - S.Stk.peek<Pointer>(align(primSize(PT_Ptr)) * 2 + LimitSize); - const Pointer &B = S.Stk.peek<Pointer>(align(primSize(PT_Ptr)) + LimitSize); - - if (ID == Builtin::BIstrcmp || ID == Builtin::BIstrncmp || - ID == Builtin::BIwcscmp || ID == Builtin::BIwcsncmp) - diagnoseNonConstexprBuiltin(S, OpPC, ID); - uint64_t Limit = ~static_cast<uint64_t>(0); if (ID == Builtin::BIstrncmp || ID == Builtin::BI__builtin_strncmp || ID == Builtin::BIwcsncmp || ID == Builtin::BI__builtin_wcsncmp) - Limit = peekToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(2))) + Limit = popToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(2))) .getZExtValue(); + const Pointer &B = S.Stk.pop<Pointer>(); + const Pointer &A = S.Stk.pop<Pointer>(); + if (ID == Builtin::BIstrcmp || ID == Builtin::BIstrncmp || + ID == Builtin::BIwcscmp || ID == Builtin::BIwcsncmp) + diagnoseNonConstexprBuiltin(S, OpPC, ID); + if (Limit == 0) { pushInteger(S, 0, Call->getType()); return true; @@ -305,7 +239,7 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC, static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned ID) { - const Pointer &StrPtr = S.Stk.peek<Pointer>(); + const Pointer &StrPtr = S.Stk.pop<Pointer>(); if (ID == Builtin::BIstrlen || ID == Builtin::BIwcslen) diagnoseNonConstexprBuiltin(S, OpPC, ID); @@ -360,7 +294,7 @@ static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC, static bool interp__builtin_nan(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, bool Signaling) { - const Pointer &Arg = S.Stk.peek<Pointer>(); + const Pointer &Arg = S.Stk.pop<Pointer>(); if (!CheckLoad(S, OpPC, Arg)) return false; @@ -432,8 +366,8 @@ static bool interp__builtin_inf(InterpState &S, CodePtr OpPC, static bool interp__builtin_copysign(InterpState &S, CodePtr OpPC, const InterpFrame *Frame) { - const Floating &Arg1 = S.Stk.peek<Floating>(align(primSize(PT_Float)) * 2); - const Floating &Arg2 = S.Stk.peek<Floating>(); + const Floating &Arg2 = S.Stk.pop<Floating>(); + const Floating &Arg1 = S.Stk.pop<Floating>(); APFloat Copy = Arg1.getAPFloat(); Copy.copySign(Arg2.getAPFloat()); @@ -444,8 +378,8 @@ static bool interp__builtin_copysign(InterpState &S, CodePtr OpPC, static bool interp__builtin_fmin(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, bool IsNumBuiltin) { - const Floating &LHS = S.Stk.peek<Floating>(align(primSize(PT_Float)) * 2); - const Floating &RHS = S.Stk.peek<Floating>(); + const Floating &RHS = S.Stk.pop<Floating>(); + const Floating &LHS = S.Stk.pop<Floating>(); if (IsNumBuiltin) S.Stk.push<Floating>(llvm::minimumnum(LHS.getAPFloat(), RHS.getAPFloat())); @@ -456,8 +390,8 @@ static bool interp__builtin_fmin(InterpState &S, CodePtr OpPC, static bool interp__builtin_fmax(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, bool IsNumBuiltin) { - const Floating &LHS = S.Stk.peek<Floating>(align(primSize(PT_Float)) * 2); - const Floating &RHS = S.Stk.peek<Floating>(); + const Floating &RHS = S.Stk.pop<Floating>(); + const Floating &LHS = S.Stk.pop<Floating>(); if (IsNumBuiltin) S.Stk.push<Floating>(llvm::maximumnum(LHS.getAPFloat(), RHS.getAPFloat())); @@ -472,7 +406,7 @@ static bool interp__builtin_fmax(InterpState &S, CodePtr OpPC, static bool interp__builtin_isnan(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call) { - const Floating &Arg = S.Stk.peek<Floating>(); + const Floating &Arg = S.Stk.pop<Floating>(); pushInteger(S, Arg.isNan(), Call->getType()); return true; @@ -481,7 +415,7 @@ static bool interp__builtin_isnan(InterpState &S, CodePtr OpPC, static bool interp__builtin_issignaling(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call) { - const Floating &Arg = S.Stk.peek<Floating>(); + const Floating &Arg = S.Stk.pop<Floating>(); pushInteger(S, Arg.isSignaling(), Call->getType()); return true; @@ -490,7 +424,7 @@ static bool interp__builtin_issignaling(InterpState &S, CodePtr OpPC, static bool interp__builtin_isinf(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, bool CheckSign, const CallExpr *Call) { - const Floating &Arg = S.Stk.peek<Floating>(); + const Floating &Arg = S.Stk.pop<Floating>(); bool IsInf = Arg.isInf(); if (CheckSign) @@ -503,7 +437,7 @@ static bool interp__builtin_isinf(InterpState &S, CodePtr OpPC, static bool interp__builtin_isfinite(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call) { - const Floating &Arg = S.Stk.peek<Floating>(); + const Floating &Arg = S.Stk.pop<Floating>(); pushInteger(S, Arg.isFinite(), Call->getType()); return true; @@ -512,7 +446,7 @@ static bool interp__builtin_isfinite(InterpState &S, CodePtr OpPC, static bool interp__builtin_isnormal(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call) { - const Floating &Arg = S.Stk.peek<Floating>(); + const Floating &Arg = S.Stk.pop<Floating>(); pushInteger(S, Arg.isNormal(), Call->getType()); return true; @@ -521,7 +455,7 @@ static bool interp__builtin_isnormal(InterpState &S, CodePtr OpPC, static bool interp__builtin_issubnormal(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call) { - const Floating &Arg = S.Stk.peek<Floating>(); + const Floating &Arg = S.Stk.pop<Floating>(); pushInteger(S, Arg.isDenormal(), Call->getType()); return true; @@ -530,7 +464,7 @@ static bool interp__builtin_issubnormal(InterpState &S, CodePtr OpPC, static bool interp__builtin_iszero(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call) { - const Floating &Arg = S.Stk.peek<Floating>(); + const Floating &Arg = S.Stk.pop<Floating>(); pushInteger(S, Arg.isZero(), Call->getType()); return true; @@ -539,7 +473,7 @@ static bool interp__builtin_iszero(InterpState &S, CodePtr OpPC, static bool interp__builtin_signbit(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call) { - const Floating &Arg = S.Stk.peek<Floating>(); + const Floating &Arg = S.Stk.pop<Floating>(); pushInteger(S, Arg.isNegative(), Call->getType()); return true; @@ -547,8 +481,8 @@ static bool interp__builtin_signbit(InterpState &S, CodePtr OpPC, static bool interp_floating_comparison(InterpState &S, CodePtr OpPC, const CallExpr *Call, unsigned ID) { - const Floating &RHS = S.Stk.peek<Floating>(); - const Floating &LHS = S.Stk.peek<Floating>(align(2u * primSize(PT_Float))); + const Floating &RHS = S.Stk.pop<Floating>(); + const Floating &LHS = S.Stk.pop<Floating>(); pushInteger( S, @@ -584,9 +518,8 @@ static bool interp__builtin_isfpclass(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call) { PrimType FPClassArgT = *S.getContext().classify(Call->getArg(1)->getType()); - APSInt FPClassArg = peekToAPSInt(S.Stk, FPClassArgT); - const Floating &F = - S.Stk.peek<Floating>(align(primSize(FPClassArgT) + primSize(PT_Float))); + APSInt FPClassArg = popToAPSInt(S.Stk, FPClassArgT); + const Floating &F = S.Stk.pop<Floating>(); int32_t Result = static_cast<int32_t>((F.classify() & FPClassArg).getZExtValue()); @@ -596,10 +529,16 @@ static bool interp__builtin_isfpclass(InterpState &S, CodePtr OpPC, } /// Five int values followed by one floating value. +/// __builtin_fpclassify(int, int, int, int, int, float) static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call) { - const Floating &Val = S.Stk.peek<Floating>(); + const Floating &Val = S.Stk.pop<Floating>(); + + PrimType IntT = *S.getContext().classify(Call->getArg(0)); + APSInt Values[5]; + for (unsigned I = 0; I != 5; ++I) + Values[4 - I] = popToAPSInt(S.Stk, IntT); unsigned Index; switch (Val.getCategory()) { @@ -619,13 +558,8 @@ static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC, // The last argument is first on the stack. assert(Index <= 4); - PrimType IntT = *S.getContext().classify(Call->getArg(0)); - unsigned IntSize = primSize(IntT); - unsigned Offset = - align(primSize(PT_Float)) + ((1 + (4 - Index)) * align(IntSize)); - APSInt I = peekToAPSInt(S.Stk, IntT, Offset); - pushInteger(S, I, Call->getType()); + pushInteger(S, Values[Index], Call->getType()); return true; } @@ -636,7 +570,7 @@ static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC, // Reference, WG14 N2478 F.10.4.3 static bool interp__builtin_fabs(InterpState &S, CodePtr OpPC, const InterpFrame *Frame) { - const Floating &Val = S.Stk.peek<Floating>(); + const Floating &Val = S.Stk.pop<Floating>(); S.Stk.push<Floating>(Floating::abs(Val)); return true; @@ -646,7 +580,7 @@ static bool interp__builtin_abs(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call) { PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); - APSInt Val = peekToAPSInt(S.Stk, ArgT); + APSInt Val = popToAPSInt(S.Stk, ArgT); if (Val == APSInt(APInt::getSignedMinValue(Val.getBitWidth()), /*IsUnsigned=*/false)) return false; @@ -660,7 +594,7 @@ static bool interp__builtin_popcount(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call) { PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); - APSInt Val = peekToAPSInt(S.Stk, ArgT); + APSInt Val = popToAPSInt(S.Stk, ArgT); pushInteger(S, Val.popcount(), Call->getType()); return true; } @@ -669,7 +603,7 @@ static bool interp__builtin_parity(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call) { PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); - APSInt Val = peekToAPSInt(S.Stk, ArgT); + APSInt Val = popToAPSInt(S.Stk, ArgT); pushInteger(S, Val.popcount() % 2, Call->getType()); return true; } @@ -678,7 +612,7 @@ static bool interp__builtin_clrsb(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call) { PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); - APSInt Val = peekToAPSInt(S.Stk, ArgT); + APSInt Val = popToAPSInt(S.Stk, ArgT); pushInteger(S, Val.getBitWidth() - Val.getSignificantBits(), Call->getType()); return true; } @@ -687,7 +621,7 @@ static bool interp__builtin_bitreverse(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call) { PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); - APSInt Val = peekToAPSInt(S.Stk, ArgT); + APSInt Val = popToAPSInt(S.Stk, ArgT); pushInteger(S, Val.reverseBits(), Call->getType()); return true; } @@ -717,11 +651,11 @@ static bool interp__builtin_expect(InterpState &S, CodePtr OpPC, assert(NumArgs == 2 || NumArgs == 3); PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); - unsigned Offset = align(ArgT) * 2; if (NumArgs == 3) - Offset += align(primSize(PT_Float)); + S.Stk.discard<Floating>(); + discard(S.Stk, ArgT); - APSInt Val = peekToAPSInt(S.Stk, ArgT, Offset); + APSInt Val = popToAPSInt(S.Stk, ArgT); pushInteger(S, Val, Call->getType()); return true; } @@ -733,9 +667,8 @@ static bool interp__builtin_rotate(InterpState &S, CodePtr OpPC, PrimType AmountT = *S.getContext().classify(Call->getArg(1)->getType()); PrimType ValueT = *S.getContext().classify(Call->getArg(0)->getType()); - APSInt Amount = peekToAPSInt(S.Stk, AmountT); - APSInt Value = peekToAPSInt( - S.Stk, ValueT, align(primSize(AmountT)) + align(primSize(ValueT))); + APSInt Amount = popToAPSInt(S.Stk, AmountT); + APSInt Value = popToAPSInt(S.Stk, ValueT); APSInt Result; if (Right) @@ -753,7 +686,7 @@ static bool interp__builtin_ffs(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call) { PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); - APSInt Value = peekToAPSInt(S.Stk, ArgT); + APSInt Value = popToAPSInt(S.Stk, ArgT); uint64_t N = Value.countr_zero(); pushInteger(S, N == Value.getBitWidth() ? 0 : N + 1, Call->getType()); @@ -782,7 +715,7 @@ static bool interp__builtin_eh_return_data_regno(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call) { PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); - APSInt Arg = peekToAPSInt(S.Stk, ArgT); + APSInt Arg = popToAPSInt(S.Stk, ArgT); int Result = S.getASTContext().getTargetInfo().getEHDataRegisterNumber( Arg.getZExtValue()); @@ -794,17 +727,14 @@ static bool interp__builtin_eh_return_data_regno(InterpState &S, CodePtr OpPC, static bool interp__builtin_overflowop(InterpState &S, CodePtr OpPC, const CallExpr *Call, unsigned BuiltinOp) { - Pointer &ResultPtr = S.Stk.peek<Pointer>(); + const Pointer &ResultPtr = S.Stk.pop<Pointer>(); if (ResultPtr.isDummy()) return false; PrimType RHST = *S.getContext().classify(Call->getArg(1)->getType()); PrimType LHST = *S.getContext().classify(Call->getArg(0)->getType()); - APSInt RHS = peekToAPSInt(S.Stk, RHST, - align(primSize(PT_Ptr)) + align(primSize(RHST))); - APSInt LHS = peekToAPSInt(S.Stk, LHST, - align(primSize(PT_Ptr)) + align(primSize(RHST)) + - align(primSize(LHST))); + APSInt RHS = popToAPSInt(S.Stk, RHST); + APSInt LHS = popToAPSInt(S.Stk, LHST); QualType ResultType = Call->getArg(2)->getType()->getPointeeType(); PrimType ResultT = *S.getContext().classify(ResultType); bool Overflow; @@ -899,18 +829,13 @@ static bool interp__builtin_overflowop(InterpState &S, CodePtr OpPC, static bool interp__builtin_carryop(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned BuiltinOp) { + const Pointer &CarryOutPtr = S.Stk.pop<Pointer>(); PrimType LHST = *S.getContext().classify(Call->getArg(0)->getType()); PrimType RHST = *S.getContext().classify(Call->getArg(1)->getType()); - PrimType CarryT = *S.getContext().classify(Call->getArg(2)->getType()); - APSInt RHS = peekToAPSInt(S.Stk, RHST, - align(primSize(PT_Ptr)) + align(primSize(CarryT)) + - align(primSize(RHST))); - APSInt LHS = - peekToAPSInt(S.Stk, LHST, - ... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/142832 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits