return CurDAG->getTargetConstant(Imm, Node->getValueType(0));
}
+ const SystemZTargetMachine &getTargetMachine() const {
+ return static_cast<const SystemZTargetMachine &>(TM);
+ }
+
+ const SystemZInstrInfo *getInstrInfo() const {
+ return getTargetMachine().getInstrInfo();
+ }
+
// Try to fold more of the base or index of AM into AM, where IsBase
// selects between the base and index.
bool expandAddress(SystemZAddressingMode &AM, bool IsBase);
// set Op to that Y.
bool detectOrAndInsertion(SDValue &Op, uint64_t InsertMask);
+ // Try to update RxSBG so that only the bits of RxSBG.Input in Mask are used.
+ // Return true on success.
+ bool refineRxSBGMask(RxSBGOperands &RxSBG, uint64_t Mask);
+
// Try to fold some of RxSBG.Input into other fields of RxSBG.
// Return true on success.
bool expandRxSBG(RxSBGOperands &RxSBG);
return true;
}
-// Return true if Mask matches the regexp 0*1+0*, given that zero masks
-// have already been filtered out. Store the first set bit in LSB and
-// the number of set bits in Length if so.
-static bool isStringOfOnes(uint64_t Mask, unsigned &LSB, unsigned &Length) {
- unsigned First = findFirstSet(Mask);
- uint64_t Top = (Mask >> First) + 1;
- if ((Top & -Top) == Top) {
- LSB = First;
- Length = findFirstSet(Top);
- return true;
- }
- return false;
-}
-
-// Try to update RxSBG so that only the bits of RxSBG.Input in Mask are used.
-// Return true on success.
-static bool refineRxSBGMask(RxSBGOperands &RxSBG, uint64_t Mask) {
+bool SystemZDAGToDAGISel::refineRxSBGMask(RxSBGOperands &RxSBG, uint64_t Mask) {
+ const SystemZInstrInfo *TII = getInstrInfo();
if (RxSBG.Rotate != 0)
Mask = (Mask << RxSBG.Rotate) | (Mask >> (64 - RxSBG.Rotate));
Mask &= RxSBG.Mask;
-
- // Reject trivial all-zero masks.
- if (Mask == 0)
- return false;
-
- // Handle the 1+0+ or 0+1+0* cases. Start then specifies the index of
- // the msb and End specifies the index of the lsb.
- unsigned LSB, Length;
- if (isStringOfOnes(Mask, LSB, Length)) {
- RxSBG.Mask = Mask;
- RxSBG.Start = 63 - (LSB + Length - 1);
- RxSBG.End = 63 - LSB;
- return true;
- }
-
- // Handle the wrap-around 1+0+1+ cases. Start then specifies the msb
- // of the low 1s and End specifies the lsb of the high 1s.
- if (isStringOfOnes(Mask ^ allOnes(RxSBG.BitSize), LSB, Length)) {
- assert(LSB > 0 && "Bottom bit must be set");
- assert(LSB + Length < RxSBG.BitSize && "Top bit must be set");
+ if (TII->isRxSBGMask(Mask, RxSBG.BitSize, RxSBG.Start, RxSBG.End)) {
RxSBG.Mask = Mask;
- RxSBG.Start = 63 - (LSB - 1);
- RxSBG.End = 63 - (LSB + Length);
return true;
}
-
return false;
}
}
SDNode *SystemZDAGToDAGISel::tryRISBGZero(SDNode *N) {
+ EVT VT = N->getValueType(0);
RxSBGOperands RISBG(SystemZ::RISBG, SDValue(N, 0));
unsigned Count = 0;
while (expandRxSBG(RISBG))
Count += 1;
- // Prefer to use normal shift instructions over RISBG, since they can handle
- // all cases and are sometimes shorter. Prefer to use RISBG for ANDs though,
- // since it is effectively a three-operand instruction in this case,
- // and since it can handle some masks that AND IMMEDIATE can't.
- if (Count < (N->getOpcode() == ISD::AND ? 1U : 2U))
- return 0;
-
- // Prefer register extensions like LLC over RISBG.
- if (RISBG.Rotate == 0 &&
- (RISBG.Start == 32 || RISBG.Start == 48 || RISBG.Start == 56) &&
- RISBG.End == 63)
+ if (Count == 0)
return 0;
+ if (Count == 1) {
+ // Prefer to use normal shift instructions over RISBG, since they can handle
+ // all cases and are sometimes shorter.
+ if (N->getOpcode() != ISD::AND)
+ return 0;
+
+ // Prefer register extensions like LLC over RISBG. Also prefer to start
+ // out with normal ANDs if one instruction would be enough. We can convert
+ // these ANDs into an RISBG later if a three-address instruction is useful.
+ if (VT == MVT::i32 ||
+ RISBG.Mask == 0xff ||
+ RISBG.Mask == 0xffff ||
+ SystemZ::isImmLF(~RISBG.Mask) ||
+ SystemZ::isImmHF(~RISBG.Mask)) {
+ // Force the new mask into the DAG, since it may include known-one bits.
+ ConstantSDNode *MaskN = cast<ConstantSDNode>(N->getOperand(1).getNode());
+ if (MaskN->getZExtValue() != RISBG.Mask) {
+ SDValue NewMask = CurDAG->getConstant(RISBG.Mask, VT);
+ N = CurDAG->UpdateNodeOperands(N, N->getOperand(0), NewMask);
+ return SelectCode(N);
+ }
+ return 0;
+ }
+ }
- EVT VT = N->getValueType(0);
SDValue Ops[5] = {
getUNDEF64(SDLoc(N)),
convertTo(SDLoc(N), MVT::i64, RISBG.Input),
using namespace llvm;
+// Return a mask with Count low bits set.
+static uint64_t allOnes(unsigned int Count) {
+ return Count == 0 ? 0 : (uint64_t(1) << (Count - 1) << 1) - 1;
+}
+
SystemZInstrInfo::SystemZInstrInfo(SystemZTargetMachine &tm)
: SystemZGenInstrInfo(SystemZ::ADJCALLSTACKDOWN, SystemZ::ADJCALLSTACKUP),
RI(tm), TM(tm) {
MI->getOperand(3).getReg() == 0);
}
+namespace {
+ struct LogicOp {
+ LogicOp() : RegSize(0), ImmLSB(0), ImmSize(0) {}
+ LogicOp(unsigned regSize, unsigned immLSB, unsigned immSize)
+ : RegSize(regSize), ImmLSB(immLSB), ImmSize(immSize) {}
+
+ operator bool() const { return RegSize; }
+
+ unsigned RegSize, ImmLSB, ImmSize;
+ };
+}
+
+static LogicOp interpretAndImmediate(unsigned Opcode) {
+ switch (Opcode) {
+ case SystemZ::NILL32: return LogicOp(32, 0, 16);
+ case SystemZ::NILH32: return LogicOp(32, 16, 16);
+ case SystemZ::NILL: return LogicOp(64, 0, 16);
+ case SystemZ::NILH: return LogicOp(64, 16, 16);
+ case SystemZ::NIHL: return LogicOp(64, 32, 16);
+ case SystemZ::NIHH: return LogicOp(64, 48, 16);
+ case SystemZ::NILF32: return LogicOp(32, 0, 32);
+ case SystemZ::NILF: return LogicOp(64, 0, 32);
+ case SystemZ::NIHF: return LogicOp(64, 32, 32);
+ default: return LogicOp();
+ }
+}
+
+// Used to return from convertToThreeAddress after replacing two-address
+// instruction OldMI with three-address instruction NewMI.
+static MachineInstr *finishConvertToThreeAddress(MachineInstr *OldMI,
+ MachineInstr *NewMI,
+ LiveVariables *LV) {
+ if (LV) {
+ unsigned NumOps = OldMI->getNumOperands();
+ for (unsigned I = 1; I < NumOps; ++I) {
+ MachineOperand &Op = OldMI->getOperand(I);
+ if (Op.isReg() && Op.isKill())
+ LV->replaceKillInstruction(Op.getReg(), OldMI, NewMI);
+ }
+ }
+ return NewMI;
+}
+
MachineInstr *
SystemZInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
MachineBasicBlock::iterator &MBBI,
if (TM.getSubtargetImpl()->hasDistinctOps()) {
int ThreeOperandOpcode = SystemZ::getThreeOperandOpcode(Opcode);
if (ThreeOperandOpcode >= 0) {
- unsigned DestReg = MI->getOperand(0).getReg();
+ MachineOperand &Dest = MI->getOperand(0);
MachineOperand &Src = MI->getOperand(1);
- MachineInstrBuilder MIB = BuildMI(*MBB, MBBI, MI->getDebugLoc(),
- get(ThreeOperandOpcode), DestReg);
+ MachineInstrBuilder MIB =
+ BuildMI(*MBB, MBBI, MI->getDebugLoc(), get(ThreeOperandOpcode))
+ .addOperand(Dest);
// Keep the kill state, but drop the tied flag.
- MIB.addReg(Src.getReg(), getKillRegState(Src.isKill()));
+ MIB.addReg(Src.getReg(), getKillRegState(Src.isKill()), Src.getSubReg());
// Keep the remaining operands as-is.
for (unsigned I = 2; I < NumOps; ++I)
MIB.addOperand(MI->getOperand(I));
- MachineInstr *NewMI = MIB;
-
- // Transfer killing information to the new instruction.
- if (LV) {
- for (unsigned I = 1; I < NumOps; ++I) {
- MachineOperand &Op = MI->getOperand(I);
- if (Op.isReg() && Op.isKill())
- LV->replaceKillInstruction(Op.getReg(), MI, NewMI);
+ return finishConvertToThreeAddress(MI, MIB, LV);
+ }
+ }
+
+ // Try to convert an AND into an RISBG-type instruction.
+ if (LogicOp And = interpretAndImmediate(Opcode)) {
+ unsigned NewOpcode;
+ if (And.RegSize == 64)
+ NewOpcode = SystemZ::RISBG;
+ else if (TM.getSubtargetImpl()->hasHighWord())
+ NewOpcode = SystemZ::RISBLG32;
+ else
+ // We can't use RISBG for 32-bit operations because it clobbers the
+ // high word of the destination too.
+ NewOpcode = 0;
+ if (NewOpcode) {
+ uint64_t Imm = MI->getOperand(2).getImm() << And.ImmLSB;
+ // AND IMMEDIATE leaves the other bits of the register unchanged.
+ Imm |= allOnes(And.RegSize) & ~(allOnes(And.ImmSize) << And.ImmLSB);
+ unsigned Start, End;
+ if (isRxSBGMask(Imm, And.RegSize, Start, End)) {
+ if (NewOpcode == SystemZ::RISBLG32) {
+ Start &= 31;
+ End &= 31;
}
+ MachineOperand &Dest = MI->getOperand(0);
+ MachineOperand &Src = MI->getOperand(1);
+ MachineInstrBuilder MIB =
+ BuildMI(*MBB, MI, MI->getDebugLoc(), get(NewOpcode))
+ .addOperand(Dest).addReg(0)
+ .addReg(Src.getReg(), getKillRegState(Src.isKill()), Src.getSubReg())
+ .addImm(Start).addImm(End + 128).addImm(0);
+ return finishConvertToThreeAddress(MI, MIB, LV);
}
- return MIB;
}
}
return 0;
return 0;
}
+// Return true if Mask matches the regexp 0*1+0*, given that zero masks
+// have already been filtered out. Store the first set bit in LSB and
+// the number of set bits in Length if so.
+static bool isStringOfOnes(uint64_t Mask, unsigned &LSB, unsigned &Length) {
+ unsigned First = findFirstSet(Mask);
+ uint64_t Top = (Mask >> First) + 1;
+ if ((Top & -Top) == Top) {
+ LSB = First;
+ Length = findFirstSet(Top);
+ return true;
+ }
+ return false;
+}
+
+bool SystemZInstrInfo::isRxSBGMask(uint64_t Mask, unsigned BitSize,
+ unsigned &Start, unsigned &End) const {
+ // Reject trivial all-zero masks.
+ if (Mask == 0)
+ return false;
+
+ // Handle the 1+0+ or 0+1+0* cases. Start then specifies the index of
+ // the msb and End specifies the index of the lsb.
+ unsigned LSB, Length;
+ if (isStringOfOnes(Mask, LSB, Length)) {
+ Start = 63 - (LSB + Length - 1);
+ End = 63 - LSB;
+ return true;
+ }
+
+ // Handle the wrap-around 1+0+1+ cases. Start then specifies the msb
+ // of the low 1s and End specifies the lsb of the high 1s.
+ if (isStringOfOnes(Mask ^ allOnes(BitSize), LSB, Length)) {
+ assert(LSB > 0 && "Bottom bit must be set");
+ assert(LSB + Length < BitSize && "Top bit must be set");
+ Start = 63 - (LSB - 1);
+ End = 63 - (LSB + Length);
+ return true;
+ }
+
+ return false;
+}
+
unsigned SystemZInstrInfo::getCompareAndBranch(unsigned Opcode,
const MachineInstr *MI) const {
switch (Opcode) {
// exists.
unsigned getOpcodeForOffset(unsigned Opcode, int64_t Offset) const;
+ // Return true if ROTATE AND ... SELECTED BITS can be used to select bits
+ // Mask of the R2 operand, given that only the low BitSize bits of Mask are
+ // significant. Set Start and End to the I3 and I4 operands if so.
+ bool isRxSBGMask(uint64_t Mask, unsigned BitSize,
+ unsigned &Start, unsigned &End) const;
+
// If Opcode is a COMPARE opcode for which an associated COMPARE AND
// BRANCH exists, return the opcode for the latter, otherwise return 0.
// MI, if nonnull, is the compare instruction.
defm NGR : BinaryRREAndK<"ng", 0xB980, 0xB9E4, and, GR64, GR64>;
}
- // ANDs of a 16-bit immediate, leaving other bits unaffected.
- let isCodeGenOnly = 1 in {
- def NILL32 : BinaryRI<"nill", 0xA57, and, GR32, imm32ll16c>;
- def NILH32 : BinaryRI<"nilh", 0xA56, and, GR32, imm32lh16c>;
+ let isConvertibleToThreeAddress = 1 in {
+ // ANDs of a 16-bit immediate, leaving other bits unaffected.
+ let isCodeGenOnly = 1 in {
+ def NILL32 : BinaryRI<"nill", 0xA57, and, GR32, imm32ll16c>;
+ def NILH32 : BinaryRI<"nilh", 0xA56, and, GR32, imm32lh16c>;
+ }
+ def NILL : BinaryRI<"nill", 0xA57, and, GR64, imm64ll16c>;
+ def NILH : BinaryRI<"nilh", 0xA56, and, GR64, imm64lh16c>;
+ def NIHL : BinaryRI<"nihl", 0xA55, and, GR64, imm64hl16c>;
+ def NIHH : BinaryRI<"nihh", 0xA54, and, GR64, imm64hh16c>;
+
+ // ANDs of a 32-bit immediate, leaving other bits unaffected.
+ let isCodeGenOnly = 1 in
+ def NILF32 : BinaryRIL<"nilf", 0xC0B, and, GR32, uimm32>;
+ def NILF : BinaryRIL<"nilf", 0xC0B, and, GR64, imm64lf32c>;
+ def NIHF : BinaryRIL<"nihf", 0xC0A, and, GR64, imm64hf32c>;
}
- def NILL : BinaryRI<"nill", 0xA57, and, GR64, imm64ll16c>;
- def NILH : BinaryRI<"nilh", 0xA56, and, GR64, imm64lh16c>;
- def NIHL : BinaryRI<"nihl", 0xA55, and, GR64, imm64hl16c>;
- def NIHH : BinaryRI<"nihh", 0xA54, and, GR64, imm64hh16c>;
-
- // ANDs of a 32-bit immediate, leaving other bits unaffected.
- let isCodeGenOnly = 1 in
- def NILF32 : BinaryRIL<"nilf", 0xC0B, and, GR32, uimm32>;
- def NILF : BinaryRIL<"nilf", 0xC0B, and, GR64, imm64lf32c>;
- def NIHF : BinaryRIL<"nihf", 0xC0A, and, GR64, imm64hf32c>;
// ANDs of memory.
defm N : BinaryRXPair<"n", 0x54, 0xE354, and, GR32, load, 4>;
// Forms of RISBG that only affect one word of the destination register.
// They do not set CC.
+let isCodeGenOnly = 1 in
+ def RISBLG32 : RotateSelectRIEf<"risblg", 0xEC51, GR32, GR32>,
+ Requires<[FeatureHighWord]>;
def RISBHG : RotateSelectRIEf<"risbhg", 0xEC5D, GR64, GR64>,
Requires<[FeatureHighWord]>;
def RISBLG : RotateSelectRIEf<"risblg", 0xEC51, GR64, GR64>,
; An address with an index and a displacement added using OR.
define void @f6(i64 %addr, i64 %index) {
; CHECK-LABEL: f6:
-; CHECK: risbg [[BASE:%r[1245]]], %r2, 0, 188, 0
-; CHECK: lb %r0, 6(%r3,[[BASE]])
+; CHECK: nill %r2, 65528
+; CHECK: lb %r0, 6(%r3,%r2)
; CHECK: br %r14
%aligned = and i64 %addr, -8
%or = or i64 %aligned, 6
; about the alignment of %add here.
define void @f8(i64 %addr, i64 %index) {
; CHECK-LABEL: f8:
-; CHECK: risbg [[BASE:%r[1245]]], %r2, 0, 188, 0
-; CHECK: agr [[BASE]], %r3
-; CHECK: oill [[BASE]], 6
-; CHECK: lb %r0, 0([[BASE]])
+; CHECK: nill %r2, 65528
+; CHECK: agr %r2, %r3
+; CHECK: oill %r2, 6
+; CHECK: lb %r0, 0(%r2)
; CHECK: br %r14
%aligned = and i64 %addr, -8
%add = add i64 %aligned, %index
; An address with an index and a displacement added using OR.
define void @f6(i64 %addr, i64 %index, i8 **%dst) {
; CHECK-LABEL: f6:
-; CHECK: risbg [[BASE:%r[1245]]], %r2, 0, 188, 0
-; CHECK: lb %r0, 6(%r3,[[BASE]])
+; CHECK: nill %r2, 65528
+; CHECK: lb %r0, 6(%r3,%r2)
; CHECK: br %r14
%aligned = and i64 %addr, -8
%or = or i64 %aligned, 6
; about the alignment of %add here.
define void @f8(i64 %addr, i64 %index, i8 **%dst) {
; CHECK-LABEL: f8:
-; CHECK: risbg [[BASE:%r[1245]]], %r2, 0, 188, 0
-; CHECK: agr [[BASE]], %r3
-; CHECK: oill [[BASE]], 6
-; CHECK: lb %r0, 0([[BASE]])
+; CHECK: nill %r2, 65528
+; CHECK: agr %r2, %r3
+; CHECK: oill %r2, 6
+; CHECK: lb %r0, 0(%r2)
; CHECK: br %r14
%aligned = and i64 %addr, -8
%add = add i64 %aligned, %index
;
; lgr %r1, %r15
; sgr %r1, %r2
-; risbg %r1, %r1, 0, 188, 0
+; nill %r1, 0xfff8
; lgr %r15, %r1
;
; CHECK-LABEL: f1:
; CHECK-DAG: la [[REG1:%r[0-5]]], 7(%r2)
-; CHECK-DAG: risbg [[REG2:%r[0-5]]], [[REG1]], 0, 188, 0
-; CHECK-DAG: lgr [[REG3:%r[0-5]]], %r15
-; CHECK: sgr [[REG3]], [[REG2]]
-; CHECK: lgr %r15, [[REG3]]
+; CHECK-DAG: nill [[REG1]], 65528
+; CHECK-DAG: lgr [[REG2:%r[0-5]]], %r15
+; CHECK: sgr [[REG2]], [[REG1]]
+; CHECK: lgr %r15, [[REG2]]
;
; CHECK-A-LABEL: f1:
; CHECK-A: lgr %r15, %r1
; Test 32-bit ANDs in which the second operand is constant.
;
-; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
+; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s
-; ANDs with 1 should use RISBG
+; ANDs with 1 can use NILF.
define i32 @f1(i32 %a) {
; CHECK-LABEL: f1:
-; CHECK: risbg %r2, %r2, 63, 191, 0
+; CHECK: nilf %r2, 1
; CHECK: br %r14
%and = and i32 %a, 1
ret i32 %and
}
-; ...same for 2.
-define i32 @f2(i32 %a) {
+; ...but RISBLG is available as a three-address form.
+define i32 @f2(i32 %a, i32 %b) {
; CHECK-LABEL: f2:
-; CHECK: risbg %r2, %r2, 62, 190, 0
+; CHECK: risblg %r2, %r3, 31, 159, 0
; CHECK: br %r14
- %and = and i32 %a, 2
+ %and = and i32 %b, 1
ret i32 %and
}
-; ...and 3.
-define i32 @f3(i32 %a) {
+; ...same for 4.
+define i32 @f3(i32 %a, i32 %b) {
; CHECK-LABEL: f3:
-; CHECK: risbg %r2, %r2, 62, 191, 0
+; CHECK: risblg %r2, %r3, 29, 157, 0
; CHECK: br %r14
- %and = and i32 %a, 3
+ %and = and i32 %b, 4
ret i32 %and
}
-; ...and 4.
+; ANDs with 5 must use NILF.
define i32 @f4(i32 %a) {
; CHECK-LABEL: f4:
-; CHECK: risbg %r2, %r2, 61, 189, 0
+; CHECK: nilf %r2, 5
; CHECK: br %r14
- %and = and i32 %a, 4
+ %and = and i32 %a, 5
ret i32 %and
}
-; Check the lowest useful NILF value.
-define i32 @f5(i32 %a) {
+; ...a single RISBLG isn't enough.
+define i32 @f5(i32 %a, i32 %b) {
; CHECK-LABEL: f5:
-; CHECK: nilf %r2, 5
+; CHECK-NOT: risb
; CHECK: br %r14
- %and = and i32 %a, 5
+ %and = and i32 %b, 5
ret i32 %and
}
ret i32 %and
}
-; ANDs of 0xffff are zero extensions from i16.
-define i32 @f7(i32 %a) {
+; ...a single RISBLG isn't enough.
+define i32 @f7(i32 %a, i32 %b) {
; CHECK-LABEL: f7:
-; CHECK: llhr %r2, %r2
+; CHECK-NOT: risb
; CHECK: br %r14
- %and = and i32 %a, 65535
+ %and = and i32 %b, 65533
ret i32 %and
}
-; Check the next value up, which can use RISBG.
+; Check the next highest value, which can use NILF.
define i32 @f8(i32 %a) {
; CHECK-LABEL: f8:
-; CHECK: risbg %r2, %r2, 47, 175, 0
+; CHECK: nilf %r2, 65534
; CHECK: br %r14
- %and = and i32 %a, 65536
+ %and = and i32 %a, 65534
ret i32 %and
}
-; Check the next value up, which must again use NILF.
-define i32 @f9(i32 %a) {
+; ...although the three-address case should use RISBLG.
+define i32 @f9(i32 %a, i32 %b) {
; CHECK-LABEL: f9:
-; CHECK: nilf %r2, 65537
+; CHECK: risblg %r2, %r3, 16, 158, 0
; CHECK: br %r14
- %and = and i32 %a, 65537
+ %and = and i32 %b, 65534
ret i32 %and
}
-; This value is in range of NILH, but we use RISBG instead.
-define i32 @f10(i32 %a) {
+; ANDs of 0xffff are zero extensions from i16.
+define i32 @f10(i32 %a, i32 %b) {
; CHECK-LABEL: f10:
-; CHECK: risbg %r2, %r2, 47, 191, 0
+; CHECK: llhr %r2, %r3
; CHECK: br %r14
- %and = and i32 %a, 131071
+ %and = and i32 %b, 65535
ret i32 %and
}
-; Check the lowest useful NILH value.
+; Check the next value up, which must again use NILF.
define i32 @f11(i32 %a) {
; CHECK-LABEL: f11:
-; CHECK: nilh %r2, 2
+; CHECK: nilf %r2, 65536
; CHECK: br %r14
- %and = and i32 %a, 196607
+ %and = and i32 %a, 65536
ret i32 %and
}
-; Check the highest useful NILH value.
-define i32 @f12(i32 %a) {
+; ...but the three-address case can use RISBLG.
+define i32 @f12(i32 %a, i32 %b) {
; CHECK-LABEL: f12:
-; CHECK: nilh %r2, 65530
+; CHECK: risblg %r2, %r3, 15, 143, 0
; CHECK: br %r14
- %and = and i32 %a, -327681
+ %and = and i32 %b, 65536
ret i32 %and
}
-; Check the equivalent of NILH of 65531, which can use RISBG.
+; Check the lowest useful NILH value.
define i32 @f13(i32 %a) {
; CHECK-LABEL: f13:
-; CHECK: risbg %r2, %r2, 46, 172, 0
+; CHECK: nilh %r2, 1
; CHECK: br %r14
- %and = and i32 %a, -262145
+ %and = and i32 %a, 131071
ret i32 %and
}
-; ...same for 65532.
-define i32 @f14(i32 %a) {
+; ...but RISBLG is OK in the three-address case.
+define i32 @f14(i32 %a, i32 %b) {
; CHECK-LABEL: f14:
-; CHECK: risbg %r2, %r2, 48, 173, 0
+; CHECK: risblg %r2, %r3, 15, 159, 0
; CHECK: br %r14
- %and = and i32 %a, -196609
+ %and = and i32 %b, 131071
ret i32 %and
}
-; ...and 65533.
+; Check the highest useful NILF value.
define i32 @f15(i32 %a) {
; CHECK-LABEL: f15:
-; CHECK: risbg %r2, %r2, 47, 173, 0
+; CHECK: nilf %r2, 4294901758
; CHECK: br %r14
- %and = and i32 %a, -131073
+ %and = and i32 %a, -65538
ret i32 %and
}
-; Check the highest useful NILF value.
+; Check the next value up, which is the highest useful NILH value.
define i32 @f16(i32 %a) {
; CHECK-LABEL: f16:
-; CHECK: nilf %r2, 4294901758
+; CHECK: nilh %r2, 65534
; CHECK: br %r14
- %and = and i32 %a, -65538
+ %and = and i32 %a, -65537
ret i32 %and
}
-; Check the next value up, which is the equivalent of an NILH of 65534.
-; We use RISBG instead.
+; Check the next value up, which is the first useful NILL value.
define i32 @f17(i32 %a) {
; CHECK-LABEL: f17:
-; CHECK: risbg %r2, %r2, 48, 174, 0
+; CHECK: nill %r2, 0
; CHECK: br %r14
- %and = and i32 %a, -65537
+ %and = and i32 %a, -65536
ret i32 %and
}
-; Check the next value up, which can also use RISBG.
-define i32 @f18(i32 %a) {
+; ...although the three-address case should use RISBLG.
+define i32 @f18(i32 %a, i32 %b) {
; CHECK-LABEL: f18:
-; CHECK: risbg %r2, %r2, 32, 175, 0
+; CHECK: risblg %r2, %r3, 0, 143, 0
; CHECK: br %r14
- %and = and i32 %a, -65536
+ %and = and i32 %b, -65536
ret i32 %and
}
-; ...and again.
+; Check the next value up again, which can still use NILL.
define i32 @f19(i32 %a) {
; CHECK-LABEL: f19:
-; CHECK: risbg %r2, %r2, 63, 175, 0
+; CHECK: nill %r2, 1
; CHECK: br %r14
%and = and i32 %a, -65535
ret i32 %and
}
-; Check the next value up again, which is the lowest useful NILL value.
-define i32 @f20(i32 %a) {
+; Check the next value up again, which cannot use RISBLG.
+define i32 @f20(i32 %a, i32 %b) {
; CHECK-LABEL: f20:
-; CHECK: nill %r2, 2
+; CHECK-NOT: risb
; CHECK: br %r14
- %and = and i32 %a, -65534
+ %and = and i32 %b, -65534
ret i32 %and
}
-; Check the highest useful NILL value.
+; Check the last useful mask, which can use NILL.
define i32 @f21(i32 %a) {
; CHECK-LABEL: f21:
-; CHECK: nill %r2, 65530
+; CHECK: nill %r2, 65534
; CHECK: br %r14
- %and = and i32 %a, -6
+ %and = and i32 %a, -2
ret i32 %and
}
-; Check the next value up, which can use RISBG.
-define i32 @f22(i32 %a) {
+; ...or RISBLG for the three-address case.
+define i32 @f22(i32 %a, i32 %b) {
; CHECK-LABEL: f22:
-; CHECK: risbg %r2, %r2, 62, 188, 0
+; CHECK: risblg %r2, %r3, 0, 158, 0
; CHECK: br %r14
- %and = and i32 %a, -5
+ %and = and i32 %b, -2
ret i32 %and
}
-; ...and again.
-define i32 @f23(i32 %a) {
+; Test that RISBLG can be used when inserting a non-wraparound mask
+; into another register.
+define i64 @f23(i64 %a, i32 %b) {
; CHECK-LABEL: f23:
-; CHECK: risbg %r2, %r2, 32, 189, 0
+; CHECK: risblg %r2, %r3, 30, 158, 0
; CHECK: br %r14
- %and = and i32 %a, -4
- ret i32 %and
+ %and1 = and i64 %a, -4294967296
+ %and2 = and i32 %b, 2
+ %ext = zext i32 %and2 to i64
+ %or = or i64 %and1, %ext
+ ret i64 %or
}
-; ...and again.
-define i32 @f24(i32 %a) {
+; ...and when inserting a wrap-around mask.
+define i64 @f24(i64 %a, i32 %b) {
; CHECK-LABEL: f24:
-; CHECK: risbg %r2, %r2, 63, 189, 0
-; CHECK: br %r14
- %and = and i32 %a, -3
- ret i32 %and
-}
-
-; Check the last useful mask.
-define i32 @f25(i32 %a) {
-; CHECK-LABEL: f25:
-; CHECK: risbg %r2, %r2, 32, 190, 0
+; CHECK: risblg %r2, %r3, 30, 156
; CHECK: br %r14
- %and = and i32 %a, -2
- ret i32 %and
+ %and1 = and i64 %a, -4294967296
+ %and2 = and i32 %b, -5
+ %ext = zext i32 %and2 to i64
+ %or = or i64 %and1, %ext
+ ret i64 %or
}
}
; ...but 0xffff is a 16-bit zero extension.
-define i64 @f3(i64 %a) {
+define i64 @f3(i64 %a, i64 %b) {
; CHECK-LABEL: f3:
-; CHECK: llghr %r2, %r2
+; CHECK: llghr %r2, %r3
; CHECK: br %r14
- %and = and i64 %a, 65535
+ %and = and i64 %b, 65535
ret i64 %and
}
}
; Check the next value up, which is a 32-bit zero extension.
-define i64 @f6(i64 %a) {
+define i64 @f6(i64 %a, i64 %b) {
; CHECK-LABEL: f6:
-; CHECK: llgfr %r2, %r2
+; CHECK: llgfr %r2, %r3
; CHECK: br %r14
- %and = and i64 %a, 4294967295
+ %and = and i64 %b, 4294967295
ret i64 %and
}
-; Check the lowest useful NIHF value (0x00000002_ffffffff).
+; Check the lowest useful NIHF value (0x00000001_ffffffff).
define i64 @f7(i64 %a) {
; CHECK-LABEL: f7:
-; CHECK: nihf %r2, 2
+; CHECK: nihf %r2, 1
; CHECK: br %r14
- %and = and i64 %a, 12884901887
+ %and = and i64 %a, 8589934591
ret i64 %and
}
-; Check the lowest useful NIHH value (0x0002ffff_ffffffff).
-define i64 @f8(i64 %a) {
+; ...but RISBG can be used if a three-address form is useful.
+define i64 @f8(i64 %a, i64 %b) {
; CHECK-LABEL: f8:
-; CHECK: nihh %r2, 2
+; CHECK: risbg %r2, %r3, 31, 191, 0
; CHECK: br %r14
- %and = and i64 %a, 844424930131967
+ %and = and i64 %b, 8589934591
ret i64 %and
}
-; Check the highest useful NIHH value (0xfffaffff_ffffffff).
+; Check the lowest NIHH value outside the RISBG range (0x0002ffff_ffffffff).
define i64 @f9(i64 %a) {
; CHECK-LABEL: f9:
+; CHECK: nihh %r2, 2
+; CHECK: br %r14
+ %and = and i64 %a, 844424930131967
+ ret i64 %and
+}
+
+; Check the highest NIHH value outside the RISBG range (0xfffaffff_ffffffff).
+define i64 @f10(i64 %a) {
+; CHECK-LABEL: f10:
; CHECK: nihh %r2, 65530
; CHECK: br %r14
%and = and i64 %a, -1407374883553281
}
; Check the highest useful NIHF value (0xfffefffe_ffffffff).
-define i64 @f10(i64 %a) {
-; CHECK-LABEL: f10:
+define i64 @f11(i64 %a) {
+; CHECK-LABEL: f11:
; CHECK: nihf %r2, 4294901758
; CHECK: br %r14
%and = and i64 %a, -281479271677953
ret i64 %and
}
-; Check the lowest useful NIHL value (0xffff0002_ffffffff).
-define i64 @f11(i64 %a) {
-; CHECK-LABEL: f11:
+; Check the lowest NIHL value outside the RISBG range (0xffff0002_ffffffff).
+define i64 @f12(i64 %a) {
+; CHECK-LABEL: f12:
; CHECK: nihl %r2, 2
; CHECK: br %r14
%and = and i64 %a, -281462091808769
ret i64 %and
}
-; Check the highest useful NIHL value (0xfffffffa_ffffffff).
-define i64 @f12(i64 %a) {
-; CHECK-LABEL: f12:
+; Check the highest NIHL value outside the RISBG range (0xfffffffa_ffffffff).
+define i64 @f13(i64 %a) {
+; CHECK-LABEL: f13:
; CHECK: nihl %r2, 65530
; CHECK: br %r14
%and = and i64 %a, -21474836481
ret i64 %and
}
-; Check the lowest useful NILF range (0xffffffff_00000002).
-define i64 @f13(i64 %a) {
-; CHECK-LABEL: f13:
+; Check the lowest NILF value outside the RISBG range (0xffffffff_00000002).
+define i64 @f14(i64 %a) {
+; CHECK-LABEL: f14:
; CHECK: nilf %r2, 2
; CHECK: br %r14
%and = and i64 %a, -4294967294
ret i64 %and
}
-; Check the low end of the NILH range (0xffffffff_0002ffff).
-define i64 @f14(i64 %a) {
-; CHECK-LABEL: f14:
+; Check the lowest NILH value outside the RISBG range (0xffffffff_0002ffff).
+define i64 @f15(i64 %a) {
+; CHECK-LABEL: f15:
; CHECK: nilh %r2, 2
; CHECK: br %r14
%and = and i64 %a, -4294770689
}
; Check the next value up, which must use NILF.
-define i64 @f15(i64 %a) {
-; CHECK-LABEL: f15:
+define i64 @f16(i64 %a) {
+; CHECK-LABEL: f16:
; CHECK: nilf %r2, 196608
; CHECK: br %r14
%and = and i64 %a, -4294770688
ret i64 %and
}
-; Check the highest useful NILH value (0xffffffff_fffaffff).
-define i64 @f16(i64 %a) {
-; CHECK-LABEL: f16:
+; Check the highest NILH value outside the RISBG range (0xffffffff_fffaffff).
+define i64 @f17(i64 %a) {
+; CHECK-LABEL: f17:
; CHECK: nilh %r2, 65530
; CHECK: br %r14
%and = and i64 %a, -327681
}
; Check the maximum useful NILF value (0xffffffff_fffefffe).
-define i64 @f17(i64 %a) {
-; CHECK-LABEL: f17:
+define i64 @f18(i64 %a) {
+; CHECK-LABEL: f18:
; CHECK: nilf %r2, 4294901758
; CHECK: br %r14
%and = and i64 %a, -65538
ret i64 %and
}
-; Check the lowest useful NILL value (0xffffffff_ffff0002).
-define i64 @f18(i64 %a) {
-; CHECK-LABEL: f18:
+; Check the lowest NILL value outside the RISBG range (0xffffffff_ffff0002).
+define i64 @f19(i64 %a) {
+; CHECK-LABEL: f19:
; CHECK: nill %r2, 2
; CHECK: br %r14
%and = and i64 %a, -65534
ret i64 %and
}
-; Check the highest useful NILL value.
-define i64 @f19(i64 %a) {
-; CHECK-LABEL: f19:
+; Check the highest NILL value outside the RISBG range.
+define i64 @f20(i64 %a) {
+; CHECK-LABEL: f20:
; CHECK: nill %r2, 65530
; CHECK: br %r14
%and = and i64 %a, -6
; instructions.
define i8 @f1(i8 *%src, i8 %b) {
; CHECK-LABEL: f1:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: ar [[ROT]], %r3
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
; CHECK: br %r14
; Check the minimum signed value. We add 0x80000000 to the rotated word.
define i8 @f2(i8 *%src) {
; CHECK-LABEL: f2:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: afi [[ROT]], -2147483648
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0([[NEGSHIFT:%r[1-9]+]])
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
; CHECK: br %r14
; instructions.
define i16 @f1(i16 *%src, i16 %b) {
; CHECK-LABEL: f1:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: ar [[ROT]], %r3
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
; CHECK: br %r14
; Check the minimum signed value. We add 0x80000000 to the rotated word.
define i16 @f2(i16 *%src) {
; CHECK-LABEL: f2:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: afi [[ROT]], -2147483648
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0([[NEGSHIFT:%r[1-9]+]])
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
; CHECK: br %r14
; independent of the other loop prologue instructions.
define i8 @f1(i8 *%src, i8 %b) {
; CHECK-LABEL: f1:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: nr [[ROT]], %r3
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
; CHECK: br %r14
; Check the minimum signed value. We AND the rotated word with 0x80ffffff.
define i8 @f2(i8 *%src) {
; CHECK-LABEL: f2:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: nilh [[ROT]], 33023
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0([[NEGSHIFT:%r[1-9]+]])
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
; CHECK: br %r14
; independent of the other loop prologue instructions.
define i16 @f1(i16 *%src, i16 %b) {
; CHECK-LABEL: f1:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: nr [[ROT]], %r3
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
; CHECK: br %r14
; Check the minimum signed value. We AND the rotated word with 0x8000ffff.
define i16 @f2(i16 *%src) {
; CHECK-LABEL: f2:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: nilh [[ROT]], 32768
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0([[NEGSHIFT:%r[1-9]+]])
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
; CHECK: br %r14
ret i64 %res
}
-; Check ANDs of 1, which must be done using a register.
+; Check ANDs of 1, which are done using a register. (We could use RISBG
+; instead, but that isn't implemented yet.)
define i64 @f2(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f2:
; CHECK: ngr
ret i64 %res
}
-; Check the low end of the NIHF range.
+; Check the equivalent of NIHF with 1, which can use RISBG instead.
define i64 @f3(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f3:
; CHECK: lg %r2, 0(%r3)
; CHECK: [[LABEL:\.[^:]*]]:
-; CHECK: lgr %r0, %r2
-; CHECK: nihf %r0, 0
+; CHECK: risbg %r0, %r2, 31, 191, 0
; CHECK: csg %r2, %r0, 0(%r3)
; CHECK: jlh [[LABEL]]
; CHECK: br %r14
- %res = atomicrmw and i64 *%src, i64 4294967295 seq_cst
+ %res = atomicrmw and i64 *%src, i64 8589934591 seq_cst
ret i64 %res
}
-; Check the next value up, which must use a register.
+; Check the lowest NIHF value outside the range of RISBG.
define i64 @f4(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f4:
-; CHECK: ngr
+; CHECK: lg %r2, 0(%r3)
+; CHECK: [[LABEL:\.[^:]*]]:
+; CHECK: lgr %r0, %r2
+; CHECK: nihf %r0, 2
+; CHECK: csg %r2, %r0, 0(%r3)
+; CHECK: jlh [[LABEL]]
; CHECK: br %r14
- %res = atomicrmw and i64 *%src, i64 4294967296 seq_cst
+ %res = atomicrmw and i64 *%src, i64 12884901887 seq_cst
ret i64 %res
}
-; Check the low end of the NIHH range.
+; Check the next value up, which must use a register.
define i64 @f5(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f5:
-; CHECK: nihh %r0, 0
+; CHECK: ngr
; CHECK: br %r14
- %res = atomicrmw and i64 *%src, i64 281474976710655 seq_cst
+ %res = atomicrmw and i64 *%src, i64 12884901888 seq_cst
ret i64 %res
}
-; Check the next value up, which must use a register.
+; Check the lowest NIHH value outside the range of RISBG.
define i64 @f6(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f6:
-; CHECK: ngr
+; CHECK: nihh {{%r[0-5]}}, 2
; CHECK: br %r14
- %res = atomicrmw and i64 *%src, i64 281474976710656 seq_cst
+ %res = atomicrmw and i64 *%src, i64 844424930131967 seq_cst
ret i64 %res
}
-; Check the highest useful NILL value.
+; Check the next value up, which must use a register.
define i64 @f7(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f7:
-; CHECK: nill %r0, 65534
+; CHECK: ngr
; CHECK: br %r14
- %res = atomicrmw and i64 *%src, i64 -2 seq_cst
+ %res = atomicrmw and i64 *%src, i64 281474976710656 seq_cst
ret i64 %res
}
-; Check the low end of the NILL range.
+; Check the highest NILL value outside the range of RISBG.
define i64 @f8(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f8:
-; CHECK: nill %r0, 0
+; CHECK: nill {{%r[0-5]}}, 65530
; CHECK: br %r14
- %res = atomicrmw and i64 *%src, i64 -65536 seq_cst
+ %res = atomicrmw and i64 *%src, i64 -6 seq_cst
ret i64 %res
}
-; Check the highest useful NILH value, which is one less than the above.
+; Check the lowest NILL value outside the range of RISBG.
define i64 @f9(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f9:
-; CHECK: nilh %r0, 65534
+; CHECK: nill {{%r[0-5]}}, 2
; CHECK: br %r14
- %res = atomicrmw and i64 *%src, i64 -65537 seq_cst
+ %res = atomicrmw and i64 *%src, i64 -65534 seq_cst
ret i64 %res
}
-; Check the highest useful NILF value, which is one less than the above.
+; Check the highest useful NILF value.
define i64 @f10(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f10:
-; CHECK: nilf %r0, 4294901758
+; CHECK: nilf {{%r[0-5]}}, 4294901758
; CHECK: br %r14
%res = atomicrmw and i64 *%src, i64 -65538 seq_cst
ret i64 %res
}
-; Check the low end of the NILH range.
+; Check the highest NILH value outside the range of RISBG.
define i64 @f11(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f11:
-; CHECK: nilh %r0, 0
+; CHECK: nilh {{%r[0-5]}}, 65530
; CHECK: br %r14
- %res = atomicrmw and i64 *%src, i64 -4294901761 seq_cst
+ %res = atomicrmw and i64 *%src, i64 -327681 seq_cst
ret i64 %res
}
-; Check the low end of the NILF range.
+; Check the lowest NILH value outside the range of RISBG.
define i64 @f12(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f12:
-; CHECK: nilf %r0, 0
+; CHECK: nilh {{%r[0-5]}}, 2
; CHECK: br %r14
- %res = atomicrmw and i64 *%src, i64 -4294967296 seq_cst
+ %res = atomicrmw and i64 *%src, i64 -4294770689 seq_cst
ret i64 %res
}
-; Check the highest useful NIHL value, which is one less than the above.
+; Check the lowest NILF value outside the range of RISBG.
define i64 @f13(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f13:
-; CHECK: nihl %r0, 65534
+; CHECK: nilf {{%r[0-5]}}, 2
; CHECK: br %r14
- %res = atomicrmw and i64 *%src, i64 -4294967297 seq_cst
+ %res = atomicrmw and i64 *%src, i64 -4294967294 seq_cst
ret i64 %res
}
-; Check the low end of the NIHL range.
+; Check the highest NIHL value outside the range of RISBG.
define i64 @f14(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f14:
-; CHECK: nihl %r0, 0
+; CHECK: nihl {{%r[0-5]}}, 65530
; CHECK: br %r14
- %res = atomicrmw and i64 *%src, i64 -281470681743361 seq_cst
+ %res = atomicrmw and i64 *%src, i64 -21474836481 seq_cst
ret i64 %res
}
-; Check the highest useful NIHH value, which is 1<<32 less than the above.
+; Check the lowest NIHL value outside the range of RISBG.
define i64 @f15(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f15:
-; CHECK: nihh %r0, 65534
+; CHECK: nihl {{%r[0-5]}}, 2
; CHECK: br %r14
- %res = atomicrmw and i64 *%src, i64 -281474976710657 seq_cst
+ %res = atomicrmw and i64 *%src, i64 -281462091808769 seq_cst
ret i64 %res
}
-; Check the highest useful NIHF value, which is 1<<32 less than the above.
+; Check the highest NIHH value outside the range of RISBG.
define i64 @f16(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f16:
-; CHECK: nihf %r0, 4294901758
+; CHECK: nihh {{%r[0-5]}}, 65530
+; CHECK: br %r14
+ %res = atomicrmw and i64 *%src, i64 -1407374883553281 seq_cst
+ ret i64 %res
+}
+
+; Check the highest useful NIHF value.
+define i64 @f17(i64 %dummy, i64 *%src) {
+; CHECK-LABEL: f17:
+; CHECK: nihf {{%r[0-5]}}, 4294901758
; CHECK: br %r14
%res = atomicrmw and i64 *%src, i64 -281479271677953 seq_cst
ret i64 %res
; independent of the other loop prologue instructions.
define i8 @f1(i8 *%src, i8 %b) {
; CHECK-LABEL: f1:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LOOP:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: crjle [[ROT]], %r3, [[KEEP:\..*]]
; CHECK: risbg [[ROT]], %r3, 32, 39, 0
; CHECK: [[KEEP]]:
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LOOP]]
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
; CHECK: br %r14
; Check signed maximum.
define i8 @f2(i8 *%src, i8 %b) {
; CHECK-LABEL: f2:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LOOP:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: crjhe [[ROT]], %r3, [[KEEP:\..*]]
; CHECK: risbg [[ROT]], %r3, 32, 39, 0
; CHECK: [[KEEP]]:
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LOOP]]
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
; CHECK: br %r14
; Check unsigned minimum.
define i8 @f3(i8 *%src, i8 %b) {
; CHECK-LABEL: f3:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LOOP:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: clr [[ROT]], %r3
; CHECK: risbg [[ROT]], %r3, 32, 39, 0
; CHECK: [[KEEP]]:
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LOOP]]
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
; CHECK: br %r14
; Check unsigned maximum.
define i8 @f4(i8 *%src, i8 %b) {
; CHECK-LABEL: f4:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LOOP:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: clr [[ROT]], %r3
; CHECK: risbg [[ROT]], %r3, 32, 39, 0
; CHECK: [[KEEP]]:
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LOOP]]
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
; CHECK: br %r14
; independent of the other loop prologue instructions.
define i16 @f1(i16 *%src, i16 %b) {
; CHECK-LABEL: f1:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LOOP:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: crjle [[ROT]], %r3, [[KEEP:\..*]]
; CHECK: risbg [[ROT]], %r3, 32, 47, 0
; CHECK: [[KEEP]]:
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LOOP]]
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
; CHECK: br %r14
; Check signed maximum.
define i16 @f2(i16 *%src, i16 %b) {
; CHECK-LABEL: f2:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LOOP:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: crjhe [[ROT]], %r3, [[KEEP:\..*]]
; CHECK: risbg [[ROT]], %r3, 32, 47, 0
; CHECK: [[KEEP]]:
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LOOP]]
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
; CHECK: br %r14
; Check unsigned minimum.
define i16 @f3(i16 *%src, i16 %b) {
; CHECK-LABEL: f3:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LOOP:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: clr [[ROT]], %r3
; CHECK: risbg [[ROT]], %r3, 32, 47, 0
; CHECK: [[KEEP]]:
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LOOP]]
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
; CHECK: br %r14
; Check unsigned maximum.
define i16 @f4(i16 *%src, i16 %b) {
; CHECK-LABEL: f4:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LOOP:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: clr [[ROT]], %r3
; CHECK: risbg [[ROT]], %r3, 32, 47, 0
; CHECK: [[KEEP]]:
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LOOP]]
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
; CHECK: br %r14
; independent of the other loop prologue instructions.
define i8 @f1(i8 *%src, i8 %b) {
; CHECK-LABEL: f1:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: nr [[ROT]], %r3
; CHECK: xilf [[ROT]], 4278190080
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
; CHECK: br %r14
; Check the minimum signed value. We AND the rotated word with 0x80ffffff.
define i8 @f2(i8 *%src) {
; CHECK-LABEL: f2:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: nilh [[ROT]], 33023
; CHECK: xilf [[ROT]], 4278190080
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0([[NEGSHIFT:%r[1-9]+]])
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
; CHECK: br %r14
; independent of the other loop prologue instructions.
define i16 @f1(i16 *%src, i16 %b) {
; CHECK-LABEL: f1:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: nr [[ROT]], %r3
; CHECK: xilf [[ROT]], 4294901760
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
; CHECK: br %r14
; Check the minimum signed value. We AND the rotated word with 0x8000ffff.
define i16 @f2(i16 *%src) {
; CHECK-LABEL: f2:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: nilh [[ROT]], 32768
; CHECK: xilf [[ROT]], 4294901760
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0([[NEGSHIFT:%r[1-9]+]])
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
; CHECK: br %r14
ret i64 %res
}
-; Check NANDs of 1, which must be done using a register.
+; Check NANDs of 1, which are done using a register. (We could use RISBG
+; instead, but that isn't implemented yet.)
define i64 @f2(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f2:
; CHECK: ngr
ret i64 %res
}
-; Check the low end of the NIHF range.
+; Check the equivalent of NIHF with 1, which can use RISBG instead.
define i64 @f3(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f3:
; CHECK: lg %r2, 0(%r3)
; CHECK: [[LABEL:\.[^:]*]]:
-; CHECK: lgr %r0, %r2
-; CHECK: nihf %r0, 0
+; CHECK: risbg %r0, %r2, 31, 191, 0
; CHECK: lcgr %r0, %r0
; CHECK: aghi %r0, -1
; CHECK: csg %r2, %r0, 0(%r3)
; CHECK: jlh [[LABEL]]
; CHECK: br %r14
- %res = atomicrmw nand i64 *%src, i64 4294967295 seq_cst
+ %res = atomicrmw nand i64 *%src, i64 8589934591 seq_cst
ret i64 %res
}
-; Check the next value up, which must use a register.
+; Check the lowest NIHF value outside the range of RISBG.
define i64 @f4(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f4:
-; CHECK: ngr
+; CHECK: lg %r2, 0(%r3)
+; CHECK: [[LABEL:\.[^:]*]]:
+; CHECK: lgr %r0, %r2
+; CHECK: nihf %r0, 2
+; CHECK: lcgr %r0, %r0
+; CHECK: aghi %r0, -1
+; CHECK: csg %r2, %r0, 0(%r3)
+; CHECK: jlh [[LABEL]]
; CHECK: br %r14
- %res = atomicrmw nand i64 *%src, i64 4294967296 seq_cst
+ %res = atomicrmw nand i64 *%src, i64 12884901887 seq_cst
ret i64 %res
}
-; Check the low end of the NIHH range.
+; Check the next value up, which must use a register.
define i64 @f5(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f5:
-; CHECK: nihh %r0, 0
-; CHECK: lcgr %r0, %r0
-; CHECK: aghi %r0, -1
+; CHECK: ngr
; CHECK: br %r14
- %res = atomicrmw nand i64 *%src, i64 281474976710655 seq_cst
+ %res = atomicrmw nand i64 *%src, i64 12884901888 seq_cst
ret i64 %res
}
-; Check the next value up, which must use a register.
+; Check the lowest NIHH value outside the range of RISBG.
define i64 @f6(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f6:
-; CHECK: ngr
+; CHECK: nihh {{%r[0-5]}}, 2
; CHECK: br %r14
- %res = atomicrmw nand i64 *%src, i64 281474976710656 seq_cst
+ %res = atomicrmw nand i64 *%src, i64 844424930131967 seq_cst
ret i64 %res
}
-; Check the highest useful NILL value.
+; Check the next value up, which must use a register.
define i64 @f7(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f7:
-; CHECK: nill %r0, 65534
-; CHECK: lcgr %r0, %r0
-; CHECK: aghi %r0, -1
+; CHECK: ngr
; CHECK: br %r14
- %res = atomicrmw nand i64 *%src, i64 -2 seq_cst
+ %res = atomicrmw nand i64 *%src, i64 281474976710656 seq_cst
ret i64 %res
}
-; Check the low end of the NILL range.
+; Check the highest NILL value outside the range of RISBG.
define i64 @f8(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f8:
-; CHECK: nill %r0, 0
-; CHECK: lcgr %r0, %r0
-; CHECK: aghi %r0, -1
+; CHECK: nill {{%r[0-5]}}, 65530
; CHECK: br %r14
- %res = atomicrmw nand i64 *%src, i64 -65536 seq_cst
+ %res = atomicrmw nand i64 *%src, i64 -6 seq_cst
ret i64 %res
}
-; Check the highest useful NILH value, which is one less than the above.
+; Check the lowest NILL value outside the range of RISBG.
define i64 @f9(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f9:
-; CHECK: nilh %r0, 65534
-; CHECK: lcgr %r0, %r0
-; CHECK: aghi %r0, -1
+; CHECK: nill {{%r[0-5]}}, 2
; CHECK: br %r14
- %res = atomicrmw nand i64 *%src, i64 -65537 seq_cst
+ %res = atomicrmw nand i64 *%src, i64 -65534 seq_cst
ret i64 %res
}
-; Check the highest useful NILF value, which is one less than the above.
+; Check the highest useful NILF value.
define i64 @f10(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f10:
-; CHECK: nilf %r0, 4294901758
-; CHECK: lcgr %r0, %r0
-; CHECK: aghi %r0, -1
+; CHECK: nilf {{%r[0-5]}}, 4294901758
; CHECK: br %r14
%res = atomicrmw nand i64 *%src, i64 -65538 seq_cst
ret i64 %res
}
-; Check the low end of the NILH range.
+; Check the highest NILH value outside the range of RISBG.
define i64 @f11(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f11:
-; CHECK: nilh %r0, 0
-; CHECK: lcgr %r0, %r0
-; CHECK: aghi %r0, -1
+; CHECK: nilh {{%r[0-5]}}, 65530
; CHECK: br %r14
- %res = atomicrmw nand i64 *%src, i64 -4294901761 seq_cst
+ %res = atomicrmw nand i64 *%src, i64 -327681 seq_cst
ret i64 %res
}
-; Check the low end of the NILF range.
+; Check the lowest NILH value outside the range of RISBG.
define i64 @f12(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f12:
-; CHECK: nilf %r0, 0
-; CHECK: lcgr %r0, %r0
-; CHECK: aghi %r0, -1
+; CHECK: nilh {{%r[0-5]}}, 2
; CHECK: br %r14
- %res = atomicrmw nand i64 *%src, i64 -4294967296 seq_cst
+ %res = atomicrmw nand i64 *%src, i64 -4294770689 seq_cst
ret i64 %res
}
-; Check the highest useful NIHL value, which is one less than the above.
+; Check the lowest NILF value outside the range of RISBG.
define i64 @f13(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f13:
-; CHECK: nihl %r0, 65534
-; CHECK: lcgr %r0, %r0
-; CHECK: aghi %r0, -1
+; CHECK: nilf {{%r[0-5]}}, 2
; CHECK: br %r14
- %res = atomicrmw nand i64 *%src, i64 -4294967297 seq_cst
+ %res = atomicrmw nand i64 *%src, i64 -4294967294 seq_cst
ret i64 %res
}
-; Check the low end of the NIHL range.
+; Check the highest NIHL value outside the range of RISBG.
define i64 @f14(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f14:
-; CHECK: nihl %r0, 0
-; CHECK: lcgr %r0, %r0
-; CHECK: aghi %r0, -1
+; CHECK: nihl {{%r[0-5]}}, 65530
; CHECK: br %r14
- %res = atomicrmw nand i64 *%src, i64 -281470681743361 seq_cst
+ %res = atomicrmw nand i64 *%src, i64 -21474836481 seq_cst
ret i64 %res
}
-; Check the highest useful NIHH value, which is 1<<32 less than the above.
+; Check the lowest NIHL value outside the range of RISBG.
define i64 @f15(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f15:
-; CHECK: nihh %r0, 65534
-; CHECK: lcgr %r0, %r0
-; CHECK: aghi %r0, -1
+; CHECK: nihl {{%r[0-5]}}, 2
; CHECK: br %r14
- %res = atomicrmw nand i64 *%src, i64 -281474976710657 seq_cst
+ %res = atomicrmw nand i64 *%src, i64 -281462091808769 seq_cst
ret i64 %res
}
-; Check the highest useful NIHF value, which is 1<<32 less than the above.
+; Check the highest NIHH value outside the range of RISBG.
define i64 @f16(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f16:
-; CHECK: nihf %r0, 4294901758
-; CHECK: lcgr %r0, %r0
-; CHECK: aghi %r0, -1
+; CHECK: nihh {{%r[0-5]}}, 65530
+; CHECK: br %r14
+ %res = atomicrmw nand i64 *%src, i64 -1407374883553281 seq_cst
+ ret i64 %res
+}
+
+; Check the highest useful NIHF value.
+define i64 @f17(i64 %dummy, i64 *%src) {
+; CHECK-LABEL: f17:
+; CHECK: nihf {{%r[0-5]}}, 4294901758
; CHECK: br %r14
%res = atomicrmw nand i64 *%src, i64 -281479271677953 seq_cst
ret i64 %res
; instructions.
define i8 @f1(i8 *%src, i8 %b) {
; CHECK-LABEL: f1:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: or [[ROT]], %r3
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
; CHECK: br %r14
; Check the minimum signed value. We OR the rotated word with 0x80000000.
define i8 @f2(i8 *%src) {
; CHECK-LABEL: f2:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: oilh [[ROT]], 32768
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0([[NEGSHIFT:%r[1-9]+]])
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
; CHECK: br %r14
; instructions.
define i16 @f1(i16 *%src, i16 %b) {
; CHECK-LABEL: f1:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: or [[ROT]], %r3
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
; CHECK: br %r14
; Check the minimum signed value. We OR the rotated word with 0x80000000.
define i16 @f2(i16 *%src) {
; CHECK-LABEL: f2:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: oilh [[ROT]], 32768
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0([[NEGSHIFT:%r[1-9]+]])
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
; CHECK: br %r14
; instructions.
define i8 @f1(i8 *%src, i8 %b) {
; CHECK-LABEL: f1:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: sr [[ROT]], %r3
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
; CHECK: br %r14
; Check the minimum signed value. We add 0x80000000 to the rotated word.
define i8 @f2(i8 *%src) {
; CHECK-LABEL: f2:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: afi [[ROT]], -2147483648
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0([[NEGSHIFT:%r[1-9]+]])
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
; CHECK: br %r14
; instructions.
define i16 @f1(i16 *%src, i16 %b) {
; CHECK-LABEL: f1:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: sr [[ROT]], %r3
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
; CHECK: br %r14
; Check the minimum signed value. We add 0x80000000 to the rotated word.
define i16 @f2(i16 *%src) {
; CHECK-LABEL: f2:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: afi [[ROT]], -2147483648
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0([[NEGSHIFT:%r[1-9]+]])
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
; CHECK: br %r14
; which shift %r3 left so that %b is at the high end of the word).
define i8 @f1(i8 *%src, i8 %b) {
; CHECK-LABEL: f1:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: risbg [[ROT]], %r3, 32, 39, 24
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
; CHECK: br %r14
; which shift %r3 left so that %b is at the high end of the word).
define i16 @f1(i16 *%src, i16 %b) {
; CHECK-LABEL: f1:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: risbg [[ROT]], %r3, 32, 47, 16
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
; CHECK: br %r14
; instructions.
define i8 @f1(i8 *%src, i8 %b) {
; CHECK-LABEL: f1:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: xr [[ROT]], %r3
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
; CHECK: br %r14
; Check the minimum signed value. We XOR the rotated word with 0x80000000.
define i8 @f2(i8 *%src) {
; CHECK-LABEL: f2:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: xilf [[ROT]], 2147483648
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0([[NEGSHIFT:%r[1-9]+]])
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 8([[SHIFT]])
; CHECK: br %r14
; instructions.
define i16 @f1(i16 *%src, i16 %b) {
; CHECK-LABEL: f1:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: xr [[ROT]], %r3
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
; CHECK: br %r14
; Check the minimum signed value. We XOR the rotated word with 0x80000000.
define i16 @f2(i16 *%src) {
; CHECK-LABEL: f2:
-; CHECK-DAG: sllg [[SHIFT:%r[1-9]+]], %r2, 3
-; CHECK-DAG: risbg [[BASE:%r[1-9]+]], %r2, 0, 189, 0
-; CHECK: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK: sllg [[SHIFT:%r[1-9]+]], %r2, 3
+; CHECK: nill %r2, 65532
+; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LABEL:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
; CHECK: xilf [[ROT]], 2147483648
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0([[NEGSHIFT:%r[1-9]+]])
-; CHECK: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK: cs [[OLD]], [[NEW]], 0(%r2)
; CHECK: jlh [[LABEL]]
; CHECK: rll %r2, [[OLD]], 16([[SHIFT]])
; CHECK: br %r14
; which shift %r3 left so that %b is at the high end of the word).
define i8 @f1(i8 %dummy, i8 *%src, i8 %cmp, i8 %swap) {
; CHECK-MAIN-LABEL: f1:
-; CHECK-MAIN-DAG: sllg [[SHIFT:%r[1-9]+]], %r3, 3
-; CHECK-MAIN-DAG: risbg [[BASE:%r[1-9]+]], %r3, 0, 189, 0
-; CHECK-MAIN: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK-MAIN: sllg [[SHIFT:%r[1-9]+]], %r3, 3
+; CHECK-MAIN: nill %r3, 65532
+; CHECK-MAIN: l [[OLD:%r[0-9]+]], 0(%r3)
; CHECK-MAIN: [[LOOP:\.[^ ]*]]:
; CHECK-MAIN: rll %r2, [[OLD]], 8([[SHIFT]])
; CHECK-MAIN: risbg %r4, %r2, 32, 55, 0
; CHECK-MAIN: crjlh %r2, %r4, [[EXIT:\.[^ ]*]]
; CHECK-MAIN: risbg %r5, %r2, 32, 55, 0
; CHECK-MAIN: rll [[NEW:%r[0-9]+]], %r5, -8({{%r[1-9]+}})
-; CHECK-MAIN: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK-MAIN: cs [[OLD]], [[NEW]], 0(%r3)
; CHECK-MAIN: jlh [[LOOP]]
; CHECK-MAIN: [[EXIT]]:
; CHECK-MAIN-NOT: %r2
; which shift %r3 left so that %b is at the high end of the word).
define i16 @f1(i16 %dummy, i16 *%src, i16 %cmp, i16 %swap) {
; CHECK-MAIN-LABEL: f1:
-; CHECK-MAIN-DAG: sllg [[SHIFT:%r[1-9]+]], %r3, 3
-; CHECK-MAIN-DAG: risbg [[BASE:%r[1-9]+]], %r3, 0, 189, 0
-; CHECK-MAIN: l [[OLD:%r[0-9]+]], 0([[BASE]])
+; CHECK-MAIN: sllg [[SHIFT:%r[1-9]+]], %r3, 3
+; CHECK-MAIN: nill %r3, 65532
+; CHECK-MAIN: l [[OLD:%r[0-9]+]], 0(%r3)
; CHECK-MAIN: [[LOOP:\.[^ ]*]]:
; CHECK-MAIN: rll %r2, [[OLD]], 16([[SHIFT]])
; CHECK-MAIN: risbg %r4, %r2, 32, 47, 0
; CHECK-MAIN: crjlh %r2, %r4, [[EXIT:\.[^ ]*]]
; CHECK-MAIN: risbg %r5, %r2, 32, 47, 0
; CHECK-MAIN: rll [[NEW:%r[0-9]+]], %r5, -16({{%r[1-9]+}})
-; CHECK-MAIN: cs [[OLD]], [[NEW]], 0([[BASE]])
+; CHECK-MAIN: cs [[OLD]], [[NEW]], 0(%r3)
; CHECK-MAIN: jlh [[LOOP]]
; CHECK-MAIN: [[EXIT]]:
; CHECK-MAIN-NOT: %r2
define float @f4(i64 %big) {
; CHECK-LABEL: f4:
; CHECK-NOT: %r2
-; CHECK: risbg [[REG:%r[0-5]]], %r2, 0, 159, 0
-; CHECK-NOT: [[REG]]
-; CHECK: ldgr %f0, [[REG]]
+; CHECK: nilf %r2, 0
+; CHECK-NOT: %r2
+; CHECK: ldgr %f0, %r2
%shift = ashr i64 %big, 32
%a = trunc i64 %shift to i32
%res = bitcast i32 %a to float
; register value. We can use IC but must keep the original mask.
define i32 @f3(i32 %orig, i8 *%ptr) {
; CHECK-LABEL: f3:
-; CHECK: risbg %r2, %r2, 32, 182, 0
+; CHECK: nill %r2, 65024
; CHECK: ic %r2, 0(%r3)
; CHECK: br %r14
%val = load i8 *%ptr
; Like f3, but with the operands reversed.
define i32 @f4(i32 %orig, i8 *%ptr) {
; CHECK-LABEL: f4:
-; CHECK: risbg %r2, %r2, 32, 182, 0
+; CHECK: nill %r2, 65024
; CHECK: ic %r2, 0(%r3)
; CHECK: br %r14
%val = load i8 *%ptr
; register value. We can use IC but must keep the original mask.
define i64 @f3(i64 %orig, i8 *%ptr) {
; CHECK-LABEL: f3:
-; CHECK: risbg %r2, %r2, 0, 182, 0
+; CHECK: nill %r2, 65024
; CHECK: ic %r2, 0(%r3)
; CHECK: br %r14
%val = load i8 *%ptr
; Like f3, but with the operands reversed.
define i64 @f4(i64 %orig, i8 *%ptr) {
; CHECK-LABEL: f4:
-; CHECK: risbg %r2, %r2, 0, 182, 0
+; CHECK: nill %r2, 65024
; CHECK: ic %r2, 0(%r3)
; CHECK: br %r14
%val = load i8 *%ptr
ret i64 %and
}
-; Try the next value up (mask ....1111001). The mask itself is suitable
-; for RISBG, but the shift is still needed.
+; Try the next value up (mask ....1111001). This needs a separate shift
+; and mask.
define i32 @f7(i32 %foo) {
; CHECK-LABEL: f7:
; CHECK: srl %r2, 2
-; CHECK: risbg %r2, %r2, 63, 188, 0
+; CHECK: nill %r2, 65529
; CHECK: br %r14
%shr = lshr i32 %foo, 2
%and = and i32 %shr, -7
; ...and again with i64.
define i64 @f8(i64 %foo) {
; CHECK-LABEL: f8:
-; CHECK: srlg [[REG:%r[0-5]]], %r2, 2
-; CHECK: risbg %r2, [[REG]], 63, 188, 0
+; CHECK: srlg %r2, %r2, 2
+; CHECK: nill %r2, 65529
; CHECK: br %r14
%shr = lshr i64 %foo, 2
%and = and i64 %shr, -7
ret i64 %and
}
-; Try a wrap-around mask (mask ....111100001111). The mask itself is suitable
-; for RISBG, but the shift is still needed.
+; Try a wrap-around mask (mask ....111100001111). This needs a separate shift
+; and mask.
define i32 @f11(i32 %foo) {
; CHECK-LABEL: f11:
; CHECK: sll %r2, 2
-; CHECK: risbg %r2, %r2, 60, 183, 0
+; CHECK: nill %r2, 65295
; CHECK: br %r14
%shr = shl i32 %foo, 2
%and = and i32 %shr, -241
; ...and again with i64.
define i64 @f12(i64 %foo) {
; CHECK-LABEL: f12:
-; CHECK: sllg [[REG:%r[0-5]]], %r2, 2
-; CHECK: risbg %r2, [[REG]], 60, 183, 0
+; CHECK: sllg %r2, %r2, 2
+; CHECK: nill %r2, 65295
; CHECK: br %r14
%shr = shl i64 %foo, 2
%and = and i64 %shr, -241
}
; Test a 32-bit rotate in which both parts of the OR are needed.
-; This needs a separate shift (although RISBLG would be better
-; if supported).
+; This needs a separate shift and mask.
define i32 @f17(i32 %foo) {
; CHECK-LABEL: f17:
-; CHECK: rll [[REG:%r[0-5]]], %r2, 4
-; CHECK: risbg %r2, [[REG]], 57, 190, 0
+; CHECK: rll %r2, %r2, 4
+; CHECK: nilf %r2, 126
; CHECK: br %r14
%parta = shl i32 %foo, 4
%partb = lshr i32 %foo, 28
}
; Test an arithmetic shift right in which some of the sign bits are kept.
-; The SRA is still needed.
+; This needs a separate shift and mask.
define i32 @f19(i32 %foo) {
; CHECK-LABEL: f19:
; CHECK: sra %r2, 28
-; CHECK: risbg %r2, %r2, 59, 190, 0
+; CHECK: nilf %r2, 30
; CHECK: br %r14
%shr = ashr i32 %foo, 28
%and = and i32 %shr, 30
ret i32 %and
}
-; ...and again with i64.
+; ...and again with i64. In this case RISBG is the best way of doing the AND.
define i64 @f20(i64 %foo) {
; CHECK-LABEL: f20:
; CHECK: srag [[REG:%r[0-5]]], %r2, 60
ret i64 %and
}
-; Test a case where the AND comes before a rotate.
+; Test a case where the AND comes before a rotate. This needs a separate
+; mask and rotate.
define i32 @f24(i32 %foo) {
; CHECK-LABEL: f24:
-; CHECK: risbg [[REG:%r[0-5]]], %r2, 60, 190, 0
-; CHECK: rll %r2, [[REG]], 3
+; CHECK: nilf %r2, 14
+; CHECK: rll %r2, %r2, 3
; CHECK: br %r14
%and = and i32 %foo, 14
%parta = shl i32 %and, 3
ret i64 %rotl
}
-; Test a wrap-around case in which the rotate comes after the AND.
+; Test a wrap-around case in which the AND comes before a rotate.
+; This again needs a separate mask and rotate.
define i32 @f26(i32 %foo) {
; CHECK-LABEL: f26:
-; CHECK: risbg [[REG:%r[0-5]]], %r2, 60, 185, 0
-; CHECK: rll %r2, [[REG]], 5
+; CHECK: nill %r2, 65487
+; CHECK: rll %r2, %r2, 5
; CHECK: br %r14
%and = and i32 %foo, -49
%parta = shl i32 %and, 5