@@ -548,7 +548,13 @@ static Value *emit_condition(jl_codectx_t &ctx, const jl_cgval_t &condV, const s
548548static void allocate_gc_frame (jl_codectx_t &ctx, BasicBlock *b0);
549549static void CreateTrap (IRBuilder<> &irbuilder);
550550static CallInst *emit_jlcall (jl_codectx_t &ctx, Value *theFptr, Value *theF,
551- jl_cgval_t *args, size_t nargs, CallingConv::ID cc);
551+ jl_cgval_t *args, size_t nargs,
552+ AttributeList Attrs, CallingConv::ID cc);
553+ static CallInst *emit_jlcall (jl_codectx_t &ctx, Value *theFptr, Value *theF,
554+ jl_cgval_t *args, size_t nargs) {
555+ AttributeList Attrs;
556+ return emit_jlcall (ctx, theFptr, theF, args, nargs, Attrs, JLCALL_F_CC);
557+ }
552558
553559static Value *literal_pointer_val (jl_codectx_t &ctx, jl_value_t *p);
554560static GlobalVariable *prepare_global_in (Module *M, GlobalVariable *G);
@@ -2182,7 +2188,7 @@ static jl_cgval_t emit_getfield(jl_codectx_t &ctx, const jl_cgval_t &strct, jl_s
21822188 strct,
21832189 mark_julia_const ((jl_value_t *)name)
21842190 };
2185- Value *result = emit_jlcall (ctx, jlgetfield_func, maybe_decay_untracked (V_null), myargs_array, 2 , JLCALL_F_CC );
2191+ Value *result = emit_jlcall (ctx, jlgetfield_func, maybe_decay_untracked (V_null), myargs_array, 2 );
21862192 return mark_julia_type (ctx, result, true , jl_any_type);
21872193}
21882194
@@ -3022,7 +3028,8 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
30223028}
30233029
30243030static CallInst *emit_jlcall (jl_codectx_t &ctx, Value *theFptr, Value *theF,
3025- jl_cgval_t *argv, size_t nargs, CallingConv::ID cc)
3031+ jl_cgval_t *argv, size_t nargs,
3032+ AttributeList Attrs, CallingConv::ID cc)
30263033{
30273034 // emit arguments
30283035 SmallVector<Value*, 3 > theArgs;
@@ -3040,7 +3047,8 @@ static CallInst *emit_jlcall(jl_codectx_t &ctx, Value *theFptr, Value *theF,
30403047 CallInst *result = ctx.builder .CreateCall (FTy,
30413048 ctx.builder .CreateBitCast (prepare_call (theFptr), FTy->getPointerTo ()),
30423049 theArgs);
3043- add_return_attr (result, Attribute::NonNull);
3050+ Attrs = Attrs.addAttribute (jl_LLVMContext, AttributeList::ReturnIndex, Attribute::NonNull);
3051+ result->setAttributes (Attrs);
30443052 result->setCallingConv (cc);
30453053 return result;
30463054}
@@ -3052,7 +3060,14 @@ static jl_cgval_t emit_call_specfun_other(jl_codectx_t &ctx, jl_code_instance_t
30523060 // emit specialized call site
30533061 jl_value_t *jlretty = codeinst->rettype ;
30543062 jl_returninfo_t returninfo = get_specsig_function (jl_Module, specFunctionObject, codeinst->def ->specTypes , jlretty);
3055- FunctionType *cft = returninfo.decl ->getFunctionType ();
3063+ Function *f = returninfo.decl ;
3064+ FunctionType *cft = f->getFunctionType ();
3065+ if (codeinst->def ->def .method ->pure ) {
3066+ // pure marked functions don't have side-effects, nor observe them
3067+ f->addFnAttr (Thunk);
3068+ f->addFnAttr (Attribute::ReadNone);
3069+ f->addFnAttr (Attribute::NoUnwind);
3070+ }
30563071
30573072 size_t nfargs = cft->getNumParams ();
30583073 Value **argvals = (Value**)alloca (nfargs * sizeof (Value*));
@@ -3116,8 +3131,8 @@ static jl_cgval_t emit_call_specfun_other(jl_codectx_t &ctx, jl_code_instance_t
31163131 idx++;
31173132 }
31183133 assert (idx == nfargs);
3119- CallInst *call = ctx.builder .CreateCall (returninfo. decl , ArrayRef<Value*>(&argvals[0 ], nfargs));
3120- call->setAttributes (returninfo. decl ->getAttributes ());
3134+ CallInst *call = ctx.builder .CreateCall (f , ArrayRef<Value*>(&argvals[0 ], nfargs));
3135+ call->setAttributes (f ->getAttributes ());
31213136
31223137 jl_cgval_t retval;
31233138 switch (returninfo.cc ) {
@@ -3157,7 +3172,7 @@ static jl_cgval_t emit_call_specfun_other(jl_codectx_t &ctx, jl_code_instance_t
31573172 return retval;
31583173}
31593174
3160- static jl_cgval_t emit_call_specfun_boxed (jl_codectx_t &ctx, StringRef specFunctionObject,
3175+ static jl_cgval_t emit_call_specfun_boxed (jl_codectx_t &ctx, jl_code_instance_t *codeinst, StringRef specFunctionObject,
31613176 jl_cgval_t *argv, size_t nargs, jl_value_t *inferred_retty)
31623177{
31633178 auto theFptr = jl_Module->getOrInsertFunction (specFunctionObject, jl_func_sig)
@@ -3166,11 +3181,20 @@ static jl_cgval_t emit_call_specfun_boxed(jl_codectx_t &ctx, StringRef specFunct
31663181#else
31673182 ;
31683183#endif
3169- if (auto F = dyn_cast<Function>(theFptr->stripPointerCasts ())) {
3170- add_return_attr (F, Attribute::NonNull);
3171- F->addFnAttr (Thunk);
3172- }
3173- Value *ret = emit_jlcall (ctx, theFptr, nullptr , argv, nargs, JLCALL_F_CC);
3184+ AttributeList Attrs;
3185+ auto F = dyn_cast<Function>(theFptr->stripPointerCasts ());
3186+ if (F)
3187+ Attrs = F->getAttributes ();
3188+ Attrs = Attrs.addAttribute (jl_LLVMContext, AttributeList::ReturnIndex, Attribute::NonNull)
3189+ .addAttribute (jl_LLVMContext, AttributeList::FunctionIndex, Thunk);
3190+ if (codeinst->def ->def .method ->pure ) {
3191+ // pure marked functions don't have side-effects, nor observe them
3192+ Attrs = Attrs.addAttribute (jl_LLVMContext, AttributeList::FunctionIndex, Attribute::ReadNone)
3193+ .addAttribute (jl_LLVMContext, AttributeList::FunctionIndex, Attribute::NoUnwind);
3194+ }
3195+ if (F)
3196+ F->setAttributes (Attrs);
3197+ Value *ret = emit_jlcall (ctx, theFptr, nullptr , argv, nargs, Attrs, JLCALL_F_CC);
31743198 return mark_julia_type (ctx, ret, true , inferred_retty);
31753199}
31763200
@@ -3204,7 +3228,7 @@ static jl_cgval_t emit_invoke(jl_codectx_t &ctx, jl_expr_t *ex, jl_value_t *rt)
32043228 }
32053229 if (decls.functionObject ) {
32063230 if (!strcmp (decls.functionObject , " jl_fptr_args" )) {
3207- result = emit_call_specfun_boxed (ctx, decls.specFunctionObject , argv, nargs, rt);
3231+ result = emit_call_specfun_boxed (ctx, codeinst, decls.specFunctionObject , argv, nargs, rt);
32083232 handled = true ;
32093233 }
32103234 else if (!!strcmp (decls.functionObject , " jl_fptr_sparam" )) {
@@ -3216,7 +3240,7 @@ static jl_cgval_t emit_invoke(jl_codectx_t &ctx, jl_expr_t *ex, jl_value_t *rt)
32163240 }
32173241 }
32183242 if (!handled) {
3219- Value *r = emit_jlcall (ctx, prepare_call (jlinvoke_func), boxed (ctx, lival), argv, nargs, JLCALL_F2_CC);
3243+ Value *r = emit_jlcall (ctx, prepare_call (jlinvoke_func), boxed (ctx, lival), argv, nargs, jlinvoke_func-> getAttributes (), JLCALL_F2_CC);
32203244 result = mark_julia_type (ctx, r, true , rt);
32213245 }
32223246 if (result.typ == jl_bottom_type)
@@ -3257,13 +3281,13 @@ static jl_cgval_t emit_call(jl_codectx_t &ctx, jl_expr_t *ex, jl_value_t *rt)
32573281 std::map<jl_fptr_args_t , Function*>::iterator it = builtin_func_map.find (jl_get_builtin_fptr (f.constant ));
32583282 if (it != builtin_func_map.end ()) {
32593283 Value *theFptr = it->second ;
3260- Value *ret = emit_jlcall (ctx, theFptr, maybe_decay_untracked (V_null), &argv[1 ], nargs - 1 , JLCALL_F_CC );
3284+ Value *ret = emit_jlcall (ctx, theFptr, maybe_decay_untracked (V_null), &argv[1 ], nargs - 1 );
32613285 return mark_julia_type (ctx, ret, true , rt);
32623286 }
32633287 }
32643288
32653289 // emit function and arguments
3266- Value *callval = emit_jlcall (ctx, jlapplygeneric_func, nullptr , argv, nargs, JLCALL_F_CC );
3290+ Value *callval = emit_jlcall (ctx, jlapplygeneric_func, nullptr , argv, nargs);
32673291 return mark_julia_type (ctx, callval, true , rt);
32683292}
32693293
@@ -4128,7 +4152,7 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaval)
41284152 assert (nargs <= jl_datatype_nfields (jl_tparam0 (ty)) + 1 );
41294153 return emit_new_struct (ctx, jl_tparam0 (ty), nargs - 1 , &argv[1 ]);
41304154 }
4131- Value *val = emit_jlcall (ctx, jlnew_func, nullptr , argv, nargs, JLCALL_F_CC );
4155+ Value *val = emit_jlcall (ctx, jlnew_func, nullptr , argv, nargs);
41324156 // temporarily mark as `Any`, expecting `emit_ssaval_assign` to update
41334157 // it to the inferred type.
41344158 return mark_julia_type (ctx, val, true , (jl_value_t *)jl_any_type);
@@ -4325,7 +4349,7 @@ static void emit_cfunc_invalidate(
43254349 }
43264350 }
43274351 assert (AI == gf_thunk->arg_end ());
4328- Value *gf_ret = emit_jlcall (ctx, jlapplygeneric_func, nullptr , myargs, nargs, JLCALL_F_CC );
4352+ Value *gf_ret = emit_jlcall (ctx, jlapplygeneric_func, nullptr , myargs, nargs);
43294353 jl_cgval_t gf_retbox = mark_julia_type (ctx, gf_ret, true , jl_any_type);
43304354 jl_value_t *astrt = codeinst->rettype ;
43314355 if (cc != jl_returninfo_t ::Boxed) {
@@ -4697,11 +4721,11 @@ static Function* gen_cfun_wrapper(
46974721 // for jlcall, we need to pass the function object even if it is a ghost.
46984722 Value *theF = boxed (ctx, inputargs[0 ]);
46994723 assert (theF);
4700- ret_jlcall = emit_jlcall (ctx, theFptr, theF, &inputargs[1 ], nargs, JLCALL_F_CC );
4724+ ret_jlcall = emit_jlcall (ctx, theFptr, theF, &inputargs[1 ], nargs);
47014725 ctx.builder .CreateBr (b_after);
47024726 ctx.builder .SetInsertPoint (b_generic);
47034727 }
4704- Value *ret = emit_jlcall (ctx, prepare_call (jlapplygeneric_func), NULL , inputargs, nargs + 1 , JLCALL_F_CC );
4728+ Value *ret = emit_jlcall (ctx, prepare_call (jlapplygeneric_func), NULL , inputargs, nargs + 1 );
47054729 if (age_ok) {
47064730 ctx.builder .CreateBr (b_after);
47074731 ctx.builder .SetInsertPoint (b_after);
@@ -5998,7 +6022,7 @@ static std::unique_ptr<Module> emit_function(
59986022 emit_varinfo_assign (ctx, vi, tuple);
59996023 } else {
60006024 Value *vtpl = emit_jlcall (ctx, prepare_call (jltuple_func), maybe_decay_untracked (V_null),
6001- vargs, ctx.nvargs , JLCALL_F_CC );
6025+ vargs, ctx.nvargs );
60026026 jl_cgval_t tuple = mark_julia_type (ctx, vtpl, true , vi.value .typ );
60036027 emit_varinfo_assign (ctx, vi, tuple);
60046028 }
0 commit comments