Bug 680547 - Compile Linux 64-bit NS_InvokeByIndex with -mno-avx to allow compiling with -march=native on new hardware, or similar -march flags. r=froydnj
authorL. David Baron <dbaron@dbaron.org>
Tue, 10 Feb 2015 16:04:46 +1100
changeset 241877 3023f9390942ce022a214b224f18cb01bb24daa0
parent 241876 cb655f416527aa70f67fcf8992cf814f843af311
child 241878 b266a69f1947eba525712b4e8c472e3003f816ee
push id625
push userdburns@mozilla.com
push dateTue, 10 Feb 2015 14:14:40 +0000
reviewersfroydnj
bugs680547, 1111355
milestone38.0a1
Bug 680547 - Compile Linux 64-bit NS_InvokeByIndex with -mno-avx to allow compiling with -march=native on new hardware, or similar -march flags. r=froydnj As explained in bug 1111355, having avx enabled appears to change the alignment behavior of alloca (apparently adding an extra 16 bytes) of padding/alignment (and using 32-byte alignment instead of 16-byte). The suggestion of using __bultin_alloca_with_align in bug 1111355 didn't fix the problem, so this seems to be the best available workaround, given that this code, which should perhaps better be written in assembly, is written in C++. Interestingly, this is NOT fixed by #pragma GCC target ("arch=x86-64"). (I determined the (undocumented) name for the default -march value on x86_64 from the gcc source code (gcc/config/i386/i386.c, function ix86_option_override_internal, code that sets opts->x_ix86_arch_string .) I confirmed that this sets the same macros based on the empty diff between the output of 'gcc -E -dM -x c++ /dev/null' and 'gcc -E -dM -x c++ -march=x86-64 /dev/null', which was not an empty diff for other -march values (e.g., k8).) I confirmed that the push_options and pop_options actually work by putting the push/pop pair around a different (earlier) function, and testing that this did not fix the bug (with the pop_options before NS_InvokeByIndex). See the gcc documentation at: https://gcc.gnu.org/onlinedocs/gcc-4.9.0/gcc/Function-Specific-Option-Pragmas.html https://gcc.gnu.org/onlinedocs/gcc-4.9.0/gcc/Function-Attributes.html https://gcc.gnu.org/onlinedocs/gcc-4.9.0/gcc/i386-and-x86-64-Options.html
xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp
--- a/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_x86_64_unix.cpp
@@ -96,16 +96,26 @@ invoke_copy_to_stack(uint64_t * d, uint3
             if (nr_gpr < GPR_COUNT)
                 gpregs[nr_gpr++] = value;
             else
                 *d++ = value;
         }
     }
 }
 
+// Disable avx for the next function to allow compilation with
+// -march=native on new machines, or similar hardcoded -march options.
+// Having avx enabled appears to change the alignment behavior of alloca
+// (apparently adding an extra 16 bytes) of padding/alignment (and using
+// 32-byte alignment instead of 16-byte).  This seems to be the best
+// available workaround, given that this code, which should perhaps
+// better be written in assembly, is written in C++.
+#pragma GCC push_options
+#pragma GCC target ("no-avx")
+
 EXPORT_XPCOM_API(nsresult)
 NS_InvokeByIndex(nsISupports * that, uint32_t methodIndex,
                  uint32_t paramCount, nsXPTCVariant * params)
 {
     uint32_t nr_stack;
     invoke_count_words(paramCount, params, nr_stack);
     
     // Stack, if used, must be 16-bytes aligned
@@ -159,8 +169,10 @@ NS_InvokeByIndex(nsISupports * that, uin
     typedef nsresult (*Method)(uint64_t, uint64_t, uint64_t, uint64_t,
                                uint64_t, uint64_t, double, double, double,
                                double, double, double, double, double);
     nsresult result = ((Method)methodAddress)(a0, a1, a2, a3, a4, a5,
                                               d0, d1, d2, d3, d4, d5,
                                               d6, d7);
     return result;
 }
+
+#pragma GCC pop_options