1 ; RUN: llc < %s -march=sparcv9 -mattr=+popc -disable-sparc-delay-filler -disable-sparc-leaf-proc | FileCheck %s 2 ; RUN: llc < %s -march=sparcv9 -mattr=+popc | FileCheck %s -check-prefix=OPT 3 4 ; CHECK-LABEL: ret2: 5 ; CHECK: mov %i1, %i0 6 7 ; OPT-LABEL: ret2: 8 ; OPT: retl 9 ; OPT: mov %o1, %o0 10 define i64 @ret2(i64 %a, i64 %b) { 11 ret i64 %b 12 } 13 14 ; CHECK: shl_imm 15 ; CHECK: sllx %i0, 7, %i0 16 17 ; OPT-LABEL: shl_imm: 18 ; OPT: retl 19 ; OPT: sllx %o0, 7, %o0 20 define i64 @shl_imm(i64 %a) { 21 %x = shl i64 %a, 7 22 ret i64 %x 23 } 24 25 ; CHECK: sra_reg 26 ; CHECK: srax %i0, %i1, %i0 27 28 ; OPT-LABEL: sra_reg: 29 ; OPT: retl 30 ; OPT: srax %o0, %o1, %o0 31 define i64 @sra_reg(i64 %a, i64 %b) { 32 %x = ashr i64 %a, %b 33 ret i64 %x 34 } 35 36 ; Immediate materialization. Many of these patterns could actually be merged 37 ; into the restore instruction: 38 ; 39 ; restore %g0, %g0, %o0 40 ; 41 ; CHECK: ret_imm0 42 ; CHECK: mov 0, %i0 43 44 ; OPT: ret_imm0 45 ; OPT: retl 46 ; OPT: mov 0, %o0 47 define i64 @ret_imm0() { 48 ret i64 0 49 } 50 51 ; CHECK: ret_simm13 52 ; CHECK: mov -4096, %i0 53 54 ; OPT: ret_simm13 55 ; OPT: retl 56 ; OPT: mov -4096, %o0 57 define i64 @ret_simm13() { 58 ret i64 -4096 59 } 60 61 ; CHECK: ret_sethi 62 ; CHECK: sethi 4, %i0 63 ; CHECK-NOT: or 64 ; CHECK: restore 65 66 ; OPT: ret_sethi 67 ; OPT: retl 68 ; OPT: sethi 4, %o0 69 define i64 @ret_sethi() { 70 ret i64 4096 71 } 72 73 ; CHECK: ret_sethi_or 74 ; CHECK: sethi 4, [[R:%[goli][0-7]]] 75 ; CHECK: or [[R]], 1, %i0 76 77 ; OPT: ret_sethi_or 78 ; OPT: sethi 4, [[R:%[go][0-7]]] 79 ; OPT: retl 80 ; OPT: or [[R]], 1, %o0 81 82 define i64 @ret_sethi_or() { 83 ret i64 4097 84 } 85 86 ; CHECK: ret_nimm33 87 ; CHECK: sethi 4, [[R:%[goli][0-7]]] 88 ; CHECK: xor [[R]], -4, %i0 89 90 ; OPT: ret_nimm33 91 ; OPT: sethi 4, [[R:%[go][0-7]]] 92 ; OPT: retl 93 ; OPT: xor [[R]], -4, %o0 94 95 define i64 @ret_nimm33() { 96 ret i64 -4100 97 } 98 99 ; CHECK: ret_bigimm 100 ; CHECK: sethi 101 ; CHECK: sethi 102 define i64 @ret_bigimm() { 103 ret i64 6800754272627607872 104 } 105 106 ; CHECK: ret_bigimm2 107 ; CHECK: sethi 1048576 108 define i64 @ret_bigimm2() { 109 ret i64 4611686018427387904 ; 0x4000000000000000 110 } 111 112 ; CHECK: reg_reg_alu 113 ; CHECK: add %i0, %i1, [[R0:%[goli][0-7]]] 114 ; CHECK: sub [[R0]], %i2, [[R1:%[goli][0-7]]] 115 ; CHECK: andn [[R1]], %i0, %i0 116 define i64 @reg_reg_alu(i64 %x, i64 %y, i64 %z) { 117 %a = add i64 %x, %y 118 %b = sub i64 %a, %z 119 %c = xor i64 %x, -1 120 %d = and i64 %b, %c 121 ret i64 %d 122 } 123 124 ; CHECK: reg_imm_alu 125 ; CHECK: add %i0, -5, [[R0:%[goli][0-7]]] 126 ; CHECK: xor [[R0]], 2, %i0 127 define i64 @reg_imm_alu(i64 %x, i64 %y, i64 %z) { 128 %a = add i64 %x, -5 129 %b = xor i64 %a, 2 130 ret i64 %b 131 } 132 133 ; CHECK: loads 134 ; CHECK: ldx [%i0] 135 ; CHECK: stx % 136 ; CHECK: ld [%i1] 137 ; CHECK: st % 138 ; CHECK: ldsw [%i2] 139 ; CHECK: stx % 140 ; CHECK: ldsh [%i3] 141 ; CHECK: sth % 142 define i64 @loads(i64* %p, i32* %q, i32* %r, i16* %s) { 143 %a = load i64, i64* %p 144 %ai = add i64 1, %a 145 store i64 %ai, i64* %p 146 %b = load i32, i32* %q 147 %b2 = zext i32 %b to i64 148 %bi = trunc i64 %ai to i32 149 store i32 %bi, i32* %q 150 %c = load i32, i32* %r 151 %c2 = sext i32 %c to i64 152 store i64 %ai, i64* %p 153 %d = load i16, i16* %s 154 %d2 = sext i16 %d to i64 155 %di = trunc i64 %ai to i16 156 store i16 %di, i16* %s 157 158 %x1 = add i64 %a, %b2 159 %x2 = add i64 %c2, %d2 160 %x3 = add i64 %x1, %x2 161 ret i64 %x3 162 } 163 164 ; CHECK: load_bool 165 ; CHECK: ldub [%i0], %i0 166 define i64 @load_bool(i1* %p) { 167 %a = load i1, i1* %p 168 %b = zext i1 %a to i64 169 ret i64 %b 170 } 171 172 ; CHECK: stores 173 ; CHECK: ldx [%i0+8], [[R:%[goli][0-7]]] 174 ; CHECK: stx [[R]], [%i0+16] 175 ; CHECK: st [[R]], [%i1+-8] 176 ; CHECK: sth [[R]], [%i2+40] 177 ; CHECK: stb [[R]], [%i3+-20] 178 define void @stores(i64* %p, i32* %q, i16* %r, i8* %s) { 179 %p1 = getelementptr i64, i64* %p, i64 1 180 %p2 = getelementptr i64, i64* %p, i64 2 181 %pv = load i64, i64* %p1 182 store i64 %pv, i64* %p2 183 184 %q2 = getelementptr i32, i32* %q, i32 -2 185 %qv = trunc i64 %pv to i32 186 store i32 %qv, i32* %q2 187 188 %r2 = getelementptr i16, i16* %r, i16 20 189 %rv = trunc i64 %pv to i16 190 store i16 %rv, i16* %r2 191 192 %s2 = getelementptr i8, i8* %s, i8 -20 193 %sv = trunc i64 %pv to i8 194 store i8 %sv, i8* %s2 195 196 ret void 197 } 198 199 ; CHECK: promote_shifts 200 ; CHECK: ldub [%i0], [[R:%[goli][0-7]]] 201 ; CHECK: sll [[R]], [[R]], %i0 202 define i8 @promote_shifts(i8* %p) { 203 %L24 = load i8, i8* %p 204 %L32 = load i8, i8* %p 205 %B36 = shl i8 %L24, %L32 206 ret i8 %B36 207 } 208 209 ; CHECK: multiply 210 ; CHECK: mulx %i0, %i1, %i0 211 define i64 @multiply(i64 %a, i64 %b) { 212 %r = mul i64 %a, %b 213 ret i64 %r 214 } 215 216 ; CHECK: signed_divide 217 ; CHECK: sdivx %i0, %i1, %i0 218 define i64 @signed_divide(i64 %a, i64 %b) { 219 %r = sdiv i64 %a, %b 220 ret i64 %r 221 } 222 223 ; CHECK: unsigned_divide 224 ; CHECK: udivx %i0, %i1, %i0 225 define i64 @unsigned_divide(i64 %a, i64 %b) { 226 %r = udiv i64 %a, %b 227 ret i64 %r 228 } 229 230 define void @access_fi() { 231 entry: 232 %b = alloca [32 x i8], align 1 233 %arraydecay = getelementptr inbounds [32 x i8], [32 x i8]* %b, i64 0, i64 0 234 call void @g(i8* %arraydecay) #2 235 ret void 236 } 237 238 declare void @g(i8*) 239 240 ; CHECK: expand_setcc 241 ; CHECK: cmp %i0, 1 242 ; CHECK: movl %xcc, 1, 243 define i32 @expand_setcc(i64 %a) { 244 %cond = icmp sle i64 %a, 0 245 %cast2 = zext i1 %cond to i32 246 %RV = sub i32 1, %cast2 247 ret i32 %RV 248 } 249 250 ; CHECK: spill_i64 251 ; CHECK: stx 252 ; CHECK: ldx 253 define i64 @spill_i64(i64 %x) { 254 call void asm sideeffect "", "~{i0},~{i1},~{i2},~{i3},~{i4},~{i5},~{o0},~{o1},~{o2},~{o3},~{o4},~{o5},~{o7},~{l0},~{l1},~{l2},~{l3},~{l4},~{l5},~{l6},~{l7},~{g1},~{g2},~{g3},~{g4},~{g5},~{g6},~{g7}"() 255 ret i64 %x 256 } 257 258 ; CHECK: bitcast_i64_f64 259 ; CHECK: std 260 ; CHECK: ldx 261 define i64 @bitcast_i64_f64(double %x) { 262 %y = bitcast double %x to i64 263 ret i64 %y 264 } 265 266 ; CHECK: bitcast_f64_i64 267 ; CHECK: stx 268 ; CHECK: ldd 269 define double @bitcast_f64_i64(i64 %x) { 270 %y = bitcast i64 %x to double 271 ret double %y 272 } 273 274 ; CHECK-LABEL: store_zero: 275 ; CHECK: stx %g0, [%i0] 276 ; CHECK: stx %g0, [%i1+8] 277 278 ; OPT-LABEL: store_zero: 279 ; OPT: stx %g0, [%o0] 280 ; OPT: stx %g0, [%o1+8] 281 define i64 @store_zero(i64* nocapture %a, i64* nocapture %b) { 282 entry: 283 store i64 0, i64* %a, align 8 284 %0 = getelementptr inbounds i64, i64* %b, i32 1 285 store i64 0, i64* %0, align 8 286 ret i64 0 287 } 288 289 ; CHECK-LABEL: bit_ops 290 ; CHECK: popc 291 292 ; OPT-LABEL: bit_ops 293 ; OPT: popc 294 295 define i64 @bit_ops(i64 %arg) { 296 entry: 297 %0 = tail call i64 @llvm.ctpop.i64(i64 %arg) 298 %1 = tail call i64 @llvm.ctlz.i64(i64 %arg, i1 true) 299 %2 = tail call i64 @llvm.cttz.i64(i64 %arg, i1 true) 300 %3 = tail call i64 @llvm.bswap.i64(i64 %arg) 301 %4 = add i64 %0, %1 302 %5 = add i64 %2, %3 303 %6 = add i64 %4, %5 304 ret i64 %6 305 } 306 307 declare i64 @llvm.ctpop.i64(i64) nounwind readnone 308 declare i64 @llvm.ctlz.i64(i64, i1) nounwind readnone 309 declare i64 @llvm.cttz.i64(i64, i1) nounwind readnone 310 declare i64 @llvm.bswap.i64(i64) nounwind readnone 311