1 ; RUN: llc -march=mipsel --disable-machine-licm -mcpu=mips32 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS32-ANY -check-prefix=NO-SEB-SEH -check-prefix=CHECK-EL 2 ; RUN: llc -march=mipsel --disable-machine-licm -mcpu=mips32r2 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS32-ANY -check-prefix=HAS-SEB-SEH -check-prefix=CHECK-EL 3 ; RUN: llc -march=mipsel --disable-machine-licm -mcpu=mips32r6 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS32-ANY -check-prefix=HAS-SEB-SEH -check-prefix=CHECK-EL 4 ; RUN: llc -march=mips64el --disable-machine-licm -mcpu=mips4 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS64-ANY -check-prefix=NO-SEB-SEH -check-prefix=CHECK-EL 5 ; RUN: llc -march=mips64el --disable-machine-licm -mcpu=mips64 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS64-ANY -check-prefix=NO-SEB-SEH -check-prefix=CHECK-EL 6 ; RUN: llc -march=mips64el --disable-machine-licm -mcpu=mips64r2 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS64-ANY -check-prefix=HAS-SEB-SEH -check-prefix=CHECK-EL 7 ; RUN: llc -march=mips64el --disable-machine-licm -mcpu=mips64r6 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS64-ANY -check-prefix=HAS-SEB-SEH -check-prefix=CHECK-EL 8 9 ; Keep one big-endian check so that we don't reduce testing, but don't add more 10 ; since endianness doesn't affect the body of the atomic operations. 11 ; RUN: llc -march=mips --disable-machine-licm -mcpu=mips32 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS32-ANY -check-prefix=CHECK-EB 12 13 @x = common global i32 0, align 4 14 15 define i32 @AtomicLoadAdd32(i32 %incr) nounwind { 16 entry: 17 %0 = atomicrmw add i32* @x, i32 %incr monotonic 18 ret i32 %0 19 20 ; ALL-LABEL: AtomicLoadAdd32: 21 22 ; MIPS32-ANY: lw $[[R0:[0-9]+]], %got(x) 23 ; MIPS64-ANY: ld $[[R0:[0-9]+]], %got_disp(x)( 24 25 ; ALL: $[[BB0:[A-Z_0-9]+]]: 26 ; ALL: ll $[[R1:[0-9]+]], 0($[[R0]]) 27 ; ALL: addu $[[R2:[0-9]+]], $[[R1]], $4 28 ; ALL: sc $[[R2]], 0($[[R0]]) 29 ; ALL: beqz $[[R2]], $[[BB0]] 30 } 31 32 define i32 @AtomicLoadNand32(i32 %incr) nounwind { 33 entry: 34 %0 = atomicrmw nand i32* @x, i32 %incr monotonic 35 ret i32 %0 36 37 ; ALL-LABEL: AtomicLoadNand32: 38 39 ; MIPS32-ANY: lw $[[R0:[0-9]+]], %got(x) 40 ; MIPS64-ANY: ld $[[R0:[0-9]+]], %got_disp(x)( 41 42 ; ALL: $[[BB0:[A-Z_0-9]+]]: 43 ; ALL: ll $[[R1:[0-9]+]], 0($[[R0]]) 44 ; ALL: and $[[R3:[0-9]+]], $[[R1]], $4 45 ; ALL: nor $[[R2:[0-9]+]], $zero, $[[R3]] 46 ; ALL: sc $[[R2]], 0($[[R0]]) 47 ; ALL: beqz $[[R2]], $[[BB0]] 48 } 49 50 define i32 @AtomicSwap32(i32 %newval) nounwind { 51 entry: 52 %newval.addr = alloca i32, align 4 53 store i32 %newval, i32* %newval.addr, align 4 54 %tmp = load i32* %newval.addr, align 4 55 %0 = atomicrmw xchg i32* @x, i32 %tmp monotonic 56 ret i32 %0 57 58 ; ALL-LABEL: AtomicSwap32: 59 60 ; MIPS32-ANY: lw $[[R0:[0-9]+]], %got(x) 61 ; MIPS64-ANY: ld $[[R0:[0-9]+]], %got_disp(x) 62 63 ; ALL: $[[BB0:[A-Z_0-9]+]]: 64 ; ALL: ll ${{[0-9]+}}, 0($[[R0]]) 65 ; ALL: sc $[[R2:[0-9]+]], 0($[[R0]]) 66 ; ALL: beqz $[[R2]], $[[BB0]] 67 } 68 69 define i32 @AtomicCmpSwap32(i32 %oldval, i32 %newval) nounwind { 70 entry: 71 %newval.addr = alloca i32, align 4 72 store i32 %newval, i32* %newval.addr, align 4 73 %tmp = load i32* %newval.addr, align 4 74 %0 = cmpxchg i32* @x, i32 %oldval, i32 %tmp monotonic monotonic 75 %1 = extractvalue { i32, i1 } %0, 0 76 ret i32 %1 77 78 ; ALL-LABEL: AtomicCmpSwap32: 79 80 ; MIPS32-ANY: lw $[[R0:[0-9]+]], %got(x) 81 ; MIPS64-ANY: ld $[[R0:[0-9]+]], %got_disp(x)( 82 83 ; ALL: $[[BB0:[A-Z_0-9]+]]: 84 ; ALL: ll $2, 0($[[R0]]) 85 ; ALL: bne $2, $4, $[[BB1:[A-Z_0-9]+]] 86 ; ALL: sc $[[R2:[0-9]+]], 0($[[R0]]) 87 ; ALL: beqz $[[R2]], $[[BB0]] 88 ; ALL: $[[BB1]]: 89 } 90 91 92 93 @y = common global i8 0, align 1 94 95 define signext i8 @AtomicLoadAdd8(i8 signext %incr) nounwind { 96 entry: 97 %0 = atomicrmw add i8* @y, i8 %incr monotonic 98 ret i8 %0 99 100 ; ALL-LABEL: AtomicLoadAdd8: 101 102 ; MIPS32-ANY: lw $[[R0:[0-9]+]], %got(y) 103 ; MIPS64-ANY: ld $[[R0:[0-9]+]], %got_disp(y)( 104 105 ; ALL: addiu $[[R1:[0-9]+]], $zero, -4 106 ; ALL: and $[[R2:[0-9]+]], $[[R0]], $[[R1]] 107 ; ALL: andi $[[R3:[0-9]+]], $[[R0]], 3 108 ; CHECK-EB: xori $[[R4:[0-9]+]], $[[R3]], 3 109 ; CHECK-EB: sll $[[R5:[0-9]+]], $[[R4]], 3 110 ; CHECK-EL: sll $[[R5:[0-9]+]], $[[R3]], 3 111 ; ALL: ori $[[R6:[0-9]+]], $zero, 255 112 ; ALL: sllv $[[R7:[0-9]+]], $[[R6]], $[[R5]] 113 ; ALL: nor $[[R8:[0-9]+]], $zero, $[[R7]] 114 ; ALL: sllv $[[R9:[0-9]+]], $4, $[[R5]] 115 116 ; ALL: $[[BB0:[A-Z_0-9]+]]: 117 ; ALL: ll $[[R10:[0-9]+]], 0($[[R2]]) 118 ; ALL: addu $[[R11:[0-9]+]], $[[R10]], $[[R9]] 119 ; ALL: and $[[R12:[0-9]+]], $[[R11]], $[[R7]] 120 ; ALL: and $[[R13:[0-9]+]], $[[R10]], $[[R8]] 121 ; ALL: or $[[R14:[0-9]+]], $[[R13]], $[[R12]] 122 ; ALL: sc $[[R14]], 0($[[R2]]) 123 ; ALL: beqz $[[R14]], $[[BB0]] 124 125 ; ALL: and $[[R15:[0-9]+]], $[[R10]], $[[R7]] 126 ; ALL: srlv $[[R16:[0-9]+]], $[[R15]], $[[R5]] 127 128 ; NO-SEB-SEH: sll $[[R17:[0-9]+]], $[[R16]], 24 129 ; NO-SEB-SEH: sra $2, $[[R17]], 24 130 131 ; HAS-SEB-SEH: seb $2, $[[R16]] 132 } 133 134 define signext i8 @AtomicLoadSub8(i8 signext %incr) nounwind { 135 entry: 136 %0 = atomicrmw sub i8* @y, i8 %incr monotonic 137 ret i8 %0 138 139 ; ALL-LABEL: AtomicLoadSub8: 140 141 ; MIPS32-ANY: lw $[[R0:[0-9]+]], %got(y) 142 ; MIPS64-ANY: ld $[[R0:[0-9]+]], %got_disp(y)( 143 144 ; ALL: addiu $[[R1:[0-9]+]], $zero, -4 145 ; ALL: and $[[R2:[0-9]+]], $[[R0]], $[[R1]] 146 ; ALL: andi $[[R3:[0-9]+]], $[[R0]], 3 147 ; CHECK-EL: sll $[[R5:[0-9]+]], $[[R3]], 3 148 ; CHECK-EB: xori $[[R4:[0-9]+]], $[[R3]], 3 149 ; CHECK-EB: sll $[[R5:[0-9]+]], $[[R4]], 3 150 ; ALL: ori $[[R6:[0-9]+]], $zero, 255 151 ; ALL: sllv $[[R7:[0-9]+]], $[[R6]], $[[R5]] 152 ; ALL: nor $[[R8:[0-9]+]], $zero, $[[R7]] 153 ; ALL: sllv $[[R9:[0-9]+]], $4, $[[R5]] 154 155 ; ALL: $[[BB0:[A-Z_0-9]+]]: 156 ; ALL: ll $[[R10:[0-9]+]], 0($[[R2]]) 157 ; ALL: subu $[[R11:[0-9]+]], $[[R10]], $[[R9]] 158 ; ALL: and $[[R12:[0-9]+]], $[[R11]], $[[R7]] 159 ; ALL: and $[[R13:[0-9]+]], $[[R10]], $[[R8]] 160 ; ALL: or $[[R14:[0-9]+]], $[[R13]], $[[R12]] 161 ; ALL: sc $[[R14]], 0($[[R2]]) 162 ; ALL: beqz $[[R14]], $[[BB0]] 163 164 ; ALL: and $[[R15:[0-9]+]], $[[R10]], $[[R7]] 165 ; ALL: srlv $[[R16:[0-9]+]], $[[R15]], $[[R5]] 166 167 ; NO-SEB-SEH: sll $[[R17:[0-9]+]], $[[R16]], 24 168 ; NO-SEB-SEH: sra $2, $[[R17]], 24 169 170 ; HAS-SEB-SEH:seb $2, $[[R16]] 171 } 172 173 define signext i8 @AtomicLoadNand8(i8 signext %incr) nounwind { 174 entry: 175 %0 = atomicrmw nand i8* @y, i8 %incr monotonic 176 ret i8 %0 177 178 ; ALL-LABEL: AtomicLoadNand8: 179 180 ; MIPS32-ANY: lw $[[R0:[0-9]+]], %got(y) 181 ; MIPS64-ANY: ld $[[R0:[0-9]+]], %got_disp(y)( 182 183 ; ALL: addiu $[[R1:[0-9]+]], $zero, -4 184 ; ALL: and $[[R2:[0-9]+]], $[[R0]], $[[R1]] 185 ; ALL: andi $[[R3:[0-9]+]], $[[R0]], 3 186 ; CHECK-EL: sll $[[R5:[0-9]+]], $[[R3]], 3 187 ; CHECK-EB: xori $[[R4:[0-9]+]], $[[R3]], 3 188 ; CHECK-EB: sll $[[R5:[0-9]+]], $[[R4]], 3 189 ; ALL: ori $[[R6:[0-9]+]], $zero, 255 190 ; ALL: sllv $[[R7:[0-9]+]], $[[R6]], $[[R5]] 191 ; ALL: nor $[[R8:[0-9]+]], $zero, $[[R7]] 192 ; ALL: sllv $[[R9:[0-9]+]], $4, $[[R5]] 193 194 ; ALL: $[[BB0:[A-Z_0-9]+]]: 195 ; ALL: ll $[[R10:[0-9]+]], 0($[[R2]]) 196 ; ALL: and $[[R18:[0-9]+]], $[[R10]], $[[R9]] 197 ; ALL: nor $[[R11:[0-9]+]], $zero, $[[R18]] 198 ; ALL: and $[[R12:[0-9]+]], $[[R11]], $[[R7]] 199 ; ALL: and $[[R13:[0-9]+]], $[[R10]], $[[R8]] 200 ; ALL: or $[[R14:[0-9]+]], $[[R13]], $[[R12]] 201 ; ALL: sc $[[R14]], 0($[[R2]]) 202 ; ALL: beqz $[[R14]], $[[BB0]] 203 204 ; ALL: and $[[R15:[0-9]+]], $[[R10]], $[[R7]] 205 ; ALL: srlv $[[R16:[0-9]+]], $[[R15]], $[[R5]] 206 207 ; NO-SEB-SEH: sll $[[R17:[0-9]+]], $[[R16]], 24 208 ; NO-SEB-SEH: sra $2, $[[R17]], 24 209 210 ; HAS-SEB-SEH: seb $2, $[[R16]] 211 } 212 213 define signext i8 @AtomicSwap8(i8 signext %newval) nounwind { 214 entry: 215 %0 = atomicrmw xchg i8* @y, i8 %newval monotonic 216 ret i8 %0 217 218 ; ALL-LABEL: AtomicSwap8: 219 220 ; MIPS32-ANY: lw $[[R0:[0-9]+]], %got(y) 221 ; MIPS64-ANY: ld $[[R0:[0-9]+]], %got_disp(y)( 222 223 ; ALL: addiu $[[R1:[0-9]+]], $zero, -4 224 ; ALL: and $[[R2:[0-9]+]], $[[R0]], $[[R1]] 225 ; ALL: andi $[[R3:[0-9]+]], $[[R0]], 3 226 ; CHECK-EL: sll $[[R5:[0-9]+]], $[[R3]], 3 227 ; CHECK-EB: xori $[[R4:[0-9]+]], $[[R3]], 3 228 ; CHECK-EB: sll $[[R5:[0-9]+]], $[[R4]], 3 229 ; ALL: ori $[[R6:[0-9]+]], $zero, 255 230 ; ALL: sllv $[[R7:[0-9]+]], $[[R6]], $[[R5]] 231 ; ALL: nor $[[R8:[0-9]+]], $zero, $[[R7]] 232 ; ALL: sllv $[[R9:[0-9]+]], $4, $[[R5]] 233 234 ; ALL: $[[BB0:[A-Z_0-9]+]]: 235 ; ALL: ll $[[R10:[0-9]+]], 0($[[R2]]) 236 ; ALL: and $[[R18:[0-9]+]], $[[R9]], $[[R7]] 237 ; ALL: and $[[R13:[0-9]+]], $[[R10]], $[[R8]] 238 ; ALL: or $[[R14:[0-9]+]], $[[R13]], $[[R18]] 239 ; ALL: sc $[[R14]], 0($[[R2]]) 240 ; ALL: beqz $[[R14]], $[[BB0]] 241 242 ; ALL: and $[[R15:[0-9]+]], $[[R10]], $[[R7]] 243 ; ALL: srlv $[[R16:[0-9]+]], $[[R15]], $[[R5]] 244 245 ; NO-SEB-SEH: sll $[[R17:[0-9]+]], $[[R16]], 24 246 ; NO-SEB-SEH: sra $2, $[[R17]], 24 247 248 ; HAS-SEB-SEH: seb $2, $[[R16]] 249 } 250 251 define signext i8 @AtomicCmpSwap8(i8 signext %oldval, i8 signext %newval) nounwind { 252 entry: 253 %pair0 = cmpxchg i8* @y, i8 %oldval, i8 %newval monotonic monotonic 254 %0 = extractvalue { i8, i1 } %pair0, 0 255 ret i8 %0 256 257 ; ALL-LABEL: AtomicCmpSwap8: 258 259 ; MIPS32-ANY: lw $[[R0:[0-9]+]], %got(y) 260 ; MIPS64-ANY: ld $[[R0:[0-9]+]], %got_disp(y)( 261 262 ; ALL: addiu $[[R1:[0-9]+]], $zero, -4 263 ; ALL: and $[[R2:[0-9]+]], $[[R0]], $[[R1]] 264 ; ALL: andi $[[R3:[0-9]+]], $[[R0]], 3 265 ; CHECK-EL: sll $[[R5:[0-9]+]], $[[R3]], 3 266 ; CHECK-EB: xori $[[R4:[0-9]+]], $[[R3]], 3 267 ; CHECK-EB: sll $[[R5:[0-9]+]], $[[R4]], 3 268 ; ALL: ori $[[R6:[0-9]+]], $zero, 255 269 ; ALL: sllv $[[R7:[0-9]+]], $[[R6]], $[[R5]] 270 ; ALL: nor $[[R8:[0-9]+]], $zero, $[[R7]] 271 ; ALL: andi $[[R9:[0-9]+]], $4, 255 272 ; ALL: sllv $[[R10:[0-9]+]], $[[R9]], $[[R5]] 273 ; ALL: andi $[[R11:[0-9]+]], $5, 255 274 ; ALL: sllv $[[R12:[0-9]+]], $[[R11]], $[[R5]] 275 276 ; ALL: $[[BB0:[A-Z_0-9]+]]: 277 ; ALL: ll $[[R13:[0-9]+]], 0($[[R2]]) 278 ; ALL: and $[[R14:[0-9]+]], $[[R13]], $[[R7]] 279 ; ALL: bne $[[R14]], $[[R10]], $[[BB1:[A-Z_0-9]+]] 280 281 ; ALL: and $[[R15:[0-9]+]], $[[R13]], $[[R8]] 282 ; ALL: or $[[R16:[0-9]+]], $[[R15]], $[[R12]] 283 ; ALL: sc $[[R16]], 0($[[R2]]) 284 ; ALL: beqz $[[R16]], $[[BB0]] 285 286 ; ALL: $[[BB1]]: 287 ; ALL: srlv $[[R17:[0-9]+]], $[[R14]], $[[R5]] 288 289 ; NO-SEB-SEH: sll $[[R18:[0-9]+]], $[[R17]], 24 290 ; NO-SEB-SEH: sra $2, $[[R18]], 24 291 292 ; HAS-SEB-SEH: seb $2, $[[R17]] 293 } 294 295 ; Check one i16 so that we cover the seh sign extend 296 @z = common global i16 0, align 1 297 298 define signext i16 @AtomicLoadAdd16(i16 signext %incr) nounwind { 299 entry: 300 %0 = atomicrmw add i16* @z, i16 %incr monotonic 301 ret i16 %0 302 303 ; ALL-LABEL: AtomicLoadAdd16: 304 305 ; MIPS32-ANY: lw $[[R0:[0-9]+]], %got(z) 306 ; MIPS64-ANY: ld $[[R0:[0-9]+]], %got_disp(z)( 307 308 ; ALL: addiu $[[R1:[0-9]+]], $zero, -4 309 ; ALL: and $[[R2:[0-9]+]], $[[R0]], $[[R1]] 310 ; ALL: andi $[[R3:[0-9]+]], $[[R0]], 3 311 ; CHECK-EB: xori $[[R4:[0-9]+]], $[[R3]], 2 312 ; CHECK-EB: sll $[[R5:[0-9]+]], $[[R4]], 3 313 ; CHECK-EL: sll $[[R5:[0-9]+]], $[[R3]], 3 314 ; ALL: ori $[[R6:[0-9]+]], $zero, 65535 315 ; ALL: sllv $[[R7:[0-9]+]], $[[R6]], $[[R5]] 316 ; ALL: nor $[[R8:[0-9]+]], $zero, $[[R7]] 317 ; ALL: sllv $[[R9:[0-9]+]], $4, $[[R5]] 318 319 ; ALL: $[[BB0:[A-Z_0-9]+]]: 320 ; ALL: ll $[[R10:[0-9]+]], 0($[[R2]]) 321 ; ALL: addu $[[R11:[0-9]+]], $[[R10]], $[[R9]] 322 ; ALL: and $[[R12:[0-9]+]], $[[R11]], $[[R7]] 323 ; ALL: and $[[R13:[0-9]+]], $[[R10]], $[[R8]] 324 ; ALL: or $[[R14:[0-9]+]], $[[R13]], $[[R12]] 325 ; ALL: sc $[[R14]], 0($[[R2]]) 326 ; ALL: beqz $[[R14]], $[[BB0]] 327 328 ; ALL: and $[[R15:[0-9]+]], $[[R10]], $[[R7]] 329 ; ALL: srlv $[[R16:[0-9]+]], $[[R15]], $[[R5]] 330 331 ; NO-SEB-SEH: sll $[[R17:[0-9]+]], $[[R16]], 16 332 ; NO-SEB-SEH: sra $2, $[[R17]], 16 333 334 ; MIPS32R2: seh $2, $[[R16]] 335 } 336 337 338 @countsint = common global i32 0, align 4 339 340 define i32 @CheckSync(i32 %v) nounwind noinline { 341 entry: 342 %0 = atomicrmw add i32* @countsint, i32 %v seq_cst 343 ret i32 %0 344 345 ; ALL-LABEL: CheckSync: 346 347 ; ALL: sync 348 ; ALL: ll 349 ; ALL: sc 350 ; ALL: beq 351 ; ALL: sync 352 } 353 354 ; make sure that this assertion in 355 ; TwoAddressInstructionPass::TryInstructionTransform does not fail: 356 ; 357 ; line 1203: assert(TargetRegisterInfo::isVirtualRegister(regB) && 358 ; 359 ; it failed when MipsDAGToDAGISel::ReplaceUsesWithZeroReg replaced an 360 ; operand of an atomic instruction with register $zero. 361 @a = external global i32 362 363 define i32 @zeroreg() nounwind { 364 entry: 365 %pair0 = cmpxchg i32* @a, i32 1, i32 0 seq_cst seq_cst 366 %0 = extractvalue { i32, i1 } %pair0, 0 367 %1 = icmp eq i32 %0, 1 368 %conv = zext i1 %1 to i32 369 ret i32 %conv 370 } 371 372 ; Check that MIPS32R6 has the correct offset range. 373 ; FIXME: At the moment, we don't seem to do addr+offset for any atomic load/store. 374 define i32 @AtomicLoadAdd32_OffGt9Bit(i32 %incr) nounwind { 375 entry: 376 %0 = atomicrmw add i32* getelementptr(i32* @x, i32 256), i32 %incr monotonic 377 ret i32 %0 378 379 ; ALL-LABEL: AtomicLoadAdd32_OffGt9Bit: 380 381 ; MIPS32-ANY: lw $[[R0:[0-9]+]], %got(x) 382 ; MIPS64-ANY: ld $[[R0:[0-9]+]], %got_disp(x)( 383 384 ; ALL: addiu $[[PTR:[0-9]+]], $[[R0]], 1024 385 ; ALL: $[[BB0:[A-Z_0-9]+]]: 386 ; ALL: ll $[[R1:[0-9]+]], 0($[[PTR]]) 387 ; ALL: addu $[[R2:[0-9]+]], $[[R1]], $4 388 ; ALL: sc $[[R2]], 0($[[PTR]]) 389 ; ALL: beqz $[[R2]], $[[BB0]] 390 } 391