Skip to content

Commit 2ccd8c1

Browse files
committed
Merging r353308 and r353383:
------------------------------------------------------------------------ r353308 | tnorthover | 2019-02-06 16:26:35 +0100 (Wed, 06 Feb 2019) | 5 lines AArch64: enforce even/odd register pairs for CASP instructions. ARMv8.1a CASP instructions need the first of the pair to be an even register (otherwise the encoding is unallocated). We enforced this during assembly, but not CodeGen before. ------------------------------------------------------------------------ ------------------------------------------------------------------------ r353383 | tnorthover | 2019-02-07 11:35:34 +0100 (Thu, 07 Feb 2019) | 4 lines AArch64: implement copy for paired GPR registers. When doing 128-bit atomics using CASP we might need to copy a GPRPair to a different register, but that was unimplemented up to now. ------------------------------------------------------------------------ llvm-svn: 353822
1 parent e552366 commit 2ccd8c1

File tree

6 files changed

+93
-6
lines changed

6 files changed

+93
-6
lines changed

llvm/lib/Target/AArch64/AArch64InstrInfo.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2292,6 +2292,31 @@ void AArch64InstrInfo::copyPhysRegTuple(MachineBasicBlock &MBB,
22922292
}
22932293
}
22942294

2295+
void AArch64InstrInfo::copyGPRRegTuple(MachineBasicBlock &MBB,
2296+
MachineBasicBlock::iterator I,
2297+
DebugLoc DL, unsigned DestReg,
2298+
unsigned SrcReg, bool KillSrc,
2299+
unsigned Opcode, unsigned ZeroReg,
2300+
llvm::ArrayRef<unsigned> Indices) const {
2301+
const TargetRegisterInfo *TRI = &getRegisterInfo();
2302+
unsigned NumRegs = Indices.size();
2303+
2304+
#ifndef NDEBUG
2305+
uint16_t DestEncoding = TRI->getEncodingValue(DestReg);
2306+
uint16_t SrcEncoding = TRI->getEncodingValue(SrcReg);
2307+
assert(DestEncoding % NumRegs == 0 && SrcEncoding % NumRegs == 0 &&
2308+
"GPR reg sequences should not be able to overlap");
2309+
#endif
2310+
2311+
for (unsigned SubReg = 0; SubReg != NumRegs; ++SubReg) {
2312+
const MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opcode));
2313+
AddSubReg(MIB, DestReg, Indices[SubReg], RegState::Define, TRI);
2314+
MIB.addReg(ZeroReg);
2315+
AddSubReg(MIB, SrcReg, Indices[SubReg], getKillRegState(KillSrc), TRI);
2316+
MIB.addImm(0);
2317+
}
2318+
}
2319+
22952320
void AArch64InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
22962321
MachineBasicBlock::iterator I,
22972322
const DebugLoc &DL, unsigned DestReg,
@@ -2431,6 +2456,22 @@ void AArch64InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
24312456
return;
24322457
}
24332458

