From 12c2093e1ee8cc814984fc10da0c36a90d12ac43 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Sat, 18 Feb 2017 21:03:28 +0000 Subject: [PATCH] [x86] fold sext (xor Bool, -1) --> sub (zext Bool), 1 This is the same transform that is current used for: select Bool, 0, -1 llvm-svn: 295568 --- llvm/lib/Target/X86/X86ISelLowering.cpp | 10 ++++++++ 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 57d937dd5456..5522c7138b9f 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 935e88d57530..ecda0f4e08cb 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 %EDI %RDI +; 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