Author: chenli
Date: 2023-07-25T09:02:29+08:00
New Revision: d25c79dc70008b835312e5cc7ef48b199fda3165

URL: 
https://github.com/llvm/llvm-project/commit/d25c79dc70008b835312e5cc7ef48b199fda3165
DIFF: 
https://github.com/llvm/llvm-project/commit/d25c79dc70008b835312e5cc7ef48b199fda3165.diff

LOG: [LoongArch] Support InlineAsm for LSX and LASX

The author of the following files is licongtian <licongt...@loongson.cn>:
- clang/lib/Basic/Targets/LoongArch.cpp
- llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
- llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp

The files mentioned above implement InlineAsm for LSX and LASX as follows:
- Enable clang parsing LSX/LASX register name, such as $vr0.
- Support the case which operand type is 128bit or 256bit when the
  constraints is 'f'.
- Support the way of specifying LSX/LASX register by using constraint,
  such as "={$xr0}".
- Support the operand modifiers 'u' and 'w'.
- Support and legalize the data types and register classes involved in
  LSX/LASX in the lowering process.

Reviewed By: xen0n, SixWeining

Differential Revision: https://reviews.llvm.org/D154931

Added: 
    clang/test/CodeGen/LoongArch/lasx/inline-asm-gcc-regs-error.c
    clang/test/CodeGen/LoongArch/lasx/inline-asm-gcc-regs.c
    clang/test/CodeGen/LoongArch/lasx/inline-asm-operand-modifier.c
    clang/test/CodeGen/LoongArch/lsx/inline-asm-gcc-regs-error.c
    clang/test/CodeGen/LoongArch/lsx/inline-asm-gcc-regs.c
    clang/test/CodeGen/LoongArch/lsx/inline-asm-operand-modifier.c
    llvm/test/CodeGen/LoongArch/lasx/inline-asm-operand-modifier.ll
    llvm/test/CodeGen/LoongArch/lasx/inline-asm-reg-names.ll
    llvm/test/CodeGen/LoongArch/lsx/inline-asm-operand-modifier.ll
    llvm/test/CodeGen/LoongArch/lsx/inline-asm-reg-names.ll

Modified: 
    clang/lib/Basic/Targets/LoongArch.cpp
    llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
    llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Basic/Targets/LoongArch.cpp 
b/clang/lib/Basic/Targets/LoongArch.cpp
index 9af871895f7429..6958479cd7c42d 100644
--- a/clang/lib/Basic/Targets/LoongArch.cpp
+++ b/clang/lib/Basic/Targets/LoongArch.cpp
@@ -33,7 +33,17 @@ ArrayRef<const char *> LoongArchTargetInfo::getGCCRegNames() 
const {
       "$f19", "$f20", "$f21", "$f22", "$f23", "$f24", "$f25", "$f26", "$f27",
       "$f28", "$f29", "$f30", "$f31",
       // Condition flag registers.
-      "$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5", "$fcc6", "$fcc7"};
+      "$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5", "$fcc6", "$fcc7",
+      // 128-bit vector registers.
+      "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6", "$vr7", "$vr8",
+      "$vr9", "$vr10", "$vr11", "$vr12", "$vr13", "$vr14", "$vr15", "$vr16",
+      "$vr17", "$vr18", "$vr19", "$vr20", "$vr21", "$vr22", "$vr23", "$vr24",
+      "$vr25", "$vr26", "$vr27", "$vr28", "$vr29", "$vr30", "$vr31",
+      // 256-bit vector registers.
+      "$xr0", "$xr1", "$xr2", "$xr3", "$xr4", "$xr5", "$xr6", "$xr7", "$xr8",
+      "$xr9", "$xr10", "$xr11", "$xr12", "$xr13", "$xr14", "$xr15", "$xr16",
+      "$xr17", "$xr18", "$xr19", "$xr20", "$xr21", "$xr22", "$xr23", "$xr24",
+      "$xr25", "$xr26", "$xr27", "$xr28", "$xr29", "$xr30", "$xr31"};
   return llvm::ArrayRef(GCCRegNames);
 }
 

diff  --git a/clang/test/CodeGen/LoongArch/lasx/inline-asm-gcc-regs-error.c 
b/clang/test/CodeGen/LoongArch/lasx/inline-asm-gcc-regs-error.c
new file mode 100644
index 00000000000000..1fd602574b8e8d
--- /dev/null
+++ b/clang/test/CodeGen/LoongArch/lasx/inline-asm-gcc-regs-error.c
@@ -0,0 +1,10 @@
+// RUN: not %clang_cc1 -triple loongarch64 -emit-llvm -O2 %s 2>&1 -o - | 
FileCheck %s
+
+typedef signed char v32i8 __attribute__((vector_size(32), aligned(32)));
+
+void test() {
+// CHECK: :[[#@LINE+1]]:28: error: unknown register name 'xr0' in asm
+    register v32i8 p0 asm ("xr0");
+// CHECK: :[[#@LINE+1]]:29: error: unknown register name '$xr32' in asm
+    register v32i8 p32 asm ("$xr32");
+}

diff  --git a/clang/test/CodeGen/LoongArch/lasx/inline-asm-gcc-regs.c 
b/clang/test/CodeGen/LoongArch/lasx/inline-asm-gcc-regs.c
new file mode 100644
index 00000000000000..ed1a9660a06c9f
--- /dev/null
+++ b/clang/test/CodeGen/LoongArch/lasx/inline-asm-gcc-regs.c
@@ -0,0 +1,36 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --filter "^define |tail call"
+// RUN: %clang_cc1 -triple loongarch64 -emit-llvm -O2 %s -o - | FileCheck %s
+
+typedef signed char v32i8 __attribute__((vector_size(32), aligned(32)));
+
+// CHECK-LABEL: @test_xr0(
+// CHECK:    tail call void asm sideeffect "", "{$xr0}"(<32 x i8> undef) 
#[[ATTR1:[0-9]+]], !srcloc !2
+//
+void test_xr0() {
+    register v32i8 a asm ("$xr0");
+    asm ("" :: "f"(a));
+}
+
+// CHECK-LABEL: @test_xr7(
+// CHECK:    tail call void asm sideeffect "", "{$xr7}"(<32 x i8> undef) 
#[[ATTR1]], !srcloc !3
+//
+void test_xr7() {
+    register v32i8 a asm ("$xr7");
+    asm ("" :: "f"(a));
+}
+
+// CHECK-LABEL: @test_xr15(
+// CHECK:    tail call void asm sideeffect "", "{$xr15}"(<32 x i8> undef) 
#[[ATTR1]], !srcloc !4
+//
+void test_xr15() {
+    register v32i8 a asm ("$xr15");
+    asm ("" :: "f"(a));
+}
+
+// CHECK-LABEL: @test_xr31(
+// CHECK:    tail call void asm sideeffect "", "{$xr31}"(<32 x i8> undef) 
#[[ATTR1]], !srcloc !5
+//
+void test_xr31() {
+    register v32i8 a asm ("$xr31");
+    asm ("" :: "f"(a));
+}

diff  --git a/clang/test/CodeGen/LoongArch/lasx/inline-asm-operand-modifier.c 
b/clang/test/CodeGen/LoongArch/lasx/inline-asm-operand-modifier.c
new file mode 100644
index 00000000000000..a5cc8798fd66b8
--- /dev/null
+++ b/clang/test/CodeGen/LoongArch/lasx/inline-asm-operand-modifier.c
@@ -0,0 +1,15 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --version 2
+// RUN: %clang_cc1 -triple loongarch64 -emit-llvm -O2 %s -o - | FileCheck %s
+
+typedef long long v4i64 __attribute__ ((vector_size(32), aligned(32)));
+
+// CHECK-LABEL: define dso_local void @test_u
+// CHECK-SAME: () local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call <4 x i64> asm sideeffect "xvldi 
${0:u}, 1", "=f"() #[[ATTR1:[0-9]+]], !srcloc !2
+// CHECK-NEXT:    ret void
+//
+void test_u() {
+  v4i64 v4i64_r;
+  asm volatile ("xvldi %u0, 1" : "=f" (v4i64_r));
+}

diff  --git a/clang/test/CodeGen/LoongArch/lsx/inline-asm-gcc-regs-error.c 
b/clang/test/CodeGen/LoongArch/lsx/inline-asm-gcc-regs-error.c
new file mode 100644
index 00000000000000..54132307e93f48
--- /dev/null
+++ b/clang/test/CodeGen/LoongArch/lsx/inline-asm-gcc-regs-error.c
@@ -0,0 +1,10 @@
+// RUN: not %clang_cc1 -triple loongarch64 -emit-llvm -O2 %s 2>&1 -o - | 
FileCheck %s
+
+typedef signed char v16i8 __attribute__((vector_size(16), aligned(16)));
+
+void test() {
+// CHECK: :[[#@LINE+1]]:28: error: unknown register name 'vr0' in asm
+    register v16i8 p0 asm ("vr0");
+// CHECK: :[[#@LINE+1]]:29: error: unknown register name '$vr32' in asm
+    register v16i8 p32 asm ("$vr32");
+}

