[llvm] r352616 - [RISCV] Insert R_RISCV_ALIGN relocation type and Nops for code alignment when linker relaxation enabled

Shiva Chen via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 30 03:16:59 PST 2019


Author: shiva
Date: Wed Jan 30 03:16:59 2019
New Revision: 352616

URL: http://llvm.org/viewvc/llvm-project?rev=352616&view=rev
Log:
[RISCV] Insert R_RISCV_ALIGN relocation type and Nops for code alignment when linker relaxation enabled

Linker relaxation may change code size. We need to fix up the alignment
of alignment directive in text section by inserting Nops and R_RISCV_ALIGN
relocation type. So then linker could satisfy the alignment by removing Nops.

To do this:

1. Add shouldInsertExtraNopBytesForCodeAlign target hook to calculate
   the Nops we need to insert.

2. Add shouldInsertFixupForCodeAlign target hook to insert
   R_RISCV_ALIGN fixup type.

Differential Revision: https://reviews.llvm.org/D47755

Added:
    llvm/trunk/test/MC/RISCV/align.s
Modified:
    llvm/trunk/include/llvm/MC/MCAsmBackend.h
    llvm/trunk/lib/MC/MCAssembler.cpp
    llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
    llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
    llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp
    llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h

Modified: llvm/trunk/include/llvm/MC/MCAsmBackend.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCAsmBackend.h?rev=352616&r1=352615&r2=352616&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCAsmBackend.h (original)
+++ llvm/trunk/include/llvm/MC/MCAsmBackend.h Wed Jan 30 03:16:59 2019
@@ -87,6 +87,22 @@ public:
     return false;
   }
 
+  /// Hook to check if extra nop bytes must be inserted for alignment directive.
+  /// For some targets this may be necessary in order to support linker
+  /// relaxation. The number of bytes to insert are returned in Size.
+  virtual bool shouldInsertExtraNopBytesForCodeAlign(const MCAlignFragment &AF,
+                                                     unsigned &Size) {
+    return false;
+  }
+
+  /// Hook which indicates if the target requires a fixup to be generated when
+  /// handling an align directive in an executable section
+  virtual bool shouldInsertFixupForCodeAlign(MCAssembler &Asm,
+                                             const MCAsmLayout &Layout,
+                                             MCAlignFragment &AF) {
+    return false;
+  }
+
   /// Apply the \p Value for given \p Fixup into the provided data fragment, at
   /// the offset specified by the fixup and following the fixup kind as
   /// appropriate. Errors (such as an out of range fixup value) should be

Modified: llvm/trunk/lib/MC/MCAssembler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCAssembler.cpp?rev=352616&r1=352615&r2=352616&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCAssembler.cpp (original)
+++ llvm/trunk/lib/MC/MCAssembler.cpp Wed Jan 30 03:16:59 2019
@@ -322,6 +322,13 @@ uint64_t MCAssembler::computeFragmentSiz
     const MCAlignFragment &AF = cast<MCAlignFragment>(F);
     unsigned Offset = Layout.getFragmentOffset(&AF);
     unsigned Size = OffsetToAlignment(Offset, AF.getAlignment());
