"$f19", "$f20", "$f21", "$f22", "$f23", "$f24", "$f25", "$f26", "$f27",
"$f28", "$f29", "$f30", "$f31",
// Condition flag registers.
- "$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"};
+ "$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5", "$fcc6", "$fcc7"};
return llvm::ArrayRef(GCCRegNames);
}
+++ /dev/null
-// 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");
-}
+++ /dev/null
-// 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));
-}
+++ /dev/null
-// 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));
-}
+++ /dev/null
-// 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");
-}
+++ /dev/null
-// 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));
-}
+++ /dev/null
-// 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));
-}
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.
}
}
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);
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;
// 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") ||
- Constraint.startswith("{$vr") || Constraint.startswith("{$xr")) {
+ if (Constraint.startswith("{$r") || Constraint.startswith("{$f")) {
bool IsFP = Constraint[2] == 'f';
std::pair<StringRef, StringRef> Temp = Constraint.split('$');
std::pair<unsigned, const TargetRegisterClass *> R;
+++ /dev/null
-; 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
-}
+++ /dev/null
-; 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
-}
+++ /dev/null
-; 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
-}
+++ /dev/null
-; 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
-}