diff --git a/llvm/lib/Transforms/Utils/FunctionComparator.cpp b/llvm/lib/Transforms/Utils/FunctionComparator.cpp --- a/llvm/lib/Transforms/Utils/FunctionComparator.cpp +++ b/llvm/lib/Transforms/Utils/FunctionComparator.cpp @@ -30,6 +30,7 @@ #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" @@ -616,6 +617,20 @@ if (int Res = cmpNumbers(CI->getTailCallKind(), cast(R)->getTailCallKind())) return Res; + + // Comparison for the metadata argument of llvm.type.test for CFI checks + if (CBL->getCalledFunction()->getIntrinsicID() == + llvm::Intrinsic::type_test) { + auto *MDL = + dyn_cast(CBL->getArgOperand(1))->getMetadata(); + auto *MDR = + dyn_cast(CBR->getArgOperand(1))->getMetadata(); + + if (MDL != MDR) { + return -1; + } + } + return cmpRangeMetadata(L->getMetadata(LLVMContext::MD_range), R->getMetadata(LLVMContext::MD_range)); } diff --git a/llvm/test/Transforms/MergeFunc/cfi-function-merging.ll b/llvm/test/Transforms/MergeFunc/cfi-function-merging.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/MergeFunc/cfi-function-merging.ll @@ -0,0 +1,41 @@ +;; Check the cases involving internal CFI instrumented functions where we do not expect functions to be merged. +; RUN: opt -S -passes=mergefunc < %s | FileCheck %s + + +target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" +target triple = "aarch64-none-linux-android28" + +; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn +declare i1 @llvm.type.test(ptr, metadata) #6 + +define internal void @A__on_zero_sharedEv(ptr noundef nonnull align 8 dereferenceable(32) %this) unnamed_addr #3 align 2 { +; CHECK-LABEL: @A__on_zero_sharedEv +entry: + %this.addr = alloca ptr, align 8 + store ptr %this, ptr %this.addr, align 8 + %this1 = load ptr, ptr %this.addr, align 8 + %vtable = load ptr, ptr %this1, align 8 + %0 = call i1 @llvm.type.test(ptr %vtable, metadata !11), !nosanitize !47 + ret void +} + +; Function Attrs: mustprogress noinline nounwind optnone uwtable +define internal void @B__on_zero_sharedEv(ptr noundef nonnull align 8 dereferenceable(32) %this) unnamed_addr #3 align 2 { +; CHECK-LABEL: @B__on_zero_sharedEv +entry: + %this.addr = alloca ptr, align 8 + store ptr %this, ptr %this.addr, align 8 + %this1 = load ptr, ptr %this.addr, align 8 + %vtable = load ptr, ptr %this1, align 8 + %0 = call i1 @llvm.type.test(ptr %vtable, metadata !22), !nosanitize !47 + ret void +} + +attributes #3 = { mustprogress noinline nounwind optnone uwtable "frame-pointer"="non-leaf" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+fix-cortex-a53-835769,+neon,+outline-atomics,+v8a" } +attributes #6 = { nocallback nofree nosync nounwind readnone speculatable willreturn } + +!10 = !{i64 16, !11} +!11 = distinct !{} +!21 = !{i64 16, !22} +!22 = distinct !{} +!47 = !{}