diff  --git a/clang/test/CodeGen/LoongArch/lsx/inline-asm-gcc-regs.c 
b/clang/test/CodeGen/LoongArch/lsx/inline-asm-gcc-regs.c
new file mode 100644
index 00000000000000..b05b1c8c15fae2
--- /dev/null
+++ b/clang/test/CodeGen/LoongArch/lsx/inline-asm-gcc-regs.c
@@ -0,0 +1,36 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --filter "^define |tail call"
+// RUN: %clang_cc1 -triple loongarch64 -emit-llvm -O2 %s -o - | FileCheck %s
+
+typedef signed char v16i8 __attribute__((vector_size(16), aligned(16)));
+
+// CHECK-LABEL: @test_vr0(
+// CHECK:    tail call void asm sideeffect "", "{$vr0}"(<16 x i8> undef) 
#[[ATTR1:[0-9]+]], !srcloc !2
+//
+void test_vr0() {
+    register v16i8 a asm ("$vr0");
+    asm ("" :: "f"(a));
+}
+
+// CHECK-LABEL: @test_vr7(
+// CHECK:    tail call void asm sideeffect "", "{$vr7}"(<16 x i8> undef) 
#[[ATTR1]], !srcloc !3
+//
+void test_vr7() {
+    register v16i8 a asm ("$vr7");
+    asm ("" :: "f"(a));
+}
+
+// CHECK-LABEL: @test_vr15(
+// CHECK:    tail call void asm sideeffect "", "{$vr15}"(<16 x i8> undef) 
#[[ATTR1]], !srcloc !4
+//
+void test_vr15() {
+    register v16i8 a asm ("$vr15");
+    asm ("" :: "f"(a));
+}
+
+// CHECK-LABEL: @test_vr31(
+// CHECK:    tail call void asm sideeffect "", "{$vr31}"(<16 x i8> undef) 
#[[ATTR1]], !srcloc !5
+//
+void test_vr31() {
+    register v16i8 a asm ("$vr31");
+    asm ("" :: "f"(a));
+}

diff  --git a/clang/test/CodeGen/LoongArch/lsx/inline-asm-operand-modifier.c 
b/clang/test/CodeGen/LoongArch/lsx/inline-asm-operand-modifier.c
new file mode 100644
index 00000000000000..5e0fae984134ef
--- /dev/null
+++ b/clang/test/CodeGen/LoongArch/lsx/inline-asm-operand-modifier.c
@@ -0,0 +1,15 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --version 2
+// RUN: %clang_cc1 -triple loongarch64 -emit-llvm -O2 %s -o - | FileCheck %s
+
+typedef long long v2i64 __attribute__ ((vector_size(16), aligned(16)));
+
+// CHECK-LABEL: define dso_local void @test_w
+// CHECK-SAME: () local_unnamed_addr #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call <2 x i64> asm sideeffect "vldi 
${0:w}, 1", "=f"() #[[ATTR1:[0-9]+]], !srcloc !2
+// CHECK-NEXT:    ret void
+//
+void test_w() {
+  v2i64 v2i64_r;
+  asm volatile ("vldi %w0, 1" : "=f" (v2i64_r));
+}

diff  --git a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp 
b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
index 5cf0673df69a68..27979a830b10e6 100644
--- a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
@@ -75,6 +75,20 @@ bool LoongArchAsmPrinter::PrintAsmOperand(const MachineInstr 
*MI, unsigned OpNo,
         return false;
       }
       break;
+    case 'w': // Print LSX registers.
+      if (MO.getReg().id() >= LoongArch::VR0 &&
+          MO.getReg().id() <= LoongArch::VR31)
+        break;
+      // The modifier is 'w' but the operand is not an LSX register; Report an
+      // unknown operand error.
+      return true;
+    case 'u': // Print LASX registers.
+      if (MO.getReg().id() >= LoongArch::XR0 &&
+          MO.getReg().id() <= LoongArch::XR31)
+        break;
+      // The modifier is 'u' but the operand is not an LASX register; Report an
+      // unknown operand error.
+      return true;
       // TODO: handle other extra codes if any.
     }
   }

