Ignore:
Timestamp:
Jul 18, 2017, 3:07:43 PM (8 years ago)
Author:
[email protected]
Message:

AirLowerAfterRegAlloc may incorrectly use a callee save that's live as a scratch register
https://bugs.webkit.org/show_bug.cgi?id=174515
<rdar://problem/33358092>

Reviewed by Filip Pizlo.

AirLowerAfterRegAlloc was computing the set of available scratch
registers incorrectly. It was always excluding callee save registers
from the set of live registers. It did not guarantee that live callee save
registers were not in the set of scratch registers that could
get clobbered. That's incorrect as the shuffling code is free
to overwrite whatever is in the scratch register it gets passed.

  • b3/air/AirLowerAfterRegAlloc.cpp:

(JSC::B3::Air::lowerAfterRegAlloc):

  • b3/testb3.cpp:

(JSC::B3::functionNineArgs):
(JSC::B3::testShuffleDoesntTrashCalleeSaves):
(JSC::B3::run):

  • jit/RegisterSet.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/b3/testb3.cpp

    r219047 r219633  
    1554415544        }
    1554515545    }
     15546}
     15547
     15548void functionNineArgs(int32_t, void*, void*, void*, void*, void*, void*, void*, void*) { }
     15549
     15550void testShuffleDoesntTrashCalleeSaves()
     15551{
     15552    Procedure proc;
     15553
     15554    BasicBlock* root = proc.addBlock();
     15555    BasicBlock* likely = proc.addBlock();
     15556    BasicBlock* unlikely = proc.addBlock();
     15557
     15558    RegisterSet regs = RegisterSet::allGPRs();
     15559    regs.exclude(RegisterSet::stackRegisters());
     15560    regs.exclude(RegisterSet::reservedHardwareRegisters());
     15561    regs.exclude(RegisterSet::calleeSaveRegisters());
     15562    regs.exclude(RegisterSet::argumentGPRS());
     15563
     15564    unsigned i = 0;
     15565    Vector<Value*> patches;
     15566    for (Reg reg : regs) {
     15567        ++i;
     15568        PatchpointValue* patchpoint = root->appendNew<PatchpointValue>(proc, Int32, Origin());
     15569        patchpoint->clobber(RegisterSet::macroScratchRegisters());
     15570        RELEASE_ASSERT(reg.isGPR());
     15571        patchpoint->resultConstraint = ValueRep::reg(reg.gpr());
     15572        patchpoint->setGenerator(
     15573            [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
     15574                AllowMacroScratchRegisterUsage allowScratch(jit);
     15575                jit.move(CCallHelpers::TrustedImm32(i), params[0].gpr());
     15576            });
     15577        patches.append(patchpoint);
     15578    }
     15579
     15580    Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::toArgumentRegister(0 % GPRInfo::numberOfArgumentRegisters));
     15581    Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::toArgumentRegister(1 % GPRInfo::numberOfArgumentRegisters));
     15582    Value* arg3 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::toArgumentRegister(2 % GPRInfo::numberOfArgumentRegisters));
     15583    Value* arg4 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::toArgumentRegister(3 % GPRInfo::numberOfArgumentRegisters));
     15584    Value* arg5 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::toArgumentRegister(4 % GPRInfo::numberOfArgumentRegisters));
     15585    Value* arg6 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::toArgumentRegister(5 % GPRInfo::numberOfArgumentRegisters));
     15586    Value* arg7 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::toArgumentRegister(6 % GPRInfo::numberOfArgumentRegisters));
     15587    Value* arg8 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::toArgumentRegister(7 % GPRInfo::numberOfArgumentRegisters));
     15588
     15589    PatchpointValue* ptr = root->appendNew<PatchpointValue>(proc, Int64, Origin());
     15590    ptr->clobber(RegisterSet::macroScratchRegisters());
     15591    ptr->resultConstraint = ValueRep::reg(GPRInfo::regCS0);
     15592    ptr->appendSomeRegister(arg1);
     15593    ptr->setGenerator(
     15594        [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
     15595            AllowMacroScratchRegisterUsage allowScratch(jit);
     15596            jit.move(params[1].gpr(), params[0].gpr());
     15597        });
     15598
     15599    Value* condition = root->appendNew<Value>(
     15600        proc, Equal, Origin(),
     15601        ptr,
     15602        root->appendNew<Const64Value>(proc, Origin(), 0));
     15603
     15604    root->appendNewControlValue(
     15605        proc, Branch, Origin(),
     15606        condition,
     15607        FrequentedBlock(likely, FrequencyClass::Normal), FrequentedBlock(unlikely, FrequencyClass::Rare));
     15608
     15609    // Never executes.
     15610    Value* const42 = likely->appendNew<Const32Value>(proc, Origin(), 42);
     15611    likely->appendNewControlValue(proc, Return, Origin(), const42);
     15612
     15613    // Always executes.
     15614    Value* constNumber = unlikely->appendNew<Const32Value>(proc, Origin(), 0x1);
     15615
     15616    unlikely->appendNew<CCallValue>(
     15617        proc, Void, Origin(),
     15618        unlikely->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(functionNineArgs)),
     15619        constNumber, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
     15620
     15621    PatchpointValue* voidPatch = unlikely->appendNew<PatchpointValue>(proc, Void, Origin());
     15622    voidPatch->clobber(RegisterSet::macroScratchRegisters());
     15623    for (Value* v : patches)
     15624        voidPatch->appendSomeRegister(v);
     15625    voidPatch->appendSomeRegister(arg1);
     15626    voidPatch->appendSomeRegister(arg2);
     15627    voidPatch->appendSomeRegister(arg3);
     15628    voidPatch->appendSomeRegister(arg4);
     15629    voidPatch->appendSomeRegister(arg5);
     15630    voidPatch->appendSomeRegister(arg6);
     15631    voidPatch->setGenerator([=] (CCallHelpers&, const StackmapGenerationParams&) { });
     15632
     15633    unlikely->appendNewControlValue(proc, Return, Origin(),
     15634        unlikely->appendNew<MemoryValue>(proc, Load, Int32, Origin(), ptr));
     15635
     15636    int32_t* inputPtr = static_cast<int32_t*>(fastMalloc(sizeof(int32_t)));
     15637    *inputPtr = 48;
     15638    CHECK(compileAndRun<int32_t>(proc, inputPtr) == 48);
     15639    fastFree(inputPtr);
    1554615640}
    1554715641
     
    1708917183    RUN(testFloatEqualOrUnorderedDontFold());
    1709017184
     17185    RUN(testShuffleDoesntTrashCalleeSaves());
     17186
    1709117187    if (isX86()) {
    1709217188        RUN(testBranchBitAndImmFusion(Identity, Int64, 1, Air::BranchTest32, Air::Arg::Tmp));
Note: See TracChangeset for help on using the changeset viewer.