diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -86,6 +86,9 @@ Changes to TableGen ------------------- +* Named arguments are supported. Arguments can be specified in the form of + ``name=value``. + Changes to Interprocedural Optimizations ---------------------------------------- diff --git a/llvm/docs/TableGen/ProgRef.rst b/llvm/docs/TableGen/ProgRef.rst --- a/llvm/docs/TableGen/ProgRef.rst +++ b/llvm/docs/TableGen/ProgRef.rst @@ -475,7 +475,7 @@ def Foo#i; .. productionlist:: - SimpleValue8: `ClassID` "<" `ValueListNE` ">" + SimpleValue8: `ClassID` "<" `ArgValueList` ">" This form creates a new anonymous record definition (as would be created by an unnamed ``def`` inheriting from the given class with the given template @@ -642,12 +642,27 @@ RecordBody: `ParentClassList` `Body` ParentClassList: [":" `ParentClassListNE`] ParentClassListNE: `ClassRef` ("," `ClassRef`)* - ClassRef: (`ClassID` | `MultiClassID`) ["<" [`ValueList`] ">"] + ClassRef: (`ClassID` | `MultiClassID`) ["<" [`ArgValueList`] ">"] + ArgValueList: `PostionalArgValueList` [","] `NamedArgValueList` + PostionalArgValueList: [`Value` {"," `Value`}*] + NamedArgValueList: [`NameValue` "=" `Value` {"," `NameValue` "=" `Value`}*] A :token:`ParentClassList` containing a :token:`MultiClassID` is valid only in the class list of a ``defm`` statement. In that case, the ID must be the name of a multiclass. +The argument values can be specified in two forms: + +* Positional argument (``value``). The value is assigned to the argument in the + corresponding position. For ``Foo``, ``a0`` will be assigned to first + argument and ``a1`` will be assigned to second argument. +* Named argument (``name=value``). The value is assigned to argument with + specified name. For ``Foo``, ``a0`` will be assigned to argument + with name ``a`` and ``a1`` will be assigned to argument with name ``b``. + +Positional arguments should be put before named arguments. Required arguments +can alse be specified as named argument. + .. productionlist:: Body: ";" | "{" `BodyItem`* "}" BodyItem: (`Type` | "code") `TokIdentifier` ["=" `Value`] ";" diff --git a/llvm/lib/TableGen/TGParser.h b/llvm/lib/TableGen/TGParser.h --- a/llvm/lib/TableGen/TGParser.h +++ b/llvm/lib/TableGen/TGParser.h @@ -279,7 +279,8 @@ void ParseValueList(SmallVectorImpl &Result, Record *CurRec, RecTy *ItemType = nullptr); bool ParseTemplateArgValueList(SmallVectorImpl &Result, - Record *CurRec, Record *ArgsRec); + Record *CurRec, Record *ArgsRec, + bool IsDefm = false); void ParseDagArgList( SmallVectorImpl> &Result, Record *CurRec); diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp --- a/llvm/lib/TableGen/TGParser.cpp +++ b/llvm/lib/TableGen/TGParser.cpp @@ -117,11 +117,6 @@ Init *NewName = BinOpInit::getStrConcat(CurRec.getNameInit(), StringInit::get(RK, Scoper)); NewName = BinOpInit::getStrConcat(NewName, Name); - if (CurMultiClass && Scoper != "::") { - Init *Prefix = BinOpInit::getStrConcat(CurMultiClass->Rec.getNameInit(), - StringInit::get(RK, "::")); - NewName = BinOpInit::getStrConcat(Prefix, NewName); - } if (BinOpInit *BinOp = dyn_cast(NewName)) NewName = BinOp->Fold(&CurRec); @@ -714,7 +709,7 @@ /// multiclass. This returns a SubClassRefTy with a null Record* on error. /// /// SubClassRef ::= ClassID -/// SubClassRef ::= ClassID '<' ValueList '>' +/// SubClassRef ::= ClassID '<' ArgValueList '>' /// SubClassReference TGParser:: ParseSubClassReference(Record *CurRec, bool isDefm) { @@ -735,7 +730,8 @@ return Result; } - if (ParseTemplateArgValueList(Result.TemplateArgs, CurRec, Result.Rec)) { + if (ParseTemplateArgValueList(Result.TemplateArgs, CurRec, Result.Rec, + isDefm)) { Result.Rec = nullptr; // Error parsing value list. return Result; } @@ -755,7 +751,7 @@ /// Record* on error. /// /// SubMultiClassRef ::= MultiClassID -/// SubMultiClassRef ::= MultiClassID '<' ValueList '>' +/// SubMultiClassRef ::= MultiClassID '<' ArgValueList '>' /// SubMultiClassReference TGParser:: ParseSubMultiClassReference(MultiClass *CurMC) { @@ -772,7 +768,7 @@ } if (ParseTemplateArgValueList(Result.TemplateArgs, &CurMC->Rec, - &Result.MC->Rec)) { + &Result.MC->Rec, true)) { Result.MC = nullptr; // Error parsing value list. return Result; } @@ -2574,10 +2570,13 @@ case tgtok::Id: { SMRange NameLoc = Lex.getLocRange(); StringInit *Name = StringInit::get(Records, Lex.getCurStrVal()); - if (Lex.Lex() != tgtok::less) // consume the Id. - return ParseIDValue(CurRec, Name, NameLoc, Mode); // Value ::= IDValue + tgtok::TokKind Next = Lex.Lex(); + if (Next == tgtok::equal) // Named argument. + return Name; + if (Next != tgtok::less) // consume the Id. + return ParseIDValue(CurRec, Name, NameLoc, Mode); // Value ::= IDValue - // Value ::= CLASSID '<' ValueListNE '>' (CLASSID has been consumed) + // Value ::= CLASSID '<' ArgValueList '>' (CLASSID has been consumed) // This is supposed to synthesize a new anonymous definition, deriving // from the class with the template arguments, but no body. Record *Class = Records.getClass(Name->getValue()); @@ -3118,41 +3117,81 @@ // ParseTemplateArgValueList - Parse a template argument list with the syntax // shown, filling in the Result vector. The open angle has been consumed. -// An empty argument list is allowed. Return false if okay, true if an +// An empty argument list is allowed. Return false if okay, true if an // error was detected. -// -// TemplateArgList ::= '<' [Value {',' Value}*] '>' +// ArgValueList ::= '<' PostionalArgValueList [','] NamedArgValueList '>' +// PostionalArgValueList ::= [Value {',' Value}*] +// NamedArgValueList ::= [NameValue '=' Value {',' NameValue '=' Value}*] bool TGParser::ParseTemplateArgValueList(SmallVectorImpl &Result, - Record *CurRec, Record *ArgsRec) { - + Record *CurRec, Record *ArgsRec, + bool IsDefm) { assert(Result.empty() && "Result vector is not empty"); ArrayRef TArgs = ArgsRec->getTemplateArgs(); - unsigned ArgIndex = 0; - RecTy *ItemType; if (consume(tgtok::greater)) // empty value list return false; - while (true) { - if (ArgIndex >= TArgs.size()) { - TokError("Too many template arguments: " + utostr(ArgIndex + 1)); - return true; - } - const RecordVal *Arg = ArgsRec->getValue(TArgs[ArgIndex]); - assert(Arg && "Template argument record not found"); + // First, we fill the arguments map with initilzed values. + DenseMap ArgMap(TArgs.size()); + for (auto *ArgName : TArgs) { + ArgMap.insert({ArgName, ArgsRec->getValue(ArgName)->getValue()}); + } - ItemType = Arg->getType(); - Init *Value = ParseValue(CurRec, ItemType); + bool HasNamedArg = false; + for (auto *ArgName : TArgs) { + SMLoc ValueLoc = Lex.getLoc(); + Init *Value = ParseValue( + CurRec, HasNamedArg ? nullptr : ArgsRec->getValue(ArgName)->getType()); if (!Value) return true; - Result.push_back(Value); - if (consume(tgtok::greater)) // end of argument list? + // If we meet '=', then we are parsing named arguments. + if (Lex.getCode() == tgtok::equal) { + if (auto *Name = dyn_cast(Value)) { + Init *QualifiedName = + QualifyName(*ArgsRec, CurMultiClass, Name, IsDefm ? "::" : ":"); + auto *NamedArg = ArgsRec->getValue(QualifiedName); + if (!NamedArg) { + Error(ValueLoc, "Argument " + Name->getAsString() + " doesn't exist"); + return true; + } + Lex.Lex(); // eat the '='. + ValueLoc = Lex.getLoc(); + Value = ParseValue(CurRec, NamedArg->getType()); + // Named value can't be uninitialized. + if (isa(Value)) { + Error(ValueLoc, "The value of named argument should be initialized, " + "but we got '" + + Value->getAsString() + "'"); + return true; + } + ArgMap[QualifiedName] = Value; + HasNamedArg = true; + } else { + Error(ValueLoc, + "The name of named argument should be a valid identifier"); + return true; + } + } else { + // Positional arguments should be put before named arguments. + if (HasNamedArg) { + Error(ValueLoc, + "Positional argument should be put before named argument"); + return true; + } + ArgMap[ArgName] = Value; + } + + if (consume(tgtok::greater)) { // end of argument list? + for (auto *Arg : TArgs) + Result.push_back(ArgMap[Arg]); return false; + } if (!consume(tgtok::comma)) return TokError("Expected comma before next argument"); - ++ArgIndex; } + TokError("Too many template arguments: " + utostr(TArgs.size() + 1)); + return true; } /// ParseDeclaration - Read a declaration, returning the name of field ID, or an diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -684,7 +684,7 @@ def SRLI : Shift_ri<0b00000, 0b101, "srli">; def SRAI : Shift_ri<0b01000, 0b101, "srai">; -def ADD : ALU_rr<0b0000000, 0b000, "add", /*Commutable*/1>, +def ADD : ALU_rr<0b0000000, 0b000, "add", Commutable=1>, Sched<[WriteIALU, ReadIALU, ReadIALU]>; def SUB : ALU_rr<0b0100000, 0b000, "sub">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; @@ -696,15 +696,15 @@ def SLTU : ALU_rr<0b0000000, 0b011, "sltu">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; } -def XOR : ALU_rr<0b0000000, 0b100, "xor", /*Commutable*/1>, +def XOR : ALU_rr<0b0000000, 0b100, "xor", Commutable=1>, Sched<[WriteIALU, ReadIALU, ReadIALU]>; def SRL : ALU_rr<0b0000000, 0b101, "srl">, Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; def SRA : ALU_rr<0b0100000, 0b101, "sra">, Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; -def OR : ALU_rr<0b0000000, 0b110, "or", /*Commutable*/1>, +def OR : ALU_rr<0b0000000, 0b110, "or", Commutable=1>, Sched<[WriteIALU, ReadIALU, ReadIALU]>; -def AND : ALU_rr<0b0000000, 0b111, "and", /*Commutable*/1>, +def AND : ALU_rr<0b0000000, 0b111, "and", Commutable=1>, Sched<[WriteIALU, ReadIALU, ReadIALU]>; let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in { @@ -798,7 +798,7 @@ def SRLIW : ShiftW_ri<0b0000000, 0b101, "srliw">; def SRAIW : ShiftW_ri<0b0100000, 0b101, "sraiw">; -def ADDW : ALUW_rr<0b0000000, 0b000, "addw", /*Commutable*/1>, +def ADDW : ALUW_rr<0b0000000, 0b000, "addw", Commutable=1>, Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>; def SUBW : ALUW_rr<0b0100000, 0b000, "subw">, Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoD.td b/llvm/lib/Target/RISCV/RISCVInstrInfoD.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoD.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoD.td @@ -86,11 +86,11 @@ } let SchedRW = [WriteFAdd64, ReadFAdd64, ReadFAdd64] in { - defm FADD_D : FPALU_rr_frm_m<0b0000001, "fadd.d", Ext, /*Commutable*/1>; + defm FADD_D : FPALU_rr_frm_m<0b0000001, "fadd.d", Ext, Commutable=1>; defm FSUB_D : FPALU_rr_frm_m<0b0000101, "fsub.d", Ext>; } let SchedRW = [WriteFMul64, ReadFMul64, ReadFMul64] in - defm FMUL_D : FPALU_rr_frm_m<0b0001001, "fmul.d", Ext, /*Commutable*/1>; + defm FMUL_D : FPALU_rr_frm_m<0b0001001, "fmul.d", Ext, Commutable=1>; let SchedRW = [WriteFDiv64, ReadFDiv64, ReadFDiv64] in defm FDIV_D : FPALU_rr_frm_m<0b0001101, "fdiv.d", Ext>; @@ -107,8 +107,8 @@ } let SchedRW = [WriteFMinMax64, ReadFMinMax64, ReadFMinMax64] in { - defm FMIN_D : FPALU_rr_m<0b0010101, 0b000, "fmin.d", Ext, /*Commutable*/1>; - defm FMAX_D : FPALU_rr_m<0b0010101, 0b001, "fmax.d", Ext, /*Commutable*/1>; + defm FMIN_D : FPALU_rr_m<0b0010101, 0b000, "fmin.d", Ext, Commutable=1>; + defm FMAX_D : FPALU_rr_m<0b0010101, 0b001, "fmax.d", Ext, Commutable=1>; } defm FCVT_S_D : FPUnaryOp_r_frm_m<0b0100000, 0b00001, Ext, Ext.F32Ty, @@ -120,7 +120,7 @@ Sched<[WriteFCvtF32ToF64, ReadFCvtF32ToF64]>; let SchedRW = [WriteFCmp64, ReadFCmp64, ReadFCmp64] in { - defm FEQ_D : FPCmp_rr_m<0b1010001, 0b010, "feq.d", Ext, /*Commutable*/1>; + defm FEQ_D : FPCmp_rr_m<0b1010001, 0b010, "feq.d", Ext, Commutable=1>; defm FLT_D : FPCmp_rr_m<0b1010001, 0b001, "flt.d", Ext>; defm FLE_D : FPCmp_rr_m<0b1010001, 0b000, "fle.d", Ext>; } diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoF.td b/llvm/lib/Target/RISCV/RISCVInstrInfoF.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoF.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoF.td @@ -268,12 +268,12 @@ } let SchedRW = [WriteFAdd32, ReadFAdd32, ReadFAdd32] in { - defm FADD_S : FPALU_rr_frm_m<0b0000000, "fadd.s", Ext, /*Commutable*/1>; + defm FADD_S : FPALU_rr_frm_m<0b0000000, "fadd.s", Ext, Commutable=1>; defm FSUB_S : FPALU_rr_frm_m<0b0000100, "fsub.s", Ext>; } let SchedRW = [WriteFMul32, ReadFMul32, ReadFMul32] in - defm FMUL_S : FPALU_rr_frm_m<0b0001000, "fmul.s", Ext, /*Commutable*/1>; + defm FMUL_S : FPALU_rr_frm_m<0b0001000, "fmul.s", Ext, Commutable=1>; let SchedRW = [WriteFDiv32, ReadFDiv32, ReadFDiv32] in defm FDIV_S : FPALU_rr_frm_m<0b0001100, "fdiv.s", Ext>; @@ -290,8 +290,8 @@ } let SchedRW = [WriteFMinMax32, ReadFMinMax32, ReadFMinMax32] in { - defm FMIN_S : FPALU_rr_m<0b0010100, 0b000, "fmin.s", Ext, /*Commutable*/1>; - defm FMAX_S : FPALU_rr_m<0b0010100, 0b001, "fmax.s", Ext, /*Commutable*/1>; + defm FMIN_S : FPALU_rr_m<0b0010100, 0b000, "fmin.s", Ext, Commutable=1>; + defm FMAX_S : FPALU_rr_m<0b0010100, 0b001, "fmax.s", Ext, Commutable=1>; } let IsSignExtendingOpW = 1 in @@ -305,7 +305,7 @@ Sched<[WriteFCvtF32ToI32, ReadFCvtF32ToI32]>; let SchedRW = [WriteFCmp32, ReadFCmp32, ReadFCmp32] in { - defm FEQ_S : FPCmp_rr_m<0b1010000, 0b010, "feq.s", Ext, /*Commutable*/1>; + defm FEQ_S : FPCmp_rr_m<0b1010000, 0b010, "feq.s", Ext, Commutable=1>; defm FLT_S : FPCmp_rr_m<0b1010000, 0b001, "flt.s", Ext>; defm FLE_S : FPCmp_rr_m<0b1010000, 0b000, "fle.s", Ext>; } diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoM.td b/llvm/lib/Target/RISCV/RISCVInstrInfoM.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoM.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoM.td @@ -25,13 +25,13 @@ //===----------------------------------------------------------------------===// let Predicates = [HasStdExtMOrZmmul] in { -def MUL : ALU_rr<0b0000001, 0b000, "mul", /*Commutable*/1>, +def MUL : ALU_rr<0b0000001, 0b000, "mul", Commutable=1>, Sched<[WriteIMul, ReadIMul, ReadIMul]>; -def MULH : ALU_rr<0b0000001, 0b001, "mulh", /*Commutable*/1>, +def MULH : ALU_rr<0b0000001, 0b001, "mulh", Commutable=1>, Sched<[WriteIMul, ReadIMul, ReadIMul]>; def MULHSU : ALU_rr<0b0000001, 0b010, "mulhsu">, Sched<[WriteIMul, ReadIMul, ReadIMul]>; -def MULHU : ALU_rr<0b0000001, 0b011, "mulhu", /*Commutable*/1>, +def MULHU : ALU_rr<0b0000001, 0b011, "mulhu", Commutable=1>, Sched<[WriteIMul, ReadIMul, ReadIMul]>; } // Predicates = [HasStdExtMOrZmmul] @@ -47,7 +47,7 @@ } // Predicates = [HasStdExtM] let Predicates = [HasStdExtMOrZmmul, IsRV64], IsSignExtendingOpW = 1 in { -def MULW : ALUW_rr<0b0000001, 0b000, "mulw", /*Commutable*/1>, +def MULW : ALUW_rr<0b0000001, 0b000, "mulw", Commutable=1>, Sched<[WriteIMul32, ReadIMul32, ReadIMul32]>; } // Predicates = [HasStdExtMOrZmmul, IsRV64] diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td @@ -2393,7 +2393,7 @@ multiclass VPseudoVSQR_V { foreach m = MxListF in { defvar mx = m.MX; - defvar sews = SchedSEWSet.val; + defvar sews = SchedSEWSet.val; let VLMul = m.value in foreach e = sews in { @@ -2748,7 +2748,7 @@ multiclass VPseudoVFDIV_VV_VF { foreach m = MxListF in { defvar mx = m.MX; - defvar sews = SchedSEWSet.val; + defvar sews = SchedSEWSet.val; foreach e = sews in { defvar WriteVFDivV_MX_E = !cast("WriteVFDivV_" # mx # "_E" # e); defvar ReadVFDivV_MX_E = !cast("ReadVFDivV_" # mx # "_E" # e); @@ -3089,11 +3089,11 @@ defvar ReadVICALUV_MX = !cast("ReadVICALUV_" # mx); defvar ReadVICALUX_MX = !cast("ReadVICALUX_" # mx); - defm "" : VPseudoBinaryV_VM, + defm "" : VPseudoBinaryV_VM, Sched<[WriteVICALUV_MX, ReadVICALUV_MX, ReadVICALUV_MX, ReadVMask]>; - defm "" : VPseudoBinaryV_XM, + defm "" : VPseudoBinaryV_XM, Sched<[WriteVICALUX_MX, ReadVICALUV_MX, ReadVICALUX_MX, ReadVMask]>; - defm "" : VPseudoBinaryV_IM, + defm "" : VPseudoBinaryV_IM, Sched<[WriteVICALUI_MX, ReadVICALUV_MX, ReadVMask]>; } } @@ -3106,9 +3106,9 @@ defvar ReadVICALUV_MX = !cast("ReadVICALUV_" # mx); defvar ReadVICALUX_MX = !cast("ReadVICALUX_" # mx); - defm "" : VPseudoBinaryV_VM, + defm "" : VPseudoBinaryV_VM, Sched<[WriteVICALUV_MX, ReadVICALUV_MX, ReadVICALUV_MX, ReadVMask]>; - defm "" : VPseudoBinaryV_XM, + defm "" : VPseudoBinaryV_XM, Sched<[WriteVICALUX_MX, ReadVICALUV_MX, ReadVICALUX_MX, ReadVMask]>; } } @@ -3122,11 +3122,11 @@ defvar ReadVICALUV_MX = !cast("ReadVICALUV_" # mx); defvar ReadVICALUX_MX = !cast("ReadVICALUX_" # mx); - defm "" : VPseudoBinaryV_VM, + defm "" : VPseudoBinaryV_VM, Sched<[WriteVICALUV_MX, ReadVICALUV_MX, ReadVICALUV_MX]>; - defm "" : VPseudoBinaryV_XM, + defm "" : VPseudoBinaryV_XM, Sched<[WriteVICALUX_MX, ReadVICALUV_MX, ReadVICALUX_MX]>; - defm "" : VPseudoBinaryV_IM, + defm "" : VPseudoBinaryV_IM, Sched<[WriteVICALUI_MX, ReadVICALUV_MX]>; } } @@ -3139,9 +3139,9 @@ defvar ReadVICALUV_MX = !cast("ReadVICALUV_" # mx); defvar ReadVICALUX_MX = !cast("ReadVICALUX_" # mx); - defm "" : VPseudoBinaryV_VM, + defm "" : VPseudoBinaryV_VM, Sched<[WriteVICALUV_MX, ReadVICALUV_MX, ReadVICALUV_MX]>; - defm "" : VPseudoBinaryV_XM, + defm "" : VPseudoBinaryV_XM, Sched<[WriteVICALUX_MX, ReadVICALUV_MX, ReadVICALUX_MX]>; } } @@ -3236,18 +3236,18 @@ multiclass VPseudoTernaryV_VV_AAXA { defm _VV : VPseudoTernaryWithPolicy; + Constraint, Commutable=1>; } multiclass VPseudoTernaryV_VX_AAXA { defm "_VX" : VPseudoTernaryWithPolicy; + Constraint, Commutable=1>; } multiclass VPseudoTernaryV_VF_AAXA { defm "_V" # f.FX : VPseudoTernaryWithPolicy; + Commutable=1>; } multiclass VPseudoTernaryW_VV { @@ -3498,7 +3498,7 @@ multiclass VPseudoVWRED_VS { foreach m = MxListWRed in { defvar mx = m.MX; - foreach e = SchedSEWSet.val in { + foreach e = SchedSEWSet.val in { defvar WriteVIWRedV_From_MX_E = !cast("WriteVIWRedV_From_" # mx # "_E" # e); defm _VS : VPseudoTernaryWithTailPolicy, Sched<[WriteVIWRedV_From_MX_E, ReadVIWRedV, ReadVIWRedV, @@ -3510,7 +3510,7 @@ multiclass VPseudoVFRED_VS { foreach m = MxListF in { defvar mx = m.MX; - foreach e = SchedSEWSet.val in { + foreach e = SchedSEWSet.val in { defvar WriteVFRedV_From_MX_E = !cast("WriteVFRedV_From_" # mx # "_E" # e); defm _VS : VPseudoTernaryWithTailPolicy, Sched<[WriteVFRedV_From_MX_E, ReadVFRedV, ReadVFRedV, ReadVFRedV, @@ -3534,7 +3534,7 @@ multiclass VPseudoVFREDO_VS { foreach m = MxListF in { defvar mx = m.MX; - foreach e = SchedSEWSet.val in { + foreach e = SchedSEWSet.val in { defvar WriteVFRedOV_From_MX_E = !cast("WriteVFRedOV_From_" # mx # "_E" # e); defm _VS : VPseudoTernaryWithTailPolicy, Sched<[WriteVFRedOV_From_MX_E, ReadVFRedOV, ReadVFRedOV, @@ -3546,7 +3546,7 @@ multiclass VPseudoVFWRED_VS { foreach m = MxListFWRed in { defvar mx = m.MX; - foreach e = SchedSEWSet.val in { + foreach e = SchedSEWSet.val in { defvar WriteVFWRedV_From_MX_E = !cast("WriteVFWRedV_From_" # mx # "_E" # e); defm _VS : VPseudoTernaryWithTailPolicy, Sched<[WriteVFWRedV_From_MX_E, ReadVFWRedV, ReadVFWRedV, @@ -5248,9 +5248,9 @@ VPatBinaryV_IM_TAIL; multiclass VPatBinaryM_VM_XM_IM - : VPatBinaryV_VM, - VPatBinaryV_XM, - VPatBinaryV_IM; + : VPatBinaryV_VM, + VPatBinaryV_XM, + VPatBinaryV_IM; multiclass VPatBinaryM_V_X_I : VPatBinaryV_V, @@ -5262,8 +5262,8 @@ VPatBinaryV_XM_TAIL; multiclass VPatBinaryM_VM_XM - : VPatBinaryV_VM, - VPatBinaryV_XM; + : VPatBinaryV_VM, + VPatBinaryV_XM; multiclass VPatBinaryM_V_X : VPatBinaryV_V, @@ -6560,10 +6560,10 @@ //===----------------------------------------------------------------------===// // 11.11. Vector Integer Divide Instructions //===----------------------------------------------------------------------===// -defm : VPatBinaryV_VV_VX<"int_riscv_vdivu", "PseudoVDIVU", AllIntegerVectors, /*isSEWAware*/ 1>; -defm : VPatBinaryV_VV_VX<"int_riscv_vdiv", "PseudoVDIV", AllIntegerVectors, /*isSEWAware*/ 1>; -defm : VPatBinaryV_VV_VX<"int_riscv_vremu", "PseudoVREMU", AllIntegerVectors, /*isSEWAware*/ 1>; -defm : VPatBinaryV_VV_VX<"int_riscv_vrem", "PseudoVREM", AllIntegerVectors, /*isSEWAware*/ 1>; +defm : VPatBinaryV_VV_VX<"int_riscv_vdivu", "PseudoVDIVU", AllIntegerVectors, isSEWAware=1>; +defm : VPatBinaryV_VV_VX<"int_riscv_vdiv", "PseudoVDIV", AllIntegerVectors, isSEWAware=1>; +defm : VPatBinaryV_VV_VX<"int_riscv_vremu", "PseudoVREMU", AllIntegerVectors, isSEWAware=1>; +defm : VPatBinaryV_VV_VX<"int_riscv_vrem", "PseudoVREM", AllIntegerVectors, isSEWAware=1>; //===----------------------------------------------------------------------===// // 11.12. Vector Widening Integer Multiply Instructions @@ -6686,8 +6686,8 @@ // 13.4. Vector Single-Width Floating-Point Multiply/Divide Instructions //===----------------------------------------------------------------------===// defm : VPatBinaryV_VV_VX<"int_riscv_vfmul", "PseudoVFMUL", AllFloatVectors>; -defm : VPatBinaryV_VV_VX<"int_riscv_vfdiv", "PseudoVFDIV", AllFloatVectors, /*isSEWAware*/ 1>; -defm : VPatBinaryV_VX<"int_riscv_vfrdiv", "PseudoVFRDIV", AllFloatVectors, /*isSEWAware*/ 1>; +defm : VPatBinaryV_VV_VX<"int_riscv_vfdiv", "PseudoVFDIV", AllFloatVectors, isSEWAware=1>; +defm : VPatBinaryV_VX<"int_riscv_vfrdiv", "PseudoVFRDIV", AllFloatVectors, isSEWAware=1>; //===----------------------------------------------------------------------===// // 13.5. Vector Widening Floating-Point Multiply @@ -6717,7 +6717,7 @@ //===----------------------------------------------------------------------===// // 13.8. Vector Floating-Point Square-Root Instruction //===----------------------------------------------------------------------===// -defm : VPatUnaryV_V<"int_riscv_vfsqrt", "PseudoVFSQRT", AllFloatVectors, /*isSEWAware*/ 1>; +defm : VPatUnaryV_V<"int_riscv_vfsqrt", "PseudoVFSQRT", AllFloatVectors, isSEWAware=1>; //===----------------------------------------------------------------------===// // 13.9. Vector Floating-Point Reciprocal Square-Root Estimate Instruction @@ -6765,12 +6765,9 @@ // We can use vmerge.vvm to support vector-vector vfmerge. // NOTE: Clang previously used int_riscv_vfmerge for vector-vector, but now uses // int_riscv_vmerge. Support both for compatibility. -defm : VPatBinaryV_VM_TAIL<"int_riscv_vmerge", "PseudoVMERGE", - /*CarryOut = */0, /*vtilist=*/AllFloatVectors>; -defm : VPatBinaryV_VM_TAIL<"int_riscv_vfmerge", "PseudoVMERGE", - /*CarryOut = */0, /*vtilist=*/AllFloatVectors>; -defm : VPatBinaryV_XM_TAIL<"int_riscv_vfmerge", "PseudoVFMERGE", - /*CarryOut = */0, /*vtilist=*/AllFloatVectors>; +defm : VPatBinaryV_VM_TAIL<"int_riscv_vmerge", "PseudoVMERGE", vtilist=AllFloatVectors>; +defm : VPatBinaryV_VM_TAIL<"int_riscv_vfmerge", "PseudoVMERGE", vtilist=AllFloatVectors>; +defm : VPatBinaryV_XM_TAIL<"int_riscv_vfmerge", "PseudoVFMERGE", vtilist=AllFloatVectors>; foreach fvti = AllFloatVectors in { defvar instr = !cast("PseudoVMERGE_VIM_"#fvti.LMul.MX); @@ -6848,16 +6845,16 @@ //===----------------------------------------------------------------------===// // 14.3. Vector Single-Width Floating-Point Reduction Instructions //===----------------------------------------------------------------------===// -defm : VPatReductionV_VS<"int_riscv_vfredosum", "PseudoVFREDOSUM", /*IsFloat=*/1>; -defm : VPatReductionV_VS<"int_riscv_vfredusum", "PseudoVFREDUSUM", /*IsFloat=*/1>; -defm : VPatReductionV_VS<"int_riscv_vfredmin", "PseudoVFREDMIN", /*IsFloat=*/1>; -defm : VPatReductionV_VS<"int_riscv_vfredmax", "PseudoVFREDMAX", /*IsFloat=*/1>; +defm : VPatReductionV_VS<"int_riscv_vfredosum", "PseudoVFREDOSUM", IsFloat=1>; +defm : VPatReductionV_VS<"int_riscv_vfredusum", "PseudoVFREDUSUM", IsFloat=1>; +defm : VPatReductionV_VS<"int_riscv_vfredmin", "PseudoVFREDMIN", IsFloat=1>; +defm : VPatReductionV_VS<"int_riscv_vfredmax", "PseudoVFREDMAX", IsFloat=1>; //===----------------------------------------------------------------------===// // 14.4. Vector Widening Floating-Point Reduction Instructions //===----------------------------------------------------------------------===// -defm : VPatReductionW_VS<"int_riscv_vfwredusum", "PseudoVFWREDUSUM", /*IsFloat=*/1>; -defm : VPatReductionW_VS<"int_riscv_vfwredosum", "PseudoVFWREDOSUM", /*IsFloat=*/1>; +defm : VPatReductionW_VS<"int_riscv_vfwredusum", "PseudoVFWREDUSUM", IsFloat=1>; +defm : VPatReductionW_VS<"int_riscv_vfwredosum", "PseudoVFWREDOSUM", IsFloat=1>; //===----------------------------------------------------------------------===// // 15. Vector Mask Instructions diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td @@ -841,10 +841,10 @@ } // 11.11. Vector Integer Divide Instructions -defm : VPatBinarySDNode_VV_VX; -defm : VPatBinarySDNode_VV_VX; -defm : VPatBinarySDNode_VV_VX; -defm : VPatBinarySDNode_VV_VX; +defm : VPatBinarySDNode_VV_VX; +defm : VPatBinarySDNode_VV_VX; +defm : VPatBinarySDNode_VV_VX; +defm : VPatBinarySDNode_VV_VX; // 11.12. Vector Widening Integer Multiply Instructions defm : VPatWidenBinarySDNode_VV_VX; -defm : VPatBinaryFPSDNode_VV_VF; -defm : VPatBinaryFPSDNode_R_VF; +defm : VPatBinaryFPSDNode_VV_VF; +defm : VPatBinaryFPSDNode_R_VF; // 13.5. Vector Widening Floating-Point Multiply Instructions defm : VPatWidenBinaryFPSDNode_VV_VF; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td @@ -1697,10 +1697,10 @@ } // 11.11. Vector Integer Divide Instructions -defm : VPatBinaryVL_VV_VX; -defm : VPatBinaryVL_VV_VX; -defm : VPatBinaryVL_VV_VX; -defm : VPatBinaryVL_VV_VX; +defm : VPatBinaryVL_VV_VX; +defm : VPatBinaryVL_VV_VX; +defm : VPatBinaryVL_VV_VX; +defm : VPatBinaryVL_VV_VX; // 11.12. Vector Widening Integer Multiply Instructions defm : VPatBinaryWVL_VV_VX; @@ -1838,8 +1838,8 @@ // 13.4. Vector Single-Width Floating-Point Multiply/Divide Instructions defm : VPatBinaryFPVL_VV_VF; -defm : VPatBinaryFPVL_VV_VF; -defm : VPatBinaryFPVL_R_VF; +defm : VPatBinaryFPVL_VV_VF; +defm : VPatBinaryFPVL_R_VF; // 13.5. Vector Widening Floating-Point Multiply Instructions defm : VPatBinaryFPWVL_VV_VF; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td @@ -397,25 +397,25 @@ } // Predicates = [HasStdExtZbb] let Predicates = [HasStdExtZbc] in { -def CLMULR : ALU_rr<0b0000101, 0b010, "clmulr", /*Commutable*/1>, +def CLMULR : ALU_rr<0b0000101, 0b010, "clmulr", Commutable=1>, Sched<[WriteCLMUL, ReadCLMUL, ReadCLMUL]>; } // Predicates = [HasStdExtZbc] let Predicates = [HasStdExtZbcOrZbkc] in { -def CLMUL : ALU_rr<0b0000101, 0b001, "clmul", /*Commutable*/1>, +def CLMUL : ALU_rr<0b0000101, 0b001, "clmul", Commutable=1>, Sched<[WriteCLMUL, ReadCLMUL, ReadCLMUL]>; -def CLMULH : ALU_rr<0b0000101, 0b011, "clmulh", /*Commutable*/1>, +def CLMULH : ALU_rr<0b0000101, 0b011, "clmulh", Commutable=1>, Sched<[WriteCLMUL, ReadCLMUL, ReadCLMUL]>; } // Predicates = [HasStdExtZbcOrZbkc] let Predicates = [HasStdExtZbb] in { -def MIN : ALU_rr<0b0000101, 0b100, "min", /*Commutable*/1>, +def MIN : ALU_rr<0b0000101, 0b100, "min", Commutable=1>, Sched<[WriteIALU, ReadIALU, ReadIALU]>; -def MINU : ALU_rr<0b0000101, 0b101, "minu", /*Commutable*/1>, +def MINU : ALU_rr<0b0000101, 0b101, "minu", Commutable=1>, Sched<[WriteIALU, ReadIALU, ReadIALU]>; -def MAX : ALU_rr<0b0000101, 0b110, "max", /*Commutable*/1>, +def MAX : ALU_rr<0b0000101, 0b110, "max", Commutable=1>, Sched<[WriteIALU, ReadIALU, ReadIALU]>; -def MAXU : ALU_rr<0b0000101, 0b111, "maxu", /*Commutable*/1>, +def MAXU : ALU_rr<0b0000101, 0b111, "maxu", Commutable=1>, Sched<[WriteIALU, ReadIALU, ReadIALU]>; } // Predicates = [HasStdExtZbb] diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZfa.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZfa.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZfa.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZfa.td @@ -89,8 +89,8 @@ Sched<[WriteFLI32]>; let SchedRW = [WriteFMinMax32, ReadFMinMax32, ReadFMinMax32] in { -def FMINM_S: FPALU_rr<0b0010100, 0b010, "fminm.s", FPR32, /*Commutable*/ 1>; -def FMAXM_S: FPALU_rr<0b0010100, 0b011, "fmaxm.s", FPR32, /*Commutable*/ 1>; +def FMINM_S: FPALU_rr<0b0010100, 0b010, "fminm.s", FPR32, Commutable=1>; +def FMAXM_S: FPALU_rr<0b0010100, 0b011, "fmaxm.s", FPR32, Commutable=1>; } def FROUND_S : FPUnaryOp_r_frm<0b0100000, 0b00100, FPR32, FPR32, "fround.s">, @@ -111,8 +111,8 @@ Sched<[WriteFLI64]>; let SchedRW = [WriteFMinMax64, ReadFMinMax64, ReadFMinMax64] in { -def FMINM_D: FPALU_rr<0b0010101, 0b010, "fminm.d", FPR64, /*Commutable*/ 1>; -def FMAXM_D: FPALU_rr<0b0010101, 0b011, "fmaxm.d", FPR64, /*Commutable*/ 1>; +def FMINM_D: FPALU_rr<0b0010101, 0b010, "fminm.d", FPR64, Commutable=1>; +def FMAXM_D: FPALU_rr<0b0010101, 0b011, "fmaxm.d", FPR64, Commutable=1>; } def FROUND_D : FPUnaryOp_r_frm<0b0100001, 0b00100, FPR64, FPR64, "fround.d">, @@ -152,8 +152,8 @@ let Predicates = [HasStdExtZfa, HasStdExtZfh] in { let SchedRW = [WriteFMinMax16, ReadFMinMax16, ReadFMinMax16] in { -def FMINM_H: FPALU_rr<0b0010110, 0b010, "fminm.h", FPR16, /*Commutable*/ 1>; -def FMAXM_H: FPALU_rr<0b0010110, 0b011, "fmaxm.h", FPR16, /*Commutable*/ 1>; +def FMINM_H: FPALU_rr<0b0010110, 0b010, "fminm.h", FPR16, Commutable=1>; +def FMAXM_H: FPALU_rr<0b0010110, 0b011, "fmaxm.h", FPR16, Commutable=1>; } def FROUND_H : FPUnaryOp_r_frm<0b0100010, 0b00100, FPR16, FPR16, "fround.h">, diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td @@ -93,11 +93,11 @@ } let SchedRW = [WriteFAdd16, ReadFAdd16, ReadFAdd16] in { - defm FADD_H : FPALU_rr_frm_m<0b0000010, "fadd.h", Ext, /*Commutable*/1>; + defm FADD_H : FPALU_rr_frm_m<0b0000010, "fadd.h", Ext, Commutable=1>; defm FSUB_H : FPALU_rr_frm_m<0b0000110, "fsub.h", Ext>; } let SchedRW = [WriteFMul16, ReadFMul16, ReadFMul16] in - defm FMUL_H : FPALU_rr_frm_m<0b0001010, "fmul.h", Ext, /*Commutable*/1>; + defm FMUL_H : FPALU_rr_frm_m<0b0001010, "fmul.h", Ext, Commutable=1>; let SchedRW = [WriteFDiv16, ReadFDiv16, ReadFDiv16] in defm FDIV_H : FPALU_rr_frm_m<0b0001110, "fdiv.h", Ext>; @@ -114,8 +114,8 @@ } let SchedRW = [WriteFMinMax16, ReadFMinMax16, ReadFMinMax16] in { - defm FMIN_H : FPALU_rr_m<0b0010110, 0b000, "fmin.h", Ext, /*Commutable*/1>; - defm FMAX_H : FPALU_rr_m<0b0010110, 0b001, "fmax.h", Ext, /*Commutable*/1>; + defm FMIN_H : FPALU_rr_m<0b0010110, 0b000, "fmin.h", Ext, Commutable=1>; + defm FMAX_H : FPALU_rr_m<0b0010110, 0b001, "fmax.h", Ext, Commutable=1>; } let IsSignExtendingOpW = 1 in @@ -159,7 +159,7 @@ foreach Ext = ZfhExts in { let SchedRW = [WriteFCmp16, ReadFCmp16, ReadFCmp16] in { - defm FEQ_H : FPCmp_rr_m<0b1010010, 0b010, "feq.h", Ext, /*Commutable*/1>; + defm FEQ_H : FPCmp_rr_m<0b1010010, 0b010, "feq.h", Ext, Commutable=1>; defm FLT_H : FPCmp_rr_m<0b1010010, 0b001, "flt.h", Ext>; defm FLE_H : FPCmp_rr_m<0b1010010, 0b000, "fle.h", Ext>; } diff --git a/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td b/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td --- a/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSiFive7.td @@ -732,7 +732,7 @@ } } foreach mx = SchedMxListF in { - foreach sew = SchedSEWSet.val in { + foreach sew = SchedSEWSet.val in { defvar Cycles = !mul(SiFive7GetDivOrSqrtFactor.c, !div(SiFive7GetCyclesOnePerElement.c, 4)); defvar IsWorstCase = SiFive7IsWorstCaseMXSEW.c; diff --git a/llvm/lib/Target/RISCV/RISCVScheduleV.td b/llvm/lib/Target/RISCV/RISCVScheduleV.td --- a/llvm/lib/Target/RISCV/RISCVScheduleV.td +++ b/llvm/lib/Target/RISCV/RISCVScheduleV.td @@ -170,21 +170,21 @@ : LMULSEWReadAdvanceImpl; multiclass LMULSEWSchedWritesWRed - : LMULSEWSchedWritesImpl; + : LMULSEWSchedWritesImpl; multiclass LMULSEWWriteResWRed resources> - : LMULSEWWriteResImpl; + : LMULSEWWriteResImpl; multiclass LMULSEWSchedWritesFWRed - : LMULSEWSchedWritesImpl; + : LMULSEWSchedWritesImpl; multiclass LMULSEWWriteResFWRed resources> - : LMULSEWWriteResImpl; + : LMULSEWWriteResImpl; -multiclass LMULSEWSchedWritesF : LMULSEWSchedWritesImpl; -multiclass LMULSEWSchedReadsF : LMULSEWSchedReadsImpl; +multiclass LMULSEWSchedWritesF : LMULSEWSchedWritesImpl; +multiclass LMULSEWSchedReadsF : LMULSEWSchedReadsImpl; multiclass LMULSEWWriteResF resources> - : LMULSEWWriteResImpl; + : LMULSEWWriteResImpl; multiclass LMULSEWReadAdvanceF writes = []> - : LMULSEWReadAdvanceImpl; + : LMULSEWReadAdvanceImpl; multiclass LMULSchedWritesW : LMULSchedWritesImpl; multiclass LMULSchedReadsW : LMULSchedReadsImpl; diff --git a/llvm/test/TableGen/named-arguments.td b/llvm/test/TableGen/named-arguments.td new file mode 100644 --- /dev/null +++ b/llvm/test/TableGen/named-arguments.td @@ -0,0 +1,98 @@ +// RUN: llvm-tblgen %s | FileCheck %s +// RUN: not llvm-tblgen -DERROR1 %s 2>&1 | FileCheck --check-prefix=ERROR1 %s +// RUN: not llvm-tblgen -DERROR2 %s 2>&1 | FileCheck --check-prefix=ERROR2 %s +// RUN: not llvm-tblgen -DERROR3 %s 2>&1 | FileCheck --check-prefix=ERROR3 %s +// RUN: not llvm-tblgen -DERROR4 %s 2>&1 | FileCheck --check-prefix=ERROR4 %s + +class TestClass { + int value = !add(a, b, c); +} +// CHECK: def testClass1 { +// CHECK-NEXT: int value = 6; +// CHECK-NEXT: } +// CHECK: def testClass2 { +// CHECK-NEXT: int value = 6; +// CHECK-NEXT: } +// CHECK: def testClass3 { +// CHECK-NEXT: int value = 6; +// CHECK-NEXT: } +// CHECK: def testClass4 { +// CHECK-NEXT: int value = 6; +// CHECK-NEXT: } +// CHECK: def testClass5 { +// CHECK-NEXT: int value = 6; +// CHECK-NEXT: } +// CHECK: def testClass6 { +// CHECK-NEXT: int value = 6; +// CHECK-NEXT: } +// CHECK: def testClass7 { +// CHECK-NEXT: int value = 6; +// CHECK-NEXT: } +// CHECK: def testClass8 { +// CHECK-NEXT: int value = 6; +// CHECK-NEXT: } +def testClass1: TestClass<1>; +def testClass2: TestClass<1, 2>; +def testClass3: TestClass<1, 2, 3>; +def testClass4: TestClass<1, b=2>; +def testClass5: TestClass<1, c=3>; +def testClass6: TestClass<1, b=2, c=3>; +def testClass7: TestClass<1, c=3, b=2>; +def testClass8: TestClass; + +#ifdef ERROR1 +// ERROR1: Argument "d" doesn't exist +def testError1: TestClass<1, d=3>; +#endif + +#ifdef ERROR2 +// ERROR2: The name of named argument should be a valid identifier +def testError2: TestClass<1, 3=0>; +#endif + +#ifdef ERROR3 +// ERROR3: Positional argument should be put before named argument +def testError3: TestClass<1, b=1, 2>; +#endif + +#ifdef ERROR4 +// ERROR4: The value of named argument should be initialized, but we got '?' +def testError4: TestClass<1, b=?>; +#endif + +multiclass TestMultiClass { + def "": TestClass; +} + +// CHECK: def testMultiClass1 { +// CHECK-NEXT: int value = 6; +// CHECK-NEXT: } +// CHECK: def testMultiClass2 { +// CHECK-NEXT: int value = 6; +// CHECK-NEXT: } +// CHECK: def testMultiClass3 { +// CHECK-NEXT: int value = 6; +// CHECK-NEXT: } +// CHECK: def testMultiClass4 { +// CHECK-NEXT: int value = 6; +// CHECK-NEXT: } +// CHECK: def testMultiClass5 { +// CHECK-NEXT: int value = 6; +// CHECK-NEXT: } +// CHECK: def testMultiClass6 { +// CHECK-NEXT: int value = 6; +// CHECK-NEXT: } +// CHECK: def testMultiClass7 { +// CHECK-NEXT: int value = 6; +// CHECK-NEXT: } +// CHECK: def testMultiClass8 { +// CHECK-NEXT: int value = 6; +// CHECK-NEXT: } +defm testMultiClass1: TestMultiClass<1>; +defm testMultiClass2: TestMultiClass<1, 2>; +defm testMultiClass3: TestMultiClass<1, 2, 3>; +defm testMultiClass4: TestMultiClass<1, b=2>; +defm testMultiClass5: TestMultiClass<1, c=3>; +defm testMultiClass6: TestMultiClass<1, b=2, c=3>; +defm testMultiClass7: TestMultiClass<1, c=3, b=2>; +defm testMultiClass8: TestMultiClass; \ No newline at end of file