@@ -35,6 +35,9 @@ class RISCVABIInfo : public DefaultABIInfo {
35
35
llvm::Type *&Field2Ty,
36
36
CharUnits &Field2Off) const ;
37
37
38
+ bool detectVLSCCEligibleStruct (QualType Ty, unsigned ABIVLen,
39
+ llvm::Type *&VLSType) const ;
40
+
38
41
public:
39
42
RISCVABIInfo (CodeGen::CodeGenTypes &CGT, unsigned XLen, unsigned FLen,
40
43
bool EABI)
@@ -361,6 +364,149 @@ ABIArgInfo RISCVABIInfo::coerceAndExpandFPCCEligibleStruct(
361
364
return ABIArgInfo::getCoerceAndExpand (CoerceToType, UnpaddedCoerceToType);
362
365
}
363
366
367
+ bool RISCVABIInfo::detectVLSCCEligibleStruct (QualType Ty, unsigned ABIVLen,
368
+ llvm::Type *&VLSType) const {
369
+ // No riscv_vls_cc attribute.
370
+ if (ABIVLen == 1 )
371
+ return false ;
372
+
373
+ // Legal struct for VLS calling convention should fulfill following rules:
374
+ // 1. Struct element should be either "homogeneous fixed-length vectors" or "a
375
+ // fixed-length vector array".
376
+ // 2. Number of struct elements or array elements should be power of 2.
377
+ // 3. Total number of vector registers needed should not exceed 8.
378
+ //
379
+ // Examples: Assume ABI_VLEN = 128.
380
+ // These are legal structs:
381
+ // a. Structs with 1, 2, 4 or 8 "same" fixed-length vectors, e.g.
382
+ // struct {
383
+ // __attribute__((vector_size(16))) int a;
384
+ // __attribute__((vector_size(16))) int b;
385
+ // }
386
+ //
387
+ // b. Structs with "single" fixed-length vector array with lengh 1, 2, 4
388
+ // or 8, e.g.
389
+ // struct {
390
+ // __attribute__((vector_size(16))) int a[2];
391
+ // }
392
+ // These are illegal structs:
393
+ // a. Structs with 3 fixed-length vectors, e.g.
394
+ // struct {
395
+ // __attribute__((vector_size(16))) int a;
396
+ // __attribute__((vector_size(16))) int b;
397
+ // __attribute__((vector_size(16))) int c;
398
+ // }
399
+ //
400
+ // b. Structs with "multiple" fixed-length vector array, e.g.
401
+ // struct {
402
+ // __attribute__((vector_size(16))) int a[2];
403
+ // __attribute__((vector_size(16))) int b[2];
404
+ // }
405
+ //
406
+ // c. Vector registers needed exceeds 8, e.g.
407
+ // struct {
408
+ // // Registers needed for single fixed-length element:
409
+ // // 64 * 8 / ABI_VLEN = 4
410
+ // __attribute__((vector_size(64))) int a;
411
+ // __attribute__((vector_size(64))) int b;
412
+ // __attribute__((vector_size(64))) int c;
413
+ // __attribute__((vector_size(64))) int d;
414
+ // }
415
+ //
416
+ // Struct of 1 fixed-length vector is passed as a scalable vector.
417
+ // Struct of >1 fixed-length vectors are passed as vector tuple.
418
+ // Struct of 1 array of fixed-length vectors is passed as a scalable vector.
419
+ // Otherwise, pass the struct indirectly.
420
+
421
+ if (llvm::StructType *STy = dyn_cast<llvm::StructType>(CGT.ConvertType (Ty))) {
422
+ int NumElts = STy->getStructNumElements ();
423
+ if (NumElts > 8 || !llvm::isPowerOf2_32 (NumElts))
424
+ return false ;
425
+
426
+ auto *FirstEltTy = STy->getElementType (0 );
427
+ if (!STy->containsHomogeneousTypes ())
428
+ return false ;
429
+
430
+ // Check structure of fixed-length vectors and turn them into vector tuple
431
+ // type if legal.
432
+ if (auto *FixedVecTy = dyn_cast<llvm::FixedVectorType>(FirstEltTy)) {
433
+ if (NumElts == 1 ) {
434
+ // Handle single fixed-length vector.
435
+ VLSType = llvm::ScalableVectorType::get (
436
+ FixedVecTy->getElementType (),
437
+ llvm::divideCeil (FixedVecTy->getNumElements () *
438
+ llvm::RISCV::RVVBitsPerBlock,
439
+ ABIVLen));
440
+ // Check registers needed <= 8.
441
+ return llvm::divideCeil (
442
+ FixedVecTy->getNumElements () *
443
+ FixedVecTy->getElementType ()->getScalarSizeInBits (),
444
+ ABIVLen) <= 8 ;
445
+ }
446
+ // LMUL
447
+ // = fixed-length vector size / ABIVLen
448
+ // = 8 * I8EltCount / RVVBitsPerBlock
449
+ // =>
450
+ // I8EltCount
451
+ // = (fixed-length vector size * RVVBitsPerBlock) / (ABIVLen * 8)
452
+ unsigned I8EltCount = llvm::divideCeil (
453
+ FixedVecTy->getNumElements () *
454
+ FixedVecTy->getElementType ()->getScalarSizeInBits () *
455
+ llvm::RISCV::RVVBitsPerBlock,
456
+ ABIVLen * 8 );
457
+ VLSType = llvm::TargetExtType::get (
458
+ getVMContext (), " riscv.vector.tuple" ,
459
+ llvm::ScalableVectorType::get (llvm::Type::getInt8Ty (getVMContext ()),
460
+ I8EltCount),
461
+ NumElts);
462
+ // Check registers needed <= 8.
463
+ return NumElts *
464
+ llvm::divideCeil (
465
+ FixedVecTy->getNumElements () *
466
+ FixedVecTy->getElementType ()->getScalarSizeInBits (),
467
+ ABIVLen) <=
468
+ 8 ;
469
+ }
470
+
471
+ // If elements are not fixed-length vectors, it should be an array.
472
+ if (NumElts != 1 )
473
+ return false ;
474
+
475
+ // Check array of fixed-length vector and turn it into scalable vector type
476
+ // if legal.
477
+ if (auto *ArrTy = dyn_cast<llvm::ArrayType>(FirstEltTy)) {
478
+ int NumArrElt = ArrTy->getNumElements ();
479
+ if (NumArrElt > 8 || !llvm::isPowerOf2_32 (NumArrElt))
480
+ return false ;
481
+
482
+ auto *ArrEltTy = dyn_cast<llvm::FixedVectorType>(ArrTy->getElementType ());
483
+ if (!ArrEltTy)
484
+ return false ;
485
+
486
+ // LMUL
487
+ // = NumArrElt * fixed-length vector size / ABIVLen
488
+ // = fixed-length vector elt size * ScalVecNumElts / RVVBitsPerBlock
489
+ // =>
490
+ // ScalVecNumElts
491
+ // = (NumArrElt * fixed-length vector size * RVVBitsPerBlock) /
492
+ // (ABIVLen * fixed-length vector elt size)
493
+ // = NumArrElt * num fixed-length vector elt * RVVBitsPerBlock /
494
+ // ABIVLen
495
+ unsigned ScalVecNumElts = llvm::divideCeil (
496
+ NumArrElt * ArrEltTy->getNumElements () * llvm::RISCV::RVVBitsPerBlock,
497
+ ABIVLen);
498
+ VLSType = llvm::ScalableVectorType::get (ArrEltTy->getElementType (),
499
+ ScalVecNumElts);
500
+ // Check registers needed <= 8.
501
+ return llvm::divideCeil (
502
+ ScalVecNumElts *
503
+ ArrEltTy->getElementType ()->getScalarSizeInBits (),
504
+ llvm::RISCV::RVVBitsPerBlock) <= 8 ;
505
+ }
506
+ }
507
+ return false ;
508
+ }
509
+
364
510
// Fixed-length RVV vectors are represented as scalable vectors in function
365
511
// args/return and must be coerced from fixed vectors.
366
512
ABIArgInfo RISCVABIInfo::coerceVLSVector (QualType Ty,
@@ -410,11 +556,13 @@ ABIArgInfo RISCVABIInfo::coerceVLSVector(QualType Ty,
410
556
(EltType->isBFloatTy () && !TI.hasFeature (" zvfbfmin" )) ||
411
557
(EltType->isFloatTy () && !TI.hasFeature (" zve32f" )) ||
412
558
(EltType->isDoubleTy () && !TI.hasFeature (" zve64d" )) ||
413
- (EltType->isIntegerTy (64 ) && !TI.hasFeature (" zve64x" )) ||
414
- EltType->isIntegerTy (128 )) {
559
+ EltType->isIntegerTy (128 ))
415
560
EltType =
416
561
llvm::Type::getIntNTy (getVMContext (), EltType->getScalarSizeInBits ());
417
- }
562
+
563
+ // Check registers needed <= 8.
564
+ if ((EltType->getScalarSizeInBits () * NumElts / ABIVLen) > 8 )
565
+ return getNaturalAlignIndirect (Ty, /* ByVal=*/ false );
418
566
419
567
// Generic vector
420
568
// The number of elements needs to be at least 1.
@@ -485,6 +633,12 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
485
633
}
486
634
}
487
635
636
+ if (IsFixed && Ty->isStructureOrClassType ()) {
637
+ llvm::Type *VLSType = nullptr ;
638
+ if (detectVLSCCEligibleStruct (Ty, ABIVLen, VLSType))
639
+ return ABIArgInfo::getDirect (VLSType);
640
+ }
641
+
488
642
uint64_t NeededAlign = getContext ().getTypeAlign (Ty);
489
643
// Determine the number of GPRs needed to pass the current argument
490
644
// according to the ABI. 2*XLen-aligned varargs are passed in "aligned"
0 commit comments