|
23 | 23 | #include "llvm/ADT/SmallBitVector.h"
|
24 | 24 | #include "llvm/Analysis/MemoryLocation.h"
|
25 | 25 | #include "llvm/Analysis/VectorUtils.h"
|
| 26 | +#include "llvm/CodeGen/ISDOpcodes.h" |
26 | 27 | #include "llvm/IR/DataLayout.h"
|
27 | 28 | #include "llvm/Support/ErrorHandling.h"
|
28 | 29 | #include "llvm/Support/TypeSize.h"
|
@@ -116,6 +117,9 @@ void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) {
|
116 | 117 | case ISD::FCANONICALIZE:
|
117 | 118 | R = ScalarizeVecRes_UnaryOp(N);
|
118 | 119 | break;
|
| 120 | + case ISD::ADDRSPACECAST: |
| 121 | + R = ScalarizeVecRes_ADDRSPACECAST(N); |
| 122 | + break; |
119 | 123 | case ISD::FFREXP:
|
120 | 124 | R = ScalarizeVecRes_FFREXP(N, ResNo);
|
121 | 125 | break;
|
@@ -475,6 +479,31 @@ SDValue DAGTypeLegalizer::ScalarizeVecRes_VecInregOp(SDNode *N) {
|
475 | 479 | llvm_unreachable("Illegal extend_vector_inreg opcode");
|
476 | 480 | }
|
477 | 481 |
|
| 482 | +SDValue DAGTypeLegalizer::ScalarizeVecRes_ADDRSPACECAST(SDNode *N) { |
| 483 | + EVT DestVT = N->getValueType(0).getVectorElementType(); |
| 484 | + SDValue Op = N->getOperand(0); |
| 485 | + EVT OpVT = Op.getValueType(); |
| 486 | + SDLoc DL(N); |
| 487 | + // The result needs scalarizing, but it's not a given that the source does. |
| 488 | + // This is a workaround for targets where it's impossible to scalarize the |
| 489 | + // result of a conversion, because the source type is legal. |
| 490 | + // For instance, this happens on AArch64: v1i1 is illegal but v1i{8,16,32} |
| 491 | + // are widened to v8i8, v4i16, and v2i32, which is legal, because v1i64 is |
| 492 | + // legal and was not scalarized. |
| 493 | + // See the similar logic in ScalarizeVecRes_SETCC |
| 494 | + if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) { |
| 495 | + Op = GetScalarizedVector(Op); |
| 496 | + } else { |
| 497 | + EVT VT = OpVT.getVectorElementType(); |
| 498 | + Op = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, Op, |
| 499 | + DAG.getVectorIdxConstant(0, DL)); |
| 500 | + } |
| 501 | + auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N); |
| 502 | + unsigned SrcAS = AddrSpaceCastN->getSrcAddressSpace(); |
| 503 | + unsigned DestAS = AddrSpaceCastN->getDestAddressSpace(); |
| 504 | + return DAG.getAddrSpaceCast(DL, DestVT, Op, SrcAS, DestAS); |
| 505 | +} |
| 506 | + |
478 | 507 | SDValue DAGTypeLegalizer::ScalarizeVecRes_SCALAR_TO_VECTOR(SDNode *N) {
|
479 | 508 | // If the operand is wider than the vector element type then it is implicitly
|
480 | 509 | // truncated. Make that explicit here.
|
@@ -1122,6 +1151,9 @@ void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) {
|
1122 | 1151 | case ISD::FCANONICALIZE:
|
1123 | 1152 | SplitVecRes_UnaryOp(N, Lo, Hi);
|
1124 | 1153 | break;
|
| 1154 | + case ISD::ADDRSPACECAST: |
| 1155 | + SplitVecRes_ADDRSPACECAST(N, Lo, Hi); |
| 1156 | + break; |
1125 | 1157 | case ISD::FFREXP:
|
1126 | 1158 | SplitVecRes_FFREXP(N, ResNo, Lo, Hi);
|
1127 | 1159 | break;
|
@@ -2353,6 +2385,26 @@ void DAGTypeLegalizer::SplitVecRes_UnaryOp(SDNode *N, SDValue &Lo,
|
2353 | 2385 | Hi = DAG.getNode(Opcode, dl, HiVT, {Hi, MaskHi, EVLHi}, Flags);
|
2354 | 2386 | }
|
2355 | 2387 |
|
| 2388 | +void DAGTypeLegalizer::SplitVecRes_ADDRSPACECAST(SDNode *N, SDValue &Lo, |
| 2389 | + SDValue &Hi) { |
| 2390 | + SDLoc dl(N); |
| 2391 | + auto [LoVT, HiVT] = DAG.GetSplitDestVTs(N->getValueType(0)); |
| 2392 | + |
| 2393 | + // If the input also splits, handle it directly for a compile time speedup. |
| 2394 | + // Otherwise split it by hand. |
| 2395 | + EVT InVT = N->getOperand(0).getValueType(); |
| 2396 | + if (getTypeAction(InVT) == TargetLowering::TypeSplitVector) |
| 2397 | + GetSplitVector(N->getOperand(0), Lo, Hi); |
| 2398 | + else |
| 2399 | + std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, 0); |
| 2400 | + |
| 2401 | + auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N); |
| 2402 | + unsigned SrcAS = AddrSpaceCastN->getSrcAddressSpace(); |
| 2403 | + unsigned DestAS = AddrSpaceCastN->getDestAddressSpace(); |
| 2404 | + Lo = DAG.getAddrSpaceCast(dl, LoVT, Lo, SrcAS, DestAS); |
| 2405 | + Hi = DAG.getAddrSpaceCast(dl, HiVT, Hi, SrcAS, DestAS); |
| 2406 | +} |
| 2407 | + |
2356 | 2408 | void DAGTypeLegalizer::SplitVecRes_FFREXP(SDNode *N, unsigned ResNo,
|
2357 | 2409 | SDValue &Lo, SDValue &Hi) {
|
2358 | 2410 | SDLoc dl(N);
|
@@ -4121,6 +4173,9 @@ void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
|
4121 | 4173 | report_fatal_error("Do not know how to widen the result of this operator!");
|
4122 | 4174 |
|
4123 | 4175 | case ISD::MERGE_VALUES: Res = WidenVecRes_MERGE_VALUES(N, ResNo); break;
|
| 4176 | + case ISD::ADDRSPACECAST: |
| 4177 | + Res = WidenVecRes_ADDRSPACECAST(N); |
| 4178 | + break; |
4124 | 4179 | case ISD::AssertZext: Res = WidenVecRes_AssertZext(N); break;
|
4125 | 4180 | case ISD::BITCAST: Res = WidenVecRes_BITCAST(N); break;
|
4126 | 4181 | case ISD::BUILD_VECTOR: Res = WidenVecRes_BUILD_VECTOR(N); break;
|
@@ -5086,6 +5141,16 @@ SDValue DAGTypeLegalizer::WidenVecRes_MERGE_VALUES(SDNode *N, unsigned ResNo) {
|
5086 | 5141 | return GetWidenedVector(WidenVec);
|
5087 | 5142 | }
|
5088 | 5143 |
|
| 5144 | +SDValue DAGTypeLegalizer::WidenVecRes_ADDRSPACECAST(SDNode *N) { |
| 5145 | + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); |
| 5146 | + SDValue InOp = GetWidenedVector(N->getOperand(0)); |
| 5147 | + auto *AddrSpaceCastN = cast<AddrSpaceCastSDNode>(N); |
| 5148 | + |
| 5149 | + return DAG.getAddrSpaceCast(SDLoc(N), WidenVT, InOp, |
| 5150 | + AddrSpaceCastN->getSrcAddressSpace(), |
| 5151 | + AddrSpaceCastN->getDestAddressSpace()); |
| 5152 | +} |
| 5153 | + |
5089 | 5154 | SDValue DAGTypeLegalizer::WidenVecRes_BITCAST(SDNode *N) {
|
5090 | 5155 | SDValue InOp = N->getOperand(0);
|
5091 | 5156 | EVT InVT = InOp.getValueType();
|
|
0 commit comments