diff --git a/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp b/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp --- a/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp +++ b/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp @@ -1564,6 +1564,15 @@ continue; } + // If the BaseReg has been modified, then we cannot do the optimization. + // For example, in the following pattern + // ldr x1 [x2] + // ldr x2 [x3] + // ldr x4 [x2, #8], + // the first and third ldr cannot be converted to ldp x1, x4, [x2] + if (!ModifiedRegUnits.available(BaseReg)) + return E; + // If the Rt of the second instruction was not modified or used between // the two instructions and none of the instructions between the second // and first alias with the second, we can combine the second into the diff --git a/llvm/test/CodeGen/AArch64/aarch64-ldst-modified-baseReg.mir b/llvm/test/CodeGen/AArch64/aarch64-ldst-modified-baseReg.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/aarch64-ldst-modified-baseReg.mir @@ -0,0 +1,105 @@ +# RUN: llc -mtriple=aarch64-linux-gnu -verify-machineinstrs -run-pass=aarch64-ldst-opt %s -o - | FileCheck %s +# +# When the AArch64 Load Store Optimization pass tries to convert load instructions +# into a ldp instruction, and when the base register of the second ldr instruction +# has been modified in between these two ldr instructions, the conversion should not +# occur. +# +# For example, for the following pattern: +# ldr x9 [x10] +# ldr x10 [x8] +# ldr x10 [x10, 8], +# the first and third ldr instructions cannot be converted to ldp x9, x10, [x10]. +# +# CHECK-LABEL: name: ldr-modified-baseReg-no-ldp1 +# CHECK-NOT: LDP +# CHECK: $x9 = LDRXui $x10, 1 :: (load 8) +# CHECK: $x10 = LDURXi $x8, 1 :: (load 8) +# CHECK: $x10 = LDRXui $x10, 0 :: (load 8) +# CHECK: RET +--- +name: ldr-modified-baseReg-no-ldp1 +tracksRegLiveness: true +body: | + bb.0: + liveins: $x8, $x10 + + $x9 = LDRXui $x10, 1 :: (load 8) + $x10 = LDURXi $x8, 1 :: (load 8) + $x10 = LDRXui $x10, 0 :: (load 8) + RET undef $lr, implicit undef $w0 +... + +# CHECK-LABEL: name: str-modified-baseReg-no-stp1 +# CHECK-NOT: STP +# CHECK: STRXui $x9, $x10, 1 :: (store 8) +# CHECK: $x10 = LDRXui $x8, 0 :: (load 8) +# CHECK: STRXui $x10, $x10, 0 :: (store 8) +# CHECK: RET +--- +name: str-modified-baseReg-no-stp1 +tracksRegLiveness: true +body: | + bb.0: + liveins: $x9, $x8, $x10 + + STRXui $x9, $x10, 1 :: (store 8) + $x10 = LDRXui $x8, 0 :: (load 8) + STRXui $x10, $x10, 0 :: (store 8) + RET undef $lr, implicit undef $w0 +... + +# CHECK-LABEL: name: ldr-modified-baseReg-no-ldp2 +# CHECK-NOT: LDP +# CHECK: $x9 = LDRXui $x10, 1 :: (load 8) +# CHECK: $x10 = MOVi64imm 13 +# CHECK: $x11 = LDRXui $x10, 0 :: (load 8) +# CHECK: RET +--- +name: ldr-modified-baseReg-no-ldp2 +tracksRegLiveness: true +body: | + bb.0: + liveins: $x8, $x10 + + $x9 = LDRXui $x10, 1 :: (load 8) + $x10 = MOVi64imm 13 + $x11 = LDRXui $x10, 0 :: (load 8) + RET undef $lr, implicit undef $w0 +... + +# CHECK-LABEL: name: ldr-modified-baseReg-no-ldp3 +# CHECK-NOT: LDP +# CHECK: $x9 = LDRXui $x10, 1 :: (load 8) +# CHECK: $x10 = ADDXri $x8, $x11, 0 +# CHECK: $x12 = LDRXui $x10, 0 :: (load 8) +# CHECK: RET +--- +name: ldr-modified-baseReg-no-ldp3 +tracksRegLiveness: true +body: | + bb.0: + liveins: $x8, $x10, $x11 + + $x9 = LDRXui $x10, 1 :: (load 8) + $x10 = ADDXri $x8, $x11, 0 + $x12 = LDRXui $x10, 0 :: (load 8) + RET undef $lr, implicit undef $w0 +... + +# CHECK-LABEL: name: ldr-modified-baseAddr-convert-to-ldp +# CHECK: $x12, $x9 = LDPXi $x10, 0 :: (load 8) +# CHECK: STRXui $x11, $x10, 1 :: (store 8) +# CHECK: RET +--- +name: ldr-modified-baseAddr-convert-to-ldp +tracksRegLiveness: true +body: | + bb.0: + liveins: $x8, $x10, $x11 + + $x9 = LDRXui $x10, 1 :: (load 8) + STRXui $x11, $x10, 1 :: (store 8) + $x12 = LDRXui $x10, 0 :: (load 8) + RET undef $lr, implicit undef $w0 +...