[llvm] [EarlyCSE] De-Duplicate callsites with differing attrs (PR #110929)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 3 09:54:01 PDT 2024
https://github.com/goldsteinn updated https://github.com/llvm/llvm-project/pull/110929
>From 00f8f7666cce3827a1bbd96dd3bfa85c7b584101 Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Wed, 2 Oct 2024 15:53:27 -0500
Subject: [PATCH 1/2] [EarlyCSE] Add tests for de-duplication of callsites with
differing attrs; NFC
---
.../EarlyCSE/replace-calls-def-attrs.ll | 263 ++++++++++++++++++
1 file changed, 263 insertions(+)
create mode 100644 llvm/test/Transforms/EarlyCSE/replace-calls-def-attrs.ll
diff --git a/llvm/test/Transforms/EarlyCSE/replace-calls-def-attrs.ll b/llvm/test/Transforms/EarlyCSE/replace-calls-def-attrs.ll
new file mode 100644
index 00000000000000..19560080744a1f
--- /dev/null
+++ b/llvm/test/Transforms/EarlyCSE/replace-calls-def-attrs.ll
@@ -0,0 +1,263 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes --check-globals all --version 5
+; RUN: opt -S -passes=early-cse < %s | FileCheck %s
+
+declare i8 @baz(i8, i8)
+declare i8 @baz_side_effects(i8, i8)
+declare i8 @buz(i8, i8)
+
+declare ptr @baz.ptr(i8, i8)
+declare i8 @buz.ptr(ptr, ptr)
+
+declare float @baz.fp(float, float)
+declare i8 @buz.fp(float, float)
+define i8 @same_parent_combine_diff_attrs(i8 %x, i8 %y) {
+; CHECK-LABEL: define i8 @same_parent_combine_diff_attrs(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[C2:%.*]] = call i8 @baz(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR0:[0-9]+]]
+; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 [[X]], i8 noundef [[Y]]) #[[ATTR0]]
+; CHECK-NEXT: [[R:%.*]] = call i8 @buz(i8 [[C1]], i8 [[C2]])
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %c1 = call i8 @baz(i8 noundef %x, i8 noundef %y) readnone
+ %c0 = call i8 @baz(i8 %x, i8 noundef %y) readnone
+ %r = call i8 @buz(i8 %c0, i8 %c1)
+ ret i8 %r
+
+}
+
+define i8 @same_parent_combine_diff_attrs_needs_intersect(i8 %x, i8 %y) {
+; CHECK-LABEL: define i8 @same_parent_combine_diff_attrs_needs_intersect(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[C1:%.*]] = call nonnull ptr @baz.ptr(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR0]]
+; CHECK-NEXT: [[C0:%.*]] = call ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR0]]
+; CHECK-NEXT: [[R:%.*]] = call i8 @buz.ptr(ptr [[C0]], ptr [[C1]])
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %c1 = call nonnull ptr @baz.ptr(i8 noundef %x, i8 noundef %y) readnone
+ %c0 = call ptr @baz.ptr(i8 %x, i8 noundef %y) readnone
+ %r = call i8 @buz.ptr(ptr %c0, ptr %c1)
+ ret i8 %r
+
+}
+
+define i8 @same_parent_combine_diff_attrs_fmf(float %x, float %y) {
+; CHECK-LABEL: define i8 @same_parent_combine_diff_attrs_fmf(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT: [[C1:%.*]] = call nnan nsz float @baz.fp(float noundef [[X]], float noundef [[Y]]) #[[ATTR1:[0-9]+]]
+; CHECK-NEXT: [[C0:%.*]] = call nnan float @baz.fp(float [[X]], float noundef [[Y]]) #[[ATTR1]]
+; CHECK-NEXT: [[R:%.*]] = call i8 @buz.fp(float [[C0]], float [[C1]])
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %c1 = call nnan nsz float @baz.fp(float noundef %x, float noundef %y) readonly
+ %c0 = call nnan float @baz.fp(float %x, float noundef %y) readonly
+ %r = call i8 @buz.fp(float %c0, float %c1)
+ ret i8 %r
+
+}
+
+define i8 @same_parent_combine_diff_attrs_fmf2(float %x, float %y) {
+; CHECK-LABEL: define i8 @same_parent_combine_diff_attrs_fmf2(
+; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
+; CHECK-NEXT: [[C1:%.*]] = call nnan float @baz.fp(float noundef [[X]], float noundef [[Y]]) #[[ATTR0]]
+; CHECK-NEXT: [[C0:%.*]] = call nnan nsz float @baz.fp(float [[X]], float noundef [[Y]]) #[[ATTR0]]
+; CHECK-NEXT: [[R:%.*]] = call i8 @buz.fp(float [[C0]], float [[C1]])
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %c1 = call nnan float @baz.fp(float noundef %x, float noundef %y) readnone
+ %c0 = call nnan nsz float @baz.fp(float %x, float noundef %y) readnone
+ %r = call i8 @buz.fp(float %c0, float %c1)
+ ret i8 %r
+
+}
+
+define i8 @same_parent_combine_diff_attrs_needs_intersect2(i8 %x, i8 %y) {
+; CHECK-LABEL: define i8 @same_parent_combine_diff_attrs_needs_intersect2(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[C1:%.*]] = call nonnull ptr @baz.ptr(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR1]]
+; CHECK-NEXT: [[C0:%.*]] = call ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR1]]
+; CHECK-NEXT: [[R:%.*]] = call i8 @buz.ptr(ptr [[C0]], ptr [[C1]])
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %c1 = call nonnull ptr @baz.ptr(i8 noundef %x, i8 noundef %y) readonly
+ %c0 = call ptr @baz.ptr(i8 %x, i8 noundef %y) readonly
+ %r = call i8 @buz.ptr(ptr %c0, ptr %c1)
+ ret i8 %r
+
+}
+
+define i8 @same_parent_combine_diff_attrs_really_needs_intersect(i8 %x, i8 %y) {
+; CHECK-LABEL: define i8 @same_parent_combine_diff_attrs_really_needs_intersect(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[C1:%.*]] = call nonnull ptr @baz.ptr(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR1]]
+; CHECK-NEXT: [[C0:%.*]] = call ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR1]]
+; CHECK-NEXT: [[R:%.*]] = call i8 @buz.ptr(ptr [[C0]], ptr noundef [[C1]])
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %c1 = call nonnull ptr @baz.ptr(i8 noundef %x, i8 noundef %y) readonly
+ %c0 = call ptr @baz.ptr(i8 %x, i8 noundef %y) readonly
+ %r = call i8 @buz.ptr(ptr %c0, ptr noundef %c1)
+ ret i8 %r
+
+}
+
+define i8 @same_parent_combine_diff_attrs_fail_side_effects(i8 %x, i8 %y) {
+; CHECK-LABEL: define i8 @same_parent_combine_diff_attrs_fail_side_effects(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 noundef [[X]], i8 noundef [[Y]])
+; CHECK-NEXT: [[C0:%.*]] = call i8 @baz(i8 [[X]], i8 noundef [[Y]])
+; CHECK-NEXT: [[R:%.*]] = call i8 @buz(i8 [[C0]], i8 [[C1]])
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %c1 = call i8 @baz(i8 noundef %x, i8 noundef %y)
+ %c0 = call i8 @baz(i8 %x, i8 noundef %y)
+ %r = call i8 @buz(i8 %c0, i8 %c1)
+ ret i8 %r
+
+}
+
+define i8 @same_parent_combine_diff_attrs_quasi_side_effects2(i8 %x, i8 %y) {
+; CHECK-LABEL: define i8 @same_parent_combine_diff_attrs_quasi_side_effects2(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR0]]
+; CHECK-NEXT: [[C0:%.*]] = call i8 @baz(i8 [[X]], i8 noundef [[Y]])
+; CHECK-NEXT: [[R:%.*]] = call i8 @buz(i8 [[C0]], i8 [[C1]])
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %c1 = call i8 @baz(i8 noundef %x, i8 noundef %y) readnone
+ %c0 = call i8 @baz(i8 %x, i8 noundef %y)
+ %r = call i8 @buz(i8 %c0, i8 %c1)
+ ret i8 %r
+
+}
+
+define i8 @diff_parent_combine_diff_attrs(i1 %c, i8 %x, i8 %y) {
+; CHECK-LABEL: define i8 @diff_parent_combine_diff_attrs(
+; CHECK-SAME: i1 [[C:%.*]], i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 [[X]], i8 noundef [[Y]]) #[[ATTR0]]
+; CHECK-NEXT: br i1 [[C]], label %[[T:.*]], label %[[F:.*]]
+; CHECK: [[T]]:
+; CHECK-NEXT: [[C0:%.*]] = call i8 @baz(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR1]]
+; CHECK-NEXT: [[R:%.*]] = call i8 @buz(i8 [[C0]], i8 [[C1]])
+; CHECK-NEXT: ret i8 [[R]]
+; CHECK: [[F]]:
+; CHECK-NEXT: [[R2:%.*]] = add i8 [[C1]], 4
+; CHECK-NEXT: ret i8 [[R2]]
+;
+ %c1 = call i8 @baz(i8 %x, i8 noundef %y) readnone
+ br i1 %c, label %T, label %F
+T:
+ %c0 = call i8 @baz(i8 noundef %x, i8 noundef %y) readonly
+ %r = call i8 @buz(i8 %c0, i8 %c1)
+ ret i8 %r
+F:
+ %r2 = add i8 %c1, 4
+ ret i8 %r2
+}
+
+define i8 @diff_parent_combine_diff_attrs_preserves_return_attrs(i1 %c, i8 %x, i8 %y) {
+; CHECK-LABEL: define i8 @diff_parent_combine_diff_attrs_preserves_return_attrs(
+; CHECK-SAME: i1 [[C:%.*]], i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[C1:%.*]] = call nonnull ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR1]]
+; CHECK-NEXT: br i1 [[C]], label %[[T:.*]], label %[[F:.*]]
+; CHECK: [[T]]:
+; CHECK-NEXT: [[C0:%.*]] = call nonnull ptr @baz.ptr(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR1]]
+; CHECK-NEXT: [[R:%.*]] = call i8 @buz.ptr(ptr [[C0]], ptr noundef [[C1]])
+; CHECK-NEXT: ret i8 [[R]]
+; CHECK: [[F]]:
+; CHECK-NEXT: ret i8 9
+;
+ %c1 = call nonnull ptr @baz.ptr(i8 %x, i8 noundef %y) readonly
+ br i1 %c, label %T, label %F
+T:
+ %c0 = call nonnull ptr @baz.ptr(i8 noundef %x, i8 noundef %y) readonly
+ %r = call i8 @buz.ptr(ptr %c0, ptr noundef %c1)
+ ret i8 %r
+F:
+ ret i8 9
+}
+
+define i8 @same_parent_combine_diff_attrs_todo(i8 %x, i8 %y) {
+; CHECK-LABEL: define i8 @same_parent_combine_diff_attrs_todo(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 [[X]], i8 noundef [[Y]]) #[[ATTR0]]
+; CHECK-NEXT: [[C0:%.*]] = call i8 @baz(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR2:[0-9]+]]
+; CHECK-NEXT: [[R:%.*]] = call i8 @buz(i8 [[C0]], i8 [[C1]])
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %c1 = call i8 @baz(i8 %x, i8 noundef %y) readnone
+ %c0 = call i8 @baz(i8 noundef %x, i8 noundef %y) readnone alwaysinline
+ %r = call i8 @buz(i8 %c0, i8 %c1)
+ ret i8 %r
+
+}
+
+define i8 @same_parent_combine_diff_attrs_fail(i8 %x, i8 %y) {
+; CHECK-LABEL: define i8 @same_parent_combine_diff_attrs_fail(
+; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 [[X]], i8 noundef [[Y]]) #[[ATTR0]]
+; CHECK-NEXT: [[C0:%.*]] = call i8 @baz(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR3:[0-9]+]]
+; CHECK-NEXT: [[R:%.*]] = call i8 @buz(i8 [[C0]], i8 [[C1]])
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %c1 = call i8 @baz(i8 %x, i8 noundef %y) readnone
+ %c0 = call i8 @baz(i8 noundef %x, i8 noundef %y) readnone strictfp
+ %r = call i8 @buz(i8 %c0, i8 %c1)
+ ret i8 %r
+
+}
+
+define i8 @diff_parent_combine_diff_attrs_todo(i1 %c, i8 %x, i8 %y) {
+; CHECK-LABEL: define i8 @diff_parent_combine_diff_attrs_todo(
+; CHECK-SAME: i1 [[C:%.*]], i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 [[X]], i8 noundef [[Y]]) #[[ATTR0]]
+; CHECK-NEXT: br i1 [[C]], label %[[T:.*]], label %[[F:.*]]
+; CHECK: [[T]]:
+; CHECK-NEXT: [[C0:%.*]] = call i8 @baz(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR4:[0-9]+]]
+; CHECK-NEXT: [[R:%.*]] = call i8 @buz(i8 [[C0]], i8 [[C1]])
+; CHECK-NEXT: ret i8 [[R]]
+; CHECK: [[F]]:
+; CHECK-NEXT: [[R2:%.*]] = add i8 [[C1]], 4
+; CHECK-NEXT: ret i8 [[R2]]
+;
+ %c1 = call i8 @baz(i8 %x, i8 noundef %y) readnone
+ br i1 %c, label %T, label %F
+T:
+ %c0 = call i8 @baz(i8 noundef %x, i8 noundef %y) readnone optnone noinline
+ %r = call i8 @buz(i8 %c0, i8 %c1)
+ ret i8 %r
+F:
+ %r2 = add i8 %c1, 4
+ ret i8 %r2
+}
+
+define i8 @diff_parent_combine_diff_attrs_fail(i1 %c, i8 %x, i8 %y) {
+; CHECK-LABEL: define i8 @diff_parent_combine_diff_attrs_fail(
+; CHECK-SAME: i1 [[C:%.*]], i8 [[X:%.*]], i8 [[Y:%.*]]) {
+; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 [[X]], i8 noundef [[Y]]) #[[ATTR0]]
+; CHECK-NEXT: br i1 [[C]], label %[[T:.*]], label %[[F:.*]]
+; CHECK: [[T]]:
+; CHECK-NEXT: [[C0:%.*]] = call i8 @baz(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR3]]
+; CHECK-NEXT: [[R:%.*]] = call i8 @buz(i8 [[C0]], i8 [[C1]])
+; CHECK-NEXT: ret i8 [[R]]
+; CHECK: [[F]]:
+; CHECK-NEXT: [[R2:%.*]] = add i8 [[C1]], 4
+; CHECK-NEXT: ret i8 [[R2]]
+;
+ %c1 = call i8 @baz(i8 %x, i8 noundef %y) readnone
+ br i1 %c, label %T, label %F
+T:
+ %c0 = call i8 @baz(i8 noundef %x, i8 noundef %y) readnone strictfp
+ %r = call i8 @buz(i8 %c0, i8 %c1)
+ ret i8 %r
+F:
+ %r2 = add i8 %c1, 4
+ ret i8 %r2
+}
+
+;.
+; CHECK: attributes #[[ATTR0]] = { memory(none) }
+; CHECK: attributes #[[ATTR1]] = { memory(read) }
+; CHECK: attributes #[[ATTR2]] = { alwaysinline memory(none) }
+; CHECK: attributes #[[ATTR3]] = { strictfp memory(none) }
+; CHECK: attributes #[[ATTR4]] = { noinline optnone memory(none) }
+;.
>From 8ff29eadc6bd4f46f511f4f77dba319870abe131 Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Wed, 2 Oct 2024 15:53:17 -0500
Subject: [PATCH 2/2] [EarlyCSE] De-Duplicate callsites with differing attrs
We only do this if the attributes of the two callsites are compatible
(intersectable) which is probably not in fact necessary.
---
llvm/lib/Transforms/Scalar/EarlyCSE.cpp | 22 +++++++++++--
.../EarlyCSE/replace-calls-def-attrs.ll | 33 ++++++++-----------
2 files changed, 33 insertions(+), 22 deletions(-)
diff --git a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
index cf11f5bc885a75..b8eab9bb18b69c 100644
--- a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
+++ b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
@@ -362,7 +362,7 @@ static bool isEqualImpl(SimpleValue LHS, SimpleValue RHS) {
if (LHSI->getOpcode() != RHSI->getOpcode())
return false;
- if (LHSI->isIdenticalToWhenDefined(RHSI)) {
+ if (LHSI->isIdenticalToWhenDefined(RHSI, /*IntersectAttrs=*/true)) {
// Convergent calls implicitly depend on the set of threads that is
// currently executing, so conservatively return false if they are in
// different basic blocks.
@@ -551,7 +551,7 @@ bool DenseMapInfo<CallValue>::isEqual(CallValue LHS, CallValue RHS) {
if (LHSI->isConvergent() && LHSI->getParent() != RHSI->getParent())
return false;
- return LHSI->isIdenticalTo(RHSI);
+ return LHSI->isIdenticalToWhenDefined(RHSI, /*IntersectAttrs=*/true);
}
//===----------------------------------------------------------------------===//
@@ -1307,6 +1307,23 @@ static void combineIRFlags(Instruction &From, Value *To) {
(I->hasPoisonGeneratingFlags() && !programUndefinedIfPoison(I)))
I->andIRFlags(&From);
}
+ if (isa<CallBase>(&From) && isa<CallBase>(To)) {
+ // NB: Intersection of attrs between InVal.first and Inst is overly
+ // conservative. Since we only CSE readonly functions that have the same
+ // memory state, we can preserve (or possibly in some cases combine)
+ // more attributes. Likewise this implies when checking equality of
+ // callsite for CSEing, we can probably ignore more attributes.
+ // Generally poison generating attributes need to be handled with more
+ // care as they can create *new* UB if preserved/combined and violated.
+ // Attributes that imply immediate UB on the otherhand would have been
+ // violated either way.
+ bool Success =
+ cast<CallBase>(To)->tryIntersectAttributes(cast<CallBase>(&From));
+ assert(Success && "Failed to intersect attributes in callsites that "
+ "passed identical check");
+ // For NDEBUG Compile.
+ (void)Success;
+ }
}
bool EarlyCSE::overridingStores(const ParseMemoryInst &Earlier,
@@ -1632,6 +1649,7 @@ bool EarlyCSE::processNode(DomTreeNode *Node) {
LLVM_DEBUG(dbgs() << "Skipping due to debug counter\n");
continue;
}
+ combineIRFlags(Inst, InVal.first);
if (!Inst.use_empty())
Inst.replaceAllUsesWith(InVal.first);
salvageKnowledge(&Inst, &AC);
diff --git a/llvm/test/Transforms/EarlyCSE/replace-calls-def-attrs.ll b/llvm/test/Transforms/EarlyCSE/replace-calls-def-attrs.ll
index 19560080744a1f..2adaf1c7b67a04 100644
--- a/llvm/test/Transforms/EarlyCSE/replace-calls-def-attrs.ll
+++ b/llvm/test/Transforms/EarlyCSE/replace-calls-def-attrs.ll
@@ -13,9 +13,8 @@ declare i8 @buz.fp(float, float)
define i8 @same_parent_combine_diff_attrs(i8 %x, i8 %y) {
; CHECK-LABEL: define i8 @same_parent_combine_diff_attrs(
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
-; CHECK-NEXT: [[C2:%.*]] = call i8 @baz(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR0:[0-9]+]]
-; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 [[X]], i8 noundef [[Y]]) #[[ATTR0]]
-; CHECK-NEXT: [[R:%.*]] = call i8 @buz(i8 [[C1]], i8 [[C2]])
+; CHECK-NEXT: [[C1:%.*]] = call i8 @baz(i8 [[X]], i8 noundef [[Y]]) #[[ATTR0:[0-9]+]]
+; CHECK-NEXT: [[R:%.*]] = call i8 @buz(i8 [[C1]], i8 [[C1]])
; CHECK-NEXT: ret i8 [[R]]
;
%c1 = call i8 @baz(i8 noundef %x, i8 noundef %y) readnone
@@ -28,9 +27,8 @@ define i8 @same_parent_combine_diff_attrs(i8 %x, i8 %y) {
define i8 @same_parent_combine_diff_attrs_needs_intersect(i8 %x, i8 %y) {
; CHECK-LABEL: define i8 @same_parent_combine_diff_attrs_needs_intersect(
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
-; CHECK-NEXT: [[C1:%.*]] = call nonnull ptr @baz.ptr(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR0]]
-; CHECK-NEXT: [[C0:%.*]] = call ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR0]]
-; CHECK-NEXT: [[R:%.*]] = call i8 @buz.ptr(ptr [[C0]], ptr [[C1]])
+; CHECK-NEXT: [[C1:%.*]] = call ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR0]]
+; CHECK-NEXT: [[R:%.*]] = call i8 @buz.ptr(ptr [[C1]], ptr [[C1]])
; CHECK-NEXT: ret i8 [[R]]
;
%c1 = call nonnull ptr @baz.ptr(i8 noundef %x, i8 noundef %y) readnone
@@ -43,9 +41,8 @@ define i8 @same_parent_combine_diff_attrs_needs_intersect(i8 %x, i8 %y) {
define i8 @same_parent_combine_diff_attrs_fmf(float %x, float %y) {
; CHECK-LABEL: define i8 @same_parent_combine_diff_attrs_fmf(
; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
-; CHECK-NEXT: [[C1:%.*]] = call nnan nsz float @baz.fp(float noundef [[X]], float noundef [[Y]]) #[[ATTR1:[0-9]+]]
-; CHECK-NEXT: [[C0:%.*]] = call nnan float @baz.fp(float [[X]], float noundef [[Y]]) #[[ATTR1]]
-; CHECK-NEXT: [[R:%.*]] = call i8 @buz.fp(float [[C0]], float [[C1]])
+; CHECK-NEXT: [[C1:%.*]] = call nnan float @baz.fp(float [[X]], float noundef [[Y]]) #[[ATTR1:[0-9]+]]
+; CHECK-NEXT: [[R:%.*]] = call i8 @buz.fp(float [[C1]], float [[C1]])
; CHECK-NEXT: ret i8 [[R]]
;
%c1 = call nnan nsz float @baz.fp(float noundef %x, float noundef %y) readonly
@@ -58,9 +55,8 @@ define i8 @same_parent_combine_diff_attrs_fmf(float %x, float %y) {
define i8 @same_parent_combine_diff_attrs_fmf2(float %x, float %y) {
; CHECK-LABEL: define i8 @same_parent_combine_diff_attrs_fmf2(
; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
-; CHECK-NEXT: [[C1:%.*]] = call nnan float @baz.fp(float noundef [[X]], float noundef [[Y]]) #[[ATTR0]]
-; CHECK-NEXT: [[C0:%.*]] = call nnan nsz float @baz.fp(float [[X]], float noundef [[Y]]) #[[ATTR0]]
-; CHECK-NEXT: [[R:%.*]] = call i8 @buz.fp(float [[C0]], float [[C1]])
+; CHECK-NEXT: [[C1:%.*]] = call nnan float @baz.fp(float [[X]], float noundef [[Y]]) #[[ATTR0]]
+; CHECK-NEXT: [[R:%.*]] = call i8 @buz.fp(float [[C1]], float [[C1]])
; CHECK-NEXT: ret i8 [[R]]
;
%c1 = call nnan float @baz.fp(float noundef %x, float noundef %y) readnone
@@ -73,9 +69,8 @@ define i8 @same_parent_combine_diff_attrs_fmf2(float %x, float %y) {
define i8 @same_parent_combine_diff_attrs_needs_intersect2(i8 %x, i8 %y) {
; CHECK-LABEL: define i8 @same_parent_combine_diff_attrs_needs_intersect2(
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
-; CHECK-NEXT: [[C1:%.*]] = call nonnull ptr @baz.ptr(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR1]]
-; CHECK-NEXT: [[C0:%.*]] = call ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR1]]
-; CHECK-NEXT: [[R:%.*]] = call i8 @buz.ptr(ptr [[C0]], ptr [[C1]])
+; CHECK-NEXT: [[C1:%.*]] = call ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR1]]
+; CHECK-NEXT: [[R:%.*]] = call i8 @buz.ptr(ptr [[C1]], ptr [[C1]])
; CHECK-NEXT: ret i8 [[R]]
;
%c1 = call nonnull ptr @baz.ptr(i8 noundef %x, i8 noundef %y) readonly
@@ -88,9 +83,8 @@ define i8 @same_parent_combine_diff_attrs_needs_intersect2(i8 %x, i8 %y) {
define i8 @same_parent_combine_diff_attrs_really_needs_intersect(i8 %x, i8 %y) {
; CHECK-LABEL: define i8 @same_parent_combine_diff_attrs_really_needs_intersect(
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
-; CHECK-NEXT: [[C1:%.*]] = call nonnull ptr @baz.ptr(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR1]]
-; CHECK-NEXT: [[C0:%.*]] = call ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR1]]
-; CHECK-NEXT: [[R:%.*]] = call i8 @buz.ptr(ptr [[C0]], ptr noundef [[C1]])
+; CHECK-NEXT: [[C1:%.*]] = call ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR1]]
+; CHECK-NEXT: [[R:%.*]] = call i8 @buz.ptr(ptr [[C1]], ptr noundef [[C1]])
; CHECK-NEXT: ret i8 [[R]]
;
%c1 = call nonnull ptr @baz.ptr(i8 noundef %x, i8 noundef %y) readonly
@@ -160,8 +154,7 @@ define i8 @diff_parent_combine_diff_attrs_preserves_return_attrs(i1 %c, i8 %x, i
; CHECK-NEXT: [[C1:%.*]] = call nonnull ptr @baz.ptr(i8 [[X]], i8 noundef [[Y]]) #[[ATTR1]]
; CHECK-NEXT: br i1 [[C]], label %[[T:.*]], label %[[F:.*]]
; CHECK: [[T]]:
-; CHECK-NEXT: [[C0:%.*]] = call nonnull ptr @baz.ptr(i8 noundef [[X]], i8 noundef [[Y]]) #[[ATTR1]]
-; CHECK-NEXT: [[R:%.*]] = call i8 @buz.ptr(ptr [[C0]], ptr noundef [[C1]])
+; CHECK-NEXT: [[R:%.*]] = call i8 @buz.ptr(ptr [[C1]], ptr noundef [[C1]])
; CHECK-NEXT: ret i8 [[R]]
; CHECK: [[F]]:
; CHECK-NEXT: ret i8 9
More information about the llvm-commits
mailing list