https://github.com/xlauko updated 
https://github.com/llvm/llvm-project/pull/223418

>From 059e5cd5f78feec96cbd56e9fcc29600b4b9184d Mon Sep 17 00:00:00 2001
From: Henrich Lauko <[email protected]>
Date: Mon, 14 Sep 2026 13:05:25 +0000
Subject: [PATCH] [CIR][CodeGen][NFCI] Move shared AST-only helpers into
 CodeGenUtils

Follow-up to PR #221001. Ten more helpers that both CodeGens had
equivalent copies of, several of them already marked "should be shared" in
CIR.

Instead of growing CodeGenUtils.h, each helper goes in a header named for
the classic CodeGen file it came from, with the CGExpr*.cpp family sharing
ExprUtils.h. CIR's files mirror the classic ones, so the grouping reads the
same from both sides.

CIR's getNoFPClassTestMask returned unsigned where classic returns
llvm::FPClassTest; the shared version keeps the classic return type.

No functional change intended.
---
 clang/include/clang/CodeGenUtils/CallUtils.h  |  32 +++++
 clang/include/clang/CodeGenUtils/ClassUtils.h |  29 ++++
 clang/include/clang/CodeGenUtils/ExprUtils.h  |  48 +++++++
 .../clang/CodeGenUtils/FunctionUtils.h        |  28 ++++
 .../clang/CodeGenUtils/ItaniumCXXABIUtils.h   |  28 ++++
 clang/lib/CIR/CodeGen/CIRGenCall.cpp          |  28 +---
 clang/lib/CIR/CodeGen/CIRGenClass.cpp         |  27 +---
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp          |  24 +---
 clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp |  92 +------------
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp    |  24 +---
 clang/lib/CIR/CodeGen/CIRGenFunction.cpp      |  21 +--
 clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp |  56 +-------
 clang/lib/CodeGen/CGCall.cpp                  |  34 ++---
 clang/lib/CodeGen/CGClass.cpp                 |  28 +---
 clang/lib/CodeGen/CGExpr.cpp                  |  24 +---
 clang/lib/CodeGen/CGExprAgg.cpp               |  93 +------------
 clang/lib/CodeGen/CGExprScalar.cpp            |  25 +---
 clang/lib/CodeGen/CodeGenFunction.cpp         |  23 +---
 clang/lib/CodeGen/ItaniumCXXABI.cpp           |  56 +-------
 clang/lib/CodeGenUtils/CMakeLists.txt         |   5 +
 clang/lib/CodeGenUtils/CallUtils.cpp          |  28 ++++
 clang/lib/CodeGenUtils/ClassUtils.cpp         |  39 ++++++
 clang/lib/CodeGenUtils/ExprUtils.cpp          | 128 ++++++++++++++++++
 clang/lib/CodeGenUtils/FunctionUtils.cpp      |  29 ++++
 clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp |  64 +++++++++
 25 files changed, 513 insertions(+), 500 deletions(-)
 create mode 100644 clang/include/clang/CodeGenUtils/CallUtils.h
 create mode 100644 clang/include/clang/CodeGenUtils/ClassUtils.h
 create mode 100644 clang/include/clang/CodeGenUtils/ExprUtils.h
 create mode 100644 clang/include/clang/CodeGenUtils/FunctionUtils.h
 create mode 100644 clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h
 create mode 100644 clang/lib/CodeGenUtils/CallUtils.cpp
 create mode 100644 clang/lib/CodeGenUtils/ClassUtils.cpp
 create mode 100644 clang/lib/CodeGenUtils/ExprUtils.cpp
 create mode 100644 clang/lib/CodeGenUtils/FunctionUtils.cpp
 create mode 100644 clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp

diff --git a/clang/include/clang/CodeGenUtils/CallUtils.h 
b/clang/include/clang/CodeGenUtils/CallUtils.h
new file mode 100644
index 0000000000000..450a62a448e49
--- /dev/null
+++ b/clang/include/clang/CodeGenUtils/CallUtils.h
@@ -0,0 +1,32 @@
+//===--- CallUtils.h - Shared call emission queries -------------*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file holds the AST and language option queries that both classic
+// CodeGen and CIR CodeGen need while building a call and its argument and
+// return value attributes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CODEGENUTILS_CALLUTILS_H
+#define LLVM_CLANG_CODEGENUTILS_CALLUTILS_H
+
+#include "clang/AST/ASTContext.h"
+#include "llvm/ADT/FloatingPointMode.h"
+
+namespace clang::CodeGenUtils {
+
+/// Returns the canonical formal type of the given C++ method.
+CanQual<FunctionProtoType> getFormalType(const CXXMethodDecl *MD);
+
+/// Returns the set of floating-point value kinds that the language options
+/// promise never reach a function's arguments or return value.
+llvm::FPClassTest getNoFPClassTestMask(const LangOptions &LangOpts);
+
+} // namespace clang::CodeGenUtils
+
+#endif // LLVM_CLANG_CODEGENUTILS_CALLUTILS_H
diff --git a/clang/include/clang/CodeGenUtils/ClassUtils.h 
b/clang/include/clang/CodeGenUtils/ClassUtils.h
new file mode 100644
index 0000000000000..63664ed737933
--- /dev/null
+++ b/clang/include/clang/CodeGenUtils/ClassUtils.h
@@ -0,0 +1,29 @@
+//===--- ClassUtils.h - Shared C++ class emission queries -------*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file holds the AST queries about C++ class construction and destruction
+// that both classic CodeGen and CIR CodeGen need, chiefly to decide when a
+// vtable pointer has to be established before running member initializers or
+// a destructor body.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CODEGENUTILS_CLASSUTILS_H
+#define LLVM_CLANG_CODEGENUTILS_CLASSUTILS_H
+
+#include "clang/AST/ASTContext.h"
+
+namespace clang::CodeGenUtils {
+
+/// Check whether \p Init uses 'this' in a way which requires the vtable to be
+/// properly set.
+bool baseInitializerUsesThis(ASTContext &Ctx, const Expr *Init);
+
+} // namespace clang::CodeGenUtils
+
+#endif // LLVM_CLANG_CODEGENUTILS_CLASSUTILS_H
diff --git a/clang/include/clang/CodeGenUtils/ExprUtils.h 
b/clang/include/clang/CodeGenUtils/ExprUtils.h
new file mode 100644
index 0000000000000..e6a5248440d33
--- /dev/null
+++ b/clang/include/clang/CodeGenUtils/ExprUtils.h
@@ -0,0 +1,48 @@
+//===--- ExprUtils.h - Shared expression emission queries -------*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file holds the AST queries about expressions that both classic CodeGen
+// and CIR CodeGen need while emitting scalar, aggregate and lvalue
+// expressions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CODEGENUTILS_EXPRUTILS_H
+#define LLVM_CLANG_CODEGENUTILS_EXPRUTILS_H
+
+#include "clang/AST/ASTContext.h"
+
+namespace clang::CodeGenUtils {
+
+/// Strip off the variably-modified array types wrapping \p VLA and return the
+/// first element type that has a fixed size.
+QualType getFixedSizeElementType(const ASTContext &Ctx,
+                                 const VariableArrayType *VLA);
+
+/// Check whether the value of \p E is possibly a reference to or into a
+/// __block variable.
+bool isBlockVarRef(const Expr *E);
+
+/// Check whether \p E is cheap enough and side-effect-free enough to evaluate
+/// unconditionally instead of conditionally.  This is used to convert control
+/// flow into selects in some cases.
+bool isCheapEnoughToEvaluateUnconditionally(const Expr *E,
+                                            const ASTContext &Ctx);
+
+/// Check whether \p E is a trivial array filler, that is, one that is
+/// equivalent to zero-initialization.
+bool isTrivialFiller(const Expr *E);
+
+/// Detect the unusual situation where an inline version of a builtin is
+/// shadowed by a non-inline version.  In that case we should pick the external
+/// one everywhere.  That's GCC behavior too.
+bool onlyHasInlineBuiltinDeclaration(const FunctionDecl *FD);
+
+} // namespace clang::CodeGenUtils
+
+#endif // LLVM_CLANG_CODEGENUTILS_EXPRUTILS_H
diff --git a/clang/include/clang/CodeGenUtils/FunctionUtils.h 
b/clang/include/clang/CodeGenUtils/FunctionUtils.h
new file mode 100644
index 0000000000000..f924874d829e0
--- /dev/null
+++ b/clang/include/clang/CodeGenUtils/FunctionUtils.h
@@ -0,0 +1,28 @@
+//===--- FunctionUtils.h - Shared function emission queries -----*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file holds the queries that both classic CodeGen and CIR CodeGen need
+// while emitting a function body.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CODEGENUTILS_FUNCTIONUTILS_H
+#define LLVM_CLANG_CODEGENUTILS_FUNCTIONUTILS_H
+
+#include "clang/Basic/CodeGenOptions.h"
+#include "clang/Basic/LangOptions.h"
+
+namespace clang::CodeGenUtils {
+
+/// Decide whether we need to emit the lifetime markers.
+bool shouldEmitLifetimeMarkers(const CodeGenOptions &CGOpts,
+                               const LangOptions &LangOpts);
+
+} // namespace clang::CodeGenUtils
+
+#endif // LLVM_CLANG_CODEGENUTILS_FUNCTIONUTILS_H
diff --git a/clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h 
b/clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h
new file mode 100644
index 0000000000000..45b358ad343bb
--- /dev/null
+++ b/clang/include/clang/CodeGenUtils/ItaniumCXXABIUtils.h
@@ -0,0 +1,28 @@
+//===--- ItaniumCXXABIUtils.h - Shared Itanium C++ ABI queries --*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file holds the Itanium C++ ABI queries that both classic CodeGen and
+// CIR CodeGen need while lowering ABI constructs whose encoding the ABI
+// specifies in terms of the AST.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CODEGENUTILS_ITANIUMCXXABIUTILS_H
+#define LLVM_CLANG_CODEGENUTILS_ITANIUMCXXABIUTILS_H
+
+#include "clang/AST/ASTContext.h"
+
+namespace clang::CodeGenUtils {
+
+/// Compute the src2dst_offset hint as described in the Itanium C++ ABI 
[2.9.7].
+CharUnits computeOffsetHint(ASTContext &Ctx, const CXXRecordDecl *Src,
+                            const CXXRecordDecl *Dst);
+
+} // namespace clang::CodeGenUtils
+
+#endif // LLVM_CLANG_CODEGENUTILS_ITANIUMCXXABIUTILS_H
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index e7b451b82d853..d0ef751347b5a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -20,6 +20,7 @@
 #include "mlir/IR/Attributes.h"
 #include "clang/CIR/ABIArgInfo.h"
 #include "clang/CIR/MissingFeatures.h"
