mirror of https://github.com/microsoft/clang.git
[Clang][x86][Inline Asm] support for GCC style inline asm - Y<x> constraints
This patch is intended to enable the use of basic double letter constraints used in GCC extended inline asm {Yi Y2 Yz Y0 Ym Yt}. Supersedes D35205 llvm counterpart: D36369 Differential Revision: https://reviews.llvm.org/D36371 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@311643 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
deada28d59
commit
5cce8b32d1
|
@ -1386,7 +1386,9 @@ bool X86TargetInfo::validateAsmConstraint(
|
||||||
switch (*Name) {
|
switch (*Name) {
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
case 'z':
|
||||||
case '0': // First SSE register.
|
case '0': // First SSE register.
|
||||||
|
case '2':
|
||||||
case 't': // Any SSE register, when SSE2 is enabled.
|
case 't': // Any SSE register, when SSE2 is enabled.
|
||||||
case 'i': // Any SSE register, when SSE2 and inter-unit moves enabled.
|
case 'i': // Any SSE register, when SSE2 and inter-unit moves enabled.
|
||||||
case 'm': // Any MMX register, when inter-unit moves enabled.
|
case 'm': // Any MMX register, when inter-unit moves enabled.
|
||||||
|
@ -1455,6 +1457,29 @@ bool X86TargetInfo::validateOperandSize(StringRef Constraint,
|
||||||
case 't':
|
case 't':
|
||||||
case 'u':
|
case 'u':
|
||||||
return Size <= 128;
|
return Size <= 128;
|
||||||
|
case 'Y':
|
||||||
|
// 'Y' is the first character for several 2-character constraints.
|
||||||
|
switch (Constraint[1]) {
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
case 'm':
|
||||||
|
// 'Ym' is synonymous with 'y'.
|
||||||
|
case 'k':
|
||||||
|
return Size <= 64;
|
||||||
|
case 'z':
|
||||||
|
case '0':
|
||||||
|
// XMM0
|
||||||
|
if (SSELevel >= SSE1)
|
||||||
|
return Size <= 128U;
|
||||||
|
return false;
|
||||||
|
case 'i':
|
||||||
|
case 't':
|
||||||
|
case '2':
|
||||||
|
// 'Yi','Yt','Y2' are synonymous with 'x' when SSE2 is enabled.
|
||||||
|
if (SSELevel < SSE2)
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'v':
|
case 'v':
|
||||||
case 'x':
|
case 'x':
|
||||||
if (SSELevel >= AVX512F)
|
if (SSELevel >= AVX512F)
|
||||||
|
@ -1464,24 +1489,7 @@ bool X86TargetInfo::validateOperandSize(StringRef Constraint,
|
||||||
// 256-bit ymm registers can be used if target supports AVX.
|
// 256-bit ymm registers can be used if target supports AVX.
|
||||||
return Size <= 256U;
|
return Size <= 256U;
|
||||||
return Size <= 128U;
|
return Size <= 128U;
|
||||||
case 'Y':
|
|
||||||
// 'Y' is the first character for several 2-character constraints.
|
|
||||||
switch (Constraint[1]) {
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
case 'm':
|
|
||||||
// 'Ym' is synonymous with 'y'.
|
|
||||||
case 'k':
|
|
||||||
return Size <= 64;
|
|
||||||
case 'i':
|
|
||||||
case 't':
|
|
||||||
// 'Yi' and 'Yt' are synonymous with 'x' when SSE2 is enabled.
|
|
||||||
if (SSELevel >= AVX512F)
|
|
||||||
return Size <= 512U;
|
|
||||||
else if (SSELevel >= AVX)
|
|
||||||
return Size <= 256U;
|
|
||||||
return SSELevel >= SSE2 && Size <= 128U;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -1515,6 +1523,12 @@ std::string X86TargetInfo::convertConstraint(const char *&Constraint) const {
|
||||||
// the return string.
|
// the return string.
|
||||||
break;
|
break;
|
||||||
case 'k':
|
case 'k':
|
||||||
|
case 'm':
|
||||||
|
case 'i':
|
||||||
|
case 't':
|
||||||
|
case 'z':
|
||||||
|
case '0':
|
||||||
|
case '2':
|
||||||
// "^" hints llvm that this is a 2 letter constraint.
|
// "^" hints llvm that this is a 2 letter constraint.
|
||||||
// "Constraint++" is used to promote the string iterator
|
// "Constraint++" is used to promote the string iterator
|
||||||
// to the next constraint.
|
// to the next constraint.
|
||||||
|
|
|
@ -437,9 +437,12 @@ public:
|
||||||
// In case the constraint is 'r' we need to return Expression
|
// In case the constraint is 'r' we need to return Expression
|
||||||
case 'r':
|
case 'r':
|
||||||
return Expression;
|
return Expression;
|
||||||
|
// Double letters Y<x> constraints
|
||||||
|
case 'Y':
|
||||||
|
if ((++I != E) && ((*I == '0') || (*I == 'z')))
|
||||||
|
return "xmm0";
|
||||||
default:
|
default:
|
||||||
// Default value if there is no constraint for the register
|
break;
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "clang/CodeGen/SwiftCallingConv.h"
|
#include "clang/CodeGen/SwiftCallingConv.h"
|
||||||
#include "clang/Frontend/CodeGenOptions.h"
|
#include "clang/Frontend/CodeGenOptions.h"
|
||||||
#include "llvm/ADT/StringExtras.h"
|
#include "llvm/ADT/StringExtras.h"
|
||||||
|
#include "llvm/ADT/StringSwitch.h"
|
||||||
#include "llvm/ADT/Triple.h"
|
#include "llvm/ADT/Triple.h"
|
||||||
#include "llvm/IR/DataLayout.h"
|
#include "llvm/IR/DataLayout.h"
|
||||||
#include "llvm/IR/Type.h"
|
#include "llvm/IR/Type.h"
|
||||||
|
@ -870,7 +871,10 @@ bool IsX86_MMXType(llvm::Type *IRType) {
|
||||||
static llvm::Type* X86AdjustInlineAsmType(CodeGen::CodeGenFunction &CGF,
|
static llvm::Type* X86AdjustInlineAsmType(CodeGen::CodeGenFunction &CGF,
|
||||||
StringRef Constraint,
|
StringRef Constraint,
|
||||||
llvm::Type* Ty) {
|
llvm::Type* Ty) {
|
||||||
if ((Constraint == "y" || Constraint == "&y") && Ty->isVectorTy()) {
|
bool IsMMXCons = llvm::StringSwitch<bool>(Constraint)
|
||||||
|
.Cases("y", "&y", "^Ym", true)
|
||||||
|
.Default(false);
|
||||||
|
if (IsMMXCons && Ty->isVectorTy()) {
|
||||||
if (cast<llvm::VectorType>(Ty)->getBitWidth() != 64) {
|
if (cast<llvm::VectorType>(Ty)->getBitWidth() != 64) {
|
||||||
// Invalid MMX constraint
|
// Invalid MMX constraint
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
// RUN: %clang_cc1 -ffreestanding -triple=x86_64-apple-darwin -target-cpu skx %s -emit-llvm -o - | FileCheck %s
|
||||||
|
#include <xmmintrin.h>
|
||||||
|
// 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_Yt
|
||||||
|
void f_Yt(__m128 x, __m128 y, __m128 z)
|
||||||
|
{
|
||||||
|
// CHECK: vpaddq
|
||||||
|
// CHECK-SAME: "=^Yt,^Yt,^Yt,~{dirflag},~{fpsr},~{flags}"
|
||||||
|
__asm__ volatile ("vpaddq %0, %1, %2\n\t"
|
||||||
|
:"=Yt" (x)
|
||||||
|
:"Yt" (y),"Yt"(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) );
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue