[llvm] [InstCombine] Factorise Add and Min/Max using Distributivity (PR #101717)

Jorge Botto via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 3 12:32:18 PDT 2024


https://github.com/jf-botto updated https://github.com/llvm/llvm-project/pull/101717

>From 38bb1bc306ecd21dfda8574fc1546c1489a222e8 Mon Sep 17 00:00:00 2001
From: Jorge Botto <jorge.botto.16 at ucl.ac.uk>
Date: Sat, 3 Aug 2024 16:20:59 +0100
Subject: [PATCH 1/2] Precommit test

---
 .../InstCombine/intrinsic-distributive.ll     | 571 ++++++++++++++++++
 1 file changed, 571 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/intrinsic-distributive.ll

diff --git a/llvm/test/Transforms/InstCombine/intrinsic-distributive.ll b/llvm/test/Transforms/InstCombine/intrinsic-distributive.ll
new file mode 100644
index 0000000000000..5f40a7453c94c
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/intrinsic-distributive.ll
@@ -0,0 +1,571 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -S -passes=instcombine < %s 2>&1 | FileCheck %s
+
+
+define i8 @umax_of_add_nuw(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umax_of_add_nuw(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw i8 [[B]], [[A]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw i8 [[C]], [[A]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MAX]]
+;
+  %add1 = add nuw i8 %b, %a ; thwart complexity-based canonicalization
+  %add2 = add nuw i8 %c, %a ; thwart complexity-based canonicalization
+  %max = call i8 @llvm.umax.i8(i8 %add1, i8 %add2)
+  ret i8 %max
+}
+
+define i8 @umax_of_add_nuw_comm(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umax_of_add_nuw_comm(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw i8 [[A]], [[B]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw i8 [[A]], [[C]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MAX]]
+;
+  %add1 = add nuw i8 %a, %b ; thwart complexity-based canonicalization
+  %add2 = add nuw i8 %a, %c ; thwart complexity-based canonicalization
+  %max = call i8 @llvm.umax.i8(i8 %add1, i8 %add2)
+  ret i8 %max
+}
+
+define i8 @umax_of_add_nuw_nsw_lhs(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umax_of_add_nuw_nsw_lhs(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[B]], [[A]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw i8 [[C]], [[A]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MAX]]
+;
+  %add1 = add nuw nsw i8 %b, %a ; thwart complexity-based canonicalization
+  %add2 = add nuw i8 %c, %a ; thwart complexity-based canonicalization
+  %max = call i8 @llvm.umax.i8(i8 %add1, i8 %add2)
+  ret i8 %max
+}
+
+define i8 @umax_of_add_nuw_nsw_lhs_comm(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umax_of_add_nuw_nsw_lhs_comm(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[A]], [[B]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw i8 [[A]], [[C]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MAX]]
+;
+  %add1 = add nuw nsw i8 %a, %b ; thwart complexity-based canonicalization
+  %add2 = add nuw i8 %a, %c ; thwart complexity-based canonicalization
+  %max = call i8 @llvm.umax.i8(i8 %add1, i8 %add2)
+  ret i8 %max
+}
+
+define i8 @umax_of_add_nuw_nsw_rhs(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umax_of_add_nuw_nsw_rhs(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw i8 [[B]], [[A]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[C]], [[A]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MAX]]
+;
+  %add1 = add nuw i8 %b, %a ; thwart complexity-based canonicalization
+  %add2 = add nuw nsw i8 %c, %a ; thwart complexity-based canonicalization
+  %max = call i8 @llvm.umax.i8(i8 %add1, i8 %add2)
+  ret i8 %max
+}
+
+define i8 @umax_of_add_nuw_nsw_rhs_comm(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umax_of_add_nuw_nsw_rhs_comm(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw i8 [[A]], [[B]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[A]], [[C]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MAX]]
+;
+  %add1 = add nuw i8 %a, %b ; thwart complexity-based canonicalization
+  %add2 = add nuw nsw i8 %a, %c ; thwart complexity-based canonicalization
+  %max = call i8 @llvm.umax.i8(i8 %add1, i8 %add2)
+  ret i8 %max
+}
+
+define i8 @umax_of_add_nuw_nsw(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umax_of_add_nuw_nsw(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[B]], [[A]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[C]], [[A]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MAX]]
+;
+  %add1 = add nuw nsw i8 %b, %a ; thwart complexity-based canonicalization
+  %add2 = add nuw nsw i8 %c, %a ; thwart complexity-based canonicalization
+  %max = call i8 @llvm.umax.i8(i8 %add1, i8 %add2)
+  ret i8 %max
+}
+
+define i8 @umax_of_add_nuw_nsw_comm(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umax_of_add_nuw_nsw_comm(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[A]], [[B]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[A]], [[C]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MAX]]
+;
+  %add1 = add nuw nsw i8 %a, %b ; thwart complexity-based canonicalization
+  %add2 = add nuw nsw i8 %a, %c ; thwart complexity-based canonicalization
+  %max = call i8 @llvm.umax.i8(i8 %add1, i8 %add2)
+  ret i8 %max
+}
+
+; negative test
+define i8 @umax_of_add_nsw(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umax_of_add_nsw(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nsw i8 [[B]], [[A]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nsw i8 [[C]], [[A]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MAX]]
+;
+  %add1 = add nsw i8 %b, %a
+  %add2 = add nsw i8 %c, %a
+  %max = call i8 @llvm.umax.i8(i8 %add1, i8 %add2)
+  ret i8 %max
+}
+
+; negative test
+define i8 @umax_of_add(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umax_of_add(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add i8 [[B]], [[A]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add i8 [[C]], [[A]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MAX]]
+;
+  %add1 = add i8 %b, %a
+  %add2 = add i8 %c, %a
+  %max = call i8 @llvm.umax.i8(i8 %add1, i8 %add2)
+  ret i8 %max
+}
+
+define i8 @umin_of_add_nuw(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umin_of_add_nuw(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw i8 [[B]], [[A]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw i8 [[C]], [[A]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.umin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MIN]]
+;
+  %add1 = add nuw i8 %b, %a ; thwart complexity-based canonicalization
+  %add2 = add nuw i8 %c, %a ; thwart complexity-based canonicalization
+  %min = call i8 @llvm.umin.i8(i8 %add1, i8 %add2)
+  ret i8 %min
+}
+
+define i8 @umin_of_add_nuw_comm(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umin_of_add_nuw_comm(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw i8 [[A]], [[B]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw i8 [[A]], [[C]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.umin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MIN]]
+;
+  %add1 = add nuw i8 %a, %b ; thwart complexity-based canonicalization
+  %add2 = add nuw i8 %a, %c ; thwart complexity-based canonicalization
+  %min = call i8 @llvm.umin.i8(i8 %add1, i8 %add2)
+  ret i8 %min
+}
+
+define i8 @umin_of_add_nuw_nsw_lhs(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umin_of_add_nuw_nsw_lhs(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[B]], [[A]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw i8 [[C]], [[A]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.umin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MIN]]
+;
+  %add1 = add nuw nsw i8 %b, %a ; thwart complexity-based canonicalization
+  %add2 = add nuw i8 %c, %a ; thwart complexity-based canonicalization
+  %min = call i8 @llvm.umin.i8(i8 %add1, i8 %add2)
+  ret i8 %min
+}
+
+define i8 @umin_of_add_nuw_nsw_lhs_comm(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umin_of_add_nuw_nsw_lhs_comm(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[A]], [[B]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw i8 [[A]], [[C]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.umin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MIN]]
+;
+  %add1 = add nuw nsw i8 %a, %b ; thwart complexity-based canonicalization
+  %add2 = add nuw i8 %a, %c ; thwart complexity-based canonicalization
+  %min = call i8 @llvm.umin.i8(i8 %add1, i8 %add2)
+  ret i8 %min
+}
+
+define i8 @umin_of_add_nuw_nsw_rhs(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umin_of_add_nuw_nsw_rhs(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw i8 [[B]], [[A]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[C]], [[A]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.umin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MIN]]
+;
+  %add1 = add nuw i8 %b, %a ; thwart complexity-based canonicalization
+  %add2 = add nuw nsw i8 %c, %a ; thwart complexity-based canonicalization
+  %min = call i8 @llvm.umin.i8(i8 %add1, i8 %add2)
+  ret i8 %min
+}
+
+define i8 @umin_of_add_nuw_nsw_rhs_comm(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umin_of_add_nuw_nsw_rhs_comm(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw i8 [[A]], [[B]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[A]], [[C]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.umin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MIN]]
+;
+  %add1 = add nuw i8 %a, %b ; thwart complexity-based canonicalization
+  %add2 = add nuw nsw i8 %a, %c ; thwart complexity-based canonicalization
+  %min = call i8 @llvm.umin.i8(i8 %add1, i8 %add2)
+  ret i8 %min
+}
+
+define i8 @umin_of_add_nuw_nsw(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umin_of_add_nuw_nsw(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[B]], [[A]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[C]], [[A]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.umin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MIN]]
+;
+  %add1 = add nuw nsw i8 %b, %a ; thwart complexity-based canonicalization
+  %add2 = add nuw nsw i8 %c, %a ; thwart complexity-based canonicalization
+  %min = call i8 @llvm.umin.i8(i8 %add1, i8 %add2)
+  ret i8 %min
+}
+
+define i8 @umin_of_add_nuw_nsw_comm(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umin_of_add_nuw_nsw_comm(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[A]], [[B]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[A]], [[C]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.umin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MIN]]
+;
+  %add1 = add nuw nsw i8 %a, %b ; thwart complexity-based canonicalization
+  %add2 = add nuw nsw i8 %a, %c ; thwart complexity-based canonicalization
+  %min = call i8 @llvm.umin.i8(i8 %add1, i8 %add2)
+  ret i8 %min
+}
+
+; negative test
+define i8 @umin_of_add_nsw(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umin_of_add_nsw(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nsw i8 [[B]], [[A]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nsw i8 [[C]], [[A]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.umin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MIN]]
+;
+  %add1 = add nsw i8 %b, %a
+  %add2 = add nsw i8 %c, %a
+  %min = call i8 @llvm.umin.i8(i8 %add1, i8 %add2)
+  ret i8 %min
+}
+
+; negative test
+define i8 @umin_of_add(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umin_of_add(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add i8 [[B]], [[A]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add i8 [[C]], [[A]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.umin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MIN]]
+;
+  %add1 = add i8 %b, %a
+  %add2 = add i8 %c, %a
+  %min = call i8 @llvm.umin.i8(i8 %add1, i8 %add2)
+  ret i8 %min
+}
+
+; negative test
+define i8 @smax_of_add_nuw(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smax_of_add_nuw(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw i8 [[B]], [[A]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw i8 [[C]], [[A]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MAX]]
+;
+  %add1 = add nuw i8 %b, %a
+  %add2 = add nuw i8 %c, %a
+  %max = call i8 @llvm.smax.i8(i8 %add1, i8 %add2)
+  ret i8 %max
+}
+
+define i8 @smax_of_add_nsw(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smax_of_add_nsw(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nsw i8 [[B]], [[A]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nsw i8 [[C]], [[A]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MAX]]
+;
+  %add1 = add nsw i8 %b, %a ; thwart complexity-based canonicalization
+  %add2 = add nsw i8 %c, %a ; thwart complexity-based canonicalization
+  %max = call i8 @llvm.smax.i8(i8 %add1, i8 %add2)
+  ret i8 %max
+}
+
+define i8 @smax_of_add_nsw_comm(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smax_of_add_nsw_comm(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nsw i8 [[A]], [[B]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nsw i8 [[A]], [[C]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MAX]]
+;
+  %add1 = add nsw i8 %a, %b ; thwart complexity-based canonicalization
+  %add2 = add nsw i8 %a, %c ; thwart complexity-based canonicalization
+  %max = call i8 @llvm.smax.i8(i8 %add1, i8 %add2)
+  ret i8 %max
+}
+
+define i8 @smax_of_add_nsw_nuw_lhs(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smax_of_add_nsw_nuw_lhs(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[B]], [[A]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nsw i8 [[C]], [[A]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MAX]]
+;
+  %add1 = add nsw nuw i8 %b, %a ; thwart complexity-based canonicalization
+  %add2 = add nsw i8 %c, %a ; thwart complexity-based canonicalization
+  %max = call i8 @llvm.smax.i8(i8 %add1, i8 %add2)
+  ret i8 %max
+}
+
+define i8 @smax_of_add_nsw_nuw_lhs_comm(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smax_of_add_nsw_nuw_lhs_comm(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[A]], [[B]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nsw i8 [[A]], [[C]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MAX]]
+;
+  %add1 = add nsw nuw i8 %a, %b ; thwart complexity-based canonicalization
+  %add2 = add nsw i8 %a, %c ; thwart complexity-based canonicalization
+  %max = call i8 @llvm.smax.i8(i8 %add1, i8 %add2)
+  ret i8 %max
+}
+
+define i8 @smax_of_add_nsw_nuw_rhs(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smax_of_add_nsw_nuw_rhs(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nsw i8 [[B]], [[A]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[C]], [[A]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MAX]]
+;
+  %add1 = add nsw i8 %b, %a ; thwart complexity-based canonicalization
+  %add2 = add nsw nuw i8 %c, %a ; thwart complexity-based canonicalization
+  %max = call i8 @llvm.smax.i8(i8 %add1, i8 %add2)
+  ret i8 %max
+}
+
+define i8 @smax_of_add_nsw_nuw_rhs_comm(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smax_of_add_nsw_nuw_rhs_comm(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nsw i8 [[A]], [[B]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[A]], [[C]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MAX]]
+;
+  %add1 = add nsw i8 %a, %b ; thwart complexity-based canonicalization
+  %add2 = add nsw nuw i8 %a, %c ; thwart complexity-based canonicalization
+  %max = call i8 @llvm.smax.i8(i8 %add1, i8 %add2)
+  ret i8 %max
+}
+
+define i8 @smax_of_add_nsw_nuw(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smax_of_add_nsw_nuw(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[B]], [[A]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[C]], [[A]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MAX]]
+;
+  %add1 = add nsw nuw i8 %b, %a ; thwart complexity-based canonicalization
+  %add2 = add nsw nuw i8 %c, %a ; thwart complexity-based canonicalization
+  %max = call i8 @llvm.smax.i8(i8 %add1, i8 %add2)
+  ret i8 %max
+}
+
+define i8 @smax_of_add_nsw_nuw_comm(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smax_of_add_nsw_nuw_comm(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[A]], [[B]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[A]], [[C]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MAX]]
+;
+  %add1 = add nsw nuw i8 %a, %b ; thwart complexity-based canonicalization
+  %add2 = add nsw nuw i8 %a, %c ; thwart complexity-based canonicalization
+  %max = call i8 @llvm.smax.i8(i8 %add1, i8 %add2)
+  ret i8 %max
+}
+
+; negative test
+define i8 @smax_of_add(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smax_of_add(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add i8 [[B]], [[A]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add i8 [[C]], [[A]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MAX]]
+;
+  %add1 = add i8 %b, %a
+  %add2 = add i8 %c, %a
+  %max = call i8 @llvm.smax.i8(i8 %add1, i8 %add2)
+  ret i8 %max
+}
+
+; negative test
+define i8 @smin_of_add_nuw(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smin_of_add_nuw(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw i8 [[B]], [[A]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw i8 [[C]], [[A]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.smin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MIN]]
+;
+  %add1 = add nuw i8 %b, %a
+  %add2 = add nuw i8 %c, %a
+  %min = call i8 @llvm.smin.i8(i8 %add1, i8 %add2)
+  ret i8 %min
+}
+
+define i8 @smin_of_add_nsw(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smin_of_add_nsw(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nsw i8 [[B]], [[A]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nsw i8 [[C]], [[A]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.smin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MIN]]
+;
+  %add1 = add nsw i8 %b, %a ; thwart complexity-based canonicalization
+  %add2 = add nsw i8 %c, %a ; thwart complexity-based canonicalization
+  %min = call i8 @llvm.smin.i8(i8 %add1, i8 %add2)
+  ret i8 %min
+}
+
+define i8 @smin_of_add_nsw_comm(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smin_of_add_nsw_comm(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nsw i8 [[A]], [[B]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nsw i8 [[A]], [[C]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.smin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MIN]]
+;
+  %add1 = add nsw i8 %a, %b ; thwart complexity-based canonicalization
+  %add2 = add nsw i8 %a, %c ; thwart complexity-based canonicalization
+  %min = call i8 @llvm.smin.i8(i8 %add1, i8 %add2)
+  ret i8 %min
+}
+
+define i8 @smin_of_add_nsw_nuw_lhs(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smin_of_add_nsw_nuw_lhs(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[B]], [[A]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nsw i8 [[C]], [[A]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.smin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MIN]]
+;
+  %add1 = add nsw nuw i8 %b, %a ; thwart complexity-based canonicalization
+  %add2 = add nsw i8 %c, %a ; thwart complexity-based canonicalization
+  %min = call i8 @llvm.smin.i8(i8 %add1, i8 %add2)
+  ret i8 %min
+}
+
+define i8 @smin_of_add_nsw_nuw_lhs_comm(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smin_of_add_nsw_nuw_lhs_comm(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[A]], [[B]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nsw i8 [[A]], [[C]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.smin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MIN]]
+;
+  %add1 = add nsw nuw i8 %a, %b ; thwart complexity-based canonicalization
+  %add2 = add nsw i8 %a, %c ; thwart complexity-based canonicalization
+  %min = call i8 @llvm.smin.i8(i8 %add1, i8 %add2)
+  ret i8 %min
+}
+
+define i8 @smin_of_add_nsw_nuw_rhs(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smin_of_add_nsw_nuw_rhs(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nsw i8 [[B]], [[A]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[C]], [[A]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.smin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MIN]]
+;
+  %add1 = add nsw i8 %b, %a ; thwart complexity-based canonicalization
+  %add2 = add nsw nuw i8 %c, %a ; thwart complexity-based canonicalization
+  %min = call i8 @llvm.smin.i8(i8 %add1, i8 %add2)
+  ret i8 %min
+}
+
+define i8 @smin_of_add_nsw_nuw_rhs_comm(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smin_of_add_nsw_nuw_rhs_comm(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nsw i8 [[A]], [[B]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[A]], [[C]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.smin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MIN]]
+;
+  %add1 = add nsw i8 %a, %b ; thwart complexity-based canonicalization
+  %add2 = add nsw nuw i8 %a, %c ; thwart complexity-based canonicalization
+  %min = call i8 @llvm.smin.i8(i8 %add1, i8 %add2)
+  ret i8 %min
+}
+
+define i8 @smin_of_add_nsw_nuw(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smin_of_add_nsw_nuw(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[B]], [[A]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[C]], [[A]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.smin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MIN]]
+;
+  %add1 = add nsw nuw i8 %b, %a ; thwart complexity-based canonicalization
+  %add2 = add nsw nuw i8 %c, %a ; thwart complexity-based canonicalization
+  %min = call i8 @llvm.smin.i8(i8 %add1, i8 %add2)
+  ret i8 %min
+}
+
+define i8 @smin_of_add_nsw_nuw_comm(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smin_of_add_nsw_nuw_comm(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[A]], [[B]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[A]], [[C]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.smin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MIN]]
+;
+  %add1 = add nsw nuw i8 %a, %b ; thwart complexity-based canonicalization
+  %add2 = add nsw nuw i8 %a, %c ; thwart complexity-based canonicalization
+  %min = call i8 @llvm.smin.i8(i8 %add1, i8 %add2)
+  ret i8 %min
+}
+
+; negative test
+define i8 @smin_of_add(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smin_of_add(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT:    [[ADD1:%.*]] = add i8 [[B]], [[A]]
+; CHECK-NEXT:    [[ADD2:%.*]] = add i8 [[C]], [[A]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.smin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    ret i8 [[MIN]]
+;
+  %add1 = add i8 %b, %a
+  %add2 = add i8 %c, %a
+  %min = call i8 @llvm.smin.i8(i8 %add1, i8 %add2)
+  ret i8 %min
+}

>From b1543ac693629ddc270feeed38991a213f65f489 Mon Sep 17 00:00:00 2001
From: Jorge Botto <jorge.botto.16 at ucl.ac.uk>
Date: Sat, 3 Aug 2024 17:10:39 +0100
Subject: [PATCH 2/2] Adding missed optimisation

---
 llvm/include/llvm/IR/Operator.h               |   3 +
 .../InstCombine/InstCombineCalls.cpp          |  77 +++++++++
 .../InstCombine/intrinsic-distributive.ll     | 160 +++++++-----------
 3 files changed, 144 insertions(+), 96 deletions(-)

diff --git a/llvm/include/llvm/IR/Operator.h b/llvm/include/llvm/IR/Operator.h
index f63f54ef94107..d0a0242ec657d 100644
--- a/llvm/include/llvm/IR/Operator.h
+++ b/llvm/include/llvm/IR/Operator.h
@@ -123,6 +123,9 @@ class OverflowingBinaryOperator : public Operator {
     return NoWrapKind;
   }
 
+  /// Return true if the instruction is commutative
+  bool isCommutative() const { return Instruction::isCommutative(getOpcode()); }
+
   static bool classof(const Instruction *I) {
     return I->getOpcode() == Instruction::Add ||
            I->getOpcode() == Instruction::Sub ||
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index bf7c91bf36306..d4ec09bfdac4b 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -1505,6 +1505,80 @@ foldMinimumOverTrailingOrLeadingZeroCount(Value *I0, Value *I1,
       ConstantInt::getTrue(ZeroUndef->getType()));
 }
 
+/// Return whether "X LOp (Y ROp Z)" is always equal to
+/// "(X LOp Y) ROp (X LOp Z)".
+static bool foldIntrinsicUsingDistributiveLaws(Instruction::BinaryOps LOp,
+                                               bool hasNUW, bool hasNSW,
+                                               Intrinsic::ID ROp) {
+  switch (ROp) {
+  case Intrinsic::umax:
+    return hasNUW && LOp == Instruction::Add;
+  case Intrinsic::umin:
+    return hasNUW && LOp == Instruction::Add;
+  case Intrinsic::smax:
+    return hasNSW && LOp == Instruction::Add;
+  case Intrinsic::smin:
+    return hasNSW && LOp == Instruction::Add;
+  default:
+    return false;
+  }
+}
+
+// Attempts to factorise a common term
+// in an instruction that has the form "(A op' B) op (C op' D)
+// where op is an intrinsic and op' is a binop
+static Value *
+foldIntrinsicUsingDistributiveLaws(IntrinsicInst *II,
+                                   InstCombiner::BuilderTy &Builder) {
+  Value *LHS = II->getOperand(0), *RHS = II->getOperand(1);
+  Intrinsic::ID TopLevelOpcode = II->getIntrinsicID();
+
+  OverflowingBinaryOperator *Op0 = dyn_cast<OverflowingBinaryOperator>(LHS);
+  OverflowingBinaryOperator *Op1 = dyn_cast<OverflowingBinaryOperator>(RHS);
+
+  if (!Op0 || !Op1)
+    return nullptr;
+
+  if (Op0->getOpcode() != Op1->getOpcode())
+    return nullptr;
+
+  if (!Op0->hasOneUse() || !Op1->hasOneUse())
+    return nullptr;
+
+  Instruction::BinaryOps InnerOpcode =
+      static_cast<Instruction::BinaryOps>(Op0->getOpcode());
+  bool HasNUW = Op0->hasNoUnsignedWrap() && Op1->hasNoUnsignedWrap();
+  bool HasNSW = Op0->hasNoSignedWrap() && Op1->hasNoSignedWrap();
+
+  if (!foldIntrinsicUsingDistributiveLaws(InnerOpcode, HasNUW, HasNSW,
+                                          TopLevelOpcode))
+    return nullptr;
+
+  assert(II->isCommutative() && Op0->isCommutative() &&
+         "Only inner and outer commutative op codes are supported.");
+
+  Value *A = Op0->getOperand(0);
+  Value *B = Op0->getOperand(1);
+  Value *C = Op1->getOperand(0);
+  Value *D = Op1->getOperand(1);
+
+  // Attempts to swap variables such that A always equals C
+  if (A != C && A != D)
+    std::swap(A, B);
+  if (A == C || A == D) {
+    if (A != C)
+      std::swap(C, D);
+    Value *NewIntrinsic = Builder.CreateBinaryIntrinsic(TopLevelOpcode, B, D);
+    BinaryOperator *NewBinop =
+        cast<BinaryOperator>(Builder.CreateBinOp(InnerOpcode, NewIntrinsic, A));
+    NewBinop->setHasNoSignedWrap(HasNSW);
+    NewBinop->setHasNoUnsignedWrap(HasNUW);
+    return NewBinop;
+  }
+
+  return nullptr;
+}
+
 /// CallInst simplification. This mostly only handles folding of intrinsic
 /// instructions. For normal calls, it allows visitCallBase to do the heavy
 /// lifting.
@@ -1929,6 +2003,9 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
       }
     }
 
+    if (Value *V = foldIntrinsicUsingDistributiveLaws(II, Builder))
+      return replaceInstUsesWith(*II, V);
+
     break;
   }
   case Intrinsic::bitreverse: {
diff --git a/llvm/test/Transforms/InstCombine/intrinsic-distributive.ll b/llvm/test/Transforms/InstCombine/intrinsic-distributive.ll
index 5f40a7453c94c..c8be5f2dac1f7 100644
--- a/llvm/test/Transforms/InstCombine/intrinsic-distributive.ll
+++ b/llvm/test/Transforms/InstCombine/intrinsic-distributive.ll
@@ -5,9 +5,8 @@
 define i8 @umax_of_add_nuw(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @umax_of_add_nuw(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nuw i8 [[B]], [[A]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nuw i8 [[C]], [[A]]
-; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MAX:%.*]] = add nuw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MAX]]
 ;
   %add1 = add nuw i8 %b, %a ; thwart complexity-based canonicalization
@@ -19,9 +18,8 @@ define i8 @umax_of_add_nuw(i8 %a, i8 %b, i8 %c) {
 define i8 @umax_of_add_nuw_comm(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @umax_of_add_nuw_comm(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nuw i8 [[A]], [[B]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nuw i8 [[A]], [[C]]
-; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MAX:%.*]] = add nuw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MAX]]
 ;
   %add1 = add nuw i8 %a, %b ; thwart complexity-based canonicalization
@@ -33,9 +31,8 @@ define i8 @umax_of_add_nuw_comm(i8 %a, i8 %b, i8 %c) {
 define i8 @umax_of_add_nuw_nsw_lhs(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @umax_of_add_nuw_nsw_lhs(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[B]], [[A]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nuw i8 [[C]], [[A]]
-; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MAX:%.*]] = add nuw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MAX]]
 ;
   %add1 = add nuw nsw i8 %b, %a ; thwart complexity-based canonicalization
@@ -47,9 +44,8 @@ define i8 @umax_of_add_nuw_nsw_lhs(i8 %a, i8 %b, i8 %c) {
 define i8 @umax_of_add_nuw_nsw_lhs_comm(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @umax_of_add_nuw_nsw_lhs_comm(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[A]], [[B]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nuw i8 [[A]], [[C]]
-; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MAX:%.*]] = add nuw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MAX]]
 ;
   %add1 = add nuw nsw i8 %a, %b ; thwart complexity-based canonicalization
@@ -61,9 +57,8 @@ define i8 @umax_of_add_nuw_nsw_lhs_comm(i8 %a, i8 %b, i8 %c) {
 define i8 @umax_of_add_nuw_nsw_rhs(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @umax_of_add_nuw_nsw_rhs(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nuw i8 [[B]], [[A]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[C]], [[A]]
-; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MAX:%.*]] = add nuw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MAX]]
 ;
   %add1 = add nuw i8 %b, %a ; thwart complexity-based canonicalization
@@ -75,9 +70,8 @@ define i8 @umax_of_add_nuw_nsw_rhs(i8 %a, i8 %b, i8 %c) {
 define i8 @umax_of_add_nuw_nsw_rhs_comm(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @umax_of_add_nuw_nsw_rhs_comm(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nuw i8 [[A]], [[B]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[A]], [[C]]
-; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MAX:%.*]] = add nuw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MAX]]
 ;
   %add1 = add nuw i8 %a, %b ; thwart complexity-based canonicalization
@@ -89,9 +83,8 @@ define i8 @umax_of_add_nuw_nsw_rhs_comm(i8 %a, i8 %b, i8 %c) {
 define i8 @umax_of_add_nuw_nsw(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @umax_of_add_nuw_nsw(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[B]], [[A]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[C]], [[A]]
-; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MAX:%.*]] = add nuw nsw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MAX]]
 ;
   %add1 = add nuw nsw i8 %b, %a ; thwart complexity-based canonicalization
@@ -103,9 +96,8 @@ define i8 @umax_of_add_nuw_nsw(i8 %a, i8 %b, i8 %c) {
 define i8 @umax_of_add_nuw_nsw_comm(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @umax_of_add_nuw_nsw_comm(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[A]], [[B]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[A]], [[C]]
-; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MAX:%.*]] = add nuw nsw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MAX]]
 ;
   %add1 = add nuw nsw i8 %a, %b ; thwart complexity-based canonicalization
