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 03:54:46 +02:00
|
|
|
//===---- llvm/unittest/IR/PatternMatch.cpp - PatternMatch unit tests ----===//
|
|
|
|
//
|
2019-01-19 09:50:56 +01: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 03:54:46 +02:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-06-06 13:06:56 +02:00
|
|
|
#include "llvm/IR/PatternMatch.h"
|
2019-07-25 15:34:24 +02:00
|
|
|
#include "llvm/ADT/APSInt.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 03:54:46 +02: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 03:07:20 +01: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 03:54:46 +02:00
|
|
|
#include "llvm/IR/IRBuilder.h"
|
2014-01-05 03:07:20 +01: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 03:54:46 +02:00
|
|
|
#include "llvm/IR/LLVMContext.h"
|
|
|
|
#include "llvm/IR/MDBuilder.h"
|
2014-01-05 03:07:20 +01:00
|
|
|
#include "llvm/IR/Module.h"
|
2014-03-04 13:05:47 +01: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 03:54:46 +02:00
|
|
|
#include "llvm/IR/Operator.h"
|
2014-01-05 03:07:20 +01: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 03:54:46 +02:00
|
|
|
#include "gtest/gtest.h"
|
|
|
|
|
2014-01-05 03:07:20 +01: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 03:54:46 +02:00
|
|
|
using namespace llvm::PatternMatch;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2014-01-05 03:07:20 +01:00
|
|
|
struct PatternMatchTest : ::testing::Test {
|
|
|
|
LLVMContext Ctx;
|
2014-03-06 06:51:42 +01:00
|
|
|
std::unique_ptr<Module> M;
|
2014-01-05 03:07:20 +01:00
|
|
|
Function *F;
|
|
|
|
BasicBlock *BB;
|
2016-03-13 22:05:13 +01:00
|
|
|
IRBuilder<NoFolder> IRB;
|
2014-01-05 03:07:20 +01:00
|
|
|
|
|
|
|
PatternMatchTest()
|
|
|
|
: M(new Module("PatternMatchTestModule", Ctx)),
|
|
|
|
F(Function::Create(
|
|
|
|
FunctionType::get(Type::getVoidTy(Ctx), /* IsVarArg */ false),
|
|
|
|
Function::ExternalLinkage, "f", M.get())),
|
2019-07-15 18:43:36 +02:00
|
|
|
BB(BasicBlock::Create(Ctx, "entry", F)), IRB(BB) {}
|
2014-01-05 03:07:20 +01:00
|
|
|
};
|
|
|
|
|
2014-01-05 10:14:53 +01: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));
|
|
|
|
}
|
|
|
|
|
2019-07-10 18:07:35 +02:00
|
|
|
TEST_F(PatternMatchTest, SpecificIntEQ) {
|
|
|
|
Type *IntTy = IRB.getInt32Ty();
|
|
|
|
unsigned BitWidth = IntTy->getScalarSizeInBits();
|
|
|
|
|
|
|
|
Value *Zero = ConstantInt::get(IntTy, 0);
|
|
|
|
Value *One = ConstantInt::get(IntTy, 1);
|
|
|
|
Value *NegOne = ConstantInt::get(IntTy, -1);
|
|
|
|
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_EQ, APInt(BitWidth, 0))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_EQ, APInt(BitWidth, 0))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_EQ, APInt(BitWidth, 0))
|
|
|
|
.match(NegOne));
|
|
|
|
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_EQ, APInt(BitWidth, 1))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_EQ, APInt(BitWidth, 1))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_EQ, APInt(BitWidth, 1))
|
|
|
|
.match(NegOne));
|
|
|
|
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_EQ, APInt(BitWidth, -1))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_EQ, APInt(BitWidth, -1))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_EQ, APInt(BitWidth, -1))
|
|
|
|
.match(NegOne));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(PatternMatchTest, SpecificIntNE) {
|
|
|
|
Type *IntTy = IRB.getInt32Ty();
|
|
|
|
unsigned BitWidth = IntTy->getScalarSizeInBits();
|
|
|
|
|
|
|
|
Value *Zero = ConstantInt::get(IntTy, 0);
|
|
|
|
Value *One = ConstantInt::get(IntTy, 1);
|
|
|
|
Value *NegOne = ConstantInt::get(IntTy, -1);
|
|
|
|
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_NE, APInt(BitWidth, 0))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_NE, APInt(BitWidth, 0))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_NE, APInt(BitWidth, 0))
|
|
|
|
.match(NegOne));
|
|
|
|
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_NE, APInt(BitWidth, 1))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_NE, APInt(BitWidth, 1))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_NE, APInt(BitWidth, 1))
|
|
|
|
.match(NegOne));
|
|
|
|
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_NE, APInt(BitWidth, -1))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_NE, APInt(BitWidth, -1))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_NE, APInt(BitWidth, -1))
|
|
|
|
.match(NegOne));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(PatternMatchTest, SpecificIntUGT) {
|
|
|
|
Type *IntTy = IRB.getInt32Ty();
|
|
|
|
unsigned BitWidth = IntTy->getScalarSizeInBits();
|
|
|
|
|
|
|
|
Value *Zero = ConstantInt::get(IntTy, 0);
|
|
|
|
Value *One = ConstantInt::get(IntTy, 1);
|
|
|
|
Value *NegOne = ConstantInt::get(IntTy, -1);
|
|
|
|
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_UGT, APInt(BitWidth, 0))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_UGT, APInt(BitWidth, 0))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_UGT, APInt(BitWidth, 0))
|
|
|
|
.match(NegOne));
|
|
|
|
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_UGT, APInt(BitWidth, 1))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_UGT, APInt(BitWidth, 1))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_UGT, APInt(BitWidth, 1))
|
|
|
|
.match(NegOne));
|
|
|
|
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_UGT, APInt(BitWidth, -1))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_UGT, APInt(BitWidth, -1))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_UGT, APInt(BitWidth, -1))
|
|
|
|
.match(NegOne));
|
|
|
|
}
|
|
|
|
|
2019-12-03 19:17:51 +01:00
|
|
|
TEST_F(PatternMatchTest, SignbitZeroChecks) {
|
|
|
|
Type *IntTy = IRB.getInt32Ty();
|
|
|
|
|
|
|
|
Value *Zero = ConstantInt::get(IntTy, 0);
|
|
|
|
Value *One = ConstantInt::get(IntTy, 1);
|
|
|
|
Value *NegOne = ConstantInt::get(IntTy, -1);
|
|
|
|
|
|
|
|
EXPECT_TRUE(m_Negative().match(NegOne));
|
|
|
|
EXPECT_FALSE(m_NonNegative().match(NegOne));
|
|
|
|
EXPECT_FALSE(m_StrictlyPositive().match(NegOne));
|
|
|
|
EXPECT_TRUE(m_NonPositive().match(NegOne));
|
|
|
|
|
|
|
|
EXPECT_FALSE(m_Negative().match(Zero));
|
|
|
|
EXPECT_TRUE(m_NonNegative().match(Zero));
|
|
|
|
EXPECT_FALSE(m_StrictlyPositive().match(Zero));
|
|
|
|
EXPECT_TRUE(m_NonPositive().match(Zero));
|
|
|
|
|
|
|
|
EXPECT_FALSE(m_Negative().match(One));
|
|
|
|
EXPECT_TRUE(m_NonNegative().match(One));
|
|
|
|
EXPECT_TRUE(m_StrictlyPositive().match(One));
|
|
|
|
EXPECT_FALSE(m_NonPositive().match(One));
|
|
|
|
}
|
|
|
|
|
2019-07-10 18:07:35 +02:00
|
|
|
TEST_F(PatternMatchTest, SpecificIntUGE) {
|
|
|
|
Type *IntTy = IRB.getInt32Ty();
|
|
|
|
unsigned BitWidth = IntTy->getScalarSizeInBits();
|
|
|
|
|
|
|
|
Value *Zero = ConstantInt::get(IntTy, 0);
|
|
|
|
Value *One = ConstantInt::get(IntTy, 1);
|
|
|
|
Value *NegOne = ConstantInt::get(IntTy, -1);
|
|
|
|
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_UGE, APInt(BitWidth, 0))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_UGE, APInt(BitWidth, 0))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_UGE, APInt(BitWidth, 0))
|
|
|
|
.match(NegOne));
|
|
|
|
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_UGE, APInt(BitWidth, 1))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_UGE, APInt(BitWidth, 1))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_UGE, APInt(BitWidth, 1))
|
|
|
|
.match(NegOne));
|
|
|
|
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_UGE, APInt(BitWidth, -1))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_UGE, APInt(BitWidth, -1))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_UGE, APInt(BitWidth, -1))
|
|
|
|
.match(NegOne));
|
|
|
|
}
|
|
|
|
|
2019-06-29 13:51:37 +02:00
|
|
|
TEST_F(PatternMatchTest, SpecificIntULT) {
|
|
|
|
Type *IntTy = IRB.getInt32Ty();
|
|
|
|
unsigned BitWidth = IntTy->getScalarSizeInBits();
|
|
|
|
|
|
|
|
Value *Zero = ConstantInt::get(IntTy, 0);
|
|
|
|
Value *One = ConstantInt::get(IntTy, 1);
|
|
|
|
Value *NegOne = ConstantInt::get(IntTy, -1);
|
|
|
|
|
2019-07-10 18:07:35 +02:00
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_ULT, APInt(BitWidth, 0))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_ULT, APInt(BitWidth, 0))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_ULT, APInt(BitWidth, 0))
|
|
|
|
.match(NegOne));
|
|
|
|
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_ULT, APInt(BitWidth, 1))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_ULT, APInt(BitWidth, 1))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_ULT, APInt(BitWidth, 1))
|
|
|
|
.match(NegOne));
|
|
|
|
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_ULT, APInt(BitWidth, -1))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_ULT, APInt(BitWidth, -1))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_ULT, APInt(BitWidth, -1))
|
|
|
|
.match(NegOne));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(PatternMatchTest, SpecificIntULE) {
|
|
|
|
Type *IntTy = IRB.getInt32Ty();
|
|
|
|
unsigned BitWidth = IntTy->getScalarSizeInBits();
|
|
|
|
|
|
|
|
Value *Zero = ConstantInt::get(IntTy, 0);
|
|
|
|
Value *One = ConstantInt::get(IntTy, 1);
|
|
|
|
Value *NegOne = ConstantInt::get(IntTy, -1);
|
|
|
|
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_ULE, APInt(BitWidth, 0))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_ULE, APInt(BitWidth, 0))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_ULE, APInt(BitWidth, 0))
|
|
|
|
.match(NegOne));
|
|
|
|
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_ULE, APInt(BitWidth, 1))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_ULE, APInt(BitWidth, 1))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_ULE, APInt(BitWidth, 1))
|
|
|
|
.match(NegOne));
|
|
|
|
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_ULE, APInt(BitWidth, -1))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_ULE, APInt(BitWidth, -1))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_ULE, APInt(BitWidth, -1))
|
|
|
|
.match(NegOne));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(PatternMatchTest, SpecificIntSGT) {
|
|
|
|
Type *IntTy = IRB.getInt32Ty();
|
|
|
|
unsigned BitWidth = IntTy->getScalarSizeInBits();
|
|
|
|
|
|
|
|
Value *Zero = ConstantInt::get(IntTy, 0);
|
|
|
|
Value *One = ConstantInt::get(IntTy, 1);
|
|
|
|
Value *NegOne = ConstantInt::get(IntTy, -1);
|
|
|
|
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SGT, APInt(BitWidth, 0))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SGT, APInt(BitWidth, 0))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SGT, APInt(BitWidth, 0))
|
|
|
|
.match(NegOne));
|
|
|
|
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SGT, APInt(BitWidth, 1))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SGT, APInt(BitWidth, 1))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SGT, APInt(BitWidth, 1))
|
|
|
|
.match(NegOne));
|
|
|
|
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SGT, APInt(BitWidth, -1))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SGT, APInt(BitWidth, -1))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SGT, APInt(BitWidth, -1))
|
|
|
|
.match(NegOne));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(PatternMatchTest, SpecificIntSGE) {
|
|
|
|
Type *IntTy = IRB.getInt32Ty();
|
|
|
|
unsigned BitWidth = IntTy->getScalarSizeInBits();
|
|
|
|
|
|
|
|
Value *Zero = ConstantInt::get(IntTy, 0);
|
|
|
|
Value *One = ConstantInt::get(IntTy, 1);
|
|
|
|
Value *NegOne = ConstantInt::get(IntTy, -1);
|
|
|
|
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SGE, APInt(BitWidth, 0))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SGE, APInt(BitWidth, 0))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SGE, APInt(BitWidth, 0))
|
|
|
|
.match(NegOne));
|
|
|
|
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SGE, APInt(BitWidth, 1))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SGE, APInt(BitWidth, 1))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SGE, APInt(BitWidth, 1))
|
|
|
|
.match(NegOne));
|
|
|
|
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SGE, APInt(BitWidth, -1))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SGE, APInt(BitWidth, -1))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SGE, APInt(BitWidth, -1))
|
|
|
|
.match(NegOne));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(PatternMatchTest, SpecificIntSLT) {
|
|
|
|
Type *IntTy = IRB.getInt32Ty();
|
|
|
|
unsigned BitWidth = IntTy->getScalarSizeInBits();
|
|
|
|
|
|
|
|
Value *Zero = ConstantInt::get(IntTy, 0);
|
|
|
|
Value *One = ConstantInt::get(IntTy, 1);
|
|
|
|
Value *NegOne = ConstantInt::get(IntTy, -1);
|
|
|
|
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SLT, APInt(BitWidth, 0))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SLT, APInt(BitWidth, 0))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SLT, APInt(BitWidth, 0))
|
|
|
|
.match(NegOne));
|
|
|
|
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SLT, APInt(BitWidth, 1))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SLT, APInt(BitWidth, 1))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SLT, APInt(BitWidth, 1))
|
|
|
|
.match(NegOne));
|
|
|
|
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SLT, APInt(BitWidth, -1))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SLT, APInt(BitWidth, -1))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SLT, APInt(BitWidth, -1))
|
|
|
|
.match(NegOne));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(PatternMatchTest, SpecificIntSLE) {
|
|
|
|
Type *IntTy = IRB.getInt32Ty();
|
|
|
|
unsigned BitWidth = IntTy->getScalarSizeInBits();
|
|
|
|
|
|
|
|
Value *Zero = ConstantInt::get(IntTy, 0);
|
|
|
|
Value *One = ConstantInt::get(IntTy, 1);
|
|
|
|
Value *NegOne = ConstantInt::get(IntTy, -1);
|
|
|
|
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SLE, APInt(BitWidth, 0))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SLE, APInt(BitWidth, 0))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SLE, APInt(BitWidth, 0))
|
|
|
|
.match(NegOne));
|
2019-06-29 13:51:37 +02:00
|
|
|
|
2019-07-10 18:07:35 +02:00
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SLE, APInt(BitWidth, 1))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SLE, APInt(BitWidth, 1))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SLE, APInt(BitWidth, 1))
|
|
|
|
.match(NegOne));
|
2019-06-29 13:51:37 +02:00
|
|
|
|
2019-07-10 18:07:35 +02:00
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SLE, APInt(BitWidth, -1))
|
|
|
|
.match(Zero));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SLE, APInt(BitWidth, -1))
|
|
|
|
.match(One));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_SLE, APInt(BitWidth, -1))
|
|
|
|
.match(NegOne));
|
2019-06-29 13:51:37 +02:00
|
|
|
}
|
|
|
|
|
2019-07-25 15:34:14 +02:00
|
|
|
TEST_F(PatternMatchTest, Unless) {
|
|
|
|
Value *X = IRB.CreateAdd(IRB.getInt32(1), IRB.getInt32(0));
|
|
|
|
|
|
|
|
EXPECT_TRUE(m_Add(m_One(), m_Zero()).match(X));
|
|
|
|
EXPECT_FALSE(m_Add(m_Zero(), m_One()).match(X));
|
|
|
|
|
|
|
|
EXPECT_FALSE(m_Unless(m_Add(m_One(), m_Zero())).match(X));
|
|
|
|
EXPECT_TRUE(m_Unless(m_Add(m_Zero(), m_One())).match(X));
|
|
|
|
|
|
|
|
EXPECT_TRUE(m_c_Add(m_One(), m_Zero()).match(X));
|
|
|
|
EXPECT_TRUE(m_c_Add(m_Zero(), m_One()).match(X));
|
|
|
|
|
|
|
|
EXPECT_FALSE(m_Unless(m_c_Add(m_One(), m_Zero())).match(X));
|
|
|
|
EXPECT_FALSE(m_Unless(m_c_Add(m_Zero(), m_One())).match(X));
|
|
|
|
}
|
|
|
|
|
2019-09-27 23:53:04 +02:00
|
|
|
TEST_F(PatternMatchTest, ZExtSExtSelf) {
|
|
|
|
LLVMContext &Ctx = IRB.getContext();
|
|
|
|
|
|
|
|
Value *One32 = IRB.getInt32(1);
|
|
|
|
Value *One64Z = IRB.CreateZExt(One32, IntegerType::getInt64Ty(Ctx));
|
|
|
|
Value *One64S = IRB.CreateSExt(One32, IntegerType::getInt64Ty(Ctx));
|
|
|
|
|
|
|
|
EXPECT_TRUE(m_One().match(One32));
|
|
|
|
EXPECT_FALSE(m_One().match(One64Z));
|
|
|
|
EXPECT_FALSE(m_One().match(One64S));
|
|
|
|
|
|
|
|
EXPECT_FALSE(m_ZExt(m_One()).match(One32));
|
|
|
|
EXPECT_TRUE(m_ZExt(m_One()).match(One64Z));
|
|
|
|
EXPECT_FALSE(m_ZExt(m_One()).match(One64S));
|
|
|
|
|
|
|
|
EXPECT_FALSE(m_SExt(m_One()).match(One32));
|
|
|
|
EXPECT_FALSE(m_SExt(m_One()).match(One64Z));
|
|
|
|
EXPECT_TRUE(m_SExt(m_One()).match(One64S));
|
|
|
|
|
|
|
|
EXPECT_TRUE(m_ZExtOrSelf(m_One()).match(One32));
|
|
|
|
EXPECT_TRUE(m_ZExtOrSelf(m_One()).match(One64Z));
|
|
|
|
EXPECT_FALSE(m_ZExtOrSelf(m_One()).match(One64S));
|
|
|
|
|
|
|
|
EXPECT_TRUE(m_SExtOrSelf(m_One()).match(One32));
|
|
|
|
EXPECT_FALSE(m_SExtOrSelf(m_One()).match(One64Z));
|
|
|
|
EXPECT_TRUE(m_SExtOrSelf(m_One()).match(One64S));
|
|
|
|
|
|
|
|
EXPECT_FALSE(m_ZExtOrSExt(m_One()).match(One32));
|
|
|
|
EXPECT_TRUE(m_ZExtOrSExt(m_One()).match(One64Z));
|
|
|
|
EXPECT_TRUE(m_ZExtOrSExt(m_One()).match(One64S));
|
|
|
|
|
|
|
|
EXPECT_TRUE(m_ZExtOrSExtOrSelf(m_One()).match(One32));
|
|
|
|
EXPECT_TRUE(m_ZExtOrSExtOrSelf(m_One()).match(One64Z));
|
|
|
|
EXPECT_TRUE(m_ZExtOrSExtOrSelf(m_One()).match(One64S));
|
|
|
|
}
|
|
|
|
|
2019-07-25 15:34:24 +02:00
|
|
|
TEST_F(PatternMatchTest, Power2) {
|
|
|
|
Value *C128 = IRB.getInt32(128);
|
|
|
|
Value *CNeg128 = ConstantExpr::getNeg(cast<Constant>(C128));
|
|
|
|
|
|
|
|
EXPECT_TRUE(m_Power2().match(C128));
|
|
|
|
EXPECT_FALSE(m_Power2().match(CNeg128));
|
|
|
|
|
|
|
|
EXPECT_FALSE(m_NegatedPower2().match(C128));
|
|
|
|
EXPECT_TRUE(m_NegatedPower2().match(CNeg128));
|
|
|
|
|
|
|
|
Value *CIntMin = IRB.getInt64(APSInt::getSignedMinValue(64).getSExtValue());
|
|
|
|
Value *CNegIntMin = ConstantExpr::getNeg(cast<Constant>(CIntMin));
|
|
|
|
|
|
|
|
EXPECT_TRUE(m_Power2().match(CIntMin));
|
|
|
|
EXPECT_TRUE(m_Power2().match(CNegIntMin));
|
|
|
|
|
|
|
|
EXPECT_TRUE(m_NegatedPower2().match(CIntMin));
|
|
|
|
EXPECT_TRUE(m_NegatedPower2().match(CNegIntMin));
|
|
|
|
}
|
|
|
|
|
[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-27 23:23:20 +02: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 03:07:20 +01:00
|
|
|
TEST_F(PatternMatchTest, FloatingPointOrderedMin) {
|
2014-01-05 03:23:11 +01: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 03:54:46 +02:00
|
|
|
Value *L = ConstantFP::get(FltTy, 1.0);
|
|
|
|
Value *R = ConstantFP::get(FltTy, 2.0);
|
2014-01-05 03:07:20 +01: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 03:54:46 +02:00
|
|
|
|
|
|
|
// Test OLT.
|
2014-01-05 03:23:11 +01:00
|
|
|
EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), L, R)));
|
2014-01-05 03:07:20 +01: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 03:54:46 +02:00
|
|
|
|
|
|
|
// Test OLE.
|
2014-01-05 03:23:11 +01:00
|
|
|
EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), L, R)));
|
2014-01-05 03:07:20 +01: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 03:54:46 +02:00
|
|
|
|
|
|
|
// Test no match on OGE.
|
2014-01-05 03:23:11 +01: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 03:54:46 +02:00
|
|
|
|
|
|
|
// Test no match on OGT.
|
2014-01-05 03:23:11 +01: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 03:54:46 +02:00
|
|
|
|
2017-06-13 19:18:45 +02: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 03:23:11 +01:00
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), R, L)));
|
2017-06-13 19:18:45 +02:00
|
|
|
EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), R, L)));
|
2014-01-05 03:07:20 +01: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 03:54:46 +02:00
|
|
|
|
2017-06-13 19:18:45 +02:00
|
|
|
// [OU]GT with inverted select.
|
|
|
|
EXPECT_FALSE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
|
2014-01-05 03:23:11 +01:00
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), R, L)));
|
2017-06-13 19:18:45 +02:00
|
|
|
EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), R, L)));
|
2014-01-05 03:07:20 +01: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 03:54:46 +02:00
|
|
|
}
|
|
|
|
|
2014-01-05 03:07:20 +01:00
|
|
|
TEST_F(PatternMatchTest, FloatingPointOrderedMax) {
|
2014-01-05 03:23:11 +01: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 03:54:46 +02:00
|
|
|
Value *L = ConstantFP::get(FltTy, 1.0);
|
|
|
|
Value *R = ConstantFP::get(FltTy, 2.0);
|
2014-01-05 03:07:20 +01: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 03:54:46 +02:00
|
|
|
|
|
|
|
// Test OGT.
|
2014-01-05 03:23:11 +01:00
|
|
|
EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), L, R)));
|
2014-01-05 03:07:20 +01: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 03:54:46 +02:00
|
|
|
|
|
|
|
// Test OGE.
|
2014-01-05 03:23:11 +01:00
|
|
|
EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), L, R)));
|
2014-01-05 03:07:20 +01: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 03:54:46 +02:00
|
|
|
|
|
|
|
// Test no match on OLE.
|
2014-01-05 03:23:11 +01: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 03:54:46 +02:00
|
|
|
|
|
|
|
// Test no match on OLT.
|
2014-01-05 03:23:11 +01: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 03:54:46 +02:00
|
|
|
|
2017-06-13 19:18:45 +02: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 03:23:11 +01:00
|
|
|
EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
|
2017-06-13 19:18:45 +02: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 03:54:46 +02:00
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
|
|
|
|
2017-06-13 19:18:45 +02: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 03:23:11 +01:00
|
|
|
EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
|
2017-06-13 19:18:45 +02: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 03:54:46 +02:00
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
|
|
|
}
|
|
|
|
|
2014-01-05 03:07:20 +01:00
|
|
|
TEST_F(PatternMatchTest, FloatingPointUnorderedMin) {
|
2014-01-05 03:23:11 +01: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 03:54:46 +02:00
|
|
|
Value *L = ConstantFP::get(FltTy, 1.0);
|
|
|
|
Value *R = ConstantFP::get(FltTy, 2.0);
|
2014-01-05 03:07:20 +01: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 03:54:46 +02:00
|
|
|
|
|
|
|
// Test ULT.
|
2014-01-05 03:23:11 +01:00
|
|
|
EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), L, R)));
|
2014-01-05 03:07:20 +01: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 03:54:46 +02:00
|
|
|
|
|
|
|
// Test ULE.
|
2014-01-05 03:23:11 +01:00
|
|
|
EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpULE(L, R), L, R)));
|
2014-01-05 03:07:20 +01: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 03:54:46 +02:00
|
|
|
|
|
|
|
// Test no match on UGE.
|
2014-01-05 03:23:11 +01: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 03:54:46 +02:00
|
|
|
|
|
|
|
// Test no match on UGT.
|
2014-01-05 03:23:11 +01: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 03:54:46 +02:00
|
|
|
|
2017-06-13 19:18:45 +02: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 03:23:11 +01:00
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), R, L)));
|
2017-06-13 19:18:45 +02:00
|
|
|
EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), R, L)));
|
2014-01-05 03:07:20 +01: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 03:54:46 +02:00
|
|
|
|
2017-06-13 19:18:45 +02:00
|
|
|
// [UO]GT with inverted select.
|
|
|
|
EXPECT_FALSE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
|
2014-01-05 03:23:11 +01:00
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), R, L)));
|
2017-06-13 19:18:45 +02:00
|
|
|
EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), R, L)));
|
2014-01-05 03:07:20 +01: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 03:54:46 +02:00
|
|
|
}
|
|
|
|
|
2014-01-05 03:07:20 +01:00
|
|
|
TEST_F(PatternMatchTest, FloatingPointUnorderedMax) {
|
2014-01-05 03:23:11 +01: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 03:54:46 +02:00
|
|
|
Value *L = ConstantFP::get(FltTy, 1.0);
|
|
|
|
Value *R = ConstantFP::get(FltTy, 2.0);
|
2014-01-05 03:07:20 +01: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 03:54:46 +02:00
|
|
|
|
|
|
|
// Test UGT.
|
2014-01-05 03:23:11 +01:00
|
|
|
EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), L, R)));
|
2014-01-05 03:07:20 +01: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 03:54:46 +02:00
|
|
|
|
|
|
|
// Test UGE.
|
2014-01-05 03:23:11 +01:00
|
|
|
EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), L, R)));
|
2014-01-05 03:07:20 +01: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 03:54:46 +02:00
|
|
|
|
|
|
|
// Test no match on ULE.
|
2014-01-05 03:23:11 +01: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 03:54:46 +02:00
|
|
|
|
|
|
|
// Test no match on ULT.
|
2014-01-05 03:23:11 +01: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 03:54:46 +02:00
|
|
|
|
2017-06-13 19:18:45 +02: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 03:23:11 +01:00
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpULE(L, R), R, L)));
|
2017-06-13 19:18:45 +02:00
|
|
|
EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), R, L)));
|
2014-01-05 03:07:20 +01: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 03:54:46 +02:00
|
|
|
|
2017-06-13 19:18:45 +02:00
|
|
|
// [UO]LT with inverted select.
|
|
|
|
EXPECT_FALSE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
|
2014-01-05 03:23:11 +01:00
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), R, L)));
|
2017-06-13 19:18:45 +02:00
|
|
|
EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), R, L)));
|
2014-01-05 03:07:20 +01: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 03:54:46 +02:00
|
|
|
}
|
|
|
|
|
2014-01-05 04:28:29 +01: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 00:29:17 +02:00
|
|
|
MatchL = MatchR = nullptr;
|
2014-01-05 04:28:29 +01: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 00:29:17 +02:00
|
|
|
MatchL = MatchR = nullptr;
|
2014-01-05 04:28:29 +01: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 00:29:17 +02:00
|
|
|
MatchL = MatchR = nullptr;
|
2014-01-05 04:28:29 +01: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 00:29:17 +02:00
|
|
|
MatchL = MatchR = nullptr;
|
2014-01-05 04:28:29 +01: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 00:29:17 +02:00
|
|
|
MatchL = MatchR = nullptr;
|
2014-01-05 04:28:29 +01: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 00:29:17 +02:00
|
|
|
MatchL = MatchR = nullptr;
|
2014-01-05 04:28:29 +01: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 09:27:45 +02: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-01 21:44:24 +01:00
|
|
|
Value *LoadInst = IRB.CreateLoad(IRB.getInt32Ty(), Alloca);
|
2018-06-20 09:27:45 +02: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 17:39:00 +02: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)
|
2020-06-16 23:55:32 +02:00
|
|
|
Type *VecTy = FixedVectorType::get(IRB.getInt8Ty(), 2);
|
2018-03-28 17:39:00 +02:00
|
|
|
Type *i32 = IRB.getInt32Ty();
|
2020-06-16 23:55:32 +02:00
|
|
|
Type *i32VecTy = FixedVectorType::get(i32, 2);
|
2018-03-28 17:39:00 +02:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2020-12-29 23:28:17 +01:00
|
|
|
Constant *Zero = ConstantAggregateZero::get(i32VecTy);
|
|
|
|
SmallVector<int, 16> ZeroMask;
|
|
|
|
ShuffleVectorInst::getShuffleMask(Zero, ZeroMask);
|
|
|
|
|
|
|
|
Value *SI1 = IRB.CreateShuffleVector(VI1, ZeroMask);
|
2018-03-28 17:39:00 +02:00
|
|
|
Value *SI2 = IRB.CreateShuffleVector(VI3, VI4, IdxVec);
|
2020-12-29 23:28:17 +01:00
|
|
|
Value *SI3 = IRB.CreateShuffleVector(VI3, ZeroMask);
|
|
|
|
Value *SI4 = IRB.CreateShuffleVector(VI4, ZeroMask);
|
2018-03-28 17:39:00 +02:00
|
|
|
|
|
|
|
Value *SP1 = IRB.CreateVectorSplat(2, IRB.getInt8(2));
|
|
|
|
Value *SP2 = IRB.CreateVectorSplat(2, Val);
|
|
|
|
|
|
|
|
Value *A = nullptr, *B = nullptr, *C = nullptr;
|
|
|
|
|
|
|
|
// Test matching insertelement
|
2020-05-23 16:13:50 +02:00
|
|
|
EXPECT_TRUE(match(VI1, m_InsertElt(m_Value(), m_Value(), m_Value())));
|
2018-03-28 17:39:00 +02:00
|
|
|
EXPECT_TRUE(
|
2020-05-23 16:13:50 +02:00
|
|
|
match(VI1, m_InsertElt(m_Undef(), m_ConstantInt(), m_ConstantInt())));
|
2018-03-28 17:39:00 +02:00
|
|
|
EXPECT_TRUE(
|
2020-05-23 16:13:50 +02:00
|
|
|
match(VI1, m_InsertElt(m_Undef(), m_ConstantInt(), m_Zero())));
|
2018-03-28 17:39:00 +02:00
|
|
|
EXPECT_TRUE(
|
2020-05-23 16:13:50 +02:00
|
|
|
match(VI1, m_InsertElt(m_Undef(), m_SpecificInt(1), m_Zero())));
|
|
|
|
EXPECT_TRUE(match(VI2, m_InsertElt(m_Value(), m_Value(), m_Value())));
|
2018-03-28 17:39:00 +02:00
|
|
|
EXPECT_FALSE(
|
2020-05-23 16:13:50 +02:00
|
|
|
match(VI2, m_InsertElt(m_Value(), m_Value(), m_ConstantInt())));
|
2018-03-28 17:39:00 +02:00
|
|
|
EXPECT_FALSE(
|
2020-05-23 16:13:50 +02:00
|
|
|
match(VI2, m_InsertElt(m_Value(), m_ConstantInt(), m_Value())));
|
|
|
|
EXPECT_FALSE(match(VI2, m_InsertElt(m_Constant(), m_Value(), m_Value())));
|
|
|
|
EXPECT_TRUE(match(VI3, m_InsertElt(m_Value(A), m_Value(B), m_Value(C))));
|
2018-03-28 17:39:00 +02:00
|
|
|
EXPECT_TRUE(A == VI1);
|
|
|
|
EXPECT_TRUE(B == Val2);
|
|
|
|
EXPECT_TRUE(isa<ConstantInt>(C));
|
|
|
|
A = B = C = nullptr; // reset
|
|
|
|
|
|
|
|
// Test matching extractelement
|
2020-05-23 16:13:50 +02:00
|
|
|
EXPECT_TRUE(match(EX1, m_ExtractElt(m_Value(A), m_Value(B))));
|
2018-03-28 17:39:00 +02:00
|
|
|
EXPECT_TRUE(A == VI4);
|
|
|
|
EXPECT_TRUE(B == Val);
|
|
|
|
A = B = C = nullptr; // reset
|
2020-05-23 16:13:50 +02:00
|
|
|
EXPECT_FALSE(match(EX1, m_ExtractElt(m_Value(), m_ConstantInt())));
|
|
|
|
EXPECT_TRUE(match(EX2, m_ExtractElt(m_Value(), m_ConstantInt())));
|
|
|
|
EXPECT_TRUE(match(EX3, m_ExtractElt(m_Constant(), m_ConstantInt())));
|
2018-03-28 17:39:00 +02:00
|
|
|
|
|
|
|
// Test matching shufflevector
|
2020-03-31 22:08:59 +02:00
|
|
|
ArrayRef<int> Mask;
|
2020-05-23 16:13:50 +02:00
|
|
|
EXPECT_TRUE(match(SI1, m_Shuffle(m_Value(), m_Undef(), m_ZeroMask())));
|
|
|
|
EXPECT_TRUE(match(SI2, m_Shuffle(m_Value(A), m_Value(B), m_Mask(Mask))));
|
2018-03-28 17:39:00 +02:00
|
|
|
EXPECT_TRUE(A == VI3);
|
|
|
|
EXPECT_TRUE(B == VI4);
|
|
|
|
A = B = C = nullptr; // reset
|
|
|
|
|
|
|
|
// Test matching the vector splat pattern
|
|
|
|
EXPECT_TRUE(match(
|
|
|
|
SI1,
|
2020-05-23 16:13:50 +02:00
|
|
|
m_Shuffle(m_InsertElt(m_Undef(), m_SpecificInt(1), m_Zero()),
|
|
|
|
m_Undef(), m_ZeroMask())));
|
2018-03-28 17:39:00 +02:00
|
|
|
EXPECT_FALSE(match(
|
2020-05-23 16:13:50 +02:00
|
|
|
SI3, m_Shuffle(m_InsertElt(m_Undef(), m_Value(), m_Zero()),
|
|
|
|
m_Undef(), m_ZeroMask())));
|
2018-03-28 17:39:00 +02:00
|
|
|
EXPECT_FALSE(match(
|
2020-05-23 16:13:50 +02:00
|
|
|
SI4, m_Shuffle(m_InsertElt(m_Undef(), m_Value(), m_Zero()),
|
|
|
|
m_Undef(), m_ZeroMask())));
|
2018-03-28 17:39:00 +02:00
|
|
|
EXPECT_TRUE(match(
|
|
|
|
SP1,
|
2020-05-23 16:13:50 +02:00
|
|
|
m_Shuffle(m_InsertElt(m_Undef(), m_SpecificInt(2), m_Zero()),
|
|
|
|
m_Undef(), m_ZeroMask())));
|
2018-03-28 17:39:00 +02:00
|
|
|
EXPECT_TRUE(match(
|
2020-05-23 16:13:50 +02:00
|
|
|
SP2, m_Shuffle(m_InsertElt(m_Undef(), m_Value(A), m_Zero()),
|
|
|
|
m_Undef(), m_ZeroMask())));
|
2018-03-28 17:39:00 +02:00
|
|
|
EXPECT_TRUE(A == Val);
|
|
|
|
}
|
|
|
|
|
2018-11-20 17:08:19 +01:00
|
|
|
TEST_F(PatternMatchTest, VectorUndefInt) {
|
|
|
|
Type *ScalarTy = IRB.getInt8Ty();
|
2020-06-16 23:55:32 +02:00
|
|
|
Type *VectorTy = FixedVectorType::get(ScalarTy, 4);
|
2018-11-20 17:08:19 +01:00
|
|
|
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()));
|
2020-01-18 12:21:14 +01:00
|
|
|
|
|
|
|
const APInt *C;
|
|
|
|
// Regardless of whether undefs are allowed,
|
|
|
|
// a fully undef constant does not match.
|
|
|
|
EXPECT_FALSE(match(ScalarUndef, m_APInt(C)));
|
|
|
|
EXPECT_FALSE(match(ScalarUndef, m_APIntForbidUndef(C)));
|
|
|
|
EXPECT_FALSE(match(ScalarUndef, m_APIntAllowUndef(C)));
|
|
|
|
EXPECT_FALSE(match(VectorUndef, m_APInt(C)));
|
|
|
|
EXPECT_FALSE(match(VectorUndef, m_APIntForbidUndef(C)));
|
|
|
|
EXPECT_FALSE(match(VectorUndef, m_APIntAllowUndef(C)));
|
|
|
|
|
|
|
|
// We can always match simple constants and simple splats.
|
|
|
|
C = nullptr;
|
|
|
|
EXPECT_TRUE(match(ScalarZero, m_APInt(C)));
|
|
|
|
EXPECT_TRUE(C->isNullValue());
|
|
|
|
C = nullptr;
|
|
|
|
EXPECT_TRUE(match(ScalarZero, m_APIntForbidUndef(C)));
|
|
|
|
EXPECT_TRUE(C->isNullValue());
|
|
|
|
C = nullptr;
|
|
|
|
EXPECT_TRUE(match(ScalarZero, m_APIntAllowUndef(C)));
|
|
|
|
EXPECT_TRUE(C->isNullValue());
|
|
|
|
C = nullptr;
|
|
|
|
EXPECT_TRUE(match(VectorZero, m_APInt(C)));
|
|
|
|
EXPECT_TRUE(C->isNullValue());
|
|
|
|
C = nullptr;
|
|
|
|
EXPECT_TRUE(match(VectorZero, m_APIntForbidUndef(C)));
|
|
|
|
EXPECT_TRUE(C->isNullValue());
|
|
|
|
C = nullptr;
|
|
|
|
EXPECT_TRUE(match(VectorZero, m_APIntAllowUndef(C)));
|
|
|
|
EXPECT_TRUE(C->isNullValue());
|
|
|
|
|
|
|
|
// Whether splats with undef can be matched depends on the matcher.
|
|
|
|
EXPECT_FALSE(match(VectorZeroUndef, m_APInt(C)));
|
|
|
|
EXPECT_FALSE(match(VectorZeroUndef, m_APIntForbidUndef(C)));
|
|
|
|
C = nullptr;
|
|
|
|
EXPECT_TRUE(match(VectorZeroUndef, m_APIntAllowUndef(C)));
|
|
|
|
EXPECT_TRUE(C->isNullValue());
|
2018-11-20 17:08:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(PatternMatchTest, VectorUndefFloat) {
|
|
|
|
Type *ScalarTy = IRB.getFloatTy();
|
2020-06-16 23:55:32 +02:00
|
|
|
Type *VectorTy = FixedVectorType::get(ScalarTy, 4);
|
2018-11-20 17:08:19 +01:00
|
|
|
Constant *ScalarUndef = UndefValue::get(ScalarTy);
|
|
|
|
Constant *VectorUndef = UndefValue::get(VectorTy);
|
|
|
|
Constant *ScalarZero = Constant::getNullValue(ScalarTy);
|
|
|
|
Constant *VectorZero = Constant::getNullValue(VectorTy);
|
2020-03-11 21:51:30 +01:00
|
|
|
Constant *ScalarPosInf = ConstantFP::getInfinity(ScalarTy, false);
|
|
|
|
Constant *ScalarNegInf = ConstantFP::getInfinity(ScalarTy, true);
|
2020-10-16 14:54:19 +02:00
|
|
|
Constant *ScalarNaN = ConstantFP::getNaN(ScalarTy, true);
|
2018-11-20 17:08:19 +01:00
|
|
|
|
2020-10-16 14:54:19 +02:00
|
|
|
Constant *VectorZeroUndef =
|
|
|
|
ConstantVector::get({ScalarUndef, ScalarZero, ScalarUndef, ScalarZero});
|
|
|
|
|
|
|
|
Constant *VectorInfUndef = ConstantVector::get(
|
|
|
|
{ScalarPosInf, ScalarNegInf, ScalarUndef, ScalarPosInf});
|
2018-11-20 17:08:19 +01:00
|
|
|
|
2020-10-16 14:54:19 +02:00
|
|
|
Constant *VectorNaNUndef =
|
|
|
|
ConstantVector::get({ScalarUndef, ScalarNaN, ScalarNaN, ScalarNaN});
|
2020-03-11 21:51:30 +01:00
|
|
|
|
2018-11-20 17:08:19 +01:00
|
|
|
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()));
|
2020-10-16 14:54:19 +02:00
|
|
|
EXPECT_FALSE(match(VectorInfUndef, m_Undef()));
|
|
|
|
EXPECT_FALSE(match(VectorNaNUndef, m_Undef()));
|
2018-11-20 17:08:19 +01:00
|
|
|
|
|
|
|
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()));
|
2020-10-16 14:54:19 +02:00
|
|
|
EXPECT_FALSE(match(VectorInfUndef, m_AnyZeroFP()));
|
|
|
|
EXPECT_FALSE(match(VectorNaNUndef, m_AnyZeroFP()));
|
|
|
|
|
|
|
|
EXPECT_FALSE(match(ScalarUndef, m_NaN()));
|
|
|
|
EXPECT_FALSE(match(VectorUndef, m_NaN()));
|
|
|
|
EXPECT_FALSE(match(VectorZeroUndef, m_NaN()));
|
|
|
|
EXPECT_FALSE(match(ScalarPosInf, m_NaN()));
|
|
|
|
EXPECT_FALSE(match(ScalarNegInf, m_NaN()));
|
|
|
|
EXPECT_TRUE(match(ScalarNaN, m_NaN()));
|
|
|
|
EXPECT_FALSE(match(VectorInfUndef, m_NaN()));
|
|
|
|
EXPECT_TRUE(match(VectorNaNUndef, m_NaN()));
|
|
|
|
|
|
|
|
EXPECT_FALSE(match(ScalarUndef, m_NonNaN()));
|
|
|
|
EXPECT_FALSE(match(VectorUndef, m_NonNaN()));
|
|
|
|
EXPECT_TRUE(match(VectorZeroUndef, m_NonNaN()));
|
|
|
|
EXPECT_TRUE(match(ScalarPosInf, m_NonNaN()));
|
|
|
|
EXPECT_TRUE(match(ScalarNegInf, m_NonNaN()));
|
|
|
|
EXPECT_FALSE(match(ScalarNaN, m_NonNaN()));
|
|
|
|
EXPECT_TRUE(match(VectorInfUndef, m_NonNaN()));
|
|
|
|
EXPECT_FALSE(match(VectorNaNUndef, m_NonNaN()));
|
2020-01-18 12:21:14 +01:00
|
|
|
|
2020-03-11 21:51:30 +01:00
|
|
|
EXPECT_FALSE(match(ScalarUndef, m_Inf()));
|
|
|
|
EXPECT_FALSE(match(VectorUndef, m_Inf()));
|
|
|
|
EXPECT_FALSE(match(VectorZeroUndef, m_Inf()));
|
|
|
|
EXPECT_TRUE(match(ScalarPosInf, m_Inf()));
|
|
|
|
EXPECT_TRUE(match(ScalarNegInf, m_Inf()));
|
2020-10-16 14:54:19 +02:00
|
|
|
EXPECT_FALSE(match(ScalarNaN, m_Inf()));
|
2020-03-11 21:51:30 +01:00
|
|
|
EXPECT_TRUE(match(VectorInfUndef, m_Inf()));
|
2020-10-16 14:54:19 +02:00
|
|
|
EXPECT_FALSE(match(VectorNaNUndef, m_Inf()));
|
|
|
|
|
|
|
|
EXPECT_FALSE(match(ScalarUndef, m_NonInf()));
|
|
|
|
EXPECT_FALSE(match(VectorUndef, m_NonInf()));
|
|
|
|
EXPECT_TRUE(match(VectorZeroUndef, m_NonInf()));
|
|
|
|
EXPECT_FALSE(match(ScalarPosInf, m_NonInf()));
|
|
|
|
EXPECT_FALSE(match(ScalarNegInf, m_NonInf()));
|
|
|
|
EXPECT_TRUE(match(ScalarNaN, m_NonInf()));
|
|
|
|
EXPECT_FALSE(match(VectorInfUndef, m_NonInf()));
|
|
|
|
EXPECT_TRUE(match(VectorNaNUndef, m_NonInf()));
|
|
|
|
|
|
|
|
EXPECT_FALSE(match(ScalarUndef, m_Finite()));
|
|
|
|
EXPECT_FALSE(match(VectorUndef, m_Finite()));
|
|
|
|
EXPECT_TRUE(match(VectorZeroUndef, m_Finite()));
|
|
|
|
EXPECT_FALSE(match(ScalarPosInf, m_Finite()));
|
|
|
|
EXPECT_FALSE(match(ScalarNegInf, m_Finite()));
|
|
|
|
EXPECT_FALSE(match(ScalarNaN, m_Finite()));
|
|
|
|
EXPECT_FALSE(match(VectorInfUndef, m_Finite()));
|
|
|
|
EXPECT_FALSE(match(VectorNaNUndef, m_Finite()));
|
2020-03-11 21:51:30 +01:00
|
|
|
|
2020-01-18 12:21:14 +01:00
|
|
|
const APFloat *C;
|
|
|
|
// Regardless of whether undefs are allowed,
|
|
|
|
// a fully undef constant does not match.
|
|
|
|
EXPECT_FALSE(match(ScalarUndef, m_APFloat(C)));
|
|
|
|
EXPECT_FALSE(match(ScalarUndef, m_APFloatForbidUndef(C)));
|
|
|
|
EXPECT_FALSE(match(ScalarUndef, m_APFloatAllowUndef(C)));
|
|
|
|
EXPECT_FALSE(match(VectorUndef, m_APFloat(C)));
|
|
|
|
EXPECT_FALSE(match(VectorUndef, m_APFloatForbidUndef(C)));
|
|
|
|
EXPECT_FALSE(match(VectorUndef, m_APFloatAllowUndef(C)));
|
|
|
|
|
|
|
|
// We can always match simple constants and simple splats.
|
|
|
|
C = nullptr;
|
|
|
|
EXPECT_TRUE(match(ScalarZero, m_APFloat(C)));
|
|
|
|
EXPECT_TRUE(C->isZero());
|
|
|
|
C = nullptr;
|
|
|
|
EXPECT_TRUE(match(ScalarZero, m_APFloatForbidUndef(C)));
|
|
|
|
EXPECT_TRUE(C->isZero());
|
|
|
|
C = nullptr;
|
|
|
|
EXPECT_TRUE(match(ScalarZero, m_APFloatAllowUndef(C)));
|
|
|
|
EXPECT_TRUE(C->isZero());
|
|
|
|
C = nullptr;
|
|
|
|
EXPECT_TRUE(match(VectorZero, m_APFloat(C)));
|
|
|
|
EXPECT_TRUE(C->isZero());
|
|
|
|
C = nullptr;
|
|
|
|
EXPECT_TRUE(match(VectorZero, m_APFloatForbidUndef(C)));
|
|
|
|
EXPECT_TRUE(C->isZero());
|
|
|
|
C = nullptr;
|
|
|
|
EXPECT_TRUE(match(VectorZero, m_APFloatAllowUndef(C)));
|
|
|
|
EXPECT_TRUE(C->isZero());
|
|
|
|
|
|
|
|
// Whether splats with undef can be matched depends on the matcher.
|
|
|
|
EXPECT_FALSE(match(VectorZeroUndef, m_APFloat(C)));
|
|
|
|
EXPECT_FALSE(match(VectorZeroUndef, m_APFloatForbidUndef(C)));
|
|
|
|
C = nullptr;
|
|
|
|
EXPECT_TRUE(match(VectorZeroUndef, m_APFloatAllowUndef(C)));
|
|
|
|
EXPECT_TRUE(C->isZero());
|
2020-10-16 14:54:19 +02:00
|
|
|
C = nullptr;
|
|
|
|
EXPECT_TRUE(match(VectorZeroUndef, m_Finite(C)));
|
|
|
|
EXPECT_TRUE(C->isZero());
|
2018-11-20 17:08:19 +01:00
|
|
|
}
|
|
|
|
|
2019-05-03 23:19:12 +02:00
|
|
|
TEST_F(PatternMatchTest, FloatingPointFNeg) {
|
|
|
|
Type *FltTy = IRB.getFloatTy();
|
|
|
|
Value *One = ConstantFP::get(FltTy, 1.0);
|
|
|
|
Value *Z = ConstantFP::get(FltTy, 0.0);
|
|
|
|
Value *NZ = ConstantFP::get(FltTy, -0.0);
|
|
|
|
Value *V = IRB.CreateFNeg(One);
|
|
|
|
Value *V1 = IRB.CreateFSub(NZ, One);
|
|
|
|
Value *V2 = IRB.CreateFSub(Z, One);
|
|
|
|
Value *V3 = IRB.CreateFAdd(NZ, One);
|
|
|
|
Value *Match;
|
|
|
|
|
|
|
|
// Test FNeg(1.0)
|
|
|
|
EXPECT_TRUE(match(V, m_FNeg(m_Value(Match))));
|
|
|
|
EXPECT_EQ(One, Match);
|
|
|
|
|
|
|
|
// Test FSub(-0.0, 1.0)
|
|
|
|
EXPECT_TRUE(match(V1, m_FNeg(m_Value(Match))));
|
|
|
|
EXPECT_EQ(One, Match);
|
|
|
|
|
|
|
|
// Test FSub(0.0, 1.0)
|
|
|
|
EXPECT_FALSE(match(V2, m_FNeg(m_Value(Match))));
|
|
|
|
cast<Instruction>(V2)->setHasNoSignedZeros(true);
|
|
|
|
EXPECT_TRUE(match(V2, m_FNeg(m_Value(Match))));
|
|
|
|
EXPECT_EQ(One, Match);
|
|
|
|
|
|
|
|
// Test FAdd(-0.0, 1.0)
|
|
|
|
EXPECT_FALSE(match(V3, m_FNeg(m_Value(Match))));
|
|
|
|
}
|
|
|
|
|
2019-09-25 17:05:08 +02:00
|
|
|
TEST_F(PatternMatchTest, CondBranchTest) {
|
|
|
|
BasicBlock *TrueBB = BasicBlock::Create(Ctx, "TrueBB", F);
|
|
|
|
BasicBlock *FalseBB = BasicBlock::Create(Ctx, "FalseBB", F);
|
|
|
|
Value *Br1 = IRB.CreateCondBr(IRB.getTrue(), TrueBB, FalseBB);
|
|
|
|
|
|
|
|
EXPECT_TRUE(match(Br1, m_Br(m_Value(), m_BasicBlock(), m_BasicBlock())));
|
|
|
|
|
|
|
|
BasicBlock *A, *B;
|
|
|
|
EXPECT_TRUE(match(Br1, m_Br(m_Value(), m_BasicBlock(A), m_BasicBlock(B))));
|
|
|
|
EXPECT_EQ(TrueBB, A);
|
|
|
|
EXPECT_EQ(FalseBB, B);
|
|
|
|
|
|
|
|
EXPECT_FALSE(
|
|
|
|
match(Br1, m_Br(m_Value(), m_SpecificBB(FalseBB), m_BasicBlock())));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
match(Br1, m_Br(m_Value(), m_BasicBlock(), m_SpecificBB(TrueBB))));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
match(Br1, m_Br(m_Value(), m_SpecificBB(FalseBB), m_BasicBlock(TrueBB))));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
match(Br1, m_Br(m_Value(), m_SpecificBB(TrueBB), m_BasicBlock(FalseBB))));
|
|
|
|
|
|
|
|
// Check we can use m_Deferred with branches.
|
|
|
|
EXPECT_FALSE(match(Br1, m_Br(m_Value(), m_BasicBlock(A), m_Deferred(A))));
|
|
|
|
Value *Br2 = IRB.CreateCondBr(IRB.getTrue(), TrueBB, TrueBB);
|
|
|
|
A = nullptr;
|
|
|
|
EXPECT_TRUE(match(Br2, m_Br(m_Value(), m_BasicBlock(A), m_Deferred(A))));
|
|
|
|
}
|
|
|
|
|
2019-10-31 12:47:47 +01:00
|
|
|
TEST_F(PatternMatchTest, WithOverflowInst) {
|
|
|
|
Value *Add = IRB.CreateBinaryIntrinsic(Intrinsic::uadd_with_overflow,
|
|
|
|
IRB.getInt32(0), IRB.getInt32(0));
|
|
|
|
Value *Add0 = IRB.CreateExtractValue(Add, 0);
|
|
|
|
Value *Add1 = IRB.CreateExtractValue(Add, 1);
|
|
|
|
|
|
|
|
EXPECT_TRUE(match(Add0, m_ExtractValue<0>(m_Value())));
|
|
|
|
EXPECT_FALSE(match(Add0, m_ExtractValue<1>(m_Value())));
|
|
|
|
EXPECT_FALSE(match(Add1, m_ExtractValue<0>(m_Value())));
|
|
|
|
EXPECT_TRUE(match(Add1, m_ExtractValue<1>(m_Value())));
|
|
|
|
EXPECT_FALSE(match(Add, m_ExtractValue<1>(m_Value())));
|
|
|
|
EXPECT_FALSE(match(Add, m_ExtractValue<1>(m_Value())));
|
|
|
|
|
|
|
|
WithOverflowInst *WOI;
|
|
|
|
EXPECT_FALSE(match(Add0, m_WithOverflowInst(WOI)));
|
|
|
|
EXPECT_FALSE(match(Add1, m_WithOverflowInst(WOI)));
|
|
|
|
EXPECT_TRUE(match(Add, m_WithOverflowInst(WOI)));
|
|
|
|
|
|
|
|
EXPECT_TRUE(match(Add0, m_ExtractValue<0>(m_WithOverflowInst(WOI))));
|
|
|
|
EXPECT_EQ(Add, WOI);
|
|
|
|
EXPECT_TRUE(match(Add1, m_ExtractValue<1>(m_WithOverflowInst(WOI))));
|
|
|
|
EXPECT_EQ(Add, WOI);
|
|
|
|
}
|
|
|
|
|
2020-08-06 16:49:26 +02:00
|
|
|
TEST_F(PatternMatchTest, MinMaxIntrinsics) {
|
|
|
|
Type *Ty = IRB.getInt32Ty();
|
|
|
|
Value *L = ConstantInt::get(Ty, 1);
|
|
|
|
Value *R = ConstantInt::get(Ty, 2);
|
|
|
|
Value *MatchL, *MatchR;
|
|
|
|
|
|
|
|
// Check for intrinsic ID match and capture of operands.
|
|
|
|
EXPECT_TRUE(m_SMax(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateBinaryIntrinsic(Intrinsic::smax, L, R)));
|
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
|
|
|
|
|
|
|
EXPECT_TRUE(m_SMin(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateBinaryIntrinsic(Intrinsic::smin, L, R)));
|
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
|
|
|
|
|
|
|
EXPECT_TRUE(m_UMax(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateBinaryIntrinsic(Intrinsic::umax, L, R)));
|
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
|
|
|
|
|
|
|
EXPECT_TRUE(m_UMin(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateBinaryIntrinsic(Intrinsic::umin, L, R)));
|
|
|
|
EXPECT_EQ(L, MatchL);
|
|
|
|
EXPECT_EQ(R, MatchR);
|
|
|
|
|
|
|
|
// Check for intrinsic ID mismatch.
|
|
|
|
EXPECT_FALSE(m_SMax(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateBinaryIntrinsic(Intrinsic::smin, L, R)));
|
|
|
|
EXPECT_FALSE(m_SMin(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateBinaryIntrinsic(Intrinsic::umax, L, R)));
|
|
|
|
EXPECT_FALSE(m_UMax(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateBinaryIntrinsic(Intrinsic::umin, L, R)));
|
|
|
|
EXPECT_FALSE(m_UMin(m_Value(MatchL), m_Value(MatchR))
|
|
|
|
.match(IRB.CreateBinaryIntrinsic(Intrinsic::smax, L, R)));
|
|
|
|
}
|
|
|
|
|
2019-12-02 16:29:53 +01:00
|
|
|
TEST_F(PatternMatchTest, IntrinsicMatcher) {
|
|
|
|
Value *Name = IRB.CreateAlloca(IRB.getInt8Ty());
|
|
|
|
Value *Hash = IRB.getInt64(0);
|
|
|
|
Value *Num = IRB.getInt32(1);
|
|
|
|
Value *Index = IRB.getInt32(2);
|
|
|
|
Value *Step = IRB.getInt64(3);
|
|
|
|
|
|
|
|
Value *Ops[] = {Name, Hash, Num, Index, Step};
|
|
|
|
Module *M = BB->getParent()->getParent();
|
|
|
|
Function *TheFn =
|
|
|
|
Intrinsic::getDeclaration(M, Intrinsic::instrprof_increment_step);
|
|
|
|
|
|
|
|
Value *Intrinsic5 = CallInst::Create(TheFn, Ops, "", BB);
|
|
|
|
|
|
|
|
// Match without capturing.
|
|
|
|
EXPECT_TRUE(match(
|
|
|
|
Intrinsic5, m_Intrinsic<Intrinsic::instrprof_increment_step>(
|
|
|
|
m_Value(), m_Value(), m_Value(), m_Value(), m_Value())));
|
|
|
|
EXPECT_FALSE(match(
|
|
|
|
Intrinsic5, m_Intrinsic<Intrinsic::memmove>(
|
|
|
|
m_Value(), m_Value(), m_Value(), m_Value(), m_Value())));
|
|
|
|
|
|
|
|
// Match with capturing.
|
|
|
|
Value *Arg1 = nullptr;
|
|
|
|
Value *Arg2 = nullptr;
|
|
|
|
Value *Arg3 = nullptr;
|
|
|
|
Value *Arg4 = nullptr;
|
|
|
|
Value *Arg5 = nullptr;
|
|
|
|
EXPECT_TRUE(
|
|
|
|
match(Intrinsic5, m_Intrinsic<Intrinsic::instrprof_increment_step>(
|
|
|
|
m_Value(Arg1), m_Value(Arg2), m_Value(Arg3),
|
|
|
|
m_Value(Arg4), m_Value(Arg5))));
|
|
|
|
EXPECT_EQ(Arg1, Name);
|
|
|
|
EXPECT_EQ(Arg2, Hash);
|
|
|
|
EXPECT_EQ(Arg3, Num);
|
|
|
|
EXPECT_EQ(Arg4, Index);
|
|
|
|
EXPECT_EQ(Arg5, Step);
|
|
|
|
|
|
|
|
// Match specific second argument.
|
|
|
|
EXPECT_TRUE(
|
|
|
|
match(Intrinsic5,
|
|
|
|
m_Intrinsic<Intrinsic::instrprof_increment_step>(
|
|
|
|
m_Value(), m_SpecificInt(0), m_Value(), m_Value(), m_Value())));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
match(Intrinsic5, m_Intrinsic<Intrinsic::instrprof_increment_step>(
|
|
|
|
m_Value(), m_SpecificInt(10), m_Value(), m_Value(),
|
|
|
|
m_Value())));
|
|
|
|
|
|
|
|
// Match specific third argument.
|
|
|
|
EXPECT_TRUE(
|
|
|
|
match(Intrinsic5,
|
|
|
|
m_Intrinsic<Intrinsic::instrprof_increment_step>(
|
|
|
|
m_Value(), m_Value(), m_SpecificInt(1), m_Value(), m_Value())));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
match(Intrinsic5, m_Intrinsic<Intrinsic::instrprof_increment_step>(
|
|
|
|
m_Value(), m_Value(), m_SpecificInt(10), m_Value(),
|
|
|
|
m_Value())));
|
|
|
|
|
|
|
|
// Match specific fourth argument.
|
|
|
|
EXPECT_TRUE(
|
|
|
|
match(Intrinsic5,
|
|
|
|
m_Intrinsic<Intrinsic::instrprof_increment_step>(
|
|
|
|
m_Value(), m_Value(), m_Value(), m_SpecificInt(2), m_Value())));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
match(Intrinsic5, m_Intrinsic<Intrinsic::instrprof_increment_step>(
|
|
|
|
m_Value(), m_Value(), m_Value(), m_SpecificInt(10),
|
|
|
|
m_Value())));
|
|
|
|
|
|
|
|
// Match specific fifth argument.
|
|
|
|
EXPECT_TRUE(
|
|
|
|
match(Intrinsic5,
|
|
|
|
m_Intrinsic<Intrinsic::instrprof_increment_step>(
|
|
|
|
m_Value(), m_Value(), m_Value(), m_Value(), m_SpecificInt(3))));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
match(Intrinsic5, m_Intrinsic<Intrinsic::instrprof_increment_step>(
|
|
|
|
m_Value(), m_Value(), m_Value(), m_Value(),
|
|
|
|
m_SpecificInt(10))));
|
|
|
|
}
|
|
|
|
|
2020-07-14 22:36:33 +02:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
struct is_unsigned_zero_pred {
|
|
|
|
bool isValue(const APInt &C) { return C.isNullValue(); }
|
|
|
|
};
|
|
|
|
|
|
|
|
struct is_float_zero_pred {
|
|
|
|
bool isValue(const APFloat &C) { return C.isZero(); }
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T> struct always_true_pred {
|
|
|
|
bool isValue(const T &) { return true; }
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T> struct always_false_pred {
|
|
|
|
bool isValue(const T &) { return false; }
|
|
|
|
};
|
|
|
|
|
|
|
|
struct is_unsigned_max_pred {
|
|
|
|
bool isValue(const APInt &C) { return C.isMaxValue(); }
|
|
|
|
};
|
|
|
|
|
|
|
|
struct is_float_nan_pred {
|
|
|
|
bool isValue(const APFloat &C) { return C.isNaN(); }
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
TEST_F(PatternMatchTest, ConstantPredicateType) {
|
|
|
|
|
|
|
|
// Scalar integer
|
|
|
|
APInt U32Max = APInt::getAllOnesValue(32);
|
|
|
|
APInt U32Zero = APInt::getNullValue(32);
|
|
|
|
APInt U32DeadBeef(32, 0xDEADBEEF);
|
|
|
|
|
|
|
|
Type *U32Ty = Type::getInt32Ty(Ctx);
|
|
|
|
|
|
|
|
Constant *CU32Max = Constant::getIntegerValue(U32Ty, U32Max);
|
|
|
|
Constant *CU32Zero = Constant::getIntegerValue(U32Ty, U32Zero);
|
|
|
|
Constant *CU32DeadBeef = Constant::getIntegerValue(U32Ty, U32DeadBeef);
|
|
|
|
|
|
|
|
EXPECT_TRUE(match(CU32Max, cst_pred_ty<is_unsigned_max_pred>()));
|
|
|
|
EXPECT_FALSE(match(CU32Max, cst_pred_ty<is_unsigned_zero_pred>()));
|
|
|
|
EXPECT_TRUE(match(CU32Max, cst_pred_ty<always_true_pred<APInt>>()));
|
|
|
|
EXPECT_FALSE(match(CU32Max, cst_pred_ty<always_false_pred<APInt>>()));
|
|
|
|
|
|
|
|
EXPECT_FALSE(match(CU32Zero, cst_pred_ty<is_unsigned_max_pred>()));
|
|
|
|
EXPECT_TRUE(match(CU32Zero, cst_pred_ty<is_unsigned_zero_pred>()));
|
|
|
|
EXPECT_TRUE(match(CU32Zero, cst_pred_ty<always_true_pred<APInt>>()));
|
|
|
|
EXPECT_FALSE(match(CU32Zero, cst_pred_ty<always_false_pred<APInt>>()));
|
|
|
|
|
|
|
|
EXPECT_FALSE(match(CU32DeadBeef, cst_pred_ty<is_unsigned_max_pred>()));
|
|
|
|
EXPECT_FALSE(match(CU32DeadBeef, cst_pred_ty<is_unsigned_zero_pred>()));
|
|
|
|
EXPECT_TRUE(match(CU32DeadBeef, cst_pred_ty<always_true_pred<APInt>>()));
|
|
|
|
EXPECT_FALSE(match(CU32DeadBeef, cst_pred_ty<always_false_pred<APInt>>()));
|
|
|
|
|
|
|
|
// Scalar float
|
|
|
|
APFloat F32NaN = APFloat::getNaN(APFloat::IEEEsingle());
|
|
|
|
APFloat F32Zero = APFloat::getZero(APFloat::IEEEsingle());
|
|
|
|
APFloat F32Pi(3.14f);
|
|
|
|
|
|
|
|
Type *F32Ty = Type::getFloatTy(Ctx);
|
|
|
|
|
|
|
|
Constant *CF32NaN = ConstantFP::get(F32Ty, F32NaN);
|
|
|
|
Constant *CF32Zero = ConstantFP::get(F32Ty, F32Zero);
|
|
|
|
Constant *CF32Pi = ConstantFP::get(F32Ty, F32Pi);
|
|
|
|
|
|
|
|
EXPECT_TRUE(match(CF32NaN, cstfp_pred_ty<is_float_nan_pred>()));
|
|
|
|
EXPECT_FALSE(match(CF32NaN, cstfp_pred_ty<is_float_zero_pred>()));
|
|
|
|
EXPECT_TRUE(match(CF32NaN, cstfp_pred_ty<always_true_pred<APFloat>>()));
|
|
|
|
EXPECT_FALSE(match(CF32NaN, cstfp_pred_ty<always_false_pred<APFloat>>()));
|
|
|
|
|
|
|
|
EXPECT_FALSE(match(CF32Zero, cstfp_pred_ty<is_float_nan_pred>()));
|
|
|
|
EXPECT_TRUE(match(CF32Zero, cstfp_pred_ty<is_float_zero_pred>()));
|
|
|
|
EXPECT_TRUE(match(CF32Zero, cstfp_pred_ty<always_true_pred<APFloat>>()));
|
|
|
|
EXPECT_FALSE(match(CF32Zero, cstfp_pred_ty<always_false_pred<APFloat>>()));
|
|
|
|
|
|
|
|
EXPECT_FALSE(match(CF32Pi, cstfp_pred_ty<is_float_nan_pred>()));
|
|
|
|
EXPECT_FALSE(match(CF32Pi, cstfp_pred_ty<is_float_zero_pred>()));
|
|
|
|
EXPECT_TRUE(match(CF32Pi, cstfp_pred_ty<always_true_pred<APFloat>>()));
|
|
|
|
EXPECT_FALSE(match(CF32Pi, cstfp_pred_ty<always_false_pred<APFloat>>()));
|
|
|
|
|
2020-08-19 19:26:36 +02:00
|
|
|
auto FixedEC = ElementCount::getFixed(4);
|
|
|
|
auto ScalableEC = ElementCount::getScalable(4);
|
2020-07-14 22:36:33 +02:00
|
|
|
|
|
|
|
// Vector splat
|
|
|
|
|
|
|
|
for (auto EC : {FixedEC, ScalableEC}) {
|
|
|
|
// integer
|
|
|
|
|
|
|
|
Constant *CSplatU32Max = ConstantVector::getSplat(EC, CU32Max);
|
|
|
|
Constant *CSplatU32Zero = ConstantVector::getSplat(EC, CU32Zero);
|
|
|
|
Constant *CSplatU32DeadBeef = ConstantVector::getSplat(EC, CU32DeadBeef);
|
|
|
|
|
|
|
|
EXPECT_TRUE(match(CSplatU32Max, cst_pred_ty<is_unsigned_max_pred>()));
|
|
|
|
EXPECT_FALSE(match(CSplatU32Max, cst_pred_ty<is_unsigned_zero_pred>()));
|
|
|
|
EXPECT_TRUE(match(CSplatU32Max, cst_pred_ty<always_true_pred<APInt>>()));
|
|
|
|
EXPECT_FALSE(match(CSplatU32Max, cst_pred_ty<always_false_pred<APInt>>()));
|
|
|
|
|
|
|
|
EXPECT_FALSE(match(CSplatU32Zero, cst_pred_ty<is_unsigned_max_pred>()));
|
|
|
|
EXPECT_TRUE(match(CSplatU32Zero, cst_pred_ty<is_unsigned_zero_pred>()));
|
|
|
|
EXPECT_TRUE(match(CSplatU32Zero, cst_pred_ty<always_true_pred<APInt>>()));
|
|
|
|
EXPECT_FALSE(match(CSplatU32Zero, cst_pred_ty<always_false_pred<APInt>>()));
|
|
|
|
|
|
|
|
EXPECT_FALSE(match(CSplatU32DeadBeef, cst_pred_ty<is_unsigned_max_pred>()));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
match(CSplatU32DeadBeef, cst_pred_ty<is_unsigned_zero_pred>()));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
match(CSplatU32DeadBeef, cst_pred_ty<always_true_pred<APInt>>()));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
match(CSplatU32DeadBeef, cst_pred_ty<always_false_pred<APInt>>()));
|
|
|
|
|
|
|
|
// float
|
|
|
|
|
|
|
|
Constant *CSplatF32NaN = ConstantVector::getSplat(EC, CF32NaN);
|
|
|
|
Constant *CSplatF32Zero = ConstantVector::getSplat(EC, CF32Zero);
|
|
|
|
Constant *CSplatF32Pi = ConstantVector::getSplat(EC, CF32Pi);
|
|
|
|
|
|
|
|
EXPECT_TRUE(match(CSplatF32NaN, cstfp_pred_ty<is_float_nan_pred>()));
|
|
|
|
EXPECT_FALSE(match(CSplatF32NaN, cstfp_pred_ty<is_float_zero_pred>()));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
match(CSplatF32NaN, cstfp_pred_ty<always_true_pred<APFloat>>()));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
match(CSplatF32NaN, cstfp_pred_ty<always_false_pred<APFloat>>()));
|
|
|
|
|
|
|
|
EXPECT_FALSE(match(CSplatF32Zero, cstfp_pred_ty<is_float_nan_pred>()));
|
|
|
|
EXPECT_TRUE(match(CSplatF32Zero, cstfp_pred_ty<is_float_zero_pred>()));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
match(CSplatF32Zero, cstfp_pred_ty<always_true_pred<APFloat>>()));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
match(CSplatF32Zero, cstfp_pred_ty<always_false_pred<APFloat>>()));
|
|
|
|
|
|
|
|
EXPECT_FALSE(match(CSplatF32Pi, cstfp_pred_ty<is_float_nan_pred>()));
|
|
|
|
EXPECT_FALSE(match(CSplatF32Pi, cstfp_pred_ty<is_float_zero_pred>()));
|
|
|
|
EXPECT_TRUE(match(CSplatF32Pi, cstfp_pred_ty<always_true_pred<APFloat>>()));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
match(CSplatF32Pi, cstfp_pred_ty<always_false_pred<APFloat>>()));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Int arbitrary vector
|
|
|
|
|
|
|
|
Constant *CMixedU32 = ConstantVector::get({CU32Max, CU32Zero, CU32DeadBeef});
|
|
|
|
Constant *CU32Undef = UndefValue::get(U32Ty);
|
|
|
|
Constant *CU32MaxWithUndef =
|
|
|
|
ConstantVector::get({CU32Undef, CU32Max, CU32Undef});
|
|
|
|
|
|
|
|
EXPECT_FALSE(match(CMixedU32, cst_pred_ty<is_unsigned_max_pred>()));
|
|
|
|
EXPECT_FALSE(match(CMixedU32, cst_pred_ty<is_unsigned_zero_pred>()));
|
|
|
|
EXPECT_TRUE(match(CMixedU32, cst_pred_ty<always_true_pred<APInt>>()));
|
|
|
|
EXPECT_FALSE(match(CMixedU32, cst_pred_ty<always_false_pred<APInt>>()));
|
|
|
|
|
|
|
|
EXPECT_TRUE(match(CU32MaxWithUndef, cst_pred_ty<is_unsigned_max_pred>()));
|
|
|
|
EXPECT_FALSE(match(CU32MaxWithUndef, cst_pred_ty<is_unsigned_zero_pred>()));
|
|
|
|
EXPECT_TRUE(match(CU32MaxWithUndef, cst_pred_ty<always_true_pred<APInt>>()));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
match(CU32MaxWithUndef, cst_pred_ty<always_false_pred<APInt>>()));
|
|
|
|
|
|
|
|
// Float arbitrary vector
|
|
|
|
|
|
|
|
Constant *CMixedF32 = ConstantVector::get({CF32NaN, CF32Zero, CF32Pi});
|
|
|
|
Constant *CF32Undef = UndefValue::get(F32Ty);
|
|
|
|
Constant *CF32NaNWithUndef =
|
|
|
|
ConstantVector::get({CF32Undef, CF32NaN, CF32Undef});
|
|
|
|
|
|
|
|
EXPECT_FALSE(match(CMixedF32, cstfp_pred_ty<is_float_nan_pred>()));
|
|
|
|
EXPECT_FALSE(match(CMixedF32, cstfp_pred_ty<is_float_zero_pred>()));
|
|
|
|
EXPECT_TRUE(match(CMixedF32, cstfp_pred_ty<always_true_pred<APFloat>>()));
|
|
|
|
EXPECT_FALSE(match(CMixedF32, cstfp_pred_ty<always_false_pred<APFloat>>()));
|
|
|
|
|
|
|
|
EXPECT_TRUE(match(CF32NaNWithUndef, cstfp_pred_ty<is_float_nan_pred>()));
|
|
|
|
EXPECT_FALSE(match(CF32NaNWithUndef, cstfp_pred_ty<is_float_zero_pred>()));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
match(CF32NaNWithUndef, cstfp_pred_ty<always_true_pred<APFloat>>()));
|
|
|
|
EXPECT_FALSE(
|
|
|
|
match(CF32NaNWithUndef, cstfp_pred_ty<always_false_pred<APFloat>>()));
|
|
|
|
}
|
|
|
|
|
2020-11-12 21:13:13 +01:00
|
|
|
TEST_F(PatternMatchTest, InsertValue) {
|
|
|
|
Type *StructTy = StructType::create(IRB.getContext(),
|
|
|
|
{IRB.getInt32Ty(), IRB.getInt64Ty()});
|
|
|
|
Value *Ins0 =
|
|
|
|
IRB.CreateInsertValue(UndefValue::get(StructTy), IRB.getInt32(20), 0);
|
|
|
|
Value *Ins1 = IRB.CreateInsertValue(Ins0, IRB.getInt64(90), 1);
|
|
|
|
|
|
|
|
EXPECT_TRUE(match(Ins0, m_InsertValue<0>(m_Value(), m_Value())));
|
|
|
|
EXPECT_FALSE(match(Ins0, m_InsertValue<1>(m_Value(), m_Value())));
|
|
|
|
EXPECT_FALSE(match(Ins1, m_InsertValue<0>(m_Value(), m_Value())));
|
|
|
|
EXPECT_TRUE(match(Ins1, m_InsertValue<1>(m_Value(), m_Value())));
|
|
|
|
|
|
|
|
EXPECT_TRUE(match(Ins0, m_InsertValue<0>(m_Undef(), m_SpecificInt(20))));
|
|
|
|
EXPECT_FALSE(match(Ins0, m_InsertValue<0>(m_Undef(), m_SpecificInt(0))));
|
|
|
|
|
|
|
|
EXPECT_TRUE(
|
|
|
|
match(Ins1, m_InsertValue<1>(m_InsertValue<0>(m_Value(), m_Value()),
|
|
|
|
m_SpecificInt(90))));
|
|
|
|
EXPECT_FALSE(match(IRB.getInt64(99), m_InsertValue<0>(m_Value(), m_Value())));
|
|
|
|
}
|
|
|
|
|
2016-08-13 00:16:05 +02: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;
|
|
|
|
|
Use std::foo_t rather than std::foo in LLVM.
Summary: C++14 migration. No functional change.
Reviewers: bkramer, JDevlieghere, lebedev.ri
Subscribers: MatzeB, hiraditya, jkorous, dexonsmith, arphaman, kadircet, lebedev.ri, usaxena95, cfe-commits, llvm-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D74384
2020-02-11 05:33:08 +01:00
|
|
|
typedef std::tuple_element_t<0, TypeParam> ValueType;
|
|
|
|
typedef std::tuple_element_t<1, TypeParam> InstructionType;
|
2016-08-13 00:16:05 +02:00
|
|
|
|
|
|
|
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 03:54:46 +02:00
|
|
|
} // anonymous namespace.
|