llvm.org GIT mirror llvm / b6c1f00
[AVX512][inline-asm] Fix AVX512 inline assembly instruction resolution when the size qualifier of a memory operand is not specified explicitly. This commit handles cases where the size qualifier of an indirect memory reference operand in Intel syntax is missing (e.g. "vaddps xmm1, xmm2, [a]"). GCC will deduce the size qualifier for AVX512 vector and broadcast memory operands based on the possible matches: "vaddps xmm1, xmm2, [a]" matches only “XMMWORD PTR” qualifier. "vaddps xmm1, xmm2, [a]{1to4}" matches only “DWORD PTR” qualifier. This is different from the current behavior of LLVM, which deduces the size qualifier based on the size of the memory operand. For "vaddps xmm1, xmm2, [a]" "char a;" will imply "BYTE PTR" qualifier "short a;" will imply "WORD PTR" qualifier. This commit aligns LLVM to GCC’s behavior. This is the LLVM part of the review. The Clang part of the review: https://reviews.llvm.org/D26587 Differential Revision: https://reviews.llvm.org/D26586 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@287630 91177308-0d34-0410-b5e6-96231b3b80d8 Coby Tayree 4 years ago
1 changed file(s) with 58 addition(s) and 3 deletion(s). Raw diff Collapse all Expand all
721721 CreateMemForInlineAsm(unsigned SegReg, const MCExpr *Disp, unsigned BaseReg,
722722 unsigned IndexReg, unsigned Scale, SMLoc Start,
723723 SMLoc End, unsigned Size, StringRef Identifier,
724 InlineAsmIdentifierInfo &Info);
724 InlineAsmIdentifierInfo &Info,
725 bool AllowBetterSizeMatch = false);
725726
726727 bool parseDirectiveEven(SMLoc L);
727728 bool ParseDirectiveWord(unsigned Size, SMLoc L);
763764 const MCParsedAsmOperand &Op);
764765
765766 bool ParseZ(std::unique_ptr &Z, const SMLoc &StartLoc);
767
768 /// MS-compatibility:
769 /// Obtain an appropriate size qualifier, when facing its absence,
770 /// upon AVX512 vector/broadcast memory operand
771 unsigned AdjustAVX512Mem(unsigned Size, X86Operand* UnsizedMemOpNext);
766772
767773 bool is64BitMode() const {
768774 // FIXME: Can tablegen auto-generate this?
11711177 std::unique_ptr X86AsmParser::CreateMemForInlineAsm(
11721178 unsigned SegReg, const MCExpr *Disp, unsigned BaseReg, unsigned IndexReg,
11731179 unsigned Scale, SMLoc Start, SMLoc End, unsigned Size, StringRef Identifier,
1174 InlineAsmIdentifierInfo &Info) {
1180 InlineAsmIdentifierInfo &Info, bool AllowBetterSizeMatch) {
11751181 // If we found a decl other than a VarDecl, then assume it is a FuncDecl or
11761182 // some other label reference.
11771183 if (isa(Disp) && Info.OpDecl && !Info.IsVarDecl) {
12001206 if (Size)
12011207 InstInfo->AsmRewrites->emplace_back(AOK_SizeDirective, Start,
12021208 /*Len=*/0, Size);
1209 if (AllowBetterSizeMatch)
1210 // Handle cases where size qualifier is absent, upon an indirect symbol
1211 // reference - e.g. "vaddps zmm1, zmm2, [var]"
1212 // set Size to zero to allow matching mechansim to try and find a better
1213 // size qualifier than our initial guess, based on available variants of
1214 // the given instruction
1215 Size = 0;
12031216 }
12041217 }
12051218
14861499
14871500 InlineAsmIdentifierInfo &Info = SM.getIdentifierInfo();
14881501 return CreateMemForInlineAsm(SegReg, Disp, BaseReg, IndexReg, Scale, Start,
1489 End, Size, SM.getSymName(), Info);
1502 End, Size, SM.getSymName(), Info,
1503 isParsingInlineAsm());
14901504 }
14911505
14921506 // Inline assembly may use variable names with namespace alias qualifiers.
28272841 return true;
28282842 }
28292843
2844 unsigned X86AsmParser::AdjustAVX512Mem(unsigned Size,
2845 X86Operand* UnsizedMemOpNext) {
2846 // Check for the existence of an AVX512 platform
2847 if (!getSTI().getFeatureBits()[X86::FeatureAVX512])
2848 return 0;
2849 // Allow adjusting upon a (x|y|z)mm
2850 if (Size == 512 || Size == 256 || Size == 128)
2851 return Size;
2852 // This is an allegadly broadcasting mem op adjustment,
2853 // allow some more inquiring to validate it
2854 if (Size == 64 || Size == 32)
2855 return UnsizedMemOpNext && UnsizedMemOpNext->isToken() &&
2856 UnsizedMemOpNext->getToken().substr(0, 4).equals("{1to") ? Size : 0;
2857 // Do not allow any other type of adjustments
2858 return 0;
2859 }
2860
28302861 bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode,
28312862 OperandVector &Operands,
28322863 MCStreamer &Out,
28462877
28472878 // Find one unsized memory operand, if present.
28482879 X86Operand *UnsizedMemOp = nullptr;
2880 // If unsized memory operand was found - obtain following operand.
2881 // For use in AdjustAVX512Mem
2882 X86Operand *UnsizedMemOpNext = nullptr;
28492883 for (const auto &Op : Operands) {
28502884 X86Operand *X86Op = static_cast(Op.get());
2885 if (UnsizedMemOp) {
2886 UnsizedMemOpNext = X86Op;
2887 // Have we found an unqualified memory operand,
2888 // break. IA allows only one memory operand.
2889 break;
2890 }
28512891 if (X86Op->isMemUnsized())
28522892 UnsizedMemOp = X86Op;
28532893 }
28952935 // If an unsized memory operand is present, try to match with each memory
28962936 // operand size. In Intel assembly, the size is not part of the instruction
28972937 // mnemonic.
2938 unsigned MatchedSize = 0;
28982939 if (UnsizedMemOp && UnsizedMemOp->isMemUnsized()) {
28992940 static const unsigned MopSizes[] = {8, 16, 32, 64, 80, 128, 256, 512};
29002941 for (unsigned Size : MopSizes) {
29092950 // If this returned as a missing feature failure, remember that.
29102951 if (Match.back() == Match_MissingFeature)
29112952 ErrorInfoMissingFeature = ErrorInfoIgnore;
2953 if (M == Match_Success)
2954 // MS-compatability:
2955 // Adjust AVX512 vector/broadcast memory operand,
2956 // when facing the absence of a size qualifier.
2957 // Match GCC behavior on respective cases.
2958 MatchedSize = AdjustAVX512Mem(Size, UnsizedMemOpNext);
29122959 }
29132960
29142961 // Restore the size of the unsized memory operand if we modified it.
29432990 unsigned NumSuccessfulMatches =
29442991 std::count(std::begin(Match), std::end(Match), Match_Success);
29452992 if (NumSuccessfulMatches == 1) {
2993 if (MatchedSize && isParsingInlineAsm() && isParsingIntelSyntax())
2994 // MS compatibility -
2995 // Fix the rewrite according to the matched memory size
2996 // MS inline assembly only
2997 for (AsmRewrite &AR : *InstInfo->AsmRewrites)
2998 if ((AR.Loc.getPointer() == UnsizedMemOp->StartLoc.getPointer()) &&
2999 (AR.Kind == AOK_SizeDirective))
3000 AR.Val = MatchedSize;
29463001 // Some instructions need post-processing to, for example, tweak which
29473002 // encoding is selected. Loop on it while changes happen so the individual
29483003 // transformations can chain off each other.