diff options
-rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.cpp | 10 | ||||
-rw-r--r-- | llvm/test/CodeGen/X86/sext-i1.ll | 34 |
2 files changed, 22 insertions, 22 deletions
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 57d937dd545..5522c7138b9 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -33436,6 +33436,16 @@ static SDValue combineSext(SDNode *N, SelectionDAG &DAG, return SDValue(); } + if (InVT == MVT::i1 && N0.getOpcode() == ISD::XOR && + isAllOnesConstant(N0.getOperand(1)) && N0.hasOneUse()) { + // Invert and sign-extend a boolean is the same as zero-extend and subtract + // 1 because 0 becomes -1 and 1 becomes 0. The subtract is efficiently + // lowered with an LEA or a DEC. This is the same as: select Bool, 0, -1. + // sext (xor Bool, -1) --> sub (zext Bool), 1 + SDValue Zext = DAG.getNode(ISD::ZERO_EXTEND, DL, VT, N0.getOperand(0)); + return DAG.getNode(ISD::SUB, DL, VT, Zext, DAG.getConstant(1, DL, VT)); + } + if (SDValue V = combineToExtendVectorInReg(N, DAG, DCI, Subtarget)) return V; diff --git a/llvm/test/CodeGen/X86/sext-i1.ll b/llvm/test/CodeGen/X86/sext-i1.ll index 935e88d5753..ecda0f4e08c 100644 --- a/llvm/test/CodeGen/X86/sext-i1.ll +++ b/llvm/test/CodeGen/X86/sext-i1.ll @@ -117,19 +117,16 @@ define i64 @t5(i32 %x) nounwind readnone ssp { define i32 @select_0_or_1s(i1 %cond) { ; X32-LABEL: select_0_or_1s: ; X32: # BB#0: -; X32-NEXT: movb {{[0-9]+}}(%esp), %al -; X32-NEXT: notb %al -; X32-NEXT: movzbl %al, %eax +; X32-NEXT: movzbl {{[0-9]+}}(%esp), %eax ; X32-NEXT: andl $1, %eax -; X32-NEXT: negl %eax +; X32-NEXT: decl %eax ; X32-NEXT: retl ; ; X64-LABEL: select_0_or_1s: ; X64: # BB#0: -; X64-NEXT: notb %dil -; X64-NEXT: movzbl %dil, %eax -; X64-NEXT: andl $1, %eax -; X64-NEXT: negl %eax +; X64-NEXT: # kill: %EDI<def> %EDI<kill> %RDI<def> +; X64-NEXT: andl $1, %edi +; X64-NEXT: leal -1(%rdi), %eax ; X64-NEXT: retq %not = xor i1 %cond, 1 %sext = sext i1 %not to i32 @@ -141,19 +138,14 @@ define i32 @select_0_or_1s(i1 %cond) { define i32 @select_0_or_1s_zeroext(i1 zeroext %cond) { ; X32-LABEL: select_0_or_1s_zeroext: ; X32: # BB#0: -; X32-NEXT: movb {{[0-9]+}}(%esp), %al -; X32-NEXT: notb %al -; X32-NEXT: movzbl %al, %eax -; X32-NEXT: andl $1, %eax -; X32-NEXT: negl %eax +; X32-NEXT: movzbl {{[0-9]+}}(%esp), %eax +; X32-NEXT: decl %eax ; X32-NEXT: retl ; ; X64-LABEL: select_0_or_1s_zeroext: ; X64: # BB#0: -; X64-NEXT: notb %dil ; X64-NEXT: movzbl %dil, %eax -; X64-NEXT: andl $1, %eax -; X64-NEXT: negl %eax +; X64-NEXT: decl %eax ; X64-NEXT: retq %not = xor i1 %cond, 1 %sext = sext i1 %not to i32 @@ -166,18 +158,16 @@ define i32 @select_0_or_1s_signext(i1 signext %cond) { ; X32-LABEL: select_0_or_1s_signext: ; X32: # BB#0: ; X32-NEXT: movb {{[0-9]+}}(%esp), %al -; X32-NEXT: notb %al +; X32-NEXT: andb $1, %al ; X32-NEXT: movzbl %al, %eax -; X32-NEXT: andl $1, %eax -; X32-NEXT: negl %eax +; X32-NEXT: decl %eax ; X32-NEXT: retl ; ; X64-LABEL: select_0_or_1s_signext: ; X64: # BB#0: -; X64-NEXT: notb %dil +; X64-NEXT: andb $1, %dil ; X64-NEXT: movzbl %dil, %eax -; X64-NEXT: andl $1, %eax -; X64-NEXT: negl %eax +; X64-NEXT: decl %eax ; X64-NEXT: retq %not = xor i1 %cond, 1 %sext = sext i1 %not to i32 |