[LLVM][ConstantFold] Undefined values are not constant (#130713)

llvm.is.constant (and therefore Clang's __builtin_constant_p()) need to
report undefined values as non-constant or future DCE choices end up
making no sense. This was encountered while building the Linux kernel
which uses __builtin_constant_p() while trying to evaluate if it is safe
to use a compile-time constant resolution for string lengths or if it
must kick over to a full runtime call to strlen(). Obviously an
undefined variable cannot be known at compile-time, so
__builtin_constant_p() needs to return false. This change will also mean
that Clang will match GCC's behavior under the same conditions.

Fixes #130649
This commit is contained in:
Kees Cook 2025-03-12 09:50:50 -07:00 committed by GitHub
parent dd181af950
commit ea2e66aa8b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 20 additions and 0 deletions

View File

@ -841,6 +841,8 @@ Constant *Constant::mergeUndefsWith(Constant *C, Constant *Other) {
}
bool Constant::isManifestConstant() const {
if (isa<UndefValue>(this))
return false;
if (isa<ConstantData>(this))
return true;
if (isa<ConstantAggregate>(this) || isa<ConstantExpr>(this)) {

View File

@ -120,3 +120,21 @@ define i1 @global_array() {
%1 = call i1 @llvm.is.constant.i64(i64 ptrtoint (ptr @real_mode_blob_end to i64))
ret i1 %1
}
;; Ensure that is.constant of undef gets lowered reasonably to "false" in
;; optimized codegen: specifically that the "true" branch is eliminated.
;; CHECK-NOT: tail call i32 @subfun_1()
;; CHECK: tail call i32 @subfun_2()
;; CHECK-NOT: tail call i32 @subfun_1()
define i32 @test_undef_branch() nounwind {
%v = call i1 @llvm.is.constant.i32(i32 undef)
br i1 %v, label %True, label %False
True:
%call1 = tail call i32 @subfun_1()
ret i32 %call1
False:
%call2 = tail call i32 @subfun_2()
ret i32 %call2
}