[llvm] 241c2da - [AIX][Power10] Restrict prefixed instructions from crossing the 64byte boundary

Victor Huang via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 27 09:56:17 PDT 2021


Author: Victor Huang
Date: 2021-04-27T11:55:18-05:00
New Revision: 241c2da4064c850d58896e0a870b0c3485dfd82d

URL: https://github.com/llvm/llvm-project/commit/241c2da4064c850d58896e0a870b0c3485dfd82d
DIFF: https://github.com/llvm/llvm-project/commit/241c2da4064c850d58896e0a870b0c3485dfd82d.diff

LOG: [AIX][Power10] Restrict prefixed instructions from crossing the 64byte boundary

This patch adds the support to restrict prefixed instruction from
crossing the 64 byte boundary:
- Add the infrastructure to register a custom XCOFF streamer
- Add a custom XCOFF streamer for PowerPC to allow us to
  intercept instructions as they are being emitted and align all 8 byte
  instructions to a 64 byte boundary if required by adding a 4 byte nop.

Reviewed By: stefanp

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

Added: 
    llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFStreamer.cpp
    llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFStreamer.h
    llvm/test/CodeGen/PowerPC/aix-prefixed-instruction-boundary.mir

Modified: 
    llvm/include/llvm/Support/TargetRegistry.h
    llvm/lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt
    llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Support/TargetRegistry.h b/llvm/include/llvm/Support/TargetRegistry.h
index 75bc5ce75104d..9d21babd82e02 100644
--- a/llvm/include/llvm/Support/TargetRegistry.h
+++ b/llvm/include/llvm/Support/TargetRegistry.h
@@ -183,6 +183,12 @@ class Target {
                       std::unique_ptr<MCAsmBackend> &&TAB,
                       std::unique_ptr<MCObjectWriter> &&OW,
                       std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll);
