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 @@ -1610,7 +1610,13 @@ !UsedRegUnits.available(getLdStBaseOp(MI).getReg()); bool IsBaseRegModified = !ModifiedRegUnits.available(getLdStBaseOp(MI).getReg()); - if (IsOutOfBounds || IsBaseRegUsed || IsBaseRegModified) { + // If the stored value and the address of the second instruction is + // the same, it needs to be using the updated register and therefore + // it must not be folded. + bool IsMIRegTheSame = + getLdStRegOp(MI).getReg() == getLdStBaseOp(MI).getReg(); + if (IsOutOfBounds || IsBaseRegUsed || IsBaseRegModified || + IsMIRegTheSame) { LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits, TRI); MemInsns.push_back(&MI); diff --git a/llvm/test/CodeGen/AArch64/strpre-str-merge.mir b/llvm/test/CodeGen/AArch64/strpre-str-merge.mir --- a/llvm/test/CodeGen/AArch64/strpre-str-merge.mir +++ b/llvm/test/CodeGen/AArch64/strpre-str-merge.mir @@ -424,3 +424,30 @@ STRSui killed renamable $s1, renamable $x0, 1 :: (store 4) RET undef $lr, implicit $x0 ... + +--- +name: 16-strxpre-strxui-same-reg-no-merge +alignment: 4 +tracksRegLiveness: true +liveins: + - { reg: '$x0' } + - { reg: '$x1' } + - { reg: '$x2' } +frameInfo: + maxAlignment: 1 + maxCallFrameSize: 0 +machineFunctionInfo: + hasRedZone: false +body: | + bb.0.entry: + liveins: $x0, $x1, $x2 + ; CHECK-LABEL: name: 16-strxpre-strxui-same-reg-no-merge + ; CHECK: liveins: $x0, $x1, $x2 + ; CHECK: early-clobber renamable $x0 = STRXpre renamable $x1, renamable $x0, 24, implicit $w0 :: (store 8) + ; CHECK: STRXui renamable $x0, renamable $x0, 1 :: (store 8) + ; CHECK: RET undef $lr, implicit $x0 + early-clobber renamable $x0 = STRXpre killed renamable $x1, killed renamable $x0, 24 :: (store 8) + STRXui renamable $x0, renamable $x0, 1 :: (store 8) + RET undef $lr, implicit $x0 + +...