From e7a02ebed07cdac1a4831330ab3ef92a3b79875b Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Wed, 10 Dec 2025 18:09:25 +0100 Subject: [PATCH] InstCombine: Add baseline test for #64697 fmul reassociation Currently fmul is not reassociated unless it has nsz, although this should be unnecessary. --- .../InstCombine/issue64967-reassoc-fmul.ll | 117 ++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 llvm/test/Transforms/InstCombine/issue64967-reassoc-fmul.ll diff --git a/llvm/test/Transforms/InstCombine/issue64967-reassoc-fmul.ll b/llvm/test/Transforms/InstCombine/issue64967-reassoc-fmul.ll new file mode 100644 index 0000000000000..16f9cf2dd64c5 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/issue64967-reassoc-fmul.ll @@ -0,0 +1,117 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 +; RUN: opt -S -passes=instcombine < %s | FileCheck %s + +; Show that unlike fadd, fmul does not require nsz to be reassociated. + +; Can't reassociate anyway +define float @fmul(float %x) { +; CHECK-LABEL: define float @fmul( +; CHECK-SAME: float [[X:%.*]]) { +; CHECK-NEXT: [[FMUL0:%.*]] = fmul float [[X]], 2.000000e+00 +; CHECK-NEXT: [[FMUL1:%.*]] = fmul float [[FMUL0]], 4.000000e+00 +; CHECK-NEXT: ret float [[FMUL1]] +; + %fmul0 = fmul float %x, 2.0 + %fmul1 = fmul float %fmul0, 4.0 + ret float %fmul1 +} + +; Should be able to reassociate without nsz +; (+0 * 2) * 4 = +0 +; (-0 * 2) * 4 = -0 + +; (+0 * 8) = +0 +; (-0 * 8) = -0 +define float @fmul_reassoc(float %x) { +; CHECK-LABEL: define float @fmul_reassoc( +; CHECK-SAME: float [[X:%.*]]) { +; CHECK-NEXT: [[FMUL0:%.*]] = fmul reassoc float [[X]], 2.000000e+00 +; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc float [[FMUL0]], 4.000000e+00 +; CHECK-NEXT: ret float [[FMUL1]] +; + %fmul0 = fmul reassoc float %x, 2.0 + %fmul1 = fmul reassoc float %fmul0, 4.0 + ret float %fmul1 +} + +define <2 x float> @fmul_reassoc_v2(<2 x float> %x) { +; CHECK-LABEL: define <2 x float> @fmul_reassoc_v2( +; CHECK-SAME: <2 x float> [[X:%.*]]) { +; CHECK-NEXT: [[FMUL0:%.*]] = fmul reassoc <2 x float> [[X]], splat (float 2.000000e+00) +; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc <2 x float> [[FMUL0]], splat (float 4.000000e+00) +; CHECK-NEXT: ret <2 x float> [[FMUL1]] +; + %fmul0 = fmul reassoc <2 x float> %x, splat (float 2.0) + %fmul1 = fmul reassoc <2 x float> %fmul0, splat (float 4.0) + ret <2 x float> %fmul1 +} + +; (+0 * 2) * -4 = -0 +; (-0 * 2) * -4 = +0 + +; (+0 * -8) = -0 +; (-0 * -8) = +0 +define float @fmul_reassoc_negative_0(float %x) { +; CHECK-LABEL: define float @fmul_reassoc_negative_0( +; CHECK-SAME: float [[X:%.*]]) { +; CHECK-NEXT: [[FMUL0:%.*]] = fmul reassoc float [[X]], 2.000000e+00 +; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc float [[FMUL0]], -4.000000e+00 +; CHECK-NEXT: ret float [[FMUL1]] +; + %fmul0 = fmul reassoc float %x, 2.0 + %fmul1 = fmul reassoc float %fmul0, -4.0 + ret float %fmul1 +} + +; (+0 * -2) * 4 = -0 +; (-0 * -2) * 4 = +0 + +; (+0 * -8) = -0 +; (-0 * -8) = +0 +define float @fmul_reassoc_negative_1(float %x) { +; CHECK-LABEL: define float @fmul_reassoc_negative_1( +; CHECK-SAME: float [[X:%.*]]) { +; CHECK-NEXT: [[FMUL0:%.*]] = fmul reassoc float [[X]], -2.000000e+00 +; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc float [[FMUL0]], 4.000000e+00 +; CHECK-NEXT: ret float [[FMUL1]] +; + %fmul0 = fmul reassoc float %x, -2.0 + %fmul1 = fmul reassoc float %fmul0, 4.0 + ret float %fmul1 +} + +; Does reassociate already, unnecessarily requires nsz on both multiplies. +define float @fmul_reassoc_nsz(float %x) { +; CHECK-LABEL: define float @fmul_reassoc_nsz( +; CHECK-SAME: float [[X:%.*]]) { +; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc nsz float [[X]], 8.000000e+00 +; CHECK-NEXT: ret float [[FMUL1]] +; + %fmul0 = fmul nsz reassoc float %x, 2.0 + %fmul1 = fmul nsz reassoc float %fmul0, 4.0 + ret float %fmul1 +} + +define float @fmul_reassoc_posk_neg0(float %x) { +; CHECK-LABEL: define float @fmul_reassoc_posk_neg0( +; CHECK-SAME: float [[X:%.*]]) { +; CHECK-NEXT: [[FMUL0:%.*]] = fmul reassoc float [[X]], 4.000000e+00 +; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc float [[FMUL0]], -0.000000e+00 +; CHECK-NEXT: ret float [[FMUL1]] +; + %fmul0 = fmul reassoc float %x, 4.0 + %fmul1 = fmul reassoc float %fmul0, -0.0 + ret float %fmul1 +} + +define float @fmul_reassoc_neg0_posk(float %x) { +; CHECK-LABEL: define float @fmul_reassoc_neg0_posk( +; CHECK-SAME: float [[X:%.*]]) { +; CHECK-NEXT: [[FMUL0:%.*]] = fmul reassoc float [[X]], -0.000000e+00 +; CHECK-NEXT: [[FMUL1:%.*]] = fmul reassoc float [[FMUL0]], 4.000000e+00 +; CHECK-NEXT: ret float [[FMUL1]] +; + %fmul0 = fmul reassoc float %x, -0.0 + %fmul1 = fmul reassoc float %fmul0, 4.0 + ret float %fmul1 +}