[llvm] 3b9795b - [AArch64] Add CodeGen support for scalar FEAT_CPA (#105669)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 20 13:14:55 PDT 2025
Author: Rodolfo Wottrich
Date: 2025-06-20T21:14:52+01:00
New Revision: 3b9795b3d3b249a5a3052a44f2c1ad7268ed34c6
URL: https://github.com/llvm/llvm-project/commit/3b9795b3d3b249a5a3052a44f2c1ad7268ed34c6
DIFF: https://github.com/llvm/llvm-project/commit/3b9795b3d3b249a5a3052a44f2c1ad7268ed34c6.diff
LOG: [AArch64] Add CodeGen support for scalar FEAT_CPA (#105669)
CPA stands for Checked Pointer Arithmetic and is part of the 2023 MTE
architecture extensions for A-profile.
The new CPA instructions perform regular pointer arithmetic (such as
base register + offset) but check for overflow in the most significant
bits of the result, enhancing security by detecting address tampering.
In this patch we intend to capture the semantics of pointer arithmetic
when it is not folded into loads/stores, then generate the appropriate
scalar CPA instructions. In order to preserve pointer arithmetic
semantics through the backend, we use the PTRADD SelectionDAG node type.
Use backend option `-aarch64-use-featcpa-codegen=true` to enable CPA
CodeGen (for a target with CPA enabled).
The story of this PR is that initially it introduced the PTRADD
SelectionDAG node and the respective visitPTRADD() function, adapted
from the CHERI/Morello LLVM tree. The original authors are
@davidchisnall, @jrtc27, @arichardson.
After a while, @ritter-x2a took the part of the code that was
target-independent and merged it separately in #140017. This PR thus
remains as the AArch64-part only.
Mode details about the CPA extension can be found at:
-
https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/arm-a-profile-architecture-developments-2023
- https://developer.arm.com/documentation/ddi0602/2023-09/ (e.g ADDPT
instruction)
This PR follows #79569.
It does not address vector FEAT_CPA instructions.
Added:
llvm/test/CodeGen/AArch64/cpa-globalisel.ll
llvm/test/CodeGen/AArch64/cpa-selectiondag.ll
Modified:
llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
llvm/lib/Target/AArch64/AArch64ISelLowering.h
llvm/lib/Target/AArch64/AArch64InstrFormats.td
llvm/lib/Target/AArch64/AArch64InstrInfo.td
llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index e9d05710cbc4f..a2c914c6e09c2 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -153,6 +153,14 @@ cl::opt<bool> EnableSVEGISel(
cl::desc("Enable / disable SVE scalable vectors in Global ISel"),
cl::init(false));
+// TODO: This option should be removed once we switch to always using PTRADD in
+// the SelectionDAG.
+static cl::opt<bool> UseFEATCPACodegen(
+ "aarch64-use-featcpa-codegen", cl::Hidden,
+ cl::desc("Generate ISD::PTRADD nodes for pointer arithmetic in "
+ "SelectionDAG for FEAT_CPA"),
+ cl::init(false));
+
/// Value type used for condition codes.
static const MVT MVT_CC = MVT::i32;
@@ -30480,3 +30488,8 @@ bool AArch64TargetLowering::isTypeDesirableForOp(unsigned Opc, EVT VT) const {
return TargetLowering::isTypeDesirableForOp(Opc, VT);
}
+
+bool AArch64TargetLowering::shouldPreservePtrArith(const Function &F,
+ EVT VT) const {
+ return Subtarget->hasCPA() && UseFEATCPACodegen;
+}
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
index e0b6c1b8c0baf..89f90ee2b7707 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
@@ -539,6 +539,10 @@ class AArch64TargetLowering : public TargetLowering {
/// True if stack clash protection is enabled for this functions.
bool hasInlineStackProbe(const MachineFunction &MF) const override;
+ /// In AArch64, true if FEAT_CPA is present. Allows pointer arithmetic
+ /// semantics to be preserved for instruction selection.
+ bool shouldPreservePtrArith(const Function &F, EVT PtrVT) const override;
+
private:
/// Keep a pointer to the AArch64Subtarget around so that we can
/// make the right decision when generating code for
diff erent targets.
diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
index 9078748c14834..ba7cbccc0bcd6 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td
@@ -13124,7 +13124,7 @@ def LSLImm3ShiftOperand : AsmOperandClass {
let DiagnosticType = "AddSubLSLImm3ShiftLarge";
}
-def lsl_imm3_shift_operand : Operand<i32> {
+def lsl_imm3_shift_operand : Operand<i64> {
let PrintMethod = "printShifter";
let ParserMatchClass = LSLImm3ShiftOperand;
}
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index efe6cc1aa8aec..0f3f24f0853c9 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -10741,6 +10741,21 @@ let Predicates = [HasCPA] in {
// Scalar multiply-add/subtract
def MADDPT : MulAccumCPA<0, "maddpt">;
def MSUBPT : MulAccumCPA<1, "msubpt">;
+
+ def : Pat<(ptradd GPR64sp:$Rn, GPR64sp:$Rm),
+ (ADDPT_shift GPR64sp:$Rn, GPR64sp:$Rm, (i64 0))>;
+ def : Pat<(ptradd GPR64sp:$Rn, (shl GPR64sp:$Rm, (i64 imm0_7:$imm))),
+ (ADDPT_shift GPR64sp:$Rn, GPR64sp:$Rm,
+ (i64 imm0_7:$imm))>;
+ def : Pat<(ptradd GPR64sp:$Rn, (ineg GPR64sp:$Rm)),
+ (SUBPT_shift GPR64sp:$Rn, GPR64sp:$Rm, (i64 0))>;
+ def : Pat<(ptradd GPR64sp:$Rn, (ineg (shl GPR64sp:$Rm, (i64 imm0_7:$imm)))),
+ (SUBPT_shift GPR64sp:$Rn, GPR64sp:$Rm,
+ (i64 imm0_7:$imm))>;
+ def : Pat<(ptradd GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)),
+ (MADDPT GPR64:$Rn, GPR64:$Rm, GPR64:$Ra)>;
+ def : Pat<(ptradd GPR64:$Ra, (mul GPR64:$Rn, (ineg GPR64:$Rm))),
+ (MSUBPT GPR64:$Rn, GPR64:$Rm, GPR64:$Ra)>;
}
def round_v4fp32_to_v4bf16 :
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index 51b42325ef842..5081cc4bba144 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -2197,8 +2197,14 @@ bool AArch64InstructionSelector::preISelLower(MachineInstr &I) {
}
return Changed;
}
- case TargetOpcode::G_PTR_ADD:
+ case TargetOpcode::G_PTR_ADD: {
+ // If Checked Pointer Arithmetic (FEAT_CPA) is present, preserve the pointer
+ // arithmetic semantics instead of falling back to regular arithmetic.
+ const auto &TL = STI.getTargetLowering();
+ if (TL->shouldPreservePtrArith(MF.getFunction(), EVT()))
+ return false;
return convertPtrAddToAdd(I, MRI);
+ }
case TargetOpcode::G_LOAD: {
// For scalar loads of pointers, we try to convert the dest type from p0
// to s64 so that our imported patterns can match. Like with the G_PTR_ADD
diff --git a/llvm/test/CodeGen/AArch64/cpa-globalisel.ll b/llvm/test/CodeGen/AArch64/cpa-globalisel.ll
new file mode 100644
index 0000000000000..c9b48b9685df3
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/cpa-globalisel.ll
@@ -0,0 +1,776 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=aarch64 -verify-machineinstrs --mattr=+cpa -aarch64-use-featcpa-codegen=true -O0 -global-isel=1 %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK-CPA-O0
+; RUN: llc -mtriple=aarch64 -verify-machineinstrs --mattr=+cpa -aarch64-use-featcpa-codegen=true -O3 -global-isel=1 %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK-CPA-O3
+; RUN: llc -mtriple=aarch64 -verify-machineinstrs --mattr=-cpa -O0 -global-isel=1 %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK-NOCPA-O0
+; RUN: llc -mtriple=aarch64 -verify-machineinstrs --mattr=-cpa -O3 -global-isel=1 %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK-NOCPA-O3
+
+%struct.my_type = type { i64, i64 }
+%struct.my_type2 = type { i64, i64, i64, i64, i64, i64 }
+
+ at array = external dso_local global [10 x %struct.my_type], align 8
+ at array2 = external dso_local global [10 x %struct.my_type2], align 8
+
+define void @addpt1(i64 %index, i64 %arg) {
+; CHECK-CPA-O0-LABEL: addpt1:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: adrp x8, array
+; CHECK-CPA-O0-NEXT: add x8, x8, :lo12:array
+; CHECK-CPA-O0-NEXT: addpt x8, x8, x0, lsl #4
+; CHECK-CPA-O0-NEXT: str x1, [x8, #8]
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: addpt1:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: adrp x8, array
+; CHECK-CPA-O3-NEXT: add x8, x8, :lo12:array
+; CHECK-CPA-O3-NEXT: addpt x8, x8, x0, lsl #4
+; CHECK-CPA-O3-NEXT: str x1, [x8, #8]
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: addpt1:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: adrp x8, array
+; CHECK-NOCPA-O0-NEXT: add x8, x8, :lo12:array
+; CHECK-NOCPA-O0-NEXT: add x8, x8, x0, lsl #4
+; CHECK-NOCPA-O0-NEXT: str x1, [x8, #8]
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: addpt1:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: adrp x8, array
+; CHECK-NOCPA-O3-NEXT: add x8, x8, :lo12:array
+; CHECK-NOCPA-O3-NEXT: add x8, x8, x0, lsl #4
+; CHECK-NOCPA-O3-NEXT: str x1, [x8, #8]
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %e2 = getelementptr inbounds %struct.my_type, ptr @array, i64 %index, i32 1
+ store i64 %arg, ptr %e2, align 8
+ ret void
+}
+
+define void @maddpt1(i32 %pos, ptr %val) {
+; CHECK-CPA-O0-LABEL: maddpt1:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: // implicit-def: $x8
+; CHECK-CPA-O0-NEXT: mov w8, w0
+; CHECK-CPA-O0-NEXT: sxtw x8, w8
+; CHECK-CPA-O0-NEXT: mov w9, #48 // =0x30
+; CHECK-CPA-O0-NEXT: // kill: def $x9 killed $w9
+; CHECK-CPA-O0-NEXT: adrp x10, array2
+; CHECK-CPA-O0-NEXT: add x10, x10, :lo12:array2
+; CHECK-CPA-O0-NEXT: maddpt x0, x8, x9, x10
+; CHECK-CPA-O0-NEXT: mov w8, #48 // =0x30
+; CHECK-CPA-O0-NEXT: mov w2, w8
+; CHECK-CPA-O0-NEXT: b memcpy
+;
+; CHECK-CPA-O3-LABEL: maddpt1:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: // kill: def $w0 killed $w0 def $x0
+; CHECK-CPA-O3-NEXT: sxtw x9, w0
+; CHECK-CPA-O3-NEXT: mov w8, #48 // =0x30
+; CHECK-CPA-O3-NEXT: ldr q0, [x1]
+; CHECK-CPA-O3-NEXT: adrp x10, array2
+; CHECK-CPA-O3-NEXT: add x10, x10, :lo12:array2
+; CHECK-CPA-O3-NEXT: maddpt x8, x9, x8, x10
+; CHECK-CPA-O3-NEXT: str q0, [x8]
+; CHECK-CPA-O3-NEXT: ldr q0, [x1, #16]
+; CHECK-CPA-O3-NEXT: str q0, [x8, #16]
+; CHECK-CPA-O3-NEXT: ldr q0, [x1, #32]
+; CHECK-CPA-O3-NEXT: str q0, [x8, #32]
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: maddpt1:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: adrp x9, array2
+; CHECK-NOCPA-O0-NEXT: add x9, x9, :lo12:array2
+; CHECK-NOCPA-O0-NEXT: mov w8, #48 // =0x30
+; CHECK-NOCPA-O0-NEXT: smaddl x0, w0, w8, x9
+; CHECK-NOCPA-O0-NEXT: mov w8, #48 // =0x30
+; CHECK-NOCPA-O0-NEXT: mov w2, w8
+; CHECK-NOCPA-O0-NEXT: b memcpy
+;
+; CHECK-NOCPA-O3-LABEL: maddpt1:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: mov w8, #48 // =0x30
+; CHECK-NOCPA-O3-NEXT: adrp x9, array2
+; CHECK-NOCPA-O3-NEXT: add x9, x9, :lo12:array2
+; CHECK-NOCPA-O3-NEXT: smaddl x8, w0, w8, x9
+; CHECK-NOCPA-O3-NEXT: ldr q0, [x1]
+; CHECK-NOCPA-O3-NEXT: str q0, [x8]
+; CHECK-NOCPA-O3-NEXT: ldr q0, [x1, #16]
+; CHECK-NOCPA-O3-NEXT: str q0, [x8, #16]
+; CHECK-NOCPA-O3-NEXT: ldr q0, [x1, #32]
+; CHECK-NOCPA-O3-NEXT: str q0, [x8, #32]
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %idxprom = sext i32 %pos to i64
+ %arrayidx = getelementptr inbounds [10 x %struct.my_type2], ptr @array2, i64 0, i64 %idxprom
+ tail call void @llvm.memcpy.p0.p0.i64(ptr align 8 dereferenceable(48) %arrayidx, ptr align 8 dereferenceable(48) %val, i64 48, i1 false)
+ ret void
+}
+
+define void @msubpt1(i32 %index, i32 %elem) {
+; CHECK-CPA-O0-LABEL: msubpt1:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: // implicit-def: $x8
+; CHECK-CPA-O0-NEXT: mov w8, w0
+; CHECK-CPA-O0-NEXT: sxtw x10, w8
+; CHECK-CPA-O0-NEXT: mov w8, #48 // =0x30
+; CHECK-CPA-O0-NEXT: mov w9, w8
+; CHECK-CPA-O0-NEXT: mov w8, #288 // =0x120
+; CHECK-CPA-O0-NEXT: mov w11, w8
+; CHECK-CPA-O0-NEXT: adrp x8, array2
+; CHECK-CPA-O0-NEXT: add x8, x8, :lo12:array2
+; CHECK-CPA-O0-NEXT: addpt x11, x8, x11
+; CHECK-CPA-O0-NEXT: msubpt x0, x9, x10, x11
+; CHECK-CPA-O0-NEXT: mov w9, #48 // =0x30
+; CHECK-CPA-O0-NEXT: mov w2, w9
+; CHECK-CPA-O0-NEXT: mov w9, #96 // =0x60
+; CHECK-CPA-O0-NEXT: // kill: def $x9 killed $w9
+; CHECK-CPA-O0-NEXT: addpt x1, x8, x9
+; CHECK-CPA-O0-NEXT: b memcpy
+;
+; CHECK-CPA-O3-LABEL: msubpt1:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: // kill: def $w0 killed $w0 def $x0
+; CHECK-CPA-O3-NEXT: sxtw x9, w0
+; CHECK-CPA-O3-NEXT: adrp x10, array2+96
+; CHECK-CPA-O3-NEXT: add x10, x10, :lo12:array2+96
+; CHECK-CPA-O3-NEXT: mov w8, #48 // =0x30
+; CHECK-CPA-O3-NEXT: ldr q0, [x10]
+; CHECK-CPA-O3-NEXT: msubpt x8, x8, x9, x10
+; CHECK-CPA-O3-NEXT: str q0, [x8, #192]
+; CHECK-CPA-O3-NEXT: ldr q0, [x10, #16]
+; CHECK-CPA-O3-NEXT: str q0, [x8, #208]
+; CHECK-CPA-O3-NEXT: ldr q0, [x10, #32]
+; CHECK-CPA-O3-NEXT: str q0, [x8, #224]
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: msubpt1:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: // implicit-def: $x8
+; CHECK-NOCPA-O0-NEXT: mov w8, w0
+; CHECK-NOCPA-O0-NEXT: sxtw x8, w8
+; CHECK-NOCPA-O0-NEXT: mov w9, #48 // =0x30
+; CHECK-NOCPA-O0-NEXT: // kill: def $x9 killed $w9
+; CHECK-NOCPA-O0-NEXT: mneg x10, x8, x9
+; CHECK-NOCPA-O0-NEXT: adrp x8, array2
+; CHECK-NOCPA-O0-NEXT: add x8, x8, :lo12:array2
+; CHECK-NOCPA-O0-NEXT: add x9, x8, #288
+; CHECK-NOCPA-O0-NEXT: add x0, x9, x10
+; CHECK-NOCPA-O0-NEXT: mov w9, #48 // =0x30
+; CHECK-NOCPA-O0-NEXT: mov w2, w9
+; CHECK-NOCPA-O0-NEXT: add x1, x8, #96
+; CHECK-NOCPA-O0-NEXT: b memcpy
+;
+; CHECK-NOCPA-O3-LABEL: msubpt1:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: // kill: def $w0 killed $w0 def $x0
+; CHECK-NOCPA-O3-NEXT: sxtw x8, w0
+; CHECK-NOCPA-O3-NEXT: mov w9, #48 // =0x30
+; CHECK-NOCPA-O3-NEXT: mneg x8, x8, x9
+; CHECK-NOCPA-O3-NEXT: adrp x9, array2+96
+; CHECK-NOCPA-O3-NEXT: add x9, x9, :lo12:array2+96
+; CHECK-NOCPA-O3-NEXT: ldr q0, [x9]
+; CHECK-NOCPA-O3-NEXT: add x8, x9, x8
+; CHECK-NOCPA-O3-NEXT: str q0, [x8, #192]
+; CHECK-NOCPA-O3-NEXT: ldr q0, [x9, #16]
+; CHECK-NOCPA-O3-NEXT: str q0, [x8, #208]
+; CHECK-NOCPA-O3-NEXT: ldr q0, [x9, #32]
+; CHECK-NOCPA-O3-NEXT: str q0, [x8, #224]
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %idx.ext = sext i32 %index to i64
+ %idx.neg = sub nsw i64 0, %idx.ext
+ %add.ptr = getelementptr inbounds %struct.my_type2, ptr getelementptr inbounds ([10 x %struct.my_type2], ptr @array2, i64 0, i64 6), i64 %idx.neg
+ tail call void @llvm.memcpy.p0.p0.i64(ptr align 8 dereferenceable(48) %add.ptr, ptr align 8 dereferenceable(48) getelementptr inbounds ([10 x %struct.my_type2], ptr @array2, i64 0, i64 2), i64 48, i1 false), !tbaa.struct !6
+ ret void
+}
+
+define void @subpt1(i32 %index, i32 %elem) {
+; CHECK-CPA-O0-LABEL: subpt1:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: mov w8, #-16 // =0xfffffff0
+; CHECK-CPA-O0-NEXT: smull x9, w0, w8
+; CHECK-CPA-O0-NEXT: adrp x8, array
+; CHECK-CPA-O0-NEXT: add x8, x8, :lo12:array
+; CHECK-CPA-O0-NEXT: ldr q0, [x8, #32]
+; CHECK-CPA-O0-NEXT: mov w10, #96 // =0x60
+; CHECK-CPA-O0-NEXT: // kill: def $x10 killed $w10
+; CHECK-CPA-O0-NEXT: addpt x8, x8, x10
+; CHECK-CPA-O0-NEXT: str q0, [x8, x9, lsl #4]
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: subpt1:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: mov w8, #-16 // =0xfffffff0
+; CHECK-CPA-O3-NEXT: adrp x9, array+32
+; CHECK-CPA-O3-NEXT: add x9, x9, :lo12:array+32
+; CHECK-CPA-O3-NEXT: smull x8, w0, w8
+; CHECK-CPA-O3-NEXT: ldr q0, [x9]
+; CHECK-CPA-O3-NEXT: addpt x8, x9, x8, lsl #4
+; CHECK-CPA-O3-NEXT: str q0, [x8, #64]
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: subpt1:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: mov w8, #-16 // =0xfffffff0
+; CHECK-NOCPA-O0-NEXT: smull x9, w0, w8
+; CHECK-NOCPA-O0-NEXT: adrp x8, array
+; CHECK-NOCPA-O0-NEXT: add x8, x8, :lo12:array
+; CHECK-NOCPA-O0-NEXT: ldr q0, [x8, #32]
+; CHECK-NOCPA-O0-NEXT: add x8, x8, #96
+; CHECK-NOCPA-O0-NEXT: str q0, [x8, x9, lsl #4]
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: subpt1:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: mov w8, #-16 // =0xfffffff0
+; CHECK-NOCPA-O3-NEXT: adrp x9, array+32
+; CHECK-NOCPA-O3-NEXT: add x9, x9, :lo12:array+32
+; CHECK-NOCPA-O3-NEXT: smull x8, w0, w8
+; CHECK-NOCPA-O3-NEXT: ldr q0, [x9]
+; CHECK-NOCPA-O3-NEXT: add x8, x9, x8, lsl #4
+; CHECK-NOCPA-O3-NEXT: str q0, [x8, #64]
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %conv = sext i32 %index to i64
+ %mul.neg = mul nsw i64 %conv, -16
+ %add.ptr = getelementptr inbounds %struct.my_type, ptr getelementptr inbounds ([10 x %struct.my_type], ptr @array, i64 0, i64 6), i64 %mul.neg
+ tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 8 dereferenceable(16) %add.ptr, ptr noundef nonnull align 8 dereferenceable(16) getelementptr inbounds ([10 x %struct.my_type], ptr @array, i64 0, i64 2), i64 16, i1 false), !tbaa.struct !6
+ ret void
+}
+
+define void @subpt2(i32 %index, i32 %elem) {
+; CHECK-CPA-O0-LABEL: subpt2:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: mov x8, xzr
+; CHECK-CPA-O0-NEXT: subs x9, x8, w0, sxtw
+; CHECK-CPA-O0-NEXT: adrp x8, array
+; CHECK-CPA-O0-NEXT: add x8, x8, :lo12:array
+; CHECK-CPA-O0-NEXT: ldr q0, [x8, #32]
+; CHECK-CPA-O0-NEXT: mov w10, #96 // =0x60
+; CHECK-CPA-O0-NEXT: // kill: def $x10 killed $w10
+; CHECK-CPA-O0-NEXT: addpt x8, x8, x10
+; CHECK-CPA-O0-NEXT: str q0, [x8, x9, lsl #4]
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: subpt2:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: mov x8, xzr
+; CHECK-CPA-O3-NEXT: adrp x9, array+32
+; CHECK-CPA-O3-NEXT: add x9, x9, :lo12:array+32
+; CHECK-CPA-O3-NEXT: sub x8, x8, w0, sxtw
+; CHECK-CPA-O3-NEXT: ldr q0, [x9]
+; CHECK-CPA-O3-NEXT: addpt x8, x9, x8, lsl #4
+; CHECK-CPA-O3-NEXT: str q0, [x8, #64]
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: subpt2:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: mov x8, xzr
+; CHECK-NOCPA-O0-NEXT: subs x9, x8, w0, sxtw
+; CHECK-NOCPA-O0-NEXT: adrp x8, array
+; CHECK-NOCPA-O0-NEXT: add x8, x8, :lo12:array
+; CHECK-NOCPA-O0-NEXT: ldr q0, [x8, #32]
+; CHECK-NOCPA-O0-NEXT: add x8, x8, #96
+; CHECK-NOCPA-O0-NEXT: str q0, [x8, x9, lsl #4]
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: subpt2:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: mov x8, xzr
+; CHECK-NOCPA-O3-NEXT: adrp x9, array+32
+; CHECK-NOCPA-O3-NEXT: add x9, x9, :lo12:array+32
+; CHECK-NOCPA-O3-NEXT: sub x8, x8, w0, sxtw
+; CHECK-NOCPA-O3-NEXT: ldr q0, [x9]
+; CHECK-NOCPA-O3-NEXT: add x8, x9, x8, lsl #4
+; CHECK-NOCPA-O3-NEXT: str q0, [x8, #64]
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %idx.ext = sext i32 %index to i64
+ %idx.neg = sub nsw i64 0, %idx.ext
+ %add.ptr = getelementptr inbounds %struct.my_type, ptr getelementptr inbounds ([10 x %struct.my_type], ptr @array, i64 0, i64 6), i64 %idx.neg
+ tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 8 dereferenceable(16) %add.ptr, ptr noundef nonnull align 8 dereferenceable(16) getelementptr inbounds ([10 x %struct.my_type], ptr @array, i64 0, i64 2), i64 16, i1 false), !tbaa.struct !11
+ ret void
+}
+
+define ptr @subpt3(ptr %ptr, i32 %index) {
+; CHECK-CPA-O0-LABEL: subpt3:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: mov x8, #-8 // =0xfffffffffffffff8
+; CHECK-CPA-O0-NEXT: addpt x0, x0, x8
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: subpt3:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: mov x8, #-8 // =0xfffffffffffffff8
+; CHECK-CPA-O3-NEXT: addpt x0, x0, x8
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: subpt3:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: subs x0, x0, #8
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: subpt3:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: sub x0, x0, #8
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %incdec.ptr.i.i.i = getelementptr inbounds i64, ptr %ptr, i64 -1
+ ret ptr %incdec.ptr.i.i.i
+}
+
+define i64 @subi64(i64 %ptr, i32 %index) {
+; CHECK-CPA-O0-LABEL: subi64:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: subs x0, x0, #1
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: subi64:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: sub x0, x0, #1
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: subi64:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: subs x0, x0, #1
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: subi64:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: sub x0, x0, #1
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %incdec.ptr.i.i.i = add i64 %ptr, -1
+ ret i64 %incdec.ptr.i.i.i
+}
+
+define i32 @subi32(i32 %ptr, i32 %index) {
+; CHECK-CPA-O0-LABEL: subi32:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: subs w0, w0, #1
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: subi32:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: sub w0, w0, #1
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: subi32:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: subs w0, w0, #1
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: subi32:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: sub w0, w0, #1
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %incdec.ptr.i.i.i = add i32 %ptr, -1
+ ret i32 %incdec.ptr.i.i.i
+}
+
+define i16 @subi16(i16 %ptr, i32 %index) {
+; CHECK-CPA-O0-LABEL: subi16:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: subs w0, w0, #1
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: subi16:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: sub w0, w0, #1
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: subi16:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: subs w0, w0, #1
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: subi16:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: sub w0, w0, #1
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %incdec.ptr.i.i.i = add i16 %ptr, -1
+ ret i16 %incdec.ptr.i.i.i
+}
+
+define i64 @addi64(i64 %ptr, i32 %index) {
+; CHECK-CPA-O0-LABEL: addi64:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: add x0, x0, #1
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: addi64:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: add x0, x0, #1
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: addi64:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: add x0, x0, #1
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: addi64:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: add x0, x0, #1
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %incdec.ptr.i.i.i = add i64 %ptr, 1
+ ret i64 %incdec.ptr.i.i.i
+}
+
+define i32 @addi32(i32 %ptr, i32 %index) {
+; CHECK-CPA-O0-LABEL: addi32:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: add w0, w0, #1
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: addi32:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: add w0, w0, #1
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: addi32:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: add w0, w0, #1
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: addi32:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: add w0, w0, #1
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %incdec.ptr.i.i.i = add i32 %ptr, 1
+ ret i32 %incdec.ptr.i.i.i
+}
+
+define i16 @addi16(i16 %ptr, i32 %index) {
+; CHECK-CPA-O0-LABEL: addi16:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: add w0, w0, #1
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: addi16:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: add w0, w0, #1
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: addi16:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: add w0, w0, #1
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: addi16:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: add w0, w0, #1
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %incdec.ptr.i.i.i = add i16 %ptr, 1
+ ret i16 %incdec.ptr.i.i.i
+}
+
+define i64 @arith1(i64 noundef %0, i64 noundef %1, i64 noundef %2) {
+; CHECK-CPA-O0-LABEL: arith1:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: sub sp, sp, #32
+; CHECK-CPA-O0-NEXT: .cfi_def_cfa_offset 32
+; CHECK-CPA-O0-NEXT: str x0, [sp, #24]
+; CHECK-CPA-O0-NEXT: str x1, [sp, #16]
+; CHECK-CPA-O0-NEXT: str x2, [sp, #8]
+; CHECK-CPA-O0-NEXT: ldr x8, [sp, #24]
+; CHECK-CPA-O0-NEXT: ldr x9, [sp, #16]
+; CHECK-CPA-O0-NEXT: ldr x10, [sp, #8]
+; CHECK-CPA-O0-NEXT: mul x9, x9, x10
+; CHECK-CPA-O0-NEXT: add x0, x8, x9
+; CHECK-CPA-O0-NEXT: add sp, sp, #32
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: arith1:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: sub sp, sp, #32
+; CHECK-CPA-O3-NEXT: .cfi_def_cfa_offset 32
+; CHECK-CPA-O3-NEXT: stp x2, x1, [sp, #8]
+; CHECK-CPA-O3-NEXT: str x0, [sp, #24]
+; CHECK-CPA-O3-NEXT: madd x0, x1, x2, x0
+; CHECK-CPA-O3-NEXT: add sp, sp, #32
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: arith1:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: sub sp, sp, #32
+; CHECK-NOCPA-O0-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NOCPA-O0-NEXT: str x0, [sp, #24]
+; CHECK-NOCPA-O0-NEXT: str x1, [sp, #16]
+; CHECK-NOCPA-O0-NEXT: str x2, [sp, #8]
+; CHECK-NOCPA-O0-NEXT: ldr x8, [sp, #24]
+; CHECK-NOCPA-O0-NEXT: ldr x9, [sp, #16]
+; CHECK-NOCPA-O0-NEXT: ldr x10, [sp, #8]
+; CHECK-NOCPA-O0-NEXT: mul x9, x9, x10
+; CHECK-NOCPA-O0-NEXT: add x0, x8, x9
+; CHECK-NOCPA-O0-NEXT: add sp, sp, #32
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: arith1:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: sub sp, sp, #32
+; CHECK-NOCPA-O3-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NOCPA-O3-NEXT: stp x2, x1, [sp, #8]
+; CHECK-NOCPA-O3-NEXT: str x0, [sp, #24]
+; CHECK-NOCPA-O3-NEXT: madd x0, x1, x2, x0
+; CHECK-NOCPA-O3-NEXT: add sp, sp, #32
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %4 = alloca i64, align 8
+ %5 = alloca i64, align 8
+ %6 = alloca i64, align 8
+ store i64 %0, ptr %4, align 8
+ store i64 %1, ptr %5, align 8
+ store i64 %2, ptr %6, align 8
+ %7 = load i64, ptr %4, align 8
+ %8 = load i64, ptr %5, align 8
+ %9 = load i64, ptr %6, align 8
+ %10 = mul nsw i64 %8, %9
+ %11 = add nsw i64 %7, %10
+ ret i64 %11
+}
+
+define i64 @arith2(ptr noundef %0, i64 noundef %1, i64 noundef %2, i32 noundef %3) {
+; CHECK-CPA-O0-LABEL: arith2:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: sub sp, sp, #32
+; CHECK-CPA-O0-NEXT: .cfi_def_cfa_offset 32
+; CHECK-CPA-O0-NEXT: str x0, [sp, #24]
+; CHECK-CPA-O0-NEXT: str x1, [sp, #16]
+; CHECK-CPA-O0-NEXT: str x2, [sp, #8]
+; CHECK-CPA-O0-NEXT: str w3, [sp, #4]
+; CHECK-CPA-O0-NEXT: ldr x10, [sp, #24]
+; CHECK-CPA-O0-NEXT: ldrsw x8, [sp, #4]
+; CHECK-CPA-O0-NEXT: mov w9, #48 // =0x30
+; CHECK-CPA-O0-NEXT: // kill: def $x9 killed $w9
+; CHECK-CPA-O0-NEXT: maddpt x8, x8, x9, x10
+; CHECK-CPA-O0-NEXT: ldr x8, [x8, #24]
+; CHECK-CPA-O0-NEXT: ldr x10, [sp, #16]
+; CHECK-CPA-O0-NEXT: ldr x9, [sp, #8]
+; CHECK-CPA-O0-NEXT: mul x10, x10, x9
+; CHECK-CPA-O0-NEXT: add x8, x8, x10
+; CHECK-CPA-O0-NEXT: subs x0, x8, x9
+; CHECK-CPA-O0-NEXT: add sp, sp, #32
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: arith2:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: sub sp, sp, #32
+; CHECK-CPA-O3-NEXT: .cfi_def_cfa_offset 32
+; CHECK-CPA-O3-NEXT: str w3, [sp, #4]
+; CHECK-CPA-O3-NEXT: mov w10, #48 // =0x30
+; CHECK-CPA-O3-NEXT: ldrsw x9, [sp, #4]
+; CHECK-CPA-O3-NEXT: stp x1, x0, [sp, #16]
+; CHECK-CPA-O3-NEXT: maddpt x8, x9, x10, x0
+; CHECK-CPA-O3-NEXT: str x2, [sp, #8]
+; CHECK-CPA-O3-NEXT: ldr x8, [x8, #24]
+; CHECK-CPA-O3-NEXT: madd x8, x1, x2, x8
+; CHECK-CPA-O3-NEXT: sub x0, x8, x2
+; CHECK-CPA-O3-NEXT: add sp, sp, #32
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: arith2:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: sub sp, sp, #32
+; CHECK-NOCPA-O0-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NOCPA-O0-NEXT: str x0, [sp, #24]
+; CHECK-NOCPA-O0-NEXT: str x1, [sp, #16]
+; CHECK-NOCPA-O0-NEXT: str x2, [sp, #8]
+; CHECK-NOCPA-O0-NEXT: str w3, [sp, #4]
+; CHECK-NOCPA-O0-NEXT: ldr x8, [sp, #24]
+; CHECK-NOCPA-O0-NEXT: ldrsw x9, [sp, #4]
+; CHECK-NOCPA-O0-NEXT: mov w10, #48 // =0x30
+; CHECK-NOCPA-O0-NEXT: // kill: def $x10 killed $w10
+; CHECK-NOCPA-O0-NEXT: mul x9, x9, x10
+; CHECK-NOCPA-O0-NEXT: add x8, x8, x9
+; CHECK-NOCPA-O0-NEXT: ldr x8, [x8, #24]
+; CHECK-NOCPA-O0-NEXT: ldr x10, [sp, #16]
+; CHECK-NOCPA-O0-NEXT: ldr x9, [sp, #8]
+; CHECK-NOCPA-O0-NEXT: mul x10, x10, x9
+; CHECK-NOCPA-O0-NEXT: add x8, x8, x10
+; CHECK-NOCPA-O0-NEXT: subs x0, x8, x9
+; CHECK-NOCPA-O0-NEXT: add sp, sp, #32
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: arith2:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: sub sp, sp, #32
+; CHECK-NOCPA-O3-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NOCPA-O3-NEXT: str w3, [sp, #4]
+; CHECK-NOCPA-O3-NEXT: mov w9, #48 // =0x30
+; CHECK-NOCPA-O3-NEXT: ldrsw x8, [sp, #4]
+; CHECK-NOCPA-O3-NEXT: stp x1, x0, [sp, #16]
+; CHECK-NOCPA-O3-NEXT: str x2, [sp, #8]
+; CHECK-NOCPA-O3-NEXT: madd x8, x8, x9, x0
+; CHECK-NOCPA-O3-NEXT: ldr x8, [x8, #24]
+; CHECK-NOCPA-O3-NEXT: madd x8, x1, x2, x8
+; CHECK-NOCPA-O3-NEXT: sub x0, x8, x2
+; CHECK-NOCPA-O3-NEXT: add sp, sp, #32
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %5 = alloca ptr, align 8
+ %6 = alloca i64, align 8
+ %7 = alloca i64, align 8
+ %8 = alloca i32, align 4
+ store ptr %0, ptr %5, align 8
+ store i64 %1, ptr %6, align 8
+ store i64 %2, ptr %7, align 8
+ store i32 %3, ptr %8, align 4
+ %9 = load ptr, ptr %5, align 8
+ %10 = load i32, ptr %8, align 4
+ %11 = sext i32 %10 to i64
+ %12 = getelementptr inbounds %struct.my_type2, ptr %9, i64 %11
+ %13 = getelementptr inbounds %struct.my_type2, ptr %12, i32 0, i32 3
+ %14 = load i64, ptr %13, align 8
+ %15 = load i64, ptr %6, align 8
+ %16 = load i64, ptr %7, align 8
+ %17 = mul nsw i64 %15, %16
+ %18 = add nsw i64 %14, %17
+ %19 = sub nsw i64 %18, %16
+ ret i64 %19
+}
+
+ at a = hidden global [2 x [1 x [2 x i8]]] [[1 x [2 x i8]] [[2 x i8] c"\01\01"], [1 x [2 x i8]] [[2 x i8] c"\01\01"]], align 1
+ at b = hidden global i16 0, align 2
+ at .str = private unnamed_addr constant [7 x i8] c"hello\0A\00", align 1
+
+define hidden void @multidim() {
+; CHECK-CPA-O0-LABEL: multidim:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-CPA-O0-NEXT: .cfi_def_cfa_offset 16
+; CHECK-CPA-O0-NEXT: .cfi_offset w30, -16
+; CHECK-CPA-O0-NEXT: adrp x8, b
+; CHECK-CPA-O0-NEXT: ldrh w9, [x8, :lo12:b]
+; CHECK-CPA-O0-NEXT: mov w10, w9
+; CHECK-CPA-O0-NEXT: ldrh w8, [x8, :lo12:b]
+; CHECK-CPA-O0-NEXT: add w9, w8, #1
+; CHECK-CPA-O0-NEXT: // implicit-def: $x8
+; CHECK-CPA-O0-NEXT: mov w8, w9
+; CHECK-CPA-O0-NEXT: sxtw x9, w8
+; CHECK-CPA-O0-NEXT: mov w8, #2 // =0x2
+; CHECK-CPA-O0-NEXT: mov w11, w8
+; CHECK-CPA-O0-NEXT: adrp x8, a
+; CHECK-CPA-O0-NEXT: add x8, x8, :lo12:a
+; CHECK-CPA-O0-NEXT: addpt x8, x8, x11
+; CHECK-CPA-O0-NEXT: addpt x8, x8, x10, lsl #1
+; CHECK-CPA-O0-NEXT: addpt x8, x8, x9
+; CHECK-CPA-O0-NEXT: ldrb w8, [x8]
+; CHECK-CPA-O0-NEXT: cbz w8, .LBB14_2
+; CHECK-CPA-O0-NEXT: b .LBB14_1
+; CHECK-CPA-O0-NEXT: .LBB14_1:
+; CHECK-CPA-O0-NEXT: adrp x0, .L.str
+; CHECK-CPA-O0-NEXT: add x0, x0, :lo12:.L.str
+; CHECK-CPA-O0-NEXT: bl printf
+; CHECK-CPA-O0-NEXT: b .LBB14_2
+; CHECK-CPA-O0-NEXT: .LBB14_2:
+; CHECK-CPA-O0-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: multidim:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: adrp x8, b
+; CHECK-CPA-O3-NEXT: adrp x10, a+2
+; CHECK-CPA-O3-NEXT: add x10, x10, :lo12:a+2
+; CHECK-CPA-O3-NEXT: ldrh w9, [x8, :lo12:b]
+; CHECK-CPA-O3-NEXT: ldrh w8, [x8, :lo12:b]
+; CHECK-CPA-O3-NEXT: addpt x9, x10, x9, lsl #1
+; CHECK-CPA-O3-NEXT: addpt x8, x9, x8
+; CHECK-CPA-O3-NEXT: ldrb w8, [x8, #1]
+; CHECK-CPA-O3-NEXT: cbz w8, .LBB14_2
+; CHECK-CPA-O3-NEXT: // %bb.1:
+; CHECK-CPA-O3-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-CPA-O3-NEXT: .cfi_def_cfa_offset 16
+; CHECK-CPA-O3-NEXT: .cfi_offset w30, -16
+; CHECK-CPA-O3-NEXT: adrp x0, .L.str
+; CHECK-CPA-O3-NEXT: add x0, x0, :lo12:.L.str
+; CHECK-CPA-O3-NEXT: bl printf
+; CHECK-CPA-O3-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; CHECK-CPA-O3-NEXT: .LBB14_2:
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: multidim:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-NOCPA-O0-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NOCPA-O0-NEXT: .cfi_offset w30, -16
+; CHECK-NOCPA-O0-NEXT: adrp x8, b
+; CHECK-NOCPA-O0-NEXT: ldrh w9, [x8, :lo12:b]
+; CHECK-NOCPA-O0-NEXT: mov w10, w9
+; CHECK-NOCPA-O0-NEXT: ldrh w8, [x8, :lo12:b]
+; CHECK-NOCPA-O0-NEXT: add w9, w8, #1
+; CHECK-NOCPA-O0-NEXT: adrp x8, a
+; CHECK-NOCPA-O0-NEXT: add x8, x8, :lo12:a
+; CHECK-NOCPA-O0-NEXT: add x8, x8, #2
+; CHECK-NOCPA-O0-NEXT: add x8, x8, x10, lsl #1
+; CHECK-NOCPA-O0-NEXT: add x8, x8, w9, sxtw
+; CHECK-NOCPA-O0-NEXT: ldrb w8, [x8]
+; CHECK-NOCPA-O0-NEXT: cbz w8, .LBB14_2
+; CHECK-NOCPA-O0-NEXT: b .LBB14_1
+; CHECK-NOCPA-O0-NEXT: .LBB14_1:
+; CHECK-NOCPA-O0-NEXT: adrp x0, .L.str
+; CHECK-NOCPA-O0-NEXT: add x0, x0, :lo12:.L.str
+; CHECK-NOCPA-O0-NEXT: bl printf
+; CHECK-NOCPA-O0-NEXT: b .LBB14_2
+; CHECK-NOCPA-O0-NEXT: .LBB14_2:
+; CHECK-NOCPA-O0-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: multidim:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: adrp x8, b
+; CHECK-NOCPA-O3-NEXT: adrp x10, a+2
+; CHECK-NOCPA-O3-NEXT: add x10, x10, :lo12:a+2
+; CHECK-NOCPA-O3-NEXT: ldrh w9, [x8, :lo12:b]
+; CHECK-NOCPA-O3-NEXT: ldrh w8, [x8, :lo12:b]
+; CHECK-NOCPA-O3-NEXT: add x9, x10, x9, lsl #1
+; CHECK-NOCPA-O3-NEXT: add x8, x9, x8
+; CHECK-NOCPA-O3-NEXT: ldrb w8, [x8, #1]
+; CHECK-NOCPA-O3-NEXT: cbz w8, .LBB14_2
+; CHECK-NOCPA-O3-NEXT: // %bb.1:
+; CHECK-NOCPA-O3-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-NOCPA-O3-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NOCPA-O3-NEXT: .cfi_offset w30, -16
+; CHECK-NOCPA-O3-NEXT: adrp x0, .L.str
+; CHECK-NOCPA-O3-NEXT: add x0, x0, :lo12:.L.str
+; CHECK-NOCPA-O3-NEXT: bl printf
+; CHECK-NOCPA-O3-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; CHECK-NOCPA-O3-NEXT: .LBB14_2:
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %1 = load i16, ptr @b, align 2
+ %2 = zext i16 %1 to i64
+ %3 = getelementptr inbounds nuw [1 x [2 x i8]], ptr getelementptr inbounds ([2 x [1 x [2 x i8]]], ptr @a, i64 0, i64 1), i64 0, i64 %2
+ %4 = load i16, ptr @b, align 2
+ %5 = zext i16 %4 to i32
+ %6 = add nsw i32 %5, 1
+ %7 = sext i32 %6 to i64
+ %8 = getelementptr inbounds [2 x i8], ptr %3, i64 0, i64 %7
+ %9 = load i8, ptr %8, align 1
+ %10 = icmp ne i8 %9, 0
+ br i1 %10, label %11, label %13
+
+11:
+ %12 = call i32 (ptr, ...) @printf(ptr noundef @.str)
+ br label %13
+
+13:
+ ret void
+}
+
+declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)
+declare i32 @printf(ptr noundef, ...) #1
+
+!6 = !{i64 0, i64 8, !7, i64 8, i64 8, !7, i64 16, i64 8, !7, i64 24, i64 8, !7, i64 32, i64 8, !7, i64 40, i64 8, !7}
+!7 = !{!8, !8, i64 0}
+!8 = !{!"long", !9, i64 0}
+!9 = !{!"omnipotent char", !10, i64 0}
+!10 = !{!"Simple C++ TBAA"}
+!11 = !{i64 0, i64 8, !7, i64 8, i64 8, !7}
diff --git a/llvm/test/CodeGen/AArch64/cpa-selectiondag.ll b/llvm/test/CodeGen/AArch64/cpa-selectiondag.ll
new file mode 100644
index 0000000000000..69fd6c4de78bc
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/cpa-selectiondag.ll
@@ -0,0 +1,796 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=aarch64 -verify-machineinstrs --mattr=+cpa -aarch64-use-featcpa-codegen=true -O0 -global-isel=0 -fast-isel=0 %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK-CPA-O0
+; RUN: llc -mtriple=aarch64 -verify-machineinstrs --mattr=+cpa -aarch64-use-featcpa-codegen=true -O3 -global-isel=0 -fast-isel=0 %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK-CPA-O3
+; RUN: llc -mtriple=aarch64 -verify-machineinstrs --mattr=-cpa -O0 -global-isel=0 -fast-isel=0 %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK-NOCPA-O0
+; RUN: llc -mtriple=aarch64 -verify-machineinstrs --mattr=-cpa -O3 -global-isel=0 -fast-isel=0 %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK-NOCPA-O3
+
+%struct.my_type = type { i64, i64 }
+%struct.my_type2 = type { i64, i64, i64, i64, i64, i64 }
+
+ at array = external dso_local global [10 x %struct.my_type], align 8
+ at array2 = external dso_local global [10 x %struct.my_type2], align 8
+
+define void @addpt1(i64 %index, i64 %arg) {
+; CHECK-CPA-O0-LABEL: addpt1:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: adrp x8, array
+; CHECK-CPA-O0-NEXT: add x8, x8, :lo12:array
+; CHECK-CPA-O0-NEXT: addpt x8, x8, x0, lsl #4
+; CHECK-CPA-O0-NEXT: str x1, [x8, #8]
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: addpt1:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: adrp x8, array
+; CHECK-CPA-O3-NEXT: add x8, x8, :lo12:array
+; CHECK-CPA-O3-NEXT: addpt x8, x8, x0, lsl #4
+; CHECK-CPA-O3-NEXT: str x1, [x8, #8]
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: addpt1:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: adrp x8, array
+; CHECK-NOCPA-O0-NEXT: add x8, x8, :lo12:array
+; CHECK-NOCPA-O0-NEXT: add x8, x8, x0, lsl #4
+; CHECK-NOCPA-O0-NEXT: str x1, [x8, #8]
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: addpt1:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: adrp x8, array
+; CHECK-NOCPA-O3-NEXT: add x8, x8, :lo12:array
+; CHECK-NOCPA-O3-NEXT: add x8, x8, x0, lsl #4
+; CHECK-NOCPA-O3-NEXT: str x1, [x8, #8]
+; CHECK-NOCPA-O3-NEXT: ret
+
+entry:
+ %e2 = getelementptr inbounds %struct.my_type, ptr @array, i64 %index, i32 1
+ store i64 %arg, ptr %e2, align 8
+ ret void
+}
+
+define void @maddpt1(i32 %pos, ptr %val) {
+; CHECK-CPA-O0-LABEL: maddpt1:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: // implicit-def: $x8
+; CHECK-CPA-O0-NEXT: mov w8, w0
+; CHECK-CPA-O0-NEXT: sxtw x8, w8
+; CHECK-CPA-O0-NEXT: adrp x10, array2
+; CHECK-CPA-O0-NEXT: add x10, x10, :lo12:array2
+; CHECK-CPA-O0-NEXT: mov w9, #48 // =0x30
+; CHECK-CPA-O0-NEXT: // kill: def $x9 killed $w9
+; CHECK-CPA-O0-NEXT: maddpt x8, x8, x9, x10
+; CHECK-CPA-O0-NEXT: ldr q0, [x1]
+; CHECK-CPA-O0-NEXT: ldr q1, [x1, #16]
+; CHECK-CPA-O0-NEXT: ldr q2, [x1, #32]
+; CHECK-CPA-O0-NEXT: str q2, [x8, #32]
+; CHECK-CPA-O0-NEXT: str q1, [x8, #16]
+; CHECK-CPA-O0-NEXT: str q0, [x8]
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: maddpt1:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: // kill: def $w0 killed $w0 def $x0
+; CHECK-CPA-O3-NEXT: sxtw x9, w0
+; CHECK-CPA-O3-NEXT: ldp q1, q0, [x1, #16]
+; CHECK-CPA-O3-NEXT: mov w8, #48 // =0x30
+; CHECK-CPA-O3-NEXT: adrp x10, array2
+; CHECK-CPA-O3-NEXT: add x10, x10, :lo12:array2
+; CHECK-CPA-O3-NEXT: ldr q2, [x1]
+; CHECK-CPA-O3-NEXT: maddpt x8, x9, x8, x10
+; CHECK-CPA-O3-NEXT: stp q1, q0, [x8, #16]
+; CHECK-CPA-O3-NEXT: str q2, [x8]
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: maddpt1:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: adrp x9, array2
+; CHECK-NOCPA-O0-NEXT: add x9, x9, :lo12:array2
+; CHECK-NOCPA-O0-NEXT: mov w8, #48 // =0x30
+; CHECK-NOCPA-O0-NEXT: smaddl x8, w0, w8, x9
+; CHECK-NOCPA-O0-NEXT: ldr q0, [x1]
+; CHECK-NOCPA-O0-NEXT: ldr q1, [x1, #16]
+; CHECK-NOCPA-O0-NEXT: ldr q2, [x1, #32]
+; CHECK-NOCPA-O0-NEXT: str q2, [x8, #32]
+; CHECK-NOCPA-O0-NEXT: str q1, [x8, #16]
+; CHECK-NOCPA-O0-NEXT: str q0, [x8]
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: maddpt1:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: mov w8, #48 // =0x30
+; CHECK-NOCPA-O3-NEXT: adrp x9, array2
+; CHECK-NOCPA-O3-NEXT: add x9, x9, :lo12:array2
+; CHECK-NOCPA-O3-NEXT: smaddl x8, w0, w8, x9
+; CHECK-NOCPA-O3-NEXT: ldp q1, q0, [x1, #16]
+; CHECK-NOCPA-O3-NEXT: ldr q2, [x1]
+; CHECK-NOCPA-O3-NEXT: stp q1, q0, [x8, #16]
+; CHECK-NOCPA-O3-NEXT: str q2, [x8]
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %idxprom = sext i32 %pos to i64
+ %arrayidx = getelementptr inbounds [10 x %struct.my_type2], ptr @array2, i64 0, i64 %idxprom
+ tail call void @llvm.memcpy.p0.p0.i64(ptr align 8 dereferenceable(48) %arrayidx, ptr align 8 dereferenceable(48) %val, i64 48, i1 false)
+ ret void
+}
+
+define void @msubpt1(i32 %index, i32 %elem) {
+; CHECK-CPA-O0-LABEL: msubpt1:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: // implicit-def: $x8
+; CHECK-CPA-O0-NEXT: mov w8, w0
+; CHECK-CPA-O0-NEXT: sxtw x9, w8
+; CHECK-CPA-O0-NEXT: mov x8, xzr
+; CHECK-CPA-O0-NEXT: subs x8, x8, x9
+; CHECK-CPA-O0-NEXT: lsl x8, x8, #1
+; CHECK-CPA-O0-NEXT: subs x10, x8, x9
+; CHECK-CPA-O0-NEXT: adrp x9, array2
+; CHECK-CPA-O0-NEXT: add x9, x9, :lo12:array2
+; CHECK-CPA-O0-NEXT: mov w8, #288 // =0x120
+; CHECK-CPA-O0-NEXT: // kill: def $x8 killed $w8
+; CHECK-CPA-O0-NEXT: addpt x8, x9, x8
+; CHECK-CPA-O0-NEXT: addpt x8, x8, x10, lsl #4
+; CHECK-CPA-O0-NEXT: mov w10, #96 // =0x60
+; CHECK-CPA-O0-NEXT: // kill: def $x10 killed $w10
+; CHECK-CPA-O0-NEXT: addpt x10, x9, x10
+; CHECK-CPA-O0-NEXT: ldr q1, [x10, #16]
+; CHECK-CPA-O0-NEXT: ldr q2, [x10, #32]
+; CHECK-CPA-O0-NEXT: ldr q0, [x9, #96]
+; CHECK-CPA-O0-NEXT: str q2, [x8, #32]
+; CHECK-CPA-O0-NEXT: str q1, [x8, #16]
+; CHECK-CPA-O0-NEXT: str q0, [x8]
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: msubpt1:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: // kill: def $w0 killed $w0 def $x0
+; CHECK-CPA-O3-NEXT: sxtw x9, w0
+; CHECK-CPA-O3-NEXT: adrp x8, array2
+; CHECK-CPA-O3-NEXT: add x8, x8, :lo12:array2
+; CHECK-CPA-O3-NEXT: mov w11, #96 // =0x60
+; CHECK-CPA-O3-NEXT: mov w12, #288 // =0x120
+; CHECK-CPA-O3-NEXT: ldr q2, [x8, #96]
+; CHECK-CPA-O3-NEXT: neg x10, x9
+; CHECK-CPA-O3-NEXT: addpt x11, x8, x11
+; CHECK-CPA-O3-NEXT: lsl x10, x10, #1
+; CHECK-CPA-O3-NEXT: ldp q1, q0, [x11, #16]
+; CHECK-CPA-O3-NEXT: sub x9, x10, x9
+; CHECK-CPA-O3-NEXT: addpt x10, x8, x12
+; CHECK-CPA-O3-NEXT: addpt x9, x10, x9, lsl #4
+; CHECK-CPA-O3-NEXT: stp q1, q0, [x9, #16]
+; CHECK-CPA-O3-NEXT: str q2, [x9]
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: msubpt1:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: // implicit-def: $x8
+; CHECK-NOCPA-O0-NEXT: mov w8, w0
+; CHECK-NOCPA-O0-NEXT: sxtw x8, w8
+; CHECK-NOCPA-O0-NEXT: mov w9, #48 // =0x30
+; CHECK-NOCPA-O0-NEXT: // kill: def $x9 killed $w9
+; CHECK-NOCPA-O0-NEXT: mneg x8, x8, x9
+; CHECK-NOCPA-O0-NEXT: adrp x9, array2
+; CHECK-NOCPA-O0-NEXT: add x9, x9, :lo12:array2
+; CHECK-NOCPA-O0-NEXT: add x8, x9, x8
+; CHECK-NOCPA-O0-NEXT: ldr q0, [x9, #96]
+; CHECK-NOCPA-O0-NEXT: ldr q1, [x9, #112]
+; CHECK-NOCPA-O0-NEXT: ldr q2, [x9, #128]
+; CHECK-NOCPA-O0-NEXT: str q2, [x8, #320]
+; CHECK-NOCPA-O0-NEXT: str q1, [x8, #304]
+; CHECK-NOCPA-O0-NEXT: str q0, [x8, #288]
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: msubpt1:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: // kill: def $w0 killed $w0 def $x0
+; CHECK-NOCPA-O3-NEXT: sxtw x8, w0
+; CHECK-NOCPA-O3-NEXT: mov w9, #48 // =0x30
+; CHECK-NOCPA-O3-NEXT: mneg x8, x8, x9
+; CHECK-NOCPA-O3-NEXT: adrp x9, array2
+; CHECK-NOCPA-O3-NEXT: add x9, x9, :lo12:array2
+; CHECK-NOCPA-O3-NEXT: ldp q1, q0, [x9, #112]
+; CHECK-NOCPA-O3-NEXT: ldr q2, [x9, #96]
+; CHECK-NOCPA-O3-NEXT: add x8, x9, x8
+; CHECK-NOCPA-O3-NEXT: stp q1, q0, [x8, #304]
+; CHECK-NOCPA-O3-NEXT: str q2, [x8, #288]
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %idx.ext = sext i32 %index to i64
+ %idx.neg = sub nsw i64 0, %idx.ext
+ %add.ptr = getelementptr inbounds %struct.my_type2, ptr getelementptr inbounds ([10 x %struct.my_type2], ptr @array2, i64 0, i64 6), i64 %idx.neg
+ tail call void @llvm.memcpy.p0.p0.i64(ptr align 8 dereferenceable(48) %add.ptr, ptr align 8 dereferenceable(48) getelementptr inbounds ([10 x %struct.my_type2], ptr @array2, i64 0, i64 2), i64 48, i1 false), !tbaa.struct !6
+ ret void
+}
+
+define void @subpt1(i32 %index, i32 %elem) {
+; CHECK-CPA-O0-LABEL: subpt1:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: adrp x9, array
+; CHECK-CPA-O0-NEXT: add x9, x9, :lo12:array
+; CHECK-CPA-O0-NEXT: mov w8, #96 // =0x60
+; CHECK-CPA-O0-NEXT: // kill: def $x8 killed $w8
+; CHECK-CPA-O0-NEXT: addpt x8, x9, x8
+; CHECK-CPA-O0-NEXT: // implicit-def: $x10
+; CHECK-CPA-O0-NEXT: mov w10, w0
+; CHECK-CPA-O0-NEXT: sbfiz x10, x10, #8, #32
+; CHECK-CPA-O0-NEXT: subpt x8, x8, x10
+; CHECK-CPA-O0-NEXT: ldr q0, [x9, #32]
+; CHECK-CPA-O0-NEXT: str q0, [x8]
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: subpt1:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: // kill: def $w0 killed $w0 def $x0
+; CHECK-CPA-O3-NEXT: adrp x8, array
+; CHECK-CPA-O3-NEXT: add x8, x8, :lo12:array
+; CHECK-CPA-O3-NEXT: mov w9, #96 // =0x60
+; CHECK-CPA-O3-NEXT: sbfiz x10, x0, #8, #32
+; CHECK-CPA-O3-NEXT: addpt x9, x8, x9
+; CHECK-CPA-O3-NEXT: ldr q0, [x8, #32]
+; CHECK-CPA-O3-NEXT: subpt x8, x9, x10
+; CHECK-CPA-O3-NEXT: str q0, [x8]
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: subpt1:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: // implicit-def: $x8
+; CHECK-NOCPA-O0-NEXT: mov w8, w0
+; CHECK-NOCPA-O0-NEXT: sxtw x8, w8
+; CHECK-NOCPA-O0-NEXT: adrp x9, array
+; CHECK-NOCPA-O0-NEXT: add x9, x9, :lo12:array
+; CHECK-NOCPA-O0-NEXT: subs x8, x9, x8, lsl #8
+; CHECK-NOCPA-O0-NEXT: ldr q0, [x9, #32]
+; CHECK-NOCPA-O0-NEXT: str q0, [x8, #96]
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: subpt1:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: // kill: def $w0 killed $w0 def $x0
+; CHECK-NOCPA-O3-NEXT: sxtw x9, w0
+; CHECK-NOCPA-O3-NEXT: adrp x8, array
+; CHECK-NOCPA-O3-NEXT: add x8, x8, :lo12:array
+; CHECK-NOCPA-O3-NEXT: ldr q0, [x8, #32]
+; CHECK-NOCPA-O3-NEXT: sub x9, x8, x9, lsl #8
+; CHECK-NOCPA-O3-NEXT: str q0, [x9, #96]
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %conv = sext i32 %index to i64
+ %mul.neg = mul nsw i64 %conv, -16
+ %add.ptr = getelementptr inbounds %struct.my_type, ptr getelementptr inbounds ([10 x %struct.my_type], ptr @array, i64 0, i64 6), i64 %mul.neg
+ tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 8 dereferenceable(16) %add.ptr, ptr noundef nonnull align 8 dereferenceable(16) getelementptr inbounds ([10 x %struct.my_type], ptr @array, i64 0, i64 2), i64 16, i1 false), !tbaa.struct !6
+ ret void
+}
+
+define void @subpt2(i32 %index, i32 %elem) {
+; CHECK-CPA-O0-LABEL: subpt2:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: mov x8, xzr
+; CHECK-CPA-O0-NEXT: subs x10, x8, w0, sxtw
+; CHECK-CPA-O0-NEXT: adrp x9, array
+; CHECK-CPA-O0-NEXT: add x9, x9, :lo12:array
+; CHECK-CPA-O0-NEXT: mov w8, #96 // =0x60
+; CHECK-CPA-O0-NEXT: // kill: def $x8 killed $w8
+; CHECK-CPA-O0-NEXT: addpt x8, x9, x8
+; CHECK-CPA-O0-NEXT: addpt x8, x8, x10, lsl #4
+; CHECK-CPA-O0-NEXT: ldr q0, [x9, #32]
+; CHECK-CPA-O0-NEXT: str q0, [x8]
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: subpt2:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: mov x8, xzr
+; CHECK-CPA-O3-NEXT: mov w9, #96 // =0x60
+; CHECK-CPA-O3-NEXT: adrp x10, array
+; CHECK-CPA-O3-NEXT: add x10, x10, :lo12:array
+; CHECK-CPA-O3-NEXT: sub x8, x8, w0, sxtw
+; CHECK-CPA-O3-NEXT: addpt x9, x10, x9
+; CHECK-CPA-O3-NEXT: ldr q0, [x10, #32]
+; CHECK-CPA-O3-NEXT: addpt x8, x9, x8, lsl #4
+; CHECK-CPA-O3-NEXT: str q0, [x8]
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: subpt2:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: adrp x9, array
+; CHECK-NOCPA-O0-NEXT: add x9, x9, :lo12:array
+; CHECK-NOCPA-O0-NEXT: subs x8, x9, w0, sxtw #4
+; CHECK-NOCPA-O0-NEXT: ldr q0, [x9, #32]
+; CHECK-NOCPA-O0-NEXT: str q0, [x8, #96]
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: subpt2:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: adrp x8, array
+; CHECK-NOCPA-O3-NEXT: add x8, x8, :lo12:array
+; CHECK-NOCPA-O3-NEXT: sub x9, x8, w0, sxtw #4
+; CHECK-NOCPA-O3-NEXT: ldr q0, [x8, #32]
+; CHECK-NOCPA-O3-NEXT: str q0, [x9, #96]
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %idx.ext = sext i32 %index to i64
+ %idx.neg = sub nsw i64 0, %idx.ext
+ %add.ptr = getelementptr inbounds %struct.my_type, ptr getelementptr inbounds ([10 x %struct.my_type], ptr @array, i64 0, i64 6), i64 %idx.neg
+ tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 8 dereferenceable(16) %add.ptr, ptr noundef nonnull align 8 dereferenceable(16) getelementptr inbounds ([10 x %struct.my_type], ptr @array, i64 0, i64 2), i64 16, i1 false), !tbaa.struct !11
+ ret void
+}
+
+define ptr @subpt3(ptr %ptr, i32 %index) {
+; CHECK-CPA-O0-LABEL: subpt3:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: mov x8, #-8 // =0xfffffffffffffff8
+; CHECK-CPA-O0-NEXT: addpt x0, x0, x8
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: subpt3:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: mov x8, #-8 // =0xfffffffffffffff8
+; CHECK-CPA-O3-NEXT: addpt x0, x0, x8
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: subpt3:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: subs x0, x0, #8
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: subpt3:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: sub x0, x0, #8
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %incdec.ptr.i.i.i = getelementptr inbounds i64, ptr %ptr, i64 -1
+ ret ptr %incdec.ptr.i.i.i
+}
+
+define i64 @subi64(i64 %ptr, i32 %index) {
+; CHECK-CPA-O0-LABEL: subi64:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: subs x0, x0, #1
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: subi64:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: sub x0, x0, #1
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: subi64:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: subs x0, x0, #1
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: subi64:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: sub x0, x0, #1
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %incdec.ptr.i.i.i = add i64 %ptr, -1
+ ret i64 %incdec.ptr.i.i.i
+}
+
+define i32 @subi32(i32 %ptr, i32 %index) {
+; CHECK-CPA-O0-LABEL: subi32:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: subs w0, w0, #1
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: subi32:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: sub w0, w0, #1
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: subi32:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: subs w0, w0, #1
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: subi32:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: sub w0, w0, #1
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %incdec.ptr.i.i.i = add i32 %ptr, -1
+ ret i32 %incdec.ptr.i.i.i
+}
+
+define i16 @subi16(i16 %ptr, i32 %index) {
+; CHECK-CPA-O0-LABEL: subi16:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: subs w0, w0, #1
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: subi16:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: sub w0, w0, #1
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: subi16:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: subs w0, w0, #1
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: subi16:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: sub w0, w0, #1
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %incdec.ptr.i.i.i = add i16 %ptr, -1
+ ret i16 %incdec.ptr.i.i.i
+}
+
+define i64 @addi64(i64 %ptr, i32 %index) {
+; CHECK-CPA-O0-LABEL: addi64:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: add x0, x0, #1
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: addi64:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: add x0, x0, #1
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: addi64:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: add x0, x0, #1
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: addi64:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: add x0, x0, #1
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %incdec.ptr.i.i.i = add i64 %ptr, 1
+ ret i64 %incdec.ptr.i.i.i
+}
+
+define i32 @addi32(i32 %ptr, i32 %index) {
+; CHECK-CPA-O0-LABEL: addi32:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: add w0, w0, #1
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: addi32:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: add w0, w0, #1
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: addi32:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: add w0, w0, #1
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: addi32:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: add w0, w0, #1
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %incdec.ptr.i.i.i = add i32 %ptr, 1
+ ret i32 %incdec.ptr.i.i.i
+}
+
+define i16 @addi16(i16 %ptr, i32 %index) {
+; CHECK-CPA-O0-LABEL: addi16:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: add w0, w0, #1
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: addi16:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: add w0, w0, #1
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: addi16:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: add w0, w0, #1
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: addi16:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: add w0, w0, #1
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %incdec.ptr.i.i.i = add i16 %ptr, 1
+ ret i16 %incdec.ptr.i.i.i
+}
+
+define i64 @arith1(i64 noundef %0, i64 noundef %1, i64 noundef %2) {
+; CHECK-CPA-O0-LABEL: arith1:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: sub sp, sp, #32
+; CHECK-CPA-O0-NEXT: .cfi_def_cfa_offset 32
+; CHECK-CPA-O0-NEXT: str x0, [sp, #24]
+; CHECK-CPA-O0-NEXT: str x1, [sp, #16]
+; CHECK-CPA-O0-NEXT: str x2, [sp, #8]
+; CHECK-CPA-O0-NEXT: ldr x8, [sp, #24]
+; CHECK-CPA-O0-NEXT: ldr x9, [sp, #16]
+; CHECK-CPA-O0-NEXT: ldr x10, [sp, #8]
+; CHECK-CPA-O0-NEXT: mul x9, x9, x10
+; CHECK-CPA-O0-NEXT: add x0, x8, x9
+; CHECK-CPA-O0-NEXT: add sp, sp, #32
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: arith1:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: sub sp, sp, #32
+; CHECK-CPA-O3-NEXT: .cfi_def_cfa_offset 32
+; CHECK-CPA-O3-NEXT: madd x8, x1, x2, x0
+; CHECK-CPA-O3-NEXT: stp x1, x0, [sp, #16]
+; CHECK-CPA-O3-NEXT: str x2, [sp, #8]
+; CHECK-CPA-O3-NEXT: mov x0, x8
+; CHECK-CPA-O3-NEXT: add sp, sp, #32
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: arith1:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: sub sp, sp, #32
+; CHECK-NOCPA-O0-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NOCPA-O0-NEXT: str x0, [sp, #24]
+; CHECK-NOCPA-O0-NEXT: str x1, [sp, #16]
+; CHECK-NOCPA-O0-NEXT: str x2, [sp, #8]
+; CHECK-NOCPA-O0-NEXT: ldr x8, [sp, #24]
+; CHECK-NOCPA-O0-NEXT: ldr x9, [sp, #16]
+; CHECK-NOCPA-O0-NEXT: ldr x10, [sp, #8]
+; CHECK-NOCPA-O0-NEXT: mul x9, x9, x10
+; CHECK-NOCPA-O0-NEXT: add x0, x8, x9
+; CHECK-NOCPA-O0-NEXT: add sp, sp, #32
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: arith1:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: sub sp, sp, #32
+; CHECK-NOCPA-O3-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NOCPA-O3-NEXT: madd x8, x1, x2, x0
+; CHECK-NOCPA-O3-NEXT: stp x1, x0, [sp, #16]
+; CHECK-NOCPA-O3-NEXT: str x2, [sp, #8]
+; CHECK-NOCPA-O3-NEXT: mov x0, x8
+; CHECK-NOCPA-O3-NEXT: add sp, sp, #32
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %4 = alloca i64, align 8
+ %5 = alloca i64, align 8
+ %6 = alloca i64, align 8
+ store i64 %0, ptr %4, align 8
+ store i64 %1, ptr %5, align 8
+ store i64 %2, ptr %6, align 8
+ %7 = load i64, ptr %4, align 8
+ %8 = load i64, ptr %5, align 8
+ %9 = load i64, ptr %6, align 8
+ %10 = mul nsw i64 %8, %9
+ %11 = add nsw i64 %7, %10
+ ret i64 %11
+}
+
+define i64 @arith2(ptr noundef %0, i64 noundef %1, i64 noundef %2, i32 noundef %3) {
+; CHECK-CPA-O0-LABEL: arith2:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: sub sp, sp, #32
+; CHECK-CPA-O0-NEXT: .cfi_def_cfa_offset 32
+; CHECK-CPA-O0-NEXT: str x0, [sp, #24]
+; CHECK-CPA-O0-NEXT: str x1, [sp, #16]
+; CHECK-CPA-O0-NEXT: str x2, [sp, #8]
+; CHECK-CPA-O0-NEXT: str w3, [sp, #4]
+; CHECK-CPA-O0-NEXT: ldr x8, [sp, #24]
+; CHECK-CPA-O0-NEXT: ldrsw x9, [sp, #4]
+; CHECK-CPA-O0-NEXT: add x9, x9, x9, lsl #1
+; CHECK-CPA-O0-NEXT: addpt x8, x8, x9, lsl #4
+; CHECK-CPA-O0-NEXT: ldr x8, [x8, #24]
+; CHECK-CPA-O0-NEXT: ldr x10, [sp, #16]
+; CHECK-CPA-O0-NEXT: ldr x9, [sp, #8]
+; CHECK-CPA-O0-NEXT: mul x10, x10, x9
+; CHECK-CPA-O0-NEXT: add x8, x8, x10
+; CHECK-CPA-O0-NEXT: subs x0, x8, x9
+; CHECK-CPA-O0-NEXT: add sp, sp, #32
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: arith2:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: sub sp, sp, #32
+; CHECK-CPA-O3-NEXT: .cfi_def_cfa_offset 32
+; CHECK-CPA-O3-NEXT: // kill: def $w3 killed $w3 def $x3
+; CHECK-CPA-O3-NEXT: sxtw x8, w3
+; CHECK-CPA-O3-NEXT: mov w9, #48 // =0x30
+; CHECK-CPA-O3-NEXT: stp x1, x0, [sp, #16]
+; CHECK-CPA-O3-NEXT: str x2, [sp, #8]
+; CHECK-CPA-O3-NEXT: maddpt x8, x8, x9, x0
+; CHECK-CPA-O3-NEXT: str w3, [sp, #4]
+; CHECK-CPA-O3-NEXT: ldr x8, [x8, #24]
+; CHECK-CPA-O3-NEXT: madd x8, x1, x2, x8
+; CHECK-CPA-O3-NEXT: sub x0, x8, x2
+; CHECK-CPA-O3-NEXT: add sp, sp, #32
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: arith2:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: sub sp, sp, #32
+; CHECK-NOCPA-O0-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NOCPA-O0-NEXT: str x0, [sp, #24]
+; CHECK-NOCPA-O0-NEXT: str x1, [sp, #16]
+; CHECK-NOCPA-O0-NEXT: str x2, [sp, #8]
+; CHECK-NOCPA-O0-NEXT: str w3, [sp, #4]
+; CHECK-NOCPA-O0-NEXT: ldr x10, [sp, #24]
+; CHECK-NOCPA-O0-NEXT: ldrsw x8, [sp, #4]
+; CHECK-NOCPA-O0-NEXT: mov w9, #48 // =0x30
+; CHECK-NOCPA-O0-NEXT: mov w0, w9
+; CHECK-NOCPA-O0-NEXT: mov w9, w0
+; CHECK-NOCPA-O0-NEXT: // kill: def $w8 killed $w8 killed $x8
+; CHECK-NOCPA-O0-NEXT: smaddl x8, w8, w9, x10
+; CHECK-NOCPA-O0-NEXT: ldr x8, [x8, #24]
+; CHECK-NOCPA-O0-NEXT: ldr x10, [sp, #16]
+; CHECK-NOCPA-O0-NEXT: ldr x9, [sp, #8]
+; CHECK-NOCPA-O0-NEXT: mul x10, x10, x9
+; CHECK-NOCPA-O0-NEXT: add x8, x8, x10
+; CHECK-NOCPA-O0-NEXT: subs x0, x8, x9
+; CHECK-NOCPA-O0-NEXT: add sp, sp, #32
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: arith2:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: sub sp, sp, #32
+; CHECK-NOCPA-O3-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NOCPA-O3-NEXT: mov w8, #48 // =0x30
+; CHECK-NOCPA-O3-NEXT: stp x1, x0, [sp, #16]
+; CHECK-NOCPA-O3-NEXT: smaddl x8, w3, w8, x0
+; CHECK-NOCPA-O3-NEXT: str x2, [sp, #8]
+; CHECK-NOCPA-O3-NEXT: str w3, [sp, #4]
+; CHECK-NOCPA-O3-NEXT: ldr x8, [x8, #24]
+; CHECK-NOCPA-O3-NEXT: madd x8, x1, x2, x8
+; CHECK-NOCPA-O3-NEXT: sub x0, x8, x2
+; CHECK-NOCPA-O3-NEXT: add sp, sp, #32
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %5 = alloca ptr, align 8
+ %6 = alloca i64, align 8
+ %7 = alloca i64, align 8
+ %8 = alloca i32, align 4
+ store ptr %0, ptr %5, align 8
+ store i64 %1, ptr %6, align 8
+ store i64 %2, ptr %7, align 8
+ store i32 %3, ptr %8, align 4
+ %9 = load ptr, ptr %5, align 8
+ %10 = load i32, ptr %8, align 4
+ %11 = sext i32 %10 to i64
+ %12 = getelementptr inbounds %struct.my_type2, ptr %9, i64 %11
+ %13 = getelementptr inbounds %struct.my_type2, ptr %12, i32 0, i32 3
+ %14 = load i64, ptr %13, align 8
+ %15 = load i64, ptr %6, align 8
+ %16 = load i64, ptr %7, align 8
+ %17 = mul nsw i64 %15, %16
+ %18 = add nsw i64 %14, %17
+ %19 = sub nsw i64 %18, %16
+ ret i64 %19
+}
+
+ at a = hidden global [2 x [1 x [2 x i8]]] [[1 x [2 x i8]] [[2 x i8] c"\01\01"], [1 x [2 x i8]] [[2 x i8] c"\01\01"]], align 1
+ at b = hidden global i16 0, align 2
+ at .str = private unnamed_addr constant [7 x i8] c"hello\0A\00", align 1
+
+define hidden void @multidim() {
+; CHECK-CPA-O0-LABEL: multidim:
+; CHECK-CPA-O0: // %bb.0: // %entry
+; CHECK-CPA-O0-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-CPA-O0-NEXT: .cfi_def_cfa_offset 16
+; CHECK-CPA-O0-NEXT: .cfi_offset w30, -16
+; CHECK-CPA-O0-NEXT: adrp x8, b
+; CHECK-CPA-O0-NEXT: ldrh w9, [x8, :lo12:b]
+; CHECK-CPA-O0-NEXT: mov w8, w9
+; CHECK-CPA-O0-NEXT: mov w10, w8
+; CHECK-CPA-O0-NEXT: adrp x8, a
+; CHECK-CPA-O0-NEXT: add x8, x8, :lo12:a
+; CHECK-CPA-O0-NEXT: mov w11, #2 // =0x2
+; CHECK-CPA-O0-NEXT: // kill: def $x11 killed $w11
+; CHECK-CPA-O0-NEXT: addpt x8, x8, x11
+; CHECK-CPA-O0-NEXT: addpt x8, x8, x10, lsl #1
+; CHECK-CPA-O0-NEXT: add w9, w9, #1
+; CHECK-CPA-O0-NEXT: mov w9, w9
+; CHECK-CPA-O0-NEXT: // kill: def $x9 killed $w9
+; CHECK-CPA-O0-NEXT: addpt x8, x8, x9
+; CHECK-CPA-O0-NEXT: ldrb w8, [x8]
+; CHECK-CPA-O0-NEXT: cbz w8, .LBB14_2
+; CHECK-CPA-O0-NEXT: b .LBB14_1
+; CHECK-CPA-O0-NEXT: .LBB14_1:
+; CHECK-CPA-O0-NEXT: adrp x0, .L.str
+; CHECK-CPA-O0-NEXT: add x0, x0, :lo12:.L.str
+; CHECK-CPA-O0-NEXT: bl printf
+; CHECK-CPA-O0-NEXT: b .LBB14_2
+; CHECK-CPA-O0-NEXT: .LBB14_2:
+; CHECK-CPA-O0-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; CHECK-CPA-O0-NEXT: ret
+;
+; CHECK-CPA-O3-LABEL: multidim:
+; CHECK-CPA-O3: // %bb.0: // %entry
+; CHECK-CPA-O3-NEXT: adrp x8, b
+; CHECK-CPA-O3-NEXT: mov w9, #2 // =0x2
+; CHECK-CPA-O3-NEXT: adrp x10, a
+; CHECK-CPA-O3-NEXT: add x10, x10, :lo12:a
+; CHECK-CPA-O3-NEXT: ldrh w8, [x8, :lo12:b]
+; CHECK-CPA-O3-NEXT: addpt x9, x10, x9
+; CHECK-CPA-O3-NEXT: addpt x9, x9, x8, lsl #1
+; CHECK-CPA-O3-NEXT: add x8, x8, #1
+; CHECK-CPA-O3-NEXT: addpt x8, x9, x8
+; CHECK-CPA-O3-NEXT: ldrb w8, [x8]
+; CHECK-CPA-O3-NEXT: cbz w8, .LBB14_2
+; CHECK-CPA-O3-NEXT: // %bb.1:
+; CHECK-CPA-O3-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-CPA-O3-NEXT: .cfi_def_cfa_offset 16
+; CHECK-CPA-O3-NEXT: .cfi_offset w30, -16
+; CHECK-CPA-O3-NEXT: adrp x0, .L.str
+; CHECK-CPA-O3-NEXT: add x0, x0, :lo12:.L.str
+; CHECK-CPA-O3-NEXT: bl printf
+; CHECK-CPA-O3-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; CHECK-CPA-O3-NEXT: .LBB14_2:
+; CHECK-CPA-O3-NEXT: ret
+;
+; CHECK-NOCPA-O0-LABEL: multidim:
+; CHECK-NOCPA-O0: // %bb.0: // %entry
+; CHECK-NOCPA-O0-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-NOCPA-O0-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NOCPA-O0-NEXT: .cfi_offset w30, -16
+; CHECK-NOCPA-O0-NEXT: adrp x8, b
+; CHECK-NOCPA-O0-NEXT: ldrh w9, [x8, :lo12:b]
+; CHECK-NOCPA-O0-NEXT: adrp x8, a
+; CHECK-NOCPA-O0-NEXT: add x8, x8, :lo12:a
+; CHECK-NOCPA-O0-NEXT: add x8, x8, w9, uxtw #1
+; CHECK-NOCPA-O0-NEXT: add w9, w9, #1
+; CHECK-NOCPA-O0-NEXT: mov w9, w9
+; CHECK-NOCPA-O0-NEXT: // kill: def $x9 killed $w9
+; CHECK-NOCPA-O0-NEXT: add x8, x8, x9
+; CHECK-NOCPA-O0-NEXT: ldrb w8, [x8, #2]
+; CHECK-NOCPA-O0-NEXT: cbz w8, .LBB14_2
+; CHECK-NOCPA-O0-NEXT: b .LBB14_1
+; CHECK-NOCPA-O0-NEXT: .LBB14_1:
+; CHECK-NOCPA-O0-NEXT: adrp x0, .L.str
+; CHECK-NOCPA-O0-NEXT: add x0, x0, :lo12:.L.str
+; CHECK-NOCPA-O0-NEXT: bl printf
+; CHECK-NOCPA-O0-NEXT: b .LBB14_2
+; CHECK-NOCPA-O0-NEXT: .LBB14_2:
+; CHECK-NOCPA-O0-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; CHECK-NOCPA-O0-NEXT: ret
+;
+; CHECK-NOCPA-O3-LABEL: multidim:
+; CHECK-NOCPA-O3: // %bb.0: // %entry
+; CHECK-NOCPA-O3-NEXT: adrp x8, b
+; CHECK-NOCPA-O3-NEXT: adrp x9, a
+; CHECK-NOCPA-O3-NEXT: add x9, x9, :lo12:a
+; CHECK-NOCPA-O3-NEXT: ldrh w8, [x8, :lo12:b]
+; CHECK-NOCPA-O3-NEXT: add x9, x9, x8, lsl #1
+; CHECK-NOCPA-O3-NEXT: add x8, x9, x8
+; CHECK-NOCPA-O3-NEXT: ldrb w8, [x8, #3]
+; CHECK-NOCPA-O3-NEXT: cbz w8, .LBB14_2
+; CHECK-NOCPA-O3-NEXT: // %bb.1:
+; CHECK-NOCPA-O3-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-NOCPA-O3-NEXT: .cfi_def_cfa_offset 16
+; CHECK-NOCPA-O3-NEXT: .cfi_offset w30, -16
+; CHECK-NOCPA-O3-NEXT: adrp x0, .L.str
+; CHECK-NOCPA-O3-NEXT: add x0, x0, :lo12:.L.str
+; CHECK-NOCPA-O3-NEXT: bl printf
+; CHECK-NOCPA-O3-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; CHECK-NOCPA-O3-NEXT: .LBB14_2:
+; CHECK-NOCPA-O3-NEXT: ret
+entry:
+ %1 = load i16, ptr @b, align 2
+ %2 = zext i16 %1 to i64
+ %3 = getelementptr inbounds nuw [1 x [2 x i8]], ptr getelementptr inbounds ([2 x [1 x [2 x i8]]], ptr @a, i64 0, i64 1), i64 0, i64 %2
+ %4 = load i16, ptr @b, align 2
+ %5 = zext i16 %4 to i32
+ %6 = add nsw i32 %5, 1
+ %7 = sext i32 %6 to i64
+ %8 = getelementptr inbounds [2 x i8], ptr %3, i64 0, i64 %7
+ %9 = load i8, ptr %8, align 1
+ %10 = icmp ne i8 %9, 0
+ br i1 %10, label %11, label %13
+
+11:
+ %12 = call i32 (ptr, ...) @printf(ptr noundef @.str)
+ br label %13
+
+13:
+ ret void
+}
+
+declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)
+declare i32 @printf(ptr noundef, ...) #1
+
+!6 = !{i64 0, i64 8, !7, i64 8, i64 8, !7, i64 16, i64 8, !7, i64 24, i64 8, !7, i64 32, i64 8, !7, i64 40, i64 8, !7}
+!7 = !{!8, !8, i64 0}
+!8 = !{!"long", !9, i64 0}
+!9 = !{!"omnipotent char", !10, i64 0}
+!10 = !{!"Simple C++ TBAA"}
+!11 = !{i64 0, i64 8, !7, i64 8, i64 8, !7}
More information about the llvm-commits
mailing list