; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: sed 's/iXLen/i32/g' %s | llc -mtriple=riscv32 | FileCheck %s --check-prefixes=CHECK,RV32I
; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 | FileCheck %s --check-prefixes=CHECK,RV64I
; RUN: sed 's/iXLen/i32/g' %s | llc -mtriple=riscv32 -mattr=+zba | FileCheck %s --check-prefixes=ZBA,RV32ZBA
; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -mattr=+zba | FileCheck %s --check-prefixes=ZBA,RV64ZBA

define i64 @test_sh3add(ptr %p, iXLen %x, iXLen %y) {
; RV32I-LABEL: test_sh3add:
; RV32I:       # %bb.0: # %entry
; RV32I-NEXT:    slli a1, a1, 3
; RV32I-NEXT:    slli a2, a2, 3
; RV32I-NEXT:    add a1, a1, a0
; RV32I-NEXT:    add a0, a0, a2
; RV32I-NEXT:    lw a2, 480(a1)
; RV32I-NEXT:    lw a1, 484(a1)
; RV32I-NEXT:    lw a3, 404(a0)
; RV32I-NEXT:    lw a4, 400(a0)
; RV32I-NEXT:    add a1, a3, a1
; RV32I-NEXT:    add a0, a4, a2
; RV32I-NEXT:    sltu a2, a0, a4
; RV32I-NEXT:    add a1, a1, a2
; RV32I-NEXT:    ret
;
; RV64I-LABEL: test_sh3add:
; RV64I:       # %bb.0: # %entry
; RV64I-NEXT:    slli a1, a1, 3
; RV64I-NEXT:    slli a2, a2, 3
; RV64I-NEXT:    add a1, a1, a0
; RV64I-NEXT:    add a0, a0, a2
; RV64I-NEXT:    ld a1, 480(a1)
; RV64I-NEXT:    ld a0, 400(a0)
; RV64I-NEXT:    add a0, a0, a1
; RV64I-NEXT:    ret
;
; RV32ZBA-LABEL: test_sh3add:
; RV32ZBA:       # %bb.0: # %entry
; RV32ZBA-NEXT:    sh3add a1, a1, a0
; RV32ZBA-NEXT:    sh3add a0, a2, a0
; RV32ZBA-NEXT:    lw a2, 480(a1)
; RV32ZBA-NEXT:    lw a1, 484(a1)
; RV32ZBA-NEXT:    lw a3, 404(a0)
; RV32ZBA-NEXT:    lw a4, 400(a0)
; RV32ZBA-NEXT:    add a1, a3, a1
; RV32ZBA-NEXT:    add a0, a4, a2
; RV32ZBA-NEXT:    sltu a2, a0, a4
; RV32ZBA-NEXT:    add a1, a1, a2
; RV32ZBA-NEXT:    ret
;
; RV64ZBA-LABEL: test_sh3add:
; RV64ZBA:       # %bb.0: # %entry
; RV64ZBA-NEXT:    sh3add a1, a1, a0
; RV64ZBA-NEXT:    sh3add a0, a2, a0
; RV64ZBA-NEXT:    ld a1, 480(a1)
; RV64ZBA-NEXT:    ld a0, 400(a0)
; RV64ZBA-NEXT:    add a0, a0, a1
; RV64ZBA-NEXT:    ret
entry:
  %b = getelementptr inbounds nuw i8, ptr %p, i64 400
  %add = add iXLen %x, 10
  %arrayidx = getelementptr inbounds nuw [100 x i64], ptr %b, i64 0, iXLen %add
  %0 = load i64, ptr %arrayidx, align 8
  %arrayidx2 = getelementptr inbounds nuw [100 x i64], ptr %b, i64 0, iXLen %y
  %1 = load i64, ptr %arrayidx2, align 8
  %add3 = add nsw i64 %1, %0
  ret i64 %add3
}

