[AArch64] Use an unknown size for memcpy ops with non-constant sizes. (#187445)

The previous value of 0 was allowing loads to move past the mops
operations where it is not valid. Use a LocationSize::afterPointer()
size instead.

The GISel lowering currently loses the MMO, which is fine as it should
be conservatively treated as a load/store to any location.
This commit is contained in:
David Green 2026-03-20 07:28:16 +00:00 committed by GitHub
parent 421bf13e4b
commit 441790b31f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 32 additions and 4 deletions

View File

@ -127,9 +127,9 @@ SDValue AArch64SelectionDAGInfo::EmitMOPS(unsigned Opcode, SelectionDAG &DAG,
MachinePointerInfo SrcPtrInfo) const {
// Get the constant size of the copy/set.
uint64_t ConstSize = 0;
LocationSize MemSize = LocationSize::afterPointer();
if (auto *C = dyn_cast<ConstantSDNode>(Size))
ConstSize = C->getZExtValue();
MemSize = LocationSize::precise(C->getZExtValue());
const bool IsSet = Opcode == AArch64::MOPSMemorySetPseudo ||
Opcode == AArch64::MOPSMemorySetTaggingPseudo;
@ -140,7 +140,7 @@ SDValue AArch64SelectionDAGInfo::EmitMOPS(unsigned Opcode, SelectionDAG &DAG,
isVolatile ? MachineMemOperand::MOVolatile : MachineMemOperand::MONone;
auto DstFlags = MachineMemOperand::MOStore | Vol;
auto *DstOp =
MF.getMachineMemOperand(DstPtrInfo, DstFlags, ConstSize, Alignment);
MF.getMachineMemOperand(DstPtrInfo, DstFlags, MemSize, Alignment);
if (IsSet) {
// Extend value to i64, if required.
@ -158,7 +158,7 @@ SDValue AArch64SelectionDAGInfo::EmitMOPS(unsigned Opcode, SelectionDAG &DAG,
auto SrcFlags = MachineMemOperand::MOLoad | Vol;
auto *SrcOp =
MF.getMachineMemOperand(SrcPtrInfo, SrcFlags, ConstSize, Alignment);
MF.getMachineMemOperand(SrcPtrInfo, SrcFlags, MemSize, Alignment);
DAG.setNodeMemRefs(Node, {DstOp, SrcOp});
return SDValue(Node, 3);
}

View File

@ -0,0 +1,28 @@
; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
; RUN: llc -mtriple=aarch64-none-linux-gnu -mattr=+mops -stop-after=aarch64-isel -o - %s | FileCheck %s --check-prefix=CHECK-SD
; RUN: llc -mtriple=aarch64-none-linux-gnu -mattr=+mops -global-isel -stop-after=finalize-isel -o - %s | FileCheck %s --check-prefix=CHECK-GI
define void @test(ptr %out, ptr %in, i64 %a) {
; CHECK-SD-LABEL: name: test
; CHECK-SD: bb.0.entry:
; CHECK-SD-NEXT: liveins: $x0, $x1, $x2
; CHECK-SD-NEXT: {{ $}}
; CHECK-SD-NEXT: [[COPY:%[0-9]+]]:gpr64 = COPY $x2
; CHECK-SD-NEXT: [[COPY1:%[0-9]+]]:gpr64common = COPY $x1
; CHECK-SD-NEXT: [[COPY2:%[0-9]+]]:gpr64common = COPY $x0
; CHECK-SD-NEXT: [[MOPSMemoryMovePseudo:%[0-9]+]]:gpr64common, [[MOPSMemoryMovePseudo1:%[0-9]+]]:gpr64common, [[MOPSMemoryMovePseudo2:%[0-9]+]]:gpr64 = MOPSMemoryMovePseudo [[COPY2]], [[COPY1]], [[COPY]], implicit-def dead $nzcv :: (store unknown-size into %ir.out, align 1), (load unknown-size from %ir.in, align 1)
; CHECK-SD-NEXT: RET_ReallyLR
;
; CHECK-GI-LABEL: name: test
; CHECK-GI: bb.1.entry:
; CHECK-GI-NEXT: liveins: $x0, $x1, $x2
; CHECK-GI-NEXT: {{ $}}
; CHECK-GI-NEXT: [[COPY:%[0-9]+]]:gpr64common = COPY $x0
; CHECK-GI-NEXT: [[COPY1:%[0-9]+]]:gpr64common = COPY $x1
; CHECK-GI-NEXT: [[COPY2:%[0-9]+]]:gpr64 = COPY $x2
; CHECK-GI-NEXT: [[MOPSMemoryMovePseudo:%[0-9]+]]:gpr64common, [[MOPSMemoryMovePseudo1:%[0-9]+]]:gpr64common, [[MOPSMemoryMovePseudo2:%[0-9]+]]:gpr64 = MOPSMemoryMovePseudo [[COPY]], [[COPY1]], [[COPY2]], implicit-def dead $nzcv
; CHECK-GI-NEXT: RET_ReallyLR
entry:
call void @llvm.memmove.p0.p0.i64(ptr %out, ptr %in, i64 %a, i1 false)
ret void
}