Author: Timm Baeder Date: 2025-08-28T16:46:09+02:00 New Revision: 82ada737b1cd05d69f15283415691e8411c0789a
URL: https://github.com/llvm/llvm-project/commit/82ada737b1cd05d69f15283415691e8411c0789a DIFF: https://github.com/llvm/llvm-project/commit/82ada737b1cd05d69f15283415691e8411c0789a.diff LOG: [clang] Optimize EmbedExpr child iterator callback (#155803) Instead of querying the bitwidth and signeness of the integer literal for every iteration, get the bitwidth directly from the `APIntStorage` and assume the signeness to be `true` since we set the type of the `EmbedExpr` to `Ctx.IntTy` and the type of the integer literal to that of the `EmbedExpr`, so it should always be signed, as long as `ASTContext::IntTy` is signed. Before: ``` $ hyperfine -r 50 -w 3 'bin/clang -c ../../benchmarks/embed.cpp -std=c++20 -fconstexpr-steps=1000000000' Benchmark 1: bin/clang -c ../../benchmarks/embed.cpp -std=c++20 -fconstexpr-steps=1000000000 Time (mean ± σ): 1.796 s ± 0.090 s [User: 0.961 s, System: 0.834 s] Range (min … max): 1.640 s … 2.150 s 50 runs ``` After: ``` $ hyperfine -r 50 -w 3 'bin/clang -c ../../benchmarks/embed.cpp -std=c++20 -fconstexpr-steps=1000000000' Benchmark 1: bin/clang -c ../../benchmarks/embed.cpp -std=c++20 -fconstexpr-steps=1000000000 Time (mean ± σ): 1.700 s ± 0.050 s [User: 0.909 s, System: 0.789 s] Range (min … max): 1.637 s … 1.880 s 50 runs ``` That is roughly .1s less, or whatever, 5% or something. The benchmark is simply: ```c++ constexpr char str[] = { #embed "sqlite3.c" suffix(,0) }; constexpr char str2[] = { #embed "sqlite3.c" suffix(,0) }; constexpr char str3[] = { #embed "sqlite3.c" suffix(,0) }; ``` where `sqlite3.c` contains the sqlite3 amalgamation (roughly 9 million characters). Added: Modified: clang/include/clang/AST/APNumericStorage.h clang/include/clang/AST/Expr.h clang/lib/AST/Expr.cpp clang/lib/Serialization/ASTWriterStmt.cpp Removed: ################################################################################ diff --git a/clang/include/clang/AST/APNumericStorage.h b/clang/include/clang/AST/APNumericStorage.h index 95eddbcd86e83..e1948a552bf7e 100644 --- a/clang/include/clang/AST/APNumericStorage.h +++ b/clang/include/clang/AST/APNumericStorage.h @@ -28,7 +28,6 @@ class APNumericStorage { uint64_t VAL; ///< Used to store the <= 64 bits integer value. uint64_t *pVal; ///< Used to store the >64 bits integer value. }; - unsigned BitWidth; bool hasAllocation() const { return llvm::APInt::getNumWords(BitWidth) > 1; } @@ -36,6 +35,7 @@ class APNumericStorage { void operator=(const APNumericStorage &) = delete; protected: + unsigned BitWidth; APNumericStorage() : VAL(0), BitWidth(0) {} llvm::APInt getIntValue() const { @@ -51,6 +51,7 @@ class APNumericStorage { class APIntStorage : private APNumericStorage { public: llvm::APInt getValue() const { return getIntValue(); } + unsigned getBitWidth() const { return BitWidth; } void setValue(const ASTContext &C, const llvm::APInt &Val) { setIntValue(C, Val); } diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 574ee54077ce7..23a0996f02725 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -5113,9 +5113,9 @@ class EmbedExpr final : public Expr { "trying to dereference an invalid iterator"); IntegerLiteral *N = EExpr->FakeChildNode; N->setValue(*EExpr->Ctx, - llvm::APInt(N->getValue().getBitWidth(), + llvm::APInt(N->getBitWidth(), EExpr->Data->BinaryData->getCodeUnit(CurOffset), - N->getType()->isSignedIntegerType())); + /*Signed=*/true)); // We want to return a reference to the fake child node in the // EmbedExpr, not the local variable N. return const_cast<typename BaseTy::reference>(EExpr->FakeChildNode); diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 512f152059a01..cdff160067fed 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -2395,6 +2395,7 @@ EmbedExpr::EmbedExpr(const ASTContext &Ctx, SourceLocation Loc, setDependence(ExprDependence::None); FakeChildNode = IntegerLiteral::Create( Ctx, llvm::APInt::getZero(Ctx.getTypeSize(getType())), getType(), Loc); + assert(getType()->isSignedIntegerType() && "IntTy should be signed"); } InitListExpr::InitListExpr(const ASTContext &C, SourceLocation lbraceloc, diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index be9bad9e96cc1..301ed9b23c206 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -730,7 +730,7 @@ void ASTStmtWriter::VisitIntegerLiteral(IntegerLiteral *E) { Record.AddSourceLocation(E->getLocation()); Record.AddAPInt(E->getValue()); - if (E->getValue().getBitWidth() == 32) { + if (E->getBitWidth() == 32) { AbbrevToUse = Writer.getIntegerLiteralAbbrev(); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits