Make fixups reference any constant (allow const float/double pool literals).

This avoids doing getConstantSym to avoid hitting the global
context's getConstantSym during emitIAS(), which may be desirable for
multi-threading, since each function's emitIAS() should be able to happen
on a separate thread.

The stringification is moved till later, so it still happens, just without
creating a constant relocatable w/ offset of 0.

This ends up tickling an issue where -O0 on 252.eon now gets 2x as many
page faults, and I'm not sure exactly why. This makes the overall time
higher, though emit time is lower.

When translating with -O2 # of page faults is about the same before/after,
so that oddness is restricted to O0.

Before this change, tweaking the slab size at O0 doesn't
seem to affect as drastically as 2x swings either.

To work around this, I turned the slab size of the assembler down to 32KB.

===

Move all the .L$type$poolid into a function (replacing getPoolEntryID).

BUG=none
R=stichnot@chromium.org

Review URL: https://codereview.chromium.org/837553009
diff --git a/src/IceCfg.cpp b/src/IceCfg.cpp
index d3c47d4..a16b35c 100644
--- a/src/IceCfg.cpp
+++ b/src/IceCfg.cpp
@@ -25,7 +25,7 @@
 
 thread_local const Cfg *Cfg::CurrentCfg = nullptr;
 
-ArenaAllocator *getCurrentCfgAllocator() {
+ArenaAllocator<> *getCurrentCfgAllocator() {
   return Cfg::getCurrentCfgAllocator();
 }
 
@@ -33,7 +33,7 @@
     : Ctx(Ctx), FunctionName(""), ReturnType(IceType_void),
       IsInternalLinkage(false), HasError(false), FocusedTiming(false),
       ErrorMessage(""), Entry(nullptr), NextInstNumber(Inst::NumberInitial),
-      Allocator(new ArenaAllocator()), Live(nullptr),
+      Allocator(new ArenaAllocator<>()), Live(nullptr),
       Target(TargetLowering::createLowering(Ctx->getTargetArch(), this)),
       VMetadata(new VariablesMetadata(this)),
       TargetAssembler(
diff --git a/src/IceCfg.h b/src/IceCfg.h
index 1db1357..15f353c 100644
--- a/src/IceCfg.h
+++ b/src/IceCfg.h
@@ -43,7 +43,7 @@
   // Gets a pointer to the current thread's Cfg.
   static const Cfg *getCurrentCfg() { return CurrentCfg; }
   // Gets a pointer to the current thread's Cfg's allocator.
-  static ArenaAllocator *getCurrentCfgAllocator() {
+  static ArenaAllocator<> *getCurrentCfgAllocator() {
     assert(CurrentCfg);
     return CurrentCfg->Allocator.get();
   }
@@ -197,7 +197,7 @@
   VarList Variables;
   VarList Args; // subset of Variables, in argument order
   VarList ImplicitArgs; // subset of Variables
-  std::unique_ptr<ArenaAllocator> Allocator;
+  std::unique_ptr<ArenaAllocator<>> Allocator;
   std::unique_ptr<Liveness> Live;
   std::unique_ptr<TargetLowering> Target;
   std::unique_ptr<VariablesMetadata> VMetadata;
diff --git a/src/IceDefs.h b/src/IceDefs.h
index f5147c6..584e059 100644
--- a/src/IceDefs.h
+++ b/src/IceDefs.h
@@ -58,10 +58,11 @@
 class VariableDeclaration;
 class VariablesMetadata;
 
-typedef llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, 1024 * 1024>
-ArenaAllocator;
+template <size_t SlabSize = 1024 * 1024>
+using ArenaAllocator =
+    llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, SlabSize>;
 
-ArenaAllocator *getCurrentCfgAllocator();
+ArenaAllocator<> *getCurrentCfgAllocator();
 
 template <typename T> struct CfgLocalAllocator {
   using value_type = T;
diff --git a/src/IceELFObjectWriter.cpp b/src/IceELFObjectWriter.cpp
index 4a31a99..7eebfa9 100644
--- a/src/IceELFObjectWriter.cpp
+++ b/src/IceELFObjectWriter.cpp
@@ -325,7 +325,7 @@
     auto Const = llvm::cast<ConstType>(C);
     std::string SymBuffer;
     llvm::raw_string_ostream SymStrBuf(SymBuffer);
-    SymStrBuf << ".L$" << Ty << "$" << Const->getPoolEntryID();
+    Const->emitPoolLabel(SymStrBuf);
     std::string &SymName = SymStrBuf.str();
     SymTab->createDefinedSym(SymName, STT_NOTYPE, STB_LOCAL, Section,
                              OffsetInSection, SymbolSize);
diff --git a/src/IceGlobalContext.h b/src/IceGlobalContext.h
index 1b66294..9508b07 100644
--- a/src/IceGlobalContext.h
+++ b/src/IceGlobalContext.h
@@ -197,7 +197,7 @@
   Ostream *StrDump; // Stream for dumping / diagnostics
   Ostream *StrEmit; // Stream for code emission
 
-  ArenaAllocator Allocator;
+  ArenaAllocator<> Allocator;
   VerboseMask VMask;
   std::unique_ptr<class ConstantPool> ConstPool;
   Intrinsics IntrinsicsInfo;
diff --git a/src/IceInstX8632.cpp b/src/IceInstX8632.cpp
index 95be640..77f54ef 100644
--- a/src/IceInstX8632.cpp
+++ b/src/IceInstX8632.cpp
@@ -587,7 +587,8 @@
   } else if (const auto Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
     AssemblerFixup *Fixup =
         x86::DisplacementRelocation::create(Asm, FK_Abs_4, Reloc);
-    (Asm->*(Emitter.GPRImm))(Ty, VarReg, x86::Immediate(Fixup));
+    (Asm->*(Emitter.GPRImm))(Ty, VarReg,
+                             x86::Immediate(Reloc->getOffset(), Fixup));
   } else if (const auto Split = llvm::dyn_cast<VariableSplit>(Src)) {
     (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Split->toAsmAddress(Func));
   } else {
@@ -610,7 +611,8 @@
   } else if (const auto Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
     AssemblerFixup *Fixup =
         x86::DisplacementRelocation::create(Asm, FK_Abs_4, Reloc);
-    (Asm->*(Emitter.AddrImm))(Ty, Addr, x86::Immediate(Fixup));
+    (Asm->*(Emitter.AddrImm))(Ty, Addr,
+                              x86::Immediate(Reloc->getOffset(), Fixup));
   } else {
     llvm_unreachable("Unexpected operand type");
   }
@@ -727,8 +729,7 @@
     assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment);
     (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm));
   } else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) {
-    (Asm->*(Emitter.XmmAddr))(
-        Ty, VarReg, x86::Address::ofConstPool(Func->getContext(), Asm, Imm));
+    (Asm->*(Emitter.XmmAddr))(Ty, VarReg, x86::Address::ofConstPool(Asm, Imm));
   } else {
     llvm_unreachable("Unexpected operand type");
   }
@@ -2319,7 +2320,7 @@
     assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment);
     Asm->fld(Ty, Mem->toAsmAddress(Asm));
   } else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) {
-    Asm->fld(Ty, x86::Address::ofConstPool(Func->getContext(), Asm, Imm));
+    Asm->fld(Ty, x86::Address::ofConstPool(Asm, Imm));
   } else {
     llvm_unreachable("Unexpected operand type");
   }
@@ -2849,6 +2850,7 @@
       Disp = static_cast<int32_t>(CI->getValue());
     } else if (const auto CR =
                    llvm::dyn_cast<ConstantRelocatable>(getOffset())) {
+      Disp = CR->getOffset();
       Fixup = x86::DisplacementRelocation::create(Asm, FK_Abs_4, CR);
     } else {
       llvm_unreachable("Unexpected offset type");
@@ -2866,9 +2868,7 @@
     return x86::Address(RegX8632::getEncodedGPR(getIndex()->getRegNum()),
                         x86::ScaleFactor(getShift()), Disp);
   } else if (Fixup) {
-    // The fixup itself has an offset, so Disp should still be 0.
-    assert(Disp == 0);
-    return x86::Address::Absolute(Fixup);
+    return x86::Address::Absolute(Disp, Fixup);
   } else {
     return x86::Address::Absolute(Disp);
   }
diff --git a/src/IceOperand.h b/src/IceOperand.h
index 035dc16..6eb5eb9 100644
--- a/src/IceOperand.h
+++ b/src/IceOperand.h
@@ -101,7 +101,9 @@
   Constant &operator=(const Constant &) = delete;
 
 public:
-  uint32_t getPoolEntryID() const { return PoolEntryID; }
+  void emitPoolLabel(Ostream &Str) const {
+    Str << ".L$" << getType() << "$" << PoolEntryID;
+  }
   using Operand::dump;
   void emit(const Cfg *Func) const override { emit(Func->getContext()); }
   virtual void emit(GlobalContext *Ctx) const = 0;
diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp
index 5a111b8..b0a08b0 100644
--- a/src/IceTargetLoweringX8632.cpp
+++ b/src/IceTargetLoweringX8632.cpp
@@ -1013,8 +1013,8 @@
     assert(CharsPrinted >= 0 &&
            (size_t)CharsPrinted < llvm::array_lengthof(buf));
     (void)CharsPrinted; // avoid warnings if asserts are disabled
-    Str << ".L$" << Ty << "$" << Const->getPoolEntryID() << ":\n";
-    Str << "\t" << T::AsmTag << "\t" << buf << "\t# " << T::TypeName << " "
+    Const->emitPoolLabel(Str);
+    Str << ":\n\t" << T::AsmTag << "\t" << buf << "\t# " << T::TypeName << " "
         << Value << "\n";
   }
 }
@@ -4610,14 +4610,14 @@
   if (!ALLOW_DUMP)
     return;
   Ostream &Str = Ctx->getStrEmit();
-  Str << ".L$" << IceType_f32 << "$" << getPoolEntryID();
+  emitPoolLabel(Str);
 }
 
 template <> void ConstantDouble::emit(GlobalContext *Ctx) const {
   if (!ALLOW_DUMP)
     return;
   Ostream &Str = Ctx->getStrEmit();
-  Str << ".L$" << IceType_f64 << "$" << getPoolEntryID();
+  emitPoolLabel(Str);
 }
 
 void ConstantUndef::emit(GlobalContext *) const {
diff --git a/src/assembler.cpp b/src/assembler.cpp
index a9516e8..d4f566b 100644
--- a/src/assembler.cpp
+++ b/src/assembler.cpp
@@ -124,14 +124,7 @@
       Str << "\n";
     }
     Str << "\t.long ";
-    const ConstantRelocatable *Reloc = NextFixup->value();
-    if (Reloc->getSuppressMangling())
-      Str << Reloc->getName();
-    else
-      Str << Ctx->mangleName(Reloc->getName());
-    if (Reloc->getOffset()) {
-      Str << " + " << Reloc->getOffset();
-    }
+    NextFixup->emit(Ctx);
     bool IsPCRel = NextFixup->kind() == FK_PcRel_4;
     if (IsPCRel)
       Str << " - (. + " << FixupSize << ")";
@@ -147,4 +140,34 @@
   }
 }
 
+RelocOffsetT AssemblerFixup::offset() const {
+  if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(value_))
+    return CR->getOffset();
+  return 0;
+}
+
+IceString AssemblerFixup::symbol(GlobalContext *Ctx) const {
+  std::string Buffer;
+  llvm::raw_string_ostream Str(Buffer);
+  const Constant *C = value_;
+  if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(C)) {
+    if (CR->getSuppressMangling())
+      Str << CR->getName();
+    else
+      Str << Ctx->mangleName(CR->getName());
+  } else {
+    assert(llvm::isa<ConstantFloat>(C) || llvm::isa<ConstantDouble>(C));
+    C->emitPoolLabel(Str);
+  }
+  return Str.str();
+}
+
+void AssemblerFixup::emit(GlobalContext *Ctx) const {
+  Ostream &Str = Ctx->getStrEmit();
+  Str << symbol(Ctx);
+  RelocOffsetT Offset = offset();
+  if (Offset)
+    Str << " + " << Offset;
+}
+
 } // end of namespace Ice
diff --git a/src/assembler.h b/src/assembler.h
index cdbc505..44159e0 100644
--- a/src/assembler.h
+++ b/src/assembler.h
@@ -51,16 +51,20 @@
 
   FixupKind kind() const { return kind_; }
 
-  const ConstantRelocatable *value() const { return value_; }
+  RelocOffsetT offset() const;
+
+  IceString symbol(GlobalContext *Ctx) const;
+
+  void emit(GlobalContext *Ctx) const;
 
 protected:
-  AssemblerFixup(FixupKind Kind, const ConstantRelocatable *Value)
+  AssemblerFixup(FixupKind Kind, const Constant *Value)
       : position_(0), kind_(Kind), value_(Value) {}
 
 private:
   intptr_t position_;
   FixupKind kind_;
-  const ConstantRelocatable *value_;
+  const Constant *value_;
 
   void set_position(intptr_t position) { position_ = position; }
 
@@ -230,7 +234,7 @@
   void emitIASBytes(GlobalContext *Ctx) const;
 
 private:
-  ArenaAllocator Allocator;
+  ArenaAllocator<32 * 1024> Allocator;
 
 protected:
   AssemblerBuffer buffer_;
