| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py |
| ; RUN: llc -mtriple=riscv32 -mattr=+xtheadmempair -verify-machineinstrs < %s \ |
| ; RUN: | FileCheck %s -check-prefix=RV32XTHEADMEMPAIR |
| ; RUN: llc -mtriple=riscv64 -mattr=+xtheadmempair -verify-machineinstrs < %s \ |
| ; RUN: | FileCheck %s -check-prefix=RV64XTHEADMEMPAIR |
| |
| define i64 @lwd(i32* %a) { |
| ; RV32XTHEADMEMPAIR-LABEL: lwd: |
| ; RV32XTHEADMEMPAIR: # %bb.0: |
| ; RV32XTHEADMEMPAIR-NEXT: th.lwd a1, a2, (a0), 2, 3 |
| ; RV32XTHEADMEMPAIR-NEXT: srai a3, a1, 31 |
| ; RV32XTHEADMEMPAIR-NEXT: srai a4, a2, 31 |
| ; RV32XTHEADMEMPAIR-NEXT: add a0, a1, a2 |
| ; RV32XTHEADMEMPAIR-NEXT: sltu a1, a0, a1 |
| ; RV32XTHEADMEMPAIR-NEXT: add a3, a3, a4 |
| ; RV32XTHEADMEMPAIR-NEXT: add a1, a3, a1 |
| ; RV32XTHEADMEMPAIR-NEXT: ret |
| ; |
| ; RV64XTHEADMEMPAIR-LABEL: lwd: |
| ; RV64XTHEADMEMPAIR: # %bb.0: |
| ; RV64XTHEADMEMPAIR-NEXT: th.lwd a1, a2, (a0), 2, 3 |
| ; RV64XTHEADMEMPAIR-NEXT: add a0, a1, a2 |
| ; RV64XTHEADMEMPAIR-NEXT: ret |
| %1 = getelementptr i32, i32* %a, i64 4 |
| %2 = load i32, i32* %1, align 4 |
| %3 = getelementptr i32, i32* %a, i64 5 |
| %4 = load i32, i32* %3, align 4 |
| %5 = sext i32 %2 to i64 |
| %6 = sext i32 %4 to i64 |
| %7 = add i64 %5, %6 |
| ret i64 %7 |
| } |
| |
| define i64 @lwud(i32* %a) { |
| ; RV32XTHEADMEMPAIR-LABEL: lwud: |
| ; RV32XTHEADMEMPAIR: # %bb.0: |
| ; RV32XTHEADMEMPAIR-NEXT: th.lwd a1, a2, (a0), 2, 3 |
| ; RV32XTHEADMEMPAIR-NEXT: add a0, a1, a2 |
| ; RV32XTHEADMEMPAIR-NEXT: sltu a1, a0, a1 |
| ; RV32XTHEADMEMPAIR-NEXT: ret |
| ; |
| ; RV64XTHEADMEMPAIR-LABEL: lwud: |
| ; RV64XTHEADMEMPAIR: # %bb.0: |
| ; RV64XTHEADMEMPAIR-NEXT: th.lwud a1, a2, (a0), 2, 3 |
| ; RV64XTHEADMEMPAIR-NEXT: add a0, a1, a2 |
| ; RV64XTHEADMEMPAIR-NEXT: ret |
| %1 = getelementptr i32, i32* %a, i64 4 |
| %2 = load i32, i32* %1, align 4 |
| %3 = getelementptr i32, i32* %a, i64 5 |
| %4 = load i32, i32* %3, align 4 |
| %5 = zext i32 %2 to i64 |
| %6 = zext i32 %4 to i64 |
| %7 = add i64 %5, %6 |
| ret i64 %7 |
| } |
| |
| define i64 @ldd(i64* %a) { |
| ; RV32XTHEADMEMPAIR-LABEL: ldd: |
| ; RV32XTHEADMEMPAIR: # %bb.0: |
| ; RV32XTHEADMEMPAIR-NEXT: lw a1, 32(a0) |
| ; RV32XTHEADMEMPAIR-NEXT: lw a2, 36(a0) |
| ; RV32XTHEADMEMPAIR-NEXT: lw a3, 44(a0) |
| ; RV32XTHEADMEMPAIR-NEXT: lw a0, 40(a0) |
| ; RV32XTHEADMEMPAIR-NEXT: add a2, a2, a3 |
| ; RV32XTHEADMEMPAIR-NEXT: add a0, a1, a0 |
| ; RV32XTHEADMEMPAIR-NEXT: sltu a1, a0, a1 |
| ; RV32XTHEADMEMPAIR-NEXT: add a1, a2, a1 |
| ; RV32XTHEADMEMPAIR-NEXT: ret |
| ; |
| ; RV64XTHEADMEMPAIR-LABEL: ldd: |
| ; RV64XTHEADMEMPAIR: # %bb.0: |
| ; RV64XTHEADMEMPAIR-NEXT: th.ldd a1, a2, (a0), 2, 4 |
| ; RV64XTHEADMEMPAIR-NEXT: add a0, a1, a2 |
| ; RV64XTHEADMEMPAIR-NEXT: ret |
| %1 = getelementptr i64, i64* %a, i64 4 |
| %2 = load i64, i64* %1, align 8 |
| %3 = getelementptr i64, i64* %a, i64 5 |
| %4 = load i64, i64* %3, align 8 |
| %5 = add i64 %2, %4 |
| ret i64 %5 |
| } |
| |
| define i64 @lwd_0(i32* %a) { |
| ; RV32XTHEADMEMPAIR-LABEL: lwd_0: |
| ; RV32XTHEADMEMPAIR: # %bb.0: |
| ; RV32XTHEADMEMPAIR-NEXT: th.lwd a1, a2, (a0), 0, 3 |
| ; RV32XTHEADMEMPAIR-NEXT: srai a3, a1, 31 |
| ; RV32XTHEADMEMPAIR-NEXT: srai a4, a2, 31 |
| ; RV32XTHEADMEMPAIR-NEXT: add a0, a1, a2 |
| ; RV32XTHEADMEMPAIR-NEXT: sltu a1, a0, a1 |
| ; RV32XTHEADMEMPAIR-NEXT: add a3, a3, a4 |
| ; RV32XTHEADMEMPAIR-NEXT: add a1, a3, a1 |
| ; RV32XTHEADMEMPAIR-NEXT: ret |
| ; |
| ; RV64XTHEADMEMPAIR-LABEL: lwd_0: |
| ; RV64XTHEADMEMPAIR: # %bb.0: |
| ; RV64XTHEADMEMPAIR-NEXT: th.lwd a1, a2, (a0), 0, 3 |
| ; RV64XTHEADMEMPAIR-NEXT: add a0, a1, a2 |
| ; RV64XTHEADMEMPAIR-NEXT: ret |
| %1 = getelementptr i32, i32* %a, i64 0 |
| %2 = load i32, i32* %1, align 4 |
| %3 = getelementptr i32, i32* %a, i64 1 |
| %4 = load i32, i32* %3, align 4 |
| %5 = sext i32 %2 to i64 |
| %6 = sext i32 %4 to i64 |
| %7 = add i64 %5, %6 |
| ret i64 %7 |
| } |
| |
| define i64 @lwud_0(i32* %a) { |
| ; RV32XTHEADMEMPAIR-LABEL: lwud_0: |
| ; RV32XTHEADMEMPAIR: # %bb.0: |
| ; RV32XTHEADMEMPAIR-NEXT: th.lwd a1, a2, (a0), 0, 3 |
| ; RV32XTHEADMEMPAIR-NEXT: add a0, a1, a2 |
| ; RV32XTHEADMEMPAIR-NEXT: sltu a1, a0, a1 |
| ; RV32XTHEADMEMPAIR-NEXT: ret |
| ; |
| ; RV64XTHEADMEMPAIR-LABEL: lwud_0: |
| ; RV64XTHEADMEMPAIR: # %bb.0: |
| ; RV64XTHEADMEMPAIR-NEXT: th.lwud a1, a2, (a0), 0, 3 |
| ; RV64XTHEADMEMPAIR-NEXT: add a0, a1, a2 |
| ; RV64XTHEADMEMPAIR-NEXT: ret |
| %1 = getelementptr i32, i32* %a, i64 0 |
| %2 = load i32, i32* %1, align 4 |
| %3 = getelementptr i32, i32* %a, i64 1 |
| %4 = load i32, i32* %3, align 4 |
| %5 = zext i32 %2 to i64 |
| %6 = zext i32 %4 to i64 |
| %7 = add i64 %5, %6 |
| ret i64 %7 |
| } |
| |
| define i64 @ldd_0(i64* %a) { |
| ; RV32XTHEADMEMPAIR-LABEL: ldd_0: |
| ; RV32XTHEADMEMPAIR: # %bb.0: |
| ; RV32XTHEADMEMPAIR-NEXT: th.lwd a1, a2, (a0), 0, 3 |
| ; RV32XTHEADMEMPAIR-NEXT: th.lwd a3, a4, (a0), 1, 3 |
| ; RV32XTHEADMEMPAIR-NEXT: add a2, a2, a4 |
| ; RV32XTHEADMEMPAIR-NEXT: add a0, a1, a3 |
| ; RV32XTHEADMEMPAIR-NEXT: sltu a1, a0, a1 |
| ; RV32XTHEADMEMPAIR-NEXT: add a1, a2, a1 |
| ; RV32XTHEADMEMPAIR-NEXT: ret |
| ; |
| ; RV64XTHEADMEMPAIR-LABEL: ldd_0: |
| ; RV64XTHEADMEMPAIR: # %bb.0: |
| ; RV64XTHEADMEMPAIR-NEXT: th.ldd a1, a2, (a0), 0, 4 |
| ; RV64XTHEADMEMPAIR-NEXT: add a0, a1, a2 |
| ; RV64XTHEADMEMPAIR-NEXT: ret |
| %1 = getelementptr i64, i64* %a, i64 0 |
| %2 = load i64, i64* %1, align 8 |
| %3 = getelementptr i64, i64* %a, i64 1 |
| %4 = load i64, i64* %3, align 8 |
| %5 = add i64 %2, %4 |
| ret i64 %5 |
| } |
| |
| define void @swd(i32* %a, i32 %b, i32%c) { |
| ; RV32XTHEADMEMPAIR-LABEL: swd: |
| ; RV32XTHEADMEMPAIR: # %bb.0: |
| ; RV32XTHEADMEMPAIR-NEXT: th.swd a1, a2, (a0), 2, 3 |
| ; RV32XTHEADMEMPAIR-NEXT: ret |
| ; |
| ; RV64XTHEADMEMPAIR-LABEL: swd: |
| ; RV64XTHEADMEMPAIR: # %bb.0: |
| ; RV64XTHEADMEMPAIR-NEXT: th.swd a1, a2, (a0), 2, 3 |
| ; RV64XTHEADMEMPAIR-NEXT: ret |
| %1 = getelementptr i32, i32* %a, i64 4 |
| store i32 %b, i32* %1, align 4 |
| %2 = getelementptr i32, i32* %a, i64 5 |
| store i32 %c, i32* %2, align 4 |
| ret void |
| } |
| |
| define void @sdd(i64* %a, i64 %b, i64%c) { |
| ; RV32XTHEADMEMPAIR-LABEL: sdd: |
| ; RV32XTHEADMEMPAIR: # %bb.0: |
| ; RV32XTHEADMEMPAIR-NEXT: sw a2, 36(a0) |
| ; RV32XTHEADMEMPAIR-NEXT: sw a1, 32(a0) |
| ; RV32XTHEADMEMPAIR-NEXT: sw a4, 44(a0) |
| ; RV32XTHEADMEMPAIR-NEXT: sw a3, 40(a0) |
| ; RV32XTHEADMEMPAIR-NEXT: ret |
| ; |
| ; RV64XTHEADMEMPAIR-LABEL: sdd: |
| ; RV64XTHEADMEMPAIR: # %bb.0: |
| ; RV64XTHEADMEMPAIR-NEXT: th.sdd a1, a2, (a0), 2, 4 |
| ; RV64XTHEADMEMPAIR-NEXT: ret |
| %1 = getelementptr i64, i64* %a, i64 4 |
| store i64 %b, i64* %1, align 8 |
| %2 = getelementptr i64, i64* %a, i64 5 |
| store i64 %c, i64* %2, align 8 |
| ret void |
| } |
| |
| define void @swd_0(i32* %a, i32 %b, i32%c) { |
| ; RV32XTHEADMEMPAIR-LABEL: swd_0: |
| ; RV32XTHEADMEMPAIR: # %bb.0: |
| ; RV32XTHEADMEMPAIR-NEXT: th.swd a1, a2, (a0), 0, 3 |
| ; RV32XTHEADMEMPAIR-NEXT: ret |
| ; |
| ; RV64XTHEADMEMPAIR-LABEL: swd_0: |
| ; RV64XTHEADMEMPAIR: # %bb.0: |
| ; RV64XTHEADMEMPAIR-NEXT: th.swd a1, a2, (a0), 0, 3 |
| ; RV64XTHEADMEMPAIR-NEXT: ret |
| %1 = getelementptr i32, i32* %a, i64 0 |
| store i32 %b, i32* %1, align 4 |
| %2 = getelementptr i32, i32* %a, i64 1 |
| store i32 %c, i32* %2, align 4 |
| ret void |
| } |
| |
| define void @sdd_0(i64* %a, i64 %b, i64%c) { |
| ; RV32XTHEADMEMPAIR-LABEL: sdd_0: |
| ; RV32XTHEADMEMPAIR: # %bb.0: |
| ; RV32XTHEADMEMPAIR-NEXT: th.swd a1, a2, (a0), 0, 3 |
| ; RV32XTHEADMEMPAIR-NEXT: th.swd a3, a4, (a0), 1, 3 |
| ; RV32XTHEADMEMPAIR-NEXT: ret |
| ; |
| ; RV64XTHEADMEMPAIR-LABEL: sdd_0: |
| ; RV64XTHEADMEMPAIR: # %bb.0: |
| ; RV64XTHEADMEMPAIR-NEXT: th.sdd a1, a2, (a0), 0, 4 |
| ; RV64XTHEADMEMPAIR-NEXT: ret |
| %1 = getelementptr i64, i64* %a, i64 0 |
| store i64 %b, i64* %1, align 8 |
| %2 = getelementptr i64, i64* %a, i64 1 |
| store i64 %c, i64* %2, align 8 |
| ret void |
| } |
| |
| define i64 @ld64(i64* %a) { |
| ; RV32XTHEADMEMPAIR-LABEL: ld64: |
| ; RV32XTHEADMEMPAIR: # %bb.0: |
| ; RV32XTHEADMEMPAIR-NEXT: th.lwd a2, a1, (a0), 0, 3 |
| ; RV32XTHEADMEMPAIR-NEXT: mv a0, a2 |
| ; RV32XTHEADMEMPAIR-NEXT: ret |
| ; |
| ; RV64XTHEADMEMPAIR-LABEL: ld64: |
| ; RV64XTHEADMEMPAIR: # %bb.0: |
| ; RV64XTHEADMEMPAIR-NEXT: ld a0, 0(a0) |
| ; RV64XTHEADMEMPAIR-NEXT: ret |
| %1 = getelementptr i64, i64* %a, i64 0 |
| %2 = load i64, i64* %1, align 8 |
| ret i64 %2 |
| } |
| |
| define i128 @ld128(i128* %a) { |
| ; RV32XTHEADMEMPAIR-LABEL: ld128: |
| ; RV32XTHEADMEMPAIR: # %bb.0: |
| ; RV32XTHEADMEMPAIR-NEXT: th.lwd a2, a3, (a1), 1, 3 |
| ; RV32XTHEADMEMPAIR-NEXT: th.lwd a4, a5, (a1), 0, 3 |
| ; RV32XTHEADMEMPAIR-NEXT: th.swd a2, a3, (a0), 1, 3 |
| ; RV32XTHEADMEMPAIR-NEXT: th.swd a4, a5, (a0), 0, 3 |
| ; RV32XTHEADMEMPAIR-NEXT: ret |
| ; |
| ; RV64XTHEADMEMPAIR-LABEL: ld128: |
| ; RV64XTHEADMEMPAIR: # %bb.0: |
| ; RV64XTHEADMEMPAIR-NEXT: th.ldd a2, a1, (a0), 0, 4 |
| ; RV64XTHEADMEMPAIR-NEXT: mv a0, a2 |
| ; RV64XTHEADMEMPAIR-NEXT: ret |
| %1 = getelementptr i128, i128* %a, i64 0 |
| %2 = load i128, i128* %1, align 8 |
| ret i128 %2 |
| } |
| |
| define void @sd64(i64* %a, i64 %b) { |
| ; RV32XTHEADMEMPAIR-LABEL: sd64: |
| ; RV32XTHEADMEMPAIR: # %bb.0: |
| ; RV32XTHEADMEMPAIR-NEXT: th.swd a1, a2, (a0), 0, 3 |
| ; RV32XTHEADMEMPAIR-NEXT: ret |
| ; |
| ; RV64XTHEADMEMPAIR-LABEL: sd64: |
| ; RV64XTHEADMEMPAIR: # %bb.0: |
| ; RV64XTHEADMEMPAIR-NEXT: sd a1, 0(a0) |
| ; RV64XTHEADMEMPAIR-NEXT: ret |
| %1 = getelementptr i64, i64* %a, i64 0 |
| store i64 %b, i64* %1, align 8 |
| ret void |
| } |
| |
| define void @sd128(i128* %a, i128 %b) { |
| ; RV32XTHEADMEMPAIR-LABEL: sd128: |
| ; RV32XTHEADMEMPAIR: # %bb.0: |
| ; RV32XTHEADMEMPAIR-NEXT: th.lwd a2, a3, (a1), 1, 3 |
| ; RV32XTHEADMEMPAIR-NEXT: th.lwd a4, a5, (a1), 0, 3 |
| ; RV32XTHEADMEMPAIR-NEXT: th.swd a2, a3, (a0), 1, 3 |
| ; RV32XTHEADMEMPAIR-NEXT: th.swd a4, a5, (a0), 0, 3 |
| ; RV32XTHEADMEMPAIR-NEXT: ret |
| ; |
| ; RV64XTHEADMEMPAIR-LABEL: sd128: |
| ; RV64XTHEADMEMPAIR: # %bb.0: |
| ; RV64XTHEADMEMPAIR-NEXT: th.sdd a1, a2, (a0), 0, 4 |
| ; RV64XTHEADMEMPAIR-NEXT: ret |
| %1 = getelementptr i128, i128* %a, i64 0 |
| store i128 %b, i128* %1, align 8 |
| ret void |
| } |
| |
| define i32 @lh(i16* %a) { |
| ; RV32XTHEADMEMPAIR-LABEL: lh: |
| ; RV32XTHEADMEMPAIR: # %bb.0: |
| ; RV32XTHEADMEMPAIR-NEXT: lh a1, 0(a0) |
| ; RV32XTHEADMEMPAIR-NEXT: lh a0, 2(a0) |
| ; RV32XTHEADMEMPAIR-NEXT: add a0, a1, a0 |
| ; RV32XTHEADMEMPAIR-NEXT: ret |
| ; |
| ; RV64XTHEADMEMPAIR-LABEL: lh: |
| ; RV64XTHEADMEMPAIR: # %bb.0: |
| ; RV64XTHEADMEMPAIR-NEXT: lh a1, 0(a0) |
| ; RV64XTHEADMEMPAIR-NEXT: lh a0, 2(a0) |
| ; RV64XTHEADMEMPAIR-NEXT: add a0, a1, a0 |
| ; RV64XTHEADMEMPAIR-NEXT: ret |
| %1 = getelementptr i16, i16* %a, i64 0 |
| %2 = load i16, i16* %1, align 4 |
| %3 = getelementptr i16, i16* %a, i64 1 |
| %4 = load i16, i16* %3, align 4 |
| %5 = sext i16 %2 to i32 |
| %6 = sext i16 %4 to i32 |
| %7 = add i32 %5, %6 |
| ret i32 %7 |
| } |
| |
| define i32 @lb(i8* %a) { |
| ; RV32XTHEADMEMPAIR-LABEL: lb: |
| ; RV32XTHEADMEMPAIR: # %bb.0: |
| ; RV32XTHEADMEMPAIR-NEXT: lb a1, 0(a0) |
| ; RV32XTHEADMEMPAIR-NEXT: lb a0, 1(a0) |
| ; RV32XTHEADMEMPAIR-NEXT: add a0, a1, a0 |
| ; RV32XTHEADMEMPAIR-NEXT: ret |
| ; |
| ; RV64XTHEADMEMPAIR-LABEL: lb: |
| ; RV64XTHEADMEMPAIR: # %bb.0: |
| ; RV64XTHEADMEMPAIR-NEXT: lb a1, 0(a0) |
| ; RV64XTHEADMEMPAIR-NEXT: lb a0, 1(a0) |
| ; RV64XTHEADMEMPAIR-NEXT: add a0, a1, a0 |
| ; RV64XTHEADMEMPAIR-NEXT: ret |
| %1 = getelementptr i8, i8* %a, i64 0 |
| %2 = load i8, i8* %1, align 4 |
| %3 = getelementptr i8, i8* %a, i64 1 |
| %4 = load i8, i8* %3, align 4 |
| %5 = sext i8 %2 to i32 |
| %6 = sext i8 %4 to i32 |
| %7 = add i32 %5, %6 |
| ret i32 %7 |
| } |