Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit 408691f

Browse files
committed
[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
1 parent 4046db0 commit 408691f

File tree

5 files changed

+676
-96
lines changed

5 files changed

+676
-96
lines changed

lib/Target/X86/X86FastISel.cpp

Lines changed: 102 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "X86.h"
1717
#include "X86CallingConv.h"
1818
#include "X86InstrBuilder.h"
19+
#include "X86InstrInfo.h"
1920
#include "X86MachineFunctionInfo.h"
2021
#include "X86RegisterInfo.h"
2122
#include "X86Subtarget.h"
@@ -154,6 +155,44 @@ class X86FastISel final : public FastISel {
154155

155156
} // end anonymous namespace.
156157

158+
static std::pair<X86::CondCode, bool>
159+
getX86ConditonCode(CmpInst::Predicate Predicate) {
160+
X86::CondCode CC = X86::COND_INVALID;
161+
bool NeedSwap = false;
162+
switch (Predicate) {
163+
default: break;
164+
// Floating-point Predicates
165+
case CmpInst::FCMP_UEQ: CC = X86::COND_E; break;
166+
case CmpInst::FCMP_OLT: NeedSwap = true; // fall-through
167+
case CmpInst::FCMP_OGT: CC = X86::COND_A; break;
168+
case CmpInst::FCMP_OLE: NeedSwap = true; // fall-through
169+
case CmpInst::FCMP_OGE: CC = X86::COND_AE; break;
170+
case CmpInst::FCMP_UGT: NeedSwap = true; // fall-through
171+
case CmpInst::FCMP_ULT: CC = X86::COND_B; break;
172+
case CmpInst::FCMP_UGE: NeedSwap = true; // fall-through
173+
case CmpInst::FCMP_ULE: CC = X86::COND_BE; break;
174+
case CmpInst::FCMP_ONE: CC = X86::COND_NE; break;
175+
case CmpInst::FCMP_UNO: CC = X86::COND_P; break;
176+
case CmpInst::FCMP_ORD: CC = X86::COND_NP; break;
177+
case CmpInst::FCMP_OEQ: // fall-through
178+
case CmpInst::FCMP_UNE: CC = X86::COND_INVALID; break;
179+
180+
// Integer Predicates
181+
case CmpInst::ICMP_EQ: CC = X86::COND_E; break;
182+
case CmpInst::ICMP_NE: CC = X86::COND_NE; break;
183+
case CmpInst::ICMP_UGT: CC = X86::COND_A; break;
184+
case CmpInst::ICMP_UGE: CC = X86::COND_AE; break;
185+
case CmpInst::ICMP_ULT: CC = X86::COND_B; break;
186+
case CmpInst::ICMP_ULE: CC = X86::COND_BE; break;
187+
case CmpInst::ICMP_SGT: CC = X86::COND_G; break;
188+
case CmpInst::ICMP_SGE: CC = X86::COND_GE; break;
189+
case CmpInst::ICMP_SLT: CC = X86::COND_L; break;
190+
case CmpInst::ICMP_SLE: CC = X86::COND_LE; break;
191+
}
192+
193+
return std::make_pair(CC, NeedSwap);
194+
}
195+
157196
bool X86FastISel::isTypeLegal(Type *Ty, MVT &VT, bool AllowI1) {
158197
EVT evt = TLI.getValueType(Ty, /*HandleUnknown=*/true);
159198
if (evt == MVT::Other || !evt.isSimple())
@@ -1009,73 +1048,51 @@ bool X86FastISel::X86SelectCmp(const Instruction *I) {
10091048
if (!isTypeLegal(I->getOperand(0)->getType(), VT))
10101049
return false;
10111050

1012-
unsigned ResultReg = createResultReg(&X86::GR8RegClass);
1013-
unsigned SetCCOpc;
1014-
bool SwapArgs; // false -> compare Op0, Op1. true -> compare Op1, Op0.
1051+
// FCMP_OEQ and FCMP_UNE cannot be checked with a single instruction.
1052+
static unsigned SETFOpcTable[2][2] = {
1053+
{ X86::SETEr, X86::SETNPr },
1054+
{ X86::SETNEr, X86::SETPr }
1055+
};
1056+
unsigned *SETFOpc = nullptr;
10151057
switch (CI->getPredicate()) {
1016-
case CmpInst::FCMP_OEQ: {
1017-
if (!X86FastEmitCompare(CI->getOperand(0), CI->getOperand(1), VT))
1018-
return false;
1019-
1020-
unsigned EReg = createResultReg(&X86::GR8RegClass);
1021-
unsigned NPReg = createResultReg(&X86::GR8RegClass);
1022-
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::SETEr), EReg);
1023-
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1024-
TII.get(X86::SETNPr), NPReg);
1025-
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1026-
TII.get(X86::AND8rr), ResultReg).addReg(NPReg).addReg(EReg);
1027-
UpdateValueMap(I, ResultReg);
1028-
return true;
1058+
default: break;
1059+
case CmpInst::FCMP_OEQ: SETFOpc = &SETFOpcTable[0][0]; break;
1060+
case CmpInst::FCMP_UNE: SETFOpc = &SETFOpcTable[1][0]; break;
10291061
}
1030-
case CmpInst::FCMP_UNE: {
1062+
1063+
unsigned ResultReg = createResultReg(&X86::GR8RegClass);
1064+
if (SETFOpc) {
10311065
if (!X86FastEmitCompare(CI->getOperand(0), CI->getOperand(1), VT))
10321066
return false;
10331067

1034-
unsigned NEReg = createResultReg(&X86::GR8RegClass);
1035-
unsigned PReg = createResultReg(&X86::GR8RegClass);
1036-
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::SETNEr), NEReg);
1037-
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::SETPr), PReg);
1038-
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::OR8rr),ResultReg)
1039-
.addReg(PReg).addReg(NEReg);
1068+
unsigned FlagReg1 = createResultReg(&X86::GR8RegClass);
1069+
unsigned FlagReg2 = createResultReg(&X86::GR8RegClass);
1070+
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(SETFOpc[0]),
1071+
FlagReg1);
1072+
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(SETFOpc[1]),
1073+
FlagReg2);
1074+
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::AND8rr),
1075+
ResultReg).addReg(FlagReg1).addReg(FlagReg2);
10401076
UpdateValueMap(I, ResultReg);
10411077
return true;
10421078
}
1043-
case CmpInst::FCMP_OGT: SwapArgs = false; SetCCOpc = X86::SETAr; break;
1044-
case CmpInst::FCMP_OGE: SwapArgs = false; SetCCOpc = X86::SETAEr; break;
1045-
case CmpInst::FCMP_OLT: SwapArgs = true; SetCCOpc = X86::SETAr; break;
1046-
case CmpInst::FCMP_OLE: SwapArgs = true; SetCCOpc = X86::SETAEr; break;
1047-
case CmpInst::FCMP_ONE: SwapArgs = false; SetCCOpc = X86::SETNEr; break;
1048-
case CmpInst::FCMP_ORD: SwapArgs = false; SetCCOpc = X86::SETNPr; break;
1049-
case CmpInst::FCMP_UNO: SwapArgs = false; SetCCOpc = X86::SETPr; break;
1050-
case CmpInst::FCMP_UEQ: SwapArgs = false; SetCCOpc = X86::SETEr; break;
1051-
case CmpInst::FCMP_UGT: SwapArgs = true; SetCCOpc = X86::SETBr; break;
1052-
case CmpInst::FCMP_UGE: SwapArgs = true; SetCCOpc = X86::SETBEr; break;
1053-
case CmpInst::FCMP_ULT: SwapArgs = false; SetCCOpc = X86::SETBr; break;
1054-
case CmpInst::FCMP_ULE: SwapArgs = false; SetCCOpc = X86::SETBEr; break;
1055-
1056-
case CmpInst::ICMP_EQ: SwapArgs = false; SetCCOpc = X86::SETEr; break;
1057-
case CmpInst::ICMP_NE: SwapArgs = false; SetCCOpc = X86::SETNEr; break;
1058-
case CmpInst::ICMP_UGT: SwapArgs = false; SetCCOpc = X86::SETAr; break;
1059-
case CmpInst::ICMP_UGE: SwapArgs = false; SetCCOpc = X86::SETAEr; break;
1060-
case CmpInst::ICMP_ULT: SwapArgs = false; SetCCOpc = X86::SETBr; break;
1061-
case CmpInst::ICMP_ULE: SwapArgs = false; SetCCOpc = X86::SETBEr; break;
1062-
case CmpInst::ICMP_SGT: SwapArgs = false; SetCCOpc = X86::SETGr; break;
1063-
case CmpInst::ICMP_SGE: SwapArgs = false; SetCCOpc = X86::SETGEr; break;
1064-
case CmpInst::ICMP_SLT: SwapArgs = false; SetCCOpc = X86::SETLr; break;
1065-
case CmpInst::ICMP_SLE: SwapArgs = false; SetCCOpc = X86::SETLEr; break;
1066-
default:
1067-
return false;
1068-
}
10691079

