Don't warn if the input size is less than the register size. Also don't warn if
the output size is greater than the register size. No truncation occurs with
those. Reword warning to make it clearer what's the problem is.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@169054 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 46a3bbc..18874b6 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5152,7 +5152,8 @@
     "accepted due to -fheinous-gnu-extensions, but clang may remove support "
     "for this in the future">;
   def warn_asm_mismatched_size_modifier : Warning<
-    "the size being stored is truncated, use a modifier to specify the size">,
+    "the value is truncated when put into register, "
+    "use a modifier to specify the size">,
     InGroup<ASMOperandWidths>;
 }
 
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index d6312d6..3c076ca 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -3364,6 +3364,8 @@
   virtual bool validateConstraintModifier(StringRef Constraint,
                                           const char Modifier,
                                           unsigned Size) const {
+    bool isOutput = (Constraint[0] == '=');
+
     // Strip off constraint modifiers.
     while (Constraint[0] == '=' ||
            Constraint[0] == '+' ||
@@ -3375,7 +3377,7 @@
     case 'r': {
       switch (Modifier) {
       default:
-        return Size == 32;
+        return (isOutput && Size >= 32) || Size <= 32;
       case 'q':
         // A register of size 32 cannot fit a vector type.
         return false;
diff --git a/test/CodeGen/arm-asm-warn.c b/test/CodeGen/arm-asm-warn.c
index 0c4e97a..38d5345 100644
--- a/test/CodeGen/arm-asm-warn.c
+++ b/test/CodeGen/arm-asm-warn.c
@@ -1,7 +1,16 @@
 // REQUIRES: arm-registered-target
 // RUN: %clang_cc1 -triple armv7 %s -emit-llvm -o /dev/null
-// <rdar://problem/12284092>
 
+char bar();
+
+void t1(int x, char y) {
+  __asm__ volatile("mcr p15, 0, %1, c9, c12, 5;"
+                   "mrc p15, 0, %0, c9, c13, 2;"
+                   : "=r" (x)
+                   : "r" (bar())); // no warning
+}
+
+// <rdar://problem/12284092>
 typedef __attribute__((neon_vector_type(2))) long long int64x2_t;
 typedef struct int64x2x4_t {
   int64x2_t val[4];
@@ -9,10 +18,10 @@
 int64x2x4_t t2(const long long a[]) {
   int64x2x4_t r;
   __asm__("vldm %[a], { %q[r0], %q[r1], %q[r2], %q[r3] }"
-          : [r0] "=r"(r.val[0]), // expected-warning {{the size being stored is truncated, use a modifier to specify the size}}
-            [r1] "=r"(r.val[1]), // expected-warning {{the size being stored is truncated, use a modifier to specify the size}}
-            [r2] "=r"(r.val[2]), // expected-warning {{the size being stored is truncated, use a modifier to specify the size}}
-            [r3] "=r"(r.val[3])  // expected-warning {{the size being stored is truncated, use a modifier to specify the size}}
+          : [r0] "=r"(r.val[0]), // expected-warning {{the value is truncated when put into register, use a modifier to specify the size}}
+            [r1] "=r"(r.val[1]), // expected-warning {{the value is truncated when put into register, use a modifier to specify the size}}
+            [r2] "=r"(r.val[2]), // expected-warning {{the value is truncated when put into register, use a modifier to specify the size}}
+            [r3] "=r"(r.val[3])  // expected-warning {{the value is truncated when put into register, use a modifier to specify the size}}
           : [a] "r"(a));
   return r;
 }