@@ -2375,25 +2375,18 @@ static Value *emit_box_compare(jl_codectx_t &ctx, const jl_cgval_t &arg1, const
2375
2375
Value *nullcheck1, Value *nullcheck2)
2376
2376
{
2377
2377
if (jl_pointer_egal (arg1.typ ) || jl_pointer_egal (arg2.typ )) {
2378
- assert ((arg1.isboxed || arg1.constant ) && (arg2.isboxed || arg2.constant ) &&
2379
- " Expected unboxed cases to be handled earlier" );
2380
- Value *varg1 = arg1.constant ? literal_pointer_val (ctx, arg1.constant ) : arg1.V ;
2381
- Value *varg2 = arg2.constant ? literal_pointer_val (ctx, arg2.constant ) : arg2.V ;
2382
- varg1 = maybe_decay_tracked (ctx, varg1);
2383
- varg2 = maybe_decay_tracked (ctx, varg2);
2384
- if (cast<PointerType>(varg1->getType ())->getAddressSpace () != cast<PointerType>(varg2->getType ())->getAddressSpace ()) {
2385
- varg1 = decay_derived (ctx, varg1);
2386
- varg2 = decay_derived (ctx, varg2);
2387
- }
2388
- return ctx.builder .CreateICmpEQ (emit_bitcast (ctx, varg1, T_pint8),
2389
- emit_bitcast (ctx, varg2, T_pint8));
2378
+ // if we can be certain we won't try to load from the pointer (because
2379
+ // we know boxed is trivial), we can skip the separate null checks
2380
+ // and just do the ICmpEQ test
2381
+ if (!arg1.TIndex && !arg2.TIndex )
2382
+ nullcheck1 = nullcheck2 = nullptr ;
2390
2383
}
2391
-
2392
2384
return emit_nullcheck_guard2 (ctx, nullcheck1, nullcheck2, [&] {
2393
- Value *varg1 = arg1.constant ? literal_pointer_val (ctx, arg1.constant ) : maybe_bitcast (ctx, value_to_pointer (ctx, arg1).V , T_pjlvalue);
2394
- Value *varg2 = arg2.constant ? literal_pointer_val (ctx, arg2.constant ) : maybe_bitcast (ctx, value_to_pointer (ctx, arg2).V , T_pjlvalue);
2395
- varg1 = decay_derived (ctx, varg1);
2396
- varg2 = decay_derived (ctx, varg2);
2385
+ Value *varg1 = decay_derived (ctx, boxed (ctx, arg1));
2386
+ Value *varg2 = decay_derived (ctx, boxed (ctx, arg2));
2387
+ if (jl_pointer_egal (arg1.typ ) || jl_pointer_egal (arg2.typ )) {
2388
+ return ctx.builder .CreateICmpEQ (varg1, varg2);
2389
+ }
2397
2390
Value *neq = ctx.builder .CreateICmpNE (varg1, varg2);
2398
2391
return emit_guarded_test (ctx, neq, true , [&] {
2399
2392
Value *dtarg = emit_typeof_boxed (ctx, arg1);
@@ -2938,28 +2931,28 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
2938
2931
*ret = ghostValue (ety);
2939
2932
}
2940
2933
else if (!isboxed && jl_is_uniontype (ety)) {
2941
- Type *AT = ArrayType::get (IntegerType::get (jl_LLVMContext, 8 * al), (elsz + al - 1 ) / al);
2942
- Value *data = emit_bitcast (ctx, emit_arrayptr (ctx, ary, ary_ex), AT->getPointerTo ());
2943
- // isbits union selector bytes are stored after a->maxsize
2944
- Value *ndims = (nd == -1 ? emit_arrayndims (ctx, ary) : ConstantInt::get (T_int16, nd));
2945
- Value *is_vector = ctx.builder .CreateICmpEQ (ndims, ConstantInt::get (T_int16, 1 ));
2934
+ Value *data = emit_arrayptr (ctx, ary, ary_ex);
2946
2935
Value *offset = emit_arrayoffset (ctx, ary, nd);
2947
- Value *selidx_v = ctx.builder .CreateSub (emit_vectormaxsize (ctx, ary), ctx.builder .CreateZExt (offset, T_size));
2948
- Value *selidx_m = emit_arraylen (ctx, ary);
2949
- Value *selidx = ctx.builder .CreateSelect (is_vector, selidx_v, selidx_m);
2950
- Value *ptindex = ctx.builder .CreateInBoundsGEP (AT, data, selidx);
2936
+ Value *ptindex;
2937
+ if (elsz == 0 ) {
2938
+ ptindex = data;
2939
+ }
2940
+ else {
2941
+ Type *AT = ArrayType::get (IntegerType::get (jl_LLVMContext, 8 * al), (elsz + al - 1 ) / al);
2942
+ data = emit_bitcast (ctx, data, AT->getPointerTo ());
2943
+ // isbits union selector bytes are stored after a->maxsize
2944
+ Value *ndims = (nd == -1 ? emit_arrayndims (ctx, ary) : ConstantInt::get (T_int16, nd));
2945
+ Value *is_vector = ctx.builder .CreateICmpEQ (ndims, ConstantInt::get (T_int16, 1 ));
2946
+ Value *selidx_v = ctx.builder .CreateSub (emit_vectormaxsize (ctx, ary), ctx.builder .CreateZExt (offset, T_size));
2947
+ Value *selidx_m = emit_arraylen (ctx, ary);
2948
+ Value *selidx = ctx.builder .CreateSelect (is_vector, selidx_v, selidx_m);
2949
+ ptindex = ctx.builder .CreateInBoundsGEP (AT, data, selidx);
2950
+ data = ctx.builder .CreateInBoundsGEP (AT, data, idx);
2951
+ }
2951
2952
ptindex = emit_bitcast (ctx, ptindex, T_pint8);
2952
2953
ptindex = ctx.builder .CreateInBoundsGEP (T_int8, ptindex, offset);
2953
2954
ptindex = ctx.builder .CreateInBoundsGEP (T_int8, ptindex, idx);
2954
- Instruction *tindex = tbaa_decorate (tbaa_arrayselbyte, ctx.builder .CreateAlignedLoad (T_int8, ptindex, Align (1 )));
2955
- tindex->setMetadata (LLVMContext::MD_range, MDNode::get (jl_LLVMContext, {
2956
- ConstantAsMetadata::get (ConstantInt::get (T_int8, 0 )),
2957
- ConstantAsMetadata::get (ConstantInt::get (T_int8, union_max)) }));
2958
- AllocaInst *lv = emit_static_alloca (ctx, AT);
2959
- if (al > 1 )
2960
- lv->setAlignment (Align (al));
2961
- emit_memcpy (ctx, lv, tbaa_arraybuf, ctx.builder .CreateInBoundsGEP (AT, data, idx), tbaa_arraybuf, elsz, al, false );
2962
- *ret = mark_julia_slot (lv, ety, ctx.builder .CreateNUWAdd (ConstantInt::get (T_int8, 1 ), tindex), tbaa_arraybuf);
2955
+ *ret = emit_unionload (ctx, data, ptindex, ety, elsz, al, tbaa_arraybuf, true , union_max, tbaa_arrayselbyte);
2963
2956
}
2964
2957
else {
2965
2958
MDNode *aliasscope = (f == jl_builtin_const_arrayref) ? ctx.aliasscope : nullptr ;
@@ -3045,28 +3038,31 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
3045
3038
if (!isboxed && jl_is_uniontype (ety)) {
3046
3039
Type *AT = ArrayType::get (IntegerType::get (jl_LLVMContext, 8 * al), (elsz + al - 1 ) / al);
3047
3040
Value *data = emit_bitcast (ctx, emit_arrayptr (ctx, ary, ary_ex), AT->getPointerTo ());
3041
+ Value *offset = emit_arrayoffset (ctx, ary, nd);
3048
3042
// compute tindex from val
3049
3043
jl_cgval_t rhs_union = convert_julia_type (ctx, val, ety);
3050
3044
Value *tindex = compute_tindex_unboxed (ctx, rhs_union, ety);
3051
3045
tindex = ctx.builder .CreateNUWSub (tindex, ConstantInt::get (T_int8, 1 ));
3052
- Value *ndims = (nd == -1 ? emit_arrayndims (ctx, ary) : ConstantInt::get (T_int16, nd));
3053
- Value *is_vector = ctx.builder .CreateICmpEQ (ndims, ConstantInt::get (T_int16, 1 ));
3054
- Value *offset = emit_arrayoffset (ctx, ary, nd);
3055
- Value *selidx_v = ctx.builder .CreateSub (emit_vectormaxsize (ctx, ary), ctx.builder .CreateZExt (offset, T_size));
3056
- Value *selidx_m = emit_arraylen (ctx, ary);
3057
- Value *selidx = ctx.builder .CreateSelect (is_vector, selidx_v, selidx_m);
3058
- Value *ptindex = ctx.builder .CreateInBoundsGEP (AT, data, selidx);
3046
+ Value *ptindex;
3047
+ if (elsz == 0 ) {
3048
+ ptindex = data;
3049
+ }
3050
+ else {
3051
+ Value *ndims = (nd == -1 ? emit_arrayndims (ctx, ary) : ConstantInt::get (T_int16, nd));
3052
+ Value *is_vector = ctx.builder .CreateICmpEQ (ndims, ConstantInt::get (T_int16, 1 ));
3053
+ Value *selidx_v = ctx.builder .CreateSub (emit_vectormaxsize (ctx, ary), ctx.builder .CreateZExt (offset, T_size));
3054
+ Value *selidx_m = emit_arraylen (ctx, ary);
3055
+ Value *selidx = ctx.builder .CreateSelect (is_vector, selidx_v, selidx_m);
3056
+ ptindex = ctx.builder .CreateInBoundsGEP (AT, data, selidx);
3057
+ data = ctx.builder .CreateInBoundsGEP (AT, data, idx);
3058
+ }
3059
3059
ptindex = emit_bitcast (ctx, ptindex, T_pint8);
3060
3060
ptindex = ctx.builder .CreateInBoundsGEP (T_int8, ptindex, offset);
3061
3061
ptindex = ctx.builder .CreateInBoundsGEP (T_int8, ptindex, idx);
3062
3062
tbaa_decorate (tbaa_arrayselbyte, ctx.builder .CreateStore (tindex, ptindex));
3063
- if (jl_is_datatype (val.typ ) && jl_datatype_size (val.typ ) == 0 ) {
3064
- // no-op
3065
- }
3066
- else {
3067
- // copy data
3068
- Value *addr = ctx.builder .CreateInBoundsGEP (AT, data, idx);
3069
- emit_unionmove (ctx, addr, tbaa_arraybuf, val, nullptr );
3063
+ if (elsz > 0 && (!jl_is_datatype (val.typ ) || jl_datatype_size (val.typ ) > 0 )) {
3064
+ // copy data (if any)
3065
+ emit_unionmove (ctx, data, tbaa_arraybuf, val, nullptr );
3070
3066
}
3071
3067
}
3072
3068
else {
0 commit comments