mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-25 21:33:25 +00:00
[CodeGen] Don't assume that fixed stack objects are aligned in a stack-realigned function.
Summary: After we make the adjustment, we can assume that for local allocas, but not for stack parameters, the return address, or any other fixed stack object (which has a negative offset and therefore lies prior to the adjusted SP). Fixes PR26662. Reviewers: hfinkel, qcolombet, rnk Subscribers: rnk, llvm-commits Differential Revision: http://reviews.llvm.org/D18471 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@265886 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7c0a10f790
commit
c15a907754
@ -253,6 +253,9 @@ class MachineFrameInfo {
|
||||
/// Whether the "realign-stack" option is on.
|
||||
bool RealignOption;
|
||||
|
||||
/// Whether the function has the \c alignstack attribute.
|
||||
bool ForcedRealign;
|
||||
|
||||
/// True if the function dynamically adjusts the stack pointer through some
|
||||
/// opaque mechanism like inline assembly or Win32 EH.
|
||||
bool HasOpaqueSPAdjustment;
|
||||
@ -279,9 +282,9 @@ class MachineFrameInfo {
|
||||
|
||||
public:
|
||||
explicit MachineFrameInfo(unsigned StackAlign, bool isStackRealign,
|
||||
bool RealignOpt)
|
||||
bool RealignOpt, bool ForceRealign)
|
||||
: StackAlignment(StackAlign), StackRealignable(isStackRealign),
|
||||
RealignOption(RealignOpt) {
|
||||
RealignOption(RealignOpt), ForcedRealign(ForceRealign) {
|
||||
StackSize = NumFixedObjects = OffsetAdjustment = MaxAlignment = 0;
|
||||
HasVarSizedObjects = false;
|
||||
FrameAddressTaken = false;
|
||||
|
@ -84,6 +84,13 @@ void ilist_traits<MachineBasicBlock>::deleteNode(MachineBasicBlock *MBB) {
|
||||
MBB->getParent()->DeleteMachineBasicBlock(MBB);
|
||||
}
|
||||
|
||||
static inline unsigned getFnStackAlignment(const TargetSubtargetInfo *STI,
|
||||
const Function *Fn) {
|
||||
if (Fn->hasFnAttribute(Attribute::StackAlignment))
|
||||
return Fn->getFnStackAlignment();
|
||||
return STI->getFrameLowering()->getStackAlignment();
|
||||
}
|
||||
|
||||
MachineFunction::MachineFunction(const Function *F, const TargetMachine &TM,
|
||||
unsigned FunctionNum, MachineModuleInfo &mmi)
|
||||
: Fn(F), Target(TM), STI(TM.getSubtargetImpl(*F)), Ctx(mmi.getContext()),
|
||||
@ -97,9 +104,11 @@ MachineFunction::MachineFunction(const Function *F, const TargetMachine &TM,
|
||||
|
||||
MFInfo = nullptr;
|
||||
FrameInfo = new (Allocator)
|
||||
MachineFrameInfo(STI->getFrameLowering()->getStackAlignment(),
|
||||
MachineFrameInfo(getFnStackAlignment(STI, Fn),
|
||||
STI->getFrameLowering()->isStackRealignable(),
|
||||
!F->hasFnAttribute("no-realign-stack"));
|
||||
!F->hasFnAttribute("no-realign-stack"),
|
||||
!F->hasFnAttribute("no-realign-stack") &&
|
||||
F->hasFnAttribute(Attribute::StackAlignment));
|
||||
|
||||
if (Fn->hasFnAttribute(Attribute::StackAlignment))
|
||||
FrameInfo->ensureMaxAlignment(Fn->getFnStackAlignment());
|
||||
@ -613,8 +622,10 @@ int MachineFrameInfo::CreateFixedObject(uint64_t Size, int64_t SPOffset,
|
||||
// The alignment of the frame index can be determined from its offset from
|
||||
// the incoming frame position. If the frame object is at offset 32 and
|
||||
// the stack is guaranteed to be 16-byte aligned, then we know that the
|
||||
// object is 16-byte aligned.
|
||||
unsigned Align = MinAlign(SPOffset, StackAlignment);
|
||||
// object is 16-byte aligned. Note that unlike the non-fixed case, if the
|
||||
// stack needs realignment, we can't assume that the stack will in fact be
|
||||
// aligned.
|
||||
unsigned Align = MinAlign(SPOffset, ForcedRealign ? 1 : StackAlignment);
|
||||
Align = clampStackAlignment(!StackRealignable || !RealignOption, Align,
|
||||
StackAlignment);
|
||||
Objects.insert(Objects.begin(), StackObject(Size, Align, SPOffset, Immutable,
|
||||
@ -627,7 +638,7 @@ int MachineFrameInfo::CreateFixedObject(uint64_t Size, int64_t SPOffset,
|
||||
/// Returns an index with a negative value.
|
||||
int MachineFrameInfo::CreateFixedSpillStackObject(uint64_t Size,
|
||||
int64_t SPOffset) {
|
||||
unsigned Align = MinAlign(SPOffset, StackAlignment);
|
||||
unsigned Align = MinAlign(SPOffset, ForcedRealign ? 1 : StackAlignment);
|
||||
Align = clampStackAlignment(!StackRealignable || !RealignOption, Align,
|
||||
StackAlignment);
|
||||
Objects.insert(Objects.begin(), StackObject(Size, Align, SPOffset,
|
||||
|
@ -61,3 +61,31 @@ entry:
|
||||
; CHECK-NOT: and
|
||||
; CHECK: ret
|
||||
}
|
||||
|
||||
%struct.sixteen = type { [16 x i8] }
|
||||
|
||||
; Accessing stack parameters shouldn't assume stack alignment. Here we should
|
||||
; emit two 8-byte loads, followed by two 8-byte stores.
|
||||
define x86_stdcallcc void @test5(%struct.sixteen* byval nocapture readonly align 4 %s) #0 {
|
||||
%d.sroa.0 = alloca [16 x i8], align 1
|
||||
%1 = getelementptr inbounds [16 x i8], [16 x i8]* %d.sroa.0, i32 0, i32 0
|
||||
call void @llvm.lifetime.start(i64 16, i8* %1)
|
||||
%2 = getelementptr inbounds %struct.sixteen, %struct.sixteen* %s, i32 0, i32 0, i32 0
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* %1, i8* %2, i32 16, i32 1, i1 true)
|
||||
call void @llvm.lifetime.end(i64 16, i8* %1)
|
||||
ret void
|
||||
; CHECK-LABEL: test5:
|
||||
; CHECK: and
|
||||
; CHECK: movsd
|
||||
; CHECK-NEXT: movsd
|
||||
; CHECK-NEXT: movsd
|
||||
; CHECK-NEXT: movsd
|
||||
}
|
||||
|
||||
declare void @llvm.lifetime.start(i64, i8* nocapture) argmemonly nounwind
|
||||
|
||||
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1) argmemonly nounwind
|
||||
|
||||
declare void @llvm.lifetime.end(i64, i8* nocapture) argmemonly nounwind
|
||||
|
||||
attributes #0 = { nounwind alignstack=16 "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" }
|
||||
|
Loading…
x
Reference in New Issue
Block a user