[clang] [Clang] Introduce TBAA metadata for some returned structs (PR #171173)

2025-12-11 Thread Eli Friedman via cfe-commits

efriedma-quic wrote:

See 
https://discourse.llvm.org/t/rfc-add-tbaa-metadata-to-returned-aggregates/88988/

https://github.com/llvm/llvm-project/pull/171173
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Introduce TBAA metadata for some returned structs (PR #171173)

2025-12-11 Thread Benjamin Stott via cfe-commits

https://github.com/BStott6 updated 
https://github.com/llvm/llvm-project/pull/171173

>From 5f99cd51f08af43229c41b04f1865884b4e38d3a Mon Sep 17 00:00:00 2001
From: BStott 
Date: Fri, 5 Dec 2025 15:49:51 +
Subject: [PATCH] Introduce TBAA metadata for some structs returned via direct
 coerced store

---
 clang/lib/CodeGen/CGCall.cpp| 74 -
 clang/lib/CodeGen/CGExpr.cpp| 37 ++-
 clang/lib/CodeGen/CodeGenFunction.h |  3 +-
 clang/lib/CodeGen/CodeGenModule.cpp | 42 
 clang/lib/CodeGen/CodeGenModule.h   |  5 ++
 clang/test/CodeGen/tbaa-returned-struct.cpp | 37 +++
 6 files changed, 162 insertions(+), 36 deletions(-)
 create mode 100644 clang/test/CodeGen/tbaa-returned-struct.cpp

diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index efacb3cc04c01..a35cab83fd286 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -44,12 +44,49 @@
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/Type.h"
 #include "llvm/Transforms/Utils/Local.h"
+#include 
 #include 
 using namespace clang;
 using namespace CodeGen;
 
 /***/
 
+namespace {
+/// Creates a table of `FieldDecl` pointers for each `llvm::StructTy` element
+/// no, by working backwards from the `CGRecordLayout`.
+class LLVMToClangFieldLookup {
+public:
+  LLVMToClangFieldLookup(const llvm::StructType *LLVMType,
+ const RecordDecl *RDecl, const CGRecordLayout 
&RLayout)
+  : Table(LLVMType->getNumElements(), nullptr) {
+for (const auto *FDecl : RDecl->fields()) {
+  if (!isa(FDecl))
+continue;
+  if (!RLayout.containsFieldDecl(FDecl))
+continue;
+
+  unsigned FieldIndex = RLayout.getLLVMFieldNo(FDecl);
+  assert(FieldIndex < Table.size() &&
+ "Field index should not exceed num elements");
+
+  if (!Table[FieldIndex]) {
+// If several LLVM fields correspond to the same Clang FieldDecl,
+// arbitrarily pick the first.
+Table[FieldIndex] = FDecl;
+  }
+}
+  }
+
+  const FieldDecl *getFieldDeclForFieldNo(unsigned FieldNo) {
+assert(FieldNo < Table.size());
+return Table[FieldNo];
+  }
+
+private:
+  SmallVector Table;
+};
+} // namespace
+
 unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
   switch (CC) {
   default:
@@ -1398,7 +1435,8 @@ static llvm::Value *CreateCoercedLoad(Address Src, 
llvm::Type *Ty,
 
 void CodeGenFunction::CreateCoercedStore(llvm::Value *Src, Address Dst,
  llvm::TypeSize DstSize,
- bool DstIsVolatile) {
+ bool DstIsVolatile,
+ std::optional QTy) {
   if (!DstSize)
 return;
 
@@ -1426,6 +1464,22 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value 
*Src, Address Dst,
   addInstToCurrentSourceAtom(I, Src);
 } else if (llvm::StructType *STy =
dyn_cast(Src->getType())) {
+  // For TBAA metadata, get the record layout
+  std::optional FieldLookupForTBAA;
+  if (QTy && CGM.shouldUseTBAA()) {
+if (const RecordDecl *RDecl = (*QTy)->getAsRecordDecl()) {
+  const CGRecordLayout &RLayout =
+  CGM.getTypes().getCGRecordLayout(RDecl);
+
+  if (RLayout.getLLVMType()->isLayoutIdentical(STy)) {
+// There are cases where the returned LLVM struct type does not
+// match the LLVM type corresponding to the record's layout, so we
+// can't use it to work out the correct TBAA metadata.
+FieldLookupForTBAA.emplace(STy, RDecl, RLayout);
+  }
+}
+  }
+
   // Prefer scalar stores to first-class aggregate stores.
   Dst = Dst.withElementType(SrcTy);
   for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
@@ -1433,6 +1487,21 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value 
*Src, Address Dst,
 llvm::Value *Elt = Builder.CreateExtractValue(Src, i);
 auto *I = Builder.CreateStore(Elt, EltPtr, DstIsVolatile);
 addInstToCurrentSourceAtom(I, Elt);
+
+if (FieldLookupForTBAA) {
+  // Try to find the field declaration corresponding to this struct
+  // element no.
+  const FieldDecl *FDecl =
+  FieldLookupForTBAA->getFieldDeclForFieldNo(i);
+
+  if (FDecl && FDecl->getType()->isScalarType()) {
+// FIXME Decide on a way to add TBAA MD for store to an aggregate
+// type. Currently, TBAA MD requires that the access type is a
+// scalar.
+CGM.DecorateInstructionWithTBAA(
+I, CGM.getTBAAInfoForField(TBAAAccessInfo(), *QTy, FDecl));
+  }
+}
   }
 } else {
   auto *I =
@@ -6235,9 +6304,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo 
&CallInfo,
   CreateCoercedStore(
   

[clang] [Clang] Introduce TBAA metadata for some returned structs (PR #171173)

2025-12-08 Thread via cfe-commits

github-actions[bot] wrote:


# :penguin: Linux x64 Test Results

* 84972 tests passed
* 1150 tests skipped
* 1 test failed

## Failed Tests
(click on a test name to see its output)

### lldb-api

lldb-api.tools/lldb-dap/output/TestDAP_output.py

```
Script:
--
/usr/bin/python3 
/home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/test/API/dotest.py
 -u CXXFLAGS -u CFLAGS --env 
LLVM_LIBS_DIR=/home/gha/actions-runner/_work/llvm-project/llvm-project/build/./lib
 --env 
LLVM_INCLUDE_DIR=/home/gha/actions-runner/_work/llvm-project/llvm-project/build/include
 --env 
LLVM_TOOLS_DIR=/home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin
 --libcxx-include-dir 
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/include/c++/v1 
--libcxx-include-target-dir 
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/include/x86_64-unknown-linux-gnu/c++/v1
 --libcxx-library-dir 
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/./lib/x86_64-unknown-linux-gnu
 --arch x86_64 --build-dir 
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/lldb-test-build.noindex
 --lldb-module-cache-dir 
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/lldb-test-build.noindex/module-cache-lldb/lldb-api
 --clang-module-cache-dir 
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/lldb-test-build.noindex/module-cache-clang/lldb-api
 --executable 
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin/lldb 
--compiler 
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin/clang 
--dsymutil 
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin/dsymutil 
--make /usr/bin/gmake --llvm-tools-dir 
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin 
--lldb-obj-root 
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/lldb 
--lldb-libs-dir 
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/./lib 
--cmake-build-type Release 
/home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/test/API/tools/lldb-dap/output
 -p TestDAP_output.py
--
Exit Code: 1

Command Output (stdout):
--
lldb version 22.0.0git (https://github.com/llvm/llvm-project revision 
55b1de5078481bfd17d17f9fac5c86206fed7ab1)
  clang revision 55b1de5078481bfd17d17f9fac5c86206fed7ab1
  llvm revision 55b1de5078481bfd17d17f9fac5c86206fed7ab1
Skipping the following test categories: msvcstl, dsym, pdb, gmodules, 
debugserver, objc

--
Command Output (stderr):
--
= DEBUG ADAPTER PROTOCOL LOGS =
FAIL: LLDB 
(/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64)
 :: test_output (TestDAP_output.TestDAP_output.test_output)
[18:24:22.733] (stdio) --> 
{"command":"initialize","type":"request","arguments":{"adapterID":"lldb-native","clientID":"vscode","columnsStartAt1":true,"linesStartAt1":true,"locale":"en-us","pathFormat":"path","supportsRunInTerminalRequest":true,"supportsVariablePaging":true,"supportsVariableType":true,"supportsStartDebuggingRequest":true,"supportsProgressReporting":true,"supportsInvalidatedEvent":true,"supportsMemoryEvent":true,"$__lldb_sourceInitFile":false},"seq":1}
[18:24:22.733] DAP.cpp:1007 (stdio) queued (command=initialize seq=1)
[18:24:22.734] (stdio) <-- {"body":{"$__lldb_version":"lldb version 22.0.0git 
(https://github.com/llvm/llvm-project revision 
55b1de5078481bfd17d17f9fac5c86206fed7ab1)\n  clang revision 
55b1de5078481bfd17d17f9fac5c86206fed7ab1\n  llvm revision 
55b1de5078481bfd17d17f9fac5c86206fed7ab1","completionTriggerCharacters":["."," 
","\t"],"exceptionBreakpointFilters":[{"description":"C++ 
Catch","filter":"cpp_catch","label":"C++ 
Catch","supportsCondition":true},{"description":"C++ 
Throw","filter":"cpp_throw","label":"C++ 
Throw","supportsCondition":true},{"description":"Objective-C 
Catch","filter":"objc_catch","label":"Objective-C 
Catch","supportsCondition":true},{"description":"Objective-C 
Throw","filter":"objc_throw","label":"Objective-C 
Throw","supportsCondition":true}],"supportTerminateDebuggee":true,"supportsBreakpointLocationsRequest":true,"supportsCancelRequest":true,"supportsCompletionsRequest":true,"supportsConditionalBreakpoints":true,"supportsConfigurationDoneRequest":true,"supportsDataBreakpointBytes":true,"supportsDataBreakpoints":true,"supportsDelayedStackTraceLoading":true,"supportsDisassembleRequest":true,"supportsEvaluateForHovers":true,"supportsExceptionFilterOptions":true,"supportsExceptionInfoRequest":true,"supportsFunctionBreakpoints":true,"supportsHitConditionalBreakpoints":true,"supportsInstructionBreakpoints":true,"supportsLogPoints":true,"supportsModuleSymbolsRequest":true,"supportsModulesRequest":true,"supportsReadMemoryRequest":true,"supportsSetVariable":true,"supportsSteppingGranularity":true,"supportsValueFormattingOptions":true,"supportsWriteMemoryRequest":true},"command":"initialize","request_seq":1,"seq":1,"success":true,"type":"response"}
[18:24:22.734] (stdio) --> 
{"command":"launch","

[clang] [Clang] Introduce TBAA metadata for some returned structs (PR #171173)

2025-12-08 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-codegen

Author: Benjamin Stott (BStott6)


Changes

This PR is intending to improve 
[this](https://github.com/llvm/llvm-project/issues/168577) and potentially 
enable more optimizations by adding TBAA metadata to the fields of structs 
returned directly (not via sret pointer) and where the returned struct matches 
the RecordDecl's struct layout (this is not always true).

---
Full diff: https://github.com/llvm/llvm-project/pull/171173.diff


6 Files Affected:

- (modified) clang/lib/CodeGen/CGCall.cpp (+71-3) 
- (modified) clang/lib/CodeGen/CGExpr.cpp (+5-32) 
- (modified) clang/lib/CodeGen/CodeGenFunction.h (+2-1) 
- (modified) clang/lib/CodeGen/CodeGenModule.cpp (+42) 
- (modified) clang/lib/CodeGen/CodeGenModule.h (+5) 
- (added) clang/test/CodeGen/tbaa-returned-struct.cpp (+37) 


``diff
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index efacb3cc04c01..a35cab83fd286 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -44,12 +44,49 @@
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/Type.h"
 #include "llvm/Transforms/Utils/Local.h"
+#include 
 #include 
 using namespace clang;
 using namespace CodeGen;
 
 /***/
 
+namespace {
+/// Creates a table of `FieldDecl` pointers for each `llvm::StructTy` element
+/// no, by working backwards from the `CGRecordLayout`.
+class LLVMToClangFieldLookup {
+public:
+  LLVMToClangFieldLookup(const llvm::StructType *LLVMType,
+ const RecordDecl *RDecl, const CGRecordLayout 
&RLayout)
+  : Table(LLVMType->getNumElements(), nullptr) {
+for (const auto *FDecl : RDecl->fields()) {
+  if (!isa(FDecl))
+continue;
+  if (!RLayout.containsFieldDecl(FDecl))
+continue;
+
+  unsigned FieldIndex = RLayout.getLLVMFieldNo(FDecl);
+  assert(FieldIndex < Table.size() &&
+ "Field index should not exceed num elements");
+
+  if (!Table[FieldIndex]) {
+// If several LLVM fields correspond to the same Clang FieldDecl,
+// arbitrarily pick the first.
+Table[FieldIndex] = FDecl;
+  }
+}
+  }
+
+  const FieldDecl *getFieldDeclForFieldNo(unsigned FieldNo) {
+assert(FieldNo < Table.size());
+return Table[FieldNo];
+  }
+
+private:
+  SmallVector Table;
+};
+} // namespace
+
 unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
   switch (CC) {
   default:
@@ -1398,7 +1435,8 @@ static llvm::Value *CreateCoercedLoad(Address Src, 
llvm::Type *Ty,
 
 void CodeGenFunction::CreateCoercedStore(llvm::Value *Src, Address Dst,
  llvm::TypeSize DstSize,
- bool DstIsVolatile) {
+ bool DstIsVolatile,
+ std::optional QTy) {
   if (!DstSize)
 return;
 
@@ -1426,6 +1464,22 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value 
*Src, Address Dst,
   addInstToCurrentSourceAtom(I, Src);
 } else if (llvm::StructType *STy =
dyn_cast(Src->getType())) {
+  // For TBAA metadata, get the record layout
+  std::optional FieldLookupForTBAA;
+  if (QTy && CGM.shouldUseTBAA()) {
+if (const RecordDecl *RDecl = (*QTy)->getAsRecordDecl()) {
+  const CGRecordLayout &RLayout =
+  CGM.getTypes().getCGRecordLayout(RDecl);
+
+  if (RLayout.getLLVMType()->isLayoutIdentical(STy)) {
+// There are cases where the returned LLVM struct type does not
+// match the LLVM type corresponding to the record's layout, so we
+// can't use it to work out the correct TBAA metadata.
+FieldLookupForTBAA.emplace(STy, RDecl, RLayout);
+  }
+}
+  }
+
   // Prefer scalar stores to first-class aggregate stores.
   Dst = Dst.withElementType(SrcTy);
   for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
@@ -1433,6 +1487,21 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value 
*Src, Address Dst,
 llvm::Value *Elt = Builder.CreateExtractValue(Src, i);
 auto *I = Builder.CreateStore(Elt, EltPtr, DstIsVolatile);
 addInstToCurrentSourceAtom(I, Elt);
+
+if (FieldLookupForTBAA) {
+  // Try to find the field declaration corresponding to this struct
+  // element no.
+  const FieldDecl *FDecl =
+  FieldLookupForTBAA->getFieldDeclForFieldNo(i);
+
+  if (FDecl && FDecl->getType()->isScalarType()) {
+// FIXME Decide on a way to add TBAA MD for store to an aggregate
+// type. Currently, TBAA MD requires that the access type is a
+// scalar.
+CGM.DecorateInstructionWithTBAA(
+I, CGM.getTBAAInfoForField(TBAAAccessInfo(), *QTy, FDecl));
+  }
+}
   }
 } else {
   auto *I =
@@ -6235,9 +6304,8 @@ RValue CodeGenFunction::EmitCall(const 

[clang] [Clang] Introduce TBAA metadata for some returned structs (PR #171173)

2025-12-08 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Benjamin Stott (BStott6)


Changes

This PR is intending to improve 
[this](https://github.com/llvm/llvm-project/issues/168577) and potentially 
enable more optimizations by adding TBAA metadata to the fields of structs 
returned directly (not via sret pointer) and where the returned struct matches 
the RecordDecl's struct layout (this is not always true).

---
Full diff: https://github.com/llvm/llvm-project/pull/171173.diff


6 Files Affected:

- (modified) clang/lib/CodeGen/CGCall.cpp (+71-3) 
- (modified) clang/lib/CodeGen/CGExpr.cpp (+5-32) 
- (modified) clang/lib/CodeGen/CodeGenFunction.h (+2-1) 
- (modified) clang/lib/CodeGen/CodeGenModule.cpp (+42) 
- (modified) clang/lib/CodeGen/CodeGenModule.h (+5) 
- (added) clang/test/CodeGen/tbaa-returned-struct.cpp (+37) 


``diff
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index efacb3cc04c01..a35cab83fd286 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -44,12 +44,49 @@
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/Type.h"
 #include "llvm/Transforms/Utils/Local.h"
+#include 
 #include 
 using namespace clang;
 using namespace CodeGen;
 
 /***/
 
+namespace {
+/// Creates a table of `FieldDecl` pointers for each `llvm::StructTy` element
+/// no, by working backwards from the `CGRecordLayout`.
+class LLVMToClangFieldLookup {
+public:
+  LLVMToClangFieldLookup(const llvm::StructType *LLVMType,
+ const RecordDecl *RDecl, const CGRecordLayout 
&RLayout)
+  : Table(LLVMType->getNumElements(), nullptr) {
+for (const auto *FDecl : RDecl->fields()) {
+  if (!isa(FDecl))
+continue;
+  if (!RLayout.containsFieldDecl(FDecl))
+continue;
+
+  unsigned FieldIndex = RLayout.getLLVMFieldNo(FDecl);
+  assert(FieldIndex < Table.size() &&
+ "Field index should not exceed num elements");
+
+  if (!Table[FieldIndex]) {
+// If several LLVM fields correspond to the same Clang FieldDecl,
+// arbitrarily pick the first.
+Table[FieldIndex] = FDecl;
+  }
+}
+  }
+
+  const FieldDecl *getFieldDeclForFieldNo(unsigned FieldNo) {
+assert(FieldNo < Table.size());
+return Table[FieldNo];
+  }
+
+private:
+  SmallVector Table;
+};
+} // namespace
+
 unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
   switch (CC) {
   default:
@@ -1398,7 +1435,8 @@ static llvm::Value *CreateCoercedLoad(Address Src, 
llvm::Type *Ty,
 
 void CodeGenFunction::CreateCoercedStore(llvm::Value *Src, Address Dst,
  llvm::TypeSize DstSize,
- bool DstIsVolatile) {
+ bool DstIsVolatile,
+ std::optional QTy) {
   if (!DstSize)
 return;
 
@@ -1426,6 +1464,22 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value 
*Src, Address Dst,
   addInstToCurrentSourceAtom(I, Src);
 } else if (llvm::StructType *STy =
dyn_cast(Src->getType())) {
+  // For TBAA metadata, get the record layout
+  std::optional FieldLookupForTBAA;
+  if (QTy && CGM.shouldUseTBAA()) {
+if (const RecordDecl *RDecl = (*QTy)->getAsRecordDecl()) {
+  const CGRecordLayout &RLayout =
+  CGM.getTypes().getCGRecordLayout(RDecl);
+
+  if (RLayout.getLLVMType()->isLayoutIdentical(STy)) {
+// There are cases where the returned LLVM struct type does not
+// match the LLVM type corresponding to the record's layout, so we
+// can't use it to work out the correct TBAA metadata.
+FieldLookupForTBAA.emplace(STy, RDecl, RLayout);
+  }
+}
+  }
+
   // Prefer scalar stores to first-class aggregate stores.
   Dst = Dst.withElementType(SrcTy);
   for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
@@ -1433,6 +1487,21 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value 
*Src, Address Dst,
 llvm::Value *Elt = Builder.CreateExtractValue(Src, i);
 auto *I = Builder.CreateStore(Elt, EltPtr, DstIsVolatile);
 addInstToCurrentSourceAtom(I, Elt);
+
+if (FieldLookupForTBAA) {
+  // Try to find the field declaration corresponding to this struct
+  // element no.
+  const FieldDecl *FDecl =
+  FieldLookupForTBAA->getFieldDeclForFieldNo(i);
+
+  if (FDecl && FDecl->getType()->isScalarType()) {
+// FIXME Decide on a way to add TBAA MD for store to an aggregate
+// type. Currently, TBAA MD requires that the access type is a
+// scalar.
+CGM.DecorateInstructionWithTBAA(
+I, CGM.getTBAAInfoForField(TBAAAccessInfo(), *QTy, FDecl));
+  }
+}
   }
 } else {
   auto *I =
@@ -6235,9 +6304,8 @@ RValue CodeGenFunction::EmitCall(const CGFuncti

[clang] [Clang] Introduce TBAA metadata for some returned structs (PR #171173)

2025-12-08 Thread Benjamin Stott via cfe-commits

https://github.com/BStott6 created 
https://github.com/llvm/llvm-project/pull/171173

This PR is intending to improve 
[this](https://github.com/llvm/llvm-project/issues/168577) and potentially 
enable more optimizations by adding TBAA metadata to the fields of structs 
returned directly (not via sret pointer) and where the returned struct matches 
the RecordDecl's struct layout (this is not always true).

>From 5f99cd51f08af43229c41b04f1865884b4e38d3a Mon Sep 17 00:00:00 2001
From: BStott 
Date: Fri, 5 Dec 2025 15:49:51 +
Subject: [PATCH] Introduce TBAA metadata for some structs returned via direct
 coerced store

---
 clang/lib/CodeGen/CGCall.cpp| 74 -
 clang/lib/CodeGen/CGExpr.cpp| 37 ++-
 clang/lib/CodeGen/CodeGenFunction.h |  3 +-
 clang/lib/CodeGen/CodeGenModule.cpp | 42 
 clang/lib/CodeGen/CodeGenModule.h   |  5 ++
 clang/test/CodeGen/tbaa-returned-struct.cpp | 37 +++
 6 files changed, 162 insertions(+), 36 deletions(-)
 create mode 100644 clang/test/CodeGen/tbaa-returned-struct.cpp

diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index efacb3cc04c01..a35cab83fd286 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -44,12 +44,49 @@
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/Type.h"
 #include "llvm/Transforms/Utils/Local.h"
+#include 
 #include 
 using namespace clang;
 using namespace CodeGen;
 
 /***/
 
+namespace {
+/// Creates a table of `FieldDecl` pointers for each `llvm::StructTy` element
+/// no, by working backwards from the `CGRecordLayout`.
+class LLVMToClangFieldLookup {
+public:
+  LLVMToClangFieldLookup(const llvm::StructType *LLVMType,
+ const RecordDecl *RDecl, const CGRecordLayout 
&RLayout)
+  : Table(LLVMType->getNumElements(), nullptr) {
+for (const auto *FDecl : RDecl->fields()) {
+  if (!isa(FDecl))
+continue;
+  if (!RLayout.containsFieldDecl(FDecl))
+continue;
+
+  unsigned FieldIndex = RLayout.getLLVMFieldNo(FDecl);
+  assert(FieldIndex < Table.size() &&
+ "Field index should not exceed num elements");
+
+  if (!Table[FieldIndex]) {
+// If several LLVM fields correspond to the same Clang FieldDecl,
+// arbitrarily pick the first.
+Table[FieldIndex] = FDecl;
+  }
+}
+  }
+
+  const FieldDecl *getFieldDeclForFieldNo(unsigned FieldNo) {
+assert(FieldNo < Table.size());
+return Table[FieldNo];
+  }
+
+private:
+  SmallVector Table;
+};
+} // namespace
+
 unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) {
   switch (CC) {
   default:
@@ -1398,7 +1435,8 @@ static llvm::Value *CreateCoercedLoad(Address Src, 
llvm::Type *Ty,
 
 void CodeGenFunction::CreateCoercedStore(llvm::Value *Src, Address Dst,
  llvm::TypeSize DstSize,
- bool DstIsVolatile) {
+ bool DstIsVolatile,
+ std::optional QTy) {
   if (!DstSize)
 return;
 
@@ -1426,6 +1464,22 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value 
*Src, Address Dst,
   addInstToCurrentSourceAtom(I, Src);
 } else if (llvm::StructType *STy =
dyn_cast(Src->getType())) {
+  // For TBAA metadata, get the record layout
+  std::optional FieldLookupForTBAA;
+  if (QTy && CGM.shouldUseTBAA()) {
+if (const RecordDecl *RDecl = (*QTy)->getAsRecordDecl()) {
+  const CGRecordLayout &RLayout =
+  CGM.getTypes().getCGRecordLayout(RDecl);
+
+  if (RLayout.getLLVMType()->isLayoutIdentical(STy)) {
+// There are cases where the returned LLVM struct type does not
+// match the LLVM type corresponding to the record's layout, so we
+// can't use it to work out the correct TBAA metadata.
+FieldLookupForTBAA.emplace(STy, RDecl, RLayout);
+  }
+}
+  }
+
   // Prefer scalar stores to first-class aggregate stores.
   Dst = Dst.withElementType(SrcTy);
   for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
@@ -1433,6 +1487,21 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value 
*Src, Address Dst,
 llvm::Value *Elt = Builder.CreateExtractValue(Src, i);
 auto *I = Builder.CreateStore(Elt, EltPtr, DstIsVolatile);
 addInstToCurrentSourceAtom(I, Elt);
+
+if (FieldLookupForTBAA) {
+  // Try to find the field declaration corresponding to this struct
+  // element no.
+  const FieldDecl *FDecl =
+  FieldLookupForTBAA->getFieldDeclForFieldNo(i);
+
+  if (FDecl && FDecl->getType()->isScalarType()) {
+// FIXME Decide on a way to add TBAA MD for store to an aggregate
+// type. Currently, TBAA MD requires that the access type is a
+// s