labrinea updated this revision to Diff 355908.
labrinea retitled this revision from "[Clang] Inline assembly support for the 
ACLE type 'data512_t'." to "[Clang][AArch64] Inline assembly support for the 
ACLE type 'data512_t'.".
labrinea edited the summary of this revision.
labrinea added a reviewer: momchil.velikov.
Herald added subscribers: danielkiss, pengfei.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D94098/new/

https://reviews.llvm.org/D94098

Files:
  clang/include/clang/Basic/TargetInfo.h
  clang/lib/Basic/Targets/AArch64.cpp
  clang/lib/Basic/Targets/AArch64.h
  clang/lib/CodeGen/CGStmt.cpp
  clang/test/CodeGen/aarch64-ls64-inline-asm.c

Index: clang/test/CodeGen/aarch64-ls64-inline-asm.c
===================================================================
--- clang/test/CodeGen/aarch64-ls64-inline-asm.c
+++ clang/test/CodeGen/aarch64-ls64-inline-asm.c
@@ -0,0 +1,37 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple aarch64-eabi -target-feature +ls64 -S -emit-llvm -x c %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64_be-eabi -target-feature +ls64 -S -emit-llvm -x c %s -o - | FileCheck %s
+
+struct foo { unsigned long long x[8]; };
+
+// CHECK-LABEL: @load(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[OUTPUT_ADDR:%.*]] = alloca %struct.foo*, align 8
+// CHECK-NEXT:    [[ADDR_ADDR:%.*]] = alloca i8*, align 8
+// CHECK-NEXT:    store %struct.foo* [[OUTPUT:%.*]], %struct.foo** [[OUTPUT_ADDR]], align 8
+// CHECK-NEXT:    store i8* [[ADDR:%.*]], i8** [[ADDR_ADDR]], align 8
+// CHECK-NEXT:    [[TMP0:%.*]] = load %struct.foo*, %struct.foo** [[OUTPUT_ADDR]], align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = load i8*, i8** [[ADDR_ADDR]], align 8
+// CHECK-NEXT:    call void asm sideeffect "ld64b $0,[$1]", "=*r,r,~{memory}"(%struct.foo* [[TMP0]], i8* [[TMP1]]) #[[ATTR1:[0-9]+]], !srcloc !6
+// CHECK-NEXT:    ret void
+//
+void load(struct foo *output, void *addr)
+{
+    __asm__ volatile ("ld64b %0,[%1]" : "=r" (*output) : "r" (addr) : "memory");
+}
+
+// CHECK-LABEL: @store(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[INPUT_ADDR:%.*]] = alloca %struct.foo*, align 8
+// CHECK-NEXT:    [[ADDR_ADDR:%.*]] = alloca i8*, align 8
+// CHECK-NEXT:    store %struct.foo* [[INPUT:%.*]], %struct.foo** [[INPUT_ADDR]], align 8
+// CHECK-NEXT:    store i8* [[ADDR:%.*]], i8** [[ADDR_ADDR]], align 8
+// CHECK-NEXT:    [[TMP0:%.*]] = load %struct.foo*, %struct.foo** [[INPUT_ADDR]], align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = load i8*, i8** [[ADDR_ADDR]], align 8
+// CHECK-NEXT:    call void asm sideeffect "st64b $0,[$1]", "*r,r,~{memory}"(%struct.foo* [[TMP0]], i8* [[TMP1]]) #[[ATTR1]], !srcloc !7
+// CHECK-NEXT:    ret void
+//
+void store(const struct foo *input, void *addr)
+{
+    __asm__ volatile ("st64b %0,[%1]" : : "r" (*input), "r" (addr) : "memory" );
+}
Index: clang/lib/CodeGen/CGStmt.cpp
===================================================================
--- clang/lib/CodeGen/CGStmt.cpp
+++ clang/lib/CodeGen/CGStmt.cpp
@@ -2287,15 +2287,25 @@
     // by-value.  If this is a memory result, return the value by-reference.
     bool isScalarizableAggregate =
         hasAggregateEvaluationKind(OutExpr->getType());
-    if (!Info.allowsMemory() && (hasScalarEvaluationKind(OutExpr->getType()) ||
-                                 isScalarizableAggregate)) {
+
+    unsigned Size = getContext().getTypeSize(OutExpr->getType());
+
+    // If this is a register output but the asm operand is of aggregate
+    // type, then make the inline asm return it by-reference and let
+    // the target deal with it when possible.
+    bool byRef = Info.allowsRegister() && isScalarizableAggregate &&
+        getTarget().canStoreAggregateOperandInRegister(Size);
+
+    bool byVal = !Info.allowsMemory() &&
+       (hasScalarEvaluationKind(OutExpr->getType()) || isScalarizableAggregate);
+
+    if (byVal && !byRef) {
       Constraints += "=" + OutputConstraint;
       ResultRegQualTys.push_back(OutExpr->getType());
       ResultRegDests.push_back(Dest);
       ResultTruncRegTypes.push_back(ConvertTypeForMem(OutExpr->getType()));
       if (Info.allowsRegister() && isScalarizableAggregate) {
         ResultTypeRequiresCast.push_back(true);
-        unsigned Size = getContext().getTypeSize(OutExpr->getType());
         llvm::Type *ConvTy = llvm::IntegerType::get(getLLVMContext(), Size);
         ResultRegTypes.push_back(ConvTy);
       } else {
Index: clang/lib/Basic/Targets/AArch64.h
===================================================================
--- clang/lib/Basic/Targets/AArch64.h
+++ clang/lib/Basic/Targets/AArch64.h
@@ -141,6 +141,10 @@
   bool hasInt128Type() const override;
 
   bool hasExtIntType() const override { return true; }
+
+  bool canStoreAggregateOperandInRegister(unsigned size) const override {
+    return size == 512 && HasLS64;
+  }
 };
 
 class LLVM_LIBRARY_VISIBILITY AArch64leTargetInfo : public AArch64TargetInfo {
Index: clang/lib/Basic/Targets/AArch64.cpp
===================================================================
--- clang/lib/Basic/Targets/AArch64.cpp
+++ clang/lib/Basic/Targets/AArch64.cpp
@@ -751,6 +751,9 @@
       if (Size == 64)
         return true;
 
+      if (Size == 512)
+        return HasLS64;
+
       SuggestedModifier = "w";
       return false;
     }
Index: clang/include/clang/Basic/TargetInfo.h
===================================================================
--- clang/include/clang/Basic/TargetInfo.h
+++ clang/include/clang/Basic/TargetInfo.h
@@ -585,6 +585,12 @@
     return false;
   }
 
+  /// Determine whether an aggregate output operand of inline assembly is
+  /// compatible with register constraints on this target.
+  virtual bool canStoreAggregateOperandInRegister(unsigned size) const {
+    return false;
+  }
+
   /// Determine whether _Float16 is supported on this target.
   virtual bool hasLegalHalfType() const { return HasLegalHalfType; }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to