1070-
const Value *Op0 = CI->getOperand(0), *Op1 = CI->getOperand(1);
1080+
X86::CondCode CC;
1081+
bool SwapArgs; // false -> compare Op0, Op1. true -> compare Op1, Op0.
1082+
std::tie(CC, SwapArgs) = getX86ConditonCode(CI->getPredicate());
1083+
assert(CC <= X86::LAST_VALID_COND && "Unexpected conditon code.");
1084+
unsigned Opc = X86::getSETFromCond(CC);
1085+
1086+
const Value *LHS = CI->getOperand(0);
1087+
const Value *RHS = CI->getOperand(1);
10711088
if (SwapArgs)
1072-
std::swap(Op0, Op1);
1089+
std::swap(LHS, RHS);
10731090

10741091
// Emit a compare of Op0/Op1.
1075-
if (!X86FastEmitCompare(Op0, Op1, VT))
1092+
if (!X86FastEmitCompare(LHS, RHS, VT))
10761093
return false;
10771094

1078-
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(SetCCOpc), ResultReg);
1095+
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg);
10791096
UpdateValueMap(I, ResultReg);
10801097
return true;
10811098
}
@@ -1152,66 +1169,59 @@ bool X86FastISel::X86SelectBranch(const Instruction *I) {
11521169
Predicate = CmpInst::getInversePredicate(Predicate);
11531170
}
11541171

