Skip to content

Commit 3b9795b

Browse files
authored
[AArch64] Add CodeGen support for scalar FEAT_CPA (#105669)
CPA stands for Checked Pointer Arithmetic and is part of the 2023 MTE architecture extensions for A-profile. The new CPA instructions perform regular pointer arithmetic (such as base register + offset) but check for overflow in the most significant bits of the result, enhancing security by detecting address tampering. In this patch we intend to capture the semantics of pointer arithmetic when it is not folded into loads/stores, then generate the appropriate scalar CPA instructions. In order to preserve pointer arithmetic semantics through the backend, we use the PTRADD SelectionDAG node type. Use backend option `-aarch64-use-featcpa-codegen=true` to enable CPA CodeGen (for a target with CPA enabled). The story of this PR is that initially it introduced the PTRADD SelectionDAG node and the respective visitPTRADD() function, adapted from the CHERI/Morello LLVM tree. The original authors are @davidchisnall, @jrtc27, @arichardson. After a while, @ritter-x2a took the part of the code that was target-independent and merged it separately in #140017. This PR thus remains as the AArch64-part only. Mode details about the CPA extension can be found at: - https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/arm-a-profile-architecture-developments-2023 - https://developer.arm.com/documentation/ddi0602/2023-09/ (e.g ADDPT instruction) This PR follows #79569. It does not address vector FEAT_CPA instructions.
1 parent f8ffb4e commit 3b9795b

File tree

7 files changed

+1612
-2
lines changed

7 files changed

+1612
-2
lines changed

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,14 @@ cl::opt<bool> EnableSVEGISel(
153153
cl::desc("Enable / disable SVE scalable vectors in Global ISel"),
154154
cl::init(false));
155155

156+
// TODO: This option should be removed once we switch to always using PTRADD in
157+
// the SelectionDAG.
158+
static cl::opt<bool> UseFEATCPACodegen(
159+
"aarch64-use-featcpa-codegen", cl::Hidden,
160+
cl::desc("Generate ISD::PTRADD nodes for pointer arithmetic in "
161+
"SelectionDAG for FEAT_CPA"),
162+
cl::init(false));
163+
156164
/// Value type used for condition codes.
157165
static const MVT MVT_CC = MVT::i32;
158166

@@ -30480,3 +30488,8 @@ bool AArch64TargetLowering::isTypeDesirableForOp(unsigned Opc, EVT VT) const {
3048030488

3048130489
return TargetLowering::isTypeDesirableForOp(Opc, VT);
3048230490
}
30491+
30492+
bool AArch64TargetLowering::shouldPreservePtrArith(const Function &F,
30493+
EVT VT) const {
30494+
return Subtarget->hasCPA() && UseFEATCPACodegen;
30495+
}

llvm/lib/Target/AArch64/AArch64ISelLowering.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,10 @@ class AArch64TargetLowering : public TargetLowering {
539539
/// True if stack clash protection is enabled for this functions.
540540
bool hasInlineStackProbe(const MachineFunction &MF) const override;
541541

542+
/// In AArch64, true if FEAT_CPA is present. Allows pointer arithmetic
543+
/// semantics to be preserved for instruction selection.
544+
bool shouldPreservePtrArith(const Function &F, EVT PtrVT) const override;
545+
542546
private:
543547
/// Keep a pointer to the AArch64Subtarget around so that we can
544548
/// make the right decision when generating code for different targets.

llvm/lib/Target/AArch64/AArch64InstrFormats.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13124,7 +13124,7 @@ def LSLImm3ShiftOperand : AsmOperandClass {
1312413124
let DiagnosticType = "AddSubLSLImm3ShiftLarge";
1312513125
}
1312613126

13127-
def lsl_imm3_shift_operand : Operand<i32> {
13127+
def lsl_imm3_shift_operand : Operand<i64> {
1312813128
let PrintMethod = "printShifter";
1312913129
let ParserMatchClass = LSLImm3ShiftOperand;
1313013130
}

llvm/lib/Target/AArch64/AArch64InstrInfo.td

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10741,6 +10741,21 @@ let Predicates = [HasCPA] in {
1074110741
// Scalar multiply-add/subtract
1074210742
def MADDPT : MulAccumCPA<0, "maddpt">;
1074310743
def MSUBPT : MulAccumCPA<1, "msubpt">;
10744+
10745+
def : Pat<(ptradd GPR64sp:$Rn, GPR64sp:$Rm),
10746+
(ADDPT_shift GPR64sp:$Rn, GPR64sp:$Rm, (i64 0))>;
10747+
def : Pat<(ptradd GPR64sp:$Rn, (shl GPR64sp:$Rm, (i64 imm0_7:$imm))),
10748+
(ADDPT_shift GPR64sp:$Rn, GPR64sp:$Rm,
10749+
(i64 imm0_7:$imm))>;
10750+
def : Pat<(ptradd GPR64sp:$Rn, (ineg GPR64sp:$Rm)),
10751+
(SUBPT_shift GPR64sp:$Rn, GPR64sp:$Rm, (i64 0))>;
10752+
def : Pat<(ptradd GPR64sp:$Rn, (ineg (shl GPR64sp:$Rm, (i64 imm0_7:$imm)))),
10753+
(SUBPT_shift GPR64sp:$Rn, GPR64sp:$Rm,
10754+
(i64 imm0_7:$imm))>;
10755+
def : Pat<(ptradd GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)),
10756+
(MADDPT GPR64:$Rn, GPR64:$Rm, GPR64:$Ra)>;
10757+
def : Pat<(ptradd GPR64:$Ra, (mul GPR64:$Rn, (ineg GPR64:$Rm))),
10758+
(MSUBPT GPR64:$Rn, GPR64:$Rm, GPR64:$Ra)>;
1074410759
}
1074510760

1074610761
def round_v4fp32_to_v4bf16 :

llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2197,8 +2197,14 @@ bool AArch64InstructionSelector::preISelLower(MachineInstr &I) {
21972197
}
21982198
return Changed;
21992199
}
2200-
case TargetOpcode::G_PTR_ADD:
2200+
case TargetOpcode::G_PTR_ADD: {
2201+
// If Checked Pointer Arithmetic (FEAT_CPA) is present, preserve the pointer
2202+
// arithmetic semantics instead of falling back to regular arithmetic.
2203+
const auto &TL = STI.getTargetLowering();
2204+
if (TL->shouldPreservePtrArith(MF.getFunction(), EVT()))
2205+
return false;
22012206
return convertPtrAddToAdd(I, MRI);
2207+
}
22022208
case TargetOpcode::G_LOAD: {
22032209
// For scalar loads of pointers, we try to convert the dest type from p0
22042210
// to s64 so that our imported patterns can match. Like with the G_PTR_ADD

0 commit comments

Comments
 (0)