diff options
author | Sanjay Patel <spatel@rotateright.com> | 2018-11-05 21:51:39 +0000 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2018-11-05 21:51:39 +0000 |
commit | 1440107821cf72a1ce15ed626c9c17460e699d8e (patch) | |
tree | b2975fc97d8af4ca79b0eb5e96ab9577c3a1b102 /llvm/lib | |
parent | 72c2d355b789d73b7815fab64b12e7c68d1f3a1c (diff) | |
download | bcm5719-llvm-1440107821cf72a1ce15ed626c9c17460e699d8e.tar.gz bcm5719-llvm-1440107821cf72a1ce15ed626c9c17460e699d8e.zip |
[InstSimplify] fold select (fcmp X, Y), X, Y
This is NFCI for InstCombine because it calls InstSimplify,
so I left the tests for this transform there. As noted in
the code comment, we can allow this fold more often by using
FMF and/or value tracking.
llvm-svn: 346169
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Analysis/InstructionSimplify.cpp | 31 | ||||
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | 50 |
2 files changed, 31 insertions, 50 deletions
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index db929aa7059..fd6f4ba476e 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -3874,6 +3874,34 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal, return nullptr; } +/// Try to simplify a select instruction when its condition operand is a +/// floating-point comparison. +static Value *simplifySelectWithFCmp(Value *Cond, Value *T, Value *F) { + FCmpInst::Predicate Pred; + if (!match(Cond, m_FCmp(Pred, m_Specific(T), m_Specific(F))) && + !match(Cond, m_FCmp(Pred, m_Specific(F), m_Specific(T)))) + return nullptr; + + // TODO: The transform may not be valid with -0.0. An incomplete way of + // testing for that possibility is to check if at least one operand is a + // non-zero constant. + const APFloat *C; + if ((match(T, m_APFloat(C)) && C->isNonZero()) || + (match(F, m_APFloat(C)) && C->isNonZero())) { + // (T == F) ? T : F --> F + // (F == T) ? T : F --> F + if (Pred == FCmpInst::FCMP_OEQ) + return F; + + // (T != F) ? T : F --> T + // (F != T) ? T : F --> T + if (Pred == FCmpInst::FCMP_UNE) + return T; + } + + return nullptr; +} + /// Given operands for a SelectInst, see if we can fold the result. /// If not, this returns null. static Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal, @@ -3910,6 +3938,9 @@ static Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal, simplifySelectWithICmpCond(Cond, TrueVal, FalseVal, Q, MaxRecurse)) return V; + if (Value *V = simplifySelectWithFCmp(Cond, TrueVal, FalseVal)) + return V; + if (Value *V = foldSelectWithBinaryOp(Cond, TrueVal, FalseVal)) return V; diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 724662f0128..88a72bb8eb5 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -1660,31 +1660,6 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) { // See if we are selecting two values based on a comparison of the two values. if (FCmpInst *FCI = dyn_cast<FCmpInst>(CondVal)) { if (FCI->getOperand(0) == TrueVal && FCI->getOperand(1) == FalseVal) { - // Transform (X == Y) ? X : Y -> Y - if (FCI->getPredicate() == FCmpInst::FCMP_OEQ) { - // This is not safe in general for floating point: - // consider X== -0, Y== +0. - // It becomes safe if either operand is a nonzero constant. - ConstantFP *CFPt, *CFPf; - if (((CFPt = dyn_cast<ConstantFP>(TrueVal)) && - !CFPt->getValueAPF().isZero()) || - ((CFPf = dyn_cast<ConstantFP>(FalseVal)) && - !CFPf->getValueAPF().isZero())) - return replaceInstUsesWith(SI, FalseVal); - } - // Transform (X une Y) ? X : Y -> X - if (FCI->getPredicate() == FCmpInst::FCMP_UNE) { - // This is not safe in general for floating point: - // consider X== -0, Y== +0. - // It becomes safe if either operand is a nonzero constant. - ConstantFP *CFPt, *CFPf; - if (((CFPt = dyn_cast<ConstantFP>(TrueVal)) && - !CFPt->getValueAPF().isZero()) || - ((CFPf = dyn_cast<ConstantFP>(FalseVal)) && - !CFPf->getValueAPF().isZero())) - return replaceInstUsesWith(SI, TrueVal); - } - // Canonicalize to use ordered comparisons by swapping the select // operands. // @@ -1703,31 +1678,6 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) { // NOTE: if we wanted to, this is where to detect MIN/MAX } else if (FCI->getOperand(0) == FalseVal && FCI->getOperand(1) == TrueVal){ - // Transform (X == Y) ? Y : X -> X - if (FCI->getPredicate() == FCmpInst::FCMP_OEQ) { - // This is not safe in general for floating point: - // consider X== -0, Y== +0. - // It becomes safe if either operand is a nonzero constant. - ConstantFP *CFPt, *CFPf; - if (((CFPt = dyn_cast<ConstantFP>(TrueVal)) && - !CFPt->getValueAPF().isZero()) || - ((CFPf = dyn_cast<ConstantFP>(FalseVal)) && - !CFPf->getValueAPF().isZero())) - return replaceInstUsesWith(SI, FalseVal); - } - // Transform (X une Y) ? Y : X -> Y - if (FCI->getPredicate() == FCmpInst::FCMP_UNE) { - // This is not safe in general for floating point: - // consider X== -0, Y== +0. - // It becomes safe if either operand is a nonzero constant. - ConstantFP *CFPt, *CFPf; - if (((CFPt = dyn_cast<ConstantFP>(TrueVal)) && - !CFPt->getValueAPF().isZero()) || - ((CFPf = dyn_cast<ConstantFP>(FalseVal)) && - !CFPf->getValueAPF().isZero())) - return replaceInstUsesWith(SI, TrueVal); - } - // Canonicalize to use ordered comparisons by swapping the select // operands. // |