| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 |
| ; Codegen for load/store addresses of the form (base + large constant offset) |
| ; under the Qualcomm Xqcilo/Xqcilia extensions. |
| ; |
| ; RUN: llc < %s -mtriple=riscv32 -mattr=+xqcilo,+xqcilia -riscv-no-aliases \ |
| ; RUN: | FileCheck %s --check-prefix=CHECK |
| |
| ;===----------------------------------------------------------------------===; |
| ; Path A: offset in simm26 but not simm12 -> folded directly into qc.e.lw/sw. |
| ;===----------------------------------------------------------------------===; |
| |
| define i32 @load_simm26_pos(ptr %p) nounwind optsize { |
| ; CHECK-LABEL: load_simm26_pos: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: qc.e.lw a0, 3000000(a0) |
| ; CHECK-NEXT: c.jr ra |
| %g = getelementptr inbounds nuw i8, ptr %p, i32 3000000 |
| %v = load i32, ptr %g, align 4 |
| ret i32 %v |
| } |
| |
| ; Positive simm26 boundary (maxIntN(26) = 33554431). |
| define i32 @load_simm26_pos_max(ptr %p) nounwind optsize { |
| ; CHECK-LABEL: load_simm26_pos_max: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: qc.e.lw a0, 33554431(a0) |
| ; CHECK-NEXT: c.jr ra |
| %g = getelementptr inbounds nuw i8, ptr %p, i32 33554431 |
| %v = load i32, ptr %g, align 4 |
| ret i32 %v |
| } |
| |
| define i32 @load_simm26_neg(ptr %p) nounwind optsize { |
| ; CHECK-LABEL: load_simm26_neg: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: qc.e.lw a0, -3000000(a0) |
| ; CHECK-NEXT: c.jr ra |
| %g = getelementptr inbounds nuw i8, ptr %p, i32 -3000000 |
| %v = load i32, ptr %g, align 4 |
| ret i32 %v |
| } |
| |
| ; Negative simm26 boundary (minIntN(26) = -33554432). |
| define i32 @load_simm26_neg_max(ptr %p) nounwind optsize { |
| ; CHECK-LABEL: load_simm26_neg_max: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: qc.e.lw a0, -33554432(a0) |
| ; CHECK-NEXT: c.jr ra |
| %g = getelementptr inbounds nuw i8, ptr %p, i32 -33554432 |
| %v = load i32, ptr %g, align 4 |
| ret i32 %v |
| } |
| |
| define void @store_simm26_pos(ptr %p, i32 %v) nounwind optsize { |
| ; CHECK-LABEL: store_simm26_pos: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: qc.e.sw a1, 3000000(a0) |
| ; CHECK-NEXT: c.jr ra |
| %g = getelementptr inbounds nuw i8, ptr %p, i32 3000000 |
| store i32 %v, ptr %g, align 4 |
| ret void |
| } |
| |
| define void @store_simm26_neg(ptr %p, i32 %v) nounwind optsize { |
| ; CHECK-LABEL: store_simm26_neg: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: qc.e.sw a1, -3000000(a0) |
| ; CHECK-NEXT: c.jr ra |
| %g = getelementptr inbounds nuw i8, ptr %p, i32 -3000000 |
| store i32 %v, ptr %g, align 4 |
| ret void |
| } |
| |
| ;===----------------------------------------------------------------------===; |
| ; Path B: offset just outside simm26 where the saturation adjustment fits simm6 |
| ; -> compressible ADDI (c.addi) + qc.e.lw/sw. |
| ;===----------------------------------------------------------------------===; |
| |
| ; Positive, boundary (maxIntN(26) + 31): +31 adjustment fits simm6. |
| define i32 @load_band_pos_boundary(ptr %p) nounwind optsize { |
| ; CHECK-LABEL: load_band_pos_boundary: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: c.addi a0, 31 |
| ; CHECK-NEXT: qc.e.lw a0, 33554431(a0) |
| ; CHECK-NEXT: c.jr ra |
| %g = getelementptr inbounds nuw i8, ptr %p, i32 33554462 |
| %v = load i32, ptr %g, align 4 |
| ret i32 %v |
| } |
| |
| ; Negative, boundary (minIntN(26) - 32): -32 adjustment fits simm6. |
| define i32 @load_band_neg_boundary(ptr %p) nounwind optsize { |
| ; CHECK-LABEL: load_band_neg_boundary: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: c.addi a0, -32 |
| ; CHECK-NEXT: qc.e.lw a0, -33554432(a0) |
| ; CHECK-NEXT: c.jr ra |
| %g = getelementptr inbounds nuw i8, ptr %p, i32 -33554464 |
| %v = load i32, ptr %g, align 4 |
| ret i32 %v |
| } |
| |
| define void @store_band_pos_boundary(ptr %p, i32 %v) nounwind optsize { |
| ; CHECK-LABEL: store_band_pos_boundary: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: c.addi a0, 31 |
| ; CHECK-NEXT: qc.e.sw a1, 33554431(a0) |
| ; CHECK-NEXT: c.jr ra |
| %g = getelementptr inbounds nuw i8, ptr %p, i32 33554462 |
| store i32 %v, ptr %g, align 4 |
| ret void |
| } |
| |
| define void @store_band_neg_boundary(ptr %p, i32 %v) nounwind optsize { |
| ; CHECK-LABEL: store_band_neg_boundary: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: c.addi a0, -32 |
| ; CHECK-NEXT: qc.e.sw a1, -33554432(a0) |
| ; CHECK-NEXT: c.jr ra |
| %g = getelementptr inbounds nuw i8, ptr %p, i32 -33554464 |
| store i32 %v, ptr %g, align 4 |
| ret void |
| } |
| |
| ;===----------------------------------------------------------------------===; |
| ; Path C: the saturation adjustment does not fit simm6, but the residual low-12 |
| ; offset is 4-aligned and in the c.lw range, therefore the standard lui + add + |
| ; c.lw/c.sw sequence (with a compressible access) is used. |
| ;===----------------------------------------------------------------------===; |
| |
| ; Positive, low-12 offset 32 (4-aligned, in c.lw range). |
| define i32 @load_pathC_pos(ptr %p) nounwind optsize { |
| ; CHECK-LABEL: load_pathC_pos: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: lui a1, 8192 |
| ; CHECK-NEXT: c.add a0, a1 |
| ; CHECK-NEXT: c.lw a0, 32(a0) |
| ; CHECK-NEXT: c.jr ra |
| %g = getelementptr inbounds nuw i8, ptr %p, i32 33554464 |
| %v = load i32, ptr %g, align 4 |
| ret i32 %v |
| } |
| |
| ; Negative, low-12 offset 0 (4-aligned, in c.lw range). |
| define i32 @load_pathC_neg(ptr %p) nounwind optsize { |
| ; CHECK-LABEL: load_pathC_neg: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: lui a1, 1040383 |
| ; CHECK-NEXT: c.add a0, a1 |
| ; CHECK-NEXT: c.lw a0, 0(a0) |
| ; CHECK-NEXT: c.jr ra |
| %g = getelementptr inbounds nuw i8, ptr %p, i32 -33558528 |
| %v = load i32, ptr %g, align 4 |
| ret i32 %v |
| } |
| |
| define void @store_pathC_pos(ptr %p, i32 %v) nounwind optsize { |
| ; CHECK-LABEL: store_pathC_pos: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: lui a2, 8192 |
| ; CHECK-NEXT: c.add a0, a2 |
| ; CHECK-NEXT: c.sw a1, 32(a0) |
| ; CHECK-NEXT: c.jr ra |
| %g = getelementptr inbounds nuw i8, ptr %p, i32 33554464 |
| store i32 %v, ptr %g, align 4 |
| ret void |
| } |
| |
| define void @store_pathC_neg(ptr %p, i32 %v) nounwind optsize { |
| ; CHECK-LABEL: store_pathC_neg: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: lui a2, 1040383 |
| ; CHECK-NEXT: c.add a0, a2 |
| ; CHECK-NEXT: c.sw a1, 0(a0) |
| ; CHECK-NEXT: c.jr ra |
| %g = getelementptr inbounds nuw i8, ptr %p, i32 -33558528 |
| store i32 %v, ptr %g, align 4 |
| ret void |
| } |
| |
| ;===----------------------------------------------------------------------===; |
| ; Path D: the saturation adjustment does not fit simm6, the residual low-12 |
| ; offset is not c.lw-compressible, therefore ADDI + qc.e.lw/sw is emitted. |
| ;===----------------------------------------------------------------------===; |
| |
| define i32 @load_pathD_pos(ptr %p) nounwind optsize { |
| ; CHECK-LABEL: load_pathD_pos: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: addi a0, a0, 129 |
| ; CHECK-NEXT: qc.e.lw a0, 33554431(a0) |
| ; CHECK-NEXT: c.jr ra |
| %g = getelementptr inbounds nuw i8, ptr %p, i32 33554560 |
| %v = load i32, ptr %g, align 4 |
| ret i32 %v |
| } |
| |
| define i32 @load_pathD_neg(ptr %p) nounwind optsize { |
| ; CHECK-LABEL: load_pathD_neg: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: addi a0, a0, -128 |
| ; CHECK-NEXT: qc.e.lw a0, -33554432(a0) |
| ; CHECK-NEXT: c.jr ra |
| %g = getelementptr inbounds nuw i8, ptr %p, i32 -33554560 |
| %v = load i32, ptr %g, align 4 |
| ret i32 %v |
| } |
| |
| define void @store_pathD_pos(ptr %p, i32 %v) nounwind optsize { |
| ; CHECK-LABEL: store_pathD_pos: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: addi a0, a0, 129 |
| ; CHECK-NEXT: qc.e.sw a1, 33554431(a0) |
| ; CHECK-NEXT: c.jr ra |
| %g = getelementptr inbounds nuw i8, ptr %p, i32 33554560 |
| store i32 %v, ptr %g, align 4 |
| ret void |
| } |
| |
| define void @store_pathD_neg(ptr %p, i32 %v) nounwind optsize { |
| ; CHECK-LABEL: store_pathD_neg: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: addi a0, a0, -128 |
| ; CHECK-NEXT: qc.e.sw a1, -33554432(a0) |
| ; CHECK-NEXT: c.jr ra |
| %g = getelementptr inbounds nuw i8, ptr %p, i32 -33554560 |
| store i32 %v, ptr %g, align 4 |
| ret void |
| } |
| |
| ;===----------------------------------------------------------------------===; |
| ; Path E: the offset is so far outside simm26 that even the simm12 split does |
| ; not land back in simm26 therefore lui + add + lw is used and no qc.e.addai is |
| ; emitted for a single-use address. |
| ;===----------------------------------------------------------------------===; |
| |
| define i32 @load_too_large(ptr %p) nounwind optsize { |
| ; CHECK-LABEL: load_too_large: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: lui a1, 17090 |
| ; CHECK-NEXT: c.add a0, a1 |
| ; CHECK-NEXT: lw a0, -640(a0) |
| ; CHECK-NEXT: c.jr ra |
| %g = getelementptr inbounds nuw i8, ptr %p, i32 70000000 |
| %v = load i32, ptr %g, align 4 |
| ret i32 %v |
| } |
| |
| define i32 @load_too_large_neg(ptr %p) nounwind optsize { |
| ; CHECK-LABEL: load_too_large_neg: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: lui a1, 1031486 |
| ; CHECK-NEXT: c.add a0, a1 |
| ; CHECK-NEXT: lw a0, 640(a0) |
| ; CHECK-NEXT: c.jr ra |
| %g = getelementptr inbounds nuw i8, ptr %p, i32 -70000000 |
| %v = load i32, ptr %g, align 4 |
| ret i32 %v |
| } |
| |
| define void @store_too_large(ptr %p, i32 %v) nounwind optsize { |
| ; CHECK-LABEL: store_too_large: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: lui a2, 17090 |
| ; CHECK-NEXT: c.add a0, a2 |
| ; CHECK-NEXT: sw a1, -640(a0) |
| ; CHECK-NEXT: c.jr ra |
| %g = getelementptr inbounds nuw i8, ptr %p, i32 70000000 |
| store i32 %v, ptr %g, align 4 |
| ret void |
| } |
| |
| define void @store_too_large_neg(ptr %p, i32 %v) nounwind optsize { |
| ; CHECK-LABEL: store_too_large_neg: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: lui a2, 1031486 |
| ; CHECK-NEXT: c.add a0, a2 |
| ; CHECK-NEXT: sw a1, 640(a0) |
| ; CHECK-NEXT: c.jr ra |
| %g = getelementptr inbounds nuw i8, ptr %p, i32 -70000000 |
| store i32 %v, ptr %g, align 4 |
| ret void |
| } |
| |
| ;===----------------------------------------------------------------------===; |
| ; Path F: Shared-base / reuse cases: multiple accesses off the same pointer whose |
| ; large offsets are close enough to share one materialized base. |
| ;===----------------------------------------------------------------------===; |
| |
| ; Base %p reused (also loaded at a small offset), two accesses. |
| define i32 @load_band_reuse2(ptr %p) nounwind optsize { |
| ; CHECK-LABEL: load_band_reuse2: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: addi a1, a0, 569 |
| ; CHECK-NEXT: c.lw a0, 100(a0) |
| ; CHECK-NEXT: qc.e.lw a1, 33554431(a1) |
| ; CHECK-NEXT: c.add a0, a1 |
| ; CHECK-NEXT: c.jr ra |
| %g0 = getelementptr inbounds nuw i8, ptr %p, i32 33555000 |
| %v0 = load i32, ptr %g0, align 4 |
| %g1 = getelementptr inbounds nuw i8, ptr %p, i32 100 |
| %v1 = load i32, ptr %g1, align 4 |
| %r1 = add i32 %v1, %v0 |
| ret i32 %r1 |
| } |
| |
| ; Base %p reused with a third large-offset access sharing the common base. |
| define i32 @load_band_reuse(ptr %p) nounwind optsize { |
| ; CHECK-LABEL: load_band_reuse: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: c.mv a1, a0 |
| ; CHECK-NEXT: qc.e.addai a1, 33554462 |
| ; CHECK-NEXT: c.lw a0, 100(a0) |
| ; CHECK-NEXT: lw a2, 538(a1) |
| ; CHECK-NEXT: c.lw a1, 0(a1) |
| ; CHECK-NEXT: c.add a0, a2 |
| ; CHECK-NEXT: c.add a0, a1 |
| ; CHECK-NEXT: c.jr ra |
| %g0 = getelementptr inbounds nuw i8, ptr %p, i32 33555000 |
| %v0 = load i32, ptr %g0, align 4 |
| %g1 = getelementptr inbounds nuw i8, ptr %p, i32 100 |
| %v1 = load i32, ptr %g1, align 4 |
| %g2 = getelementptr inbounds nuw i8, ptr %p, i32 33554462 |
| %v2 = load i32, ptr %g2, align 4 |
| %r1 = add i32 %v1, %v0 |
| %r2 = add i32 %r1, %v2 |
| ret i32 %r2 |
| } |
| |
| ; Four large-offset accesses; the last one's delta from the shared base exceeds |
| ; simm26 (by 1), so it needs a separate base materialization. |
| define i32 @load_band_reuse_4(ptr %p) nounwind optsize { |
| ; CHECK-LABEL: load_band_reuse_4: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: lui a1, 16384 |
| ; CHECK-NEXT: c.mv a2, a0 |
| ; CHECK-NEXT: c.lw a3, 100(a0) |
| ; CHECK-NEXT: qc.e.addai a2, 33554462 |
| ; CHECK-NEXT: lw a4, 538(a2) |
| ; CHECK-NEXT: c.lw a5, 0(a2) |
| ; CHECK-NEXT: c.add a0, a1 |
| ; CHECK-NEXT: qc.e.lw a1, 33554431(a2) |
| ; CHECK-NEXT: lw a0, 30(a0) |
| ; CHECK-NEXT: c.add a3, a4 |
| ; CHECK-NEXT: c.add a1, a5 |
| ; CHECK-NEXT: c.add a1, a3 |
| ; CHECK-NEXT: c.add a0, a1 |
| ; CHECK-NEXT: c.jr ra |
| %g0 = getelementptr inbounds nuw i8, ptr %p, i32 33555000 |
| %v0 = load i32, ptr %g0, align 4 |
| %g1 = getelementptr inbounds nuw i8, ptr %p, i32 100 |
| %v1 = load i32, ptr %g1, align 4 |
| %g2 = getelementptr inbounds nuw i8, ptr %p, i32 33554462 |
| %v2 = load i32, ptr %g2, align 4 |
| %g3 = getelementptr inbounds nuw i8, ptr %p, i32 67108893 |
| %v3 = load i32, ptr %g3, align 4 |
| %g4 = getelementptr inbounds nuw i8, ptr %p, i32 67108894 |
| %v4 = load i32, ptr %g4, align 4 |
| %r1 = add i32 %v1, %v0 |
| %r2 = add i32 %r1, %v2 |
| %r3 = add i32 %r2, %v3 |
| %r4 = add i32 %r3, %v4 |
| ret i32 %r4 |
| } |
| |
| ; Two loads whose offsets differ by a foldable 26-bit amount: the DAG shares a |
| ; common base %p + 70000000 (materialized once as qc.e.addai) and folds the |
| ; second access's residual into a qc.e.lw. |
| define i32 @qcaddai_plus_qcelw(ptr %p) nounwind optsize { |
| ; CHECK-LABEL: qcaddai_plus_qcelw: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: qc.e.addai a0, 70000000 |
| ; CHECK-NEXT: c.lw a1, 0(a0) |
| ; CHECK-NEXT: qc.e.lw a0, 40000(a0) |
| ; CHECK-NEXT: c.add a0, a1 |
| ; CHECK-NEXT: c.jr ra |
| %g0 = getelementptr inbounds nuw i8, ptr %p, i32 70000000 |
| %v0 = load i32, ptr %g0, align 4 |
| %g1 = getelementptr inbounds nuw i8, ptr %p, i32 70040000 |
| %v1 = load i32, ptr %g1, align 4 |
| %r = add i32 %v0, %v1 |
| ret i32 %r |
| } |
| |
| ; Store variant of the shared-base qc.e.addai case above. |
| define void @qcaddai_plus_qcesw(ptr %p, i32 %v) nounwind optsize { |
| ; CHECK-LABEL: qcaddai_plus_qcesw: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: qc.e.addai a0, 70000000 |
| ; CHECK-NEXT: c.sw a1, 0(a0) |
| ; CHECK-NEXT: qc.e.sw a1, 40000(a0) |
| ; CHECK-NEXT: c.jr ra |
| %g0 = getelementptr inbounds nuw i8, ptr %p, i32 70000000 |
| store i32 %v, ptr %g0, align 4 |
| %g1 = getelementptr inbounds nuw i8, ptr %p, i32 70040000 |
| store i32 %v, ptr %g1, align 4 |
| ret void |
| } |
| |
| ;===----------------------------------------------------------------------===; |
| ; Path G: Offset is within compressed immediate range for loads however due to |
| ; register pressure, register allocator is not able to allocate any register |
| ; from GPRC register set resulting in lw not being compressed. |
| ;===----------------------------------------------------------------------===; |
| |
| define i32 @load_no_clw_reg_pressure(ptr %p) nounwind { |
| ; CHECK-LABEL: load_no_clw_reg_pressure: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: c.lw a1, 0(a0) |
| ; CHECK-NEXT: c.lw a2, 4(a0) |
| ; CHECK-NEXT: c.lw a3, 8(a0) |
| ; CHECK-NEXT: c.lw a4, 12(a0) |
| ; CHECK-NEXT: c.lw a5, 16(a0) |
| ; CHECK-NEXT: lw a6, 20(a0) |
| ; CHECK-NEXT: lw a7, 24(a0) |
| ; CHECK-NEXT: lw t0, 28(a0) |
| ; CHECK-NEXT: lw t1, 32(a0) |
| ; CHECK-NEXT: lw t2, 36(a0) |
| ; CHECK-NEXT: c.add a1, a2 |
| ; CHECK-NEXT: c.add a3, a4 |
| ; CHECK-NEXT: c.lw a2, 40(a0) |
| ; CHECK-NEXT: c.lw a0, 44(a0) |
| ; CHECK-NEXT: c.add a1, a3 |
| ; CHECK-NEXT: c.add a5, a6 |
| ; CHECK-NEXT: c.add t0, t1 |
| ; CHECK-NEXT: c.add a5, a7 |
| ; CHECK-NEXT: c.add t0, t2 |
| ; CHECK-NEXT: c.add a1, a5 |
| ; CHECK-NEXT: c.add a2, t0 |
| ; CHECK-NEXT: c.add a1, a2 |
| ; CHECK-NEXT: c.add a0, a1 |
| ; CHECK-NEXT: c.jr ra |
| %g0 = getelementptr inbounds nuw i8, ptr %p, i32 0 |
| %g1 = getelementptr inbounds nuw i8, ptr %p, i32 4 |
| %g2 = getelementptr inbounds nuw i8, ptr %p, i32 8 |
| %g3 = getelementptr inbounds nuw i8, ptr %p, i32 12 |
| %g4 = getelementptr inbounds nuw i8, ptr %p, i32 16 |
| %g5 = getelementptr inbounds nuw i8, ptr %p, i32 20 |
| %g6 = getelementptr inbounds nuw i8, ptr %p, i32 24 |
| %g7 = getelementptr inbounds nuw i8, ptr %p, i32 28 |
| %g8 = getelementptr inbounds nuw i8, ptr %p, i32 32 |
| %g9 = getelementptr inbounds nuw i8, ptr %p, i32 36 |
| %g10 = getelementptr inbounds nuw i8, ptr %p, i32 40 |
| %g11 = getelementptr inbounds nuw i8, ptr %p, i32 44 |
| %v0 = load i32, ptr %g0 |
| %v1 = load i32, ptr %g1 |
| %v2 = load i32, ptr %g2 |
| %v3 = load i32, ptr %g3 |
| %v4 = load i32, ptr %g4 |
| %v5 = load i32, ptr %g5 |
| %v6 = load i32, ptr %g6 |
| %v7 = load i32, ptr %g7 |
| %v8 = load i32, ptr %g8 |
| %v9 = load i32, ptr %g9 |
| %v10 = load i32, ptr %g10 |
| %v11 = load i32, ptr %g11 |
| %s0 = add i32 %v0, %v1 |
| %s1 = add i32 %s0, %v2 |
| %s2 = add i32 %s1, %v3 |
| %s3 = add i32 %s2, %v4 |
| %s4 = add i32 %s3, %v5 |
| %s5 = add i32 %s4, %v6 |
| %s6 = add i32 %s5, %v7 |
| %s7 = add i32 %s6, %v8 |
| %s8 = add i32 %s7, %v9 |
| %s9 = add i32 %s8, %v10 |
| %s10 = add i32 %s9, %v11 |
| ret i32 %s10 |
| } |