Skip to content

The cmm pipeline may generate redundant cmm locals for the wasm32 target

One example is the cmm_sink_sp test case, containing the following .cmm code:

#include "Cmm.h"

stg_sink_things ( P_ x1 )
{
    W_ res;
    W_ x2, x3, x4, x5, x6;

    // Should produce a series of loads that are sunk into
    // stores to Sp like this:
    //    I64[Sp - 64] = I64[R1 + 1];   // CmmStore
    //    I64[Sp - 56] = I64[R1 + 2];   // CmmStore
    x2 = W_[x1+4];
    x3 = W_[x1+8];
    x4 = W_[x1+12];
    x5 = W_[x1+16];
    x6 = W_[x1+20];
    W_[Sp - 8] = x2;
    W_[Sp - 16] = x3;
    W_[Sp - 24] = x4;
    W_[Sp - 32] = x5;
    W_[Sp - 40] = x6;

    return (x1);
}

When compiled with -O, the cmm dump looks like:

==================== Output Cmm ====================
[stg_sink_things() { //  [R1]
         { info_tbls: []
           stack_info: arg_space: 8
         }
     {offset
       _lbl_: // global
           //tick src<cmm_sink_sp.cmm:(4,1)-(24,1)>
           //tick src<cmm_sink_sp.cmm:12:8-22>
           //tick src<cmm_sink_sp.cmm:13:8-22>
           //tick src<cmm_sink_sp.cmm:14:8-23>
           //tick src<cmm_sink_sp.cmm:15:8-23>
           //tick src<cmm_sink_sp.cmm:16:8-23>
           //tick src<cmm_sink_sp.cmm:17:11-24>
           I64[Sp - 8] = I64[R1 + 4];   // CmmStore
           //tick src<cmm_sink_sp.cmm:18:11-25>
           I64[Sp - 16] = I64[R1 + 8];   // CmmStore
           //tick src<cmm_sink_sp.cmm:19:11-25>
           I64[Sp - 24] = I64[R1 + 12];   // CmmStore
           //tick src<cmm_sink_sp.cmm:20:11-25>
           I64[Sp - 32] = I64[R1 + 16];   // CmmStore
           //tick src<cmm_sink_sp.cmm:21:11-25>
           I64[Sp - 40] = I64[R1 + 20];   // CmmStore
           call (P64[Sp])(R1) args: 8, res: 0, upd: 8;   // CmmCall
     }
 }]

However, for wasm32 target, it produces cmm that contains a redundant cmm local:

==================== Output Cmm ====================

[stg_sink_things() { //  [R1]
         { info_tbls: []
           stack_info: arg_space: 0
         }
     {offset
       _lbl_: // global
           //tick src<cmm_sink_sp.cmm:(4,1)-(24,1)>
           //tick src<cmm_sink_sp.cmm:12:8-22>
           //tick src<cmm_sink_sp.cmm:13:8-22>
           //tick src<cmm_sink_sp.cmm:14:8-23>
           //tick src<cmm_sink_sp.cmm:15:8-23>
           //tick src<cmm_sink_sp.cmm:16:8-23>
           //tick src<cmm_sink_sp.cmm:17:11-24>
           __locVar_::P32 = R1;
           I32[Sp - 8] = I32[__locVar_::P32 + 4];
           //tick src<cmm_sink_sp.cmm:18:11-25>
           I32[Sp - 16] = I32[__locVar_::P32 + 8];
           //tick src<cmm_sink_sp.cmm:19:11-25>
           I32[Sp - 24] = I32[__locVar_::P32 + 12];
           //tick src<cmm_sink_sp.cmm:20:11-25>
           I32[Sp - 32] = I32[__locVar_::P32 + 16];
           //tick src<cmm_sink_sp.cmm:21:11-25>
           I32[Sp - 40] = I32[__locVar_::P32 + 20];
           R1 = __locVar_::P32;
           call (I32[P32[Sp]])(R1) args: 4, res: 0, upd: 4;
     }
 }]

This doesn't affect correctness of output code, but it still bothers me, since the parts of cmm pipeline before the NCG backend should be more or less target independent, and it doesn't ring me a quick bell why it would generate code like this for wasm32.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information