From d1840a054d43341f98b8a37f490248818c11fee4 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Tue, 18 Dec 2018 22:54:03 +0000 Subject: [PATCH] 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 --- lib/Basic/TargetInfo.cpp | 2 ++ lib/CodeGen/CGStmt.cpp | 7 +++++-- lib/Sema/SemaStmtAsm.cpp | 16 ++++++++-------- test/CodeGen/builtin-constant-p.c | 11 +++++++++++ 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp index 7b69cb097c..269fad38b8 100644 --- a/lib/Basic/TargetInfo.cpp +++ b/lib/Basic/TargetInfo.cpp @@ -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': diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index bc7a18af1e..0242b48659 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/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 // (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()) diff --git a/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp index d209266049..b10b3d852c 100644 --- a/lib/Sema/SemaStmtAsm.cpp +++ b/lib/Sema/SemaStmtAsm.cpp @@ -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 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 { diff --git a/test/CodeGen/builtin-constant-p.c b/test/CodeGen/builtin-constant-p.c index 7f4e7d07cc..f1cd06ad4a 100644 --- a/test/CodeGen/builtin-constant-p.c +++ b/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 -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)); +} -- 2.40.0