diff --git a/lib/Target/Mips/Mips16InstrInfo.cpp b/lib/Target/Mips/Mips16InstrInfo.cpp index dbad0a499fa..8edc0029bd2 100644 --- a/lib/Target/Mips/Mips16InstrInfo.cpp +++ b/lib/Target/Mips/Mips16InstrInfo.cpp @@ -10,7 +10,8 @@ // This file contains the Mips16 implementation of the TargetInstrInfo class. // //===----------------------------------------------------------------------===// - +#include +#include #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(*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; +} diff --git a/lib/Target/Mips/Mips16InstrInfo.h b/lib/Target/Mips/Mips16InstrInfo.h index 118d258a2bb..d9a594b537a 100644 --- a/lib/Target/Mips/Mips16InstrInfo.h +++ b/lib/Target/Mips/Mips16InstrInfo.h @@ -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; diff --git a/lib/Target/Mips/MipsConstantIslandPass.cpp b/lib/Target/Mips/MipsConstantIslandPass.cpp index 16573644b93..c40b7fe39b8 100644 --- a/lib/Target/Mips/MipsConstantIslandPass.cpp +++ b/lib/Target/Mips/MipsConstantIslandPass.cpp @@ -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(); DEBUG(dbgs() << "constant island processing " << "\n"); // diff --git a/test/CodeGen/Mips/const6a.ll b/test/CodeGen/Mips/const6a.ll new file mode 100644 index 00000000000..8b402accc7d --- /dev/null +++ b/test/CodeGen/Mips/const6a.ll @@ -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}