diff --git a/src/codegen.cpp b/src/codegen.cpp index cc576f7c19ca1..e577faf1b87bb 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -355,10 +355,12 @@ typedef struct { typedef struct { Function *f; std::map *vars; + std::map *SAvars; std::map *passedArguments; std::map *closureEnv; std::map *isAssigned; std::map *isCaptured; + std::map *isSA; std::map *escapes; std::map *arrayvars; std::set *volatilevars; @@ -1754,6 +1756,9 @@ static Value *emit_var(jl_sym_t *sym, jl_value_t *ty, jl_codectx_t *ctx, return arg; } jl_binding_t *jbp; + Value *ssaval = (*ctx->SAvars)[sym]; + if (ssaval != NULL) + return ssaval; Value *bp = var_binding_pointer(sym, &jbp, false, ctx); if (arg != NULL || // arguments are always defined (!is_var_closed(sym, ctx) && @@ -1807,6 +1812,13 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) assign_arrayvar(*av, rval); } } + if ((*ctx->isSA)[s] && jl_is_leaf_type((*ctx->declTypes)[s]) && + (*ctx->vars)[s] != NULL && !isBoxed(s,ctx) && + rval->getType() == jl_pvalue_llvmt && + (*ctx->passedArguments)[s] == NULL) { + // use SSA value instead of GC frame load for var access + (*ctx->SAvars)[s] = rval; + } } } @@ -2271,11 +2283,13 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle) //JL_PRINTF((jl_value_t*)ast); //JL_PRINTF(JL_STDOUT, "\n"); std::map localVars; + std::map SAvars; //std::map argumentMap; std::map passedArgumentMap; std::map closureEnv; std::map isAssigned; std::map isCaptured; + std::map isSA; std::map escapes; std::map arrayvars; std::set volvars; @@ -2284,11 +2298,13 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle) std::map handlers; jl_codectx_t ctx; ctx.vars = &localVars; + ctx.SAvars = &SAvars; //ctx.arguments = &argumentMap; ctx.passedArguments = &passedArgumentMap; ctx.closureEnv = &closureEnv; ctx.isAssigned = &isAssigned; ctx.isCaptured = &isCaptured; + ctx.isSA = &isSA; ctx.escapes = &escapes; ctx.arrayvars = &arrayvars; ctx.volatilevars = &volvars; @@ -2328,6 +2344,7 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle) bool iscapt = (jl_vinfo_capt(vi)!=0); isCaptured[vname] = iscapt; escapes[vname] = iscapt; + isSA[vname] = (jl_vinfo_sa(vi)!=0); declTypes[vname] = jl_cellref(vi,1); } vinfos = jl_lam_capt(ast); diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index def819af2f56c..e8d9c45cf022f 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -2286,6 +2286,7 @@ So far only the second case can actually occur. (define vinfo:name car) (define vinfo:type cadr) (define (vinfo:capt v) (< 0 (logand (caddr v) 1))) +(define (vinfo:asgn v) (< 0 (logand (caddr v) 2))) (define (vinfo:const v) (< 0 (logand (caddr v) 8))) (define (vinfo:set-type! v t) (set-car! (cdr v) t)) ;; record whether var is captured @@ -2308,6 +2309,11 @@ So far only the second case can actually occur. (if a (logior (caddr v) 8) (logand (caddr v) -9)))) +;; whether var is assigned once +(define (vinfo:set-sa! v a) (set-car! (cddr v) + (if a + (logior (caddr v) 16) + (logand (caddr v) -17)))) (define var-info-for assq) @@ -2332,6 +2338,9 @@ So far only the second case can actually occur. (let ((vi (var-info-for (cadr e) env))) (if vi (begin + (if (vinfo:asgn vi) + (vinfo:set-sa! vi #f) + (vinfo:set-sa! vi #t)) (vinfo:set-asgn! vi #t) (if (assq (car vi) captvars) (vinfo:set-iasg! vi #t))))) diff --git a/src/julia.h b/src/julia.h index 3cad47d907102..1591a32d6aec3 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1001,6 +1001,11 @@ static inline int jl_vinfo_assigned_inner(jl_array_t *vi) return (jl_unbox_long(jl_cellref(vi,2))&4)!=0; } +static inline int jl_vinfo_sa(jl_array_t *vi) +{ + return (jl_unbox_long(jl_cellref(vi,2))&16)!=0; +} + // for writing julia functions in C #define JL_CALLABLE(name) \ jl_value_t *name(jl_value_t *F, jl_value_t **args, uint32_t nargs)