Index: include/llvm/CodeGen/AsmPrinter.h =================================================================== --- include/llvm/CodeGen/AsmPrinter.h +++ include/llvm/CodeGen/AsmPrinter.h @@ -205,6 +205,7 @@ bool runOnMachineFunction(MachineFunction &MF) override { SetupMachineFunction(MF); EmitFunctionBody(); + FinalizeMachineFunction(); return false; } @@ -216,6 +217,9 @@ /// runOnMachineFunction. void SetupMachineFunction(MachineFunction &MF); + /// This should be called at the end of runOnMachineFunction. + void FinalizeMachineFunction(); + /// This method emits the body and trailer for a function. void EmitFunctionBody(); Index: include/llvm/MC/MCAsmBackend.h =================================================================== --- include/llvm/MC/MCAsmBackend.h +++ include/llvm/MC/MCAsmBackend.h @@ -124,7 +124,8 @@ /// target cannot generate such a sequence, it should return an error. /// /// \return - True on success. - virtual bool writeNopData(uint64_t Count, MCObjectWriter *OW) const = 0; + virtual bool writeNopData(uint64_t Count, MCObjectWriter *OW, + const MCSubtargetInfo *STI) const = 0; /// Give backend an opportunity to finish layout after relaxation virtual void finishLayout(MCAssembler const &Asm, Index: include/llvm/MC/MCFragment.h =================================================================== --- include/llvm/MC/MCFragment.h +++ include/llvm/MC/MCFragment.h @@ -16,6 +16,7 @@ #include "llvm/ADT/iterator.h" #include "llvm/MC/MCFixup.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSubtargetInfo.h" namespace llvm { class MCSection; @@ -78,6 +79,8 @@ /// @} + const MCSubtargetInfo *STI; + protected: MCFragment(FragmentType Kind, bool HasInstructions, uint8_t BundlePadding, MCSection *Parent = nullptr); @@ -126,6 +129,13 @@ /// and only some fragments have a meaningful implementation. void setBundlePadding(uint8_t N) { BundlePadding = N; } + /// \brief Get subtarget info for given fragment. + const MCSubtargetInfo *getSubtarget() const { return STI; }; + + /// \brief Set subtarget info for given fragment to be able to write it + /// depending on the target (e.g. the way to encode long nops). + void setSubtarget(const MCSubtargetInfo *S) { STI = S; } + /// \brief Return true if given frgment has FT_Dummy type. bool isDummy() const { return Kind == FT_Dummy; } Index: lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1282,6 +1282,20 @@ LI = &getAnalysis(); } +void AsmPrinter::FinalizeMachineFunction() { + // Store TargetSubtargetInfo in MCFragments to be able to generate long nops + // depending on the function target preferences. + assert(!OutStreamer->PopSection() && "The section stack must be empty"); + MCSection *Sec = const_cast(getCurrentSection()); + for (auto &F : *Sec) { + // If the fragment already contains a subtarget info than it belongs to + // another function which has been streamed into the same section, so don't + // change its subtarget. + if (!F.getSubtarget()) + F.setSubtarget(&MF->getSubtarget()); + } +} + namespace { // Keep track the alignment, constpool entries per Section. struct SectionCPs { Index: lib/MC/MCAssembler.cpp =================================================================== --- lib/MC/MCAssembler.cpp +++ lib/MC/MCAssembler.cpp @@ -406,12 +406,12 @@ // ---------------------------- // ^-------------------^ <- TotalLength unsigned DistanceToBoundary = TotalLength - getBundleAlignSize(); - if (!getBackend().writeNopData(DistanceToBoundary, OW)) + if (!getBackend().writeNopData(DistanceToBoundary, OW, F.getSubtarget())) report_fatal_error("unable to write NOP sequence of " + Twine(DistanceToBoundary) + " bytes"); BundlePadding -= DistanceToBoundary; } - if (!getBackend().writeNopData(BundlePadding, OW)) + if (!getBackend().writeNopData(BundlePadding, OW, F.getSubtarget())) report_fatal_error("unable to write NOP sequence of " + Twine(BundlePadding) + " bytes"); } @@ -456,7 +456,7 @@ // bytes left to fill use the Value and ValueSize to fill the rest. // If we are aligning with nops, ask that target to emit the right data. if (AF.hasEmitNops()) { - if (!Asm.getBackend().writeNopData(Count, OW)) + if (!Asm.getBackend().writeNopData(Count, OW, F.getSubtarget())) report_fatal_error("unable to write nop sequence of " + Twine(Count) + " bytes"); break; Index: lib/MC/MCFragment.cpp =================================================================== --- lib/MC/MCFragment.cpp +++ lib/MC/MCFragment.cpp @@ -235,9 +235,9 @@ V->destroy(); } -MCFragment::MCFragment() : Kind(FragmentType(~0)), HasInstructions(false), - AlignToBundleEnd(false), BundlePadding(0) { -} +MCFragment::MCFragment() + : Kind(FragmentType(~0)), HasInstructions(false), AlignToBundleEnd(false), + BundlePadding(0), STI(nullptr) {} MCFragment::~MCFragment() { } @@ -245,7 +245,7 @@ uint8_t BundlePadding, MCSection *Parent) : Kind(Kind), HasInstructions(HasInstructions), AlignToBundleEnd(false), BundlePadding(BundlePadding), Parent(Parent), Atom(nullptr), - Offset(~UINT64_C(0)) { + Offset(~UINT64_C(0)), STI(nullptr) { if (Parent && !isDummy()) Parent->getFragmentList().push_back(this); } Index: lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp =================================================================== --- lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp +++ lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp @@ -79,7 +79,8 @@ const MCRelaxableFragment *DF, const MCAsmLayout &Layout) const override; void relaxInstruction(const MCInst &Inst, MCInst &Res) const override; - bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override; + bool writeNopData(uint64_t Count, MCObjectWriter *OW, + const MCSubtargetInfo *STI) const override; void HandleAssemblerFlag(MCAssemblerFlag Flag) {} @@ -317,7 +318,8 @@ llvm_unreachable("AArch64AsmBackend::relaxInstruction() unimplemented"); } -bool AArch64AsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { +bool AArch64AsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW, + const MCSubtargetInfo *STI) const { // If the count is not 4-byte aligned, we must be writing data into the text // section (otherwise we have unaligned instructions, and thus have far // bigger problems), so just write zeros instead. Index: lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp =================================================================== --- lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp +++ lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp @@ -235,6 +235,8 @@ } } + FinalizeMachineFunction(); + return false; } Index: lib/Target/AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp =================================================================== --- lib/Target/AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp +++ lib/Target/AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp @@ -57,7 +57,8 @@ assert(!"Not implemented"); } bool mayNeedRelaxation(const MCInst &Inst) const override { return false; } - bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override; + bool writeNopData(uint64_t Count, MCObjectWriter *OW, + const MCSubtargetInfo *STI) const override; const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override; }; @@ -161,7 +162,8 @@ return Infos[Kind - FirstTargetFixupKind]; } -bool AMDGPUAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { +bool AMDGPUAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW, + const MCSubtargetInfo *STI) const { OW->WriteZeros(Count); return true; Index: lib/Target/ARM/ARMAsmPrinter.cpp =================================================================== --- lib/Target/ARM/ARMAsmPrinter.cpp +++ lib/Target/ARM/ARMAsmPrinter.cpp @@ -167,6 +167,8 @@ ThumbIndirectPads.clear(); } + FinalizeMachineFunction(); + // We didn't modify anything. return false; } Index: lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h =================================================================== --- lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h +++ lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h @@ -65,7 +65,8 @@ void relaxInstruction(const MCInst &Inst, MCInst &Res) const override; - bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override; + bool writeNopData(uint64_t Count, MCObjectWriter *OW, + const MCSubtargetInfo *STI) const override; void handleAssemblerFlag(MCAssemblerFlag Flag) override; Index: lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp =================================================================== --- lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -287,7 +287,8 @@ Res.setOpcode(RelaxedOp); } -bool ARMAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { +bool ARMAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW, + const MCSubtargetInfo *STI) const { const uint16_t Thumb1_16bitNopEncoding = 0x46c0; // using MOV r8,r8 const uint16_t Thumb2_16bitNopEncoding = 0xbf00; // NOP const uint32_t ARMv4_NopEncoding = 0xe1a00000; // using MOV r0,r0 Index: lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp =================================================================== --- lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp +++ lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp @@ -49,10 +49,12 @@ void relaxInstruction(const MCInst &Inst, MCInst &Res) const override {} - bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override; + bool writeNopData(uint64_t Count, MCObjectWriter *OW, + const MCSubtargetInfo *STI) const override; }; -bool BPFAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { +bool BPFAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW, + const MCSubtargetInfo *STI) const { if ((Count % 8) != 0) return false; Index: lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp =================================================================== --- lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp +++ lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp @@ -664,8 +664,8 @@ assert(Update && "Didn't find relaxation target"); } - bool writeNopData(uint64_t Count, - MCObjectWriter * OW) const override { + bool writeNopData(uint64_t Count, MCObjectWriter *OW, + const MCSubtargetInfo *STI) const override { static const uint32_t Nopcode = 0x7f000000, // Hard-coded NOP. ParseIn = 0x00004000, // In packet parse-bits. ParseEnd = 0x0000c000; // End of packet parse-bits. Index: lib/Target/Lanai/MCTargetDesc/LanaiAsmBackend.cpp =================================================================== --- lib/Target/Lanai/MCTargetDesc/LanaiAsmBackend.cpp +++ lib/Target/Lanai/MCTargetDesc/LanaiAsmBackend.cpp @@ -71,10 +71,12 @@ void relaxInstruction(const MCInst &Inst, MCInst &Res) const override {} - bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override; + bool writeNopData(uint64_t Count, MCObjectWriter *OW, + const MCSubtargetInfo *STI) const override; }; -bool LanaiAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { +bool LanaiAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW, + const MCSubtargetInfo *STI) const { if ((Count % 4) != 0) return false; Index: lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h +++ lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h @@ -79,7 +79,8 @@ /// @} - bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override; + bool writeNopData(uint64_t Count, MCObjectWriter *OW, + const MCSubtargetInfo *STI) const override; void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFixup &Fixup, const MCFragment *DF, Index: lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp +++ lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp @@ -449,7 +449,8 @@ /// it should return an error. /// /// \return - True on success. -bool MipsAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { +bool MipsAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW, + const MCSubtargetInfo *STI) const { // Check for a less than instruction size number of bytes // FIXME: 16 bit instructions are not handled yet here. // We shouldn't be using a hard coded number for instruction size. Index: lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp =================================================================== --- lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp +++ lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp @@ -174,7 +174,8 @@ llvm_unreachable("relaxInstruction() unimplemented"); } - bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override { + bool writeNopData(uint64_t Count, MCObjectWriter *OW, + const MCSubtargetInfo *STI) const override { uint64_t NumNops = Count / 4; for (uint64_t i = 0; i != NumNops; ++i) OW->write32(0x60000000); Index: lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +++ lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp @@ -253,7 +253,8 @@ llvm_unreachable("relaxInstruction() unimplemented"); } - bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override { + bool writeNopData(uint64_t Count, MCObjectWriter *OW, + const MCSubtargetInfo *STI) const override { // Cannot emit NOP with size not multiple of 32 bits. if (Count % 4 != 0) return false; Index: lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp =================================================================== --- lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp +++ lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp @@ -61,7 +61,8 @@ void relaxInstruction(const MCInst &Inst, MCInst &Res) const override { llvm_unreachable("SystemZ does do not have assembler relaxation"); } - bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override; + bool writeNopData(uint64_t Count, MCObjectWriter *OW, + const MCSubtargetInfo *STI) const override; MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override { return createSystemZObjectWriter(OS, OSABI); } @@ -102,8 +103,8 @@ } } -bool SystemZMCAsmBackend::writeNopData(uint64_t Count, - MCObjectWriter *OW) const { +bool SystemZMCAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW, + const MCSubtargetInfo *STI) const { for (uint64_t I = 0; I != Count; ++I) OW->write8(7); return true; Index: lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp =================================================================== --- lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp +++ lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp @@ -57,11 +57,12 @@ void relaxInstruction(const MCInst &Inst, MCInst &Res) const override {} - bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override; + bool writeNopData(uint64_t Count, MCObjectWriter *OW, + const MCSubtargetInfo *STI) const override; }; -bool WebAssemblyAsmBackend::writeNopData(uint64_t Count, - MCObjectWriter *OW) const { +bool WebAssemblyAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW, + const MCSubtargetInfo *STI) const { if (Count == 0) return true; Index: lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp =================================================================== --- lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -80,13 +80,11 @@ }; class X86AsmBackend : public MCAsmBackend { - const bool HasNopl; - const uint64_t MaxNopLength; + const MCSubtargetInfo &ModuleSTI; public: X86AsmBackend(const Target &T, const MCSubtargetInfo &STI) - : MCAsmBackend(), HasNopl(STI.getFeatureBits()[X86::FeatureLongNop]), - MaxNopLength(getMaxNopLength(STI, HasNopl)) {} + : MCAsmBackend(), ModuleSTI(STI) {} unsigned getNumFixupKinds() const override { return X86::NumTargetFixupKinds; @@ -137,7 +135,8 @@ void relaxInstruction(const MCInst &Inst, MCInst &Res) const override; - bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override; + bool writeNopData(uint64_t Count, MCObjectWriter *OW, + const MCSubtargetInfo *STI) const override; }; } // end anonymous namespace @@ -305,7 +304,16 @@ /// \brief Write a sequence of optimal nops to the output, covering \p Count /// bytes. /// \return - true on success, false on failure -bool X86AsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { +bool X86AsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW, + const MCSubtargetInfo *STI) const { + // Use module STI if local STI is not specified. + if (!STI) + STI = &ModuleSTI; + assert(STI && "STI object should always be available"); + + const bool HasNopl = STI->getFeatureBits()[X86::FeatureLongNop]; + const uint64_t MaxNopLength = getMaxNopLength(*STI, HasNopl); + static const uint8_t TrueNops[10][10] = { // nop {0x90}, @@ -348,7 +356,6 @@ }; // Select the right NOP table. - // FIXME: Can we get if CPU supports long nops from the subtarget somehow? const uint8_t (*Nops)[10] = HasNopl ? TrueNops : AltNops; assert(HasNopl || MaxNopLength <= 7); Index: lib/Target/X86/X86AsmPrinter.cpp =================================================================== --- lib/Target/X86/X86AsmPrinter.cpp +++ lib/Target/X86/X86AsmPrinter.cpp @@ -69,6 +69,8 @@ // Emit the rest of the function body. EmitFunctionBody(); + FinalizeMachineFunction(); + // We didn't modify anything. return false; } Index: test/CodeGen/X86/func-specific-nops.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/func-specific-nops.ll @@ -0,0 +1,66 @@ +; RUN: llc -march=x86 -mtriple=i386-pc-linux-gnu -mcpu=i386 -filetype=obj < %s | llvm-objdump -d - | FileCheck %s + +target datalayout = "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128" +target triple = "i386-unknown-linux-gnu" + +; Use module target information to generate long nops of the right length. +module asm "inc %eax" +module asm ".p2align 5" +module asm "inc %eax" +; CHECK-LABEL: .text +; CHECK: 0: 40 incl %eax +; CHECK: 1: 8d b4 26 00 00 00 00 leal (%esi), %esi +; CHECK: 8: 8d b4 26 00 00 00 00 leal (%esi), %esi +; CHECK: f: 8d b4 26 00 00 00 00 leal (%esi), %esi +; CHECK: 16: 8d b4 26 00 00 00 00 leal (%esi), %esi +; CHECK: 1d: 8d 76 00 leal (%esi), %esi +; CHECK: 20: 40 incl %eax + +; Use function target information to generate long nop of the right length. +; The target information for this function was inherited from the module. +define void @test1() #0 { +entry: + call void asm sideeffect "inc %eax", "~{dirflag},~{fpsr},~{flags}"() + call void asm sideeffect ".p2align 5", "~{dirflag},~{fpsr},~{flags}"() + call void asm sideeffect "inc %eax", "~{dirflag},~{fpsr},~{flags}"() + ret void +; CHECK-LABEL: test1 +; CHECK: 33: 40 incl %eax +; CHECK: 34: 8d b4 26 00 00 00 00 leal (%esi), %esi +; CHECK: 3b: 90 nop +; CHECK: 3c: 8d 74 26 00 leal (%esi), %esi +; CHECK: 40: 40 incl %eax +} + +; Use function target information to generate long nop of the right length. +; The target information for this function was specified through __attribute__. +define void @test2() #1 { +entry: + call void asm sideeffect "inc %eax", "~{dirflag},~{fpsr},~{flags}"() + call void asm sideeffect ".p2align 5", "~{dirflag},~{fpsr},~{flags}"() + call void asm sideeffect "inc %eax", "~{dirflag},~{fpsr},~{flags}"() + ret void +; CHECK-LABEL: test2 +; CHECK: 53: 40 incl %eax +; CHECK: 54: 66 66 66 2e 0f 1f 84 00 00 00 00 00 nopw %cs:(%eax,%eax) +; CHECK: 60: 40 incl %eax +} + +; Use function target information to generate long nop of the right length. +; The target information for this function was specified through __attribute__. +define void @test3() #2 { +entry: + call void asm sideeffect "inc %eax", "~{dirflag},~{fpsr},~{flags}"() + call void asm sideeffect ".p2align 5", "~{dirflag},~{fpsr},~{flags}"() + call void asm sideeffect "inc %eax", "~{dirflag},~{fpsr},~{flags}"() + ret void +; CHECK-LABEL: test3 +; CHECK: 73: 40 incl %eax +; CHECK: 74: 0f 1f 80 00 00 00 00 nopl (%eax) +; CHECK: 7b: 0f 1f 44 00 00 nopl (%eax,%eax) +; CHECK: 80: 40 incl %eax +} + +attributes #0 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="i386" "target-features"="+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core-avx2" "target-features"="+long-nop,+aes,+avx,+avx2,+bmi,+bmi2,+cx16,+f16c,+fma,+fsgsbase,+fxsr,+lzcnt,+mmx,+movbe,+pclmul,+popcnt,+rdrnd,+rtm,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87,+xsave,+xsaveopt" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="slm" "target-features"="+long-nop,+fast-nop-7,+aes,+cx16,+fxsr,+mmx,+pclmul,+popcnt,+sse,+sse2,+sse3,+sse4.1,+sse4.2,+ssse3,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }