Index: lib/Basic/TargetInfo.cpp =================================================================== --- lib/Basic/TargetInfo.cpp +++ lib/Basic/TargetInfo.cpp @@ -685,7 +685,9 @@ // 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: lib/CodeGen/CGStmt.cpp =================================================================== --- lib/CodeGen/CGStmt.cpp +++ lib/CodeGen/CGStmt.cpp @@ -1820,11 +1820,14 @@ // 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: lib/Sema/SemaStmtAsm.cpp =================================================================== --- lib/Sema/SemaStmtAsm.cpp +++ lib/Sema/SemaStmtAsm.cpp @@ -378,17 +378,17 @@ << 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 { Index: test/CodeGen/builtin-constant-p.c =================================================================== --- test/CodeGen/builtin-constant-p.c +++ 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 --check-prefix=O2 %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s -O0 | FileCheck --check-prefix=O0 %s int a = 42; @@ -14,8 +15,8 @@ struct foo f = (struct foo){ __builtin_constant_p(y), 42 }; struct foo test0(int expr) { - // CHECK: define i64 @test0(i32 %expr) - // CHECK: call i1 @llvm.is.constant.i32(i32 %expr) + // O2: define i64 @test0(i32 %expr) + // O2: call i1 @llvm.is.constant.i32(i32 %expr) struct foo f = (struct foo){ __builtin_constant_p(expr), 42 }; return f; } @@ -27,15 +28,15 @@ } int test1() { - // CHECK: define i32 @test1 - // CHECK: add nsw i32 %0, -13 - // CHECK-NEXT: call i1 @llvm.is.constant.i32(i32 %sub) + // O2: define i32 @test1 + // O2: add nsw i32 %0, -13 + // O2-NEXT: call i1 @llvm.is.constant.i32(i32 %sub) return bcp(test1_i(&a) - 13); } int test2() { - // CHECK: define i32 @test2 - // CHECK: ret i32 0 + // O2: define i32 @test2 + // O2: ret i32 0 return __builtin_constant_p(&a - 13); } @@ -44,8 +45,8 @@ } int test3() { - // CHECK: define i32 @test3 - // CHECK: ret i32 1 + // O2: define i32 @test3 + // O2: ret i32 1 return bcp(test3_i(&a) - 13); } @@ -54,16 +55,16 @@ int b[] = {1, 2, 3}; int test4() { - // CHECK: define i32 @test4 - // CHECK: ret i32 0 + // O2: define i32 @test4 + // O2: ret i32 0 return __builtin_constant_p(b); } const char test5_c[] = {1, 2, 3, 0}; int test5() { - // CHECK: define i32 @test5 - // CHECK: ret i32 0 + // O2: define i32 @test5 + // O2: ret i32 0 return __builtin_constant_p(test5_c); } @@ -72,16 +73,16 @@ } int test6() { - // CHECK: define i32 @test6 - // CHECK: ret i32 0 + // O2: define i32 @test6 + // O2: ret i32 0 return __builtin_constant_p(test6_i(test5_c)); } /* --- Non-constant global variables */ int test7() { - // CHECK: define i32 @test7 - // CHECK: call i1 @llvm.is.constant.i32(i32 %0) + // O2: define i32 @test7 + // O2: call i1 @llvm.is.constant.i32(i32 %0) return bcp(a); } @@ -90,8 +91,8 @@ const int c = 42; int test8() { - // CHECK: define i32 @test8 - // CHECK: ret i32 1 + // O2: define i32 @test8 + // O2: ret i32 1 return bcp(c); } @@ -101,34 +102,34 @@ const int c_arr[] = { 1, 2, 3 }; int test9() { - // CHECK: define i32 @test9 - // CHECK: call i1 @llvm.is.constant.i32(i32 %0) + // O2: define i32 @test9 + // O2: call i1 @llvm.is.constant.i32(i32 %0) return __builtin_constant_p(arr[2]); } int test10() { - // CHECK: define i32 @test10 - // CHECK: ret i32 1 + // O2: define i32 @test10 + // O2: ret i32 1 return __builtin_constant_p(c_arr[2]); } int test11() { - // CHECK: define i32 @test11 - // CHECK: ret i32 0 + // O2: define i32 @test11 + // O2: ret i32 0 return __builtin_constant_p(c_arr); } /* --- Function pointers */ int test12() { - // CHECK: define i32 @test12 - // CHECK: ret i32 0 + // O2: define i32 @test12 + // O2: ret i32 0 return __builtin_constant_p(&test10); } int test13() { - // CHECK: define i32 @test13 - // CHECK: ret i32 1 + // O2: define i32 @test13 + // O2: ret i32 1 return __builtin_constant_p(&test10 != 0); } @@ -166,3 +167,13 @@ 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) + // O2: define void @test17 + // O2: call void asm sideeffect "", {{.*}}(i32 -1) + __asm__ __volatile__("" :: "n"( (__builtin_constant_p(test17_v) || 0) ? 1 : -1)); +}