mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-02 16:56:50 +00:00
Targets: commonize some stack realignment code
This patch does the following: * Fix FIXME on `needsStackRealignment`: it is now shared between multiple targets, implemented in `TargetRegisterInfo`, and isn't `virtual` anymore. This will break out-of-tree targets, silently if they used `virtual` and with a build error if they used `override`. * Factor out `canRealignStack` as a `virtual` function on `TargetRegisterInfo`, by default only looks for the `no-realign-stack` function attribute. Multiple targets duplicated the same `needsStackRealignment` code: - Aarch64. - ARM. - Mips almost: had extra `DEBUG` diagnostic, which the default implementation now has. - PowerPC. - WebAssembly. - x86 almost: has an extra `-force-align-stack` option, which the default implementation now has. The default implementation of `needsStackRealignment` used to just return `false`. My current patch changes the behavior by simply using the above shared behavior. This affects: - AMDGPU - BPF - CppBackend - MSP430 - NVPTX - Sparc - SystemZ - XCore - Out-of-tree targets This is a breaking change! `make check` passes. The only implementation of the `virtual` function (besides the slight different in x86) was Hexagon (which did `MF.getFrameInfo()->getMaxAlignment() > 8`), and potentially some out-of-tree targets. Hexagon now uses the default implementation. `needsStackRealignment` was being overwritten in `<Target>GenRegisterInfo.inc`, to return `false` as the default also did. That was odd and is now gone. Reviewers: sunfish Subscribers: aemerson, llvm-commits, jfb Differential Revision: http://reviews.llvm.org/D11160 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@242727 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
dfc9688bd9
commit
9994b911f4
@ -21,6 +21,7 @@
|
||||
#include "llvm/CodeGen/MachineValueType.h"
|
||||
#include "llvm/IR/CallingConv.h"
|
||||
#include "llvm/MC/MCRegisterInfo.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
|
||||
@ -34,6 +35,8 @@ class VirtRegMap;
|
||||
class raw_ostream;
|
||||
class LiveRegMatrix;
|
||||
|
||||
extern cl::opt<bool> ForceStackAlign;
|
||||
|
||||
class TargetRegisterClass {
|
||||
public:
|
||||
typedef const MCPhysReg* iterator;
|
||||
@ -784,12 +787,14 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
/// canRealignStack - true if the stack can be realigned for the target.
|
||||
virtual bool canRealignStack(const MachineFunction &MF) const;
|
||||
|
||||
/// needsStackRealignment - true if storage within the function requires the
|
||||
/// stack pointer to be aligned more than the normal calling convention calls
|
||||
/// for.
|
||||
virtual bool needsStackRealignment(const MachineFunction &MF) const {
|
||||
return false;
|
||||
}
|
||||
/// for. This cannot be overriden by the target, but canRealignStack can be
|
||||
/// overriden.
|
||||
bool needsStackRealignment(const MachineFunction &MF) const;
|
||||
|
||||
/// getFrameIndexInstrOffset - Get the offset from the referenced frame
|
||||
/// index in the instruction, if there is one.
|
||||
|
@ -11,13 +11,26 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/VirtRegMap.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/TargetFrameLowering.h"
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
|
||||
#define DEBUG_TYPE "target-reg-info"
|
||||
|
||||
namespace llvm {
|
||||
cl::opt<bool>
|
||||
ForceStackAlign("force-align-stack",
|
||||
cl::desc("Force align the stack to the minimum alignment"
|
||||
" needed for the function."),
|
||||
cl::init(false), cl::Hidden);
|
||||
} // end namespace llvm
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@ -296,6 +309,26 @@ TargetRegisterInfo::getRegAllocationHints(unsigned VirtReg,
|
||||
Hints.push_back(Phys);
|
||||
}
|
||||
|
||||
bool TargetRegisterInfo::canRealignStack(const MachineFunction &MF) const {
|
||||
return !MF.getFunction()->hasFnAttribute("no-realign-stack");
|
||||
}
|
||||
|
||||
bool TargetRegisterInfo::needsStackRealignment(
|
||||
const MachineFunction &MF) const {
|
||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
|
||||
const Function *F = MF.getFunction();
|
||||
unsigned StackAlign = TFI->getStackAlignment();
|
||||
bool requiresRealignment = ((MFI->getMaxAlignment() > StackAlign) ||
|
||||
F->hasFnAttribute(Attribute::StackAlignment));
|
||||
if (ForceStackAlign || requiresRealignment) {
|
||||
if (canRealignStack(MF))
|
||||
return true;
|
||||
DEBUG(dbgs() << "Can't realign function's stack: " << F->getName() << "\n");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
||||
void
|
||||
TargetRegisterInfo::dumpReg(unsigned Reg, unsigned SubRegIndex,
|
||||
|
@ -186,29 +186,6 @@ bool AArch64RegisterInfo::hasBasePointer(const MachineFunction &MF) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AArch64RegisterInfo::canRealignStack(const MachineFunction &MF) const {
|
||||
|
||||
if (MF.getFunction()->hasFnAttribute("no-realign-stack"))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// FIXME: share this with other backends with identical implementation?
|
||||
bool
|
||||
AArch64RegisterInfo::needsStackRealignment(const MachineFunction &MF) const {
|
||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
const AArch64FrameLowering *TFI = getFrameLowering(MF);
|
||||
const Function *F = MF.getFunction();
|
||||
unsigned StackAlign = TFI->getStackAlignment();
|
||||
bool requiresRealignment =
|
||||
((MFI->getMaxAlignment() > StackAlign) ||
|
||||
F->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
|
||||
Attribute::StackAlignment));
|
||||
|
||||
return requiresRealignment && canRealignStack(MF);
|
||||
}
|
||||
|
||||
unsigned
|
||||
AArch64RegisterInfo::getFrameRegister(const MachineFunction &MF) const {
|
||||
const AArch64FrameLowering *TFI = getFrameLowering(MF);
|
||||
|
@ -93,9 +93,6 @@ public:
|
||||
|
||||
unsigned getRegPressureLimit(const TargetRegisterClass *RC,
|
||||
MachineFunction &MF) const override;
|
||||
// Base pointer (stack realignment) support.
|
||||
bool canRealignStack(const MachineFunction &MF) const;
|
||||
bool needsStackRealignment(const MachineFunction &MF) const override;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -339,7 +339,7 @@ bool ARMBaseRegisterInfo::canRealignStack(const MachineFunction &MF) const {
|
||||
// 1. Dynamic stack realignment is explicitly disabled,
|
||||
// 2. This is a Thumb1 function (it's not useful, so we don't bother), or
|
||||
// 3. There are VLAs in the function and the base pointer is disabled.
|
||||
if (MF.getFunction()->hasFnAttribute("no-realign-stack"))
|
||||
if (!TargetRegisterInfo::canRealignStack(MF))
|
||||
return false;
|
||||
if (AFI->isThumb1OnlyFunction())
|
||||
return false;
|
||||
@ -356,18 +356,6 @@ bool ARMBaseRegisterInfo::canRealignStack(const MachineFunction &MF) const {
|
||||
return MRI->canReserveReg(BasePtr);
|
||||
}
|
||||
|
||||
bool ARMBaseRegisterInfo::
|
||||
needsStackRealignment(const MachineFunction &MF) const {
|
||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
const ARMFrameLowering *TFI = getFrameLowering(MF);
|
||||
const Function *F = MF.getFunction();
|
||||
unsigned StackAlign = TFI->getStackAlignment();
|
||||
bool requiresRealignment = ((MFI->getMaxAlignment() > StackAlign) ||
|
||||
F->hasFnAttribute(Attribute::StackAlignment));
|
||||
|
||||
return requiresRealignment && canRealignStack(MF);
|
||||
}
|
||||
|
||||
bool ARMBaseRegisterInfo::
|
||||
cannotEliminateFrame(const MachineFunction &MF) const {
|
||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
|
@ -134,8 +134,7 @@ public:
|
||||
|
||||
bool hasBasePointer(const MachineFunction &MF) const;
|
||||
|
||||
bool canRealignStack(const MachineFunction &MF) const;
|
||||
bool needsStackRealignment(const MachineFunction &MF) const override;
|
||||
bool canRealignStack(const MachineFunction &MF) const override;
|
||||
int64_t getFrameIndexInstrOffset(const MachineInstr *MI,
|
||||
int Idx) const override;
|
||||
bool needsFrameBaseReg(MachineInstr *MI, int64_t Offset) const override;
|
||||
|
@ -245,13 +245,6 @@ HexagonRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const {
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
HexagonRegisterInfo::needsStackRealignment(const MachineFunction &MF) const {
|
||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
return MFI->getMaxAlignment() > 8;
|
||||
}
|
||||
|
||||
|
||||
unsigned HexagonRegisterInfo::getFirstCallerSavedNonParamReg() const {
|
||||
return Hexagon::R6;
|
||||
}
|
||||
|
@ -63,8 +63,6 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool needsStackRealignment(const MachineFunction &MF) const override;
|
||||
|
||||
/// Returns true if the frame pointer is valid.
|
||||
bool useFPForScavengingIndex(const MachineFunction &MF) const override;
|
||||
|
||||
|
@ -284,6 +284,16 @@ getFrameRegister(const MachineFunction &MF) const {
|
||||
}
|
||||
|
||||
bool MipsRegisterInfo::canRealignStack(const MachineFunction &MF) const {
|
||||
// Avoid realigning functions that explicitly do not want to be realigned.
|
||||
// Normally, we should report an error when a function should be dynamically
|
||||
// realigned but also has the attribute no-realign-stack. Unfortunately,
|
||||
// with this attribute, MachineFrameInfo clamps each new object's alignment
|
||||
// to that of the stack's alignment as specified by the ABI. As a result,
|
||||
// the information of whether we have objects with larger alignment
|
||||
// requirement than the stack's alignment is already lost at this point.
|
||||
if (!TargetRegisterInfo::canRealignStack(MF))
|
||||
return false;
|
||||
|
||||
const MipsSubtarget &Subtarget = MF.getSubtarget<MipsSubtarget>();
|
||||
unsigned FP = Subtarget.isGP32bit() ? Mips::FP : Mips::FP_64;
|
||||
unsigned BP = Subtarget.isGP32bit() ? Mips::S7 : Mips::S7_64;
|
||||
@ -306,42 +316,3 @@ bool MipsRegisterInfo::canRealignStack(const MachineFunction &MF) const {
|
||||
// sized objects.
|
||||
return MF.getRegInfo().canReserveReg(BP);
|
||||
}
|
||||
|
||||
bool MipsRegisterInfo::needsStackRealignment(const MachineFunction &MF) const {
|
||||
const MipsSubtarget &Subtarget = MF.getSubtarget<MipsSubtarget>();
|
||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
|
||||
bool CanRealign = canRealignStack(MF);
|
||||
|
||||
// Avoid realigning functions that explicitly do not want to be realigned.
|
||||
// Normally, we should report an error when a function should be dynamically
|
||||
// realigned but also has the attribute no-realign-stack. Unfortunately,
|
||||
// with this attribute, MachineFrameInfo clamps each new object's alignment
|
||||
// to that of the stack's alignment as specified by the ABI. As a result,
|
||||
// the information of whether we have objects with larger alignment
|
||||
// requirement than the stack's alignment is already lost at this point.
|
||||
if (MF.getFunction()->hasFnAttribute("no-realign-stack"))
|
||||
return false;
|
||||
|
||||
const Function *F = MF.getFunction();
|
||||
if (F->hasFnAttribute(Attribute::StackAlignment)) {
|
||||
#ifdef DEBUG
|
||||
if (!CanRealign)
|
||||
DEBUG(dbgs() << "It's not possible to realign the stack of the function: "
|
||||
<< F->getName() << "\n");
|
||||
#endif
|
||||
return CanRealign;
|
||||
}
|
||||
|
||||
unsigned StackAlignment = Subtarget.getFrameLowering()->getStackAlignment();
|
||||
if (MFI->getMaxAlignment() > StackAlignment) {
|
||||
#ifdef DEBUG
|
||||
if (!CanRealign)
|
||||
DEBUG(dbgs() << "It's not possible to realign the stack of the function: "
|
||||
<< F->getName() << "\n");
|
||||
#endif
|
||||
return CanRealign;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -61,9 +61,7 @@ public:
|
||||
RegScavenger *RS = nullptr) const;
|
||||
|
||||
// Stack realignment queries.
|
||||
bool canRealignStack(const MachineFunction &MF) const;
|
||||
|
||||
bool needsStackRealignment(const MachineFunction &MF) const override;
|
||||
bool canRealignStack(const MachineFunction &MF) const override;
|
||||
|
||||
/// Debug information queries.
|
||||
unsigned getFrameRegister(const MachineFunction &MF) const override;
|
||||
|
@ -898,24 +898,6 @@ bool PPCRegisterInfo::hasBasePointer(const MachineFunction &MF) const {
|
||||
return needsStackRealignment(MF);
|
||||
}
|
||||
|
||||
bool PPCRegisterInfo::canRealignStack(const MachineFunction &MF) const {
|
||||
if (MF.getFunction()->hasFnAttribute("no-realign-stack"))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PPCRegisterInfo::needsStackRealignment(const MachineFunction &MF) const {
|
||||
const PPCFrameLowering *TFI = getFrameLowering(MF);
|
||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
const Function *F = MF.getFunction();
|
||||
unsigned StackAlign = TFI->getStackAlignment();
|
||||
bool requiresRealignment = ((MFI->getMaxAlignment() > StackAlign) ||
|
||||
F->hasFnAttribute(Attribute::StackAlignment));
|
||||
|
||||
return requiresRealignment && canRealignStack(MF);
|
||||
}
|
||||
|
||||
/// Returns true if the instruction's frame index
|
||||
/// reference would be better served by a base register other than FP
|
||||
/// or SP. Used by LocalStackFrameAllocation to determine which frame index
|
||||
|
@ -136,8 +136,6 @@ public:
|
||||
// Base pointer (stack realignment) support.
|
||||
unsigned getBaseRegister(const MachineFunction &MF) const;
|
||||
bool hasBasePointer(const MachineFunction &MF) const;
|
||||
bool canRealignStack(const MachineFunction &MF) const;
|
||||
bool needsStackRealignment(const MachineFunction &MF) const override;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -66,22 +66,3 @@ WebAssemblyRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
|
||||
const WebAssemblyFrameLowering *TFI = getFrameLowering(MF);
|
||||
return Regs[TFI->hasFP(MF)][TT.isArch64Bit()];
|
||||
}
|
||||
|
||||
bool WebAssemblyRegisterInfo::canRealignStack(const MachineFunction &MF) const {
|
||||
return !MF.getFunction()->hasFnAttribute("no-realign-stack");
|
||||
}
|
||||
|
||||
// FIXME: share this with other backends with identical implementation?
|
||||
bool WebAssemblyRegisterInfo::needsStackRealignment(
|
||||
const MachineFunction &MF) const {
|
||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
const WebAssemblyFrameLowering *TFI = getFrameLowering(MF);
|
||||
const Function *F = MF.getFunction();
|
||||
unsigned StackAlign = TFI->getStackAlignment();
|
||||
bool requiresRealignment =
|
||||
((MFI->getMaxAlignment() > StackAlign) ||
|
||||
F->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
|
||||
Attribute::StackAlignment));
|
||||
|
||||
return requiresRealignment && canRealignStack(MF);
|
||||
}
|
||||
|
@ -41,10 +41,6 @@ public:
|
||||
|
||||
// Debug information queries.
|
||||
unsigned getFrameRegister(const MachineFunction &MF) const override;
|
||||
|
||||
// Base pointer (stack realignment) support.
|
||||
bool canRealignStack(const MachineFunction &MF) const;
|
||||
bool needsStackRealignment(const MachineFunction &MF) const override;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -27,16 +27,12 @@
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include <cstdlib>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
// FIXME: completely move here.
|
||||
extern cl::opt<bool> ForceStackAlign;
|
||||
|
||||
X86FrameLowering::X86FrameLowering(const X86Subtarget &STI,
|
||||
unsigned StackAlignOverride)
|
||||
: TargetFrameLowering(StackGrowsDown, StackAlignOverride,
|
||||
|
@ -44,12 +44,6 @@ using namespace llvm;
|
||||
#define GET_REGINFO_TARGET_DESC
|
||||
#include "X86GenRegisterInfo.inc"
|
||||
|
||||
cl::opt<bool>
|
||||
ForceStackAlign("force-align-stack",
|
||||
cl::desc("Force align the stack to the minimum alignment"
|
||||
" needed for the function."),
|
||||
cl::init(false), cl::Hidden);
|
||||
|
||||
static cl::opt<bool>
|
||||
EnableBasePointer("x86-use-base-pointer", cl::Hidden, cl::init(true),
|
||||
cl::desc("Enable use of a base pointer for complex stack frames"));
|
||||
@ -457,7 +451,7 @@ bool X86RegisterInfo::hasBasePointer(const MachineFunction &MF) const {
|
||||
}
|
||||
|
||||
bool X86RegisterInfo::canRealignStack(const MachineFunction &MF) const {
|
||||
if (MF.getFunction()->hasFnAttribute("no-realign-stack"))
|
||||
if (!TargetRegisterInfo::canRealignStack(MF))
|
||||
return false;
|
||||
|
||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
@ -475,21 +469,6 @@ bool X86RegisterInfo::canRealignStack(const MachineFunction &MF) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool X86RegisterInfo::needsStackRealignment(const MachineFunction &MF) const {
|
||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
const X86FrameLowering *TFI = getFrameLowering(MF);
|
||||
const Function *F = MF.getFunction();
|
||||
unsigned StackAlign = TFI->getStackAlignment();
|
||||
bool requiresRealignment = ((MFI->getMaxAlignment() > StackAlign) ||
|
||||
F->hasFnAttribute(Attribute::StackAlignment));
|
||||
|
||||
// If we've requested that we force align the stack do so now.
|
||||
if (ForceStackAlign)
|
||||
return canRealignStack(MF);
|
||||
|
||||
return requiresRealignment && canRealignStack(MF);
|
||||
}
|
||||
|
||||
bool X86RegisterInfo::hasReservedSpillSlot(const MachineFunction &MF,
|
||||
unsigned Reg, int &FrameIdx) const {
|
||||
// Since X86 defines assignCalleeSavedSpillSlots which always return true
|
||||
|
@ -108,9 +108,7 @@ public:
|
||||
|
||||
bool hasBasePointer(const MachineFunction &MF) const;
|
||||
|
||||
bool canRealignStack(const MachineFunction &MF) const;
|
||||
|
||||
bool needsStackRealignment(const MachineFunction &MF) const override;
|
||||
bool canRealignStack(const MachineFunction &MF) const override;
|
||||
|
||||
bool hasReservedSpillSlot(const MachineFunction &MF, unsigned Reg,
|
||||
int &FrameIdx) const override;
|
||||
|
27
test/CodeGen/Generic/ForceStackAlign.ll
Normal file
27
test/CodeGen/Generic/ForceStackAlign.ll
Normal file
@ -0,0 +1,27 @@
|
||||
; Check that stack alignment can be forced. Individual targets should test their
|
||||
; specific implementation details.
|
||||
|
||||
; RUN: llc < %s -force-align-stack -stack-alignment=32 | FileCheck %s
|
||||
; CHECK-LABEL: @f
|
||||
; CHECK-LABEL: @g
|
||||
|
||||
define i32 @f(i8* %p) nounwind {
|
||||
entry:
|
||||
%0 = load i8, i8* %p
|
||||
%conv = sext i8 %0 to i32
|
||||
ret i32 %conv
|
||||
}
|
||||
|
||||
define i64 @g(i32 %i) nounwind {
|
||||
entry:
|
||||
br label %if.then
|
||||
|
||||
if.then:
|
||||
%0 = alloca i8, i32 %i
|
||||
call void @llvm.memset.p0i8.i32(i8* %0, i8 0, i32 %i, i32 1, i1 false)
|
||||
%call = call i32 @f(i8* %0)
|
||||
%conv = sext i32 %call to i64
|
||||
ret i64 %conv
|
||||
}
|
||||
|
||||
declare void @llvm.memset.p0i8.i32(i8*, i8, i32, i32, i1) nounwind
|
@ -1074,9 +1074,7 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
|
||||
|
||||
OS << "struct " << ClassName << " : public TargetRegisterInfo {\n"
|
||||
<< " explicit " << ClassName
|
||||
<< "(unsigned RA, unsigned D = 0, unsigned E = 0, unsigned PC = 0);\n"
|
||||
<< " bool needsStackRealignment(const MachineFunction &) const override\n"
|
||||
<< " { return false; }\n";
|
||||
<< "(unsigned RA, unsigned D = 0, unsigned E = 0, unsigned PC = 0);\n";
|
||||
if (!RegBank.getSubRegIndices().empty()) {
|
||||
OS << " unsigned composeSubRegIndicesImpl"
|
||||
<< "(unsigned, unsigned) const override;\n"
|
||||
|
Loading…
Reference in New Issue
Block a user