Skip to content

Commit 2c05c35

Browse files
committed
[ASan][RISCV] Support asan check for segment load/store RVV intrinsics.
RVV segment is an array of SegNum contingous elements. This patch emulates RVV segment as a large integer with bitwidth equaled to SegNum * SEW. The reason to not emulate RVV segment as some aggregated type is that vector type should use premative types as element types. There is another approach is to create SegNum InterestingMemoryOperand objects. It could avoid create pseudo types, but this approach also generates large code for asan check.
1 parent 32baec4 commit 2c05c35

File tree

2 files changed

+2917
-139
lines changed

2 files changed

+2917
-139
lines changed

llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp

Lines changed: 177 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2747,20 +2747,69 @@ bool RISCVTTIImpl::getTgtMemIntrinsic(IntrinsicInst *Inst,
27472747
Intrinsic::ID IID = Inst->getIntrinsicID();
27482748
LLVMContext &C = Inst->getContext();
27492749
bool HasMask = false;
2750+
2751+
auto getSegNum = [](const IntrinsicInst *II, unsigned PtrOperandNo,
2752+
bool IsWrite) -> int64_t {
2753+
if (auto *TarExtTy =
2754+
dyn_cast<TargetExtType>(II->getArgOperand(0)->getType()))
2755+
return TarExtTy->getIntParameter(0);
2756+
if (IsWrite)
2757+
return PtrOperandNo;
2758+
return 1;
2759+
};
2760+
27502761
switch (IID) {
27512762
case Intrinsic::riscv_vle_mask:
27522763
case Intrinsic::riscv_vse_mask:
2764+
case Intrinsic::riscv_vlseg2_mask:
2765+
case Intrinsic::riscv_vlseg3_mask:
2766+
case Intrinsic::riscv_vlseg4_mask:
2767+
case Intrinsic::riscv_vlseg5_mask:
2768+
case Intrinsic::riscv_vlseg6_mask:
2769+
case Intrinsic::riscv_vlseg7_mask:
2770+
case Intrinsic::riscv_vlseg8_mask:
2771+
case Intrinsic::riscv_vsseg2_mask:
2772+
case Intrinsic::riscv_vsseg3_mask:
2773+
case Intrinsic::riscv_vsseg4_mask:
2774+
case Intrinsic::riscv_vsseg5_mask:
2775+
case Intrinsic::riscv_vsseg6_mask:
2776+
case Intrinsic::riscv_vsseg7_mask:
2777+
case Intrinsic::riscv_vsseg8_mask:
27532778
HasMask = true;
27542779
[[fallthrough]];
27552780
case Intrinsic::riscv_vle:
2756-
case Intrinsic::riscv_vse: {
2781+
case Intrinsic::riscv_vse:
2782+
case Intrinsic::riscv_vlseg2:
2783+
case Intrinsic::riscv_vlseg3:
2784+
case Intrinsic::riscv_vlseg4:
2785+
case Intrinsic::riscv_vlseg5:
2786+
case Intrinsic::riscv_vlseg6:
2787+
case Intrinsic::riscv_vlseg7:
2788+
case Intrinsic::riscv_vlseg8:
2789+
case Intrinsic::riscv_vsseg2:
2790+
case Intrinsic::riscv_vsseg3:
2791+
case Intrinsic::riscv_vsseg4:
2792+
case Intrinsic::riscv_vsseg5:
2793+
case Intrinsic::riscv_vsseg6:
2794+
case Intrinsic::riscv_vsseg7:
2795+
case Intrinsic::riscv_vsseg8: {
27572796
// Intrinsic interface:
27582797
// riscv_vle(merge, ptr, vl)
27592798
// riscv_vle_mask(merge, ptr, mask, vl, policy)
27602799
// riscv_vse(val, ptr, vl)
27612800
// riscv_vse_mask(val, ptr, mask, vl, policy)
27622801
bool IsWrite = Inst->getType()->isVoidTy();
27632802
Type *Ty = IsWrite ? Inst->getArgOperand(0)->getType() : Inst->getType();
2803+
// The results of segment loads are TargetExtType.
2804+
if (auto *TarExtTy = dyn_cast<TargetExtType>(Ty)) {
2805+
unsigned SEW =
2806+
1 << cast<ConstantInt>(Inst->getArgOperand(Inst->arg_size() - 1))
2807+
->getZExtValue();
2808+
Ty = TarExtTy->getTypeParameter(0U);
2809+
Ty = ScalableVectorType::get(
2810+
IntegerType::get(C, SEW),
2811+
cast<ScalableVectorType>(Ty)->getMinNumElements() * 8 / SEW);
2812+
}
27642813
const auto *RVVIInfo = RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IID);
27652814
unsigned VLIndex = RVVIInfo->VLOperand;
27662815
unsigned PtrOperandNo = VLIndex - 1 - HasMask;
@@ -2771,23 +2820,68 @@ bool RISCVTTIImpl::getTgtMemIntrinsic(IntrinsicInst *Inst,
27712820
if (HasMask)
27722821
Mask = Inst->getArgOperand(VLIndex - 1);
27732822
Value *EVL = Inst->getArgOperand(VLIndex);
2823+
unsigned SegNum = getSegNum(Inst, PtrOperandNo, IsWrite);
2824+
// RVV uses contiguous elements as a segment.
2825+
if (SegNum > 1) {
2826+
unsigned ElemSize = Ty->getScalarSizeInBits();
2827+
auto *SegTy = IntegerType::get(C, ElemSize * SegNum);
2828+
Ty = VectorType::get(SegTy, cast<VectorType>(Ty));
2829+
}
27742830
Info.InterestingOperands.emplace_back(Inst, PtrOperandNo, IsWrite, Ty,
27752831
Alignment, Mask, EVL);
27762832
return true;
27772833
}
27782834
case Intrinsic::riscv_vlse_mask:
27792835
case Intrinsic::riscv_vsse_mask:
2836+
case Intrinsic::riscv_vlsseg2_mask:
2837+
case Intrinsic::riscv_vlsseg3_mask:
2838+
case Intrinsic::riscv_vlsseg4_mask:
2839+
case Intrinsic::riscv_vlsseg5_mask:
2840+
case Intrinsic::riscv_vlsseg6_mask:
2841+
case Intrinsic::riscv_vlsseg7_mask:
2842+
case Intrinsic::riscv_vlsseg8_mask:
2843+
case Intrinsic::riscv_vssseg2_mask:
2844+
case Intrinsic::riscv_vssseg3_mask:
2845+
case Intrinsic::riscv_vssseg4_mask:
2846+
case Intrinsic::riscv_vssseg5_mask:
2847+
case Intrinsic::riscv_vssseg6_mask:
2848+
case Intrinsic::riscv_vssseg7_mask:
2849+
case Intrinsic::riscv_vssseg8_mask:
27802850
HasMask = true;
27812851
[[fallthrough]];
27822852
case Intrinsic::riscv_vlse:
2783-
case Intrinsic::riscv_vsse: {
2853+
case Intrinsic::riscv_vsse:
2854+
case Intrinsic::riscv_vlsseg2:
2855+
case Intrinsic::riscv_vlsseg3:
2856+
case Intrinsic::riscv_vlsseg4:
2857+
case Intrinsic::riscv_vlsseg5:
2858+
case Intrinsic::riscv_vlsseg6:
2859+
case Intrinsic::riscv_vlsseg7:
2860+
case Intrinsic::riscv_vlsseg8:
2861+
case Intrinsic::riscv_vssseg2:
2862+
case Intrinsic::riscv_vssseg3:
2863+
case Intrinsic::riscv_vssseg4:
2864+
case Intrinsic::riscv_vssseg5:
2865+
case Intrinsic::riscv_vssseg6:
2866+
case Intrinsic::riscv_vssseg7:
2867+
case Intrinsic::riscv_vssseg8: {
27842868
// Intrinsic interface:
27852869
// riscv_vlse(merge, ptr, stride, vl)
27862870
// riscv_vlse_mask(merge, ptr, stride, mask, vl, policy)
27872871
// riscv_vsse(val, ptr, stride, vl)
27882872
// riscv_vsse_mask(val, ptr, stride, mask, vl, policy)
27892873
bool IsWrite = Inst->getType()->isVoidTy();
27902874
Type *Ty = IsWrite ? Inst->getArgOperand(0)->getType() : Inst->getType();
2875+
// The results of segment loads are TargetExtType.
2876+
if (auto *TarExtTy = dyn_cast<TargetExtType>(Ty)) {
2877+
unsigned SEW =
2878+
1 << cast<ConstantInt>(Inst->getArgOperand(Inst->arg_size() - 1))
2879+
->getZExtValue();
2880+
Ty = TarExtTy->getTypeParameter(0U);
2881+
Ty = ScalableVectorType::get(
2882+
IntegerType::get(C, SEW),
2883+
cast<ScalableVectorType>(Ty)->getMinNumElements() * 8 / SEW);
2884+
}
27912885
const auto *RVVIInfo = RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IID);
27922886
unsigned VLIndex = RVVIInfo->VLOperand;
27932887
unsigned PtrOperandNo = VLIndex - 2 - HasMask;
@@ -2809,6 +2903,13 @@ bool RISCVTTIImpl::getTgtMemIntrinsic(IntrinsicInst *Inst,
28092903
if (HasMask)
28102904
Mask = Inst->getArgOperand(VLIndex - 1);
28112905
Value *EVL = Inst->getArgOperand(VLIndex);
2906+
unsigned SegNum = getSegNum(Inst, PtrOperandNo, IsWrite);
2907+
// RVV uses contiguous elements as a segment.
2908+
if (SegNum > 1) {
2909+
unsigned ElemSize = Ty->getScalarSizeInBits();
2910+
auto *SegTy = IntegerType::get(C, ElemSize * SegNum);
2911+
Ty = VectorType::get(SegTy, cast<VectorType>(Ty));
2912+
}
28122913
Info.InterestingOperands.emplace_back(Inst, PtrOperandNo, IsWrite, Ty,
28132914
Alignment, Mask, EVL, Stride);
28142915
return true;
@@ -2817,19 +2918,85 @@ bool RISCVTTIImpl::getTgtMemIntrinsic(IntrinsicInst *Inst,
28172918
case Intrinsic::riscv_vluxei_mask:
28182919
case Intrinsic::riscv_vsoxei_mask:
28192920
case Intrinsic::riscv_vsuxei_mask:
2921+
case Intrinsic::riscv_vloxseg2_mask:
2922+
case Intrinsic::riscv_vloxseg3_mask:
2923+
case Intrinsic::riscv_vloxseg4_mask:
2924+
case Intrinsic::riscv_vloxseg5_mask:
2925+
case Intrinsic::riscv_vloxseg6_mask:
2926+
case Intrinsic::riscv_vloxseg7_mask:
2927+
case Intrinsic::riscv_vloxseg8_mask:
2928+
case Intrinsic::riscv_vluxseg2_mask:
2929+
case Intrinsic::riscv_vluxseg3_mask:
2930+
case Intrinsic::riscv_vluxseg4_mask:
2931+
case Intrinsic::riscv_vluxseg5_mask:
2932+
case Intrinsic::riscv_vluxseg6_mask:
2933+
case Intrinsic::riscv_vluxseg7_mask:
2934+
case Intrinsic::riscv_vluxseg8_mask:
2935+
case Intrinsic::riscv_vsoxseg2_mask:
2936+
case Intrinsic::riscv_vsoxseg3_mask:
2937+
case Intrinsic::riscv_vsoxseg4_mask:
2938+
case Intrinsic::riscv_vsoxseg5_mask:
2939+
case Intrinsic::riscv_vsoxseg6_mask:
2940+
case Intrinsic::riscv_vsoxseg7_mask:
2941+
case Intrinsic::riscv_vsoxseg8_mask:
2942+
case Intrinsic::riscv_vsuxseg2_mask:
2943+
case Intrinsic::riscv_vsuxseg3_mask:
2944+
case Intrinsic::riscv_vsuxseg4_mask:
2945+
case Intrinsic::riscv_vsuxseg5_mask:
2946+
case Intrinsic::riscv_vsuxseg6_mask:
2947+
case Intrinsic::riscv_vsuxseg7_mask:
2948+
case Intrinsic::riscv_vsuxseg8_mask:
28202949
HasMask = true;
28212950
[[fallthrough]];
28222951
case Intrinsic::riscv_vloxei:
28232952
case Intrinsic::riscv_vluxei:
28242953
case Intrinsic::riscv_vsoxei:
2825-
case Intrinsic::riscv_vsuxei: {
2954+
case Intrinsic::riscv_vsuxei:
2955+
case Intrinsic::riscv_vloxseg2:
2956+
case Intrinsic::riscv_vloxseg3:
2957+
case Intrinsic::riscv_vloxseg4:
2958+
case Intrinsic::riscv_vloxseg5:
2959+
case Intrinsic::riscv_vloxseg6:
2960+
case Intrinsic::riscv_vloxseg7:
2961+
case Intrinsic::riscv_vloxseg8:
2962+
case Intrinsic::riscv_vluxseg2:
2963+
case Intrinsic::riscv_vluxseg3:
2964+
case Intrinsic::riscv_vluxseg4:
2965+
case Intrinsic::riscv_vluxseg5:
2966+
case Intrinsic::riscv_vluxseg6:
2967+
case Intrinsic::riscv_vluxseg7:
2968+
case Intrinsic::riscv_vluxseg8:
2969+
case Intrinsic::riscv_vsoxseg2:
2970+
case Intrinsic::riscv_vsoxseg3:
2971+
case Intrinsic::riscv_vsoxseg4:
2972+
case Intrinsic::riscv_vsoxseg5:
2973+
case Intrinsic::riscv_vsoxseg6:
2974+
case Intrinsic::riscv_vsoxseg7:
2975+
case Intrinsic::riscv_vsoxseg8:
2976+
case Intrinsic::riscv_vsuxseg2:
2977+
case Intrinsic::riscv_vsuxseg3:
2978+
case Intrinsic::riscv_vsuxseg4:
2979+
case Intrinsic::riscv_vsuxseg5:
2980+
case Intrinsic::riscv_vsuxseg6:
2981+
case Intrinsic::riscv_vsuxseg7:
2982+
case Intrinsic::riscv_vsuxseg8: {
28262983
// Intrinsic interface (only listed ordered version):
28272984
// riscv_vloxei(merge, ptr, index, vl)
28282985
// riscv_vloxei_mask(merge, ptr, index, mask, vl, policy)
28292986
// riscv_vsoxei(val, ptr, index, vl)
28302987
// riscv_vsoxei_mask(val, ptr, index, mask, vl, policy)
28312988
bool IsWrite = Inst->getType()->isVoidTy();
28322989
Type *Ty = IsWrite ? Inst->getArgOperand(0)->getType() : Inst->getType();
2990+
// The results of segment loads are TargetExtType.
2991+
if (auto *TarExtTy = dyn_cast<TargetExtType>(Ty)) {
2992+
unsigned SEW =
2993+
1 << cast<ConstantInt>(Inst->getArgOperand(Inst->arg_size() - 1))
2994+
->getZExtValue();
2995+
Ty = TarExtTy->getTypeParameter(0U);
2996+
Ty = ScalableVectorType::get(
2997+
IntegerType::get(C, SEW),
2998+
cast<ScalableVectorType>(Ty)->getMinNumElements() * 8 / SEW);
2999+
}
28333000
const auto *RVVIInfo = RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IID);
28343001
unsigned VLIndex = RVVIInfo->VLOperand;
28353002
unsigned PtrOperandNo = VLIndex - 2 - HasMask;
@@ -2845,6 +3012,13 @@ bool RISCVTTIImpl::getTgtMemIntrinsic(IntrinsicInst *Inst,
28453012
Mask = ConstantInt::getTrue(MaskType);
28463013
}
28473014
Value *EVL = Inst->getArgOperand(VLIndex);
3015+
unsigned SegNum = getSegNum(Inst, PtrOperandNo, IsWrite);
3016+
// RVV uses contiguous elements as a segment.
3017+
if (SegNum > 1) {
3018+
unsigned ElemSize = Ty->getScalarSizeInBits();
3019+
auto *SegTy = IntegerType::get(C, ElemSize * SegNum);
3020+
Ty = VectorType::get(SegTy, cast<VectorType>(Ty));
3021+
}
28483022
Value *OffsetOp = Inst->getArgOperand(PtrOperandNo + 1);
28493023
Info.InterestingOperands.emplace_back(Inst, PtrOperandNo, IsWrite, Ty,
28503024
Align(1), Mask, EVL,

0 commit comments

Comments
 (0)