1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=riscv32 < %s | FileCheck %s
4 %struct.S = type { [40 x i32], i32, i32, i32, [4100 x i32], i32, i32, i32 }
5 @s = common dso_local global %struct.S zeroinitializer, align 4
6 @foo = global [6 x i16] [i16 1, i16 2, i16 3, i16 4, i16 5, i16 0], align 2
7 @g = global [1048576 x i8] zeroinitializer, align 1
10 define dso_local void @multiple_stores() local_unnamed_addr nounwind {
11 ; CHECK-LABEL: multiple_stores:
12 ; CHECK: # %bb.0: # %entry
13 ; CHECK-NEXT: lui a0, %hi(s)
14 ; CHECK-NEXT: addi a0, a0, %lo(s)
15 ; CHECK-NEXT: addi a1, zero, 10
16 ; CHECK-NEXT: sw a1, 160(a0)
17 ; CHECK-NEXT: addi a1, zero, 20
18 ; CHECK-NEXT: sw a1, 164(a0)
21 store i32 10, i32* getelementptr inbounds (%struct.S, %struct.S* @s, i32 0, i32 1), align 4
22 store i32 20, i32* getelementptr inbounds (%struct.S, %struct.S* @s, i32 0, i32 2), align 4
26 define dso_local void @control_flow_with_mem_access() local_unnamed_addr nounwind {
27 ; CHECK-LABEL: control_flow_with_mem_access:
28 ; CHECK: # %bb.0: # %entry
29 ; CHECK-NEXT: lui a0, %hi(s)
30 ; CHECK-NEXT: addi a0, a0, %lo(s)
31 ; CHECK-NEXT: lw a1, 164(a0)
32 ; CHECK-NEXT: blez a1, .LBB1_2
33 ; CHECK-NEXT: # %bb.1: # %if.then
34 ; CHECK-NEXT: addi a1, zero, 10
35 ; CHECK-NEXT: sw a1, 160(a0)
36 ; CHECK-NEXT: .LBB1_2: # %if.end
39 %0 = load i32, i32* getelementptr inbounds (%struct.S, %struct.S* @s, i32 0, i32 2), align 4
40 %cmp = icmp sgt i32 %0, 0
41 br i1 %cmp, label %if.then, label %if.end
43 if.then: ; preds = %entry
44 store i32 10, i32* getelementptr inbounds (%struct.S, %struct.S* @s, i32 0, i32 1), align 4
47 if.end: ; preds = %if.then, %entry
51 ; This test checks that the offset is reconstructed correctly when
52 ; "addi" of the big offset has a negative immediate.
53 ; without peephole this generates:
56 ; lui a0, 18 ---> offset
58 ; add a0, a0, a1 ---> base + offset.
59 define i8* @big_offset_neg_addi() nounwind {
60 ; CHECK-LABEL: big_offset_neg_addi:
62 ; CHECK-NEXT: lui a0, %hi(g+73568)
63 ; CHECK-NEXT: addi a0, a0, %lo(g+73568)
65 ret i8* getelementptr inbounds ([1048576 x i8], [1048576 x i8]* @g, i32 0, i32 73568)
68 ; This test checks for the case where the offset is only an LUI.
69 ; without peephole this generates:
72 ; lui a1, 128 ---> offset
73 ; add a0, a0, a1 ---> base + offset.
74 define i8* @big_offset_lui_tail() nounwind {
75 ; CHECK-LABEL: big_offset_lui_tail:
77 ; CHECK-NEXT: lui a0, %hi(g+524288)
78 ; CHECK-NEXT: addi a0, a0, %lo(g+524288)
80 ret i8* getelementptr inbounds ([1048576 x i8], [1048576 x i8]* @g, i32 0, i32 524288)
83 define dso_local i32* @big_offset_one_use() local_unnamed_addr nounwind {
84 ; CHECK-LABEL: big_offset_one_use:
85 ; CHECK: # %bb.0: # %entry
86 ; CHECK-NEXT: lui a0, %hi(s+16572)
87 ; CHECK-NEXT: addi a0, a0, %lo(s+16572)
90 ret i32* getelementptr inbounds (%struct.S, %struct.S* @s, i32 0, i32 5)
93 define dso_local i32* @small_offset_one_use() local_unnamed_addr nounwind {
94 ; CHECK-LABEL: small_offset_one_use:
95 ; CHECK: # %bb.0: # %entry
96 ; CHECK-NEXT: lui a0, %hi(s+160)
97 ; CHECK-NEXT: addi a0, a0, %lo(s+160)
100 ret i32* getelementptr inbounds (%struct.S, %struct.S* @s, i32 0, i32 1)
103 define dso_local i32* @control_flow_no_mem(i32 %n) local_unnamed_addr nounwind {
104 ; CHECK-LABEL: control_flow_no_mem:
105 ; CHECK: # %bb.0: # %entry
106 ; CHECK-NEXT: lui a0, %hi(s)
107 ; CHECK-NEXT: addi a0, a0, %lo(s)
108 ; CHECK-NEXT: lw a1, 164(a0)
109 ; CHECK-NEXT: beqz a1, .LBB6_2
110 ; CHECK-NEXT: # %bb.1: # %if.end
111 ; CHECK-NEXT: addi a0, a0, 168
113 ; CHECK-NEXT: .LBB6_2: # %if.then
114 ; CHECK-NEXT: addi a0, a0, 160
117 %0 = load i32, i32* getelementptr inbounds (%struct.S, %struct.S* @s, i32 0, i32 2), align 4
118 %cmp = icmp eq i32 %0, 0
119 br i1 %cmp, label %if.then, label %if.end
120 if.then: ; preds = %entry
121 ret i32* getelementptr inbounds (%struct.S, %struct.S* @s, i32 0, i32 1)
122 if.end: ; preds = %if.then, %entry
123 ret i32* getelementptr inbounds (%struct.S, %struct.S* @s, i32 0, i32 3)
126 define dso_local i32 @load_half() nounwind {
127 ; CHECK-LABEL: load_half:
128 ; CHECK: # %bb.0: # %entry
129 ; CHECK-NEXT: addi sp, sp, -16
130 ; CHECK-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
131 ; CHECK-NEXT: lui a0, %hi(foo+8)
132 ; CHECK-NEXT: lhu a0, %lo(foo+8)(a0)
133 ; CHECK-NEXT: addi a1, zero, 140
134 ; CHECK-NEXT: bne a0, a1, .LBB7_2
135 ; CHECK-NEXT: # %bb.1: # %if.end
136 ; CHECK-NEXT: mv a0, zero
137 ; CHECK-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
138 ; CHECK-NEXT: addi sp, sp, 16
140 ; CHECK-NEXT: .LBB7_2: # %if.then
141 ; CHECK-NEXT: call abort@plt
143 %0 = load i16, i16* getelementptr inbounds ([6 x i16], [6 x i16]* @foo, i32 0, i32 4), align 2
144 %cmp = icmp eq i16 %0, 140
145 br i1 %cmp, label %if.end, label %if.then
148 tail call void @abort()
155 declare void @abort()
157 define dso_local void @one_store() local_unnamed_addr nounwind {
158 ; CHECK-LABEL: one_store:
159 ; CHECK: # %bb.0: # %entry
160 ; CHECK-NEXT: lui a0, %hi(s+160)
161 ; CHECK-NEXT: addi a1, zero, 10
162 ; CHECK-NEXT: sw a1, %lo(s+160)(a0)
165 store i32 10, i32* getelementptr inbounds (%struct.S, %struct.S* @s, i32 0, i32 1), align 4