The smallest sample I can find to reproduce this problem is:
test = Compile[{}, If[True, 1]];
<< CompiledFunctionTools`
CompilePrint@test
………… 1 R0 = MainEvaluate[ Function[{}, If[True, 1]][ ]] 2 Return
The problem disappears when the If[]
is followed by a semicolon:
test = Compile[{}, If[True, 1];];
CompilePrint@test
………… 1 if[ !B0] goto 3 2 goto 3 3 Return
or enclosed by a redundant Do[]
:
test = Compile[{}, Do[If[True, 1], {1}]];
CompilePrint@test
………… 1 I1 = I0 2 I3 = I2 3 goto 6 4 if[ !B0] goto 6 5 goto 6 6 if[ ++ I3 < I1] goto 4 7 Return
while a redundant Table[]
won't help:
test = Compile[{}, Table[If[True, 1], {1}]];
CompilePrint@test
………… 1 I1 = I0 2 I4 = I3 3 T(R1)0 = Table[ I1] 4 I2 = I3 5 goto 8 6 R1 = MainEvaluate[ Function[{}, If[True, 1]][ ]] 7 Element[ T(R1)0, I4] = R1 8 if[ ++ I2 < I1] goto 6 9 Return
This phenomenon may lead to a total failure of compilation when codes become more complicated:
ie = 200;
ez = ConstantArray[0., {ie + 1}];
hy = ConstantArray[0., {ie}];
f1 = Compile[{{steps}},
Module[{ie = ie, ez = ez, hy = hy},
Do[ez[[2 ;; ie]] = ez[[2 ;; ie]] + (hy[[2 ;; ie]] - hy[[1 ;; ie - 1]]);
ez[[1]] = Sin[n/10];
hy[[1 ;; ie]] = hy[[1 ;; ie]] + (ez[[2 ;; ie + 1]] - ez[[1 ;; ie]]), {n, steps}];
ez]];
f2 = Compile[{{steps, _Integer}, {test, True | False}},
Module[{ie = ie, ez = ez, hy = hy},
Do[ez[[2 ;; ie]] = ez[[2 ;; ie]] + (hy[[2 ;; ie]] - hy[[1 ;; ie - 1]]);
ez[[1]] = Sin[n/10];
hy[[1 ;; ie]] = hy[[1 ;; ie]] + (ez[[2 ;; ie + 1]] - ez[[1 ;; ie]]), {n, steps}];
If[test, ez]]];
f1[1500]; // AbsoluteTiming
{0.0250000, Null}
f2[1500, True]; // AbsoluteTiming
Warnings……
{0.5730000, Null}
So, as the title said, If
won't compile when its output is the output of Compile
?
Of course it can be easily circumvented, but I wonder if there's a universal rule behind this, or it's just another unreasonable behavior of Compile
?