1409 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 52; RUN: opt -S -passes=instcombine < %s | FileCheck %s3 4; Reassociate add.5define i8 @add_reassoc(i32 %n) {6; CHECK-LABEL: define i8 @add_reassoc(7; CHECK-SAME: i32 [[N:%.*]]) {8; CHECK-NEXT: [[ENTRY:.*]]:9; CHECK-NEXT: br label %[[BODY:.*]]10; CHECK: [[BODY]]:11; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]12; CHECK-NEXT: [[REDUCED_PHI:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[RDX:%.*]], %[[BODY]] ]13; CHECK-NEXT: [[RDX]] = add i8 [[REDUCED_PHI]], 514; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 115; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]16; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]17; CHECK: [[EXIT]]:18; CHECK-NEXT: ret i8 [[RDX]]19;20entry:21 br label %body22 23body:24 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]25 %pn = phi i8 [ 0, %entry ], [ %op1, %body ]26 %pn2 = phi i8 [ 1, %entry ], [ %op2, %body ]27 %op1 = add i8 %pn, 228 %op2 = add i8 %pn2, 329 %i.next = add nuw nsw i32 %i, 130 %cmp = icmp eq i32 %i.next, %n31 br i1 %cmp, label %exit, label %body32 33exit:34 %rdx = add i8 %op2, %op135 ret i8 %rdx36}37 38; Reassociate add, and maintain nuw if all ops have it.39define i8 @add_nuw(i32 %n) {40; CHECK-LABEL: define i8 @add_nuw(41; CHECK-SAME: i32 [[N:%.*]]) {42; CHECK-NEXT: [[ENTRY:.*]]:43; CHECK-NEXT: br label %[[BODY:.*]]44; CHECK: [[BODY]]:45; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]46; CHECK-NEXT: [[REDUCED_PHI:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[RDX:%.*]], %[[BODY]] ]47; CHECK-NEXT: [[RDX]] = add nuw i8 [[REDUCED_PHI]], 548; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 149; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]50; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]51; CHECK: [[EXIT]]:52; CHECK-NEXT: ret i8 [[RDX]]53;54entry:55 br label %body56 57body:58 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]59 %pn = phi i8 [ 0, %entry ], [ %op1, %body ]60 %pn2 = phi i8 [ 1, %entry ], [ %op2, %body ]61 %op1 = add nuw i8 %pn, 262 %op2 = add nuw i8 %pn2, 363 %i.next = add nuw nsw i32 %i, 164 %cmp = icmp eq i32 %i.next, %n65 br i1 %cmp, label %exit, label %body66 67exit:68 %rdx = add nuw i8 %op2, %op169 ret i8 %rdx70}71 72; Reassociate add, drop nuw if op1 doesn't have it.73define i8 @add_op1_no_nuw(i32 %n) {74; CHECK-LABEL: define i8 @add_op1_no_nuw(75; CHECK-SAME: i32 [[N:%.*]]) {76; CHECK-NEXT: [[ENTRY:.*]]:77; CHECK-NEXT: br label %[[BODY:.*]]78; CHECK: [[BODY]]:79; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]80; CHECK-NEXT: [[REDUCED_PHI:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[RDX:%.*]], %[[BODY]] ]81; CHECK-NEXT: [[RDX]] = add i8 [[REDUCED_PHI]], 582; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 183; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]84; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]85; CHECK: [[EXIT]]:86; CHECK-NEXT: ret i8 [[RDX]]87;88entry:89 br label %body90 91body:92 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]93 %pn = phi i8 [ 0, %entry ], [ %op1, %body ]94 %pn2 = phi i8 [ 1, %entry ], [ %op2, %body ]95 %op1 = add i8 %pn, 296 %op2 = add nuw i8 %pn2, 397 %i.next = add nuw nsw i32 %i, 198 %cmp = icmp eq i32 %i.next, %n99 br i1 %cmp, label %exit, label %body100 101exit:102 %rdx = add nuw i8 %op2, %op1103 ret i8 %rdx104}105 106; Reassociate add, drop nuw if op2 doesn't have it.107define i8 @add_op2_no_nuw(i32 %n) {108; CHECK-LABEL: define i8 @add_op2_no_nuw(109; CHECK-SAME: i32 [[N:%.*]]) {110; CHECK-NEXT: [[ENTRY:.*]]:111; CHECK-NEXT: br label %[[BODY:.*]]112; CHECK: [[BODY]]:113; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]114; CHECK-NEXT: [[REDUCED_PHI:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[RDX:%.*]], %[[BODY]] ]115; CHECK-NEXT: [[RDX]] = add i8 [[REDUCED_PHI]], 5116; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1117; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]118; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]119; CHECK: [[EXIT]]:120; CHECK-NEXT: ret i8 [[RDX]]121;122entry:123 br label %body124 125body:126 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]127 %pn = phi i8 [ 0, %entry ], [ %op1, %body ]128 %pn2 = phi i8 [ 1, %entry ], [ %op2, %body ]129 %op1 = add nuw i8 %pn, 2130 %op2 = add i8 %pn2, 3131 %i.next = add nuw nsw i32 %i, 1132 %cmp = icmp eq i32 %i.next, %n133 br i1 %cmp, label %exit, label %body134 135exit:136 %rdx = add nuw i8 %op2, %op1137 ret i8 %rdx138}139 140; Reassociate add, drop nuw if rdx doesn't have it.141define i8 @add_rdx_no_nuw(i32 %n) {142; CHECK-LABEL: define i8 @add_rdx_no_nuw(143; CHECK-SAME: i32 [[N:%.*]]) {144; CHECK-NEXT: [[ENTRY:.*]]:145; CHECK-NEXT: br label %[[BODY:.*]]146; CHECK: [[BODY]]:147; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]148; CHECK-NEXT: [[REDUCED_PHI:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[RDX:%.*]], %[[BODY]] ]149; CHECK-NEXT: [[RDX]] = add i8 [[REDUCED_PHI]], 5150; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1151; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]152; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]153; CHECK: [[EXIT]]:154; CHECK-NEXT: ret i8 [[RDX]]155;156entry:157 br label %body158 159body:160 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]161 %pn = phi i8 [ 0, %entry ], [ %op1, %body ]162 %pn2 = phi i8 [ 1, %entry ], [ %op2, %body ]163 %op1 = add nuw i8 %pn, 2164 %op2 = add nuw i8 %pn2, 3165 %i.next = add nuw nsw i32 %i, 1166 %cmp = icmp eq i32 %i.next, %n167 br i1 %cmp, label %exit, label %body168 169exit:170 %rdx = add i8 %op2, %op1171 ret i8 %rdx172}173 174; Reassociate add, drop nsw even if all ops have it.175define i8 @add_no_nsw(i32 %n) {176; CHECK-LABEL: define i8 @add_no_nsw(177; CHECK-SAME: i32 [[N:%.*]]) {178; CHECK-NEXT: [[ENTRY:.*]]:179; CHECK-NEXT: br label %[[BODY:.*]]180; CHECK: [[BODY]]:181; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]182; CHECK-NEXT: [[REDUCED_PHI:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[RDX:%.*]], %[[BODY]] ]183; CHECK-NEXT: [[RDX]] = add i8 [[REDUCED_PHI]], 5184; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1185; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]186; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]187; CHECK: [[EXIT]]:188; CHECK-NEXT: ret i8 [[RDX]]189;190entry:191 br label %body192 193body:194 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]195 %pn = phi i8 [ 0, %entry ], [ %op1, %body ]196 %pn2 = phi i8 [ 1, %entry ], [ %op2, %body ]197 %op1 = add nsw i8 %pn, 2198 %op2 = add nsw i8 %pn2, 3199 %i.next = add nuw nsw i32 %i, 1200 %cmp = icmp eq i32 %i.next, %n201 br i1 %cmp, label %exit, label %body202 203exit:204 %rdx = add nsw i8 %op2, %op1205 ret i8 %rdx206}207 208; Reassociate add, keep nuw/nsw if all ops have them.209define i8 @add_nuw_nsw(i32 %n) {210; CHECK-LABEL: define i8 @add_nuw_nsw(211; CHECK-SAME: i32 [[N:%.*]]) {212; CHECK-NEXT: [[ENTRY:.*]]:213; CHECK-NEXT: br label %[[BODY:.*]]214; CHECK: [[BODY]]:215; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]216; CHECK-NEXT: [[REDUCED_PHI:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[RDX:%.*]], %[[BODY]] ]217; CHECK-NEXT: [[RDX]] = add nuw nsw i8 [[REDUCED_PHI]], 5218; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1219; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]220; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]221; CHECK: [[EXIT]]:222; CHECK-NEXT: ret i8 [[RDX]]223;224entry:225 br label %body226 227body:228 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]229 %pn = phi i8 [ 0, %entry ], [ %op1, %body ]230 %pn2 = phi i8 [ 1, %entry ], [ %op2, %body ]231 %op1 = add nuw nsw i8 %pn, 2232 %op2 = add nuw nsw i8 %pn2, 3233 %i.next = add nuw nsw i32 %i, 1234 %cmp = icmp eq i32 %i.next, %n235 br i1 %cmp, label %exit, label %body236 237exit:238 %rdx = add nuw nsw i8 %op2, %op1239 ret i8 %rdx240}241 242; Reassociate fixed-length vector operands.243define <16 x i8> @add_v16i8(i32 %n) {244; CHECK-LABEL: define <16 x i8> @add_v16i8(245; CHECK-SAME: i32 [[N:%.*]]) {246; CHECK-NEXT: [[ENTRY:.*]]:247; CHECK-NEXT: br label %[[BODY:.*]]248; CHECK: [[BODY]]:249; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]250; CHECK-NEXT: [[REDUCED_PHI:%.*]] = phi <16 x i8> [ splat (i8 1), %[[ENTRY]] ], [ [[RDX:%.*]], %[[BODY]] ]251; CHECK-NEXT: [[RDX]] = add <16 x i8> [[REDUCED_PHI]], splat (i8 5)252; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1253; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]254; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]255; CHECK: [[EXIT]]:256; CHECK-NEXT: ret <16 x i8> [[RDX]]257;258entry:259 br label %body260 261body:262 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]263 %pn = phi <16 x i8> [ splat (i8 0), %entry ], [ %op1, %body ]264 %pn2 = phi <16 x i8> [ splat (i8 1), %entry ], [ %op2, %body ]265 %op1 = add <16 x i8> %pn, splat (i8 2)266 %op2 = add <16 x i8> %pn2, splat (i8 3)267 %i.next = add nuw nsw i32 %i, 1268 %cmp = icmp eq i32 %i.next, %n269 br i1 %cmp, label %exit, label %body270 271exit:272 %rdx = add <16 x i8> %op2, %op1273 ret <16 x i8> %rdx274}275 276; Reassociate scalable vector operands.277define <vscale x 16 x i8> @add_nxv16i8(i32 %n) {278; CHECK-LABEL: define <vscale x 16 x i8> @add_nxv16i8(279; CHECK-SAME: i32 [[N:%.*]]) {280; CHECK-NEXT: [[ENTRY:.*]]:281; CHECK-NEXT: br label %[[BODY:.*]]282; CHECK: [[BODY]]:283; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]284; CHECK-NEXT: [[REDUCED_PHI:%.*]] = phi <vscale x 16 x i8> [ splat (i8 1), %[[ENTRY]] ], [ [[RDX:%.*]], %[[BODY]] ]285; CHECK-NEXT: [[RDX]] = add <vscale x 16 x i8> [[REDUCED_PHI]], splat (i8 5)286; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1287; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]288; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]289; CHECK: [[EXIT]]:290; CHECK-NEXT: ret <vscale x 16 x i8> [[RDX]]291;292entry:293 br label %body294 295body:296 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]297 %pn = phi <vscale x 16 x i8> [ splat (i8 0), %entry ], [ %op1, %body ]298 %pn2 = phi <vscale x 16 x i8> [ splat (i8 1), %entry ], [ %op2, %body ]299 %op1 = add <vscale x 16 x i8> %pn, splat (i8 2)300 %op2 = add <vscale x 16 x i8> %pn2, splat (i8 3)301 %i.next = add nuw nsw i32 %i, 1302 %cmp = icmp eq i32 %i.next, %n303 br i1 %cmp, label %exit, label %body304 305exit:306 %rdx = add <vscale x 16 x i8> %op2, %op1307 ret <vscale x 16 x i8> %rdx308}309 310; Check other opcodes.311 312; Reassociate mul.313define i8 @mul_reassoc(i32 %n) {314; CHECK-LABEL: define i8 @mul_reassoc(315; CHECK-SAME: i32 [[N:%.*]]) {316; CHECK-NEXT: [[ENTRY:.*]]:317; CHECK-NEXT: br label %[[BODY:.*]]318; CHECK: [[BODY]]:319; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]320; CHECK-NEXT: [[REDUCED_PHI:%.*]] = phi i8 [ 2, %[[ENTRY]] ], [ [[RDX:%.*]], %[[BODY]] ]321; CHECK-NEXT: [[RDX]] = mul i8 [[REDUCED_PHI]], 15322; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1323; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]324; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]325; CHECK: [[EXIT]]:326; CHECK-NEXT: ret i8 [[RDX]]327;328entry:329 br label %body330 331body:332 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]333 %pn = phi i8 [ 1, %entry ], [ %op1, %body ]334 %pn2 = phi i8 [ 2, %entry ], [ %op2, %body ]335 %op1 = mul i8 %pn, 3336 %op2 = mul i8 %pn2, 5337 %i.next = add nuw nsw i32 %i, 1338 %cmp = icmp eq i32 %i.next, %n339 br i1 %cmp, label %exit, label %body340 341exit:342 %rdx = mul i8 %op2, %op1343 ret i8 %rdx344}345 346; Reassociate mul, don't expect any flags to be propagated.347define i8 @mul_reassoc_no_nuw_no_nsw(i32 %n) {348; CHECK-LABEL: define i8 @mul_reassoc_no_nuw_no_nsw(349; CHECK-SAME: i32 [[N:%.*]]) {350; CHECK-NEXT: [[ENTRY:.*]]:351; CHECK-NEXT: br label %[[BODY:.*]]352; CHECK: [[BODY]]:353; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]354; CHECK-NEXT: [[REDUCED_PHI:%.*]] = phi i8 [ 2, %[[ENTRY]] ], [ [[RDX:%.*]], %[[BODY]] ]355; CHECK-NEXT: [[RDX]] = mul i8 [[REDUCED_PHI]], 15356; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1357; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]358; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]359; CHECK: [[EXIT]]:360; CHECK-NEXT: ret i8 [[RDX]]361;362entry:363 br label %body364 365body:366 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]367 %pn = phi i8 [ 1, %entry ], [ %op1, %body ]368 %pn2 = phi i8 [ 2, %entry ], [ %op2, %body ]369 %op1 = mul nuw nsw i8 %pn, 3370 %op2 = mul nuw nsw i8 %pn2, 5371 %i.next = add nuw nsw i32 %i, 1372 %cmp = icmp eq i32 %i.next, %n373 br i1 %cmp, label %exit, label %body374 375exit:376 %rdx = mul nuw nsw i8 %op2, %op1377 ret i8 %rdx378}379 380; Reassociate and, although it should already be optimized separately.381define i8 @and_reassoc(i32 %n) {382; CHECK-LABEL: define i8 @and_reassoc(383; CHECK-SAME: i32 [[N:%.*]]) {384; CHECK-NEXT: [[ENTRY:.*]]:385; CHECK-NEXT: br label %[[BODY:.*]]386; CHECK: [[BODY]]:387; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]388; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1389; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]390; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]391; CHECK: [[EXIT]]:392; CHECK-NEXT: ret i8 3393;394entry:395 br label %body396 397body:398 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]399 %pn = phi i8 [ 31, %entry ], [ %op1, %body ]400 %pn2 = phi i8 [ 63, %entry ], [ %op2, %body ]401 %op1 = and i8 %pn, 3402 %op2 = and i8 %pn2, 7403 %i.next = add nuw nsw i32 %i, 1404 %cmp = icmp eq i32 %i.next, %n405 br i1 %cmp, label %exit, label %body406 407exit:408 %rdx = and i8 %op2, %op1409 ret i8 %rdx410}411 412; Reassociate or, although it should already be optimized separately.413define i8 @or_reassoc(i32 %n) {414; CHECK-LABEL: define i8 @or_reassoc(415; CHECK-SAME: i32 [[N:%.*]]) {416; CHECK-NEXT: [[ENTRY:.*]]:417; CHECK-NEXT: br label %[[BODY:.*]]418; CHECK: [[BODY]]:419; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]420; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1421; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]422; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]423; CHECK: [[EXIT]]:424; CHECK-NEXT: ret i8 7425;426entry:427 br label %body428 429body:430 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]431 %pn = phi i8 [ 0, %entry ], [ %op1, %body ]432 %pn2 = phi i8 [ 1, %entry ], [ %op2, %body ]433 %op1 = or i8 %pn, 3434 %op2 = or i8 %pn2, 7435 %i.next = add nuw nsw i32 %i, 1436 %cmp = icmp eq i32 %i.next, %n437 br i1 %cmp, label %exit, label %body438 439exit:440 %rdx = or i8 %op2, %op1441 ret i8 %rdx442}443 444; Reassociate or and propagate disjoint if all ops have it.445; Note: This can't currently be seen as the results get optimized away.446define i8 @or_disjoint(i32 %n) {447; CHECK-LABEL: define i8 @or_disjoint(448; CHECK-SAME: i32 [[N:%.*]]) {449; CHECK-NEXT: [[ENTRY:.*]]:450; CHECK-NEXT: br label %[[BODY:.*]]451; CHECK: [[BODY]]:452; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]453; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1454; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]455; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]456; CHECK: [[EXIT]]:457; CHECK-NEXT: ret i8 7458;459entry:460 br label %body461 462body:463 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]464 %pn = phi i8 [ 0, %entry ], [ %op1, %body ]465 %pn2 = phi i8 [ 1, %entry ], [ %op2, %body ]466 %op1 = or disjoint i8 %pn, 3467 %op2 = or disjoint i8 %pn2, 7468 %i.next = add nuw nsw i32 %i, 1469 %cmp = icmp eq i32 %i.next, %n470 br i1 %cmp, label %exit, label %body471 472exit:473 %rdx = or disjoint i8 %op2, %op1474 ret i8 %rdx475}476 477; Reassociate xor.478define i8 @xor_reassoc(i32 %n) {479; CHECK-LABEL: define i8 @xor_reassoc(480; CHECK-SAME: i32 [[N:%.*]]) {481; CHECK-NEXT: [[ENTRY:.*]]:482; CHECK-NEXT: br label %[[BODY:.*]]483; CHECK: [[BODY]]:484; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]485; CHECK-NEXT: [[REDUCED_PHI:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[RDX:%.*]], %[[BODY]] ]486; CHECK-NEXT: [[RDX]] = xor i8 [[REDUCED_PHI]], 4487; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1488; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]489; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]490; CHECK: [[EXIT]]:491; CHECK-NEXT: ret i8 [[RDX]]492;493entry:494 br label %body495 496body:497 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]498 %pn = phi i8 [ 0, %entry ], [ %op1, %body ]499 %pn2 = phi i8 [ 1, %entry ], [ %op2, %body ]500 %op1 = xor i8 %pn, 3501 %op2 = xor i8 %pn2, 7502 %i.next = add nuw nsw i32 %i, 1503 %cmp = icmp eq i32 %i.next, %n504 br i1 %cmp, label %exit, label %body505 506exit:507 %rdx = xor i8 %op2, %op1508 ret i8 %rdx509}510 511; Reassociate fadd if reassoc and nsz are present on all instructions.512define float @fadd_reassoc_nsz(i32 %n) {513; CHECK-LABEL: define float @fadd_reassoc_nsz(514; CHECK-SAME: i32 [[N:%.*]]) {515; CHECK-NEXT: [[ENTRY:.*]]:516; CHECK-NEXT: br label %[[BODY:.*]]517; CHECK: [[BODY]]:518; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]519; CHECK-NEXT: [[REDUCED_PHI:%.*]] = phi float [ 1.000000e+00, %[[ENTRY]] ], [ [[RDX:%.*]], %[[BODY]] ]520; CHECK-NEXT: [[RDX]] = fadd reassoc nsz float [[REDUCED_PHI]], 5.000000e+00521; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1522; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]523; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]524; CHECK: [[EXIT]]:525; CHECK-NEXT: ret float [[RDX]]526;527entry:528 br label %body529 530body:531 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]532 %pn = phi float [ 0.0, %entry ], [ %op1, %body ]533 %pn2 = phi float [ 1.0, %entry ], [ %op2, %body ]534 %op1 = fadd reassoc nsz float %pn, 2.0535 %op2 = fadd reassoc nsz float %pn2, 3.0536 %i.next = add nuw nsw i32 %i, 1537 %cmp = icmp eq i32 %i.next, %n538 br i1 %cmp, label %exit, label %body539 540exit:541 %rdx = fadd reassoc nsz float %op2, %op1542 ret float %rdx543}544 545; Reassociate fmul if reassoc and nsz are present on all instructions.546define float @fmul_reassoc_nsz(i32 %n) {547; CHECK-LABEL: define float @fmul_reassoc_nsz(548; CHECK-SAME: i32 [[N:%.*]]) {549; CHECK-NEXT: [[ENTRY:.*]]:550; CHECK-NEXT: br label %[[BODY:.*]]551; CHECK: [[BODY]]:552; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]553; CHECK-NEXT: [[REDUCED_PHI:%.*]] = phi float [ 2.000000e+00, %[[ENTRY]] ], [ [[RDX:%.*]], %[[BODY]] ]554; CHECK-NEXT: [[RDX]] = fmul reassoc nsz float [[REDUCED_PHI]], 1.200000e+01555; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1556; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]557; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]558; CHECK: [[EXIT]]:559; CHECK-NEXT: ret float [[RDX]]560;561entry:562 br label %body563 564body:565 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]566 %pn = phi float [ 1.0, %entry ], [ %op1, %body ]567 %pn2 = phi float [ 2.0, %entry ], [ %op2, %body ]568 %op1 = fmul reassoc nsz float %pn, 3.0569 %op2 = fmul reassoc nsz float %pn2, 4.0570 %i.next = add nuw nsw i32 %i, 1571 %cmp = icmp eq i32 %i.next, %n572 br i1 %cmp, label %exit, label %body573 574exit:575 %rdx = fmul reassoc nsz float %op2, %op1576 ret float %rdx577}578 579; Don't reassociate without `reassoc'.580define float @fadd_no_reassoc(i32 %n) {581; CHECK-LABEL: define float @fadd_no_reassoc(582; CHECK-SAME: i32 [[N:%.*]]) {583; CHECK-NEXT: [[ENTRY:.*]]:584; CHECK-NEXT: br label %[[BODY:.*]]585; CHECK: [[BODY]]:586; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]587; CHECK-NEXT: [[PN:%.*]] = phi float [ 0.000000e+00, %[[ENTRY]] ], [ [[OP1:%.*]], %[[BODY]] ]588; CHECK-NEXT: [[PN2:%.*]] = phi float [ 1.000000e+00, %[[ENTRY]] ], [ [[OP2:%.*]], %[[BODY]] ]589; CHECK-NEXT: [[OP1]] = fadd nsz float [[PN]], 2.000000e+00590; CHECK-NEXT: [[OP2]] = fadd nsz float [[PN2]], 3.000000e+00591; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1592; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]593; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]594; CHECK: [[EXIT]]:595; CHECK-NEXT: [[RDX:%.*]] = fadd nsz float [[OP2]], [[OP1]]596; CHECK-NEXT: ret float [[RDX]]597;598entry:599 br label %body600 601body:602 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]603 %pn = phi float [ 0.0, %entry ], [ %op1, %body ]604 %pn2 = phi float [ 1.0, %entry ], [ %op2, %body ]605 %op1 = fadd nsz float %pn, 2.0606 %op2 = fadd nsz float %pn2, 3.0607 %i.next = add nuw nsw i32 %i, 1608 %cmp = icmp eq i32 %i.next, %n609 br i1 %cmp, label %exit, label %body610 611exit:612 %rdx = fadd nsz float %op2, %op1613 ret float %rdx614}615 616; Don't reassociate without `nsz'.617define float @fadd_no_nsz(i32 %n) {618; CHECK-LABEL: define float @fadd_no_nsz(619; CHECK-SAME: i32 [[N:%.*]]) {620; CHECK-NEXT: [[ENTRY:.*]]:621; CHECK-NEXT: br label %[[BODY:.*]]622; CHECK: [[BODY]]:623; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]624; CHECK-NEXT: [[PN:%.*]] = phi float [ 0.000000e+00, %[[ENTRY]] ], [ [[OP1:%.*]], %[[BODY]] ]625; CHECK-NEXT: [[PN2:%.*]] = phi float [ 1.000000e+00, %[[ENTRY]] ], [ [[OP2:%.*]], %[[BODY]] ]626; CHECK-NEXT: [[OP1]] = fadd reassoc float [[PN]], 2.000000e+00627; CHECK-NEXT: [[OP2]] = fadd reassoc float [[PN2]], 3.000000e+00628; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1629; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]630; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]631; CHECK: [[EXIT]]:632; CHECK-NEXT: [[RDX:%.*]] = fadd reassoc float [[OP2]], [[OP1]]633; CHECK-NEXT: ret float [[RDX]]634;635entry:636 br label %body637 638body:639 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]640 %pn = phi float [ 0.0, %entry ], [ %op1, %body ]641 %pn2 = phi float [ 1.0, %entry ], [ %op2, %body ]642 %op1 = fadd reassoc float %pn, 2.0643 %op2 = fadd reassoc float %pn2, 3.0644 %i.next = add nuw nsw i32 %i, 1645 %cmp = icmp eq i32 %i.next, %n646 br i1 %cmp, label %exit, label %body647 648exit:649 %rdx = fadd reassoc float %op2, %op1650 ret float %rdx651}652 653; Check commuted operands.654 655; Reassociate, even if op1 has commuted operands.656define i8 @add_op1_commuted(i32 %n) {657; CHECK-LABEL: define i8 @add_op1_commuted(658; CHECK-SAME: i32 [[N:%.*]]) {659; CHECK-NEXT: [[ENTRY:.*]]:660; CHECK-NEXT: br label %[[BODY:.*]]661; CHECK: [[BODY]]:662; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]663; CHECK-NEXT: [[REDUCED_PHI:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[RDX:%.*]], %[[BODY]] ]664; CHECK-NEXT: [[RDX]] = add i8 [[REDUCED_PHI]], 5665; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1666; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]667; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]668; CHECK: [[EXIT]]:669; CHECK-NEXT: ret i8 [[RDX]]670;671entry:672 br label %body673 674body:675 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]676 %pn = phi i8 [ 0, %entry ], [ %op1, %body ]677 %pn2 = phi i8 [ 1, %entry ], [ %op2, %body ]678 %op1 = add i8 2, %pn679 %op2 = add i8 %pn2, 3680 %i.next = add nuw nsw i32 %i, 1681 %cmp = icmp eq i32 %i.next, %n682 br i1 %cmp, label %exit, label %body683 684exit:685 %rdx = add i8 %op2, %op1686 ret i8 %rdx687}688 689; Reassociate, even if op2 has commuted operands.690define i8 @add_op2_commuted(i32 %n) {691; CHECK-LABEL: define i8 @add_op2_commuted(692; CHECK-SAME: i32 [[N:%.*]]) {693; CHECK-NEXT: [[ENTRY:.*]]:694; CHECK-NEXT: br label %[[BODY:.*]]695; CHECK: [[BODY]]:696; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]697; CHECK-NEXT: [[REDUCED_PHI:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[RDX:%.*]], %[[BODY]] ]698; CHECK-NEXT: [[RDX]] = add i8 [[REDUCED_PHI]], 5699; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1700; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]701; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]702; CHECK: [[EXIT]]:703; CHECK-NEXT: ret i8 [[RDX]]704;705entry:706 br label %body707 708body:709 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]710 %pn = phi i8 [ 0, %entry ], [ %op1, %body ]711 %pn2 = phi i8 [ 1, %entry ], [ %op2, %body ]712 %op1 = add i8 %pn, 2713 %op2 = add i8 3, %pn2714 %i.next = add nuw nsw i32 %i, 1715 %cmp = icmp eq i32 %i.next, %n716 br i1 %cmp, label %exit, label %body717 718exit:719 %rdx = add i8 %op2, %op1720 ret i8 %rdx721}722 723; Reassociate, even if rdx has commuted operands.724define i8 @add_rdx_commuted(i32 %n) {725; CHECK-LABEL: define i8 @add_rdx_commuted(726; CHECK-SAME: i32 [[N:%.*]]) {727; CHECK-NEXT: [[ENTRY:.*]]:728; CHECK-NEXT: br label %[[BODY:.*]]729; CHECK: [[BODY]]:730; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]731; CHECK-NEXT: [[REDUCED_PHI:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[RDX:%.*]], %[[BODY]] ]732; CHECK-NEXT: [[RDX]] = add i8 [[REDUCED_PHI]], 5733; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1734; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]735; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]736; CHECK: [[EXIT]]:737; CHECK-NEXT: ret i8 [[RDX]]738;739entry:740 br label %body741 742body:743 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]744 %pn = phi i8 [ 0, %entry ], [ %op1, %body ]745 %pn2 = phi i8 [ 1, %entry ], [ %op2, %body ]746 %op1 = add i8 %pn, 2747 %op2 = add i8 %pn2, 3748 %i.next = add nuw nsw i32 %i, 1749 %cmp = icmp eq i32 %i.next, %n750 br i1 %cmp, label %exit, label %body751 752exit:753 %rdx = add i8 %op1, %op2754 ret i8 %rdx755}756 757; Reassociate, even if pn has commuted incoming values.758define i8 @add_pn_commuted(i32 %n) {759; CHECK-LABEL: define i8 @add_pn_commuted(760; CHECK-SAME: i32 [[N:%.*]]) {761; CHECK-NEXT: [[ENTRY:.*]]:762; CHECK-NEXT: br label %[[BODY:.*]]763; CHECK: [[BODY]]:764; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]765; CHECK-NEXT: [[REDUCED_PHI:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[RDX:%.*]], %[[BODY]] ]766; CHECK-NEXT: [[RDX]] = add i8 [[REDUCED_PHI]], 5767; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1768; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]769; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]770; CHECK: [[EXIT]]:771; CHECK-NEXT: ret i8 [[RDX]]772;773entry:774 br label %body775 776body:777 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]778 %pn = phi i8 [ %op1, %body ], [ 0, %entry ]779 %pn2 = phi i8 [ 1, %entry ], [ %op2, %body ]780 %op1 = add i8 %pn, 2781 %op2 = add i8 %pn2, 3782 %i.next = add nuw nsw i32 %i, 1783 %cmp = icmp eq i32 %i.next, %n784 br i1 %cmp, label %exit, label %body785 786exit:787 %rdx = add i8 %op2, %op1788 ret i8 %rdx789}790 791; Reassociate, even if pn2 has commuted incoming values.792define i8 @add_pn2_commuted(i32 %n) {793; CHECK-LABEL: define i8 @add_pn2_commuted(794; CHECK-SAME: i32 [[N:%.*]]) {795; CHECK-NEXT: [[ENTRY:.*]]:796; CHECK-NEXT: br label %[[BODY:.*]]797; CHECK: [[BODY]]:798; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]799; CHECK-NEXT: [[REDUCED_PHI:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[RDX:%.*]], %[[BODY]] ]800; CHECK-NEXT: [[RDX]] = add i8 [[REDUCED_PHI]], 5801; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1802; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]803; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]804; CHECK: [[EXIT]]:805; CHECK-NEXT: ret i8 [[RDX]]806;807entry:808 br label %body809 810body:811 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]812 %pn = phi i8 [ 0, %entry ], [ %op1, %body ]813 %pn2 = phi i8 [ %op2, %body ], [ 1, %entry ]814 %op1 = add i8 %pn, 2815 %op2 = add i8 %pn2, 3816 %i.next = add nuw nsw i32 %i, 1817 %cmp = icmp eq i32 %i.next, %n818 br i1 %cmp, label %exit, label %body819 820exit:821 %rdx = add i8 %op1, %op2822 ret i8 %rdx823}824 825; Check the instructions have the same opcodes.826 827; Don't reassociate if the first op doesn't match the rest.828define i8 @no_mul_add_add(i32 %n) {829; CHECK-LABEL: define i8 @no_mul_add_add(830; CHECK-SAME: i32 [[N:%.*]]) {831; CHECK-NEXT: [[ENTRY:.*]]:832; CHECK-NEXT: br label %[[BODY:.*]]833; CHECK: [[BODY]]:834; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]835; CHECK-NEXT: [[PN:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[OP1:%.*]], %[[BODY]] ]836; CHECK-NEXT: [[PN2:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[OP2:%.*]], %[[BODY]] ]837; CHECK-NEXT: [[OP1]] = shl i8 [[PN]], 1838; CHECK-NEXT: [[OP2]] = add i8 [[PN2]], 3839; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1840; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]841; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]842; CHECK: [[EXIT]]:843; CHECK-NEXT: [[RDX:%.*]] = add i8 [[OP2]], [[OP1]]844; CHECK-NEXT: ret i8 [[RDX]]845;846entry:847 br label %body848 849body:850 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]851 %pn = phi i8 [ 1, %entry ], [ %op1, %body ]852 %pn2 = phi i8 [ 1, %entry ], [ %op2, %body ]853 %op1 = mul i8 %pn, 2854 %op2 = add i8 %pn2, 3855 %i.next = add nuw nsw i32 %i, 1856 %cmp = icmp eq i32 %i.next, %n857 br i1 %cmp, label %exit, label %body858 859exit:860 %rdx = add i8 %op2, %op1861 ret i8 %rdx862}863 864; Don't reassociate if the second op doesn't match the rest.865define i8 @no_add_mul_add(i32 %n) {866; CHECK-LABEL: define i8 @no_add_mul_add(867; CHECK-SAME: i32 [[N:%.*]]) {868; CHECK-NEXT: [[ENTRY:.*]]:869; CHECK-NEXT: br label %[[BODY:.*]]870; CHECK: [[BODY]]:871; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]872; CHECK-NEXT: [[PN:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[OP1:%.*]], %[[BODY]] ]873; CHECK-NEXT: [[PN2:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[OP2:%.*]], %[[BODY]] ]874; CHECK-NEXT: [[OP1]] = add i8 [[PN]], 2875; CHECK-NEXT: [[OP2]] = mul i8 [[PN2]], 3876; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1877; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]878; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]879; CHECK: [[EXIT]]:880; CHECK-NEXT: [[RDX:%.*]] = add i8 [[OP2]], [[OP1]]881; CHECK-NEXT: ret i8 [[RDX]]882;883entry:884 br label %body885 886body:887 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]888 %pn = phi i8 [ 0, %entry ], [ %op1, %body ]889 %pn2 = phi i8 [ 1, %entry ], [ %op2, %body ]890 %op1 = add i8 %pn, 2891 %op2 = mul i8 %pn2, 3892 %i.next = add nuw nsw i32 %i, 1893 %cmp = icmp eq i32 %i.next, %n894 br i1 %cmp, label %exit, label %body895 896exit:897 %rdx = add i8 %op2, %op1898 ret i8 %rdx899}900 901; Don't reassociate if the third op doesn't match the rest.902define i8 @no_add_add_mul(i32 %n) {903; CHECK-LABEL: define i8 @no_add_add_mul(904; CHECK-SAME: i32 [[N:%.*]]) {905; CHECK-NEXT: [[ENTRY:.*]]:906; CHECK-NEXT: br label %[[BODY:.*]]907; CHECK: [[BODY]]:908; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]909; CHECK-NEXT: [[PN:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[OP1:%.*]], %[[BODY]] ]910; CHECK-NEXT: [[PN2:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[OP2:%.*]], %[[BODY]] ]911; CHECK-NEXT: [[OP1]] = add i8 [[PN]], 2912; CHECK-NEXT: [[OP2]] = add i8 [[PN2]], 3913; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1914; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]915; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]916; CHECK: [[EXIT]]:917; CHECK-NEXT: [[RDX:%.*]] = mul i8 [[OP2]], [[OP1]]918; CHECK-NEXT: ret i8 [[RDX]]919;920entry:921 br label %body922 923body:924 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]925 %pn = phi i8 [ 0, %entry ], [ %op1, %body ]926 %pn2 = phi i8 [ 1, %entry ], [ %op2, %body ]927 %op1 = add i8 %pn, 2928 %op2 = add i8 %pn2, 3929 %i.next = add nuw nsw i32 %i, 1930 %cmp = icmp eq i32 %i.next, %n931 br i1 %cmp, label %exit, label %body932 933exit:934 %rdx = mul i8 %op2, %op1935 ret i8 %rdx936}937 938; Check the number of uses of pn, pn2, op1 and op2.939 940; Don't reassociate if pn has more uses.941define i8 @no_add_pn_use(i32 %n) {942; CHECK-LABEL: define i8 @no_add_pn_use(943; CHECK-SAME: i32 [[N:%.*]]) {944; CHECK-NEXT: [[ENTRY:.*]]:945; CHECK-NEXT: br label %[[BODY:.*]]946; CHECK: [[BODY]]:947; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]948; CHECK-NEXT: [[PN:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[OP1:%.*]], %[[BODY]] ]949; CHECK-NEXT: [[PN2:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[OP2:%.*]], %[[BODY]] ]950; CHECK-NEXT: [[OP1]] = add i8 [[PN]], 2951; CHECK-NEXT: [[OP2]] = add i8 [[PN2]], 3952; CHECK-NEXT: tail call void @use(i8 [[PN]])953; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1954; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]955; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]956; CHECK: [[EXIT]]:957; CHECK-NEXT: [[RDX:%.*]] = add i8 [[OP2]], [[OP1]]958; CHECK-NEXT: ret i8 [[RDX]]959;960entry:961 br label %body962 963body:964 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]965 %pn = phi i8 [ 0, %entry ], [ %op1, %body ]966 %pn2 = phi i8 [ 1, %entry ], [ %op2, %body ]967 %op1 = add i8 %pn, 2968 %op2 = add i8 %pn2, 3969 tail call void @use(i8 %pn)970 %i.next = add nuw nsw i32 %i, 1971 %cmp = icmp eq i32 %i.next, %n972 br i1 %cmp, label %exit, label %body973 974exit:975 %rdx = add i8 %op2, %op1976 ret i8 %rdx977}978 979; Don't reassociate if pn2 has more uses.980define i8 @no_add_pn2_use(i32 %n) {981; CHECK-LABEL: define i8 @no_add_pn2_use(982; CHECK-SAME: i32 [[N:%.*]]) {983; CHECK-NEXT: [[ENTRY:.*]]:984; CHECK-NEXT: br label %[[BODY:.*]]985; CHECK: [[BODY]]:986; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]987; CHECK-NEXT: [[PN:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[OP1:%.*]], %[[BODY]] ]988; CHECK-NEXT: [[PN2:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[OP2:%.*]], %[[BODY]] ]989; CHECK-NEXT: [[OP1]] = add i8 [[PN]], 2990; CHECK-NEXT: [[OP2]] = add i8 [[PN2]], 3991; CHECK-NEXT: tail call void @use(i8 [[PN2]])992; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1993; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]994; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]995; CHECK: [[EXIT]]:996; CHECK-NEXT: [[RDX:%.*]] = add i8 [[OP2]], [[OP1]]997; CHECK-NEXT: ret i8 [[RDX]]998;999entry:1000 br label %body1001 1002body:1003 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]1004 %pn = phi i8 [ 0, %entry ], [ %op1, %body ]1005 %pn2 = phi i8 [ 1, %entry ], [ %op2, %body ]1006 %op1 = add i8 %pn, 21007 %op2 = add i8 %pn2, 31008 tail call void @use(i8 %pn2)1009 %i.next = add nuw nsw i32 %i, 11010 %cmp = icmp eq i32 %i.next, %n1011 br i1 %cmp, label %exit, label %body1012 1013exit:1014 %rdx = add i8 %op2, %op11015 ret i8 %rdx1016}1017 1018; Don't reassociate if op1 has more uses.1019define i8 @no_add_op1_use(i32 %n) {1020; CHECK-LABEL: define i8 @no_add_op1_use(1021; CHECK-SAME: i32 [[N:%.*]]) {1022; CHECK-NEXT: [[ENTRY:.*]]:1023; CHECK-NEXT: br label %[[BODY:.*]]1024; CHECK: [[BODY]]:1025; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]1026; CHECK-NEXT: [[PN:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[OP1:%.*]], %[[BODY]] ]1027; CHECK-NEXT: [[PN2:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[OP2:%.*]], %[[BODY]] ]1028; CHECK-NEXT: [[OP1]] = add i8 [[PN]], 21029; CHECK-NEXT: [[OP2]] = add i8 [[PN2]], 31030; CHECK-NEXT: tail call void @use(i8 [[OP1]])1031; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 11032; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]1033; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]1034; CHECK: [[EXIT]]:1035; CHECK-NEXT: [[RDX:%.*]] = add i8 [[OP2]], [[OP1]]1036; CHECK-NEXT: ret i8 [[RDX]]1037;1038entry:1039 br label %body1040 1041body:1042 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]1043 %pn = phi i8 [ 0, %entry ], [ %op1, %body ]1044 %pn2 = phi i8 [ 1, %entry ], [ %op2, %body ]1045 %op1 = add i8 %pn, 21046 %op2 = add i8 %pn2, 31047 tail call void @use(i8 %op1)1048 %i.next = add nuw nsw i32 %i, 11049 %cmp = icmp eq i32 %i.next, %n1050 br i1 %cmp, label %exit, label %body1051 1052exit:1053 %rdx = add i8 %op2, %op11054 ret i8 %rdx1055}1056 1057; Don't reassociate if op2 has more uses.1058define i8 @no_add_op2_use(i32 %n) {1059; CHECK-LABEL: define i8 @no_add_op2_use(1060; CHECK-SAME: i32 [[N:%.*]]) {1061; CHECK-NEXT: [[ENTRY:.*]]:1062; CHECK-NEXT: br label %[[BODY:.*]]1063; CHECK: [[BODY]]:1064; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]1065; CHECK-NEXT: [[PN:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[OP1:%.*]], %[[BODY]] ]1066; CHECK-NEXT: [[PN2:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[OP2:%.*]], %[[BODY]] ]1067; CHECK-NEXT: [[OP1]] = add i8 [[PN]], 21068; CHECK-NEXT: [[OP2]] = add i8 [[PN2]], 31069; CHECK-NEXT: tail call void @use(i8 [[OP2]])1070; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 11071; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]1072; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]1073; CHECK: [[EXIT]]:1074; CHECK-NEXT: [[RDX:%.*]] = add i8 [[OP2]], [[OP1]]1075; CHECK-NEXT: ret i8 [[RDX]]1076;1077entry:1078 br label %body1079 1080body:1081 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]1082 %pn = phi i8 [ 0, %entry ], [ %op1, %body ]1083 %pn2 = phi i8 [ 1, %entry ], [ %op2, %body ]1084 %op1 = add i8 %pn, 21085 %op2 = add i8 %pn2, 31086 tail call void @use(i8 %op2)1087 %i.next = add nuw nsw i32 %i, 11088 %cmp = icmp eq i32 %i.next, %n1089 br i1 %cmp, label %exit, label %body1090 1091exit:1092 %rdx = add i8 %op2, %op11093 ret i8 %rdx1094}1095 1096; Check that init1, init2, c1 and c2 are constants.1097; Note: It should be possible to support non-constant operands, we just don't1098; do so yet.1099 1100; Don't reassociate if the initial value of pn isn't constant.1101define i8 @no_add_init1(i8 %init1, i32 %n) {1102; CHECK-LABEL: define i8 @no_add_init1(1103; CHECK-SAME: i8 [[INIT1:%.*]], i32 [[N:%.*]]) {1104; CHECK-NEXT: [[ENTRY:.*]]:1105; CHECK-NEXT: br label %[[BODY:.*]]1106; CHECK: [[BODY]]:1107; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]1108; CHECK-NEXT: [[PN:%.*]] = phi i8 [ [[INIT1]], %[[ENTRY]] ], [ [[OP1:%.*]], %[[BODY]] ]1109; CHECK-NEXT: [[PN2:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[OP2:%.*]], %[[BODY]] ]1110; CHECK-NEXT: [[OP1]] = add i8 [[PN]], 21111; CHECK-NEXT: [[OP2]] = add i8 [[PN2]], 31112; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 11113; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]1114; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]1115; CHECK: [[EXIT]]:1116; CHECK-NEXT: [[RDX:%.*]] = add i8 [[OP2]], [[OP1]]1117; CHECK-NEXT: ret i8 [[RDX]]1118;1119entry:1120 br label %body1121 1122body:1123 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]1124 %pn = phi i8 [ %init1, %entry ], [ %op1, %body ]1125 %pn2 = phi i8 [ 1, %entry ], [ %op2, %body ]1126 %op1 = add i8 %pn, 21127 %op2 = add i8 %pn2, 31128 %i.next = add nuw nsw i32 %i, 11129 %cmp = icmp eq i32 %i.next, %n1130 br i1 %cmp, label %exit, label %body1131 1132exit:1133 %rdx = add i8 %op2, %op11134 ret i8 %rdx1135}1136 1137; Don't reassociate if the initial value of pn2 isn't constant.1138define i8 @no_add_init2(i8 %init2, i32 %n) {1139; CHECK-LABEL: define i8 @no_add_init2(1140; CHECK-SAME: i8 [[INIT2:%.*]], i32 [[N:%.*]]) {1141; CHECK-NEXT: [[ENTRY:.*]]:1142; CHECK-NEXT: br label %[[BODY:.*]]1143; CHECK: [[BODY]]:1144; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]1145; CHECK-NEXT: [[PN:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[OP1:%.*]], %[[BODY]] ]1146; CHECK-NEXT: [[PN2:%.*]] = phi i8 [ [[INIT2]], %[[ENTRY]] ], [ [[OP2:%.*]], %[[BODY]] ]1147; CHECK-NEXT: [[OP1]] = add i8 [[PN]], 21148; CHECK-NEXT: [[OP2]] = add i8 [[PN2]], 31149; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 11150; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]1151; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]1152; CHECK: [[EXIT]]:1153; CHECK-NEXT: [[RDX:%.*]] = add i8 [[OP2]], [[OP1]]1154; CHECK-NEXT: ret i8 [[RDX]]1155;1156entry:1157 br label %body1158 1159body:1160 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]1161 %pn = phi i8 [ 0, %entry ], [ %op1, %body ]1162 %pn2 = phi i8 [ %init2, %entry ], [ %op2, %body ]1163 %op1 = add i8 %pn, 21164 %op2 = add i8 %pn2, 31165 %i.next = add nuw nsw i32 %i, 11166 %cmp = icmp eq i32 %i.next, %n1167 br i1 %cmp, label %exit, label %body1168 1169exit:1170 %rdx = add i8 %op2, %op11171 ret i8 %rdx1172}1173 1174; Don't reassociate if the recurrence operand of op1 isn't constant.1175define i8 @no_add_c1(i8 %c1, i32 %n) {1176; CHECK-LABEL: define i8 @no_add_c1(1177; CHECK-SAME: i8 [[C1:%.*]], i32 [[N:%.*]]) {1178; CHECK-NEXT: [[ENTRY:.*]]:1179; CHECK-NEXT: br label %[[BODY:.*]]1180; CHECK: [[BODY]]:1181; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]1182; CHECK-NEXT: [[PN:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[OP1:%.*]], %[[BODY]] ]1183; CHECK-NEXT: [[PN2:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[OP2:%.*]], %[[BODY]] ]1184; CHECK-NEXT: [[OP1]] = add i8 [[PN]], [[C1]]1185; CHECK-NEXT: [[OP2]] = add i8 [[PN2]], 31186; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 11187; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]1188; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]1189; CHECK: [[EXIT]]:1190; CHECK-NEXT: [[RDX:%.*]] = add i8 [[OP2]], [[OP1]]1191; CHECK-NEXT: ret i8 [[RDX]]1192;1193entry:1194 br label %body1195 1196body:1197 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]1198 %pn = phi i8 [ 0, %entry ], [ %op1, %body ]1199 %pn2 = phi i8 [ 1, %entry ], [ %op2, %body ]1200 %op1 = add i8 %pn, %c11201 %op2 = add i8 %pn2, 31202 %i.next = add nuw nsw i32 %i, 11203 %cmp = icmp eq i32 %i.next, %n1204 br i1 %cmp, label %exit, label %body1205 1206exit:1207 %rdx = add i8 %op2, %op11208 ret i8 %rdx1209}1210 1211; Don't reassociate if the recurrence operand of op2 isn't constant.1212define i8 @no_add_c2(i8 %c2, i32 %n) {1213; CHECK-LABEL: define i8 @no_add_c2(1214; CHECK-SAME: i8 [[C2:%.*]], i32 [[N:%.*]]) {1215; CHECK-NEXT: [[ENTRY:.*]]:1216; CHECK-NEXT: br label %[[BODY:.*]]1217; CHECK: [[BODY]]:1218; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]1219; CHECK-NEXT: [[PN:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[OP1:%.*]], %[[BODY]] ]1220; CHECK-NEXT: [[PN2:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[OP2:%.*]], %[[BODY]] ]1221; CHECK-NEXT: [[OP1]] = add i8 [[PN]], 21222; CHECK-NEXT: [[OP2]] = add i8 [[PN2]], [[C2]]1223; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 11224; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]1225; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]1226; CHECK: [[EXIT]]:1227; CHECK-NEXT: [[RDX:%.*]] = add i8 [[OP2]], [[OP1]]1228; CHECK-NEXT: ret i8 [[RDX]]1229;1230entry:1231 br label %body1232 1233body:1234 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]1235 %pn = phi i8 [ 0, %entry ], [ %op1, %body ]1236 %pn2 = phi i8 [ 1, %entry ], [ %op2, %body ]1237 %op1 = add i8 %pn, 21238 %op2 = add i8 %pn2, %c21239 %i.next = add nuw nsw i32 %i, 11240 %cmp = icmp eq i32 %i.next, %n1241 br i1 %cmp, label %exit, label %body1242 1243exit:1244 %rdx = add i8 %op2, %op11245 ret i8 %rdx1246}1247 1248; Check the incoming values of pn and pn2.1249 1250; Don't reassociate if op1 doesn't recurse to pn.1251define i8 @no_add_op1_to_pn(i1 %c, i32 %n) {1252; CHECK-LABEL: define i8 @no_add_op1_to_pn(1253; CHECK-SAME: i1 [[C:%.*]], i32 [[N:%.*]]) {1254; CHECK-NEXT: [[ENTRY:.*]]:1255; CHECK-NEXT: br label %[[BODY:.*]]1256; CHECK: [[BODY]]:1257; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]1258; CHECK-NEXT: [[PN:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[OP2:%.*]], %[[BODY]] ]1259; CHECK-NEXT: [[PN2:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[OP2]], %[[BODY]] ]1260; CHECK-NEXT: [[OP2]] = add i8 [[PN2]], 31261; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 11262; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]1263; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]1264; CHECK: [[EXIT]]:1265; CHECK-NEXT: [[OP1:%.*]] = add i8 [[PN]], 21266; CHECK-NEXT: [[RDX:%.*]] = add i8 [[OP2]], [[OP1]]1267; CHECK-NEXT: ret i8 [[RDX]]1268;1269entry:1270 br label %body1271 1272body:1273 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]1274 %pn = phi i8 [ 0, %entry ], [ %op2, %body ]1275 %pn2 = phi i8 [ 1, %entry ], [ %op2, %body ]1276 %op1 = add i8 %pn, 21277 %op2 = add i8 %pn2, 31278 %i.next = add nuw nsw i32 %i, 11279 %cmp = icmp eq i32 %i.next, %n1280 br i1 %cmp, label %exit, label %body1281 1282exit:1283 %rdx = add i8 %op2, %op11284 ret i8 %rdx1285}1286 1287; Don't reassociate if op2 doesn't recurse to pn2.1288define i8 @no_add_op2_to_pn2(i1 %c, i32 %n) {1289; CHECK-LABEL: define i8 @no_add_op2_to_pn2(1290; CHECK-SAME: i1 [[C:%.*]], i32 [[N:%.*]]) {1291; CHECK-NEXT: [[ENTRY:.*]]:1292; CHECK-NEXT: br label %[[BODY:.*]]1293; CHECK: [[BODY]]:1294; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]1295; CHECK-NEXT: [[PN:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[OP1:%.*]], %[[BODY]] ]1296; CHECK-NEXT: [[PN2:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[OP1]], %[[BODY]] ]1297; CHECK-NEXT: [[OP1]] = add i8 [[PN]], 21298; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 11299; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]1300; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]1301; CHECK: [[EXIT]]:1302; CHECK-NEXT: [[OP2:%.*]] = add i8 [[PN2]], 31303; CHECK-NEXT: [[RDX:%.*]] = add i8 [[OP2]], [[OP1]]1304; CHECK-NEXT: ret i8 [[RDX]]1305;1306entry:1307 br label %body1308 1309body:1310 %i = phi i32 [ 0, %entry ], [ %i.next, %body ]1311 %pn = phi i8 [ 0, %entry ], [ %op1, %body ]1312 %pn2 = phi i8 [ 1, %entry ], [ %op1, %body ]1313 %op1 = add i8 %pn, 21314 %op2 = add i8 %pn2, 31315 %i.next = add nuw nsw i32 %i, 11316 %cmp = icmp eq i32 %i.next, %n1317 br i1 %cmp, label %exit, label %body1318 1319exit:1320 %rdx = add i8 %op2, %op11321 ret i8 %rdx1322}1323 1324; Don't reassociate if the phis have more than two incoming values.1325define i8 @no_add_phis_more_incoming_values(i1 %c, i32 %n) {1326; CHECK-LABEL: define i8 @no_add_phis_more_incoming_values(1327; CHECK-SAME: i1 [[C:%.*]], i32 [[N:%.*]]) {1328; CHECK-NEXT: [[ENTRY:.*]]:1329; CHECK-NEXT: br i1 [[C]], label %[[BODY:.*]], label %[[OTHER:.*]]1330; CHECK: [[OTHER]]:1331; CHECK-NEXT: br label %[[BODY]]1332; CHECK: [[BODY]]:1333; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ 1, %[[OTHER]] ], [ [[I_NEXT:%.*]], %[[BODY]] ]1334; CHECK-NEXT: [[PN:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ 0, %[[OTHER]] ], [ [[OP1:%.*]], %[[BODY]] ]1335; CHECK-NEXT: [[PN2:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ 1, %[[OTHER]] ], [ [[OP2:%.*]], %[[BODY]] ]1336; CHECK-NEXT: [[OP1]] = add i8 [[PN]], 21337; CHECK-NEXT: [[OP2]] = add i8 [[PN2]], 31338; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 11339; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]1340; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]1341; CHECK: [[EXIT]]:1342; CHECK-NEXT: [[RDX:%.*]] = add i8 [[OP2]], [[OP1]]1343; CHECK-NEXT: ret i8 [[RDX]]1344;1345entry:1346 br i1 %c, label %body, label %other1347 1348other:1349 br label %body1350 1351body:1352 %i = phi i32 [ 0, %entry ], [ 1, %other ], [ %i.next, %body ]1353 %pn = phi i8 [ 0, %entry ], [ 0, %other ], [ %op1, %body ]1354 %pn2 = phi i8 [ 1, %entry ], [ 1, %other ], [ %op2, %body ]1355 %op1 = add i8 %pn, 21356 %op2 = add i8 %pn2, 31357 %i.next = add nuw nsw i32 %i, 11358 %cmp = icmp eq i32 %i.next, %n1359 br i1 %cmp, label %exit, label %body1360 1361exit:1362 %rdx = add i8 %op2, %op11363 ret i8 %rdx1364}1365 1366; Don't reassociate if the ops span different blocks.1367define i8 @no_add_op_multi_block(i32 %n) {1368; CHECK-LABEL: define i8 @no_add_op_multi_block(1369; CHECK-SAME: i32 [[N:%.*]]) {1370; CHECK-NEXT: [[ENTRY:.*]]:1371; CHECK-NEXT: br label %[[BODY:.*]]1372; CHECK: [[BODY]]:1373; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[OTHER:.*]] ]1374; CHECK-NEXT: [[PN:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[OP1:%.*]], %[[OTHER]] ]1375; CHECK-NEXT: [[PN2:%.*]] = phi i8 [ 1, %[[ENTRY]] ], [ [[OP2:%.*]], %[[OTHER]] ]1376; CHECK-NEXT: [[OP1]] = add i8 [[PN]], 21377; CHECK-NEXT: br label %[[OTHER]]1378; CHECK: [[OTHER]]:1379; CHECK-NEXT: [[OP2]] = add i8 [[PN2]], 31380; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 11381; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]1382; CHECK-NEXT: br i1 [[CMP]], label %[[EXIT:.*]], label %[[BODY]]1383; CHECK: [[EXIT]]:1384; CHECK-NEXT: [[RDX:%.*]] = add i8 [[OP2]], [[OP1]]1385; CHECK-NEXT: ret i8 [[RDX]]1386;1387entry:1388 br label %body1389 1390body:1391 %i = phi i32 [ 0, %entry ], [ %i.next, %other ]1392 %pn = phi i8 [ 0, %entry ], [ %op1, %other ]1393 %pn2 = phi i8 [ 1, %entry ], [ %op2, %other ]1394 %op1 = add i8 %pn, 21395 br label %other1396 1397other:1398 %op2 = add i8 %pn2, 31399 %i.next = add nuw nsw i32 %i, 11400 %cmp = icmp eq i32 %i.next, %n1401 br i1 %cmp, label %exit, label %body1402 1403exit:1404 %rdx = add i8 %op2, %op11405 ret i8 %rdx1406}1407 1408declare void @use(i8)1409