When lowering GlobalAddressNodes, we were removing a non-zero offset and creating a separate ADD. It already comes out of SelectionDAGBuilder with a separate ADD. The ADD was being removed by DAGCombiner. This patch disables the DAG combine so we don't have to reverse it. Test changes all look to be instruction order changes. Probably due to different DAG node ordering. Differential Revision: https://reviews.llvm.org/D126558
97 lines
2.9 KiB
LLVM
97 lines
2.9 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc < %s -mtriple=riscv32 -verify-machineinstrs | FileCheck %s -check-prefixes=RV32
|
|
; RUN: llc < %s -mtriple=riscv64 -verify-machineinstrs | FileCheck %s -check-prefixes=RV64
|
|
|
|
; Test case:
|
|
; - `A[row]` is loop invariant and should be hoisted up to preheader
|
|
; FIXME: RV32 is working as expected, but RV64 doesn't
|
|
|
|
; The following LLVM IR simulates:
|
|
; int A[16][16];
|
|
; void test(int row, int N) {
|
|
; for (int i=0; i<N; ++I) {
|
|
; A[row][i+1] = 4;
|
|
; A[row][i+2] = 5;
|
|
; }
|
|
; }
|
|
|
|
; After LSR:
|
|
; int A[16][16];
|
|
; void test(int row, int N) {
|
|
; for (int *ptr = A[row][2]; N>0; N--) {
|
|
; *(ptr-1) = 4;
|
|
; *(ptr) = 5;
|
|
; ++ptr;
|
|
; }
|
|
; }
|
|
|
|
@A = internal global [16 x [16 x i32]] zeroinitializer, align 32 ; <[16 x [16 x i32]]*> [#uses=2]
|
|
|
|
define void @test(i32 signext %row, i32 signext %N.in) nounwind {
|
|
; RV32-LABEL: test:
|
|
; RV32: # %bb.0: # %entry
|
|
; RV32-NEXT: blez a1, .LBB0_3
|
|
; RV32-NEXT: # %bb.1: # %cond_true.preheader
|
|
; RV32-NEXT: slli a0, a0, 6
|
|
; RV32-NEXT: lui a2, %hi(A)
|
|
; RV32-NEXT: addi a2, a2, %lo(A)
|
|
; RV32-NEXT: add a0, a2, a0
|
|
; RV32-NEXT: addi a0, a0, 8
|
|
; RV32-NEXT: li a2, 4
|
|
; RV32-NEXT: li a3, 5
|
|
; RV32-NEXT: .LBB0_2: # %cond_true
|
|
; RV32-NEXT: # =>This Inner Loop Header: Depth=1
|
|
; RV32-NEXT: sw a2, -4(a0)
|
|
; RV32-NEXT: sw a3, 0(a0)
|
|
; RV32-NEXT: addi a1, a1, -1
|
|
; RV32-NEXT: addi a0, a0, 4
|
|
; RV32-NEXT: bnez a1, .LBB0_2
|
|
; RV32-NEXT: .LBB0_3: # %return
|
|
; RV32-NEXT: ret
|
|
;
|
|
; RV64-LABEL: test:
|
|
; RV64: # %bb.0: # %entry
|
|
; RV64-NEXT: blez a1, .LBB0_3
|
|
; RV64-NEXT: # %bb.1: # %cond_true.preheader
|
|
; RV64-NEXT: li a4, 0
|
|
; RV64-NEXT: slli a0, a0, 6
|
|
; RV64-NEXT: lui a2, %hi(A)
|
|
; RV64-NEXT: addi a2, a2, %lo(A)
|
|
; RV64-NEXT: add a0, a2, a0
|
|
; RV64-NEXT: li a2, 4
|
|
; RV64-NEXT: li a3, 5
|
|
; RV64-NEXT: .LBB0_2: # %cond_true
|
|
; RV64-NEXT: # =>This Inner Loop Header: Depth=1
|
|
; RV64-NEXT: addiw a5, a4, 1
|
|
; RV64-NEXT: slli a6, a5, 2
|
|
; RV64-NEXT: add a6, a0, a6
|
|
; RV64-NEXT: sw a2, 0(a6)
|
|
; RV64-NEXT: addiw a4, a4, 2
|
|
; RV64-NEXT: slli a4, a4, 2
|
|
; RV64-NEXT: add a4, a0, a4
|
|
; RV64-NEXT: sw a3, 0(a4)
|
|
; RV64-NEXT: mv a4, a5
|
|
; RV64-NEXT: bne a5, a1, .LBB0_2
|
|
; RV64-NEXT: .LBB0_3: # %return
|
|
; RV64-NEXT: ret
|
|
entry:
|
|
%N = bitcast i32 %N.in to i32
|
|
%tmp5 = icmp sgt i32 %N.in, 0
|
|
br i1 %tmp5, label %cond_true, label %return
|
|
|
|
cond_true:
|
|
%indvar = phi i32 [ 0, %entry ], [ %indvar.next, %cond_true ]
|
|
%tmp2 = add i32 %indvar, 1
|
|
%tmp = getelementptr [16 x [16 x i32]], [16 x [16 x i32]]* @A, i32 0, i32 %row, i32 %tmp2
|
|
store i32 4, i32* %tmp
|
|
%tmp5.upgrd.1 = add i32 %indvar, 2
|
|
%tmp7 = getelementptr [16 x [16 x i32]], [16 x [16 x i32]]* @A, i32 0, i32 %row, i32 %tmp5.upgrd.1
|
|
store i32 5, i32* %tmp7
|
|
%indvar.next = add i32 %indvar, 1
|
|
%exitcond = icmp eq i32 %indvar.next, %N
|
|
br i1 %exitcond, label %return, label %cond_true
|
|
|
|
return:
|
|
ret void
|
|
}
|