[llvm] [RISCV] A test demonstrating missed opportunity to combine `addi` into (PR #67022)

Mikhail Gudim via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 2 09:21:55 PDT 2023


https://github.com/mgudim updated https://github.com/llvm/llvm-project/pull/67022

>From aa7d8ec32df2d44e93c5e27b753e5c194c265384 Mon Sep 17 00:00:00 2001
From: Mikhail Gudim <mgudim at gmail.com>
Date: Thu, 21 Sep 2023 10:33:43 -0400
Subject: [PATCH] [RISCV] A test demonstrating missed opportunity to combine
 `addi` into load / store offset.

The patch to fix this will be commited in a separate PR.
---
 .../test/CodeGen/RISCV/fold-addi-loadstore.ll | 267 ++++++++++++++++++
 1 file changed, 267 insertions(+)

diff --git a/llvm/test/CodeGen/RISCV/fold-addi-loadstore.ll b/llvm/test/CodeGen/RISCV/fold-addi-loadstore.ll
index 279f4628147f274..1669466546c3b14 100644
--- a/llvm/test/CodeGen/RISCV/fold-addi-loadstore.ll
+++ b/llvm/test/CodeGen/RISCV/fold-addi-loadstore.ll
@@ -733,3 +733,270 @@ entry:
   %0 = load i32, ptr inttoptr (i64 2147481600 to ptr)
   ret i32 %0
 }
