llvm.org GIT mirror llvm / b055896
Merging r279933: ------------------------------------------------------------------------ r279933 | hfinkel | 2016-08-28 09:17:58 -0700 (Sun, 28 Aug 2016) | 4 lines [PowerPC] Implement lowering for atomicrmw min/max/umin/umax Implement lowering for atomicrmw min/max/umin/umax. Fixes PR28818. ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_39@287810 91177308-0d34-0410-b5e6-96231b3b80d8 Tom Stellard 2 years ago
5 changed file(s) with 587 addition(s) and 5 deletion(s). Raw diff Collapse all Expand all
83848384 MachineBasicBlock *
83858385 PPCTargetLowering::EmitAtomicBinary(MachineInstr &MI, MachineBasicBlock *BB,
83868386 unsigned AtomicSize,
8387 unsigned BinOpcode) const {
8387 unsigned BinOpcode,
8388 unsigned CmpOpcode,
8389 unsigned CmpPred) const {
83888390 // This also handles ATOMIC_SWAP, indicated by BinOpcode==0.
83898391 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
83908392
84248426 DebugLoc dl = MI.getDebugLoc();
84258427
84268428 MachineBasicBlock *loopMBB = F->CreateMachineBasicBlock(LLVM_BB);
8429 MachineBasicBlock *loop2MBB =
8430 CmpOpcode ? F->CreateMachineBasicBlock(LLVM_BB) : nullptr;
84278431 MachineBasicBlock *exitMBB = F->CreateMachineBasicBlock(LLVM_BB);
84288432 F->insert(It, loopMBB);
8433 if (CmpOpcode)
8434 F->insert(It, loop2MBB);
84298435 F->insert(It, exitMBB);
84308436 exitMBB->splice(exitMBB->begin(), BB,
84318437 std::next(MachineBasicBlock::iterator(MI)), BB->end());
84478453 // st[wd]cx. r0, ptr
84488454 // bne- loopMBB
84498455 // fallthrough --> exitMBB
8456
8457 // For max/min...
8458 // loopMBB:
8459 // l[wd]arx dest, ptr
8460 // cmpl?[wd] incr, dest
8461 // bgt exitMBB
8462 // loop2MBB:
8463 // st[wd]cx. dest, ptr
8464 // bne- loopMBB
8465 // fallthrough --> exitMBB
8466
84508467 BB = loopMBB;
84518468 BuildMI(BB, dl, TII->get(LoadMnemonic), dest)
84528469 .addReg(ptrA).addReg(ptrB);
84538470 if (BinOpcode)
84548471 BuildMI(BB, dl, TII->get(BinOpcode), TmpReg).addReg(incr).addReg(dest);
8472 if (CmpOpcode) {
8473 BuildMI(BB, dl, TII->get(CmpOpcode), PPC::CR0)
8474 .addReg(incr).addReg(dest);
8475 BuildMI(BB, dl, TII->get(PPC::BCC))
8476 .addImm(CmpPred).addReg(PPC::CR0).addMBB(exitMBB);
8477 BB->addSuccessor(loop2MBB);
8478 BB->addSuccessor(exitMBB);
8479 BB = loop2MBB;
8480 }
84558481 BuildMI(BB, dl, TII->get(StoreMnemonic))
84568482 .addReg(TmpReg).addReg(ptrA).addReg(ptrB);
84578483 BuildMI(BB, dl, TII->get(PPC::BCC))
84698495 PPCTargetLowering::EmitPartwordAtomicBinary(MachineInstr &MI,
84708496 MachineBasicBlock *BB,
84718497 bool is8bit, // operation
8472 unsigned BinOpcode) const {
8498 unsigned BinOpcode,
8499 unsigned CmpOpcode,
8500 unsigned CmpPred) const {
84738501 // If we support part-word atomic mnemonics, just use them
84748502 if (Subtarget.hasPartwordAtomics())
8475 return EmitAtomicBinary(MI, BB, is8bit ? 1 : 2, BinOpcode);
8503 return EmitAtomicBinary(MI, BB, is8bit ? 1 : 2, BinOpcode,
8504 CmpOpcode, CmpPred);
84768505
84778506 // This also handles ATOMIC_SWAP, indicated by BinOpcode==0.
84788507 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
84948523 DebugLoc dl = MI.getDebugLoc();
84958524
84968525 MachineBasicBlock *loopMBB = F->CreateMachineBasicBlock(LLVM_BB);
8526 MachineBasicBlock *loop2MBB =
8527 CmpOpcode ? F->CreateMachineBasicBlock(LLVM_BB) : nullptr;
84978528 MachineBasicBlock *exitMBB = F->CreateMachineBasicBlock(LLVM_BB);
84988529 F->insert(It, loopMBB);
8530 if (CmpOpcode)
8531 F->insert(It, loop2MBB);
84998532 F->insert(It, exitMBB);
85008533 exitMBB->splice(exitMBB->begin(), BB,
85018534 std::next(MachineBasicBlock::iterator(MI)), BB->end());
85808613 .addReg(TmpDestReg).addReg(MaskReg);
85818614 BuildMI(BB, dl, TII->get(is64bit ? PPC::AND8 : PPC::AND), Tmp3Reg)
85828615 .addReg(TmpReg).addReg(MaskReg);
8616 if (CmpOpcode) {
8617 // For unsigned comparisons, we can directly compare the shifted values.
8618 // For signed comparisons we shift and sign extend.
8619 unsigned SReg = RegInfo.createVirtualRegister(RC);
8620 BuildMI(BB, dl, TII->get(is64bit ? PPC::AND8 : PPC::AND), SReg)
8621 .addReg(TmpDestReg).addReg(MaskReg);
8622 unsigned ValueReg = SReg;
8623 unsigned CmpReg = Incr2Reg;
8624 if (CmpOpcode == PPC::CMPW) {
8625 ValueReg = RegInfo.createVirtualRegister(RC);
8626 BuildMI(BB, dl, TII->get(PPC::SRW), ValueReg)
8627 .addReg(SReg).addReg(ShiftReg);
8628 unsigned ValueSReg = RegInfo.createVirtualRegister(RC);
8629 BuildMI(BB, dl, TII->get(is8bit ? PPC::EXTSB : PPC::EXTSH), ValueSReg)
8630 .addReg(ValueReg);
8631 ValueReg = ValueSReg;
8632 CmpReg = incr;
8633 }
8634 BuildMI(BB, dl, TII->get(CmpOpcode), PPC::CR0)
8635 .addReg(CmpReg).addReg(ValueReg);
8636 BuildMI(BB, dl, TII->get(PPC::BCC))
8637 .addImm(CmpPred).addReg(PPC::CR0).addMBB(exitMBB);
8638 BB->addSuccessor(loop2MBB);
8639 BB->addSuccessor(exitMBB);
8640 BB = loop2MBB;
8641 }
85838642 BuildMI(BB, dl, TII->get(is64bit ? PPC::OR8 : PPC::OR), Tmp4Reg)
85848643 .addReg(Tmp3Reg).addReg(Tmp2Reg);
85858644 BuildMI(BB, dl, TII->get(PPC::STWCX))
90859144 BB = EmitAtomicBinary(MI, BB, 4, PPC::SUBF);
90869145 else if (MI.getOpcode() == PPC::ATOMIC_LOAD_SUB_I64)
90879146 BB = EmitAtomicBinary(MI, BB, 8, PPC::SUBF8);
9147
9148 else if (MI.getOpcode() == PPC::ATOMIC_LOAD_MIN_I8)
9149 BB = EmitPartwordAtomicBinary(MI, BB, true, 0, PPC::CMPW, PPC::PRED_GE);
9150 else if (MI.getOpcode() == PPC::ATOMIC_LOAD_MIN_I16)
9151 BB = EmitPartwordAtomicBinary(MI, BB, false, 0, PPC::CMPW, PPC::PRED_GE);
9152 else if (MI.getOpcode() == PPC::ATOMIC_LOAD_MIN_I32)
9153 BB = EmitAtomicBinary(MI, BB, 4, 0, PPC::CMPW, PPC::PRED_GE);
9154 else if (MI.getOpcode() == PPC::ATOMIC_LOAD_MIN_I64)
9155 BB = EmitAtomicBinary(MI, BB, 8, 0, PPC::CMPD, PPC::PRED_GE);
9156
9157 else if (MI.getOpcode() == PPC::ATOMIC_LOAD_MAX_I8)
9158 BB = EmitPartwordAtomicBinary(MI, BB, true, 0, PPC::CMPW, PPC::PRED_LE);
9159 else if (MI.getOpcode() == PPC::ATOMIC_LOAD_MAX_I16)
9160 BB = EmitPartwordAtomicBinary(MI, BB, false, 0, PPC::CMPW, PPC::PRED_LE);
9161 else if (MI.getOpcode() == PPC::ATOMIC_LOAD_MAX_I32)
9162 BB = EmitAtomicBinary(MI, BB, 4, 0, PPC::CMPW, PPC::PRED_LE);
9163 else if (MI.getOpcode() == PPC::ATOMIC_LOAD_MAX_I64)
9164 BB = EmitAtomicBinary(MI, BB, 8, 0, PPC::CMPD, PPC::PRED_LE);
9165
9166 else if (MI.getOpcode() == PPC::ATOMIC_LOAD_UMIN_I8)
9167 BB = EmitPartwordAtomicBinary(MI, BB, true, 0, PPC::CMPLW, PPC::PRED_GE);
9168 else if (MI.getOpcode() == PPC::ATOMIC_LOAD_UMIN_I16)
9169 BB = EmitPartwordAtomicBinary(MI, BB, false, 0, PPC::CMPLW, PPC::PRED_GE);
9170 else if (MI.getOpcode() == PPC::ATOMIC_LOAD_UMIN_I32)
9171 BB = EmitAtomicBinary(MI, BB, 4, 0, PPC::CMPLW, PPC::PRED_GE);
9172 else if (MI.getOpcode() == PPC::ATOMIC_LOAD_UMIN_I64)
9173 BB = EmitAtomicBinary(MI, BB, 8, 0, PPC::CMPLD, PPC::PRED_GE);
9174
9175 else if (MI.getOpcode() == PPC::ATOMIC_LOAD_UMAX_I8)
9176 BB = EmitPartwordAtomicBinary(MI, BB, true, 0, PPC::CMPLW, PPC::PRED_LE);
9177 else if (MI.getOpcode() == PPC::ATOMIC_LOAD_UMAX_I16)
9178 BB = EmitPartwordAtomicBinary(MI, BB, false, 0, PPC::CMPLW, PPC::PRED_LE);
9179 else if (MI.getOpcode() == PPC::ATOMIC_LOAD_UMAX_I32)
9180 BB = EmitAtomicBinary(MI, BB, 4, 0, PPC::CMPLW, PPC::PRED_LE);
9181 else if (MI.getOpcode() == PPC::ATOMIC_LOAD_UMAX_I64)
9182 BB = EmitAtomicBinary(MI, BB, 8, 0, PPC::CMPLD, PPC::PRED_LE);
90889183
90899184 else if (MI.getOpcode() == PPC::ATOMIC_SWAP_I8)
90909185 BB = EmitPartwordAtomicBinary(MI, BB, true, 0);
584584 MachineBasicBlock *EmitAtomicBinary(MachineInstr &MI,
585585 MachineBasicBlock *MBB,
586586 unsigned AtomicSize,
587 unsigned BinOpcode) const;
587 unsigned BinOpcode,
588 unsigned CmpOpcode = 0,
589 unsigned CmpPred = 0) const;
588590 MachineBasicBlock *EmitPartwordAtomicBinary(MachineInstr &MI,
589591 MachineBasicBlock *MBB,
590592 bool is8bit,
591 unsigned Opcode) const;
593 unsigned Opcode,
594 unsigned CmpOpcode = 0,
595 unsigned CmpPred = 0) const;
592596
593597 MachineBasicBlock *emitEHSjLjSetJmp(MachineInstr &MI,
594598 MachineBasicBlock *MBB) const;
223223 def ATOMIC_LOAD_NAND_I64 : Pseudo<
224224 (outs g8rc:$dst), (ins memrr:$ptr, g8rc:$incr), "#ATOMIC_LOAD_NAND_I64",
225225 [(set i64:$dst, (atomic_load_nand_64 xoaddr:$ptr, i64:$incr))]>;
226 def ATOMIC_LOAD_MIN_I64 : Pseudo<
227 (outs g8rc:$dst), (ins memrr:$ptr, g8rc:$incr), "#ATOMIC_LOAD_MIN_I64",
228 [(set i64:$dst, (atomic_load_min_64 xoaddr:$ptr, i64:$incr))]>;
229 def ATOMIC_LOAD_MAX_I64 : Pseudo<
230 (outs g8rc:$dst), (ins memrr:$ptr, g8rc:$incr), "#ATOMIC_LOAD_MAX_I64",
231 [(set i64:$dst, (atomic_load_max_64 xoaddr:$ptr, i64:$incr))]>;
232 def ATOMIC_LOAD_UMIN_I64 : Pseudo<
233 (outs g8rc:$dst), (ins memrr:$ptr, g8rc:$incr), "#ATOMIC_LOAD_UMIN_I64",
234 [(set i64:$dst, (atomic_load_umin_64 xoaddr:$ptr, i64:$incr))]>;
235 def ATOMIC_LOAD_UMAX_I64 : Pseudo<
236 (outs g8rc:$dst), (ins memrr:$ptr, g8rc:$incr), "#ATOMIC_LOAD_UMAX_I64",
237 [(set i64:$dst, (atomic_load_umax_64 xoaddr:$ptr, i64:$incr))]>;
226238
227239 def ATOMIC_CMP_SWAP_I64 : Pseudo<
228240 (outs g8rc:$dst), (ins memrr:$ptr, g8rc:$old, g8rc:$new), "#ATOMIC_CMP_SWAP_I64",
15081508 def ATOMIC_LOAD_NAND_I8 : Pseudo<
15091509 (outs gprc:$dst), (ins memrr:$ptr, gprc:$incr), "#ATOMIC_LOAD_NAND_I8",
15101510 [(set i32:$dst, (atomic_load_nand_8 xoaddr:$ptr, i32:$incr))]>;
1511 def ATOMIC_LOAD_MIN_I8 : Pseudo<
1512 (outs gprc:$dst), (ins memrr:$ptr, gprc:$incr), "#ATOMIC_LOAD_MIN_I8",
1513 [(set i32:$dst, (atomic_load_min_8 xoaddr:$ptr, i32:$incr))]>;
1514 def ATOMIC_LOAD_MAX_I8 : Pseudo<
1515 (outs gprc:$dst), (ins memrr:$ptr, gprc:$incr), "#ATOMIC_LOAD_MAX_I8",
1516 [(set i32:$dst, (atomic_load_max_8 xoaddr:$ptr, i32:$incr))]>;
1517 def ATOMIC_LOAD_UMIN_I8 : Pseudo<
1518 (outs gprc:$dst), (ins memrr:$ptr, gprc:$incr), "#ATOMIC_LOAD_UMIN_I8",
1519 [(set i32:$dst, (atomic_load_umin_8 xoaddr:$ptr, i32:$incr))]>;
1520 def ATOMIC_LOAD_UMAX_I8 : Pseudo<
1521 (outs gprc:$dst), (ins memrr:$ptr, gprc:$incr), "#ATOMIC_LOAD_UMAX_I8",
1522 [(set i32:$dst, (atomic_load_umax_8 xoaddr:$ptr, i32:$incr))]>;
15111523 def ATOMIC_LOAD_ADD_I16 : Pseudo<
15121524 (outs gprc:$dst), (ins memrr:$ptr, gprc:$incr), "#ATOMIC_LOAD_ADD_I16",
15131525 [(set i32:$dst, (atomic_load_add_16 xoaddr:$ptr, i32:$incr))]>;
15261538 def ATOMIC_LOAD_NAND_I16 : Pseudo<
15271539 (outs gprc:$dst), (ins memrr:$ptr, gprc:$incr), "#ATOMIC_LOAD_NAND_I16",
15281540 [(set i32:$dst, (atomic_load_nand_16 xoaddr:$ptr, i32:$incr))]>;
1541 def ATOMIC_LOAD_MIN_I16 : Pseudo<
1542 (outs gprc:$dst), (ins memrr:$ptr, gprc:$incr), "#ATOMIC_LOAD_MIN_I16",
1543 [(set i32:$dst, (atomic_load_min_16 xoaddr:$ptr, i32:$incr))]>;
1544 def ATOMIC_LOAD_MAX_I16 : Pseudo<
1545 (outs gprc:$dst), (ins memrr:$ptr, gprc:$incr), "#ATOMIC_LOAD_MAX_I16",
1546 [(set i32:$dst, (atomic_load_max_16 xoaddr:$ptr, i32:$incr))]>;
1547 def ATOMIC_LOAD_UMIN_I16 : Pseudo<
1548 (outs gprc:$dst), (ins memrr:$ptr, gprc:$incr), "#ATOMIC_LOAD_UMIN_I16",
1549 [(set i32:$dst, (atomic_load_umin_16 xoaddr:$ptr, i32:$incr))]>;
1550 def ATOMIC_LOAD_UMAX_I16 : Pseudo<
1551 (outs gprc:$dst), (ins memrr:$ptr, gprc:$incr), "#ATOMIC_LOAD_UMAX_I16",
1552 [(set i32:$dst, (atomic_load_umax_16 xoaddr:$ptr, i32:$incr))]>;
15291553 def ATOMIC_LOAD_ADD_I32 : Pseudo<
15301554 (outs gprc:$dst), (ins memrr:$ptr, gprc:$incr), "#ATOMIC_LOAD_ADD_I32",
15311555 [(set i32:$dst, (atomic_load_add_32 xoaddr:$ptr, i32:$incr))]>;
15441568 def ATOMIC_LOAD_NAND_I32 : Pseudo<
15451569 (outs gprc:$dst), (ins memrr:$ptr, gprc:$incr), "#ATOMIC_LOAD_NAND_I32",
15461570 [(set i32:$dst, (atomic_load_nand_32 xoaddr:$ptr, i32:$incr))]>;
1571 def ATOMIC_LOAD_MIN_I32 : Pseudo<
1572 (outs gprc:$dst), (ins memrr:$ptr, gprc:$incr), "#ATOMIC_LOAD_MIN_I32",
1573 [(set i32:$dst, (atomic_load_min_32 xoaddr:$ptr, i32:$incr))]>;
1574 def ATOMIC_LOAD_MAX_I32 : Pseudo<
1575 (outs gprc:$dst), (ins memrr:$ptr, gprc:$incr), "#ATOMIC_LOAD_MAX_I32",
1576 [(set i32:$dst, (atomic_load_max_32 xoaddr:$ptr, i32:$incr))]>;
1577 def ATOMIC_LOAD_UMIN_I32 : Pseudo<
1578 (outs gprc:$dst), (ins memrr:$ptr, gprc:$incr), "#ATOMIC_LOAD_UMIN_I32",
1579 [(set i32:$dst, (atomic_load_umin_32 xoaddr:$ptr, i32:$incr))]>;
1580 def ATOMIC_LOAD_UMAX_I32 : Pseudo<
1581 (outs gprc:$dst), (ins memrr:$ptr, gprc:$incr), "#ATOMIC_LOAD_UMAX_I32",
1582 [(set i32:$dst, (atomic_load_umax_32 xoaddr:$ptr, i32:$incr))]>;
15471583
15481584 def ATOMIC_CMP_SWAP_I8 : Pseudo<
15491585 (outs gprc:$dst), (ins memrr:$ptr, gprc:$old, gprc:$new), "#ATOMIC_CMP_SWAP_I8",
0 ; RUN: llc < %s | FileCheck %s
1 target datalayout = "E-m:e-i64:64-n32:64"
2 target triple = "powerpc64-unknown-linux-gnu"
3
4 define void @a32min(i32* nocapture dereferenceable(4) %minimum, i32 %val) #0 {
5 entry:
6 %0 = atomicrmw min i32* %minimum, i32 %val monotonic
7 ret void
8
9 ; CHECK-LABEL: @a32min
10 ; CHECK: lwarx [[OLDV:[0-9]+]], 0, 3
11 ; CHECK: cmpw 4, [[OLDV]]
12 ; CHECK: bgelr 0
13 ; CHECK: stwcx. 4, 0, 3
14 ; CHECK: bne 0,
15 ; CHECK: blr
16 }
17
18 define void @a32max(i32* nocapture dereferenceable(4) %minimum, i32 %val) #0 {
19 entry:
20 %0 = atomicrmw max i32* %minimum, i32 %val monotonic
21 ret void
22
23 ; CHECK-LABEL: @a32max
24 ; CHECK: lwarx [[OLDV:[0-9]+]], 0, 3
25 ; CHECK: cmpw 4, [[OLDV]]
26 ; CHECK: blelr 0
27 ; CHECK: stwcx. 4, 0, 3
28 ; CHECK: bne 0,
29 ; CHECK: blr
30 }
31
32 define void @a32umin(i32* nocapture dereferenceable(4) %minimum, i32 %val) #0 {
33 entry:
34 %0 = atomicrmw umin i32* %minimum, i32 %val monotonic
35 ret void
36
37 ; CHECK-LABEL: @a32umin
38 ; CHECK: lwarx [[OLDV:[0-9]+]], 0, 3
39 ; CHECK: cmplw 4, [[OLDV]]
40 ; CHECK: bgelr 0
41 ; CHECK: stwcx. 4, 0, 3
42 ; CHECK: bne 0,
43 ; CHECK: blr
44 }
45
46 define void @a32umax(i32* nocapture dereferenceable(4) %minimum, i32 %val) #0 {
47 entry:
48 %0 = atomicrmw umax i32* %minimum, i32 %val monotonic
49 ret void
50
51 ; CHECK-LABEL: @a32umax
52 ; CHECK: lwarx [[OLDV:[0-9]+]], 0, 3
53 ; CHECK: cmplw 4, [[OLDV]]
54 ; CHECK: blelr 0
55 ; CHECK: stwcx. 4, 0, 3
56 ; CHECK: bne 0,
57 ; CHECK: blr
58 }
59
60 define void @a16min(i16* nocapture dereferenceable(4) %minimum, i16 %val) #1 {
61 entry:
62 %0 = atomicrmw min i16* %minimum, i16 %val monotonic
63 ret void
64
65 ; CHECK-LABEL: @a16min
66 ; CHECK: lharx [[OLDV:[0-9]+]], 0, 3
67 ; CHECK: cmpw 4, [[OLDV]]
68 ; CHECK: bgelr 0
69 ; CHECK: sthcx. 4, 0, 3
70 ; CHECK: bne 0,
71 ; CHECK: blr
72 }
73
74 define void @a16max(i16* nocapture dereferenceable(4) %minimum, i16 %val) #1 {
75 entry:
76 %0 = atomicrmw max i16* %minimum, i16 %val monotonic
77 ret void
78
79 ; CHECK-LABEL: @a16max
80 ; CHECK: lharx [[OLDV:[0-9]+]], 0, 3
81 ; CHECK: cmpw 4, [[OLDV]]
82 ; CHECK: blelr 0
83 ; CHECK: sthcx. 4, 0, 3
84 ; CHECK: bne 0,
85 ; CHECK: blr
86 }
87
88 define void @a16umin(i16* nocapture dereferenceable(4) %minimum, i16 %val) #1 {
89 entry:
90 %0 = atomicrmw umin i16* %minimum, i16 %val monotonic
91 ret void
92
93 ; CHECK-LABEL: @a16umin
94 ; CHECK: lharx [[OLDV:[0-9]+]], 0, 3
95 ; CHECK: cmplw 4, [[OLDV]]
96 ; CHECK: bgelr 0
97 ; CHECK: sthcx. 4, 0, 3
98 ; CHECK: bne 0,
99 ; CHECK: blr
100 }
101
102 define void @a16umax(i16* nocapture dereferenceable(4) %minimum, i16 %val) #1 {
103 entry:
104 %0 = atomicrmw umax i16* %minimum, i16 %val monotonic
105 ret void
106
107 ; CHECK-LABEL: @a16umax
108 ; CHECK: lharx [[OLDV:[0-9]+]], 0, 3
109 ; CHECK: cmplw 4, [[OLDV]]
110 ; CHECK: blelr 0
111 ; CHECK: sthcx. 4, 0, 3
112 ; CHECK: bne 0,
113 ; CHECK: blr
114 }
115
116 define void @a8min(i8* nocapture dereferenceable(4) %minimum, i8 %val) #1 {
117 entry:
118 %0 = atomicrmw min i8* %minimum, i8 %val monotonic
119 ret void
120
121 ; CHECK-LABEL: @a8min
122 ; CHECK: lbarx [[OLDV:[0-9]+]], 0, 3
123 ; CHECK: cmpw 4, [[OLDV]]
124 ; CHECK: bgelr 0
125 ; CHECK: stbcx. 4, 0, 3
126 ; CHECK: bne 0,
127 ; CHECK: blr
128 }
129
130 define void @a8max(i8* nocapture dereferenceable(4) %minimum, i8 %val) #1 {
131 entry:
132 %0 = atomicrmw max i8* %minimum, i8 %val monotonic
133 ret void
134
135 ; CHECK-LABEL: @a8max
136 ; CHECK: lbarx [[OLDV:[0-9]+]], 0, 3
137 ; CHECK: cmpw 4, [[OLDV]]
138 ; CHECK: blelr 0
139 ; CHECK: stbcx. 4, 0, 3
140 ; CHECK: bne 0,
141 ; CHECK: blr
142 }
143
144 define void @a8umin(i8* nocapture dereferenceable(4) %minimum, i8 %val) #1 {
145 entry:
146 %0 = atomicrmw umin i8* %minimum, i8 %val monotonic
147 ret void
148
149 ; CHECK-LABEL: @a8umin
150 ; CHECK: lbarx [[OLDV:[0-9]+]], 0, 3
151 ; CHECK: cmplw 4, [[OLDV]]
152 ; CHECK: bgelr 0
153 ; CHECK: stbcx. 4, 0, 3
154 ; CHECK: bne 0,
155 ; CHECK: blr
156 }
157
158 define void @a8umax(i8* nocapture dereferenceable(4) %minimum, i8 %val) #1 {
159 entry:
160 %0 = atomicrmw umax i8* %minimum, i8 %val monotonic
161 ret void
162
163 ; CHECK-LABEL: @a8umax
164 ; CHECK: lbarx [[OLDV:[0-9]+]], 0, 3
165 ; CHECK: cmplw 4, [[OLDV]]
166 ; CHECK: blelr 0
167 ; CHECK: stbcx. 4, 0, 3
168 ; CHECK: bne 0,
169 ; CHECK: blr
170 }
171
172 define void @a64min(i64* nocapture dereferenceable(4) %minimum, i64 %val) #0 {
173 entry:
174 %0 = atomicrmw min i64* %minimum, i64 %val monotonic
175 ret void
176
177 ; CHECK-LABEL: @a64min
178 ; CHECK: ldarx [[OLDV:[0-9]+]], 0, 3
179 ; CHECK: cmpd 4, [[OLDV]]
180 ; CHECK: bgelr 0
181 ; CHECK: stdcx. 4, 0, 3
182 ; CHECK: bne 0,
183 ; CHECK: blr
184 }
185
186 define void @a64max(i64* nocapture dereferenceable(4) %minimum, i64 %val) #0 {
187 entry:
188 %0 = atomicrmw max i64* %minimum, i64 %val monotonic
189 ret void
190
191 ; CHECK-LABEL: @a64max
192 ; CHECK: ldarx [[OLDV:[0-9]+]], 0, 3
193 ; CHECK: cmpd 4, [[OLDV]]
194 ; CHECK: blelr 0
195 ; CHECK: stdcx. 4, 0, 3
196 ; CHECK: bne 0,
197 ; CHECK: blr
198 }
199
200 define void @a64umin(i64* nocapture dereferenceable(4) %minimum, i64 %val) #0 {
201 entry:
202 %0 = atomicrmw umin i64* %minimum, i64 %val monotonic
203 ret void
204
205 ; CHECK-LABEL: @a64umin
206 ; CHECK: ldarx [[OLDV:[0-9]+]], 0, 3
207 ; CHECK: cmpld 4, [[OLDV]]
208 ; CHECK: bgelr 0
209 ; CHECK: stdcx. 4, 0, 3
210 ; CHECK: bne 0,
211 ; CHECK: blr
212 }
213
214 define void @a64umax(i64* nocapture dereferenceable(4) %minimum, i64 %val) #0 {
215 entry:
216 %0 = atomicrmw umax i64* %minimum, i64 %val monotonic
217 ret void
218
219 ; CHECK-LABEL: @a64umax
220 ; CHECK: ldarx [[OLDV:[0-9]+]], 0, 3
221 ; CHECK: cmpld 4, [[OLDV]]
222 ; CHECK: blelr 0
223 ; CHECK: stdcx. 4, 0, 3
224 ; CHECK: bne 0,
225 ; CHECK: blr
226 }
227
228 define void @ae16min(i16* nocapture dereferenceable(4) %minimum, i16 %val) #0 {
229 entry:
230 %0 = atomicrmw min i16* %minimum, i16 %val monotonic
231 ret void
232
233 ; CHECK-LABEL: @ae16min
234 ; CHECK-DAG: rlwinm [[SA1:[0-9]+]], 3, 3, 27, 27
235 ; CHECK-DAG: li [[M1:[0-9]+]], 0
236 ; CHECK-DAG: rldicr 3, 3, 0, 61
237 ; CHECK-DAG: xori [[SA:[0-9]+]], [[SA1]], 16
238 ; CHECK-DAG: ori [[M2:[0-9]+]], [[M1]], 65535
239 ; CHECK-DAG: slw [[SV:[0-9]+]], 4, [[SA]]
240 ; CHECK-DAG: slw [[M:[0-9]+]], [[M2]], [[SA]]
241 ; CHECK-DAG: and [[SMV:[0-9]+]], [[SV]], [[M]]
242 ; CHECK: lwarx [[OLDV:[0-9]+]], 0, 3
243 ; CHECK: and [[MOLDV:[0-9]+]], [[OLDV]], [[M]]
244 ; CHECK: srw [[SMOLDV:[0-9]+]], [[MOLDV]], [[SA]]
245 ; CHECK: extsh [[SESMOLDV:[0-9]+]], [[SMOLDV]]
246 ; CHECK: cmpw 0, 4, [[SESMOLDV]]
247 ; CHECK: bgelr 0
248 ; CHECK: andc [[NOLDV:[0-9]+]], [[OLDV]], [[M]]
249 ; CHECK: or [[NEWV:[0-9]+]], [[SMV]], [[NOLDV]]
250 ; CHECK: stwcx. [[NEWV]], 0, 3
251 ; CHECK: bne 0,
252 ; CHECK: blr
253 }
254
255 define void @ae16max(i16* nocapture dereferenceable(4) %minimum, i16 %val) #0 {
256 entry:
257 %0 = atomicrmw max i16* %minimum, i16 %val monotonic
258 ret void
259
260 ; CHECK-LABEL: @ae16max
261 ; CHECK-DAG: rlwinm [[SA1:[0-9]+]], 3, 3, 27, 27
262 ; CHECK-DAG: li [[M1:[0-9]+]], 0
263 ; CHECK-DAG: rldicr 3, 3, 0, 61
264 ; CHECK-DAG: xori [[SA:[0-9]+]], [[SA1]], 16
265 ; CHECK-DAG: ori [[M2:[0-9]+]], [[M1]], 65535
266 ; CHECK-DAG: slw [[SV:[0-9]+]], 4, [[SA]]
267 ; CHECK-DAG: slw [[M:[0-9]+]], [[M2]], [[SA]]
268 ; CHECK-DAG: and [[SMV:[0-9]+]], [[SV]], [[M]]
269 ; CHECK: lwarx [[OLDV:[0-9]+]], 0, 3
270 ; CHECK: and [[MOLDV:[0-9]+]], [[OLDV]], [[M]]
271 ; CHECK: srw [[SMOLDV:[0-9]+]], [[MOLDV]], [[SA]]
272 ; CHECK: extsh [[SESMOLDV:[0-9]+]], [[SMOLDV]]
273 ; CHECK: cmpw 0, 4, [[SESMOLDV]]
274 ; CHECK: blelr 0
275 ; CHECK: andc [[NOLDV:[0-9]+]], [[OLDV]], [[M]]
276 ; CHECK: or [[NEWV:[0-9]+]], [[SMV]], [[NOLDV]]
277 ; CHECK: stwcx. [[NEWV]], 0, 3
278 ; CHECK: bne 0,
279 ; CHECK: blr
280 }
281
282 define void @ae16umin(i16* nocapture dereferenceable(4) %minimum, i16 %val) #0 {
283 entry:
284 %0 = atomicrmw umin i16* %minimum, i16 %val monotonic
285 ret void
286
287 ; CHECK-LABEL: @ae16umin
288 ; CHECK-DAG: rlwinm [[SA1:[0-9]+]], 3, 3, 27, 27
289 ; CHECK-DAG: li [[M1:[0-9]+]], 0
290 ; CHECK-DAG: rldicr 3, 3, 0, 61
291 ; CHECK-DAG: xori [[SA:[0-9]+]], [[SA1]], 16
292 ; CHECK-DAG: ori [[M2:[0-9]+]], [[M1]], 65535
293 ; CHECK-DAG: slw [[SV:[0-9]+]], 4, [[SA]]
294 ; CHECK-DAG: slw [[M:[0-9]+]], [[M2]], [[SA]]
295 ; CHECK-DAG: and [[SMV:[0-9]+]], [[SV]], [[M]]
296 ; CHECK: lwarx [[OLDV:[0-9]+]], 0, 3
297 ; CHECK: and [[MOLDV:[0-9]+]], [[OLDV]], [[M]]
298 ; CHECK: cmplw 0, 4, [[MOLDV]]
299 ; CHECK: bgelr 0
300 ; CHECK: andc [[NOLDV:[0-9]+]], [[OLDV]], [[M]]
301 ; CHECK: or [[NEWV:[0-9]+]], [[SMV]], [[NOLDV]]
302 ; CHECK: stwcx. [[NEWV]], 0, 3
303 ; CHECK: bne 0,
304 ; CHECK: blr
305 }
306
307 define void @ae16umax(i16* nocapture dereferenceable(4) %minimum, i16 %val) #0 {
308 entry:
309 %0 = atomicrmw umax i16* %minimum, i16 %val monotonic
310 ret void
311
312 ; CHECK-LABEL: @ae16umax
313 ; CHECK-DAG: rlwinm [[SA1:[0-9]+]], 3, 3, 27, 27
314 ; CHECK-DAG: li [[M1:[0-9]+]], 0
315 ; CHECK-DAG: rldicr 3, 3, 0, 61
316 ; CHECK-DAG: xori [[SA:[0-9]+]], [[SA1]], 16
317 ; CHECK-DAG: ori [[M2:[0-9]+]], [[M1]], 65535
318 ; CHECK-DAG: slw [[SV:[0-9]+]], 4, [[SA]]
319 ; CHECK-DAG: slw [[M:[0-9]+]], [[M2]], [[SA]]
320 ; CHECK-DAG: and [[SMV:[0-9]+]], [[SV]], [[M]]
321 ; CHECK: lwarx [[OLDV:[0-9]+]], 0, 3
322 ; CHECK: and [[MOLDV:[0-9]+]], [[OLDV]], [[M]]
323 ; CHECK: cmplw 0, 4, [[MOLDV]]
324 ; CHECK: blelr 0
325 ; CHECK: andc [[NOLDV:[0-9]+]], [[OLDV]], [[M]]
326 ; CHECK: or [[NEWV:[0-9]+]], [[SMV]], [[NOLDV]]
327 ; CHECK: stwcx. [[NEWV]], 0, 3
328 ; CHECK: bne 0,
329 ; CHECK: blr
330 }
331
332 define void @ae8min(i8* nocapture dereferenceable(4) %minimum, i8 %val) #0 {
333 entry:
334 %0 = atomicrmw min i8* %minimum, i8 %val monotonic
335 ret void
336
337 ; CHECK-LABEL: @ae8min
338 ; CHECK-DAG: rlwinm [[SA1:[0-9]+]], 3, 3, 27, 28
339 ; CHECK-DAG: li [[M1:[0-9]+]], 255
340 ; CHECK-DAG: rldicr 3, 3, 0, 61
341 ; CHECK-DAG: xori [[SA:[0-9]+]], [[SA1]], 24
342 ; CHECK-DAG: slw [[SV:[0-9]+]], 4, [[SA]]
343 ; CHECK-DAG: slw [[M:[0-9]+]], [[M1]], [[SA]]
344 ; CHECK-DAG: and [[SMV:[0-9]+]], [[SV]], [[M]]
345 ; CHECK: lwarx [[OLDV:[0-9]+]], 0, 3
346 ; CHECK: and [[MOLDV:[0-9]+]], [[OLDV]], [[M]]
347 ; CHECK: srw [[SMOLDV:[0-9]+]], [[MOLDV]], [[SA]]
348 ; CHECK: extsb [[SESMOLDV:[0-9]+]], [[SMOLDV]]
349 ; CHECK: cmpw 0, 4, [[SESMOLDV]]
350 ; CHECK: bgelr 0
351 ; CHECK: andc [[NOLDV:[0-9]+]], [[OLDV]], [[M]]
352 ; CHECK: or [[NEWV:[0-9]+]], [[SMV]], [[NOLDV]]
353 ; CHECK: stwcx. [[NEWV]], 0, 3
354 ; CHECK: bne 0,
355 ; CHECK: blr
356 }
357
358 define void @ae8max(i8* nocapture dereferenceable(4) %minimum, i8 %val) #0 {
359 entry:
360 %0 = atomicrmw max i8* %minimum, i8 %val monotonic
361 ret void
362
363 ; CHECK-LABEL: @ae8max
364 ; CHECK-DAG: rlwinm [[SA1:[0-9]+]], 3, 3, 27, 28
365 ; CHECK-DAG: li [[M1:[0-9]+]], 255
366 ; CHECK-DAG: rldicr 3, 3, 0, 61
367 ; CHECK-DAG: xori [[SA:[0-9]+]], [[SA1]], 24
368 ; CHECK-DAG: slw [[SV:[0-9]+]], 4, [[SA]]
369 ; CHECK-DAG: slw [[M:[0-9]+]], [[M1]], [[SA]]
370 ; CHECK-DAG: and [[SMV:[0-9]+]], [[SV]], [[M]]
371 ; CHECK: lwarx [[OLDV:[0-9]+]], 0, 3
372 ; CHECK: and [[MOLDV:[0-9]+]], [[OLDV]], [[M]]
373 ; CHECK: srw [[SMOLDV:[0-9]+]], [[MOLDV]], [[SA]]
374 ; CHECK: extsb [[SESMOLDV:[0-9]+]], [[SMOLDV]]
375 ; CHECK: cmpw 0, 4, [[SESMOLDV]]
376 ; CHECK: blelr 0
377 ; CHECK: andc [[NOLDV:[0-9]+]], [[OLDV]], [[M]]
378 ; CHECK: or [[NEWV:[0-9]+]], [[SMV]], [[NOLDV]]
379 ; CHECK: stwcx. [[NEWV]], 0, 3
380 ; CHECK: bne 0,
381 ; CHECK: blr
382 }
383
384 define void @ae8umin(i8* nocapture dereferenceable(4) %minimum, i8 %val) #0 {
385 entry:
386 %0 = atomicrmw umin i8* %minimum, i8 %val monotonic
387 ret void
388
389 ; CHECK-LABEL: @ae8umin
390 ; CHECK-DAG: rlwinm [[SA1:[0-9]+]], 3, 3, 27, 28
391 ; CHECK-DAG: li [[M1:[0-9]+]], 255
392 ; CHECK-DAG: rldicr 3, 3, 0, 61
393 ; CHECK-DAG: xori [[SA:[0-9]+]], [[SA1]], 24
394 ; CHECK-DAG: slw [[SV:[0-9]+]], 4, [[SA]]
395 ; CHECK-DAG: slw [[M:[0-9]+]], [[M1]], [[SA]]
396 ; CHECK-DAG: and [[SMV:[0-9]+]], [[SV]], [[M]]
397 ; CHECK: lwarx [[OLDV:[0-9]+]], 0, 3
398 ; CHECK: and [[MOLDV:[0-9]+]], [[OLDV]], [[M]]
399 ; CHECK: cmplw 0, 4, [[MOLDV]]
400 ; CHECK: bgelr 0
401 ; CHECK: andc [[NOLDV:[0-9]+]], [[OLDV]], [[M]]
402 ; CHECK: or [[NEWV:[0-9]+]], [[SMV]], [[NOLDV]]
403 ; CHECK: stwcx. [[NEWV]], 0, 3
404 ; CHECK: bne 0,
405 ; CHECK: blr
406 }
407
408 define void @ae8umax(i8* nocapture dereferenceable(4) %minimum, i8 %val) #0 {
409 entry:
410 %0 = atomicrmw umax i8* %minimum, i8 %val monotonic
411 ret void
412
413 ; CHECK-LABEL: @ae8umax
414 ; CHECK-DAG: rlwinm [[SA1:[0-9]+]], 3, 3, 27, 28
415 ; CHECK-DAG: li [[M1:[0-9]+]], 255
416 ; CHECK-DAG: rldicr 3, 3, 0, 61
417 ; CHECK-DAG: xori [[SA:[0-9]+]], [[SA1]], 24
418 ; CHECK-DAG: slw [[SV:[0-9]+]], 4, [[SA]]
419 ; CHECK-DAG: slw [[M:[0-9]+]], [[M1]], [[SA]]
420 ; CHECK-DAG: and [[SMV:[0-9]+]], [[SV]], [[M]]
421 ; CHECK: lwarx [[OLDV:[0-9]+]], 0, 3
422 ; CHECK: and [[MOLDV:[0-9]+]], [[OLDV]], [[M]]
423 ; CHECK: cmplw 0, 4, [[MOLDV]]
424 ; CHECK: blelr 0
425 ; CHECK: andc [[NOLDV:[0-9]+]], [[OLDV]], [[M]]
426 ; CHECK: or [[NEWV:[0-9]+]], [[SMV]], [[NOLDV]]
427 ; CHECK: stwcx. [[NEWV]], 0, 3
428 ; CHECK: bne 0,
429 ; CHECK: blr
430 }
431
432 attributes #0 = { nounwind "target-cpu"="ppc64" }
433 attributes #1 = { nounwind "target-cpu"="pwr8" }
434