Skip to content

Commit

Permalink
[AArch64][v8.5A] Add Memory Tagging instructions
Browse files Browse the repository at this point in the history
This adds new instructions to manipluate tagged pointers, and to load
and store the tags associated with memory.

Patch by Pablo Barrio, David Spickett and Oliver Stannard!

Differential revision: https://reviews.llvm.org/D52490

llvm-svn: 343572
  • Loading branch information
ostannard committed Oct 2, 2018
1 parent 2a5fcba commit c419028
Show file tree
Hide file tree
Showing 9 changed files with 1,805 additions and 25 deletions.
115 changes: 111 additions & 4 deletions llvm/lib/Target/AArch64/AArch64InstrFormats.td
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,12 @@ def simm10Scaled : Operand<i64> {
let PrintMethod = "printImmScale<8>";
}

def simm9s16 : Operand<i64> {
let ParserMatchClass = SImmScaledMemoryIndexed<9, 16>;
let DecoderMethod = "DecodeSImm<9>";
let PrintMethod = "printImmScale<16>";
}

// uimm6 predicate - True if the immediate is in the range [0, 63].
def UImm6Operand : AsmOperandClass {
let Name = "UImm6";
Expand Down Expand Up @@ -366,6 +372,7 @@ def UImm6s1Operand : UImmScaledMemoryIndexed<6, 1>;
def UImm6s2Operand : UImmScaledMemoryIndexed<6, 2>;
def UImm6s4Operand : UImmScaledMemoryIndexed<6, 4>;
def UImm6s8Operand : UImmScaledMemoryIndexed<6, 8>;
def UImm6s16Operand : UImmScaledMemoryIndexed<6, 16>;

def uimm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
let ParserMatchClass = UImm6s1Operand;
Expand All @@ -385,6 +392,11 @@ def uimm6s8 : Operand<i64>, ImmLeaf<i64,
let PrintMethod = "printImmScale<8>";
let ParserMatchClass = UImm6s8Operand;
}
def uimm6s16 : Operand<i64>, ImmLeaf<i64,
[{ return Imm >= 0 && Imm < (64*16) && ((Imm % 16) == 0); }]> {
let PrintMethod = "printImmScale<16>";
let ParserMatchClass = UImm6s16Operand;
}

// simm6sN predicate - True if the immediate is a multiple of N in the range
// [-32 * N, 31 * N].
Expand Down Expand Up @@ -1740,10 +1752,12 @@ multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
}

class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
SDPatternOperator OpNode>
: I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
SDPatternOperator OpNode,
RegisterClass in1regtype = regtype,
RegisterClass in2regtype = regtype>
: I<(outs regtype:$Rd), (ins in1regtype:$Rn, in2regtype:$Rm),
asm, "\t$Rd, $Rn, $Rm", "",
[(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]> {
[(set regtype:$Rd, (OpNode in1regtype:$Rn, in2regtype:$Rm))]> {
bits<5> Rd;
bits<5> Rn;
bits<5> Rm;
Expand Down Expand Up @@ -2009,7 +2023,6 @@ class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
let Inst{28-24} = 0b10001;
let Inst{9-5} = Rn;
let Inst{4-0} = Rd;
let DecoderMethod = "DecodeBaseAddSubImm";
}

class AddSubImmShift<bit isSub, bit setFlags, RegisterClass dstRegtype,
Expand All @@ -2021,6 +2034,7 @@ class AddSubImmShift<bit isSub, bit setFlags, RegisterClass dstRegtype,
bits<14> imm;
let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
let Inst{21-10} = imm{11-0};
let DecoderMethod = "DecodeAddSubImmShift";
}

class BaseAddSubRegPseudo<RegisterClass regtype,
Expand Down Expand Up @@ -2298,6 +2312,27 @@ multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
}

