@@ -2375,25 +2375,18 @@ static Value *emit_box_compare(jl_codectx_t &ctx, const jl_cgval_t &arg1, const
23752375 Value *nullcheck1, Value *nullcheck2)
23762376{
23772377 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 ;
23902383 }
2391-
23922384 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+ }
23972390 Value *neq = ctx.builder .CreateICmpNE (varg1, varg2);
23982391 return emit_guarded_test (ctx, neq, true , [&] {
23992392 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,
29382931 *ret = ghostValue (ety);
29392932 }
29402933 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);
29462935 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+ }
29512952 ptindex = emit_bitcast (ctx, ptindex, T_pint8);
29522953 ptindex = ctx.builder .CreateInBoundsGEP (T_int8, ptindex, offset);
29532954 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);
29632956 }
29642957 else {
29652958 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,
30453038 if (!isboxed && jl_is_uniontype (ety)) {
30463039 Type *AT = ArrayType::get (IntegerType::get (jl_LLVMContext, 8 * al), (elsz + al - 1 ) / al);
30473040 Value *data = emit_bitcast (ctx, emit_arrayptr (ctx, ary, ary_ex), AT->getPointerTo ());
3041+ Value *offset = emit_arrayoffset (ctx, ary, nd);
30483042 // compute tindex from val
30493043 jl_cgval_t rhs_union = convert_julia_type (ctx, val, ety);
30503044 Value *tindex = compute_tindex_unboxed (ctx, rhs_union, ety);
30513045 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+ }
30593059 ptindex = emit_bitcast (ctx, ptindex, T_pint8);
30603060 ptindex = ctx.builder .CreateInBoundsGEP (T_int8, ptindex, offset);
30613061 ptindex = ctx.builder .CreateInBoundsGEP (T_int8, ptindex, idx);
30623062 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 );
30703066 }
30713067 }
30723068 else {
0 commit comments