SixWeining created this revision. SixWeining added reviewers: xen0n, xry111, MaskRay, wangleiat, gonglingqin. Herald added subscribers: StephenFan, pengfei, hiraditya. Herald added a project: All. SixWeining requested review of this revision. Herald added projects: clang, LLVM. Herald added subscribers: llvm-commits, cfe-commits.
Print $zero register if operand is zero, otherwise print it normally. Clang is highly compatible [1] with GCC inline assembly extensions, allowing the same set of constraints, modifiers and operands as GCC inline assembly. This patch tries to make it compatible regarding LoongArch specific operand modifiers. GCC supports many modifiers [2], but it seems that only x86 and msp430 are documented [3][4]. I don't know if any other modifiers are being used except the 'z' in Linux [5]. [1]: https://clang.llvm.org/compatibility.html#inline-asm [2]: https://github.com/gcc-mirror/gcc/blob/master/gcc/config/loongarch/loongarch.cc#L4884-L4911 [3]: https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#x86Operandmodifiers [4]: https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#msp430Operandmodifiers [5]: https://github.com/torvalds/linux/blob/master/arch/loongarch/include/asm/cmpxchg.h#L17 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D136841 Files: clang/test/CodeGen/LoongArch/inline-asm-operand-modifiers.c llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp llvm/test/CodeGen/LoongArch/inline-asm-operand-modidiers.ll
Index: llvm/test/CodeGen/LoongArch/inline-asm-operand-modidiers.ll =================================================================== --- /dev/null +++ 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 +} Index: llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp =================================================================== --- llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp +++ 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; } Index: clang/test/CodeGen/LoongArch/inline-asm-operand-modifiers.c =================================================================== --- /dev/null +++ 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)); +}
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits