Skip to content

Commit

Permalink
[SystemZ] Emit EXRL target instructions before text section is ended.
Browse files Browse the repository at this point in the history
SystemZ adds the EXRL target instructions in the end of each file. This must
be done before debug info emission since that may end the text section, and
therefore this is now done in emitConstantPools() (instead of in
emitEndOfAsmFile).

Review: Ulrich Weigand

Differential Revision: https://reviews.llvm.org/D109513
  • Loading branch information
JonPsson committed Sep 21, 2021
1 parent ea27dd7 commit a48b43f
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 45 deletions.
16 changes: 16 additions & 0 deletions llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "SystemZMCAsmInfo.h"
#include "SystemZTargetStreamer.h"
#include "TargetInfo/SystemZTargetInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
Expand Down Expand Up @@ -183,6 +184,21 @@ static MCInstPrinter *createSystemZMCInstPrinter(const Triple &T,
return new SystemZInstPrinter(MAI, MII, MRI);
}

void SystemZTargetStreamer::emitConstantPools() {
// Emit EXRL target instructions.
if (EXRLTargets2Sym.empty())
return;
// Switch to the .text section.
const MCObjectFileInfo &OFI = *Streamer.getContext().getObjectFileInfo();
Streamer.SwitchSection(OFI.getTextSection());
for (auto &I : EXRLTargets2Sym) {
Streamer.emitLabel(I.second);
const MCInstSTIPair &MCI_STI = I.first;
Streamer.emitInstruction(MCI_STI.first, *MCI_STI.second);
}
EXRLTargets2Sym.clear();
}

namespace {
class SystemZTargetAsmStreamer : public SystemZTargetStreamer {
formatted_raw_ostream &OS;
Expand Down
24 changes: 6 additions & 18 deletions llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -549,15 +549,17 @@ void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
Register SrcReg = MI->getOperand(4).getReg();
int64_t SrcDisp = MI->getOperand(5).getImm();

SystemZTargetStreamer *TS = getTargetStreamer();
MCSymbol *DotSym = nullptr;
MCInst ET = MCInstBuilder(TargetInsOpc).addReg(DestReg)
.addImm(DestDisp).addImm(1).addReg(SrcReg).addImm(SrcDisp);
MCInstSTIPair ET_STI(ET, &MF->getSubtarget());
EXRLT2SymMap::iterator I = EXRLTargets2Sym.find(ET_STI);
if (I != EXRLTargets2Sym.end())
SystemZTargetStreamer::MCInstSTIPair ET_STI(ET, &MF->getSubtarget());
SystemZTargetStreamer::EXRLT2SymMap::iterator I =
TS->EXRLTargets2Sym.find(ET_STI);
if (I != TS->EXRLTargets2Sym.end())
DotSym = I->second;
else
EXRLTargets2Sym[ET_STI] = DotSym = OutContext.createTempSymbol();
TS->EXRLTargets2Sym[ET_STI] = DotSym = OutContext.createTempSymbol();
const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
EmitToStreamer(
*OutStreamer,
Expand Down Expand Up @@ -722,19 +724,6 @@ void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
getSubtargetInfo());
}

void SystemZAsmPrinter::emitEXRLTargetInstructions() {
if (EXRLTargets2Sym.empty())
return;
// Switch to the .text section.
OutStreamer->SwitchSection(getObjFileLowering().getTextSection());
for (auto &I : EXRLTargets2Sym) {
OutStreamer->emitLabel(I.second);
const MCInstSTIPair &MCI_STI = I.first;
OutStreamer->emitInstruction(MCI_STI.first, *MCI_STI.second);
}
EXRLTargets2Sym.clear();
}

// Convert a SystemZ-specific constant pool modifier into the associated
// MCSymbolRefExpr variant kind.
static MCSymbolRefExpr::VariantKind
Expand Down Expand Up @@ -793,7 +782,6 @@ bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
}

void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
emitEXRLTargetInstructions();
emitStackMaps(SM);
}

Expand Down
33 changes: 6 additions & 27 deletions llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "SystemZMCInstLower.h"
#include "SystemZTargetMachine.h"
#include "SystemZTargetStreamer.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/StackMaps.h"
#include "llvm/MC/MCInstBuilder.h"
Expand All @@ -27,32 +28,11 @@ class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
private:
StackMaps SM;

typedef std::pair<MCInst, const MCSubtargetInfo *> MCInstSTIPair;
struct CmpMCInst {
bool operator()(const MCInstSTIPair &MCI_STI_A,
const MCInstSTIPair &MCI_STI_B) const {
if (MCI_STI_A.second != MCI_STI_B.second)
return uintptr_t(MCI_STI_A.second) < uintptr_t(MCI_STI_B.second);
const MCInst &A = MCI_STI_A.first;
const MCInst &B = MCI_STI_B.first;
assert(A.getNumOperands() == B.getNumOperands() &&
A.getNumOperands() == 5 && A.getOperand(2).getImm() == 1 &&
B.getOperand(2).getImm() == 1 && "Unexpected EXRL target MCInst");
if (A.getOpcode() != B.getOpcode())
return A.getOpcode() < B.getOpcode();
if (A.getOperand(0).getReg() != B.getOperand(0).getReg())
return A.getOperand(0).getReg() < B.getOperand(0).getReg();
if (A.getOperand(1).getImm() != B.getOperand(1).getImm())
return A.getOperand(1).getImm() < B.getOperand(1).getImm();
if (A.getOperand(3).getReg() != B.getOperand(3).getReg())
return A.getOperand(3).getReg() < B.getOperand(3).getReg();
if (A.getOperand(4).getImm() != B.getOperand(4).getImm())
return A.getOperand(4).getImm() < B.getOperand(4).getImm();
return false;
}
};
typedef std::map<MCInstSTIPair, MCSymbol *, CmpMCInst> EXRLT2SymMap;
EXRLT2SymMap EXRLTargets2Sym;
SystemZTargetStreamer *getTargetStreamer() {
MCTargetStreamer *TS = OutStreamer->getTargetStreamer();
assert(TS && "do not have a target streamer");
return static_cast<SystemZTargetStreamer *>(TS);
}

