]> granicus.if.org Git - clang/commitdiff
Emit ASM input in a constant context
authorBill Wendling <isanbard@gmail.com>
Tue, 18 Dec 2018 22:54:03 +0000 (22:54 +0000)
committerBill Wendling <isanbard@gmail.com>
Tue, 18 Dec 2018 22:54:03 +0000 (22:54 +0000)
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

lib/Basic/TargetInfo.cpp
lib/CodeGen/CGStmt.cpp
lib/Sema/SemaStmtAsm.cpp
test/CodeGen/builtin-constant-p.c

index 7b69cb097c84ccb0830d7c1fa2e1dc82725765dd..269fad38b8d57fdda040a789c7fe72396b046421 100644 (file)
@@ -685,7 +685,9 @@ bool TargetInfo::validateInputConstraint(
       // FIXME: Fail if % is used with the last operand.
       break;
     case 'i': // immediate integer.
+      break;
     case 'n': // immediate integer with a known value.
+      Info.setRequiresImmediate();
       break;
     case 'I':  // Various constant constraints with target-specific meanings.
     case 'J':
index bc7a18af1e5c0fdb717bfad4d184978db23890d3..0242b48659d10eda3c1ff95e06ab6142c6706124 100644 (file)
@@ -1820,11 +1820,14 @@ llvm::Value* CodeGenFunction::EmitAsmInput(
   // 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.
   if (!Info.allowsRegister() && !Info.allowsMemory()) {
+    if (Info.requiresImmediateConstant()) {
+      llvm::APSInt AsmConst = InputExpr->EvaluateKnownConstInt(getContext());
+      return llvm::ConstantInt::get(getLLVMContext(), AsmConst);
+    }
+
     Expr::EvalResult Result;
     if (InputExpr->EvaluateAsInt(Result, getContext()))
       return llvm::ConstantInt::get(getLLVMContext(), Result.Val.getInt());
-    assert(!Info.requiresImmediateConstant() &&
-           "Required-immediate inlineasm arg isn't constant?");
   }
 
   if (Info.allowsRegister() || !Info.allowsMemory())
index d209266049e60c060a06a2eb250ea734a4128b24..b10b3d852c66763b6bc7f8d32f7fe35b86ed964f 100644 (file)
@@ -378,17 +378,17 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
                          << InputExpr->getSourceRange());
     } else if (Info.requiresImmediateConstant() && !Info.allowsRegister()) {
       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(
               Diag(InputExpr->getBeginLoc(), diag::err_asm_immediate_expected)
               << 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 {
index 7f4e7d07cc6667b3a7d8686cd0e12967f64c9c36..f1cd06ad4aabfc803e7ca2ab945cb894b91dfa08 100644 (file)
@@ -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 -O0 | FileCheck --check-prefix=O0 %s
 
 int a = 42;
 
@@ -166,3 +167,13 @@ struct { const char *t; int a; } test15[] = {
 
 extern char 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));
+}