diff  --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp 
b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 948716606f030b..b6e92106a9f3f7 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -53,6 +53,14 @@ LoongArchTargetLowering::LoongArchTargetLowering(const 
TargetMachine &TM,
     addRegisterClass(MVT::f32, &LoongArch::FPR32RegClass);
   if (Subtarget.hasBasicD())
     addRegisterClass(MVT::f64, &LoongArch::FPR64RegClass);
+  if (Subtarget.hasExtLSX())
+    for (auto VT : {MVT::v4f32, MVT::v2f64, MVT::v16i8, MVT::v8i16, MVT::v4i32,
+                    MVT::v2i64})
+      addRegisterClass(VT, &LoongArch::LSX128RegClass);
+  if (Subtarget.hasExtLASX())
+    for (auto VT : {MVT::v8f32, MVT::v4f64, MVT::v32i8, MVT::v16i16, 
MVT::v8i32,
+                    MVT::v4i64})
+      addRegisterClass(VT, &LoongArch::LASX256RegClass);
 
   setLoadExtAction({ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD}, GRLenVT,
                    MVT::i1, Promote);
@@ -3048,6 +3056,12 @@ LoongArchTargetLowering::getRegForInlineAsmConstraint(
         return std::make_pair(0U, &LoongArch::FPR32RegClass);
       if (Subtarget.hasBasicD() && VT == MVT::f64)
         return std::make_pair(0U, &LoongArch::FPR64RegClass);
+      if (Subtarget.hasExtLSX() &&
+          TRI->isTypeLegalForClass(LoongArch::LSX128RegClass, VT))
+        return std::make_pair(0U, &LoongArch::LSX128RegClass);
+      if (Subtarget.hasExtLASX() &&
+          TRI->isTypeLegalForClass(LoongArch::LASX256RegClass, VT))
+        return std::make_pair(0U, &LoongArch::LASX256RegClass);
       break;
     default:
       break;
@@ -3065,7 +3079,8 @@ LoongArchTargetLowering::getRegForInlineAsmConstraint(
   // decode the usage of register name aliases into their official names. And
   // AFAIK, the not yet upstreamed `rustc` for LoongArch will always use
   // official register names.
-  if (Constraint.startswith("{$r") || Constraint.startswith("{$f")) {
+  if (Constraint.startswith("{$r") || Constraint.startswith("{$f") ||
+      Constraint.startswith("{$vr") || Constraint.startswith("{$xr")) {
     bool IsFP = Constraint[2] == 'f';
     std::pair<StringRef, StringRef> Temp = Constraint.split('$');
     std::pair<unsigned, const TargetRegisterClass *> R;

diff  --git a/llvm/test/CodeGen/LoongArch/lasx/inline-asm-operand-modifier.ll 
b/llvm/test/CodeGen/LoongArch/lasx/inline-asm-operand-modifier.ll
new file mode 100644
index 00000000000000..201e34c8b5ae0d
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/lasx/inline-asm-operand-modifier.ll
@@ -0,0 +1,14 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 
UTC_ARGS: --version 2
+; RUN: llc --mtriple=loongarch64 --mattr=+lasx < %s | FileCheck %s
+
+define void @test_u() nounwind {
+; CHECK-LABEL: test_u:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    #APP
+; CHECK-NEXT:    xvldi $xr0, 1
+; CHECK-NEXT:    #NO_APP
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call <4 x i64> asm sideeffect "xvldi ${0:u}, 1", "=f"()
+  ret void
+}

diff  --git a/llvm/test/CodeGen/LoongArch/lasx/inline-asm-reg-names.ll 
b/llvm/test/CodeGen/LoongArch/lasx/inline-asm-reg-names.ll
new file mode 100644
index 00000000000000..dd400ecfcf91d7
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/lasx/inline-asm-reg-names.ll
@@ -0,0 +1,58 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 
UTC_ARGS: --version 2
+; RUN: llc --mtriple=loongarch64 --mattr=+lasx < %s | FileCheck %s
+
+define void @register_xr1() nounwind {
+; CHECK-LABEL: register_xr1:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    #APP
+; CHECK-NEXT:    xvldi $xr1, 1
+; CHECK-NEXT:    #NO_APP
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call <4 x i64> asm sideeffect "xvldi ${0:u}, 1", "={$xr1}"()
+  ret void
+}
+
+define void @register_xr7() nounwind {
+; CHECK-LABEL: register_xr7:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    #APP
+; CHECK-NEXT:    xvldi $xr7, 1
+; CHECK-NEXT:    #NO_APP
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call <4 x i64> asm sideeffect "xvldi ${0:u}, 1", "={$xr7}"()
+  ret void
+}
+
+define void @register_xr23() nounwind {
+; CHECK-LABEL: register_xr23:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    #APP
+; CHECK-NEXT:    xvldi $xr23, 1
+; CHECK-NEXT:    #NO_APP
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call <4 x i64> asm sideeffect "xvldi ${0:u}, 1", "={$xr23}"()
+  ret void
+}
+
+;; The lower 64-bit of the vector register '$xr31' is overlapped with
+;; the floating-point register '$f31' ('$fs7'). And '$f31' ('$fs7')
+;; is a callee-saved register which is preserved across calls.
+;; That's why the fst.d and fld.d instructions are emitted.
+define void @register_xr31() nounwind {
+; CHECK-LABEL: register_xr31:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addi.d $sp, $sp, -16
+; CHECK-NEXT:    fst.d $fs7, $sp, 8 # 8-byte Folded Spill
+; CHECK-NEXT:    #APP
+; CHECK-NEXT:    xvldi $xr31, 1
+; CHECK-NEXT:    #NO_APP
+; CHECK-NEXT:    fld.d $fs7, $sp, 8 # 8-byte Folded Reload
+; CHECK-NEXT:    addi.d $sp, $sp, 16
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call <4 x i64> asm sideeffect "xvldi ${0:u}, 1", "={$xr31}"()
+  ret void
+}

diff  --git a/llvm/test/CodeGen/LoongArch/lsx/inline-asm-operand-modifier.ll 
b/llvm/test/CodeGen/LoongArch/lsx/inline-asm-operand-modifier.ll
new file mode 100644
index 00000000000000..c46e624ddaa82a
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/lsx/inline-asm-operand-modifier.ll
@@ -0,0 +1,14 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 
UTC_ARGS: --version 2
+; RUN: llc --mtriple=loongarch64 --mattr=+lsx < %s | FileCheck %s
+
+define void @test_w() nounwind {
+; CHECK-LABEL: test_w:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    #APP
+; CHECK-NEXT:    vldi $vr0, 1
+; CHECK-NEXT:    #NO_APP
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call <2 x i64> asm sideeffect "vldi ${0:w}, 1", "=f"()
+  ret void
+}

diff  --git a/llvm/test/CodeGen/LoongArch/lsx/inline-asm-reg-names.ll 
b/llvm/test/CodeGen/LoongArch/lsx/inline-asm-reg-names.ll
new file mode 100644
index 00000000000000..ceea3621be2f69
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/lsx/inline-asm-reg-names.ll
@@ -0,0 +1,58 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 
UTC_ARGS: --version 2
+; RUN: llc --mtriple=loongarch64 --mattr=+lsx < %s | FileCheck %s
+
+define void @register_vr1() nounwind {
+; CHECK-LABEL: register_vr1:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    #APP
+; CHECK-NEXT:    vldi $vr1, 1
+; CHECK-NEXT:    #NO_APP
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call <2 x i64> asm sideeffect "vldi ${0:w}, 1", "={$vr1}"()
+  ret void
+}
+
+define void @register_vr7() nounwind {
+; CHECK-LABEL: register_vr7:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    #APP
+; CHECK-NEXT:    vldi $vr7, 1
+; CHECK-NEXT:    #NO_APP
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call <2 x i64> asm sideeffect "vldi ${0:w}, 1", "={$vr7}"()
+  ret void
+}
+
+define void @register_vr23() nounwind {
+; CHECK-LABEL: register_vr23:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    #APP
+; CHECK-NEXT:    vldi $vr23, 1
+; CHECK-NEXT:    #NO_APP
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call <2 x i64> asm sideeffect "vldi ${0:w}, 1", "={$vr23}"()
+  ret void
+}
+
+;; The lower half of the vector register '$vr31' is overlapped with
+;; the floating-point register '$f31'. And '$f31' is a callee-saved
+;; register which is preserved across calls. That's why the
+;; fst.d and fld.d instructions are emitted.
+define void @register_vr31() nounwind {
+; CHECK-LABEL: register_vr31:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    addi.d $sp, $sp, -16
+; CHECK-NEXT:    fst.d $fs7, $sp, 8 # 8-byte Folded Spill
+; CHECK-NEXT:    #APP
+; CHECK-NEXT:    vldi $vr31, 1
+; CHECK-NEXT:    #NO_APP
+; CHECK-NEXT:    fld.d $fs7, $sp, 8 # 8-byte Folded Reload
+; CHECK-NEXT:    addi.d $sp, $sp, 16
+; CHECK-NEXT:    ret
+entry:
+  %0 = tail call <2 x i64> asm sideeffect "vldi ${0:w}, 1", "={$vr31}"()
+  ret void
+}


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to