diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 28cb4df..32ca18a 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -7368,6 +7368,33 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA,
   // handled somewhere else.
   Args.ClaimAllArgs(options::OPT_w);
 
+  if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
+    unsigned Level;
+    const Option &Opt = A->getOption();
+    if (Opt.matches(options::OPT_O0)) {
+      Level = 0;
+    } else if (Opt.matches(options::OPT_O4)) {
+      // FIXME: Should we warn/convert in here? We don't control which levels the linker supports.
+      Level = 4;
+    } else if (Opt.matches(options::OPT_Ofast)) {
+      Level = 3;
+    } else if (Opt.matches(options::OPT_O)) {
+      StringRef S(A->getValue());
+      if (S == "s" || S == "z") {
+        Level = 2;
+      } else {
+        unsigned OptLevel = 0;
+        if (S.getAsInteger(10, OptLevel))
+          Level = 0; // FIXME: Should we produce an error?
+        Level = OptLevel;
+      }
+    } else {
+      llvm_unreachable("Unknown -O option");
+    }
+    if (Level != 0)
+      CmdArgs.push_back(Args.MakeArgString("-O" + Twine(Level)));
+  }
+
   if (!D.SysRoot.empty())
     CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
 
diff --git a/test/Driver/gnu-link-opt.c b/test/Driver/gnu-link-opt.c
new file mode 100644
index 0000000..1989fca
--- /dev/null
+++ b/test/Driver/gnu-link-opt.c
@@ -0,0 +1,43 @@
+// Test that the various -O options are passed to ld, but that -Wl,-O goes after and takes precedence
+
+// RUN: %clang -### %t.o -o %t2 --target=i386-unknown-linux -O0 -Wl,-O1 2>&1 | \
+// RUN:   FileCheck --check-prefix=CHECK-O0 %s
+// CHECK-O0: ld
+// CHECK-O0-NOT: -O
+// CHECK-O0: -O1
+
+// RUN: %clang -### %t.o -o %t2 --target=i386-unknown-linux -O4 -Wl,-O1 2>&1 | \
+// RUN:   FileCheck --check-prefix=CHECK-O4 %s
+// CHECK-O4: ld
+// CHECK-O4: -O4
+// CHECK-O4: -O1
+
+// RUN: %clang -### %t.o -o %t2 --target=i386-unknown-linux -Ofast -Wl,-O1 2>&1 | \
+// RUN:   FileCheck --check-prefix=CHECK-Ofast %s
+// CHECK-Ofast: ld
+// CHECK-Ofast: -O3
+// CHECK-Ofast: -O1
+
+// RUN: %clang -### %t.o -o %t2 --target=i386-unknown-linux -Os -Wl,-O1 2>&1 | \
+// RUN:   FileCheck --check-prefix=CHECK-Os %s
+// CHECK-Os: ld
+// CHECK-Os: -O2
+// CHECK-Os: -O1
+
+// RUN: %clang -### %t.o -o %t2 --target=i386-unknown-linux -Oz -Wl,-O1 2>&1 | \
+// RUN:   FileCheck --check-prefix=CHECK-Oz %s
+// CHECK-Oz: ld
+// CHECK-Oz: -O2
+// CHECK-Oz: -O1
+
+// RUN: %clang -### %t.o -o %t2 --target=i386-unknown-linux -O3 -Wl,-O1 2>&1 | \
+// RUN:   FileCheck --check-prefix=CHECK-O3 %s
+// CHECK-O3: ld
+// CHECK-O3: -O3
+// CHECK-O3: -O1
+
+// RUN: %clang -### %t.o -o %t2 --target=i386-unknown-linux -Ox -Wl,-O1 2>&1 | \
+// RUN:   FileCheck --check-prefix=CHECK-Ox %s
+// CHECK-Ox: ld
+// CHECK-Ox-NOT: -O
+// CHECK-Ox: -O1
