aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/RISCV/RISCVISelLowering.cpp')
-rw-r--r--llvm/lib/Target/RISCV/RISCVISelLowering.cpp137
1 files changed, 65 insertions, 72 deletions
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index cda64ae..6c58989 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -5104,6 +5104,7 @@ static SDValue lowerShuffleViaVRegSplitting(ShuffleVectorSDNode *SVN,
SDValue V1 = SVN->getOperand(0);
SDValue V2 = SVN->getOperand(1);
ArrayRef<int> Mask = SVN->getMask();
+ unsigned NumElts = VT.getVectorNumElements();
// If we don't know exact data layout, not much we can do. If this
// is already m1 or smaller, no point in splitting further.
@@ -5120,70 +5121,58 @@ static SDValue lowerShuffleViaVRegSplitting(ShuffleVectorSDNode *SVN,
MVT ElemVT = VT.getVectorElementType();
unsigned ElemsPerVReg = *VLen / ElemVT.getFixedSizeInBits();
+ unsigned VRegsPerSrc = NumElts / ElemsPerVReg;
+
+ SmallVector<std::pair<int, SmallVector<int>>>
+ OutMasks(VRegsPerSrc, {-1, {}});
+
+ // Check if our mask can be done as a 1-to-1 mapping from source
+ // to destination registers in the group without needing to
+ // write each destination more than once.
+ for (unsigned DstIdx = 0; DstIdx < Mask.size(); DstIdx++) {
+ int DstVecIdx = DstIdx / ElemsPerVReg;
+ int DstSubIdx = DstIdx % ElemsPerVReg;
+ int SrcIdx = Mask[DstIdx];
+ if (SrcIdx < 0 || (unsigned)SrcIdx >= 2 * NumElts)
+ continue;
+ int SrcVecIdx = SrcIdx / ElemsPerVReg;
+ int SrcSubIdx = SrcIdx % ElemsPerVReg;
+ if (OutMasks[DstVecIdx].first == -1)
+ OutMasks[DstVecIdx].first = SrcVecIdx;
+ if (OutMasks[DstVecIdx].first != SrcVecIdx)
+ // Note: This case could easily be handled by keeping track of a chain
+ // of source values and generating two element shuffles below. This is
+ // less an implementation question, and more a profitability one.
+ return SDValue();
+
+ OutMasks[DstVecIdx].second.resize(ElemsPerVReg, -1);
+ OutMasks[DstVecIdx].second[DstSubIdx] = SrcSubIdx;
+ }
EVT ContainerVT = getContainerForFixedLengthVector(DAG, VT, Subtarget);
MVT OneRegVT = MVT::getVectorVT(ElemVT, ElemsPerVReg);
MVT M1VT = getContainerForFixedLengthVector(DAG, OneRegVT, Subtarget);
assert(M1VT == getLMUL1VT(M1VT));
unsigned NumOpElts = M1VT.getVectorMinNumElements();
- unsigned NormalizedVF = ContainerVT.getVectorMinNumElements();
- unsigned NumOfSrcRegs = NormalizedVF / NumOpElts;
- unsigned NumOfDestRegs = NormalizedVF / NumOpElts;
+ SDValue Vec = DAG.getUNDEF(ContainerVT);
// The following semantically builds up a fixed length concat_vector
// of the component shuffle_vectors. We eagerly lower to scalable here
// to avoid DAG combining it back to a large shuffle_vector again.
V1 = convertToScalableVector(ContainerVT, V1, DAG, Subtarget);
V2 = convertToScalableVector(ContainerVT, V2, DAG, Subtarget);
- SmallVector<SDValue> SubRegs(NumOfDestRegs);
- unsigned RegCnt = 0;
- unsigned PrevCnt = 0;
- processShuffleMasks(
- Mask, NumOfSrcRegs, NumOfDestRegs, NumOfDestRegs,
- [&]() {
- PrevCnt = RegCnt;
- ++RegCnt;
- },
- [&, &DAG = DAG](ArrayRef<int> SrcSubMask, unsigned SrcVecIdx,
- unsigned DstVecIdx) {
- SDValue SrcVec = SrcVecIdx >= NumOfSrcRegs ? V2 : V1;
- unsigned ExtractIdx = (SrcVecIdx % NumOfSrcRegs) * NumOpElts;
- SDValue SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, M1VT, SrcVec,
- DAG.getVectorIdxConstant(ExtractIdx, DL));
- SubVec = convertFromScalableVector(OneRegVT, SubVec, DAG, Subtarget);
- SubVec = DAG.getVectorShuffle(OneRegVT, DL, SubVec, SubVec, SrcSubMask);
- SubRegs[RegCnt] = convertToScalableVector(M1VT, SubVec, DAG, Subtarget);
- PrevCnt = RegCnt;
- ++RegCnt;
- },
- [&, &DAG = DAG](ArrayRef<int> SrcSubMask, unsigned Idx1, unsigned Idx2) {
- if (PrevCnt + 1 == RegCnt)
- ++RegCnt;
- SDValue SubVec1 = SubRegs[PrevCnt + 1];
- if (!SubVec1) {
- SDValue SrcVec = Idx1 >= NumOfSrcRegs ? V2 : V1;
- unsigned ExtractIdx = (Idx1 % NumOfSrcRegs) * NumOpElts;
- SubVec1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, M1VT, SrcVec,
- DAG.getVectorIdxConstant(ExtractIdx, DL));
- }
- SubVec1 = convertFromScalableVector(OneRegVT, SubVec1, DAG, Subtarget);
- SDValue SrcVec = Idx2 >= NumOfSrcRegs ? V2 : V1;
- unsigned ExtractIdx = (Idx2 % NumOfSrcRegs) * NumOpElts;
- SDValue SubVec2 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, M1VT, SrcVec,
- DAG.getVectorIdxConstant(ExtractIdx, DL));
- SubVec2 = convertFromScalableVector(OneRegVT, SubVec2, DAG, Subtarget);
- SubVec1 =
- DAG.getVectorShuffle(OneRegVT, DL, SubVec1, SubVec2, SrcSubMask);
- SubVec1 = convertToScalableVector(M1VT, SubVec1, DAG, Subtarget);
- SubRegs[PrevCnt + 1] = SubVec1;
- });
- assert(RegCnt == NumOfDestRegs && "Whole vector must be processed");
- SDValue Vec = DAG.getUNDEF(ContainerVT);
- for (auto [I, V] : enumerate(SubRegs)) {
- if (!V)
+ for (unsigned DstVecIdx = 0 ; DstVecIdx < OutMasks.size(); DstVecIdx++) {
+ auto &[SrcVecIdx, SrcSubMask] = OutMasks[DstVecIdx];
+ if (SrcVecIdx == -1)
continue;
- unsigned InsertIdx = I * NumOpElts;
-
- Vec = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, ContainerVT, Vec, V,
+ unsigned ExtractIdx = (SrcVecIdx % VRegsPerSrc) * NumOpElts;
+ SDValue SrcVec = (unsigned)SrcVecIdx >= VRegsPerSrc ? V2 : V1;
+ SDValue SubVec = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, M1VT, SrcVec,
+ DAG.getVectorIdxConstant(ExtractIdx, DL));
+ SubVec = convertFromScalableVector(OneRegVT, SubVec, DAG, Subtarget);
+ SubVec = DAG.getVectorShuffle(OneRegVT, DL, SubVec, SubVec, SrcSubMask);
+ SubVec = convertToScalableVector(M1VT, SubVec, DAG, Subtarget);
+ unsigned InsertIdx = DstVecIdx * NumOpElts;
+ Vec = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, ContainerVT, Vec, SubVec,
DAG.getVectorIdxConstant(InsertIdx, DL));
}
return convertFromScalableVector(VT, Vec, DAG, Subtarget);
@@ -10165,7 +10154,10 @@ SDValue RISCVTargetLowering::lowerVectorMaskVecReduction(SDValue Op,
case ISD::VP_REDUCE_AND: {
// vcpop ~x == 0
SDValue TrueMask = DAG.getNode(RISCVISD::VMSET_VL, DL, ContainerVT, VL);
- Vec = DAG.getNode(RISCVISD::VMXOR_VL, DL, ContainerVT, Vec, TrueMask, VL);
+ if (IsVP || VecVT.isFixedLengthVector())
+ Vec = DAG.getNode(RISCVISD::VMXOR_VL, DL, ContainerVT, Vec, TrueMask, VL);
+ else
+ Vec = DAG.getNode(ISD::XOR, DL, ContainerVT, Vec, TrueMask);
Vec = DAG.getNode(RISCVISD::VCPOP_VL, DL, XLenVT, Vec, Mask, VL);
CC = ISD::SETEQ;
break;
@@ -12674,8 +12666,7 @@ SDValue RISCVTargetLowering::lowerGET_ROUNDING(SDValue Op,
const MVT XLenVT = Subtarget.getXLenVT();
SDLoc DL(Op);
SDValue Chain = Op->getOperand(0);
- SDValue SysRegNo = DAG.getTargetConstant(
- RISCVSysReg::lookupSysRegByName("FRM")->Encoding, DL, XLenVT);
+ SDValue SysRegNo = DAG.getTargetConstant(RISCVSysReg::frm, DL, XLenVT);
SDVTList VTs = DAG.getVTList(XLenVT, MVT::Other);
SDValue RM = DAG.getNode(RISCVISD::READ_CSR, DL, VTs, Chain, SysRegNo);
@@ -12706,8 +12697,7 @@ SDValue RISCVTargetLowering::lowerSET_ROUNDING(SDValue Op,
SDLoc DL(Op);
SDValue Chain = Op->getOperand(0);
SDValue RMValue = Op->getOperand(1);
- SDValue SysRegNo = DAG.getTargetConstant(
- RISCVSysReg::lookupSysRegByName("FRM")->Encoding, DL, XLenVT);
+ SDValue SysRegNo = DAG.getTargetConstant(RISCVSysReg::frm, DL, XLenVT);
// Encoding used for rounding mode in RISC-V differs from that used in
// FLT_ROUNDS. To convert it the C rounding mode is used as an index in
@@ -12910,15 +12900,11 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
SDValue LoCounter, HiCounter;
MVT XLenVT = Subtarget.getXLenVT();
if (N->getOpcode() == ISD::READCYCLECOUNTER) {
- LoCounter = DAG.getTargetConstant(
- RISCVSysReg::lookupSysRegByName("CYCLE")->Encoding, DL, XLenVT);
- HiCounter = DAG.getTargetConstant(
- RISCVSysReg::lookupSysRegByName("CYCLEH")->Encoding, DL, XLenVT);
+ LoCounter = DAG.getTargetConstant(RISCVSysReg::cycle, DL, XLenVT);
+ HiCounter = DAG.getTargetConstant(RISCVSysReg::cycleh, DL, XLenVT);
} else {
- LoCounter = DAG.getTargetConstant(
- RISCVSysReg::lookupSysRegByName("TIME")->Encoding, DL, XLenVT);
- HiCounter = DAG.getTargetConstant(
- RISCVSysReg::lookupSysRegByName("TIMEH")->Encoding, DL, XLenVT);
+ LoCounter = DAG.getTargetConstant(RISCVSysReg::time, DL, XLenVT);
+ HiCounter = DAG.getTargetConstant(RISCVSysReg::timeh, DL, XLenVT);
}
SDVTList VTs = DAG.getVTList(MVT::i32, MVT::i32, MVT::Other);
SDValue RCW = DAG.getNode(RISCVISD::READ_COUNTER_WIDE, DL, VTs,
@@ -18397,6 +18383,15 @@ bool RISCVTargetLowering::isDesirableToCommuteWithShift(
auto *C1 = dyn_cast<ConstantSDNode>(N0->getOperand(1));
auto *C2 = dyn_cast<ConstantSDNode>(N->getOperand(1));
+
+ // Bail if we might break a sh{1,2,3}add pattern.
+ if (Subtarget.hasStdExtZba() && C2 && C2->getZExtValue() >= 1 &&
+ C2->getZExtValue() <= 3 && N->hasOneUse() &&
+ N->user_begin()->getOpcode() == ISD::ADD &&
+ !isUsedByLdSt(*N->user_begin(), nullptr) &&
+ !isa<ConstantSDNode>(N->user_begin()->getOperand(1)))
+ return false;
+
if (C1 && C2) {
const APInt &C1Int = C1->getAPIntValue();
APInt ShiftedC1Int = C1Int << C2->getAPIntValue();
@@ -20278,13 +20273,11 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
for (auto &Reg : RegsToPass)
Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType()));
- if (!IsTailCall) {
- // Add a register mask operand representing the call-preserved registers.
- const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
- const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv);
- assert(Mask && "Missing call preserved mask for calling convention");
- Ops.push_back(DAG.getRegisterMask(Mask));
- }
+ // Add a register mask operand representing the call-preserved registers.
+ const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
+ const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv);
+ assert(Mask && "Missing call preserved mask for calling convention");
+ Ops.push_back(DAG.getRegisterMask(Mask));
// Glue the call to the argument copies, if any.
if (Glue.getNode())