lbr@holos0.uucp (Len Reed) (09/12/90)
Perl will not work properly on an NCR Tower when compiled with full optimization (-O2). I have confirmed this on a Tower 32-600 running System V.2 and a Tower 32-500 running V.3. It *does* pass the test suite, however. The problems concern local variable handling. Perl seems to get confused when deallocating local variables. It's not a simple as saying when the local $i is deallocated that the previous one doesn't reappear; rather, when the local $i is deallocated other variables suddenly take on the wrong values. The problem is especially acute when using recursion. In general, though, it doesn't happen often. The debugger script also messes up, probably due to the same problem. I think I know what the problem is, but I don't understand why this problem doesn't occur on other machines. The following script causes the problem: #!/usr/acct/lbin/perl sub doubleary { local(*someary, *another) = @_; local ($elem); foreach $elem (@someary) { $elem *= 2; } foreach $elem (@another) { $elem += 5; } } @foo = (1,3,5); @bar = (9,11,13); @other = (21,23,25); do doubleary(*foo, *other); do doubleary(*bar, *other); print "@foo\n"; print "@bar\n"; print "@other\n"; __END__ It should yield 2 6 10 18 22 26 31 33 35 but with the bug will yield 2 6 10 18 22 26 21 23 25 The Tower manuals warn against using -O2 with setjmp and longjmp. The compiler will do global register allocation, using registers rather than stack variables for automatic variables it decides are heavily used. The manual says go to -O1 or make these static, not auto. Consider the following code: #include <setjmp.h> #define VOLATILE /* Tower doesn't know about volatile */ int main() { static jmp_buf saveit; VOLATILE int x; int y, z; /* used to cause optimizer to put x into a register */ x = 12; if (setjmp(saveit)) { printf("x is %d\n", x); return 0; } y = 2*x; /* tickle the register allocation heuristic */ x = 25; longjmp(saveit, 1); z = 4*x + 23; /* tickle the heuristic */ } The printf should give 25 but it gives 12 under cc -O2. Well, why doesn't this problem occur on other machines? Surely other compilers perform this kind of optimization. If fact, the mappings from variables to registers are not necessarily static; e.g., r4 might be x some places and y others. I presume that this is the purpose of VOLATILE in Larry's code. SCO Xenix 386, which supports volatile, experienced no such problems. The Tower does not recognize volatile, though. Presuming that volatile is the key to this puzzle, I recompiled perly.c and cmd.c with -O1. The other files that use setjmp/longjmp don't use VOLATILE, so I presume that there are no traps there. It might be better to allocate static variables and use -O2, but what I have works satisfactorily. I'm still puzzled, though, as to why similar problems don't occur on other machines. Is the global register optimization plus no volatile keyword combination all that rare? -- Len Reed Holos Software, Inc. Voice: (404) 496-1358 UUCP: ...!gatech!holos0!lbr