]> granicus.if.org Git - llvm/commitdiff
Merging r353308 and r353383:
authorHans Wennborg <hans@hanshq.net>
Tue, 12 Feb 2019 10:45:41 +0000 (10:45 +0000)
committerHans Wennborg <hans@hanshq.net>
Tue, 12 Feb 2019 10:45:41 +0000 (10:45 +0000)
------------------------------------------------------------------------
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.
------------------------------------------------------------------------

git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_80@353822 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/AArch64/AArch64InstrInfo.cpp
lib/Target/AArch64/AArch64InstrInfo.h
lib/Target/AArch64/AArch64RegisterInfo.td
lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp
test/CodeGen/AArch64/cmpxchg-lse-even-regs.ll [new file with mode: 0644]
test/CodeGen/AArch64/seqpaircopy.mir [new file with mode: 0644]

index ada06788857293848340736251057021c29a6097..50316ebe218b707757e80af10d15327a238b86a7 100644 (file)
@@ -2292,6 +2292,31 @@ void AArch64InstrInfo::copyPhysRegTuple(MachineBasicBlock &MBB,
   }
 }
 
+void AArch64InstrInfo::copyGPRRegTuple(MachineBasicBlock &MBB,
+                                       MachineBasicBlock::iterator I,
+                                       DebugLoc DL, unsigned DestReg,
+                                       unsigned SrcReg, bool KillSrc,
+                                       unsigned Opcode, unsigned ZeroReg,
+                                       llvm::ArrayRef<unsigned> Indices) const {
+  const TargetRegisterInfo *TRI = &getRegisterInfo();
+  unsigned NumRegs = Indices.size();
+
+#ifndef NDEBUG
+  uint16_t DestEncoding = TRI->getEncodingValue(DestReg);
+  uint16_t SrcEncoding = TRI->getEncodingValue(SrcReg);
+  assert(DestEncoding % NumRegs == 0 && SrcEncoding % NumRegs == 0 &&
+         "GPR reg sequences should not be able to overlap");
+#endif
+
+  for (unsigned SubReg = 0; SubReg != NumRegs; ++SubReg) {
+    const MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opcode));
+    AddSubReg(MIB, DestReg, Indices[SubReg], RegState::Define, TRI);
+    MIB.addReg(ZeroReg);
+    AddSubReg(MIB, SrcReg, Indices[SubReg], getKillRegState(KillSrc), TRI);
+    MIB.addImm(0);
+  }
+}
+
 void AArch64InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
                                    MachineBasicBlock::iterator I,
                                    const DebugLoc &DL, unsigned DestReg,
@@ -2431,6 +2456,22 @@ void AArch64InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
     return;
   }
 
+  if (AArch64::XSeqPairsClassRegClass.contains(DestReg) &&
+      AArch64::XSeqPairsClassRegClass.contains(SrcReg)) {
+    static const unsigned Indices[] = {AArch64::sube64, AArch64::subo64};
+    copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRXrs,
+                    AArch64::XZR, Indices);
+    return;
+  }
+
+  if (AArch64::WSeqPairsClassRegClass.contains(DestReg) &&
+      AArch64::WSeqPairsClassRegClass.contains(SrcReg)) {
+    static const unsigned Indices[] = {AArch64::sube32, AArch64::subo32};
+    copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRWrs,
+                    AArch64::WZR, Indices);
+    return;
+  }
+
   if (AArch64::FPR128RegClass.contains(DestReg) &&
       AArch64::FPR128RegClass.contains(SrcReg)) {
     if (Subtarget.hasNEON()) {
index 9954669d567508d6ce83cb9d17d00dee077c1a91..e48c26d4a84a03bc36f49a129d3c3e29f697b708 100644 (file)
@@ -122,6 +122,10 @@ public:
                         const DebugLoc &DL, unsigned DestReg, unsigned SrcReg,
                         bool KillSrc, unsigned Opcode,
                         llvm::ArrayRef<unsigned> Indices) const;
+  void copyGPRRegTuple(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
+                       DebugLoc DL, unsigned DestReg, unsigned SrcReg,
+                       bool KillSrc, unsigned Opcode, unsigned ZeroReg,
+                       llvm::ArrayRef<unsigned> Indices) const;
   void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
                    const DebugLoc &DL, unsigned DestReg, unsigned SrcReg,
                    bool KillSrc) const override;
index d3710cea0687ec53fac2d72382ce8b9eefe041ed..8e6aa69eae854feb66945f13180c55bc82b1ee8b 100644 (file)
@@ -649,10 +649,12 @@ def FPR128Op : RegisterOperand<FPR128, "printOperand"> {
 // ARMv8.1a atomic CASP register operands
 
 
-def WSeqPairs : RegisterTuples<[sube32, subo32], 
-                               [(rotl GPR32, 0), (rotl GPR32, 1)]>;
-def XSeqPairs : RegisterTuples<[sube64, subo64], 
-                               [(rotl GPR64, 0), (rotl GPR64, 1)]>;
+def WSeqPairs : RegisterTuples<[sube32, subo32],
+                               [(decimate (rotl GPR32, 0), 2),
+                                (decimate (rotl GPR32, 1), 2)]>;
+def XSeqPairs : RegisterTuples<[sube64, subo64],
+                               [(decimate (rotl GPR64, 0), 2),
+                                (decimate (rotl GPR64, 1), 2)]>;
 
 def WSeqPairsClass   : RegisterClass<"AArch64", [untyped], 32, 
                                      (add WSeqPairs)>{
index 4102f1eb5cc12c6afdacebd52182058db2888844..64afabd450c1fa10f02bdd438383e2d7e6a33bdd 100644 (file)
@@ -1779,8 +1779,8 @@ static DecodeStatus DecodeGPRSeqPairsClassRegisterClass(MCInst &Inst,
   if (RegNo & 0x1)
     return Fail;
 
-  unsigned Register = AArch64MCRegisterClasses[RegClassID].getRegister(RegNo);
-  Inst.addOperand(MCOperand::createReg(Register));
+  unsigned Reg = AArch64MCRegisterClasses[RegClassID].getRegister(RegNo / 2);
+  Inst.addOperand(MCOperand::createReg(Reg));
   return Success;
 }
 
diff --git a/test/CodeGen/AArch64/cmpxchg-lse-even-regs.ll b/test/CodeGen/AArch64/cmpxchg-lse-even-regs.ll
new file mode 100644 (file)
index 0000000..9c6d8cc
--- /dev/null
@@ -0,0 +1,17 @@
+; RUN: llc -mtriple arm64-apple-ios -mattr=+lse %s -o - | FileCheck %s
+
+; Only "even,even+1" pairs are valid for CASP instructions. Make sure LLVM
+; doesn't allocate odd ones and that it can copy them around properly. N.b. we
+; don't actually check that they're sequential because FileCheck can't; odd/even
+; will have to be good enough.
+define void @test_atomic_cmpxchg_i128_register_shuffling(i128* %addr, i128 %desired, i128 %new) nounwind {
+; CHECK-LABEL: test_atomic_cmpxchg_i128_register_shuffling:
+; CHECK-DAG: mov [[DESIRED_LO:x[0-9]*[02468]]], x1
+; CHECK-DAG: mov [[DESIRED_HI:x[0-9]*[13579]]], x2
+; CHECK-DAG: mov [[NEW_LO:x[0-9]*[02468]]], x3
+; CHECK-DAG: mov [[NEW_HI:x[0-9]*[13579]]], x4
+; CHECK: caspal [[DESIRED_LO]], [[DESIRED_HI]], [[NEW_LO]], [[NEW_HI]], [x0]
+
+  %res = cmpxchg i128* %addr, i128 %desired, i128 %new seq_cst seq_cst
+  ret void
+}
diff --git a/test/CodeGen/AArch64/seqpaircopy.mir b/test/CodeGen/AArch64/seqpaircopy.mir
new file mode 100644 (file)
index 0000000..89511cb
--- /dev/null
@@ -0,0 +1,23 @@
+# RUN: llc -o - %s -mtriple=aarch64-- -mattr=+v8.1a -run-pass=postrapseudos | FileCheck %s
+---
+# CHECK-LABEL: name: copy_xseqpairs
+name: copy_xseqpairs
+body: |
+  bb.0:
+    ; CHECK: $x4_x5 = CASPALX $x4_x5, $x2_x3, $x0
+    ; CHECK: $x0 = ORRXrs $xzr, $x4, 0
+    ; CHECK: $x1 = ORRXrs $xzr, $x5, 0
+    $x4_x5 = CASPALX $x4_x5, $x2_x3, $x0
+    $x0_x1 = COPY $x4_x5
+...
+---
+# CHECK-LABEL: name: copy_wseqpairs
+name: copy_wseqpairs
+body: |
+  bb.0:
+    ; CHECK: $w4_w5 = CASPALW $w4_w5, $w2_w3, $x0
+    ; CHECK: $w0 = ORRWrs $wzr, $w4, 0
+    ; CHECK: $w1 = ORRWrs $wzr, $w5, 0
+    $w4_w5 = CASPALW $w4_w5, $w2_w3, $x0
+    $w0_w1 = COPY $w4_w5
+...