Index: lib/Target/X86/X86ISelLowering.cpp =================================================================== --- lib/Target/X86/X86ISelLowering.cpp +++ lib/Target/X86/X86ISelLowering.cpp @@ -319,7 +319,7 @@ setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i32, Legal); setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16 , Legal); setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8 , Legal); - setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Expand); + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Custom); setOperationAction(ISD::FP_ROUND_INREG , MVT::f32 , Expand); setOperationAction(ISD::FREM , MVT::f32 , Expand); @@ -16330,6 +16330,21 @@ return DAG.getNode(X86ISD::VTRUNC, dl, VT, V); } +static SDValue LowerSIGN_EXTEND_INREG(SDValue Op, SelectionDAG &DAG) { + SDValue N0 = Op.getOperand(0); + EVT VT = Op.getValueType(); + EVT SrcVT = cast(Op.getOperand(1))->getVT(); + SDLoc DL(Op); + + // An in-register sign-extend of a boolean is a negation: + // 'true' (1) sign-extended is -1. + // 'false' (0) sign-extended is 0. + if (SrcVT.getScalarSizeInBits() == 1) + return DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT), N0); + + return SDValue(); +} + static SDValue LowerSIGN_EXTEND_VECTOR_INREG(SDValue Op, const X86Subtarget &Subtarget, SelectionDAG &DAG) { @@ -22034,6 +22049,7 @@ case ISD::ZERO_EXTEND: return LowerZERO_EXTEND(Op, Subtarget, DAG); case ISD::SIGN_EXTEND: return LowerSIGN_EXTEND(Op, Subtarget, DAG); case ISD::ANY_EXTEND: return LowerANY_EXTEND(Op, Subtarget, DAG); + case ISD::SIGN_EXTEND_INREG: return LowerSIGN_EXTEND_INREG(Op, DAG); case ISD::SIGN_EXTEND_VECTOR_INREG: return LowerSIGN_EXTEND_VECTOR_INREG(Op, Subtarget, DAG); case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG); Index: test/CodeGen/X86/negate-i1.ll =================================================================== --- test/CodeGen/X86/negate-i1.ll +++ test/CodeGen/X86/negate-i1.ll @@ -4,8 +4,7 @@ define i8 @select_i8_neg1_or_0(i1 %a) { ; CHECK-LABEL: select_i8_neg1_or_0: ; CHECK: # BB#0: -; CHECK-NEXT: shlb $7, %dil -; CHECK-NEXT: sarb $7, %dil +; CHECK-NEXT: negb %dil ; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: retq ; @@ -16,8 +15,7 @@ define i8 @select_i8_neg1_or_0_zeroext(i1 zeroext %a) { ; CHECK-LABEL: select_i8_neg1_or_0_zeroext: ; CHECK: # BB#0: -; CHECK-NEXT: shlb $7, %dil -; CHECK-NEXT: sarb $7, %dil +; CHECK-NEXT: negb %dil ; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: retq ; @@ -28,8 +26,7 @@ define i16 @select_i16_neg1_or_0(i1 %a) { ; CHECK-LABEL: select_i16_neg1_or_0: ; CHECK: # BB#0: -; CHECK-NEXT: shll $15, %edi -; CHECK-NEXT: sarw $15, %di +; CHECK-NEXT: negl %edi ; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: retq ; @@ -41,8 +38,7 @@ ; CHECK-LABEL: select_i16_neg1_or_0_zeroext: ; CHECK: # BB#0: ; CHECK-NEXT: movzbl %dil, %eax -; CHECK-NEXT: shll $15, %eax -; CHECK-NEXT: sarw $15, %ax +; CHECK-NEXT: negl %eax ; CHECK-NEXT: # kill: %AX %AX %EAX ; CHECK-NEXT: retq ; @@ -53,8 +49,7 @@ define i32 @select_i32_neg1_or_0(i1 %a) { ; CHECK-LABEL: select_i32_neg1_or_0: ; CHECK: # BB#0: -; CHECK-NEXT: shll $31, %edi -; CHECK-NEXT: sarl $31, %edi +; CHECK-NEXT: negl %edi ; CHECK-NEXT: movl %edi, %eax ; CHECK-NEXT: retq ; @@ -66,8 +61,7 @@ ; CHECK-LABEL: select_i32_neg1_or_0_zeroext: ; CHECK: # BB#0: ; CHECK-NEXT: movzbl %dil, %eax -; CHECK-NEXT: shll $31, %eax -; CHECK-NEXT: sarl $31, %eax +; CHECK-NEXT: negl %eax ; CHECK-NEXT: retq ; %b = sext i1 %a to i32 @@ -78,8 +72,7 @@ ; CHECK-LABEL: select_i64_neg1_or_0: ; CHECK: # BB#0: ; CHECK-NEXT: # kill: %EDI %EDI %RDI -; CHECK-NEXT: shlq $63, %rdi -; CHECK-NEXT: sarq $63, %rdi +; CHECK-NEXT: negq %rdi ; CHECK-NEXT: movq %rdi, %rax ; CHECK-NEXT: retq ; @@ -91,8 +84,7 @@ ; CHECK-LABEL: select_i64_neg1_or_0_zeroext: ; CHECK: # BB#0: ; CHECK-NEXT: movzbl %dil, %eax -; CHECK-NEXT: shlq $63, %rax -; CHECK-NEXT: sarq $63, %rax +; CHECK-NEXT: negq %rax ; CHECK-NEXT: retq ; %b = sext i1 %a to i64