[llvm] r306865 - ARM: fix big-endian 64-bit cmpxchg.

Tim Northover via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 30 12:51:02 PDT 2017


Author: tnorthover
Date: Fri Jun 30 12:51:02 2017
New Revision: 306865

URL: http://llvm.org/viewvc/llvm-project?rev=306865&view=rev
Log:
ARM: fix big-endian 64-bit cmpxchg.

On big-endian machines the high and low parts of the value accessed by ldrexd
and strexd are swapped around. To account for this we swap inputs and outputs
in ISelLowering.

Patch by Bharathi Seshadri.

Added:
    llvm/trunk/test/CodeGen/ARM/cmpxchg-O0-be.ll
Modified:
    llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp

Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=306865&r1=306864&r2=306865&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Fri Jun 30 12:51:02 2017
@@ -7580,6 +7580,9 @@ static SDValue createGPRPairNode(Selecti
   SDValue VHi = DAG.getAnyExtOrTrunc(
       DAG.getNode(ISD::SRL, dl, MVT::i64, V, DAG.getConstant(32, dl, MVT::i32)),
       dl, MVT::i32);
+  bool isBigEndian = DAG.getDataLayout().isBigEndian();
+  if (isBigEndian)
+    std::swap (VLo, VHi);
   SDValue RegClass =
       DAG.getTargetConstant(ARM::GPRPairRegClassID, dl, MVT::i32);
   SDValue SubReg0 = DAG.getTargetConstant(ARM::gsub_0, dl, MVT::i32);
@@ -7607,10 +7610,14 @@ static void ReplaceCMP_SWAP_64Results(SD
   MemOp[0] = cast<MemSDNode>(N)->getMemOperand();
   cast<MachineSDNode>(CmpSwap)->setMemRefs(MemOp, MemOp + 1);
 
-  Results.push_back(DAG.getTargetExtractSubreg(ARM::gsub_0, SDLoc(N), MVT::i32,
-                                               SDValue(CmpSwap, 0)));
-  Results.push_back(DAG.getTargetExtractSubreg(ARM::gsub_1, SDLoc(N), MVT::i32,
-                                               SDValue(CmpSwap, 0)));
+  bool isBigEndian = DAG.getDataLayout().isBigEndian();
+
+  Results.push_back(
+      DAG.getTargetExtractSubreg(isBigEndian ? ARM::gsub_1 : ARM::gsub_0,
+                                 SDLoc(N), MVT::i32, SDValue(CmpSwap, 0)));
+  Results.push_back(
+      DAG.getTargetExtractSubreg(isBigEndian ? ARM::gsub_0 : ARM::gsub_1,
+                                 SDLoc(N), MVT::i32, SDValue(CmpSwap, 0)));
   Results.push_back(SDValue(CmpSwap, 2));
 }
 

Added: llvm/trunk/test/CodeGen/ARM/cmpxchg-O0-be.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/cmpxchg-O0-be.ll?rev=306865&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/cmpxchg-O0-be.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/cmpxchg-O0-be.ll Fri Jun 30 12:51:02 2017
@@ -0,0 +1,26 @@
+; RUN: llc -verify-machineinstrs -mtriple=armebv8-linux-gnueabi -O0 %s -o - | FileCheck %s
+
+ at x = global i64 10, align 8
+ at y = global i64 20, align 8
+ at z = global i64 20, align 8
+
+; CHECK_LABEL:	main:
+; CHECK:	ldr [[R2:r[0-9]+]], {{\[}}[[R1:r[0-9]+]]{{\]}}
+; CHECK-NEXT:	ldr [[R1]], {{\[}}[[R1]], #4]
+; CHECK:	mov [[R4:r[0-9]+]], [[R2]]
+; CHECK-NEXT:	mov [[R5:r[0-9]+]], [[R1]]
+; CHECK:	ldr [[R2]], {{\[}}[[R1]]{{\]}}
+; CHECK-NEXT:	ldr [[R1]], {{\[}}[[R1]], #4]
+; CHECK:	mov [[R6:r[0-9]+]], [[R2]]
+; CHECK-NEXT:	mov [[R7:r[0-9]+]], [[R1]]
+
+define arm_aapcs_vfpcc i32 @main() #0 {
+entry:
+  %retval = alloca i32, align 4
+  store i32 0, i32* %retval, align 4
+  %0 = load i64, i64* @z, align 8
+  %1 = load i64, i64* @x, align 8
+  %2 = cmpxchg i64* @y, i64 %0, i64 %1 seq_cst seq_cst
+  %3 = extractvalue { i64, i1 } %2, 1
+  ret i32 0
+}




More information about the llvm-commits mailing list