Skip to content

[clang][bytecode] Pop builtin args from the stack while evaluating #142832

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 5, 2025

Conversation

tbaederr
Copy link
Contributor

@tbaederr tbaederr commented Jun 4, 2025

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.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:bytecode Issues for the clang bytecode constexpr interpreter labels Jun 4, 2025
@llvmbot
Copy link
Member

llvmbot commented Jun 4, 2025

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

Changes

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 --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]

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.
@tbaederr tbaederr merged commit c7a93ef into llvm:main Jun 5, 2025
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:bytecode Issues for the clang bytecode constexpr interpreter clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants