r354053 - [X86] Add clang support for X86 flag output parameters.

Nirav Dave via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 14 11:27:25 PST 2019


Author: niravd
Date: Thu Feb 14 11:27:25 2019
New Revision: 354053

URL: http://llvm.org/viewvc/llvm-project?rev=354053&view=rev
Log:
[X86] Add clang support for X86 flag output parameters.

Summary:
Add frontend support and expected flags for X86 inline assembly flag
parameters.

Reviewers: craig.topper, rnk, echristo

Subscribers: eraman, nickdesaulniers, void, llvm-commits

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

Added:
    cfe/trunk/test/CodeGen/inline-asm-x86-flag-output.c
    cfe/trunk/test/Preprocessor/x86_asm_flag_output.c
Modified:
    cfe/trunk/lib/Basic/Targets/X86.cpp
    cfe/trunk/test/Preprocessor/predefined-win-macros.c

Modified: cfe/trunk/lib/Basic/Targets/X86.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets/X86.cpp?rev=354053&r1=354052&r2=354053&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Targets/X86.cpp (original)
+++ cfe/trunk/lib/Basic/Targets/X86.cpp Thu Feb 14 11:27:25 2019
@@ -864,6 +864,9 @@ bool X86TargetInfo::handleTargetFeatures
 /// definitions for this particular subtarget.
 void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
                                      MacroBuilder &Builder) const {
+  // Inline assembly supports X86 flag outputs. 
+  Builder.defineMacro("__GCC_ASM_FLAG_OUTPUTS__");
+
   std::string CodeModel = getTargetOpts().CodeModel;
   if (CodeModel == "default")
     CodeModel = "small";
@@ -1553,6 +1556,40 @@ bool X86TargetInfo::validateCpuIs(String
       .Default(false);
 }
 
+static unsigned matchAsmCCConstraint(const char *&Name) {
+  auto RV = llvm::StringSwitch<unsigned>(Name)
+                .Case("@cca", 4)
+                .Case("@ccae", 5)
+                .Case("@ccb", 4)
+                .Case("@ccbe", 5)
+                .Case("@ccc", 4)
+                .Case("@cce", 4)
+                .Case("@ccz", 4)
+                .Case("@ccg", 4)
+                .Case("@ccge", 5)
+                .Case("@ccl", 4)
+                .Case("@ccle", 5)
+                .Case("@ccna", 5)
+                .Case("@ccnae", 6)
+                .Case("@ccnb", 5)
+                .Case("@ccnbe", 6)
+                .Case("@ccnc", 5)
+                .Case("@ccne", 5)
+                .Case("@ccnz", 5)
+                .Case("@ccng", 5)
+                .Case("@ccnge", 6)
+                .Case("@ccnl", 5)
+                .Case("@ccnle", 6)
+                .Case("@ccno", 5)
+                .Case("@ccnp", 5)
+                .Case("@ccns", 5)
+                .Case("@cco", 4)
+                .Case("@ccp", 4)
+                .Case("@ccs", 4)
+                .Default(0);
+  return RV;
+}
+
 bool X86TargetInfo::validateAsmConstraint(
     const char *&Name, TargetInfo::ConstraintInfo &Info) const {
   switch (*Name) {
@@ -1635,6 +1672,14 @@ bool X86TargetInfo::validateAsmConstrain
   case 'C': // SSE floating point constant.
   case 'G': // x87 floating point constant.
     return true;
+  case '@':
+    // CC condition changes.
+    if (auto Len = matchAsmCCConstraint(Name)) {
+      Name += Len - 1;
+      Info.setAllowsRegister();
+      return true;
+    }
+    return false;
   }
 }
 
@@ -1706,6 +1751,13 @@ bool X86TargetInfo::validateOperandSize(
 
 std::string X86TargetInfo::convertConstraint(const char *&Constraint) const {
   switch (*Constraint) {
+  case '@':
+    if (auto Len = matchAsmCCConstraint(Constraint)) {
+      std::string Converted = "{" + std::string(Constraint, Len) + "}";
+      Constraint += Len - 1;
+      return Converted;
+    }
+    return std::string(1, *Constraint);
   case 'a':
     return std::string("{ax}");
   case 'b':

Added: cfe/trunk/test/CodeGen/inline-asm-x86-flag-output.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/inline-asm-x86-flag-output.c?rev=354053&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/inline-asm-x86-flag-output.c (added)
+++ cfe/trunk/test/CodeGen/inline-asm-x86-flag-output.c Thu Feb 14 11:27:25 2019
@@ -0,0 +1,365 @@
+// RUN: %clang_cc1 -O2 -emit-llvm %s -o - -triple x86_64-unknown-linux-gnu | FileCheck %s
+
+int test_cca(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_cca
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@cca},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@cca"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_ccae(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_ccae
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@ccae},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@ccae"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_ccb(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_ccb
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@ccb},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@ccb"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_ccbe(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_ccbe
+  //CHECK: tail call i32 asm "cmp $2,$1", "={@ccbe},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@ccbe"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_ccc(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_ccc
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@ccc},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@ccc"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_cce(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_cce
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@cce},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@cce"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_ccz(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_ccz
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@ccz},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@ccz"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_ccg(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_ccg
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@ccg},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@ccg"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_ccge(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_ccge
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@ccge},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@ccge"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_ccl(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_ccl
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@ccl},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@ccl"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_ccle(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_ccle
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@ccle},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@ccle"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_ccna(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_ccna
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@ccna},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@ccna"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_ccnae(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_ccnae
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@ccnae},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@ccnae"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_ccnb(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_ccnb
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@ccnb},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@ccnb"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_ccnbe(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_ccnbe
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@ccnbe},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@ccnbe"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_ccnc(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_ccnc
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@ccnc},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@ccnc"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_ccne(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_ccne
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@ccne},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@ccne"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_ccnz(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_ccnz
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@ccnz},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@ccnz"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_ccng(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_ccng
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@ccng},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@ccng"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_ccnge(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_ccnge
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@ccnge},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@ccnge"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_ccnl(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_ccnl
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@ccnl},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@ccnl"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_ccnle(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_ccnle
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@ccnle},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@ccnle"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_ccno(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_ccno
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@ccno},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@ccno"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_ccnp(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_ccnp
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@ccnp},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@ccnp"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_ccns(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_ccns
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@ccns},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@ccns"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_cco(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_cco
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@cco},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@cco"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_ccp(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_ccp
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@ccp},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@ccp"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}
+
+int test_ccs(long nr, volatile long *addr) {
+  //CHECK-LABEL: @test_ccs
+  //CHECK: = tail call i32 asm "cmp $2,$1", "={@ccs},=*m,r,~{cc},~{dirflag},~{fpsr},~{flags}"(i64* %addr, i64 %nr)
+  int x;
+  asm("cmp %2,%1"
+      : "=@ccs"(x), "=m"(*(volatile long *)(addr))
+      : "r"(nr)
+      : "cc");
+  if (x)
+    return 0;
+  return 1;
+}

