Skip to content

Commit

Permalink
[SPARC] Implement L and H inline asm argument modifiers (#87259)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
koachan committed Apr 4, 2024
1 parent 18380c5 commit 697dd93
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 0 deletions.
2 changes: 2 additions & 0 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5557,6 +5557,8 @@ RISC-V:

Sparc:

- ``L``: Print the low-order register of a two-register operand.
- ``H``: Print the high-order register of a two-register operand.
- ``r``: No effect.

SystemZ:
Expand Down
44 changes: 44 additions & 0 deletions llvm/lib/Target/Sparc/SparcAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,50 @@ bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
default:
// See if this is a generic print operand
return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
case 'L': // Low order register of a twin word register operand
case 'H': // High order register of a twin word register operand
{
const SparcSubtarget &Subtarget = MF->getSubtarget<SparcSubtarget>();
const MachineOperand &MO = MI->getOperand(OpNo);
const SparcRegisterInfo *RegisterInfo = Subtarget.getRegisterInfo();
Register MOReg = MO.getReg();

Register HiReg, LoReg;
if (!SP::IntPairRegClass.contains(MOReg)) {
// If we aren't given a register pair already, find out which pair it
// belongs to. Note that here, the specified register operand, which
// refers to the high part of the twinword, needs to be an even-numbered
// register.
MOReg = RegisterInfo->getMatchingSuperReg(MOReg, SP::sub_even,
&SP::IntPairRegClass);
if (!MOReg) {
SMLoc Loc;
OutContext.reportError(
Loc, "Hi part of pair should point to an even-numbered register");
OutContext.reportError(
Loc, "(note that in some cases it might be necessary to manually "
"bind the input/output registers instead of relying on "
"automatic allocation)");
return true;
}
}

HiReg = RegisterInfo->getSubReg(MOReg, SP::sub_even);
LoReg = RegisterInfo->getSubReg(MOReg, SP::sub_odd);

Register Reg;
switch (ExtraCode[0]) {
case 'L':
Reg = LoReg;
break;
case 'H':
Reg = HiReg;
break;
}

O << '%' << SparcInstPrinter::getRegisterName(Reg);
return false;
}
case 'f':
case 'r':
break;
Expand Down
9 changes: 9 additions & 0 deletions llvm/test/CodeGen/SPARC/inlineasm-bad.ll
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,12 @@ entry:
tail call void asm sideeffect "faddq $0,$1,$2", "{f38},{f0},{f0}"(fp128 0xL0, fp128 0xL0, fp128 0xL0)
ret void
}

; CHECK-label:test_twinword_error
; CHECK: error: Hi part of pair should point to an even-numbered register
; CHECK: error: (note that in some cases it might be necessary to manually bind the input/output registers instead of relying on automatic allocation)

define i64 @test_twinword_error(){
%1 = tail call i64 asm sideeffect "rd %asr5, ${0:L} \0A\09 srlx ${0:L}, 32, ${0:H}", "={i1}"()

This comment has been minimized.

Copy link
@mahesh-attarde

mahesh-attarde Apr 8, 2024

Contributor

@koachan
I am working on constraints error messaging from AsmPrinter https://github.com/llvm/llvm-project/pull/86910 and stumbled on your latest change for specialized message. I see you have 2 L and 1 H constraint here. Are you expecting single error for all 3 case? since line
697dd93#diff-d68f40b543f55bd7e31c3fc6a3dbe06455d7857fb1f5bd7270bb871d1c39e830R437 .

This comment has been minimized.

Copy link
@koachan

koachan Apr 9, 2024

Author Contributor

Yep. Currently it emits one error message per operand.
Do you want to change it to only emit one error for the entire inline asm instance?

Either way, any approach would be fine by me.

This comment has been minimized.

Copy link
@mahesh-attarde

mahesh-attarde Apr 9, 2024

Contributor

I am updating test on my side will add you as reviewer.
Thanks.

ret i64 %1
}
9 changes: 9 additions & 0 deletions llvm/test/CodeGen/SPARC/inlineasm.ll
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,12 @@ entry:
%1 = call double asm sideeffect "faddd $1, $2, $0", "=f,f,e"(i64 0, i64 0)
ret void
}

; CHECK-label:test_twinword
; CHECK: rd %asr5, %i1
; CHECK: srlx %i1, 32, %i0

define i64 @test_twinword(){
%1 = tail call i64 asm sideeffect "rd %asr5, ${0:L} \0A\09 srlx ${0:L}, 32, ${0:H}", "={i0}"()
ret i64 %1
}

0 comments on commit 697dd93

Please sign in to comment.