public:
SystemZAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
Expand All @@ -77,7 +57,6 @@ class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
void LowerFENTRY_CALL(const MachineInstr &MI, SystemZMCInstLower &MCIL);
void LowerSTACKMAP(const MachineInstr &MI);
void LowerPATCHPOINT(const MachineInstr &MI, SystemZMCInstLower &Lower);
void emitEXRLTargetInstructions();
};
} // end namespace llvm

Expand Down
29 changes: 29 additions & 0 deletions llvm/lib/Target/SystemZ/SystemZTargetStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,35 @@ class SystemZTargetStreamer : public MCTargetStreamer {
public:
SystemZTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}

typedef std::pair<MCInst, const MCSubtargetInfo *> MCInstSTIPair;
struct CmpMCInst {
bool operator()(const MCInstSTIPair &MCI_STI_A,
const MCInstSTIPair &MCI_STI_B) const {
if (MCI_STI_A.second != MCI_STI_B.second)
return uintptr_t(MCI_STI_A.second) < uintptr_t(MCI_STI_B.second);
const MCInst &A = MCI_STI_A.first;
const MCInst &B = MCI_STI_B.first;
assert(A.getNumOperands() == B.getNumOperands() &&
A.getNumOperands() == 5 && A.getOperand(2).getImm() == 1 &&
B.getOperand(2).getImm() == 1 && "Unexpected EXRL target MCInst");
if (A.getOpcode() != B.getOpcode())
return A.getOpcode() < B.getOpcode();
if (A.getOperand(0).getReg() != B.getOperand(0).getReg())
return A.getOperand(0).getReg() < B.getOperand(0).getReg();
if (A.getOperand(1).getImm() != B.getOperand(1).getImm())
return A.getOperand(1).getImm() < B.getOperand(1).getImm();
if (A.getOperand(3).getReg() != B.getOperand(3).getReg())
return A.getOperand(3).getReg() < B.getOperand(3).getReg();
if (A.getOperand(4).getImm() != B.getOperand(4).getImm())
return A.getOperand(4).getImm() < B.getOperand(4).getImm();
return false;
}
};
typedef std::map<MCInstSTIPair, MCSymbol *, CmpMCInst> EXRLT2SymMap;
EXRLT2SymMap EXRLTargets2Sym;

void emitConstantPools() override;

virtual void emitMachine(StringRef CPU) = 0;
};

Expand Down
46 changes: 46 additions & 0 deletions llvm/test/CodeGen/SystemZ/memset-06.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
; RUN: llc < %s -mtriple=s390x-linux-gnu -generate-arange-section
;
; Test that the EXRL target instruction is emitted successfully (before text
; section is closed).

@a = dso_local global i32* null, align 8, !dbg !0
@j = dso_local global i32 0, align 4, !dbg !5

define void @fun() !dbg !14 {
entry:
%0 = load i32*, i32** @a, align 8, !dbg !18
%1 = bitcast i32* %0 to i8*, !dbg !19
%2 = load i32, i32* @j, align 4, !dbg !20
%conv = sext i32 %2 to i64, !dbg !20
call void @llvm.memset.p0i8.i64(i8* align 4 %1, i8 0, i64 %conv, i1 false), !dbg !19
ret void, !dbg !21
}

declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg) #1

!llvm.dbg.cu = !{!2}
!llvm.module.flags = !{!9, !10, !11, !12}
!llvm.ident = !{!13}

!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 1, type: !8, isLocal: false, isDefinition: true)
!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None)
!3 = !DIFile(filename: "file.c", directory: "")
!4 = !{!0, !5}
!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression())
!6 = distinct !DIGlobalVariable(name: "j", scope: !2, file: !3, line: 2, type: !7, isLocal: false, isDefinition: true)
!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64)
!9 = !{i32 7, !"Dwarf Version", i32 4}
!10 = !{i32 2, !"Debug Info Version", i32 3}
!11 = !{i32 1, !"wchar_size", i32 4}
!12 = !{i32 7, !"frame-pointer", i32 2}
!13 = !{!"clang version 14.0.0"}
!14 = distinct !DISubprogram(name: "fun", scope: !3, file: !3, line: 3, type: !15, scopeLine: 3, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !17)
!15 = !DISubroutineType(types: !16)
!16 = !{null}
!17 = !{}
!18 = !DILocation(line: 4, column: 11, scope: !14)
!19 = !DILocation(line: 4, column: 4, scope: !14)
!20 = !DILocation(line: 4, column: 15, scope: !14)
!21 = !DILocation(line: 5, column: 1, scope: !14)

0 comments on commit a48b43f

Please sign in to comment.