Index: llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp +++ llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp @@ -1550,10 +1550,12 @@ continue; } } - // If the destination register of the loads is the same register, bail - // and keep looking. A load-pair instruction with both destination - // registers the same is UNPREDICTABLE and will result in an exception. - if (MayLoad && Reg == getLdStRegOp(MI).getReg()) { + // If the destination register of one load is the same register or a + // sub/super register of the other load, bail and keep looking. A + // load-pair instruction with both destination registers the same is + // UNPREDICTABLE and will result in an exception. + if (MayLoad && + TRI->isSuperOrSubRegisterEq(Reg, getLdStRegOp(MI).getReg())) { LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits, TRI); MemInsns.push_back(&MI); Index: llvm/test/CodeGen/AArch64/aarch64-ldst-subsuperReg-no-ldp.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/aarch64-ldst-subsuperReg-no-ldp.mir @@ -0,0 +1,23 @@ +# RUN: llc -mtriple=aarch64-linux-gnu -verify-machineinstrs -run-pass=aarch64-ldst-opt %s -o - | FileCheck %s +# +# The test below tests that when the AArch64 Load Store Optimization pass tries to +# convert load instructions into a ldp instruction, and when the destination +# registers are sub/super register of each other, then the convertion should not occur. +# +# For example, for the following pattern: +# ldr x10 [x9] +# ldr w10 [x9, 8], +# We cannot convert it to an ldp instruction. +# +# CHECK-NOT: LDP +--- +name: test +tracksRegLiveness: true +body: | + bb.0: + liveins: $x9 + renamable $x10 = LDRSWui renamable $x9, 0 :: (load 4) + renamable $w10 = LDRWui renamable $x9, 1 :: (load 4) + RET undef $lr, implicit undef $w0 + +...