diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 1169efce3123f..f9f52d628d8f3 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -153,6 +153,14 @@ cl::opt 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 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; @@ -30416,3 +30424,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 different 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 { +def lsl_imm3_shift_operand : Operand { let PrintMethod = "printShifter"; let ParserMatchClass = LSLImm3ShiftOperand; } diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index f90f12b5ac3c7..47f88ee5f05b0 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -10716,6 +10716,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 } + +@array = external dso_local global [10 x %struct.my_type], align 8 +@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 +} + +@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 +@b = hidden global i16 0, align 2 +@.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 } + +@array = external dso_local global [10 x %struct.my_type], align 8 +@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 +} + +@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 +@b = hidden global i16 0, align 2 +@.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}