Index: lib/Target/X86/AsmParser/X86AsmParser.cpp =================================================================== --- lib/Target/X86/AsmParser/X86AsmParser.cpp +++ lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -749,6 +749,8 @@ bool HandleAVX512Operand(OperandVector &Operands, const MCParsedAsmOperand &Op); + bool ParseZ(std::unique_ptr &Z, const SMLoc &StartLoc); + bool is64BitMode() const { // FIXME: Can tablegen auto-generate this? return getSTI().getFeatureBits()[X86::Mode64Bit]; @@ -1879,6 +1881,28 @@ } } +// False on failure, true otherwise +// If no {z} mark was found - Parser doesn't advance +bool X86AsmParser::ParseZ(std::unique_ptr &Z, + const SMLoc &StartLoc) { + MCAsmParser &Parser = getParser(); + // Assuming we are just pass the '{' mark, quering the next token + // Searched for {z}, but none was found. Return true, as no parsing error was + // encountered + if (!(getLexer().is(AsmToken::Identifier) && + (getLexer().getTok().getIdentifier() == "z"))) + return true; + Parser.Lex(); // Eat z + // Query and eat the '}' mark + if (!getLexer().is(AsmToken::RCurly)) + return !Error(getLexer().getLoc(), "Expected } at this point"); + Parser.Lex(); // Eat '}' + // Assign Z with the {z} mark opernad + Z.reset(X86Operand::CreateToken("{z}", StartLoc).release()); + return true; +} + +// False on failure, true otherwise bool X86AsmParser::HandleAVX512Operand(OperandVector &Operands, const MCParsedAsmOperand &Op) { MCAsmParser &Parser = getParser(); @@ -1915,24 +1939,38 @@ // after memory broadcasting, so return. return true; } else { - // Parse mask register {%k1} - Operands.push_back(X86Operand::CreateToken("{", consumedToken)); - if (std::unique_ptr Op = ParseOperand()) { - Operands.push_back(std::move(Op)); - if (!getLexer().is(AsmToken::RCurly)) - return !TokError("Expected } at this point"); - Operands.push_back(X86Operand::CreateToken("}", consumeToken())); - - // Parse "zeroing non-masked" semantic {z} - if (getLexer().is(AsmToken::LCurly)) { - Operands.push_back(X86Operand::CreateToken("{z}", consumeToken())); - if (!getLexer().is(AsmToken::Identifier) || - getLexer().getTok().getIdentifier() != "z") - return !TokError("Expected z at this point"); - Parser.Lex(); // Eat the z + // Parse either {k}{z}, {z}{k}, {k} or {z} + // last one have no meaning, but GCC accepts it + // Currently, we're just pass a '{' mark + std::unique_ptr Z; + if (!ParseZ(Z, consumedToken)) + return false; + // Reaching here means that parsing of the allegadly '{z}' mark yielded + // no errors. + // Query for the need of further parsing for a {%k} mark + if (!Z || getLexer().is(AsmToken::LCurly)) { + const SMLoc StartLoc = Z ? consumeToken() : consumedToken; + // Parse an op-mask register mark ({%k}), which is now to be + // expected + if (std::unique_ptr Op = ParseOperand()) { if (!getLexer().is(AsmToken::RCurly)) - return !TokError("Expected } at this point"); - Parser.Lex(); // Eat the } + return !Error(getLexer().getLoc(), "Expected } at this point"); + Operands.push_back(X86Operand::CreateToken("{", StartLoc)); + Operands.push_back(std::move(Op)); + Operands.push_back(X86Operand::CreateToken("}", consumeToken())); + } else + return !Error(getLexer().getLoc(), + "Expected an op-mask register at this point"); + // {%k} mark is found, inquire for {z} + if (getLexer().is(AsmToken::LCurly) && !Z) { + // Have we've found a parsing error, or found no (expected) {z} mark + // - report an error + if (!ParseZ(Z, consumeToken()) || !Z) + return false; + // '{z}' on its own is meaningless, hence should be ignored. + // on the contrary - have it been accompanied by a K register, + // allow it. + Operands.push_back(std::move(Z)); } } } Index: test/MC/X86/avx512bw-encoding.s =================================================================== --- test/MC/X86/avx512bw-encoding.s +++ test/MC/X86/avx512bw-encoding.s @@ -12,6 +12,10 @@ // CHECK: encoding: [0x62,0x82,0x6d,0xc5,0x66,0xc9] vpblendmb %zmm25, %zmm18, %zmm17 {%k5} {z} +// CHECK: vpblendmb %zmm25, %zmm18, %zmm17 {%k5} {z} +// CHECK: encoding: [0x62,0x82,0x6d,0xc5,0x66,0xc9] + vpblendmb %zmm25, %zmm18, %zmm17 {z} {%k5} + // CHECK: vpblendmb (%rcx), %zmm18, %zmm17 // CHECK: encoding: [0x62,0xe2,0x6d,0x40,0x66,0x09] vpblendmb (%rcx), %zmm18, %zmm17 Index: test/MC/X86/intel-syntax-avx512.s =================================================================== --- test/MC/X86/intel-syntax-avx512.s +++ test/MC/X86/intel-syntax-avx512.s @@ -16,6 +16,10 @@ // CHECK: encoding: [0x62,0xf1,0xf5,0xcd,0x58,0xca] vaddpd zmm1 {k5} {z}, zmm1, zmm2 +// CHECK: vaddpd zmm1 {k5} {z}, zmm1, zmm2 +// CHECK: encoding: [0x62,0xf1,0xf5,0xcd,0x58,0xca] +vaddpd zmm1 {z} {k5}, zmm1, zmm2 + // CHECK: vaddpd zmm1, zmm1, zmm2, {rn-sae} // CHECK: encoding: [0x62,0xf1,0xf5,0x18,0x58,0xca] vaddpd zmm1, zmm1, zmm2, {rn-sae}