; 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 }