Please use GitHub pull requests for new patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
llvm/lib/Target/PowerPC/PPCISelLowering.cpp
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
Show First 20 Lines • Show All 1,293 Lines • ▼ Show 20 Lines | if (Subtarget.hasP9Altivec()) { | ||||
} | } | ||||
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::v4i8, Legal); | setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::v4i8, Legal); | ||||
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::v4i16, Legal); | setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::v4i16, Legal); | ||||
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::v4i32, Legal); | setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::v4i32, Legal); | ||||
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::v2i8, Legal); | setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::v2i8, Legal); | ||||
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::v2i16, Legal); | setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::v2i16, Legal); | ||||
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::v2i32, Legal); | setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::v2i32, Legal); | ||||
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::v2i64, Legal); | setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::v2i64, Legal); | ||||
setOperationAction(ISD::ABDU, MVT::v16i8, Legal); | |||||
setOperationAction(ISD::ABDU, MVT::v8i16, Legal); | |||||
setOperationAction(ISD::ABDU, MVT::v4i32, Legal); | |||||
setOperationAction(ISD::ABDS, MVT::v4i32, Legal); | |||||
} | } | ||||
if (Subtarget.hasP10Vector()) { | if (Subtarget.hasP10Vector()) { | ||||
setOperationAction(ISD::SELECT_CC, MVT::f128, Custom); | setOperationAction(ISD::SELECT_CC, MVT::f128, Custom); | ||||
} | } | ||||
} | } | ||||
if (Subtarget.pairedVectorMemops()) { | if (Subtarget.pairedVectorMemops()) { | ||||
▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Lines | |||||
setTargetDAGCombine({ISD::TRUNCATE, ISD::VECTOR_SHUFFLE}); | setTargetDAGCombine({ISD::TRUNCATE, ISD::VECTOR_SHUFFLE}); | ||||
if (Subtarget.useCRBits()) { | if (Subtarget.useCRBits()) { | ||||
setTargetDAGCombine({ISD::TRUNCATE, ISD::SETCC, ISD::SELECT_CC}); | setTargetDAGCombine({ISD::TRUNCATE, ISD::SETCC, ISD::SELECT_CC}); | ||||
} | } | ||||
if (Subtarget.hasP9Altivec()) { | if (Subtarget.hasP9Altivec()) { | ||||
setTargetDAGCombine({ISD::ABS, ISD::VSELECT}); | setTargetDAGCombine({ISD::VSELECT}); | ||||
} | } | ||||
setLibcallName(RTLIB::LOG_F128, "logf128"); | setLibcallName(RTLIB::LOG_F128, "logf128"); | ||||
setLibcallName(RTLIB::LOG2_F128, "log2f128"); | setLibcallName(RTLIB::LOG2_F128, "log2f128"); | ||||
setLibcallName(RTLIB::LOG10_F128, "log10f128"); | setLibcallName(RTLIB::LOG10_F128, "log10f128"); | ||||
setLibcallName(RTLIB::EXP_F128, "expf128"); | setLibcallName(RTLIB::EXP_F128, "expf128"); | ||||
setLibcallName(RTLIB::EXP2_F128, "exp2f128"); | setLibcallName(RTLIB::EXP2_F128, "exp2f128"); | ||||
setLibcallName(RTLIB::SIN_F128, "sinf128"); | setLibcallName(RTLIB::SIN_F128, "sinf128"); | ||||
▲ Show 20 Lines • Show All 347 Lines • ▼ Show 20 Lines | case PPCISD::PADDI_DTPREL: | ||||
return "PPCISD::PADDI_DTPREL"; | return "PPCISD::PADDI_DTPREL"; | ||||
case PPCISD::VADD_SPLAT: return "PPCISD::VADD_SPLAT"; | case PPCISD::VADD_SPLAT: return "PPCISD::VADD_SPLAT"; | ||||
case PPCISD::SC: return "PPCISD::SC"; | case PPCISD::SC: return "PPCISD::SC"; | ||||
case PPCISD::CLRBHRB: return "PPCISD::CLRBHRB"; | case PPCISD::CLRBHRB: return "PPCISD::CLRBHRB"; | ||||
case PPCISD::MFBHRBE: return "PPCISD::MFBHRBE"; | case PPCISD::MFBHRBE: return "PPCISD::MFBHRBE"; | ||||
case PPCISD::RFEBB: return "PPCISD::RFEBB"; | case PPCISD::RFEBB: return "PPCISD::RFEBB"; | ||||
case PPCISD::XXSWAPD: return "PPCISD::XXSWAPD"; | case PPCISD::XXSWAPD: return "PPCISD::XXSWAPD"; | ||||
case PPCISD::SWAP_NO_CHAIN: return "PPCISD::SWAP_NO_CHAIN"; | case PPCISD::SWAP_NO_CHAIN: return "PPCISD::SWAP_NO_CHAIN"; | ||||
case PPCISD::VABSD: return "PPCISD::VABSD"; | |||||
case PPCISD::BUILD_FP128: return "PPCISD::BUILD_FP128"; | case PPCISD::BUILD_FP128: return "PPCISD::BUILD_FP128"; | ||||
case PPCISD::BUILD_SPE64: return "PPCISD::BUILD_SPE64"; | case PPCISD::BUILD_SPE64: return "PPCISD::BUILD_SPE64"; | ||||
case PPCISD::EXTRACT_SPE: return "PPCISD::EXTRACT_SPE"; | case PPCISD::EXTRACT_SPE: return "PPCISD::EXTRACT_SPE"; | ||||
case PPCISD::EXTSWSLI: return "PPCISD::EXTSWSLI"; | case PPCISD::EXTSWSLI: return "PPCISD::EXTSWSLI"; | ||||
case PPCISD::LD_VSX_LH: return "PPCISD::LD_VSX_LH"; | case PPCISD::LD_VSX_LH: return "PPCISD::LD_VSX_LH"; | ||||
case PPCISD::FP_EXTEND_HALF: return "PPCISD::FP_EXTEND_HALF"; | case PPCISD::FP_EXTEND_HALF: return "PPCISD::FP_EXTEND_HALF"; | ||||
case PPCISD::MAT_PCREL_ADDR: return "PPCISD::MAT_PCREL_ADDR"; | case PPCISD::MAT_PCREL_ADDR: return "PPCISD::MAT_PCREL_ADDR"; | ||||
case PPCISD::TLS_DYNAMIC_MAT_PCREL_ADDR: | case PPCISD::TLS_DYNAMIC_MAT_PCREL_ADDR: | ||||
▲ Show 20 Lines • Show All 14,267 Lines • ▼ Show 20 Lines | if (LHS.getOpcode() == ISD::INTRINSIC_WO_CHAIN && | ||||
DAG.getConstant(CompOpc, dl, MVT::i32), | DAG.getConstant(CompOpc, dl, MVT::i32), | ||||
DAG.getRegister(PPC::CR6, MVT::i32), | DAG.getRegister(PPC::CR6, MVT::i32), | ||||
N->getOperand(4), CompNode.getValue(1)); | N->getOperand(4), CompNode.getValue(1)); | ||||
} | } | ||||
break; | break; | ||||
} | } | ||||
case ISD::BUILD_VECTOR: | case ISD::BUILD_VECTOR: | ||||
return DAGCombineBuildVector(N, DCI); | return DAGCombineBuildVector(N, DCI); | ||||
case ISD::ABS: | |||||
return combineABS(N, DCI); | |||||
case ISD::VSELECT: | case ISD::VSELECT: | ||||
return combineVSelect(N, DCI); | return combineVSelect(N, DCI); | ||||
} | } | ||||
return SDValue(); | return SDValue(); | ||||
} | } | ||||
SDValue | SDValue | ||||
▲ Show 20 Lines • Show All 1,411 Lines • ▼ Show 20 Lines | if (Subtarget.useCRBits()) { | ||||
// Check if CRBits did anything and return that if it did. | // Check if CRBits did anything and return that if it did. | ||||
if (SDValue CRTruncValue = DAGCombineTruncBoolExt(N, DCI)) | if (SDValue CRTruncValue = DAGCombineTruncBoolExt(N, DCI)) | ||||
return CRTruncValue; | return CRTruncValue; | ||||
} | } | ||||
SDLoc dl(N); | SDLoc dl(N); | ||||
SDValue Op0 = N->getOperand(0); | SDValue Op0 = N->getOperand(0); | ||||
// fold (truncate (abs (sub (zext a), (zext b)))) -> (vabsd a, b) | |||||
if (Subtarget.hasP9Altivec() && Op0.getOpcode() == ISD::ABS) { | |||||
EVT VT = N->getValueType(0); | |||||
if (VT != MVT::v4i32 && VT != MVT::v8i16 && VT != MVT::v16i8) | |||||
return SDValue(); | |||||
SDValue Sub = Op0.getOperand(0); | |||||
if (Sub.getOpcode() == ISD::SUB) { | |||||
SDValue SubOp0 = Sub.getOperand(0); | |||||
SDValue SubOp1 = Sub.getOperand(1); | |||||
if ((SubOp0.getOpcode() == ISD::ZERO_EXTEND) && | |||||
(SubOp1.getOpcode() == ISD::ZERO_EXTEND)) { | |||||
return DCI.DAG.getNode(PPCISD::VABSD, dl, VT, SubOp0.getOperand(0), | |||||
SubOp1.getOperand(0), | |||||
DCI.DAG.getTargetConstant(0, dl, MVT::i32)); | |||||
} | |||||
} | |||||
} | |||||
// Looking for a truncate of i128 to i64. | // Looking for a truncate of i128 to i64. | ||||
if (Op0.getValueType() != MVT::i128 || N->getValueType(0) != MVT::i64) | if (Op0.getValueType() != MVT::i128 || N->getValueType(0) != MVT::i64) | ||||
return SDValue(); | return SDValue(); | ||||
int EltToExtract = DCI.DAG.getDataLayout().isBigEndian() ? 1 : 0; | int EltToExtract = DCI.DAG.getDataLayout().isBigEndian() ? 1 : 0; | ||||
// SRL feeding TRUNCATE. | // SRL feeding TRUNCATE. | ||||
if (Op0.getOpcode() == ISD::SRL) { | if (Op0.getOpcode() == ISD::SRL) { | ||||
▲ Show 20 Lines • Show All 183 Lines • ▼ Show 20 Lines | if (const ConstantInt *CI = dyn_cast<ConstantInt>(Mask)) { | ||||
int64_t ConstVal = CI->getZExtValue(); | int64_t ConstVal = CI->getZExtValue(); | ||||
return isUInt<16>(ConstVal) || | return isUInt<16>(ConstVal) || | ||||
(isUInt<16>(ConstVal >> 16) && !(ConstVal & 0xFFFF)); | (isUInt<16>(ConstVal >> 16) && !(ConstVal & 0xFFFF)); | ||||
} | } | ||||
// For non-constant masks, we can always use the record-form and. | // For non-constant masks, we can always use the record-form and. | ||||
return true; | return true; | ||||
} | } | ||||
// Transform (abs (sub (zext a), (zext b))) to (vabsd a b 0) | |||||
// Transform (abs (sub (zext a), (zext_invec b))) to (vabsd a b 0) | |||||
// Transform (abs (sub (zext_invec a), (zext_invec b))) to (vabsd a b 0) | |||||
// Transform (abs (sub (zext_invec a), (zext b))) to (vabsd a b 0) | |||||
// Transform (abs (sub a, b) to (vabsd a b 1)) if a & b of type v4i32 | |||||
SDValue PPCTargetLowering::combineABS(SDNode *N, DAGCombinerInfo &DCI) const { | |||||
assert((N->getOpcode() == ISD::ABS) && "Need ABS node here"); | |||||
assert(Subtarget.hasP9Altivec() && | |||||
"Only combine this when P9 altivec supported!"); | |||||
EVT VT = N->getValueType(0); | |||||
if (VT != MVT::v4i32 && VT != MVT::v8i16 && VT != MVT::v16i8) | |||||
return SDValue(); | |||||
SelectionDAG &DAG = DCI.DAG; | |||||
SDLoc dl(N); | |||||
if (N->getOperand(0).getOpcode() == ISD::SUB) { | |||||
// Even for signed integers, if it's known to be positive (as signed | |||||
// integer) due to zero-extended inputs. | |||||
unsigned SubOpcd0 = N->getOperand(0)->getOperand(0).getOpcode(); | |||||
unsigned SubOpcd1 = N->getOperand(0)->getOperand(1).getOpcode(); | |||||
if ((SubOpcd0 == ISD::ZERO_EXTEND || | |||||
SubOpcd0 == ISD::ZERO_EXTEND_VECTOR_INREG) && | |||||
(SubOpcd1 == ISD::ZERO_EXTEND || | |||||
SubOpcd1 == ISD::ZERO_EXTEND_VECTOR_INREG)) { | |||||
return DAG.getNode(PPCISD::VABSD, dl, N->getOperand(0).getValueType(), | |||||
N->getOperand(0)->getOperand(0), | |||||
N->getOperand(0)->getOperand(1), | |||||
DAG.getTargetConstant(0, dl, MVT::i32)); | |||||
} | |||||
// For type v4i32, it can be optimized with xvnegsp + vabsduw | |||||
if (N->getOperand(0).getValueType() == MVT::v4i32 && | |||||
N->getOperand(0).hasOneUse()) { | |||||
return DAG.getNode(PPCISD::VABSD, dl, N->getOperand(0).getValueType(), | |||||
N->getOperand(0)->getOperand(0), | |||||
N->getOperand(0)->getOperand(1), | |||||
DAG.getTargetConstant(1, dl, MVT::i32)); | |||||
} | |||||
} | |||||
return SDValue(); | |||||
} | |||||
// For type v4i32/v8ii16/v16i8, transform | // For type v4i32/v8ii16/v16i8, transform | ||||
RKSimon: I'm wondering if this is actually correct? If there had been… | |||||
// from (vselect (setcc a, b, setugt), (sub a, b), (sub b, a)) to (vabsd a, b) | // from (vselect (setcc a, b, setugt), (sub a, b), (sub b, a)) to (abdu a, b) | ||||
// from (vselect (setcc a, b, setuge), (sub a, b), (sub b, a)) to (vabsd a, b) | // from (vselect (setcc a, b, setuge), (sub a, b), (sub b, a)) to (abdu a, b) | ||||
// from (vselect (setcc a, b, setult), (sub b, a), (sub a, b)) to (vabsd a, b) | // from (vselect (setcc a, b, setult), (sub b, a), (sub a, b)) to (abdu a, b) | ||||
// from (vselect (setcc a, b, setule), (sub b, a), (sub a, b)) to (vabsd a, b) | // from (vselect (setcc a, b, setule), (sub b, a), (sub a, b)) to (abdu a, b) | ||||
// TODO: Move this to DAGCombiner? | |||||
SDValue PPCTargetLowering::combineVSelect(SDNode *N, | SDValue PPCTargetLowering::combineVSelect(SDNode *N, | ||||
DAGCombinerInfo &DCI) const { | DAGCombinerInfo &DCI) const { | ||||
assert((N->getOpcode() == ISD::VSELECT) && "Need VSELECT node here"); | assert((N->getOpcode() == ISD::VSELECT) && "Need VSELECT node here"); | ||||
assert(Subtarget.hasP9Altivec() && | assert(Subtarget.hasP9Altivec() && | ||||
"Only combine this when P9 altivec supported!"); | "Only combine this when P9 altivec supported!"); | ||||
SelectionDAG &DAG = DCI.DAG; | SelectionDAG &DAG = DCI.DAG; | ||||
SDLoc dl(N); | SDLoc dl(N); | ||||
Show All 34 Lines | SDValue PPCTargetLowering::combineVSelect(SDNode *N, | ||||
// SETCC CmpOpnd1 CmpOpnd2 cond | // SETCC CmpOpnd1 CmpOpnd2 cond | ||||
// TrueOpnd = CmpOpnd1 - CmpOpnd2 | // TrueOpnd = CmpOpnd1 - CmpOpnd2 | ||||
// FalseOpnd = CmpOpnd2 - CmpOpnd1 | // FalseOpnd = CmpOpnd2 - CmpOpnd1 | ||||
if (TrueOpnd.getOperand(0) == CmpOpnd1 && | if (TrueOpnd.getOperand(0) == CmpOpnd1 && | ||||
TrueOpnd.getOperand(1) == CmpOpnd2 && | TrueOpnd.getOperand(1) == CmpOpnd2 && | ||||
FalseOpnd.getOperand(0) == CmpOpnd2 && | FalseOpnd.getOperand(0) == CmpOpnd2 && | ||||
FalseOpnd.getOperand(1) == CmpOpnd1) { | FalseOpnd.getOperand(1) == CmpOpnd1) { | ||||
return DAG.getNode(PPCISD::VABSD, dl, N->getOperand(1).getValueType(), | return DAG.getNode(ISD::ABDU, dl, N->getOperand(1).getValueType(), CmpOpnd1, | ||||
CmpOpnd1, CmpOpnd2, | CmpOpnd2, DAG.getTargetConstant(0, dl, MVT::i32)); | ||||
DAG.getTargetConstant(0, dl, MVT::i32)); | |||||
} | } | ||||
return SDValue(); | return SDValue(); | ||||
} | } | ||||
/// getAddrModeForFlags - Based on the set of address flags, select the most | /// getAddrModeForFlags - Based on the set of address flags, select the most | ||||
/// optimal instruction format to match by. | /// optimal instruction format to match by. | ||||
PPC::AddrMode PPCTargetLowering::getAddrModeForFlags(unsigned Flags) const { | PPC::AddrMode PPCTargetLowering::getAddrModeForFlags(unsigned Flags) const { | ||||
▲ Show 20 Lines • Show All 665 Lines • Show Last 20 Lines |
I'm wondering if this is actually correct? If there had been SIGN_EXTEND/SIGN_EXTEND_VECTOR_INREG equivalent nodes to the previous ABDU pattern then this would be ABSD.
https://alive2.llvm.org/ce/z/k8wpeF