mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1019831: SIMD x86-x64: Align stack top on 16 bytes boundaries if SIMD instructions are present; r=sunfish
--HG-- extra : rebase_source : 28a14e3c7251e86d181cdee0db424b74ad24ea1d
This commit is contained in:
parent
416eea5b85
commit
e3b29c20e7
@ -2228,7 +2228,7 @@ LIRGenerator::visitInterruptCheck(MInterruptCheck *ins)
|
||||
bool
|
||||
LIRGenerator::visitAsmJSInterruptCheck(MAsmJSInterruptCheck *ins)
|
||||
{
|
||||
gen->setPerformsAsmJSCall();
|
||||
gen->setPerformsCall();
|
||||
|
||||
LAsmJSInterruptCheck *lir = new(alloc()) LAsmJSInterruptCheck(temp(),
|
||||
ins->interruptExit(),
|
||||
@ -3556,7 +3556,7 @@ LIRGenerator::visitAsmJSPassStackArg(MAsmJSPassStackArg *ins)
|
||||
bool
|
||||
LIRGenerator::visitAsmJSCall(MAsmJSCall *ins)
|
||||
{
|
||||
gen->setPerformsAsmJSCall();
|
||||
gen->setPerformsCall();
|
||||
|
||||
LAllocation *args = gen->allocate<LAllocation>(ins->numOperands());
|
||||
if (!args)
|
||||
|
@ -127,18 +127,9 @@ class MIRGenerator
|
||||
bool performsCall() const {
|
||||
return performsCall_;
|
||||
}
|
||||
void setNeedsInitialStackAlignment() {
|
||||
needsInitialStackAlignment_ = true;
|
||||
}
|
||||
bool needsInitialStackAlignment() const {
|
||||
JS_ASSERT(compilingAsmJS());
|
||||
return needsInitialStackAlignment_;
|
||||
}
|
||||
void setPerformsAsmJSCall() {
|
||||
JS_ASSERT(compilingAsmJS());
|
||||
setPerformsCall();
|
||||
setNeedsInitialStackAlignment();
|
||||
}
|
||||
// Traverses the graph to find if there's any SIMD instruction. Costful but
|
||||
// the value is cached, so don't worry about calling it several times.
|
||||
bool usesSimd();
|
||||
void noteMinAsmJSHeapLength(uint32_t len) {
|
||||
minAsmJSHeapLength_ = len;
|
||||
}
|
||||
@ -167,7 +158,8 @@ class MIRGenerator
|
||||
|
||||
uint32_t maxAsmJSStackArgBytes_;
|
||||
bool performsCall_;
|
||||
bool needsInitialStackAlignment_;
|
||||
bool usesSimd_;
|
||||
bool usesSimdCached_;
|
||||
uint32_t minAsmJSHeapLength_;
|
||||
|
||||
// Keep track of whether frame arguments are modified during execution.
|
||||
|
@ -30,12 +30,44 @@ MIRGenerator::MIRGenerator(CompileCompartment *compartment, const JitCompileOpti
|
||||
cancelBuild_(false),
|
||||
maxAsmJSStackArgBytes_(0),
|
||||
performsCall_(false),
|
||||
needsInitialStackAlignment_(false),
|
||||
usesSimd_(false),
|
||||
usesSimdCached_(false),
|
||||
minAsmJSHeapLength_(AsmJSAllocationGranularity),
|
||||
modifiesFrameArguments_(false),
|
||||
options(options)
|
||||
{ }
|
||||
|
||||
bool
|
||||
MIRGenerator::usesSimd()
|
||||
{
|
||||
if (usesSimdCached_)
|
||||
return usesSimd_;
|
||||
|
||||
usesSimdCached_ = true;
|
||||
for (ReversePostorderIterator block = graph_->rpoBegin(),
|
||||
end = graph_->rpoEnd();
|
||||
block != end;
|
||||
block++)
|
||||
{
|
||||
// It's fine to use MInstructionIterator here because we don't have to
|
||||
// worry about Phis, since any reachable phi (or phi cycle) will have at
|
||||
// least one instruction as an input.
|
||||
for (MInstructionIterator inst = block->begin(); inst != block->end(); inst++) {
|
||||
// Instructions that have SIMD inputs but not a SIMD type are fine
|
||||
// to ignore, as their inputs are also reached at some point. By
|
||||
// induction, at least one instruction with a SIMD type is reached
|
||||
// at some point.
|
||||
if (IsSimdType(inst->type())) {
|
||||
JS_ASSERT(SupportsSimd);
|
||||
usesSimd_ = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
usesSimd_ = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
MIRGenerator::abortFmt(const char *message, va_list ap)
|
||||
{
|
||||
|
@ -150,6 +150,7 @@ static const bool StackKeptAligned = true;
|
||||
// here such that it is accessible from the entire codebase. Once full support
|
||||
// for SIMD is reached on all tier-1 platforms, this constant can be deleted.
|
||||
static const bool SupportsSimd = false;
|
||||
static const uint32_t SimdStackAlignment = 8;
|
||||
|
||||
static const Scale ScalePointer = TimesFour;
|
||||
|
||||
|
@ -68,10 +68,14 @@ CodeGeneratorShared::CodeGeneratorShared(MIRGenerator *gen, LIRGraph *graph, Mac
|
||||
// An MAsmJSCall does not align the stack pointer at calls sites but instead
|
||||
// relies on the a priori stack adjustment (in the prologue) on platforms
|
||||
// (like x64) which require the stack to be aligned.
|
||||
if (StackKeptAligned || gen->needsInitialStackAlignment()) {
|
||||
if (StackKeptAligned || gen->performsCall() || gen->usesSimd()) {
|
||||
unsigned alignmentAtCall = sizeof(AsmJSFrame) + frameDepth_;
|
||||
unsigned firstFixup = 0;
|
||||
if (unsigned rem = alignmentAtCall % StackAlignment)
|
||||
frameDepth_ += StackAlignment - rem;
|
||||
frameDepth_ += (firstFixup = StackAlignment - rem);
|
||||
|
||||
if (gen->usesSimd())
|
||||
setupSimdAlignment(firstFixup);
|
||||
}
|
||||
|
||||
// FrameSizeClass is only used for bailing, which cannot happen in
|
||||
@ -82,6 +86,38 @@ CodeGeneratorShared::CodeGeneratorShared(MIRGenerator *gen, LIRGraph *graph, Mac
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CodeGeneratorShared::setupSimdAlignment(unsigned fixup)
|
||||
{
|
||||
JS_STATIC_ASSERT(SimdStackAlignment % StackAlignment == 0);
|
||||
// At this point, we have:
|
||||
// (frameDepth_ + sizeof(AsmJSFrame)) % StackAlignment == 0
|
||||
// which means we can add as many SimdStackAlignment as needed.
|
||||
|
||||
// The next constraint is to have all stack slots
|
||||
// aligned for SIMD. That's done by having the first stack slot
|
||||
// aligned. We need an offset such that:
|
||||
// (frameDepth_ - offset) % SimdStackAlignment == 0
|
||||
frameInitialAdjustment_ = frameDepth_ % SimdStackAlignment;
|
||||
|
||||
// We need to ensure that the first stack slot is actually
|
||||
// located in this frame and not beforehand, when taking this
|
||||
// offset into account, i.e.:
|
||||
// frameDepth_ - initial adjustment >= frameDepth_ - fixup
|
||||
// <=> fixup >= initial adjustment
|
||||
//
|
||||
// For instance, on x86 with gcc, if the initial frameDepth
|
||||
// % 16 is 8, then the fixup is 0, although the initial
|
||||
// adjustment is 8. The first stack slot would be located at
|
||||
// frameDepth - 8 in this case, which is obviously before
|
||||
// frameDepth.
|
||||
//
|
||||
// If that's not the case, we add SimdStackAlignment to the
|
||||
// fixup, which will keep on satisfying other constraints.
|
||||
if (frameInitialAdjustment_ > int32_t(fixup))
|
||||
frameDepth_ += SimdStackAlignment;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGeneratorShared::generateOutOfLineCode()
|
||||
{
|
||||
|
@ -458,6 +458,8 @@ class CodeGeneratorShared : public LInstructionVisitor
|
||||
private:
|
||||
void generateInvalidateEpilogue();
|
||||
|
||||
void setupSimdAlignment(unsigned fixup);
|
||||
|
||||
public:
|
||||
CodeGeneratorShared(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm);
|
||||
|
||||
|
@ -194,6 +194,7 @@ static const uint32_t CodeAlignment = 8;
|
||||
// here such that it is accessible from the entire codebase. Once full support
|
||||
// for SIMD is reached on all tier-1 platforms, this constant can be deleted.
|
||||
static const bool SupportsSimd = true;
|
||||
static const uint32_t SimdStackAlignment = 16;
|
||||
|
||||
static const Scale ScalePointer = TimesEight;
|
||||
|
||||
|
@ -122,6 +122,7 @@ static const uint32_t CodeAlignment = 8;
|
||||
// here such that it is accessible from the entire codebase. Once full support
|
||||
// for SIMD is reached on all tier-1 platforms, this constant can be deleted.
|
||||
static const bool SupportsSimd = true;
|
||||
static const uint32_t SimdStackAlignment = 16;
|
||||
|
||||
struct ImmTag : public Imm32
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user