|
36 | 36 | function test_expand_error(ex)
|
37 | 37 | @test_throws LoadError macroexpand(@__MODULE__, ex)
|
38 | 38 | end
|
| 39 | + |
| 40 | +mutable struct ErrorCounterTestSet <: Test.AbstractTestSet |
| 41 | + passcount::Int |
| 42 | + errorcount::Int |
| 43 | + failcount::Int |
| 44 | +end |
| 45 | +ErrorCounterTestSet(args...; kws...) = ErrorCounterTestSet(0,0,0) |
| 46 | +Test.finish(ts::ErrorCounterTestSet) = ts |
| 47 | +Test.record(ts::ErrorCounterTestSet, ::Test.Pass) = (ts.passcount += 1) |
| 48 | +Test.record(ts::ErrorCounterTestSet, ::Test.Error) = (ts.errorcount += 1) |
| 49 | +Test.record(ts::ErrorCounterTestSet, ::Test.Fail) = (ts.failcount += 1) |
| 50 | + |
| 51 | +""" |
| 52 | + @test_inlined f(x,y, ...) |
| 53 | +
|
| 54 | +Check that the (optimized) llvm code generated for the expression |
| 55 | +`f(x,y,...)` contains no `call` instructions. |
| 56 | +
|
| 57 | +Note that LLVM IR can contain `call` instructions to intrinsics which don't |
| 58 | +make it into the native code, so this can be overly eager in declaring a |
| 59 | +a lack of complete inlining. |
| 60 | +""" |
| 61 | +macro test_inlined(ex) |
| 62 | + ex_orig = ex |
| 63 | + ex = macroexpand(@__MODULE__, :(@code_llvm $ex)) |
| 64 | + expr = quote |
| 65 | + code_str = sprint() do io |
| 66 | + code_llvm(io, $(map(esc, ex.args[2:end])...)) |
| 67 | + end |
| 68 | + # Crude detection of call instructions remaining within what should be |
| 69 | + # fully inlined code. |
| 70 | + # |
| 71 | + # TODO: Figure out some better pattern matching; LLVM IR can contain |
| 72 | + # calls to intrinsics, so this will sometimes/often fail even when the |
| 73 | + # native code has no call instructions. |
| 74 | + @test !occursin("call", code_str) |
| 75 | + end |
| 76 | + @assert expr.args[4].head == :macrocall |
| 77 | + expr.args[4].args[2] = __source__ |
| 78 | + expr |
| 79 | +end |
| 80 | + |
| 81 | +should_be_inlined(x) = x*x |
| 82 | +@noinline _should_not_be_inlined(x) = x*x |
| 83 | +should_not_be_inlined(x) = _should_not_be_inlined(x) |
| 84 | + |
| 85 | +@testset "@test_inlined" begin |
| 86 | + @test_inlined should_be_inlined(1) |
| 87 | + ts = @testset ErrorCounterTestSet "" begin |
| 88 | + @test_inlined should_not_be_inlined(1) |
| 89 | + end |
| 90 | + @test ts.errorcount == 0 && ts.failcount == 1 && ts.passcount == 0 |
| 91 | +end |
| 92 | + |
0 commit comments