From ea56ef761a84bb8895ad74bc8cf5fb91f6c78695 Mon Sep 17 00:00:00 2001 From: Igor Laevsky Date: Thu, 13 Aug 2015 17:40:04 +0000 Subject: [PATCH] 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 --- test/Analysis/BasicAA/cs-cs.ll | 26 +++++---- test/Analysis/BasicAA/intrinsics.ll | 3 +- .../TypeBasedAliasAnalysis/intrinsics.ll | 3 +- test/Bitcode/compatibility-3.6.ll | 8 ++- test/Bitcode/compatibility.ll | 8 ++- test/Transforms/Inline/inline_invoke.ll | 3 +- test/Transforms/Inline/noalias-calls.ll | 19 ++++--- test/Transforms/MemCpyOpt/memcpy.ll | 5 +- test/Transforms/ObjCARC/nested.ll | 4 +- utils/TableGen/CodeGenIntrinsics.h | 5 +- utils/TableGen/IntrinsicEmitter.cpp | 56 ++++++++----------- 11 files changed, 73 insertions(+), 67 deletions(-) diff --git a/test/Analysis/BasicAA/cs-cs.ll b/test/Analysis/BasicAA/cs-cs.ll index 427242580ed..b0024434a51 100644 --- a/test/Analysis/BasicAA/cs-cs.ll +++ b/test/Analysis/BasicAA/cs-cs.ll @@ -22,18 +22,18 @@ entry: ; CHECK-LABEL: Function: test1: ; CHECK: NoAlias: i8* %p, i8* %q -; CHECK: Just Ref: Ptr: i8* %p <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1 -; CHECK: NoModRef: Ptr: i8* %q <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1 +; CHECK: Just Ref: Ptr: i8* %p <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #4 +; CHECK: NoModRef: Ptr: i8* %q <-> %a = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #4 ; CHECK: NoModRef: Ptr: i8* %p <-> call void @llvm.arm.neon.vst1.v8i16(i8* %q, <8 x i16> %y, i32 16) ; CHECK: Both ModRef: Ptr: i8* %q <-> call void @llvm.arm.neon.vst1.v8i16(i8* %q, <8 x i16> %y, i32 16) -; CHECK: Just Ref: Ptr: i8* %p <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1 -; CHECK: NoModRef: Ptr: i8* %q <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #1 -; 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) -; 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 -; 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 -; 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 -; 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 -; 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) +; CHECK: Just Ref: Ptr: i8* %p <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #4 +; CHECK: NoModRef: Ptr: i8* %q <-> %b = call <8 x i16> @llvm.arm.neon.vld1.v8i16(i8* %p, i32 16) #4 +; 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) +; 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 +; 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 +; 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 +; 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 +; 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) } define void @test2(i8* %P, i8* %Q) nounwind ssp { @@ -233,7 +233,9 @@ define void @test6(i8* %P) nounwind ssp { ; 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) } -attributes #0 = { nounwind readonly } -attributes #1 = { nounwind } +attributes #0 = { nounwind readonly argmemonly } +attributes #1 = { nounwind argmemonly } attributes #2 = { noinline nounwind readonly } attributes #3 = { nounwind ssp } +attributes #4 = { nounwind } + diff --git a/test/Analysis/BasicAA/intrinsics.ll b/test/Analysis/BasicAA/intrinsics.ll index 8c05587ce23..619673f1957 100644 --- a/test/Analysis/BasicAA/intrinsics.ll +++ b/test/Analysis/BasicAA/intrinsics.ll @@ -38,5 +38,6 @@ entry: declare <8 x i16> @llvm.arm.neon.vld1.v8i16(i8*, i32) nounwind readonly declare void @llvm.arm.neon.vst1.v8i16(i8*, <8 x i16>, i32) nounwind -; CHECK: attributes #0 = { nounwind readonly } +; CHECK: attributes #0 = { nounwind readonly argmemonly } +; CHECK: attributes #1 = { nounwind argmemonly } ; CHECK: attributes [[ATTR]] = { nounwind } diff --git a/test/Analysis/TypeBasedAliasAnalysis/intrinsics.ll b/test/Analysis/TypeBasedAliasAnalysis/intrinsics.ll index 0c12cac27d3..43426c0b764 100644 --- a/test/Analysis/TypeBasedAliasAnalysis/intrinsics.ll +++ b/test/Analysis/TypeBasedAliasAnalysis/intrinsics.ll @@ -22,7 +22,8 @@ entry: declare <8 x i16> @llvm.arm.neon.vld1.v8i16(i8*, i32) nounwind readonly declare void @llvm.arm.neon.vst1.v8i16(i8*, <8 x i16>, i32) nounwind -; CHECK: attributes #0 = { nounwind readonly } +; CHECK: attributes #0 = { nounwind readonly argmemonly } +; CHECK: attributes #1 = { nounwind argmemonly } ; CHECK: attributes [[NUW]] = { nounwind } !0 = !{!"tbaa root", null} diff --git a/test/Bitcode/compatibility-3.6.ll b/test/Bitcode/compatibility-3.6.ll index f7baa60a8a4..d283f7120f4 100644 --- a/test/Bitcode/compatibility-3.6.ll +++ b/test/Bitcode/compatibility-3.6.ll @@ -981,7 +981,7 @@ exit: ; CHECK: select <2 x i1> , <2 x i8> , <2 x i8> call void @f.nobuiltin() builtin - ; CHECK: call void @f.nobuiltin() #31 + ; CHECK: call void @f.nobuiltin() #33 call fastcc noalias i32* @f.noalias() noinline ; CHECK: call fastcc noalias i32* @f.noalias() #11 @@ -1179,7 +1179,11 @@ define void @intrinsics.codegen() { ; CHECK: attributes #26 = { sspstrong } ; CHECK: attributes #27 = { uwtable } ; CHECK: attributes #28 = { "cpu"="cortex-a8" } -; CHECK: attributes #31 = { builtin } +; CHECK: attributes #29 = { nounwind readnone } +; CHECK: attributes #30 = { nounwind readonly argmemonly } +; CHECK: attributes #31 = { nounwind argmemonly } +; CHECK: attributes #32 = { nounwind readonly } +; CHECK: attributes #33 = { builtin } ;; Metadata diff --git a/test/Bitcode/compatibility.ll b/test/Bitcode/compatibility.ll index caf45c2d353..585d51b73d4 100644 --- a/test/Bitcode/compatibility.ll +++ b/test/Bitcode/compatibility.ll @@ -1024,7 +1024,7 @@ exit: ; CHECK: select <2 x i1> , <2 x i8> , <2 x i8> call void @f.nobuiltin() builtin - ; CHECK: call void @f.nobuiltin() #34 + ; CHECK: call void @f.nobuiltin() #36 call fastcc noalias i32* @f.noalias() noinline ; CHECK: call fastcc noalias i32* @f.noalias() #12 @@ -1245,8 +1245,10 @@ define void @misc.metadata() { ; CHECK: attributes #30 = { uwtable } ; CHECK: attributes #31 = { "cpu"="cortex-a8" } ; CHECK: attributes #32 = { nounwind readnone } -; CHECK: attributes #33 = { nounwind readonly } -; CHECK: attributes #34 = { builtin } +; CHECK: attributes #33 = { nounwind readonly argmemonly } +; CHECK: attributes #34 = { nounwind argmemonly } +; CHECK: attributes #35 = { nounwind readonly } +; CHECK: attributes #36 = { builtin } ;; Metadata diff --git a/test/Transforms/Inline/inline_invoke.ll b/test/Transforms/Inline/inline_invoke.ll index 2ef216e2d38..8b666956c91 100644 --- a/test/Transforms/Inline/inline_invoke.ll +++ b/test/Transforms/Inline/inline_invoke.ll @@ -344,4 +344,5 @@ terminate: ; CHECK: attributes [[NUW]] = { nounwind } ; CHECK: attributes #1 = { nounwind readnone } ; CHECK: attributes #2 = { ssp uwtable } -; CHECK: attributes #3 = { noreturn nounwind } +; CHECK: attributes #3 = { nounwind argmemonly } +; CHECK: attributes #4 = { noreturn nounwind } diff --git a/test/Transforms/Inline/noalias-calls.ll b/test/Transforms/Inline/noalias-calls.ll index c09d2a67329..56d5c6dc081 100644 --- a/test/Transforms/Inline/noalias-calls.ll +++ b/test/Transforms/Inline/noalias-calls.ll @@ -16,24 +16,25 @@ entry: ret void } -define void @foo(i8* nocapture %a, i8* nocapture readonly %c, i8* nocapture %b) #1 { +define void @foo(i8* nocapture %a, i8* nocapture readonly %c, i8* nocapture %b) #2 { entry: tail call void @hello(i8* %a, i8* %c, i8* %b) ret void } -; CHECK: define void @foo(i8* nocapture %a, i8* nocapture readonly %c, i8* nocapture %b) #1 { +; CHECK: define void @foo(i8* nocapture %a, i8* nocapture readonly %c, i8* nocapture %b) #2 { ; CHECK: entry: -; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %b, i64 16, i32 16, i1 false) #0, !noalias !0 -; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %b, i8* %c, i64 16, i32 16, i1 false) #0, !noalias !3 -; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %c, i64 16, i32 16, i1 false) #0, !alias.scope !5 -; CHECK: call void @hey() #0, !noalias !5 -; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.*}}, i8* %c, i64 16, i32 16, i1 false) #0, !noalias !3 +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %b, i64 16, i32 16, i1 false) #1, !noalias !0 +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %b, i8* %c, i64 16, i32 16, i1 false) #1, !noalias !3 +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %c, i64 16, i32 16, i1 false) #1, !alias.scope !5 +; CHECK: call void @hey() #1, !noalias !5 +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %{{.*}}, i8* %c, i64 16, i32 16, i1 false) #1, !noalias !3 ; CHECK: ret void ; CHECK: } -attributes #0 = { nounwind } -attributes #1 = { nounwind uwtable } +attributes #0 = { nounwind argmemonly } +attributes #1 = { nounwind } +attributes #2 = { nounwind uwtable } ; CHECK: !0 = !{!1} ; CHECK: !1 = distinct !{!1, !2, !"hello: %c"} diff --git a/test/Transforms/MemCpyOpt/memcpy.ll b/test/Transforms/MemCpyOpt/memcpy.ll index 731847440d7..c091073db84 100644 --- a/test/Transforms/MemCpyOpt/memcpy.ll +++ b/test/Transforms/MemCpyOpt/memcpy.ll @@ -206,5 +206,6 @@ declare void @f1(%struct.big* nocapture sret) declare void @f2(%struct.big*) ; CHECK: attributes [[NUW]] = { nounwind } -; CHECK: attributes #1 = { nounwind ssp } -; CHECK: attributes #2 = { nounwind ssp uwtable } +; CHECK: attributes #1 = { nounwind argmemonly } +; CHECK: attributes #2 = { nounwind ssp } +; CHECK: attributes #3 = { nounwind ssp uwtable } diff --git a/test/Transforms/ObjCARC/nested.ll b/test/Transforms/ObjCARC/nested.ll index 464426abfb0..58cac76d1e6 100644 --- a/test/Transforms/ObjCARC/nested.ll +++ b/test/Transforms/ObjCARC/nested.ll @@ -819,5 +819,7 @@ entry: ret void } -; CHECK: attributes [[NUW]] = { nounwind } + +; CHECK: attributes #0 = { nounwind argmemonly } ; CHECK: attributes #1 = { nonlazybind } +; CHECK: attributes [[NUW]] = { nounwind } diff --git a/utils/TableGen/CodeGenIntrinsics.h b/utils/TableGen/CodeGenIntrinsics.h index f4055571b1c..7bdb7e1bc53 100644 --- a/utils/TableGen/CodeGenIntrinsics.h +++ b/utils/TableGen/CodeGenIntrinsics.h @@ -60,9 +60,10 @@ namespace llvm { IntrinsicSignature IS; // Memory mod/ref behavior of this intrinsic. - enum { + enum ModRefKind { NoMem, ReadArgMem, ReadMem, ReadWriteArgMem, ReadWriteMem - } ModRef; + }; + ModRefKind ModRef; /// This is set to true if the intrinsic is overloaded by its argument /// types. diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index cebe5bbc313..c4bb6bf9cc3 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -502,28 +502,6 @@ void IntrinsicEmitter::EmitGenerator(const std::vector &Ints, OS << "#endif\n\n"; // End of GET_INTRINSIC_GENERATOR_GLOBAL } -namespace { -enum ModRefKind { - MRK_none, - MRK_readonly, - MRK_readnone -}; -} - -static ModRefKind getModRefKind(const CodeGenIntrinsic &intrinsic) { - switch (intrinsic.ModRef) { - case CodeGenIntrinsic::NoMem: - return MRK_readnone; - case CodeGenIntrinsic::ReadArgMem: - case CodeGenIntrinsic::ReadMem: - return MRK_readonly; - case CodeGenIntrinsic::ReadWriteArgMem: - case CodeGenIntrinsic::ReadWriteMem: - return MRK_none; - } - llvm_unreachable("bad mod-ref kind"); -} - namespace { struct AttributeComparator { bool operator()(const CodeGenIntrinsic *L, const CodeGenIntrinsic *R) const { @@ -541,8 +519,8 @@ struct AttributeComparator { return R->isConvergent; // Try to order by readonly/readnone attribute. - ModRefKind LK = getModRefKind(*L); - ModRefKind RK = getModRefKind(*R); + CodeGenIntrinsic::ModRefKind LK = L->ModRef; + CodeGenIntrinsic::ModRefKind RK = R->ModRef; if (LK != RK) return (LK > RK); // Order by argument attributes. @@ -649,10 +627,10 @@ EmitAttributes(const std::vector &Ints, raw_ostream &OS) { } } - ModRefKind modRef = getModRefKind(intrinsic); - - if (!intrinsic.canThrow || modRef || intrinsic.isNoReturn || - intrinsic.isNoDuplicate || intrinsic.isConvergent) { + if (!intrinsic.canThrow || + intrinsic.ModRef != CodeGenIntrinsic::ReadWriteMem || + intrinsic.isNoReturn || intrinsic.isNoDuplicate || + intrinsic.isConvergent) { OS << " const Attribute::AttrKind Atts[] = {"; bool addComma = false; if (!intrinsic.canThrow) { @@ -678,17 +656,29 @@ EmitAttributes(const std::vector &Ints, raw_ostream &OS) { addComma = true; } - switch (modRef) { - case MRK_none: break; - case MRK_readonly: + switch (intrinsic.ModRef) { + case CodeGenIntrinsic::NoMem: + if (addComma) + OS << ","; + OS << "Attribute::ReadNone"; + break; + case CodeGenIntrinsic::ReadArgMem: + if (addComma) + OS << ","; + OS << "Attribute::ReadOnly,"; + OS << "Attribute::ArgMemOnly"; + break; + case CodeGenIntrinsic::ReadMem: if (addComma) OS << ","; OS << "Attribute::ReadOnly"; break; - case MRK_readnone: + case CodeGenIntrinsic::ReadWriteArgMem: if (addComma) OS << ","; - OS << "Attribute::ReadNone"; + OS << "Attribute::ArgMemOnly"; + break; + case CodeGenIntrinsic::ReadWriteMem: break; } OS << "};\n"; -- 2.34.1