diff --git a/src/llvm-alloc-helpers.cpp b/src/llvm-alloc-helpers.cpp index f4ca0bdf3e029..f215281821313 100644 --- a/src/llvm-alloc-helpers.cpp +++ b/src/llvm-alloc-helpers.cpp @@ -89,7 +89,7 @@ bool AllocUseInfo::addMemOp(Instruction *inst, unsigned opno, uint32_t offset, memop.isobjref = hasObjref(elty); auto &field = getField(offset, size, elty); - field.second.hasbits |= !hasObjref(elty) || (hasObjref(elty) && !isa(elty)); + field.second.hasunboxed |= !hasObjref(elty) || (hasObjref(elty) && !isa(elty)); if (field.second.hasobjref != memop.isobjref) field.second.multiloc = true; // can't split this field, since it contains a mix of references and bits @@ -201,7 +201,7 @@ void jl_alloc::runEscapeAnalysis(llvm::CallInst *I, EscapeAnalysisRequiredArgs r auto elty = inst->getType(); required.use_info.has_unknown_objref |= hasObjref(elty); required.use_info.has_unknown_objrefaggr |= hasObjref(elty) && !isa(elty); - required.use_info.has_unknown_bits |= !hasObjref(elty) || (hasObjref(elty) && !isa(elty)); + required.use_info.has_unknown_unboxed |= !hasObjref(elty) || (hasObjref(elty) && !isa(elty)); required.use_info.hasunknownmem = true; } else if (!required.use_info.addMemOp(inst, 0, cur.offset, inst->getType(), @@ -293,7 +293,7 @@ void jl_alloc::runEscapeAnalysis(llvm::CallInst *I, EscapeAnalysisRequiredArgs r auto elty = storev->getType(); required.use_info.has_unknown_objref |= hasObjref(elty); required.use_info.has_unknown_objrefaggr |= hasObjref(elty) && !isa(elty); - required.use_info.has_unknown_bits |= !hasObjref(elty) || (hasObjref(elty) && !isa(elty)); + required.use_info.has_unknown_unboxed |= !hasObjref(elty) || (hasObjref(elty) && !isa(elty)); required.use_info.hasunknownmem = true; } else if (!required.use_info.addMemOp(inst, use->getOperandNo(), cur.offset, storev->getType(), @@ -322,7 +322,7 @@ void jl_alloc::runEscapeAnalysis(llvm::CallInst *I, EscapeAnalysisRequiredArgs r LLVM_DEBUG(dbgs() << "Atomic inst has unknown offset\n"); required.use_info.has_unknown_objref |= hasObjref(elty); required.use_info.has_unknown_objrefaggr |= hasObjref(elty) && !isa(elty); - required.use_info.has_unknown_bits |= !hasObjref(elty) || (hasObjref(elty) && !isa(elty)); + required.use_info.has_unknown_unboxed |= !hasObjref(elty) || (hasObjref(elty) && !isa(elty)); required.use_info.hasunknownmem = true; } required.use_info.refload = true; diff --git a/src/llvm-alloc-helpers.h b/src/llvm-alloc-helpers.h index c567d8e218790..b235bcca8bafa 100644 --- a/src/llvm-alloc-helpers.h +++ b/src/llvm-alloc-helpers.h @@ -47,7 +47,7 @@ namespace jl_alloc { bool multiloc:1; bool hasload:1; // The alloc has a non-julia object at this offset. - bool hasbits:1; + bool hasunboxed:1; llvm::Type *elty; llvm::SmallVector accesses; Field(uint32_t size, llvm::Type *elty) @@ -56,7 +56,7 @@ namespace jl_alloc { hasaggr(false), multiloc(false), hasload(false), - hasbits(false), + hasunboxed(false), elty(elty) { } @@ -99,7 +99,7 @@ namespace jl_alloc { bool has_unknown_objrefaggr:1; // The alloc has a non-julia object at an unknown offset. - bool has_unknown_bits:1; + bool has_unknown_unboxed:1; void reset() { @@ -116,7 +116,7 @@ namespace jl_alloc { allockind = llvm::AllocFnKind::Unknown; has_unknown_objref = false; has_unknown_objrefaggr = false; - has_unknown_bits = false; + has_unknown_unboxed = false; uses.clear(); preserves.clear(); memops.clear(); diff --git a/src/llvm-alloc-opt.cpp b/src/llvm-alloc-opt.cpp index 0f2b5663b0ba9..91ac12710bd92 100644 --- a/src/llvm-alloc-opt.cpp +++ b/src/llvm-alloc-opt.cpp @@ -252,12 +252,12 @@ void Optimizer::optimizeAll() removeAlloc(orig); continue; } - bool has_bits = use_info.has_unknown_bits; + bool has_unboxed = use_info.has_unknown_bits; bool has_ref = use_info.has_unknown_objref; bool has_refaggr = use_info.has_unknown_objrefaggr; for (auto memop: use_info.memops) { auto &field = memop.second; - has_bits |= field.hasbits; + has_unboxed |= field.hasbits; if (field.hasobjref) { has_ref = true; // This can be relaxed a little based on hasload @@ -286,7 +286,11 @@ void Optimizer::optimizeAll() splitOnStack(orig); continue; } - if (has_bits && has_ref) { + // The move to stack code below, if has_ref is set, changes the allocation to an array of jlvalue_t's. This is fine + // if all objects are jlvalue_t's. However, if part of the allocation is not a julia object (e.g. it is a { float, jlvaluet }), + // then the moveToStackCAll will create a [2 x jlvaluet] bitcast to { float, jlvaluet }. The float clearly is not a GC + // value and will result in segfaults and other problems. + if (has_unboxed && has_ref) { REMARK([&]() { return OptimizationRemarkMissed(DEBUG_TYPE, "Escaped", orig) << "GC allocation could not be split and contained both julia object and non-julia-object data, unable to move to stack " << ore::NV("GC Allocation", orig);