Skip to content

Commit b6ebea7

Browse files
koachantstellar
authored andcommitted
[SPARC] Implement L and H inline asm argument modifiers (#87259)
This adds support for using the L and H argument modifiers for twinword operands in inline asm code, such as in: ``` %1 = tail call i64 asm sideeffect "rd %pc, ${0:L} ; srlx ${0:L}, 32, ${0:H}", "={o4}"() ``` This is needed by the Linux kernel. (cherry picked from commit 697dd93)
1 parent bffecba commit b6ebea7

File tree

4 files changed

+64
-0
lines changed

4 files changed

+64
-0
lines changed

llvm/docs/LangRef.rst

+2
Original file line numberDiff line numberDiff line change
@@ -5499,6 +5499,8 @@ RISC-V:
54995499

55005500
Sparc:
55015501

5502+
- ``L``: Print the low-order register of a two-register operand.
5503+
- ``H``: Print the high-order register of a two-register operand.
55025504
- ``r``: No effect.
55035505

55045506
SystemZ:

llvm/lib/Target/Sparc/SparcAsmPrinter.cpp

+44
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,50 @@ bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
434434
default:
435435
// See if this is a generic print operand
436436
return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
437+
case 'L': // Low order register of a twin word register operand
438+
case 'H': // High order register of a twin word register operand
439+
{
440+
const SparcSubtarget &Subtarget = MF->getSubtarget<SparcSubtarget>();
441+
const MachineOperand &MO = MI->getOperand(OpNo);
442+
const SparcRegisterInfo *RegisterInfo = Subtarget.getRegisterInfo();
443+
Register MOReg = MO.getReg();
444+
445+
Register HiReg, LoReg;
446+
if (!SP::IntPairRegClass.contains(MOReg)) {
447+
// If we aren't given a register pair already, find out which pair it
448+
// belongs to. Note that here, the specified register operand, which
449+
// refers to the high part of the twinword, needs to be an even-numbered
450+
// register.
451+
MOReg = RegisterInfo->getMatchingSuperReg(MOReg, SP::sub_even,
452+
&SP::IntPairRegClass);
453+
if (!MOReg) {
454+
SMLoc Loc;
455+
OutContext.reportError(
456+
Loc, "Hi part of pair should point to an even-numbered register");
457+
OutContext.reportError(
458+
Loc, "(note that in some cases it might be necessary to manually "
459+
"bind the input/output registers instead of relying on "
460+
"automatic allocation)");
461+
return true;
462+
}
463+
}
464+
465+
HiReg = RegisterInfo->getSubReg(MOReg, SP::sub_even);
466+
LoReg = RegisterInfo->getSubReg(MOReg, SP::sub_odd);
467+
468+
Register Reg;
469+
switch (ExtraCode[0]) {
470+
case 'L':
471+
Reg = LoReg;
472+
break;
473+
case 'H':
474+
Reg = HiReg;
475+
break;
476+
}
477+
478+
O << '%' << SparcInstPrinter::getRegisterName(Reg);
479+
return false;
480+
}
437481
case 'f':
438482
case 'r':
439483
break;

llvm/test/CodeGen/SPARC/inlineasm-bad.ll

+9
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,12 @@ entry:
1111
tail call void asm sideeffect "faddq $0,$1,$2", "{f38},{f0},{f0}"(fp128 0xL0, fp128 0xL0, fp128 0xL0)
1212
ret void
1313
}
14+
15+
; CHECK-label:test_twinword_error
16+
; CHECK: error: Hi part of pair should point to an even-numbered register
17+
; CHECK: error: (note that in some cases it might be necessary to manually bind the input/output registers instead of relying on automatic allocation)
18+
19+
define i64 @test_twinword_error(){
20+
%1 = tail call i64 asm sideeffect "rd %asr5, ${0:L} \0A\09 srlx ${0:L}, 32, ${0:H}", "={i1}"()
21+
ret i64 %1
22+
}

llvm/test/CodeGen/SPARC/inlineasm.ll

+9
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,12 @@ entry:
143143
%1 = call double asm sideeffect "faddd $1, $2, $0", "=f,f,e"(i64 0, i64 0)
144144
ret void
145145
}
146+
147+
; CHECK-label:test_twinword
148+
; CHECK: rd %asr5, %i1
149+
; CHECK: srlx %i1, 32, %i0
150+
151+
define i64 @test_twinword(){
152+
%1 = tail call i64 asm sideeffect "rd %asr5, ${0:L} \0A\09 srlx ${0:L}, 32, ${0:H}", "={i0}"()
153+
ret i64 %1
154+
}

0 commit comments

Comments
 (0)