diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -56734,9 +56734,11 @@ // X86 can't encode an immediate LHS of a sub. See if we can push the // negation into a preceding instruction. If the RHS of the sub is a XOR with // one use and a constant, invert the immediate, saving one register. + // However, ignore cases where C1 is 0, as those will become a NEG. // sub(C1, xor(X, C2)) -> add(xor(X, ~C2), C1+1) if (Op1.getOpcode() == ISD::XOR && IsNonOpaqueConstant(Op0) && - IsNonOpaqueConstant(Op1.getOperand(1)) && Op1->hasOneUse()) { + !isNullConstant(Op0) && IsNonOpaqueConstant(Op1.getOperand(1)) && + Op1->hasOneUse()) { SDLoc DL(N); EVT VT = Op0.getValueType(); SDValue NewXor = DAG.getNode(ISD::XOR, SDLoc(Op1), VT, Op1.getOperand(0), diff --git a/llvm/test/CodeGen/X86/select-neg.ll b/llvm/test/CodeGen/X86/select-neg.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/select-neg.ll @@ -0,0 +1,17 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=i386-unknown-unknown | FileCheck %s + +@value1 = external hidden constant i32 + +define i32 @function(i32 %arg1) { +; CHECK-LABEL: function: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: movl $value1, %eax +; CHECK-NEXT: xorl {{[0-9]+}}(%esp), %eax +; CHECK-NEXT: negl %eax +; CHECK-NEXT: retl +entry: + %0 = xor i32 %arg1, xor (i32 ptrtoint (i32* @value1 to i32), i32 -1) + %.neg = add i32 %0, 1 + ret i32 %.neg +}