Index: llvm/trunk/docs/LangRef.rst =================================================================== --- llvm/trunk/docs/LangRef.rst +++ llvm/trunk/docs/LangRef.rst @@ -3825,6 +3825,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: llvm/trunk/lib/IR/InlineAsm.cpp =================================================================== --- llvm/trunk/lib/IR/InlineAsm.cpp +++ llvm/trunk/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) && "Expected a digit!"); + int N = C - '0'; + assert(N > 0 && "Found a zero letter constraint!"); + ++I; + pCodes->push_back(StringRef(I, N)); + I += N; } else { // Single letter constraint. pCodes->push_back(StringRef(I, 1)); Index: llvm/trunk/lib/Target/AArch64/AArch64AsmPrinter.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ llvm/trunk/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -618,6 +618,8 @@ const TargetRegisterClass *RegClass; if (AArch64::ZPRRegClass.contains(Reg)) { RegClass = &AArch64::ZPRRegClass; + } else if (AArch64::PPRRegClass.contains(Reg)) { + RegClass = &AArch64::PPRRegClass; } else { RegClass = &AArch64::FPR128RegClass; AltName = AArch64::vreg; Index: llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp +++ llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -5837,6 +5837,21 @@ return "r"; } +enum PredicateConstraint { + Upl, + Upa, + Invalid +}; + +PredicateConstraint parsePredicateConstraint(StringRef Constraint) { + PredicateConstraint P = PredicateConstraint::Invalid; + if (Constraint == "Upa") + P = PredicateConstraint::Upa; + if (Constraint == "Upl") + P = PredicateConstraint::Upl; + return P; +} + /// getConstraintType - Given a constraint letter, return the type of /// constraint it is for this target. AArch64TargetLowering::ConstraintType @@ -5866,7 +5881,9 @@ case 'S': // A symbolic address return C_Other; } - } + } else if (parsePredicateConstraint(Constraint) != + PredicateConstraint::Invalid) + return C_RegisterClass; return TargetLowering::getConstraintType(Constraint); } @@ -5897,6 +5914,10 @@ case 'z': weight = CW_Constant; break; + case 'U': + if (parsePredicateConstraint(constraint) != PredicateConstraint::Invalid) + weight = CW_Register; + break; } return weight; } @@ -5941,6 +5962,14 @@ return std::make_pair(0U, &AArch64::ZPR_3bRegClass); break; } + } else { + PredicateConstraint PC = parsePredicateConstraint(Constraint); + if (PC != PredicateConstraint::Invalid) { + assert(VT.isScalableVector()); + bool restricted = (PC == PredicateConstraint::Upl); + 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: llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.cpp +++ llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -2507,6 +2507,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: llvm/trunk/test/CodeGen/AArch64/aarch64-sve-asm.ll =================================================================== --- llvm/trunk/test/CodeGen/AArch64/aarch64-sve-asm.ll +++ llvm/trunk/test/CodeGen/AArch64/aarch64-sve-asm.ll @@ -8,6 +8,7 @@ ; CHECK: [[ARG2:%[0-9]+]]:zpr = COPY $z0 ; CHECK: [[ARG3:%[0-9]+]]:zpr = COPY [[ARG2]] ; CHECK: [[ARG4:%[0-9]+]]:zpr_3b = COPY [[ARG1]] +; CHECK: INLINEASM {{.*}} [[ARG4]] define @test_svadd_i8( %Zn, %Zm) { %1 = tail call asm "add $0.b, $1.b, $2.b", "=w,w,y"( %Zn, %Zm) ret %1 @@ -18,6 +19,7 @@ ; CHECK: [[ARG2:%[0-9]+]]:zpr = COPY $z0 ; CHECK: [[ARG3:%[0-9]+]]:zpr = COPY [[ARG2]] ; CHECK: [[ARG4:%[0-9]+]]:zpr_4b = COPY [[ARG1]] +; CHECK: INLINEASM {{.*}} [[ARG4]] define @test_svsub_i64( %Zn, %Zm) { %1 = tail call asm "sub $0.d, $1.d, $2.d", "=w,w,x"( %Zn, %Zm) ret %1 @@ -28,6 +30,7 @@ ; CHECK: [[ARG2:%[0-9]+]]:zpr = COPY $z0 ; CHECK: [[ARG3:%[0-9]+]]:zpr = COPY [[ARG2]] ; CHECK: [[ARG4:%[0-9]+]]:zpr_3b = COPY [[ARG1]] +; CHECK: INLINEASM {{.*}} [[ARG4]] define @test_svfmul_f16( %Zn, %Zm) { %1 = tail call asm "fmul $0.h, $1.h, $2.h", "=w,w,y"( %Zn, %Zm) ret %1 @@ -38,7 +41,30 @@ ; CHECK: [[ARG2:%[0-9]+]]:zpr = COPY $z0 ; CHECK: [[ARG3:%[0-9]+]]:zpr = COPY [[ARG2]] ; CHECK: [[ARG4:%[0-9]+]]:zpr_4b = COPY [[ARG1]] +; CHECK: INLINEASM {{.*}} [[ARG4]] define @test_svfmul_f( %Zn, %Zm) { %1 = tail call asm "fmul $0.s, $1.s, $2.s", "=w,w,x"( %Zn, %Zm) 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]] +; CHECK: INLINEASM {{.*}} [[ARG4]] +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]] +; CHECK: INLINEASM {{.*}} [[ARG3]] +define @test_incp( %Pg, %Zn) { + %1 = tail call asm "incp $0.s, $1", "=w,@3Upa,0"( %Pg, %Zn) + ret %1 +}