[CodeGen] Consider tied operands when adjusting inline asm operands.
authorEli Friedman <efriedma@quicinc.com>
Thu, 14 Mar 2019 19:46:51 +0000 (19:46 +0000)
committerEli Friedman <efriedma@quicinc.com>
Thu, 14 Mar 2019 19:46:51 +0000 (19:46 +0000)
The constraint "0" in the following asm did not consider the its
relationship with "=y" when try to replace the type of the operands.

asm ("nop" : "=y"(Mu8_1 ) : "0"(Mu8_0 ));

Patch by Xiang Zhang.

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

llvm-svn: 356196

clang/lib/CodeGen/CGStmt.cpp
clang/test/CodeGen/asm-inout.c

index b9905a2..c617b19 100644 (file)
@@ -1939,6 +1939,9 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
   std::vector<llvm::Value*> InOutArgs;
   std::vector<llvm::Type*> InOutArgTypes;
 
+  // Keep track of out constraints for tied input operand.
+  std::vector<std::string> OutputConstraints;
+
   // An inline asm can be marked readonly if it meets the following conditions:
   //  - it doesn't have any sideeffects
   //  - it doesn't clobber memory
@@ -1961,7 +1964,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
     OutputConstraint = AddVariableConstraints(OutputConstraint, *OutExpr,
                                               getTarget(), CGM, S,
                                               Info.earlyClobber());
-
+    OutputConstraints.push_back(OutputConstraint);
     LValue Dest = EmitLValue(OutExpr);
     if (!Constraints.empty())
       Constraints += ',';
@@ -2079,6 +2082,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
         InputConstraint, *InputExpr->IgnoreParenNoopCasts(getContext()),
         getTarget(), CGM, S, false /* No EarlyClobber */);
 
+    std::string ReplaceConstraint (InputConstraint);
     llvm::Value *Arg = EmitAsmInput(Info, InputExpr, Constraints);
 
     // If this input argument is tied to a larger output result, extend the
@@ -2106,9 +2110,11 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
           Arg = Builder.CreateFPExt(Arg, OutputTy);
         }
       }
+      // Deal with the tied operands' constraint code in adjustInlineAsmType.
+      ReplaceConstraint = OutputConstraints[Output];
     }
     if (llvm::Type* AdjTy =
-              getTargetHooks().adjustInlineAsmType(*this, InputConstraint,
+          getTargetHooks().adjustInlineAsmType(*this, ReplaceConstraint,
                                                    Arg->getType()))
       Arg = Builder.CreateBitCast(Arg, AdjTy);
     else
index e5da5c5..411f6fa 100644 (file)
@@ -46,3 +46,12 @@ __m64 test5(__m64 __A, __m64 __B) {
   asm ("pmulhuw %1, %0\n\t" : "+y" (__A) : "y" (__B));
   return __A;
 }
+
+// CHECK: @test6
+int test6(void) {
+  typedef unsigned char __attribute__((vector_size(8))) _m64u8;
+  _m64u8 __attribute__((aligned(16))) Mu8_0, __attribute__((aligned(16))) Mu8_1;
+  // CHECK: call x86_mmx asm "nop", "=y,0,~{dirflag},~{fpsr},~{flags}"(x86_mmx %1)
+  asm ("nop" : "=y"(Mu8_1 ) : "0"(Mu8_0 ));
+  return 0;
+}