MipsSEISelLowering.cpp revision 9a308df027b60057d0fe3ba7a3ee9648f6677879
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===-- MipsSEISelLowering.cpp - MipsSE DAG Lowering Interface --*- C++ -*-===// 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The LLVM Compiler Infrastructure 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// License. See LICENSE.TXT for details. 7424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// 84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)//===----------------------------------------------------------------------===// 9424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// 1058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Subclass of MipsTargetLowering specialized for mips32/64. 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 1258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//===----------------------------------------------------------------------===// 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "MipsSEISelLowering.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "MipsRegisterInfo.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "MipsTargetMachine.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/CodeGen/MachineInstrBuilder.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "llvm/CodeGen/MachineRegisterInfo.h" 18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "llvm/IR/Intrinsics.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/Support/CommandLine.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/Target/TargetInstrInfo.h" 214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using namespace llvm; 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 24424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)static cl::opt<bool> 25424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)EnableMipsTailCalls("enable-mips-tail-calls", cl::Hidden, 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cl::desc("MIPS: Enable tail calls."), cl::init(false)); 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)MipsSETargetLowering::MipsSETargetLowering(MipsTargetMachine &TM) 294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) : MipsTargetLowering(TM) { 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Set up the register classes 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) clearRegisterClasses(); 3358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 3458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) addRegisterClass(MVT::i32, &Mips::CPURegsRegClass); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HasMips64) 37424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) addRegisterClass(MVT::i64, &Mips::CPU64RegsRegClass); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (Subtarget->hasDSP()) { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MVT::SimpleValueType VecTys[2] = {MVT::v2i16, MVT::v4i8}; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (unsigned i = 0; i < array_lengthof(VecTys); ++i) { 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) addRegisterClass(VecTys[i], &Mips::DSPRegsRegClass); 447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Expand all builtin opcodes. 464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc) 4758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) setOperationAction(Opc, VecTys[i], Expand); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) setOperationAction(ISD::ADD, VecTys[i], Legal); 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) setOperationAction(ISD::SUB, VecTys[i], Legal); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setOperationAction(ISD::LOAD, VecTys[i], Legal); 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) setOperationAction(ISD::STORE, VecTys[i], Legal); 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) setOperationAction(ISD::BITCAST, VecTys[i], Legal); 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) setTargetDAGCombine(ISD::SHL); 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) setTargetDAGCombine(ISD::SRA); 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) setTargetDAGCombine(ISD::SRL); 59424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) setTargetDAGCombine(ISD::SETCC); 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) setTargetDAGCombine(ISD::VSELECT); 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (Subtarget->hasDSPR2()) 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) setOperationAction(ISD::MUL, MVT::v2i16, Legal); 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!TM.Options.UseSoftFloat) { 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) addRegisterClass(MVT::f32, &Mips::FGR32RegClass); 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When dealing with single precision only, use libcalls 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!Subtarget->isSingleFloat()) { 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (HasMips64) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addRegisterClass(MVT::f64, &Mips::FGR64RegClass); 734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) else 744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) addRegisterClass(MVT::f64, &Mips::AFGR64RegClass); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setOperationAction(ISD::SMUL_LOHI, MVT::i32, Custom); 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) setOperationAction(ISD::UMUL_LOHI, MVT::i32, Custom); 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) setOperationAction(ISD::MULHS, MVT::i32, Custom); 817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) setOperationAction(ISD::MULHU, MVT::i32, Custom); 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (HasMips64) { 84a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) setOperationAction(ISD::MULHS, MVT::i64, Custom); 85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch setOperationAction(ISD::MULHU, MVT::i64, Custom); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setOperationAction(ISD::MUL, MVT::i64, Custom); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::i64, Custom); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::i64, Custom); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) setOperationAction(ISD::SDIVREM, MVT::i32, Custom); 934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) setOperationAction(ISD::UDIVREM, MVT::i32, Custom); 94d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) setOperationAction(ISD::SDIVREM, MVT::i64, Custom); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setOperationAction(ISD::UDIVREM, MVT::i64, Custom); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setOperationAction(ISD::LOAD, MVT::i32, Custom); 98424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) setOperationAction(ISD::STORE, MVT::i32, Custom); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) setTargetDAGCombine(ISD::ADDE); 1013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) setTargetDAGCombine(ISD::SUBE); 10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) setTargetDAGCombine(ISD::MUL); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) computeRegisterProperties(); 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const MipsTargetLowering * 1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)llvm::createMipsSETargetLowering(MipsTargetMachine &TM) { 1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return new MipsSETargetLowering(TM); 1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool 114424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)MipsSETargetLowering::allowsUnalignedMemoryAccesses(EVT VT, bool *Fast) const { 115424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) MVT::SimpleValueType SVT = VT.getSimpleVT().SimpleTy; 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (SVT) { 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case MVT::i64: 119424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case MVT::i32: 120424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (Fast) 121424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) *Fast = true; 122424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 123424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) default: 124424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 125424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 126424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 127424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 128424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)SDValue MipsSETargetLowering::LowerOperation(SDValue Op, 129424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) SelectionDAG &DAG) const { 130424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) switch(Op.getOpcode()) { 131424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case ISD::SMUL_LOHI: return lowerMulDiv(Op, MipsISD::Mult, true, true, DAG); 132424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case ISD::UMUL_LOHI: return lowerMulDiv(Op, MipsISD::Multu, true, true, DAG); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ISD::MULHS: return lowerMulDiv(Op, MipsISD::Mult, false, true, DAG); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ISD::MULHU: return lowerMulDiv(Op, MipsISD::Multu, false, true, DAG); 135424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case ISD::MUL: return lowerMulDiv(Op, MipsISD::Mult, true, false, DAG); 136424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case ISD::SDIVREM: return lowerMulDiv(Op, MipsISD::DivRem, true, true, DAG); 137424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case ISD::UDIVREM: return lowerMulDiv(Op, MipsISD::DivRemU, true, true, 13858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DAG); 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case ISD::INTRINSIC_WO_CHAIN: return lowerINTRINSIC_WO_CHAIN(Op, DAG); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ISD::INTRINSIC_W_CHAIN: return lowerINTRINSIC_W_CHAIN(Op, DAG); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 14358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return MipsTargetLowering::LowerOperation(Op, DAG); 14458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 14558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// selectMADD - 14758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Transforms a subgraph in CurDAG if the following pattern is found: 14858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// (addc multLo, Lo0), (adde multHi, Hi0), 14958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// where, 15058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// multHi/Lo: product of multiplication 1518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Lo0: initial value of Lo register 1528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Hi0: initial value of Hi register 1538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Return true if pattern matching was successful. 1548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)static bool selectMADD(SDNode *ADDENode, SelectionDAG *CurDAG) { 1558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // ADDENode's second operand must be a flag output of an ADDC node in order 1568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // for the matching to be successful. 1578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) SDNode *ADDCNode = ADDENode->getOperand(2).getNode(); 1588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (ADDCNode->getOpcode() != ISD::ADDC) 1608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 1618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) SDValue MultHi = ADDENode->getOperand(0); 1638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) SDValue MultLo = ADDCNode->getOperand(0); 1648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) SDNode *MultNode = MultHi.getNode(); 1658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) unsigned MultOpc = MultHi.getOpcode(); 1668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // MultHi and MultLo must be generated by the same node, 1688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (MultLo.getNode() != MultNode) 1698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 1708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // and it must be a multiplication. 1728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (MultOpc != ISD::SMUL_LOHI && MultOpc != ISD::UMUL_LOHI) 1738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 1748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // MultLo amd MultHi must be the first and second output of MultNode 1768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // respectively. 1778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (MultHi.getResNo() != 1 || MultLo.getResNo() != 0) 1788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 1798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 1808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Transform this to a MADD only if ADDENode and ADDCNode are the only users 1818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // of the values of MultNode, in which case MultNode will be removed in later 1828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // phases. 1838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // If there exist users other than ADDENode or ADDCNode, this function returns 1848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // here, which will result in MultNode being mapped to a single MULT 185424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // instruction node rather than a pair of MULT and MADD instructions being 186424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // produced. 187424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!MultHi.hasOneUse() || !MultLo.hasOneUse()) 188424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 189424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 190424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) SDLoc DL(ADDENode); 191424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 192424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Initialize accumulator. 193424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) SDValue ACCIn = CurDAG->getNode(MipsISD::InsertLOHI, DL, MVT::Untyped, 194424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) ADDCNode->getOperand(1), 195424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) ADDENode->getOperand(1)); 196424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 197424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // create MipsMAdd(u) node 198424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MAddu : MipsISD::MAdd; 19958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 20058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SDValue MAdd = CurDAG->getNode(MultOpc, DL, MVT::Untyped, 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MultNode->getOperand(0),// Factor 0 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MultNode->getOperand(1),// Factor 1 203424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) ACCIn); 204424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 205424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // replace uses of adde and addc here 2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!SDValue(ADDCNode, 0).use_empty()) { 2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SDValue LoIdx = CurDAG->getConstant(Mips::sub_lo, MVT::i32); 2084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SDValue LoOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MAdd, 2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) LoIdx); 2104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDCNode, 0), LoOut); 2114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!SDValue(ADDENode, 0).use_empty()) { 2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SDValue HiIdx = CurDAG->getConstant(Mips::sub_hi, MVT::i32); 2144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SDValue HiOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MAdd, 2154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) HiIdx); 2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDENode, 0), HiOut); 2174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 218424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 219424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 220424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 221424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 222424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// selectMSUB - 223424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Transforms a subgraph in CurDAG if the following pattern is found: 22458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// (addc Lo0, multLo), (sube Hi0, multHi), 22558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// where, 22658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// multHi/Lo: product of multiplication 22758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Lo0: initial value of Lo register 22858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Hi0: initial value of Hi register 22958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Return true if pattern matching was successful. 23058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)static bool selectMSUB(SDNode *SUBENode, SelectionDAG *CurDAG) { 23158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // SUBENode's second operand must be a flag output of an SUBC node in order 23258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // for the matching to be successful. 23358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SDNode *SUBCNode = SUBENode->getOperand(2).getNode(); 23458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 23558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (SUBCNode->getOpcode() != ISD::SUBC) 23658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return false; 23758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 23858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SDValue MultHi = SUBENode->getOperand(1); 23958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SDValue MultLo = SUBCNode->getOperand(1); 24058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SDNode *MultNode = MultHi.getNode(); 24158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) unsigned MultOpc = MultHi.getOpcode(); 24258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 24358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // MultHi and MultLo must be generated by the same node, 24458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (MultLo.getNode() != MultNode) 24558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return false; 24658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 24758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // and it must be a multiplication. 24858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (MultOpc != ISD::SMUL_LOHI && MultOpc != ISD::UMUL_LOHI) 24958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return false; 25058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 25158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // MultLo amd MultHi must be the first and second output of MultNode 25258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // respectively. 25358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (MultHi.getResNo() != 1 || MultLo.getResNo() != 0) 25458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return false; 25558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 25658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Transform this to a MSUB only if SUBENode and SUBCNode are the only users 25758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // of the values of MultNode, in which case MultNode will be removed in later 258424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // phases. 259424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // If there exist users other than SUBENode or SUBCNode, this function returns 260424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // here, which will result in MultNode being mapped to a single MULT 261424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // instruction node rather than a pair of MULT and MSUB instructions being 262424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // produced. 263424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!MultHi.hasOneUse() || !MultLo.hasOneUse()) 264424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 265424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 266424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) SDLoc DL(SUBENode); 267424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 268424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Initialize accumulator. 269424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) SDValue ACCIn = CurDAG->getNode(MipsISD::InsertLOHI, DL, MVT::Untyped, 270424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) SUBCNode->getOperand(0), 271424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) SUBENode->getOperand(0)); 272424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 273424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // create MipsSub(u) node 274424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MSubu : MipsISD::MSub; 275424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 276424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) SDValue MSub = CurDAG->getNode(MultOpc, DL, MVT::Glue, 277424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) MultNode->getOperand(0),// Factor 0 278424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) MultNode->getOperand(1),// Factor 1 279424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) ACCIn); 280424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 281424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // replace uses of sube and subc here 282424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!SDValue(SUBCNode, 0).use_empty()) { 28358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SDValue LoIdx = CurDAG->getConstant(Mips::sub_lo, MVT::i32); 28458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SDValue LoOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MSub, 28558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) LoIdx); 28658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBCNode, 0), LoOut); 28758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 28858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!SDValue(SUBENode, 0).use_empty()) { 28958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SDValue HiIdx = CurDAG->getConstant(Mips::sub_hi, MVT::i32); 29058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SDValue HiOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MSub, 29158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) HiIdx); 29258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBENode, 0), HiOut); 29358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 29458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 29558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return true; 29658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 29758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 29858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)static SDValue performADDECombine(SDNode *N, SelectionDAG &DAG, 29958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) TargetLowering::DAGCombinerInfo &DCI, 30058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const MipsSubtarget *Subtarget) { 30158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (DCI.isBeforeLegalize()) 30258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return SDValue(); 30358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 30458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (Subtarget->hasMips32() && N->getValueType(0) == MVT::i32 && 305424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) selectMADD(N, &DAG)) 306424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return SDValue(N, 0); 307424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 308424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return SDValue(); 309424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 310424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 311424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)static SDValue performSUBECombine(SDNode *N, SelectionDAG &DAG, 312424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) TargetLowering::DAGCombinerInfo &DCI, 31358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const MipsSubtarget *Subtarget) { 31458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (DCI.isBeforeLegalize()) 31558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return SDValue(); 31658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 31758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (Subtarget->hasMips32() && N->getValueType(0) == MVT::i32 && 31858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) selectMSUB(N, &DAG)) 31958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return SDValue(N, 0); 32058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 32158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return SDValue(); 32258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 32358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 324424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)static SDValue genConstMult(SDValue X, uint64_t C, SDLoc DL, EVT VT, 325424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) EVT ShiftTy, SelectionDAG &DAG) { 326424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Clear the upper (64 - VT.sizeInBits) bits. 327424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) C &= ((uint64_t)-1) >> (64 - VT.getSizeInBits()); 32858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 329424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Return 0. 330424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (C == 0) 331424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return DAG.getConstant(0, VT); 332424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 333424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Return x. 334424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (C == 1) 335424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return X; 336424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 337424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // If c is power of 2, return (shl x, log2(c)). 338424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (isPowerOf2_64(C)) 339424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return DAG.getNode(ISD::SHL, DL, VT, X, 340424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DAG.getConstant(Log2_64(C), ShiftTy)); 341424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 342424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) unsigned Log2Ceil = Log2_64_Ceil(C); 343424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) uint64_t Floor = 1LL << Log2_64(C); 344424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) uint64_t Ceil = Log2Ceil == 64 ? 0LL : 1LL << Log2Ceil; 345424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 346424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // If |c - floor_c| <= |c - ceil_c|, 347424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // where floor_c = pow(2, floor(log2(c))) and ceil_c = pow(2, ceil(log2(c))), 34858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // return (add constMult(x, floor_c), constMult(x, c - floor_c)). 34958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (C - Floor <= Ceil - C) { 35058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SDValue Op0 = genConstMult(X, Floor, DL, VT, ShiftTy, DAG); 35158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SDValue Op1 = genConstMult(X, C - Floor, DL, VT, ShiftTy, DAG); 35258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return DAG.getNode(ISD::ADD, DL, VT, Op0, Op1); 35358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 35458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 35558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // If |c - floor_c| > |c - ceil_c|, 35658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // return (sub constMult(x, ceil_c), constMult(x, ceil_c - c)). 35758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SDValue Op0 = genConstMult(X, Ceil, DL, VT, ShiftTy, DAG); 35858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SDValue Op1 = genConstMult(X, Ceil - C, DL, VT, ShiftTy, DAG); 35958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return DAG.getNode(ISD::SUB, DL, VT, Op0, Op1); 36058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 36158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 36258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)static SDValue performMULCombine(SDNode *N, SelectionDAG &DAG, 36358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const TargetLowering::DAGCombinerInfo &DCI, 36458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const MipsSETargetLowering *TL) { 36558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) EVT VT = N->getValueType(0); 3664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) 3684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!VT.isVector()) 3694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return genConstMult(N->getOperand(0), C->getZExtValue(), SDLoc(N), 3704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) VT, TL->getScalarShiftAmountTy(VT), DAG); 3714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return SDValue(N, 0); 3734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 3744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)static SDValue performDSPShiftCombine(unsigned Opc, SDNode *N, EVT Ty, 3764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SelectionDAG &DAG, 3774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const MipsSubtarget *Subtarget) { 3784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // See if this is a vector splat immediate node. 3794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) APInt SplatValue, SplatUndef; 3804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) unsigned SplatBitSize; 3814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool HasAnyUndefs; 3824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) unsigned EltSize = Ty.getVectorElementType().getSizeInBits(); 3834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) BuildVectorSDNode *BV = dyn_cast<BuildVectorSDNode>(N->getOperand(1)); 3844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!BV || 386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !BV->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs, 387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EltSize, !Subtarget->isLittle()) || 388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (SplatBitSize != EltSize) || 389 (SplatValue.getZExtValue() >= EltSize)) 390 return SDValue(); 391 392 return DAG.getNode(Opc, SDLoc(N), Ty, N->getOperand(0), 393 DAG.getConstant(SplatValue.getZExtValue(), MVT::i32)); 394} 395 396static SDValue performSHLCombine(SDNode *N, SelectionDAG &DAG, 397 TargetLowering::DAGCombinerInfo &DCI, 398 const MipsSubtarget *Subtarget) { 399 EVT Ty = N->getValueType(0); 400 401 if ((Ty != MVT::v2i16) && (Ty != MVT::v4i8)) 402 return SDValue(); 403 404 return performDSPShiftCombine(MipsISD::SHLL_DSP, N, Ty, DAG, Subtarget); 405} 406 407static SDValue performSRACombine(SDNode *N, SelectionDAG &DAG, 408 TargetLowering::DAGCombinerInfo &DCI, 409 const MipsSubtarget *Subtarget) { 410 EVT Ty = N->getValueType(0); 411 412 if ((Ty != MVT::v2i16) && ((Ty != MVT::v4i8) || !Subtarget->hasDSPR2())) 413 return SDValue(); 414 415 return performDSPShiftCombine(MipsISD::SHRA_DSP, N, Ty, DAG, Subtarget); 416} 417 418 419static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG, 420 TargetLowering::DAGCombinerInfo &DCI, 421 const MipsSubtarget *Subtarget) { 422 EVT Ty = N->getValueType(0); 423 424 if (((Ty != MVT::v2i16) || !Subtarget->hasDSPR2()) && (Ty != MVT::v4i8)) 425 return SDValue(); 426 427 return performDSPShiftCombine(MipsISD::SHRL_DSP, N, Ty, DAG, Subtarget); 428} 429 430static bool isLegalDSPCondCode(EVT Ty, ISD::CondCode CC) { 431 bool IsV216 = (Ty == MVT::v2i16); 432 433 switch (CC) { 434 case ISD::SETEQ: 435 case ISD::SETNE: return true; 436 case ISD::SETLT: 437 case ISD::SETLE: 438 case ISD::SETGT: 439 case ISD::SETGE: return IsV216; 440 case ISD::SETULT: 441 case ISD::SETULE: 442 case ISD::SETUGT: 443 case ISD::SETUGE: return !IsV216; 444 default: return false; 445 } 446} 447 448static SDValue performSETCCCombine(SDNode *N, SelectionDAG &DAG) { 449 EVT Ty = N->getValueType(0); 450 451 if ((Ty != MVT::v2i16) && (Ty != MVT::v4i8)) 452 return SDValue(); 453 454 if (!isLegalDSPCondCode(Ty, cast<CondCodeSDNode>(N->getOperand(2))->get())) 455 return SDValue(); 456 457 return DAG.getNode(MipsISD::SETCC_DSP, SDLoc(N), Ty, N->getOperand(0), 458 N->getOperand(1), N->getOperand(2)); 459} 460 461static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG) { 462 EVT Ty = N->getValueType(0); 463 464 if ((Ty != MVT::v2i16) && (Ty != MVT::v4i8)) 465 return SDValue(); 466 467 SDValue SetCC = N->getOperand(0); 468 469 if (SetCC.getOpcode() != MipsISD::SETCC_DSP) 470 return SDValue(); 471 472 return DAG.getNode(MipsISD::SELECT_CC_DSP, SDLoc(N), Ty, 473 SetCC.getOperand(0), SetCC.getOperand(1), N->getOperand(1), 474 N->getOperand(2), SetCC.getOperand(2)); 475} 476 477SDValue 478MipsSETargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { 479 SelectionDAG &DAG = DCI.DAG; 480 SDValue Val; 481 482 switch (N->getOpcode()) { 483 case ISD::ADDE: 484 return performADDECombine(N, DAG, DCI, Subtarget); 485 case ISD::SUBE: 486 return performSUBECombine(N, DAG, DCI, Subtarget); 487 case ISD::MUL: 488 return performMULCombine(N, DAG, DCI, this); 489 case ISD::SHL: 490 return performSHLCombine(N, DAG, DCI, Subtarget); 491 case ISD::SRA: 492 return performSRACombine(N, DAG, DCI, Subtarget); 493 case ISD::SRL: 494 return performSRLCombine(N, DAG, DCI, Subtarget); 495 case ISD::VSELECT: 496 return performVSELECTCombine(N, DAG); 497 case ISD::SETCC: { 498 Val = performSETCCCombine(N, DAG); 499 break; 500 } 501 } 502 503 if (Val.getNode()) 504 return Val; 505 506 return MipsTargetLowering::PerformDAGCombine(N, DCI); 507} 508 509MachineBasicBlock * 510MipsSETargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, 511 MachineBasicBlock *BB) const { 512 switch (MI->getOpcode()) { 513 default: 514 return MipsTargetLowering::EmitInstrWithCustomInserter(MI, BB); 515 case Mips::BPOSGE32_PSEUDO: 516 return emitBPOSGE32(MI, BB); 517 } 518} 519 520bool MipsSETargetLowering:: 521isEligibleForTailCallOptimization(const MipsCC &MipsCCInfo, 522 unsigned NextStackOffset, 523 const MipsFunctionInfo& FI) const { 524 if (!EnableMipsTailCalls) 525 return false; 526 527 // Return false if either the callee or caller has a byval argument. 528 if (MipsCCInfo.hasByValArg() || FI.hasByvalArg()) 529 return false; 530 531 // Return true if the callee's argument area is no larger than the 532 // caller's. 533 return NextStackOffset <= FI.getIncomingArgSize(); 534} 535 536void MipsSETargetLowering:: 537getOpndList(SmallVectorImpl<SDValue> &Ops, 538 std::deque< std::pair<unsigned, SDValue> > &RegsToPass, 539 bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, 540 CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const { 541 // T9 should contain the address of the callee function if 542 // -reloction-model=pic or it is an indirect call. 543 if (IsPICCall || !GlobalOrExternal) { 544 unsigned T9Reg = IsN64 ? Mips::T9_64 : Mips::T9; 545 RegsToPass.push_front(std::make_pair(T9Reg, Callee)); 546 } else 547 Ops.push_back(Callee); 548 549 MipsTargetLowering::getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal, 550 InternalLinkage, CLI, Callee, Chain); 551} 552 553SDValue MipsSETargetLowering::lowerMulDiv(SDValue Op, unsigned NewOpc, 554 bool HasLo, bool HasHi, 555 SelectionDAG &DAG) const { 556 EVT Ty = Op.getOperand(0).getValueType(); 557 SDLoc DL(Op); 558 SDValue Mult = DAG.getNode(NewOpc, DL, MVT::Untyped, 559 Op.getOperand(0), Op.getOperand(1)); 560 SDValue Lo, Hi; 561 562 if (HasLo) 563 Lo = DAG.getNode(MipsISD::ExtractLOHI, DL, Ty, Mult, 564 DAG.getConstant(Mips::sub_lo, MVT::i32)); 565 if (HasHi) 566 Hi = DAG.getNode(MipsISD::ExtractLOHI, DL, Ty, Mult, 567 DAG.getConstant(Mips::sub_hi, MVT::i32)); 568 569 if (!HasLo || !HasHi) 570 return HasLo ? Lo : Hi; 571 572 SDValue Vals[] = { Lo, Hi }; 573 return DAG.getMergeValues(Vals, 2, DL); 574} 575 576 577static SDValue initAccumulator(SDValue In, SDLoc DL, SelectionDAG &DAG) { 578 SDValue InLo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, In, 579 DAG.getConstant(0, MVT::i32)); 580 SDValue InHi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, In, 581 DAG.getConstant(1, MVT::i32)); 582 return DAG.getNode(MipsISD::InsertLOHI, DL, MVT::Untyped, InLo, InHi); 583} 584 585static SDValue extractLOHI(SDValue Op, SDLoc DL, SelectionDAG &DAG) { 586 SDValue Lo = DAG.getNode(MipsISD::ExtractLOHI, DL, MVT::i32, Op, 587 DAG.getConstant(Mips::sub_lo, MVT::i32)); 588 SDValue Hi = DAG.getNode(MipsISD::ExtractLOHI, DL, MVT::i32, Op, 589 DAG.getConstant(Mips::sub_hi, MVT::i32)); 590 return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Lo, Hi); 591} 592 593// This function expands mips intrinsic nodes which have 64-bit input operands 594// or output values. 595// 596// out64 = intrinsic-node in64 597// => 598// lo = copy (extract-element (in64, 0)) 599// hi = copy (extract-element (in64, 1)) 600// mips-specific-node 601// v0 = copy lo 602// v1 = copy hi 603// out64 = merge-values (v0, v1) 604// 605static SDValue lowerDSPIntr(SDValue Op, SelectionDAG &DAG, unsigned Opc) { 606 SDLoc DL(Op); 607 bool HasChainIn = Op->getOperand(0).getValueType() == MVT::Other; 608 SmallVector<SDValue, 3> Ops; 609 unsigned OpNo = 0; 610 611 // See if Op has a chain input. 612 if (HasChainIn) 613 Ops.push_back(Op->getOperand(OpNo++)); 614 615 // The next operand is the intrinsic opcode. 616 assert(Op->getOperand(OpNo).getOpcode() == ISD::TargetConstant); 617 618 // See if the next operand has type i64. 619 SDValue Opnd = Op->getOperand(++OpNo), In64; 620 621 if (Opnd.getValueType() == MVT::i64) 622 In64 = initAccumulator(Opnd, DL, DAG); 623 else 624 Ops.push_back(Opnd); 625 626 // Push the remaining operands. 627 for (++OpNo ; OpNo < Op->getNumOperands(); ++OpNo) 628 Ops.push_back(Op->getOperand(OpNo)); 629 630 // Add In64 to the end of the list. 631 if (In64.getNode()) 632 Ops.push_back(In64); 633 634 // Scan output. 635 SmallVector<EVT, 2> ResTys; 636 637 for (SDNode::value_iterator I = Op->value_begin(), E = Op->value_end(); 638 I != E; ++I) 639 ResTys.push_back((*I == MVT::i64) ? MVT::Untyped : *I); 640 641 // Create node. 642 SDValue Val = DAG.getNode(Opc, DL, ResTys, &Ops[0], Ops.size()); 643 SDValue Out = (ResTys[0] == MVT::Untyped) ? extractLOHI(Val, DL, DAG) : Val; 644 645 if (!HasChainIn) 646 return Out; 647 648 assert(Val->getValueType(1) == MVT::Other); 649 SDValue Vals[] = { Out, SDValue(Val.getNode(), 1) }; 650 return DAG.getMergeValues(Vals, 2, DL); 651} 652 653SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, 654 SelectionDAG &DAG) const { 655 switch (cast<ConstantSDNode>(Op->getOperand(0))->getZExtValue()) { 656 default: 657 return SDValue(); 658 case Intrinsic::mips_shilo: 659 return lowerDSPIntr(Op, DAG, MipsISD::SHILO); 660 case Intrinsic::mips_dpau_h_qbl: 661 return lowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBL); 662 case Intrinsic::mips_dpau_h_qbr: 663 return lowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBR); 664 case Intrinsic::mips_dpsu_h_qbl: 665 return lowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBL); 666 case Intrinsic::mips_dpsu_h_qbr: 667 return lowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBR); 668 case Intrinsic::mips_dpa_w_ph: 669 return lowerDSPIntr(Op, DAG, MipsISD::DPA_W_PH); 670 case Intrinsic::mips_dps_w_ph: 671 return lowerDSPIntr(Op, DAG, MipsISD::DPS_W_PH); 672 case Intrinsic::mips_dpax_w_ph: 673 return lowerDSPIntr(Op, DAG, MipsISD::DPAX_W_PH); 674 case Intrinsic::mips_dpsx_w_ph: 675 return lowerDSPIntr(Op, DAG, MipsISD::DPSX_W_PH); 676 case Intrinsic::mips_mulsa_w_ph: 677 return lowerDSPIntr(Op, DAG, MipsISD::MULSA_W_PH); 678 case Intrinsic::mips_mult: 679 return lowerDSPIntr(Op, DAG, MipsISD::Mult); 680 case Intrinsic::mips_multu: 681 return lowerDSPIntr(Op, DAG, MipsISD::Multu); 682 case Intrinsic::mips_madd: 683 return lowerDSPIntr(Op, DAG, MipsISD::MAdd); 684 case Intrinsic::mips_maddu: 685 return lowerDSPIntr(Op, DAG, MipsISD::MAddu); 686 case Intrinsic::mips_msub: 687 return lowerDSPIntr(Op, DAG, MipsISD::MSub); 688 case Intrinsic::mips_msubu: 689 return lowerDSPIntr(Op, DAG, MipsISD::MSubu); 690 } 691} 692 693SDValue MipsSETargetLowering::lowerINTRINSIC_W_CHAIN(SDValue Op, 694 SelectionDAG &DAG) const { 695 switch (cast<ConstantSDNode>(Op->getOperand(1))->getZExtValue()) { 696 default: 697 return SDValue(); 698 case Intrinsic::mips_extp: 699 return lowerDSPIntr(Op, DAG, MipsISD::EXTP); 700 case Intrinsic::mips_extpdp: 701 return lowerDSPIntr(Op, DAG, MipsISD::EXTPDP); 702 case Intrinsic::mips_extr_w: 703 return lowerDSPIntr(Op, DAG, MipsISD::EXTR_W); 704 case Intrinsic::mips_extr_r_w: 705 return lowerDSPIntr(Op, DAG, MipsISD::EXTR_R_W); 706 case Intrinsic::mips_extr_rs_w: 707 return lowerDSPIntr(Op, DAG, MipsISD::EXTR_RS_W); 708 case Intrinsic::mips_extr_s_h: 709 return lowerDSPIntr(Op, DAG, MipsISD::EXTR_S_H); 710 case Intrinsic::mips_mthlip: 711 return lowerDSPIntr(Op, DAG, MipsISD::MTHLIP); 712 case Intrinsic::mips_mulsaq_s_w_ph: 713 return lowerDSPIntr(Op, DAG, MipsISD::MULSAQ_S_W_PH); 714 case Intrinsic::mips_maq_s_w_phl: 715 return lowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHL); 716 case Intrinsic::mips_maq_s_w_phr: 717 return lowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHR); 718 case Intrinsic::mips_maq_sa_w_phl: 719 return lowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHL); 720 case Intrinsic::mips_maq_sa_w_phr: 721 return lowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHR); 722 case Intrinsic::mips_dpaq_s_w_ph: 723 return lowerDSPIntr(Op, DAG, MipsISD::DPAQ_S_W_PH); 724 case Intrinsic::mips_dpsq_s_w_ph: 725 return lowerDSPIntr(Op, DAG, MipsISD::DPSQ_S_W_PH); 726 case Intrinsic::mips_dpaq_sa_l_w: 727 return lowerDSPIntr(Op, DAG, MipsISD::DPAQ_SA_L_W); 728 case Intrinsic::mips_dpsq_sa_l_w: 729 return lowerDSPIntr(Op, DAG, MipsISD::DPSQ_SA_L_W); 730 case Intrinsic::mips_dpaqx_s_w_ph: 731 return lowerDSPIntr(Op, DAG, MipsISD::DPAQX_S_W_PH); 732 case Intrinsic::mips_dpaqx_sa_w_ph: 733 return lowerDSPIntr(Op, DAG, MipsISD::DPAQX_SA_W_PH); 734 case Intrinsic::mips_dpsqx_s_w_ph: 735 return lowerDSPIntr(Op, DAG, MipsISD::DPSQX_S_W_PH); 736 case Intrinsic::mips_dpsqx_sa_w_ph: 737 return lowerDSPIntr(Op, DAG, MipsISD::DPSQX_SA_W_PH); 738 } 739} 740 741MachineBasicBlock * MipsSETargetLowering:: 742emitBPOSGE32(MachineInstr *MI, MachineBasicBlock *BB) const{ 743 // $bb: 744 // bposge32_pseudo $vr0 745 // => 746 // $bb: 747 // bposge32 $tbb 748 // $fbb: 749 // li $vr2, 0 750 // b $sink 751 // $tbb: 752 // li $vr1, 1 753 // $sink: 754 // $vr0 = phi($vr2, $fbb, $vr1, $tbb) 755 756 MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); 757 const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); 758 const TargetRegisterClass *RC = &Mips::CPURegsRegClass; 759 DebugLoc DL = MI->getDebugLoc(); 760 const BasicBlock *LLVM_BB = BB->getBasicBlock(); 761 MachineFunction::iterator It = llvm::next(MachineFunction::iterator(BB)); 762 MachineFunction *F = BB->getParent(); 763 MachineBasicBlock *FBB = F->CreateMachineBasicBlock(LLVM_BB); 764 MachineBasicBlock *TBB = F->CreateMachineBasicBlock(LLVM_BB); 765 MachineBasicBlock *Sink = F->CreateMachineBasicBlock(LLVM_BB); 766 F->insert(It, FBB); 767 F->insert(It, TBB); 768 F->insert(It, Sink); 769 770 // Transfer the remainder of BB and its successor edges to Sink. 771 Sink->splice(Sink->begin(), BB, llvm::next(MachineBasicBlock::iterator(MI)), 772 BB->end()); 773 Sink->transferSuccessorsAndUpdatePHIs(BB); 774 775 // Add successors. 776 BB->addSuccessor(FBB); 777 BB->addSuccessor(TBB); 778 FBB->addSuccessor(Sink); 779 TBB->addSuccessor(Sink); 780 781 // Insert the real bposge32 instruction to $BB. 782 BuildMI(BB, DL, TII->get(Mips::BPOSGE32)).addMBB(TBB); 783 784 // Fill $FBB. 785 unsigned VR2 = RegInfo.createVirtualRegister(RC); 786 BuildMI(*FBB, FBB->end(), DL, TII->get(Mips::ADDiu), VR2) 787 .addReg(Mips::ZERO).addImm(0); 788 BuildMI(*FBB, FBB->end(), DL, TII->get(Mips::B)).addMBB(Sink); 789 790 // Fill $TBB. 791 unsigned VR1 = RegInfo.createVirtualRegister(RC); 792 BuildMI(*TBB, TBB->end(), DL, TII->get(Mips::ADDiu), VR1) 793 .addReg(Mips::ZERO).addImm(1); 794 795 // Insert phi function to $Sink. 796 BuildMI(*Sink, Sink->begin(), DL, TII->get(Mips::PHI), 797 MI->getOperand(0).getReg()) 798 .addReg(VR2).addMBB(FBB).addReg(VR1).addMBB(TBB); 799 800 MI->eraseFromParent(); // The pseudo instruction is gone now. 801 return Sink; 802} 803