[JumpThreading] Teach jump threading how to analyze (and (cmp A, C1), (cmp A, C2)) after InstCombine has turned it into (cmp (add A, C3), C4)

Currently JumpThreading can use LazyValueInfo to analyze an 'and' or 'or' of compare if the compare is fed by a livein of a basic block. This can be used to to prove the condition can't be met for some predecessor and the jump from that predecessor can be moved to the false path of the condition.

But if the compare is something that InstCombine turns into an add and a single compare, it can't be analyzed because the livein is now an input to the add and not the compare.

This patch adds a new method to LVI to get a ConstantRange on an edge. Then we teach jump threading to detect the add livein feeding a compare and to get the ConstantRange and propagate it.

Differential Revision: https://reviews.llvm.org/D33262

llvm-svn: 306085
This commit is contained in:
Craig Topper 2017-06-23 05:41:35 +00:00
parent 7927996140
commit 2c20c42cb6
3 changed files with 68 additions and 0 deletions

View File

@ -93,6 +93,13 @@ public:
Constant *getConstantOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB, Constant *getConstantOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB,
Instruction *CxtI = nullptr); Instruction *CxtI = nullptr);
/// Return the ConstantRage constraint that is known to hold for the
/// specified value on the specified edge. This may be only be called
/// on integer-typed Values.
ConstantRange getConstantRangeOnEdge(Value *V, BasicBlock *FromBB,
BasicBlock *ToBB,
Instruction *CxtI = nullptr);
/// Inform the analysis cache that we have threaded an edge from /// Inform the analysis cache that we have threaded an edge from
/// PredBB to OldSucc to be from PredBB to NewSucc instead. /// PredBB to OldSucc to be from PredBB to NewSucc instead.
void threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc, BasicBlock *NewSucc); void threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc, BasicBlock *NewSucc);

View File

@ -1660,6 +1660,26 @@ Constant *LazyValueInfo::getConstantOnEdge(Value *V, BasicBlock *FromBB,
return nullptr; return nullptr;
} }
ConstantRange LazyValueInfo::getConstantRangeOnEdge(Value *V,
BasicBlock *FromBB,
BasicBlock *ToBB,
Instruction *CxtI) {
unsigned Width = V->getType()->getIntegerBitWidth();
const DataLayout &DL = FromBB->getModule()->getDataLayout();
LVILatticeVal Result =
getImpl(PImpl, AC, &DL, DT).getValueOnEdge(V, FromBB, ToBB, CxtI);
if (Result.isUndefined())
return ConstantRange(Width, /*isFullSet=*/false);
if (Result.isConstantRange())
return Result.getConstantRange();
// We represent ConstantInt constants as constant ranges but other kinds
// of integer constants, i.e. ConstantExpr will be tagged as constants
assert(!(Result.isConstant() && isa<ConstantInt>(Result.getConstant())) &&
"ConstantInt value must be represented as constantrange");
return ConstantRange(Width, /*isFullSet=*/true);
}
static LazyValueInfo::Tristate getPredicateResult(unsigned Pred, Constant *C, static LazyValueInfo::Tristate getPredicateResult(unsigned Pred, Constant *C,
const LVILatticeVal &Val, const LVILatticeVal &Val,
const DataLayout &DL, const DataLayout &DL,

View File

@ -25,6 +25,7 @@
#include "llvm/Analysis/Loads.h" #include "llvm/Analysis/Loads.h"
#include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/ValueTracking.h" #include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/DataLayout.h" #include "llvm/IR/DataLayout.h"
#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h" #include "llvm/IR/LLVMContext.h"
@ -635,6 +636,46 @@ bool JumpThreadingPass::ComputeValueKnownInPredecessors(
return !Result.empty(); return !Result.empty();
} }
// InstCombine can fold some forms of constant range checks into
// (icmp (add (x, C1)), C2). See if we have we have such a thing with
// x as a live-in.
{
using namespace PatternMatch;
Value *AddLHS;
ConstantInt *AddConst;
if (isa<ConstantInt>(CmpConst) &&
match(CmpLHS, m_Add(m_Value(AddLHS), m_ConstantInt(AddConst)))) {
if (!isa<Instruction>(AddLHS) ||
cast<Instruction>(AddLHS)->getParent() != BB) {
for (BasicBlock *P : predecessors(BB)) {
// If the value is known by LazyValueInfo to be a ConstantRange in
// a predecessor, use that information to try to thread this
// block.
ConstantRange CR = LVI->getConstantRangeOnEdge(
AddLHS, P, BB, CxtI ? CxtI : cast<Instruction>(CmpLHS));
// Propagate the range through the addition.
CR = CR.add(AddConst->getValue());
// Get the range where the compare returns true.
ConstantRange CmpRange = ConstantRange::makeExactICmpRegion(
Pred, cast<ConstantInt>(CmpConst)->getValue());
Constant *ResC;
if (CmpRange.contains(CR))
ResC = ConstantInt::getTrue(CmpType);
else if (CmpRange.inverse().contains(CR))
ResC = ConstantInt::getFalse(CmpType);
else
continue;
Result.push_back(std::make_pair(ResC, P));
}
return !Result.empty();
}
}
}
// Try to find a constant value for the LHS of a comparison, // Try to find a constant value for the LHS of a comparison,
// and evaluate it statically if we can. // and evaluate it statically if we can.
PredValueInfoTy LHSVals; PredValueInfoTy LHSVals;