Index: include/llvm/CodeGen/MIRYamlMapping.h =================================================================== --- include/llvm/CodeGen/MIRYamlMapping.h +++ include/llvm/CodeGen/MIRYamlMapping.h @@ -427,7 +427,7 @@ bool IsReturnAddressTaken = false; bool HasStackMap = false; bool HasPatchPoint = false; - uint64_t StackSize = 0; + Optional StackSize; int OffsetAdjustment = 0; unsigned MaxAlignment = 0; bool AdjustsStack = false; @@ -470,7 +470,7 @@ YamlIO.mapOptional("isReturnAddressTaken", MFI.IsReturnAddressTaken, false); YamlIO.mapOptional("hasStackMap", MFI.HasStackMap, false); YamlIO.mapOptional("hasPatchPoint", MFI.HasPatchPoint, false); - YamlIO.mapOptional("stackSize", MFI.StackSize, (uint64_t)0); + YamlIO.mapOptional("stackSize", MFI.StackSize); YamlIO.mapOptional("offsetAdjustment", MFI.OffsetAdjustment, (int)0); YamlIO.mapOptional("maxAlignment", MFI.MaxAlignment, (unsigned)0); YamlIO.mapOptional("adjustsStack", MFI.AdjustsStack, false); Index: include/llvm/CodeGen/MachineFrameInfo.h =================================================================== --- include/llvm/CodeGen/MachineFrameInfo.h +++ include/llvm/CodeGen/MachineFrameInfo.h @@ -13,6 +13,7 @@ #ifndef LLVM_CODEGEN_MACHINEFRAMEINFO_H #define LLVM_CODEGEN_MACHINEFRAMEINFO_H +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/DataTypes.h" #include @@ -240,7 +241,7 @@ /// offsets for all of the fixed size objects, updating the Objects list /// above. It then updates StackSize to contain the number of bytes that need /// to be allocated on entry to the function. - uint64_t StackSize = 0; + Optional StackSize; /// The amount that a frame offset needs to be adjusted to /// have the actual offset from the stack/frame pointer. The exact usage of @@ -545,7 +546,10 @@ /// Return the number of bytes that must be allocated to hold /// all of the fixed size frame objects. This is only valid after /// Prolog/Epilog code insertion has finalized the stack frame layout. - uint64_t getStackSize() const { return StackSize; } + uint64_t getStackSize() const { return StackSize.getValue(); } + + /// Return if the stack layout is finalized. + bool stackSizeIsKnown() const { return StackSize.hasValue(); } /// Set the size of the stack. void setStackSize(uint64_t Size) { StackSize = Size; } Index: lib/CodeGen/MIRParser/MIRParser.cpp =================================================================== --- lib/CodeGen/MIRParser/MIRParser.cpp +++ lib/CodeGen/MIRParser/MIRParser.cpp @@ -587,7 +587,8 @@ MFI.setReturnAddressIsTaken(YamlMFI.IsReturnAddressTaken); MFI.setHasStackMap(YamlMFI.HasStackMap); MFI.setHasPatchPoint(YamlMFI.HasPatchPoint); - MFI.setStackSize(YamlMFI.StackSize); + if (YamlMFI.StackSize.hasValue()) + MFI.setStackSize(YamlMFI.StackSize.getValue()); MFI.setOffsetAdjustment(YamlMFI.OffsetAdjustment); if (YamlMFI.MaxAlignment) MFI.ensureMaxAlignment(YamlMFI.MaxAlignment); Index: lib/CodeGen/MIRPrinter.cpp =================================================================== --- lib/CodeGen/MIRPrinter.cpp +++ lib/CodeGen/MIRPrinter.cpp @@ -327,7 +327,8 @@ YamlMFI.IsReturnAddressTaken = MFI.isReturnAddressTaken(); YamlMFI.HasStackMap = MFI.hasStackMap(); YamlMFI.HasPatchPoint = MFI.hasPatchPoint(); - YamlMFI.StackSize = MFI.getStackSize(); + if (MFI.stackSizeIsKnown()) + YamlMFI.StackSize = MFI.getStackSize(); YamlMFI.OffsetAdjustment = MFI.getOffsetAdjustment(); YamlMFI.MaxAlignment = MFI.getMaxAlignment(); YamlMFI.AdjustsStack = MFI.adjustsStack(); Index: lib/CodeGen/RegisterScavenging.cpp =================================================================== --- lib/CodeGen/RegisterScavenging.cpp +++ lib/CodeGen/RegisterScavenging.cpp @@ -782,7 +782,7 @@ namespace { -/// This class runs register scavenging independ of the PrologEpilogInserter. +/// This class runs register scavenging independent of the PrologEpilogInserter. /// This is used in for testing. class ScavengerTest : public MachineFunctionPass { public: @@ -802,6 +802,9 @@ TFL.determineCalleeSaves(MF, SavedRegs, &RS); TFL.processFunctionBeforeFrameFinalized(MF, &RS); + // FIXME: calculateFrameObjectOffsets not exposed here. + MF.getFrameInfo().setStackSize(0); + // Let's scavenge the current function scavengeFrameVirtualRegs(MF, RS); return true; Index: lib/Target/AMDGPU/SIFrameLowering.cpp =================================================================== --- lib/Target/AMDGPU/SIFrameLowering.cpp +++ lib/Target/AMDGPU/SIFrameLowering.cpp @@ -851,7 +851,7 @@ if (MFI.hasCalls()) { // All offsets are unsigned, so need to be addressed in the same direction // as stack growth. - if (MFI.getStackSize() != 0) + if (MFI.stackSizeIsKnown() && MFI.getStackSize() != 0) return true; // For the entry point, the input wave scratch offset must be copied to the Index: lib/Target/Hexagon/HexagonFrameLowering.cpp =================================================================== --- lib/Target/Hexagon/HexagonFrameLowering.cpp +++ lib/Target/Hexagon/HexagonFrameLowering.cpp @@ -577,6 +577,7 @@ return F.hasFnAttribute(Attribute::NoReturn) && F.hasFnAttribute(Attribute::NoUnwind) && !F.hasFnAttribute(Attribute::UWTable) && HST.noreturnStackElim() && + MFI.stackSizeIsKnown() && MFI.getStackSize() == 0; } @@ -1014,7 +1015,7 @@ if (HasAlloca || HasExtraAlign) return true; - if (MFI.getStackSize() > 0) { + if (MFI.stackSizeIsKnown() && MFI.getStackSize() > 0) { // If FP-elimination is disabled, we have to use FP at this point. const TargetMachine &TM = MF.getTarget(); if (TM.Options.DisableFramePointerElim(MF) || !EliminateFramePointer) Index: lib/Target/PowerPC/PPCFrameLowering.cpp =================================================================== --- lib/Target/PowerPC/PPCFrameLowering.cpp +++ lib/Target/PowerPC/PPCFrameLowering.cpp @@ -466,8 +466,8 @@ const MachineFrameInfo &MFI = MF.getFrameInfo(); // Get the number of bytes to allocate from the FrameInfo - unsigned FrameSize = - UseEstimate ? MFI.estimateStackSize(MF) : MFI.getStackSize(); + unsigned FrameSize = (UseEstimate || !MFI.stackSizeIsKnown()) ? + MFI.estimateStackSize(MF) : MFI.getStackSize(); // Get stack alignments. The frame must be aligned to the greatest of these: unsigned TargetAlign = getStackAlignment(); // alignment required per the ABI @@ -525,7 +525,7 @@ // FIXME: This is pretty much broken by design: hasFP() might be called really // early, before the stack layout was calculated and thus hasFP() might return // true or false here depending on the time of call. - return (MFI.getStackSize()) && needsFP(MF); + return (MFI.stackSizeIsKnown() && MFI.getStackSize()) && needsFP(MF); } // needsFP - Return true if the specified function should have a dedicated frame Index: lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp +++ lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp @@ -59,7 +59,7 @@ // If we already need a base pointer, we use that to fix up the stack pointer. // If there are no fixed-size objects, we would have no use of a frame // pointer, and thus should not emit one. - bool HasFixedSizedObjects = MFI.getStackSize() > 0; + bool HasFixedSizedObjects = MFI.stackSizeIsKnown() && MFI.getStackSize() > 0; bool NeedsFixedReference = !hasBP(MF) || HasFixedSizedObjects; return MFI.isFrameAddressTaken() || @@ -82,7 +82,8 @@ bool WebAssemblyFrameLowering::needsSPForLocalFrame( const MachineFunction &MF) const { auto &MFI = MF.getFrameInfo(); - return MFI.getStackSize() || MFI.adjustsStack() || hasFP(MF); + return (MFI.stackSizeIsKnown() && MFI.getStackSize()) || + MFI.adjustsStack() || hasFP(MF); } // In function with EH pads, we need to make a copy of the value of @@ -117,7 +118,8 @@ // 1. We need SP not only for EH support but also because we actually use // stack or we have a frame address taken. // 2. We cannot use the red zone. - bool CanUseRedZone = MFI.getStackSize() <= RedZoneSize && !MFI.hasCalls() && + bool CanUseRedZone = MFI.stackSizeIsKnown() && + MFI.getStackSize() <= RedZoneSize && !MFI.hasCalls() && !MF.getFunction().hasFnAttribute(Attribute::NoRedZone); return needsSPForLocalFrame(MF) && !CanUseRedZone; } Index: test/CodeGen/ARM/scavenging.mir =================================================================== --- test/CodeGen/ARM/scavenging.mir +++ test/CodeGen/ARM/scavenging.mir @@ -12,6 +12,8 @@ # CHECK-NOT: tSTRi {{.*}}$r6,{{.*}}$r6 # CHECK-NOT: tSTRi {{.*}}$r7,{{.*}}$r7 name: scavengebug0 +frameInfo: + stackSize: 0 body: | bb.0: ; Bring up register pressure to force emergency spilling Index: test/CodeGen/MIR/Generic/frame-info.mir =================================================================== --- test/CodeGen/MIR/Generic/frame-info.mir +++ test/CodeGen/MIR/Generic/frame-info.mir @@ -20,17 +20,26 @@ ret i32 %c } + define i32 @test3(i32 %a) { + entry: + %b = alloca i32 + store i32 %a, i32* %b + %c = load i32, i32* %b + ret i32 %c + } + ... --- + name: test tracksRegLiveness: true +# CHECK-LABEL: name: test{{$}} # CHECK: frameInfo: # CHECK-NEXT: isFrameAddressTaken: false # CHECK-NEXT: isReturnAddressTaken: false # CHECK-NEXT: hasStackMap: false # CHECK-NEXT: hasPatchPoint: false -# CHECK-NEXT: stackSize: 0 # CHECK-NEXT: offsetAdjustment: 0 # Note: max alignment can be target specific when printed. # CHECK-NEXT: maxAlignment: @@ -55,7 +64,7 @@ name: test2 tracksRegLiveness: true -# CHECK: test2 +# CHECK-LABEL: name: test2{{$}} # CHECK: frameInfo: # CHECK-NEXT: isFrameAddressTaken: true # CHECK-NEXT: isReturnAddressTaken: true @@ -94,3 +103,47 @@ bb.0.entry: ... +# Test an explicit stack size of 0 +--- +name: test3 +tracksRegLiveness: true + +# CHECK-LABEL: name: test3{{$}} +# CHECK: frameInfo: +# CHECK-NEXT: isFrameAddressTaken: true +# CHECK-NEXT: isReturnAddressTaken: true +# CHECK-NEXT: hasStackMap: true +# CHECK-NEXT: hasPatchPoint: true +# CHECK-NEXT: stackSize: 0 +# CHECK-NEXT: offsetAdjustment: 4 +# Note: max alignment can be target specific when printed. +# CHECK-NEXT: maxAlignment: +# CHECK-NEXT: adjustsStack: true +# CHECK-NEXT: hasCalls: true +# CHECK-NEXT: stackProtector: '' +# CHECK-NEXT: maxCallFrameSize: 4 +# CHECK-NEXT: cvBytesOfCalleeSavedRegisters: 8 +# CHECK-NEXT: hasOpaqueSPAdjustment: true +# CHECK-NEXT: hasVAStart: true +# CHECK-NEXT: hasMustTailInVarArgFunc: true +# CHECK: body +frameInfo: + isFrameAddressTaken: true + isReturnAddressTaken: true + hasStackMap: true + hasPatchPoint: true + stackSize: 0 + offsetAdjustment: 4 + maxAlignment: 4 + adjustsStack: true + hasCalls: true + maxCallFrameSize: 4 + cvBytesOfCalleeSavedRegisters: 8 + hasOpaqueSPAdjustment: true + hasVAStart: true + hasMustTailInVarArgFunc: true + localFrameSize: 256 +body: | + bb.0.entry: +... +