|
15 | 15 | #include "MCTargetDesc/LoongArchMCTargetDesc.h" |
16 | 16 | #include "MCTargetDesc/LoongArchMatInt.h" |
17 | 17 | #include "llvm/Support/KnownBits.h" |
| 18 | +#include "llvm/Support/raw_ostream.h" |
18 | 19 |
|
19 | 20 | using namespace llvm; |
20 | 21 |
|
@@ -75,7 +76,14 @@ void LoongArchDAGToDAGISel::Select(SDNode *Node) { |
75 | 76 | ReplaceNode(Node, CurDAG->getMachineNode(ADDIOp, DL, VT, TFI, Imm)); |
76 | 77 | return; |
77 | 78 | } |
78 | | - // TODO: Add selection nodes needed later. |
| 79 | + case ISD::BITCAST: { |
| 80 | + if (VT.is128BitVector() || VT.is512BitVector()) { |
| 81 | + ReplaceUses(SDValue(Node, 0), Node->getOperand(0)); |
| 82 | + CurDAG->RemoveDeadNode(Node); |
| 83 | + return; |
| 84 | + } |
| 85 | + break; |
| 86 | + } |
79 | 87 | } |
80 | 88 |
|
81 | 89 | // Select the default instruction. |
@@ -262,6 +270,96 @@ bool LoongArchDAGToDAGISel::selectZExti32(SDValue N, SDValue &Val) { |
262 | 270 | return false; |
263 | 271 | } |
264 | 272 |
|
| 273 | +bool LoongArchDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm, |
| 274 | + unsigned MinSizeInBits) const { |
| 275 | + if (!Subtarget->hasExtLSX()) |
| 276 | + return false; |
| 277 | + |
| 278 | + BuildVectorSDNode *Node = dyn_cast<BuildVectorSDNode>(N); |
| 279 | + |
| 280 | + if (!Node) |
| 281 | + return false; |
| 282 | + |
| 283 | + APInt SplatValue, SplatUndef; |
| 284 | + unsigned SplatBitSize; |
| 285 | + bool HasAnyUndefs; |
| 286 | + |
| 287 | + if (!Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs, |
| 288 | + MinSizeInBits, /*IsBigEndian=*/false)) |
| 289 | + return false; |
| 290 | + |
| 291 | + Imm = SplatValue; |
| 292 | + |
| 293 | + return true; |
| 294 | +} |
| 295 | + |
| 296 | +template <unsigned ImmBitSize, bool IsSigned> |
| 297 | +bool LoongArchDAGToDAGISel::selectVSplatImm(SDValue N, SDValue &SplatVal) { |
| 298 | + APInt ImmValue; |
| 299 | + EVT EltTy = N->getValueType(0).getVectorElementType(); |
| 300 | + |
| 301 | + if (N->getOpcode() == ISD::BITCAST) |
| 302 | + N = N->getOperand(0); |
| 303 | + |
| 304 | + if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && |
| 305 | + ImmValue.getBitWidth() == EltTy.getSizeInBits()) { |
| 306 | + if (IsSigned && ImmValue.isSignedIntN(ImmBitSize)) { |
| 307 | + SplatVal = CurDAG->getTargetConstant(ImmValue.getSExtValue(), SDLoc(N), |
| 308 | + Subtarget->getGRLenVT()); |
| 309 | + return true; |
| 310 | + } |
| 311 | + if (!IsSigned && ImmValue.isIntN(ImmBitSize)) { |
| 312 | + SplatVal = CurDAG->getTargetConstant(ImmValue.getZExtValue(), SDLoc(N), |
| 313 | + Subtarget->getGRLenVT()); |
| 314 | + return true; |
| 315 | + } |
| 316 | + } |
| 317 | + |
| 318 | + return false; |
| 319 | +} |
| 320 | + |
| 321 | +bool LoongArchDAGToDAGISel::selectVSplatUimmInvPow2(SDValue N, |
| 322 | + SDValue &SplatImm) const { |
| 323 | + APInt ImmValue; |
| 324 | + EVT EltTy = N->getValueType(0).getVectorElementType(); |
| 325 | + |
| 326 | + if (N->getOpcode() == ISD::BITCAST) |
| 327 | + N = N->getOperand(0); |
| 328 | + |
| 329 | + if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && |
| 330 | + ImmValue.getBitWidth() == EltTy.getSizeInBits()) { |
| 331 | + int32_t Log2 = (~ImmValue).exactLogBase2(); |
| 332 | + |
| 333 | + if (Log2 != -1) { |
| 334 | + SplatImm = CurDAG->getTargetConstant(Log2, SDLoc(N), EltTy); |
| 335 | + return true; |
| 336 | + } |
| 337 | + } |
| 338 | + |
| 339 | + return false; |
| 340 | +} |
| 341 | + |
| 342 | +bool LoongArchDAGToDAGISel::selectVSplatUimmPow2(SDValue N, |
| 343 | + SDValue &SplatImm) const { |
| 344 | + APInt ImmValue; |
| 345 | + EVT EltTy = N->getValueType(0).getVectorElementType(); |
| 346 | + |
| 347 | + if (N->getOpcode() == ISD::BITCAST) |
| 348 | + N = N->getOperand(0); |
| 349 | + |
| 350 | + if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && |
| 351 | + ImmValue.getBitWidth() == EltTy.getSizeInBits()) { |
| 352 | + int32_t Log2 = ImmValue.exactLogBase2(); |
| 353 | + |
| 354 | + if (Log2 != -1) { |
| 355 | + SplatImm = CurDAG->getTargetConstant(Log2, SDLoc(N), EltTy); |
| 356 | + return true; |
| 357 | + } |
| 358 | + } |
| 359 | + |
| 360 | + return false; |
| 361 | +} |
| 362 | + |
265 | 363 | // This pass converts a legalized DAG into a LoongArch-specific DAG, ready |
266 | 364 | // for instruction scheduling. |
267 | 365 | FunctionPass *llvm::createLoongArchISelDag(LoongArchTargetMachine &TM) { |
|
0 commit comments