class AddSubG<bit isSub, string asm_inst, SDPatternOperator OpNode>
: BaseAddSubImm<
isSub, 0, GPR64sp, asm_inst, "\t$Rd, $Rn, $imm6, $imm4",
(ins GPR64sp:$Rn, uimm6s16:$imm6, imm0_15:$imm4),
(set GPR64sp:$Rd, (OpNode GPR64sp:$Rn, imm0_63:$imm6, imm0_15:$imm4))> {
bits<6> imm6;
bits<4> imm4;
let Inst{31} = 1;
let Inst{23-22} = 0b10;
let Inst{21-16} = imm6;
let Inst{15-14} = 0b00;
let Inst{13-10} = imm4;
let Unpredictable{15-14} = 0b11;
}

class SUBP<bit setsFlags, string asm_instr, SDPatternOperator OpNode>
: BaseTwoOperand<0b0000, GPR64, asm_instr, null_frag, GPR64sp, GPR64sp> {
let Inst{31} = 1;
let Inst{29} = setsFlags;
}

//---
// Extract
//---
Expand Down Expand Up @@ -3959,6 +3994,78 @@ class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
let Constraints = "@earlyclobber $Ws";
}

// Armv8.5-A Memory Tagging Extension
class BaseMemTag<bits<2> opc1, bits<2> opc2, string asm_insn,
string asm_opnds, string cstr, dag oops, dag iops>
: I<oops, iops, asm_insn, asm_opnds, cstr, []>,
Sched<[]> {
bits<5> Rn;

let Inst{31-24} = 0b11011001;
let Inst{23-22} = opc1;
let Inst{21} = 1;
// Inst{20-12} defined by subclass
let Inst{11-10} = opc2;
let Inst{9-5} = Rn;
// Inst{4-0} defined by subclass
}

class MemTagVector<bit Load, string asm_insn, string asm_opnds,
dag oops, dag iops>
: BaseMemTag<{0b1, Load}, 0b00, asm_insn, asm_opnds,
"$Rn = $wback,@earlyclobber $wback", oops, iops> {
bits<5> Rt;

let Inst{20-12} = 0b000000000;
let Inst{4-0} = Rt;

let mayLoad = Load;
}

class MemTagLoad<string asm_insn, string asm_opnds>
: BaseMemTag<0b01, 0b00, asm_insn, asm_opnds, "", (outs GPR64:$Rt),
(ins GPR64sp:$Rn, simm9s16:$offset)> {
bits<5> Rt;
bits<9> offset;

let Inst{20-12} = offset;
let Inst{4-0} = Rt;

let mayLoad = 1;
}

class BaseMemTagStore<bits<2> opc1, bits<2> opc2, string asm_insn,
string asm_opnds, string cstr, dag oops, dag iops>
: BaseMemTag<opc1, opc2, asm_insn, asm_opnds, cstr, oops, iops> {
bits<5> Rt;
bits<9> offset;

let Inst{20-12} = offset;
let Inst{4-0} = 0b11111;
let Unpredictable{4-0} = 0b11111;

let mayStore = 1;
}