+#include "clang/CodeGenUtils/CallUtils.h"
 #include "llvm/ADT/FloatingPointMode.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/Support/TypeSize.h"
@@ -619,16 +620,6 @@ static bool determineNoUndef(QualType clangTy, CIRGenTypes 
&types,
   return false;
 }
 
-/// Compute the nofpclass mask for FP types based on language options.
-static unsigned getNoFPClassTestMask(const LangOptions &langOpts) {
-  unsigned mask = 0;
-  if (langOpts.NoHonorInfs)
-    mask |= llvm::fcInf;
-  if (langOpts.NoHonorNaNs)
-    mask |= llvm::fcNan;
-  return mask;
-}
-
 void CIRGenModule::constructFunctionReturnAttributes(
     const CIRGenFunctionInfo &info, const Decl *targetDecl, bool isThunk,
     mlir::NamedAttrList &retAttrs) {
@@ -644,7 +635,8 @@ void CIRGenModule::constructFunctionReturnAttributes(
                  mlir::UnitAttr::get(&getMLIRContext()));
 
   if (retTy->hasFloatingRepresentation())
-    if (unsigned mask = getNoFPClassTestMask(getLangOpts()))
+    if (llvm::FPClassTest mask =
+            CodeGenUtils::getNoFPClassTestMask(getLangOpts()))
       retAttrs.set(mlir::LLVM::LLVMDialect::getNoFPClassAttrName(),
                    builder.getI64IntegerAttr(mask));
 
@@ -769,7 +761,8 @@ void CIRGenModule::constructFunctionArgumentAttributes(
     }
 
     if (argType->hasFloatingRepresentation())
-      if (unsigned mask = getNoFPClassTestMask(getLangOpts()))
+      if (llvm::FPClassTest mask =
+              CodeGenUtils::getNoFPClassTestMask(getLangOpts()))
         argAttrList.set(mlir::LLVM::LLVMDialect::getNoFPClassAttrName(),
                         builder.getI64IntegerAttr(mask));
 
@@ -793,13 +786,6 @@ void CIRGenModule::constructFunctionArgumentAttributes(
   }
 }
 
-/// Returns the canonical formal type of the given C++ method.
-static CanQual<FunctionProtoType> getFormalType(const CXXMethodDecl *md) {
-  return md->getType()
-      ->getCanonicalTypeUnqualified()
-      .getAs<FunctionProtoType>();
-}
-
 /// Adds the formal parameters in FPT to the given prefix.  If any parameter in
 /// FPT has pass_object_size attrs, then we'll add parameters for those, too.
 /// TODO(cir): this should be shared with LLVM codegen
@@ -844,7 +830,7 @@ CIRGenTypes::arrangeCXXStructorDeclaration(GlobalDecl gd) {
       passParams = inheritingCtorHasParams(inherited, gd.getCtorType());
   }
 
-  CanQual<FunctionProtoType> fpt = getFormalType(md);
+  CanQual<FunctionProtoType> fpt = CodeGenUtils::getFormalType(md);
 
   if (passParams)
     appendParameterTypes(*this, argTypes, fpt);
@@ -994,7 +980,7 @@ const CIRGenFunctionInfo 
&CIRGenTypes::arrangeCXXConstructorCall(
   // +1 for implicit this, which should always be args[0]
   unsigned totalPrefixArgs = 1 + extraPrefixArgs;
 
-  CanQual<FunctionProtoType> fpt = getFormalType(d);
+  CanQual<FunctionProtoType> fpt = CodeGenUtils::getFormalType(d);
   RequiredArgs required = passProtoArgs
                               ? RequiredArgs::getFromProtoWithExtraSlots(
                                     fpt, totalPrefixArgs + extraSuffixArgs)
diff --git a/clang/lib/CIR/CodeGen/CIRGenClass.cpp 
b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
index 8cd014415e4ee..c8edc1ccd02c6 100644
--- a/clang/lib/CIR/CodeGen/CIRGenClass.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
@@ -14,12 +14,12 @@
 #include "CIRGenFunction.h"
 #include "CIRGenValue.h"
 
-#include "clang/AST/EvaluatedExprVisitor.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/RecordLayout.h"
 #include "clang/AST/Type.h"
 #include "clang/CIR/Dialect/IR/CIRDialect.h"
 #include "clang/CIR/MissingFeatures.h"
+#include "clang/CodeGenUtils/ClassUtils.h"
 #include "clang/CodeGenUtils/CodeGenUtils.h"
 
 using namespace clang;
@@ -199,31 +199,8 @@ struct CallDelegatingCtorDtor final : 
EHScopeStack::Cleanup {
   }
 };
 
-/// A visitor which checks whether an initializer uses 'this' in a
-/// way which requires the vtable to be properly set.
-struct DynamicThisUseChecker
-    : ConstEvaluatedExprVisitor<DynamicThisUseChecker> {
-  using super = ConstEvaluatedExprVisitor<DynamicThisUseChecker>;
-
-  bool usesThis = false;
-
-  DynamicThisUseChecker(const ASTContext &c) : super(c) {}
-
-  // Black-list all explicit and implicit references to 'this'.
-  //
-  // Do we need to worry about external references to 'this' derived
-  // from arbitrary code? If so, then anything which runs arbitrary
-  // external code might potentially access the vtable.
-  void VisitCXXThisExpr(const CXXThisExpr *e) { usesThis = true; }
-};
 } // end anonymous namespace
 
-static bool baseInitializerUsesThis(ASTContext &c, const Expr *init) {
-  DynamicThisUseChecker checker(c);
-  checker.Visit(init);
-  return checker.usesThis;
-}
-
 /// Gets the address of a direct base class within a complete object.
 /// This should only be used for (1) non-virtual bases or (2) virtual bases
 /// when the type is known to be complete (e.g. in complete destructors).
