[llvm] [llvm-exegesis] Add AArch64 operand initializers, SetRegTo (PR #169912)
Simon Wallis via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 28 05:35:25 PST 2025
https://github.com/simonwallis2 updated https://github.com/llvm/llvm-project/pull/169912
>From 0e8b759f259c3b829428b11737e8d30666655a17 Mon Sep 17 00:00:00 2001
From: Simon Wallis <simon.wallis2 at arm.com>
Date: Fri, 28 Nov 2025 12:56:48 +0000
Subject: [PATCH 1/3] [llvm-exegesis] Add AArch64 operand initializers,
SetRegTo
Make llvm-exegesis more usable on AArch64 by doing the following:
Add some missing exegesis handling of register classes
Add some missing LLVM AArch64 OperandTypes
Llvm-exegesis can now handle many more instructions.
Load/store instructions not yet supported by llvm-exegesis,
until https://github.com/llvm/llvm-project/pull/144895 lands.
Change-Id: I945079ae290395a207e4cc4619d177a67f0d5a47
---
.../lib/Target/AArch64/AArch64InstrFormats.td | 126 +++++++++++++
.../MCTargetDesc/AArch64MCTargetDesc.h | 2 +
.../llvm-exegesis/lib/AArch64/Target.cpp | 168 ++++++++++++++++++
3 files changed, 296 insertions(+)
diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 58a53af76e1b5..7832f3ae35718 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -375,12 +375,14 @@ def simm10Scaled : Operand<i64> {
let ParserMatchClass = SImm10s8Operand;
let DecoderMethod = "DecodeSImm<10>";
let PrintMethod = "printImmScale<8>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def simm9s16 : Operand<i64> {
let ParserMatchClass = SImmScaledMemoryIndexed<9, 16>;
let DecoderMethod = "DecodeSImm<9>";
let PrintMethod = "printImmScale<16>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
// uimm6 predicate - True if the immediate is in the range [0, 63].
@@ -391,18 +393,22 @@ def UImm6Operand : AsmOperandClass {
def uimm6 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
let ParserMatchClass = UImm6Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def uimm16 : Operand<i16>, ImmLeaf<i16, [{return Imm >= 0 && Imm < 65536;}]>{
let ParserMatchClass = AsmImmRange<0, 65535>;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def uimm6_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
let ParserMatchClass = UImm6Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def uimm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 64; }]> {
let ParserMatchClass = UImm6Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def CmpBranchUImm6Operand_32b
@@ -433,24 +439,29 @@ def UImm6Minus1Operand : AsmOperandClass {
def uimm6p1_32b : Operand<i32> {
let ParserMatchClass = UImm6Plus1Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def uimm6p1_64b : Operand<i64> {
let ParserMatchClass = UImm6Plus1Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def uimm6m1_32b : Operand<i32> {
let ParserMatchClass = UImm6Minus1Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def uimm6m1_64b : Operand<i64> {
let ParserMatchClass = UImm6Minus1Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def SImm9Operand : SImmOperand<9>;
def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
let ParserMatchClass = SImm9Operand;
let DecoderMethod = "DecodeSImm<9>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
// imm0_255 predicate - True if the immediate is in the range [0,255].
@@ -458,48 +469,57 @@ def Imm0_255Operand : AsmImmRange<0,255>;
def uimm8_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 256; }]> {
let ParserMatchClass = Imm0_255Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def uimm8_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 256; }]> {
let ParserMatchClass = Imm0_255Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def SImm8Operand : SImmOperand<8>;
def simm8_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -128 && Imm < 128; }]> {
let ParserMatchClass = SImm8Operand;
let DecoderMethod = "DecodeSImm<8>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def simm8_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -128 && Imm < 128; }]> {
let ParserMatchClass = SImm8Operand;
let DecoderMethod = "DecodeSImm<8>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def SImm6Operand : SImmOperand<6>;
def simm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -32 && Imm < 32; }]> {
let ParserMatchClass = SImm6Operand;
let DecoderMethod = "DecodeSImm<6>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def SImm5Operand : SImmOperand<5>;
def simm5_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -16 && Imm < 16; }]> {
let ParserMatchClass = SImm5Operand;
let DecoderMethod = "DecodeSImm<5>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def simm5_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -16 && Imm < 16; }]> {
let ParserMatchClass = SImm5Operand;
let DecoderMethod = "DecodeSImm<5>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def simm5_8b : Operand<i32>, ImmLeaf<i32, [{ return (int8_t)Imm >= -16 && (int8_t)Imm < 16; }]> {
let ParserMatchClass = SImm5Operand;
let DecoderMethod = "DecodeSImm<5>";
let PrintMethod = "printSImm<8>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def simm5_16b : Operand<i32>, ImmLeaf<i32, [{ return (int16_t)Imm >= -16 && (int16_t)Imm < 16; }]> {
let ParserMatchClass = SImm5Operand;
let DecoderMethod = "DecodeSImm<5>";
let PrintMethod = "printSImm<16>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
// simm7sN predicate - True if the immediate is a multiple of N in the range
@@ -512,16 +532,19 @@ def SImm7s16Operand : SImmScaledMemoryIndexed<7, 16>;
def simm7s4 : Operand<i32> {
let ParserMatchClass = SImm7s4Operand;
let PrintMethod = "printImmScale<4>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def simm7s8 : Operand<i32> {
let ParserMatchClass = SImm7s8Operand;
let PrintMethod = "printImmScale<8>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def simm7s16 : Operand<i32> {
let ParserMatchClass = SImm7s16Operand;
let PrintMethod = "printImmScale<16>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def am_sve_fi : ComplexPattern<iPTR, 2, "SelectAddrModeFrameIndexSVE", []>;
@@ -571,18 +594,21 @@ def uimm5s2 : Operand<i64>, ImmLeaf<i64,
UImmS2XForm> {
let ParserMatchClass = UImm5s2Operand;
let PrintMethod = "printImmScale<2>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def uimm5s4 : Operand<i64>, ImmLeaf<i64,
[{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
UImmS4XForm> {
let ParserMatchClass = UImm5s4Operand;
let PrintMethod = "printImmScale<4>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def uimm5s8 : Operand<i64>, ImmLeaf<i64,
[{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
UImmS8XForm> {
let ParserMatchClass = UImm5s8Operand;
let PrintMethod = "printImmScale<8>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
// tuimm5sN predicate - similar to uimm5sN, but use TImmLeaf (TargetConstant)
@@ -592,18 +618,21 @@ def tuimm5s2 : Operand<i64>, TImmLeaf<i64,
UImmS2XForm> {
let ParserMatchClass = UImm5s2Operand;
let PrintMethod = "printImmScale<2>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def tuimm5s4 : Operand<i64>, TImmLeaf<i64,
[{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
UImmS4XForm> {
let ParserMatchClass = UImm5s4Operand;
let PrintMethod = "printImmScale<4>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def tuimm5s8 : Operand<i64>, TImmLeaf<i64,
[{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
UImmS8XForm> {
let ParserMatchClass = UImm5s8Operand;
let PrintMethod = "printImmScale<8>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
// uimm6sN predicate - True if the immediate is a multiple of N in the range
@@ -616,26 +645,31 @@ def UImm6s16Operand : UImmScaledMemoryIndexed<6, 16>;
def uimm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
let ParserMatchClass = UImm6s1Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def uimm6s2 : Operand<i64>, ImmLeaf<i64,
[{ return Imm >= 0 && Imm < (64*2) && ((Imm % 2) == 0); }]> {
let PrintMethod = "printImmScale<2>";
let ParserMatchClass = UImm6s2Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def uimm6s4 : Operand<i64>, ImmLeaf<i64,
[{ return Imm >= 0 && Imm < (64*4) && ((Imm % 4) == 0); }]> {
let PrintMethod = "printImmScale<4>";
let ParserMatchClass = UImm6s4Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def uimm6s8 : Operand<i64>, ImmLeaf<i64,
[{ return Imm >= 0 && Imm < (64*8) && ((Imm % 8) == 0); }]> {
let PrintMethod = "printImmScale<8>";
let ParserMatchClass = UImm6s8Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def uimm6s16 : Operand<i64>, ImmLeaf<i64,
[{ return Imm >= 0 && Imm < (64*16) && ((Imm % 16) == 0); }]> {
let PrintMethod = "printImmScale<16>";
let ParserMatchClass = UImm6s16Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def SImmS2XForm : SDNodeXForm<imm, [{
@@ -660,6 +694,7 @@ def SImm6s1Operand : SImmScaledMemoryIndexed<6, 1>;
def simm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -32 && Imm < 32; }]> {
let ParserMatchClass = SImm6s1Operand;
let DecoderMethod = "DecodeSImm<6>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
// simm4sN predicate - True if the immediate is a multiple of N in the range
@@ -675,6 +710,7 @@ def simm4s1 : Operand<i64>, ImmLeaf<i64,
[{ return Imm >=-8 && Imm <= 7; }]> {
let ParserMatchClass = SImm4s1Operand;
let DecoderMethod = "DecodeSImm<4>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def simm4s2 : Operand<i64>, ImmLeaf<i64,
@@ -682,6 +718,7 @@ def simm4s2 : Operand<i64>, ImmLeaf<i64,
let PrintMethod = "printImmScale<2>";
let ParserMatchClass = SImm4s2Operand;
let DecoderMethod = "DecodeSImm<4>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def simm4s3 : Operand<i64>, ImmLeaf<i64,
@@ -689,6 +726,7 @@ def simm4s3 : Operand<i64>, ImmLeaf<i64,
let PrintMethod = "printImmScale<3>";
let ParserMatchClass = SImm4s3Operand;
let DecoderMethod = "DecodeSImm<4>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def simm4s4 : Operand<i64>, ImmLeaf<i64,
@@ -696,18 +734,21 @@ def simm4s4 : Operand<i64>, ImmLeaf<i64,
let PrintMethod = "printImmScale<4>";
let ParserMatchClass = SImm4s4Operand;
let DecoderMethod = "DecodeSImm<4>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def simm4s16 : Operand<i64>, ImmLeaf<i64,
[{ return Imm >=-128 && Imm <= 112 && (Imm % 16) == 0x0; }], SImmS16XForm> {
let PrintMethod = "printImmScale<16>";
let ParserMatchClass = SImm4s16Operand;
let DecoderMethod = "DecodeSImm<4>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def simm4s32 : Operand<i64>, ImmLeaf<i64,
[{ return Imm >=-256 && Imm <= 224 && (Imm % 32) == 0x0; }], SImmS32XForm> {
let PrintMethod = "printImmScale<32>";
let ParserMatchClass = SImm4s32Operand;
let DecoderMethod = "DecodeSImm<4>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def Imm1_8Operand : AsmImmRange<1, 8>;
@@ -737,6 +778,7 @@ def MovWSymbolG3AsmOperand : AsmOperandClass {
def movw_symbol_g3 : Operand<i32> {
let ParserMatchClass = MovWSymbolG3AsmOperand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def MovWSymbolG2AsmOperand : AsmOperandClass {
@@ -746,6 +788,7 @@ def MovWSymbolG2AsmOperand : AsmOperandClass {
def movw_symbol_g2 : Operand<i32> {
let ParserMatchClass = MovWSymbolG2AsmOperand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def MovWSymbolG1AsmOperand : AsmOperandClass {
@@ -755,6 +798,7 @@ def MovWSymbolG1AsmOperand : AsmOperandClass {
def movw_symbol_g1 : Operand<i32> {
let ParserMatchClass = MovWSymbolG1AsmOperand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def MovWSymbolG0AsmOperand : AsmOperandClass {
@@ -764,6 +808,7 @@ def MovWSymbolG0AsmOperand : AsmOperandClass {
def movw_symbol_g0 : Operand<i32> {
let ParserMatchClass = MovWSymbolG0AsmOperand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
class fixedpoint_i32<ValueType FloatVT>
@@ -772,6 +817,7 @@ class fixedpoint_i32<ValueType FloatVT>
let EncoderMethod = "getFixedPointScaleOpValue";
let DecoderMethod = "DecodeFixedPointScaleImm32";
let ParserMatchClass = Imm1_32Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
class fixedpoint_i64<ValueType FloatVT>
@@ -780,6 +826,7 @@ class fixedpoint_i64<ValueType FloatVT>
let EncoderMethod = "getFixedPointScaleOpValue";
let DecoderMethod = "DecodeFixedPointScaleImm64";
let ParserMatchClass = Imm1_64Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def fixedpoint_f16_i32 : fixedpoint_i32<f16>;
@@ -795,6 +842,7 @@ class fixedpoint_recip_i32<ValueType FloatVT>
ComplexPattern<FloatVT, 1, "SelectCVTFixedPosRecipOperand<32>", [fpimm, ld]> {
let EncoderMethod = "getFixedPointScaleOpValue";
let DecoderMethod = "DecodeFixedPointScaleImm32";
+ let OperandType = "OPERAND_IMMEDIATE";
}
class fixedpoint_recip_i64<ValueType FloatVT>
@@ -802,6 +850,7 @@ class fixedpoint_recip_i64<ValueType FloatVT>
ComplexPattern<FloatVT, 1, "SelectCVTFixedPosRecipOperand<64>", [fpimm, ld]> {
let EncoderMethod = "getFixedPointScaleOpValue";
let DecoderMethod = "DecodeFixedPointScaleImm64";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def fixedpoint_recip_f16_i32 : fixedpoint_recip_i32<f16>;
@@ -818,6 +867,7 @@ def vecshiftR8 : Operand<i32>, TImmLeaf<i32, [{
let EncoderMethod = "getVecShiftR8OpValue";
let DecoderMethod = "DecodeVecShiftR8Imm";
let ParserMatchClass = Imm1_8Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def vecshiftR16 : Operand<i32>, TImmLeaf<i32, [{
return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
@@ -825,6 +875,7 @@ def vecshiftR16 : Operand<i32>, TImmLeaf<i32, [{
let EncoderMethod = "getVecShiftR16OpValue";
let DecoderMethod = "DecodeVecShiftR16Imm";
let ParserMatchClass = Imm1_16Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def vecshiftR16Narrow : Operand<i32>, TImmLeaf<i32, [{
return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
@@ -832,6 +883,7 @@ def vecshiftR16Narrow : Operand<i32>, TImmLeaf<i32, [{
let EncoderMethod = "getVecShiftR16OpValue";
let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
let ParserMatchClass = Imm1_8Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def vecshiftR32 : Operand<i32>, TImmLeaf<i32, [{
return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
@@ -839,6 +891,7 @@ def vecshiftR32 : Operand<i32>, TImmLeaf<i32, [{
let EncoderMethod = "getVecShiftR32OpValue";
let DecoderMethod = "DecodeVecShiftR32Imm";
let ParserMatchClass = Imm1_32Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def vecshiftR32Narrow : Operand<i32>, TImmLeaf<i32, [{
return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
@@ -846,6 +899,7 @@ def vecshiftR32Narrow : Operand<i32>, TImmLeaf<i32, [{
let EncoderMethod = "getVecShiftR32OpValue";
let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
let ParserMatchClass = Imm1_16Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def vecshiftR64 : Operand<i32>, TImmLeaf<i32, [{
return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
@@ -853,6 +907,7 @@ def vecshiftR64 : Operand<i32>, TImmLeaf<i32, [{
let EncoderMethod = "getVecShiftR64OpValue";
let DecoderMethod = "DecodeVecShiftR64Imm";
let ParserMatchClass = Imm1_64Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def vecshiftR64Narrow : Operand<i32>, TImmLeaf<i32, [{
return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
@@ -860,6 +915,7 @@ def vecshiftR64Narrow : Operand<i32>, TImmLeaf<i32, [{
let EncoderMethod = "getVecShiftR64OpValue";
let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
let ParserMatchClass = Imm1_32Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def Imm0_0Operand : AsmImmRange<0, 0>;
@@ -879,6 +935,7 @@ def vecshiftL8 : Operand<i32>, TImmLeaf<i32, [{
let EncoderMethod = "getVecShiftL8OpValue";
let DecoderMethod = "DecodeVecShiftL8Imm";
let ParserMatchClass = Imm0_7Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def vecshiftL16 : Operand<i32>, TImmLeaf<i32, [{
return (((uint32_t)Imm) < 16);
@@ -886,6 +943,7 @@ def vecshiftL16 : Operand<i32>, TImmLeaf<i32, [{
let EncoderMethod = "getVecShiftL16OpValue";
let DecoderMethod = "DecodeVecShiftL16Imm";
let ParserMatchClass = Imm0_15Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def vecshiftL32 : Operand<i32>, TImmLeaf<i32, [{
return (((uint32_t)Imm) < 32);
@@ -893,6 +951,7 @@ def vecshiftL32 : Operand<i32>, TImmLeaf<i32, [{
let EncoderMethod = "getVecShiftL32OpValue";
let DecoderMethod = "DecodeVecShiftL32Imm";
let ParserMatchClass = Imm0_31Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def vecshiftL64 : Operand<i32>, TImmLeaf<i32, [{
return (((uint32_t)Imm) < 64);
@@ -900,6 +959,7 @@ def vecshiftL64 : Operand<i32>, TImmLeaf<i32, [{
let EncoderMethod = "getVecShiftL64OpValue";
let DecoderMethod = "DecodeVecShiftL64Imm";
let ParserMatchClass = Imm0_63Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
@@ -1199,6 +1259,8 @@ class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
let PrintMethod = "printShiftedRegister";
let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
+ let OperandType = "OPERAND_SHIFTED_REGISTER";
+ let OperandNamespace = "AArch64";
}
def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
@@ -1219,6 +1281,7 @@ class logical_shift<int width> : Operand<i32> {
let PrintMethod = "printShifter";
let ParserMatchClass = !cast<AsmOperandClass>(
"LogicalShifterOperand" # width);
+ let OperandType = "OPERAND_IMMEDIATE";
}
def logical_shift32 : logical_shift<32>;
@@ -1229,6 +1292,8 @@ class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
let PrintMethod = "printShiftedRegister";
let MIOperandInfo = (ops regclass, shiftop);
+ let OperandType = "OPERAND_SHIFTED_REGISTER";
+ let OperandNamespace = "AArch64";
}
def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
@@ -1249,6 +1314,8 @@ def logical_vec_shift : Operand<i32> {
let PrintMethod = "printShifter";
let EncoderMethod = "getVecShifterOpValue";
let ParserMatchClass = LogicalVecShifterOperand;
+ let OperandType = "OPERAND_SHIFTED_IMMEDIATE";
+ let OperandNamespace = "AArch64";
}
// A logical vector half-word shifter operand:
@@ -1258,6 +1325,8 @@ def logical_vec_hw_shift : Operand<i32> {
let PrintMethod = "printShifter";
let EncoderMethod = "getVecShifterOpValue";
let ParserMatchClass = LogicalVecHalfWordShifterOperand;
+ let OperandType = "OPERAND_SHIFTED_IMMEDIATE";
+ let OperandNamespace = "AArch64";
}
// A vector move shifter operand:
@@ -1292,6 +1361,8 @@ class addsub_shifted_imm<ValueType Ty>
let EncoderMethod = "getAddSubImmOpValue";
let ParserMatchClass = AddSubImmOperand;
let MIOperandInfo = (ops i32imm, i32imm);
+ let OperandType = "OPERAND_SHIFTED_IMMEDIATE";
+ let OperandNamespace = "AArch64";
}
class addsub_shifted_imm_neg<ValueType Ty>
@@ -1299,6 +1370,8 @@ class addsub_shifted_imm_neg<ValueType Ty>
let EncoderMethod = "getAddSubImmOpValue";
let ParserMatchClass = AddSubImmNegOperand;
let MIOperandInfo = (ops i32imm, i32imm);
+ let OperandType = "OPERAND_SHIFTED_IMMEDIATE";
+ let OperandNamespace = "AArch64";
}
def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
@@ -1320,6 +1393,8 @@ class neg_addsub_shifted_imm<ValueType Ty>
let EncoderMethod = "getAddSubImmOpValue";
let ParserMatchClass = AddSubImmOperand;
let MIOperandInfo = (ops i32imm, i32imm);
+ let OperandType = "OPERAND_SHIFTED_IMMEDIATE";
+ let OperandNamespace = "AArch64";
}
def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
@@ -1339,28 +1414,35 @@ def gi_neg_addsub_shifted_imm64 :
def arith_extend : Operand<i32> {
let PrintMethod = "printArithExtend";
let ParserMatchClass = ExtendOperand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def arith_extend64 : Operand<i32> {
let PrintMethod = "printArithExtend";
let ParserMatchClass = ExtendOperand64;
+ let OperandType = "OPERAND_IMMEDIATE";
}
// 'extend' that's a lsl of a 64-bit register.
def arith_extendlsl64 : Operand<i32> {
let PrintMethod = "printArithExtend";
let ParserMatchClass = ExtendOperandLSL64;
+ let OperandType = "OPERAND_IMMEDIATE";
}
class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
let PrintMethod = "printExtendedRegister";
let MIOperandInfo = (ops GPR32, arith_extend);
+ let OperandType = "OPERAND_SHIFTED_REGISTER";
+ let OperandNamespace = "AArch64";
}
class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
let PrintMethod = "printExtendedRegister";
let MIOperandInfo = (ops GPR32, arith_extend64);
+ let OperandType = "OPERAND_SHIFTED_REGISTER";
+ let OperandNamespace = "AArch64";
}
def arith_extended_reg32_i32 : arith_extended_reg32<i32>;
@@ -1442,6 +1524,7 @@ def fpimm64 : Operand<f64>,
def fpimm8 : Operand<i32> {
let ParserMatchClass = FPImmOperand;
let PrintMethod = "printFPImmOperand";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def fpimm0 : FPImmLeaf<fAny, [{
@@ -1507,6 +1590,7 @@ let OperandNamespace = "AArch64", OperandType = "OPERAND_IMPLICIT_IMM_0",
defm VectorIndex032b : VectorIndex<i32, VectorIndex0Operand,
[{ return ((uint32_t)Imm) == 0; }]>;
}
+let OperandType = "OPERAND_IMMEDIATE" in {
defm VectorIndex1 : VectorIndex<i64, VectorIndex1Operand,
[{ return ((uint64_t)Imm) == 1; }]>;
defm VectorIndexB : VectorIndex<i64, VectorIndexBOperand,
@@ -1528,6 +1612,7 @@ defm VectorIndexS32b : VectorIndex<i32, VectorIndexSOperand,
[{ return ((uint64_t)Imm) < 4; }]>;
defm VectorIndexD32b : VectorIndex<i32, VectorIndexDOperand,
[{ return ((uint64_t)Imm) < 2; }]>;
+}
def SVEVectorIndexExtDupBOperand : AsmVectorIndex<0, 63, "SVE">;
def SVEVectorIndexExtDupHOperand : AsmVectorIndex<0, 31, "SVE">;
@@ -1535,6 +1620,7 @@ def SVEVectorIndexExtDupSOperand : AsmVectorIndex<0, 15, "SVE">;
def SVEVectorIndexExtDupDOperand : AsmVectorIndex<0, 7, "SVE">;
def SVEVectorIndexExtDupQOperand : AsmVectorIndex<0, 3, "SVE">;
+let OperandType = "OPERAND_IMMEDIATE" in {
defm sve_elm_idx_extdup_b
: VectorIndex<i64, SVEVectorIndexExtDupBOperand,
[{ return ((uint64_t)Imm) < 64; }]>;
@@ -1550,6 +1636,7 @@ defm sve_elm_idx_extdup_d
defm sve_elm_idx_extdup_q
: VectorIndex<i64, SVEVectorIndexExtDupQOperand,
[{ return ((uint64_t)Imm) < 4; }]>;
+}
def sme_elm_idx0_0 : Operand<i32>, TImmLeaf<i32, [{
return ((uint32_t)Imm) == 0;
@@ -1565,24 +1652,28 @@ def sme_elm_idx0_1 : Operand<i32>, TImmLeaf<i32, [{
}]> {
let ParserMatchClass = Imm0_1Operand;
let PrintMethod = "printMatrixIndex";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def sme_elm_idx0_3 : Operand<i32>, TImmLeaf<i32, [{
return ((uint32_t)Imm) <= 3;
}]> {
let ParserMatchClass = Imm0_3Operand;
let PrintMethod = "printMatrixIndex";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def sme_elm_idx0_7 : Operand<i32>, TImmLeaf<i32, [{
return ((uint32_t)Imm) <= 7;
}]> {
let ParserMatchClass = Imm0_7Operand;
let PrintMethod = "printMatrixIndex";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def sme_elm_idx0_15 : Operand<i32>, TImmLeaf<i32, [{
return ((uint32_t)Imm) <= 15;
}]> {
let ParserMatchClass = Imm0_15Operand;
let PrintMethod = "printMatrixIndex";
+ let OperandType = "OPERAND_IMMEDIATE";
}
// SME2 vector select offset operands
@@ -1595,6 +1686,7 @@ def uimm3s8 : Operand<i64>, ImmLeaf<i64,
[{ return Imm >= 0 && Imm <= 56 && ((Imm % 8) == 0); }], UImmS8XForm> {
let PrintMethod = "printMatrixIndex<8>";
let ParserMatchClass = UImm3s8Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
class UImmScaledMemoryIndexedRange<int Width, int Scale, int OffsetVal> : AsmOperandClass {
@@ -1638,30 +1730,35 @@ def uimm1s2range : Operand<i64>, ImmLeaf<i64,
[{ return Imm >= 0 && Imm <= 2 && ((Imm % 2) == 0); }], UImmS2XForm> {
let PrintMethod = "printImmRangeScale<2, 1>";
let ParserMatchClass = UImm1s2RangeOperand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def uimm1s4range : Operand<i64>, ImmLeaf<i64,
[{ return Imm >= 0 && Imm <= 4 && ((Imm % 4) == 0); }], UImmS4XForm> {
let PrintMethod = "printImmRangeScale<4, 3>";
let ParserMatchClass = UImm1s4RangeOperand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def uimm2s2range : Operand<i64>, ImmLeaf<i64,
[{ return Imm >= 0 && Imm <= 6 && ((Imm % 2) == 0); }], UImmS2XForm> {
let PrintMethod = "printImmRangeScale<2, 1>";
let ParserMatchClass = UImm2s2RangeOperand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def uimm2s4range : Operand<i64>, ImmLeaf<i64,
[{ return Imm >= 0 && Imm <= 12 && ((Imm % 4) == 0); }], UImmS4XForm> {
let PrintMethod = "printImmRangeScale<4, 3>";
let ParserMatchClass = UImm2s4RangeOperand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def uimm3s2range : Operand<i64>, ImmLeaf<i64,
[{ return Imm >= 0 && Imm <= 14 && ((Imm % 2) == 0); }], UImmS2XForm> {
let PrintMethod = "printImmRangeScale<2, 1>";
let ParserMatchClass = UImm3s2RangeOperand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
@@ -1680,6 +1777,7 @@ def simdimmtype10 : Operand<i32>,
}]>> {
let ParserMatchClass = SIMDImmType10Operand;
let PrintMethod = "printSIMDType10Operand";
+ let OperandType = "OPERAND_IMMEDIATE";
}
@@ -1788,6 +1886,7 @@ def PHintInstOperand : AsmOperandClass {
def phint_op : Operand<i32> {
let ParserMatchClass = PHintInstOperand;
let PrintMethod = "printPHintOp";
+ let OperandType = "OPERAND_IMMEDIATE";
}
class STSHHI
@@ -1808,6 +1907,7 @@ def BarrierAsmOperand : AsmOperandClass {
def barrier_op : Operand<i32> {
let PrintMethod = "printBarrierOption";
let ParserMatchClass = BarrierAsmOperand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def BarriernXSAsmOperand : AsmOperandClass {
let Name = "BarriernXS";
@@ -1816,6 +1916,7 @@ def BarriernXSAsmOperand : AsmOperandClass {
def barrier_nxs_op : Operand<i32> {
let PrintMethod = "printBarriernXSOption";
let ParserMatchClass = BarriernXSAsmOperand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
list<dag> pattern = []>
@@ -1850,6 +1951,7 @@ def mrs_sysreg_op : Operand<i32> {
let ParserMatchClass = MRSSystemRegisterOperand;
let DecoderMethod = "DecodeMRSSystemRegister";
let PrintMethod = "printMRSSystemRegister";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def MSRSystemRegisterOperand : AsmOperandClass {
@@ -1861,6 +1963,7 @@ def msr_sysreg_op : Operand<i32> {
let ParserMatchClass = MSRSystemRegisterOperand;
let DecoderMethod = "DecodeMSRSystemRegister";
let PrintMethod = "printMSRSystemRegister";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def PSBHintOperand : AsmOperandClass {
@@ -1877,6 +1980,7 @@ def psbhint_op : Operand<i32> {
return false;
return AArch64PSBHint::lookupPSBByEncoding(MCOp.getImm()) != nullptr;
}];
+ let OperandType = "OPERAND_IMMEDIATE";
}
def BTIHintOperand : AsmOperandClass {
@@ -1892,6 +1996,7 @@ def btihint_op : Operand<i32> {
return false;
return AArch64BTIHint::lookupBTIByEncoding(MCOp.getImm() ^ 32) != nullptr;
}];
+ let OperandType = "OPERAND_IMMEDIATE";
}
def CMHPriorityHintOperand : AsmOperandClass {
@@ -1907,6 +2012,7 @@ def CMHPriorityHint_op : Operand<i32> {
return false;
return AArch64CMHPriorityHint::lookupCMHPriorityHintByEncoding(MCOp.getImm()) != nullptr;
}];
+ let OperandType = "OPERAND_IMMEDIATE";
}
class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
@@ -1943,6 +2049,7 @@ def pstatefield4_op : Operand<i32> {
return false;
return AArch64SVCR::lookupPStateImm0_15ByEncoding(MCOp.getImm()) != nullptr;
}];
+ let OperandType = "OPERAND_IMMEDIATE";
}
// Instructions to modify PSTATE, no input reg
@@ -1983,6 +2090,7 @@ def pstatefield1_op : Operand<i32> {
return false;
return AArch64SVCR::lookupPStateImm0_1ByEncoding(MCOp.getImm()) != nullptr;
}];
+ let OperandType = "OPERAND_IMMEDIATE";
}
class MSRpstateImm0_1
@@ -2013,6 +2121,7 @@ def SysCRAsmOperand : AsmOperandClass {
def sys_cr_op : Operand<i32> {
let PrintMethod = "printSysCROperand";
let ParserMatchClass = SysCRAsmOperand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
class SystemXtI<bit L, string asm>
@@ -2057,6 +2166,7 @@ def rprfop : Operand<i32>, TImmLeaf<i32, [{
}]> {
let PrintMethod = "printRPRFMOperand";
let ParserMatchClass = RangePrefetchOperand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
// Branch (register) instructions:
@@ -2184,6 +2294,7 @@ multiclass AuthLoad<bit M, string asm, Operand opr> {
def ccode : Operand<i32> {
let PrintMethod = "printCondCode";
let ParserMatchClass = CondCode;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def inv_ccode : Operand<i32> {
// AL and NV are invalid in the aliases which use inv_ccode
@@ -2194,6 +2305,7 @@ def inv_ccode : Operand<i32> {
MCOp.getImm() != AArch64CC::AL &&
MCOp.getImm() != AArch64CC::NV;
}];
+ let OperandType = "OPERAND_IMMEDIATE";
}
// Conditional branch target. 19-bit immediate. The low two bits of the target
@@ -2290,6 +2402,7 @@ class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
return (((uint32_t)Imm) < 32);
}]> {
let ParserMatchClass = matcher;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
@@ -2299,6 +2412,7 @@ def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
}]> {
let ParserMatchClass = TBZImm32_63Operand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
class BaseTestBranch<RegisterClass regtype, Operand immtype,
@@ -2810,14 +2924,17 @@ def movimm32_imm : Operand<i32> {
let ParserMatchClass = AsmImmRange<0, 65535>;
let EncoderMethod = "getMoveWideImmOpValue";
let PrintMethod = "printImm";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def movimm32_shift : Operand<i32> {
let PrintMethod = "printShifter";
let ParserMatchClass = MovImm32ShifterOperand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
def movimm64_shift : Operand<i32> {
let PrintMethod = "printShifter";
let ParserMatchClass = MovImm64ShifterOperand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
@@ -3634,9 +3751,11 @@ multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
//---
def maski8_or_more : Operand<i32>,
ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
+ let OperandType = "OPERAND_IMMEDIATE";
}
def maski16_or_more : Operand<i32>,
ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
+ let OperandType = "OPERAND_IMMEDIATE";
}
@@ -3694,6 +3813,7 @@ class uimm12_scaled<int Scale> : Operand<i64> {
let EncoderMethod
= "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
let PrintMethod = "printUImm12Offset<" # Scale # ">";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def uimm12s1 : uimm12_scaled<1>;
@@ -3770,6 +3890,7 @@ def PrefetchOperand : AsmOperandClass {
def prfop : Operand<i32> {
let PrintMethod = "printPrefetchOp";
let ParserMatchClass = PrefetchOperand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
@@ -3905,6 +4026,8 @@ class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
let DecoderMethod = "DecodeMemExtend";
let EncoderMethod = "getMemExtendOpValue";
let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
+ let OperandType = "OPERAND_SHIFTED_IMMEDIATE";
+ let OperandNamespace = "AArch64";
}
def ro_Wextend8 : ro_extend<MemWExtend8Operand, "w", 8>;
@@ -11700,6 +11823,7 @@ def complexrotateop : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 2
}]>> {
let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
let PrintMethod = "printComplexRotationOp<90, 0>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
def complexrotateopodd : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270; }],
SDNodeXForm<imm, [{
@@ -11707,6 +11831,7 @@ def complexrotateopodd : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <
}]>> {
let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
let PrintMethod = "printComplexRotationOp<180, 90>";
+ let OperandType = "OPERAND_IMMEDIATE";
}
let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
class BaseSIMDThreeSameVectorComplex<bit Q, bit U, bits<2> size, bits<3> opcode,
@@ -13078,6 +13203,7 @@ def LSLImm3ShiftOperand : AsmOperandClass {
def lsl_imm3_shift_operand : Operand<i64> {
let PrintMethod = "printShifter";
let ParserMatchClass = LSLImm3ShiftOperand;
+ let OperandType = "OPERAND_IMMEDIATE";
}
// Base CPA scalar add/subtract with lsl #imm3 shift
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.h
index 7774d07a214bf..f6d9855e78612 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.h
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.h
@@ -71,6 +71,8 @@ namespace AArch64 {
enum OperandType {
OPERAND_IMPLICIT_IMM_0 = MCOI::OPERAND_FIRST_TARGET,
OPERAND_SHIFT_MSL,
+ OPERAND_SHIFTED_REGISTER,
+ OPERAND_SHIFTED_IMMEDIATE,
};
} // namespace AArch64
diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index 0e73adab15d86..99b583ed54437 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -70,6 +70,13 @@ static MCInst loadPPRImmediate(MCRegister Reg, unsigned RegBitWidth,
.addImm(31); // All lanes true for 16 bits
}
+static MCInst loadFFRImmediate(MCRegister Reg, unsigned RegBitWidth,
+ const APInt &Value) {
+ assert(Value.getZExtValue() == 0 && "Expected initialisation value 0");
+ // For first-fault register FFR, we set it to a true
+ return MCInstBuilder(AArch64::SETFFR);
+}
+
// Generates instructions to load an immediate value into an FPCR register.
static std::vector<MCInst>
loadFPCRImmediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value) {
@@ -80,6 +87,40 @@ loadFPCRImmediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value) {
return {LoadImm, MoveToFPCR};
}
+// Generates instructions to load an immediate value into a pair of W registers
+static std::vector<MCInst>
+loadWSeqPairImmediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value) {
+ MCRegister EvenReg = (Reg - AArch64::W0_W1) * 2 + AArch64::W0 + 0;
+ MCRegister OddReg = (Reg - AArch64::W0_W1) * 2 + AArch64::W0 + 1;
+ assert(Value.getBitWidth() <= RegBitWidth &&
+ "Value must fit in the Register");
+
+ MCInst LoadEven = MCInstBuilder(getLoadImmediateOpcode(RegBitWidth))
+ .addReg(EvenReg)
+ .addImm(Value.getZExtValue());
+ MCInst LoadOdd = MCInstBuilder(getLoadImmediateOpcode(RegBitWidth))
+ .addReg(OddReg)
+ .addImm(Value.getZExtValue());
+ return {LoadEven, LoadOdd};
+}
+
+// Generates instructions to load an immediate value into a pair of X registers
+static std::vector<MCInst>
+loadXSeqPairImmediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value) {
+ MCRegister EvenReg = (Reg - AArch64::X0_X1) * 2 + AArch64::X0 + 0;
+ MCRegister OddReg = (Reg - AArch64::X0_X1) * 2 + AArch64::X0 + 1;
+ assert(Value.getBitWidth() <= RegBitWidth &&
+ "Value must fit in the Register");
+
+ MCInst LoadEven = MCInstBuilder(getLoadImmediateOpcode(RegBitWidth))
+ .addReg(EvenReg)
+ .addImm(Value.getZExtValue());
+ MCInst LoadOdd = MCInstBuilder(getLoadImmediateOpcode(RegBitWidth))
+ .addReg(OddReg)
+ .addImm(Value.getZExtValue());
+ return {LoadEven, LoadOdd};
+}
+
// Fetch base-instruction to load an FP immediate value into a register.
static unsigned getLoadFPImmediateOpcode(unsigned RegBitWidth) {
switch (RegBitWidth) {
@@ -106,6 +147,103 @@ static MCInst loadFPImmediate(MCRegister Reg, unsigned RegBitWidth,
return Instructions;
}
+// Generates instructions to load an immediate value into a DD Reg
+static std::vector<MCInst>
+loadDDRegImmediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value) {
+ MCRegister RegDD0 = AArch64::D0 + (Reg - AArch64::D0_D1);
+ MCRegister RegDD1 = AArch64::D0 + ((Reg - AArch64::D0_D1 + 1) % 32);
+
+ MCInst LoadDD0 = loadFPImmediate(RegDD0, RegBitWidth, Value);
+ MCInst LoadDD1 = loadFPImmediate(RegDD1, RegBitWidth, Value);
+ return {LoadDD0, LoadDD1};
+}
+
+// Generates instructions to load an immediate value into a DDD Reg
+static std::vector<MCInst>
+loadDDDRegImmediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value) {
+ MCRegister RegDDD0 = AArch64::D0 + (Reg - AArch64::D0_D1_D2);
+ MCRegister RegDDD1 = AArch64::D0 + ((Reg - AArch64::D0_D1_D2 + 1) % 32);
+ MCRegister RegDDD2 = AArch64::D0 + ((Reg - AArch64::D0_D1_D2 + 2) % 32);
+
+ MCInst LoadDDD0 = loadFPImmediate(RegDDD0, RegBitWidth, Value);
+ MCInst LoadDDD1 = loadFPImmediate(RegDDD1, RegBitWidth, Value);
+ MCInst LoadDDD2 = loadFPImmediate(RegDDD2, RegBitWidth, Value);
+ return {LoadDDD0, LoadDDD1, LoadDDD2};
+}
+
+// Generates instructions to load an immediate value into a DDDD Reg
+static std::vector<MCInst>
+loadDDDDRegImmediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value) {
+ MCRegister RegDDDD0 = AArch64::D0 + (Reg - AArch64::D0_D1_D2_D3);
+ MCRegister RegDDDD1 = AArch64::D0 + ((Reg - AArch64::D0_D1_D2_D3 + 1) % 32);
+ MCRegister RegDDDD2 = AArch64::D0 + ((Reg - AArch64::D0_D1_D2_D3 + 2) % 32);
+ MCRegister RegDDDD3 = AArch64::D0 + ((Reg - AArch64::D0_D1_D2_D3 + 3) % 32);
+
+ MCInst LoadDDDD0 = loadFPImmediate(RegDDDD0, RegBitWidth, Value);
+ MCInst LoadDDDD1 = loadFPImmediate(RegDDDD1, RegBitWidth, Value);
+ MCInst LoadDDDD2 = loadFPImmediate(RegDDDD2, RegBitWidth, Value);
+ MCInst LoadDDDD3 = loadFPImmediate(RegDDDD3, RegBitWidth, Value);
+ return {LoadDDDD0, LoadDDDD1, LoadDDDD2, LoadDDDD3};
+}
+
+// Generates instructions to load an immediate value into a QQ Reg
+static std::vector<MCInst>
+loadQQRegImmediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value) {
+ MCRegister RegQQ0 = AArch64::Q0 + (Reg - AArch64::Q0_Q1);
+ MCRegister RegQQ1 = AArch64::Q0 + ((Reg - AArch64::Q0_Q1 + 1) % 32);
+
+ MCInst LoadQQ0 = loadFPImmediate(RegQQ0, RegBitWidth, Value);
+ MCInst LoadQQ1 = loadFPImmediate(RegQQ1, RegBitWidth, Value);
+ return {LoadQQ0, LoadQQ1};
+}
+
+// Generates instructions to load an immediate value into a QQQ Reg
+static std::vector<MCInst>
+loadQQQRegImmediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value) {
+ MCRegister RegQQQ0 = AArch64::Q0 + (Reg - AArch64::Q0_Q1_Q2);
+ MCRegister RegQQQ1 = AArch64::Q0 + ((Reg - AArch64::Q0_Q1_Q2 + 1) % 32);
+ MCRegister RegQQQ2 = AArch64::Q0 + ((Reg - AArch64::Q0_Q1_Q2 + 2) % 32);
+
+ MCInst LoadQQQ0 = loadFPImmediate(RegQQQ0, RegBitWidth, Value);
+ MCInst LoadQQQ1 = loadFPImmediate(RegQQQ1, RegBitWidth, Value);
+ MCInst LoadQQQ2 = loadFPImmediate(RegQQQ2, RegBitWidth, Value);
+ return {LoadQQQ0, LoadQQQ1, LoadQQQ2};
+}
+
+// Generates instructions to load an immediate value into a QQQQ Reg
+static std::vector<MCInst>
+loadQQQQRegImmediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value) {
+ MCRegister RegQQQQ0 = AArch64::Q0 + (Reg - AArch64::Q0_Q1_Q2_Q3);
+ MCRegister RegQQQQ1 = AArch64::Q0 + ((Reg - AArch64::Q0_Q1_Q2_Q3 + 1) % 32);
+ MCRegister RegQQQQ2 = AArch64::Q0 + ((Reg - AArch64::Q0_Q1_Q2_Q3 + 2) % 32);
+ MCRegister RegQQQQ3 = AArch64::Q0 + ((Reg - AArch64::Q0_Q1_Q2_Q3 + 3) % 32);
+
+ MCInst LoadQQQQ0 = loadFPImmediate(RegQQQQ0, RegBitWidth, Value);
+ MCInst LoadQQQQ1 = loadFPImmediate(RegQQQQ1, RegBitWidth, Value);
+ MCInst LoadQQQQ2 = loadFPImmediate(RegQQQQ2, RegBitWidth, Value);
+ MCInst LoadQQQQ3 = loadFPImmediate(RegQQQQ3, RegBitWidth, Value);
+ return {LoadQQQQ0, LoadQQQQ1, LoadQQQQ2, LoadQQQQ3};
+}
+
+// Generates instructions to load immediate in the flags register
+static std::vector<MCInst>
+loadNZCVImmediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value) {
+ MCRegister TempReg1 = AArch64::X8;
+ MCRegister TempReg2 = AArch64::X9;
+
+ MCInst MoveFromNZCV =
+ MCInstBuilder(AArch64::MRS).addReg(TempReg1).addImm(AArch64SysReg::NZCV);
+ MCInst LoadMask = MCInstBuilder(AArch64::MOVi64imm).addReg(TempReg2).addImm(0xf0000000);
+ MCInst BitClear = MCInstBuilder(AArch64::BICXrr).addReg(TempReg1).addReg(TempReg1).addReg(TempReg2);
+ MCInst OrrMask = MCInstBuilder(AArch64::ORRXrr).addReg(TempReg1).addReg(TempReg1).addImm(Value.getZExtValue());
+ MCInst MoveToNZCV =
+ MCInstBuilder(AArch64::MSR).addImm(AArch64SysReg::NZCV).addReg(TempReg1);
+
+ if (Value.getZExtValue() == 0)
+ return {MoveFromNZCV, LoadMask, BitClear, MoveToNZCV};
+ return {MoveFromNZCV, LoadMask, BitClear, OrrMask, MoveToNZCV};
+}
+
#include "AArch64GenExegesis.inc"
namespace {
@@ -146,6 +284,30 @@ class ExegesisAArch64Target : public ExegesisTarget {
return {loadZPRImmediate(Reg, 128, Value)};
if (Reg == AArch64::FPCR)
return {loadFPCRImmediate(Reg, 32, Value)};
+ if (Reg == AArch64::NZCV)
+ return {loadNZCVImmediate(Reg, 32, Value)};
+ if (Reg == AArch64::FFR)
+ return {loadFFRImmediate(Reg, 32, Value)};
+ if (AArch64::WSeqPairsClassRegClass.contains(Reg))
+ return {loadWSeqPairImmediate(Reg, 32, Value)};
+ if (AArch64::XSeqPairsClassRegClass.contains(Reg))
+ return {loadXSeqPairImmediate(Reg, 64, Value)};
+ if (AArch64::DDRegClass.contains(Reg))
+ return {loadDDRegImmediate(Reg, 64, Value)};
+ if (AArch64::DDDRegClass.contains(Reg))
+ return {loadDDDRegImmediate(Reg, 64, Value)};
+ if (AArch64::DDDDRegClass.contains(Reg))
+ return {loadDDDDRegImmediate(Reg, 64, Value)};
+ if (AArch64::QQRegClass.contains(Reg))
+ return {loadQQRegImmediate(Reg, 128, Value)};
+ if (AArch64::QQQRegClass.contains(Reg))
+ return {loadQQQRegImmediate(Reg, 128, Value)};
+ if (AArch64::QQQQRegClass.contains(Reg))
+ return {loadQQQQRegImmediate(Reg, 128, Value)};
+ // TODO if (AArch64::PNRRegClass.contains(Reg))
+ // TODO if (AArch64::ZPRRegClass.contains(Reg))
+ // TODO if (AArch64::ZPR2RegClass.contains(Reg))
+ // TODO if (AArch64::ZPR2StridedOrContiguousRegClass.contains(Reg))
errs() << "setRegTo is not implemented, results will be unreliable\n";
return {};
@@ -224,6 +386,12 @@ Error ExegesisAArch64Target::randomizeTargetMCOperand(
case llvm::AArch64::OPERAND_IMPLICIT_IMM_0:
AssignedValue = MCOperand::createImm(0);
return Error::success();
+ case llvm::AArch64::OPERAND_SHIFTED_REGISTER:
+ AssignedValue = MCOperand::createReg(0);
+ return Error::success();
+ case llvm::AArch64::OPERAND_SHIFTED_IMMEDIATE:
+ AssignedValue = MCOperand::createImm(0);
+ return Error::success();
case MCOI::OperandType::OPERAND_PCREL:
AssignedValue = MCOperand::createImm(8);
return Error::success();
>From 7dd1e72b3f100d6937415174da49f253fbf57d49 Mon Sep 17 00:00:00 2001
From: Simon Wallis <simon.wallis2 at arm.com>
Date: Fri, 28 Nov 2025 13:28:34 +0000
Subject: [PATCH 2/3] [llvm-exegesis] Add AArch64 operand initializers,
SetRegTo
Make llvm-exegesis more usable on AArch64 by doing the following:
Add some missing exegesis handling of register classes
Add some missing LLVM AArch64 OperandTypes
Llvm-exegesis can now handle many more instructions.
Load/store instructions not yet supported by llvm-exegesis,
until https://github.com/llvm/llvm-project/pull/144895 lands.
Change-Id: I73d22942943ee5882e89852f538cf1805645def5
---
.../llvm-exegesis/lib/AArch64/Target.cpp | 39 ++++++++++++-------
1 file changed, 24 insertions(+), 15 deletions(-)
diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index 99b583ed54437..5c375999df99e 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -88,36 +88,38 @@ loadFPCRImmediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value) {
}
// Generates instructions to load an immediate value into a pair of W registers
-static std::vector<MCInst>
-loadWSeqPairImmediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value) {
+static std::vector<MCInst> loadWSeqPairImmediate(MCRegister Reg,
+ unsigned RegBitWidth,
+ const APInt &Value) {
MCRegister EvenReg = (Reg - AArch64::W0_W1) * 2 + AArch64::W0 + 0;
MCRegister OddReg = (Reg - AArch64::W0_W1) * 2 + AArch64::W0 + 1;
assert(Value.getBitWidth() <= RegBitWidth &&
"Value must fit in the Register");
MCInst LoadEven = MCInstBuilder(getLoadImmediateOpcode(RegBitWidth))
- .addReg(EvenReg)
- .addImm(Value.getZExtValue());
+ .addReg(EvenReg)
+ .addImm(Value.getZExtValue());
MCInst LoadOdd = MCInstBuilder(getLoadImmediateOpcode(RegBitWidth))
- .addReg(OddReg)
- .addImm(Value.getZExtValue());
+ .addReg(OddReg)
+ .addImm(Value.getZExtValue());
return {LoadEven, LoadOdd};
}
// Generates instructions to load an immediate value into a pair of X registers
-static std::vector<MCInst>
-loadXSeqPairImmediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value) {
+static std::vector<MCInst> loadXSeqPairImmediate(MCRegister Reg,
+ unsigned RegBitWidth,
+ const APInt &Value) {
MCRegister EvenReg = (Reg - AArch64::X0_X1) * 2 + AArch64::X0 + 0;
MCRegister OddReg = (Reg - AArch64::X0_X1) * 2 + AArch64::X0 + 1;
assert(Value.getBitWidth() <= RegBitWidth &&
"Value must fit in the Register");
MCInst LoadEven = MCInstBuilder(getLoadImmediateOpcode(RegBitWidth))
- .addReg(EvenReg)
- .addImm(Value.getZExtValue());
+ .addReg(EvenReg)
+ .addImm(Value.getZExtValue());
MCInst LoadOdd = MCInstBuilder(getLoadImmediateOpcode(RegBitWidth))
- .addReg(OddReg)
- .addImm(Value.getZExtValue());
+ .addReg(OddReg)
+ .addImm(Value.getZExtValue());
return {LoadEven, LoadOdd};
}
@@ -233,9 +235,16 @@ loadNZCVImmediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value) {
MCInst MoveFromNZCV =
MCInstBuilder(AArch64::MRS).addReg(TempReg1).addImm(AArch64SysReg::NZCV);
- MCInst LoadMask = MCInstBuilder(AArch64::MOVi64imm).addReg(TempReg2).addImm(0xf0000000);
- MCInst BitClear = MCInstBuilder(AArch64::BICXrr).addReg(TempReg1).addReg(TempReg1).addReg(TempReg2);
- MCInst OrrMask = MCInstBuilder(AArch64::ORRXrr).addReg(TempReg1).addReg(TempReg1).addImm(Value.getZExtValue());
+ MCInst LoadMask =
+ MCInstBuilder(AArch64::MOVi64imm).addReg(TempReg2).addImm(0xf0000000);
+ MCInst BitClear = MCInstBuilder(AArch64::BICXrr)
+ .addReg(TempReg1)
+ .addReg(TempReg1)
+ .addReg(TempReg2);
+ MCInst OrrMask = MCInstBuilder(AArch64::ORRXrr)
+ .addReg(TempReg1)
+ .addReg(TempReg1)
+ .addImm(Value.getZExtValue());
MCInst MoveToNZCV =
MCInstBuilder(AArch64::MSR).addImm(AArch64SysReg::NZCV).addReg(TempReg1);
>From 13fad4af616fe3cdc8a5a3be000c960a4126e667 Mon Sep 17 00:00:00 2001
From: Simon Wallis <simon.wallis2 at arm.com>
Date: Fri, 28 Nov 2025 13:34:54 +0000
Subject: [PATCH 3/3] [llvm-exegesis] Add AArch64 operand initializers,
SetRegTo
Make llvm-exegesis more usable on AArch64 by doing the following:
Add some missing exegesis handling of register classes
Add some missing LLVM AArch64 OperandTypes
Llvm-exegesis can now handle many more instructions.
Load/store instructions not yet supported by llvm-exegesis,
until https://github.com/llvm/llvm-project/pull/144895 lands.
Change-Id: I344efdcfa66b05321125f21c20f7556da583e7ee
---
llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index 5c375999df99e..d2926c243c607 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -118,8 +118,8 @@ static std::vector<MCInst> loadXSeqPairImmediate(MCRegister Reg,
.addReg(EvenReg)
.addImm(Value.getZExtValue());
MCInst LoadOdd = MCInstBuilder(getLoadImmediateOpcode(RegBitWidth))
- .addReg(OddReg)
- .addImm(Value.getZExtValue());
+ .addReg(OddReg)
+ .addImm(Value.getZExtValue());
return {LoadEven, LoadOdd};
}
@@ -242,9 +242,9 @@ loadNZCVImmediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value) {
.addReg(TempReg1)
.addReg(TempReg2);
MCInst OrrMask = MCInstBuilder(AArch64::ORRXrr)
- .addReg(TempReg1)
- .addReg(TempReg1)
- .addImm(Value.getZExtValue());
+ .addReg(TempReg1)
+ .addReg(TempReg1)
+ .addImm(Value.getZExtValue());
MCInst MoveToNZCV =
MCInstBuilder(AArch64::MSR).addImm(AArch64SysReg::NZCV).addReg(TempReg1);
More information about the llvm-commits
mailing list