define signext i32 @test_sh2add(ptr %p, iXLen %x, iXLen %y) {
; RV32I-LABEL: test_sh2add:
; RV32I:       # %bb.0: # %entry
; RV32I-NEXT:    slli a1, a1, 2
; RV32I-NEXT:    slli a2, a2, 2
; RV32I-NEXT:    add a1, a0, a1
; RV32I-NEXT:    add a0, a2, a0
; RV32I-NEXT:    lw a1, 1200(a1)
; RV32I-NEXT:    lw a0, 1240(a0)
; RV32I-NEXT:    add a0, a0, a1
; RV32I-NEXT:    ret
;
; RV64I-LABEL: test_sh2add:
; RV64I:       # %bb.0: # %entry
; RV64I-NEXT:    slli a1, a1, 2
; RV64I-NEXT:    slli a2, a2, 2
; RV64I-NEXT:    add a1, a0, a1
; RV64I-NEXT:    add a0, a2, a0
; RV64I-NEXT:    lw a1, 1200(a1)
; RV64I-NEXT:    lw a0, 1240(a0)
; RV64I-NEXT:    addw a0, a0, a1
; RV64I-NEXT:    ret
;
; RV32ZBA-LABEL: test_sh2add:
; RV32ZBA:       # %bb.0: # %entry
; RV32ZBA-NEXT:    sh2add a1, a1, a0
; RV32ZBA-NEXT:    sh2add a0, a2, a0
; RV32ZBA-NEXT:    lw a1, 1200(a1)
; RV32ZBA-NEXT:    lw a0, 1240(a0)
; RV32ZBA-NEXT:    add a0, a0, a1
; RV32ZBA-NEXT:    ret
;
; RV64ZBA-LABEL: test_sh2add:
; RV64ZBA:       # %bb.0: # %entry
; RV64ZBA-NEXT:    sh2add a1, a1, a0
; RV64ZBA-NEXT:    sh2add a0, a2, a0
; RV64ZBA-NEXT:    lw a1, 1200(a1)
; RV64ZBA-NEXT:    lw a0, 1240(a0)
; RV64ZBA-NEXT:    addw a0, a0, a1
; RV64ZBA-NEXT:    ret
entry:
  %c = getelementptr inbounds nuw i8, ptr %p, i64 1200
  %arrayidx = getelementptr inbounds nuw [100 x i32], ptr %c, i64 0, iXLen %x
  %0 = load i32, ptr %arrayidx, align 4
  %add = add iXLen %y, 10
  %arrayidx2 = getelementptr inbounds nuw [100 x i32], ptr %c, i64 0, iXLen %add
  %1 = load i32, ptr %arrayidx2, align 4
  %add3 = add nsw i32 %1, %0
  ret i32 %add3
}

define signext i16 @test_sh1add(ptr %p, iXLen %x, iXLen %y) {
; RV32I-LABEL: test_sh1add:
; RV32I:       # %bb.0: # %entry
; RV32I-NEXT:    slli a1, a1, 1
; RV32I-NEXT:    slli a2, a2, 1
; RV32I-NEXT:    add a1, a0, a1
; RV32I-NEXT:    add a0, a2, a0
; RV32I-NEXT:    lh a1, 1600(a1)
; RV32I-NEXT:    lh a0, 1620(a0)
; RV32I-NEXT:    add a0, a0, a1
; RV32I-NEXT:    slli a0, a0, 16
; RV32I-NEXT:    srai a0, a0, 16
; RV32I-NEXT:    ret
;
; RV64I-LABEL: test_sh1add:
; RV64I:       # %bb.0: # %entry
; RV64I-NEXT:    slli a1, a1, 1
; RV64I-NEXT:    slli a2, a2, 1
; RV64I-NEXT:    add a1, a0, a1
; RV64I-NEXT:    add a0, a2, a0
; RV64I-NEXT:    lh a1, 1600(a1)
; RV64I-NEXT:    lh a0, 1620(a0)
; RV64I-NEXT:    add a0, a0, a1
; RV64I-NEXT:    slli a0, a0, 48
; RV64I-NEXT:    srai a0, a0, 48
; RV64I-NEXT:    ret
;
; RV32ZBA-LABEL: test_sh1add:
; RV32ZBA:       # %bb.0: # %entry
; RV32ZBA-NEXT:    sh1add a1, a1, a0
; RV32ZBA-NEXT:    sh1add a0, a2, a0
; RV32ZBA-NEXT:    lh a1, 1600(a1)
; RV32ZBA-NEXT:    lh a0, 1620(a0)
; RV32ZBA-NEXT:    add a0, a0, a1
; RV32ZBA-NEXT:    slli a0, a0, 16
; RV32ZBA-NEXT:    srai a0, a0, 16
; RV32ZBA-NEXT:    ret
;
; RV64ZBA-LABEL: test_sh1add:
; RV64ZBA:       # %bb.0: # %entry
; RV64ZBA-NEXT:    sh1add a1, a1, a0
; RV64ZBA-NEXT:    sh1add a0, a2, a0
; RV64ZBA-NEXT:    lh a1, 1600(a1)
; RV64ZBA-NEXT:    lh a0, 1620(a0)
; RV64ZBA-NEXT:    add a0, a0, a1
; RV64ZBA-NEXT:    slli a0, a0, 48
; RV64ZBA-NEXT:    srai a0, a0, 48
; RV64ZBA-NEXT:    ret
entry:
  %d = getelementptr inbounds nuw i8, ptr %p, i64 1600
  %arrayidx = getelementptr inbounds nuw [100 x i16], ptr %d, i64 0, iXLen %x
  %0 = load i16, ptr %arrayidx, align 2
  %add = add iXLen %y, 10
  %arrayidx2 = getelementptr inbounds nuw [100 x i16], ptr %d, i64 0, iXLen %add
  %1 = load i16, ptr %arrayidx2, align 2
  %add4 = add i16 %1, %0
  ret i16 %add4
}

