Index: lib/Transforms/Scalar/LoopUnswitch.cpp =================================================================== --- lib/Transforms/Scalar/LoopUnswitch.cpp +++ lib/Transforms/Scalar/LoopUnswitch.cpp @@ -47,6 +47,7 @@ #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/InstrTypes.h" #include "llvm/IR/Module.h" #include "llvm/IR/MDBuilder.h" #include "llvm/Support/CommandLine.h" @@ -255,6 +256,11 @@ TerminatorInst *TI); void SimplifyCode(std::vector &Worklist, Loop *L); + + /// Given that the condition is not equal to \p Val. Simplify instructions + /// in the loop. + Value *SimplifyInstructionWithInverse(Instruction *Inst, Value *Cond, + Constant *Val); }; } @@ -1245,6 +1251,7 @@ return; } + // Otherwise, we don't know the precise value of LIC, but we do know that it // is certainly NOT "Val". As such, simplify any uses in the loop that we // can. This case occurs when we unswitch switch statements. @@ -1255,8 +1262,18 @@ Worklist.push_back(UI); - // TODO: We could do other simplifications, for example, turning - // 'icmp eq LIC, Val' -> false. + // At this point, we know LIC is definitely not Val. Try to use some simple + // logic to simplify the user. + // + // We should have checked that the UI is part of the loop at this point. + assert(L->contains(UI) && "Illegal to simplify instructions outside the loop"); + if (Value *Replacement = SimplifyInstructionWithInverse(UI, LIC, Val)) { + // This in-loop instruction has been simplified w.r.t. its context, + // i.e. LIC != Val, make sure we propagate its replacement value to + // all its users. + ReplaceUsesOfWith(UI, Replacement, Worklist, L, LPM); + continue; + } // If we know that LIC is not Val, use this info to simplify code. SwitchInst *SI = dyn_cast(UI); @@ -1397,3 +1414,32 @@ } } } + +/// A list of simple simplifications we can do given the information that +/// \p Cond is definitely not equal to \p IV. +Value *LoopUnswitch::SimplifyInstructionWithInverse(Instruction *Inst, + Value *Cond, + Constant *Val) { + // This is an integer comparison instruction and its operands are Cond + // and Val. And we know Cond is definitely not equal to Val, try to + // simplify it. + ICmpInst *CI = dyn_cast(Inst); + if (CI && CI->isEquality()) { + Value *Op0 = CI->getOperand(0); + Value *Op1 = CI->getOperand(1); + if ((Op0 == Cond && Op1 == Val) || (Op0 == Val && Op1 == Cond)) { + LLVMContext &Ctx = Inst->getContext(); + if (CI->getPredicate() == CmpInst::ICMP_EQ) + return ConstantInt::getFalse(Ctx); + else + return ConstantInt::getTrue(Ctx); + } + } + + // FIXME: there are other simplification opprotunities. e.g. comparison + // with floating points, or try to propagate its non-valness through other + // instructions such as subtraction. + // + // Do not know how to simplify instruction. + return nullptr; +} Index: test/Transforms/LoopUnswitch/simplify-with-inverse.ll =================================================================== --- /dev/null +++ test/Transforms/LoopUnswitch/simplify-with-inverse.ll @@ -0,0 +1,57 @@ +; RUN: opt < %s -loop-unswitch -verify-loop-info -S < %s 2>&1 | FileCheck %s + +; There are 1 case and 1 default case in the switch. after we unswitch, we know the +; %a is definitely not 0 in one of the unswitched loop, make sure we take advantage +; of that and simplify the branches in the loop. +; +; CHECK: define void @simplify_with_inverse( + +; This is the loop in which we know %a is definitely 0. +; CHECK: sw.bb.us: +; CHECK: br i1 true, label %if.then.us, label %if.end.us + +; This is the loop in which we do not know what %a is but we know %a is definitely NOT 0. +; Make sure we use that information to simplify. +; CHECK: sw.bb.split: +; CHECK: br i1 false, label %if.then, label %if.end + +define void @simplify_with_inverse(i32 %a) #0 { +entry: + br label %for.cond + +for.cond: + %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ] + %cmp = icmp slt i32 %i.0, 1024 + br i1 %cmp, label %for.body, label %for.end + +for.body: + switch i32 %a, label %sw.default [ + i32 0, label %sw.bb + ] + +sw.bb: + %cmp1 = icmp eq i32 %a, 0 + br i1 %cmp1, label %if.then, label %if.end + +if.then: + call void (...) @bar() + br label %if.end + +if.end: + br label %sw.epilog + +sw.default: + br label %sw.epilog + +sw.epilog: + br label %for.inc + +for.inc: + %inc = add nsw i32 %i.0, 1 + br label %for.cond + +for.end: + ret void +} + +declare void @bar(...)