Skip to content

Commit 96342eb

Browse files
author
Ivan A. Kosarev
committed
[Analysis] Fix merging TBAA tags with different final access types
There are cases when we have to merge TBAA access tags with the same base access type, but different final access types. For example, accesses to different members of the same structure may be vectorized into a single load or store instruction. Since we currently assume that the tags to merge always share the same final access type, we incorrectly return a tag that describes an access to one of the original final access types as the generic tag. This patch fixes that by producing generic tags for the common type and not the final access types of the original tags. Resolves: PR35225: Wrong tbaa metadata after load store vectorizer due to recent change https://bugs.llvm.org/show_bug.cgi?id=35225 Differential Revision: https://reviews.llvm.org/D39732 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@317682 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent d036c9c commit 96342eb

File tree

2 files changed

+59
-24
lines changed

2 files changed

+59
-24
lines changed

lib/Analysis/TypeBasedAliasAnalysis.cpp

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,11 @@ static bool findAccessType(TBAAStructTagNode BaseTag,
506506
}
507507

508508
static const MDNode *createAccessTag(const MDNode *AccessType) {
509+
// If there is no access type or the access type is the root node, then
510+
// we don't have any useful access tag to return.
511+
if (!AccessType || AccessType->getNumOperands() < 2)
512+
return nullptr;
513+
509514
Type *Int64 = IntegerType::get(AccessType->getContext(), 64);
510515
auto *ImmutabilityFlag = ConstantAsMetadata::get(ConstantInt::get(Int64, 0));
511516
Metadata *Ops[] = {const_cast<MDNode*>(AccessType),
@@ -537,42 +542,26 @@ static bool matchAccessTags(const MDNode *A, const MDNode *B,
537542
assert(isStructPathTBAA(B) && "Access B is not struct-path aware!");
538543

539544
TBAAStructTagNode TagA(A), TagB(B);
545+
const MDNode *CommonType = getLeastCommonType(TagA.getAccessType(),
546+
TagB.getAccessType());
547+
if (GenericTag)
548+
*GenericTag = createAccessTag(CommonType);
540549

541550
// TODO: We need to check if AccessType of TagA encloses AccessType of
542551
// TagB to support aggregate AccessType. If yes, return true.
543552

544-
const MDNode *BaseA = TagA.getBaseType();
545-
const MDNode *BaseB = TagB.getBaseType();
546-
547553
// Climb the type DAG from base type of A to see if we reach base type of B.
548554
uint64_t OffsetA;
549-
if (findAccessType(TagA, BaseB, OffsetA)) {
550-
if (GenericTag)
551-
*GenericTag = createAccessTag(TagB.getAccessType());
555+
if (findAccessType(TagA, TagB.getBaseType(), OffsetA))
552556
return OffsetA == TagB.getOffset();
553-
}
554557

555558
// Climb the type DAG from base type of B to see if we reach base type of A.
556559
uint64_t OffsetB;
557-
if (findAccessType(TagB, BaseA, OffsetB)) {
558-
if (GenericTag)
559-
*GenericTag = createAccessTag(TagA.getAccessType());
560+
if (findAccessType(TagB, TagA.getBaseType(), OffsetB))
560561
return OffsetB == TagA.getOffset();
561-
}
562-
563-
// If neither node is an ancestor of the other, then try to find the type
564-
// that is common to both the final access types.
565-
const MDNode *CommonType = getLeastCommonType(TagA.getAccessType(),
566-
TagB.getAccessType());
567-
568-
// If there is no common type or the only common type is the root node, then
569-
// we don't have any useful generic access tag to return.
570-
if (GenericTag)
571-
*GenericTag = !CommonType || CommonType->getNumOperands() < 2 ?
572-
nullptr : createAccessTag(CommonType);
573562

574-
// If they have different roots, they're part of different potentially
575-
// unrelated type systems, so we must be conservative.
563+
// If the final access types have different roots, they're part of different
564+
// potentially unrelated type systems, so we must be conservative.
576565
if (!CommonType)
577566
return true;
578567

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
; RUN: opt -mtriple=x86_64-unknown-linux-gnu -load-store-vectorizer -S < %s | \
2+
; RUN: FileCheck %s
3+
;
4+
; The GPU Load & Store Vectorizer may merge differently-typed accesses into a
5+
; single instruction. This test checks that we merge TBAA tags for such
6+
; accesses correctly.
7+
8+
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
9+
10+
; struct S {
11+
; float f;
12+
; int i;
13+
; };
14+
%struct.S = type { float, i32 }
15+
16+
; float foo(S *p) {
17+
; p->f -= 1;
18+
; p->i -= 1;
19+
; return p->f;
20+
; }
21+
define float @foo(%struct.S* %p) {
22+
entry:
23+
; CHECK-LABEL: foo
24+
; CHECK: load <2 x i32>, {{.*}}, !tbaa [[TAG_char:!.*]]
25+
; CHECK: store <2 x i32> {{.*}}, !tbaa [[TAG_char]]
26+
%f = getelementptr inbounds %struct.S, %struct.S* %p, i64 0, i32 0
27+
%0 = load float, float* %f, align 4, !tbaa !2
28+
%sub = fadd float %0, -1.000000e+00
29+
store float %sub, float* %f, align 4, !tbaa !2
30+
%i = getelementptr inbounds %struct.S, %struct.S* %p, i64 0, i32 1
31+
%1 = load i32, i32* %i, align 4, !tbaa !8
32+
%sub1 = add nsw i32 %1, -1
33+
store i32 %sub1, i32* %i, align 4, !tbaa !8
34+
ret float %sub
35+
}
36+
37+
!2 = !{!3, !4, i64 0}
38+
!3 = !{!"_ZTS1S", !4, i64 0, !7, i64 4}
39+
!4 = !{!"float", !5, i64 0}
40+
!5 = !{!"omnipotent char", !6, i64 0}
41+
!6 = !{!"Simple C++ TBAA"}
42+
!7 = !{!"int", !5, i64 0}
43+
!8 = !{!3, !7, i64 4}
44+
45+
; CHECK-DAG: [[TYPE_char:!.*]] = !{!"omnipotent char", {{.*}}, i64 0}
46+
; CHECK-FAG: [[TAG_char]] = !{[[TYPE_char]], [[TYPE_char]], i64 0}

0 commit comments

Comments
 (0)