[SystemZ] Postpone NI->RISBG conversion to convertToThreeAddress()

r186399 aggressively used the RISBG instruction for immediate ANDs,
both because it can handle some values that AND IMMEDIATE can't,
and because it allows the destination register to be different from
the source.  I realized later while implementing the distinct-ops
support that it would be better to leave the choice up to
convertToThreeAddress() instead.  The AND IMMEDIATE form is shorter
and is less likely to be cracked.

This is a problem for 32-bit ANDs because we assume that all 32-bit
operations will leave the high word untouched, whereas RISBG used in
this way will either clear the high word or copy it from the source
register.  The patch uses the z196 instruction RISBLG for this instead.

This means that z10 will be restricted to NILL, NILH and NILF for
32-bit ANDs, but I think that should be OK for now.  Although we're
using z10 as the base architecture, the optimization work is going
to be focused more on z196 and zEC12.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@187492 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Richard Sandiford 2013-07-31 11:36:35 +00:00
parent 8395251c0a
commit b3f912b510
33 changed files with 691 additions and 562 deletions

View File

@ -132,6 +132,14 @@ class SystemZDAGToDAGISel : public SelectionDAGISel {
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);
@ -236,6 +244,10 @@ class SystemZDAGToDAGISel : public SelectionDAGISel {
// 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);
@ -607,52 +619,15 @@ bool SystemZDAGToDAGISel::detectOrAndInsertion(SDValue &Op,
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)) {
if (TII->isRxSBGMask(Mask, RxSBG.BitSize, RxSBG.Start, RxSBG.End)) {
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");
RxSBG.Mask = Mask;
RxSBG.Start = 63 - (LSB - 1);
RxSBG.End = 63 - (LSB + Length);
return true;
}
return false;
}
@ -824,24 +799,38 @@ SDValue SystemZDAGToDAGISel::convertTo(SDLoc DL, EVT VT, SDValue N) {
}
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))
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.
if (RISBG.Rotate == 0 &&
(RISBG.Start == 32 || RISBG.Start == 48 || RISBG.Start == 56) &&
RISBG.End == 63)
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),

View File

