1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; Replace a 'select' with 'or' in 'select - cmp [eq|ne] - br' sequence 3; RUN: opt -passes=instcombine -S < %s | FileCheck %s 4 5%struct.S = type { ptr, i32, i32 } 6%C = type <{ %struct.S }> 7 8declare void @bar(ptr) 9declare void @foobar() 10 11define void @test1(ptr %arg) { 12; CHECK-LABEL: @test1( 13; CHECK-NEXT: entry: 14; CHECK-NEXT: [[M:%.*]] = load ptr, ptr [[ARG:%.*]], align 8 15; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[ARG]], i64 16 16; CHECK-NEXT: [[N:%.*]] = load ptr, ptr [[TMP1]], align 8 17; CHECK-NEXT: [[TMP5_NOT:%.*]] = icmp eq ptr [[M]], [[N]] 18; CHECK-NEXT: br i1 [[TMP5_NOT]], label [[BB8:%.*]], label [[BB10:%.*]] 19; CHECK: bb: 20; CHECK-NEXT: ret void 21; CHECK: bb8: 22; CHECK-NEXT: tail call void @bar(ptr nonnull [[ARG]]) 23; CHECK-NEXT: br label [[BB:%.*]] 24; CHECK: bb10: 25; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[M]], i64 72 26; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP2]], align 8 27; CHECK-NEXT: [[TMP11:%.*]] = tail call i64 [[TMP4]](ptr nonnull [[ARG]]) 28; CHECK-NEXT: br label [[BB]] 29; 30entry: 31 %m = load ptr, ptr %arg, align 8 32 %tmp1 = getelementptr inbounds %C, ptr %arg, i64 1, i32 0, i32 0 33 %n = load ptr, ptr %tmp1, align 8 34 %tmp2 = getelementptr inbounds i64, ptr %m, i64 9 35 %tmp4 = load ptr, ptr %tmp2, align 8 36 %tmp5 = icmp eq ptr %m, %n 37 %tmp6 = select i1 %tmp5, ptr %arg, ptr null 38 %tmp7 = icmp eq ptr %tmp6, null 39 br i1 %tmp7, label %bb10, label %bb8 40 41bb: ; preds = %bb10, %bb8 42 ret void 43 44bb8: ; preds = %entry 45 tail call void @bar(ptr %tmp6) 46 br label %bb 47 48bb10: ; preds = %entry 49 %tmp11 = tail call i64 %tmp4(ptr %arg) 50 br label %bb 51} 52 53define void @test2(ptr %arg) { 54; CHECK-LABEL: @test2( 55; CHECK-NEXT: entry: 56; CHECK-NEXT: [[M:%.*]] = load ptr, ptr [[ARG:%.*]], align 8 57; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[ARG]], i64 16 58; CHECK-NEXT: [[N:%.*]] = load ptr, ptr [[TMP1]], align 8 59; CHECK-NEXT: [[TMP5:%.*]] = icmp eq ptr [[M]], [[N]] 60; CHECK-NEXT: br i1 [[TMP5]], label [[BB10:%.*]], label [[BB8:%.*]] 61; CHECK: bb: 62; CHECK-NEXT: ret void 63; CHECK: bb8: 64; CHECK-NEXT: tail call void @bar(ptr nonnull [[ARG]]) 65; CHECK-NEXT: br label [[BB:%.*]] 66; CHECK: bb10: 67; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[M]], i64 72 68; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP2]], align 8 69; CHECK-NEXT: [[TMP11:%.*]] = tail call i64 [[TMP4]](ptr nonnull [[ARG]]) 70; CHECK-NEXT: br label [[BB]] 71; 72entry: 73 %m = load ptr, ptr %arg, align 8 74 %tmp1 = getelementptr inbounds %C, ptr %arg, i64 1, i32 0, i32 0 75 %n = load ptr, ptr %tmp1, align 8 76 %tmp2 = getelementptr inbounds i64, ptr %m, i64 9 77 %tmp4 = load ptr, ptr %tmp2, align 8 78 %tmp5 = icmp eq ptr %m, %n 79 %tmp6 = select i1 %tmp5, ptr null, ptr %arg 80 %tmp7 = icmp eq ptr %tmp6, null 81 br i1 %tmp7, label %bb10, label %bb8 82 83bb: ; preds = %bb10, %bb8 84 ret void 85 86bb8: ; preds = %entry 87 tail call void @bar(ptr %tmp6) 88 br label %bb 89 90bb10: ; preds = %entry 91 %tmp11 = tail call i64 %tmp4(ptr %arg) 92 br label %bb 93} 94 95define void @test3(ptr %arg) { 96; CHECK-LABEL: @test3( 97; CHECK-NEXT: entry: 98; CHECK-NEXT: [[M:%.*]] = load ptr, ptr [[ARG:%.*]], align 8 99; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[ARG]], i64 16 100; CHECK-NEXT: [[N:%.*]] = load ptr, ptr [[TMP1]], align 8 101; CHECK-NEXT: [[TMP5:%.*]] = icmp eq ptr [[M]], [[N]] 102; CHECK-NEXT: br i1 [[TMP5]], label [[BB8:%.*]], label [[BB10:%.*]] 103; CHECK: bb: 104; CHECK-NEXT: ret void 105; CHECK: bb8: 106; CHECK-NEXT: tail call void @bar(ptr nonnull [[ARG]]) 107; CHECK-NEXT: br label [[BB:%.*]] 108; CHECK: bb10: 109; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[M]], i64 72 110; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP2]], align 8 111; CHECK-NEXT: [[TMP11:%.*]] = tail call i64 [[TMP4]](ptr nonnull [[ARG]]) 112; CHECK-NEXT: br label [[BB]] 113; 114entry: 115 %m = load ptr, ptr %arg, align 8 116 %tmp1 = getelementptr inbounds %C, ptr %arg, i64 1, i32 0, i32 0 117 %n = load ptr, ptr %tmp1, align 8 118 %tmp2 = getelementptr inbounds i64, ptr %m, i64 9 119 %tmp4 = load ptr, ptr %tmp2, align 8 120 %tmp5 = icmp eq ptr %m, %n 121 %tmp6 = select i1 %tmp5, ptr %arg, ptr null 122 %tmp7 = icmp ne ptr %tmp6, null 123 br i1 %tmp7, label %bb8, label %bb10 124 125bb: ; preds = %bb10, %bb8 126 ret void 127 128bb8: ; preds = %entry 129 tail call void @bar(ptr %tmp6) 130 br label %bb 131 132bb10: ; preds = %entry 133 %tmp11 = tail call i64 %tmp4(ptr %arg) 134 br label %bb 135} 136 137define void @test4(ptr %arg) { 138; CHECK-LABEL: @test4( 139; CHECK-NEXT: entry: 140; CHECK-NEXT: [[M:%.*]] = load ptr, ptr [[ARG:%.*]], align 8 141; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[ARG]], i64 16 142; CHECK-NEXT: [[N:%.*]] = load ptr, ptr [[TMP1]], align 8 143; CHECK-NEXT: [[TMP5:%.*]] = icmp eq ptr [[M]], [[N]] 144; CHECK-NEXT: br i1 [[TMP5]], label [[BB10:%.*]], label [[BB8:%.*]] 145; CHECK: bb: 146; CHECK-NEXT: ret void 147; CHECK: bb8: 148; CHECK-NEXT: tail call void @bar(ptr nonnull [[ARG]]) 149; CHECK-NEXT: br label [[BB:%.*]] 150; CHECK: bb10: 151; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[M]], i64 72 152; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP2]], align 8 153; CHECK-NEXT: [[TMP11:%.*]] = tail call i64 [[TMP4]](ptr nonnull [[ARG]]) 154; CHECK-NEXT: br label [[BB]] 155; 156entry: 157 %m = load ptr, ptr %arg, align 8 158 %tmp1 = getelementptr inbounds %C, ptr %arg, i64 1, i32 0, i32 0 159 %n = load ptr, ptr %tmp1, align 8 160 %tmp2 = getelementptr inbounds i64, ptr %m, i64 9 161 %tmp4 = load ptr, ptr %tmp2, align 8 162 %tmp5 = icmp eq ptr %m, %n 163 %tmp6 = select i1 %tmp5, ptr null, ptr %arg 164 %tmp7 = icmp ne ptr %tmp6, null 165 br i1 %tmp7, label %bb8, label %bb10 166 167bb: ; preds = %bb10, %bb8 168 ret void 169 170bb8: ; preds = %entry 171 tail call void @bar(ptr %tmp6) 172 br label %bb 173 174bb10: ; preds = %entry 175 %tmp11 = tail call i64 %tmp4(ptr %arg) 176 br label %bb 177} 178 179define void @test5(ptr %arg, i1 %arg1) { 180; CHECK-LABEL: @test5( 181; CHECK-NEXT: entry: 182; CHECK-NEXT: [[TMP2_NOT1:%.*]] = icmp eq ptr [[ARG:%.*]], null 183; CHECK-NEXT: [[TMP2_NOT:%.*]] = select i1 [[ARG1:%.*]], i1 true, i1 [[TMP2_NOT1]] 184; CHECK-NEXT: br i1 [[TMP2_NOT]], label [[BB5:%.*]], label [[BB3:%.*]] 185; CHECK: bb: 186; CHECK-NEXT: ret void 187; CHECK: bb3: 188; CHECK-NEXT: tail call void @bar(ptr [[ARG]]) 189; CHECK-NEXT: br label [[BB:%.*]] 190; CHECK: bb5: 191; CHECK-NEXT: tail call void @foobar() 192; CHECK-NEXT: br label [[BB]] 193; 194entry: 195 %tmp = select i1 %arg1, ptr null, ptr %arg 196 %tmp2 = icmp ne ptr %tmp, null 197 br i1 %tmp2, label %bb3, label %bb5 198 199bb: ; preds = %bb5, %bb3 200 ret void 201 202bb3: ; preds = %entry 203 tail call void @bar(ptr %tmp) 204 br label %bb 205 206bb5: ; preds = %entry 207 tail call void @foobar() 208 br label %bb 209} 210 211; Negative test. Must not trigger the select-cmp-br combine because the result 212; of the select is used in both flows following the br (the special case where 213; the conditional branch has the same target for both flows). 214define i32 @test6(i32 %arg, i1 %arg1) { 215; CHECK-LABEL: @test6( 216; CHECK-NEXT: entry: 217; CHECK-NEXT: br i1 false, label [[BB:%.*]], label [[BB]] 218; CHECK: bb: 219; CHECK-NEXT: [[TMP:%.*]] = select i1 [[ARG1:%.*]], i32 [[ARG:%.*]], i32 0 220; CHECK-NEXT: ret i32 [[TMP]] 221; 222entry: 223 %tmp = select i1 %arg1, i32 %arg, i32 0 224 %tmp2 = icmp eq i32 %tmp, 0 225 br i1 %tmp2, label %bb, label %bb 226 227bb: ; preds = %entry, %entry 228 ret i32 %tmp 229} 230