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::FrameIndex: { 72 SDValue Imm = CurDAG->getTargetConstant(0, Dl, MVT::i32); 73 int FI = cast<FrameIndexSDNode>(N)->getIndex(); 74 SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i32); 75 ReplaceNode(N, CurDAG->getMachineNode(Subtarget->hasE2() ? CSKY::ADDI32 76 : CSKY::ADDI16XZ, 77 Dl, MVT::i32, TFI, Imm)); 78 79 IsSelected = true; 80 break; 81 } 82 } 83 84 if (IsSelected) 85 return; 86 87 // Select the default instruction. 88 SelectCode(N); 89 } 90 91 bool CSKYDAGToDAGISel::selectAddCarry(SDNode *N) { 92 MachineSDNode *NewNode = nullptr; 93 auto Type0 = N->getValueType(0); 94 auto Type1 = N->getValueType(1); 95 auto Op0 = N->getOperand(0); 96 auto Op1 = N->getOperand(1); 97 auto Op2 = N->getOperand(2); 98 99 SDLoc Dl(N); 100 101 if (isNullConstant(Op2)) { 102 auto *CA = CurDAG->getMachineNode( 103 Subtarget->has2E3() ? CSKY::CLRC32 : CSKY::CLRC16, Dl, Type1); 104 NewNode = CurDAG->getMachineNode( 105 Subtarget->has2E3() ? CSKY::ADDC32 : CSKY::ADDC16, Dl, {Type0, Type1}, 106 {Op0, Op1, SDValue(CA, 0)}); 107 } else if (isOneConstant(Op2)) { 108 auto *CA = CurDAG->getMachineNode( 109 Subtarget->has2E3() ? CSKY::SETC32 : CSKY::SETC16, Dl, Type1); 110 NewNode = CurDAG->getMachineNode( 111 Subtarget->has2E3() ? CSKY::ADDC32 : CSKY::ADDC16, Dl, {Type0, Type1}, 112 {Op0, Op1, SDValue(CA, 0)}); 113 } else { 114 NewNode = CurDAG->getMachineNode(Subtarget->has2E3() ? CSKY::ADDC32 115 : CSKY::ADDC16, 116 Dl, {Type0, Type1}, {Op0, Op1, Op2}); 117 } 118 ReplaceNode(N, NewNode); 119 return true; 120 } 121 122 static SDValue InvertCarryFlag(const CSKYSubtarget *Subtarget, 123 SelectionDAG *DAG, SDLoc Dl, SDValue OldCarry) { 124 auto NewCarryReg = 125 DAG->getMachineNode(Subtarget->has2E3() ? CSKY::MVCV32 : CSKY::MVCV16, Dl, 126 MVT::i32, OldCarry); 127 auto NewCarry = 128 DAG->getMachineNode(Subtarget->hasE2() ? CSKY::BTSTI32 : CSKY::BTSTI16, 129 Dl, OldCarry.getValueType(), SDValue(NewCarryReg, 0), 130 DAG->getTargetConstant(0, Dl, MVT::i32)); 131 return SDValue(NewCarry, 0); 132 } 133 134 bool CSKYDAGToDAGISel::selectSubCarry(SDNode *N) { 135 MachineSDNode *NewNode = nullptr; 136 auto Type0 = N->getValueType(0); 137 auto Type1 = N->getValueType(1); 138 auto Op0 = N->getOperand(0); 139 auto Op1 = N->getOperand(1); 140 auto Op2 = N->getOperand(2); 141 142 SDLoc Dl(N); 143 144 if (isNullConstant(Op2)) { 145 auto *CA = CurDAG->getMachineNode( 146 Subtarget->has2E3() ? CSKY::SETC32 : CSKY::SETC16, Dl, Type1); 147 NewNode = CurDAG->getMachineNode( 148 Subtarget->has2E3() ? CSKY::SUBC32 : CSKY::SUBC16, Dl, {Type0, Type1}, 149 {Op0, Op1, SDValue(CA, 0)}); 150 } else if (isOneConstant(Op2)) { 151 auto *CA = CurDAG->getMachineNode( 152 Subtarget->has2E3() ? CSKY::CLRC32 : CSKY::CLRC16, Dl, Type1); 153 NewNode = CurDAG->getMachineNode( 154 Subtarget->has2E3() ? CSKY::SUBC32 : CSKY::SUBC16, Dl, {Type0, Type1}, 155 {Op0, Op1, SDValue(CA, 0)}); 156 } else { 157 auto CarryIn = InvertCarryFlag(Subtarget, CurDAG, Dl, Op2); 158 NewNode = CurDAG->getMachineNode(Subtarget->has2E3() ? CSKY::SUBC32 159 : CSKY::SUBC16, 160 Dl, {Type0, Type1}, {Op0, Op1, CarryIn}); 161 } 162 auto CarryOut = InvertCarryFlag(Subtarget, CurDAG, Dl, SDValue(NewNode, 1)); 163 164 ReplaceUses(SDValue(N, 0), SDValue(NewNode, 0)); 165 ReplaceUses(SDValue(N, 1), CarryOut); 166 CurDAG->RemoveDeadNode(N); 167 168 return true; 169 } 170 171 FunctionPass *llvm::createCSKYISelDag(CSKYTargetMachine &TM) { 172 return new CSKYDAGToDAGISel(TM); 173 } 174