diff options
author | James Molloy <james.molloy@arm.com> | 2015-05-15 16:04:50 +0000 |
---|---|---|
committer | James Molloy <james.molloy@arm.com> | 2015-05-15 16:04:50 +0000 |
commit | 270ef8c28b427bbd2be76b06ff53862bf8575146 (patch) | |
tree | d96e3ba2e2e3a1fa0ae5b8759666873e78cf6225 /llvm/lib/Analysis | |
parent | eeb2fa98774159100263f927c2b44b674ffd9e96 (diff) | |
download | bcm5719-llvm-270ef8c28b427bbd2be76b06ff53862bf8575146.tar.gz bcm5719-llvm-270ef8c28b427bbd2be76b06ff53862bf8575146.zip |
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.
llvm-svn: 237452
Diffstat (limited to 'llvm/lib/Analysis')
-rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 70 |
1 files changed, 56 insertions, 14 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 21d9e2e7f69..c70a8087d86 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -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); +} |