Allow the code which returns the length for inline assembler to know
authorReed Kotler <rkotler@mips.com>
Wed, 13 Nov 2013 04:37:52 +0000 (04:37 +0000)
committerReed Kotler <rkotler@mips.com>
Wed, 13 Nov 2013 04:37:52 +0000 (04:37 +0000)
specifically about the .space directive. This allows us to force large
blocks of code to appear in test cases for things like constant islands
without having to make giant test cases to force things like long
branches to take effect.

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

lib/Target/Mips/Mips16InstrInfo.cpp
lib/Target/Mips/Mips16InstrInfo.h
lib/Target/Mips/MipsConstantIslandPass.cpp
test/CodeGen/Mips/const6a.ll [new file with mode: 0644]

index dbad0a499fa66b0ac80b97f6973cdc2836cb1f38..8edc0029bd20b296cfd52cbf810bb73993b38c4b 100644 (file)
@@ -10,7 +10,8 @@
 // This file contains the Mips16 implementation of the TargetInstrInfo class.
 //
 //===----------------------------------------------------------------------===//
-
+#include <ctype.h>
+#include <stdlib.h>
 #include "Mips16InstrInfo.h"
 #include "InstPrinter/MipsInstPrinter.h"
 #include "MipsMachineFunction.h"
@@ -20,6 +21,7 @@
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/CodeGen/RegisterScavenging.h"
+#include "llvm/MC/MCAsmInfo.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -495,3 +497,47 @@ bool Mips16InstrInfo::validImmediate(unsigned Opcode, unsigned Reg,
   }
   llvm_unreachable("unexpected Opcode in validImmediate");
 }
+
+/// Measure the specified inline asm to determine an approximation of its
+/// length.
+/// Comments (which run till the next SeparatorString or newline) do not
+/// count as an instruction.
+/// Any other non-whitespace text is considered an instruction, with
+/// multiple instructions separated by SeparatorString or newlines.
+/// Variable-length instructions are not handled here; this function
+/// may be overloaded in the target code to do that.
+/// We implement the special case of the .space directive taking only an
+/// integer argument, which is the size in bytes. This is used for creating
+/// inline code spacing for testing purposes using inline assembly.
+///
+unsigned Mips16InstrInfo::getInlineAsmLength(const char *Str,
+                                             const MCAsmInfo &MAI) const {
+
+
+  // Count the number of instructions in the asm.
+  bool atInsnStart = true;
+  unsigned Length = 0;
+  for (; *Str; ++Str) {
+    if (*Str == '\n' || strncmp(Str, MAI.getSeparatorString(),
+                                strlen(MAI.getSeparatorString())) == 0)
+      atInsnStart = true;
+    if (atInsnStart && !std::isspace(static_cast<unsigned char>(*Str))) {
+      if (strncmp(Str, ".space", 6)==0) {
+        char *EStr; int Sz;
+        Sz = strtol(Str+6, &EStr, 10);
+        while (isspace(*EStr)) ++EStr;
+        if (*EStr=='\0') {
+          DEBUG(dbgs() << "parsed .space " << Sz << '\n');
+          return Sz;
+        }
+      }
+      Length += MAI.getMaxInstLength();
+      atInsnStart = false;
+    }
+    if (atInsnStart && strncmp(Str, MAI.getCommentString(),
+                               strlen(MAI.getCommentString())) == 0)
+      atInsnStart = false;
+  }
+
+  return Length;
+}
index 118d258a2bb71dd0ef62afc71382163f81400cee..d9a594b537a277ee517ee4bbbc416a16aa1f369f 100644 (file)
@@ -108,6 +108,8 @@ public:
   void BuildAddiuSpImm
     (MachineBasicBlock &MBB, MachineBasicBlock::iterator I, int64_t Imm) const;
 
+  unsigned getInlineAsmLength(const char *Str,
+                              const MCAsmInfo &MAI) const;
 private:
   virtual unsigned getAnalyzableBrOpc(unsigned Opc) const;
 
index 16573644b93d598d8e4a4a291fb92619d42d365a..c40b7fe39b82b401a0e9c20136fb6da1d8080a6c 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "Mips.h"
 #include "MCTargetDesc/MipsBaseInfo.h"
+#include "Mips16InstrInfo.h"
 #include "MipsMachineFunction.h"
 #include "MipsTargetMachine.h"
 #include "llvm/ADT/Statistic.h"
@@ -237,7 +238,7 @@ namespace {
   bool IsPIC;
   unsigned ABI;
   const MipsSubtarget *STI;
-  const MipsInstrInfo *TII;
+  const Mips16InstrInfo *TII;
   MipsFunctionInfo *MFI;
   MachineFunction *MF;
   MachineConstantPool *MCP;
@@ -359,7 +360,7 @@ bool MipsConstantIslands::runOnMachineFunction(MachineFunction &mf) {
       !MipsSubtarget::useConstantIslands()) {
     return false;
   }
-  TII = (const MipsInstrInfo*)MF->getTarget().getInstrInfo();
+  TII = (const Mips16InstrInfo*)MF->getTarget().getInstrInfo();
   MFI = MF->getInfo<MipsFunctionInfo>();
   DEBUG(dbgs() << "constant island processing " << "\n");
   //
diff --git a/test/CodeGen/Mips/const6a.ll b/test/CodeGen/Mips/const6a.ll
new file mode 100644 (file)
index 0000000..8b402ac
--- /dev/null
@@ -0,0 +1,29 @@
+; RUN: llc -mtriple=mipsel-linux-gnu -march=mipsel -mcpu=mips16 -soft-float -mips16-hard-float -relocation-model=pic -mips16-constant-islands   < %s | FileCheck %s -check-prefix=load-relax1
+
+; RUN: llc -mtriple=mipsel-linux-gnu -march=mipsel -mcpu=mips16 -soft-float -mips16-hard-float -relocation-model=pic -mips16-constant-islands   < %s | FileCheck %s -check-prefix=load-relax
+
+; ModuleID = 'const6a.c'
+target datalayout = "E-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32-S64"
+target triple = "mips--linux-gnu"
+
+@i = common global i32 0, align 4
+
+; Function Attrs: nounwind
+define void @t() #0 {
+entry:
+  store i32 -559023410, i32* @i, align 4
+; load-relax-NOT:      lw      ${{[0-9]+}}, $CPI0_0 # 16 bit inst
+; load-relax1: lw      ${{[0-9]+}}, $CPI0_0
+; load-relax:  jrc      $ra
+; load-relax:  .align  2
+; load-relax: $CPI0_0:
+; load-relax:  .4byte  3735943886
+; load-relax:  .end    t
+  call void asm sideeffect ".space 40000", ""() #1, !srcloc !1
+  ret void
+}
+
+attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="true" }
+attributes #1 = { nounwind }
+
+!1 = metadata !{i32 121}