PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
//===---- llvm/unittest/IR/PatternMatch.cpp - PatternMatch unit tests ----===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// 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
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-06-06 19:06:56 +08:00
|
|
|
#include "llvm/IR/PatternMatch.h"
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
|
|
|
#include "llvm/Analysis/ValueTracking.h"
|
|
|
|
#include "llvm/IR/BasicBlock.h"
|
|
|
|
#include "llvm/IR/Constants.h"
|
|
|
|
#include "llvm/IR/DataLayout.h"
|
|
|
|
#include "llvm/IR/DerivedTypes.h"
|
2014-01-05 10:07:20 +08:00
|
|
|
#include "llvm/IR/Function.h"
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
#include "llvm/IR/IRBuilder.h"
|
2014-01-05 10:07:20 +08:00
|
|
|
#include "llvm/IR/Instructions.h"
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
#include "llvm/IR/LLVMContext.h"
|
|
|
|
#include "llvm/IR/MDBuilder.h"
|
2014-01-05 10:07:20 +08:00
|
|
|
#include "llvm/IR/Module.h"
|
2014-03-04 20:05:47 +08:00
|
|
|
#include "llvm/IR/NoFolder.h"
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
#include "llvm/IR/Operator.h"
|
2014-01-05 10:07:20 +08:00
|
|
|
#include "llvm/IR/Type.h"
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
#include "gtest/gtest.h"
|
|
|
|
|
2014-01-05 10:07:20 +08:00
|
|
|
using namespace llvm;
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
using namespace llvm::PatternMatch;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2014-01-05 10:07:20 +08:00
|
|
|
struct PatternMatchTest : ::testing::Test {
|
|
|
|
LLVMContext Ctx;
|
2014-03-06 13:51:42 +08:00
|
|
|
std::unique_ptr<Module> M;
|
2014-01-05 10:07:20 +08:00
|
|
|
Function *F;
|
|
|
|
BasicBlock *BB;
|
2016-03-14 05:05:13 +08:00
|
|
|
IRBuilder<NoFolder> IRB;
|
2014-01-05 10:07:20 +08:00
|
|
|
|
|
|
|
PatternMatchTest()
|
|
|
|
: M(new Module("PatternMatchTestModule", Ctx)),
|
|
|
|
F(Function::Create(
|
|
|
|
FunctionType::get(Type::getVoidTy(Ctx), /* IsVarArg */ false),
|
|
|
|
Function::ExternalLinkage, "f", M.get())),
|
2014-01-05 10:23:11 +08:00
|
|
|
BB(BasicBlock::Create(Ctx, "entry", F)), IRB(BB) {}
|
2014-01-05 10:07:20 +08:00
|
|
|
};
|
|
|
|
|
2014-01-05 17:14:53 +08:00
|
|
|
TEST_F(PatternMatchTest, OneUse) {
|
|
|
|
// Build up a little tree of values:
|
|
|
|
//
|
|
|
|
// One = (1 + 2) + 42
|
|
|
|
// Two = One + 42
|
|
|
|
// Leaf = (Two + 8) + (Two + 13)
|
|
|
|
Value *One = IRB.CreateAdd(IRB.CreateAdd(IRB.getInt32(1), IRB.getInt32(2)),
|
|
|
|
IRB.getInt32(42));
|
|
|
|
Value *Two = IRB.CreateAdd(One, IRB.getInt32(42));
|
|
|
|
Value *Leaf = IRB.CreateAdd(IRB.CreateAdd(Two, IRB.getInt32(8)),
|
|
|
|
IRB.CreateAdd(Two, IRB.getInt32(13)));
|
|
|
|
Value *V;
|
|
|
|
|
|
|
|
EXPECT_TRUE(m_OneUse(m_Value(V)).match(One));
|
|
|
|
EXPECT_EQ(One, V);
|
|
|
|
|
|
|
|
EXPECT_FALSE(m_OneUse(m_Value()).match(Two));
|
|
|
|
EXPECT_FALSE(m_OneUse(m_Value()).match(Leaf));
|
|
|
|
}
|
|
|
|
|
[PatternMatch] Stabilize the matching order of commutative matchers
Summary:
Currently, we
1. match `LHS` matcher to the `first` operand of binary operator,
2. and then match `RHS` matcher to the `second` operand of binary operator.
If that does not match, we swap the `LHS` and `RHS` matchers:
1. match `RHS` matcher to the `first` operand of binary operator,
2. and then match `LHS` matcher to the `second` operand of binary operator.
This works ok.
But it complicates writing of commutative matchers, where one would like to match
(`m_Value()`) the value on one side, and use (`m_Specific()`) it on the other side.
This is additionally complicated by the fact that `m_Specific()` stores the `Value *`,
not `Value **`, so it won't work at all out of the box.
The last problem is trivially solved by adding a new `m_c_Specific()` that stores the
`Value **`, not `Value *`. I'm choosing to add a new matcher, not change the existing
one because i guess all the current users are ok with existing behavior,
and this additional pointer indirection may have performance drawbacks.
Also, i'm storing pointer, not reference, because for some mysterious-to-me reason
it did not work with the reference.
The first one appears trivial, too.
Currently, we
1. match `LHS` matcher to the `first` operand of binary operator,
2. and then match `RHS` matcher to the `second` operand of binary operator.
If that does not match, we swap the ~~`LHS` and `RHS` matchers~~ **operands**:
1. match ~~`RHS`~~ **`LHS`** matcher to the ~~`first`~~ **`second`** operand of binary operator,
2. and then match ~~`LHS`~~ **`RHS`** matcher to the ~~`second`~ **`first`** operand of binary operator.
Surprisingly, `$ ninja check-llvm` still passes with this.
But i expect the bots will disagree..
The motivational unittest is included.
I'd like to use this in D45664.
Reviewers: spatel, craig.topper, arsenm, RKSimon
Reviewed By: craig.topper
Subscribers: xbolva00, wdng, llvm-commits
Differential Revision: https://reviews.llvm.org/D45828
llvm-svn: 331085
2018-04-28 05:23:20 +08:00
|
|
|
TEST_F(PatternMatchTest, CommutativeDeferredValue) {
|
|
|
|
Value *X = IRB.getInt32(1);
|
|
|
|
Value *Y = IRB.getInt32(2);
|
|
|
|
|
|
|
|
{
|
|
|
|
Value *tX = X;
|
|
|
|
EXPECT_TRUE(match(X, m_Deferred(tX)));
|
|
|
|
EXPECT_FALSE(match(Y, m_Deferred(tX)));
|
|
|
|
}
|
|
|
|
{
|
|
|
|
const Value *tX = X;
|
|
|
|
EXPECT_TRUE(match(X, m_Deferred(tX)));
|
|
|
|
EXPECT_FALSE(match(Y, m_Deferred(tX)));
|
|
|
|
}
|
|
|
|
{
|
|
|
|
Value *const tX = X;
|
|
|
|
EXPECT_TRUE(match(X, m_Deferred(tX)));
|
|
|
|
EXPECT_FALSE(match(Y, m_Deferred(tX)));
|
|
|
|
}
|
|
|
|
{
|
|
|
|
const Value *const tX = X;
|
|
|
|
EXPECT_TRUE(match(X, m_Deferred(tX)));
|
|
|
|
EXPECT_FALSE(match(Y, m_Deferred(tX)));
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
Value *tX = nullptr;
|
|
|
|
EXPECT_TRUE(match(IRB.CreateAnd(X, X), m_And(m_Value(tX), m_Deferred(tX))));
|
|
|
|
EXPECT_EQ(tX, X);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
Value *tX = nullptr;
|
|
|
|
EXPECT_FALSE(
|
|
|
|
match(IRB.CreateAnd(X, Y), m_c_And(m_Value(tX), m_Deferred(tX))));
|
|
|
|
}
|
|
|
|
|
|
|
|
auto checkMatch = [X, Y](Value *Pattern) {
|
|
|
|
Value *tX = nullptr, *tY = nullptr;
|
|
|
|
EXPECT_TRUE(match(
|
|
|
|
Pattern, m_c_And(m_Value(tX), m_c_And(m_Deferred(tX), m_Value(tY)))));
|
|
|
|
EXPECT_EQ(tX, X);
|
|
|
|
EXPECT_EQ(tY, Y);
|
|
|
|
};
|
|
|
|
|
|
|
|
checkMatch(IRB.CreateAnd(X, IRB.CreateAnd(X, Y)));
|
|
|
|
checkMatch(IRB.CreateAnd(X, IRB.CreateAnd(Y, X)));
|
|
|
|
checkMatch(IRB.CreateAnd(IRB.CreateAnd(X, Y), X));
|
|
|
|
checkMatch(IRB.CreateAnd(IRB.CreateAnd(Y, X), X));
|
|
|
|
}
|
|
|
|
|
2014-01-05 10:07:20 +08:00
|
|
|
TEST_F(PatternMatchTest, FloatingPointOrderedMin) {
|
2014-01-05 10:23:11 +08:00
|
|
|
Type *FltTy = IRB.getFloatTy();
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
Value *L = ConstantFP::get(FltTy, 1.0);
|
|
|
|
Value *R = ConstantFP::get(FltTy, 2.0);
|
2014-01-05 10:07:20 +08:00
|
|
|
Value *MatchL, *MatchR;
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
|
|
|
|
// Test OLT.
|
2014-01-05 10:23:11 +08:00
|
|
|
EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), L, R)));
|
2014-01-05 10:07:20 +08:00
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
|
|
|
|
// Test OLE.
|
2014-01-05 10:23:11 +08:00
|
|
|
EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), L, R)));
|
2014-01-05 10:07:20 +08:00
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
|
|
|
|
// Test no match on OGE.
|
2014-01-05 10:23:11 +08:00
|
|
|
EXPECT_FALSE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), L, R)));
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
|
|
|
|
// Test no match on OGT.
|
2014-01-05 10:23:11 +08:00
|
|
|
EXPECT_FALSE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), L, R)));
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
|
2017-06-14 01:18:45 +08:00
|
|
|
// Test inverted selects. Note, that this "inverts" the ordering, e.g.:
|
|
|
|
// %cmp = fcmp oge L, R
|
|
|
|
// %min = select %cmp R, L
|
|
|
|
// Given L == NaN
|
|
|
|
// the above is expanded to %cmp == false ==> %min = L
|
|
|
|
// which is true for UnordFMin, not OrdFMin, so test that:
|
|
|
|
|
|
|
|
// [OU]GE with inverted select.
|
|
|
|
EXPECT_FALSE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
|
2014-01-05 10:23:11 +08:00
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), R, L)));
|
2017-06-14 01:18:45 +08:00
|
|
|
EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), R, L)));
|
2014-01-05 10:07:20 +08:00
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
|
2017-06-14 01:18:45 +08:00
|
|
|
// [OU]GT with inverted select.
|
|
|
|
EXPECT_FALSE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
|
2014-01-05 10:23:11 +08:00
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), R, L)));
|
2017-06-14 01:18:45 +08:00
|
|
|
EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), R, L)));
|
2014-01-05 10:07:20 +08:00
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
}
|
|
|
|
|
2014-01-05 10:07:20 +08:00
|
|
|
TEST_F(PatternMatchTest, FloatingPointOrderedMax) {
|
2014-01-05 10:23:11 +08:00
|
|
|
Type *FltTy = IRB.getFloatTy();
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
Value *L = ConstantFP::get(FltTy, 1.0);
|
|
|
|
Value *R = ConstantFP::get(FltTy, 2.0);
|
2014-01-05 10:07:20 +08:00
|
|
|
Value *MatchL, *MatchR;
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
|
|
|
|
// Test OGT.
|
2014-01-05 10:23:11 +08:00
|
|
|
EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), L, R)));
|
2014-01-05 10:07:20 +08:00
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
|
|
|
|
// Test OGE.
|
2014-01-05 10:23:11 +08:00
|
|
|
EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), L, R)));
|
2014-01-05 10:07:20 +08:00
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
|
|
|
|
// Test no match on OLE.
|
2014-01-05 10:23:11 +08:00
|
|
|
EXPECT_FALSE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), L, R)));
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
|
|
|
|
// Test no match on OLT.
|
2014-01-05 10:23:11 +08:00
|
|
|
EXPECT_FALSE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), L, R)));
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
|
2017-06-14 01:18:45 +08:00
|
|
|
|
|
|
|
// Test inverted selects. Note, that this "inverts" the ordering, e.g.:
|
|
|
|
// %cmp = fcmp ole L, R
|
|
|
|
// %max = select %cmp, R, L
|
|
|
|
// Given L == NaN,
|
|
|
|
// the above is expanded to %cmp == false ==> %max == L
|
|
|
|
// which is true for UnordFMax, not OrdFMax, so test that:
|
|
|
|
|
|
|
|
// [OU]LE with inverted select.
|
|
|
|
EXPECT_FALSE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), R, L)));
|
2014-01-05 10:23:11 +08:00
|
|
|
EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
|
2017-06-14 01:18:45 +08:00
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpULE(L, R), R, L)));
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
|
|
|
|
2017-06-14 01:18:45 +08:00
|
|
|
// [OUT]LT with inverted select.
|
|
|
|
EXPECT_FALSE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), R, L)));
|
2014-01-05 10:23:11 +08:00
|
|
|
EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
|
2017-06-14 01:18:45 +08:00
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), R, L)));
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
|
|
|
}
|
|
|
|
|
2014-01-05 10:07:20 +08:00
|
|
|
TEST_F(PatternMatchTest, FloatingPointUnorderedMin) {
|
2014-01-05 10:23:11 +08:00
|
|
|
Type *FltTy = IRB.getFloatTy();
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
Value *L = ConstantFP::get(FltTy, 1.0);
|
|
|
|
Value *R = ConstantFP::get(FltTy, 2.0);
|
2014-01-05 10:07:20 +08:00
|
|
|
Value *MatchL, *MatchR;
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
|
|
|
|
// Test ULT.
|
2014-01-05 10:23:11 +08:00
|
|
|
EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), L, R)));
|
2014-01-05 10:07:20 +08:00
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
|
|
|
|
// Test ULE.
|
2014-01-05 10:23:11 +08:00
|
|
|
EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpULE(L, R), L, R)));
|
2014-01-05 10:07:20 +08:00
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
|
|
|
|
// Test no match on UGE.
|
2014-01-05 10:23:11 +08:00
|
|
|
EXPECT_FALSE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), L, R)));
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
|
|
|
|
// Test no match on UGT.
|
2014-01-05 10:23:11 +08:00
|
|
|
EXPECT_FALSE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), L, R)));
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
|
2017-06-14 01:18:45 +08:00
|
|
|
// Test inverted selects. Note, that this "inverts" the ordering, e.g.:
|
|
|
|
// %cmp = fcmp uge L, R
|
|
|
|
// %min = select %cmp R, L
|
|
|
|
// Given L == NaN
|
|
|
|
// the above is expanded to %cmp == true ==> %min = R
|
|
|
|
// which is true for OrdFMin, not UnordFMin, so test that:
|
|
|
|
|
|
|
|
// [UO]GE with inverted select.
|
|
|
|
EXPECT_FALSE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
|
2014-01-05 10:23:11 +08:00
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), R, L)));
|
2017-06-14 01:18:45 +08:00
|
|
|
EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), R, L)));
|
2014-01-05 10:07:20 +08:00
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
|
2017-06-14 01:18:45 +08:00
|
|
|
// [UO]GT with inverted select.
|
|
|
|
EXPECT_FALSE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
|
2014-01-05 10:23:11 +08:00
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), R, L)));
|
2017-06-14 01:18:45 +08:00
|
|
|
EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), R, L)));
|
2014-01-05 10:07:20 +08:00
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
}
|
|
|
|
|
2014-01-05 10:07:20 +08:00
|
|
|
TEST_F(PatternMatchTest, FloatingPointUnorderedMax) {
|
2014-01-05 10:23:11 +08:00
|
|
|
Type *FltTy = IRB.getFloatTy();
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
Value *L = ConstantFP::get(FltTy, 1.0);
|
|
|
|
Value *R = ConstantFP::get(FltTy, 2.0);
|
2014-01-05 10:07:20 +08:00
|
|
|
Value *MatchL, *MatchR;
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
|
|
|
|
// Test UGT.
|
2014-01-05 10:23:11 +08:00
|
|
|
EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), L, R)));
|
2014-01-05 10:07:20 +08:00
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
|
|
|
|
// Test UGE.
|
2014-01-05 10:23:11 +08:00
|
|
|
EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), L, R)));
|
2014-01-05 10:07:20 +08:00
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
|
|
|
|
// Test no match on ULE.
|
2014-01-05 10:23:11 +08:00
|
|
|
EXPECT_FALSE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpULE(L, R), L, R)));
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
|
|
|
|
// Test no match on ULT.
|
2014-01-05 10:23:11 +08:00
|
|
|
EXPECT_FALSE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), L, R)));
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
|
2017-06-14 01:18:45 +08:00
|
|
|
// Test inverted selects. Note, that this "inverts" the ordering, e.g.:
|
|
|
|
// %cmp = fcmp ule L, R
|
|
|
|
// %max = select %cmp R, L
|
|
|
|
// Given L == NaN
|
|
|
|
// the above is expanded to %cmp == true ==> %max = R
|
|
|
|
// which is true for OrdFMax, not UnordFMax, so test that:
|
|
|
|
|
|
|
|
// [UO]LE with inverted select.
|
|
|
|
EXPECT_FALSE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
|
2014-01-05 10:23:11 +08:00
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpULE(L, R), R, L)));
|
2017-06-14 01:18:45 +08:00
|
|
|
EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), R, L)));
|
2014-01-05 10:07:20 +08:00
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
|
2017-06-14 01:18:45 +08:00
|
|
|
// [UO]LT with inverted select.
|
|
|
|
EXPECT_FALSE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
|
2014-01-05 10:23:11 +08:00
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), R, L)));
|
2017-06-14 01:18:45 +08:00
|
|
|
EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), R, L)));
|
2014-01-05 10:07:20 +08:00
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
}
|
|
|
|
|
2014-01-05 11:28:29 +08:00
|
|
|
TEST_F(PatternMatchTest, OverflowingBinOps) {
|
|
|
|
Value *L = IRB.getInt32(1);
|
|
|
|
Value *R = IRB.getInt32(2);
|
|
|
|
Value *MatchL, *MatchR;
|
|
|
|
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_NSWAdd(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNSWAdd(L, R)));
|
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
2014-06-09 06:29:17 +08:00
|
|
|
MatchL = MatchR = nullptr;
|
2014-01-05 11:28:29 +08:00
|
|
|
EXPECT_TRUE(
|
|
|
|
m_NSWSub(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNSWSub(L, R)));
|
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
2014-06-09 06:29:17 +08:00
|
|
|
MatchL = MatchR = nullptr;
|
2014-01-05 11:28:29 +08:00
|
|
|
EXPECT_TRUE(
|
|
|
|
m_NSWMul(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNSWMul(L, R)));
|
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
2014-06-09 06:29:17 +08:00
|
|
|
MatchL = MatchR = nullptr;
|
2014-01-05 11:28:29 +08:00
|
|
|
EXPECT_TRUE(m_NSWShl(m_Value(MatchL), m_Value(MatchR)).match(
|
|
|
|
IRB.CreateShl(L, R, "", /* NUW */ false, /* NSW */ true)));
|
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
|
|
|
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_NUWAdd(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNUWAdd(L, R)));
|
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
2014-06-09 06:29:17 +08:00
|
|
|
MatchL = MatchR = nullptr;
|
2014-01-05 11:28:29 +08:00
|
|
|
EXPECT_TRUE(
|
|
|
|
m_NUWSub(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNUWSub(L, R)));
|
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
2014-06-09 06:29:17 +08:00
|
|
|
MatchL = MatchR = nullptr;
|
2014-01-05 11:28:29 +08:00
|
|
|
EXPECT_TRUE(
|
|
|
|
m_NUWMul(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNUWMul(L, R)));
|
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
2014-06-09 06:29:17 +08:00
|
|
|
MatchL = MatchR = nullptr;
|
2014-01-05 11:28:29 +08:00
|
|
|
EXPECT_TRUE(m_NUWShl(m_Value(MatchL), m_Value(MatchR)).match(
|
|
|
|
IRB.CreateShl(L, R, "", /* NUW */ true, /* NSW */ false)));
|
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
|
|
|
|
|
|
|
EXPECT_FALSE(m_NSWAdd(m_Value(), m_Value()).match(IRB.CreateAdd(L, R)));
|
|
|
|
EXPECT_FALSE(m_NSWAdd(m_Value(), m_Value()).match(IRB.CreateNUWAdd(L, R)));
|
|
|
|
EXPECT_FALSE(m_NSWAdd(m_Value(), m_Value()).match(IRB.CreateNSWSub(L, R)));
|
|
|
|
EXPECT_FALSE(m_NSWSub(m_Value(), m_Value()).match(IRB.CreateSub(L, R)));
|
|
|
|
EXPECT_FALSE(m_NSWSub(m_Value(), m_Value()).match(IRB.CreateNUWSub(L, R)));
|
|
|
|
EXPECT_FALSE(m_NSWSub(m_Value(), m_Value()).match(IRB.CreateNSWAdd(L, R)));
|
|
|
|
EXPECT_FALSE(m_NSWMul(m_Value(), m_Value()).match(IRB.CreateMul(L, R)));
|
|
|
|
EXPECT_FALSE(m_NSWMul(m_Value(), m_Value()).match(IRB.CreateNUWMul(L, R)));
|
|
|
|
EXPECT_FALSE(m_NSWMul(m_Value(), m_Value()).match(IRB.CreateNSWAdd(L, R)));
|
|
|
|
EXPECT_FALSE(m_NSWShl(m_Value(), m_Value()).match(IRB.CreateShl(L, R)));
|
|
|
|
EXPECT_FALSE(m_NSWShl(m_Value(), m_Value()).match(
|
|
|
|
IRB.CreateShl(L, R, "", /* NUW */ true, /* NSW */ false)));
|
|
|
|
EXPECT_FALSE(m_NSWShl(m_Value(), m_Value()).match(IRB.CreateNSWAdd(L, R)));
|
|
|
|
|
|
|
|
EXPECT_FALSE(m_NUWAdd(m_Value(), m_Value()).match(IRB.CreateAdd(L, R)));
|
|
|
|
EXPECT_FALSE(m_NUWAdd(m_Value(), m_Value()).match(IRB.CreateNSWAdd(L, R)));
|
|
|
|
EXPECT_FALSE(m_NUWAdd(m_Value(), m_Value()).match(IRB.CreateNUWSub(L, R)));
|
|
|
|
EXPECT_FALSE(m_NUWSub(m_Value(), m_Value()).match(IRB.CreateSub(L, R)));
|
|
|
|
EXPECT_FALSE(m_NUWSub(m_Value(), m_Value()).match(IRB.CreateNSWSub(L, R)));
|
|
|
|
EXPECT_FALSE(m_NUWSub(m_Value(), m_Value()).match(IRB.CreateNUWAdd(L, R)));
|
|
|
|
EXPECT_FALSE(m_NUWMul(m_Value(), m_Value()).match(IRB.CreateMul(L, R)));
|
|
|
|
EXPECT_FALSE(m_NUWMul(m_Value(), m_Value()).match(IRB.CreateNSWMul(L, R)));
|
|
|
|
EXPECT_FALSE(m_NUWMul(m_Value(), m_Value()).match(IRB.CreateNUWAdd(L, R)));
|
|
|
|
EXPECT_FALSE(m_NUWShl(m_Value(), m_Value()).match(IRB.CreateShl(L, R)));
|
|
|
|
EXPECT_FALSE(m_NUWShl(m_Value(), m_Value()).match(
|
|
|
|
IRB.CreateShl(L, R, "", /* NUW */ false, /* NSW */ true)));
|
|
|
|
EXPECT_FALSE(m_NUWShl(m_Value(), m_Value()).match(IRB.CreateNUWAdd(L, R)));
|
|
|
|
}
|
|
|
|
|
2018-06-20 15:27:45 +08:00
|
|
|
TEST_F(PatternMatchTest, LoadStoreOps) {
|
|
|
|
// Create this load/store sequence:
|
|
|
|
//
|
|
|
|
// %p = alloca i32*
|
|
|
|
// %0 = load i32*, i32** %p
|
|
|
|
// store i32 42, i32* %0
|
|
|
|
|
|
|
|
Value *Alloca = IRB.CreateAlloca(IRB.getInt32Ty());
|
2019-02-02 04:44:24 +08:00
|
|
|
Value *LoadInst = IRB.CreateLoad(IRB.getInt32Ty(), Alloca);
|
2018-06-20 15:27:45 +08:00
|
|
|
Value *FourtyTwo = IRB.getInt32(42);
|
|
|
|
Value *StoreInst = IRB.CreateStore(FourtyTwo, Alloca);
|
|
|
|
Value *MatchLoad, *MatchStoreVal, *MatchStorePointer;
|
|
|
|
|
|
|
|
EXPECT_TRUE(m_Load(m_Value(MatchLoad)).match(LoadInst));
|
|
|
|
EXPECT_EQ(Alloca, MatchLoad);
|
|
|
|
|
|
|
|
EXPECT_TRUE(m_Load(m_Specific(Alloca)).match(LoadInst));
|
|
|
|
|
|
|
|
EXPECT_FALSE(m_Load(m_Value(MatchLoad)).match(Alloca));
|
|
|
|
|
|
|
|
EXPECT_TRUE(m_Store(m_Value(MatchStoreVal), m_Value(MatchStorePointer))
|
|
|
|
.match(StoreInst));
|
|
|
|
EXPECT_EQ(FourtyTwo, MatchStoreVal);
|
|
|
|
EXPECT_EQ(Alloca, MatchStorePointer);
|
|
|
|
|
|
|
|
EXPECT_FALSE(m_Store(m_Value(MatchStoreVal), m_Value(MatchStorePointer))
|
|
|
|
.match(Alloca));
|
|
|
|
|
|
|
|
EXPECT_TRUE(m_Store(m_SpecificInt(42), m_Specific(Alloca))
|
|
|
|
.match(StoreInst));
|
|
|
|
EXPECT_FALSE(m_Store(m_SpecificInt(42), m_Specific(FourtyTwo))
|
|
|
|
.match(StoreInst));
|
|
|
|
EXPECT_FALSE(m_Store(m_SpecificInt(43), m_Specific(Alloca))
|
|
|
|
.match(StoreInst));
|
|
|
|
}
|
|
|
|
|
2018-03-28 23:39:00 +08:00
|
|
|
TEST_F(PatternMatchTest, VectorOps) {
|
|
|
|
// Build up small tree of vector operations
|
|
|
|
//
|
|
|
|
// Val = 0 + 1
|
|
|
|
// Val2 = Val + 3
|
|
|
|
// VI1 = insertelement <2 x i8> undef, i8 1, i32 0 = <1, undef>
|
|
|
|
// VI2 = insertelement <2 x i8> %VI1, i8 %Val2, i8 %Val = <1, 4>
|
|
|
|
// VI3 = insertelement <2 x i8> %VI1, i8 %Val2, i32 1 = <1, 4>
|
|
|
|
// VI4 = insertelement <2 x i8> %VI1, i8 2, i8 %Val = <1, 2>
|
|
|
|
//
|
|
|
|
// SI1 = shufflevector <2 x i8> %VI1, <2 x i8> undef, zeroinitializer
|
|
|
|
// SI2 = shufflevector <2 x i8> %VI3, <2 x i8> %VI4, <2 x i8> <i8 0, i8 2>
|
|
|
|
// SI3 = shufflevector <2 x i8> %VI3, <2 x i8> undef, zeroinitializer
|
|
|
|
// SI4 = shufflevector <2 x i8> %VI4, <2 x i8> undef, zeroinitializer
|
|
|
|
//
|
|
|
|
// SP1 = VectorSplat(2, i8 2)
|
|
|
|
// SP2 = VectorSplat(2, i8 %Val)
|
|
|
|
Type *VecTy = VectorType::get(IRB.getInt8Ty(), 2);
|
|
|
|
Type *i32 = IRB.getInt32Ty();
|
|
|
|
Type *i32VecTy = VectorType::get(i32, 2);
|
|
|
|
|
|
|
|
Value *Val = IRB.CreateAdd(IRB.getInt8(0), IRB.getInt8(1));
|
|
|
|
Value *Val2 = IRB.CreateAdd(Val, IRB.getInt8(3));
|
|
|
|
|
|
|
|
SmallVector<Constant *, 2> VecElemIdxs;
|
|
|
|
VecElemIdxs.push_back(ConstantInt::get(i32, 0));
|
|
|
|
VecElemIdxs.push_back(ConstantInt::get(i32, 2));
|
|
|
|
auto *IdxVec = ConstantVector::get(VecElemIdxs);
|
|
|
|
|
|
|
|
Value *UndefVec = UndefValue::get(VecTy);
|
|
|
|
Value *VI1 = IRB.CreateInsertElement(UndefVec, IRB.getInt8(1), (uint64_t)0);
|
|
|
|
Value *VI2 = IRB.CreateInsertElement(VI1, Val2, Val);
|
|
|
|
Value *VI3 = IRB.CreateInsertElement(VI1, Val2, (uint64_t)1);
|
|
|
|
Value *VI4 = IRB.CreateInsertElement(VI1, IRB.getInt8(2), Val);
|
|
|
|
|
|
|
|
Value *EX1 = IRB.CreateExtractElement(VI4, Val);
|
|
|
|
Value *EX2 = IRB.CreateExtractElement(VI4, (uint64_t)0);
|
|
|
|
Value *EX3 = IRB.CreateExtractElement(IdxVec, (uint64_t)1);
|
|
|
|
|
|
|
|
Value *Zero = ConstantAggregateZero::get(i32VecTy);
|
|
|
|
Value *SI1 = IRB.CreateShuffleVector(VI1, UndefVec, Zero);
|
|
|
|
Value *SI2 = IRB.CreateShuffleVector(VI3, VI4, IdxVec);
|
|
|
|
Value *SI3 = IRB.CreateShuffleVector(VI3, UndefVec, Zero);
|
|
|
|
Value *SI4 = IRB.CreateShuffleVector(VI4, UndefVec, Zero);
|
|
|
|
|
|
|
|
Value *SP1 = IRB.CreateVectorSplat(2, IRB.getInt8(2));
|
|
|
|
Value *SP2 = IRB.CreateVectorSplat(2, Val);
|
|
|
|
|
|
|
|
Value *A = nullptr, *B = nullptr, *C = nullptr;
|
|
|
|
|
|
|
|
// Test matching insertelement
|
|
|
|
EXPECT_TRUE(match(VI1, m_InsertElement(m_Value(), m_Value(), m_Value())));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
match(VI1, m_InsertElement(m_Undef(), m_ConstantInt(), m_ConstantInt())));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
match(VI1, m_InsertElement(m_Undef(), m_ConstantInt(), m_Zero())));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
match(VI1, m_InsertElement(m_Undef(), m_SpecificInt(1), m_Zero())));
|
|
|
|
EXPECT_TRUE(match(VI2, m_InsertElement(m_Value(), m_Value(), m_Value())));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
match(VI2, m_InsertElement(m_Value(), m_Value(), m_ConstantInt())));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
match(VI2, m_InsertElement(m_Value(), m_ConstantInt(), m_Value())));
|
|
|
|
EXPECT_FALSE(match(VI2, m_InsertElement(m_Constant(), m_Value(), m_Value())));
|
|
|
|
EXPECT_TRUE(match(VI3, m_InsertElement(m_Value(A), m_Value(B), m_Value(C))));
|
|
|
|
EXPECT_TRUE(A == VI1);
|
|
|
|
EXPECT_TRUE(B == Val2);
|
|
|
|
EXPECT_TRUE(isa<ConstantInt>(C));
|
|
|
|
A = B = C = nullptr; // reset
|
|
|
|
|
|
|
|
// Test matching extractelement
|
|
|
|
EXPECT_TRUE(match(EX1, m_ExtractElement(m_Value(A), m_Value(B))));
|
|
|
|
EXPECT_TRUE(A == VI4);
|
|
|
|
EXPECT_TRUE(B == Val);
|
|
|
|
A = B = C = nullptr; // reset
|
|
|
|
EXPECT_FALSE(match(EX1, m_ExtractElement(m_Value(), m_ConstantInt())));
|
|
|
|
EXPECT_TRUE(match(EX2, m_ExtractElement(m_Value(), m_ConstantInt())));
|
|
|
|
EXPECT_TRUE(match(EX3, m_ExtractElement(m_Constant(), m_ConstantInt())));
|
|
|
|
|
|
|
|
// Test matching shufflevector
|
|
|
|
EXPECT_TRUE(match(SI1, m_ShuffleVector(m_Value(), m_Undef(), m_Zero())));
|
|
|
|
EXPECT_TRUE(match(SI2, m_ShuffleVector(m_Value(A), m_Value(B), m_Value(C))));
|
|
|
|
EXPECT_TRUE(A == VI3);
|
|
|
|
EXPECT_TRUE(B == VI4);
|
|
|
|
EXPECT_TRUE(C == IdxVec);
|
|
|
|
A = B = C = nullptr; // reset
|
|
|
|
|
|
|
|
// Test matching the vector splat pattern
|
|
|
|
EXPECT_TRUE(match(
|
|
|
|
SI1,
|
|
|
|
m_ShuffleVector(m_InsertElement(m_Undef(), m_SpecificInt(1), m_Zero()),
|
|
|
|
m_Undef(), m_Zero())));
|
|
|
|
EXPECT_FALSE(match(
|
|
|
|
SI3, m_ShuffleVector(m_InsertElement(m_Undef(), m_Value(), m_Zero()),
|
|
|
|
m_Undef(), m_Zero())));
|
|
|
|
EXPECT_FALSE(match(
|
|
|
|
SI4, m_ShuffleVector(m_InsertElement(m_Undef(), m_Value(), m_Zero()),
|
|
|
|
m_Undef(), m_Zero())));
|
|
|
|
EXPECT_TRUE(match(
|
|
|
|
SP1,
|
|
|
|
m_ShuffleVector(m_InsertElement(m_Undef(), m_SpecificInt(2), m_Zero()),
|
|
|
|
m_Undef(), m_Zero())));
|
|
|
|
EXPECT_TRUE(match(
|
|
|
|
SP2, m_ShuffleVector(m_InsertElement(m_Undef(), m_Value(A), m_Zero()),
|
|
|
|
m_Undef(), m_Zero())));
|
|
|
|
EXPECT_TRUE(A == Val);
|
|
|
|
}
|
|
|
|
|
2018-11-21 00:08:19 +08:00
|
|
|
TEST_F(PatternMatchTest, VectorUndefInt) {
|
|
|
|
Type *ScalarTy = IRB.getInt8Ty();
|
|
|
|
Type *VectorTy = VectorType::get(ScalarTy, 4);
|
|
|
|
Constant *ScalarUndef = UndefValue::get(ScalarTy);
|
|
|
|
Constant *VectorUndef = UndefValue::get(VectorTy);
|
|
|
|
Constant *ScalarZero = Constant::getNullValue(ScalarTy);
|
|
|
|
Constant *VectorZero = Constant::getNullValue(VectorTy);
|
|
|
|
|
|
|
|
SmallVector<Constant *, 4> Elems;
|
|
|
|
Elems.push_back(ScalarUndef);
|
|
|
|
Elems.push_back(ScalarZero);
|
|
|
|
Elems.push_back(ScalarUndef);
|
|
|
|
Elems.push_back(ScalarZero);
|
|
|
|
Constant *VectorZeroUndef = ConstantVector::get(Elems);
|
|
|
|
|
|
|
|
EXPECT_TRUE(match(ScalarUndef, m_Undef()));
|
|
|
|
EXPECT_TRUE(match(VectorUndef, m_Undef()));
|
|
|
|
EXPECT_FALSE(match(ScalarZero, m_Undef()));
|
|
|
|
EXPECT_FALSE(match(VectorZero, m_Undef()));
|
|
|
|
EXPECT_FALSE(match(VectorZeroUndef, m_Undef()));
|
|
|
|
|
|
|
|
EXPECT_FALSE(match(ScalarUndef, m_Zero()));
|
|
|
|
EXPECT_FALSE(match(VectorUndef, m_Zero()));
|
|
|
|
EXPECT_TRUE(match(ScalarZero, m_Zero()));
|
|
|
|
EXPECT_TRUE(match(VectorZero, m_Zero()));
|
|
|
|
EXPECT_TRUE(match(VectorZeroUndef, m_Zero()));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(PatternMatchTest, VectorUndefFloat) {
|
|
|
|
Type *ScalarTy = IRB.getFloatTy();
|
|
|
|
Type *VectorTy = VectorType::get(ScalarTy, 4);
|
|
|
|
Constant *ScalarUndef = UndefValue::get(ScalarTy);
|
|
|
|
Constant *VectorUndef = UndefValue::get(VectorTy);
|
|
|
|
Constant *ScalarZero = Constant::getNullValue(ScalarTy);
|
|
|
|
Constant *VectorZero = Constant::getNullValue(VectorTy);
|
|
|
|
|
|
|
|
SmallVector<Constant *, 4> Elems;
|
|
|
|
Elems.push_back(ScalarUndef);
|
|
|
|
Elems.push_back(ScalarZero);
|
|
|
|
Elems.push_back(ScalarUndef);
|
|
|
|
Elems.push_back(ScalarZero);
|
|
|
|
Constant *VectorZeroUndef = ConstantVector::get(Elems);
|
|
|
|
|
|
|
|
EXPECT_TRUE(match(ScalarUndef, m_Undef()));
|
|
|
|
EXPECT_TRUE(match(VectorUndef, m_Undef()));
|
|
|
|
EXPECT_FALSE(match(ScalarZero, m_Undef()));
|
|
|
|
EXPECT_FALSE(match(VectorZero, m_Undef()));
|
|
|
|
EXPECT_FALSE(match(VectorZeroUndef, m_Undef()));
|
|
|
|
|
|
|
|
EXPECT_FALSE(match(ScalarUndef, m_AnyZeroFP()));
|
|
|
|
EXPECT_FALSE(match(VectorUndef, m_AnyZeroFP()));
|
|
|
|
EXPECT_TRUE(match(ScalarZero, m_AnyZeroFP()));
|
|
|
|
EXPECT_TRUE(match(VectorZero, m_AnyZeroFP()));
|
|
|
|
EXPECT_TRUE(match(VectorZeroUndef, m_AnyZeroFP()));
|
|
|
|
}
|
|
|
|
|
2016-08-13 06:16:05 +08:00
|
|
|
template <typename T> struct MutableConstTest : PatternMatchTest { };
|
|
|
|
|
|
|
|
typedef ::testing::Types<std::tuple<Value*, Instruction*>,
|
|
|
|
std::tuple<const Value*, const Instruction *>>
|
|
|
|
MutableConstTestTypes;
|
|
|
|
TYPED_TEST_CASE(MutableConstTest, MutableConstTestTypes);
|
|
|
|
|
|
|
|
TYPED_TEST(MutableConstTest, ICmp) {
|
|
|
|
auto &IRB = PatternMatchTest::IRB;
|
|
|
|
|
|
|
|
typedef typename std::tuple_element<0, TypeParam>::type ValueType;
|
|
|
|
typedef typename std::tuple_element<1, TypeParam>::type InstructionType;
|
|
|
|
|
|
|
|
Value *L = IRB.getInt32(1);
|
|
|
|
Value *R = IRB.getInt32(2);
|
|
|
|
ICmpInst::Predicate Pred = ICmpInst::ICMP_UGT;
|
|
|
|
|
|
|
|
ValueType MatchL;
|
|
|
|
ValueType MatchR;
|
|
|
|
ICmpInst::Predicate MatchPred;
|
|
|
|
|
|
|
|
EXPECT_TRUE(m_ICmp(MatchPred, m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
|
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
|
|
|
}
|
|
|
|
|
PatternMatch: Matcher for (un)ordered floating point min/max
Add support for matching 'ordered' and 'unordered' floating point min/max
constructs.
In LLVM we can express min/max functions as a combination of compare and select.
We have support for matching such constructs for integers but not for floating
point. In floating point math there is no total order because of the presence of
'NaN'. Therefore, we have to be careful to preserve the original fcmp semantics
when interpreting floating point compare select combinations as a minimum or
maximum function. The resulting 'ordered/unordered' floating point maximum
function has to select the same value as the select/fcmp combination it is based
on.
ordered_max(x,y) = max(x,y) iff x and y are not NaN, y otherwise
unordered_max(x,y) = max(x,y) iff x and y are not NaN, x otherwise
ordered_min(x,y) = min(x,y) iff x and y are not NaN, y otherwise
unordered_min(x,y) = min(x,y) iff x and y are not NaN, x otherwise
This matches the behavior of the underlying select(fcmp(olt/ult/.., L, R), L, R)
construct.
Any code using this predicate has to preserve this semantics.
A follow-up patch will use this to implement floating point min/max reductions
in the vectorizer.
radar://13723044
llvm-svn: 181143
2013-05-05 09:54:46 +08:00
|
|
|
} // anonymous namespace.
|