1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=riscv32 -mattr=+f -target-abi=ilp32f -code-model=small -verify-machineinstrs < %s \
3; RUN:   | FileCheck %s -check-prefix=RV32I-SMALL
4; RUN: llc -mtriple=riscv32 -mattr=+f -target-abi=ilp32f -code-model=medium -verify-machineinstrs < %s \
5; RUN:   | FileCheck %s -check-prefix=RV32I-MEDIUM
6
7; Check lowering of globals
8@G = global i32 0
9
10define i32 @lower_global(i32 %a) nounwind {
11; RV32I-SMALL-LABEL: lower_global:
12; RV32I-SMALL:       # %bb.0:
13; RV32I-SMALL-NEXT:    lui a0, %hi(G)
14; RV32I-SMALL-NEXT:    lw a0, %lo(G)(a0)
15; RV32I-SMALL-NEXT:    ret
16;
17; RV32I-MEDIUM-LABEL: lower_global:
18; RV32I-MEDIUM:       # %bb.0:
19; RV32I-MEDIUM-NEXT:  .LBB0_1: # Label of block must be emitted
20; RV32I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(G)
21; RV32I-MEDIUM-NEXT:    addi a0, a0, %pcrel_lo(.LBB0_1)
22; RV32I-MEDIUM-NEXT:    lw a0, 0(a0)
23; RV32I-MEDIUM-NEXT:    ret
24  %1 = load volatile i32, i32* @G
25  ret i32 %1
26}
27
28; Check lowering of blockaddresses
29
30@addr = global i8* null
31
32define void @lower_blockaddress() nounwind {
33; RV32I-SMALL-LABEL: lower_blockaddress:
34; RV32I-SMALL:       # %bb.0:
35; RV32I-SMALL-NEXT:    lui a0, %hi(addr)
36; RV32I-SMALL-NEXT:    li a1, 1
37; RV32I-SMALL-NEXT:    sw a1, %lo(addr)(a0)
38; RV32I-SMALL-NEXT:    ret
39;
40; RV32I-MEDIUM-LABEL: lower_blockaddress:
41; RV32I-MEDIUM:       # %bb.0:
42; RV32I-MEDIUM-NEXT:  .LBB1_1: # Label of block must be emitted
43; RV32I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(addr)
44; RV32I-MEDIUM-NEXT:    addi a0, a0, %pcrel_lo(.LBB1_1)
45; RV32I-MEDIUM-NEXT:    li a1, 1
46; RV32I-MEDIUM-NEXT:    sw a1, 0(a0)
47; RV32I-MEDIUM-NEXT:    ret
48  store volatile i8* blockaddress(@lower_blockaddress, %block), i8** @addr
49  ret void
50
51block:
52  unreachable
53}
54
55; Check lowering of blockaddress that forces a displacement to be added
56
57define signext i32 @lower_blockaddress_displ(i32 signext %w) nounwind {
58; RV32I-SMALL-LABEL: lower_blockaddress_displ:
59; RV32I-SMALL:       # %bb.0: # %entry
60; RV32I-SMALL-NEXT:    addi sp, sp, -16
61; RV32I-SMALL-NEXT:    lui a1, %hi(.Ltmp0)
62; RV32I-SMALL-NEXT:    addi a1, a1, %lo(.Ltmp0)
63; RV32I-SMALL-NEXT:    li a2, 101
64; RV32I-SMALL-NEXT:    sw a1, 8(sp)
65; RV32I-SMALL-NEXT:    blt a0, a2, .LBB2_3
66; RV32I-SMALL-NEXT:  # %bb.1: # %if.then
67; RV32I-SMALL-NEXT:    lw a0, 8(sp)
68; RV32I-SMALL-NEXT:    jr a0
69; RV32I-SMALL-NEXT:  .Ltmp0: # Block address taken
70; RV32I-SMALL-NEXT:  .LBB2_2: # %return
71; RV32I-SMALL-NEXT:    li a0, 4
72; RV32I-SMALL-NEXT:    addi sp, sp, 16
73; RV32I-SMALL-NEXT:    ret
74; RV32I-SMALL-NEXT:  .LBB2_3: # %return.clone
75; RV32I-SMALL-NEXT:    li a0, 3
76; RV32I-SMALL-NEXT:    addi sp, sp, 16
77; RV32I-SMALL-NEXT:    ret
78;
79; RV32I-MEDIUM-LABEL: lower_blockaddress_displ:
80; RV32I-MEDIUM:       # %bb.0: # %entry
81; RV32I-MEDIUM-NEXT:    addi sp, sp, -16
82; RV32I-MEDIUM-NEXT:  .LBB2_4: # %entry
83; RV32I-MEDIUM-NEXT:    # Label of block must be emitted
84; RV32I-MEDIUM-NEXT:    auipc a1, %pcrel_hi(.Ltmp0)
85; RV32I-MEDIUM-NEXT:    addi a1, a1, %pcrel_lo(.LBB2_4)
86; RV32I-MEDIUM-NEXT:    li a2, 101
87; RV32I-MEDIUM-NEXT:    sw a1, 8(sp)
88; RV32I-MEDIUM-NEXT:    blt a0, a2, .LBB2_3
89; RV32I-MEDIUM-NEXT:  # %bb.1: # %if.then
90; RV32I-MEDIUM-NEXT:    lw a0, 8(sp)
91; RV32I-MEDIUM-NEXT:    jr a0
92; RV32I-MEDIUM-NEXT:  .Ltmp0: # Block address taken
93; RV32I-MEDIUM-NEXT:  .LBB2_2: # %return
94; RV32I-MEDIUM-NEXT:    li a0, 4
95; RV32I-MEDIUM-NEXT:    addi sp, sp, 16
96; RV32I-MEDIUM-NEXT:    ret
97; RV32I-MEDIUM-NEXT:  .LBB2_3: # %return.clone
98; RV32I-MEDIUM-NEXT:    li a0, 3
99; RV32I-MEDIUM-NEXT:    addi sp, sp, 16
100; RV32I-MEDIUM-NEXT:    ret
101entry:
102  %x = alloca i8*, align 8
103  store i8* blockaddress(@lower_blockaddress_displ, %test_block), i8** %x, align 8
104  %cmp = icmp sgt i32 %w, 100
105  br i1 %cmp, label %if.then, label %if.end
106
107if.then:
108  %addr = load i8*, i8** %x, align 8
109  br label %indirectgoto
110
111if.end:
112  br label %return
113
114test_block:
115  br label %return
116
117return:
118  %retval = phi i32 [ 3, %if.end ], [ 4, %test_block ]
119  ret i32 %retval
120
121indirectgoto:
122  indirectbr i8* %addr, [ label %test_block ]
123}
124
125; Check lowering of constantpools
126
127define float @lower_constantpool(float %a) nounwind {
128; RV32I-SMALL-LABEL: lower_constantpool:
129; RV32I-SMALL:       # %bb.0:
130; RV32I-SMALL-NEXT:    lui a0, %hi(.LCPI3_0)
131; RV32I-SMALL-NEXT:    flw ft0, %lo(.LCPI3_0)(a0)
132; RV32I-SMALL-NEXT:    fadd.s fa0, fa0, ft0
133; RV32I-SMALL-NEXT:    ret
134;
135; RV32I-MEDIUM-LABEL: lower_constantpool:
136; RV32I-MEDIUM:       # %bb.0:
137; RV32I-MEDIUM-NEXT:  .LBB3_1: # Label of block must be emitted
138; RV32I-MEDIUM-NEXT:    auipc a0, %pcrel_hi(.LCPI3_0)
139; RV32I-MEDIUM-NEXT:    addi a0, a0, %pcrel_lo(.LBB3_1)
140; RV32I-MEDIUM-NEXT:    flw ft0, 0(a0)
141; RV32I-MEDIUM-NEXT:    fadd.s fa0, fa0, ft0
142; RV32I-MEDIUM-NEXT:    ret
143  %1 = fadd float %a, 1.0
144  ret float %1
145}
146