1; RUN: llc < %s -mtriple=arm64-linux-gnu | FileCheck %s 2; RUN: llc < %s -global-isel -global-isel-abort=2 -pass-remarks-missed=gisel* -mtriple=arm64-linux-gnu 2>&1 | FileCheck %s --check-prefixes=GISEL,FALLBACK 3 4%0 = type { i64, i64 } 5 6define i128 @f0(i8* %p) nounwind readonly { 7; CHECK-LABEL: f0: 8; CHECK: ldxp {{x[0-9]+}}, {{x[0-9]+}}, [x0] 9entry: 10 %ldrexd = tail call %0 @llvm.aarch64.ldxp(i8* %p) 11 %0 = extractvalue %0 %ldrexd, 1 12 %1 = extractvalue %0 %ldrexd, 0 13 %2 = zext i64 %0 to i128 14 %3 = zext i64 %1 to i128 15 %shl = shl nuw i128 %2, 64 16 %4 = or i128 %shl, %3 17 ret i128 %4 18} 19 20define i32 @f1(i8* %ptr, i128 %val) nounwind { 21; CHECK-LABEL: f1: 22; CHECK: stxp {{w[0-9]+}}, {{x[0-9]+}}, {{x[0-9]+}}, [x0] 23entry: 24 %tmp4 = trunc i128 %val to i64 25 %tmp6 = lshr i128 %val, 64 26 %tmp7 = trunc i128 %tmp6 to i64 27 %strexd = tail call i32 @llvm.aarch64.stxp(i64 %tmp4, i64 %tmp7, i8* %ptr) 28 ret i32 %strexd 29} 30 31declare %0 @llvm.aarch64.ldxp(i8*) nounwind 32declare i32 @llvm.aarch64.stxp(i64, i64, i8*) nounwind 33 34@var = global i64 0, align 8 35 36; FALLBACK-NOT: remark:{{.*}}test_load_i8 37define void @test_load_i8(i8* %addr) { 38; CHECK-LABEL: test_load_i8: 39; CHECK: ldxrb w[[LOADVAL:[0-9]+]], [x0] 40; CHECK-NOT: uxtb 41; CHECK-NOT: and 42; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var] 43 44; GISEL-LABEL: test_load_i8: 45; GISEL: ldxrb w[[LOADVAL:[0-9]+]], [x0] 46; GISEL-NOT: uxtb 47; GISEL: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var] 48 %val = call i64 @llvm.aarch64.ldxr.p0i8(i8* %addr) 49 %shortval = trunc i64 %val to i8 50 %extval = zext i8 %shortval to i64 51 store i64 %extval, i64* @var, align 8 52 ret void 53} 54 55; FALLBACK-NOT: remark:{{.*}}test_load_i16 56define void @test_load_i16(i16* %addr) { 57; CHECK-LABEL: test_load_i16: 58; CHECK: ldxrh w[[LOADVAL:[0-9]+]], [x0] 59; CHECK-NOT: uxth 60; CHECK-NOT: and 61; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var] 62 63; GISEL-LABEL: test_load_i16: 64; GISEL: ldxrh w[[LOADVAL:[0-9]+]], [x0] 65; GISEL-NOT: uxtb 66; GISEL: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var] 67 %val = call i64 @llvm.aarch64.ldxr.p0i16(i16* %addr) 68 %shortval = trunc i64 %val to i16 69 %extval = zext i16 %shortval to i64 70 store i64 %extval, i64* @var, align 8 71 ret void 72} 73 74; FALLBACK-NOT: remark:{{.*}}test_load_i32 75define void @test_load_i32(i32* %addr) { 76; CHECK-LABEL: test_load_i32: 77; CHECK: ldxr w[[LOADVAL:[0-9]+]], [x0] 78; CHECK-NOT: uxtw 79; CHECK-NOT: and 80; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var] 81 82; GISEL-LABEL: test_load_i32: 83; GISEL: ldxr w[[LOADVAL:[0-9]+]], [x0] 84; GISEL-NOT: uxtb 85; GISEL: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var] 86 %val = call i64 @llvm.aarch64.ldxr.p0i32(i32* %addr) 87 %shortval = trunc i64 %val to i32 88 %extval = zext i32 %shortval to i64 89 store i64 %extval, i64* @var, align 8 90 ret void 91} 92 93; FALLBACK-NOT: remark:{{.*}}test_load_i64 94define void @test_load_i64(i64* %addr) { 95; CHECK-LABEL: test_load_i64: 96; CHECK: ldxr x[[LOADVAL:[0-9]+]], [x0] 97; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var] 98 99; GISEL-LABEL: test_load_i64: 100; GISEL: ldxr x[[LOADVAL:[0-9]+]], [x0] 101; GISEL-NOT: uxtb 102; GISEL: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var] 103 %val = call i64 @llvm.aarch64.ldxr.p0i64(i64* %addr) 104 store i64 %val, i64* @var, align 8 105 ret void 106} 107 108 109declare i64 @llvm.aarch64.ldxr.p0i8(i8*) nounwind 110declare i64 @llvm.aarch64.ldxr.p0i16(i16*) nounwind 111declare i64 @llvm.aarch64.ldxr.p0i32(i32*) nounwind 112declare i64 @llvm.aarch64.ldxr.p0i64(i64*) nounwind 113 114; FALLBACK-NOT: remark:{{.*}}test_store_i8 115define i32 @test_store_i8(i32, i8 %val, i8* %addr) { 116; CHECK-LABEL: test_store_i8: 117; CHECK-NOT: uxtb 118; CHECK-NOT: and 119; CHECK: stxrb w0, w1, [x2] 120; GISEL-LABEL: test_store_i8: 121; GISEL-NOT: uxtb 122; GISEL-NOT: and 123; GISEL: stxrb w0, w1, [x2] 124 %extval = zext i8 %val to i64 125 %res = call i32 @llvm.aarch64.stxr.p0i8(i64 %extval, i8* %addr) 126 ret i32 %res 127} 128 129; FALLBACK-NOT: remark:{{.*}}test_store_i16 130define i32 @test_store_i16(i32, i16 %val, i16* %addr) { 131; CHECK-LABEL: test_store_i16: 132; CHECK-NOT: uxth 133; CHECK-NOT: and 134; CHECK: stxrh w0, w1, [x2] 135; GISEL-LABEL: test_store_i16: 136; GISEL-NOT: uxth 137; GISEL-NOT: and 138; GISEL: stxrh w0, w1, [x2] 139 %extval = zext i16 %val to i64 140 %res = call i32 @llvm.aarch64.stxr.p0i16(i64 %extval, i16* %addr) 141 ret i32 %res 142} 143 144; FALLBACK-NOT: remark:{{.*}}test_store_i32 145define i32 @test_store_i32(i32, i32 %val, i32* %addr) { 146; CHECK-LABEL: test_store_i32: 147; CHECK-NOT: uxtw 148; CHECK-NOT: and 149; CHECK: stxr w0, w1, [x2] 150; GISEL-LABEL: test_store_i32: 151; GISEL-NOT: uxtw 152; GISEL-NOT: and 153; GISEL: stxr w0, w1, [x2] 154 %extval = zext i32 %val to i64 155 %res = call i32 @llvm.aarch64.stxr.p0i32(i64 %extval, i32* %addr) 156 ret i32 %res 157} 158 159; FALLBACK-NOT: remark:{{.*}}test_store_i64 160define i32 @test_store_i64(i32, i64 %val, i64* %addr) { 161; CHECK-LABEL: test_store_i64: 162; CHECK: stxr w0, x1, [x2] 163; GISEL-LABEL: test_store_i64: 164; GISEL: stxr w0, x1, [x2] 165 %res = call i32 @llvm.aarch64.stxr.p0i64(i64 %val, i64* %addr) 166 ret i32 %res 167} 168 169declare i32 @llvm.aarch64.stxr.p0i8(i64, i8*) nounwind 170declare i32 @llvm.aarch64.stxr.p0i16(i64, i16*) nounwind 171declare i32 @llvm.aarch64.stxr.p0i32(i64, i32*) nounwind 172declare i32 @llvm.aarch64.stxr.p0i64(i64, i64*) nounwind 173 174; CHECK: test_clear: 175; CHECK: clrex 176define void @test_clear() { 177 call void @llvm.aarch64.clrex() 178 ret void 179} 180 181declare void @llvm.aarch64.clrex() nounwind 182 183define i128 @test_load_acquire_i128(i8* %p) nounwind readonly { 184; CHECK-LABEL: test_load_acquire_i128: 185; CHECK: ldaxp {{x[0-9]+}}, {{x[0-9]+}}, [x0] 186entry: 187 %ldrexd = tail call %0 @llvm.aarch64.ldaxp(i8* %p) 188 %0 = extractvalue %0 %ldrexd, 1 189 %1 = extractvalue %0 %ldrexd, 0 190 %2 = zext i64 %0 to i128 191 %3 = zext i64 %1 to i128 192 %shl = shl nuw i128 %2, 64 193 %4 = or i128 %shl, %3 194 ret i128 %4 195} 196 197define i32 @test_store_release_i128(i8* %ptr, i128 %val) nounwind { 198; CHECK-LABEL: test_store_release_i128: 199; CHECK: stlxp {{w[0-9]+}}, {{x[0-9]+}}, {{x[0-9]+}}, [x0] 200entry: 201 %tmp4 = trunc i128 %val to i64 202 %tmp6 = lshr i128 %val, 64 203 %tmp7 = trunc i128 %tmp6 to i64 204 %strexd = tail call i32 @llvm.aarch64.stlxp(i64 %tmp4, i64 %tmp7, i8* %ptr) 205 ret i32 %strexd 206} 207 208declare %0 @llvm.aarch64.ldaxp(i8*) nounwind 209declare i32 @llvm.aarch64.stlxp(i64, i64, i8*) nounwind 210 211; FALLBACK-NOT: remark:{{.*}}test_load_acquire_i8 212define void @test_load_acquire_i8(i8* %addr) { 213; CHECK-LABEL: test_load_acquire_i8: 214; CHECK: ldaxrb w[[LOADVAL:[0-9]+]], [x0] 215; CHECK-NOT: uxtb 216; CHECK-NOT: and 217; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var] 218 219; GISEL-LABEL: test_load_acquire_i8: 220; GISEL: ldaxrb w[[LOADVAL:[0-9]+]], [x0] 221; GISEL-DAG: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var] 222 %val = call i64 @llvm.aarch64.ldaxr.p0i8(i8* %addr) 223 %shortval = trunc i64 %val to i8 224 %extval = zext i8 %shortval to i64 225 store i64 %extval, i64* @var, align 8 226 ret void 227} 228 229; FALLBACK-NOT: remark:{{.*}}test_load_acquire_i16 230define void @test_load_acquire_i16(i16* %addr) { 231; CHECK-LABEL: test_load_acquire_i16: 232; CHECK: ldaxrh w[[LOADVAL:[0-9]+]], [x0] 233; CHECK-NOT: uxth 234; CHECK-NOT: and 235; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var] 236 237; GISEL-LABEL: test_load_acquire_i16: 238; GISEL: ldaxrh w[[LOADVAL:[0-9]+]], [x0] 239; GISEL: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var] 240 %val = call i64 @llvm.aarch64.ldaxr.p0i16(i16* %addr) 241 %shortval = trunc i64 %val to i16 242 %extval = zext i16 %shortval to i64 243 store i64 %extval, i64* @var, align 8 244 ret void 245} 246 247; FALLBACK-NOT: remark:{{.*}}test_load_acquire_i32 248define void @test_load_acquire_i32(i32* %addr) { 249; CHECK-LABEL: test_load_acquire_i32: 250; CHECK: ldaxr w[[LOADVAL:[0-9]+]], [x0] 251; CHECK-NOT: uxtw 252; CHECK-NOT: and 253; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var] 254 255; GISEL-LABEL: test_load_acquire_i32: 256; GISEL: ldaxr w[[LOADVAL:[0-9]+]], [x0] 257; GISEL: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var] 258 %val = call i64 @llvm.aarch64.ldaxr.p0i32(i32* %addr) 259 %shortval = trunc i64 %val to i32 260 %extval = zext i32 %shortval to i64 261 store i64 %extval, i64* @var, align 8 262 ret void 263} 264 265; FALLBACK-NOT: remark:{{.*}}test_load_acquire_i64 266define void @test_load_acquire_i64(i64* %addr) { 267; CHECK-LABEL: test_load_acquire_i64: 268; CHECK: ldaxr x[[LOADVAL:[0-9]+]], [x0] 269; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var] 270 271; GISEL-LABEL: test_load_acquire_i64: 272; GISEL: ldaxr x[[LOADVAL:[0-9]+]], [x0] 273; GISEL: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var] 274 %val = call i64 @llvm.aarch64.ldaxr.p0i64(i64* %addr) 275 store i64 %val, i64* @var, align 8 276 ret void 277} 278 279 280declare i64 @llvm.aarch64.ldaxr.p0i8(i8*) nounwind 281declare i64 @llvm.aarch64.ldaxr.p0i16(i16*) nounwind 282declare i64 @llvm.aarch64.ldaxr.p0i32(i32*) nounwind 283declare i64 @llvm.aarch64.ldaxr.p0i64(i64*) nounwind 284 285; FALLBACK-NOT: remark:{{.*}}test_store_release_i8 286define i32 @test_store_release_i8(i32, i8 %val, i8* %addr) { 287; CHECK-LABEL: test_store_release_i8: 288; CHECK-NOT: uxtb 289; CHECK-NOT: and 290; CHECK: stlxrb w0, w1, [x2] 291; GISEL-LABEL: test_store_release_i8: 292; GISEL-NOT: uxtb 293; GISEL-NOT: and 294; GISEL: stlxrb w0, w1, [x2] 295 %extval = zext i8 %val to i64 296 %res = call i32 @llvm.aarch64.stlxr.p0i8(i64 %extval, i8* %addr) 297 ret i32 %res 298} 299 300; FALLBACK-NOT: remark:{{.*}}test_store_release_i16 301define i32 @test_store_release_i16(i32, i16 %val, i16* %addr) { 302; CHECK-LABEL: test_store_release_i16: 303; CHECK-NOT: uxth 304; CHECK-NOT: and 305; CHECK: stlxrh w0, w1, [x2] 306; GISEL-LABEL: test_store_release_i16: 307; GISEL-NOT: uxth 308; GISEL-NOT: and 309; GISEL: stlxrh w0, w1, [x2] 310 %extval = zext i16 %val to i64 311 %res = call i32 @llvm.aarch64.stlxr.p0i16(i64 %extval, i16* %addr) 312 ret i32 %res 313} 314 315; FALLBACK-NOT: remark:{{.*}}test_store_release_i32 316define i32 @test_store_release_i32(i32, i32 %val, i32* %addr) { 317; CHECK-LABEL: test_store_release_i32: 318; CHECK-NOT: uxtw 319; CHECK-NOT: and 320; CHECK: stlxr w0, w1, [x2] 321; GISEL-LABEL: test_store_release_i32: 322; GISEL-NOT: uxtw 323; GISEL-NOT: and 324; GISEL: stlxr w0, w1, [x2] 325 %extval = zext i32 %val to i64 326 %res = call i32 @llvm.aarch64.stlxr.p0i32(i64 %extval, i32* %addr) 327 ret i32 %res 328} 329 330; FALLBACK-NOT: remark:{{.*}}test_store_release_i64 331define i32 @test_store_release_i64(i32, i64 %val, i64* %addr) { 332; CHECK-LABEL: test_store_release_i64: 333; CHECK: stlxr w0, x1, [x2] 334; GISEL-LABEL: test_store_release_i64: 335; GISEL: stlxr w0, x1, [x2] 336 %res = call i32 @llvm.aarch64.stlxr.p0i64(i64 %val, i64* %addr) 337 ret i32 %res 338} 339 340declare i32 @llvm.aarch64.stlxr.p0i8(i64, i8*) nounwind 341declare i32 @llvm.aarch64.stlxr.p0i16(i64, i16*) nounwind 342declare i32 @llvm.aarch64.stlxr.p0i32(i64, i32*) nounwind 343declare i32 @llvm.aarch64.stlxr.p0i64(i64, i64*) nounwind 344