%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -*- fundamental -*-
% fftwgel_simdvectorization_basics.pl
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Description:	This module features some basics predicates 
%		(for handling bindings, joining loads and stores).
% Language:	SICStus Prolog 3
% Copyright:	2003, Stefan Kral
% Author: 	Stefan Kral (URL mailto:skral@complang.tuwien.ac.at)
% License:	GNU General Public License (GPL) Version 2 (or higher)
% History:	Fri Feb 21 11:49:34 CET 2003: created
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

scalarinstr_dst(load(_,_,_,D), D).
scalarinstr_dst(binop(_,_,_,D), D).
scalarinstr_dst(unaryop(_,_,D), D).

nounaryopinstr_dst(binop(_,_,_,D), D).
nounaryopinstr_dst(load(_,_,_,D), D).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% partitioning of scalar instructions
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

scalarinstrs_stores_rest(Instrs, Stores, Rest) :-
   scalarinstrs_stores0_stores_rest0_rest(Instrs, Stores, [], Rest, []).

scalarinstrs_stores0_stores_rest0_rest([], Xs, Xs, Zs, Zs).
scalarinstrs_stores0_stores_rest0_rest([I|Is], Xs0, Xs, Zs0, Zs) :-
   scalarinstr_classified_(I, Xs0, Xs1, Zs0, Zs1),
   scalarinstrs_stores0_stores_rest0_rest(Is, Xs1, Xs, Zs1, Zs).

scalarinstr_classified_(store(S,P,A,X), [store(S,P,A,X)|Xs], Xs, Zs, Zs).
scalarinstr_classified_(binop(Op,S,T,D), Xs, Xs, [binop(Op,S,T,D)|Rs], Rs).
scalarinstr_classified_(unaryop(Op,S,D), Xs, Xs, [unaryop(Op,S,D)|Rs], Rs).
scalarinstr_classified_(load(P,A,X,D), Xs, Xs, [load(P,A,X,D)|Rs], Rs).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% auxiliary code for joining two binop-instructions
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

bindingtype_(acc, S1,S2, T1,T2,  S1,S2, T1,T2).
bindingtype_(par, S1,S2, T1,T2,  S1,T1, S2,T2).
bindingtype_(chi, S1,S2, T1,T2,  S2,T1, S1,T2).

binop_binop_bindingtypes(add, add, [acc,par,chi]).
binop_binop_bindingtypes(add, sub, [acc,par,chi]).
binop_binop_bindingtypes(sub, add, [acc,par,chi]).
binop_binop_bindingtypes(sub, sub, [acc,par,chi]).
binop_binop_bindingtypes(mul, mul, [par,chi]).


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% auxiliary code for joining two loads/stores
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

validInterleavedAccessPair_(realPartOfIComplex, imagPartOfIComplex).
validInterleavedAccessPair_(imagPartOfIComplex, realPartOfIComplex).

validSplitAccessPair_(real, real).
validSplitAccessPair_(realPartOfSComplex, P) :-
   is_splitcomplexaccess(P).
validSplitAccessPair_(imagPartOfSComplex, P) :-
   is_splitcomplexaccess(P).


%%%%%%%%%%%%%%%%%%%
% handling bindings
%%%%%%%%%%%%%%%%%%%

existingbinding_r1_r2(Bs, R1, R2) :-
   member_of(R1+R2, Bs).
existingbinding_r1_r2(Bs, R1, R2) :-
   member_of(R2+R1, Bs).

newbind_(_I, R1, R2, Bs, Bs, Is, Is, Xs, Xs) :-
   existingbinding_r1_r2(Bs, R1, R2).
newbind_(I, R1, R2, Bs0, [R1+R2|Bs0], Is0, [I|Is0], Xs0, [R1+R2|Xs0]) :-
   dif(R1, R2),
   list_nonmember(Bs0, R1+R2),
   list_nonmember(Bs0, R2+R1).

bind_(R1, R2, Bs, Bs, Xs, Xs) :-
   existingbinding_r1_r2(Bs, R1, R2).
bind_(R1, R2, Bs0, [R1+R2|Bs0], Xs0, [R1+R2|Xs0]) :-
   dif(R1, R2),
   bindings_donotaffect(Bs0, R1),
   bindings_donotaffect(Bs0, R2).

bindings_donotaffect([], _R).
bindings_donotaffect([X+Y|Bs], R) :-
   dif(X, R),
   dif(Y, R),
   bindings_donotaffect(Bs, R).
