llvm.org GIT mirror llvm / d5f902e
[x86][inline-asm][avx512] allow swapping of '{k<num>}' & '{z}' marks Committing on behalf of Coby Tayree: After check-all and LGTM Desc: AVX512 allows dest operand to be followed by an op-mask register specifier ('{k<num>}', which in turn may be followed by a merging/zeroing specifier ('{z}') Currently, the following forms are allowed: {k<num>} {k<num>}{z} This patch allows the following forms: {z}{k<num>} and ignores the next form: {z} Justification would be quite simple - GCC Differential Revision: http://reviews.llvm.org/D25013 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@284479 91177308-0d34-0410-b5e6-96231b3b80d8 Michael Zuckerman 4 years ago
3 changed file(s) with 73 addition(s) and 25 deletion(s). Raw diff Collapse all Expand all
758758
759759 /// Parses AVX512 specific operand primitives: masked registers ({%k}, {z})
760760 /// and memory broadcasting ({1to}) primitives, updating Operands vector if required.
761 /// \return \c true if no parsing errors occurred, \c false otherwise.
761 /// return false if no parsing errors occurred, true otherwise.
762762 bool HandleAVX512Operand(OperandVector &Operands,
763763 const MCParsedAsmOperand &Op);
764
765 bool ParseZ(std::unique_ptr &Z, const SMLoc &StartLoc);
764766
765767 bool is64BitMode() const {
766768 // FIXME: Can tablegen auto-generate this?
19061908 }
19071909 }
19081910
1911 // true on failure, false otherwise
1912 // If no {z} mark was found - Parser doesn't advance
1913 bool X86AsmParser::ParseZ(std::unique_ptr &Z,
1914 const SMLoc &StartLoc) {
1915 MCAsmParser &Parser = getParser();
1916 // Assuming we are just pass the '{' mark, quering the next token
1917 // Searched for {z}, but none was found. Return true, as no parsing error was
1918 // encountered
1919 if (!(getLexer().is(AsmToken::Identifier) &&
1920 (getLexer().getTok().getIdentifier() == "z")))
1921 return false;
1922 Parser.Lex(); // Eat z
1923 // Query and eat the '}' mark
1924 if (!getLexer().is(AsmToken::RCurly))
1925 return Error(getLexer().getLoc(), "Expected } at this point");
1926 Parser.Lex(); // Eat '}'
1927 // Assign Z with the {z} mark opernad
1928 Z.reset(X86Operand::CreateToken("{z}", StartLoc).release());
1929 return false;
1930 }
1931
1932 // true on failure, false otherwise
19091933 bool X86AsmParser::HandleAVX512Operand(OperandVector &Operands,
19101934 const MCParsedAsmOperand &Op) {
19111935 MCAsmParser &Parser = getParser();
19171941 if(getLexer().is(AsmToken::Integer)) {
19181942 // Parse memory broadcasting ({1to}).
19191943 if (getLexer().getTok().getIntVal() != 1)
1920 return !TokError("Expected 1to at this point");
1944 return TokError("Expected 1to at this point");
19211945 Parser.Lex(); // Eat "1" of 1to8
19221946 if (!getLexer().is(AsmToken::Identifier) ||
19231947 !getLexer().getTok().getIdentifier().startswith("to"))
1924 return !TokError("Expected 1to at this point");
1948 return TokError("Expected 1to at this point");
19251949 // Recognize only reasonable suffixes.
19261950 const char *BroadcastPrimitive =
19271951 StringSwitch(getLexer().getTok().getIdentifier())
19311955 .Case("to16", "{1to16}")
19321956 .Default(nullptr);
19331957 if (!BroadcastPrimitive)
1934 return !TokError("Invalid memory broadcast primitive.");
1958 return TokError("Invalid memory broadcast primitive.");
19351959 Parser.Lex(); // Eat "toN" of 1toN
19361960 if (!getLexer().is(AsmToken::RCurly))
1937 return !TokError("Expected } at this point");
1961 return TokError("Expected } at this point");
19381962 Parser.Lex(); // Eat "}"
19391963 Operands.push_back(X86Operand::CreateToken(BroadcastPrimitive,
19401964 consumedToken));
19411965 // No AVX512 specific primitives can pass
19421966 // after memory broadcasting, so return.
1943 return true;
1967 return false;
19441968 } else {
1945 // Parse mask register {%k1}
1946 Operands.push_back(X86Operand::CreateToken("{", consumedToken));
1947 if (std::unique_ptr Op = ParseOperand()) {
1948 Operands.push_back(std::move(Op));
1949 if (!getLexer().is(AsmToken::RCurly))
1950 return !TokError("Expected } at this point");
1951 Operands.push_back(X86Operand::CreateToken("}", consumeToken()));
1952
1953 // Parse "zeroing non-masked" semantic {z}
1954 if (getLexer().is(AsmToken::LCurly)) {
1955 Operands.push_back(X86Operand::CreateToken("{z}", consumeToken()));
1956 if (!getLexer().is(AsmToken::Identifier) ||
1957 getLexer().getTok().getIdentifier() != "z")
1958 return !TokError("Expected z at this point");
1959 Parser.Lex(); // Eat the z
1969 // Parse either {k}{z}, {z}{k}, {k} or {z}
1970 // last one have no meaning, but GCC accepts it
1971 // Currently, we're just pass a '{' mark
1972 std::unique_ptr Z;
1973 if (ParseZ(Z, consumedToken))
1974 return true;
1975 // Reaching here means that parsing of the allegadly '{z}' mark yielded
1976 // no errors.
1977 // Query for the need of further parsing for a {%k} mark
1978 if (!Z || getLexer().is(AsmToken::LCurly)) {
1979 const SMLoc StartLoc = Z ? consumeToken() : consumedToken;
1980 // Parse an op-mask register mark ({%k}), which is now to be
1981 // expected
1982 if (std::unique_ptr Op = ParseOperand()) {
19601983 if (!getLexer().is(AsmToken::RCurly))
1961 return !TokError("Expected } at this point");
1962 Parser.Lex(); // Eat the }
1984 return Error(getLexer().getLoc(), "Expected } at this point");
1985 Operands.push_back(X86Operand::CreateToken("{", StartLoc));
1986 Operands.push_back(std::move(Op));
1987 Operands.push_back(X86Operand::CreateToken("}", consumeToken()));
1988 } else
1989 return Error(getLexer().getLoc(),
1990 "Expected an op-mask register at this point");
1991 // {%k} mark is found, inquire for {z}
1992 if (getLexer().is(AsmToken::LCurly) && !Z) {
1993 // Have we've found a parsing error, or found no (expected) {z} mark
1994 // - report an error
1995 if (ParseZ(Z, consumeToken()) || !Z)
1996 return true;
1997
19631998 }
1999 // '{z}' on its own is meaningless, hence should be ignored.
2000 // on the contrary - have it been accompanied by a K register,
2001 // allow it.
2002 if (Z)
2003 Operands.push_back(std::move(Z));
19642004 }
19652005 }
19662006 }
19672007 }
1968 return true;
2008 return false;
19692009 }
19702010
19712011 /// ParseMemOperand: segment: disp(basereg, indexreg, scale). The '%ds:' prefix
23222362 while(1) {
23232363 if (std::unique_ptr Op = ParseOperand()) {
23242364 Operands.push_back(std::move(Op));
2325 if (!HandleAVX512Operand(Operands, *Operands.back()))
2365 if (HandleAVX512Operand(Operands, *Operands.back()))
23262366 return true;
23272367 } else {
23282368 return true;
1111 // CHECK: encoding: [0x62,0x82,0x6d,0xc5,0x66,0xc9]
1212 vpblendmb %zmm25, %zmm18, %zmm17 {%k5} {z}
1313
14 // CHECK: vpblendmb %zmm25, %zmm18, %zmm17 {%k5} {z}
15 // CHECK: encoding: [0x62,0x82,0x6d,0xc5,0x66,0xc9]
16 vpblendmb %zmm25, %zmm18, %zmm17 {z} {%k5}
17
1418 // CHECK: vpblendmb (%rcx), %zmm18, %zmm17
1519 // CHECK: encoding: [0x62,0xe2,0x6d,0x40,0x66,0x09]
1620 vpblendmb (%rcx), %zmm18, %zmm17
1414 // CHECK: vaddpd zmm1 {k5} {z}, zmm1, zmm2
1515 // CHECK: encoding: [0x62,0xf1,0xf5,0xcd,0x58,0xca]
1616 vaddpd zmm1 {k5} {z}, zmm1, zmm2
17
18 // CHECK: vaddpd zmm1 {k5} {z}, zmm1, zmm2
19 // CHECK: encoding: [0x62,0xf1,0xf5,0xcd,0x58,0xca]
20 vaddpd zmm1 {z} {k5}, zmm1, zmm2
1721
1822 // CHECK: vaddpd zmm1, zmm1, zmm2, {rn-sae}
1923 // CHECK: encoding: [0x62,0xf1,0xf5,0x18,0x58,0xca]