2459+
if (AArch64::XSeqPairsClassRegClass.contains(DestReg) &&
2460+
AArch64::XSeqPairsClassRegClass.contains(SrcReg)) {
2461+
static const unsigned Indices[] = {AArch64::sube64, AArch64::subo64};
2462+
copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRXrs,
2463+
AArch64::XZR, Indices);
2464+
return;
2465+
}
2466+
2467+
if (AArch64::WSeqPairsClassRegClass.contains(DestReg) &&
2468+
AArch64::WSeqPairsClassRegClass.contains(SrcReg)) {
2469+
static const unsigned Indices[] = {AArch64::sube32, AArch64::subo32};
2470+
copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRWrs,
2471+
AArch64::WZR, Indices);
2472+
return;
2473+
}
2474+
24342475
if (AArch64::FPR128RegClass.contains(DestReg) &&
24352476
AArch64::FPR128RegClass.contains(SrcReg)) {
24362477
if (Subtarget.hasNEON()) {

llvm/lib/Target/AArch64/AArch64InstrInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ class AArch64InstrInfo final : public AArch64GenInstrInfo {
122122
const DebugLoc &DL, unsigned DestReg, unsigned SrcReg,
123123
bool KillSrc, unsigned Opcode,
124124
llvm::ArrayRef<unsigned> Indices) const;
125+
void copyGPRRegTuple(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
126+
DebugLoc DL, unsigned DestReg, unsigned SrcReg,
127+
bool KillSrc, unsigned Opcode, unsigned ZeroReg,
128+
llvm::ArrayRef<unsigned> Indices) const;
125129
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
126130
const DebugLoc &DL, unsigned DestReg, unsigned SrcReg,
127131
bool KillSrc) const override;

llvm/lib/Target/AArch64/AArch64RegisterInfo.td

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -649,10 +649,12 @@ def FPR128Op : RegisterOperand<FPR128, "printOperand"> {
649649
// ARMv8.1a atomic CASP register operands
650650

651651

652-
def WSeqPairs : RegisterTuples<[sube32, subo32],
653-
[(rotl GPR32, 0), (rotl GPR32, 1)]>;
654-
def XSeqPairs : RegisterTuples<[sube64, subo64],
655-
[(rotl GPR64, 0), (rotl GPR64, 1)]>;
652+
def WSeqPairs : RegisterTuples<[sube32, subo32],
653+
[(decimate (rotl GPR32, 0), 2),
654+
(decimate (rotl GPR32, 1), 2)]>;
655+
def XSeqPairs : RegisterTuples<[sube64, subo64],
656+
[(decimate (rotl GPR64, 0), 2),
657+
(decimate (rotl GPR64, 1), 2)]>;
656658

657659
def WSeqPairsClass : RegisterClass<"AArch64", [untyped], 32,
658660
(add WSeqPairs)>{

llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1779,8 +1779,8 @@ static DecodeStatus DecodeGPRSeqPairsClassRegisterClass(MCInst &Inst,
17791779
if (RegNo & 0x1)
17801780
return Fail;
17811781

1782-
unsigned Register = AArch64MCRegisterClasses[RegClassID].getRegister(RegNo);
1783-
Inst.addOperand(MCOperand::createReg(Register));
1782+
unsigned Reg = AArch64MCRegisterClasses[RegClassID].getRegister(RegNo / 2);
1783+
Inst.addOperand(MCOperand::createReg(Reg));
17841784
return Success;
17851785
}
17861786

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
; RUN: llc -mtriple arm64-apple-ios -mattr=+lse %s -o - | FileCheck %s
2+
3+
; Only "even,even+1" pairs are valid for CASP instructions. Make sure LLVM
4+
; doesn't allocate odd ones and that it can copy them around properly. N.b. we
5+
; don't actually check that they're sequential because FileCheck can't; odd/even
6+
; will have to be good enough.
7+
define void @test_atomic_cmpxchg_i128_register_shuffling(i128* %addr, i128 %desired, i128 %new) nounwind {
8+
; CHECK-LABEL: test_atomic_cmpxchg_i128_register_shuffling:
9+
; CHECK-DAG: mov [[DESIRED_LO:x[0-9]*[02468]]], x1
10+
; CHECK-DAG: mov [[DESIRED_HI:x[0-9]*[13579]]], x2
11+
; CHECK-DAG: mov [[NEW_LO:x[0-9]*[02468]]], x3
12+
; CHECK-DAG: mov [[NEW_HI:x[0-9]*[13579]]], x4
13+
; CHECK: caspal [[DESIRED_LO]], [[DESIRED_HI]], [[NEW_LO]], [[NEW_HI]], [x0]
14+
15+
%res = cmpxchg i128* %addr, i128 %desired, i128 %new seq_cst seq_cst
16+
ret void
17+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# RUN: llc -o - %s -mtriple=aarch64-- -mattr=+v8.1a -run-pass=postrapseudos | FileCheck %s
2+
---
3+
# CHECK-LABEL: name: copy_xseqpairs
4+
name: copy_xseqpairs
5+
body: |
6+
bb.0:
7+
; CHECK: $x4_x5 = CASPALX $x4_x5, $x2_x3, $x0
8+
; CHECK: $x0 = ORRXrs $xzr, $x4, 0
9+
; CHECK: $x1 = ORRXrs $xzr, $x5, 0
10+
$x4_x5 = CASPALX $x4_x5, $x2_x3, $x0
11+
$x0_x1 = COPY $x4_x5
12+
...
13+
---
14+
# CHECK-LABEL: name: copy_wseqpairs
15+
name: copy_wseqpairs
16+
body: |
17+
bb.0:
18+
; CHECK: $w4_w5 = CASPALW $w4_w5, $w2_w3, $x0
19+
; CHECK: $w0 = ORRWrs $wzr, $w4, 0
20+
; CHECK: $w1 = ORRWrs $wzr, $w5, 0
21+
$w4_w5 = CASPALW $w4_w5, $w2_w3, $x0
22+
$w0_w1 = COPY $w4_w5
23+
...

0 commit comments

Comments
 (0)