1 ; FIXME: FastISel currently returns false if it hits code that uses VSX 2 ; registers and with -fast-isel-abort=1 turned on the test case will then fail. 3 ; When fastisel better supports VSX fix up this test case. 4 ; 5 ; RUN: llc -relocation-model=static < %s -O0 -verify-machineinstrs -fast-isel -fast-isel-abort=1 -mattr=-vsx -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr7 | FileCheck %s --check-prefix=ELF64 6 ; RUN: llc -relocation-model=static < %s -O0 -verify-machineinstrs -fast-isel -fast-isel-abort=1 -mattr=spe -mtriple=powerpc-unknown-linux-gnu -mcpu=e500 | FileCheck %s --check-prefix=SPE 7 8 ; This test verifies that load/store instructions are properly generated, 9 ; and that they pass MI verification. 10 11 @a = global i8 1, align 1 12 @b = global i16 2, align 2 13 @c = global i32 4, align 4 14 @d = global i64 8, align 8 15 @e = global float 1.25, align 4 16 @f = global double 3.5, align 8 17 18 %struct.s = type<{ i8, i32 }> 19 %struct.t = type<{ i8, i64 }> 20 21 @g = global %struct.s <{ i8 1, i32 2 }>, align 1 22 @h = global %struct.t <{ i8 1, i64 2 }>, align 1 23 24 @i = common global [8192 x i64] zeroinitializer, align 8 25 26 ; load 27 28 define i8 @t1() nounwind { 29 ; ELF64: t1 30 %1 = load i8, i8* @a, align 1 31 ; ELF64: lbz 32 %2 = add nsw i8 %1, 1 33 ; ELF64: addi 34 ret i8 %2 35 } 36 37 define i16 @t2() nounwind { 38 ; ELF64: t2 39 %1 = load i16, i16* @b, align 2 40 ; ELF64: lhz 41 %2 = add nsw i16 %1, 1 42 ; ELF64: addi 43 ret i16 %2 44 } 45 46 define i32 @t3() nounwind { 47 ; ELF64: t3 48 %1 = load i32, i32* @c, align 4 49 ; ELF64: lwz 50 %2 = add nsw i32 %1, 1 51 ; ELF64: addi 52 ret i32 %2 53 } 54 55 define i64 @t4() nounwind { 56 ; ELF64: t4 57 %1 = load i64, i64* @d, align 4 58 ; ELF64: ld 59 %2 = add nsw i64 %1, 1 60 ; ELF64: addi 61 ret i64 %2 62 } 63 64 define float @t5() nounwind { 65 ; ELF64: t5 66 ; SPE: t5 67 %1 = load float, float* @e, align 4 68 ; ELF64: lfs 69 ; SPE: lwz 70 %2 = fadd float %1, 1.0 71 ; ELF64: fadds 72 ; SPE: efsadd 73 ret float %2 74 } 75 76 define double @t6() nounwind { 77 ; ELF64: t6 78 ; SPE: t6 79 %1 = load double, double* @f, align 8 80 ; ELF64: lfd 81 ; SPE: evldd 82 %2 = fadd double %1, 1.0 83 ; ELF64: fadd 84 ; SPE: efdadd 85 ret double %2 86 } 87 88 ; store 89 90 define void @t7(i8 %v) nounwind { 91 ; ELF64: t7 92 %1 = add nsw i8 %v, 1 93 store i8 %1, i8* @a, align 1 94 ; ELF64: addis 95 ; ELF64: addi 96 ; ELF64: addi 97 ; ELF64: stb 98 ret void 99 } 100 101 define void @t8(i16 %v) nounwind { 102 ; ELF64: t8 103 %1 = add nsw i16 %v, 1 104 store i16 %1, i16* @b, align 2 105 ; ELF64: addis 106 ; ELF64: addi 107 ; ELF64: addi 108 ; ELF64: sth 109 ret void 110 } 111 112 define void @t9(i32 %v) nounwind { 113 ; ELF64: t9 114 %1 = add nsw i32 %v, 1 115 store i32 %1, i32* @c, align 4 116 ; ELF64: addis 117 ; ELF64: addi 118 ; ELF64: addi 119 ; ELF64: stw 120 ret void 121 } 122 123 define void @t10(i64 %v) nounwind { 124 ; ELF64: t10 125 %1 = add nsw i64 %v, 1 126 store i64 %1, i64* @d, align 4 127 ; ELF64: addis 128 ; ELF64: addi 129 ; ELF64: addi 130 ; ELF64: std 131 ret void 132 } 133 134 define void @t11(float %v) nounwind { 135 ; ELF64: t11 136 ; SPE: t11 137 %1 = fadd float %v, 1.0 138 store float %1, float* @e, align 4 139 ; ELF64: fadds 140 ; ELF64: stfs 141 ; SPE: efsadd 142 ; SPE: stw 143 ret void 144 } 145 146 define void @t12(double %v) nounwind { 147 ; ELF64: t12 148 ; SPE: t12 149 %1 = fadd double %v, 1.0 150 store double %1, double* @f, align 8 151 ; ELF64: fadd 152 ; ELF64: stfd 153 ; SPE: efdadd 154 ; SPE: evstdd 155 ret void 156 } 157 158 ;; lwa requires an offset divisible by 4, so we need lwax here. 159 define i64 @t13() nounwind { 160 ; ELF64: t13 161 %1 = load i32, i32* getelementptr inbounds (%struct.s, %struct.s* @g, i32 0, i32 1), align 1 162 %2 = sext i32 %1 to i64 163 ; ELF64: li 164 ; ELF64: lwax 165 %3 = add nsw i64 %2, 1 166 ; ELF64: addi 167 ret i64 %3 168 } 169 170 ;; ld requires an offset divisible by 4, so we need ldx here. 171 define i64 @t14() nounwind { 172 ; ELF64: t14 173 %1 = load i64, i64* getelementptr inbounds (%struct.t, %struct.t* @h, i32 0, i32 1), align 1 174 ; ELF64: li 175 ; ELF64: ldx 176 %2 = add nsw i64 %1, 1 177 ; ELF64: addi 178 ret i64 %2 179 } 180 181 ;; std requires an offset divisible by 4, so we need stdx here. 182 define void @t15(i64 %v) nounwind { 183 ; ELF64: t15 184 %1 = add nsw i64 %v, 1 185 store i64 %1, i64* getelementptr inbounds (%struct.t, %struct.t* @h, i32 0, i32 1), align 1 186 ; ELF64: addis 187 ; ELF64: addi 188 ; ELF64: addi 189 ; ELF64: li 190 ; ELF64: stdx 191 ret void 192 } 193 194 ;; ld requires an offset that fits in 16 bits, so we need ldx here. 195 define i64 @t16() nounwind { 196 ; ELF64: t16 197 %1 = load i64, i64* getelementptr inbounds ([8192 x i64], [8192 x i64]* @i, i32 0, i64 5000), align 8 198 ; ELF64: lis 199 ; ELF64: ori 200 ; ELF64: ldx 201 %2 = add nsw i64 %1, 1 202 ; ELF64: addi 203 ret i64 %2 204 } 205 206 ;; std requires an offset that fits in 16 bits, so we need stdx here. 207 define void @t17(i64 %v) nounwind { 208 ; ELF64: t17 209 %1 = add nsw i64 %v, 1 210 store i64 %1, i64* getelementptr inbounds ([8192 x i64], [8192 x i64]* @i, i32 0, i64 5000), align 8 211 ; ELF64: addis 212 ; ELF64: addi 213 ; ELF64: addi 214 ; ELF64: lis 215 ; ELF64: ori 216 ; ELF64: stdx 217 ret void 218 } 219 220