diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -81,6 +81,11 @@ int ArgNo = idx.Value; } +// NoUndef - The specified argument is neither undef nor poison. +class NoUndef : IntrinsicProperty { + int ArgNo = idx.Value; +} + class Align : IntrinsicProperty { int ArgNo = idx.Value; int Align = align; @@ -508,7 +513,8 @@ // The assume intrinsic is marked as arbitrarily writing so that proper // control dependencies will be maintained. -def int_assume : Intrinsic<[], [llvm_i1_ty], [IntrWillReturn]>; +def int_assume : Intrinsic<[], [llvm_i1_ty], [IntrWillReturn, + NoUndef>]>; // Stack Protector Intrinsic - The stackprotector intrinsic writes the stack // guard to the correct place on the stack frame. @@ -548,6 +554,7 @@ [IntrArgMemOnly, IntrWillReturn, NoCapture>, NoCapture>, NoAlias>, NoAlias>, + NoUndef>, NoUndef>, WriteOnly>, ReadOnly>, ImmArg>]>; @@ -561,6 +568,7 @@ [IntrArgMemOnly, IntrWillReturn, NoCapture>, NoCapture>, NoAlias>, NoAlias>, + NoUndef>, NoUndef>, WriteOnly>, ReadOnly>, ImmArg>, ImmArg>]>; @@ -569,13 +577,14 @@ llvm_i1_ty], [IntrArgMemOnly, IntrWillReturn, NoCapture>, NoCapture>, + NoUndef>, NoUndef>, ReadOnly>, ImmArg>]>; def int_memset : Intrinsic<[], [llvm_anyptr_ty, llvm_i8_ty, llvm_anyint_ty, llvm_i1_ty], [IntrWriteMem, IntrArgMemOnly, IntrWillReturn, - NoCapture>, WriteOnly>, - ImmArg>]>; + NoCapture>, NoUndef>, + WriteOnly>, ImmArg>]>; // FIXME: Add version of these floating point intrinsics which allow non-default // rounding modes and FP exception handling. @@ -1340,26 +1349,28 @@ LLVMAnyPointerType>, llvm_i32_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], - [IntrArgMemOnly, IntrWillReturn, ImmArg>]>; + [IntrArgMemOnly, IntrWillReturn, + NoUndef>, ImmArg>]>; def int_masked_load : Intrinsic<[llvm_anyvector_ty], [LLVMAnyPointerType>, llvm_i32_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<0>], [IntrReadMem, IntrArgMemOnly, IntrWillReturn, - ImmArg>]>; + NoUndef>, ImmArg>]>; def int_masked_gather: Intrinsic<[llvm_anyvector_ty], [LLVMVectorOfAnyPointersToElt<0>, llvm_i32_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<0>], [IntrReadMem, IntrWillReturn, - ImmArg>]>; + NoUndef>, ImmArg>]>; def int_masked_scatter: Intrinsic<[], [llvm_anyvector_ty, LLVMVectorOfAnyPointersToElt<0>, llvm_i32_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], - [IntrWillReturn, ImmArg>]>; + [IntrWillReturn, NoUndef>, + ImmArg>]>; def int_masked_expandload: Intrinsic<[llvm_anyvector_ty], [LLVMPointerToElt<0>, diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -5093,16 +5093,6 @@ case Instruction::Call: case Instruction::Invoke: { - if (auto *II = dyn_cast(I)) { - switch (II->getIntrinsicID()) { - case Intrinsic::assume: - Operands.insert(II->getArgOperand(0)); - break; - default: - break; - } - } - const CallBase *CB = cast(I); if (CB->isIndirectCall()) Operands.insert(CB->getCalledOperand()); diff --git a/llvm/test/Bitcode/upgrade-memory-intrinsics.ll b/llvm/test/Bitcode/upgrade-memory-intrinsics.ll --- a/llvm/test/Bitcode/upgrade-memory-intrinsics.ll +++ b/llvm/test/Bitcode/upgrade-memory-intrinsics.ll @@ -27,9 +27,9 @@ ret void } -; CHECK: declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, 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) +; CHECK: declare void @llvm.memset.p0i8.i64(i8* nocapture noundef writeonly, i8, i64, i1 immarg) +; CHECK: declare void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias nocapture noundef writeonly, i8* noalias nocapture noundef readonly, i64, i1 immarg) +; CHECK: declare void @llvm.memmove.p0i8.p0i8.i64(i8* nocapture noundef, i8* nocapture noundef 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) declare void @llvm.memmove.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) diff --git a/llvm/test/Transforms/Attributor/norecurse.ll b/llvm/test/Transforms/Attributor/norecurse.ll --- a/llvm/test/Transforms/Attributor/norecurse.ll +++ b/llvm/test/Transforms/Attributor/norecurse.ll @@ -72,7 +72,7 @@ ; CHECK: Function Attrs: argmemonly nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@intrinsic ; CHECK-SAME: (i8* nocapture writeonly [[DEST:%.*]], i8* nocapture readonly [[SRC:%.*]], i32 [[LEN:%.*]]) -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture writeonly [[DEST]], i8* noalias nocapture readonly [[SRC]], i32 [[LEN]], i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture noundef writeonly [[DEST]], i8* noalias nocapture noundef readonly [[SRC]], i32 [[LEN]], i1 false) ; CHECK-NEXT: ret void ; call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 false) diff --git a/llvm/test/Transforms/Attributor/nosync.ll b/llvm/test/Transforms/Attributor/nosync.ll --- a/llvm/test/Transforms/Attributor/nosync.ll +++ b/llvm/test/Transforms/Attributor/nosync.ll @@ -402,7 +402,7 @@ ; CHECK: Function Attrs: argmemonly nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@memcpy_volatile ; CHECK-SAME: (i8* nocapture writeonly [[PTR1:%.*]], i8* nocapture readonly [[PTR2:%.*]]) -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture writeonly [[PTR1]], i8* noalias nocapture readonly [[PTR2]], i32 8, i1 true) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture noundef writeonly [[PTR1]], i8* noalias nocapture noundef readonly [[PTR2]], i32 8, i1 true) ; CHECK-NEXT: ret i32 4 ; call void @llvm.memcpy(i8* %ptr1, i8* %ptr2, i32 8, i1 1) @@ -417,7 +417,7 @@ ; CHECK: Function Attrs: argmemonly nosync nounwind willreturn writeonly ; CHECK-LABEL: define {{[^@]+}}@memset_non_volatile ; CHECK-SAME: (i8* nocapture writeonly [[PTR1:%.*]], i8 [[VAL:%.*]]) -; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* nocapture writeonly [[PTR1]], i8 [[VAL]], i32 8, i1 false) +; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* nocapture noundef writeonly [[PTR1]], i8 [[VAL]], i32 8, i1 false) ; CHECK-NEXT: ret i32 4 ; call void @llvm.memset(i8* %ptr1, i8 %val, i32 8, i1 0) diff --git a/llvm/utils/TableGen/CodeGenIntrinsics.h b/llvm/utils/TableGen/CodeGenIntrinsics.h --- a/llvm/utils/TableGen/CodeGenIntrinsics.h +++ b/llvm/utils/TableGen/CodeGenIntrinsics.h @@ -148,6 +148,7 @@ enum ArgAttrKind { NoCapture, NoAlias, + NoUndef, Returned, ReadOnly, WriteOnly, diff --git a/llvm/utils/TableGen/CodeGenTarget.cpp b/llvm/utils/TableGen/CodeGenTarget.cpp --- a/llvm/utils/TableGen/CodeGenTarget.cpp +++ b/llvm/utils/TableGen/CodeGenTarget.cpp @@ -814,6 +814,9 @@ } else if (Property->isSubClassOf("NoAlias")) { unsigned ArgNo = Property->getValueAsInt("ArgNo"); ArgumentAttributes.emplace_back(ArgNo, NoAlias, 0); + } else if (Property->isSubClassOf("NoUndef")) { + unsigned ArgNo = Property->getValueAsInt("ArgNo"); + ArgumentAttributes.emplace_back(ArgNo, NoUndef, 0); } else if (Property->isSubClassOf("Returned")) { unsigned ArgNo = Property->getValueAsInt("ArgNo"); ArgumentAttributes.emplace_back(ArgNo, Returned, 0); diff --git a/llvm/utils/TableGen/IntrinsicEmitter.cpp b/llvm/utils/TableGen/IntrinsicEmitter.cpp --- a/llvm/utils/TableGen/IntrinsicEmitter.cpp +++ b/llvm/utils/TableGen/IntrinsicEmitter.cpp @@ -687,6 +687,12 @@ OS << "Attribute::NoAlias"; addComma = true; break; + case CodeGenIntrinsic::NoUndef: + if (addComma) + OS << ","; + OS << "Attribute::NoUndef"; + addComma = true; + break; case CodeGenIntrinsic::Returned: if (addComma) OS << ",";