const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
DebugLoc dl = MI->getDebugLoc();
- unsigned Dest = MI->getOperand(0).getReg();
+ unsigned Oldval = MI->getOperand(0).getReg();
unsigned Ptr = MI->getOperand(1).getReg();
unsigned Incr = MI->getOperand(2).getReg();
- unsigned Oldval = RegInfo.createVirtualRegister(RC);
unsigned Tmp1 = RegInfo.createVirtualRegister(RC);
unsigned Tmp2 = RegInfo.createVirtualRegister(RC);
unsigned Tmp3 = RegInfo.createVirtualRegister(RC);
// thisMBB:
// ...
- // sw incr, fi(sp) // store incr to stack (when BinOpcode == 0)
// fallthrough --> loopMBB
-
- // Note: for atomic.swap (when BinOpcode == 0), storing incr to stack before
- // the loop and then loading it from stack in block loopMBB is necessary to
- // prevent MachineLICM pass to hoist "or" instruction out of the block
- // loopMBB.
-
- int fi = 0;
- if (BinOpcode == 0 && !Nand) {
- // Get or create a temporary stack location.
- MipsFunctionInfo *MipsFI = MF->getInfo<MipsFunctionInfo>();
- fi = MipsFI->getAtomicFrameIndex();
- if (fi == -1) {
- fi = MF->getFrameInfo()->CreateStackObject(Size, Size, false);
- MipsFI->setAtomicFrameIndex(fi);
- }
-
- BuildMI(BB, dl, TII->get(Mips::SW))
- .addReg(Incr).addFrameIndex(fi).addImm(0);
- }
BB->addSuccessor(loopMBB);
// loopMBB:
// ll oldval, 0(ptr)
- // or dest, $0, oldval
// <binop> tmp1, oldval, incr
// sc tmp1, 0(ptr)
// beq tmp1, $0, loopMBB
BB = loopMBB;
BuildMI(BB, dl, TII->get(Mips::LL), Oldval).addReg(Ptr).addImm(0);
- BuildMI(BB, dl, TII->get(Mips::OR), Dest).addReg(Mips::ZERO).addReg(Oldval);
if (Nand) {
// and tmp2, oldval, incr
// nor tmp1, $0, tmp2
// <binop> tmp1, oldval, incr
BuildMI(BB, dl, TII->get(BinOpcode), Tmp1).addReg(Oldval).addReg(Incr);
} else {
- // lw tmp2, fi(sp) // load incr from stack
- // or tmp1, $zero, tmp2
- BuildMI(BB, dl, TII->get(Mips::LW), Tmp2).addFrameIndex(fi).addImm(0);
- BuildMI(BB, dl, TII->get(Mips::OR), Tmp1).addReg(Mips::ZERO).addReg(Tmp2);
+ Tmp1 = Incr;
}
BuildMI(BB, dl, TII->get(Mips::SC), Tmp3).addReg(Tmp1).addReg(Ptr).addImm(0);
BuildMI(BB, dl, TII->get(Mips::BEQ))
// nor mask2,$0,mask
// andi tmp4,incr,255
// sll incr2,tmp4,shift
- // sw incr2, fi(sp) // store incr2 to stack (when BinOpcode == 0)
-
- // Note: for atomic.swap (when BinOpcode == 0), storing incr2 to stack before
- // the loop and then loading it from stack in block loopMBB is necessary to
- // prevent MachineLICM pass to hoist "or" instruction out of the block
- // loopMBB.
int64_t MaskImm = (Size == 1) ? 255 : 65535;
BuildMI(BB, dl, TII->get(Mips::ADDiu), Tmp1).addReg(Mips::ZERO).addImm(-4);
BuildMI(BB, dl, TII->get(Mips::SLL), Incr2).addReg(Tmp5).addReg(Shift);
}
- int fi = 0;
- if (BinOpcode == 0 && !Nand) {
- // Get or create a temporary stack location.
- MipsFunctionInfo *MipsFI = MF->getInfo<MipsFunctionInfo>();
- fi = MipsFI->getAtomicFrameIndex();
- if (fi == -1) {
- fi = MF->getFrameInfo()->CreateStackObject(Size, Size, false);
- MipsFI->setAtomicFrameIndex(fi);
- }
-
- BuildMI(BB, dl, TII->get(Mips::SW))
- .addReg(Incr2).addFrameIndex(fi).addImm(0);
- }
BB->addSuccessor(loopMBB);
+ // atomic.load.binop
// loopMBB:
// ll oldval,0(addr)
// binop tmp7,oldval,incr2
// or tmp9,tmp8,newval
// sc tmp9,0(addr)
// beq tmp9,$0,loopMBB
+
+ // atomic.swap
+ // loopMBB:
+ // ll oldval,0(addr)
+ // and tmp8,oldval,mask2
+ // or tmp9,tmp8,incr2
+ // sc tmp9,0(addr)
+ // beq tmp9,$0,loopMBB
+
BB = loopMBB;
BuildMI(BB, dl, TII->get(Mips::LL), Oldval).addReg(Addr).addImm(0);
if (Nand) {
} else if (BinOpcode) {
// <binop> tmp7, oldval, incr2
BuildMI(BB, dl, TII->get(BinOpcode), Tmp7).addReg(Oldval).addReg(Incr2);
- } else {
- // lw tmp6, fi(sp) // load incr2 from stack
- // or tmp7, $zero, tmp6
- BuildMI(BB, dl, TII->get(Mips::LW), Tmp6).addFrameIndex(fi).addImm(0);
- BuildMI(BB, dl, TII->get(Mips::OR), Tmp7).addReg(Mips::ZERO).addReg(Tmp6);
}
- BuildMI(BB, dl, TII->get(Mips::AND), Newval).addReg(Tmp7).addReg(Mask);
+ if (BinOpcode != 0 || Nand)
+ BuildMI(BB, dl, TII->get(Mips::AND), Newval).addReg(Tmp7).addReg(Mask);
BuildMI(BB, dl, TII->get(Mips::AND), Tmp8).addReg(Oldval).addReg(Mask2);
- BuildMI(BB, dl, TII->get(Mips::OR), Tmp9).addReg(Tmp8).addReg(Newval);
+ if (BinOpcode != 0 || Nand)
+ BuildMI(BB, dl, TII->get(Mips::OR), Tmp9).addReg(Tmp8).addReg(Newval);
+ else
+ BuildMI(BB, dl, TII->get(Mips::OR), Tmp9).addReg(Tmp8).addReg(Incr2);
BuildMI(BB, dl, TII->get(Mips::SC), Tmp13)
.addReg(Tmp9).addReg(Addr).addImm(0);
BuildMI(BB, dl, TII->get(Mips::BEQ))
unsigned Newval = MI->getOperand(3).getReg();
unsigned Tmp1 = RegInfo.createVirtualRegister(RC);
- unsigned Tmp2 = RegInfo.createVirtualRegister(RC);
unsigned Tmp3 = RegInfo.createVirtualRegister(RC);
// insert new blocks after the current block
BB->end());
exitMBB->transferSuccessorsAndUpdatePHIs(BB);
- // Get or create a temporary stack location.
- MipsFunctionInfo *MipsFI = MF->getInfo<MipsFunctionInfo>();
- int fi = MipsFI->getAtomicFrameIndex();
- if (fi == -1) {
- fi = MF->getFrameInfo()->CreateStackObject(Size, Size, false);
- MipsFI->setAtomicFrameIndex(fi);
- }
-
// thisMBB:
// ...
- // sw newval, fi(sp) // store newval to stack
// fallthrough --> loop1MBB
-
- // Note: storing newval to stack before the loop and then loading it from
- // stack in block loop2MBB is necessary to prevent MachineLICM pass to
- // hoist "or" instruction out of the block loop2MBB.
-
- BuildMI(BB, dl, TII->get(Mips::SW))
- .addReg(Newval).addFrameIndex(fi).addImm(0);
BB->addSuccessor(loop1MBB);
// loop1MBB:
BB->addSuccessor(loop2MBB);
// loop2MBB:
- // lw tmp2, fi(sp) // load newval from stack
- // or tmp1, $0, tmp2
+ // or tmp1, $0, newval
// sc tmp1, 0(ptr)
// beq tmp1, $0, loop1MBB
BB = loop2MBB;
- BuildMI(BB, dl, TII->get(Mips::LW), Tmp2).addFrameIndex(fi).addImm(0);
- BuildMI(BB, dl, TII->get(Mips::OR), Tmp1).addReg(Mips::ZERO).addReg(Tmp2);
+ BuildMI(BB, dl, TII->get(Mips::OR), Tmp1).addReg(Mips::ZERO).addReg(Newval);
BuildMI(BB, dl, TII->get(Mips::SC), Tmp3).addReg(Tmp1).addReg(Ptr).addImm(0);
BuildMI(BB, dl, TII->get(Mips::BEQ))
.addReg(Tmp3).addReg(Mips::ZERO).addMBB(loop1MBB);
; CHECK: lw $[[R0:[0-9]+]], %got(x)($gp)
; CHECK: $[[BB0:[A-Z_0-9]+]]:
; CHECK: ll $[[R1:[0-9]+]], 0($[[R0]])
-; CHECK: or $2, $zero, $[[R1]]
; CHECK: addu $[[R2:[0-9]+]], $[[R1]], $4
; CHECK: sc $[[R2]], 0($[[R0]])
; CHECK: beq $[[R2]], $zero, $[[BB0]]
; CHECK: lw $[[R0:[0-9]+]], %got(x)($gp)
; CHECK: $[[BB0:[A-Z_0-9]+]]:
; CHECK: ll $[[R1:[0-9]+]], 0($[[R0]])
-; CHECK: or $2, $zero, $[[R1]]
-; CHECK: and $[[R1]], $[[R1]], $4
-; CHECK: nor $[[R2:[0-9]+]], $zero, $[[R1]]
+; CHECK: and $[[R3:[0-9]+]], $[[R1]], $4
+; CHECK: nor $[[R2:[0-9]+]], $zero, $[[R3]]
; CHECK: sc $[[R2]], 0($[[R0]])
; CHECK: beq $[[R2]], $zero, $[[BB0]]
}
-define i32 @AtomicSwap32(i32 %oldval) nounwind {
+define i32 @AtomicSwap32(i32 %newval) nounwind {
entry:
- %0 = call i32 @llvm.atomic.swap.i32.p0i32(i32* @x, i32 %oldval)
+ %newval.addr = alloca i32, align 4
+ store i32 %newval, i32* %newval.addr, align 4
+ %tmp = load i32* %newval.addr, align 4
+ %0 = call i32 @llvm.atomic.swap.i32.p0i32(i32* @x, i32 %tmp)
ret i32 %0
; CHECK: AtomicSwap32:
; CHECK: lw $[[R0:[0-9]+]], %got(x)($gp)
-; CHECK: sw $4, [[OFFSET:[0-9]+]]($sp)
; CHECK: $[[BB0:[A-Z_0-9]+]]:
-; CHECK: ll $[[R1:[0-9]+]], 0($[[R0]])
-; CHECK: or $2, $zero, $[[R1]]
-; CHECK: lw $[[R2:[0-9]+]], [[OFFSET]]($sp)
-; CHECK: or $[[R3:[0-9]+]], $zero, $[[R2]]
-; CHECK: sc $[[R3]], 0($[[R0]])
-; CHECK: beq $[[R3]], $zero, $[[BB0]]
+; CHECK: ll ${{[0-9]+}}, 0($[[R0]])
+; CHECK: sc $[[R2:[0-9]+]], 0($[[R0]])
+; CHECK: beq $[[R2]], $zero, $[[BB0]]
}
define i32 @AtomicCmpSwap32(i32 %oldval, i32 %newval) nounwind {
entry:
- %0 = call i32 @llvm.atomic.cmp.swap.i32.p0i32(i32* @x, i32 %oldval, i32 %newval)
+ %newval.addr = alloca i32, align 4
+ store i32 %newval, i32* %newval.addr, align 4
+ %tmp = load i32* %newval.addr, align 4
+ %0 = call i32 @llvm.atomic.cmp.swap.i32.p0i32(i32* @x, i32 %oldval, i32 %tmp)
ret i32 %0
; CHECK: AtomicCmpSwap32:
; CHECK: lw $[[R0:[0-9]+]], %got(x)($gp)
-; CHECK: sw $5, [[OFFSET:[0-9]+]]($sp)
; CHECK: $[[BB0:[A-Z_0-9]+]]:
; CHECK: ll $2, 0($[[R0]])
; CHECK: bne $2, $4, $[[BB1:[A-Z_0-9]+]]
-; CHECK: lw $[[R1:[0-9]+]], [[OFFSET]]($sp)
-; CHECK: or $[[R2:[0-9]+]], $zero, $[[R1]]
+; CHECK: or $[[R2:[0-9]+]], $zero, $5
; CHECK: sc $[[R2]], 0($[[R0]])
; CHECK: beq $[[R2]], $zero, $[[BB0]]
; CHECK: $[[BB1]]:
; CHECK: sra $2, $[[R17]], 24
}
-define signext i8 @AtomicSwap8(i8 signext %oldval) nounwind {
+define signext i8 @AtomicSwap8(i8 signext %newval) nounwind {
entry:
- %0 = call i8 @llvm.atomic.swap.i8.p0i8(i8* @y, i8 %oldval)
+ %0 = call i8 @llvm.atomic.swap.i8.p0i8(i8* @y, i8 %newval)
ret i8 %0
; CHECK: AtomicSwap8:
; CHECK: nor $[[R7:[0-9]+]], $zero, $[[R6]]
; CHECK: andi $[[R8:[0-9]+]], $4, 255
; CHECK: sll $[[R9:[0-9]+]], $[[R8]], $[[R4]]
-; CHECK: sw $[[R9]], [[OFFSET:[0-9]+]]($sp)
; CHECK: $[[BB0:[A-Z_0-9]+]]:
; CHECK: ll $[[R10:[0-9]+]], 0($[[R2]])
-; CHECK: lw $[[R18:[0-9]+]], [[OFFSET]]($sp)
-; CHECK: or $[[R11:[0-9]+]], $zero, $[[R18]]
-; CHECK: and $[[R12:[0-9]+]], $[[R11]], $[[R6]]
; CHECK: and $[[R13:[0-9]+]], $[[R10]], $[[R7]]
-; CHECK: or $[[R14:[0-9]+]], $[[R13]], $[[R12]]
+; CHECK: or $[[R14:[0-9]+]], $[[R13]], $[[R9]]
; CHECK: sc $[[R14]], 0($[[R2]])
; CHECK: beq $[[R14]], $zero, $[[BB0]]