Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AArch64] Assembly support for the Checked Pointer Arithmetic Extension #73777

Merged
merged 1 commit into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions clang/test/Driver/aarch64-v95a.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,8 @@
// RUN: %clang -target aarch64_be -mbig-endian -march=armv9.5-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV95A-BE %s
// GENERICV95A-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "generic" "-target-feature" "+neon" "-target-feature" "+v9.5a"

// ===== Features supported on aarch64 =====

// RUN: %clang -target aarch64 -march=armv9.5a+cpa -### -c %s 2>&1 | FileCheck -check-prefix=V95A-CPA %s
// RUN: %clang -target aarch64 -march=armv9.5-a+cpa -### -c %s 2>&1 | FileCheck -check-prefix=V95A-CPA %s
// V95A-CPA: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+neon" "-target-feature" "+v9.5a" "-target-feature" "+cpa"
5 changes: 4 additions & 1 deletion llvm/include/llvm/TargetParser/AArch64TargetParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ enum ArchExtKind : unsigned {
AEK_SMEF8F16 = 69, // FEAT_SME_F8F16
AEK_SMEF8F32 = 70, // FEAT_SME_F8F32
AEK_SMEFA64 = 71, // FEAT_SME_FA64
AEK_CPA = 72, // FEAT_CPA
AEK_NUM_EXTENSIONS
};
using ExtensionBitset = Bitset<AEK_NUM_EXTENSIONS>;
Expand Down Expand Up @@ -295,6 +296,7 @@ inline constexpr ExtensionInfo Extensions[] = {
{"sme-f8f16", AArch64::AEK_SMEF8F16, "+sme-f8f16", "-sme-f8f16", FEAT_INIT, "+sme2,+fp8", 0},
{"sme-f8f32", AArch64::AEK_SMEF8F32, "+sme-f8f32", "-sme-f8f32", FEAT_INIT, "+sme2,+fp8", 0},
{"sme-fa64", AArch64::AEK_SMEFA64, "+sme-fa64", "-sme-fa64", FEAT_INIT, "", 0},
{"cpa", AArch64::AEK_CPA, "+cpa", "-cpa", FEAT_INIT, "", 0},
// Special cases
{"none", AArch64::AEK_NONE, {}, {}, FEAT_INIT, "", ExtensionInfo::MaxFMVPriority},
};
Expand Down Expand Up @@ -378,7 +380,8 @@ inline constexpr ArchInfo ARMV9_3A = { VersionTuple{9, 3}, AProfile, "armv9.3-a
AArch64::ExtensionBitset({AArch64::AEK_MOPS, AArch64::AEK_HBC}))};
inline constexpr ArchInfo ARMV9_4A = { VersionTuple{9, 4}, AProfile, "armv9.4-a", "+v9.4a", (ARMV9_3A.DefaultExts |
AArch64::ExtensionBitset({AArch64::AEK_SPECRES2, AArch64::AEK_CSSC, AArch64::AEK_RASv2}))};
inline constexpr ArchInfo ARMV9_5A = { VersionTuple{9, 5}, AProfile, "armv9.5-a", "+v9.5a", (ARMV9_4A.DefaultExts)};
inline constexpr ArchInfo ARMV9_5A = { VersionTuple{9, 5}, AProfile, "armv9.5-a", "+v9.5a", (ARMV9_4A.DefaultExts |
AArch64::ExtensionBitset({AArch64::AEK_CPA}))};
// For v8-R, we do not enable crypto and align with GCC that enables a more minimal set of optional architecture extensions.
inline constexpr ArchInfo ARMV8R = { VersionTuple{8, 0}, RProfile, "armv8-r", "+v8r", (ARMV8_5A.DefaultExts |
AArch64::ExtensionBitset({AArch64::AEK_SSBS,
Expand Down
5 changes: 4 additions & 1 deletion llvm/lib/Target/AArch64/AArch64.td
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,9 @@ def FeatureLdpAlignedOnly : SubtargetFeature<"ldp-aligned-only", "HasLdpAlignedO
def FeatureStpAlignedOnly : SubtargetFeature<"stp-aligned-only", "HasStpAlignedOnly",
"true", "In order to emit stp, first check if the store will be aligned to 2 * element_size">;

def FeatureCPA : SubtargetFeature<"cpa", "HasCPA", "true",
"Enable ARMv9.5-A Checked Pointer Arithmetic (FEAT_CPA)">;

//===----------------------------------------------------------------------===//
// Architectures.
//
Expand Down Expand Up @@ -692,7 +695,7 @@ def HasV9_4aOps : SubtargetFeature<

def HasV9_5aOps : SubtargetFeature<
"v9.5a", "HasV9_5aOps", "true", "Support ARM v9.5a instructions",
[HasV9_4aOps]>;
[HasV9_4aOps, FeatureCPA]>;

def HasV8_0rOps : SubtargetFeature<
"v8r", "HasV8_0rOps", "true", "Support ARM v8r instructions",
Expand Down
52 changes: 52 additions & 0 deletions llvm/lib/Target/AArch64/AArch64InstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -12446,6 +12446,58 @@ class SystemPXtI<bit L, string asm> :
BaseSYSPEncoding<L, asm, "\t$op1, $Cn, $Cm, $op2, $Rt", (outs),
(ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, XSeqPairClassOperand:$Rt)>;

//----------------------------------------------------------------------------
// 2023 Armv9.5 Extensions
//----------------------------------------------------------------------------

//---
// Checked Pointer Arithmetic (FEAT_CPA)
//---

def LSLImm3ShiftOperand : AsmOperandClass {
let SuperClasses = [ExtendOperandLSL64];
let Name = "LSLImm3Shift";
let RenderMethod = "addLSLImm3ShifterOperands";
let DiagnosticType = "AddSubLSLImm3ShiftLarge";
}

def lsl_imm3_shift_operand : Operand<i32> {
let PrintMethod = "printShifter";
let ParserMatchClass = LSLImm3ShiftOperand;
}

// Base CPA scalar add/subtract with lsl #imm3 shift
class BaseAddSubCPA<bit isSub, string asm> : I<(outs GPR64sp:$Rd),
(ins GPR64sp:$Rn, GPR64:$Rm, lsl_imm3_shift_operand:$shift_imm),
asm, "\t$Rd, $Rn, $Rm$shift_imm", "", []>, Sched<[]> {
bits<5> Rd;
bits<5> Rn;
bits<5> Rm;
bits<3> shift_imm;
let Inst{31} = 0b1;
let Inst{30} = isSub;
let Inst{29-21} = 0b011010000;
let Inst{20-16} = Rm;
let Inst{15-13} = 0b001;
let Inst{12-10} = shift_imm;
let Inst{9-5} = Rn;
let Inst{4-0} = Rd;
}

// Alias for CPA scalar add/subtract with no shift
class AddSubCPAAlias<string asm, Instruction inst>
: InstAlias<asm#"\t$Rd, $Rn, $Rm",
(inst GPR64sp:$Rd, GPR64sp:$Rn, GPR64:$Rm, 0)>;

multiclass AddSubCPA<bit isSub, string asm> {
def _shift : BaseAddSubCPA<isSub, asm>;
def _noshift : AddSubCPAAlias<asm, !cast<Instruction>(NAME#"_shift")>;
}

class MulAccumCPA<bit isSub, string asm>
: BaseMulAccum<isSub, 0b011, GPR64, GPR64, asm, []>, Sched<[]> {
let Inst{31} = 0b1;
}

//----------------------------------------------------------------------------
// Allow the size specifier tokens to be upper case, not just lower.
Expand Down
19 changes: 19 additions & 0 deletions llvm/lib/Target/AArch64/AArch64InstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,8 @@ def HasCHK : Predicate<"Subtarget->hasCHK()">,
AssemblerPredicateWithAll<(all_of FeatureCHK), "chk">;
def HasGCS : Predicate<"Subtarget->hasGCS()">,
AssemblerPredicateWithAll<(all_of FeatureGCS), "gcs">;
def HasCPA : Predicate<"Subtarget->hasCPA()">,
AssemblerPredicateWithAll<(all_of FeatureCPA), "cpa">;
def IsLE : Predicate<"Subtarget->isLittleEndian()">;
def IsBE : Predicate<"!Subtarget->isLittleEndian()">;
def IsWindows : Predicate<"Subtarget->isTargetWindows()">;
Expand Down Expand Up @@ -9367,6 +9369,10 @@ let Predicates = [HasD128] in {
}
}

//===----------------------------===//
// 2023 Architecture Extensions:
//===----------------------------===//

let Predicates = [HasFP8] in {
defm F1CVTL : SIMDMixedTwoVectorFP8<0b00, "f1cvtl">;
defm F2CVTL : SIMDMixedTwoVectorFP8<0b01, "f2cvtl">;
Expand Down Expand Up @@ -9408,6 +9414,19 @@ let Predicates = [HasFP8DOT4] in {
defm FDOT : SIMDThreeSameVectorDOT4<"fdot">;
} // End let Predicates = [HasFP8DOT4]

//===----------------------------------------------------------------------===//
// Checked Pointer Arithmetic (FEAT_CPA)
//===----------------------------------------------------------------------===//
let Predicates = [HasCPA] in {
// Scalar add/subtract
defm ADDPT : AddSubCPA<0, "addpt">;
defm SUBPT : AddSubCPA<1, "subpt">;

// Scalar multiply-add/subtract
def MADDPT : MulAccumCPA<0, "maddpt">;
def MSUBPT : MulAccumCPA<1, "msubpt">;
}

include "AArch64InstrAtomics.td"
include "AArch64SVEInstrInfo.td"
include "AArch64SMEInstrInfo.td"
Expand Down
21 changes: 21 additions & 0 deletions llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -4163,3 +4163,24 @@ let Predicates = [HasSVE2orSME2, HasLUT] in {
// LUTI4 (two contiguous registers)
defm LUTI4_Z2ZZI : sve2_luti4_vector_vg2_index<"luti4">;
} // End HasSVE2orSME2, HasLUT

//===----------------------------------------------------------------------===//
// Checked Pointer Arithmetic (FEAT_CPA)
//===----------------------------------------------------------------------===//
let Predicates = [HasSVEorSME, HasCPA] in {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that FEAT_CPA is only [HasSVE, HasCPA] .
At least that is what I see here:
https://developer.arm.com/documentation/ddi0602/2023-09/SVE-Instructions/ADDPT--predicated---Add-checked-pointer-vectors--predicated--?lang=en
if !IsFeatureImplemented(FEAT_SVE) || !IsFeatureImplemented(FEAT_CPA) then
UNDEFINED;
And in bellow I see :
CheckNonStreamingSVEEnabled();
I believe it means that these instructions are not available in streaming mode.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! Thanks @CarolineConcatto
I'll upload a fix for this soon

// Add/subtract (vectors, unpredicated)
def ADD_ZZZ_CPA : sve_int_bin_cons_arit_0<0b11, 0b010, "addpt", ZPR64>;
def SUB_ZZZ_CPA : sve_int_bin_cons_arit_0<0b11, 0b011, "subpt", ZPR64>;

// Add/subtract (vectors, predicated)
let DestructiveInstType = DestructiveBinaryComm in {
def ADD_ZPmZ_CPA : sve_int_bin_pred_arit_log<0b11, 0b00, 0b100, "addpt", ZPR64>;
def SUB_ZPmZ_CPA : sve_int_bin_pred_arit_log<0b11, 0b00, 0b101, "subpt", ZPR64>;
}

// Multiply-add vectors, writing multiplicand
def MAD_CPA : sve_int_mad_cpa<"madpt">;

// Multiply-add vectors, writing addend
def MLA_CPA : sve_int_mla_cpa<"mlapt">;
}
2 changes: 1 addition & 1 deletion llvm/lib/Target/AArch64/AArch64SchedA64FX.td
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def A64FXModel : SchedMachineModel {
[HasSVE2, HasSVE2AES, HasSVE2SM4, HasSVE2SHA3, HasSVE2BitPerm, HasPAuth,
HasSVE2orSME, HasMTE, HasMatMulInt8, HasBF16, HasSME2, HasSME2p1, HasSVE2p1,
HasSVE2p1_or_HasSME2p1, HasSMEF16F16, HasSSVE_FP8FMA, HasSMEF8F16, HasSMEF8F32,
HasSMEFA64];
HasSMEFA64, HasCPA];

let FullInstRWOverlapCheck = 0;
}
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/AArch64/AArch64SchedNeoverseN2.td
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def NeoverseN2Model : SchedMachineModel {
let CompleteModel = 1;

list<Predicate> UnsupportedFeatures = !listconcat(SMEUnsupported.F,
[HasSVE2p1]);
[HasSVE2p1, HasCPA]);
}

//===----------------------------------------------------------------------===//
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/AArch64/AArch64SchedNeoverseV1.td
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def NeoverseV1Model : SchedMachineModel {

list<Predicate> UnsupportedFeatures = !listconcat(SVE2Unsupported.F,
SMEUnsupported.F,
[HasMTE]);
[HasMTE, HasCPA]);
}

//===----------------------------------------------------------------------===//
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/AArch64/AArch64SchedNeoverseV2.td
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def NeoverseV2Model : SchedMachineModel {
let CompleteModel = 1;

list<Predicate> UnsupportedFeatures = !listconcat(SMEUnsupported.F,
[HasSVE2p1]);
[HasSVE2p1, HasCPA]);
}

//===----------------------------------------------------------------------===//
Expand Down
18 changes: 18 additions & 0 deletions llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1541,6 +1541,13 @@ class AArch64Operand : public MCParsedAsmOperand {
getShiftExtendAmount() <= 4;
}

bool isLSLImm3Shift() const {
if (!isShiftExtend())
return false;
AArch64_AM::ShiftExtendType ET = getShiftExtendType();
return ET == AArch64_AM::LSL && getShiftExtendAmount() <= 7;
}

template<int Width> bool isMemXExtend() const {
if (!isExtend())
return false;
Expand Down Expand Up @@ -2091,6 +2098,12 @@ class AArch64Operand : public MCParsedAsmOperand {
Inst.addOperand(MCOperand::createImm(Imm));
}

void addLSLImm3ShifterOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
unsigned Imm = getShiftExtendAmount();
Inst.addOperand(MCOperand::createImm(Imm));
}

void addSyspXzrPairOperand(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");

Expand Down Expand Up @@ -3664,6 +3677,7 @@ static const struct Extension {
{"sme-f8f16", {AArch64::FeatureSMEF8F16}},
{"sme-f8f32", {AArch64::FeatureSMEF8F32}},
{"sme-fa64", {AArch64::FeatureSMEFA64}},
{"cpa", {AArch64::FeatureCPA}},
};

static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
Expand Down Expand Up @@ -6064,6 +6078,9 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
"Invalid vector list, expected list with each SVE vector in the list "
"4 registers apart, and the first register in the range [z0, z3] or "
"[z16, z19] and with correct element type");
case Match_AddSubLSLImm3ShiftLarge:
return Error(Loc,
"expected 'lsl' with optional integer in range [0, 7]");
default:
llvm_unreachable("unexpected error code!");
}
Expand Down Expand Up @@ -6448,6 +6465,7 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_InvalidMemoryIndexed8:
case Match_InvalidMemoryIndexed16:
case Match_InvalidCondCode:
case Match_AddSubLSLImm3ShiftLarge:
case Match_AddSubRegExtendSmall:
case Match_AddSubRegExtendLarge:
case Match_AddSubSecondSource:
Expand Down
31 changes: 31 additions & 0 deletions llvm/lib/Target/AArch64/SVEInstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -10424,3 +10424,34 @@ multiclass sve2_luti4_vector_vg2_index<string mnemonic> {
let Inst{23-22} = idx;
}
}

