mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 12:50:30 +00:00
Bug 21610: Canonicalize min/max fcmp selects to use ordered comparisons
llvm-svn: 222705
This commit is contained in:
parent
ae1a2b7c22
commit
454e837bd2
@ -928,8 +928,22 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
|
||||
!CFPf->getValueAPF().isZero()))
|
||||
return ReplaceInstUsesWith(SI, TrueVal);
|
||||
}
|
||||
// NOTE: if we wanted to, this is where to detect MIN/MAX
|
||||
|
||||
// Canonicalize to use ordered comparisons by swapping the select
|
||||
// operands.
|
||||
//
|
||||
// e.g.
|
||||
// (X ugt Y) ? X : Y -> (X ole Y) ? Y : X
|
||||
if (FCI->hasOneUse() && FCmpInst::isUnordered(FCI->getPredicate())) {
|
||||
FCmpInst::Predicate InvPred = FCI->getInversePredicate();
|
||||
Value *NewCond = Builder->CreateFCmp(InvPred, TrueVal, FalseVal,
|
||||
FCI->getName() + ".inv");
|
||||
|
||||
return SelectInst::Create(NewCond, FalseVal, TrueVal,
|
||||
SI.getName() + ".p");
|
||||
}
|
||||
|
||||
// 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) {
|
||||
@ -955,6 +969,21 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
|
||||
!CFPf->getValueAPF().isZero()))
|
||||
return ReplaceInstUsesWith(SI, TrueVal);
|
||||
}
|
||||
|
||||
// Canonicalize to use ordered comparisons by swapping the select
|
||||
// operands.
|
||||
//
|
||||
// e.g.
|
||||
// (X ugt Y) ? X : Y -> (X ole Y) ? X : Y
|
||||
if (FCI->hasOneUse() && FCmpInst::isUnordered(FCI->getPredicate())) {
|
||||
FCmpInst::Predicate InvPred = FCI->getInversePredicate();
|
||||
Value *NewCond = Builder->CreateFCmp(InvPred, FalseVal, TrueVal,
|
||||
FCI->getName() + ".inv");
|
||||
|
||||
return SelectInst::Create(NewCond, FalseVal, TrueVal,
|
||||
SI.getName() + ".p");
|
||||
}
|
||||
|
||||
// NOTE: if we wanted to, this is where to detect MIN/MAX
|
||||
}
|
||||
// NOTE: if we wanted to, this is where to detect ABS
|
||||
|
125
test/Transforms/InstCombine/unordered-fcmp-select.ll
Normal file
125
test/Transforms/InstCombine/unordered-fcmp-select.ll
Normal file
@ -0,0 +1,125 @@
|
||||
; RUN: opt -S -instcombine < %s | FileCheck %s
|
||||
|
||||
; CHECK-LABEL: @select_max_ugt(
|
||||
; CHECK: %cmp.inv = fcmp ole float %a, %b
|
||||
; CHECK-NEXT: %sel = select i1 %cmp.inv, float %b, float %a
|
||||
; CHECK-NEXT: ret float %sel
|
||||
define float @select_max_ugt(float %a, float %b) {
|
||||
%cmp = fcmp ugt float %a, %b
|
||||
%sel = select i1 %cmp, float %a, float %b
|
||||
ret float %sel
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @select_max_uge(
|
||||
; CHECK: %cmp.inv = fcmp olt float %a, %b
|
||||
; CHECK-NEXT: %sel = select i1 %cmp.inv, float %b, float %a
|
||||
; CHECK-NEXT: ret float %sel
|
||||
define float @select_max_uge(float %a, float %b) {
|
||||
%cmp = fcmp uge float %a, %b
|
||||
%sel = select i1 %cmp, float %a, float %b
|
||||
ret float %sel
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @select_min_ugt(
|
||||
; CHECK: %cmp.inv = fcmp ole float %a, %b
|
||||
; CHECK-NEXT: %sel = select i1 %cmp.inv, float %a, float %b
|
||||
; CHECK-NEXT: ret float %sel
|
||||
define float @select_min_ugt(float %a, float %b) {
|
||||
%cmp = fcmp ugt float %a, %b
|
||||
%sel = select i1 %cmp, float %b, float %a
|
||||
ret float %sel
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @select_min_uge(
|
||||
; CHECK: %cmp.inv = fcmp olt float %a, %b
|
||||
; CHECK-NEXT: %sel = select i1 %cmp.inv, float %a, float %b
|
||||
; CHECK-NEXT: ret float %sel
|
||||
define float @select_min_uge(float %a, float %b) {
|
||||
%cmp = fcmp uge float %a, %b
|
||||
%sel = select i1 %cmp, float %b, float %a
|
||||
ret float %sel
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @select_max_ult(
|
||||
; CHECK: %cmp.inv = fcmp oge float %a, %b
|
||||
; CHECK-NEXT: %sel = select i1 %cmp.inv, float %a, float %b
|
||||
; CHECK-NEXT: ret float %sel
|
||||
define float @select_max_ult(float %a, float %b) {
|
||||
%cmp = fcmp ult float %a, %b
|
||||
%sel = select i1 %cmp, float %b, float %a
|
||||
ret float %sel
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @select_max_ule(
|
||||
; CHECK: %cmp.inv = fcmp ogt float %a, %b
|
||||
; CHECK-NEXT: %sel = select i1 %cmp.inv, float %a, float %b
|
||||
; CHECK: ret float %sel
|
||||
define float @select_max_ule(float %a, float %b) {
|
||||
%cmp = fcmp ule float %a, %b
|
||||
%sel = select i1 %cmp, float %b, float %a
|
||||
ret float %sel
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @select_min_ult(
|
||||
; CHECK: %cmp.inv = fcmp oge float %a, %b
|
||||
; CHECK-NEXT: %sel = select i1 %cmp.inv, float %b, float %a
|
||||
; CHECK-NEXT: ret float %sel
|
||||
define float @select_min_ult(float %a, float %b) {
|
||||
%cmp = fcmp ult float %a, %b
|
||||
%sel = select i1 %cmp, float %a, float %b
|
||||
ret float %sel
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @select_min_ule(
|
||||
; CHECK: %cmp.inv = fcmp ogt float %a, %b
|
||||
; CHECK-NEXT: %sel = select i1 %cmp.inv, float %b, float %a
|
||||
; CHECK-NEXT: ret float %sel
|
||||
define float @select_min_ule(float %a, float %b) {
|
||||
%cmp = fcmp ule float %a, %b
|
||||
%sel = select i1 %cmp, float %a, float %b
|
||||
ret float %sel
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @select_fcmp_une(
|
||||
; CHECK: %cmp.inv = fcmp oeq float %a, %b
|
||||
; CHECK-NEXT: %sel = select i1 %cmp.inv, float %b, float %a
|
||||
; CHECK-NEXT: ret float %sel
|
||||
define float @select_fcmp_une(float %a, float %b) {
|
||||
%cmp = fcmp une float %a, %b
|
||||
%sel = select i1 %cmp, float %a, float %b
|
||||
ret float %sel
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @select_fcmp_ueq
|
||||
; CHECK: %cmp.inv = fcmp one float %a, %b
|
||||
; CHECK-NEXT: %sel = select i1 %cmp.inv, float %b, float %a
|
||||
; CHECK-NEXT: ret float %sel
|
||||
define float @select_fcmp_ueq(float %a, float %b) {
|
||||
%cmp = fcmp ueq float %a, %b
|
||||
%sel = select i1 %cmp, float %a, float %b
|
||||
ret float %sel
|
||||
}
|
||||
|
||||
declare void @foo(i1)
|
||||
|
||||
; CHECK-LABEL: @select_max_ugt_2_use_cmp(
|
||||
; CHECK: fcmp ugt
|
||||
; CHECK-NOT: fcmp
|
||||
; CHECK: ret
|
||||
define float @select_max_ugt_2_use_cmp(float %a, float %b) {
|
||||
%cmp = fcmp ugt float %a, %b
|
||||
call void @foo(i1 %cmp)
|
||||
%sel = select i1 %cmp, float %a, float %b
|
||||
ret float %sel
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @select_min_uge_2_use_cmp(
|
||||
; CHECK: fcmp uge
|
||||
; CHECK-NOT: fcmp
|
||||
; CHECK: ret
|
||||
define float @select_min_uge_2_use_cmp(float %a, float %b) {
|
||||
%cmp = fcmp uge float %a, %b
|
||||
call void @foo(i1 %cmp)
|
||||
%sel = select i1 %cmp, float %b, float %a
|
||||
ret float %sel
|
||||
}
|
@ -516,7 +516,7 @@ for.end:
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @unordered_max_red_float(
|
||||
; CHECK: fcmp ugt <2 x float>
|
||||
; CHECK: fcmp ole <2 x float>
|
||||
; CHECK: select <2 x i1>
|
||||
; CHECK: middle.block
|
||||
; CHECK: fcmp ogt <2 x float>
|
||||
@ -542,7 +542,7 @@ for.end:
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @unordered_max_red_float_ge(
|
||||
; CHECK: fcmp uge <2 x float>
|
||||
; CHECK: fcmp olt <2 x float>
|
||||
; CHECK: select <2 x i1>
|
||||
; CHECK: middle.block
|
||||
; CHECK: fcmp ogt <2 x float>
|
||||
@ -568,7 +568,7 @@ for.end:
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @inverted_unordered_max_red_float(
|
||||
; CHECK: fcmp ult <2 x float>
|
||||
; CHECK: fcmp oge <2 x float>
|
||||
; CHECK: select <2 x i1>
|
||||
; CHECK: middle.block
|
||||
; CHECK: fcmp ogt <2 x float>
|
||||
@ -594,7 +594,7 @@ for.end:
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @inverted_unordered_max_red_float_le(
|
||||
; CHECK: fcmp ule <2 x float>
|
||||
; CHECK: fcmp ogt <2 x float>
|
||||
; CHECK: select <2 x i1>
|
||||
; CHECK: middle.block
|
||||
; CHECK: fcmp ogt <2 x float>
|
||||
@ -727,7 +727,7 @@ for.end:
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @unordered_min_red_float(
|
||||
; CHECK: fcmp ult <2 x float>
|
||||
; CHECK: fcmp oge <2 x float>
|
||||
; CHECK: select <2 x i1>
|
||||
; CHECK: middle.block
|
||||
; CHECK: fcmp olt <2 x float>
|
||||
@ -753,7 +753,7 @@ for.end:
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @unordered_min_red_float_le(
|
||||
; CHECK: fcmp ule <2 x float>
|
||||
; CHECK: fcmp ogt <2 x float>
|
||||
; CHECK: select <2 x i1>
|
||||
; CHECK: middle.block
|
||||
; CHECK: fcmp olt <2 x float>
|
||||
@ -779,7 +779,7 @@ for.end:
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @inverted_unordered_min_red_float(
|
||||
; CHECK: fcmp ugt <2 x float>
|
||||
; CHECK: fcmp ole <2 x float>
|
||||
; CHECK: select <2 x i1>
|
||||
; CHECK: middle.block
|
||||
; CHECK: fcmp olt <2 x float>
|
||||
@ -805,7 +805,7 @@ for.end:
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @inverted_unordered_min_red_float_ge(
|
||||
; CHECK: fcmp uge <2 x float>
|
||||
; CHECK: fcmp olt <2 x float>
|
||||
; CHECK: select <2 x i1>
|
||||
; CHECK: middle.block
|
||||
; CHECK: fcmp olt <2 x float>
|
||||
|
Loading…
Reference in New Issue
Block a user