@@ -40,6 +40,8 @@ class CSKYDAGToDAGISel : public SelectionDAGISel {
40
40
}
41
41
42
42
void Select (SDNode *N) override ;
43
+ bool selectAddCarry (SDNode *N);
44
+ bool selectSubCarry (SDNode *N);
43
45
44
46
#include " CSKYGenDAGISel.inc"
45
47
};
@@ -60,7 +62,12 @@ void CSKYDAGToDAGISel::Select(SDNode *N) {
60
62
switch (Opcode) {
61
63
default :
62
64
break ;
63
- // FIXME: Add selection nodes needed later.
65
+ case ISD::ADDCARRY:
66
+ IsSelected = selectAddCarry (N);
67
+ break ;
68
+ case ISD::SUBCARRY:
69
+ IsSelected = selectSubCarry (N);
70
+ break ;
64
71
}
65
72
66
73
if (IsSelected)
@@ -70,6 +77,86 @@ void CSKYDAGToDAGISel::Select(SDNode *N) {
70
77
SelectCode (N);
71
78
}
72
79
80
+ bool CSKYDAGToDAGISel::selectAddCarry (SDNode *N) {
81
+ MachineSDNode *NewNode = nullptr ;
82
+ auto Type0 = N->getValueType (0 );
83
+ auto Type1 = N->getValueType (1 );
84
+ auto Op0 = N->getOperand (0 );
85
+ auto Op1 = N->getOperand (1 );
86
+ auto Op2 = N->getOperand (2 );
87
+
88
+ SDLoc Dl (N);
89
+
90
+ if (isNullConstant (Op2)) {
91
+ auto *CA = CurDAG->getMachineNode (
92
+ Subtarget->has2E3 () ? CSKY::CLRC32 : CSKY::CLRC16, Dl, Type1);
93
+ NewNode = CurDAG->getMachineNode (
94
+ Subtarget->has2E3 () ? CSKY::ADDC32 : CSKY::ADDC16, Dl, {Type0, Type1},
95
+ {Op0, Op1, SDValue (CA, 0 )});
96
+ } else if (isOneConstant (Op2)) {
97
+ auto *CA = CurDAG->getMachineNode (
98
+ Subtarget->has2E3 () ? CSKY::SETC32 : CSKY::SETC16, Dl, Type1);
99
+ NewNode = CurDAG->getMachineNode (
100
+ Subtarget->has2E3 () ? CSKY::ADDC32 : CSKY::ADDC16, Dl, {Type0, Type1},
101
+ {Op0, Op1, SDValue (CA, 0 )});
102
+ } else {
103
+ NewNode = CurDAG->getMachineNode (Subtarget->has2E3 () ? CSKY::ADDC32
104
+ : CSKY::ADDC16,
105
+ Dl, {Type0, Type1}, {Op0, Op1, Op2});
106
+ }
107
+ ReplaceNode (N, NewNode);
108
+ return true ;
109
+ }
110
+
111
+ static SDValue InvertCarryFlag (const CSKYSubtarget *Subtarget,
112
+ SelectionDAG *DAG, SDLoc Dl, SDValue OldCarry) {
113
+ auto NewCarryReg =
114
+ DAG->getMachineNode (Subtarget->has2E3 () ? CSKY::MVCV32 : CSKY::MVCV16, Dl,
115
+ MVT::i32 , OldCarry);
116
+ auto NewCarry =
117
+ DAG->getMachineNode (Subtarget->hasE2 () ? CSKY::BTSTI32 : CSKY::BTSTI16,
118
+ Dl, OldCarry.getValueType (), SDValue (NewCarryReg, 0 ),
119
+ DAG->getTargetConstant (0 , Dl, MVT::i32 ));
120
+ return SDValue (NewCarry, 0 );
121
+ }
122
+
123
+ bool CSKYDAGToDAGISel::selectSubCarry (SDNode *N) {
124
+ MachineSDNode *NewNode = nullptr ;
125
+ auto Type0 = N->getValueType (0 );
126
+ auto Type1 = N->getValueType (1 );
127
+ auto Op0 = N->getOperand (0 );
128
+ auto Op1 = N->getOperand (1 );
129
+ auto Op2 = N->getOperand (2 );
130
+
131
+ SDLoc Dl (N);
132
+
133
+ if (isNullConstant (Op2)) {
134
+ auto *CA = CurDAG->getMachineNode (
135
+ Subtarget->has2E3 () ? CSKY::SETC32 : CSKY::SETC16, Dl, Type1);
136
+ NewNode = CurDAG->getMachineNode (
137
+ Subtarget->has2E3 () ? CSKY::SUBC32 : CSKY::SUBC16, Dl, {Type0, Type1},
138
+ {Op0, Op1, SDValue (CA, 0 )});
139
+ } else if (isOneConstant (Op2)) {
140
+ auto *CA = CurDAG->getMachineNode (
141
+ Subtarget->has2E3 () ? CSKY::CLRC32 : CSKY::CLRC16, Dl, Type1);
142
+ NewNode = CurDAG->getMachineNode (
143
+ Subtarget->has2E3 () ? CSKY::SUBC32 : CSKY::SUBC16, Dl, {Type0, Type1},
144
+ {Op0, Op1, SDValue (CA, 0 )});
145
+ } else {
146
+ auto CarryIn = InvertCarryFlag (Subtarget, CurDAG, Dl, Op2);
147
+ NewNode = CurDAG->getMachineNode (Subtarget->has2E3 () ? CSKY::SUBC32
148
+ : CSKY::SUBC16,
149
+ Dl, {Type0, Type1}, {Op0, Op1, CarryIn});
150
+ }
151
+ auto CarryOut = InvertCarryFlag (Subtarget, CurDAG, Dl, SDValue (NewNode, 1 ));
152
+
153
+ ReplaceUses (SDValue (N, 0 ), SDValue (NewNode, 0 ));
154
+ ReplaceUses (SDValue (N, 1 ), CarryOut);
155
+ CurDAG->RemoveDeadNode (N);
156
+
157
+ return true ;
158
+ }
159
+
73
160
FunctionPass *llvm::createCSKYISelDag (CSKYTargetMachine &TM) {
74
161
return new CSKYDAGToDAGISel (TM);
75
162
}
0 commit comments