1155-
bool SwapArgs; // false -> compare Op0, Op1. true -> compare Op1, Op0.
1156-
unsigned BranchOpc; // Opcode to jump on, e.g. "X86::JA"
1157-
1172+
// FCMP_OEQ and FCMP_UNE cannot be expressed with a single flag/conditon
1173+
// code check. Instead two branch instructions are required to check all
1174+
// the flags. First we change the predicate to a supported conditon code,
1175+
// which will be the first branch. Later one we will emit the second
1176+
// branch.
1177+
bool NeedExtraBranch = false;
11581178
switch (Predicate) {
1179+
default: break;
11591180
case CmpInst::FCMP_OEQ:
1160-
std::swap(TrueMBB, FalseMBB);
1161-
Predicate = CmpInst::FCMP_UNE;
1162-
// FALL THROUGH
1163-
case CmpInst::FCMP_UNE: SwapArgs = false; BranchOpc = X86::JNE_4; break;
1164-
case CmpInst::FCMP_OGT: SwapArgs = false; BranchOpc = X86::JA_4; break;
1165-
case CmpInst::FCMP_OGE: SwapArgs = false; BranchOpc = X86::JAE_4; break;
1166-
case CmpInst::FCMP_OLT: SwapArgs = true; BranchOpc = X86::JA_4; break;
1167-
case CmpInst::FCMP_OLE: SwapArgs = true; BranchOpc = X86::JAE_4; break;
1168-
case CmpInst::FCMP_ONE: SwapArgs = false; BranchOpc = X86::JNE_4; break;
1169-
case CmpInst::FCMP_ORD: SwapArgs = false; BranchOpc = X86::JNP_4; break;
1170-
case CmpInst::FCMP_UNO: SwapArgs = false; BranchOpc = X86::JP_4; break;
1171-
case CmpInst::FCMP_UEQ: SwapArgs = false; BranchOpc = X86::JE_4; break;
1172-
case CmpInst::FCMP_UGT: SwapArgs = true; BranchOpc = X86::JB_4; break;
1173-
case CmpInst::FCMP_UGE: SwapArgs = true; BranchOpc = X86::JBE_4; break;
1174-
case CmpInst::FCMP_ULT: SwapArgs = false; BranchOpc = X86::JB_4; break;
1175-
case CmpInst::FCMP_ULE: SwapArgs = false; BranchOpc = X86::JBE_4; break;
1176-
1177-
case CmpInst::ICMP_EQ: SwapArgs = false; BranchOpc = X86::JE_4; break;
1178-
case CmpInst::ICMP_NE: SwapArgs = false; BranchOpc = X86::JNE_4; break;
1179-
case CmpInst::ICMP_UGT: SwapArgs = false; BranchOpc = X86::JA_4; break;
1180-
case CmpInst::ICMP_UGE: SwapArgs = false; BranchOpc = X86::JAE_4; break;
1181-
case CmpInst::ICMP_ULT: SwapArgs = false; BranchOpc = X86::JB_4; break;
1182-
case CmpInst::ICMP_ULE: SwapArgs = false; BranchOpc = X86::JBE_4; break;
1183-
case CmpInst::ICMP_SGT: SwapArgs = false; BranchOpc = X86::JG_4; break;
1184-
case CmpInst::ICMP_SGE: SwapArgs = false; BranchOpc = X86::JGE_4; break;
1185-
case CmpInst::ICMP_SLT: SwapArgs = false; BranchOpc = X86::JL_4; break;
1186-
case CmpInst::ICMP_SLE: SwapArgs = false; BranchOpc = X86::JLE_4; break;
1187-
default:
1188-
return false;
1181+
std::swap(TrueMBB, FalseMBB); // fall-through
1182+
case CmpInst::FCMP_UNE:
1183+
NeedExtraBranch = true;
1184+
Predicate = CmpInst::FCMP_ONE;
1185+
break;
11891186
}
11901187

