summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Analysis
diff options
context:
space:
mode:
authorJames Molloy <james.molloy@arm.com>2015-05-15 16:04:50 +0000
committerJames Molloy <james.molloy@arm.com>2015-05-15 16:04:50 +0000
commit270ef8c28b427bbd2be76b06ff53862bf8575146 (patch)
treed96e3ba2e2e3a1fa0ae5b8759666873e78cf6225 /llvm/lib/Analysis
parenteeb2fa98774159100263f927c2b44b674ffd9e96 (diff)
downloadbcm5719-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.cpp70
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);
+}
OpenPOWER on IntegriCloud