| /* |
| * Copyright (C) 2015-2021 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #pragma once |
| |
| #if ENABLE(B3_JIT) |
| |
| #include "AirArgInlines.h" |
| #include "AirBlockWorklist.h" |
| #include "AirCode.h" |
| #include "AirInstInlines.h" |
| #include "AirTmpInlines.h" |
| #include <wtf/CommaPrinter.h> |
| #include <wtf/Vector.h> |
| |
| namespace JSC { namespace B3 { namespace Air { |
| |
| class Code; |
| |
| // Computes the number of uses of a tmp based on frequency of execution. The frequency of blocks |
| // that are only reachable by rare edges is scaled by Options::rareBlockPenalty(). |
| class UseCounts { |
| public: |
| UseCounts(Code& code) |
| { |
| // Find non-rare blocks. |
| BlockWorklist fastWorklist; |
| fastWorklist.push(code[0]); |
| while (BasicBlock* block = fastWorklist.pop()) { |
| for (FrequentedBlock& successor : block->successors()) { |
| if (!successor.isRare()) |
| fastWorklist.push(successor.block()); |
| } |
| } |
| |
| unsigned gpArraySize = AbsoluteTmpMapper<GP>::absoluteIndex(code.numTmps(GP)); |
| m_gpNumWarmUsesAndDefs.resize(gpArraySize); |
| m_gpConstDefs.ensureSize(gpArraySize); |
| unsigned fpArraySize = AbsoluteTmpMapper<FP>::absoluteIndex(code.numTmps(FP)); |
| m_fpNumWarmUsesAndDefs.resize(fpArraySize); |
| m_fpConstDefs.ensureSize(fpArraySize); |
| |
| for (BasicBlock* block : code) { |
| double frequency = block->frequency(); |
| if (!fastWorklist.saw(block)) |
| frequency *= Options::rareBlockPenalty(); |
| for (Inst& inst : *block) { |
| inst.forEach<Tmp>( |
| [&] (Tmp& tmp, Arg::Role role, Bank bank, Width) { |
| |
| if (Arg::isWarmUse(role) || Arg::isAnyDef(role)) { |
| if (bank == GP) |
| m_gpNumWarmUsesAndDefs[AbsoluteTmpMapper<GP>::absoluteIndex(tmp)] += frequency; |
| else |
| m_fpNumWarmUsesAndDefs[AbsoluteTmpMapper<FP>::absoluteIndex(tmp)] += frequency; |
| } |
| }); |
| |
| if ((inst.kind.opcode == Move || inst.kind.opcode == Move32) |
| && inst.args[0].isSomeImm() |
| && inst.args[1].is<Tmp>()) { |
| Tmp tmp = inst.args[1].as<Tmp>(); |
| if (tmp.bank() == GP) |
| m_gpConstDefs.quickSet(AbsoluteTmpMapper<GP>::absoluteIndex(tmp)); |
| else |
| m_fpConstDefs.quickSet(AbsoluteTmpMapper<FP>::absoluteIndex(tmp)); |
| } |
| } |
| } |
| } |
| |
| template<Bank bank> |
| bool isConstDef(unsigned absoluteIndex) const |
| { |
| if (bank == GP) |
| return m_gpConstDefs.quickGet(absoluteIndex); |
| return m_fpConstDefs.quickGet(absoluteIndex); |
| } |
| |
| template<Bank bank> |
| float numWarmUsesAndDefs(unsigned absoluteIndex) const |
| { |
| if (bank == GP) |
| return m_gpNumWarmUsesAndDefs[absoluteIndex]; |
| return m_fpNumWarmUsesAndDefs[absoluteIndex]; |
| } |
| |
| void dump(PrintStream& out) const |
| { |
| CommaPrinter comma(", "); |
| for (unsigned i = 0; i < m_gpNumWarmUsesAndDefs.size(); ++i) |
| out.print(comma, AbsoluteTmpMapper<GP>::tmpFromAbsoluteIndex(i), "=> {numWarmUsesAndDefs=", m_gpNumWarmUsesAndDefs[i], ", isConstDef=", m_gpConstDefs.quickGet(i), "}"); |
| for (unsigned i = 0; i < m_fpNumWarmUsesAndDefs.size(); ++i) |
| out.print(comma, AbsoluteTmpMapper<FP>::tmpFromAbsoluteIndex(i), "=> {numWarmUsesAndDefs=", m_fpNumWarmUsesAndDefs[i], ", isConstDef=", m_fpConstDefs.quickGet(i), "}"); |
| } |
| |
| private: |
| Vector<float> m_gpNumWarmUsesAndDefs; |
| Vector<float> m_fpNumWarmUsesAndDefs; |
| BitVector m_gpConstDefs; |
| BitVector m_fpConstDefs; |
| }; |
| |
| } } } // namespace JSC::B3::Air |
| |
| #endif // ENABLE(B3_JIT) |