1191-
const Value *Op0 = CI->getOperand(0), *Op1 = CI->getOperand(1);
1188+
X86::CondCode CC;
1189+
bool SwapArgs; // false -> compare Op0, Op1. true -> compare Op1, Op0.
1190+
unsigned BranchOpc; // Opcode to jump on, e.g. "X86::JA"
1191+
std::tie(CC, SwapArgs) = getX86ConditonCode(Predicate);
1192+
assert(CC <= X86::LAST_VALID_COND && "Unexpected conditon code.");
1193+
1194+
BranchOpc = X86::GetCondBranchFromCond(CC);
1195+
const Value *CmpLHS = CI->getOperand(0);
1196+
const Value *CmpRHS = CI->getOperand(1);
11921197
if (SwapArgs)
1193-
std::swap(Op0, Op1);
1198+
std::swap(CmpLHS, CmpRHS);
11941199

11951200
// Emit a compare of the LHS and RHS, setting the flags.
1196-
if (!X86FastEmitCompare(Op0, Op1, VT))
1201+
if (!X86FastEmitCompare(CmpLHS, CmpRHS, VT))
11971202
return false;
11981203

11991204
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(BranchOpc))
12001205
.addMBB(TrueMBB);
12011206

1202-
if (Predicate == CmpInst::FCMP_UNE) {
1203-
// X86 requires a second branch to handle UNE (and OEQ,
1204-
// which is mapped to UNE above).
1207+
// X86 requires a second branch to handle UNE (and OEQ, which is mapped
1208+
// to UNE above).
1209+
if (NeedExtraBranch) {
12051210
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::JP_4))
12061211
.addMBB(TrueMBB);
12071212
}
12081213

1209-
FastEmitBranch(FalseMBB, DbgLoc);
1214+
// Obtain the branch weight and add the TrueBB to the successor list.
12101215
uint32_t BranchWeight = 0;
12111216
if (FuncInfo.BPI)
12121217
BranchWeight = FuncInfo.BPI->getEdgeWeight(BI->getParent(),
12131218
TrueMBB->getBasicBlock());
12141219
FuncInfo.MBB->addSuccessor(TrueMBB, BranchWeight);
1220+
1221+
// Emits an unconditional branch to the FalseBB, obtains the branch
1222+
// weight, andd adds it to the successor list.
1223+
FastEmitBranch(FalseMBB, DbgLoc);
1224+
12151225
return true;
12161226
}
12171227
} else if (TruncInst *TI = dyn_cast<TruncInst>(BI->getCondition())) {

lib/Target/X86/X86InstrInfo.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2670,8 +2670,7 @@ static X86::CondCode getSwappedCondition(X86::CondCode CC) {
26702670

26712671
/// getSETFromCond - Return a set opcode for the given condition and
26722672
/// whether it has memory operand.
2673-
static unsigned getSETFromCond(X86::CondCode CC,
2674-
bool HasMemoryOperand) {
2673+
unsigned X86::getSETFromCond(CondCode CC, bool HasMemoryOperand) {
26752674
static const uint16_t Opc[16][2] = {
26762675
{ X86::SETAr, X86::SETAm },
26772676
{ X86::SETAEr, X86::SETAEm },
@@ -2691,7 +2690,7 @@ static unsigned getSETFromCond(X86::CondCode CC,
26912690
{ X86::SETSr, X86::SETSm }
26922691
};
26932692

2694-
assert(CC < 16 && "Can only handle standard cond codes");
2693+
assert(CC <= LAST_VALID_COND && "Can only handle standard cond codes");
26952694
return Opc[CC][HasMemoryOperand ? 1 : 0];
26962695
}
26972696

lib/Target/X86/X86InstrInfo.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ namespace X86 {
4646
COND_O = 13,
4747
COND_P = 14,
4848
COND_S = 15,
49+
LAST_VALID_COND = COND_S,
4950

5051
// Artificial condition codes. These are used by AnalyzeBranch
5152
// to indicate a block terminated with two conditional branches to
@@ -61,12 +62,16 @@ namespace X86 {
6162
// Turn condition code into conditional branch opcode.
6263
unsigned GetCondBranchFromCond(CondCode CC);
6364

65+
/// \brief Return a set opcode for the given condition and whether it has
66+
/// a memory operand.
67+
unsigned getSETFromCond(CondCode CC, bool HasMemoryOperand = false);
68+
6469
// Turn CMov opcode into condition code.
6570
CondCode getCondFromCMovOpc(unsigned Opc);
6671

6772
/// GetOppositeBranchCondition - Return the inverse of the specified cond,
6873
/// e.g. turning COND_E to COND_NE.
69-
CondCode GetOppositeBranchCondition(X86::CondCode CC);
74+
CondCode GetOppositeBranchCondition(CondCode CC);
7075
} // end namespace X86;
7176

7277

0 commit comments

Comments
 (0)