; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt %s -passes=ipsccp -S | FileCheck %s declare i1 @cond() declare void @use(i1) define internal {i64, i64} @struct1() { ; CHECK-LABEL: @struct1( ; CHECK-NEXT: [[C:%.*]] = call i1 @cond() ; CHECK-NEXT: br i1 [[C]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: ; CHECK-NEXT: br label [[EXIT:%.*]] ; CHECK: false: ; CHECK-NEXT: br label [[EXIT]] ; CHECK: exit: ; CHECK-NEXT: [[R:%.*]] = phi { i64, i64 } [ { i64 20, i64 200 }, [[TRUE]] ], [ { i64 30, i64 300 }, [[FALSE]] ] ; CHECK-NEXT: ret { i64, i64 } [[R]] ; %c = call i1 @cond() br i1 %c, label %true, label %false true: %s.1 = insertvalue {i64, i64} undef, i64 20, 0 %s.2 = insertvalue {i64, i64} %s.1, i64 200, 1 br label %exit false: %s.3 = insertvalue {i64, i64} poison, i64 30, 0 %s.4 = insertvalue {i64, i64} %s.3, i64 300, 1 br label %exit exit: %r = phi {i64, i64} [ %s.2, %true], [ %s.4, %false ] ret {i64, i64} %r } define void @struct1_caller() { ; CHECK-LABEL: @struct1_caller( ; CHECK-NEXT: [[S:%.*]] = call { i64, i64 } @struct1() ; CHECK-NEXT: [[V1:%.*]] = extractvalue { i64, i64 } [[S]], 0 ; CHECK-NEXT: [[V2:%.*]] = extractvalue { i64, i64 } [[S]], 1 ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[T_3:%.*]] = icmp eq i64 [[V1]], 20 ; CHECK-NEXT: call void @use(i1 [[T_3]]) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[T_6:%.*]] = icmp eq i64 [[V2]], 300 ; CHECK-NEXT: call void @use(i1 [[T_6]]) ; CHECK-NEXT: ret void ; %s = call {i64, i64} @struct1() %v1 = extractvalue {i64, i64} %s, 0 %v2 = extractvalue {i64, i64} %s, 1 %t.1 = icmp ne i64 %v1, 10 call void @use(i1 %t.1) %t.2 = icmp ult i64 %v1, 100 call void @use(i1 %t.2) %t.3 = icmp eq i64 %v1, 20 call void @use(i1 %t.3) %t.4 = icmp ne i64 %v2, 0 call void @use(i1 %t.4) %t.5 = icmp ult i64 %v2, 301 call void @use(i1 %t.5) %t.6 = icmp eq i64 %v2, 300 call void @use(i1 %t.6) ret void } define internal {i64, i64} @struct2() { ; CHECK-LABEL: @struct2( ; CHECK-NEXT: [[C:%.*]] = call i1 @cond() ; CHECK-NEXT: br i1 [[C]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: ; CHECK-NEXT: br label [[EXIT:%.*]] ; CHECK: false: ; CHECK-NEXT: br label [[EXIT]] ; CHECK: exit: ; CHECK-NEXT: [[V1:%.*]] = phi i64 [ 20, [[TRUE]] ], [ 30, [[FALSE]] ] ; CHECK-NEXT: [[V2:%.*]] = phi i64 [ 200, [[TRUE]] ], [ 300, [[FALSE]] ] ; CHECK-NEXT: [[S_1:%.*]] = insertvalue { i64, i64 } poison, i64 [[V1]], 0 ; CHECK-NEXT: [[S_2:%.*]] = insertvalue { i64, i64 } [[S_1]], i64 [[V2]], 1 ; CHECK-NEXT: ret { i64, i64 } [[S_2]] ; %c = call i1 @cond() br i1 %c, label %true, label %false true: br label %exit false: br label %exit exit: %v1 = phi i64 [ 20, %true ], [ 30, %false ] %v2 = phi i64 [ 200, %true ], [ 300, %false ] %s.1 = insertvalue {i64, i64} poison, i64 %v1, 0 %s.2 = insertvalue {i64, i64} %s.1, i64 %v2, 1 ret {i64, i64} %s.2 } define void @struct2_caller() { ; CHECK-LABEL: @struct2_caller( ; CHECK-NEXT: [[S:%.*]] = call { i64, i64 } @struct2() ; CHECK-NEXT: [[V1:%.*]] = extractvalue { i64, i64 } [[S]], 0 ; CHECK-NEXT: [[V2:%.*]] = extractvalue { i64, i64 } [[S]], 1 ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i64 [[V1]], 25 ; CHECK-NEXT: call void @use(i1 [[C_1]]) ; CHECK-NEXT: [[C_2:%.*]] = icmp ult i64 [[V1]], 25 ; CHECK-NEXT: call void @use(i1 [[C_2]]) ; CHECK-NEXT: [[C_3:%.*]] = icmp eq i64 [[V2]], 250 ; CHECK-NEXT: call void @use(i1 [[C_3]]) ; CHECK-NEXT: [[C_4:%.*]] = icmp ugt i64 [[V2]], 250 ; CHECK-NEXT: call void @use(i1 [[C_4]]) ; CHECK-NEXT: ret void ; %s = call {i64, i64} @struct2() %v1 = extractvalue {i64, i64} %s, 0 %v2 = extractvalue {i64, i64} %s, 1 %t.1 = icmp ne i64 %v1, 10 call void @use(i1 %t.1) %t.2 = icmp ult i64 %v1, 100 call void @use(i1 %t.2) %t.3 = icmp ne i64 %v2, 0 call void @use(i1 %t.3) %t.4 = icmp ult i64 %v2, 301 call void @use(i1 %t.4) %f.1 = icmp eq i64 %v1, 10 call void @use(i1 %f.1) %f.2 = icmp ult i64 %v1, 19 call void @use(i1 %f.2) %f.3 = icmp eq i64 %v2, 50 call void @use(i1 %f.3) %f.4 = icmp ugt i64 %v2, 301 call void @use(i1 %f.4) %c.1 = icmp eq i64 %v1, 25 call void @use(i1 %c.1) %c.2 = icmp ult i64 %v1, 25 call void @use(i1 %c.2) %c.3 = icmp eq i64 %v2, 250 call void @use(i1 %c.3) %c.4 = icmp ugt i64 %v2, 250 call void @use(i1 %c.4) ret void } %"phi_type" = type {i64, i64} define internal %"phi_type" @test(i32 %input) { ; CHECK-LABEL: @test( ; CHECK-NEXT: br label [[COND_TRUE_I:%.*]] ; CHECK: cond.true.i: ; CHECK-NEXT: br label [[COND_END_I:%.*]] ; CHECK: cond.end.i: ; CHECK-NEXT: ret [[PHI_TYPE:%.*]] poison ; %cmp.cond = icmp eq i32 %input, 1 br i1 %cmp.cond, label %cond.true.i, label %cond.false.i cond.true.i: %r1.tmp = insertvalue %"phi_type" poison, i64 1, 0 %r1.tmp.2 = insertvalue %"phi_type" %r1.tmp, i64 2, 1 br label %cond.end.i cond.false.i: %r2.tmp = insertvalue %"phi_type" poison, i64 3, 0 %r2.tmp.2 = insertvalue %"phi_type" %r2.tmp, i64 4, 1 br label %cond.end.i cond.end.i: %retval = phi %"phi_type" [ %r1.tmp.2, %cond.true.i ], [ %r2.tmp.2, %cond.false.i ] ret %"phi_type" %retval } define %"phi_type" @test2() { ; CHECK-LABEL: @test2( ; CHECK-NEXT: [[CALL_1:%.*]] = tail call fastcc [[PHI_TYPE:%.*]] @[[TEST:[a-zA-Z0-9_$\"\\.-]*[a-zA-Z_$\"\\.-][a-zA-Z0-9_$\"\\.-]*]](i32 noundef 1) ; CHECK-NEXT: ret [[PHI_TYPE]] { i64 1, i64 2 } ; %call.1 = tail call fastcc noundef %"phi_type" @test(i32 noundef 1) ret %"phi_type" %call.1 }