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:
JF Bastien 2015-07-20 22:51:32 +00:00
parent dfc9688bd9
commit 9994b911f4
19 changed files with 86 additions and 172 deletions

View File

@ -21,6 +21,7 @@
#include "llvm/CodeGen/MachineValueType.h" #include "llvm/CodeGen/MachineValueType.h"
#include "llvm/IR/CallingConv.h" #include "llvm/IR/CallingConv.h"
#include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Support/CommandLine.h"
#include <cassert> #include <cassert>
#include <functional> #include <functional>
@ -34,6 +35,8 @@ class VirtRegMap;
class raw_ostream; class raw_ostream;
class LiveRegMatrix; class LiveRegMatrix;
extern cl::opt<bool> ForceStackAlign;
class TargetRegisterClass { class TargetRegisterClass {
public: public:
typedef const MCPhysReg* iterator; typedef const MCPhysReg* iterator;
@ -784,12 +787,14 @@ public:
return false; 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 /// needsStackRealignment - true if storage within the function requires the
/// stack pointer to be aligned more than the normal calling convention calls /// stack pointer to be aligned more than the normal calling convention calls
/// for. /// for. This cannot be overriden by the target, but canRealignStack can be
virtual bool needsStackRealignment(const MachineFunction &MF) const { /// overriden.
return false; bool needsStackRealignment(const MachineFunction &MF) const;
}
/// getFrameIndexInstrOffset - Get the offset from the referenced frame /// getFrameIndexInstrOffset - Get the offset from the referenced frame
/// index in the instruction, if there is one. /// index in the instruction, if there is one.

View File

@ -11,13 +11,26 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/ADT/BitVector.h" #include "llvm/ADT/BitVector.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/VirtRegMap.h" #include "llvm/CodeGen/VirtRegMap.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.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; using namespace llvm;
@ -296,6 +309,26 @@ TargetRegisterInfo::getRegAllocationHints(unsigned VirtReg,
Hints.push_back(Phys); 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) #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void void
TargetRegisterInfo::dumpReg(unsigned Reg, unsigned SubRegIndex, TargetRegisterInfo::dumpReg(unsigned Reg, unsigned SubRegIndex,

View File

@ -186,29 +186,6 @@ bool AArch64RegisterInfo::hasBasePointer(const MachineFunction &MF) const {
return false; 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 unsigned
AArch64RegisterInfo::getFrameRegister(const MachineFunction &MF) const { AArch64RegisterInfo::getFrameRegister(const MachineFunction &MF) const {
const AArch64FrameLowering *TFI = getFrameLowering(MF); const AArch64FrameLowering *TFI = getFrameLowering(MF);

View File

@ -93,9 +93,6 @@ public:
unsigned getRegPressureLimit(const TargetRegisterClass *RC, unsigned getRegPressureLimit(const TargetRegisterClass *RC,
MachineFunction &MF) const override; 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 } // end namespace llvm

View File

@ -339,7 +339,7 @@ bool ARMBaseRegisterInfo::canRealignStack(const MachineFunction &MF) const {
// 1. Dynamic stack realignment is explicitly disabled, // 1. Dynamic stack realignment is explicitly disabled,
// 2. This is a Thumb1 function (it's not useful, so we don't bother), or // 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. // 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; return false;
if (AFI->isThumb1OnlyFunction()) if (AFI->isThumb1OnlyFunction())
return false; return false;
@ -356,18 +356,6 @@ bool ARMBaseRegisterInfo::canRealignStack(const MachineFunction &MF) const {
return MRI->canReserveReg(BasePtr); 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:: bool ARMBaseRegisterInfo::
cannotEliminateFrame(const MachineFunction &MF) const { cannotEliminateFrame(const MachineFunction &MF) const {
const MachineFrameInfo *MFI = MF.getFrameInfo(); const MachineFrameInfo *MFI = MF.getFrameInfo();

View File

@ -134,8 +134,7 @@ public:
bool hasBasePointer(const MachineFunction &MF) const; bool hasBasePointer(const MachineFunction &MF) const;
bool canRealignStack(const MachineFunction &MF) const; bool canRealignStack(const MachineFunction &MF) const override;
bool needsStackRealignment(const MachineFunction &MF) const override;
int64_t getFrameIndexInstrOffset(const MachineInstr *MI, int64_t getFrameIndexInstrOffset(const MachineInstr *MI,
int Idx) const override; int Idx) const override;
bool needsFrameBaseReg(MachineInstr *MI, int64_t Offset) const override; bool needsFrameBaseReg(MachineInstr *MI, int64_t Offset) const override;

View File

@ -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 { unsigned HexagonRegisterInfo::getFirstCallerSavedNonParamReg() const {
return Hexagon::R6; return Hexagon::R6;
} }

View File

@ -63,8 +63,6 @@ public:
return true; return true;
} }
bool needsStackRealignment(const MachineFunction &MF) const override;
/// Returns true if the frame pointer is valid. /// Returns true if the frame pointer is valid.
bool useFPForScavengingIndex(const MachineFunction &MF) const override; bool useFPForScavengingIndex(const MachineFunction &MF) const override;

View File

@ -284,6 +284,16 @@ getFrameRegister(const MachineFunction &MF) const {
} }
bool MipsRegisterInfo::canRealignStack(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>(); const MipsSubtarget &Subtarget = MF.getSubtarget<MipsSubtarget>();
unsigned FP = Subtarget.isGP32bit() ? Mips::FP : Mips::FP_64; unsigned FP = Subtarget.isGP32bit() ? Mips::FP : Mips::FP_64;
unsigned BP = Subtarget.isGP32bit() ? Mips::S7 : Mips::S7_64; unsigned BP = Subtarget.isGP32bit() ? Mips::S7 : Mips::S7_64;
@ -306,42 +316,3 @@ bool MipsRegisterInfo::canRealignStack(const MachineFunction &MF) const {
// sized objects. // sized objects.
return MF.getRegInfo().canReserveReg(BP); 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;
}

View File

@ -61,9 +61,7 @@ public:
RegScavenger *RS = nullptr) const; RegScavenger *RS = nullptr) const;
// Stack realignment queries. // Stack realignment queries.
bool canRealignStack(const MachineFunction &MF) const; bool canRealignStack(const MachineFunction &MF) const override;
bool needsStackRealignment(const MachineFunction &MF) const override;
/// Debug information queries. /// Debug information queries.
unsigned getFrameRegister(const MachineFunction &MF) const override; unsigned getFrameRegister(const MachineFunction &MF) const override;

View File

@ -898,24 +898,6 @@ bool PPCRegisterInfo::hasBasePointer(const MachineFunction &MF) const {
return needsStackRealignment(MF); 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 /// Returns true if the instruction's frame index
/// reference would be better served by a base register other than FP /// reference would be better served by a base register other than FP
/// or SP. Used by LocalStackFrameAllocation to determine which frame index /// or SP. Used by LocalStackFrameAllocation to determine which frame index

View File

@ -136,8 +136,6 @@ public:
// Base pointer (stack realignment) support. // Base pointer (stack realignment) support.
unsigned getBaseRegister(const MachineFunction &MF) const; unsigned getBaseRegister(const MachineFunction &MF) const;
bool hasBasePointer(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 } // end namespace llvm

View File

@ -66,22 +66,3 @@ WebAssemblyRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
const WebAssemblyFrameLowering *TFI = getFrameLowering(MF); const WebAssemblyFrameLowering *TFI = getFrameLowering(MF);
return Regs[TFI->hasFP(MF)][TT.isArch64Bit()]; 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);
}

View File

@ -41,10 +41,6 @@ public:
// Debug information queries. // Debug information queries.
unsigned getFrameRegister(const MachineFunction &MF) const override; 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 } // end namespace llvm

View File

@ -27,16 +27,12 @@
#include "llvm/IR/Function.h" #include "llvm/IR/Function.h"
#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSymbol.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetOptions.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include <cstdlib> #include <cstdlib>
using namespace llvm; using namespace llvm;
// FIXME: completely move here.
extern cl::opt<bool> ForceStackAlign;
X86FrameLowering::X86FrameLowering(const X86Subtarget &STI, X86FrameLowering::X86FrameLowering(const X86Subtarget &STI,
unsigned StackAlignOverride) unsigned StackAlignOverride)
: TargetFrameLowering(StackGrowsDown, StackAlignOverride, : TargetFrameLowering(StackGrowsDown, StackAlignOverride,

View File

@ -44,12 +44,6 @@ using namespace llvm;
#define GET_REGINFO_TARGET_DESC #define GET_REGINFO_TARGET_DESC
#include "X86GenRegisterInfo.inc" #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> static cl::opt<bool>
EnableBasePointer("x86-use-base-pointer", cl::Hidden, cl::init(true), EnableBasePointer("x86-use-base-pointer", cl::Hidden, cl::init(true),
cl::desc("Enable use of a base pointer for complex stack frames")); 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 { bool X86RegisterInfo::canRealignStack(const MachineFunction &MF) const {
if (MF.getFunction()->hasFnAttribute("no-realign-stack")) if (!TargetRegisterInfo::canRealignStack(MF))
return false; return false;
const MachineFrameInfo *MFI = MF.getFrameInfo(); const MachineFrameInfo *MFI = MF.getFrameInfo();
@ -475,21 +469,6 @@ bool X86RegisterInfo::canRealignStack(const MachineFunction &MF) const {
return true; 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, bool X86RegisterInfo::hasReservedSpillSlot(const MachineFunction &MF,
unsigned Reg, int &FrameIdx) const { unsigned Reg, int &FrameIdx) const {
// Since X86 defines assignCalleeSavedSpillSlots which always return true // Since X86 defines assignCalleeSavedSpillSlots which always return true

View File

@ -108,9 +108,7 @@ public:
bool hasBasePointer(const MachineFunction &MF) const; bool hasBasePointer(const MachineFunction &MF) const;
bool canRealignStack(const MachineFunction &MF) const; bool canRealignStack(const MachineFunction &MF) const override;
bool needsStackRealignment(const MachineFunction &MF) const override;
bool hasReservedSpillSlot(const MachineFunction &MF, unsigned Reg, bool hasReservedSpillSlot(const MachineFunction &MF, unsigned Reg,
int &FrameIdx) const override; int &FrameIdx) const override;

View 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

View File

@ -1074,9 +1074,7 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
OS << "struct " << ClassName << " : public TargetRegisterInfo {\n" OS << "struct " << ClassName << " : public TargetRegisterInfo {\n"
<< " explicit " << ClassName << " explicit " << ClassName
<< "(unsigned RA, unsigned D = 0, unsigned E = 0, unsigned PC = 0);\n" << "(unsigned RA, unsigned D = 0, unsigned E = 0, unsigned PC = 0);\n";
<< " bool needsStackRealignment(const MachineFunction &) const override\n"
<< " { return false; }\n";
if (!RegBank.getSubRegIndices().empty()) { if (!RegBank.getSubRegIndices().empty()) {
OS << " unsigned composeSubRegIndicesImpl" OS << " unsigned composeSubRegIndicesImpl"
<< "(unsigned, unsigned) const override;\n" << "(unsigned, unsigned) const override;\n"