Index: llvm/lib/Target/AArch64/AArch64RegisterInfo.td =================================================================== --- llvm/lib/Target/AArch64/AArch64RegisterInfo.td +++ llvm/lib/Target/AArch64/AArch64RegisterInfo.td @@ -871,15 +871,16 @@ //****************************************************************************** // SVE predicate register classes. -class PPRClass : RegisterClass< +class PPRClass : RegisterClass< "AArch64", [ nxv16i1, nxv8i1, nxv4i1, nxv2i1, nxv1i1 ], 16, - (sequence "P%u", 0, lastreg)> { + (sequence "P%u", firstreg, lastreg)> { let Size = 16; } -def PPR : PPRClass<15>; -def PPR_3b : PPRClass<7>; // Restricted 3 bit SVE predicate register class. +def PPR : PPRClass<0, 15>; +def PPR_3b : PPRClass<0, 7>; // Restricted 3 bit SVE predicate register class. +def PPR_p8to15 : PPRClass<8, 15>; class PPRAsmOperand : AsmOperandClass { let Name = "SVE" # name # "Reg"; @@ -906,6 +907,38 @@ def PPR3bAny : PPRRegOp<"", PPRAsmOp3bAny, ElementSizeNone, PPR_3b>; + +// SME predicate-as-counter operand +class PNRAsmOperand + : PPRAsmOperand { + let PredicateMethod = "isSVEPredicateAsCounterRegOfWidth<" + # Width # ", " # "AArch64::" + # RegClass # "RegClassID>"; + let DiagnosticType = "InvalidSME" # name # "Reg"; + let ParserMethod = "tryParseSVEPredicateAsCounter"; +} + +class PNRP8to15RegOp + : PPRRegOp { + let PrintMethod = "printPredicateAsCounter<" # EltSize # ">"; + let EncoderMethod = "EncodePPR_p8to15"; + let DecoderMethod = "DecodePPR_p8to15RegisterClass"; +} + +def PNRAsmAny_p8to15 : PNRAsmOperand<"PNPredicateAny_p8to15", "PPR_p8to15", 0>; +def PNRAsmOp8_p8to15 : PNRAsmOperand<"PNPredicateB_p8to15", "PPR_p8to15", 8>; +def PNRAsmOp16_p8to15 : PNRAsmOperand<"PNPredicateH_p8to15", "PPR_p8to15", 16>; +def PNRAsmOp32_p8to15 : PNRAsmOperand<"PNPredicateS_p8to15", "PPR_p8to15", 32>; +def PNRAsmOp64_p8to15 : PNRAsmOperand<"PNPredicateD_p8to15", "PPR_p8to15", 64>; + +def PNRAny_p8to15 : PNRP8to15RegOp<"", PNRAsmAny_p8to15, 0, PPR_p8to15>; +def PNR8_p8to15 : PNRP8to15RegOp<"b", PNRAsmOp8_p8to15, 8, PPR_p8to15>; +def PNR16_p8to15 : PNRP8to15RegOp<"h", PNRAsmOp16_p8to15, 16, PPR_p8to15>; +def PNR32_p8to15 : PNRP8to15RegOp<"s", PNRAsmOp32_p8to15, 32, PPR_p8to15>; +def PNR64_p8to15 : PNRP8to15RegOp<"d", PNRAsmOp64_p8to15, 64, PPR_p8to15>; + + + //****************************************************************************** // SVE vector register classes Index: llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td =================================================================== --- llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -3586,4 +3586,7 @@ def UDOT_ZZZ_HtoS : sve2p1_two_way_dot_vv<"udot", 0b1>; def SDOT_ZZZI_HtoS : sve2p1_two_way_dot_vvi<"sdot", 0b0>; def UDOT_ZZZI_HtoS : sve2p1_two_way_dot_vvi<"udot", 0b1>; + +defm PEXT_PCI : sve2p1_int_ctr_to_mask<"pext">; +defm PTRUE_C : sve2p1_ptrue_pn<"ptrue">; } // End HasSVE2p1_or_HasSME2 Index: llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp =================================================================== --- llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -68,6 +68,7 @@ Scalar, NeonVector, SVEDataVector, + SVEPredicateAsCounter, SVEPredicateVector, Matrix }; @@ -266,6 +267,7 @@ template OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands); OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands); + OperandMatchResultTy tryParseSVEPredicateAsCounter(OperandVector &Operands); template OperandMatchResultTy tryParseVectorList(OperandVector &Operands, bool ExpectMatch = false); @@ -1198,6 +1200,22 @@ bool isMatrix() const { return Kind == k_MatrixRegister; } bool isMatrixTileList() const { return Kind == k_MatrixTileList; } + template bool isSMEVectorReg() const { + RegKind RK; + switch (Class) { + case AArch64::PPRRegClassID: + case AArch64::PPR_3bRegClassID: + case AArch64::PPR_p8to15RegClassID: + RK = RegKind::SVEPredicateAsCounter; + break; + default: + llvm_unreachable("Unsupport register class"); + } + + return (Kind == k_Register && Reg.Kind == RK) && + AArch64MCRegisterClasses[Class].contains(getReg()); + } + template bool isSVEVectorReg() const { RegKind RK; switch (Class) { @@ -1234,6 +1252,17 @@ return DiagnosticPredicateTy::NearMatch; } + template + DiagnosticPredicate isSVEPredicateAsCounterRegOfWidth() const { + if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateAsCounter) + return DiagnosticPredicateTy::NoMatch; + + if (isSMEVectorReg() && (Reg.ElementWidth == ElementWidth)) + return DiagnosticPredicateTy::Match; + + return DiagnosticPredicateTy::NearMatch; + } + template DiagnosticPredicate isSVEDataVectorRegOfWidth() const { if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector) @@ -2059,7 +2088,8 @@ unsigned ShiftAmount = 0, unsigned HasExplicitAmount = false) { assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector || - Kind == RegKind::SVEPredicateVector) && + Kind == RegKind::SVEPredicateVector || + Kind == RegKind::SVEPredicateAsCounter) && "Invalid vector kind"); auto Op = CreateReg(RegNum, Kind, S, E, Ctx, EqualsReg, ExtTy, ShiftAmount, HasExplicitAmount); @@ -2478,6 +2508,7 @@ .Case(".d", {0, 64}) .Default({-1, -1}); break; + case RegKind::SVEPredicateAsCounter: case RegKind::SVEPredicateVector: case RegKind::SVEDataVector: case RegKind::Matrix: @@ -2562,6 +2593,27 @@ .Default(0); } +static unsigned matchSVEPredicateAsCounterRegName(StringRef Name) { + return StringSwitch(Name.lower()) + .Case("pn0", AArch64::P0) + .Case("pn1", AArch64::P1) + .Case("pn2", AArch64::P2) + .Case("pn3", AArch64::P3) + .Case("pn4", AArch64::P4) + .Case("pn5", AArch64::P5) + .Case("pn6", AArch64::P6) + .Case("pn7", AArch64::P7) + .Case("pn8", AArch64::P8) + .Case("pn9", AArch64::P9) + .Case("pn10", AArch64::P10) + .Case("pn11", AArch64::P11) + .Case("pn12", AArch64::P12) + .Case("pn13", AArch64::P13) + .Case("pn14", AArch64::P14) + .Case("pn15", AArch64::P15) + .Default(0); +} + static unsigned matchMatrixTileListRegName(StringRef Name) { return StringSwitch(Name.lower()) .Case("za0.d", AArch64::ZAD0) @@ -2705,6 +2757,9 @@ if ((RegNum = matchSVEPredicateVectorRegName(Name))) return Kind == RegKind::SVEPredicateVector ? RegNum : 0; + if ((RegNum = matchSVEPredicateAsCounterRegName(Name))) + return Kind == RegKind::SVEPredicateAsCounter ? RegNum : 0; + if ((RegNum = MatchNeonVectorRegName(Name))) return Kind == RegKind::NeonVector ? RegNum : 0; @@ -3803,6 +3858,60 @@ return MatchOperand_NoMatch; } +OperandMatchResultTy +AArch64AsmParser::tryParseSVEPredicateAsCounter(OperandVector &Operands) { + const SMLoc S = getLoc(); + StringRef Kind; + unsigned RegNum; + auto Res = + tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateAsCounter); + if (Res != MatchOperand_Success) + return Res; + + const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateAsCounter); + if (!KindRes) + return MatchOperand_NoMatch; + + unsigned ElementWidth = KindRes->second; + Operands.push_back( + AArch64Operand::CreateVectorReg(RegNum, RegKind::SVEPredicateAsCounter, + ElementWidth, S, getLoc(), getContext())); + + // Check if register is followed by an index + OperandMatchResultTy ResIndex = tryParseVectorIndex(Operands); + if (ResIndex == MatchOperand_Success) + return MatchOperand_Success; + + // Not all predicates are followed by a '/z'. + MCAsmParser &Parser = getParser(); + if (Parser.getTok().isNot(AsmToken::Slash)) + return MatchOperand_Success; + + // But when they do they shouldn't have an element type suffix. + if (!Kind.empty()) { + Error(S, "not expecting size suffix"); + return MatchOperand_ParseFail; + } + + // Add a literal slash as operand + Operands.push_back(AArch64Operand::CreateToken("/", getLoc(), getContext())); + + Parser.Lex(); // Eat the slash. + + // Zeroing or merging? + auto Pred = Parser.getTok().getString().lower(); + if (Pred != "z") { + Error(getLoc(), "expecting 'z' predication"); + return MatchOperand_ParseFail; + } + + // Add zero token. + const char *ZM = "z"; + Operands.push_back(AArch64Operand::CreateToken(ZM, getLoc(), getContext())); + + Parser.Lex(); // Eat zero token. + return MatchOperand_Success; +} /// tryParseSVEPredicateVector - Parse a SVE predicate register operand. OperandMatchResultTy AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) { @@ -5573,6 +5682,15 @@ return Error(Loc, "invalid predicate register."); case Match_InvalidSVEPredicate3bAnyReg: return Error(Loc, "invalid restricted predicate register, expected p0..p7 (without element suffix)"); + case Match_InvalidSMEPNPredicateB_p8to15Reg: + case Match_InvalidSMEPNPredicateH_p8to15Reg: + case Match_InvalidSMEPNPredicateS_p8to15Reg: + case Match_InvalidSMEPNPredicateD_p8to15Reg: + return Error(Loc, "Invalid predicate register, expected PN in range " + "pn8..pn15 with element suffix."); + case Match_InvalidSMEPNPredicateAny_p8to15Reg: + return Error(Loc, "invalid restricted predicate-as-counter register " + "expected pn8..pn15"); case Match_InvalidSVEExactFPImmOperandHalfOne: return Error(Loc, "Invalid floating point constant, expected 0.5 or 1.0."); case Match_InvalidSVEExactFPImmOperandHalfTwo: @@ -6145,6 +6263,11 @@ case Match_InvalidSVEPredicateSReg: case Match_InvalidSVEPredicateDReg: case Match_InvalidSVEPredicate3bAnyReg: + case Match_InvalidSMEPNPredicateB_p8to15Reg: + case Match_InvalidSMEPNPredicateH_p8to15Reg: + case Match_InvalidSMEPNPredicateS_p8to15Reg: + case Match_InvalidSMEPNPredicateD_p8to15Reg: + case Match_InvalidSMEPNPredicateAny_p8to15Reg: case Match_InvalidSVEExactFPImmOperandHalfOne: case Match_InvalidSVEExactFPImmOperandHalfTwo: case Match_InvalidSVEExactFPImmOperandZeroOne: Index: llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp =================================================================== --- llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp +++ llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp @@ -137,6 +137,9 @@ static DecodeStatus DecodePPR_3bRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const MCDisassembler *Decoder); +static DecodeStatus +DecodePPR_p8to15RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, + const MCDisassembler *Decoder); static DecodeStatus DecodeFixedPointScaleImm32(MCInst &Inst, unsigned Imm, uint64_t Address, @@ -709,6 +712,16 @@ return DecodePPRRegisterClass(Inst, RegNo, Addr, Decoder); } +static DecodeStatus +DecodePPR_p8to15RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Addr, + const MCDisassembler *Decoder) { + if (RegNo > 7) + return Fail; + + // Just reuse the PPR decode table + return DecodePPRRegisterClass(Inst, RegNo + 8, Addr, Decoder); +} + static DecodeStatus DecodeQQRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Addr, const MCDisassembler *Decoder) { Index: llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h =================================================================== --- llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h +++ llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h @@ -182,6 +182,10 @@ const MCSubtargetInfo &STI, raw_ostream &O); void printSIMDType10Operand(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O); + template + void printPredicateAsCounter(const MCInst *MI, unsigned OpNum, + const MCSubtargetInfo &STI, raw_ostream &O); + template void printComplexRotationOp(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, raw_ostream &O); Index: llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp =================================================================== --- llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp +++ llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp @@ -1193,6 +1193,35 @@ } } +template +void AArch64InstPrinter::printPredicateAsCounter(const MCInst *MI, + unsigned OpNum, + const MCSubtargetInfo &STI, + raw_ostream &O) { + unsigned Reg = MI->getOperand(OpNum).getReg(); + + assert(Reg <= AArch64::P15 && "Unsupported predicate register"); + O << "pn" << (Reg - AArch64::P0); + switch (EltSize) { + case 0: + break; + case 8: + O << ".b"; + break; + case 16: + O << ".h"; + break; + case 32: + O << ".s"; + break; + case 64: + O << ".d"; + break; + default: + llvm_unreachable("Unsupported element size"); + } +} + void AArch64InstPrinter::printCondCode(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O) { Index: llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp =================================================================== --- llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp +++ llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp @@ -189,6 +189,9 @@ uint32_t EncodeRegAsMultipleOf(const MCInst &MI, unsigned OpIdx, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + uint32_t EncodePPR_p8to15(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; uint32_t EncodeMatrixTileListRegisterClass(const MCInst &MI, unsigned OpIdx, SmallVectorImpl &Fixups, @@ -533,6 +536,14 @@ return RegVal / Multiple; } +uint32_t +AArch64MCCodeEmitter::EncodePPR_p8to15(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + auto RegOpnd = MI.getOperand(OpIdx).getReg(); + return RegOpnd - AArch64::P8; +} + uint32_t AArch64MCCodeEmitter::EncodeMatrixTileListRegisterClass( const MCInst &MI, unsigned OpIdx, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { Index: llvm/lib/Target/AArch64/SVEInstrFormats.td =================================================================== --- llvm/lib/Target/AArch64/SVEInstrFormats.td +++ llvm/lib/Target/AArch64/SVEInstrFormats.td @@ -8695,3 +8695,47 @@ let Constraints = "$Zda = $_Zda"; let DestructiveInstType = DestructiveOther; } + + +class sve2p1_ptrue_pn sz, PNRP8to15RegOp pnrty> + : I<(outs pnrty:$PNd), (ins ), mnemonic, "\t$PNd", + "", []>, Sched<[]> { + bits<3> PNd; + let Inst{31-24} = 0b00100101; + let Inst{23-22} = sz; + let Inst{21-3} = 0b1000000111100000010; + let Inst{2-0} = PNd; +} + + +multiclass sve2p1_ptrue_pn { + def _B : sve2p1_ptrue_pn; + def _H : sve2p1_ptrue_pn; + def _S : sve2p1_ptrue_pn; + def _D : sve2p1_ptrue_pn; +} + + +class sve2p1_int_ctr_to_mask sz, PPRRegOp pprty> + : I<(outs pprty:$Pd), (ins PNRAny_p8to15:$PNn, VectorIndexS:$imm2), + mnemonic, "\t$Pd, $PNn$imm2", + "", []>, Sched<[]> { + bits<4> Pd; + bits<3> PNn; + bits<2> imm2; + let Inst{31-24} = 0b00100101; + let Inst{23-22} = sz; + let Inst{21-10} = 0b100000011100; + let Inst{9-8} = imm2; + let Inst{7-5} = PNn; + let Inst{4} = 0b1; + let Inst{3-0} = Pd; +} + + +multiclass sve2p1_int_ctr_to_mask { + def _B : sve2p1_int_ctr_to_mask; + def _H : sve2p1_int_ctr_to_mask; + def _S : sve2p1_int_ctr_to_mask; + def _D : sve2p1_int_ctr_to_mask; +} Index: llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-inline-asm.ll =================================================================== --- llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-inline-asm.ll +++ llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-inline-asm.ll @@ -4,9 +4,9 @@ define void @asm_simple_memory_clobber() { ; CHECK-LABEL: name: asm_simple_memory_clobber ; CHECK: bb.1 (%ir-block.0): - ; CHECK: INLINEASM &"", 25 /* sideeffect mayload maystore attdialect */, !0 - ; CHECK: INLINEASM &"", 1 /* sideeffect attdialect */, !0 - ; CHECK: RET_ReallyLR + ; CHECK-NEXT: INLINEASM &"", 25 /* sideeffect mayload maystore attdialect */, !0 + ; CHECK-NEXT: INLINEASM &"", 1 /* sideeffect attdialect */, !0 + ; CHECK-NEXT: RET_ReallyLR call void asm sideeffect "", "~{memory}"(), !srcloc !0 call void asm sideeffect "", ""(), !srcloc !0 ret void @@ -17,8 +17,8 @@ define void @asm_simple_register_clobber() { ; CHECK-LABEL: name: asm_simple_register_clobber ; CHECK: bb.1 (%ir-block.0): - ; CHECK: INLINEASM &"mov x0, 7", 1 /* sideeffect attdialect */, 12 /* clobber */, implicit-def early-clobber $x0, !0 - ; CHECK: RET_ReallyLR + ; CHECK-NEXT: INLINEASM &"mov x0, 7", 1 /* sideeffect attdialect */, 12 /* clobber */, implicit-def early-clobber $x0, !0 + ; CHECK-NEXT: RET_ReallyLR call void asm sideeffect "mov x0, 7", "~{x0}"(), !srcloc !0 ret void } @@ -26,12 +26,12 @@ define i64 @asm_register_early_clobber() { ; CHECK-LABEL: name: asm_register_early_clobber ; CHECK: bb.1 (%ir-block.0): - ; CHECK: INLINEASM &"mov $0, 7; mov $1, 7", 1 /* sideeffect attdialect */, 1703947 /* regdef-ec:GPR64common */, def early-clobber %0, 1703947 /* regdef-ec:GPR64common */, def early-clobber %1, !0 - ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY %0 - ; CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY %1 - ; CHECK: [[ADD:%[0-9]+]]:_(s64) = G_ADD [[COPY]], [[COPY1]] - ; CHECK: $x0 = COPY [[ADD]](s64) - ; CHECK: RET_ReallyLR implicit $x0 + ; CHECK-NEXT: INLINEASM &"mov $0, 7; mov $1, 7", 1 /* sideeffect attdialect */, 1769483 /* regdef-ec:GPR64common */, def early-clobber %0, 1769483 /* regdef-ec:GPR64common */, def early-clobber %1, !0 + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY %0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY %1 + ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s64) = G_ADD [[COPY]], [[COPY1]] + ; CHECK-NEXT: $x0 = COPY [[ADD]](s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 call { i64, i64 } asm sideeffect "mov $0, 7; mov $1, 7", "=&r,=&r"(), !srcloc !0 %asmresult = extractvalue { i64, i64 } %1, 0 %asmresult1 = extractvalue { i64, i64 } %1, 1 @@ -42,10 +42,10 @@ define i32 @test_specific_register_output() nounwind ssp { ; CHECK-LABEL: name: test_specific_register_output ; CHECK: bb.1.entry: - ; CHECK: INLINEASM &"mov ${0:w}, 7", 0 /* attdialect */, 10 /* regdef */, implicit-def $w0 - ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 - ; CHECK: $w0 = COPY [[COPY]](s32) - ; CHECK: RET_ReallyLR implicit $w0 + ; CHECK-NEXT: INLINEASM &"mov ${0:w}, 7", 0 /* attdialect */, 10 /* regdef */, implicit-def $w0 + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 + ; CHECK-NEXT: $w0 = COPY [[COPY]](s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 entry: %0 = tail call i32 asm "mov ${0:w}, 7", "={w0}"() nounwind ret i32 %0 @@ -54,10 +54,10 @@ define i32 @test_single_register_output() nounwind ssp { ; CHECK-LABEL: name: test_single_register_output ; CHECK: bb.1.entry: - ; CHECK: INLINEASM &"mov ${0:w}, 7", 0 /* attdialect */, 655370 /* regdef:GPR32common */, def %0 - ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY %0 - ; CHECK: $w0 = COPY [[COPY]](s32) - ; CHECK: RET_ReallyLR implicit $w0 + ; CHECK-NEXT: INLINEASM &"mov ${0:w}, 7", 0 /* attdialect */, 720906 /* regdef:GPR32common */, def %0 + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY %0 + ; CHECK-NEXT: $w0 = COPY [[COPY]](s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 entry: %0 = tail call i32 asm "mov ${0:w}, 7", "=r"() nounwind ret i32 %0 @@ -66,10 +66,10 @@ define i64 @test_single_register_output_s64() nounwind ssp { ; CHECK-LABEL: name: test_single_register_output_s64 ; CHECK: bb.1.entry: - ; CHECK: INLINEASM &"mov $0, 7", 0 /* attdialect */, 1703946 /* regdef:GPR64common */, def %0 - ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY %0 - ; CHECK: $x0 = COPY [[COPY]](s64) - ; CHECK: RET_ReallyLR implicit $x0 + ; CHECK-NEXT: INLINEASM &"mov $0, 7", 0 /* attdialect */, 1769482 /* regdef:GPR64common */, def %0 + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY %0 + ; CHECK-NEXT: $x0 = COPY [[COPY]](s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 entry: %0 = tail call i64 asm "mov $0, 7", "=r"() nounwind ret i64 %0 @@ -79,12 +79,12 @@ define float @test_multiple_register_outputs_same() #0 { ; CHECK-LABEL: name: test_multiple_register_outputs_same ; CHECK: bb.1 (%ir-block.0): - ; CHECK: INLINEASM &"mov $0, #0; mov $1, #0", 0 /* attdialect */, 655370 /* regdef:GPR32common */, def %0, 655370 /* regdef:GPR32common */, def %1 - ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY %0 - ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY %1 - ; CHECK: [[FADD:%[0-9]+]]:_(s32) = G_FADD [[COPY]], [[COPY1]] - ; CHECK: $s0 = COPY [[FADD]](s32) - ; CHECK: RET_ReallyLR implicit $s0 + ; CHECK-NEXT: INLINEASM &"mov $0, #0; mov $1, #0", 0 /* attdialect */, 720906 /* regdef:GPR32common */, def %0, 720906 /* regdef:GPR32common */, def %1 + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY %0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY %1 + ; CHECK-NEXT: [[FADD:%[0-9]+]]:_(s32) = G_FADD [[COPY]], [[COPY1]] + ; CHECK-NEXT: $s0 = COPY [[FADD]](s32) + ; CHECK-NEXT: RET_ReallyLR implicit $s0 %1 = call { float, float } asm "mov $0, #0; mov $1, #0", "=r,=r"() %asmresult = extractvalue { float, float } %1, 0 %asmresult1 = extractvalue { float, float } %1, 1 @@ -96,11 +96,11 @@ define double @test_multiple_register_outputs_mixed() #0 { ; CHECK-LABEL: name: test_multiple_register_outputs_mixed ; CHECK: bb.1 (%ir-block.0): - ; CHECK: INLINEASM &"mov $0, #0; mov $1, #0", 0 /* attdialect */, 655370 /* regdef:GPR32common */, def %0, 1507338 /* regdef:FPR64 */, def %1 - ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY %0 - ; CHECK: [[COPY1:%[0-9]+]]:_(s64) = COPY %1 - ; CHECK: $d0 = COPY [[COPY1]](s64) - ; CHECK: RET_ReallyLR implicit $d0 + ; CHECK-NEXT: INLINEASM &"mov $0, #0; mov $1, #0", 0 /* attdialect */, 720906 /* regdef:GPR32common */, def %0, 1572874 /* regdef:FPR64 */, def %1 + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY %0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY %1 + ; CHECK-NEXT: $d0 = COPY [[COPY1]](s64) + ; CHECK-NEXT: RET_ReallyLR implicit $d0 %1 = call { float, double } asm "mov $0, #0; mov $1, #0", "=r,=w"() %asmresult = extractvalue { float, double } %1, 1 ret double %asmresult @@ -109,28 +109,29 @@ define i32 @test_specific_register_output_trunc() nounwind ssp { ; CHECK-LABEL: name: test_specific_register_output_trunc ; CHECK: bb.1.entry: - ; CHECK: INLINEASM &"mov ${0:w}, 7", 0 /* attdialect */, 10 /* regdef */, implicit-def $x0 - ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 - ; CHECK: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) - ; CHECK: $w0 = COPY [[TRUNC]](s32) - ; CHECK: RET_ReallyLR implicit $w0 + ; CHECK-NEXT: INLINEASM &"mov ${0:w}, 7", 0 /* attdialect */, 10 /* regdef */, implicit-def $x0 + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) + ; CHECK-NEXT: $w0 = COPY [[TRUNC]](s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 entry: %0 = tail call i32 asm "mov ${0:w}, 7", "={x0}"() nounwind ret i32 %0 } define zeroext i8 @test_register_output_trunc(i8* %src) nounwind { + ; ; CHECK-LABEL: name: test_register_output_trunc ; CHECK: bb.1.entry: - ; CHECK: liveins: $x0 - ; - ; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x0 - ; CHECK: INLINEASM &"mov ${0:w}, 32", 0 /* attdialect */, 655370 /* regdef:GPR32common */, def %1 - ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY %1 - ; CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) - ; CHECK: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s8) - ; CHECK: $w0 = COPY [[ZEXT]](s32) - ; CHECK: RET_ReallyLR implicit $w0 + ; CHECK-NEXT: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0 + ; CHECK-NEXT: INLINEASM &"mov ${0:w}, 32", 0 /* attdialect */, 720906 /* regdef:GPR32common */, def %1 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY %1 + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) + ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s8) + ; CHECK-NEXT: $w0 = COPY [[ZEXT]](s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 entry: %0 = tail call i8 asm "mov ${0:w}, 32", "=r"() nounwind ret i8 %0 @@ -139,12 +140,12 @@ define float @test_vector_output() nounwind { ; CHECK-LABEL: name: test_vector_output ; CHECK: bb.1 (%ir-block.0): - ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 - ; CHECK: INLINEASM &"fmov ${0}.2s, #1.0", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $d14 - ; CHECK: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $d14 - ; CHECK: [[EVEC:%[0-9]+]]:_(s32) = G_EXTRACT_VECTOR_ELT [[COPY]](<2 x s32>), [[C]](s64) - ; CHECK: $s0 = COPY [[EVEC]](s32) - ; CHECK: RET_ReallyLR implicit $s0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 + ; CHECK-NEXT: INLINEASM &"fmov ${0}.2s, #1.0", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $d14 + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $d14 + ; CHECK-NEXT: [[EVEC:%[0-9]+]]:_(s32) = G_EXTRACT_VECTOR_ELT [[COPY]](<2 x s32>), [[C]](s64) + ; CHECK-NEXT: $s0 = COPY [[EVEC]](s32) + ; CHECK-NEXT: RET_ReallyLR implicit $s0 %1 = tail call <2 x float> asm sideeffect "fmov ${0}.2s, #1.0", "={v14}"() nounwind %2 = extractelement <2 x float> %1, i32 0 ret float %2 @@ -153,10 +154,10 @@ define void @test_input_register_imm() { ; CHECK-LABEL: name: test_input_register_imm ; CHECK: bb.1 (%ir-block.0): - ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 42 - ; CHECK: [[COPY:%[0-9]+]]:gpr64common = COPY [[C]](s64) - ; CHECK: INLINEASM &"mov x0, $0", 1 /* sideeffect attdialect */, 1703945 /* reguse:GPR64common */, [[COPY]] - ; CHECK: RET_ReallyLR + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 42 + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64common = COPY [[C]](s64) + ; CHECK-NEXT: INLINEASM &"mov x0, $0", 1 /* sideeffect attdialect */, 1769481 /* reguse:GPR64common */, [[COPY]] + ; CHECK-NEXT: RET_ReallyLR call void asm sideeffect "mov x0, $0", "r"(i64 42) ret void } @@ -165,10 +166,10 @@ define i32 @test_boolean_imm_ext() { ; CHECK-LABEL: name: test_boolean_imm_ext ; CHECK: bb.1.entry: - ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 - ; CHECK: INLINEASM &"#TEST 42 + ${0:c} - .\0A\09", 9 /* sideeffect mayload attdialect */, 13 /* imm */, 1 - ; CHECK: $w0 = COPY [[C]](s32) - ; CHECK: RET_ReallyLR implicit $w0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 + ; CHECK-NEXT: INLINEASM &"#TEST 42 + ${0:c} - .\0A\09", 9 /* sideeffect mayload attdialect */, 13 /* imm */, 1 + ; CHECK-NEXT: $w0 = COPY [[C]](s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 entry: tail call void asm sideeffect "#TEST 42 + ${0:c} - .\0A\09", "i"(i1 true) ret i32 1 @@ -177,8 +178,8 @@ define void @test_input_imm() { ; CHECK-LABEL: name: test_input_imm ; CHECK: bb.1 (%ir-block.0): - ; CHECK: INLINEASM &"mov x0, $0", 9 /* sideeffect mayload attdialect */, 13 /* imm */, 42 - ; CHECK: RET_ReallyLR + ; CHECK-NEXT: INLINEASM &"mov x0, $0", 9 /* sideeffect mayload attdialect */, 13 /* imm */, 42 + ; CHECK-NEXT: RET_ReallyLR call void asm sideeffect "mov x0, $0", "i"(i64 42) ret void } @@ -186,15 +187,16 @@ define zeroext i8 @test_input_register(i8* %src) nounwind { ; CHECK-LABEL: name: test_input_register ; CHECK: bb.1.entry: - ; CHECK: liveins: $x0 - ; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x0 - ; CHECK: [[COPY1:%[0-9]+]]:gpr64common = COPY [[COPY]](p0) - ; CHECK: INLINEASM &"ldtrb ${0:w}, [$1]", 0 /* attdialect */, 655370 /* regdef:GPR32common */, def %1, 1703945 /* reguse:GPR64common */, [[COPY1]] - ; CHECK: [[COPY2:%[0-9]+]]:_(s32) = COPY %1 - ; CHECK: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY2]](s32) - ; CHECK: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s8) - ; CHECK: $w0 = COPY [[ZEXT]](s32) - ; CHECK: RET_ReallyLR implicit $w0 + ; CHECK-NEXT: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64common = COPY [[COPY]](p0) + ; CHECK-NEXT: INLINEASM &"ldtrb ${0:w}, [$1]", 0 /* attdialect */, 720906 /* regdef:GPR32common */, def %1, 1769481 /* reguse:GPR64common */, [[COPY1]] + ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY %1 + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY2]](s32) + ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s8) + ; CHECK-NEXT: $w0 = COPY [[ZEXT]](s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 entry: %0 = tail call i8 asm "ldtrb ${0:w}, [$1]", "=r,r"(i8* %src) nounwind ret i8 %0 @@ -203,12 +205,13 @@ define i32 @test_memory_constraint(i32* %a) nounwind { ; CHECK-LABEL: name: test_memory_constraint ; CHECK: bb.1 (%ir-block.0): - ; CHECK: liveins: $x0 - ; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x0 - ; CHECK: INLINEASM &"ldr $0, $1", 8 /* mayload attdialect */, 655370 /* regdef:GPR32common */, def %1, 262158 /* mem:m */, [[COPY]](p0) - ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY %1 - ; CHECK: $w0 = COPY [[COPY1]](s32) - ; CHECK: RET_ReallyLR implicit $w0 + ; CHECK-NEXT: liveins: $x0 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0 + ; CHECK-NEXT: INLINEASM &"ldr $0, $1", 8 /* mayload attdialect */, 720906 /* regdef:GPR32common */, def %1, 262158 /* mem:m */, [[COPY]](p0) + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY %1 + ; CHECK-NEXT: $w0 = COPY [[COPY1]](s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 %1 = tail call i32 asm "ldr $0, $1", "=r,*m"(i32* elementtype(i32) %a) ret i32 %1 } @@ -216,15 +219,15 @@ define i16 @test_anyext_input() { ; CHECK-LABEL: name: test_anyext_input ; CHECK: bb.1 (%ir-block.0): - ; CHECK: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 1 - ; CHECK: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[C]](s16) - ; CHECK: [[COPY:%[0-9]+]]:gpr32common = COPY [[ANYEXT]](s32) - ; CHECK: INLINEASM &"", 1 /* sideeffect attdialect */, 655370 /* regdef:GPR32common */, def %0, 655369 /* reguse:GPR32common */, [[COPY]] - ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY %0 - ; CHECK: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) - ; CHECK: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC]](s16) - ; CHECK: $w0 = COPY [[ANYEXT1]](s32) - ; CHECK: RET_ReallyLR implicit $w0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 1 + ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[C]](s16) + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr32common = COPY [[ANYEXT]](s32) + ; CHECK-NEXT: INLINEASM &"", 1 /* sideeffect attdialect */, 720906 /* regdef:GPR32common */, def %0, 720905 /* reguse:GPR32common */, [[COPY]] + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY %0 + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC]](s16) + ; CHECK-NEXT: $w0 = COPY [[ANYEXT1]](s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 %1 = call i16 asm sideeffect "", "=r,r"(i16 1) ret i16 %1 } @@ -232,15 +235,15 @@ define i16 @test_anyext_input_with_matching_constraint() { ; CHECK-LABEL: name: test_anyext_input_with_matching_constraint ; CHECK: bb.1 (%ir-block.0): - ; CHECK: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 1 - ; CHECK: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[C]](s16) - ; CHECK: [[COPY:%[0-9]+]]:gpr32common = COPY [[ANYEXT]](s32) - ; CHECK: INLINEASM &"", 1 /* sideeffect attdialect */, 655370 /* regdef:GPR32common */, def %0, 2147483657 /* reguse tiedto:$0 */, [[COPY]](tied-def 3) - ; CHECK: [[COPY1:%[0-9]+]]:_(s32) = COPY %0 - ; CHECK: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) - ; CHECK: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC]](s16) - ; CHECK: $w0 = COPY [[ANYEXT1]](s32) - ; CHECK: RET_ReallyLR implicit $w0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 1 + ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[C]](s16) + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr32common = COPY [[ANYEXT]](s32) + ; CHECK-NEXT: INLINEASM &"", 1 /* sideeffect attdialect */, 720906 /* regdef:GPR32common */, def %0, 2147483657 /* reguse tiedto:$0 */, [[COPY]](tied-def 3) + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY %0 + ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC]](s16) + ; CHECK-NEXT: $w0 = COPY [[ANYEXT1]](s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 %1 = call i16 asm sideeffect "", "=r,0"(i16 1) ret i16 %1 } @@ -248,11 +251,11 @@ define i64 @test_input_with_matching_constraint_to_physical_register() { ; CHECK-LABEL: name: test_input_with_matching_constraint_to_physical_register ; CHECK: bb.1 (%ir-block.0): - ; CHECK: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 - ; CHECK: INLINEASM &"", 0 /* attdialect */, 10 /* regdef */, implicit-def $x2, 2147483657 /* reguse tiedto:$0 */, [[C]](tied-def 3)(s64) - ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x2 - ; CHECK: $x0 = COPY [[COPY]](s64) - ; CHECK: RET_ReallyLR implicit $x0 + ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 + ; CHECK-NEXT: INLINEASM &"", 0 /* attdialect */, 10 /* regdef */, implicit-def $x2, 2147483657 /* reguse tiedto:$0 */, [[C]](tied-def 3)(s64) + ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x2 + ; CHECK-NEXT: $x0 = COPY [[COPY]](s64) + ; CHECK-NEXT: RET_ReallyLR implicit $x0 %1 = tail call i64 asm "", "={x2},0"(i64 0) ret i64 %1 } Index: llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-unwind-inline-asm.ll =================================================================== --- llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-unwind-inline-asm.ll +++ llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-unwind-inline-asm.ll @@ -69,7 +69,7 @@ ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: [[DEF:%[0-9]+]]:_(p0) = G_IMPLICIT_DEF ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64common = COPY [[DEF]](p0) - ; CHECK-NEXT: INLINEASM &"", 1 /* sideeffect attdialect */, 1703945 /* reguse:GPR64common */, [[COPY]] + ; CHECK-NEXT: INLINEASM &"", 1 /* sideeffect attdialect */, 1769481 /* reguse:GPR64common */, [[COPY]] ; CHECK-NEXT: G_BR %bb.2 ; CHECK-NEXT: {{ $}} ; CHECK-NEXT: bb.2.a: Index: llvm/test/CodeGen/AArch64/GlobalISel/regbank-inlineasm.mir =================================================================== --- llvm/test/CodeGen/AArch64/GlobalISel/regbank-inlineasm.mir +++ llvm/test/CodeGen/AArch64/GlobalISel/regbank-inlineasm.mir @@ -10,8 +10,8 @@ bb.1: ; CHECK-LABEL: name: inlineasm_memory_clobber ; CHECK: INLINEASM &"", 25 /* sideeffect mayload maystore attdialect */ - ; CHECK: INLINEASM &"", 1 /* sideeffect attdialect */ - ; CHECK: RET_ReallyLR + ; CHECK-NEXT: INLINEASM &"", 1 /* sideeffect attdialect */ + ; CHECK-NEXT: RET_ReallyLR INLINEASM &"", 25 INLINEASM &"", 1 RET_ReallyLR @@ -26,7 +26,7 @@ bb.1: ; CHECK-LABEL: name: inlineasm_register_clobber ; CHECK: INLINEASM &"", 25 /* sideeffect mayload maystore attdialect */, 12 /* clobber */, implicit-def early-clobber $d0 - ; CHECK: RET_ReallyLR + ; CHECK-NEXT: RET_ReallyLR INLINEASM &"", 25, 12, implicit-def early-clobber $d0 RET_ReallyLR ... @@ -40,9 +40,9 @@ bb.1: ; CHECK-LABEL: name: inlineasm_phys_reg_output ; CHECK: INLINEASM &"mov ${0:w}, 7", 0 /* attdialect */, 10 /* regdef */, implicit-def $w0 - ; CHECK: [[COPY:%[0-9]+]]:gpr(s32) = COPY $w0 - ; CHECK: $w0 = COPY [[COPY]](s32) - ; CHECK: RET_ReallyLR implicit $w0 + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr(s32) = COPY $w0 + ; CHECK-NEXT: $w0 = COPY [[COPY]](s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 INLINEASM &"mov ${0:w}, 7", 0 /* attdialect */, 10 /* regdef */, implicit-def $w0 %0:_(s32) = COPY $w0 $w0 = COPY %0(s32) @@ -57,10 +57,10 @@ body: | bb.1: ; CHECK-LABEL: name: inlineasm_virt_reg_output - ; CHECK: INLINEASM &"mov ${0:w}, 7", 0 /* attdialect */, 1310730 /* regdef:WSeqPairsClass_with_sube32_in_MatrixIndexGPR32_12_15 */, def %0 - ; CHECK: [[COPY:%[0-9]+]]:gpr(s32) = COPY %0 - ; CHECK: $w0 = COPY [[COPY]](s32) - ; CHECK: RET_ReallyLR implicit $w0 + ; CHECK: INLINEASM &"mov ${0:w}, 7", 0 /* attdialect */, 1310730 /* regdef:WSeqPairsClass_with_sube32_in_GPR32arg */, def %0 + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr(s32) = COPY %0 + ; CHECK-NEXT: $w0 = COPY [[COPY]](s32) + ; CHECK-NEXT: RET_ReallyLR implicit $w0 INLINEASM &"mov ${0:w}, 7", 0 /* attdialect */, 1310730 /* regdef:GPR32common */, def %0:gpr32common %1:_(s32) = COPY %0 $w0 = COPY %1(s32) @@ -75,11 +75,11 @@ body: | bb.1: ; CHECK-LABEL: name: inlineasm_virt_mixed_types - ; CHECK: INLINEASM &"mov $0, #0; mov $1, #0", 0 /* attdialect */, 1310730 /* regdef:WSeqPairsClass_with_sube32_in_MatrixIndexGPR32_12_15 */, def %0, 2162698 /* regdef:FIXED_REGS */, def %1 - ; CHECK: [[COPY:%[0-9]+]]:gpr(s32) = COPY %0 - ; CHECK: [[COPY1:%[0-9]+]]:fpr(s64) = COPY %1 - ; CHECK: $d0 = COPY [[COPY1]](s64) - ; CHECK: RET_ReallyLR implicit $d0 + ; CHECK: INLINEASM &"mov $0, #0; mov $1, #0", 0 /* attdialect */, 1310730 /* regdef:WSeqPairsClass_with_sube32_in_GPR32arg */, def %0, 2162698 /* regdef:GPR64arg */, def %1 + ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr(s32) = COPY %0 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:fpr(s64) = COPY %1 + ; CHECK-NEXT: $d0 = COPY [[COPY1]](s64) + ; CHECK-NEXT: RET_ReallyLR implicit $d0 INLINEASM &"mov $0, #0; mov $1, #0", 0 /* attdialect */, 1310730 /* regdef:GPR32common */, def %0:gpr32common, 2162698 /* regdef:FPR64 */, def %1:fpr64 %3:_(s32) = COPY %0 %4:_(s64) = COPY %1 Index: llvm/test/MC/AArch64/SVE2p1/pext-diagnostics.s =================================================================== --- /dev/null +++ llvm/test/MC/AArch64/SVE2p1/pext-diagnostics.s @@ -0,0 +1,22 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p1 2>&1 < %s | FileCheck %s + +// --------------------------------------------------------------------------// +// Invalid predicate as counter register + +pext p0.h, pn3[0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid restricted predicate-as-counter register expected pn8..pn15 +// CHECK-NEXT: pext p0.h, pn3[0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Invalid lane index + +pext p0.d, pn8[4] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 3]. +// CHECK-NEXT: pext p0.d, pn8[4] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +pext p0.b, pn8[-1] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 3]. +// CHECK-NEXT: pext p0.b, pn8[-1] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: Index: llvm/test/MC/AArch64/SVE2p1/pext.s =================================================================== --- /dev/null +++ llvm/test/MC/AArch64/SVE2p1/pext.s @@ -0,0 +1,110 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p1 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme2 < %s \ +// RUN: | llvm-objdump -d --mattr=+sme2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2 < %s \ +// RUN: | sed '/.text/d' | sed 's/.*encoding: //g' \ +// RUN: | llvm-mc -triple=aarch64 -mattr=+sme2 -disassemble -show-encoding \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST + +pext p0.h, pn8[0] // 00100101-01100000-01110000-00010000 +// CHECK-INST: pext p0.h, pn8[0] +// CHECK-ENCODING: [0x10,0x70,0x60,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25607010 + +pext p5.h, pn10[1] // 00100101-01100000-01110001-01010101 +// CHECK-INST: pext p5.h, pn10[1] +// CHECK-ENCODING: [0x55,0x71,0x60,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25607155 + +pext p7.h, pn13[1] // 00100101-01100000-01110001-10110111 +// CHECK-INST: pext p7.h, pn13[1] +// CHECK-ENCODING: [0xb7,0x71,0x60,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 256071b7 + +pext p15.h, pn15[3] // 00100101-01100000-01110011-11111111 +// CHECK-INST: pext p15.h, pn15[3] +// CHECK-ENCODING: [0xff,0x73,0x60,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 256073ff + +pext p0.s, pn8[0] // 00100101-10100000-01110000-00010000 +// CHECK-INST: pext p0.s, pn8[0] +// CHECK-ENCODING: [0x10,0x70,0xa0,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25a07010 + +pext p5.s, pn10[1] // 00100101-10100000-01110001-01010101 +// CHECK-INST: pext p5.s, pn10[1] +// CHECK-ENCODING: [0x55,0x71,0xa0,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25a07155 + +pext p7.s, pn13[1] // 00100101-10100000-01110001-10110111 +// CHECK-INST: pext p7.s, pn13[1] +// CHECK-ENCODING: [0xb7,0x71,0xa0,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25a071b7 + +pext p15.s, pn15[3] // 00100101-10100000-01110011-11111111 +// CHECK-INST: pext p15.s, pn15[3] +// CHECK-ENCODING: [0xff,0x73,0xa0,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25a073ff + +pext p0.d, pn8[0] // 00100101-11100000-01110000-00010000 +// CHECK-INST: pext p0.d, pn8[0] +// CHECK-ENCODING: [0x10,0x70,0xe0,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25e07010 + +pext p5.d, pn10[1] // 00100101-11100000-01110001-01010101 +// CHECK-INST: pext p5.d, pn10[1] +// CHECK-ENCODING: [0x55,0x71,0xe0,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25e07155 + +pext p7.d, pn13[1] // 00100101-11100000-01110001-10110111 +// CHECK-INST: pext p7.d, pn13[1] +// CHECK-ENCODING: [0xb7,0x71,0xe0,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25e071b7 + +pext p15.d, pn15[3] // 00100101-11100000-01110011-11111111 +// CHECK-INST: pext p15.d, pn15[3] +// CHECK-ENCODING: [0xff,0x73,0xe0,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25e073ff + +pext p0.b, pn8[0] // 00100101-00100000-01110000-00010000 +// CHECK-INST: pext p0.b, pn8[0] +// CHECK-ENCODING: [0x10,0x70,0x20,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25207010 + +pext p5.b, pn10[1] // 00100101-00100000-01110001-01010101 +// CHECK-INST: pext p5.b, pn10[1] +// CHECK-ENCODING: [0x55,0x71,0x20,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25207155 + +pext p7.b, pn13[1] // 00100101-00100000-01110001-10110111 +// CHECK-INST: pext p7.b, pn13[1] +// CHECK-ENCODING: [0xb7,0x71,0x20,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 252071b7 + +pext p15.b, pn15[3] // 00100101-00100000-01110011-11111111 +// CHECK-INST: pext p15.b, pn15[3] +// CHECK-ENCODING: [0xff,0x73,0x20,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 252073ff Index: llvm/test/MC/AArch64/SVE2p1/ptrue-diagnostics.s =================================================================== --- /dev/null +++ llvm/test/MC/AArch64/SVE2p1/ptrue-diagnostics.s @@ -0,0 +1,18 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p1 2>&1 < %s | FileCheck %s + +// --------------------------------------------------------------------------// +// Invalid use of predicate as counter register + +ptrue pn7.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid predicate register, expected PN in range pn8..pn15 with element suffix. +// CHECK-NEXT: ptrue pn7.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Invalid use of predicate as counter without suffix + +ptrue pn8 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid predicate register, expected PN in range pn8..pn15 with element suffix. +// CHECK-NEXT: ptrue pn8 +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + Index: llvm/test/MC/AArch64/SVE2p1/ptrue.s =================================================================== --- /dev/null +++ llvm/test/MC/AArch64/SVE2p1/ptrue.s @@ -0,0 +1,110 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p1 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme2 < %s \ +// RUN: | llvm-objdump -d --mattr=+sme2 - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme2 < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2 < %s \ +// RUN: | sed '/.text/d' | sed 's/.*encoding: //g' \ +// RUN: | llvm-mc -triple=aarch64 -mattr=+sme2 -disassemble -show-encoding \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST + +ptrue pn8.h // 00100101-01100000-01111000-00010000 +// CHECK-INST: ptrue pn8.h +// CHECK-ENCODING: [0x10,0x78,0x60,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25607810 + +ptrue pn13.h // 00100101-01100000-01111000-00010101 +// CHECK-INST: ptrue pn13.h +// CHECK-ENCODING: [0x15,0x78,0x60,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25607815 + +ptrue pn15.h // 00100101-01100000-01111000-00010111 +// CHECK-INST: ptrue pn15.h +// CHECK-ENCODING: [0x17,0x78,0x60,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25607817 + +ptrue pn9.h // 00100101-01100000-01111000-00010001 +// CHECK-INST: ptrue pn9.h +// CHECK-ENCODING: [0x11,0x78,0x60,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25607811 + +ptrue pn8.s // 00100101-10100000-01111000-00010000 +// CHECK-INST: ptrue pn8.s +// CHECK-ENCODING: [0x10,0x78,0xa0,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25a07810 + +ptrue pn13.s // 00100101-10100000-01111000-00010101 +// CHECK-INST: ptrue pn13.s +// CHECK-ENCODING: [0x15,0x78,0xa0,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25a07815 + +ptrue pn15.s // 00100101-10100000-01111000-00010111 +// CHECK-INST: ptrue pn15.s +// CHECK-ENCODING: [0x17,0x78,0xa0,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25a07817 + +ptrue pn9.s // 00100101-10100000-01111000-00010001 +// CHECK-INST: ptrue pn9.s +// CHECK-ENCODING: [0x11,0x78,0xa0,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25a07811 + +ptrue pn8.d // 00100101-11100000-01111000-00010000 +// CHECK-INST: ptrue pn8.d +// CHECK-ENCODING: [0x10,0x78,0xe0,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25e07810 + +ptrue pn13.d // 00100101-11100000-01111000-00010101 +// CHECK-INST: ptrue pn13.d +// CHECK-ENCODING: [0x15,0x78,0xe0,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25e07815 + +ptrue pn15.d // 00100101-11100000-01111000-00010111 +// CHECK-INST: ptrue pn15.d +// CHECK-ENCODING: [0x17,0x78,0xe0,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25e07817 + +ptrue pn9.d // 00100101-11100000-01111000-00010001 +// CHECK-INST: ptrue pn9.d +// CHECK-ENCODING: [0x11,0x78,0xe0,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25e07811 + +ptrue pn8.b // 00100101-00100000-01111000-00010000 +// CHECK-INST: ptrue pn8.b +// CHECK-ENCODING: [0x10,0x78,0x20,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25207810 + +ptrue pn13.b // 00100101-00100000-01111000-00010101 +// CHECK-INST: ptrue pn13.b +// CHECK-ENCODING: [0x15,0x78,0x20,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25207815 + +ptrue pn15.b // 00100101-00100000-01111000-00010111 +// CHECK-INST: ptrue pn15.b +// CHECK-ENCODING: [0x17,0x78,0x20,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25207817 + +ptrue pn9.b // 00100101-00100000-01111000-00010001 +// CHECK-INST: ptrue pn9.b +// CHECK-ENCODING: [0x11,0x78,0x20,0x25] +// CHECK-ERROR: instruction requires: sme2 or sve2p1 +// CHECK-UNKNOWN: 25207811