@@ -331,8 +331,12 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
331
331
332
332
setBooleanContents (ZeroOrOneBooleanContent);
333
333
334
- if (Subtarget.hasStdExtV ())
334
+ if (Subtarget.hasStdExtV ()) {
335
335
setBooleanVectorContents (ZeroOrOneBooleanContent);
336
+ // RVV intrinsics may have illegal operands.
337
+ for (auto VT : {MVT::i8 , MVT::i16 , MVT::i32 })
338
+ setOperationAction (ISD::INTRINSIC_WO_CHAIN, VT, Custom);
339
+ }
336
340
337
341
// Function alignments.
338
342
const Align FunctionAlignment (Subtarget.hasStdExtC () ? 2 : 4 );
@@ -1002,6 +1006,28 @@ SDValue RISCVTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
1002
1006
SelectionDAG &DAG) const {
1003
1007
unsigned IntNo = cast<ConstantSDNode>(Op.getOperand (0 ))->getZExtValue ();
1004
1008
SDLoc DL (Op);
1009
+
1010
+ if (Subtarget.hasStdExtV ()) {
1011
+ // Some RVV intrinsics may claim that they want an integer operand to be
1012
+ // extended.
1013
+ if (const RISCVVIntrinsicsTable::RISCVVIntrinsicInfo *II =
1014
+ RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo (IntNo)) {
1015
+ if (II->ExtendedOperand ) {
1016
+ assert (II->ExtendedOperand < Op.getNumOperands ());
1017
+ SmallVector<SDValue, 8 > Operands (Op->op_begin (), Op->op_end ());
1018
+ SDValue &ScalarOp = Operands[II->ExtendedOperand ];
1019
+ if (ScalarOp.getValueType () == MVT::i8 ||
1020
+ ScalarOp.getValueType () == MVT::i16 ||
1021
+ ScalarOp.getValueType () == MVT::i32 ) {
1022
+ ScalarOp =
1023
+ DAG.getNode (ISD::ANY_EXTEND, DL, Subtarget.getXLenVT (), ScalarOp);
1024
+ return DAG.getNode (ISD::INTRINSIC_WO_CHAIN, DL, Op.getValueType (),
1025
+ Operands);
1026
+ }
1027
+ }
1028
+ }
1029
+ }
1030
+
1005
1031
switch (IntNo) {
1006
1032
default :
1007
1033
return SDValue (); // Don't custom lower most intrinsics.
@@ -2038,6 +2064,16 @@ static const MCPhysReg ArgFPR64s[] = {
2038
2064
RISCV::F10_D, RISCV::F11_D, RISCV::F12_D, RISCV::F13_D,
2039
2065
RISCV::F14_D, RISCV::F15_D, RISCV::F16_D, RISCV::F17_D
2040
2066
};
2067
+ // This is an interim calling convention and it may be changed in the future.
2068
+ static const MCPhysReg ArgVRs[] = {
2069
+ RISCV::V16, RISCV::V17, RISCV::V18, RISCV::V19, RISCV::V20,
2070
+ RISCV::V21, RISCV::V22, RISCV::V23
2071
+ };
2072
+ static const MCPhysReg ArgVRM2s[] = {
2073
+ RISCV::V16M2, RISCV::V18M2, RISCV::V20M2, RISCV::V22M2
2074
+ };
2075
+ static const MCPhysReg ArgVRM4s[] = {RISCV::V16M4, RISCV::V20M4};
2076
+ static const MCPhysReg ArgVRM8s[] = {RISCV::V16M8};
2041
2077
2042
2078
// Pass a 2*XLEN argument that has been split into two XLEN values through
2043
2079
// registers or the stack as necessary.
@@ -2082,7 +2118,8 @@ static bool CC_RISCVAssign2XLen(unsigned XLen, CCState &State, CCValAssign VA1,
2082
2118
static bool CC_RISCV (const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo,
2083
2119
MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo,
2084
2120
ISD::ArgFlagsTy ArgFlags, CCState &State, bool IsFixed,
2085
- bool IsRet, Type *OrigTy) {
2121
+ bool IsRet, Type *OrigTy, const RISCVTargetLowering &TLI,
2122
+ Optional<unsigned > FirstMaskArgument) {
2086
2123
unsigned XLen = DL.getLargestLegalIntTypeSizeInBits ();
2087
2124
assert (XLen == 32 || XLen == 64 );
2088
2125
MVT XLenVT = XLen == 32 ? MVT::i32 : MVT::i64 ;
@@ -2215,7 +2252,34 @@ static bool CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo,
2215
2252
Reg = State.AllocateReg (ArgFPR32s);
2216
2253
else if (ValVT == MVT::f64 && !UseGPRForF64)
2217
2254
Reg = State.AllocateReg (ArgFPR64s);
2218
- else
2255
+ else if (ValVT.isScalableVector ()) {
2256
+ const TargetRegisterClass *RC = TLI.getRegClassFor (ValVT);
2257
+ if (RC == &RISCV::VRRegClass) {
2258
+ // Assign the first mask argument to V0.
2259
+ // This is an interim calling convention and it may be changed in the
2260
+ // future.
2261
+ if (FirstMaskArgument.hasValue () &&
2262
+ ValNo == FirstMaskArgument.getValue ()) {
2263
+ Reg = State.AllocateReg (RISCV::V0);
2264
+ } else {
2265
+ Reg = State.AllocateReg (ArgVRs);
2266
+ }
2267
+ } else if (RC == &RISCV::VRM2RegClass) {
2268
+ Reg = State.AllocateReg (ArgVRM2s);
2269
+ } else if (RC == &RISCV::VRM4RegClass) {
2270
+ Reg = State.AllocateReg (ArgVRM4s);
2271
+ } else if (RC == &RISCV::VRM8RegClass) {
2272
+ Reg = State.AllocateReg (ArgVRM8s);
2273
+ } else {
2274
+ llvm_unreachable (" Unhandled class register for ValueType" );
2275
+ }
2276
+ if (!Reg) {
2277
+ LocInfo = CCValAssign::Indirect;
2278
+ // Try using a GPR to pass the address
2279
+ Reg = State.AllocateReg (ArgGPRs);
2280
+ LocVT = XLenVT;
2281
+ }
2282
+ } else
2219
2283
Reg = State.AllocateReg (ArgGPRs);
2220
2284
unsigned StackOffset =
2221
2285
Reg ? 0 : State.AllocateStack (XLen / 8 , Align (XLen / 8 ));
@@ -2238,8 +2302,9 @@ static bool CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo,
2238
2302
return false ;
2239
2303
}
2240
2304
2241
- assert ((!UseGPRForF16_F32 || !UseGPRForF64 || LocVT == XLenVT) &&
2242
- " Expected an XLenVT at this stage" );
2305
+ assert ((!UseGPRForF16_F32 || !UseGPRForF64 || LocVT == XLenVT ||
2306
+ (TLI.getSubtarget ().hasStdExtV () && ValVT.isScalableVector ())) &&
2307
+ " Expected an XLenVT or scalable vector types at this stage" );
2243
2308
2244
2309
if (Reg) {
2245
2310
State.addLoc (CCValAssign::getReg (ValNo, ValVT, Reg, LocVT, LocInfo));
@@ -2256,12 +2321,32 @@ static bool CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo,
2256
2321
return false ;
2257
2322
}
2258
2323
2324
+ template <typename ArgTy>
2325
+ static void preAssignMask (const ArgTy &Args,
2326
+ Optional<unsigned > &FirstMaskArgument,
2327
+ CCState &CCInfo) {
2328
+ unsigned NumArgs = Args.size ();
2329
+ for (unsigned I = 0 ; I != NumArgs; ++I) {
2330
+ MVT ArgVT = Args[I].VT ;
2331
+ if (!ArgVT.isScalableVector () ||
2332
+ ArgVT.getVectorElementType ().SimpleTy != MVT::i1)
2333
+ continue ;
2334
+
2335
+ FirstMaskArgument = I;
2336
+ break ;
2337
+ }
2338
+ }
2339
+
2259
2340
void RISCVTargetLowering::analyzeInputArgs (
2260
2341
MachineFunction &MF, CCState &CCInfo,
2261
2342
const SmallVectorImpl<ISD::InputArg> &Ins, bool IsRet) const {
2262
2343
unsigned NumArgs = Ins.size ();
2263
2344
FunctionType *FType = MF.getFunction ().getFunctionType ();
2264
2345
2346
+ Optional<unsigned > FirstMaskArgument;
2347
+ if (Subtarget.hasStdExtV ())
2348
+ preAssignMask (Ins, FirstMaskArgument, CCInfo);
2349
+
2265
2350
for (unsigned i = 0 ; i != NumArgs; ++i) {
2266
2351
MVT ArgVT = Ins[i].VT ;
2267
2352
ISD::ArgFlagsTy ArgFlags = Ins[i].Flags ;
@@ -2274,7 +2359,8 @@ void RISCVTargetLowering::analyzeInputArgs(
2274
2359
2275
2360
RISCVABI::ABI ABI = MF.getSubtarget <RISCVSubtarget>().getTargetABI ();
2276
2361
if (CC_RISCV (MF.getDataLayout (), ABI, i, ArgVT, ArgVT, CCValAssign::Full,
2277
- ArgFlags, CCInfo, /* IsFixed=*/ true , IsRet, ArgTy)) {
2362
+ ArgFlags, CCInfo, /* IsFixed=*/ true , IsRet, ArgTy, *this ,
2363
+ FirstMaskArgument)) {
2278
2364
LLVM_DEBUG (dbgs () << " InputArg #" << i << " has unhandled type "
2279
2365
<< EVT (ArgVT).getEVTString () << ' \n ' );
2280
2366
llvm_unreachable (nullptr );
@@ -2288,14 +2374,19 @@ void RISCVTargetLowering::analyzeOutputArgs(
2288
2374
CallLoweringInfo *CLI) const {
2289
2375
unsigned NumArgs = Outs.size ();
2290
2376
2377
+ Optional<unsigned > FirstMaskArgument;
2378
+ if (Subtarget.hasStdExtV ())
2379
+ preAssignMask (Outs, FirstMaskArgument, CCInfo);
2380
+
2291
2381
for (unsigned i = 0 ; i != NumArgs; i++) {
2292
2382
MVT ArgVT = Outs[i].VT ;
2293
2383
ISD::ArgFlagsTy ArgFlags = Outs[i].Flags ;
2294
2384
Type *OrigTy = CLI ? CLI->getArgs ()[Outs[i].OrigArgIndex ].Ty : nullptr ;
2295
2385
2296
2386
RISCVABI::ABI ABI = MF.getSubtarget <RISCVSubtarget>().getTargetABI ();
2297
2387
if (CC_RISCV (MF.getDataLayout (), ABI, i, ArgVT, ArgVT, CCValAssign::Full,
2298
- ArgFlags, CCInfo, Outs[i].IsFixed , IsRet, OrigTy)) {
2388
+ ArgFlags, CCInfo, Outs[i].IsFixed , IsRet, OrigTy, *this ,
2389
+ FirstMaskArgument)) {
2299
2390
LLVM_DEBUG (dbgs () << " OutputArg #" << i << " has unhandled type "
2300
2391
<< EVT (ArgVT).getEVTString () << " \n " );
2301
2392
llvm_unreachable (nullptr );
@@ -2327,31 +2418,13 @@ static SDValue convertLocVTToValVT(SelectionDAG &DAG, SDValue Val,
2327
2418
// The caller is responsible for loading the full value if the argument is
2328
2419
// passed with CCValAssign::Indirect.
2329
2420
static SDValue unpackFromRegLoc (SelectionDAG &DAG, SDValue Chain,
2330
- const CCValAssign &VA, const SDLoc &DL) {
2421
+ const CCValAssign &VA, const SDLoc &DL,
2422
+ const RISCVTargetLowering &TLI) {
2331
2423
MachineFunction &MF = DAG.getMachineFunction ();
2332
2424
MachineRegisterInfo &RegInfo = MF.getRegInfo ();
2333
2425
EVT LocVT = VA.getLocVT ();
2334
2426
SDValue Val;
2335
- const TargetRegisterClass *RC;
2336
-
2337
- switch (LocVT.getSimpleVT ().SimpleTy ) {
2338
- default :
2339
- llvm_unreachable (" Unexpected register type" );
2340
- case MVT::i32 :
2341
- case MVT::i64 :
2342
- RC = &RISCV::GPRRegClass;
2343
- break ;
2344
- case MVT::f16 :
2345
- RC = &RISCV::FPR16RegClass;
2346
- break ;
2347
- case MVT::f32 :
2348
- RC = &RISCV::FPR32RegClass;
2349
- break ;
2350
- case MVT::f64 :
2351
- RC = &RISCV::FPR64RegClass;
2352
- break ;
2353
- }
2354
-
2427
+ const TargetRegisterClass *RC = TLI.getRegClassFor (LocVT.getSimpleVT ());
2355
2428
Register VReg = RegInfo.createVirtualRegister (RC);
2356
2429
RegInfo.addLiveIn (VA.getLocReg (), VReg);
2357
2430
Val = DAG.getCopyFromReg (Chain, DL, VReg, LocVT);
@@ -2623,7 +2696,7 @@ SDValue RISCVTargetLowering::LowerFormalArguments(
2623
2696
if (VA.getLocVT () == MVT::i32 && VA.getValVT () == MVT::f64 )
2624
2697
ArgValue = unpackF64OnRV32DSoftABI (DAG, Chain, VA, DL);
2625
2698
else if (VA.isRegLoc ())
2626
- ArgValue = unpackFromRegLoc (DAG, Chain, VA, DL);
2699
+ ArgValue = unpackFromRegLoc (DAG, Chain, VA, DL, * this );
2627
2700
else
2628
2701
ArgValue = unpackFromMemLoc (DAG, Chain, VA, DL);
2629
2702
@@ -3071,12 +3144,18 @@ bool RISCVTargetLowering::CanLowerReturn(
3071
3144
const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const {
3072
3145
SmallVector<CCValAssign, 16 > RVLocs;
3073
3146
CCState CCInfo (CallConv, IsVarArg, MF, RVLocs, Context);
3147
+
3148
+ Optional<unsigned > FirstMaskArgument;
3149
+ if (Subtarget.hasStdExtV ())
3150
+ preAssignMask (Outs, FirstMaskArgument, CCInfo);
3151
+
3074
3152
for (unsigned i = 0 , e = Outs.size (); i != e; ++i) {
3075
3153
MVT VT = Outs[i].VT ;
3076
3154
ISD::ArgFlagsTy ArgFlags = Outs[i].Flags ;
3077
3155
RISCVABI::ABI ABI = MF.getSubtarget <RISCVSubtarget>().getTargetABI ();
3078
3156
if (CC_RISCV (MF.getDataLayout (), ABI, i, VT, VT, CCValAssign::Full,
3079
- ArgFlags, CCInfo, /* IsFixed=*/ true , /* IsRet=*/ true , nullptr ))
3157
+ ArgFlags, CCInfo, /* IsFixed=*/ true , /* IsRet=*/ true , nullptr ,
3158
+ *this , FirstMaskArgument))
3080
3159
return false ;
3081
3160
}
3082
3161
return true ;
@@ -3673,3 +3752,12 @@ RISCVTargetLowering::getRegisterByName(const char *RegName, LLT VT,
3673
3752
StringRef (RegName) + " \" ." ));
3674
3753
return Reg;
3675
3754
}
3755
+
3756
+ namespace llvm {
3757
+ namespace RISCVVIntrinsicsTable {
3758
+
3759
+ #define GET_RISCVVIntrinsicsTable_IMPL
3760
+ #include " RISCVGenSearchableTables.inc"
3761
+
3762
+ } // namespace RISCVVIntrinsicsTable
3763
+ } // namespace llvm
0 commit comments