fortrangoingonforty/armfortas / a270539

Browse files

Route scalar-returning function call to bulk fill on whole-array assignment

Authored by espadonne
Committed by mfwolffe
SHA
a27053930009f3efdcde7fcdf50c27396a9aeb13
Parents
276e447
Tree
d3b33f0

1 changed file

StatusFile+-
M src/ir/lower/stmt.rs 36 0
src/ir/lower/stmt.rsmodified
@@ -423,9 +423,45 @@ pub(crate) fn lower_stmt(b: &mut FuncBuilder, ctx: &mut LowerCtx, stmt: &Spanned
423423
                                             } else {
424424
                                                 false
425425
                                             };
426
+                                        // Scalar-returning call assigned to a whole array is a
427
+                                        // broadcast: `x = ieee_value(...)`, `x = sin(scalar_y)`,
428
+                                        // user `x = scalar_func()`. The fall-through path
429
+                                        // lowers the call as a scalar then treats the result as
430
+                                        // a source descriptor — `load %x from non-pointer f32`
431
+                                        // in the IR verifier, or afs_assign_allocatable with the
432
+                                        // scalar value in the wrong arg register at runtime
433
+                                        // (stdlib's pinv_s_operator hit this on the
434
+                                        // `pinva = ieee_value(1.0, NaN)` error path). Route
435
+                                        // through lower_array_assign so its bulk-fill plan
436
+                                        // applies. Skip when args contain array refs (the
437
+                                        // call really is producing an array result that other
438
+                                        // arms above already handle) or when the callee is an
439
+                                        // alloc-return user function (handled below).
440
+                                        let callee_is_scalar_broadcast = local_is_array_like(&info)
441
+                                            && !callee_is_local_array
442
+                                            && !callee_is_elemental_array_intrinsic
443
+                                            && !callee_is_transformational_intrinsic
444
+                                            && call_args.iter().all(|arg| {
445
+                                                if let crate::ast::expr::SectionSubscript::Element(e)
446
+                                                    = &arg.value
447
+                                                {
448
+                                                    !expr_contains_array_refs(e, &ctx.locals)
449
+                                                } else {
450
+                                                    false
451
+                                                }
452
+                                            })
453
+                                            && {
454
+                                                if let Expr::Name { name: cname } = &callee.node {
455
+                                                    let lk = cname.to_lowercase();
456
+                                                    !ctx.alloc_return_funcs.contains(&lk)
457
+                                                } else {
458
+                                                    false
459
+                                                }
460
+                                            };
426461
                                         if callee_is_local_array
427462
                                             || callee_is_elemental_array_intrinsic
428463
                                             || callee_is_transformational_intrinsic
464
+                                            || callee_is_scalar_broadcast
429465
                                         {
430466
                                             lower_array_assign(b, ctx, name, &info, value);
431467
                                             return;