define zeroext i8 @test_add(ptr %p, iXLen %x, iXLen %y) {
; CHECK-LABEL: test_add:
; CHECK:       # %bb.0: # %entry
; CHECK-NEXT:    add a1, a0, a1
; CHECK-NEXT:    add a0, a2, a0
; CHECK-NEXT:    lbu a1, 1800(a1)
; CHECK-NEXT:    lbu a0, 1810(a0)
; CHECK-NEXT:    add a0, a0, a1
; CHECK-NEXT:    zext.b a0, a0
; CHECK-NEXT:    ret
;
; ZBA-LABEL: test_add:
; ZBA:       # %bb.0: # %entry
; ZBA-NEXT:    add a1, a0, a1
; ZBA-NEXT:    add a0, a2, a0
; ZBA-NEXT:    lbu a1, 1800(a1)
; ZBA-NEXT:    lbu a0, 1810(a0)
; ZBA-NEXT:    add a0, a0, a1
; ZBA-NEXT:    zext.b a0, a0
; ZBA-NEXT:    ret
entry:
  %e = getelementptr inbounds nuw i8, ptr %p, i64 1800
  %arrayidx = getelementptr inbounds nuw [1000 x i8], ptr %e, i64 0, iXLen %x
  %0 = load i8, ptr %arrayidx, align 1
  %add = add iXLen %y, 10
  %arrayidx2 = getelementptr inbounds nuw [1000 x i8], ptr %e, i64 0, iXLen %add
  %1 = load i8, ptr %arrayidx2, align 1
  %add4 = add i8 %1, %0
  ret i8 %add4
}

define i64 @test_sh3add_uw(ptr %p, i32 signext %x, i32 signext %y) {
; RV32I-LABEL: test_sh3add_uw:
; RV32I:       # %bb.0: # %entry
; RV32I-NEXT:    slli a1, a1, 3
; RV32I-NEXT:    slli a2, a2, 3
; RV32I-NEXT:    add a1, a0, a1
; RV32I-NEXT:    add a0, a0, a2
; RV32I-NEXT:    lw a2, 400(a1)
; RV32I-NEXT:    lw a1, 404(a1)
; RV32I-NEXT:    lw a3, 404(a0)
; RV32I-NEXT:    lw a4, 400(a0)
; RV32I-NEXT:    add a1, a3, a1
; RV32I-NEXT:    add a0, a4, a2
; RV32I-NEXT:    sltu a2, a0, a4
; RV32I-NEXT:    add a1, a1, a2
; RV32I-NEXT:    ret
;
; RV64I-LABEL: test_sh3add_uw:
; RV64I:       # %bb.0: # %entry
; RV64I-NEXT:    slli a1, a1, 32
; RV64I-NEXT:    slli a2, a2, 32
; RV64I-NEXT:    srli a1, a1, 29
; RV64I-NEXT:    srli a2, a2, 29
; RV64I-NEXT:    add a1, a0, a1
; RV64I-NEXT:    add a0, a0, a2
; RV64I-NEXT:    ld a1, 400(a1)
; RV64I-NEXT:    ld a0, 400(a0)
; RV64I-NEXT:    add a0, a0, a1
; RV64I-NEXT:    ret
;
; RV32ZBA-LABEL: test_sh3add_uw:
; RV32ZBA:       # %bb.0: # %entry
; RV32ZBA-NEXT:    sh3add a1, a1, a0
; RV32ZBA-NEXT:    sh3add a0, a2, a0
; RV32ZBA-NEXT:    lw a2, 400(a1)
; RV32ZBA-NEXT:    lw a1, 404(a1)
; RV32ZBA-NEXT:    lw a3, 404(a0)
; RV32ZBA-NEXT:    lw a4, 400(a0)
; RV32ZBA-NEXT:    add a1, a3, a1
; RV32ZBA-NEXT:    add a0, a4, a2
; RV32ZBA-NEXT:    sltu a2, a0, a4
; RV32ZBA-NEXT:    add a1, a1, a2
; RV32ZBA-NEXT:    ret
;
; RV64ZBA-LABEL: test_sh3add_uw:
; RV64ZBA:       # %bb.0: # %entry
; RV64ZBA-NEXT:    sh3add.uw a1, a1, a0
; RV64ZBA-NEXT:    sh3add.uw a0, a2, a0
; RV64ZBA-NEXT:    ld a1, 400(a1)
; RV64ZBA-NEXT:    ld a0, 400(a0)
; RV64ZBA-NEXT:    add a0, a0, a1
; RV64ZBA-NEXT:    ret
entry:
  %b = getelementptr inbounds nuw i8, ptr %p, i64 400
  %idxprom = zext i32 %x to i64
  %arrayidx = getelementptr inbounds nuw [100 x i64], ptr %b, i64 0, i64 %idxprom
  %0 = load i64, ptr %arrayidx, align 8
  %idxprom2 = zext i32 %y to i64
  %arrayidx3 = getelementptr inbounds nuw [100 x i64], ptr %b, i64 0, i64 %idxprom2
  %1 = load i64, ptr %arrayidx3, align 8
  %add4 = add nsw i64 %1, %0
  ret i64 %add4
}

