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:
Matthias Braun 2015-08-18 20:48:29 +00:00
parent edaba3b7c3
commit 2e920bd04f
2 changed files with 49 additions and 32 deletions

View File

@ -4955,38 +4955,6 @@ SDValue DAGCombiner::visitSELECT(SDNode *N) {
if (SimplifySelectOps(N, N1, N2))
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 (TLI.shouldNormalizeToSelectSequence(*DAG.getContext(), VT)) {
// 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();
}

View File

@ -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
}