@@ -2180,34 +2180,19 @@ static jl_cgval_t emit_globalref(jl_codectx_t &ctx, jl_module_t *mod, jl_sym_t *
2180
2180
static Value *emit_box_compare (jl_codectx_t &ctx, const jl_cgval_t &arg1, const jl_cgval_t &arg2,
2181
2181
Value *nullcheck1, Value *nullcheck2)
2182
2182
{
2183
- // If either sides is boxed or can be trivially boxed,
2184
- // we'll prefer to do a pointer check.
2185
- // At this point, we know that at least one of the arguments isn't a constant
2186
- // so a runtime content check will involve at least one load from the
2187
- // pointer (and likely a type check)
2188
- // so a pointer comparison should be no worse than that even in imaging mode
2189
- // when the constant pointer has to be loaded.
2190
- // Note that we ignore nullcheck, since in the case where it may be set, we
2191
- // also knew the types of both fields must be the same so there cannot be
2192
- // any unboxed values on either side.
2193
- if ((!arg1.TIndex && jl_pointer_egal (arg1.typ )) || (!arg2.TIndex && jl_pointer_egal (arg2.typ ))) {
2194
- // n.b. Vboxed may be incomplete if Tindex is set (missing singletons)
2195
- // and Vboxed == isboxed || Tindex
2196
- if ((arg1.Vboxed || arg1.constant ) && (arg2.Vboxed || arg2.constant )) {
2197
- Value *varg1 = arg1.constant ? literal_pointer_val (ctx, arg1.constant ) : maybe_bitcast (ctx, arg1.Vboxed , T_pjlvalue);
2198
- Value *varg2 = arg2.constant ? literal_pointer_val (ctx, arg2.constant ) : maybe_bitcast (ctx, arg2.Vboxed , T_pjlvalue);
2199
- return ctx.builder .CreateICmpEQ (decay_derived (ctx, varg1), decay_derived (ctx, varg2));
2200
- }
2201
- return ConstantInt::get (T_int1, 0 ); // seems probably unreachable?
2202
- // (since intersection of rt1 and rt2 is non-empty here, so we should have
2203
- // a value in this intersection, but perhaps intersection might have failed)
2183
+ if (jl_pointer_egal (arg1.typ ) || jl_pointer_egal (arg2.typ )) {
2184
+ // if we can be certain we won't try to load from the pointer (because
2185
+ // we know boxed is trivial), we can skip the separate null checks
2186
+ // and just do the ICmpEQ test
2187
+ if (!arg1.TIndex && !arg2.TIndex )
2188
+ nullcheck1 = nullcheck2 = nullptr ;
2204
2189
}
2205
-
2206
2190
return emit_nullcheck_guard2 (ctx, nullcheck1, nullcheck2, [&] {
2207
- Value *varg1 = arg1.constant ? literal_pointer_val (ctx, arg1.constant ) : maybe_bitcast (ctx, value_to_pointer (ctx, arg1).V , T_pjlvalue);
2208
- Value *varg2 = arg2.constant ? literal_pointer_val (ctx, arg2.constant ) : maybe_bitcast (ctx, value_to_pointer (ctx, arg2).V , T_pjlvalue);
2209
- varg1 = decay_derived (ctx, varg1);
2210
- varg2 = decay_derived (ctx, varg2);
2191
+ Value *varg1 = decay_derived (ctx, boxed (ctx, arg1));
2192
+ Value *varg2 = decay_derived (ctx, boxed (ctx, arg2));
2193
+ if (jl_pointer_egal (arg1.typ ) || jl_pointer_egal (arg2.typ )) {
2194
+ return ctx.builder .CreateICmpEQ (varg1, varg2);
2195
+ }
2211
2196
Value *neq = ctx.builder .CreateICmpNE (varg1, varg2);
2212
2197
return emit_guarded_test (ctx, neq, true , [&] {
2213
2198
Value *dtarg = emit_typeof_boxed (ctx, arg1);
@@ -2733,28 +2718,28 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
2733
2718
*ret = ghostValue (ety);
2734
2719
}
2735
2720
else if (!isboxed && jl_is_uniontype (ety)) {
2736
- Type *AT = ArrayType::get (IntegerType::get (jl_LLVMContext, 8 * al), (elsz + al - 1 ) / al);
2737
- Value *data = emit_bitcast (ctx, emit_arrayptr (ctx, ary, ary_ex), AT->getPointerTo ());
2738
- // isbits union selector bytes are stored after a->maxsize
2739
- Value *ndims = (nd == -1 ? emit_arrayndims (ctx, ary) : ConstantInt::get (T_int16, nd));
2740
- Value *is_vector = ctx.builder .CreateICmpEQ (ndims, ConstantInt::get (T_int16, 1 ));
2721
+ Value *data = emit_arrayptr (ctx, ary, ary_ex);
2741
2722
Value *offset = emit_arrayoffset (ctx, ary, nd);
2742
- Value *selidx_v = ctx.builder .CreateSub (emit_vectormaxsize (ctx, ary), ctx.builder .CreateZExt (offset, T_size));
2743
- Value *selidx_m = emit_arraylen (ctx, ary);
2744
- Value *selidx = ctx.builder .CreateSelect (is_vector, selidx_v, selidx_m);
2745
- Value *ptindex = ctx.builder .CreateInBoundsGEP (AT, data, selidx);
2723
+ Value *ptindex;
2724
+ if (elsz == 0 ) {
2725
+ ptindex = data;
2726
+ }
2727
+ else {
2728
+ Type *AT = ArrayType::get (IntegerType::get (jl_LLVMContext, 8 * al), (elsz + al - 1 ) / al);
2729
+ data = emit_bitcast (ctx, data, AT->getPointerTo ());
2730
+ // isbits union selector bytes are stored after a->maxsize
2731
+ Value *ndims = (nd == -1 ? emit_arrayndims (ctx, ary) : ConstantInt::get (T_int16, nd));
2732
+ Value *is_vector = ctx.builder .CreateICmpEQ (ndims, ConstantInt::get (T_int16, 1 ));
2733
+ Value *selidx_v = ctx.builder .CreateSub (emit_vectormaxsize (ctx, ary), ctx.builder .CreateZExt (offset, T_size));
2734
+ Value *selidx_m = emit_arraylen (ctx, ary);
2735
+ Value *selidx = ctx.builder .CreateSelect (is_vector, selidx_v, selidx_m);
2736
+ ptindex = ctx.builder .CreateInBoundsGEP (AT, data, selidx);
2737
+ data = ctx.builder .CreateInBoundsGEP (AT, data, idx);
2738
+ }
2746
2739
ptindex = emit_bitcast (ctx, ptindex, T_pint8);
2747
2740
ptindex = ctx.builder .CreateInBoundsGEP (T_int8, ptindex, offset);
2748
2741
ptindex = ctx.builder .CreateInBoundsGEP (T_int8, ptindex, idx);
2749
- Instruction *tindex = tbaa_decorate (tbaa_arrayselbyte, ctx.builder .CreateAlignedLoad (T_int8, ptindex, Align (1 )));
2750
- tindex->setMetadata (LLVMContext::MD_range, MDNode::get (jl_LLVMContext, {
2751
- ConstantAsMetadata::get (ConstantInt::get (T_int8, 0 )),
2752
- ConstantAsMetadata::get (ConstantInt::get (T_int8, union_max)) }));
2753
- AllocaInst *lv = emit_static_alloca (ctx, AT);
2754
- if (al > 1 )
2755
- lv->setAlignment (Align (al));
2756
- emit_memcpy (ctx, lv, tbaa_arraybuf, ctx.builder .CreateInBoundsGEP (AT, data, idx), tbaa_arraybuf, elsz, al, false );
2757
- *ret = mark_julia_slot (lv, ety, ctx.builder .CreateNUWAdd (ConstantInt::get (T_int8, 1 ), tindex), tbaa_arraybuf);
2742
+ *ret = emit_unionload (ctx, data, ptindex, ety, elsz, al, tbaa_arraybuf, true , union_max, tbaa_arrayselbyte);
2758
2743
}
2759
2744
else {
2760
2745
MDNode *aliasscope = (f == jl_builtin_const_arrayref) ? ctx.aliasscope : nullptr ;
@@ -2840,28 +2825,31 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
2840
2825
if (!isboxed && jl_is_uniontype (ety)) {
2841
2826
Type *AT = ArrayType::get (IntegerType::get (jl_LLVMContext, 8 * al), (elsz + al - 1 ) / al);
2842
2827
Value *data = emit_bitcast (ctx, emit_arrayptr (ctx, ary, ary_ex), AT->getPointerTo ());
2828
+ Value *offset = emit_arrayoffset (ctx, ary, nd);
2843
2829
// compute tindex from val
2844
2830
jl_cgval_t rhs_union = convert_julia_type (ctx, val, ety);
2845
2831
Value *tindex = compute_tindex_unboxed (ctx, rhs_union, ety);
2846
2832
tindex = ctx.builder .CreateNUWSub (tindex, ConstantInt::get (T_int8, 1 ));
2847
- Value *ndims = (nd == -1 ? emit_arrayndims (ctx, ary) : ConstantInt::get (T_int16, nd));
2848
- Value *is_vector = ctx.builder .CreateICmpEQ (ndims, ConstantInt::get (T_int16, 1 ));
2849
- Value *offset = emit_arrayoffset (ctx, ary, nd);
2850
- Value *selidx_v = ctx.builder .CreateSub (emit_vectormaxsize (ctx, ary), ctx.builder .CreateZExt (offset, T_size));
2851
- Value *selidx_m = emit_arraylen (ctx, ary);
2852
- Value *selidx = ctx.builder .CreateSelect (is_vector, selidx_v, selidx_m);
2853
- Value *ptindex = ctx.builder .CreateInBoundsGEP (AT, data, selidx);
2833
+ Value *ptindex;
2834
+ if (elsz == 0 ) {
2835
+ ptindex = data;
2836
+ }
2837
+ else {
2838
+ Value *ndims = (nd == -1 ? emit_arrayndims (ctx, ary) : ConstantInt::get (T_int16, nd));
2839
+ Value *is_vector = ctx.builder .CreateICmpEQ (ndims, ConstantInt::get (T_int16, 1 ));
2840
+ Value *selidx_v = ctx.builder .CreateSub (emit_vectormaxsize (ctx, ary), ctx.builder .CreateZExt (offset, T_size));
2841
+ Value *selidx_m = emit_arraylen (ctx, ary);
2842
+ Value *selidx = ctx.builder .CreateSelect (is_vector, selidx_v, selidx_m);
2843
+ ptindex = ctx.builder .CreateInBoundsGEP (AT, data, selidx);
2844
+ data = ctx.builder .CreateInBoundsGEP (AT, data, idx);
2845
+ }
2854
2846
ptindex = emit_bitcast (ctx, ptindex, T_pint8);
2855
2847
ptindex = ctx.builder .CreateInBoundsGEP (T_int8, ptindex, offset);
2856
2848
ptindex = ctx.builder .CreateInBoundsGEP (T_int8, ptindex, idx);
2857
2849
tbaa_decorate (tbaa_arrayselbyte, ctx.builder .CreateStore (tindex, ptindex));
2858
- if (jl_is_datatype (val.typ ) && jl_datatype_size (val.typ ) == 0 ) {
2859
- // no-op
2860
- }
2861
- else {
2862
- // copy data
2863
- Value *addr = ctx.builder .CreateInBoundsGEP (AT, data, idx);
2864
- emit_unionmove (ctx, addr, tbaa_arraybuf, val, nullptr );
2850
+ if (elsz > 0 && (!jl_is_datatype (val.typ ) || jl_datatype_size (val.typ ) > 0 )) {
2851
+ // copy data (if any)
2852
+ emit_unionmove (ctx, data, tbaa_arraybuf, val, nullptr );
2865
2853
}
2866
2854
}
2867
2855
else {
0 commit comments