mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-24 07:01:35 +00:00
LoopUnswitch - Simplify based on known not to a be constant.
Summary: In case we do not know what the condition is in an unswitched loop, but we know its definitely NOT a known constant. We can perform simplifcations based on this information. Reviewers: sanjoy, hfinkel, chenli, efriedma Reviewed By: efriedma Subscribers: david2050, llvm-commits, mzolotukhin Differential Revision: https://reviews.llvm.org/D28968 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@296041 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b7b23a945d
commit
3addda9e5e
@ -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"
|
||||
@ -235,6 +236,11 @@ namespace {
|
||||
TerminatorInst *TI);
|
||||
|
||||
void SimplifyCode(std::vector<Instruction*> &Worklist, Loop *L);
|
||||
|
||||
/// Given that the Invariant is not equal to Val. Simplify instructions
|
||||
/// in the loop.
|
||||
Value *SimplifyInstructionWithNotEqual(Instruction *Inst, Value *Invariant,
|
||||
Constant *Val);
|
||||
};
|
||||
}
|
||||
|
||||
@ -1218,10 +1224,21 @@ void LoopUnswitch::RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC,
|
||||
if (!UI || !L->contains(UI))
|
||||
continue;
|
||||
|
||||
Worklist.push_back(UI);
|
||||
// At this point, we know LIC is definitely not Val. Try to use some simple
|
||||
// logic to simplify the user w.r.t. to the context.
|
||||
if (Value *Replacement = SimplifyInstructionWithNotEqual(UI, LIC, Val)) {
|
||||
if (LI->replacementPreservesLCSSAForm(UI, Replacement)) {
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: We could do other simplifications, for example, turning
|
||||
// 'icmp eq LIC, Val' -> false.
|
||||
// Unable to simplify with non-valueness, push it into the worklist so that
|
||||
// SimplifyCode can attempt to simplify it.
|
||||
Worklist.push_back(UI);
|
||||
|
||||
// If we know that LIC is not Val, use this info to simplify code.
|
||||
SwitchInst *SI = dyn_cast<SwitchInst>(UI);
|
||||
@ -1362,3 +1379,27 @@ void LoopUnswitch::SimplifyCode(std::vector<Instruction*> &Worklist, Loop *L) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Simple simplifications we can do given the information that Cond is
|
||||
/// definitely not equal to Val.
|
||||
Value *LoopUnswitch::SimplifyInstructionWithNotEqual(Instruction *Inst,
|
||||
Value *Invariant,
|
||||
Constant *Val) {
|
||||
// icmp eq cond, val -> false
|
||||
ICmpInst *CI = dyn_cast<ICmpInst>(Inst);
|
||||
if (CI && CI->isEquality()) {
|
||||
Value *Op0 = CI->getOperand(0);
|
||||
Value *Op1 = CI->getOperand(1);
|
||||
if ((Op0 == Invariant && Op1 == Val) || (Op0 == Val && Op1 == Invariant)) {
|
||||
LLVMContext &Ctx = Inst->getContext();
|
||||
if (CI->getPredicate() == CmpInst::ICMP_EQ)
|
||||
return ConstantInt::getFalse(Ctx);
|
||||
else
|
||||
return ConstantInt::getTrue(Ctx);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: there may be other opportunities, e.g. comparison with floating
|
||||
// point, or Invariant - Val != 0, etc.
|
||||
return nullptr;
|
||||
}
|
||||
|
58
test/Transforms/LoopUnswitch/simplify-with-nonvalness.ll
Normal file
58
test/Transforms/LoopUnswitch/simplify-with-nonvalness.ll
Normal file
@ -0,0 +1,58 @@
|
||||
; 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_nonvalness(
|
||||
|
||||
; 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.
|
||||
; The icmp eq i32 %a, 0 in one of the unswitched loop is simplified to false.
|
||||
; CHECK: sw.bb.split:
|
||||
; CHECK: br i1 false, label %if.then, label %if.end
|
||||
|
||||
define void @simplify_with_nonvalness(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(...)
|
Loading…
x
Reference in New Issue
Block a user