multiclass MemTagStore<bits<2> opc1, string insn> {
def Offset :
BaseMemTagStore<opc1, 0b10, insn, "\t[$Rn, $offset]", "",
(outs), (ins GPR64sp:$Rn, simm9s16:$offset)>;
def PreIndex :
BaseMemTagStore<opc1, 0b11, insn, "\t[$Rn, $offset]!",
"$Rn = $wback,@earlyclobber $wback",
(outs GPR64sp:$wback),
(ins GPR64sp:$Rn, simm9s16:$offset)>;
def PostIndex :
BaseMemTagStore<opc1, 0b01, insn, "\t[$Rn], $offset",
"$Rn = $wback,@earlyclobber $wback",
(outs GPR64sp:$wback),
(ins GPR64sp:$Rn, simm9s16:$offset)>;

def : InstAlias<insn # "\t[$Rn]",
(!cast<Instruction>(NAME # "Offset") GPR64sp:$Rn, 0)>;
}

//---
// Exception generation
//---
Expand Down
46 changes: 46 additions & 0 deletions llvm/lib/Target/AArch64/AArch64InstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ def HasCCDP : Predicate<"Subtarget->hasCCDP()">,
AssemblerPredicate<"FeatureCacheDeepPersist", "ccdp">;
def HasBTI : Predicate<"Subtarget->hasBTI()">,
AssemblerPredicate<"FeatureBranchTargetId", "bti">;
def HasMTE : Predicate<"Subtarget->hasMTE()">,
AssemblerPredicate<"FeatureMTE", "mte">;
def IsLE : Predicate<"Subtarget->isLittleEndian()">;
def IsBE : Predicate<"!Subtarget->isLittleEndian()">;
def UseAlternateSExtLoadCVTF32
Expand Down Expand Up @@ -1123,6 +1125,50 @@ defm : STOPregister<"stsmin","LDSMIN">;// STSMINx
defm : STOPregister<"stumax","LDUMAX">;// STUMAXx
defm : STOPregister<"stumin","LDUMIN">;// STUMINx

// v8.5 Memory Tagging Extension
let Predicates = [HasMTE] in {

def IRG : BaseTwoOperand<0b0100, GPR64sp, "irg", null_frag, GPR64sp, GPR64>,
Sched<[]>{
let Inst{31} = 1;
}
def GMI : BaseTwoOperand<0b0101, GPR64, "gmi", null_frag, GPR64sp>, Sched<[]>{
let Inst{31} = 1;
let isNotDuplicable = 1;
}
def ADDG : AddSubG<0, "addg", null_frag>;
def SUBG : AddSubG<1, "subg", null_frag>;

def : InstAlias<"irg $dst, $src", (IRG GPR64sp:$dst, GPR64sp:$src, XZR), 1>;

def SUBP : SUBP<0, "subp", null_frag>, Sched<[]>;
def SUBPS : SUBP<1, "subps", null_frag>, Sched<[]>{
let Defs = [NZCV];
}

def : InstAlias<"cmpp $lhs, $rhs", (SUBPS XZR, GPR64sp:$lhs, GPR64sp:$rhs), 0>;

def LDG : MemTagLoad<"ldg", "\t$Rt, [$Rn, $offset]">;
def : InstAlias<"ldg $Rt, [$Rn]", (LDG GPR64:$Rt, GPR64sp:$Rn, 0), 1>;

def LDGV : MemTagVector<1, "ldgv", "\t$Rt, [$Rn]!",
(outs GPR64sp:$wback, GPR64:$Rt), (ins GPR64sp:$Rn)> {
let DecoderMethod = "DecodeLoadAllocTagArrayInstruction";
}
def STGV : MemTagVector<0, "stgv", "\t$Rt, [$Rn]!",
(outs GPR64sp:$wback), (ins GPR64:$Rt, GPR64sp:$Rn)>;

defm STG : MemTagStore<0b00, "stg">;
defm STZG : MemTagStore<0b01, "stzg">;
defm ST2G : MemTagStore<0b10, "st2g">;
defm STZ2G : MemTagStore<0b11, "stz2g">;

defm STGP : StorePairOffset <0b01, 0, GPR64z, simm7s16, "stgp">;
def STGPpre : StorePairPreIdx <0b01, 0, GPR64z, simm7s16, "stgp">;
def STGPpost : StorePairPostIdx<0b01, 0, GPR64z, simm7s16, "stgp">;

} // Predicates = [HasMTE]

//===----------------------------------------------------------------------===//
// Logical instructions.
//===----------------------------------------------------------------------===//
Expand Down
14 changes: 7 additions & 7 deletions llvm/lib/Target/AArch64/AArch64Subtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -323,13 +323,13 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo {
bool hasAggressiveFMA() const { return HasAggressiveFMA; }
bool hasAlternativeNZCV() const { return HasAlternativeNZCV; }
bool hasFRInt3264() const { return HasFRInt3264; }
bool hasSpecRestrict() { return HasSpecRestrict; }
bool hasSpecCtrl() { return HasSpecCtrl; }
bool hasPredCtrl() { return HasPredCtrl; }
bool hasCCDP() { return HasCCDP; }
bool hasBTI() { return HasBTI; }
bool hasRandGen() { return HasRandGen; }
bool hasMTE() { return HasMTE; }
bool hasSpecRestrict() const { return HasSpecRestrict; }
bool hasSpecCtrl() const { return HasSpecCtrl; }
bool hasPredCtrl() const { return HasPredCtrl; }
bool hasCCDP() const { return HasCCDP; }
bool hasBTI() const { return HasBTI; }
bool hasRandGen() const { return HasRandGen; }
bool hasMTE() const { return HasMTE; }

bool isLittleEndian() const { return IsLittle; }

Expand Down
25 changes: 18 additions & 7 deletions llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3826,13 +3826,9 @@ bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,

// Read the remaining operands.
if (getLexer().isNot(AsmToken::EndOfStatement)) {
// Read the first operand.
if (parseOperand(Operands, false, false)) {
return true;
}

unsigned N = 2;
while (parseOptionalToken(AsmToken::Comma)) {
unsigned N = 1;
do {
// Parse and remember the operand.
if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
(N == 3 && condCodeThirdOperand) ||
Expand Down Expand Up @@ -3860,7 +3856,7 @@ bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
AArch64Operand::CreateToken("!", false, ELoc, getContext()));

++N;
}
} while (parseOptionalToken(AsmToken::Comma));
}

if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
Expand Down Expand Up @@ -4097,6 +4093,15 @@ bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc,
"unpredictable STXP instruction, status is also a source");
break;
}
case AArch64::LDGV: {
unsigned Rt = Inst.getOperand(0).getReg();
unsigned Rn = Inst.getOperand(1).getReg();
if (RI->isSubRegisterEq(Rt, Rn)) {
return Error(Loc[0],
"unpredictable LDGV instruction, writeback register is also "
"the target register");
}
}
}


