180 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \3; RUN: | FileCheck %s -check-prefix=RV32I4; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \5; RUN: | FileCheck %s -check-prefix=RV64I6 7; Check that memory accesses to array elements with large offsets have those8; offsets split into a base offset, plus a smaller offset that is folded into9; the memory operation. We should also only compute that base offset once,10; since it can be shared for all memory operations in this test.11define void @test1(ptr %sp, ptr %t, i32 %n) {12; RV32I-LABEL: test1:13; RV32I: # %bb.0: # %entry14; RV32I-NEXT: lw a0, 0(a0)15; RV32I-NEXT: lui a2, 2016; RV32I-NEXT: li a3, 217; RV32I-NEXT: add a1, a1, a218; RV32I-NEXT: add a0, a0, a219; RV32I-NEXT: li a2, 120; RV32I-NEXT: sw a3, -1920(a0)21; RV32I-NEXT: sw a2, -1916(a0)22; RV32I-NEXT: sw a2, -1920(a1)23; RV32I-NEXT: sw a3, -1916(a1)24; RV32I-NEXT: ret25;26; RV64I-LABEL: test1:27; RV64I: # %bb.0: # %entry28; RV64I-NEXT: ld a0, 0(a0)29; RV64I-NEXT: lui a2, 2030; RV64I-NEXT: li a3, 231; RV64I-NEXT: add a1, a1, a232; RV64I-NEXT: add a0, a0, a233; RV64I-NEXT: li a2, 134; RV64I-NEXT: sw a3, -1920(a0)35; RV64I-NEXT: sw a2, -1916(a0)36; RV64I-NEXT: sw a2, -1920(a1)37; RV64I-NEXT: sw a3, -1916(a1)38; RV64I-NEXT: ret39entry:40 %s = load ptr, ptr %sp41 %gep0 = getelementptr [65536 x i32], ptr %s, i64 0, i32 2000042 %gep1 = getelementptr [65536 x i32], ptr %s, i64 0, i32 2000143 %gep2 = getelementptr [65536 x i32], ptr %t, i64 0, i32 2000044 %gep3 = getelementptr [65536 x i32], ptr %t, i64 0, i32 2000145 store i32 2, ptr %gep046 store i32 1, ptr %gep147 store i32 1, ptr %gep248 store i32 2, ptr %gep349 ret void50}51 52; Ditto. Check it when the GEPs are not in the entry block.53define void @test2(ptr %sp, ptr %t, i32 %n) {54; RV32I-LABEL: test2:55; RV32I: # %bb.0: # %entry56; RV32I-NEXT: li a3, 057; RV32I-NEXT: lw a0, 0(a0)58; RV32I-NEXT: lui a4, 2059; RV32I-NEXT: add a1, a1, a460; RV32I-NEXT: add a0, a0, a461; RV32I-NEXT: blez a2, .LBB1_262; RV32I-NEXT: .LBB1_1: # %while_body63; RV32I-NEXT: # =>This Inner Loop Header: Depth=164; RV32I-NEXT: addi a4, a3, 165; RV32I-NEXT: sw a4, -1920(a0)66; RV32I-NEXT: sw a3, -1916(a0)67; RV32I-NEXT: sw a4, -1920(a1)68; RV32I-NEXT: sw a3, -1916(a1)69; RV32I-NEXT: mv a3, a470; RV32I-NEXT: blt a4, a2, .LBB1_171; RV32I-NEXT: .LBB1_2: # %while_end72; RV32I-NEXT: ret73;74; RV64I-LABEL: test2:75; RV64I: # %bb.0: # %entry76; RV64I-NEXT: li a3, 077; RV64I-NEXT: ld a0, 0(a0)78; RV64I-NEXT: lui a4, 2079; RV64I-NEXT: add a1, a1, a480; RV64I-NEXT: add a0, a0, a481; RV64I-NEXT: sext.w a2, a282; RV64I-NEXT: blez a2, .LBB1_283; RV64I-NEXT: .LBB1_1: # %while_body84; RV64I-NEXT: # =>This Inner Loop Header: Depth=185; RV64I-NEXT: addiw a4, a3, 186; RV64I-NEXT: sw a4, -1920(a0)87; RV64I-NEXT: sw a3, -1916(a0)88; RV64I-NEXT: sw a4, -1920(a1)89; RV64I-NEXT: sw a3, -1916(a1)90; RV64I-NEXT: mv a3, a491; RV64I-NEXT: blt a4, a2, .LBB1_192; RV64I-NEXT: .LBB1_2: # %while_end93; RV64I-NEXT: ret94entry:95 %s = load ptr, ptr %sp96 br label %while_cond97while_cond:98 %phi = phi i32 [ 0, %entry ], [ %i, %while_body ]99 %gep0 = getelementptr [65536 x i32], ptr %s, i64 0, i32 20000100 %gep1 = getelementptr [65536 x i32], ptr %s, i64 0, i32 20001101 %gep2 = getelementptr [65536 x i32], ptr %t, i64 0, i32 20000102 %gep3 = getelementptr [65536 x i32], ptr %t, i64 0, i32 20001103 %cmp = icmp slt i32 %phi, %n104 br i1 %cmp, label %while_body, label %while_end105while_body:106 %i = add i32 %phi, 1107 %j = add i32 %phi, 2108 store i32 %i, ptr %gep0109 store i32 %phi, ptr %gep1110 store i32 %i, ptr %gep2111 store i32 %phi, ptr %gep3112 br label %while_cond113while_end:114 ret void115}116 117; GEPs have been manually split so the base GEP does not get used by any memory118; instructions. Make sure we use an offset and common base for each of the119; stores.120define void @test3(ptr %t) {121; RV32I-LABEL: test3:122; RV32I: # %bb.0: # %entry123; RV32I-NEXT: lui a1, 20124; RV32I-NEXT: li a2, 2125; RV32I-NEXT: add a0, a0, a1126; RV32I-NEXT: li a1, 3127; RV32I-NEXT: sw a2, -1916(a0)128; RV32I-NEXT: sw a1, -1912(a0)129; RV32I-NEXT: ret130;131; RV64I-LABEL: test3:132; RV64I: # %bb.0: # %entry133; RV64I-NEXT: lui a1, 20134; RV64I-NEXT: li a2, 2135; RV64I-NEXT: add a0, a0, a1136; RV64I-NEXT: li a1, 3137; RV64I-NEXT: sw a2, -1916(a0)138; RV64I-NEXT: sw a1, -1912(a0)139; RV64I-NEXT: ret140entry:141 %splitgep = getelementptr i8, ptr %t, i64 80000142 %0 = getelementptr i8, ptr %splitgep, i64 4143 %1 = getelementptr i8, ptr %splitgep, i64 8144 store i32 2, ptr %0, align 4145 store i32 3, ptr %1, align 4146 ret void147}148 149; Test from PR62734.150define void @test4(ptr %dest) {151; RV32I-LABEL: test4:152; RV32I: # %bb.0:153; RV32I-NEXT: addi a0, a0, 2047154; RV32I-NEXT: li a1, 1155; RV32I-NEXT: sb a1, 1(a0)156; RV32I-NEXT: sb a1, 2(a0)157; RV32I-NEXT: sb a1, 3(a0)158; RV32I-NEXT: sb a1, 4(a0)159; RV32I-NEXT: ret160;161; RV64I-LABEL: test4:162; RV64I: # %bb.0:163; RV64I-NEXT: addi a0, a0, 2047164; RV64I-NEXT: li a1, 1165; RV64I-NEXT: sb a1, 1(a0)166; RV64I-NEXT: sb a1, 2(a0)167; RV64I-NEXT: sb a1, 3(a0)168; RV64I-NEXT: sb a1, 4(a0)169; RV64I-NEXT: ret170 %p1 = getelementptr i8, ptr %dest, i32 2048171 store i8 1, ptr %p1172 %p2 = getelementptr i8, ptr %dest, i32 2049173 store i8 1, ptr %p2174 %p3 = getelementptr i8, ptr %dest, i32 2050175 store i8 1, ptr %p3176 %p4 = getelementptr i8, ptr %dest, i32 2051177 store i8 1, ptr %p4178 ret void179}180