diff options
Diffstat (limited to 'llvm/lib/Target/Mips/MipsInstructionSelector.cpp')
| -rw-r--r-- | llvm/lib/Target/Mips/MipsInstructionSelector.cpp | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/llvm/lib/Target/Mips/MipsInstructionSelector.cpp b/llvm/lib/Target/Mips/MipsInstructionSelector.cpp index 442244af609..8fddcca4cfe 100644 --- a/llvm/lib/Target/Mips/MipsInstructionSelector.cpp +++ b/llvm/lib/Target/Mips/MipsInstructionSelector.cpp @@ -11,6 +11,7 @@ /// \todo This should be generated by TableGen. //===----------------------------------------------------------------------===// +#include "MCTargetDesc/MipsInstPrinter.h" #include "MipsMachineFunction.h" #include "MipsRegisterBankInfo.h" #include "MipsTargetMachine.h" @@ -492,6 +493,84 @@ bool MipsInstructionSelector::select(MachineInstr &I, I.eraseFromParent(); return true; } + case G_FCMP: { + unsigned MipsFCMPCondCode; + bool isLogicallyNegated; + switch (CmpInst::Predicate Cond = static_cast<CmpInst::Predicate>( + I.getOperand(1).getPredicate())) { + case CmpInst::FCMP_UNO: // Unordered + case CmpInst::FCMP_ORD: // Ordered (OR) + MipsFCMPCondCode = Mips::FCOND_UN; + isLogicallyNegated = Cond != CmpInst::FCMP_UNO; + break; + case CmpInst::FCMP_OEQ: // Equal + case CmpInst::FCMP_UNE: // Not Equal (NEQ) + MipsFCMPCondCode = Mips::FCOND_OEQ; + isLogicallyNegated = Cond != CmpInst::FCMP_OEQ; + break; + case CmpInst::FCMP_UEQ: // Unordered or Equal + case CmpInst::FCMP_ONE: // Ordered or Greater Than or Less Than (OGL) + MipsFCMPCondCode = Mips::FCOND_UEQ; + isLogicallyNegated = Cond != CmpInst::FCMP_UEQ; + break; + case CmpInst::FCMP_OLT: // Ordered or Less Than + case CmpInst::FCMP_UGE: // Unordered or Greater Than or Equal (UGE) + MipsFCMPCondCode = Mips::FCOND_OLT; + isLogicallyNegated = Cond != CmpInst::FCMP_OLT; + break; + case CmpInst::FCMP_ULT: // Unordered or Less Than + case CmpInst::FCMP_OGE: // Ordered or Greater Than or Equal (OGE) + MipsFCMPCondCode = Mips::FCOND_ULT; + isLogicallyNegated = Cond != CmpInst::FCMP_ULT; + break; + case CmpInst::FCMP_OLE: // Ordered or Less Than or Equal + case CmpInst::FCMP_UGT: // Unordered or Greater Than (UGT) + MipsFCMPCondCode = Mips::FCOND_OLE; + isLogicallyNegated = Cond != CmpInst::FCMP_OLE; + break; + case CmpInst::FCMP_ULE: // Unordered or Less Than or Equal + case CmpInst::FCMP_OGT: // Ordered or Greater Than (OGT) + MipsFCMPCondCode = Mips::FCOND_ULE; + isLogicallyNegated = Cond != CmpInst::FCMP_ULE; + break; + default: + return false; + } + + // Default compare result in gpr register will be `true`. + // We will move `false` (MIPS::Zero) to gpr result when fcmp gives false + // using MOVF_I. When orignal predicate (Cond) is logically negated + // MipsFCMPCondCode, result is inverted i.e. MOVT_I is used. + unsigned MoveOpcode = isLogicallyNegated ? Mips::MOVT_I : Mips::MOVF_I; + + unsigned TrueInReg = MRI.createVirtualRegister(&Mips::GPR32RegClass); + BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu)) + .addDef(TrueInReg) + .addUse(Mips::ZERO) + .addImm(1); + + unsigned Size = MRI.getType(I.getOperand(2).getReg()).getSizeInBits(); + unsigned FCMPOpcode = + Size == 32 ? Mips::FCMP_S32 + : STI.isFP64bit() ? Mips::FCMP_D64 : Mips::FCMP_D32; + MachineInstr *FCMP = BuildMI(MBB, I, I.getDebugLoc(), TII.get(FCMPOpcode)) + .addUse(I.getOperand(2).getReg()) + .addUse(I.getOperand(3).getReg()) + .addImm(MipsFCMPCondCode); + if (!constrainSelectedInstRegOperands(*FCMP, TII, TRI, RBI)) + return false; + + MachineInstr *Move = BuildMI(MBB, I, I.getDebugLoc(), TII.get(MoveOpcode)) + .addDef(I.getOperand(0).getReg()) + .addUse(Mips::ZERO) + .addUse(Mips::FCC0) + .addUse(TrueInReg); + if (!constrainSelectedInstRegOperands(*Move, TII, TRI, RBI)) + return false; + + I.eraseFromParent(); + return true; + } default: return false; } |

