1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 2; RUN: opt -passes=instsimplify -S %s | FileCheck %s 3 4define i1 @incr_sle(i32 %i, i32 %len) { 5; CHECK-LABEL: define i1 @incr_sle( 6; CHECK-SAME: i32 [[I:%.*]], i32 [[LEN:%.*]]) { 7; CHECK-NEXT: ret i1 true 8; 9 %i.incr = add nsw nuw i32 %i, 1 10 %i.gt.len = icmp samesign ugt i32 %i, %len 11 %i.incr.sgt.len = icmp sgt i32 %i.incr, %len 12 %res = icmp sle i1 %i.incr.sgt.len, %i.gt.len 13 ret i1 %res 14} 15 16define i1 @incr_sle_no_nsw_nuw(i32 %i, i32 %len) { 17; CHECK-LABEL: define i1 @incr_sle_no_nsw_nuw( 18; CHECK-SAME: i32 [[I:%.*]], i32 [[LEN:%.*]]) { 19; CHECK-NEXT: [[I_INCR:%.*]] = add i32 [[I]], 1 20; CHECK-NEXT: [[I_GT_LEN:%.*]] = icmp samesign ugt i32 [[I]], [[LEN]] 21; CHECK-NEXT: [[I_INCR_SGT_LEN:%.*]] = icmp sgt i32 [[I_INCR]], [[LEN]] 22; CHECK-NEXT: [[RES:%.*]] = icmp sle i1 [[I_INCR_SGT_LEN]], [[I_GT_LEN]] 23; CHECK-NEXT: ret i1 [[RES]] 24; 25 %i.incr = add i32 %i, 1 26 %i.gt.len = icmp samesign ugt i32 %i, %len 27 %i.incr.sgt.len = icmp sgt i32 %i.incr, %len 28 %res = icmp sle i1 %i.incr.sgt.len, %i.gt.len 29 ret i1 %res 30} 31 32define i1 @incr_sge(i32 %i, i32 %len) { 33; CHECK-LABEL: define i1 @incr_sge( 34; CHECK-SAME: i32 [[I:%.*]], i32 [[LEN:%.*]]) { 35; CHECK-NEXT: ret i1 true 36; 37 %i.incr = add nsw nuw i32 %i, 1 38 %i.lt.len = icmp samesign ult i32 %i, %len 39 %i.incr.slt.len = icmp slt i32 %i.incr, %len 40 %res = icmp sge i1 %i.incr.slt.len, %i.lt.len 41 ret i1 %res 42} 43 44define i1 @incr_sge_no_nsw_nuw(i32 %i, i32 %len) { 45; CHECK-LABEL: define i1 @incr_sge_no_nsw_nuw( 46; CHECK-SAME: i32 [[I:%.*]], i32 [[LEN:%.*]]) { 47; CHECK-NEXT: [[I_INCR:%.*]] = add i32 [[I]], 1 48; CHECK-NEXT: [[I_LT_LEN:%.*]] = icmp samesign ult i32 [[I]], [[LEN]] 49; CHECK-NEXT: [[I_INCR_SLT_LEN:%.*]] = icmp slt i32 [[I_INCR]], [[LEN]] 50; CHECK-NEXT: [[RES:%.*]] = icmp sge i1 [[I_INCR_SLT_LEN]], [[I_LT_LEN]] 51; CHECK-NEXT: ret i1 [[RES]] 52; 53 %i.incr = add i32 %i, 1 54 %i.lt.len = icmp samesign ult i32 %i, %len 55 %i.incr.slt.len = icmp slt i32 %i.incr, %len 56 %res = icmp sge i1 %i.incr.slt.len, %i.lt.len 57 ret i1 %res 58} 59 60define i1 @incr_ule(i32 %i, i32 %len) { 61; CHECK-LABEL: define i1 @incr_ule( 62; CHECK-SAME: i32 [[I:%.*]], i32 [[LEN:%.*]]) { 63; CHECK-NEXT: ret i1 true 64; 65 %i.incr = add nsw nuw i32 %i, 1 66 %i.gt.len = icmp samesign ugt i32 %i, %len 67 %i.incr.sgt.len = icmp sgt i32 %i.incr, %len 68 %res = icmp ule i1 %i.gt.len, %i.incr.sgt.len 69 ret i1 %res 70} 71 72define i1 @incr_ule_no_nsw_nuw(i32 %i, i32 %len) { 73; CHECK-LABEL: define i1 @incr_ule_no_nsw_nuw( 74; CHECK-SAME: i32 [[I:%.*]], i32 [[LEN:%.*]]) { 75; CHECK-NEXT: [[I_INCR:%.*]] = add i32 [[I]], 1 76; CHECK-NEXT: [[I_GT_LEN:%.*]] = icmp samesign ugt i32 [[I]], [[LEN]] 77; CHECK-NEXT: [[I_INCR_SGT_LEN:%.*]] = icmp sgt i32 [[I_INCR]], [[LEN]] 78; CHECK-NEXT: [[RES:%.*]] = icmp ule i1 [[I_GT_LEN]], [[I_INCR_SGT_LEN]] 79; CHECK-NEXT: ret i1 [[RES]] 80; 81 %i.incr = add i32 %i, 1 82 %i.gt.len = icmp samesign ugt i32 %i, %len 83 %i.incr.sgt.len = icmp sgt i32 %i.incr, %len 84 %res = icmp ule i1 %i.gt.len, %i.incr.sgt.len 85 ret i1 %res 86} 87 88define i1 @incr_uge(i32 %i, i32 %len) { 89; CHECK-LABEL: define i1 @incr_uge( 90; CHECK-SAME: i32 [[I:%.*]], i32 [[LEN:%.*]]) { 91; CHECK-NEXT: ret i1 true 92; 93 %i.incr = add nsw nuw i32 %i, 1 94 %i.lt.len = icmp samesign ult i32 %i, %len 95 %i.incr.slt.len = icmp slt i32 %i.incr, %len 96 %res = icmp uge i1 %i.lt.len, %i.incr.slt.len 97 ret i1 %res 98} 99 100define i1 @incr_uge_no_nsw_nuw(i32 %i, i32 %len) { 101; CHECK-LABEL: define i1 @incr_uge_no_nsw_nuw( 102; CHECK-SAME: i32 [[I:%.*]], i32 [[LEN:%.*]]) { 103; CHECK-NEXT: [[I_INCR:%.*]] = add i32 [[I]], 1 104; CHECK-NEXT: [[I_LT_LEN:%.*]] = icmp samesign ult i32 [[I]], [[LEN]] 105; CHECK-NEXT: [[I_INCR_SLT_LEN:%.*]] = icmp slt i32 [[I_INCR]], [[LEN]] 106; CHECK-NEXT: [[RES:%.*]] = icmp uge i1 [[I_LT_LEN]], [[I_INCR_SLT_LEN]] 107; CHECK-NEXT: ret i1 [[RES]] 108; 109 %i.incr = add i32 %i, 1 110 %i.lt.len = icmp samesign ult i32 %i, %len 111 %i.incr.slt.len = icmp slt i32 %i.incr, %len 112 %res = icmp uge i1 %i.lt.len, %i.incr.slt.len 113 ret i1 %res 114} 115 116define i1 @sgt_implies_ge_via_assume(i32 %i, i32 %j) { 117; CHECK-LABEL: define i1 @sgt_implies_ge_via_assume( 118; CHECK-SAME: i32 [[I:%.*]], i32 [[J:%.*]]) { 119; CHECK-NEXT: [[I_SGT_J:%.*]] = icmp sgt i32 [[I]], [[J]] 120; CHECK-NEXT: call void @llvm.assume(i1 [[I_SGT_J]]) 121; CHECK-NEXT: ret i1 true 122; 123 %i.sgt.j = icmp sgt i32 %i, %j 124 call void @llvm.assume(i1 %i.sgt.j) 125 %i.ge.j = icmp samesign uge i32 %i, %j 126 ret i1 %i.ge.j 127} 128 129define i1 @sgt_implies_false_le_via_assume(i32 %i, i32 %j) { 130; CHECK-LABEL: define i1 @sgt_implies_false_le_via_assume( 131; CHECK-SAME: i32 [[I:%.*]], i32 [[J:%.*]]) { 132; CHECK-NEXT: [[I_SGT_J:%.*]] = icmp sgt i32 [[I]], [[J]] 133; CHECK-NEXT: call void @llvm.assume(i1 [[I_SGT_J]]) 134; CHECK-NEXT: ret i1 false 135; 136 %i.sgt.j = icmp sgt i32 %i, %j 137 call void @llvm.assume(i1 %i.sgt.j) 138 %i.le.j = icmp samesign ule i32 %i, %j 139 ret i1 %i.le.j 140} 141 142define i32 @gt_implies_sge_dominating(i32 %a, i32 %len) { 143; CHECK-LABEL: define i32 @gt_implies_sge_dominating( 144; CHECK-SAME: i32 [[A:%.*]], i32 [[LEN:%.*]]) { 145; CHECK-NEXT: [[ENTRY:.*:]] 146; CHECK-NEXT: [[A_GT_LEN:%.*]] = icmp samesign ugt i32 [[A]], [[LEN]] 147; CHECK-NEXT: br i1 [[A_GT_LEN]], label %[[TAKEN:.*]], label %[[END:.*]] 148; CHECK: [[TAKEN]]: 149; CHECK-NEXT: ret i32 30 150; CHECK: [[END]]: 151; CHECK-NEXT: ret i32 -1 152; 153entry: 154 %a.gt.len = icmp samesign ugt i32 %a, %len 155 br i1 %a.gt.len, label %taken, label %end 156 157taken: 158 %a.sge.len = icmp sge i32 %a, %len 159 %res = select i1 %a.sge.len, i32 30, i32 0 160 ret i32 %res 161 162end: 163 ret i32 -1 164} 165 166define i32 @gt_implies_false_sle_dominating(i32 %a, i32 %len) { 167; CHECK-LABEL: define i32 @gt_implies_false_sle_dominating( 168; CHECK-SAME: i32 [[A:%.*]], i32 [[LEN:%.*]]) { 169; CHECK-NEXT: [[ENTRY:.*:]] 170; CHECK-NEXT: [[A_GT_LEN:%.*]] = icmp samesign ugt i32 [[A]], [[LEN]] 171; CHECK-NEXT: br i1 [[A_GT_LEN]], label %[[TAKEN:.*]], label %[[END:.*]] 172; CHECK: [[TAKEN]]: 173; CHECK-NEXT: ret i32 0 174; CHECK: [[END]]: 175; CHECK-NEXT: ret i32 -1 176; 177entry: 178 %a.gt.len = icmp samesign ugt i32 %a, %len 179 br i1 %a.gt.len, label %taken, label %end 180 181taken: 182 %a.sle.len = icmp sle i32 %a, %len 183 %res = select i1 %a.sle.len, i32 30, i32 0 184 ret i32 %res 185 186end: 187 ret i32 -1 188} 189 190define i32 @gt_implies_sge_dominating_cr(i32 %a, i32 %len) { 191; CHECK-LABEL: define i32 @gt_implies_sge_dominating_cr( 192; CHECK-SAME: i32 [[A:%.*]], i32 [[LEN:%.*]]) { 193; CHECK-NEXT: [[ENTRY:.*:]] 194; CHECK-NEXT: [[A_GT_20:%.*]] = icmp samesign ugt i32 [[A]], 20 195; CHECK-NEXT: br i1 [[A_GT_20]], label %[[TAKEN:.*]], label %[[END:.*]] 196; CHECK: [[TAKEN]]: 197; CHECK-NEXT: ret i32 30 198; CHECK: [[END]]: 199; CHECK-NEXT: ret i32 -1 200; 201entry: 202 %a.gt.20 = icmp samesign ugt i32 %a, 20 203 br i1 %a.gt.20, label %taken, label %end 204 205taken: 206 %a.sge.10 = icmp sge i32 %a, 10 207 %res = select i1 %a.sge.10, i32 30, i32 0 208 ret i32 %res 209 210end: 211 ret i32 -1 212} 213 214define i32 @sgt_implies_ge_dominating_cr(i32 %a, i32 %len) { 215; CHECK-LABEL: define i32 @sgt_implies_ge_dominating_cr( 216; CHECK-SAME: i32 [[A:%.*]], i32 [[LEN:%.*]]) { 217; CHECK-NEXT: [[ENTRY:.*:]] 218; CHECK-NEXT: [[A_SGT_MINUS_10:%.*]] = icmp sgt i32 [[A]], -10 219; CHECK-NEXT: br i1 [[A_SGT_MINUS_10]], label %[[TAKEN:.*]], label %[[END:.*]] 220; CHECK: [[TAKEN]]: 221; CHECK-NEXT: ret i32 30 222; CHECK: [[END]]: 223; CHECK-NEXT: ret i32 -1 224; 225entry: 226 %a.sgt.minus.10 = icmp sgt i32 %a, -10 227 br i1 %a.sgt.minus.10, label %taken, label %end 228 229taken: 230 %a.ge.minus.20 = icmp samesign uge i32 %a, -20 231 %res = select i1 %a.ge.minus.20, i32 30, i32 0 232 ret i32 %res 233 234end: 235 ret i32 -1 236} 237 238define i32 @gt_sub_nsw(i32 %x, i32 %y) { 239; CHECK-LABEL: define i32 @gt_sub_nsw( 240; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 241; CHECK-NEXT: [[ENTRY:.*:]] 242; CHECK-NEXT: [[X_GT_Y:%.*]] = icmp samesign ugt i32 [[X]], [[Y]] 243; CHECK-NEXT: br i1 [[X_GT_Y]], label %[[TAKEN:.*]], label %[[END:.*]] 244; CHECK: [[TAKEN]]: 245; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[X]], [[Y]] 246; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[SUB]], 1 247; CHECK-NEXT: ret i32 [[ADD]] 248; CHECK: [[END]]: 249; CHECK-NEXT: ret i32 0 250; 251entry: 252 %x.gt.y = icmp samesign ugt i32 %x, %y 253 br i1 %x.gt.y, label %taken, label %end 254 255taken: 256 %sub = sub nsw i32 %x, %y 257 %add = add nsw i32 %sub, 1 258 %neg = xor i32 %sub, -1 259 %abscond = icmp samesign ult i32 %sub, -1 260 %abs = select i1 %abscond, i32 %neg, i32 %add 261 ret i32 %abs 262 263end: 264 ret i32 0 265} 266 267define i32 @ge_sub_nsw(i32 %x, i32 %y) { 268; CHECK-LABEL: define i32 @ge_sub_nsw( 269; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) { 270; CHECK-NEXT: [[ENTRY:.*:]] 271; CHECK-NEXT: [[X_GE_Y:%.*]] = icmp samesign uge i32 [[X]], [[Y]] 272; CHECK-NEXT: br i1 [[X_GE_Y]], label %[[TAKEN:.*]], label %[[END:.*]] 273; CHECK: [[TAKEN]]: 274; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[X]], [[Y]] 275; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[SUB]], 1 276; CHECK-NEXT: ret i32 [[ADD]] 277; CHECK: [[END]]: 278; CHECK-NEXT: ret i32 0 279; 280entry: 281 %x.ge.y = icmp samesign uge i32 %x, %y 282 br i1 %x.ge.y, label %taken, label %end 283 284taken: 285 %sub = sub nsw i32 %x, %y 286 %add = add nsw i32 %sub, 1 287 %neg = xor i32 %sub, -1 288 %abscond = icmp samesign ult i32 %sub, -1 289 %abs = select i1 %abscond, i32 %neg, i32 %add 290 ret i32 %abs 291 292end: 293 ret i32 0 294} 295 296define i1 @gt_sub_nsw_ult(i8 %L0, i8 %L1, i1 %V) { 297; CHECK-LABEL: define i1 @gt_sub_nsw_ult( 298; CHECK-SAME: i8 [[L0:%.*]], i8 [[L1:%.*]], i1 [[V:%.*]]) { 299; CHECK-NEXT: [[LHS:%.*]] = icmp samesign ugt i8 [[L0]], [[L1]] 300; CHECK-NEXT: br i1 [[LHS]], label %[[LHS_TRUE:.*]], label %[[LHS_FALSE:.*]] 301; CHECK: [[LHS_TRUE]]: 302; CHECK-NEXT: [[R0:%.*]] = sub nsw i8 [[L0]], [[L1]] 303; CHECK-NEXT: [[RHS:%.*]] = icmp ult i8 [[R0]], -1 304; CHECK-NEXT: ret i1 [[RHS]] 305; CHECK: [[LHS_FALSE]]: 306; CHECK-NEXT: ret i1 [[V]] 307; 308 %LHS = icmp samesign ugt i8 %L0, %L1 309 br i1 %LHS, label %LHS_true, label %LHS_false 310 311LHS_true: 312 %R0 = sub nsw i8 %L0, %L1 313 %RHS = icmp ult i8 %R0, -1 314 ret i1 %RHS 315 316LHS_false: 317 ret i1 %V 318} 319 320define i1 @lt_sub_nsw_ult(i8 %L0, i8 %L1, i1 %V) { 321; CHECK-LABEL: define i1 @lt_sub_nsw_ult( 322; CHECK-SAME: i8 [[L0:%.*]], i8 [[L1:%.*]], i1 [[V:%.*]]) { 323; CHECK-NEXT: [[LHS:%.*]] = icmp samesign ult i8 [[L0]], [[L1]] 324; CHECK-NEXT: br i1 [[LHS]], label %[[LHS_TRUE:.*]], label %[[LHS_FALSE:.*]] 325; CHECK: [[LHS_TRUE]]: 326; CHECK-NEXT: [[R0:%.*]] = sub nsw i8 [[L0]], [[L1]] 327; CHECK-NEXT: [[RHS:%.*]] = icmp ult i8 [[R0]], 1 328; CHECK-NEXT: ret i1 [[RHS]] 329; CHECK: [[LHS_FALSE]]: 330; CHECK-NEXT: ret i1 [[V]] 331; 332 %LHS = icmp samesign ult i8 %L0, %L1 333 br i1 %LHS, label %LHS_true, label %LHS_false 334 335LHS_true: 336 %R0 = sub nsw i8 %L0, %L1 337 %RHS = icmp ult i8 %R0, 1 338 ret i1 %RHS 339 340LHS_false: 341 ret i1 %V 342} 343