//===----------------------------------------------------------------------===//
// Checked Pointer Arithmetic (FEAT_CPA)
//===----------------------------------------------------------------------===//
class sve_int_mad_cpa<string asm>
: I<(outs ZPR64:$Zdn), (ins ZPR64:$_Zdn, ZPR64:$Zm, ZPR64:$Za),
asm, "\t$Zdn, $Zm, $Za", "", []>, Sched<[]> {
bits<5> Zdn;
bits<5> Zm;
bits<5> Za;
let Inst{31-24} = 0b01000100;
let Inst{23-22} = 0b11; // sz
let Inst{21} = 0b0;
let Inst{20-16} = Zm;
let Inst{15} = 0b1;
let Inst{14-10} = 0b10110; // opc
let Inst{9-5} = Za;
let Inst{4-0} = Zdn;

let Constraints = "$Zdn = $_Zdn";
let DestructiveInstType = DestructiveOther;
let ElementSize = ZPR64.ElementSize;
let hasSideEffects = 0;
}

class sve_int_mla_cpa<string asm>
: sve2_int_mla<0b11, 0b10100, asm, ZPR64, ZPR64> {
let Inst{15} = 0b1;

let ElementSize = ZPR64.ElementSize;
}
69 changes: 69 additions & 0 deletions llvm/test/MC/AArch64/SVE/armv9.5a-cpa.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve -mattr=+cpa < %s \
// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme -mattr=+cpa < %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: not llvm-mc -triple=aarch64 -show-encoding -mattr=+cpa < %s 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-ERROR-NO-SVESME
// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve < %s 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-ERROR-NO-CPA
// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sme < %s 2>&1 \
// RUN: | FileCheck %s --check-prefix=CHECK-ERROR-NO-CPA
// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve -mattr=+cpa < %s \
// RUN: | llvm-objdump -d --mattr=+sve --mattr=+cpa - \
// RUN: | FileCheck %s --check-prefix=CHECK-INST
// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve -mattr=+cpa < %s \
// RUN: | llvm-objdump -d --mattr=+sve --mattr=-cpa - \
// RUN: | FileCheck %s --check-prefix=CHECK-UNKNOWN
// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve -mattr=+cpa < %s \
// RUN: | llvm-objdump -d --mattr=-sve --mattr=+cpa - \
// RUN: | FileCheck %s --check-prefix=CHECK-UNKNOWN

