Index: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -18173,6 +18173,7 @@ EVT VT = N2.getValueType(); ConstantSDNode *N1C = dyn_cast(N1.getNode()); ConstantSDNode *N2C = dyn_cast(N2.getNode()); + ConstantSDNode *N3C = dyn_cast(N3.getNode()); // Determine if the condition we're dealing with is constant SDValue SCC = SimplifySetCC(getSetCCResultType(N0.getValueType()), @@ -18273,48 +18274,49 @@ } // 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. Index: llvm/trunk/test/CodeGen/AArch64/select_cc.ll =================================================================== --- llvm/trunk/test/CodeGen/AArch64/select_cc.ll +++ llvm/trunk/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 +} Index: llvm/trunk/test/CodeGen/Thumb/branchless-cmp.ll =================================================================== --- llvm/trunk/test/CodeGen/Thumb/branchless-cmp.ll +++ llvm/trunk/test/CodeGen/Thumb/branchless-cmp.ll @@ -74,23 +74,17 @@ ; 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) {