1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s 3 4declare { i8, i1 } @llvm.usub.with.overflow.i8(i8, i8) 5 6define i8 @usub_no_overflow_due_to_cmp_condition(i8 %a, i8 %b) { 7; CHECK-LABEL: @usub_no_overflow_due_to_cmp_condition( 8; CHECK-NEXT: entry: 9; CHECK-NEXT: [[C_1:%.*]] = icmp uge i8 [[B:%.*]], [[A:%.*]] 10; CHECK-NEXT: br i1 [[C_1]], label [[MATH:%.*]], label [[EXIT_FAIL:%.*]] 11; CHECK: math: 12; CHECK-NEXT: [[OP:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[B]], i8 [[A]]) 13; CHECK-NEXT: [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1 14; CHECK-NEXT: br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]] 15; CHECK: exit.ok: 16; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0 17; CHECK-NEXT: ret i8 [[RES]] 18; CHECK: exit.fail: 19; CHECK-NEXT: ret i8 0 20; 21entry: 22 %c.1 = icmp uge i8 %b, %a 23 br i1 %c.1, label %math, label %exit.fail 24 25math: 26 %op = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %b, i8 %a) 27 %status = extractvalue { i8, i1 } %op, 1 28 br i1 %status, label %exit.fail, label %exit.ok 29 30exit.ok: 31 %res = extractvalue { i8, i1 } %op, 0 32 ret i8 %res 33 34exit.fail: 35 ret i8 0 36} 37 38define i8 @usub_no_overflow_due_to_cmp_condition2(i8 %a, i8 %b) { 39; CHECK-LABEL: @usub_no_overflow_due_to_cmp_condition2( 40; CHECK-NEXT: entry: 41; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[B:%.*]], [[A:%.*]] 42; CHECK-NEXT: br i1 [[C_1]], label [[EXIT_FAIL:%.*]], label [[MATH:%.*]] 43; CHECK: math: 44; CHECK-NEXT: [[OP:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[B]], i8 [[A]]) 45; CHECK-NEXT: [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1 46; CHECK-NEXT: br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]] 47; CHECK: exit.ok: 48; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0 49; CHECK-NEXT: ret i8 [[RES]] 50; CHECK: exit.fail: 51; CHECK-NEXT: ret i8 0 52; 53entry: 54 %c.1 = icmp ule i8 %b, %a 55 br i1 %c.1, label %exit.fail, label %math 56 57math: 58 %op = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %b, i8 %a) 59 %status = extractvalue { i8, i1 } %op, 1 60 br i1 %status, label %exit.fail, label %exit.ok 61 62exit.ok: 63 %res = extractvalue { i8, i1 } %op, 0 64 ret i8 %res 65 66exit.fail: 67 ret i8 0 68} 69 70declare void @use_res({ i8, i1 }) 71 72define i8 @sub_no_overflow_due_to_cmp_condition_result_used(i8 %a, i8 %b) { 73; CHECK-LABEL: @sub_no_overflow_due_to_cmp_condition_result_used( 74; CHECK-NEXT: entry: 75; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[B:%.*]], [[A:%.*]] 76; CHECK-NEXT: br i1 [[C_1]], label [[EXIT_FAIL:%.*]], label [[MATH:%.*]] 77; CHECK: math: 78; CHECK-NEXT: [[OP:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[B]], i8 [[A]]) 79; CHECK-NEXT: call void @use_res({ i8, i1 } [[OP]]) 80; CHECK-NEXT: [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1 81; CHECK-NEXT: br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]] 82; CHECK: exit.ok: 83; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0 84; CHECK-NEXT: ret i8 [[RES]] 85; CHECK: exit.fail: 86; CHECK-NEXT: ret i8 0 87; 88entry: 89 %c.1 = icmp ule i8 %b, %a 90 br i1 %c.1, label %exit.fail, label %math 91 92math: 93 %op = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %b, i8 %a) 94 call void @use_res({ i8, i1 } %op) 95 %status = extractvalue { i8, i1 } %op, 1 96 br i1 %status, label %exit.fail, label %exit.ok 97 98exit.ok: 99 %res = extractvalue { i8, i1 } %op, 0 100 ret i8 %res 101 102exit.fail: 103 ret i8 0 104} 105 106define i8 @usub_no_overflow_due_to_or_conds(i8 %a, i8 %b) { 107; CHECK-LABEL: @usub_no_overflow_due_to_or_conds( 108; CHECK-NEXT: entry: 109; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[B:%.*]], [[A:%.*]] 110; CHECK-NEXT: [[C_2:%.*]] = icmp ule i8 [[A]], 0 111; CHECK-NEXT: [[OR:%.*]] = or i1 [[C_2]], [[C_1]] 112; CHECK-NEXT: br i1 [[OR]], label [[EXIT_FAIL:%.*]], label [[MATH:%.*]] 113; CHECK: math: 114; CHECK-NEXT: [[OP:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[B]], i8 [[A]]) 115; CHECK-NEXT: [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1 116; CHECK-NEXT: br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]] 117; CHECK: exit.ok: 118; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0 119; CHECK-NEXT: ret i8 [[RES]] 120; CHECK: exit.fail: 121; CHECK-NEXT: ret i8 0 122; 123entry: 124 %c.1 = icmp ule i8 %b, %a 125 %c.2 = icmp ule i8 %a, 0 126 %or = or i1 %c.2, %c.1 127 br i1 %or, label %exit.fail, label %math 128 129math: 130 %op = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %b, i8 %a) 131 %status = extractvalue { i8, i1 } %op, 1 132 br i1 %status, label %exit.fail, label %exit.ok 133 134exit.ok: 135 %res = extractvalue { i8, i1 } %op, 0 136 ret i8 %res 137 138exit.fail: 139 ret i8 0 140} 141 142define i8 @usub_no_overflow_due_to_or_conds_sub_result_not_used(i8 %a, i8 %b) { 143; CHECK-LABEL: @usub_no_overflow_due_to_or_conds_sub_result_not_used( 144; CHECK-NEXT: entry: 145; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[B:%.*]], [[A:%.*]] 146; CHECK-NEXT: [[C_2:%.*]] = icmp ule i8 [[A]], 0 147; CHECK-NEXT: [[OR:%.*]] = or i1 [[C_2]], [[C_1]] 148; CHECK-NEXT: br i1 [[OR]], label [[EXIT_FAIL:%.*]], label [[MATH:%.*]] 149; CHECK: math: 150; CHECK-NEXT: [[OP:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[B]], i8 [[A]]) 151; CHECK-NEXT: [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1 152; CHECK-NEXT: br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]] 153; CHECK: exit.ok: 154; CHECK-NEXT: ret i8 20 155; CHECK: exit.fail: 156; CHECK-NEXT: ret i8 0 157; 158entry: 159 %c.1 = icmp ule i8 %b, %a 160 %c.2 = icmp ule i8 %a, 0 161 %or = or i1 %c.2, %c.1 162 br i1 %or, label %exit.fail, label %math 163 164math: 165 %op = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %b, i8 %a) 166 %status = extractvalue { i8, i1 } %op, 1 167 br i1 %status, label %exit.fail, label %exit.ok 168 169exit.ok: 170 ret i8 20 171 172exit.fail: 173 ret i8 0 174} 175 176define i8 @usub_no_overflow_due_to_and_conds(i8 %a, i8 %b) { 177; CHECK-LABEL: @usub_no_overflow_due_to_and_conds( 178; CHECK-NEXT: entry: 179; CHECK-NEXT: [[C_1:%.*]] = icmp uge i8 [[B:%.*]], [[A:%.*]] 180; CHECK-NEXT: [[C_2:%.*]] = icmp uge i8 [[A]], -1 181; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_2]], [[C_1]] 182; CHECK-NEXT: br i1 [[AND]], label [[MATH:%.*]], label [[EXIT_FAIL:%.*]] 183; CHECK: math: 184; CHECK-NEXT: [[OP:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[B]], i8 [[A]]) 185; CHECK-NEXT: [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1 186; CHECK-NEXT: br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]] 187; CHECK: exit.ok: 188; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0 189; CHECK-NEXT: ret i8 [[RES]] 190; CHECK: exit.fail: 191; CHECK-NEXT: ret i8 0 192; 193entry: 194 %c.1 = icmp uge i8 %b, %a 195 %c.2 = icmp uge i8 %a, -1 196 %and = and i1 %c.2, %c.1 197 br i1 %and, label %math, label %exit.fail 198 199math: 200 %op = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %b, i8 %a) 201 %status = extractvalue { i8, i1 } %op, 1 202 br i1 %status, label %exit.fail, label %exit.ok 203 204exit.ok: 205 %res = extractvalue { i8, i1 } %op, 0 206 ret i8 %res 207 208exit.fail: 209 ret i8 0 210} 211 212define i8 @usub_may_overflow1(i8 %a, i8 %b) { 213; CHECK-LABEL: @usub_may_overflow1( 214; CHECK-NEXT: entry: 215; CHECK-NEXT: br i1 true, label [[MATH:%.*]], label [[EXIT_FAIL:%.*]] 216; CHECK: math: 217; CHECK-NEXT: [[OP:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[B:%.*]], i8 [[A:%.*]]) 218; CHECK-NEXT: [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1 219; CHECK-NEXT: br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]] 220; CHECK: exit.ok: 221; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0 222; CHECK-NEXT: ret i8 [[RES]] 223; CHECK: exit.fail: 224; CHECK-NEXT: ret i8 0 225; 226entry: 227 %c.1 = icmp uge i8 %a, 0 228 br i1 %c.1, label %math, label %exit.fail 229 230math: 231 %op = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %b, i8 %a) 232 %status = extractvalue { i8, i1 } %op, 1 233 br i1 %status, label %exit.fail, label %exit.ok 234 235exit.ok: 236 %res = extractvalue { i8, i1 } %op, 0 237 ret i8 %res 238 239exit.fail: 240 ret i8 0 241} 242 243 244define i8 @usub_may_overflow2(i8 %a, i8 %b) { 245; CHECK-LABEL: @usub_may_overflow2( 246; CHECK-NEXT: entry: 247; CHECK-NEXT: [[C_1:%.*]] = icmp sge i8 [[B:%.*]], [[A:%.*]] 248; CHECK-NEXT: br i1 [[C_1]], label [[MATH:%.*]], label [[EXIT_FAIL:%.*]] 249; CHECK: math: 250; CHECK-NEXT: [[OP:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[B]], i8 [[A]]) 251; CHECK-NEXT: [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1 252; CHECK-NEXT: br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]] 253; CHECK: exit.ok: 254; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0 255; CHECK-NEXT: ret i8 [[RES]] 256; CHECK: exit.fail: 257; CHECK-NEXT: ret i8 0 258; 259entry: 260 %c.1 = icmp sge i8 %b, %a 261 br i1 %c.1, label %math, label %exit.fail 262 263math: 264 %op = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %b, i8 %a) 265 %status = extractvalue { i8, i1 } %op, 1 266 br i1 %status, label %exit.fail, label %exit.ok 267 268exit.ok: 269 %res = extractvalue { i8, i1 } %op, 0 270 ret i8 %res 271 272exit.fail: 273 ret i8 0 274} 275 276define i8 @usub_may_overflow3(i8 %a, i8 %b) { 277; CHECK-LABEL: @usub_may_overflow3( 278; CHECK-NEXT: entry: 279; CHECK-NEXT: [[C_1:%.*]] = icmp slt i8 [[B:%.*]], [[A:%.*]] 280; CHECK-NEXT: br i1 [[C_1]], label [[EXIT_FAIL:%.*]], label [[MATH:%.*]] 281; CHECK: math: 282; CHECK-NEXT: [[OP:%.*]] = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[B]], i8 [[A]]) 283; CHECK-NEXT: [[STATUS:%.*]] = extractvalue { i8, i1 } [[OP]], 1 284; CHECK-NEXT: br i1 [[STATUS]], label [[EXIT_FAIL]], label [[EXIT_OK:%.*]] 285; CHECK: exit.ok: 286; CHECK-NEXT: [[RES:%.*]] = extractvalue { i8, i1 } [[OP]], 0 287; CHECK-NEXT: ret i8 [[RES]] 288; CHECK: exit.fail: 289; CHECK-NEXT: ret i8 0 290; 291entry: 292 %c.1 = icmp slt i8 %b, %a 293 br i1 %c.1, label %exit.fail, label %math 294math: 295 %op = tail call { i8, i1 } @llvm.usub.with.overflow.i8(i8 %b, i8 %a) 296 %status = extractvalue { i8, i1 } %op, 1 297 br i1 %status, label %exit.fail, label %exit.ok 298 299exit.ok: 300 %res = extractvalue { i8, i1 } %op, 0 301 ret i8 %res 302 303exit.fail: 304 ret i8 0 305} 306 307