diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index 3ad1d92e8c2..b10efe340da 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -63,6 +63,12 @@ class NoCapture : IntrinsicProperty { int ArgNo = argNo; } +// NoAlias - The specified argument pointer is not aliasing other "noalias" pointer +// arguments of the intrinsic wrt. the intrinsic scope. +class NoAlias : IntrinsicProperty { + int ArgNo = argNo; +} + // Returned - The specified argument is always the return value of the // intrinsic. class Returned : IntrinsicProperty { @@ -494,7 +500,7 @@ def int_memcpy : Intrinsic<[], [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i1_ty], [IntrArgMemOnly, IntrWillReturn, NoCapture<0>, NoCapture<1>, - WriteOnly<0>, ReadOnly<1>, ImmArg<3>]>; + NoAlias<0>, NoAlias<1>, WriteOnly<0>, ReadOnly<1>, ImmArg<3>]>; def int_memmove : Intrinsic<[], [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i1_ty], diff --git a/test/Bitcode/upgrade-memory-intrinsics.ll b/test/Bitcode/upgrade-memory-intrinsics.ll index 1bdee928cca..c534313170f 100644 --- a/test/Bitcode/upgrade-memory-intrinsics.ll +++ b/test/Bitcode/upgrade-memory-intrinsics.ll @@ -28,7 +28,7 @@ define void @test2(i8* %p1, i8* %p2, i8* %p3) { } ; CHECK: declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg) -; CHECK: declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i1 immarg) +; CHECK: declare void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i64, i1 immarg) ; CHECK: declare void @llvm.memmove.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i1 immarg) declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1) declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly , i8* nocapture readonly, i64, i32, i1) diff --git a/test/Other/lint.ll b/test/Other/lint.ll index ab5df0ec228..415fc29d8f0 100644 --- a/test/Other/lint.ll +++ b/test/Other/lint.ll @@ -9,6 +9,7 @@ declare void @has_noaliases(i32* noalias %p, i32* %q) declare void @one_arg(i32) @CG = constant i32 7 +@CG2 = constant i32 7 @E = external global i8 define i32 @foo() noreturn { @@ -78,7 +79,9 @@ define i32 @foo() noreturn { call void (float) bitcast (void (i32)* @one_arg to void (float)*)(float 0.0) ; CHECK: Write to read-only memory - call void @llvm.memcpy.p0i8.p0i8.i64(i8* bitcast (i32* @CG to i8*), i8* bitcast (i32* @CG to i8*), i64 1, i1 0) +call void @llvm.memcpy.p0i8.p0i8.i64(i8* bitcast (i32* @CG to i8*), i8* bitcast (i32* @CG2 to i8*), i64 1, i1 0) +; CHECK: Unusual: noalias argument aliases another argument +call void @llvm.memcpy.p0i8.p0i8.i64(i8* bitcast (i32* @CG to i8*), i8* bitcast (i32* @CG to i8*), i64 1, i1 0) ; CHECK: Undefined behavior: Buffer overflow %wider = bitcast i8* %buf to i16* diff --git a/utils/TableGen/CodeGenIntrinsics.h b/utils/TableGen/CodeGenIntrinsics.h index 7b74bb07d6e..0e70be2c0aa 100644 --- a/utils/TableGen/CodeGenIntrinsics.h +++ b/utils/TableGen/CodeGenIntrinsics.h @@ -141,6 +141,7 @@ struct CodeGenIntrinsic { enum ArgAttribute { NoCapture, + NoAlias, Returned, ReadOnly, WriteOnly, diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index b65e1b6af79..05f9f22e282 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -733,6 +733,9 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { else if (Property->isSubClassOf("NoCapture")) { unsigned ArgNo = Property->getValueAsInt("ArgNo"); ArgumentAttributes.push_back(std::make_pair(ArgNo, NoCapture)); + } else if (Property->isSubClassOf("NoAlias")) { + unsigned ArgNo = Property->getValueAsInt("ArgNo"); + ArgumentAttributes.push_back(std::make_pair(ArgNo, NoAlias)); } else if (Property->isSubClassOf("Returned")) { unsigned ArgNo = Property->getValueAsInt("ArgNo"); ArgumentAttributes.push_back(std::make_pair(ArgNo, Returned)); diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index 979af98f676..255d78e0821 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -647,6 +647,12 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints, OS << "Attribute::NoCapture"; addComma = true; break; + case CodeGenIntrinsic::NoAlias: + if (addComma) + OS << ","; + OS << "Attribute::NoAlias"; + addComma = true; + break; case CodeGenIntrinsic::Returned: if (addComma) OS << ",";