361 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 52; RUN: llc < %s -mtriple=arm64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-SD3; RUN: llc < %s -mtriple=arm64-linux-gnu -global-isel | FileCheck %s --check-prefixes=CHECK,CHECK-GI4 5%0 = type { i64, i64 }6 7define dso_local i128 @f0(ptr %p) nounwind readonly {8; CHECK-LABEL: f0:9; CHECK: // %bb.0: // %entry10; CHECK-NEXT: ldxp x0, x1, [x0]11; CHECK-NEXT: ret12entry:13 %ldrexd = tail call %0 @llvm.aarch64.ldxp(ptr %p)14 %0 = extractvalue %0 %ldrexd, 115 %1 = extractvalue %0 %ldrexd, 016 %2 = zext i64 %0 to i12817 %3 = zext i64 %1 to i12818 %shl = shl nuw i128 %2, 6419 %4 = or i128 %shl, %320 ret i128 %421}22 23define dso_local i32 @f1(ptr %ptr, i128 %val) nounwind {24; CHECK-LABEL: f1:25; CHECK: // %bb.0: // %entry26; CHECK-NEXT: stxp w8, x2, x3, [x0]27; CHECK-NEXT: mov w0, w828; CHECK-NEXT: ret29entry:30 %tmp4 = trunc i128 %val to i6431 %tmp6 = lshr i128 %val, 6432 %tmp7 = trunc i128 %tmp6 to i6433 %strexd = tail call i32 @llvm.aarch64.stxp(i64 %tmp4, i64 %tmp7, ptr %ptr)34 ret i32 %strexd35}36 37declare %0 @llvm.aarch64.ldxp(ptr) nounwind38declare i32 @llvm.aarch64.stxp(i64, i64, ptr) nounwind39 40@var = dso_local global i64 0, align 841 42define dso_local void @test_load_i8(ptr %addr) {43; CHECK-SD-LABEL: test_load_i8:44; CHECK-SD: // %bb.0:45; CHECK-SD-NEXT: ldxrb w8, [x0]46; CHECK-SD-NEXT: adrp x9, var47; CHECK-SD-NEXT: str x8, [x9, :lo12:var]48; CHECK-SD-NEXT: ret49;50; CHECK-GI-LABEL: test_load_i8:51; CHECK-GI: // %bb.0:52; CHECK-GI-NEXT: ldxrb w9, [x0]53; CHECK-GI-NEXT: adrp x8, var54; CHECK-GI-NEXT: and x9, x9, #0xff55; CHECK-GI-NEXT: str x9, [x8, :lo12:var]56; CHECK-GI-NEXT: ret57 58 %val = call i64 @llvm.aarch64.ldxr.p0(ptr elementtype(i8) %addr)59 %shortval = trunc i64 %val to i860 %extval = zext i8 %shortval to i6461 store i64 %extval, ptr @var, align 862 ret void63}64 65define dso_local void @test_load_i16(ptr %addr) {66; CHECK-SD-LABEL: test_load_i16:67; CHECK-SD: // %bb.0:68; CHECK-SD-NEXT: ldxrh w8, [x0]69; CHECK-SD-NEXT: adrp x9, var70; CHECK-SD-NEXT: str x8, [x9, :lo12:var]71; CHECK-SD-NEXT: ret72;73; CHECK-GI-LABEL: test_load_i16:74; CHECK-GI: // %bb.0:75; CHECK-GI-NEXT: ldxrh w9, [x0]76; CHECK-GI-NEXT: adrp x8, var77; CHECK-GI-NEXT: and x9, x9, #0xffff78; CHECK-GI-NEXT: str x9, [x8, :lo12:var]79; CHECK-GI-NEXT: ret80 81 %val = call i64 @llvm.aarch64.ldxr.p0(ptr elementtype(i16) %addr)82 %shortval = trunc i64 %val to i1683 %extval = zext i16 %shortval to i6484 store i64 %extval, ptr @var, align 885 ret void86}87 88define dso_local void @test_load_i32(ptr %addr) {89; CHECK-SD-LABEL: test_load_i32:90; CHECK-SD: // %bb.0:91; CHECK-SD-NEXT: ldxr w8, [x0]92; CHECK-SD-NEXT: adrp x9, var93; CHECK-SD-NEXT: str x8, [x9, :lo12:var]94; CHECK-SD-NEXT: ret95;96; CHECK-GI-LABEL: test_load_i32:97; CHECK-GI: // %bb.0:98; CHECK-GI-NEXT: ldxr w9, [x0]99; CHECK-GI-NEXT: adrp x8, var100; CHECK-GI-NEXT: mov w9, w9101; CHECK-GI-NEXT: str x9, [x8, :lo12:var]102; CHECK-GI-NEXT: ret103 104 %val = call i64 @llvm.aarch64.ldxr.p0(ptr elementtype(i32) %addr)105 %shortval = trunc i64 %val to i32106 %extval = zext i32 %shortval to i64107 store i64 %extval, ptr @var, align 8108 ret void109}110 111define dso_local void @test_load_i64(ptr %addr) {112; CHECK-LABEL: test_load_i64:113; CHECK: // %bb.0:114; CHECK-NEXT: ldxr x8, [x0]115; CHECK-NEXT: adrp x9, var116; CHECK-NEXT: str x8, [x9, :lo12:var]117; CHECK-NEXT: ret118 119 %val = call i64 @llvm.aarch64.ldxr.p0(ptr elementtype(i64) %addr)120 store i64 %val, ptr @var, align 8121 ret void122}123 124 125declare i64 @llvm.aarch64.ldxr.p0(ptr) nounwind126 127define dso_local i32 @test_store_i8(i32, i8 %val, ptr %addr) {128; CHECK-LABEL: test_store_i8:129; CHECK: // %bb.0:130; CHECK-NEXT: stxrb w0, w1, [x2]131; CHECK-NEXT: ret132 %extval = zext i8 %val to i64133 %res = call i32 @llvm.aarch64.stxr.p0(i64 %extval, ptr elementtype(i8) %addr)134 ret i32 %res135}136 137define dso_local i32 @test_store_i16(i32, i16 %val, ptr %addr) {138; CHECK-LABEL: test_store_i16:139; CHECK: // %bb.0:140; CHECK-NEXT: stxrh w0, w1, [x2]141; CHECK-NEXT: ret142 %extval = zext i16 %val to i64143 %res = call i32 @llvm.aarch64.stxr.p0(i64 %extval, ptr elementtype(i16) %addr)144 ret i32 %res145}146 147define dso_local i32 @test_store_i32(i32, i32 %val, ptr %addr) {148; CHECK-LABEL: test_store_i32:149; CHECK: // %bb.0:150; CHECK-NEXT: stxr w0, w1, [x2]151; CHECK-NEXT: ret152 %extval = zext i32 %val to i64153 %res = call i32 @llvm.aarch64.stxr.p0(i64 %extval, ptr elementtype(i32) %addr)154 ret i32 %res155}156 157define dso_local i32 @test_store_i64(i32, i64 %val, ptr %addr) {158; CHECK-LABEL: test_store_i64:159; CHECK: // %bb.0:160; CHECK-NEXT: stxr w0, x1, [x2]161; CHECK-NEXT: ret162 %res = call i32 @llvm.aarch64.stxr.p0(i64 %val, ptr elementtype(i64) %addr)163 ret i32 %res164}165 166declare i32 @llvm.aarch64.stxr.p0(i64, ptr) nounwind167 168define dso_local void @test_clear() {169; CHECK-LABEL: test_clear:170; CHECK: // %bb.0:171; CHECK-NEXT: clrex172; CHECK-NEXT: ret173 call void @llvm.aarch64.clrex()174 ret void175}176 177declare void @llvm.aarch64.clrex() nounwind178 179define dso_local i128 @test_load_acquire_i128(ptr %p) nounwind readonly {180; CHECK-LABEL: test_load_acquire_i128:181; CHECK: // %bb.0: // %entry182; CHECK-NEXT: ldaxp x0, x1, [x0]183; CHECK-NEXT: ret184entry:185 %ldrexd = tail call %0 @llvm.aarch64.ldaxp(ptr %p)186 %0 = extractvalue %0 %ldrexd, 1187 %1 = extractvalue %0 %ldrexd, 0188 %2 = zext i64 %0 to i128189 %3 = zext i64 %1 to i128190 %shl = shl nuw i128 %2, 64191 %4 = or i128 %shl, %3192 ret i128 %4193}194 195define dso_local i32 @test_store_release_i128(ptr %ptr, i128 %val) nounwind {196; CHECK-LABEL: test_store_release_i128:197; CHECK: // %bb.0: // %entry198; CHECK-NEXT: stlxp w8, x2, x3, [x0]199; CHECK-NEXT: mov w0, w8200; CHECK-NEXT: ret201entry:202 %tmp4 = trunc i128 %val to i64203 %tmp6 = lshr i128 %val, 64204 %tmp7 = trunc i128 %tmp6 to i64205 %strexd = tail call i32 @llvm.aarch64.stlxp(i64 %tmp4, i64 %tmp7, ptr %ptr)206 ret i32 %strexd207}208 209declare %0 @llvm.aarch64.ldaxp(ptr) nounwind210declare i32 @llvm.aarch64.stlxp(i64, i64, ptr) nounwind211 212define dso_local void @test_load_acquire_i8(ptr %addr) {213; CHECK-SD-LABEL: test_load_acquire_i8:214; CHECK-SD: // %bb.0:215; CHECK-SD-NEXT: ldaxrb w8, [x0]216; CHECK-SD-NEXT: adrp x9, var217; CHECK-SD-NEXT: str x8, [x9, :lo12:var]218; CHECK-SD-NEXT: ret219;220; CHECK-GI-LABEL: test_load_acquire_i8:221; CHECK-GI: // %bb.0:222; CHECK-GI-NEXT: ldaxrb w9, [x0]223; CHECK-GI-NEXT: adrp x8, var224; CHECK-GI-NEXT: and x9, x9, #0xff225; CHECK-GI-NEXT: str x9, [x8, :lo12:var]226; CHECK-GI-NEXT: ret227 228 %val = call i64 @llvm.aarch64.ldaxr.p0(ptr elementtype(i8) %addr)229 %shortval = trunc i64 %val to i8230 %extval = zext i8 %shortval to i64231 store i64 %extval, ptr @var, align 8232 ret void233}234 235define dso_local void @test_load_acquire_i16(ptr %addr) {236; CHECK-SD-LABEL: test_load_acquire_i16:237; CHECK-SD: // %bb.0:238; CHECK-SD-NEXT: ldaxrh w8, [x0]239; CHECK-SD-NEXT: adrp x9, var240; CHECK-SD-NEXT: str x8, [x9, :lo12:var]241; CHECK-SD-NEXT: ret242;243; CHECK-GI-LABEL: test_load_acquire_i16:244; CHECK-GI: // %bb.0:245; CHECK-GI-NEXT: ldaxrh w9, [x0]246; CHECK-GI-NEXT: adrp x8, var247; CHECK-GI-NEXT: and x9, x9, #0xffff248; CHECK-GI-NEXT: str x9, [x8, :lo12:var]249; CHECK-GI-NEXT: ret250 251 %val = call i64 @llvm.aarch64.ldaxr.p0(ptr elementtype(i16) %addr)252 %shortval = trunc i64 %val to i16253 %extval = zext i16 %shortval to i64254 store i64 %extval, ptr @var, align 8255 ret void256}257 258define dso_local void @test_load_acquire_i32(ptr %addr) {259; CHECK-SD-LABEL: test_load_acquire_i32:260; CHECK-SD: // %bb.0:261; CHECK-SD-NEXT: ldaxr w8, [x0]262; CHECK-SD-NEXT: adrp x9, var263; CHECK-SD-NEXT: str x8, [x9, :lo12:var]264; CHECK-SD-NEXT: ret265;266; CHECK-GI-LABEL: test_load_acquire_i32:267; CHECK-GI: // %bb.0:268; CHECK-GI-NEXT: ldaxr w9, [x0]269; CHECK-GI-NEXT: adrp x8, var270; CHECK-GI-NEXT: mov w9, w9271; CHECK-GI-NEXT: str x9, [x8, :lo12:var]272; CHECK-GI-NEXT: ret273 274 %val = call i64 @llvm.aarch64.ldaxr.p0(ptr elementtype(i32) %addr)275 %shortval = trunc i64 %val to i32276 %extval = zext i32 %shortval to i64277 store i64 %extval, ptr @var, align 8278 ret void279}280 281define dso_local void @test_load_acquire_i64(ptr %addr) {282; CHECK-LABEL: test_load_acquire_i64:283; CHECK: // %bb.0:284; CHECK-NEXT: ldaxr x8, [x0]285; CHECK-NEXT: adrp x9, var286; CHECK-NEXT: str x8, [x9, :lo12:var]287; CHECK-NEXT: ret288 289 %val = call i64 @llvm.aarch64.ldaxr.p0(ptr elementtype(i64) %addr)290 store i64 %val, ptr @var, align 8291 ret void292}293 294 295declare i64 @llvm.aarch64.ldaxr.p0(ptr) nounwind296 297define dso_local i32 @test_store_release_i8(i32, i8 %val, ptr %addr) {298; CHECK-LABEL: test_store_release_i8:299; CHECK: // %bb.0:300; CHECK-NEXT: stlxrb w0, w1, [x2]301; CHECK-NEXT: ret302 %extval = zext i8 %val to i64303 %res = call i32 @llvm.aarch64.stlxr.p0(i64 %extval, ptr elementtype(i8) %addr)304 ret i32 %res305}306 307define dso_local i32 @test_store_release_i16(i32, i16 %val, ptr %addr) {308; CHECK-LABEL: test_store_release_i16:309; CHECK: // %bb.0:310; CHECK-NEXT: stlxrh w0, w1, [x2]311; CHECK-NEXT: ret312 %extval = zext i16 %val to i64313 %res = call i32 @llvm.aarch64.stlxr.p0(i64 %extval, ptr elementtype(i16) %addr)314 ret i32 %res315}316 317define dso_local i32 @test_store_release_i32(i32, i32 %val, ptr %addr) {318; CHECK-LABEL: test_store_release_i32:319; CHECK: // %bb.0:320; CHECK-NEXT: stlxr w0, w1, [x2]321; CHECK-NEXT: ret322 %extval = zext i32 %val to i64323 %res = call i32 @llvm.aarch64.stlxr.p0(i64 %extval, ptr elementtype(i32) %addr)324 ret i32 %res325}326 327define dso_local i32 @test_store_release_i64(i32, i64 %val, ptr %addr) {328; CHECK-LABEL: test_store_release_i64:329; CHECK: // %bb.0:330; CHECK-NEXT: stlxr w0, x1, [x2]331; CHECK-NEXT: ret332 %res = call i32 @llvm.aarch64.stlxr.p0(i64 %val, ptr elementtype(i64) %addr)333 ret i32 %res334}335 336; The stxp result cannot be allocated to the same register as the inputs.337define dso_local i32 @test_stxp_undef(ptr %p, i64 %x) nounwind {338; CHECK-LABEL: test_stxp_undef:339; CHECK: // %bb.0:340; CHECK-NEXT: stxp w8, x9, x1, [x0]341; CHECK-NEXT: mov w0, w8342; CHECK-NEXT: ret343 %res = call i32 @llvm.aarch64.stxp(i64 undef, i64 %x, ptr %p)344 ret i32 %res345}346 347; Same as previous test, but using inline asm.348define dso_local i32 @test_stxp_undef_inline_asm(ptr %p, i64 %x) nounwind {349; CHECK-LABEL: test_stxp_undef_inline_asm:350; CHECK: // %bb.0:351; CHECK-NEXT: //APP352; CHECK-NEXT: stxp w8, x9, x1, [x0]353; CHECK-NEXT: //NO_APP354; CHECK-NEXT: mov w0, w8355; CHECK-NEXT: ret356 %res = call i32 asm sideeffect "stxp ${0:w}, ${2}, ${3}, [${1}]", "=&r,r,r,r,~{memory}"(ptr %p, i64 undef, i64 %x)357 ret i32 %res358}359 360declare i32 @llvm.aarch64.stlxr.p0(i64, ptr) nounwind361