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 15define i32 @AtomicLoadAdd32(i32 %incr) nounwind { 16entry: 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 32define i32 @AtomicLoadNand32(i32 %incr) nounwind { 33entry: 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 50define i32 @AtomicSwap32(i32 %newval) nounwind { 51entry: 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 69define i32 @AtomicCmpSwap32(i32 %oldval, i32 %newval) nounwind { 70entry: 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 95define signext i8 @AtomicLoadAdd8(i8 signext %incr) nounwind { 96entry: 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 134define signext i8 @AtomicLoadSub8(i8 signext %incr) nounwind { 135entry: 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 173define signext i8 @AtomicLoadNand8(i8 signext %incr) nounwind { 174entry: 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 213define signext i8 @AtomicSwap8(i8 signext %newval) nounwind { 214entry: 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 251define signext i8 @AtomicCmpSwap8(i8 signext %oldval, i8 signext %newval) nounwind { 252entry: 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 298define signext i16 @AtomicLoadAdd16(i16 signext %incr) nounwind { 299entry: 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 340define i32 @CheckSync(i32 %v) nounwind noinline { 341entry: 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 363define i32 @zeroreg() nounwind { 364entry: 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. 374define i32 @AtomicLoadAdd32_OffGt9Bit(i32 %incr) nounwind { 375entry: 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