Multi-operator fold loop puts accumulators in wrong order
Compiler
sac2c 1.3.3-MijasCosta-1135-g4b472
build-type: DEBUG
built-by: "thomas" at 2024-01-24T13:04:00
No flags
Test
The following program creates three constant arrays of length 1000
with values 1, 5, 13 respectively. These are then summed with a multi-operator with-loop and the results are printed. It should print 1000, 5000, 13000
, but it prints 7000, 5000, 7000
.
#define N 1000
int add(int a, int b)
{
return _add_SxS_(a, b);
}
noinline
int, int, int sum(int[N] eren, int[N] mikasa, int[N] reiner)
{
eren_res, mikasa_res, reiner_res =
with {
([0] <= iv < [N]) {
eren_term = _sel_VxA_(iv, eren);
mikasa_term = _sel_VxA_(iv, mikasa);
reiner_term = _sel_VxA_(iv, reiner);
}: (eren_term, mikasa_term, reiner_term);
}: (fold(add, 0), fold(add, 0), fold(add, 0));
return (eren_res, mikasa_res, reiner_res);
}
int main()
{
eren = with {}: genarray([N], 1);
mikasa = with {}: genarray([N], 5);
reiner = with {}: genarray([N], 13);
eren_sum, mikasa_sum, reiner_sum = sum(eren, mikasa, reiner);
StdIO::printf("%d, %d, %d\n", eren_sum, mikasa_sum, reiner_sum);
return 0;
}
Investigation
The optimized code looks as follows. We see that the accumulators _ea_150_reiner_res, _ea_148_mikasa_res, _ea_146_eren_res
are in reverse order. This means that the first and third sum get alternating terms from the first and third arrays, which explains the 7000 = 1 * 1000 / 2 + 13 * 1000 / 2
.
int, int, int _MAIN::sum( int[1000] eren { ,NN } , int[1000] mikasa { ,NN } , int[1000] reiner { ,NN } )
/*
* sum :: ---
*/
{
int _ivesli_2673 { , NN } ;
int _ea_151_reiner_term { , NN } ;
int _ea_150_reiner_res { , NN } ;
int _ea_149_mikasa_term { , NN } ;
int _ea_148_mikasa_res { , NN } ;
int _ea_147_eren_term { , NN } ;
int _ea_146_eren_res { , NN } ;
int _eat_74 { , NN } ;
int reiner_res { , NN } ;
int mikasa_res { , NN } ;
int eren_res { , NN } ;
int reiner_term { , NN } ;
int mikasa_term { , NN } ;
int eren_term { , NN } ;
int[1] iv { , NN } ;
int{0} _flat_16 { , NN } ;
_flat_16 = 0;
eren_res, mikasa_res, reiner_res = with /** FOLDABLE (all gen's const) **/
/** REFERENCED: 3 (total num refs) **/
{
/* Partn */
([ 0 ] <= iv=[_eat_74] < [ 1000 ] genwidth [ 1000 ])
{
_ea_150_reiner_res, _ea_148_mikasa_res, _ea_146_eren_res = _accu_( iv, _flat_16, _flat_16, _flat_16);
_ivesli_2673 = _idxs2offset_( [ 1000 ], _eat_74);
eren_term = _idx_sel_( _ivesli_2673, eren);
mikasa_term = _idx_sel_( _ivesli_2673, mikasa);
reiner_term = _idx_sel_( _ivesli_2673, reiner);
_ea_151_reiner_term = _add_SxS_( _ea_150_reiner_res, reiner_term);
_ea_149_mikasa_term = _add_SxS_( _ea_148_mikasa_res, mikasa_term);
_ea_147_eren_term = _add_SxS_( _ea_146_eren_res, eren_term);
} : _ea_147_eren_term, _ea_149_mikasa_term, _ea_151_reiner_term ;
} :
fold( _MAIN::add(), _flat_16),
fold( _MAIN::add(), _flat_16),
fold( _MAIN::add(), _flat_16);
return( eren_res, mikasa_res, reiner_res);
}