| ; 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 | |
| } |