Index: lib/Transforms/Scalar/LoopUnswitch.cpp =================================================================== --- lib/Transforms/Scalar/LoopUnswitch.cpp +++ lib/Transforms/Scalar/LoopUnswitch.cpp @@ -415,8 +415,32 @@ } if (BinaryOperator *BO = dyn_cast(Cond)) - if (BO->getOpcode() == Instruction::And || - BO->getOpcode() == Instruction::Or) { + // Do not walk up the and/or chain for values with more than + // 1 bit, beause we can not reliably find a value that will + // simplify the original and new loops. + // + // e.g. + // + // %and = and i32 %loop_invariant, %loop_variant + // switch i32 %and, label %sw.default [ + // i32 11, label %sw.bb + // i32 12, label %sw.bb1 + // ] + // + // Once we pick a value to unswitch, we still wont be able to simplified + // the %and instruction in the original loop, then we do not know what + // value we have unswitched out of the original loop. As a result, we + // end up unswitching the original loop again ... + // + // In case this is an instruction working on 1 bit value, we will + // be able to simplify the %and to either a constant or + // loop-variant value. In both cases, it will not get unswitched again. + // + // This will still allow us to simplify switch(i1), even though it + // probably should be converted to an if-else at this point. + if (BO->getType()->isIntegerTy(1) && + (BO->getOpcode() == Instruction::And || + BO->getOpcode() == Instruction::Or)) { // If either the left or right side is invariant, we can unswitch on this, // which will cause the branch to go away in one loop and the condition to // simplify in the other one. @@ -651,15 +675,22 @@ // FIXME: scan for a case with a non-critical edge? Constant *UnswitchVal = nullptr; - // Do not process same value again and again. - // At this point we have some cases already unswitched and - // some not yet unswitched. Let's find the first not yet unswitched one. - for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end(); - i != e; ++i) { - Constant *UnswitchValCandidate = i.getCaseValue(); - if (!BranchesInfo.isUnswitched(SI, UnswitchValCandidate)) { - UnswitchVal = UnswitchValCandidate; - break; + // If this is a cond we get by walking up the chain, it must be a 1 bit value. + if (LoopCond != SI->getCondition()) { + assert(LoopCond->getType()->isIntegerTy(1) && + "Loop condition must be a 1 bit value"); + UnswitchVal = ConstantInt::getTrue(Context); + } else { + // Do not process same value again and again. + // At this point we have some cases already unswitched and + // some not yet unswitched. Let's find the first not yet unswitched one. + for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end(); + i != e; ++i) { + Constant *UnswitchValCandidate = i.getCaseValue(); + if (!BranchesInfo.isUnswitched(SI, UnswitchValCandidate)) { + UnswitchVal = UnswitchValCandidate; + break; + } } } Index: test/Transforms/LoopUnswitch/basictest.ll =================================================================== --- test/Transforms/LoopUnswitch/basictest.ll +++ test/Transforms/LoopUnswitch/basictest.ll @@ -101,6 +101,87 @@ ; CHECK: } } +; Make sure we do not unswitch this loop, as we do not really know the +; right value for %a to unswitch on. +; +; CHECK: define void @and_i32_as_switch_input(i32 +; CHECK: entry: +; This is an indication that the loop has not been unswitched. +; CHECK-NOT: icmp +; CHECK: br +define void @and_i32_as_switch_input(i32 %a) #0 { +entry: + br label %for.body + +for.body: + %i = phi i32 [ 0, %entry ], [ %inc, %for.inc ] + %and = and i32 %a, %i + switch i32 %and, label %sw.default [ + i32 11, label %sw.bb + i32 12, label %sw.bb1 + ] + +sw.bb: + br label %sw.epilog + +sw.bb1: + br label %sw.epilog + +sw.default: + br label %sw.epilog + +sw.epilog: + br label %for.inc + +for.inc: + %inc = add nsw i32 %i, 1 + %cmp = icmp slt i32 %inc, 1024 + br i1 %cmp, label %for.body, label %for.end + +for.end: + ret void +} + +; Make sure we unswitch this loop. +; +; CHECK: define void @and_i1_as_switch_input(i1 +; CHECK: entry: +; This is an indication that the loop has been unswitched. +; CHECK: icmp +; CHECK: br +define void @and_i1_as_switch_input(i1 %a) #0 { +entry: + br label %for.body + +for.body: + %i = phi i32 [ 0, %entry ], [ %inc, %for.inc ] + %t = trunc i32 %i to i1 + %and = and i1 %a, %t + switch i1 %and, label %sw.default [ + i1 0, label %sw.bb + i1 1, label %sw.bb1 + ] + +sw.bb: + br label %sw.epilog + +sw.bb1: + br label %sw.epilog + +sw.default: + br label %sw.epilog + +sw.epilog: + br label %for.inc + +for.inc: + %inc = add nsw i32 %i, 1 + %cmp = icmp slt i32 %inc, 1024 + br i1 %cmp, label %for.body, label %for.end + +for.end: + ret void +} declare void @incf() noreturn declare void @decf() noreturn