| 791 | } |
| 792 | |
| 793 | bool InlinePass::IsInlinableFunction(Function* func) { |
| 794 | // We can only inline a function if it has blocks. |
| 795 | if (func->cbegin() == func->cend()) return false; |
| 796 | |
| 797 | // Do not inline functions with DontInline flag. |
| 798 | if (func->control_mask() & uint32_t(spv::FunctionControlMask::DontInline)) { |
| 799 | return false; |
| 800 | } |
| 801 | |
| 802 | // Do not inline functions with returns in loops. Currently early return |
| 803 | // functions are inlined by wrapping them in a one trip loop and implementing |
| 804 | // the returns as a branch to the loop's merge block. However, this can only |
| 805 | // done validly if the return was not in a loop in the original function. |
| 806 | // Also remember functions with multiple (early) returns. |
| 807 | AnalyzeReturns(func); |
| 808 | if (no_return_in_loop_.find(func->result_id()) == no_return_in_loop_.cend()) { |
| 809 | return false; |
| 810 | } |
| 811 | |
| 812 | if (func->IsRecursive()) { |
| 813 | return false; |
| 814 | } |
| 815 | |
| 816 | // Do not inline functions with an abort instruction if they are called from a |
| 817 | // continue construct. If it is inlined into a continue construct the backedge |
| 818 | // will no longer post-dominate the continue target, which is invalid. An |
| 819 | // `OpUnreachable` is acceptable because it will not change post-dominance if |
| 820 | // it is statically unreachable. |
| 821 | bool func_is_called_from_continue = |
| 822 | funcs_called_from_continue_.count(func->result_id()) != 0; |
| 823 | |
| 824 | if (func_is_called_from_continue && ContainsAbortOtherThanUnreachable(func)) { |
| 825 | return false; |
| 826 | } |
| 827 | |
| 828 | return true; |
| 829 | } |
| 830 | |
| 831 | bool InlinePass::ContainsAbortOtherThanUnreachable(Function* func) const { |
| 832 | return !func->WhileEachInst([](Instruction* inst) { |
nothing calls this directly
no test coverage detected