define signext i32 @test_sh2add_uw(ptr %p, i32 signext %x, i32 signext %y) {
; RV32I-LABEL: test_sh2add_uw:
; RV32I:       # %bb.0: # %entry
; RV32I-NEXT:    slli a1, a1, 2
; RV32I-NEXT:    slli a2, a2, 2
; RV32I-NEXT:    add a1, a0, a1
; RV32I-NEXT:    add a0, a0, a2
; RV32I-NEXT:    lw a1, 1200(a1)
; RV32I-NEXT:    lw a0, 1200(a0)
; RV32I-NEXT:    add a0, a0, a1
; RV32I-NEXT:    ret
;
; RV64I-LABEL: test_sh2add_uw:
; RV64I:       # %bb.0: # %entry
; RV64I-NEXT:    slli a1, a1, 32
; RV64I-NEXT:    slli a2, a2, 32
; RV64I-NEXT:    srli a1, a1, 30
; RV64I-NEXT:    srli a2, a2, 30
; RV64I-NEXT:    add a1, a0, a1
; RV64I-NEXT:    add a0, a0, a2
; RV64I-NEXT:    lw a1, 1200(a1)
; RV64I-NEXT:    lw a0, 1200(a0)
; RV64I-NEXT:    addw a0, a0, a1
; RV64I-NEXT:    ret
;
; RV32ZBA-LABEL: test_sh2add_uw:
; RV32ZBA:       # %bb.0: # %entry
; RV32ZBA-NEXT:    sh2add a1, a1, a0
; RV32ZBA-NEXT:    sh2add a0, a2, a0
; RV32ZBA-NEXT:    lw a1, 1200(a1)
; RV32ZBA-NEXT:    lw a0, 1200(a0)
; RV32ZBA-NEXT:    add a0, a0, a1
; RV32ZBA-NEXT:    ret
;
; RV64ZBA-LABEL: test_sh2add_uw:
; RV64ZBA:       # %bb.0: # %entry
; RV64ZBA-NEXT:    sh2add.uw a1, a1, a0
; RV64ZBA-NEXT:    sh2add.uw a0, a2, a0
; RV64ZBA-NEXT:    lw a1, 1200(a1)
; RV64ZBA-NEXT:    lw a0, 1200(a0)
; RV64ZBA-NEXT:    addw a0, a0, a1
; RV64ZBA-NEXT:    ret
entry:
  %c = getelementptr inbounds nuw i8, ptr %p, i64 1200
  %idxprom = zext i32 %x to i64
  %arrayidx = getelementptr inbounds nuw [100 x i32], ptr %c, i64 0, i64 %idxprom
  %0 = load i32, ptr %arrayidx, align 4
  %idxprom2 = zext i32 %y to i64
  %arrayidx3 = getelementptr inbounds nuw [100 x i32], ptr %c, i64 0, i64 %idxprom2
  %1 = load i32, ptr %arrayidx3, align 4
  %add4 = add nsw i32 %1, %0
  ret i32 %add4
}

define signext i16 @test_sh1add_uw(ptr %p, i32 signext %x, i32 signext %y) {
; RV32I-LABEL: test_sh1add_uw:
; RV32I:       # %bb.0: # %entry
; RV32I-NEXT:    slli a1, a1, 1
; RV32I-NEXT:    slli a2, a2, 1
; RV32I-NEXT:    add a1, a0, a1
; RV32I-NEXT:    add a0, a2, a0
; RV32I-NEXT:    lh a1, 1600(a1)
; RV32I-NEXT:    lh a0, 1620(a0)
; RV32I-NEXT:    add a0, a0, a1
; RV32I-NEXT:    slli a0, a0, 16
; RV32I-NEXT:    srai a0, a0, 16
; RV32I-NEXT:    ret
;
; RV64I-LABEL: test_sh1add_uw:
; RV64I:       # %bb.0: # %entry
; RV64I-NEXT:    slli a1, a1, 32
; RV64I-NEXT:    addi a2, a2, 10
; RV64I-NEXT:    srli a1, a1, 31
; RV64I-NEXT:    slli a2, a2, 32
; RV64I-NEXT:    add a1, a0, a1
; RV64I-NEXT:    srli a2, a2, 31
; RV64I-NEXT:    add a0, a0, a2
; RV64I-NEXT:    lh a1, 1600(a1)
; RV64I-NEXT:    lh a0, 1600(a0)
; RV64I-NEXT:    add a0, a0, a1
; RV64I-NEXT:    slli a0, a0, 48
; RV64I-NEXT:    srai a0, a0, 48
; RV64I-NEXT:    ret
;
; RV32ZBA-LABEL: test_sh1add_uw:
; RV32ZBA:       # %bb.0: # %entry
; RV32ZBA-NEXT:    sh1add a1, a1, a0
; RV32ZBA-NEXT:    sh1add a0, a2, a0
; RV32ZBA-NEXT:    lh a1, 1600(a1)
; RV32ZBA-NEXT:    lh a0, 1620(a0)
; RV32ZBA-NEXT:    add a0, a0, a1
; RV32ZBA-NEXT:    slli a0, a0, 16
; RV32ZBA-NEXT:    srai a0, a0, 16
; RV32ZBA-NEXT:    ret
;
; RV64ZBA-LABEL: test_sh1add_uw:
; RV64ZBA:       # %bb.0: # %entry
; RV64ZBA-NEXT:    sh1add.uw a1, a1, a0
; RV64ZBA-NEXT:    addi a2, a2, 10
; RV64ZBA-NEXT:    sh1add.uw a0, a2, a0
; RV64ZBA-NEXT:    lh a1, 1600(a1)
; RV64ZBA-NEXT:    lh a0, 1600(a0)
; RV64ZBA-NEXT:    add a0, a0, a1
; RV64ZBA-NEXT:    slli a0, a0, 48
; RV64ZBA-NEXT:    srai a0, a0, 48
; RV64ZBA-NEXT:    ret
entry:
  %d = getelementptr inbounds nuw i8, ptr %p, i64 1600
  %idxprom = zext i32 %x to i64
  %arrayidx = getelementptr inbounds nuw [100 x i16], ptr %d, i64 0, i64 %idxprom
  %0 = load i16, ptr %arrayidx, align 2
  %add = add i32 %y, 10
  %idxprom2 = zext i32 %add to i64
  %arrayidx3 = getelementptr inbounds nuw [100 x i16], ptr %d, i64 0, i64 %idxprom2
  %1 = load i16, ptr %arrayidx3, align 2
  %add5 = add i16 %1, %0
  ret i16 %add5
}

