"git@repo.hca.bsc.es:rferrer/llvm-epi-0.8.git" did not exist on "52576719e077568017d4a5e745a4d77631702fb2"
Newer
Older
Akira Hatanaka
committed
//===-- MipsISelLowering.cpp - Mips DAG Lowering Implementation -----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
Akira Hatanaka
committed
//===----------------------------------------------------------------------===//
//
// This file defines the interfaces that Mips uses to lower LLVM code into a
// selection DAG.
//
Akira Hatanaka
committed
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "mips-lower"
#include "MipsISelLowering.h"
#include "MipsMachineFunction.h"
#include "MipsTargetMachine.h"
#include "MipsTargetObjectFile.h"
Bruno Cardoso Lopes
committed
#include "MipsSubtarget.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Intrinsics.h"
#include "llvm/CallingConv.h"
#include "InstPrinter/MipsInstPrinter.h"
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/Support/Debug.h"
// If I is a shifted mask, set the size (Size) and the first bit of the
// mask (Pos), and return true.
Akira Hatanaka
committed
// For example, if I is 0x003ff800, (Pos, Size) = (11, 11).
static bool IsShiftedMask(uint64_t I, uint64_t &Pos, uint64_t &Size) {
if (!isUInt<32>(I) || !isShiftedMask_32(I))
return false;
Akira Hatanaka
committed
Size = CountPopulation_32(I);
Pos = CountTrailingZeros_32(I);
return true;
const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const {
switch (Opcode) {
case MipsISD::JmpLink: return "MipsISD::JmpLink";
case MipsISD::Hi: return "MipsISD::Hi";
case MipsISD::Lo: return "MipsISD::Lo";
case MipsISD::GPRel: return "MipsISD::GPRel";
Bruno Cardoso Lopes
committed
case MipsISD::TlsGd: return "MipsISD::TlsGd";
case MipsISD::TprelHi: return "MipsISD::TprelHi";
case MipsISD::TprelLo: return "MipsISD::TprelLo";
case MipsISD::ThreadPointer: return "MipsISD::ThreadPointer";
case MipsISD::Ret: return "MipsISD::Ret";
case MipsISD::FPBrcond: return "MipsISD::FPBrcond";
case MipsISD::FPCmp: return "MipsISD::FPCmp";
case MipsISD::CMovFP_T: return "MipsISD::CMovFP_T";
case MipsISD::CMovFP_F: return "MipsISD::CMovFP_F";
case MipsISD::FPRound: return "MipsISD::FPRound";
case MipsISD::MAdd: return "MipsISD::MAdd";
case MipsISD::MAddu: return "MipsISD::MAddu";
case MipsISD::MSub: return "MipsISD::MSub";
case MipsISD::MSubu: return "MipsISD::MSubu";
case MipsISD::DivRem: return "MipsISD::DivRem";
case MipsISD::DivRemU: return "MipsISD::DivRemU";
case MipsISD::BuildPairF64: return "MipsISD::BuildPairF64";
case MipsISD::ExtractElementF64: return "MipsISD::ExtractElementF64";
case MipsISD::WrapperPIC: return "MipsISD::WrapperPIC";
case MipsISD::DynAlloc: return "MipsISD::DynAlloc";
case MipsISD::Sync: return "MipsISD::Sync";
case MipsISD::Ext: return "MipsISD::Ext";
case MipsISD::Ins: return "MipsISD::Ins";
}
}
MipsTargetLowering::
MipsTargetLowering(MipsTargetMachine &TM)
: TargetLowering(TM, new MipsTargetObjectFile()) {
Bruno Cardoso Lopes
committed
Subtarget = &TM.getSubtarget<MipsSubtarget>();
// Mips does not have i1 type, so use i32 for
Wesley Peck
committed
// setcc operations results (slt, sgt, ...).
setBooleanContents(ZeroOrOneBooleanContent);
setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct?
// Set up the register classes
Owen Anderson
committed
addRegisterClass(MVT::i32, Mips::CPURegsRegisterClass);
addRegisterClass(MVT::f32, Mips::FGR32RegisterClass);
Bruno Cardoso Lopes
committed
// When dealing with single precision only, use libcalls
Owen Anderson
committed
addRegisterClass(MVT::f64, Mips::AFGR64RegisterClass);
Bruno Cardoso Lopes
committed
Wesley Peck
committed
// Load extented operations for i1 types must be promoted
Owen Anderson
committed
setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
// MIPS doesn't have extending float->double load/store
Owen Anderson
committed
setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand);
setTruncStoreAction(MVT::f64, MVT::f32, Expand);
Wesley Peck
committed
// Used by legalize types to correctly generate the setcc result.
// Without this, every float setcc comes with a AND/OR with the result,
// we don't want this, since the fpcmp result goes to a flag register,
Bruno Cardoso Lopes
committed
// which is used implicitly by brcond and select operations.
Owen Anderson
committed
AddPromotedToType(ISD::SETCC, MVT::i1, MVT::i32);
Bruno Cardoso Lopes
committed
Owen Anderson
committed
setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
Bruno Cardoso Lopes
committed
setOperationAction(ISD::BlockAddress, MVT::i32, Custom);
Owen Anderson
committed
setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);
setOperationAction(ISD::JumpTable, MVT::i32, Custom);
setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
setOperationAction(ISD::SELECT, MVT::f32, Custom);
setOperationAction(ISD::SELECT, MVT::f64, Custom);
setOperationAction(ISD::SELECT, MVT::i32, Custom);
setOperationAction(ISD::BRCOND, MVT::Other, Custom);
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Custom);
setOperationAction(ISD::VASTART, MVT::Other, Custom);
setOperationAction(ISD::SDIV, MVT::i32, Expand);
setOperationAction(ISD::SREM, MVT::i32, Expand);
setOperationAction(ISD::UDIV, MVT::i32, Expand);
setOperationAction(ISD::UREM, MVT::i32, Expand);
// Operations not directly supported by Mips.
Owen Anderson
committed
setOperationAction(ISD::BR_JT, MVT::Other, Expand);
setOperationAction(ISD::BR_CC, MVT::Other, Expand);
setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand);
setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand);
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
setOperationAction(ISD::CTPOP, MVT::i32, Expand);
setOperationAction(ISD::CTTZ, MVT::i32, Expand);
setOperationAction(ISD::ROTL, MVT::i32, Expand);
if (!Subtarget->hasMips32r2())
setOperationAction(ISD::ROTR, MVT::i32, Expand);
Owen Anderson
committed
setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
setOperationAction(ISD::FCOPYSIGN, MVT::f32, Custom);
setOperationAction(ISD::FCOPYSIGN, MVT::f64, Custom);
Owen Anderson
committed
setOperationAction(ISD::FSIN, MVT::f32, Expand);
setOperationAction(ISD::FSIN, MVT::f64, Expand);
Owen Anderson
committed
setOperationAction(ISD::FCOS, MVT::f32, Expand);
setOperationAction(ISD::FCOS, MVT::f64, Expand);
Owen Anderson
committed
setOperationAction(ISD::FPOWI, MVT::f32, Expand);
setOperationAction(ISD::FPOW, MVT::f32, Expand);
Owen Anderson
committed
setOperationAction(ISD::FLOG, MVT::f32, Expand);
setOperationAction(ISD::FLOG2, MVT::f32, Expand);
setOperationAction(ISD::FLOG10, MVT::f32, Expand);
setOperationAction(ISD::FEXP, MVT::f32, Expand);
Cameron Zwarich
committed
setOperationAction(ISD::FMA, MVT::f32, Expand);
setOperationAction(ISD::FMA, MVT::f64, Expand);
setOperationAction(ISD::EXCEPTIONADDR, MVT::i32, Expand);
setOperationAction(ISD::EHSELECTION, MVT::i32, Expand);
setOperationAction(ISD::VAARG, MVT::Other, Expand);
setOperationAction(ISD::VACOPY, MVT::Other, Expand);
setOperationAction(ISD::VAEND, MVT::Other, Expand);
Owen Anderson
committed
setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
setOperationAction(ISD::MEMBARRIER, MVT::Other, Custom);
setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);
Eli Friedman
committed
setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Expand);
setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Expand);
setInsertFencesForAtomic(true);
if (Subtarget->isSingleFloat())
Owen Anderson
committed
setOperationAction(ISD::SELECT_CC, MVT::f64, Expand);
Owen Anderson
committed
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Expand);
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand);
Bruno Cardoso Lopes
committed
}
if (!Subtarget->hasBitCount())
Owen Anderson
committed
setOperationAction(ISD::CTLZ, MVT::i32, Expand);
Bruno Cardoso Lopes
committed
if (!Subtarget->hasSwap())
Owen Anderson
committed
setOperationAction(ISD::BSWAP, MVT::i32, Expand);
Bruno Cardoso Lopes
committed
Bruno Cardoso Lopes
committed
setTargetDAGCombine(ISD::ADDE);
setTargetDAGCombine(ISD::SUBE);
setTargetDAGCombine(ISD::SDIVREM);
setTargetDAGCombine(ISD::UDIVREM);
Akira Hatanaka
committed
setTargetDAGCombine(ISD::SETCC);
Akira Hatanaka
committed
setTargetDAGCombine(ISD::AND);
setTargetDAGCombine(ISD::OR);
Bruno Cardoso Lopes
committed
Eli Friedman
committed
setMinFunctionAlignment(2);
setStackPointerRegisterToSaveRestore(Mips::SP);
computeRegisterProperties();
setExceptionPointerRegister(Mips::A0);
setExceptionSelectorRegister(Mips::A1);
bool MipsTargetLowering::allowsUnalignedMemoryAccesses(EVT VT) const {
MVT::SimpleValueType SVT = VT.getSimpleVT().SimpleTy;
return SVT == MVT::i32 || SVT == MVT::i16;
EVT MipsTargetLowering::getSetCCResultType(EVT VT) const {
Owen Anderson
committed
return MVT::i32;
}
Bruno Cardoso Lopes
committed
// SelectMadd -
// Transforms a subgraph in CurDAG if the following pattern is found:
// (addc multLo, Lo0), (adde multHi, Hi0),
// where,
// multHi/Lo: product of multiplication
Bruno Cardoso Lopes
committed
// Lo0: initial value of Lo register
// Hi0: initial value of Hi register
Bruno Cardoso Lopes
committed
static bool SelectMadd(SDNode* ADDENode, SelectionDAG* CurDAG) {
Bruno Cardoso Lopes
committed
// ADDENode's second operand must be a flag output of an ADDC node in order
Bruno Cardoso Lopes
committed
// for the matching to be successful.
SDNode* ADDCNode = ADDENode->getOperand(2).getNode();
if (ADDCNode->getOpcode() != ISD::ADDC)
return false;
SDValue MultHi = ADDENode->getOperand(0);
SDValue MultLo = ADDCNode->getOperand(0);
Bruno Cardoso Lopes
committed
SDNode* MultNode = MultHi.getNode();
Bruno Cardoso Lopes
committed
unsigned MultOpc = MultHi.getOpcode();
// MultHi and MultLo must be generated by the same node,
if (MultLo.getNode() != MultNode)
return false;
// and it must be a multiplication.
if (MultOpc != ISD::SMUL_LOHI && MultOpc != ISD::UMUL_LOHI)
return false;
Bruno Cardoso Lopes
committed
// MultLo amd MultHi must be the first and second output of MultNode
// respectively.
Bruno Cardoso Lopes
committed
if (MultHi.getResNo() != 1 || MultLo.getResNo() != 0)
return false;
Bruno Cardoso Lopes
committed
// Transform this to a MADD only if ADDENode and ADDCNode are the only users
Bruno Cardoso Lopes
committed
// of the values of MultNode, in which case MultNode will be removed in later
// phases.
Akira Hatanaka
committed
// If there exist users other than ADDENode or ADDCNode, this function returns
// here, which will result in MultNode being mapped to a single MULT
Bruno Cardoso Lopes
committed
// instruction node rather than a pair of MULT and MADD instructions being
Bruno Cardoso Lopes
committed
// produced.
if (!MultHi.hasOneUse() || !MultLo.hasOneUse())
return false;
Bruno Cardoso Lopes
committed
SDValue Chain = CurDAG->getEntryNode();
Bruno Cardoso Lopes
committed
DebugLoc dl = ADDENode->getDebugLoc();
// create MipsMAdd(u) node
MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MAddu : MipsISD::MAdd;
Bruno Cardoso Lopes
committed
Bruno Cardoso Lopes
committed
SDValue MAdd = CurDAG->getNode(MultOpc, dl,
MVT::Glue,
MultNode->getOperand(0),// Factor 0
MultNode->getOperand(1),// Factor 1
Bruno Cardoso Lopes
committed
ADDCNode->getOperand(1),// Lo0
Bruno Cardoso Lopes
committed
ADDENode->getOperand(1));// Hi0
// create CopyFromReg nodes
SDValue CopyFromLo = CurDAG->getCopyFromReg(Chain, dl, Mips::LO, MVT::i32,
MAdd);
Bruno Cardoso Lopes
committed
SDValue CopyFromHi = CurDAG->getCopyFromReg(CopyFromLo.getValue(1), dl,
Bruno Cardoso Lopes
committed
Mips::HI, MVT::i32,
CopyFromLo.getValue(2));
// replace uses of adde and addc here
if (!SDValue(ADDCNode, 0).use_empty())
CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDCNode, 0), CopyFromLo);
if (!SDValue(ADDENode, 0).use_empty())
CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDENode, 0), CopyFromHi);
Bruno Cardoso Lopes
committed
return true;
Bruno Cardoso Lopes
committed
}
// SelectMsub -
// Transforms a subgraph in CurDAG if the following pattern is found:
// (addc Lo0, multLo), (sube Hi0, multHi),
// where,
// multHi/Lo: product of multiplication
Bruno Cardoso Lopes
committed
// Lo0: initial value of Lo register
// Hi0: initial value of Hi register
Bruno Cardoso Lopes
committed
static bool SelectMsub(SDNode* SUBENode, SelectionDAG* CurDAG) {
Bruno Cardoso Lopes
committed
// SUBENode's second operand must be a flag output of an SUBC node in order
Bruno Cardoso Lopes
committed
// for the matching to be successful.
SDNode* SUBCNode = SUBENode->getOperand(2).getNode();
if (SUBCNode->getOpcode() != ISD::SUBC)
return false;
SDValue MultHi = SUBENode->getOperand(1);
SDValue MultLo = SUBCNode->getOperand(1);
Bruno Cardoso Lopes
committed
SDNode* MultNode = MultHi.getNode();
Bruno Cardoso Lopes
committed
unsigned MultOpc = MultHi.getOpcode();
// MultHi and MultLo must be generated by the same node,
if (MultLo.getNode() != MultNode)
return false;
// and it must be a multiplication.
if (MultOpc != ISD::SMUL_LOHI && MultOpc != ISD::UMUL_LOHI)
return false;
// MultLo amd MultHi must be the first and second output of MultNode
// respectively.
if (MultHi.getResNo() != 1 || MultLo.getResNo() != 0)
return false;
// Transform this to a MSUB only if SUBENode and SUBCNode are the only users
// of the values of MultNode, in which case MultNode will be removed in later
// phases.
Akira Hatanaka
committed
// If there exist users other than SUBENode or SUBCNode, this function returns
// here, which will result in MultNode being mapped to a single MULT
Bruno Cardoso Lopes
committed
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
// instruction node rather than a pair of MULT and MSUB instructions being
// produced.
if (!MultHi.hasOneUse() || !MultLo.hasOneUse())
return false;
SDValue Chain = CurDAG->getEntryNode();
DebugLoc dl = SUBENode->getDebugLoc();
// create MipsSub(u) node
MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MSubu : MipsISD::MSub;
SDValue MSub = CurDAG->getNode(MultOpc, dl,
MVT::Glue,
MultNode->getOperand(0),// Factor 0
MultNode->getOperand(1),// Factor 1
SUBCNode->getOperand(0),// Lo0
SUBENode->getOperand(0));// Hi0
// create CopyFromReg nodes
SDValue CopyFromLo = CurDAG->getCopyFromReg(Chain, dl, Mips::LO, MVT::i32,
MSub);
SDValue CopyFromHi = CurDAG->getCopyFromReg(CopyFromLo.getValue(1), dl,
Mips::HI, MVT::i32,
CopyFromLo.getValue(2));
// replace uses of sube and subc here
if (!SDValue(SUBCNode, 0).use_empty())
CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBCNode, 0), CopyFromLo);
if (!SDValue(SUBENode, 0).use_empty())
CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBENode, 0), CopyFromHi);
return true;
}
static SDValue PerformADDECombine(SDNode *N, SelectionDAG& DAG,
TargetLowering::DAGCombinerInfo &DCI,
const MipsSubtarget* Subtarget) {
if (DCI.isBeforeLegalize())
return SDValue();
if (Subtarget->hasMips32() && SelectMadd(N, &DAG))
Bruno Cardoso Lopes
committed
return SDValue(N, 0);
Bruno Cardoso Lopes
committed
Bruno Cardoso Lopes
committed
return SDValue();
Bruno Cardoso Lopes
committed
}
Bruno Cardoso Lopes
committed
static SDValue PerformSUBECombine(SDNode *N, SelectionDAG& DAG,
TargetLowering::DAGCombinerInfo &DCI,
const MipsSubtarget* Subtarget) {
if (DCI.isBeforeLegalize())
return SDValue();
if (Subtarget->hasMips32() && SelectMsub(N, &DAG))
Bruno Cardoso Lopes
committed
return SDValue(N, 0);
Bruno Cardoso Lopes
committed
Bruno Cardoso Lopes
committed
return SDValue();
Bruno Cardoso Lopes
committed
}
Bruno Cardoso Lopes
committed
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
static SDValue PerformDivRemCombine(SDNode *N, SelectionDAG& DAG,
TargetLowering::DAGCombinerInfo &DCI,
const MipsSubtarget* Subtarget) {
if (DCI.isBeforeLegalizeOps())
return SDValue();
unsigned opc = N->getOpcode() == ISD::SDIVREM ? MipsISD::DivRem :
MipsISD::DivRemU;
DebugLoc dl = N->getDebugLoc();
SDValue DivRem = DAG.getNode(opc, dl, MVT::Glue,
N->getOperand(0), N->getOperand(1));
SDValue InChain = DAG.getEntryNode();
SDValue InGlue = DivRem;
// insert MFLO
if (N->hasAnyUseOfValue(0)) {
SDValue CopyFromLo = DAG.getCopyFromReg(InChain, dl, Mips::LO, MVT::i32,
InGlue);
DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), CopyFromLo);
InChain = CopyFromLo.getValue(1);
InGlue = CopyFromLo.getValue(2);
}
// insert MFHI
if (N->hasAnyUseOfValue(1)) {
SDValue CopyFromHi = DAG.getCopyFromReg(InChain, dl,
DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), CopyFromHi);
}
return SDValue();
}
Akira Hatanaka
committed
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
static Mips::CondCode FPCondCCodeToFCC(ISD::CondCode CC) {
switch (CC) {
default: llvm_unreachable("Unknown fp condition code!");
case ISD::SETEQ:
case ISD::SETOEQ: return Mips::FCOND_OEQ;
case ISD::SETUNE: return Mips::FCOND_UNE;
case ISD::SETLT:
case ISD::SETOLT: return Mips::FCOND_OLT;
case ISD::SETGT:
case ISD::SETOGT: return Mips::FCOND_OGT;
case ISD::SETLE:
case ISD::SETOLE: return Mips::FCOND_OLE;
case ISD::SETGE:
case ISD::SETOGE: return Mips::FCOND_OGE;
case ISD::SETULT: return Mips::FCOND_ULT;
case ISD::SETULE: return Mips::FCOND_ULE;
case ISD::SETUGT: return Mips::FCOND_UGT;
case ISD::SETUGE: return Mips::FCOND_UGE;
case ISD::SETUO: return Mips::FCOND_UN;
case ISD::SETO: return Mips::FCOND_OR;
case ISD::SETNE:
case ISD::SETONE: return Mips::FCOND_ONE;
case ISD::SETUEQ: return Mips::FCOND_UEQ;
}
}
// Returns true if condition code has to be inverted.
static bool InvertFPCondCode(Mips::CondCode CC) {
if (CC >= Mips::FCOND_F && CC <= Mips::FCOND_NGT)
return false;
if (CC >= Mips::FCOND_T && CC <= Mips::FCOND_GT)
return true;
assert(false && "Illegal Condition Code");
return false;
}
// Creates and returns an FPCmp node from a setcc node.
// Returns Op if setcc is not a floating point comparison.
static SDValue CreateFPCmp(SelectionDAG& DAG, const SDValue& Op) {
// must be a SETCC node
if (Op.getOpcode() != ISD::SETCC)
return Op;
SDValue LHS = Op.getOperand(0);
if (!LHS.getValueType().isFloatingPoint())
return Op;
SDValue RHS = Op.getOperand(1);
DebugLoc dl = Op.getDebugLoc();
Akira Hatanaka
committed
// Assume the 3rd operand is a CondCodeSDNode. Add code to check the type of
// node if necessary.
Akira Hatanaka
committed
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
return DAG.getNode(MipsISD::FPCmp, dl, MVT::Glue, LHS, RHS,
DAG.getConstant(FPCondCCodeToFCC(CC), MVT::i32));
}
// Creates and returns a CMovFPT/F node.
static SDValue CreateCMovFP(SelectionDAG& DAG, SDValue Cond, SDValue True,
SDValue False, DebugLoc DL) {
bool invert = InvertFPCondCode((Mips::CondCode)
cast<ConstantSDNode>(Cond.getOperand(2))
->getSExtValue());
return DAG.getNode((invert ? MipsISD::CMovFP_F : MipsISD::CMovFP_T), DL,
True.getValueType(), True, False, Cond);
}
static SDValue PerformSETCCCombine(SDNode *N, SelectionDAG& DAG,
TargetLowering::DAGCombinerInfo &DCI,
const MipsSubtarget* Subtarget) {
if (DCI.isBeforeLegalizeOps())
return SDValue();
SDValue Cond = CreateFPCmp(DAG, SDValue(N, 0));
if (Cond.getOpcode() != MipsISD::FPCmp)
return SDValue();
SDValue True = DAG.getConstant(1, MVT::i32);
SDValue False = DAG.getConstant(0, MVT::i32);
return CreateCMovFP(DAG, Cond, True, False, N->getDebugLoc());
}
Akira Hatanaka
committed
static SDValue PerformANDCombine(SDNode *N, SelectionDAG& DAG,
TargetLowering::DAGCombinerInfo &DCI,
const MipsSubtarget* Subtarget) {
// Pattern match EXT.
// $dst = and ((sra or srl) $src , pos), (2**size - 1)
// => ext $dst, $src, size, pos
if (DCI.isBeforeLegalizeOps() || !Subtarget->hasMips32r2())
Akira Hatanaka
committed
return SDValue();
SDValue ShiftRight = N->getOperand(0), Mask = N->getOperand(1);
// Op's first operand must be a shift right.
if (ShiftRight.getOpcode() != ISD::SRA && ShiftRight.getOpcode() != ISD::SRL)
return SDValue();
// The second operand of the shift must be an immediate.
uint64_t Pos;
ConstantSDNode *CN;
if (!(CN = dyn_cast<ConstantSDNode>(ShiftRight.getOperand(1))))
return SDValue();
Pos = CN->getZExtValue();
uint64_t SMPos, SMSize;
// Op's second operand must be a shifted mask.
if (!(CN = dyn_cast<ConstantSDNode>(Mask)) ||
Akira Hatanaka
committed
!IsShiftedMask(CN->getZExtValue(), SMPos, SMSize))
Akira Hatanaka
committed
return SDValue();
// Return if the shifted mask does not start at bit 0 or the sum of its size
// and Pos exceeds the word's size.
if (SMPos != 0 || Pos + SMSize > 32)
return SDValue();
return DAG.getNode(MipsISD::Ext, N->getDebugLoc(), MVT::i32,
ShiftRight.getOperand(0),
DAG.getConstant(Pos, MVT::i32),
DAG.getConstant(SMSize, MVT::i32));
Akira Hatanaka
committed
}
static SDValue PerformORCombine(SDNode *N, SelectionDAG& DAG,
TargetLowering::DAGCombinerInfo &DCI,
const MipsSubtarget* Subtarget) {
// Pattern match INS.
// $dst = or (and $src1 , mask0), (and (shl $src, pos), mask1),
// where mask1 = (2**size - 1) << pos, mask0 = ~mask1
// => ins $dst, $src, size, pos, $src1
if (DCI.isBeforeLegalizeOps() || !Subtarget->hasMips32r2())
Akira Hatanaka
committed
return SDValue();
SDValue And0 = N->getOperand(0), And1 = N->getOperand(1);
uint64_t SMPos0, SMSize0, SMPos1, SMSize1;
ConstantSDNode *CN;
// See if Op's first operand matches (and $src1 , mask0).
if (And0.getOpcode() != ISD::AND)
return SDValue();
if (!(CN = dyn_cast<ConstantSDNode>(And0.getOperand(1))) ||
Akira Hatanaka
committed
!IsShiftedMask(~CN->getSExtValue(), SMPos0, SMSize0))
Akira Hatanaka
committed
return SDValue();
// See if Op's second operand matches (and (shl $src, pos), mask1).
if (And1.getOpcode() != ISD::AND)
return SDValue();
if (!(CN = dyn_cast<ConstantSDNode>(And1.getOperand(1))) ||
Akira Hatanaka
committed
!IsShiftedMask(CN->getZExtValue(), SMPos1, SMSize1))
Akira Hatanaka
committed
return SDValue();
// The shift masks must have the same position and size.
if (SMPos0 != SMPos1 || SMSize0 != SMSize1)
return SDValue();
SDValue Shl = And1.getOperand(0);
if (Shl.getOpcode() != ISD::SHL)
return SDValue();
if (!(CN = dyn_cast<ConstantSDNode>(Shl.getOperand(1))))
return SDValue();
unsigned Shamt = CN->getZExtValue();
// Return if the shift amount and the first bit position of mask are not the
// same.
if (Shamt != SMPos0)
return SDValue();
return DAG.getNode(MipsISD::Ins, N->getDebugLoc(), MVT::i32,
Shl.getOperand(0),
DAG.getConstant(SMPos0, MVT::i32),
DAG.getConstant(SMSize0, MVT::i32),
Akira Hatanaka
committed
And0.getOperand(0));
}
Bruno Cardoso Lopes
committed
SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
Bruno Cardoso Lopes
committed
const {
SelectionDAG &DAG = DCI.DAG;
unsigned opc = N->getOpcode();
switch (opc) {
default: break;
case ISD::ADDE:
return PerformADDECombine(N, DAG, DCI, Subtarget);
case ISD::SUBE:
return PerformSUBECombine(N, DAG, DCI, Subtarget);
case ISD::SDIVREM:
case ISD::UDIVREM:
return PerformDivRemCombine(N, DAG, DCI, Subtarget);
Akira Hatanaka
committed
case ISD::SETCC:
return PerformSETCCCombine(N, DAG, DCI, Subtarget);
Akira Hatanaka
committed
case ISD::AND:
return PerformANDCombine(N, DAG, DCI, Subtarget);
case ISD::OR:
return PerformORCombine(N, DAG, DCI, Subtarget);
Bruno Cardoso Lopes
committed
}
return SDValue();
}
LowerOperation(SDValue Op, SelectionDAG &DAG) const
Wesley Peck
committed
switch (Op.getOpcode())
case ISD::BRCOND: return LowerBRCOND(Op, DAG);
case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
Bruno Cardoso Lopes
committed
case ISD::BlockAddress: return LowerBlockAddress(Op, DAG);
case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
case ISD::JumpTable: return LowerJumpTable(Op, DAG);
case ISD::SELECT: return LowerSELECT(Op, DAG);
case ISD::VASTART: return LowerVASTART(Op, DAG);
case ISD::FCOPYSIGN: return LowerFCOPYSIGN(Op, DAG);
case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
case ISD::MEMBARRIER: return LowerMEMBARRIER(Op, DAG);
case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op, DAG);
Akira Hatanaka
committed
//===----------------------------------------------------------------------===//
Akira Hatanaka
committed
//===----------------------------------------------------------------------===//
// AddLiveIn - This helper function adds the specified physical register to the
// MachineFunction as a live in value. It also creates a corresponding
// virtual register for it.
static unsigned
Wesley Peck
committed
AddLiveIn(MachineFunction &MF, unsigned PReg, TargetRegisterClass *RC)
{
assert(RC->contains(PReg) && "Not the correct regclass!");
unsigned VReg = MF.getRegInfo().createVirtualRegister(RC);
MF.getRegInfo().addLiveIn(PReg, VReg);
// Get fp branch code (not opcode) from condition code.
static Mips::FPBranchCode GetFPBranchCodeFromCond(Mips::CondCode CC) {
if (CC >= Mips::FCOND_F && CC <= Mips::FCOND_NGT)
return Mips::BRANCH_T;
if (CC >= Mips::FCOND_T && CC <= Mips::FCOND_GT)
return Mips::BRANCH_F;
return Mips::BRANCH_INVALID;
}
Wesley Peck
committed
static MachineBasicBlock* ExpandCondMov(MachineInstr *MI, MachineBasicBlock *BB,
DebugLoc dl,
const MipsSubtarget* Subtarget,
const TargetInstrInfo *TII,
bool isFPCmp, unsigned Opc) {
Bruno Cardoso Lopes
committed
// There is no need to expand CMov instructions if target has
// conditional moves.
if (Subtarget->hasCondMov())
return BB;
Akira Hatanaka
committed
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
// To "insert" a SELECT_CC instruction, we actually have to insert the
// diamond control-flow pattern. The incoming instruction knows the
// destination vreg to set, the condition code register to branch on, the
// true/false values to select between, and a branch opcode to use.
const BasicBlock *LLVM_BB = BB->getBasicBlock();
MachineFunction::iterator It = BB;
++It;
// thisMBB:
// ...
// TrueVal = ...
// setcc r1, r2, r3
// bNE r1, r0, copy1MBB
// fallthrough --> copy0MBB
MachineBasicBlock *thisMBB = BB;
MachineFunction *F = BB->getParent();
MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
F->insert(It, copy0MBB);
F->insert(It, sinkMBB);
// Transfer the remainder of BB and its successor edges to sinkMBB.
sinkMBB->splice(sinkMBB->begin(), BB,
llvm::next(MachineBasicBlock::iterator(MI)),
BB->end());
sinkMBB->transferSuccessorsAndUpdatePHIs(BB);
// Next, add the true and fallthrough blocks as its successors.
BB->addSuccessor(copy0MBB);
BB->addSuccessor(sinkMBB);
// Emit the right instruction according to the type of the operands compared
if (isFPCmp)
BuildMI(BB, dl, TII->get(Opc)).addMBB(sinkMBB);
else
BuildMI(BB, dl, TII->get(Opc)).addReg(MI->getOperand(2).getReg())
.addReg(Mips::ZERO).addMBB(sinkMBB);
// copy0MBB:
// %FalseValue = ...
// # fallthrough to sinkMBB
BB = copy0MBB;
// Update machine-CFG edges
BB->addSuccessor(sinkMBB);
// sinkMBB:
// %Result = phi [ %TrueValue, thisMBB ], [ %FalseValue, copy0MBB ]
// ...
BB = sinkMBB;
if (isFPCmp)
BuildMI(*BB, BB->begin(), dl,
TII->get(Mips::PHI), MI->getOperand(0).getReg())
.addReg(MI->getOperand(2).getReg()).addMBB(thisMBB)
Akira Hatanaka
committed
.addReg(MI->getOperand(1).getReg()).addMBB(copy0MBB);
else
BuildMI(*BB, BB->begin(), dl,
TII->get(Mips::PHI), MI->getOperand(0).getReg())
.addReg(MI->getOperand(3).getReg()).addMBB(thisMBB)
.addReg(MI->getOperand(1).getReg()).addMBB(copy0MBB);
Akira Hatanaka
committed
MI->eraseFromParent(); // The pseudo instruction is gone now.
return BB;
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
MachineBasicBlock *
MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
MachineBasicBlock *BB) const {
const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
DebugLoc dl = MI->getDebugLoc();
switch (MI->getOpcode()) {
default:
assert(false && "Unexpected instr type to insert");
return NULL;
case Mips::MOVT:
case Mips::MOVT_S:
case Mips::MOVT_D:
return ExpandCondMov(MI, BB, dl, Subtarget, TII, true, Mips::BC1F);
case Mips::MOVF:
case Mips::MOVF_S:
case Mips::MOVF_D:
return ExpandCondMov(MI, BB, dl, Subtarget, TII, true, Mips::BC1T);
case Mips::MOVZ_I:
case Mips::MOVZ_S:
case Mips::MOVZ_D:
return ExpandCondMov(MI, BB, dl, Subtarget, TII, false, Mips::BNE);
case Mips::MOVN_I:
case Mips::MOVN_S:
case Mips::MOVN_D:
return ExpandCondMov(MI, BB, dl, Subtarget, TII, false, Mips::BEQ);
case Mips::ATOMIC_LOAD_ADD_I8:
return EmitAtomicBinaryPartword(MI, BB, 1, Mips::ADDu);
case Mips::ATOMIC_LOAD_ADD_I16:
return EmitAtomicBinaryPartword(MI, BB, 2, Mips::ADDu);
case Mips::ATOMIC_LOAD_ADD_I32:
return EmitAtomicBinary(MI, BB, 4, Mips::ADDu);
case Mips::ATOMIC_LOAD_AND_I8:
return EmitAtomicBinaryPartword(MI, BB, 1, Mips::AND);
case Mips::ATOMIC_LOAD_AND_I16:
return EmitAtomicBinaryPartword(MI, BB, 2, Mips::AND);
case Mips::ATOMIC_LOAD_AND_I32:
return EmitAtomicBinary(MI, BB, 4, Mips::AND);
case Mips::ATOMIC_LOAD_OR_I8:
return EmitAtomicBinaryPartword(MI, BB, 1, Mips::OR);
case Mips::ATOMIC_LOAD_OR_I16:
return EmitAtomicBinaryPartword(MI, BB, 2, Mips::OR);
case Mips::ATOMIC_LOAD_OR_I32:
return EmitAtomicBinary(MI, BB, 4, Mips::OR);
case Mips::ATOMIC_LOAD_XOR_I8:
return EmitAtomicBinaryPartword(MI, BB, 1, Mips::XOR);
case Mips::ATOMIC_LOAD_XOR_I16:
return EmitAtomicBinaryPartword(MI, BB, 2, Mips::XOR);
case Mips::ATOMIC_LOAD_XOR_I32:
return EmitAtomicBinary(MI, BB, 4, Mips::XOR);
case Mips::ATOMIC_LOAD_NAND_I8:
return EmitAtomicBinaryPartword(MI, BB, 1, 0, true);
case Mips::ATOMIC_LOAD_NAND_I16:
return EmitAtomicBinaryPartword(MI, BB, 2, 0, true);
case Mips::ATOMIC_LOAD_NAND_I32:
return EmitAtomicBinary(MI, BB, 4, 0, true);
case Mips::ATOMIC_LOAD_SUB_I8:
return EmitAtomicBinaryPartword(MI, BB, 1, Mips::SUBu);
case Mips::ATOMIC_LOAD_SUB_I16:
return EmitAtomicBinaryPartword(MI, BB, 2, Mips::SUBu);
case Mips::ATOMIC_LOAD_SUB_I32:
return EmitAtomicBinary(MI, BB, 4, Mips::SUBu);
case Mips::ATOMIC_SWAP_I8:
return EmitAtomicBinaryPartword(MI, BB, 1, 0);
case Mips::ATOMIC_SWAP_I16:
return EmitAtomicBinaryPartword(MI, BB, 2, 0);
case Mips::ATOMIC_SWAP_I32:
return EmitAtomicBinary(MI, BB, 4, 0);
case Mips::ATOMIC_CMP_SWAP_I8:
return EmitAtomicCmpSwapPartword(MI, BB, 1);
case Mips::ATOMIC_CMP_SWAP_I16:
return EmitAtomicCmpSwapPartword(MI, BB, 2);
case Mips::ATOMIC_CMP_SWAP_I32:
return EmitAtomicCmpSwap(MI, BB, 4);
}
}
Bruno Cardoso Lopes
committed
// This function also handles Mips::ATOMIC_SWAP_I32 (when BinOpcode == 0), and
// Mips::ATOMIC_LOAD_NAND_I32 (when Nand == true)
MachineBasicBlock *
MipsTargetLowering::EmitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB,
unsigned Size, unsigned BinOpcode,
Bruno Cardoso Lopes
committed
assert(Size == 4 && "Unsupported size for EmitAtomicBinary.");
MachineFunction *MF = BB->getParent();
MachineRegisterInfo &RegInfo = MF->getRegInfo();
const TargetRegisterClass *RC = getRegClassFor(MVT::i32);
const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
DebugLoc dl = MI->getDebugLoc();
unsigned OldVal = MI->getOperand(0).getReg();
Bruno Cardoso Lopes
committed
unsigned Ptr = MI->getOperand(1).getReg();
unsigned Incr = MI->getOperand(2).getReg();
unsigned StoreVal = RegInfo.createVirtualRegister(RC);
unsigned AndRes = RegInfo.createVirtualRegister(RC);
unsigned Success = RegInfo.createVirtualRegister(RC);
Bruno Cardoso Lopes
committed
// insert new blocks after the current block
const BasicBlock *LLVM_BB = BB->getBasicBlock();
MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB);
MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB);
MachineFunction::iterator It = BB;
++It;
MF->insert(It, loopMBB);
MF->insert(It, exitMBB);
// Transfer the remainder of BB and its successor edges to exitMBB.
exitMBB->splice(exitMBB->begin(), BB,
llvm::next(MachineBasicBlock::iterator(MI)),
BB->end());
exitMBB->transferSuccessorsAndUpdatePHIs(BB);
// thisMBB:
// ...
// fallthrough --> loopMBB
BB->addSuccessor(loopMBB);
Akira Hatanaka
committed
loopMBB->addSuccessor(loopMBB);
loopMBB->addSuccessor(exitMBB);
Bruno Cardoso Lopes
committed
// loopMBB:
// ll oldval, 0(ptr)
// <binop> storeval, oldval, incr
// sc success, storeval, 0(ptr)
// beq success, $0, loopMBB
Bruno Cardoso Lopes
committed
BB = loopMBB;
BuildMI(BB, dl, TII->get(Mips::LL), OldVal).addReg(Ptr).addImm(0);
Bruno Cardoso Lopes
committed
if (Nand) {
// and andres, oldval, incr
// nor storeval, $0, andres
BuildMI(BB, dl, TII->get(Mips::AND), AndRes).addReg(OldVal).addReg(Incr);
BuildMI(BB, dl, TII->get(Mips::NOR), StoreVal)
.addReg(Mips::ZERO).addReg(AndRes);
Bruno Cardoso Lopes
committed
} else if (BinOpcode) {
// <binop> storeval, oldval, incr
BuildMI(BB, dl, TII->get(BinOpcode), StoreVal).addReg(OldVal).addReg(Incr);
Bruno Cardoso Lopes
committed
} else {
Bruno Cardoso Lopes
committed
}
BuildMI(BB, dl, TII->get(Mips::SC), Success)
.addReg(StoreVal).addReg(Ptr).addImm(0);
Bruno Cardoso Lopes
committed
BuildMI(BB, dl, TII->get(Mips::BEQ))
.addReg(Success).addReg(Mips::ZERO).addMBB(loopMBB);
Bruno Cardoso Lopes
committed
MI->eraseFromParent(); // The instruction is gone now.
return exitMBB;
Bruno Cardoso Lopes
committed
}
MachineBasicBlock *
MipsTargetLowering::EmitAtomicBinaryPartword(MachineInstr *MI,
MachineBasicBlock *BB,
unsigned Size, unsigned BinOpcode,
bool Nand) const {
Bruno Cardoso Lopes
committed
assert((Size == 1 || Size == 2) &&
"Unsupported size for EmitAtomicBinaryPartial.");
MachineFunction *MF = BB->getParent();
MachineRegisterInfo &RegInfo = MF->getRegInfo();
const TargetRegisterClass *RC = getRegClassFor(MVT::i32);
const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
DebugLoc dl = MI->getDebugLoc();
unsigned Dest = MI->getOperand(0).getReg();
unsigned Ptr = MI->getOperand(1).getReg();
unsigned Incr = MI->getOperand(2).getReg();
unsigned AlignedAddr = RegInfo.createVirtualRegister(RC);
unsigned ShiftAmt = RegInfo.createVirtualRegister(RC);
Bruno Cardoso Lopes
committed
unsigned Mask = RegInfo.createVirtualRegister(RC);
unsigned Mask2 = RegInfo.createVirtualRegister(RC);
unsigned NewVal = RegInfo.createVirtualRegister(RC);
unsigned OldVal = RegInfo.createVirtualRegister(RC);
Bruno Cardoso Lopes
committed
unsigned Incr2 = RegInfo.createVirtualRegister(RC);
unsigned MaskLSB2 = RegInfo.createVirtualRegister(RC);
unsigned PtrLSB2 = RegInfo.createVirtualRegister(RC);
unsigned MaskUpper = RegInfo.createVirtualRegister(RC);
unsigned AndRes = RegInfo.createVirtualRegister(RC);
unsigned BinOpRes = RegInfo.createVirtualRegister(RC);
unsigned MaskedOldVal0 = RegInfo.createVirtualRegister(RC);
unsigned StoreVal = RegInfo.createVirtualRegister(RC);
unsigned MaskedOldVal1 = RegInfo.createVirtualRegister(RC);
unsigned SrlRes = RegInfo.createVirtualRegister(RC);
unsigned SllRes = RegInfo.createVirtualRegister(RC);
unsigned Success = RegInfo.createVirtualRegister(RC);
Bruno Cardoso Lopes
committed
// insert new blocks after the current block
const BasicBlock *LLVM_BB = BB->getBasicBlock();
MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB);
MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB);
Bruno Cardoso Lopes
committed
MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB);
MachineFunction::iterator It = BB;
++It;
MF->insert(It, loopMBB);
MF->insert(It, sinkMBB);
Bruno Cardoso Lopes
committed
MF->insert(It, exitMBB);
// Transfer the remainder of BB and its successor edges to exitMBB.
exitMBB->splice(exitMBB->begin(), BB,
llvm::next(MachineBasicBlock::iterator(MI)),
BB->end());
exitMBB->transferSuccessorsAndUpdatePHIs(BB);
Akira Hatanaka
committed
BB->addSuccessor(loopMBB);
loopMBB->addSuccessor(loopMBB);
loopMBB->addSuccessor(sinkMBB);
sinkMBB->addSuccessor(exitMBB);
Bruno Cardoso Lopes
committed
// thisMBB:
// addiu masklsb2,$0,-4 # 0xfffffffc
// and alignedaddr,ptr,masklsb2
// andi ptrlsb2,ptr,3
// sll shiftamt,ptrlsb2,3
// ori maskupper,$0,255 # 0xff
// sll mask,maskupper,shiftamt
Bruno Cardoso Lopes
committed
// nor mask2,$0,mask
Bruno Cardoso Lopes
committed
int64_t MaskImm = (Size == 1) ? 255 : 65535;
BuildMI(BB, dl, TII->get(Mips::ADDiu), MaskLSB2)
.addReg(Mips::ZERO).addImm(-4);
BuildMI(BB, dl, TII->get(Mips::AND), AlignedAddr)
.addReg(Ptr).addReg(MaskLSB2);
BuildMI(BB, dl, TII->get(Mips::ANDi), PtrLSB2).addReg(Ptr).addImm(3);
BuildMI(BB, dl, TII->get(Mips::SLL), ShiftAmt).addReg(PtrLSB2).addImm(3);