Forráskód Böngészése

Emit ASM input in a constant context

Summary:
Some ASM input constraints (e.g., "i" and "n") require immediate values. At O0,
very few code transformations are performed. So if we cannot resolve to an
immediate when emitting the ASM input we shouldn't delay its processing.

Reviewers: rsmith, efriedma

Reviewed By: efriedma

Subscribers: rehana, efriedma, craig.topper, jyknight, cfe-commits

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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@349561 91177308-0d34-0410-b5e6-96231b3b80d8
Bill Wendling 6 éve
szülő
commit
d1840a054d

+ 2 - 0
lib/Basic/TargetInfo.cpp

@@ -685,7 +685,9 @@ bool TargetInfo::validateInputConstraint(
       // FIXME: Fail if % is used with the last operand.
       // FIXME: Fail if % is used with the last operand.
       break;
       break;
     case 'i': // immediate integer.
     case 'i': // immediate integer.
+      break;
     case 'n': // immediate integer with a known value.
     case 'n': // immediate integer with a known value.
+      Info.setRequiresImmediate();
       break;
       break;
     case 'I':  // Various constant constraints with target-specific meanings.
     case 'I':  // Various constant constraints with target-specific meanings.
     case 'J':
     case 'J':

+ 5 - 2
lib/CodeGen/CGStmt.cpp

@@ -1820,11 +1820,14 @@ llvm::Value* CodeGenFunction::EmitAsmInput(
   // If this can't be a register or memory, i.e., has to be a constant
   // If this can't be a register or memory, i.e., has to be a constant
   // (immediate or symbolic), try to emit it as such.
   // (immediate or symbolic), try to emit it as such.
   if (!Info.allowsRegister() && !Info.allowsMemory()) {
   if (!Info.allowsRegister() && !Info.allowsMemory()) {
+    if (Info.requiresImmediateConstant()) {
+      llvm::APSInt AsmConst = InputExpr->EvaluateKnownConstInt(getContext());
+      return llvm::ConstantInt::get(getLLVMContext(), AsmConst);
+    }
+
     Expr::EvalResult Result;
     Expr::EvalResult Result;
     if (InputExpr->EvaluateAsInt(Result, getContext()))
     if (InputExpr->EvaluateAsInt(Result, getContext()))
       return llvm::ConstantInt::get(getLLVMContext(), Result.Val.getInt());
       return llvm::ConstantInt::get(getLLVMContext(), Result.Val.getInt());
-    assert(!Info.requiresImmediateConstant() &&
-           "Required-immediate inlineasm arg isn't constant?");
   }
   }
 
 
   if (Info.allowsRegister() || !Info.allowsMemory())
   if (Info.allowsRegister() || !Info.allowsMemory())

+ 8 - 8
lib/Sema/SemaStmtAsm.cpp

@@ -378,17 +378,17 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
                          << InputExpr->getSourceRange());
                          << InputExpr->getSourceRange());
     } else if (Info.requiresImmediateConstant() && !Info.allowsRegister()) {
     } else if (Info.requiresImmediateConstant() && !Info.allowsRegister()) {
       if (!InputExpr->isValueDependent()) {
       if (!InputExpr->isValueDependent()) {
-        Expr::EvalResult EVResult;
-        if (!InputExpr->EvaluateAsInt(EVResult, Context))
+        llvm::SmallVector<PartialDiagnosticAt, 1> Diags;
+        llvm::APSInt Result = InputExpr->EvaluateKnownConstInt(Context, &Diags);
+        if (!Diags.empty())
           return StmtError(
           return StmtError(
               Diag(InputExpr->getBeginLoc(), diag::err_asm_immediate_expected)
               Diag(InputExpr->getBeginLoc(), diag::err_asm_immediate_expected)
               << Info.getConstraintStr() << InputExpr->getSourceRange());
               << Info.getConstraintStr() << InputExpr->getSourceRange());
-        llvm::APSInt Result = EVResult.Val.getInt();
-         if (!Info.isValidAsmImmediate(Result))
-           return StmtError(Diag(InputExpr->getBeginLoc(),
-                                 diag::err_invalid_asm_value_for_constraint)
-                            << Result.toString(10) << Info.getConstraintStr()
-                            << InputExpr->getSourceRange());
+        if (!Info.isValidAsmImmediate(Result))
+          return StmtError(Diag(InputExpr->getBeginLoc(),
+                                diag::err_invalid_asm_value_for_constraint)
+                           << Result.toString(10) << Info.getConstraintStr()
+                           << InputExpr->getSourceRange());
       }
       }
 
 
     } else {
     } else {

+ 11 - 0
test/CodeGen/builtin-constant-p.c

@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s -O2 | FileCheck %s
 // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s -O2 | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s -O0 | FileCheck --check-prefix=O0 %s
 
 
 int a = 42;
 int a = 42;
 
 
@@ -166,3 +167,13 @@ struct { const char *t; int a; } test15[] = {
 
 
 extern char test16_v;
 extern char test16_v;
 struct { int a; } test16 = { __builtin_constant_p(test16_v) };
 struct { int a; } test16 = { __builtin_constant_p(test16_v) };
+
+extern unsigned long long test17_v;
+
+void test17() {
+  // O0: define void @test17
+  // O0: call void asm sideeffect "", {{.*}}(i32 -1) 
+  // CHECK: define void @test17
+  // CHECK: call void asm sideeffect "", {{.*}}(i32 -1) 
+  __asm__ __volatile__("" :: "n"( (__builtin_constant_p(test17_v) || 0) ? 1 : -1));
+}