Skip to content

Commit abb5a98

Browse files
committed
[RISCV] Support mask policy for RVV IR intrinsics.
Add the UsesMaskPolicy flag to indicate the operations result would be effected by the mask policy. (ex. mask operations). It means RISCVInsertVSETVLI should decide the mask policy according by mask policy operand or passthru operand. If UsesMaskPolicy is false (ex. unmasked, store, and reduction operations), the mask policy could be either mask undisturbed or agnostic. Currently, RISCVInsertVSETVLI sets UsesMaskPolicy operations default to MA, otherwise to MU to keep the current mask policy would not be changed for unmasked operations. Add masked-tama, masked-tamu, masked-tuma and masked-tumu test cases. I didn't add all operations because most of implementations are using the same pseudo multiclass. Some tests maybe be duplicated in different tests. (ex. masked vmacc with tumu shows in vmacc-rv32.ll and masked-tumu) I think having different tests only for policy would make the testing clear. Reviewed By: craig.topper Differential Revision: https://reviews.llvm.org/D120226
1 parent 0ff19b1 commit abb5a98

File tree

10 files changed

+4955
-107
lines changed

10 files changed

+4955
-107
lines changed

llvm/include/llvm/IR/IntrinsicsRISCV.td

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ let TargetPrefix = "riscv" in {
219219
let VLOperand = 2;
220220
}
221221
// For unit stride load with mask
222-
// Input: (maskedoff, pointer, mask, vl, ta)
222+
// Input: (maskedoff, pointer, mask, vl, policy)
223223
class RISCVUSLoadMask
224224
: Intrinsic<[llvm_anyvector_ty ],
225225
[LLVMMatchType<0>,
@@ -231,7 +231,7 @@ let TargetPrefix = "riscv" in {
231231
let VLOperand = 3;
232232
}
233233
// For unit stride fault-only-first load with mask
234-
// Input: (maskedoff, pointer, mask, vl, ta)
234+
// Input: (maskedoff, pointer, mask, vl, policy)
235235
// Output: (data, vl)
236236
// NOTE: We model this with default memory properties since we model writing
237237
// VL as a side effect. IntrReadMem, IntrHasSideEffects does not work.
@@ -255,7 +255,7 @@ let TargetPrefix = "riscv" in {
255255
let VLOperand = 3;
256256
}
257257
// For strided load with mask
258-
// Input: (maskedoff, pointer, stride, mask, vl, ta)
258+
// Input: (maskedoff, pointer, stride, mask, vl, policy)
259259
class RISCVSLoadMask
260260
: Intrinsic<[llvm_anyvector_ty ],
261261
[LLVMMatchType<0>,
@@ -277,7 +277,7 @@ let TargetPrefix = "riscv" in {
277277
let VLOperand = 3;
278278
}
279279
// For indexed load with mask
280-
// Input: (maskedoff, pointer, index, mask, vl, ta)
280+
// Input: (maskedoff, pointer, index, mask, vl, policy)
281281
class RISCVILoadMask
282282
: Intrinsic<[llvm_anyvector_ty ],
283283
[LLVMMatchType<0>,
@@ -358,7 +358,7 @@ let TargetPrefix = "riscv" in {
358358
let VLOperand = 2;
359359
}
360360
// For destination vector type is the same as first source vector (with mask).
361-
// Input: (vector_in, mask, vl, ta)
361+
// Input: (vector_in, vector_in, mask, vl, policy)
362362
class RISCVUnaryAAMask
363363
: Intrinsic<[llvm_anyvector_ty],
364364
[LLVMMatchType<0>, LLVMMatchType<0>,
@@ -367,7 +367,8 @@ let TargetPrefix = "riscv" in {
367367
[ImmArg<ArgIndex<4>>, IntrNoMem]>, RISCVVIntrinsic {
368368
let VLOperand = 3;
369369
}
370-
class RISCVUnaryAAMaskTU
370+
// Input: (passthru, vector_in, vector_in, mask, vl)
371+
class RISCVCompress
371372
: Intrinsic<[llvm_anyvector_ty],
372373
[LLVMMatchType<0>, LLVMMatchType<0>,
373374
LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_anyint_ty],
@@ -392,7 +393,7 @@ let TargetPrefix = "riscv" in {
392393
let VLOperand = 3;
393394
}
394395
// For destination vector type is the same as first and second source vector.
395-
// Input: (vector_in, vector_in, int_vector_in, vl, ta)
396+
// Input: (vector_in, vector_in, int_vector_in, vl, policy)
396397
class RISCVRGatherVVMask
397398
: Intrinsic<[llvm_anyvector_ty],
398399
[LLVMMatchType<0>, LLVMMatchType<0>, LLVMVectorOfBitcastsToInt<0>,
@@ -411,7 +412,7 @@ let TargetPrefix = "riscv" in {
411412
let VLOperand = 3;
412413
}
413414
// For destination vector type is the same as first and second source vector.
414-
// Input: (vector_in, vector_in, int16_vector_in, vl, ta)
415+
// Input: (vector_in, vector_in, int16_vector_in, vl, policy)
415416
class RISCVRGatherEI16VVMask
416417
: Intrinsic<[llvm_anyvector_ty],
417418
[LLVMMatchType<0>, LLVMMatchType<0>,
@@ -426,14 +427,14 @@ let TargetPrefix = "riscv" in {
426427
// Input: (passthru, vector_in, xlen_in, vl)
427428
class RISCVGatherVXNoMask
428429
: Intrinsic<[llvm_anyvector_ty],
429-
[LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyint_ty,
430+
[LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyint_ty,
430431
LLVMMatchType<1>],
431432
[IntrNoMem]>, RISCVVIntrinsic {
432433
let VLOperand = 3;
433434
}
434435
// For destination vector type is the same as first source vector (with mask).
435436
// Second operand is XLen.
436-
// Input: (maskedoff, vector_in, xlen_in, mask, vl, ta)
437+
// Input: (maskedoff, vector_in, xlen_in, mask, vl, policy)
437438
class RISCVGatherVXMask
438439
: Intrinsic<[llvm_anyvector_ty],
439440
[LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyint_ty,
@@ -453,7 +454,7 @@ let TargetPrefix = "riscv" in {
453454
let VLOperand = 3;
454455
}
455456
// For destination vector type is the same as first source vector (with mask).
456-
// Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, ta)
457+
// Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, policy)
457458
class RISCVBinaryAAXMask
458459
: Intrinsic<[llvm_anyvector_ty],
459460
[LLVMMatchType<0>, LLVMMatchType<0>, llvm_any_ty,
@@ -475,7 +476,7 @@ let TargetPrefix = "riscv" in {
475476
}
476477
// For destination vector type is the same as first source vector (with mask).
477478
// The second source operand must match the destination type or be an XLen scalar.
478-
// Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, ta)
479+
// Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, policy)
479480
class RISCVBinaryAAShiftMask
480481
: Intrinsic<[llvm_anyvector_ty],
481482
[LLVMMatchType<0>, LLVMMatchType<0>, llvm_any_ty,
@@ -495,7 +496,7 @@ let TargetPrefix = "riscv" in {
495496
let VLOperand = 3;
496497
}
497498
// For destination vector type is NOT the same as first source vector (with mask).
498-
// Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, ta)
499+
// Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, policy)
499500
class RISCVBinaryABXMask
500501
: Intrinsic<[llvm_anyvector_ty],
501502
[LLVMMatchType<0>, llvm_anyvector_ty, llvm_any_ty,
@@ -517,7 +518,7 @@ let TargetPrefix = "riscv" in {
517518
}
518519
// For destination vector type is NOT the same as first source vector (with mask).
519520
// The second source operand must match the destination type or be an XLen scalar.
520-
// Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, ta)
521+
// Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, policy)
521522
class RISCVBinaryABShiftMask
522523
: Intrinsic<[llvm_anyvector_ty],
523524
[LLVMMatchType<0>, llvm_anyvector_ty, llvm_any_ty,
@@ -615,7 +616,7 @@ let TargetPrefix = "riscv" in {
615616
}
616617
// For Saturating binary operations with mask.
617618
// The destination vector type is the same as first source vector.
618-
// Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, ta)
619+
// Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, policy)
619620
class RISCVSaturatingBinaryAAXMask
620621
: Intrinsic<[llvm_anyvector_ty],
621622
[LLVMMatchType<0>, LLVMMatchType<0>, llvm_any_ty,
@@ -639,7 +640,7 @@ let TargetPrefix = "riscv" in {
639640
// For Saturating binary operations with mask.
640641
// The destination vector type is the same as first source vector.
641642
// The second source operand matches the destination type or is an XLen scalar.
642-
// Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, ta)
643+
// Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, policy)
643644
class RISCVSaturatingBinaryAAShiftMask
644645
: Intrinsic<[llvm_anyvector_ty],
645646
[LLVMMatchType<0>, LLVMMatchType<0>, llvm_any_ty,
@@ -662,7 +663,7 @@ let TargetPrefix = "riscv" in {
662663
// For Saturating binary operations with mask.
663664
// The destination vector type is NOT the same as first source vector (with mask).
664665
// The second source operand matches the destination type or is an XLen scalar.
665-
// Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, ta)
666+
// Input: (maskedoff, vector_in, vector_in/scalar_in, mask, vl, policy)
666667
class RISCVSaturatingBinaryABShiftMask
667668
: Intrinsic<[llvm_anyvector_ty],
668669
[LLVMMatchType<0>, llvm_anyvector_ty, llvm_any_ty,
@@ -671,13 +672,15 @@ let TargetPrefix = "riscv" in {
671672
[ImmArg<ArgIndex<5>>, IntrNoMem, IntrHasSideEffects]>, RISCVVIntrinsic {
672673
let VLOperand = 4;
673674
}
675+
// Input: (vector_in, vector_in, vector_in/scalar_in, vl)
674676
class RISCVTernaryAAAXNoMask
675677
: Intrinsic<[llvm_anyvector_ty],
676678
[LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyint_ty,
677679
LLVMMatchType<1>],
678680
[IntrNoMem]>, RISCVVIntrinsic {
679681
let VLOperand = 3;
680682
}
683+
// Input: (vector_in, vector_in, vector_in/scalar_in, mask, vl, policy)
681684
class RISCVTernaryAAAXMask
682685
: Intrinsic<[llvm_anyvector_ty],
683686
[LLVMMatchType<0>, LLVMMatchType<0>, llvm_anyint_ty,
@@ -686,6 +689,7 @@ let TargetPrefix = "riscv" in {
686689
[ImmArg<ArgIndex<5>>, IntrNoMem]>, RISCVVIntrinsic {
687690
let VLOperand = 4;
688691
}
692+
// NoMask Vector Multiply-Add operations, its first operand can not be undef.
689693
// Input: (vector_in, vector_in/scalar, vector_in, vl, policy)
690694
class RISCVTernaryAAXANoMask
691695
: Intrinsic<[llvm_anyvector_ty],
@@ -695,6 +699,7 @@ let TargetPrefix = "riscv" in {
695699
let ScalarOperand = 1;
696700
let VLOperand = 3;
697701
}
702+
// Mask Vector Multiply-Add operations, its first operand can not be undef.
698703
// Input: (vector_in, vector_in/scalar, vector_in, mask, vl, policy
699704
class RISCVTernaryAAXAMask
700705
: Intrinsic<[llvm_anyvector_ty],
@@ -705,6 +710,7 @@ let TargetPrefix = "riscv" in {
705710
let ScalarOperand = 1;
706711
let VLOperand = 4;
707712
}
713+
// NoMask Widening Vector Multiply-Add operations, its first operand can not be undef.
708714
// Input: (vector_in, vector_in/scalar, vector_in, vl, policy)
709715
class RISCVTernaryWideNoMask
710716
: Intrinsic< [llvm_anyvector_ty],
@@ -714,6 +720,7 @@ let TargetPrefix = "riscv" in {
714720
let ScalarOperand = 1;
715721
let VLOperand = 3;
716722
}
723+
// Mask Widening Vector Multiply-Add operations, its first operand can not be undef.
717724
// Input: (vector_in, vector_in/scalar, vector_in, mask, vl, policy
718725
class RISCVTernaryWideMask
719726
: Intrinsic< [llvm_anyvector_ty],
@@ -772,7 +779,7 @@ let TargetPrefix = "riscv" in {
772779
let VLOperand = 2;
773780
}
774781
// For destination vector type is NOT the same as source vector (with mask).
775-
// Input: (maskedoff, vector_in, mask, vl, ta)
782+
// Input: (maskedoff, vector_in, mask, vl, policy)
776783
class RISCVUnaryABMask
777784
: Intrinsic<[llvm_anyvector_ty],
778785
[LLVMMatchType<0>, llvm_anyvector_ty,
@@ -824,7 +831,7 @@ let TargetPrefix = "riscv" in {
824831
let VLOperand = 2;
825832
}
826833
// For Conversion unary operations with mask.
827-
// Input: (maskedoff, vector_in, mask, vl, ta)
834+
// Input: (maskedoff, vector_in, mask, vl, policy)
828835
class RISCVConversionMask
829836
: Intrinsic<[llvm_anyvector_ty],
830837
[LLVMMatchType<0>, llvm_anyvector_ty,
@@ -844,7 +851,7 @@ let TargetPrefix = "riscv" in {
844851
let VLOperand = 1;
845852
}
846853
// For unit stride segment load with mask
847-
// Input: (maskedoff, pointer, mask, vl, ta)
854+
// Input: (maskedoff, pointer, mask, vl, policy)
848855
class RISCVUSSegLoadMask<int nf>
849856
: Intrinsic<!listconcat([llvm_anyvector_ty], !listsplat(LLVMMatchType<0>,
850857
!add(nf, -1))),
@@ -870,7 +877,7 @@ let TargetPrefix = "riscv" in {
870877
let VLOperand = 1;
871878
}
872879
// For unit stride fault-only-first segment load with mask
873-
// Input: (maskedoff, pointer, mask, vl, ta)
880+
// Input: (maskedoff, pointer, mask, vl, policy)
874881
// Output: (data, vl)
875882
// NOTE: We model this with default memory properties since we model writing
876883
// VL as a side effect. IntrReadMem, IntrHasSideEffects does not work.
@@ -896,7 +903,7 @@ let TargetPrefix = "riscv" in {
896903
let VLOperand = 2;
897904
}
898905
// For stride segment load with mask
899-
// Input: (maskedoff, pointer, offset, mask, vl, ta)
906+
// Input: (maskedoff, pointer, offset, mask, vl, policy)
900907
class RISCVSSegLoadMask<int nf>
901908
: Intrinsic<!listconcat([llvm_anyvector_ty], !listsplat(LLVMMatchType<0>,
902909
!add(nf, -1))),
@@ -920,7 +927,7 @@ let TargetPrefix = "riscv" in {
920927
let VLOperand = 2;
921928
}
922929
// For indexed segment load with mask
923-
// Input: (maskedoff, pointer, index, mask, vl, ta)
930+
// Input: (maskedoff, pointer, index, mask, vl, policy)
924931
class RISCVISegLoadMask<int nf>
925932
: Intrinsic<!listconcat([llvm_anyvector_ty], !listsplat(LLVMMatchType<0>,
926933
!add(nf, -1))),
@@ -1360,7 +1367,7 @@ let TargetPrefix = "riscv" in {
13601367
defm vrgather_vx : RISCVRGatherVX;
13611368
defm vrgatherei16_vv : RISCVRGatherEI16VV;
13621369

1363-
def "int_riscv_vcompress" : RISCVUnaryAAMaskTU;
1370+
def "int_riscv_vcompress" : RISCVCompress;
13641371

13651372
defm vaaddu : RISCVSaturatingBinaryAAX;
13661373
defm vaadd : RISCVSaturatingBinaryAAX;

llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ enum {
8888
// Pseudos.
8989
IsRVVWideningReductionShift = HasVecPolicyOpShift + 1,
9090
IsRVVWideningReductionMask = 1 << IsRVVWideningReductionShift,
91+
92+
// Does this instruction care about mask policy. If it is not, the mask policy
93+
// could be either agnostic or undisturbed. For example, unmasked, store, and
94+
// reduction operations result would not be affected by mask policy, so
95+
// compiler has free to select either one.
96+
UsesMaskPolicyShift = IsRVVWideningReductionShift + 1,
97+
UsesMaskPolicyMask = 1 << UsesMaskPolicyShift,
9198
};
9299

93100
// Match with the definitions in RISCVInstrFormatsV.td
@@ -110,8 +117,8 @@ enum VLMUL : uint8_t {
110117
};
111118

112119
enum {
113-
TAIL_UNDISTURBED = 0,
114120
TAIL_AGNOSTIC = 1,
121+
MASK_AGNOSTIC = 2,
115122
};
116123

117124
// Helper functions to read TSFlags.
@@ -156,6 +163,10 @@ static inline bool hasVecPolicyOp(uint64_t TSFlags) {
156163
static inline bool isRVVWideningReduction(uint64_t TSFlags) {
157164
return TSFlags & IsRVVWideningReductionMask;
158165
}
166+
/// \returns true if mask policy is valid for the instruction.
167+
static inline bool UsesMaskPolicy(uint64_t TSFlags) {
168+
return TSFlags & UsesMaskPolicyMask;
169+
}
159170

160171
// RISC-V Specific Machine Operand Flags
161172
enum {

llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -502,29 +502,46 @@ static VSETVLIInfo computeInfoForInstr(const MachineInstr &MI, uint64_t TSFlags,
502502
unsigned NumOperands = MI.getNumExplicitOperands();
503503
bool HasPolicy = RISCVII::hasVecPolicyOp(TSFlags);
504504

505-
// Default to tail agnostic unless the destination is tied to a source.
506-
// Unless the source is undef. In that case the user would have some control
507-
// over the tail values. Some pseudo instructions force a tail agnostic policy
508-
// despite having a tied def.
505+
// If the instruction has policy argument, use the argument.
506+
// If there is no policy argument, default to tail agnostic unless the
507+
// destination is tied to a source. Unless the source is undef. In that case
508+
// the user would have some control over the policy values. Some pseudo
509+
// instructions force a tail agnostic policy despite having a tied def.
509510
bool ForceTailAgnostic = RISCVII::doesForceTailAgnostic(TSFlags);
510511
bool TailAgnostic = true;
511-
// If the instruction has policy argument, use the argument.
512+
bool UsesMaskPolicy = RISCVII::UsesMaskPolicy(TSFlags);
513+
// FIXME: Could we look at the above or below instructions to choose the
514+
// matched mask policy to reduce vsetvli instructions? Default mask policy is
515+
// agnostic if instructions use mask policy, otherwise is undisturbed. Because
516+
// most mask operations are mask undisturbed, so we could possibly reduce the
517+
// vsetvli between mask and nomasked instruction sequence.
518+
bool MaskAgnostic = UsesMaskPolicy;
519+
unsigned UseOpIdx;
512520
if (HasPolicy) {
513521
const MachineOperand &Op = MI.getOperand(MI.getNumExplicitOperands() - 1);
514-
TailAgnostic = Op.getImm() & 0x1;
515-
}
516-
517-
unsigned UseOpIdx;
518-
if (!(ForceTailAgnostic || (HasPolicy && TailAgnostic)) &&
519-
MI.isRegTiedToUseOperand(0, &UseOpIdx)) {
522+
uint64_t Policy = Op.getImm();
523+
assert(Policy <= (RISCVII::TAIL_AGNOSTIC | RISCVII::MASK_AGNOSTIC) &&
524+
"Invalid Policy Value");
525+
// Although in some cases, mismatched passthru/maskedoff with policy value
526+
// does not make sense (ex. tied operand is IMPLICIT_DEF with non-TAMA
527+
// policy, or tied operand is not IMPLICIT_DEF with TAMA policy), but users
528+
// have set the policy value explicitly, so compiler would not fix it.
529+
TailAgnostic = Policy & RISCVII::TAIL_AGNOSTIC;
530+
MaskAgnostic = Policy & RISCVII::MASK_AGNOSTIC;
531+
} else if (!ForceTailAgnostic && MI.isRegTiedToUseOperand(0, &UseOpIdx)) {
520532
TailAgnostic = false;
533+
if (UsesMaskPolicy)
534+
MaskAgnostic = false;
521535
// If the tied operand is an IMPLICIT_DEF we can keep TailAgnostic.
522536
const MachineOperand &UseMO = MI.getOperand(UseOpIdx);
523537
MachineInstr *UseMI = MRI->getVRegDef(UseMO.getReg());
524538
if (UseMI) {
525539
UseMI = elideCopies(UseMI, MRI);
526-
if (UseMI && UseMI->isImplicitDef())
540+
if (UseMI && UseMI->isImplicitDef()) {
527541
TailAgnostic = true;
542+
if (UsesMaskPolicy)
543+
MaskAgnostic = true;
544+
}
528545
}
529546
}
530547

@@ -559,8 +576,8 @@ static VSETVLIInfo computeInfoForInstr(const MachineInstr &MI, uint64_t TSFlags,
559576
}
560577
} else
561578
InstrInfo.setAVLReg(RISCV::NoRegister);
562-
InstrInfo.setVTYPE(VLMul, SEW, /*TailAgnostic*/ TailAgnostic,
563-
/*MaskAgnostic*/ false, MaskRegOp, StoreOp, ScalarMovOp);
579+
InstrInfo.setVTYPE(VLMul, SEW, TailAgnostic, MaskAgnostic, MaskRegOp, StoreOp,
580+
ScalarMovOp);
564581

565582
return InstrInfo;
566583
}

llvm/lib/Target/RISCV/RISCVInstrFormats.td

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,10 @@ class RVInst<dag outs, dag ins, string opcodestr, string argstr,
196196
let TSFlags{16} = HasVecPolicyOp;
197197

198198
bit IsRVVWideningReduction = 0;
199-
let TSFlags{17} = IsRVVWideningReduction;
199+
let TSFlags{17} = IsRVVWideningReduction;
200+
201+
bit UsesMaskPolicy = 0;
202+
let TSFlags{18} = UsesMaskPolicy;
200203
}
201204

202205
// Pseudo instructions

0 commit comments

Comments
 (0)