473 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=aggressive-instcombine -S | FileCheck %s3 4; https://bugs.llvm.org/show_bug.cgi?id=349245 6define i32 @rotl(i32 %a, i32 %b) {7; CHECK-LABEL: @rotl(8; CHECK-NEXT: entry:9; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[B:%.*]], 010; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[ROTBB:%.*]]11; CHECK: rotbb:12; CHECK-NEXT: br label [[END]]13; CHECK: end:14; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.fshl.i32(i32 [[A:%.*]], i32 [[A]], i32 [[B]])15; CHECK-NEXT: ret i32 [[TMP0]]16;17entry:18 %cmp = icmp eq i32 %b, 019 br i1 %cmp, label %end, label %rotbb20 21rotbb:22 %sub = sub i32 32, %b23 %shr = lshr i32 %a, %sub24 %shl = shl i32 %a, %b25 %or = or i32 %shr, %shl26 br label %end27 28end:29 %cond = phi i32 [ %or, %rotbb ], [ %a, %entry ]30 ret i32 %cond31}32 33define i32 @rotl_commute_phi(i32 %a, i32 %b) {34; CHECK-LABEL: @rotl_commute_phi(35; CHECK-NEXT: entry:36; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[B:%.*]], 037; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[ROTBB:%.*]]38; CHECK: rotbb:39; CHECK-NEXT: br label [[END]]40; CHECK: end:41; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.fshl.i32(i32 [[A:%.*]], i32 [[A]], i32 [[B]])42; CHECK-NEXT: ret i32 [[TMP0]]43;44entry:45 %cmp = icmp eq i32 %b, 046 br i1 %cmp, label %end, label %rotbb47 48rotbb:49 %sub = sub i32 32, %b50 %shr = lshr i32 %a, %sub51 %shl = shl i32 %a, %b52 %or = or i32 %shr, %shl53 br label %end54 55end:56 %cond = phi i32 [ %a, %entry ], [ %or, %rotbb ]57 ret i32 %cond58}59 60define i32 @rotl_commute_or(i32 %a, i32 %b) {61; CHECK-LABEL: @rotl_commute_or(62; CHECK-NEXT: entry:63; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[B:%.*]], 064; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[ROTBB:%.*]]65; CHECK: rotbb:66; CHECK-NEXT: br label [[END]]67; CHECK: end:68; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.fshl.i32(i32 [[A:%.*]], i32 [[A]], i32 [[B]])69; CHECK-NEXT: ret i32 [[TMP0]]70;71entry:72 %cmp = icmp eq i32 %b, 073 br i1 %cmp, label %end, label %rotbb74 75rotbb:76 %sub = sub i32 32, %b77 %shr = lshr i32 %a, %sub78 %shl = shl i32 %a, %b79 %or = or i32 %shl, %shr80 br label %end81 82end:83 %cond = phi i32 [ %a, %entry ], [ %or, %rotbb ]84 ret i32 %cond85}86 87; Verify that the intrinsic is inserted into a valid position.88 89define i32 @rotl_insert_valid_location(i32 %a, i32 %b) {90; CHECK-LABEL: @rotl_insert_valid_location(91; CHECK-NEXT: entry:92; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[B:%.*]], 093; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[ROTBB:%.*]]94; CHECK: rotbb:95; CHECK-NEXT: br label [[END]]96; CHECK: end:97; CHECK-NEXT: [[OTHER:%.*]] = phi i32 [ 1, [[ROTBB]] ], [ 2, [[ENTRY:%.*]] ]98; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.fshl.i32(i32 [[A:%.*]], i32 [[A]], i32 [[B]])99; CHECK-NEXT: [[RES:%.*]] = or i32 [[TMP0]], [[OTHER]]100; CHECK-NEXT: ret i32 [[RES]]101;102entry:103 %cmp = icmp eq i32 %b, 0104 br i1 %cmp, label %end, label %rotbb105 106rotbb:107 %sub = sub i32 32, %b108 %shr = lshr i32 %a, %sub109 %shl = shl i32 %a, %b110 %or = or i32 %shr, %shl111 br label %end112 113end:114 %cond = phi i32 [ %or, %rotbb ], [ %a, %entry ]115 %other = phi i32 [ 1, %rotbb ], [ 2, %entry ]116 %res = or i32 %cond, %other117 ret i32 %res118}119 120define i32 @rotr(i32 %a, i32 %b) {121; CHECK-LABEL: @rotr(122; CHECK-NEXT: entry:123; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[B:%.*]], 0124; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[ROTBB:%.*]]125; CHECK: rotbb:126; CHECK-NEXT: br label [[END]]127; CHECK: end:128; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.fshr.i32(i32 [[A:%.*]], i32 [[A]], i32 [[B]])129; CHECK-NEXT: ret i32 [[TMP0]]130;131entry:132 %cmp = icmp eq i32 %b, 0133 br i1 %cmp, label %end, label %rotbb134 135rotbb:136 %sub = sub i32 32, %b137 %shl = shl i32 %a, %sub138 %shr = lshr i32 %a, %b139 %or = or i32 %shr, %shl140 br label %end141 142end:143 %cond = phi i32 [ %or, %rotbb ], [ %a, %entry ]144 ret i32 %cond145}146 147define i32 @rotr_commute_phi(i32 %a, i32 %b) {148; CHECK-LABEL: @rotr_commute_phi(149; CHECK-NEXT: entry:150; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[B:%.*]], 0151; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[ROTBB:%.*]]152; CHECK: rotbb:153; CHECK-NEXT: br label [[END]]154; CHECK: end:155; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.fshr.i32(i32 [[A:%.*]], i32 [[A]], i32 [[B]])156; CHECK-NEXT: ret i32 [[TMP0]]157;158entry:159 %cmp = icmp eq i32 %b, 0160 br i1 %cmp, label %end, label %rotbb161 162rotbb:163 %sub = sub i32 32, %b164 %shl = shl i32 %a, %sub165 %shr = lshr i32 %a, %b166 %or = or i32 %shr, %shl167 br label %end168 169end:170 %cond = phi i32 [ %a, %entry ], [ %or, %rotbb ]171 ret i32 %cond172}173 174define i32 @rotr_commute_or(i32 %a, i32 %b) {175; CHECK-LABEL: @rotr_commute_or(176; CHECK-NEXT: entry:177; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[B:%.*]], 0178; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[ROTBB:%.*]]179; CHECK: rotbb:180; CHECK-NEXT: br label [[END]]181; CHECK: end:182; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.fshr.i32(i32 [[A:%.*]], i32 [[A]], i32 [[B]])183; CHECK-NEXT: ret i32 [[TMP0]]184;185entry:186 %cmp = icmp eq i32 %b, 0187 br i1 %cmp, label %end, label %rotbb188 189rotbb:190 %sub = sub i32 32, %b191 %shl = shl i32 %a, %sub192 %shr = lshr i32 %a, %b193 %or = or i32 %shl, %shr194 br label %end195 196end:197 %cond = phi i32 [ %a, %entry ], [ %or, %rotbb ]198 ret i32 %cond199}200 201; Negative test - non-power-of-2 might require urem expansion in the backend.202 203define i12 @could_be_rotr_weird_type(i12 %a, i12 %b) {204; CHECK-LABEL: @could_be_rotr_weird_type(205; CHECK-NEXT: entry:206; CHECK-NEXT: [[CMP:%.*]] = icmp eq i12 [[B:%.*]], 0207; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[ROTBB:%.*]]208; CHECK: rotbb:209; CHECK-NEXT: [[SUB:%.*]] = sub i12 12, [[B]]210; CHECK-NEXT: [[SHL:%.*]] = shl i12 [[A:%.*]], [[SUB]]211; CHECK-NEXT: [[SHR:%.*]] = lshr i12 [[A]], [[B]]212; CHECK-NEXT: [[OR:%.*]] = or i12 [[SHL]], [[SHR]]213; CHECK-NEXT: br label [[END]]214; CHECK: end:215; CHECK-NEXT: [[COND:%.*]] = phi i12 [ [[A]], [[ENTRY:%.*]] ], [ [[OR]], [[ROTBB]] ]216; CHECK-NEXT: ret i12 [[COND]]217;218entry:219 %cmp = icmp eq i12 %b, 0220 br i1 %cmp, label %end, label %rotbb221 222rotbb:223 %sub = sub i12 12, %b224 %shl = shl i12 %a, %sub225 %shr = lshr i12 %a, %b226 %or = or i12 %shl, %shr227 br label %end228 229end:230 %cond = phi i12 [ %a, %entry ], [ %or, %rotbb ]231 ret i12 %cond232}233 234; Negative test - wrong phi ops.235 236define i32 @not_rotr_1(i32 %a, i32 %b) {237; CHECK-LABEL: @not_rotr_1(238; CHECK-NEXT: entry:239; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[B:%.*]], 0240; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[ROTBB:%.*]]241; CHECK: rotbb:242; CHECK-NEXT: [[SUB:%.*]] = sub i32 32, [[B]]243; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[A:%.*]], [[SUB]]244; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[A]], [[B]]245; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHL]], [[SHR]]246; CHECK-NEXT: br label [[END]]247; CHECK: end:248; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[B]], [[ENTRY:%.*]] ], [ [[OR]], [[ROTBB]] ]249; CHECK-NEXT: ret i32 [[COND]]250;251entry:252 %cmp = icmp eq i32 %b, 0253 br i1 %cmp, label %end, label %rotbb254 255rotbb:256 %sub = sub i32 32, %b257 %shl = shl i32 %a, %sub258 %shr = lshr i32 %a, %b259 %or = or i32 %shl, %shr260 br label %end261 262end:263 %cond = phi i32 [ %b, %entry ], [ %or, %rotbb ]264 ret i32 %cond265}266 267; Negative test - too many phi ops.268 269define i32 @not_rotr_2(i32 %a, i32 %b, i32 %c) {270; CHECK-LABEL: @not_rotr_2(271; CHECK-NEXT: entry:272; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[B:%.*]], 0273; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[ROTBB:%.*]]274; CHECK: rotbb:275; CHECK-NEXT: [[SUB:%.*]] = sub i32 32, [[B]]276; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[A:%.*]], [[SUB]]277; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[A]], [[B]]278; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHL]], [[SHR]]279; CHECK-NEXT: [[CMP42:%.*]] = icmp ugt i32 [[OR]], 42280; CHECK-NEXT: br i1 [[CMP42]], label [[END]], label [[BOGUS:%.*]]281; CHECK: bogus:282; CHECK-NEXT: br label [[END]]283; CHECK: end:284; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[A]], [[ENTRY:%.*]] ], [ [[OR]], [[ROTBB]] ], [ [[C:%.*]], [[BOGUS]] ]285; CHECK-NEXT: ret i32 [[COND]]286;287entry:288 %cmp = icmp eq i32 %b, 0289 br i1 %cmp, label %end, label %rotbb290 291rotbb:292 %sub = sub i32 32, %b293 %shl = shl i32 %a, %sub294 %shr = lshr i32 %a, %b295 %or = or i32 %shl, %shr296 %cmp42 = icmp ugt i32 %or, 42297 br i1 %cmp42, label %end, label %bogus298 299bogus:300 br label %end301 302end:303 %cond = phi i32 [ %a, %entry ], [ %or, %rotbb ], [ %c, %bogus ]304 ret i32 %cond305}306 307; Negative test - wrong cmp (but this should match?).308 309define i32 @not_rotr_3(i32 %a, i32 %b) {310; CHECK-LABEL: @not_rotr_3(311; CHECK-NEXT: entry:312; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[B:%.*]], 0313; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[ROTBB:%.*]]314; CHECK: rotbb:315; CHECK-NEXT: [[SUB:%.*]] = sub i32 32, [[B]]316; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[A:%.*]], [[SUB]]317; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[A]], [[B]]318; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHL]], [[SHR]]319; CHECK-NEXT: br label [[END]]320; CHECK: end:321; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[A]], [[ENTRY:%.*]] ], [ [[OR]], [[ROTBB]] ]322; CHECK-NEXT: ret i32 [[COND]]323;324entry:325 %cmp = icmp sle i32 %b, 0326 br i1 %cmp, label %end, label %rotbb327 328rotbb:329 %sub = sub i32 32, %b330 %shl = shl i32 %a, %sub331 %shr = lshr i32 %a, %b332 %or = or i32 %shl, %shr333 br label %end334 335end:336 %cond = phi i32 [ %a, %entry ], [ %or, %rotbb ]337 ret i32 %cond338}339 340; Negative test - wrong shift.341 342define i32 @not_rotr_4(i32 %a, i32 %b) {343; CHECK-LABEL: @not_rotr_4(344; CHECK-NEXT: entry:345; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[B:%.*]], 0346; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[ROTBB:%.*]]347; CHECK: rotbb:348; CHECK-NEXT: [[SUB:%.*]] = sub i32 32, [[B]]349; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[A:%.*]], [[SUB]]350; CHECK-NEXT: [[SHR:%.*]] = ashr i32 [[A]], [[B]]351; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHL]], [[SHR]]352; CHECK-NEXT: br label [[END]]353; CHECK: end:354; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[A]], [[ENTRY:%.*]] ], [ [[OR]], [[ROTBB]] ]355; CHECK-NEXT: ret i32 [[COND]]356;357entry:358 %cmp = icmp eq i32 %b, 0359 br i1 %cmp, label %end, label %rotbb360 361rotbb:362 %sub = sub i32 32, %b363 %shl = shl i32 %a, %sub364 %shr = ashr i32 %a, %b365 %or = or i32 %shl, %shr366 br label %end367 368end:369 %cond = phi i32 [ %a, %entry ], [ %or, %rotbb ]370 ret i32 %cond371}372 373; Negative test - wrong shift for rotate (but can be folded to a generic funnel shift).374 375define i32 @not_rotr_5(i32 %a, i32 %b) {376; CHECK-LABEL: @not_rotr_5(377; CHECK-NEXT: entry:378; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[B:%.*]], 0379; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[ROTBB:%.*]]380; CHECK: rotbb:381; CHECK-NEXT: br label [[END]]382; CHECK: end:383; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.fshr.i32(i32 [[B]], i32 [[A:%.*]], i32 [[B]])384; CHECK-NEXT: ret i32 [[TMP0]]385;386entry:387 %cmp = icmp eq i32 %b, 0388 br i1 %cmp, label %end, label %rotbb389 390rotbb:391 %sub = sub i32 32, %b392 %shl = shl i32 %b, %sub393 %shr = lshr i32 %a, %b394 %or = or i32 %shl, %shr395 br label %end396 397end:398 %cond = phi i32 [ %a, %entry ], [ %or, %rotbb ]399 ret i32 %cond400}401 402; Negative test - wrong sub.403 404define i32 @not_rotr_6(i32 %a, i32 %b) {405; CHECK-LABEL: @not_rotr_6(406; CHECK-NEXT: entry:407; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[B:%.*]], 0408; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[ROTBB:%.*]]409; CHECK: rotbb:410; CHECK-NEXT: [[SUB:%.*]] = sub i32 8, [[B]]411; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[A:%.*]], [[SUB]]412; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[A]], [[B]]413; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHL]], [[SHR]]414; CHECK-NEXT: br label [[END]]415; CHECK: end:416; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[A]], [[ENTRY:%.*]] ], [ [[OR]], [[ROTBB]] ]417; CHECK-NEXT: ret i32 [[COND]]418;419entry:420 %cmp = icmp eq i32 %b, 0421 br i1 %cmp, label %end, label %rotbb422 423rotbb:424 %sub = sub i32 8, %b425 %shl = shl i32 %a, %sub426 %shr = lshr i32 %a, %b427 %or = or i32 %shl, %shr428 br label %end429 430end:431 %cond = phi i32 [ %a, %entry ], [ %or, %rotbb ]432 ret i32 %cond433}434 435; Negative test - extra use. Technically, we could transform this436; because it doesn't increase the instruction count, but we're437; being cautious not to cause a potential perf pessimization for438; targets that do not have a rotate instruction.439 440define i32 @could_be_rotr(i32 %a, i32 %b, ptr %p) {441; CHECK-LABEL: @could_be_rotr(442; CHECK-NEXT: entry:443; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[B:%.*]], 0444; CHECK-NEXT: br i1 [[CMP]], label [[END:%.*]], label [[ROTBB:%.*]]445; CHECK: rotbb:446; CHECK-NEXT: [[SUB:%.*]] = sub i32 32, [[B]]447; CHECK-NEXT: [[SHL:%.*]] = shl i32 [[A:%.*]], [[SUB]]448; CHECK-NEXT: [[SHR:%.*]] = lshr i32 [[A]], [[B]]449; CHECK-NEXT: [[OR:%.*]] = or i32 [[SHL]], [[SHR]]450; CHECK-NEXT: store i32 [[OR]], ptr [[P:%.*]], align 4451; CHECK-NEXT: br label [[END]]452; CHECK: end:453; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[A]], [[ENTRY:%.*]] ], [ [[OR]], [[ROTBB]] ]454; CHECK-NEXT: ret i32 [[COND]]455;456entry:457 %cmp = icmp eq i32 %b, 0458 br i1 %cmp, label %end, label %rotbb459 460rotbb:461 %sub = sub i32 32, %b462 %shl = shl i32 %a, %sub463 %shr = lshr i32 %a, %b464 %or = or i32 %shl, %shr465 store i32 %or, ptr %p466 br label %end467 468end:469 %cond = phi i32 [ %a, %entry ], [ %or, %rotbb ]470 ret i32 %cond471}472 473