@@ -147,9 +139,8 @@ define i8 @umax_of_add(i8 %a, i8 %b, i8 %c) {
 define i8 @umin_of_add_nuw(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @umin_of_add_nuw(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nuw i8 [[B]], [[A]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nuw i8 [[C]], [[A]]
-; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.umin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MIN:%.*]] = add nuw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MIN]]
 ;
   %add1 = add nuw i8 %b, %a ; thwart complexity-based canonicalization
@@ -161,9 +152,8 @@ define i8 @umin_of_add_nuw(i8 %a, i8 %b, i8 %c) {
 define i8 @umin_of_add_nuw_comm(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @umin_of_add_nuw_comm(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nuw i8 [[A]], [[B]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nuw i8 [[A]], [[C]]
-; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.umin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MIN:%.*]] = add nuw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MIN]]
 ;
   %add1 = add nuw i8 %a, %b ; thwart complexity-based canonicalization
@@ -175,9 +165,8 @@ define i8 @umin_of_add_nuw_comm(i8 %a, i8 %b, i8 %c) {
 define i8 @umin_of_add_nuw_nsw_lhs(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @umin_of_add_nuw_nsw_lhs(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[B]], [[A]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nuw i8 [[C]], [[A]]
-; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.umin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MIN:%.*]] = add nuw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MIN]]
 ;
   %add1 = add nuw nsw i8 %b, %a ; thwart complexity-based canonicalization
