From 28041f859a40e7acb797758972eb1f5b8da2fa53 Mon Sep 17 00:00:00 2001 From: Rot127 Date: Sat, 3 May 2025 06:29:16 -0500 Subject: [PATCH 1/9] Add Sparc and patch out , for sparc alias. --- llvm/utils/TableGen/PrinterCapstone.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/llvm/utils/TableGen/PrinterCapstone.cpp b/llvm/utils/TableGen/PrinterCapstone.cpp index d37174a719e8..bdd3db8291dc 100644 --- a/llvm/utils/TableGen/PrinterCapstone.cpp +++ b/llvm/utils/TableGen/PrinterCapstone.cpp @@ -1116,7 +1116,7 @@ void PrinterCapstone::decoderEmitterEmitDecodeInstruction( std::set InsnBytesAsUint24 = {"Xtensa"}; std::set InsnBytesAsUint32 = {"ARM", "AArch64", "LoongArch", "Alpha", "Mips", "TriCore", - "ARC"}; + "ARC", "Sparc"}; std::set InsnBytesAsUint64 = {"SystemZ", "ARC"}; bool MacroDefined = false; if (InsnBytesAsUint16.find(TargetName) != InsnBytesAsUint16.end()) { @@ -2657,6 +2657,7 @@ normalizedMnemonic(StringRef const &Mn, const bool Upper = true, // Each tuple is: Regex Pattern : Replacement char static SmallVector> Replacements = { {"[.]", "_"}, + {"[,]", "_"}, {"[|]", "_"}, {"[+]", "p"}, {"[-]", "m"}, From df72407a6bfb1e41b70d32aa95391f5906ddd680 Mon Sep 17 00:00:00 2001 From: Rot127 Date: Sat, 3 May 2025 10:51:13 -0500 Subject: [PATCH 2/9] Emit Sparc ASI tags and change default inc name to SystemOperands. --- llvm/lib/Target/Sparc/SparcASITags.td | 26 ++++++------------- llvm/utils/TableGen/PrinterCapstone.cpp | 10 ++++--- .../utils/TableGen/SearchableTableEmitter.cpp | 15 +++++++++-- 3 files changed, 27 insertions(+), 24 deletions(-) diff --git a/llvm/lib/Target/Sparc/SparcASITags.td b/llvm/lib/Target/Sparc/SparcASITags.td index 115e41bfe033..54de2e0282aa 100644 --- a/llvm/lib/Target/Sparc/SparcASITags.td +++ b/llvm/lib/Target/Sparc/SparcASITags.td @@ -13,29 +13,19 @@ include "llvm/TableGen/SearchableTable.td" -class ASITag op> { +// Capstone edit: +// This is changed to a Searchable Table. +// Simply because emitting generic tables with the PrinterCapstone class +// is not implemented (and is annoying to do so). + +class ASITag op> : SearchableTable { string Name = name; // A maximum of one alias is supported right now. string AltName = alt_name; bits<8> Encoding = op; -} - -def ASITagsList : GenericTable { - let FilterClass = "ASITag"; - let Fields = ["Name", "AltName", "Encoding"]; - - let PrimaryKey = [ "Encoding" ]; - let PrimaryKeyName = "lookupASITagByEncoding"; -} - -def lookupASITagByName : SearchIndex { - let Table = ASITagsList; - let Key = [ "Name" ]; -} + let EnumValueField = "Encoding"; -def lookupASITagByAltName : SearchIndex { - let Table = ASITagsList; - let Key = [ "AltName" ]; + let SearchableFields = ["Name", "AltName", "Encoding"]; } def : ASITag<"ASI_N", "ASI_NUCLEUS", 0x4>; diff --git a/llvm/utils/TableGen/PrinterCapstone.cpp b/llvm/utils/TableGen/PrinterCapstone.cpp index bdd3db8291dc..3a7f0186a5f4 100644 --- a/llvm/utils/TableGen/PrinterCapstone.cpp +++ b/llvm/utils/TableGen/PrinterCapstone.cpp @@ -3857,7 +3857,7 @@ void PrinterCapstone::asmMatcherEmitComputeAssemblerAvailableFeatures( AsmMatcherInfo &Info, StringRef const &ClassName) const {} void PrinterCapstone::searchableTablesWriteFiles() const { - std::string Filename = TargetName + "GenSystemRegister.inc"; + std::string Filename = TargetName + "GenSystemOperands.inc"; std::string HeaderStr; raw_string_ostream Header(HeaderStr); emitDefaultSourceFileHeader(Header); @@ -4027,16 +4027,18 @@ std::string getTableNamespacePrefix(const GenericTable &Table, {"ARMSysReg", "MClassSysReg"}, {"ARMBankedReg", "BankedReg"}, }; + std::set> SparcNSTypePairs = { + {"Sparc_ASITag", "ASITag"}, + }; std::set> *NSTable; - if (StringRef(TargetName).upper() != "AARCH64" && TargetName != "ARM") - return Table.CppTypeName + "_"; - if (StringRef(TargetName).upper() == "AARCH64") NSTable = &AArch64NSTypePairs; else if (TargetName == "ARM") NSTable = &ARMNSTypePairs; + else if (StringRef(TargetName).upper() == "SPARC") + NSTable = &SparcNSTypePairs; else PrintFatalNote("No Namespace Type table defined for target."); diff --git a/llvm/utils/TableGen/SearchableTableEmitter.cpp b/llvm/utils/TableGen/SearchableTableEmitter.cpp index a28a4082de62..5b722b49af6b 100644 --- a/llvm/utils/TableGen/SearchableTableEmitter.cpp +++ b/llvm/utils/TableGen/SearchableTableEmitter.cpp @@ -633,12 +633,23 @@ void EmitSearchableTables(RecordKeeper &RK, raw_ostream &OS) { break; case PRINTER_LANG_CAPSTONE_C: Record *IDef = RK.getClass("I"); - if (!IDef) + if (!IDef) { + // Sparc's lowest class is InstSP not I + IDef = RK.getClass("InstSP"); + } + if (!IDef) { // If this is reached we need to implement the search for other classes which have Namespace set. - llvm_unreachable("Base instruction class \"I\" does not exist for this target."); + llvm_unreachable("Root instruction class \"I\" does not exist for this target."); + } if (!IDef->getValue("Namespace")) llvm_unreachable("Field \"Namespace\" does not exist."); std::string TName = IDef->getValueAsString("Namespace").str(); + if (TName.empty()) { + llvm_unreachable("Field \"Namespace\" is empty, but should be the target name."); + } else if (TName == "SP") { + // Rename namespace nickname. + TName = "Sparc"; + } PI = new PrinterCapstone(FOS, TName); break; } From 302e86a380f86017481910b383a5eb1d20053578 Mon Sep 17 00:00:00 2001 From: Rot127 Date: Mon, 5 May 2025 12:13:37 -0500 Subject: [PATCH 3/9] Rename SP to Sparc namespace and clearify Namespace should be TargetName. --- llvm/lib/Target/Sparc/SparcInstrFormats.td | 2 +- llvm/lib/Target/Sparc/SparcRegisterInfo.td | 8 ++++---- llvm/utils/TableGen/PrinterCapstone.cpp | 23 ++++++++++++---------- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/llvm/lib/Target/Sparc/SparcInstrFormats.td b/llvm/lib/Target/Sparc/SparcInstrFormats.td index 3939f4ed9427..a4408ec63e4a 100644 --- a/llvm/lib/Target/Sparc/SparcInstrFormats.td +++ b/llvm/lib/Target/Sparc/SparcInstrFormats.td @@ -11,7 +11,7 @@ class InstSP pattern, : Instruction { field bits<32> Inst; - let Namespace = "SP"; + let Namespace = "Sparc"; let Size = 4; bits<2> op; diff --git a/llvm/lib/Target/Sparc/SparcRegisterInfo.td b/llvm/lib/Target/Sparc/SparcRegisterInfo.td index d8319a8d41dd..54806f3c1e4d 100644 --- a/llvm/lib/Target/Sparc/SparcRegisterInfo.td +++ b/llvm/lib/Target/Sparc/SparcRegisterInfo.td @@ -12,23 +12,23 @@ class SparcReg Enc, string n> : Register { let HWEncoding = Enc; - let Namespace = "SP"; + let Namespace = "Sparc"; } class SparcCtrlReg Enc, string n, list altNames = []>: Register { let HWEncoding = Enc; - let Namespace = "SP"; + let Namespace = "Sparc"; } -let Namespace = "SP" in { +let Namespace = "Sparc" in { def sub_even : SubRegIndex<32>; def sub_odd : SubRegIndex<32, 32>; def sub_even64 : SubRegIndex<64>; def sub_odd64 : SubRegIndex<64, 64>; } -let Namespace = "SP", +let Namespace = "Sparc", FallbackRegAltNameIndex = NoRegAltName in { def RegNamesStateReg : RegAltNameIndex; } diff --git a/llvm/utils/TableGen/PrinterCapstone.cpp b/llvm/utils/TableGen/PrinterCapstone.cpp index 3a7f0186a5f4..70a6a2c08ada 100644 --- a/llvm/utils/TableGen/PrinterCapstone.cpp +++ b/llvm/utils/TableGen/PrinterCapstone.cpp @@ -303,12 +303,12 @@ void PrinterCapstone::regInfoEmitRegUnitRoots( } static std::string getQualifiedNameCCS(const Record *R) { - std::string Namespace; + StringRef TargetName; if (R->getValue("Namespace")) - Namespace = std::string(R->getValueAsString("Namespace")); - if (Namespace.empty()) + TargetName = R->getValueAsString("Namespace"); + if (TargetName.empty()) return std::string(R->getName()); - return StringRef(Namespace).str() + "_" + R->getName().str(); + return TargetName.str() + "_" + R->getName().str(); } void PrinterCapstone::regInfoEmitRegClasses( @@ -1696,6 +1696,7 @@ void PrinterCapstone::asmWriterEmitRegAsmOffsets( void PrinterCapstone::asmWriterEmitAltIdxSwitch( bool HasAltNames, std::vector const &AltNameIndices, StringRef const &Namespace) const { + StringRef TargetName = Namespace; if (HasAltNames) { OS << " switch(AltIdx) {\n" << " default: CS_ASSERT_RET_VAL(0 && \"Invalid register alt name " @@ -1703,8 +1704,8 @@ void PrinterCapstone::asmWriterEmitAltIdxSwitch( for (const Record *R : AltNameIndices) { StringRef const AltName = R->getName(); OS << " case "; - if (!Namespace.empty()) - OS << Namespace << "_"; + if (!TargetName.empty()) + OS << TargetName << "_"; OS << AltName << ":\n"; if (R->isValueUnset("FallbackRegAltNameIndex")) OS << " CS_ASSERT_RET_VAL(*(AsmStrs" << AltName << "+RegAsmOffset" @@ -1714,8 +1715,8 @@ void PrinterCapstone::asmWriterEmitAltIdxSwitch( OS << " if (!*(AsmStrs" << AltName << "+RegAsmOffset" << AltName << "[RegNo-1]))\n" << " return getRegisterName(RegNo, "; - if (!Namespace.empty()) - OS << Namespace << "_"; + if (!TargetName.empty()) + OS << TargetName << "_"; OS << R->getValueAsDef("FallbackRegAltNameIndex")->getName() << ");\n"; } OS << " return AsmStrs" << AltName << "+RegAsmOffset" << AltName @@ -2520,7 +2521,8 @@ void PrinterCapstone::instrInfoEmitGetOpMemSizeTbl( std::string PrinterCapstone::instrInfoGetInstMapEntry(StringRef const &Namespace, StringRef const &InstrName) const { - return Namespace.str() + "_" + InstrName.str(); + StringRef TargetName = Namespace; + return TargetName.str() + "_" + InstrName.str(); } void PrinterCapstone::instrInfoEmitGetLogicalOpSizeHdr() const {} @@ -2602,11 +2604,12 @@ void PrinterCapstone::instrInfoEmitEnums( CodeGenTarget const &Target, StringRef const &Namespace, CodeGenSchedModels const &SchedModels) const { emitIncludeToggle("GET_INSTRINFO_ENUM", true); + StringRef TargetName = Namespace; unsigned Num = 0; OS << " enum {\n"; for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) - OS << " " << Namespace << "_" << Inst->TheDef->getName() + OS << " " << TargetName << "_" << Inst->TheDef->getName() << "\t= " << Num++ << ",\n"; OS << " INSTRUCTION_LIST_END = " << Num << "\n"; OS << " };\n\n"; From c7150a331ada84ac81d263b79f38baa97f05aaaa Mon Sep 17 00:00:00 2001 From: Rot127 Date: Wed, 7 May 2025 10:14:47 -0500 Subject: [PATCH 4/9] Add memory types and formats. --- llvm/lib/Target/Sparc/SparcInstrInfo.td | 9 ++++++ llvm/utils/TableGen/PrinterCapstone.cpp | 39 ++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td index 5e792427cca2..b4c4f0ac7bd7 100644 --- a/llvm/lib/Target/Sparc/SparcInstrInfo.td +++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td @@ -146,11 +146,13 @@ def MEMrr : Operand { let PrintMethod = "printMemOperand"; let MIOperandInfo = (ops ptr_rc, ptr_rc); let ParserMatchClass = SparcMEMrrAsmOperand; + let OperandType = "OPERAND_MEMORY"; } def MEMri : Operand { let PrintMethod = "printMemOperand"; let MIOperandInfo = (ops ptr_rc, i32imm); let ParserMatchClass = SparcMEMriAsmOperand; + let OperandType = "OPERAND_MEMORY"; } // Represents a tail relocation operand for instructions such as add, ld, call. @@ -200,14 +202,17 @@ def ASITag : Operand { // Branch targets have OtherVT type. def brtarget : Operand { let EncoderMethod = "getBranchTargetOpValue"; + let OperandType = "OPERAND_IMMEDIATE"; } def bprtarget : Operand { let EncoderMethod = "getBranchPredTargetOpValue"; + let OperandType = "OPERAND_IMMEDIATE"; } def bprtarget16 : Operand { let EncoderMethod = "getBranchOnRegTargetOpValue"; + let OperandType = "OPERAND_IMMEDIATE"; } def SparcCallTargetAsmOperand : AsmOperandClass { @@ -419,6 +424,7 @@ multiclass F3_12np Op3Val, InstrItinClass itin = IIC_iu_i itin>; } +let mayLoad = 1 in { // Load multiclass - Define both Reg+Reg/Reg+Imm patterns in one shot. multiclass Load Op3Val, SDPatternOperator OpNode, RegisterClass RC, ValueType Ty, InstrItinClass itin = IIC_iu_instr> { @@ -470,7 +476,9 @@ let Predicates = [HasV9], Uses = [ASR3] in def LDSTUBAri : F3_2<3, 0b011101, (outs IntRegs:$rd), (ins (MEMri $rs1, $simm13):$addr), "ldstuba [$addr] %asi, $rd", []>; +} +let mayStore = 1 in { // Store multiclass - Define both Reg+Reg/Reg+Imm patterns in one shot. multiclass Store Op3Val, SDPatternOperator OpNode, RegisterClass RC, ValueType Ty, InstrItinClass itin = IIC_st> { @@ -507,6 +515,7 @@ multiclass StoreA Op3Val, bits<6> StoreAOp3Val, Store { defm A : StoreASI; } +} //===----------------------------------------------------------------------===// // Instructions diff --git a/llvm/utils/TableGen/PrinterCapstone.cpp b/llvm/utils/TableGen/PrinterCapstone.cpp index 70a6a2c08ada..43e1dd94ceb5 100644 --- a/llvm/utils/TableGen/PrinterCapstone.cpp +++ b/llvm/utils/TableGen/PrinterCapstone.cpp @@ -2802,6 +2802,41 @@ std::string getArchSupplInfoPPC(StringRef const &TargetName, return "{{ 0 }}"; } +std::string getArchSupplInfoSparc(StringRef const &TargetName, + CodeGenInstruction const *CGI, + raw_string_ostream &SparcFormatEnum) { + static std::set Formats; + // Get instruction format + ArrayRef> SCs = CGI->TheDef->getSuperClasses(); + if (SCs.empty()) { + llvm_unreachable("A CGI without superclass should not exist."); + } + + // Get base instruction format class "I" + const Record *PrevSC = nullptr; + // Superclasses are in post-order. So we go through them backwards. + // The class before the "I" class is the format class. + for (int I = SCs.size() - 1; I >= 0; --I) { + const Record *SC = SCs[I].first; + if (SC->getName() == "InstSP" || SC->getName() == "F2" || SC->getName() == "F3" || SC->getName() == "F4") { + // In this case of !PrevSC the instruction inherits directly from InstSP. + // In code they document this is a FOMRAT 1 instruction. + // + // If SC->getName() == "F2...4" we emit the format as well. Because there are many + // F2/F3/F4 encodings, not just one. F2/F3/F4 are the base. + std::string Format = "SPARC_INSN_FORM_" + (!PrevSC ? "F1" : PrevSC->getName().upper()); + if (Formats.find(Format) == Formats.end()) { + SparcFormatEnum << Format + ",\n"; + } + Formats.emplace(Format); + return "{ .sparc = { " + Format + " }}"; + } + PrevSC = SC; + } + // Pseudo instructions + return "{{ 0 }}"; +} + std::string getArchSupplInfoSystemZ(StringRef const &TargetName, CodeGenInstruction const *CGI, raw_string_ostream &PPCFormatEnum) { @@ -2930,6 +2965,8 @@ std::string getArchSupplInfo(StringRef const &TargetName, return getArchSupplInfoSystemZ(TargetName, CGI, FormatEnum); } else if (StringRef(TargetName).upper() == "XTENSA") { return getArchSupplInfoXtensa(TargetName, CGI, FormatEnum); + } else if (StringRef(TargetName).upper() == "SPARC") { + return getArchSupplInfoSparc(TargetName, CGI, FormatEnum); } return "{{ 0 }}"; } @@ -3715,7 +3752,7 @@ void PrinterCapstone::asmMatcherEmitMatchTable(CodeGenTarget const &Target, InsnMapFilename = TName + "GenCSAliasMnemMap.inc"; writeFile(InsnMapFilename, AliasMnemMapStr); if (TName == "PPC" || TName == "LoongArch" || TName == "SystemZ" || - TName == "Xtensa") { + TName == "Xtensa" || TName == "Sparc") { InsnMapFilename = TName + "GenCSInsnFormatsEnum.inc"; writeFile(InsnMapFilename, FormatEnumStr); } From 5e1b6dd6ab45156f2c578f8754efc5efb9468066 Mon Sep 17 00:00:00 2001 From: Rot127 Date: Sat, 10 May 2025 09:40:36 -0500 Subject: [PATCH 5/9] Add disponent decoders. --- llvm/lib/Target/Sparc/SparcInstrInfo.td | 3 +++ 1 file changed, 3 insertions(+) diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td index b4c4f0ac7bd7..05b84c20a113 100644 --- a/llvm/lib/Target/Sparc/SparcInstrInfo.td +++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td @@ -202,16 +202,19 @@ def ASITag : Operand { // Branch targets have OtherVT type. def brtarget : Operand { let EncoderMethod = "getBranchTargetOpValue"; + let DecoderMethod = "DecodeDisp22"; let OperandType = "OPERAND_IMMEDIATE"; } def bprtarget : Operand { let EncoderMethod = "getBranchPredTargetOpValue"; + let DecoderMethod = "DecodeDisp19"; let OperandType = "OPERAND_IMMEDIATE"; } def bprtarget16 : Operand { let EncoderMethod = "getBranchOnRegTargetOpValue"; + let DecoderMethod = "DecodeDisp16"; let OperandType = "OPERAND_IMMEDIATE"; } From 00a0381b4ffd31072bf30e0e6dbb3d6b0ecb660d Mon Sep 17 00:00:00 2001 From: Rot127 Date: Sat, 10 May 2025 11:44:22 -0500 Subject: [PATCH 6/9] Add memory flag to CASA instructions. --- llvm/utils/TableGen/PrinterCapstone.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/utils/TableGen/PrinterCapstone.cpp b/llvm/utils/TableGen/PrinterCapstone.cpp index 43e1dd94ceb5..8aace5d24b4e 100644 --- a/llvm/utils/TableGen/PrinterCapstone.cpp +++ b/llvm/utils/TableGen/PrinterCapstone.cpp @@ -3131,9 +3131,9 @@ std::string getCSOperandType( std::map> const InsnPatternMap) { std::string OperandType = getPrimaryCSOperandType(OpRec); - if ((StringRef(TargetName).upper() == "AARCH64") && + if ((StringRef(TargetName).upper() == "AARCH64" || StringRef(TargetName).upper() == "SPARC") && OperandType != "CS_OP_MEM") { - // The definitions of AArch64 are so flawed, when it comes to memory + // The definitions of AArch64/Sparc are so flawed, when it comes to memory // operands (they are not labeled as such), that we just search for the op // name enclosed in []. if (Regex("\\[[^]]*\\$" + OpName.str() + "[^[]*]").match(CGI->AsmString)) { From be3aa1f07e046c1ede77c2d4e780ffe077a7d7ab Mon Sep 17 00:00:00 2001 From: Rot127 Date: Sun, 11 May 2025 07:11:23 -0500 Subject: [PATCH 7/9] Fix incorrect memory classificatin of simm14. --- llvm/utils/TableGen/PrinterCapstone.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/llvm/utils/TableGen/PrinterCapstone.cpp b/llvm/utils/TableGen/PrinterCapstone.cpp index 8aace5d24b4e..2953d4b22a4d 100644 --- a/llvm/utils/TableGen/PrinterCapstone.cpp +++ b/llvm/utils/TableGen/PrinterCapstone.cpp @@ -3125,6 +3125,11 @@ bool opIsPartOfiPTRPattern(Record const *OpRec, StringRef const &OpName, return false; } +/// Some operands are wrongly defined as iPTR or other markers we use to identify memory operands. +static inline bool wrongMemClassification(StringRef const &TargetName, StringRef const &OpName) { + return (TargetName.compare_insensitive("Sparc") == 0 && OpName.compare_insensitive("simm13") == 0); +} + std::string getCSOperandType( StringRef const &TargetName, CodeGenInstruction const *CGI, Record const *OpRec, StringRef const &OpName, @@ -3148,6 +3153,9 @@ std::string getCSOperandType( return OperandType += " | CS_OP_BOUND"; } } + if (wrongMemClassification(TargetName, OpName)) { + return OperandType; + } DagInit *PatternDag = nullptr; if (OperandType == "CS_OP_MEM") From b46d57407e2ec3919900c12d852a3345d8b0f4d7 Mon Sep 17 00:00:00 2001 From: Rot127 Date: Sat, 17 May 2025 13:43:42 -0500 Subject: [PATCH 8/9] Remove real BA instruction. --- llvm/lib/Target/Sparc/SparcInstrInfo.td | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td index 05b84c20a113..372addf495a7 100644 --- a/llvm/lib/Target/Sparc/SparcInstrInfo.td +++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td @@ -894,8 +894,7 @@ class BranchPredictAlways pattern> : F2_3<0b001, 0, 1, (outs), ins, asmstr, pattern>; } -let cond = 8 in - def BA : BranchAlways<(ins brtarget:$imm22), "ba $imm22", [(br bb:$imm22)]>; +// Capstone: Remove BA which is already correctly defined as Alias. let isBranch = 1, isTerminator = 1, hasDelaySlot = 1 in { From 18007e0743ce30bb0f9548bd1115e79989638fea Mon Sep 17 00:00:00 2001 From: Rot127 Date: Sat, 7 Jun 2025 06:10:53 -0500 Subject: [PATCH 9/9] Partially copy fix from llvm-project/#143232 --- llvm/lib/Target/Sparc/SparcInstrInfo.td | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.td b/llvm/lib/Target/Sparc/SparcInstrInfo.td index 372addf495a7..2114a76b388c 100644 --- a/llvm/lib/Target/Sparc/SparcInstrInfo.td +++ b/llvm/lib/Target/Sparc/SparcInstrInfo.td @@ -24,7 +24,8 @@ include "SparcInstrFormats.td" def Is32Bit : Predicate<"!Subtarget->is64Bit()">; // True when generating 64-bit code. This also implies HasV9. -def Is64Bit : Predicate<"Subtarget->is64Bit()">; +def Is64Bit : Predicate<"Subtarget->is64Bit()">, + AssemblerPredicate<(all_of FeatureV9)>; def UseSoftMulDiv : Predicate<"Subtarget->useSoftMulDiv()">, AssemblerPredicate<(all_of FeatureSoftMulDiv)>;