diff --git a/base/intfuncs.jl b/base/intfuncs.jl index bc305b48664d7d..d10ee3a781d3b3 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -195,6 +195,11 @@ end ^(x::Number, p::Integer) = power_by_squaring(x,p) ^(x, p::Integer) = power_by_squaring(x,p) +# x^p for small literal p is lowered to x^Val{p}, +# to enable compile-time optimizations specialized to p. +# However, we still need a fallback that calls the general ^: +^{p}(x, ::Type{Val{p}}) = x^p + # b^p mod m """ diff --git a/src/ast.c b/src/ast.c index f8950299809919..211d7265d4bf06 100644 --- a/src/ast.c +++ b/src/ast.c @@ -245,12 +245,26 @@ value_t fl_julia_scalar(fl_context_t *fl_ctx, value_t *args, uint32_t nargs) return fl_ctx->F; } +value_t fl_julia_smallnum(fl_context_t *fl_ctx, value_t *args, uint32_t nargs) +{ + argcount(fl_ctx, "julia-smallnum?", nargs, 1); + if (isfixnum(args[0]) && numval(args[0]) < 32 && numval(args[0]) > -32) + return fl_ctx->T; + else if (iscvalue(args[0]) && fl_ctx->jl_sym == cv_type((cvalue_t*)ptr(args[0]))) { + jl_value_t *v = *(jl_value_t**)cptr(args[0]); + if (jl_is_long(v) && jl_unbox_long(v) < 32 && jl_unbox_long(v) > -32) + return fl_ctx->T; + } + return fl_ctx->F; +} + static const builtinspec_t julia_flisp_ast_ext[] = { { "defined-julia-global", fl_defined_julia_global }, { "invoke-julia-macro", fl_invoke_julia_macro }, { "current-julia-module", fl_current_julia_module }, { "current-julia-module-counter", fl_current_module_counter }, { "julia-scalar?", fl_julia_scalar }, + { "julia-smallnum?", fl_julia_smallnum }, { NULL, NULL } }; diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 39536bdac5e7e6..2bd9dce4aec41d 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -2050,6 +2050,10 @@ (expand-forms `(call (core _apply) ,f ,@(tuple-wrap argl '()))))) + ((and (eq? f '^) (length= e 4) (julia-smallnum? (cadddr e))) + (expand-forms + `(call ^ ,(caddr e) (call (core apply_type) (top Val) ,(cadddr e))))) + ((and (eq? f '*) (length= e 4)) (expand-transposed-op e