r242665 - [X86, inlineasm] Improve analysis of x, Y0, Yi, Ym, Yt, L, e, Z, s asm constraints (patch by Alexey Frolov)

Alexey Bataev a.bataev at hotmail.com
Mon Jul 20 05:08:00 PDT 2015


Author: abataev
Date: Mon Jul 20 07:08:00 2015
New Revision: 242665

URL: http://llvm.org/viewvc/llvm-project?rev=242665&view=rev
Log:
[X86, inlineasm] Improve analysis of x,Y0,Yi,Ym,Yt,L,e,Z,s asm constraints (patch by Alexey Frolov)

Improve Sema checking of 9 existing inline asm constraints (‘x’, ‘Y*’, ‘L’, ‘e’, ‘Z’, ‘s’).
Differential Revision: http://reviews.llvm.org/D10536

Modified:
    cfe/trunk/include/clang/Basic/TargetInfo.h
    cfe/trunk/lib/Basic/Targets.cpp
    cfe/trunk/lib/Sema/SemaStmtAsm.cpp
    cfe/trunk/test/CodeGen/mult-alt-x86.c
    cfe/trunk/test/Sema/inline-asm-validate-x86.c

Modified: cfe/trunk/include/clang/Basic/TargetInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TargetInfo.h?rev=242665&r1=242664&r2=242665&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TargetInfo.h (original)
+++ cfe/trunk/include/clang/Basic/TargetInfo.h Mon Jul 20 07:08:00 2015
@@ -22,6 +22,8 @@
 #include "clang/Basic/TargetOptions.h"
 #include "clang/Basic/VersionTuple.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -556,6 +558,7 @@ public:
       int Min;
       int Max;
     } ImmRange;
+    llvm::SmallSet<int, 4> ImmSet;
 
     std::string ConstraintStr;  // constraint: "=rm"
     std::string Name;           // Operand name: [foo] with no []'s.
@@ -591,8 +594,10 @@ public:
     bool requiresImmediateConstant() const {
       return (Flags & CI_ImmediateConstant) != 0;
     }
-    int getImmConstantMin() const { return ImmRange.Min; }
-    int getImmConstantMax() const { return ImmRange.Max; }
+    bool isValidAsmImmediate(const llvm::APInt &Value) const {
+      return (Value.sge(ImmRange.Min) && Value.sle(ImmRange.Max)) ||
+             ImmSet.count(Value.getZExtValue()) != 0;
+    }
 
     void setIsReadWrite() { Flags |= CI_ReadWrite; }
     void setEarlyClobber() { Flags |= CI_EarlyClobber; }
@@ -604,6 +609,20 @@ public:
       ImmRange.Min = Min;
       ImmRange.Max = Max;
     }
+    void setRequiresImmediate(llvm::ArrayRef<int> Exacts) {
+      Flags |= CI_ImmediateConstant;
+      for (int Exact : Exacts)
+        ImmSet.insert(Exact);
+    }
+    void setRequiresImmediate(int Exact) {
+      Flags |= CI_ImmediateConstant;
+      ImmSet.insert(Exact);
+    }
+    void setRequiresImmediate() {
+      Flags |= CI_ImmediateConstant;
+      ImmRange.Min = INT_MIN;
+      ImmRange.Max = INT_MAX;
+    }
 
     /// \brief Indicate that this is an input operand that is tied to
     /// the specified output operand. 

