mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-20 14:29:27 +00:00
DAGCombiner: fold (xor (shl 1, x), -1) -> (rotl ~1, x)
Targets which provide a rotate make it possible to replace a sequence of (XOR (SHL 1, x), -1) with (ROTL ~1, x). This saves an instruction on architectures like X86 and POWER(64). Differential Revision: http://reviews.llvm.org/D8350 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@232572 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7605cdd6e4
commit
8f01b96d93
@ -3980,6 +3980,32 @@ SDValue DAGCombiner::visitXOR(SDNode *N) {
|
||||
if (N0 == N1)
|
||||
return tryFoldToZero(SDLoc(N), TLI, VT, DAG, LegalOperations, LegalTypes);
|
||||
|
||||
// fold (xor (shl 1, x), -1) -> (rotl ~1, x)
|
||||
// Here is a concrete example of this equivalence:
|
||||
// i16 x == 14
|
||||
// i16 shl == 1 << 14 == 16384 == 0b0100000000000000
|
||||
// i16 xor == ~(1 << 14) == 49151 == 0b1011111111111111
|
||||
//
|
||||
// =>
|
||||
//
|
||||
// i16 ~1 == 0b1111111111111110
|
||||
// i16 rol(~1, 14) == 0b1011111111111111
|
||||
//
|
||||
// Some additional tips to help conceptualize this transform:
|
||||
// - Try to see the operation as placing a single zero in a value of all ones.
|
||||
// - There exists no value for x which would allow the result to contain zero.
|
||||
// - Values of x larger than the bitwidth are undefined and do not require a
|
||||
// consistent result.
|
||||
// - Pushing the zero left requires shifting one bits in from the right.
|
||||
// A rotate left of ~1 is a nice way of achieving the desired result.
|
||||
if (TLI.isOperationLegalOrCustom(ISD::ROTL, VT))
|
||||
if (auto *N1C = dyn_cast<ConstantSDNode>(N1.getNode()))
|
||||
if (N0.getOpcode() == ISD::SHL)
|
||||
if (auto *ShlLHS = dyn_cast<ConstantSDNode>(N0.getOperand(0)))
|
||||
if (N1C->isAllOnesValue() && ShlLHS->isOne())
|
||||
return DAG.getNode(ISD::ROTL, SDLoc(N), VT, DAG.getConstant(~1, VT),
|
||||
N0.getOperand(1));
|
||||
|
||||
// Simplify: xor (op x...), (op y...) -> (op (xor x, y))
|
||||
if (N0.getOpcode() == N1.getOpcode()) {
|
||||
SDValue Tmp = SimplifyBinOpWithSameOpcodeHands(N);
|
||||
|
@ -181,3 +181,15 @@ define i32 @PR17487(i1 %tobool) {
|
||||
; 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]]
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user