Allow min/max detection to see through casts.

This teaches the min/max idiom detector in ValueTracking to see through
casts such as SExt/ZExt/Trunc. SCEV can already do this, so we're bringing
non-SCEV analyses up to the same level.

The returned LHS/RHS will not match the type of the original SelectInst
any more, so a CastOp is returned too to inform the caller how to
convert to the SelectInst's type.

No in-tree users yet; this will be used by InstCombine in a followup.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@237452 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
James Molloy
2015-05-15 16:04:50 +00:00
parent 975307cc50
commit eb9033d963
2 changed files with 72 additions and 15 deletions
+56 -14
View File
@@ -3220,20 +3220,10 @@ OverflowResult llvm::computeOverflowForUnsignedAdd(Value *LHS, Value *RHS,
return OverflowResult::MayOverflow;
}
SelectPatternFlavor llvm::matchSelectPattern(Value *V,
Value *&LHS, Value *&RHS) {
SelectInst *SI = dyn_cast<SelectInst>(V);
if (!SI) return SPF_UNKNOWN;
ICmpInst *ICI = dyn_cast<ICmpInst>(SI->getCondition());
if (!ICI) return SPF_UNKNOWN;
ICmpInst::Predicate Pred = ICI->getPredicate();
Value *CmpLHS = ICI->getOperand(0);
Value *CmpRHS = ICI->getOperand(1);
Value *TrueVal = SI->getTrueValue();
Value *FalseVal = SI->getFalseValue();
static SelectPatternFlavor matchSelectPattern(ICmpInst::Predicate Pred,
Value *CmpLHS, Value *CmpRHS,
Value *TrueVal, Value *FalseVal,
Value *&LHS, Value *&RHS) {
LHS = CmpLHS;
RHS = CmpRHS;
@@ -3300,3 +3290,55 @@ SelectPatternFlavor llvm::matchSelectPattern(Value *V,
return SPF_UNKNOWN;
}
static Constant *lookThroughCast(ICmpInst *CmpI, Value *V1, Value *V2,
Instruction::CastOps *CastOp) {
CastInst *CI = dyn_cast<CastInst>(V1);
Constant *C = dyn_cast<Constant>(V2);
if (!CI || !C)
return nullptr;
*CastOp = CI->getOpcode();
if ((isa<SExtInst>(CI) && CmpI->isSigned()) ||
(isa<ZExtInst>(CI) && CmpI->isUnsigned()))
return ConstantExpr::getTrunc(C, CI->getSrcTy());
if (isa<TruncInst>(CI))
return ConstantExpr::getIntegerCast(C, CI->getSrcTy(), CmpI->isSigned());
return nullptr;
}
SelectPatternFlavor llvm::matchSelectPattern(Value *V,
Value *&LHS, Value *&RHS,
Instruction::CastOps *CastOp) {
SelectInst *SI = dyn_cast<SelectInst>(V);
if (!SI) return SPF_UNKNOWN;
ICmpInst *CmpI = dyn_cast<ICmpInst>(SI->getCondition());
if (!CmpI) return SPF_UNKNOWN;
ICmpInst::Predicate Pred = CmpI->getPredicate();
Value *CmpLHS = CmpI->getOperand(0);
Value *CmpRHS = CmpI->getOperand(1);
Value *TrueVal = SI->getTrueValue();
Value *FalseVal = SI->getFalseValue();
// Bail out early.
if (CmpI->isEquality())
return SPF_UNKNOWN;
// Deal with type mismatches.
if (CastOp && CmpLHS->getType() != TrueVal->getType()) {
if (Constant *C = lookThroughCast(CmpI, TrueVal, FalseVal, CastOp))
return ::matchSelectPattern(Pred, CmpLHS, CmpRHS,
cast<CastInst>(TrueVal)->getOperand(0), C,
LHS, RHS);
if (Constant *C = lookThroughCast(CmpI, FalseVal, TrueVal, CastOp))
return ::matchSelectPattern(Pred, CmpLHS, CmpRHS,
C, cast<CastInst>(FalseVal)->getOperand(0),
LHS, RHS);
}
return ::matchSelectPattern(Pred, CmpLHS, CmpRHS, TrueVal, FalseVal,
LHS, RHS);
}