Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -3980,6 +3980,15 @@ if (N0 == N1) return tryFoldToZero(SDLoc(N), TLI, VT, DAG, LegalOperations, LegalTypes); + // fold (xor (shl 1, x), -1) -> (rotl -2, x) + if (TLI.isOperationLegalOrCustom(ISD::ROTL, VT)) + if (auto *N1C = dyn_cast(N1.getNode())) + if (N0.getOpcode() == ISD::SHL) + if (auto *ShlLHS = dyn_cast(N0.getOperand(0))) + if (N1C->isAllOnesValue() && ShlLHS->isOne()) + return DAG.getNode(ISD::ROTL, SDLoc(N), VT, DAG.getConstant(-2, VT), + N0.getOperand(1)); + // Simplify: xor (op x...), (op y...) -> (op (xor x, y)) if (N0.getOpcode() == N1.getOpcode()) { SDValue Tmp = SimplifyBinOpWithSameOpcodeHands(N); Index: test/CodeGen/X86/xor.ll =================================================================== --- test/CodeGen/X86/xor.ll +++ test/CodeGen/X86/xor.ll @@ -181,3 +181,15 @@ ; X32-LABEL: PR17487: ; X32: andn } + +define i32 @test11(i32 %b) { + %shl = shl i32 1, %b + %neg = xor i32 %shl, -1 + ret i32 %neg +; X64-LABEL: test11: +; X64: movl $-2, %[[REG:.*]] +; X64: roll %{{.*}}, %[[REG]] +; X32-LABEL: test11: +; X32: movl $-2, %[[REG:.*]] +; X32: roll %{{.*}}, %[[REG]] +}