From f2bec8702688ea034cefcf4e13922aa4d40bd4a0 Mon Sep 17 00:00:00 2001 From: eopXD Date: Thu, 29 Dec 2022 01:05:54 -0800 Subject: [PATCH] [NFC][Clang][RISCV] Reduce boilerplate when determining prototype for segment loads No functionality change of the RVV builtin and compiler intrinsics is intended in this patch. This patch gathers scattered comments for the segment load builtin/intrinsics and its variants (e.g. segment unit-stride load, segment strided load) into a single paragraph under riscv_vector.td. This patch also tries to reduce one level of the if-statements as the push_back are essentially the same actions but differs in index based on the the value of the policy attributes and whether the intrinsic is masked. Reviewed By: kito-cheng Differential Revision: https://reviews.llvm.org/D140662 --- clang/include/clang/Basic/riscv_vector.td | 291 +++++++++++++++++------------- 1 file changed, 161 insertions(+), 130 deletions(-) diff --git a/clang/include/clang/Basic/riscv_vector.td b/clang/include/clang/Basic/riscv_vector.td index 9c05d893..6e089a7 100644 --- a/clang/include/clang/Basic/riscv_vector.td +++ b/clang/include/clang/Basic/riscv_vector.td @@ -812,6 +812,80 @@ multiclass RVVIndexedStore { } defvar NFList = [2, 3, 4, 5, 6, 7, 8]; +/* +A segment load builtin has different variants. + +Therefore a segment unit-stride load builtin can have 4 variants, +1. When unmasked and the policies are all specified as agnostic: +(Address0, ..., Address{NF - 1}, Ptr, VL) +2. When masked and the policies are all specified as agnostic: +(Address0, ..., Address{NF - 1}, Mask, Ptr, VL) +3. When unmasked and one of the policies is specified as undisturbed: +(Address0, ..., Address{NF - 1}, Maskedoff0, ..., Maskedoff{NF - 1}, + Ptr, VL) +4. When masked and one of the policies is specified as undisturbed: +(Address0, ..., Address{NF - 1}, Mask, Maskedoff0, ..., Maskedoff{NF - 1}, + Ptr, VL) + +Other variants of segment load builtin share the same structure, but they +have their own extra parameter. + +The segment unit-stride fault-only-first load builtin has a 'NewVL' +operand after the 'Ptr' operand. +1. When unmasked and the policies are all specified as agnostic: +(Address0, ..., Address{NF - 1}, Ptr, NewVL, VL) +2. When masked and the policies are all specified as agnostic: +(Address0, ..., Address{NF - 1}, Mask, Ptr, NewVL, VL) +3. When unmasked and one of the policies is specified as undisturbed: +(Address0, ..., Address{NF - 1}, Maskedoff0, ..., Maskedoff{NF - 1}, + Ptr, NewVL, VL) +4. When masked and one of the policies is specified as undisturbed: +(Address0, ..., Address{NF - 1}, Mask, Maskedoff0, ..., Maskedoff{NF - 1}, + Ptr, NewVL, VL) + +The segment strided load builtin has a 'Stride' operand after the 'Ptr' +operand. +1. When unmasked and the policies are all specified as agnostic: +(Address0, ..., Address{NF - 1}, Ptr, Stride, VL) +2. When masked and the policies are all specified as agnostic: +(Address0, ..., Address{NF - 1}, Mask, Ptr, Stride, VL) +3. When unmasked and one of the policies is specified as undisturbed: +(Address0, ..., Address{NF - 1}, Maskedoff0, ..., Maskedoff{NF - 1}, + Ptr, Stride, VL) +4. When masked and one of the policies is specified as undisturbed: +(Address0, ..., Address{NF - 1}, Mask, Maskedoff0, ..., Maskedoff{NF - 1}, + Ptr, Stride, VL) + +The segment indexed load builtin has a 'Idx' operand after the 'Ptr' operand. +1. When unmasked and the policies are all specified as agnostic: +(Address0, ..., Address{NF - 1}, Ptr, Idx, VL) +2. When masked and the policies are all specified as agnostic: +(Address0, ..., Address{NF - 1}, Mask, Ptr, Idx, VL) +3. When unmasked and one of the policies is specified as undisturbed: +(Address0, ..., Address{NF - 1}, Maskedoff0, ..., Maskedoff{NF - 1}, + Ptr, Idx, VL) +4. When masked and one of the policies is specified as undisturbed: +(Address0, ..., Address{NF - 1}, Mask, Maskedoff0, ..., Maskedoff{NF - 1}, + Ptr, Idx, VL) + +Segment load intrinsics has different variants similar to their builtins. + +Segment unit-stride load intrinsic, + Masked: (Vector0, ..., Vector{NF - 1}, Ptr, Mask, VL, Policy) + Unmasked: (Vector0, ..., Vector{NF - 1}, Ptr, VL) +Segment unit-stride fault-only-first load intrinsic, + Masked: (Vector0, ..., Vector{NF - 1}, Ptr, Mask, VL, Policy) + Unmasked: (Vector0, ..., Vector{NF - 1}, Ptr, VL) +Segment strided load intrinsic, + Masked: (Vector0, ..., Vector{NF - 1}, Ptr, Stride, Mask, VL, Policy) + Unmasked: (Vector0, ..., Vector{NF - 1}, Ptr, Stride, VL) +Segment indexed load intrinsic, + Masked: (Vector0, ..., Vector{NF - 1}, Ptr, Index, Mask, VL, Policy) + Unmasked: (Vector0, ..., Vector{NF - 1}, Ptr, Index, VL) + +The Vector(s) is poison when the policy behavior allows us to not care +about any masked-off elements. +*/ class PVString { string S = @@ -842,36 +916,30 @@ multiclass RVVUnitStridedSegLoad { { ResultType = ConvertType(E->getArg(0)->getType()->getPointeeType()); IntrinsicTypes = {ResultType, Ops.back()->getType()}; - SmallVector Operands; - if (IsMasked) { - // TAMA builtin: (val0 address, ..., mask, ptr, vl) - // builtin: (val0 address, ..., mask, maskedoff0, ..., ptr, vl) - // intrinsic: (maskedoff0, ..., ptr, mask, vl) - if (PolicyAttrs == TAIL_AGNOSTIC_MASK_AGNOSTIC) { - Operands.append(NF, llvm::PoisonValue::get(ResultType)); - Operands.push_back(Ops[NF + 1]); - Operands.push_back(Ops[NF]); - Operands.push_back(Ops[NF + 2]); - } else { + SmallVector Operands; + + // Please refer to comment under 'defvar NFList' in this file + if ((IsMasked && PolicyAttrs == TAIL_AGNOSTIC_MASK_AGNOSTIC) || + (!IsMasked && PolicyAttrs == TAIL_AGNOSTIC)) + Operands.append(NF, llvm::PoisonValue::get(ResultType)); + else { + if (IsMasked) Operands.append(Ops.begin() + NF + 1, Ops.begin() + 2 * NF + 1); - Operands.push_back(Ops[2 * NF + 1]); - Operands.push_back(Ops[NF]); - Operands.push_back(Ops[2 * NF + 2]); - } - Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - assert(Operands.size() == NF + 4); - } else { - // TA builtin: (val0 address, val1 address, ..., ptr, vl) - // TU builtin: (val0 address, ..., passthru0, ..., ptr, vl) - // intrinsic: (passthru0, passthru1, ..., ptr, vl) - if (PolicyAttrs == TAIL_AGNOSTIC) { - Operands.append(NF, llvm::PoisonValue::get(ResultType)); - Operands.push_back(Ops[NF]); - Operands.push_back(Ops[NF + 1]); - } else { - Operands.append(Ops.begin() + NF, Ops.begin() + 2 * NF + 2); - } + else // Unmasked + Operands.append(Ops.begin() + NF, Ops.begin() + 2 * NF); } + unsigned PtrOperandIdx = IsMasked ? + (PolicyAttrs == TAIL_AGNOSTIC_MASK_AGNOSTIC) ? NF + 1 : 2 * NF + 1 : + (PolicyAttrs == TAIL_AGNOSTIC) ? NF : 2 * NF; + Value *PtrOperand = Ops[PtrOperandIdx]; + Value *VLOperand = Ops[PtrOperandIdx + 1]; + Operands.push_back(PtrOperand); + if (IsMasked) + Operands.push_back(Ops[NF]); + Operands.push_back(VLOperand); + if (IsMasked) + Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); llvm::Value *LoadValue = Builder.CreateCall(F, Operands, ""); clang::CharUnits Align = @@ -914,43 +982,30 @@ multiclass RVVUnitStridedSegLoadFF { ResultType = ConvertType(E->getArg(0)->getType()->getPointeeType()); IntrinsicTypes = {ResultType, Ops.back()->getType()}; SmallVector Operands; - Value *NewVL; - if (IsMasked) { - // TAMA builtin: (val0 address, ..., mask, ptr, new_vl, vl) - // builtin: (val0 address, ..., mask, maskedoff0, ..., ptr, new_vl, vl) - // intrinsic: (maskedoff0, ..., ptr, mask, vl) - if (PolicyAttrs == TAIL_AGNOSTIC_MASK_AGNOSTIC) { - Operands.append(NF, llvm::PoisonValue::get(ResultType)); - Operands.push_back(Ops[NF + 1]); - Operands.push_back(Ops[NF]); - Operands.push_back(Ops[NF + 3]); - NewVL = Ops[NF + 2]; - } else { + // Please refer to comment under 'defvar NFList' in this file + if ((IsMasked && PolicyAttrs == TAIL_AGNOSTIC_MASK_AGNOSTIC) || + (!IsMasked && PolicyAttrs == TAIL_AGNOSTIC)) + Operands.append(NF, llvm::PoisonValue::get(ResultType)); + else { + if (IsMasked) Operands.append(Ops.begin() + NF + 1, Ops.begin() + 2 * NF + 1); - Operands.push_back(Ops[2 * NF + 1]); - Operands.push_back(Ops[NF]); - Operands.push_back(Ops[2 * NF + 3]); - NewVL = Ops[2 * NF + 2]; - } - Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - assert(Operands.size() == NF + 4); - } else { - // TA builtin: (val0 address, val1 address, ..., ptr, new_vl, vl) - // TU builtin: (val0 address, ..., passthru0, ..., ptr, new_vl, vl) - // intrinsic: (passthru0, passthru1, ..., ptr, vl) - if (PolicyAttrs == TAIL_AGNOSTIC) { - Operands.append(NF, llvm::PoisonValue::get(ResultType)); - Operands.push_back(Ops[NF]); - Operands.push_back(Ops[NF + 2]); - NewVL = Ops[NF + 1]; - } else { + else // Unmasked Operands.append(Ops.begin() + NF, Ops.begin() + 2 * NF); - Operands.push_back(Ops[2 * NF]); - Operands.push_back(Ops[2 * NF + 2]); - NewVL = Ops[2 * NF + 1]; - } } + unsigned PtrOperandIdx = IsMasked ? + (PolicyAttrs == TAIL_AGNOSTIC_MASK_AGNOSTIC) ? NF + 1 : 2 * NF + 1 : + (PolicyAttrs == TAIL_AGNOSTIC) ? NF : 2 * NF; + Value *PtrOperand = Ops[PtrOperandIdx]; + Value *NewVLOperand = Ops[PtrOperandIdx + 1]; + Value *VLOperand = Ops[PtrOperandIdx + 2]; + Operands.push_back(PtrOperand); + if (IsMasked) + Operands.push_back(Ops[NF]); + Operands.push_back(VLOperand); + if (IsMasked) + Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); llvm::Value *LoadValue = Builder.CreateCall(F, Operands, ""); clang::CharUnits Align = @@ -961,7 +1016,7 @@ multiclass RVVUnitStridedSegLoadFF { } // Store new_vl. llvm::Value *Val = Builder.CreateExtractValue(LoadValue, {NF}); - return Builder.CreateStore(Val, Address(NewVL, Val->getType(), Align)); + return Builder.CreateStore(Val, Address(NewVLOperand, Val->getType(), Align)); } }] in { defvar PV = PVString.S; @@ -995,41 +1050,30 @@ multiclass RVVStridedSegLoad { IntrinsicTypes = {ResultType, Ops.back()->getType()}; SmallVector Operands; - if (IsMasked) { - // TAMA builtin: (val0 address, ..., mask, ptr, stride, vl) - // builtin: (val0 address, ..., mask, maskedoff0, ..., ptr, stride, vl) - // intrinsic: (maskedoff0, ..., ptr, stride, mask, vl) - if (PolicyAttrs == TAIL_AGNOSTIC_MASK_AGNOSTIC) { - Operands.append(NF, llvm::PoisonValue::get(ResultType)); - Operands.push_back(Ops[NF + 1]); - Operands.push_back(Ops[NF + 2]); - Operands.push_back(Ops[NF]); - Operands.push_back(Ops[NF + 3]); - } else { + // Please refer to comment under 'defvar NFList' in this file + if ((IsMasked && PolicyAttrs == TAIL_AGNOSTIC_MASK_AGNOSTIC) || + (!IsMasked && PolicyAttrs == TAIL_AGNOSTIC)) + Operands.append(NF, llvm::PoisonValue::get(ResultType)); + else { + if (IsMasked) Operands.append(Ops.begin() + NF + 1, Ops.begin() + 2 * NF + 1); - Operands.push_back(Ops[2 * NF + 1]); - Operands.push_back(Ops[2 * NF + 2]); - Operands.push_back(Ops[NF]); - Operands.push_back(Ops[2 * NF + 3]); - } - Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - assert(Operands.size() == NF + 5); - } else { - // TA builtin: (val0 address, val1 address, ..., ptr, stride, vl) - // TU builtin: (val0 address, ..., passthru0, ..., ptr, stride, vl) - // intrinsic: (passthru0, passthru1, ..., ptr, stride, vl) - if (PolicyAttrs == TAIL_AGNOSTIC) { - Operands.append(NF, llvm::PoisonValue::get(ResultType)); - Operands.push_back(Ops[NF]); - Operands.push_back(Ops[NF + 1]); - Operands.push_back(Ops[NF + 2]); - } else { + else // Unmasked Operands.append(Ops.begin() + NF, Ops.begin() + 2 * NF); - Operands.push_back(Ops[2 * NF]); - Operands.push_back(Ops[2 * NF + 1]); - Operands.push_back(Ops[2 * NF + 2]); - } } + unsigned PtrOperandIdx = IsMasked ? + (PolicyAttrs == TAIL_AGNOSTIC_MASK_AGNOSTIC) ? NF + 1 : 2 * NF + 1 : + (PolicyAttrs == TAIL_AGNOSTIC) ? NF : 2 * NF; + Value *PtrOperand = Ops[PtrOperandIdx]; + Value *StrideOperand = Ops[PtrOperandIdx + 1]; + Value *VLOperand = Ops[PtrOperandIdx + 2]; + Operands.push_back(PtrOperand); + Operands.push_back(StrideOperand); + if (IsMasked) + Operands.push_back(Ops[NF]); + Operands.push_back(VLOperand); + if (IsMasked) + Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); llvm::Value *LoadValue = Builder.CreateCall(F, Operands, ""); clang::CharUnits Align = @@ -1067,45 +1111,32 @@ multiclass RVVIndexedSegLoad { { ResultType = ConvertType(E->getArg(0)->getType()->getPointeeType()); SmallVector Operands; - if (IsMasked) { - // TAMA builtin: (val0 address, ..., mask, ptr, index, vl) - // builtin: (val0 address, ..., mask, maskedoff0, ..., ptr, index, vl) - // intrinsic: (maskedoff0, ..., ptr, index, mask, vl) - if (PolicyAttrs == TAIL_AGNOSTIC_MASK_AGNOSTIC) { - Operands.append(NF, llvm::PoisonValue::get(ResultType)); - Operands.push_back(Ops[NF + 1]); - Operands.push_back(Ops[NF + 2]); - Operands.push_back(Ops[NF]); - Operands.push_back(Ops[NF + 3]); - IntrinsicTypes = {ResultType, Ops[NF + 2]->getType(), Ops.back()->getType()}; - } else { + + // Please refer to comment under 'defvar NFList' in this file + if ((IsMasked && PolicyAttrs == TAIL_AGNOSTIC_MASK_AGNOSTIC) || + (!IsMasked && PolicyAttrs == TAIL_AGNOSTIC)) + Operands.append(NF, llvm::PoisonValue::get(ResultType)); + else { + if (IsMasked) Operands.append(Ops.begin() + NF + 1, Ops.begin() + 2 * NF + 1); - Operands.push_back(Ops[2 * NF + 1]); - Operands.push_back(Ops[2 * NF + 2]); - Operands.push_back(Ops[NF]); - Operands.push_back(Ops[2 * NF + 3]); - IntrinsicTypes = {ResultType, Ops[2 * NF + 2]->getType(), Ops.back()->getType()}; - } - Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); - assert(Operands.size() == NF + 5); - } else { - // TA builtin: (val0 address, val1 address, ..., ptr, index, vl) - // TU builtin: (val0 address, ..., passthru0, ..., ptr, index, vl) - // intrinsic: (passthru0, passthru1, ..., ptr, index, vl) - if (PolicyAttrs == TAIL_AGNOSTIC) { - Operands.append(NF, llvm::PoisonValue::get(ResultType)); - Operands.push_back(Ops[NF]); - Operands.push_back(Ops[NF + 1]); - Operands.push_back(Ops[NF + 2]); - IntrinsicTypes = {ResultType, Ops[NF + 1]->getType(), Ops.back()->getType()}; - } else { + else // Unmasked Operands.append(Ops.begin() + NF, Ops.begin() + 2 * NF); - Operands.push_back(Ops[2 * NF]); - Operands.push_back(Ops[2 * NF + 1]); - Operands.push_back(Ops[2 * NF + 2]); - IntrinsicTypes = {ResultType, Ops[2 * NF + 1]->getType(), Ops.back()->getType()}; - } } + unsigned PtrOperandIdx = IsMasked ? + (PolicyAttrs == TAIL_AGNOSTIC_MASK_AGNOSTIC) ? NF + 1 : 2 * NF + 1 : + (PolicyAttrs == TAIL_AGNOSTIC) ? NF : 2 * NF; + Value *PtrOperand = Ops[PtrOperandIdx]; + Value *IndexOperand = Ops[PtrOperandIdx + 1]; + Value *VLOperand = Ops[PtrOperandIdx + 2]; + Operands.push_back(PtrOperand); + Operands.push_back(IndexOperand); + if (IsMasked) + Operands.push_back(Ops[NF]); + Operands.push_back(VLOperand); + if (IsMasked) + Operands.push_back(ConstantInt::get(Ops.back()->getType(), PolicyAttrs)); + IntrinsicTypes = {ResultType, IndexOperand->getType(), Ops.back()->getType()}; + llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); llvm::Value *LoadValue = Builder.CreateCall(F, Operands, ""); clang::CharUnits Align = -- 2.7.4