Modified: cfe/trunk/test/Preprocessor/predefined-win-macros.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/predefined-win-macros.c?rev=354053&r1=354052&r2=354053&view=diff
==============================================================================
--- cfe/trunk/test/Preprocessor/predefined-win-macros.c (original)
+++ cfe/trunk/test/Preprocessor/predefined-win-macros.c Thu Feb 14 11:27:25 2019
@@ -2,6 +2,8 @@
 //
 // RUN: %clang_cc1 %s -x c++ -E -dM -triple x86_64-pc-win32 -fms-extensions -fms-compatibility \
 // RUN:     -fms-compatibility-version=19.00 -std=c++14 -o - | FileCheck -match-full-lines %s --check-prefix=CHECK-MS64
+// RUN: %clang_cc1 %s -x c++ -E -dM -triple x86_64-pc-win32 -fms-extensions -fms-compatibility \
+// RUN:     -fms-compatibility-version=19.00 -std=c++14 -o - | grep GCC | count 1
 // CHECK-MS64: #define _INTEGRAL_MAX_BITS 64
 // CHECK-MS64: #define _MSC_EXTENSIONS 1
 // CHECK-MS64: #define _MSC_VER 1900
@@ -10,12 +12,16 @@
 // CHECK-MS64: #define _M_X64 100
 // CHECK-MS64: #define _WIN64 1
 // CHECK-MS64-NOT: #define __STRICT_ANSI__
-// CHECK-MS64-NOT: GCC
+// CHECK-MS64-NOT: GNU
+// CHECK-MS64-NOT: GXX
+// CHECK-MS64: #define __GCC_ASM_FLAG_OUTPUTS__ 1
 // CHECK-MS64-NOT: GNU
 // CHECK-MS64-NOT: GXX
 
 // RUN: %clang_cc1 %s -x c++ -E -dM -triple i686-pc-win32 -fms-extensions -fms-compatibility \
 // RUN:     -fms-compatibility-version=19.00 -std=c++17 -o - | FileCheck -match-full-lines %s --check-prefix=CHECK-MS
+// RUN: %clang_cc1 %s -x c++ -E -dM -triple i686-pc-win32 -fms-extensions -fms-compatibility \
+// RUN:     -fms-compatibility-version=19.00 -std=c++17 -o - | grep GCC | count 1
 // CHECK-MS: #define _INTEGRAL_MAX_BITS 64
 // CHECK-MS: #define _MSC_EXTENSIONS 1
 // CHECK-MS: #define _MSC_VER 1900
@@ -24,7 +30,9 @@
 // CHECK-MS: #define _M_IX86_FP 0
 // CHECK-MS: #define _WIN32 1
 // CHECK-MS-NOT: #define __STRICT_ANSI__
-// CHECK-MS-NOT: GCC
+// CHECK-MS-NOT: GNU
+// CHECK-MS-NOT: GXX
+// CHECK-MS: #define __GCC_ASM_FLAG_OUTPUTS__ 1
 // CHECK-MS-NOT: GNU
 // CHECK-MS-NOT: GXX
 
@@ -107,4 +115,3 @@
 // CHECK-ARM64-MINGW: #define _WIN32 1
 // CHECK-ARM64-MINGW: #define _WIN64 1
 // CHECK-ARM64-MINGW: #define __aarch64__ 1
-

Added: cfe/trunk/test/Preprocessor/x86_asm_flag_output.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/x86_asm_flag_output.c?rev=354053&view=auto
==============================================================================
--- cfe/trunk/test/Preprocessor/x86_asm_flag_output.c (added)
+++ cfe/trunk/test/Preprocessor/x86_asm_flag_output.c Thu Feb 14 11:27:25 2019
@@ -0,0 +1,4 @@
+// RUN: %clang -target i386-unknown-unknown -x c -E -dM -o - %s | FileCheck -match-full-lines %s
+// RUN: %clang -target x86_64-unknown-unknown -x c -E -dM -o - %s | FileCheck -match-full-lines %s
+
+// CHECK: #define __GCC_ASM_FLAG_OUTPUTS__ 1




More information about the cfe-commits mailing list