diff --git a/clang/test/CodeGen/LoongArch/inline-asm-operand-modifiers.c b/clang/test/CodeGen/LoongArch/inline-asm-operand-modifiers.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/LoongArch/inline-asm-operand-modifiers.c @@ -0,0 +1,25 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple loongarch32 -O2 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple loongarch64 -O2 -emit-llvm %s -o - | FileCheck %s + +/// Test LoongArch specific operand modifiers (i.e. operand codes). + +// CHECK-LABEL: @test_z_zero( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call i32 asm sideeffect "add.w $0, $1, ${2:z}", "=r,r,ri"(i32 [[A:%.*]], i32 0) #[[ATTR1]], !srcloc !4 +// CHECK-NEXT: ret void +// +void test_z_zero(int a) { + int tmp; + asm volatile ("add.w %0, %1, %z2" : "=r" (tmp) : "r" (a), "ri" (0)); +} + +// CHECK-LABEL: @test_z_nonzero( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[TMP0:%.*]] = tail call i32 asm sideeffect "add.w $0, $1, ${2:z}", "=r,r,ri"(i32 [[A:%.*]], i32 1) #[[ATTR1]], !srcloc !5 +// CHECK-NEXT: ret void +// +void test_z_nonzero(int a) { + int tmp; + asm volatile ("add.w %0, %1, %z2" : "=r" (tmp) : "r" (a), "ri" (1)); +} diff --git a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp --- a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp @@ -47,24 +47,38 @@ if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS)) return false; - // TODO: handle other extra codes if we have. - if (!ExtraCode) { - const MachineOperand &MO = MI->getOperand(OpNo); - switch (MO.getType()) { - case MachineOperand::MO_Immediate: - OS << MO.getImm(); - return false; - case MachineOperand::MO_Register: - OS << '$' << LoongArchInstPrinter::getRegisterName(MO.getReg()); - return false; - case MachineOperand::MO_GlobalAddress: - PrintSymbolOperand(MO, OS); - return false; + const MachineOperand &MO = MI->getOperand(OpNo); + if (ExtraCode && ExtraCode[0]) { + if (ExtraCode[1] != 0) + return true; // Unknown modifier. + + switch (ExtraCode[0]) { default: - llvm_unreachable("not implemented"); + return true; // Unknown modifier. + case 'z': // Print $zero register if zero, regular printing otherwise. + if (MO.isImm() && MO.getImm() == 0) { + OS << '$' << LoongArchInstPrinter::getRegisterName(LoongArch::R0); + return false; + } + break; + // TODO: handle other extra codes if we have. } } + switch (MO.getType()) { + case MachineOperand::MO_Immediate: + OS << MO.getImm(); + return false; + case MachineOperand::MO_Register: + OS << '$' << LoongArchInstPrinter::getRegisterName(MO.getReg()); + return false; + case MachineOperand::MO_GlobalAddress: + PrintSymbolOperand(MO, OS); + return false; + default: + llvm_unreachable("not implemented"); + } + return true; } diff --git a/llvm/test/CodeGen/LoongArch/inline-asm-operand-modidiers.ll b/llvm/test/CodeGen/LoongArch/inline-asm-operand-modidiers.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/LoongArch/inline-asm-operand-modidiers.ll @@ -0,0 +1,25 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc --mtriple=loongarch32 --verify-machineinstrs < %s | FileCheck %s +; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s | FileCheck %s + +define i32 @modifier_z_zero(i32 %a) nounwind { +; CHECK-LABEL: modifier_z_zero: +; CHECK: # %bb.0: +; CHECK-NEXT: #APP +; CHECK-NEXT: add.w $a0, $a0, $zero +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: ret + %1 = tail call i32 asm "add.w $0, $1, ${2:z}", "=r,r,ri"(i32 %a, i32 0) + ret i32 %1 +} + +define i32 @modifier_z_nonzero(i32 %a) nounwind { +; CHECK-LABEL: modifier_z_nonzero: +; CHECK: # %bb.0: +; CHECK-NEXT: #APP +; CHECK-NEXT: addi.w $a0, $a0, 1 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: ret + %1 = tail call i32 asm "addi.w $0, $1, ${2:z}", "=r,r,ri"(i32 %a, i32 1) + ret i32 %1 +}