[AArch64][GlobalISel] Add post-legalizer lowering for NEON vector fcmps

This is roughly equivalent to the floating point portion of
`AArch64TargetLowering::LowerVSETCC`. Main part that's missing is the v4s16 bit.

This also adds helpers equivalent to `EmitVectorComparison`, and
`changeVectorFPCCToAArch64CC`. This moves `changeFCMPPredToAArch64CC` out of
the selector into AArch64GlobalISelUtils for the sake of code reuse.

This is done in post-legalizer lowering with pseudos to simplify selection.
The imported patterns end up handling selection for us this way.

Differential Revision: https://reviews.llvm.org/D101782
This commit is contained in:
Jessica Paquette 2021-05-03 12:21:11 -07:00
parent 061e071d8c
commit 79be9c59c6
9 changed files with 2995 additions and 58 deletions

View File

@ -176,13 +176,20 @@ def bitfield_extract_from_sext_inreg : GICombineRule<
def form_bitfield_extract : GICombineGroup<[bitfield_extract_from_sext_inreg]>;
def lower_vector_fcmp : GICombineRule<
(defs root:$root),
(match (wip_match_opcode G_FCMP):$root,
[{ return lowerVectorFCMP(*${root}, MRI, B); }]),
(apply [{}])>;
// Post-legalization combines which should happen at all optimization levels.
// (E.g. ones that facilitate matching for the selector) For example, matching
// pseudos.
def AArch64PostLegalizerLoweringHelper
: GICombinerHelper<"AArch64GenPostLegalizerLoweringHelper",
[shuffle_vector_lowering, vashr_vlshr_imm,
icmp_lowering, build_vector_lowering]> {
icmp_lowering, build_vector_lowering,
lower_vector_fcmp]> {
let DisableRuleOption = "aarch64postlegalizerlowering-disable-rule";
}

View File

@ -156,6 +156,54 @@ def G_UITOF : AArch64GenericInstruction {
let InOperandList = (ins type0:$src);
}
def G_FCMEQ : AArch64GenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins type0:$src1, type1:$src2);
let hasSideEffects = 0;
}
def G_FCMGE : AArch64GenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins type0:$src1, type1:$src2);
let hasSideEffects = 0;
}
def G_FCMGT : AArch64GenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins type0:$src1, type1:$src2);
let hasSideEffects = 0;
}
def G_FCMEQZ : AArch64GenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins type0:$src);
let hasSideEffects = 0;
}
def G_FCMGEZ : AArch64GenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins type0:$src);
let hasSideEffects = 0;
}
def G_FCMGTZ : AArch64GenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins type0:$src);
let hasSideEffects = 0;
}
def G_FCMLEZ : AArch64GenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins type0:$src);
let hasSideEffects = 0;
}
def G_FCMLTZ : AArch64GenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins type0:$src);
let hasSideEffects = 0;
}
def : GINodeEquiv<G_REV16, AArch64rev16>;
def : GINodeEquiv<G_REV32, AArch64rev32>;
def : GINodeEquiv<G_REV64, AArch64rev64>;
@ -176,6 +224,16 @@ def : GINodeEquiv<G_VLSHR, AArch64vlshr>;
def : GINodeEquiv<G_SITOF, AArch64sitof>;
def : GINodeEquiv<G_UITOF, AArch64uitof>;
def : GINodeEquiv<G_FCMEQ, AArch64fcmeq>;
def : GINodeEquiv<G_FCMGE, AArch64fcmge>;
def : GINodeEquiv<G_FCMGT, AArch64fcmgt>;
def : GINodeEquiv<G_FCMEQZ, AArch64fcmeqz>;
def : GINodeEquiv<G_FCMGEZ, AArch64fcmgez>;
def : GINodeEquiv<G_FCMGTZ, AArch64fcmgtz>;
def : GINodeEquiv<G_FCMLEZ, AArch64fcmlez>;
def : GINodeEquiv<G_FCMLTZ, AArch64fcmltz>;
def : GINodeEquiv<G_EXTRACT_VECTOR_ELT, vector_extract>;
// These are patterns that we only use for GlobalISel via the importer.

View File

