© 1998 IRISA / INRIA - University of Rennes 1 Version 1.194

Tempo Specializer - Limitations


Caution: The limitations listed in this document are not meant to be exhaustive.


MAIN  TUTOR  USER  REF  INSTALL  FAQ  LIMIT  BUGS  SUPPORT  SML  SUIF  DEMO  CONTRIB

Missing Features

Some features are missing in Tempo. Though some of them are still challenges, others are just due to a (relative) lack of manpower.


Limitations of the Input Language

Though Tempo internally works on a small C subset, it accepts most ANSI C constructions. However, the following constructs are not handled:

Limitations on Aliases and Casts

For the time being, in order to guarantee that the alias analysis will produce correct results, the following rules should be obeyed:

  1. Pointer arithmetic can only be applied to pointers pointing to the contents of an array. (A warning is raised.)

  2. The only scalar that can be cast to a pointer is 0, i.e. the pointer NULL pointer. (A fatal error is raised: Tempo stops.)

  3. Casting a pointer to a pointer is allowed only if the pointed objects are scalars. (A pointer is a scalar.) A warning is raised when the target type is not a pointer to a scalar.

  4. If a pointer to a structure or union is cast to another pointer type it should be considered ``opaque'' (i.e. not dereferenced, neither for reading nor writing) until it is cast back into the original type.

All cast restrictions apply to unions that are used as casts, i.e. when an object is stored in the union under a certain name (and type) and retrieved under another name.

Some of these limitations are due to the monovariance of the alias analysis, others to the lack of a store model in Tempo. (Locations rely on names rather than physical, even abstract, memory.)

In order to express non-opaque casts between structure types (as may be needed for object-oriented programming), consider modeling them explicitly as abstract functions in the actx.c analysis context file.

For the analysis to be correct, Tempo has to know all the possible aliases of locations if they have an impact on the semantics. This can also specified using the actx.c analysis context file.


Mutually Recursive Structure Declarations

Tempo doesn't give an error if there is mutual recursion among structure declarations. However side-effect analysis just might not collect as many read/written non-locals as it should. Self recursion is OK though.


Binding-Time Imprecision Due to Goto elimination

Tempo rewrites gotos using a combination of new variables, conditionals, while loops, breaks, and continues, using an algorithm developed by Ana Erosa and Laurie Hendren at McGill University (described in ACAPS Technical Memo 76). The conditionals introduced by the goto elimination can interfere with each other causing binding-time problems. Consider the following program:

int if_test(int S, int D)
{
  int x,y;

  if (S > 32) goto L33;
  x=150;
  if (D > 32) goto L38;
  y=100;
  goto L38;
L33:
  x=200;
L38:
  return x + y;
}

This program corresponds to the following program without conditionals:

