diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp index b4c5afc5c1a4..214b9291167e 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -27,6 +27,7 @@ #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SlotIndexes.h" +#include "llvm/CodeGen/StackMaps.h" #include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/MC/MCInstrDesc.h" @@ -1515,6 +1516,13 @@ unsigned SystemZInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { const char *AsmStr = MI.getOperand(0).getSymbolName(); return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo()); } + else if (MI.getOpcode() == SystemZ::PATCHPOINT) + return PatchPointOpers(&MI).getNumPatchBytes(); + else if (MI.getOpcode() == SystemZ::STACKMAP) + return MI.getOperand(1).getImm(); + else if (MI.getOpcode() == SystemZ::FENTRY_CALL) + return 6; + return MI.getDesc().getSize(); } diff --git a/llvm/lib/Target/SystemZ/SystemZLongBranch.cpp b/llvm/lib/Target/SystemZ/SystemZLongBranch.cpp index b1964321c78a..9c985c16f082 100644 --- a/llvm/lib/Target/SystemZ/SystemZLongBranch.cpp +++ b/llvm/lib/Target/SystemZ/SystemZLongBranch.cpp @@ -209,10 +209,24 @@ void SystemZLongBranch::skipTerminator(BlockPosition &Position, Position.Address += Terminator.ExtraRelaxSize; } +static unsigned getInstSizeInBytes(const MachineInstr &MI, + const SystemZInstrInfo *TII) { + unsigned Size = TII->getInstSizeInBytes(MI); + assert((Size || + // These do not have a size: + MI.isDebugOrPseudoInstr() || MI.isPosition() || MI.isKill() || + MI.isImplicitDef() || MI.getOpcode() == SystemZ::MemBarrier || + // These have a size that may be zero: + MI.isInlineAsm() || MI.getOpcode() == SystemZ::STACKMAP || + MI.getOpcode() == SystemZ::PATCHPOINT) && + "Missing size value for instruction."); + return Size; +} + // Return a description of terminator instruction MI. TerminatorInfo SystemZLongBranch::describeTerminator(MachineInstr &MI) { TerminatorInfo Terminator; - Terminator.Size = TII->getInstSizeInBytes(MI); + Terminator.Size = getInstSizeInBytes(MI, TII); if (MI.isConditionalBranch() || MI.isUnconditionalBranch()) { switch (MI.getOpcode()) { case SystemZ::J: @@ -287,7 +301,7 @@ uint64_t SystemZLongBranch::initMBBInfo() { MachineBasicBlock::iterator MI = MBB->begin(); MachineBasicBlock::iterator End = MBB->end(); while (MI != End && !MI->isTerminator()) { - Block.Size += TII->getInstSizeInBytes(*MI); + Block.Size += getInstSizeInBytes(*MI, TII); ++MI; } skipNonTerminators(Position, Block); diff --git a/llvm/test/CodeGen/SystemZ/patchpoint.ll b/llvm/test/CodeGen/SystemZ/patchpoint.ll index bd67bdf12814..ef98190a2af0 100644 --- a/llvm/test/CodeGen/SystemZ/patchpoint.ll +++ b/llvm/test/CodeGen/SystemZ/patchpoint.ll @@ -97,6 +97,59 @@ entry: ret i64 %result } +; Test that the number of bytes is reflected in the instruction size and +; therefore cause relaxation of the initial branch. +define void @patchpoint_size(i32 %Arg) { +; CHECK-LABEL: patchpoint_size: +; CHECK: # %bb.0: +; CHECK-NEXT: stmg %r14, %r15, 112(%r15) +; CHECK-NEXT: .cfi_offset %r14, -48 +; CHECK-NEXT: .cfi_offset %r15, -40 +; CHECK-NEXT: aghi %r15, -160 +; CHECK-NEXT: .cfi_def_cfa_offset 320 +; CHECK-NEXT: chi %r2, 0 +; CHECK-NEXT: jge .LBB6_2 + %c = icmp eq i32 %Arg, 0 + br i1 %c, label %block0, label %patch1 + +block0: + call i64 @foo(i64 0, i64 0) + br label %exit + +patch1: + call void (i64, i32, i8*, i32, ...) @llvm.experimental.patchpoint.void(i64 0, i32 65536, i8* null, i32 0) + br label %exit + +exit: + ret void +} + +define void @stackmap_size(i32 %Arg) { +; CHECK-LABEL: stackmap_size: +; CHECK: # %bb.0: +; CHECK-NEXT: stmg %r14, %r15, 112(%r15) +; CHECK-NEXT: .cfi_offset %r14, -48 +; CHECK-NEXT: .cfi_offset %r15, -40 +; CHECK-NEXT: aghi %r15, -160 +; CHECK-NEXT: .cfi_def_cfa_offset 320 +; CHECK-NEXT: chi %r2, 0 +; CHECK-NEXT: jge .LBB7_2 + %c = icmp eq i32 %Arg, 0 + br i1 %c, label %block0, label %stackmap1 + +block0: + call i64 @foo(i64 0, i64 0) + br label %exit + +stackmap1: + call void (i64, i32, ...) @llvm.experimental.stackmap(i64 1, i32 65536) + br label %exit + +exit: + ret void +} + + declare void @llvm.experimental.stackmap(i64, i32, ...) declare void @llvm.experimental.patchpoint.void(i64, i32, i8*, i32, ...) declare i64 @llvm.experimental.patchpoint.i64(i64, i32, i8*, i32, ...)