Index: lib/Basic/Targets.cpp =================================================================== --- lib/Basic/Targets.cpp +++ lib/Basic/Targets.cpp @@ -2987,6 +2987,15 @@ // In case the constraint is 'r' we need to return Expression case 'r': return Expression; + case 'Y': + switch (*++I) + { + default: + return ""; + case '0': // First SSE register. + case 'z': + return "xmm0"; + } default: // Default value if there is no constraint for the register return ""; @@ -4314,8 +4323,10 @@ default: return false; case '0': // First SSE register. - case 't': // Any SSE register, when SSE2 is enabled. - case 'i': // Any SSE register, when SSE2 and inter-unit moves enabled. + case 'z': // First SSE register. + case '2': // Any SSE register, when SSE2 is enabled. + case 't': // Any SSE register, when SSE2 is enabled (GCC). + case 'i': // Any SSE register, when SSE2 and inter-unit moves enabled(GCC). case 'm': // Any MMX register, when inter-unit moves enabled. case 'k': // AVX512 arch mask registers: k1-k7. Info.setAllowsRegister(); @@ -4400,9 +4411,12 @@ // 'Ym' is synonymous with 'y'. case 'k': return Size <= 64; - case 'i': + case 'z': // First SSE register xmm0. + case '0': + case '2': // Any SSE register when SSE 2 is enabled (ICC). + case 'i': case 't': - // 'Yi' and 'Yt' are synonymous with 'x' when SSE2 is enabled. + // 'Y2' 'Yi' and 'Yt' are synonymous with 'x' when SSE2 is enabled. if (SSELevel >= AVX512F) return Size <= 512U; else if (SSELevel >= AVX) @@ -4438,6 +4452,11 @@ // the return string. break; case 'k': + case 'm': + case 'i': + case '2': + case 'z': + case '0': // "^" hints llvm that this is a 2 letter constraint. // "Constraint++" is used to promote the string iterator // to the next constraint. Index: lib/CodeGen/TargetInfo.cpp =================================================================== --- lib/CodeGen/TargetInfo.cpp +++ lib/CodeGen/TargetInfo.cpp @@ -845,7 +845,7 @@ static llvm::Type* X86AdjustInlineAsmType(CodeGen::CodeGenFunction &CGF, StringRef Constraint, llvm::Type* Ty) { - if ((Constraint == "y" || Constraint == "&y") && Ty->isVectorTy()) { + if ((Constraint == "y" || Constraint == "&y" || Constraint =="^Ym") && Ty->isVectorTy()) { if (cast(Ty)->getBitWidth() != 64) { // Invalid MMX constraint return nullptr; Index: test/CodeGen/x86-GCC-inline-asm-Y-constraints.c =================================================================== --- test/CodeGen/x86-GCC-inline-asm-Y-constraints.c +++ test/CodeGen/x86-GCC-inline-asm-Y-constraints.c @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -ffreestanding -triple=x86_64-apple-darwin -target-cpu skx %s -emit-llvm -o - | FileCheck %s +#include +// This test is complimented by the .ll test under llvm/test/MC/X86/. +// At this level we can only check if the constarints are passed correctly +// from inline asm to llvm IR. + +// CHECK-LABEL: @f_Ym +void f_Ym(__m64 m) + { + // CHECK: movq $0, %mm1 + // CHECK-SAME: "=^Ym,~{dirflag},~{fpsr},~{flags}" + __asm__ volatile ("movq %0, %%mm1\n\t" + :"=Ym" (m)); +} + +// CHECK-LABEL: f_Yi +void f_Yi(__m128 x, __m128 y, __m128 z) + { + // CHECK: vpaddq + // CHECK-SAME: "=^Yi,^Yi,^Yi,~{dirflag},~{fpsr},~{flags}" + __asm__ volatile ("vpaddq %0, %1, %2\n\t" + :"=Yi" (x) + :"Yi" (y),"Yi"(z)); +} + +// CHECK-LABEL: f_Y2 +void f_Y2(__m128 x, __m128 y, __m128 z) + { + // CHECK: vpaddq + // CHECK-SAME: "=^Y2,^Y2,^Y2,~{dirflag},~{fpsr},~{flags}" + __asm__ volatile ("vpaddq %0, %1, %2\n\t" + :"=Y2" (x) + :"Y2" (y),"Y2"(z)); +} + +// CHECK-LABEL: f_Yz +void f_Yz(__m128 x, __m128 y, __m128 z) + { + // CHECK: vpaddq + // CHECK-SAME: vpaddq + // CHECK-SAME: "=^Yi,=^Yz,^Yi,0,~{dirflag},~{fpsr},~{flags}" + __asm__ volatile ("vpaddq %0,%2,%1\n\t" + "vpaddq %1,%0,%2\n\t" + :"+Yi"(z),"=Yz" (x) + :"Yi" (y) ); +} + +// CHECK-LABEL: f_Y0 +void f_Y0(__m128 x, __m128 y, __m128 z) + { + // CHECK: vpaddq + // CHECK-SAME: "=^Yi,=^Y0,^Yi,0,~{dirflag},~{fpsr},~{flags}" + __asm__ volatile ("vpaddq %0,%2,%1\n\t" + "vpaddq %1,%0,%2\n\t" + :"+Yi"(z),"=Y0" (x) + :"Yi" (y) ); +} \ No newline at end of file