+
+%struct.S = type { i64, i64 }
+
+define dso_local i64 @fold_addi_from_different_bb(i64 %k, i64 %n, ptr %a) {
+; RV32I-LABEL: fold_addi_from_different_bb:
+; RV32I:       # %bb.0: # %entry
+; RV32I-NEXT:    addi sp, sp, -48
+; RV32I-NEXT:    .cfi_def_cfa_offset 48
+; RV32I-NEXT:    sw ra, 44(sp) # 4-byte Folded Spill
+; RV32I-NEXT:    sw s0, 40(sp) # 4-byte Folded Spill
+; RV32I-NEXT:    sw s1, 36(sp) # 4-byte Folded Spill
+; RV32I-NEXT:    sw s2, 32(sp) # 4-byte Folded Spill
+; RV32I-NEXT:    sw s3, 28(sp) # 4-byte Folded Spill
+; RV32I-NEXT:    sw s4, 24(sp) # 4-byte Folded Spill
+; RV32I-NEXT:    sw s5, 20(sp) # 4-byte Folded Spill
+; RV32I-NEXT:    sw s6, 16(sp) # 4-byte Folded Spill
+; RV32I-NEXT:    sw s7, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT:    .cfi_offset ra, -4
+; RV32I-NEXT:    .cfi_offset s0, -8
+; RV32I-NEXT:    .cfi_offset s1, -12
+; RV32I-NEXT:    .cfi_offset s2, -16
+; RV32I-NEXT:    .cfi_offset s3, -20
+; RV32I-NEXT:    .cfi_offset s4, -24
+; RV32I-NEXT:    .cfi_offset s5, -28
+; RV32I-NEXT:    .cfi_offset s6, -32
+; RV32I-NEXT:    .cfi_offset s7, -36
+; RV32I-NEXT:    mv s0, a4
+; RV32I-NEXT:    mv s1, a3
+; RV32I-NEXT:    mv s2, a2
+; RV32I-NEXT:    beqz a3, .LBB20_3
+; RV32I-NEXT:  # %bb.1: # %entry
+; RV32I-NEXT:    slti a1, s1, 0
+; RV32I-NEXT:    beqz a1, .LBB20_4
+; RV32I-NEXT:  .LBB20_2:
+; RV32I-NEXT:    li s3, 0
+; RV32I-NEXT:    li s4, 0
+; RV32I-NEXT:    j .LBB20_6
+; RV32I-NEXT:  .LBB20_3:
+; RV32I-NEXT:    seqz a1, s2
+; RV32I-NEXT:    bnez a1, .LBB20_2
+; RV32I-NEXT:  .LBB20_4: # %for.body.lr.ph
+; RV32I-NEXT:    li s5, 0
+; RV32I-NEXT:    li s6, 0
+; RV32I-NEXT:    li s3, 0
+; RV32I-NEXT:    li s4, 0
+; RV32I-NEXT:    slli a0, a0, 4
+; RV32I-NEXT:    add a0, s0, a0
+; RV32I-NEXT:    addi s7, a0, 8
+; RV32I-NEXT:  .LBB20_5: # %for.body
+; RV32I-NEXT:    # =>This Inner Loop Header: Depth=1
+; RV32I-NEXT:    mv a0, s0
+; RV32I-NEXT:    call f at plt
+; RV32I-NEXT:    lw a0, 4(s7)
+; RV32I-NEXT:    lw a1, 0(s7)
+; RV32I-NEXT:    add a0, a0, s4
+; RV32I-NEXT:    add s3, a1, s3
+; RV32I-NEXT:    sltu s4, s3, a1
+; RV32I-NEXT:    addi s5, s5, 1
+; RV32I-NEXT:    seqz a1, s5
+; RV32I-NEXT:    add s6, s6, a1
+; RV32I-NEXT:    xor a1, s5, s2
+; RV32I-NEXT:    xor a2, s6, s1
+; RV32I-NEXT:    or a1, a1, a2
+; RV32I-NEXT:    add s4, a0, s4
+; RV32I-NEXT:    bnez a1, .LBB20_5
+; RV32I-NEXT:  .LBB20_6: # %for.cond.cleanup
+; RV32I-NEXT:    mv a0, s3
+; RV32I-NEXT:    mv a1, s4
+; RV32I-NEXT:    lw ra, 44(sp) # 4-byte Folded Reload
+; RV32I-NEXT:    lw s0, 40(sp) # 4-byte Folded Reload
+; RV32I-NEXT:    lw s1, 36(sp) # 4-byte Folded Reload
+; RV32I-NEXT:    lw s2, 32(sp) # 4-byte Folded Reload
+; RV32I-NEXT:    lw s3, 28(sp) # 4-byte Folded Reload
+; RV32I-NEXT:    lw s4, 24(sp) # 4-byte Folded Reload
+; RV32I-NEXT:    lw s5, 20(sp) # 4-byte Folded Reload
+; RV32I-NEXT:    lw s6, 16(sp) # 4-byte Folded Reload
+; RV32I-NEXT:    lw s7, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT:    addi sp, sp, 48
+; RV32I-NEXT:    ret
+;
+; RV32I-MEDIUM-LABEL: fold_addi_from_different_bb:
+; RV32I-MEDIUM:       # %bb.0: # %entry
+; RV32I-MEDIUM-NEXT:    addi sp, sp, -48
+; RV32I-MEDIUM-NEXT:    .cfi_def_cfa_offset 48
+; RV32I-MEDIUM-NEXT:    sw ra, 44(sp) # 4-byte Folded Spill
+; RV32I-MEDIUM-NEXT:    sw s0, 40(sp) # 4-byte Folded Spill
+; RV32I-MEDIUM-NEXT:    sw s1, 36(sp) # 4-byte Folded Spill
+; RV32I-MEDIUM-NEXT:    sw s2, 32(sp) # 4-byte Folded Spill
+; RV32I-MEDIUM-NEXT:    sw s3, 28(sp) # 4-byte Folded Spill
+; RV32I-MEDIUM-NEXT:    sw s4, 24(sp) # 4-byte Folded Spill
+; RV32I-MEDIUM-NEXT:    sw s5, 20(sp) # 4-byte Folded Spill
+; RV32I-MEDIUM-NEXT:    sw s6, 16(sp) # 4-byte Folded Spill
+; RV32I-MEDIUM-NEXT:    sw s7, 12(sp) # 4-byte Folded Spill
+; RV32I-MEDIUM-NEXT:    .cfi_offset ra, -4
+; RV32I-MEDIUM-NEXT:    .cfi_offset s0, -8
+; RV32I-MEDIUM-NEXT:    .cfi_offset s1, -12
+; RV32I-MEDIUM-NEXT:    .cfi_offset s2, -16
+; RV32I-MEDIUM-NEXT:    .cfi_offset s3, -20
+; RV32I-MEDIUM-NEXT:    .cfi_offset s4, -24
+; RV32I-MEDIUM-NEXT:    .cfi_offset s5, -28
+; RV32I-MEDIUM-NEXT:    .cfi_offset s6, -32
+; RV32I-MEDIUM-NEXT:    .cfi_offset s7, -36
+; RV32I-MEDIUM-NEXT:    mv s0, a4
+; RV32I-MEDIUM-NEXT:    mv s1, a3
+; RV32I-MEDIUM-NEXT:    mv s2, a2
+; RV32I-MEDIUM-NEXT:    beqz a3, .LBB20_3
+; RV32I-MEDIUM-NEXT:  # %bb.1: # %entry
+; RV32I-MEDIUM-NEXT:    slti a1, s1, 0
+; RV32I-MEDIUM-NEXT:    beqz a1, .LBB20_4
+; RV32I-MEDIUM-NEXT:  .LBB20_2:
+; RV32I-MEDIUM-NEXT:    li s3, 0
+; RV32I-MEDIUM-NEXT:    li s4, 0
+; RV32I-MEDIUM-NEXT:    j .LBB20_6
+; RV32I-MEDIUM-NEXT:  .LBB20_3:
+; RV32I-MEDIUM-NEXT:    seqz a1, s2
+; RV32I-MEDIUM-NEXT:    bnez a1, .LBB20_2
+; RV32I-MEDIUM-NEXT:  .LBB20_4: # %for.body.lr.ph
+; RV32I-MEDIUM-NEXT:    li s5, 0
+; RV32I-MEDIUM-NEXT:    li s6, 0
+; RV32I-MEDIUM-NEXT:    li s3, 0
+; RV32I-MEDIUM-NEXT:    li s4, 0
+; RV32I-MEDIUM-NEXT:    slli a0, a0, 4
+; RV32I-MEDIUM-NEXT:    add a0, s0, a0
+; RV32I-MEDIUM-NEXT:    addi s7, a0, 8
+; RV32I-MEDIUM-NEXT:  .LBB20_5: # %for.body
+; RV32I-MEDIUM-NEXT:    # =>This Inner Loop Header: Depth=1
+; RV32I-MEDIUM-NEXT:    mv a0, s0
+; RV32I-MEDIUM-NEXT:    call f at plt
+; RV32I-MEDIUM-NEXT:    lw a0, 4(s7)
+; RV32I-MEDIUM-NEXT:    lw a1, 0(s7)
+; RV32I-MEDIUM-NEXT:    add a0, a0, s4
+; RV32I-MEDIUM-NEXT:    add s3, a1, s3
+; RV32I-MEDIUM-NEXT:    sltu s4, s3, a1
+; RV32I-MEDIUM-NEXT:    addi s5, s5, 1
+; RV32I-MEDIUM-NEXT:    seqz a1, s5
+; RV32I-MEDIUM-NEXT:    add s6, s6, a1
+; RV32I-MEDIUM-NEXT:    xor a1, s5, s2
+; RV32I-MEDIUM-NEXT:    xor a2, s6, s1
+; RV32I-MEDIUM-NEXT:    or a1, a1, a2
+; RV32I-MEDIUM-NEXT:    add s4, a0, s4
+; RV32I-MEDIUM-NEXT:    bnez a1, .LBB20_5
+; RV32I-MEDIUM-NEXT:  .LBB20_6: # %for.cond.cleanup
+; RV32I-MEDIUM-NEXT:    mv a0, s3
+; RV32I-MEDIUM-NEXT:    mv a1, s4
+; RV32I-MEDIUM-NEXT:    lw ra, 44(sp) # 4-byte Folded Reload
+; RV32I-MEDIUM-NEXT:    lw s0, 40(sp) # 4-byte Folded Reload
+; RV32I-MEDIUM-NEXT:    lw s1, 36(sp) # 4-byte Folded Reload
+; RV32I-MEDIUM-NEXT:    lw s2, 32(sp) # 4-byte Folded Reload
+; RV32I-MEDIUM-NEXT:    lw s3, 28(sp) # 4-byte Folded Reload
+; RV32I-MEDIUM-NEXT:    lw s4, 24(sp) # 4-byte Folded Reload
+; RV32I-MEDIUM-NEXT:    lw s5, 20(sp) # 4-byte Folded Reload
+; RV32I-MEDIUM-NEXT:    lw s6, 16(sp) # 4-byte Folded Reload
+; RV32I-MEDIUM-NEXT:    lw s7, 12(sp) # 4-byte Folded Reload
+; RV32I-MEDIUM-NEXT:    addi sp, sp, 48
+; RV32I-MEDIUM-NEXT:    ret
+;
+; RV64I-LABEL: fold_addi_from_different_bb:
+; RV64I:       # %bb.0: # %entry
+; RV64I-NEXT:    addi sp, sp, -48
+; RV64I-NEXT:    .cfi_def_cfa_offset 48
+; RV64I-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
+; RV64I-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
+; RV64I-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
+; RV64I-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
+; RV64I-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT:    .cfi_offset ra, -8
+; RV64I-NEXT:    .cfi_offset s0, -16
+; RV64I-NEXT:    .cfi_offset s1, -24
+; RV64I-NEXT:    .cfi_offset s2, -32
+; RV64I-NEXT:    .cfi_offset s3, -40
+; RV64I-NEXT:    blez a1, .LBB20_3
+; RV64I-NEXT:  # %bb.1: # %for.body.lr.ph
+; RV64I-NEXT:    mv s0, a2
+; RV64I-NEXT:    mv s1, a1
+; RV64I-NEXT:    li s2, 0
+; RV64I-NEXT:    slli a0, a0, 4
+; RV64I-NEXT:    add a0, a2, a0
+; RV64I-NEXT:    addi s3, a0, 8
+; RV64I-NEXT:  .LBB20_2: # %for.body
+; RV64I-NEXT:    # =>This Inner Loop Header: Depth=1
+; RV64I-NEXT:    mv a0, s0
+; RV64I-NEXT:    call f at plt
+; RV64I-NEXT:    ld a0, 0(s3)
+; RV64I-NEXT:    addi s1, s1, -1
+; RV64I-NEXT:    add s2, a0, s2
+; RV64I-NEXT:    bnez s1, .LBB20_2
+; RV64I-NEXT:    j .LBB20_4
+; RV64I-NEXT:  .LBB20_3:
+; RV64I-NEXT:    li s2, 0
+; RV64I-NEXT:  .LBB20_4: # %for.cond.cleanup
+; RV64I-NEXT:    mv a0, s2
+; RV64I-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
+; RV64I-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
+; RV64I-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
+; RV64I-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
+; RV64I-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT:    addi sp, sp, 48
+; RV64I-NEXT:    ret
+;
+; RV64I-MEDIUM-LABEL: fold_addi_from_different_bb:
+; RV64I-MEDIUM:       # %bb.0: # %entry
+; RV64I-MEDIUM-NEXT:    addi sp, sp, -48
+; RV64I-MEDIUM-NEXT:    .cfi_def_cfa_offset 48
+; RV64I-MEDIUM-NEXT:    sd ra, 40(sp) # 8-byte Folded Spill
+; RV64I-MEDIUM-NEXT:    sd s0, 32(sp) # 8-byte Folded Spill
+; RV64I-MEDIUM-NEXT:    sd s1, 24(sp) # 8-byte Folded Spill
+; RV64I-MEDIUM-NEXT:    sd s2, 16(sp) # 8-byte Folded Spill
+; RV64I-MEDIUM-NEXT:    sd s3, 8(sp) # 8-byte Folded Spill
+; RV64I-MEDIUM-NEXT:    .cfi_offset ra, -8
+; RV64I-MEDIUM-NEXT:    .cfi_offset s0, -16
+; RV64I-MEDIUM-NEXT:    .cfi_offset s1, -24
+; RV64I-MEDIUM-NEXT:    .cfi_offset s2, -32
+; RV64I-MEDIUM-NEXT:    .cfi_offset s3, -40
+; RV64I-MEDIUM-NEXT:    blez a1, .LBB20_3
+; RV64I-MEDIUM-NEXT:  # %bb.1: # %for.body.lr.ph
+; RV64I-MEDIUM-NEXT:    mv s0, a2
+; RV64I-MEDIUM-NEXT:    mv s1, a1
+; RV64I-MEDIUM-NEXT:    li s2, 0
+; RV64I-MEDIUM-NEXT:    slli a0, a0, 4
+; RV64I-MEDIUM-NEXT:    add a0, a2, a0
+; RV64I-MEDIUM-NEXT:    addi s3, a0, 8
+; RV64I-MEDIUM-NEXT:  .LBB20_2: # %for.body
+; RV64I-MEDIUM-NEXT:    # =>This Inner Loop Header: Depth=1
+; RV64I-MEDIUM-NEXT:    mv a0, s0
+; RV64I-MEDIUM-NEXT:    call f at plt
+; RV64I-MEDIUM-NEXT:    ld a0, 0(s3)
+; RV64I-MEDIUM-NEXT:    addi s1, s1, -1
+; RV64I-MEDIUM-NEXT:    add s2, a0, s2
+; RV64I-MEDIUM-NEXT:    bnez s1, .LBB20_2
+; RV64I-MEDIUM-NEXT:    j .LBB20_4
+; RV64I-MEDIUM-NEXT:  .LBB20_3:
+; RV64I-MEDIUM-NEXT:    li s2, 0
+; RV64I-MEDIUM-NEXT:  .LBB20_4: # %for.cond.cleanup
+; RV64I-MEDIUM-NEXT:    mv a0, s2
+; RV64I-MEDIUM-NEXT:    ld ra, 40(sp) # 8-byte Folded Reload
+; RV64I-MEDIUM-NEXT:    ld s0, 32(sp) # 8-byte Folded Reload
+; RV64I-MEDIUM-NEXT:    ld s1, 24(sp) # 8-byte Folded Reload
+; RV64I-MEDIUM-NEXT:    ld s2, 16(sp) # 8-byte Folded Reload
+; RV64I-MEDIUM-NEXT:    ld s3, 8(sp) # 8-byte Folded Reload
+; RV64I-MEDIUM-NEXT:    addi sp, sp, 48
+; RV64I-MEDIUM-NEXT:    ret
+entry:
+  %cmp4 = icmp sgt i64 %n, 0
+  br i1 %cmp4, label %for.body.lr.ph, label %for.cond.cleanup
+
+for.body.lr.ph:                                   ; preds = %entry
+  ; TODO: when this GEP is expanded, the resulting `addi` should be folded
+  ; into the load in the loop body.
+  %y = getelementptr inbounds %struct.S, ptr %a, i64 %k, i32 1
+  br label %for.body
+
+for.cond.cleanup:                                 ; preds = %for.body, %entry
+  %s.0.lcssa = phi i64 [ 0, %entry ], [ %add, %for.body ]
+  ret i64 %s.0.lcssa
+
+for.body:                                         ; preds = %for.body.lr.ph, %for.body
+  %i.06 = phi i64 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]
+  %s.05 = phi i64 [ 0, %for.body.lr.ph ], [ %add, %for.body ]
+  call void @f(ptr %a)
+  %0 = load i64, ptr %y, align 8
+  %add = add nsw i64 %0, %s.05
+  %inc = add nuw nsw i64 %i.06, 1
+  %exitcond.not = icmp eq i64 %inc, %n
+  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
+}
+
+declare void @f(ptr)



More information about the llvm-commits mailing list