diff --git a/BUILD.gn b/BUILD.gn
index b405f5122..4c9ad3d45 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -34,7 +34,7 @@ config("swiftshader_config") {
     defines += [ "_ENABLE_EXTENDED_ALIGNED_STORAGE" ]
 
     # Diable some MSVC warnings.
-    if (!is_clang) {
+    if (!is_clang && !is_mingw) {
       cflags += [
         "/wd4065",  # switch statement contains 'default' but no 'case' labels
         "/wd4309",  # Truncation of constant value. See PixelRoutine.cpp casts
diff --git a/src/Reactor/BUILD.gn b/src/Reactor/BUILD.gn
index 67dfeb0ec..379bb6468 100644
--- a/src/Reactor/BUILD.gn
+++ b/src/Reactor/BUILD.gn
@@ -16,7 +16,7 @@ import("reactor.gni")
 import("../swiftshader.gni")
 
 config("swiftshader_llvm_reactor_private_config") {
-  if (is_win) {
+  if (is_msvc) {
     cflags = [
       "/wd4141",  # 'inline' used more than once. (LLVM 7.0)
       "/wd4146",  # unary minus operator applied to unsigned type. (LLVM 7.0)
@@ -25,6 +25,8 @@ config("swiftshader_llvm_reactor_private_config") {
       "/wd4245",  # conversion from int to unsigned int (llvm)
       "/wd4624",  # destructor was implicitly defined as deleted (LLVM 7.0)
     ]
+  } else if (is_mingw) {
+    cflags = [ "-Wno-missing-template-keyword" ]
   } else {
     cflags = [ "-Wno-unused-local-typedef" ]
   }
@@ -104,12 +106,20 @@ if (supports_subzero) {
     } else if (is_mac) {
       include_dirs += [ "../../third_party/llvm-subzero/build/MacOS/include/" ]
     }
+
+    if (is_mingw) {
+      defines += [
+        "__STDC_CONSTANT_MACROS",
+        "__STDC_FORMAT_MACROS",
+        "__STDC_LIMIT_MACROS",
+      ]
+    }
   }
 
   config("swiftshader_subzero_private_config") {
     cflags = []
 
-    if (is_win) {
+    if (is_msvc) {
       cflags += [
         "/wd4005",
         "/wd4018",
@@ -155,7 +165,7 @@ if (supports_subzero) {
   config("swiftshader_reactor_with_subzero_private_config") {
     cflags = []
 
-    if (is_win) {
+    if (is_msvc) {
       cflags += [
         "/wd4141",
         "/wd4146",
diff --git a/src/Reactor/SubzeroReactor.cpp b/src/Reactor/SubzeroReactor.cpp
index c0c6b1d6e..c33dd10c5 100644
--- a/src/Reactor/SubzeroReactor.cpp
+++ b/src/Reactor/SubzeroReactor.cpp
@@ -286,7 +286,7 @@ private:
 	static void cpuid(int registers[4], int info)
 	{
 #if defined(__i386__) || defined(__x86_64__)
-#	if defined(_WIN32)
+#	if defined(_MSC_VER)
 		__cpuid(registers, info);
 #	else
 		__asm volatile("cpuid"
diff --git a/src/Vulkan/BUILD.gn b/src/Vulkan/BUILD.gn
index 852068cad..c70307160 100644
--- a/src/Vulkan/BUILD.gn
+++ b/src/Vulkan/BUILD.gn
@@ -50,7 +50,7 @@ config("swiftshader_libvulkan_private_config") {
     defines = [ "VK_EXPORT=" ]
   }
 
-  if (is_clang) {
+  if (is_clang || is_mingw) {
     cflags = [
       "-Wno-unused-private-field",
       "-Wno-switch",
@@ -172,8 +172,10 @@ swiftshader_source_set("_swiftshader_libvulkan") {
 
   if (is_win) {
     libs += [
-      "gdi32.lib",
-      "user32.lib",
+      "psapi",
+      "shell32",
+      "gdi32",
+      "user32",
     ]
   }
 
@@ -200,7 +202,7 @@ swiftshader_source_set("_swiftshader_libvulkan") {
 
 swiftshader_shared_library("swiftshader_libvulkan") {
   # TODO(capn): Use the same ICD name on both Windows and non-Windows.
-  if (is_win) {
+  if (is_msvc) {
     output_name = "vk_swiftshader"
   } else {
     output_name = "libvk_swiftshader"
@@ -242,8 +244,10 @@ action("icd_file") {
   output_icd_file = "${root_out_dir}/${swiftshader_icd_file_name}"
   input_file = swiftshader_icd_file_name
 
-  if (is_win) {
+  if (is_msvc) {
     library_path = ".\\vk_swiftshader.dll"
+  } else if (is_mingw) {
+    library_path = "./libvk_swiftshader.dll"
   } else if (is_mac) {
     library_path = "./libvk_swiftshader.dylib"
   } else if (is_fuchsia) {
diff --git a/third_party/SPIRV-Tools/BUILD.gn b/third_party/SPIRV-Tools/BUILD.gn
index 4848fddd0..7da529600 100644
--- a/third_party/SPIRV-Tools/BUILD.gn
+++ b/third_party/SPIRV-Tools/BUILD.gn
@@ -374,7 +374,7 @@ config("spvtools_internal_config") {
       "-Wno-unreachable-code-break",
       "-Wno-unreachable-code-return",
     ]
-  } else if (!is_win) {
+  } else if (!is_msvc) {
     # Work around a false-positive on a Skia GCC 10 builder.
     cflags += [ "-Wno-format-truncation" ]
   } else {
@@ -382,7 +382,7 @@ config("spvtools_internal_config") {
     cflags += [ "/Zc:__cplusplus" ]
   }
 
-  if (!is_win) {
+  if (!is_msvc) {
     cflags += [ "-std=c++17" ]
   } else {
     cflags += [ "/std:c++17" ]
diff --git a/third_party/llvm-10.0/BUILD.gn b/third_party/llvm-10.0/BUILD.gn
index f99abba37..46754bbc0 100644
--- a/third_party/llvm-10.0/BUILD.gn
+++ b/third_party/llvm-10.0/BUILD.gn
@@ -18,7 +18,7 @@ import("../../src/swiftshader.gni")
 config("swiftshader_llvm_private_config") {
   cflags = []
 
-  if (is_win) {
+  if (is_msvc) {
     cflags += [
       "/wd4005",
       "/wd4018",
@@ -53,6 +53,18 @@ config("swiftshader_llvm_private_config") {
         "-Wno-macro-redefined",
       ]
     }
+  } else if (is_mingw) {
+    cflags += [
+      "-Wno-format",
+      "-Wno-sign-compare",
+    ]
+    if (!is_clang) {
+      cflags_cc = [
+        "-Wno-cast-user-defined",
+        "-Wno-init-list-lifetime",
+        "-Wno-missing-template-keyword",
+      ]
+    }
   }
 
   if (is_fuchsia) {
@@ -80,6 +92,7 @@ config("swiftshader_llvm_private_config") {
 
   defines = [
     "__STDC_CONSTANT_MACROS",
+    "__STDC_FORMAT_MACROS",
     "__STDC_LIMIT_MACROS",
   ]
 }
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Support/Threading.h b/third_party/llvm-10.0/llvm/include/llvm/Support/Threading.h
index bacab8fa2..16ddf6d20 100644
--- a/third_party/llvm-10.0/llvm/include/llvm/Support/Threading.h
+++ b/third_party/llvm-10.0/llvm/include/llvm/Support/Threading.h
@@ -18,7 +18,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX
 #include "llvm/Support/Compiler.h"
-#include <ciso646> // So we can check the C++ standard lib macros.
+#include <version> // So we can check the C++ standard lib macros.
 #include <functional>
 
 #if defined(_MSC_VER)
diff --git a/third_party/llvm-10.0/llvm/include/llvm/Support/Windows/WindowsSupport.h b/third_party/llvm-10.0/llvm/include/llvm/Support/Windows/WindowsSupport.h
index bb7e79b86..640c00eed 100644
--- a/third_party/llvm-10.0/llvm/include/llvm/Support/Windows/WindowsSupport.h
+++ b/third_party/llvm-10.0/llvm/include/llvm/Support/Windows/WindowsSupport.h
@@ -28,7 +28,9 @@
 // Require at least Windows 7 API.
 #define _WIN32_WINNT 0x0601
 #define _WIN32_IE    0x0800 // MinGW at it again. FIXME: verify if still needed.
+#ifndef WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN
+#endif
 #ifndef NOMINMAX
 #define NOMINMAX
 #endif
diff --git a/third_party/llvm-10.0/llvm/lib/Support/ErrorHandling.cpp b/third_party/llvm-10.0/llvm/lib/Support/ErrorHandling.cpp
index a9463024c..2df917cc7 100644
--- a/third_party/llvm-10.0/llvm/lib/Support/ErrorHandling.cpp
+++ b/third_party/llvm-10.0/llvm/lib/Support/ErrorHandling.cpp
@@ -32,7 +32,7 @@
 #if defined(HAVE_UNISTD_H)
 # include <unistd.h>
 #endif
-#if defined(_MSC_VER)
+#if defined(_WIN32)
 # include <io.h>
 # include <fcntl.h>
 #endif
diff --git a/third_party/llvm-subzero/include/llvm/Support/Atomic.h b/third_party/llvm-subzero/include/llvm/Support/Atomic.h
index d03714b00..552313f0c 100644
--- a/third_party/llvm-subzero/include/llvm/Support/Atomic.h
+++ b/third_party/llvm-subzero/include/llvm/Support/Atomic.h
@@ -20,6 +20,11 @@
 
 #include "llvm/Support/DataTypes.h"
 
+// Windows will at times define MemoryFence.
+#ifdef MemoryFence
+#undef MemoryFence
+#endif
+
 namespace llvm {
   namespace sys {
     void MemoryFence();
diff --git a/third_party/llvm-subzero/include/llvm/Support/Threading.h b/third_party/llvm-subzero/include/llvm/Support/Threading.h
index 4bef7ec8d..be8da3621 100644
--- a/third_party/llvm-subzero/include/llvm/Support/Threading.h
+++ b/third_party/llvm-subzero/include/llvm/Support/Threading.h
@@ -17,7 +17,7 @@
 
 #include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX
 #include "llvm/Support/Compiler.h"
-#include <ciso646> // So we can check the C++ standard lib macros.
+#include <version> // So we can check the C++ standard lib macros.
 #include <functional>
 
 // std::call_once from libc++ is used on all Unix platforms. Other
diff --git a/third_party/llvm-subzero/lib/Support/ErrorHandling.cpp b/third_party/llvm-subzero/lib/Support/ErrorHandling.cpp
index a7d3a1800..191264b4b 100644
--- a/third_party/llvm-subzero/lib/Support/ErrorHandling.cpp
+++ b/third_party/llvm-subzero/lib/Support/ErrorHandling.cpp
@@ -33,7 +33,7 @@
 #if defined(HAVE_UNISTD_H)
 # include <unistd.h>
 #endif
-#if defined(_MSC_VER)
+#if defined(_WIN32)
 # include <io.h>
 # include <fcntl.h>
 #endif
diff --git a/third_party/llvm-subzero/lib/Support/Timer.cpp b/third_party/llvm-subzero/lib/Support/Timer.cpp
index 7e95b4514..420b6d1ac 100644
--- a/third_party/llvm-subzero/lib/Support/Timer.cpp
+++ b/third_party/llvm-subzero/lib/Support/Timer.cpp
@@ -22,6 +22,7 @@
 #include "llvm/Support/Process.h"
 #include "llvm/Support/YAMLTraits.h"
 #include "llvm/Support/raw_ostream.h"
+#include <cinttypes>
 #include <ratio>
 using namespace llvm;
 
diff --git a/third_party/llvm-subzero/lib/Support/Windows/Process.inc b/third_party/llvm-subzero/lib/Support/Windows/Process.inc
index 8d646b321..2d56e4c0d 100644
--- a/third_party/llvm-subzero/lib/Support/Windows/Process.inc
+++ b/third_party/llvm-subzero/lib/Support/Windows/Process.inc
@@ -24,14 +24,7 @@
 #include <psapi.h>
 #include <shellapi.h>
 
-#ifdef __MINGW32__
- #if (HAVE_LIBPSAPI != 1)
-  #error "libpsapi.a should be present"
- #endif
- #if (HAVE_LIBSHELL32 != 1)
-  #error "libshell32.a should be present"
- #endif
-#else
+#ifdef _MSC_VER
  #pragma comment(lib, "psapi.lib")
  #pragma comment(lib, "shell32.lib")
 #endif
diff --git a/third_party/llvm-subzero/lib/Support/Windows/Signals.inc b/third_party/llvm-subzero/lib/Support/Windows/Signals.inc
index 38cc56654..edd9f8d3d 100644
--- a/third_party/llvm-subzero/lib/Support/Windows/Signals.inc
+++ b/third_party/llvm-subzero/lib/Support/Windows/Signals.inc
@@ -36,9 +36,6 @@
 #ifdef _MSC_VER
  #pragma comment(lib, "psapi.lib")
 #elif __MINGW32__
- #if (HAVE_LIBPSAPI != 1)
-  #error "libpsapi.a should be present"
- #endif
  // The version of g++ that comes with MinGW does *not* properly understand
  // the ll format specifier for printf. However, MinGW passes the format
  // specifiers on to the MSVCRT entirely, and the CRT understands the ll
diff --git a/third_party/llvm-subzero/lib/Support/Windows/WindowsSupport.h b/third_party/llvm-subzero/lib/Support/Windows/WindowsSupport.h
index c358b99ab..d67b21ec8 100644
--- a/third_party/llvm-subzero/lib/Support/Windows/WindowsSupport.h
+++ b/third_party/llvm-subzero/lib/Support/Windows/WindowsSupport.h
@@ -29,7 +29,9 @@
 // Require at least Windows 7 API.
 #define _WIN32_WINNT 0x0601
 #define _WIN32_IE    0x0800 // MinGW at it again. FIXME: verify if still needed.
+#ifndef WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN
+#endif
 #ifndef NOMINMAX
 #define NOMINMAX
 #endif
diff --git a/third_party/marl/BUILD.gn b/third_party/marl/BUILD.gn
index 4c0264892..ad8ee6239 100644
--- a/third_party/marl/BUILD.gn
+++ b/third_party/marl/BUILD.gn
@@ -14,7 +14,6 @@
 
 import("../../src/swiftshader.gni")
 
-import("//testing/test.gni")
 
 config("marl_config") {
   include_dirs = [ "include" ]
diff --git a/third_party/marl/src/scheduler.cpp b/third_party/marl/src/scheduler.cpp
index 51bb27b44..fd2cf6c0c 100644
--- a/third_party/marl/src/scheduler.cpp
+++ b/third_party/marl/src/scheduler.cpp
@@ -20,7 +20,7 @@
 #include "marl/thread.h"
 #include "marl/trace.h"
 
-#if defined(_WIN32)
+#if defined(_MSC_VER)
 #include <intrin.h>  // __nop()
 #endif
 
@@ -60,7 +60,7 @@ inline uint64_t threadID() {
 #endif
 
 inline void nop() {
-#if defined(_WIN32)
+#if defined(_MSC_VER)
   __nop();
 #else
   __asm__ __volatile__("nop");
diff --git a/third_party/subzero/src/IceTargetLowering.cpp b/third_party/subzero/src/IceTargetLowering.cpp
index ab09b48cb..64cca4cda 100644
--- a/third_party/subzero/src/IceTargetLowering.cpp
+++ b/third_party/subzero/src/IceTargetLowering.cpp
@@ -48,6 +48,7 @@
 //       createTargetHeaderLowering(Ice::GlobalContext *);
 //   void staticInit(::Ice::GlobalContext *);
 // }
+#undef SUBZERO_TARGET
 #define SUBZERO_TARGET(X)                                                      \
   namespace X {                                                                \
   std::unique_ptr<::Ice::TargetLowering>                                       \
diff --git a/third_party/subzero/src/IceTargetLoweringX8632.cpp b/third_party/subzero/src/IceTargetLoweringX8632.cpp
index 6875c8aa3..c5055d6d3 100644
--- a/third_party/subzero/src/IceTargetLoweringX8632.cpp
+++ b/third_party/subzero/src/IceTargetLoweringX8632.cpp
@@ -34,7 +34,7 @@
 
 #include <stack>
 
-#if defined(_WIN32)
+#if defined(_MSC_VER) && defined(_WIN32)
 extern "C" void _chkstk();
 #endif
 
@@ -7868,7 +7868,7 @@ Variable *TargetX8632::moveReturnValueToRegister(Operand *Value,
 }
 
 void TargetX8632::emitStackProbe(size_t StackSizeBytes) {
-#if defined(_WIN32)
+#if defined(_MSC_VER) && defined(_WIN32)
   if (StackSizeBytes >= 4096) {
     // _chkstk on Win32 is actually __alloca_probe, which adjusts ESP by the
     // stack amount specified in EAX, so we save ESP in ECX, and restore them
diff --git a/third_party/subzero/src/IceTargetLoweringX8664.cpp b/third_party/subzero/src/IceTargetLoweringX8664.cpp
index 13f8f85ff..a0f92fe8b 100644
--- a/third_party/subzero/src/IceTargetLoweringX8664.cpp
+++ b/third_party/subzero/src/IceTargetLoweringX8664.cpp
@@ -33,7 +33,7 @@
 
 #include <stack>
 
-#if defined(_WIN64)
+#if defined(_MSC_VER) && defined(_WIN64)
 extern "C" void __chkstk();
 #endif
 
@@ -7183,7 +7183,7 @@ Variable *TargetX8664::moveReturnValueToRegister(Operand *Value,
 }
 
 void TargetX8664::emitStackProbe(size_t StackSizeBytes) {
-#if defined(_WIN64)
+#if defined(_MSC_VER) && defined(_WIN64)
   // Mirroring the behavior of MSVC here, which emits a _chkstk when locals are
   // >= 4KB, rather than the 8KB claimed by the docs.
   if (StackSizeBytes >= 4096) {
