diff --git a/clang/lib/Basic/Targets/LoongArch.cpp b/clang/lib/Basic/Targets/LoongArch.cpp --- a/clang/lib/Basic/Targets/LoongArch.cpp +++ b/clang/lib/Basic/Targets/LoongArch.cpp @@ -31,7 +31,9 @@ "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", "$f24", "$f25", "$f26", "$f27", - "$f28", "$f29", "$f30", "$f31"}; + "$f28", "$f29", "$f30", "$f31", + // Condition flag registers. + "$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5", "$fcc6", "$fcc7"}; return llvm::ArrayRef(GCCRegNames); } diff --git a/clang/test/CodeGen/LoongArch/inline-asm-gcc-regs-error.c b/clang/test/CodeGen/LoongArch/inline-asm-gcc-regs-error.c --- a/clang/test/CodeGen/LoongArch/inline-asm-gcc-regs-error.c +++ b/clang/test/CodeGen/LoongArch/inline-asm-gcc-regs-error.c @@ -19,4 +19,6 @@ register float a5 asm ("f0"); // CHECK: :[[#@LINE+1]]:26: error: unknown register name 'fa0' in asm register float a6 asm ("fa0"); +// CHECK: :[[#@LINE+1]]:15: error: unknown register name 'fcc0' in asm + asm ("" ::: "fcc0"); } diff --git a/clang/test/CodeGen/LoongArch/inline-asm-gcc-regs.c b/clang/test/CodeGen/LoongArch/inline-asm-gcc-regs.c --- a/clang/test/CodeGen/LoongArch/inline-asm-gcc-regs.c +++ b/clang/test/CodeGen/LoongArch/inline-asm-gcc-regs.c @@ -100,3 +100,11 @@ register float a asm ("$fs2"); asm ("" :: "f" (a)); } + +// CHECK-LABEL: @test_fcc +// CHECK: call void asm sideeffect "", "~{$fcc0}"() +// CHECK: call void asm sideeffect "", "~{$fcc7}"() +void test_fcc() { + asm ("" ::: "$fcc0"); + asm ("" ::: "$fcc7"); +} diff --git a/llvm/test/CodeGen/LoongArch/inline-asm-clobbers-fcc.mir b/llvm/test/CodeGen/LoongArch/inline-asm-clobbers-fcc.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/LoongArch/inline-asm-clobbers-fcc.mir @@ -0,0 +1,33 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc --mtriple=loongarch64 --mattr=+d --run-pass=greedy %s -o - | FileCheck %s + +## Check that fcc register clobbered by inlineasm is correctly saved by examing +## a pair of pseudos (PseudoST_CFR and PseudoLD_CFR) are generated before and +## after the INLINEASM. +... +--- +name: test +tracksRegLiveness: true +body: | + bb.0.entry: + liveins: $f0_64, $f1_64 + + ; CHECK-LABEL: name: test + ; CHECK: liveins: $f0_64, $f1_64 + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $f1_64 + ; CHECK-NEXT: [[COPY1:%[0-9]+]]:fpr64 = COPY $f0_64 + ; CHECK-NEXT: [[FCMP_CLT_D:%[0-9]+]]:cfr = FCMP_CLT_D [[COPY]], [[COPY1]] + ; CHECK-NEXT: PseudoST_CFR [[FCMP_CLT_D]], %stack.0, 0 :: (store (s64) into %stack.0) + ; CHECK-NEXT: INLINEASM &nop, 1 /* sideeffect attdialect */, 12 /* clobber */, implicit-def dead early-clobber $fcc0 + ; CHECK-NEXT: [[PseudoLD_CFR:%[0-9]+]]:cfr = PseudoLD_CFR %stack.0, 0 :: (load (s64) from %stack.0) + ; CHECK-NEXT: $r4 = COPY [[PseudoLD_CFR]] + ; CHECK-NEXT: PseudoRET implicit killed $r4 + %1:fpr64 = COPY $f1_64 + %0:fpr64 = COPY $f0_64 + %2:cfr = FCMP_CLT_D %1, %0 + INLINEASM &"nop", 1 /* sideeffect attdialect */, 12 /* clobber */, implicit-def dead early-clobber $fcc0 + $r4 = COPY %2 + PseudoRET implicit killed $r4 + +...