|
24 | 24 | #include "llvm/IR/DerivedTypes.h"
|
25 | 25 | #include "llvm/IR/Type.h"
|
26 | 26 | #include <initializer_list>
|
| 27 | +#include "llvm/Support/MathExtras.h" |
27 | 28 |
|
28 | 29 | #define DEBUG_TYPE "aarch64-legalinfo"
|
29 | 30 |
|
@@ -373,7 +374,8 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
|
373 | 374 | .minScalarOrEltIf(
|
374 | 375 | [=](const LegalityQuery &Query) { return Query.Types[1] == v2p0; }, 0,
|
375 | 376 | s64)
|
376 |
| - .widenScalarOrEltToNextPow2(1); |
| 377 | + .widenScalarOrEltToNextPow2(1) |
| 378 | + .clampNumElements(0, v2s32, v4s32); |
377 | 379 |
|
378 | 380 | getActionDefinitionsBuilder(G_FCMP)
|
379 | 381 | .legalFor({{s32, s32}, {s32, s64}})
|
@@ -412,7 +414,16 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
|
412 | 414 | .legalIf(ExtLegalFunc)
|
413 | 415 | .clampScalar(0, s64, s64); // Just for s128, others are handled above.
|
414 | 416 |
|
415 |
| - getActionDefinitionsBuilder(G_TRUNC).alwaysLegal(); |
| 417 | + getActionDefinitionsBuilder(G_TRUNC) |
| 418 | + .minScalarOrEltIf( |
| 419 | + [=](const LegalityQuery &Query) { return Query.Types[0].isVector(); }, |
| 420 | + 0, s8) |
| 421 | + .customIf([=](const LegalityQuery &Query) { |
| 422 | + LLT DstTy = Query.Types[0]; |
| 423 | + LLT SrcTy = Query.Types[1]; |
| 424 | + return DstTy == v8s8 && SrcTy.getSizeInBits() > 128; |
| 425 | + }) |
| 426 | + .alwaysLegal(); |
416 | 427 |
|
417 | 428 | getActionDefinitionsBuilder(G_SEXT_INREG).legalFor({s32, s64}).lower();
|
418 | 429 |
|
@@ -709,11 +720,60 @@ bool AArch64LegalizerInfo::legalizeCustom(LegalizerHelper &Helper,
|
709 | 720 | return legalizeShlAshrLshr(MI, MRI, MIRBuilder, Observer);
|
710 | 721 | case TargetOpcode::G_GLOBAL_VALUE:
|
711 | 722 | return legalizeSmallCMGlobalValue(MI, MRI, MIRBuilder, Observer);
|
| 723 | + case TargetOpcode::G_TRUNC: |
| 724 | + return legalizeVectorTrunc(MI, Helper); |
712 | 725 | }
|
713 | 726 |
|
714 | 727 | llvm_unreachable("expected switch to return");
|
715 | 728 | }
|
716 | 729 |
|
| 730 | +static void extractParts(Register Reg, MachineRegisterInfo &MRI, |
| 731 | + MachineIRBuilder &MIRBuilder, LLT Ty, int NumParts, |
| 732 | + SmallVectorImpl<Register> &VRegs) { |
| 733 | + for (int I = 0; I < NumParts; ++I) |
| 734 | + VRegs.push_back(MRI.createGenericVirtualRegister(Ty)); |
| 735 | + MIRBuilder.buildUnmerge(VRegs, Reg); |
| 736 | +} |
| 737 | + |
| 738 | +bool AArch64LegalizerInfo::legalizeVectorTrunc( |
| 739 | + MachineInstr &MI, LegalizerHelper &Helper) const { |
| 740 | + MachineIRBuilder &MIRBuilder = Helper.MIRBuilder; |
| 741 | + MachineRegisterInfo &MRI = *MIRBuilder.getMRI(); |
| 742 | + // Similar to how operand splitting is done in SelectiondDAG, we can handle |
| 743 | + // %res(v8s8) = G_TRUNC %in(v8s32) by generating: |
| 744 | + // %inlo(<4x s32>), %inhi(<4 x s32>) = G_UNMERGE %in(<8 x s32>) |
| 745 | + // %lo16(<4 x s16>) = G_TRUNC %inlo |
| 746 | + // %hi16(<4 x s16>) = G_TRUNC %inhi |
| 747 | + // %in16(<8 x s16>) = G_CONCAT_VECTORS %lo16, %hi16 |
| 748 | + // %res(<8 x s8>) = G_TRUNC %in16 |
| 749 | + |
| 750 | + Register DstReg = MI.getOperand(0).getReg(); |
| 751 | + Register SrcReg = MI.getOperand(1).getReg(); |
| 752 | + LLT DstTy = MRI.getType(DstReg); |
| 753 | + LLT SrcTy = MRI.getType(SrcReg); |
| 754 | + assert(isPowerOf2_32(DstTy.getSizeInBits()) && |
| 755 | + isPowerOf2_32(SrcTy.getSizeInBits())); |
| 756 | + |
| 757 | + // Split input type. |
| 758 | + LLT SplitSrcTy = SrcTy.changeNumElements(SrcTy.getNumElements() / 2); |
| 759 | + // First, split the source into two smaller vectors. |
| 760 | + SmallVector<Register, 2> SplitSrcs; |
| 761 | + extractParts(SrcReg, MRI, MIRBuilder, SplitSrcTy, 2, SplitSrcs); |
| 762 | + |
| 763 | + // Truncate the splits into intermediate narrower elements. |
| 764 | + LLT InterTy = SplitSrcTy.changeElementSize(DstTy.getScalarSizeInBits() * 2); |
| 765 | + for (unsigned I = 0; I < SplitSrcs.size(); ++I) |
| 766 | + SplitSrcs[I] = MIRBuilder.buildTrunc(InterTy, SplitSrcs[I]).getReg(0); |
| 767 | + |
| 768 | + auto Concat = MIRBuilder.buildConcatVectors( |
| 769 | + DstTy.changeElementSize(DstTy.getScalarSizeInBits() * 2), SplitSrcs); |
| 770 | + |
| 771 | + Helper.Observer.changingInstr(MI); |
| 772 | + MI.getOperand(1).setReg(Concat.getReg(0)); |
| 773 | + Helper.Observer.changedInstr(MI); |
| 774 | + return true; |
| 775 | +} |
| 776 | + |
717 | 777 | bool AArch64LegalizerInfo::legalizeSmallCMGlobalValue(
|
718 | 778 | MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &MIRBuilder,
|
719 | 779 | GISelChangeObserver &Observer) const {
|
|
0 commit comments