[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