mirror of
https://github.com/llvm/llvm-project.git
synced 2025-05-08 23:46:05 +00:00

The select pattern recognition in ValueTracking (as used by InstCombine and SelectionDAGBuilder) only knew about integer patterns. This teaches it about minimum and maximum operations. matchSelectPattern() has been extended to return a struct containing the existing Flavor and a new enum defining the pattern's behavior when given one NaN operand. C minnum() is defined to return the non-NaN operand in this case, but the idiomatic C "a < b ? a : b" would return the NaN operand. ARM and AArch64 at least have different instructions for these different cases. llvm-svn: 244580
149 lines
4.2 KiB
C++
149 lines
4.2 KiB
C++
//===- ValueTrackingTest.cpp - ValueTracking tests ------------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Analysis/ValueTracking.h"
|
|
#include "llvm/AsmParser/Parser.h"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/IR/InstIterator.h"
|
|
#include "llvm/IR/LLVMContext.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/SourceMgr.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
|
|
class MatchSelectPatternTest : public testing::Test {
|
|
protected:
|
|
void parseAssembly(const char *Assembly) {
|
|
SMDiagnostic Error;
|
|
M = parseAssemblyString(Assembly, Error, getGlobalContext());
|
|
|
|
std::string errMsg;
|
|
raw_string_ostream os(errMsg);
|
|
Error.print("", os);
|
|
|
|
// A failure here means that the test itself is buggy.
|
|
if (!M)
|
|
report_fatal_error(os.str());
|
|
|
|
Function *F = M->getFunction("test");
|
|
if (F == nullptr)
|
|
report_fatal_error("Test must have a function named @test");
|
|
|
|
A = nullptr;
|
|
for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
|
|
if (I->hasName()) {
|
|
if (I->getName() == "A")
|
|
A = &*I;
|
|
}
|
|
}
|
|
if (A == nullptr)
|
|
report_fatal_error("@test must have an instruction %A");
|
|
}
|
|
|
|
void expectPattern(const SelectPatternResult &P) {
|
|
Value *LHS, *RHS;
|
|
Instruction::CastOps CastOp;
|
|
SelectPatternResult R = matchSelectPattern(A, LHS, RHS, &CastOp);
|
|
EXPECT_EQ(P.Flavor, R.Flavor);
|
|
EXPECT_EQ(P.NaNBehavior, R.NaNBehavior);
|
|
EXPECT_EQ(P.Ordered, R.Ordered);
|
|
}
|
|
|
|
std::unique_ptr<Module> M;
|
|
Instruction *A, *B;
|
|
};
|
|
|
|
}
|
|
|
|
TEST_F(MatchSelectPatternTest, SimpleFMin) {
|
|
parseAssembly(
|
|
"define float @test(float %a) {\n"
|
|
" %1 = fcmp ult float %a, 5.0\n"
|
|
" %A = select i1 %1, float %a, float 5.0\n"
|
|
" ret float %A\n"
|
|
"}\n");
|
|
expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false});
|
|
}
|
|
|
|
TEST_F(MatchSelectPatternTest, SimpleFMax) {
|
|
parseAssembly(
|
|
"define float @test(float %a) {\n"
|
|
" %1 = fcmp ogt float %a, 5.0\n"
|
|
" %A = select i1 %1, float %a, float 5.0\n"
|
|
" ret float %A\n"
|
|
"}\n");
|
|
expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true});
|
|
}
|
|
|
|
TEST_F(MatchSelectPatternTest, SwappedFMax) {
|
|
parseAssembly(
|
|
"define float @test(float %a) {\n"
|
|
" %1 = fcmp olt float 5.0, %a\n"
|
|
" %A = select i1 %1, float %a, float 5.0\n"
|
|
" ret float %A\n"
|
|
"}\n");
|
|
expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, false});
|
|
}
|
|
|
|
TEST_F(MatchSelectPatternTest, SwappedFMax2) {
|
|
parseAssembly(
|
|
"define float @test(float %a) {\n"
|
|
" %1 = fcmp olt float %a, 5.0\n"
|
|
" %A = select i1 %1, float 5.0, float %a\n"
|
|
" ret float %A\n"
|
|
"}\n");
|
|
expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, false});
|
|
}
|
|
|
|
TEST_F(MatchSelectPatternTest, SwappedFMax3) {
|
|
parseAssembly(
|
|
"define float @test(float %a) {\n"
|
|
" %1 = fcmp ult float %a, 5.0\n"
|
|
" %A = select i1 %1, float 5.0, float %a\n"
|
|
" ret float %A\n"
|
|
"}\n");
|
|
expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true});
|
|
}
|
|
|
|
TEST_F(MatchSelectPatternTest, FastFMin) {
|
|
parseAssembly(
|
|
"define float @test(float %a) {\n"
|
|
" %1 = fcmp nnan olt float %a, 5.0\n"
|
|
" %A = select i1 %1, float %a, float 5.0\n"
|
|
" ret float %A\n"
|
|
"}\n");
|
|
expectPattern({SPF_FMINNUM, SPNB_RETURNS_ANY, false});
|
|
}
|
|
|
|
TEST_F(MatchSelectPatternTest, FMinConstantZero) {
|
|
parseAssembly(
|
|
"define float @test(float %a) {\n"
|
|
" %1 = fcmp ole float %a, 0.0\n"
|
|
" %A = select i1 %1, float %a, float 0.0\n"
|
|
" ret float %A\n"
|
|
"}\n");
|
|
// This shouldn't be matched, as %a could be -0.0.
|
|
expectPattern({SPF_UNKNOWN, SPNB_NA, false});
|
|
}
|
|
|
|
TEST_F(MatchSelectPatternTest, FMinConstantZeroNsz) {
|
|
parseAssembly(
|
|
"define float @test(float %a) {\n"
|
|
" %1 = fcmp nsz ole float %a, 0.0\n"
|
|
" %A = select i1 %1, float %a, float 0.0\n"
|
|
" ret float %A\n"
|
|
"}\n");
|
|
// But this should be, because we've ignored signed zeroes.
|
|
expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true});
|
|
}
|