Skip to content
This repository has been archived by the owner on Apr 23, 2020. It is now read-only.

Commit

Permalink
[AArch64][v8.5A] Add prediction invalidation instructions to AArch64
Browse files Browse the repository at this point in the history
This adds new system instructions which act as barriers to speculative
execution based on earlier execution within a particular execution
context.

Patch by Pablo Barrio!

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



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@343214 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
ostannard committed Sep 27, 2018
1 parent 13a8300 commit 9322555
Show file tree
Hide file tree
Showing 11 changed files with 142 additions and 4 deletions.
6 changes: 5 additions & 1 deletion lib/Target/AArch64/AArch64.td
Expand Up @@ -214,6 +214,9 @@ def FeatureFRInt3264 : SubtargetFeature<"fptoint", "HasFRInt3264", "true",
def FeatureSpecCtrl : SubtargetFeature<"specctrl", "HasSpecCtrl", "true",
"Enable speculation control barrier" >;

def FeaturePredCtrl : SubtargetFeature<"predctrl", "HasPredCtrl", "true",
"Enable execution and data prediction invalidation instructions" >;

//===----------------------------------------------------------------------===//
// Architectures.
//
Expand All @@ -232,7 +235,8 @@ def HasV8_4aOps : SubtargetFeature<"v8.4a", "HasV8_4aOps", "true",

def HasV8_5aOps : SubtargetFeature<
"v8.5a", "HasV8_5aOps", "true", "Support ARM v8.5a instructions",
[HasV8_4aOps, FeatureAltFPCmp, FeatureFRInt3264, FeatureSpecCtrl]
[HasV8_4aOps, FeatureAltFPCmp, FeatureFRInt3264, FeatureSpecCtrl,
FeaturePredCtrl]
>;

//===----------------------------------------------------------------------===//
Expand Down
2 changes: 2 additions & 0 deletions lib/Target/AArch64/AArch64InstrInfo.td
Expand Up @@ -68,6 +68,8 @@ def HasFRInt3264 : Predicate<"Subtarget->hasFRInt3264()">,
AssemblerPredicate<"FeatureFRInt3264", "frint3264">;
def HasSpecCtrl : Predicate<"Subtarget->hasSpecCtrl()">,
AssemblerPredicate<"FeatureSpecCtrl", "specctrl">;
def HasPredCtrl : Predicate<"Subtarget->hasPredCtrl()">,
AssemblerPredicate<"FeaturePredCtrl", "predctrl">;
def IsLE : Predicate<"Subtarget->isLittleEndian()">;
def IsBE : Predicate<"!Subtarget->isLittleEndian()">;
def UseAlternateSExtLoadCVTF32
Expand Down
2 changes: 2 additions & 0 deletions lib/Target/AArch64/AArch64Subtarget.h
Expand Up @@ -98,6 +98,7 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo {
bool HasAlternativeNZCV = false;
bool HasFRInt3264 = false;
bool HasSpecCtrl = false;
bool HasPredCtrl = false;

// HasZeroCycleRegMove - Has zero-cycle register mov instructions.
bool HasZeroCycleRegMove = false;
Expand Down Expand Up @@ -314,6 +315,7 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo {
bool hasAlternativeNZCV() const { return HasAlternativeNZCV; }
bool hasFRInt3264() const { return HasFRInt3264; }
bool hasSpecCtrl() { return HasSpecCtrl; }
bool hasPredCtrl() { return HasPredCtrl; }

bool isLittleEndian() const { return IsLittle; }

Expand Down
17 changes: 17 additions & 0 deletions lib/Target/AArch64/AArch64SystemOperands.td
Expand Up @@ -420,6 +420,23 @@ def : TLBI<"RVAE3OS", 0b110, 0b1000, 0b0101, 0b001>;
def : TLBI<"RVALE3OS", 0b110, 0b1000, 0b0101, 0b101>;
}

// Armv8.5-A Prediction Restriction by Context instruction options:
class PRCTX<string name, bits<4> crm> : SearchableTable {
let SearchableFields = ["Name", "Encoding"];
let EnumValueField = "Encoding";

string Name = name;
bits<11> Encoding;
let Encoding{10-4} = 0b0110111;
let Encoding{3-0} = crm;
bit NeedsReg = 1;
code Requires = [{ {} }];
}

let Requires = [{ {AArch64::FeaturePredCtrl} }] in {
def : PRCTX<"RCTX", 0b0011>;
}

//===----------------------------------------------------------------------===//
// MRS/MSR (system register read/write) instruction options.
//===----------------------------------------------------------------------===//
Expand Down
24 changes: 22 additions & 2 deletions lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
Expand Up @@ -2756,6 +2756,7 @@ static const struct Extension {
{ "simd", {AArch64::FeatureNEON} },
{ "ras", {AArch64::FeatureRAS} },
{ "lse", {AArch64::FeatureLSE} },
{ "predctrl", {AArch64::FeaturePredCtrl} },

// FIXME: Unsupported extensions
{ "pan", {} },
Expand Down Expand Up @@ -2864,6 +2865,23 @@ bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
return TokError(Str.c_str());
}
createSysAlias(TLBI->Encoding, Operands, S);
} else if (Mnemonic == "cfp" || Mnemonic == "dvp" || Mnemonic == "cpp") {
const AArch64PRCTX::PRCTX *PRCTX = AArch64PRCTX::lookupPRCTXByName(Op);
if (!PRCTX)
return TokError("invalid operand for prediction restriction instruction");
else if (!PRCTX->haveFeatures(getSTI().getFeatureBits())) {
std::string Str(
Mnemonic.upper() + std::string(PRCTX->Name) + " requires ");
setRequiredFeatureString(PRCTX->getRequiredFeatures(), Str);
return TokError(Str.c_str());
}
uint16_t PRCTX_Op2 =
Mnemonic == "cfp" ? 4 :
Mnemonic == "dvp" ? 5 :
Mnemonic == "cpp" ? 7 :
0;
assert(PRCTX_Op2 && "Invalid mnemonic for prediction restriction instruction");
createSysAlias(PRCTX->Encoding << 3 | PRCTX_Op2 , Operands, S);
}

Parser.Lex(); // Eat operand.
Expand Down Expand Up @@ -3682,8 +3700,10 @@ bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
size_t Start = 0, Next = Name.find('.');
StringRef Head = Name.slice(Start, Next);

// IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
// IC, DC, AT, TLBI and Prediction invalidation instructions are aliases for
// the SYS instruction.
if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi" ||
Head == "cfp" || Head == "dvp" || Head == "cpp")
return parseSysAlias(Head, NameLoc, Operands);

Operands.push_back(
Expand Down
27 changes: 26 additions & 1 deletion lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp
Expand Up @@ -775,8 +775,33 @@ bool AArch64InstPrinter::printSysAlias(const MCInst *MI,
if (CnVal == 7) {
switch (CmVal) {
default: return false;
// Maybe IC, maybe Prediction Restriction
case 1:
switch (Op1Val) {
default: return false;
case 0: goto Search_IC;
case 3: goto Search_PRCTX;
}
// Prediction Restriction aliases
case 3: {
Search_PRCTX:
const AArch64PRCTX::PRCTX *PRCTX = AArch64PRCTX::lookupPRCTXByEncoding(Encoding >> 3);
if (!PRCTX || !PRCTX->haveFeatures(STI.getFeatureBits()))
return false;

NeedsReg = PRCTX->NeedsReg;
switch (Op2Val) {
default: return false;
case 4: Ins = "cfp\t"; break;
case 5: Ins = "dvp\t"; break;
case 7: Ins = "cpp\t"; break;
}
Name = std::string(PRCTX->Name);
}
break;
// IC aliases
case 1: case 5: {
case 5: {
Search_IC:
const AArch64IC::IC *IC = AArch64IC::lookupICByEncoding(Encoding);
if (!IC || !IC->haveFeatures(STI.getFeatureBits()))
return false;
Expand Down
7 changes: 7 additions & 0 deletions lib/Target/AArch64/Utils/AArch64BaseInfo.cpp
Expand Up @@ -61,6 +61,13 @@ namespace llvm {
}
}

namespace llvm {
namespace AArch64PRCTX {
#define GET_PRCTX_IMPL
#include "AArch64GenSystemOperands.inc"
}
}

namespace llvm {
namespace AArch64PRFM {
#define GET_PRFM_IMPL
Expand Down
8 changes: 8 additions & 0 deletions lib/Target/AArch64/Utils/AArch64BaseInfo.h
Expand Up @@ -499,6 +499,14 @@ namespace AArch64TLBI {
#include "AArch64GenSystemOperands.inc"
}

namespace AArch64PRCTX {
struct PRCTX : SysAliasReg {
using SysAliasReg::SysAliasReg;
};
#define GET_PRCTX_DECL
#include "AArch64GenSystemOperands.inc"
}

namespace AArch64II {
/// Target Operand Flag enum.
enum TOF {
Expand Down
20 changes: 20 additions & 0 deletions test/MC/AArch64/armv8.5a-predctrl-error.s
@@ -0,0 +1,20 @@
// RUN: not llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+predctrl < %s 2>&1| FileCheck %s

cfp rctx
dvp rctx
cpp rctx

// CHECK: specified cfp op requires a register
// CHECK: specified dvp op requires a register
// CHECK: specified cpp op requires a register

cfp x0, x1
dvp x1, x2
cpp x2, x3

// CHECK: invalid operand for prediction restriction instruction
// CHECK-NEXT: cfp
// CHECK: invalid operand for prediction restriction instruction
// CHECK-NEXT: dvp
// CHECK: invalid operand for prediction restriction instruction
// CHECK-NEXT: cpp
18 changes: 18 additions & 0 deletions test/MC/AArch64/armv8.5a-predctrl.s
@@ -0,0 +1,18 @@
// RUN: llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+predctrl < %s | FileCheck %s
// RUN: llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+v8.5a < %s | FileCheck %s
// RUN: not llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=-predctrl < %s 2>&1 | FileCheck %s --check-prefix=NOPREDCTRL

cfp rctx, x0
dvp rctx, x1
cpp rctx, x2

// CHECK: cfp rctx, x0 // encoding: [0x80,0x73,0x0b,0xd5]
// CHECK: dvp rctx, x1 // encoding: [0xa1,0x73,0x0b,0xd5]
// CHECK: cpp rctx, x2 // encoding: [0xe2,0x73,0x0b,0xd5]

// NOPREDCTRL: CFPRCTX requires predctrl
// NOPREDCTRL-NEXT: cfp
// NOPREDCTRL: DVPRCTX requires predctrl
// NOPREDCTRL-NEXT: dvp
// NOPREDCTRL: CPPRCTX requires predctrl
// NOPREDCTRL-NEXT: cpp
15 changes: 15 additions & 0 deletions test/MC/Disassembler/AArch64/armv8.5a-predctrl.txt
@@ -0,0 +1,15 @@
# RUN: llvm-mc -triple=aarch64 -mattr=+predctrl -disassemble < %s | FileCheck %s
# RUN: llvm-mc -triple=aarch64 -mattr=+v8.5a -disassemble < %s | FileCheck %s
# RUN: llvm-mc -triple=aarch64 -mattr=-predctrl -disassemble < %s 2>&1 | FileCheck %s --check-prefix=NOSB

[0x80 0x73 0x0b 0xd5]
[0xa1 0x73 0x0b 0xd5]
[0xe2 0x73 0x0b 0xd5]

# CHECK: cfp rctx, x0
# CHECK: dvp rctx, x1
# CHECK: cpp rctx, x2

# NOSB: sys #3, c7, c3, #4, x0
# NOSB: sys #3, c7, c3, #5, x1
# NOSB: sys #3, c7, c3, #7, x2

0 comments on commit 9322555

Please sign in to comment.