llvm.org GIT mirror llvm / ea56ef7
Emit argmemonly attribute for intrinsics. Differential Revision: http://reviews.llvm.org/D11352 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@244920 91177308-0d34-0410-b5e6-96231b3b80d8 Igor Laevsky 4 years ago
11 changed file(s) with 73 addition(s) and 67 deletion(s). Raw diff Collapse all Expand all
2121 ; CHECK-LABEL: Function: test1:
2222
2323 ; CHECK: NoAlias: i8* %p, i8* %q
24 ; CHECK: Just Ref: Ptr: i8* %p <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1
25 ; CHECK: NoModRef: Ptr: i8* %q <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1
24 ; CHECK: Just Ref: Ptr: i8* %p <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #4
25 ; CHECK: NoModRef: Ptr: i8* %q <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #4
2626 ; CHECK: NoModRef: Ptr: i8* %p <-> call void @llvm.arm.neon.vst1.v8i16(i8* %q, <8 x i16> %y, i32 16)
2727 ; CHECK: Both ModRef: Ptr: i8* %q <-> call void @llvm.arm.neon.vst1.v8i16(i8* %q, <8 x i16> %y, i32 16)
28 ; CHECK: Just Ref: Ptr: i8* %p <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1
29 ; CHECK: NoModRef: Ptr: i8* %q <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1
30 ; CHECK: NoModRef: %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1 <-> call void @llvm.arm.neon.vst1.v8i16(i8* %q, <8 x i16> %y, i32 16)
31 ; CHECK: NoModRef: %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1 <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1
32 ; CHECK: NoModRef: call void @llvm.arm.neon.vst1.v8i16(i8* %q, <8 x i16> %y, i32 16) <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1
33 ; CHECK: NoModRef: call void @llvm.arm.neon.vst1.v8i16(i8* %q, <8 x i16> %y, i32 16) <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1
34 ; CHECK: NoModRef: %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1 <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1
35 ; CHECK: NoModRef: %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1 <-> call void @llvm.arm.neon.vst1.v8i16(i8* %q, <8 x i16> %y, i32 16)
28 ; CHECK: Just Ref: Ptr: i8* %p <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #4
29 ; CHECK: NoModRef: Ptr: i8* %q <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #4
30 ; CHECK: NoModRef: %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #4 <-> call void @llvm.arm.neon.vst1.v8i16(i8* %q, <8 x i16> %y, i32 16)
31 ; CHECK: NoModRef: %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #4 <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #4
32 ; CHECK: NoModRef: call void @llvm.arm.neon.vst1.v8i16(i8* %q, <8 x i16> %y, i32 16) <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #4
33 ; CHECK: NoModRef: call void @llvm.arm.neon.vst1.v8i16(i8* %q, <8 x i16> %y, i32 16) <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #4
34 ; CHECK: NoModRef: %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #4 <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #4
35 ; CHECK: NoModRef: %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #4 <-> call void @llvm.arm.neon.vst1.v8i16(i8* %q, <8 x i16> %y, i32 16)
3636 }
3737
3838 define void @test2(i8* %P, i8* %Q) nounwind ssp {
232232 ; CHECK: Just Ref: call void @a_readonly_func(i8* %P) <-> call void @llvm.memset.p0i8.i64(i8* %P, i8 -51, i64 32, i32 8, i1 false)
233233 }
234234
235 attributes #0 = { nounwind readonly }
236 attributes #1 = { nounwind }
235 attributes #0 = { nounwind readonly argmemonly }
236 attributes #1 = { nounwind argmemonly }
237237 attributes #2 = { noinline nounwind readonly }
238238 attributes #3 = { nounwind ssp }
239 attributes #4 = { nounwind }
240
3737 declare <8 x i16> @llvm.arm.neon.vld1.v8i16(i8*, i32) nounwind readonly
3838 declare void @llvm.arm.neon.vst1.v8i16(i8*, <8 x i16>, i32) nounwind
3939
40 ; CHECK: attributes #0 = { nounwind readonly }
40 ; CHECK: attributes #0 = { nounwind readonly argmemonly }
41 ; CHECK: attributes #1 = { nounwind argmemonly }
4142 ; CHECK: attributes [[ATTR]] = { nounwind }
2121 declare <8 x i16> @llvm.arm.neon.vld1.v8i16(i8*, i32) nounwind readonly
2222 declare void @llvm.arm.neon.vst1.v8i16(i8*, <8 x i16>, i32) nounwind
2323
24 ; CHECK: attributes #0 = { nounwind readonly }
24 ; CHECK: attributes #0 = { nounwind readonly argmemonly }
25 ; CHECK: attributes #1 = { nounwind argmemonly }
2526 ; CHECK: attributes [[NUW]] = { nounwind }
2627
2728 !0 = !{!"tbaa root", null}
980980 ; CHECK: select <2 x i1> , <2 x i8> , <2 x i8>
981981
982982 call void @f.nobuiltin() builtin
983 ; CHECK: call void @f.nobuiltin() #31
983 ; CHECK: call void @f.nobuiltin() #33
984984
985985 call fastcc noalias i32* @f.noalias() noinline
986986 ; CHECK: call fastcc noalias i32* @f.noalias() #11
11781178 ; CHECK: attributes #26 = { sspstrong }
11791179 ; CHECK: attributes #27 = { uwtable }
11801180 ; CHECK: attributes #28 = { "cpu"="cortex-a8" }
1181 ; CHECK: attributes #31 = { builtin }
1181 ; CHECK: attributes #29 = { nounwind readnone }
1182 ; CHECK: attributes #30 = { nounwind readonly argmemonly }
1183 ; CHECK: attributes #31 = { nounwind argmemonly }
1184 ; CHECK: attributes #32 = { nounwind readonly }
1185 ; CHECK: attributes #33 = { builtin }
11821186
11831187 ;; Metadata
11841188
10231023 ; CHECK: select <2 x i1> , <2 x i8> , <2 x i8>
10241024
10251025 call void @f.nobuiltin() builtin
1026 ; CHECK: call void @f.nobuiltin() #34
1026 ; CHECK: call void @f.nobuiltin() #36
10271027
10281028 call fastcc noalias i32* @f.noalias() noinline
10291029 ; CHECK: call fastcc noalias i32* @f.noalias() #12
12441244 ; CHECK: attributes #30 = { uwtable }
12451245 ; CHECK: attributes #31 = { "cpu"="cortex-a8" }
12461246 ; CHECK: attributes #32 = { nounwind readnone }
1247 ; CHECK: attributes #33 = { nounwind readonly }
1248 ; CHECK: attributes #34 = { builtin }
1247 ; CHECK: attributes #33 = { nounwind readonly argmemonly }
1248 ; CHECK: attributes #34 = { nounwind argmemonly }
1249 ; CHECK: attributes #35 = { nounwind readonly }
1250 ; CHECK: attributes #36 = { builtin }
12491251
12501252 ;; Metadata
12511253
343343 ; CHECK: attributes [[NUW]] = { nounwind }
344344 ; CHECK: attributes #1 = { nounwind readnone }
345345 ; CHECK: attributes #2 = { ssp uwtable }
346 ; CHECK: attributes #3 = { noreturn nounwind }
346 ; CHECK: attributes #3 = { nounwind argmemonly }
347 ; CHECK: attributes #4 = { noreturn nounwind }
1515 ret void
1616 }
1717
18 define void @foo(i8* nocapture %a, i8* nocapture readonly %c, i8* nocapture %b) #1 {
18 define void @foo(i8* nocapture %a, i8* nocapture readonly %c, i8* nocapture %b) #2 {
1919 entry:
2020 tail call void @hello(i8* %a, i8* %c, i8* %b)
2121 ret void
2222 }
2323
24 ; CHECK: define void @foo(i8* nocapture %a, i8* nocapture readonly %c, i8* nocapture %b) #1 {
24 ; CHECK: define void @foo(i8* nocapture %a, i8* nocapture readonly %c, i8* nocapture %b) #2 {
2525 ; CHECK: entry:
26 ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %b, i64 16, i32 16, i1 false) #0, !noalias !0
27 ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %b, i8* %c, i64 16, i32 16, i1 false) #0, !noalias !3
28 ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %c, i64 16, i32 16, i1 false) #0, !alias.scope !5
29 ; CHECK: call void @hey() #0, !noalias !5
30 ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.*}}, i8* %c, i64 16, i32 16, i1 false) #0, !noalias !3
26 ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %b, i64 16, i32 16, i1 false) #1, !noalias !0
27 ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %b, i8* %c, i64 16, i32 16, i1 false) #1, !noalias !3
28 ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %c, i64 16, i32 16, i1 false) #1, !alias.scope !5
29 ; CHECK: call void @hey() #1, !noalias !5
30 ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.*}}, i8* %c, i64 16, i32 16, i1 false) #1, !noalias !3
3131 ; CHECK: ret void
3232 ; CHECK: }
3333
34 attributes #0 = { nounwind }
35 attributes #1 = { nounwind uwtable }
34 attributes #0 = { nounwind argmemonly }
35 attributes #1 = { nounwind }
36 attributes #2 = { nounwind uwtable }
3637
3738 ; CHECK: !0 = !{!1}
3839 ; CHECK: !1 = distinct !{!1, !2, !"hello: %c"}
205205 declare void @f2(%struct.big*)
206206
207207 ; CHECK: attributes [[NUW]] = { nounwind }
208 ; CHECK: attributes #1 = { nounwind ssp }
209 ; CHECK: attributes #2 = { nounwind ssp uwtable }
208 ; CHECK: attributes #1 = { nounwind argmemonly }
209 ; CHECK: attributes #2 = { nounwind ssp }
210 ; CHECK: attributes #3 = { nounwind ssp uwtable }
818818 ret void
819819 }
820820
821
822 ; CHECK: attributes #0 = { nounwind argmemonly }
823 ; CHECK: attributes #1 = { nonlazybind }
821824 ; CHECK: attributes [[NUW]] = { nounwind }
822 ; CHECK: attributes #1 = { nonlazybind }
5959 IntrinsicSignature IS;
6060
6161 // Memory mod/ref behavior of this intrinsic.
62 enum {
62 enum ModRefKind {
6363 NoMem, ReadArgMem, ReadMem, ReadWriteArgMem, ReadWriteMem
64 } ModRef;
64 };
65 ModRefKind ModRef;
6566
6667 /// This is set to true if the intrinsic is overloaded by its argument
6768 /// types.
502502 }
503503
504504 namespace {
505 enum ModRefKind {
506 MRK_none,
507 MRK_readonly,
508 MRK_readnone
509 };
510 }
511
512 static ModRefKind getModRefKind(const CodeGenIntrinsic &intrinsic) {
513 switch (intrinsic.ModRef) {
514 case CodeGenIntrinsic::NoMem:
515 return MRK_readnone;
516 case CodeGenIntrinsic::ReadArgMem:
517 case CodeGenIntrinsic::ReadMem:
518 return MRK_readonly;
519 case CodeGenIntrinsic::ReadWriteArgMem:
520 case CodeGenIntrinsic::ReadWriteMem:
521 return MRK_none;
522 }
523 llvm_unreachable("bad mod-ref kind");
524 }
525
526 namespace {
527505 struct AttributeComparator {
528506 bool operator()(const CodeGenIntrinsic *L, const CodeGenIntrinsic *R) const {
529507 // Sort throwing intrinsics after non-throwing intrinsics.
540518 return R->isConvergent;
541519
542520 // Try to order by readonly/readnone attribute.
543 ModRefKind LK = getModRefKind(*L);
544 ModRefKind RK = getModRefKind(*R);
521 CodeGenIntrinsic::ModRefKind LK = L->ModRef;
522 CodeGenIntrinsic::ModRefKind RK = R->ModRef;
545523 if (LK != RK) return (LK > RK);
546524
547525 // Order by argument attributes.
648626 }
649627 }
650628
651 ModRefKind modRef = getModRefKind(intrinsic);
652
653 if (!intrinsic.canThrow || modRef || intrinsic.isNoReturn ||
654 intrinsic.isNoDuplicate || intrinsic.isConvergent) {
629 if (!intrinsic.canThrow ||
630 intrinsic.ModRef != CodeGenIntrinsic::ReadWriteMem ||
631 intrinsic.isNoReturn || intrinsic.isNoDuplicate ||
632 intrinsic.isConvergent) {
655633 OS << " const Attribute::AttrKind Atts[] = {";
656634 bool addComma = false;
657635 if (!intrinsic.canThrow) {
677655 addComma = true;
678656 }
679657
680 switch (modRef) {
681 case MRK_none: break;
682 case MRK_readonly:
658 switch (intrinsic.ModRef) {
659 case CodeGenIntrinsic::NoMem:
660 if (addComma)
661 OS << ",";
662 OS << "Attribute::ReadNone";
663 break;
664 case CodeGenIntrinsic::ReadArgMem:
665 if (addComma)
666 OS << ",";
667 OS << "Attribute::ReadOnly,";
668 OS << "Attribute::ArgMemOnly";
669 break;
670 case CodeGenIntrinsic::ReadMem:
683671 if (addComma)
684672 OS << ",";
685673 OS << "Attribute::ReadOnly";
686674 break;
687 case MRK_readnone:
675 case CodeGenIntrinsic::ReadWriteArgMem:
688676 if (addComma)
689677 OS << ",";
690 OS << "Attribute::ReadNone";
678 OS << "Attribute::ArgMemOnly";
679 break;
680 case CodeGenIntrinsic::ReadWriteMem:
691681 break;
692682 }
693683 OS << "};\n";