llvmpipe: Avoid corrupting the FPU stack with MMX instructions on 32bit OSes.
authorJosé Fonseca <jfonseca@vmware.com>
Thu, 22 Jul 2010 17:37:46 +0000 (18:37 +0100)
committerJosé Fonseca <jfonseca@vmware.com>
Thu, 29 Jul 2010 18:10:59 +0000 (19:10 +0100)
Unfortunately LLVM doesn't emit EMMS itself, and there is no
easy/effective way to disable MMX.

http://llvm.org/bugs/show_bug.cgi?id=3287

src/gallium/auxiliary/gallivm/lp_bld_misc.cpp
src/gallium/drivers/llvmpipe/lp_state_fs.c

index 5a9488b5f794ebe78ff56b30227b0b08d578b5cd..072408b26897a04a9f82da04c0f94ff5c89c9feb 100644 (file)
@@ -39,6 +39,7 @@
 #include <llvm/Target/TargetOptions.h>
 #include <llvm/ExecutionEngine/ExecutionEngine.h>
 #include <llvm/ExecutionEngine/JITEventListener.h>
+#include <llvm/Support/CommandLine.h>
 
 #include "pipe/p_config.h"
 #include "util/u_debug.h"
@@ -141,4 +142,27 @@ lp_set_target_options(void)
 #if 0
    llvm::UnsafeFPMath = true;
 #endif
+
+#if 0
+   /*
+    * LLVM will generate MMX instructions for vectors <= 64 bits, leading to
+    * innefficient code, and in 32bit systems, to the corruption of the FPU
+    * stack given that it expects the user to generate the EMMS instructions.
+    *
+    * See also:
+    * - http://llvm.org/bugs/show_bug.cgi?id=3287
+    * - http://l4.me.uk/post/2009/06/07/llvm-wrinkle-3-configuration-what-configuration/
+    *
+    * XXX: Unfortunately this is not working.
+    */
+   static boolean first = FALSE;
+   if (first) {
+      static const char* options[] = {
+         "prog",
+         "-disable-mmx"
+      };
+      llvm::cl::ParseCommandLineOptions(2, const_cast<char**>(options));
+      first = FALSE;
+   }
+#endif
 }
index 5953d690a41c7f3951a42814952b58bb93821d16..dbcc286417af2f915a9cccb6be3c585d6a903296 100644 (file)
@@ -676,6 +676,11 @@ generate_fragment(struct llvmpipe_context *lp,
                     color_ptr);
    }
 
+#ifdef PIPE_ARCH_X86
+   /* Avoid corrupting the FPU stack on 32bit OSes. */
+   lp_build_intrinsic(builder, "llvm.x86.mmx.emms", LLVMVoidType(), NULL, 0);
+#endif
+
    LLVMBuildRetVoid(builder);
 
    LLVMDisposeBuilder(builder);