@@ -189,9 +178,8 @@ define i8 @umin_of_add_nuw_nsw_lhs(i8 %a, i8 %b, i8 %c) {
 define i8 @umin_of_add_nuw_nsw_lhs_comm(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @umin_of_add_nuw_nsw_lhs_comm(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[A]], [[B]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nuw i8 [[A]], [[C]]
-; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.umin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MIN:%.*]] = add nuw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MIN]]
 ;
   %add1 = add nuw nsw i8 %a, %b ; thwart complexity-based canonicalization
@@ -203,9 +191,8 @@ define i8 @umin_of_add_nuw_nsw_lhs_comm(i8 %a, i8 %b, i8 %c) {
 define i8 @umin_of_add_nuw_nsw_rhs(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @umin_of_add_nuw_nsw_rhs(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nuw i8 [[B]], [[A]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[C]], [[A]]
-; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.umin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MIN:%.*]] = add nuw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MIN]]
 ;
   %add1 = add nuw i8 %b, %a ; thwart complexity-based canonicalization
@@ -217,9 +204,8 @@ define i8 @umin_of_add_nuw_nsw_rhs(i8 %a, i8 %b, i8 %c) {
 define i8 @umin_of_add_nuw_nsw_rhs_comm(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @umin_of_add_nuw_nsw_rhs_comm(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nuw i8 [[A]], [[B]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[A]], [[C]]
-; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.umin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MIN:%.*]] = add nuw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MIN]]
 ;
   %add1 = add nuw i8 %a, %b ; thwart complexity-based canonicalization
