forked from OSchip/llvm-project
DAGCombiner: Optimize SELECTs first before turning them into SELECT_CC
This is part of http://reviews.llvm.org/D11616 - I just decided to split this up into a separate commit. llvm-svn: 245349
This commit is contained in:
parent
edaba3b7c3
commit
2e920bd04f
|
@ -4955,38 +4955,6 @@ SDValue DAGCombiner::visitSELECT(SDNode *N) {
|
||||||
if (SimplifySelectOps(N, N1, N2))
|
if (SimplifySelectOps(N, N1, N2))
|
||||||
return SDValue(N, 0); // Don't revisit N.
|
return SDValue(N, 0); // Don't revisit N.
|
||||||
|
|
||||||
// fold selects based on a setcc into other things, such as min/max/abs
|
|
||||||
if (N0.getOpcode() == ISD::SETCC) {
|
|
||||||
// select x, y (fcmp lt x, y) -> fminnum x, y
|
|
||||||
// select x, y (fcmp gt x, y) -> fmaxnum x, y
|
|
||||||
//
|
|
||||||
// This is OK if we don't care about what happens if either operand is a
|
|
||||||
// NaN.
|
|
||||||
//
|
|
||||||
|
|
||||||
// FIXME: Instead of testing for UnsafeFPMath, this should be checking for
|
|
||||||
// no signed zeros as well as no nans.
|
|
||||||
const TargetOptions &Options = DAG.getTarget().Options;
|
|
||||||
if (Options.UnsafeFPMath &&
|
|
||||||
VT.isFloatingPoint() && N0.hasOneUse() &&
|
|
||||||
DAG.isKnownNeverNaN(N1) && DAG.isKnownNeverNaN(N2)) {
|
|
||||||
ISD::CondCode CC = cast<CondCodeSDNode>(N0.getOperand(2))->get();
|
|
||||||
|
|
||||||
if (SDValue FMinMax = combineMinNumMaxNum(SDLoc(N), VT, N0.getOperand(0),
|
|
||||||
N0.getOperand(1), N1, N2, CC,
|
|
||||||
TLI, DAG))
|
|
||||||
return FMinMax;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((!LegalOperations &&
|
|
||||||
TLI.isOperationLegalOrCustom(ISD::SELECT_CC, VT)) ||
|
|
||||||
TLI.isOperationLegal(ISD::SELECT_CC, VT))
|
|
||||||
return DAG.getNode(ISD::SELECT_CC, SDLoc(N), VT,
|
|
||||||
N0.getOperand(0), N0.getOperand(1),
|
|
||||||
N1, N2, N0.getOperand(2));
|
|
||||||
return SimplifySelect(SDLoc(N), N0, N1, N2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (VT0 == MVT::i1) {
|
if (VT0 == MVT::i1) {
|
||||||
if (TLI.shouldNormalizeToSelectSequence(*DAG.getContext(), VT)) {
|
if (TLI.shouldNormalizeToSelectSequence(*DAG.getContext(), VT)) {
|
||||||
// select (and Cond0, Cond1), X, Y
|
// select (and Cond0, Cond1), X, Y
|
||||||
|
@ -5050,6 +5018,38 @@ SDValue DAGCombiner::visitSELECT(SDNode *N) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fold selects based on a setcc into other things, such as min/max/abs
|
||||||
|
if (N0.getOpcode() == ISD::SETCC) {
|
||||||
|
// select x, y (fcmp lt x, y) -> fminnum x, y
|
||||||
|
// select x, y (fcmp gt x, y) -> fmaxnum x, y
|
||||||
|
//
|
||||||
|
// This is OK if we don't care about what happens if either operand is a
|
||||||
|
// NaN.
|
||||||
|
//
|
||||||
|
|
||||||
|
// FIXME: Instead of testing for UnsafeFPMath, this should be checking for
|
||||||
|
// no signed zeros as well as no nans.
|
||||||
|
const TargetOptions &Options = DAG.getTarget().Options;
|
||||||
|
if (Options.UnsafeFPMath &&
|
||||||
|
VT.isFloatingPoint() && N0.hasOneUse() &&
|
||||||
|
DAG.isKnownNeverNaN(N1) && DAG.isKnownNeverNaN(N2)) {
|
||||||
|
ISD::CondCode CC = cast<CondCodeSDNode>(N0.getOperand(2))->get();
|
||||||
|
|
||||||
|
if (SDValue FMinMax = combineMinNumMaxNum(SDLoc(N), VT, N0.getOperand(0),
|
||||||
|
N0.getOperand(1), N1, N2, CC,
|
||||||
|
TLI, DAG))
|
||||||
|
return FMinMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!LegalOperations &&
|
||||||
|
TLI.isOperationLegalOrCustom(ISD::SELECT_CC, VT)) ||
|
||||||
|
TLI.isOperationLegal(ISD::SELECT_CC, VT))
|
||||||
|
return DAG.getNode(ISD::SELECT_CC, SDLoc(N), VT,
|
||||||
|
N0.getOperand(0), N0.getOperand(1),
|
||||||
|
N1, N2, N0.getOperand(2));
|
||||||
|
return SimplifySelect(SDLoc(N), N0, N1, N2);
|
||||||
|
}
|
||||||
|
|
||||||
return SDValue();
|
return SDValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
; RUN: llc -o - %s | FileCheck %s
|
||||||
|
target triple = "arm64--"
|
||||||
|
|
||||||
|
; Ensure that we transform select(C0, x, select(C1, x, y)) towards
|
||||||
|
; select(C0 | C1, x, y) so we can use CMP;CCMP for the implementation.
|
||||||
|
; CHECK-LABEL: test0:
|
||||||
|
; CHECK: cmp w0, #7
|
||||||
|
; CHECK: ccmp w1, #0, #0, ne
|
||||||
|
; CHECK: csel w0, w1, w2, gt
|
||||||
|
; CHECK: ret
|
||||||
|
define i32 @test0(i32 %v0, i32 %v1, i32 %v2) {
|
||||||
|
%cmp1 = icmp eq i32 %v0, 7
|
||||||
|
%cmp2 = icmp sgt i32 %v1, 0
|
||||||
|
%sel0 = select i1 %cmp1, i32 %v1, i32 %v2
|
||||||
|
%sel1 = select i1 %cmp2, i32 %v1, i32 %sel0
|
||||||
|
ret i32 %sel1
|
||||||
|
}
|
Loading…
Reference in New Issue