define zeroext i8 @test_add_uw(ptr %p, i32 signext %x, i32 signext %y) {
; RV32I-LABEL: test_add_uw:
; RV32I:       # %bb.0: # %entry
; RV32I-NEXT:    add a1, a0, a1
; RV32I-NEXT:    add a0, a0, a2
; RV32I-NEXT:    lbu a1, 1800(a1)
; RV32I-NEXT:    lbu a0, 1800(a0)
; RV32I-NEXT:    add a0, a0, a1
; RV32I-NEXT:    zext.b a0, a0
; RV32I-NEXT:    ret
;
; RV64I-LABEL: test_add_uw:
; RV64I:       # %bb.0: # %entry
; RV64I-NEXT:    slli a1, a1, 32
; RV64I-NEXT:    slli a2, a2, 32
; RV64I-NEXT:    srli a1, a1, 32
; RV64I-NEXT:    srli a2, a2, 32
; RV64I-NEXT:    add a1, a0, a1
; RV64I-NEXT:    add a0, a0, a2
; RV64I-NEXT:    lbu a1, 1800(a1)
; RV64I-NEXT:    lbu a0, 1800(a0)
; RV64I-NEXT:    add a0, a0, a1
; RV64I-NEXT:    zext.b a0, a0
; RV64I-NEXT:    ret
;
; RV32ZBA-LABEL: test_add_uw:
; RV32ZBA:       # %bb.0: # %entry
; RV32ZBA-NEXT:    add a1, a0, a1
; RV32ZBA-NEXT:    add a0, a0, a2
; RV32ZBA-NEXT:    lbu a1, 1800(a1)
; RV32ZBA-NEXT:    lbu a0, 1800(a0)
; RV32ZBA-NEXT:    add a0, a0, a1
; RV32ZBA-NEXT:    zext.b a0, a0
; RV32ZBA-NEXT:    ret
;
; RV64ZBA-LABEL: test_add_uw:
; RV64ZBA:       # %bb.0: # %entry
; RV64ZBA-NEXT:    add.uw a1, a1, a0
; RV64ZBA-NEXT:    add.uw a0, a2, a0
; RV64ZBA-NEXT:    lbu a1, 1800(a1)
; RV64ZBA-NEXT:    lbu a0, 1800(a0)
; RV64ZBA-NEXT:    add a0, a0, a1
; RV64ZBA-NEXT:    zext.b a0, a0
; RV64ZBA-NEXT:    ret
entry:
  %e = getelementptr inbounds nuw i8, ptr %p, i64 1800
  %idxprom = zext i32 %x to i64
  %arrayidx = getelementptr inbounds nuw [1000 x i8], ptr %e, i64 0, i64 %idxprom
  %0 = load i8, ptr %arrayidx, align 1
  %idxprom2 = zext i32 %y to i64
  %arrayidx3 = getelementptr inbounds nuw [1000 x i8], ptr %e, i64 0, i64 %idxprom2
  %1 = load i8, ptr %arrayidx3, align 1
  %add5 = add i8 %1, %0
  ret i8 %add5
}