Modified: cfe/trunk/lib/Basic/Targets.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets.cpp?rev=242665&r1=242664&r2=242665&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Targets.cpp (original)
+++ cfe/trunk/lib/Basic/Targets.cpp Mon Jul 20 07:08:00 2015
@@ -3447,6 +3447,14 @@ X86TargetInfo::validateAsmConstraint(con
                                      TargetInfo::ConstraintInfo &Info) const {
   switch (*Name) {
   default: return false;
+  // Constant constraints.
+  case 'e': // 32-bit signed integer constant for use with sign-extending x86_64
+            // instructions.
+  case 'Z': // 32-bit unsigned integer constant for use with zero-extending
+            // x86_64 instructions.
+  case 's':
+    Info.setRequiresImmediate();
+    return true;
   case 'I':
     Info.setRequiresImmediate(0, 31);
     return true;
@@ -3457,8 +3465,7 @@ X86TargetInfo::validateAsmConstraint(con
     Info.setRequiresImmediate(-128, 127);
     return true;
   case 'L':
-    // FIXME: properly analyze this constraint:
-    //  must be one of 0xff, 0xffff, or 0xffffffff
+    Info.setRequiresImmediate({ int(0xff), int(0xffff), int(0xffffffff) });
     return true;
   case 'M':
     Info.setRequiresImmediate(0, 3);
@@ -3469,20 +3476,24 @@ X86TargetInfo::validateAsmConstraint(con
   case 'O':
     Info.setRequiresImmediate(0, 127);
     return true;
-  case 'Y': // first letter of a pair:
-    switch (*(Name+1)) {
-    default: return false;
-    case '0':  // First SSE register.
-    case 't':  // Any SSE register, when SSE2 is enabled.
-    case 'i':  // Any SSE register, when SSE2 and inter-unit moves enabled.
-    case 'm':  // any MMX register, when inter-unit moves enabled.
-      break;   // falls through to setAllowsRegister.
-  }
-  case 'f': // any x87 floating point stack register.
+  // Register constraints.
+  case 'Y': // 'Y' is the first character for several 2-character constraints.
+    // Shift the pointer to the second character of the constraint.
+    Name++;
+    switch (*Name) {
+    default:
+      return false;
+    case '0': // First SSE register.
+    case 't': // Any SSE register, when SSE2 is enabled.
+    case 'i': // Any SSE register, when SSE2 and inter-unit moves enabled.
+    case 'm': // Any MMX register, when inter-unit moves enabled.
+      Info.setAllowsRegister();
+      return true;
+    }
+  case 'f': // Any x87 floating point stack register.
     // Constraint 'f' cannot be used for output operands.
     if (Info.ConstraintStr[0] == '=')
       return false;
-
     Info.setAllowsRegister();
     return true;
   case 'a': // eax.
@@ -3492,8 +3503,8 @@ X86TargetInfo::validateAsmConstraint(con
   case 'S': // esi.
   case 'D': // edi.
   case 'A': // edx:eax.
-  case 't': // top of floating point stack.
-  case 'u': // second from top of floating point stack.
+  case 't': // Top of floating point stack.
+  case 'u': // Second from top of floating point stack.
   case 'q': // Any register accessible as [r]l: a, b, c, and d.
   case 'y': // Any MMX register.
   case 'x': // Any SSE register.
@@ -3503,12 +3514,9 @@ X86TargetInfo::validateAsmConstraint(con
             // index in a base+index memory access.
     Info.setAllowsRegister();
     return true;
+  // Floating point constant constraints.
   case 'C': // SSE floating point constant.
   case 'G': // x87 floating point constant.
-  case 'e': // 32-bit signed integer constant for use with zero-extending
-            // x86_64 instructions.
-  case 'Z': // 32-bit unsigned integer constant for use with zero-extending
-            // x86_64 instructions.
     return true;
   }
 }
@@ -3540,8 +3548,30 @@ bool X86TargetInfo::validateOperandSize(
   case 'u':
     return Size <= 128;
   case 'x':
-    // 256-bit ymm registers can be used if target supports AVX.
-    return Size <= (SSELevel >= AVX ? 256U : 128U);
+    if (SSELevel >= AVX512F)
+      // 512-bit zmm registers can be used if target supports AVX512F.
+      return Size <= 512U;
+    else if (SSELevel >= AVX)
+      // 256-bit ymm registers can be used if target supports AVX.
+      return Size <= 256U;
+    return Size <= 128U;
+  case 'Y':
+    // 'Y' is the first character for several 2-character constraints.
+    switch (Constraint[1]) {
+    default: break;
+    case 'm':
+      // 'Ym' is synonymous with 'y'.
+      return Size <= 64;
+    case 'i':
+    case 't':
+      // 'Yi' and 'Yt' are synonymous with 'x' when SSE2 is enabled.
+      if (SSELevel >= AVX512F)
+        return Size <= 512U;
+      else if (SSELevel >= AVX)
+        return Size <= 256U;
+      return SSELevel >= SSE2 && Size <= 128U;
+    }
+
   }
 
   return true;

Modified: cfe/trunk/lib/Sema/SemaStmtAsm.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmtAsm.cpp?rev=242665&r1=242664&r2=242665&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmtAsm.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmtAsm.cpp Mon Jul 20 07:08:00 2015
@@ -260,8 +260,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceL
            return StmtError(
                Diag(InputExpr->getLocStart(), diag::err_asm_immediate_expected)
                 << Info.getConstraintStr() << InputExpr->getSourceRange());
-         if (Result.slt(Info.getImmConstantMin()) ||
-             Result.sgt(Info.getImmConstantMax()))
+         if (!Info.isValidAsmImmediate(Result))
            return StmtError(Diag(InputExpr->getLocStart(),
                                  diag::err_invalid_asm_value_for_constraint)
                             << Result.toString(10) << Info.getConstraintStr()

Modified: cfe/trunk/test/CodeGen/mult-alt-x86.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/mult-alt-x86.c?rev=242665&r1=242664&r2=242665&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/mult-alt-x86.c (original)
+++ cfe/trunk/test/CodeGen/mult-alt-x86.c Mon Jul 20 07:08:00 2015
@@ -110,9 +110,9 @@ void single_x()
 }
 
 // CHECK: @single_Y
-void single_Y0()
+void single_Y()
 {
-  // Y constraint currently broken.
+  // 'Y' constraint currently broken.
   //asm("foo %1,%0" : "=Y0" (mout0) : "Y0" (min1));
   //asm("foo %1,%0" : "=Yz" (mout0) : "Yz" (min1));
   //asm("foo %1,%0" : "=Yt" (mout0) : "Yt" (min1));
@@ -144,8 +144,12 @@ void single_K()
 // CHECK: @single_L
 void single_L()
 {
-  // CHECK: asm "foo $1,$0", "=*m,L[[CLOBBERS]](i32* @mout0, i32 1)
-  asm("foo %1,%0" : "=m" (mout0) : "L" (1));
+  // CHECK: asm "foo $1,$0", "=*m,L[[CLOBBERS]](i32* @mout0, i32 255)
+  asm("foo %1,%0" : "=m" (mout0) : "L" (0xff));
+  // CHECK: asm "foo $1,$0", "=*m,L[[CLOBBERS]](i32* @mout0, i32 65535)
+  asm("foo %1,%0" : "=m" (mout0) : "L" (0xffff));
+  // CHECK: asm "foo $1,$0", "=*m,L[[CLOBBERS]](i32* @mout0, i32 -1)
+  asm("foo %1,%0" : "=m" (mout0) : "L" (0xffffffff));
 }
 
 // CHECK: @single_M

Modified: cfe/trunk/test/Sema/inline-asm-validate-x86.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/inline-asm-validate-x86.c?rev=242665&r1=242664&r2=242665&view=diff
==============================================================================
--- cfe/trunk/test/Sema/inline-asm-validate-x86.c (original)
+++ cfe/trunk/test/Sema/inline-asm-validate-x86.c Mon Jul 20 07:08:00 2015
@@ -52,6 +52,32 @@ void K(int i, int j) {
           : "0"(i), "K"(96)); // expected-no-error
 }
 
+void L(int i, int j) {
+  static const int Invalid1 = 1;
+  static const int Invalid2 = 42;
+  static const int Valid1 = 0xff;
+  static const int Valid2 = 0xffff;
+  static const int Valid3 = 0xffffffff;
+  __asm__("xorl %0,%2"
+          : "=r"(i)
+          : "0"(i), "L"(j)); // expected-error{{constraint 'L' expects an integer constant expression}}
+  __asm__("xorl %0,%2"
+          : "=r"(i)
+          : "0"(i), "L"(Invalid1)); // expected-error{{value '1' out of range for constraint 'L'}}
+  __asm__("xorl %0,%2"
+          : "=r"(i)
+          : "0"(i), "L"(Invalid2)); // expected-error{{value '42' out of range for constraint 'L'}}
+  __asm__("xorl %0,%2"
+          : "=r"(i)
+          : "0"(i), "L"(Valid1)); // expected-no-error
+  __asm__("xorl %0,%2"
+          : "=r"(i)
+          : "0"(i), "L"(Valid2)); // expected-no-error
+  __asm__("xorl %0,%2"
+          : "=r"(i)
+          : "0"(i), "L"(Valid3)); // expected-no-error
+}
+
 void M(int i, int j) {
   static const int BelowMin = -1;
   static const int AboveMax = 4;






More information about the cfe-commits mailing list