diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/X86/X86InstructionSelector.cpp | 96 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86LegalizerInfo.cpp | 6 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86RegisterBankInfo.cpp | 15 |
3 files changed, 117 insertions, 0 deletions
diff --git a/llvm/lib/Target/X86/X86InstructionSelector.cpp b/llvm/lib/Target/X86/X86InstructionSelector.cpp index 36d36cb11d7..8be677312b1 100644 --- a/llvm/lib/Target/X86/X86InstructionSelector.cpp +++ b/llvm/lib/Target/X86/X86InstructionSelector.cpp @@ -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 { diff --git a/llvm/lib/Target/X86/X86LegalizerInfo.cpp b/llvm/lib/Target/X86/X86LegalizerInfo.cpp index d372cada8de..2ba00708836 100644 --- a/llvm/lib/Target/X86/X86LegalizerInfo.cpp +++ b/llvm/lib/Target/X86/X86LegalizerInfo.cpp @@ -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}) diff --git a/llvm/lib/Target/X86/X86RegisterBankInfo.cpp b/llvm/lib/Target/X86/X86RegisterBankInfo.cpp index 246d6d5a58d..7e40a9e3a00 100644 --- a/llvm/lib/Target/X86/X86RegisterBankInfo.cpp +++ b/llvm/lib/Target/X86/X86RegisterBankInfo.cpp @@ -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); |