1 //===-- CSKYISelDAGToDAG.cpp - A dag to dag inst selector for CSKY---------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines an instruction selector for the CSKY target. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "CSKY.h" 14 #include "CSKYSubtarget.h" 15 #include "CSKYTargetMachine.h" 16 #include "MCTargetDesc/CSKYMCTargetDesc.h" 17 #include "llvm/CodeGen/SelectionDAG.h" 18 #include "llvm/CodeGen/SelectionDAGISel.h" 19 20 using namespace llvm; 21 22 #define DEBUG_TYPE "csky-isel" 23 24 namespace { 25 class CSKYDAGToDAGISel : public SelectionDAGISel { 26 const CSKYSubtarget *Subtarget; 27 28 public: 29 explicit CSKYDAGToDAGISel(CSKYTargetMachine &TM) : SelectionDAGISel(TM) {} 30 31 StringRef getPassName() const override { 32 return "CSKY DAG->DAG Pattern Instruction Selection"; 33 } 34 35 bool runOnMachineFunction(MachineFunction &MF) override { 36 // Reset the subtarget each time through. 37 Subtarget = &MF.getSubtarget<CSKYSubtarget>(); 38 SelectionDAGISel::runOnMachineFunction(MF); 39 return true; 40 } 41 42 void Select(SDNode *N) override; 43 bool selectAddCarry(SDNode *N); 44 bool selectSubCarry(SDNode *N); 45 46 #include "CSKYGenDAGISel.inc" 47 }; 48 } // namespace 49 50 void CSKYDAGToDAGISel::Select(SDNode *N) { 51 // If we have a custom node, we have already selected 52 if (N->isMachineOpcode()) { 53 LLVM_DEBUG(dbgs() << "== "; N->dump(CurDAG); dbgs() << "\n"); 54 N->setNodeId(-1); 55 return; 56 } 57 58 SDLoc Dl(N); 59 unsigned Opcode = N->getOpcode(); 60 bool IsSelected = false; 61 62 switch (Opcode) { 63 default: 64 break; 65 case ISD::ADDCARRY: 66 IsSelected = selectAddCarry(N); 67 break; 68 case ISD::SUBCARRY: 69 IsSelected = selectSubCarry(N); 70 break; 71 case ISD::GLOBAL_OFFSET_TABLE: { 72 Register GP = Subtarget->getInstrInfo()->getGlobalBaseReg(*MF); 73 ReplaceNode(N, CurDAG->getRegister(GP, N->getValueType(0)).getNode()); 74 75 IsSelected = true; 76 break; 77 } 78 case ISD::FrameIndex: { 79 SDValue Imm = CurDAG->getTargetConstant(0, Dl, MVT::i32); 80 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 81 SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i32); 82 ReplaceNode(N, CurDAG->getMachineNode(Subtarget->hasE2() ? CSKY::ADDI32 83 : CSKY::ADDI16XZ, 84 Dl, MVT::i32, TFI, Imm)); 85 86 IsSelected = true; 87 break; 88 } 89 } 90 91 if (IsSelected) 92 return; 93 94 // Select the default instruction. 95 SelectCode(N); 96 } 97 98 bool CSKYDAGToDAGISel::selectAddCarry(SDNode *N) { 99 MachineSDNode *NewNode = nullptr; 100 auto Type0 = N->getValueType(0); 101 auto Type1 = N->getValueType(1); 102 auto Op0 = N->getOperand(0); 103 auto Op1 = N->getOperand(1); 104 auto Op2 = N->getOperand(2); 105 106 SDLoc Dl(N); 107 108 if (isNullConstant(Op2)) { 109 auto *CA = CurDAG->getMachineNode( 110 Subtarget->has2E3() ? CSKY::CLRC32 : CSKY::CLRC16, Dl, Type1); 111 NewNode = CurDAG->getMachineNode( 112 Subtarget->has2E3() ? CSKY::ADDC32 : CSKY::ADDC16, Dl, {Type0, Type1}, 113 {Op0, Op1, SDValue(CA, 0)}); 114 } else if (isOneConstant(Op2)) { 115 auto *CA = CurDAG->getMachineNode( 116 Subtarget->has2E3() ? CSKY::SETC32 : CSKY::SETC16, Dl, Type1); 117 NewNode = CurDAG->getMachineNode( 118 Subtarget->has2E3() ? CSKY::ADDC32 : CSKY::ADDC16, Dl, {Type0, Type1}, 119 {Op0, Op1, SDValue(CA, 0)}); 120 } else { 121 NewNode = CurDAG->getMachineNode(Subtarget->has2E3() ? CSKY::ADDC32 122 : CSKY::ADDC16, 123 Dl, {Type0, Type1}, {Op0, Op1, Op2}); 124 } 125 ReplaceNode(N, NewNode); 126 return true; 127 } 128 129 static SDValue InvertCarryFlag(const CSKYSubtarget *Subtarget, 130 SelectionDAG *DAG, SDLoc Dl, SDValue OldCarry) { 131 auto NewCarryReg = 132 DAG->getMachineNode(Subtarget->has2E3() ? CSKY::MVCV32 : CSKY::MVCV16, Dl, 133 MVT::i32, OldCarry); 134 auto NewCarry = 135 DAG->getMachineNode(Subtarget->hasE2() ? CSKY::BTSTI32 : CSKY::BTSTI16, 136 Dl, OldCarry.getValueType(), SDValue(NewCarryReg, 0), 137 DAG->getTargetConstant(0, Dl, MVT::i32)); 138 return SDValue(NewCarry, 0); 139 } 140 141 bool CSKYDAGToDAGISel::selectSubCarry(SDNode *N) { 142 MachineSDNode *NewNode = nullptr; 143 auto Type0 = N->getValueType(0); 144 auto Type1 = N->getValueType(1); 145 auto Op0 = N->getOperand(0); 146 auto Op1 = N->getOperand(1); 147 auto Op2 = N->getOperand(2); 148 149 SDLoc Dl(N); 150 151 if (isNullConstant(Op2)) { 152 auto *CA = CurDAG->getMachineNode( 153 Subtarget->has2E3() ? CSKY::SETC32 : CSKY::SETC16, Dl, Type1); 154 NewNode = CurDAG->getMachineNode( 155 Subtarget->has2E3() ? CSKY::SUBC32 : CSKY::SUBC16, Dl, {Type0, Type1}, 156 {Op0, Op1, SDValue(CA, 0)}); 157 } else if (isOneConstant(Op2)) { 158 auto *CA = CurDAG->getMachineNode( 159 Subtarget->has2E3() ? CSKY::CLRC32 : CSKY::CLRC16, Dl, Type1); 160 NewNode = CurDAG->getMachineNode( 161 Subtarget->has2E3() ? CSKY::SUBC32 : CSKY::SUBC16, Dl, {Type0, Type1}, 162 {Op0, Op1, SDValue(CA, 0)}); 163 } else { 164 auto CarryIn = InvertCarryFlag(Subtarget, CurDAG, Dl, Op2); 165 NewNode = CurDAG->getMachineNode(Subtarget->has2E3() ? CSKY::SUBC32 166 : CSKY::SUBC16, 167 Dl, {Type0, Type1}, {Op0, Op1, CarryIn}); 168 } 169 auto CarryOut = InvertCarryFlag(Subtarget, CurDAG, Dl, SDValue(NewNode, 1)); 170 171 ReplaceUses(SDValue(N, 0), SDValue(NewNode, 0)); 172 ReplaceUses(SDValue(N, 1), CarryOut); 173 CurDAG->RemoveDeadNode(N); 174 175 return true; 176 } 177 178 FunctionPass *llvm::createCSKYISelDag(CSKYTargetMachine &TM) { 179 return new CSKYDAGToDAGISel(TM); 180 } 181