+  using XCOFFStreamerCtorTy =
+      MCStreamer *(*)(const Triple &T, MCContext &Ctx,
+                      std::unique_ptr<MCAsmBackend> &&TAB,
+                      std::unique_ptr<MCObjectWriter> &&OW,
+                      std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll);
+
   using NullTargetStreamerCtorTy = MCTargetStreamer *(*)(MCStreamer &S);
   using AsmTargetStreamerCtorTy = MCTargetStreamer *(*)(
       MCStreamer &S, formatted_raw_ostream &OS, MCInstPrinter *InstPrint,
@@ -270,6 +276,7 @@ class Target {
   MachOStreamerCtorTy MachOStreamerCtorFn = nullptr;
   ELFStreamerCtorTy ELFStreamerCtorFn = nullptr;
   WasmStreamerCtorTy WasmStreamerCtorFn = nullptr;
+  XCOFFStreamerCtorTy XCOFFStreamerCtorFn = nullptr;
 
   /// Construction function for this target's null TargetStreamer, if
   /// registered (default = nullptr).
@@ -513,8 +520,12 @@ class Target {
     case Triple::GOFF:
       report_fatal_error("GOFF MCObjectStreamer not implemented yet");
     case Triple::XCOFF:
-      S = createXCOFFStreamer(Ctx, std::move(TAB), std::move(OW),
-                              std::move(Emitter), RelaxAll);
+      if (XCOFFStreamerCtorFn)
+        S = XCOFFStreamerCtorFn(T, Ctx, std::move(TAB), std::move(OW),
+                                std::move(Emitter), RelaxAll);
+      else
+        S = createXCOFFStreamer(Ctx, std::move(TAB), std::move(OW),
+                                std::move(Emitter), RelaxAll);
       break;
     }
     if (ObjectTargetStreamerCtorFn)
@@ -868,6 +879,10 @@ struct TargetRegistry {
     T.WasmStreamerCtorFn = Fn;
   }
 
+  static void RegisterXCOFFStreamer(Target &T, Target::XCOFFStreamerCtorTy Fn) {
+    T.XCOFFStreamerCtorFn = Fn;
+  }
+
   static void RegisterNullTargetStreamer(Target &T,
                                          Target::NullTargetStreamerCtorTy Fn) {
     T.NullTargetStreamerCtorFn = Fn;

diff  --git a/llvm/lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt
index 75c81e5123622..6433111aabfa3 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/CMakeLists.txt
@@ -9,6 +9,7 @@ add_llvm_component_library(LLVMPowerPCDesc
   PPCELFObjectWriter.cpp
   PPCXCOFFObjectWriter.cpp
   PPCELFStreamer.cpp
+  PPCXCOFFStreamer.cpp
 
   LINK_COMPONENTS
   MC

diff  --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
index c5babbee39b4a..15810b59faf47 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
@@ -15,6 +15,7 @@
 #include "MCTargetDesc/PPCMCAsmInfo.h"
 #include "PPCELFStreamer.h"
 #include "PPCTargetStreamer.h"
+#include "PPCXCOFFStreamer.h"
 #include "TargetInfo/PowerPCTargetInfo.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/StringRef.h"
@@ -112,15 +113,23 @@ static MCAsmInfo *createPPCMCAsmInfo(const MCRegisterInfo &MRI,
   return MAI;
 }
 
-static MCStreamer *createPPCMCStreamer(const Triple &T, MCContext &Context,
-                                       std::unique_ptr<MCAsmBackend> &&MAB,
-                                       std::unique_ptr<MCObjectWriter> &&OW,
-                                       std::unique_ptr<MCCodeEmitter> &&Emitter,
-                                       bool RelaxAll) {
+static MCStreamer *
+createPPCELFStreamer(const Triple &T, MCContext &Context,
+                     std::unique_ptr<MCAsmBackend> &&MAB,
+                     std::unique_ptr<MCObjectWriter> &&OW,
+                     std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll) {
   return createPPCELFStreamer(Context, std::move(MAB), std::move(OW),
                               std::move(Emitter));
 }
 
+static MCStreamer *createPPCXCOFFStreamer(
+    const Triple &T, MCContext &Context, std::unique_ptr<MCAsmBackend> &&MAB,
+    std::unique_ptr<MCObjectWriter> &&OW,
+    std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll) {
+  return createPPCXCOFFStreamer(Context, std::move(MAB), std::move(OW),
+                                std::move(Emitter));
+}
+
 namespace {
 
 class PPCTargetAsmStreamer : public PPCTargetStreamer {
@@ -377,7 +386,10 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCTargetMC() {
     TargetRegistry::RegisterMCAsmBackend(*T, createPPCAsmBackend);
 
     // Register the elf streamer.
-    TargetRegistry::RegisterELFStreamer(*T, createPPCMCStreamer);
+    TargetRegistry::RegisterELFStreamer(*T, createPPCELFStreamer);
+
+    // Register the XCOFF streamer.
+    TargetRegistry::RegisterXCOFFStreamer(*T, createPPCXCOFFStreamer);
 
     // Register the object target streamer.
     TargetRegistry::RegisterObjectTargetStreamer(*T,

diff  --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFStreamer.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFStreamer.cpp
new file mode 100644
index 0000000000000..e582ddfca3233
--- /dev/null
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFStreamer.cpp
@@ -0,0 +1,78 @@
+//===-------- PPCXCOFFStreamer.cpp - XCOFF Object Output ------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a custom MCXCOFFStreamer for PowerPC.
+//
+// The purpose of the custom XCOFF streamer is to allow us to intercept
+// instructions as they are being emitted and align all 8 byte instructions
+// to a 64 byte boundary if required (by adding a 4 byte nop). This is important
+// because 8 byte instructions are not allowed to cross 64 byte boundaries
+// and by aligning anything that is within 4 bytes of the boundary we can
+// guarantee that the 8 byte instructions do not cross that boundary.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PPCXCOFFStreamer.h"
+#include "PPCMCCodeEmitter.h"
+#include "llvm/BinaryFormat/XCOFF.h"
+#include "llvm/MC/MCAsmBackend.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCDirectives.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/MC/MCSectionXCOFF.h"
+#include "llvm/MC/MCSymbolXCOFF.h"
+#include "llvm/Support/TargetRegistry.h"
+
+using namespace llvm;
+
+PPCXCOFFStreamer::PPCXCOFFStreamer(MCContext &Context,
+                                   std::unique_ptr<MCAsmBackend> MAB,
+                                   std::unique_ptr<MCObjectWriter> OW,
+                                   std::unique_ptr<MCCodeEmitter> Emitter)
+    : MCXCOFFStreamer(Context, std::move(MAB), std::move(OW),
+                      std::move(Emitter)) {}
+
+void PPCXCOFFStreamer::emitPrefixedInstruction(const MCInst &Inst,
+                                               const MCSubtargetInfo &STI) {
+  // Prefixed instructions must not cross a 64-byte boundary (i.e. prefix is
+  // before the boundary and the remaining 4-bytes are after the boundary). In
+  // order to achieve this, a nop is added prior to any such boundary-crossing
+  // prefixed instruction. Align to 64 bytes if possible but add a maximum of 4
+  // bytes when trying to do that. If alignment requires adding more than 4
+  // bytes then the instruction won't be aligned.
+  emitCodeAlignment(64, 4);
+
+  // Emit the instruction.
+  // Since the previous emit created a new fragment then adding this instruction
+  // also forces the addition of a new fragment. Inst is now the first
+  // instruction in that new fragment.
+  MCXCOFFStreamer::emitInstruction(Inst, STI);
+}
+
+void PPCXCOFFStreamer::emitInstruction(const MCInst &Inst,
+                                       const MCSubtargetInfo &STI) {
+  PPCMCCodeEmitter *Emitter =
+      static_cast<PPCMCCodeEmitter *>(getAssembler().getEmitterPtr());
+
+  // Special handling is only for prefixed instructions.
+  if (!Emitter->isPrefixedInstruction(Inst)) {
+    MCXCOFFStreamer::emitInstruction(Inst, STI);
+    return;
+  }
+  emitPrefixedInstruction(Inst, STI);
+}
+
+MCXCOFFStreamer *
+llvm::createPPCXCOFFStreamer(MCContext &Context,
+                             std::unique_ptr<MCAsmBackend> MAB,
+                             std::unique_ptr<MCObjectWriter> OW,
+                             std::unique_ptr<MCCodeEmitter> Emitter) {
+  return new PPCXCOFFStreamer(Context, std::move(MAB), std::move(OW),
+                              std::move(Emitter));
+}

diff  --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFStreamer.h b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFStreamer.h
new file mode 100644
index 0000000000000..f6eb5edfb7a7f
--- /dev/null
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFStreamer.h
@@ -0,0 +1,39 @@
+//===- PPCXCOFFStreamer.h - XCOFF Object Output -----------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a custom MCXCOFFStreamer for PowerPC.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_PPC_MCXCOFFSTREAMER_PPCXCOFFSTREAMER_H
+#define LLVM_LIB_TARGET_PPC_MCXCOFFSTREAMER_PPCXCOFFSTREAMER_H
+
+#include "llvm/MC/MCXCOFFStreamer.h"
+
+namespace llvm {
+
+class PPCXCOFFStreamer : public MCXCOFFStreamer {
+public:
+  PPCXCOFFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,
+                   std::unique_ptr<MCObjectWriter> OW,
+                   std::unique_ptr<MCCodeEmitter> Emitter);
+
+  void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override;
+
+private:
+  void emitPrefixedInstruction(const MCInst &Inst, const MCSubtargetInfo &STI);
+};
+
+MCXCOFFStreamer *createPPCXCOFFStreamer(MCContext &Context,
+                                        std::unique_ptr<MCAsmBackend> MAB,
+                                        std::unique_ptr<MCObjectWriter> OW,
+                                        std::unique_ptr<MCCodeEmitter> Emitter);
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_PPC_MCXCOFFSTREAMER_PPCXCOFFSTREAMER_H

diff  --git a/llvm/test/CodeGen/PowerPC/aix-prefixed-instruction-boundary.mir b/llvm/test/CodeGen/PowerPC/aix-prefixed-instruction-boundary.mir
new file mode 100644
index 0000000000000..9ea49bf40c897
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-prefixed-instruction-boundary.mir
@@ -0,0 +1,74 @@
+# RUN: llc -verify-machineinstrs -mcpu=pwr4 -mtriple powerpc-ibm-aix-xcoff -x mir -verify-machineinstrs \
+# RUN:     -xcoff-traceback-table=false -start-before=ppc-branch-select -filetype=obj -o %t.o < %s
+# RUN: llvm-objdump -D -r --mcpu=pwr10 %t.o | FileCheck --check-prefix=DIS %s
+
+---
+name:            aix-prefixed-instruction-boundary
+alignment:       16
+tracksRegLiveness: true
+liveins:
+  - { reg: '$x3', virtual-reg: '' }
+body:             |
+  bb.0.entry:
+    liveins: $x3
+    renamable $x3 = LI8 2
+    renamable $x3 = PADDI8 $x3, 13
+    renamable $x3 = PADDI8 $x3, 13
+    renamable $x3 = PADDI8 $x3, 13
+    renamable $x3 = PADDI8 $x3, 13
+    renamable $x3 = PADDI8 $x3, 13
+    renamable $x3 = PADDI8 $x3, 13
+    renamable $x3 = PADDI8 $x3, 13
+
+    renamable $x3 = PADDI8 $x3, 13
+    renamable $x3 = PADDI8 $x3, 13
+    renamable $x3 = PADDI8 $x3, 13
+    renamable $x3 = PADDI8 $x3, 13
+    renamable $x3 = PADDI8 $x3, 13
+    renamable $x3 = PADDI8 $x3, 13
+    renamable $x3 = PADDI8 $x3, 13
+    renamable $x3 = PADDI8 $x3, 13
+
+    renamable $x3 = PADDI8 $x3, 13
+    renamable $x3 = PADDI8 $x3, 13
+    renamable $x3 = PADDI8 $x3, 13
+    renamable $x3 = PADDI8 $x3, 13
+    renamable $x3 = PADDI8 $x3, 13
+    renamable $x3 = PADDI8 $x3, 13
+    renamable $x3 = PADDI8 $x3, 13
+    renamable $x3 = LI8 2
+
+    renamable $x3 = PADDI8 $x3, 13
+    BLR8 implicit $lr8, implicit $rm, implicit killed $x3
+...
+
+# DIS:      Disassembly of section .text:
+# DIS:      00000000 <.text>:
+# DIS-NEXT:   0: 38 60 00 02  	          li 3, 2
+# DIS-NEXT:   4: 06 00 00 00 38 63 00 0d  paddi 3, 3, 13, 0
+# DIS-NEXT:   c: 06 00 00 00 38 63 00 0d  paddi 3, 3, 13, 0
+# DIS-NEXT:  14: 06 00 00 00 38 63 00 0d  paddi 3, 3, 13, 0
+# DIS-NEXT:  1c: 06 00 00 00 38 63 00 0d  paddi 3, 3, 13, 0
+# DIS-NEXT:  24: 06 00 00 00 38 63 00 0d  paddi 3, 3, 13, 0
+# DIS-NEXT:  2c: 06 00 00 00 38 63 00 0d  paddi 3, 3, 13, 0
+# DIS-NEXT:  34: 06 00 00 00 38 63 00 0d  paddi 3, 3, 13, 0
+# DIS-NEXT:  3c: 60 00 00 00  	          nop
+# DIS-NEXT:  40: 06 00 00 00 38 63 00 0d  paddi 3, 3, 13, 0
+# DIS-NEXT:  48: 06 00 00 00 38 63 00 0d  paddi 3, 3, 13, 0
+# DIS-NEXT:  50: 06 00 00 00 38 63 00 0d  paddi 3, 3, 13, 0
+# DIS-NEXT:  58: 06 00 00 00 38 63 00 0d  paddi 3, 3, 13, 0
+# DIS-NEXT:  60: 06 00 00 00 38 63 00 0d  paddi 3, 3, 13, 0
+# DIS-NEXT:  68: 06 00 00 00 38 63 00 0d  paddi 3, 3, 13, 0
+# DIS-NEXT:  70: 06 00 00 00 38 63 00 0d  paddi 3, 3, 13, 0
+# DIS-NEXT:  78: 06 00 00 00 38 63 00 0d  paddi 3, 3, 13, 0
+# DIS-NEXT:  80: 06 00 00 00 38 63 00 0d  paddi 3, 3, 13, 0
+# DIS-NEXT:  88: 06 00 00 00 38 63 00 0d  paddi 3, 3, 13, 0
+# DIS-NEXT:  90: 06 00 00 00 38 63 00 0d  paddi 3, 3, 13, 0
+# DIS-NEXT:  98: 06 00 00 00 38 63 00 0d  paddi 3, 3, 13, 0
+# DIS-NEXT:  a0: 06 00 00 00 38 63 00 0d  paddi 3, 3, 13, 0
+# DIS-NEXT:  a8: 06 00 00 00 38 63 00 0d  paddi 3, 3, 13, 0
+# DIS-NEXT:  b0: 06 00 00 00 38 63 00 0d  paddi 3, 3, 13, 0
+# DIS-NEXT:  b8: 38 60 00 02  	          li 3, 2
+# DIS-NEXT:  bc: 60 00 00 00  	          nop
+# DIS-NEXT:  c0: 06 00 00 00 38 63 00 0d  paddi 3, 3, 13, 0
+# DIS-NEXT:  c8: 4e 80 00 20  	          blr


        


More information about the llvm-commits mailing list