[clang] 97e4960 - [Clang][CSKY] Add the CSKY target and compiler driver

Zi Xuan Wu via cfe-commits cfe-commits at lists.llvm.org
Tue Apr 5 20:38:03 PDT 2022


Author: Zi Xuan Wu
Date: 2022-04-06T11:37:37+08:00
New Revision: 97e496054a378131227262109c856f89b288c309

URL: https://github.com/llvm/llvm-project/commit/97e496054a378131227262109c856f89b288c309
DIFF: https://github.com/llvm/llvm-project/commit/97e496054a378131227262109c856f89b288c309.diff

LOG: [Clang][CSKY] Add the CSKY target and compiler driver

Add CSKY target toolchains to support csky in linux and elf environment.

It can leverage the basic universal Linux toolchain for linux environment, and only add some compile or link parameters.
For elf environment, add a CSKYToolChain to support compile and link.

Also add some parameters into basic codebase of clang driver.

Differential Revision: https://reviews.llvm.org/D121445

Added: 
    clang/lib/Basic/Targets/CSKY.cpp
    clang/lib/Basic/Targets/CSKY.h
    clang/lib/Driver/ToolChains/Arch/CSKY.cpp
    clang/lib/Driver/ToolChains/Arch/CSKY.h
    clang/lib/Driver/ToolChains/CSKYToolChain.cpp
    clang/lib/Driver/ToolChains/CSKYToolChain.h
    clang/test/Driver/Inputs/multilib_csky_linux_sdk/csky-linux-gnuabiv2/bin/ld
    clang/test/Driver/Inputs/multilib_csky_linux_sdk/csky-linux-gnuabiv2/libc/ck860v/lib/.keep
    clang/test/Driver/Inputs/multilib_csky_linux_sdk/csky-linux-gnuabiv2/libc/ck860v/usr/lib/crt1.o
    clang/test/Driver/Inputs/multilib_csky_linux_sdk/csky-linux-gnuabiv2/libc/lib/.keep
    clang/test/Driver/Inputs/multilib_csky_linux_sdk/csky-linux-gnuabiv2/libc/usr/lib/crt1.o
    clang/test/Driver/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/ck860v/crtbegin.o
    clang/test/Driver/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/ck860v/crtend.o
    clang/test/Driver/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/ck860v/crti.o
    clang/test/Driver/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/ck860v/crtn.o
    clang/test/Driver/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/crtbegin.o
    clang/test/Driver/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/crtend.o
    clang/test/Driver/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/crti.o
    clang/test/Driver/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/crtn.o
    clang/test/Driver/csky-arch-error.c
    clang/test/Driver/csky-arch.c
    clang/test/Driver/csky-cpus-error.c
    clang/test/Driver/csky-cpus.c
    clang/test/Driver/csky-toolchain.c
    clang/test/Preprocessor/csky-target-features.c
    clang/test/Preprocessor/init-csky.c

Modified: 
    clang/lib/Basic/CMakeLists.txt
    clang/lib/Basic/Targets.cpp
    clang/lib/Driver/CMakeLists.txt
    clang/lib/Driver/Driver.cpp
    clang/lib/Driver/ToolChains/Clang.cpp
    clang/lib/Driver/ToolChains/CommonArgs.cpp
    clang/lib/Driver/ToolChains/Gnu.cpp
    clang/lib/Driver/ToolChains/Linux.cpp
    llvm/lib/Support/CSKYTargetParser.cpp
    llvm/unittests/Support/CSKYTargetParserTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Basic/CMakeLists.txt b/clang/lib/Basic/CMakeLists.txt
index 12ed97b99b45f..c815b571bc9c0 100644
--- a/clang/lib/Basic/CMakeLists.txt
+++ b/clang/lib/Basic/CMakeLists.txt
@@ -75,6 +75,7 @@ add_clang_library(clangBasic
   Targets/ARM.cpp
   Targets/AVR.cpp
   Targets/BPF.cpp
+  Targets/CSKY.cpp
   Targets/DirectX.cpp
   Targets/Hexagon.cpp
   Targets/Lanai.cpp

diff  --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index 641345452cfe3..85c73abde1826 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -19,6 +19,7 @@
 #include "Targets/ARM.h"
 #include "Targets/AVR.h"
 #include "Targets/BPF.h"
+#include "Targets/CSKY.h"
 #include "Targets/DirectX.h"
 #include "Targets/Hexagon.h"
 #include "Targets/Lanai.h"
@@ -659,6 +660,14 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple,
 
   case llvm::Triple::ve:
     return new LinuxTargetInfo<VETargetInfo>(Triple, Opts);
+
+  case llvm::Triple::csky:
+    switch (os) {
+    case llvm::Triple::Linux:
+      return new LinuxTargetInfo<CSKYTargetInfo>(Triple, Opts);
+    default:
+      return new CSKYTargetInfo(Triple, Opts);
+    }
   }
 }
 } // namespace targets

diff  --git a/clang/lib/Basic/Targets/CSKY.cpp b/clang/lib/Basic/Targets/CSKY.cpp
new file mode 100644
index 0000000000000..40004da982594
--- /dev/null
+++ b/clang/lib/Basic/Targets/CSKY.cpp
@@ -0,0 +1,295 @@
+//===--- CSKY.cpp - Implement CSKY target feature support -----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements CSKY TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CSKY.h"
+
+using namespace clang;
+using namespace clang::targets;
+
+bool CSKYTargetInfo::isValidCPUName(StringRef Name) const {
+  return llvm::CSKY::parseCPUArch(Name) != llvm::CSKY::ArchKind::INVALID;
+}
+
+bool CSKYTargetInfo::setCPU(const std::string &Name) {
+  llvm::CSKY::ArchKind archKind = llvm::CSKY::parseCPUArch(Name);
+  bool isValid = (archKind != llvm::CSKY::ArchKind::INVALID);
+
+  if (isValid) {
+    CPU = Name;
+    Arch = archKind;
+  }
+
+  return isValid;
+}
+
+void CSKYTargetInfo::getTargetDefines(const LangOptions &Opts,
+                                      MacroBuilder &Builder) const {
+  Builder.defineMacro("__ELF__");
+  Builder.defineMacro("__csky__", "2");
+  Builder.defineMacro("__CSKY__", "2");
+  Builder.defineMacro("__ckcore__", "2");
+  Builder.defineMacro("__CKCORE__", "2");
+
+  Builder.defineMacro("__CSKYABI__", ABI == "abiv2" ? "2" : "1");
+  Builder.defineMacro("__cskyabi__", ABI == "abiv2" ? "2" : "1");
+
+  StringRef ArchName = "ck810";
+  StringRef CPUName = "ck810";
+
+  if (Arch != llvm::CSKY::ArchKind::INVALID) {
+    ArchName = llvm::CSKY::getArchName(Arch);
+    CPUName = CPU;
+  }
+
+  Builder.defineMacro("__" + ArchName.upper() + "__");
+  Builder.defineMacro("__" + ArchName.lower() + "__");
+  Builder.defineMacro("__" + CPUName.upper() + "__");
+  Builder.defineMacro("__" + CPUName.lower() + "__");
+
+  // TODO: Add support for BE if BE was supported later
+  StringRef endian = "__cskyLE__";
+
+  Builder.defineMacro(endian);
+  Builder.defineMacro(endian.upper());
+  Builder.defineMacro(endian.lower());
+
+  if (DSPV2) {
+    StringRef dspv2 = "__CSKY_DSPV2__";
+    Builder.defineMacro(dspv2);
+    Builder.defineMacro(dspv2.lower());
+  }
+
+  if (VDSPV2) {
+    StringRef vdspv2 = "__CSKY_VDSPV2__";
+    Builder.defineMacro(vdspv2);
+    Builder.defineMacro(vdspv2.lower());
+
+    if (HardFloat) {
+      StringRef vdspv2_f = "__CSKY_VDSPV2_F__";
+      Builder.defineMacro(vdspv2_f);
+      Builder.defineMacro(vdspv2_f.lower());
+    }
+  }
+  if (VDSPV1) {
+    StringRef vdspv1_64 = "__CSKY_VDSP64__";
+    StringRef vdspv1_128 = "__CSKY_VDSP128__";
+
+    Builder.defineMacro(vdspv1_64);
+    Builder.defineMacro(vdspv1_64.lower());
+    Builder.defineMacro(vdspv1_128);
+    Builder.defineMacro(vdspv1_128.lower());
+  }
+  if (is3E3R1) {
+    StringRef is3e3r1 = "__CSKY_3E3R1__";
+    Builder.defineMacro(is3e3r1);
+    Builder.defineMacro(is3e3r1.lower());
+  }
+}
+
+bool CSKYTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
+                                          DiagnosticsEngine &Diags) {
+  HardFloat = false;
+  VDSPV2 = false;
+  VDSPV1 = false;
+  DSPV2 = false;
+  is3E3R1 = false;
+
+  for (const auto &Feature : Features) {
+    if (Feature == "+hard-float")
+      HardFloat = true;
+    if (Feature == "+vdspv2")
+      VDSPV2 = true;
+    if (Feature == "+dspv2")
+      DSPV2 = true;
+    if (Feature == "+vdspv1")
+      VDSPV1 = true;
+    if (Feature == "+3e3r1")
+      is3E3R1 = true;
+  }
+
+  return true;
+}
+
+ArrayRef<Builtin::Info> CSKYTargetInfo::getTargetBuiltins() const {
+  return ArrayRef<Builtin::Info>();
+}
+
+ArrayRef<const char *> CSKYTargetInfo::getGCCRegNames() const {
+  static const char *const GCCRegNames[] = {
+      // Integer registers
+      "r0",
+      "r1",
+      "r2",
+      "r3",
+      "r4",
+      "r5",
+      "r6",
+      "r7",
+      "r8",
+      "r9",
+      "r10",
+      "r11",
+      "r12",
+      "r13",
+      "r14",
+      "r15",
+      "r16",
+      "r17",
+      "r18",
+      "r19",
+      "r20",
+      "r21",
+      "r22",
+      "r23",
+      "r24",
+      "r25",
+      "r26",
+      "r27",
+      "r28",
+      "r29",
+      "r30",
+      "r31",
+
+      // Floating point registers
+      "fr0",
+      "fr1",
+      "fr2",
+      "fr3",
+      "fr4",
+      "fr5",
+      "fr6",
+      "fr7",
+      "fr8",
+      "fr9",
+      "fr10",
+      "fr11",
+      "fr12",
+      "fr13",
+      "fr14",
+      "fr15",
+      "fr16",
+      "fr17",
+      "fr18",
+      "fr19",
+      "fr20",
+      "fr21",
+      "fr22",
+      "fr23",
+      "fr24",
+      "fr25",
+      "fr26",
+      "fr27",
+      "fr28",
+      "fr29",
+      "fr30",
+      "fr31",
+
+  };
+  return llvm::makeArrayRef(GCCRegNames);
+}
+
+ArrayRef<TargetInfo::GCCRegAlias> CSKYTargetInfo::getGCCRegAliases() const {
+  static const TargetInfo::GCCRegAlias GCCRegAliases[] = {
+      {{"a0"}, "r0"},
+      {{"a1"}, "r1"},
+      {{"a2"}, "r2"},
+      {{"a3"}, "r3"},
+      {{"l0"}, "r4"},
+      {{"l1"}, "r5"},
+      {{"l2"}, "r6"},
+      {{"l3"}, "r7"},
+      {{"l4"}, "r8"},
+      {{"l5"}, "r9"},
+      {{"l6"}, "r10"},
+      {{"l7"}, "r11"},
+      {{"t0"}, "r12"},
+      {{"t1"}, "r13"},
+      {{"sp"}, "r14"},
+      {{"lr"}, "r15"},
+      {{"l8"}, "r16"},
+      {{"l9"}, "r17"},
+      {{"t2"}, "r18"},
+      {{"t3"}, "r19"},
+      {{"t4"}, "r20"},
+      {{"t5"}, "r21"},
+      {{"t6"}, "r22"},
+      {{"t7", "fp"}, "r23"},
+      {{"t8", "top"}, "r24"},
+      {{"t9", "bsp"}, "r25"},
+      {{"r26"}, "r26"},
+      {{"r27"}, "r27"},
+      {{"gb", "rgb", "rdb"}, "r28"},
+      {{"tb", "rtb"}, "r29"},
+      {{"svbr"}, "r30"},
+      {{"tls"}, "r31"},
+
+      {{"vr0"}, "fr0"},
+      {{"vr1"}, "fr1"},
+      {{"vr2"}, "fr2"},
+      {{"vr3"}, "fr3"},
+      {{"vr4"}, "fr4"},
+      {{"vr5"}, "fr5"},
+      {{"vr6"}, "fr6"},
+      {{"vr7"}, "fr7"},
+      {{"vr8"}, "fr8"},
+      {{"vr9"}, "fr9"},
+      {{"vr10"}, "fr10"},
+      {{"vr11"}, "fr11"},
+      {{"vr12"}, "fr12"},
+      {{"vr13"}, "fr13"},
+      {{"vr14"}, "fr14"},
+      {{"vr15"}, "fr15"},
+      {{"vr16"}, "fr16"},
+      {{"vr17"}, "fr17"},
+      {{"vr18"}, "fr18"},
+      {{"vr19"}, "fr19"},
+      {{"vr20"}, "fr20"},
+      {{"vr21"}, "fr21"},
+      {{"vr22"}, "fr22"},
+      {{"vr23"}, "fr23"},
+      {{"vr24"}, "fr24"},
+      {{"vr25"}, "fr25"},
+      {{"vr26"}, "fr26"},
+      {{"vr27"}, "fr27"},
+      {{"vr28"}, "fr28"},
+      {{"vr29"}, "fr29"},
+      {{"vr30"}, "fr30"},
+      {{"vr31"}, "fr31"},
+
+  };
+  return llvm::makeArrayRef(GCCRegAliases);
+}
+
+bool CSKYTargetInfo::validateAsmConstraint(
+    const char *&Name, TargetInfo::ConstraintInfo &Info) const {
+  switch (*Name) {
+  default:
+    return false;
+  case 'a':
+  case 'b':
+  case 'c':
+  case 'y':
+  case 'l':
+  case 'h':
+  case 'w':
+  case 'v': // A floating-point and vector register.
+  case 'z':
+    Info.setAllowsRegister();
+    return true;
+  }
+}
+
+unsigned CSKYTargetInfo::getMinGlobalAlign(uint64_t Size) const {
+  if (Size >= 32)
+    return 32;
+  return 0;
+}

diff  --git a/clang/lib/Basic/Targets/CSKY.h b/clang/lib/Basic/Targets/CSKY.h
new file mode 100644
index 0000000000000..17e5f30d3cd87
--- /dev/null
+++ b/clang/lib/Basic/Targets/CSKY.h
@@ -0,0 +1,101 @@
+//===--- CSKY.h - Declare CSKY target feature support -----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares CSKY TargetInfo objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_CSKY_H
+#define LLVM_CLANG_LIB_BASIC_TARGETS_CSKY_H
+
+#include "clang/Basic/MacroBuilder.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/Support/CSKYTargetParser.h"
+
+namespace clang {
+namespace targets {
+
+class LLVM_LIBRARY_VISIBILITY CSKYTargetInfo : public TargetInfo {
+protected:
+  std::string ABI;
+  llvm::CSKY::ArchKind Arch = llvm::CSKY::ArchKind::INVALID;
+  std::string CPU;
+
+  bool HardFloat;
+  bool VDSPV2;
+  bool VDSPV1;
+  bool DSPV2;
+  bool is3E3R1;
+
+public:
+  CSKYTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+      : TargetInfo(Triple) {
+    NoAsmVariants = true;
+    LongLongAlign = 32;
+    SuitableAlign = 32;
+    DoubleAlign = LongDoubleAlign = 32;
+    SizeType = UnsignedInt;
+    PtrDiffType = SignedInt;
+    IntPtrType = SignedInt;
+    WCharType = SignedInt;
+    WIntType = UnsignedInt;
+
+    UseZeroLengthBitfieldAlignment = true;
+    MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32;
+    resetDataLayout("e-m:e-S32-p:32:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-"
+                    "v64:32:32-v128:32:32-a:0:32-Fi32-n32");
+
+    setABI("abiv2");
+  }
+
+  StringRef getABI() const override { return ABI; }
+  bool setABI(const std::string &Name) override {
+    if (Name == "abiv2" || Name == "abiv1") {
+      ABI = Name;
+      return true;
+    }
+    return false;
+  }
+
+  bool setCPU(const std::string &Name) override;
+
+  bool isValidCPUName(StringRef Name) const override;
+
+  virtual unsigned getMinGlobalAlign(uint64_t) const override;
+
+  ArrayRef<Builtin::Info> getTargetBuiltins() const override;
+
+  BuiltinVaListKind getBuiltinVaListKind() const override {
+    return VoidPtrBuiltinVaList;
+  }
+
+  bool validateAsmConstraint(const char *&Name,
+                             TargetInfo::ConstraintInfo &info) const override;
+
+  const char *getClobbers() const override { return ""; }
+
+  void getTargetDefines(const LangOptions &Opts,
+                        MacroBuilder &Builder) const override;
+  bool handleTargetFeatures(std::vector<std::string> &Features,
+                            DiagnosticsEngine &Diags) override;
+
+  /// Whether target allows to overalign ABI-specified preferred alignment
+  bool allowsLargerPreferedTypeAlignment() const override { return false; }
+
+  bool hasBitIntType() const override { return true; }
+
+protected:
+  ArrayRef<const char *> getGCCRegNames() const override;
+
+  ArrayRef<GCCRegAlias> getGCCRegAliases() const override;
+};
+
+} // namespace targets
+} // namespace clang
+
+#endif // LLVM_CLANG_LIB_BASIC_TARGETS_CSKY_H

