llvm.org GIT mirror llvm / 96342eb
[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 Ivan A. Kosarev 2 years ago
2 changed file(s) with 60 addition(s) and 25 deletion(s). Raw diff Collapse all Expand all
505505 }
506506
507507 static const MDNode *createAccessTag(const MDNode *AccessType) {
508 // If there is no access type or the access type is the root node, then
509 // we don't have any useful access tag to return.
510 if (!AccessType || AccessType->getNumOperands() < 2)
511 return nullptr;
512
508513 Type *Int64 = IntegerType::get(AccessType->getContext(), 64);
509514 auto *ImmutabilityFlag = ConstantAsMetadata::get(ConstantInt::get(Int64, 0));
510515 Metadata *Ops[] = {const_cast(AccessType),
536541 assert(isStructPathTBAA(B) && "Access B is not struct-path aware!");
537542
538543 TBAAStructTagNode TagA(A), TagB(B);
544 const MDNode *CommonType = getLeastCommonType(TagA.getAccessType(),
545 TagB.getAccessType());
546 if (GenericTag)
547 *GenericTag = createAccessTag(CommonType);
539548
540549 // TODO: We need to check if AccessType of TagA encloses AccessType of
541550 // TagB to support aggregate AccessType. If yes, return true.
542551
543 const MDNode *BaseA = TagA.getBaseType();
544 const MDNode *BaseB = TagB.getBaseType();
545
546552 // Climb the type DAG from base type of A to see if we reach base type of B.
547553 uint64_t OffsetA;
548 if (findAccessType(TagA, BaseB, OffsetA)) {
549 if (GenericTag)
550 *GenericTag = createAccessTag(TagB.getAccessType());
554 if (findAccessType(TagA, TagB.getBaseType(), OffsetA))
551555 return OffsetA == TagB.getOffset();
552 }
553556
554557 // Climb the type DAG from base type of B to see if we reach base type of A.
555558 uint64_t OffsetB;
556 if (findAccessType(TagB, BaseA, OffsetB)) {
557 if (GenericTag)
558 *GenericTag = createAccessTag(TagA.getAccessType());
559 if (findAccessType(TagB, TagA.getBaseType(), OffsetB))
559560 return OffsetB == TagA.getOffset();
560 }
561
562 // If neither node is an ancestor of the other, then try to find the type
563 // that is common to both the final access types.
564 const MDNode *CommonType = getLeastCommonType(TagA.getAccessType(),
565 TagB.getAccessType());
566
567 // If there is no common type or the only common type is the root node, then
568 // we don't have any useful generic access tag to return.
569 if (GenericTag)
570 *GenericTag = !CommonType || CommonType->getNumOperands() < 2 ?
571 nullptr : createAccessTag(CommonType);
572
573 // If they have different roots, they're part of different potentially
574 // unrelated type systems, so we must be conservative.
561
562 // If the final access types have different roots, they're part of different
563 // potentially unrelated type systems, so we must be conservative.
575564 if (!CommonType)
576565 return true;
577566
0 ; RUN: opt -mtriple=x86_64-unknown-linux-gnu -load-store-vectorizer -S < %s | \
1 ; RUN: FileCheck %s
2 ;
3 ; The GPU Load & Store Vectorizer may merge differently-typed accesses into a
4 ; single instruction. This test checks that we merge TBAA tags for such
5 ; accesses correctly.
6
7 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
8
9 ; struct S {
10 ; float f;
11 ; int i;
12 ; };
13 %struct.S = type { float, i32 }
14
15 ; float foo(S *p) {
16 ; p->f -= 1;
17 ; p->i -= 1;
18 ; return p->f;
19 ; }
20 define float @foo(%struct.S* %p) {
21 entry:
22 ; CHECK-LABEL: foo
23 ; CHECK: load <2 x i32>, {{.*}}, !tbaa [[TAG_char:!.*]]
24 ; CHECK: store <2 x i32> {{.*}}, !tbaa [[TAG_char]]
25 %f = getelementptr inbounds %struct.S, %struct.S* %p, i64 0, i32 0
26 %0 = load float, float* %f, align 4, !tbaa !2
27 %sub = fadd float %0, -1.000000e+00
28 store float %sub, float* %f, align 4, !tbaa !2
29 %i = getelementptr inbounds %struct.S, %struct.S* %p, i64 0, i32 1
30 %1 = load i32, i32* %i, align 4, !tbaa !8
31 %sub1 = add nsw i32 %1, -1
32 store i32 %sub1, i32* %i, align 4, !tbaa !8
33 ret float %sub
34 }
35
36 !2 = !{!3, !4, i64 0}
37 !3 = !{!"_ZTS1S", !4, i64 0, !7, i64 4}
38 !4 = !{!"float", !5, i64 0}
39 !5 = !{!"omnipotent char", !6, i64 0}
40 !6 = !{!"Simple C++ TBAA"}
41 !7 = !{!"int", !5, i64 0}
42 !8 = !{!3, !7, i64 4}
43
44 ; CHECK-DAG: [[TYPE_char:!.*]] = !{!"omnipotent char", {{.*}}, i64 0}
45 ; CHECK-FAG: [[TAG_char]] = !{[[TYPE_char]], [[TYPE_char]], i64 0}