19
19
#include " llvm/CodeGen/GlobalISel/LegalizerHelper.h"
20
20
#include " llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
21
21
#include " llvm/CodeGen/MachineConstantPool.h"
22
+ #include " llvm/CodeGen/MachineMemOperand.h"
22
23
#include " llvm/CodeGen/MachineRegisterInfo.h"
23
24
#include " llvm/CodeGen/TargetOpcodes.h"
24
25
#include " llvm/CodeGen/ValueTypes.h"
@@ -67,6 +68,17 @@ typeIsLegalBoolVec(unsigned TypeIdx, std::initializer_list<LLT> BoolVecTys,
67
68
return all (typeInSet (TypeIdx, BoolVecTys), P);
68
69
}
69
70
71
+ static LegalityPredicate typeIsLegalPtrVec (unsigned TypeIdx,
72
+ std::initializer_list<LLT> PtrVecTys,
73
+ const RISCVSubtarget &ST) {
74
+ LegalityPredicate P = [=, &ST](const LegalityQuery &Query) {
75
+ return ST.hasVInstructions () &&
76
+ (Query.Types [TypeIdx].getElementCount ().getKnownMinValue () != 1 ||
77
+ ST.getELen () == 64 );
78
+ };
79
+ return all (typeInSet (TypeIdx, PtrVecTys), P);
80
+ }
81
+
70
82
RISCVLegalizerInfo::RISCVLegalizerInfo (const RISCVSubtarget &ST)
71
83
: STI(ST), XLen(STI.getXLen()), sXLen(LLT::scalar(XLen)) {
72
84
const LLT sDoubleXLen = LLT::scalar (2 * XLen);
@@ -111,6 +123,11 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
111
123
const LLT nxv4s64 = LLT::scalable_vector (4 , s64);
112
124
const LLT nxv8s64 = LLT::scalable_vector (8 , s64);
113
125
126
+ const LLT nxv1p0 = LLT::scalable_vector (1 , p0);
127
+ const LLT nxv2p0 = LLT::scalable_vector (2 , p0);
128
+ const LLT nxv4p0 = LLT::scalable_vector (4 , p0);
129
+ const LLT nxv8p0 = LLT::scalable_vector (8 , p0);
130
+
114
131
using namespace TargetOpcode ;
115
132
116
133
auto BoolVecTys = {nxv1s1, nxv2s1, nxv4s1, nxv8s1, nxv16s1, nxv32s1, nxv64s1};
@@ -120,6 +137,8 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
120
137
nxv32s16, nxv1s32, nxv2s32, nxv4s32, nxv8s32, nxv16s32,
121
138
nxv1s64, nxv2s64, nxv4s64, nxv8s64};
122
139
140
+ auto PtrVecTys = {nxv1p0, nxv2p0, nxv4p0, nxv8p0};
141
+
123
142
getActionDefinitionsBuilder ({G_ADD, G_SUB, G_AND, G_OR, G_XOR})
124
143
.legalFor ({s32, sXLen })
125
144
.legalIf (typeIsLegalIntOrFPVec (0 , IntOrFPVecTys, ST))
@@ -266,6 +285,23 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
266
285
{s32, p0, s16, 16 },
267
286
{s32, p0, s32, 32 },
268
287
{p0, p0, sXLen , XLen}});
288
+ if (ST.hasVInstructions ())
289
+ LoadStoreActions.legalForTypesWithMemDesc ({{nxv2s8, p0, nxv2s8, 8 },
290
+ {nxv4s8, p0, nxv4s8, 8 },
291
+ {nxv8s8, p0, nxv8s8, 8 },
292
+ {nxv16s8, p0, nxv16s8, 8 },
293
+ {nxv32s8, p0, nxv32s8, 8 },
294
+ {nxv64s8, p0, nxv64s8, 8 },
295
+ {nxv2s16, p0, nxv2s16, 16 },
296
+ {nxv4s16, p0, nxv4s16, 16 },
297
+ {nxv8s16, p0, nxv8s16, 16 },
298
+ {nxv16s16, p0, nxv16s16, 16 },
299
+ {nxv32s16, p0, nxv32s16, 16 },
300
+ {nxv2s32, p0, nxv2s32, 32 },
301
+ {nxv4s32, p0, nxv4s32, 32 },
302
+ {nxv8s32, p0, nxv8s32, 32 },
303
+ {nxv16s32, p0, nxv16s32, 32 }});
304
+
269
305
auto &ExtLoadActions =
270
306
getActionDefinitionsBuilder ({G_SEXTLOAD, G_ZEXTLOAD})
271
307
.legalForTypesWithMemDesc ({{s32, p0, s8, 8 }, {s32, p0, s16, 16 }});
@@ -279,7 +315,28 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
279
315
} else if (ST.hasStdExtD ()) {
280
316
LoadStoreActions.legalForTypesWithMemDesc ({{s64, p0, s64, 64 }});
281
317
}
282
- LoadStoreActions.clampScalar (0 , s32, sXLen ).lower ();
318
+ if (ST.hasVInstructions () && ST.getELen () == 64 )
319
+ LoadStoreActions.legalForTypesWithMemDesc ({{nxv1s8, p0, nxv1s8, 8 },
320
+ {nxv1s16, p0, nxv1s16, 16 },
321
+ {nxv1s32, p0, nxv1s32, 32 }});
322
+
323
+ if (ST.hasVInstructionsI64 ())
324
+ LoadStoreActions.legalForTypesWithMemDesc ({{nxv1s64, p0, nxv1s64, 64 },
325
+
326
+ {nxv2s64, p0, nxv2s64, 64 },
327
+ {nxv4s64, p0, nxv4s64, 64 },
328
+ {nxv8s64, p0, nxv8s64, 64 }});
329
+
330
+ LoadStoreActions.widenScalarToNextPow2 (0 , /* MinSize = */ 8 )
331
+ .lowerIfMemSizeNotByteSizePow2 ()
332
+ // we will take the custom lowering logic if we have scalable vector types
333
+ // with non-standard alignments
334
+ .customIf (LegalityPredicate (
335
+ LegalityPredicates::any (typeIsLegalIntOrFPVec (0 , IntOrFPVecTys, ST),
336
+ typeIsLegalPtrVec (0 , PtrVecTys, ST))))
337
+ .clampScalar (0 , s32, sXLen )
338
+ .lower ();
339
+
283
340
ExtLoadActions.widenScalarToNextPow2 (0 ).clampScalar (0 , s32, sXLen ).lower ();
284
341
285
342
getActionDefinitionsBuilder ({G_PTR_ADD, G_PTRMASK}).legalFor ({{p0, sXLen }});
@@ -651,6 +708,46 @@ bool RISCVLegalizerInfo::legalizeExt(MachineInstr &MI,
651
708
return true ;
652
709
}
653
710
711
+ bool RISCVLegalizerInfo::legalizeLoadStore (MachineInstr &MI,
712
+ LegalizerHelper &Helper,
713
+ MachineIRBuilder &MIB) const {
714
+ assert ((isa<GLoad>(MI) || isa<GStore>(MI)) &&
715
+ " Machine instructions must be Load/Store." );
716
+ MachineRegisterInfo &MRI = *MIB.getMRI ();
717
+ MachineFunction *MF = MI.getMF ();
718
+ const DataLayout &DL = MIB.getDataLayout ();
719
+ LLVMContext &Ctx = MF->getFunction ().getContext ();
720
+
721
+ Register DstReg = MI.getOperand (0 ).getReg ();
722
+ LLT DataTy = MRI.getType (DstReg);
723
+ if (!DataTy.isVector ())
724
+ return false ;
725
+
726
+ if (!MI.hasOneMemOperand ())
727
+ return false ;
728
+
729
+ MachineMemOperand *MMO = *MI.memoperands_begin ();
730
+
731
+ const auto *TLI = STI.getTargetLowering ();
732
+ EVT VT = EVT::getEVT (getTypeForLLT (DataTy, Ctx));
733
+
734
+ if (TLI->allowsMemoryAccessForAlignment (Ctx, DL, VT, *MMO))
735
+ return true ;
736
+
737
+ unsigned EltSizeBits = DataTy.getScalarSizeInBits ();
738
+ assert ((EltSizeBits == 16 || EltSizeBits == 32 || EltSizeBits == 64 ) &&
739
+ " Unexpected unaligned RVV load type" );
740
+
741
+ // Calculate the new vector type with i8 elements
742
+ unsigned NumElements =
743
+ DataTy.getElementCount ().getKnownMinValue () * (EltSizeBits / 8 );
744
+ LLT NewDataTy = LLT::scalable_vector (NumElements, 8 );
745
+
746
+ Helper.bitcast (MI, 0 , NewDataTy);
747
+
748
+ return true ;
749
+ }
750
+
654
751
// / Return the type of the mask type suitable for masking the provided
655
752
// / vector type. This is simply an i1 element type vector of the same
656
753
// / (possibly scalable) length.
@@ -828,6 +925,9 @@ bool RISCVLegalizerInfo::legalizeCustom(
828
925
return legalizeExt (MI, MIRBuilder);
829
926
case TargetOpcode::G_SPLAT_VECTOR:
830
927
return legalizeSplatVector (MI, MIRBuilder);
928
+ case TargetOpcode::G_LOAD:
929
+ case TargetOpcode::G_STORE:
930
+ return legalizeLoadStore (MI, Helper, MIRBuilder);
831
931
}
832
932
833
933
llvm_unreachable (" expected switch to return" );
0 commit comments