Improve __builtin_constant_p lowering

__builtin_constant_p used to be short-cut evaluated to false when
building with -O0. This is undesirable as it means that constant folding
in the front-end can give different results than folding in the back-end.
It can also create conditional branches on constant conditions that don't
get folded away. With the pending improvements to the llvm.is.constant
handling on the LLVM side, the short-cut is no longer useful.

Adjust various codegen tests to not depend on the short-cut or the
backend optimisations.

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

llvm-svn: 374742
This commit is contained in:
Joerg Sonnenberger 2019-10-13 22:33:46 +00:00
parent f79716774a
commit 529f4ed401
4 changed files with 75 additions and 95 deletions

View File

@ -2101,10 +2101,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
case Builtin::BI__builtin_constant_p: { case Builtin::BI__builtin_constant_p: {
llvm::Type *ResultType = ConvertType(E->getType()); llvm::Type *ResultType = ConvertType(E->getType());
if (CGM.getCodeGenOpts().OptimizationLevel == 0)
// At -O0, we don't perform inlining, so we don't need to delay the
// processing.
return RValue::get(ConstantInt::get(ResultType, 0));
const Expr *Arg = E->getArg(0); const Expr *Arg = E->getArg(0);
QualType ArgType = Arg->getType(); QualType ArgType = Arg->getType();

View File

@ -1,12 +1,8 @@
// 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 -disable-llvm-optzns -o - %s -O2 | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s -O0 | FileCheck --check-prefix=O0 %s // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -disable-llvm-optzns -o - %s -O0 | FileCheck %s
int a = 42; int a = 42;
inline int bcp(int x) {
return __builtin_constant_p(x);
}
/* --- Compound literals */ /* --- Compound literals */
struct foo { int x, y; }; struct foo { int x, y; };
@ -15,85 +11,56 @@ int y;
struct foo f = (struct foo){ __builtin_constant_p(y), 42 }; struct foo f = (struct foo){ __builtin_constant_p(y), 42 };
struct foo test0(int expr) { struct foo test0(int expr) {
// CHECK: define i64 @test0(i32 %expr) // CHECK-LABEL: test0
// CHECK: call i1 @llvm.is.constant.i32(i32 %expr) // CHECK: call i1 @llvm.is.constant.i32
struct foo f = (struct foo){ __builtin_constant_p(expr), 42 }; struct foo f = (struct foo){ __builtin_constant_p(expr), 42 };
return f; return f;
} }
/* --- Pointer types */ /* --- Pointer types */
inline int test1_i(int *x) {
return *x;
}
int test1() { int test1() {
// CHECK: define i32 @test1 // CHECK-LABEL: test1
// CHECK: add nsw i32 %0, -13
// CHECK-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 // CHECK: ret i32 0
return __builtin_constant_p(&a - 13); return __builtin_constant_p(&a - 13);
} }
inline int test3_i(int *x) {
return 42;
}
int test3() {
// CHECK: define i32 @test3
// CHECK: ret i32 1
return bcp(test3_i(&a) - 13);
}
/* --- Aggregate types */ /* --- Aggregate types */
int b[] = {1, 2, 3}; int b[] = {1, 2, 3};
int test4() { int test2() {
// CHECK: define i32 @test4 // CHECK-LABEL: test2
// CHECK: ret i32 0 // CHECK: ret i32 0
return __builtin_constant_p(b); return __builtin_constant_p(b);
} }
const char test5_c[] = {1, 2, 3, 0}; const char test3_c[] = {1, 2, 3, 0};
int test5() { int test3() {
// CHECK: define i32 @test5 // CHECK-LABEL: test3
// CHECK: ret i32 0 // CHECK: ret i32 0
return __builtin_constant_p(test5_c); return __builtin_constant_p(test3_c);
} }
inline char test6_i(const char *x) { inline char test4_i(const char *x) {
return x[1]; return x[1];
} }
int test6() { int test4() {
// CHECK: define i32 @test6 // CHECK: define i32 @test4
// CHECK: ret i32 0 // CHECK: ret i32 0
return __builtin_constant_p(test6_i(test5_c)); return __builtin_constant_p(test4_i(test3_c));
}
/* --- Non-constant global variables */
int test7() {
// CHECK: define i32 @test7
// CHECK: call i1 @llvm.is.constant.i32(i32 %0)
return bcp(a);
} }
/* --- Constant global variables */ /* --- Constant global variables */
const int c = 42; const int c = 42;
int test8() { int test5() {
// CHECK: define i32 @test8 // CHECK-LABEL: test5
// CHECK: ret i32 1 // CHECK: ret i32 1
return bcp(c); return __builtin_constant_p(c);
} }
/* --- Array types */ /* --- Array types */
@ -101,34 +68,34 @@ int test8() {
int arr[] = { 1, 2, 3 }; int arr[] = { 1, 2, 3 };
const int c_arr[] = { 1, 2, 3 }; const int c_arr[] = { 1, 2, 3 };
int test9() { int test6() {
// CHECK: define i32 @test9 // CHECK-LABEL: test6
// CHECK: call i1 @llvm.is.constant.i32(i32 %0) // CHECK: call i1 @llvm.is.constant.i32
return __builtin_constant_p(arr[2]); return __builtin_constant_p(arr[2]);
} }
int test10() { int test7() {
// CHECK: define i32 @test10 // CHECK-LABEL: test7
// CHECK: ret i32 1 // CHECK: call i1 @llvm.is.constant.i32
return __builtin_constant_p(c_arr[2]); return __builtin_constant_p(c_arr[2]);
} }
int test11() { int test8() {
// CHECK: define i32 @test11 // CHECK-LABEL: test8
// CHECK: ret i32 0 // CHECK: ret i32 0
return __builtin_constant_p(c_arr); return __builtin_constant_p(c_arr);
} }
/* --- Function pointers */ /* --- Function pointers */
int test12() { int test9() {
// CHECK: define i32 @test12 // CHECK-LABEL: test9
// CHECK: ret i32 0 // CHECK: ret i32 0
return __builtin_constant_p(&test10); return __builtin_constant_p(&test9);
} }
int test13() { int test10() {
// CHECK: define i32 @test13 // CHECK-LABEL: test10
// CHECK: ret i32 1 // CHECK: ret i32 1
return __builtin_constant_p(&test10 != 0); return __builtin_constant_p(&test10 != 0);
} }
@ -155,33 +122,31 @@ extern fn_p *dest_p;
static void src_fn(void) { static void src_fn(void) {
} }
void test14() { void test11() {
assign(dest_p, src_fn); assign(dest_p, src_fn);
} }
extern int test15_v; extern int test12_v;
struct { const char *t; int a; } test15[] = { struct { const char *t; int a; } test12[] = {
{ "tag", __builtin_constant_p(test15_v) && !test15_v ? 1 : 0 } { "tag", __builtin_constant_p(test12_v) && !test12_v ? 1 : 0 }
}; };
extern char test16_v; extern char test13_v;
struct { int a; } test16 = { __builtin_constant_p(test16_v) }; struct { int a; } test13 = { __builtin_constant_p(test13_v) };
extern unsigned long long test17_v; extern unsigned long long test14_v;
void test17() { void test14() {
// O0: define void @test17 // CHECK-LABEL: test14
// O0: call void asm sideeffect "", {{.*}}(i32 -1)
// CHECK: define void @test17
// CHECK: call void asm sideeffect "", {{.*}}(i32 -1) // CHECK: call void asm sideeffect "", {{.*}}(i32 -1)
__asm__ __volatile__("" :: "n"( (__builtin_constant_p(test17_v) || 0) ? 1 : -1)); __asm__ __volatile__("" :: "n"( (__builtin_constant_p(test14_v) || 0) ? 1 : -1));
} }
int test18_f(); int test15_f();
// CHECK: define void @test18 // CHECK-LABEL: define void @test15
// CHECK-NOT: call {{.*}}test18_f // CHECK-NOT: call {{.*}}test15_f
void test18() { void test15() {
int a, b; int a, b;
(void)__builtin_constant_p((a = b, test18_f())); (void)__builtin_constant_p((a = b, test15_f()));
} }

View File

@ -231,7 +231,9 @@ test_bs() {
// CHECK-NEXT: br i1 [[REG147]], label %[[REG148:[0-9a-zA-Z_%.]+]], label %[[REG149:[0-9a-zA-Z_%.]+]] // CHECK-NEXT: br i1 [[REG147]], label %[[REG148:[0-9a-zA-Z_%.]+]], label %[[REG149:[0-9a-zA-Z_%.]+]]
// CHECK: [[REG148]]: // CHECK: [[REG148]]:
// CHECK-LE-NEXT: br i1 false, label %[[REG150:[0-9a-zA-Z_%.]+]], label %[[REG151:[0-9a-zA-Z_%.]+]] // CHECK-LE-NEXT: load
// CHECK-LE-NEXT: call i1 @llvm.is.constant
// CHECK-LE-NEXT: br i1 %[[REG1896a:[0-9a-zA-Z_%.]+]], label %[[REG150:[0-9a-zA-Z_%.]+]], label %[[REG151:[0-9a-zA-Z_%.]+]]
// CHECK-LE: [[REG150]]: // CHECK-LE: [[REG150]]:
// CHECK-LE: [[REG152:[0-9a-zA-Z_%.]+]] = load <2 x i64>, <2 x i64>* [[REG143]], align 16 // CHECK-LE: [[REG152:[0-9a-zA-Z_%.]+]] = load <2 x i64>, <2 x i64>* [[REG143]], align 16
// CHECK-LE-NEXT: [[REG153:[0-9a-zA-Z_%.]+]] = bitcast <2 x i64> [[REG152]] to <16 x i8> // CHECK-LE-NEXT: [[REG153:[0-9a-zA-Z_%.]+]] = bitcast <2 x i64> [[REG152]] to <16 x i8>
@ -2326,7 +2328,9 @@ test_sll() {
// CHECK-NEXT: br i1 [[REG1559]], label %[[REG1560:[0-9a-zA-Z_%.]+]], label %[[REG1557:[0-9a-zA-Z_%.]+]] // CHECK-NEXT: br i1 [[REG1559]], label %[[REG1560:[0-9a-zA-Z_%.]+]], label %[[REG1557:[0-9a-zA-Z_%.]+]]
// CHECK: [[REG1560]]: // CHECK: [[REG1560]]:
// CHECK-NEXT: br i1 false, label %[[REG1561:[0-9a-zA-Z_%.]+]], label %[[REG1562:[0-9a-zA-Z_%.]+]] // CHECK-NEXT: load
// CHECK-NEXT: call i1 @llvm.is.constant
// CHECK-NEXT: br i1 %[[REG1561a:[0-9a-zA-Z_%.]+]], label %[[REG1561:[0-9a-zA-Z_%.]+]], label %[[REG1562:[0-9a-zA-Z_%.]+]]
// CHECK: [[REG1561]]: // CHECK: [[REG1561]]:
// CHECK-NEXT: [[REG1563:[0-9a-zA-Z_%.]+]] = load i32, i32* [[REG1552]], align 4 // CHECK-NEXT: [[REG1563:[0-9a-zA-Z_%.]+]] = load i32, i32* [[REG1552]], align 4
@ -2369,7 +2373,9 @@ test_sll() {
// CHECK-NEXT: br i1 [[REG1587]], label %[[REG1588:[0-9a-zA-Z_%.]+]], label %[[REG1585:[0-9a-zA-Z_%.]+]] // CHECK-NEXT: br i1 [[REG1587]], label %[[REG1588:[0-9a-zA-Z_%.]+]], label %[[REG1585:[0-9a-zA-Z_%.]+]]
// CHECK: [[REG1588]]: // CHECK: [[REG1588]]:
// CHECK-NEXT: br i1 false, label %[[REG1589:[0-9a-zA-Z_%.]+]], label %[[REG1590:[0-9a-zA-Z_%.]+]] // CHECK-NEXT: load
// CHECK-NEXT: call i1 @llvm.is.constant
// CHECK-NEXT: br i1 %{{[0-9a-zA-Z_%.]+}}, label %[[REG1589:[0-9a-zA-Z_%.]+]], label %[[REG1590:[0-9a-zA-Z_%.]+]]
// CHECK: [[REG1589]]: // CHECK: [[REG1589]]:
// CHECK-NEXT: [[REG1591:[0-9a-zA-Z_%.]+]] = load i32, i32* [[REG1580]], align 4 // CHECK-NEXT: [[REG1591:[0-9a-zA-Z_%.]+]] = load i32, i32* [[REG1580]], align 4
@ -2416,7 +2422,9 @@ test_sll() {
// CHECK-NEXT: br i1 [[REG1617]], label %[[REG1618:[0-9a-zA-Z_%.]+]], label %[[REG1615:[0-9a-zA-Z_%.]+]] // CHECK-NEXT: br i1 [[REG1617]], label %[[REG1618:[0-9a-zA-Z_%.]+]], label %[[REG1615:[0-9a-zA-Z_%.]+]]
// CHECK: [[REG1618]]: // CHECK: [[REG1618]]:
// CHECK-NEXT: br i1 false, label %[[REG1619:[0-9a-zA-Z_%.]+]], label %[[REG1620:[0-9a-zA-Z_%.]+]] // CHECK-NEXT: load
// CHECK-NEXT: call i1 @llvm.is.constant
// CHECK-NEXT: br i1 %{{[0-9a-zA-Z_%.]+}}, label %[[REG1619:[0-9a-zA-Z_%.]+]], label %[[REG1620:[0-9a-zA-Z_%.]+]]
// CHECK: [[REG1619]]: // CHECK: [[REG1619]]:
// CHECK-NEXT: [[REG1621:[0-9a-zA-Z_%.]+]] = load i32, i32* [[REG1610]], align 4 // CHECK-NEXT: [[REG1621:[0-9a-zA-Z_%.]+]] = load i32, i32* [[REG1610]], align 4
@ -2563,7 +2571,9 @@ test_sra() {
// CHECK-NEXT: br i1 [[REG1712]], label %[[REG1713:[0-9a-zA-Z_%.]+]], label %[[REG1714:[0-9a-zA-Z_%.]+]] // CHECK-NEXT: br i1 [[REG1712]], label %[[REG1713:[0-9a-zA-Z_%.]+]], label %[[REG1714:[0-9a-zA-Z_%.]+]]
// CHECK: [[REG1713]]: // CHECK: [[REG1713]]:
// CHECK-NEXT: br i1 false, label %[[REG1715:[0-9a-zA-Z_%.]+]], label %[[REG1716:[0-9a-zA-Z_%.]+]] // CHECK-NEXT: load
// CHECK-NEXT: call i1 @llvm.is.constant
// CHECK-NEXT: br i1 %[[REG1715a:[0-9a-zA-Z_%.]+]], label %[[REG1715:[0-9a-zA-Z_%.]+]], label %[[REG1716:[0-9a-zA-Z_%.]+]]
// CHECK: [[REG1715]]: // CHECK: [[REG1715]]:
// CHECK-NEXT: [[REG1717:[0-9a-zA-Z_%.]+]] = load i32, i32* [[REG1709]], align 4 // CHECK-NEXT: [[REG1717:[0-9a-zA-Z_%.]+]] = load i32, i32* [[REG1709]], align 4
@ -2601,7 +2611,9 @@ test_sra() {
// CHECK-NEXT: br i1 [[REG1737]], label %[[REG1738:[0-9a-zA-Z_%.]+]], label %[[REG1739:[0-9a-zA-Z_%.]+]] // CHECK-NEXT: br i1 [[REG1737]], label %[[REG1738:[0-9a-zA-Z_%.]+]], label %[[REG1739:[0-9a-zA-Z_%.]+]]
// CHECK: [[REG1738]]: // CHECK: [[REG1738]]:
// CHECK-NEXT: br i1 false, label %[[REG1740:[0-9a-zA-Z_%.]+]], label %[[REG1741:[0-9a-zA-Z_%.]+]] // CHECK-NEXT: load
// CHECK-NEXT: call i1 @llvm.is.constant
// CHECK-NEXT: br i1 %[[REG1738:[0-9a-zA-Z_%.]+]], label %[[REG1740:[0-9a-zA-Z_%.]+]], label %[[REG1741:[0-9a-zA-Z_%.]+]]
// CHECK: [[REG1740]]: // CHECK: [[REG1740]]:
// CHECK-NEXT: [[REG1742:[0-9a-zA-Z_%.]+]] = load i32, i32* [[REG1734]], align 4 // CHECK-NEXT: [[REG1742:[0-9a-zA-Z_%.]+]] = load i32, i32* [[REG1734]], align 4
@ -2741,7 +2753,9 @@ test_srl() {
// CHECK-NEXT: [[REG1837:[0-9a-zA-Z_%.]+]] = icmp slt i32 [[REG1836]], 16 // CHECK-NEXT: [[REG1837:[0-9a-zA-Z_%.]+]] = icmp slt i32 [[REG1836]], 16
// CHECK-NEXT: br i1 [[REG1837]], label %[[REG1838:[0-9a-zA-Z_%.]+]], label %[[REG1839:[0-9a-zA-Z_%.]+]] // CHECK-NEXT: br i1 [[REG1837]], label %[[REG1838:[0-9a-zA-Z_%.]+]], label %[[REG1839:[0-9a-zA-Z_%.]+]]
// CHECK: [[REG1838]]: // CHECK: [[REG1838]]:
// CHECK-NEXT: br i1 false, label %[[REG1840:[0-9a-zA-Z_%.]+]], label %[[REG1841:[0-9a-zA-Z_%.]+]] // CHECK-NEXT: load
// CHECK-NEXT: call i1 @llvm.is.constant
// CHECK-NEXT: br i1 %[[REG1838a:[0-9a-zA-Z_%.]+]], label %[[REG1840:[0-9a-zA-Z_%.]+]], label %[[REG1841:[0-9a-zA-Z_%.]+]]
// CHECK: [[REG1840]]: // CHECK: [[REG1840]]:
// CHECK-NEXT: [[REG1842:[0-9a-zA-Z_%.]+]] = load i32, i32* [[REG1834]], align 4 // CHECK-NEXT: [[REG1842:[0-9a-zA-Z_%.]+]] = load i32, i32* [[REG1834]], align 4
// CHECK-NEXT: [[REG1843:[0-9a-zA-Z_%.]+]] = trunc i32 [[REG1842]] to i8 // CHECK-NEXT: [[REG1843:[0-9a-zA-Z_%.]+]] = trunc i32 [[REG1842]] to i8
@ -2775,7 +2789,9 @@ test_srl() {
// CHECK-NEXT: br i1 [[REG1862]], label %[[REG1863:[0-9a-zA-Z_%.]+]], label %[[REG1864:[0-9a-zA-Z_%.]+]] // CHECK-NEXT: br i1 [[REG1862]], label %[[REG1863:[0-9a-zA-Z_%.]+]], label %[[REG1864:[0-9a-zA-Z_%.]+]]
// CHECK: [[REG1863]]: // CHECK: [[REG1863]]:
// CHECK-NEXT: br i1 false, label %[[REG1865:[0-9a-zA-Z_%.]+]], label %[[REG1866:[0-9a-zA-Z_%.]+]] // CHECK-NEXT: load
// CHECK-NEXT: call i1 @llvm.is.constant
// CHECK-NEXT: br i1 %[[REG1865a:[0-9a-zA-Z_%.]+]], label %[[REG1865:[0-9a-zA-Z_%.]+]], label %[[REG1866:[0-9a-zA-Z_%.]+]]
// CHECK: [[REG1865]]: // CHECK: [[REG1865]]:
// CHECK-NEXT: [[REG1867:[0-9a-zA-Z_%.]+]] = load i32, i32* [[REG1859]], align 4 // CHECK-NEXT: [[REG1867:[0-9a-zA-Z_%.]+]] = load i32, i32* [[REG1859]], align 4
@ -2826,7 +2842,9 @@ test_srl() {
// CHECK-NEXT: br i1 [[REG1893]], label %[[REG1894:[0-9a-zA-Z_%.]+]], label %[[REG1895:[0-9a-zA-Z_%.]+]] // CHECK-NEXT: br i1 [[REG1893]], label %[[REG1894:[0-9a-zA-Z_%.]+]], label %[[REG1895:[0-9a-zA-Z_%.]+]]
// CHECK: [[REG1894]]: // CHECK: [[REG1894]]:
// CHECK-NEXT: br i1 false, label %[[REG1896:[0-9a-zA-Z_%.]+]], label %[[REG1897:[0-9a-zA-Z_%.]+]] // CHECK-NEXT: load
// CHECK-NEXT: call i1 @llvm.is.constant
// CHECK-NEXT: br i1 %[[REG1896a:[0-9a-zA-Z_%.]+]], label %[[REG1896:[0-9a-zA-Z_%.]+]], label %[[REG1897:[0-9a-zA-Z_%.]+]]
// CHECK: [[REG1896]]: // CHECK: [[REG1896]]:
// CHECK-NEXT: [[REG1898:[0-9a-zA-Z_%.]+]] = load i32, i32* [[REG1890]], align 4 // CHECK-NEXT: [[REG1898:[0-9a-zA-Z_%.]+]] = load i32, i32* [[REG1890]], align 4

View File

@ -108,7 +108,8 @@ test_alignr() {
// CHECK: store <2 x i64> [[REG61]], <2 x i64>* [[REG65:[0-9a-zA-Z_%.]+]], align 16 // CHECK: store <2 x i64> [[REG61]], <2 x i64>* [[REG65:[0-9a-zA-Z_%.]+]], align 16
// CHECK-NEXT: store <2 x i64> [[REG62]], <2 x i64>* [[REG66:[0-9a-zA-Z_%.]+]], align 16 // CHECK-NEXT: store <2 x i64> [[REG62]], <2 x i64>* [[REG66:[0-9a-zA-Z_%.]+]], align 16
// CHECK-NEXT: store i32 [[REG63]], i32* [[REG64:[0-9a-zA-Z_%.]+]], align 4 // CHECK-NEXT: store i32 [[REG63]], i32* [[REG64:[0-9a-zA-Z_%.]+]], align 4
// CHECK-NEXT: br i1 false, label %[[REG67:[0-9a-zA-Z_%.]+]], label %[[REG68:[0-9a-zA-Z_%.]+]] // CHECK: %[[REG64b:[0-9a-zA-Z_%.]+]] = call i1 @llvm.is.constant.i32(i32 %0)
// CHECK-NEXT: br i1 %[[REG64b]], label %[[REG67:[0-9a-zA-Z_%.]+]], label %[[REG68:[0-9a-zA-Z_%.]+]]
// CHECK: [[REG67]]: // CHECK: [[REG67]]:
// CHECK-NEXT: [[REG69:[0-9a-zA-Z_%.]+]] = load i32, i32* [[REG64]], align 4 // CHECK-NEXT: [[REG69:[0-9a-zA-Z_%.]+]] = load i32, i32* [[REG64]], align 4