CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
1716 lines
50 KiB
C++
1716 lines
50 KiB
C++
//===- KnownFPClassTest.cpp -----------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "GISelMITest.h"
|
|
#include "llvm/ADT/FloatingPointMode.h"
|
|
#include "llvm/CodeGen/GlobalISel/GISelValueTracking.h"
|
|
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
|
|
#include "gtest/gtest.h"
|
|
#include <optional>
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassCstPosZero) {
|
|
StringRef MIRString = " %3:_(s32) = G_FCONSTANT float 0.0\n"
|
|
" %4:_(s32) = COPY %3\n";
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
unsigned CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcPosZero, Known.KnownFPClasses);
|
|
EXPECT_EQ(false, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassCstNegZero) {
|
|
StringRef MIRString = " %3:_(s32) = G_FCONSTANT float -0.0\n"
|
|
" %4:_(s32) = COPY %3\n";
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcNegZero, Known.KnownFPClasses);
|
|
EXPECT_EQ(true, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassUndef) {
|
|
StringRef MIRString = R"(
|
|
%def:_(s32) = G_IMPLICIT_DEF
|
|
%copy_def:_(s32) = COPY %def
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcAllFlags, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassCstVecNegZero) {
|
|
StringRef MIRString = R"(
|
|
%c0:_(s32) = G_FCONSTANT float -0.0
|
|
%c1:_(s32) = G_FCONSTANT float -0.0
|
|
%c2:_(s32) = G_FCONSTANT float -0.0
|
|
%vector:_(<3 x s32>) = G_BUILD_VECTOR %c0, %c1, %c2
|
|
%copy_vector:_(<3 x s32>) = COPY %vector
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcNegZero, Known.KnownFPClasses);
|
|
EXPECT_EQ(true, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassCstZeroFPExt) {
|
|
StringRef MIRString = R"(
|
|
%c0:_(s32) = G_FCONSTANT float 0.0
|
|
%ext:_(s64) = nnan ninf G_FPEXT %c0
|
|
%copy_vector:_(s64) = COPY %ext
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcPosZero, Known.KnownFPClasses);
|
|
EXPECT_EQ(false, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassCstVecZeroFPExt) {
|
|
StringRef MIRString = R"(
|
|
%c0:_(s32) = G_FCONSTANT float 0.0
|
|
%c1:_(s32) = G_FCONSTANT float 0.0
|
|
%c2:_(s32) = G_FCONSTANT float 0.0
|
|
%vector:_(<3 x s32>) = G_BUILD_VECTOR %c0, %c1, %c2
|
|
%ext:_(<3 x s64>) = nnan ninf G_FPEXT %vector
|
|
%copy_vector:_(<3 x s64>) = COPY %ext
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcPosZero, Known.KnownFPClasses);
|
|
EXPECT_EQ(false, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassCstZeroFPTrunc) {
|
|
StringRef MIRString = R"(
|
|
%c0:_(s64) = G_FCONSTANT double 0.0
|
|
%trunc:_(s32) = nnan ninf G_FPTRUNC %c0
|
|
%copy_vector:_(s32) = COPY %trunc
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcPosFinite | fcNegZero, Known.KnownFPClasses);
|
|
EXPECT_EQ(false, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassCstVecZeroFPTrunc) {
|
|
StringRef MIRString = R"(
|
|
%c0:_(s64) = G_FCONSTANT double 0.0
|
|
%c1:_(s64) = G_FCONSTANT double 0.0
|
|
%c2:_(s64) = G_FCONSTANT double 0.0
|
|
%vector:_(<3 x s64>) = G_BUILD_VECTOR %c0, %c1, %c2
|
|
%trunc:_(<3 x s32>) = nnan ninf G_FPTRUNC %vector
|
|
%copy_vector:_(<3 x s32>) = COPY %trunc
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcPosFinite | fcNegZero, Known.KnownFPClasses);
|
|
EXPECT_EQ(false, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassSelectPos0) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%cond:_(s1) = G_LOAD %ptr(p0) :: (load (s1))
|
|
%lhs:_(s32) = G_FCONSTANT float 0.0
|
|
%rhs:_(s32) = G_FCONSTANT float 0.0
|
|
%sel:_(s32) = G_SELECT %cond, %lhs, %rhs
|
|
%copy_sel:_(s32) = COPY %sel
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcPosZero, Known.KnownFPClasses);
|
|
EXPECT_EQ(false, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassSelectNeg0) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%cond:_(s1) = G_LOAD %ptr(p0) :: (load (s1))
|
|
%lhs:_(s32) = G_FCONSTANT float -0.0
|
|
%rhs:_(s32) = G_FCONSTANT float -0.0
|
|
%sel:_(s32) = G_SELECT %cond, %lhs, %rhs
|
|
%copy_sel:_(s32) = COPY %sel
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcNegZero, Known.KnownFPClasses);
|
|
EXPECT_EQ(true, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassSelectPosOrNeg0) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%cond:_(s1) = G_LOAD %ptr(p0) :: (load (s1))
|
|
%lhs:_(s32) = G_FCONSTANT float -0.0
|
|
%rhs:_(s32) = G_FCONSTANT float 0.0
|
|
%sel:_(s32) = G_SELECT %cond, %lhs, %rhs
|
|
%copy_sel:_(s32) = COPY %sel
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcZero, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassSelectPosInf) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%cond:_(s1) = G_LOAD %ptr(p0) :: (load (s1))
|
|
%lhs:_(s32) = G_FCONSTANT float 0x7FF0000000000000
|
|
%rhs:_(s32) = G_FCONSTANT float 0x7FF0000000000000
|
|
%sel:_(s32) = G_SELECT %cond, %lhs, %rhs
|
|
%copy_sel:_(s32) = COPY %sel
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcPosInf, Known.KnownFPClasses);
|
|
EXPECT_EQ(false, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassSelectNegInf) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%cond:_(s1) = G_LOAD %ptr(p0) :: (load (s1))
|
|
%lhs:_(s32) = G_FCONSTANT float 0xFFF0000000000000
|
|
%rhs:_(s32) = G_FCONSTANT float 0xFFF0000000000000
|
|
%sel:_(s32) = G_SELECT %cond, %lhs, %rhs
|
|
%copy_sel:_(s32) = COPY %sel
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcNegInf, Known.KnownFPClasses);
|
|
EXPECT_EQ(true, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassSelectPosOrNegInf) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%cond:_(s1) = G_LOAD %ptr(p0) :: (load (s1))
|
|
%lhs:_(s32) = G_FCONSTANT float 0x7FF0000000000000
|
|
%rhs:_(s32) = G_FCONSTANT float 0xFFF0000000000000
|
|
%sel:_(s32) = G_SELECT %cond, %lhs, %rhs
|
|
%copy_sel:_(s32) = COPY %sel
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcInf, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassSelectNNaN) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%cond:_(s1) = G_LOAD %ptr(p0) :: (load (s1))
|
|
%lhs:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%rhs:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%sel:_(s32) = nnan G_SELECT %cond, %lhs, %rhs
|
|
%copy_sel:_(s32) = COPY %sel
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(~fcNan, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassSelectNInf) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%cond:_(s1) = G_LOAD %ptr(p0) :: (load (s1))
|
|
%lhs:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%rhs:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%sel:_(s32) = ninf G_SELECT %cond, %lhs, %rhs
|
|
%copy_sel:_(s32) = COPY %sel
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(~fcInf, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassSelectNNaNNInf) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%cond:_(s1) = G_LOAD %ptr(p0) :: (load (s1))
|
|
%lhs:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%rhs:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%sel:_(s32) = nnan ninf G_SELECT %cond, %lhs, %rhs
|
|
%copy_sel:_(s32) = COPY %sel
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(~(fcNan | fcInf), Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFNegNInf) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%fneg:_(s32) = ninf G_FNEG %val
|
|
%copy_fneg:_(s32) = COPY %fneg
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(~fcInf, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFabsUnknown) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%fabs:_(s32) = G_FABS %val
|
|
%copy_fabs:_(s32) = COPY %fabs
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcPositive | fcNan, Known.KnownFPClasses);
|
|
EXPECT_EQ(false, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassVecFabsUnknown) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(<3 x s32>) = G_LOAD %ptr(p0) :: (load (<3 x s32>))
|
|
%fabs:_(<3 x s32>) = G_FABS %val
|
|
%copy_fabs:_(<3 x s32>) = COPY %fabs
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcPositive | fcNan, Known.KnownFPClasses);
|
|
EXPECT_EQ(false, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFnegFabs) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%fabs:_(s32) = G_FABS %val
|
|
%fneg:_(s32) = G_FNEG %fabs
|
|
%copy_fneg:_(s32) = COPY %fneg
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcNegative | fcNan, Known.KnownFPClasses);
|
|
EXPECT_EQ(true, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFnegFabsNInf) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%fabs:_(s32) = ninf G_FABS %val
|
|
%fneg:_(s32) = G_FNEG %fabs
|
|
%copy_fneg:_(s32) = COPY %fneg
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcNegFinite | fcNan, Known.KnownFPClasses);
|
|
EXPECT_EQ(true, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFnegFabsNNan) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%fabs:_(s32) = nnan G_FABS %val
|
|
%fneg:_(s32) = G_FNEG %fabs
|
|
%copy_fneg:_(s32) = COPY %fneg
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcNegative, Known.KnownFPClasses);
|
|
EXPECT_EQ(true, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassCopySignNNanSrc0) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%mag:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%sgn:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%fabs:_(s32) = nnan G_FABS %mag
|
|
%fcopysign:_(s32) = G_FCOPYSIGN %fabs, %sgn
|
|
%copy_fcopysign:_(s32) = COPY %fcopysign
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(~fcNan, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassCopySignNInfSrc0_NegSign) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%mag:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%sgn:_(s32) = G_FCONSTANT float -1.0
|
|
%fabs:_(s32) = ninf G_FLOG %mag
|
|
%fcopysign:_(s32) = G_FCOPYSIGN %fabs, %sgn
|
|
%copy_fcopysign:_(s32) = COPY %fcopysign
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcNan | fcNegZero | fcNegNormal, Known.KnownFPClasses);
|
|
EXPECT_EQ(true, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassCopySignNInfSrc0_PosSign) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%mag:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%sgn:_(s32) = G_FCONSTANT float 1.0
|
|
%fabs:_(s32) = ninf G_FSQRT %mag
|
|
%fcopysign:_(s32) = G_FCOPYSIGN %fabs, %sgn
|
|
%copy_fcopysign:_(s32) = COPY %fcopysign
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcNan | fcPosZero | fcPosNormal, Known.KnownFPClasses);
|
|
EXPECT_EQ(false, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassUIToFP) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%cast:_(s32) = G_UITOFP %val
|
|
%copy_cast:_(s32) = COPY %cast
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcPosZero | fcPosNormal, Known.KnownFPClasses);
|
|
EXPECT_EQ(false, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassSIToFP) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%cast:_(s32) = G_SITOFP %val
|
|
%copy_cast:_(s32) = COPY %cast
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcPosNormal | fcNegNormal | fcPosZero, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFAdd) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%lhs:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%rhs:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%fadd:_(s32) = G_FADD %lhs, %rhs
|
|
%copy_fadd:_(s32) = COPY %fadd
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcAllFlags, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFAdd_Zero) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%lhs:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%rhs:_(s32) = G_FCONSTANT float 0.0
|
|
%fadd:_(s32) = G_FADD %lhs, %rhs
|
|
%copy_fadd:_(s32) = COPY %fadd
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcAllFlags & ~fcNegZero, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFAdd_NegZero) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%lhs:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%rhs:_(s32) = G_FCONSTANT float -0.0
|
|
%fadd:_(s32) = G_FADD %lhs, %rhs
|
|
%copy_fadd:_(s32) = COPY %fadd
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcAllFlags, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFstrictAdd_Zero) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%lhs:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%rhs:_(s32) = G_FCONSTANT float 0.0
|
|
%fadd:_(s32) = G_STRICT_FADD %lhs, %rhs
|
|
%copy_fadd:_(s32) = COPY %fadd
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcAllFlags & ~fcNegZero, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFMul) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%load:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%val:_(s32) = G_FREEZE %load
|
|
%fmul:_(s32) = G_FMUL %val, %val
|
|
%copy_fadd:_(s32) = COPY %fmul
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcPositive | fcNan, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFMulZero) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%lhs:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%rhs:_(s32) = G_FCONSTANT float 0.0
|
|
%fabs:_(s32) = nnan ninf G_FABS %lhs
|
|
%fmul:_(s32) = G_FMUL %fabs, %rhs
|
|
%copy_fadd:_(s32) = COPY %fmul
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcPosZero, Known.KnownFPClasses);
|
|
EXPECT_EQ(false, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFLogNeg) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%fabs:_(s32) = nnan ninf G_FABS %val
|
|
%fneg:_(s32) = nnan ninf G_FNEG %fabs
|
|
%flog:_(s32) = G_FLOG %fneg
|
|
%copy_flog:_(s32) = COPY %flog
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcNan | fcNegInf | fcPosZero | fcNormal, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFLogPosZero) {
|
|
StringRef MIRString = R"(
|
|
%val:_(s32) = G_FCONSTANT float 0.0
|
|
%flog:_(s32) = G_FLOG %val
|
|
%copy_flog:_(s32) = COPY %flog
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcNegInf | fcPosZero | fcNormal, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFLogNegZero) {
|
|
StringRef MIRString = R"(
|
|
%val:_(s32) = G_FCONSTANT float -0.0
|
|
%flog:_(s32) = G_FLOG %val
|
|
%copy_flog:_(s32) = COPY %flog
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcNegInf | fcPosZero | fcNormal, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassCopy) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%fabs:_(s32) = G_FABS %val
|
|
%copy:_(s32) = COPY %fabs
|
|
%copy_copy:_(s32) = COPY %copy
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(~fcNegative, Known.KnownFPClasses);
|
|
EXPECT_EQ(false, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassSelectIsFPClass) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%lhs:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%rhs:_(s32) = G_FCONSTANT float 0.0
|
|
%cond:_(s1) = G_IS_FPCLASS %lhs, 96
|
|
%sel:_(s32) = G_SELECT %cond, %lhs, %rhs
|
|
%copy_sel:_(s32) = COPY %sel
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcZero, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFLDExp) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%exp:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%fabs:_(s32) = G_FABS %val
|
|
%fldexp:_(s32) = G_FLDEXP %fabs, %exp
|
|
%copy_fldexp:_(s32) = COPY %fldexp
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcPositive | fcNan, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFPowIEvenExp) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%pwr:_(s32) = G_CONSTANT i32 2
|
|
%fpowi:_(s32) = G_FPOWI %val, %pwr
|
|
%copy_fpowi:_(s32) = COPY %fpowi
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcPositive | fcNan, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFPowIPos) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%pwr:_(s32) = G_CONSTANT i32 3
|
|
%fabs:_(s32) = nnan ninf G_FABS %val
|
|
%fpowi:_(s32) = G_FPOWI %fabs, %pwr
|
|
%copy_fpowi:_(s32) = COPY %fpowi
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcPositive, Known.KnownFPClasses);
|
|
EXPECT_EQ(false, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFPowIInf) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%load:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%val:_(s32) = G_FREEZE %load
|
|
%x:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%finite:_(s32) = ninf G_FNEG %val
|
|
%normal:_(s32) = G_FCONSTANT float 2.0
|
|
%zero_or_nan:_(s32) = G_FREM %val, %val
|
|
%nonneg_mask:_(s32) = G_CONSTANT i32 2147483647
|
|
%nonneg:_(s32) = G_AND %x, %nonneg_mask
|
|
%one:_(s32) = G_CONSTANT i32 1
|
|
%two:_(s32) = G_CONSTANT i32 2
|
|
%negone:_(s32) = G_CONSTANT i32 -1
|
|
%fpowi0:_(s32) = G_FPOWI %finite, %one
|
|
%copy_fpowi0:_(s32) = COPY %fpowi0
|
|
%fpowi1:_(s32) = G_FPOWI %finite, %two
|
|
%copy_fpowi1:_(s32) = COPY %fpowi1
|
|
%fpowi2:_(s32) = G_FPOWI %normal, %negone
|
|
%copy_fpowi2:_(s32) = COPY %fpowi2
|
|
%fpowi3:_(s32) = G_FPOWI %zero_or_nan, %nonneg
|
|
%copy_fpowi3:_(s32) = COPY %fpowi3
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
// powi(finite, 1) --> ~fcInf
|
|
Register CopyReg0 = Copies[Copies.size() - 4];
|
|
MachineInstr *FinalCopy0 = MRI->getVRegDef(CopyReg0);
|
|
Register SrcReg0 = FinalCopy0->getOperand(1).getReg();
|
|
KnownFPClass Known0 = Info.computeKnownFPClass(SrcReg0, fcAllFlags);
|
|
KnownFPClass KnownInf0 = Info.computeKnownFPClass(SrcReg0, fcInf);
|
|
EXPECT_EQ(~fcInf, Known0.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known0.SignBit);
|
|
EXPECT_TRUE(KnownInf0.isKnownNeverInfinity());
|
|
|
|
// powi(finite, 2) --> fcPositive | fcNan
|
|
Register CopyReg1 = Copies[Copies.size() - 3];
|
|
MachineInstr *FinalCopy1 = MRI->getVRegDef(CopyReg1);
|
|
Register SrcReg1 = FinalCopy1->getOperand(1).getReg();
|
|
KnownFPClass Known1 = Info.computeKnownFPClass(SrcReg1, fcAllFlags);
|
|
KnownFPClass KnownInf1 = Info.computeKnownFPClass(SrcReg1, fcInf);
|
|
EXPECT_EQ(fcPositive | fcNan, Known1.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known1.SignBit);
|
|
EXPECT_FALSE(KnownInf1.isKnownNeverInfinity());
|
|
|
|
// powi(normal, -1) --> fcPosFinite
|
|
Register CopyReg2 = Copies[Copies.size() - 2];
|
|
MachineInstr *FinalCopy2 = MRI->getVRegDef(CopyReg2);
|
|
Register SrcReg2 = FinalCopy2->getOperand(1).getReg();
|
|
KnownFPClass Known2 = Info.computeKnownFPClass(SrcReg2, fcAllFlags);
|
|
KnownFPClass KnownInf2 = Info.computeKnownFPClass(SrcReg2, fcInf);
|
|
EXPECT_EQ(fcPosFinite, Known2.KnownFPClasses);
|
|
EXPECT_EQ(false, Known2.SignBit);
|
|
EXPECT_TRUE(KnownInf2.isKnownNeverInfinity());
|
|
|
|
// powi(zero_or_nan, nonneg) --> ~fcInf
|
|
Register CopyReg3 = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy3 = MRI->getVRegDef(CopyReg3);
|
|
Register SrcReg3 = FinalCopy3->getOperand(1).getReg();
|
|
KnownFPClass KnownInf3 = Info.computeKnownFPClass(SrcReg3, fcInf);
|
|
EXPECT_TRUE(KnownInf3.isKnownNeverInfinity());
|
|
|
|
// TODO: Add powi(0/nan, exp), exp > 0 --> fcNan | fcZero | fcPosNormal
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFDiv) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%load:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%val:_(s32) = G_FREEZE %load
|
|
%fdiv:_(s32) = G_FDIV %val, %val
|
|
%copy_fdiv:_(s32) = COPY %fdiv
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcPosNormal | fcNan, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFDiv_Inf) {
|
|
StringRef MIRString = R"(
|
|
%lhs:_(s32) = G_FCONSTANT float 1.0
|
|
%rhs:_(s32) = G_FCONSTANT float 0.0
|
|
%fdiv:_(s32) = G_FDIV %lhs, %rhs
|
|
%copy_fdiv:_(s32) = COPY %fdiv
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcPosInf, Known.KnownFPClasses);
|
|
EXPECT_EQ(false, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFRem) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%load:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%val:_(s32) = G_FREEZE %load
|
|
%frem:_(s32) = G_FREM %val, %val
|
|
%copy_frem:_(s32) = COPY %frem
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcZero | fcNan, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFRemSelf_KnownFiniteNonZero) {
|
|
// X % X where X is a known-finite, known-nonzero value should produce
|
|
// exactly [+-]0.0 (no NaN possible).
|
|
StringRef MIRString = R"(
|
|
%val:_(s32) = G_FCONSTANT float 2.0
|
|
%frem:_(s32) = G_FREM %val, %val
|
|
%copy_frem:_(s32) = COPY %frem
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
// 2.0 % 2.0 = 0.0 exactly — NaN is impossible since 2.0 is finite and
|
|
// nonzero.
|
|
EXPECT_EQ(fcZero, Known.KnownFPClasses);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassShuffleVec) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%vec:_(<4 x s32>) = G_LOAD %ptr(p0) :: (load (<4 x s32>))
|
|
%fabs:_(<4 x s32>) = nnan ninf G_FABS %vec
|
|
%def:_(<4 x s32>) = G_IMPLICIT_DEF
|
|
%shuf:_(<4 x s32>) = G_SHUFFLE_VECTOR %fabs(<4 x s32>), %def, shufflemask(0, 0, 0, 0)
|
|
%copy_shuf:_(<4 x s32>) = COPY %shuf
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcPosFinite, Known.KnownFPClasses);
|
|
EXPECT_EQ(false, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassBuildVec) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val1:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%fabs:_(s32) = nnan ninf G_FABS %val1
|
|
%val2:_(s32) = G_FCONSTANT float 3.0
|
|
%vec:_(<2 x s32>) = G_BUILD_VECTOR %fabs, %val2
|
|
%copy_vec:_(<2 x s32>) = COPY %vec
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcPosFinite, Known.KnownFPClasses);
|
|
EXPECT_EQ(false, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassConcatVec) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%vec1:_(<2 x s32>) = G_LOAD %ptr(p0) :: (load (<2 x s32>))
|
|
%c1:_(s32) = G_FCONSTANT float 1.0
|
|
%c2:_(s32) = G_FCONSTANT float 2.0
|
|
%vec2:_(<2 x s32>) = G_BUILD_VECTOR %c1, %c2
|
|
%fabs1:_(<2 x s32>) = nnan ninf G_FABS %vec1
|
|
%fabs2:_(<2 x s32>) = nnan ninf G_FABS %vec2
|
|
%cat:_(<4 x s32>) = G_CONCAT_VECTORS %fabs1, %fabs2
|
|
%copy_cat:_(<4 x s32>) = COPY %cat
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcPosFinite, Known.KnownFPClasses);
|
|
EXPECT_EQ(false, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassVecExtractElem) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%vec:_(<4 x s32>) = G_LOAD %ptr(p0) :: (load (<4 x s32>))
|
|
%fabs:_(<4 x s32>) = nnan ninf G_FABS %vec
|
|
%idx:_(s64) = G_CONSTANT i64 1
|
|
%extract:_(s32) = G_EXTRACT_VECTOR_ELT %fabs, %idx
|
|
%copy_elem:_(s32) = COPY %extract
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcPosFinite, Known.KnownFPClasses);
|
|
EXPECT_EQ(false, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassVecInsertElem) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%vec:_(<4 x s32>) = G_LOAD %ptr(p0) :: (load (<4 x s32>))
|
|
%fabs1:_(<4 x s32>) = nnan ninf G_FABS %vec
|
|
%elem:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%fabs2:_(s32) = nnan ninf G_FABS %elem
|
|
%idx:_(s64) = G_CONSTANT i64 1
|
|
%insert:_(<4 x s32>) = G_INSERT_VECTOR_ELT %fabs1, %fabs2, %idx
|
|
%copy_insert:_(<4 x s32>) = COPY %insert
|
|
)";
|
|
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
|
|
GISelValueTracking Info(*MF);
|
|
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
|
|
EXPECT_EQ(fcPosFinite, Known.KnownFPClasses);
|
|
EXPECT_EQ(false, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFSinh) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%fsinh:_(s32) = G_FSINH %val
|
|
%copy:_(s32) = COPY %fsinh
|
|
)";
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
GISelValueTracking Info(*MF);
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
EXPECT_EQ(fcAllFlags, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFSinhPos) {
|
|
// sinh is sign-preserving: non-negative input → non-negative output.
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%fabs:_(s32) = nnan ninf G_FABS %val
|
|
%fsinh:_(s32) = G_FSINH %fabs
|
|
%copy:_(s32) = COPY %fsinh
|
|
)";
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
GISelValueTracking Info(*MF);
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
EXPECT_EQ(fcPositive, Known.KnownFPClasses);
|
|
EXPECT_EQ(false, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFCosh) {
|
|
// cosh(x) >= 1 for all real x; never negative.
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%fcosh:_(s32) = G_FCOSH %val
|
|
%copy:_(s32) = COPY %fcosh
|
|
)";
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
GISelValueTracking Info(*MF);
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
EXPECT_EQ(fcPositive | fcNan, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFCoshNNaN) {
|
|
// cosh of a non-NaN source is non-NaN (and non-negative).
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%fabs:_(s32) = nnan G_FABS %val
|
|
%fcosh:_(s32) = G_FCOSH %fabs
|
|
%copy:_(s32) = COPY %fcosh
|
|
)";
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
GISelValueTracking Info(*MF);
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
EXPECT_EQ(fcPositive, Known.KnownFPClasses);
|
|
EXPECT_EQ(false, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFTanh) {
|
|
// tanh is bounded to (-1, 1): never Inf.
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%ftanh:_(s32) = G_FTANH %val
|
|
%copy:_(s32) = COPY %ftanh
|
|
)";
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
GISelValueTracking Info(*MF);
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
EXPECT_EQ(fcAllFlags & ~fcInf, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFTanhPos) {
|
|
// tanh is sign-preserving and bounded to (-1,1): non-negative finite output.
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%fabs:_(s32) = nnan ninf G_FABS %val
|
|
%ftanh:_(s32) = G_FTANH %fabs
|
|
%copy:_(s32) = COPY %ftanh
|
|
)";
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
GISelValueTracking Info(*MF);
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
EXPECT_EQ(fcPosFinite, Known.KnownFPClasses);
|
|
EXPECT_EQ(false, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFAsin) {
|
|
// asin is bounded to [-π/2, π/2]: never Inf.
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%fasin:_(s32) = G_FASIN %val
|
|
%copy:_(s32) = COPY %fasin
|
|
)";
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
GISelValueTracking Info(*MF);
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
EXPECT_EQ(fcAllFlags & ~fcInf, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFAsinPos) {
|
|
// asin is sign-preserving and bounded: non-negative finite output.
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%fabs:_(s32) = nnan ninf G_FABS %val
|
|
%fasin:_(s32) = G_FASIN %fabs
|
|
%copy:_(s32) = COPY %fasin
|
|
)";
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
GISelValueTracking Info(*MF);
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
EXPECT_EQ(fcPosFinite, Known.KnownFPClasses);
|
|
EXPECT_EQ(false, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFAcos) {
|
|
// acos is bounded to [0, π]: never Inf, never negative.
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%facos:_(s32) = G_FACOS %val
|
|
%copy:_(s32) = COPY %facos
|
|
)";
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
GISelValueTracking Info(*MF);
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
EXPECT_EQ(fcPosFinite | fcNan, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFAtan) {
|
|
// atan is bounded to (-π/2, π/2): never Inf (atan(±Inf) = ±π/2, finite).
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%fatan:_(s32) = G_FATAN %val
|
|
%copy:_(s32) = COPY %fatan
|
|
)";
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
GISelValueTracking Info(*MF);
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
EXPECT_EQ(fcAllFlags & ~fcInf, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFAtanPos) {
|
|
// atan is sign-preserving and bounded: non-negative finite output.
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%fabs:_(s32) = nnan ninf G_FABS %val
|
|
%fatan:_(s32) = G_FATAN %fabs
|
|
%copy:_(s32) = COPY %fatan
|
|
)";
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
GISelValueTracking Info(*MF);
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
EXPECT_EQ(fcPosFinite, Known.KnownFPClasses);
|
|
EXPECT_EQ(false, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFTan) {
|
|
// tan(±Inf) = NaN, tan(finite) = finite: never Inf.
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%ftan:_(s32) = G_FTAN %val
|
|
%copy:_(s32) = COPY %ftan
|
|
)";
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
GISelValueTracking Info(*MF);
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
EXPECT_EQ(fcAllFlags & ~fcInf, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFTanNNaN) {
|
|
// tan of a non-NaN, non-Inf source is non-NaN and non-Inf.
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%fabs:_(s32) = nnan ninf G_FABS %val
|
|
%ftan:_(s32) = G_FTAN %fabs
|
|
%copy:_(s32) = COPY %ftan
|
|
)";
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
GISelValueTracking Info(*MF);
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
EXPECT_EQ(fcFinite, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFAtan2) {
|
|
// atan2 result is in (-π, π]: never Inf.
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%y:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%x:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%fatan2:_(s32) = G_FATAN2 %y, %x
|
|
%copy:_(s32) = COPY %fatan2
|
|
)";
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
GISelValueTracking Info(*MF);
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
EXPECT_EQ(fcAllFlags & ~fcInf, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
TEST_F(AArch64GISelMITest, TestFPClassFAtan2NNaN) {
|
|
// atan2 with two non-NaN inputs is non-NaN and non-Inf.
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%y:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%x:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%fabs_y:_(s32) = nnan ninf G_FABS %y
|
|
%fabs_x:_(s32) = nnan ninf G_FABS %x
|
|
%fatan2:_(s32) = G_FATAN2 %fabs_y, %fabs_x
|
|
%copy:_(s32) = COPY %fatan2
|
|
)";
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
GISelValueTracking Info(*MF);
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
EXPECT_EQ(fcFinite, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
// isAbsoluteValueULEOne: x - floor(x) is in [0, 1), so multiplying a known-
|
|
// finite value by it cannot overflow to infinity.
|
|
TEST_F(AArch64GISelMITest, TestFPClassFMulAbsULEOne) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%x:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%val:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%floor:_(s32) = G_FFLOOR %x
|
|
%fract:_(s32) = G_FSUB %x, %floor
|
|
%finite:_(s32) = nnan ninf G_FABS %val
|
|
%fmul:_(s32) = G_FMUL %finite, %fract
|
|
%copy:_(s32) = COPY %fmul
|
|
)";
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
GISelValueTracking Info(*MF);
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
EXPECT_EQ(~fcInf, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|
|
|
|
// G_FMA with A == B (and A guaranteed not-undef): the multiply part is a
|
|
// square, so the result is known non-negative (never fcNegative).
|
|
TEST_F(AArch64GISelMITest, TestFPClassFMASelfSquare) {
|
|
StringRef MIRString = R"(
|
|
%ptr:_(p0) = G_IMPLICIT_DEF
|
|
%load:_(s32) = G_LOAD %ptr(p0) :: (load (s32))
|
|
%val:_(s32) = G_FREEZE %load
|
|
%c:_(s32) = G_FCONSTANT float 1.0
|
|
%fma:_(s32) = G_FMA %val, %val, %c
|
|
%copy:_(s32) = COPY %fma
|
|
)";
|
|
setUp(MIRString);
|
|
if (!TM)
|
|
GTEST_SKIP();
|
|
Register CopyReg = Copies[Copies.size() - 1];
|
|
MachineInstr *FinalCopy = MRI->getVRegDef(CopyReg);
|
|
Register SrcReg = FinalCopy->getOperand(1).getReg();
|
|
GISelValueTracking Info(*MF);
|
|
KnownFPClass Known = Info.computeKnownFPClass(SrcReg);
|
|
EXPECT_EQ(fcNan | fcPosInf | fcPosNormal, Known.KnownFPClasses);
|
|
EXPECT_EQ(std::nullopt, Known.SignBit);
|
|
}
|