13
$\begingroup$

Bug introduced in 9.0 or earlier, persisting through 13.2 or later


Below I post some rudimentary code to show that there is something wrong using Goto and Label commands in compiled functions (or I believe there is something wrong). It seems that the command Label is not found. Does anybody know what's going on?

toy=Compile[{{x,_Real}},
  Label["t"];
  y=RandomReal[{-1.,1.}];
  If[x*y<-0.,Print[y*x];Goto["t"],Print[y*x," ","done"]]
];

toy[1.]
(*Goto::nolabel: "Label ("t") not found.*)
$\endgroup$
0

2 Answers 2

6
$\begingroup$

This one is weird, and by my understanding of things, it is a bug. Label and Goto are on the list of compilable functions, and in fact, if you make your function completely compilable (i.e. compilable to code that does not call MainEvaluate), there is no problem. For example, this works without a hitch:

toy = Compile[{{x, _Real}},
  c = 0;
  Label[t];
  c++;
  If[x*RandomReal[{-1., 1.}] < -0., Goto[t]];
  c]

In your original function, however, the print statements prevented the Goto to be compiled, and it stayed inside a call to MainEvaluate. CompilePrint says your function is compiled into:

2   V17 = MainEvaluate[ Function[{x}, y = RandomReal[{-1., 1.}]][ R0]]
3   R3 = MainEvaluate[ Function[{x}, y][ R0]]
4   R4 = R0 * R3
5   B0 = R4 < R5 (tol R6)
6   R4 = MainEvaluate[ Function[{x}, If[x y < 0., Print[y x]; Goto[t], Print[y x,  , done]]][ R0]]

You see the Goto is still there, inside the MainEvaluate call, but the Label has been compiled away: thus, the warning that the label cannot be found.

If you remove the print statement near the Goto, the If is compiled and MainEvaluate is called only on its second branch:

toy3 = Compile[{{x, _Real}},
   Label["t"];
   y = RandomReal[{-1., 1.}];
   If[x*y < -0., Goto["t"], Print[y*x, " ", "done"]]];

gives

2   V17 = MainEvaluate[ Function[{x}, y = RandomReal[{-1., 1.}]][ R0]]
3   R3 = MainEvaluate[ Function[{x}, y][ R0]]
4   R4 = R0 * R3
5   B0 = R4 < R5 (tol R6)
6   if[ !B0] goto 9
7   goto 2
8   goto 10
9   V17 = MainEvaluate[ Function[{x}, Print[y x,  , done]][ R0]]

which works fine too, because now both the Label and the Goto have been compiled.


The reason I call it a bug is that I don't see this limitation specified anywhere in the documentation. I suggest reporting it to Wolfram support.

$\endgroup$
2
  • 6
    $\begingroup$ The label is still there in both cases. The problem is that labels aren't shared between the VM and the main evaluator (which makes sense, as you can't jump into compiled code at an arbitrary point), so Goto[t] does not find its target. That the compiler can be tricked into divorcing a Goto from its corresponding Label probably is a bug, I guess stemming from an attempt to minimize the number of (expensive) calls back into the main evaluator. $\endgroup$ Commented Sep 12, 2012 at 10:48
  • 5
    $\begingroup$ I should mention as well that the performance of compiled code like this, peppered as it is with calls out of the VM, will be absolutely horrific. For example, a single Ordering call per iteration in an early version of this consumed about 80% of the runtime--and that's with a fairly substantial loop body. The practical impact of this bug, then, will probably be minimal in most cases (as performance improvement is usually the main reason why one would use Compile in the first place). $\endgroup$ Commented Sep 12, 2012 at 11:18
4
$\begingroup$

There is nothing wrong with Label. The problem is that print can not be compiled. (see the list of compilable functions). Also y must be localized.

So compare

Needs["CompiledFunctionTools`"]
CompilePrint[toy]

which returns

        1 argument
        2 Boolean registers
        9 Real registers
        Underflow checking off
        Overflow checking off
        Integer overflow checking on
        RuntimeAttributes -> {}

        R0 = A1
        R2 = 1.
        R6 = 7.
        R1 = -1.
        R7 = -0.6382060350723182
        R5 = 0.
        Result = R4

1   
2   V17 = MainEvaluate[ Function[{x}, y = RandomReal[{-1., 1.}]][ R0]]
3   R3 = MainEvaluate[ Function[{x}, y][ R0]]
4   R4 = R0 * R3
5   B0 = R4 < R5 (tol R6)
6   R4 = MainEvaluate[ Function[{x}, If[x y < 0., Print[y x]; Goto[t], \
Print[y x,  , done]]][ R0]]
7   Return

(Notice all the call to MainEvaluate)

Now compare to this:

toy1 = Compile[{{x, _Real}}, Block[{y},
   Label["t"];
   y = RandomReal[{-1., 1.}];
   If[x*y < -0., Goto["t"]];
   x*y
   ]]

Needs["CompiledFunctionTools`"]
CompilePrint[toy1]

    1 argument
        1 Boolean register
        7 Real registers
        Underflow checking off
        Overflow checking off
        Integer overflow checking on
        RuntimeAttributes -> {}

        R0 = A1
        R2 = 1.
        R6 = 7.
        R1 = -1.
        R5 = 0.
        Result = R4

1   
2   R3 = RandomReal[ R1, R2]]
3   R4 = R0 * R3
4   B0 = R4 < R5 (tol R6)
5   if[ !B0] goto 8
6   goto 2
7   goto 8
8   R4 = R0 * R3
9   Return

which returns a nicely compiled function without problems.

$\endgroup$
4
  • 1
    $\begingroup$ The Print goes to MainEvaluate but other functions are compiled. Compile[{{x, _Real}}, Block[{y}, Label["t"]; y = RandomReal[{-1., 1.}]; Print[x*y]; If[x*y < -0., Goto["t"]]; Print[y*x, " ", "done"]; x*y]] $\endgroup$ Commented Sep 12, 2012 at 10:01
  • 1
    $\begingroup$ Does CompilationTarget -> "C" works for this example? For me it does not. $\endgroup$ Commented Sep 12, 2012 at 10:05
  • 2
    $\begingroup$ @PlatoManiac looks like someone forgot to specify the C translation for the label opcode! $\endgroup$ Commented Sep 12, 2012 at 10:38
  • $\begingroup$ @PlatoManiac Doesn't work for me either. Will anybody post a bug report to Wolfram? $\endgroup$
    – Ajasja
    Commented Sep 12, 2012 at 12:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.