Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -3814,6 +3814,8 @@ - ``w``: A 32, 64, or 128-bit floating-point, SIMD or SVE vector register. - ``x``: Like w, but restricted to registers 0 to 15 inclusive. - ``y``: Like w, but restricted to SVE vector registers Z0 to Z7 inclusive. +- ``Upl``: One of the low eight SVE predicate registers (P0 to P7) +- ``Upa``: Any of the SVE predicate registers (P0 to P15) AMDGPU: Index: lib/IR/InlineAsm.cpp =================================================================== --- lib/IR/InlineAsm.cpp +++ lib/IR/InlineAsm.cpp @@ -181,6 +181,16 @@ // FIXME: For now assuming these are 2-character constraints. pCodes->push_back(StringRef(I+1, 2)); I += 3; + } else if (*I == '@') { + // Multi-letter constraint + ++I; + unsigned char C = static_cast(*I); + assert(isdigit(C) && "Not a single digit!"); + int N = C - '0'; + assert(N > 0 && "Found a zero letter constraint!"); + ++I; + pCodes->push_back(std::string(I, I+N)); + I += N; } else { // Single letter constraint. pCodes->push_back(StringRef(I, 1)); Index: lib/Target/AArch64/AArch64AsmPrinter.cpp =================================================================== --- lib/Target/AArch64/AArch64AsmPrinter.cpp +++ lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -620,6 +620,9 @@ if (AArch64::ZPRRegClass.contains(Reg)) { RegClass = &AArch64::ZPRRegClass; hasAltName = false; + } else if (AArch64::PPRRegClass.contains(Reg)) { + RegClass = &AArch64::PPRRegClass; + hasAltName = false; } else { RegClass = &AArch64::FPR128RegClass; hasAltName = true; Index: lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- lib/Target/AArch64/AArch64ISelLowering.cpp +++ lib/Target/AArch64/AArch64ISelLowering.cpp @@ -5764,6 +5764,10 @@ case 'S': // A symbolic address return C_Other; } + } else if (Constraint.size() == 3 && Constraint[0] == 'U' + && Constraint[1] == 'p' + && (Constraint[2] == 'l' || Constraint[2] == 'a')) { + return C_RegisterClass; } return TargetLowering::getConstraintType(Constraint); } @@ -5795,6 +5799,10 @@ case 'z': weight = CW_Constant; break; + case 'U': + if (constraint[1] == 'p' && (constraint[2] == 'l' || constraint[2] == 'a')) + weight = CW_Register; + break; } return weight; } @@ -5838,6 +5846,13 @@ return std::make_pair(0U, &AArch64::ZPR_3bRegClass); break; } + } else if (Constraint.size() == 3 && Constraint[0] == 'U' + && Constraint[1] == 'p' + && (Constraint[2] == 'l' || Constraint[2] == 'a')) { + assert(VT.isScalableVector()); + bool restricted = (Constraint[2] == 'l'); + return restricted ? std::make_pair(0U, &AArch64::PPR_3bRegClass) + : std::make_pair(0U, &AArch64::PPRRegClass); } if (StringRef("{cc}").equals_lower(Constraint)) return std::make_pair(unsigned(AArch64::NZCV), &AArch64::CCRRegClass); Index: lib/Target/AArch64/AArch64InstrInfo.cpp =================================================================== --- lib/Target/AArch64/AArch64InstrInfo.cpp +++ lib/Target/AArch64/AArch64InstrInfo.cpp @@ -2486,6 +2486,17 @@ return; } + // Copy a Predicate register by ORRing with itself. + if (AArch64::PPRRegClass.contains(DestReg) && + AArch64::PPRRegClass.contains(SrcReg)) { + assert(Subtarget.hasSVE() && "Unexpected SVE register."); + BuildMI(MBB, I, DL, get(AArch64::ORR_PPzPP), DestReg) + .addReg(SrcReg) // Pg + .addReg(SrcReg) + .addReg(SrcReg, getKillRegState(KillSrc)); + return; + } + // Copy a Z register by ORRing with itself. if (AArch64::ZPRRegClass.contains(DestReg) && AArch64::ZPRRegClass.contains(SrcReg)) { Index: test/CodeGen/AArch64/aarch64-sve-asm.ll =================================================================== --- test/CodeGen/AArch64/aarch64-sve-asm.ll +++ test/CodeGen/AArch64/aarch64-sve-asm.ll @@ -43,4 +43,24 @@ ret %1 } +; Function Attrs: nounwind readnone +; CHECK: [[ARG1:%[0-9]+]]:zpr = COPY $z1 +; CHECK: [[ARG2:%[0-9]+]]:zpr = COPY $z0 +; CHECK: [[ARG3:%[0-9]+]]:ppr = COPY $p0 +; CHECK: [[ARG4:%[0-9]+]]:ppr_3b = COPY [[ARG3]] +define @test_svfadd_f16( %Pg, %Zn, %Zm) { + %1 = tail call asm "fadd $0.h, $1/m, $2.h, $3.h", "=w,@3Upl,w,w"( %Pg, %Zn, %Zm) + ret %1 +} + +; Function Attrs: nounwind readnone +; CHECK: [[ARG1:%[0-9]+]]:zpr = COPY $z0 +; CHECK: [[ARG2:%[0-9]+]]:ppr = COPY $p0 +; CHECK: [[ARG3:%[0-9]+]]:ppr = COPY [[ARG2]] +; CHECK: [[ARG4:%[0-9]+]]:zpr = COPY [[ARG1]] +define @test_incp( %Pg, %Zn) { + %1 = tail call asm "incp $0.s, $1", "=w,@3Upa,0"( %Pg, %Zn) + ret %1 +} + !0 = !{i32 188, i32 210}