diff  --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt
index 00c7a8f893ff4..dc6d370810abb 100644
--- a/clang/lib/Driver/CMakeLists.txt
+++ b/clang/lib/Driver/CMakeLists.txt
@@ -27,6 +27,7 @@ add_clang_library(clangDriver
   ToolChain.cpp
   ToolChains/Arch/AArch64.cpp
   ToolChains/Arch/ARM.cpp
+  ToolChains/Arch/CSKY.cpp
   ToolChains/Arch/M68k.cpp
   ToolChains/Arch/Mips.cpp
   ToolChains/Arch/PPC.cpp
@@ -46,6 +47,7 @@ add_clang_library(clangDriver
   ToolChains/CommonArgs.cpp
   ToolChains/Contiki.cpp
   ToolChains/CrossWindows.cpp
+  ToolChains/CSKYToolChain.cpp
   ToolChains/Cuda.cpp
   ToolChains/Darwin.cpp
   ToolChains/DragonFly.cpp

diff  --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 0c79cc7589e19..392364ce22bad 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -13,6 +13,7 @@
 #include "ToolChains/AVR.h"
 #include "ToolChains/Ananas.h"
 #include "ToolChains/BareMetal.h"
+#include "ToolChains/CSKYToolChain.h"
 #include "ToolChains/Clang.h"
 #include "ToolChains/CloudABI.h"
 #include "ToolChains/Contiki.h"
@@ -5726,6 +5727,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
       case llvm::Triple::spirv64:
         TC = std::make_unique<toolchains::SPIRVToolChain>(*this, Target, Args);
         break;
+      case llvm::Triple::csky:
+        TC = std::make_unique<toolchains::CSKYToolChain>(*this, Target, Args);
+        break;
       default:
         if (Target.getVendor() == llvm::Triple::Myriad)
           TC = std::make_unique<toolchains::MyriadToolChain>(*this, Target,

diff  --git a/clang/lib/Driver/ToolChains/Arch/CSKY.cpp b/clang/lib/Driver/ToolChains/Arch/CSKY.cpp
new file mode 100644
index 0000000000000..fb809956afa80
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/Arch/CSKY.cpp
@@ -0,0 +1,154 @@
+//===--- CSKY.cpp - CSKY Helpers for Tools --------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "CSKY.h"
+#include "ToolChains/CommonArgs.h"
+#include "clang/Basic/CharInfo.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/CSKYTargetParser.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/TargetParser.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+llvm::Optional<llvm::StringRef>
+csky::getCSKYArchName(const Driver &D, const ArgList &Args,
+                      const llvm::Triple &Triple) {
+  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+    llvm::CSKY::ArchKind ArchKind = llvm::CSKY::parseArch(A->getValue());
+
+    if (ArchKind == llvm::CSKY::ArchKind::INVALID) {
+      D.Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args);
+      return llvm::Optional<llvm::StringRef>();
+    }
+    return llvm::Optional<llvm::StringRef>(A->getValue());
+  }
+
+  if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) {
+    llvm::CSKY::ArchKind ArchKind = llvm::CSKY::parseCPUArch(A->getValue());
+    if (ArchKind == llvm::CSKY::ArchKind::INVALID) {
+      D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+      return llvm::Optional<llvm::StringRef>();
+    }
+    return llvm::Optional<llvm::StringRef>(llvm::CSKY::getArchName(ArchKind));
+  }
+
+  return llvm::Optional<llvm::StringRef>("ck810");
+}
+
+csky::FloatABI csky::getCSKYFloatABI(const Driver &D, const ArgList &Args) {
+  csky::FloatABI ABI = FloatABI::Soft;
+  if (Arg *A =
+          Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
+                          options::OPT_mfloat_abi_EQ)) {
+    if (A->getOption().matches(options::OPT_msoft_float)) {
+      ABI = FloatABI::Soft;
+    } else if (A->getOption().matches(options::OPT_mhard_float)) {
+      ABI = FloatABI::Hard;
+    } else {
+      ABI = llvm::StringSwitch<csky::FloatABI>(A->getValue())
+                .Case("soft", FloatABI::Soft)
+                .Case("softfp", FloatABI::SoftFP)
+                .Case("hard", FloatABI::Hard)
+                .Default(FloatABI::Invalid);
+      if (ABI == FloatABI::Invalid) {
+        D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
+        ABI = FloatABI::Soft;
+      }
+    }
+  }
+
+  return ABI;
+}
+
+// Handle -mfpu=.
+static llvm::CSKY::CSKYFPUKind
+getCSKYFPUFeatures(const Driver &D, const Arg *A, const ArgList &Args,
+                   StringRef FPU, std::vector<StringRef> &Features) {
+
+  llvm::CSKY::CSKYFPUKind FPUID =
+      llvm::StringSwitch<llvm::CSKY::CSKYFPUKind>(FPU)
+          .Case("auto", llvm::CSKY::FK_AUTO)
+          .Case("fpv2", llvm::CSKY::FK_FPV2)
+          .Case("fpv2_divd", llvm::CSKY::FK_FPV2_DIVD)
+          .Case("fpv2_sf", llvm::CSKY::FK_FPV2_SF)
+          .Case("fpv3", llvm::CSKY::FK_FPV3)
+          .Case("fpv3_hf", llvm::CSKY::FK_FPV3_HF)
+          .Case("fpv3_hsf", llvm::CSKY::FK_FPV3_HSF)
+          .Case("fpv3_sdf", llvm::CSKY::FK_FPV3_SDF)
+          .Default(llvm::CSKY::FK_INVALID);
+
+  if (!llvm::CSKY::getFPUFeatures(FPUID, Features)) {
+    D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+    return llvm::CSKY::FK_INVALID;
+  }
+
+  return FPUID;
+}
+
+void csky::getCSKYTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+                                 const ArgList &Args, ArgStringList &CmdArgs,
+                                 std::vector<llvm::StringRef> &Features) {
+  llvm::StringRef archName;
+  llvm::StringRef cpuName;
+  llvm::CSKY::ArchKind ArchKind = llvm::CSKY::ArchKind::INVALID;
+  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+    ArchKind = llvm::CSKY::parseArch(A->getValue());
+    if (ArchKind == llvm::CSKY::ArchKind::INVALID) {
+      D.Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args);
+      return;
+    }
+    archName = A->getValue();
+  }
+
+  if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) {
+    llvm::CSKY::ArchKind Kind = llvm::CSKY::parseCPUArch(A->getValue());
+    if (Kind == llvm::CSKY::ArchKind::INVALID) {
+      D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+      return;
+    }
+    if (!archName.empty() && Kind != ArchKind) {
+      D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
+      return;
+    }
+    cpuName = A->getValue();
+  }
+
+  if (archName.empty() && cpuName.empty()) {
+    archName = "ck810";
+    cpuName = "ck810";
+  } else if (!archName.empty() && cpuName.empty()) {
+    cpuName = archName;
+  }
+
+  csky::FloatABI FloatABI = csky::getCSKYFloatABI(D, Args);
+
+  if (FloatABI == csky::FloatABI::Hard) {
+    Features.push_back("+hard-float-abi");
+    Features.push_back("+hard-float");
+  } else if (FloatABI == csky::FloatABI::SoftFP) {
+    Features.push_back("+hard-float");
+  }
+
+  if (const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ))
+    getCSKYFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features);
+  else if (FloatABI != csky::FloatABI::Soft && archName.empty())
+    llvm::CSKY::getFPUFeatures(llvm::CSKY::FK_AUTO, Features);
+
+  uint64_t Extension = llvm::CSKY::getDefaultExtensions(cpuName);
+  llvm::CSKY::getExtensionFeatures(Extension, Features);
+}

diff  --git a/clang/lib/Driver/ToolChains/Arch/CSKY.h b/clang/lib/Driver/ToolChains/Arch/CSKY.h
new file mode 100644
index 0000000000000..d23da1d66e357
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/Arch/CSKY.h
@@ -0,0 +1,47 @@
+//===--- CSKY.h - CSKY-specific Tool Helpers ------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_CSKY_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_CSKY_H
+
+#include "clang/Driver/Driver.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/Option.h"
+#include <string>
+#include <vector>
+
+namespace clang {
+namespace driver {
+namespace tools {
+namespace csky {
+
+enum class FloatABI {
+  Invalid,
+  Soft,
+  SoftFP,
+  Hard,
+};
+
+FloatABI getCSKYFloatABI(const Driver &D, const llvm::opt::ArgList &Args);
+
+void getCSKYTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+                           const llvm::opt::ArgList &Args,
+                           llvm::opt::ArgStringList &CmdArgs,
+                           std::vector<llvm::StringRef> &Features);
+
+llvm::Optional<llvm::StringRef> getCSKYArchName(const Driver &D,
+                                                const llvm::opt::ArgList &Args,
+                                                const llvm::Triple &Triple);
+
+} // end namespace csky
+} // namespace tools
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_CSKY_H

diff  --git a/clang/lib/Driver/ToolChains/CSKYToolChain.cpp b/clang/lib/Driver/ToolChains/CSKYToolChain.cpp
new file mode 100644
index 0000000000000..de286faaca6d8
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/CSKYToolChain.cpp
@@ -0,0 +1,204 @@
+//===--- CSKYToolchain.cpp - CSKY ToolChain Implementations ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "CSKYToolChain.h"
+#include "CommonArgs.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/InputInfo.h"
+#include "clang/Driver/Options.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang::driver;
+using namespace clang::driver::toolchains;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+static void addMultilibsFilePaths(const Driver &D, const MultilibSet &Multilibs,
+                                  const Multilib &Multilib,
+                                  StringRef InstallPath,
+                                  ToolChain::path_list &Paths) {
+  if (const auto &PathsCallback = Multilibs.filePathsCallback())
+    for (const auto &Path : PathsCallback(Multilib))
+      addPathIfExists(D, InstallPath + Path, Paths);
+}
+
+/// CSKY Toolchain
+CSKYToolChain::CSKYToolChain(const Driver &D, const llvm::Triple &Triple,
+                             const ArgList &Args)
+    : Generic_ELF(D, Triple, Args) {
+  GCCInstallation.init(Triple, Args);
+  if (GCCInstallation.isValid()) {
+    Multilibs = GCCInstallation.getMultilibs();
+    SelectedMultilib = GCCInstallation.getMultilib();
+    path_list &Paths = getFilePaths();
+    // Add toolchain/multilib specific file paths.
+    addMultilibsFilePaths(D, Multilibs, SelectedMultilib,
+                          GCCInstallation.getInstallPath(), Paths);
+    getFilePaths().push_back(GCCInstallation.getInstallPath().str() +
+                             SelectedMultilib.osSuffix());
+    ToolChain::path_list &PPaths = getProgramPaths();
+    // Multilib cross-compiler GCC installations put ld in a triple-prefixed
+    // directory off of the parent of the GCC installation.
+    PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" +
+                           GCCInstallation.getTriple().str() + "/bin")
+                         .str());
+    PPaths.push_back((GCCInstallation.getParentLibPath() + "/../bin").str());
+  } else {
+    getProgramPaths().push_back(D.Dir);
+  }
+  getFilePaths().push_back(computeSysRoot() + "/lib" +
+                           SelectedMultilib.osSuffix());
+}
+
+Tool *CSKYToolChain::buildLinker() const {
+  return new tools::CSKY::Linker(*this);
+}
+
+ToolChain::RuntimeLibType CSKYToolChain::GetDefaultRuntimeLibType() const {
+  return GCCInstallation.isValid() ? ToolChain::RLT_Libgcc
+                                   : ToolChain::RLT_CompilerRT;
+}
+
+ToolChain::UnwindLibType
+CSKYToolChain::GetUnwindLibType(const llvm::opt::ArgList &Args) const {
+  return ToolChain::UNW_None;
+}
+
+void CSKYToolChain::addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+                                          llvm::opt::ArgStringList &CC1Args,
+                                          Action::OffloadKind) const {
+  CC1Args.push_back("-nostdsysteminc");
+}
+
+void CSKYToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+                                              ArgStringList &CC1Args) const {
+  if (DriverArgs.hasArg(options::OPT_nostdinc))
+    return;
+
+  if (!DriverArgs.hasArg(options::OPT_nostdlibinc)) {
+    SmallString<128> Dir(computeSysRoot());
+    llvm::sys::path::append(Dir, "include");
+    addSystemInclude(DriverArgs, CC1Args, Dir.str());
+    SmallString<128> Dir2(computeSysRoot());
+    llvm::sys::path::append(Dir2, "sys-include");
+    addSystemInclude(DriverArgs, CC1Args, Dir2.str());
+  }
+}
+
+void CSKYToolChain::addLibStdCxxIncludePaths(
+    const llvm::opt::ArgList &DriverArgs,
+    llvm::opt::ArgStringList &CC1Args) const {
+  const GCCVersion &Version = GCCInstallation.getVersion();
+  StringRef TripleStr = GCCInstallation.getTriple().str();
+  const Multilib &Multilib = GCCInstallation.getMultilib();
+  addLibStdCXXIncludePaths(computeSysRoot() + "/include/c++/" + Version.Text,
+                           TripleStr, Multilib.includeSuffix(), DriverArgs,
+                           CC1Args);
+}
+
+std::string CSKYToolChain::computeSysRoot() const {
+  if (!getDriver().SysRoot.empty())
+    return getDriver().SysRoot;
+
+  SmallString<128> SysRootDir;
+  if (GCCInstallation.isValid()) {
+    StringRef LibDir = GCCInstallation.getParentLibPath();
+    StringRef TripleStr = GCCInstallation.getTriple().str();
+    llvm::sys::path::append(SysRootDir, LibDir, "..", TripleStr);
+  } else {
+    // Use the triple as provided to the driver. Unlike the parsed triple
+    // this has not been normalized to always contain every field.
+    llvm::sys::path::append(SysRootDir, getDriver().Dir, "..",
+                            getDriver().getTargetTriple());
+  }
+
+  if (!llvm::sys::fs::exists(SysRootDir))
+    return std::string();
+
+  return std::string(SysRootDir.str());
+}
+
+void CSKY::Linker::ConstructJob(Compilation &C, const JobAction &JA,
+                                const InputInfo &Output,
+                                const InputInfoList &Inputs,
+                                const ArgList &Args,
+                                const char *LinkingOutput) const {
+  const ToolChain &ToolChain = getToolChain();
+  const Driver &D = ToolChain.getDriver();
+  ArgStringList CmdArgs;
+
+  if (!D.SysRoot.empty())
+    CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
+
+  CmdArgs.push_back("-m");
+  CmdArgs.push_back("cskyelf");
+
+  std::string Linker = getToolChain().GetLinkerPath();
+
+  bool WantCRTs =
+      !Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles);
+
+  const char *crtbegin, *crtend;
+  auto RuntimeLib = ToolChain.GetRuntimeLibType(Args);
+  if (RuntimeLib == ToolChain::RLT_Libgcc) {
+    crtbegin = "crtbegin.o";
+    crtend = "crtend.o";
+  } else {
+    assert(RuntimeLib == ToolChain::RLT_CompilerRT);
+    crtbegin = ToolChain.getCompilerRTArgString(Args, "crtbegin",
+                                                ToolChain::FT_Object);
+    crtend =
+        ToolChain.getCompilerRTArgString(Args, "crtend", ToolChain::FT_Object);
+  }
+
+  if (WantCRTs) {
+    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
+    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o")));
+    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtbegin)));
+  }
+
+  Args.AddAllArgs(CmdArgs, options::OPT_L);
+  ToolChain.AddFilePathLibArgs(Args, CmdArgs);
+  Args.AddAllArgs(CmdArgs,
+                  {options::OPT_T_Group, options::OPT_e, options::OPT_s,
+                   options::OPT_t, options::OPT_Z_Flag, options::OPT_r});
+
+  AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
+
+  // TODO: add C++ includes and libs if compiling C++.
+
+  if (!Args.hasArg(options::OPT_nostdlib) &&
+      !Args.hasArg(options::OPT_nodefaultlibs)) {
+    if (ToolChain.ShouldLinkCXXStdlib(Args))
+      ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+    CmdArgs.push_back("--start-group");
+    CmdArgs.push_back("-lc");
+    if (Args.hasArg(options::OPT_msim))
+      CmdArgs.push_back("-lsemi");
+    else
+      CmdArgs.push_back("-lnosys");
+    CmdArgs.push_back("--end-group");
+    AddRunTimeLibs(ToolChain, ToolChain.getDriver(), CmdArgs, Args);
+  }
+
+  if (WantCRTs) {
+    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
+    CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
+  }
+
+  CmdArgs.push_back("-o");
+  CmdArgs.push_back(Output.getFilename());
+  C.addCommand(std::make_unique<Command>(
+      JA, *this, ResponseFileSupport::AtFileCurCP(), Args.MakeArgString(Linker),
+      CmdArgs, Inputs, Output));
+}
+// CSKY tools end.

