Skip to content

Commit 48dc0c6

Browse files
authored
Merge pull request #8312 from fhahn/tbaa-struct-improvements
Pick !tbaa.struct improvements.
2 parents 8e868d4 + 643bc6b commit 48dc0c6

File tree

11 files changed

+795
-61
lines changed

11 files changed

+795
-61
lines changed

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -393,8 +393,8 @@ CodeGenModule::CodeGenModule(ASTContext &C,
393393
// Enable TBAA unless it's suppressed. ThreadSanitizer needs TBAA even at O0.
394394
if (LangOpts.Sanitize.has(SanitizerKind::Thread) ||
395395
(!CodeGenOpts.RelaxedAliasing && CodeGenOpts.OptimizationLevel > 0))
396-
TBAA.reset(new CodeGenTBAA(Context, TheModule, CodeGenOpts, getLangOpts(),
397-
getCXXABI().getMangleContext()));
396+
TBAA.reset(new CodeGenTBAA(Context, getTypes(), TheModule, CodeGenOpts,
397+
getLangOpts(), getCXXABI().getMangleContext()));
398398

399399
// If debug info or coverage generation is enabled, create the CGDebugInfo
400400
// object.

clang/lib/CodeGen/CodeGenTBAA.cpp

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
//===----------------------------------------------------------------------===//
1616

1717
#include "CodeGenTBAA.h"
18+
#include "CGRecordLayout.h"
19+
#include "CodeGenTypes.h"
1820
#include "clang/AST/ASTContext.h"
1921
#include "clang/AST/Attr.h"
2022
#include "clang/AST/Mangle.h"
@@ -26,16 +28,16 @@
2628
#include "llvm/IR/Metadata.h"
2729
#include "llvm/IR/Module.h"
2830
#include "llvm/IR/Type.h"
31+
#include "llvm/Support/Debug.h"
2932
using namespace clang;
3033
using namespace CodeGen;
3134

32-
CodeGenTBAA::CodeGenTBAA(ASTContext &Ctx, llvm::Module &M,
33-
const CodeGenOptions &CGO,
35+
CodeGenTBAA::CodeGenTBAA(ASTContext &Ctx, CodeGenTypes &CGTypes,
36+
llvm::Module &M, const CodeGenOptions &CGO,
3437
const LangOptions &Features, MangleContext &MContext)
35-
: Context(Ctx), Module(M), CodeGenOpts(CGO),
36-
Features(Features), MContext(MContext), MDHelper(M.getContext()),
37-
Root(nullptr), Char(nullptr)
38-
{}
38+
: Context(Ctx), CGTypes(CGTypes), Module(M), CodeGenOpts(CGO),
39+
Features(Features), MContext(MContext), MDHelper(M.getContext()),
40+
Root(nullptr), Char(nullptr) {}
3941

4042
CodeGenTBAA::~CodeGenTBAA() {
4143
}
@@ -291,14 +293,34 @@ CodeGenTBAA::CollectFields(uint64_t BaseOffset,
291293
return false;
292294

293295
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
296+
const CGRecordLayout &CGRL = CGTypes.getCGRecordLayout(RD);
294297

295298
unsigned idx = 0;
296-
for (RecordDecl::field_iterator i = RD->field_begin(),
297-
e = RD->field_end(); i != e; ++i, ++idx) {
298-
if ((*i)->isZeroSize(Context) || (*i)->isUnnamedBitfield())
299+
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
300+
i != e; ++i, ++idx) {
301+
if ((*i)->isZeroSize(Context))
299302
continue;
300-
uint64_t Offset = BaseOffset +
301-
Layout.getFieldOffset(idx) / Context.getCharWidth();
303+
304+
uint64_t Offset =
305+
BaseOffset + Layout.getFieldOffset(idx) / Context.getCharWidth();
306+
307+
// Create a single field for consecutive named bitfields using char as
308+
// base type.
309+
if ((*i)->isBitField()) {
310+
const CGBitFieldInfo &Info = CGRL.getBitFieldInfo(*i);
311+
if (Info.Offset != 0)
312+
continue;
313+
unsigned CurrentBitFieldSize = Info.StorageSize;
314+
uint64_t Size =
315+
llvm::divideCeil(CurrentBitFieldSize, Context.getCharWidth());
316+
llvm::MDNode *TBAAType = getChar();
317+
llvm::MDNode *TBAATag =
318+
getAccessTagInfo(TBAAAccessInfo(TBAAType, Size));
319+
Fields.push_back(
320+
llvm::MDBuilder::TBAAStructField(Offset, Size, TBAATag));
321+
continue;
322+
}
323+
302324
QualType FieldQTy = i->getType();
303325
if (!CollectFields(Offset, FieldQTy, Fields,
304326
MayAlias || TypeHasMayAlias(FieldQTy)))

clang/lib/CodeGen/CodeGenTBAA.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ namespace clang {
2929
class Type;
3030

3131
namespace CodeGen {
32+
class CodeGenTypes;
3233

3334
// TBAAAccessKind - A kind of TBAA memory access descriptor.
3435
enum class TBAAAccessKind : unsigned {
@@ -115,6 +116,7 @@ struct TBAAAccessInfo {
115116
/// while lowering AST types to LLVM types.
116117
class CodeGenTBAA {
117118
ASTContext &Context;
119+
CodeGenTypes &CGTypes;
118120
llvm::Module &Module;
119121
const CodeGenOptions &CodeGenOpts;
120122
const LangOptions &Features;
@@ -167,8 +169,9 @@ class CodeGenTBAA {
167169
llvm::MDNode *getBaseTypeInfoHelper(const Type *Ty);
168170

169171
public:
170-
CodeGenTBAA(ASTContext &Ctx, llvm::Module &M, const CodeGenOptions &CGO,
171-
const LangOptions &Features, MangleContext &MContext);
172+
CodeGenTBAA(ASTContext &Ctx, CodeGenTypes &CGTypes, llvm::Module &M,
173+
const CodeGenOptions &CGO, const LangOptions &Features,
174+
MangleContext &MContext);
172175
~CodeGenTBAA();
173176

174177
/// getTypeInfo - Get metadata used to describe accesses to objects of the

clang/test/CodeGen/tbaa-struct.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,55 @@ void copy7(A *a1, AA *a2) {
102102
*a1 = *a2;
103103
}
104104

105+
struct NamedBitfields {
106+
signed f0 : 9;
107+
unsigned f1 : 2;
108+
char f2;
109+
double f3;
110+
};
111+
112+
void copy8(NamedBitfields *a1, NamedBitfields *a2) {
113+
// CHECK-LABEL: _Z5copy8P14NamedBitfieldsS0_
114+
// CHECK: tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 8 dereferenceable(16) %a1, ptr noundef nonnull align 8 dereferenceable(16) %a2, i64 16, i1 false),
115+
// CHECK-OLD-SAME: !tbaa.struct [[TS6:!.*]]
116+
// CHECK-NEW-SAME: !tbaa [[TAG_NamedBitfields:!.+]], !tbaa.struct
117+
*a1 = *a2;
118+
}
119+
120+
struct NamedBitfields2 {
121+
char a, b, c;
122+
signed f0 : 3;
123+
unsigned f1 : 4;
124+
char f2 : 7;
125+
double f3;
126+
unsigned f4 : 4;
127+
};
128+
129+
void copy9(NamedBitfields2 *a1, NamedBitfields2 *a2) {
130+
// CHECK-LABEL: _Z5copy9P15NamedBitfields2S0_
131+
// CHECK: tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 8 dereferenceable(24) %a1, ptr noundef nonnull align 8 dereferenceable(24) %a2, i64 24, i1 false),
132+
// CHECK-OLD-SAME: !tbaa.struct [[TS7:!.*]]
133+
// CHECK-NEW-SAME: !tbaa [[TAG_NamedBitfields2:!.+]], !tbaa.struct
134+
*a1 = *a2;
135+
}
136+
137+
// Test with unnamed bitfield at the start and in between named ones..
138+
struct NamedBitfields3 {
139+
unsigned : 11;
140+
signed f0 : 9;
141+
char : 2;
142+
int f1 : 2;
143+
double f2;
144+
};
145+
146+
void copy10(NamedBitfields3 *a1, NamedBitfields3 *a2) {
147+
// CHECK-LABEL: _Z6copy10P15NamedBitfields3S0_
148+
// CHECK: tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 8 dereferenceable(16) %a1, ptr noundef nonnull align 8 dereferenceable(16) %a2, i64 16, i1 false),
149+
// CHECK-OLD-SAME: !tbaa.struct [[TS8:!.*]]
150+
// CHECK-NEW-SAME: !tbaa [[TAG_NamedBitfields3:!.+]], !tbaa.struct
151+
*a1 = *a2;
152+
}
153+
105154
// CHECK-OLD: [[TS]] = !{i64 0, i64 2, !{{.*}}, i64 4, i64 4, !{{.*}}, i64 8, i64 1, !{{.*}}, i64 12, i64 4, !{{.*}}}
106155
// CHECK-OLD: [[CHAR:!.*]] = !{!"omnipotent char", !{{.*}}}
107156
// CHECK-OLD: [[TAG_INT:!.*]] = !{[[INT:!.*]], [[INT]], i64 0}
@@ -113,6 +162,11 @@ void copy7(A *a1, AA *a2) {
113162
// CHECK-OLD: [[TS3]] = !{i64 0, i64 8, !{{.*}}, i64 0, i64 2, !{{.*}}, i64 4, i64 8, !{{.*}}}
114163
// CHECK-OLD: [[TS4]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 1, i64 1, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]]}
115164
// CHECK-OLD: [[TS5]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 4, i64 1, [[TAG_CHAR]], i64 5, i64 1, [[TAG_CHAR]]}
165+
// CHECK-OLD: [[TS6]] = !{i64 0, i64 2, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]], i64 8, i64 8, [[TAG_DOUBLE:!.+]]}
166+
// CHECK-OLD: [[TAG_DOUBLE]] = !{[[DOUBLE:!.+]], [[DOUBLE]], i64 0}
167+
// CHECK-OLD [[DOUBLE]] = !{!"double", [[CHAR]], i64 0}
168+
// CHECK-OLD: [[TS7]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 1, i64 1, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]], i64 3, i64 1, [[TAG_CHAR]], i64 4, i64 1, [[TAG_CHAR]], i64 8, i64 8, [[TAG_DOUBLE]], i64 16, i64 1, [[TAG_CHAR]]}
169+
// CHECK-OLD: [[TS8]] = !{i64 0, i64 4, [[TAG_CHAR]], i64 8, i64 8, [[TAG_DOUBLE]]}
116170

117171
// CHECK-NEW-DAG: [[TYPE_char:!.*]] = !{{{.*}}, i64 1, !"omnipotent char"}
118172
// CHECK-NEW-DAG: [[TAG_char]] = !{[[TYPE_char]], [[TYPE_char]], i64 0, i64 0}
@@ -127,3 +181,10 @@ void copy7(A *a1, AA *a2) {
127181
// CHECK-NEW-DAG: [[TAG_C]] = !{[[TYPE_C]], [[TYPE_C]], i64 0, i64 3}
128182
// CHECK-NEW-DAG: [[TYPE_D:!.*]] = !{[[TYPE_char]], i64 6, !"_ZTS1D", [[TYPE_char]], i64 0, i64 1, [[TYPE_char]], i64 4, i64 1, [[TYPE_char]], i64 5, i64 1}
129183
// CHECK-NEW-DAG: [[TAG_D]] = !{[[TYPE_D]], [[TYPE_D]], i64 0, i64 6}
184+
// CHECK-NEW-DAG: [[TAG_NamedBitfields]] = !{[[TYPE_NamedBitfields:!.+]], [[TYPE_NamedBitfields]], i64 0, i64 16}
185+
// CHECK-NEW-DAG: [[TYPE_NamedBitfields]] = !{[[TYPE_char]], i64 16, !"_ZTS14NamedBitfields", [[TYPE_int]], i64 0, i64 4, [[TYPE_int]], i64 1, i64 4, [[TYPE_char]], i64 2, i64 1, [[TYPE_double:!.+]], i64 8, i64 8}
186+
// CHECK-NEW-DAG: [[TYPE_double]] = !{[[TYPE_char]], i64 8, !"double"}
187+
// CHECK-NEW-DAG: [[TAG_NamedBitfields2]] = !{[[TYPE_NamedBitfields2:!.+]], [[TYPE_NamedBitfields2]], i64 0, i64 24}
188+
// CHECK-NEW-DAG: [[TYPE_NamedBitfields2]] = !{[[TYPE_char]], i64 24, !"_ZTS15NamedBitfields2", [[TYPE_char]], i64 0, i64 1, [[TYPE_char]], i64 1, i64 1, [[TYPE_char]], i64 2, i64 1, [[TYPE_int]], i64 3, i64 4, [[TYPE_int]], i64 3, i64 4, [[TYPE_char]], i64 4, i64 1, [[TYPE_double]], i64 8, i64 8, [[TYPE_int]], i64 16, i64 4}
189+
// CHECK-NEW-DAG: [[TAG_NamedBitfields3]] = !{[[TYPE_NamedBitfields3:!.+]], [[TYPE_NamedBitfields3]], i64 0, i64 16}
190+
// CHECK-NEW-DAG: [[TYPE_NamedBitfields3]] = !{[[TYPE_char]], i64 16, !"_ZTS15NamedBitfields3", [[TYPE_int]], i64 1, i64 4, [[TYPE_int]], i64 2, i64 4, [[TYPE_double]], i64 8, i64 8}

llvm/include/llvm/IR/Metadata.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,14 @@ struct AAMDNodes {
735735
/// together. Different from `merge`, where different locations should
736736
/// overlap each other, `concat` puts non-overlapping locations together.
737737
AAMDNodes concat(const AAMDNodes &Other) const;
738+
739+
/// Create a new AAMDNode for accessing \p AccessSize bytes of this AAMDNode.
740+
/// If his AAMDNode has !tbaa.struct and \p AccessSize matches the size of the
741+
/// field at offset 0, get the TBAA tag describing the accessed field.
742+
AAMDNodes adjustForAccess(unsigned AccessSize);
743+
AAMDNodes adjustForAccess(size_t Offset, Type *AccessTy,
744+
const DataLayout &DL);
745+
AAMDNodes adjustForAccess(size_t Offset, unsigned AccessSize);
738746
};
739747

740748
// Specialize DenseMapInfo for AAMDNodes.

llvm/lib/Analysis/TypeBasedAliasAnalysis.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,3 +818,36 @@ MDNode *AAMDNodes::extendToTBAA(MDNode *MD, ssize_t Len) {
818818
ConstantAsMetadata::get(ConstantInt::get(PreviousSize->getType(), Len));
819819
return MDNode::get(MD->getContext(), NextNodes);
820820
}
821+
822+
AAMDNodes AAMDNodes::adjustForAccess(unsigned AccessSize) {
823+
AAMDNodes New = *this;
824+
MDNode *M = New.TBAAStruct;
825+
if (M && M->getNumOperands() >= 3 && M->getOperand(0) &&
826+
mdconst::hasa<ConstantInt>(M->getOperand(0)) &&
827+
mdconst::extract<ConstantInt>(M->getOperand(0))->isZero() &&
828+
M->getOperand(1) && mdconst::hasa<ConstantInt>(M->getOperand(1)) &&
829+
mdconst::extract<ConstantInt>(M->getOperand(1))->getValue() ==
830+
AccessSize &&
831+
M->getOperand(2) && isa<MDNode>(M->getOperand(2))) {
832+
New.TBAAStruct = nullptr;
833+
New.TBAA = cast<MDNode>(M->getOperand(2));
834+
}
835+
return New;
836+
}
837+
838+
AAMDNodes AAMDNodes::adjustForAccess(size_t Offset, Type *AccessTy,
839+
const DataLayout &DL) {
840+
AAMDNodes New = shift(Offset);
841+
if (!DL.typeSizeEqualsStoreSize(AccessTy))
842+
return New;
843+
TypeSize Size = DL.getTypeStoreSize(AccessTy);
844+
if (Size.isScalable())
845+
return New;
846+
847+
return New.adjustForAccess(Size.getKnownMinValue());
848+
}
849+
850+
AAMDNodes AAMDNodes::adjustForAccess(size_t Offset, unsigned AccessSize) {
851+
AAMDNodes New = shift(Offset);
852+
return New.adjustForAccess(AccessSize);
853+
}

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -185,28 +185,14 @@ Instruction *InstCombinerImpl::SimplifyAnyMemTransfer(AnyMemTransferInst *MI) {
185185

186186
// If the memcpy has metadata describing the members, see if we can get the
187187
// TBAA tag describing our copy.
188-
MDNode *CopyMD = nullptr;
189-
if (MDNode *M = MI->getMetadata(LLVMContext::MD_tbaa)) {
190-
CopyMD = M;
191-
} else if (MDNode *M = MI->getMetadata(LLVMContext::MD_tbaa_struct)) {
192-
if (M->getNumOperands() == 3 && M->getOperand(0) &&
193-
mdconst::hasa<ConstantInt>(M->getOperand(0)) &&
194-
mdconst::extract<ConstantInt>(M->getOperand(0))->isZero() &&
195-
M->getOperand(1) &&
196-
mdconst::hasa<ConstantInt>(M->getOperand(1)) &&
197-
mdconst::extract<ConstantInt>(M->getOperand(1))->getValue() ==
198-
Size &&
199-
M->getOperand(2) && isa<MDNode>(M->getOperand(2)))
200-
CopyMD = cast<MDNode>(M->getOperand(2));
201-
}
188+
AAMDNodes AACopyMD = MI->getAAMetadata().adjustForAccess(Size);
202189

203190
Value *Src = Builder.CreateBitCast(MI->getArgOperand(1), NewSrcPtrTy);
204191
Value *Dest = Builder.CreateBitCast(MI->getArgOperand(0), NewDstPtrTy);
205192
LoadInst *L = Builder.CreateLoad(IntType, Src);
206193
// Alignment from the mem intrinsic will be better, so use it.
207194
L->setAlignment(*CopySrcAlign);
208-
if (CopyMD)
209-
L->setMetadata(LLVMContext::MD_tbaa, CopyMD);
195+
L->setAAMetadata(AACopyMD);
210196
MDNode *LoopMemParallelMD =
211197
MI->getMetadata(LLVMContext::MD_mem_parallel_loop_access);
212198
if (LoopMemParallelMD)
@@ -218,8 +204,7 @@ Instruction *InstCombinerImpl::SimplifyAnyMemTransfer(AnyMemTransferInst *MI) {
218204
StoreInst *S = Builder.CreateStore(L, Dest);
219205
// Alignment from the mem intrinsic will be better, so use it.
220206
S->setAlignment(*CopyDstAlign);
221-
if (CopyMD)
222-
S->setMetadata(LLVMContext::MD_tbaa, CopyMD);
207+
S->setAAMetadata(AACopyMD);
223208
if (LoopMemParallelMD)
224209
S->setMetadata(LLVMContext::MD_mem_parallel_loop_access, LoopMemParallelMD);
225210
if (AccessGroupMD)

0 commit comments

Comments
 (0)