Skip to content

Commit e415cb1

Browse files
committed
[LoongArch] Support inline asm operand modifier 'z'
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 Differential Revision: https://reviews.llvm.org/D136841
1 parent be8a2b9 commit e415cb1

File tree

3 files changed

+78
-14
lines changed

3 files changed

+78
-14
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
2+
// RUN: %clang_cc1 -triple loongarch32 -O2 -emit-llvm %s -o - | FileCheck %s
3+
// RUN: %clang_cc1 -triple loongarch64 -O2 -emit-llvm %s -o - | FileCheck %s
4+
5+
/// Test LoongArch specific operand modifiers (i.e. operand codes).
6+
7+
// CHECK-LABEL: @test_z_zero(
8+
// CHECK-NEXT: entry:
9+
// CHECK-NEXT: [[TMP0:%.*]] = tail call i32 asm sideeffect "add.w $0, $1, ${2:z}", "=r,r,ri"(i32 [[A:%.*]], i32 0) #[[ATTR1:[0-9]+]], !srcloc !2
10+
// CHECK-NEXT: ret void
11+
//
12+
void test_z_zero(int a) {
13+
int tmp;
14+
asm volatile ("add.w %0, %1, %z2" : "=r" (tmp) : "r" (a), "ri" (0));
15+
}
16+
17+
// CHECK-LABEL: @test_z_nonzero(
18+
// CHECK-NEXT: entry:
19+
// CHECK-NEXT: [[TMP0:%.*]] = tail call i32 asm sideeffect "add.w $0, $1, ${2:z}", "=r,r,ri"(i32 [[A:%.*]], i32 1) #[[ATTR1]], !srcloc !3
20+
// CHECK-NEXT: ret void
21+
//
22+
void test_z_nonzero(int a) {
23+
int tmp;
24+
asm volatile ("add.w %0, %1, %z2" : "=r" (tmp) : "r" (a), "ri" (1));
25+
}

llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,24 +47,38 @@ bool LoongArchAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
4747
if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
4848
return false;
4949

50-
// TODO: handle other extra codes if we have.
51-
if (!ExtraCode) {
52-
const MachineOperand &MO = MI->getOperand(OpNo);
53-
switch (MO.getType()) {
54-
case MachineOperand::MO_Immediate:
55-
OS << MO.getImm();
56-
return false;
57-
case MachineOperand::MO_Register:
58-
OS << '$' << LoongArchInstPrinter::getRegisterName(MO.getReg());
59-
return false;
60-
case MachineOperand::MO_GlobalAddress:
61-
PrintSymbolOperand(MO, OS);
62-
return false;
50+
const MachineOperand &MO = MI->getOperand(OpNo);
51+
if (ExtraCode && ExtraCode[0]) {
52+
if (ExtraCode[1] != 0)
53+
return true; // Unknown modifier.
54+
55+
switch (ExtraCode[0]) {
6356
default:
64-
llvm_unreachable("not implemented");
57+
return true; // Unknown modifier.
58+
case 'z': // Print $zero register if zero, regular printing otherwise.
59+
if (MO.isImm() && MO.getImm() == 0) {
60+
OS << '$' << LoongArchInstPrinter::getRegisterName(LoongArch::R0);
61+
return false;
62+
}
63+
break;
64+
// TODO: handle other extra codes if any.
6565
}
6666
}
6767

68+
switch (MO.getType()) {
69+
case MachineOperand::MO_Immediate:
70+
OS << MO.getImm();
71+
return false;
72+
case MachineOperand::MO_Register:
73+
OS << '$' << LoongArchInstPrinter::getRegisterName(MO.getReg());
74+
return false;
75+
case MachineOperand::MO_GlobalAddress:
76+
PrintSymbolOperand(MO, OS);
77+
return false;
78+
default:
79+
llvm_unreachable("not implemented");
80+
}
81+
6882
return true;
6983
}
7084

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc --mtriple=loongarch32 --verify-machineinstrs < %s | FileCheck %s
3+
; RUN: llc --mtriple=loongarch64 --verify-machineinstrs < %s | FileCheck %s
4+
5+
define i32 @modifier_z_zero(i32 %a) nounwind {
6+
; CHECK-LABEL: modifier_z_zero:
7+
; CHECK: # %bb.0:
8+
; CHECK-NEXT: #APP
9+
; CHECK-NEXT: add.w $a0, $a0, $zero
10+
; CHECK-NEXT: #NO_APP
11+
; CHECK-NEXT: ret
12+
%1 = tail call i32 asm "add.w $0, $1, ${2:z}", "=r,r,ri"(i32 %a, i32 0)
13+
ret i32 %1
14+
}
15+
16+
define i32 @modifier_z_nonzero(i32 %a) nounwind {
17+
; CHECK-LABEL: modifier_z_nonzero:
18+
; CHECK: # %bb.0:
19+
; CHECK-NEXT: #APP
20+
; CHECK-NEXT: addi.w $a0, $a0, 1
21+
; CHECK-NEXT: #NO_APP
22+
; CHECK-NEXT: ret
23+
%1 = tail call i32 asm "addi.w $0, $1, ${2:z}", "=r,r,ri"(i32 %a, i32 1)
24+
ret i32 %1
25+
}

0 commit comments

Comments
 (0)