diff --git a/src/assembler_ia32.cpp b/src/assembler_ia32.cpp
index 30b84e8..8feb7fe 100644
--- a/src/assembler_ia32.cpp
+++ b/src/assembler_ia32.cpp
@@ -31,31 +31,21 @@
 
 public:
   static DirectCallRelocation *create(Assembler *Asm, FixupKind Kind,
-                                      const ConstantRelocatable *Sym) {
+                                      const Constant *Sym) {
     return new (Asm->Allocate<DirectCallRelocation>())
         DirectCallRelocation(Kind, Sym);
   }
 
 private:
-  DirectCallRelocation(FixupKind Kind, const ConstantRelocatable *Sym)
+  DirectCallRelocation(FixupKind Kind, const Constant *Sym)
       : AssemblerFixup(Kind, Sym) {}
 };
 
-Address Address::ofConstPool(GlobalContext *Ctx, Assembler *Asm,
-                             const Constant *Imm) {
-  // We should make this much lighter-weight. E.g., just record the const pool
-  // entry ID.
-  std::string Buffer;
-  llvm::raw_string_ostream StrBuf(Buffer);
-  Type Ty = Imm->getType();
-  assert(llvm::isa<ConstantFloat>(Imm) || llvm::isa<ConstantDouble>(Imm));
-  StrBuf << ".L$" << Ty << "$" << Imm->getPoolEntryID();
+Address Address::ofConstPool(Assembler *Asm, const Constant *Imm) {
+  AssemblerFixup *Fixup =
+      x86::DisplacementRelocation::create(Asm, FK_Abs_4, Imm);
   const RelocOffsetT Offset = 0;
-  const bool SuppressMangling = true;
-  Constant *Sym = Ctx->getConstantSym(Offset, StrBuf.str(), SuppressMangling);
-  AssemblerFixup *Fixup = x86::DisplacementRelocation::create(
-      Asm, FK_Abs_4, llvm::cast<ConstantRelocatable>(Sym));
-  return x86::Address::Absolute(Fixup);
+  return x86::Address::Absolute(Offset, Fixup);
 }
 
 AssemblerX86::~AssemblerX86() {
diff --git a/src/assembler_ia32.h b/src/assembler_ia32.h
index d38dca7..08347c4 100644
--- a/src/assembler_ia32.h
+++ b/src/assembler_ia32.h
@@ -51,13 +51,13 @@
 
 public:
   static DisplacementRelocation *create(Assembler *Asm, FixupKind Kind,
-                                        const ConstantRelocatable *Sym) {
+                                        const Constant *Sym) {
     return new (Asm->Allocate<DisplacementRelocation>())
         DisplacementRelocation(Kind, Sym);
   }
 
 private:
-  DisplacementRelocation(FixupKind Kind, const ConstantRelocatable *Sym)
+  DisplacementRelocation(FixupKind Kind, const Constant *Sym)
       : AssemblerFixup(Kind, Sym) {}
 };
 
@@ -68,8 +68,8 @@
 public:
   explicit Immediate(int32_t value) : value_(value), fixup_(nullptr) {}
 
-  explicit Immediate(AssemblerFixup *fixup)
-      : value_(fixup->value()->getOffset()), fixup_(fixup) {
+  Immediate(RelocOffsetT offset, AssemblerFixup *fixup)
+      : value_(offset), fixup_(fixup) {
     // Use the Offset in the "value" for now. If the symbol is part of
     // ".bss", then the relocation's symbol will be plain ".bss" and
     // the value will need to be adjusted further to be sym's
@@ -250,20 +250,19 @@
     return result;
   }
 
-  static Address Absolute(AssemblerFixup *fixup) {
+  static Address Absolute(RelocOffsetT Offset, AssemblerFixup *fixup) {
     Address result;
     result.SetModRM(0, RegX8632::Encoded_Reg_ebp);
     // Use the Offset in the displacement for now. If the symbol is part of
     // ".bss", then the relocation's symbol will be plain .bss and the
     // displacement will need to be adjusted further to be sym's
     // bss offset + Offset.
-    result.SetDisp32(fixup->value()->getOffset());
+    result.SetDisp32(Offset);
     result.SetFixup(fixup);
     return result;
   }
 
-  static Address ofConstPool(GlobalContext *Ctx, Assembler *Asm,
-                             const Constant *Imm);
+  static Address ofConstPool(Assembler *Asm, const Constant *Imm);
 
 private:
   Address() {} // Needed by Address::Absolute.