diff --git a/llvm/lib/Transforms/Utils/Evaluator.cpp b/llvm/lib/Transforms/Utils/Evaluator.cpp index 2af447aadce22..d1db2ee29f3a2 100644 --- a/llvm/lib/Transforms/Utils/Evaluator.cpp +++ b/llvm/lib/Transforms/Utils/Evaluator.cpp @@ -77,7 +77,9 @@ isSimpleEnoughValueToCommitHelper(Constant *C, // We don't know exactly what relocations are allowed in constant expressions, // so we allow &global+constantoffset, which is safe and uniformly supported // across targets. - ConstantExpr *CE = cast(C); + ConstantExpr *CE = dyn_cast(C); + if (!CE) + return false; switch (CE->getOpcode()) { case Instruction::BitCast: // Bitcast is fine if the casted value is fine. diff --git a/llvm/test/Transforms/GlobalOpt/global-constructor-complex-constants.ll b/llvm/test/Transforms/GlobalOpt/global-constructor-complex-constants.ll new file mode 100644 index 0000000000000..6d9bdc41a0041 --- /dev/null +++ b/llvm/test/Transforms/GlobalOpt/global-constructor-complex-constants.ll @@ -0,0 +1,64 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 5 +; RUN: opt -p globalopt -S %s | FileCheck %s + +@llvm.global_ctors = appending global [3 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @ctor, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @ctor_nocfi, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @ctor_dso_local_equivalent, ptr null }] + +@foo = internal global ptr null + +declare void @user(ptr) + +;. +; CHECK: @llvm.global_ctors = appending global [3 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @ctor, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @ctor_nocfi, ptr null }, { i32, ptr, ptr } { i32 65535, ptr @ctor_dso_local_equivalent, ptr null }] +; CHECK: @foo = internal global ptr null +;. +define void @ctor() { +; CHECK-LABEL: define void @ctor() { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[DST:%.*]] = alloca ptr, align 8 +; CHECK-NEXT: store ptr ptrauth (ptr @foo, i32 0), ptr [[DST]], align 8 +; CHECK-NEXT: call void @user(ptr [[DST]]) +; CHECK-NEXT: ret void +; +entry: + %dst = alloca ptr, align 8 + store ptr ptrauth (ptr @foo, i32 0), ptr %dst, align 8 + call void @user(ptr %dst) + ret void +} + +define void @ctor_nocfi() { +; CHECK-LABEL: define void @ctor_nocfi() { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[DST:%.*]] = alloca ptr, align 8 +; CHECK-NEXT: store ptr no_cfi @foo, ptr [[DST]], align 8 +; CHECK-NEXT: call void @user(ptr [[DST]]) +; CHECK-NEXT: ret void +; +entry: + %dst = alloca ptr, align 8 + store ptr no_cfi @foo, ptr %dst, align 8 + call void @user(ptr %dst) + ret void +} + +define void @fn() { +; CHECK-LABEL: define void @fn() { +; CHECK-NEXT: ret void +; + ret void +} + +define void @ctor_dso_local_equivalent() { +; CHECK-LABEL: define void @ctor_dso_local_equivalent() { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[DST:%.*]] = alloca ptr, align 8 +; CHECK-NEXT: store ptr dso_local_equivalent @fn, ptr [[DST]], align 8 +; CHECK-NEXT: call void @user(ptr [[DST]]) +; CHECK-NEXT: ret void +; +entry: + %dst = alloca ptr, align 8 + store ptr dso_local_equivalent @fn, ptr %dst, align 8 + call void @user(ptr %dst) + ret void +}