[GlobalIsel][X86] Support for G_FCMP
Differential Revision: https://reviews.llvm.org/D49172 llvm-svn: 341193
This commit is contained in:
parent
43b15cddac
commit
a26a364e75
|
@ -89,6 +89,8 @@ private:
|
|||
MachineFunction &MF) const;
|
||||
bool selectCmp(MachineInstr &I, MachineRegisterInfo &MRI,
|
||||
MachineFunction &MF) const;
|
||||
bool selectFCmp(MachineInstr &I, MachineRegisterInfo &MRI,
|
||||
MachineFunction &MF) const;
|
||||
bool selectUadde(MachineInstr &I, MachineRegisterInfo &MRI,
|
||||
MachineFunction &MF) const;
|
||||
bool selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const;
|
||||
|
@ -362,6 +364,8 @@ bool X86InstructionSelector::select(MachineInstr &I,
|
|||
return selectAnyext(I, MRI, MF);
|
||||
case TargetOpcode::G_ICMP:
|
||||
return selectCmp(I, MRI, MF);
|
||||
case TargetOpcode::G_FCMP:
|
||||
return selectFCmp(I, MRI, MF);
|
||||
case TargetOpcode::G_UADDE:
|
||||
return selectUadde(I, MRI, MF);
|
||||
case TargetOpcode::G_UNMERGE_VALUES:
|
||||
|
@ -967,6 +971,98 @@ bool X86InstructionSelector::selectCmp(MachineInstr &I,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool X86InstructionSelector::selectFCmp(MachineInstr &I,
|
||||
MachineRegisterInfo &MRI,
|
||||
MachineFunction &MF) const {
|
||||
assert((I.getOpcode() == TargetOpcode::G_FCMP) && "unexpected instruction");
|
||||
|
||||
unsigned LhsReg = I.getOperand(2).getReg();
|
||||
unsigned RhsReg = I.getOperand(3).getReg();
|
||||
CmpInst::Predicate Predicate =
|
||||
(CmpInst::Predicate)I.getOperand(1).getPredicate();
|
||||
|
||||
// FCMP_OEQ and FCMP_UNE cannot be checked with a single instruction.
|
||||
static const uint16_t SETFOpcTable[2][3] = {
|
||||
{X86::SETEr, X86::SETNPr, X86::AND8rr},
|
||||
{X86::SETNEr, X86::SETPr, X86::OR8rr}};
|
||||
const uint16_t *SETFOpc = nullptr;
|
||||
switch (Predicate) {
|
||||
default:
|
||||
break;
|
||||
case CmpInst::FCMP_OEQ:
|
||||
SETFOpc = &SETFOpcTable[0][0];
|
||||
break;
|
||||
case CmpInst::FCMP_UNE:
|
||||
SETFOpc = &SETFOpcTable[1][0];
|
||||
break;
|
||||
}
|
||||
|
||||
// Compute the opcode for the CMP instruction.
|
||||
unsigned OpCmp;
|
||||
LLT Ty = MRI.getType(LhsReg);
|
||||
switch (Ty.getSizeInBits()) {
|
||||
default:
|
||||
return false;
|
||||
case 32:
|
||||
OpCmp = X86::UCOMISSrr;
|
||||
break;
|
||||
case 64:
|
||||
OpCmp = X86::UCOMISDrr;
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned ResultReg = I.getOperand(0).getReg();
|
||||
RBI.constrainGenericRegister(
|
||||
ResultReg,
|
||||
*getRegClass(LLT::scalar(8), *RBI.getRegBank(ResultReg, MRI, TRI)), MRI);
|
||||
if (SETFOpc) {
|
||||
MachineInstr &CmpInst =
|
||||
*BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpCmp))
|
||||
.addReg(LhsReg)
|
||||
.addReg(RhsReg);
|
||||
|
||||
unsigned FlagReg1 = MRI.createVirtualRegister(&X86::GR8RegClass);
|
||||
unsigned FlagReg2 = MRI.createVirtualRegister(&X86::GR8RegClass);
|
||||
MachineInstr &Set1 = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
|
||||
TII.get(SETFOpc[0]), FlagReg1);
|
||||
MachineInstr &Set2 = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
|
||||
TII.get(SETFOpc[1]), FlagReg2);
|
||||
MachineInstr &Set3 = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
|
||||
TII.get(SETFOpc[2]), ResultReg)
|
||||
.addReg(FlagReg1)
|
||||
.addReg(FlagReg2);
|
||||
constrainSelectedInstRegOperands(CmpInst, TII, TRI, RBI);
|
||||
constrainSelectedInstRegOperands(Set1, TII, TRI, RBI);
|
||||
constrainSelectedInstRegOperands(Set2, TII, TRI, RBI);
|
||||
constrainSelectedInstRegOperands(Set3, TII, TRI, RBI);
|
||||
|
||||
I.eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
|
||||
X86::CondCode CC;
|
||||
bool SwapArgs;
|
||||
std::tie(CC, SwapArgs) = X86::getX86ConditionCode(Predicate);
|
||||
assert(CC <= X86::LAST_VALID_COND && "Unexpected condition code.");
|
||||
unsigned Opc = X86::getSETFromCond(CC);
|
||||
|
||||
if (SwapArgs)
|
||||
std::swap(LhsReg, RhsReg);
|
||||
|
||||
// Emit a compare of LHS/RHS.
|
||||
MachineInstr &CmpInst =
|
||||
*BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpCmp))
|
||||
.addReg(LhsReg)
|
||||
.addReg(RhsReg);
|
||||
|
||||
MachineInstr &Set =
|
||||
*BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opc), ResultReg);
|
||||
constrainSelectedInstRegOperands(CmpInst, TII, TRI, RBI);
|
||||
constrainSelectedInstRegOperands(Set, TII, TRI, RBI);
|
||||
I.eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool X86InstructionSelector::selectUadde(MachineInstr &I,
|
||||
MachineRegisterInfo &MRI,
|
||||
MachineFunction &MF) const {
|
||||
|
|
|
@ -222,6 +222,12 @@ void X86LegalizerInfo::setLegalizerInfo64bit() {
|
|||
// Comparison
|
||||
setAction({G_ICMP, 1, s64}, Legal);
|
||||
|
||||
getActionDefinitionsBuilder(G_FCMP)
|
||||
.legalForCartesianProduct({s8}, {s32, s64})
|
||||
.clampScalar(0, s8, s8)
|
||||
.clampScalar(1, s32, s64)
|
||||
.widenScalarToNextPow2(1);
|
||||
|
||||
// Shifts and SDIV
|
||||
getActionDefinitionsBuilder({G_SHL, G_LSHR, G_ASHR, G_SDIV})
|
||||
.legalFor({s8, s16, s32, s64})
|
||||
|
|
|
@ -209,6 +209,21 @@ X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
|
|||
OpRegBankIdx[1] = getPartialMappingIdx(Ty1, /* isFP */ false);
|
||||
break;
|
||||
}
|
||||
case TargetOpcode::G_FCMP: {
|
||||
LLT Ty1 = MRI.getType(MI.getOperand(2).getReg());
|
||||
LLT Ty2 = MRI.getType(MI.getOperand(3).getReg());
|
||||
(void)Ty2;
|
||||
assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() &&
|
||||
"Mismatched operand sizes for G_FCMP");
|
||||
|
||||
unsigned Size = Ty1.getSizeInBits();
|
||||
assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP");
|
||||
|
||||
auto FpRegBank = getPartialMappingIdx(Ty1, /* isFP */ true);
|
||||
OpRegBankIdx = {PMI_GPR8,
|
||||
/* Predicate */ PMI_None, FpRegBank, FpRegBank};
|
||||
break;
|
||||
}
|
||||
case TargetOpcode::G_TRUNC:
|
||||
case TargetOpcode::G_ANYEXT: {
|
||||
auto &Op0 = MI.getOperand(0);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue