1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s 3 4define i1 @wrapping_add_unknown_1(i8 %a) { 5; CHECK-LABEL: @wrapping_add_unknown_1( 6; CHECK-NEXT: entry: 7; CHECK-NEXT: [[SUB:%.*]] = add i8 [[A:%.*]], -1 8; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[SUB]], 0 9; CHECK-NEXT: ret i1 [[CMP]] 10; 11entry: 12 %sub = add i8 %a, -1 13 %cmp = icmp eq i8 %sub, 0 14 ret i1 %cmp 15} 16 17define i1 @wrapping_add_known_1(i8 %a) { 18; CHECK-LABEL: @wrapping_add_known_1( 19; CHECK-NEXT: entry: 20; CHECK-NEXT: [[PRE:%.*]] = icmp eq i8 [[A:%.*]], 1 21; CHECK-NEXT: br i1 [[PRE]], label [[THEN:%.*]], label [[ELSE:%.*]] 22; CHECK: then: 23; CHECK-NEXT: [[SUB_1:%.*]] = add i8 [[A]], -1 24; CHECK-NEXT: ret i1 true 25; CHECK: else: 26; CHECK-NEXT: [[SUB_2:%.*]] = add i8 [[A]], -1 27; CHECK-NEXT: [[C_2:%.*]] = icmp eq i8 [[SUB_2]], 0 28; CHECK-NEXT: ret i1 [[C_2]] 29; 30entry: 31 %pre = icmp eq i8 %a, 1 32 br i1 %pre, label %then, label %else 33 34then: 35 %sub.1 = add i8 %a, -1 36 %c.1 = icmp eq i8 %sub.1, 0 37 ret i1 %c.1 38 39else: 40 %sub.2 = add i8 %a, -1 41 %c.2 = icmp eq i8 %sub.2, 0 42 ret i1 %c.2 43} 44 45define i1 @wrapping_add_unknown_2(i8 %a) { 46; CHECK-LABEL: @wrapping_add_unknown_2( 47; CHECK-NEXT: entry: 48; CHECK-NEXT: [[PRE:%.*]] = icmp eq i8 [[A:%.*]], 0 49; CHECK-NEXT: br i1 [[PRE]], label [[THEN:%.*]], label [[ELSE:%.*]] 50; CHECK: then: 51; CHECK-NEXT: [[SUB_1:%.*]] = add i8 [[A]], -1 52; CHECK-NEXT: [[C_1:%.*]] = icmp eq i8 [[SUB_1]], 0 53; CHECK-NEXT: ret i1 [[C_1]] 54; CHECK: else: 55; CHECK-NEXT: [[SUB_2:%.*]] = add i8 [[A]], -1 56; CHECK-NEXT: [[C_2:%.*]] = icmp eq i8 [[SUB_2]], 0 57; CHECK-NEXT: ret i1 [[C_2]] 58; 59entry: 60 %pre = icmp eq i8 %a, 0 61 br i1 %pre, label %then, label %else 62 63then: 64 %sub.1 = add i8 %a, -1 65 %c.1 = icmp eq i8 %sub.1, 0 66 ret i1 %c.1 67 68else: 69 %sub.2 = add i8 %a, -1 70 %c.2 = icmp eq i8 %sub.2, 0 71 ret i1 %c.2 72} 73 74; Test from https://github.com/llvm/llvm-project/issues/48253. 75define i1 @test_48253_eq_ne(i8 %a, i8 %b) { 76; CHECK-LABEL: @test_48253_eq_ne( 77; CHECK-NEXT: entry: 78; CHECK-NEXT: [[CMP_1:%.*]] = icmp ne i8 [[A:%.*]], [[B:%.*]] 79; CHECK-NEXT: [[CMP_2:%.*]] = icmp eq i8 [[B]], 0 80; CHECK-NEXT: [[OR:%.*]] = or i1 [[CMP_1]], [[CMP_2]] 81; CHECK-NEXT: br i1 [[OR]], label [[EXIT_1:%.*]], label [[IF_END:%.*]] 82; CHECK: if.end: 83; CHECK-NEXT: [[SUB_1:%.*]] = add i8 [[B]], -1 84; CHECK-NEXT: [[SUB_2:%.*]] = add i8 [[B]], -2 85; CHECK-NEXT: [[C_2:%.*]] = icmp ult i8 [[SUB_2]], [[A]] 86; CHECK-NEXT: [[XOR_1:%.*]] = xor i1 true, [[C_2]] 87; CHECK-NEXT: ret i1 [[XOR_1]] 88; CHECK: exit.1: 89; CHECK-NEXT: [[SUB_3:%.*]] = add i8 [[B]], -1 90; CHECK-NEXT: [[C_3:%.*]] = icmp ult i8 [[SUB_3]], [[A]] 91; CHECK-NEXT: [[SUB_4:%.*]] = add i8 [[B]], -2 92; CHECK-NEXT: [[C_4:%.*]] = icmp ult i8 [[SUB_4]], [[A]] 93; CHECK-NEXT: [[XOR_2:%.*]] = xor i1 [[C_3]], [[C_4]] 94; CHECK-NEXT: ret i1 [[XOR_2]] 95; 96entry: 97 %cmp.1 = icmp ne i8 %a, %b 98 %cmp.2 = icmp eq i8 %b, 0 99 %or = or i1 %cmp.1, %cmp.2 100 br i1 %or, label %exit.1, label %if.end 101 102if.end: 103 %sub.1 = add i8 %b, -1 104 %t.1 = icmp ult i8 %sub.1, %a 105 %sub.2 = add i8 %b, -2 106 %c.2 = icmp ult i8 %sub.2, %a 107 %xor.1 = xor i1 %t.1, %c.2 108 ret i1 %xor.1 109 110exit.1: 111 %sub.3 = add i8 %b, -1 112 %c.3 = icmp ult i8 %sub.3, %a 113 %sub.4 = add i8 %b, -2 114 %c.4 = icmp ult i8 %sub.4, %a 115 %xor.2 = xor i1 %c.3, %c.4 116 ret i1 %xor.2 117} 118 119define i1 @test_ult(i8 %a, i8 %b) { 120; CHECK-LABEL: @test_ult( 121; CHECK-NEXT: entry: 122; CHECK-NEXT: [[CMP_1:%.*]] = icmp uge i8 [[A:%.*]], 20 123; CHECK-NEXT: [[CMP_2:%.*]] = icmp ult i8 [[A]], [[B:%.*]] 124; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP_1]], [[CMP_2]] 125; CHECK-NEXT: [[SUB_1:%.*]] = add i8 [[A]], -1 126; CHECK-NEXT: [[SUB_2:%.*]] = add i8 [[A]], -2 127; CHECK-NEXT: [[SUB_3:%.*]] = add i8 [[A]], -20 128; CHECK-NEXT: [[SUB_4:%.*]] = add i8 [[A]], 21 129; CHECK-NEXT: [[ADD_1:%.*]] = add i8 [[A]], 1 130; CHECK-NEXT: br i1 [[AND]], label [[IF_END:%.*]], label [[EXIT_1:%.*]] 131; CHECK: if.end: 132; CHECK-NEXT: [[XOR_1:%.*]] = xor i1 true, true 133; CHECK-NEXT: [[XOR_2:%.*]] = xor i1 [[XOR_1]], true 134; CHECK-NEXT: [[C_1:%.*]] = icmp ult i8 [[SUB_4]], [[B]] 135; CHECK-NEXT: [[XOR_3:%.*]] = xor i1 [[XOR_2]], [[C_1]] 136; CHECK-NEXT: [[C_2:%.*]] = icmp ult i8 [[ADD_1]], [[B]] 137; CHECK-NEXT: [[XOR_4:%.*]] = xor i1 [[XOR_3]], [[C_2]] 138; CHECK-NEXT: ret i1 [[XOR_4]] 139; CHECK: exit.1: 140; CHECK-NEXT: [[C_3:%.*]] = icmp ult i8 [[SUB_1]], [[B]] 141; CHECK-NEXT: [[C_4:%.*]] = icmp ult i8 [[SUB_2]], [[B]] 142; CHECK-NEXT: [[XOR_5:%.*]] = xor i1 [[C_3]], [[C_4]] 143; CHECK-NEXT: [[C_5:%.*]] = icmp ult i8 [[SUB_3]], [[B]] 144; CHECK-NEXT: [[XOR_6:%.*]] = xor i1 [[XOR_5]], [[C_5]] 145; CHECK-NEXT: [[C_6:%.*]] = icmp ult i8 [[SUB_4]], [[B]] 146; CHECK-NEXT: [[XOR_7:%.*]] = xor i1 [[XOR_6]], [[C_6]] 147; CHECK-NEXT: [[C_7:%.*]] = icmp ult i8 [[ADD_1]], [[B]] 148; CHECK-NEXT: [[XOR_8:%.*]] = xor i1 [[XOR_7]], [[C_7]] 149; CHECK-NEXT: ret i1 [[XOR_8]] 150; 151entry: 152 %cmp.1 = icmp uge i8 %a, 20 153 %cmp.2 = icmp ult i8 %a, %b 154 %and = and i1 %cmp.1, %cmp.2 155 %sub.1 = add i8 %a, -1 156 %sub.2 = add i8 %a, -2 157 %sub.3 = add i8 %a, -20 158 %sub.4 = add i8 %a, 21 159 %add.1 = add i8 %a, 1 160 br i1 %and, label %if.end, label %exit.1 161 162if.end: 163 %t.1 = icmp ult i8 %sub.1, %b 164 %t.2 = icmp ult i8 %sub.2, %b 165 %xor.1 = xor i1 %t.1, %t.2 166 167 %t.3 = icmp ult i8 %sub.3, %b 168 %xor.2 = xor i1 %xor.1, %t.3 169 170 %c.1 = icmp ult i8 %sub.4, %b 171 %xor.3 = xor i1 %xor.2, %c.1 172 173 %c.2 = icmp ult i8 %add.1, %b 174 %xor.4 = xor i1 %xor.3, %c.2 175 ret i1 %xor.4 176 177exit.1: 178 %c.3 = icmp ult i8 %sub.1, %b 179 %c.4 = icmp ult i8 %sub.2, %b 180 %xor.5 = xor i1 %c.3, %c.4 181 182 %c.5 = icmp ult i8 %sub.3, %b 183 %xor.6 = xor i1 %xor.5, %c.5 184 185 %c.6 = icmp ult i8 %sub.4, %b 186 %xor.7 = xor i1 %xor.6, %c.6 187 188 %c.7 = icmp ult i8 %add.1, %b 189 %xor.8 = xor i1 %xor.7, %c.7 190 ret i1 %xor.8 191} 192 193define i1 @test_slt(i8 %a, i8 %b) { 194; CHECK-LABEL: @test_slt( 195; CHECK-NEXT: entry: 196; CHECK-NEXT: [[CMP_1:%.*]] = icmp sge i8 [[A:%.*]], 20 197; CHECK-NEXT: [[CMP_2:%.*]] = icmp slt i8 [[A]], [[B:%.*]] 198; CHECK-NEXT: [[AND:%.*]] = and i1 [[CMP_1]], [[CMP_2]] 199; CHECK-NEXT: [[SUB_1:%.*]] = add i8 [[A]], -1 200; CHECK-NEXT: [[SUB_2:%.*]] = add i8 [[A]], -2 201; CHECK-NEXT: [[SUB_3:%.*]] = add i8 [[A]], -20 202; CHECK-NEXT: [[SUB_4:%.*]] = add i8 [[A]], 21 203; CHECK-NEXT: [[ADD_1:%.*]] = add i8 [[A]], 1 204; CHECK-NEXT: br i1 [[AND]], label [[IF_END:%.*]], label [[EXIT_1:%.*]] 205; CHECK: if.end: 206; CHECK-NEXT: [[T_1:%.*]] = icmp slt i8 [[SUB_1]], [[B]] 207; CHECK-NEXT: [[T_2:%.*]] = icmp slt i8 [[SUB_2]], [[B]] 208; CHECK-NEXT: [[XOR_1:%.*]] = xor i1 [[T_1]], [[T_2]] 209; CHECK-NEXT: [[T_3:%.*]] = icmp slt i8 [[SUB_3]], [[B]] 210; CHECK-NEXT: [[XOR_2:%.*]] = xor i1 [[XOR_1]], [[T_3]] 211; CHECK-NEXT: [[C_1:%.*]] = icmp slt i8 [[SUB_4]], [[B]] 212; CHECK-NEXT: [[XOR_3:%.*]] = xor i1 [[XOR_2]], [[C_1]] 213; CHECK-NEXT: [[C_2:%.*]] = icmp slt i8 [[ADD_1]], [[B]] 214; CHECK-NEXT: [[XOR_4:%.*]] = xor i1 [[XOR_3]], [[C_2]] 215; CHECK-NEXT: ret i1 [[XOR_4]] 216; CHECK: exit.1: 217; CHECK-NEXT: [[C_3:%.*]] = icmp slt i8 [[SUB_1]], [[B]] 218; CHECK-NEXT: [[C_4:%.*]] = icmp slt i8 [[SUB_2]], [[B]] 219; CHECK-NEXT: [[XOR_5:%.*]] = xor i1 [[C_3]], [[C_4]] 220; CHECK-NEXT: [[C_5:%.*]] = icmp slt i8 [[SUB_3]], [[B]] 221; CHECK-NEXT: [[XOR_6:%.*]] = xor i1 [[XOR_5]], [[C_5]] 222; CHECK-NEXT: [[C_6:%.*]] = icmp slt i8 [[SUB_4]], [[B]] 223; CHECK-NEXT: [[XOR_7:%.*]] = xor i1 [[XOR_6]], [[C_6]] 224; CHECK-NEXT: [[C_7:%.*]] = icmp slt i8 [[ADD_1]], [[B]] 225; CHECK-NEXT: [[XOR_8:%.*]] = xor i1 [[XOR_7]], [[C_7]] 226; CHECK-NEXT: ret i1 [[XOR_8]] 227; 228entry: 229 %cmp.1 = icmp sge i8 %a, 20 230 %cmp.2 = icmp slt i8 %a, %b 231 %and = and i1 %cmp.1, %cmp.2 232 %sub.1 = add i8 %a, -1 233 %sub.2 = add i8 %a, -2 234 %sub.3 = add i8 %a, -20 235 %sub.4 = add i8 %a, 21 236 %add.1 = add i8 %a, 1 237 br i1 %and, label %if.end, label %exit.1 238 239if.end: 240 %t.1 = icmp slt i8 %sub.1, %b 241 %t.2 = icmp slt i8 %sub.2, %b 242 %xor.1 = xor i1 %t.1, %t.2 243 244 %t.3 = icmp slt i8 %sub.3, %b 245 %xor.2 = xor i1 %xor.1, %t.3 246 247 %c.1 = icmp slt i8 %sub.4, %b 248 %xor.3 = xor i1 %xor.2, %c.1 249 250 %c.2 = icmp slt i8 %add.1, %b 251 %xor.4 = xor i1 %xor.3, %c.2 252 ret i1 %xor.4 253 254exit.1: 255 %c.3 = icmp slt i8 %sub.1, %b 256 %c.4 = icmp slt i8 %sub.2, %b 257 %xor.5 = xor i1 %c.3, %c.4 258 259 %c.5 = icmp slt i8 %sub.3, %b 260 %xor.6 = xor i1 %xor.5, %c.5 261 262 %c.6 = icmp slt i8 %sub.4, %b 263 %xor.7 = xor i1 %xor.6, %c.6 264 265 %c.7 = icmp slt i8 %add.1, %b 266 %xor.8 = xor i1 %xor.7, %c.7 267 ret i1 %xor.8 268} 269 270define i1 @wrapping_add_known_1_add_nuw(i8 %a) { 271; CHECK-LABEL: @wrapping_add_known_1_add_nuw( 272; CHECK-NEXT: entry: 273; CHECK-NEXT: [[PRE:%.*]] = icmp eq i8 [[A:%.*]], 1 274; CHECK-NEXT: call void @llvm.assume(i1 [[PRE]]) 275; CHECK-NEXT: [[SUB_1:%.*]] = add i8 [[A]], -1 276; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[SUB_1]], 10 277; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true 278; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], false 279; CHECK-NEXT: ret i1 [[RES_2]] 280; 281entry: 282 %pre = icmp eq i8 %a, 1 283 call void @llvm.assume(i1 %pre) 284 %sub.1 = add i8 %a, -1 285 %add = add nuw i8 %sub.1, 10 286 %t.1 = icmp uge i8 %add, 10 287 %t.2 = icmp ule i8 %add, 10 288 %res.1 = xor i1 %t.1, %t.2 289 %f.1 = icmp ult i8 %add, 10 290 %res.2 = xor i1 %res.1, %f.1 291 ret i1 %res.2 292} 293 294define i1 @add_nuw_wrapping_add_known_1(i8 %a) { 295; CHECK-LABEL: @add_nuw_wrapping_add_known_1( 296; CHECK-NEXT: entry: 297; CHECK-NEXT: [[PRE:%.*]] = icmp eq i8 [[A:%.*]], 1 298; CHECK-NEXT: call void @llvm.assume(i1 [[PRE]]) 299; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[A]], 10 300; CHECK-NEXT: [[SUB_1:%.*]] = add i8 [[ADD]], -1 301; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true 302; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], false 303; CHECK-NEXT: ret i1 [[RES_2]] 304; 305entry: 306 %pre = icmp eq i8 %a, 1 307 call void @llvm.assume(i1 %pre) 308 %add = add nuw i8 %a, 10 309 %sub.1 = add i8 %add, -1 310 %t.1 = icmp uge i8 %sub.1, 10 311 %t.2 = icmp ule i8 %sub.1, 10 312 %res.1 = xor i1 %t.1, %t.2 313 %f.1 = icmp ult i8 %sub.1, 10 314 %res.2 = xor i1 %res.1, %f.1 315 ret i1 %res.2 316} 317 318define i1 @add_nuw_wrapping_add_not_known_1(i8 %a) { 319; CHECK-LABEL: @add_nuw_wrapping_add_not_known_1( 320; CHECK-NEXT: entry: 321; CHECK-NEXT: [[PRE:%.*]] = icmp sge i8 [[A:%.*]], -1 322; CHECK-NEXT: call void @llvm.assume(i1 [[PRE]]) 323; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[A]], 10 324; CHECK-NEXT: [[SUB_1:%.*]] = add i8 [[ADD]], -1 325; CHECK-NEXT: [[T_1:%.*]] = icmp uge i8 [[SUB_1]], 10 326; CHECK-NEXT: [[T_2:%.*]] = icmp ule i8 [[SUB_1]], 10 327; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[T_1]], [[T_2]] 328; CHECK-NEXT: [[F_1:%.*]] = icmp ult i8 [[SUB_1]], 10 329; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], [[F_1]] 330; CHECK-NEXT: ret i1 [[RES_2]] 331; 332entry: 333 %pre = icmp sge i8 %a, -1 334 call void @llvm.assume(i1 %pre) 335 %add = add nuw i8 %a, 10 336 %sub.1 = add i8 %add, -1 337 %t.1 = icmp uge i8 %sub.1, 10 338 %t.2 = icmp ule i8 %sub.1, 10 339 %res.1 = xor i1 %t.1, %t.2 340 %f.1 = icmp ult i8 %sub.1, 10 341 %res.2 = xor i1 %res.1, %f.1 342 ret i1 %res.2 343} 344 345declare void @llvm.assume(i1) 346