|
16 | 16 | #include "X86.h"
|
17 | 17 | #include "X86CallingConv.h"
|
18 | 18 | #include "X86InstrBuilder.h"
|
| 19 | +#include "X86InstrInfo.h" |
19 | 20 | #include "X86MachineFunctionInfo.h"
|
20 | 21 | #include "X86RegisterInfo.h"
|
21 | 22 | #include "X86Subtarget.h"
|
@@ -154,6 +155,44 @@ class X86FastISel final : public FastISel {
|
154 | 155 |
|
155 | 156 | } // end anonymous namespace.
|
156 | 157 |
|
| 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 | + |
157 | 196 | bool X86FastISel::isTypeLegal(Type *Ty, MVT &VT, bool AllowI1) {
|
158 | 197 | EVT evt = TLI.getValueType(Ty, /*HandleUnknown=*/true);
|
159 | 198 | if (evt == MVT::Other || !evt.isSimple())
|
@@ -1009,73 +1048,51 @@ bool X86FastISel::X86SelectCmp(const Instruction *I) {
|
1009 | 1048 | if (!isTypeLegal(I->getOperand(0)->getType(), VT))
|
1010 | 1049 | return false;
|
1011 | 1050 |
|
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; |
1015 | 1057 | 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; |
1029 | 1061 | }
|
1030 |
| - case CmpInst::FCMP_UNE: { |
| 1062 | + |
| 1063 | + unsigned ResultReg = createResultReg(&X86::GR8RegClass); |
| 1064 | + if (SETFOpc) { |
1031 | 1065 | if (!X86FastEmitCompare(CI->getOperand(0), CI->getOperand(1), VT))
|
1032 | 1066 | return false;
|
1033 | 1067 |
|
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); |
1040 | 1076 | UpdateValueMap(I, ResultReg);
|
1041 | 1077 | return true;
|
1042 | 1078 | }
|
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 |
| - } |
1069 | 1079 |
|
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); |
1071 | 1088 | if (SwapArgs)
|
1072 |
| - std::swap(Op0, Op1); |
| 1089 | + std::swap(LHS, RHS); |
1073 | 1090 |
|
1074 | 1091 | // Emit a compare of Op0/Op1.
|
1075 |
| - if (!X86FastEmitCompare(Op0, Op1, VT)) |
| 1092 | + if (!X86FastEmitCompare(LHS, RHS, VT)) |
1076 | 1093 | return false;
|
1077 | 1094 |
|
1078 |
| - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(SetCCOpc), ResultReg); |
| 1095 | + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg); |
1079 | 1096 | UpdateValueMap(I, ResultReg);
|
1080 | 1097 | return true;
|
1081 | 1098 | }
|
@@ -1152,66 +1169,59 @@ bool X86FastISel::X86SelectBranch(const Instruction *I) {
|
1152 | 1169 | Predicate = CmpInst::getInversePredicate(Predicate);
|
1153 | 1170 | }
|
1154 | 1171 |
|
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; |
1158 | 1178 | switch (Predicate) {
|
| 1179 | + default: break; |
1159 | 1180 | 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; |
1189 | 1186 | }
|
1190 | 1187 |
|
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); |
1192 | 1197 | if (SwapArgs)
|
1193 |
| - std::swap(Op0, Op1); |
| 1198 | + std::swap(CmpLHS, CmpRHS); |
1194 | 1199 |
|
1195 | 1200 | // Emit a compare of the LHS and RHS, setting the flags.
|
1196 |
| - if (!X86FastEmitCompare(Op0, Op1, VT)) |
| 1201 | + if (!X86FastEmitCompare(CmpLHS, CmpRHS, VT)) |
1197 | 1202 | return false;
|
1198 | 1203 |
|
1199 | 1204 | BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(BranchOpc))
|
1200 | 1205 | .addMBB(TrueMBB);
|
1201 | 1206 |
|
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) { |
1205 | 1210 | BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(X86::JP_4))
|
1206 | 1211 | .addMBB(TrueMBB);
|
1207 | 1212 | }
|
1208 | 1213 |
|
1209 |
| - FastEmitBranch(FalseMBB, DbgLoc); |
| 1214 | + // Obtain the branch weight and add the TrueBB to the successor list. |
1210 | 1215 | uint32_t BranchWeight = 0;
|
1211 | 1216 | if (FuncInfo.BPI)
|
1212 | 1217 | BranchWeight = FuncInfo.BPI->getEdgeWeight(BI->getParent(),
|
1213 | 1218 | TrueMBB->getBasicBlock());
|
1214 | 1219 | 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 | + |
1215 | 1225 | return true;
|
1216 | 1226 | }
|
1217 | 1227 | } else if (TruncInst *TI = dyn_cast<TruncInst>(BI->getCondition())) {
|
|
0 commit comments