S_regmatch(): work around Solaris optimiser bug
authorDavid Mitchell <davem@iabyn.com>
Mon, 4 Apr 2016 12:27:35 +0000 (13:27 +0100)
committerDavid Mitchell <davem@iabyn.com>
Mon, 4 Apr 2016 13:32:51 +0000 (14:32 +0100)
Recently these test scripts started failing on Solaris i386 with
-Duse64bitall:

    re/charset.t
    re/subst.t
    re/substT.t
    re/subst_wamp.t

The first failure is due to a Solaris Studio optimiser bug; this commit
works around that failure. It may or may not also fix the other failures
(all tests pass now on the development box I was using, but I didn't
confirm whether the other tests failed before the fix).

The basic problem is that within the main while loop in S_regmatch(),
the expression PL_charclass['\n'] returns the wrong value.

Looking at the disassembled code, it appears that looking up this value
just before the while loop correctly does it by getting the address of the
global array PL_charclass, adding 40 to it (ord('\n')*sizeof(U32)), then
dereffing it.

Within the loop however, it just reads the value from a local var. The
optimiser is under the misapprehension that this value has previously been
read in and assigned to a local var, but it certainly hasn't been at the
point where the while loop is first entered.

This commit works round the problem on builds with -Duse64bitall and the
bad version of Solaris Studio compiler (12.3), by making a copy of
PL_charclass's address.

This is a bit of hack. For one thing, I don't know whether other versions
of the compiler also need this workaround.

The failures were seen on a 32-bit system with -Duse64bitall: this created
a 64-bit executable (i.e. with 64-bit pointers) with the -m64 compiler
flag. I would speculate that the bug in the compiler relates to to
this particular circumstance (i.e. the bug might not appear for a build
done on a 64-bit OS host with or without -Duse64bitall).

regexec.c

index 0c549df..9acb5a0 100644 (file)
--- a/regexec.c
+++ b/regexec.c
@@ -5232,6 +5232,13 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
     bool is_utf8_pat = reginfo->is_utf8_pat;
     bool match = FALSE;
 
+/* Solaris Studio 12.3 messes up fetching PL_charclass['\n'] */
+#if (defined(__SUNPRO_C) && (__SUNPRO_C == 0x5120) && defined(__x86_64) && defined(USE_64_BIT_ALL))
+#  define SOLARIS_BAD_OPTIMIZER
+    const U32 *pl_charclass_dup = PL_charclass;
+#  define PL_charclass pl_charclass_dup
+#endif
+
 #ifdef DEBUGGING
     GET_RE_DEBUG_FLAGS_DECL;
 #endif
@@ -8316,6 +8323,9 @@ NULL
             /* NOTREACHED */
        }
     }
+#ifdef SOLARIS_BAD_OPTIMIZER
+#  undef pl_charclass_dup
+#endif
 
     /*
     * We get here only if there's trouble -- normally "case END" is