@ -23,6 +23,11 @@
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) {
@ -507,6 +512,49 @@ static bool isSimpleBD12Move(const MachineInstr *MI, unsigned Flag) {
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,
@ -524,26 +572,50 @@ SystemZInstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
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;
return finishConvertToThreeAddress(MI, MIB, LV);
}
}
// 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);
// 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;
@ -775,6 +847,48 @@ unsigned SystemZInstrInfo::getOpcodeForOffset(unsigned Opcode,
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) {

View File

@ -187,6 +187,12 @@ public:
// 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.

View File

@ -692,21 +692,23 @@ let Defs = [CC] in {
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>;
}
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>;
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>;
// 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>;
@ -869,6 +871,9 @@ let Defs = [CC] in {
// 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>,

View File

@ -65,8 +65,8 @@ define void @f5(i64 %addr, i64 %index) {
; 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
@ -93,10 +93,10 @@ define void @f7(i64 %addr, i64 %index) {
; 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

View File

@ -71,8 +71,8 @@ define void @f5(i64 %addr, i64 %index, i8 **%dst) {
; 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
@ -101,10 +101,10 @@ define void @f7(i64 %addr, i64 %index, i8 **%dst) {
; 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

View File

@ -18,15 +18,15 @@ define i64 @f1(i64 %length, i64 %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

View File

@ -1,52 +1,52 @@
; 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: br %r14
%and = and i32 %a, 4
ret i32 %and
}
; Check the lowest useful NILF value.
define i32 @f5(i32 %a) {
; CHECK-LABEL: f5:
; CHECK: nilf %r2, 5
; CHECK: br %r14
%and = and i32 %a, 5
ret i32 %and
}
; ...a single RISBLG isn't enough.
define i32 @f5(i32 %a, i32 %b) {
; CHECK-LABEL: f5:
; CHECK-NOT: risb
; CHECK: br %r14
%and = and i32 %b, 5
ret i32 %and
}
; Check the highest 16-bit constant that must be handled by NILF.
define i32 @f6(i32 %a) {
; CHECK-LABEL: f6:
@ -56,174 +56,171 @@ define i32 @f6(i32 %a) {
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, 65534
ret i32 %and
}
; ...although the three-address case should use RISBLG.
define i32 @f9(i32 %a, i32 %b) {
; CHECK-LABEL: f9:
; CHECK: risblg %r2, %r3, 16, 158, 0
; CHECK: br %r14
%and = and i32 %b, 65534
ret i32 %and
}
; ANDs of 0xffff are zero extensions from i16.
define i32 @f10(i32 %a, i32 %b) {
; CHECK-LABEL: f10:
; CHECK: llhr %r2, %r3
; CHECK: br %r14
%and = and i32 %b, 65535
ret i32 %and
}
; Check the next value up, which must again use NILF.
define i32 @f11(i32 %a) {
; CHECK-LABEL: f11:
; CHECK: nilf %r2, 65536
; CHECK: br %r14
%and = and i32 %a, 65536
ret i32 %and
}
; Check the next value up, which must again use NILF.
define i32 @f9(i32 %a) {
; CHECK-LABEL: f9:
; CHECK: nilf %r2, 65537
; ...but the three-address case can use RISBLG.
define i32 @f12(i32 %a, i32 %b) {
; CHECK-LABEL: f12:
; CHECK: risblg %r2, %r3, 15, 143, 0
; CHECK: br %r14
%and = and i32 %a, 65537
%and = and i32 %b, 65536
ret i32 %and
}
; This value is in range of NILH, but we use RISBG instead.
define i32 @f10(i32 %a) {
; CHECK-LABEL: f10:
; CHECK: risbg %r2, %r2, 47, 191, 0
; Check the lowest useful NILH value.
define i32 @f13(i32 %a) {
; CHECK-LABEL: f13:
; CHECK: nilh %r2, 1
; CHECK: br %r14
%and = and i32 %a, 131071
ret i32 %and
}
; Check the lowest useful NILH value.
define i32 @f11(i32 %a) {
; CHECK-LABEL: f11:
; CHECK: nilh %r2, 2
; CHECK: br %r14
%and = and i32 %a, 196607
ret i32 %and
}
; Check the highest useful NILH value.
define i32 @f12(i32 %a) {
; CHECK-LABEL: f12:
; CHECK: nilh %r2, 65530
; CHECK: br %r14
%and = and i32 %a, -327681
ret i32 %and
}
; Check the equivalent of NILH of 65531, which can use RISBG.
define i32 @f13(i32 %a) {
; CHECK-LABEL: f13:
; CHECK: risbg %r2, %r2, 46, 172, 0
; CHECK: br %r14
%and = and i32 %a, -262145
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
ret i32 %and
}
; ...and 65533.
define i32 @f15(i32 %a) {
; CHECK-LABEL: f15:
; CHECK: risbg %r2, %r2, 47, 173, 0
; CHECK: br %r14
%and = and i32 %a, -131073
%and = and i32 %b, 131071
ret i32 %and
}
; Check the highest useful NILF value.
define i32 @f16(i32 %a) {
; CHECK-LABEL: f16:
define i32 @f15(i32 %a) {
; CHECK-LABEL: f15:
; CHECK: nilf %r2, 4294901758
; CHECK: br %r14
%and = and i32 %a, -65538
ret i32 %and
}
; Check the next value up, which is the equivalent of an NILH of 65534.
; We use RISBG instead.
define i32 @f17(i32 %a) {
; CHECK-LABEL: f17:
; CHECK: risbg %r2, %r2, 48, 174, 0
; Check the next value up, which is the highest useful NILH value.
define i32 @f16(i32 %a) {
; CHECK-LABEL: f16:
; CHECK: nilh %r2, 65534
; CHECK: br %r14
%and = and i32 %a, -65537
ret i32 %and
}
; Check the next value up, which can also use RISBG.
define i32 @f18(i32 %a) {
; CHECK-LABEL: f18:
; CHECK: risbg %r2, %r2, 32, 175, 0
; Check the next value up, which is the first useful NILL value.
define i32 @f17(i32 %a) {
; CHECK-LABEL: f17:
; CHECK: nill %r2, 0
; CHECK: br %r14
%and = and i32 %a, -65536
ret i32 %and
}
; ...and again.
; ...although the three-address case should use RISBLG.
define i32 @f18(i32 %a, i32 %b) {
; CHECK-LABEL: f18:
; CHECK: risblg %r2, %r3, 0, 143, 0
; CHECK: br %r14
%and = and i32 %b, -65536
ret i32 %and
}
; 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: br %r14
%and = and i32 %a, -6
ret i32 %and
}
; Check the next value up, which can use RISBG.
define i32 @f22(i32 %a) {
; CHECK-LABEL: f22:
; CHECK: risbg %r2, %r2, 62, 188, 0
; CHECK: br %r14
%and = and i32 %a, -5
ret i32 %and
}
; ...and again.
define i32 @f23(i32 %a) {
; CHECK-LABEL: f23:
; CHECK: risbg %r2, %r2, 32, 189, 0
; CHECK: br %r14
%and = and i32 %a, -4
ret i32 %and
}
; ...and again.
define i32 @f24(i32 %a) {
; 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: nill %r2, 65534
; CHECK: br %r14
%and = and i32 %a, -2
ret i32 %and
}
; ...or RISBLG for the three-address case.
define i32 @f22(i32 %a, i32 %b) {
; CHECK-LABEL: f22:
; CHECK: risblg %r2, %r3, 0, 158, 0
; CHECK: br %r14
%and = and i32 %b, -2
ret i32 %and
}
; 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: risblg %r2, %r3, 30, 158, 0
; CHECK: br %r14
%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 when inserting a wrap-around mask.
define i64 @f24(i64 %a, i32 %b) {
; CHECK-LABEL: f24:
; CHECK: risblg %r2, %r3, 30, 156
; CHECK: br %r14
%and1 = and i64 %a, -4294967296
%and2 = and i32 %b, -5
%ext = zext i32 %and2 to i64
%or = or i64 %and1, %ext
ret i64 %or
}

View File

@ -21,11 +21,11 @@ define i64 @f2(i64 %a) {
}
; ...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
}
@ -48,35 +48,44 @@ define i64 @f5(i64 %a) {
}
; 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: risbg %r2, %r3, 31, 191, 0
; CHECK: br %r14
%and = and i64 %b, 8589934591
ret i64 %and
}
; 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 useful NIHH value (0xfffaffff_ffffffff).
define i64 @f9(i64 %a) {
; CHECK-LABEL: f9:
; 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
@ -84,44 +93,44 @@ define i64 @f9(i64 %a) {
}
; 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
@ -129,17 +138,17 @@ define i64 @f14(i64 %a) {
}
; 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
@ -147,26 +156,26 @@ define i64 @f16(i64 %a) {
}
; 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

View File

@ -14,14 +14,14 @@
; 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
@ -48,14 +48,14 @@ define i8 @f1(i8 *%src, i8 %b) {
; 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

View File

@ -14,14 +14,14 @@
; 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
@ -48,14 +48,14 @@ define i16 @f1(i16 *%src, i16 %b) {
; 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

View File

@ -14,14 +14,14 @@
; 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
@ -49,14 +49,14 @@ define i8 @f1(i8 *%src, i8 %b) {
; 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

View File

@ -14,14 +14,14 @@
; 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
@ -49,14 +49,14 @@ define i16 @f1(i16 *%src, i16 %b) {
; 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

View File

@ -16,7 +16,8 @@ define i64 @f1(i64 %dummy, i64 *%src, i64 %b) {
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
@ -25,132 +26,145 @@ define i64 @f2(i64 %dummy, i64 *%src) {
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
ret i64 %res
}
; Check the low end of the NIHH range.
define i64 @f5(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f5:
; CHECK: nihh %r0, 0
; CHECK: br %r14
%res = atomicrmw and i64 *%src, i64 281474976710655 seq_cst
%res = atomicrmw and i64 *%src, i64 12884901887 seq_cst
ret i64 %res
}
; Check the next value up, which must use a register.
define i64 @f5(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f5:
; CHECK: ngr
; CHECK: br %r14
%res = atomicrmw and i64 *%src, i64 12884901888 seq_cst
ret i64 %res
}
; Check the lowest NIHH value outside the range of RISBG.
define i64 @f6(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f6:
; CHECK: nihh {{%r[0-5]}}, 2
; CHECK: br %r14
%res = atomicrmw and i64 *%src, i64 844424930131967 seq_cst
ret i64 %res
}
; Check the next value up, which must use a register.
define i64 @f7(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f7:
; CHECK: ngr
; CHECK: br %r14
%res = atomicrmw and i64 *%src, i64 281474976710656 seq_cst
ret i64 %res
}
; Check the highest useful NILL value.
define i64 @f7(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f7:
; CHECK: nill %r0, 65534
; CHECK: br %r14
%res = atomicrmw and i64 *%src, i64 -2 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

View File

@ -14,16 +14,16 @@
; 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
@ -50,16 +50,16 @@ define i8 @f1(i8 *%src, i8 %b) {
; 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
@ -86,9 +86,9 @@ define i8 @f2(i8 *%src, i8 %b) {
; 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
@ -96,7 +96,7 @@ define i8 @f3(i8 *%src, i8 %b) {
; 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
@ -123,9 +123,9 @@ define i8 @f3(i8 *%src, i8 %b) {
; 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
@ -133,7 +133,7 @@ define i8 @f4(i8 *%src, i8 %b) {
; 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

View File

@ -14,16 +14,16 @@
; 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
@ -50,16 +50,16 @@ define i16 @f1(i16 *%src, i16 %b) {
; 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
@ -86,9 +86,9 @@ define i16 @f2(i16 *%src, i16 %b) {
; 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
@ -96,7 +96,7 @@ define i16 @f3(i16 *%src, i16 %b) {
; 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
@ -123,9 +123,9 @@ define i16 @f3(i16 *%src, i16 %b) {
; 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
@ -133,7 +133,7 @@ define i16 @f4(i16 *%src, i16 %b) {
; 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

View File

@ -14,15 +14,15 @@
; 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
@ -50,15 +50,15 @@ define i8 @f1(i8 *%src, i8 %b) {
; 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

View File

@ -14,15 +14,15 @@
; 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
@ -50,15 +50,15 @@ define i16 @f1(i16 *%src, i16 %b) {
; 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

View File

@ -18,7 +18,8 @@ define i64 @f1(i64 %dummy, i64 *%src, i64 %b) {
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
@ -27,156 +28,149 @@ define i64 @f2(i64 %dummy, i64 *%src) {
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: br %r14
%res = atomicrmw nand i64 *%src, i64 4294967296 seq_cst
ret i64 %res
}
; Check the low end of the NIHH range.
define i64 @f5(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f5:
; CHECK: nihh %r0, 0
; 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 281474976710655 seq_cst
%res = atomicrmw nand i64 *%src, i64 12884901887 seq_cst
ret i64 %res
}
; Check the next value up, which must use a register.
define i64 @f5(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f5:
; CHECK: ngr
; CHECK: br %r14
%res = atomicrmw nand i64 *%src, i64 12884901888 seq_cst
ret i64 %res
}
; Check the lowest NIHH value outside the range of RISBG.
define i64 @f6(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f6:
; CHECK: nihh {{%r[0-5]}}, 2
; CHECK: br %r14
%res = atomicrmw nand i64 *%src, i64 844424930131967 seq_cst
ret i64 %res
}
; Check the next value up, which must use a register.
define i64 @f7(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f7:
; CHECK: ngr
; CHECK: br %r14
%res = atomicrmw nand i64 *%src, i64 281474976710656 seq_cst
ret i64 %res
}
; Check the highest useful NILL value.
define i64 @f7(i64 %dummy, i64 *%src) {
; CHECK-LABEL: f7:
; CHECK: nill %r0, 65534
; CHECK: lcgr %r0, %r0
; CHECK: aghi %r0, -1
; CHECK: br %r14
%res = atomicrmw nand i64 *%src, i64 -2 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

View File

@ -14,14 +14,14 @@
; 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
@ -48,14 +48,14 @@ define i8 @f1(i8 *%src, i8 %b) {
; 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

View File

@ -14,14 +14,14 @@
; 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
@ -48,14 +48,14 @@ define i16 @f1(i16 *%src, i16 %b) {
; 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

View File

@ -14,14 +14,14 @@
; 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
@ -48,14 +48,14 @@ define i8 @f1(i8 *%src, i8 %b) {
; 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

View File

@ -14,14 +14,14 @@
; 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
@ -48,14 +48,14 @@ define i16 @f1(i16 *%src, i16 %b) {
; 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

View File

@ -12,14 +12,14 @@
; 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

View File

@ -12,14 +12,14 @@
; 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

View File

@ -14,14 +14,14 @@
; 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
@ -48,14 +48,14 @@ define i8 @f1(i8 *%src, i8 %b) {
; 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

View File

@ -14,14 +14,14 @@
; 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
@ -48,14 +48,14 @@ define i16 @f1(i16 *%src, i16 %b) {
; 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

View File

@ -12,16 +12,16 @@
; 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

View File

@ -12,16 +12,16 @@
; 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

View File

@ -44,9 +44,9 @@ define float @f3(i64 %big) {
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

View File

@ -33,7 +33,7 @@ define i32 @f2(i32 %orig, i8 *%ptr) {
; 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
@ -46,7 +46,7 @@ define i32 @f3(i32 %orig, 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

View File

@ -33,7 +33,7 @@ define i64 @f2(i64 %orig, 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
@ -46,7 +46,7 @@ define i64 @f3(i64 %orig, 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

View File

@ -63,12 +63,12 @@ define i64 @f6(i64 %foo) {
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
@ -78,8 +78,8 @@ define i32 @f7(i32 %foo) {
; ...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
@ -107,12 +107,12 @@ define i64 @f10(i64 %foo) {
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
@ -122,8 +122,8 @@ define i32 @f11(i32 %foo) {
; ...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
@ -181,12 +181,11 @@ define i64 @f16(i64 %foo) {
}
; 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
@ -208,18 +207,18 @@ define i64 @f18(i64 %foo) {
}
; 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
@ -265,11 +264,12 @@ define i64 @f23(i64 %foo) {
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
@ -290,11 +290,12 @@ define i64 @f25(i64 %foo) {
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