@@ -231,9 +217,8 @@ define i8 @umin_of_add_nuw_nsw_rhs_comm(i8 %a, i8 %b, i8 %c) {
 define i8 @umin_of_add_nuw_nsw(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @umin_of_add_nuw_nsw(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[B]], [[A]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[C]], [[A]]
-; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.umin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MIN:%.*]] = add nuw nsw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MIN]]
 ;
   %add1 = add nuw nsw i8 %b, %a ; thwart complexity-based canonicalization
@@ -245,9 +230,8 @@ define i8 @umin_of_add_nuw_nsw(i8 %a, i8 %b, i8 %c) {
 define i8 @umin_of_add_nuw_nsw_comm(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @umin_of_add_nuw_nsw_comm(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[A]], [[B]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[A]], [[C]]
-; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.umin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MIN:%.*]] = add nuw nsw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MIN]]
 ;
   %add1 = add nuw nsw i8 %a, %b ; thwart complexity-based canonicalization
@@ -304,9 +288,8 @@ define i8 @smax_of_add_nuw(i8 %a, i8 %b, i8 %c) {
 define i8 @smax_of_add_nsw(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @smax_of_add_nsw(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nsw i8 [[B]], [[A]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nsw i8 [[C]], [[A]]
-; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MAX:%.*]] = add nsw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MAX]]
 ;
   %add1 = add nsw i8 %b, %a ; thwart complexity-based canonicalization