addpt z23.d, z13.d, z8.d
// CHECK-INST: addpt z23.d, z13.d, z8.d
// CHECK-ENCODING: [0xb7,0x09,0xe8,0x04]
// CHECK-ERROR: instruction requires: cpa sve or sme
// CHECK-ERROR-NO-SVESME: instruction requires: sve or sme
// CHECK-ERROR-NO-CPA: instruction requires: cpa
// CHECK-UNKNOWN: 04e809b7 <unknown>

addpt z23.d, p3/m, z23.d, z13.d
// CHECK-INST: addpt z23.d, p3/m, z23.d, z13.d
// CHECK-ENCODING: [0xb7,0x0d,0xc4,0x04]
// CHECK-ERROR: instruction requires: cpa sve or sme
// CHECK-ERROR-NO-SVESME: instruction requires: sve or sme
// CHECK-ERROR-NO-CPA: instruction requires: cpa
// CHECK-UNKNOWN: 04c40db7 <unknown>

subpt z23.d, z13.d, z8.d
// CHECK-INST: subpt z23.d, z13.d, z8.d
// CHECK-ENCODING: [0xb7,0x0d,0xe8,0x04]
// CHECK-ERROR: instruction requires: cpa sve or sme
// CHECK-ERROR-NO-SVESME: instruction requires: sve or sme
// CHECK-ERROR-NO-CPA: instruction requires: cpa
// CHECK-UNKNOWN: 04e80db7 <unknown>

