llvm.org GIT mirror llvm / 101a361
ARM ISel: Don't create illegal types during LowerMUL The transformation happening here is that we want to turn a "mul(ext(X), ext(X))" into a "vmull(X, X)", stripping off the extension. We have to make sure that X still has a valid vector type - possibly recreate an extension to a smaller type. In case of a extload of a memory type smaller than 64 bit we used create a ext(load()). The problem with doing this - instead of recreating an extload - is that an illegal type is exposed. This patch fixes this by creating extloads instead of ext(load()) sequences. Fixes PR15970. radar://13871383 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181842 91177308-0d34-0410-b5e6-96231b3b80d8 Arnold Schwaighofer 7 years ago
2 changed file(s) with 56 addition(s) and 25 deletion(s). Raw diff Collapse all Expand all
52565256 return false;
52575257 }
52585258
5259 static EVT getExtensionTo64Bits(const EVT &OrigVT) {
5260 if (OrigVT.getSizeInBits() >= 64)
5261 return OrigVT;
5262
5263 assert(OrigVT.isSimple() && "Expecting a simple value type");
5264
5265 MVT::SimpleValueType OrigSimpleTy = OrigVT.getSimpleVT().SimpleTy;
5266 switch (OrigSimpleTy) {
5267 default: llvm_unreachable("Unexpected Vector Type");
5268 case MVT::v2i8:
5269 case MVT::v2i16:
5270 return MVT::v2i32;
5271 case MVT::v4i8:
5272 return MVT::v4i16;
5273 }
5274 }
5275
52595276 /// AddRequiredExtensionForVMULL - Add a sign/zero extension to extend the total
52605277 /// value size to 64 bits. We need a 64-bit D register as an operand to VMULL.
52615278 /// We insert the required extension here to get the vector to fill a D register.
52715288 return N;
52725289
52735290 // Must extend size to at least 64 bits to be used as an operand for VMULL.
5274 MVT::SimpleValueType OrigSimpleTy = OrigTy.getSimpleVT().SimpleTy;
5275 EVT NewVT;
5276 switch (OrigSimpleTy) {
5277 default: llvm_unreachable("Unexpected Orig Vector Type");
5278 case MVT::v2i8:
5279 case MVT::v2i16:
5280 NewVT = MVT::v2i32;
5281 break;
5282 case MVT::v4i8:
5283 NewVT = MVT::v4i16;
5284 break;
5285 }
5291 EVT NewVT = getExtensionTo64Bits(OrigTy);
5292
52865293 return DAG.getNode(ExtOpcode, N->getDebugLoc(), NewVT, N);
52875294 }
52885295
52925299 /// reach a total size of 64 bits. We have to add the extension separately
52935300 /// because ARM does not have a sign/zero extending load for vectors.
52945301 static SDValue SkipLoadExtensionForVMULL(LoadSDNode *LD, SelectionDAG& DAG) {
5295 SDValue NonExtendingLoad =
5296 DAG.getLoad(LD->getMemoryVT(), LD->getDebugLoc(), LD->getChain(),
5302 EVT ExtendedTy = getExtensionTo64Bits(LD->getMemoryVT());
5303
5304 // The load already has the right type.
5305 if (ExtendedTy == LD->getMemoryVT())
5306 return DAG.getLoad(LD->getMemoryVT(), LD->getDebugLoc(), LD->getChain(),
52975307 LD->getBasePtr(), LD->getPointerInfo(), LD->isVolatile(),
52985308 LD->isNonTemporal(), LD->isInvariant(),
52995309 LD->getAlignment());
5300 unsigned ExtOp = 0;
5301 switch (LD->getExtensionType()) {
5302 default: llvm_unreachable("Unexpected LoadExtType");
5303 case ISD::EXTLOAD:
5304 case ISD::SEXTLOAD: ExtOp = ISD::SIGN_EXTEND; break;
5305 case ISD::ZEXTLOAD: ExtOp = ISD::ZERO_EXTEND; break;
5306 }
5307 MVT::SimpleValueType MemType = LD->getMemoryVT().getSimpleVT().SimpleTy;
5308 MVT::SimpleValueType ExtType = LD->getValueType(0).getSimpleVT().SimpleTy;
5309 return AddRequiredExtensionForVMULL(NonExtendingLoad, DAG,
5310 MemType, ExtType, ExtOp);
5310
5311 // We need to create a zextload/sextload. We cannot just create a load
5312 // followed by a zext/zext node because LowerMUL is also run during normal
5313 // operation legalization where we can't create illegal types.
5314 return DAG.getExtLoad(LD->getExtensionType(), LD->getDebugLoc(), ExtendedTy,
5315 LD->getChain(), LD->getBasePtr(), LD->getPointerInfo(),
5316 LD->getMemoryVT(), LD->isVolatile(),
5317 LD->isNonTemporal(), LD->getAlignment());
53115318 }
53125319
53135320 /// SkipExtensionForVMULL - For a node that is a SIGN_EXTEND, ZERO_EXTEND,
598598 declare <8 x i16> @llvm.arm.neon.vrshiftu.v8i16(<8 x i16>, <8 x i16>) nounwind readnone
599599 declare <8 x i16> @llvm.arm.neon.vqsubu.v8i16(<8 x i16>, <8 x i16>) nounwind readnone
600600 declare <8 x i8> @llvm.arm.neon.vqmovnu.v8i8(<8 x i16>) nounwind readnone
601
602 ; vmull lowering would create a zext(v4i8 load()) instead of a zextload(v4i8),
603 ; creating an illegal type during legalization and causing an assert.
604 ; PR15970
605 define void @no_illegal_types_vmull_sext(<4 x i32> %a) {
606 entry:
607 %wide.load283.i = load <4 x i8>* undef, align 1
608 %0 = sext <4 x i8> %wide.load283.i to <4 x i32>
609 %1 = sub nsw <4 x i32> %0, %a
610 %2 = mul nsw <4 x i32> %1, %1
611 %predphi290.v.i = select <4 x i1> undef, <4 x i32> undef, <4 x i32> %2
612 store <4 x i32> %predphi290.v.i, <4 x i32>* undef, align 4
613 ret void
614 }
615 define void @no_illegal_types_vmull_zext(<4 x i32> %a) {
616 entry:
617 %wide.load283.i = load <4 x i8>* undef, align 1
618 %0 = zext <4 x i8> %wide.load283.i to <4 x i32>
619 %1 = sub nsw <4 x i32> %0, %a
620 %2 = mul nsw <4 x i32> %1, %1
621 %predphi290.v.i = select <4 x i1> undef, <4 x i32> undef, <4 x i32> %2
622 store <4 x i32> %predphi290.v.i, <4 x i32>* undef, align 4
623 ret void
624 }