Ignore:
Timestamp:
Jul 25, 2017, 6:58:36 PM (8 years ago)
Author:
[email protected]
Message:

B3 should do LICM
https://bugs.webkit.org/show_bug.cgi?id=174750

Reviewed by Keith Miller and Saam Barati.

Source/JavaScriptCore:

Added a LICM phase to B3. This phase is called hoistLoopInvariantValues, to conform to the B3 naming
convention for phases (it has to be an imperative). The phase uses NaturalLoops and BackwardsDominators,
so this adds those analyses to B3. BackwardsDominators was already available in templatized form. This
change templatizes DFG::NaturalLoops so that we can just use it.

The LICM phase itself is really simple. We are decently precise with our handling of everything except
the relationship between control dependence and side exits.

Also added a bunch of tests.

This isn't super important. It's perf-neutral on JS benchmarks. FTL already does LICM on DFG SSA IR, and
probably all current WebAssembly content has had LICM done to it. That being said, this is a cheap phase
so it doesn't hurt to have it.

I wrote it because I thought I needed it for bug 174727. It turns out that there's a better way to
handle the problem I had, so I ended up not needed it - but by then I had already written it. I think
it's good to have it because LICM is one of those core compiler phases; every compiler has it
eventually.

  • CMakeLists.txt:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • b3/B3BackwardsCFG.h: Added.

(JSC::B3::BackwardsCFG::BackwardsCFG):

  • b3/B3BackwardsDominators.h: Added.

(JSC::B3::BackwardsDominators::BackwardsDominators):

  • b3/B3BasicBlock.cpp:

(JSC::B3::BasicBlock::appendNonTerminal):

  • b3/B3Effects.h:
  • b3/B3EnsureLoopPreHeaders.cpp: Added.

(JSC::B3::ensureLoopPreHeaders):

  • b3/B3EnsureLoopPreHeaders.h: Added.
  • b3/B3Generate.cpp:

(JSC::B3::generateToAir):

  • b3/B3HoistLoopInvariantValues.cpp: Added.

(JSC::B3::hoistLoopInvariantValues):

  • b3/B3HoistLoopInvariantValues.h: Added.
  • b3/B3NaturalLoops.h: Added.

(JSC::B3::NaturalLoops::NaturalLoops):

  • b3/B3Procedure.cpp:

(JSC::B3::Procedure::invalidateCFG):
(JSC::B3::Procedure::naturalLoops):
(JSC::B3::Procedure::backwardsCFG):
(JSC::B3::Procedure::backwardsDominators):

  • b3/B3Procedure.h:
  • b3/testb3.cpp:

(JSC::B3::generateLoop):
(JSC::B3::makeArrayForLoops):
(JSC::B3::generateLoopNotBackwardsDominant):
(JSC::B3::oneFunction):
(JSC::B3::noOpFunction):
(JSC::B3::testLICMPure):
(JSC::B3::testLICMPureSideExits):
(JSC::B3::testLICMPureWritesPinned):
(JSC::B3::testLICMPureWrites):
(JSC::B3::testLICMReadsLocalState):
(JSC::B3::testLICMReadsPinned):
(JSC::B3::testLICMReads):
(JSC::B3::testLICMPureNotBackwardsDominant):
(JSC::B3::testLICMPureFoiledByChild):
(JSC::B3::testLICMPureNotBackwardsDominantFoiledByChild):
(JSC::B3::testLICMExitsSideways):
(JSC::B3::testLICMWritesLocalState):
(JSC::B3::testLICMWrites):
(JSC::B3::testLICMFence):
(JSC::B3::testLICMWritesPinned):
(JSC::B3::testLICMControlDependent):
(JSC::B3::testLICMControlDependentNotBackwardsDominant):
(JSC::B3::testLICMControlDependentSideExits):
(JSC::B3::testLICMReadsPinnedWritesPinned):
(JSC::B3::testLICMReadsWritesDifferentHeaps):
(JSC::B3::testLICMReadsWritesOverlappingHeaps):
(JSC::B3::testLICMDefaultCall):
(JSC::B3::run):

  • dfg/DFGBasicBlock.h:
  • dfg/DFGCFG.h:
  • dfg/DFGNaturalLoops.cpp: Removed.
  • dfg/DFGNaturalLoops.h:

(JSC::DFG::NaturalLoops::NaturalLoops):
(JSC::DFG::NaturalLoop::NaturalLoop): Deleted.
(JSC::DFG::NaturalLoop::header): Deleted.
(JSC::DFG::NaturalLoop::size): Deleted.
(JSC::DFG::NaturalLoop::at): Deleted.
(JSC::DFG::NaturalLoop::operator[]): Deleted.
(JSC::DFG::NaturalLoop::contains): Deleted.
(JSC::DFG::NaturalLoop::index): Deleted.
(JSC::DFG::NaturalLoop::isOuterMostLoop): Deleted.
(JSC::DFG::NaturalLoop::addBlock): Deleted.
(JSC::DFG::NaturalLoops::numLoops): Deleted.
(JSC::DFG::NaturalLoops::loop): Deleted.
(JSC::DFG::NaturalLoops::headerOf): Deleted.
(JSC::DFG::NaturalLoops::innerMostLoopOf): Deleted.
(JSC::DFG::NaturalLoops::innerMostOuterLoop): Deleted.
(JSC::DFG::NaturalLoops::belongsTo): Deleted.
(JSC::DFG::NaturalLoops::loopDepth): Deleted.

Source/WTF:

Moved DFG::NaturalLoops to WTF. The new templatized NaturalLoops<> uses the same Graph abstraction as
Dominators<>. This allows us to add a B3::NaturalLoops for free.

Also made small tweaks to RangeSet, which the LICM uses.

  • WTF.xcodeproj/project.pbxproj:
  • wtf/CMakeLists.txt:
  • wtf/Dominators.h:
  • wtf/NaturalLoops.h: Added.

(WTF::NaturalLoop::NaturalLoop):
(WTF::NaturalLoop::graph):
(WTF::NaturalLoop::header):
(WTF::NaturalLoop::size):
(WTF::NaturalLoop::at):
(WTF::NaturalLoop::operator[]):
(WTF::NaturalLoop::contains):
(WTF::NaturalLoop::index):
(WTF::NaturalLoop::isOuterMostLoop):
(WTF::NaturalLoop::dump):
(WTF::NaturalLoop::addBlock):
(WTF::NaturalLoops::NaturalLoops):
(WTF::NaturalLoops::graph):
(WTF::NaturalLoops::numLoops):
(WTF::NaturalLoops::loop):
(WTF::NaturalLoops::headerOf):
(WTF::NaturalLoops::innerMostLoopOf):
(WTF::NaturalLoops::innerMostOuterLoop):
(WTF::NaturalLoops::belongsTo):
(WTF::NaturalLoops::loopDepth):
(WTF::NaturalLoops::loopsOf):
(WTF::NaturalLoops::dump):

  • wtf/RangeSet.h:

(WTF::RangeSet::begin):
(WTF::RangeSet::end):
(WTF::RangeSet::addAll):

File:
1 edited

