1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -S -simplifycfg | FileCheck %s 3 4declare void @foo() 5declare void @bar() 6 7define void @test_and1(i32 %a, i32 %b) { 8; CHECK-LABEL: @test_and1( 9; CHECK-NEXT: entry: 10; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 0 11; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[B:%.*]], 0 12; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]] 13; CHECK-NEXT: br i1 [[AND]], label [[TAKEN:%.*]], label [[END:%.*]] 14; CHECK: taken: 15; CHECK-NEXT: call void @bar() 16; CHECK-NEXT: call void @foo() 17; CHECK-NEXT: br label [[END]] 18; CHECK: end: 19; CHECK-NEXT: ret void 20; 21entry: 22 %cmp1 = icmp eq i32 %a, 0 23 %cmp2 = icmp eq i32 %b, 0 24 %and = and i1 %cmp1, %cmp2 25 br i1 %and, label %taken, label %end 26 27taken: 28 call void @bar() 29 %cmp3 = icmp eq i32 %a, 0 ;; <-- implied true 30 br i1 %cmp3, label %if.then, label %end 31 32if.then: 33 call void @foo() 34 br label %end 35 36end: 37 ret void 38} 39 40; We can't infer anything if the result of the 'and' is false 41 42define void @test_and2(i32 %a, i32 %b) { 43; CHECK-LABEL: @test_and2( 44; CHECK-NEXT: entry: 45; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 0 46; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[B:%.*]], 0 47; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP1]], [[CMP2]] 48; CHECK-NEXT: br i1 [[AND]], label [[END:%.*]], label [[TAKEN:%.*]] 49; CHECK: taken: 50; CHECK-NEXT: call void @bar() 51; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[A]], 0 52; CHECK-NEXT: br i1 [[CMP3]], label [[IF_THEN:%.*]], label [[END]] 53; CHECK: if.then: 54; CHECK-NEXT: call void @foo() 55; CHECK-NEXT: br label [[END]] 56; CHECK: end: 57; CHECK-NEXT: ret void 58; 59entry: 60 %cmp1 = icmp eq i32 %a, 0 61 %cmp2 = icmp eq i32 %b, 0 62 %and = and i1 %cmp1, %cmp2 63 br i1 %and, label %end, label %taken 64 65taken: 66 call void @bar() 67 %cmp3 = icmp eq i32 %a, 0 68 br i1 %cmp3, label %if.then, label %end 69 70if.then: 71 call void @foo() 72 br label %end 73 74end: 75 ret void 76} 77 78define void @test_or1(i32 %a, i32 %b) { 79; CHECK-LABEL: @test_or1( 80; CHECK-NEXT: entry: 81; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 0 82; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[B:%.*]], 0 83; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]] 84; CHECK-NEXT: br i1 [[OR]], label [[END:%.*]], label [[TAKEN:%.*]] 85; CHECK: taken: 86; CHECK-NEXT: call void @bar() 87; CHECK-NEXT: call void @foo() 88; CHECK-NEXT: br label [[END]] 89; CHECK: end: 90; CHECK-NEXT: ret void 91; 92entry: 93 %cmp1 = icmp eq i32 %a, 0 94 %cmp2 = icmp eq i32 %b, 0 95 %or = or i1 %cmp1, %cmp2 96 br i1 %or, label %end, label %taken 97 98taken: 99 call void @bar() 100 %cmp3 = icmp ne i32 %a, 0 ;; <-- implied true 101 br i1 %cmp3, label %if.then, label %end 102 103if.then: 104 call void @foo() 105 br label %end 106 107end: 108 ret void 109} 110 111; We can't infer anything if the result of the 'or' is true 112 113define void @test_or2(i32 %a, i32 %b) { 114; CHECK-LABEL: @test_or2( 115; CHECK-NEXT: entry: 116; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], 0 117; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[B:%.*]], 0 118; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP1]], [[CMP2]] 119; CHECK-NEXT: br i1 [[OR]], label [[TAKEN:%.*]], label [[END:%.*]] 120; CHECK: taken: 121; CHECK-NEXT: call void @bar() 122; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[A]], 0 123; CHECK-NEXT: br i1 [[CMP3]], label [[IF_THEN:%.*]], label [[END]] 124; CHECK: if.then: 125; CHECK-NEXT: call void @foo() 126; CHECK-NEXT: br label [[END]] 127; CHECK: end: 128; CHECK-NEXT: ret void 129; 130entry: 131 %cmp1 = icmp eq i32 %a, 0 132 %cmp2 = icmp eq i32 %b, 0 133 %or = or i1 %cmp1, %cmp2 134 br i1 %or, label %taken, label %end 135 136taken: 137 call void @bar() 138 %cmp3 = icmp eq i32 %a, 0 139 br i1 %cmp3, label %if.then, label %end 140 141if.then: 142 call void @foo() 143 br label %end 144 145end: 146 ret void 147} 148 149; We can recurse a tree of 'and' or 'or's. 150 151define void @test_and_recurse1(i32 %a, i32 %b, i32 %c) { 152; CHECK-LABEL: @test_and_recurse1( 153; CHECK-NEXT: entry: 154; CHECK-NEXT: [[CMPA:%.*]] = icmp eq i32 [[A:%.*]], 0 155; CHECK-NEXT: [[CMPB:%.*]] = icmp eq i32 [[B:%.*]], 0 156; CHECK-NEXT: [[CMPC:%.*]] = icmp eq i32 [[C:%.*]], 0 157; CHECK-NEXT: [[AND1:%.*]] = and i1 [[CMPA]], [[CMPB]] 158; CHECK-NEXT: [[AND2:%.*]] = and i1 [[AND1]], [[CMPC]] 159; CHECK-NEXT: br i1 [[AND2]], label [[TAKEN:%.*]], label [[END:%.*]] 160; CHECK: taken: 161; CHECK-NEXT: call void @bar() 162; CHECK-NEXT: call void @foo() 163; CHECK-NEXT: br label [[END]] 164; CHECK: end: 165; CHECK-NEXT: ret void 166; 167entry: 168 %cmpa = icmp eq i32 %a, 0 169 %cmpb = icmp eq i32 %b, 0 170 %cmpc = icmp eq i32 %c, 0 171 %and1 = and i1 %cmpa, %cmpb 172 %and2 = and i1 %and1, %cmpc 173 br i1 %and2, label %taken, label %end 174 175taken: 176 call void @bar() 177 %cmp3 = icmp eq i32 %a, 0 178 br i1 %cmp3, label %if.then, label %end 179 180if.then: 181 call void @foo() 182 br label %end 183 184end: 185 ret void 186} 187 188; Check to make sure we don't recurse too deep. 189 190define void @test_and_recurse2(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, 191; CHECK-LABEL: @test_and_recurse2( 192; CHECK-NEXT: entry: 193; CHECK-NEXT: [[CMPA:%.*]] = icmp eq i32 [[A:%.*]], 0 194; CHECK-NEXT: [[CMPB:%.*]] = icmp eq i32 [[B:%.*]], 0 195; CHECK-NEXT: [[CMPC:%.*]] = icmp eq i32 [[C:%.*]], 0 196; CHECK-NEXT: [[CMPD:%.*]] = icmp eq i32 [[D:%.*]], 0 197; CHECK-NEXT: [[CMPE:%.*]] = icmp eq i32 [[E:%.*]], 0 198; CHECK-NEXT: [[CMPF:%.*]] = icmp eq i32 [[F:%.*]], 0 199; CHECK-NEXT: [[CMPG:%.*]] = icmp eq i32 [[G:%.*]], 0 200; CHECK-NEXT: [[CMPH:%.*]] = icmp eq i32 [[H:%.*]], 0 201; CHECK-NEXT: [[AND1:%.*]] = and i1 [[CMPA]], [[CMPB]] 202; CHECK-NEXT: [[AND2:%.*]] = and i1 [[AND1]], [[CMPC]] 203; CHECK-NEXT: [[AND3:%.*]] = and i1 [[AND2]], [[CMPD]] 204; CHECK-NEXT: [[AND4:%.*]] = and i1 [[AND3]], [[CMPE]] 205; CHECK-NEXT: [[AND5:%.*]] = and i1 [[AND4]], [[CMPF]] 206; CHECK-NEXT: [[AND6:%.*]] = and i1 [[AND5]], [[CMPG]] 207; CHECK-NEXT: [[AND7:%.*]] = and i1 [[AND6]], [[CMPH]] 208; CHECK-NEXT: br i1 [[AND7]], label [[TAKEN:%.*]], label [[END:%.*]] 209; CHECK: taken: 210; CHECK-NEXT: call void @bar() 211; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[A]], 0 212; CHECK-NEXT: br i1 [[CMP3]], label [[IF_THEN:%.*]], label [[END]] 213; CHECK: if.then: 214; CHECK-NEXT: call void @foo() 215; CHECK-NEXT: br label [[END]] 216; CHECK: end: 217; CHECK-NEXT: ret void 218; 219 i32 %g, i32 %h) { 220entry: 221 %cmpa = icmp eq i32 %a, 0 222 %cmpb = icmp eq i32 %b, 0 223 %cmpc = icmp eq i32 %c, 0 224 %cmpd = icmp eq i32 %d, 0 225 %cmpe = icmp eq i32 %e, 0 226 %cmpf = icmp eq i32 %f, 0 227 %cmpg = icmp eq i32 %g, 0 228 %cmph = icmp eq i32 %h, 0 229 %and1 = and i1 %cmpa, %cmpb 230 %and2 = and i1 %and1, %cmpc 231 %and3 = and i1 %and2, %cmpd 232 %and4 = and i1 %and3, %cmpe 233 %and5 = and i1 %and4, %cmpf 234 %and6 = and i1 %and5, %cmpg 235 %and7 = and i1 %and6, %cmph 236 br i1 %and7, label %taken, label %end 237 238taken: 239 call void @bar() 240 %cmp3 = icmp eq i32 %a, 0 ; <-- can be implied true 241 br i1 %cmp3, label %if.then, label %end 242 243if.then: 244 call void @foo() 245 br label %end 246 247end: 248 ret void 249} 250 251