| ; 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, 400(a0) | |
| ; RV32I-NEXT: lw a3, 480(a1) | |
| ; RV32I-NEXT: lw a1, 484(a1) | |
| ; RV32I-NEXT: lw a4, 404(a0) | |
| ; RV32I-NEXT: add a0, a2, a3 | |
| ; RV32I-NEXT: add a1, a4, a1 | |
| ; RV32I-NEXT: sltu a2, a0, a2 | |
| ; 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, 400(a0) | |
| ; RV32ZBA-NEXT: lw a3, 480(a1) | |
| ; RV32ZBA-NEXT: lw a1, 484(a1) | |
| ; RV32ZBA-NEXT: lw a4, 404(a0) | |
| ; RV32ZBA-NEXT: add a0, a2, a3 | |
| ; RV32ZBA-NEXT: add a1, a4, a1 | |
| ; RV32ZBA-NEXT: sltu a2, a0, a2 | |
| ; 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 a3, 400(a0) | |
| ; RV32I-NEXT: lw a1, 404(a1) | |
| ; RV32I-NEXT: lw a4, 404(a0) | |
| ; RV32I-NEXT: add a0, a3, a2 | |
| ; RV32I-NEXT: add a1, a4, a1 | |
| ; RV32I-NEXT: sltu a2, a0, a3 | |
| ; 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 a3, 400(a0) | |
| ; RV32ZBA-NEXT: lw a1, 404(a1) | |
| ; RV32ZBA-NEXT: lw a4, 404(a0) | |
| ; RV32ZBA-NEXT: add a0, a3, a2 | |
| ; RV32ZBA-NEXT: add a1, a4, a1 | |
| ; RV32ZBA-NEXT: sltu a2, a0, a3 | |
| ; 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: addi a2, a2, 10 | |
| ; RV64I-NEXT: slli a1, a1, 32 | |
| ; RV64I-NEXT: slli a2, a2, 32 | |
| ; RV64I-NEXT: srli a1, a1, 31 | |
| ; RV64I-NEXT: srli a2, a2, 31 | |
| ; RV64I-NEXT: add a1, a0, a1 | |
| ; 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: addi a2, a2, 10 | |
| ; RV64ZBA-NEXT: sh1add.uw a1, a1, a0 | |
| ; 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: slli a1, a1, 2 | |
| ; RV32I-NEXT: addi a0, a0, 2047 | |
| ; 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: slli a1, a1, 2 | |
| ; RV64I-NEXT: addi a0, a0, 2047 | |
| ; 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: add a0, a0, a3 | |
| ; 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, -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: add a0, a0, a3 | |
| ; 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, -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: addi a1, a0, 2047 | |
| ; RV32I-NEXT: lw a0, 1200(a0) | |
| ; RV32I-NEXT: lw a1, 753(a1) | |
| ; RV32I-NEXT: add a0, a1, a0 | |
| ; 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: addi a1, a0, 2047 | |
| ; RV64I-NEXT: lw a0, 1200(a0) | |
| ; RV64I-NEXT: lw a1, 753(a1) | |
| ; RV64I-NEXT: addw a0, a1, a0 | |
| ; RV64I-NEXT: ret | |
| ; | |
| ; RV32ZBA-LABEL: test_cse: | |
| ; RV32ZBA: # %bb.0: # %entry | |
| ; RV32ZBA-NEXT: sh2add a0, a1, a0 | |
| ; RV32ZBA-NEXT: addi a1, a0, 2047 | |
| ; RV32ZBA-NEXT: lw a0, 1200(a0) | |
| ; RV32ZBA-NEXT: lw a1, 753(a1) | |
| ; RV32ZBA-NEXT: add a0, a1, a0 | |
| ; RV32ZBA-NEXT: ret | |
| ; | |
| ; RV64ZBA-LABEL: test_cse: | |
| ; RV64ZBA: # %bb.0: # %entry | |
| ; RV64ZBA-NEXT: sh2add a0, a1, a0 | |
| ; RV64ZBA-NEXT: addi a1, a0, 2047 | |
| ; RV64ZBA-NEXT: lw a0, 1200(a0) | |
| ; RV64ZBA-NEXT: lw a1, 753(a1) | |
| ; RV64ZBA-NEXT: addw a0, a1, a0 | |
| ; 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 | |
| } | |
| %union.u0 = type { [0 x i8] } | |
| declare void @f4() | |
| ; Make sure we don't crash when we find an global added to a frame index ADDI. | |
| define ptr @pr228053_frameindex_crash() { | |
| ; CHECK-LABEL: pr228053_frameindex_crash: | |
| ; CHECK: # %bb.0: # %entry | |
| ; CHECK-NEXT: addi sp, sp, -16 | |
| ; CHECK-NEXT: .cfi_def_cfa_offset 16 | |
| ; CHECK-NEXT: lui a0, %hi(f4) | |
| ; CHECK-NEXT: addi a0, a0, %lo(f4) | |
| ; CHECK-NEXT: addi a1, sp, 15 | |
| ; CHECK-NEXT: add a0, a1, a0 | |
| ; CHECK-NEXT: addi sp, sp, 16 | |
| ; CHECK-NEXT: .cfi_def_cfa_offset 0 | |
| ; CHECK-NEXT: ret | |
| ; | |
| ; ZBA-LABEL: pr228053_frameindex_crash: | |
| ; ZBA: # %bb.0: # %entry | |
| ; ZBA-NEXT: addi sp, sp, -16 | |
| ; ZBA-NEXT: .cfi_def_cfa_offset 16 | |
| ; ZBA-NEXT: lui a0, %hi(f4) | |
| ; ZBA-NEXT: addi a0, a0, %lo(f4) | |
| ; ZBA-NEXT: addi a1, sp, 15 | |
| ; ZBA-NEXT: add a0, a1, a0 | |
| ; ZBA-NEXT: addi sp, sp, 16 | |
| ; ZBA-NEXT: .cfi_def_cfa_offset 0 | |
| ; ZBA-NEXT: ret | |
| entry: | |
| %un18 = alloca %union.u0, align 1 | |
| %arrayidx1 = getelementptr i8, ptr %un18, i64 ptrtoint (ptr @f4 to i64) | |
| ret ptr %arrayidx1 | |
| } |