From 97599dec3c44d63af2abfe75e6c7474af7d37623 Mon Sep 17 00:00:00 2001 From: Imran Hameed Date: Thu, 27 May 2021 10:45:46 -0400 Subject: [PATCH 1/2] Synthesize undef values for SIMD types with invalid (non-primitive) element types --- src/mono/mono/mini/mini-llvm.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index 4a4308dd555c3b..898151f65fc506 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -584,12 +584,9 @@ simd_class_to_llvm_type (EmitContext *ctx, MonoClass *klass) case MONO_TYPE_R8: return LLVMVectorType (LLVMDoubleType (), size / 8); default: - g_assert_not_reached (); - return NULL; + return LLVMVectorType (LLVMInt8Type (), size); } } else { - printf ("%s\n", klass_name); - NOT_IMPLEMENTED; return NULL; } } @@ -3925,9 +3922,19 @@ emit_entry_bb (EmitContext *ctx, LLVMBuilderRef builder) case LLVMArgVtypeAddr: case LLVMArgVtypeByRef: { - if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (ainfo->type))) + MonoClass *klass = mono_class_from_mono_type_internal (ainfo->type); + if (MONO_CLASS_IS_SIMD (ctx->cfg, klass)) { /* Treat these as normal values */ ctx->values [reg] = LLVMBuildLoad (builder, ctx->addresses [reg], "simd_vtype"); + } else { + LLVMTypeRef simd_t = simd_class_to_llvm_type (ctx, klass); + if (simd_t) { + /* This is a SIMD type with an invalid non-primitive element type. Generate a + * fake value to allow the resulting LLVM IR to be well-formed. + */ + ctx->values [reg] = LLVMGetUndef (simd_t); + } + } break; } default: @@ -4482,8 +4489,10 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, #endif } - gboolean is_simd = MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (sig->ret)); + MonoClass *klass = mono_class_from_mono_type_internal (sig->ret); + gboolean is_simd = MONO_CLASS_IS_SIMD (ctx->cfg, klass); gboolean should_promote_to_value = FALSE; + LLVMTypeRef simd_t = simd_class_to_llvm_type (ctx, klass); const char *load_name = NULL; /* * Convert the result. Non-SIMD value types are manipulated via an @@ -4554,6 +4563,11 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, LLVMTypeRef addr_type = LLVMPointerType (type_to_llvm_type (ctx, sig->ret), 0); LLVMValueRef addr = convert_full (ctx, addresses [call->inst.dreg], addr_type, FALSE); values [ins->dreg] = LLVMBuildLoad (builder, addr, load_name); + } else if (simd_t) { + /* This is a SIMD type with an invalid non-primitive element type. Generate a + * fake value to allow the resulting LLVM IR to be well-formed. + */ + ctx->values [ins->dreg] = LLVMGetUndef (simd_t); } *builder_ref = ctx->builder; @@ -5688,7 +5702,6 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) /* The return type is an LLVM aggregate type, so a bare bitcast cannot be used to do this conversion. */ int width = mono_type_size (sig->ret, NULL); int elems = width / TARGET_SIZEOF_VOID_P; - /* The return value might not be set if there is a throw */ LLVMValueRef val = LLVMBuildBitCast (builder, lhs, LLVMVectorType (IntPtrType (), elems), ""); for (int i = 0; i < elems; ++i) { LLVMValueRef element = LLVMBuildExtractElement (builder, val, const_int32 (i), ""); @@ -5713,7 +5726,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) break; case LLVMArgVtypeAsScalar: if (is_simd) { - retval = LLVMBuildBitCast (builder, values [ins->sreg1], ret_type, "setret_simd_vtype_as_scalar"); + retval = LLVMBuildBitCast (builder, lhs, ret_type, "setret_simd_vtype_as_scalar"); } else { g_assert (addresses [ins->sreg1]); retval = LLVMBuildLoad (builder, LLVMBuildBitCast (builder, addresses [ins->sreg1], LLVMPointerType (ret_type, 0), ""), ""); From 0d665d8c0582341992d0a3409ed8629c81449003 Mon Sep 17 00:00:00 2001 From: Imran Hameed Date: Thu, 27 May 2021 09:44:38 -0700 Subject: [PATCH 2/2] Extend support for the "simd-but-not-exactly-simd" hack to OP_LDADDR --- src/mono/mono/mini/mini-llvm.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index 898151f65fc506..7d5dfa64c456b2 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -6694,7 +6694,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) MonoInst *var = ins->inst_i0; MonoClass *klass = var->klass; - if (var->opcode == OP_VTARG_ADDR && !MONO_CLASS_IS_SIMD(cfg, klass)) { + if (var->opcode == OP_VTARG_ADDR && !MONO_CLASS_IS_SIMD(cfg, klass) && !simd_class_to_llvm_type (ctx, klass)) { /* The variable contains the vtype address */ values [ins->dreg] = values [var->dreg]; } else if (var->opcode == OP_GSHAREDVT_LOCAL) { @@ -7309,12 +7309,14 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) dst = convert (ctx, LLVMBuildAdd (builder, convert (ctx, values [ins->inst_destbasereg], IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_offset, FALSE), ""), LLVMPointerType (LLVMInt8Type (), 0)); } break; - case OP_LOADV_MEMBASE: + case OP_LOADV_MEMBASE: { if (!addresses [ins->dreg]) addresses [ins->dreg] = build_alloca (ctx, m_class_get_byval_arg (klass)); - src = convert (ctx, LLVMBuildAdd (builder, convert (ctx, values [ins->inst_basereg], IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_offset, FALSE), ""), LLVMPointerType (LLVMInt8Type (), 0)); + LLVMValueRef base = convert (ctx, values [ins->inst_basereg], IntPtrType ()); + src = convert (ctx, LLVMBuildAdd (builder, base, LLVMConstInt (IntPtrType (), ins->inst_offset, FALSE), ""), LLVMPointerType (LLVMInt8Type (), 0)); dst = LLVMBuildBitCast (builder, addresses [ins->dreg], LLVMPointerType (LLVMInt8Type (), 0), ""); break; + } case OP_VMOVE: if (!addresses [ins->sreg1]) addresses [ins->sreg1] = build_alloca (ctx, m_class_get_byval_arg (klass));