; The addi is part of the index and used with 2 different scales.
define signext i32 @test_scaled_index_addi(ptr %p, iXLen  %x) {
; RV32I-LABEL: test_scaled_index_addi:
; RV32I:       # %bb.0: # %entry
; RV32I-NEXT:    slli a2, a1, 2
; RV32I-NEXT:    slli a1, a1, 1
; RV32I-NEXT:    add a2, a0, a2
; RV32I-NEXT:    add a0, a0, a1
; RV32I-NEXT:    lw a1, 1196(a2)
; RV32I-NEXT:    lh a0, 1598(a0)
; RV32I-NEXT:    add a0, a1, a0
; RV32I-NEXT:    ret
;
; RV64I-LABEL: test_scaled_index_addi:
; RV64I:       # %bb.0: # %entry
; RV64I-NEXT:    slli a2, a1, 2
; RV64I-NEXT:    slli a1, a1, 1
; RV64I-NEXT:    add a2, a0, a2
; RV64I-NEXT:    add a0, a0, a1
; RV64I-NEXT:    lw a1, 1196(a2)
; RV64I-NEXT:    lh a0, 1598(a0)
; RV64I-NEXT:    addw a0, a1, a0
; RV64I-NEXT:    ret
;
; RV32ZBA-LABEL: test_scaled_index_addi:
; RV32ZBA:       # %bb.0: # %entry
; RV32ZBA-NEXT:    sh2add a2, a1, a0
; RV32ZBA-NEXT:    sh1add a0, a1, a0
; RV32ZBA-NEXT:    lw a1, 1196(a2)
; RV32ZBA-NEXT:    lh a0, 1598(a0)
; RV32ZBA-NEXT:    add a0, a1, a0
; RV32ZBA-NEXT:    ret
;
; RV64ZBA-LABEL: test_scaled_index_addi:
; RV64ZBA:       # %bb.0: # %entry
; RV64ZBA-NEXT:    sh2add a2, a1, a0
; RV64ZBA-NEXT:    sh1add a0, a1, a0
; RV64ZBA-NEXT:    lw a1, 1196(a2)
; RV64ZBA-NEXT:    lh a0, 1598(a0)
; RV64ZBA-NEXT:    addw a0, a1, a0
; RV64ZBA-NEXT:    ret
entry:
  %c = getelementptr inbounds nuw i8, ptr %p, i64 1200
  %sub = add iXLen %x, -1
  %arrayidx = getelementptr inbounds nuw [100 x i32], ptr %c, i64 0, iXLen %sub
  %0 = load i32, ptr %arrayidx, align 4
  %d = getelementptr inbounds nuw i8, ptr %p, i64 1600
  %arrayidx2 = getelementptr inbounds nuw [100 x i16], ptr %d, i64 0, iXLen %sub
  %1 = load i16, ptr %arrayidx2, align 2
  %conv = sext i16 %1 to i32
  %add = add nsw i32 %0, %conv
  ret i32 %add
}

; Offset is a pair of addis. We can fold one of them.
define signext i32 @test_medium_offset(ptr %p, iXLen %x, iXLen %y) {
; RV32I-LABEL: test_medium_offset:
; RV32I:       # %bb.0: # %entry
; RV32I-NEXT:    addi a0, a0, 2047
; RV32I-NEXT:    slli a1, a1, 2
; RV32I-NEXT:    slli a2, a2, 2
; RV32I-NEXT:    add a1, a0, a1
; RV32I-NEXT:    add a0, a2, a0
; RV32I-NEXT:    lw a1, 753(a1)
; RV32I-NEXT:    lw a0, 793(a0)
; RV32I-NEXT:    add a0, a0, a1
; RV32I-NEXT:    ret
;
; RV64I-LABEL: test_medium_offset:
; RV64I:       # %bb.0: # %entry
; RV64I-NEXT:    addi a0, a0, 2047
; RV64I-NEXT:    slli a1, a1, 2
; RV64I-NEXT:    slli a2, a2, 2
; RV64I-NEXT:    add a1, a0, a1
; RV64I-NEXT:    add a0, a2, a0
; RV64I-NEXT:    lw a1, 753(a1)
; RV64I-NEXT:    lw a0, 793(a0)
; RV64I-NEXT:    addw a0, a0, a1
; RV64I-NEXT:    ret
;
; RV32ZBA-LABEL: test_medium_offset:
; RV32ZBA:       # %bb.0: # %entry
; RV32ZBA-NEXT:    addi a0, a0, 2047
; RV32ZBA-NEXT:    sh2add a1, a1, a0
; RV32ZBA-NEXT:    sh2add a0, a2, a0
; RV32ZBA-NEXT:    lw a1, 753(a1)
; RV32ZBA-NEXT:    lw a0, 793(a0)
; RV32ZBA-NEXT:    add a0, a0, a1
; RV32ZBA-NEXT:    ret
;
; RV64ZBA-LABEL: test_medium_offset:
; RV64ZBA:       # %bb.0: # %entry
; RV64ZBA-NEXT:    addi a0, a0, 2047
; RV64ZBA-NEXT:    sh2add a1, a1, a0
; RV64ZBA-NEXT:    sh2add a0, a2, a0
; RV64ZBA-NEXT:    lw a1, 753(a1)
; RV64ZBA-NEXT:    lw a0, 793(a0)
; RV64ZBA-NEXT:    addw a0, a0, a1
; RV64ZBA-NEXT:    ret
entry:
  %f = getelementptr inbounds nuw i8, ptr %p, i64 2800
  %arrayidx = getelementptr inbounds nuw [1000 x i32], ptr %f, i64 0, iXLen %x
  %0 = load i32, ptr %arrayidx, align 4
  %add = add iXLen %y, 10
  %arrayidx2 = getelementptr inbounds nuw [1000 x i32], ptr %f, i64 0, iXLen %add
  %1 = load i32, ptr %arrayidx2, align 4
  %add3 = add nsw i32 %1, %0
  ret i32 %add3
}

