1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt %s -passes=ipsccp -S | FileCheck %s 3 4declare i1 @cond() 5declare void @use(i1) 6 7define internal {i64, i64} @struct1() { 8; CHECK-LABEL: @struct1( 9; CHECK-NEXT: [[C:%.*]] = call i1 @cond() 10; CHECK-NEXT: br i1 [[C]], label [[TRUE:%.*]], label [[FALSE:%.*]] 11; CHECK: true: 12; CHECK-NEXT: br label [[EXIT:%.*]] 13; CHECK: false: 14; CHECK-NEXT: br label [[EXIT]] 15; CHECK: exit: 16; CHECK-NEXT: [[R:%.*]] = phi { i64, i64 } [ { i64 20, i64 200 }, [[TRUE]] ], [ { i64 30, i64 300 }, [[FALSE]] ] 17; CHECK-NEXT: ret { i64, i64 } [[R]] 18; 19 %c = call i1 @cond() 20 br i1 %c, label %true, label %false 21 22true: 23 %s.1 = insertvalue {i64, i64} undef, i64 20, 0 24 %s.2 = insertvalue {i64, i64} %s.1, i64 200, 1 25 br label %exit 26 27false: 28 %s.3 = insertvalue {i64, i64} undef, i64 30, 0 29 %s.4 = insertvalue {i64, i64} %s.3, i64 300, 1 30 br label %exit 31 32exit: 33 %r = phi {i64, i64} [ %s.2, %true], [ %s.4, %false ] 34 ret {i64, i64} %r 35} 36 37define void @struct1_caller() { 38; CHECK-LABEL: @struct1_caller( 39; CHECK-NEXT: [[S:%.*]] = call { i64, i64 } @struct1() 40; CHECK-NEXT: [[V1:%.*]] = extractvalue { i64, i64 } [[S]], 0 41; CHECK-NEXT: [[V2:%.*]] = extractvalue { i64, i64 } [[S]], 1 42; CHECK-NEXT: [[T_1:%.*]] = icmp ne i64 [[V1]], 10 43; CHECK-NEXT: call void @use(i1 [[T_1]]) 44; CHECK-NEXT: [[T_2:%.*]] = icmp ult i64 [[V1]], 100 45; CHECK-NEXT: call void @use(i1 [[T_2]]) 46; CHECK-NEXT: [[T_3:%.*]] = icmp ne i64 [[V2]], 0 47; CHECK-NEXT: call void @use(i1 [[T_3]]) 48; CHECK-NEXT: [[T_4:%.*]] = icmp ult i64 [[V2]], 301 49; CHECK-NEXT: call void @use(i1 [[T_4]]) 50; CHECK-NEXT: ret void 51; 52 %s = call {i64, i64} @struct1() 53 %v1 = extractvalue {i64, i64} %s, 0 54 %v2 = extractvalue {i64, i64} %s, 1 55 56 %t.1 = icmp ne i64 %v1, 10 57 call void @use(i1 %t.1) 58 %t.2 = icmp ult i64 %v1, 100 59 call void @use(i1 %t.2) 60 %t.3 = icmp ne i64 %v2, 0 61 call void @use(i1 %t.3) 62 %t.4 = icmp ult i64 %v2, 301 63 call void @use(i1 %t.4) 64 65 ret void 66} 67 68define internal {i64, i64} @struct2() { 69; CHECK-LABEL: @struct2( 70; CHECK-NEXT: [[C:%.*]] = call i1 @cond() 71; CHECK-NEXT: br i1 [[C]], label [[TRUE:%.*]], label [[FALSE:%.*]] 72; CHECK: true: 73; CHECK-NEXT: br label [[EXIT:%.*]] 74; CHECK: false: 75; CHECK-NEXT: br label [[EXIT]] 76; CHECK: exit: 77; CHECK-NEXT: [[V1:%.*]] = phi i64 [ 20, [[TRUE]] ], [ 30, [[FALSE]] ] 78; CHECK-NEXT: [[V2:%.*]] = phi i64 [ 200, [[TRUE]] ], [ 300, [[FALSE]] ] 79; CHECK-NEXT: [[S_1:%.*]] = insertvalue { i64, i64 } undef, i64 [[V1]], 0 80; CHECK-NEXT: [[S_2:%.*]] = insertvalue { i64, i64 } [[S_1]], i64 [[V2]], 1 81; CHECK-NEXT: ret { i64, i64 } [[S_2]] 82; 83 %c = call i1 @cond() 84 br i1 %c, label %true, label %false 85 86true: 87 br label %exit 88 89false: 90 br label %exit 91 92exit: 93 %v1 = phi i64 [ 20, %true ], [ 30, %false ] 94 %v2 = phi i64 [ 200, %true ], [ 300, %false ] 95 %s.1 = insertvalue {i64, i64} undef, i64 %v1, 0 96 %s.2 = insertvalue {i64, i64} %s.1, i64 %v2, 1 97 ret {i64, i64} %s.2 98} 99 100define void @struct2_caller() { 101; CHECK-LABEL: @struct2_caller( 102; CHECK-NEXT: [[S:%.*]] = call { i64, i64 } @struct2() 103; CHECK-NEXT: [[V1:%.*]] = extractvalue { i64, i64 } [[S]], 0 104; CHECK-NEXT: [[V2:%.*]] = extractvalue { i64, i64 } [[S]], 1 105; CHECK-NEXT: call void @use(i1 true) 106; CHECK-NEXT: call void @use(i1 true) 107; CHECK-NEXT: call void @use(i1 true) 108; CHECK-NEXT: call void @use(i1 true) 109; CHECK-NEXT: call void @use(i1 false) 110; CHECK-NEXT: call void @use(i1 false) 111; CHECK-NEXT: call void @use(i1 false) 112; CHECK-NEXT: call void @use(i1 false) 113; CHECK-NEXT: [[C_1:%.*]] = icmp eq i64 [[V1]], 25 114; CHECK-NEXT: call void @use(i1 [[C_1]]) 115; CHECK-NEXT: [[C_2:%.*]] = icmp ult i64 [[V1]], 25 116; CHECK-NEXT: call void @use(i1 [[C_2]]) 117; CHECK-NEXT: [[C_3:%.*]] = icmp eq i64 [[V2]], 250 118; CHECK-NEXT: call void @use(i1 [[C_3]]) 119; CHECK-NEXT: [[C_4:%.*]] = icmp ugt i64 [[V2]], 250 120; CHECK-NEXT: call void @use(i1 [[C_4]]) 121; CHECK-NEXT: ret void 122; 123 %s = call {i64, i64} @struct2() 124 %v1 = extractvalue {i64, i64} %s, 0 125 %v2 = extractvalue {i64, i64} %s, 1 126 127 %t.1 = icmp ne i64 %v1, 10 128 call void @use(i1 %t.1) 129 %t.2 = icmp ult i64 %v1, 100 130 call void @use(i1 %t.2) 131 %t.3 = icmp ne i64 %v2, 0 132 call void @use(i1 %t.3) 133 %t.4 = icmp ult i64 %v2, 301 134 call void @use(i1 %t.4) 135 136 %f.1 = icmp eq i64 %v1, 10 137 call void @use(i1 %f.1) 138 %f.2 = icmp ult i64 %v1, 19 139 call void @use(i1 %f.2) 140 %f.3 = icmp eq i64 %v2, 50 141 call void @use(i1 %f.3) 142 %f.4 = icmp ugt i64 %v2, 301 143 call void @use(i1 %f.4) 144 145 %c.1 = icmp eq i64 %v1, 25 146 call void @use(i1 %c.1) 147 %c.2 = icmp ult i64 %v1, 25 148 call void @use(i1 %c.2) 149 %c.3 = icmp eq i64 %v2, 250 150 call void @use(i1 %c.3) 151 %c.4 = icmp ugt i64 %v2, 250 152 call void @use(i1 %c.4) 153 154 ret void 155} 156