

> Unfortunately, "synchronization points" look like a bad starting point
> for defining IF semantics.  As soon as there are two statements in one
> branch of the IF, the following conflict pops up:
> 
> 	Users want synchronization between statements in the same branch
> 	Users do not want synchronization between the branches
> 
> Case study:
> 
> 	FORALL ( I = 1 : N )
> 	  IF ( A(I) < EPS ) THEN		! S0
> 	    A(I) = 0.0				! S1
> 	    B(I) = 0.0				! S2
> 	  ELSE
> 	    A(I) = (A(I-1) + A(I+1)) / 2	! S3
> 	    B(I) = A(I) * 3			! S4
> 	  END IF
> 	END FORALL
> 
> As a programmer, I expect S4 to use the value of A(I) that S3
> computes.  I do not expect S3 to see the values of A(I-1) and A(I+1)
> assigned by S1.  (It's not clear to me what users expect to happen if
> S4 is "B(I) = A(I-1)" instead.  But let's handle that after we get
> agreement on this case.)

This seems to be a case for allowing conditional expressions (as in C)
in forall-assignments, which is really what you want to express 
in the above example.  (I proposed this once before in the context of
alignment and distribution directives).  Using these, the above example
without stmts S2 and S4 could be written:

 	FORALL ( I = 1 : N )
 	    A(I) = (A(I) < EPS) ? 0.0 : (A(I-1) + A(I+1)) / 2
 	END FORALL

The full example becomes:

 	FORALL ( I = 1 : N )
 	    MASK(I) = (A(I) < EPS)
 	    A(I) = MASK (I) ? 0.0 : (A(I-1) + A(I+1)) / 2
 	    B(I) = MASK (I) ? 0.0 : 3  * A(I)
 	END FORALL

Admittedly it's a nuisance to introduce the mask, but I expect
it must be done implicitly anyway to implement this example.

I don't know how serious I am about this -- it's just my initial 
reaction on seeing this example.  I do have a general feeling that
it's better to introduce new syntax to express new semantics,
rather than overloading existing syntax by making its semantics
context dependent (which many users will find very confusing)

If you introduce the conditional expressions for this case, then
the other case, where you want S3 to use the *new* values computed by
S1, can be expressed with the IF construct using its normal meaning:

 	FORALL ( I = 1 : N )
 	  IF ( A(I) < EPS ) THEN		! S0
 	    A(I) = 0.0				! S1
 	  ELSE
 	    A(I) = (A(I-1) + A(I+1)) / 2	! S3
 	  END IF
 	END FORALL

Then you don't need to introduce a scalar WHERE construct within
FORALL for this case, which I also think should be avoided on the
same grounds as above.

> Straw poll for the group:
 
 1. Should HPF define a scalar WHERE statement (with semantics as in Guy
 Steele's proposal) in a FORALL...
no 	A) If we cannot agree on a semantics for IF?
no 	B) If we do agree on a semantics for IF that is different
 	   from WHERE semantics?
no	C) If we agree to use WHERE semantics for IF?
 
(I hope that A and B don't arise)
 
 2. Which of the following statements should be allowed in a block FORALL?
 	(Let's assume that assignment makes the cut :-)
yes 	A) single-statement FORALL
yes 	B) block FORALL
yes	C) array WHERE (i.e. current Fortran 90 WHERE)
no 	D) scalar WHERE (i.e. Marc's proposal)
yes 	E) IF-THEN-ELSE with FORALL-invariant conditions
yes 	F) IF-THEN-ELSE, conditions can depend on FORALL indices
 	G) DO loop with FORALL-invariant bounds
 	H) DO loop, bounds can depend on FORALL indices
 	J) GOTO
 	K) STOP and PAUSE
 	L) I/O statements (OPEN, CLOSE, READ, WRITE, ...)
	M) ALLOCATE and DEALLOCATE
yes 	N) CALL

I haven't really thought about the others.

                    John.

P.S.1: A colleague of mine, David Pritchard, suggests repeating labels
to indicate when stmts in different branches of an IF are to
be executed concurrently; thus...

 	FORALL ( I = 1 : N )
 	  IF ( A(I) < EPS ) THEN		! S0
1 	    A(I) = 0.0				! S1
2 	    B(I) = 0.0				! S2
 	  ELSE
1 	    A(I) = (A(I-1) + A(I+1)) / 2	! S3
2 	    B(I) = A(I) * 3			! S4
 	  END IF
 	END FORALL
 
corresponds to your desired interpretation.  I don't think he's
very serious about it though! :-)

P.S.2:  I plan to input something about user-defined elemental 
procedures soon.  It's just a matter of knuckling down to it!