// CHECK-NEXT: br i1 [[isnull]], label %[[dynamic_cast_end:[a-z0-9._]+]], label %[[dynamic_cast_notnull:[a-z0-9._]+]]
// CHECK: [[dynamic_cast_notnull]]:
// CHECK-NEXT: [[a:%[0-9]+]] = bitcast %class.A* %a to i8*
-// CHECK-NEXT: [[as_b:%[0-9]+]] = tail call i8* @__dynamic_cast(i8* nonnull [[a]], i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast ({ i8*, i8*, i8* }* @_ZTI1B to i8*), i64 0)
+// CHECK-NEXT: [[as_b:%[0-9]+]] = tail call i8* @__dynamic_cast(i8* nonnull [[a]], i8* nonnull bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* nonnull bitcast ({ i8*, i8*, i8* }* @_ZTI1B to i8*), i64 0)
// CHECK-NEXT: [[b:%[0-9]+]] = bitcast i8* [[as_b]] to %class.B*
// CHECK-NEXT: br label %[[dynamic_cast_end]]
// CHECK: [[dynamic_cast_end]]:
T* test1(V* x) { return &dynamic_cast<T&>(*x); }
// CHECK-LABEL: define dso_local noundef %struct.T* @"?test1@@YAPAUT@@PAUV@@@Z"(%struct.V* noundef %x)
// CHECK: [[CAST:%.*]] = bitcast %struct.V* %x to i8*
-// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[CAST]], i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUV@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUT@@@8" to i8*), i32 1)
+// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[CAST]], i32 0, i8* nonnull bitcast (%rtti.TypeDescriptor7* @"??_R0?AUV@@@8" to i8*), i8* nonnull bitcast (%rtti.TypeDescriptor7* @"??_R0?AUT@@@8" to i8*), i32 1)
// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T*
// CHECK-NEXT: ret %struct.T* [[RET]]
// CHECK-NEXT: [[VBOFFP:%.*]] = getelementptr inbounds i32, i32* [[VBTBL]], i32 1
// CHECK-NEXT: [[VBOFFS:%.*]] = load i32, i32* [[VBOFFP]], align 4
// CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8, i8* [[CAST]], i32 [[VBOFFS]]
-// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[VBOFFS]], i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUA@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUT@@@8" to i8*), i32 1)
+// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[VBOFFS]], i8* nonnull bitcast (%rtti.TypeDescriptor7* @"??_R0?AUA@@@8" to i8*), i8* nonnull bitcast (%rtti.TypeDescriptor7* @"??_R0?AUT@@@8" to i8*), i32 1)
// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T*
// CHECK-NEXT: ret %struct.T* [[RET]]
// CHECK-NEXT: [[VBOFFS:%.*]] = load i32, i32* [[VBOFFP]], align 4
// CHECK-NEXT: [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4
// CHECK-NEXT: [[ADJ:%.*]] = getelementptr inbounds i8, i8* [[VOIDP]], i32 [[DELTA]]
-// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[DELTA]], i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUB@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUT@@@8" to i8*), i32 1)
+// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[ADJ]], i32 [[DELTA]], i8* nonnull bitcast (%rtti.TypeDescriptor7* @"??_R0?AUB@@@8" to i8*), i8* nonnull bitcast (%rtti.TypeDescriptor7* @"??_R0?AUT@@@8" to i8*), i32 1)
// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T*
// CHECK-NEXT: ret %struct.T* [[RET]]
T* test4(V* x) { return dynamic_cast<T*>(x); }
// CHECK-LABEL: define dso_local noundef %struct.T* @"?test4@@YAPAUT@@PAUV@@@Z"(%struct.V* noundef %x)
// CHECK: [[CAST:%.*]] = bitcast %struct.V* %x to i8*
-// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[CAST]], i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUV@@@8" to i8*), i8* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUT@@@8" to i8*), i32 0)
+// CHECK-NEXT: [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8* [[CAST]], i32 0, i8* nonnull bitcast (%rtti.TypeDescriptor7* @"??_R0?AUV@@@8" to i8*), i8* nonnull bitcast (%rtti.TypeDescriptor7* @"??_R0?AUT@@@8" to i8*), i32 0)
// CHECK-NEXT: [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T*
// CHECK-NEXT: ret %struct.T* [[RET]]
A* fn();
const std::type_info* test0_typeid() { return &typeid(int); }
-// CHECK-LABEL: define dso_local noundef %struct.type_info* @"?test0_typeid@@YAPBUtype_info@@XZ"()
+// CHECK-LABEL: define dso_local noundef nonnull %struct.type_info* @"?test0_typeid@@YAPBUtype_info@@XZ"()
// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor2* @"??_R0H@8" to %struct.type_info*)
const std::type_info* test1_typeid() { return &typeid(A); }
-// CHECK-LABEL: define dso_local noundef %struct.type_info* @"?test1_typeid@@YAPBUtype_info@@XZ"()
+// CHECK-LABEL: define dso_local noundef nonnull %struct.type_info* @"?test1_typeid@@YAPBUtype_info@@XZ"()
// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUA@@@8" to %struct.type_info*)
const std::type_info* test2_typeid() { return &typeid(&a); }
-// CHECK-LABEL: define dso_local noundef %struct.type_info* @"?test2_typeid@@YAPBUtype_info@@XZ"()
+// CHECK-LABEL: define dso_local noundef nonnull %struct.type_info* @"?test2_typeid@@YAPBUtype_info@@XZ"()
// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor7* @"??_R0PAUA@@@8" to %struct.type_info*)
const std::type_info* test3_typeid() { return &typeid(*fn()); }
// CHECK-NEXT: ret %struct.type_info* [[RET]]
const std::type_info* test4_typeid() { return &typeid(b); }
-// CHECK: define dso_local noundef %struct.type_info* @"?test4_typeid@@YAPBUtype_info@@XZ"()
+// CHECK: define dso_local noundef nonnull %struct.type_info* @"?test4_typeid@@YAPBUtype_info@@XZ"()
// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor2* @"??_R0H@8" to %struct.type_info*)
const std::type_info* test5_typeid() { return &typeid(v); }
-// CHECK: define dso_local noundef %struct.type_info* @"?test5_typeid@@YAPBUtype_info@@XZ"()
+// CHECK: define dso_local noundef nonnull %struct.type_info* @"?test5_typeid@@YAPBUtype_info@@XZ"()
// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUV@@@8" to %struct.type_info*)
const std::type_info *test6_typeid() { return &typeid((V &)v); }
-// CHECK: define dso_local noundef %struct.type_info* @"?test6_typeid@@YAPBUtype_info@@XZ"()
+// CHECK: define dso_local noundef nonnull %struct.type_info* @"?test6_typeid@@YAPBUtype_info@@XZ"()
// CHECK: ret %struct.type_info* bitcast (%rtti.TypeDescriptor7* @"??_R0?AUV@@@8" to %struct.type_info*)
namespace PR26329 {
// Must be non-zero due to null test above.
return true;
- if (auto *CE = dyn_cast<ConstantExpr>(C)) {
- // See the comment for IntToPtr/PtrToInt instructions below.
- if (CE->getOpcode() == Instruction::IntToPtr ||
- CE->getOpcode() == Instruction::PtrToInt)
- if (Q.DL.getTypeSizeInBits(CE->getOperand(0)->getType())
- .getFixedSize() <=
- Q.DL.getTypeSizeInBits(CE->getType()).getFixedSize())
- return isKnownNonZero(CE->getOperand(0), Depth, Q);
- }
-
// For constant vectors, check that all elements are undefined or known
// non-zero to determine that the whole vector is known non-zero.
if (auto *VecTy = dyn_cast<FixedVectorType>(C->getType())) {
if (!GV->isAbsoluteSymbolRef() && !GV->hasExternalWeakLinkage() &&
GV->getType()->getAddressSpace() == 0)
return true;
- } else
+ }
+
+ // For constant expressions, fall through to the Operator code below.
+ if (!isa<ConstantExpr>(V))
return false;
}
}
}
- if (isKnownNonZeroFromAssume(V, Q))
+ if (!isa<Constant>(V) && isKnownNonZeroFromAssume(V, Q))
return true;
// Some of the tests below are recursive, so bail out if we hit the limit.
}
}
- if (isKnownNonNullFromDominatingCondition(V, Q.CxtI, Q.DT))
+ if (!isa<Constant>(V) &&
+ isKnownNonNullFromDominatingCondition(V, Q.CxtI, Q.DT))
return true;
const Operator *I = dyn_cast<Operator>(V);
; TUNIT-SAME: (%struct.S* noalias nocapture nofree nonnull writeonly sret([[STRUCT_S:%.*]]) align 4 dereferenceable(24) [[AGG_RESULT:%.*]]) #[[ATTR5:[0-9]+]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: call void @write_arg(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(24) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i32 0, i32 0), i32 noundef 1) #[[ATTR16]]
-; TUNIT-NEXT: call void @write_arg(i32* nocapture nofree writeonly align 4 dereferenceable_or_null(20) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 1), i32 noundef 2) #[[ATTR16]]
-; TUNIT-NEXT: call void @write_arg(i32* nocapture nofree writeonly align 4 dereferenceable_or_null(16) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 2), i32 noundef 3) #[[ATTR16]]
+; TUNIT-NEXT: call void @write_arg(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(20) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 1), i32 noundef 2) #[[ATTR16]]
+; TUNIT-NEXT: call void @write_arg(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(16) getelementptr inbounds ([[STRUCT_S]], %struct.S* @Gs1, i64 0, i32 2), i32 noundef 3) #[[ATTR16]]
; TUNIT-NEXT: [[F1:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[AGG_RESULT]], i64 0, i32 3
; TUNIT-NEXT: store float 0x3FF19999A0000000, float* [[F1]], align 4, !tbaa [[TBAA7]]
; TUNIT-NEXT: [[F2:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[AGG_RESULT]], i64 0, i32 4
; TUNIT-NEXT: [[INDVARS_IV_NEXT8]] = add nuw nsw i64 [[INDVARS_IV7]], 1
; TUNIT-NEXT: br label [[FOR_COND13]], !llvm.loop [[LOOP23:![0-9]+]]
; TUNIT: for.end23:
-; TUNIT-NEXT: call void @write_arg(i32* nocapture nofree writeonly align 4 dereferenceable_or_null(524) bitcast (i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @GBytes, i64 0, i64 500) to i32*), i32 noundef 0) #[[ATTR16]]
+; TUNIT-NEXT: call void @write_arg(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(524) bitcast (i8* getelementptr inbounds ([1024 x i8], [1024 x i8]* @GBytes, i64 0, i64 500) to i32*), i32 noundef 0) #[[ATTR16]]
; TUNIT-NEXT: br label [[FOR_COND25:%.*]]
; TUNIT: for.cond25:
; TUNIT-NEXT: [[INDVARS_IV12:%.*]] = phi i64 [ [[INDVARS_IV_NEXT13:%.*]], [[FOR_INC33:%.*]] ], [ 0, [[FOR_END23]] ]
; Similiar to static_global_simplifiable_3 but with a may-store.
define i32 @static_global_not_simplifiable_3(i1 %c, i32* %p) {
-; CGSCC: Function Attrs: nofree norecurse nosync nounwind willreturn
-; CGSCC-LABEL: define {{[^@]+}}@static_global_not_simplifiable_3
-; CGSCC-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly [[P:%.*]]) #[[ATTR5:[0-9]+]] {
-; CGSCC-NEXT: [[SEL:%.*]] = select i1 [[C]], i32* @Flag3, i32* [[P]]
-; CGSCC-NEXT: store i32 1, i32* [[SEL]], align 4, !tbaa [[TBAA3]]
-; CGSCC-NEXT: [[I:%.*]] = load i32, i32* @Flag3, align 4, !tbaa [[TBAA3]]
-; CGSCC-NEXT: ret i32 [[I]]
-;
; TUNIT: Function Attrs: nofree norecurse nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@static_global_not_simplifiable_3
; TUNIT-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly [[P:%.*]]) #[[ATTR3]] {
; TUNIT-NEXT: [[I:%.*]] = load i32, i32* @Flag3, align 4, !tbaa [[TBAA3]]
; TUNIT-NEXT: ret i32 [[I]]
;
+; CGSCC: Function Attrs: nofree norecurse nosync nounwind willreturn
+; CGSCC-LABEL: define {{[^@]+}}@static_global_not_simplifiable_3
+; CGSCC-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly [[P:%.*]]) #[[ATTR5]] {
+; CGSCC-NEXT: [[SEL:%.*]] = select i1 [[C]], i32* @Flag3, i32* [[P]]
+; CGSCC-NEXT: store i32 1, i32* [[SEL]], align 4, !tbaa [[TBAA3]]
+; CGSCC-NEXT: [[I:%.*]] = load i32, i32* @Flag3, align 4, !tbaa [[TBAA3]]
+; CGSCC-NEXT: ret i32 [[I]]
+;
%sel = select i1 %c, i32* @Flag3, i32* %p
store i32 1, i32* %sel, align 4, !tbaa !3
%i = load i32, i32* @Flag3, align 4, !tbaa !3
;
; FIXME: We could replace these loads.
define i32 @write_read_global() {
-; CGSCC: Function Attrs: nofree norecurse nosync nounwind willreturn
-; CGSCC-LABEL: define {{[^@]+}}@write_read_global
-; CGSCC-SAME: () #[[ATTR5]] {
-; CGSCC-NEXT: store i32 7, i32* @Gint1, align 4
-; CGSCC-NEXT: [[L:%.*]] = load i32, i32* @Gint1, align 4
-; CGSCC-NEXT: ret i32 [[L]]
-;
; TUNIT: Function Attrs: nofree norecurse nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@write_read_global
; TUNIT-SAME: () #[[ATTR3]] {
; TUNIT-NEXT: [[L:%.*]] = load i32, i32* @Gint1, align 4
; TUNIT-NEXT: ret i32 [[L]]
;
+; CGSCC: Function Attrs: nofree norecurse nosync nounwind willreturn
+; CGSCC-LABEL: define {{[^@]+}}@write_read_global
+; CGSCC-SAME: () #[[ATTR5]] {
+; CGSCC-NEXT: store i32 7, i32* @Gint1, align 4
+; CGSCC-NEXT: [[L:%.*]] = load i32, i32* @Gint1, align 4
+; CGSCC-NEXT: ret i32 [[L]]
+;
store i32 7, i32* @Gint1
%l = load i32, i32* @Gint1
ret i32 %l
}
define i8 @cast_and_load_1() {
-; CGSCC: Function Attrs: nofree norecurse nosync nounwind willreturn
-; CGSCC-LABEL: define {{[^@]+}}@cast_and_load_1
-; CGSCC-SAME: () #[[ATTR5]] {
-; CGSCC-NEXT: store i32 42, i32* @bytes1, align 4
-; CGSCC-NEXT: [[L:%.*]] = load i8, i8* bitcast (i32* @bytes1 to i8*), align 4
-; CGSCC-NEXT: ret i8 [[L]]
-;
; TUNIT: Function Attrs: nofree norecurse nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@cast_and_load_1
; TUNIT-SAME: () #[[ATTR3]] {
; TUNIT-NEXT: [[L:%.*]] = load i8, i8* bitcast (i32* @bytes1 to i8*), align 4
; TUNIT-NEXT: ret i8 [[L]]
;
+; CGSCC: Function Attrs: nofree norecurse nosync nounwind willreturn
+; CGSCC-LABEL: define {{[^@]+}}@cast_and_load_1
+; CGSCC-SAME: () #[[ATTR5]] {
+; CGSCC-NEXT: store i32 42, i32* @bytes1, align 4
+; CGSCC-NEXT: [[L:%.*]] = load i8, i8* bitcast (i32* @bytes1 to i8*), align 4
+; CGSCC-NEXT: ret i8 [[L]]
+;
store i32 42, i32* @bytes1
%bc = bitcast i32* @bytes1 to i8*
%l = load i8, i8* %bc
}
define i64 @cast_and_load_2() {
-; CGSCC: Function Attrs: nofree norecurse nosync nounwind willreturn
-; CGSCC-LABEL: define {{[^@]+}}@cast_and_load_2
-; CGSCC-SAME: () #[[ATTR5]] {
-; CGSCC-NEXT: store i32 42, i32* @bytes2, align 4
-; CGSCC-NEXT: [[L:%.*]] = load i64, i64* bitcast (i32* @bytes2 to i64*), align 4
-; CGSCC-NEXT: ret i64 [[L]]
-;
; TUNIT: Function Attrs: nofree norecurse nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@cast_and_load_2
; TUNIT-SAME: () #[[ATTR3]] {
; TUNIT-NEXT: [[L:%.*]] = load i64, i64* bitcast (i32* @bytes2 to i64*), align 4
; TUNIT-NEXT: ret i64 [[L]]
;
+; CGSCC: Function Attrs: nofree norecurse nosync nounwind willreturn
+; CGSCC-LABEL: define {{[^@]+}}@cast_and_load_2
+; CGSCC-SAME: () #[[ATTR5]] {
+; CGSCC-NEXT: store i32 42, i32* @bytes2, align 4
+; CGSCC-NEXT: [[L:%.*]] = load i64, i64* bitcast (i32* @bytes2 to i64*), align 4
+; CGSCC-NEXT: ret i64 [[L]]
+;
store i32 42, i32* @bytes2
%bc = bitcast i32* @bytes2 to i64*
%l = load i64, i64* %bc
define void @scope_value_traversal_helper(i32* %a, i1 %c) {
; TUNIT: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@scope_value_traversal_helper
-; TUNIT-SAME: (i32* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A:%.*]], i1 [[C:%.*]]) #[[ATTR1:[0-9]+]] {
+; TUNIT-SAME: (i32* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A:%.*]], i1 [[C:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT: [[L:%.*]] = load i32, i32* [[A]], align 4
; TUNIT-NEXT: [[SEL:%.*]] = select i1 [[C]], i32 [[L]], i32 42
; TUNIT-NEXT: store i32 [[SEL]], i32* [[A]], align 4
; TUNIT: [[META4:![0-9]+]] = !{!"int", !5, i64 0}
; TUNIT: [[META5:![0-9]+]] = !{!"omnipotent char", !6, i64 0}
; TUNIT: [[META6:![0-9]+]] = !{!"Simple C/C++ TBAA"}
-; TUNIT: [[META7:![0-9]+]] = !{!8, !9, i64 12}
+; TUNIT: [[TBAA7]] = !{!8, !9, i64 12}
; TUNIT: [[META8:![0-9]+]] = !{!"S", !4, i64 0, !4, i64 4, !4, i64 8, !9, i64 12, !9, i64 16, !9, i64 20}
; TUNIT: [[META9:![0-9]+]] = !{!"float", !5, i64 0}
-; TUNIT: [[META10:![0-9]+]] = !{!8, !9, i64 16}
-; TUNIT: [[META11:![0-9]+]] = !{!8, !9, i64 20}
-; TUNIT: [[META12:![0-9]+]] = !{!8, !4, i64 0}
-; TUNIT: [[META13:![0-9]+]] = !{!8, !4, i64 4}
-; TUNIT: [[META14:![0-9]+]] = !{!8, !4, i64 8}
-; TUNIT: [[META15:![0-9]+]] = distinct !{!15, !16}
+; TUNIT: [[TBAA10]] = !{!8, !9, i64 16}
+; TUNIT: [[TBAA11]] = !{!8, !9, i64 20}
+; TUNIT: [[TBAA12]] = !{!8, !4, i64 0}
+; TUNIT: [[TBAA13]] = !{!8, !4, i64 4}
+; TUNIT: [[TBAA14]] = !{!8, !4, i64 8}
+; TUNIT: [[LOOP15]] = distinct !{!15, !16}
; TUNIT: [[META16:![0-9]+]] = !{!"llvm.loop.mustprogress"}
-; TUNIT: [[META17:![0-9]+]] = distinct !{!17, !16}
-; TUNIT: [[META18:![0-9]+]] = distinct !{!18, !16}
-; TUNIT: [[META19:![0-9]+]] = !{!5, !5, i64 0}
-; TUNIT: [[META20:![0-9]+]] = distinct !{!20, !16}
-; TUNIT: [[META21:![0-9]+]] = distinct !{!21, !16}
-; TUNIT: [[META22:![0-9]+]] = distinct !{!22, !16}
-; TUNIT: [[META23:![0-9]+]] = distinct !{!23, !16}
-; TUNIT: [[META24:![0-9]+]] = distinct !{!24, !16}
-; TUNIT: [[META25:![0-9]+]] = distinct !{!25, !16}
-; TUNIT: [[META26:![0-9]+]] = !{!9, !9, i64 0}
-; TUNIT: [[META27:![0-9]+]] = distinct !{!27, !16}
-; TUNIT: [[META28:![0-9]+]] = !{!29, !29, i64 0}
+; TUNIT: [[LOOP17]] = distinct !{!17, !16}
+; TUNIT: [[LOOP18]] = distinct !{!18, !16}
+; TUNIT: [[TBAA19]] = !{!5, !5, i64 0}
+; TUNIT: [[LOOP20]] = distinct !{!20, !16}
+; TUNIT: [[LOOP21]] = distinct !{!21, !16}
+; TUNIT: [[LOOP22]] = distinct !{!22, !16}
+; TUNIT: [[LOOP23]] = distinct !{!23, !16}
+; TUNIT: [[LOOP24]] = distinct !{!24, !16}
+; TUNIT: [[LOOP25]] = distinct !{!25, !16}
+; TUNIT: [[TBAA26]] = !{!9, !9, i64 0}
+; TUNIT: [[LOOP27]] = distinct !{!27, !16}
+; TUNIT: [[TBAA28]] = !{!29, !29, i64 0}
; TUNIT: [[META29:![0-9]+]] = !{!"long long", !5, i64 0}
-; TUNIT: [[META30:![0-9]+]] = distinct !{!30, !16}
-; TUNIT: [[META31:![0-9]+]] = distinct !{!31, !16}
+; TUNIT: [[LOOP30]] = distinct !{!30, !16}
+; TUNIT: [[LOOP31]] = distinct !{!31, !16}
;.
; CGSCC: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
; CGSCC: [[META1:![0-9]+]] = !{i32 7, !"uwtable", i32 1}
; CGSCC: [[META4:![0-9]+]] = !{!"int", !5, i64 0}
; CGSCC: [[META5:![0-9]+]] = !{!"omnipotent char", !6, i64 0}
; CGSCC: [[META6:![0-9]+]] = !{!"Simple C/C++ TBAA"}
-; CGSCC: [[META7:![0-9]+]] = !{!8, !9, i64 12}
+; CGSCC: [[TBAA7]] = !{!8, !9, i64 12}
; CGSCC: [[META8:![0-9]+]] = !{!"S", !4, i64 0, !4, i64 4, !4, i64 8, !9, i64 12, !9, i64 16, !9, i64 20}
; CGSCC: [[META9:![0-9]+]] = !{!"float", !5, i64 0}
-; CGSCC: [[META10:![0-9]+]] = !{!8, !9, i64 16}
-; CGSCC: [[META11:![0-9]+]] = !{!8, !9, i64 20}
-; CGSCC: [[META12:![0-9]+]] = !{!8, !4, i64 0}
-; CGSCC: [[META13:![0-9]+]] = !{!8, !4, i64 4}
-; CGSCC: [[META14:![0-9]+]] = !{!8, !4, i64 8}
-; CGSCC: [[META15:![0-9]+]] = !{!5, !5, i64 0}
-; CGSCC: [[META16:![0-9]+]] = distinct !{!16, !17}
+; CGSCC: [[TBAA10]] = !{!8, !9, i64 16}
+; CGSCC: [[TBAA11]] = !{!8, !9, i64 20}
+; CGSCC: [[TBAA12]] = !{!8, !4, i64 0}
+; CGSCC: [[TBAA13]] = !{!8, !4, i64 4}
+; CGSCC: [[TBAA14]] = !{!8, !4, i64 8}
+; CGSCC: [[TBAA15]] = !{!5, !5, i64 0}
+; CGSCC: [[LOOP16]] = distinct !{!16, !17}
; CGSCC: [[META17:![0-9]+]] = !{!"llvm.loop.mustprogress"}
-; CGSCC: [[META18:![0-9]+]] = !{!9, !9, i64 0}
-; CGSCC: [[META19:![0-9]+]] = distinct !{!19, !17}
-; CGSCC: [[META20:![0-9]+]] = !{!21, !21, i64 0}
+; CGSCC: [[TBAA18]] = !{!9, !9, i64 0}
+; CGSCC: [[LOOP19]] = distinct !{!19, !17}
+; CGSCC: [[TBAA20]] = !{!21, !21, i64 0}
; CGSCC: [[META21:![0-9]+]] = !{!"long long", !5, i64 0}
-; CGSCC: [[META22:![0-9]+]] = distinct !{!22, !17}
-; CGSCC: [[META23:![0-9]+]] = distinct !{!23, !17}
-; CGSCC: [[META24:![0-9]+]] = distinct !{!24, !17}
-; CGSCC: [[META25:![0-9]+]] = distinct !{!25, !17}
-; CGSCC: [[META26:![0-9]+]] = distinct !{!26, !17}
-; CGSCC: [[META27:![0-9]+]] = distinct !{!27, !17}
-; CGSCC: [[META28:![0-9]+]] = distinct !{!28, !17}
-; CGSCC: [[META29:![0-9]+]] = distinct !{!29, !17}
-; CGSCC: [[META30:![0-9]+]] = distinct !{!30, !17}
-; CGSCC: [[META31:![0-9]+]] = distinct !{!31, !17}
+; CGSCC: [[LOOP22]] = distinct !{!22, !17}
+; CGSCC: [[LOOP23]] = distinct !{!23, !17}
+; CGSCC: [[LOOP24]] = distinct !{!24, !17}
+; CGSCC: [[LOOP25]] = distinct !{!25, !17}
+; CGSCC: [[LOOP26]] = distinct !{!26, !17}
+; CGSCC: [[LOOP27]] = distinct !{!27, !17}
+; CGSCC: [[LOOP28]] = distinct !{!28, !17}
+; CGSCC: [[LOOP29]] = distinct !{!29, !17}
+; CGSCC: [[LOOP30]] = distinct !{!30, !17}
+; CGSCC: [[LOOP31]] = distinct !{!31, !17}
;.
; CHECK: store i64 1, i64* [[ADDR2]]
; CHECK: tail call void @some_may_write(i64* nonnull %proj.1)
; CHECK: [[TASK:%.*]] = bitcast %async.task* %task to i8*
-; CHECK: [[CALLEE_CTXT:%.*]] = tail call i8* @llvm.coro.async.context.alloc(i8* [[TASK]], i8* bitcast (<{ i32, i32 }>* @my_other_async_function_fp to i8*))
+; CHECK: [[CALLEE_CTXT:%.*]] = tail call i8* @llvm.coro.async.context.alloc(i8* [[TASK]], i8* nonnull bitcast (<{ i32, i32 }>* @my_other_async_function_fp to i8*))
; CHECK: [[CALLEE_CTXT_SPILL:%.*]] = getelementptr inbounds i8, i8* %async.ctxt, i64 160
; CHECK: [[CAST2:%.*]] = bitcast i8* [[CALLEE_CTXT_SPILL]] to i8**
; CHECK: store i8* [[CALLEE_CTXT]], i8** [[CAST2]]
; expect this test case to stop after one round of inlining with a final
; argument of '1'.
; CHECK-NOT: call
-; CHECK: call void @test1_b(i8* bitcast (void (i8*, i1, i32)* @test1_b to i8*), i1 false, i32 1)
+; CHECK: call void @test1_b(i8* nonnull bitcast (void (i8*, i1, i32)* @test1_b to i8*), i1 false, i32 1)
; CHECK-NOT: call
ret void
; break the cycle by inspecting the last paramater that gets incremented with
; each inlined function body.
; CHECK-NOT: call
-; CHECK: call void @test2_b(i8* bitcast (void (i8*, i8*, i1, i32)* @test2_b to i8*), i8* bitcast (void (i8*, i8*, i1, i32)* @test2_c to i8*), i1 false, i32 2)
+; CHECK: call void @test2_b(i8* nonnull bitcast (void (i8*, i8*, i1, i32)* @test2_b to i8*), i8* nonnull bitcast (void (i8*, i8*, i1, i32)* @test2_c to i8*), i1 false, i32 2)
; CHECK-NOT: call
ret void
}
; CHECK-NEXT: [[M:%.*]] = alloca i64, align 8
; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[A:%.*]], align 32
; CHECK-NEXT: [[LOADRES:%.*]] = load i32, i32* [[B:%.*]], align 4
-; CHECK-NEXT: [[LOADRES2:%.*]] = call i32 @llvm.annotation.i32(i32 [[LOADRES]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i64 0, i64 0), i32 2)
+; CHECK-NEXT: [[LOADRES2:%.*]] = call i32 @llvm.annotation.i32(i32 [[LOADRES]], i8* nonnull getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i8* nonnull getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i64 0, i64 0), i32 2)
; CHECK-NEXT: store i32 [[LOADRES2]], i32* [[A]], align 32
; CHECK-NEXT: [[DUMMY_EQ:%.*]] = icmp ugt i32 [[LOADRES]], 42
; CHECK-NEXT: tail call void @llvm.assume(i1 [[DUMMY_EQ]])
; CHECK-NEXT: [[M_I8:%.*]] = bitcast i64* [[M]] to i8*
-; CHECK-NEXT: [[M_A:%.*]] = call i8* @llvm.ptr.annotation.p0i8(i8* nonnull [[M_I8]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i64 0, i64 0), i32 2, i8* null)
+; CHECK-NEXT: [[M_A:%.*]] = call i8* @llvm.ptr.annotation.p0i8(i8* nonnull [[M_I8]], i8* nonnull getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i8* nonnull getelementptr inbounds ([4 x i8], [4 x i8]* @.str1, i64 0, i64 0), i32 2, i8* null)
; CHECK-NEXT: [[M_X:%.*]] = bitcast i8* [[M_A]] to i64*
; CHECK-NEXT: [[OBJSZ:%.*]] = call i64 @llvm.objectsize.i64.p0i8(i8* [[C:%.*]], i1 false, i1 false, i1 false)
; CHECK-NEXT: store i64 [[OBJSZ]], i64* [[M_X]], align 4
define noalias i8* @strdup_constant_str() {
; CHECK-LABEL: @strdup_constant_str(
-; CHECK-NEXT: [[CALL:%.*]] = tail call noalias dereferenceable_or_null(6) i8* @strdup(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str, i64 0, i64 0))
+; CHECK-NEXT: [[CALL:%.*]] = tail call noalias dereferenceable_or_null(6) i8* @strdup(i8* nonnull getelementptr inbounds ([6 x i8], [6 x i8]* @.str, i64 0, i64 0))
; CHECK-NEXT: ret i8* [[CALL]]
;
%call = tail call noalias i8* @strdup(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str, i64 0, i64 0))
; Check that a memmove from a global constant is converted into a memcpy
define void @test_memmove_to_memcpy(i8* %dest) {
; CHECK-LABEL: @test_memmove_to_memcpy(
-; CHECK-NEXT: call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 1 [[DEST:%.*]], i8* align 16 getelementptr inbounds ([32 x i8], [32 x i8]* @gconst, i64 0, i64 0), i32 32, i32 1)
+; CHECK-NEXT: call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 1 [[DEST:%.*]], i8* nonnull align 16 getelementptr inbounds ([32 x i8], [32 x i8]* @gconst, i64 0, i64 0), i32 32, i32 1)
; CHECK-NEXT: ret void
;
call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i32(i8* align 1 %dest, i8* align 1 getelementptr inbounds ([32 x i8], [32 x i8]* @gconst, i64 0, i64 0), i32 32, i32 1)
%call = tail call i32 (%struct._IO_FILE*, i8*, ...) @fprintf(%struct._IO_FILE* %0, i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str, i64 0, i64 0), i32 %a) #1
br label %return
-; CHECK: %call = tail call i32 (%struct._IO_FILE*, i8*, ...) @fprintf(%struct._IO_FILE* %0, i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str, i64 0, i64 0), i32 %a) #[[$AT1:[0-9]+]]
+; CHECK: %call = tail call i32 (%struct._IO_FILE*, i8*, ...) @fprintf(%struct._IO_FILE* %0, i8* nonnull getelementptr inbounds ([13 x i8], [13 x i8]* @.str, i64 0, i64 0), i32 %a) #[[$AT1:[0-9]+]]
return: ; preds = %entry, %if.then
%retval.0 = phi i32 [ 1, %if.then ], [ 0, %entry ]
%1 = tail call i64 @fwrite(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str1, i64 0, i64 0), i64 8, i64 1, %struct._IO_FILE* %0)
br label %return
-; CHECK: tail call i64 @fwrite(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str1, i64 0, i64 0), i64 8, i64 1, %struct._IO_FILE* %0) #[[$AT2:[0-9]+]]
+; CHECK: tail call i64 @fwrite(i8* nonnull getelementptr inbounds ([9 x i8], [9 x i8]* @.str1, i64 0, i64 0), i64 8, i64 1, %struct._IO_FILE* %0) #[[$AT2:[0-9]+]]
return: ; preds = %entry, %if.then
%retval.0 = phi i32 [ 1, %if.then ], [ 0, %entry ]
define i8* @test_memccpy() {
; CHECK-LABEL: @test_memccpy(
-; CHECK-NEXT: [[MEMCCPY:%.*]] = call i8* @memccpy(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i32 0, i64 60)
+; CHECK-NEXT: [[MEMCCPY:%.*]] = call i8* @memccpy(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i32 0, i64 60)
; CHECK-NEXT: ret i8* [[MEMCCPY]]
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
define i8* @test_not_memccpy() {
; CHECK-LABEL: @test_not_memccpy(
-; CHECK-NEXT: [[RET:%.*]] = call i8* @__memccpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i32 0, i64 60, i64 59)
+; CHECK-NEXT: [[RET:%.*]] = call i8* @__memccpy_chk(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i32 0, i64 60, i64 59)
; CHECK-NEXT: ret i8* [[RET]]
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
define i8* @test_memccpy_tail() {
; CHECK-LABEL: @test_memccpy_tail(
-; CHECK-NEXT: [[MEMCCPY:%.*]] = tail call i8* @memccpy(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i32 0, i64 60)
+; CHECK-NEXT: [[MEMCCPY:%.*]] = tail call i8* @memccpy(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i32 0, i64 60)
; CHECK-NEXT: ret i8* [[MEMCCPY]]
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
define i8* @test_not_mempcpy() {
; CHECK-LABEL: @test_not_mempcpy(
-; CHECK-NEXT: [[RET:%.*]] = call i8* @__mempcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 60, i64 59)
+; CHECK-NEXT: [[RET:%.*]] = call i8* @__mempcpy_chk(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 60, i64 59)
; CHECK-NEXT: ret i8* [[RET]]
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
define i8* @test_mempcpy_tail() {
; CHECK-LABEL: @test_mempcpy_tail(
-; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noundef nonnull align 1 dereferenceable(15) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* noundef nonnull align 1 dereferenceable(15) getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 15, i1 false)
+; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* noundef nonnull align 1 dereferenceable(15) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* noundef nonnull align 1 dereferenceable(15) getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 15, i1 false)
; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 15)
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
define i32 @test_snprintf() {
; CHECK-LABEL: @test_snprintf(
-; CHECK-NEXT: [[SNPRINTF:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* nonnull dereferenceable(1) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 60, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0))
+; CHECK-NEXT: [[SNPRINTF:%.*]] = call i32 (i8*, i64, i8*, ...) @snprintf(i8* nonnull dereferenceable(1) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 60, i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0))
; CHECK-NEXT: ret i32 [[SNPRINTF]]
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
define i32 @test_not_snprintf() {
; CHECK-LABEL: @test_not_snprintf(
-; CHECK-NEXT: [[RET:%.*]] = call i32 (i8*, i64, i32, i64, i8*, ...) @__snprintf_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 60, i32 0, i64 59, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0))
-; CHECK-NEXT: [[IGN:%.*]] = call i32 (i8*, i64, i32, i64, i8*, ...) @__snprintf_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 60, i32 1, i64 -1, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0))
+; CHECK-NEXT: [[RET:%.*]] = call i32 (i8*, i64, i32, i64, i8*, ...) @__snprintf_chk(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 60, i32 0, i64 59, i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0))
+; CHECK-NEXT: [[IGN:%.*]] = call i32 (i8*, i64, i32, i64, i8*, ...) @__snprintf_chk(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 60, i32 1, i64 -1, i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0))
; CHECK-NEXT: ret i32 [[RET]]
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
define i32 @test_snprintf_tail() {
; CHECK-LABEL: @test_snprintf_tail(
-; CHECK-NEXT: [[SNPRINTF:%.*]] = tail call i32 (i8*, i64, i8*, ...) @snprintf(i8* nonnull dereferenceable(1) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 60, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0))
+; CHECK-NEXT: [[SNPRINTF:%.*]] = tail call i32 (i8*, i64, i8*, ...) @snprintf(i8* nonnull dereferenceable(1) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 60, i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0))
; CHECK-NEXT: ret i32 [[SNPRINTF]]
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
define i32 @test_not_sprintf() {
; CHECK-LABEL: @test_not_sprintf(
-; CHECK-NEXT: [[RET:%.*]] = call i32 (i8*, i32, i64, i8*, ...) @__sprintf_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i32 0, i64 59, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0))
-; CHECK-NEXT: [[IGNORED:%.*]] = call i32 (i8*, i32, i64, i8*, ...) @__sprintf_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i32 1, i64 -1, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0))
+; CHECK-NEXT: [[RET:%.*]] = call i32 (i8*, i32, i64, i8*, ...) @__sprintf_chk(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i32 0, i64 59, i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0))
+; CHECK-NEXT: [[IGNORED:%.*]] = call i32 (i8*, i32, i64, i8*, ...) @__sprintf_chk(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i32 1, i64 -1, i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0))
; CHECK-NEXT: ret i32 [[RET]]
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
define i8* @test_not_strcat() {
; CHECK-LABEL: @test_not_strcat(
-; CHECK-NEXT: [[RET:%.*]] = call i8* @__strcat_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 0)
+; CHECK-NEXT: [[RET:%.*]] = call i8* @__strcat_chk(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 0)
; CHECK-NEXT: ret i8* [[RET]]
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
define i64 @test_strlcat() {
; CHECK-LABEL: @test_strlcat(
-; CHECK-NEXT: [[STRLCAT:%.*]] = call i64 @strlcat(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 22)
+; CHECK-NEXT: [[STRLCAT:%.*]] = call i64 @strlcat(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 22)
; CHECK-NEXT: ret i64 [[STRLCAT]]
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
define i64 @test_not_strlcat() {
; CHECK-LABEL: @test_not_strlcat(
-; CHECK-NEXT: [[RET:%.*]] = call i64 @__strlcat_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 22, i64 0)
+; CHECK-NEXT: [[RET:%.*]] = call i64 @__strlcat_chk(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 22, i64 0)
; CHECK-NEXT: ret i64 [[RET]]
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
define i64 @test_strlcat_tail() {
; CHECK-LABEL: @test_strlcat_tail(
-; CHECK-NEXT: [[STRLCAT:%.*]] = tail call i64 @strlcat(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 22)
+; CHECK-NEXT: [[STRLCAT:%.*]] = tail call i64 @strlcat(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 22)
; CHECK-NEXT: ret i64 [[STRLCAT]]
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
define i8* @test_not_strncat() {
; CHECK-LABEL: @test_not_strncat(
-; CHECK-NEXT: [[RET:%.*]] = call i8* @__strncat_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 22, i64 3)
+; CHECK-NEXT: [[RET:%.*]] = call i8* @__strncat_chk(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 22, i64 3)
; CHECK-NEXT: ret i8* [[RET]]
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
define i64 @test_not_strlcpy() {
; CHECK-LABEL: @test_not_strlcpy(
-; CHECK-NEXT: [[RET:%.*]] = call i64 @__strlcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 22, i64 2)
+; CHECK-NEXT: [[RET:%.*]] = call i64 @__strlcpy_chk(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), i64 22, i64 2)
; CHECK-NEXT: ret i64 [[RET]]
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
define i32 @test_vsnprintf() {
; CHECK-LABEL: @test_vsnprintf(
-; CHECK-NEXT: [[VSNPRINTF:%.*]] = call i32 @vsnprintf(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 4, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null)
+; CHECK-NEXT: [[VSNPRINTF:%.*]] = call i32 @vsnprintf(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 4, i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null)
; CHECK-NEXT: ret i32 [[VSNPRINTF]]
;
; ret i32
define i32 @test_not_vsnprintf() {
; CHECK-LABEL: @test_not_vsnprintf(
-; CHECK-NEXT: [[RET:%.*]] = call i32 @__vsnprintf_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 4, i32 0, i64 3, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null)
-; CHECK-NEXT: [[IGN:%.*]] = call i32 @__vsnprintf_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 4, i32 1, i64 -1, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null)
+; CHECK-NEXT: [[RET:%.*]] = call i32 @__vsnprintf_chk(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 4, i32 0, i64 3, i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null)
+; CHECK-NEXT: [[IGN:%.*]] = call i32 @__vsnprintf_chk(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 4, i32 1, i64 -1, i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null)
; CHECK-NEXT: ret i32 [[RET]]
;
; ret i32
define i32 @test_vsnprintf_tail() {
; CHECK-LABEL: @test_vsnprintf_tail(
-; CHECK-NEXT: [[VSNPRINTF:%.*]] = tail call i32 @vsnprintf(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 4, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null)
+; CHECK-NEXT: [[VSNPRINTF:%.*]] = tail call i32 @vsnprintf(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i64 4, i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null)
; CHECK-NEXT: ret i32 [[VSNPRINTF]]
;
; ret i32
define i32 @test_vsprintf() {
; CHECK-LABEL: @test_vsprintf(
-; CHECK-NEXT: [[VSPRINTF:%.*]] = call i32 @vsprintf(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null)
+; CHECK-NEXT: [[VSPRINTF:%.*]] = call i32 @vsprintf(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null)
; CHECK-NEXT: ret i32 [[VSPRINTF]]
;
; ret i32
define i32 @test_not_vsprintf() {
; CHECK-LABEL: @test_not_vsprintf(
-; CHECK-NEXT: [[RET:%.*]] = call i32 @__vsprintf_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i32 0, i64 3, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null)
-; CHECK-NEXT: [[IGN:%.*]] = call i32 @__vsprintf_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i32 1, i64 -1, i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null)
+; CHECK-NEXT: [[RET:%.*]] = call i32 @__vsprintf_chk(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i32 0, i64 3, i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null)
+; CHECK-NEXT: [[IGN:%.*]] = call i32 @__vsprintf_chk(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i32 1, i64 -1, i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null)
; CHECK-NEXT: ret i32 [[RET]]
;
; ret i32
define i32 @test_vsprintf_tail() {
; CHECK-LABEL: @test_vsprintf_tail(
-; CHECK-NEXT: [[VSPRINTF:%.*]] = tail call i32 @vsprintf(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null)
+; CHECK-NEXT: [[VSPRINTF:%.*]] = tail call i32 @vsprintf(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i64 0, i64 0), i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i64 0, i64 0), %struct.__va_list_tag* null)
; CHECK-NEXT: ret i32 [[VSPRINTF]]
;
; ret i32
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; Test that the fputs library call simplifier works correctly.
;
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
define void @test_simplify1(%FILE* %fp) {
; CHECK-LABEL: @test_simplify1(
+; CHECK-NEXT: ret void
+;
%str = getelementptr [1 x i8], [1 x i8]* @empty, i32 0, i32 0
call i32 @fputs(i8* %str, %FILE* %fp)
ret void
-; CHECK-NEXT: ret void
}
; NOTE: The fwrite simplifier simplifies this further to fputc.
define void @test_simplify2(%FILE* %fp) {
; CHECK-LABEL: @test_simplify2(
+; CHECK-NEXT: [[FPUTC:%.*]] = call i32 @fputc(i32 65, %FILE* [[FP:%.*]])
+; CHECK-NEXT: ret void
+;
%str = getelementptr [2 x i8], [2 x i8]* @A, i32 0, i32 0
call i32 @fputs(i8* %str, %FILE* %fp)
-; CHECK-NEXT: call i32 @fputc(i32 65, %FILE* %fp)
ret void
-; CHECK-NEXT: ret void
}
define void @test_simplify3(%FILE* %fp) {
; CHECK-LABEL: @test_simplify3(
+; CHECK-NEXT: [[TMP1:%.*]] = call i32 @fwrite(i8* nonnull getelementptr inbounds ([7 x i8], [7 x i8]* @hello, i32 0, i32 0), i32 6, i32 1, %FILE* [[FP:%.*]])
+; CHECK-NEXT: ret void
+;
%str = getelementptr [7 x i8], [7 x i8]* @hello, i32 0, i32 0
call i32 @fputs(i8* %str, %FILE* %fp)
-; CHECK-NEXT: call i32 @fwrite(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @hello, i32 0, i32 0), i32 6, i32 1, %FILE* %fp)
ret void
-; CHECK-NEXT: ret void
}
; CHECK-NEXT: [[CMP23:%.*]] = icmp eq i8 [[TMP1]], 54
; CHECK-NEXT: br i1 [[CMP23]], label [[WHILE_COND:%.*]], label [[IF_THEN_25:%.*]]
; CHECK: if.then.25:
-; CHECK-NEXT: call void @g(i8* getelementptr inbounds ([100 x i8], [100 x i8]* @.str.4, i64 0, i64 0))
+; CHECK-NEXT: call void @g(i8* nonnull getelementptr inbounds ([100 x i8], [100 x i8]* @.str.4, i64 0, i64 0))
; CHECK-NEXT: br label [[WHILE_COND]]
; CHECK: while.cond:
; CHECK-NEXT: [[PTR:%.*]] = phi i8* [ [[INCDEC_PTR]], [[ENTRY:%.*]] ], [ [[INCDEC_PTR32:%.*]], [[WHILE_BODY:%.*]] ], [ [[INCDEC_PTR]], [[IF_THEN_25]] ]
; CHECK-NEXT: [[T349:%.*]] = getelementptr [[STRUCT_SIGINFO_T:%.*]], %struct.siginfo_t* [[T344]], i64 0, i32 3, i32 0, i32 3, i32 0
; CHECK-NEXT: [[T349350:%.*]] = bitcast i8** [[T349]] to i32*
; CHECK-NEXT: [[T351:%.*]] = load i32, i32* [[T349350]], align 8
-; CHECK-NEXT: [[T360:%.*]] = call i32 asm sideeffect "...", "=r,ir,*m,i,0,~{dirflag},~{fpsr},~{flags}"(i32 [[T351]], %struct.__large_struct* elementtype(%struct.__large_struct) null, i32 -14, i32 0) #[[ATTR0:[0-9]+]]
+; CHECK-NEXT: [[T360:%.*]] = call i32 asm sideeffect "...", "=r,ir,*m,i,0,~{dirflag},~{fpsr},~{flags}"(i32 [[T351]], %struct.__large_struct* elementtype([[STRUCT___LARGE_STRUCT:%.*]]) null, i32 -14, i32 0) #[[ATTR0:[0-9]+]]
; CHECK-NEXT: unreachable
;
entry:
define i32 @test35() nounwind {
; CHECK-LABEL: @test35(
-; CHECK-NEXT: [[TMP1:%.*]] = call i32 (i8*, ...) @printf(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([17 x i8], [17 x i8]* @"\01LC8", i64 0, i64 0), i8* getelementptr inbounds ([[T0:%.*]], %t0* @s, i64 0, i32 1, i64 0)) #[[ATTR0]]
+; CHECK-NEXT: [[TMP1:%.*]] = call i32 (i8*, ...) @printf(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([17 x i8], [17 x i8]* @"\01LC8", i64 0, i64 0), i8* nonnull getelementptr inbounds ([[T0:%.*]], %t0* @s, i64 0, i32 1, i64 0)) #[[ATTR0]]
; CHECK-NEXT: ret i32 0
;
call i32 (i8*, ...) @printf(i8* getelementptr ([17 x i8], [17 x i8]* @"\01LC8", i32 0, i32 0),
define void @memccpy_to_memcpy3_tail(i8* %dst) {
; CHECK-LABEL: @memccpy_to_memcpy3_tail(
-; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noundef nonnull align 1 dereferenceable(5) [[DST:%.*]], i8* noundef nonnull align 1 dereferenceable(5) getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i64 5, i1 false)
+; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* noundef nonnull align 1 dereferenceable(5) [[DST:%.*]], i8* noundef nonnull align 1 dereferenceable(5) getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i64 5, i1 false)
; CHECK-NEXT: ret void
;
%call = tail call i8* @memccpy(i8* %dst, i8* getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i32 111, i64 10) ; 111 is 'o'
define i8* @memccpy_to_memcpy3_musttail(i8* %dst, i8* %x, i32 %y, i64 %z) {
; CHECK-LABEL: @memccpy_to_memcpy3_musttail(
-; CHECK-NEXT: %call = musttail call i8* @memccpy(i8* %dst, i8* getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i32 111, i64 10)
-; CHECK-NEXT: ret i8* %call
+; CHECK-NEXT: [[CALL:%.*]] = musttail call i8* @memccpy(i8* [[DST:%.*]], i8* nonnull getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i32 111, i64 10)
+; CHECK-NEXT: ret i8* [[CALL]]
;
%call = musttail call i8* @memccpy(i8* %dst, i8* getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i32 111, i64 10) ; 111 is 'o'
ret i8* %call
define i8* @memccpy_to_memcpy5_musttail(i8* %dst, i8* %x, i32 %y, i64 %z) {
; CHECK-LABEL: @memccpy_to_memcpy5_musttail(
-; CHECK-NEXT: %call = musttail call i8* @memccpy(i8* %dst, i8* getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i32 114, i64 7)
-; CHECK-NEXT: ret i8* %call
+; CHECK-NEXT: [[CALL:%.*]] = musttail call i8* @memccpy(i8* [[DST:%.*]], i8* nonnull getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i32 114, i64 7)
+; CHECK-NEXT: ret i8* [[CALL]]
;
%call = musttail call i8* @memccpy(i8* %dst, i8* getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i32 114, i64 7)
ret i8* %call
define i8* @unknown_stop_char(i8* %dst, i32 %c) {
; CHECK-LABEL: @unknown_stop_char(
-; CHECK-NEXT: [[CALL:%.*]] = call i8* @memccpy(i8* [[DST:%.*]], i8* getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i32 [[C:%.*]], i64 12)
+; CHECK-NEXT: [[CALL:%.*]] = call i8* @memccpy(i8* [[DST:%.*]], i8* nonnull getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i32 [[C:%.*]], i64 12)
; CHECK-NEXT: ret i8* [[CALL]]
;
%call = call i8* @memccpy(i8* %dst, i8* getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i32 %c, i64 12)
define i8* @unknown_size_n(i8* %dst, i64 %n) {
; CHECK-LABEL: @unknown_size_n(
-; CHECK-NEXT: [[CALL:%.*]] = call i8* @memccpy(i8* [[DST:%.*]], i8* getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i32 114, i64 [[N:%.*]])
+; CHECK-NEXT: [[CALL:%.*]] = call i8* @memccpy(i8* [[DST:%.*]], i8* nonnull getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i32 114, i64 [[N:%.*]])
; CHECK-NEXT: ret i8* [[CALL]]
;
%call = call i8* @memccpy(i8* %dst, i8* getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i32 114, i64 %n)
define i8* @no_nul_terminator(i8* %dst, i64 %n) {
; CHECK-LABEL: @no_nul_terminator(
-; CHECK-NEXT: [[CALL:%.*]] = call i8* @memccpy(i8* [[DST:%.*]], i8* getelementptr inbounds ([12 x i8], [12 x i8]* @StopCharAfterNulTerminator, i64 0, i64 0), i32 120, i64 [[N:%.*]])
+; CHECK-NEXT: [[CALL:%.*]] = call i8* @memccpy(i8* [[DST:%.*]], i8* nonnull getelementptr inbounds ([12 x i8], [12 x i8]* @StopCharAfterNulTerminator, i64 0, i64 0), i32 120, i64 [[N:%.*]])
; CHECK-NEXT: ret i8* [[CALL]]
;
%call = call i8* @memccpy(i8* %dst, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @StopCharAfterNulTerminator, i64 0, i64 0), i32 120, i64 %n) ; 120 is 'x'
define i8* @possibly_valid_data_after_array(i8* %dst, i64 %n) {
; CHECK-LABEL: @possibly_valid_data_after_array(
-; CHECK-NEXT: [[CALL:%.*]] = call i8* @memccpy(i8* [[DST:%.*]], i8* getelementptr inbounds ([10 x i8], [10 x i8]* @NoNulTerminator, i64 0, i64 0), i32 115, i64 [[N:%.*]])
+; CHECK-NEXT: [[CALL:%.*]] = call i8* @memccpy(i8* [[DST:%.*]], i8* nonnull getelementptr inbounds ([10 x i8], [10 x i8]* @NoNulTerminator, i64 0, i64 0), i32 115, i64 [[N:%.*]])
; CHECK-NEXT: ret i8* [[CALL]]
;
%call = call i8* @memccpy(i8* %dst, i8* getelementptr inbounds ([10 x i8], [10 x i8]* @NoNulTerminator, i64 0, i64 0), i32 115, i64 %n) ; 115 is 's'
define i8* @possibly_valid_data_after_array2(i8* %dst, i64 %n) {
; CHECK-LABEL: @possibly_valid_data_after_array2(
-; CHECK-NEXT: [[CALL:%.*]] = call i8* @memccpy(i8* [[DST:%.*]], i8* getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i32 115, i64 [[N:%.*]])
+; CHECK-NEXT: [[CALL:%.*]] = call i8* @memccpy(i8* [[DST:%.*]], i8* nonnull getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i32 115, i64 [[N:%.*]])
; CHECK-NEXT: ret i8* [[CALL]]
;
%call = call i8* @memccpy(i8* %dst, i8* getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i32 115, i64 %n) ; 115 is 's'
define i8* @possibly_valid_data_after_array3(i8* %dst) {
; CHECK-LABEL: @possibly_valid_data_after_array3(
-; CHECK-NEXT: [[CALL:%.*]] = call i8* @memccpy(i8* [[DST:%.*]], i8* getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i32 115, i64 12)
+; CHECK-NEXT: [[CALL:%.*]] = call i8* @memccpy(i8* [[DST:%.*]], i8* nonnull getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i32 115, i64 12)
; CHECK-NEXT: ret i8* [[CALL]]
;
%call = call i8* @memccpy(i8* %dst, i8* getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i32 115, i64 12) ; 115 is 's'
define i8* @memccpy_to_memcpy_musttail(i8* %dst, i8* %x, i32 %y, i64 %z) {
; CHECK-LABEL: @memccpy_to_memcpy_musttail(
-; CHECK-NEXT: %call = musttail call i8* @memccpy(i8* %dst, i8* getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i32 114, i64 12)
-; CHECK-NEXT: ret i8* %call
+; CHECK-NEXT: [[CALL:%.*]] = musttail call i8* @memccpy(i8* [[DST:%.*]], i8* nonnull getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i32 114, i64 12)
+; CHECK-NEXT: ret i8* [[CALL]]
;
%call = musttail call i8* @memccpy(i8* %dst, i8* getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i32 114, i64 12) ; 114 is 'r'
ret i8* %call
define i8* @memccpy_to_memcpy2_musttail(i8* %dst, i8* %x, i32 %y, i64 %z) {
; CHECK-LABEL: @memccpy_to_memcpy2_musttail(
-; CHECK-NEXT: %call = musttail call i8* @memccpy(i8* %dst, i8* getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i32 114, i64 8)
-; CHECK-NEXT: ret i8* %call
+; CHECK-NEXT: [[CALL:%.*]] = musttail call i8* @memccpy(i8* [[DST:%.*]], i8* nonnull getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i32 114, i64 8)
+; CHECK-NEXT: ret i8* [[CALL]]
;
%call = musttail call i8* @memccpy(i8* %dst, i8* getelementptr inbounds ([11 x i8], [11 x i8]* @hello, i64 0, i64 0), i32 114, i64 8) ; 114 is 'r'
ret i8* %call
define void @call_memcmp_a_ax_n(i32* %pcmp, i64 %n) {
; CHECK-LABEL: @call_memcmp_a_ax_n(
-; CHECK-NEXT: [[C0_0:%.*]] = call i32 @memcmp(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @a01230123, i64 0, i64 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @ax, i64 0, i64 0), i64 [[N:%.*]])
+; CHECK-NEXT: [[C0_0:%.*]] = call i32 @memcmp(i8* nonnull getelementptr inbounds ([8 x i8], [8 x i8]* @a01230123, i64 0, i64 0), i8* nonnull getelementptr inbounds ([8 x i8], [8 x i8]* @ax, i64 0, i64 0), i64 [[N:%.*]])
; CHECK-NEXT: store i32 [[C0_0]], i32* [[PCMP:%.*]], align 4
; CHECK-NEXT: ret void
;
; CHECK-LABEL: @fold_memcmp_a5pi_a5p5_n(
; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[I:%.*]] to i64
; CHECK-NEXT: [[PA5_PI:%.*]] = getelementptr [5 x i8], ptr @a5, i64 0, i64 [[TMP1]]
-; CHECK-NEXT: [[CMP:%.*]] = call i32 @memcmp(ptr [[PA5_PI]], ptr getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0), i64 [[N:%.*]])
+; CHECK-NEXT: [[CMP:%.*]] = call i32 @memcmp(ptr [[PA5_PI]], ptr nonnull getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0), i64 [[N:%.*]])
; CHECK-NEXT: ret i32 [[CMP]]
;
%pa5_pi = getelementptr [5 x i8], ptr @a5, i32 0, i32 %i
; CHECK-LABEL: @test2(
; CHECK-NEXT: [[B1:%.*]] = alloca [124 x i8], align 8
; CHECK-NEXT: [[B1_SUB:%.*]] = getelementptr inbounds [124 x i8], [124 x i8]* [[B1]], i64 0, i64 0
-; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noundef nonnull align 8 dereferenceable(124) [[B1_SUB]], i8* noundef nonnull align 16 dereferenceable(124) getelementptr inbounds (%T, %T* @G, i64 0, i32 0), i64 124, i1 false)
+; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noundef nonnull align 8 dereferenceable(124) [[B1_SUB]], i8* noundef nonnull align 16 dereferenceable(124) getelementptr inbounds ([[T:%.*]], %T* @G, i64 0, i32 0), i64 124, i1 false)
; CHECK-NEXT: call void @bar(i8* nonnull [[B1_SUB]])
; CHECK-NEXT: ret void
;
; CHECK-LABEL: @test2_no_null_opt(
; CHECK-NEXT: [[B1:%.*]] = alloca [124 x i8], align 8
; CHECK-NEXT: [[B1_SUB:%.*]] = getelementptr inbounds [124 x i8], [124 x i8]* [[B1]], i64 0, i64 0
-; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noundef align 8 dereferenceable(124) [[B1_SUB]], i8* noundef align 16 dereferenceable(124) getelementptr inbounds (%T, %T* @G, i64 0, i32 0), i64 124, i1 false)
+; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noundef align 8 dereferenceable(124) [[B1_SUB]], i8* noundef nonnull align 16 dereferenceable(124) getelementptr inbounds ([[T:%.*]], %T* @G, i64 0, i32 0), i64 124, i1 false)
; CHECK-NEXT: call void @bar(i8* [[B1_SUB]])
; CHECK-NEXT: ret void
;
; CHECK-NEXT: [[B1:%.*]] = alloca [124 x i8], align 8
; CHECK-NEXT: [[B1_SUB:%.*]] = getelementptr inbounds [124 x i8], [124 x i8]* [[B1]], i64 0, i64 0
; CHECK-NEXT: [[B:%.*]] = addrspacecast i8* [[B1_SUB]] to i8 addrspace(1)*
-; CHECK-NEXT: call void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* noundef align 4 dereferenceable(124) [[B]], i8 addrspace(1)* noundef align 4 dereferenceable(124) addrspacecast (i8* getelementptr inbounds (%T, %T* @G, i64 0, i32 0) to i8 addrspace(1)*), i64 124, i1 false)
+; CHECK-NEXT: call void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* noundef align 4 dereferenceable(124) [[B]], i8 addrspace(1)* noundef align 4 dereferenceable(124) addrspacecast (i8* getelementptr inbounds ([[T:%.*]], %T* @G, i64 0, i32 0) to i8 addrspace(1)*), i64 124, i1 false)
; CHECK-NEXT: call void @bar_as1(i8 addrspace(1)* [[B]])
; CHECK-NEXT: ret void
;
;; Should be able to eliminate the alloca.
define void @test3() {
; CHECK-LABEL: @test3(
-; CHECK-NEXT: call void @bar(i8* getelementptr inbounds (%T, %T* @G, i64 0, i32 0)) [[ATTR2:#.*]]
+; CHECK-NEXT: call void @bar(i8* nonnull getelementptr inbounds ([[T:%.*]], %T* @G, i64 0, i32 0)) #[[ATTR3:[0-9]+]]
; CHECK-NEXT: ret void
;
%A = alloca %T
define void @test3_addrspacecast() {
; CHECK-LABEL: @test3_addrspacecast(
-; CHECK-NEXT: call void @bar(i8* getelementptr inbounds (%T, %T* @G, i64 0, i32 0)) [[ATTR2]]
+; CHECK-NEXT: call void @bar(i8* nonnull getelementptr inbounds ([[T:%.*]], %T* @G, i64 0, i32 0)) #[[ATTR3]]
; CHECK-NEXT: ret void
;
%A = alloca %T
define void @test4() {
; CHECK-LABEL: @test4(
-; CHECK-NEXT: call void @baz(i8* byval(i8) getelementptr inbounds (%T, %T* @G, i64 0, i32 0))
+; CHECK-NEXT: call void @baz(i8* nonnull byval(i8) getelementptr inbounds ([[T:%.*]], %T* @G, i64 0, i32 0))
; CHECK-NEXT: ret void
;
%A = alloca %T
declare void @llvm.lifetime.start.p0i8(i64, i8*)
define void @test5() {
; CHECK-LABEL: @test5(
-; CHECK-NEXT: call void @baz(i8* byval(i8) getelementptr inbounds (%T, %T* @G, i64 0, i32 0))
+; CHECK-NEXT: call void @baz(i8* nonnull byval(i8) getelementptr inbounds ([[T:%.*]], %T* @G, i64 0, i32 0))
; CHECK-NEXT: ret void
;
%A = alloca %T
define void @test6() {
; CHECK-LABEL: @test6(
-; CHECK-NEXT: call void @bar(i8* bitcast ([2 x %U]* @H to i8*)) [[ATTR2]]
+; CHECK-NEXT: call void @bar(i8* nonnull bitcast ([2 x %U]* @H to i8*)) #[[ATTR3]]
; CHECK-NEXT: ret void
;
%A = alloca %U, align 16
define void @test7() {
; CHECK-LABEL: @test7(
-; CHECK-NEXT: call void @bar(i8* bitcast ([2 x %U]* @H to i8*)) [[ATTR2]]
+; CHECK-NEXT: call void @bar(i8* nonnull bitcast ([2 x %U]* @H to i8*)) #[[ATTR3]]
; CHECK-NEXT: ret void
;
%A = alloca %U, align 16
; CHECK-NEXT: [[AL:%.*]] = alloca [[U:%.*]], align 16
; CHECK-NEXT: [[A:%.*]] = bitcast %U* [[AL]] to i8*
; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* noundef nonnull align 16 dereferenceable(20) [[A]], i8* noundef nonnull align 4 dereferenceable(20) bitcast (%U* getelementptr inbounds ([2 x %U], [2 x %U]* @H, i64 0, i64 1) to i8*), i64 20, i1 false)
-; CHECK-NEXT: call void @bar(i8* nonnull [[A]]) [[ATTR2]]
+; CHECK-NEXT: call void @bar(i8* nonnull [[A]]) #[[ATTR3]]
; CHECK-NEXT: ret void
;
%al = alloca %U, align 16
; CHECK-NEXT: [[AL:%.*]] = alloca [[U:%.*]], align 16
; CHECK-NEXT: [[A:%.*]] = bitcast %U* [[AL]] to i8*
; CHECK-NEXT: call void @llvm.memcpy.p0i8.p1i8.i64(i8* noundef nonnull align 16 dereferenceable(20) [[A]], i8 addrspace(1)* noundef align 4 dereferenceable(20) addrspacecast (i8* bitcast (%U* getelementptr inbounds ([2 x %U], [2 x %U]* @H, i64 0, i64 1) to i8*) to i8 addrspace(1)*), i64 20, i1 false)
-; CHECK-NEXT: call void @bar(i8* nonnull [[A]]) [[ATTR2]]
+; CHECK-NEXT: call void @bar(i8* nonnull [[A]]) #[[ATTR3]]
; CHECK-NEXT: ret void
;
%Al = alloca %U, align 16
define void @test9() {
; CHECK-LABEL: @test9(
-; CHECK-NEXT: call void @bar(i8* bitcast (%U* getelementptr inbounds ([2 x %U], [2 x %U]* @H, i64 0, i64 1) to i8*)) [[ATTR2]]
+; CHECK-NEXT: call void @bar(i8* nonnull bitcast (%U* getelementptr inbounds ([2 x %U], [2 x %U]* @H, i64 0, i64 1) to i8*)) #[[ATTR3]]
; CHECK-NEXT: ret void
;
%A = alloca %U, align 4
define void @test9_addrspacecast() {
; CHECK-LABEL: @test9_addrspacecast(
-; CHECK-NEXT: call void @bar(i8* bitcast (%U* getelementptr inbounds ([2 x %U], [2 x %U]* @H, i64 0, i64 1) to i8*)) [[ATTR2]]
+; CHECK-NEXT: call void @bar(i8* nonnull bitcast (%U* getelementptr inbounds ([2 x %U], [2 x %U]* @H, i64 0, i64 1) to i8*)) #[[ATTR3]]
; CHECK-NEXT: ret void
;
%A = alloca %U, align 4
; Should replace alloca with global even when the global is in a different address space
define float @test11(i64 %i) {
; CHECK-LABEL: @test11(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[GEP:%.*]] = getelementptr [4 x float], [4 x float] addrspace(1)* @I, i64 0, i64 %i
-; CHECK-NEXT: [[LD:%.*]] = load float, float addrspace(1)* [[GEP]]
-; CHECK-NEXT: ret float [[LD]]
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[G:%.*]] = getelementptr [4 x float], [4 x float] addrspace(1)* @I, i64 0, i64 [[I:%.*]]
+; CHECK-NEXT: [[R:%.*]] = load float, float addrspace(1)* [[G]], align 4
+; CHECK-NEXT: ret float [[R]]
+;
entry:
%a = alloca [4 x float], align 4
; If the memcpy is volatile, it should not be removed
define float @test11_volatile(i64 %i) {
; CHECK-LABEL: @test11_volatile(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: alloca
-; CHECK: call void @llvm.lifetime.start.p0i8
-; CHECK: call void @llvm.memcpy
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[A:%.*]] = alloca [4 x float], align 4
+; CHECK-NEXT: [[B:%.*]] = bitcast [4 x float]* [[A]] to i8*
+; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 16, i8* nonnull [[B]])
+; CHECK-NEXT: call void @llvm.memcpy.p0i8.p1i8.i64(i8* align 4 [[B]], i8 addrspace(1)* align 4 bitcast ([4 x float] addrspace(1)* @I to i8 addrspace(1)*), i64 16, i1 true)
+; CHECK-NEXT: [[G:%.*]] = getelementptr inbounds [4 x float], [4 x float]* [[A]], i64 0, i64 [[I:%.*]]
+; CHECK-NEXT: [[R:%.*]] = load float, float* [[G]], align 4
+; CHECK-NEXT: ret float [[R]]
+;
entry:
%a = alloca [4 x float], align 4
define void @test2(i8* %A, i32 %N) {
;; dest can't alias source since we can't write to source!
; CHECK-LABEL: @test2(
-; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 [[A:%.*]], i8* align 16 getelementptr inbounds ([33 x i8], [33 x i8]* @S, i64 0, i64 0), i32 [[N:%.*]], i1 false)
+; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 [[A:%.*]], i8* nonnull align 16 getelementptr inbounds ([33 x i8], [33 x i8]* @S, i64 0, i64 0), i32 [[N:%.*]], i1 false)
; CHECK-NEXT: ret void
;
call void @llvm.memmove.p0i8.p0i8.i32(i8* %A, i8* getelementptr inbounds ([33 x i8], [33 x i8]* @S, i32 0, i32 0), i32 %N, i1 false)
define i8* @test_no_simplify1() {
; CHECK-LABEL: @test_no_simplify1(
-; CHECK-NEXT: [[RET:%.*]] = call i8* @__memmove_chk(i8* bitcast (%struct.T3* @t3 to i8*), i8* bitcast (%struct.T1* @t1 to i8*), i64 2848, i64 1824)
+; CHECK-NEXT: [[RET:%.*]] = call i8* @__memmove_chk(i8* nonnull bitcast (%struct.T3* @t3 to i8*), i8* nonnull bitcast (%struct.T1* @t1 to i8*), i64 2848, i64 1824)
; CHECK-NEXT: ret i8* [[RET]]
;
%dst = bitcast %struct.T3* @t3 to i8*
define i8* @test_no_simplify2() {
; CHECK-LABEL: @test_no_simplify2(
-; CHECK-NEXT: [[RET:%.*]] = call i8* @__memmove_chk(i8* bitcast (%struct.T1* @t1 to i8*), i8* bitcast (%struct.T2* @t2 to i8*), i64 1024, i64 0)
+; CHECK-NEXT: [[RET:%.*]] = call i8* @__memmove_chk(i8* nonnull bitcast (%struct.T1* @t1 to i8*), i8* nonnull bitcast (%struct.T2* @t2 to i8*), i64 1024, i64 0)
; CHECK-NEXT: ret i8* [[RET]]
;
%dst = bitcast %struct.T1* @t1 to i8*
define i8* @test_no_simplify3(i8* %dst, i8* %src, i64 %a, i64 %b) {
; CHECK-LABEL: @test_no_simplify3(
-; CHECK-NEXT: %ret = musttail call i8* @__memmove_chk(i8* %dst, i8* %src, i64 1824, i64 1824)
-; CHECK-NEXT: ret i8* %ret
+; CHECK-NEXT: [[RET:%.*]] = musttail call i8* @__memmove_chk(i8* [[DST:%.*]], i8* [[SRC:%.*]], i64 1824, i64 1824)
+; CHECK-NEXT: ret i8* [[RET]]
;
%ret = musttail call i8* @__memmove_chk(i8* %dst, i8* %src, i64 1824, i64 1824)
ret i8* %ret
define i8* @call_memrchr_a123123_3_n(i64 %n) {
; CHECK-LABEL: @call_memrchr_a123123_3_n(
-; CHECK-NEXT: [[RET:%.*]] = call i8* @memrchr(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @a123123, i64 0, i64 0), i32 3, i64 [[N:%.*]])
+; CHECK-NEXT: [[RET:%.*]] = call i8* @memrchr(i8* nonnull getelementptr inbounds ([6 x i8], [6 x i8]* @a123123, i64 0, i64 0), i32 3, i64 [[N:%.*]])
; CHECK-NEXT: ret i8* [[RET]]
;
define i8* @call_memrchr_a123123_2_n(i64 %n) {
; CHECK-LABEL: @call_memrchr_a123123_2_n(
-; CHECK-NEXT: [[RET:%.*]] = call i8* @memrchr(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @a123123, i64 0, i64 0), i32 2, i64 [[N:%.*]])
+; CHECK-NEXT: [[RET:%.*]] = call i8* @memrchr(i8* nonnull getelementptr inbounds ([6 x i8], [6 x i8]* @a123123, i64 0, i64 0), i32 2, i64 [[N:%.*]])
; CHECK-NEXT: ret i8* [[RET]]
;
define i8* @call_memrchr_a123123_1_n(i64 %n) {
; CHECK-LABEL: @call_memrchr_a123123_1_n(
-; CHECK-NEXT: [[RET:%.*]] = call i8* @memrchr(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @a123123, i64 0, i64 0), i32 1, i64 [[N:%.*]])
+; CHECK-NEXT: [[RET:%.*]] = call i8* @memrchr(i8* nonnull getelementptr inbounds ([6 x i8], [6 x i8]* @a123123, i64 0, i64 0), i32 1, i64 [[N:%.*]])
; CHECK-NEXT: ret i8* [[RET]]
;
define i8* @call_memrchr_a1110111_c_n(i32 %C, i64 %N) {
; CHECK-LABEL: @call_memrchr_a1110111_c_n(
-; CHECK-NEXT: [[RET:%.*]] = call i8* @memrchr(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @a1110111, i64 0, i64 0), i32 [[C:%.*]], i64 [[N:%.*]])
+; CHECK-NEXT: [[RET:%.*]] = call i8* @memrchr(i8* nonnull getelementptr inbounds ([7 x i8], [7 x i8]* @a1110111, i64 0, i64 0), i32 [[C:%.*]], i64 [[N:%.*]])
; CHECK-NEXT: ret i8* [[RET]]
;
define i1 @call_memrchr_a_c_n_eq_a(i32 %c, i64 %n) {
; CHECK-LABEL: @call_memrchr_a_c_n_eq_a(
-; CHECK-NEXT: [[Q:%.*]] = call i8* @memrchr(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @a5, i64 0, i64 0), i32 [[C:%.*]], i64 [[N:%.*]])
+; CHECK-NEXT: [[Q:%.*]] = call i8* @memrchr(i8* nonnull getelementptr inbounds ([5 x i8], [5 x i8]* @a5, i64 0, i64 0), i32 [[C:%.*]], i64 [[N:%.*]])
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8* [[Q]], getelementptr inbounds ([5 x i8], [5 x i8]* @a5, i64 0, i64 0)
; CHECK-NEXT: ret i1 [[CMP]]
;
define i8* @test_no_simplify1() {
; CHECK-LABEL: @test_no_simplify1(
-; CHECK-NEXT: [[RET:%.*]] = call i8* @__memset_chk(i8* bitcast (%struct.T* @t to i8*), i32 0, i64 1824, i64 400)
+; CHECK-NEXT: [[RET:%.*]] = call i8* @__memset_chk(i8* nonnull bitcast (%struct.T* @t to i8*), i32 0, i64 1824, i64 400)
; CHECK-NEXT: ret i8* [[RET]]
;
%dst = bitcast %struct.T* @t to i8*
define i8* @test_no_simplify2() {
; CHECK-LABEL: @test_no_simplify2(
-; CHECK-NEXT: [[RET:%.*]] = call i8* @__memset_chk(i8* bitcast (%struct.T* @t to i8*), i32 0, i64 1824, i64 0)
+; CHECK-NEXT: [[RET:%.*]] = call i8* @__memset_chk(i8* nonnull bitcast (%struct.T* @t to i8*), i32 0, i64 1824, i64 0)
; CHECK-NEXT: ret i8* [[RET]]
;
%dst = bitcast %struct.T* @t to i8*
; CHECK: bb11:
; CHECK-NEXT: unreachable
; CHECK: bb12:
-; CHECK-NEXT: [[TMP0:%.*]] = call i8* @__inline_memcpy_chk(i8* bitcast (float* getelementptr inbounds ([480 x float], [480 x float]* @array, i32 0, i32 1) to i8*), i8* [[PTR3:%.*]], i32 512) #[[ATTR3:[0-9]+]]
+; CHECK-NEXT: [[TMP0:%.*]] = call i8* @__inline_memcpy_chk(i8* nonnull bitcast (float* getelementptr inbounds ([480 x float], [480 x float]* @array, i32 0, i32 1) to i8*), i8* [[PTR3:%.*]], i32 512) #[[ATTR3:[0-9]+]]
; CHECK-NEXT: unreachable
;
entry:
define i32 @test9(i8** %esc) {
; CHECK-LABEL: @test9(
-; CHECK-NEXT: [[CALL:%.*]] = tail call dereferenceable_or_null(8) i8* @strdup(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0)) #[[ATTR0]]
+; CHECK-NEXT: [[CALL:%.*]] = tail call dereferenceable_or_null(8) i8* @strdup(i8* nonnull getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0)) #[[ATTR0]]
; CHECK-NEXT: store i8* [[CALL]], i8** [[ESC:%.*]], align 8
; CHECK-NEXT: ret i32 8
;
define i32 @test10(i8** %esc) {
; CHECK-LABEL: @test10(
-; CHECK-NEXT: [[CALL:%.*]] = tail call dereferenceable_or_null(4) i8* @strndup(i8* dereferenceable(8) getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0), i32 3) #[[ATTR0]]
+; CHECK-NEXT: [[CALL:%.*]] = tail call dereferenceable_or_null(4) i8* @strndup(i8* nonnull dereferenceable(8) getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0), i32 3) #[[ATTR0]]
; CHECK-NEXT: store i8* [[CALL]], i8** [[ESC:%.*]], align 8
; CHECK-NEXT: ret i32 4
;
define i32 @test11(i8** %esc) {
; CHECK-LABEL: @test11(
-; CHECK-NEXT: [[STRDUP:%.*]] = tail call dereferenceable_or_null(8) i8* @strdup(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0))
+; CHECK-NEXT: [[STRDUP:%.*]] = tail call dereferenceable_or_null(8) i8* @strdup(i8* nonnull getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0))
; CHECK-NEXT: store i8* [[STRDUP]], i8** [[ESC:%.*]], align 8
; CHECK-NEXT: ret i32 8
;
define i32 @test12(i8** %esc) {
; CHECK-LABEL: @test12(
-; CHECK-NEXT: [[STRDUP:%.*]] = tail call dereferenceable_or_null(8) i8* @strdup(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0))
+; CHECK-NEXT: [[STRDUP:%.*]] = tail call dereferenceable_or_null(8) i8* @strdup(i8* nonnull getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0))
; CHECK-NEXT: store i8* [[STRDUP]], i8** [[ESC:%.*]], align 8
; CHECK-NEXT: ret i32 8
;
define i32 @test13(i8** %esc) {
; CHECK-LABEL: @test13(
-; CHECK-NEXT: [[STRDUP:%.*]] = tail call dereferenceable_or_null(8) i8* @strdup(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0))
+; CHECK-NEXT: [[STRDUP:%.*]] = tail call dereferenceable_or_null(8) i8* @strdup(i8* nonnull getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0))
; CHECK-NEXT: store i8* [[STRDUP]], i8** [[ESC:%.*]], align 8
; CHECK-NEXT: ret i32 8
;
define ptr @test1() {
; CHECK32-LABEL: @test1(
-; CHECK32-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr getelementptr inbounds ([5 x i8], ptr @str, i32 0, i32 2), i16 103)
+; CHECK32-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr nonnull getelementptr inbounds ([5 x i8], ptr @str, i32 0, i32 2), i16 103)
; CHECK32-NEXT: ret ptr [[TMP3]]
;
; CHECK16-LABEL: @test1(
define ptr @test2() {
; CHECK32-LABEL: @test2(
-; CHECK32-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr getelementptr inbounds ([8 x i8], ptr @str1, i32 0, i32 2), i16 0)
+; CHECK32-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr nonnull getelementptr inbounds ([8 x i8], ptr @str1, i32 0, i32 2), i16 0)
; CHECK32-NEXT: ret ptr [[TMP3]]
;
; CHECK16-LABEL: @test2(
define ptr @test3() {
; CHECK32-LABEL: @test3(
; CHECK32-NEXT: entry:
-; CHECK32-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr getelementptr inbounds ([5 x i8], ptr @str2, i32 0, i32 1), i16 80)
+; CHECK32-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr nonnull getelementptr inbounds ([5 x i8], ptr @str2, i32 0, i32 1), i16 80)
; CHECK32-NEXT: ret ptr [[TMP3]]
;
; CHECK16-LABEL: @test3(
; CHECK32-NEXT: ret ptr getelementptr inbounds ([5 x i8], ptr @str, i32 0, i32 3)
;
; CHECK16-LABEL: @test1(
-; CHECK16-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr getelementptr inbounds ([5 x i8], ptr @str, i32 0, i32 2), i32 103)
+; CHECK16-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr nonnull getelementptr inbounds ([5 x i8], ptr @str, i32 0, i32 2), i32 103)
; CHECK16-NEXT: ret ptr [[TMP3]]
;
%tmp3 = tail call ptr @strchr( ptr getelementptr ([5 x i8], ptr @str, i32 0, i32 2), i32 103 ) ; <ptr> [#uses=1]
; CHECK32-NEXT: ret ptr getelementptr inbounds ([8 x i8], ptr @str1, i32 0, i32 7)
;
; CHECK16-LABEL: @test2(
-; CHECK16-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr getelementptr inbounds ([8 x i8], ptr @str1, i32 0, i32 2), i32 0)
+; CHECK16-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr nonnull getelementptr inbounds ([8 x i8], ptr @str1, i32 0, i32 2), i32 0)
; CHECK16-NEXT: ret ptr [[TMP3]]
;
%tmp3 = tail call ptr @strchr( ptr getelementptr ([8 x i8], ptr @str1, i32 0, i32 2), i32 0 ) ; <ptr> [#uses=1]
;
; CHECK16-LABEL: @test3(
; CHECK16-NEXT: entry:
-; CHECK16-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr getelementptr inbounds ([5 x i8], ptr @str2, i32 0, i32 1), i32 80)
+; CHECK16-NEXT: [[TMP3:%.*]] = tail call ptr @strchr(ptr nonnull getelementptr inbounds ([5 x i8], ptr @str2, i32 0, i32 1), i32 80)
; CHECK16-NEXT: ret ptr [[TMP3]]
;
entry:
; Check fwrite is generated with arguments of ptr size, not index size
define internal void @fputs_test_custom_dl() {
; CHECK-LABEL: @fputs_test_custom_dl(
-; CHECK-NEXT: [[TMP1:%.*]] = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i32 0, i32 0))
+; CHECK-NEXT: [[CALL:%.*]] = call %struct._IO_FILE* @fopen(i8* nonnull getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i32 0, i32 0), i8* nonnull getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i32 0, i32 0))
+; CHECK-NEXT: [[TMP1:%.*]] = call i40 @fwrite(i8* nonnull getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i32 0, i32 0), i40 3, i40 1, %struct._IO_FILE* [[CALL]])
+; CHECK-NEXT: ret void
;
%call = call %struct._IO_FILE* @fopen(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @.str.1, i64 0, i64 0))
%call1 = call i32 @fputs(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.2, i64 0, i64 0), %struct._IO_FILE* %call)
define i8* @test_no_simplify1() {
; CHECK-LABEL: @test_no_simplify1(
-; CHECK-NEXT: [[RET:%.*]] = call i8* @stpcpy(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([32 x i8], [32 x i8]* @b, i32 0, i32 0))
+; CHECK-NEXT: [[RET:%.*]] = call i8* @stpcpy(i8* nonnull getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), i8* nonnull getelementptr inbounds ([32 x i8], [32 x i8]* @b, i32 0, i32 0))
; CHECK-NEXT: ret i8* [[RET]]
;
%dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0
define i8* @test_simplify1_tail() {
; CHECK-LABEL: @test_simplify1_tail(
-; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noundef nonnull align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* noundef nonnull align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false)
+; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* noundef nonnull align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* noundef nonnull align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false)
; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 11)
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
define i8* @test_simplify4() {
; CHECK-LABEL: @test_simplify4(
-; CHECK-NEXT: [[STPCPY:%.*]] = call i8* @stpcpy(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0))
+; CHECK-NEXT: [[STPCPY:%.*]] = call i8* @stpcpy(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0))
; CHECK-NEXT: ret i8* [[STPCPY]]
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
define i8* @test_simplify4_tail() {
; CHECK-LABEL: @test_simplify4_tail(
-; CHECK-NEXT: [[STPCPY:%.*]] = tail call i8* @stpcpy(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0))
+; CHECK-NEXT: [[STPCPY:%.*]] = tail call i8* @stpcpy(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0))
; CHECK-NEXT: ret i8* [[STPCPY]]
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
define i8* @test_simplify5() {
; CHECK-LABEL: @test_simplify5(
; CHECK-NEXT: [[LEN:%.*]] = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false, i1 false)
-; CHECK-NEXT: [[TMP1:%.*]] = call i8* @__memcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i32 [[LEN]])
+; CHECK-NEXT: [[TMP1:%.*]] = call i8* @__memcpy_chk(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i32 [[LEN]])
; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 11)
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
define i8* @test_simplify7() {
; CHECK-LABEL: @test_simplify7(
-; CHECK-NEXT: [[STPCPY:%.*]] = tail call i8* @stpcpy(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0))
+; CHECK-NEXT: [[STPCPY:%.*]] = tail call i8* @stpcpy(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0))
; CHECK-NEXT: ret i8* [[STPCPY]]
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
define i8* @test_no_simplify1() {
; CHECK-LABEL: @test_no_simplify1(
-; CHECK-NEXT: [[RET:%.*]] = call i8* @__stpcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0), i32 8)
+; CHECK-NEXT: [[RET:%.*]] = call i8* @__stpcpy_chk(i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* nonnull getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0), i32 8)
; CHECK-NEXT: ret i8* [[RET]]
;
%dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0
@str.5 = private unnamed_addr constant [10 x i8] c"1234\00\00\00\00\00\00", align 1
; Verify that the generated constants have the expected contents.
+
+; Verify that exactly overlapping stpncpy(D, D, N) calls are transformed
+; to D + strnlen(D, N) or, equivalently, D + (*D != '\0'), when N < 2.
+
+;.
; ANY: @[[A4:[a-zA-Z0-9_$"\\.-]+]] = constant [4 x i8] c"1234"
; ANY: @[[S4:[a-zA-Z0-9_$"\\.-]+]] = constant [5 x i8] c"1234\00"
; ANY: @[[STR:[a-zA-Z0-9_$"\\.-]+]] = private constant [4 x i8] c"4\00\00\00"
; ANY: @[[STR_7:[a-zA-Z0-9_$"\\.-]+]] = private unnamed_addr constant [10 x i8] c"4\00\00\00\00\00\00\00\00\00", align 1
; ANY: @[[STR_8:[a-zA-Z0-9_$"\\.-]+]] = private unnamed_addr constant [10 x i8] c"1234\00\00\00\00\00\00", align 1
; ANY: @[[STR_9:[a-zA-Z0-9_$"\\.-]+]] = private unnamed_addr constant [10 x i8] c"1234\00\00\00\00\00\00", align 1
-
-; Verify that exactly overlapping stpncpy(D, D, N) calls are transformed
-; to D + strnlen(D, N) or, equivalently, D + (*D != '\0'), when N < 2.
-
+;.
define void @fold_stpncpy_overlap(i8* %dst, i64 %n) {
; ANY-LABEL: @fold_stpncpy_overlap(
; ANY-NEXT: call void @sink(i8* [[DST:%.*]], i8* [[DST]])
define void @call_stpncpy_xx_n(i8* %dst, i64 %n) {
; ANY-LABEL: @call_stpncpy_xx_n(
-; ANY-NEXT: [[EA1_N:%.*]] = call i8* @stpncpy(i8* [[DST:%.*]], i8* dereferenceable(2) getelementptr inbounds ([4 x i8], [4 x i8]* @a4, i64 0, i64 3), i64 [[N:%.*]])
+; ANY-NEXT: [[EA1_N:%.*]] = call i8* @stpncpy(i8* [[DST:%.*]], i8* nonnull dereferenceable(2) getelementptr inbounds ([4 x i8], [4 x i8]* @a4, i64 0, i64 3), i64 [[N:%.*]])
; ANY-NEXT: call void @sink(i8* [[DST]], i8* [[EA1_N]])
-; ANY-NEXT: [[EA4_N:%.*]] = call i8* @stpncpy(i8* [[DST]], i8* dereferenceable(5) getelementptr inbounds ([4 x i8], [4 x i8]* @a4, i64 0, i64 0), i64 [[N]])
+; ANY-NEXT: [[EA4_N:%.*]] = call i8* @stpncpy(i8* [[DST]], i8* nonnull dereferenceable(5) getelementptr inbounds ([4 x i8], [4 x i8]* @a4, i64 0, i64 0), i64 [[N]])
; ANY-NEXT: call void @sink(i8* [[DST]], i8* [[EA4_N]])
-; ANY-NEXT: [[ES1_N:%.*]] = call i8* @stpncpy(i8* [[DST]], i8* dereferenceable(2) getelementptr inbounds ([5 x i8], [5 x i8]* @s4, i64 0, i64 3), i64 [[N]])
+; ANY-NEXT: [[ES1_N:%.*]] = call i8* @stpncpy(i8* [[DST]], i8* nonnull dereferenceable(2) getelementptr inbounds ([5 x i8], [5 x i8]* @s4, i64 0, i64 3), i64 [[N]])
; ANY-NEXT: call void @sink(i8* [[DST]], i8* [[ES1_N]])
-; ANY-NEXT: [[ES4_N:%.*]] = call i8* @stpncpy(i8* [[DST]], i8* dereferenceable(5) getelementptr inbounds ([5 x i8], [5 x i8]* @s4, i64 0, i64 0), i64 [[N]])
+; ANY-NEXT: [[ES4_N:%.*]] = call i8* @stpncpy(i8* [[DST]], i8* nonnull dereferenceable(5) getelementptr inbounds ([5 x i8], [5 x i8]* @s4, i64 0, i64 0), i64 [[N]])
; ANY-NEXT: call void @sink(i8* [[DST]], i8* [[ES4_N]])
; ANY-NEXT: ret void
;
define void @fold_atoi_offset_out_of_bounds(ptr %pi) {
; CHECK-LABEL: @fold_atoi_offset_out_of_bounds(
-; CHECK-NEXT: [[IA_0_0_32:%.*]] = call i32 @atoi(ptr nocapture getelementptr inbounds ([2 x %struct.A], ptr @a, i64 1, i64 0, i32 0, i64 0))
+; CHECK-NEXT: [[IA_0_0_32:%.*]] = call i32 @atoi(ptr nocapture nonnull getelementptr inbounds ([2 x %struct.A], ptr @a, i64 1, i64 0, i32 0, i64 0))
; CHECK-NEXT: store i32 [[IA_0_0_32]], ptr [[PI:%.*]], align 4
; CHECK-NEXT: [[IA_0_0_33:%.*]] = call i32 @atoi(ptr nocapture getelementptr ([2 x %struct.A], ptr @a, i64 1, i64 0, i32 0, i64 1))
; CHECK-NEXT: store i32 [[IA_0_0_33]], ptr [[PI]], align 4
; CHECK-NEXT: [[NWS:%.*]] = call i32 @strtol(ptr nonnull @ws, ptr nonnull @endptr, i32 10)
; CHECK-NEXT: [[PS11:%.*]] = getelementptr i32, ptr [[PS]], i64 11
; CHECK-NEXT: store i32 [[NWS]], ptr [[PS11]], align 4
-; CHECK-NEXT: [[NWSP6:%.*]] = call i32 @strtol(ptr getelementptr inbounds ([7 x i8], ptr @ws, i64 0, i64 6), ptr nonnull @endptr, i32 10)
+; CHECK-NEXT: [[NWSP6:%.*]] = call i32 @strtol(ptr nonnull getelementptr inbounds ([7 x i8], ptr @ws, i64 0, i64 6), ptr nonnull @endptr, i32 10)
; CHECK-NEXT: [[PS12:%.*]] = getelementptr i32, ptr [[PS]], i64 12
; CHECK-NEXT: store i32 [[NWSP6]], ptr [[PS12]], align 4
; CHECK-NEXT: [[I0B1:%.*]] = call i32 @strtol(ptr nonnull @i0, ptr nonnull @endptr, i32 1)
; CHECK-NEXT: [[NWS:%.*]] = call i64 @strtoll(ptr nonnull @ws, ptr nonnull @endptr, i32 10)
; CHECK-NEXT: [[PS2:%.*]] = getelementptr i64, ptr [[PS]], i64 2
; CHECK-NEXT: store i64 [[NWS]], ptr [[PS2]], align 4
-; CHECK-NEXT: [[NWSP6:%.*]] = call i64 @strtoll(ptr getelementptr inbounds ([7 x i8], ptr @ws, i64 0, i64 6), ptr nonnull @endptr, i32 10)
+; CHECK-NEXT: [[NWSP6:%.*]] = call i64 @strtoll(ptr nonnull getelementptr inbounds ([7 x i8], ptr @ws, i64 0, i64 6), ptr nonnull @endptr, i32 10)
; CHECK-NEXT: [[PS3:%.*]] = getelementptr i64, ptr [[PS]], i64 3
; CHECK-NEXT: store i64 [[NWSP6]], ptr [[PS3]], align 4
; CHECK-NEXT: ret void
; CHECK-NEXT: [[N1:%.*]] = call i32 @strtol(ptr nonnull @i_1_2_3_, ptr nonnull @endptr, i32 10)
; CHECK-NEXT: [[PS1:%.*]] = getelementptr i32, ptr [[PS:%.*]], i64 1
; CHECK-NEXT: store i32 [[N1]], ptr [[PS1]], align 4
-; CHECK-NEXT: [[N2:%.*]] = call i32 @strtol(ptr getelementptr inbounds ([9 x i8], ptr @i_1_2_3_, i64 0, i64 2), ptr nonnull @endptr, i32 10)
+; CHECK-NEXT: [[N2:%.*]] = call i32 @strtol(ptr nonnull getelementptr inbounds ([9 x i8], ptr @i_1_2_3_, i64 0, i64 2), ptr nonnull @endptr, i32 10)
; CHECK-NEXT: [[PS2:%.*]] = getelementptr i32, ptr [[PS]], i64 2
; CHECK-NEXT: store i32 [[N2]], ptr [[PS2]], align 4
-; CHECK-NEXT: [[N3:%.*]] = call i32 @strtol(ptr getelementptr inbounds ([9 x i8], ptr @i_1_2_3_, i64 0, i64 4), ptr nonnull @endptr, i32 10)
+; CHECK-NEXT: [[N3:%.*]] = call i32 @strtol(ptr nonnull getelementptr inbounds ([9 x i8], ptr @i_1_2_3_, i64 0, i64 4), ptr nonnull @endptr, i32 10)
; CHECK-NEXT: [[PS3:%.*]] = getelementptr i32, ptr [[PS]], i64 3
; CHECK-NEXT: store i32 [[N3]], ptr [[PS3]], align 4
; CHECK-NEXT: ret void
; CHECK-NEXT: [[NWS:%.*]] = call i32 @strtoul(ptr nonnull @ws, ptr nonnull @endptr, i32 10)
; CHECK-NEXT: [[PS2:%.*]] = getelementptr i32, ptr [[PS]], i64 2
; CHECK-NEXT: store i32 [[NWS]], ptr [[PS2]], align 4
-; CHECK-NEXT: [[NWSP6:%.*]] = call i32 @strtoul(ptr getelementptr inbounds ([7 x i8], ptr @ws, i64 0, i64 6), ptr nonnull @endptr, i32 10)
+; CHECK-NEXT: [[NWSP6:%.*]] = call i32 @strtoul(ptr nonnull getelementptr inbounds ([7 x i8], ptr @ws, i64 0, i64 6), ptr nonnull @endptr, i32 10)
; CHECK-NEXT: [[PS3:%.*]] = getelementptr i32, ptr [[PS]], i64 3
; CHECK-NEXT: store i32 [[NWSP6]], ptr [[PS3]], align 4
; CHECK-NEXT: ret void
; CHECK-NEXT: [[NWS:%.*]] = call i64 @strtoull(ptr nonnull @ws, ptr nonnull @endptr, i32 10)
; CHECK-NEXT: [[PS2:%.*]] = getelementptr i64, ptr [[PS]], i64 2
; CHECK-NEXT: store i64 [[NWS]], ptr [[PS2]], align 4
-; CHECK-NEXT: [[NWSP6:%.*]] = call i64 @strtoull(ptr getelementptr inbounds ([7 x i8], ptr @ws, i64 0, i64 6), ptr nonnull @endptr, i32 10)
+; CHECK-NEXT: [[NWSP6:%.*]] = call i64 @strtoull(ptr nonnull getelementptr inbounds ([7 x i8], ptr @ws, i64 0, i64 6), ptr nonnull @endptr, i32 10)
; CHECK-NEXT: [[PS3:%.*]] = getelementptr i64, ptr [[PS]], i64 3
; CHECK-NEXT: store i64 [[NWSP6]], ptr [[PS3]], align 4
; CHECK-NEXT: ret void
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; Verify that calls to known string library functions declared with
; incompatible signatures are handled gracefully and without aborting.
;
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes=instcombine -opaque-pointers -S | FileCheck %s
@a = constant [2 x i8] c"1\00"
define ptr @call_bad_strncasecmp() {
; CHECK-LABEL: @call_bad_strncasecmp(
-; CHECK-NEXT: [[CMP:%.*]] = call ptr @strncasecmp(ptr nonnull @a, ptr getelementptr inbounds ([2 x i8], ptr @a, i64 0, i64 1))
+; CHECK-NEXT: [[CMP:%.*]] = call ptr @strncasecmp(ptr nonnull @a, ptr nonnull getelementptr inbounds ([2 x i8], ptr @a, i64 0, i64 1))
; CHECK-NEXT: ret ptr [[CMP]]
;
%p1 = getelementptr [2 x i8], ptr @a, i32 0, i32 1
define i1 @call_bad_strcoll() {
; CHECK-LABEL: @call_bad_strcoll(
-; CHECK-NEXT: [[I:%.*]] = call i1 @strcoll(ptr nonnull @a, ptr getelementptr inbounds ([2 x i8], ptr @a, i64 0, i64 1), ptr nonnull @a)
+; CHECK-NEXT: [[I:%.*]] = call i1 @strcoll(ptr nonnull @a, ptr nonnull getelementptr inbounds ([2 x i8], ptr @a, i64 0, i64 1), ptr nonnull @a)
; CHECK-NEXT: ret i1 [[I]]
;
%p1 = getelementptr [2 x i8], ptr @a, i32 0, i32 1
define i1 @call_bad_strtok() {
; CHECK-LABEL: @call_bad_strtok(
-; CHECK-NEXT: [[RET:%.*]] = call i1 @strtok(ptr nonnull @a, ptr getelementptr inbounds ([2 x i8], ptr @a, i64 0, i64 1), i1 false)
+; CHECK-NEXT: [[RET:%.*]] = call i1 @strtok(ptr nonnull @a, ptr nonnull getelementptr inbounds ([2 x i8], ptr @a, i64 0, i64 1), i1 false)
; CHECK-NEXT: ret i1 [[RET]]
;
%p1 = getelementptr [2 x i8], ptr @a, i32 0, i32 1
define i1 @call_bad_strtok_r() {
; CHECK-LABEL: @call_bad_strtok_r(
-; CHECK-NEXT: [[RET:%.*]] = call i1 @strtok_r(ptr nonnull @a, ptr getelementptr inbounds ([2 x i8], ptr @a, i64 0, i64 1))
+; CHECK-NEXT: [[RET:%.*]] = call i1 @strtok_r(ptr nonnull @a, ptr nonnull getelementptr inbounds ([2 x i8], ptr @a, i64 0, i64 1))
; CHECK-NEXT: ret i1 [[RET]]
;
%p1 = getelementptr [2 x i8], ptr @a, i32 0, i32 1
define ptr @call_bad_strxfrm() {
; CHECK-LABEL: @call_bad_strxfrm(
-; CHECK-NEXT: [[RET:%.*]] = call ptr @strxfrm(ptr nonnull @a, ptr getelementptr inbounds ([2 x i8], ptr @a, i64 0, i64 1))
+; CHECK-NEXT: [[RET:%.*]] = call ptr @strxfrm(ptr nonnull @a, ptr nonnull getelementptr inbounds ([2 x i8], ptr @a, i64 0, i64 1))
; CHECK-NEXT: ret ptr [[RET]]
;
%p1 = getelementptr [2 x i8], ptr @a, i32 0, i32 1
define i32 @fold_atoi_past_end() {
; CHECK-LABEL: @fold_atoi_past_end(
-; CHECK-NEXT: [[I:%.*]] = call i32 @atoi(ptr nocapture getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0))
+; CHECK-NEXT: [[I:%.*]] = call i32 @atoi(ptr nocapture nonnull getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0))
; CHECK-NEXT: ret i32 [[I]]
;
%p5 = getelementptr [5 x i8], ptr @a5, i32 0, i32 5
define void @fold_atol_strtol_past_end(ptr %ps) {
; CHECK-LABEL: @fold_atol_strtol_past_end(
-; CHECK-NEXT: [[I0:%.*]] = call i64 @atol(ptr nocapture getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0))
+; CHECK-NEXT: [[I0:%.*]] = call i64 @atol(ptr nocapture nonnull getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0))
; CHECK-NEXT: store i64 [[I0]], ptr [[PS:%.*]], align 4
-; CHECK-NEXT: [[I1:%.*]] = call i64 @atoll(ptr nocapture getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0))
+; CHECK-NEXT: [[I1:%.*]] = call i64 @atoll(ptr nocapture nonnull getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0))
; CHECK-NEXT: [[P1:%.*]] = getelementptr i64, ptr [[PS]], i64 1
; CHECK-NEXT: store i64 [[I1]], ptr [[P1]], align 4
-; CHECK-NEXT: [[I2:%.*]] = call i64 @strtol(ptr nocapture getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0), ptr null, i32 0)
+; CHECK-NEXT: [[I2:%.*]] = call i64 @strtol(ptr nocapture nonnull getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0), ptr null, i32 0)
; CHECK-NEXT: [[P2:%.*]] = getelementptr i64, ptr [[PS]], i64 2
; CHECK-NEXT: store i64 [[I2]], ptr [[P2]], align 4
-; CHECK-NEXT: [[I3:%.*]] = call i64 @strtoul(ptr nocapture getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0), ptr null, i32 8)
+; CHECK-NEXT: [[I3:%.*]] = call i64 @strtoul(ptr nocapture nonnull getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0), ptr null, i32 8)
; CHECK-NEXT: [[P3:%.*]] = getelementptr i64, ptr [[PS]], i64 3
; CHECK-NEXT: store i64 [[I3]], ptr [[P3]], align 4
-; CHECK-NEXT: [[I4:%.*]] = call i64 @strtoll(ptr nocapture getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0), ptr null, i32 10)
+; CHECK-NEXT: [[I4:%.*]] = call i64 @strtoll(ptr nocapture nonnull getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0), ptr null, i32 10)
; CHECK-NEXT: [[P4:%.*]] = getelementptr i64, ptr [[PS]], i64 4
; CHECK-NEXT: store i64 [[I4]], ptr [[P4]], align 4
-; CHECK-NEXT: [[I5:%.*]] = call i64 @strtoul(ptr nocapture getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0), ptr null, i32 16)
+; CHECK-NEXT: [[I5:%.*]] = call i64 @strtoul(ptr nocapture nonnull getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0), ptr null, i32 16)
; CHECK-NEXT: [[P5:%.*]] = getelementptr i64, ptr [[PS]], i64 5
; CHECK-NEXT: store i64 [[I5]], ptr [[P5]], align 4
; CHECK-NEXT: ret void
define void @fold_snprintf_past_end(ptr %pcnt, ptr %dst, i64 %n) {
; CHECK-LABEL: @fold_snprintf_past_end(
-; CHECK-NEXT: [[N5_:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr [[DST:%.*]], i64 [[N:%.*]], ptr getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0))
+; CHECK-NEXT: [[N5_:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr [[DST:%.*]], i64 [[N:%.*]], ptr nonnull getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0))
; CHECK-NEXT: store i32 [[N5_]], ptr [[PCNT:%.*]], align 4
-; CHECK-NEXT: [[N05:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr [[DST]], i64 [[N]], ptr nonnull @a5, ptr getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0))
+; CHECK-NEXT: [[N05:%.*]] = call i32 (ptr, i64, ptr, ...) @snprintf(ptr [[DST]], i64 [[N]], ptr nonnull @a5, ptr nonnull getelementptr inbounds ([5 x i8], ptr @a5, i64 1, i64 0))
; CHECK-NEXT: [[PN05:%.*]] = getelementptr i32, ptr [[PCNT]], i64 1
; CHECK-NEXT: store i32 [[N05]], ptr [[PN05]], align 4
; CHECK-NEXT: ret void
define i64 @test_no_simplify1() {
; CHECK-LABEL: @test_no_simplify1(
-; CHECK-NEXT: [[A_L:%.*]] = call i64 @wcslen(i32* getelementptr inbounds ([32 x i32], [32 x i32]* @a, i64 0, i64 0))
+; CHECK-NEXT: [[A_L:%.*]] = call i64 @wcslen(i32* nonnull getelementptr inbounds ([32 x i32], [32 x i32]* @a, i64 0, i64 0))
; CHECK-NEXT: ret i64 [[A_L]]
;
%a_p = getelementptr [32 x i32], [32 x i32]* @a, i64 0, i64 0
define i64 @test_no_simplify1() {
; CHECK-LABEL: @test_no_simplify1(
-; CHECK-NEXT: [[A_L:%.*]] = call i64 @wcslen(i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a, i64 0, i64 0))
+; CHECK-NEXT: [[A_L:%.*]] = call i64 @wcslen(i16* nonnull getelementptr inbounds ([32 x i16], [32 x i16]* @a, i64 0, i64 0))
; CHECK-NEXT: ret i64 [[A_L]]
;
%a_p = getelementptr [32 x i16], [32 x i16]* @a, i64 0, i64 0
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; Test that the wcslen library call simplifier works correctly.
;
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
define i64 @test_no_simplify1() {
; CHECK-LABEL: @test_no_simplify1(
-; CHECK-NEXT: %hello_l = call i64 @wcslen(i32* getelementptr inbounds ([6 x i32], [6 x i32]* @hello, i64 0, i64 0))
-; CHECK-NEXT: ret i64 %hello_l
+; CHECK-NEXT: [[HELLO_L:%.*]] = call i64 @wcslen(i32* nonnull getelementptr inbounds ([6 x i32], [6 x i32]* @hello, i64 0, i64 0))
+; CHECK-NEXT: ret i64 [[HELLO_L]]
+;
%hello_p = getelementptr [6 x i32], [6 x i32]* @hello, i64 0, i64 0
%hello_l = call i64 @wcslen(i32* %hello_p)
ret i64 %hello_l
; CHECK-LABEL: @fold_wcslen_s3_pi_s5(
; CHECK-NEXT: [[PS3_PI:%.*]] = getelementptr inbounds [4 x i32], [4 x i32]* @ws3, i64 0, i64 [[TMP1:%.*]]
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[TMP0:%.*]], i32* [[PS3_PI]], i32* getelementptr inbounds ([6 x i32], [6 x i32]* @ws5, i64 0, i64 0)
-; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @wcslen(i32* [[SEL]])
+; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @wcslen(i32* nonnull [[SEL]])
; CHECK-NEXT: ret i64 [[LEN]]
;
; CHECK-NEXT: [[PS3_PI:%.*]] = getelementptr inbounds [4 x i32], [4 x i32]* @ws3, i64 0, i64 [[TMP1:%.*]]
; CHECK-NEXT: [[PS3_PI_P1:%.*]] = getelementptr inbounds i32, i32* [[PS3_PI]], i64 1
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[TMP0:%.*]], i32* [[PS3_PI_P1]], i32* getelementptr inbounds ([6 x i32], [6 x i32]* @ws5, i64 0, i64 0)
-; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @wcslen(i32* [[SEL]])
+; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @wcslen(i32* nonnull [[SEL]])
; CHECK-NEXT: ret i64 [[LEN]]
;
; CHECK-LABEL: @call_wcslen_s5_3_pi_s5(
; CHECK-NEXT: [[PS5_3_PI:%.*]] = getelementptr inbounds [10 x i32], [10 x i32]* @ws5_3, i64 0, i64 [[TMP1:%.*]]
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[TMP0:%.*]], i32* [[PS5_3_PI]], i32* getelementptr inbounds ([6 x i32], [6 x i32]* @ws5, i64 0, i64 0)
-; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @wcslen(i32* [[SEL]])
+; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @wcslen(i32* nonnull [[SEL]])
; CHECK-NEXT: ret i64 [[LEN]]
;
; CHECK-LABEL: @call_wcslen_s5_3_s5_pj(
; CHECK-NEXT: [[PS5:%.*]] = getelementptr inbounds [6 x i32], [6 x i32]* @ws5, i64 0, i64 [[TMP1:%.*]]
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[TMP0:%.*]], i32* getelementptr inbounds ([10 x i32], [10 x i32]* @ws5_3, i64 0, i64 0), i32* [[PS5]]
-; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @wcslen(i32* [[SEL]])
+; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @wcslen(i32* nonnull [[SEL]])
; CHECK-NEXT: ret i64 [[LEN]]
;
; CHECK-LABEL: @fold_wcslen_s3_s5_pj(
; CHECK-NEXT: [[PS5_PJ:%.*]] = getelementptr inbounds [6 x i32], [6 x i32]* @ws5, i64 0, i64 [[TMP1:%.*]]
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[TMP0:%.*]], i32* getelementptr inbounds ([4 x i32], [4 x i32]* @ws3, i64 0, i64 0), i32* [[PS5_PJ]]
-; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @wcslen(i32* [[SEL]])
+; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @wcslen(i32* nonnull [[SEL]])
; CHECK-NEXT: ret i64 [[LEN]]
;
; CHECK-LABEL: @call_wcslen_s3_s5_3_pj(
; CHECK-NEXT: [[PS5_3_PJ:%.*]] = getelementptr inbounds [10 x i32], [10 x i32]* @ws5_3, i64 0, i64 [[TMP1:%.*]]
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[TMP0:%.*]], i32* getelementptr inbounds ([4 x i32], [4 x i32]* @ws3, i64 0, i64 0), i32* [[PS5_3_PJ]]
-; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @wcslen(i32* [[SEL]])
+; CHECK-NEXT: [[LEN:%.*]] = tail call i64 @wcslen(i32* nonnull [[SEL]])
; CHECK-NEXT: ret i64 [[LEN]]
;
}
; CHECK-LABEL: define hidden void @__typeid_typeid1_0_branch_funnel(i8* nest %0, ...)
-; CHECK-NEXT: musttail call void (...) @llvm.icall.branch.funnel(i8* %0, i8* bitcast ([1 x i8*]* {{(nonnull )?}}@vt1_1 to i8*), i32 (i8*, i32)* {{(nonnull )?}}@vf1_1, i8* bitcast ([1 x i8*]* {{(nonnull )?}}@vt1_2 to i8*), i32 (i8*, i32)* {{(nonnull )?}}@vf1_2, ...)
+; CHECK-NEXT: musttail call void (...) @llvm.icall.branch.funnel(i8* %0, i8* {{(nonnull )?}}bitcast ([1 x i8*]* @vt1_1 to i8*), i32 (i8*, i32)* {{(nonnull )?}}@vf1_1, i8* {{(nonnull )?}}bitcast ([1 x i8*]* @vt1_2 to i8*), i32 (i8*, i32)* {{(nonnull )?}}@vf1_2, ...)
; CHECK: define internal void @branch_funnel(i8*