[MC] Adding code padding for performance stability - infrastructure. NFC.

Infrastructure designed for padding code with nop instructions in key places such that preformance improvement will be achieved.
The infrastructure is implemented such that the padding is done in the Assembler after the layout is done and all IPs and alignments are known.
This patch by itself in a NFC. Future patches will make use of this infrastructure to implement required policies for code padding.

Reviewers:
aaboud
zvi
craig.topper
gadi.haber

Differential revision: https://reviews.llvm.org/D34393

Change-Id: I92110d0c0a757080a8405636914a93ef6f8ad00e
llvm-svn: 316413
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp
index eaf6f19..29b1441 100644
--- a/llvm/lib/MC/MCAssembler.cpp
+++ b/llvm/lib/MC/MCAssembler.cpp
@@ -68,6 +68,10 @@
 STATISTIC(ObjectBytes, "Number of emitted object file bytes");
 STATISTIC(RelaxationSteps, "Number of assembler layout and relaxation steps");
 STATISTIC(RelaxedInstructions, "Number of relaxed instructions");
+STATISTIC(PaddingFragmentsRelaxations,
+          "Number of Padding Fragments relaxations");
+STATISTIC(PaddingFragmentsBytes,
+          "Total size of all padding from adding Fragments");
 
 } // end namespace stats
 } // end anonymous namespace
@@ -283,6 +287,9 @@
   case MCFragment::FT_LEB:
     return cast<MCLEBFragment>(F).getContents().size();
 
+  case MCFragment::FT_Padding:
+    return cast<MCPaddingFragment>(F).getSize();
+
   case MCFragment::FT_SafeSEH:
     return 4;
 
@@ -549,6 +556,13 @@
     break;
   }
 
+  case MCFragment::FT_Padding: {
+    if (!Asm.getBackend().writeNopData(FragmentSize, OW))
+      report_fatal_error("unable to write nop sequence of " +
+                         Twine(FragmentSize) + " bytes");
+    break;
+  }
+
   case MCFragment::FT_SafeSEH: {
     const MCSafeSEHFragment &SF = cast<MCSafeSEHFragment>(F);
     OW->write32(SF.getSymbol()->getIndex());
@@ -822,6 +836,19 @@
   return true;
 }
 
+bool MCAssembler::relaxPaddingFragment(MCAsmLayout &Layout,
+                                       MCPaddingFragment &PF) {
+  uint64_t OldSize = PF.getSize();
+  if (!getBackend().relaxFragment(&PF, Layout))
+    return false;
+  uint64_t NewSize = PF.getSize();
+
+  ++stats::PaddingFragmentsRelaxations;
+  stats::PaddingFragmentsBytes += NewSize;
+  stats::PaddingFragmentsBytes -= OldSize;
+  return true;
+}
+
 bool MCAssembler::relaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) {
   uint64_t OldSize = LF.getContents().size();
   int64_t Value;
@@ -916,6 +943,9 @@
     case MCFragment::FT_LEB:
       RelaxedFrag = relaxLEB(Layout, *cast<MCLEBFragment>(I));
       break;
+    case MCFragment::FT_Padding:
+      RelaxedFrag = relaxPaddingFragment(Layout, *cast<MCPaddingFragment>(I));
+      break;
     case MCFragment::FT_CVInlineLines:
       RelaxedFrag =
           relaxCVInlineLineTable(Layout, *cast<MCCVInlineLineTableFragment>(I));