[AArch64][v8.5A] Add prediction invalidation instructions to AArch64
authorOliver Stannard <oliver.stannard@arm.com>
Thu, 27 Sep 2018 13:47:40 +0000 (13:47 +0000)
committerOliver Stannard <oliver.stannard@arm.com>
Thu, 27 Sep 2018 13:47:40 +0000 (13:47 +0000)
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

llvm-svn: 343214

llvm/lib/Target/AArch64/AArch64.td
llvm/lib/Target/AArch64/AArch64InstrInfo.td
llvm/lib/Target/AArch64/AArch64Subtarget.h
llvm/lib/Target/AArch64/AArch64SystemOperands.td
llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
llvm/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp
llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.cpp
llvm/lib/Target/AArch64/Utils/AArch64BaseInfo.h
llvm/test/MC/AArch64/armv8.5a-predctrl-error.s [new file with mode: 0644]
llvm/test/MC/AArch64/armv8.5a-predctrl.s [new file with mode: 0644]
llvm/test/MC/Disassembler/AArch64/armv8.5a-predctrl.txt [new file with mode: 0644]

index 79bae03b4b83a59de2431822bdcc47caf271740f..8d2085030c08349d74adaf2fd357c50220d39dd1 100644 (file)
@@ -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.
 //
@@ -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]
 >;
 
 //===----------------------------------------------------------------------===//
index 310c1b60bf7c6cbc3e4e939a0a13e90475640c74..1192fad94bd2ff38e310ebe9dabf2c765336c655 100644 (file)
@@ -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
index 8df6e5a65703339973989d3a9c52731c17af3cd4..cc901e1c64424e9d311aea18795ae0ee0238e600 100644 (file)
@@ -98,6 +98,7 @@ protected:
   bool HasAlternativeNZCV = false;
   bool HasFRInt3264 = false;
   bool HasSpecCtrl = false;
+  bool HasPredCtrl = false;
 
   // HasZeroCycleRegMove - Has zero-cycle register mov instructions.
   bool HasZeroCycleRegMove = false;
@@ -314,6 +315,7 @@ public:
   bool hasAlternativeNZCV() const { return HasAlternativeNZCV; }
   bool hasFRInt3264() const { return HasFRInt3264; }
   bool hasSpecCtrl() { return HasSpecCtrl; }
+  bool hasPredCtrl() { return HasPredCtrl; }
 
   bool isLittleEndian() const { return IsLittle; }
 
index dbc4deaf3f9f3bd0e64e7cd712954c402c08564a..1b3887ed5e013ecc85975339c995878278a96c90 100644 (file)
@@ -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.
 //===----------------------------------------------------------------------===//
index 0f156185387d1ad1ba673add74077927645bbf0a..acbea2b5dcf05ef7fe39c90d49a7ba42e83c12c4 100644 (file)
@@ -2756,6 +2756,7 @@ static const struct Extension {
   { "simd", {AArch64::FeatureNEON} },
   { "ras", {AArch64::FeatureRAS} },
   { "lse", {AArch64::FeatureLSE} },
+  { "predctrl", {AArch64::FeaturePredCtrl} },
 
   // FIXME: Unsupported extensions
   { "pan", {} },
@@ -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.
@@ -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(
index 26e41215afc64024327987db6b9b09e73f4aa0fd..aa537abf6abd2aa40954e6d56f4624d54d624415 100644 (file)
@@ -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;
index 23cc21ce2e7cf02ccfdec51fe54097ed35194fd3..9c415aa8496ade3ad0ffa853dccecd812262ca90 100644 (file)
@@ -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
index 461a7dcf0904072a3781e4cf8f290aef9a617252..675adad2a6917432e3f405f717e075d765173b31 100644 (file)
@@ -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 {
diff --git a/llvm/test/MC/AArch64/armv8.5a-predctrl-error.s b/llvm/test/MC/AArch64/armv8.5a-predctrl-error.s
new file mode 100644 (file)
index 0000000..0fd49b0
--- /dev/null
@@ -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
diff --git a/llvm/test/MC/AArch64/armv8.5a-predctrl.s b/llvm/test/MC/AArch64/armv8.5a-predctrl.s
new file mode 100644 (file)
index 0000000..af7dda7
--- /dev/null
@@ -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
diff --git a/llvm/test/MC/Disassembler/AArch64/armv8.5a-predctrl.txt b/llvm/test/MC/Disassembler/AArch64/armv8.5a-predctrl.txt
new file mode 100644 (file)
index 0000000..ecfdeec
--- /dev/null
@@ -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