Perform the scalar expression combine in the form of:
CSNEG(1, c, cc) + b => cc ? b+1 : b-c => CSINC(b-c, b, !cc) CSNEG(c, -1, cc) + b => cc ? b+c : b+1 => CSINC(b+c, b, cc)
Differential D119105
[DAGCombiner][AArch64] Enhance to fold CSNEG into CSINC instruction Allen on Feb 6 2022, 9:20 PM. Authored by
Details Perform the scalar expression combine in the form of: CSNEG(1, c, cc) + b => cc ? b+1 : b-c => CSINC(b-c, b, !cc) CSNEG(c, -1, cc) + b => cc ? b+c : b+1 => CSINC(b+c, b, cc)
Diff Detail
Event TimelineComment Actions The code is very similar to the performAddCSelIntoCSinc method. Can they share the same code, with the differences for CSNeg accounted for? Comment Actions Thanks for you comment again! I has tried it before, it seems much complicated, I'll glad to update if you think it's better to share ? // The CSEL should include a const one operand, and the CSNEG should include // One or NegOne operand. ConstantSDNode *CTVal = dyn_cast<ConstantSDNode>(LHS.getOperand(0)); ConstantSDNode *CFVal = dyn_cast<ConstantSDNode>(LHS.getOperand(1)); if (!CTVal || !CFVal) return SDValue(); if (!(LHS.getOpcode() == AArch64ISD::CSEL && (CTVal->isOne() || CFVal->isOne())) || !(LHS.getOpcode() == AArch64ISD::CSNEG && (CTVal->isOne() || CFVal->isAllOnes()))) return SDValue(); // Switch CSEL(1, c, cc) to CSEL(c, 1, !cc) if (LHS.getOpcode() == AArch64ISD::CSEL && CTVal->isOne() && !CFVal->isOne()) { std::swap(CTVal, CFVal); AArch64CC = AArch64CC::getInvertedCondCode(AArch64CC); } SDLoc DL(N); // Switch CSNEG(1, c, cc) to CSNEG(-c, -1, !cc) if (LHS.getOpcode() == AArch64ISD::CSNEG && CTVal->isOne() && !CFVal->isAllOnes()) { int64_t C = -1 * CFVal->getSExtValue(); CTVal = cast<ConstantSDNode>(DAG.getConstant(C, DL, VT)); CFVal = cast<ConstantSDNode>(DAG.getConstant(-1, DL, VT)); AArch64CC = AArch64CC::getInvertedCondCode(AArch64CC); } ... assert((LHS.getOpcode() == AArch64ISD::CSEL && CFVal->isOne() || LHS.getOpcode() == AArch64ISD::CSNEG && CFVal->isAllOnes()) && "Unexpected constant value"); Comment Actions Hmm. I feel like it shares more code than it needs special cases? Maybe try and give it a go, and we can see if it looks too bad. (I had in the past had the idea of removing AArch64ISD::CSNEG/CSINC/CSINV - they are mostly used only for constants as far as I understand and could just as well use CSEL directly. Either that or make sure of them more, canonicalizing more patterns to use them. I don't know what the tradeoffs of those are though. Less target dependant nodes can be a good thing, but more aggressively targeting the nodes we have as opposed to leaving it to chance may be good too. That's just an aside though). Comment Actions Thanks. I think something might not be right in the new logic. Comment Actions Thanks, LGTM with a couple of suggestions.
|
Probably better to avoid the uint64_t and use APInt directly.