[llvm-branch-commits] [clang] [llvm] [AArch64][llvm] Armv9.8-A: Add support for FEAT_CFLT (Conditional Fault instructions) (PR #229362)
Jonathan Thackray via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Oct 9 03:13:01 PDT 2026
https://github.com/jthackray updated https://github.com/llvm/llvm-project/pull/229362
>From 7b29944f15b252eaef57657a75a6e8cb1afc981a Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Tue, 6 Oct 2026 21:45:34 +0100
Subject: [PATCH 1/2] [AArch64][llvm] Armv9.8-A: Add support for FEAT_CFLT
(Conditional Fault instructions)
Add support for FEAT_CFLT (Conditional Fault instructions), which
are optional from Armv9.7 onwards:
```
cflteq, cfltne,
cfltgt, cfltlt,
cfltge, cfltle,
cflthi, cfltlo,
cflths, cfltls,
cfltz, cfltnz,
tfltz, tfltnz,
flt.ne, flt.eq,
flt.mi, flt.pl,
flt.vs, flt.vc,
flt.hi, flt.ls,
flt.ge, flt.lt,
flt.gt, flt.le,
flt.al, flt.nv,
flt.cs, flt.cc,
flt.hs, flt.lo
```
Change-Id: I2bf0d806907158e804ff6610053aec8656ad6b92
---
clang/test/Driver/aarch64-v98a.c | 4 +
.../print-supported-extensions-aarch64.c | 1 +
llvm/lib/Target/AArch64/AArch64Features.td | 3 +
.../lib/Target/AArch64/AArch64InstrFormats.td | 140 ++++++++
llvm/lib/Target/AArch64/AArch64InstrInfo.td | 49 +++
.../AArch64/AsmParser/AArch64AsmParser.cpp | 45 ++-
.../Disassembler/AArch64Disassembler.cpp | 7 +
.../MC/AArch64/armv9.8a-cflt-diagnostics.s | 89 +++++
llvm/test/MC/AArch64/armv9.8a-cflt.s | 329 ++++++++++++++++++
.../test/MC/AArch64/directive-arch-negative.s | 6 +
llvm/test/MC/AArch64/directive-arch.s | 4 +
.../directive-arch_extension-negative.s | 6 +
.../MC/AArch64/directive-arch_extension.s | 4 +
.../TargetParser/TargetParserTest.cpp | 3 +
14 files changed, 679 insertions(+), 11 deletions(-)
create mode 100644 llvm/test/MC/AArch64/armv9.8a-cflt-diagnostics.s
create mode 100644 llvm/test/MC/AArch64/armv9.8a-cflt.s
diff --git a/clang/test/Driver/aarch64-v98a.c b/clang/test/Driver/aarch64-v98a.c
index b578c577d00a17..8427b2b4aa2539 100644
--- a/clang/test/Driver/aarch64-v98a.c
+++ b/clang/test/Driver/aarch64-v98a.c
@@ -17,3 +17,7 @@
// GENERICV98A-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.8a"{{.*}} "-target-feature" "+fprcvt"{{.*}} "-target-feature" "+sve2p3"{{.*}}
// ===== Features supported on aarch64 =====
+//
+// RUN: %clang -target aarch64 -march=armv9.8a+cflt -### -c %s 2>&1 | FileCheck -check-prefix=V98A-CFLT %s
+// RUN: %clang -target aarch64 -march=armv9.8-a+cflt -### -c %s 2>&1 | FileCheck -check-prefix=V98A-CFLT %s
+// V98A-CFLT: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.8a"{{.*}} "-target-feature" "+cflt"
diff --git a/clang/test/Driver/print-supported-extensions-aarch64.c b/clang/test/Driver/print-supported-extensions-aarch64.c
index 1e2882550c81fa..a57fff693eec45 100644
--- a/clang/test/Driver/print-supported-extensions-aarch64.c
+++ b/clang/test/Driver/print-supported-extensions-aarch64.c
@@ -9,6 +9,7 @@
// CHECK-NEXT: brbe FEAT_BRBE Enable Branch Record Buffer Extension
// CHECK-NEXT: bti FEAT_BTI Enable Branch Target Identification
// CHECK-NEXT: btie FEAT_BTIE Enable Enhanced Branch Target Identification extension
+// CHECK-NEXT: cflt FEAT_CFLT Enable Armv9.8-A Conditional Fault instructions
// CHECK-NEXT: cmpbr FEAT_CMPBR Enable Armv9.6-A base compare and branch instructions
// CHECK-NEXT: fcma FEAT_FCMA Enable Armv8.3-A Floating-point complex number support
// CHECK-NEXT: cpa FEAT_CPA Enable Armv9.5-A Checked Pointer Arithmetic
diff --git a/llvm/lib/Target/AArch64/AArch64Features.td b/llvm/lib/Target/AArch64/AArch64Features.td
index cda947c1bbea0b..fd1db78da1773c 100644
--- a/llvm/lib/Target/AArch64/AArch64Features.td
+++ b/llvm/lib/Target/AArch64/AArch64Features.td
@@ -621,6 +621,9 @@ def FeatureF16F32MM : ExtensionWithMArch<"f16f32mm", "F16F32MM", "FEAT_F16F32MM"
// Armv9.8 Architecture Extensions
//===----------------------------------------------------------------------===//
+def FeatureCFLT : ExtensionWithMArch<"cflt", "CFLT", "FEAT_CFLT",
+ "Enable Armv9.8-A Conditional Fault instructions">;
+
//===----------------------------------------------------------------------===//
// Future Architecture Technologies
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index fc603c2d59240f..7bdfd59f328347 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -522,6 +522,44 @@ def uimm6m1_64b : Operand<i64> {
let OperandType = "OPERAND_IMMEDIATE";
}
+def uimm9 : Operand<i64> {
+ let ParserMatchClass = AsmImmRange<0, 511>;
+ let OperandType = "OPERAND_IMMEDIATE";
+}
+
+class AdjImmAsmOperand<string name, string diagnostic, int adjustment,
+ int low, int high> : AsmOperandClass {
+ let Name = name;
+ let DiagnosticType = diagnostic;
+ let RenderMethod = "addAdjImmOperands<" # adjustment # ">";
+ let PredicateMethod = "isImmInRange<" # !sub(low, adjustment) # "," #
+ !sub(high, adjustment) # ">";
+}
+
+def uimm9p1 : Operand<i64> {
+ let ParserMatchClass =
+ AdjImmAsmOperand<"UImm9P1", "InvalidImm1_512", -1, 0, 511>;
+ let OperandType = "OPERAND_IMMEDIATE";
+}
+
+def uimm9m1 : Operand<i64> {
+ let ParserMatchClass =
+ AdjImmAsmOperand<"UImm9M1", "InvalidImmM1_510", 1, 0, 511>;
+ let OperandType = "OPERAND_IMMEDIATE";
+}
+
+def simm9p1 : Operand<i64> {
+ let ParserMatchClass =
+ AdjImmAsmOperand<"SImm9P1", "InvalidImmM255_256", -1, -256, 255>;
+ let OperandType = "OPERAND_IMMEDIATE";
+}
+
+def simm9m1 : Operand<i64> {
+ let ParserMatchClass =
+ AdjImmAsmOperand<"SImm9M1", "InvalidImmM257_254", 1, -256, 255>;
+ let OperandType = "OPERAND_IMMEDIATE";
+}
+
def SImm9Operand : SImmOperand<9>;
def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
let ParserMatchClass = SImm9Operand;
@@ -13658,3 +13696,105 @@ multiclass TEXIT<string asm> {
def NAME : TEXITInst<asm>;
def : InstAlias<asm, (!cast<Instruction>(NAME) 0), 1>;
}
+
+//----------------------------------------------------------------------------
+// Conditional Fault instructions (FEAT_CFLT)
+//----------------------------------------------------------------------------
+
+class BaseCondFLT
+ : I<(outs), (ins ccode:$cond, uimm16:$imm),
+ "flt", ".$cond\t$imm", "", []>, Sched<[]> {
+ bits<4> cond;
+ bits<16> imm;
+ let Inst{31-21} = 0b11010100001;
+ let Inst{20-5} = imm;
+ let Inst{4} = 1;
+ let Inst{3-0} = cond;
+
+ let Uses = [NZCV];
+}
+
+class BaseFLT<bit sf, dag iops, string asm, string operands>
+ : I<(outs), iops, asm, operands, "", []>, Sched<[]> {
+ bits<2> reason;
+ bits<5> Rt;
+ let Inst{31} = sf;
+ let Inst{30-24} = 0b1110110;
+ let Inst{15-12} = 0b0000;
+ let Inst{11-10} = reason;
+ let Inst{4-0} = Rt;
+}
+
+class BaseCFLTImm<RegisterClass regtype, bit sf, Operand immtype,
+ bits<3> cc, string asm>
+ : BaseFLT<sf, (ins imm0_3:$reason, regtype:$Rt, immtype:$imm),
+ asm, "\t$reason, $Rt, $imm"> {
+ bits<9> imm;
+ let Inst{23-21} = cc;
+ let Inst{20-16} = imm{8-4};
+ let Inst{9} = 0;
+ let Inst{8-5} = imm{3-0};
+}
+
+class BaseCFLTReg<RegisterClass regtype, bit sf, bits<3> cc, string asm>
+ : BaseFLT<sf, (ins imm0_3:$reason, regtype:$Rt, regtype:$Rm),
+ asm, "\t$reason, $Rt, $Rm"> {
+ bits<5> Rm;
+ let Inst{23-21} = cc;
+ let Inst{20-16} = Rm;
+ let Inst{9-5} = 0b10000;
+}
+
+multiclass CFLTImm<bits<3> cc, string asm, Operand immtype> {
+ def Wi : BaseCFLTImm<GPR32, 0, immtype, cc, asm>;
+ def Xi : BaseCFLTImm<GPR64, 1, immtype, cc, asm>;
+}
+
+multiclass CFLTReg<bits<3> cc, string asm> {
+ def Wr : BaseCFLTReg<GPR32sp, 0, cc, asm>;
+ def Xr : BaseCFLTReg<GPR64sp, 1, cc, asm>;
+}
+
+multiclass CFLTRegAlias<string mnemonic, string inst> {
+ def : InstAlias<mnemonic # "\t$reason, $Rm, $Rt",
+ (!cast<Instruction>(inst # "Wr") imm0_3:$reason,
+ GPR32sp:$Rt, GPR32sp:$Rm), 0>;
+ def : InstAlias<mnemonic # "\t$reason, $Rm, $Rt",
+ (!cast<Instruction>(inst # "Xr") imm0_3:$reason,
+ GPR64sp:$Rt, GPR64sp:$Rm), 0>;
+}
+
+multiclass CFLTImmAlias<string mnemonic, string inst, Operand immtype> {
+ def : InstAlias<mnemonic # "\t$reason, $Rt, $imm",
+ (!cast<Instruction>(inst # "Wi") imm0_3:$reason,
+ GPR32:$Rt, immtype:$imm), 0>;
+ def : InstAlias<mnemonic # "\t$reason, $Rt, $imm",
+ (!cast<Instruction>(inst # "Xi") imm0_3:$reason,
+ GPR64:$Rt, immtype:$imm), 0>;
+}
+
+def tflt_imm32_63 : Operand<i64> {
+ let ParserMatchClass = TBZImm32_63Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
+ let DecoderMethod = "DecodeTFLTImm32_63";
+}
+
+class BaseTFLT<RegisterClass regtype, Operand immtype, bit sf, bit op,
+ string asm>
+ : BaseFLT<sf, (ins imm0_3:$reason, regtype:$Rt, immtype:$bit_off),
+ asm, "\t$reason, $Rt, $bit_off"> {
+ bits<6> bit_off;
+ let Inst{23-19} = bit_off{4-0};
+ let Inst{18-16} = 0b000;
+ let Inst{9-6} = 0b1001;
+ let Inst{5} = op;
+}
+
+multiclass TFLT<bit op, string asm> {
+ def W : BaseTFLT<GPR32, tbz_imm0_31_diag, 0, op, asm>;
+ def X : BaseTFLT<GPR64, tflt_imm32_63, 1, op, asm>;
+
+ def : InstAlias<asm # "\t$reason, $Rt, $imm",
+ (!cast<Instruction>(NAME # "W") imm0_3:$reason,
+ GPR32as64:$Rt, tbz_imm0_31_nodiag:$imm), 0>;
+}
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index a23250d4e1d4e6..16131190410e86 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -237,6 +237,8 @@ def HasF16F32DOT : Predicate<"Subtarget->hasF16F32DOT()">,
AssemblerPredicateWithAll<(all_of FeatureF16F32DOT), "f16f32dot">;
def HasF16F32MM : Predicate<"Subtarget->hasF16F32MM()">,
AssemblerPredicateWithAll<(all_of FeatureF16F32MM), "f16f32mm">;
+def HasCFLT : Predicate<"Subtarget->hasCFLT()">,
+ AssemblerPredicateWithAll<(all_of FeatureCFLT), "cflt">;
// A subset of SVE(2) instructions are legal in Streaming SVE execution mode,
// they should be enabled if either has been specified.
@@ -12756,6 +12758,53 @@ let Predicates = [HasTEV] in {
defm TEXIT : TEXIT<"texit">;
}
+//===-----------------------------------------------------===//
+// Conditional Fault instructions (FEAT_CFLT)
+//===-----------------------------------------------------===//
+let Predicates = [HasCFLT] in {
+ def FLTcc : BaseCondFLT;
+
+ defm CFLTEQ : CFLTReg<0b110, "cflteq">;
+ defm CFLTEQ : CFLTImm<0b100, "cflteq", simm9>;
+
+ defm CFLTNE : CFLTReg<0b111, "cfltne">;
+ defm CFLTNE : CFLTImm<0b101, "cfltne", simm9>;
+
+ defm CFLTGT : CFLTReg<0b000, "cfltgt">;
+ defm CFLTGT : CFLTImm<0b000, "cfltgt", simm9>;
+
+ defm CFLTGE : CFLTReg<0b001, "cfltge">;
+ defm CFLTLT : CFLTImm<0b001, "cfltlt", simm9>;
+
+ defm CFLTHI : CFLTReg<0b010, "cflthi">;
+ defm CFLTHI : CFLTImm<0b010, "cflthi", uimm9>;
+
+ defm CFLTHS : CFLTReg<0b011, "cflths">;
+ defm CFLTLO : CFLTImm<0b011, "cfltlo", uimm9>;
+
+ defm : CFLTImmAlias<"cfltge", "CFLTGT", simm9p1>;
+ defm : CFLTImmAlias<"cflths", "CFLTHI", uimm9p1>;
+ defm : CFLTImmAlias<"cfltle", "CFLTLT", simm9m1>;
+ defm : CFLTImmAlias<"cfltls", "CFLTLO", uimm9m1>;
+
+ defm : CFLTRegAlias<"cfltle", "CFLTGE">;
+ defm : CFLTRegAlias<"cfltlo", "CFLTHI">;
+ defm : CFLTRegAlias<"cfltls", "CFLTHS">;
+ defm : CFLTRegAlias<"cfltlt", "CFLTGT">;
+
+ def : InstAlias<"cfltnz\t$reason, $Rt",
+ (CFLTNEWi imm0_3:$reason, GPR32:$Rt, 0), 0>;
+ def : InstAlias<"cfltnz\t$reason, $Rt",
+ (CFLTNEXi imm0_3:$reason, GPR64:$Rt, 0), 0>;
+ def : InstAlias<"cfltz\t$reason, $Rt",
+ (CFLTEQWi imm0_3:$reason, GPR32:$Rt, 0), 0>;
+ def : InstAlias<"cfltz\t$reason, $Rt",
+ (CFLTEQXi imm0_3:$reason, GPR64:$Rt, 0), 0>;
+
+ defm TFLTZ : TFLT<0, "tfltz">;
+ defm TFLTNZ : TFLT<1, "tfltnz">;
+}
+
include "AArch64InstrAtomics.td"
include "AArch64SVEInstrInfo.td"
include "AArch64SMEInstrInfo.td"
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index b2928485d46add..8e9e9c33882a4b 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -1932,6 +1932,12 @@ class AArch64Operand : public MCParsedAsmOperand {
addExpr(Inst, getImm());
}
+ template <int Adj> void addAdjImmOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ int64_t Imm = cast<MCConstantExpr>(getImm())->getValue();
+ Inst.addOperand(MCOperand::createImm(Imm + Adj));
+ }
+
template <int Shift>
void addImmWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
assert(N == 2 && "Invalid number of operands!");
@@ -3757,6 +3763,7 @@ constexpr EnumStringDef<FeatureBitset> ExtensionDefs[] = {
{{"pauth-lr"}, {AArch64::FeaturePAuthLR}},
{{"ssve-fexpa"}, {AArch64::FeatureSSVE_FEXPA}},
{{"wfxt"}, {AArch64::FeatureWFxT}},
+ {{"cflt"}, {AArch64::FeatureCFLT}},
};
constexpr auto ExtensionMap = BUILD_ENUM_STRINGS(ExtensionDefs);
@@ -5309,8 +5316,9 @@ bool AArch64AsmParser::parseInstruction(ParseInstructionInfo &Info,
Operands.push_back(AArch64Operand::CreateToken(Head, NameLoc, getContext()));
Mnemonic = Head;
- // Handle condition codes for a branch mnemonic
- if ((Head == "b" || Head == "bc") && Next != StringRef::npos) {
+ // Handle condition codes for a branch or fault mnemonic.
+ if ((Head == "b" || Head == "bc" || Head == "flt") &&
+ Next != StringRef::npos) {
Start = Next;
Next = Name.find('.', Start + 1);
Head = Name.slice(Start + 1, Next);
@@ -6091,6 +6099,8 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
return Error(Loc, "immediate must be an integer in range [0, 127].");
case Match_InvalidImm0_255:
return Error(Loc, "immediate must be an integer in range [0, 255].");
+ case Match_InvalidImm0_511:
+ return Error(Loc, "immediate must be an integer in range [0, 511].");
case Match_InvalidImm0_65535:
return Error(Loc, "immediate must be an integer in range [0, 65535].");
case Match_InvalidHinteUImm16:
@@ -6106,8 +6116,16 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
return Error(Loc, "immediate must be an integer in range [1, 32].");
case Match_InvalidImm1_64:
return Error(Loc, "immediate must be an integer in range [1, 64].");
+ case Match_InvalidImm1_512:
+ return Error(Loc, "immediate must be an integer in range [1, 512].");
case Match_InvalidImmM1_62:
return Error(Loc, "immediate must be an integer in range [-1, 62].");
+ case Match_InvalidImmM1_510:
+ return Error(Loc, "immediate must be an integer in range [-1, 510].");
+ case Match_InvalidImmM255_256:
+ return Error(Loc, "immediate must be an integer in range [-255, 256].");
+ case Match_InvalidImmM257_254:
+ return Error(Loc, "immediate must be an integer in range [-257, 254].");
case Match_InvalidMemoryIndexedRange2UImm0:
return Error(Loc, "vector select offset must be the immediate range 0:1.");
case Match_InvalidMemoryIndexedRange2UImm1:
@@ -6879,13 +6897,18 @@ bool AArch64AsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_InvalidImm0_63:
case Match_InvalidImm0_127:
case Match_InvalidImm0_255:
+ case Match_InvalidImm0_511:
case Match_InvalidImm0_65535:
case Match_InvalidHinteUImm16:
case Match_InvalidImm1_8:
case Match_InvalidImm1_16:
case Match_InvalidImm1_32:
case Match_InvalidImm1_64:
+ case Match_InvalidImm1_512:
case Match_InvalidImmM1_62:
+ case Match_InvalidImmM1_510:
+ case Match_InvalidImmM255_256:
+ case Match_InvalidImmM257_254:
case Match_InvalidMemoryIndexedRange2UImm0:
case Match_InvalidMemoryIndexedRange2UImm1:
case Match_InvalidMemoryIndexedRange2UImm2:
@@ -7050,6 +7073,11 @@ bool AArch64AsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_MRS: {
if (ErrorInfo >= Operands.size())
return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
+ // CFLT has both register and immediate forms. The matcher may select an
+ // immediate-form failure for an invalid register operand.
+ if (Tok.starts_with("cflt") &&
+ static_cast<AArch64Operand &>(*Operands[ErrorInfo]).isScalarReg())
+ MatchResult = Match_InvalidOperand;
// Any time we get here, there's nothing fancy to do. Just get the
// operand SMLoc and display the diagnostic.
SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
@@ -8772,18 +8800,13 @@ ParseStatus AArch64AsmParser::tryParseAdjImm0_63(OperandVector &Operands) {
SMLoc S = getLoc();
parseOptionalToken(AsmToken::Hash);
- bool IsNegative = parseOptionalToken(AsmToken::Minus);
- if (getTok().isNot(AsmToken::Integer))
+ if (getTok().isNot(AsmToken::Integer) && getTok().isNot(AsmToken::Minus))
return ParseStatus::NoMatch;
- const MCExpr *Ex;
- if (getParser().parseExpression(Ex))
- return ParseStatus::NoMatch;
-
- int64_t Imm = dyn_cast<MCConstantExpr>(Ex)->getValue();
- if (IsNegative)
- Imm = -Imm;
+ int64_t Imm;
+ if (parseImmExpr(Imm))
+ return ParseStatus::Failure;
// We want an adjusted immediate in the range [0, 63]. If we don't have one,
// return a value, which is certain to trigger a error message about invalid
diff --git a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
index e7820f7d6c5b13..0dbfb5e50013e9 100644
--- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
+++ b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
@@ -1356,6 +1356,13 @@ static DecodeStatus DecodeTestAndBranch(MCInst &Inst, uint32_t insn,
return Success;
}
+static DecodeStatus DecodeTFLTImm32_63(MCInst &Inst, unsigned Imm,
+ uint64_t Addr,
+ const MCDisassembler *Decoder) {
+ Inst.addOperand(MCOperand::createImm(Imm | 0x20));
+ return Success;
+}
+
static DecodeStatus
DecodeGPRSeqPairsClassRegisterClass(MCInst &Inst, unsigned RegClassID,
unsigned RegNo, uint64_t Addr,
diff --git a/llvm/test/MC/AArch64/armv9.8a-cflt-diagnostics.s b/llvm/test/MC/AArch64/armv9.8a-cflt-diagnostics.s
new file mode 100644
index 00000000000000..d4ab13432d7f15
--- /dev/null
+++ b/llvm/test/MC/AArch64/armv9.8a-cflt-diagnostics.s
@@ -0,0 +1,89 @@
+// RUN: not llvm-mc -triple=aarch64 -mattr=+cflt -show-encoding < %s 2>&1 \
+// RUN: | FileCheck %s
+
+flt.me #0
+// CHECK: [[@LINE-1]]:5: error: invalid condition code
+
+flt.eq #65536
+// CHECK: [[@LINE-1]]:8: error: immediate must be an integer in range [0, 65535].
+
+cflteq #0, wsp, #0
+// CHECK: [[@LINE-1]]:17: error: invalid operand for instruction
+
+cflteq #0, sp, #0
+// CHECK: [[@LINE-1]]:16: error: invalid operand for instruction
+
+cflteq #4, w0, #1
+// CHECK: [[@LINE-1]]:8: error: immediate must be an integer in range [0, 3].
+
+cfltgt #0, w0, #-257
+// CHECK: [[@LINE-1]]:16: error: index must be an integer in range [-256, 255].
+
+cfltgt #0, w0, #256
+// CHECK: [[@LINE-1]]:16: error: index must be an integer in range [-256, 255].
+
+cflthi #0, w0, #-1
+// CHECK: [[@LINE-1]]:16: error: immediate must be an integer in range [0, 511].
+
+cflthi #0, w0, #512
+// CHECK: [[@LINE-1]]:16: error: immediate must be an integer in range [0, 511].
+
+cfltge #0, w0, #-256
+// CHECK: [[@LINE-1]]:16: error: immediate must be an integer in range [-255, 256].
+
+cfltge #0, w0, #257
+// CHECK: [[@LINE-1]]:16: error: immediate must be an integer in range [-255, 256].
+
+cflths #0, w0, #0
+// CHECK: [[@LINE-1]]:16: error: immediate must be an integer in range [1, 512].
+
+cflths #0, w0, #513
+// CHECK: [[@LINE-1]]:16: error: immediate must be an integer in range [1, 512].
+
+cfltle #0, w0, #-258
+// CHECK: [[@LINE-1]]:16: error: immediate must be an integer in range [-257, 254].
+
+cfltle #0, w0, #255
+// CHECK: [[@LINE-1]]:16: error: immediate must be an integer in range [-257, 254].
+
+cfltls #0, w0, #-2
+// CHECK: [[@LINE-1]]:16: error: immediate must be an integer in range [-1, 510].
+
+cfltls #0, w0, #511
+// CHECK: [[@LINE-1]]:16: error: immediate must be an integer in range [-1, 510].
+
+cfltlo #0, w0, #-1
+// CHECK: [[@LINE-1]]:16: error: immediate must be an integer in range [0, 511].
+
+cfltlo #0, w0, #512
+// CHECK: [[@LINE-1]]:16: error: immediate must be an integer in range [0, 511].
+
+cflteq #0, wzr, w0
+// CHECK: [[@LINE-1]]:17: error: invalid operand for instruction
+
+cflteq #0, xzr, x0
+// CHECK: [[@LINE-1]]:17: error: invalid operand for instruction
+
+cflteq #0, w0, wzr
+// CHECK: [[@LINE-1]]:16: error: invalid operand for instruction
+
+cflteq #0, x0, xzr
+// CHECK: [[@LINE-1]]:16: error: invalid operand for instruction
+
+cfltz #0, wsp
+// CHECK: [[@LINE-1]]:11: error: invalid operand for instruction
+
+cfltnz #0, sp
+// CHECK: [[@LINE-1]]:12: error: invalid operand for instruction
+
+tfltz #4, w0, #0
+// CHECK: [[@LINE-1]]:7: error: immediate must be an integer in range [0, 3].
+
+tfltz #0, w0, #32
+// CHECK: [[@LINE-1]]:15: error: immediate must be an integer in range [0, 31].
+
+tfltnz #4, x0, #32
+// CHECK: [[@LINE-1]]:8: error: immediate must be an integer in range [0, 3].
+
+tfltnz #0, x0, #64
+// CHECK: [[@LINE-1]]:16: error: immediate must be an integer in range [0, 63].
diff --git a/llvm/test/MC/AArch64/armv9.8a-cflt.s b/llvm/test/MC/AArch64/armv9.8a-cflt.s
new file mode 100644
index 00000000000000..8a648037542450
--- /dev/null
+++ b/llvm/test/MC/AArch64/armv9.8a-cflt.s
@@ -0,0 +1,329 @@
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+cflt < %s \
+// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \
+// RUN: | FileCheck %s --check-prefix=CHECK-ERROR
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+cflt < %s \
+// RUN: | llvm-objdump -d --mattr=+cflt --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+cflt < %s \
+// RUN: | llvm-objdump -d --mattr=-cflt --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-UNKNOWN
+// Disassemble encoding and check the re-encoding (-show-encoding) matches.
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+cflt < %s \
+// RUN: | sed '/.text/d' | sed 's/.*encoding: //g' \
+// RUN: | llvm-mc -triple=aarch64 -mattr=+cflt -disassemble -show-encoding \
+// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+
+//------------------------------------------------------------------------------
+// Conditional Fault instructions (FEAT_CFLT)
+//------------------------------------------------------------------------------
+
+flt.eq #0
+// CHECK-INST: flt.eq #0
+// CHECK-ENCODING: [0x10,0x00,0x20,0xd4]
+// CHECK-UNKNOWN: d4200010
+// CHECK-ERROR: error: instruction requires: cflt
+
+flt.ne #1
+// CHECK-INST: flt.ne #1
+// CHECK-ENCODING: [0x31,0x00,0x20,0xd4]
+// CHECK-UNKNOWN: d4200031
+// CHECK-ERROR: error: instruction requires: cflt
+
+flt.cs #2
+// CHECK-INST: flt.hs #2
+// CHECK-ENCODING: [0x52,0x00,0x20,0xd4]
+// CHECK-UNKNOWN: d4200052
+// CHECK-ERROR: error: instruction requires: cflt
+
+flt.hs #2
+// CHECK-INST: flt.hs #2
+// CHECK-ENCODING: [0x52,0x00,0x20,0xd4]
+// CHECK-UNKNOWN: d4200052
+// CHECK-ERROR: error: instruction requires: cflt
+
+flt.cc #3
+// CHECK-INST: flt.lo #3
+// CHECK-ENCODING: [0x73,0x00,0x20,0xd4]
+// CHECK-UNKNOWN: d4200073
+// CHECK-ERROR: error: instruction requires: cflt
+
+flt.lo #3
+// CHECK-INST: flt.lo #3
+// CHECK-ENCODING: [0x73,0x00,0x20,0xd4]
+// CHECK-UNKNOWN: d4200073
+// CHECK-ERROR: error: instruction requires: cflt
+
+flt.mi #4
+// CHECK-INST: flt.mi #4
+// CHECK-ENCODING: [0x94,0x00,0x20,0xd4]
+// CHECK-UNKNOWN: d4200094
+// CHECK-ERROR: error: instruction requires: cflt
+
+flt.pl #5
+// CHECK-INST: flt.pl #5
+// CHECK-ENCODING: [0xb5,0x00,0x20,0xd4]
+// CHECK-UNKNOWN: d42000b5
+// CHECK-ERROR: error: instruction requires: cflt
+
+flt.vs #6
+// CHECK-INST: flt.vs #6
+// CHECK-ENCODING: [0xd6,0x00,0x20,0xd4]
+// CHECK-UNKNOWN: d42000d6
+// CHECK-ERROR: error: instruction requires: cflt
+
+flt.vc #7
+// CHECK-INST: flt.vc #7
+// CHECK-ENCODING: [0xf7,0x00,0x20,0xd4]
+// CHECK-UNKNOWN: d42000f7
+// CHECK-ERROR: error: instruction requires: cflt
+
+flt.hi #8
+// CHECK-INST: flt.hi #8
+// CHECK-ENCODING: [0x18,0x01,0x20,0xd4]
+// CHECK-UNKNOWN: d4200118
+// CHECK-ERROR: error: instruction requires: cflt
+
+flt.ls #9
+// CHECK-INST: flt.ls #9
+// CHECK-ENCODING: [0x39,0x01,0x20,0xd4]
+// CHECK-UNKNOWN: d4200139
+// CHECK-ERROR: error: instruction requires: cflt
+
+flt.ge #10
+// CHECK-INST: flt.ge #10
+// CHECK-ENCODING: [0x5a,0x01,0x20,0xd4]
+// CHECK-UNKNOWN: d420015a
+// CHECK-ERROR: error: instruction requires: cflt
+
+flt.lt #11
+// CHECK-INST: flt.lt #11
+// CHECK-ENCODING: [0x7b,0x01,0x20,0xd4]
+// CHECK-UNKNOWN: d420017b
+// CHECK-ERROR: error: instruction requires: cflt
+
+flt.gt #12
+// CHECK-INST: flt.gt #12
+// CHECK-ENCODING: [0x9c,0x01,0x20,0xd4]
+// CHECK-UNKNOWN: d420019c
+// CHECK-ERROR: error: instruction requires: cflt
+
+flt.le #13
+// CHECK-INST: flt.le #13
+// CHECK-ENCODING: [0xbd,0x01,0x20,0xd4]
+// CHECK-UNKNOWN: d42001bd
+// CHECK-ERROR: error: instruction requires: cflt
+
+flt.al #65535
+// CHECK-INST: flt.al #65535
+// CHECK-ENCODING: [0xfe,0xff,0x3f,0xd4]
+// CHECK-UNKNOWN: d43ffffe
+// CHECK-ERROR: error: instruction requires: cflt
+
+flt.nv #15
+// CHECK-INST: flt.nv #15
+// CHECK-ENCODING: [0xff,0x01,0x20,0xd4]
+// CHECK-UNKNOWN: d42001ff
+// CHECK-ERROR: error: instruction requires: cflt
+
+// CFLT<cc> (immediate).
+
+cflteq #0, w0, #1
+// CHECK-INST: cflteq #0, w0, #1
+// CHECK-ENCODING: [0x20,0x00,0x80,0x76]
+// CHECK-UNKNOWN: 76800020
+// CHECK-ERROR: error: instruction requires: cflt
+
+cfltne #3, x3, #-1
+// CHECK-INST: cfltne #3, x3, #-1
+// CHECK-ENCODING: [0xe3,0x0d,0xbf,0xf6]
+// CHECK-UNKNOWN: f6bf0de3
+// CHECK-ERROR: error: instruction requires: cflt
+
+cfltgt #0, w4, #-256
+// CHECK-INST: cfltgt #0, w4, #-256
+// CHECK-ENCODING: [0x04,0x00,0x10,0x76]
+// CHECK-UNKNOWN: 76100004
+// CHECK-ERROR: error: instruction requires: cflt
+
+cfltlt #3, x7, #0
+// CHECK-INST: cfltlt #3, x7, #0
+// CHECK-ENCODING: [0x07,0x0c,0x20,0xf6]
+// CHECK-UNKNOWN: f6200c07
+// CHECK-ERROR: error: instruction requires: cflt
+
+cflthi #1, x9, #511
+// CHECK-INST: cflthi #1, x9, #511
+// CHECK-ENCODING: [0xe9,0x05,0x5f,0xf6]
+// CHECK-UNKNOWN: f65f05e9
+// CHECK-ERROR: error: instruction requires: cflt
+
+cfltlo #2, w10, #1
+// CHECK-INST: cfltlo #2, w10, #1
+// CHECK-ENCODING: [0x2a,0x08,0x60,0x76]
+// CHECK-UNKNOWN: 7660082a
+// CHECK-ERROR: error: instruction requires: cflt
+
+// CFLT<cc> (immediate) aliases.
+
+cfltge #0, x0, #(2 - 1)
+// CHECK-INST: cfltgt #0, x0, #0
+// CHECK-ENCODING: [0x00,0x00,0x00,0xf6]
+// CHECK-UNKNOWN: f6000000
+// CHECK-ERROR: error: instruction requires: cflt
+
+cfltge #1, x13, #256
+// CHECK-INST: cfltgt #1, x13, #255
+// CHECK-ENCODING: [0xed,0x05,0x0f,0xf6]
+// CHECK-UNKNOWN: f60f05ed
+// CHECK-ERROR: error: instruction requires: cflt
+
+cflths #2, w14, #1
+// CHECK-INST: cflthi #2, w14, #0
+// CHECK-ENCODING: [0x0e,0x08,0x40,0x76]
+// CHECK-UNKNOWN: 7640080e
+// CHECK-ERROR: error: instruction requires: cflt
+
+cflths #2, w14, #+1
+// CHECK-INST: cflthi #2, w14, #0
+// CHECK-ENCODING: [0x0e,0x08,0x40,0x76]
+// CHECK-UNKNOWN: 7640080e
+// CHECK-ERROR: error: instruction requires: cflt
+
+cfltle #0, w16, #-257
+// CHECK-INST: cfltlt #0, w16, #-256
+// CHECK-ENCODING: [0x10,0x00,0x30,0x76]
+// CHECK-UNKNOWN: 76300010
+// CHECK-ERROR: error: instruction requires: cflt
+
+cfltle #0, w16, #(-257)
+// CHECK-INST: cfltlt #0, w16, #-256
+// CHECK-ENCODING: [0x10,0x00,0x30,0x76]
+// CHECK-UNKNOWN: 76300010
+// CHECK-ERROR: error: instruction requires: cflt
+
+cfltls #3, x19, #510
+// CHECK-INST: cfltlo #3, x19, #511
+// CHECK-ENCODING: [0xf3,0x0d,0x7f,0xf6]
+// CHECK-UNKNOWN: f67f0df3
+// CHECK-ERROR: error: instruction requires: cflt
+
+// CFLT<cc> (register).
+
+cflteq #0, w0, wsp
+// CHECK-INST: cflteq #0, w0, wsp
+// CHECK-ENCODING: [0x00,0x02,0xdf,0x76]
+// CHECK-UNKNOWN: 76df0200
+// CHECK-ERROR: error: instruction requires: cflt
+
+cfltne #3, x3, x4
+// CHECK-INST: cfltne #3, x3, x4
+// CHECK-ENCODING: [0x03,0x0e,0xe4,0xf6]
+// CHECK-UNKNOWN: f6e40e03
+// CHECK-ERROR: error: instruction requires: cflt
+
+cfltgt #0, w4, w5
+// CHECK-INST: cfltgt #0, w4, w5
+// CHECK-ENCODING: [0x04,0x02,0x05,0x76]
+// CHECK-UNKNOWN: 76050204
+// CHECK-ERROR: error: instruction requires: cflt
+
+cfltge #3, x7, x8
+// CHECK-INST: cfltge #3, x7, x8
+// CHECK-ENCODING: [0x07,0x0e,0x28,0xf6]
+// CHECK-UNKNOWN: f6280e07
+// CHECK-ERROR: error: instruction requires: cflt
+
+cflthi #0, w8, w9
+// CHECK-INST: cflthi #0, w8, w9
+// CHECK-ENCODING: [0x08,0x02,0x49,0x76]
+// CHECK-UNKNOWN: 76490208
+// CHECK-ERROR: error: instruction requires: cflt
+
+cflths #3, x11, x12
+// CHECK-INST: cflths #3, x11, x12
+// CHECK-ENCODING: [0x0b,0x0e,0x6c,0xf6]
+// CHECK-UNKNOWN: f66c0e0b
+// CHECK-ERROR: error: instruction requires: cflt
+
+// CFLT<cc> (register) aliases.
+
+cfltle #0, w13, w14
+// CHECK-INST: cfltge #0, w14, w13
+// CHECK-ENCODING: [0x0e,0x02,0x2d,0x76]
+// CHECK-UNKNOWN: 762d020e
+// CHECK-ERROR: error: instruction requires: cflt
+
+cfltlo #3, x16, x17
+// CHECK-INST: cflthi #3, x17, x16
+// CHECK-ENCODING: [0x11,0x0e,0x50,0xf6]
+// CHECK-UNKNOWN: f6500e11
+// CHECK-ERROR: error: instruction requires: cflt
+
+cfltls #0, w17, w18
+// CHECK-INST: cflths #0, w18, w17
+// CHECK-ENCODING: [0x12,0x02,0x71,0x76]
+// CHECK-UNKNOWN: 76710212
+// CHECK-ERROR: error: instruction requires: cflt
+
+cfltlt #3, x20, x21
+// CHECK-INST: cfltgt #3, x21, x20
+// CHECK-ENCODING: [0x15,0x0e,0x14,0xf6]
+// CHECK-UNKNOWN: f6140e15
+// CHECK-ERROR: error: instruction requires: cflt
+
+// CFLTZ and CFLTNZ.
+
+cfltz #0, w21
+// CHECK-INST: cflteq #0, w21, #0
+// CHECK-ENCODING: [0x15,0x00,0x80,0x76]
+// CHECK-UNKNOWN: 76800015
+// CHECK-ERROR: error: instruction requires: cflt
+
+cfltnz #3, x24
+// CHECK-INST: cfltne #3, x24, #0
+// CHECK-ENCODING: [0x18,0x0c,0xa0,0xf6]
+// CHECK-UNKNOWN: f6a00c18
+// CHECK-ERROR: error: instruction requires: cflt
+
+cfltnz #3, xzr
+// CHECK-INST: cfltne #3, xzr, #0
+// CHECK-ENCODING: [0x1f,0x0c,0xa0,0xf6]
+// CHECK-UNKNOWN: f6a00c1f
+// CHECK-ERROR: error: instruction requires: cflt
+
+// TFLTZ and TFLTNZ.
+
+tfltz #0, w0, #0
+// CHECK-INST: tfltz #0, w0, #0
+// CHECK-ENCODING: [0x40,0x02,0x00,0x76]
+// CHECK-UNKNOWN: 76000240
+// CHECK-ERROR: error: instruction requires: cflt
+
+tfltz #0, x0, #0
+// CHECK-INST: tfltz #0, w0, #0
+// CHECK-ENCODING: [0x40,0x02,0x00,0x76]
+// CHECK-UNKNOWN: 76000240
+// CHECK-ERROR: error: instruction requires: cflt
+
+tfltz #1, x1, #32
+// CHECK-INST: tfltz #1, x1, #32
+// CHECK-ENCODING: [0x41,0x06,0x00,0xf6]
+// CHECK-UNKNOWN: f6000641
+// CHECK-ERROR: error: instruction requires: cflt
+
+tfltnz #2, w3, #31
+// CHECK-INST: tfltnz #2, w3, #31
+// CHECK-ENCODING: [0x63,0x0a,0xf8,0x76]
+// CHECK-UNKNOWN: 76f80a63
+// CHECK-ERROR: error: instruction requires: cflt
+
+tfltnz #3, xzr, #31
+// CHECK-INST: tfltnz #3, wzr, #31
+// CHECK-ENCODING: [0x7f,0x0e,0xf8,0x76]
+// CHECK-UNKNOWN: 76f80e7f
+// CHECK-ERROR: error: instruction requires: cflt
+
+tfltnz #3, x4, #63
+// CHECK-INST: tfltnz #3, x4, #63
+// CHECK-ENCODING: [0x64,0x0e,0xf8,0xf6]
+// CHECK-UNKNOWN: f6f80e64
+// CHECK-ERROR: error: instruction requires: cflt
diff --git a/llvm/test/MC/AArch64/directive-arch-negative.s b/llvm/test/MC/AArch64/directive-arch-negative.s
index 4c17c560971203..2e7bed1ef2692e 100644
--- a/llvm/test/MC/AArch64/directive-arch-negative.s
+++ b/llvm/test/MC/AArch64/directive-arch-negative.s
@@ -79,3 +79,9 @@
# CHECK: error: instruction requires: f8f32mm
# CHECK-NEXT: fmmla v0.4s, v1.16b, v2.16b
+
+ .arch armv9-a+cflt+nocflt
+ cfltz #1, w0
+
+# CHECK: error: instruction requires: cflt
+# CHECK-NEXT: cfltz #1, w0
diff --git a/llvm/test/MC/AArch64/directive-arch.s b/llvm/test/MC/AArch64/directive-arch.s
index ba605cc5d1a698..cd68b6651448f0 100644
--- a/llvm/test/MC/AArch64/directive-arch.s
+++ b/llvm/test/MC/AArch64/directive-arch.s
@@ -38,3 +38,7 @@
.arch armv9-a+f8f32mm
fmmla v0.4s, v1.16b, v2.16b
# CHECK: fmmla v0.4s, v1.16b, v2.16b
+
+ .arch armv9-a+cflt
+ cfltz #1, w0
+# CHECK: cflteq #1, w0, #0
diff --git a/llvm/test/MC/AArch64/directive-arch_extension-negative.s b/llvm/test/MC/AArch64/directive-arch_extension-negative.s
index 0f01d899151534..7d6f608ea47cda 100644
--- a/llvm/test/MC/AArch64/directive-arch_extension-negative.s
+++ b/llvm/test/MC/AArch64/directive-arch_extension-negative.s
@@ -250,3 +250,9 @@ fmmla v2.8h, v1.16b, v0.16b
fmmla v2.4s, v1.16b, v0.16b
// CHECK: [[@LINE-1]]:1: error: instruction requires: f8f32mm
// CHECK-NEXT: fmmla v2.4s, v1.16b, v0.16b
+
+.arch_extension cflt
+.arch_extension nocflt
+cfltz #1, w0
+// CHECK: [[@LINE-1]]:1: error: instruction requires: cflt
+// CHECK-NEXT: cfltz #1, w0
diff --git a/llvm/test/MC/AArch64/directive-arch_extension.s b/llvm/test/MC/AArch64/directive-arch_extension.s
index f3377fd80c276e..6f4274f0e0edfd 100644
--- a/llvm/test/MC/AArch64/directive-arch_extension.s
+++ b/llvm/test/MC/AArch64/directive-arch_extension.s
@@ -228,3 +228,7 @@ fcmla v0.4s, v1.4s, v2.4s, #0
.arch_extension bti
bti c
// CHECK: bti c
+
+.arch_extension cflt
+cfltz #1, w0
+// CHECK: cflteq #1, w0, #0
diff --git a/llvm/unittests/TargetParser/TargetParserTest.cpp b/llvm/unittests/TargetParser/TargetParserTest.cpp
index 95661bf4a007ea..fa6bf6cb9d0966 100644
--- a/llvm/unittests/TargetParser/TargetParserTest.cpp
+++ b/llvm/unittests/TargetParser/TargetParserTest.cpp
@@ -1508,6 +1508,7 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) {
AArch64::AEK_BTIE, AArch64::AEK_F64MM,
AArch64::AEK_POPS, AArch64::AEK_SVESM4,
AArch64::AEK_MTETC, AArch64::AEK_HINTE,
+ AArch64::AEK_CFLT,
};
std::vector<StringRef> Features;
@@ -1632,6 +1633,7 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) {
EXPECT_TRUE(llvm::is_contained(Features, "+tev"));
EXPECT_TRUE(llvm::is_contained(Features, "+btie"));
EXPECT_TRUE(llvm::is_contained(Features, "+hinte"));
+ EXPECT_TRUE(llvm::is_contained(Features, "+cflt"));
// Assuming we listed every extension above, this should produce the same
// result.
@@ -1813,6 +1815,7 @@ TEST(TargetParserTest, AArch64ArchExtFeature) {
{"tev", "notev", "+tev", "-tev"},
{"btie", "nobtie", "+btie", "-btie"},
{"hinte", "nohinte", "+hinte", "-hinte"},
+ {"cflt", "nocflt", "+cflt", "-cflt"},
};
for (unsigned i = 0; i < std::size(ArchExt); i++) {
>From f07b28484bc15614ebeb5ab5ad11403b11788051 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <jonathan.thackray at arm.com>
Date: Thu, 8 Oct 2026 16:15:18 +0100
Subject: [PATCH 2/2] fixup! Remove `DecodeTFLTImm32_63` and `tflt_imm32_63`
---
.../lib/Target/AArch64/AArch64InstrFormats.td | 20 ++++++++-----------
.../AArch64/AsmParser/AArch64AsmParser.cpp | 13 ++++++++----
.../Disassembler/AArch64Disassembler.cpp | 7 -------
.../MC/AArch64/armv9.8a-cflt-diagnostics.s | 6 ++++++
llvm/test/MC/AArch64/armv9.8a-cflt.s | 12 +++++++++++
5 files changed, 35 insertions(+), 23 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 7bdfd59f328347..ce6c98c29b7424 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -527,6 +527,7 @@ def uimm9 : Operand<i64> {
let OperandType = "OPERAND_IMMEDIATE";
}
+// TODO: Use AdjImmAsmOperand for the uimm6m1 and uimm6p1 operands too.
class AdjImmAsmOperand<string name, string diagnostic, int adjustment,
int low, int high> : AsmOperandClass {
let Name = name;
@@ -1162,6 +1163,7 @@ def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
return ((uint64_t)Imm) < 32;
}]> {
let ParserMatchClass = Imm0_31Operand;
+ let MCOperandPredicate = [{ return MCOp.isImm() && isUInt<5>(MCOp.getImm()); }];
}
// timm0_31 predicate - same ass imm0_31, but use TargetConstant (TimmLeaf)
@@ -13773,17 +13775,12 @@ multiclass CFLTImmAlias<string mnemonic, string inst, Operand immtype> {
GPR64:$Rt, immtype:$imm), 0>;
}
-def tflt_imm32_63 : Operand<i64> {
- let ParserMatchClass = TBZImm32_63Operand;
- let OperandType = "OPERAND_IMMEDIATE";
- let DecoderMethod = "DecodeTFLTImm32_63";
-}
-
-class BaseTFLT<RegisterClass regtype, Operand immtype, bit sf, bit op,
+class BaseTFLT<RegisterClass regtype, Operand immtype, bit op,
string asm>
- : BaseFLT<sf, (ins imm0_3:$reason, regtype:$Rt, immtype:$bit_off),
+ : BaseFLT<0, (ins imm0_3:$reason, regtype:$Rt, immtype:$bit_off),
asm, "\t$reason, $Rt, $bit_off"> {
bits<6> bit_off;
+ let Inst{31} = bit_off{5};
let Inst{23-19} = bit_off{4-0};
let Inst{18-16} = 0b000;
let Inst{9-6} = 0b1001;
@@ -13791,10 +13788,9 @@ class BaseTFLT<RegisterClass regtype, Operand immtype, bit sf, bit op,
}
multiclass TFLT<bit op, string asm> {
- def W : BaseTFLT<GPR32, tbz_imm0_31_diag, 0, op, asm>;
- def X : BaseTFLT<GPR64, tflt_imm32_63, 1, op, asm>;
+ def NAME : BaseTFLT<GPR64, imm0_63, op, asm>;
def : InstAlias<asm # "\t$reason, $Rt, $imm",
- (!cast<Instruction>(NAME # "W") imm0_3:$reason,
- GPR32as64:$Rt, tbz_imm0_31_nodiag:$imm), 0>;
+ (!cast<Instruction>(NAME) imm0_3:$reason,
+ GPR64as32:$Rt, imm0_31:$imm), 1>;
}
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 8e9e9c33882a4b..4497f97e6f63e9 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -8800,13 +8800,18 @@ ParseStatus AArch64AsmParser::tryParseAdjImm0_63(OperandVector &Operands) {
SMLoc S = getLoc();
parseOptionalToken(AsmToken::Hash);
+ bool IsNegative = parseOptionalToken(AsmToken::Minus);
- if (getTok().isNot(AsmToken::Integer) && getTok().isNot(AsmToken::Minus))
+ if (getTok().isNot(AsmToken::Integer))
return ParseStatus::NoMatch;
- int64_t Imm;
- if (parseImmExpr(Imm))
- return ParseStatus::Failure;
+ const MCExpr *Ex;
+ if (getParser().parseExpression(Ex))
+ return ParseStatus::NoMatch;
+
+ int64_t Imm = dyn_cast<MCConstantExpr>(Ex)->getValue();
+ if (IsNegative)
+ Imm = -Imm;
// We want an adjusted immediate in the range [0, 63]. If we don't have one,
// return a value, which is certain to trigger a error message about invalid
diff --git a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
index 0dbfb5e50013e9..e7820f7d6c5b13 100644
--- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
+++ b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
@@ -1356,13 +1356,6 @@ static DecodeStatus DecodeTestAndBranch(MCInst &Inst, uint32_t insn,
return Success;
}
-static DecodeStatus DecodeTFLTImm32_63(MCInst &Inst, unsigned Imm,
- uint64_t Addr,
- const MCDisassembler *Decoder) {
- Inst.addOperand(MCOperand::createImm(Imm | 0x20));
- return Success;
-}
-
static DecodeStatus
DecodeGPRSeqPairsClassRegisterClass(MCInst &Inst, unsigned RegClassID,
unsigned RegNo, uint64_t Addr,
diff --git a/llvm/test/MC/AArch64/armv9.8a-cflt-diagnostics.s b/llvm/test/MC/AArch64/armv9.8a-cflt-diagnostics.s
index d4ab13432d7f15..b9c6683a99d226 100644
--- a/llvm/test/MC/AArch64/armv9.8a-cflt-diagnostics.s
+++ b/llvm/test/MC/AArch64/armv9.8a-cflt-diagnostics.s
@@ -82,8 +82,14 @@ tfltz #4, w0, #0
tfltz #0, w0, #32
// CHECK: [[@LINE-1]]:15: error: immediate must be an integer in range [0, 31].
+tfltz #0, w0, #-1
+// CHECK: [[@LINE-1]]:15: error: immediate must be an integer in range [0, 31].
+
tfltnz #4, x0, #32
// CHECK: [[@LINE-1]]:8: error: immediate must be an integer in range [0, 3].
tfltnz #0, x0, #64
// CHECK: [[@LINE-1]]:16: error: immediate must be an integer in range [0, 63].
+
+tfltnz #0, x0, #-1
+// CHECK: [[@LINE-1]]:16: error: immediate must be an integer in range [0, 63].
diff --git a/llvm/test/MC/AArch64/armv9.8a-cflt.s b/llvm/test/MC/AArch64/armv9.8a-cflt.s
index 8a648037542450..2a7ea280576f7e 100644
--- a/llvm/test/MC/AArch64/armv9.8a-cflt.s
+++ b/llvm/test/MC/AArch64/armv9.8a-cflt.s
@@ -310,6 +310,12 @@ tfltz #1, x1, #32
// CHECK-UNKNOWN: f6000641
// CHECK-ERROR: error: instruction requires: cflt
+tfltz #3, wzr, #31
+// CHECK-INST: tfltz #3, wzr, #31
+// CHECK-ENCODING: [0x5f,0x0e,0xf8,0x76]
+// CHECK-UNKNOWN: 76f80e5f
+// CHECK-ERROR: error: instruction requires: cflt
+
tfltnz #2, w3, #31
// CHECK-INST: tfltnz #2, w3, #31
// CHECK-ENCODING: [0x63,0x0a,0xf8,0x76]
@@ -322,6 +328,12 @@ tfltnz #3, xzr, #31
// CHECK-UNKNOWN: 76f80e7f
// CHECK-ERROR: error: instruction requires: cflt
+tfltnz #3, xzr, #32
+// CHECK-INST: tfltnz #3, xzr, #32
+// CHECK-ENCODING: [0x7f,0x0e,0x00,0xf6]
+// CHECK-UNKNOWN: f6000e7f
+// CHECK-ERROR: error: instruction requires: cflt
+
tfltnz #3, x4, #63
// CHECK-INST: tfltnz #3, x4, #63
// CHECK-ENCODING: [0x64,0x0e,0xf8,0xf6]
More information about the llvm-branch-commits
mailing list