]> granicus.if.org Git - llvm/commitdiff
AMDGPU: Workaround for instruction size with literals
authorMatt Arsenault <Matthew.Arsenault@amd.com>
Tue, 1 Nov 2016 20:42:24 +0000 (20:42 +0000)
committerMatt Arsenault <Matthew.Arsenault@amd.com>
Tue, 1 Nov 2016 20:42:24 +0000 (20:42 +0000)
Instructions with a 32-bit base encoding with an optional
32-bit literal encoded after them report their size as 4
for the disassembler. Consider these when computing the
MachineInstr size. This fixes problems caused by size estimate
consistency in BranchRelaxation.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@285743 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/AMDGPU/SIDefines.h
lib/Target/AMDGPU/SIInstrFormats.td
lib/Target/AMDGPU/SIInstrInfo.cpp
lib/Target/AMDGPU/SIInstrInfo.h
lib/Target/AMDGPU/SOPInstructions.td

index f48011fe5e1fdca6376490bb970cc2a88ad64ca3..5e6e754b5328366000430beae1750c15060d0a0f 100644 (file)
@@ -45,7 +45,8 @@ enum {
   Gather4 = 1 << 26,
   DisableWQM = 1 << 27,
   SOPK_ZEXT = 1 << 28,
-  SCALAR_STORE = 1 << 29
+  SCALAR_STORE = 1 << 29,
+  FIXED_SIZE = 1 << 30
 };
 }
 
index 8976333412b1893a4d06910ca0823c07adeeed3d..9dfe06fbb8e2667fab21b1b96fb9e3d0181cd49c 100644 (file)
@@ -65,6 +65,10 @@ class InstSI <dag outs, dag ins, string asm = "",
   // SMEM instructions like the cache flush ones.
   field bits<1> ScalarStore = 0;
 
+  // Whether the operands can be ignored when computing the
+  // instruction size.
+  field bits<1> FixedSize = 0;
+
   // These need to be kept in sync with the enum in SIInstrFlags.
   let TSFlags{0} = VM_CNT;
   let TSFlags{1} = EXP_CNT;
@@ -100,6 +104,7 @@ class InstSI <dag outs, dag ins, string asm = "",
   let TSFlags{27} = DisableWQM;
   let TSFlags{28} = SOPKZext;
   let TSFlags{29} = ScalarStore;
+  let TSFlags{30} = FixedSize;
 
   let SchedRW = [Write32Bit];
 
index cdd98c6ae71629ca9ff8d70126a7b8ebb3639fa1..905ee4673191981cd833ba28a3223d19b2fcac05 100644 (file)
@@ -3501,12 +3501,20 @@ unsigned SIInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
 
   // If we have a definitive size, we can use it. Otherwise we need to inspect
   // the operands to know the size.
-  if (DescSize != 0)
+  //
+  // FIXME: Instructions that have a base 32-bit encoding report their size as
+  // 4, even though they are really 8 bytes if they have a literal operand.
+  if (DescSize != 0 && DescSize != 4)
     return DescSize;
 
   // 4-byte instructions may have a 32-bit literal encoded after them. Check
   // operands that coud ever be literals.
   if (isVALU(MI) || isSALU(MI)) {
+    if (isFixedSize(MI)) {
+      assert(DescSize == 4);
+      return DescSize;
+    }
+
     int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
     if (Src0Idx == -1)
       return 4; // No operands.
@@ -3524,6 +3532,9 @@ unsigned SIInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
     return 4;
   }
 
+  if (DescSize == 4)
+    return 4;
+
   switch (Opc) {
   case AMDGPU::SI_MASK_BRANCH:
   case TargetOpcode::IMPLICIT_DEF:
index b83d2cd97f6aa3264f9aed5812a6cbbe3e8d69ae..515beb4bbfd2720325cb184800a81ee8f7c49902 100644 (file)
@@ -438,6 +438,14 @@ public:
     return get(Opcode).TSFlags & SIInstrFlags::SCALAR_STORE;
   }
 
+  static bool isFixedSize(const MachineInstr &MI) {
+    return MI.getDesc().TSFlags & SIInstrFlags::FIXED_SIZE;
+  }
+
+  bool isFixedSize(uint16_t Opcode) const {
+    return get(Opcode).TSFlags & SIInstrFlags::FIXED_SIZE;
+  }
+
   bool isVGPRCopy(const MachineInstr &MI) const {
     assert(MI.isCopy());
     unsigned Dest = MI.getOperand(0).getReg();
index 0d376b97b5f35052e90e9d2e7f47ab4d9abfbaa2..e38a11db9ac62f1ab7d2cc31fdad41c96c3b3266 100644 (file)
@@ -704,6 +704,7 @@ def S_SET_GPR_IDX_ON : SOPC <0x11,
   let Defs = [M0]; // No scc def
   let Uses = [M0]; // Other bits of m0 unmodified.
   let hasSideEffects = 1; // Sets mode.gpr_idx_en
+  let FixedSize = 1;
 }
 }