From 22c96a966b111ed433ddab238e9f83109c0a824a Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Thu, 27 Jun 2019 11:44:45 +0000 Subject: [PATCH] IR: compare type attributes deeply when looking into functions. FunctionComparator attempts to produce a stable comparison of two Function instances by looking at all available properties. Since ByVal attributes now contain a Type pointer, they are not trivially ordered and FunctionComparator should use its own Type comparison logic to sort them. llvm-svn: 364523 --- .../Transforms/Utils/FunctionComparator.cpp | 13 +++++++ .../Transforms/MergeFunc/byval-attr-type.ll | 37 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 llvm/test/Transforms/MergeFunc/byval-attr-type.ll diff --git a/llvm/lib/Transforms/Utils/FunctionComparator.cpp b/llvm/lib/Transforms/Utils/FunctionComparator.cpp index 5c400cec5734..a9b28754c8e9 100644 --- a/llvm/lib/Transforms/Utils/FunctionComparator.cpp +++ b/llvm/lib/Transforms/Utils/FunctionComparator.cpp @@ -113,6 +113,19 @@ int FunctionComparator::cmpAttrs(const AttributeList L, for (; LI != LE && RI != RE; ++LI, ++RI) { Attribute LA = *LI; Attribute RA = *RI; + if (LA.isTypeAttribute() && RA.isTypeAttribute()) { + if (LA.getKindAsEnum() != RA.getKindAsEnum()) + return cmpNumbers(LA.getKindAsEnum(), RA.getKindAsEnum()); + + Type *TyL = LA.getValueAsType(); + Type *TyR = RA.getValueAsType(); + if (TyL && TyR) + return cmpTypes(TyL, TyR); + + // Two pointers, at least one null, so the comparison result is + // independent of the value of a real pointer. + return cmpNumbers((uint64_t)TyL, (uint64_t)TyR); + } if (LA < RA) return -1; if (RA < LA) diff --git a/llvm/test/Transforms/MergeFunc/byval-attr-type.ll b/llvm/test/Transforms/MergeFunc/byval-attr-type.ll new file mode 100644 index 000000000000..b6592136147a --- /dev/null +++ b/llvm/test/Transforms/MergeFunc/byval-attr-type.ll @@ -0,0 +1,37 @@ +; RUN: opt -S -mergefunc %s | FileCheck %s + +@i = global i32 0 +@f = global float 0.0 + +define internal void @foo() { +; CHECK: define internal void @foo() + call void @callee_i32(i32* byval(i32) @i) + ret void +} + +define internal void @bar() { +; CHECK: define internal void @bar() + call void @callee_float(float* byval(float) @f) + ret void +} + +define internal void @baz() { +; CHECK-NOT: define{{.*}}@bar + call void @callee_float(float* byval(float) @f) + ret void +} + +define void @user() { +; CHECK-LABEL: define void @user +; CHECK: call void @foo() +; CHECK: call void @bar() +; CHECK: call void @bar() + + call void @foo() + call void @bar() + call void @baz() + ret void +} + +declare void @callee_i32(i32* byval(i32)) +declare void @callee_float(float* byval(float))