| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| ; RUN: llc < %s -mtriple=aarch64 -mattr=+mte | FileCheck %s | ||
|
|
||
| define i8* @irg_imm16(i8* %p) { | ||
| entry: | ||
| ; CHECK-LABEL: irg_imm16: | ||
| ; CHECK: mov w[[R:[0-9]+]], #16 | ||
| ; CHECK: irg x0, x0, x[[R]] | ||
| ; CHECK: ret | ||
| %q = call i8* @llvm.aarch64.irg(i8* %p, i64 16) | ||
| ret i8* %q | ||
| } | ||
|
|
||
| define i8* @irg_imm0(i8* %p) { | ||
| entry: | ||
| ; CHECK-LABEL: irg_imm0: | ||
| ; CHECK: irg x0, x0{{$}} | ||
| ; CHECK: ret | ||
| %q = call i8* @llvm.aarch64.irg(i8* %p, i64 0) | ||
| ret i8* %q | ||
| } | ||
|
|
||
| define i8* @irg_reg(i8* %p, i64 %ex) { | ||
| entry: | ||
| ; CHECK-LABEL: irg_reg: | ||
| ; CHECK: irg x0, x0, x1 | ||
| ; CHECK: ret | ||
| %q = call i8* @llvm.aarch64.irg(i8* %p, i64 %ex) | ||
| ret i8* %q | ||
| } | ||
|
|
||
| ; undef argument in irg is treated specially | ||
| define i8* @irg_sp() { | ||
| entry: | ||
| ; CHECK-LABEL: irg_sp: | ||
| ; CHECK: irg x0, sp{{$}} | ||
| ; CHECK: ret | ||
| %q = call i8* @llvm.aarch64.irg.sp(i64 0) | ||
| ret i8* %q | ||
| } | ||
|
|
||
| declare i8* @llvm.aarch64.irg(i8* %p, i64 %exclude) | ||
| declare i8* @llvm.aarch64.irg.sp(i64 %exclude) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| ; RUN: llc < %s -mtriple=aarch64 -mattr=+mte | FileCheck %s | ||
|
|
||
| define i8* @small_alloca() { | ||
| entry: | ||
| ; CHECK-LABEL: small_alloca: | ||
| ; CHECK: irg [[R:x[0-9]+]], sp{{$}} | ||
| ; CHECK-NEXT: addg x0, [[R]], #0, #1 | ||
| ; CHECK: ret | ||
| %a = alloca i8, align 16 | ||
| %q = call i8* @llvm.aarch64.irg.sp(i64 0) | ||
| %q1 = call i8* @llvm.aarch64.tagp.p0i8(i8* %a, i8* %q, i64 1) | ||
| ret i8* %q1 | ||
| } | ||
|
|
||
| ; Two large allocas. One's offset overflows addg immediate. | ||
| define void @huge_allocas() { | ||
| entry: | ||
| ; CHECK-LABEL: huge_allocas: | ||
| ; CHECK: irg [[R:x[0-9]+]], sp{{$}} | ||
| ; CHECK: add [[TMP:x[0-9]+]], [[R]], #3088 | ||
| ; CHECK: addg x0, [[TMP]], #1008, #1 | ||
| ; CHECK: addg x1, [[R]], #0, #2 | ||
| ; CHECK: bl use2 | ||
| %a = alloca i8, i64 4096, align 16 | ||
| %b = alloca i8, i64 4096, align 16 | ||
| %base = call i8* @llvm.aarch64.irg.sp(i64 0) | ||
| %a_t = call i8* @llvm.aarch64.tagp.p0i8(i8* %a, i8* %base, i64 1) | ||
| %b_t = call i8* @llvm.aarch64.tagp.p0i8(i8* %b, i8* %base, i64 2) | ||
| call void @use2(i8* %a_t, i8* %b_t) | ||
| ret void | ||
| } | ||
|
|
||
| ; Realigned stack frame. IRG uses value of SP after realignment, | ||
| ; ADDG for the first stack allocation has offset 0. | ||
| define void @realign() { | ||
| entry: | ||
| ; CHECK-LABEL: realign: | ||
| ; CHECK: add x29, sp, #16 | ||
| ; CHECK: and sp, x{{[0-9]*}}, #0xffffffffffffffc0 | ||
| ; CHECK: irg [[R:x[0-9]+]], sp{{$}} | ||
| ; CHECK: addg x0, [[R]], #0, #1 | ||
| ; CHECK: bl use | ||
| %a = alloca i8, i64 4096, align 64 | ||
| %base = call i8* @llvm.aarch64.irg.sp(i64 0) | ||
| %a_t = call i8* @llvm.aarch64.tagp.p0i8(i8* %a, i8* %base, i64 1) | ||
| call void @use(i8* %a_t) | ||
| ret void | ||
| } | ||
|
|
||
| ; With a dynamic alloca, IRG has to use FP with non-zero offset. | ||
| ; ADDG offset for the single static alloca is still zero. | ||
| define void @dynamic_alloca(i64 %size) { | ||
| entry: | ||
| ; CHECK-LABEL: dynamic_alloca: | ||
| ; CHECK: sub [[R:x[0-9]+]], x29, #[[OFS:[0-9]+]] | ||
| ; CHECK: irg [[R]], [[R]] | ||
| ; CHECK: addg x1, [[R]], #0, #1 | ||
| ; CHECK: sub x0, x29, #[[OFS]] | ||
| ; CHECK: bl use2 | ||
| %base = call i8* @llvm.aarch64.irg.sp(i64 0) | ||
| %a = alloca i128, i64 %size, align 16 | ||
| %b = alloca i8, i64 16, align 16 | ||
| %b_t = call i8* @llvm.aarch64.tagp.p0i8(i8* %b, i8* %base, i64 1) | ||
| call void @use2(i8* %b, i8* %b_t) | ||
| ret void | ||
| } | ||
|
|
||
| ; Both dynamic alloca and realigned frame. | ||
| ; After initial realignment, generate the base pointer. | ||
| ; IRG uses the base pointer w/o offset. | ||
| ; Offsets for tagged and untagged pointers to the same alloca match. | ||
| define void @dynamic_alloca_and_realign(i64 %size) { | ||
| entryz: | ||
| ; CHECK-LABEL: dynamic_alloca_and_realign: | ||
| ; CHECK: and sp, x{{.*}}, #0xffffffffffffffc0 | ||
| ; CHECK: mov x19, sp | ||
| ; CHECK: irg [[R:x[0-9]+]], x19 | ||
| ; CHECK: addg x1, [[R]], #[[OFS:[0-9]+]], #1 | ||
| ; CHECK: add x0, x19, #[[OFS]] | ||
| ; CHECK: bl use2 | ||
| %base = call i8* @llvm.aarch64.irg.sp(i64 0) | ||
| %a = alloca i128, i64 %size, align 64 | ||
| %b = alloca i8, i64 16, align 16 | ||
| %b_t = call i8* @llvm.aarch64.tagp.p0i8(i8* %b, i8* %base, i64 1) | ||
| call void @use2(i8* %b, i8* %b_t) | ||
| ret void | ||
| } | ||
|
|
||
| declare void @use(i8*) | ||
| declare void @use2(i8*, i8*) | ||
|
|
||
| declare i8* @llvm.aarch64.irg.sp(i64 %exclude) | ||
| declare i8* @llvm.aarch64.tagp.p0i8(i8* %p, i8* %tag, i64 %ofs) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,138 @@ | ||
| ; RUN: llc < %s -mtriple=aarch64 -mattr=+mte | FileCheck %s | ||
|
|
||
| define void @stg1(i8* %p) { | ||
| entry: | ||
| ; CHECK-LABEL: stg1: | ||
| ; CHECK: stg x0, [x0] | ||
| ; CHECK: ret | ||
| call void @llvm.aarch64.settag(i8* %p, i64 16) | ||
| ret void | ||
| } | ||
|
|
||
| define void @stg2(i8* %p) { | ||
| entry: | ||
| ; CHECK-LABEL: stg2: | ||
| ; CHECK: st2g x0, [x0] | ||
| ; CHECK: ret | ||
| call void @llvm.aarch64.settag(i8* %p, i64 32) | ||
| ret void | ||
| } | ||
|
|
||
| define void @stg3(i8* %p) { | ||
| entry: | ||
| ; CHECK-LABEL: stg3: | ||
| ; CHECK: stg x0, [x0, #32] | ||
| ; CHECK: st2g x0, [x0] | ||
| ; CHECK: ret | ||
| call void @llvm.aarch64.settag(i8* %p, i64 48) | ||
| ret void | ||
| } | ||
|
|
||
| define void @stg4(i8* %p) { | ||
| entry: | ||
| ; CHECK-LABEL: stg4: | ||
| ; CHECK: st2g x0, [x0, #32] | ||
| ; CHECK: st2g x0, [x0] | ||
| ; CHECK: ret | ||
| call void @llvm.aarch64.settag(i8* %p, i64 64) | ||
| ret void | ||
| } | ||
|
|
||
| define void @stg5(i8* %p) { | ||
| entry: | ||
| ; CHECK-LABEL: stg5: | ||
| ; CHECK: stg x0, [x0, #64] | ||
| ; CHECK: st2g x0, [x0, #32] | ||
| ; CHECK: st2g x0, [x0] | ||
| ; CHECK: ret | ||
| call void @llvm.aarch64.settag(i8* %p, i64 80) | ||
| ret void | ||
| } | ||
|
|
||
| define void @stg16(i8* %p) { | ||
| entry: | ||
| ; CHECK-LABEL: stg16: | ||
| ; CHECK: mov {{(w|x)}}[[R:[0-9]+]], #256 | ||
| ; CHECK: st2g x0, [x0], #32 | ||
| ; CHECK: sub x[[R]], x[[R]], #32 | ||
| ; CHECK: cbnz x[[R]], | ||
| ; CHECK: ret | ||
| call void @llvm.aarch64.settag(i8* %p, i64 256) | ||
| ret void | ||
| } | ||
|
|
||
| define void @stg17(i8* %p) { | ||
| entry: | ||
| ; CHECK-LABEL: stg17: | ||
| ; CHECK: mov {{(w|x)}}[[R:[0-9]+]], #256 | ||
| ; CHECK: stg x0, [x0], #16 | ||
| ; CHECK: st2g x0, [x0], #32 | ||
| ; CHECK: sub x[[R]], x[[R]], #32 | ||
| ; CHECK: cbnz x[[R]], | ||
| ; CHECK: ret | ||
| call void @llvm.aarch64.settag(i8* %p, i64 272) | ||
| ret void | ||
| } | ||
|
|
||
| define void @stzg3(i8* %p) { | ||
| entry: | ||
| ; CHECK-LABEL: stzg3: | ||
| ; CHECK: stzg x0, [x0, #32] | ||
| ; CHECK: stz2g x0, [x0] | ||
| ; CHECK: ret | ||
| call void @llvm.aarch64.settag.zero(i8* %p, i64 48) | ||
| ret void | ||
| } | ||
|
|
||
| define void @stzg17(i8* %p) { | ||
| entry: | ||
| ; CHECK-LABEL: stzg17: | ||
| ; CHECK: mov {{w|x}}[[R:[0-9]+]], #256 | ||
| ; CHECK: stzg x0, [x0], #16 | ||
| ; CHECK: stz2g x0, [x0], #32 | ||
| ; CHECK: sub x[[R]], x[[R]], #32 | ||
| ; CHECK: cbnz x[[R]], | ||
| ; CHECK: ret | ||
| call void @llvm.aarch64.settag.zero(i8* %p, i64 272) | ||
| ret void | ||
| } | ||
|
|
||
| define void @stg_alloca1() { | ||
| entry: | ||
| ; CHECK-LABEL: stg_alloca1: | ||
| ; CHECK: stg sp, [sp] | ||
| ; CHECK: ret | ||
| %a = alloca i8, i32 16, align 16 | ||
| call void @llvm.aarch64.settag(i8* %a, i64 16) | ||
| ret void | ||
| } | ||
|
|
||
| define void @stg_alloca5() { | ||
| entry: | ||
| ; CHECK-LABEL: stg_alloca5: | ||
| ; CHECK: stg sp, [sp, #64] | ||
| ; CHECK: st2g sp, [sp, #32] | ||
| ; CHECK: st2g sp, [sp] | ||
| ; CHECK: ret | ||
| %a = alloca i8, i32 80, align 16 | ||
| call void @llvm.aarch64.settag(i8* %a, i64 80) | ||
| ret void | ||
| } | ||
|
|
||
| define void @stg_alloca17() { | ||
| entry: | ||
| ; CHECK-LABEL: stg_alloca17: | ||
| ; CHECK: mov [[P:x[0-9]+]], sp | ||
| ; CHECK: stg [[P]], {{\[}}[[P]]{{\]}}, #16 | ||
| ; CHECK: mov {{w|x}}[[R:[0-9]+]], #256 | ||
| ; CHECK: st2g [[P]], {{\[}}[[P]]{{\]}}, #32 | ||
| ; CHECK: sub x[[R]], x[[R]], #32 | ||
| ; CHECK: cbnz x[[R]], | ||
| ; CHECK: ret | ||
| %a = alloca i8, i32 272, align 16 | ||
| call void @llvm.aarch64.settag(i8* %a, i64 272) | ||
| ret void | ||
| } | ||
|
|
||
| declare void @llvm.aarch64.settag(i8* %p, i64 %a) | ||
| declare void @llvm.aarch64.settag.zero(i8* %p, i64 %a) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| ; RUN: llc < %s -mtriple=aarch64 -mattr=+mte | FileCheck %s | ||
|
|
||
| define void @stgp0(i64 %a, i64 %b, i8* %p) { | ||
| entry: | ||
| ; CHECK-LABEL: stgp0: | ||
| ; CHECK: stgp x0, x1, [x2] | ||
| ; CHECK: ret | ||
| call void @llvm.aarch64.stgp(i8* %p, i64 %a, i64 %b) | ||
| ret void | ||
| } | ||
|
|
||
| define void @stgp1004(i64 %a, i64 %b, i8* %p) { | ||
| entry: | ||
| ; CHECK-LABEL: stgp1004: | ||
| ; CHECK: add [[R:x[0-9]+]], x2, #1004 | ||
| ; CHECK: stgp x0, x1, {{\[}}[[R]]{{\]}} | ||
| ; CHECK: ret | ||
| %q = getelementptr i8, i8* %p, i32 1004 | ||
| call void @llvm.aarch64.stgp(i8* %q, i64 %a, i64 %b) | ||
| ret void | ||
| } | ||
|
|
||
| define void @stgp1008(i64 %a, i64 %b, i8* %p) { | ||
| entry: | ||
| ; CHECK-LABEL: stgp1008: | ||
| ; CHECK: stgp x0, x1, [x2, #1008] | ||
| ; CHECK: ret | ||
| %q = getelementptr i8, i8* %p, i32 1008 | ||
| call void @llvm.aarch64.stgp(i8* %q, i64 %a, i64 %b) | ||
| ret void | ||
| } | ||
|
|
||
| define void @stgp1024(i64 %a, i64 %b, i8* %p) { | ||
| entry: | ||
| ; CHECK-LABEL: stgp1024: | ||
| ; CHECK: add [[R:x[0-9]+]], x2, #1024 | ||
| ; CHECK: stgp x0, x1, {{\[}}[[R]]{{\]}} | ||
| ; CHECK: ret | ||
| %q = getelementptr i8, i8* %p, i32 1024 | ||
| call void @llvm.aarch64.stgp(i8* %q, i64 %a, i64 %b) | ||
| ret void | ||
| } | ||
|
|
||
| define void @stgp_1024(i64 %a, i64 %b, i8* %p) { | ||
| entry: | ||
| ; CHECK-LABEL: stgp_1024: | ||
| ; CHECK: stgp x0, x1, [x2, #-1024] | ||
| ; CHECK: ret | ||
| %q = getelementptr i8, i8* %p, i32 -1024 | ||
| call void @llvm.aarch64.stgp(i8* %q, i64 %a, i64 %b) | ||
| ret void | ||
| } | ||
|
|
||
| define void @stgp_1040(i64 %a, i64 %b, i8* %p) { | ||
| entry: | ||
| ; CHECK-LABEL: stgp_1040: | ||
| ; CHECK: sub [[R:x[0-9]+]], x2, #1040 | ||
| ; CHECK: stgp x0, x1, [x{{.*}}] | ||
| ; CHECK: ret | ||
| %q = getelementptr i8, i8* %p, i32 -1040 | ||
| call void @llvm.aarch64.stgp(i8* %q, i64 %a, i64 %b) | ||
| ret void | ||
| } | ||
|
|
||
| define void @stgp_alloca(i64 %a, i64 %b) { | ||
| entry: | ||
| ; CHECK-LABEL: stgp_alloca: | ||
| ; CHECK: stgp x0, x1, [sp] | ||
| ; CHECK: stgp x1, x0, [sp, #16] | ||
| ; CHECK: ret | ||
| %x = alloca i8, i32 32, align 16 | ||
| call void @llvm.aarch64.stgp(i8* %x, i64 %a, i64 %b) | ||
| %x1 = getelementptr i8, i8* %x, i32 16 | ||
| call void @llvm.aarch64.stgp(i8* %x1, i64 %b, i64 %a) | ||
| ret void | ||
| } | ||
|
|
||
| declare void @llvm.aarch64.stgp(i8* %p, i64 %a, i64 %b) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| ; RUN: llc < %s -mtriple=aarch64 -mattr=+mte | FileCheck %s | ||
|
|
||
| define i8* @tagp2(i8* %p, i8* %tag) { | ||
| entry: | ||
| ; CHECK-LABEL: tagp2: | ||
| ; CHECK: subp [[R:x[0-9]+]], x0, x1 | ||
| ; CHECK: add [[R]], [[R]], x1 | ||
| ; CHECK: addg x0, [[R]], #0, #2 | ||
| ; CHECK: ret | ||
| %q = call i8* @llvm.aarch64.tagp.p0i8(i8* %p, i8* %tag, i64 2) | ||
| ret i8* %q | ||
| } | ||
|
|
||
| define i8* @irg_tagp_unrelated(i8* %p, i8* %q) { | ||
| entry: | ||
| ; CHECK-LABEL: irg_tagp_unrelated: | ||
| ; CHECK: irg [[R0:x[0-9]+]], x0{{$}} | ||
| ; CHECK: subp [[R:x[0-9]+]], [[R0]], x1 | ||
| ; CHECK: add [[R]], [[R0]], x1 | ||
| ; CHECK: addg x0, [[R]], #0, #1 | ||
| ; CHECK: ret | ||
| %p1 = call i8* @llvm.aarch64.irg(i8* %p, i64 0) | ||
| %q1 = call i8* @llvm.aarch64.tagp.p0i8(i8* %p1, i8* %q, i64 1) | ||
| ret i8* %q1 | ||
| } | ||
|
|
||
| define i8* @tagp_alloca(i8* %tag) { | ||
| entry: | ||
| ; CHECK-LABEL: tagp_alloca: | ||
| ; CHECK: mov [[R0:x[0-9]+]], sp{{$}} | ||
| ; CHECK: subp [[R:x[0-9]+]], [[R0]], x0{{$}} | ||
| ; CHECK: add [[R]], [[R0]], x0{{$}} | ||
| ; CHECK: addg x0, [[R]], #0, #3 | ||
| ; CHECK: ret | ||
| %a = alloca i8, align 16 | ||
| %q = call i8* @llvm.aarch64.tagp.p0i8(i8* %a, i8* %tag, i64 3) | ||
| ret i8* %q | ||
| } | ||
|
|
||
| declare i8* @llvm.aarch64.irg(i8* %p, i64 %exclude) | ||
| declare i8* @llvm.aarch64.tagp.p0i8(i8* %p, i8* %tag, i64 %ofs) |