+
+    // Insert extra Nops for code alignment if the target define
+    // shouldInsertExtraNopBytesForCodeAlign target hook.
+    if (AF.getParent()->UseCodeAlign() && AF.hasEmitNops() &&
+        getBackend().shouldInsertExtraNopBytesForCodeAlign(AF, Size))
+      return Size;
+
     // If we are padding with nops, force the padding to be larger than the
     // minimum nop size.
     if (Size > 0 && AF.hasEmitNops()) {
@@ -804,7 +811,8 @@ void MCAssembler::layout(MCAsmLayout &La
       if (isa<MCEncodedFragment>(&Frag) &&
           isa<MCCompactEncodedInstFragment>(&Frag))
         continue;
-      if (!isa<MCEncodedFragment>(&Frag) && !isa<MCCVDefRangeFragment>(&Frag))
+      if (!isa<MCEncodedFragment>(&Frag) && !isa<MCCVDefRangeFragment>(&Frag) &&
+          !isa<MCAlignFragment>(&Frag))
         continue;
       ArrayRef<MCFixup> Fixups;
       MutableArrayRef<char> Contents;
@@ -825,6 +833,13 @@ void MCAssembler::layout(MCAsmLayout &La
       } else if (auto *FragWithFixups = dyn_cast<MCDwarfLineAddrFragment>(&Frag)) {
         Fixups = FragWithFixups->getFixups();
         Contents = FragWithFixups->getContents();
+      } else if (auto *AF = dyn_cast<MCAlignFragment>(&Frag)) {
+        // Insert fixup type for code alignment if the target define
+        // shouldInsertFixupForCodeAlign target hook.
+        if (Sec.UseCodeAlign() && AF->hasEmitNops()) {
+          getBackend().shouldInsertFixupForCodeAlign(*this, Layout, *AF);
+        }
+        continue;
       } else
         llvm_unreachable("Unknown fragment with fixups!");
       for (const MCFixup &Fixup : Fixups) {

Modified: llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp?rev=352616&r1=352615&r2=352616&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp Wed Jan 30 03:16:59 2019
@@ -16,6 +16,7 @@
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCObjectWriter.h"
 #include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCValue.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -286,6 +287,57 @@ void RISCVAsmBackend::applyFixup(const M
   }
 }
 
+// Linker relaxation may change code size. We have to insert Nops
+// for .align directive when linker relaxation enabled. So then Linker
+// could satisfy alignment by removing Nops.
+// The function return the total Nops Size we need to insert.
+bool RISCVAsmBackend::shouldInsertExtraNopBytesForCodeAlign(
+    const MCAlignFragment &AF, unsigned &Size) {
+  // Calculate Nops Size only when linker relaxation enabled.
+  if (!STI.getFeatureBits()[RISCV::FeatureRelax])
+    return false;
+
+  bool HasStdExtC = STI.getFeatureBits()[RISCV::FeatureStdExtC];
+  unsigned MinNopLen = HasStdExtC ? 2 : 4;
+
+  Size = AF.getAlignment() - MinNopLen;
+  return true;
+}
+
+// We need to insert R_RISCV_ALIGN relocation type to indicate the
+// position of Nops and the total bytes of the Nops have been inserted
+// when linker relaxation enabled.
+// The function insert fixup_riscv_align fixup which eventually will
+// transfer to R_RISCV_ALIGN relocation type.
+bool RISCVAsmBackend::shouldInsertFixupForCodeAlign(MCAssembler &Asm,
+                                                    const MCAsmLayout &Layout,
+                                                    MCAlignFragment &AF) {
+  // Insert the fixup only when linker relaxation enabled.
+  if (!STI.getFeatureBits()[RISCV::FeatureRelax])
+    return false;
+
+  // Calculate total Nops we need to insert.
+  unsigned Count;
+  shouldInsertExtraNopBytesForCodeAlign(AF, Count);
+  // No Nop need to insert, simply return.
+  if (Count == 0)
+    return false;
+
+  MCContext &Ctx = Asm.getContext();
+  const MCExpr *Dummy = MCConstantExpr::create(0, Ctx);
+  // Create fixup_riscv_align fixup.
+  MCFixup Fixup =
+      MCFixup::create(0, Dummy, MCFixupKind(RISCV::fixup_riscv_align), SMLoc());
+
+  uint64_t FixedValue = 0;
+  MCValue NopBytes = MCValue::get(Count);
+
+  Asm.getWriter().recordRelocation(Asm, Layout, &AF, Fixup, NopBytes,
+                                   FixedValue);
+
+  return true;
+}
+
 std::unique_ptr<MCObjectTargetWriter>
 RISCVAsmBackend::createObjectTargetWriter() const {
   return createRISCVELFObjectWriter(OSABI, Is64Bit);

Modified: llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h?rev=352616&r1=352615&r2=352616&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h (original)
+++ llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h Wed Jan 30 03:16:59 2019
@@ -40,6 +40,16 @@ public:
   bool requiresDiffExpressionRelocations() const override {
     return STI.getFeatureBits()[RISCV::FeatureRelax] || ForceRelocs;
   }
+
+  // Return Size with extra Nop Bytes for alignment directive in code section.
+  bool shouldInsertExtraNopBytesForCodeAlign(const MCAlignFragment &AF,
+                                             unsigned &Size) override;
+
+  // Insert target specific fixup type for alignment directive in code section.
+  bool shouldInsertFixupForCodeAlign(MCAssembler &Asm,
+                                     const MCAsmLayout &Layout,
+                                     MCAlignFragment &AF) override;
+
   void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
                   const MCValue &Target, MutableArrayRef<char> Data,
                   uint64_t Value, bool IsResolved,
@@ -84,7 +94,8 @@ public:
       { "fixup_riscv_rvc_jump",      2,     11,  MCFixupKindInfo::FKF_IsPCRel },
       { "fixup_riscv_rvc_branch",    0,     16,  MCFixupKindInfo::FKF_IsPCRel },
       { "fixup_riscv_call",          0,     64,  MCFixupKindInfo::FKF_IsPCRel },
-      { "fixup_riscv_relax",         0,      0,  0 }
+      { "fixup_riscv_relax",         0,      0,  0 },
+      { "fixup_riscv_align",         0,      0,  0 }
     };
     static_assert((array_lengthof(Infos)) == RISCV::NumTargetFixupKinds,
                   "Not all fixup kinds added to Infos array");

Modified: llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp?rev=352616&r1=352615&r2=352616&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVELFObjectWriter.cpp Wed Jan 30 03:16:59 2019
@@ -95,6 +95,8 @@ unsigned RISCVELFObjectWriter::getRelocT
     return ELF::R_RISCV_CALL;
   case RISCV::fixup_riscv_relax:
     return ELF::R_RISCV_RELAX;
+  case RISCV::fixup_riscv_align:
+    return ELF::R_RISCV_ALIGN;
   }
 }
 

