Index: clang/lib/AST/Interp/Interp.h =================================================================== --- clang/lib/AST/Interp/Interp.h +++ clang/lib/AST/Interp/Interp.h @@ -109,7 +109,7 @@ /// Interpreter entry point. bool Interpret(InterpState &S, APValue &Result); -bool InterpretBuiltin(InterpState &S, CodePtr PC, unsigned BuiltinID); +bool InterpretBuiltin(InterpState &S, CodePtr PC, const FunctionDecl *FuncDecl); enum class ArithOp { Add, Sub }; @@ -1407,7 +1407,7 @@ InterpFrame *FrameBefore = S.Current; S.Current = NewFrame.get(); - if (InterpretBuiltin(S, PC, Func->getBuiltinID())) { + if (InterpretBuiltin(S, PC, Func->getDecl())) { NewFrame.release(); return true; } Index: clang/lib/AST/Interp/InterpBuiltin.cpp =================================================================== --- clang/lib/AST/Interp/InterpBuiltin.cpp +++ clang/lib/AST/Interp/InterpBuiltin.cpp @@ -36,12 +36,25 @@ return true; } -bool InterpretBuiltin(InterpState &S, CodePtr PC, unsigned BuiltinID) { +bool InterpretBuiltin(InterpState &S, CodePtr PC, + const FunctionDecl *FuncDecl) { + unsigned BuiltinID = FuncDecl->getBuiltinID(); + assert(BuiltinID != 0); + switch (BuiltinID) { case Builtin::BI__builtin_is_constant_evaluated: S.Stk.push(Boolean::from(S.inConstantContext())); Ret(S, PC); return true; + + case Builtin::BI__builtin_expect: { + // __builtin_expect(long, long). + // Pop the last argument from the stack, + // leave the first one and just ignore the function. + PrimType LongT = *S.classify(FuncDecl->getParamDecl(1)->getType()); + S.Stk.discard(LongT); + return true; + } } return false; Index: clang/lib/AST/Interp/InterpStack.h =================================================================== --- clang/lib/AST/Interp/InterpStack.h +++ clang/lib/AST/Interp/InterpStack.h @@ -13,6 +13,7 @@ #ifndef LLVM_CLANG_AST_INTERP_INTERPSTACK_H #define LLVM_CLANG_AST_INTERP_INTERPSTACK_H +#include "Pointer.h" #include "PrimType.h" #include #include @@ -61,6 +62,17 @@ shrink(aligned_size()); } + /// Discards the top value of the given PrimType. + void discard(PrimType Type) { +#ifndef NDEBUG + assert(ItemTypes.back() == Type); + ItemTypes.pop_back(); +#endif + + TYPE_SWITCH(Type, auto *Ptr = &peek(); Ptr->~T(); + shrink(aligned_size());); + } + /// Returns a reference to the value on the top of the stack. template T &peek() const { return *reinterpret_cast(peek(aligned_size())); Index: clang/lib/AST/Interp/InterpState.h =================================================================== --- clang/lib/AST/Interp/InterpState.h +++ clang/lib/AST/Interp/InterpState.h @@ -86,6 +86,8 @@ return M ? M->getSource(F, PC) : F->getSource(PC); } + std::optional classify(QualType T) const { return Ctx.classify(T); } + private: /// AST Walker state. State &Parent; Index: clang/test/AST/Interp/builtins.cpp =================================================================== --- clang/test/AST/Interp/builtins.cpp +++ clang/test/AST/Interp/builtins.cpp @@ -22,3 +22,11 @@ bool is_this_constant() { return __builtin_is_constant_evaluated(); // CHECK: ret i1 false } + +long my_expected() { + return __builtin_expect(17, 12); // CHECK: ret {{.*}} 17 +} + +long my_expected(long foo) { + return __builtin_expect(foo, 100); +}