Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -5623,8 +5623,13 @@ if (!isa(N1) || !isa(N2)) return SDValue(); - // TODO: We should handle other cases of selecting between {-1,0,1} here. - if (CondVT == MVT::i1) { + // Only do this before legalization to avoid conflicting with target-specific + // transforms in the other direction (create a select from a zext/sext). There + // is also a target-independent combine here in DAGCombiner in the other + // direction for (select Cond, -1, 0) when the condition is not i1. + // TODO: This could be generalized for any 2 constants that differ by 1: + // add ({s/z}ext Cond), C + if (CondVT == MVT::i1 && !LegalOperations) { if (isNullConstant(N1) && isOneConstant(N2)) { // select Cond, 0, 1 --> zext (!Cond) SDValue NotCond = DAG.getNOT(DL, Cond, MVT::i1); @@ -5632,6 +5637,25 @@ NotCond = DAG.getNode(ISD::ZERO_EXTEND, DL, VT, NotCond); return NotCond; } + if (isNullConstant(N1) && isAllOnesConstant(N2)) { + // select Cond, 0, -1 --> sext (!Cond) + SDValue NotCond = DAG.getNOT(DL, Cond, MVT::i1); + if (VT != MVT::i1) + NotCond = DAG.getNode(ISD::SIGN_EXTEND, DL, VT, NotCond); + return NotCond; + } + if (isOneConstant(N1) && isNullConstant(N2)) { + // select Cond, 1, 0 --> zext (Cond) + if (VT != MVT::i1) + Cond = DAG.getNode(ISD::ZERO_EXTEND, DL, VT, Cond); + return Cond; + } + if (isAllOnesConstant(N1) && isNullConstant(N2)) { + // select Cond, -1, 0 --> sext (Cond) + if (VT != MVT::i1) + Cond = DAG.getNode(ISD::SIGN_EXTEND, DL, VT, Cond); + return Cond; + } return SDValue(); } @@ -6794,7 +6818,12 @@ if (!VT.isVector()) { EVT SetCCVT = getSetCCResultType(N00VT); - if (!LegalOperations || TLI.isOperationLegal(ISD::SETCC, N00VT)) { + // Don't do this transform for i1 because there's a select transform + // that would reverse it. + // TODO: We should not do this transform at all without a target hook + // because a sext is likely cheaper than a select? + if (SetCCVT.getScalarSizeInBits() != 1 && + (!LegalOperations || TLI.isOperationLegal(ISD::SETCC, N00VT))) { SDValue SetCC = DAG.getSetCC(DL, SetCCVT, N00, N01, CC); return DAG.getSelect(DL, VT, SetCC, ExtTrueVal, Zero); } Index: test/CodeGen/AMDGPU/trunc.ll =================================================================== --- test/CodeGen/AMDGPU/trunc.ll +++ test/CodeGen/AMDGPU/trunc.ll @@ -50,8 +50,8 @@ } ; SI-LABEL: {{^}}trunc_i32_to_i1: -; SI: v_and_b32_e32 v{{[0-9]+}}, 1, v{{[0-9]+}} -; SI: v_cmp_eq_u32 +; SI: v_and_b32_e32 [[VREG:v[0-9]+]], 1, v{{[0-9]+}} +; SI: buffer_store_dword [[VREG]], off, s[4:7], 0 define void @trunc_i32_to_i1(i32 addrspace(1)* %out, i32 addrspace(1)* %ptr) { %a = load i32, i32 addrspace(1)* %ptr, align 4 %trunc = trunc i32 %a to i1 @@ -61,8 +61,8 @@ } ; SI-LABEL: {{^}}sgpr_trunc_i32_to_i1: -; SI: s_and_b32 s{{[0-9]+}}, 1, s{{[0-9]+}} -; SI: v_cmp_eq_u32 +; SI: s_and_b32 [[SREG:s[0-9]+]], s{{[0-9]+}}, 1 +; SI: v_mov_b32_e32 v0, [[SREG]] define void @sgpr_trunc_i32_to_i1(i32 addrspace(1)* %out, i32 %a) { %trunc = trunc i32 %a to i1 %result = select i1 %trunc, i32 1, i32 0 Index: test/CodeGen/ARM/select_const.ll =================================================================== --- test/CodeGen/ARM/select_const.ll +++ test/CodeGen/ARM/select_const.ll @@ -40,8 +40,7 @@ define i32 @select_1_or_0(i1 %cond) { ; CHECK-LABEL: select_1_or_0: ; CHECK: @ BB#0: -; CHECK-NEXT: ands r0, r0, #1 -; CHECK-NEXT: movne r0, #1 +; CHECK-NEXT: and r0, r0, #1 ; CHECK-NEXT: mov pc, lr %sel = select i1 %cond, i32 1, i32 0 ret i32 %sel @@ -50,8 +49,6 @@ define i32 @select_1_or_0_zeroext(i1 zeroext %cond) { ; CHECK-LABEL: select_1_or_0_zeroext: ; CHECK: @ BB#0: -; CHECK-NEXT: cmp r0, #0 -; CHECK-NEXT: movne r0, #1 ; CHECK-NEXT: mov pc, lr %sel = select i1 %cond, i32 1, i32 0 ret i32 %sel @@ -60,8 +57,7 @@ define i32 @select_1_or_0_signext(i1 signext %cond) { ; CHECK-LABEL: select_1_or_0_signext: ; CHECK: @ BB#0: -; CHECK-NEXT: ands r0, r0, #1 -; CHECK-NEXT: movne r0, #1 +; CHECK-NEXT: and r0, r0, #1 ; CHECK-NEXT: mov pc, lr %sel = select i1 %cond, i32 1, i32 0 ret i32 %sel @@ -72,10 +68,9 @@ define i32 @select_0_or_neg1(i1 %cond) { ; CHECK-LABEL: select_0_or_neg1: ; CHECK: @ BB#0: -; CHECK-NEXT: mvn r1, #0 -; CHECK-NEXT: tst r0, #1 -; CHECK-NEXT: movne r1, #0 -; CHECK-NEXT: mov r0, r1 +; CHECK-NEXT: mov r1, #1 +; CHECK-NEXT: bic r0, r1, r0 +; CHECK-NEXT: rsb r0, r0, #0 ; CHECK-NEXT: mov pc, lr %sel = select i1 %cond, i32 0, i32 -1 ret i32 %sel @@ -84,10 +79,8 @@ define i32 @select_0_or_neg1_zeroext(i1 zeroext %cond) { ; CHECK-LABEL: select_0_or_neg1_zeroext: ; CHECK: @ BB#0: -; CHECK-NEXT: mvn r1, #0 -; CHECK-NEXT: cmp r0, #0 -; CHECK-NEXT: movne r1, #0 -; CHECK-NEXT: mov r0, r1 +; CHECK-NEXT: eor r0, r0, #1 +; CHECK-NEXT: rsb r0, r0, #0 ; CHECK-NEXT: mov pc, lr %sel = select i1 %cond, i32 0, i32 -1 ret i32 %sel @@ -96,10 +89,7 @@ define i32 @select_0_or_neg1_signext(i1 signext %cond) { ; CHECK-LABEL: select_0_or_neg1_signext: ; CHECK: @ BB#0: -; CHECK-NEXT: mvn r1, #0 -; CHECK-NEXT: tst r0, #1 -; CHECK-NEXT: movne r1, #0 -; CHECK-NEXT: mov r0, r1 +; CHECK-NEXT: mvn r0, r0 ; CHECK-NEXT: mov pc, lr %sel = select i1 %cond, i32 0, i32 -1 ret i32 %sel @@ -110,8 +100,8 @@ define i32 @select_neg1_or_0(i1 %cond) { ; CHECK-LABEL: select_neg1_or_0: ; CHECK: @ BB#0: -; CHECK-NEXT: ands r0, r0, #1 -; CHECK-NEXT: mvnne r0, #0 +; CHECK-NEXT: and r0, r0, #1 +; CHECK-NEXT: rsb r0, r0, #0 ; CHECK-NEXT: mov pc, lr %sel = select i1 %cond, i32 -1, i32 0 ret i32 %sel @@ -120,8 +110,7 @@ define i32 @select_neg1_or_0_zeroext(i1 zeroext %cond) { ; CHECK-LABEL: select_neg1_or_0_zeroext: ; CHECK: @ BB#0: -; CHECK-NEXT: cmp r0, #0 -; CHECK-NEXT: mvnne r0, #0 +; CHECK-NEXT: rsb r0, r0, #0 ; CHECK-NEXT: mov pc, lr %sel = select i1 %cond, i32 -1, i32 0 ret i32 %sel @@ -130,8 +119,6 @@ define i32 @select_neg1_or_0_signext(i1 signext %cond) { ; CHECK-LABEL: select_neg1_or_0_signext: ; CHECK: @ BB#0: -; CHECK-NEXT: ands r0, r0, #1 -; CHECK-NEXT: mvnne r0, #0 ; CHECK-NEXT: mov pc, lr %sel = select i1 %cond, i32 -1, i32 0 ret i32 %sel Index: test/CodeGen/Hexagon/adde.ll =================================================================== --- test/CodeGen/Hexagon/adde.ll +++ test/CodeGen/Hexagon/adde.ll @@ -1,13 +1,12 @@ ; RUN: llc -march=hexagon -disable-hsdr -hexagon-expand-condsets=0 -hexagon-bit=0 -disable-post-ra < %s | FileCheck %s -; CHECK: r{{[0-9]+:[0-9]+}} = combine(#0,#1) -; CHECK: r{{[0-9]+:[0-9]+}} = combine(#0,#0) ; CHECK: r{{[0-9]+:[0-9]+}} = add(r{{[0-9]+:[0-9]+}},r{{[0-9]+:[0-9]+}}) +; CHECK: r{{[0-9]+:[0-9]+}} = combine(#0,#1) ; CHECK: p{{[0-9]+}} = cmp.gtu(r{{[0-9]+:[0-9]+}},r{{[0-9]+:[0-9]+}}) ; CHECK: p{{[0-9]+}} = cmp.gtu(r{{[0-9]+:[0-9]+}},r{{[0-9]+:[0-9]+}}) -; CHECK: r{{[0-9]+}} = mux(p{{[0-9]+}},r{{[0-9]+}},r{{[0-9]+}}) -; CHECK: r{{[0-9]+}} = mux(p{{[0-9]+}},r{{[0-9]+}},r{{[0-9]+}}) -; CHECK: r{{[0-9]+:[0-9]+}} = combine(r{{[0-9]+}},r{{[0-9]+}}) +; CHECK: r{{[0-9]+}} = mux(p{{[0-9]+}},#1,#0) +; CHECK: r{{[0-9]+:[0-9]+}} = combine(#0,r{{[0-9]+}}) +; CHECK: r{{[0-9]+:[0-9]+}} = add(r{{[0-9]+:[0-9]+}},r{{[0-9]+:[0-9]+}}) ; CHECK: r{{[0-9]+}} = mux(p{{[0-9]+}},r{{[0-9]+}},r{{[0-9]+}}) ; CHECK: r{{[0-9]+}} = mux(p{{[0-9]+}},r{{[0-9]+}},r{{[0-9]+}}) ; CHECK: r{{[0-9]+:[0-9]+}} = combine(r{{[0-9]+}},r{{[0-9]+}}) Index: test/CodeGen/Hexagon/sube.ll =================================================================== --- test/CodeGen/Hexagon/sube.ll +++ test/CodeGen/Hexagon/sube.ll @@ -1,13 +1,11 @@ ; RUN: llc -march=hexagon -disable-hsdr -hexagon-expand-condsets=0 -hexagon-bit=0 -disable-post-ra < %s | FileCheck %s -; CHECK: r{{[0-9]+:[0-9]+}} = combine(#0,#0) -; CHECK: r{{[0-9]+:[0-9]+}} = combine(#0,#1) ; CHECK: p{{[0-9]+}} = cmp.gtu(r{{[0-9]+:[0-9]+}},r{{[0-9]+:[0-9]+}}) ; CHECK: r{{[0-9]+:[0-9]+}} = sub(r{{[0-9]+:[0-9]+}},r{{[0-9]+:[0-9]+}}) -; CHECK: r{{[0-9]+}} = mux(p{{[0-9]+}},r{{[0-9]+}},r{{[0-9]+}}) -; CHECK: r{{[0-9]+}} = mux(p{{[0-9]+}},r{{[0-9]+}},r{{[0-9]+}}) +; CHECK: r{{[0-9]+}} = mux(p{{[0-9]+}},#1,#0 +; CHECK: r{{[0-9]+:[0-9]+}} = sub(r{{[0-9]+:[0-9]+}},r{{[0-9]+:[0-9]+}}) +; CHECK: r{{[0-9]+:[0-9]+}} = combine(#0,r{{[0-9]+}}) ; CHECK: r{{[0-9]+:[0-9]+}} = sub(r{{[0-9]+:[0-9]+}},r{{[0-9]+:[0-9]+}}) -; CHECK: r{{[0-9]+:[0-9]+}} = combine(r{{[0-9]+}},r{{[0-9]+}}) define void @check_sube_subc(i64 %AL, i64 %AH, i64 %BL, i64 %BH, i64* %RL, i64* %RH) { entry: Index: test/CodeGen/NVPTX/add-128bit.ll =================================================================== --- test/CodeGen/NVPTX/add-128bit.ll +++ test/CodeGen/NVPTX/add-128bit.ll @@ -8,7 +8,7 @@ ; CHECK: add.s64 ; CHECK: setp.lt.u64 ; CHECK: setp.lt.u64 -; CHECK: selp.b64 +; CHECK: selp.u64 ; CHECK: selp.b64 ; CHECK: add.s64 %t1 = sext i64 %a to i128 Index: test/CodeGen/PowerPC/select_const.ll =================================================================== --- test/CodeGen/PowerPC/select_const.ll +++ test/CodeGen/PowerPC/select_const.ll @@ -39,70 +39,27 @@ ; select Cond, 1, 0 --> zext (Cond) define i32 @select_1_or_0(i1 %cond) { -; ISEL-LABEL: select_1_or_0: -; ISEL: # BB#0: -; ISEL-NEXT: andi. 3, 3, 1 -; ISEL-NEXT: li 4, 1 -; ISEL-NEXT: li 3, 0 -; ISEL-NEXT: isel 3, 4, 3, 1 -; ISEL-NEXT: blr -; -; NO_ISEL-LABEL: select_1_or_0: -; NO_ISEL: # BB#0: -; NO_ISEL-NEXT: andi. 3, 3, 1 -; NO_ISEL-NEXT: li 4, 1 -; NO_ISEL-NEXT: li 3, 0 -; NO_ISEL-NEXT: bc 12, 1, .LBB3_1 -; NO_ISEL-NEXT: blr -; NO_ISEL-NEXT: .LBB3_1: -; NO_ISEL-NEXT: addi 3, 4, 0 -; NO_ISEL-NEXT: blr +; ALL-LABEL: select_1_or_0: +; ALL: # BB#0: +; ALL-NEXT: clrldi 3, 3, 63 +; ALL-NEXT: blr %sel = select i1 %cond, i32 1, i32 0 ret i32 %sel } define i32 @select_1_or_0_zeroext(i1 zeroext %cond) { -; ISEL-LABEL: select_1_or_0_zeroext: -; ISEL: # BB#0: -; ISEL-NEXT: andi. 3, 3, 1 -; ISEL-NEXT: li 4, 1 -; ISEL-NEXT: li 3, 0 -; ISEL-NEXT: isel 3, 4, 3, 1 -; ISEL-NEXT: blr -; -; NO_ISEL-LABEL: select_1_or_0_zeroext: -; NO_ISEL: # BB#0: -; NO_ISEL-NEXT: andi. 3, 3, 1 -; NO_ISEL-NEXT: li 4, 1 -; NO_ISEL-NEXT: li 3, 0 -; NO_ISEL-NEXT: bc 12, 1, .LBB4_1 -; NO_ISEL-NEXT: blr -; NO_ISEL-NEXT: .LBB4_1: -; NO_ISEL-NEXT: addi 3, 4, 0 -; NO_ISEL-NEXT: blr +; ALL-LABEL: select_1_or_0_zeroext: +; ALL: # BB#0: +; ALL-NEXT: blr %sel = select i1 %cond, i32 1, i32 0 ret i32 %sel } define i32 @select_1_or_0_signext(i1 signext %cond) { -; ISEL-LABEL: select_1_or_0_signext: -; ISEL: # BB#0: -; ISEL-NEXT: andi. 3, 3, 1 -; ISEL-NEXT: li 4, 1 -; ISEL-NEXT: li 3, 0 -; ISEL-NEXT: isel 3, 4, 3, 1 -; ISEL-NEXT: blr -; -; NO_ISEL-LABEL: select_1_or_0_signext: -; NO_ISEL: # BB#0: -; NO_ISEL-NEXT: andi. 3, 3, 1 -; NO_ISEL-NEXT: li 4, 1 -; NO_ISEL-NEXT: li 3, 0 -; NO_ISEL-NEXT: bc 12, 1, .LBB5_1 -; NO_ISEL-NEXT: blr -; NO_ISEL-NEXT: .LBB5_1: -; NO_ISEL-NEXT: addi 3, 4, 0 -; NO_ISEL-NEXT: blr +; ALL-LABEL: select_1_or_0_signext: +; ALL: # BB#0: +; ALL-NEXT: clrldi 3, 3, 63 +; ALL-NEXT: blr %sel = select i1 %cond, i32 1, i32 0 ret i32 %sel } Index: test/CodeGen/X86/select_const.ll =================================================================== --- test/CodeGen/X86/select_const.ll +++ test/CodeGen/X86/select_const.ll @@ -108,10 +108,9 @@ define i32 @select_neg1_or_0(i1 %cond) { ; CHECK-LABEL: select_neg1_or_0: ; CHECK: # BB#0: -; CHECK-NEXT: xorl %ecx, %ecx -; CHECK-NEXT: testb $1, %dil -; CHECK-NEXT: movl $-1, %eax -; CHECK-NEXT: cmovel %ecx, %eax +; CHECK-NEXT: andl $1, %edi +; CHECK-NEXT: negl %edi +; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: retq %sel = select i1 %cond, i32 -1, i32 0 ret i32 %sel @@ -120,10 +119,8 @@ define i32 @select_neg1_or_0_zeroext(i1 zeroext %cond) { ; CHECK-LABEL: select_neg1_or_0_zeroext: ; CHECK: # BB#0: -; CHECK-NEXT: xorl %ecx, %ecx -; CHECK-NEXT: testb %dil, %dil -; CHECK-NEXT: movl $-1, %eax -; CHECK-NEXT: cmovel %ecx, %eax +; CHECK-NEXT: movzbl %dil, %eax +; CHECK-NEXT: negl %eax ; CHECK-NEXT: retq %sel = select i1 %cond, i32 -1, i32 0 ret i32 %sel @@ -132,10 +129,7 @@ define i32 @select_neg1_or_0_signext(i1 signext %cond) { ; CHECK-LABEL: select_neg1_or_0_signext: ; CHECK: # BB#0: -; CHECK-NEXT: xorl %ecx, %ecx -; CHECK-NEXT: testb $1, %dil -; CHECK-NEXT: movl $-1, %eax -; CHECK-NEXT: cmovel %ecx, %eax +; CHECK-NEXT: movsbl %dil, %eax ; CHECK-NEXT: retq %sel = select i1 %cond, i32 -1, i32 0 ret i32 %sel