Legend:

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

    r219633 r219898  
    1459114591    }
    1459214592    CHECK(found);
     14593}
     14594
     14595template<typename Func>
     14596void generateLoop(Procedure& proc, const Func& func)
     14597{
     14598    BasicBlock* root = proc.addBlock();
     14599    BasicBlock* loop = proc.addBlock();
     14600    BasicBlock* end = proc.addBlock();
     14601
     14602    UpsilonValue* initialIndex = root->appendNew<UpsilonValue>(
     14603        proc, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
     14604    root->appendNew<Value>(proc, Jump, Origin());
     14605    root->setSuccessors(loop);
     14606   
     14607    Value* index = loop->appendNew<Value>(proc, Phi, Int32, Origin());
     14608    initialIndex->setPhi(index);
     14609   
     14610    Value* one = func(loop, index);
     14611   
     14612    Value* nextIndex = loop->appendNew<Value>(proc, Add, Origin(), index, one);
     14613    UpsilonValue* loopIndex = loop->appendNew<UpsilonValue>(proc, Origin(), nextIndex);
     14614    loopIndex->setPhi(index);
     14615    loop->appendNew<Value>(
     14616        proc, Branch, Origin(),
     14617        loop->appendNew<Value>(
     14618            proc, LessThan, Origin(), nextIndex,
     14619            loop->appendNew<Const32Value>(proc, Origin(), 100)));
     14620    loop->setSuccessors(loop, end);
     14621   
     14622    end->appendNew<Value>(proc, Return, Origin());
     14623}
     14624
     14625std::array<int, 100> makeArrayForLoops()
     14626{
     14627    std::array<int, 100> result;
     14628    for (unsigned i = 0; i < result.size(); ++i)
     14629        result[i] = i & 1;
     14630    return result;
     14631}
     14632
     14633template<typename Func>
     14634void generateLoopNotBackwardsDominant(Procedure& proc, std::array<int, 100>& array, const Func& func)
     14635{
     14636    BasicBlock* root = proc.addBlock();
     14637    BasicBlock* loopHeader = proc.addBlock();
     14638    BasicBlock* loopCall = proc.addBlock();
     14639    BasicBlock* loopFooter = proc.addBlock();
     14640    BasicBlock* end = proc.addBlock();
     14641
     14642    UpsilonValue* initialIndex = root->appendNew<UpsilonValue>(
     14643        proc, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
     14644    // If you look carefully, you'll notice that this is an extremely sneaky use of Upsilon that demonstrates
     14645    // the extent to which our SSA is different from normal-person SSA.
     14646    UpsilonValue* defaultOne = root->appendNew<UpsilonValue>(
     14647        proc, Origin(), root->appendNew<Const32Value>(proc, Origin(), 1));
     14648    root->appendNew<Value>(proc, Jump, Origin());
     14649    root->setSuccessors(loopHeader);
     14650   
     14651    Value* index = loopHeader->appendNew<Value>(proc, Phi, Int32, Origin());
     14652    initialIndex->setPhi(index);
     14653   
     14654    // if (array[index])
     14655    loopHeader->appendNew<Value>(
     14656        proc, Branch, Origin(),
     14657        loopHeader->appendNew<MemoryValue>(
     14658            proc, Load, Int32, Origin(),
     14659            loopHeader->appendNew<Value>(
     14660                proc, Add, Origin(),
     14661                loopHeader->appendNew<ConstPtrValue>(proc, Origin(), &array),
     14662                loopHeader->appendNew<Value>(
     14663                    proc, Mul, Origin(),
     14664                    loopHeader->appendNew<Value>(proc, ZExt32, Origin(), index),
     14665                    loopHeader->appendNew<ConstPtrValue>(proc, Origin(), sizeof(int))))));
     14666    loopHeader->setSuccessors(loopCall, loopFooter);
     14667   
     14668    Value* functionCall = func(loopCall, index);
     14669    UpsilonValue* oneFromFunction = loopCall->appendNew<UpsilonValue>(proc, Origin(), functionCall);
     14670    loopCall->appendNew<Value>(proc, Jump, Origin());
     14671    loopCall->setSuccessors(loopFooter);
     14672   
     14673    Value* one = loopFooter->appendNew<Value>(proc, Phi, Int32, Origin());
     14674    defaultOne->setPhi(one);
     14675    oneFromFunction->setPhi(one);
     14676    Value* nextIndex = loopFooter->appendNew<Value>(proc, Add, Origin(), index, one);
     14677    UpsilonValue* loopIndex = loopFooter->appendNew<UpsilonValue>(proc, Origin(), nextIndex);
     14678    loopIndex->setPhi(index);
     14679    loopFooter->appendNew<Value>(
     14680        proc, Branch, Origin(),
     14681        loopFooter->appendNew<Value>(
     14682            proc, LessThan, Origin(), nextIndex,
     14683            loopFooter->appendNew<Const32Value>(proc, Origin(), 100)));
     14684    loopFooter->setSuccessors(loopHeader, end);
     14685   
     14686    end->appendNew<Value>(proc, Return, Origin());
     14687}
     14688
     14689static int oneFunction(int* callCount)
     14690{
     14691    (*callCount)++;
     14692    return 1;
     14693}
     14694
     14695static void noOpFunction()
     14696{
     14697}
     14698
     14699void testLICMPure()
     14700{
     14701    Procedure proc;
     14702    generateLoop(
     14703        proc,
     14704        [&] (BasicBlock* loop, Value*) -> Value* {
     14705            return loop->appendNew<CCallValue>(
     14706                proc, Int32, Origin(), Effects::none(),
     14707                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(oneFunction)),
     14708                loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     14709        });
     14710   
     14711    unsigned callCount = 0;
     14712    compileAndRun<void>(proc, &callCount);
     14713    CHECK_EQ(callCount, 1u);
     14714}
     14715
     14716void testLICMPureSideExits()
     14717{
     14718    Procedure proc;
     14719    generateLoop(
     14720        proc,
     14721        [&] (BasicBlock* loop, Value*) -> Value* {
     14722            Effects effects = Effects::none();
     14723            effects.exitsSideways = true;
     14724            loop->appendNew<CCallValue>(
     14725                proc, Void, Origin(), effects,
     14726                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(noOpFunction)));
     14727
     14728            return loop->appendNew<CCallValue>(
     14729                proc, Int32, Origin(), Effects::none(),
     14730                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(oneFunction)),
     14731                loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     14732        });
     14733   
     14734    unsigned callCount = 0;
     14735    compileAndRun<void>(proc, &callCount);
     14736    CHECK_EQ(callCount, 1u);
     14737}
     14738
     14739void testLICMPureWritesPinned()
     14740{
     14741    Procedure proc;
     14742    generateLoop(
     14743        proc,
     14744        [&] (BasicBlock* loop, Value*) -> Value* {
     14745            Effects effects = Effects::none();
     14746            effects.writesPinned = true;
     14747            loop->appendNew<CCallValue>(
     14748                proc, Void, Origin(), effects,
     14749                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(noOpFunction)));
     14750
     14751            return loop->appendNew<CCallValue>(
     14752                proc, Int32, Origin(), Effects::none(),
     14753                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(oneFunction)),
     14754                loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     14755        });
     14756   
     14757    unsigned callCount = 0;
     14758    compileAndRun<void>(proc, &callCount);
     14759    CHECK_EQ(callCount, 1u);
     14760}
     14761
     14762void testLICMPureWrites()
     14763{
     14764    Procedure proc;
     14765    generateLoop(
     14766        proc,
     14767        [&] (BasicBlock* loop, Value*) -> Value* {
     14768            Effects effects = Effects::none();
     14769            effects.writes = HeapRange(63479);
     14770            loop->appendNew<CCallValue>(
     14771                proc, Void, Origin(), effects,
     14772                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(noOpFunction)));
     14773
     14774            return loop->appendNew<CCallValue>(
     14775                proc, Int32, Origin(), Effects::none(),
     14776                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(oneFunction)),
     14777                loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     14778        });
     14779   
     14780    unsigned callCount = 0;
     14781    compileAndRun<void>(proc, &callCount);
     14782    CHECK_EQ(callCount, 1u);
     14783}
     14784
     14785void testLICMReadsLocalState()
     14786{
     14787    Procedure proc;
     14788    generateLoop(
     14789        proc,
     14790        [&] (BasicBlock* loop, Value*) -> Value* {
     14791            Effects effects = Effects::none();
     14792            effects.readsLocalState = true;
     14793            return loop->appendNew<CCallValue>(
     14794                proc, Int32, Origin(), effects,
     14795                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(oneFunction)),
     14796                loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     14797        });
     14798   
     14799    unsigned callCount = 0;
     14800    compileAndRun<void>(proc, &callCount);
     14801    CHECK_EQ(callCount, 100u); // We'll fail to hoist because the loop has Upsilons.
     14802}
     14803
     14804void testLICMReadsPinned()
     14805{
     14806    Procedure proc;
     14807    generateLoop(
     14808        proc,
     14809        [&] (BasicBlock* loop, Value*) -> Value* {
     14810            Effects effects = Effects::none();
     14811            effects.readsPinned = true;
     14812            return loop->appendNew<CCallValue>(
     14813                proc, Int32, Origin(), effects,
     14814                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(oneFunction)),
     14815                loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     14816        });
     14817   
     14818    unsigned callCount = 0;
     14819    compileAndRun<void>(proc, &callCount);
     14820    CHECK_EQ(callCount, 1u);
     14821}
     14822
     14823void testLICMReads()
     14824{
     14825    Procedure proc;
     14826    generateLoop(
     14827        proc,
     14828        [&] (BasicBlock* loop, Value*) -> Value* {
     14829            Effects effects = Effects::none();
     14830            effects.reads = HeapRange::top();
     14831            return loop->appendNew<CCallValue>(
     14832                proc, Int32, Origin(), effects,
     14833                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(oneFunction)),
     14834                loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     14835        });
     14836   
     14837    unsigned callCount = 0;
     14838    compileAndRun<void>(proc, &callCount);
     14839    CHECK_EQ(callCount, 1u);
     14840}
     14841
     14842void testLICMPureNotBackwardsDominant()
     14843{
     14844    Procedure proc;
     14845    auto array = makeArrayForLoops();
     14846    generateLoopNotBackwardsDominant(
     14847        proc, array,
     14848        [&] (BasicBlock* loop, Value*) -> Value* {
     14849            return loop->appendNew<CCallValue>(
     14850                proc, Int32, Origin(), Effects::none(),
     14851                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(oneFunction)),
     14852                loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     14853        });
     14854   
     14855    unsigned callCount = 0;
     14856    compileAndRun<void>(proc, &callCount);
     14857    CHECK_EQ(callCount, 1u);
     14858}
     14859
     14860void testLICMPureFoiledByChild()
     14861{
     14862    Procedure proc;
     14863    generateLoop(
     14864        proc,
     14865        [&] (BasicBlock* loop, Value* index) -> Value* {
     14866            return loop->appendNew<CCallValue>(
     14867                proc, Int32, Origin(), Effects::none(),
     14868                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(oneFunction)),
     14869                loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
     14870                index);
     14871        });
     14872   
     14873    unsigned callCount = 0;
     14874    compileAndRun<void>(proc, &callCount);
     14875    CHECK_EQ(callCount, 100u);
     14876}
     14877
     14878void testLICMPureNotBackwardsDominantFoiledByChild()
     14879{
     14880    Procedure proc;
     14881    auto array = makeArrayForLoops();
     14882    generateLoopNotBackwardsDominant(
     14883        proc, array,
     14884        [&] (BasicBlock* loop, Value* index) -> Value* {
     14885            return loop->appendNew<CCallValue>(
     14886                proc, Int32, Origin(), Effects::none(),
     14887                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(oneFunction)),
     14888                loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0),
     14889                index);
     14890        });
     14891   
     14892    unsigned callCount = 0;
     14893    compileAndRun<void>(proc, &callCount);
     14894    CHECK_EQ(callCount, 50u);
     14895}
     14896
     14897void testLICMExitsSideways()
     14898{
     14899    Procedure proc;
     14900    generateLoop(
     14901        proc,
     14902        [&] (BasicBlock* loop, Value*) -> Value* {
     14903            Effects effects = Effects::none();
     14904            effects.exitsSideways = true;
     14905            return loop->appendNew<CCallValue>(
     14906                proc, Int32, Origin(), effects,
     14907                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(oneFunction)),
     14908                loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     14909        });
     14910   
     14911    unsigned callCount = 0;
     14912    compileAndRun<void>(proc, &callCount);
     14913    CHECK_EQ(callCount, 100u);
     14914}
     14915
     14916void testLICMWritesLocalState()
     14917{
     14918    Procedure proc;
     14919    generateLoop(
     14920        proc,
     14921        [&] (BasicBlock* loop, Value*) -> Value* {
     14922            Effects effects = Effects::none();
     14923            effects.writesLocalState = true;
     14924            return loop->appendNew<CCallValue>(
     14925                proc, Int32, Origin(), effects,
     14926                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(oneFunction)),
     14927                loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     14928        });
     14929   
     14930    unsigned callCount = 0;
     14931    compileAndRun<void>(proc, &callCount);
     14932    CHECK_EQ(callCount, 100u);
     14933}
     14934
     14935void testLICMWrites()
     14936{
     14937    Procedure proc;
     14938    generateLoop(
     14939        proc,
     14940        [&] (BasicBlock* loop, Value*) -> Value* {
     14941            Effects effects = Effects::none();
     14942            effects.writes = HeapRange(666);
     14943            return loop->appendNew<CCallValue>(
     14944                proc, Int32, Origin(), effects,
     14945                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(oneFunction)),
     14946                loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     14947        });
     14948   
     14949    unsigned callCount = 0;
     14950    compileAndRun<void>(proc, &callCount);
     14951    CHECK_EQ(callCount, 100u);
     14952}
     14953
     14954void testLICMFence()
     14955{
     14956    Procedure proc;
     14957    generateLoop(
     14958        proc,
     14959        [&] (BasicBlock* loop, Value*) -> Value* {
     14960            Effects effects = Effects::none();
     14961            effects.fence = true;
     14962            return loop->appendNew<CCallValue>(
     14963                proc, Int32, Origin(), effects,
     14964                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(oneFunction)),
     14965                loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     14966        });
     14967   
     14968    unsigned callCount = 0;
     14969    compileAndRun<void>(proc, &callCount);
     14970    CHECK_EQ(callCount, 100u);
     14971}
     14972
     14973void testLICMWritesPinned()
     14974{
     14975    Procedure proc;
     14976    generateLoop(
     14977        proc,
     14978        [&] (BasicBlock* loop, Value*) -> Value* {
     14979            Effects effects = Effects::none();
     14980            effects.writesPinned = true;
     14981            return loop->appendNew<CCallValue>(
     14982                proc, Int32, Origin(), effects,
     14983                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(oneFunction)),
     14984                loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     14985        });
     14986   
     14987    unsigned callCount = 0;
     14988    compileAndRun<void>(proc, &callCount);
     14989    CHECK_EQ(callCount, 100u);
     14990}
     14991
     14992void testLICMControlDependent()
     14993{
     14994    Procedure proc;
     14995    generateLoop(
     14996        proc,
     14997        [&] (BasicBlock* loop, Value*) -> Value* {
     14998            Effects effects = Effects::none();
     14999            effects.controlDependent = true;
     15000            return loop->appendNew<CCallValue>(
     15001                proc, Int32, Origin(), effects,
     15002                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(oneFunction)),
     15003                loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     15004        });
     15005   
     15006    unsigned callCount = 0;
     15007    compileAndRun<void>(proc, &callCount);
     15008    CHECK_EQ(callCount, 1u);
     15009}
     15010
     15011void testLICMControlDependentNotBackwardsDominant()
     15012{
     15013    Procedure proc;
     15014    auto array = makeArrayForLoops();
     15015    generateLoopNotBackwardsDominant(
     15016        proc, array,
     15017        [&] (BasicBlock* loop, Value*) -> Value* {
     15018            Effects effects = Effects::none();
     15019            effects.controlDependent = true;
     15020            return loop->appendNew<CCallValue>(
     15021                proc, Int32, Origin(), effects,
     15022                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(oneFunction)),
     15023                loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     15024        });
     15025   
     15026    unsigned callCount = 0;
     15027    compileAndRun<void>(proc, &callCount);
     15028    CHECK_EQ(callCount, 50u);
     15029}
     15030
     15031void testLICMControlDependentSideExits()
     15032{
     15033    Procedure proc;
     15034    generateLoop(
     15035        proc,
     15036        [&] (BasicBlock* loop, Value*) -> Value* {
     15037            Effects effects = Effects::none();
     15038            effects.exitsSideways = true;
     15039            loop->appendNew<CCallValue>(
     15040                proc, Void, Origin(), effects,
     15041                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(noOpFunction)));
     15042           
     15043            effects = Effects::none();
     15044            effects.controlDependent = true;
     15045            return loop->appendNew<CCallValue>(
     15046                proc, Int32, Origin(), effects,
     15047                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(oneFunction)),
     15048                loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     15049        });
     15050   
     15051    unsigned callCount = 0;
     15052    compileAndRun<void>(proc, &callCount);
     15053    CHECK_EQ(callCount, 100u);
     15054}
     15055
     15056void testLICMReadsPinnedWritesPinned()
     15057{
     15058    Procedure proc;
     15059    generateLoop(
     15060        proc,
     15061        [&] (BasicBlock* loop, Value*) -> Value* {
     15062            Effects effects = Effects::none();
     15063            effects.writesPinned = true;
     15064            loop->appendNew<CCallValue>(
     15065                proc, Void, Origin(), effects,
     15066                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(noOpFunction)));
     15067           
     15068            effects = Effects::none();
     15069            effects.readsPinned = true;
     15070            return loop->appendNew<CCallValue>(
     15071                proc, Int32, Origin(), effects,
     15072                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(oneFunction)),
     15073                loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     15074        });
     15075   
     15076    unsigned callCount = 0;
     15077    compileAndRun<void>(proc, &callCount);
     15078    CHECK_EQ(callCount, 100u);
     15079}
     15080
     15081void testLICMReadsWritesDifferentHeaps()
     15082{
     15083    Procedure proc;
     15084    generateLoop(
     15085        proc,
     15086        [&] (BasicBlock* loop, Value*) -> Value* {
     15087            Effects effects = Effects::none();
     15088            effects.writes = HeapRange(6436);
     15089            loop->appendNew<CCallValue>(
     15090                proc, Void, Origin(), effects,
     15091                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(noOpFunction)));
     15092           
     15093            effects = Effects::none();
     15094            effects.reads = HeapRange(4886);
     15095            return loop->appendNew<CCallValue>(
     15096                proc, Int32, Origin(), effects,
     15097                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(oneFunction)),
     15098                loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     15099        });
     15100   
     15101    unsigned callCount = 0;
     15102    compileAndRun<void>(proc, &callCount);
     15103    CHECK_EQ(callCount, 1u);
     15104}
     15105
     15106void testLICMReadsWritesOverlappingHeaps()
     15107{
     15108    Procedure proc;
     15109    generateLoop(
     15110        proc,
     15111        [&] (BasicBlock* loop, Value*) -> Value* {
     15112            Effects effects = Effects::none();
     15113            effects.writes = HeapRange(6436, 74458);
     15114            loop->appendNew<CCallValue>(
     15115                proc, Void, Origin(), effects,
     15116                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(noOpFunction)));
     15117           
     15118            effects = Effects::none();
     15119            effects.reads = HeapRange(48864, 78239);
     15120            return loop->appendNew<CCallValue>(
     15121                proc, Int32, Origin(), effects,
     15122                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(oneFunction)),
     15123                loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     15124        });
     15125   
     15126    unsigned callCount = 0;
     15127    compileAndRun<void>(proc, &callCount);
     15128    CHECK_EQ(callCount, 100u);
     15129}
     15130
     15131void testLICMDefaultCall()
     15132{
     15133    Procedure proc;
     15134    generateLoop(
     15135        proc,
     15136        [&] (BasicBlock* loop, Value*) -> Value* {
     15137            return loop->appendNew<CCallValue>(
     15138                proc, Int32, Origin(),
     15139                loop->appendNew<ConstPtrValue>(proc, Origin(), bitwise_cast<void*>(oneFunction)),
     15140                loop->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     15141        });
     15142   
     15143    unsigned callCount = 0;
     15144    compileAndRun<void>(proc, &callCount);
     15145    CHECK_EQ(callCount, 100u);
    1459315146}
    1459415147
     
    1712917682    RUN(testLoadBaseIndexShift32());
    1713017683    RUN(testOptimizeMaterialization());
    17131    
     17684    RUN(testLICMPure());
     17685    RUN(testLICMPureSideExits());
     17686    RUN(testLICMPureWritesPinned());
     17687    RUN(testLICMPureWrites());
     17688    RUN(testLICMReadsLocalState());
     17689    RUN(testLICMReadsPinned());
     17690    RUN(testLICMReads());
     17691    RUN(testLICMPureNotBackwardsDominant());
     17692    RUN(testLICMPureFoiledByChild());
     17693    RUN(testLICMPureNotBackwardsDominantFoiledByChild());
     17694    RUN(testLICMExitsSideways());
     17695    RUN(testLICMWritesLocalState());
     17696    RUN(testLICMWrites());
     17697    RUN(testLICMWritesPinned());
     17698    RUN(testLICMFence());
     17699    RUN(testLICMControlDependent());
     17700    RUN(testLICMControlDependentNotBackwardsDominant());
     17701    RUN(testLICMControlDependentSideExits());
     17702    RUN(testLICMReadsPinnedWritesPinned());
     17703    RUN(testLICMReadsWritesDifferentHeaps());
     17704    RUN(testLICMReadsWritesOverlappingHeaps());
     17705    RUN(testLICMDefaultCall());
     17706
    1713217707    RUN(testAtomicWeakCAS<int8_t>());
    1713317708    RUN(testAtomicWeakCAS<int16_t>());
     
    1718217757    RUN(testFloatEqualOrUnorderedFoldingNaN());
    1718317758    RUN(testFloatEqualOrUnorderedDontFold());
    17184 
     17759   
    1718517760    RUN(testShuffleDoesntTrashCalleeSaves());
    1718617761
Note: See TracChangeset for help on using the changeset viewer.