Changeset View
Changeset View
Standalone View
Standalone View
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
Show First 20 Lines • Show All 9,554 Lines • ▼ Show 20 Lines | if (SDValue ABD = combineABSToABD(N, DAG, TLI)) | ||||
return ABD; | return ABD; | ||||
return SDValue(); | return SDValue(); | ||||
} | } | ||||
SDValue DAGCombiner::visitBSWAP(SDNode *N) { | SDValue DAGCombiner::visitBSWAP(SDNode *N) { | ||||
SDValue N0 = N->getOperand(0); | SDValue N0 = N->getOperand(0); | ||||
EVT VT = N->getValueType(0); | EVT VT = N->getValueType(0); | ||||
SDLoc DL(N); | |||||
// fold (bswap c1) -> c2 | // fold (bswap c1) -> c2 | ||||
if (DAG.isConstantIntBuildVectorOrConstantInt(N0)) | if (DAG.isConstantIntBuildVectorOrConstantInt(N0)) | ||||
return DAG.getNode(ISD::BSWAP, SDLoc(N), VT, N0); | return DAG.getNode(ISD::BSWAP, DL, VT, N0); | ||||
// fold (bswap (bswap x)) -> x | // fold (bswap (bswap x)) -> x | ||||
if (N0.getOpcode() == ISD::BSWAP) | if (N0.getOpcode() == ISD::BSWAP) | ||||
return N0->getOperand(0); | return N0.getOperand(0); | ||||
// Canonicalize bswap(bitreverse(x)) -> bitreverse(bswap(x)). If bitreverse | // Canonicalize bswap(bitreverse(x)) -> bitreverse(bswap(x)). If bitreverse | ||||
// isn't supported, it will be expanded to bswap followed by a manual reversal | // isn't supported, it will be expanded to bswap followed by a manual reversal | ||||
// of bits in each byte. By placing bswaps before bitreverse, we can remove | // of bits in each byte. By placing bswaps before bitreverse, we can remove | ||||
// the two bswaps if the bitreverse gets expanded. | // the two bswaps if the bitreverse gets expanded. | ||||
if (N0.getOpcode() == ISD::BITREVERSE && N0.hasOneUse()) { | if (N0.getOpcode() == ISD::BITREVERSE && N0.hasOneUse()) { | ||||
SDLoc DL(N); | |||||
SDValue BSwap = DAG.getNode(ISD::BSWAP, DL, VT, N0.getOperand(0)); | SDValue BSwap = DAG.getNode(ISD::BSWAP, DL, VT, N0.getOperand(0)); | ||||
return DAG.getNode(ISD::BITREVERSE, DL, VT, BSwap); | return DAG.getNode(ISD::BITREVERSE, DL, VT, BSwap); | ||||
} | } | ||||
// fold (bswap shl(x,c)) -> (zext(bswap(trunc(shl(x,sub(c,bw/2)))))) | |||||
// iff x >= bw/2 (i.e. lower half is known zero) | |||||
unsigned BW = VT.getScalarSizeInBits(); | |||||
if (BW >= 32 && N0.getOpcode() == ISD::SHL && N->isOnlyUserOf(N0.getNode())) { | |||||
spatel: Is this intentionally different than the usual "N0.hasOneUse()"? | |||||
Not Done ReplyInline ActionsI'll change it - I'm just used to writing it that way to handle binops with duplicated ops. RKSimon: I'll change it - I'm just used to writing it that way to handle binops with duplicated ops. | |||||
auto *ShAmt = dyn_cast<ConstantSDNode>(N0.getOperand(1)); | |||||
EVT HalfVT = EVT::getIntegerVT(*DAG.getContext(), BW / 2); | |||||
if (ShAmt && ShAmt->getAPIntValue().uge(BW / 2) && | |||||
TLI.isTruncateFree(VT, HalfVT) && | |||||
(!LegalOperations || hasOperation(ISD::BSWAP, HalfVT))) { | |||||
Not Done ReplyInline ActionsIf I'm seeing it correctly, we need to either tighten this clause by removing !LegalOperations or add the "BW % 16" requirement. As-is (and we probably want a test either way), we could end up worse. For example on AArch64: define i32 @test_bswap32_shift17(i32 %a0) { %s = shl i32 %a0, 17 %b = call i32 @llvm.bswap.i32(i32 %s) ret i32 %b } is: lsl w8, w0, #17 rev w0, w8 but this patch would make it: lsl w8, w0, #1 rev w8, w8 lsr w0, w8, #16 spatel: If I'm seeing it correctly, we need to either tighten this clause by removing !LegalOperations… | |||||
Not Done ReplyInline ActionsYeah, I figured allowing any shift amount was probably too far - I'll reduce it to (ShAmt %16) == 0 - its what I've been doing on the InstCombine variant that I'm still working on. RKSimon: Yeah, I figured allowing any shift amount was probably too far - I'll reduce it to (ShAmt %16)… | |||||
SDValue Res = N0.getOperand(0); | |||||
if (uint64_t NewShAmt = (ShAmt->getZExtValue() - (BW / 2))) { | |||||
EVT ShiftAmtVT = N0.getOperand(1).getValueType(); | |||||
Not Done ReplyInline ActionsShould we go through getShiftAmountTy? craig.topper: Should we go through getShiftAmountTy? | |||||
Res = DAG.getNode(ISD::SHL, DL, VT, Res, | |||||
DAG.getConstant(NewShAmt, DL, ShiftAmtVT)); | |||||
} | |||||
Res = DAG.getZExtOrTrunc(Res, DL, HalfVT); | |||||
Res = DAG.getNode(ISD::BSWAP, DL, HalfVT, Res); | |||||
return DAG.getZExtOrTrunc(Res, DL, VT); | |||||
} | |||||
} | |||||
return SDValue(); | return SDValue(); | ||||
} | } | ||||
SDValue DAGCombiner::visitBITREVERSE(SDNode *N) { | SDValue DAGCombiner::visitBITREVERSE(SDNode *N) { | ||||
SDValue N0 = N->getOperand(0); | SDValue N0 = N->getOperand(0); | ||||
EVT VT = N->getValueType(0); | EVT VT = N->getValueType(0); | ||||
// fold (bitreverse c1) -> c2 | // fold (bitreverse c1) -> c2 | ||||
▲ Show 20 Lines • Show All 9,991 Lines • Show Last 20 Lines |
Is this intentionally different than the usual "N0.hasOneUse()"?