mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-05 10:17:36 +00:00
[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
This commit is contained in:
parent
9440f65af8
commit
8184a89027
@ -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;
|
||||
|
||||
|
@ -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.
|
||||
//
|
||||
|
@ -5,9 +5,7 @@
|
||||
|
||||
define double @oeq(double %x) {
|
||||
; CHECK-LABEL: @oeq(
|
||||
; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[X:%.*]], 4.200000e+01
|
||||
; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], double [[X]], double 4.200000e+01
|
||||
; CHECK-NEXT: ret double [[COND]]
|
||||
; CHECK-NEXT: ret double 4.200000e+01
|
||||
;
|
||||
%cmp = fcmp oeq double %x, 42.0
|
||||
%cond = select i1 %cmp, double %x, double 42.0
|
||||
@ -18,9 +16,7 @@ define double @oeq(double %x) {
|
||||
|
||||
define float @oeq_swapped(float %x) {
|
||||
; CHECK-LABEL: @oeq_swapped(
|
||||
; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[X:%.*]], 4.200000e+01
|
||||
; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], float 4.200000e+01, float [[X]]
|
||||
; CHECK-NEXT: ret float [[COND]]
|
||||
; CHECK-NEXT: ret float [[X:%.*]]
|
||||
;
|
||||
%cmp = fcmp oeq float %x, 42.0
|
||||
%cond = select i1 %cmp, float 42.0, float %x
|
||||
@ -34,9 +30,7 @@ define float @oeq_swapped(float %x) {
|
||||
|
||||
define double @une(double %x) {
|
||||
; CHECK-LABEL: @une(
|
||||
; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[X:%.*]], 4.200000e+01
|
||||
; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], double [[X]], double 4.200000e+01
|
||||
; CHECK-NEXT: ret double [[COND]]
|
||||
; CHECK-NEXT: ret double [[X:%.*]]
|
||||
;
|
||||
%cmp = fcmp une double %x, 42.0
|
||||
%cond = select i1 %cmp, double %x, double 42.0
|
||||
@ -47,9 +41,7 @@ define double @une(double %x) {
|
||||
|
||||
define double @une_swapped(double %x) {
|
||||
; CHECK-LABEL: @une_swapped(
|
||||
; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[X:%.*]], 4.200000e+01
|
||||
; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], double 4.200000e+01, double [[X]]
|
||||
; CHECK-NEXT: ret double [[COND]]
|
||||
; CHECK-NEXT: ret double 4.200000e+01
|
||||
;
|
||||
%cmp = fcmp une double %x, 42.0
|
||||
%cond = select i1 %cmp, double 42.0, double %x
|
||||
|
Loading…
Reference in New Issue
Block a user