@@ -318,9 +301,8 @@ define i8 @smax_of_add_nsw(i8 %a, i8 %b, i8 %c) {
 define i8 @smax_of_add_nsw_comm(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @smax_of_add_nsw_comm(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nsw i8 [[A]], [[B]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nsw i8 [[A]], [[C]]
-; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MAX:%.*]] = add nsw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MAX]]
 ;
   %add1 = add nsw i8 %a, %b ; thwart complexity-based canonicalization
@@ -332,9 +314,8 @@ define i8 @smax_of_add_nsw_comm(i8 %a, i8 %b, i8 %c) {
 define i8 @smax_of_add_nsw_nuw_lhs(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @smax_of_add_nsw_nuw_lhs(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[B]], [[A]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nsw i8 [[C]], [[A]]
-; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MAX:%.*]] = add nsw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MAX]]
 ;
   %add1 = add nsw nuw i8 %b, %a ; thwart complexity-based canonicalization
@@ -346,9 +327,8 @@ define i8 @smax_of_add_nsw_nuw_lhs(i8 %a, i8 %b, i8 %c) {
 define i8 @smax_of_add_nsw_nuw_lhs_comm(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @smax_of_add_nsw_nuw_lhs_comm(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[A]], [[B]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nsw i8 [[A]], [[C]]
-; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MAX:%.*]] = add nsw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MAX]]
 ;
   %add1 = add nsw nuw i8 %a, %b ; thwart complexity-based canonicalization
