diff --git a/clang/include/clang/Basic/riscv_vector.td b/clang/include/clang/Basic/riscv_vector.td --- a/clang/include/clang/Basic/riscv_vector.td +++ b/clang/include/clang/Basic/riscv_vector.td @@ -843,22 +843,29 @@ IRName = op # nf, MaskedIRName = op # nf # "_mask", NF = nf, - SupportOverloading = false, ManualCodegen = [{ { - // builtin: (val0 address, val1 address, ..., ptr, vl) ResultType = ConvertType(E->getArg(0)->getType()->getPointeeType()); - IntrinsicTypes = {ResultType, Ops[NF + 1]->getType()}; + // TA builtin: (val0 address, val1 address, ..., ptr, vl) + // TU builtin: (val0 address, ..., passthru0, ..., ptr, vl) + IntrinsicTypes = {ResultType, Ops.back()->getType()}; // intrinsic: (passthru0, passthru1, ..., ptr, vl) SmallVector Operands; - for (unsigned I = 0; I < NF; ++I) - Operands.push_back(llvm::UndefValue::get(ResultType)); - Operands.push_back(Ops[NF]); - Operands.push_back(Ops[NF + 1]); + if (DefaultPolicy == TAIL_AGNOSTIC) { + for (unsigned I = 0; I < NF; ++I) + Operands.push_back(llvm::UndefValue::get(ResultType)); + Operands.push_back(Ops[NF]); + Operands.push_back(Ops[NF + 1]); + } else { + for (unsigned I = 0; I < NF; ++I) + Operands.push_back(Ops[NF + I]); + Operands.push_back(Ops[2 * NF]); + Operands.push_back(Ops[2 * NF + 1]); + } llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); llvm::Value *LoadValue = Builder.CreateCall(F, Operands, ""); clang::CharUnits Align = - CGM.getNaturalPointeeTypeAlignment(E->getArg(NF)->getType()); + CGM.getNaturalPointeeTypeAlignment(E->getArg(0)->getType()); llvm::Value *V; for (unsigned I = 0; I < NF; ++I) { llvm::Value *Val = Builder.CreateExtractValue(LoadValue, {I}); @@ -869,17 +876,26 @@ }], MaskedManualCodegen = [{ { + // TAMA builtin: (val0 address, ..., mask, ptr, vl) // builtin: (val0 address, ..., mask, maskedoff0, ..., ptr, vl) // intrinsic: (maskedoff0, ..., ptr, mask, vl) - IntrinsicTypes = {ConvertType(E->getArg(0)->getType()->getPointeeType()), - Ops[2 * NF + 2]->getType()}; + ResultType = ConvertType(E->getArg(0)->getType()->getPointeeType()); + IntrinsicTypes = {ResultType, Ops.back()->getType()}; SmallVector Operands; - for (unsigned I = 0; I < NF; ++I) - Operands.push_back(Ops[NF + I + 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(), TAIL_UNDISTURBED)); + if (DefaultPolicy == TAIL_AGNOSTIC_MASK_AGNOSTIC) { + for (unsigned I = 0; I < NF; ++I) + Operands.push_back(llvm::UndefValue::get(ResultType)); + Operands.push_back(Ops[NF + 1]); + Operands.push_back(Ops[NF]); + Operands.push_back(Ops[NF + 2]); + } else { + for (unsigned I = 0; I < NF; ++I) + Operands.push_back(Ops[NF + I + 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(), DefaultPolicy)); assert(Operands.size() == NF + 4); llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); llvm::Value *LoadValue = Builder.CreateCall(F, Operands, ""); @@ -918,19 +934,28 @@ IRName = op # nf # "ff", MaskedIRName = op # nf # "ff_mask", NF = nf, - SupportOverloading = false, ManualCodegen = [{ { - // builtin: (val0 address, val1 address, ..., ptr, new_vl, vl) + // TA builtin: (val0 address, val1 address, ..., ptr, new_vl, vl) + // TU builtin: (val0 address, ..., passthru0, ..., ptr, new_vl, vl) ResultType = ConvertType(E->getArg(0)->getType()->getPointeeType()); - IntrinsicTypes = {ResultType, Ops[NF + 2]->getType()}; + IntrinsicTypes = {ResultType, Ops.back()->getType()}; // intrinsic: (passthru0, passthru1, ..., ptr, vl) SmallVector Operands; - for (unsigned I = 0; I < NF; ++I) - Operands.push_back(llvm::UndefValue::get(ResultType)); - Operands.push_back(Ops[NF]); - Operands.push_back(Ops[NF + 2]); - Value *NewVL = Ops[NF + 1]; + Value *NewVL; + if (DefaultPolicy == TAIL_AGNOSTIC) { + for (unsigned I = 0; I < NF; ++I) + Operands.push_back(llvm::UndefValue::get(ResultType)); + Operands.push_back(Ops[NF]); + Operands.push_back(Ops[NF + 2]); + NewVL = Ops[NF + 1]; + } else { + for (unsigned I = 0; I < NF; ++I) + Operands.push_back(Ops[NF + I]); + Operands.push_back(Ops[2 * NF]); + Operands.push_back(Ops[2 * NF + 2]); + NewVL = Ops[2 * NF + 1]; + } llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); llvm::Value *LoadValue = Builder.CreateCall(F, Operands, ""); clang::CharUnits Align = @@ -946,18 +971,29 @@ }], MaskedManualCodegen = [{ { + // TAMA builtin: (val0 address, ..., mask, ptr, new_vl, vl) // builtin: (val0 address, ..., mask, maskedoff0, ..., ptr, new_vl, vl) // intrinsic: (maskedoff0, ..., ptr, mask, vl) - IntrinsicTypes = {ConvertType(E->getArg(0)->getType()->getPointeeType()), - Ops[2 * NF + 3]->getType()}; + ResultType = ConvertType(E->getArg(0)->getType()->getPointeeType()); + IntrinsicTypes = {ResultType, Ops.back()->getType()}; SmallVector Operands; - for (unsigned I = 0; I < NF; ++I) - Operands.push_back(Ops[NF + I + 1]); - Operands.push_back(Ops[2 * NF + 1]); - Operands.push_back(Ops[NF]); - Operands.push_back(Ops[2 * NF + 3]); - Operands.push_back(ConstantInt::get(Ops.back()->getType(), TAIL_UNDISTURBED)); - Value *NewVL = Ops[2 * NF + 2]; + Value *NewVL; + if (DefaultPolicy == TAIL_AGNOSTIC_MASK_AGNOSTIC) { + for (unsigned I = 0; I < NF; ++I) + Operands.push_back(llvm::UndefValue::get(ResultType)); + Operands.push_back(Ops[NF + 1]); + Operands.push_back(Ops[NF]); + Operands.push_back(Ops[NF + 3]); + NewVL = Ops[NF + 2]; + } else { + for (unsigned I = 0; I < NF; ++I) + Operands.push_back(Ops[NF + I + 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(), DefaultPolicy)); assert(Operands.size() == NF + 4); llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); llvm::Value *LoadValue = Builder.CreateCall(F, Operands, ""); @@ -997,19 +1033,27 @@ IRName = op # nf, MaskedIRName = op # nf # "_mask", NF = nf, - SupportOverloading = false, ManualCodegen = [{ { - // builtin: (val0 address, val1 address, ..., ptr, stride, vl) + // TA builtin: (val0 address, val1 address, ..., ptr, stride, vl) + // TU builtin: (val0 address, ..., passthru0, ..., ptr, stride, vl) ResultType = ConvertType(E->getArg(0)->getType()->getPointeeType()); - IntrinsicTypes = {ResultType, Ops[NF + 2]->getType()}; + IntrinsicTypes = {ResultType, Ops.back()->getType()}; // intrinsic: (passthru0, passthru1, ..., ptr, stride, vl) SmallVector Operands; - for (unsigned I = 0; I < NF; ++I) - Operands.push_back(llvm::UndefValue::get(ResultType)); - Operands.push_back(Ops[NF]); - Operands.push_back(Ops[NF + 1]); - Operands.push_back(Ops[NF + 2]); + if (DefaultPolicy == TAIL_AGNOSTIC) { + for (unsigned I = 0; I < NF; ++I) + Operands.push_back(llvm::UndefValue::get(ResultType)); + Operands.push_back(Ops[NF]); + Operands.push_back(Ops[NF + 1]); + Operands.push_back(Ops[NF + 2]); + } else { + for (unsigned I = 0; I < NF; ++I) + Operands.push_back(Ops[NF + I]); + Operands.push_back(Ops[2 * NF]); + Operands.push_back(Ops[2 * NF + 1]); + Operands.push_back(Ops[2 * NF + 2]); + } llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); llvm::Value *LoadValue = Builder.CreateCall(F, Operands, ""); clang::CharUnits Align = @@ -1024,18 +1068,28 @@ }], MaskedManualCodegen = [{ { + //TAMA builtin: (val0 address, ..., mask, ptr, stride, vl) // builtin: (val0 address, ..., mask, maskedoff0, ..., ptr, stride, vl) // intrinsic: (maskedoff0, ..., ptr, stride, mask, vl) - IntrinsicTypes = {ConvertType(E->getArg(0)->getType()->getPointeeType()), - Ops[2 * NF + 3]->getType()}; + ResultType = ConvertType(E->getArg(0)->getType()->getPointeeType()); + IntrinsicTypes = {ResultType, Ops.back()->getType()}; SmallVector Operands; - for (unsigned I = 0; I < NF; ++I) - Operands.push_back(Ops[NF + I + 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(), TAIL_UNDISTURBED)); + if (DefaultPolicy == TAIL_AGNOSTIC_MASK_AGNOSTIC) { + for (unsigned I = 0; I < NF; ++I) + Operands.push_back(llvm::UndefValue::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 { + for (unsigned I = 0; I < NF; ++I) + Operands.push_back(Ops[NF + I + 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(), DefaultPolicy)); assert(Operands.size() == NF + 5); llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); llvm::Value *LoadValue = Builder.CreateCall(F, Operands, ""); @@ -1072,16 +1126,26 @@ NF = nf, ManualCodegen = [{ { - // builtin: (val0 address, val1 address, ..., ptr, index, vl) + // TA builtin: (val0 address, val1 address, ..., ptr, index, vl) + // TU builtin: (val0 address, ..., passthru0, ..., ptr, index, vl) ResultType = ConvertType(E->getArg(0)->getType()->getPointeeType()); - IntrinsicTypes = {ResultType, Ops[NF + 1]->getType(), Ops[NF + 2]->getType()}; // intrinsic: (passthru0, passthru1, ..., ptr, index, vl) SmallVector Operands; - for (unsigned I = 0; I < NF; ++I) - Operands.push_back(llvm::UndefValue::get(ResultType)); - Operands.push_back(Ops[NF]); - Operands.push_back(Ops[NF + 1]); - Operands.push_back(Ops[NF + 2]); + if (DefaultPolicy == TAIL_AGNOSTIC) { + for (unsigned I = 0; I < NF; ++I) + Operands.push_back(llvm::UndefValue::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 { + for (unsigned I = 0; I < NF; ++I) + Operands.push_back(Ops[NF + I]); + 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()}; + } llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); llvm::Value *LoadValue = Builder.CreateCall(F, Operands, ""); clang::CharUnits Align = @@ -1096,18 +1160,29 @@ }], MaskedManualCodegen = [{ { + // TAMA builtin: (val0 address, ..., mask, ptr, index, vl) // builtin: (val0 address, ..., mask, maskedoff0, ..., ptr, index, vl) - IntrinsicTypes = {ConvertType(E->getArg(0)->getType()->getPointeeType()), - Ops[2 * NF + 2]->getType(), Ops[2 * NF + 3]->getType()}; + ResultType = ConvertType(E->getArg(0)->getType()->getPointeeType()); // intrinsic: (maskedoff0, ..., ptr, index, mask, vl) SmallVector Operands; - for (unsigned I = 0; I < NF; ++I) - Operands.push_back(Ops[NF + I + 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(), TAIL_UNDISTURBED)); + if (DefaultPolicy == TAIL_AGNOSTIC_MASK_AGNOSTIC) { + for (unsigned I = 0; I < NF; ++I) + Operands.push_back(llvm::UndefValue::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 { + for (unsigned I = 0; I < NF; ++I) + Operands.push_back(Ops[NF + I + 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(), DefaultPolicy)); assert(Operands.size() == NF + 5); llvm::Function *F = CGM.getIntrinsic(ID, IntrinsicTypes); llvm::Value *LoadValue = Builder.CreateCall(F, Operands, ""); @@ -1649,14 +1724,15 @@ defm vle64ff: RVVVLEFFBuiltin<["l", "d"]>; // 7.8 Vector Load/Store Segment Instructions -// TODO: Support policy function for segment load. -let UnMaskedPolicyScheme = NonePolicy, - MaskedPolicyScheme = NonePolicy in { +let UnMaskedPolicyScheme = HasPassthruOperand in { defm : RVVUnitStridedSegLoad<"vlseg">; defm : RVVUnitStridedSegLoadFF<"vlseg">; defm : RVVStridedSegLoad<"vlsseg">; defm : RVVIndexedSegLoad<"vluxseg">; defm : RVVIndexedSegLoad<"vloxseg">; +} +let UnMaskedPolicyScheme = NonePolicy, + MaskedPolicyScheme = NonePolicy in { defm : RVVUnitStridedSegStore<"vsseg">; defm : RVVStridedSegStore<"vssseg">; defm : RVVIndexedSegStore<"vsuxseg">; diff --git a/clang/lib/Support/RISCVVIntrinsicUtils.cpp b/clang/lib/Support/RISCVVIntrinsicUtils.cpp --- a/clang/lib/Support/RISCVVIntrinsicUtils.cpp +++ b/clang/lib/Support/RISCVVIntrinsicUtils.cpp @@ -941,8 +941,8 @@ if (IsMasked) { // If HasMaskedOffOperand, insert result type as first input operand if // need. - if (HasMaskedOffOperand) { - if (NF == 1 && DefaultPolicy != Policy::TAMA) { + if (HasMaskedOffOperand && DefaultPolicy != Policy::TAMA) { + if (NF == 1) { NewPrototype.insert(NewPrototype.begin() + 1, NewPrototype[0]); } else if (NF > 1) { // Convert @@ -971,22 +971,34 @@ // If IsMasked, insert PrototypeDescriptor:Mask as first input operand. NewPrototype.insert(NewPrototype.begin() + 1, PrototypeDescriptor::Mask); } - } else if (NF == 1) { - if (DefaultPolicy == Policy::TU && HasPassthruOp && !IsPrototypeDefaultTU) - NewPrototype.insert(NewPrototype.begin(), NewPrototype[0]); - else if (DefaultPolicy == Policy::TA && HasPassthruOp && - IsPrototypeDefaultTU) - NewPrototype.erase(NewPrototype.begin() + 1); - if (DefaultScheme == PolicyScheme::HasPassthruOperandAtIdx1) { - if (DefaultPolicy == Policy::TU && !IsPrototypeDefaultTU) { - // Insert undisturbed output to index 1 - NewPrototype.insert(NewPrototype.begin() + 2, NewPrototype[0]); - } else if (DefaultPolicy == Policy::TA && IsPrototypeDefaultTU) { - // Erase passthru for TA policy - NewPrototype.erase(NewPrototype.begin() + 2); + } else { + if (NF == 1) { + if (DefaultPolicy == Policy::TU && HasPassthruOp && !IsPrototypeDefaultTU) + NewPrototype.insert(NewPrototype.begin(), NewPrototype[0]); + else if (DefaultPolicy == Policy::TA && HasPassthruOp && + IsPrototypeDefaultTU) + NewPrototype.erase(NewPrototype.begin() + 1); + if (DefaultScheme == PolicyScheme::HasPassthruOperandAtIdx1) { + if (DefaultPolicy == Policy::TU && !IsPrototypeDefaultTU) { + // Insert undisturbed output to index 1 + NewPrototype.insert(NewPrototype.begin() + 2, NewPrototype[0]); + } else if (DefaultPolicy == Policy::TA && IsPrototypeDefaultTU) { + // Erase passthru for TA policy + NewPrototype.erase(NewPrototype.begin() + 2); + } } + } else if (DefaultPolicy == Policy::TU && HasPassthruOp) { + // NF > 1 cases for segment load operations. + // Convert + // (void, op0 address, op1 address, ...) + // to + // (void, op0 address, op1 address, maskedoff0, maskedoff1, ...) + PrototypeDescriptor MaskoffType = Prototype[1]; + MaskoffType.TM &= ~static_cast(TypeModifier::Pointer); + for (unsigned I = 0; I < NF; ++I) + NewPrototype.insert(NewPrototype.begin() + NF + 1, MaskoffType); } - } + } // If HasVL, append PrototypeDescriptor:VL to last operand if (HasVL) diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vloxseg_mask_mf.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vloxseg_mask_mf.c --- a/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vloxseg_mask_mf.c +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vloxseg_mask_mf.c @@ -6922,3 +6922,55 @@ void test_vloxseg8ei64_v_f32mf2_m (vfloat32mf2_t *v0, vfloat32mf2_t *v1, vfloat32mf2_t *v2, vfloat32mf2_t *v3, vfloat32mf2_t *v4, vfloat32mf2_t *v5, vfloat32mf2_t *v6, vfloat32mf2_t *v7, vbool64_t mask, vfloat32mf2_t maskedoff0, vfloat32mf2_t maskedoff1, vfloat32mf2_t maskedoff2, vfloat32mf2_t maskedoff3, vfloat32mf2_t maskedoff4, vfloat32mf2_t maskedoff5, vfloat32mf2_t maskedoff6, vfloat32mf2_t maskedoff7, const float *base, vuint64m1_t bindex, size_t vl) { return vloxseg8ei64(v0, v1, v2, v3, v4, v5, v6, v7, mask, maskedoff0, maskedoff1, maskedoff2, maskedoff3, maskedoff4, maskedoff5, maskedoff6, maskedoff7, base, bindex, vl); } + +// CHECK-RV64-LABEL: @test_vloxseg2ei32_v_i32mf2_tuma( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vloxseg2.mask.nxv1i32.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], [[BINDEX:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 2) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vloxseg2ei32_v_i32mf2_tuma(vint32mf2_t *v0, vint32mf2_t *v1, vbool64_t mask, vint32mf2_t merge0, vint32mf2_t merge1, const int32_t *base, vuint32mf2_t bindex, size_t vl) { + return vloxseg2ei32_tuma(v0, v1, mask, merge0, merge1, base, bindex, vl); +} + +// CHECK-RV64-LABEL: @test_vloxseg2ei32_v_i32mf2_tumu( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vloxseg2.mask.nxv1i32.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], [[BINDEX:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 0) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vloxseg2ei32_v_i32mf2_tumu(vint32mf2_t *v0, vint32mf2_t *v1, vbool64_t mask, vint32mf2_t merge0, vint32mf2_t merge1, const int32_t *base, vuint32mf2_t bindex, size_t vl) { + return vloxseg2ei32_tumu(v0, v1, mask, merge0, merge1, base, bindex, vl); +} + +// CHECK-RV64-LABEL: @test_vloxseg2ei32_v_i32mf2_tama( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vloxseg2.mask.nxv1i32.nxv1i32.i64( undef, undef, i32* [[BASE:%.*]], [[BINDEX:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 3) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vloxseg2ei32_v_i32mf2_tama(vint32mf2_t *v0, vint32mf2_t *v1, vbool64_t mask, const int32_t *base, vuint32mf2_t bindex, size_t vl) { + return vloxseg2ei32_tama(v0, v1, mask, base, bindex, vl); +} + +// CHECK-RV64-LABEL: @test_vloxseg2ei32_v_i32mf2_tamu( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vloxseg2.mask.nxv1i32.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], [[BINDEX:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 1) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vloxseg2ei32_v_i32mf2_tamu(vint32mf2_t *v0, vint32mf2_t *v1, vbool64_t mask, vint32mf2_t merge0, vint32mf2_t merge1, const int32_t *base, vuint32mf2_t bindex, size_t vl) { + return vloxseg2ei32_tamu(v0, v1, mask, merge0, merge1, base, bindex, vl); +} diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vloxseg_mf.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vloxseg_mf.c --- a/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vloxseg_mf.c +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vloxseg_mf.c @@ -6922,3 +6922,29 @@ void test_vloxseg8ei64_v_f32mf2 (vfloat32mf2_t *v0, vfloat32mf2_t *v1, vfloat32mf2_t *v2, vfloat32mf2_t *v3, vfloat32mf2_t *v4, vfloat32mf2_t *v5, vfloat32mf2_t *v6, vfloat32mf2_t *v7, const float *base, vuint64m1_t bindex, size_t vl) { return vloxseg8ei64(v0, v1, v2, v3, v4, v5, v6, v7, base, bindex, vl); } + +// CHECK-RV64-LABEL: @test_vloxseg2ei32_v_i32mf2_tu( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vloxseg2.nxv1i32.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], [[BINDEX:%.*]], i64 [[VL:%.*]]) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vloxseg2ei32_v_i32mf2_tu(vint32mf2_t *v0, vint32mf2_t *v1, vint32mf2_t merge0, vint32mf2_t merge1, const int32_t *base, vuint32mf2_t bindex, size_t vl) { + return vloxseg2ei32_tu(v0, v1, merge0, merge1, base, bindex, vl); +} + +// CHECK-RV64-LABEL: @test_vloxseg2ei32_v_i32mf2_ta( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vloxseg2.nxv1i32.nxv1i32.i64( undef, undef, i32* [[BASE:%.*]], [[BINDEX:%.*]], i64 [[VL:%.*]]) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vloxseg2ei32_v_i32mf2_ta(vint32mf2_t *v0, vint32mf2_t *v1, const int32_t *base, vuint32mf2_t bindex, size_t vl) { + return vloxseg2ei32_ta(v0, v1, base, bindex, vl); +} diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vlsegff.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vlsegff.c --- a/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vlsegff.c +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vlsegff.c @@ -7290,3 +7290,159 @@ void test_vlseg2e64ff_v_f64m4_m (vfloat64m4_t *v0, vfloat64m4_t *v1, vbool16_t mask, vfloat64m4_t maskedoff0, vfloat64m4_t maskedoff1, const double *base, size_t *new_vl, size_t vl) { return vlseg2e64ff(v0, v1, mask, maskedoff0, maskedoff1, base, new_vl, vl); } + +// CHECK-RV32-LABEL: @test_vlseg2e32ff_v_u32mf2_tu( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call { , , i32 } @llvm.riscv.vlseg2ff.nxv1i32.i32( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], i32 [[VL:%.*]]) +// CHECK-RV32-NEXT: [[TMP1:%.*]] = extractvalue { , , i32 } [[TMP0]], 0 +// CHECK-RV32-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV32-NEXT: [[TMP2:%.*]] = extractvalue { , , i32 } [[TMP0]], 1 +// CHECK-RV32-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV32-NEXT: [[TMP3:%.*]] = extractvalue { , , i32 } [[TMP0]], 2 +// CHECK-RV32-NEXT: store i32 [[TMP3]], i32* [[NEW_VL:%.*]], align 4 +// CHECK-RV32-NEXT: ret void +// +// CHECK-RV64-LABEL: @test_vlseg2e32ff_v_u32mf2_tu( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , , i64 } @llvm.riscv.vlseg2ff.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], i64 [[VL:%.*]]) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , , i64 } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , , i64 } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP3:%.*]] = extractvalue { , , i64 } [[TMP0]], 2 +// CHECK-RV64-NEXT: store i64 [[TMP3]], i64* [[NEW_VL:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vlseg2e32ff_v_u32mf2_tu(vuint32mf2_t *v0, vuint32mf2_t *v1, vuint32mf2_t merge0, vuint32mf2_t merge1, const uint32_t *base, size_t *new_vl, size_t vl) { + return vlseg2e32ff_tu(v0, v1, merge0, merge1, base, new_vl, vl); +} + +// CHECK-RV32-LABEL: @test_vlseg2e32ff_v_u32mf2_ta( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call { , , i32 } @llvm.riscv.vlseg2ff.nxv1i32.i32( undef, undef, i32* [[BASE:%.*]], i32 [[VL:%.*]]) +// CHECK-RV32-NEXT: [[TMP1:%.*]] = extractvalue { , , i32 } [[TMP0]], 0 +// CHECK-RV32-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV32-NEXT: [[TMP2:%.*]] = extractvalue { , , i32 } [[TMP0]], 1 +// CHECK-RV32-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV32-NEXT: [[TMP3:%.*]] = extractvalue { , , i32 } [[TMP0]], 2 +// CHECK-RV32-NEXT: store i32 [[TMP3]], i32* [[NEW_VL:%.*]], align 4 +// CHECK-RV32-NEXT: ret void +// +// CHECK-RV64-LABEL: @test_vlseg2e32ff_v_u32mf2_ta( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , , i64 } @llvm.riscv.vlseg2ff.nxv1i32.i64( undef, undef, i32* [[BASE:%.*]], i64 [[VL:%.*]]) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , , i64 } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , , i64 } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP3:%.*]] = extractvalue { , , i64 } [[TMP0]], 2 +// CHECK-RV64-NEXT: store i64 [[TMP3]], i64* [[NEW_VL:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vlseg2e32ff_v_u32mf2_ta(vuint32mf2_t *v0, vuint32mf2_t *v1, const uint32_t *base, size_t *new_vl, size_t vl) { + return vlseg2e32ff_ta(v0, v1, base, new_vl, vl); +} + +// CHECK-RV32-LABEL: @test_vlseg2e32ff_v_u32mf2_tuma( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call { , , i32 } @llvm.riscv.vlseg2ff.mask.nxv1i32.i32( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], [[MASK:%.*]], i32 [[VL:%.*]], i32 2) +// CHECK-RV32-NEXT: [[TMP1:%.*]] = extractvalue { , , i32 } [[TMP0]], 0 +// CHECK-RV32-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV32-NEXT: [[TMP2:%.*]] = extractvalue { , , i32 } [[TMP0]], 1 +// CHECK-RV32-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV32-NEXT: [[TMP3:%.*]] = extractvalue { , , i32 } [[TMP0]], 2 +// CHECK-RV32-NEXT: store i32 [[TMP3]], i32* [[NEW_VL:%.*]], align 4 +// CHECK-RV32-NEXT: ret void +// +// CHECK-RV64-LABEL: @test_vlseg2e32ff_v_u32mf2_tuma( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , , i64 } @llvm.riscv.vlseg2ff.mask.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 2) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , , i64 } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , , i64 } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP3:%.*]] = extractvalue { , , i64 } [[TMP0]], 2 +// CHECK-RV64-NEXT: store i64 [[TMP3]], i64* [[NEW_VL:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vlseg2e32ff_v_u32mf2_tuma(vuint32mf2_t *v0, vuint32mf2_t *v1, vbool64_t mask, vuint32mf2_t merge0, vuint32mf2_t merge1, const uint32_t *base, size_t *new_vl, size_t vl) { + return vlseg2e32ff_tuma(v0, v1, mask, merge0, merge1, base, new_vl, vl); +} + +// CHECK-RV32-LABEL: @test_vlseg2e32ff_v_u32mf2_tumu( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call { , , i32 } @llvm.riscv.vlseg2ff.mask.nxv1i32.i32( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], [[MASK:%.*]], i32 [[VL:%.*]], i32 0) +// CHECK-RV32-NEXT: [[TMP1:%.*]] = extractvalue { , , i32 } [[TMP0]], 0 +// CHECK-RV32-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV32-NEXT: [[TMP2:%.*]] = extractvalue { , , i32 } [[TMP0]], 1 +// CHECK-RV32-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV32-NEXT: [[TMP3:%.*]] = extractvalue { , , i32 } [[TMP0]], 2 +// CHECK-RV32-NEXT: store i32 [[TMP3]], i32* [[NEW_VL:%.*]], align 4 +// CHECK-RV32-NEXT: ret void +// +// CHECK-RV64-LABEL: @test_vlseg2e32ff_v_u32mf2_tumu( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , , i64 } @llvm.riscv.vlseg2ff.mask.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 0) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , , i64 } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , , i64 } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP3:%.*]] = extractvalue { , , i64 } [[TMP0]], 2 +// CHECK-RV64-NEXT: store i64 [[TMP3]], i64* [[NEW_VL:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vlseg2e32ff_v_u32mf2_tumu(vuint32mf2_t *v0, vuint32mf2_t *v1, vbool64_t mask, vuint32mf2_t merge0, vuint32mf2_t merge1, const uint32_t *base, size_t *new_vl, size_t vl) { + return vlseg2e32ff_tumu(v0, v1, mask, merge0, merge1, base, new_vl, vl); +} + +// CHECK-RV32-LABEL: @test_vlseg2e32ff_v_u32mf2_tama( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call { , , i32 } @llvm.riscv.vlseg2ff.mask.nxv1i32.i32( undef, undef, i32* [[BASE:%.*]], [[MASK:%.*]], i32 [[VL:%.*]], i32 3) +// CHECK-RV32-NEXT: [[TMP1:%.*]] = extractvalue { , , i32 } [[TMP0]], 0 +// CHECK-RV32-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV32-NEXT: [[TMP2:%.*]] = extractvalue { , , i32 } [[TMP0]], 1 +// CHECK-RV32-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV32-NEXT: [[TMP3:%.*]] = extractvalue { , , i32 } [[TMP0]], 2 +// CHECK-RV32-NEXT: store i32 [[TMP3]], i32* [[NEW_VL:%.*]], align 4 +// CHECK-RV32-NEXT: ret void +// +// CHECK-RV64-LABEL: @test_vlseg2e32ff_v_u32mf2_tama( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , , i64 } @llvm.riscv.vlseg2ff.mask.nxv1i32.i64( undef, undef, i32* [[BASE:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 3) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , , i64 } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , , i64 } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP3:%.*]] = extractvalue { , , i64 } [[TMP0]], 2 +// CHECK-RV64-NEXT: store i64 [[TMP3]], i64* [[NEW_VL:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vlseg2e32ff_v_u32mf2_tama(vuint32mf2_t *v0, vuint32mf2_t *v1, vbool64_t mask, const uint32_t *base, size_t *new_vl, size_t vl) { + return vlseg2e32ff_tama(v0, v1, mask, base, new_vl, vl); +} + +// CHECK-RV32-LABEL: @test_vlseg2e32ff_v_u32mf2_tamu( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call { , , i32 } @llvm.riscv.vlseg2ff.mask.nxv1i32.i32( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], [[MASK:%.*]], i32 [[VL:%.*]], i32 1) +// CHECK-RV32-NEXT: [[TMP1:%.*]] = extractvalue { , , i32 } [[TMP0]], 0 +// CHECK-RV32-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV32-NEXT: [[TMP2:%.*]] = extractvalue { , , i32 } [[TMP0]], 1 +// CHECK-RV32-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV32-NEXT: [[TMP3:%.*]] = extractvalue { , , i32 } [[TMP0]], 2 +// CHECK-RV32-NEXT: store i32 [[TMP3]], i32* [[NEW_VL:%.*]], align 4 +// CHECK-RV32-NEXT: ret void +// +// CHECK-RV64-LABEL: @test_vlseg2e32ff_v_u32mf2_tamu( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , , i64 } @llvm.riscv.vlseg2ff.mask.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 1) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , , i64 } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , , i64 } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP3:%.*]] = extractvalue { , , i64 } [[TMP0]], 2 +// CHECK-RV64-NEXT: store i64 [[TMP3]], i64* [[NEW_VL:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vlseg2e32ff_v_u32mf2_tamu(vuint32mf2_t *v0, vuint32mf2_t *v1, vbool64_t mask, vuint32mf2_t merge0, vuint32mf2_t merge1, const uint32_t *base, size_t *new_vl, size_t vl) { + return vlseg2e32ff_tamu(v0, v1, mask, merge0, merge1, base, new_vl, vl); +} diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vlsseg.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vlsseg.c --- a/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vlsseg.c +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vlsseg.c @@ -3646,3 +3646,80 @@ return vlsseg2e64(v0, v1, mask, maskedoff0, maskedoff1, base, bstride, vl); } +// CHECK-RV64-LABEL: @test_vlsseg2e32_v_u32mf2_tu( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vlsseg2.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], i64 [[BSTRIDE:%.*]], i64 [[VL:%.*]]) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vlsseg2e32_v_u32mf2_tu(vuint32mf2_t *v0, vuint32mf2_t *v1, vuint32mf2_t merge0, vuint32mf2_t merge1, const uint32_t *base, ptrdiff_t bstride, size_t vl) { + return vlsseg2e32_tu(v0, v1, merge0, merge1, base, bstride, vl); +} + +// CHECK-RV64-LABEL: @test_vlsseg2e32_v_u32mf2_ta( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vlsseg2.nxv1i32.i64( undef, undef, i32* [[BASE:%.*]], i64 [[BSTRIDE:%.*]], i64 [[VL:%.*]]) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vlsseg2e32_v_u32mf2_ta(vuint32mf2_t *v0, vuint32mf2_t *v1, const uint32_t *base, ptrdiff_t bstride, size_t vl) { + return vlsseg2e32_ta(v0, v1, base, bstride, vl); +} + +// CHECK-RV64-LABEL: @test_vlsseg2e32_v_u32mf2_tuma( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vlsseg2.mask.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], i64 [[BSTRIDE:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 2) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vlsseg2e32_v_u32mf2_tuma(vuint32mf2_t *v0, vuint32mf2_t *v1, vbool64_t mask, vuint32mf2_t merge0, vuint32mf2_t merge1, const uint32_t *base, ptrdiff_t bstride, size_t vl) { + return vlsseg2e32_tuma(v0, v1, mask, merge0, merge1, base, bstride, vl); +} + +// CHECK-RV64-LABEL: @test_vlsseg2e32_v_u32mf2_tumu( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vlsseg2.mask.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], i64 [[BSTRIDE:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 0) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vlsseg2e32_v_u32mf2_tumu(vuint32mf2_t *v0, vuint32mf2_t *v1, vbool64_t mask, vuint32mf2_t merge0, vuint32mf2_t merge1, const uint32_t *base, ptrdiff_t bstride, size_t vl) { + return vlsseg2e32_tumu(v0, v1, mask, merge0, merge1, base, bstride, vl); +} + +// CHECK-RV64-LABEL: @test_vlsseg2e32_v_u32mf2_tama( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vlsseg2.mask.nxv1i32.i64( undef, undef, i32* [[BASE:%.*]], i64 [[BSTRIDE:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 3) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vlsseg2e32_v_u32mf2_tama(vuint32mf2_t *v0, vuint32mf2_t *v1, vbool64_t mask, const uint32_t *base, ptrdiff_t bstride, size_t vl) { + return vlsseg2e32_tama(v0, v1, mask, base, bstride, vl); +} + +// CHECK-RV64-LABEL: @test_vlsseg2e32_v_u32mf2_tamu( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vlsseg2.mask.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], i64 [[BSTRIDE:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 1) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vlsseg2e32_v_u32mf2_tamu(vuint32mf2_t *v0, vuint32mf2_t *v1, vbool64_t mask, vuint32mf2_t merge0, vuint32mf2_t merge1, const uint32_t *base, ptrdiff_t bstride, size_t vl) { + return vlsseg2e32_tamu(v0, v1, mask, merge0, merge1, base, bstride, vl); +} diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vluxseg_mask_mf.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vluxseg_mask_mf.c --- a/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vluxseg_mask_mf.c +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vluxseg_mask_mf.c @@ -6922,3 +6922,55 @@ void test_vluxseg8ei64_v_f32mf2_m (vfloat32mf2_t *v0, vfloat32mf2_t *v1, vfloat32mf2_t *v2, vfloat32mf2_t *v3, vfloat32mf2_t *v4, vfloat32mf2_t *v5, vfloat32mf2_t *v6, vfloat32mf2_t *v7, vbool64_t mask, vfloat32mf2_t maskedoff0, vfloat32mf2_t maskedoff1, vfloat32mf2_t maskedoff2, vfloat32mf2_t maskedoff3, vfloat32mf2_t maskedoff4, vfloat32mf2_t maskedoff5, vfloat32mf2_t maskedoff6, vfloat32mf2_t maskedoff7, const float *base, vuint64m1_t bindex, size_t vl) { return vluxseg8ei64(v0, v1, v2, v3, v4, v5, v6, v7, mask, maskedoff0, maskedoff1, maskedoff2, maskedoff3, maskedoff4, maskedoff5, maskedoff6, maskedoff7, base, bindex, vl); } + +// CHECK-RV64-LABEL: @test_vluxseg2ei32_v_i32mf2_tuma( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vluxseg2.mask.nxv1i32.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], [[BINDEX:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 2) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vluxseg2ei32_v_i32mf2_tuma(vint32mf2_t *v0, vint32mf2_t *v1, vbool64_t mask, vint32mf2_t merge0, vint32mf2_t merge1, const int32_t *base, vuint32mf2_t bindex, size_t vl) { + return vluxseg2ei32_tuma(v0, v1, mask, merge0, merge1, base, bindex, vl); +} + +// CHECK-RV64-LABEL: @test_vluxseg2ei32_v_i32mf2_tumu( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vluxseg2.mask.nxv1i32.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], [[BINDEX:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 0) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vluxseg2ei32_v_i32mf2_tumu(vint32mf2_t *v0, vint32mf2_t *v1, vbool64_t mask, vint32mf2_t merge0, vint32mf2_t merge1, const int32_t *base, vuint32mf2_t bindex, size_t vl) { + return vluxseg2ei32_tumu(v0, v1, mask, merge0, merge1, base, bindex, vl); +} + +// CHECK-RV64-LABEL: @test_vluxseg2ei32_v_i32mf2_tama( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vluxseg2.mask.nxv1i32.nxv1i32.i64( undef, undef, i32* [[BASE:%.*]], [[BINDEX:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 3) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vluxseg2ei32_v_i32mf2_tama(vint32mf2_t *v0, vint32mf2_t *v1, vbool64_t mask, const int32_t *base, vuint32mf2_t bindex, size_t vl) { + return vluxseg2ei32_tama(v0, v1, mask, base, bindex, vl); +} + +// CHECK-RV64-LABEL: @test_vluxseg2ei32_v_i32mf2_tamu( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vluxseg2.mask.nxv1i32.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], [[BINDEX:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 1) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vluxseg2ei32_v_i32mf2_tamu(vint32mf2_t *v0, vint32mf2_t *v1, vbool64_t mask, vint32mf2_t merge0, vint32mf2_t merge1, const int32_t *base, vuint32mf2_t bindex, size_t vl) { + return vluxseg2ei32_tamu(v0, v1, mask, merge0, merge1, base, bindex, vl); +} diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vluxseg_mf.c b/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vluxseg_mf.c --- a/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vluxseg_mf.c +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vluxseg_mf.c @@ -6922,3 +6922,29 @@ void test_vluxseg8ei64_v_f32mf2 (vfloat32mf2_t *v0, vfloat32mf2_t *v1, vfloat32mf2_t *v2, vfloat32mf2_t *v3, vfloat32mf2_t *v4, vfloat32mf2_t *v5, vfloat32mf2_t *v6, vfloat32mf2_t *v7, const float *base, vuint64m1_t bindex, size_t vl) { return vluxseg8ei64(v0, v1, v2, v3, v4, v5, v6, v7, base, bindex, vl); } + +// CHECK-RV64-LABEL: @test_vluxseg2ei32_tu( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vluxseg2.nxv1i32.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], [[BINDEX:%.*]], i64 [[VL:%.*]]) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vluxseg2ei32_tu(vint32mf2_t *v0, vint32mf2_t *v1, vint32mf2_t merge0, vint32mf2_t merge1, const int32_t *base, vuint32mf2_t bindex, size_t vl) { + return vluxseg2ei32_tu(v0, v1, merge0, merge1, base, bindex, vl); +} + +// CHECK-RV64-LABEL: @test_vluxseg2ei32_v_i32mf2_ta( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vluxseg2.nxv1i32.nxv1i32.i64( undef, undef, i32* [[BASE:%.*]], [[BINDEX:%.*]], i64 [[VL:%.*]]) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vluxseg2ei32_v_i32mf2_ta(vint32mf2_t *v0, vint32mf2_t *v1, const int32_t *base, vuint32mf2_t bindex, size_t vl) { + return vluxseg2ei32_ta(v0, v1, base, bindex, vl); +} diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics/vloxseg_mask_mf.c b/clang/test/CodeGen/RISCV/rvv-intrinsics/vloxseg_mask_mf.c --- a/clang/test/CodeGen/RISCV/rvv-intrinsics/vloxseg_mask_mf.c +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics/vloxseg_mask_mf.c @@ -9051,3 +9051,54 @@ return vloxseg8ei64_v_f16mf2_m(v0, v1, v2, v3, v4, v5, v6, v7, mask, maskedoff0, maskedoff1, maskedoff2, maskedoff3, maskedoff4, maskedoff5, maskedoff6, maskedoff7, base, bindex, vl); } +// CHECK-RV64-LABEL: @test_vloxseg2ei32_v_i32mf2_tuma( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vloxseg2.mask.nxv1i32.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], [[BINDEX:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 2) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vloxseg2ei32_v_i32mf2_tuma(vint32mf2_t *v0, vint32mf2_t *v1, vbool64_t mask, vint32mf2_t merge0, vint32mf2_t merge1, const int32_t *base, vuint32mf2_t bindex, size_t vl) { + return vloxseg2ei32_v_i32mf2_tuma(v0, v1, mask, merge0, merge1, base, bindex, vl); +} + +// CHECK-RV64-LABEL: @test_vloxseg2ei32_v_i32mf2_tumu( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vloxseg2.mask.nxv1i32.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], [[BINDEX:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 0) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vloxseg2ei32_v_i32mf2_tumu(vint32mf2_t *v0, vint32mf2_t *v1, vbool64_t mask, vint32mf2_t merge0, vint32mf2_t merge1, const int32_t *base, vuint32mf2_t bindex, size_t vl) { + return vloxseg2ei32_v_i32mf2_tumu(v0, v1, mask, merge0, merge1, base, bindex, vl); +} + +// CHECK-RV64-LABEL: @test_vloxseg2ei32_v_i32mf2_tama( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vloxseg2.mask.nxv1i32.nxv1i32.i64( undef, undef, i32* [[BASE:%.*]], [[BINDEX:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 3) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vloxseg2ei32_v_i32mf2_tama(vint32mf2_t *v0, vint32mf2_t *v1, vbool64_t mask, const int32_t *base, vuint32mf2_t bindex, size_t vl) { + return vloxseg2ei32_v_i32mf2_tama(v0, v1, mask, base, bindex, vl); +} + +// CHECK-RV64-LABEL: @test_vloxseg2ei32_v_i32mf2_tamu( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vloxseg2.mask.nxv1i32.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], [[BINDEX:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 1) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vloxseg2ei32_v_i32mf2_tamu(vint32mf2_t *v0, vint32mf2_t *v1, vbool64_t mask, vint32mf2_t merge0, vint32mf2_t merge1, const int32_t *base, vuint32mf2_t bindex, size_t vl) { + return vloxseg2ei32_v_i32mf2_tamu(v0, v1, mask, merge0, merge1, base, bindex, vl); +} diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics/vloxseg_mf.c b/clang/test/CodeGen/RISCV/rvv-intrinsics/vloxseg_mf.c --- a/clang/test/CodeGen/RISCV/rvv-intrinsics/vloxseg_mf.c +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics/vloxseg_mf.c @@ -6922,3 +6922,29 @@ void test_vloxseg8ei64_v_f32mf2 (vfloat32mf2_t *v0, vfloat32mf2_t *v1, vfloat32mf2_t *v2, vfloat32mf2_t *v3, vfloat32mf2_t *v4, vfloat32mf2_t *v5, vfloat32mf2_t *v6, vfloat32mf2_t *v7, const float *base, vuint64m1_t bindex, size_t vl) { return vloxseg8ei64_v_f32mf2(v0, v1, v2, v3, v4, v5, v6, v7, base, bindex, vl); } + +// CHECK-RV64-LABEL: @test_vloxseg2ei32_v_i32mf2_tu( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vloxseg2.nxv1i32.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], [[BINDEX:%.*]], i64 [[VL:%.*]]) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vloxseg2ei32_v_i32mf2_tu(vint32mf2_t *v0, vint32mf2_t *v1, vint32mf2_t merge0, vint32mf2_t merge1, const int32_t *base, vuint32mf2_t bindex, size_t vl) { + return vloxseg2ei32_v_i32mf2_tu(v0, v1, merge0, merge1, base, bindex, vl); +} + +// CHECK-RV64-LABEL: @test_vloxseg2ei32_v_i32mf2_ta( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vloxseg2.nxv1i32.nxv1i32.i64( undef, undef, i32* [[BASE:%.*]], [[BINDEX:%.*]], i64 [[VL:%.*]]) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vloxseg2ei32_v_i32mf2_ta(vint32mf2_t *v0, vint32mf2_t *v1, const int32_t *base, vuint32mf2_t bindex, size_t vl) { + return vloxseg2ei32_v_i32mf2_ta(v0, v1, base, bindex, vl); +} diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics/vlsegff.c b/clang/test/CodeGen/RISCV/rvv-intrinsics/vlsegff.c --- a/clang/test/CodeGen/RISCV/rvv-intrinsics/vlsegff.c +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics/vlsegff.c @@ -8204,3 +8204,55 @@ void test_vlseg2e16ff_v_f16m4 (vfloat16m4_t *v0, vfloat16m4_t *v1, const _Float16 *base, size_t *new_vl, size_t vl) { return vlseg2e16ff_v_f16m4(v0, v1, base, new_vl, vl); } + +// CHECK-RV32-LABEL: @test_vlseg2e32ff_v_u32mf2_tu( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call { , , i32 } @llvm.riscv.vlseg2ff.nxv1i32.i32( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], i32 [[VL:%.*]]) +// CHECK-RV32-NEXT: [[TMP1:%.*]] = extractvalue { , , i32 } [[TMP0]], 0 +// CHECK-RV32-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV32-NEXT: [[TMP2:%.*]] = extractvalue { , , i32 } [[TMP0]], 1 +// CHECK-RV32-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV32-NEXT: [[TMP3:%.*]] = extractvalue { , , i32 } [[TMP0]], 2 +// CHECK-RV32-NEXT: store i32 [[TMP3]], i32* [[NEW_VL:%.*]], align 4 +// CHECK-RV32-NEXT: ret void +// +// CHECK-RV64-LABEL: @test_vlseg2e32ff_v_u32mf2_tu( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , , i64 } @llvm.riscv.vlseg2ff.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], i64 [[VL:%.*]]) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , , i64 } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , , i64 } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP3:%.*]] = extractvalue { , , i64 } [[TMP0]], 2 +// CHECK-RV64-NEXT: store i64 [[TMP3]], i64* [[NEW_VL:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vlseg2e32ff_v_u32mf2_tu(vuint32mf2_t *v0, vuint32mf2_t *v1, vuint32mf2_t merge0, vuint32mf2_t merge1, const uint32_t *base, size_t *new_vl, size_t vl) { + return vlseg2e32ff_v_u32mf2_tu(v0, v1, merge0, merge1, base, new_vl, vl); +} + +// CHECK-RV32-LABEL: @test_vlseg2e32ff_v_u32mf2_ta( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call { , , i32 } @llvm.riscv.vlseg2ff.nxv1i32.i32( undef, undef, i32* [[BASE:%.*]], i32 [[VL:%.*]]) +// CHECK-RV32-NEXT: [[TMP1:%.*]] = extractvalue { , , i32 } [[TMP0]], 0 +// CHECK-RV32-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV32-NEXT: [[TMP2:%.*]] = extractvalue { , , i32 } [[TMP0]], 1 +// CHECK-RV32-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV32-NEXT: [[TMP3:%.*]] = extractvalue { , , i32 } [[TMP0]], 2 +// CHECK-RV32-NEXT: store i32 [[TMP3]], i32* [[NEW_VL:%.*]], align 4 +// CHECK-RV32-NEXT: ret void +// +// CHECK-RV64-LABEL: @test_vlseg2e32ff_v_u32mf2_ta( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , , i64 } @llvm.riscv.vlseg2ff.nxv1i32.i64( undef, undef, i32* [[BASE:%.*]], i64 [[VL:%.*]]) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , , i64 } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , , i64 } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP3:%.*]] = extractvalue { , , i64 } [[TMP0]], 2 +// CHECK-RV64-NEXT: store i64 [[TMP3]], i64* [[NEW_VL:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vlseg2e32ff_v_u32mf2_ta(vuint32mf2_t *v0, vuint32mf2_t *v1, const uint32_t *base, size_t *new_vl, size_t vl) { + return vlseg2e32ff_v_u32mf2_ta(v0, v1, base, new_vl, vl); +} diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics/vlsseg.c b/clang/test/CodeGen/RISCV/rvv-intrinsics/vlsseg.c --- a/clang/test/CodeGen/RISCV/rvv-intrinsics/vlsseg.c +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics/vlsseg.c @@ -8198,3 +8198,81 @@ void test_vlsseg2e16_v_f16m4_m (vfloat16m4_t *v0, vfloat16m4_t *v1, vbool4_t mask, vfloat16m4_t maskedoff0, vfloat16m4_t maskedoff1, const _Float16 *base, ptrdiff_t bstride, size_t vl) { return vlsseg2e16_v_f16m4_m(v0, v1, mask, maskedoff0, maskedoff1, base, bstride, vl); } + +// CHECK-RV64-LABEL: @test_vlsseg2e32_v_u32mf2_tu( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vlsseg2.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], i64 [[BSTRIDE:%.*]], i64 [[VL:%.*]]) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vlsseg2e32_v_u32mf2_tu(vuint32mf2_t *v0, vuint32mf2_t *v1, vuint32mf2_t merge0, vuint32mf2_t merge1, const uint32_t *base, ptrdiff_t bstride, size_t vl) { + return vlsseg2e32_v_u32mf2_tu(v0, v1, merge0, merge1, base, bstride, vl); +} + +// CHECK-RV64-LABEL: @test_vlsseg2e32_v_u32mf2_ta( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vlsseg2.nxv1i32.i64( undef, undef, i32* [[BASE:%.*]], i64 [[BSTRIDE:%.*]], i64 [[VL:%.*]]) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vlsseg2e32_v_u32mf2_ta(vuint32mf2_t *v0, vuint32mf2_t *v1, const uint32_t *base, ptrdiff_t bstride, size_t vl) { + return vlsseg2e32_v_u32mf2_ta(v0, v1, base, bstride, vl); +} + +// CHECK-RV64-LABEL: @test_vlsseg2e32_v_u32mf2_tuma( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vlsseg2.mask.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], i64 [[BSTRIDE:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 2) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vlsseg2e32_v_u32mf2_tuma(vuint32mf2_t *v0, vuint32mf2_t *v1, vbool64_t mask, vuint32mf2_t merge0, vuint32mf2_t merge1, const uint32_t *base, ptrdiff_t bstride, size_t vl) { + return vlsseg2e32_v_u32mf2_tuma(v0, v1, mask, merge0, merge1, base, bstride, vl); +} + +// CHECK-RV64-LABEL: @test_vlsseg2e32_v_u32mf2_tumu( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vlsseg2.mask.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], i64 [[BSTRIDE:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 0) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vlsseg2e32_v_u32mf2_tumu(vuint32mf2_t *v0, vuint32mf2_t *v1, vbool64_t mask, vuint32mf2_t merge0, vuint32mf2_t merge1, const uint32_t *base, ptrdiff_t bstride, size_t vl) { + return vlsseg2e32_v_u32mf2_tumu(v0, v1, mask, merge0, merge1, base, bstride, vl); +} + +// CHECK-RV64-LABEL: @test_vlsseg2e32_v_u32mf2_tama( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vlsseg2.mask.nxv1i32.i64( undef, undef, i32* [[BASE:%.*]], i64 [[BSTRIDE:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 3) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vlsseg2e32_v_u32mf2_tama(vuint32mf2_t *v0, vuint32mf2_t *v1, vbool64_t mask, const uint32_t *base, ptrdiff_t bstride, size_t vl) { + return vlsseg2e32_v_u32mf2_tama(v0, v1, mask, base, bstride, vl); +} + +// CHECK-RV64-LABEL: @test_vlsseg2e32_v_u32mf2_tamu( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vlsseg2.mask.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], i64 [[BSTRIDE:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 1) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vlsseg2e32_v_u32mf2_tamu(vuint32mf2_t *v0, vuint32mf2_t *v1, vbool64_t mask, vuint32mf2_t merge0, vuint32mf2_t merge1, const uint32_t *base, ptrdiff_t bstride, size_t vl) { + return vlsseg2e32_v_u32mf2_tamu(v0, v1, mask, merge0, merge1, base, bstride, vl); +} diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics/vluxseg_mask_mf.c b/clang/test/CodeGen/RISCV/rvv-intrinsics/vluxseg_mask_mf.c --- a/clang/test/CodeGen/RISCV/rvv-intrinsics/vluxseg_mask_mf.c +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics/vluxseg_mask_mf.c @@ -9051,3 +9051,54 @@ return vluxseg2ei8_v_i8mf8_m(v0, v1, mask, maskedoff0, maskedoff1, base, bindex, vl); } +// CHECK-RV64-LABEL: @test_vluxseg2ei32_v_i32mf2_tuma( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vluxseg2.mask.nxv1i32.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], [[BINDEX:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 2) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vluxseg2ei32_v_i32mf2_tuma(vint32mf2_t *v0, vint32mf2_t *v1, vbool64_t mask, vint32mf2_t merge0, vint32mf2_t merge1, const int32_t *base, vuint32mf2_t bindex, size_t vl) { + return vluxseg2ei32_v_i32mf2_tuma(v0, v1, mask, merge0, merge1, base, bindex, vl); +} + +// CHECK-RV64-LABEL: @test_vluxseg2ei32_v_i32mf2_tumu( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vluxseg2.mask.nxv1i32.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], [[BINDEX:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 0) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vluxseg2ei32_v_i32mf2_tumu(vint32mf2_t *v0, vint32mf2_t *v1, vbool64_t mask, vint32mf2_t merge0, vint32mf2_t merge1, const int32_t *base, vuint32mf2_t bindex, size_t vl) { + return vluxseg2ei32_v_i32mf2_tumu(v0, v1, mask, merge0, merge1, base, bindex, vl); +} + +// CHECK-RV64-LABEL: @test_vluxseg2ei32_v_i32mf2_tama( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vluxseg2.mask.nxv1i32.nxv1i32.i64( undef, undef, i32* [[BASE:%.*]], [[BINDEX:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 3) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vluxseg2ei32_v_i32mf2_tama(vint32mf2_t *v0, vint32mf2_t *v1, vbool64_t mask, const int32_t *base, vuint32mf2_t bindex, size_t vl) { + return vluxseg2ei32_v_i32mf2_tama(v0, v1, mask, base, bindex, vl); +} + +// CHECK-RV64-LABEL: @test_vluxseg2ei32_v_i32mf2_tamu( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vluxseg2.mask.nxv1i32.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], [[BINDEX:%.*]], [[MASK:%.*]], i64 [[VL:%.*]], i64 1) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vluxseg2ei32_v_i32mf2_tamu(vint32mf2_t *v0, vint32mf2_t *v1, vbool64_t mask, vint32mf2_t merge0, vint32mf2_t merge1, const int32_t *base, vuint32mf2_t bindex, size_t vl) { + return vluxseg2ei32_v_i32mf2_tamu(v0, v1, mask, merge0, merge1, base, bindex, vl); +} diff --git a/clang/test/CodeGen/RISCV/rvv-intrinsics/vluxseg_mf.c b/clang/test/CodeGen/RISCV/rvv-intrinsics/vluxseg_mf.c --- a/clang/test/CodeGen/RISCV/rvv-intrinsics/vluxseg_mf.c +++ b/clang/test/CodeGen/RISCV/rvv-intrinsics/vluxseg_mf.c @@ -6923,3 +6923,28 @@ return vluxseg8ei64_v_f32mf2(v0, v1, v2, v3, v4, v5, v6, v7, base, bindex, vl); } +// CHECK-RV64-LABEL: @test_vluxseg2ei32_v_i32mf2_tu( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vluxseg2.nxv1i32.nxv1i32.i64( [[MERGE0:%.*]], [[MERGE1:%.*]], i32* [[BASE:%.*]], [[BINDEX:%.*]], i64 [[VL:%.*]]) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vluxseg2ei32_v_i32mf2_tu(vint32mf2_t *v0, vint32mf2_t *v1, vint32mf2_t merge0, vint32mf2_t merge1, const int32_t *base, vuint32mf2_t bindex, size_t vl) { + return vluxseg2ei32_v_i32mf2_tu(v0, v1, merge0, merge1, base, bindex, vl); +} + +// CHECK-RV64-LABEL: @test_vluxseg2ei32_v_i32mf2_ta( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call { , } @llvm.riscv.vluxseg2.nxv1i32.nxv1i32.i64( undef, undef, i32* [[BASE:%.*]], [[BINDEX:%.*]], i64 [[VL:%.*]]) +// CHECK-RV64-NEXT: [[TMP1:%.*]] = extractvalue { , } [[TMP0]], 0 +// CHECK-RV64-NEXT: store [[TMP1]], * [[V0:%.*]], align 4 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = extractvalue { , } [[TMP0]], 1 +// CHECK-RV64-NEXT: store [[TMP2]], * [[V1:%.*]], align 4 +// CHECK-RV64-NEXT: ret void +// +void test_vluxseg2ei32_v_i32mf2_ta(vint32mf2_t *v0, vint32mf2_t *v1, const int32_t *base, vuint32mf2_t bindex, size_t vl) { + return vluxseg2ei32_v_i32mf2_ta(v0, v1, base, bindex, vl); +}