; Offset is a lui+addiw. We can't fold this on RV64.
define signext i32 @test_large_offset(ptr %p, iXLen %x, iXLen %y) {
; RV32I-LABEL: test_large_offset:
; RV32I:       # %bb.0: # %entry
; RV32I-NEXT:    lui a3, 2
; RV32I-NEXT:    slli a1, a1, 2
; RV32I-NEXT:    slli a2, a2, 2
; RV32I-NEXT:    add a0, a0, a3
; RV32I-NEXT:    add a1, a0, a1
; RV32I-NEXT:    add a0, a2, a0
; RV32I-NEXT:    lw a1, -1392(a1)
; RV32I-NEXT:    lw a0, -1352(a0)
; RV32I-NEXT:    add a0, a0, a1
; RV32I-NEXT:    ret
;
; RV64I-LABEL: test_large_offset:
; RV64I:       # %bb.0: # %entry
; RV64I-NEXT:    lui a3, 2
; RV64I-NEXT:    slli a1, a1, 2
; RV64I-NEXT:    slli a2, a2, 2
; RV64I-NEXT:    add a0, a0, a3
; RV64I-NEXT:    add a1, a0, a1
; RV64I-NEXT:    add a0, a2, a0
; RV64I-NEXT:    lw a1, -1392(a1)
; RV64I-NEXT:    lw a0, -1352(a0)
; RV64I-NEXT:    addw a0, a0, a1
; RV64I-NEXT:    ret
;
; RV32ZBA-LABEL: test_large_offset:
; RV32ZBA:       # %bb.0: # %entry
; RV32ZBA-NEXT:    li a3, 1700
; RV32ZBA-NEXT:    sh2add a0, a3, a0
; RV32ZBA-NEXT:    sh2add a1, a1, a0
; RV32ZBA-NEXT:    sh2add a0, a2, a0
; RV32ZBA-NEXT:    lw a1, 0(a1)
; RV32ZBA-NEXT:    lw a0, 40(a0)
; RV32ZBA-NEXT:    add a0, a0, a1
; RV32ZBA-NEXT:    ret
;
; RV64ZBA-LABEL: test_large_offset:
; RV64ZBA:       # %bb.0: # %entry
; RV64ZBA-NEXT:    li a3, 1700
; RV64ZBA-NEXT:    sh2add a0, a3, a0
; RV64ZBA-NEXT:    sh2add a1, a1, a0
; RV64ZBA-NEXT:    sh2add a0, a2, a0
; RV64ZBA-NEXT:    lw a1, 0(a1)
; RV64ZBA-NEXT:    lw a0, 40(a0)
; RV64ZBA-NEXT:    addw a0, a0, a1
; RV64ZBA-NEXT:    ret
entry:
  %g = getelementptr inbounds nuw i8, ptr %p, i64 6800
  %arrayidx = getelementptr inbounds nuw [200 x i32], ptr %g, i64 0, iXLen %x
  %0 = load i32, ptr %arrayidx, align 4
  %add = add iXLen %y, 10
  %arrayidx2 = getelementptr inbounds nuw [200 x i32], ptr %g, i64 0, iXLen %add
  %1 = load i32, ptr %arrayidx2, align 4
  %add3 = add nsw i32 %1, %0
  ret i32 %add3
}