diff  --git a/clang/lib/Driver/ToolChains/CSKYToolChain.h b/clang/lib/Driver/ToolChains/CSKYToolChain.h
new file mode 100644
index 0000000000000..7f6b134c49a5d
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/CSKYToolChain.h
@@ -0,0 +1,64 @@
+//===--- CSKYToolchain.h - CSKY ToolChain Implementations -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CSKYTOOLCHAIN_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CSKYTOOLCHAIN_H
+
+#include "Gnu.h"
+#include "clang/Driver/ToolChain.h"
+
+namespace clang {
+namespace driver {
+namespace toolchains {
+
+class LLVM_LIBRARY_VISIBILITY CSKYToolChain : public Generic_ELF {
+public:
+  CSKYToolChain(const Driver &D, const llvm::Triple &Triple,
+                const llvm::opt::ArgList &Args);
+
+  bool IsIntegratedAssemblerDefault() const override { return true; }
+  void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+                             llvm::opt::ArgStringList &CC1Args,
+                             Action::OffloadKind) const override;
+  RuntimeLibType GetDefaultRuntimeLibType() const override;
+  UnwindLibType GetUnwindLibType(const llvm::opt::ArgList &Args) const override;
+  void
+  AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+                            llvm::opt::ArgStringList &CC1Args) const override;
+  void
+  addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+                           llvm::opt::ArgStringList &CC1Args) const override;
+
+protected:
+  Tool *buildLinker() const override;
+
+private:
+  std::string computeSysRoot() const override;
+};
+
+} // end namespace toolchains
+
+namespace tools {
+namespace CSKY {
+class LLVM_LIBRARY_VISIBILITY Linker : public Tool {
+public:
+  Linker(const ToolChain &TC) : Tool("CSKY::Linker", "ld", TC) {}
+  bool hasIntegratedCPP() const override { return false; }
+  bool isLinkJob() const override { return true; }
+  void ConstructJob(Compilation &C, const JobAction &JA,
+                    const InputInfo &Output, const InputInfoList &Inputs,
+                    const llvm::opt::ArgList &TCArgs,
+                    const char *LinkingOutput) const override;
+};
+} // end namespace CSKY
+} // end namespace tools
+
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CSKYTOOLCHAIN_H

diff  --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index cbdb463d09682..baac938412ec8 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -10,6 +10,7 @@
 #include "AMDGPU.h"
 #include "Arch/AArch64.h"
 #include "Arch/ARM.h"
+#include "Arch/CSKY.h"
 #include "Arch/M68k.h"
 #include "Arch/Mips.h"
 #include "Arch/PPC.h"
@@ -383,6 +384,9 @@ static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
   case llvm::Triple::ve:
     ve::getVETargetFeatures(D, Args, Features);
     break;
+  case llvm::Triple::csky:
+    csky::getCSKYTargetFeatures(D, Triple, Args, CmdArgs, Features);
+    break;
   }
 
   for (auto Feature : unifyTargetFeatures(Features)) {
@@ -547,6 +551,7 @@ static bool useFramePointerForTargetByDefault(const ArgList &Args,
   case llvm::Triple::riscv64:
   case llvm::Triple::amdgcn:
   case llvm::Triple::r600:
+  case llvm::Triple::csky:
     return !areOptimizationsEnabled(Args);
   default:
     break;

diff  --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 967e503810aa7..3d12f6fb8d3b7 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -424,6 +424,13 @@ std::string tools::getCPUName(const Driver &D, const ArgList &Args,
 
     return TargetCPUName;
   }
+  case llvm::Triple::csky:
+    if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
+      return A->getValue();
+    else if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
+      return A->getValue();
+    else
+      return "ck810";
   case llvm::Triple::riscv32:
   case llvm::Triple::riscv64:
     if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))

diff  --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index fe4d997e1de24..a10edc3db409f 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -8,6 +8,7 @@
 
 #include "Gnu.h"
 #include "Arch/ARM.h"
+#include "Arch/CSKY.h"
 #include "Arch/Mips.h"
 #include "Arch/PPC.h"
 #include "Arch/RISCV.h"
@@ -299,6 +300,8 @@ static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
     return "elf_x86_64";
   case llvm::Triple::ve:
     return "elf64ve";
+  case llvm::Triple::csky:
+    return "cskyelf_linux";
   default:
     return nullptr;
   }
@@ -1577,6 +1580,68 @@ static bool findMSP430Multilibs(const Driver &D,
   return false;
 }
 
+static void findCSKYMultilibs(const Driver &D, const llvm::Triple &TargetTriple,
+                              StringRef Path, const ArgList &Args,
+                              DetectedMultilibs &Result) {
+  FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
+
+  tools::csky::FloatABI TheFloatABI = tools::csky::getCSKYFloatABI(D, Args);
+  llvm::Optional<llvm::StringRef> Res = tools::csky::getCSKYArchName(D, Args, TargetTriple);
+
+  if (!Res)
+    return;
+  auto ARCHName = *Res;
+
+  Multilib::flags_list Flags;
+  addMultilibFlag(TheFloatABI == tools::csky::FloatABI::Hard, "hard-fp", Flags);
+  addMultilibFlag(TheFloatABI == tools::csky::FloatABI::SoftFP, "soft-fp",
+                  Flags);
+  addMultilibFlag(TheFloatABI == tools::csky::FloatABI::Soft, "soft", Flags);
+  addMultilibFlag(ARCHName == "ck801", "march=ck801", Flags);
+  addMultilibFlag(ARCHName == "ck802", "march=ck802", Flags);
+  addMultilibFlag(ARCHName == "ck803", "march=ck803", Flags);
+  addMultilibFlag(ARCHName == "ck804", "march=ck804", Flags);
+  addMultilibFlag(ARCHName == "ck805", "march=ck805", Flags);
+  addMultilibFlag(ARCHName == "ck807", "march=ck807", Flags);
+  addMultilibFlag(ARCHName == "ck810", "march=ck810", Flags);
+  addMultilibFlag(ARCHName == "ck810v", "march=ck810v", Flags);
+  addMultilibFlag(ARCHName == "ck860", "march=ck860", Flags);
+  addMultilibFlag(ARCHName == "ck860v", "march=ck860v", Flags);
+
+  bool isBigEndian = false;
+  if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
+                               options::OPT_mbig_endian))
+    isBigEndian = !A->getOption().matches(options::OPT_mlittle_endian);
+  addMultilibFlag(isBigEndian, "EB", Flags);
+
+  auto HardFloat = makeMultilib("/hard-fp").flag("+hard-fp");
+  auto SoftFpFloat = makeMultilib("/soft-fp").flag("+soft-fp");
+  auto SoftFloat = makeMultilib("").flag("+soft");
+  auto Arch801 = makeMultilib("/ck801").flag("+march=ck801");
+  auto Arch802 = makeMultilib("/ck802").flag("+march=ck802");
+  auto Arch803 = makeMultilib("/ck803").flag("+march=ck803");
+  // CK804 use the same library as CK803
+  auto Arch804 = makeMultilib("/ck803").flag("+march=ck804");
+  auto Arch805 = makeMultilib("/ck805").flag("+march=ck805");
+  auto Arch807 = makeMultilib("/ck807").flag("+march=ck807");
+  auto Arch810 = makeMultilib("").flag("+march=ck810");
+  auto Arch810v = makeMultilib("/ck810v").flag("+march=ck810v");
+  auto Arch860 = makeMultilib("/ck860").flag("+march=ck860");
+  auto Arch860v = makeMultilib("/ck860v").flag("+march=ck860v");
+  auto BigEndian = makeMultilib("/big").flag("+EB");
+
+  MultilibSet CSKYMultilibs =
+      MultilibSet()
+          .Maybe(BigEndian)
+          .Either({Arch801, Arch802, Arch803, Arch804, Arch805, Arch807,
+                   Arch810, Arch810v, Arch860, Arch860v})
+          .Either(HardFloat, SoftFpFloat, SoftFloat)
+          .FilterOut(NonExistent);
+
+  if (CSKYMultilibs.select(Flags, Result.SelectedMultilib))
+    Result.Multilibs = CSKYMultilibs;
+}
+
 static void findRISCVBareMetalMultilibs(const Driver &D,
                                         const llvm::Triple &TargetTriple,
                                         StringRef Path, const ArgList &Args,
@@ -2095,6 +2160,10 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
   static const char *const AVRLibDirs[] = {"/lib"};
   static const char *const AVRTriples[] = {"avr"};
 
+  static const char *const CSKYLibDirs[] = {"/lib"};
+  static const char *const CSKYTriples[] = {
+      "csky-linux-gnuabiv2", "csky-linux-uclibcabiv2", "csky-elf-noneabiv2"};
+
   static const char *const X86_64LibDirs[] = {"/lib64", "/lib"};
   static const char *const X86_64Triples[] = {
       "x86_64-linux-gnu",       "x86_64-unknown-linux-gnu",
@@ -2329,6 +2398,10 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
     LibDirs.append(begin(AVRLibDirs), end(AVRLibDirs));
     TripleAliases.append(begin(AVRTriples), end(AVRTriples));
     break;
+  case llvm::Triple::csky:
+    LibDirs.append(begin(CSKYLibDirs), end(CSKYLibDirs));
+    TripleAliases.append(begin(CSKYTriples), end(CSKYTriples));
+    break;
   case llvm::Triple::x86_64:
     if (TargetTriple.isX32()) {
       LibDirs.append(begin(X32LibDirs), end(X32LibDirs));
@@ -2478,6 +2551,8 @@ bool Generic_GCC::GCCInstallationDetector::ScanGCCForMultilibs(
   if (isArmOrThumbArch(TargetArch) && TargetTriple.isAndroid()) {
     // It should also work without multilibs in a simplified toolchain.
     findAndroidArmMultilibs(D, TargetTriple, Path, Args, Detected);
+  } else if (TargetTriple.isCSKY()) {
+    findCSKYMultilibs(D, TargetTriple, Path, Args, Detected);
   } else if (TargetTriple.isMIPS()) {
     if (!findMIPSMultilibs(D, TargetTriple, Path, Args, Detected))
       return false;
@@ -2738,6 +2813,7 @@ bool Generic_GCC::IsIntegratedAssemblerDefault() const {
   case llvm::Triple::avr:
   case llvm::Triple::bpfel:
   case llvm::Triple::bpfeb:
+  case llvm::Triple::csky:
   case llvm::Triple::thumb:
   case llvm::Triple::thumbeb:
   case llvm::Triple::ppc:

diff  --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
index 83cb41159de7e..6be2e801d8361 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -221,8 +221,12 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
   const bool IsMips = Triple.isMIPS();
   const bool IsHexagon = Arch == llvm::Triple::hexagon;
   const bool IsRISCV = Triple.isRISCV();
+  const bool IsCSKY = Triple.isCSKY();
 
-  if (IsMips && !SysRoot.empty())
+  if (IsCSKY)
+    SysRoot = SysRoot + SelectedMultilib.osSuffix();
+
+  if ((IsMips || IsCSKY) && !SysRoot.empty())
     ExtraOpts.push_back("--sysroot=" + SysRoot);
 
   // Do not use 'gnu' hash style for Mips targets because .gnu.hash
@@ -355,6 +359,21 @@ std::string Linux::computeSysRoot() const {
       return AndroidSysRootPath;
   }
 
+  if (getTriple().isCSKY()) {
+    // CSKY toolchains use 
diff erent names for sysroot folder.
+    if (!GCCInstallation.isValid())
+      return std::string();
+    // GCCInstallation.getInstallPath() =
+    //   $GCCToolchainPath/lib/gcc/csky-linux-gnuabiv2/6.3.0
+    // Path = $GCCToolchainPath/csky-linux-gnuabiv2/libc
+    std::string Path = (GCCInstallation.getInstallPath() + "/../../../../" +
+                        GCCInstallation.getTriple().str() + "/libc")
+                           .str();
+    if (getVFS().exists(Path))
+      return Path;
+    return std::string();
+  }
+
   if (!GCCInstallation.isValid() || !getTriple().isMIPS())
     return std::string();
 
@@ -531,6 +550,11 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
   }
   case llvm::Triple::ve:
     return "/opt/nec/ve/lib/ld-linux-ve.so.1";
+  case llvm::Triple::csky: {
+    LibDir = "lib";
+    Loader = "ld.so.1";
+    break;
+  }
   }
 
   if (Distro == Distro::Exherbo &&

diff  --git a/clang/test/Driver/Inputs/multilib_csky_linux_sdk/csky-linux-gnuabiv2/bin/ld b/clang/test/Driver/Inputs/multilib_csky_linux_sdk/csky-linux-gnuabiv2/bin/ld
new file mode 100755
index 0000000000000..e69de29bb2d1d

diff  --git a/clang/test/Driver/Inputs/multilib_csky_linux_sdk/csky-linux-gnuabiv2/libc/ck860v/lib/.keep b/clang/test/Driver/Inputs/multilib_csky_linux_sdk/csky-linux-gnuabiv2/libc/ck860v/lib/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d

diff  --git a/clang/test/Driver/Inputs/multilib_csky_linux_sdk/csky-linux-gnuabiv2/libc/ck860v/usr/lib/crt1.o b/clang/test/Driver/Inputs/multilib_csky_linux_sdk/csky-linux-gnuabiv2/libc/ck860v/usr/lib/crt1.o
new file mode 100644
index 0000000000000..e69de29bb2d1d

diff  --git a/clang/test/Driver/Inputs/multilib_csky_linux_sdk/csky-linux-gnuabiv2/libc/lib/.keep b/clang/test/Driver/Inputs/multilib_csky_linux_sdk/csky-linux-gnuabiv2/libc/lib/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d

diff  --git a/clang/test/Driver/Inputs/multilib_csky_linux_sdk/csky-linux-gnuabiv2/libc/usr/lib/crt1.o b/clang/test/Driver/Inputs/multilib_csky_linux_sdk/csky-linux-gnuabiv2/libc/usr/lib/crt1.o
new file mode 100644
index 0000000000000..e69de29bb2d1d

diff  --git a/clang/test/Driver/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/ck860v/crtbegin.o b/clang/test/Driver/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/ck860v/crtbegin.o
new file mode 100644
index 0000000000000..e69de29bb2d1d

diff  --git a/clang/test/Driver/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/ck860v/crtend.o b/clang/test/Driver/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/ck860v/crtend.o
new file mode 100644
index 0000000000000..e69de29bb2d1d

diff  --git a/clang/test/Driver/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/ck860v/crti.o b/clang/test/Driver/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/ck860v/crti.o
new file mode 100644
index 0000000000000..e69de29bb2d1d

diff  --git a/clang/test/Driver/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/ck860v/crtn.o b/clang/test/Driver/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/ck860v/crtn.o
new file mode 100644
index 0000000000000..e69de29bb2d1d

diff  --git a/clang/test/Driver/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/crtbegin.o b/clang/test/Driver/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/crtbegin.o
new file mode 100644
index 0000000000000..e69de29bb2d1d

diff  --git a/clang/test/Driver/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/crtend.o b/clang/test/Driver/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/crtend.o
new file mode 100644
index 0000000000000..e69de29bb2d1d

diff  --git a/clang/test/Driver/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/crti.o b/clang/test/Driver/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/crti.o
new file mode 100644
index 0000000000000..e69de29bb2d1d

diff  --git a/clang/test/Driver/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/crtn.o b/clang/test/Driver/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/crtn.o
new file mode 100644
index 0000000000000..e69de29bb2d1d

diff  --git a/clang/test/Driver/csky-arch-error.c b/clang/test/Driver/csky-arch-error.c
new file mode 100644
index 0000000000000..22d3640cdd964
--- /dev/null
+++ b/clang/test/Driver/csky-arch-error.c
@@ -0,0 +1,7 @@
+// RUN: not %clang -target csky-unknown-elf -march=csky %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=CSKY %s
+// CSKY: error: invalid arch name '-march=csky'
+
+// RUN: not %clang -target csky-unknown-elf -march=CK810 %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=CSKY-UPPER %s
+// CSKY-UPPER: error: invalid arch name '-march=CK810'

diff  --git a/clang/test/Driver/csky-arch.c b/clang/test/Driver/csky-arch.c
new file mode 100644
index 0000000000000..4c1a349660b67
--- /dev/null
+++ b/clang/test/Driver/csky-arch.c
@@ -0,0 +1,108 @@
+// RUN: %clang -target csky-unknown-elf -march=ck801 -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=CHECK-CK801
+
+// CHECK-CK801: "-target-cpu" "ck801"
+// CHECK-CK801: "-target-feature" "+elrw" "-target-feature" "+trust"
+// CHECK-CK801: "-target-feature" "+e1"
+
+// RUN: %clang -target csky-unknown-elf -march=ck802 -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=CHECK-CK802
+
+// CHECK-CK802: "-target-cpu" "ck802"
+// CHECK-CK802: "-target-feature" "+elrw" "-target-feature" "+trust"
+// CHECK-CK802: "-target-feature" "+nvic" "-target-feature" "+e1"
+// CHECK-CK802: "-target-feature" "+e2"
+
+// RUN: %clang -target csky-unknown-elf -march=ck803 -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=CHECK-CK803
+
+// CHECK-CK803: "-target-cpu" "ck803"
+// CHECK-CK803: "-target-feature" "+hwdiv" "-target-feature" "+elrw"
+// CHECK-CK803: "-target-feature" "+trust" "-target-feature" "+nvic"
+// CHECK-CK803: "-target-feature" "+e1" "-target-feature" "+e2" "-target-feature" "+2e3"
+// CHECK-CK803: "-target-feature" "+mp"
+
+// RUN: %clang -target csky-unknown-elf -march=ck803s -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=CHECK-CK803S
+
+// CHECK-CK803S: "-target-cpu" "ck803s"
+// CHECK-CK803S: "-target-feature" "+hwdiv" "-target-feature" "+elrw"
+// CHECK-CK803S: "-target-feature" "+trust" "-target-feature" "+nvic"
+// CHECK-CK803S: "-target-feature" "+e1" "-target-feature" "+e2"
+// CHECK-CK803S: "-target-feature" "+2e3" "-target-feature" "+mp"
+
+// RUN: %clang -target csky-unknown-elf -march=ck804 -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=CHECK-CK804
+
+// CHECK-CK804: "-target-cpu" "ck804"
+// CHECK-CK804: "-target-feature" "+hwdiv" "-target-feature" "+elrw"
+// CHECK-CK804: "-target-feature" "+trust" "-target-feature" "+nvic"
+// CHECK-CK804: "-target-feature" "+doloop" "-target-feature" "+e1"
+// CHECK-CK804: "-target-feature" "+e2" "-target-feature" "+2e3"
+// CHECK-CK804: "-target-feature" "+mp" "-target-feature" "+3e3r1"
+// CHECK-CK804: "-target-feature" "+3e3r2" "-target-feature" "+3e3r3"
+
+// RUN: %clang -target csky-unknown-elf -march=ck805 -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=CHECK-CK805
+
+// CHECK-CK805: "-target-cpu" "ck805"
+// CHECK-CK805: "-target-feature" "+hwdiv" "-target-feature" "+elrw"
+// CHECK-CK805: "-target-feature" "+trust" "-target-feature" "+nvic"
+// CHECK-CK805: "-target-feature" "+doloop" "-target-feature" "+high-registers"
+// CHECK-CK805: "-target-feature" "+vdsp2e3" "-target-feature" "+vdspv2" "-target-feature" "+e1"
+// CHECK-CK805: "-target-feature" "+e2" "-target-feature" "+2e3" "-target-feature" "+mp"
+// CHECK-CK805: "-target-feature" "+3e3r1" "-target-feature" "+3e3r2" "-target-feature" "+3e3r3"
+
+// RUN: %clang -target csky-unknown-elf -march=ck807 -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=CHECK-CK807
+
+// CHECK-CK807: "-target-cpu" "ck807"
+// CHECK-CK807: "-target-feature" "+hwdiv" "-target-feature" "+edsp"
+// CHECK-CK807: "-target-feature" "+dsp1e2" "-target-feature" "+dspe60" "-target-feature" "+elrw"
+// CHECK-CK807: "-target-feature" "+trust" "-target-feature" "+cache" "-target-feature" "+nvic"
+// CHECK-CK807: "-target-feature" "+high-registers" "-target-feature" "+hard-tp" "-target-feature" "+e1"
+// CHECK-CK807: "-target-feature" "+e2" "-target-feature" "+2e3" "-target-feature" "+mp"
+// CHECK-CK807: "-target-feature" "+3e7" "-target-feature" "+mp1e2"
+
+// RUN: %clang -target csky-unknown-elf -march=ck810 -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=CHECK-CK810
+
+// CHECK-CK810: "-target-cpu" "ck810"
+// CHECK-CK810: "-target-feature" "+hwdiv" "-target-feature" "+edsp" "-target-feature" "+dsp1e2"
+// CHECK-CK810: "-target-feature" "+dspe60" "-target-feature" "+elrw" "-target-feature" "+trust"
+// CHECK-CK810: "-target-feature" "+cache" "-target-feature" "+nvic" "-target-feature" "+high-registers"
+// CHECK-CK810: "-target-feature" "+hard-tp" "-target-feature" "+e1" "-target-feature" "+e2" "-target-feature" "+2e3"
+// CHECK-CK810: "-target-feature" "+mp" "-target-feature" "+3e7" "-target-feature" "+mp1e2" "-target-feature" "+7e10"
+
+// RUN: %clang -target csky-unknown-elf -march=ck810v -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=CHECK-CK810V
+
+// CHECK-CK810V: "-target-cpu" "ck810v"
+// CHECK-CK810V: "-target-feature" "+hwdiv" "-target-feature" "+edsp" "-target-feature" "+dsp1e2"
+// CHECK-CK810V: "-target-feature" "+dspe60" "-target-feature" "+elrw" "-target-feature" "+trust"
+// CHECK-CK810V: "-target-feature" "+cache" "-target-feature" "+nvic" "-target-feature" "+high-registers"
+// CHECK-CK810V: "-target-feature" "+hard-tp" "-target-feature" "+vdspv1" "-target-feature" "+e1"
+// CHECK-CK810V: "-target-feature" "+e2" "-target-feature" "+2e3" "-target-feature" "+mp"
+// CHECK-CK810V: "-target-feature" "+3e7" "-target-feature" "+mp1e2" "-target-feature" "+7e10"
+
+// RUN: %clang -target csky-unknown-elf -march=ck860 -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=CHECK-CK860
+
+// CHECK-CK860: "-target-cpu" "ck860"
+// CHECK-CK860: "-target-feature" "+hwdiv" "-target-feature" "+dspe60" "-target-feature" "+elrw"
+// CHECK-CK860: "-target-feature" "+trust" "-target-feature" "+cache" "-target-feature" "+nvic"
+// CHECK-CK860: "-target-feature" "+doloop" "-target-feature" "+high-registers" "-target-feature" "+hard-tp"
+// CHECK-CK860: "-target-feature" "+e1" "-target-feature" "+e2" "-target-feature" "+2e3" "-target-feature" "+mp"
+// CHECK-CK860: "-target-feature" "+3e3r1" "-target-feature" "+3e3r2" "-target-feature" "+3e3r3"
+// CHECK-CK860: "-target-feature" "+3e7" "-target-feature" "+mp1e2" "-target-feature" "+7e10" "-target-feature" "+10e60"
+
+// RUN: %clang -target csky-unknown-elf -march=ck860v -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s -check-prefixes=CHECK-CK860V
+
+// CHECK-CK860V: "-target-cpu" "ck860v"
+// CHECK-CK860V: "-target-feature" "+hwdiv" "-target-feature" "+dspe60" "-target-feature" "+elrw" "-target-feature" "+trust"
+// CHECK-CK860V: "-target-feature" "+cache" "-target-feature" "+nvic" "-target-feature" "+doloop"
+// CHECK-CK860V: "-target-feature" "+high-registers" "-target-feature" "+vdsp2e60f" "-target-feature" "+vdspv2"
+// CHECK-CK860V: "-target-feature" "+hard-tp" "-target-feature" "+e1" "-target-feature" "+e2" "-target-feature" "+2e3"
+// CHECK-CK860V: "-target-feature" "+mp" "-target-feature" "+3e3r1" "-target-feature" "+3e3r2" "-target-feature" "+3e3r3"
+// CHECK-CK860V: "-target-feature" "+3e7" "-target-feature" "+mp1e2" "-target-feature" "+7e10" "-target-feature" "+10e60"
\ No newline at end of file

diff  --git a/clang/test/Driver/csky-cpus-error.c b/clang/test/Driver/csky-cpus-error.c
new file mode 100644
index 0000000000000..e1238fdd4fac5
--- /dev/null
+++ b/clang/test/Driver/csky-cpus-error.c
@@ -0,0 +1,7 @@
+// Check failed cases
+
+// RUN: not %clang -target csky -c %s 2>&1 -mcpu=generic1 | FileCheck -check-prefix=FAIL-MCPU-NAME %s
+// FAIL-MCPU-NAME: error: the clang compiler does not support '-mcpu=generic1'
+
+// RUN: not %clang -target csky -c %s 2>&1 -mcpu=generic -march=ck860 | FileCheck -check-prefix=MISMATCH-ARCH %s
+// MISMATCH-ARCH: error: the clang compiler does not support '-mcpu=generic'

diff  --git a/clang/test/Driver/csky-cpus.c b/clang/test/Driver/csky-cpus.c
new file mode 100644
index 0000000000000..a0f350e1712b0
--- /dev/null
+++ b/clang/test/Driver/csky-cpus.c
@@ -0,0 +1,25 @@
+// Check target CPUs are correctly passed.
+
+// RUN: %clang -target csky -### -c %s -fsyntax-only 2>&1 -mcpu=ck801 | FileCheck -check-prefix=MCPU-CK801 %s
+// MCPU-CK801: "-target-cpu" "ck801"
+// MCPU-CK801: "-target-feature" "+elrw" "-target-feature" "+trust" "-target-feature" "+e1"
+
+// RUN: %clang -target csky -### -c %s -fsyntax-only 2>&1 -mcpu=ck801t | FileCheck -check-prefix=MCPU-CK801T %s
+// MCPU-CK801T: "-target-cpu" "ck801t"
+// MCPU-CK801T: "-target-feature" "+elrw" "-target-feature" "+trust" "-target-feature" "+e1"
+
+// RUN: %clang -target csky -### -c %s -fsyntax-only 2>&1 -mcpu=e801 | FileCheck -check-prefix=MCPU-E801 %s
+// MCPU-E801: "-target-cpu" "e801"
+// MCPU-E801: "-target-feature" "+elrw" "-target-feature" "+trust" "-target-feature" "+e1"
+
+// RUN: %clang -target csky -### -c %s -fsyntax-only 2>&1 -mcpu=ck802 | FileCheck -check-prefix=MCPU-CK802 %s
+// MCPU-CK802: "-target-cpu" "ck802"
+// MCPU-CK802: "-target-feature" "+elrw" "-target-feature" "+trust" "-target-feature" "+nvic"
+// MCPU-CK802: "-target-feature" "+e1" "-target-feature" "+e2"
+
+// RUN: %clang -target csky -### -c %s -fsyntax-only 2>&1 -mcpu=ck802t | FileCheck -check-prefix=MCPU-CK802T %s
+// MCPU-CK802T: "-target-cpu" "ck802t"
+// MCPU-CK802T: "-target-feature" "+elrw" "-target-feature" "+trust" "-target-feature" "+nvic"
+// MCPU-CK802T: "-target-feature" "+e1" "-target-feature" "+e2"
+
+// TODO: Add more cpu test.

diff  --git a/clang/test/Driver/csky-toolchain.c b/clang/test/Driver/csky-toolchain.c
new file mode 100644
index 0000000000000..3f8069da4735d
--- /dev/null
+++ b/clang/test/Driver/csky-toolchain.c
@@ -0,0 +1,43 @@
+// A basic clang -cc1 command-line, and simple environment check.
+
+// RUN: %clang %s -### -no-canonical-prefixes -target csky 2>&1 | FileCheck -check-prefix=CC1 %s
+// CC1: clang{{.*}} "-cc1" "-triple" "csky"
+
+// Test interaction with -fuse-ld=lld, if lld is available.
+// RUN: %clang %s -### -no-canonical-prefixes -target csky -fuse-ld=lld 2>&1 | FileCheck -check-prefix=LLD %s
+// LLD: {{(error: invalid linker name in argument '-fuse-ld=lld')|(ld.lld)}}
+
+// In the below tests, --rtlib=platform is used so that the driver ignores
+// the configure-time CLANG_DEFAULT_RTLIB option when choosing the runtime lib
+
+// RUN: %clang %s -### -no-canonical-prefixes -fuse-ld=ld -target csky-unknown-linux-gnu --rtlib=platform  \
+// RUN:   --gcc-toolchain=%S/Inputs/multilib_csky_linux_sdk  2>&1 | FileCheck -check-prefix=C-CSKY-LINUX-MULTI %s
+
+// C-CSKY-LINUX-MULTI: "{{.*}}/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/../../..{{/|\\\\}}..{{/|\\\\}}csky-linux-gnuabiv2/bin{{/|\\\\}}ld"
+// C-CSKY-LINUX-MULTI: "--sysroot={{.*}}/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/../../..{{/|\\\\}}..{{/|\\\\}}csky-linux-gnuabiv2/libc"
+// C-CSKY-LINUX-MULTI: "-m" "cskyelf_linux"
+// C-CSKY-LINUX-MULTI: "-dynamic-linker" "/lib/ld.so.1"
+// C-CSKY-LINUX-MULTI: "{{.*}}/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/../../..{{/|\\\\}}..{{/|\\\\}}csky-linux-gnuabiv2/libc/usr/lib/../lib/crt1.o"
+// C-CSKY-LINUX-MULTI: "{{.*}}/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/crti.o"
+// C-CSKY-LINUX-MULTI: "{{.*}}/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/crtbegin.o"
+// C-CSKY-LINUX-MULTI: "-L{{.*}}/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0"
+// C-CSKY-LINUX-MULTI: "-L{{.*}}/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/../../..{{/|\\\\}}..{{/|\\\\}}csky-linux-gnuabiv2/libc/lib/../lib"
+// C-CSKY-LINUX-MULTI: "-L{{.*}}/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/../../..{{/|\\\\}}..{{/|\\\\}}csky-linux-gnuabiv2/libc/usr/lib/../lib"
+// C-CSKY-LINUX-MULTI: "-L{{.*}}/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/../../..{{/|\\\\}}..{{/|\\\\}}csky-linux-gnuabiv2/libc/lib"
+// C-CSKY-LINUX-MULTI: "-L{{.*}}/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/../../..{{/|\\\\}}..{{/|\\\\}}csky-linux-gnuabiv2/libc/usr/lib"
+
+// RUN: %clang %s -### -no-canonical-prefixes -fuse-ld=ld -target csky-unknown-linux-gnu --rtlib=platform -march=ck860v \
+// RUN:   --gcc-toolchain=%S/Inputs/multilib_csky_linux_sdk 2>&1 | FileCheck -check-prefix=C-CSKY-LINUX-CK860V %s
+
+// C-CSKY-LINUX-CK860V: "{{.*}}/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/../../..{{/|\\\\}}..{{/|\\\\}}csky-linux-gnuabiv2/bin{{/|\\\\}}ld"
+// C-CSKY-LINUX-CK860V: "--sysroot={{.*}}/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/../../..{{/|\\\\}}..{{/|\\\\}}csky-linux-gnuabiv2/libc/ck860v"
+// C-CSKY-LINUX-CK860V: "-m" "cskyelf_linux"
+// C-CSKY-LINUX-CK860V: "-dynamic-linker" "/lib/ld.so.1"
+// C-CSKY-LINUX-CK860V: "{{.*}}/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/../../..{{/|\\\\}}..{{/|\\\\}}csky-linux-gnuabiv2/libc/ck860v/usr/lib/../lib/crt1.o"
+// C-CSKY-LINUX-CK860V: "{{.*}}/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/ck860v/crti.o"
+// C-CSKY-LINUX-CK860V: "{{.*}}/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/ck860v/crtbegin.o"
+// C-CSKY-LINUX-CK860V: "-L{{.*}}/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/ck860v"
+// C-CSKY-LINUX-CK860V: "-L{{.*}}/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/../../..{{/|\\\\}}..{{/|\\\\}}csky-linux-gnuabiv2/libc/ck860v/lib/../lib"
+// C-CSKY-LINUX-CK860V: "-L{{.*}}/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/../../..{{/|\\\\}}..{{/|\\\\}}csky-linux-gnuabiv2/libc/ck860v/usr/lib/../lib"
+// C-CSKY-LINUX-CK860V: "-L{{.*}}/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/../../..{{/|\\\\}}..{{/|\\\\}}csky-linux-gnuabiv2/libc/ck860v/lib"
+// C-CSKY-LINUX-CK860V: "-L{{.*}}/Inputs/multilib_csky_linux_sdk/lib/gcc/csky-linux-gnuabiv2/6.3.0/../../..{{/|\\\\}}..{{/|\\\\}}csky-linux-gnuabiv2/libc/ck860v/usr/lib"

diff  --git a/clang/test/Preprocessor/csky-target-features.c b/clang/test/Preprocessor/csky-target-features.c
new file mode 100644
index 0000000000000..36301c0b4448f
--- /dev/null
+++ b/clang/test/Preprocessor/csky-target-features.c
@@ -0,0 +1,15 @@
+// RUN: %clang -target csky-unknown-linux-gnu  -x c -E -dM %s \
+// RUN: -o - | FileCheck %s
+
+// CHECK: __CK810__ 1
+// CHECK: __CKCORE__ 2
+// CHECK: __CSKYABI__ 2
+// CHECK: __CSKYLE__ 1
+// CHECK: __CSKY__ 2
+
+// CHECK: __ck810__ 1
+// CHECK: __ckcore__ 2
+// CHECK: __cskyLE__ 1
+// CHECK: __csky__ 2
+// CHECK: __cskyabi__ 2
+// CHECK: __cskyle__ 1

diff  --git a/clang/test/Preprocessor/init-csky.c b/clang/test/Preprocessor/init-csky.c
new file mode 100644
index 0000000000000..f7868e02644aa
--- /dev/null
+++ b/clang/test/Preprocessor/init-csky.c
@@ -0,0 +1,211 @@
+// RUN: %clang_cc1 -E -dM -ffreestanding -fgnuc-version=4.2.1 -triple=csky < /dev/null \
+// RUN:   | FileCheck -match-full-lines -check-prefix=CSKY %s
+// RUN: %clang_cc1 -E -dM -ffreestanding -fgnuc-version=4.2.1 -triple=csky-unknown-linux < /dev/null \
+// RUN:   | FileCheck -match-full-lines -check-prefixes=CSKY,CSKY-LINUX %s
+// RUN: %clang_cc1 -E -dM -ffreestanding -fgnuc-version=4.2.1 -triple=csky \
+// RUN: -fforce-enable-int128 < /dev/null | FileCheck -match-full-lines \
+// RUN: -check-prefixes=CSKY,CSKY-INT128 %s
+// CSKY: #define _ILP32 1
+// CSKY: #define __ATOMIC_ACQUIRE 2
+// CSKY: #define __ATOMIC_ACQ_REL 4
+// CSKY: #define __ATOMIC_CONSUME 1
+// CSKY: #define __ATOMIC_RELAXED 0
+// CSKY: #define __ATOMIC_RELEASE 3
+// CSKY: #define __ATOMIC_SEQ_CST 5
+// CSKY: #define __BIGGEST_ALIGNMENT__ 4
+// CSKY: #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
+// CSKY: #define __CHAR16_TYPE__ unsigned short
+// CSKY: #define __CHAR32_TYPE__ unsigned int
+// CSKY: #define __CHAR_BIT__ 8
+// CSKY: #define __DBL_DECIMAL_DIG__ 17
+// CSKY: #define __DBL_DENORM_MIN__ 4.9406564584124654e-324
+// CSKY: #define __DBL_DIG__ 15
+// CSKY: #define __DBL_EPSILON__ 2.2204460492503131e-16
+// CSKY: #define __DBL_HAS_DENORM__ 1
+// CSKY: #define __DBL_HAS_INFINITY__ 1
+// CSKY: #define __DBL_HAS_QUIET_NAN__ 1
+// CSKY: #define __DBL_MANT_DIG__ 53
+// CSKY: #define __DBL_MAX_10_EXP__ 308
+// CSKY: #define __DBL_MAX_EXP__ 1024
+// CSKY: #define __DBL_MAX__ 1.7976931348623157e+308
+// CSKY: #define __DBL_MIN_10_EXP__ (-307)
+// CSKY: #define __DBL_MIN_EXP__ (-1021)
+// CSKY: #define __DBL_MIN__ 2.2250738585072014e-308
+// CSKY: #define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
+// CSKY: #define __ELF__ 1
+// CSKY: #define __FINITE_MATH_ONLY__ 0
+// CSKY: #define __FLT_DECIMAL_DIG__ 9
+// CSKY: #define __FLT_DENORM_MIN__ 1.40129846e-45F
+// CSKY: #define __FLT_DIG__ 6
+// CSKY: #define __FLT_EPSILON__ 1.19209290e-7F
+// CSKY: #define __FLT_HAS_DENORM__ 1
+// CSKY: #define __FLT_HAS_INFINITY__ 1
+// CSKY: #define __FLT_HAS_QUIET_NAN__ 1
+// CSKY: #define __FLT_MANT_DIG__ 24
+// CSKY: #define __FLT_MAX_10_EXP__ 38
+// CSKY: #define __FLT_MAX_EXP__ 128
+// CSKY: #define __FLT_MAX__ 3.40282347e+38F
+// CSKY: #define __FLT_MIN_10_EXP__ (-37)
+// CSKY: #define __FLT_MIN_EXP__ (-125)
+// CSKY: #define __FLT_MIN__ 1.17549435e-38F
+// CSKY: #define __FLT_RADIX__ 2
+// CSKY: #define __GCC_ATOMIC_BOOL_LOCK_FREE 2
+// CSKY: #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
+// CSKY: #define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
+// CSKY: #define __GCC_ATOMIC_CHAR_LOCK_FREE 2
+// CSKY: #define __GCC_ATOMIC_INT_LOCK_FREE 2
+// CSKY: #define __GCC_ATOMIC_LLONG_LOCK_FREE 1
+// CSKY: #define __GCC_ATOMIC_LONG_LOCK_FREE 2
+// CSKY: #define __GCC_ATOMIC_POINTER_LOCK_FREE 2
+// CSKY: #define __GCC_ATOMIC_SHORT_LOCK_FREE 2
+// CSKY: #define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
+// CSKY: #define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
+// CSKY: #define __GNUC_MINOR__ {{.*}}
+// CSKY: #define __GNUC_PATCHLEVEL__ {{.*}}
+// CSKY: #define __GNUC_STDC_INLINE__ 1
+// CSKY: #define __GNUC__ {{.*}}
+// CSKY: #define __GXX_ABI_VERSION {{.*}}
+// CSKY: #define __ILP32__ 1
+// CSKY: #define __INT16_C_SUFFIX__
+// CSKY: #define __INT16_MAX__ 32767
+// CSKY: #define __INT16_TYPE__ short
+// CSKY: #define __INT32_C_SUFFIX__
+// CSKY: #define __INT32_MAX__ 2147483647
+// CSKY: #define __INT32_TYPE__ int
+// CSKY: #define __INT64_C_SUFFIX__ LL
+// CSKY: #define __INT64_MAX__ 9223372036854775807LL
+// CSKY: #define __INT64_TYPE__ long long int
+// CSKY: #define __INT8_C_SUFFIX__
+// CSKY: #define __INT8_MAX__ 127
+// CSKY: #define __INT8_TYPE__ signed char
+// CSKY: #define __INTMAX_C_SUFFIX__ LL
+// CSKY: #define __INTMAX_MAX__ 9223372036854775807LL
+// CSKY: #define __INTMAX_TYPE__ long long int
+// CSKY: #define __INTMAX_WIDTH__ 64
+// CSKY: #define __INTPTR_MAX__ 2147483647
+// CSKY: #define __INTPTR_TYPE__ int
+// CSKY: #define __INTPTR_WIDTH__ 32
+// TODO: C-SKY GCC defines INT_FAST16 as int
+// CSKY: #define __INT_FAST16_MAX__ 32767
+// CSKY: #define __INT_FAST16_TYPE__ short
+// CSKY: #define __INT_FAST32_MAX__ 2147483647
+// CSKY: #define __INT_FAST32_TYPE__ int
+// CSKY: #define __INT_FAST64_MAX__ 9223372036854775807LL
+// CSKY: #define __INT_FAST64_TYPE__ long long int
+// TODO: C-SKY GCC defines INT_FAST8 as int
+// CSKY: #define __INT_FAST8_MAX__ 127
+// CSKY: #define __INT_FAST8_TYPE__ signed char
+// CSKY: #define __INT_LEAST16_MAX__ 32767
+// CSKY: #define __INT_LEAST16_TYPE__ short
+// CSKY: #define __INT_LEAST32_MAX__ 2147483647
+// CSKY: #define __INT_LEAST32_TYPE__ int
+// CSKY: #define __INT_LEAST64_MAX__ 9223372036854775807LL
+// CSKY: #define __INT_LEAST64_TYPE__ long long int
+// CSKY: #define __INT_LEAST8_MAX__ 127
+// CSKY: #define __INT_LEAST8_TYPE__ signed char
+// CSKY: #define __INT_MAX__ 2147483647
+// CSKY: #define __LDBL_DECIMAL_DIG__ 17
+// CSKY: #define __LDBL_DENORM_MIN__ 4.9406564584124654e-324L
+// CSKY: #define __LDBL_DIG__ 15
+// CSKY: #define __LDBL_EPSILON__ 2.2204460492503131e-16L
+// CSKY: #define __LDBL_HAS_DENORM__ 1
+// CSKY: #define __LDBL_HAS_INFINITY__ 1
+// CSKY: #define __LDBL_HAS_QUIET_NAN__ 1
+// CSKY: #define __LDBL_MANT_DIG__ 53
+// CSKY: #define __LDBL_MAX_10_EXP__ 308
+// CSKY: #define __LDBL_MAX_EXP__ 1024
+// CSKY: #define __LDBL_MAX__ 1.7976931348623157e+308L
+// CSKY: #define __LDBL_MIN_10_EXP__ (-307)
+// CSKY: #define __LDBL_MIN_EXP__ (-1021)
+// CSKY: #define __LDBL_MIN__ 2.2250738585072014e-308L
+// CSKY: #define __LITTLE_ENDIAN__ 1
+// CSKY: #define __LONG_LONG_MAX__ 9223372036854775807LL
+// CSKY: #define __LONG_MAX__ 2147483647L
+// CSKY: #define __NO_INLINE__ 1
+// CSKY: #define __POINTER_WIDTH__ 32
+// CSKY: #define __PRAGMA_REDEFINE_EXTNAME 1
+// CSKY: #define __PTRDIFF_MAX__ 2147483647
+// CSKY: #define __PTRDIFF_TYPE__ int
+// CSKY: #define __PTRDIFF_WIDTH__ 32
+// CSKY: #define __SCHAR_MAX__ 127
+// CSKY: #define __SHRT_MAX__ 32767
+// CSKY: #define __SIG_ATOMIC_MAX__ 2147483647
+// CSKY: #define __SIG_ATOMIC_WIDTH__ 32
+// CSKY: #define __SIZEOF_DOUBLE__ 8
+// CSKY: #define __SIZEOF_FLOAT__ 4
+// CSKY-INT128: #define __SIZEOF_INT128__ 16
+// CSKY: #define __SIZEOF_INT__ 4
+// CSKY: #define __SIZEOF_LONG_DOUBLE__ 8
+// CSKY: #define __SIZEOF_LONG_LONG__ 8
+// CSKY: #define __SIZEOF_LONG__ 4
+// CSKY: #define __SIZEOF_POINTER__ 4
+// CSKY: #define __SIZEOF_PTRDIFF_T__ 4
+// CSKY: #define __SIZEOF_SHORT__ 2
+// CSKY: #define __SIZEOF_SIZE_T__ 4
+// CSKY: #define __SIZEOF_WCHAR_T__ 4
+// CSKY: #define __SIZEOF_WINT_T__ 4
+// CSKY: #define __SIZE_MAX__ 4294967295U
+// CSKY: #define __SIZE_TYPE__ unsigned int
+// CSKY: #define __SIZE_WIDTH__ 32
+// CSKY: #define __STDC_HOSTED__ 0
+// CSKY: #define __STDC_UTF_16__ 1
+// CSKY: #define __STDC_UTF_32__ 1
+// CSKY: #define __STDC_VERSION__ 201710L
+// CSKY: #define __STDC__ 1
+// CSKY: #define __UINT16_C_SUFFIX__
+// CSKY: #define __UINT16_MAX__ 65535
+// CSKY: #define __UINT16_TYPE__ unsigned short
+// CSKY: #define __UINT32_C_SUFFIX__ U
+// CSKY: #define __UINT32_MAX__ 4294967295U
+// CSKY: #define __UINT32_TYPE__ unsigned int
+// CSKY: #define __UINT64_C_SUFFIX__ ULL
+// CSKY: #define __UINT64_MAX__ 18446744073709551615ULL
+// CSKY: #define __UINT64_TYPE__ long long unsigned int
+// CSKY: #define __UINT8_C_SUFFIX__
+// CSKY: #define __UINT8_MAX__ 255
+// CSKY: #define __UINT8_TYPE__ unsigned char
+// CSKY: #define __UINTMAX_C_SUFFIX__ ULL
+// CSKY: #define __UINTMAX_MAX__ 18446744073709551615ULL
+// CSKY: #define __UINTMAX_TYPE__ long long unsigned int
+// CSKY: #define __UINTMAX_WIDTH__ 64
+// CSKY: #define __UINTPTR_MAX__ 4294967295U
+// CSKY: #define __UINTPTR_TYPE__ unsigned int
+// CSKY: #define __UINTPTR_WIDTH__ 32
+// TODO: C-SKY GCC defines UINT_FAST16 to be unsigned int
+// CSKY: #define __UINT_FAST16_MAX__ 65535
+// CSKY: #define __UINT_FAST16_TYPE__ unsigned short
+// CSKY: #define __UINT_FAST32_MAX__ 4294967295U
+// CSKY: #define __UINT_FAST32_TYPE__ unsigned int
+// CSKY: #define __UINT_FAST64_MAX__ 18446744073709551615ULL
+// CSKY: #define __UINT_FAST64_TYPE__ long long unsigned int
+// TODO: C-SKY GCC defines UINT_FAST8 to be unsigned int
+// CSKY: #define __UINT_FAST8_MAX__ 255
+// CSKY: #define __UINT_FAST8_TYPE__ unsigned char
+// CSKY: #define __UINT_LEAST16_MAX__ 65535
+// CSKY: #define __UINT_LEAST16_TYPE__ unsigned short
+// CSKY: #define __UINT_LEAST32_MAX__ 4294967295U
+// CSKY: #define __UINT_LEAST32_TYPE__ unsigned int
+// CSKY: #define __UINT_LEAST64_MAX__ 18446744073709551615ULL
+// CSKY: #define __UINT_LEAST64_TYPE__ long long unsigned int
+// CSKY: #define __UINT_LEAST8_MAX__ 255
+// CSKY: #define __UINT_LEAST8_TYPE__ unsigned char
+// CSKY: #define __USER_LABEL_PREFIX__
+// CSKY: #define __WCHAR_MAX__ 2147483647
+// CSKY: #define __WCHAR_TYPE__ int
+// CSKY: #define __WCHAR_WIDTH__ 32
+// CSKY: #define __WINT_TYPE__ unsigned int
+// CSKY: #define __WINT_UNSIGNED__ 1
+// CSKY: #define __WINT_WIDTH__ 32
+// CSKY: #define __ck810__ 1
+// CSKY: #define __ckcore__ 2
+// CSKY: #define __cskyLE__ 1
+// CSKY: #define __csky__ 2
+// CSKY: #define __cskyabi__ 2
+// CSKY: #define __cskyle__ 1
+// CSKY-LINUX: #define __gnu_linux__ 1
+// CSKY-LINUX: #define __linux 1
+// CSKY-LINUX: #define __linux__ 1
+// CSKY-LINUX: #define __unix 1
+// CSKY-LINUX: #define __unix__ 1
+// CSKY-LINUX: #define linux 1
+// CSKY-LINUX: #define unix 1

diff  --git a/llvm/lib/Support/CSKYTargetParser.cpp b/llvm/lib/Support/CSKYTargetParser.cpp
index c80fe315adb0e..2273b6dce0c75 100644
--- a/llvm/lib/Support/CSKYTargetParser.cpp
+++ b/llvm/lib/Support/CSKYTargetParser.cpp
@@ -172,8 +172,6 @@ bool CSKY::getExtensionFeatures(uint64_t Extensions,
   for (const auto &AE : CSKYARCHExtNames) {
     if ((Extensions & AE.ID) == AE.ID && AE.Feature)
       Features.push_back(AE.Feature);
-    else if (AE.NegFeature)
-      Features.push_back(AE.NegFeature);
   }
 
   return true;

diff  --git a/llvm/unittests/Support/CSKYTargetParserTest.cpp b/llvm/unittests/Support/CSKYTargetParserTest.cpp
index a9aa5767f9ea5..599e32661204d 100644
--- a/llvm/unittests/Support/CSKYTargetParserTest.cpp
+++ b/llvm/unittests/Support/CSKYTargetParserTest.cpp
@@ -1061,18 +1061,11 @@ TEST(TargetParserTest, CSKYExtensionFeatures) {
   EXPECT_FALSE(CSKY::getExtensionFeatures(CSKY::AEK_INVALID, Features));
 
   for (auto &E : Extensions) {
-    // test +extension
-    Features.clear();
     CSKY::getExtensionFeatures(E.first, Features);
     EXPECT_TRUE(llvm::is_contained(Features, E.second.at(0)));
-    EXPECT_EQ(Extensions.size(), Features.size());
-
-    // test -extension
-    Features.clear();
-    CSKY::getExtensionFeatures(~E.first, Features);
-    EXPECT_TRUE(llvm::is_contained(Features, E.second.at(1)));
-    EXPECT_EQ(Extensions.size(), Features.size());
   }
+
+  EXPECT_EQ(Extensions.size(), Features.size());
 }
 
 TEST(TargetParserTest, CSKYFPUFeatures) {


        


More information about the cfe-commits mailing list