@@ -360,9 +340,8 @@ define i8 @smax_of_add_nsw_nuw_lhs_comm(i8 %a, i8 %b, i8 %c) {
 define i8 @smax_of_add_nsw_nuw_rhs(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @smax_of_add_nsw_nuw_rhs(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nsw i8 [[B]], [[A]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[C]], [[A]]
-; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MAX:%.*]] = add nsw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MAX]]
 ;
   %add1 = add nsw i8 %b, %a ; thwart complexity-based canonicalization
@@ -374,9 +353,8 @@ define i8 @smax_of_add_nsw_nuw_rhs(i8 %a, i8 %b, i8 %c) {
 define i8 @smax_of_add_nsw_nuw_rhs_comm(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @smax_of_add_nsw_nuw_rhs_comm(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nsw i8 [[A]], [[B]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[A]], [[C]]
-; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MAX:%.*]] = add nsw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MAX]]
 ;
   %add1 = add nsw i8 %a, %b ; thwart complexity-based canonicalization
@@ -388,9 +366,8 @@ define i8 @smax_of_add_nsw_nuw_rhs_comm(i8 %a, i8 %b, i8 %c) {
 define i8 @smax_of_add_nsw_nuw(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @smax_of_add_nsw_nuw(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[B]], [[A]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[C]], [[A]]
-; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MAX:%.*]] = add nuw nsw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MAX]]
 ;
   %add1 = add nsw nuw i8 %b, %a ; thwart complexity-based canonicalization
