Skip to content

Commit

Permalink
[GlobalIsel][X86] Support for G_FCMP
Browse files Browse the repository at this point in the history
Differential Revision: https://reviews.llvm.org/D49172

llvm-svn: 341193
  • Loading branch information
Alexander Ivchenko committed Aug 31, 2018
1 parent 43b15cd commit a26a364
Show file tree
Hide file tree
Showing 6 changed files with 3,917 additions and 0 deletions.
96 changes: 96 additions & 0 deletions llvm/lib/Target/X86/X86InstructionSelector.cpp
Expand Up @@ -89,6 +89,8 @@ class X86InstructionSelector : public InstructionSelector {
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;
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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 {
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/X86/X86LegalizerInfo.cpp
Expand Up @@ -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})
Expand Down
15 changes: 15 additions & 0 deletions llvm/lib/Target/X86/X86RegisterBankInfo.cpp
Expand Up @@ -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);
Expand Down

0 comments on commit a26a364

Please sign in to comment.