diff --git a/llvm/test/Transforms/SROA/non-capturing-call.ll b/llvm/test/Transforms/SROA/non-capturing-call.ll index f6421f6def20d..da37df80ca865 100644 --- a/llvm/test/Transforms/SROA/non-capturing-call.ll +++ b/llvm/test/Transforms/SROA/non-capturing-call.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt < %s -sroa -S | FileCheck %s -; RUN: opt < %s -passes=sroa -S | FileCheck %s +; RUN: opt < %s -passes=sroa -S | FileCheck %s --check-prefix=CHECK +; RUN: opt < %s -passes=sroa -opaque-pointers -S | FileCheck %s --check-prefix=CHECK-OPAQUE define i32 @alloca_used_in_call(i32* nocapture nonnull readonly %data, i64 %n) { ; CHECK-LABEL: @alloca_used_in_call( @@ -19,9 +19,29 @@ define i32 @alloca_used_in_call(i32* nocapture nonnull readonly %data, i64 %n) { ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]] ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: -; CHECK-NEXT: [[TMP0:%.*]] = call i32 @user_of_alloca(i32* nocapture nonnull [[RETVAL]]) -; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[RETVAL]], align 4 -; CHECK-NEXT: ret i32 [[TMP1]] +; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca(i32* nocapture nonnull [[RETVAL]]) +; CHECK-NEXT: [[I1:%.*]] = load i32, i32* [[RETVAL]], align 4 +; CHECK-NEXT: ret i32 [[I1]] +; +; CHECK-OPAQUE-LABEL: @alloca_used_in_call( +; CHECK-OPAQUE-NEXT: entry: +; CHECK-OPAQUE-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +; CHECK-OPAQUE-NEXT: store i32 0, ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: br label [[LOOP:%.*]] +; CHECK-OPAQUE: loop: +; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-OPAQUE-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]] +; CHECK-OPAQUE-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +; CHECK-OPAQUE-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]] +; CHECK-OPAQUE-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1 +; CHECK-OPAQUE-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]] +; CHECK-OPAQUE-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK-OPAQUE: exit: +; CHECK-OPAQUE-NEXT: [[I0:%.*]] = call i32 @user_of_alloca(ptr nocapture nonnull [[RETVAL]]) +; CHECK-OPAQUE-NEXT: [[I1:%.*]] = load i32, ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: ret i32 [[I1]] ; entry: %retval = alloca i32, align 4 @@ -40,9 +60,9 @@ loop: br i1 %exitcond, label %loop, label %exit exit: - %0 = call i32 @user_of_alloca(i32* nocapture nonnull %retval) - %1 = load i32, i32* %retval, align 4 - ret i32 %1 + %i0 = call i32 @user_of_alloca(i32* nocapture nonnull %retval) + %i1 = load i32, i32* %retval, align 4 + ret i32 %i1 } define i32 @alloca_captured_in_call(i32* nocapture nonnull readonly %data, i64 %n) { @@ -62,9 +82,29 @@ define i32 @alloca_captured_in_call(i32* nocapture nonnull readonly %data, i64 % ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]] ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: -; CHECK-NEXT: [[TMP0:%.*]] = call i32 @capture_of_alloca(i32* nonnull [[RETVAL]]) -; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[RETVAL]], align 4 -; CHECK-NEXT: ret i32 [[TMP1]] +; CHECK-NEXT: [[I0:%.*]] = call i32 @capture_of_alloca(i32* nonnull [[RETVAL]]) +; CHECK-NEXT: [[I1:%.*]] = load i32, i32* [[RETVAL]], align 4 +; CHECK-NEXT: ret i32 [[I1]] +; +; CHECK-OPAQUE-LABEL: @alloca_captured_in_call( +; CHECK-OPAQUE-NEXT: entry: +; CHECK-OPAQUE-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +; CHECK-OPAQUE-NEXT: store i32 0, ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: br label [[LOOP:%.*]] +; CHECK-OPAQUE: loop: +; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-OPAQUE-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]] +; CHECK-OPAQUE-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +; CHECK-OPAQUE-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]] +; CHECK-OPAQUE-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1 +; CHECK-OPAQUE-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]] +; CHECK-OPAQUE-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK-OPAQUE: exit: +; CHECK-OPAQUE-NEXT: [[I0:%.*]] = call i32 @capture_of_alloca(ptr nonnull [[RETVAL]]) +; CHECK-OPAQUE-NEXT: [[I1:%.*]] = load i32, ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: ret i32 [[I1]] ; entry: %retval = alloca i32, align 4 @@ -83,9 +123,9 @@ loop: br i1 %exitcond, label %loop, label %exit exit: - %0 = call i32 @capture_of_alloca(i32* nonnull %retval) - %1 = load i32, i32* %retval, align 4 - ret i32 %1 + %i0 = call i32 @capture_of_alloca(i32* nonnull %retval) + %i1 = load i32, i32* %retval, align 4 + ret i32 %i1 } define i32 @alloca_with_gep_used_in_call(i32* nocapture nonnull readonly %data, i64 %n) { @@ -106,9 +146,30 @@ define i32 @alloca_with_gep_used_in_call(i32* nocapture nonnull readonly %data, ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: ; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, i32* [[RETVAL]], i32 0 -; CHECK-NEXT: [[TMP0:%.*]] = call i32 @user_of_alloca(i32* nocapture nonnull [[GEP]]) -; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[RETVAL]], align 4 -; CHECK-NEXT: ret i32 [[TMP1]] +; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca(i32* nocapture nonnull [[GEP]]) +; CHECK-NEXT: [[I1:%.*]] = load i32, i32* [[RETVAL]], align 4 +; CHECK-NEXT: ret i32 [[I1]] +; +; CHECK-OPAQUE-LABEL: @alloca_with_gep_used_in_call( +; CHECK-OPAQUE-NEXT: entry: +; CHECK-OPAQUE-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +; CHECK-OPAQUE-NEXT: store i32 0, ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: br label [[LOOP:%.*]] +; CHECK-OPAQUE: loop: +; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-OPAQUE-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]] +; CHECK-OPAQUE-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +; CHECK-OPAQUE-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]] +; CHECK-OPAQUE-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1 +; CHECK-OPAQUE-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]] +; CHECK-OPAQUE-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK-OPAQUE: exit: +; CHECK-OPAQUE-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[RETVAL]], i32 0 +; CHECK-OPAQUE-NEXT: [[I0:%.*]] = call i32 @user_of_alloca(ptr nocapture nonnull [[GEP]]) +; CHECK-OPAQUE-NEXT: [[I1:%.*]] = load i32, ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: ret i32 [[I1]] ; entry: %retval = alloca i32, align 4 @@ -128,9 +189,9 @@ loop: exit: %gep = getelementptr i32, i32* %retval, i32 0 - %0 = call i32 @user_of_alloca(i32* nocapture nonnull %gep) - %1 = load i32, i32* %retval, align 4 - ret i32 %1 + %i0 = call i32 @user_of_alloca(i32* nocapture nonnull %gep) + %i1 = load i32, i32* %retval, align 4 + ret i32 %i1 } define i32 @alloca_captured_second_arg(i32* nocapture nonnull readonly %data, i64 %n) { @@ -150,9 +211,29 @@ define i32 @alloca_captured_second_arg(i32* nocapture nonnull readonly %data, i6 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]] ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: -; CHECK-NEXT: [[TMP0:%.*]] = call i32 @capture_with_multiple_args(i32* nocapture nonnull [[RETVAL]], i32* nonnull [[RETVAL]]) -; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[RETVAL]], align 4 -; CHECK-NEXT: ret i32 [[TMP1]] +; CHECK-NEXT: [[I0:%.*]] = call i32 @capture_with_multiple_args(i32* nocapture nonnull [[RETVAL]], i32* nonnull [[RETVAL]]) +; CHECK-NEXT: [[I1:%.*]] = load i32, i32* [[RETVAL]], align 4 +; CHECK-NEXT: ret i32 [[I1]] +; +; CHECK-OPAQUE-LABEL: @alloca_captured_second_arg( +; CHECK-OPAQUE-NEXT: entry: +; CHECK-OPAQUE-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +; CHECK-OPAQUE-NEXT: store i32 0, ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: br label [[LOOP:%.*]] +; CHECK-OPAQUE: loop: +; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-OPAQUE-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]] +; CHECK-OPAQUE-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +; CHECK-OPAQUE-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]] +; CHECK-OPAQUE-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1 +; CHECK-OPAQUE-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]] +; CHECK-OPAQUE-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK-OPAQUE: exit: +; CHECK-OPAQUE-NEXT: [[I0:%.*]] = call i32 @capture_with_multiple_args(ptr nocapture nonnull [[RETVAL]], ptr nonnull [[RETVAL]]) +; CHECK-OPAQUE-NEXT: [[I1:%.*]] = load i32, ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: ret i32 [[I1]] ; entry: %retval = alloca i32, align 4 @@ -171,9 +252,9 @@ loop: br i1 %exitcond, label %loop, label %exit exit: - %0 = call i32 @capture_with_multiple_args(i32* nocapture nonnull %retval, i32* nonnull %retval) - %1 = load i32, i32* %retval, align 4 - ret i32 %1 + %i0 = call i32 @capture_with_multiple_args(i32* nocapture nonnull %retval, i32* nonnull %retval) + %i1 = load i32, i32* %retval, align 4 + ret i32 %i1 } define i32 @alloca_used_in_maybe_throwing_call(i32* nocapture nonnull readonly %data, i64 %n) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { @@ -193,17 +274,45 @@ define i32 @alloca_used_in_maybe_throwing_call(i32* nocapture nonnull readonly % ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]] ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: -; CHECK-NEXT: [[TMP0:%.*]] = invoke i32 @user_of_alloca(i32* nocapture nonnull [[RETVAL]]) +; CHECK-NEXT: [[I0:%.*]] = invoke i32 @user_of_alloca(i32* nocapture nonnull [[RETVAL]]) ; CHECK-NEXT: to label [[CONT:%.*]] unwind label [[UW:%.*]] ; CHECK: cont: ; CHECK-NEXT: br label [[END:%.*]] ; CHECK: uw: -; CHECK-NEXT: [[TMP1:%.*]] = landingpad { i8*, i32 } +; CHECK-NEXT: [[I1:%.*]] = landingpad { i8*, i32 } ; CHECK-NEXT: catch i8* null ; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[RETVAL]], align 4 -; CHECK-NEXT: ret i32 [[TMP2]] +; CHECK-NEXT: [[I2:%.*]] = load i32, i32* [[RETVAL]], align 4 +; CHECK-NEXT: ret i32 [[I2]] +; +; CHECK-OPAQUE-LABEL: @alloca_used_in_maybe_throwing_call( +; CHECK-OPAQUE-NEXT: entry: +; CHECK-OPAQUE-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +; CHECK-OPAQUE-NEXT: store i32 0, ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: br label [[LOOP:%.*]] +; CHECK-OPAQUE: loop: +; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-OPAQUE-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]] +; CHECK-OPAQUE-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +; CHECK-OPAQUE-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]] +; CHECK-OPAQUE-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1 +; CHECK-OPAQUE-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]] +; CHECK-OPAQUE-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK-OPAQUE: exit: +; CHECK-OPAQUE-NEXT: [[I0:%.*]] = invoke i32 @user_of_alloca(ptr nocapture nonnull [[RETVAL]]) +; CHECK-OPAQUE-NEXT: to label [[CONT:%.*]] unwind label [[UW:%.*]] +; CHECK-OPAQUE: cont: +; CHECK-OPAQUE-NEXT: br label [[END:%.*]] +; CHECK-OPAQUE: uw: +; CHECK-OPAQUE-NEXT: [[I1:%.*]] = landingpad { ptr, i32 } +; CHECK-OPAQUE-NEXT: catch ptr null +; CHECK-OPAQUE-NEXT: br label [[END]] +; CHECK-OPAQUE: end: +; CHECK-OPAQUE-NEXT: [[I2:%.*]] = load i32, ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: ret i32 [[I2]] ; entry: %retval = alloca i32, align 4 @@ -222,18 +331,18 @@ loop: br i1 %exitcond, label %loop, label %exit exit: - %0 = invoke i32 @user_of_alloca(i32* nocapture nonnull %retval) to label %cont unwind label %uw + %i0 = invoke i32 @user_of_alloca(i32* nocapture nonnull %retval) to label %cont unwind label %uw cont: br label %end uw: - %1 = landingpad { i8*, i32 } catch i8* null + %i1 = landingpad { i8*, i32 } catch i8* null br label %end end: - %2 = load i32, i32* %retval, align 4 - ret i32 %2 + %i2 = load i32, i32* %retval, align 4 + ret i32 %i2 } define i32 @alloca_used_in_maybe_throwing_call_with_same_dests(i32* nocapture nonnull readonly %data, i64 %n) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { @@ -253,15 +362,41 @@ define i32 @alloca_used_in_maybe_throwing_call_with_same_dests(i32* nocapture no ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]] ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: -; CHECK-NEXT: [[TMP0:%.*]] = invoke i32 @user_of_alloca(i32* nocapture nonnull [[RETVAL]]) +; CHECK-NEXT: [[I0:%.*]] = invoke i32 @user_of_alloca(i32* nocapture nonnull [[RETVAL]]) ; CHECK-NEXT: to label [[END:%.*]] unwind label [[UW:%.*]] ; CHECK: uw: -; CHECK-NEXT: [[TMP1:%.*]] = landingpad { i8*, i32 } +; CHECK-NEXT: [[I1:%.*]] = landingpad { i8*, i32 } ; CHECK-NEXT: catch i8* null ; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[RETVAL]], align 4 -; CHECK-NEXT: ret i32 [[TMP2]] +; CHECK-NEXT: [[I2:%.*]] = load i32, i32* [[RETVAL]], align 4 +; CHECK-NEXT: ret i32 [[I2]] +; +; CHECK-OPAQUE-LABEL: @alloca_used_in_maybe_throwing_call_with_same_dests( +; CHECK-OPAQUE-NEXT: entry: +; CHECK-OPAQUE-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +; CHECK-OPAQUE-NEXT: store i32 0, ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: br label [[LOOP:%.*]] +; CHECK-OPAQUE: loop: +; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-OPAQUE-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]] +; CHECK-OPAQUE-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +; CHECK-OPAQUE-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]] +; CHECK-OPAQUE-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1 +; CHECK-OPAQUE-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]] +; CHECK-OPAQUE-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK-OPAQUE: exit: +; CHECK-OPAQUE-NEXT: [[I0:%.*]] = invoke i32 @user_of_alloca(ptr nocapture nonnull [[RETVAL]]) +; CHECK-OPAQUE-NEXT: to label [[END:%.*]] unwind label [[UW:%.*]] +; CHECK-OPAQUE: uw: +; CHECK-OPAQUE-NEXT: [[I1:%.*]] = landingpad { ptr, i32 } +; CHECK-OPAQUE-NEXT: catch ptr null +; CHECK-OPAQUE-NEXT: br label [[END]] +; CHECK-OPAQUE: end: +; CHECK-OPAQUE-NEXT: [[I2:%.*]] = load i32, ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: ret i32 [[I2]] ; entry: %retval = alloca i32, align 4 @@ -280,15 +415,15 @@ loop: br i1 %exitcond, label %loop, label %exit exit: - %0 = invoke i32 @user_of_alloca(i32* nocapture nonnull %retval) to label %end unwind label %uw + %i0 = invoke i32 @user_of_alloca(i32* nocapture nonnull %retval) to label %end unwind label %uw uw: - %1 = landingpad { i8*, i32 } catch i8* null + %i1 = landingpad { i8*, i32 } catch i8* null br label %end end: - %2 = load i32, i32* %retval, align 4 - ret i32 %2 + %i2 = load i32, i32* %retval, align 4 + ret i32 %i2 } define [2 x i32] @part_of_alloca_used_in_call(i32* nocapture nonnull readonly %data, i64 %n) { @@ -312,19 +447,310 @@ define [2 x i32] @part_of_alloca_used_in_call(i32* nocapture nonnull readonly %d ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]] ; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: -; CHECK-NEXT: [[TMP0:%.*]] = call i32 @user_of_alloca(i32* nocapture nonnull [[RETVAL]]) -; CHECK-NEXT: [[DOTFCA_0_GEP1:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 0 -; CHECK-NEXT: [[DOTFCA_0_LOAD:%.*]] = load i32, i32* [[DOTFCA_0_GEP1]], align 4 -; CHECK-NEXT: [[DOTFCA_0_INSERT:%.*]] = insertvalue [2 x i32] undef, i32 [[DOTFCA_0_LOAD]], 0 -; CHECK-NEXT: [[DOTFCA_1_GEP2:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 1 -; CHECK-NEXT: [[DOTFCA_1_LOAD:%.*]] = load i32, i32* [[DOTFCA_1_GEP2]], align 4 -; CHECK-NEXT: [[DOTFCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[DOTFCA_0_INSERT]], i32 [[DOTFCA_1_LOAD]], 1 -; CHECK-NEXT: ret [2 x i32] [[DOTFCA_1_INSERT]] +; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca(i32* nocapture nonnull [[RETVAL]]) +; CHECK-NEXT: [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 0 +; CHECK-NEXT: [[I1_FCA_0_LOAD:%.*]] = load i32, i32* [[I1_FCA_0_GEP]], align 4 +; CHECK-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] undef, i32 [[I1_FCA_0_LOAD]], 0 +; CHECK-NEXT: [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 1 +; CHECK-NEXT: [[I1_FCA_1_LOAD:%.*]] = load i32, i32* [[I1_FCA_1_GEP]], align 4 +; CHECK-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[I1_FCA_1_LOAD]], 1 +; CHECK-NEXT: ret [2 x i32] [[I1_FCA_1_INSERT]] +; +; CHECK-OPAQUE-LABEL: @part_of_alloca_used_in_call( +; CHECK-OPAQUE-NEXT: entry: +; CHECK-OPAQUE-NEXT: [[RETVAL_FULL:%.*]] = alloca [2 x i32], align 4 +; CHECK-OPAQUE-NEXT: [[DOTFCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0 +; CHECK-OPAQUE-NEXT: store i32 0, ptr [[DOTFCA_0_GEP]], align 4 +; CHECK-OPAQUE-NEXT: [[DOTFCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1 +; CHECK-OPAQUE-NEXT: store i32 0, ptr [[DOTFCA_1_GEP]], align 4 +; CHECK-OPAQUE-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1 +; CHECK-OPAQUE-NEXT: br label [[LOOP:%.*]] +; CHECK-OPAQUE: loop: +; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-OPAQUE-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]] +; CHECK-OPAQUE-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +; CHECK-OPAQUE-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]] +; CHECK-OPAQUE-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1 +; CHECK-OPAQUE-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]] +; CHECK-OPAQUE-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK-OPAQUE: exit: +; CHECK-OPAQUE-NEXT: [[I0:%.*]] = call i32 @user_of_alloca(ptr nocapture nonnull [[RETVAL]]) +; CHECK-OPAQUE-NEXT: [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0 +; CHECK-OPAQUE-NEXT: [[I1_FCA_0_LOAD:%.*]] = load i32, ptr [[I1_FCA_0_GEP]], align 4 +; CHECK-OPAQUE-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] undef, i32 [[I1_FCA_0_LOAD]], 0 +; CHECK-OPAQUE-NEXT: [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1 +; CHECK-OPAQUE-NEXT: [[I1_FCA_1_LOAD:%.*]] = load i32, ptr [[I1_FCA_1_GEP]], align 4 +; CHECK-OPAQUE-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[I1_FCA_1_LOAD]], 1 +; CHECK-OPAQUE-NEXT: ret [2 x i32] [[I1_FCA_1_INSERT]] +; +entry: + %retval.full = alloca [2 x i32], align 4 + store [2 x i32] zeroinitializer, [2 x i32]* %retval.full, align 4 + %retval = getelementptr inbounds [2 x i32], [2 x i32]* %retval.full, i64 0, i64 1 + br label %loop + +loop: + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ] + %arrayidx = getelementptr inbounds i32, i32* %data, i64 %indvars.iv + %ld = load i32, i32* %arrayidx, align 4 + %rdx = load i32, i32* %retval, align 4 + %rdx.inc = add nsw i32 %rdx, %ld + store i32 %rdx.inc, i32* %retval, align 4 + %indvars.iv.next = add nsw i64 %indvars.iv, 1 + %exitcond = icmp ne i64 %indvars.iv.next, %n + br i1 %exitcond, label %loop, label %exit + +exit: + %i0 = call i32 @user_of_alloca(i32* nocapture nonnull %retval) + %i1 = load [2 x i32], [2 x i32]* %retval.full, align 4 + ret [2 x i32] %i1 +} + +define [2 x i32] @all_parts_of_alloca_used_in_call_with_multiple_args(i32* nocapture nonnull readonly %data, i64 %n) { +; CHECK-LABEL: @all_parts_of_alloca_used_in_call_with_multiple_args( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[RETVAL_FULL:%.*]] = alloca [2 x i32], align 4 +; CHECK-NEXT: [[DOTFCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 0 +; CHECK-NEXT: store i32 0, i32* [[DOTFCA_0_GEP]], align 4 +; CHECK-NEXT: [[DOTFCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 1 +; CHECK-NEXT: store i32 0, i32* [[DOTFCA_1_GEP]], align 4 +; CHECK-NEXT: [[RETVAL_BASE:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i64 0, i64 0 +; CHECK-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i64 0, i64 1 +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[DATA:%.*]], i64 [[INDVARS_IV]] +; CHECK-NEXT: [[LD:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 +; CHECK-NEXT: [[RDX:%.*]] = load i32, i32* [[RETVAL]], align 4 +; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]] +; CHECK-NEXT: store i32 [[RDX_INC]], i32* [[RETVAL]], align 4 +; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]] +; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(i32* nocapture nonnull [[RETVAL]], i32* nocapture nonnull [[RETVAL_BASE]]) +; CHECK-NEXT: [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 0 +; CHECK-NEXT: [[I1_FCA_0_LOAD:%.*]] = load i32, i32* [[I1_FCA_0_GEP]], align 4 +; CHECK-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] undef, i32 [[I1_FCA_0_LOAD]], 0 +; CHECK-NEXT: [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 1 +; CHECK-NEXT: [[I1_FCA_1_LOAD:%.*]] = load i32, i32* [[I1_FCA_1_GEP]], align 4 +; CHECK-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[I1_FCA_1_LOAD]], 1 +; CHECK-NEXT: ret [2 x i32] [[I1_FCA_1_INSERT]] +; +; CHECK-OPAQUE-LABEL: @all_parts_of_alloca_used_in_call_with_multiple_args( +; CHECK-OPAQUE-NEXT: entry: +; CHECK-OPAQUE-NEXT: [[RETVAL_FULL:%.*]] = alloca [2 x i32], align 4 +; CHECK-OPAQUE-NEXT: [[DOTFCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0 +; CHECK-OPAQUE-NEXT: store i32 0, ptr [[DOTFCA_0_GEP]], align 4 +; CHECK-OPAQUE-NEXT: [[DOTFCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1 +; CHECK-OPAQUE-NEXT: store i32 0, ptr [[DOTFCA_1_GEP]], align 4 +; CHECK-OPAQUE-NEXT: [[RETVAL_BASE:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 0 +; CHECK-OPAQUE-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1 +; CHECK-OPAQUE-NEXT: br label [[LOOP:%.*]] +; CHECK-OPAQUE: loop: +; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-OPAQUE-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]] +; CHECK-OPAQUE-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +; CHECK-OPAQUE-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]] +; CHECK-OPAQUE-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1 +; CHECK-OPAQUE-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]] +; CHECK-OPAQUE-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK-OPAQUE: exit: +; CHECK-OPAQUE-NEXT: [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(ptr nocapture nonnull [[RETVAL]], ptr nocapture nonnull [[RETVAL_BASE]]) +; CHECK-OPAQUE-NEXT: [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0 +; CHECK-OPAQUE-NEXT: [[I1_FCA_0_LOAD:%.*]] = load i32, ptr [[I1_FCA_0_GEP]], align 4 +; CHECK-OPAQUE-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] undef, i32 [[I1_FCA_0_LOAD]], 0 +; CHECK-OPAQUE-NEXT: [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1 +; CHECK-OPAQUE-NEXT: [[I1_FCA_1_LOAD:%.*]] = load i32, ptr [[I1_FCA_1_GEP]], align 4 +; CHECK-OPAQUE-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[I1_FCA_1_LOAD]], 1 +; CHECK-OPAQUE-NEXT: ret [2 x i32] [[I1_FCA_1_INSERT]] +; +entry: + %retval.full = alloca [2 x i32], align 4 + store [2 x i32] zeroinitializer, [2 x i32]* %retval.full, align 4 + %retval.base = getelementptr inbounds [2 x i32], [2 x i32]* %retval.full, i64 0, i64 0 + %retval = getelementptr inbounds [2 x i32], [2 x i32]* %retval.full, i64 0, i64 1 + br label %loop + +loop: + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ] + %arrayidx = getelementptr inbounds i32, i32* %data, i64 %indvars.iv + %ld = load i32, i32* %arrayidx, align 4 + %rdx = load i32, i32* %retval, align 4 + %rdx.inc = add nsw i32 %rdx, %ld + store i32 %rdx.inc, i32* %retval, align 4 + %indvars.iv.next = add nsw i64 %indvars.iv, 1 + %exitcond = icmp ne i64 %indvars.iv.next, %n + br i1 %exitcond, label %loop, label %exit + +exit: + %i0 = call i32 @user_of_alloca_with_multiple_args(i32* nocapture nonnull %retval, i32* nocapture nonnull %retval.base) + %i1 = load [2 x i32], [2 x i32]* %retval.full, align 4 + ret [2 x i32] %i1 +} + +define [2 x i32] @part_of_alloca_used_in_call_with_multiple_args(i32* nocapture nonnull readonly %data, i64 %n) { +; CHECK-LABEL: @part_of_alloca_used_in_call_with_multiple_args( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[RETVAL_FULL:%.*]] = alloca [2 x i32], align 4 +; CHECK-NEXT: [[DOTFCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 0 +; CHECK-NEXT: store i32 0, i32* [[DOTFCA_0_GEP]], align 4 +; CHECK-NEXT: [[DOTFCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 1 +; CHECK-NEXT: store i32 0, i32* [[DOTFCA_1_GEP]], align 4 +; CHECK-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i64 0, i64 1 +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[DATA:%.*]], i64 [[INDVARS_IV]] +; CHECK-NEXT: [[LD:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 +; CHECK-NEXT: [[RDX:%.*]] = load i32, i32* [[RETVAL]], align 4 +; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]] +; CHECK-NEXT: store i32 [[RDX_INC]], i32* [[RETVAL]], align 4 +; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]] +; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(i32* nocapture nonnull [[RETVAL]], i32* nocapture nonnull [[RETVAL]]) +; CHECK-NEXT: [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 0 +; CHECK-NEXT: [[I1_FCA_0_LOAD:%.*]] = load i32, i32* [[I1_FCA_0_GEP]], align 4 +; CHECK-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] undef, i32 [[I1_FCA_0_LOAD]], 0 +; CHECK-NEXT: [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 1 +; CHECK-NEXT: [[I1_FCA_1_LOAD:%.*]] = load i32, i32* [[I1_FCA_1_GEP]], align 4 +; CHECK-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[I1_FCA_1_LOAD]], 1 +; CHECK-NEXT: ret [2 x i32] [[I1_FCA_1_INSERT]] +; +; CHECK-OPAQUE-LABEL: @part_of_alloca_used_in_call_with_multiple_args( +; CHECK-OPAQUE-NEXT: entry: +; CHECK-OPAQUE-NEXT: [[RETVAL_FULL:%.*]] = alloca [2 x i32], align 4 +; CHECK-OPAQUE-NEXT: [[DOTFCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0 +; CHECK-OPAQUE-NEXT: store i32 0, ptr [[DOTFCA_0_GEP]], align 4 +; CHECK-OPAQUE-NEXT: [[DOTFCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1 +; CHECK-OPAQUE-NEXT: store i32 0, ptr [[DOTFCA_1_GEP]], align 4 +; CHECK-OPAQUE-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1 +; CHECK-OPAQUE-NEXT: br label [[LOOP:%.*]] +; CHECK-OPAQUE: loop: +; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-OPAQUE-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]] +; CHECK-OPAQUE-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +; CHECK-OPAQUE-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]] +; CHECK-OPAQUE-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1 +; CHECK-OPAQUE-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]] +; CHECK-OPAQUE-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK-OPAQUE: exit: +; CHECK-OPAQUE-NEXT: [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(ptr nocapture nonnull [[RETVAL]], ptr nocapture nonnull [[RETVAL]]) +; CHECK-OPAQUE-NEXT: [[I1_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0 +; CHECK-OPAQUE-NEXT: [[I1_FCA_0_LOAD:%.*]] = load i32, ptr [[I1_FCA_0_GEP]], align 4 +; CHECK-OPAQUE-NEXT: [[I1_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] undef, i32 [[I1_FCA_0_LOAD]], 0 +; CHECK-OPAQUE-NEXT: [[I1_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1 +; CHECK-OPAQUE-NEXT: [[I1_FCA_1_LOAD:%.*]] = load i32, ptr [[I1_FCA_1_GEP]], align 4 +; CHECK-OPAQUE-NEXT: [[I1_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I1_FCA_0_INSERT]], i32 [[I1_FCA_1_LOAD]], 1 +; CHECK-OPAQUE-NEXT: ret [2 x i32] [[I1_FCA_1_INSERT]] +; +entry: + %retval.full = alloca [2 x i32], align 4 + store [2 x i32] zeroinitializer, [2 x i32]* %retval.full, align 4 + %retval = getelementptr inbounds [2 x i32], [2 x i32]* %retval.full, i64 0, i64 1 + br label %loop + +loop: + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %loop ] + %arrayidx = getelementptr inbounds i32, i32* %data, i64 %indvars.iv + %ld = load i32, i32* %arrayidx, align 4 + %rdx = load i32, i32* %retval, align 4 + %rdx.inc = add nsw i32 %rdx, %ld + store i32 %rdx.inc, i32* %retval, align 4 + %indvars.iv.next = add nsw i64 %indvars.iv, 1 + %exitcond = icmp ne i64 %indvars.iv.next, %n + br i1 %exitcond, label %loop, label %exit + +exit: + %i0 = call i32 @user_of_alloca_with_multiple_args(i32* nocapture nonnull %retval, i32* nocapture nonnull %retval) + %i1 = load [2 x i32], [2 x i32]* %retval.full, align 4 + ret [2 x i32] %i1 +} + +define [2 x i32] @all_parts_of_alloca_used_in_calls_with_multiple_args(i32* nocapture nonnull readonly %data, i64 %n) { +; CHECK-LABEL: @all_parts_of_alloca_used_in_calls_with_multiple_args( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[RETVAL_FULL:%.*]] = alloca [2 x i32], align 4 +; CHECK-NEXT: [[SOME_ANOTHER_ALLOCA_FULL:%.*]] = alloca [42 x i32], align 4 +; CHECK-NEXT: [[DOTFCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 0 +; CHECK-NEXT: store i32 0, i32* [[DOTFCA_0_GEP]], align 4 +; CHECK-NEXT: [[DOTFCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 1 +; CHECK-NEXT: store i32 0, i32* [[DOTFCA_1_GEP]], align 4 +; CHECK-NEXT: [[RETVAL_BASE:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i64 0, i64 0 +; CHECK-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i64 0, i64 1 +; CHECK-NEXT: [[SOME_ANOTHER_ALLOCA:%.*]] = getelementptr inbounds [42 x i32], [42 x i32]* [[SOME_ANOTHER_ALLOCA_FULL]], i64 0, i64 0 +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[DATA:%.*]], i64 [[INDVARS_IV]] +; CHECK-NEXT: [[LD:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 +; CHECK-NEXT: [[RDX:%.*]] = load i32, i32* [[RETVAL]], align 4 +; CHECK-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]] +; CHECK-NEXT: store i32 [[RDX_INC]], i32* [[RETVAL]], align 4 +; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]] +; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK: exit: +; CHECK-NEXT: [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(i32* nocapture nonnull [[RETVAL]], i32* nocapture nonnull [[RETVAL_BASE]]) +; CHECK-NEXT: [[I1:%.*]] = call i32 @user_of_alloca_with_multiple_args(i32* nocapture nonnull [[RETVAL_BASE]], i32* nocapture nonnull [[RETVAL]]) +; CHECK-NEXT: [[I2:%.*]] = call i32 @capture_of_alloca(i32* [[SOME_ANOTHER_ALLOCA]]) +; CHECK-NEXT: [[I3_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 0 +; CHECK-NEXT: [[I3_FCA_0_LOAD:%.*]] = load i32, i32* [[I3_FCA_0_GEP]], align 4 +; CHECK-NEXT: [[I3_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] undef, i32 [[I3_FCA_0_LOAD]], 0 +; CHECK-NEXT: [[I3_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], [2 x i32]* [[RETVAL_FULL]], i32 0, i32 1 +; CHECK-NEXT: [[I3_FCA_1_LOAD:%.*]] = load i32, i32* [[I3_FCA_1_GEP]], align 4 +; CHECK-NEXT: [[I3_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I3_FCA_0_INSERT]], i32 [[I3_FCA_1_LOAD]], 1 +; CHECK-NEXT: ret [2 x i32] [[I3_FCA_1_INSERT]] +; +; CHECK-OPAQUE-LABEL: @all_parts_of_alloca_used_in_calls_with_multiple_args( +; CHECK-OPAQUE-NEXT: entry: +; CHECK-OPAQUE-NEXT: [[RETVAL_FULL:%.*]] = alloca [2 x i32], align 4 +; CHECK-OPAQUE-NEXT: [[SOME_ANOTHER_ALLOCA_FULL:%.*]] = alloca [42 x i32], align 4 +; CHECK-OPAQUE-NEXT: [[DOTFCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0 +; CHECK-OPAQUE-NEXT: store i32 0, ptr [[DOTFCA_0_GEP]], align 4 +; CHECK-OPAQUE-NEXT: [[DOTFCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1 +; CHECK-OPAQUE-NEXT: store i32 0, ptr [[DOTFCA_1_GEP]], align 4 +; CHECK-OPAQUE-NEXT: [[RETVAL_BASE:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 0 +; CHECK-OPAQUE-NEXT: [[RETVAL:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i64 0, i64 1 +; CHECK-OPAQUE-NEXT: [[SOME_ANOTHER_ALLOCA:%.*]] = getelementptr inbounds [42 x i32], ptr [[SOME_ANOTHER_ALLOCA_FULL]], i64 0, i64 0 +; CHECK-OPAQUE-NEXT: br label [[LOOP:%.*]] +; CHECK-OPAQUE: loop: +; CHECK-OPAQUE-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ] +; CHECK-OPAQUE-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV]] +; CHECK-OPAQUE-NEXT: [[LD:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +; CHECK-OPAQUE-NEXT: [[RDX:%.*]] = load i32, ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: [[RDX_INC:%.*]] = add nsw i32 [[RDX]], [[LD]] +; CHECK-OPAQUE-NEXT: store i32 [[RDX_INC]], ptr [[RETVAL]], align 4 +; CHECK-OPAQUE-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1 +; CHECK-OPAQUE-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[N:%.*]] +; CHECK-OPAQUE-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK-OPAQUE: exit: +; CHECK-OPAQUE-NEXT: [[I0:%.*]] = call i32 @user_of_alloca_with_multiple_args(ptr nocapture nonnull [[RETVAL]], ptr nocapture nonnull [[RETVAL_BASE]]) +; CHECK-OPAQUE-NEXT: [[I1:%.*]] = call i32 @user_of_alloca_with_multiple_args(ptr nocapture nonnull [[RETVAL_BASE]], ptr nocapture nonnull [[RETVAL]]) +; CHECK-OPAQUE-NEXT: [[I2:%.*]] = call i32 @capture_of_alloca(ptr [[SOME_ANOTHER_ALLOCA]]) +; CHECK-OPAQUE-NEXT: [[I3_FCA_0_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 0 +; CHECK-OPAQUE-NEXT: [[I3_FCA_0_LOAD:%.*]] = load i32, ptr [[I3_FCA_0_GEP]], align 4 +; CHECK-OPAQUE-NEXT: [[I3_FCA_0_INSERT:%.*]] = insertvalue [2 x i32] undef, i32 [[I3_FCA_0_LOAD]], 0 +; CHECK-OPAQUE-NEXT: [[I3_FCA_1_GEP:%.*]] = getelementptr inbounds [2 x i32], ptr [[RETVAL_FULL]], i32 0, i32 1 +; CHECK-OPAQUE-NEXT: [[I3_FCA_1_LOAD:%.*]] = load i32, ptr [[I3_FCA_1_GEP]], align 4 +; CHECK-OPAQUE-NEXT: [[I3_FCA_1_INSERT:%.*]] = insertvalue [2 x i32] [[I3_FCA_0_INSERT]], i32 [[I3_FCA_1_LOAD]], 1 +; CHECK-OPAQUE-NEXT: ret [2 x i32] [[I3_FCA_1_INSERT]] ; entry: %retval.full = alloca [2 x i32], align 4 + %some.another.alloca.full = alloca [42 x i32], align 4 store [2 x i32] zeroinitializer, [2 x i32]* %retval.full, align 4 + %retval.base = getelementptr inbounds [2 x i32], [2 x i32]* %retval.full, i64 0, i64 0 %retval = getelementptr inbounds [2 x i32], [2 x i32]* %retval.full, i64 0, i64 1 + %some.another.alloca = getelementptr inbounds [42 x i32], [42 x i32]* %some.another.alloca.full, i64 0, i64 0 br label %loop loop: @@ -339,12 +765,15 @@ loop: br i1 %exitcond, label %loop, label %exit exit: - %0 = call i32 @user_of_alloca(i32* nocapture nonnull %retval) - %1 = load [2 x i32], [2 x i32]* %retval.full, align 4 - ret [2 x i32] %1 + %i0 = call i32 @user_of_alloca_with_multiple_args(i32* nocapture nonnull %retval, i32* nocapture nonnull %retval.base) + %i1 = call i32 @user_of_alloca_with_multiple_args(i32* nocapture nonnull %retval.base, i32* nocapture nonnull %retval) + %i2 = call i32 @capture_of_alloca(i32* %some.another.alloca) + %i3 = load [2 x i32], [2 x i32]* %retval.full, align 4 + ret [2 x i32] %i3 } declare dso_local i32 @user_of_alloca(i32* nocapture nonnull) +declare dso_local i32 @user_of_alloca_with_multiple_args(i32* nocapture nonnull, i32* nocapture nonnull) declare dso_local i32 @capture_of_alloca(i32 *nonnull) declare dso_local i32 @capture_with_multiple_args(i32* nocapture nonnull, i32* nonnull)