Changeset 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 458 Lines • ▼ Show 20 Lines | private: | ||||
SDValue visitSIGN_EXTEND_INREG(SDNode *N); | SDValue visitSIGN_EXTEND_INREG(SDNode *N); | ||||
SDValue visitSIGN_EXTEND_VECTOR_INREG(SDNode *N); | SDValue visitSIGN_EXTEND_VECTOR_INREG(SDNode *N); | ||||
SDValue visitZERO_EXTEND_VECTOR_INREG(SDNode *N); | SDValue visitZERO_EXTEND_VECTOR_INREG(SDNode *N); | ||||
SDValue visitTRUNCATE(SDNode *N); | SDValue visitTRUNCATE(SDNode *N); | ||||
SDValue visitBITCAST(SDNode *N); | SDValue visitBITCAST(SDNode *N); | ||||
SDValue visitFREEZE(SDNode *N); | SDValue visitFREEZE(SDNode *N); | ||||
SDValue visitBUILD_PAIR(SDNode *N); | SDValue visitBUILD_PAIR(SDNode *N); | ||||
SDValue visitFADD(SDNode *N); | SDValue visitFADD(SDNode *N); | ||||
SDValue visitSTRICT_FADD(SDNode *N); | |||||
SDValue visitFSUB(SDNode *N); | SDValue visitFSUB(SDNode *N); | ||||
SDValue visitFMUL(SDNode *N); | SDValue visitFMUL(SDNode *N); | ||||
SDValue visitFMA(SDNode *N); | SDValue visitFMA(SDNode *N); | ||||
SDValue visitFDIV(SDNode *N); | SDValue visitFDIV(SDNode *N); | ||||
SDValue visitFREM(SDNode *N); | SDValue visitFREM(SDNode *N); | ||||
SDValue visitFSQRT(SDNode *N); | SDValue visitFSQRT(SDNode *N); | ||||
SDValue visitFCOPYSIGN(SDNode *N); | SDValue visitFCOPYSIGN(SDNode *N); | ||||
SDValue visitFPOW(SDNode *N); | SDValue visitFPOW(SDNode *N); | ||||
▲ Show 20 Lines • Show All 1,170 Lines • ▼ Show 20 Lines | SDValue DAGCombiner::visit(SDNode *N) { | ||||
case ISD::AssertAlign: return visitAssertAlign(N); | case ISD::AssertAlign: return visitAssertAlign(N); | ||||
case ISD::SIGN_EXTEND_INREG: return visitSIGN_EXTEND_INREG(N); | case ISD::SIGN_EXTEND_INREG: return visitSIGN_EXTEND_INREG(N); | ||||
case ISD::SIGN_EXTEND_VECTOR_INREG: return visitSIGN_EXTEND_VECTOR_INREG(N); | case ISD::SIGN_EXTEND_VECTOR_INREG: return visitSIGN_EXTEND_VECTOR_INREG(N); | ||||
case ISD::ZERO_EXTEND_VECTOR_INREG: return visitZERO_EXTEND_VECTOR_INREG(N); | case ISD::ZERO_EXTEND_VECTOR_INREG: return visitZERO_EXTEND_VECTOR_INREG(N); | ||||
case ISD::TRUNCATE: return visitTRUNCATE(N); | case ISD::TRUNCATE: return visitTRUNCATE(N); | ||||
case ISD::BITCAST: return visitBITCAST(N); | case ISD::BITCAST: return visitBITCAST(N); | ||||
case ISD::BUILD_PAIR: return visitBUILD_PAIR(N); | case ISD::BUILD_PAIR: return visitBUILD_PAIR(N); | ||||
case ISD::FADD: return visitFADD(N); | case ISD::FADD: return visitFADD(N); | ||||
case ISD::STRICT_FADD: return visitSTRICT_FADD(N); | |||||
case ISD::FSUB: return visitFSUB(N); | case ISD::FSUB: return visitFSUB(N); | ||||
case ISD::FMUL: return visitFMUL(N); | case ISD::FMUL: return visitFMUL(N); | ||||
case ISD::FMA: return visitFMA(N); | case ISD::FMA: return visitFMA(N); | ||||
case ISD::FDIV: return visitFDIV(N); | case ISD::FDIV: return visitFDIV(N); | ||||
case ISD::FREM: return visitFREM(N); | case ISD::FREM: return visitFREM(N); | ||||
case ISD::FSQRT: return visitFSQRT(N); | case ISD::FSQRT: return visitFSQRT(N); | ||||
case ISD::FCOPYSIGN: return visitFCOPYSIGN(N); | case ISD::FCOPYSIGN: return visitFCOPYSIGN(N); | ||||
case ISD::FPOW: return visitFPOW(N); | case ISD::FPOW: return visitFPOW(N); | ||||
▲ Show 20 Lines • Show All 11,167 Lines • ▼ Show 20 Lines | SDValue DAGCombiner::visitFADD(SDNode *N) { | ||||
// FADD -> FMA combines: | // FADD -> FMA combines: | ||||
if (SDValue Fused = visitFADDForFMACombine(N)) { | if (SDValue Fused = visitFADDForFMACombine(N)) { | ||||
AddToWorklist(Fused.getNode()); | AddToWorklist(Fused.getNode()); | ||||
return Fused; | return Fused; | ||||
} | } | ||||
return SDValue(); | return SDValue(); | ||||
} | } | ||||
SDValue DAGCombiner::visitSTRICT_FADD(SDNode *N) { | |||||
SDValue Chain = N->getOperand(0); | |||||
SDValue N0 = N->getOperand(1); | |||||
SDValue N1 = N->getOperand(2); | |||||
EVT VT = N->getValueType(0); | |||||
EVT ChainVT = N->getValueType(1); | |||||
SDLoc DL(N); | |||||
const SDNodeFlags Flags = N->getFlags(); | |||||
// fold (strict_fadd A, (fneg B)) -> (strict_fsub A, B) | |||||
if (!LegalOperations || TLI.isOperationLegalOrCustom(ISD::STRICT_FSUB, VT)) | |||||
arsenm: There is some strange legality predicate you are supposed to use for the strict cases, although… | |||||
Not Done ReplyInline ActionsWhere is this predicate? Is there an existing case that can be modeled after? My thinking is that this transform is probably safe because the FNeg will never trap and it will never round so it should therefore be safe to fold it into the add/sub. But I'm no expert on floating-point I admit. kpn: Where is this predicate? Is there an existing case that can be modeled after?
My thinking is… | |||||
Not Done ReplyInline ActionsThis is totally valid. But for some reason, we have getStrictFPOperationAction which differs from checking the regular legalization action on the STRICT_ opcode arsenm: This is totally valid. But for some reason, we have getStrictFPOperationAction which differs… | |||||
Not Done ReplyInline ActionsI think getStrictFPOperationAction works along with the code in SelectionDAGISel that mutates strict nodes to non-strict nodes for targets that haven't done the work. It was intended to query whether the target will be able to handle the mutated node. It should go away when all targets have done the work. Since I think we're now blocking clang from using strict fp on targets that haven't done the work. Then we probably can just use the normal legal operation check. craig.topper: I think getStrictFPOperationAction works along with the code in SelectionDAGISel that mutates… | |||||
As far as I can tell, that comes into play later on as craig topper has stated. I don't think there's any way for that to apply during combination. Here we have to rely on operations that we can be sure are legal. As long as this operation is legal according to the standard (I'm also no expert, but I'm pretty sure based on my interpretation) exceptions should still occur as the original code prescribes, and in the same order as such. ajwock: As far as I can tell, that comes into play later on as craig topper has stated. I don't think… | |||||
if (SDValue NegN1 = TLI.getCheaperNegatedExpression( | |||||
N1, DAG, LegalOperations, ForCodeSize)) { | |||||
return DAG.getNode(ISD::STRICT_FSUB, DL, DAG.getVTList(VT, ChainVT), | |||||
{Chain, N0, NegN1}, Flags); | |||||
} | |||||
// fold (strict_fadd (fneg A), B) -> (strict_fsub B, A) | |||||
if (!LegalOperations || TLI.isOperationLegalOrCustom(ISD::STRICT_FSUB, VT)) | |||||
if (SDValue NegN0 = TLI.getCheaperNegatedExpression( | |||||
N0, DAG, LegalOperations, ForCodeSize)) { | |||||
return DAG.getNode(ISD::STRICT_FSUB, DL, DAG.getVTList(VT, ChainVT), | |||||
{Chain, N1, NegN0}, Flags); | |||||
} | |||||
return SDValue(); | |||||
} | |||||
SDValue DAGCombiner::visitFSUB(SDNode *N) { | SDValue DAGCombiner::visitFSUB(SDNode *N) { | ||||
SDValue N0 = N->getOperand(0); | SDValue N0 = N->getOperand(0); | ||||
SDValue N1 = N->getOperand(1); | SDValue N1 = N->getOperand(1); | ||||
ConstantFPSDNode *N0CFP = isConstOrConstSplatFP(N0, true); | ConstantFPSDNode *N0CFP = isConstOrConstSplatFP(N0, true); | ||||
ConstantFPSDNode *N1CFP = isConstOrConstSplatFP(N1, true); | ConstantFPSDNode *N1CFP = isConstOrConstSplatFP(N1, true); | ||||
EVT VT = N->getValueType(0); | EVT VT = N->getValueType(0); | ||||
SDLoc DL(N); | SDLoc DL(N); | ||||
const TargetOptions &Options = DAG.getTarget().Options; | const TargetOptions &Options = DAG.getTarget().Options; | ||||
▲ Show 20 Lines • Show All 9,380 Lines • Show Last 20 Lines |
There is some strange legality predicate you are supposed to use for the strict cases, although I don't fully understand it