@@ -266,7 +243,7 @@ void CIRGenFunction::emitBaseInitializer(mlir::Location loc,
   // If the initializer for the base (other than the constructor
   // itself) accesses 'this' in any way, we need to initialize the
   // vtables.
-  if (baseInitializerUsesThis(getContext(), baseInit->getInit()))
+  if (CodeGenUtils::baseInitializerUsesThis(getContext(), baseInit->getInit()))
     initializeVTablePointers(loc, classDecl);
 
   // We can pretend to be a complete class because it only matters for
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 7e9a4d9458c93..664425b20577f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -31,6 +31,7 @@
 #include "clang/CIR/Dialect/IR/CIRTypes.h"
 #include "clang/CIR/MissingFeatures.h"
 #include "clang/CodeGenUtils/CodeGenUtils.h"
+#include "clang/CodeGenUtils/ExprUtils.h"
 #include <optional>
 
 using namespace clang;
@@ -1300,15 +1301,6 @@ static CharUnits getArrayElementAlign(CharUnits 
arrayAlign, mlir::Value idx,
   return arrayAlign.alignmentOfArrayElement(eltSize);
 }
 
-static QualType getFixedSizeElementType(const ASTContext &astContext,
-                                        const VariableArrayType *vla) {
-  QualType eltType;
-  do {
-    eltType = vla->getElementType();
-  } while ((vla = astContext.getAsVariableArrayType(eltType)));
-  return eltType;
-}
-
 static mlir::Value emitArraySubscriptPtr(CIRGenFunction &cgf,
                                          mlir::Location beginLoc,
                                          mlir::Location endLoc, mlir::Value 
ptr,
@@ -1332,7 +1324,7 @@ static Address emitArraySubscriptPtr(CIRGenFunction &cgf,
   // the thing that the indices are expressed in terms of.
   if (const VariableArrayType *vla =
           cgf.getContext().getAsVariableArrayType(eltType)) {
-    eltType = getFixedSizeElementType(cgf.getContext(), vla);
+    eltType = CodeGenUtils::getFixedSizeElementType(cgf.getContext(), vla);
   }
 
   // We can use that to compute the best alignment of the element.
@@ -2218,16 +2210,6 @@ RValue CIRGenFunction::emitAnyExpr(const Expr *e, 
AggValueSlot aggSlot,
   llvm_unreachable("bad evaluation kind");
 }
 
-// Detect the unusual situation where an inline version is shadowed by a
-// non-inline version. In that case we should pick the external one
-// everywhere. That's GCC behavior too.
-static bool onlyHasInlineBuiltinDeclaration(const FunctionDecl *fd) {
-  for (const FunctionDecl *pd = fd; pd; pd = pd->getPreviousDecl())
-    if (!pd->isInlineBuiltinDeclaration())
-      return false;
-  return true;
-}
-
 CIRGenCallee CIRGenFunction::emitDirectCallee(const GlobalDecl &gd) {
   const auto *fd = cast<FunctionDecl>(gd.getDecl());
 
@@ -2249,7 +2231,7 @@ CIRGenCallee CIRGenFunction::emitDirectCallee(const 
GlobalDecl &gd) {
     // name to make it clear it's not the actual builtin.
     if (auto fn = dyn_cast<cir::FuncOp>(curFn);
         (!fn || fn.getName() != fdInlineName) &&
-        onlyHasInlineBuiltinDeclaration(fd)) {
+        CodeGenUtils::onlyHasInlineBuiltinDeclaration(fd)) {
       cir::FuncOp clone =
           mlir::cast_or_null<cir::FuncOp>(cgm.getGlobalValue(fdInlineName));
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
index 2fb66232d806c..f9a4eb2b2033a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -20,6 +20,7 @@
 #include "clang/AST/Expr.h"
 #include "clang/AST/RecordLayout.h"
 #include "clang/AST/StmtVisitor.h"
+#include "clang/CodeGenUtils/ExprUtils.h"
 #include "llvm/IR/Value.h"
 #include <cstdint>
 
@@ -27,73 +28,6 @@ using namespace clang;
 using namespace clang::CIRGen;
 
 namespace {
-// FIXME(cir): This should be a common helper between CIRGen
-// and traditional CodeGen
-/// Is the value of the given expression possibly a reference to or
-/// into a __block variable?
-static bool isBlockVarRef(const Expr *e) {
-  // Make sure we look through parens.
-  e = e->IgnoreParens();
-
-  // Check for a direct reference to a __block variable.
-  if (const DeclRefExpr *dre = dyn_cast<DeclRefExpr>(e)) {
-    const VarDecl *var = dyn_cast<VarDecl>(dre->getDecl());
-    return (var && var->hasAttr<BlocksAttr>());
-  }
-
-  // More complicated stuff.
-
-  // Binary operators.
-  if (const BinaryOperator *op = dyn_cast<BinaryOperator>(e)) {
-    // For an assignment or pointer-to-member operation, just care
-    // about the LHS.
-    if (op->isAssignmentOp() || op->isPtrMemOp())
-      return isBlockVarRef(op->getLHS());
-
-    // For a comma, just care about the RHS.
-    if (op->getOpcode() == BO_Comma)
-      return isBlockVarRef(op->getRHS());
-
-    // FIXME: pointer arithmetic?
-    return false;
-
-    // Check both sides of a conditional operator.
-  } else if (const AbstractConditionalOperator *op =
-                 dyn_cast<AbstractConditionalOperator>(e)) {
-    return isBlockVarRef(op->getTrueExpr()) ||
-           isBlockVarRef(op->getFalseExpr());
-
-    // OVEs are required to support BinaryConditionalOperators.
-  } else if (const OpaqueValueExpr *op = dyn_cast<OpaqueValueExpr>(e)) {
-    if (const Expr *src = op->getSourceExpr())
-      return isBlockVarRef(src);
-
-    // Casts are necessary to get things like (*(int*)&var) = foo().
-    // We don't really care about the kind of cast here, except
-    // we don't want to look through l2r casts, because it's okay
-    // to get the *value* in a __block variable.
-  } else if (const CastExpr *cast = dyn_cast<CastExpr>(e)) {
-    if (cast->getCastKind() == CK_LValueToRValue)
-      return false;
-    return isBlockVarRef(cast->getSubExpr());
-
-    // Handle unary operators.  Again, just aggressively look through
-    // it, ignoring the operation.
-  } else if (const UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) {
-    return isBlockVarRef(uop->getSubExpr());
-
-    // Look into the base of a field access.
-  } else if (const MemberExpr *mem = dyn_cast<MemberExpr>(e)) {
-    return isBlockVarRef(mem->getBase());
-
-    // Look into the base of a subscript.
-  } else if (const ArraySubscriptExpr *sub = dyn_cast<ArraySubscriptExpr>(e)) {
-    return isBlockVarRef(sub->getBase());
-  }
-
-  return false;
-}
-
 class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
 
   CIRGenFunction &cgf;
@@ -172,7 +106,7 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
                                                    e->getRHS()->getType()) &&
            "Invalid assignment");
 
-    if (isBlockVarRef(e->getLHS()) &&
+    if (CodeGenUtils::isBlockVarRef(e->getLHS()) &&
         e->getRHS()->HasSideEffects(cgf.getContext())) {
       cgf.cgm.errorNYI(e->getSourceRange(),
                        "block var reference with side effects");
@@ -729,26 +663,6 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
 
 } // namespace
 
-static bool isTrivialFiller(Expr *e) {
-  if (!e)
-    return true;
-
-  if (isa<ImplicitValueInitExpr>(e))
-    return true;
-
-  if (auto *ile = dyn_cast<InitListExpr>(e)) {
-    if (ile->getNumInits())
-      return false;
-    return isTrivialFiller(ile->getArrayFiller());
-  }
-
-  if (const auto *cons = dyn_cast_or_null<CXXConstructExpr>(e))
-    return cons->getConstructor()->isDefaultConstructor() &&
-           cons->getConstructor()->isTrivial();
-
-  return false;
-}
-
 /// Given an expression with aggregate type that represents a value lvalue, 
this
 /// method emits the address of the lvalue, then loads the result into DestPtr.
 void AggExprEmitter::emitAggLoadOfLValue(const Expr *e) {
@@ -863,7 +777,7 @@ void AggExprEmitter::emitArrayInit(Address destPtr, 
cir::ArrayType arrayTy,
   const uint64_t numArrayElements = arrayTy.getSize();
 
   // Check whether there's a non-trivial array-fill expression.
-  const bool hasTrivialFiller = isTrivialFiller(arrayFiller);
+  const bool hasTrivialFiller = CodeGenUtils::isTrivialFiller(arrayFiller);
 
   // Any remaining elements need to be zero-initialized, possibly
   // using the filler expression.  We can skip this if the we're
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index eaca334e88d07..4b59698326f08 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -19,6 +19,7 @@
 #include "clang/AST/StmtVisitor.h"
 #include "clang/CIR/Dialect/IR/CIRTypes.h"
 #include "clang/CIR/MissingFeatures.h"
+#include "clang/CodeGenUtils/ExprUtils.h"
 
 #include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
 #include "mlir/IR/Location.h"
@@ -3138,23 +3139,6 @@ mlir::Value 
ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
                              e->EvaluateKnownConstInt(cgf.getContext())));
 }
 
-/// Return true if the specified expression is cheap enough and 
side-effect-free
-/// enough to evaluate unconditionally instead of conditionally.  This is used
-/// to convert control flow into selects in some cases.
-/// TODO(cir): can be shared with LLVM codegen.
-static bool isCheapEnoughToEvaluateUnconditionally(const Expr *e,
-                                                   CIRGenFunction &cgf) {
-  // Anything that is an integer or floating point constant is fine.
-  return e->IgnoreParens()->isEvaluatable(cgf.getContext());
-
-  // Even non-volatile automatic variables can't be evaluated unconditionally.
-  // Referencing a thread_local may cause non-trivial initialization work to
-  // occur. If we're inside a lambda and one of the variables is from the scope
-  // outside the lambda, that function may have returned already. Reading its
-  // locals is a bad idea. Also, these reads may introduce races there didn't
-  // exist in the source-level program.
-}
-
 mlir::Value ScalarExprEmitter::VisitAbstractConditionalOperator(
     const AbstractConditionalOperator *e) {
   CIRGenBuilderTy &builder = cgf.getBuilder();
@@ -3250,8 +3234,10 @@ mlir::Value 
ScalarExprEmitter::VisitAbstractConditionalOperator(
   // If this is a really simple expression (like x ? 4 : 5), emit this as a
   // select instead of as control flow.  We can only do this if it is cheap
   // and safe to evaluate the LHS and RHS unconditionally.
-  if (isCheapEnoughToEvaluateUnconditionally(lhsExpr, cgf) &&
-      isCheapEnoughToEvaluateUnconditionally(rhsExpr, cgf)) {
+  if (CodeGenUtils::isCheapEnoughToEvaluateUnconditionally(lhsExpr,
+                                                           cgf.getContext()) &&
+      CodeGenUtils::isCheapEnoughToEvaluateUnconditionally(rhsExpr,
+                                                           cgf.getContext())) {
     bool lhsIsVoid = false;
     mlir::Value condV = cgf.evaluateExprAsBool(condExpr);
     assert(!cir::MissingFeatures::incrementProfileCounter());
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp 
b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index a1bd15d88b118..9ba717ce7135f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -22,6 +22,7 @@
 #include "clang/CIR/Dialect/IR/CIRDialect.h"
 #include "clang/CIR/MissingFeatures.h"
 #include "clang/CodeGenUtils/CodeGenUtils.h"
+#include "clang/CodeGenUtils/FunctionUtils.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/IR/FPEnv.h"
 
@@ -29,24 +30,6 @@
 
 namespace clang::CIRGen {
 
-/// shouldEmitLifetimeMarkers - Decide whether we need emit the life-time
-/// markers. Mirror of CodeGenFunction::shouldEmitLifetimeMarkers.
-static bool shouldEmitLifetimeMarkers(const CodeGenOptions &cgOpts,
-                                      const LangOptions &langOpts) {
-
-  if (cgOpts.DisableLifetimeMarkers)
-    return false;
-
-  // Sanitizers may use markers.
-  if (cgOpts.SanitizeAddressUseAfterScope ||
-      langOpts.Sanitize.has(SanitizerKind::HWAddress) ||
-      langOpts.Sanitize.has(SanitizerKind::Memory) ||
-      langOpts.Sanitize.has(SanitizerKind::MemtagStack))
-    return true;
-
-  return cgOpts.OptimizationLevel != 0;
-}
-
 /// Does the statement tree rooted at \p s contain a label, switch, or indirect
 /// goto that could bypass a local's initialization? A coarse stand-in for
 /// classic CodeGen's per-decl bypass analysis (PR28267).
@@ -66,7 +49,7 @@ CIRGenFunction::CIRGenFunction(CIRGenModule &cgm, 
CIRGenBuilderTy &builder,
     : CIRGenTypeCache(cgm), cgm{cgm}, builder(builder),
       curFPFeatures(cgm.getLangOpts()) {
   ehStack.setCGF(this);
-  shouldEmitLifetimeMarkers = CIRGen::shouldEmitLifetimeMarkers(
+  shouldEmitLifetimeMarkers = CodeGenUtils::shouldEmitLifetimeMarkers(
       cgm.getCodeGenOpts(), getContext().getLangOpts());
 }
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp 
b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
index 4588576fd2ecf..59461a6c6de4a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
@@ -25,6 +25,7 @@
 #include "clang/AST/TypeBase.h"
 #include "clang/AST/VTableBuilder.h"
 #include "clang/CIR/MissingFeatures.h"
+#include "clang/CodeGenUtils/ItaniumCXXABIUtils.h"
 #include "llvm/Support/ErrorHandling.h"
 
 using namespace clang;
@@ -2105,58 +2106,6 @@ void CIRGenItaniumCXXABI::emitBadCastCall(CIRGenFunction 
&cgf,
   emitCallToBadCast(cgf, loc);
 }
 
-// TODO(cir): This could be shared with classic codegen.
-static CharUnits computeOffsetHint(ASTContext &astContext,
-                                   const CXXRecordDecl *src,
-                                   const CXXRecordDecl *dst) {
-  CXXBasePaths paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
-                     /*DetectVirtual=*/false);
-
-  // If Dst is not derived from Src we can skip the whole computation below and
-  // return that Src is not a public base of Dst.  Record all inheritance 
paths.
-  if (!dst->isDerivedFrom(src, paths))
-    return CharUnits::fromQuantity(-2);
-
-  unsigned numPublicPaths = 0;
-  CharUnits offset;
-
-  // Now walk all possible inheritance paths.
-  for (const CXXBasePath &path : paths) {
-    if (path.Access != AS_public) // Ignore non-public inheritance.
-      continue;
-
-    ++numPublicPaths;
-
-    for (const CXXBasePathElement &pathElement : path) {
-      // If the path contains a virtual base class we can't give any hint.
-      // -1: no hint.
-      if (pathElement.Base->isVirtual())
-        return CharUnits::fromQuantity(-1);
-
-      if (numPublicPaths > 1) // Won't use offsets, skip computation.
-        continue;
-
-      // Accumulate the base class offsets.
-      const ASTRecordLayout &L =
-          astContext.getASTRecordLayout(pathElement.Class);
-      offset += L.getBaseClassOffset(
-          pathElement.Base->getType()->getAsCXXRecordDecl());
-    }
-  }
-
-  // -2: Src is not a public base of Dst.
-  if (numPublicPaths == 0)
-    return CharUnits::fromQuantity(-2);
-
-  // -3: Src is a multiple public base type but never a virtual base type.
-  if (numPublicPaths > 1)
-    return CharUnits::fromQuantity(-3);
-
-  // Otherwise, the Src type is a unique public nonvirtual base type of Dst.
-  // Return the offset of Src from the origin of Dst.
-  return offset;
-}
-
 static cir::FuncOp getItaniumDynamicCastFn(CIRGenFunction &cgf) {
   // Prototype:
   // void *__dynamic_cast(const void *sub,
@@ -2337,7 +2286,8 @@ static cir::DynamicCastInfoAttr 
emitDynamicCastInfo(CIRGenFunction &cgf,
 
   const CXXRecordDecl *srcDecl = srcRecordTy->getAsCXXRecordDecl();
   const CXXRecordDecl *destDecl = destRecordTy->getAsCXXRecordDecl();
-  CharUnits offsetHint = computeOffsetHint(cgf.getContext(), srcDecl, 
destDecl);
+  CharUnits offsetHint =
+      CodeGenUtils::computeOffsetHint(cgf.getContext(), srcDecl, destDecl);
 
   mlir::Type ptrdiffTy = 
cgf.convertType(cgf.getContext().getPointerDiffType());
   auto offsetHintAttr = cir::IntAttr::get(ptrdiffTy, offsetHint.getQuantity());
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 4c3a4c75d3b52..c5896aa37dc5a 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -34,6 +34,7 @@
 #include "clang/Basic/TargetInfo.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
 #include "clang/CodeGen/SwiftCallingConv.h"
+#include "clang/CodeGenUtils/CallUtils.h"
 #include "llvm/ABI/FunctionInfo.h"
 #include "llvm/ABI/IRTypeMapper.h"
 #include "llvm/ABI/TargetInfo.h"
@@ -150,13 +151,6 @@ CanQualType CodeGenTypes::DeriveThisType(const 
CXXRecordDecl *RD,
   return Context.getPointerType(RecTy);
 }
 
-/// Returns the canonical formal type of the given C++ method.
-static CanQual<FunctionProtoType> GetFormalType(const CXXMethodDecl *MD) {
-  return MD->getType()
-      ->getCanonicalTypeUnqualified()
-      .getAs<FunctionProtoType>();
-}
-
 /// Returns the "extra-canonicalized" return type, which discards
 /// qualifiers on the return type.  Codegen doesn't care about them,
 /// and it makes ABI code a little easier to be able to assume that
@@ -394,7 +388,7 @@ CodeGenTypes::arrangeCXXMethodDeclaration(const 
CXXMethodDecl *MD) {
   assert(!isa<CXXConstructorDecl>(MD) && "wrong method for constructors!");
   assert(!isa<CXXDestructorDecl>(MD) && "wrong method for destructors!");
 
-  CanQualType FT = GetFormalType(MD).getAs<Type>();
+  CanQualType FT = CodeGenUtils::getFormalType(MD).getAs<Type>();
   setCUDAKernelCallingConvention(FT, CGM, MD);
   auto prototype = FT.getAs<FunctionProtoType>();
 
@@ -442,7 +436,7 @@ CodeGenTypes::arrangeCXXStructorDeclaration(GlobalDecl GD) {
       PassParams = inheritingCtorHasParams(Inherited, GD.getCtorType());
   }
 
-  CanQual<FunctionProtoType> FTP = GetFormalType(MD);
+  CanQual<FunctionProtoType> FTP = CodeGenUtils::getFormalType(MD);
 
   // Add the formal parameters.
   if (PassParams)
@@ -518,7 +512,7 @@ const CGFunctionInfo 
&CodeGenTypes::arrangeCXXConstructorCall(
   // +1 for implicit this, which should always be args[0].
   unsigned TotalPrefixArgs = 1 + ExtraPrefixArgs;
 
-  CanQual<FunctionProtoType> FPT = GetFormalType(D);
+  CanQual<FunctionProtoType> FPT = CodeGenUtils::getFormalType(D);
   RequiredArgs Required = PassProtoArgs
                               ? RequiredArgs::forPrototypePlus(
                                     FPT, TotalPrefixArgs + ExtraSuffixArgs)
@@ -661,7 +655,7 @@ const CGFunctionInfo 
&CodeGenTypes::arrangeGlobalDeclaration(GlobalDecl GD) {
 const CGFunctionInfo &
 CodeGenTypes::arrangeUnprototypedMustTailThunk(const CXXMethodDecl *MD) {
   assert(MD->isVirtual() && "only methods have thunks");
-  CanQual<FunctionProtoType> FTP = GetFormalType(MD);
+  CanQual<FunctionProtoType> FTP = CodeGenUtils::getFormalType(MD);
   CanQualType ArgTys[] = {DeriveThisType(MD->getParent(), MD)};
   return arrangeLLVMFunctionInfo(Context.VoidTy, FnInfoOpts::None, ArgTys,
                                  FTP->getExtInfo(), {}, RequiredArgs(1), MD);
@@ -672,7 +666,7 @@ CodeGenTypes::arrangeMSCtorClosure(const CXXConstructorDecl 
*CD,
                                    CXXCtorType CT) {
   assert(CT == Ctor_CopyingClosure || CT == Ctor_DefaultClosure);
 
-  CanQual<FunctionProtoType> FTP = GetFormalType(CD);
+  CanQual<FunctionProtoType> FTP = CodeGenUtils::getFormalType(CD);
   SmallVector<CanQualType, 2> ArgTys;
   const CXXRecordDecl *RD = CD->getParent();
   ArgTys.push_back(DeriveThisType(RD, CD));
@@ -2701,16 +2695,6 @@ static bool canApplyNoFPClass(const ABIArgInfo &AI, 
QualType ParamType,
   return false;
 }
 
-/// Return the nofpclass mask that can be applied to floating-point parameters.
-static llvm::FPClassTest getNoFPClassTestMask(const LangOptions &LangOpts) {
-  llvm::FPClassTest Mask = llvm::fcNone;
-  if (LangOpts.NoHonorInfs)
-    Mask |= llvm::fcInf;
-  if (LangOpts.NoHonorNaNs)
-    Mask |= llvm::fcNan;
-  return Mask;
-}
-
 void CodeGenModule::AdjustMemoryAttribute(StringRef Name,
                                           CGCalleeInfo CalleeInfo,
                                           llvm::AttributeList &Attrs) {
@@ -3035,7 +3019,8 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
       RetAttrs.addAttribute(llvm::Attribute::InReg);
 
     if (canApplyNoFPClass(RetAI, RetTy, true))
-      RetAttrs.addNoFPClassAttr(getNoFPClassTestMask(getLangOpts()));
+      RetAttrs.addNoFPClassAttr(
+          CodeGenUtils::getNoFPClassTestMask(getLangOpts()));
 
     break;
   case ABIArgInfo::Ignore:
@@ -3197,7 +3182,8 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
       Attrs.addStackAlignmentAttr(llvm::MaybeAlign(AI.getDirectAlign()));
 
       if (canApplyNoFPClass(AI, ParamType, false))
-        Attrs.addNoFPClassAttr(getNoFPClassTestMask(getLangOpts()));
+        Attrs.addNoFPClassAttr(
+            CodeGenUtils::getNoFPClassTestMask(getLangOpts()));
       break;
     case ABIArgInfo::Indirect: {
       assert(!ParamType->isIncompleteType() &&
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index ffa1304253519..63f5d9ae13dbf 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -21,11 +21,11 @@
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/CharUnits.h"
 #include "clang/AST/DeclTemplate.h"
-#include "clang/AST/EvaluatedExprVisitor.h"
 #include "clang/AST/RecordLayout.h"
 #include "clang/AST/StmtCXX.h"
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
+#include "clang/CodeGenUtils/ClassUtils.h"
 #include "clang/CodeGenUtils/CodeGenUtils.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/Metadata.h"
@@ -513,31 +513,8 @@ struct CallBaseDtor final : EHScopeStack::Cleanup {
   }
 };
 
-/// A visitor which checks whether an initializer uses 'this' in a
-/// way which requires the vtable to be properly set.
-struct DynamicThisUseChecker
-    : ConstEvaluatedExprVisitor<DynamicThisUseChecker> {
-  typedef ConstEvaluatedExprVisitor<DynamicThisUseChecker> super;
-
-  bool UsesThis;
-
-  DynamicThisUseChecker(const ASTContext &C) : super(C), UsesThis(false) {}
-
-  // Black-list all explicit and implicit references to 'this'.
-  //
-  // Do we need to worry about external references to 'this' derived
-  // from arbitrary code?  If so, then anything which runs arbitrary
-  // external code might potentially access the vtable.
-  void VisitCXXThisExpr(const CXXThisExpr *E) { UsesThis = true; }
-};
 } // end anonymous namespace
 
-static bool BaseInitializerUsesThis(ASTContext &C, const Expr *Init) {
-  DynamicThisUseChecker Checker(C);
-  Checker.Visit(Init);
-  return Checker.UsesThis;
-}
-
 static void EmitBaseInitializer(CodeGenFunction &CGF,
                                 const CXXRecordDecl *ClassDecl,
                                 CXXCtorInitializer *BaseInit) {
@@ -552,7 +529,8 @@ static void EmitBaseInitializer(CodeGenFunction &CGF,
   // If the initializer for the base (other than the constructor
   // itself) accesses 'this' in any way, we need to initialize the
   // vtables.
-  if (BaseInitializerUsesThis(CGF.getContext(), BaseInit->getInit()))
+  if (CodeGenUtils::baseInitializerUsesThis(CGF.getContext(),
+                                            BaseInit->getInit()))
     CGF.InitializeVTablePointers(ClassDecl);
 
   // We can pretend to be a complete class because it only matters for
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index eba802e187beb..35fad3a784da9 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -40,6 +40,7 @@
 #include "clang/Basic/Module.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/CodeGenUtils/CodeGenUtils.h"
+#include "clang/CodeGenUtils/ExprUtils.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/StringExtras.h"
@@ -4761,15 +4762,6 @@ static Address emitArraySubscriptGEP(CodeGenFunction 
&CGF, Address addr,
   }
 }
 
-static QualType getFixedSizeElementType(const ASTContext &ctx,
-                                        const VariableArrayType *vla) {
-  QualType eltType;
-  do {
-    eltType = vla->getElementType();
-  } while ((vla = ctx.getAsVariableArrayType(eltType)));
-  return eltType;
-}
-
 static bool hasBPFPreserveStaticOffset(const RecordDecl *D) {
   return D && D->hasAttr<BPFPreserveStaticOffsetAttr>();
 }
@@ -4852,7 +4844,7 @@ static Address emitArraySubscriptGEP(CodeGenFunction 
&CGF, Address addr,
   // Determine the element size of the statically-sized base.  This is
   // the thing that the indices are expressed in terms of.
   if (auto vla = CGF.getContext().getAsVariableArrayType(eltType)) {
-    eltType = getFixedSizeElementType(CGF.getContext(), vla);
+    eltType = CodeGenUtils::getFixedSizeElementType(CGF.getContext(), vla);
   }
 
   // We can use that to compute the best alignment of the element.
@@ -6628,16 +6620,6 @@ RValue CodeGenFunction::EmitSimpleCallExpr(const 
CallExpr *E,
                   /*Chain=*/nullptr, CallOrInvoke);
 }
 
-// Detect the unusual situation where an inline version is shadowed by a
-// non-inline version. In that case we should pick the external one
-// everywhere. That's GCC behavior too.
-static bool OnlyHasInlineBuiltinDeclaration(const FunctionDecl *FD) {
-  for (const FunctionDecl *PD = FD; PD; PD = PD->getPreviousDecl())
-    if (!PD->isInlineBuiltinDeclaration())
-      return false;
-  return true;
-}
-
 static CGCallee EmitDirectCallee(CodeGenFunction &CGF, GlobalDecl GD) {
   const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
 
@@ -6657,7 +6639,7 @@ static CGCallee EmitDirectCallee(CodeGenFunction &CGF, 
GlobalDecl GD) {
     // When directing calling an inline builtin, call it through it's mangled
     // name to make it clear it's not the actual builtin.
     if (CGF.CurFn->getName() != FDInlineName &&
-        OnlyHasInlineBuiltinDeclaration(FD)) {
+        CodeGenUtils::onlyHasInlineBuiltinDeclaration(FD)) {
       llvm::Constant *CalleePtr = CGF.CGM.getRawFunctionPointer(GD);
       llvm::Function *Fn = llvm::cast<llvm::Function>(CalleePtr);
       llvm::Module *M = Fn->getParent();
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index f18978c7a936e..ff0ed1473d7df 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -25,6 +25,7 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/StmtVisitor.h"
+#include "clang/CodeGenUtils/ExprUtils.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/GlobalVariable.h"
@@ -490,29 +491,6 @@ void AggExprEmitter::VisitCXXStdInitializerListExpr(
          "Expected std::initializer_list to only have two fields");
 }
 
-/// Determine if E is a trivial array filler, that is, one that is
-/// equivalent to zero-initialization.
-static bool isTrivialFiller(Expr *E) {
-  if (!E)
-    return true;
-
-  if (isa<ImplicitValueInitExpr>(E))
-    return true;
-
-  if (auto *ILE = dyn_cast<InitListExpr>(E)) {
-    if (ILE->getNumInits())
-      return false;
-    return isTrivialFiller(ILE->getArrayFiller());
-  }
-
-  if (auto *Cons = dyn_cast_or_null<CXXConstructExpr>(E))
-    return Cons->getConstructor()->isDefaultConstructor() &&
-           Cons->getConstructor()->isTrivial();
-
-  // FIXME: Are there other cases where we can avoid emitting an initializer?
-  return false;
-}
-
 // emit an elementwise cast where the RHS is a scalar or vector
 // or emit an aggregate splat cast
 static void EmitHLSLScalarElementwiseAndSplatCasts(CodeGenFunction &CGF,
@@ -698,7 +676,7 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, 
llvm::ArrayType *AType,
   }
 
   // Check whether there's a non-trivial array-fill expression.
-  bool hasTrivialFiller = isTrivialFiller(ArrayFiller);
+  bool hasTrivialFiller = CodeGenUtils::isTrivialFiller(ArrayFiller);
 
   // Any remaining elements need to be zero-initialized, possibly
   // using the filler expression.  We can skip this if the we're
@@ -1322,71 +1300,6 @@ void 
AggExprEmitter::VisitPointerToDataMemberBinaryOperator(
   EmitFinalDestCopy(E->getType(), LV);
 }
 
-/// Is the value of the given expression possibly a reference to or
-/// into a __block variable?
-static bool isBlockVarRef(const Expr *E) {
-  // Make sure we look through parens.
-  E = E->IgnoreParens();
-
-  // Check for a direct reference to a __block variable.
-  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
-    const VarDecl *var = dyn_cast<VarDecl>(DRE->getDecl());
-    return (var && var->hasAttr<BlocksAttr>());
-  }
-
-  // More complicated stuff.
-
-  // Binary operators.
-  if (const BinaryOperator *op = dyn_cast<BinaryOperator>(E)) {
-    // For an assignment or pointer-to-member operation, just care
-    // about the LHS.
-    if (op->isAssignmentOp() || op->isPtrMemOp())
-      return isBlockVarRef(op->getLHS());
-
-    // For a comma, just care about the RHS.
-    if (op->getOpcode() == BO_Comma)
-      return isBlockVarRef(op->getRHS());
-
-    // FIXME: pointer arithmetic?
-    return false;
-
-    // Check both sides of a conditional operator.
-  } else if (const AbstractConditionalOperator *op =
-                 dyn_cast<AbstractConditionalOperator>(E)) {
-    return isBlockVarRef(op->getTrueExpr()) ||
-           isBlockVarRef(op->getFalseExpr());
-
-    // OVEs are required to support BinaryConditionalOperators.
-  } else if (const OpaqueValueExpr *op = dyn_cast<OpaqueValueExpr>(E)) {
-    if (const Expr *src = op->getSourceExpr())
-      return isBlockVarRef(src);
-
-    // Casts are necessary to get things like (*(int*)&var) = foo().
-    // We don't really care about the kind of cast here, except
-    // we don't want to look through l2r casts, because it's okay
-    // to get the *value* in a __block variable.
-  } else if (const CastExpr *cast = dyn_cast<CastExpr>(E)) {
-    if (cast->getCastKind() == CK_LValueToRValue)
-      return false;
-    return isBlockVarRef(cast->getSubExpr());
-
-    // Handle unary operators.  Again, just aggressively look through
-    // it, ignoring the operation.
-  } else if (const UnaryOperator *uop = dyn_cast<UnaryOperator>(E)) {
-    return isBlockVarRef(uop->getSubExpr());
-
-    // Look into the base of a field access.
-  } else if (const MemberExpr *mem = dyn_cast<MemberExpr>(E)) {
-    return isBlockVarRef(mem->getBase());
-
-    // Look into the base of a subscript.
-  } else if (const ArraySubscriptExpr *sub = dyn_cast<ArraySubscriptExpr>(E)) {
-    return isBlockVarRef(sub->getBase());
-  }
-
-  return false;
-}
-
 void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) {
   ApplyAtomGroup Grp(CGF.getDebugInfo());
   // For an assignment to work, the value on the right has
@@ -1399,7 +1312,7 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator 
*E) {
   // potentially cause a block copy, we need to evaluate the RHS first
   // so that the assignment goes the right place.
   // This is pretty semantically fragile.
-  if (isBlockVarRef(E->getLHS()) &&
+  if (CodeGenUtils::isBlockVarRef(E->getLHS()) &&
       E->getRHS()->HasSideEffects(CGF.getContext())) {
     // Ensure that we have a destination, and evaluate the RHS into that.
     EnsureDest(E->getRHS()->getType());
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp 
b/clang/lib/CodeGen/CGExprScalar.cpp
index d264f4fb28bd6..7d7130dc1d389 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -33,6 +33,7 @@
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/Basic/DiagnosticTrap.h"
 #include "clang/Basic/TargetInfo.h"
+#include "clang/CodeGenUtils/ExprUtils.h"
 #include "llvm/ADT/APFixedPoint.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/IR/Argument.h"
@@ -5913,24 +5914,6 @@ Value *ScalarExprEmitter::VisitBinComma(const 
BinaryOperator *E) {
 //                             Other Operators
 
//===----------------------------------------------------------------------===//
 
-/// isCheapEnoughToEvaluateUnconditionally - Return true if the specified
-/// expression is cheap enough and side-effect-free enough to evaluate
-/// unconditionally instead of conditionally.  This is used to convert control
-/// flow into selects in some cases.
-static bool isCheapEnoughToEvaluateUnconditionally(const Expr *E,
-                                                   CodeGenFunction &CGF) {
-  // Anything that is an integer or floating point constant is fine.
-  return E->IgnoreParens()->isEvaluatable(CGF.getContext());
-
-  // Even non-volatile automatic variables can't be evaluated unconditionally.
-  // Referencing a thread_local may cause non-trivial initialization work to
-  // occur. If we're inside a lambda and one of the variables is from the scope
-  // outside the lambda, that function may have returned already. Reading its
-  // locals is a bad idea. Also, these reads may introduce races there didn't
-  // exist in the source-level program.
-}
-
-
 Value *ScalarExprEmitter::
 VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
   TestAndClearIgnoreResultAssign();
@@ -6036,8 +6019,10 @@ VisitAbstractConditionalOperator(const 
AbstractConditionalOperator *E) {
   // select instead of as control flow.  We can only do this if it is cheap and
   // safe to evaluate the LHS and RHS unconditionally.
   if (!llvm::EnableSingleByteCoverage &&
-      isCheapEnoughToEvaluateUnconditionally(lhsExpr, CGF) &&
-      isCheapEnoughToEvaluateUnconditionally(rhsExpr, CGF)) {
+      CodeGenUtils::isCheapEnoughToEvaluateUnconditionally(lhsExpr,
+                                                           CGF.getContext()) &&
+      CodeGenUtils::isCheapEnoughToEvaluateUnconditionally(rhsExpr,
+                                                           CGF.getContext())) {
     llvm::Value *CondV = CGF.EvaluateExprAsBool(condExpr);
     llvm::Value *StepV = Builder.CreateZExtOrBitCast(CondV, CGF.Int64Ty);
 
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp 
b/clang/lib/CodeGen/CodeGenFunction.cpp
index fe39235fcd4f6..745423945ca83 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -37,6 +37,7 @@
 #include "clang/Basic/TargetInfo.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
 #include "clang/CodeGenUtils/CodeGenUtils.h"
+#include "clang/CodeGenUtils/FunctionUtils.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
@@ -59,32 +60,14 @@
 using namespace clang;
 using namespace CodeGen;
 
-/// shouldEmitLifetimeMarkers - Decide whether we need emit the life-time
-/// markers.
-static bool shouldEmitLifetimeMarkers(const CodeGenOptions &CGOpts,
-                                      const LangOptions &LangOpts) {
-  if (CGOpts.DisableLifetimeMarkers)
-    return false;
-
-  // Sanitizers may use markers.
-  if (CGOpts.SanitizeAddressUseAfterScope ||
-      LangOpts.Sanitize.has(SanitizerKind::HWAddress) ||
-      LangOpts.Sanitize.has(SanitizerKind::Memory) ||
-      LangOpts.Sanitize.has(SanitizerKind::MemtagStack))
-    return true;
-
-  // For now, only in optimized builds.
-  return CGOpts.OptimizationLevel != 0;
-}
-
 CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)
     : CodeGenTypeCache(cgm), CGM(cgm), Target(cgm.getTarget()),
       Builder(cgm, cgm.getModule().getContext(), CGBuilderInserterTy(this)),
       SanOpts(CGM.getLangOpts().Sanitize), CurFPFeatures(CGM.getLangOpts()),
       DebugInfo(CGM.getModuleDebugInfo()),
       PGO(std::make_unique<CodeGenPGO>(cgm)),
-      ShouldEmitLifetimeMarkers(
-          shouldEmitLifetimeMarkers(CGM.getCodeGenOpts(), CGM.getLangOpts())) {
+      ShouldEmitLifetimeMarkers(CodeGenUtils::shouldEmitLifetimeMarkers(
+          CGM.getCodeGenOpts(), CGM.getLangOpts())) {
   if (!suppressNewContext)
     CGM.getCXXABI().getMangleContext().startNewFunction();
   EHStack.setCGF(this);
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp 
b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index c17813140b10f..42d4a15adc46c 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -31,6 +31,7 @@
 #include "clang/AST/Type.h"
 #include "clang/Basic/PointerAuthOptions.h"
 #include "clang/CodeGen/ConstantInitBuilder.h"
+#include "clang/CodeGenUtils/ItaniumCXXABIUtils.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/GlobalValue.h"
 #include "llvm/IR/Instructions.h"
@@ -1554,58 +1555,6 @@ static llvm::FunctionCallee getBadCastFn(CodeGenFunction 
&CGF) {
   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_cast");
 }
 
-/// Compute the src2dst_offset hint as described in the
-/// Itanium C++ ABI [2.9.7]
-static CharUnits computeOffsetHint(ASTContext &Context,
-                                   const CXXRecordDecl *Src,
-                                   const CXXRecordDecl *Dst) {
-  CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
-                     /*DetectVirtual=*/false);
-
-  // If Dst is not derived from Src we can skip the whole computation below and
-  // return that Src is not a public base of Dst.  Record all inheritance 
paths.
-  if (!Dst->isDerivedFrom(Src, Paths))
-    return CharUnits::fromQuantity(-2ULL);
-
-  unsigned NumPublicPaths = 0;
-  CharUnits Offset;
-
-  // Now walk all possible inheritance paths.
-  for (const CXXBasePath &Path : Paths) {
-    if (Path.Access != AS_public)  // Ignore non-public inheritance.
-      continue;
-
-    ++NumPublicPaths;
-
-    for (const CXXBasePathElement &PathElement : Path) {
-      // If the path contains a virtual base class we can't give any hint.
-      // -1: no hint.
-      if (PathElement.Base->isVirtual())
-        return CharUnits::fromQuantity(-1ULL);
-
-      if (NumPublicPaths > 1) // Won't use offsets, skip computation.
-        continue;
-
-      // Accumulate the base class offsets.
-      const ASTRecordLayout &L = Context.getASTRecordLayout(PathElement.Class);
-      Offset += L.getBaseClassOffset(
-          PathElement.Base->getType()->getAsCXXRecordDecl());
-    }
-  }
-
-  // -2: Src is not a public base of Dst.
-  if (NumPublicPaths == 0)
-    return CharUnits::fromQuantity(-2ULL);
-
-  // -3: Src is a multiple public base type but never a virtual base type.
-  if (NumPublicPaths > 1)
-    return CharUnits::fromQuantity(-3ULL);
-
-  // Otherwise, the Src type is a unique public nonvirtual base type of Dst.
-  // Return the offset of Src from the origin of Dst.
-  return Offset;
-}
-
 static llvm::FunctionCallee getBadTypeidFn(CodeGenFunction &CGF) {
   // void __cxa_bad_typeid();
   llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy, false);
@@ -1667,7 +1616,8 @@ llvm::Value *ItaniumCXXABI::emitDynamicCastCall(
   const CXXRecordDecl *DestDecl = DestRecordTy->getAsCXXRecordDecl();
   llvm::Value *OffsetHint = llvm::ConstantInt::getSigned(
       PtrDiffLTy,
-      computeOffsetHint(CGF.getContext(), SrcDecl, DestDecl).getQuantity());
+      CodeGenUtils::computeOffsetHint(CGF.getContext(), SrcDecl, DestDecl)
+          .getQuantity());
 
   // Emit the call to __dynamic_cast.
   llvm::Value *Value = ThisAddr.emitRawPointer(CGF);
diff --git a/clang/lib/CodeGenUtils/CMakeLists.txt 
b/clang/lib/CodeGenUtils/CMakeLists.txt
index b87c83b42dd9b..e3328aa13c343 100644
--- a/clang/lib/CodeGenUtils/CMakeLists.txt
+++ b/clang/lib/CodeGenUtils/CMakeLists.txt
@@ -3,7 +3,12 @@ set(LLVM_LINK_COMPONENTS
   )
 
 add_clang_library(clangCodeGenUtils
+  CallUtils.cpp
+  ClassUtils.cpp
   CodeGenUtils.cpp
+  ExprUtils.cpp
+  FunctionUtils.cpp
+  ItaniumCXXABIUtils.cpp
 
   LINK_LIBS
   clangAST
diff --git a/clang/lib/CodeGenUtils/CallUtils.cpp 
b/clang/lib/CodeGenUtils/CallUtils.cpp
new file mode 100644
index 0000000000000..9eb3c7cf0bc04
--- /dev/null
+++ b/clang/lib/CodeGenUtils/CallUtils.cpp
@@ -0,0 +1,28 @@
+//===--- CallUtils.cpp - Shared call emission queries 
---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/CodeGenUtils/CallUtils.h"
+
+namespace clang::CodeGenUtils {
+
+CanQual<FunctionProtoType> getFormalType(const CXXMethodDecl *MD) {
+  return MD->getType()
+      ->getCanonicalTypeUnqualified()
+      .getAs<FunctionProtoType>();
+}
+
+llvm::FPClassTest getNoFPClassTestMask(const LangOptions &LangOpts) {
+  llvm::FPClassTest Mask = llvm::fcNone;
+  if (LangOpts.NoHonorInfs)
+    Mask |= llvm::fcInf;
+  if (LangOpts.NoHonorNaNs)
+    Mask |= llvm::fcNan;
+  return Mask;
+}
+
+} // namespace clang::CodeGenUtils
diff --git a/clang/lib/CodeGenUtils/ClassUtils.cpp 
b/clang/lib/CodeGenUtils/ClassUtils.cpp
new file mode 100644
index 0000000000000..90bab38280c30
--- /dev/null
+++ b/clang/lib/CodeGenUtils/ClassUtils.cpp
@@ -0,0 +1,39 @@
+//===--- ClassUtils.cpp - Shared C++ class emission queries 
---------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/CodeGenUtils/ClassUtils.h"
+#include "clang/AST/EvaluatedExprVisitor.h"
+
+namespace clang::CodeGenUtils {
+namespace {
+/// A visitor which checks whether an initializer uses 'this' in a
+/// way which requires the vtable to be properly set.
+struct DynamicThisUseChecker
+    : ConstEvaluatedExprVisitor<DynamicThisUseChecker> {
+  using super = ConstEvaluatedExprVisitor<DynamicThisUseChecker>;
+
+  bool UsesThis = false;
+
+  DynamicThisUseChecker(const ASTContext &C) : super(C) {}
+
+  // Black-list all explicit and implicit references to 'this'.
+  //
+  // Do we need to worry about external references to 'this' derived
+  // from arbitrary code?  If so, then anything which runs arbitrary
+  // external code might potentially access the vtable.
+  void VisitCXXThisExpr(const CXXThisExpr *E) { UsesThis = true; }
+};
+} // namespace
+
+bool baseInitializerUsesThis(ASTContext &Ctx, const Expr *Init) {
+  DynamicThisUseChecker Checker(Ctx);
+  Checker.Visit(Init);
+  return Checker.UsesThis;
+}
+
+} // namespace clang::CodeGenUtils
diff --git a/clang/lib/CodeGenUtils/ExprUtils.cpp 
b/clang/lib/CodeGenUtils/ExprUtils.cpp
new file mode 100644
index 0000000000000..69924572c3d77
--- /dev/null
+++ b/clang/lib/CodeGenUtils/ExprUtils.cpp
@@ -0,0 +1,128 @@
+//===--- ExprUtils.cpp - Shared expression emission queries 
---------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/CodeGenUtils/ExprUtils.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/ExprCXX.h"
+
+namespace clang::CodeGenUtils {
+
+QualType getFixedSizeElementType(const ASTContext &Ctx,
+                                 const VariableArrayType *VLA) {
+  QualType EltType;
+  do {
+    EltType = VLA->getElementType();
+  } while ((VLA = Ctx.getAsVariableArrayType(EltType)));
+  return EltType;
+}
+
+bool isBlockVarRef(const Expr *E) {
+  // Make sure we look through parens.
+  E = E->IgnoreParens();
+
+  // Check for a direct reference to a __block variable.
+  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
+    const VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl());
+    return (Var && Var->hasAttr<BlocksAttr>());
+  }
+
+  // More complicated stuff.
+
+  // Binary operators.
+  if (const BinaryOperator *Op = dyn_cast<BinaryOperator>(E)) {
+    // For an assignment or pointer-to-member operation, just care
+    // about the LHS.
+    if (Op->isAssignmentOp() || Op->isPtrMemOp())
+      return isBlockVarRef(Op->getLHS());
+
+    // For a comma, just care about the RHS.
+    if (Op->getOpcode() == BO_Comma)
+      return isBlockVarRef(Op->getRHS());
+
+    // FIXME: pointer arithmetic?
+    return false;
+
+    // Check both sides of a conditional operator.
+  } else if (const AbstractConditionalOperator *Op =
+                 dyn_cast<AbstractConditionalOperator>(E)) {
+    return isBlockVarRef(Op->getTrueExpr()) ||
+           isBlockVarRef(Op->getFalseExpr());
+
+    // OVEs are required to support BinaryConditionalOperators.
+  } else if (const OpaqueValueExpr *Op = dyn_cast<OpaqueValueExpr>(E)) {
+    if (const Expr *Src = Op->getSourceExpr())
+      return isBlockVarRef(Src);
+
+    // Casts are necessary to get things like (*(int*)&var) = foo().
+    // We don't really care about the kind of cast here, except
+    // we don't want to look through l2r casts, because it's okay
+    // to get the *value* in a __block variable.
+  } else if (const CastExpr *Cast = dyn_cast<CastExpr>(E)) {
+    if (Cast->getCastKind() == CK_LValueToRValue)
+      return false;
+    return isBlockVarRef(Cast->getSubExpr());
+
+    // Handle unary operators.  Again, just aggressively look through
+    // it, ignoring the operation.
+  } else if (const UnaryOperator *UOp = dyn_cast<UnaryOperator>(E)) {
+    return isBlockVarRef(UOp->getSubExpr());
+
+    // Look into the base of a field access.
+  } else if (const MemberExpr *Mem = dyn_cast<MemberExpr>(E)) {
+    return isBlockVarRef(Mem->getBase());
+
+    // Look into the base of a subscript.
+  } else if (const ArraySubscriptExpr *Sub = dyn_cast<ArraySubscriptExpr>(E)) {
+    return isBlockVarRef(Sub->getBase());
+  }
+
+  return false;
+}
+
+bool isCheapEnoughToEvaluateUnconditionally(const Expr *E,
+                                            const ASTContext &Ctx) {
+  // Anything that is an integer or floating point constant is fine.
+  return E->IgnoreParens()->isEvaluatable(Ctx);
+
+  // Even non-volatile automatic variables can't be evaluated unconditionally.
+  // Referencing a thread_local may cause non-trivial initialization work to
+  // occur. If we're inside a lambda and one of the variables is from the scope
+  // outside the lambda, that function may have returned already. Reading its
+  // locals is a bad idea. Also, these reads may introduce races there didn't
+  // exist in the source-level program.
+}
+
+bool isTrivialFiller(const Expr *E) {
+  if (!E)
+    return true;
+
+  if (isa<ImplicitValueInitExpr>(E))
+    return true;
+
+  if (const auto *ILE = dyn_cast<InitListExpr>(E)) {
+    if (ILE->getNumInits())
+      return false;
+    return isTrivialFiller(ILE->getArrayFiller());
+  }
+
+  if (const auto *Cons = dyn_cast_or_null<CXXConstructExpr>(E))
+    return Cons->getConstructor()->isDefaultConstructor() &&
+           Cons->getConstructor()->isTrivial();
+
+  // FIXME: Are there other cases where we can avoid emitting an initializer?
+  return false;
+}
+
+bool onlyHasInlineBuiltinDeclaration(const FunctionDecl *FD) {
+  for (const FunctionDecl *PD = FD; PD; PD = PD->getPreviousDecl())
+    if (!PD->isInlineBuiltinDeclaration())
+      return false;
+  return true;
+}
+
+} // namespace clang::CodeGenUtils
diff --git a/clang/lib/CodeGenUtils/FunctionUtils.cpp 
b/clang/lib/CodeGenUtils/FunctionUtils.cpp
new file mode 100644
index 0000000000000..9f01745abbf82
--- /dev/null
+++ b/clang/lib/CodeGenUtils/FunctionUtils.cpp
@@ -0,0 +1,29 @@
+//===--- FunctionUtils.cpp - Shared function emission queries 
-------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/CodeGenUtils/FunctionUtils.h"
+
+namespace clang::CodeGenUtils {
+
+bool shouldEmitLifetimeMarkers(const CodeGenOptions &CGOpts,
+                               const LangOptions &LangOpts) {
+  if (CGOpts.DisableLifetimeMarkers)
+    return false;
+
+  // Sanitizers may use markers.
+  if (CGOpts.SanitizeAddressUseAfterScope ||
+      LangOpts.Sanitize.has(SanitizerKind::HWAddress) ||
+      LangOpts.Sanitize.has(SanitizerKind::Memory) ||
+      LangOpts.Sanitize.has(SanitizerKind::MemtagStack))
+    return true;
+
+  // For now, only in optimized builds.
+  return CGOpts.OptimizationLevel != 0;
+}
+
+} // namespace clang::CodeGenUtils
diff --git a/clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp 
b/clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp
new file mode 100644
index 0000000000000..9640bd23cca54
--- /dev/null
+++ b/clang/lib/CodeGenUtils/ItaniumCXXABIUtils.cpp
@@ -0,0 +1,64 @@
+//===--- ItaniumCXXABIUtils.cpp - Shared Itanium C++ ABI queries 
----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/CodeGenUtils/ItaniumCXXABIUtils.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/RecordLayout.h"
+
+namespace clang::CodeGenUtils {
+
+CharUnits computeOffsetHint(ASTContext &Ctx, const CXXRecordDecl *Src,
+                            const CXXRecordDecl *Dst) {
+  CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+                     /*DetectVirtual=*/false);
+
+  // If Dst is not derived from Src we can skip the whole computation below and
+  // return that Src is not a public base of Dst.  Record all inheritance 
paths.
+  if (!Dst->isDerivedFrom(Src, Paths))
+    return CharUnits::fromQuantity(-2ULL);
+
+  unsigned NumPublicPaths = 0;
+  CharUnits Offset;
+
+  // Now walk all possible inheritance paths.
+  for (const CXXBasePath &Path : Paths) {
+    if (Path.Access != AS_public) // Ignore non-public inheritance.
+      continue;
+
+    ++NumPublicPaths;
+
+    for (const CXXBasePathElement &PathElement : Path) {
+      // If the path contains a virtual base class we can't give any hint.
+      // -1: no hint.
+      if (PathElement.Base->isVirtual())
+        return CharUnits::fromQuantity(-1ULL);
+
+      if (NumPublicPaths > 1) // Won't use offsets, skip computation.
+        continue;
+
+      // Accumulate the base class offsets.
+      const ASTRecordLayout &L = Ctx.getASTRecordLayout(PathElement.Class);
+      Offset += L.getBaseClassOffset(
+          PathElement.Base->getType()->getAsCXXRecordDecl());
+    }
+  }
+
+  // -2: Src is not a public base of Dst.
+  if (NumPublicPaths == 0)
+    return CharUnits::fromQuantity(-2ULL);
+
+  // -3: Src is a multiple public base type but never a virtual base type.
+  if (NumPublicPaths > 1)
+    return CharUnits::fromQuantity(-3ULL);
+
+  // Otherwise, the Src type is a unique public nonvirtual base type of Dst.
+  // Return the offset of Src from the origin of Dst.
+  return Offset;
+}
+
+} // namespace clang::CodeGenUtils

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to