Please use GitHub pull requests for new patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
Show First 20 Lines • Show All 2,922 Lines • ▼ Show 20 Lines | if ((Cmp0 == TrueVal && Cmp1 == FalseVal) || | ||||
} | } | ||||
// NOTE: if we wanted to, this is where to detect MIN/MAX | // NOTE: if we wanted to, this is where to detect MIN/MAX | ||||
} | } | ||||
} | } | ||||
// Canonicalize select with fcmp to fabs(). -0.0 makes this tricky. We need | // Canonicalize select with fcmp to fabs(). -0.0 makes this tricky. We need | ||||
// fast-math-flags (nsz) or fsub with +0.0 (not fneg) for this to work. | // fast-math-flags (nsz) or fsub with +0.0 (not fneg) for this to work. | ||||
// (X <= +/-0.0) ? (0.0 - X) : X --> fabs(X) | // (X <= +/-0.0) ? (0.0 - X) : X --> fabs(X) | ||||
if (match(CondVal, m_FCmp(Pred, m_Specific(FalseVal), m_AnyZeroFP())) && | if (match(CondVal, m_FCmp(Pred, m_Specific(FalseVal), m_AnyZeroFP())) && | ||||
spatel: Can we remove this match as a preliminary cleanup? | |||||
match(TrueVal, m_FSub(m_PosZeroFP(), m_Specific(FalseVal))) && | match(TrueVal, m_FSub(m_PosZeroFP(), m_Specific(FalseVal))) && | ||||
(Pred == FCmpInst::FCMP_OLE || Pred == FCmpInst::FCMP_ULE)) { | (Pred == FCmpInst::FCMP_OLE || Pred == FCmpInst::FCMP_ULE)) { | ||||
Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, FalseVal, &SI); | Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, FalseVal, &SI); | ||||
return replaceInstUsesWith(SI, Fabs); | return replaceInstUsesWith(SI, Fabs); | ||||
} | } | ||||
// (X > +/-0.0) ? X : (0.0 - X) --> fabs(X) | // (X > +/-0.0) ? X : (0.0 - X) --> fabs(X) | ||||
if (match(CondVal, m_FCmp(Pred, m_Specific(TrueVal), m_AnyZeroFP())) && | if (match(CondVal, m_FCmp(Pred, m_Specific(TrueVal), m_AnyZeroFP())) && | ||||
match(FalseVal, m_FSub(m_PosZeroFP(), m_Specific(TrueVal))) && | match(FalseVal, m_FSub(m_PosZeroFP(), m_Specific(TrueVal))) && | ||||
(Pred == FCmpInst::FCMP_OGT || Pred == FCmpInst::FCMP_UGT)) { | (Pred == FCmpInst::FCMP_OGT || Pred == FCmpInst::FCMP_UGT)) { | ||||
Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, TrueVal, &SI); | Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, TrueVal, &SI); | ||||
return replaceInstUsesWith(SI, Fabs); | return replaceInstUsesWith(SI, Fabs); | ||||
} | } | ||||
// With nnan and nsz: | // (X < +/-0.0) ? X : (0.0 - X) --> (0.0 - fabs(X)) | ||||
// With nsz: | |||||
// (X < +/-0.0) ? X : -X --> -fabs(X) | |||||
if (match(CondVal, m_FCmp(Pred, m_Specific(TrueVal), m_AnyZeroFP())) && | |||||
(match(FalseVal, m_FSub(m_PosZeroFP(), m_Specific(TrueVal))) || | |||||
(match(FalseVal, m_FNeg(m_Specific(TrueVal))) && | |||||
cast<Instruction>(FalseVal)->hasNoSignedZeros())) && | |||||
(Pred == FCmpInst::FCMP_OLT || Pred == FCmpInst::FCMP_ULT)) { | |||||
Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, TrueVal, &SI); | |||||
return BinaryOperator::CreateFSubFMF(ConstantFP::get(Fabs->getType(), 0.0), | |||||
Fabs, cast<Instruction>(FalseVal)); | |||||
} | |||||
// With nsz: | |||||
// (X < +/-0.0) ? -X : X --> fabs(X) | // (X < +/-0.0) ? -X : X --> fabs(X) | ||||
// (X <= +/-0.0) ? -X : X --> fabs(X) | // (X <= +/-0.0) ? -X : X --> fabs(X) | ||||
if (match(CondVal, m_FCmp(Pred, m_Specific(FalseVal), m_AnyZeroFP())) && | if (match(CondVal, m_FCmp(Pred, m_Specific(FalseVal), m_AnyZeroFP())) && | ||||
Can we remove this match as a preliminary cleanup? spatel: Can we remove this match as a preliminary cleanup? | |||||
match(TrueVal, m_FNeg(m_Specific(FalseVal))) && SI.hasNoSignedZeros() && | match(TrueVal, m_FNeg(m_Specific(FalseVal))) && SI.hasNoSignedZeros() && | ||||
(Pred == FCmpInst::FCMP_OLT || Pred == FCmpInst::FCMP_OLE || | (Pred == FCmpInst::FCMP_OLT || Pred == FCmpInst::FCMP_OLE || | ||||
Pred == FCmpInst::FCMP_ULT || Pred == FCmpInst::FCMP_ULE)) { | Pred == FCmpInst::FCMP_ULT || Pred == FCmpInst::FCMP_ULE)) { | ||||
Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, FalseVal, &SI); | Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, FalseVal, &SI); | ||||
return replaceInstUsesWith(SI, Fabs); | return replaceInstUsesWith(SI, Fabs); | ||||
} | } | ||||
// With nnan and nsz: | // With nsz: | ||||
// (X > +/-0.0) ? X : -X --> fabs(X) | // (X > +/-0.0) ? X : -X --> fabs(X) | ||||
// (X >= +/-0.0) ? X : -X --> fabs(X) | // (X >= +/-0.0) ? X : -X --> fabs(X) | ||||
if (match(CondVal, m_FCmp(Pred, m_Specific(TrueVal), m_AnyZeroFP())) && | if (match(CondVal, m_FCmp(Pred, m_Specific(TrueVal), m_AnyZeroFP())) && | ||||
match(FalseVal, m_FNeg(m_Specific(TrueVal))) && SI.hasNoSignedZeros() && | match(FalseVal, m_FNeg(m_Specific(TrueVal))) && SI.hasNoSignedZeros() && | ||||
(Pred == FCmpInst::FCMP_OGT || Pred == FCmpInst::FCMP_OGE || | (Pred == FCmpInst::FCMP_OGT || Pred == FCmpInst::FCMP_OGE || | ||||
Pred == FCmpInst::FCMP_UGT || Pred == FCmpInst::FCMP_UGE)) { | Pred == FCmpInst::FCMP_UGT || Pred == FCmpInst::FCMP_UGE)) { | ||||
Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, TrueVal, &SI); | Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, TrueVal, &SI); | ||||
return replaceInstUsesWith(SI, Fabs); | return replaceInstUsesWith(SI, Fabs); | ||||
} | } | ||||
// With nsz: | |||||
// (X < +/-0.0) ? X : -X --> -fabs(X) | |||||
// (X <= +/-0.0) ? X : -X --> -fabs(X) | |||||
if (match(CondVal, m_FCmp(Pred, m_Specific(TrueVal), m_AnyZeroFP())) && | |||||
match(FalseVal, m_FNeg(m_Specific(TrueVal))) && SI.hasNoSignedZeros() && | |||||
(Pred == FCmpInst::FCMP_OLT || Pred == FCmpInst::FCMP_OLE || | |||||
Pred == FCmpInst::FCMP_ULT || Pred == FCmpInst::FCMP_ULE)) { | |||||
Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, TrueVal, &SI); | |||||
return UnaryOperator::CreateFNegFMF(Fabs, cast<Instruction>(FalseVal)); | |||||
} | |||||
// With nsz: | |||||
// (X > +/-0.0) ? -X : X --> -fabs(X) | |||||
// (X >= +/-0.0) ? -X : X --> -fabs(X) | |||||
if (match(CondVal, m_FCmp(Pred, m_Specific(FalseVal), m_AnyZeroFP())) && | |||||
match(TrueVal, m_FNeg(m_Specific(FalseVal))) && SI.hasNoSignedZeros() && | |||||
(Pred == FCmpInst::FCMP_OGT || Pred == FCmpInst::FCMP_OGE || | |||||
Pred == FCmpInst::FCMP_UGT || Pred == FCmpInst::FCMP_UGE)) { | |||||
Value *Fabs = Builder.CreateUnaryIntrinsic(Intrinsic::fabs, FalseVal, &SI); | |||||
return UnaryOperator::CreateFNegFMF(Fabs, cast<Instruction>(TrueVal)); | |||||
} | |||||
// See if we are selecting two values based on a comparison of the two values. | // See if we are selecting two values based on a comparison of the two values. | ||||
if (ICmpInst *ICI = dyn_cast<ICmpInst>(CondVal)) | if (ICmpInst *ICI = dyn_cast<ICmpInst>(CondVal)) | ||||
if (Instruction *Result = foldSelectInstWithICmp(SI, ICI)) | if (Instruction *Result = foldSelectInstWithICmp(SI, ICI)) | ||||
return Result; | return Result; | ||||
if (Instruction *Add = foldAddSubSelect(SI, Builder)) | if (Instruction *Add = foldAddSubSelect(SI, Builder)) | ||||
return Add; | return Add; | ||||
▲ Show 20 Lines • Show All 338 Lines • Show Last 20 Lines |
Can we remove this match as a preliminary cleanup?