llvm-project/llvm/test/Transforms/Attributor/value-simplify-pointer-info.ll
Johannes Doerfert 335e137267
[Attributor][FIX] Track returned pointer offsets (#110534)
If the pointer returned by a function is not "the base pointer" but has
an offset, we need to track the offset such that users can apply it to
their offset chain when they create accesses.
This was reported by @ye-luo and reduced test cases are included. The
OffsetInfo was moved and the container was replaced with a set to avoid
excessive growth. Otherwise, the patch just replaces the "returns
pointer" flag with the "returned offsets", and deals with the applying
to offsets at the call site.

---------

Co-authored-by: Johannes Doerfert <jdoerfert@llnl.gov>
2024-10-01 12:41:15 -05:00

3743 lines
181 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT
; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC
;
%struct.S = type { i32, i32, i32, float, float, float }
@globalBytes = global [1024 x i8] zeroinitializer, align 16
@Gint1 = global i32 zeroinitializer, align 4
@Gint2 = global i32 zeroinitializer, align 4
@Gstatic_int1 = internal global i32 zeroinitializer, align 4
@Gstatic_int2 = internal global i32 zeroinitializer, align 4
@Gstatic_int3 = internal global i32 zeroinitializer, align 4
@Gstatic_undef_int1 = internal global i32 undef, align 4
@Gstatic_undef_int2 = internal global i32 undef, align 4
@GI1 = internal global i32 undef, align 4
@GI2 = internal global i32 undef, align 4
@Gs1 = internal global %struct.S undef, align 4
@Gs2 = internal global %struct.S zeroinitializer, align 4
@Vs1 = internal global %struct.S undef, align 4
@Vs2 = internal global %struct.S undef, align 4
@GBytes = internal global [1024 x i8] zeroinitializer, align 16
@Flag0 = global i32 0, align 4
@Flag1 = internal global i32 undef, align 4
@Flag2 = internal global i32 undef, align 4
@Flag4 = internal global i32 undef, align 4
@Flag3 = internal global i32 zeroinitializer, align 4
@a1 = internal global i32 zeroinitializer
@a2 = internal global i32 zeroinitializer
@a3 = internal global i32 undef
@bytes1 = internal global i32 undef
@bytes2 = internal global i32 undef
@rec_storage = internal global i32 undef
;.
; CHECK: @globalBytes = global [1024 x i8] zeroinitializer, align 16
; CHECK: @Gint1 = global i32 0, align 4
; CHECK: @Gint2 = global i32 0, align 4
; CHECK: @Gstatic_int1 = internal global i32 0, align 4
; CHECK: @Gstatic_int2 = internal global i32 0, align 4
; CHECK: @Gstatic_int3 = internal global i32 0, align 4
; CHECK: @Gstatic_undef_int1 = internal global i32 undef, align 4
; CHECK: @Gstatic_undef_int2 = internal global i32 undef, align 4
; CHECK: @GI1 = internal global i32 undef, align 4
; CHECK: @GI2 = internal global i32 undef, align 4
; CHECK: @Gs1 = internal global %struct.S undef, align 4
; CHECK: @Gs2 = internal global %struct.S zeroinitializer, align 4
; CHECK: @Vs1 = internal global %struct.S undef, align 4
; CHECK: @Vs2 = internal global %struct.S undef, align 4
; CHECK: @GBytes = internal global [1024 x i8] zeroinitializer, align 16
; CHECK: @Flag0 = global i32 0, align 4
; CHECK: @Flag1 = internal global i32 undef, align 4
; CHECK: @Flag2 = internal global i32 undef, align 4
; CHECK: @Flag4 = internal global i32 undef, align 4
; CHECK: @Flag3 = internal global i32 0, align 4
; CHECK: @a1 = internal global i32 0
; CHECK: @a2 = internal global i32 0
; CHECK: @a3 = internal global i32 undef
; CHECK: @bytes1 = internal global i32 undef
; CHECK: @bytes2 = internal global i32 undef
; CHECK: @rec_storage = internal global i32 undef
; CHECK: @global = internal global %struct.STy zeroinitializer, align 8
; CHECK: @G = internal global i32 0, align 4
; CHECK: @GC = internal global i32 undef, align 4
; CHECK: @GRS = internal thread_local global i32 undef
; CHECK: @GRS2 = global i32 undef
;.
define void @write_arg(ptr %p, i32 %v) {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
; CHECK-LABEL: define {{[^@]+}}@write_arg
; CHECK-SAME: (ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[P:%.*]], i32 [[V:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: store i32 [[V]], ptr [[P]], align 4, !tbaa [[TBAA3:![0-9]+]]
; CHECK-NEXT: ret void
;
entry:
store i32 %v, ptr %p, align 4, !tbaa !3
ret void
}
define void @write_random(ptr %p) {
; CHECK-LABEL: define {{[^@]+}}@write_random
; CHECK-SAME: (ptr nocapture nofree writeonly [[P:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = call i32 (...) @random()
; CHECK-NEXT: store i32 [[CALL]], ptr [[P]], align 4, !tbaa [[TBAA3]]
; CHECK-NEXT: ret void
;
entry:
%call = call i32 (...) @random()
store i32 %call, ptr %p, align 4, !tbaa !3
ret void
}
declare i32 @random(...)
; struct S local_alloca_simplifiable_1(void) {
; struct S s;
; s.f1 = 1.1;
; s.f2 = 2.2;
; s.f3 = 3.3;
; write_arg(&s.i1, 1);
; write_arg(&s.i2, 2);
; write_arg(&s.i3, 3);
; struct S r;
; r.f1 = s.f1;
; r.f2 = s.f2 * 2;
; r.f3 = s.f3 + s.f1;
; r.i1 = s.i1;
; r.i2 = s.i2 * 2;
; r.i3 = s.i3 + s.i1;
; return r;
; }
define void @local_alloca_simplifiable_1(ptr noalias sret(%struct.S) align 4 %agg.result) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)
; TUNIT-LABEL: define {{[^@]+}}@local_alloca_simplifiable_1
; TUNIT-SAME: (ptr noalias nocapture nofree writeonly sret([[STRUCT_S:%.*]]) align 4 dereferenceable_or_null(24) [[AGG_RESULT:%.*]]) #[[ATTR1:[0-9]+]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[S:%.*]] = alloca [[STRUCT_S]], align 4
; TUNIT-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 24, ptr noalias nocapture nofree noundef nonnull align 4 dereferenceable(24) [[S]]) #[[ATTR17:[0-9]+]]
; TUNIT-NEXT: [[F1:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 3
; TUNIT-NEXT: [[F2:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 4
; TUNIT-NEXT: [[F3:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 5
; TUNIT-NEXT: call void @write_arg(ptr noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(24) [[S]], i32 noundef 1) #[[ATTR18:[0-9]+]]
; TUNIT-NEXT: [[I2:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 1
; TUNIT-NEXT: call void @write_arg(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(20) [[I2]], i32 noundef 2) #[[ATTR18]]
; TUNIT-NEXT: [[I3:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 2
; TUNIT-NEXT: call void @write_arg(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(16) [[I3]], i32 noundef 3) #[[ATTR18]]
; TUNIT-NEXT: [[F12:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 3
; TUNIT-NEXT: store float 0x3FF19999A0000000, ptr [[F12]], align 4, !tbaa [[TBAA7:![0-9]+]]
; TUNIT-NEXT: [[F24:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 4
; TUNIT-NEXT: store float 0x40119999A0000000, ptr [[F24]], align 4, !tbaa [[TBAA10:![0-9]+]]
; TUNIT-NEXT: [[F37:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 5
; TUNIT-NEXT: store float 0x40119999A0000000, ptr [[F37]], align 4, !tbaa [[TBAA11:![0-9]+]]
; TUNIT-NEXT: store i32 1, ptr [[AGG_RESULT]], align 4, !tbaa [[TBAA12:![0-9]+]]
; TUNIT-NEXT: [[I212:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 1
; TUNIT-NEXT: store i32 4, ptr [[I212]], align 4, !tbaa [[TBAA13:![0-9]+]]
; TUNIT-NEXT: [[I316:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 2
; TUNIT-NEXT: store i32 4, ptr [[I316]], align 4, !tbaa [[TBAA14:![0-9]+]]
; TUNIT-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 24, ptr noalias nocapture nofree noundef nonnull align 4 dereferenceable(24) [[S]]) #[[ATTR17]]
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: readwrite)
; CGSCC-LABEL: define {{[^@]+}}@local_alloca_simplifiable_1
; CGSCC-SAME: (ptr noalias nocapture nofree noundef nonnull writeonly sret([[STRUCT_S:%.*]]) align 4 dereferenceable(24) [[AGG_RESULT:%.*]]) #[[ATTR1:[0-9]+]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[S:%.*]] = alloca [[STRUCT_S]], align 4
; CGSCC-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 24, ptr noalias nocapture nofree noundef nonnull align 4 dereferenceable(24) [[S]]) #[[ATTR20:[0-9]+]]
; CGSCC-NEXT: [[F1:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 3
; CGSCC-NEXT: store float 0x3FF19999A0000000, ptr [[F1]], align 4, !tbaa [[TBAA7:![0-9]+]]
; CGSCC-NEXT: [[F2:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 4
; CGSCC-NEXT: store float 0x40019999A0000000, ptr [[F2]], align 4, !tbaa [[TBAA10:![0-9]+]]
; CGSCC-NEXT: [[F3:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 5
; CGSCC-NEXT: store float 0x400A666660000000, ptr [[F3]], align 4, !tbaa [[TBAA11:![0-9]+]]
; CGSCC-NEXT: call void @write_arg(ptr noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(24) [[S]], i32 noundef 1) #[[ATTR21:[0-9]+]]
; CGSCC-NEXT: [[I2:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 1
; CGSCC-NEXT: call void @write_arg(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(20) [[I2]], i32 noundef 2) #[[ATTR21]]
; CGSCC-NEXT: [[I3:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 2
; CGSCC-NEXT: call void @write_arg(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(16) [[I3]], i32 noundef 3) #[[ATTR21]]
; CGSCC-NEXT: [[F11:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 3
; CGSCC-NEXT: [[I4:%.*]] = load float, ptr [[F11]], align 4, !tbaa [[TBAA7]]
; CGSCC-NEXT: [[F12:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 3
; CGSCC-NEXT: store float [[I4]], ptr [[F12]], align 4, !tbaa [[TBAA7]]
; CGSCC-NEXT: [[F23:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 4
; CGSCC-NEXT: [[I5:%.*]] = load float, ptr [[F23]], align 4, !tbaa [[TBAA10]]
; CGSCC-NEXT: [[MUL:%.*]] = fmul float [[I5]], 2.000000e+00
; CGSCC-NEXT: [[F24:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 4
; CGSCC-NEXT: store float [[MUL]], ptr [[F24]], align 4, !tbaa [[TBAA10]]
; CGSCC-NEXT: [[F35:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 5
; CGSCC-NEXT: [[I6:%.*]] = load float, ptr [[F35]], align 4, !tbaa [[TBAA11]]
; CGSCC-NEXT: [[F16:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 3
; CGSCC-NEXT: [[I7:%.*]] = load float, ptr [[F16]], align 4, !tbaa [[TBAA7]]
; CGSCC-NEXT: [[ADD:%.*]] = fadd float [[I6]], [[I7]]
; CGSCC-NEXT: [[F37:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 5
; CGSCC-NEXT: store float [[ADD]], ptr [[F37]], align 4, !tbaa [[TBAA11]]
; CGSCC-NEXT: [[I8:%.*]] = load i32, ptr [[S]], align 4, !tbaa [[TBAA12:![0-9]+]]
; CGSCC-NEXT: store i32 [[I8]], ptr [[AGG_RESULT]], align 4, !tbaa [[TBAA12]]
; CGSCC-NEXT: [[I210:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 1
; CGSCC-NEXT: [[I9:%.*]] = load i32, ptr [[I210]], align 4, !tbaa [[TBAA13:![0-9]+]]
; CGSCC-NEXT: [[MUL11:%.*]] = shl nsw i32 [[I9]], 1
; CGSCC-NEXT: [[I212:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 1
; CGSCC-NEXT: store i32 [[MUL11]], ptr [[I212]], align 4, !tbaa [[TBAA13]]
; CGSCC-NEXT: [[I313:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 2
; CGSCC-NEXT: [[I10:%.*]] = load i32, ptr [[I313]], align 4, !tbaa [[TBAA14:![0-9]+]]
; CGSCC-NEXT: [[I11:%.*]] = load i32, ptr [[S]], align 4, !tbaa [[TBAA12]]
; CGSCC-NEXT: [[ADD15:%.*]] = add nsw i32 [[I10]], [[I11]]
; CGSCC-NEXT: [[I316:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 2
; CGSCC-NEXT: store i32 [[ADD15]], ptr [[I316]], align 4, !tbaa [[TBAA14]]
; CGSCC-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 24, ptr noalias nocapture nofree noundef nonnull align 4 dereferenceable(24) [[S]]) #[[ATTR20]]
; CGSCC-NEXT: ret void
;
entry:
%s = alloca %struct.S, align 4
call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %s)
%f1 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 3
store float 0x3FF19999A0000000, ptr %f1, align 4, !tbaa !7
%f2 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 4
store float 0x40019999A0000000, ptr %f2, align 4, !tbaa !10
%f3 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 5
store float 0x400A666660000000, ptr %f3, align 4, !tbaa !11
call void @write_arg(ptr nonnull %s, i32 1)
%i2 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 1
call void @write_arg(ptr nonnull %i2, i32 2)
%i3 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 2
call void @write_arg(ptr nonnull %i3, i32 3)
%f11 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 3
%i4 = load float, ptr %f11, align 4, !tbaa !7
%f12 = getelementptr inbounds %struct.S, ptr %agg.result, i64 0, i32 3
store float %i4, ptr %f12, align 4, !tbaa !7
%f23 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 4
%i5 = load float, ptr %f23, align 4, !tbaa !10
%mul = fmul float %i5, 2.000000e+00
%f24 = getelementptr inbounds %struct.S, ptr %agg.result, i64 0, i32 4
store float %mul, ptr %f24, align 4, !tbaa !10
%f35 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 5
%i6 = load float, ptr %f35, align 4, !tbaa !11
%f16 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 3
%i7 = load float, ptr %f16, align 4, !tbaa !7
%add = fadd float %i6, %i7
%f37 = getelementptr inbounds %struct.S, ptr %agg.result, i64 0, i32 5
store float %add, ptr %f37, align 4, !tbaa !11
%i8 = load i32, ptr %s, align 4, !tbaa !12
store i32 %i8, ptr %agg.result, align 4, !tbaa !12
%i210 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 1
%i9 = load i32, ptr %i210, align 4, !tbaa !13
%mul11 = shl nsw i32 %i9, 1
%i212 = getelementptr inbounds %struct.S, ptr %agg.result, i64 0, i32 1
store i32 %mul11, ptr %i212, align 4, !tbaa !13
%i313 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 2
%i10 = load i32, ptr %i313, align 4, !tbaa !14
%i11 = load i32, ptr %s, align 4, !tbaa !12
%add15 = add nsw i32 %i10, %i11
%i316 = getelementptr inbounds %struct.S, ptr %agg.result, i64 0, i32 2
store i32 %add15, ptr %i316, align 4, !tbaa !14
call void @llvm.lifetime.end.p0(i64 24, ptr nonnull %s)
ret void
}
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture)
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture)
; void local_alloca_simplifiable_2(void) {
; char Bytes[1024];
; for (int i = 0; i < 100; ++i)
; Bytes[i * 10] = 0;
; for (int i = 0; i < 10; ++i)
; ((float *)Bytes)[i * 10 + 1] = 0;
; for (int i = 0; i < 20; ++i)
; ((long long int *)Bytes)[i * 10 + 2] = 0;
; Bytes[1023] = 0;
; write_arg((int *)&Bytes[500], 0);
; struct S R;
; for (int i = 0; i < 1024; ++i)
; globalBytes[i] = Bytes[i];
; }
;
define void @local_alloca_simplifiable_2() {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@local_alloca_simplifiable_2
; TUNIT-SAME: () #[[ATTR3:[0-9]+]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16
; TUNIT-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 1024, ptr noalias nocapture nofree noundef nonnull align 16 dereferenceable(1024) [[BYTES]]) #[[ATTR17]]
; TUNIT-NEXT: br label [[FOR_COND:%.*]]
; TUNIT: for.cond:
; TUNIT-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[ENTRY:%.*]] ]
; TUNIT-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV]], 100
; TUNIT-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]]
; TUNIT: for.cond.cleanup:
; TUNIT-NEXT: br label [[FOR_END:%.*]]
; TUNIT: for.body:
; TUNIT-NEXT: [[I15:%.*]] = mul nuw nsw i64 [[INDVARS_IV]], 10
; TUNIT-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 [[I15]]
; TUNIT-NEXT: br label [[FOR_INC]]
; TUNIT: for.inc:
; TUNIT-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
; TUNIT-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP15:![0-9]+]]
; TUNIT: for.end:
; TUNIT-NEXT: br label [[FOR_COND2:%.*]]
; TUNIT: for.cond2:
; TUNIT-NEXT: [[INDVARS_IV2:%.*]] = phi i64 [ [[INDVARS_IV_NEXT3:%.*]], [[FOR_INC9:%.*]] ], [ 0, [[FOR_END]] ]
; TUNIT-NEXT: [[EXITCOND6:%.*]] = icmp ne i64 [[INDVARS_IV2]], 10
; TUNIT-NEXT: br i1 [[EXITCOND6]], label [[FOR_BODY5:%.*]], label [[FOR_COND_CLEANUP4:%.*]]
; TUNIT: for.cond.cleanup4:
; TUNIT-NEXT: br label [[FOR_END11:%.*]]
; TUNIT: for.body5:
; TUNIT-NEXT: [[I17:%.*]] = mul nuw nsw i64 [[INDVARS_IV2]], 10
; TUNIT-NEXT: [[I18:%.*]] = or i64 [[I17]], 1
; TUNIT-NEXT: [[ARRAYIDX8:%.*]] = getelementptr inbounds float, ptr [[BYTES]], i64 [[I18]]
; TUNIT-NEXT: br label [[FOR_INC9]]
; TUNIT: for.inc9:
; TUNIT-NEXT: [[INDVARS_IV_NEXT3]] = add nuw nsw i64 [[INDVARS_IV2]], 1
; TUNIT-NEXT: br label [[FOR_COND2]], !llvm.loop [[LOOP17:![0-9]+]]
; TUNIT: for.end11:
; TUNIT-NEXT: br label [[FOR_COND13:%.*]]
; TUNIT: for.cond13:
; TUNIT-NEXT: [[INDVARS_IV7:%.*]] = phi i64 [ [[INDVARS_IV_NEXT8:%.*]], [[FOR_INC22:%.*]] ], [ 0, [[FOR_END11]] ]
; TUNIT-NEXT: [[EXITCOND11:%.*]] = icmp ne i64 [[INDVARS_IV7]], 20
; TUNIT-NEXT: br i1 [[EXITCOND11]], label [[FOR_BODY16:%.*]], label [[FOR_COND_CLEANUP15:%.*]]
; TUNIT: for.cond.cleanup15:
; TUNIT-NEXT: br label [[FOR_END24:%.*]]
; TUNIT: for.body16:
; TUNIT-NEXT: [[I20:%.*]] = mul nuw nsw i64 [[INDVARS_IV7]], 10
; TUNIT-NEXT: [[I21:%.*]] = add nuw nsw i64 [[I20]], 2
; TUNIT-NEXT: [[ARRAYIDX21:%.*]] = getelementptr inbounds i64, ptr [[BYTES]], i64 [[I21]]
; TUNIT-NEXT: br label [[FOR_INC22]]
; TUNIT: for.inc22:
; TUNIT-NEXT: [[INDVARS_IV_NEXT8]] = add nuw nsw i64 [[INDVARS_IV7]], 1
; TUNIT-NEXT: br label [[FOR_COND13]], !llvm.loop [[LOOP18:![0-9]+]]
; TUNIT: for.end24:
; TUNIT-NEXT: [[ARRAYIDX25:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 1023
; TUNIT-NEXT: [[ARRAYIDX26:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 500
; TUNIT-NEXT: call void @write_arg(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(524) [[ARRAYIDX26]], i32 noundef 0) #[[ATTR18]]
; TUNIT-NEXT: br label [[FOR_COND28:%.*]]
; TUNIT: for.cond28:
; TUNIT-NEXT: [[INDVARS_IV12:%.*]] = phi i64 [ [[INDVARS_IV_NEXT13:%.*]], [[FOR_INC36:%.*]] ], [ 0, [[FOR_END24]] ]
; TUNIT-NEXT: [[EXITCOND14:%.*]] = icmp ne i64 [[INDVARS_IV12]], 1024
; TUNIT-NEXT: br i1 [[EXITCOND14]], label [[FOR_BODY31:%.*]], label [[FOR_COND_CLEANUP30:%.*]]
; TUNIT: for.cond.cleanup30:
; TUNIT-NEXT: br label [[FOR_END38:%.*]]
; TUNIT: for.body31:
; TUNIT-NEXT: [[ARRAYIDX35:%.*]] = getelementptr inbounds [1024 x i8], ptr @globalBytes, i64 0, i64 [[INDVARS_IV12]]
; TUNIT-NEXT: store i8 0, ptr [[ARRAYIDX35]], align 1, !tbaa [[TBAA19:![0-9]+]]
; TUNIT-NEXT: br label [[FOR_INC36]]
; TUNIT: for.inc36:
; TUNIT-NEXT: [[INDVARS_IV_NEXT13]] = add nuw nsw i64 [[INDVARS_IV12]], 1
; TUNIT-NEXT: br label [[FOR_COND28]], !llvm.loop [[LOOP20:![0-9]+]]
; TUNIT: for.end38:
; TUNIT-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 1024, ptr noalias nocapture nofree noundef nonnull align 16 dereferenceable(1024) [[BYTES]]) #[[ATTR17]]
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@local_alloca_simplifiable_2
; CGSCC-SAME: () #[[ATTR3:[0-9]+]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16
; CGSCC-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 1024, ptr noalias nocapture nofree noundef nonnull align 16 dereferenceable(1024) [[BYTES]]) #[[ATTR20]]
; CGSCC-NEXT: br label [[FOR_COND:%.*]]
; CGSCC: for.cond:
; CGSCC-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[ENTRY:%.*]] ]
; CGSCC-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV]], 100
; CGSCC-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]]
; CGSCC: for.cond.cleanup:
; CGSCC-NEXT: br label [[FOR_END:%.*]]
; CGSCC: for.body:
; CGSCC-NEXT: [[I15:%.*]] = mul nuw nsw i64 [[INDVARS_IV]], 10
; CGSCC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 [[I15]]
; CGSCC-NEXT: store i8 0, ptr [[ARRAYIDX]], align 2, !tbaa [[TBAA15:![0-9]+]]
; CGSCC-NEXT: br label [[FOR_INC]]
; CGSCC: for.inc:
; CGSCC-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
; CGSCC-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP16:![0-9]+]]
; CGSCC: for.end:
; CGSCC-NEXT: br label [[FOR_COND2:%.*]]
; CGSCC: for.cond2:
; CGSCC-NEXT: [[INDVARS_IV2:%.*]] = phi i64 [ [[INDVARS_IV_NEXT3:%.*]], [[FOR_INC9:%.*]] ], [ 0, [[FOR_END]] ]
; CGSCC-NEXT: [[EXITCOND6:%.*]] = icmp ne i64 [[INDVARS_IV2]], 10
; CGSCC-NEXT: br i1 [[EXITCOND6]], label [[FOR_BODY5:%.*]], label [[FOR_COND_CLEANUP4:%.*]]
; CGSCC: for.cond.cleanup4:
; CGSCC-NEXT: br label [[FOR_END11:%.*]]
; CGSCC: for.body5:
; CGSCC-NEXT: [[I17:%.*]] = mul nuw nsw i64 [[INDVARS_IV2]], 10
; CGSCC-NEXT: [[I18:%.*]] = or i64 [[I17]], 1
; CGSCC-NEXT: [[ARRAYIDX8:%.*]] = getelementptr inbounds float, ptr [[BYTES]], i64 [[I18]]
; CGSCC-NEXT: store float 0.000000e+00, ptr [[ARRAYIDX8]], align 4, !tbaa [[TBAA18:![0-9]+]]
; CGSCC-NEXT: br label [[FOR_INC9]]
; CGSCC: for.inc9:
; CGSCC-NEXT: [[INDVARS_IV_NEXT3]] = add nuw nsw i64 [[INDVARS_IV2]], 1
; CGSCC-NEXT: br label [[FOR_COND2]], !llvm.loop [[LOOP19:![0-9]+]]
; CGSCC: for.end11:
; CGSCC-NEXT: br label [[FOR_COND13:%.*]]
; CGSCC: for.cond13:
; CGSCC-NEXT: [[INDVARS_IV7:%.*]] = phi i64 [ [[INDVARS_IV_NEXT8:%.*]], [[FOR_INC22:%.*]] ], [ 0, [[FOR_END11]] ]
; CGSCC-NEXT: [[EXITCOND11:%.*]] = icmp ne i64 [[INDVARS_IV7]], 20
; CGSCC-NEXT: br i1 [[EXITCOND11]], label [[FOR_BODY16:%.*]], label [[FOR_COND_CLEANUP15:%.*]]
; CGSCC: for.cond.cleanup15:
; CGSCC-NEXT: br label [[FOR_END24:%.*]]
; CGSCC: for.body16:
; CGSCC-NEXT: [[I20:%.*]] = mul nuw nsw i64 [[INDVARS_IV7]], 10
; CGSCC-NEXT: [[I21:%.*]] = add nuw nsw i64 [[I20]], 2
; CGSCC-NEXT: [[ARRAYIDX21:%.*]] = getelementptr inbounds i64, ptr [[BYTES]], i64 [[I21]]
; CGSCC-NEXT: store i64 0, ptr [[ARRAYIDX21]], align 16, !tbaa [[TBAA20:![0-9]+]]
; CGSCC-NEXT: br label [[FOR_INC22]]
; CGSCC: for.inc22:
; CGSCC-NEXT: [[INDVARS_IV_NEXT8]] = add nuw nsw i64 [[INDVARS_IV7]], 1
; CGSCC-NEXT: br label [[FOR_COND13]], !llvm.loop [[LOOP22:![0-9]+]]
; CGSCC: for.end24:
; CGSCC-NEXT: [[ARRAYIDX25:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 1023
; CGSCC-NEXT: store i8 0, ptr [[ARRAYIDX25]], align 1, !tbaa [[TBAA15]]
; CGSCC-NEXT: [[ARRAYIDX26:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 500
; CGSCC-NEXT: call void @write_arg(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(524) [[ARRAYIDX26]], i32 noundef 0) #[[ATTR21]]
; CGSCC-NEXT: br label [[FOR_COND28:%.*]]
; CGSCC: for.cond28:
; CGSCC-NEXT: [[INDVARS_IV12:%.*]] = phi i64 [ [[INDVARS_IV_NEXT13:%.*]], [[FOR_INC36:%.*]] ], [ 0, [[FOR_END24]] ]
; CGSCC-NEXT: [[EXITCOND14:%.*]] = icmp ne i64 [[INDVARS_IV12]], 1024
; CGSCC-NEXT: br i1 [[EXITCOND14]], label [[FOR_BODY31:%.*]], label [[FOR_COND_CLEANUP30:%.*]]
; CGSCC: for.cond.cleanup30:
; CGSCC-NEXT: br label [[FOR_END38:%.*]]
; CGSCC: for.body31:
; CGSCC-NEXT: [[ARRAYIDX33:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 [[INDVARS_IV12]]
; CGSCC-NEXT: [[I23:%.*]] = load i8, ptr [[ARRAYIDX33]], align 1, !tbaa [[TBAA15]]
; CGSCC-NEXT: [[ARRAYIDX35:%.*]] = getelementptr inbounds [1024 x i8], ptr @globalBytes, i64 0, i64 [[INDVARS_IV12]]
; CGSCC-NEXT: store i8 [[I23]], ptr [[ARRAYIDX35]], align 1, !tbaa [[TBAA15]]
; CGSCC-NEXT: br label [[FOR_INC36]]
; CGSCC: for.inc36:
; CGSCC-NEXT: [[INDVARS_IV_NEXT13]] = add nuw nsw i64 [[INDVARS_IV12]], 1
; CGSCC-NEXT: br label [[FOR_COND28]], !llvm.loop [[LOOP23:![0-9]+]]
; CGSCC: for.end38:
; CGSCC-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 1024, ptr noalias nocapture nofree noundef nonnull align 16 dereferenceable(1024) [[BYTES]]) #[[ATTR20]]
; CGSCC-NEXT: ret void
;
entry:
%Bytes = alloca [1024 x i8], align 16
call void @llvm.lifetime.start.p0(i64 1024, ptr nonnull %Bytes)
br label %for.cond
for.cond: ; preds = %for.inc, %entry
%indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
%exitcond = icmp ne i64 %indvars.iv, 100
br i1 %exitcond, label %for.body, label %for.cond.cleanup
for.cond.cleanup: ; preds = %for.cond
br label %for.end
for.body: ; preds = %for.cond
%i15 = mul nuw nsw i64 %indvars.iv, 10
%arrayidx = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 %i15
store i8 0, ptr %arrayidx, align 2, !tbaa !15
br label %for.inc
for.inc: ; preds = %for.body
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
br label %for.cond, !llvm.loop !16
for.end: ; preds = %for.cond.cleanup
br label %for.cond2
for.cond2: ; preds = %for.inc9, %for.end
%indvars.iv2 = phi i64 [ %indvars.iv.next3, %for.inc9 ], [ 0, %for.end ]
%exitcond6 = icmp ne i64 %indvars.iv2, 10
br i1 %exitcond6, label %for.body5, label %for.cond.cleanup4
for.cond.cleanup4: ; preds = %for.cond2
br label %for.end11
for.body5: ; preds = %for.cond2
%i17 = mul nuw nsw i64 %indvars.iv2, 10
%i18 = or i64 %i17, 1
%arrayidx8 = getelementptr inbounds float, ptr %Bytes, i64 %i18
store float 0.000000e+00, ptr %arrayidx8, align 4, !tbaa !18
br label %for.inc9
for.inc9: ; preds = %for.body5
%indvars.iv.next3 = add nuw nsw i64 %indvars.iv2, 1
br label %for.cond2, !llvm.loop !19
for.end11: ; preds = %for.cond.cleanup4
br label %for.cond13
for.cond13: ; preds = %for.inc22, %for.end11
%indvars.iv7 = phi i64 [ %indvars.iv.next8, %for.inc22 ], [ 0, %for.end11 ]
%exitcond11 = icmp ne i64 %indvars.iv7, 20
br i1 %exitcond11, label %for.body16, label %for.cond.cleanup15
for.cond.cleanup15: ; preds = %for.cond13
br label %for.end24
for.body16: ; preds = %for.cond13
%i20 = mul nuw nsw i64 %indvars.iv7, 10
%i21 = add nuw nsw i64 %i20, 2
%arrayidx21 = getelementptr inbounds i64, ptr %Bytes, i64 %i21
store i64 0, ptr %arrayidx21, align 16, !tbaa !20
br label %for.inc22
for.inc22: ; preds = %for.body16
%indvars.iv.next8 = add nuw nsw i64 %indvars.iv7, 1
br label %for.cond13, !llvm.loop !22
for.end24: ; preds = %for.cond.cleanup15
%arrayidx25 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 1023
store i8 0, ptr %arrayidx25, align 1, !tbaa !15
%arrayidx26 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 500
call void @write_arg(ptr nonnull %arrayidx26, i32 0)
br label %for.cond28
for.cond28: ; preds = %for.inc36, %for.end24
%indvars.iv12 = phi i64 [ %indvars.iv.next13, %for.inc36 ], [ 0, %for.end24 ]
%exitcond14 = icmp ne i64 %indvars.iv12, 1024
br i1 %exitcond14, label %for.body31, label %for.cond.cleanup30
for.cond.cleanup30: ; preds = %for.cond28
br label %for.end38
for.body31: ; preds = %for.cond28
%arrayidx33 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 %indvars.iv12
%i23 = load i8, ptr %arrayidx33, align 1, !tbaa !15
%arrayidx35 = getelementptr inbounds [1024 x i8], ptr @globalBytes, i64 0, i64 %indvars.iv12
store i8 %i23, ptr %arrayidx35, align 1, !tbaa !15
br label %for.inc36
for.inc36: ; preds = %for.body31
%indvars.iv.next13 = add nuw nsw i64 %indvars.iv12, 1
br label %for.cond28, !llvm.loop !23
for.end38: ; preds = %for.cond.cleanup30
call void @llvm.lifetime.end.p0(i64 1024, ptr nonnull %Bytes)
ret void
}
; int local_alloca_simplifiable_3() {
; int A = 1;
; // split
; A = 2;
; return A;
; }
;
define i32 @local_alloca_simplifiable_3() {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CHECK-LABEL: define {{[^@]+}}@local_alloca_simplifiable_3
; CHECK-SAME: () #[[ATTR4:[0-9]+]] {
; CHECK-NEXT: br label [[SPLIT:%.*]]
; CHECK: split:
; CHECK-NEXT: ret i32 2
;
%A = alloca i32, align 4
store i32 1, ptr %A
br label %split
split:
store i32 2, ptr %A
%l = load i32, ptr %A, align 4
ret i32 %l
}
; int local_alloca_simplifiable_4() {
; int A;
; return A;
; }
;
define i32 @local_alloca_simplifiable_4() {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CHECK-LABEL: define {{[^@]+}}@local_alloca_simplifiable_4
; CHECK-SAME: () #[[ATTR4]] {
; CHECK-NEXT: ret i32 undef
;
%A = alloca i32, align 4
%l = load i32, ptr %A, align 4
ret i32 %l
}
; static int GI1 __attribute__((loader_uninitialized));
; int multi_obj_simplifiable_1(int cnd) {
; int L = GI1 = 5;
; int *p = cnd ? &GI1 : &L;
; return *p;
; }
define i32 @multi_obj_simplifiable_1(i32 %cnd) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@multi_obj_simplifiable_1
; TUNIT-SAME: (i32 [[CND:%.*]]) #[[ATTR3]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[L:%.*]] = alloca i32, align 4
; TUNIT-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 4, ptr noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[L]]) #[[ATTR17]]
; TUNIT-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[CND]], 0
; TUNIT-NEXT: br i1 [[TOBOOL_NOT]], label [[COND_FALSE:%.*]], label [[COND_TRUE:%.*]]
; TUNIT: cond.true:
; TUNIT-NEXT: br label [[COND_END:%.*]]
; TUNIT: cond.false:
; TUNIT-NEXT: br label [[COND_END]]
; TUNIT: cond.end:
; TUNIT-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 4, ptr noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[L]]) #[[ATTR17]]
; TUNIT-NEXT: ret i32 5
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@multi_obj_simplifiable_1
; CGSCC-SAME: (i32 [[CND:%.*]]) #[[ATTR5:[0-9]+]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[L:%.*]] = alloca i32, align 4
; CGSCC-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 4, ptr noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[L]]) #[[ATTR20]]
; CGSCC-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[CND]], 0
; CGSCC-NEXT: br i1 [[TOBOOL_NOT]], label [[COND_FALSE:%.*]], label [[COND_TRUE:%.*]]
; CGSCC: cond.true:
; CGSCC-NEXT: br label [[COND_END:%.*]]
; CGSCC: cond.false:
; CGSCC-NEXT: br label [[COND_END]]
; CGSCC: cond.end:
; CGSCC-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 4, ptr noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[L]]) #[[ATTR20]]
; CGSCC-NEXT: ret i32 5
;
entry:
%L = alloca i32, align 4
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %L)
store i32 5, ptr @GI1, align 4, !tbaa !3
store i32 5, ptr %L, align 4, !tbaa !3
%tobool.not = icmp eq i32 %cnd, 0
br i1 %tobool.not, label %cond.false, label %cond.true
cond.true: ; preds = %entry
br label %cond.end
cond.false: ; preds = %entry
br label %cond.end
cond.end: ; preds = %cond.false, %cond.true
%cond = phi ptr [ @GI1, %cond.true ], [ %L, %cond.false ]
%i1 = load i32, ptr %cond, align 4, !tbaa !3
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %L)
ret i32 %i1
}
; static int GI2 __attribute__((loader_uninitialized));
; int multi_obj_simplifiable_2(int cnd) {
; int L;
; int *p = cnd ? &GI2 : &L;
; *p = 5;
; return *p;
; }
;
define i32 @multi_obj_simplifiable_2(i32 %cnd) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@multi_obj_simplifiable_2
; TUNIT-SAME: (i32 [[CND:%.*]]) #[[ATTR3]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[L:%.*]] = alloca i32, align 4
; TUNIT-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 4, ptr noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[L]]) #[[ATTR17]]
; TUNIT-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[CND]], 0
; TUNIT-NEXT: br i1 [[TOBOOL_NOT]], label [[COND_FALSE:%.*]], label [[COND_TRUE:%.*]]
; TUNIT: cond.true:
; TUNIT-NEXT: br label [[COND_END:%.*]]
; TUNIT: cond.false:
; TUNIT-NEXT: br label [[COND_END]]
; TUNIT: cond.end:
; TUNIT-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 4, ptr noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[L]]) #[[ATTR17]]
; TUNIT-NEXT: ret i32 5
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@multi_obj_simplifiable_2
; CGSCC-SAME: (i32 [[CND:%.*]]) #[[ATTR5]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[L:%.*]] = alloca i32, align 4
; CGSCC-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 4, ptr noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[L]]) #[[ATTR20]]
; CGSCC-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[CND]], 0
; CGSCC-NEXT: br i1 [[TOBOOL_NOT]], label [[COND_FALSE:%.*]], label [[COND_TRUE:%.*]]
; CGSCC: cond.true:
; CGSCC-NEXT: br label [[COND_END:%.*]]
; CGSCC: cond.false:
; CGSCC-NEXT: br label [[COND_END]]
; CGSCC: cond.end:
; CGSCC-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 4, ptr noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[L]]) #[[ATTR20]]
; CGSCC-NEXT: ret i32 5
;
entry:
%L = alloca i32, align 4
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %L)
%tobool.not = icmp eq i32 %cnd, 0
br i1 %tobool.not, label %cond.false, label %cond.true
cond.true: ; preds = %entry
br label %cond.end
cond.false: ; preds = %entry
br label %cond.end
cond.end: ; preds = %cond.false, %cond.true
%cond = phi ptr [ @GI2, %cond.true ], [ %L, %cond.false ]
store i32 5, ptr %cond, align 4, !tbaa !3
%l = load i32, ptr %cond, align 4, !tbaa !3
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %L)
ret i32 %l
}
; static struct S Gs __attribute__((loader_uninitialized));
; struct S static_global_simplifiable_1(void) {
; Gs.f1 = 1.1;
; Gs.f2 = 2.2;
; Gs.f3 = 3.3;
; write_arg(&Gs.i1, 1);
; write_arg(&Gs.i2, 2);
; write_arg(&Gs.i3, 3);
; struct S r;
; r.f1 = Gs.f1;
; r.f2 = Gs.f2 * 2;
; r.f3 = Gs.f3 + Gs.f1;
; r.i1 = Gs.i1;
; r.i2 = Gs.i2 * 2;
; r.i3 = Gs.i3 + Gs.i1;
; return r;
; }
;
define void @static_global_simplifiable_1(ptr noalias sret(%struct.S) align 4 %agg.result) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; TUNIT-LABEL: define {{[^@]+}}@static_global_simplifiable_1
; TUNIT-SAME: (ptr noalias nocapture nofree writeonly sret([[STRUCT_S:%.*]]) align 4 dereferenceable_or_null(24) [[AGG_RESULT:%.*]]) #[[ATTR5:[0-9]+]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: call void @write_arg(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(24) @Gs1, i32 noundef 1) #[[ATTR18]]
; TUNIT-NEXT: call void @write_arg(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(20) getelementptr inbounds ([[STRUCT_S]], ptr @Gs1, i64 0, i32 1), i32 noundef 2) #[[ATTR18]]
; TUNIT-NEXT: call void @write_arg(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(16) getelementptr inbounds ([[STRUCT_S]], ptr @Gs1, i64 0, i32 2), i32 noundef 3) #[[ATTR18]]
; TUNIT-NEXT: [[F1:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 3
; TUNIT-NEXT: store float 0x3FF19999A0000000, ptr [[F1]], align 4, !tbaa [[TBAA7]]
; TUNIT-NEXT: [[F2:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 4
; TUNIT-NEXT: store float 0x40119999A0000000, ptr [[F2]], align 4, !tbaa [[TBAA10]]
; TUNIT-NEXT: [[F3:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 5
; TUNIT-NEXT: store float 0x40119999A0000000, ptr [[F3]], align 4, !tbaa [[TBAA11]]
; TUNIT-NEXT: store i32 1, ptr [[AGG_RESULT]], align 4, !tbaa [[TBAA12]]
; TUNIT-NEXT: [[I2:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 1
; TUNIT-NEXT: store i32 4, ptr [[I2]], align 4, !tbaa [[TBAA13]]
; TUNIT-NEXT: [[I3:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 2
; TUNIT-NEXT: store i32 4, ptr [[I3]], align 4, !tbaa [[TBAA14]]
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@static_global_simplifiable_1
; CGSCC-SAME: (ptr noalias nocapture nofree noundef nonnull writeonly sret([[STRUCT_S:%.*]]) align 4 dereferenceable(24) [[AGG_RESULT:%.*]]) #[[ATTR3]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: store float 0x3FF19999A0000000, ptr getelementptr inbounds ([[STRUCT_S]], ptr @Gs1, i64 0, i32 3), align 4, !tbaa [[TBAA7]]
; CGSCC-NEXT: store float 0x40019999A0000000, ptr getelementptr inbounds ([[STRUCT_S]], ptr @Gs1, i64 0, i32 4), align 4, !tbaa [[TBAA10]]
; CGSCC-NEXT: store float 0x400A666660000000, ptr getelementptr inbounds ([[STRUCT_S]], ptr @Gs1, i64 0, i32 5), align 4, !tbaa [[TBAA11]]
; CGSCC-NEXT: call void @write_arg(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(24) @Gs1, i32 noundef 1) #[[ATTR21]]
; CGSCC-NEXT: call void @write_arg(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(20) getelementptr inbounds ([[STRUCT_S]], ptr @Gs1, i64 0, i32 1), i32 noundef 2) #[[ATTR21]]
; CGSCC-NEXT: call void @write_arg(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(16) getelementptr inbounds ([[STRUCT_S]], ptr @Gs1, i64 0, i32 2), i32 noundef 3) #[[ATTR21]]
; CGSCC-NEXT: [[I:%.*]] = load float, ptr getelementptr inbounds ([[STRUCT_S]], ptr @Gs1, i64 0, i32 3), align 4, !tbaa [[TBAA7]]
; CGSCC-NEXT: [[F1:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 3
; CGSCC-NEXT: store float [[I]], ptr [[F1]], align 4, !tbaa [[TBAA7]]
; CGSCC-NEXT: [[I4:%.*]] = load float, ptr getelementptr inbounds ([[STRUCT_S]], ptr @Gs1, i64 0, i32 4), align 4, !tbaa [[TBAA10]]
; CGSCC-NEXT: [[MUL:%.*]] = fmul float [[I4]], 2.000000e+00
; CGSCC-NEXT: [[F2:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 4
; CGSCC-NEXT: store float [[MUL]], ptr [[F2]], align 4, !tbaa [[TBAA10]]
; CGSCC-NEXT: [[I5:%.*]] = load float, ptr getelementptr inbounds ([[STRUCT_S]], ptr @Gs1, i64 0, i32 5), align 4, !tbaa [[TBAA11]]
; CGSCC-NEXT: [[I6:%.*]] = load float, ptr getelementptr inbounds ([[STRUCT_S]], ptr @Gs1, i64 0, i32 3), align 4, !tbaa [[TBAA7]]
; CGSCC-NEXT: [[ADD:%.*]] = fadd float [[I5]], [[I6]]
; CGSCC-NEXT: [[F3:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 5
; CGSCC-NEXT: store float [[ADD]], ptr [[F3]], align 4, !tbaa [[TBAA11]]
; CGSCC-NEXT: [[I7:%.*]] = load i32, ptr @Gs1, align 4, !tbaa [[TBAA12]]
; CGSCC-NEXT: store i32 [[I7]], ptr [[AGG_RESULT]], align 4, !tbaa [[TBAA12]]
; CGSCC-NEXT: [[I8:%.*]] = load i32, ptr getelementptr inbounds ([[STRUCT_S]], ptr @Gs1, i64 0, i32 1), align 4, !tbaa [[TBAA13]]
; CGSCC-NEXT: [[MUL1:%.*]] = shl nsw i32 [[I8]], 1
; CGSCC-NEXT: [[I2:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 1
; CGSCC-NEXT: store i32 [[MUL1]], ptr [[I2]], align 4, !tbaa [[TBAA13]]
; CGSCC-NEXT: [[I9:%.*]] = load i32, ptr getelementptr inbounds ([[STRUCT_S]], ptr @Gs1, i64 0, i32 2), align 4, !tbaa [[TBAA14]]
; CGSCC-NEXT: [[I10:%.*]] = load i32, ptr @Gs1, align 4, !tbaa [[TBAA12]]
; CGSCC-NEXT: [[ADD2:%.*]] = add nsw i32 [[I9]], [[I10]]
; CGSCC-NEXT: [[I3:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 2
; CGSCC-NEXT: store i32 [[ADD2]], ptr [[I3]], align 4, !tbaa [[TBAA14]]
; CGSCC-NEXT: ret void
;
entry:
store float 0x3FF19999A0000000, ptr getelementptr inbounds (%struct.S, ptr @Gs1, i64 0, i32 3), align 4, !tbaa !7
store float 0x40019999A0000000, ptr getelementptr inbounds (%struct.S, ptr @Gs1, i64 0, i32 4), align 4, !tbaa !10
store float 0x400A666660000000, ptr getelementptr inbounds (%struct.S, ptr @Gs1, i64 0, i32 5), align 4, !tbaa !11
call void @write_arg(ptr @Gs1, i32 1)
call void @write_arg(ptr getelementptr inbounds (%struct.S, ptr @Gs1, i64 0, i32 1), i32 2)
call void @write_arg(ptr getelementptr inbounds (%struct.S, ptr @Gs1, i64 0, i32 2), i32 3)
%i = load float, ptr getelementptr inbounds (%struct.S, ptr @Gs1, i64 0, i32 3), align 4, !tbaa !7
%f1 = getelementptr inbounds %struct.S, ptr %agg.result, i64 0, i32 3
store float %i, ptr %f1, align 4, !tbaa !7
%i4 = load float, ptr getelementptr inbounds (%struct.S, ptr @Gs1, i64 0, i32 4), align 4, !tbaa !10
%mul = fmul float %i4, 2.000000e+00
%f2 = getelementptr inbounds %struct.S, ptr %agg.result, i64 0, i32 4
store float %mul, ptr %f2, align 4, !tbaa !10
%i5 = load float, ptr getelementptr inbounds (%struct.S, ptr @Gs1, i64 0, i32 5), align 4, !tbaa !11
%i6 = load float, ptr getelementptr inbounds (%struct.S, ptr @Gs1, i64 0, i32 3), align 4, !tbaa !7
%add = fadd float %i5, %i6
%f3 = getelementptr inbounds %struct.S, ptr %agg.result, i64 0, i32 5
store float %add, ptr %f3, align 4, !tbaa !11
%i7 = load i32, ptr @Gs1, align 4, !tbaa !12
store i32 %i7, ptr %agg.result, align 4, !tbaa !12
%i8 = load i32, ptr getelementptr inbounds (%struct.S, ptr @Gs1, i64 0, i32 1), align 4, !tbaa !13
%mul1 = shl nsw i32 %i8, 1
%i2 = getelementptr inbounds %struct.S, ptr %agg.result, i64 0, i32 1
store i32 %mul1, ptr %i2, align 4, !tbaa !13
%i9 = load i32, ptr getelementptr inbounds (%struct.S, ptr @Gs1, i64 0, i32 2), align 4, !tbaa !14
%i10 = load i32, ptr @Gs1, align 4, !tbaa !12
%add2 = add nsw i32 %i9, %i10
%i3 = getelementptr inbounds %struct.S, ptr %agg.result, i64 0, i32 2
store i32 %add2, ptr %i3, align 4, !tbaa !14
ret void
}
define i32 @test_range_merge1() {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; TUNIT-LABEL: define {{[^@]+}}@test_range_merge1
; TUNIT-SAME: () #[[ATTR5]] {
; TUNIT-NEXT: ret i32 2
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; CGSCC-LABEL: define {{[^@]+}}@test_range_merge1
; CGSCC-SAME: () #[[ATTR6:[0-9]+]] {
; CGSCC-NEXT: ret i32 2
;
store <2 x i32> <i32 1, i32 1>, ptr @Vs1
store float 2.000000e+00, ptr getelementptr inbounds (%struct.S, ptr @Vs1, i64 0, i32 4)
%l0 = load i32, ptr @Vs1
%l1 = load i32, ptr getelementptr inbounds (%struct.S, ptr @Vs1, i64 0, i32 1)
%add = add i32 %l0, %l1
ret i32 %add
}
define i32 @test_range_merge2() {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@test_range_merge2
; TUNIT-SAME: () #[[ATTR3]] {
; TUNIT-NEXT: store <2 x i32> <i32 3, i32 4>, ptr @Vs2, align 8
; TUNIT-NEXT: [[L0:%.*]] = load i32, ptr @Vs2, align 4
; TUNIT-NEXT: [[L1:%.*]] = load i32, ptr getelementptr inbounds ([[STRUCT_S:%.*]], ptr @Vs2, i64 0, i32 1), align 4
; TUNIT-NEXT: [[ADD:%.*]] = add i32 [[L0]], [[L1]]
; TUNIT-NEXT: ret i32 [[ADD]]
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@test_range_merge2
; CGSCC-SAME: () #[[ATTR5]] {
; CGSCC-NEXT: store <2 x i32> <i32 3, i32 4>, ptr @Vs2, align 8
; CGSCC-NEXT: [[L0:%.*]] = load i32, ptr @Vs2, align 4
; CGSCC-NEXT: [[L1:%.*]] = load i32, ptr getelementptr inbounds ([[STRUCT_S:%.*]], ptr @Vs2, i64 0, i32 1), align 4
; CGSCC-NEXT: [[ADD:%.*]] = add i32 [[L0]], [[L1]]
; CGSCC-NEXT: ret i32 [[ADD]]
;
store <2 x i32> <i32 3, i32 4>, ptr @Vs2
store float 2.000000e+00, ptr getelementptr inbounds (%struct.S, ptr @Vs2, i64 0, i32 4)
%l0 = load i32, ptr @Vs2
%l1 = load i32, ptr getelementptr inbounds (%struct.S, ptr @Vs2, i64 0, i32 1)
%add = add i32 %l0, %l1
ret i32 %add
}
; static char GBytes[1024];
; void static_global_simplifiable_2(void) {
; for (int i = 0; i < 100; ++i)
; GBytes[i * 10] = 0;
; for (int i = 0; i < 10; ++i)
; ((float *)GBytes)[i * 10 + 1] = 0;
; for (int i = 0; i < 20; ++i)
; ((long long int *)GBytes)[i * 10 + 2] = 0;
; GBytes[1023] = 0;
; write_arg((int *)&GBytes[500], 0);
; struct S R;
; for (int i = 0; i < 1024; ++i)
; globalBytes[i] = GBytes[i];
; }
;
define void @static_global_simplifiable_2() {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; TUNIT-LABEL: define {{[^@]+}}@static_global_simplifiable_2
; TUNIT-SAME: () #[[ATTR5]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: br label [[FOR_COND:%.*]]
; TUNIT: for.cond:
; TUNIT-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[ENTRY:%.*]] ]
; TUNIT-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV]], 100
; TUNIT-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]]
; TUNIT: for.cond.cleanup:
; TUNIT-NEXT: br label [[FOR_END:%.*]]
; TUNIT: for.body:
; TUNIT-NEXT: [[I:%.*]] = mul nuw nsw i64 [[INDVARS_IV]], 10
; TUNIT-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [1024 x i8], ptr @GBytes, i64 0, i64 [[I]]
; TUNIT-NEXT: br label [[FOR_INC]]
; TUNIT: for.inc:
; TUNIT-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
; TUNIT-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP21:![0-9]+]]
; TUNIT: for.end:
; TUNIT-NEXT: br label [[FOR_COND2:%.*]]
; TUNIT: for.cond2:
; TUNIT-NEXT: [[INDVARS_IV2:%.*]] = phi i64 [ [[INDVARS_IV_NEXT3:%.*]], [[FOR_INC9:%.*]] ], [ 0, [[FOR_END]] ]
; TUNIT-NEXT: [[EXITCOND6:%.*]] = icmp ne i64 [[INDVARS_IV2]], 10
; TUNIT-NEXT: br i1 [[EXITCOND6]], label [[FOR_BODY5:%.*]], label [[FOR_COND_CLEANUP4:%.*]]
; TUNIT: for.cond.cleanup4:
; TUNIT-NEXT: br label [[FOR_END11:%.*]]
; TUNIT: for.body5:
; TUNIT-NEXT: [[I15:%.*]] = mul nuw nsw i64 [[INDVARS_IV2]], 10
; TUNIT-NEXT: [[I16:%.*]] = or i64 [[I15]], 1
; TUNIT-NEXT: [[ARRAYIDX8:%.*]] = getelementptr inbounds float, ptr @GBytes, i64 [[I16]]
; TUNIT-NEXT: br label [[FOR_INC9]]
; TUNIT: for.inc9:
; TUNIT-NEXT: [[INDVARS_IV_NEXT3]] = add nuw nsw i64 [[INDVARS_IV2]], 1
; TUNIT-NEXT: br label [[FOR_COND2]], !llvm.loop [[LOOP22:![0-9]+]]
; TUNIT: for.end11:
; TUNIT-NEXT: br label [[FOR_COND13:%.*]]
; TUNIT: for.cond13:
; TUNIT-NEXT: [[INDVARS_IV7:%.*]] = phi i64 [ [[INDVARS_IV_NEXT8:%.*]], [[FOR_INC21:%.*]] ], [ 0, [[FOR_END11]] ]
; TUNIT-NEXT: [[EXITCOND11:%.*]] = icmp ne i64 [[INDVARS_IV7]], 20
; TUNIT-NEXT: br i1 [[EXITCOND11]], label [[FOR_BODY16:%.*]], label [[FOR_COND_CLEANUP15:%.*]]
; TUNIT: for.cond.cleanup15:
; TUNIT-NEXT: br label [[FOR_END23:%.*]]
; TUNIT: for.body16:
; TUNIT-NEXT: [[I17:%.*]] = mul nuw nsw i64 [[INDVARS_IV7]], 10
; TUNIT-NEXT: [[I18:%.*]] = add nuw nsw i64 [[I17]], 2
; TUNIT-NEXT: [[ARRAYIDX20:%.*]] = getelementptr inbounds i64, ptr @GBytes, i64 [[I18]]
; TUNIT-NEXT: br label [[FOR_INC21]]
; TUNIT: for.inc21:
; 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(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(524) getelementptr inbounds ([1024 x i8], ptr @GBytes, i64 0, i64 500), i32 noundef 0) #[[ATTR18]]
; TUNIT-NEXT: br label [[FOR_COND25:%.*]]
; TUNIT: for.cond25:
; TUNIT-NEXT: [[INDVARS_IV12:%.*]] = phi i64 [ [[INDVARS_IV_NEXT13:%.*]], [[FOR_INC33:%.*]] ], [ 0, [[FOR_END23]] ]
; TUNIT-NEXT: [[EXITCOND14:%.*]] = icmp ne i64 [[INDVARS_IV12]], 1024
; TUNIT-NEXT: br i1 [[EXITCOND14]], label [[FOR_BODY28:%.*]], label [[FOR_COND_CLEANUP27:%.*]]
; TUNIT: for.cond.cleanup27:
; TUNIT-NEXT: br label [[FOR_END35:%.*]]
; TUNIT: for.body28:
; TUNIT-NEXT: [[ARRAYIDX32:%.*]] = getelementptr inbounds [1024 x i8], ptr @globalBytes, i64 0, i64 [[INDVARS_IV12]]
; TUNIT-NEXT: store i8 0, ptr [[ARRAYIDX32]], align 1, !tbaa [[TBAA19]]
; TUNIT-NEXT: br label [[FOR_INC33]]
; TUNIT: for.inc33:
; TUNIT-NEXT: [[INDVARS_IV_NEXT13]] = add nuw nsw i64 [[INDVARS_IV12]], 1
; TUNIT-NEXT: br label [[FOR_COND25]], !llvm.loop [[LOOP24:![0-9]+]]
; TUNIT: for.end35:
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@static_global_simplifiable_2
; CGSCC-SAME: () #[[ATTR3]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: br label [[FOR_COND:%.*]]
; CGSCC: for.cond:
; CGSCC-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[ENTRY:%.*]] ]
; CGSCC-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV]], 100
; CGSCC-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]]
; CGSCC: for.cond.cleanup:
; CGSCC-NEXT: br label [[FOR_END:%.*]]
; CGSCC: for.body:
; CGSCC-NEXT: [[I:%.*]] = mul nuw nsw i64 [[INDVARS_IV]], 10
; CGSCC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [1024 x i8], ptr @GBytes, i64 0, i64 [[I]]
; CGSCC-NEXT: store i8 0, ptr [[ARRAYIDX]], align 2, !tbaa [[TBAA15]]
; CGSCC-NEXT: br label [[FOR_INC]]
; CGSCC: for.inc:
; CGSCC-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
; CGSCC-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP24:![0-9]+]]
; CGSCC: for.end:
; CGSCC-NEXT: br label [[FOR_COND2:%.*]]
; CGSCC: for.cond2:
; CGSCC-NEXT: [[INDVARS_IV2:%.*]] = phi i64 [ [[INDVARS_IV_NEXT3:%.*]], [[FOR_INC9:%.*]] ], [ 0, [[FOR_END]] ]
; CGSCC-NEXT: [[EXITCOND6:%.*]] = icmp ne i64 [[INDVARS_IV2]], 10
; CGSCC-NEXT: br i1 [[EXITCOND6]], label [[FOR_BODY5:%.*]], label [[FOR_COND_CLEANUP4:%.*]]
; CGSCC: for.cond.cleanup4:
; CGSCC-NEXT: br label [[FOR_END11:%.*]]
; CGSCC: for.body5:
; CGSCC-NEXT: [[I15:%.*]] = mul nuw nsw i64 [[INDVARS_IV2]], 10
; CGSCC-NEXT: [[I16:%.*]] = or i64 [[I15]], 1
; CGSCC-NEXT: [[ARRAYIDX8:%.*]] = getelementptr inbounds float, ptr @GBytes, i64 [[I16]]
; CGSCC-NEXT: store float 0.000000e+00, ptr [[ARRAYIDX8]], align 4, !tbaa [[TBAA18]]
; CGSCC-NEXT: br label [[FOR_INC9]]
; CGSCC: for.inc9:
; CGSCC-NEXT: [[INDVARS_IV_NEXT3]] = add nuw nsw i64 [[INDVARS_IV2]], 1
; CGSCC-NEXT: br label [[FOR_COND2]], !llvm.loop [[LOOP25:![0-9]+]]
; CGSCC: for.end11:
; CGSCC-NEXT: br label [[FOR_COND13:%.*]]
; CGSCC: for.cond13:
; CGSCC-NEXT: [[INDVARS_IV7:%.*]] = phi i64 [ [[INDVARS_IV_NEXT8:%.*]], [[FOR_INC21:%.*]] ], [ 0, [[FOR_END11]] ]
; CGSCC-NEXT: [[EXITCOND11:%.*]] = icmp ne i64 [[INDVARS_IV7]], 20
; CGSCC-NEXT: br i1 [[EXITCOND11]], label [[FOR_BODY16:%.*]], label [[FOR_COND_CLEANUP15:%.*]]
; CGSCC: for.cond.cleanup15:
; CGSCC-NEXT: br label [[FOR_END23:%.*]]
; CGSCC: for.body16:
; CGSCC-NEXT: [[I17:%.*]] = mul nuw nsw i64 [[INDVARS_IV7]], 10
; CGSCC-NEXT: [[I18:%.*]] = add nuw nsw i64 [[I17]], 2
; CGSCC-NEXT: [[ARRAYIDX20:%.*]] = getelementptr inbounds i64, ptr @GBytes, i64 [[I18]]
; CGSCC-NEXT: store i64 0, ptr [[ARRAYIDX20]], align 16, !tbaa [[TBAA20]]
; CGSCC-NEXT: br label [[FOR_INC21]]
; CGSCC: for.inc21:
; CGSCC-NEXT: [[INDVARS_IV_NEXT8]] = add nuw nsw i64 [[INDVARS_IV7]], 1
; CGSCC-NEXT: br label [[FOR_COND13]], !llvm.loop [[LOOP26:![0-9]+]]
; CGSCC: for.end23:
; CGSCC-NEXT: store i8 0, ptr getelementptr inbounds ([1024 x i8], ptr @GBytes, i64 0, i64 1023), align 1, !tbaa [[TBAA15]]
; CGSCC-NEXT: call void @write_arg(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(524) getelementptr inbounds ([1024 x i8], ptr @GBytes, i64 0, i64 500), i32 noundef 0) #[[ATTR21]]
; CGSCC-NEXT: br label [[FOR_COND25:%.*]]
; CGSCC: for.cond25:
; CGSCC-NEXT: [[INDVARS_IV12:%.*]] = phi i64 [ [[INDVARS_IV_NEXT13:%.*]], [[FOR_INC33:%.*]] ], [ 0, [[FOR_END23]] ]
; CGSCC-NEXT: [[EXITCOND14:%.*]] = icmp ne i64 [[INDVARS_IV12]], 1024
; CGSCC-NEXT: br i1 [[EXITCOND14]], label [[FOR_BODY28:%.*]], label [[FOR_COND_CLEANUP27:%.*]]
; CGSCC: for.cond.cleanup27:
; CGSCC-NEXT: br label [[FOR_END35:%.*]]
; CGSCC: for.body28:
; CGSCC-NEXT: [[ARRAYIDX30:%.*]] = getelementptr inbounds [1024 x i8], ptr @GBytes, i64 0, i64 [[INDVARS_IV12]]
; CGSCC-NEXT: [[I19:%.*]] = load i8, ptr [[ARRAYIDX30]], align 1, !tbaa [[TBAA15]]
; CGSCC-NEXT: [[ARRAYIDX32:%.*]] = getelementptr inbounds [1024 x i8], ptr @globalBytes, i64 0, i64 [[INDVARS_IV12]]
; CGSCC-NEXT: store i8 [[I19]], ptr [[ARRAYIDX32]], align 1, !tbaa [[TBAA15]]
; CGSCC-NEXT: br label [[FOR_INC33]]
; CGSCC: for.inc33:
; CGSCC-NEXT: [[INDVARS_IV_NEXT13]] = add nuw nsw i64 [[INDVARS_IV12]], 1
; CGSCC-NEXT: br label [[FOR_COND25]], !llvm.loop [[LOOP27:![0-9]+]]
; CGSCC: for.end35:
; CGSCC-NEXT: ret void
;
entry:
br label %for.cond
for.cond: ; preds = %for.inc, %entry
%indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
%exitcond = icmp ne i64 %indvars.iv, 100
br i1 %exitcond, label %for.body, label %for.cond.cleanup
for.cond.cleanup: ; preds = %for.cond
br label %for.end
for.body: ; preds = %for.cond
%i = mul nuw nsw i64 %indvars.iv, 10
%arrayidx = getelementptr inbounds [1024 x i8], ptr @GBytes, i64 0, i64 %i
store i8 0, ptr %arrayidx, align 2, !tbaa !15
br label %for.inc
for.inc: ; preds = %for.body
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
br label %for.cond, !llvm.loop !24
for.end: ; preds = %for.cond.cleanup
br label %for.cond2
for.cond2: ; preds = %for.inc9, %for.end
%indvars.iv2 = phi i64 [ %indvars.iv.next3, %for.inc9 ], [ 0, %for.end ]
%exitcond6 = icmp ne i64 %indvars.iv2, 10
br i1 %exitcond6, label %for.body5, label %for.cond.cleanup4
for.cond.cleanup4: ; preds = %for.cond2
br label %for.end11
for.body5: ; preds = %for.cond2
%i15 = mul nuw nsw i64 %indvars.iv2, 10
%i16 = or i64 %i15, 1
%arrayidx8 = getelementptr inbounds float, ptr @GBytes, i64 %i16
store float 0.000000e+00, ptr %arrayidx8, align 4, !tbaa !18
br label %for.inc9
for.inc9: ; preds = %for.body5
%indvars.iv.next3 = add nuw nsw i64 %indvars.iv2, 1
br label %for.cond2, !llvm.loop !25
for.end11: ; preds = %for.cond.cleanup4
br label %for.cond13
for.cond13: ; preds = %for.inc21, %for.end11
%indvars.iv7 = phi i64 [ %indvars.iv.next8, %for.inc21 ], [ 0, %for.end11 ]
%exitcond11 = icmp ne i64 %indvars.iv7, 20
br i1 %exitcond11, label %for.body16, label %for.cond.cleanup15
for.cond.cleanup15: ; preds = %for.cond13
br label %for.end23
for.body16: ; preds = %for.cond13
%i17 = mul nuw nsw i64 %indvars.iv7, 10
%i18 = add nuw nsw i64 %i17, 2
%arrayidx20 = getelementptr inbounds i64, ptr @GBytes, i64 %i18
store i64 0, ptr %arrayidx20, align 16, !tbaa !20
br label %for.inc21
for.inc21: ; preds = %for.body16
%indvars.iv.next8 = add nuw nsw i64 %indvars.iv7, 1
br label %for.cond13, !llvm.loop !26
for.end23: ; preds = %for.cond.cleanup15
store i8 0, ptr getelementptr inbounds ([1024 x i8], ptr @GBytes, i64 0, i64 1023), align 1, !tbaa !15
call void @write_arg(ptr getelementptr inbounds ([1024 x i8], ptr @GBytes, i64 0, i64 500), i32 0)
br label %for.cond25
for.cond25: ; preds = %for.inc33, %for.end23
%indvars.iv12 = phi i64 [ %indvars.iv.next13, %for.inc33 ], [ 0, %for.end23 ]
%exitcond14 = icmp ne i64 %indvars.iv12, 1024
br i1 %exitcond14, label %for.body28, label %for.cond.cleanup27
for.cond.cleanup27: ; preds = %for.cond25
br label %for.end35
for.body28: ; preds = %for.cond25
%arrayidx30 = getelementptr inbounds [1024 x i8], ptr @GBytes, i64 0, i64 %indvars.iv12
%i19 = load i8, ptr %arrayidx30, align 1, !tbaa !15
%arrayidx32 = getelementptr inbounds [1024 x i8], ptr @globalBytes, i64 0, i64 %indvars.iv12
store i8 %i19, ptr %arrayidx32, align 1, !tbaa !15
br label %for.inc33
for.inc33: ; preds = %for.body28
%indvars.iv.next13 = add nuw nsw i64 %indvars.iv12, 1
br label %for.cond25, !llvm.loop !27
for.end35: ; preds = %for.cond.cleanup27
ret void
}
; static int Flag3;
; int static_global_simplifiable_3() {
; Flag3 = 1;
; return Flag3;
; }
define i32 @static_global_simplifiable_3() {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; TUNIT-LABEL: define {{[^@]+}}@static_global_simplifiable_3
; TUNIT-SAME: () #[[ATTR5]] {
; TUNIT-NEXT: store i32 1, ptr @Flag3, align 4, !tbaa [[TBAA3]]
; TUNIT-NEXT: ret i32 1
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; CGSCC-LABEL: define {{[^@]+}}@static_global_simplifiable_3
; CGSCC-SAME: () #[[ATTR6]] {
; CGSCC-NEXT: store i32 1, ptr @Flag3, align 4, !tbaa [[TBAA3]]
; CGSCC-NEXT: ret i32 1
;
store i32 1, ptr @Flag3, align 4, !tbaa !3
%i = load i32, ptr @Flag3, align 4, !tbaa !3
ret i32 %i
}
; struct S noalias_arg_simplifiable_1(struct S s) {
; s.f1 = 1.1;
; s.f2 = 2.2;
; s.f3 = 3.3;
; write_arg(&s.i1, 1);
; write_arg(&s.i2, 2);
; write_arg(&s.i3, 3);
; struct S r;
; r.f1 = s.f1;
; r.f2 = s.f2 * 2;
; r.f3 = s.f3 + s.f1;
; r.i1 = s.i1;
; r.i2 = s.i2 * 2;
; r.i3 = s.i3 + s.i1;
; return r;
; }
;
define void @noalias_arg_simplifiable_1(ptr noalias sret(%struct.S) align 4 %agg.result, ptr byval(%struct.S) align 8 %s) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)
; TUNIT-LABEL: define {{[^@]+}}@noalias_arg_simplifiable_1
; TUNIT-SAME: (ptr noalias nocapture nofree writeonly sret([[STRUCT_S:%.*]]) align 4 dereferenceable_or_null(24) [[AGG_RESULT:%.*]], ptr noalias nocapture nofree nonnull byval([[STRUCT_S]]) align 8 dereferenceable(24) [[S:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[F1:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 3
; TUNIT-NEXT: store float 0x3FF19999A0000000, ptr [[F1]], align 4, !tbaa [[TBAA7]]
; TUNIT-NEXT: [[F2:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 4
; TUNIT-NEXT: store float 0x40019999A0000000, ptr [[F2]], align 8, !tbaa [[TBAA10]]
; TUNIT-NEXT: [[F3:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 5
; TUNIT-NEXT: store float 0x400A666660000000, ptr [[F3]], align 4, !tbaa [[TBAA11]]
; TUNIT-NEXT: call void @write_arg(ptr noalias nocapture nofree noundef nonnull writeonly align 8 dereferenceable(24) [[S]], i32 noundef 1) #[[ATTR18]]
; TUNIT-NEXT: [[I2:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 1
; TUNIT-NEXT: call void @write_arg(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(20) [[I2]], i32 noundef 2) #[[ATTR18]]
; TUNIT-NEXT: [[I3:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 2
; TUNIT-NEXT: call void @write_arg(ptr nocapture nofree noundef nonnull writeonly align 8 dereferenceable(16) [[I3]], i32 noundef 3) #[[ATTR18]]
; TUNIT-NEXT: [[F11:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 3
; TUNIT-NEXT: [[I:%.*]] = load float, ptr [[F11]], align 4, !tbaa [[TBAA7]]
; TUNIT-NEXT: [[F12:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 3
; TUNIT-NEXT: store float [[I]], ptr [[F12]], align 4, !tbaa [[TBAA7]]
; TUNIT-NEXT: [[F23:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 4
; TUNIT-NEXT: [[I4:%.*]] = load float, ptr [[F23]], align 8, !tbaa [[TBAA10]]
; TUNIT-NEXT: [[MUL:%.*]] = fmul float [[I4]], 2.000000e+00
; TUNIT-NEXT: [[F24:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 4
; TUNIT-NEXT: store float [[MUL]], ptr [[F24]], align 4, !tbaa [[TBAA10]]
; TUNIT-NEXT: [[F35:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 5
; TUNIT-NEXT: [[I5:%.*]] = load float, ptr [[F35]], align 4, !tbaa [[TBAA11]]
; TUNIT-NEXT: [[F16:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 3
; TUNIT-NEXT: [[I6:%.*]] = load float, ptr [[F16]], align 4, !tbaa [[TBAA7]]
; TUNIT-NEXT: [[ADD:%.*]] = fadd float [[I5]], [[I6]]
; TUNIT-NEXT: [[F37:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 5
; TUNIT-NEXT: store float [[ADD]], ptr [[F37]], align 4, !tbaa [[TBAA11]]
; TUNIT-NEXT: [[I7:%.*]] = load i32, ptr [[S]], align 8, !tbaa [[TBAA12]]
; TUNIT-NEXT: store i32 [[I7]], ptr [[AGG_RESULT]], align 4, !tbaa [[TBAA12]]
; TUNIT-NEXT: [[I210:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 1
; TUNIT-NEXT: [[I8:%.*]] = load i32, ptr [[I210]], align 4, !tbaa [[TBAA13]]
; TUNIT-NEXT: [[MUL11:%.*]] = shl nsw i32 [[I8]], 1
; TUNIT-NEXT: [[I212:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 1
; TUNIT-NEXT: store i32 [[MUL11]], ptr [[I212]], align 4, !tbaa [[TBAA13]]
; TUNIT-NEXT: [[I313:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 2
; TUNIT-NEXT: [[I9:%.*]] = load i32, ptr [[I313]], align 8, !tbaa [[TBAA14]]
; TUNIT-NEXT: [[I10:%.*]] = load i32, ptr [[S]], align 8, !tbaa [[TBAA12]]
; TUNIT-NEXT: [[ADD15:%.*]] = add nsw i32 [[I9]], [[I10]]
; TUNIT-NEXT: [[I316:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 2
; TUNIT-NEXT: store i32 [[ADD15]], ptr [[I316]], align 4, !tbaa [[TBAA14]]
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: readwrite)
; CGSCC-LABEL: define {{[^@]+}}@noalias_arg_simplifiable_1
; CGSCC-SAME: (ptr noalias nocapture nofree noundef nonnull writeonly sret([[STRUCT_S:%.*]]) align 4 dereferenceable(24) [[AGG_RESULT:%.*]], ptr noalias nocapture nofree noundef nonnull byval([[STRUCT_S]]) align 8 dereferenceable(24) [[S:%.*]]) #[[ATTR1]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[F1:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 3
; CGSCC-NEXT: store float 0x3FF19999A0000000, ptr [[F1]], align 4, !tbaa [[TBAA7]]
; CGSCC-NEXT: [[F2:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 4
; CGSCC-NEXT: store float 0x40019999A0000000, ptr [[F2]], align 8, !tbaa [[TBAA10]]
; CGSCC-NEXT: [[F3:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 5
; CGSCC-NEXT: store float 0x400A666660000000, ptr [[F3]], align 4, !tbaa [[TBAA11]]
; CGSCC-NEXT: call void @write_arg(ptr noalias nocapture nofree noundef nonnull writeonly align 8 dereferenceable(24) [[S]], i32 noundef 1) #[[ATTR21]]
; CGSCC-NEXT: [[I2:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 1
; CGSCC-NEXT: call void @write_arg(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(20) [[I2]], i32 noundef 2) #[[ATTR21]]
; CGSCC-NEXT: [[I3:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 2
; CGSCC-NEXT: call void @write_arg(ptr nocapture nofree noundef nonnull writeonly align 8 dereferenceable(16) [[I3]], i32 noundef 3) #[[ATTR21]]
; CGSCC-NEXT: [[F11:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 3
; CGSCC-NEXT: [[I:%.*]] = load float, ptr [[F11]], align 4, !tbaa [[TBAA7]]
; CGSCC-NEXT: [[F12:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 3
; CGSCC-NEXT: store float [[I]], ptr [[F12]], align 4, !tbaa [[TBAA7]]
; CGSCC-NEXT: [[F23:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 4
; CGSCC-NEXT: [[I4:%.*]] = load float, ptr [[F23]], align 8, !tbaa [[TBAA10]]
; CGSCC-NEXT: [[MUL:%.*]] = fmul float [[I4]], 2.000000e+00
; CGSCC-NEXT: [[F24:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 4
; CGSCC-NEXT: store float [[MUL]], ptr [[F24]], align 4, !tbaa [[TBAA10]]
; CGSCC-NEXT: [[F35:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 5
; CGSCC-NEXT: [[I5:%.*]] = load float, ptr [[F35]], align 4, !tbaa [[TBAA11]]
; CGSCC-NEXT: [[F16:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 3
; CGSCC-NEXT: [[I6:%.*]] = load float, ptr [[F16]], align 4, !tbaa [[TBAA7]]
; CGSCC-NEXT: [[ADD:%.*]] = fadd float [[I5]], [[I6]]
; CGSCC-NEXT: [[F37:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 5
; CGSCC-NEXT: store float [[ADD]], ptr [[F37]], align 4, !tbaa [[TBAA11]]
; CGSCC-NEXT: [[I7:%.*]] = load i32, ptr [[S]], align 8, !tbaa [[TBAA12]]
; CGSCC-NEXT: store i32 [[I7]], ptr [[AGG_RESULT]], align 4, !tbaa [[TBAA12]]
; CGSCC-NEXT: [[I210:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 1
; CGSCC-NEXT: [[I8:%.*]] = load i32, ptr [[I210]], align 4, !tbaa [[TBAA13]]
; CGSCC-NEXT: [[MUL11:%.*]] = shl nsw i32 [[I8]], 1
; CGSCC-NEXT: [[I212:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 1
; CGSCC-NEXT: store i32 [[MUL11]], ptr [[I212]], align 4, !tbaa [[TBAA13]]
; CGSCC-NEXT: [[I313:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 2
; CGSCC-NEXT: [[I9:%.*]] = load i32, ptr [[I313]], align 8, !tbaa [[TBAA14]]
; CGSCC-NEXT: [[I10:%.*]] = load i32, ptr [[S]], align 8, !tbaa [[TBAA12]]
; CGSCC-NEXT: [[ADD15:%.*]] = add nsw i32 [[I9]], [[I10]]
; CGSCC-NEXT: [[I316:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[AGG_RESULT]], i64 0, i32 2
; CGSCC-NEXT: store i32 [[ADD15]], ptr [[I316]], align 4, !tbaa [[TBAA14]]
; CGSCC-NEXT: ret void
;
entry:
%f1 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 3
store float 0x3FF19999A0000000, ptr %f1, align 4, !tbaa !7
%f2 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 4
store float 0x40019999A0000000, ptr %f2, align 8, !tbaa !10
%f3 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 5
store float 0x400A666660000000, ptr %f3, align 4, !tbaa !11
call void @write_arg(ptr nonnull %s, i32 1)
%i2 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 1
call void @write_arg(ptr nonnull %i2, i32 2)
%i3 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 2
call void @write_arg(ptr nonnull %i3, i32 3)
%f11 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 3
%i = load float, ptr %f11, align 4, !tbaa !7
%f12 = getelementptr inbounds %struct.S, ptr %agg.result, i64 0, i32 3
store float %i, ptr %f12, align 4, !tbaa !7
%f23 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 4
%i4 = load float, ptr %f23, align 8, !tbaa !10
%mul = fmul float %i4, 2.000000e+00
%f24 = getelementptr inbounds %struct.S, ptr %agg.result, i64 0, i32 4
store float %mul, ptr %f24, align 4, !tbaa !10
%f35 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 5
%i5 = load float, ptr %f35, align 4, !tbaa !11
%f16 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 3
%i6 = load float, ptr %f16, align 4, !tbaa !7
%add = fadd float %i5, %i6
%f37 = getelementptr inbounds %struct.S, ptr %agg.result, i64 0, i32 5
store float %add, ptr %f37, align 4, !tbaa !11
%i7 = load i32, ptr %s, align 8, !tbaa !12
store i32 %i7, ptr %agg.result, align 4, !tbaa !12
%i210 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 1
%i8 = load i32, ptr %i210, align 4, !tbaa !13
%mul11 = shl nsw i32 %i8, 1
%i212 = getelementptr inbounds %struct.S, ptr %agg.result, i64 0, i32 1
store i32 %mul11, ptr %i212, align 4, !tbaa !13
%i313 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 2
%i9 = load i32, ptr %i313, align 8, !tbaa !14
%i10 = load i32, ptr %s, align 8, !tbaa !12
%add15 = add nsw i32 %i9, %i10
%i316 = getelementptr inbounds %struct.S, ptr %agg.result, i64 0, i32 2
store i32 %add15, ptr %i316, align 4, !tbaa !14
ret void
}
; void noalias_arg_simplifiable_2(char Bytes[1024]) {
; for (int i = 0; i < 100; ++i)
; Bytes[i * 10] = 0;
; for (int i = 0; i < 10; ++i)
; ((float *)Bytes)[i * 10 + 1] = 0;
; for (int i = 0; i < 20; ++i)
; ((long long int *)Bytes)[i * 10 + 2] = 0;
; Bytes[1023] = 0;
; write_arg((int *)&Bytes[500], 0);
; struct S R;
; for (int i = 0; i < 1024; ++i)
; globalBytes[i] = Bytes[i];
; }
;
define void @noalias_arg_simplifiable_2(ptr %Bytes) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@noalias_arg_simplifiable_2
; TUNIT-SAME: (ptr nocapture nofree [[BYTES:%.*]]) #[[ATTR3]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: br label [[FOR_COND:%.*]]
; TUNIT: for.cond:
; TUNIT-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[ENTRY:%.*]] ]
; TUNIT-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV]], 100
; TUNIT-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]]
; TUNIT: for.cond.cleanup:
; TUNIT-NEXT: br label [[FOR_END:%.*]]
; TUNIT: for.body:
; TUNIT-NEXT: [[I:%.*]] = mul nuw nsw i64 [[INDVARS_IV]], 10
; TUNIT-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[BYTES]], i64 [[I]]
; TUNIT-NEXT: store i8 0, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA19]]
; TUNIT-NEXT: br label [[FOR_INC]]
; TUNIT: for.inc:
; TUNIT-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
; TUNIT-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP25:![0-9]+]]
; TUNIT: for.end:
; TUNIT-NEXT: br label [[FOR_COND2:%.*]]
; TUNIT: for.cond2:
; TUNIT-NEXT: [[INDVARS_IV2:%.*]] = phi i64 [ [[INDVARS_IV_NEXT3:%.*]], [[FOR_INC9:%.*]] ], [ 0, [[FOR_END]] ]
; TUNIT-NEXT: [[EXITCOND6:%.*]] = icmp ne i64 [[INDVARS_IV2]], 10
; TUNIT-NEXT: br i1 [[EXITCOND6]], label [[FOR_BODY5:%.*]], label [[FOR_COND_CLEANUP4:%.*]]
; TUNIT: for.cond.cleanup4:
; TUNIT-NEXT: br label [[FOR_END11:%.*]]
; TUNIT: for.body5:
; TUNIT-NEXT: [[I16:%.*]] = mul nuw nsw i64 [[INDVARS_IV2]], 10
; TUNIT-NEXT: [[I17:%.*]] = or i64 [[I16]], 1
; TUNIT-NEXT: [[ARRAYIDX8:%.*]] = getelementptr inbounds float, ptr [[BYTES]], i64 [[I17]]
; TUNIT-NEXT: store float 0.000000e+00, ptr [[ARRAYIDX8]], align 4, !tbaa [[TBAA26:![0-9]+]]
; TUNIT-NEXT: br label [[FOR_INC9]]
; TUNIT: for.inc9:
; TUNIT-NEXT: [[INDVARS_IV_NEXT3]] = add nuw nsw i64 [[INDVARS_IV2]], 1
; TUNIT-NEXT: br label [[FOR_COND2]], !llvm.loop [[LOOP27:![0-9]+]]
; TUNIT: for.end11:
; TUNIT-NEXT: br label [[FOR_COND13:%.*]]
; TUNIT: for.cond13:
; TUNIT-NEXT: [[INDVARS_IV7:%.*]] = phi i64 [ [[INDVARS_IV_NEXT8:%.*]], [[FOR_INC21:%.*]] ], [ 0, [[FOR_END11]] ]
; TUNIT-NEXT: [[EXITCOND11:%.*]] = icmp ne i64 [[INDVARS_IV7]], 20
; TUNIT-NEXT: br i1 [[EXITCOND11]], label [[FOR_BODY16:%.*]], label [[FOR_COND_CLEANUP15:%.*]]
; TUNIT: for.cond.cleanup15:
; TUNIT-NEXT: br label [[FOR_END23:%.*]]
; TUNIT: for.body16:
; TUNIT-NEXT: [[I19:%.*]] = mul nuw nsw i64 [[INDVARS_IV7]], 10
; TUNIT-NEXT: [[I20:%.*]] = add nuw nsw i64 [[I19]], 2
; TUNIT-NEXT: [[ARRAYIDX20:%.*]] = getelementptr inbounds i64, ptr [[BYTES]], i64 [[I20]]
; TUNIT-NEXT: store i64 0, ptr [[ARRAYIDX20]], align 8, !tbaa [[TBAA28:![0-9]+]]
; TUNIT-NEXT: br label [[FOR_INC21]]
; TUNIT: for.inc21:
; TUNIT-NEXT: [[INDVARS_IV_NEXT8]] = add nuw nsw i64 [[INDVARS_IV7]], 1
; TUNIT-NEXT: br label [[FOR_COND13]], !llvm.loop [[LOOP30:![0-9]+]]
; TUNIT: for.end23:
; TUNIT-NEXT: [[ARRAYIDX24:%.*]] = getelementptr inbounds i8, ptr [[BYTES]], i64 1023
; TUNIT-NEXT: store i8 0, ptr [[ARRAYIDX24]], align 1, !tbaa [[TBAA19]]
; TUNIT-NEXT: [[ARRAYIDX25:%.*]] = getelementptr inbounds i8, ptr [[BYTES]], i64 500
; TUNIT-NEXT: call void @write_arg(ptr nocapture nofree noundef nonnull writeonly align 4 [[ARRAYIDX25]], i32 noundef 0) #[[ATTR18]]
; TUNIT-NEXT: br label [[FOR_COND27:%.*]]
; TUNIT: for.cond27:
; TUNIT-NEXT: [[INDVARS_IV12:%.*]] = phi i64 [ [[INDVARS_IV_NEXT13:%.*]], [[FOR_INC35:%.*]] ], [ 0, [[FOR_END23]] ]
; TUNIT-NEXT: [[EXITCOND14:%.*]] = icmp ne i64 [[INDVARS_IV12]], 1024
; TUNIT-NEXT: br i1 [[EXITCOND14]], label [[FOR_BODY30:%.*]], label [[FOR_COND_CLEANUP29:%.*]]
; TUNIT: for.cond.cleanup29:
; TUNIT-NEXT: br label [[FOR_END37:%.*]]
; TUNIT: for.body30:
; TUNIT-NEXT: [[ARRAYIDX32:%.*]] = getelementptr inbounds i8, ptr [[BYTES]], i64 [[INDVARS_IV12]]
; TUNIT-NEXT: [[I22:%.*]] = load i8, ptr [[ARRAYIDX32]], align 1, !tbaa [[TBAA19]]
; TUNIT-NEXT: [[ARRAYIDX34:%.*]] = getelementptr inbounds [1024 x i8], ptr @globalBytes, i64 0, i64 [[INDVARS_IV12]]
; TUNIT-NEXT: store i8 [[I22]], ptr [[ARRAYIDX34]], align 1, !tbaa [[TBAA19]]
; TUNIT-NEXT: br label [[FOR_INC35]]
; TUNIT: for.inc35:
; TUNIT-NEXT: [[INDVARS_IV_NEXT13]] = add nuw nsw i64 [[INDVARS_IV12]], 1
; TUNIT-NEXT: br label [[FOR_COND27]], !llvm.loop [[LOOP31:![0-9]+]]
; TUNIT: for.end37:
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@noalias_arg_simplifiable_2
; CGSCC-SAME: (ptr nocapture nofree [[BYTES:%.*]]) #[[ATTR3]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: br label [[FOR_COND:%.*]]
; CGSCC: for.cond:
; CGSCC-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[ENTRY:%.*]] ]
; CGSCC-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV]], 100
; CGSCC-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]]
; CGSCC: for.cond.cleanup:
; CGSCC-NEXT: br label [[FOR_END:%.*]]
; CGSCC: for.body:
; CGSCC-NEXT: [[I:%.*]] = mul nuw nsw i64 [[INDVARS_IV]], 10
; CGSCC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[BYTES]], i64 [[I]]
; CGSCC-NEXT: store i8 0, ptr [[ARRAYIDX]], align 1, !tbaa [[TBAA15]]
; CGSCC-NEXT: br label [[FOR_INC]]
; CGSCC: for.inc:
; CGSCC-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
; CGSCC-NEXT: br label [[FOR_COND]], !llvm.loop [[LOOP28:![0-9]+]]
; CGSCC: for.end:
; CGSCC-NEXT: br label [[FOR_COND2:%.*]]
; CGSCC: for.cond2:
; CGSCC-NEXT: [[INDVARS_IV2:%.*]] = phi i64 [ [[INDVARS_IV_NEXT3:%.*]], [[FOR_INC9:%.*]] ], [ 0, [[FOR_END]] ]
; CGSCC-NEXT: [[EXITCOND6:%.*]] = icmp ne i64 [[INDVARS_IV2]], 10
; CGSCC-NEXT: br i1 [[EXITCOND6]], label [[FOR_BODY5:%.*]], label [[FOR_COND_CLEANUP4:%.*]]
; CGSCC: for.cond.cleanup4:
; CGSCC-NEXT: br label [[FOR_END11:%.*]]
; CGSCC: for.body5:
; CGSCC-NEXT: [[I16:%.*]] = mul nuw nsw i64 [[INDVARS_IV2]], 10
; CGSCC-NEXT: [[I17:%.*]] = or i64 [[I16]], 1
; CGSCC-NEXT: [[ARRAYIDX8:%.*]] = getelementptr inbounds float, ptr [[BYTES]], i64 [[I17]]
; CGSCC-NEXT: store float 0.000000e+00, ptr [[ARRAYIDX8]], align 4, !tbaa [[TBAA18]]
; CGSCC-NEXT: br label [[FOR_INC9]]
; CGSCC: for.inc9:
; CGSCC-NEXT: [[INDVARS_IV_NEXT3]] = add nuw nsw i64 [[INDVARS_IV2]], 1
; CGSCC-NEXT: br label [[FOR_COND2]], !llvm.loop [[LOOP29:![0-9]+]]
; CGSCC: for.end11:
; CGSCC-NEXT: br label [[FOR_COND13:%.*]]
; CGSCC: for.cond13:
; CGSCC-NEXT: [[INDVARS_IV7:%.*]] = phi i64 [ [[INDVARS_IV_NEXT8:%.*]], [[FOR_INC21:%.*]] ], [ 0, [[FOR_END11]] ]
; CGSCC-NEXT: [[EXITCOND11:%.*]] = icmp ne i64 [[INDVARS_IV7]], 20
; CGSCC-NEXT: br i1 [[EXITCOND11]], label [[FOR_BODY16:%.*]], label [[FOR_COND_CLEANUP15:%.*]]
; CGSCC: for.cond.cleanup15:
; CGSCC-NEXT: br label [[FOR_END23:%.*]]
; CGSCC: for.body16:
; CGSCC-NEXT: [[I19:%.*]] = mul nuw nsw i64 [[INDVARS_IV7]], 10
; CGSCC-NEXT: [[I20:%.*]] = add nuw nsw i64 [[I19]], 2
; CGSCC-NEXT: [[ARRAYIDX20:%.*]] = getelementptr inbounds i64, ptr [[BYTES]], i64 [[I20]]
; CGSCC-NEXT: store i64 0, ptr [[ARRAYIDX20]], align 8, !tbaa [[TBAA20]]
; CGSCC-NEXT: br label [[FOR_INC21]]
; CGSCC: for.inc21:
; CGSCC-NEXT: [[INDVARS_IV_NEXT8]] = add nuw nsw i64 [[INDVARS_IV7]], 1
; CGSCC-NEXT: br label [[FOR_COND13]], !llvm.loop [[LOOP30:![0-9]+]]
; CGSCC: for.end23:
; CGSCC-NEXT: [[ARRAYIDX24:%.*]] = getelementptr inbounds i8, ptr [[BYTES]], i64 1023
; CGSCC-NEXT: store i8 0, ptr [[ARRAYIDX24]], align 1, !tbaa [[TBAA15]]
; CGSCC-NEXT: [[ARRAYIDX25:%.*]] = getelementptr inbounds i8, ptr [[BYTES]], i64 500
; CGSCC-NEXT: call void @write_arg(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[ARRAYIDX25]], i32 noundef 0) #[[ATTR21]]
; CGSCC-NEXT: br label [[FOR_COND27:%.*]]
; CGSCC: for.cond27:
; CGSCC-NEXT: [[INDVARS_IV12:%.*]] = phi i64 [ [[INDVARS_IV_NEXT13:%.*]], [[FOR_INC35:%.*]] ], [ 0, [[FOR_END23]] ]
; CGSCC-NEXT: [[EXITCOND14:%.*]] = icmp ne i64 [[INDVARS_IV12]], 1024
; CGSCC-NEXT: br i1 [[EXITCOND14]], label [[FOR_BODY30:%.*]], label [[FOR_COND_CLEANUP29:%.*]]
; CGSCC: for.cond.cleanup29:
; CGSCC-NEXT: br label [[FOR_END37:%.*]]
; CGSCC: for.body30:
; CGSCC-NEXT: [[ARRAYIDX32:%.*]] = getelementptr inbounds i8, ptr [[BYTES]], i64 [[INDVARS_IV12]]
; CGSCC-NEXT: [[I22:%.*]] = load i8, ptr [[ARRAYIDX32]], align 1, !tbaa [[TBAA15]]
; CGSCC-NEXT: [[ARRAYIDX34:%.*]] = getelementptr inbounds [1024 x i8], ptr @globalBytes, i64 0, i64 [[INDVARS_IV12]]
; CGSCC-NEXT: store i8 [[I22]], ptr [[ARRAYIDX34]], align 1, !tbaa [[TBAA15]]
; CGSCC-NEXT: br label [[FOR_INC35]]
; CGSCC: for.inc35:
; CGSCC-NEXT: [[INDVARS_IV_NEXT13]] = add nuw nsw i64 [[INDVARS_IV12]], 1
; CGSCC-NEXT: br label [[FOR_COND27]], !llvm.loop [[LOOP31:![0-9]+]]
; CGSCC: for.end37:
; CGSCC-NEXT: ret void
;
entry:
br label %for.cond
for.cond: ; preds = %for.inc, %entry
%indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
%exitcond = icmp ne i64 %indvars.iv, 100
br i1 %exitcond, label %for.body, label %for.cond.cleanup
for.cond.cleanup: ; preds = %for.cond
br label %for.end
for.body: ; preds = %for.cond
%i = mul nuw nsw i64 %indvars.iv, 10
%arrayidx = getelementptr inbounds i8, ptr %Bytes, i64 %i
store i8 0, ptr %arrayidx, align 1, !tbaa !15
br label %for.inc
for.inc: ; preds = %for.body
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
br label %for.cond, !llvm.loop !28
for.end: ; preds = %for.cond.cleanup
br label %for.cond2
for.cond2: ; preds = %for.inc9, %for.end
%indvars.iv2 = phi i64 [ %indvars.iv.next3, %for.inc9 ], [ 0, %for.end ]
%exitcond6 = icmp ne i64 %indvars.iv2, 10
br i1 %exitcond6, label %for.body5, label %for.cond.cleanup4
for.cond.cleanup4: ; preds = %for.cond2
br label %for.end11
for.body5: ; preds = %for.cond2
%i16 = mul nuw nsw i64 %indvars.iv2, 10
%i17 = or i64 %i16, 1
%arrayidx8 = getelementptr inbounds float, ptr %Bytes, i64 %i17
store float 0.000000e+00, ptr %arrayidx8, align 4, !tbaa !18
br label %for.inc9
for.inc9: ; preds = %for.body5
%indvars.iv.next3 = add nuw nsw i64 %indvars.iv2, 1
br label %for.cond2, !llvm.loop !29
for.end11: ; preds = %for.cond.cleanup4
br label %for.cond13
for.cond13: ; preds = %for.inc21, %for.end11
%indvars.iv7 = phi i64 [ %indvars.iv.next8, %for.inc21 ], [ 0, %for.end11 ]
%exitcond11 = icmp ne i64 %indvars.iv7, 20
br i1 %exitcond11, label %for.body16, label %for.cond.cleanup15
for.cond.cleanup15: ; preds = %for.cond13
br label %for.end23
for.body16: ; preds = %for.cond13
%i19 = mul nuw nsw i64 %indvars.iv7, 10
%i20 = add nuw nsw i64 %i19, 2
%arrayidx20 = getelementptr inbounds i64, ptr %Bytes, i64 %i20
store i64 0, ptr %arrayidx20, align 8, !tbaa !20
br label %for.inc21
for.inc21: ; preds = %for.body16
%indvars.iv.next8 = add nuw nsw i64 %indvars.iv7, 1
br label %for.cond13, !llvm.loop !30
for.end23: ; preds = %for.cond.cleanup15
%arrayidx24 = getelementptr inbounds i8, ptr %Bytes, i64 1023
store i8 0, ptr %arrayidx24, align 1, !tbaa !15
%arrayidx25 = getelementptr inbounds i8, ptr %Bytes, i64 500
call void @write_arg(ptr nonnull %arrayidx25, i32 0)
br label %for.cond27
for.cond27: ; preds = %for.inc35, %for.end23
%indvars.iv12 = phi i64 [ %indvars.iv.next13, %for.inc35 ], [ 0, %for.end23 ]
%exitcond14 = icmp ne i64 %indvars.iv12, 1024
br i1 %exitcond14, label %for.body30, label %for.cond.cleanup29
for.cond.cleanup29: ; preds = %for.cond27
br label %for.end37
for.body30: ; preds = %for.cond27
%arrayidx32 = getelementptr inbounds i8, ptr %Bytes, i64 %indvars.iv12
%i22 = load i8, ptr %arrayidx32, align 1, !tbaa !15
%arrayidx34 = getelementptr inbounds [1024 x i8], ptr @globalBytes, i64 0, i64 %indvars.iv12
store i8 %i22, ptr %arrayidx34, align 1, !tbaa !15
br label %for.inc35
for.inc35: ; preds = %for.body30
%indvars.iv.next13 = add nuw nsw i64 %indvars.iv12, 1
br label %for.cond27, !llvm.loop !31
for.end37: ; preds = %for.cond.cleanup29
ret void
}
; int local_alloca_not_simplifiable_1() {
; int X, Y, Z;
; X = Y = 1;
; escape(&X);
; write_random(&Y);
; Z = X ? 1 : 2;
; return X + Y + Z;
; }
;
define i32 @local_alloca_not_simplifiable_1() {
; TUNIT-LABEL: define {{[^@]+}}@local_alloca_not_simplifiable_1() {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[X:%.*]] = alloca i32, align 4
; TUNIT-NEXT: [[Y:%.*]] = alloca i32, align 4
; TUNIT-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 4, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[X]]) #[[ATTR17]]
; TUNIT-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 4, ptr noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[Y]]) #[[ATTR17]]
; TUNIT-NEXT: store i32 1, ptr [[Y]], align 4, !tbaa [[TBAA3]]
; TUNIT-NEXT: store i32 1, ptr [[X]], align 4, !tbaa [[TBAA3]]
; TUNIT-NEXT: call void @escape(ptr noundef nonnull align 4 dereferenceable(4) [[X]])
; TUNIT-NEXT: call void @write_random(ptr noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[Y]])
; TUNIT-NEXT: [[I3:%.*]] = load i32, ptr [[X]], align 4, !tbaa [[TBAA3]]
; TUNIT-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[I3]], 0
; TUNIT-NEXT: [[COND:%.*]] = select i1 [[TOBOOL_NOT]], i32 2, i32 1
; TUNIT-NEXT: [[I4:%.*]] = load i32, ptr [[Y]], align 4, !tbaa [[TBAA3]]
; TUNIT-NEXT: [[ADD:%.*]] = add nsw i32 [[I3]], [[I4]]
; TUNIT-NEXT: [[ADD1:%.*]] = add nsw i32 [[ADD]], [[COND]]
; TUNIT-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 4, ptr noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[Y]])
; TUNIT-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 4, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[X]])
; TUNIT-NEXT: ret i32 [[ADD1]]
;
; CGSCC-LABEL: define {{[^@]+}}@local_alloca_not_simplifiable_1() {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[X:%.*]] = alloca i32, align 4
; CGSCC-NEXT: [[Y:%.*]] = alloca i32, align 4
; CGSCC-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 4, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[X]]) #[[ATTR20]]
; CGSCC-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 4, ptr noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[Y]]) #[[ATTR20]]
; CGSCC-NEXT: store i32 1, ptr [[Y]], align 4, !tbaa [[TBAA3]]
; CGSCC-NEXT: store i32 1, ptr [[X]], align 4, !tbaa [[TBAA3]]
; CGSCC-NEXT: call void @escape(ptr noundef nonnull align 4 dereferenceable(4) [[X]])
; CGSCC-NEXT: call void @write_random(ptr noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[Y]])
; CGSCC-NEXT: [[I3:%.*]] = load i32, ptr [[X]], align 4, !tbaa [[TBAA3]]
; CGSCC-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[I3]], 0
; CGSCC-NEXT: [[COND:%.*]] = select i1 [[TOBOOL_NOT]], i32 2, i32 1
; CGSCC-NEXT: [[I4:%.*]] = load i32, ptr [[Y]], align 4, !tbaa [[TBAA3]]
; CGSCC-NEXT: [[ADD:%.*]] = add nsw i32 [[I3]], [[I4]]
; CGSCC-NEXT: [[ADD1:%.*]] = add nsw i32 [[ADD]], [[COND]]
; CGSCC-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 4, ptr noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[Y]])
; CGSCC-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 4, ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[X]])
; CGSCC-NEXT: ret i32 [[ADD1]]
;
entry:
%X = alloca i32, align 4
%Y = alloca i32, align 4
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %X)
call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %Y)
store i32 1, ptr %Y, align 4, !tbaa !3
store i32 1, ptr %X, align 4, !tbaa !3
call void @escape(ptr nonnull %X)
call void @write_random(ptr nonnull %Y)
%i3 = load i32, ptr %X, align 4, !tbaa !3
%tobool.not = icmp eq i32 %i3, 0
%cond = select i1 %tobool.not, i32 2, i32 1
%i4 = load i32, ptr %Y, align 4, !tbaa !3
%add = add nsw i32 %i3, %i4
%add1 = add nsw i32 %add, %cond
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %Y)
call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %X)
ret i32 %add1
}
define i8 @local_alloca_not_simplifiable_2(i64 %index1, i64 %index2, i1 %cnd) {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CHECK-LABEL: define {{[^@]+}}@local_alloca_not_simplifiable_2
; CHECK-SAME: (i64 [[INDEX1:%.*]], i64 [[INDEX2:%.*]], i1 noundef [[CND:%.*]]) #[[ATTR4]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16
; CHECK-NEXT: store i8 7, ptr [[BYTES]], align 16
; CHECK-NEXT: br i1 [[CND]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
; CHECK: left:
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 [[INDEX1]]
; CHECK-NEXT: br label [[JOIN:%.*]]
; CHECK: right:
; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 [[INDEX2]]
; CHECK-NEXT: br label [[JOIN]]
; CHECK: join:
; CHECK-NEXT: [[GEP_JOIN:%.*]] = phi ptr [ [[GEP1]], [[LEFT]] ], [ [[GEP2]], [[RIGHT]] ]
; CHECK-NEXT: store i8 9, ptr [[GEP_JOIN]], align 4
; CHECK-NEXT: [[I:%.*]] = load i8, ptr [[BYTES]], align 16
; CHECK-NEXT: ret i8 [[I]]
;
entry:
%Bytes = alloca [1024 x i8], align 16
store i8 7, ptr %Bytes, align 4
br i1 %cnd, label %left, label %right
left: ; preds = %entry
%gep1 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 %index1
br label %join
right: ; preds = %entry
%gep2 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 %index2
br label %join
join: ; preds = %right, %left
%gep.join = phi ptr [ %gep1, %left ], [ %gep2, %right ]
store i8 9, ptr %gep.join, align 4
; This load cannot be replaced by the value 7 from %entry, since the previous
; store interferes due to its unknown offset.
%i = load i8, ptr %Bytes, align 4
ret i8 %i
}
; We could simplify these if we separate accessed bins wrt. alignment (here mod 4).
define i32 @unknown_access_mixed_simplifiable(i32 %arg1, i32 %arg2) {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CHECK-LABEL: define {{[^@]+}}@unknown_access_mixed_simplifiable
; CHECK-SAME: (i32 [[ARG1:%.*]], i32 [[ARG2:%.*]]) #[[ATTR4]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_S:%.*]], align 4
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 2
; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i32, ptr [[S]], i32 [[ARG1]]
; CHECK-NEXT: [[GEP3:%.*]] = getelementptr inbounds i32, ptr [[S]], i32 [[ARG2]]
; CHECK-NEXT: store i32 7, ptr [[GEP1]], align 4
; CHECK-NEXT: store i32 7, ptr [[GEP2]], align 4
; CHECK-NEXT: store i32 7, ptr [[GEP3]], align 4
; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[GEP1]], align 4
; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[GEP2]], align 4
; CHECK-NEXT: [[L3:%.*]] = load i32, ptr [[GEP3]], align 4
; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[L1]], [[L2]]
; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[ADD1]], [[L3]]
; CHECK-NEXT: ret i32 [[ADD2]]
;
entry:
%s = alloca %struct.S, align 4
%gep1 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 2
%gep2 = getelementptr inbounds i32, ptr %s, i32 %arg1
%gep3 = getelementptr inbounds i32, ptr %s, i32 %arg2
store i32 7, ptr %gep1
store i32 7, ptr %gep2
store i32 7, ptr %gep3
%l1 = load i32, ptr %gep1
%l2 = load i32, ptr %gep2
%l3 = load i32, ptr %gep3
%add1 = add i32 %l1, %l2
%add2 = add i32 %add1, %l3
ret i32 %add2
}
; The access to bc4b could go anywhere, nothing is simplifiable.
define i32 @unknown_access_mixed_not_simplifiable(i32 %arg1, i32 %arg2, i32 %arg3) {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CHECK-LABEL: define {{[^@]+}}@unknown_access_mixed_not_simplifiable
; CHECK-SAME: (i32 [[ARG1:%.*]], i32 [[ARG2:%.*]], i32 [[ARG3:%.*]]) #[[ATTR4]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_S:%.*]], align 4
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[S]], i64 0, i32 2
; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i32, ptr [[S]], i32 [[ARG1]]
; CHECK-NEXT: [[GEP3:%.*]] = getelementptr inbounds i32, ptr [[S]], i32 [[ARG2]]
; CHECK-NEXT: [[GEP4:%.*]] = getelementptr inbounds i8, ptr [[S]], i32 [[ARG3]]
; CHECK-NEXT: store i32 7, ptr [[GEP1]], align 4
; CHECK-NEXT: store i32 7, ptr [[GEP2]], align 4
; CHECK-NEXT: store i32 7, ptr [[GEP3]], align 4
; CHECK-NEXT: store i32 7, ptr [[GEP4]], align 4
; CHECK-NEXT: [[L1:%.*]] = load i32, ptr [[GEP1]], align 4
; CHECK-NEXT: [[L2:%.*]] = load i32, ptr [[GEP2]], align 4
; CHECK-NEXT: [[L3:%.*]] = load i32, ptr [[GEP3]], align 4
; CHECK-NEXT: [[L4:%.*]] = load i32, ptr [[GEP4]], align 4
; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[L1]], [[L2]]
; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[ADD1]], [[L3]]
; CHECK-NEXT: [[ADD3:%.*]] = add i32 [[ADD2]], [[L4]]
; CHECK-NEXT: ret i32 [[ADD3]]
;
entry:
%s = alloca %struct.S, align 4
%gep1 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 2
%gep2 = getelementptr inbounds i32, ptr %s, i32 %arg1
%gep3 = getelementptr inbounds i32, ptr %s, i32 %arg2
%gep4 = getelementptr inbounds i8, ptr %s, i32 %arg3
store i32 7, ptr %gep1
store i32 7, ptr %gep2
store i32 7, ptr %gep3
store i32 7, ptr %gep4
%l1 = load i32, ptr %gep1
%l2 = load i32, ptr %gep2
%l3 = load i32, ptr %gep3
%l4 = load i32, ptr %gep4
%add1 = add i32 %l1, %l2
%add2 = add i32 %add1, %l3
%add3 = add i32 %add2, %l4
ret i32 %add3
}
declare void @escape(ptr)
; int Flag0 = 0;
; int global_not_simplifiable_1(int cnd) {
; return Flag0;
; }
;
define i32 @global_not_simplifiable_1(i32 %cnd) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read)
; TUNIT-LABEL: define {{[^@]+}}@global_not_simplifiable_1
; TUNIT-SAME: (i32 [[CND:%.*]]) #[[ATTR6:[0-9]+]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[I:%.*]] = load i32, ptr @Flag0, align 4, !tbaa [[TBAA3]]
; TUNIT-NEXT: ret i32 [[I]]
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read)
; CGSCC-LABEL: define {{[^@]+}}@global_not_simplifiable_1
; CGSCC-SAME: (i32 [[CND:%.*]]) #[[ATTR7:[0-9]+]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[I:%.*]] = load i32, ptr @Flag0, align 4, !tbaa [[TBAA3]]
; CGSCC-NEXT: ret i32 [[I]]
;
entry:
%i = load i32, ptr @Flag0, align 4, !tbaa !3
ret i32 %i
}
; static int Flag1 __attribute__((loader_uninitialized));
; int static_global_not_simplifiable_1(int cnd) {
; int v = Flag1;
; sync();
; if (cnd)
; Flag1 = 1;
; return v;
; }
;
define i32 @static_global_not_simplifiable_1(i32 %cnd) {
; CHECK-LABEL: define {{[^@]+}}@static_global_not_simplifiable_1
; CHECK-SAME: (i32 [[CND:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: call void @sync()
; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[CND]], 0
; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
; CHECK: if.then:
; CHECK-NEXT: br label [[IF_END]]
; CHECK: if.end:
; CHECK-NEXT: ret i32 1
;
entry:
%i = load i32, ptr @Flag1, align 4, !tbaa !3
call void @sync()
%tobool.not = icmp eq i32 %cnd, 0
br i1 %tobool.not, label %if.end, label %if.then
if.then: ; preds = %entry
store i32 1, ptr @Flag1, align 4, !tbaa !3
br label %if.end
if.end: ; preds = %if.then, %entry
ret i32 %i
}
declare void @sync()
; static int Flag2 __attribute__((loader_uninitialized));
; int static_global_simplifiable_4(int cnd) {
; Flag2 = 1;
; sync();
; int v = Flag2;
; Flag2 = 2;
; return v;
; }
define i32 @static_global_simplifiable_4(i32 %cnd) {
; CHECK-LABEL: define {{[^@]+}}@static_global_simplifiable_4
; CHECK-SAME: (i32 [[CND:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: store i32 1, ptr @Flag2, align 4, !tbaa [[TBAA3]]
; CHECK-NEXT: call void @sync()
; CHECK-NEXT: [[I:%.*]] = load i32, ptr @Flag2, align 4, !tbaa [[TBAA3]]
; CHECK-NEXT: store i32 2, ptr @Flag2, align 4, !tbaa [[TBAA3]]
; CHECK-NEXT: ret i32 [[I]]
;
entry:
store i32 1, ptr @Flag2, align 4, !tbaa !3
call void @sync()
%i = load i32, ptr @Flag2, align 4, !tbaa !3
store i32 2, ptr @Flag2, align 4, !tbaa !3
ret i32 %i
}
; static int Flag2 __attribute__((loader_uninitialized));
; int static_global_not_simplifiable_2(int cnd) {
; Flag2 = 1;
; sync();
; int v = Flag2;
; Flag2 = 2;
; return v;
; }
define i32 @static_global_not_simplifiable_2(i32 %cnd) {
; TUNIT-LABEL: define {{[^@]+}}@static_global_not_simplifiable_2
; TUNIT-SAME: (i32 [[CND:%.*]]) {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: store i32 1, ptr @Flag4, align 4, !tbaa [[TBAA3]]
; TUNIT-NEXT: call void @sync() #[[ATTR19:[0-9]+]]
; TUNIT-NEXT: [[I:%.*]] = load i32, ptr @Flag4, align 4, !tbaa [[TBAA3]]
; TUNIT-NEXT: store i32 2, ptr @Flag4, align 4, !tbaa [[TBAA3]]
; TUNIT-NEXT: ret i32 [[I]]
;
; CGSCC-LABEL: define {{[^@]+}}@static_global_not_simplifiable_2
; CGSCC-SAME: (i32 [[CND:%.*]]) {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: store i32 1, ptr @Flag4, align 4, !tbaa [[TBAA3]]
; CGSCC-NEXT: call void @sync() #[[ATTR22:[0-9]+]]
; CGSCC-NEXT: [[I:%.*]] = load i32, ptr @Flag4, align 4, !tbaa [[TBAA3]]
; CGSCC-NEXT: store i32 2, ptr @Flag4, align 4, !tbaa [[TBAA3]]
; CGSCC-NEXT: ret i32 [[I]]
;
entry:
store i32 1, ptr @Flag4, align 4, !tbaa !3
call void @sync() nocallback
%i = load i32, ptr @Flag4, align 4, !tbaa !3
store i32 2, ptr @Flag4, align 4, !tbaa !3
ret i32 %i
}
define void @static_global_not_simplifiable_2_helper() {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; TUNIT-LABEL: define {{[^@]+}}@static_global_not_simplifiable_2_helper
; TUNIT-SAME: () #[[ATTR5]] {
; TUNIT-NEXT: store i32 2, ptr @Flag4, align 4, !tbaa [[TBAA3]]
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; CGSCC-LABEL: define {{[^@]+}}@static_global_not_simplifiable_2_helper
; CGSCC-SAME: () #[[ATTR6]] {
; CGSCC-NEXT: store i32 2, ptr @Flag4, align 4, !tbaa [[TBAA3]]
; CGSCC-NEXT: ret void
;
store i32 2, ptr @Flag4, align 4, !tbaa !3
ret void
}
; Similiar to static_global_simplifiable_3 but with a may-store.
define i32 @static_global_not_simplifiable_3(i1 %c, ptr %p) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@static_global_not_simplifiable_3
; TUNIT-SAME: (i1 [[C:%.*]], ptr nocapture nofree writeonly [[P:%.*]]) #[[ATTR3]] {
; TUNIT-NEXT: [[SEL:%.*]] = select i1 [[C]], ptr @Flag3, ptr [[P]]
; TUNIT-NEXT: store i32 1, ptr [[SEL]], align 4, !tbaa [[TBAA3]]
; TUNIT-NEXT: [[I:%.*]] = load i32, ptr @Flag3, align 4, !tbaa [[TBAA3]]
; TUNIT-NEXT: ret i32 [[I]]
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@static_global_not_simplifiable_3
; CGSCC-SAME: (i1 [[C:%.*]], ptr nocapture nofree writeonly [[P:%.*]]) #[[ATTR5]] {
; CGSCC-NEXT: [[SEL:%.*]] = select i1 [[C]], ptr @Flag3, ptr [[P]]
; CGSCC-NEXT: store i32 1, ptr [[SEL]], align 4, !tbaa [[TBAA3]]
; CGSCC-NEXT: [[I:%.*]] = load i32, ptr @Flag3, align 4, !tbaa [[TBAA3]]
; CGSCC-NEXT: ret i32 [[I]]
;
%sel = select i1 %c, ptr @Flag3, ptr %p
store i32 1, ptr %sel, align 4, !tbaa !3
%i = load i32, ptr @Flag3, align 4, !tbaa !3
ret i32 %i
}
; int write_read{,_static,_static_undef}_global(void) {
; Gint{,static,_static_undef}1 = 7;
; return Gint1;
; }
; void write{,_static,_static_undef}_global(void) {
; Gint{,static,_static_undef}2 = 7;
; }
; int read{,_static,_static_undef}_global(void) {
; return Gint{,static,_static_undef}2;
; }
;
; FIXME: We could replace these loads.
define i32 @write_read_global() {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@write_read_global
; TUNIT-SAME: () #[[ATTR3]] {
; TUNIT-NEXT: store i32 7, ptr @Gint1, align 4
; TUNIT-NEXT: [[L:%.*]] = load i32, ptr @Gint1, align 4
; TUNIT-NEXT: ret i32 [[L]]
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@write_read_global
; CGSCC-SAME: () #[[ATTR5]] {
; CGSCC-NEXT: store i32 7, ptr @Gint1, align 4
; CGSCC-NEXT: [[L:%.*]] = load i32, ptr @Gint1, align 4
; CGSCC-NEXT: ret i32 [[L]]
;
store i32 7, ptr @Gint1
%l = load i32, ptr @Gint1
ret i32 %l
}
define void @write_global() {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; TUNIT-LABEL: define {{[^@]+}}@write_global
; TUNIT-SAME: () #[[ATTR5]] {
; TUNIT-NEXT: store i32 7, ptr @Gint2, align 4
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; CGSCC-LABEL: define {{[^@]+}}@write_global
; CGSCC-SAME: () #[[ATTR6]] {
; CGSCC-NEXT: store i32 7, ptr @Gint2, align 4
; CGSCC-NEXT: ret void
;
store i32 7, ptr @Gint2
ret void
}
define i32 @read_global() {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read)
; TUNIT-LABEL: define {{[^@]+}}@read_global
; TUNIT-SAME: () #[[ATTR6]] {
; TUNIT-NEXT: [[L:%.*]] = load i32, ptr @Gint2, align 4
; TUNIT-NEXT: ret i32 [[L]]
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read)
; CGSCC-LABEL: define {{[^@]+}}@read_global
; CGSCC-SAME: () #[[ATTR7]] {
; CGSCC-NEXT: [[L:%.*]] = load i32, ptr @Gint2, align 4
; CGSCC-NEXT: ret i32 [[L]]
;
%l = load i32, ptr @Gint2
ret i32 %l
}
define i32 @write_read_static_global() {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; TUNIT-LABEL: define {{[^@]+}}@write_read_static_global
; TUNIT-SAME: () #[[ATTR5]] {
; TUNIT-NEXT: ret i32 7
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; CGSCC-LABEL: define {{[^@]+}}@write_read_static_global
; CGSCC-SAME: () #[[ATTR6]] {
; CGSCC-NEXT: ret i32 7
;
store i32 7, ptr @Gstatic_int1
%l = load i32, ptr @Gstatic_int1
ret i32 %l
}
define void @write_static_global() {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; TUNIT-LABEL: define {{[^@]+}}@write_static_global
; TUNIT-SAME: () #[[ATTR5]] {
; TUNIT-NEXT: store i32 7, ptr @Gstatic_int2, align 4
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; CGSCC-LABEL: define {{[^@]+}}@write_static_global
; CGSCC-SAME: () #[[ATTR6]] {
; CGSCC-NEXT: store i32 7, ptr @Gstatic_int2, align 4
; CGSCC-NEXT: ret void
;
store i32 7, ptr @Gstatic_int2
ret void
}
define i32 @read_static_global() {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read)
; TUNIT-LABEL: define {{[^@]+}}@read_static_global
; TUNIT-SAME: () #[[ATTR6]] {
; TUNIT-NEXT: [[L:%.*]] = load i32, ptr @Gstatic_int2, align 4
; TUNIT-NEXT: ret i32 [[L]]
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read)
; CGSCC-LABEL: define {{[^@]+}}@read_static_global
; CGSCC-SAME: () #[[ATTR7]] {
; CGSCC-NEXT: [[L:%.*]] = load i32, ptr @Gstatic_int2, align 4
; CGSCC-NEXT: ret i32 [[L]]
;
%l = load i32, ptr @Gstatic_int2
ret i32 %l
}
define i32 @write_read_static_undef_global() {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; TUNIT-LABEL: define {{[^@]+}}@write_read_static_undef_global
; TUNIT-SAME: () #[[ATTR5]] {
; TUNIT-NEXT: ret i32 7
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; CGSCC-LABEL: define {{[^@]+}}@write_read_static_undef_global
; CGSCC-SAME: () #[[ATTR6]] {
; CGSCC-NEXT: ret i32 7
;
store i32 7, ptr @Gstatic_undef_int1
%l = load i32, ptr @Gstatic_undef_int1
ret i32 %l
}
define void @write_static_undef_global() {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; TUNIT-LABEL: define {{[^@]+}}@write_static_undef_global
; TUNIT-SAME: () #[[ATTR5]] {
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)
; CGSCC-LABEL: define {{[^@]+}}@write_static_undef_global
; CGSCC-SAME: () #[[ATTR6]] {
; CGSCC-NEXT: store i32 7, ptr @Gstatic_undef_int2, align 4
; CGSCC-NEXT: ret void
;
store i32 7, ptr @Gstatic_undef_int2
ret void
}
define i32 @read_static_undef_global() {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CHECK-LABEL: define {{[^@]+}}@read_static_undef_global
; CHECK-SAME: () #[[ATTR4]] {
; CHECK-NEXT: ret i32 7
;
%l = load i32, ptr @Gstatic_undef_int2
ret i32 %l
}
define i32 @single_read_of_static_global() {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CHECK-LABEL: define {{[^@]+}}@single_read_of_static_global
; CHECK-SAME: () #[[ATTR4]] {
; CHECK-NEXT: ret i32 0
;
%l = load i32, ptr @Gstatic_int3
ret i32 %l
}
define i8 @phi_store() {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CHECK-LABEL: define {{[^@]+}}@phi_store
; CHECK-SAME: () #[[ATTR4]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[A:%.*]] = alloca i16, align 2
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[P:%.*]] = phi ptr [ [[A]], [[ENTRY:%.*]] ], [ [[G:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[I:%.*]] = phi i8 [ 0, [[ENTRY]] ], [ [[O:%.*]], [[LOOP]] ]
; CHECK-NEXT: store i8 1, ptr [[P]], align 1
; CHECK-NEXT: [[G]] = getelementptr i8, ptr [[P]], i64 1
; CHECK-NEXT: [[O]] = add nsw i8 [[I]], 1
; CHECK-NEXT: [[C:%.*]] = icmp eq i8 [[O]], 2
; CHECK-NEXT: br i1 [[C]], label [[END:%.*]], label [[LOOP]]
; CHECK: end:
; CHECK-NEXT: [[S:%.*]] = getelementptr i8, ptr [[A]], i64 1
; CHECK-NEXT: [[L:%.*]] = load i8, ptr [[S]], align 1
; CHECK-NEXT: ret i8 [[L]]
;
entry:
%a = alloca i16
br label %loop
loop:
%p = phi ptr [%a, %entry], [%g, %loop]
%i = phi i8 [0, %entry], [%o, %loop]
store i8 1, ptr %p
%g = getelementptr i8, ptr %p, i64 1
%o = add nsw i8 %i, 1
%c = icmp eq i8 %o, 2
br i1 %c, label %end, label %loop
end:
%s = getelementptr i8, ptr %a, i64 1
%l = load i8, ptr %s
ret i8 %l
}
; FIXME: This function returns 1.
define i8 @phi_no_store_1() {
;
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@phi_no_store_1
; TUNIT-SAME: () #[[ATTR3]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: br label [[LOOP:%.*]]
; TUNIT: loop:
; TUNIT-NEXT: [[P:%.*]] = phi ptr [ @a1, [[ENTRY:%.*]] ], [ [[G:%.*]], [[LOOP]] ]
; TUNIT-NEXT: [[I:%.*]] = phi i8 [ 0, [[ENTRY]] ], [ [[O:%.*]], [[LOOP]] ]
; TUNIT-NEXT: store i8 1, ptr [[P]], align 1
; TUNIT-NEXT: [[G]] = getelementptr i8, ptr [[P]], i64 1
; TUNIT-NEXT: [[O]] = add nsw i8 [[I]], 1
; TUNIT-NEXT: [[C:%.*]] = icmp eq i8 [[O]], 3
; TUNIT-NEXT: br i1 [[C]], label [[END:%.*]], label [[LOOP]]
; TUNIT: end:
; TUNIT-NEXT: [[S11:%.*]] = getelementptr i8, ptr @a1, i64 2
; TUNIT-NEXT: [[L11:%.*]] = load i8, ptr [[S11]], align 2
; TUNIT-NEXT: [[S12:%.*]] = getelementptr i8, ptr @a1, i64 3
; TUNIT-NEXT: [[L12:%.*]] = load i8, ptr [[S12]], align 1
; TUNIT-NEXT: [[ADD:%.*]] = add i8 [[L11]], [[L12]]
; TUNIT-NEXT: ret i8 [[ADD]]
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@phi_no_store_1
; CGSCC-SAME: () #[[ATTR5]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: br label [[LOOP:%.*]]
; CGSCC: loop:
; CGSCC-NEXT: [[P:%.*]] = phi ptr [ @a1, [[ENTRY:%.*]] ], [ [[G:%.*]], [[LOOP]] ]
; CGSCC-NEXT: [[I:%.*]] = phi i8 [ 0, [[ENTRY]] ], [ [[O:%.*]], [[LOOP]] ]
; CGSCC-NEXT: store i8 1, ptr [[P]], align 1
; CGSCC-NEXT: [[G]] = getelementptr i8, ptr [[P]], i64 1
; CGSCC-NEXT: [[O]] = add nsw i8 [[I]], 1
; CGSCC-NEXT: [[C:%.*]] = icmp eq i8 [[O]], 3
; CGSCC-NEXT: br i1 [[C]], label [[END:%.*]], label [[LOOP]]
; CGSCC: end:
; CGSCC-NEXT: [[S11:%.*]] = getelementptr i8, ptr @a1, i64 2
; CGSCC-NEXT: [[L11:%.*]] = load i8, ptr [[S11]], align 2
; CGSCC-NEXT: [[S12:%.*]] = getelementptr i8, ptr @a1, i64 3
; CGSCC-NEXT: [[L12:%.*]] = load i8, ptr [[S12]], align 1
; CGSCC-NEXT: [[ADD:%.*]] = add i8 [[L11]], [[L12]]
; CGSCC-NEXT: ret i8 [[ADD]]
;
entry:
br label %loop
loop:
%p = phi ptr [@a1, %entry], [%g, %loop]
%i = phi i8 [0, %entry], [%o, %loop]
store i8 1, ptr %p
%g = getelementptr i8, ptr %p, i64 1
%o = add nsw i8 %i, 1
%c = icmp eq i8 %o, 3
br i1 %c, label %end, label %loop
end:
%s11 = getelementptr i8, ptr @a1, i64 2
%l11 = load i8, ptr %s11
%s12 = getelementptr i8, ptr @a1, i64 3
%l12 = load i8, ptr %s12
%add = add i8 %l11, %l12
ret i8 %add
}
; FIXME: This function returns 1.
define i8 @phi_no_store_2() {
;
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@phi_no_store_2
; TUNIT-SAME: () #[[ATTR3]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: br label [[LOOP:%.*]]
; TUNIT: loop:
; TUNIT-NEXT: [[P:%.*]] = phi ptr [ @a2, [[ENTRY:%.*]] ], [ [[G:%.*]], [[LOOP]] ]
; TUNIT-NEXT: [[I:%.*]] = phi i8 [ 0, [[ENTRY]] ], [ [[O:%.*]], [[LOOP]] ]
; TUNIT-NEXT: store i8 1, ptr [[P]], align 1
; TUNIT-NEXT: [[G]] = getelementptr i8, ptr @a2, i64 2
; TUNIT-NEXT: [[O]] = add nsw i8 [[I]], 1
; TUNIT-NEXT: [[C:%.*]] = icmp eq i8 [[O]], 7
; TUNIT-NEXT: br i1 [[C]], label [[END:%.*]], label [[LOOP]]
; TUNIT: end:
; TUNIT-NEXT: [[S21:%.*]] = getelementptr i8, ptr @a2, i64 2
; TUNIT-NEXT: [[L21:%.*]] = load i8, ptr [[S21]], align 2
; TUNIT-NEXT: [[S22:%.*]] = getelementptr i8, ptr @a2, i64 3
; TUNIT-NEXT: [[L22:%.*]] = load i8, ptr [[S22]], align 1
; TUNIT-NEXT: [[ADD:%.*]] = add i8 [[L21]], [[L22]]
; TUNIT-NEXT: ret i8 [[ADD]]
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@phi_no_store_2
; CGSCC-SAME: () #[[ATTR5]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: br label [[LOOP:%.*]]
; CGSCC: loop:
; CGSCC-NEXT: [[P:%.*]] = phi ptr [ @a2, [[ENTRY:%.*]] ], [ [[G:%.*]], [[LOOP]] ]
; CGSCC-NEXT: [[I:%.*]] = phi i8 [ 0, [[ENTRY]] ], [ [[O:%.*]], [[LOOP]] ]
; CGSCC-NEXT: store i8 1, ptr [[P]], align 1
; CGSCC-NEXT: [[G]] = getelementptr i8, ptr @a2, i64 2
; CGSCC-NEXT: [[O]] = add nsw i8 [[I]], 1
; CGSCC-NEXT: [[C:%.*]] = icmp eq i8 [[O]], 7
; CGSCC-NEXT: br i1 [[C]], label [[END:%.*]], label [[LOOP]]
; CGSCC: end:
; CGSCC-NEXT: [[S21:%.*]] = getelementptr i8, ptr @a2, i64 2
; CGSCC-NEXT: [[L21:%.*]] = load i8, ptr [[S21]], align 2
; CGSCC-NEXT: [[S22:%.*]] = getelementptr i8, ptr @a2, i64 3
; CGSCC-NEXT: [[L22:%.*]] = load i8, ptr [[S22]], align 1
; CGSCC-NEXT: [[ADD:%.*]] = add i8 [[L21]], [[L22]]
; CGSCC-NEXT: ret i8 [[ADD]]
;
entry:
br label %loop
loop:
%p = phi ptr [@a2, %entry], [%g, %loop]
%i = phi i8 [0, %entry], [%o, %loop]
store i8 1, ptr %p
%g = getelementptr i8, ptr @a2, i64 2
%o = add nsw i8 %i, 1
%c = icmp eq i8 %o, 7
br i1 %c, label %end, label %loop
end:
%s21 = getelementptr i8, ptr @a2, i64 2
%l21 = load i8, ptr %s21
%s22 = getelementptr i8, ptr @a2, i64 3
%l22 = load i8, ptr %s22
%add = add i8 %l21, %l22
ret i8 %add
}
define i8 @phi_no_store_3() {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@phi_no_store_3
; TUNIT-SAME: () #[[ATTR3]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[S30:%.*]] = getelementptr i8, ptr @a3, i64 3
; TUNIT-NEXT: store i8 0, ptr [[S30]], align 1
; TUNIT-NEXT: br label [[LOOP:%.*]]
; TUNIT: loop:
; TUNIT-NEXT: [[P:%.*]] = phi ptr [ @a3, [[ENTRY:%.*]] ], [ [[G:%.*]], [[LOOP]] ]
; TUNIT-NEXT: [[I:%.*]] = phi i8 [ 0, [[ENTRY]] ], [ [[O:%.*]], [[LOOP]] ]
; TUNIT-NEXT: store i8 1, ptr [[P]], align 1
; TUNIT-NEXT: [[G]] = getelementptr i8, ptr @a3, i64 2
; TUNIT-NEXT: [[O]] = add nsw i8 [[I]], 1
; TUNIT-NEXT: [[C:%.*]] = icmp eq i8 [[O]], 7
; TUNIT-NEXT: br i1 [[C]], label [[END:%.*]], label [[LOOP]]
; TUNIT: end:
; TUNIT-NEXT: [[S31:%.*]] = getelementptr i8, ptr @a3, i64 2
; TUNIT-NEXT: [[L31:%.*]] = load i8, ptr [[S31]], align 2
; TUNIT-NEXT: [[S32:%.*]] = getelementptr i8, ptr @a3, i64 3
; TUNIT-NEXT: [[L32:%.*]] = load i8, ptr [[S32]], align 1
; TUNIT-NEXT: [[ADD:%.*]] = add i8 [[L31]], [[L32]]
; TUNIT-NEXT: [[S34:%.*]] = getelementptr i8, ptr @a3, i64 4
; TUNIT-NEXT: [[L34:%.*]] = load i8, ptr [[S34]], align 4
; TUNIT-NEXT: [[ADD2:%.*]] = add i8 [[ADD]], [[L34]]
; TUNIT-NEXT: ret i8 [[ADD2]]
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@phi_no_store_3
; CGSCC-SAME: () #[[ATTR5]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[S30:%.*]] = getelementptr i8, ptr @a3, i64 3
; CGSCC-NEXT: store i8 0, ptr [[S30]], align 1
; CGSCC-NEXT: br label [[LOOP:%.*]]
; CGSCC: loop:
; CGSCC-NEXT: [[P:%.*]] = phi ptr [ @a3, [[ENTRY:%.*]] ], [ [[G:%.*]], [[LOOP]] ]
; CGSCC-NEXT: [[I:%.*]] = phi i8 [ 0, [[ENTRY]] ], [ [[O:%.*]], [[LOOP]] ]
; CGSCC-NEXT: store i8 1, ptr [[P]], align 1
; CGSCC-NEXT: [[G]] = getelementptr i8, ptr @a3, i64 2
; CGSCC-NEXT: [[O]] = add nsw i8 [[I]], 1
; CGSCC-NEXT: [[C:%.*]] = icmp eq i8 [[O]], 7
; CGSCC-NEXT: br i1 [[C]], label [[END:%.*]], label [[LOOP]]
; CGSCC: end:
; CGSCC-NEXT: [[S31:%.*]] = getelementptr i8, ptr @a3, i64 2
; CGSCC-NEXT: [[L31:%.*]] = load i8, ptr [[S31]], align 2
; CGSCC-NEXT: [[S32:%.*]] = getelementptr i8, ptr @a3, i64 3
; CGSCC-NEXT: [[L32:%.*]] = load i8, ptr [[S32]], align 1
; CGSCC-NEXT: [[ADD:%.*]] = add i8 [[L31]], [[L32]]
; CGSCC-NEXT: [[S34:%.*]] = getelementptr i8, ptr @a3, i64 4
; CGSCC-NEXT: [[L34:%.*]] = load i8, ptr [[S34]], align 4
; CGSCC-NEXT: [[ADD2:%.*]] = add i8 [[ADD]], [[L34]]
; CGSCC-NEXT: ret i8 [[ADD2]]
;
entry:
%s30 = getelementptr i8, ptr @a3, i64 3
store i8 0, ptr %s30
br label %loop
loop:
%p = phi ptr [@a3, %entry], [%g, %loop]
%i = phi i8 [0, %entry], [%o, %loop]
store i8 1, ptr %p
%g = getelementptr i8, ptr @a3, i64 2
%o = add nsw i8 %i, 1
%c = icmp eq i8 %o, 7
br i1 %c, label %end, label %loop
end:
%s31 = getelementptr i8, ptr @a3, i64 2
%l31 = load i8, ptr %s31
%s32 = getelementptr i8, ptr @a3, i64 3
%l32 = load i8, ptr %s32
%add = add i8 %l31, %l32
%s34 = getelementptr i8, ptr @a3, i64 4
%l34 = load i8, ptr %s34
%add2 = add i8 %add, %l34
ret i8 %add2
}
define i8 @cast_and_load_1() {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@cast_and_load_1
; TUNIT-SAME: () #[[ATTR3]] {
; TUNIT-NEXT: store i32 42, ptr @bytes1, align 4
; TUNIT-NEXT: [[L:%.*]] = load i8, ptr @bytes1, align 4
; TUNIT-NEXT: ret i8 [[L]]
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@cast_and_load_1
; CGSCC-SAME: () #[[ATTR5]] {
; CGSCC-NEXT: store i32 42, ptr @bytes1, align 4
; CGSCC-NEXT: [[L:%.*]] = load i8, ptr @bytes1, align 4
; CGSCC-NEXT: ret i8 [[L]]
;
store i32 42, ptr @bytes1
%l = load i8, ptr @bytes1
ret i8 %l
}
define i64 @cast_and_load_2() {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@cast_and_load_2
; TUNIT-SAME: () #[[ATTR3]] {
; TUNIT-NEXT: store i32 42, ptr @bytes2, align 4
; TUNIT-NEXT: [[L:%.*]] = load i64, ptr @bytes2, align 4
; TUNIT-NEXT: ret i64 [[L]]
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@cast_and_load_2
; CGSCC-SAME: () #[[ATTR5]] {
; CGSCC-NEXT: store i32 42, ptr @bytes2, align 4
; CGSCC-NEXT: [[L:%.*]] = load i64, ptr @bytes2, align 4
; CGSCC-NEXT: ret i64 [[L]]
;
store i32 42, ptr @bytes2
%l = load i64, ptr @bytes2
ret i64 %l
}
define void @recursive_load_store(i64 %N, i32 %v) {
;
; TUNIT: Function Attrs: nofree norecurse nosync nounwind memory(write)
; TUNIT-LABEL: define {{[^@]+}}@recursive_load_store
; TUNIT-SAME: (i64 [[N:%.*]], i32 [[V:%.*]]) #[[ATTR7:[0-9]+]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: br label [[FOR_COND:%.*]]
; TUNIT: for.cond:
; TUNIT-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY:%.*]] ], [ 0, [[ENTRY:%.*]] ]
; TUNIT-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV]], [[N]]
; TUNIT-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END:%.*]]
; TUNIT: for.body:
; TUNIT-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
; TUNIT-NEXT: br label [[FOR_COND]]
; TUNIT: for.end:
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: nofree norecurse nosync nounwind memory(write)
; CGSCC-LABEL: define {{[^@]+}}@recursive_load_store
; CGSCC-SAME: (i64 [[N:%.*]], i32 [[V:%.*]]) #[[ATTR8:[0-9]+]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: br label [[FOR_COND:%.*]]
; CGSCC: for.cond:
; CGSCC-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY:%.*]] ], [ 0, [[ENTRY:%.*]] ]
; CGSCC-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV]], [[N]]
; CGSCC-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END:%.*]]
; CGSCC: for.body:
; CGSCC-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
; CGSCC-NEXT: br label [[FOR_COND]]
; CGSCC: for.end:
; CGSCC-NEXT: ret void
;
entry:
store i32 %v, ptr @rec_storage
br label %for.cond
for.cond:
%indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]
%exitcond = icmp ne i64 %indvars.iv, %N
br i1 %exitcond, label %for.body, label %for.end
for.body:
%ll = load i32, ptr @rec_storage
store i32 %ll, ptr @rec_storage
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
br label %for.cond
for.end:
%lr = load i32, ptr @rec_storage
store i32 %lr, ptr @rec_storage
ret void
}
define dso_local i32 @round_trip_malloc(i32 %x) {
; CHECK-LABEL: define {{[^@]+}}@round_trip_malloc
; CHECK-SAME: (i32 returned [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL_H2S:%.*]] = alloca i8, i64 4, align 1
; CHECK-NEXT: store i32 [[X]], ptr [[CALL_H2S]], align 4
; CHECK-NEXT: ret i32 [[X]]
;
entry:
%call = call noalias ptr @malloc(i64 4) norecurse
store i32 %x, ptr %call, align 4
%0 = load i32, ptr %call, align 4
call void @free(ptr %call) norecurse
ret i32 %0
}
define dso_local i32 @round_trip_malloc_constant() {
; CHECK-LABEL: define {{[^@]+}}@round_trip_malloc_constant() {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i32 7
;
entry:
%call = call noalias ptr @malloc(i64 4) norecurse
store i32 7, ptr %call, align 4
%0 = load i32, ptr %call, align 4
call void @free(ptr %call) norecurse
ret i32 %0
}
declare noalias ptr @malloc(i64) allockind("alloc,uninitialized") allocsize(0) "alloc-family"="malloc"
declare void @free(ptr) allockind("free") "alloc-family"="malloc"
define dso_local i32 @conditional_malloc(i32 %x) {
; CHECK-LABEL: define {{[^@]+}}@conditional_malloc
; CHECK-SAME: (i32 returned [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL_H2S:%.*]] = alloca i8, i64 4, align 1
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[X]], 0
; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
; CHECK: if.then:
; CHECK-NEXT: store i32 [[X]], ptr [[CALL_H2S]], align 4
; CHECK-NEXT: br label [[IF_END]]
; CHECK: if.end:
; CHECK-NEXT: ret i32 [[X]]
;
entry:
%call = call noalias ptr @malloc(i64 4) norecurse
%tobool = icmp ne i32 %x, 0
br i1 %tobool, label %if.then, label %if.end
if.then: ; preds = %entry
store i32 %x, ptr %call, align 4
br label %if.end
if.end: ; preds = %if.then, %entry
%0 = load i32, ptr %call, align 4
ret i32 %0
}
define dso_local i32 @round_trip_calloc(i32 %x) {
; CHECK-LABEL: define {{[^@]+}}@round_trip_calloc
; CHECK-SAME: (i32 returned [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL_H2S:%.*]] = alloca i8, i64 4, align 1
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[CALL_H2S]], i8 0, i64 4, i1 false)
; CHECK-NEXT: store i32 [[X]], ptr [[CALL_H2S]], align 4
; CHECK-NEXT: ret i32 [[X]]
;
entry:
%call = call noalias ptr @calloc(i64 4, i64 1) norecurse
store i32 %x, ptr %call, align 4
%0 = load i32, ptr %call, align 4
ret i32 %0
}
define dso_local i32 @round_trip_calloc_constant() {
; CHECK-LABEL: define {{[^@]+}}@round_trip_calloc_constant() {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL_H2S:%.*]] = alloca i8, i64 4, align 1
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[CALL_H2S]], i8 0, i64 4, i1 false)
; CHECK-NEXT: ret i32 11
;
entry:
%call = call noalias ptr @calloc(i64 4, i64 1) norecurse
store i32 11, ptr %call, align 4
%0 = load i32, ptr %call, align 4
ret i32 %0
}
declare noalias ptr @calloc(i64, i64) allockind("alloc,zeroed") allocsize(0, 1) "alloc-family"="malloc"
define dso_local i32 @conditional_calloc(i32 %x) {
; CHECK-LABEL: define {{[^@]+}}@conditional_calloc
; CHECK-SAME: (i32 [[X:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL_H2S:%.*]] = alloca i8, i64 4, align 1
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[CALL_H2S]], i8 0, i64 4, i1 false)
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[X]], 0
; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
; CHECK: if.then:
; CHECK-NEXT: store i32 [[X]], ptr [[CALL_H2S]], align 4
; CHECK-NEXT: br label [[IF_END]]
; CHECK: if.end:
; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[CALL_H2S]], align 4
; CHECK-NEXT: ret i32 [[TMP0]]
;
entry:
%call = call noalias ptr @calloc(i64 1, i64 4) norecurse
%tobool = icmp ne i32 %x, 0
br i1 %tobool, label %if.end, label %if.then
if.then: ; preds = %entry
store i32 %x, ptr %call, align 4
br label %if.end
if.end: ; preds = %if.then, %entry
%0 = load i32, ptr %call, align 4
call void @free(ptr %call) norecurse
ret i32 %0
}
define dso_local i32 @conditional_calloc_zero(i1 %c) {
; CHECK-LABEL: define {{[^@]+}}@conditional_calloc_zero
; CHECK-SAME: (i1 [[C:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL_H2S:%.*]] = alloca i8, i64 4, align 1
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[CALL_H2S]], i8 0, i64 4, i1 false)
; CHECK-NEXT: br i1 [[C]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
; CHECK: if.then:
; CHECK-NEXT: br label [[IF_END]]
; CHECK: if.end:
; CHECK-NEXT: ret i32 0
;
entry:
%call = call noalias ptr @calloc(i64 1, i64 4) norecurse
br i1 %c, label %if.end, label %if.then
if.then: ; preds = %entry
store i32 0, ptr %call, align 4
br label %if.end
if.end: ; preds = %if.then, %entry
%0 = load i32, ptr %call, align 4
call void @free(ptr %call) norecurse
ret i32 %0
}
define dso_local ptr @malloc_like(i32 %s) {
; TUNIT-LABEL: define {{[^@]+}}@malloc_like
; TUNIT-SAME: (i32 [[S:%.*]]) {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[CONV:%.*]] = sext i32 [[S]] to i64
; TUNIT-NEXT: [[CALL:%.*]] = call noalias ptr @malloc(i64 [[CONV]]) #[[ATTR20:[0-9]+]]
; TUNIT-NEXT: ret ptr [[CALL]]
;
; CGSCC-LABEL: define {{[^@]+}}@malloc_like
; CGSCC-SAME: (i32 [[S:%.*]]) {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[CONV:%.*]] = sext i32 [[S]] to i64
; CGSCC-NEXT: [[CALL:%.*]] = call noalias ptr @malloc(i64 [[CONV]]) #[[ATTR23:[0-9]+]]
; CGSCC-NEXT: ret ptr [[CALL]]
;
entry:
%conv = sext i32 %s to i64
%call = call noalias ptr @malloc(i64 %conv) norecurse
ret ptr %call
}
define dso_local i32 @round_trip_malloc_like(i32 %x) {
; TUNIT-LABEL: define {{[^@]+}}@round_trip_malloc_like
; TUNIT-SAME: (i32 [[X:%.*]]) {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[CALL:%.*]] = call noalias ptr @malloc_like(i32 noundef 4) #[[ATTR20]]
; TUNIT-NEXT: store i32 [[X]], ptr [[CALL]], align 4
; TUNIT-NEXT: [[TMP0:%.*]] = load i32, ptr [[CALL]], align 4
; TUNIT-NEXT: call void @free(ptr noundef nonnull align 4 dereferenceable(4) [[CALL]]) #[[ATTR20]]
; TUNIT-NEXT: ret i32 [[TMP0]]
;
; CGSCC-LABEL: define {{[^@]+}}@round_trip_malloc_like
; CGSCC-SAME: (i32 [[X:%.*]]) {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[CALL:%.*]] = call noalias ptr @malloc_like(i32 noundef 4) #[[ATTR23]]
; CGSCC-NEXT: store i32 [[X]], ptr [[CALL]], align 4
; CGSCC-NEXT: [[TMP0:%.*]] = load i32, ptr [[CALL]], align 4
; CGSCC-NEXT: call void @free(ptr noundef nonnull align 4 dereferenceable(4) [[CALL]]) #[[ATTR23]]
; CGSCC-NEXT: ret i32 [[TMP0]]
;
entry:
%call = call ptr @malloc_like(i32 4) norecurse
store i32 %x, ptr %call, align 4
%0 = load i32, ptr %call, align 4
call void @free(ptr %call) norecurse
ret i32 %0
}
define dso_local i32 @round_trip_unknown_alloc(i32 %x) {
; TUNIT-LABEL: define {{[^@]+}}@round_trip_unknown_alloc
; TUNIT-SAME: (i32 [[X:%.*]]) {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[CALL:%.*]] = call noalias ptr @unknown_alloc(i32 noundef 4) #[[ATTR20]]
; TUNIT-NEXT: store i32 [[X]], ptr [[CALL]], align 4
; TUNIT-NEXT: [[TMP0:%.*]] = load i32, ptr [[CALL]], align 4
; TUNIT-NEXT: call void @free(ptr noundef nonnull align 4 dereferenceable(4) [[CALL]]) #[[ATTR20]]
; TUNIT-NEXT: ret i32 [[TMP0]]
;
; CGSCC-LABEL: define {{[^@]+}}@round_trip_unknown_alloc
; CGSCC-SAME: (i32 [[X:%.*]]) {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[CALL:%.*]] = call noalias ptr @unknown_alloc(i32 noundef 4) #[[ATTR23]]
; CGSCC-NEXT: store i32 [[X]], ptr [[CALL]], align 4
; CGSCC-NEXT: [[TMP0:%.*]] = load i32, ptr [[CALL]], align 4
; CGSCC-NEXT: call void @free(ptr noundef nonnull align 4 dereferenceable(4) [[CALL]]) #[[ATTR23]]
; CGSCC-NEXT: ret i32 [[TMP0]]
;
entry:
%call = call ptr @unknown_alloc(i32 4) norecurse
store i32 %x, ptr %call, align 4
%0 = load i32, ptr %call, align 4
call void @free(ptr %call) norecurse
ret i32 %0
}
declare noalias ptr @unknown_alloc(i32)
define dso_local i32 @conditional_unknown_alloc(i32 %x) {
; TUNIT-LABEL: define {{[^@]+}}@conditional_unknown_alloc
; TUNIT-SAME: (i32 [[X:%.*]]) {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[CALL:%.*]] = call noalias ptr @unknown_alloc(i32 noundef 4) #[[ATTR20]]
; TUNIT-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[X]], 0
; TUNIT-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
; TUNIT: if.then:
; TUNIT-NEXT: store i32 [[X]], ptr [[CALL]], align 4
; TUNIT-NEXT: br label [[IF_END]]
; TUNIT: if.end:
; TUNIT-NEXT: [[TMP0:%.*]] = load i32, ptr [[CALL]], align 4
; TUNIT-NEXT: call void @free(ptr nonnull align 4 dereferenceable(4) [[CALL]]) #[[ATTR20]]
; TUNIT-NEXT: ret i32 [[TMP0]]
;
; CGSCC-LABEL: define {{[^@]+}}@conditional_unknown_alloc
; CGSCC-SAME: (i32 [[X:%.*]]) {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[CALL:%.*]] = call noalias ptr @unknown_alloc(i32 noundef 4) #[[ATTR23]]
; CGSCC-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[X]], 0
; CGSCC-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
; CGSCC: if.then:
; CGSCC-NEXT: store i32 [[X]], ptr [[CALL]], align 4
; CGSCC-NEXT: br label [[IF_END]]
; CGSCC: if.end:
; CGSCC-NEXT: [[TMP0:%.*]] = load i32, ptr [[CALL]], align 4
; CGSCC-NEXT: call void @free(ptr nonnull align 4 dereferenceable(4) [[CALL]]) #[[ATTR23]]
; CGSCC-NEXT: ret i32 [[TMP0]]
;
entry:
%call = call noalias ptr @unknown_alloc(i32 4) norecurse
%tobool = icmp ne i32 %x, 0
br i1 %tobool, label %if.end, label %if.then
if.then: ; preds = %entry
store i32 %x, ptr %call, align 4
br label %if.end
if.end: ; preds = %if.then, %entry
%0 = load i32, ptr %call, align 4
call void @free(ptr %call) norecurse
ret i32 %0
}
%struct.STy = type { ptr, ptr, ptr }
@global = internal global %struct.STy zeroinitializer, align 8
; We mark %dst as writeonly and %src as readonly, that is (for now) all we can expect.
define dso_local void @test_nested_memory(ptr %dst, ptr %src) {
; TUNIT-LABEL: define {{[^@]+}}@test_nested_memory
; TUNIT-SAME: (ptr nocapture nofree writeonly [[DST:%.*]], ptr nocapture nofree readonly [[SRC:%.*]]) {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[CALL_H2S:%.*]] = alloca i8, i64 24, align 1
; TUNIT-NEXT: [[LOCAL:%.*]] = alloca [[STRUCT_STY:%.*]], align 8
; TUNIT-NEXT: [[INNER:%.*]] = getelementptr inbounds [[STRUCT_STY]], ptr [[LOCAL]], i64 0, i32 2
; TUNIT-NEXT: store ptr @global, ptr [[INNER]], align 8
; TUNIT-NEXT: store ptr [[DST]], ptr [[CALL_H2S]], align 8
; TUNIT-NEXT: [[SRC2:%.*]] = getelementptr inbounds i8, ptr [[CALL_H2S]], i64 8
; TUNIT-NEXT: store ptr [[SRC]], ptr [[SRC2]], align 8
; TUNIT-NEXT: store ptr [[CALL_H2S]], ptr getelementptr inbounds ([[STRUCT_STY]], ptr @global, i64 0, i32 2), align 8
; TUNIT-NEXT: [[TMP0:%.*]] = load ptr, ptr [[LOCAL]], align 8
; TUNIT-NEXT: [[LOCAL_B8:%.*]] = getelementptr i8, ptr [[LOCAL]], i64 8
; TUNIT-NEXT: [[TMP1:%.*]] = load ptr, ptr [[LOCAL_B8]], align 8
; TUNIT-NEXT: [[LOCAL_B16:%.*]] = getelementptr i8, ptr [[LOCAL]], i64 16
; TUNIT-NEXT: [[TMP2:%.*]] = load ptr, ptr [[LOCAL_B16]], align 8
; TUNIT-NEXT: call fastcc void @nested_memory_callee(ptr [[TMP0]], ptr [[TMP1]], ptr [[TMP2]]) #[[ATTR21:[0-9]+]]
; TUNIT-NEXT: ret void
;
; CGSCC-LABEL: define {{[^@]+}}@test_nested_memory
; CGSCC-SAME: (ptr nofree [[DST:%.*]], ptr nofree [[SRC:%.*]]) {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[LOCAL:%.*]] = alloca [[STRUCT_STY:%.*]], align 8
; CGSCC-NEXT: [[INNER:%.*]] = getelementptr inbounds [[STRUCT_STY]], ptr [[LOCAL]], i64 0, i32 2
; CGSCC-NEXT: [[CALL:%.*]] = call noalias dereferenceable_or_null(24) ptr @malloc(i64 noundef 24)
; CGSCC-NEXT: store ptr [[DST]], ptr [[CALL]], align 8
; CGSCC-NEXT: [[SRC2:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 8
; CGSCC-NEXT: store ptr [[SRC]], ptr [[SRC2]], align 8
; CGSCC-NEXT: store ptr [[CALL]], ptr getelementptr inbounds ([[STRUCT_STY]], ptr @global, i64 0, i32 2), align 8
; CGSCC-NEXT: call fastcc void @nested_memory_callee(ptr nofree align 4294967296 undef, ptr nofree align 4294967296 undef, ptr nofree noundef nonnull align 8 dereferenceable(24) @global) #[[ATTR24:[0-9]+]]
; CGSCC-NEXT: ret void
;
entry:
%local = alloca %struct.STy, align 8
%inner = getelementptr inbounds %struct.STy, ptr %local, i64 0, i32 2
store ptr @global, ptr %inner, align 8
%call = call noalias dereferenceable_or_null(24) ptr @malloc(i64 24) #4
store ptr %dst, ptr %call, align 8
%src2 = getelementptr inbounds i8, ptr %call, i64 8
store ptr %src, ptr %src2, align 8
store ptr %call, ptr getelementptr inbounds (%struct.STy, ptr @global, i64 0, i32 2), align 8
call fastcc void @nested_memory_callee(ptr nonnull %local)
ret void
}
define internal fastcc void @nested_memory_callee(ptr nocapture readonly %S) nofree norecurse nounwind uwtable {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn uwtable
; TUNIT-LABEL: define {{[^@]+}}@nested_memory_callee
; TUNIT-SAME: (ptr [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr [[TMP2:%.*]]) #[[ATTR11:[0-9]+]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[S_PRIV:%.*]] = alloca [[STRUCT_STY:%.*]], align 8
; TUNIT-NEXT: store ptr [[TMP0]], ptr [[S_PRIV]], align 8
; TUNIT-NEXT: [[S_PRIV_B8:%.*]] = getelementptr i8, ptr [[S_PRIV]], i64 8
; TUNIT-NEXT: store ptr [[TMP1]], ptr [[S_PRIV_B8]], align 8
; TUNIT-NEXT: [[S_PRIV_B16:%.*]] = getelementptr i8, ptr [[S_PRIV]], i64 16
; TUNIT-NEXT: store ptr [[TMP2]], ptr [[S_PRIV_B16]], align 8
; TUNIT-NEXT: [[INNER:%.*]] = getelementptr inbounds [[STRUCT_STY]], ptr [[S_PRIV]], i64 0, i32 2
; TUNIT-NEXT: [[TMP3:%.*]] = load ptr, ptr [[INNER]], align 8
; TUNIT-NEXT: [[INNER1:%.*]] = getelementptr inbounds [[STRUCT_STY]], ptr [[TMP3]], i64 0, i32 2
; TUNIT-NEXT: [[TMP4:%.*]] = load ptr, ptr [[INNER1]], align 8
; TUNIT-NEXT: [[SRC:%.*]] = getelementptr inbounds [[STRUCT_STY]], ptr [[TMP4]], i64 0, i32 1
; TUNIT-NEXT: [[TMP5:%.*]] = load ptr, ptr [[SRC]], align 8
; TUNIT-NEXT: [[TMP6:%.*]] = load double, ptr [[TMP5]], align 8
; TUNIT-NEXT: [[CONV:%.*]] = fptrunc double [[TMP6]] to float
; TUNIT-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP4]], align 8
; TUNIT-NEXT: store float [[CONV]], ptr [[TMP7]], align 4
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn uwtable
; CGSCC-LABEL: define {{[^@]+}}@nested_memory_callee
; CGSCC-SAME: (ptr nofree [[TMP0:%.*]], ptr nofree [[TMP1:%.*]], ptr nofree [[TMP2:%.*]]) #[[ATTR12:[0-9]+]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[S_PRIV:%.*]] = alloca [[STRUCT_STY:%.*]], align 8
; CGSCC-NEXT: store ptr [[TMP0]], ptr [[S_PRIV]], align 8
; CGSCC-NEXT: [[S_PRIV_B8:%.*]] = getelementptr i8, ptr [[S_PRIV]], i64 8
; CGSCC-NEXT: store ptr [[TMP1]], ptr [[S_PRIV_B8]], align 8
; CGSCC-NEXT: [[S_PRIV_B16:%.*]] = getelementptr i8, ptr [[S_PRIV]], i64 16
; CGSCC-NEXT: store ptr [[TMP2]], ptr [[S_PRIV_B16]], align 8
; CGSCC-NEXT: [[INNER:%.*]] = getelementptr inbounds [[STRUCT_STY]], ptr [[S_PRIV]], i64 0, i32 2
; CGSCC-NEXT: [[TMP3:%.*]] = load ptr, ptr [[INNER]], align 8
; CGSCC-NEXT: [[INNER1:%.*]] = getelementptr inbounds [[STRUCT_STY]], ptr [[TMP3]], i64 0, i32 2
; CGSCC-NEXT: [[TMP4:%.*]] = load ptr, ptr [[INNER1]], align 8
; CGSCC-NEXT: [[SRC:%.*]] = getelementptr inbounds [[STRUCT_STY]], ptr [[TMP4]], i64 0, i32 1
; CGSCC-NEXT: [[TMP5:%.*]] = load ptr, ptr [[SRC]], align 8
; CGSCC-NEXT: [[TMP6:%.*]] = load double, ptr [[TMP5]], align 8
; CGSCC-NEXT: [[CONV:%.*]] = fptrunc double [[TMP6]] to float
; CGSCC-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP4]], align 8
; CGSCC-NEXT: store float [[CONV]], ptr [[TMP7]], align 4
; CGSCC-NEXT: ret void
;
entry:
%inner = getelementptr inbounds %struct.STy, ptr %S, i64 0, i32 2
%0 = load ptr, ptr %inner, align 8
%inner1 = getelementptr inbounds %struct.STy, ptr %0, i64 0, i32 2
%1 = load ptr, ptr %inner1, align 8
%src = getelementptr inbounds %struct.STy, ptr %1, i64 0, i32 1
%2 = load ptr, ptr %src, align 8
%3 = load double, ptr %2, align 8
%conv = fptrunc double %3 to float
%4 = load ptr, ptr %1, align 8
store float %conv, ptr %4, align 4
ret void
}
; Make sure the access %1 is not forwarded to the loads %2 and %3 as the indices are
; varying and the accesses thus not "exact". This used to simplify %cmp12 to true.
define hidden void @no_propagation_of_unknown_index_access(ptr %in, ptr %out, i32 %idx) #0 {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)
; TUNIT-LABEL: define {{[^@]+}}@no_propagation_of_unknown_index_access
; TUNIT-SAME: (ptr nocapture nofree readonly [[IN:%.*]], ptr nocapture nofree writeonly [[OUT:%.*]], i32 [[IDX:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[BUF:%.*]] = alloca [128 x i32], align 16
; TUNIT-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 512, ptr noalias nocapture nofree noundef nonnull align 16 dereferenceable(512) [[BUF]]) #[[ATTR17]]
; TUNIT-NEXT: br label [[FOR_COND:%.*]]
; TUNIT: for.cond:
; TUNIT-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY:%.*]] ]
; TUNIT-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], 128
; TUNIT-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]]
; TUNIT: for.cond.cleanup:
; TUNIT-NEXT: br label [[FOR_COND4:%.*]]
; TUNIT: for.body:
; TUNIT-NEXT: [[IDXPROM:%.*]] = sext i32 [[I_0]] to i64
; TUNIT-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[IN]], i64 [[IDXPROM]]
; TUNIT-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
; TUNIT-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds [128 x i32], ptr [[BUF]], i64 0, i64 [[IDXPROM]]
; TUNIT-NEXT: store i32 [[TMP0]], ptr [[ARRAYIDX2]], align 4
; TUNIT-NEXT: [[INC]] = add nsw i32 [[I_0]], 1
; TUNIT-NEXT: br label [[FOR_COND]], !llvm.loop [[TBAA10]]
; TUNIT: for.cond4:
; TUNIT-NEXT: [[I3_0:%.*]] = phi i32 [ 0, [[FOR_COND_CLEANUP]] ], [ [[INC16:%.*]], [[FOR_BODY7:%.*]] ]
; TUNIT-NEXT: [[CMP5:%.*]] = icmp slt i32 [[I3_0]], 128
; TUNIT-NEXT: br i1 [[CMP5]], label [[FOR_BODY7]], label [[FOR_COND_CLEANUP6:%.*]]
; TUNIT: for.cond.cleanup6:
; TUNIT-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 512, ptr noalias nocapture nofree noundef nonnull align 16 dereferenceable(512) [[BUF]]) #[[ATTR17]]
; TUNIT-NEXT: ret void
; TUNIT: for.body7:
; TUNIT-NEXT: [[IDXPROM8:%.*]] = sext i32 [[I3_0]] to i64
; TUNIT-NEXT: [[ARRAYIDX9:%.*]] = getelementptr inbounds [128 x i32], ptr [[BUF]], i64 0, i64 [[IDXPROM8]]
; TUNIT-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX9]], align 4
; TUNIT-NEXT: [[IDXPROM10:%.*]] = sext i32 [[IDX]] to i64
; TUNIT-NEXT: [[ARRAYIDX11:%.*]] = getelementptr inbounds [128 x i32], ptr [[BUF]], i64 0, i64 [[IDXPROM10]]
; TUNIT-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX11]], align 4
; TUNIT-NEXT: [[CMP12:%.*]] = icmp sle i32 [[TMP1]], [[TMP2]]
; TUNIT-NEXT: [[CONV:%.*]] = zext i1 [[CMP12]] to i32
; TUNIT-NEXT: [[ARRAYIDX14:%.*]] = getelementptr inbounds i32, ptr [[OUT]], i64 [[IDXPROM8]]
; TUNIT-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX14]], align 4
; TUNIT-NEXT: [[INC16]] = add nsw i32 [[I3_0]], 1
; TUNIT-NEXT: br label [[FOR_COND4]], !llvm.loop [[TBAA12]]
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)
; CGSCC-LABEL: define {{[^@]+}}@no_propagation_of_unknown_index_access
; CGSCC-SAME: (ptr nocapture nofree readonly [[IN:%.*]], ptr nocapture nofree writeonly [[OUT:%.*]], i32 [[IDX:%.*]]) #[[ATTR13:[0-9]+]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[BUF:%.*]] = alloca [128 x i32], align 16
; CGSCC-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 512, ptr noalias nocapture nofree noundef nonnull align 16 dereferenceable(512) [[BUF]]) #[[ATTR20]]
; CGSCC-NEXT: br label [[FOR_COND:%.*]]
; CGSCC: for.cond:
; CGSCC-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY:%.*]] ]
; CGSCC-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], 128
; CGSCC-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]]
; CGSCC: for.cond.cleanup:
; CGSCC-NEXT: br label [[FOR_COND4:%.*]]
; CGSCC: for.body:
; CGSCC-NEXT: [[IDXPROM:%.*]] = sext i32 [[I_0]] to i64
; CGSCC-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[IN]], i64 [[IDXPROM]]
; CGSCC-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
; CGSCC-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds [128 x i32], ptr [[BUF]], i64 0, i64 [[IDXPROM]]
; CGSCC-NEXT: store i32 [[TMP0]], ptr [[ARRAYIDX2]], align 4
; CGSCC-NEXT: [[INC]] = add nsw i32 [[I_0]], 1
; CGSCC-NEXT: br label [[FOR_COND]], !llvm.loop [[TBAA10]]
; CGSCC: for.cond4:
; CGSCC-NEXT: [[I3_0:%.*]] = phi i32 [ 0, [[FOR_COND_CLEANUP]] ], [ [[INC16:%.*]], [[FOR_BODY7:%.*]] ]
; CGSCC-NEXT: [[CMP5:%.*]] = icmp slt i32 [[I3_0]], 128
; CGSCC-NEXT: br i1 [[CMP5]], label [[FOR_BODY7]], label [[FOR_COND_CLEANUP6:%.*]]
; CGSCC: for.cond.cleanup6:
; CGSCC-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 512, ptr noalias nocapture nofree noundef nonnull align 16 dereferenceable(512) [[BUF]]) #[[ATTR20]]
; CGSCC-NEXT: ret void
; CGSCC: for.body7:
; CGSCC-NEXT: [[IDXPROM8:%.*]] = sext i32 [[I3_0]] to i64
; CGSCC-NEXT: [[ARRAYIDX9:%.*]] = getelementptr inbounds [128 x i32], ptr [[BUF]], i64 0, i64 [[IDXPROM8]]
; CGSCC-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX9]], align 4
; CGSCC-NEXT: [[IDXPROM10:%.*]] = sext i32 [[IDX]] to i64
; CGSCC-NEXT: [[ARRAYIDX11:%.*]] = getelementptr inbounds [128 x i32], ptr [[BUF]], i64 0, i64 [[IDXPROM10]]
; CGSCC-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX11]], align 4
; CGSCC-NEXT: [[CMP12:%.*]] = icmp sle i32 [[TMP1]], [[TMP2]]
; CGSCC-NEXT: [[CONV:%.*]] = zext i1 [[CMP12]] to i32
; CGSCC-NEXT: [[ARRAYIDX14:%.*]] = getelementptr inbounds i32, ptr [[OUT]], i64 [[IDXPROM8]]
; CGSCC-NEXT: store i32 [[CONV]], ptr [[ARRAYIDX14]], align 4
; CGSCC-NEXT: [[INC16]] = add nsw i32 [[I3_0]], 1
; CGSCC-NEXT: br label [[FOR_COND4]], !llvm.loop [[TBAA12]]
;
entry:
%buf = alloca [128 x i32], align 16
call void @llvm.lifetime.start.p0(i64 512, ptr %buf) #2
br label %for.cond
for.cond: ; preds = %for.body, %entry
%i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
%cmp = icmp slt i32 %i.0, 128
br i1 %cmp, label %for.body, label %for.cond.cleanup
for.cond.cleanup: ; preds = %for.cond
br label %for.cond4
for.body: ; preds = %for.cond
%idxprom = sext i32 %i.0 to i64
%arrayidx = getelementptr inbounds i32, ptr %in, i64 %idxprom
%0 = load i32, ptr %arrayidx, align 4
%arrayidx2 = getelementptr inbounds [128 x i32], ptr %buf, i64 0, i64 %idxprom
store i32 %0, ptr %arrayidx2, align 4
%inc = add nsw i32 %i.0, 1
br label %for.cond, !llvm.loop !10
for.cond4: ; preds = %for.body7, %for.cond.cleanup
%i3.0 = phi i32 [ 0, %for.cond.cleanup ], [ %inc16, %for.body7 ]
%cmp5 = icmp slt i32 %i3.0, 128
br i1 %cmp5, label %for.body7, label %for.cond.cleanup6
for.cond.cleanup6: ; preds = %for.cond4
call void @llvm.lifetime.end.p0(i64 512, ptr %buf) #2
ret void
for.body7: ; preds = %for.cond4
%idxprom8 = sext i32 %i3.0 to i64
%arrayidx9 = getelementptr inbounds [128 x i32], ptr %buf, i64 0, i64 %idxprom8
%1 = load i32, ptr %arrayidx9, align 4
%idxprom10 = sext i32 %idx to i64
%arrayidx11 = getelementptr inbounds [128 x i32], ptr %buf, i64 0, i64 %idxprom10
%2 = load i32, ptr %arrayidx11, align 4
%cmp12 = icmp sle i32 %1, %2
%conv = zext i1 %cmp12 to i32
%arrayidx14 = getelementptr inbounds i32, ptr %out, i64 %idxprom8
store i32 %conv, ptr %arrayidx14, align 4
%inc16 = add nsw i32 %i3.0, 1
br label %for.cond4, !llvm.loop !12
}
; Ensure we do not return true.
define internal i1 @alloca_non_unique(ptr %p, i32 %in, i1 %c) {
; TUNIT: Function Attrs: nofree nosync nounwind memory(argmem: readwrite)
; TUNIT-LABEL: define {{[^@]+}}@alloca_non_unique
; TUNIT-SAME: (ptr noalias nocapture nofree readonly align 4 [[P:%.*]], i32 [[IN:%.*]], i1 noundef [[C:%.*]]) #[[ATTR12:[0-9]+]] {
; TUNIT-NEXT: [[A:%.*]] = alloca i32, align 4
; TUNIT-NEXT: store i32 [[IN]], ptr [[A]], align 4
; TUNIT-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; TUNIT: t:
; TUNIT-NEXT: [[R:%.*]] = call i1 @alloca_non_unique(ptr noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A]], i32 noundef 42, i1 noundef false) #[[ATTR14:[0-9]+]]
; TUNIT-NEXT: ret i1 [[R]]
; TUNIT: f:
; TUNIT-NEXT: [[L:%.*]] = load i32, ptr [[P]], align 4
; TUNIT-NEXT: [[CMP:%.*]] = icmp eq i32 [[IN]], [[L]]
; TUNIT-NEXT: ret i1 [[CMP]]
;
; CGSCC: Function Attrs: nofree nosync nounwind memory(argmem: readwrite)
; CGSCC-LABEL: define {{[^@]+}}@alloca_non_unique
; CGSCC-SAME: (ptr noalias nocapture nofree readonly align 4 [[P:%.*]], i32 [[IN:%.*]], i1 noundef [[C:%.*]]) #[[ATTR14:[0-9]+]] {
; CGSCC-NEXT: [[A:%.*]] = alloca i32, align 4
; CGSCC-NEXT: store i32 [[IN]], ptr [[A]], align 4
; CGSCC-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; CGSCC: t:
; CGSCC-NEXT: [[R:%.*]] = call i1 @alloca_non_unique(ptr noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A]], i32 noundef 42, i1 noundef false) #[[ATTR17:[0-9]+]]
; CGSCC-NEXT: ret i1 [[R]]
; CGSCC: f:
; CGSCC-NEXT: [[L:%.*]] = load i32, ptr [[P]], align 4
; CGSCC-NEXT: [[CMP:%.*]] = icmp eq i32 [[IN]], [[L]]
; CGSCC-NEXT: ret i1 [[CMP]]
;
%a = alloca i32
store i32 %in, ptr %a
br i1 %c, label %t, label %f
t:
%r = call i1 @alloca_non_unique(ptr %a, i32 42, i1 false)
ret i1 %r
f:
%l = load i32, ptr %p
%cmp = icmp eq i32 %in, %l
ret i1 %cmp
}
; Ensure we do not return true.
define i1 @alloca_non_unique_caller(i32 %in, i1 %c) {
; TUNIT: Function Attrs: nofree norecurse nosync nounwind memory(none)
; TUNIT-LABEL: define {{[^@]+}}@alloca_non_unique_caller
; TUNIT-SAME: (i32 [[IN:%.*]], i1 [[C:%.*]]) #[[ATTR13:[0-9]+]] {
; TUNIT-NEXT: [[R:%.*]] = call i1 @alloca_non_unique(ptr undef, i32 [[IN]], i1 noundef [[C]]) #[[ATTR14]]
; TUNIT-NEXT: ret i1 [[R]]
;
; CGSCC: Function Attrs: nofree nosync nounwind memory(none)
; CGSCC-LABEL: define {{[^@]+}}@alloca_non_unique_caller
; CGSCC-SAME: (i32 [[IN:%.*]], i1 noundef [[C:%.*]]) #[[ATTR15:[0-9]+]] {
; CGSCC-NEXT: [[R:%.*]] = call i1 @alloca_non_unique(ptr nofree undef, i32 [[IN]], i1 noundef [[C]]) #[[ATTR25:[0-9]+]]
; CGSCC-NEXT: ret i1 [[R]]
;
%r = call i1 @alloca_non_unique(ptr undef, i32 %in, i1 %c)
ret i1 %r
}
; Ensure we do not return %bad or %l, but %sel
define i32 @scope_value_traversal(i32 %bad, i1 %c, i1 %c2) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@scope_value_traversal
; TUNIT-SAME: (i32 [[BAD:%.*]], i1 [[C:%.*]], i1 [[C2:%.*]]) #[[ATTR4]] {
; TUNIT-NEXT: [[A:%.*]] = alloca i32, align 4
; TUNIT-NEXT: store i32 [[BAD]], ptr [[A]], align 4
; TUNIT-NEXT: call void @scope_value_traversal_helper(ptr noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A]], i1 [[C2]]) #[[ATTR22:[0-9]+]]
; TUNIT-NEXT: [[L:%.*]] = load i32, ptr [[A]], align 4
; TUNIT-NEXT: [[SEL:%.*]] = select i1 [[C]], i32 [[BAD]], i32 [[L]]
; TUNIT-NEXT: ret i32 [[SEL]]
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@scope_value_traversal
; CGSCC-SAME: (i32 [[BAD:%.*]], i1 [[C:%.*]], i1 [[C2:%.*]]) #[[ATTR16:[0-9]+]] {
; CGSCC-NEXT: [[A:%.*]] = alloca i32, align 4
; CGSCC-NEXT: store i32 [[BAD]], ptr [[A]], align 4
; CGSCC-NEXT: call void @scope_value_traversal_helper(ptr noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A]], i1 [[C2]]) #[[ATTR26:[0-9]+]]
; CGSCC-NEXT: [[L:%.*]] = load i32, ptr [[A]], align 4
; CGSCC-NEXT: [[SEL:%.*]] = select i1 [[C]], i32 [[BAD]], i32 [[L]]
; CGSCC-NEXT: ret i32 [[SEL]]
;
%a = alloca i32
store i32 %bad, ptr %a
call void @scope_value_traversal_helper(ptr %a, i1 %c2)
%l = load i32, ptr %a
%sel = select i1 %c, i32 %bad, i32 %l
ret i32 %sel
}
define void @scope_value_traversal_helper(ptr %a, i1 %c) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)
; TUNIT-LABEL: define {{[^@]+}}@scope_value_traversal_helper
; TUNIT-SAME: (ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A:%.*]], i1 [[C:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT: [[L:%.*]] = load i32, ptr [[A]], align 4
; TUNIT-NEXT: [[SEL:%.*]] = select i1 [[C]], i32 [[L]], i32 42
; TUNIT-NEXT: store i32 [[SEL]], ptr [[A]], align 4
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)
; CGSCC-LABEL: define {{[^@]+}}@scope_value_traversal_helper
; CGSCC-SAME: (ptr nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A:%.*]], i1 [[C:%.*]]) #[[ATTR13]] {
; CGSCC-NEXT: [[L:%.*]] = load i32, ptr [[A]], align 4
; CGSCC-NEXT: [[SEL:%.*]] = select i1 [[C]], i32 [[L]], i32 42
; CGSCC-NEXT: store i32 [[SEL]], ptr [[A]], align 4
; CGSCC-NEXT: ret void
;
%l = load i32, ptr %a
%sel = select i1 %c, i32 %l, i32 42
store i32 %sel, ptr %a
ret void
}
define i8 @gep_index_from_binary_operator(i1 %cnd1, i1 %cnd2) {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CHECK-LABEL: define {{[^@]+}}@gep_index_from_binary_operator
; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR4]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16
; CHECK-NEXT: [[GEP_FIXED:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 12
; CHECK-NEXT: ret i8 100
;
entry:
%Bytes = alloca [1024 x i8], align 16
%offset = add i64 5, 7
%gep.fixed = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 12
%gep.sum = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 %offset
store i8 100, ptr %gep.fixed, align 4
%i = load i8, ptr %gep.sum, align 4
ret i8 %i
}
define i8 @gep_index_from_memory(i1 %cnd1, i1 %cnd2) {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CHECK-LABEL: define {{[^@]+}}@gep_index_from_memory
; CHECK-SAME: (i1 [[CND1:%.*]], i1 [[CND2:%.*]]) #[[ATTR4]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[BYTES:%.*]] = alloca [1024 x i8], align 16
; CHECK-NEXT: [[GEP_LOADED:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 12
; CHECK-NEXT: ret i8 100
;
entry:
%Bytes = alloca [1024 x i8], align 16
%addr = alloca i64, align 16
store i64 12, ptr %addr, align 8
%offset = load i64, ptr %addr, align 8
%gep.fixed = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 12
%gep.loaded = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 %offset
store i8 100, ptr %gep.loaded, align 4
%i = load i8, ptr %gep.fixed, align 4
ret i8 %i
}
@G = internal global i32 0, align 4
; Ensure this is not flattened to return 3
define i32 @a(i1 %c) {
; TUNIT: Function Attrs: nofree nosync nounwind
; TUNIT-LABEL: define {{[^@]+}}@a
; TUNIT-SAME: (i1 noundef [[C:%.*]]) #[[ATTR14]] {
; TUNIT-NEXT: store i32 3, ptr @G, align 4
; TUNIT-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; TUNIT: t:
; TUNIT-NEXT: [[REC:%.*]] = call i32 @a(i1 noundef false) #[[ATTR14]]
; TUNIT-NEXT: br label [[F]]
; TUNIT: f:
; TUNIT-NEXT: [[R:%.*]] = load i32, ptr @G, align 4
; TUNIT-NEXT: store i32 5, ptr @G, align 4
; TUNIT-NEXT: ret i32 [[R]]
;
; CGSCC: Function Attrs: nofree nosync nounwind
; CGSCC-LABEL: define {{[^@]+}}@a
; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR17]] {
; CGSCC-NEXT: store i32 3, ptr @G, align 4
; CGSCC-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; CGSCC: t:
; CGSCC-NEXT: [[REC:%.*]] = call i32 @a(i1 noundef false) #[[ATTR17]]
; CGSCC-NEXT: br label [[F]]
; CGSCC: f:
; CGSCC-NEXT: [[R:%.*]] = load i32, ptr @G, align 4
; CGSCC-NEXT: store i32 5, ptr @G, align 4
; CGSCC-NEXT: ret i32 [[R]]
;
store i32 3, ptr @G
br i1 %c, label %t, label %f
t:
%rec = call i32 @a(i1 false)
br label %f
f:
%r = load i32, ptr @G
store i32 5, ptr @G
ret i32 %r
}
@GC = internal global i32 undef, align 4
define void @atomicrmw(ptr %p, i32 %i, i1 %cnd) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; TUNIT-LABEL: define {{[^@]+}}@atomicrmw
; TUNIT-SAME: (ptr nofree [[P:%.*]], i32 [[I:%.*]], i1 noundef [[CND:%.*]]) #[[ATTR3]] {
; TUNIT-NEXT: br i1 [[CND]], label [[T:%.*]], label [[M:%.*]]
; TUNIT: t:
; TUNIT-NEXT: br label [[M]]
; TUNIT: m:
; TUNIT-NEXT: [[ARMW:%.*]] = atomicrmw add ptr @GC, i32 [[I]] monotonic, align 4
; TUNIT-NEXT: ret void
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@atomicrmw
; CGSCC-SAME: (ptr nofree [[P:%.*]], i32 [[I:%.*]], i1 noundef [[CND:%.*]]) #[[ATTR5]] {
; CGSCC-NEXT: br i1 [[CND]], label [[T:%.*]], label [[M:%.*]]
; CGSCC: t:
; CGSCC-NEXT: br label [[M]]
; CGSCC: m:
; CGSCC-NEXT: [[ARMW:%.*]] = atomicrmw add ptr @GC, i32 [[I]] monotonic, align 4
; CGSCC-NEXT: ret void
;
%alloca = alloca <2 x ptr>
%gep1 = getelementptr ptr, ptr %alloca, i32 0
%gep2 = getelementptr ptr, ptr %alloca, i32 1
store <2 x ptr> <ptr @GC, ptr @GC>, ptr %alloca
br i1 %cnd, label %t, label %m
t:
store ptr null, ptr %gep2
br label %m
m:
%l1 = load ptr, ptr %gep1
%l2 = load ptr, ptr %gep2
%c1 = icmp eq ptr %l2, %p
call void @llvm.assume(i1 %c1)
%s = select i1 true, ptr %l1, ptr %l2
%armw = atomicrmw add ptr %s, i32 %i monotonic
ret void
}
@GRS = internal thread_local global i32 undef
@GRS2 = global i32 undef
define i32 @recSimplify(i32 %v, i1 %cond) {
; TUNIT: Function Attrs: nofree nosync nounwind
; TUNIT-LABEL: define {{[^@]+}}@recSimplify
; TUNIT-SAME: (i32 [[V:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR14]] {
; TUNIT-NEXT: br i1 [[COND]], label [[REC:%.*]], label [[COMP:%.*]]
; TUNIT: rec:
; TUNIT-NEXT: [[RV:%.*]] = call i32 @recSimplify(i32 undef, i1 noundef false) #[[ATTR14]]
; TUNIT-NEXT: ret i32 1
; TUNIT: comp:
; TUNIT-NEXT: store i32 1, ptr @GRS2, align 4
; TUNIT-NEXT: ret i32 1
;
; CGSCC: Function Attrs: nofree nosync nounwind
; CGSCC-LABEL: define {{[^@]+}}@recSimplify
; CGSCC-SAME: (i32 [[V:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR17]] {
; CGSCC-NEXT: br i1 [[COND]], label [[REC:%.*]], label [[COMP:%.*]]
; CGSCC: rec:
; CGSCC-NEXT: [[RV:%.*]] = call i32 @recSimplify(i32 [[V]], i1 noundef false) #[[ATTR17]]
; CGSCC-NEXT: ret i32 [[RV]]
; CGSCC: comp:
; CGSCC-NEXT: store i32 [[V]], ptr @GRS, align 4
; CGSCC-NEXT: store i32 1, ptr @GRS2, align 4
; CGSCC-NEXT: [[L:%.*]] = load i32, ptr @GRS, align 4
; CGSCC-NEXT: [[C:%.*]] = icmp eq i32 [[L]], 1
; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[C]]) #[[ATTR27:[0-9]+]]
; CGSCC-NEXT: [[R:%.*]] = call i32 @recSimplify2() #[[ATTR27]]
; CGSCC-NEXT: ret i32 [[R]]
;
br i1 %cond, label %rec, label %comp
rec:
%rv = call i32 @recSimplify(i32 %v, i1 false)
ret i32 %rv
comp:
store i32 %v, ptr @GRS
%s1 = select i1 %cond, i32 1, i32 1
%s2 = select i1 %cond, i32 1, i32 %s1
store i32 %s2, ptr @GRS2
%l = load i32, ptr @GRS
%c = icmp eq i32 %l, %s2
call void @llvm.assume(i1 %c)
%r = call i32 @recSimplify2()
ret i32 %r
}
define internal i32 @recSimplify2() {
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read)
; CGSCC-LABEL: define {{[^@]+}}@recSimplify2
; CGSCC-SAME: () #[[ATTR7]] {
; CGSCC-NEXT: [[R:%.*]] = load i32, ptr @GRS, align 4
; CGSCC-NEXT: ret i32 [[R]]
;
%r = load i32, ptr @GRS
ret i32 %r
}
; Verify we do not return 10.
define i32 @may_access_after_return(i32 noundef %N, i32 noundef %M) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@may_access_after_return
; TUNIT-SAME: (i32 noundef [[N:%.*]], i32 noundef [[M:%.*]]) #[[ATTR4]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[A:%.*]] = alloca i32, align 4
; TUNIT-NEXT: [[B:%.*]] = alloca i32, align 4
; TUNIT-NEXT: call void @write_both(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A]], ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[B]]) #[[ATTR18]]
; TUNIT-NEXT: ret i32 8
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@may_access_after_return
; CGSCC-SAME: (i32 noundef [[N:%.*]], i32 noundef [[M:%.*]]) #[[ATTR16]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[A:%.*]] = alloca i32, align 4
; CGSCC-NEXT: [[B:%.*]] = alloca i32, align 4
; CGSCC-NEXT: call void @write_both(ptr noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A]], ptr noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[B]]) #[[ATTR21]]
; CGSCC-NEXT: [[TMP0:%.*]] = load i32, ptr [[A]], align 4
; CGSCC-NEXT: [[TMP1:%.*]] = load i32, ptr [[B]], align 4
; CGSCC-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[TMP1]]
; CGSCC-NEXT: ret i32 [[ADD]]
;
entry:
%A = alloca i32, align 4
%B = alloca i32, align 4
%call = call ptr @passthrough(ptr noundef %A)
%call1 = call ptr @passthrough(ptr noundef %B)
call void @write_both(ptr noundef %call, ptr noundef %call1)
%0 = load i32, ptr %A, align 4
%1 = load i32, ptr %B, align 4
%add = add nsw i32 %0, %1
ret i32 %add
}
define internal void @write_both(ptr noundef %Q, ptr noundef %R) {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
; CHECK-LABEL: define {{[^@]+}}@write_both
; CHECK-SAME: (ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[Q:%.*]], ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[R:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: store i32 3, ptr [[Q]], align 4
; CHECK-NEXT: store i32 5, ptr [[R]], align 4
; CHECK-NEXT: ret void
;
entry:
store i32 3, ptr %Q, align 4
store i32 5, ptr %R, align 4
ret void
}
define internal ptr @passthrough(ptr noundef %P) {
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@passthrough
; CGSCC-SAME: (ptr noalias nofree noundef nonnull readnone returned align 4 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR4]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: ret ptr [[P]]
;
entry:
ret ptr %P
}
; Verify we do not return 10.
define i32 @may_access_after_return_choice(i32 noundef %N, i32 noundef %M, i1 %c) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@may_access_after_return_choice
; TUNIT-SAME: (i32 noundef [[N:%.*]], i32 noundef [[M:%.*]], i1 [[C:%.*]]) #[[ATTR4]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[A:%.*]] = alloca i32, align 4
; TUNIT-NEXT: [[B:%.*]] = alloca i32, align 4
; TUNIT-NEXT: [[CALL:%.*]] = call nonnull align 4 dereferenceable(4) ptr @passthrough_choice(i1 [[C]], ptr noalias nofree noundef nonnull readnone align 4 dereferenceable(4) "no-capture-maybe-returned" [[A]], ptr noalias nofree noundef nonnull readnone align 4 dereferenceable(4) "no-capture-maybe-returned" [[B]]) #[[ATTR23:[0-9]+]]
; TUNIT-NEXT: [[CALL1:%.*]] = call nonnull align 4 dereferenceable(4) ptr @passthrough_choice(i1 [[C]], ptr noalias nofree noundef nonnull readnone align 4 dereferenceable(4) "no-capture-maybe-returned" [[B]], ptr noalias nofree noundef nonnull readnone align 4 dereferenceable(4) "no-capture-maybe-returned" [[A]]) #[[ATTR23]]
; TUNIT-NEXT: call void @write_both(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[CALL]], ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[CALL1]]) #[[ATTR18]]
; TUNIT-NEXT: [[TMP0:%.*]] = load i32, ptr [[A]], align 4
; TUNIT-NEXT: [[TMP1:%.*]] = load i32, ptr [[B]], align 4
; TUNIT-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[TMP1]]
; TUNIT-NEXT: ret i32 [[ADD]]
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn
; CGSCC-LABEL: define {{[^@]+}}@may_access_after_return_choice
; CGSCC-SAME: (i32 noundef [[N:%.*]], i32 noundef [[M:%.*]], i1 [[C:%.*]]) #[[ATTR3]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[A:%.*]] = alloca i32, align 4
; CGSCC-NEXT: [[B:%.*]] = alloca i32, align 4
; CGSCC-NEXT: [[CALL:%.*]] = call nonnull align 4 dereferenceable(4) ptr @passthrough_choice(i1 [[C]], ptr noalias nofree noundef nonnull readnone align 4 dereferenceable(4) [[A]], ptr noalias nofree noundef nonnull readnone align 4 dereferenceable(4) [[B]]) #[[ATTR28:[0-9]+]]
; CGSCC-NEXT: [[CALL1:%.*]] = call nonnull align 4 dereferenceable(4) ptr @passthrough_choice(i1 [[C]], ptr noalias nofree noundef nonnull readnone align 4 dereferenceable(4) [[B]], ptr noalias nofree noundef nonnull readnone align 4 dereferenceable(4) [[A]]) #[[ATTR28]]
; CGSCC-NEXT: call void @write_both(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[CALL]], ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[CALL1]]) #[[ATTR21]]
; CGSCC-NEXT: [[TMP0:%.*]] = load i32, ptr [[A]], align 4
; CGSCC-NEXT: [[TMP1:%.*]] = load i32, ptr [[B]], align 4
; CGSCC-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[TMP1]]
; CGSCC-NEXT: ret i32 [[ADD]]
;
entry:
%A = alloca i32, align 4
%B = alloca i32, align 4
%call = call ptr @passthrough_choice(i1 %c, ptr noundef %A, ptr noundef %B)
%call1 = call ptr @passthrough_choice(i1 %c, ptr noundef %B, ptr noundef %A)
call void @write_both(ptr noundef %call, ptr noundef %call1)
%0 = load i32, ptr %A, align 4
%1 = load i32, ptr %B, align 4
%add = add nsw i32 %0, %1
ret i32 %add
}
define internal ptr @passthrough_choice(i1 %c, ptr noundef %P, ptr noundef %Q) {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CHECK-LABEL: define {{[^@]+}}@passthrough_choice
; CHECK-SAME: (i1 [[C:%.*]], ptr noalias nofree noundef nonnull readnone align 4 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]], ptr noalias nofree noundef nonnull readnone align 4 dereferenceable(4) "no-capture-maybe-returned" [[Q:%.*]]) #[[ATTR4]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], ptr [[P]], ptr [[Q]]
; CHECK-NEXT: ret ptr [[R]]
;
entry:
%R = select i1 %c, ptr %P, ptr %Q
ret ptr %R
}
; Verify we do not return 10.
define i32 @may_access_after_return_no_choice1(i32 noundef %N, i32 noundef %M) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@may_access_after_return_no_choice1
; TUNIT-SAME: (i32 noundef [[N:%.*]], i32 noundef [[M:%.*]]) #[[ATTR4]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[A:%.*]] = alloca i32, align 4
; TUNIT-NEXT: [[B:%.*]] = alloca i32, align 4
; TUNIT-NEXT: call void @write_both(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A]], ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[B]]) #[[ATTR18]]
; TUNIT-NEXT: ret i32 8
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@may_access_after_return_no_choice1
; CGSCC-SAME: (i32 noundef [[N:%.*]], i32 noundef [[M:%.*]]) #[[ATTR16]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[A:%.*]] = alloca i32, align 4
; CGSCC-NEXT: [[B:%.*]] = alloca i32, align 4
; CGSCC-NEXT: call void @write_both(ptr noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A]], ptr noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[B]]) #[[ATTR21]]
; CGSCC-NEXT: [[TMP0:%.*]] = load i32, ptr [[A]], align 4
; CGSCC-NEXT: [[TMP1:%.*]] = load i32, ptr [[B]], align 4
; CGSCC-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[TMP1]]
; CGSCC-NEXT: ret i32 [[ADD]]
;
entry:
%A = alloca i32, align 4
%B = alloca i32, align 4
%call = call ptr @passthrough_no_choice_true(i1 true, ptr noundef %A, ptr noundef %B)
%call1 = call ptr @passthrough_no_choice_true(i1 true, ptr noundef %B, ptr noundef %A)
call void @write_both(ptr noundef %call, ptr noundef %call1)
%0 = load i32, ptr %A, align 4
%1 = load i32, ptr %B, align 4
%add = add nsw i32 %0, %1
ret i32 %add
}
; Verify we do not return 10.
define i32 @may_access_after_return_no_choice2(i32 noundef %N, i32 noundef %M) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@may_access_after_return_no_choice2
; TUNIT-SAME: (i32 noundef [[N:%.*]], i32 noundef [[M:%.*]]) #[[ATTR4]] {
; TUNIT-NEXT: entry:
; TUNIT-NEXT: [[A:%.*]] = alloca i32, align 4
; TUNIT-NEXT: [[B:%.*]] = alloca i32, align 4
; TUNIT-NEXT: call void @write_both(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[B]], ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A]]) #[[ATTR18]]
; TUNIT-NEXT: ret i32 8
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@may_access_after_return_no_choice2
; CGSCC-SAME: (i32 noundef [[N:%.*]], i32 noundef [[M:%.*]]) #[[ATTR16]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[A:%.*]] = alloca i32, align 4
; CGSCC-NEXT: [[B:%.*]] = alloca i32, align 4
; CGSCC-NEXT: call void @write_both(ptr noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[B]], ptr noalias nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A]]) #[[ATTR21]]
; CGSCC-NEXT: [[TMP0:%.*]] = load i32, ptr [[A]], align 4
; CGSCC-NEXT: [[TMP1:%.*]] = load i32, ptr [[B]], align 4
; CGSCC-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[TMP1]]
; CGSCC-NEXT: ret i32 [[ADD]]
;
entry:
%A = alloca i32, align 4
%B = alloca i32, align 4
%call = call ptr @passthrough_no_choice_false(i1 false, ptr noundef %A, ptr noundef %B)
%call1 = call ptr @passthrough_no_choice_false(i1 false, ptr noundef %B, ptr noundef %A)
call void @write_both(ptr noundef %call, ptr noundef %call1)
%0 = load i32, ptr %A, align 4
%1 = load i32, ptr %B, align 4
%add = add nsw i32 %0, %1
ret i32 %add
}
define internal ptr @passthrough_no_choice_true(i1 %c, ptr noundef %P, ptr noundef %Q) {
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@passthrough_no_choice_true
; CGSCC-SAME: (ptr noalias nofree noundef nonnull readnone returned align 4 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]], i32 [[TMP0:%.*]]) #[[ATTR4]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[Q_PRIV:%.*]] = alloca i32, align 4
; CGSCC-NEXT: store i32 [[TMP0]], ptr [[Q_PRIV]], align 4
; CGSCC-NEXT: ret ptr [[P]]
;
entry:
%R = select i1 %c, ptr %P, ptr %Q
ret ptr %R
}
define internal ptr @passthrough_no_choice_false(i1 %c, ptr noundef %P, ptr noundef %Q) {
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@passthrough_no_choice_false
; CGSCC-SAME: (i32 [[TMP0:%.*]], ptr noalias nofree noundef nonnull readnone returned align 4 dereferenceable(4) "no-capture-maybe-returned" [[Q:%.*]]) #[[ATTR4]] {
; CGSCC-NEXT: entry:
; CGSCC-NEXT: [[P_PRIV:%.*]] = alloca i32, align 4
; CGSCC-NEXT: store i32 [[TMP0]], ptr [[P_PRIV]], align 4
; CGSCC-NEXT: ret ptr [[Q]]
;
entry:
%R = select i1 %c, ptr %P, ptr %Q
ret ptr %R
}
define ptr @move2(ptr %p) {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CHECK-LABEL: define {{[^@]+}}@move2
; CHECK-SAME: (ptr nofree readnone "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR4]] {
; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[P]], i32 2
; CHECK-NEXT: ret ptr [[G]]
;
%g = getelementptr i8, ptr %p, i32 2
ret ptr %g
}
define internal ptr @move4(ptr %p) {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CHECK-LABEL: define {{[^@]+}}@move4
; CHECK-SAME: (ptr noalias nofree readnone "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR4]] {
; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[P]], i32 4
; CHECK-NEXT: ret ptr [[G]]
;
%g = getelementptr i8, ptr %p, i32 4
ret ptr %g
}
define ptr @move246(i32 %i, ptr %p) {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CHECK-LABEL: define {{[^@]+}}@move246
; CHECK-SAME: (i32 [[I:%.*]], ptr nofree readnone "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR4]] {
; CHECK-NEXT: [[C0:%.*]] = icmp eq i32 [[I]], 0
; CHECK-NEXT: br i1 [[C0]], label [[BG2:%.*]], label [[BG46:%.*]]
; CHECK: bg2:
; CHECK-NEXT: [[G2:%.*]] = getelementptr i8, ptr [[P]], i32 2
; CHECK-NEXT: ret ptr [[G2]]
; CHECK: bg46:
; CHECK-NEXT: [[C1:%.*]] = icmp eq i32 [[I]], 1
; CHECK-NEXT: br i1 [[C1]], label [[BG4:%.*]], label [[BG6:%.*]]
; CHECK: bg4:
; CHECK-NEXT: [[G4:%.*]] = getelementptr i8, ptr [[P]], i32 4
; CHECK-NEXT: ret ptr [[G4]]
; CHECK: bg6:
; CHECK-NEXT: [[G6:%.*]] = getelementptr i8, ptr [[P]], i32 6
; CHECK-NEXT: ret ptr [[G6]]
;
%c0 = icmp eq i32 %i, 0
br i1 %c0, label %bg2, label %bg46
bg2:
%g2 = getelementptr i8, ptr %p, i32 2
ret ptr %g2
bg46:
%c1 = icmp eq i32 %i, 1
br i1 %c1, label %bg4, label %bg6
bg4:
%g4 = getelementptr i8, ptr %p, i32 4
ret ptr %g4
bg6:
%g6 = getelementptr i8, ptr %p, i32 6
ret ptr %g6
}
declare void @use3i8(i8, i8, i8)
define void @returnedPtrAccesses() {
; TUNIT-LABEL: define {{[^@]+}}@returnedPtrAccesses() {
; TUNIT-NEXT: [[A:%.*]] = alloca i64, align 8
; TUNIT-NEXT: [[A2:%.*]] = call ptr @move2(ptr noalias nofree noundef nonnull readnone align 8 dereferenceable(8) "no-capture-maybe-returned" [[A]]) #[[ATTR23]]
; TUNIT-NEXT: [[A4:%.*]] = call ptr @move4(ptr noalias nofree noundef nonnull readnone align 8 dereferenceable(8) "no-capture-maybe-returned" [[A]]) #[[ATTR23]]
; TUNIT-NEXT: [[A6:%.*]] = call ptr @move4(ptr noalias nofree readnone "no-capture-maybe-returned" [[A2]]) #[[ATTR23]]
; TUNIT-NEXT: store i8 2, ptr [[A2]], align 1
; TUNIT-NEXT: store i8 4, ptr [[A4]], align 1
; TUNIT-NEXT: store i8 6, ptr [[A6]], align 1
; TUNIT-NEXT: call void @use3i8(i8 2, i8 4, i8 6)
; TUNIT-NEXT: ret void
;
; CGSCC-LABEL: define {{[^@]+}}@returnedPtrAccesses() {
; CGSCC-NEXT: [[A:%.*]] = alloca i64, align 8
; CGSCC-NEXT: [[A2:%.*]] = call nonnull dereferenceable(1) ptr @move2(ptr noalias nofree noundef nonnull readnone align 8 dereferenceable(8) [[A]]) #[[ATTR20]]
; CGSCC-NEXT: [[A4:%.*]] = call ptr @move4(ptr noalias nofree noundef nonnull readnone align 8 dereferenceable(8) [[A]]) #[[ATTR20]]
; CGSCC-NEXT: [[A6:%.*]] = call ptr @move4(ptr noalias nofree noundef nonnull readnone dereferenceable(1) [[A2]]) #[[ATTR20]]
; CGSCC-NEXT: [[G2:%.*]] = getelementptr i8, ptr [[A]], i32 2
; CGSCC-NEXT: [[G4:%.*]] = getelementptr i8, ptr [[A]], i32 4
; CGSCC-NEXT: [[G6:%.*]] = getelementptr i8, ptr [[A]], i32 6
; CGSCC-NEXT: store i8 2, ptr [[A2]], align 1
; CGSCC-NEXT: store i8 4, ptr [[A4]], align 1
; CGSCC-NEXT: store i8 6, ptr [[A6]], align 1
; CGSCC-NEXT: [[L2:%.*]] = load i8, ptr [[G2]], align 2
; CGSCC-NEXT: [[L4:%.*]] = load i8, ptr [[G4]], align 4
; CGSCC-NEXT: [[L6:%.*]] = load i8, ptr [[G6]], align 2
; CGSCC-NEXT: call void @use3i8(i8 [[L2]], i8 [[L4]], i8 [[L6]])
; CGSCC-NEXT: ret void
;
%a = alloca i64
%a2 = call ptr @move2(ptr %a)
%a4 = call ptr @move4(ptr %a)
%a6 = call ptr @move4(ptr %a2)
%g2 = getelementptr i8, ptr %a, i32 2
%g4 = getelementptr i8, ptr %a, i32 4
%g6 = getelementptr i8, ptr %a, i32 6
store i8 2, ptr %a2
store i8 4, ptr %a4
store i8 6, ptr %a6
%l2 = load i8, ptr %g2
%l4 = load i8, ptr %g4
%l6 = load i8, ptr %g6
call void @use3i8(i8 %l2, i8 %l4, i8 %l6)
ret void
}
define void @returnedPtrAccessesMultiple(i32 %i) {
; TUNIT-LABEL: define {{[^@]+}}@returnedPtrAccessesMultiple
; TUNIT-SAME: (i32 [[I:%.*]]) {
; TUNIT-NEXT: [[A:%.*]] = alloca i64, align 8
; TUNIT-NEXT: [[AP:%.*]] = call ptr @move246(i32 [[I]], ptr noalias nofree noundef nonnull readnone align 8 dereferenceable(8) "no-capture-maybe-returned" [[A]]) #[[ATTR23]]
; TUNIT-NEXT: store i8 2, ptr [[AP]], align 1
; TUNIT-NEXT: call void @use3i8(i8 2, i8 2, i8 2)
; TUNIT-NEXT: ret void
;
; CGSCC-LABEL: define {{[^@]+}}@returnedPtrAccessesMultiple
; CGSCC-SAME: (i32 [[I:%.*]]) {
; CGSCC-NEXT: [[A:%.*]] = alloca i64, align 8
; CGSCC-NEXT: [[AP:%.*]] = call ptr @move246(i32 [[I]], ptr noalias nofree noundef nonnull readnone align 8 dereferenceable(8) [[A]]) #[[ATTR20]]
; CGSCC-NEXT: [[G2:%.*]] = getelementptr i8, ptr [[A]], i32 2
; CGSCC-NEXT: [[G4:%.*]] = getelementptr i8, ptr [[A]], i32 4
; CGSCC-NEXT: [[G6:%.*]] = getelementptr i8, ptr [[A]], i32 6
; CGSCC-NEXT: store i8 2, ptr [[AP]], align 1
; CGSCC-NEXT: [[L2:%.*]] = load i8, ptr [[G2]], align 2
; CGSCC-NEXT: [[L4:%.*]] = load i8, ptr [[G4]], align 4
; CGSCC-NEXT: [[L6:%.*]] = load i8, ptr [[G6]], align 2
; CGSCC-NEXT: call void @use3i8(i8 [[L2]], i8 [[L4]], i8 [[L6]])
; CGSCC-NEXT: ret void
;
%a = alloca i64
%ap = call ptr @move246(i32 %i, ptr %a)
%g2 = getelementptr i8, ptr %a, i32 2
%g4 = getelementptr i8, ptr %a, i32 4
%g6 = getelementptr i8, ptr %a, i32 6
store i8 2, ptr %ap
%l2 = load i8, ptr %g2
%l4 = load i8, ptr %g4
%l6 = load i8, ptr %g6
call void @use3i8(i8 %l2, i8 %l4, i8 %l6)
ret void
}
define void @returnedPtrAccessesMultiple2(i32 %i) {
; TUNIT-LABEL: define {{[^@]+}}@returnedPtrAccessesMultiple2
; TUNIT-SAME: (i32 [[I:%.*]]) {
; TUNIT-NEXT: [[A:%.*]] = alloca i64, align 8
; TUNIT-NEXT: [[G2:%.*]] = getelementptr i8, ptr [[A]], i32 2
; TUNIT-NEXT: [[G4:%.*]] = getelementptr i8, ptr [[A]], i32 4
; TUNIT-NEXT: [[G6:%.*]] = getelementptr i8, ptr [[A]], i32 6
; TUNIT-NEXT: store i8 0, ptr [[G2]], align 2
; TUNIT-NEXT: store i8 0, ptr [[G4]], align 4
; TUNIT-NEXT: store i8 0, ptr [[G6]], align 2
; TUNIT-NEXT: [[AP:%.*]] = call ptr @move246(i32 [[I]], ptr noalias nofree noundef nonnull readnone align 8 dereferenceable(8) "no-capture-maybe-returned" [[A]]) #[[ATTR23]]
; TUNIT-NEXT: store i8 2, ptr [[AP]], align 1
; TUNIT-NEXT: [[L2:%.*]] = load i8, ptr [[G2]], align 2
; TUNIT-NEXT: [[L4:%.*]] = load i8, ptr [[G4]], align 4
; TUNIT-NEXT: [[L6:%.*]] = load i8, ptr [[G6]], align 2
; TUNIT-NEXT: call void @use3i8(i8 noundef [[L2]], i8 noundef [[L4]], i8 noundef [[L6]])
; TUNIT-NEXT: ret void
;
; CGSCC-LABEL: define {{[^@]+}}@returnedPtrAccessesMultiple2
; CGSCC-SAME: (i32 [[I:%.*]]) {
; CGSCC-NEXT: [[A:%.*]] = alloca i64, align 8
; CGSCC-NEXT: [[G2:%.*]] = getelementptr i8, ptr [[A]], i32 2
; CGSCC-NEXT: [[G4:%.*]] = getelementptr i8, ptr [[A]], i32 4
; CGSCC-NEXT: [[G6:%.*]] = getelementptr i8, ptr [[A]], i32 6
; CGSCC-NEXT: store i8 0, ptr [[G2]], align 2
; CGSCC-NEXT: store i8 0, ptr [[G4]], align 4
; CGSCC-NEXT: store i8 0, ptr [[G6]], align 2
; CGSCC-NEXT: [[AP:%.*]] = call ptr @move246(i32 [[I]], ptr noalias nofree noundef nonnull readnone align 8 dereferenceable(8) [[A]]) #[[ATTR20]]
; CGSCC-NEXT: store i8 2, ptr [[AP]], align 1
; CGSCC-NEXT: [[L2:%.*]] = load i8, ptr [[G2]], align 2
; CGSCC-NEXT: [[L4:%.*]] = load i8, ptr [[G4]], align 4
; CGSCC-NEXT: [[L6:%.*]] = load i8, ptr [[G6]], align 2
; CGSCC-NEXT: call void @use3i8(i8 [[L2]], i8 [[L4]], i8 [[L6]])
; CGSCC-NEXT: ret void
;
%a = alloca i64
%g2 = getelementptr i8, ptr %a, i32 2
%g4 = getelementptr i8, ptr %a, i32 4
%g6 = getelementptr i8, ptr %a, i32 6
store i8 0, ptr %g2
store i8 0, ptr %g4
store i8 0, ptr %g6
%ap = call ptr @move246(i32 %i, ptr %a)
store i8 2, ptr %ap
%l2 = load i8, ptr %g2
%l4 = load i8, ptr %g4
%l6 = load i8, ptr %g6
call void @use3i8(i8 %l2, i8 %l4, i8 %l6)
ret void
}
declare void @llvm.assume(i1 noundef)
!llvm.module.flags = !{!0, !1}
!llvm.ident = !{!2}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 7, !"uwtable", i32 1}
!2 = !{!"clang version 13.0.0"}
!3 = !{!4, !4, i64 0}
!4 = !{!"int", !5, i64 0}
!5 = !{!"omnipotent char", !6, i64 0}
!6 = !{!"Simple C/C++ TBAA"}
!7 = !{!8, !9, i64 12}
!8 = !{!"S", !4, i64 0, !4, i64 4, !4, i64 8, !9, i64 12, !9, i64 16, !9, i64 20}
!9 = !{!"float", !5, i64 0}
!10 = !{!8, !9, i64 16}
!11 = !{!8, !9, i64 20}
!12 = !{!8, !4, i64 0}
!13 = !{!8, !4, i64 4}
!14 = !{!8, !4, i64 8}
!15 = !{!5, !5, i64 0}
!16 = distinct !{!16, !17}
!17 = !{!"llvm.loop.mustprogress"}
!18 = !{!9, !9, i64 0}
!19 = distinct !{!19, !17}
!20 = !{!21, !21, i64 0}
!21 = !{!"long long", !5, i64 0}
!22 = distinct !{!22, !17}
!23 = distinct !{!23, !17}
!24 = distinct !{!24, !17}
!25 = distinct !{!25, !17}
!26 = distinct !{!26, !17}
!27 = distinct !{!27, !17}
!28 = distinct !{!28, !17}
!29 = distinct !{!29, !17}
!30 = distinct !{!30, !17}
!31 = distinct !{!31, !17}
;.
; TUNIT: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
; TUNIT: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) }
; TUNIT: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
; TUNIT: attributes #[[ATTR3]] = { mustprogress nofree norecurse nosync nounwind willreturn }
; TUNIT: attributes #[[ATTR4]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
; TUNIT: attributes #[[ATTR5]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) }
; TUNIT: attributes #[[ATTR6]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(read) }
; TUNIT: attributes #[[ATTR7]] = { nofree norecurse nosync nounwind memory(write) }
; TUNIT: attributes #[[ATTR8:[0-9]+]] = { allockind("alloc,uninitialized") allocsize(0) "alloc-family"="malloc" }
; TUNIT: attributes #[[ATTR9:[0-9]+]] = { allockind("free") "alloc-family"="malloc" }
; TUNIT: attributes #[[ATTR10:[0-9]+]] = { allockind("alloc,zeroed") allocsize(0,1) "alloc-family"="malloc" }
; TUNIT: attributes #[[ATTR11]] = { mustprogress nofree norecurse nosync nounwind willreturn uwtable }
; TUNIT: attributes #[[ATTR12]] = { nofree nosync nounwind memory(argmem: readwrite) }
; TUNIT: attributes #[[ATTR13]] = { nofree norecurse nosync nounwind memory(none) }
; TUNIT: attributes #[[ATTR14]] = { nofree nosync nounwind }
; TUNIT: attributes #[[ATTR15:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }
; TUNIT: attributes #[[ATTR16:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
; TUNIT: attributes #[[ATTR17]] = { nofree willreturn }
; TUNIT: attributes #[[ATTR18]] = { nofree nosync nounwind willreturn memory(write) }
; TUNIT: attributes #[[ATTR19]] = { nocallback }
; TUNIT: attributes #[[ATTR20]] = { norecurse }
; TUNIT: attributes #[[ATTR21]] = { nounwind }
; TUNIT: attributes #[[ATTR22]] = { nofree nosync nounwind willreturn }
; TUNIT: attributes #[[ATTR23]] = { nofree nosync nounwind willreturn memory(none) }
;.
; CGSCC: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree nosync nounwind willreturn memory(argmem: readwrite) }
; CGSCC: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
; CGSCC: attributes #[[ATTR3]] = { mustprogress nofree nosync nounwind willreturn }
; CGSCC: attributes #[[ATTR4]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
; CGSCC: attributes #[[ATTR5]] = { mustprogress nofree norecurse nosync nounwind willreturn }
; CGSCC: attributes #[[ATTR6]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) }
; CGSCC: attributes #[[ATTR7]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(read) }
; CGSCC: attributes #[[ATTR8]] = { nofree norecurse nosync nounwind memory(write) }
; CGSCC: attributes #[[ATTR9:[0-9]+]] = { allockind("alloc,uninitialized") allocsize(0) "alloc-family"="malloc" }
; CGSCC: attributes #[[ATTR10:[0-9]+]] = { allockind("free") "alloc-family"="malloc" }
; CGSCC: attributes #[[ATTR11:[0-9]+]] = { allockind("alloc,zeroed") allocsize(0,1) "alloc-family"="malloc" }
; CGSCC: attributes #[[ATTR12]] = { mustprogress nofree norecurse nosync nounwind willreturn uwtable }
; CGSCC: attributes #[[ATTR13]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) }
; CGSCC: attributes #[[ATTR14]] = { nofree nosync nounwind memory(argmem: readwrite) }
; CGSCC: attributes #[[ATTR15]] = { nofree nosync nounwind memory(none) }
; CGSCC: attributes #[[ATTR16]] = { mustprogress nofree nosync nounwind willreturn memory(none) }
; CGSCC: attributes #[[ATTR17]] = { nofree nosync nounwind }
; CGSCC: attributes #[[ATTR18:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }
; CGSCC: attributes #[[ATTR19:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
; CGSCC: attributes #[[ATTR20]] = { nofree willreturn }
; CGSCC: attributes #[[ATTR21]] = { nofree nounwind willreturn memory(write) }
; CGSCC: attributes #[[ATTR22]] = { nocallback }
; CGSCC: attributes #[[ATTR23]] = { norecurse }
; CGSCC: attributes #[[ATTR24]] = { nounwind }
; CGSCC: attributes #[[ATTR25]] = { nofree nounwind }
; CGSCC: attributes #[[ATTR26]] = { nofree nounwind willreturn }
; CGSCC: attributes #[[ATTR27]] = { nofree }
; CGSCC: attributes #[[ATTR28]] = { nofree nosync willreturn }
;.
; TUNIT: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
; TUNIT: [[META1:![0-9]+]] = !{i32 7, !"uwtable", i32 1}
; TUNIT: [[META2:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
; TUNIT: [[TBAA3]] = !{[[META4:![0-9]+]], [[META4]], i64 0}
; TUNIT: [[META4]] = !{!"int", [[META5:![0-9]+]], i64 0}
; TUNIT: [[META5]] = !{!"omnipotent char", [[META6:![0-9]+]], i64 0}
; TUNIT: [[META6]] = !{!"Simple C/C++ TBAA"}
; TUNIT: [[TBAA7]] = !{[[META8:![0-9]+]], [[META9:![0-9]+]], i64 12}
; TUNIT: [[META8]] = !{!"S", [[META4]], i64 0, [[META4]], i64 4, [[META4]], i64 8, [[META9]], i64 12, [[META9]], i64 16, [[META9]], i64 20}
; TUNIT: [[META9]] = !{!"float", [[META5]], i64 0}
; TUNIT: [[TBAA10]] = !{[[META8]], [[META9]], i64 16}
; TUNIT: [[TBAA11]] = !{[[META8]], [[META9]], i64 20}
; TUNIT: [[TBAA12]] = !{[[META8]], [[META4]], i64 0}
; TUNIT: [[TBAA13]] = !{[[META8]], [[META4]], i64 4}
; TUNIT: [[TBAA14]] = !{[[META8]], [[META4]], i64 8}
; TUNIT: [[LOOP15]] = distinct !{[[LOOP15]], [[META16:![0-9]+]]}
; TUNIT: [[META16]] = !{!"llvm.loop.mustprogress"}
; TUNIT: [[LOOP17]] = distinct !{[[LOOP17]], [[META16]]}
; TUNIT: [[LOOP18]] = distinct !{[[LOOP18]], [[META16]]}
; TUNIT: [[TBAA19]] = !{[[META5]], [[META5]], i64 0}
; TUNIT: [[LOOP20]] = distinct !{[[LOOP20]], [[META16]]}
; TUNIT: [[LOOP21]] = distinct !{[[LOOP21]], [[META16]]}
; TUNIT: [[LOOP22]] = distinct !{[[LOOP22]], [[META16]]}
; TUNIT: [[LOOP23]] = distinct !{[[LOOP23]], [[META16]]}
; TUNIT: [[LOOP24]] = distinct !{[[LOOP24]], [[META16]]}
; TUNIT: [[LOOP25]] = distinct !{[[LOOP25]], [[META16]]}
; TUNIT: [[TBAA26]] = !{[[META9]], [[META9]], i64 0}
; TUNIT: [[LOOP27]] = distinct !{[[LOOP27]], [[META16]]}
; TUNIT: [[TBAA28]] = !{[[META29:![0-9]+]], [[META29]], i64 0}
; TUNIT: [[META29]] = !{!"long long", [[META5]], i64 0}
; TUNIT: [[LOOP30]] = distinct !{[[LOOP30]], [[META16]]}
; TUNIT: [[LOOP31]] = distinct !{[[LOOP31]], [[META16]]}
;.
; CGSCC: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
; CGSCC: [[META1:![0-9]+]] = !{i32 7, !"uwtable", i32 1}
; CGSCC: [[META2:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
; CGSCC: [[TBAA3]] = !{[[META4:![0-9]+]], [[META4]], i64 0}
; CGSCC: [[META4]] = !{!"int", [[META5:![0-9]+]], i64 0}
; CGSCC: [[META5]] = !{!"omnipotent char", [[META6:![0-9]+]], i64 0}
; CGSCC: [[META6]] = !{!"Simple C/C++ TBAA"}
; CGSCC: [[TBAA7]] = !{[[META8:![0-9]+]], [[META9:![0-9]+]], i64 12}
; CGSCC: [[META8]] = !{!"S", [[META4]], i64 0, [[META4]], i64 4, [[META4]], i64 8, [[META9]], i64 12, [[META9]], i64 16, [[META9]], i64 20}
; CGSCC: [[META9]] = !{!"float", [[META5]], i64 0}
; CGSCC: [[TBAA10]] = !{[[META8]], [[META9]], i64 16}
; CGSCC: [[TBAA11]] = !{[[META8]], [[META9]], i64 20}
; CGSCC: [[TBAA12]] = !{[[META8]], [[META4]], i64 0}
; CGSCC: [[TBAA13]] = !{[[META8]], [[META4]], i64 4}
; CGSCC: [[TBAA14]] = !{[[META8]], [[META4]], i64 8}
; CGSCC: [[TBAA15]] = !{[[META5]], [[META5]], i64 0}
; CGSCC: [[LOOP16]] = distinct !{[[LOOP16]], [[META17:![0-9]+]]}
; CGSCC: [[META17]] = !{!"llvm.loop.mustprogress"}
; CGSCC: [[TBAA18]] = !{[[META9]], [[META9]], i64 0}
; CGSCC: [[LOOP19]] = distinct !{[[LOOP19]], [[META17]]}
; CGSCC: [[TBAA20]] = !{[[META21:![0-9]+]], [[META21]], i64 0}
; CGSCC: [[META21]] = !{!"long long", [[META5]], i64 0}
; CGSCC: [[LOOP22]] = distinct !{[[LOOP22]], [[META17]]}
; CGSCC: [[LOOP23]] = distinct !{[[LOOP23]], [[META17]]}
; CGSCC: [[LOOP24]] = distinct !{[[LOOP24]], [[META17]]}
; CGSCC: [[LOOP25]] = distinct !{[[LOOP25]], [[META17]]}
; CGSCC: [[LOOP26]] = distinct !{[[LOOP26]], [[META17]]}
; CGSCC: [[LOOP27]] = distinct !{[[LOOP27]], [[META17]]}
; CGSCC: [[LOOP28]] = distinct !{[[LOOP28]], [[META17]]}
; CGSCC: [[LOOP29]] = distinct !{[[LOOP29]], [[META17]]}
; CGSCC: [[LOOP30]] = distinct !{[[LOOP30]], [[META17]]}
; CGSCC: [[LOOP31]] = distinct !{[[LOOP31]], [[META17]]}
;.