int if_test(int S, int D)
{
  int x,y;

  if (S <= 32) {
    x = 150;
    if (D <= 32) {
      y = 100;
    }
  else x = 200;
  return x + y;
}

Suppose we specialize these programs with S static and D dynamic. In the second case, S should be static, because it is not assigned within the dynamic conditional. In the first program, the goto elimination moves what should be the else branch of a static conditional, i.e. the assignment of x to 200, inside of the dynamic conditional. This behavior is shown by the following at.color (or at.html file). (If this document is printed in black and white, this example will not tell you much.)

extern int if_test_1/*0*/(int S, int D)  {
    int goto1_L33;
    int goto1_L38;
    int x;
    int y;

    goto1_L33 = 0;
    goto1_L38 = 0;
    goto1_L33 = 32 < S;
    if (! goto1_L33)
      {
        x = 150;
      }

    if (goto1_L33 || 32 >= D)
      {
        if (! goto1_L33)
          {
            y = 100;
            goto1_L38 = 1;
          }

        if (! goto1_L38)
          {
            goto1_L33 = 0;
            x = 200;
          }

      }
    goto1_L38 = 0;
    return x + y;
  }

The slightly more complicated program below, exhibits similar behavior.

int if_test(int S, int D)
{
  int x,y;

  if (S > 32) goto L33;
  x=150;
  if (D > 32) goto L27;
  y=100;
  goto L38;
L27:
  y=45;
  goto L38;
L33:
  x=200;
L38:
  return x + y;
}

Here the lines below label L27 correspond to the else branch of the inner dynamic conditional statement. In this case, the else branch of the outer conditional is not actually placed within the inner conditional, but dynamic tests of goto variables are placed around the code, making x again dynamic:

extern int if_test_1/*0*/(int S, int D)  {
    int goto1_L27;
    int goto1_L33;
    int goto1_L38;
    int x;
    int y;

    goto1_L27 = 0;
    goto1_L33 = 0;
    goto1_L38 = 0;
    if (32 >= S)
      {
        x = 150;
        if (32 >= D)
          {
            y = 100;
            goto1_L38 = 1;
          }
        if (! goto1_L38)
          {
            goto1_L27 = 0;
            y = 45;
            goto1_L38 = 1;
          }
      }

    if (! goto1_L38 && ! goto1_L38)
      {
        goto1_L33 = 0;
        x = 200;
      }
    goto1_L38 = 0;
    return x + y;
  }

Essentially the problem is that because else branches are not introduced by the goto elimination, dynamic tests are introduced to jump over the else branch of the static conditional in all cases that can result from taking its then branch.

The PORKY_DEFAULTS and PORKY_PRE_DEFAULTS phases of Suif rearrange goto statements in a way that can also be detrimental to binding times. In many cases, these options can be turned off (which is the default for the current version of Tempo), but in some cases porky will not work if these phases have not been performed.


Identifier Naming In Compile-Time Specialization

In the current implementation of the compile-time specializer, global names are renamed during specialization. This can cause problems if they are external, or are referenced externally during specialization.

The renaming of global variables is controlled by the .sctx.h file, which for the global variable var might contain a definition akin to:

#define var _store.var
As long as the .sctx.h file is included into all C files used by the specializer, this works fine. However, if the program slice being specialized is part of a larger set of object files that are linked together, problems may occur. Specifically, object files that are not recompiled into the specializer will all refer to var , whereas those files that were recompiled will refer to _store.var. If the specializer depends upon side effects from other parts of the program to var, it is likely to fail.

One solution is to only give Tempo the relevant program slice during analysis, and then give it the whole program during specialization. This allows any redefinitions in the sctx.h file to take effect without incurring a large overhead (unless the program is very large). Of course, this only works if source code is available for the whole program, and may require some minor rewriting of the program. Other alternative solutions include referencing such variables through functions or to copy their value when the specialization starts.

This problem is likely to be removed in a future version, by avoiding any renaming of variables during specialization.


Limitations on Multiple Compile-Time Specialization

There is no specific support for multiple compile-time specialization. In particular, when linking simultaneously different specializations, redundant definitions may appear. They must be removed by hand. Similarly, useless declarations may occur.

Note that identifiers are renamed by compile-time specialization. Global identifier are prefixed with _G, local identifiers are prefixed with _L (or _Y for nested block declarations) and the name of the function they belong to.


Limitations to Run-Time Specialization

At the moment, the run-time specializer does not support:

This may not preserve the semantics of the run-time specialized function (see below).

Only gcc and a slightly modified version of lcc can be used for constructing a run-time specializer; see variable compiler.


Limitations on the Preservation of the Semantics

While a program transformer ideally always preserves the semantics of programs, this might not always be the case with Tempo, in very limited cases though!


Limitations Common to Off-Line Partial Evaluators

As is the case for most off-line partial evaluator, Tempo will blindly evaluate all static expression. In particular,

Naming of Identifiers

Tempo does not check that the identifiers that it creates do not already exist. Uncommon suffixes and counters seem to do the trick in most cases. However, theoretically, a name clash is possible.


Initializations

Other limitations are due to the transformations that Tempo performs in order to work on a smaller C subset. In particular, definitions of global variables of scalar type are turned into assignments in the entry point function to facilitate analysis. At the same time, the initializer is removed from the variable declaration, which may be a problem if the variable is actually used in some other files.


Limitations to Run-Time Specialization

As mentioned above, there is no store management in the run-time specialization. This can produce an incorrect result from run-time specialization. A conditional statement is annotated ``rebuild'' when the test is dynamic by there is code that can be evaluated during specialization in one of the branches. In compile-time specialization, when specializing each branch the store is initialized to the store that existed just after specializing the conditional test. Thus the static side-effects in one branch have no influence on the other branch. This is not the case for run-time specialization. In run-time specialization the store that exists at the end of specializing the first branch is the store that is used to specialize the second branch. This strategy can lead to wrong results, as illustrated by the following example:

Original program Wrong specialization Correct specialization
x=1;
if(Dyn)
{
  x=2;
  f(x);
}
else
{
  g(x);
}

if(Dyn)
{
  f(2);
}
else
{
  g(2);
}


if(Dyn)
{
  f(2);
}
else
{
  g(1);
}

Note that no warning will be issued. If such a situation is spotted, one possible workaround is to prevent speculative evaluation by turning dynamic the dangerous side-effects.

Another effect of the lack of store management is that there is no memoization of the current store when specializing a function. This is in contrast with compile-time specialization that able to recognize that a function has already been specialized (or is being specialized) and to yield a call to that specialized function rather than invoking the specializer anew. As a result, run-time specialization may loop if the specialized function is recursive. This is typically the case when specializing interpreters with backward jumps. There are workarounds though; see Recursive and Multiple Run-Time Specializations in the User's Manual.


Limitations on the Improvements Gained by Specialization

Partial evaluation is not magic. There are several reasons why the specialized program could be worse that the original one. In particular,


Plans for the Future

The following features are being considered for the next releases of Tempo. Some are already implemented in large part and being tested. They are listed in order of likeliness to be released soon.

  1. Switch
  2. Inlining at run time
  3. User-refined memory management (compile-time specialization)
  4. Data specialization
  5. More efficient compile-time specialization
  6. Structure (and union) polyvariance
  7. Better handling of casts

Tempo currently relies on version 0.93 of SML New Jersey (see the SML Environment). This is quite an old version, that in particular performs very badly on PCs. We plan to port it on the new version 110, offering thus not only better performances but also support for Windows.


MAIN  TUTOR  USER  REF  INSTALL  FAQ  LIMIT  BUGS  SUPPORT  SML  SUIF  DEMO  CONTRIB


Last modified: Sun Apr 26 18:48:25 MET DST 1998