firedrakeproject / tsfc

Two-stage form compiler
Other
15 stars 24 forks source link

Common subexpression elimination breaks complex mode #171

Closed miklos1 closed 4 years ago

miklos1 commented 6 years ago

Originally reported in firedrakeproject/firedrake#1255. Minimal failing example:

from firedrake import *
import ufl

mesh = UnitSquareMesh(10,10)

x = SpatialCoordinate(mesh)

domain = SubDomainData(ufl.And(0.0 <= real(x[0]),real(x[0]) <= 1.0))

real(x[0]) will be CSEd, and thus assigned to a temporary variable, however, that variable has type double complex so the subsequent comparison does not compile with the C compiler.

  double complex  t3  = creal(creal((((((0.333333333333333) * (coords[0]))) + (((0.333333333333333) * (coords[2]))))) + (((0.333333333333333) * (coords[4])))));
  double complex  t4  = ((((t3) >= (0))) && (((t3) <= (1))) ? 1 : 0);
wence- commented 6 years ago

I suppose that the code generation pass needs to be type-aware enough to declare variables of the correct type.

miklos1 commented 6 years ago

That would be the proper solution. A quick fix could be to generate creal(x) OP creal(y) instead of x OP y in complex mode, where OP is a comparison operator. Ideally, C compiler could optimise away the extra rubbish generated this way.

Another possible approach would be to hack around the inlining rules...

miklos1 commented 5 years ago

For reference: FEniCS/ffcx#127

wence- commented 4 years ago

I think that 6391bbc does (at least in loopy mode) my proposed type propagation fix.