Modified: llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h?rev=352616&r1=352615&r2=352616&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h (original)
+++ llvm/trunk/lib/Target/RISCV/MCTargetDesc/RISCVFixupKinds.h Wed Jan 30 03:16:59 2019
@@ -52,6 +52,10 @@ enum Fixups {
   // fixup_riscv_relax - Used to generate an R_RISCV_RELAX relocation type,
   // which indicates the linker may relax the instruction pair.
   fixup_riscv_relax,
+  // fixup_riscv_align - Used to generate an R_RISCV_ALIGN relocation type,
+  // which indicates the linker should fixup the alignment after linker
+  // relaxation.
+  fixup_riscv_align,
 
   // fixup_riscv_invalid - used as a sentinel and a marker, must be last fixup
   fixup_riscv_invalid,

Added: llvm/trunk/test/MC/RISCV/align.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/RISCV/align.s?rev=352616&view=auto
==============================================================================
--- llvm/trunk/test/MC/RISCV/align.s (added)
+++ llvm/trunk/test/MC/RISCV/align.s Wed Jan 30 03:16:59 2019
@@ -0,0 +1,105 @@
+# The file testing Nop insertion with R_RISCV_ALIGN for relaxation.
+
+# Relaxation enabled:
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+relax < %s \
+# RUN:     | llvm-objdump -d -riscv-no-aliases - \
+# RUN:     | FileCheck -check-prefix=RELAX-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+relax < %s \
+# RUN:     | llvm-readobj -r | FileCheck -check-prefix=RELAX-RELOC %s
+
+# Relaxation disabled:
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=-relax < %s \
+# RUN:     | llvm-objdump -d -riscv-no-aliases - \
+# RUN:     | FileCheck -check-prefix=NORELAX-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=-relax < %s \
+# RUN:     | llvm-readobj -r | FileCheck -check-prefix=NORELAX-RELOC %s
+
+# Relaxation enabled with C extension:
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+c,+relax < %s \
+# RUN:     | llvm-objdump -d -riscv-no-aliases - \
+# RUN:     | FileCheck -check-prefix=C-EXT-RELAX-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+c,+relax < %s \
+# RUN:     | llvm-readobj -r | FileCheck -check-prefix=C-EXT-RELAX-RELOC %s
+
+# Relaxation disabled with C extension:
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+c,-relax < %s \
+# RUN:     | llvm-objdump -d -riscv-no-aliases - \
+# RUN:     | FileCheck -check-prefix=C-EXT-NORELAX-INST %s
+# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+c,-relax < %s \
+# RUN:     | llvm-readobj -r | FileCheck -check-prefix=C-EXT-NORELAX-RELOC %s
+
+# We need to insert N-MinNopSize bytes NOPs and R_RISCV_ALIGN relocation
+# type for .align N directive when linker relaxation enabled.
+# Linker could satisfy alignment by removing NOPs after linker relaxation.
+
+# The first R_RISCV_ALIGN come from
+# MCELFStreamer::InitSections() EmitCodeAlignment(4).
+# C-EXT-RELAX-RELOC: R_RISCV_ALIGN - 0x2
+# C-EXT-RELAX-INST:  c.nop
+test:
+	.p2align 2
+# C-EXT-RELAX-RELOC: R_RISCV_ALIGN - 0x2
+# C-EXT-RELAX-INST:  c.nop
+	bne     zero, a0, .LBB0_2
+	mv	a0, zero
+	.p2align 3
+# RELAX-RELOC: R_RISCV_ALIGN - 0x4
+# RELAX-INST:  addi    zero, zero, 0
+# C-EXT-RELAX-RELOC: R_RISCV_ALIGN - 0x6
+# C-EXT-RELAX-INST:  addi    zero, zero, 0
+# C-EXT-RELAX-INST:  c.nop
+# C-EXT-NORELAX-INST: addi    zero, zero, 0
+	add	a0, a0, a1
+	.align 4
+.LBB0_2:
+# RELAX-RELOC: R_RISCV_ALIGN - 0xC
+# RELAX-INST:  addi    zero, zero, 0
+# RELAX-INST:  addi    zero, zero, 0
+# RELAX-INST:  addi    zero, zero, 0
+# NORELAX-INST: addi    zero, zero, 0
+# C-EXT-RELAX-RELOC: R_RISCV_ALIGN - 0xE
+# C-EXT-RELAX-INST:  addi    zero, zero, 0
+# C-EXT-RELAX-INST:  addi    zero, zero, 0
+# C-EXT-RELAX-INST:  addi    zero, zero, 0
+# C-EXT-RELAX-INST:  c.nop
+# C-EXT-INST: addi    zero, zero, 0
+# C-EXT-INST: c.nop
+	add	a0, a0, a1
+	.p2align 3
+.constant_pool:
+.long	3126770193
+# RELAX-RELOC: R_RISCV_ALIGN - 0x4
+# RELAX-INST:  addi    zero, zero, 0
+# NORELAX-INST: addi    zero, zero, 0
+# C-EXT-RELAX-RELOC: R_RISCV_ALIGN - 0x6
+# C-EXT-RELAX-INST:  addi    zero, zero, 0
+# C-EXT-RELAX-INST:  c.nop
+# C-EXT-INST: addi    zero, zero, 0
+# C-EXT-INST: c.nop
+	add	a0, a0, a1
+# Alignment directive with specific padding value 0x01.
+# We will not emit R_RISCV_ALIGN in this case.
+# The behavior is the same as GNU assembler.
+	.p2align 4, 1
+# RELAX-RELOC-NOT: R_RISCV_ALIGN - 0xC
+# RELAX-INST:  01 01
+# RELAX-INST:  01 01
+# C-EXT-RELAX-RELOC-NOT: R_RISCV_ALIGN - 0xE
+# C-EXT-RELAX-INST:  01 01
+# C-EXT-INST:  01 01
+	ret
+# NORELAX-RELOC-NOT: R_RISCV
+# C-EXT-NORELAX-RELOC-NOT: R_RISCV
+# We only need to insert R_RISCV_ALIGN for code section
+# when the linker relaxation enabled.
+        .data
+	.p2align        3
+# RELAX-RELOC-NOT: R_RISCV_ALIGN
+# C-EXT-RELAX-RELOC-NOT: R_RISCV_ALIGN
+data1:
+	.word 7
+	.p2align        4
+# RELAX-RELOC-NOT: R_RISCV_ALIGN
+# C-EXT-RELAX-RELOC-NOT: R_RISCV_ALIGN
+data2:
+	.word 9




More information about the llvm-commits mailing list