@ -12,6 +12,7 @@
#include "AArch64InstrInfo.h"
#include "llvm/CodeGen/GlobalISel/Utils.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@ -93,3 +94,87 @@ bool AArch64GISelUtils::tryEmitBZero(MachineInstr &MI,
MI.eraseFromParent();
return true;
}
void AArch64GISelUtils::changeFCMPPredToAArch64CC(
const CmpInst::Predicate P, AArch64CC::CondCode &CondCode,
AArch64CC::CondCode &CondCode2) {
CondCode2 = AArch64CC::AL;
switch (P) {
default:
llvm_unreachable("Unknown FP condition!");
case CmpInst::FCMP_OEQ:
CondCode = AArch64CC::EQ;
break;
case CmpInst::FCMP_OGT:
CondCode = AArch64CC::GT;
break;
case CmpInst::FCMP_OGE:
CondCode = AArch64CC::GE;
break;
case CmpInst::FCMP_OLT:
CondCode = AArch64CC::MI;
break;
case CmpInst::FCMP_OLE:
CondCode = AArch64CC::LS;
break;
case CmpInst::FCMP_ONE:
CondCode = AArch64CC::MI;
CondCode2 = AArch64CC::GT;
break;
case CmpInst::FCMP_ORD:
CondCode = AArch64CC::VC;
break;
case CmpInst::FCMP_UNO:
CondCode = AArch64CC::VS;
break;
case CmpInst::FCMP_UEQ:
CondCode = AArch64CC::EQ;
CondCode2 = AArch64CC::VS;
break;
case CmpInst::FCMP_UGT:
CondCode = AArch64CC::HI;
break;
case CmpInst::FCMP_UGE:
CondCode = AArch64CC::PL;
break;
case CmpInst::FCMP_ULT:
CondCode = AArch64CC::LT;
break;
case CmpInst::FCMP_ULE:
CondCode = AArch64CC::LE;
break;
case CmpInst::FCMP_UNE:
CondCode = AArch64CC::NE;
break;
}
}
void AArch64GISelUtils::changeVectorFCMPPredToAArch64CC(
const CmpInst::Predicate P, AArch64CC::CondCode &CondCode,
AArch64CC::CondCode &CondCode2, bool &Invert) {
Invert = false;
switch (P) {
default:
// Mostly the scalar mappings work fine.
changeFCMPPredToAArch64CC(P, CondCode, CondCode2);
break;
case CmpInst::FCMP_UNO:
Invert = true;
LLVM_FALLTHROUGH;
case CmpInst::FCMP_ORD:
CondCode = AArch64CC::MI;
CondCode2 = AArch64CC::GE;
break;
case CmpInst::FCMP_UEQ:
case CmpInst::FCMP_ULT:
case CmpInst::FCMP_ULE:
case CmpInst::FCMP_UGT:
case CmpInst::FCMP_UGE:
// All of the compare-mask comparisons are ordered, but we can switch
// between the two by a double inversion. E.g. ULE == !OGT.
Invert = true;
changeFCMPPredToAArch64CC(CmpInst::getInversePredicate(P), CondCode,
CondCode2);
break;
}
}

View File

@ -11,12 +11,12 @@
#ifndef LLVM_LIB_TARGET_AARCH64_GISEL_AARCH64GLOBALISELUTILS_H
#define LLVM_LIB_TARGET_AARCH64_GISEL_AARCH64GLOBALISELUTILS_H
#include "MCTargetDesc/AArch64AddressingModes.h"
#include "Utils/AArch64BaseInfo.h"
#include "llvm/ADT/Optional.h"
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/GlobalISel/Utils.h"
#include "llvm/CodeGen/Register.h"
#include "MCTargetDesc/AArch64AddressingModes.h"
#include "llvm/IR/InstrTypes.h"
#include <cstdint>
@ -53,6 +53,28 @@ bool isCMN(const MachineInstr *MaybeSub, const CmpInst::Predicate &Pred,
/// \returns true if \p MI was replaced with a G_BZERO.
bool tryEmitBZero(MachineInstr &MI, MachineIRBuilder &MIRBuilder, bool MinSize);
/// Find the AArch64 condition codes necessary to represent \p P for a scalar
/// floating point comparison.
///
/// \param [out] CondCode is the first condition code.
/// \param [out] CondCode2 is the second condition code if necessary.
/// AArch64CC::AL otherwise.
void changeFCMPPredToAArch64CC(const CmpInst::Predicate P,
AArch64CC::CondCode &CondCode,
AArch64CC::CondCode &CondCode2);
/// Find the AArch64 condition codes necessary to represent \p P for a vector
/// floating point comparison.
///
/// \param [out] CondCode - The first condition code.
/// \param [out] CondCode2 - The second condition code if necessary.
/// AArch64CC::AL otherwise.
/// \param [out] Invert - True if the comparison must be inverted with a NOT.
void changeVectorFCMPPredToAArch64CC(const CmpInst::Predicate P,
AArch64CC::CondCode &CondCode,
AArch64CC::CondCode &CondCode2,
bool &Invert);
} // namespace AArch64GISelUtils
} // namespace llvm

View File