Expand Down Expand Up @@ -4231,6 +4236,8 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
return Error(Loc, "index must be an integer in range [-128, 127].");
case Match_InvalidMemoryIndexedSImm9:
return Error(Loc, "index must be an integer in range [-256, 255].");
case Match_InvalidMemoryIndexed16SImm9:
return Error(Loc, "index must be a multiple of 16 in range [-4096, 4080].");
case Match_InvalidMemoryIndexed8SImm10:
return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
case Match_InvalidMemoryIndexed4SImm7:
Expand All @@ -4247,6 +4254,8 @@ bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
case Match_InvalidMemoryIndexed8UImm6:
return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
case Match_InvalidMemoryIndexed16UImm6:
return Error(Loc, "index must be a multiple of 16 in range [0, 1008].");
case Match_InvalidMemoryIndexed4UImm6:
return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
case Match_InvalidMemoryIndexed2UImm6:
Expand Down Expand Up @@ -4883,10 +4892,12 @@ bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_InvalidMemoryIndexed2UImm6:
case Match_InvalidMemoryIndexed4UImm6:
case Match_InvalidMemoryIndexed8UImm6:
case Match_InvalidMemoryIndexed16UImm6:
case Match_InvalidMemoryIndexedSImm6:
case Match_InvalidMemoryIndexedSImm5:
case Match_InvalidMemoryIndexedSImm8:
case Match_InvalidMemoryIndexedSImm9:
case Match_InvalidMemoryIndexed16SImm9:
case Match_InvalidMemoryIndexed8SImm10:
case Match_InvalidImm0_1:
case Match_InvalidImm0_7:
Expand Down

0 comments on commit c419028

Please sign in to comment.