1; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py 2; RUN: llc -mtriple=aarch64-darwin-ios13 -O0 -global-isel -stop-after=irtranslator -verify-machineinstrs -o - %s | FileCheck %s 3 4define void @asm_simple_memory_clobber() { 5 ; CHECK-LABEL: name: asm_simple_memory_clobber 6 ; CHECK: bb.1 (%ir-block.0): 7 ; CHECK-NEXT: INLINEASM &"", 25 /* sideeffect mayload maystore attdialect */, !0 8 ; CHECK-NEXT: INLINEASM &"", 1 /* sideeffect attdialect */, !0 9 ; CHECK-NEXT: RET_ReallyLR 10 call void asm sideeffect "", "~{memory}"(), !srcloc !0 11 call void asm sideeffect "", ""(), !srcloc !0 12 ret void 13} 14 15!0 = !{i32 70} 16 17define void @asm_simple_register_clobber() { 18 ; CHECK-LABEL: name: asm_simple_register_clobber 19 ; CHECK: bb.1 (%ir-block.0): 20 ; CHECK-NEXT: INLINEASM &"mov x0, 7", 1 /* sideeffect attdialect */, 12 /* clobber */, implicit-def early-clobber $x0, !0 21 ; CHECK-NEXT: RET_ReallyLR 22 call void asm sideeffect "mov x0, 7", "~{x0}"(), !srcloc !0 23 ret void 24} 25 26define i64 @asm_register_early_clobber() { 27 ; CHECK-LABEL: name: asm_register_early_clobber 28 ; CHECK: bb.1 (%ir-block.0): 29 ; CHECK-NEXT: INLINEASM &"mov $0, 7; mov $1, 7", 1 /* sideeffect attdialect */, {{[0-9]+}} /* regdef-ec:GPR64common */, def early-clobber %0, {{[0-9]+}} /* regdef-ec:GPR64common */, def early-clobber %1, !0 30 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY %0 31 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY %1 32 ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s64) = G_ADD [[COPY]], [[COPY1]] 33 ; CHECK-NEXT: $x0 = COPY [[ADD]](s64) 34 ; CHECK-NEXT: RET_ReallyLR implicit $x0 35 call { i64, i64 } asm sideeffect "mov $0, 7; mov $1, 7", "=&r,=&r"(), !srcloc !0 36 %asmresult = extractvalue { i64, i64 } %1, 0 37 %asmresult1 = extractvalue { i64, i64 } %1, 1 38 %add = add i64 %asmresult, %asmresult1 39 ret i64 %add 40} 41 42define i32 @test_specific_register_output() nounwind ssp { 43 ; CHECK-LABEL: name: test_specific_register_output 44 ; CHECK: bb.1.entry: 45 ; CHECK-NEXT: INLINEASM &"mov ${0:w}, 7", 0 /* attdialect */, 10 /* regdef */, implicit-def $w0 46 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0 47 ; CHECK-NEXT: $w0 = COPY [[COPY]](s32) 48 ; CHECK-NEXT: RET_ReallyLR implicit $w0 49entry: 50 %0 = tail call i32 asm "mov ${0:w}, 7", "={w0}"() nounwind 51 ret i32 %0 52} 53 54define i32 @test_single_register_output() nounwind ssp { 55 ; CHECK-LABEL: name: test_single_register_output 56 ; CHECK: bb.1.entry: 57 ; CHECK-NEXT: INLINEASM &"mov ${0:w}, 7", 0 /* attdialect */, {{[0-9]+}} /* regdef:GPR32common */, def %0 58 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY %0 59 ; CHECK-NEXT: $w0 = COPY [[COPY]](s32) 60 ; CHECK-NEXT: RET_ReallyLR implicit $w0 61entry: 62 %0 = tail call i32 asm "mov ${0:w}, 7", "=r"() nounwind 63 ret i32 %0 64} 65 66define i64 @test_single_register_output_s64() nounwind ssp { 67 ; CHECK-LABEL: name: test_single_register_output_s64 68 ; CHECK: bb.1.entry: 69 ; CHECK-NEXT: INLINEASM &"mov $0, 7", 0 /* attdialect */, {{[0-9]+}} /* regdef:GPR64common */, def %0 70 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY %0 71 ; CHECK-NEXT: $x0 = COPY [[COPY]](s64) 72 ; CHECK-NEXT: RET_ReallyLR implicit $x0 73entry: 74 %0 = tail call i64 asm "mov $0, 7", "=r"() nounwind 75 ret i64 %0 76} 77 78; Check support for returning several floats 79define float @test_multiple_register_outputs_same() #0 { 80 ; CHECK-LABEL: name: test_multiple_register_outputs_same 81 ; CHECK: bb.1 (%ir-block.0): 82 ; CHECK-NEXT: INLINEASM &"mov $0, #0; mov $1, #0", 0 /* attdialect */, {{[0-9]+}} /* regdef:GPR32common */, def %0, {{[0-9]+}} /* regdef:GPR32common */, def %1 83 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY %0 84 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY %1 85 ; CHECK-NEXT: [[FADD:%[0-9]+]]:_(s32) = G_FADD [[COPY]], [[COPY1]] 86 ; CHECK-NEXT: $s0 = COPY [[FADD]](s32) 87 ; CHECK-NEXT: RET_ReallyLR implicit $s0 88 %1 = call { float, float } asm "mov $0, #0; mov $1, #0", "=r,=r"() 89 %asmresult = extractvalue { float, float } %1, 0 90 %asmresult1 = extractvalue { float, float } %1, 1 91 %add = fadd float %asmresult, %asmresult1 92 ret float %add 93} 94 95; Check support for returning several floats 96define double @test_multiple_register_outputs_mixed() #0 { 97 ; CHECK-LABEL: name: test_multiple_register_outputs_mixed 98 ; CHECK: bb.1 (%ir-block.0): 99 ; CHECK-NEXT: INLINEASM &"mov $0, #0; mov $1, #0", 0 /* attdialect */, {{[0-9]+}} /* regdef:GPR32common */, def %0, {{[0-9]+}} /* regdef:FPR64 */, def %1 100 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY %0 101 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY %1 102 ; CHECK-NEXT: $d0 = COPY [[COPY1]](s64) 103 ; CHECK-NEXT: RET_ReallyLR implicit $d0 104 %1 = call { float, double } asm "mov $0, #0; mov $1, #0", "=r,=w"() 105 %asmresult = extractvalue { float, double } %1, 1 106 ret double %asmresult 107} 108 109define i32 @test_specific_register_output_trunc() nounwind ssp { 110 ; CHECK-LABEL: name: test_specific_register_output_trunc 111 ; CHECK: bb.1.entry: 112 ; CHECK-NEXT: INLINEASM &"mov ${0:w}, 7", 0 /* attdialect */, 10 /* regdef */, implicit-def $x0 113 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0 114 ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64) 115 ; CHECK-NEXT: $w0 = COPY [[TRUNC]](s32) 116 ; CHECK-NEXT: RET_ReallyLR implicit $w0 117entry: 118 %0 = tail call i32 asm "mov ${0:w}, 7", "={x0}"() nounwind 119 ret i32 %0 120} 121 122define zeroext i8 @test_register_output_trunc(ptr %src) nounwind { 123 ; CHECK-LABEL: name: test_register_output_trunc 124 ; CHECK: bb.1.entry: 125 ; CHECK-NEXT: liveins: $x0 126 ; CHECK-NEXT: {{ $}} 127 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0 128 ; CHECK-NEXT: INLINEASM &"mov ${0:w}, 32", 0 /* attdialect */, {{[0-9]+}} /* regdef:GPR32common */, def %1 129 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY %1 130 ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) 131 ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s8) 132 ; CHECK-NEXT: $w0 = COPY [[ZEXT]](s32) 133 ; CHECK-NEXT: RET_ReallyLR implicit $w0 134entry: 135 %0 = tail call i8 asm "mov ${0:w}, 32", "=r"() nounwind 136 ret i8 %0 137} 138 139define float @test_vector_output() nounwind { 140 ; CHECK-LABEL: name: test_vector_output 141 ; CHECK: bb.1 (%ir-block.0): 142 ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 143 ; CHECK-NEXT: INLINEASM &"fmov ${0}.2s, #1.0", 1 /* sideeffect attdialect */, 10 /* regdef */, implicit-def $d14 144 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $d14 145 ; CHECK-NEXT: [[EVEC:%[0-9]+]]:_(s32) = G_EXTRACT_VECTOR_ELT [[COPY]](<2 x s32>), [[C]](s64) 146 ; CHECK-NEXT: $s0 = COPY [[EVEC]](s32) 147 ; CHECK-NEXT: RET_ReallyLR implicit $s0 148 %1 = tail call <2 x float> asm sideeffect "fmov ${0}.2s, #1.0", "={v14}"() nounwind 149 %2 = extractelement <2 x float> %1, i32 0 150 ret float %2 151} 152 153define void @test_input_register_imm() { 154 ; CHECK-LABEL: name: test_input_register_imm 155 ; CHECK: bb.1 (%ir-block.0): 156 ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 42 157 ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr64common = COPY [[C]](s64) 158 ; CHECK-NEXT: INLINEASM &"mov x0, $0", 1 /* sideeffect attdialect */, {{[0-9]+}} /* reguse:GPR64common */, [[COPY]] 159 ; CHECK-NEXT: RET_ReallyLR 160 call void asm sideeffect "mov x0, $0", "r"(i64 42) 161 ret void 162} 163 164; Make sure that boolean immediates are properly (zero) extended. 165define i32 @test_boolean_imm_ext() { 166 ; CHECK-LABEL: name: test_boolean_imm_ext 167 ; CHECK: bb.1.entry: 168 ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1 169 ; CHECK-NEXT: INLINEASM &"#TEST 42 + ${0:c} - .\0A\09", 9 /* sideeffect mayload attdialect */, 13 /* imm */, 1 170 ; CHECK-NEXT: $w0 = COPY [[C]](s32) 171 ; CHECK-NEXT: RET_ReallyLR implicit $w0 172entry: 173 tail call void asm sideeffect "#TEST 42 + ${0:c} - .\0A\09", "i"(i1 true) 174 ret i32 1 175} 176 177define void @test_input_imm() { 178 ; CHECK-LABEL: name: test_input_imm 179 ; CHECK: bb.1 (%ir-block.0): 180 ; CHECK-NEXT: INLINEASM &"mov x0, $0", 9 /* sideeffect mayload attdialect */, 13 /* imm */, 42 181 ; CHECK-NEXT: RET_ReallyLR 182 call void asm sideeffect "mov x0, $0", "i"(i64 42) 183 ret void 184} 185 186define zeroext i8 @test_input_register(ptr %src) nounwind { 187 ; CHECK-LABEL: name: test_input_register 188 ; CHECK: bb.1.entry: 189 ; CHECK-NEXT: liveins: $x0 190 ; CHECK-NEXT: {{ $}} 191 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0 192 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr64common = COPY [[COPY]](p0) 193 ; CHECK-NEXT: INLINEASM &"ldtrb ${0:w}, [$1]", 0 /* attdialect */, {{[0-9]+}} /* regdef:GPR32common */, def %1, {{[0-9]+}} /* reguse:GPR64common */, [[COPY1]] 194 ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY %1 195 ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY2]](s32) 196 ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[TRUNC]](s8) 197 ; CHECK-NEXT: $w0 = COPY [[ZEXT]](s32) 198 ; CHECK-NEXT: RET_ReallyLR implicit $w0 199entry: 200 %0 = tail call i8 asm "ldtrb ${0:w}, [$1]", "=r,r"(ptr %src) nounwind 201 ret i8 %0 202} 203 204define i32 @test_memory_constraint(ptr %a) nounwind { 205 ; CHECK-LABEL: name: test_memory_constraint 206 ; CHECK: bb.1 (%ir-block.0): 207 ; CHECK-NEXT: liveins: $x0 208 ; CHECK-NEXT: {{ $}} 209 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0 210 ; CHECK-NEXT: INLINEASM &"ldr $0, $1", 8 /* mayload attdialect */, {{[0-9]+}} /* regdef:GPR32common */, def %1, 262158 /* mem:m */, [[COPY]](p0) 211 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY %1 212 ; CHECK-NEXT: $w0 = COPY [[COPY1]](s32) 213 ; CHECK-NEXT: RET_ReallyLR implicit $w0 214 %1 = tail call i32 asm "ldr $0, $1", "=r,*m"(ptr elementtype(i32) %a) 215 ret i32 %1 216} 217 218define i16 @test_anyext_input() { 219 ; CHECK-LABEL: name: test_anyext_input 220 ; CHECK: bb.1 (%ir-block.0): 221 ; CHECK-NEXT: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 1 222 ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[C]](s16) 223 ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr32common = COPY [[ANYEXT]](s32) 224 ; CHECK-NEXT: INLINEASM &"", 1 /* sideeffect attdialect */, {{[0-9]+}} /* regdef:GPR32common */, def %0, {{[0-9]+}} /* reguse:GPR32common */, [[COPY]] 225 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY %0 226 ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) 227 ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC]](s16) 228 ; CHECK-NEXT: $w0 = COPY [[ANYEXT1]](s32) 229 ; CHECK-NEXT: RET_ReallyLR implicit $w0 230 %1 = call i16 asm sideeffect "", "=r,r"(i16 1) 231 ret i16 %1 232} 233 234define i16 @test_anyext_input_with_matching_constraint() { 235 ; CHECK-LABEL: name: test_anyext_input_with_matching_constraint 236 ; CHECK: bb.1 (%ir-block.0): 237 ; CHECK-NEXT: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 1 238 ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[C]](s16) 239 ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr32common = COPY [[ANYEXT]](s32) 240 ; CHECK-NEXT: INLINEASM &"", 1 /* sideeffect attdialect */, {{[0-9]+}} /* regdef:GPR32common */, def %0, 2147483657 /* reguse tiedto:$0 */, [[COPY]](tied-def 3) 241 ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY %0 242 ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) 243 ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC]](s16) 244 ; CHECK-NEXT: $w0 = COPY [[ANYEXT1]](s32) 245 ; CHECK-NEXT: RET_ReallyLR implicit $w0 246 %1 = call i16 asm sideeffect "", "=r,0"(i16 1) 247 ret i16 %1 248} 249 250define i64 @test_input_with_matching_constraint_to_physical_register() { 251 ; CHECK-LABEL: name: test_input_with_matching_constraint_to_physical_register 252 ; CHECK: bb.1 (%ir-block.0): 253 ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0 254 ; CHECK-NEXT: INLINEASM &"", 0 /* attdialect */, 10 /* regdef */, implicit-def $x2, 2147483657 /* reguse tiedto:$0 */, [[C]](tied-def 3)(s64) 255 ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x2 256 ; CHECK-NEXT: $x0 = COPY [[COPY]](s64) 257 ; CHECK-NEXT: RET_ReallyLR implicit $x0 258 %1 = tail call i64 asm "", "={x2},0"(i64 0) 259 ret i64 %1 260} 261