|
| 1 | +; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3 |
| 2 | +; RUN: llc -mtriple=riscv32 \ |
| 3 | +; RUN: -global-isel -stop-after=irtranslator -verify-machineinstrs < %s \ |
| 4 | +; RUN: | FileCheck -check-prefix=RV32I %s |
| 5 | +; RUN: llc -mtriple=riscv32 -mattr=+f -target-abi ilp32f \ |
| 6 | +; RUN: -global-isel -stop-after=irtranslator -verify-machineinstrs < %s \ |
| 7 | +; RUN: | FileCheck -check-prefix=RV32I %s |
| 8 | +; RUN: llc -mtriple=riscv32 -mattr=+d -target-abi ilp32d \ |
| 9 | +; RUN: -global-isel -stop-after=irtranslator -verify-machineinstrs < %s \ |
| 10 | +; RUN: | FileCheck -check-prefix=RV32I %s |
| 11 | + |
| 12 | +; This file contains tests that should have identical output for the ilp32, |
| 13 | +; ilp32f, and ilp32d ABIs. i.e. where no arguments are passed according to |
| 14 | +; the floating point ABI. |
| 15 | + |
| 16 | +; Check that on RV32, i64 is passed in a pair of registers. Unlike |
| 17 | +; the convention for varargs, this need not be an aligned pair. |
| 18 | + |
| 19 | +define i32 @callee_i64_in_regs(i32 %a, i64 %b) nounwind { |
| 20 | + ; RV32I-LABEL: name: callee_i64_in_regs |
| 21 | + ; RV32I: bb.1 (%ir-block.0): |
| 22 | + ; RV32I-NEXT: liveins: $x10, $x11, $x12 |
| 23 | + ; RV32I-NEXT: {{ $}} |
| 24 | + ; RV32I-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 |
| 25 | + ; RV32I-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 |
| 26 | + ; RV32I-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x12 |
| 27 | + ; RV32I-NEXT: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY1]](s32), [[COPY2]](s32) |
| 28 | + ; RV32I-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[MV]](s64) |
| 29 | + ; RV32I-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[TRUNC]] |
| 30 | + ; RV32I-NEXT: $x10 = COPY [[ADD]](s32) |
| 31 | + ; RV32I-NEXT: PseudoRET implicit $x10 |
| 32 | + %b_trunc = trunc i64 %b to i32 |
| 33 | + %1 = add i32 %a, %b_trunc |
| 34 | + ret i32 %1 |
| 35 | +} |
| 36 | + |
| 37 | +define i32 @caller_i64_in_regs() nounwind { |
| 38 | + ; RV32I-LABEL: name: caller_i64_in_regs |
| 39 | + ; RV32I: bb.1 (%ir-block.0): |
| 40 | + ; RV32I-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 |
| 41 | + ; RV32I-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 2 |
| 42 | + ; RV32I-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C1]](s64) |
| 43 | + ; RV32I-NEXT: $x10 = COPY [[C]](s32) |
| 44 | + ; RV32I-NEXT: $x11 = COPY [[UV]](s32) |
| 45 | + ; RV32I-NEXT: $x12 = COPY [[UV1]](s32) |
| 46 | + ; RV32I-NEXT: PseudoCALL target-flags(riscv-call) @callee_i64_in_regs, implicit-def $x1, implicit $x10, implicit $x11, implicit $x12, implicit-def $x10 |
| 47 | + ; RV32I-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 |
| 48 | + ; RV32I-NEXT: $x10 = COPY [[COPY]](s32) |
| 49 | + ; RV32I-NEXT: PseudoRET implicit $x10 |
| 50 | + %1 = call i32 @callee_i64_in_regs(i32 1, i64 2) |
| 51 | + ret i32 %1 |
| 52 | +} |
| 53 | + |
| 54 | +; Check that the stack is used once the GPRs are exhausted |
| 55 | + |
| 56 | +define i32 @callee_many_scalars(i8 %a, i16 %b, i32 %c, i64 %d, i32 %e, i32 %f, i64 %g, i32 %h) nounwind { |
| 57 | + ; RV32I-LABEL: name: callee_many_scalars |
| 58 | + ; RV32I: bb.1 (%ir-block.0): |
| 59 | + ; RV32I-NEXT: liveins: $x10, $x11, $x12, $x13, $x14, $x15, $x16, $x17 |
| 60 | + ; RV32I-NEXT: {{ $}} |
| 61 | + ; RV32I-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 |
| 62 | + ; RV32I-NEXT: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) |
| 63 | + ; RV32I-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 |
| 64 | + ; RV32I-NEXT: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) |
| 65 | + ; RV32I-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x12 |
| 66 | + ; RV32I-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $x13 |
| 67 | + ; RV32I-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY $x14 |
| 68 | + ; RV32I-NEXT: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY3]](s32), [[COPY4]](s32) |
| 69 | + ; RV32I-NEXT: [[COPY5:%[0-9]+]]:_(s32) = COPY $x15 |
| 70 | + ; RV32I-NEXT: [[COPY6:%[0-9]+]]:_(s32) = COPY $x16 |
| 71 | + ; RV32I-NEXT: [[COPY7:%[0-9]+]]:_(s32) = COPY $x17 |
| 72 | + ; RV32I-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.1 |
| 73 | + ; RV32I-NEXT: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (load (s32) from %fixed-stack.1, align 16) |
| 74 | + ; RV32I-NEXT: [[MV1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY7]](s32), [[LOAD]](s32) |
| 75 | + ; RV32I-NEXT: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.0 |
| 76 | + ; RV32I-NEXT: [[LOAD1:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX1]](p0) :: (load (s32) from %fixed-stack.0) |
| 77 | + ; RV32I-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s8) |
| 78 | + ; RV32I-NEXT: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC1]](s16) |
| 79 | + ; RV32I-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ZEXT]], [[ZEXT1]] |
| 80 | + ; RV32I-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[ADD]], [[COPY2]] |
| 81 | + ; RV32I-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[MV]](s64), [[MV1]] |
| 82 | + ; RV32I-NEXT: [[ZEXT2:%[0-9]+]]:_(s32) = G_ZEXT [[ICMP]](s1) |
| 83 | + ; RV32I-NEXT: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[ZEXT2]], [[ADD1]] |
| 84 | + ; RV32I-NEXT: [[ADD3:%[0-9]+]]:_(s32) = G_ADD [[ADD2]], [[COPY5]] |
| 85 | + ; RV32I-NEXT: [[ADD4:%[0-9]+]]:_(s32) = G_ADD [[ADD3]], [[COPY6]] |
| 86 | + ; RV32I-NEXT: [[ADD5:%[0-9]+]]:_(s32) = G_ADD [[ADD4]], [[LOAD1]] |
| 87 | + ; RV32I-NEXT: $x10 = COPY [[ADD5]](s32) |
| 88 | + ; RV32I-NEXT: PseudoRET implicit $x10 |
| 89 | + %a_ext = zext i8 %a to i32 |
| 90 | + %b_ext = zext i16 %b to i32 |
| 91 | + %1 = add i32 %a_ext, %b_ext |
| 92 | + %2 = add i32 %1, %c |
| 93 | + %3 = icmp eq i64 %d, %g |
| 94 | + %4 = zext i1 %3 to i32 |
| 95 | + %5 = add i32 %4, %2 |
| 96 | + %6 = add i32 %5, %e |
| 97 | + %7 = add i32 %6, %f |
| 98 | + %8 = add i32 %7, %h |
| 99 | + ret i32 %8 |
| 100 | +} |
| 101 | + |
| 102 | +define i32 @caller_many_scalars() nounwind { |
| 103 | + ; RV32I-LABEL: name: caller_many_scalars |
| 104 | + ; RV32I: bb.1 (%ir-block.0): |
| 105 | + ; RV32I-NEXT: [[C:%[0-9]+]]:_(s8) = G_CONSTANT i8 1 |
| 106 | + ; RV32I-NEXT: [[C1:%[0-9]+]]:_(s16) = G_CONSTANT i16 2 |
| 107 | + ; RV32I-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 |
| 108 | + ; RV32I-NEXT: [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 4 |
| 109 | + ; RV32I-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 5 |
| 110 | + ; RV32I-NEXT: [[C5:%[0-9]+]]:_(s32) = G_CONSTANT i32 6 |
| 111 | + ; RV32I-NEXT: [[C6:%[0-9]+]]:_(s64) = G_CONSTANT i64 7 |
| 112 | + ; RV32I-NEXT: [[C7:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 |
| 113 | + ; RV32I-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[C]](s8) |
| 114 | + ; RV32I-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[C1]](s16) |
| 115 | + ; RV32I-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C3]](s64) |
| 116 | + ; RV32I-NEXT: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C6]](s64) |
| 117 | + ; RV32I-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x2 |
| 118 | + ; RV32I-NEXT: [[C8:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 |
| 119 | + ; RV32I-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C8]](s32) |
| 120 | + ; RV32I-NEXT: G_STORE [[UV3]](s32), [[PTR_ADD]](p0) :: (store (s32) into stack, align 16) |
| 121 | + ; RV32I-NEXT: [[C9:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 |
| 122 | + ; RV32I-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C9]](s32) |
| 123 | + ; RV32I-NEXT: G_STORE [[C7]](s32), [[PTR_ADD1]](p0) :: (store (s32) into stack + 4) |
| 124 | + ; RV32I-NEXT: $x10 = COPY [[ANYEXT]](s32) |
| 125 | + ; RV32I-NEXT: $x11 = COPY [[ANYEXT1]](s32) |
| 126 | + ; RV32I-NEXT: $x12 = COPY [[C2]](s32) |
| 127 | + ; RV32I-NEXT: $x13 = COPY [[UV]](s32) |
| 128 | + ; RV32I-NEXT: $x14 = COPY [[UV1]](s32) |
| 129 | + ; RV32I-NEXT: $x15 = COPY [[C4]](s32) |
| 130 | + ; RV32I-NEXT: $x16 = COPY [[C5]](s32) |
| 131 | + ; RV32I-NEXT: $x17 = COPY [[UV2]](s32) |
| 132 | + ; RV32I-NEXT: PseudoCALL target-flags(riscv-call) @callee_many_scalars, implicit-def $x1, implicit $x10, implicit $x11, implicit $x12, implicit $x13, implicit $x14, implicit $x15, implicit $x16, implicit $x17, implicit-def $x10 |
| 133 | + ; RV32I-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x10 |
| 134 | + ; RV32I-NEXT: $x10 = COPY [[COPY1]](s32) |
| 135 | + ; RV32I-NEXT: PseudoRET implicit $x10 |
| 136 | + %1 = call i32 @callee_many_scalars(i8 1, i16 2, i32 3, i64 4, i32 5, i32 6, i64 7, i32 8) |
| 137 | + ret i32 %1 |
| 138 | +} |
| 139 | + |
| 140 | +; Check return of 2x xlen scalars |
| 141 | + |
| 142 | +define i64 @callee_small_scalar_ret() nounwind { |
| 143 | + ; RV32I-LABEL: name: callee_small_scalar_ret |
| 144 | + ; RV32I: bb.1 (%ir-block.0): |
| 145 | + ; RV32I-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 1234567898765 |
| 146 | + ; RV32I-NEXT: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[C]](s64) |
| 147 | + ; RV32I-NEXT: $x10 = COPY [[UV]](s32) |
| 148 | + ; RV32I-NEXT: $x11 = COPY [[UV1]](s32) |
| 149 | + ; RV32I-NEXT: PseudoRET implicit $x10, implicit $x11 |
| 150 | + ret i64 1234567898765 |
| 151 | +} |
| 152 | + |
| 153 | +define i32 @caller_small_scalar_ret() nounwind { |
| 154 | + ; RV32I-LABEL: name: caller_small_scalar_ret |
| 155 | + ; RV32I: bb.1 (%ir-block.0): |
| 156 | + ; RV32I-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 987654321234567 |
| 157 | + ; RV32I-NEXT: PseudoCALL target-flags(riscv-call) @callee_small_scalar_ret, implicit-def $x1, implicit-def $x10, implicit-def $x11 |
| 158 | + ; RV32I-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 |
| 159 | + ; RV32I-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11 |
| 160 | + ; RV32I-NEXT: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32) |
| 161 | + ; RV32I-NEXT: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(eq), [[C]](s64), [[MV]] |
| 162 | + ; RV32I-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[ICMP]](s1) |
| 163 | + ; RV32I-NEXT: $x10 = COPY [[ZEXT]](s32) |
| 164 | + ; RV32I-NEXT: PseudoRET implicit $x10 |
| 165 | + %1 = call i64 @callee_small_scalar_ret() |
| 166 | + %2 = icmp eq i64 987654321234567, %1 |
| 167 | + %3 = zext i1 %2 to i32 |
| 168 | + ret i32 %3 |
| 169 | +} |
| 170 | + |
| 171 | +; Check return of 2x xlen structs |
| 172 | + |
| 173 | +%struct.small = type { i32, ptr } |
| 174 | + |
| 175 | +define %struct.small @callee_small_struct_ret() nounwind { |
| 176 | + ; RV32I-LABEL: name: callee_small_struct_ret |
| 177 | + ; RV32I: bb.1 (%ir-block.0): |
| 178 | + ; RV32I-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 |
| 179 | + ; RV32I-NEXT: [[C1:%[0-9]+]]:_(p0) = G_CONSTANT i32 0 |
| 180 | + ; RV32I-NEXT: $x10 = COPY [[C]](s32) |
| 181 | + ; RV32I-NEXT: $x11 = COPY [[C1]](p0) |
| 182 | + ; RV32I-NEXT: PseudoRET implicit $x10, implicit $x11 |
| 183 | + ret %struct.small { i32 1, ptr null } |
| 184 | +} |
| 185 | + |
| 186 | +define i32 @caller_small_struct_ret() nounwind { |
| 187 | + ; RV32I-LABEL: name: caller_small_struct_ret |
| 188 | + ; RV32I: bb.1 (%ir-block.0): |
| 189 | + ; RV32I-NEXT: PseudoCALL target-flags(riscv-call) @callee_small_struct_ret, implicit-def $x1, implicit-def $x10, implicit-def $x11 |
| 190 | + ; RV32I-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $x10 |
| 191 | + ; RV32I-NEXT: [[COPY1:%[0-9]+]]:_(p0) = COPY $x11 |
| 192 | + ; RV32I-NEXT: [[PTRTOINT:%[0-9]+]]:_(s32) = G_PTRTOINT [[COPY1]](p0) |
| 193 | + ; RV32I-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[PTRTOINT]] |
| 194 | + ; RV32I-NEXT: $x10 = COPY [[ADD]](s32) |
| 195 | + ; RV32I-NEXT: PseudoRET implicit $x10 |
| 196 | + %1 = call %struct.small @callee_small_struct_ret() |
| 197 | + %2 = extractvalue %struct.small %1, 0 |
| 198 | + %3 = extractvalue %struct.small %1, 1 |
| 199 | + %4 = ptrtoint ptr %3 to i32 |
| 200 | + %5 = add i32 %2, %4 |
| 201 | + ret i32 %5 |
| 202 | +} |
| 203 | + |
| 204 | +; Check return of >2x xlen structs |
| 205 | + |
| 206 | +%struct.large = type { i32, i32, i32, i32 } |
| 207 | + |
| 208 | +define void @callee_large_struct_ret(ptr noalias sret(%struct.large) %agg.result) nounwind { |
| 209 | + ; RV32I-LABEL: name: callee_large_struct_ret |
| 210 | + ; RV32I: bb.1 (%ir-block.0): |
| 211 | + ; RV32I-NEXT: liveins: $x10 |
| 212 | + ; RV32I-NEXT: {{ $}} |
| 213 | + ; RV32I-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10 |
| 214 | + ; RV32I-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 |
| 215 | + ; RV32I-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 2 |
| 216 | + ; RV32I-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 3 |
| 217 | + ; RV32I-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 |
| 218 | + ; RV32I-NEXT: G_STORE [[C]](s32), [[COPY]](p0) :: (store (s32) into %ir.agg.result) |
| 219 | + ; RV32I-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 4 |
| 220 | + ; RV32I-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = nuw G_PTR_ADD [[COPY]], [[C4]](s32) |
| 221 | + ; RV32I-NEXT: G_STORE [[C1]](s32), [[PTR_ADD]](p0) :: (store (s32) into %ir.b) |
| 222 | + ; RV32I-NEXT: [[C5:%[0-9]+]]:_(s32) = G_CONSTANT i32 8 |
| 223 | + ; RV32I-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p0) = nuw G_PTR_ADD [[COPY]], [[C5]](s32) |
| 224 | + ; RV32I-NEXT: G_STORE [[C2]](s32), [[PTR_ADD1]](p0) :: (store (s32) into %ir.c) |
| 225 | + ; RV32I-NEXT: [[C6:%[0-9]+]]:_(s32) = G_CONSTANT i32 12 |
| 226 | + ; RV32I-NEXT: [[PTR_ADD2:%[0-9]+]]:_(p0) = nuw G_PTR_ADD [[COPY]], [[C6]](s32) |
| 227 | + ; RV32I-NEXT: G_STORE [[C3]](s32), [[PTR_ADD2]](p0) :: (store (s32) into %ir.d) |
| 228 | + ; RV32I-NEXT: PseudoRET |
| 229 | + store i32 1, ptr %agg.result, align 4 |
| 230 | + %b = getelementptr inbounds %struct.large, ptr %agg.result, i32 0, i32 1 |
| 231 | + store i32 2, ptr %b, align 4 |
| 232 | + %c = getelementptr inbounds %struct.large, ptr %agg.result, i32 0, i32 2 |
| 233 | + store i32 3, ptr %c, align 4 |
| 234 | + %d = getelementptr inbounds %struct.large, ptr %agg.result, i32 0, i32 3 |
| 235 | + store i32 4, ptr %d, align 4 |
| 236 | + ret void |
| 237 | +} |
| 238 | + |
| 239 | +define i32 @caller_large_struct_ret() nounwind { |
| 240 | + ; RV32I-LABEL: name: caller_large_struct_ret |
| 241 | + ; RV32I: bb.1 (%ir-block.0): |
| 242 | + ; RV32I-NEXT: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0 |
| 243 | + ; RV32I-NEXT: $x10 = COPY [[FRAME_INDEX]](p0) |
| 244 | + ; RV32I-NEXT: PseudoCALL target-flags(riscv-call) @callee_large_struct_ret, implicit-def $x1, implicit $x10 |
| 245 | + ; RV32I-NEXT: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[FRAME_INDEX]](p0) :: (dereferenceable load (s32) from %ir.1) |
| 246 | + ; RV32I-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 12 |
| 247 | + ; RV32I-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = nuw G_PTR_ADD [[FRAME_INDEX]], [[C]](s32) |
| 248 | + ; RV32I-NEXT: [[LOAD1:%[0-9]+]]:_(s32) = G_LOAD [[PTR_ADD]](p0) :: (dereferenceable load (s32) from %ir.3) |
| 249 | + ; RV32I-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[LOAD]], [[LOAD1]] |
| 250 | + ; RV32I-NEXT: $x10 = COPY [[ADD]](s32) |
| 251 | + ; RV32I-NEXT: PseudoRET implicit $x10 |
| 252 | + %1 = alloca %struct.large |
| 253 | + call void @callee_large_struct_ret(ptr sret(%struct.large) %1) |
| 254 | + %2 = load i32, ptr %1 |
| 255 | + %3 = getelementptr inbounds %struct.large, ptr %1, i32 0, i32 3 |
| 256 | + %4 = load i32, ptr %3 |
| 257 | + %5 = add i32 %2, %4 |
| 258 | + ret i32 %5 |
| 259 | +} |
0 commit comments