1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2 ; RUN: llc -mtriple=riscv32 < %s | FileCheck %s 3 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 8 9 10 define dso_local void @multiple_stores() local_unnamed_addr { 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, 20 16 ; CHECK-NEXT: sw a1, 164(a0) 17 ; CHECK-NEXT: addi a1, zero, 10 18 ; CHECK-NEXT: sw a1, 160(a0) 19 ; CHECK-NEXT: ret 20 entry: 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 23 ret void 24 } 25 26 define dso_local void @control_flow_with_mem_access() local_unnamed_addr #0 { 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: addi a2, zero, 1 33 ; CHECK-NEXT: blt a1, a2, .LBB1_2 34 ; CHECK-NEXT: # %bb.1: # %if.then 35 ; CHECK-NEXT: addi a1, zero, 10 36 ; CHECK-NEXT: sw a1, 160(a0) 37 ; CHECK-NEXT: .LBB1_2: # %if.end 38 ; CHECK-NEXT: ret 39 entry: 40 %0 = load i32, i32* getelementptr inbounds (%struct.S, %struct.S* @s, i32 0, i32 2), align 4 41 %cmp = icmp sgt i32 %0, 0 42 br i1 %cmp, label %if.then, label %if.end 43 44 if.then: ; preds = %entry 45 store i32 10, i32* getelementptr inbounds (%struct.S, %struct.S* @s, i32 0, i32 1), align 4 46 br label %if.end 47 48 if.end: ; preds = %if.then, %entry 49 ret void 50 } 51 52 ; This test checks that the offset is reconstructed correctly when 53 ; "addi" of the big offset has a negative immediate. 54 ; without peephole this generates: 55 ; lui a1, %hi(g) 56 ; addi a1, a0, %lo(g) 57 ; lui a0, 18 ---> offset 58 ; addi a0, a0, -160 59 ; add a0, a0, a1 ---> base + offset. 60 define i8* @big_offset_neg_addi() { 61 ; CHECK-LABEL: big_offset_neg_addi: 62 ; CHECK: # %bb.0: 63 ; CHECK-NEXT: lui a0, %hi(g+73568) 64 ; CHECK-NEXT: addi a0, a0, %lo(g+73568) 65 ; CHECK-NEXT: ret 66 ret i8* getelementptr inbounds ([1048576 x i8], [1048576 x i8]* @g, i32 0, i32 73568) 67 } 68 69 ; This test checks for the case where the offset is only an LUI. 70 ; without peephole this generates: 71 ; lui a0, %hi(g) 72 ; addi a0, a0, %lo(g) 73 ; lui a1, 128 ---> offset 74 ; add a0, a0, a1 ---> base + offset. 75 define i8* @big_offset_lui_tail() { 76 ; CHECK-LABEL: big_offset_lui_tail: 77 ; CHECK: # %bb.0: 78 ; CHECK-NEXT: lui a0, %hi(g+524288) 79 ; CHECK-NEXT: addi a0, a0, %lo(g+524288) 80 ; CHECK-NEXT: ret 81 ret i8* getelementptr inbounds ([1048576 x i8], [1048576 x i8]* @g, i32 0, i32 524288) 82 } 83 84 define dso_local i32* @big_offset_one_use() local_unnamed_addr { 85 ; CHECK-LABEL: big_offset_one_use: 86 ; CHECK: # %bb.0: # %entry 87 ; CHECK-NEXT: lui a0, %hi(s+16572) 88 ; CHECK-NEXT: addi a0, a0, %lo(s+16572) 89 ; CHECK-NEXT: ret 90 entry: 91 ret i32* getelementptr inbounds (%struct.S, %struct.S* @s, i32 0, i32 5) 92 } 93 94 define dso_local i32* @small_offset_one_use() local_unnamed_addr { 95 ; CHECK-LABEL: small_offset_one_use: 96 ; CHECK: # %bb.0: # %entry 97 ; CHECK-NEXT: lui a0, %hi(s+160) 98 ; CHECK-NEXT: addi a0, a0, %lo(s+160) 99 ; CHECK-NEXT: ret 100 entry: 101 ret i32* getelementptr inbounds (%struct.S, %struct.S* @s, i32 0, i32 1) 102 } 103 104 ; Function Attrs: norecurse nounwind optsize readonly 105 define dso_local i32* @control_flow_no_mem(i32 %n) local_unnamed_addr #1 { 106 ; CHECK-LABEL: control_flow_no_mem: 107 ; CHECK: # %bb.0: # %entry 108 ; CHECK-NEXT: lui a0, %hi(s) 109 ; CHECK-NEXT: addi a0, a0, %lo(s) 110 ; CHECK-NEXT: lw a1, 164(a0) 111 ; CHECK-NEXT: beqz a1, .LBB6_2 112 ; CHECK-NEXT: # %bb.1: # %if.end 113 ; CHECK-NEXT: addi a0, a0, 168 114 ; CHECK-NEXT: ret 115 ; CHECK-NEXT: .LBB6_2: # %if.then 116 ; CHECK-NEXT: addi a0, a0, 160 117 ; CHECK-NEXT: ret 118 entry: 119 %0 = load i32, i32* getelementptr inbounds (%struct.S, %struct.S* @s, i32 0, i32 2), align 4 120 %cmp = icmp eq i32 %0, 0 121 br i1 %cmp, label %if.then, label %if.end 122 if.then: ; preds = %entry 123 ret i32* getelementptr inbounds (%struct.S, %struct.S* @s, i32 0, i32 1) 124 if.end: ; preds = %if.then, %entry 125 ret i32* getelementptr inbounds (%struct.S, %struct.S* @s, i32 0, i32 3) 126 } 127 128 define dso_local i32 @load_half() nounwind { 129 ; CHECK-LABEL: load_half: 130 ; CHECK: # %bb.0: # %entry 131 ; CHECK-NEXT: addi sp, sp, -16 132 ; CHECK-NEXT: sw ra, 12(sp) 133 ; CHECK-NEXT: lui a0, %hi(foo+8) 134 ; CHECK-NEXT: lhu a0, %lo(foo+8)(a0) 135 ; CHECK-NEXT: addi a1, zero, 140 136 ; CHECK-NEXT: bne a0, a1, .LBB7_2 137 ; CHECK-NEXT: # %bb.1: # %if.end 138 ; CHECK-NEXT: mv a0, zero 139 ; CHECK-NEXT: lw ra, 12(sp) 140 ; CHECK-NEXT: addi sp, sp, 16 141 ; CHECK-NEXT: ret 142 ; CHECK-NEXT: .LBB7_2: # %if.then 143 ; CHECK-NEXT: call abort 144 entry: 145 %0 = load i16, i16* getelementptr inbounds ([6 x i16], [6 x i16]* @foo, i32 0, i32 4), align 2 146 %cmp = icmp eq i16 %0, 140 147 br i1 %cmp, label %if.end, label %if.then 148 149 if.then: 150 tail call void @abort() 151 unreachable 152 153 if.end: 154 ret i32 0 155 } 156 157 declare void @abort() 158 159 define dso_local void @one_store() local_unnamed_addr { 160 ; CHECK-LABEL: one_store: 161 ; CHECK: # %bb.0: # %entry 162 ; CHECK-NEXT: lui a0, %hi(s+160) 163 ; CHECK-NEXT: addi a1, zero, 10 164 ; CHECK-NEXT: sw a1, %lo(s+160)(a0) 165 ; CHECK-NEXT: ret 166 entry: 167 store i32 10, i32* getelementptr inbounds (%struct.S, %struct.S* @s, i32 0, i32 1), align 4 168 ret void 169 } 170