From a8b6c543a8f297ae9455fc6f6ec65f64810acc71 Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Fri, 30 Jun 2017 19:51:02 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@306865 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMISelLowering.cpp | 15 +++++++++++---- test/CodeGen/ARM/cmpxchg-O0-be.ll | 26 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 test/CodeGen/ARM/cmpxchg-O0-be.ll diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 2bcc707e9fc..e42514acd76 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -7580,6 +7580,9 @@ static SDValue createGPRPairNode(SelectionDAG &DAG, SDValue V) { 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(SDNode *N, MemOp[0] = cast(N)->getMemOperand(); cast(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)); } diff --git a/test/CodeGen/ARM/cmpxchg-O0-be.ll b/test/CodeGen/ARM/cmpxchg-O0-be.ll new file mode 100644 index 00000000000..9e9a93e19b6 --- /dev/null +++ b/test/CodeGen/ARM/cmpxchg-O0-be.ll @@ -0,0 +1,26 @@ +; RUN: llc -verify-machineinstrs -mtriple=armebv8-linux-gnueabi -O0 %s -o - | FileCheck %s + +@x = global i64 10, align 8 +@y = global i64 20, align 8 +@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 +} -- 2.40.0