brintos

brintos / llvm-project-archived public Read only

0
0
Text · 22.9 KiB · cddadca Raw
779 lines · plain
1; RUN: llc -mtriple=arm64_32-apple-ios7.0 %s -filetype=obj -o - -disable-post-ra -frame-pointer=non-leaf | \2; RUN:     llvm-objdump --private-headers - | \3; RUN:     FileCheck %s --check-prefix=CHECK-MACHO4; RUN: llc -mtriple=arm64_32-apple-ios7.0 %s -o - -aarch64-enable-atomic-cfg-tidy=0 -disable-post-ra -frame-pointer=non-leaf | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-OPT5; RUN: llc -mtriple=arm64_32-apple-ios7.0 %s -o - -fast-isel -aarch64-enable-atomic-cfg-tidy=0 -disable-post-ra -frame-pointer=non-leaf | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-FAST6 7; CHECK-MACHO: Mach header8; CHECK-MACHO: MH_MAGIC ARM64_32 V89 10@var64 = global i64 zeroinitializer, align 811@var32 = global i32 zeroinitializer, align 412 13@var_got = external global i814 15define ptr @test_global_addr() {16; CHECK-LABEL: test_global_addr:17; CHECK: adrp [[PAGE:x[0-9]+]], _var32@PAGE18; CHECK-OPT: add x0, [[PAGE]], _var32@PAGEOFF19; CHECK-FAST: add [[TMP:x[0-9]+]], [[PAGE]], _var32@PAGEOFF20; CHECK-FAST: and x0, [[TMP]], #0xffffffff21  ret ptr @var3222}23 24; ADRP is necessarily 64-bit. The important point to check is that, however that25; gets truncated to 32-bits, it's free. No need to zero out higher bits of that26; register.27define i64 @test_global_addr_extension() {28; CHECK-LABEL: test_global_addr_extension:29; CHECK: adrp [[PAGE:x[0-9]+]], _var32@PAGE30; CHECK: add x0, [[PAGE]], _var32@PAGEOFF31; CHECK-NOT: and32; CHECK: ret33 34  ret i64 ptrtoint(ptr @var32 to i64)35}36 37define i32 @test_global_value() {38; CHECK-LABEL: test_global_value:39; CHECK: adrp x[[PAGE:[0-9]+]], _var32@PAGE40; CHECK: ldr w0, [x[[PAGE]], _var32@PAGEOFF]41  %val = load i32, ptr @var32, align 442  ret i32 %val43}44 45; Because the addition may wrap, it is not safe to use "ldr w0, [xN, #32]" here.46define i32 @test_unsafe_indexed_add() {47; CHECK-LABEL: test_unsafe_indexed_add:48; CHECK: add x[[VAR32:[0-9]+]], {{x[0-9]+}}, _var32@PAGEOFF49; CHECK: add w[[ADDR:[0-9]+]], w[[VAR32]], #3250; CHECK: ldr w0, [x[[ADDR]]]51  %addr_int = ptrtoint ptr @var32 to i3252  %addr_plus_32 = add i32 %addr_int, 3253  %addr = inttoptr i32 %addr_plus_32 to ptr54  %val = load i32, ptr %addr, align 455  ret i32 %val56}57 58; Since we've promised there is no unsigned overflow, @var32 must be at least59; 32-bytes below 2^32, and we can use the load this time.60define i32 @test_safe_indexed_add() {61; CHECK-LABEL: test_safe_indexed_add:62; CHECK: add x[[VAR32:[0-9]+]], {{x[0-9]+}}, _var32@PAGEOFF63; CHECK: add w[[ADDR:[0-9]+]], w[[VAR32]], #3264; CHECK: ldr w0, [x[[ADDR]]]65  %addr_int = ptrtoint ptr @var32 to i6466  %addr_plus_32 = add nuw i64 %addr_int, 3267  %addr = inttoptr i64 %addr_plus_32 to ptr68  %val = load i32, ptr %addr, align 469  ret i32 %val70}71 72define i32 @test_safe_indexed_or(i32 %in) {73; CHECK-LABEL: test_safe_indexed_or:74; CHECK: and [[TMP:w[0-9]+]], {{w[0-9]+}}, #0xfffffff075; CHECK: orr w[[ADDR:[0-9]+]], [[TMP]], #0x476; CHECK: ldr w0, [x[[ADDR]]]77  %addr_int = and i32 %in, -1678  %addr_plus_4 = or i32 %addr_int, 479  %addr = inttoptr i32 %addr_plus_4 to ptr80  %val = load i32, ptr %addr, align 481  ret i32 %val82}83 84 85; Promising nsw is not sufficient because the addressing mode basically86; calculates "zext(base) + zext(offset)" and nsw only guarantees87; "sext(base) + sext(offset) == base + offset".88define i32 @test_unsafe_nsw_indexed_add() {89; CHECK-LABEL: test_unsafe_nsw_indexed_add:90; CHECK: add x[[VAR32:[0-9]+]], {{x[0-9]+}}, _var32@PAGEOFF91; CHECK: add w[[ADDR:[0-9]+]], w[[VAR32]], #3292; CHECK-NOT: ubfx93; CHECK: ldr w0, [x[[ADDR]]]94  %addr_int = ptrtoint ptr @var32 to i3295  %addr_plus_32 = add nsw i32 %addr_int, 3296  %addr = inttoptr i32 %addr_plus_32 to ptr97  %val = load i32, ptr %addr, align 498  ret i32 %val99}100 101; Because the addition may wrap, it is not safe to use "ldr w0, [xN, #32]" here.102define i32 @test_unsafe_unscaled_add() {103; CHECK-LABEL: test_unsafe_unscaled_add:104; CHECK: add x[[VAR32:[0-9]+]], {{x[0-9]+}}, _var32@PAGEOFF105; CHECK: add w[[ADDR:[0-9]+]], w[[VAR32]], #3106; CHECK: ldr w0, [x[[ADDR]]]107  %addr_int = ptrtoint ptr @var32 to i32108  %addr_plus_3 = add i32 %addr_int, 3109  %addr = inttoptr i32 %addr_plus_3 to ptr110  %val = load i32, ptr %addr, align 1111  ret i32 %val112}113 114; Since we've promised there is no unsigned overflow, @var32 must be at least115; 32-bytes below 2^32, and we can use the load this time.116define i32 @test_safe_unscaled_add() {117; CHECK-LABEL: test_safe_unscaled_add:118; CHECK: add x[[VAR32:[0-9]+]], {{x[0-9]+}}, _var32@PAGEOFF119; CHECK: add w[[ADDR:[0-9]+]], w[[VAR32]], #3120; CHECK: ldr w0, [x[[ADDR]]]121  %addr_int = ptrtoint ptr @var32 to i32122  %addr_plus_3 = add nuw i32 %addr_int, 3123  %addr = inttoptr i32 %addr_plus_3 to ptr124  %val = load i32, ptr %addr, align 1125  ret i32 %val126}127 128; Promising nsw is not sufficient because the addressing mode basically129; calculates "zext(base) + zext(offset)" and nsw only guarantees130; "sext(base) + sext(offset) == base + offset".131define i32 @test_unsafe_nsw_unscaled_add() {132; CHECK-LABEL: test_unsafe_nsw_unscaled_add:133; CHECK: add x[[VAR32:[0-9]+]], {{x[0-9]+}}, _var32@PAGEOFF134; CHECK: add w[[ADDR:[0-9]+]], w[[VAR32]], #3135; CHECK-NOT: ubfx136; CHECK: ldr w0, [x[[ADDR]]]137  %addr_int = ptrtoint ptr @var32 to i32138  %addr_plus_3 = add nsw i32 %addr_int, 3139  %addr = inttoptr i32 %addr_plus_3 to ptr140  %val = load i32, ptr %addr, align 1141  ret i32 %val142}143 144; Because the addition may wrap, it is not safe to use "ldur w0, [xN, #-3]"145; here.146define i32 @test_unsafe_negative_unscaled_add() {147; CHECK-LABEL: test_unsafe_negative_unscaled_add:148; CHECK: add x[[VAR32:[0-9]+]], {{x[0-9]+}}, _var32@PAGEOFF149; CHECK: sub w[[ADDR:[0-9]+]], w[[VAR32]], #3150; CHECK: ldr w0, [x[[ADDR]]]151  %addr_int = ptrtoint ptr @var32 to i32152  %addr_minus_3 = add i32 %addr_int, -3153  %addr = inttoptr i32 %addr_minus_3 to ptr154  %val = load i32, ptr %addr, align 1155  ret i32 %val156}157 158define ptr @test_got_addr() {159; CHECK-LABEL: test_got_addr:160; CHECK: adrp x[[PAGE:[0-9]+]], _var_got@GOTPAGE161; CHECK-OPT: ldr w0, [x[[PAGE]], _var_got@GOTPAGEOFF]162; CHECK-FAST: ldr w[[TMP:[0-9]+]], [x[[PAGE]], _var_got@GOTPAGEOFF]163; CHECK-FAST: and x0, x[[TMP]], #0xffffffff164  ret ptr @var_got165}166 167define float @test_va_arg_f32(ptr %list) {168; CHECK-LABEL: test_va_arg_f32:169 170; CHECK: ldr w[[START:[0-9]+]], [x0]171; CHECK: add [[AFTER:w[0-9]+]], w[[START]], #8172; CHECK: str [[AFTER]], [x0]173 174  ; Floating point arguments get promoted to double as per C99.175; CHECK: ldr [[DBL:d[0-9]+]], [x[[START]]]176; CHECK: fcvt s0, [[DBL]]177  %res = va_arg ptr %list, float178  ret float %res179}180 181; Interesting point is that the slot is 4 bytes.182define i8 @test_va_arg_i8(ptr %list) {183; CHECK-LABEL: test_va_arg_i8:184 185; CHECK: ldr w[[START:[0-9]+]], [x0]186; CHECK: add [[AFTER:w[0-9]+]], w[[START]], #4187; CHECK: str [[AFTER]], [x0]188 189  ; i8 gets promoted to int (again, as per C99).190; CHECK: ldr w0, [x[[START]]]191 192  %res = va_arg ptr %list, i8193  ret i8 %res194}195 196; Interesting point is that the slot needs aligning (again, min size is 4197; bytes).198define i64 @test_va_arg_i64(ptr %list) {199; CHECK-LABEL: test_va_arg_i64:200 201  ; Update the list for the next user (minimum slot size is 4, but the actual202  ; argument is 8 which had better be reflected!)203; CHECK: ldr w[[UNALIGNED_START:[0-9]+]], [x0]204; CHECK: add [[ALIGN_TMP:x[0-9]+]], x[[UNALIGNED_START]], #7205; CHECK: and x[[START:[0-9]+]], [[ALIGN_TMP]], #0x1fffffff8206; CHECK: add w[[AFTER:[0-9]+]], w[[START]], #8207; CHECK: str w[[AFTER]], [x0]208 209; CHECK: ldr x0, [x[[START]]]210 211  %res = va_arg ptr %list, i64212  ret i64 %res213}214 215declare void @bar(...)216define void @test_va_call(i8 %l, i8 %r, float %in, ptr %ptr) {217; CHECK-LABEL: test_va_call:218; CHECK: add [[SUM:w[0-9]+]], {{w[0-9]+}}, w1219 220; CHECK-DAG: str w2, [sp, #32]221; CHECK-DAG: str xzr, [sp, #24]222; CHECK-DAG: str s0, [sp, #16]223; CHECK-DAG: str xzr, [sp, #8]224; CHECK-DAG: str [[SUM]], [sp]225 226  ; Add them to ensure real promotion occurs.227  %sum = add i8 %l, %r228  call void(...) @bar(i8 %sum, i64 0, float %in, double 0.0, ptr %ptr)229  ret void230}231 232declare ptr @llvm.frameaddress(i32)233 234define ptr @test_frameaddr() {235; CHECK-LABEL: test_frameaddr:236; CHECK-OPT: ldr x0, [x29]237; CHECK-FAST: ldr [[TMP:x[0-9]+]], [x29]238; CHECK-FAST: and x0, [[TMP]], #0xffffffff239  %val = call ptr @llvm.frameaddress(i32 1)240  ret ptr %val241}242 243declare ptr @llvm.returnaddress(i32)244 245define ptr @test_toplevel_returnaddr() {246; CHECK-LABEL: test_toplevel_returnaddr:247; CHECK-OPT: mov x0, x30248; CHECK-FAST: and x0, x30, #0xffffffff249  %val = call ptr @llvm.returnaddress(i32 0)250  ret ptr %val251}252 253define ptr @test_deep_returnaddr() {254; CHECK-LABEL: test_deep_returnaddr:255; CHECK: ldr x[[FRAME_REC:[0-9]+]], [x29]256; CHECK-OPT: ldr x30, [x[[FRAME_REC]], #8]257; CHECK-OPT: hint #7258; CHECK-OPT: mov x0, x30259; CHECK-FAST: ldr [[TMP:x[0-9]+]], [x[[FRAME_REC]], #8]260; CHECK-FAST: and x0, [[TMP]], #0xffffffff261  %val = call ptr @llvm.returnaddress(i32 1)262  ret ptr %val263}264 265define void @test_indirect_call(ptr %func) {266; CHECK-LABEL: test_indirect_call:267; CHECK: blr x0268  call void() %func()269  ret void270}271 272; Safe to use the unextended address here273define void @test_indirect_safe_call(ptr %weird_funcs) {274; CHECK-LABEL: test_indirect_safe_call:275; CHECK: add w[[ADDR32:[0-9]+]], w0, #4276; CHECK-OPT-NOT: ubfx277; CHECK: blr x[[ADDR32]]278  %addr = getelementptr i32, ptr %weird_funcs, i32 1279  call void() %addr()280  ret void281}282 283declare void @simple()284define void @test_simple_tail_call() {285; CHECK-LABEL: test_simple_tail_call:286; CHECK: b _simple287  tail call void @simple()288  ret void289}290 291define void @test_indirect_tail_call(ptr %func) {292; CHECK-LABEL: test_indirect_tail_call:293; CHECK: br x0294  tail call void() %func()295  ret void296}297 298; Safe to use the unextended address here299define void @test_indirect_safe_tail_call(ptr %weird_funcs) {300; CHECK-LABEL: test_indirect_safe_tail_call:301; CHECK: add w[[ADDR32:[0-9]+]], w0, #4302; CHECK-OPT-NOT: ubfx303; CHECK-OPT: br x[[ADDR32]]304  %addr = getelementptr i32, ptr %weird_funcs, i32 1305  tail call void() %addr()306  ret void307}308 309; For the "armv7k" slice, Clang will be emitting some small structs as [N x310; i32]. For ABI compatibility with arm64_32 these need to be passed in *X*311; registers (e.g. [2 x i32] would be packed into a single register).312 313define i32 @test_in_smallstruct_low([3 x i32] %in) {314; CHECK-LABEL: test_in_smallstruct_low:315; CHECK: mov x0, x1316  %val = extractvalue [3 x i32] %in, 2317  ret i32 %val318}319 320define i32 @test_in_smallstruct_high([3 x i32] %in) {321; CHECK-LABEL: test_in_smallstruct_high:322; CHECK: lsr x0, x0, #32323  %val = extractvalue [3 x i32] %in, 1324  ret i32 %val325}326 327; The 64-bit DarwinPCS ABI has the quirk that structs on the stack are always328; 64-bit aligned. This must not happen for arm64_32 since othwerwise va_arg will329; be incompatible with the armv7k ABI.330define i32 @test_in_smallstruct_stack([8 x i64], i32, [3 x i32] %in) {331; CHECK-LABEL: test_in_smallstruct_stack:332; CHECK: ldr w0, [sp, #4]333  %val = extractvalue [3 x i32] %in, 0334  ret i32 %val335}336 337define [2 x i32] @test_ret_smallstruct([3 x i32] %in) {338; CHECK-LABEL: test_ret_smallstruct:339; CHECK: mov x0, #1340; CHECK: movk x0, #2, lsl #32341 342  ret [2 x i32] [i32 1, i32 2]343}344 345declare void @smallstruct_callee([4 x i32])346define void @test_call_smallstruct() {347; CHECK-LABEL: test_call_smallstruct:348; CHECK: mov x0, #1349; CHECK: movk x0, #2, lsl #32350; CHECK: mov x1, #3351; CHECK: movk x1, #4, lsl #32352; CHECK: bl _smallstruct_callee353 354  call void @smallstruct_callee([4 x i32] [i32 1, i32 2, i32 3, i32 4])355  ret void356}357 358declare void @smallstruct_callee_stack([8 x i64], i32, [2 x i32])359define void @test_call_smallstruct_stack() {360; CHECK-LABEL: test_call_smallstruct_stack:361; CHECK: mov [[VAL:x[0-9]+]], #1362; CHECK: movk [[VAL]], #2, lsl #32363; CHECK: stur [[VAL]], [sp, #4]364 365  call void @smallstruct_callee_stack([8 x i64] undef, i32 undef, [2 x i32] [i32 1, i32 2])366  ret void367}368 369declare [3 x i32] @returns_smallstruct()370define i32 @test_use_smallstruct_low() {371; CHECK-LABEL: test_use_smallstruct_low:372; CHECK: bl _returns_smallstruct373; CHECK: mov x0, x1374 375  %struct = call [3 x i32] @returns_smallstruct()376  %val = extractvalue [3 x i32] %struct, 2377  ret i32 %val378}379 380define i32 @test_use_smallstruct_high() {381; CHECK-LABEL: test_use_smallstruct_high:382; CHECK: bl _returns_smallstruct383; CHECK: lsr x0, x0, #32384 385  %struct = call [3 x i32] @returns_smallstruct()386  %val = extractvalue [3 x i32] %struct, 1387  ret i32 %val388}389 390; If a small struct can't be allocated to x0-x7, the remaining registers should391; be marked as unavailable and subsequent GPR arguments should also be on the392; stack. Obviously the struct itself should be passed entirely on the stack.393define i32 @test_smallstruct_padding([7 x i64], [4 x i32] %struct, i32 %in) {394; CHECK-LABEL: test_smallstruct_padding:395; CHECK-DAG: ldr [[IN:w[0-9]+]], [sp, #16]396; CHECK-DAG: ldr [[LHS:w[0-9]+]], [sp]397; CHECK: add w0, [[LHS]], [[IN]]398  %lhs = extractvalue [4 x i32] %struct, 0399  %sum = add i32 %lhs, %in400  ret i32 %sum401}402 403declare void @take_small_smallstruct(i64, [1 x i32])404define void @test_small_smallstruct() {405; CHECK-LABEL: test_small_smallstruct:406; CHECK-DAG: mov w0, #1407; CHECK-DAG: mov w1, #2408; CHECK: bl _take_small_smallstruct409  call void @take_small_smallstruct(i64 1, [1 x i32] [i32 2])410  ret void411}412 413define void @test_bare_frameaddr(ptr %addr) {414; CHECK-LABEL: test_bare_frameaddr:415; CHECK: add x[[LOCAL:[0-9]+]], sp, #{{[0-9]+}}416; CHECK: str w[[LOCAL]],417 418  %ptr = alloca i8419  store ptr %ptr, ptr %addr, align 4420  ret void421}422 423define void @test_sret_use(ptr sret([8 x i64]) %out) {424; CHECK-LABEL: test_sret_use:425; CHECK: str xzr, [x8]426  store i64 0, ptr %out427  ret void428}429 430define i64 @test_sret_call() {431; CHECK-LABEL: test_sret_call:432; CHECK: mov x8, sp433; CHECK: bl _test_sret_use434  %arr = alloca [8 x i64]435  call void @test_sret_use(ptr sret([8 x i64]) %arr)436 437  %val = load i64, ptr %arr438  ret i64 %val439}440 441define double @test_constpool() {442; CHECK-LABEL: test_constpool:443; CHECK: adrp x[[PAGE:[0-9]+]], [[POOL:lCPI[0-9]+_[0-9]+]]@PAGE444; CHECK: ldr d0, [x[[PAGE]], [[POOL]]@PAGEOFF]445  ret double 1.0e-6446}447 448define ptr @test_blockaddress() {449; CHECK-LABEL: test_blockaddress:450; CHECK: [[BLOCK:Ltmp[0-9]+]]:451; CHECK: adrp x[[PAGE:[0-9]+]], lCPI{{[0-9]+_[0-9]+}}@PAGE452; CHECK: ldr x0, [x[[PAGE]], lCPI{{[0-9]+_[0-9]+}}@PAGEOFF]453  br label %dest454dest:455  ret ptr blockaddress(@test_blockaddress, %dest)456}457 458define ptr @test_indirectbr(ptr %dest) {459; CHECK-LABEL: test_indirectbr:460; CHECK: br x0461  indirectbr ptr %dest, [label %true, label %false]462 463true:464  ret ptr blockaddress(@test_indirectbr, %true)465false:466  ret ptr blockaddress(@test_indirectbr, %false)467}468 469; ISelDAGToDAG tries to fold an offset FI load (in this case var+4) into the470; actual load instruction. This needs to be done slightly carefully since we471; claim the FI in the process -- it doesn't need extending.472define float @test_frameindex_offset_load() {473; CHECK-LABEL: test_frameindex_offset_load:474; CHECK: ldr s0, [sp, #4]475  %arr = alloca float, i32 4, align 8476  %addr = getelementptr inbounds float, ptr %arr, i32 1477 478  %val = load float, ptr %addr, align 4479  ret float %val480}481 482define void @test_unaligned_frameindex_offset_store() {483; CHECK-LABEL: test_unaligned_frameindex_offset_store:484; CHECK: mov x[[TMP:[0-9]+]], sp485; CHECK: orr w[[ADDR:[0-9]+]], w[[TMP]], #0x2486; CHECK: mov [[VAL:w[0-9]+]], #42487; CHECK: str [[VAL]], [x[[ADDR]]]488  %arr = alloca [4 x i32]489 490  %addr.int = ptrtoint ptr %arr to i32491  %addr.nextint = add nuw i32 %addr.int, 2492  %addr.next = inttoptr i32 %addr.nextint to ptr493  store i32 42, ptr %addr.next494  ret void495}496 497 498define {i64, ptr} @test_pre_idx(ptr %addr) {499; CHECK-LABEL: test_pre_idx:500 501; CHECK: add w[[ADDR:[0-9]+]], w0, #8502; CHECK: ldr x0, [x[[ADDR]]]503  %addr.int = ptrtoint ptr %addr to i32504  %addr.next.int = add nuw i32 %addr.int, 8505  %addr.next = inttoptr i32 %addr.next.int to ptr506  %val = load i64, ptr %addr.next507 508  %tmp = insertvalue {i64, ptr} undef, i64 %val, 0509  %res = insertvalue {i64, ptr} %tmp, ptr %addr.next, 1510 511  ret {i64, ptr} %res512}513 514; Forming a post-indexed load is invalid here since the GEP needs to work when515; %addr wraps round to 0.516define {i64, ptr} @test_invalid_pre_idx(ptr %addr) {517; CHECK-LABEL: test_invalid_pre_idx:518; CHECK: add w1, w0, #8519; CHECK: ldr x0, [x1]520  %addr.next = getelementptr i64, ptr %addr, i32 1521  %val = load i64, ptr %addr.next522 523  %tmp = insertvalue {i64, ptr} undef, i64 %val, 0524  %res = insertvalue {i64, ptr} %tmp, ptr %addr.next, 1525 526  ret {i64, ptr} %res527}528 529declare void @callee(ptr)530define void @test_stack_guard() ssp {531; CHECK-LABEL: test_stack_guard:532; CHECK: adrp x[[GUARD_GOTPAGE:[0-9]+]], ___stack_chk_guard@GOTPAGE533; CHECK: ldr w[[GUARD_ADDR:[0-9]+]], [x[[GUARD_GOTPAGE]], ___stack_chk_guard@GOTPAGEOFF]534; CHECK: ldr [[GUARD_VAL:w[0-9]+]], [x[[GUARD_ADDR]]]535; CHECK: stur [[GUARD_VAL]], [x29, #[[GUARD_OFFSET:-[0-9]+]]]536 537; CHECK: add x0, sp, #{{[0-9]+}}538; CHECK: bl _callee539 540; CHECK-OPT: adrp x[[GUARD_GOTPAGE:[0-9]+]], ___stack_chk_guard@GOTPAGE541; CHECK-OPT: ldr w[[GUARD_ADDR:[0-9]+]], [x[[GUARD_GOTPAGE]], ___stack_chk_guard@GOTPAGEOFF]542; CHECK-OPT: ldr [[GUARD_VAL:w[0-9]+]], [x[[GUARD_ADDR]]]543; CHECK-OPT: ldur [[NEW_VAL:w[0-9]+]], [x29, #[[GUARD_OFFSET]]]544; CHECK-OPT: cmp [[GUARD_VAL]], [[NEW_VAL]]545; CHECK-OPT: b.ne [[FAIL:LBB[0-9]+_[0-9]+]]546 547; CHECK-OPT: [[FAIL]]:548; CHECK-OPT-NEXT: bl ___stack_chk_fail549  %arr = alloca [8 x i32]550  call void @callee(ptr %arr)551  ret void552}553 554declare i32 @__gxx_personality_v0(...)555declare void @eat_landingpad_args(i32, ptr, i32)556@_ZTI8Whatever = external global i8557define void @test_landingpad_marshalling() personality ptr @__gxx_personality_v0 {558; CHECK-LABEL: test_landingpad_marshalling:559; CHECK-OPT: mov x2, x1560; CHECK-OPT: mov x1, x0561; CHECK: bl _eat_landingpad_args562  invoke void @callee(ptr undef) to label %done unwind label %lpad563 564lpad:                                             ; preds = %entry565  %exc = landingpad { ptr, i32 }566          catch ptr @_ZTI8Whatever567  %pointer = extractvalue { ptr, i32 } %exc, 0568  %selector = extractvalue { ptr, i32 } %exc, 1569  call void @eat_landingpad_args(i32 undef, ptr %pointer, i32 %selector)570  ret void571 572done:573  ret void574}575 576define void @test_dynamic_stackalloc() {577; CHECK-LABEL: test_dynamic_stackalloc:578; CHECK: sub [[REG:x[0-9]+]], sp, #32579; CHECK: mov sp, [[REG]]580; CHECK-OPT-NOT: ubfx581; CHECK: bl _callee582  br label %next583 584next:585  %val = alloca [8 x i32]586  call void @callee(ptr %val)587  ret void588}589 590define void @test_asm_memory(ptr %base.addr) {591; CHECK-LABEL: test_asm_memory:592; CHECK: add w[[ADDR:[0-9]+]], w0, #4593; CHECK: str wzr, [x[[ADDR]]594  %addr = getelementptr i32, ptr %base.addr, i32 1595  call void asm sideeffect "str wzr, $0", "*m"(ptr elementtype(i32) %addr)596  ret void597}598 599define void @test_unsafe_asm_memory(i64 %val) {600; CHECK-LABEL: test_unsafe_asm_memory:601; CHECK: mov w[[ADDR:[0-9]+]], w0602; CHECK: str wzr, [x[[ADDR]]]603  %addr_int = trunc i64 %val to i32604  %addr = inttoptr i32 %addr_int to ptr605  call void asm sideeffect "str wzr, $0", "*m"(ptr elementtype(i32) %addr)606  ret void607}608 609define [9 x ptr] @test_demoted_return(ptr %in) {610; CHECK-LABEL: test_demoted_return:611; CHECK: str w0, [x8, #32]612  %res = insertvalue [9 x ptr] undef, ptr %in, 8613  ret [9 x ptr] %res614}615 616define ptr @test_inttoptr(i64 %in) {617; CHECK-LABEL: test_inttoptr:618; CHECK-OPT: mov w0, w0619; CHECK-FAST: and x0, x0, #0xffffffff620  %res = inttoptr i64 %in to ptr621  ret ptr %res622}623 624declare i32 @llvm.get.dynamic.area.offset.i32()625define i32 @test_dynamic_area() {626; CHECK-LABEL: test_dynamic_area:627; CHECK: mov w0, wzr628  %res = call i32 @llvm.get.dynamic.area.offset.i32()629  ret i32 %res630}631 632define void @test_pointer_vec_store(ptr %addr) {633; CHECK-LABEL: test_pointer_vec_store:634; CHECK: str xzr, [x0]635; CHECK-NOT: str636; CHECK-NOT: stp637 638  store <2 x ptr> zeroinitializer, ptr %addr, align 16639  ret void640}641 642define <2 x ptr> @test_pointer_vec_load(ptr %addr) {643; CHECK-LABEL: test_pointer_vec_load:644; CHECK: ldr d[[TMP:[0-9]+]], [x0]645; CHECK: ushll.2d v0, v[[TMP]], #0646  %val = load <2 x ptr>, ptr %addr, align 16647  ret <2 x ptr> %val648}649 650define void @test_inline_asm_mem_pointer(ptr %in) {651; CHECK-LABEL: test_inline_asm_mem_pointer:652; CHECK: str w0,653  tail call void asm sideeffect "ldr x0, $0", "m"(ptr %in)654  ret void655}656 657 658define void @test_struct_hi(i32 %hi) nounwind {659; CHECK-LABEL: test_struct_hi:660; CHECK: mov w[[IN:[0-9]+]], w0661; CHECK: bl _get_int662; CHECK-FAST-NEXT: mov w[[DST:[0-9]+]], w0663; CHECK-FAST-NEXT: orr x0, x[[DST]], x[[IN]], lsl #32664; CHECK-OPT-NEXT: bfi x0, x[[IN]], #32, #32665; CHECK-NEXT: bl _take_pair666  %val.64 = call i64 @get_int()667  %val.32 = trunc i64 %val.64 to i32668 669  %pair.0 = insertvalue [2 x i32] undef, i32 %val.32, 0670  %pair.1 = insertvalue [2 x i32] %pair.0, i32 %hi, 1671  call void @take_pair([2 x i32] %pair.1)672 673  ret void674}675declare void @take_pair([2 x i32])676declare i64 @get_int()677 678define i1 @test_icmp_ptr(ptr %in) {679; CHECK-LABEL: test_icmp_ptr680; CHECK: lsr w0, w0, #31681  %res = icmp slt ptr %in, null682  ret i1 %res683}684 685define void @test_multiple_icmp_ptr(ptr %l, ptr %r) {686; CHECK-LABEL: test_multiple_icmp_ptr:687; CHECK: tbnz w0, #31, [[FALSEBB:LBB[0-9]+_[0-9]+]]688; CHECK: tbnz w1, #31, [[FALSEBB]]689  %tst1 = icmp sgt ptr %l, inttoptr (i32 -1 to ptr)690  %tst2 = icmp sgt ptr %r, inttoptr (i32 -1 to ptr)691  %tst = and i1 %tst1, %tst2692  br i1 %tst, label %true, label %false693 694true:695  call void(...) @bar()696  ret void697 698false:699  ret void700}701 702define void @test_multiple_icmp_ptr_select(ptr %l, ptr %r) {703; CHECK-LABEL: test_multiple_icmp_ptr_select:704; CHECK: tbnz w0, #31, [[FALSEBB:LBB[0-9]+_[0-9]+]]705; CHECK: tbnz w1, #31, [[FALSEBB]]706  %tst1 = icmp sgt ptr %l, inttoptr (i32 -1 to ptr)707  %tst2 = icmp sgt ptr %r, inttoptr (i32 -1 to ptr)708  %tst = select i1 %tst1, i1 %tst2, i1 false709  br i1 %tst, label %true, label %false710 711true:712  call void(...) @bar()713  ret void714 715false:716  ret void717}718 719define ptr @test_gep_nonpow2(ptr %a0, i32 %a1) {720; CHECK-LABEL: test_gep_nonpow2:721; CHECK-OPT:      mov w[[SIZE:[0-9]+]], #18722; CHECK-OPT-NEXT: smaddl x0, w1, w[[SIZE]], x0723; CHECK-OPT-NEXT: ret724 725; CHECK-FAST:      mov w[[SIZE:[0-9]+]], #18726; CHECK-FAST-NEXT: smaddl [[TMP:x[0-9]+]], w1, w[[SIZE]], x0727; CHECK-FAST-NEXT: and x0, [[TMP]], #0xffffffff728; CHECK-FAST-NEXT: ret729  %tmp0 = getelementptr inbounds { [18 x i8] }, ptr %a0, i32 %a1730  ret ptr %tmp0731}732 733define void @test_memset(i64 %in, i8 %value)  {734; CHECK-LABEL: test_memset:735; CHECK-DAG: lsr x2, x0, #32736; CHECK-DAG: mov w0, w0737; CHECK: b _memset738 739  %ptr.i32 = trunc i64 %in to i32740  %size.64 = lshr i64 %in, 32741  %size = trunc i64 %size.64 to i32742  %ptr = inttoptr i32 %ptr.i32 to ptr743  tail call void @llvm.memset.p0.i32(ptr align 4 %ptr, i8 %value, i32 %size, i1 false)744  ret void745}746 747define void @test_bzero(i64 %in)  {748; CHECK-LABEL: test_bzero:749; CHECK-DAG: lsr x1, x0, #32750; CHECK-DAG: mov w0, w0751; CHECK: b _bzero752 753  %ptr.i32 = trunc i64 %in to i32754  %size.64 = lshr i64 %in, 32755  %size = trunc i64 %size.64 to i32756  %ptr = inttoptr i32 %ptr.i32 to ptr757  tail call void @llvm.memset.p0.i32(ptr align 4 %ptr, i8 0, i32 %size, i1 false)758  ret void759}760 761declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1)762 763define i1 @test_stackguard(ptr %p1) {764; CHECK-LABEL: test_stackguard:765; CHECK: adrp x[[TMP:[0-9]+]], ___stack_chk_guard@GOTPAGE766; CHECK: ldr [[GUARD:w[0-9]+]], [x[[TMP]], ___stack_chk_guard@GOTPAGEOFF]767; CHECK: cmp [[GUARD]], w768 769  %p2 = call ptr @llvm.stackguard()770  %res = icmp ne ptr %p2, %p1771  ret i1 %res772}773declare ptr @llvm.stackguard()774@__stack_chk_guard = external global i32775 776 777!llvm.module.flags = !{!0}778!0 = !{i32 7, !"PIC Level", i32 2}779