@@ -402,9 +379,8 @@ define i8 @smax_of_add_nsw_nuw(i8 %a, i8 %b, i8 %c) {
 define i8 @smax_of_add_nsw_nuw_comm(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @smax_of_add_nsw_nuw_comm(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[A]], [[B]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[A]], [[C]]
-; CHECK-NEXT:    [[MAX:%.*]] = call i8 @llvm.smax.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MAX:%.*]] = add nuw nsw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MAX]]
 ;
   %add1 = add nsw nuw i8 %a, %b ; thwart complexity-based canonicalization
@@ -446,9 +422,8 @@ define i8 @smin_of_add_nuw(i8 %a, i8 %b, i8 %c) {
 define i8 @smin_of_add_nsw(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @smin_of_add_nsw(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nsw i8 [[B]], [[A]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nsw i8 [[C]], [[A]]
-; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.smin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MIN:%.*]] = add nsw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MIN]]
 ;
   %add1 = add nsw i8 %b, %a ; thwart complexity-based canonicalization
@@ -460,9 +435,8 @@ define i8 @smin_of_add_nsw(i8 %a, i8 %b, i8 %c) {
 define i8 @smin_of_add_nsw_comm(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @smin_of_add_nsw_comm(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nsw i8 [[A]], [[B]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nsw i8 [[A]], [[C]]
-; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.smin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MIN:%.*]] = add nsw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MIN]]
 ;
   %add1 = add nsw i8 %a, %b ; thwart complexity-based canonicalization