@ -1231,60 +1231,6 @@ static AArch64CC::CondCode changeICMPPredToAArch64CC(CmpInst::Predicate P) {
}
}
static void changeFCMPPredToAArch64CC(CmpInst::Predicate P,
AArch64CC::CondCode &CondCode,
AArch64CC::CondCode &CondCode2) {
CondCode2 = AArch64CC::AL;
switch (P) {
default:
llvm_unreachable("Unknown FP condition!");
case CmpInst::FCMP_OEQ:
CondCode = AArch64CC::EQ;
break;
case CmpInst::FCMP_OGT:
CondCode = AArch64CC::GT;
break;
case CmpInst::FCMP_OGE:
CondCode = AArch64CC::GE;
break;
case CmpInst::FCMP_OLT:
CondCode = AArch64CC::MI;
break;
case CmpInst::FCMP_OLE:
CondCode = AArch64CC::LS;
break;
case CmpInst::FCMP_ONE:
CondCode = AArch64CC::MI;
CondCode2 = AArch64CC::GT;
break;
case CmpInst::FCMP_ORD:
CondCode = AArch64CC::VC;
break;
case CmpInst::FCMP_UNO:
CondCode = AArch64CC::VS;
break;
case CmpInst::FCMP_UEQ:
CondCode = AArch64CC::EQ;
CondCode2 = AArch64CC::VS;
break;
case CmpInst::FCMP_UGT:
CondCode = AArch64CC::HI;
break;
case CmpInst::FCMP_UGE:
CondCode = AArch64CC::PL;
break;
case CmpInst::FCMP_ULT:
CondCode = AArch64CC::LT;
break;
case CmpInst::FCMP_ULE:
CondCode = AArch64CC::LE;
break;
case CmpInst::FCMP_UNE:
CondCode = AArch64CC::NE;
break;
}
}
/// Return a register which can be used as a bit to test in a TB(N)Z.
static Register getTestBitReg(Register Reg, uint64_t &Bit, bool &Invert,
MachineRegisterInfo &MRI) {

View File

@ -19,9 +19,13 @@
///
//===----------------------------------------------------------------------===//
#include "AArch64TargetMachine.h"
#include "AArch64GlobalISelUtils.h"
#include "AArch64Subtarget.h"
#include "AArch64TargetMachine.h"
#include "GISel/AArch64LegalizerInfo.h"
#include "MCTargetDesc/AArch64MCTargetDesc.h"
#include "TargetInfo/AArch64TargetInfo.h"
#include "Utils/AArch64BaseInfo.h"
#include "llvm/CodeGen/GlobalISel/Combiner.h"
#include "llvm/CodeGen/GlobalISel/CombinerHelper.h"
#include "llvm/CodeGen/GlobalISel/CombinerInfo.h"
@ -33,8 +37,10 @@
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#define DEBUG_TYPE "aarch64-postlegalizer-lowering"
@ -842,6 +848,109 @@ static bool applySwapICmpOperands(MachineInstr &MI,
return true;
}
/// \returns a function which builds a vector floating point compare instruction
/// for a condition code \p CC.
/// \param [in] IsZero - True if the comparison is against 0.
/// \param [in] NoNans - True if the target has NoNansFPMath.
static std::function<Register(MachineIRBuilder &)>
getVectorFCMP(AArch64CC::CondCode CC, Register LHS, Register RHS, bool IsZero,
bool NoNans, MachineRegisterInfo &MRI) {
LLT DstTy = MRI.getType(LHS);
assert(DstTy.isVector() && "Expected vector types only?");
assert(DstTy == MRI.getType(RHS) && "Src and Dst types must match!");
switch (CC) {
default:
llvm_unreachable("Unexpected condition code!");
case AArch64CC::NE:
return [LHS, RHS, IsZero, DstTy](MachineIRBuilder &MIB) {
auto FCmp = IsZero
? MIB.buildInstr(AArch64::G_FCMEQZ, {DstTy}, {LHS})
: MIB.buildInstr(AArch64::G_FCMEQ, {DstTy}, {LHS, RHS});
return MIB.buildNot(DstTy, FCmp).getReg(0);
};
case AArch64CC::EQ:
return [LHS, RHS, IsZero, DstTy](MachineIRBuilder &MIB) {
return IsZero
? MIB.buildInstr(AArch64::G_FCMEQZ, {DstTy}, {LHS}).getReg(0)
: MIB.buildInstr(AArch64::G_FCMEQ, {DstTy}, {LHS, RHS})
.getReg(0);
};
case AArch64CC::GE:
return [LHS, RHS, IsZero, DstTy](MachineIRBuilder &MIB) {
return IsZero
? MIB.buildInstr(AArch64::G_FCMGEZ, {DstTy}, {LHS}).getReg(0)
: MIB.buildInstr(AArch64::G_FCMGE, {DstTy}, {LHS, RHS})
.getReg(0);
};
case AArch64CC::GT:
return [LHS, RHS, IsZero, DstTy](MachineIRBuilder &MIB) {
return IsZero
? MIB.buildInstr(AArch64::G_FCMGTZ, {DstTy}, {LHS}).getReg(0)
: MIB.buildInstr(AArch64::G_FCMGT, {DstTy}, {LHS, RHS})
.getReg(0);
};
case AArch64CC::LS:
return [LHS, RHS, IsZero, DstTy](MachineIRBuilder &MIB) {
return IsZero
? MIB.buildInstr(AArch64::G_FCMLEZ, {DstTy}, {LHS}).getReg(0)
: MIB.buildInstr(AArch64::G_FCMGE, {DstTy}, {RHS, LHS})
.getReg(0);
};
case AArch64CC::MI:
return [LHS, RHS, IsZero, DstTy](MachineIRBuilder &MIB) {
return IsZero
? MIB.buildInstr(AArch64::G_FCMLTZ, {DstTy}, {LHS}).getReg(0)
: MIB.buildInstr(AArch64::G_FCMGT, {DstTy}, {RHS, LHS})
.getReg(0);
};
}
}
/// Try to lower a vector G_FCMP \p MI into an AArch64-specific pseudo.
static bool lowerVectorFCMP(MachineInstr &MI, MachineRegisterInfo &MRI,
MachineIRBuilder &MIB) {
assert(MI.getOpcode() == TargetOpcode::G_FCMP);
const auto &ST = MI.getMF()->getSubtarget<AArch64Subtarget>();
Register Dst = MI.getOperand(0).getReg();
LLT DstTy = MRI.getType(Dst);
if (!DstTy.isVector() || !ST.hasNEON())
return false;
const auto Pred =
static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
Register LHS = MI.getOperand(2).getReg();
// TODO: Handle v4s16 case.
unsigned EltSize = MRI.getType(LHS).getScalarSizeInBits();
if (EltSize != 32 && EltSize != 64)
return false;
Register RHS = MI.getOperand(3).getReg();
auto Splat = getAArch64VectorSplat(*MRI.getVRegDef(RHS), MRI);
// Compares against 0 have special target-specific pseudos.
bool IsZero = Splat && Splat->isCst() && Splat->getCst() == 0;
bool Invert;
AArch64CC::CondCode CC, CC2;
changeVectorFCMPPredToAArch64CC(Pred, CC, CC2, Invert);
bool NoNans = ST.getTargetLowering()->getTargetMachine().Options.NoNaNsFPMath;
// Instead of having an apply function, just build here to simplify things.
MIB.setInstrAndDebugLoc(MI);
auto Cmp = getVectorFCMP(CC, LHS, RHS, IsZero, NoNans, MRI);
Register CmpRes;
if (CC2 == AArch64CC::AL)
CmpRes = Cmp(MIB);
else {
auto Cmp2 = getVectorFCMP(CC2, LHS, RHS, IsZero, NoNans, MRI);
auto Cmp2Dst = Cmp2(MIB);
auto Cmp1Dst = Cmp(MIB);
CmpRes = MIB.buildOr(DstTy, Cmp1Dst, Cmp2Dst).getReg(0);
}
if (Invert)
CmpRes = MIB.buildNot(DstTy, CmpRes).getReg(0);
MRI.replaceRegWith(Dst, CmpRes);
MI.eraseFromParent();
return false;
}
#define AARCH64POSTLEGALIZERLOWERINGHELPER_GENCOMBINERHELPER_DEPS
#include "AArch64GenPostLegalizeGILowering.inc"
#undef AARCH64POSTLEGALIZERLOWERINGHELPER_GENCOMBINERHELPER_DEPS

View File

@ -0,0 +1,672 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -mtriple aarch64 -run-pass=aarch64-postlegalizer-lowering -verify-machineinstrs %s -o - | FileCheck %s
...
---
name: oeq
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; CHECK-LABEL: name: oeq
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %rhs:_(<2 x s64>) = COPY $q1
; CHECK: [[FCMEQ:%[0-9]+]]:_(<2 x s64>) = G_FCMEQ %lhs, %rhs(<2 x s64>)
; CHECK: $q0 = COPY [[FCMEQ]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%rhs:_(<2 x s64>) = COPY $q1
%fcmp:_(<2 x s64>) = G_FCMP floatpred(oeq), %lhs(<2 x s64>), %rhs
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: oeq_zero
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; Should be inverted. Needs two compares.
; CHECK-LABEL: name: oeq_zero
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %zero:_(s64) = G_CONSTANT i64 0
; CHECK: %zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero(s64), %zero(s64)
; CHECK: [[FCMEQZ:%[0-9]+]]:_(<2 x s64>) = G_FCMEQZ %lhs
; CHECK: $q0 = COPY [[FCMEQZ]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%zero:_(s64) = G_CONSTANT i64 0
%zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero, %zero
%fcmp:_(<2 x s64>) = G_FCMP floatpred(oeq), %lhs(<2 x s64>), %zero_vec
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: ogt
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; CHECK-LABEL: name: ogt
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %rhs:_(<2 x s64>) = COPY $q1
; CHECK: [[FCMGT:%[0-9]+]]:_(<2 x s64>) = G_FCMGT %lhs, %rhs(<2 x s64>)
; CHECK: $q0 = COPY [[FCMGT]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%rhs:_(<2 x s64>) = COPY $q1
%fcmp:_(<2 x s64>) = G_FCMP floatpred(ogt), %lhs(<2 x s64>), %rhs
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: ogt_zero
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; CHECK-LABEL: name: ogt_zero
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %zero:_(s64) = G_CONSTANT i64 0
; CHECK: %zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero(s64), %zero(s64)
; CHECK: [[FCMGTZ:%[0-9]+]]:_(<2 x s64>) = G_FCMGTZ %lhs
; CHECK: $q0 = COPY [[FCMGTZ]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%zero:_(s64) = G_CONSTANT i64 0
%zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero, %zero
%fcmp:_(<2 x s64>) = G_FCMP floatpred(ogt), %lhs(<2 x s64>), %zero_vec
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: oge
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; CHECK-LABEL: name: oge
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %rhs:_(<2 x s64>) = COPY $q1
; CHECK: [[FCMGE:%[0-9]+]]:_(<2 x s64>) = G_FCMGE %lhs, %rhs(<2 x s64>)
; CHECK: $q0 = COPY [[FCMGE]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%rhs:_(<2 x s64>) = COPY $q1
%fcmp:_(<2 x s64>) = G_FCMP floatpred(oge), %lhs(<2 x s64>), %rhs
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: oge_zero
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; Should be inverted. Needs two compares.
; CHECK-LABEL: name: oge_zero
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %zero:_(s64) = G_CONSTANT i64 0
; CHECK: %zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero(s64), %zero(s64)
; CHECK: [[FCMGEZ:%[0-9]+]]:_(<2 x s64>) = G_FCMGEZ %lhs
; CHECK: $q0 = COPY [[FCMGEZ]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%zero:_(s64) = G_CONSTANT i64 0
%zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero, %zero
%fcmp:_(<2 x s64>) = G_FCMP floatpred(oge), %lhs(<2 x s64>), %zero_vec
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: olt
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; CHECK-LABEL: name: olt
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %rhs:_(<2 x s64>) = COPY $q1
; CHECK: [[FCMGT:%[0-9]+]]:_(<2 x s64>) = G_FCMGT %rhs, %lhs(<2 x s64>)
; CHECK: $q0 = COPY [[FCMGT]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%rhs:_(<2 x s64>) = COPY $q1
%fcmp:_(<2 x s64>) = G_FCMP floatpred(olt), %lhs(<2 x s64>), %rhs
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: olt_zero
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; CHECK-LABEL: name: olt_zero
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %zero:_(s64) = G_CONSTANT i64 0
; CHECK: %zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero(s64), %zero(s64)
; CHECK: [[FCMLTZ:%[0-9]+]]:_(<2 x s64>) = G_FCMLTZ %lhs
; CHECK: $q0 = COPY [[FCMLTZ]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%zero:_(s64) = G_CONSTANT i64 0
%zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero, %zero
%fcmp:_(<2 x s64>) = G_FCMP floatpred(olt), %lhs(<2 x s64>), %zero_vec
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: ole
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; CHECK-LABEL: name: ole
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %rhs:_(<2 x s64>) = COPY $q1
; CHECK: [[FCMGE:%[0-9]+]]:_(<2 x s64>) = G_FCMGE %rhs, %lhs(<2 x s64>)
; CHECK: $q0 = COPY [[FCMGE]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%rhs:_(<2 x s64>) = COPY $q1
%fcmp:_(<2 x s64>) = G_FCMP floatpred(ole), %lhs(<2 x s64>), %rhs
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: ole_zero
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; CHECK-LABEL: name: ole_zero
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %zero:_(s64) = G_CONSTANT i64 0
; CHECK: %zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero(s64), %zero(s64)
; CHECK: [[FCMLEZ:%[0-9]+]]:_(<2 x s64>) = G_FCMLEZ %lhs
; CHECK: $q0 = COPY [[FCMLEZ]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%zero:_(s64) = G_CONSTANT i64 0
%zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero, %zero
%fcmp:_(<2 x s64>) = G_FCMP floatpred(ole), %lhs(<2 x s64>), %zero_vec
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: one
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; Two compares.
; CHECK-LABEL: name: one
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %rhs:_(<2 x s64>) = COPY $q1
; CHECK: [[FCMGT:%[0-9]+]]:_(<2 x s64>) = G_FCMGT %lhs, %rhs(<2 x s64>)
; CHECK: [[FCMGT1:%[0-9]+]]:_(<2 x s64>) = G_FCMGT %rhs, %lhs(<2 x s64>)
; CHECK: [[OR:%[0-9]+]]:_(<2 x s64>) = G_OR [[FCMGT1]], [[FCMGT]]
; CHECK: $q0 = COPY [[OR]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%rhs:_(<2 x s64>) = COPY $q1
%fcmp:_(<2 x s64>) = G_FCMP floatpred(one), %lhs(<2 x s64>), %rhs
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: one_zero
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; Two compares.
; CHECK-LABEL: name: one_zero
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %zero:_(s64) = G_CONSTANT i64 0
; CHECK: %zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero(s64), %zero(s64)
; CHECK: [[FCMGTZ:%[0-9]+]]:_(<2 x s64>) = G_FCMGTZ %lhs
; CHECK: [[FCMLTZ:%[0-9]+]]:_(<2 x s64>) = G_FCMLTZ %lhs
; CHECK: [[OR:%[0-9]+]]:_(<2 x s64>) = G_OR [[FCMLTZ]], [[FCMGTZ]]
; CHECK: $q0 = COPY [[OR]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%zero:_(s64) = G_CONSTANT i64 0
%zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero, %zero
%fcmp:_(<2 x s64>) = G_FCMP floatpred(one), %lhs(<2 x s64>), %zero_vec
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: uno
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; Should be inverted. Needs two compares.
; CHECK-LABEL: name: uno
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %rhs:_(<2 x s64>) = COPY $q1
; CHECK: [[FCMGE:%[0-9]+]]:_(<2 x s64>) = G_FCMGE %lhs, %rhs(<2 x s64>)
; CHECK: [[FCMGT:%[0-9]+]]:_(<2 x s64>) = G_FCMGT %rhs, %lhs(<2 x s64>)
; CHECK: [[OR:%[0-9]+]]:_(<2 x s64>) = G_OR [[FCMGT]], [[FCMGE]]
; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
; CHECK: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[C]](s64), [[C]](s64)
; CHECK: [[XOR:%[0-9]+]]:_(<2 x s64>) = G_XOR [[OR]], [[BUILD_VECTOR]]
; CHECK: $q0 = COPY [[XOR]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%rhs:_(<2 x s64>) = COPY $q1
%fcmp:_(<2 x s64>) = G_FCMP floatpred(uno), %lhs(<2 x s64>), %rhs
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: uno_zero
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; Should be inverted. Needs two compares.
; CHECK-LABEL: name: uno_zero
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %zero:_(s64) = G_CONSTANT i64 0
; CHECK: %zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero(s64), %zero(s64)
; CHECK: [[FCMGEZ:%[0-9]+]]:_(<2 x s64>) = G_FCMGEZ %lhs
; CHECK: [[FCMLTZ:%[0-9]+]]:_(<2 x s64>) = G_FCMLTZ %lhs
; CHECK: [[OR:%[0-9]+]]:_(<2 x s64>) = G_OR [[FCMLTZ]], [[FCMGEZ]]
; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
; CHECK: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[C]](s64), [[C]](s64)
; CHECK: [[XOR:%[0-9]+]]:_(<2 x s64>) = G_XOR [[OR]], [[BUILD_VECTOR]]
; CHECK: $q0 = COPY [[XOR]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%zero:_(s64) = G_CONSTANT i64 0
%zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero, %zero
%fcmp:_(<2 x s64>) = G_FCMP floatpred(uno), %lhs(<2 x s64>), %zero_vec
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: ord
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; Needs two compares. No invert.
; CHECK-LABEL: name: ord
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %rhs:_(<2 x s64>) = COPY $q1
; CHECK: [[FCMGE:%[0-9]+]]:_(<2 x s64>) = G_FCMGE %lhs, %rhs(<2 x s64>)
; CHECK: [[FCMGT:%[0-9]+]]:_(<2 x s64>) = G_FCMGT %rhs, %lhs(<2 x s64>)
; CHECK: [[OR:%[0-9]+]]:_(<2 x s64>) = G_OR [[FCMGT]], [[FCMGE]]
; CHECK: $q0 = COPY [[OR]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%rhs:_(<2 x s64>) = COPY $q1
%fcmp:_(<2 x s64>) = G_FCMP floatpred(ord), %lhs(<2 x s64>), %rhs
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: ord_zero
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; Needs two compares. No invert.
; CHECK-LABEL: name: ord_zero
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %zero:_(s64) = G_CONSTANT i64 0
; CHECK: %zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero(s64), %zero(s64)
; CHECK: [[FCMGEZ:%[0-9]+]]:_(<2 x s64>) = G_FCMGEZ %lhs
; CHECK: [[FCMLTZ:%[0-9]+]]:_(<2 x s64>) = G_FCMLTZ %lhs
; CHECK: [[OR:%[0-9]+]]:_(<2 x s64>) = G_OR [[FCMLTZ]], [[FCMGEZ]]
; CHECK: $q0 = COPY [[OR]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%zero:_(s64) = G_CONSTANT i64 0
%zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero, %zero
%fcmp:_(<2 x s64>) = G_FCMP floatpred(ord), %lhs(<2 x s64>), %zero_vec
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: ult
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; Should be inverted. Needs two compares.
; CHECK-LABEL: name: ult
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %rhs:_(<2 x s64>) = COPY $q1
; CHECK: [[FCMGE:%[0-9]+]]:_(<2 x s64>) = G_FCMGE %lhs, %rhs(<2 x s64>)
; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
; CHECK: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[C]](s64), [[C]](s64)
; CHECK: [[XOR:%[0-9]+]]:_(<2 x s64>) = G_XOR [[FCMGE]], [[BUILD_VECTOR]]
; CHECK: $q0 = COPY [[XOR]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%rhs:_(<2 x s64>) = COPY $q1
%fcmp:_(<2 x s64>) = G_FCMP floatpred(ult), %lhs(<2 x s64>), %rhs
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: ueq_zero
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; Should be inverted. Needs two compares.
; CHECK-LABEL: name: ueq_zero
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %zero:_(s64) = G_CONSTANT i64 0
; CHECK: %zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero(s64), %zero(s64)
; CHECK: [[FCMGEZ:%[0-9]+]]:_(<2 x s64>) = G_FCMGEZ %lhs
; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
; CHECK: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[C]](s64), [[C]](s64)
; CHECK: [[XOR:%[0-9]+]]:_(<2 x s64>) = G_XOR [[FCMGEZ]], [[BUILD_VECTOR]]
; CHECK: $q0 = COPY [[XOR]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%zero:_(s64) = G_CONSTANT i64 0
%zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero, %zero
%fcmp:_(<2 x s64>) = G_FCMP floatpred(ult), %lhs(<2 x s64>), %zero_vec
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: ule
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; Should be inverted. Needs two compares.
; CHECK-LABEL: name: ule
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %rhs:_(<2 x s64>) = COPY $q1
; CHECK: [[FCMGT:%[0-9]+]]:_(<2 x s64>) = G_FCMGT %lhs, %rhs(<2 x s64>)
; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
; CHECK: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[C]](s64), [[C]](s64)
; CHECK: [[XOR:%[0-9]+]]:_(<2 x s64>) = G_XOR [[FCMGT]], [[BUILD_VECTOR]]
; CHECK: $q0 = COPY [[XOR]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%rhs:_(<2 x s64>) = COPY $q1
%fcmp:_(<2 x s64>) = G_FCMP floatpred(ule), %lhs(<2 x s64>), %rhs
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: ule_zero
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; Should be inverted. Needs two compares.
; CHECK-LABEL: name: ule_zero
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %zero:_(s64) = G_CONSTANT i64 0
; CHECK: %zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero(s64), %zero(s64)
; CHECK: [[FCMGTZ:%[0-9]+]]:_(<2 x s64>) = G_FCMGTZ %lhs
; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
; CHECK: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[C]](s64), [[C]](s64)
; CHECK: [[XOR:%[0-9]+]]:_(<2 x s64>) = G_XOR [[FCMGTZ]], [[BUILD_VECTOR]]
; CHECK: $q0 = COPY [[XOR]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%zero:_(s64) = G_CONSTANT i64 0
%zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero, %zero
%fcmp:_(<2 x s64>) = G_FCMP floatpred(ule), %lhs(<2 x s64>), %zero_vec
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: ugt
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; Should be inverted. Needs two compares.
; CHECK-LABEL: name: ugt
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %rhs:_(<2 x s64>) = COPY $q1
; CHECK: [[FCMGE:%[0-9]+]]:_(<2 x s64>) = G_FCMGE %rhs, %lhs(<2 x s64>)
; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
; CHECK: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[C]](s64), [[C]](s64)
; CHECK: [[XOR:%[0-9]+]]:_(<2 x s64>) = G_XOR [[FCMGE]], [[BUILD_VECTOR]]
; CHECK: $q0 = COPY [[XOR]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%rhs:_(<2 x s64>) = COPY $q1
%fcmp:_(<2 x s64>) = G_FCMP floatpred(ugt), %lhs(<2 x s64>), %rhs
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: ugt_zero
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; Should be inverted. Needs two compares.
; CHECK-LABEL: name: ugt_zero
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %zero:_(s64) = G_CONSTANT i64 0
; CHECK: %zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero(s64), %zero(s64)
; CHECK: [[FCMLEZ:%[0-9]+]]:_(<2 x s64>) = G_FCMLEZ %lhs
; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
; CHECK: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[C]](s64), [[C]](s64)
; CHECK: [[XOR:%[0-9]+]]:_(<2 x s64>) = G_XOR [[FCMLEZ]], [[BUILD_VECTOR]]
; CHECK: $q0 = COPY [[XOR]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%zero:_(s64) = G_CONSTANT i64 0
%zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero, %zero
%fcmp:_(<2 x s64>) = G_FCMP floatpred(ugt), %lhs(<2 x s64>), %zero_vec
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: uge
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; Should be inverted. Needs two compares.
; CHECK-LABEL: name: uge
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %rhs:_(<2 x s64>) = COPY $q1
; CHECK: [[FCMGT:%[0-9]+]]:_(<2 x s64>) = G_FCMGT %rhs, %lhs(<2 x s64>)
; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
; CHECK: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[C]](s64), [[C]](s64)
; CHECK: [[XOR:%[0-9]+]]:_(<2 x s64>) = G_XOR [[FCMGT]], [[BUILD_VECTOR]]
; CHECK: $q0 = COPY [[XOR]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%rhs:_(<2 x s64>) = COPY $q1
%fcmp:_(<2 x s64>) = G_FCMP floatpred(uge), %lhs(<2 x s64>), %rhs
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: uge_zero
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; Should be inverted. Needs two compares.
; CHECK-LABEL: name: uge_zero
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %zero:_(s64) = G_CONSTANT i64 0
; CHECK: %zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero(s64), %zero(s64)
; CHECK: [[FCMLTZ:%[0-9]+]]:_(<2 x s64>) = G_FCMLTZ %lhs
; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
; CHECK: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[C]](s64), [[C]](s64)
; CHECK: [[XOR:%[0-9]+]]:_(<2 x s64>) = G_XOR [[FCMLTZ]], [[BUILD_VECTOR]]
; CHECK: $q0 = COPY [[XOR]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%zero:_(s64) = G_CONSTANT i64 0
%zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero, %zero
%fcmp:_(<2 x s64>) = G_FCMP floatpred(uge), %lhs(<2 x s64>), %zero_vec
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: une
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; Negated EQ.
; CHECK-LABEL: name: une
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %rhs:_(<2 x s64>) = COPY $q1
; CHECK: [[FCMEQ:%[0-9]+]]:_(<2 x s64>) = G_FCMEQ %lhs, %rhs(<2 x s64>)
; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
; CHECK: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[C]](s64), [[C]](s64)
; CHECK: [[XOR:%[0-9]+]]:_(<2 x s64>) = G_XOR [[FCMEQ]], [[BUILD_VECTOR]]
; CHECK: $q0 = COPY [[XOR]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%rhs:_(<2 x s64>) = COPY $q1
%fcmp:_(<2 x s64>) = G_FCMP floatpred(une), %lhs(<2 x s64>), %rhs
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: une_zero
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; Negated EQ.
; CHECK-LABEL: name: une_zero
; CHECK: %lhs:_(<2 x s64>) = COPY $q0
; CHECK: %zero:_(s64) = G_CONSTANT i64 0
; CHECK: %zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero(s64), %zero(s64)
; CHECK: [[FCMEQZ:%[0-9]+]]:_(<2 x s64>) = G_FCMEQZ %lhs
; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
; CHECK: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[C]](s64), [[C]](s64)
; CHECK: [[XOR:%[0-9]+]]:_(<2 x s64>) = G_XOR [[FCMEQZ]], [[BUILD_VECTOR]]
; CHECK: $q0 = COPY [[XOR]](<2 x s64>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<2 x s64>) = COPY $q0
%zero:_(s64) = G_CONSTANT i64 0
%zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero, %zero
%fcmp:_(<2 x s64>) = G_FCMP floatpred(une), %lhs(<2 x s64>), %zero_vec
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: dont_lower_s16
alignment: 4
legalized: true
body: |
bb.0:
liveins: $q0, $q1
; CHECK-LABEL: name: dont_lower_s16
; CHECK: %lhs:_(<8 x s16>) = COPY $q0
; CHECK: %rhs:_(<8 x s16>) = COPY $q1
; CHECK: %fcmp:_(<8 x s16>) = G_FCMP floatpred(oeq), %lhs(<8 x s16>), %rhs
; CHECK: $q0 = COPY %fcmp(<8 x s16>)
; CHECK: RET_ReallyLR implicit $q0
%lhs:_(<8 x s16>) = COPY $q0
%rhs:_(<8 x s16>) = COPY $q1
%fcmp:_(<8 x s16>) = G_FCMP floatpred(oeq), %lhs(<8 x s16>), %rhs
$q0 = COPY %fcmp(<8 x s16>)
RET_ReallyLR implicit $q0

View File

@ -0,0 +1,162 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -mtriple=aarch64 -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s
...
---
name: fcmeq
alignment: 4
legalized: true
regBankSelected: true
body: |
bb.0:
; CHECK-LABEL: name: fcmeq
; CHECK: %lhs:fpr128 = COPY $q0
; CHECK: %rhs:fpr128 = COPY $q1
; CHECK: %fcmp:fpr128 = FCMEQv2f64 %lhs, %rhs
; CHECK: $q0 = COPY %fcmp
; CHECK: RET_ReallyLR implicit $q0
%lhs:fpr(<2 x s64>) = COPY $q0
%rhs:fpr(<2 x s64>) = COPY $q1
%fcmp:fpr(<2 x s64>) = G_FCMEQ %lhs, %rhs(<2 x s64>)
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: fcmge
alignment: 4
legalized: true
regBankSelected: true
body: |
bb.0:
; CHECK-LABEL: name: fcmge
; CHECK: %lhs:fpr128 = COPY $q0
; CHECK: %rhs:fpr128 = COPY $q1
; CHECK: %fcmp:fpr128 = FCMGEv2f64 %lhs, %rhs
; CHECK: $q0 = COPY %fcmp
; CHECK: RET_ReallyLR implicit $q0
%lhs:fpr(<2 x s64>) = COPY $q0
%rhs:fpr(<2 x s64>) = COPY $q1
%fcmp:fpr(<2 x s64>) = G_FCMGE %lhs, %rhs(<2 x s64>)
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: fcmgt
alignment: 4
legalized: true
regBankSelected: true
body: |
bb.0:
; CHECK-LABEL: name: fcmgt
; CHECK: %lhs:fpr128 = COPY $q0
; CHECK: %rhs:fpr128 = COPY $q1
; CHECK: %fcmp:fpr128 = FCMGTv2f64 %lhs, %rhs
; CHECK: $q0 = COPY %fcmp
; CHECK: RET_ReallyLR implicit $q0
%lhs:fpr(<2 x s64>) = COPY $q0
%rhs:fpr(<2 x s64>) = COPY $q1
%fcmp:fpr(<2 x s64>) = G_FCMGT %lhs, %rhs(<2 x s64>)
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: fcmeqz
alignment: 4
legalized: true
regBankSelected: true
body: |
bb.0:
; CHECK-LABEL: name: fcmeqz
; CHECK: %lhs:fpr128 = COPY $q0
; CHECK: %fcmp:fpr128 = FCMEQv2i64rz %lhs
; CHECK: $q0 = COPY %fcmp
; CHECK: RET_ReallyLR implicit $q0
%lhs:fpr(<2 x s64>) = COPY $q0
%zero:gpr(s64) = G_CONSTANT i64 0
%zero_vec:fpr(<2 x s64>) = G_BUILD_VECTOR %zero(s64), %zero(s64)
%fcmp:fpr(<2 x s64>) = G_FCMEQZ %lhs
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: fcmgez
alignment: 4
legalized: true
regBankSelected: true
body: |
bb.0:
; CHECK-LABEL: name: fcmgez
; CHECK: %lhs:fpr128 = COPY $q0
; CHECK: %fcmp:fpr128 = FCMGEv2i64rz %lhs
; CHECK: $q0 = COPY %fcmp
; CHECK: RET_ReallyLR implicit $q0
%lhs:fpr(<2 x s64>) = COPY $q0
%zero:gpr(s64) = G_CONSTANT i64 0
%zero_vec:fpr(<2 x s64>) = G_BUILD_VECTOR %zero(s64), %zero(s64)
%fcmp:fpr(<2 x s64>) = G_FCMGEZ %lhs
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: fcmgtz
alignment: 4
legalized: true
regBankSelected: true
body: |
bb.0:
; CHECK-LABEL: name: fcmgtz
; CHECK: %lhs:fpr128 = COPY $q0
; CHECK: %fcmp:fpr128 = FCMGTv2i64rz %lhs
; CHECK: $q0 = COPY %fcmp
; CHECK: RET_ReallyLR implicit $q0
%lhs:fpr(<2 x s64>) = COPY $q0
%zero:gpr(s64) = G_CONSTANT i64 0
%zero_vec:fpr(<2 x s64>) = G_BUILD_VECTOR %zero(s64), %zero(s64)
%fcmp:fpr(<2 x s64>) = G_FCMGTZ %lhs
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: fcmlez
alignment: 4
legalized: true
regBankSelected: true
body: |
bb.0:
; CHECK-LABEL: name: fcmlez
; CHECK: %lhs:fpr128 = COPY $q0
; CHECK: %fcmp:fpr128 = FCMLEv2i64rz %lhs
; CHECK: $q0 = COPY %fcmp
; CHECK: RET_ReallyLR implicit $q0
%lhs:fpr(<2 x s64>) = COPY $q0
%zero:gpr(s64) = G_CONSTANT i64 0
%zero_vec:fpr(<2 x s64>) = G_BUILD_VECTOR %zero(s64), %zero(s64)
%fcmp:fpr(<2 x s64>) = G_FCMLEZ %lhs
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0
...
---
name: fcmltz
alignment: 4
legalized: true
regBankSelected: true
body: |
bb.0:
; CHECK-LABEL: name: fcmltz
; CHECK: %lhs:fpr128 = COPY $q0
; CHECK: %fcmp:fpr128 = FCMLTv2i64rz %lhs
; CHECK: $q0 = COPY %fcmp
; CHECK: RET_ReallyLR implicit $q0
%lhs:fpr(<2 x s64>) = COPY $q0
%zero:gpr(s64) = G_CONSTANT i64 0
%zero_vec:fpr(<2 x s64>) = G_BUILD_VECTOR %zero(s64), %zero(s64)
%fcmp:fpr(<2 x s64>) = G_FCMLTZ %lhs
$q0 = COPY %fcmp(<2 x s64>)
RET_ReallyLR implicit $q0

File diff suppressed because it is too large Load Diff