AArch64: remove ConstantIsland pass & put literals in separate section.
[oota-llvm.git] / lib / Target / AArch64 / AArch64InstrInfo.td
index 03cae93a115ab10eb75cbd401f97a13233534338..562a7f60bbd9b09e2037214b41528d871b762b40 100644 (file)
@@ -1,3 +1,16 @@
+//===----- AArch64InstrInfo.td - AArch64 Instruction Info ----*- tablegen -*-=//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file describes the AArch64 scalar instructions in TableGen format.
+//
+//===----------------------------------------------------------------------===//
+
 include "AArch64InstrFormats.td"
 
 //===----------------------------------------------------------------------===//
@@ -205,11 +218,12 @@ def ATOMIC_CMP_SWAP_I64
 // is not optional in that case (but can explicitly be 0), and the
 // entire suffix can be skipped (e.g. "add sp, x3, x2").
 
-multiclass extend_operands<string PREFIX> {
+multiclass extend_operands<string PREFIX, string Diag> {
      def _asmoperand : AsmOperandClass {
          let Name = PREFIX;
          let RenderMethod = "addRegExtendOperands";
          let PredicateMethod = "isRegExtend<A64SE::" # PREFIX # ">";
+         let DiagnosticType = "AddSubRegExtend" # Diag;
      }
 
      def _operand : Operand<i64>,
@@ -220,18 +234,19 @@ multiclass extend_operands<string PREFIX> {
      }
 }
 
-defm UXTB : extend_operands<"UXTB">;
-defm UXTH : extend_operands<"UXTH">;
-defm UXTW : extend_operands<"UXTW">;
-defm UXTX : extend_operands<"UXTX">;
-defm SXTB : extend_operands<"SXTB">;
-defm SXTH : extend_operands<"SXTH">;
-defm SXTW : extend_operands<"SXTW">;
-defm SXTX : extend_operands<"SXTX">;
+defm UXTB : extend_operands<"UXTB", "Small">;
+defm UXTH : extend_operands<"UXTH", "Small">;
+defm UXTW : extend_operands<"UXTW", "Small">;
+defm UXTX : extend_operands<"UXTX", "Large">;
+defm SXTB : extend_operands<"SXTB", "Small">;
+defm SXTH : extend_operands<"SXTH", "Small">;
+defm SXTW : extend_operands<"SXTW", "Small">;
+defm SXTX : extend_operands<"SXTX", "Large">;
 
 def LSL_extasmoperand : AsmOperandClass {
     let Name = "RegExtendLSL";
     let RenderMethod = "addRegExtendOperands";
+    let DiagnosticType = "AddSubRegExtendLarge";
 }
 
 def LSL_extoperand : Operand<i64> {
@@ -540,10 +555,14 @@ let ParserMethod = "ParseImmWithLSLOperand",
   // Derived PredicateMethod fields are different for each
   def addsubimm_lsl0_asmoperand : AsmOperandClass {
     let Name = "AddSubImmLSL0";
+    // If an error is reported against this operand, instruction could also be a
+    // register variant.
+    let DiagnosticType = "AddSubSecondSource";
   }
 
   def addsubimm_lsl12_asmoperand : AsmOperandClass {
     let Name = "AddSubImmLSL12";
+    let DiagnosticType = "AddSubSecondSource";
   }
 }
 
@@ -689,8 +708,8 @@ multiclass shift_operands<string prefix, string form> {
   def _asmoperand_i32 : AsmOperandClass {
     let Name = "Shift" # form # "i32";
     let RenderMethod = "addShiftOperands";
-    let PredicateMethod
-          = "isShift<A64SE::" # form # ", false>";
+    let PredicateMethod = "isShift<A64SE::" # form # ", false>";
+    let DiagnosticType = "AddSubRegShift32";
   }
 
   // Note that the operand type is intentionally i64 because the DAGCombiner
@@ -705,8 +724,8 @@ multiclass shift_operands<string prefix, string form> {
   def _asmoperand_i64 : AsmOperandClass {
       let Name = "Shift" # form # "i64";
       let RenderMethod = "addShiftOperands";
-      let PredicateMethod
-            = "isShift<A64SE::" # form # ", true>";
+      let PredicateMethod = "isShift<A64SE::" # form # ", true>";
+      let DiagnosticType = "AddSubRegShift64";
   }
 
   def _i64 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm <= 63; }]> {
@@ -957,12 +976,14 @@ def uimm5_asmoperand : AsmOperandClass {
   let Name = "UImm5";
   let PredicateMethod = "isUImm<5>";
   let RenderMethod = "addImmOperands";
+  let DiagnosticType = "UImm5";
 }
 
 def uimm6_asmoperand : AsmOperandClass {
   let Name = "UImm6";
   let PredicateMethod = "isUImm<6>";
   let RenderMethod = "addImmOperands";
+  let DiagnosticType = "UImm6";
 }
 
 def bitfield32_imm : Operand<i64>,
@@ -1157,6 +1178,7 @@ def bfx32_width_asmoperand : AsmOperandClass {
   let Name = "BFX32Width";
   let PredicateMethod = "isBitfieldWidth<32>";
   let RenderMethod = "addBFXWidthOperands";
+  let DiagnosticType = "Width32";
 }
 
 def bfx32_width : Operand<i64>, ImmLeaf<i64, [{ return true; }]> {
@@ -1168,6 +1190,7 @@ def bfx64_width_asmoperand : AsmOperandClass {
   let Name = "BFX64Width";
   let PredicateMethod = "isBitfieldWidth<64>";
   let RenderMethod = "addBFXWidthOperands";
+  let DiagnosticType = "Width64";
 }
 
 def bfx64_width : Operand<i64> {
@@ -1235,6 +1258,7 @@ def bfi32_lsb_asmoperand : AsmOperandClass {
   let Name = "BFI32LSB";
   let PredicateMethod = "isUImm<5>";
   let RenderMethod = "addBFILSBOperands<32>";
+  let DiagnosticType = "UImm5";
 }
 
 def bfi32_lsb : Operand<i64>,
@@ -1247,6 +1271,7 @@ def bfi64_lsb_asmoperand : AsmOperandClass {
   let Name = "BFI64LSB";
   let PredicateMethod = "isUImm<6>";
   let RenderMethod = "addBFILSBOperands<64>";
+  let DiagnosticType = "UImm6";
 }
 
 def bfi64_lsb : Operand<i64>,
@@ -1262,6 +1287,7 @@ def bfi32_width_asmoperand : AsmOperandClass {
   let Name = "BFI32Width";
   let PredicateMethod = "isBitfieldWidth<32>";
   let RenderMethod = "addBFIWidthOperands";
+  let DiagnosticType = "Width32";
 }
 
 def bfi32_width : Operand<i64>,
@@ -1274,6 +1300,7 @@ def bfi64_width_asmoperand : AsmOperandClass {
   let Name = "BFI64Width";
   let PredicateMethod = "isBitfieldWidth<64>";
   let RenderMethod = "addBFIWidthOperands";
+  let DiagnosticType = "Width64";
 }
 
 def bfi64_width : Operand<i64>,
@@ -1329,6 +1356,7 @@ class label_asmoperand<int width, int scale> : AsmOperandClass {
   let Name = "Label" # width # "_" # scale;
   let PredicateMethod = "isLabel<" # width # "," # scale # ">";
   let RenderMethod = "addLabelOperands<" # width # ", " # scale # ">";
+  let DiagnosticType = "Label";
 }
 
 def label_wid19_scal4_asmoperand : label_asmoperand<19, 4>;
@@ -1375,6 +1403,7 @@ defm CBNZ : cmpbr_sizes<0b1, "cbnz", ImmLeaf<i32, [{
 
 def cond_code_asmoperand : AsmOperandClass {
   let Name = "CondCode";
+  let DiagnosticType = "CondCode";
 }
 
 def cond_code : Operand<i32>, ImmLeaf<i32, [{
@@ -1402,6 +1431,7 @@ def uimm4_asmoperand : AsmOperandClass {
   let Name = "UImm4";
   let PredicateMethod = "isUImm<4>";
   let RenderMethod = "addImmOperands";
+  let DiagnosticType = "UImm4";
 }
 
 def uimm4 : Operand<i32> {
@@ -1420,6 +1450,7 @@ def cond_code_op_asmoperand : AsmOperandClass {
   let RenderMethod = "addCondCodeOperands";
   let PredicateMethod = "isCondCode";
   let ParserMethod = "ParseCondCodeOperand";
+  let DiagnosticType = "CondCode";
 }
 
 def cond_code_op : Operand<i32> {
@@ -1471,6 +1502,7 @@ def inv_cond_code_op_asmoperand : AsmOperandClass {
   let RenderMethod = "addInvCondCodeOperands";
   let PredicateMethod = "isCondCode";
   let ParserMethod = "ParseCondCodeOperand";
+  let DiagnosticType = "CondCode";
 }
 
 def inv_cond_code_op : Operand<i32> {
@@ -1619,7 +1651,7 @@ class A64I_dp_1src_impl<bit sf, bits<6> opcode, string asmop,
                    itin>;
 
 multiclass A64I_dp_1src <bits<6> opcode, string asmop> {
-  let neverHasSideEffects = 1 in {
+  let hasSideEffects = 0 in {
     def ww : A64I_dp_1src_impl<0b0, opcode, asmop, [], GPR32, NoItinerary>;
     def xx : A64I_dp_1src_impl<0b1, opcode, asmop, [], GPR64, NoItinerary>;
   }
@@ -1658,7 +1690,9 @@ def REV16xx : A64I_dp_1src_impl<0b1, 0b000001, "rev16", [], GPR64, NoItinerary>;
 //===----------------------------------------------------------------------===//
 // Data Processing (2 sources) instructions
 //===----------------------------------------------------------------------===//
-// Contains: UDIV, SDIV, LSLV, LSRV, ASRV, RORV + aliases LSL, LSR, ASR, ROR
+// Contains: CRC32C?[BHWX], UDIV, SDIV, LSLV, LSRV, ASRV, RORV + aliases LSL,
+//           LSR, ASR, ROR
+
 
 class dp_2src_impl<bit sf, bits<6> opcode, string asmop, list<dag> patterns,
                    RegisterClass GPRsp,
@@ -1672,6 +1706,19 @@ class dp_2src_impl<bit sf, bits<6> opcode, string asmop, list<dag> patterns,
                    patterns,
                    itin>;
 
+multiclass dp_2src_crc<bit c, string asmop> {
+  def B_www : dp_2src_impl<0b0, {0, 1, 0, c, 0, 0},
+                           !strconcat(asmop, "b"), [], GPR32, NoItinerary>;
+  def H_www : dp_2src_impl<0b0, {0, 1, 0, c, 0, 1},
+                           !strconcat(asmop, "h"), [], GPR32, NoItinerary>;
+  def W_www : dp_2src_impl<0b0, {0, 1, 0, c, 1, 0},
+                           !strconcat(asmop, "w"), [], GPR32, NoItinerary>;
+  def X_wwx : A64I_dp_2src<0b1, {0, 1, 0, c, 1, 1}, 0b0,
+                           !strconcat(asmop, "x\t$Rd, $Rn, $Rm"),
+                           (outs GPR32:$Rd), (ins GPR32:$Rn, GPR64:$Rm), [],
+                           NoItinerary>;
+}
+
 multiclass dp_2src_zext <bits<6> opcode, string asmop, SDPatternOperator op> {
    def www : dp_2src_impl<0b0,
                          opcode,
@@ -1705,6 +1752,9 @@ multiclass dp_2src <bits<6> opcode, string asmop, SDPatternOperator op> {
 }
 
 // Here we define the data processing 2 source instructions.
+defm CRC32  : dp_2src_crc<0b0, "crc32">;
+defm CRC32C : dp_2src_crc<0b1, "crc32c">;
+
 defm UDIV : dp_2src<0b000010, "udiv", udiv>;
 defm SDIV : dp_2src<0b000011, "sdiv", sdiv>;
 
@@ -1818,6 +1868,7 @@ def uimm16_asmoperand : AsmOperandClass {
   let Name = "UImm16";
   let PredicateMethod = "isUImm<16>";
   let RenderMethod = "addImmOperands";
+  let DiagnosticType = "UImm16";
 }
 
 def uimm16 : Operand<i32> {
@@ -1884,6 +1935,7 @@ def : Pat<(rotr GPR64:$Rn, bitfield64_imm:$LSB),
 def fpzero_asmoperand : AsmOperandClass {
   let Name = "FPZero";
   let ParserMethod = "ParseFPImmOperand";
+  let DiagnosticType = "FPZero";
 }
 
 def fpz32 : Operand<f32>,
@@ -2121,6 +2173,7 @@ def fixedpos_asmoperand_i32 : AsmOperandClass {
   let Name = "CVTFixedPos32";
   let RenderMethod = "addCVTFixedPosOperands";
   let PredicateMethod = "isCVTFixedPos<32>";
+  let DiagnosticType = "CVTFixedPos32";
 }
 
 // Also encoded as "64 - <specified imm>" but #1-#64 allowed.
@@ -2128,6 +2181,7 @@ def fixedpos_asmoperand_i64 : AsmOperandClass {
   let Name = "CVTFixedPos64";
   let RenderMethod = "addCVTFixedPosOperands";
   let PredicateMethod = "isCVTFixedPos<64>";
+  let DiagnosticType = "CVTFixedPos64";
 }
 
 // We need the cartesian product of f32/f64 i32/i64 operands for
@@ -2283,6 +2337,7 @@ def : Pat<(f64 (bitconvert (i64 GPR64:$Rn))), (FMOVdx GPR64:$Rn)>;
 def lane1_asmoperand : AsmOperandClass {
   let Name = "Lane1";
   let RenderMethod = "addImmOperands";
+  let DiagnosticType = "Lane1";
 }
 
 def lane1 : Operand<i32> {
@@ -2314,6 +2369,7 @@ def : InstAlias<"fmov $Rd.2d[$Lane], $Rn",
 def fpimm_asmoperand : AsmOperandClass {
   let Name = "FMOVImm";
   let ParserMethod = "ParseFPImmOperand";
+  let DiagnosticType = "FPImm";
 }
 
 // The MCOperand for these instructions are the encoded 8-bit values.
@@ -2354,6 +2410,7 @@ def FMOVdi : A64I_fpimm_impl<0b01, FPR64, f64, fmov64_operand>;
 def ldrlit_label_asmoperand : AsmOperandClass {
   let Name = "LoadLitLabel";
   let RenderMethod = "addLabelOperands<19, 4>";
+  let DiagnosticType = "Label";
 }
 
 def ldrlit_label : Operand<i64> {
@@ -2374,6 +2431,7 @@ multiclass namedimm<string prefix, string mapper> {
     let PredicateMethod = "isUImm";
     let RenderMethod = "addImmOperands";
     let ParserMethod = "ParseNamedImmOperand<" # mapper # ">";
+    let DiagnosticType = "NamedImm_" # prefix;
   }
 
   def _op : Operand<i32> {
@@ -2395,10 +2453,8 @@ let mayLoad = 1 in {
   def LDRx_lit : A64I_LDRlitSimple<0b01, 0b0, GPR64>;
 }
 
-def LDRs_lit  : A64I_LDRlitSimple<0b00, 0b1, FPR32,
-                              [(set (f32 FPR32:$Rt), (load constpool:$Imm19))]>;
-def LDRd_lit  : A64I_LDRlitSimple<0b01, 0b1, FPR64,
-                              [(set (f64 FPR64:$Rt), (load constpool:$Imm19))]>;
+def LDRs_lit  : A64I_LDRlitSimple<0b00, 0b1, FPR32>;
+def LDRd_lit  : A64I_LDRlitSimple<0b01, 0b1, FPR64>;
 
 let mayLoad = 1 in {
   def LDRq_lit : A64I_LDRlitSimple<0b10, 0b1, FPR128>;
@@ -2441,6 +2497,7 @@ def GPR64xsp0_asmoperand : AsmOperandClass {
   let PredicateMethod = "isWrappedReg";
   let RenderMethod = "addRegOperands";
   let ParserMethod = "ParseLSXAddressOperand";
+  // Diagnostics are provided by ParserMethod
 }
 
 def GPR64xsp0 : RegisterOperand<GPR64xsp> {
@@ -2718,6 +2775,7 @@ multiclass offsets_uimm12<int MemSize, string prefix> {
     let Name = "OffsetUImm12_" # MemSize;
     let PredicateMethod = "isOffsetUImm12<" # MemSize # ">";
     let RenderMethod = "addOffsetUImm12Operands<" # MemSize # ">";
+    let DiagnosticType = "LoadStoreUImm12_" # MemSize;
   }
 
   // Pattern is really no more than an ImmLeaf, but predicated on MemSize which
@@ -2752,6 +2810,7 @@ def simm9_asmoperand : AsmOperandClass {
   let Name = "SImm9";
   let PredicateMethod = "isSImm<9>";
   let RenderMethod = "addSImmOperands<9>";
+  let DiagnosticType = "LoadStoreSImm9";
 }
 
 def simm9 : Operand<i64>,
@@ -2784,6 +2843,7 @@ multiclass regexts<int MemSize, int RmSize, RegisterClass GPR,
     let Name = "AddrRegExtend_" # MemSize # "_" #  Rm;
     let PredicateMethod = "isAddrRegExtend<" # MemSize # "," # RmSize # ">";
     let RenderMethod = "addAddrRegExtendOperands<" # MemSize # ">";
+    let DiagnosticType = "LoadStoreExtend" # RmSize # "_" # MemSize;
   }
 
   def regext : Operand<i64> {
@@ -3357,6 +3417,7 @@ multiclass offsets_simm7<string MemSize, string prefix> {
     let Name = "SImm7_Scaled" # MemSize;
     let PredicateMethod = "isSImm7Scaled<" # MemSize # ">";
     let RenderMethod = "addSImm7ScaledOperands<" # MemSize # ">";
+    let DiagnosticType = "LoadStoreSImm7_" # MemSize;
   }
 
   def simm7 : Operand<i64> {
@@ -3508,6 +3569,7 @@ multiclass logical_imm_operands<string prefix, string note,
     let Name = "LogicalImm" # note # size;
     let PredicateMethod = "isLogicalImm" # note # "<" # size # ">";
     let RenderMethod = "addLogicalImmOperands<" # size # ">";
+    let DiagnosticType = "LogicalSecondSource";
   }
 
   def _operand
@@ -3799,8 +3861,8 @@ multiclass movw_operands<string prefix, string instname, int width> {
     let Name = instname # width # "Shifted" # shift;
     let PredicateMethod = "is" # instname # width # "Imm";
     let RenderMethod = "addMoveWideImmOperands";
-
     let ParserMethod = "ParseImmWithLSLOperand";
+    let DiagnosticType = "MOVWUImm16";
   }
 
   def _imm : Operand<i32> {
@@ -3841,7 +3903,7 @@ multiclass A64I_movwSizes<bits<2> opc, string asmop, dag ins32bit,
 }
 
 let isMoveImm = 1, isReMaterializable = 1,
-    isAsCheapAsAMove = 1, neverHasSideEffects = 1 in {
+    isAsCheapAsAMove = 1, hasSideEffects = 0 in {
   defm MOVN : A64I_movwSizes<0b00, "movn",
                              (ins movn32_imm:$FullImm),
                              (ins movn64_imm:$FullImm)>;
@@ -3915,6 +3977,7 @@ def adr_label : Operand<i64> {
 def adrp_label_asmoperand : AsmOperandClass {
   let Name = "AdrpLabel";
   let RenderMethod = "addLabelOperands<21, 4096>";
+  let DiagnosticType = "Label";
 }
 
 def adrp_label : Operand<i64> {
@@ -3926,7 +3989,7 @@ def adrp_label : Operand<i64> {
   let OperandType = "OPERAND_PCREL";
 }
 
-let neverHasSideEffects = 1 in {
+let hasSideEffects = 0 in {
   def ADRxi : A64I_PCADR<0b0, (outs GPR64:$Rd), (ins adr_label:$Label),
                          "adr\t$Rd, $Label", [], NoItinerary>;
 
@@ -3945,6 +4008,7 @@ def uimm3_asmoperand : AsmOperandClass {
   let Name = "UImm3";
   let PredicateMethod = "isUImm<3>";
   let RenderMethod = "addImmOperands";
+  let DiagnosticType = "UImm3";
 }
 
 def uimm3 : Operand<i32> {
@@ -3956,6 +4020,7 @@ def uimm7_asmoperand : AsmOperandClass {
   let Name = "UImm7";
   let PredicateMethod = "isUImm<7>";
   let RenderMethod = "addImmOperands";
+  let DiagnosticType = "UImm7";
 }
 
 def uimm7 : Operand<i32> {
@@ -3991,6 +4056,7 @@ defm tlbi : namedimm<"tlbi", "A64TLBI::TLBIMapper">;
 def mrs_asmoperand : AsmOperandClass {
   let Name = "MRS";
   let ParserMethod = "ParseSysRegOperand";
+  let DiagnosticType = "MRS";
 }
 
 def mrs_op : Operand<i32> {
@@ -4007,6 +4073,7 @@ def msr_asmoperand : AsmOperandClass {
   // AArch64Operand rather than an immediate. The overlap is small enough that
   // it could be resolved with hackery now, but who can say in future?
   let ParserMethod = "ParseSysRegOperand";
+  let DiagnosticType = "MSR";
 }
 
 def msr_op : Operand<i32> {
@@ -4019,6 +4086,7 @@ def pstate_asmoperand : AsmOperandClass {
   let Name = "MSRPState";
   // See comment above about parser.
   let ParserMethod = "ParseSysRegOperand";
+  let DiagnosticType = "MSR";
 }
 
 def pstate_op : Operand<i32> {
@@ -4034,6 +4102,7 @@ def CRx_asmoperand : AsmOperandClass {
   let PredicateMethod = "isUImm<4>";
   let RenderMethod = "addImmOperands";
   let ParserMethod = "ParseCRxOperand";
+  // Diagnostics are handled in all cases by ParseCRxOperand.
 }
 
 def CRx : Operand<i32> {
@@ -4491,22 +4560,6 @@ def : Pat<(and (A64Bfi GPR64:$src, GPR64:$Rn, imm:$ImmR, imm:$ImmS),
 
 }
 
-//===----------------------------------------------------------------------===//
-// Constant island entries
-//===----------------------------------------------------------------------===//
-
-// The constant island pass needs to create "instructions" in the middle of the
-// instruction stream to reresent its constants.
-
-def cpinst_operand : Operand<i32>;
-
-def CONSTPOOL_ENTRY : PseudoInst<(outs), (ins cpinst_operand:$instid,
-                                              cpinst_operand:$cpidx,
-                                              i32imm:$size), []> {
-  let neverHasSideEffects = 1;
-  let isNotDuplicable = 1;
-}
-
 //===----------------------------------------------------------------------===//
 // Miscellaneous patterns
 //===----------------------------------------------------------------------===//
@@ -4825,6 +4878,8 @@ defm : uimm12_pats<(A64WrapperSmall texternalsym:$Hi, texternalsym:$Lo12,
                                     ALIGN),
                    (ADRPxi texternalsym:$Hi), (i64 texternalsym:$Lo12)>;
 
+defm : uimm12_pats<(A64WrapperSmall tconstpool:$Hi, tconstpool:$Lo12, ALIGN),
+                   (ADRPxi tconstpool:$Hi), (i64 tconstpool:$Lo12)>;
 
 // We also want to use uimm12 instructions for local variables at the moment.
 def tframeindex_XFORM : SDNodeXForm<frameindex, [{