; After folding we can CSE the sh2add
define signext i32 @test_cse(ptr %p, iXLen %x) {
; RV32I-LABEL: test_cse:
; RV32I:       # %bb.0: # %entry
; RV32I-NEXT:    slli a1, a1, 2
; RV32I-NEXT:    add a0, a0, a1
; RV32I-NEXT:    lw a1, 1200(a0)
; RV32I-NEXT:    addi a0, a0, 2047
; RV32I-NEXT:    lw a0, 753(a0)
; RV32I-NEXT:    add a0, a0, a1
; RV32I-NEXT:    ret
;
; RV64I-LABEL: test_cse:
; RV64I:       # %bb.0: # %entry
; RV64I-NEXT:    slli a1, a1, 2
; RV64I-NEXT:    add a0, a0, a1
; RV64I-NEXT:    lw a1, 1200(a0)
; RV64I-NEXT:    addi a0, a0, 2047
; RV64I-NEXT:    lw a0, 753(a0)
; RV64I-NEXT:    addw a0, a0, a1
; RV64I-NEXT:    ret
;
; RV32ZBA-LABEL: test_cse:
; RV32ZBA:       # %bb.0: # %entry
; RV32ZBA-NEXT:    sh2add a0, a1, a0
; RV32ZBA-NEXT:    lw a1, 1200(a0)
; RV32ZBA-NEXT:    addi a0, a0, 2047
; RV32ZBA-NEXT:    lw a0, 753(a0)
; RV32ZBA-NEXT:    add a0, a0, a1
; RV32ZBA-NEXT:    ret
;
; RV64ZBA-LABEL: test_cse:
; RV64ZBA:       # %bb.0: # %entry
; RV64ZBA-NEXT:    sh2add a0, a1, a0
; RV64ZBA-NEXT:    lw a1, 1200(a0)
; RV64ZBA-NEXT:    addi a0, a0, 2047
; RV64ZBA-NEXT:    lw a0, 753(a0)
; RV64ZBA-NEXT:    addw a0, a0, a1
; RV64ZBA-NEXT:    ret
entry:
  %c = getelementptr inbounds nuw i8, ptr %p, i64 1200
  %arrayidx = getelementptr inbounds nuw [100 x i32], ptr %c, i64 0, iXLen %x
  %0 = load i32, ptr %arrayidx, align 4
  %f = getelementptr inbounds nuw i8, ptr %p, i64 2800
  %arrayidx1 = getelementptr inbounds nuw [1000 x i32], ptr %f, i64 0, iXLen %x
  %1 = load i32, ptr %arrayidx1, align 4
  %add = add nsw i32 %1, %0
  ret i32 %add
}

define zeroext i8 @test_optsize(ptr %p, iXLen %x, iXLen %y) optsize {
; CHECK-LABEL: test_optsize:
; CHECK:       # %bb.0: # %entry
; CHECK-NEXT:    addi a0, a0, 1800
; CHECK-NEXT:    add a1, a0, a1
; CHECK-NEXT:    add a0, a2, a0
; CHECK-NEXT:    lbu a1, 0(a1)
; CHECK-NEXT:    lbu a0, 10(a0)
; CHECK-NEXT:    add a0, a0, a1
; CHECK-NEXT:    zext.b a0, a0
; CHECK-NEXT:    ret
;
; ZBA-LABEL: test_optsize:
; ZBA:       # %bb.0: # %entry
; ZBA-NEXT:    addi a0, a0, 1800
; ZBA-NEXT:    add a1, a0, a1
; ZBA-NEXT:    add a0, a2, a0
; ZBA-NEXT:    lbu a1, 0(a1)
; ZBA-NEXT:    lbu a0, 10(a0)
; ZBA-NEXT:    add a0, a0, a1
; ZBA-NEXT:    zext.b a0, a0
; ZBA-NEXT:    ret
entry:
  %e = getelementptr inbounds nuw i8, ptr %p, i64 1800
  %arrayidx = getelementptr inbounds nuw [1000 x i8], ptr %e, i64 0, iXLen %x
  %0 = load i8, ptr %arrayidx, align 1
  %add = add iXLen %y, 10
  %arrayidx2 = getelementptr inbounds nuw [1000 x i8], ptr %e, i64 0, iXLen %add
  %1 = load i8, ptr %arrayidx2, align 1
  %add4 = add i8 %1, %0
  ret i8 %add4
}

define zeroext i8 @test_minsize(ptr %p, iXLen %x, iXLen %y) minsize {
; CHECK-LABEL: test_minsize:
; CHECK:       # %bb.0: # %entry
; CHECK-NEXT:    addi a0, a0, 1800
; CHECK-NEXT:    add a1, a0, a1
; CHECK-NEXT:    add a0, a2, a0
; CHECK-NEXT:    lbu a1, 0(a1)
; CHECK-NEXT:    lbu a0, 10(a0)
; CHECK-NEXT:    add a0, a0, a1
; CHECK-NEXT:    zext.b a0, a0
; CHECK-NEXT:    ret
;
; ZBA-LABEL: test_minsize:
; ZBA:       # %bb.0: # %entry
; ZBA-NEXT:    addi a0, a0, 1800
; ZBA-NEXT:    add a1, a0, a1
; ZBA-NEXT:    add a0, a2, a0
; ZBA-NEXT:    lbu a1, 0(a1)
; ZBA-NEXT:    lbu a0, 10(a0)
; ZBA-NEXT:    add a0, a0, a1
; ZBA-NEXT:    zext.b a0, a0
; ZBA-NEXT:    ret
entry:
  %e = getelementptr inbounds nuw i8, ptr %p, i64 1800
  %arrayidx = getelementptr inbounds nuw [1000 x i8], ptr %e, i64 0, iXLen %x
  %0 = load i8, ptr %arrayidx, align 1
  %add = add iXLen %y, 10
  %arrayidx2 = getelementptr inbounds nuw [1000 x i8], ptr %e, i64 0, iXLen %add
  %1 = load i8, ptr %arrayidx2, align 1
  %add4 = add i8 %1, %0
  ret i8 %add4
}
