1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 2; RUN: opt < %s -passes=inline -S | FileCheck %s 3; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s 4 5%struct.a = type { i32, i32, i32, i32, i32 } 6 7@g_var = global %struct.a { i32 1, i32 0, i32 0, i32 0, i32 0 }, align 8 8@other_g_var = global %struct.a zeroinitializer, align 4 9 10define void @callee(ptr noundef byval(%struct.a) align 8 %ptr) { 11; CHECK-LABEL: define void @callee( 12; CHECK-SAME: ptr noundef byval([[STRUCT_A:%.*]]) align 8 [[PTR:%.*]]) { 13; CHECK-NEXT: entry: 14; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[PTR]], align 8 15; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[VAL]], 0 16; CHECK-NEXT: br i1 [[DOTNOT]], label [[CHECK_POINTERS_ARE_EQUAL:%.*]], label [[STORE_PTR_IN_GVAR:%.*]] 17; CHECK: store_ptr_in_gvar: 18; CHECK-NEXT: store ptr [[PTR]], ptr @other_g_var, align 8 19; CHECK-NEXT: br label [[CHECK_POINTERS_ARE_EQUAL]] 20; CHECK: check_pointers_are_equal: 21; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[PTR]], [[STORE_PTR_IN_GVAR]] ], [ @other_g_var, [[ENTRY:%.*]] ] 22; CHECK-NEXT: [[DOTNOT1:%.*]] = icmp eq ptr [[PHI]], [[PTR]] 23; CHECK-NEXT: br i1 [[DOTNOT1]], label [[RETURN:%.*]], label [[ABORT:%.*]] 24; CHECK: abort: 25; CHECK-NEXT: call void @abort() 26; CHECK-NEXT: unreachable 27; CHECK: return: 28; CHECK-NEXT: ret void 29; 30entry: 31 %val = load i32, ptr %ptr, align 8 32 %.not = icmp eq i32 %val, 0 33 br i1 %.not, label %check_pointers_are_equal, label %store_ptr_in_gvar 34 35store_ptr_in_gvar: ; preds = %entry 36 store ptr %ptr, ptr @other_g_var, align 8 37 br label %check_pointers_are_equal 38 39check_pointers_are_equal: ; preds = %store_ptr_in_gvar, %entry 40 %phi = phi ptr [ %ptr, %store_ptr_in_gvar ], [ @other_g_var, %entry ] 41 %.not1 = icmp eq ptr %phi, %ptr 42 br i1 %.not1, label %return, label %abort 43 44abort: ; preds = %check_pointers_are_equal 45 call void @abort() 46 unreachable 47 48return: ; preds = %check_pointers_are_equal 49 ret void 50} 51 52define i32 @main() { 53; CHECK-LABEL: define i32 @main() { 54; CHECK-NEXT: [[G_VAR:%.*]] = alloca [[STRUCT_A:%.*]], align 8 55; CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 20, ptr [[G_VAR]]) 56; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[G_VAR]], ptr align 1 @g_var, i64 20, i1 false) 57; CHECK-NEXT: [[VAL_I:%.*]] = load i32, ptr [[G_VAR]], align 8 58; CHECK-NEXT: [[DOTNOT_I:%.*]] = icmp eq i32 [[VAL_I]], 0 59; CHECK-NEXT: br i1 [[DOTNOT_I]], label [[CHECK_POINTERS_ARE_EQUAL_I:%.*]], label [[STORE_PTR_IN_GVAR_I:%.*]] 60; CHECK: store_ptr_in_gvar.i: 61; CHECK-NEXT: store ptr [[G_VAR]], ptr @other_g_var, align 8 62; CHECK-NEXT: br label [[CHECK_POINTERS_ARE_EQUAL_I]] 63; CHECK: check_pointers_are_equal.i: 64; CHECK-NEXT: [[PHI_I:%.*]] = phi ptr [ [[G_VAR]], [[STORE_PTR_IN_GVAR_I]] ], [ @other_g_var, [[TMP0:%.*]] ] 65; CHECK-NEXT: [[DOTNOT1_I:%.*]] = icmp eq ptr [[PHI_I]], [[G_VAR]] 66; CHECK-NEXT: br i1 [[DOTNOT1_I]], label [[CALLEE_EXIT:%.*]], label [[ABORT_I:%.*]] 67; CHECK: abort.i: 68; CHECK-NEXT: call void @abort() 69; CHECK-NEXT: unreachable 70; CHECK: callee.exit: 71; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 20, ptr [[G_VAR]]) 72; CHECK-NEXT: ret i32 0 73; 74 call void @callee(ptr noundef byval(%struct.a) align 8 @g_var) 75 ret i32 0 76} 77 78declare void @abort() 79