@@ -474,9 +448,8 @@ define i8 @smin_of_add_nsw_comm(i8 %a, i8 %b, i8 %c) {
 define i8 @smin_of_add_nsw_nuw_lhs(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @smin_of_add_nsw_nuw_lhs(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[B]], [[A]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nsw i8 [[C]], [[A]]
-; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.smin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MIN:%.*]] = add nsw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MIN]]
 ;
   %add1 = add nsw nuw i8 %b, %a ; thwart complexity-based canonicalization
@@ -488,9 +461,8 @@ define i8 @smin_of_add_nsw_nuw_lhs(i8 %a, i8 %b, i8 %c) {
 define i8 @smin_of_add_nsw_nuw_lhs_comm(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @smin_of_add_nsw_nuw_lhs_comm(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[A]], [[B]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nsw i8 [[A]], [[C]]
-; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.smin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MIN:%.*]] = add nsw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MIN]]
 ;
   %add1 = add nsw nuw i8 %a, %b ; thwart complexity-based canonicalization
@@ -502,9 +474,8 @@ define i8 @smin_of_add_nsw_nuw_lhs_comm(i8 %a, i8 %b, i8 %c) {
 define i8 @smin_of_add_nsw_nuw_rhs(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @smin_of_add_nsw_nuw_rhs(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nsw i8 [[B]], [[A]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[C]], [[A]]
-; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.smin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MIN:%.*]] = add nsw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MIN]]
 ;
   %add1 = add nsw i8 %b, %a ; thwart complexity-based canonicalization
@@ -516,9 +487,8 @@ define i8 @smin_of_add_nsw_nuw_rhs(i8 %a, i8 %b, i8 %c) {
 define i8 @smin_of_add_nsw_nuw_rhs_comm(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @smin_of_add_nsw_nuw_rhs_comm(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nsw i8 [[A]], [[B]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[A]], [[C]]
-; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.smin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MIN:%.*]] = add nsw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MIN]]
 ;
   %add1 = add nsw i8 %a, %b ; thwart complexity-based canonicalization
@@ -530,9 +500,8 @@ define i8 @smin_of_add_nsw_nuw_rhs_comm(i8 %a, i8 %b, i8 %c) {
 define i8 @smin_of_add_nsw_nuw(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @smin_of_add_nsw_nuw(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[B]], [[A]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[C]], [[A]]
-; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.smin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MIN:%.*]] = add nuw nsw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MIN]]
 ;
   %add1 = add nsw nuw i8 %b, %a ; thwart complexity-based canonicalization
@@ -544,9 +513,8 @@ define i8 @smin_of_add_nsw_nuw(i8 %a, i8 %b, i8 %c) {
 define i8 @smin_of_add_nsw_nuw_comm(i8 %a, i8 %b, i8 %c) {
 ; CHECK-LABEL: define i8 @smin_of_add_nsw_nuw_comm(
 ; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
-; CHECK-NEXT:    [[ADD1:%.*]] = add nuw nsw i8 [[A]], [[B]]
-; CHECK-NEXT:    [[ADD2:%.*]] = add nuw nsw i8 [[A]], [[C]]
-; CHECK-NEXT:    [[MIN:%.*]] = call i8 @llvm.smin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT:    [[MIN:%.*]] = add nuw nsw i8 [[TMP1]], [[A]]
 ; CHECK-NEXT:    ret i8 [[MIN]]
 ;
   %add1 = add nsw nuw i8 %a, %b ; thwart complexity-based canonicalization



More information about the llvm-commits mailing list