|  | //===- MipsLegalizerInfo.cpp ------------------------------------*- C++ -*-===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | /// \file | 
|  | /// This file implements the targeting of the Machinelegalizer class for Mips. | 
|  | /// \todo This should be generated by TableGen. | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "MipsLegalizerInfo.h" | 
|  | #include "MipsTargetMachine.h" | 
|  | #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" | 
|  |  | 
|  | using namespace llvm; | 
|  |  | 
|  | MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) { | 
|  | using namespace TargetOpcode; | 
|  |  | 
|  | const LLT s32 = LLT::scalar(32); | 
|  | const LLT s64 = LLT::scalar(64); | 
|  | const LLT p0 = LLT::pointer(0, 32); | 
|  |  | 
|  | getActionDefinitionsBuilder(G_ADD) | 
|  | .legalFor({s32}) | 
|  | .minScalar(0, s32) | 
|  | .customFor({s64}); | 
|  |  | 
|  | getActionDefinitionsBuilder({G_LOAD, G_STORE}) | 
|  | .legalForCartesianProduct({p0, s32}, {p0}); | 
|  |  | 
|  | getActionDefinitionsBuilder({G_AND, G_OR, G_XOR, G_SHL, G_ASHR, G_LSHR}) | 
|  | .legalFor({s32}); | 
|  |  | 
|  | getActionDefinitionsBuilder(G_ICMP) | 
|  | .legalFor({{s32, s32}}) | 
|  | .minScalar(0, s32); | 
|  |  | 
|  | getActionDefinitionsBuilder(G_CONSTANT) | 
|  | .legalFor({s32}) | 
|  | .clampScalar(0, s32, s32); | 
|  |  | 
|  | getActionDefinitionsBuilder(G_GEP) | 
|  | .legalFor({{p0, s32}}); | 
|  |  | 
|  | getActionDefinitionsBuilder(G_FRAME_INDEX) | 
|  | .legalFor({p0}); | 
|  |  | 
|  | getActionDefinitionsBuilder(G_GLOBAL_VALUE) | 
|  | .legalFor({p0}); | 
|  |  | 
|  | computeTables(); | 
|  | verify(*ST.getInstrInfo()); | 
|  | } | 
|  |  | 
|  | bool MipsLegalizerInfo::legalizeCustom(MachineInstr &MI, | 
|  | MachineRegisterInfo &MRI, | 
|  | MachineIRBuilder &MIRBuilder, | 
|  | GISelChangeObserver &Observer) const { | 
|  |  | 
|  | using namespace TargetOpcode; | 
|  |  | 
|  | MIRBuilder.setInstr(MI); | 
|  |  | 
|  | switch (MI.getOpcode()) { | 
|  | case G_ADD: { | 
|  | unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); | 
|  |  | 
|  | const LLT sHalf = LLT::scalar(Size / 2); | 
|  |  | 
|  | unsigned RHSLow = MRI.createGenericVirtualRegister(sHalf); | 
|  | unsigned RHSHigh = MRI.createGenericVirtualRegister(sHalf); | 
|  | unsigned LHSLow = MRI.createGenericVirtualRegister(sHalf); | 
|  | unsigned LHSHigh = MRI.createGenericVirtualRegister(sHalf); | 
|  | unsigned ResLow = MRI.createGenericVirtualRegister(sHalf); | 
|  | unsigned ResHigh = MRI.createGenericVirtualRegister(sHalf); | 
|  | unsigned Carry = MRI.createGenericVirtualRegister(sHalf); | 
|  | unsigned TmpResHigh = MRI.createGenericVirtualRegister(sHalf); | 
|  |  | 
|  | MIRBuilder.buildUnmerge({RHSLow, RHSHigh}, MI.getOperand(2).getReg()); | 
|  | MIRBuilder.buildUnmerge({LHSLow, LHSHigh}, MI.getOperand(1).getReg()); | 
|  |  | 
|  | MIRBuilder.buildAdd(TmpResHigh, LHSHigh, RHSHigh); | 
|  | MIRBuilder.buildAdd(ResLow, LHSLow, RHSLow); | 
|  | MIRBuilder.buildICmp(CmpInst::ICMP_ULT, Carry, ResLow, LHSLow); | 
|  | MIRBuilder.buildAdd(ResHigh, TmpResHigh, Carry); | 
|  |  | 
|  | MIRBuilder.buildMerge(MI.getOperand(0).getReg(), {ResLow, ResHigh}); | 
|  |  | 
|  | MI.eraseFromParent(); | 
|  | break; | 
|  | } | 
|  | default: | 
|  | return false; | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } |