Commit 0cb415c1 authored by Fangrui Song's avatar Fangrui Song
Browse files

[X86][BranchAlign] Suppress branch alignment for {,_}__tls_get_addr

The x86-64 General Dynamic TLS code sequence uses prefixes to allow
linker relaxation.  Adding segment override prefix or NOPs can break
linker relaxation (ld -pie/-no-pie).

i386 General Dynamic and x86-64 Local Dynamic do not use prefixes, but
for simplicity, just disable auto padding consistently.

Reviewed By: skan, LuoYuanke

Differential Revision: https://reviews.llvm.org/D72878
parent 9583a3f2
Loading
Loading
Loading
Loading
+22 −23
Original line number Diff line number Diff line
@@ -72,6 +72,27 @@ private:

} // end anonymous namespace

/// A RAII helper which defines a region of instructions which can't have
/// padding added between them for correctness.
struct NoAutoPaddingScope {
  MCStreamer &OS;
  const bool OldAllowAutoPadding;
  NoAutoPaddingScope(MCStreamer &OS)
      : OS(OS), OldAllowAutoPadding(OS.getAllowAutoPadding()) {
    changeAndComment(false);
  }
  ~NoAutoPaddingScope() { changeAndComment(OldAllowAutoPadding); }
  void changeAndComment(bool b) {
    if (b == OS.getAllowAutoPadding())
      return;
    OS.setAllowAutoPadding(b);
    if (b)
      OS.emitRawComment("autopadding");
    else
      OS.emitRawComment("noautopadding");
  }
};

// Emit a minimal sequence of nops spanning NumBytes bytes.
static void EmitNops(MCStreamer &OS, unsigned NumBytes, bool Is64Bit,
                     const MCSubtargetInfo &STI);
@@ -929,6 +950,7 @@ void X86MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {

void X86AsmPrinter::LowerTlsAddr(X86MCInstLower &MCInstLowering,
                                 const MachineInstr &MI) {
  NoAutoPaddingScope NoPadScope(*OutStreamer);
  bool Is64Bits = MI.getOpcode() == X86::TLS_addr64 ||
                  MI.getOpcode() == X86::TLS_base_addr64;
  MCContext &Ctx = OutStreamer->getContext();
@@ -1161,29 +1183,6 @@ static void EmitNops(MCStreamer &OS, unsigned NumBytes, bool Is64Bit,
  }
}

/// A RAII helper which defines a region of instructions which can't have
/// padding added between them for correctness.
struct NoAutoPaddingScope {
  MCStreamer &OS;
  const bool OldAllowAutoPadding;
  NoAutoPaddingScope(MCStreamer &OS)
    : OS(OS), OldAllowAutoPadding(OS.getAllowAutoPadding()) {
    changeAndComment(false);
  }
  ~NoAutoPaddingScope() {
    changeAndComment(OldAllowAutoPadding);
  }
  void changeAndComment(bool b) {
    if (b == OS.getAllowAutoPadding())
      return;
    OS.setAllowAutoPadding(b);
    if (b)
      OS.emitRawComment("autopadding");
    else
      OS.emitRawComment("noautopadding");
  }
};

void X86AsmPrinter::LowerSTATEPOINT(const MachineInstr &MI,
                                    X86MCInstLower &MCIL) {
  assert(Subtarget->is64Bit() && "Statepoint currently only supports X86-64");
+30 −0
Original line number Diff line number Diff line
;; Test that we don't pad the x86-64 General Dynamic/Local Dynamic TLS code
;; sequence. It uses prefixes to allow linker relaxation. We need to disable
;; prefix or nop padding for it. For simplicity and consistency, disable for
;; Local Dynamic and 32-bit as well.
; RUN: llc -mtriple=i386 -relocation-model=pic -x86-branches-within-32B-boundaries < %s | FileCheck --check-prefixes=CHECK,32 %s
; RUN: llc -mtriple=x86_64 -relocation-model=pic -x86-branches-within-32B-boundaries < %s | FileCheck --check-prefixes=CHECK,64 %s

@gd = external thread_local global i32
@ld = internal thread_local global i32 0

define i32 @tls_get_addr() {
; CHECK-LABEL: tls_get_addr:
; CHECK: #noautopadding
; 32: leal gd@TLSGD(,%ebx), %eax
; 32: calll ___tls_get_addr@PLT
; 64: data16
; 64: leaq gd@TLSGD(%rip), %rdi
; 64: callq __tls_get_addr@PLT
; CHECK: #autopadding
; CHECK: #noautopadding
; 32: leal ld@TLSLDM(%ebx), %eax
; 32: calll ___tls_get_addr@PLT
; 64: leaq ld@TLSLD(%rip), %rdi
; 64: callq __tls_get_addr@PLT
; CHECK: #autopadding
  %1 = load i32, i32* @gd
  %2 = load i32, i32* @ld
  %3 = add i32 %1, %2
  ret i32 %3
}