diff options
author | Alexandros Lamprineas <alexandros.lamprineas@arm.com> | 2018-11-09 11:09:40 +0000 |
---|---|---|
committer | Alexandros Lamprineas <alexandros.lamprineas@arm.com> | 2018-11-09 11:09:40 +0000 |
commit | e15c982f6d6ae355d8fbf9c9272ac549785b68e2 (patch) | |
tree | c71b0cd236625b81cd79828b2ddb2cff38606b63 | |
parent | 52578f95c9fcf7b85beea921d401f49b2f6e9d1d (diff) | |
download | bcm5719-llvm-e15c982f6d6ae355d8fbf9c9272ac549785b68e2.tar.gz bcm5719-llvm-e15c982f6d6ae355d8fbf9c9272ac549785b68e2.zip |
[SelectionDAG] swap select_cc operands to enable folding
The DAGCombiner tries to SimplifySelectCC as follows:
select_cc(x, y, 16, 0, cc) -> shl(zext(set_cc(x, y, cc)), 4)
It can't cope with the situation of reordered operands:
select_cc(x, y, 0, 16, cc)
In that case we just need to swap the operands and invert the Condition Code:
select_cc(x, y, 16, 0, ~cc)
Differential Revision: https://reviews.llvm.org/D53236
llvm-svn: 346484
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 66 | ||||
-rw-r--r-- | llvm/test/CodeGen/AArch64/select_cc.ll | 54 | ||||
-rw-r--r-- | llvm/test/CodeGen/Thumb/branchless-cmp.ll | 16 |
3 files changed, 93 insertions, 43 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index bb0c3fb4c2f..f46b9e84789 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -18173,6 +18173,7 @@ SDValue DAGCombiner::SimplifySelectCC(const SDLoc &DL, SDValue N0, SDValue N1, EVT VT = N2.getValueType(); ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1.getNode()); ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2.getNode()); + ConstantSDNode *N3C = dyn_cast<ConstantSDNode>(N3.getNode()); // Determine if the condition we're dealing with is constant SDValue SCC = SimplifySetCC(getSetCCResultType(N0.getValueType()), @@ -18273,48 +18274,49 @@ SDValue DAGCombiner::SimplifySelectCC(const SDLoc &DL, SDValue N0, SDValue N1, } // fold select C, 16, 0 -> shl C, 4 - if (N2C && isNullConstant(N3) && N2C->getAPIntValue().isPowerOf2() && + bool Fold = N2C && isNullConstant(N3) && N2C->getAPIntValue().isPowerOf2(); + bool Swap = N3C && isNullConstant(N2) && N3C->getAPIntValue().isPowerOf2(); + + if ((Fold || Swap) && TLI.getBooleanContents(N0.getValueType()) == - TargetLowering::ZeroOrOneBooleanContent) { + TargetLowering::ZeroOrOneBooleanContent && + (!LegalOperations || + TLI.isOperationLegal(ISD::SETCC, N0.getValueType()))) { + + if (Swap) { + CC = ISD::getSetCCInverse(CC, N0.getValueType().isInteger()); + std::swap(N2C, N3C); + } // If the caller doesn't want us to simplify this into a zext of a compare, // don't do it. if (NotExtCompare && N2C->isOne()) return SDValue(); - // Get a SetCC of the condition - // NOTE: Don't create a SETCC if it's not legal on this target. - if (!LegalOperations || - TLI.isOperationLegal(ISD::SETCC, N0.getValueType())) { - SDValue Temp, SCC; - // cast from setcc result type to select result type - if (LegalTypes) { - SCC = DAG.getSetCC(DL, getSetCCResultType(N0.getValueType()), - N0, N1, CC); - if (N2.getValueType().bitsLT(SCC.getValueType())) - Temp = DAG.getZeroExtendInReg(SCC, SDLoc(N2), - N2.getValueType()); - else - Temp = DAG.getNode(ISD::ZERO_EXTEND, SDLoc(N2), - N2.getValueType(), SCC); - } else { - SCC = DAG.getSetCC(SDLoc(N0), MVT::i1, N0, N1, CC); - Temp = DAG.getNode(ISD::ZERO_EXTEND, SDLoc(N2), - N2.getValueType(), SCC); - } + SDValue Temp, SCC; + // zext (setcc n0, n1) + if (LegalTypes) { + SCC = DAG.getSetCC(DL, getSetCCResultType(N0.getValueType()), N0, N1, CC); + if (N2.getValueType().bitsLT(SCC.getValueType())) + Temp = DAG.getZeroExtendInReg(SCC, SDLoc(N2), N2.getValueType()); + else + Temp = DAG.getNode(ISD::ZERO_EXTEND, SDLoc(N2), N2.getValueType(), SCC); + } else { + SCC = DAG.getSetCC(SDLoc(N0), MVT::i1, N0, N1, CC); + Temp = DAG.getNode(ISD::ZERO_EXTEND, SDLoc(N2), N2.getValueType(), SCC); + } - AddToWorklist(SCC.getNode()); - AddToWorklist(Temp.getNode()); + AddToWorklist(SCC.getNode()); + AddToWorklist(Temp.getNode()); - if (N2C->isOne()) - return Temp; + if (N2C->isOne()) + return Temp; - // shl setcc result by log2 n2c - return DAG.getNode( - ISD::SHL, DL, N2.getValueType(), Temp, - DAG.getConstant(N2C->getAPIntValue().logBase2(), SDLoc(Temp), - getShiftAmountTy(Temp.getValueType()))); - } + // shl setcc result by log2 n2c + return DAG.getNode(ISD::SHL, DL, N2.getValueType(), Temp, + DAG.getConstant(N2C->getAPIntValue().logBase2(), + SDLoc(Temp), + getShiftAmountTy(Temp.getValueType()))); } // Check to see if this is an integer abs. diff --git a/llvm/test/CodeGen/AArch64/select_cc.ll b/llvm/test/CodeGen/AArch64/select_cc.ll new file mode 100644 index 00000000000..785e6b800ed --- /dev/null +++ b/llvm/test/CodeGen/AArch64/select_cc.ll @@ -0,0 +1,54 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=aarch64 | FileCheck %s + +define i64 @select_ogt_float(float %a, float %b) { +; CHECK-LABEL: select_ogt_float: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: fcmp s0, s1 +; CHECK-NEXT: cset w8, gt +; CHECK-NEXT: lsl x0, x8, #2 +; CHECK-NEXT: ret +entry: + %cc = fcmp ogt float %a, %b + %sel = select i1 %cc, i64 4, i64 0 + ret i64 %sel +} + +define i64 @select_ule_float_inverse(float %a, float %b) { +; CHECK-LABEL: select_ule_float_inverse: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: fcmp s0, s1 +; CHECK-NEXT: cset w8, gt +; CHECK-NEXT: lsl x0, x8, #2 +; CHECK-NEXT: ret +entry: + %cc = fcmp ule float %a, %b + %sel = select i1 %cc, i64 0, i64 4 + ret i64 %sel +} + +define i64 @select_eq_i32(i32 %a, i32 %b) { +; CHECK-LABEL: select_eq_i32: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: cmp w0, w1 +; CHECK-NEXT: cset w8, eq +; CHECK-NEXT: lsl x0, x8, #2 +; CHECK-NEXT: ret +entry: + %cc = icmp eq i32 %a, %b + %sel = select i1 %cc, i64 4, i64 0 + ret i64 %sel +} + +define i64 @select_ne_i32_inverse(i32 %a, i32 %b) { +; CHECK-LABEL: select_ne_i32_inverse: +; CHECK: // %bb.0: // %entry +; CHECK-NEXT: cmp w0, w1 +; CHECK-NEXT: cset w8, eq +; CHECK-NEXT: lsl x0, x8, #2 +; CHECK-NEXT: ret +entry: + %cc = icmp ne i32 %a, %b + %sel = select i1 %cc, i64 0, i64 4 + ret i64 %sel +} diff --git a/llvm/test/CodeGen/Thumb/branchless-cmp.ll b/llvm/test/CodeGen/Thumb/branchless-cmp.ll index ed34d630733..40c5b8853da 100644 --- a/llvm/test/CodeGen/Thumb/branchless-cmp.ll +++ b/llvm/test/CodeGen/Thumb/branchless-cmp.ll @@ -74,23 +74,17 @@ entry: ; CHECK-NEXT: lsls r0, r1, #2 } -; FIXME: This one hasn't changed actually -; but could look like test3b define i32 @test4a(i32 %a, i32 %b) { entry: %cmp = icmp ne i32 %a, %b %cond = select i1 %cmp, i32 0, i32 4 ret i32 %cond ; CHECK-LABEL: test4a: -; CHECK: bb.0: -; CHECK-NEXT: cmp r0, r1 -; CHECK-NEXT: bne .LBB6_2 -; CHECK-NEXT: bb.1: -; CHECK-NEXT: movs r0, #4 -; CHECK-NEXT: bx lr -; CHECK-NEXT: .LBB6_2: -; CHECK-NEXT: movs r0, #0 -; CHECK-NEXT: bx lr +; CHECK-NOT: b{{(ne)|(eq)}} +; CHECK: subs r0, r0, r1 +; CHECK-NEXT: rsbs r1, r0, #0 +; CHECK-NEXT: adcs r1, r0 +; CHECK-NEXT: lsls r0, r1, #2 } define i32 @test4b(i32 %a, i32 %b) { |