mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-10 04:33:40 +00:00
[FastISel][X86] Refactor the code to get the X86 condition from a helper function. NFC.
Make use of helper functions to simplify the branch and compare instruction selection in FastISel. Also add test cases for compare and conditonal branch. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211077 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
4046db0cdb
commit
408691f967
@ -16,6 +16,7 @@
|
||||
#include "X86.h"
|
||||
#include "X86CallingConv.h"
|
||||
#include "X86InstrBuilder.h"
|
||||
#include "X86InstrInfo.h"
|
||||
#include "X86MachineFunctionInfo.h"
|
||||
#include "X86RegisterInfo.h"
|
||||
#include "X86Subtarget.h"
|
||||
@ -154,6 +155,44 @@ private:
|
||||
|
||||
} // end anonymous namespace.
|
||||
|
||||
static std::pair<X86::CondCode, bool>
|
||||
getX86ConditonCode(CmpInst::Predicate Predicate) {
|
||||
X86::CondCode CC = X86::COND_INVALID;
|
||||
bool NeedSwap = false;
|
||||
switch (Predicate) {
|
||||
default: break;
|
||||
// Floating-point Predicates
|
||||
case CmpInst::FCMP_UEQ: CC = X86::COND_E; break;
|
||||
case CmpInst::FCMP_OLT: NeedSwap = true; // fall-through
|
||||
case CmpInst::FCMP_OGT: CC = X86::COND_A; break;
|
||||
case CmpInst::FCMP_OLE: NeedSwap = true; // fall-through
|
||||
case CmpInst::FCMP_OGE: CC = X86::COND_AE; break;
|
||||
case CmpInst::FCMP_UGT: NeedSwap = true; // fall-through
|
||||
case CmpInst::FCMP_ULT: CC = X86::COND_B; break;
|
||||
case CmpInst::FCMP_UGE: NeedSwap = true; // fall-through
|
||||
case CmpInst::FCMP_ULE: CC = X86::COND_BE; break;
|
||||
case CmpInst::FCMP_ONE: CC = X86::COND_NE; break;
|
||||
case CmpInst::FCMP_UNO: CC = X86::COND_P; break;
|
||||
case CmpInst::FCMP_ORD: CC = X86::COND_NP; break;
|
||||
case CmpInst::FCMP_OEQ: // fall-through
|
||||
case CmpInst::FCMP_UNE: CC = X86::COND_INVALID; break;
|
||||
|
||||
// Integer Predicates
|
||||
case CmpInst::ICMP_EQ: CC = X86::COND_E; break;
|
||||
case CmpInst::ICMP_NE: CC = X86::COND_NE; break;
|
||||
case CmpInst::ICMP_UGT: CC = X86::COND_A; break;
|
||||
case CmpInst::ICMP_UGE: CC = X86::COND_AE; break;
|
||||
case CmpInst::ICMP_ULT: CC = X86::COND_B; break;
|
||||
case CmpInst::ICMP_ULE: CC = X86::COND_BE; break;
|
||||
case CmpInst::ICMP_SGT: CC = X86::COND_G; break;
|
||||
case CmpInst::ICMP_SGE: CC = X86::COND_GE; break;
|
||||
case CmpInst::ICMP_SLT: CC = X86::COND_L; break;
|
||||
case CmpInst::ICMP_SLE: CC = X86::COND_LE; break;
|
||||
}
|
||||
|
||||
return std::make_pair(CC, NeedSwap);
|
||||
}
|
||||
|
||||
bool X86FastISel::isTypeLegal(Type *Ty, MVT &VT, bool AllowI1) {
|
||||
EVT evt = TLI.getValueType(Ty, /*HandleUnknown=*/true);
|
||||
if (evt == MVT::Other || !evt.isSimple())
|
||||
@ -1009,73 +1048,51 @@ bool X86FastISel::X86SelectCmp(const Instruction *I) {
|
||||
if (!isTypeLegal(I->getOperand(0)->getType(), VT))
|
||||
return false;
|
||||
|
||||
unsigned ResultReg = createResultReg(&X86::GR8RegClass);
|
||||
unsigned SetCCOpc;
|
||||
bool SwapArgs; // false -> compare Op0, Op1. true -> compare Op1, Op0.
|
||||
// FCMP_OEQ and FCMP_UNE cannot be checked with a single instruction.
|
||||
static unsigned SETFOpcTable[2][2] = {
|
||||
{ X86::SETEr, X86::SETNPr },
|
||||
{ X86::SETNEr, X86::SETPr }
|
||||
};
|
||||
unsigned *SETFOpc = nullptr;
|
||||
switch (CI->getPredicate()) {
|
||||
case CmpInst::FCMP_OEQ: {
|
||||
default: break;
|
||||
case CmpInst::FCMP_OEQ: SETFOpc = &SETFOpcTable[0][0]; break;
|
||||
case CmpInst::FCMP_UNE: SETFOpc = &SETFOpcTable[1][0]; break;
|
||||
}
|
||||
|
||||
unsigned ResultReg = createResultReg(&X86::GR8RegClass);
|
||||
if (SETFOpc) {
|
||||
if (!X86FastEmitCompare(CI->getOperand(0), CI->getOperand(1), VT))
|
||||
return false;
|
||||
|
||||
unsigned EReg = createResultReg(&X86::GR8RegClass);
|
||||
unsigned NPReg = createResultReg(&X86::GR8RegClass);
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::SETEr), EReg);
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
|
||||
TII.get(X86::SETNPr), NPReg);
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
|
||||
TII.get(X86::AND8rr), ResultReg).addReg(NPReg).addReg(EReg);
|
||||
unsigned FlagReg1 = createResultReg(&X86::GR8RegClass);
|
||||
unsigned FlagReg2 = createResultReg(&X86::GR8RegClass);
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(SETFOpc[0]),
|
||||
FlagReg1);
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(SETFOpc[1]),
|
||||
FlagReg2);
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::AND8rr),
|
||||
ResultReg).addReg(FlagReg1).addReg(FlagReg2);
|
||||
UpdateValueMap(I, ResultReg);
|
||||
return true;
|
||||
}
|
||||
case CmpInst::FCMP_UNE: {
|
||||
if (!X86FastEmitCompare(CI->getOperand(0), CI->getOperand(1), VT))
|
||||
return false;
|
||||
|
||||
unsigned NEReg = createResultReg(&X86::GR8RegClass);
|
||||
unsigned PReg = createResultReg(&X86::GR8RegClass);
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::SETNEr), NEReg);
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::SETPr), PReg);
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::OR8rr),ResultReg)
|
||||
.addReg(PReg).addReg(NEReg);
|
||||
UpdateValueMap(I, ResultReg);
|
||||
return true;
|
||||
}
|
||||
case CmpInst::FCMP_OGT: SwapArgs = false; SetCCOpc = X86::SETAr; break;
|
||||
case CmpInst::FCMP_OGE: SwapArgs = false; SetCCOpc = X86::SETAEr; break;
|
||||
case CmpInst::FCMP_OLT: SwapArgs = true; SetCCOpc = X86::SETAr; break;
|
||||
case CmpInst::FCMP_OLE: SwapArgs = true; SetCCOpc = X86::SETAEr; break;
|
||||
case CmpInst::FCMP_ONE: SwapArgs = false; SetCCOpc = X86::SETNEr; break;
|
||||
case CmpInst::FCMP_ORD: SwapArgs = false; SetCCOpc = X86::SETNPr; break;
|
||||
case CmpInst::FCMP_UNO: SwapArgs = false; SetCCOpc = X86::SETPr; break;
|
||||
case CmpInst::FCMP_UEQ: SwapArgs = false; SetCCOpc = X86::SETEr; break;
|
||||
case CmpInst::FCMP_UGT: SwapArgs = true; SetCCOpc = X86::SETBr; break;
|
||||
case CmpInst::FCMP_UGE: SwapArgs = true; SetCCOpc = X86::SETBEr; break;
|
||||
case CmpInst::FCMP_ULT: SwapArgs = false; SetCCOpc = X86::SETBr; break;
|
||||
case CmpInst::FCMP_ULE: SwapArgs = false; SetCCOpc = X86::SETBEr; break;
|
||||
X86::CondCode CC;
|
||||
bool SwapArgs; // false -> compare Op0, Op1. true -> compare Op1, Op0.
|
||||
std::tie(CC, SwapArgs) = getX86ConditonCode(CI->getPredicate());
|
||||
assert(CC <= X86::LAST_VALID_COND && "Unexpected conditon code.");
|
||||
unsigned Opc = X86::getSETFromCond(CC);
|
||||
|
||||
case CmpInst::ICMP_EQ: SwapArgs = false; SetCCOpc = X86::SETEr; break;
|
||||
case CmpInst::ICMP_NE: SwapArgs = false; SetCCOpc = X86::SETNEr; break;
|
||||
case CmpInst::ICMP_UGT: SwapArgs = false; SetCCOpc = X86::SETAr; break;
|
||||
case CmpInst::ICMP_UGE: SwapArgs = false; SetCCOpc = X86::SETAEr; break;
|
||||
case CmpInst::ICMP_ULT: SwapArgs = false; SetCCOpc = X86::SETBr; break;
|
||||
case CmpInst::ICMP_ULE: SwapArgs = false; SetCCOpc = X86::SETBEr; break;
|
||||
case CmpInst::ICMP_SGT: SwapArgs = false; SetCCOpc = X86::SETGr; break;
|
||||
case CmpInst::ICMP_SGE: SwapArgs = false; SetCCOpc = X86::SETGEr; break;
|
||||
case CmpInst::ICMP_SLT: SwapArgs = false; SetCCOpc = X86::SETLr; break;
|
||||
case CmpInst::ICMP_SLE: SwapArgs = false; SetCCOpc = X86::SETLEr; break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
const Value *Op0 = CI->getOperand(0), *Op1 = CI->getOperand(1);
|
||||
const Value *LHS = CI->getOperand(0);
|
||||
const Value *RHS = CI->getOperand(1);
|
||||
if (SwapArgs)
|
||||
std::swap(Op0, Op1);
|
||||
std::swap(LHS, RHS);
|
||||
|
||||
// Emit a compare of Op0/Op1.
|
||||
if (!X86FastEmitCompare(Op0, Op1, VT))
|
||||
if (!X86FastEmitCompare(LHS, RHS, VT))
|
||||
return false;
|
||||
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(SetCCOpc), ResultReg);
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg);
|
||||
UpdateValueMap(I, ResultReg);
|
||||
return true;
|
||||
}
|
||||
@ -1152,66 +1169,59 @@ bool X86FastISel::X86SelectBranch(const Instruction *I) {
|
||||
Predicate = CmpInst::getInversePredicate(Predicate);
|
||||
}
|
||||
|
||||
bool SwapArgs; // false -> compare Op0, Op1. true -> compare Op1, Op0.
|
||||
unsigned BranchOpc; // Opcode to jump on, e.g. "X86::JA"
|
||||
|
||||
// FCMP_OEQ and FCMP_UNE cannot be expressed with a single flag/conditon
|
||||
// code check. Instead two branch instructions are required to check all
|
||||
// the flags. First we change the predicate to a supported conditon code,
|
||||
// which will be the first branch. Later one we will emit the second
|
||||
// branch.
|
||||
bool NeedExtraBranch = false;
|
||||
switch (Predicate) {
|
||||
default: break;
|
||||
case CmpInst::FCMP_OEQ:
|
||||
std::swap(TrueMBB, FalseMBB);
|
||||
Predicate = CmpInst::FCMP_UNE;
|
||||
// FALL THROUGH
|
||||
case CmpInst::FCMP_UNE: SwapArgs = false; BranchOpc = X86::JNE_4; break;
|
||||
case CmpInst::FCMP_OGT: SwapArgs = false; BranchOpc = X86::JA_4; break;
|
||||
case CmpInst::FCMP_OGE: SwapArgs = false; BranchOpc = X86::JAE_4; break;
|
||||
case CmpInst::FCMP_OLT: SwapArgs = true; BranchOpc = X86::JA_4; break;
|
||||
case CmpInst::FCMP_OLE: SwapArgs = true; BranchOpc = X86::JAE_4; break;
|
||||
case CmpInst::FCMP_ONE: SwapArgs = false; BranchOpc = X86::JNE_4; break;
|
||||
case CmpInst::FCMP_ORD: SwapArgs = false; BranchOpc = X86::JNP_4; break;
|
||||
case CmpInst::FCMP_UNO: SwapArgs = false; BranchOpc = X86::JP_4; break;
|
||||
case CmpInst::FCMP_UEQ: SwapArgs = false; BranchOpc = X86::JE_4; break;
|
||||
case CmpInst::FCMP_UGT: SwapArgs = true; BranchOpc = X86::JB_4; break;
|
||||
case CmpInst::FCMP_UGE: SwapArgs = true; BranchOpc = X86::JBE_4; break;
|
||||
case CmpInst::FCMP_ULT: SwapArgs = false; BranchOpc = X86::JB_4; break;
|
||||
case CmpInst::FCMP_ULE: SwapArgs = false; BranchOpc = X86::JBE_4; break;
|
||||
|
||||
case CmpInst::ICMP_EQ: SwapArgs = false; BranchOpc = X86::JE_4; break;
|
||||
case CmpInst::ICMP_NE: SwapArgs = false; BranchOpc = X86::JNE_4; break;
|
||||
case CmpInst::ICMP_UGT: SwapArgs = false; BranchOpc = X86::JA_4; break;
|
||||
case CmpInst::ICMP_UGE: SwapArgs = false; BranchOpc = X86::JAE_4; break;
|
||||
case CmpInst::ICMP_ULT: SwapArgs = false; BranchOpc = X86::JB_4; break;
|
||||
case CmpInst::ICMP_ULE: SwapArgs = false; BranchOpc = X86::JBE_4; break;
|
||||
case CmpInst::ICMP_SGT: SwapArgs = false; BranchOpc = X86::JG_4; break;
|
||||
case CmpInst::ICMP_SGE: SwapArgs = false; BranchOpc = X86::JGE_4; break;
|
||||
case CmpInst::ICMP_SLT: SwapArgs = false; BranchOpc = X86::JL_4; break;
|
||||
case CmpInst::ICMP_SLE: SwapArgs = false; BranchOpc = X86::JLE_4; break;
|
||||
default:
|
||||
return false;
|
||||
std::swap(TrueMBB, FalseMBB); // fall-through
|
||||
case CmpInst::FCMP_UNE:
|
||||
NeedExtraBranch = true;
|
||||
Predicate = CmpInst::FCMP_ONE;
|
||||
break;
|
||||
}
|
||||
|
||||
const Value *Op0 = CI->getOperand(0), *Op1 = CI->getOperand(1);
|
||||
X86::CondCode CC;
|
||||
bool SwapArgs; // false -> compare Op0, Op1. true -> compare Op1, Op0.
|
||||
unsigned BranchOpc; // Opcode to jump on, e.g. "X86::JA"
|
||||
std::tie(CC, SwapArgs) = getX86ConditonCode(Predicate);
|
||||
assert(CC <= X86::LAST_VALID_COND && "Unexpected conditon code.");
|
||||
|
||||
BranchOpc = X86::GetCondBranchFromCond(CC);
|
||||
const Value *CmpLHS = CI->getOperand(0);
|
||||
const Value *CmpRHS = CI->getOperand(1);
|
||||
if (SwapArgs)
|
||||
std::swap(Op0, Op1);
|
||||
std::swap(CmpLHS, CmpRHS);
|
||||
|
||||
// Emit a compare of the LHS and RHS, setting the flags.
|
||||
if (!X86FastEmitCompare(Op0, Op1, VT))
|
||||
if (!X86FastEmitCompare(CmpLHS, CmpRHS, VT))
|
||||
return false;
|
||||
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(BranchOpc))
|
||||
.addMBB(TrueMBB);
|
||||
|
||||
if (Predicate == CmpInst::FCMP_UNE) {
|
||||
// X86 requires a second branch to handle UNE (and OEQ,
|
||||
// which is mapped to UNE above).
|
||||
// X86 requires a second branch to handle UNE (and OEQ, which is mapped
|
||||
// to UNE above).
|
||||
if (NeedExtraBranch) {
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::JP_4))
|
||||
.addMBB(TrueMBB);
|
||||
}
|
||||
|
||||
FastEmitBranch(FalseMBB, DbgLoc);
|
||||
// Obtain the branch weight and add the TrueBB to the successor list.
|
||||
uint32_t BranchWeight = 0;
|
||||
if (FuncInfo.BPI)
|
||||
BranchWeight = FuncInfo.BPI->getEdgeWeight(BI->getParent(),
|
||||
TrueMBB->getBasicBlock());
|
||||
FuncInfo.MBB->addSuccessor(TrueMBB, BranchWeight);
|
||||
|
||||
// Emits an unconditional branch to the FalseBB, obtains the branch
|
||||
// weight, andd adds it to the successor list.
|
||||
FastEmitBranch(FalseMBB, DbgLoc);
|
||||
|
||||
return true;
|
||||
}
|
||||
} else if (TruncInst *TI = dyn_cast<TruncInst>(BI->getCondition())) {
|
||||
|
@ -2670,8 +2670,7 @@ static X86::CondCode getSwappedCondition(X86::CondCode CC) {
|
||||
|
||||
/// getSETFromCond - Return a set opcode for the given condition and
|
||||
/// whether it has memory operand.
|
||||
static unsigned getSETFromCond(X86::CondCode CC,
|
||||
bool HasMemoryOperand) {
|
||||
unsigned X86::getSETFromCond(CondCode CC, bool HasMemoryOperand) {
|
||||
static const uint16_t Opc[16][2] = {
|
||||
{ X86::SETAr, X86::SETAm },
|
||||
{ X86::SETAEr, X86::SETAEm },
|
||||
@ -2691,7 +2690,7 @@ static unsigned getSETFromCond(X86::CondCode CC,
|
||||
{ X86::SETSr, X86::SETSm }
|
||||
};
|
||||
|
||||
assert(CC < 16 && "Can only handle standard cond codes");
|
||||
assert(CC <= LAST_VALID_COND && "Can only handle standard cond codes");
|
||||
return Opc[CC][HasMemoryOperand ? 1 : 0];
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,7 @@ namespace X86 {
|
||||
COND_O = 13,
|
||||
COND_P = 14,
|
||||
COND_S = 15,
|
||||
LAST_VALID_COND = COND_S,
|
||||
|
||||
// Artificial condition codes. These are used by AnalyzeBranch
|
||||
// to indicate a block terminated with two conditional branches to
|
||||
@ -61,12 +62,16 @@ namespace X86 {
|
||||
// Turn condition code into conditional branch opcode.
|
||||
unsigned GetCondBranchFromCond(CondCode CC);
|
||||
|
||||
/// \brief Return a set opcode for the given condition and whether it has
|
||||
/// a memory operand.
|
||||
unsigned getSETFromCond(CondCode CC, bool HasMemoryOperand = false);
|
||||
|
||||
// Turn CMov opcode into condition code.
|
||||
CondCode getCondFromCMovOpc(unsigned Opc);
|
||||
|
||||
/// GetOppositeBranchCondition - Return the inverse of the specified cond,
|
||||
/// e.g. turning COND_E to COND_NE.
|
||||
CondCode GetOppositeBranchCondition(X86::CondCode CC);
|
||||
CondCode GetOppositeBranchCondition(CondCode CC);
|
||||
} // end namespace X86;
|
||||
|
||||
|
||||
|
294
test/CodeGen/X86/fast-isel-cmp-branch2.ll
Normal file
294
test/CodeGen/X86/fast-isel-cmp-branch2.ll
Normal file
@ -0,0 +1,294 @@
|
||||
; RUN: llc < %s -mtriple=x86_64-apple-darwin10 | FileCheck %s
|
||||
; RUN: llc < %s -fast-isel -fast-isel-abort -mtriple=x86_64-apple-darwin10 | FileCheck %s
|
||||
|
||||
define i32 @fcmp_oeq(float %x, float %y) {
|
||||
; CHECK-LABEL: fcmp_oeq
|
||||
; CHECK: ucomiss %xmm1, %xmm0
|
||||
; CHECK-NEXT: jne {{LBB.+_1}}
|
||||
; CHECK-NEXT: jnp {{LBB.+_2}}
|
||||
%1 = fcmp oeq float %x, %y
|
||||
br i1 %1, label %bb1, label %bb2
|
||||
bb2:
|
||||
ret i32 1
|
||||
bb1:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @fcmp_ogt(float %x, float %y) {
|
||||
; CHECK-LABEL: fcmp_ogt
|
||||
; CHECK: ucomiss %xmm1, %xmm0
|
||||
; CHECK-NEXT: jbe {{LBB.+_1}}
|
||||
%1 = fcmp ogt float %x, %y
|
||||
br i1 %1, label %bb1, label %bb2
|
||||
bb2:
|
||||
ret i32 1
|
||||
bb1:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @fcmp_oge(float %x, float %y) {
|
||||
; CHECK-LABEL: fcmp_oge
|
||||
; CHECK: ucomiss %xmm1, %xmm0
|
||||
; CHECK-NEXT: jb {{LBB.+_1}}
|
||||
%1 = fcmp oge float %x, %y
|
||||
br i1 %1, label %bb1, label %bb2
|
||||
bb2:
|
||||
ret i32 1
|
||||
bb1:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @fcmp_olt(float %x, float %y) {
|
||||
; CHECK-LABEL: fcmp_olt
|
||||
; CHECK: ucomiss %xmm0, %xmm1
|
||||
; CHECK-NEXT: jbe {{LBB.+_1}}
|
||||
%1 = fcmp olt float %x, %y
|
||||
br i1 %1, label %bb1, label %bb2
|
||||
bb2:
|
||||
ret i32 1
|
||||
bb1:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @fcmp_ole(float %x, float %y) {
|
||||
; CHECK-LABEL: fcmp_ole
|
||||
; CHECK: ucomiss %xmm0, %xmm1
|
||||
; CHECK-NEXT: jb {{LBB.+_1}}
|
||||
%1 = fcmp ole float %x, %y
|
||||
br i1 %1, label %bb1, label %bb2
|
||||
bb2:
|
||||
ret i32 1
|
||||
bb1:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @fcmp_one(float %x, float %y) {
|
||||
; CHECK-LABEL: fcmp_one
|
||||
; CHECK: ucomiss %xmm1, %xmm0
|
||||
; CHECK-NEXT: je {{LBB.+_1}}
|
||||
%1 = fcmp one float %x, %y
|
||||
br i1 %1, label %bb1, label %bb2
|
||||
bb2:
|
||||
ret i32 1
|
||||
bb1:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @fcmp_ord(float %x, float %y) {
|
||||
; CHECK-LABEL: fcmp_ord
|
||||
; CHECK: ucomiss %xmm1, %xmm0
|
||||
; CHECK-NEXT: jp {{LBB.+_1}}
|
||||
%1 = fcmp ord float %x, %y
|
||||
br i1 %1, label %bb1, label %bb2
|
||||
bb2:
|
||||
ret i32 1
|
||||
bb1:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @fcmp_uno(float %x, float %y) {
|
||||
; CHECK-LABEL: fcmp_uno
|
||||
; CHECK: ucomiss %xmm1, %xmm0
|
||||
; CHECK-NEXT: jp {{LBB.+_2}}
|
||||
%1 = fcmp uno float %x, %y
|
||||
br i1 %1, label %bb1, label %bb2
|
||||
bb2:
|
||||
ret i32 1
|
||||
bb1:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @fcmp_ueq(float %x, float %y) {
|
||||
; CHECK-LABEL: fcmp_ueq
|
||||
; CHECK: ucomiss %xmm1, %xmm0
|
||||
; CHECK-NEXT: je {{LBB.+_2}}
|
||||
%1 = fcmp ueq float %x, %y
|
||||
br i1 %1, label %bb1, label %bb2
|
||||
bb2:
|
||||
ret i32 1
|
||||
bb1:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @fcmp_ugt(float %x, float %y) {
|
||||
; CHECK-LABEL: fcmp_ugt
|
||||
; CHECK: ucomiss %xmm0, %xmm1
|
||||
; CHECK-NEXT: jae {{LBB.+_1}}
|
||||
%1 = fcmp ugt float %x, %y
|
||||
br i1 %1, label %bb1, label %bb2
|
||||
bb2:
|
||||
ret i32 1
|
||||
bb1:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @fcmp_uge(float %x, float %y) {
|
||||
; CHECK-LABEL: fcmp_uge
|
||||
; CHECK: ucomiss %xmm0, %xmm1
|
||||
; CHECK-NEXT: ja {{LBB.+_1}}
|
||||
%1 = fcmp uge float %x, %y
|
||||
br i1 %1, label %bb1, label %bb2
|
||||
bb2:
|
||||
ret i32 1
|
||||
bb1:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @fcmp_ult(float %x, float %y) {
|
||||
; CHECK-LABEL: fcmp_ult
|
||||
; CHECK: ucomiss %xmm1, %xmm0
|
||||
; CHECK-NEXT: jae {{LBB.+_1}}
|
||||
%1 = fcmp ult float %x, %y
|
||||
br i1 %1, label %bb1, label %bb2
|
||||
bb2:
|
||||
ret i32 1
|
||||
bb1:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @fcmp_ule(float %x, float %y) {
|
||||
; CHECK-LABEL: fcmp_ule
|
||||
; CHECK: ucomiss %xmm1, %xmm0
|
||||
; CHECK-NEXT: ja {{LBB.+_1}}
|
||||
%1 = fcmp ule float %x, %y
|
||||
br i1 %1, label %bb1, label %bb2
|
||||
bb2:
|
||||
ret i32 1
|
||||
bb1:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @fcmp_une(float %x, float %y) {
|
||||
; CHECK-LABEL: fcmp_une
|
||||
; CHECK: ucomiss %xmm1, %xmm0
|
||||
; CHECK-NEXT: jne {{LBB.+_2}}
|
||||
; CHECK-NEXT: jp {{LBB.+_2}}
|
||||
; CHECK-NEXT: jmp {{LBB.+_1}}
|
||||
%1 = fcmp une float %x, %y
|
||||
br i1 %1, label %bb1, label %bb2
|
||||
bb2:
|
||||
ret i32 1
|
||||
bb1:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @icmp_eq(i32 %x, i32 %y) {
|
||||
; CHECK-LABEL: icmp_eq
|
||||
; CHECK: cmpl %esi, %edi
|
||||
; CHECK-NEXT: jne {{LBB.+_1}}
|
||||
%1 = icmp eq i32 %x, %y
|
||||
br i1 %1, label %bb1, label %bb2
|
||||
bb2:
|
||||
ret i32 1
|
||||
bb1:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @icmp_ne(i32 %x, i32 %y) {
|
||||
; CHECK-LABEL: icmp_ne
|
||||
; CHECK: cmpl %esi, %edi
|
||||
; CHECK-NEXT: je {{LBB.+_1}}
|
||||
%1 = icmp ne i32 %x, %y
|
||||
br i1 %1, label %bb1, label %bb2
|
||||
bb2:
|
||||
ret i32 1
|
||||
bb1:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @icmp_ugt(i32 %x, i32 %y) {
|
||||
; CHECK-LABEL: icmp_ugt
|
||||
; CHECK: cmpl %esi, %edi
|
||||
; CHECK-NEXT: jbe {{LBB.+_1}}
|
||||
%1 = icmp ugt i32 %x, %y
|
||||
br i1 %1, label %bb1, label %bb2
|
||||
bb2:
|
||||
ret i32 1
|
||||
bb1:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @icmp_uge(i32 %x, i32 %y) {
|
||||
; CHECK-LABEL: icmp_uge
|
||||
; CHECK: cmpl %esi, %edi
|
||||
; CHECK-NEXT: jb {{LBB.+_1}}
|
||||
%1 = icmp uge i32 %x, %y
|
||||
br i1 %1, label %bb1, label %bb2
|
||||
bb2:
|
||||
ret i32 1
|
||||
bb1:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @icmp_ult(i32 %x, i32 %y) {
|
||||
; CHECK-LABEL: icmp_ult
|
||||
; CHECK: cmpl %esi, %edi
|
||||
; CHECK-NEXT: jae {{LBB.+_1}}
|
||||
%1 = icmp ult i32 %x, %y
|
||||
br i1 %1, label %bb1, label %bb2
|
||||
bb2:
|
||||
ret i32 1
|
||||
bb1:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @icmp_ule(i32 %x, i32 %y) {
|
||||
; CHECK-LABEL: icmp_ule
|
||||
; CHECK: cmpl %esi, %edi
|
||||
; CHECK-NEXT: ja {{LBB.+_1}}
|
||||
%1 = icmp ule i32 %x, %y
|
||||
br i1 %1, label %bb1, label %bb2
|
||||
bb2:
|
||||
ret i32 1
|
||||
bb1:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @icmp_sgt(i32 %x, i32 %y) {
|
||||
; CHECK-LABEL: icmp_sgt
|
||||
; CHECK: cmpl %esi, %edi
|
||||
; CHECK-NEXT: jle {{LBB.+_1}}
|
||||
%1 = icmp sgt i32 %x, %y
|
||||
br i1 %1, label %bb1, label %bb2
|
||||
bb2:
|
||||
ret i32 1
|
||||
bb1:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @icmp_sge(i32 %x, i32 %y) {
|
||||
; CHECK-LABEL: icmp_sge
|
||||
; CHECK: cmpl %esi, %edi
|
||||
; CHECK-NEXT: jl {{LBB.+_1}}
|
||||
%1 = icmp sge i32 %x, %y
|
||||
br i1 %1, label %bb1, label %bb2
|
||||
bb2:
|
||||
ret i32 1
|
||||
bb1:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @icmp_slt(i32 %x, i32 %y) {
|
||||
; CHECK-LABEL: icmp_slt
|
||||
; CHECK: cmpl %esi, %edi
|
||||
; CHECK-NEXT: jge {{LBB.+_1}}
|
||||
%1 = icmp slt i32 %x, %y
|
||||
br i1 %1, label %bb1, label %bb2
|
||||
bb2:
|
||||
ret i32 1
|
||||
bb1:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @icmp_sle(i32 %x, i32 %y) {
|
||||
; CHECK-LABEL: icmp_sle
|
||||
; CHECK: cmpl %esi, %edi
|
||||
; CHECK-NEXT: jg {{LBB.+_1}}
|
||||
%1 = icmp sle i32 %x, %y
|
||||
br i1 %1, label %bb1, label %bb2
|
||||
bb2:
|
||||
ret i32 1
|
||||
bb1:
|
||||
ret i32 0
|
||||
}
|
||||
|
272
test/CodeGen/X86/fast-isel-cmp.ll
Normal file
272
test/CodeGen/X86/fast-isel-cmp.ll
Normal file
@ -0,0 +1,272 @@
|
||||
; RUN: llc < %s -mtriple=x86_64-apple-darwin10 | FileCheck %s --check-prefix=SDAG
|
||||
; RUN: llc < %s -fast-isel -fast-isel-abort -mtriple=x86_64-apple-darwin10 | FileCheck %s --check-prefix=FAST
|
||||
|
||||
define zeroext i1 @fcmp_oeq(float %x, float %y) {
|
||||
; SDAG-LABEL: fcmp_oeq
|
||||
; SDAG: cmpeqss %xmm1, %xmm0
|
||||
; SDAG-NEXT: movd %xmm0, %eax
|
||||
; SDAG-NEXT: andl $1, %eax
|
||||
; FAST-LABEL: fcmp_oeq
|
||||
; FAST: ucomiss %xmm1, %xmm0
|
||||
; FAST-NEXT: sete %al
|
||||
; FAST-NEXT: setnp %cl
|
||||
; FAST-NEXT: andb %al, %cl
|
||||
%1 = fcmp oeq float %x, %y
|
||||
ret i1 %1
|
||||
}
|
||||
|
||||
define zeroext i1 @fcmp_ogt(float %x, float %y) {
|
||||
; SDAG-LABEL: fcmp_ogt
|
||||
; SDAG: ucomiss %xmm1, %xmm0
|
||||
; SDAG-NEXT: seta %al
|
||||
; FAST: ucomiss %xmm1, %xmm0
|
||||
; FAST-NEXT: seta %al
|
||||
%1 = fcmp ogt float %x, %y
|
||||
ret i1 %1
|
||||
}
|
||||
|
||||
define zeroext i1 @fcmp_oge(float %x, float %y) {
|
||||
; SDAG-LABEL: fcmp_oge
|
||||
; SDAG: ucomiss %xmm1, %xmm0
|
||||
; SDAG-NEXT: setae %al
|
||||
; FAST-LABEL: fcmp_oge
|
||||
; FAST: ucomiss %xmm1, %xmm0
|
||||
; FAST-NEXT: setae %al
|
||||
%1 = fcmp oge float %x, %y
|
||||
ret i1 %1
|
||||
}
|
||||
|
||||
define zeroext i1 @fcmp_olt(float %x, float %y) {
|
||||
; SDAG-LABEL: fcmp_olt
|
||||
; SDAG: ucomiss %xmm0, %xmm1
|
||||
; SDAG-NEXT: seta %al
|
||||
; FAST-LABEL: fcmp_olt
|
||||
; FAST: ucomiss %xmm0, %xmm1
|
||||
; FAST-NEXT: seta %al
|
||||
%1 = fcmp olt float %x, %y
|
||||
ret i1 %1
|
||||
}
|
||||
|
||||
define zeroext i1 @fcmp_ole(float %x, float %y) {
|
||||
; SDAG-LABEL: fcmp_ole
|
||||
; SDAG: ucomiss %xmm0, %xmm1
|
||||
; SDAG-NEXT: setae %al
|
||||
; FAST-LABEL: fcmp_ole
|
||||
; FAST: ucomiss %xmm0, %xmm1
|
||||
; FAST-NEXT: setae %al
|
||||
%1 = fcmp ole float %x, %y
|
||||
ret i1 %1
|
||||
}
|
||||
|
||||
define zeroext i1 @fcmp_one(float %x, float %y) {
|
||||
; SDAG-LABEL: fcmp_one
|
||||
; SDAG: ucomiss %xmm1, %xmm0
|
||||
; SDAG-NEXT: setne %al
|
||||
; FAST-LABEL: fcmp_one
|
||||
; FAST: ucomiss %xmm1, %xmm0
|
||||
; FAST-NEXT: setne %al
|
||||
%1 = fcmp one float %x, %y
|
||||
ret i1 %1
|
||||
}
|
||||
|
||||
define zeroext i1 @fcmp_ord(float %x, float %y) {
|
||||
; SDAG-LABEL: fcmp_ord
|
||||
; SDAG: ucomiss %xmm1, %xmm0
|
||||
; SDAG-NEXT: setnp %al
|
||||
; FAST-LABEL: fcmp_ord
|
||||
; FAST: ucomiss %xmm1, %xmm0
|
||||
; FAST-NEXT: setnp %al
|
||||
%1 = fcmp ord float %x, %y
|
||||
ret i1 %1
|
||||
}
|
||||
|
||||
define zeroext i1 @fcmp_uno(float %x, float %y) {
|
||||
; SDAG-LABEL: fcmp_uno
|
||||
; SDAG: ucomiss %xmm1, %xmm0
|
||||
; SDAG-NEXT: setp %al
|
||||
; FAST-LABEL: fcmp_uno
|
||||
; FAST: ucomiss %xmm1, %xmm0
|
||||
; FAST-NEXT: setp %al
|
||||
%1 = fcmp uno float %x, %y
|
||||
ret i1 %1
|
||||
}
|
||||
|
||||
define zeroext i1 @fcmp_ueq(float %x, float %y) {
|
||||
; SDAG-LABEL: fcmp_ueq
|
||||
; SDAG: ucomiss %xmm1, %xmm0
|
||||
; SDAG-NEXT: sete %al
|
||||
; FAST-LABEL: fcmp_ueq
|
||||
; FAST: ucomiss %xmm1, %xmm0
|
||||
; FAST-NEXT: sete %al
|
||||
%1 = fcmp ueq float %x, %y
|
||||
ret i1 %1
|
||||
}
|
||||
|
||||
define zeroext i1 @fcmp_ugt(float %x, float %y) {
|
||||
; SDAG-LABEL: fcmp_ugt
|
||||
; SDAG: ucomiss %xmm0, %xmm1
|
||||
; SDAG-NEXT: setb %al
|
||||
; FAST-LABEL: fcmp_ugt
|
||||
; FAST: ucomiss %xmm0, %xmm1
|
||||
; FAST-NEXT: setb %al
|
||||
%1 = fcmp ugt float %x, %y
|
||||
ret i1 %1
|
||||
}
|
||||
|
||||
define zeroext i1 @fcmp_uge(float %x, float %y) {
|
||||
; SDAG-LABEL: fcmp_uge
|
||||
; SDAG: ucomiss %xmm0, %xmm1
|
||||
; SDAG-NEXT: setbe %al
|
||||
; FAST-LABEL: fcmp_uge
|
||||
; FAST: ucomiss %xmm0, %xmm1
|
||||
; FAST-NEXT: setbe %al
|
||||
%1 = fcmp uge float %x, %y
|
||||
ret i1 %1
|
||||
}
|
||||
|
||||
define zeroext i1 @fcmp_ult(float %x, float %y) {
|
||||
; SDAG-LABEL: fcmp_ult
|
||||
; SDAG: ucomiss %xmm1, %xmm0
|
||||
; SDAG-NEXT: setb %al
|
||||
; FAST-LABEL: fcmp_ult
|
||||
; FAST: ucomiss %xmm1, %xmm0
|
||||
; FAST-NEXT: setb %al
|
||||
%1 = fcmp ult float %x, %y
|
||||
ret i1 %1
|
||||
}
|
||||
|
||||
define zeroext i1 @fcmp_ule(float %x, float %y) {
|
||||
; SDAG-LABEL: fcmp_ule
|
||||
; SDAG: ucomiss %xmm1, %xmm0
|
||||
; SDAG-NEXT: setbe %al
|
||||
; FAST-LABEL: fcmp_ule
|
||||
; FAST: ucomiss %xmm1, %xmm0
|
||||
; FAST-NEXT: setbe %al
|
||||
%1 = fcmp ule float %x, %y
|
||||
ret i1 %1
|
||||
}
|
||||
|
||||
define zeroext i1 @fcmp_une(float %x, float %y) {
|
||||
; SDAG-LABEL: fcmp_une
|
||||
; SDAG: cmpneqss %xmm1, %xmm0
|
||||
; SDAG-NEXT: movd %xmm0, %eax
|
||||
; SDAG-NEXT: andl $1, %eax
|
||||
; FAST-LABEL: fcmp_une
|
||||
; FAST: ucomiss %xmm1, %xmm0
|
||||
; FAST-NEXT: setne %al
|
||||
; FAST-NEXT: setp %cl
|
||||
; FAST-NEXT: andb %al, %cl
|
||||
%1 = fcmp une float %x, %y
|
||||
ret i1 %1
|
||||
}
|
||||
|
||||
define zeroext i1 @icmp_eq(i32 %x, i32 %y) {
|
||||
; SDAG-LABEL: icmp_eq
|
||||
; SDAG: cmpl %esi, %edi
|
||||
; SDAG-NEXT: sete %al
|
||||
; FAST-LABEL: icmp_eq
|
||||
; FAST: cmpl %esi, %edi
|
||||
; FAST-NEXT: sete %al
|
||||
%1 = icmp eq i32 %x, %y
|
||||
ret i1 %1
|
||||
}
|
||||
|
||||
define zeroext i1 @icmp_ne(i32 %x, i32 %y) {
|
||||
; SDAG-LABEL: icmp_ne
|
||||
; SDAG: cmpl %esi, %edi
|
||||
; SDAG-NEXT: setne %al
|
||||
; FAST-LABEL: icmp_ne
|
||||
; FAST: cmpl %esi, %edi
|
||||
; FAST-NEXT: setne %al
|
||||
%1 = icmp ne i32 %x, %y
|
||||
ret i1 %1
|
||||
}
|
||||
|
||||
define zeroext i1 @icmp_ugt(i32 %x, i32 %y) {
|
||||
; SDAG-LABEL: icmp_ugt
|
||||
; SDAG: cmpl %edi, %esi
|
||||
; SDAG-NEXT: setb %al
|
||||
; FAST-LABEL: icmp_ugt
|
||||
; FAST: cmpl %esi, %edi
|
||||
; FAST-NEXT: seta %al
|
||||
%1 = icmp ugt i32 %x, %y
|
||||
ret i1 %1
|
||||
}
|
||||
|
||||
define zeroext i1 @icmp_uge(i32 %x, i32 %y) {
|
||||
; SDAG-LABEL: icmp_uge
|
||||
; SDAG: cmpl %esi, %edi
|
||||
; SDAG-NEXT: setae %al
|
||||
; FAST-LABEL: icmp_uge
|
||||
; FAST: cmpl %esi, %edi
|
||||
; FAST-NEXT: setae %al
|
||||
%1 = icmp uge i32 %x, %y
|
||||
ret i1 %1
|
||||
}
|
||||
|
||||
define zeroext i1 @icmp_ult(i32 %x, i32 %y) {
|
||||
; SDAG-LABEL: icmp_ult
|
||||
; SDAG: cmpl %esi, %edi
|
||||
; SDAG-NEXT: setb %al
|
||||
; FAST-LABEL: icmp_ult
|
||||
; FAST: cmpl %esi, %edi
|
||||
; FAST-NEXT: setb %al
|
||||
%1 = icmp ult i32 %x, %y
|
||||
ret i1 %1
|
||||
}
|
||||
|
||||
define zeroext i1 @icmp_ule(i32 %x, i32 %y) {
|
||||
; SDAG-LABEL: icmp_ule
|
||||
; SDAG: cmpl %esi, %edi
|
||||
; SDAG-NEXT: setbe %al
|
||||
; FAST-LABEL: icmp_ule
|
||||
; FAST: cmpl %esi, %edi
|
||||
; FAST-NEXT: setbe %al
|
||||
%1 = icmp ule i32 %x, %y
|
||||
ret i1 %1
|
||||
}
|
||||
|
||||
define zeroext i1 @icmp_sgt(i32 %x, i32 %y) {
|
||||
; SDAG-LABEL: icmp_sgt
|
||||
; SDAG: cmpl %esi, %edi
|
||||
; SDAG-NEXT: setg %al
|
||||
; FAST-LABEL: icmp_sgt
|
||||
; FAST: cmpl %esi, %edi
|
||||
; FAST-NEXT: setg %al
|
||||
%1 = icmp sgt i32 %x, %y
|
||||
ret i1 %1
|
||||
}
|
||||
|
||||
define zeroext i1 @icmp_sge(i32 %x, i32 %y) {
|
||||
; SDAG-LABEL: icmp_sge
|
||||
; SDAG: cmpl %esi, %edi
|
||||
; SDAG-NEXT: setge %al
|
||||
; FAST-LABEL: icmp_sge
|
||||
; FAST: cmpl %esi, %edi
|
||||
; FAST-NEXT: setge %al
|
||||
%1 = icmp sge i32 %x, %y
|
||||
ret i1 %1
|
||||
}
|
||||
|
||||
define zeroext i1 @icmp_slt(i32 %x, i32 %y) {
|
||||
; SDAG-LABEL: icmp_slt
|
||||
; SDAG: cmpl %esi, %edi
|
||||
; SDAG-NEXT: setl %al
|
||||
; FAST-LABEL: icmp_slt
|
||||
; FAST: cmpl %esi, %edi
|
||||
; FAST-NEXT: setl %al
|
||||
%1 = icmp slt i32 %x, %y
|
||||
ret i1 %1
|
||||
}
|
||||
|
||||
define zeroext i1 @icmp_sle(i32 %x, i32 %y) {
|
||||
; SDAG-LABEL: icmp_sle
|
||||
; SDAG: cmpl %esi, %edi
|
||||
; SDAG-NEXT: setle %al
|
||||
; FAST-LABEL: icmp_sle
|
||||
; FAST: cmpl %esi, %edi
|
||||
; FAST-NEXT: setle %al
|
||||
%1 = icmp sle i32 %x, %y
|
||||
ret i1 %1
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user