[llvm] 21b03bf - [llvm] Handle dso_local_equivalent in FunctionComparator

Leonard Chan via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 22 11:46:18 PDT 2022


Author: Leonard Chan
Date: 2022-09-22T18:42:31Z
New Revision: 21b03bf9706138b8b8f0b0ab06df763acad17704

URL: https://github.com/llvm/llvm-project/commit/21b03bf9706138b8b8f0b0ab06df763acad17704
DIFF: https://github.com/llvm/llvm-project/commit/21b03bf9706138b8b8f0b0ab06df763acad17704.diff

LOG: [llvm] Handle dso_local_equivalent in FunctionComparator

This addresses https://github.com/llvm/llvm-project/issues/51066.

Prior to this, dso_local_equivalent would lead to an llvm_unreachable in
a switch in the FunctionComparator. This adds a conservative case in
that switch that just compares the underlying functions.

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

Added: 
    llvm/test/Transforms/MergeFunc/dso_local_equivalent_merged.ll
    llvm/test/Transforms/MergeFunc/dso_local_equivalent_unmerged.ll

Modified: 
    llvm/lib/Transforms/Utils/FunctionComparator.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Utils/FunctionComparator.cpp b/llvm/lib/Transforms/Utils/FunctionComparator.cpp
index a548c4e241a6e..b38e9c5731814 100644
--- a/llvm/lib/Transforms/Utils/FunctionComparator.cpp
+++ b/llvm/lib/Transforms/Utils/FunctionComparator.cpp
@@ -402,6 +402,15 @@ int FunctionComparator::cmpConstants(const Constant *L,
       return cmpValues(LBA->getBasicBlock(), RBA->getBasicBlock());
     }
   }
+  case Value::DSOLocalEquivalentVal: {
+    // dso_local_equivalent is functionally equivalent to whatever it points to.
+    // This means the behavior of the IR should be the exact same as if the
+    // function was referenced directly rather than through a
+    // dso_local_equivalent.
+    const auto *LEquiv = cast<DSOLocalEquivalent>(L);
+    const auto *REquiv = cast<DSOLocalEquivalent>(R);
+    return cmpGlobalValues(LEquiv->getGlobalValue(), REquiv->getGlobalValue());
+  }
   default: // Unknown constant, abort.
     LLVM_DEBUG(dbgs() << "Looking at valueID " << L->getValueID() << "\n");
     llvm_unreachable("Constant ValueID not recognized.");

diff  --git a/llvm/test/Transforms/MergeFunc/dso_local_equivalent_merged.ll b/llvm/test/Transforms/MergeFunc/dso_local_equivalent_merged.ll
new file mode 100644
index 0000000000000..9b1692ffd535b
--- /dev/null
+++ b/llvm/test/Transforms/MergeFunc/dso_local_equivalent_merged.ll
@@ -0,0 +1,29 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+;; Check the cases involving dso_local_equivalent where we do expect functions to be merged.
+; RUN: opt -S -mergefunc < %s | FileCheck %s
+
+; CHECK-NOT: @b
+
+ at x = constant { i32 ()*, i32 ()* } { i32 ()* @a, i32 ()* @b }
+; CHECK: { i32 ()* @a, i32 ()* @a }
+
+define i32 @func() {
+; CHECK-LABEL: @func(
+; CHECK-NEXT:    ret i32 0
+;
+  ret i32 0
+}
+
+define internal i32 @a() unnamed_addr {
+; CHECK-LABEL: @a(
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 dso_local_equivalent @func()
+; CHECK-NEXT:    ret i32 [[TMP1]]
+;
+  %1 = call i32 dso_local_equivalent @func()
+  ret i32 %1
+}
+
+define internal i32 @b() unnamed_addr {
+  %1 = call i32 dso_local_equivalent @func()
+  ret i32 %1
+}

diff  --git a/llvm/test/Transforms/MergeFunc/dso_local_equivalent_unmerged.ll b/llvm/test/Transforms/MergeFunc/dso_local_equivalent_unmerged.ll
new file mode 100644
index 0000000000000..3657f993b1332
--- /dev/null
+++ b/llvm/test/Transforms/MergeFunc/dso_local_equivalent_unmerged.ll
@@ -0,0 +1,69 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+;; Check the cases involving dso_local_equivalent where we do not expect functions to be merged.
+; RUN: opt -S -mergefunc < %s | FileCheck %s
+
+ at x = constant { i32 ()*, i32 ()* } { i32 ()* @a, i32 ()* @b }
+; CHECK: { i32 ()* @a, i32 ()* @b }
+
+ at x2 = constant { i32 ()*, i32 ()* } { i32 ()* @c, i32 ()* @d }
+; CHECK: { i32 ()* @c, i32 ()* @d }
+
+;; func1 and func2 are 
diff erent functions.
+declare i32 @func1()
+define i32 @func2() {
+; CHECK-LABEL: @func2(
+; CHECK-NEXT:    ret i32 0
+;
+  ret i32 0
+}
+
+define internal i32 @a() unnamed_addr {
+; CHECK-LABEL: @a(
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 dso_local_equivalent @func1()
+; CHECK-NEXT:    ret i32 [[TMP1]]
+;
+  %1 = call i32 dso_local_equivalent @func1()
+  ret i32 %1
+}
+
+define internal i32 @b() unnamed_addr {
+; CHECK-LABEL: @b(
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 dso_local_equivalent @func2()
+; CHECK-NEXT:    ret i32 [[TMP1]]
+;
+  %1 = call i32 dso_local_equivalent @func2()
+  ret i32 %1
+}
+
+;; func3 and func4 have the same body and signature but do not have merged
+;; callers because they are 
diff erent functions.
+define i32 @func3() {
+; CHECK-LABEL: @func3(
+; CHECK-NEXT:    ret i32 0
+;
+  ret i32 0
+}
+define i32 @func4() {
+; CHECK-LABEL: @func4(
+; CHECK-NEXT:    ret i32 0
+;
+  ret i32 0
+}
+
+define internal i32 @c() unnamed_addr {
+; CHECK-LABEL: @c(
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 dso_local_equivalent @func3()
+; CHECK-NEXT:    ret i32 [[TMP1]]
+;
+  %1 = call i32 dso_local_equivalent @func3()
+  ret i32 %1
+}
+
+define internal i32 @d() unnamed_addr {
+; CHECK-LABEL: @d(
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 dso_local_equivalent @func4()
+; CHECK-NEXT:    ret i32 [[TMP1]]
+;
+  %1 = call i32 dso_local_equivalent @func4()
+  ret i32 %1
+}


        


More information about the llvm-commits mailing list