subpt z23.d, p3/m, z23.d, z13.d
// CHECK-INST: subpt z23.d, p3/m, z23.d, z13.d
// CHECK-ENCODING: [0xb7,0x0d,0xc5,0x04]
// CHECK-ERROR: instruction requires: cpa sve or sme
// CHECK-ERROR-NO-SVESME: instruction requires: sve or sme
// CHECK-ERROR-NO-CPA: instruction requires: cpa
// CHECK-UNKNOWN: 04c50db7 <unknown>

madpt z0.d, z1.d, z31.d
// CHECK-INST: madpt z0.d, z1.d, z31.d
// CHECK-ENCODING: [0xe0,0xdb,0xc1,0x44]
// CHECK-ERROR: instruction requires: cpa sve or sme
// CHECK-ERROR-NO-SVESME: instruction requires: sve or sme
// CHECK-ERROR-NO-CPA: instruction requires: cpa
// CHECK-UNKNOWN: 44c1dbe0 <unknown>

mlapt z0.d, z1.d, z31.d
// CHECK-INST: mlapt z0.d, z1.d, z31.d
// CHECK-ENCODING: [0x20,0xd0,0xdf,0x44]
// CHECK-ERROR: instruction requires: cpa sve or sme
// CHECK-ERROR-NO-SVESME: instruction requires: sve or sme
// CHECK-ERROR-NO-CPA: instruction requires: cpa
// CHECK-UNKNOWN: 44dfd020 <unknown>
Loading
Loading