326 changes: 316 additions & 10 deletions llvm/lib/Target/SystemZ/SystemZInstrFormats.td

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1434,6 +1434,7 @@ SystemZII::Branch
SystemZInstrInfo::getBranchInfo(const MachineInstr &MI) const {
switch (MI.getOpcode()) {
case SystemZ::BR:
case SystemZ::BI:
case SystemZ::J:
case SystemZ::JG:
return SystemZII::Branch(SystemZII::BranchNormal, SystemZ::CCMASK_ANY,
Expand Down
62 changes: 60 additions & 2 deletions llvm/lib/Target/SystemZ/SystemZInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ let isBranch = 1, isTerminator = 1, Uses = [CC] in {
let isIndirectBranch = 1 in {
def BC : CondBranchRX<"b#", 0x47>;
def BCR : CondBranchRR<"b#r", 0x07>;
def BIC : CondBranchRXY<"bi#", 0xe347>,
Requires<[FeatureMiscellaneousExtensions2]>;
}
}

Expand All @@ -58,6 +60,8 @@ let isBranch = 1, isTerminator = 1, Uses = [CC] in {
let isIndirectBranch = 1 in {
def BCAsm : AsmCondBranchRX<"bc", 0x47>;
def BCRAsm : AsmCondBranchRR<"bcr", 0x07>;
def BICAsm : AsmCondBranchRXY<"bic", 0xe347>,
Requires<[FeatureMiscellaneousExtensions2]>;
}

// Define AsmParser extended mnemonics for each general condition-code mask
Expand All @@ -69,6 +73,8 @@ let isBranch = 1, isTerminator = 1, Uses = [CC] in {
let isIndirectBranch = 1 in {
def BAsm#V : FixedCondBranchRX <CV<V>, "b#", 0x47>;
def BRAsm#V : FixedCondBranchRR <CV<V>, "b#r", 0x07>;
def BIAsm#V : FixedCondBranchRXY<CV<V>, "bi#", 0xe347>,
Requires<[FeatureMiscellaneousExtensions2]>;
}
}
}
Expand All @@ -81,6 +87,8 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
let isIndirectBranch = 1 in {
def B : FixedCondBranchRX<CondAlways, "b", 0x47>;
def BR : FixedCondBranchRR<CondAlways, "br", 0x07, brind>;
def BI : FixedCondBranchRXY<CondAlways, "bi", 0xe347, brind>,
Requires<[FeatureMiscellaneousExtensions2]>;
}
}

Expand Down Expand Up @@ -921,6 +929,8 @@ let Defs = [CC], CCValues = 0xF, CompareZeroCCMask = 0x8 in {
// Addition of memory.
defm AH : BinaryRXPair<"ah", 0x4A, 0xE37A, add, GR32, asextloadi16, 2>;
defm A : BinaryRXPair<"a", 0x5A, 0xE35A, add, GR32, load, 4>;
def AGH : BinaryRXY<"agh", 0xE338, add, GR64, asextloadi16, 2>,
Requires<[FeatureMiscellaneousExtensions2]>;
def AGF : BinaryRXY<"agf", 0xE318, add, GR64, asextloadi32, 4>;
def AG : BinaryRXY<"ag", 0xE308, add, GR64, load, 8>;

Expand Down Expand Up @@ -1006,6 +1016,8 @@ let Defs = [CC], CCValues = 0xF, CompareZeroCCMask = 0x8 in {
// Subtraction of memory.
defm SH : BinaryRXPair<"sh", 0x4B, 0xE37B, sub, GR32, asextloadi16, 2>;
defm S : BinaryRXPair<"s", 0x5B, 0xE35B, sub, GR32, load, 4>;
def SGH : BinaryRXY<"sgh", 0xE339, sub, GR64, asextloadi16, 2>,
Requires<[FeatureMiscellaneousExtensions2]>;
def SGF : BinaryRXY<"sgf", 0xE319, sub, GR64, asextloadi32, 4>;
def SG : BinaryRXY<"sg", 0xE309, sub, GR64, load, 8>;
}
Expand Down Expand Up @@ -1207,6 +1219,15 @@ defm : RMWIByte<xor, bdaddr20pair, XIY>;
// Multiplication
//===----------------------------------------------------------------------===//

// Multiplication of a register, setting the condition code. We prefer these
// over MS(G)R if available, even though we cannot use the condition code,
// since they are three-operand instructions.
let Predicates = [FeatureMiscellaneousExtensions2],
Defs = [CC], isCommutable = 1 in {
def MSRKC : BinaryRRFa<"msrkc", 0xB9FD, mul, GR32, GR32, GR32>;
def MSGRKC : BinaryRRFa<"msgrkc", 0xB9ED, mul, GR64, GR64, GR64>;
}

// Multiplication of a register.
let isCommutable = 1 in {
def MSR : BinaryRRE<"msr", 0xB252, mul, GR32, GR32>;
Expand All @@ -1226,21 +1247,37 @@ def MSGFI : BinaryRIL<"msgfi", 0xC20, mul, GR64, imm64sx32>;
// Multiplication of memory.
defm MH : BinaryRXPair<"mh", 0x4C, 0xE37C, mul, GR32, asextloadi16, 2>;
defm MS : BinaryRXPair<"ms", 0x71, 0xE351, mul, GR32, load, 4>;
def MGH : BinaryRXY<"mgh", 0xE33C, mul, GR64, asextloadi16, 2>,
Requires<[FeatureMiscellaneousExtensions2]>;
def MSGF : BinaryRXY<"msgf", 0xE31C, mul, GR64, asextloadi32, 4>;
def MSG : BinaryRXY<"msg", 0xE30C, mul, GR64, load, 8>;

// Multiplication of memory, setting the condition code.
let Predicates = [FeatureMiscellaneousExtensions2], Defs = [CC] in {
def MSC : BinaryRXY<"msc", 0xE353, null_frag, GR32, load, 4>;
def MSGC : BinaryRXY<"msgc", 0xE383, null_frag, GR64, load, 8>;
}

// Multiplication of a register, producing two results.
def MR : BinaryRR <"mr", 0x1C, null_frag, GR128, GR32>;
def MR : BinaryRR <"mr", 0x1C, null_frag, GR128, GR32>;
def MGRK : BinaryRRFa<"mgrk", 0xB9EC, null_frag, GR128, GR64, GR64>,
Requires<[FeatureMiscellaneousExtensions2]>;
def MLR : BinaryRRE<"mlr", 0xB996, null_frag, GR128, GR32>;
def MLGR : BinaryRRE<"mlgr", 0xB986, null_frag, GR128, GR64>;
def : Pat<(z_smul_lohi GR64:$src1, GR64:$src2),
(MGRK GR64:$src1, GR64:$src2)>;
def : Pat<(z_umul_lohi GR64:$src1, GR64:$src2),
(MLGR (AEXT128 GR64:$src1), GR64:$src2)>;

// Multiplication of memory, producing two results.
def M : BinaryRX <"m", 0x5C, null_frag, GR128, load, 4>;
def MFY : BinaryRXY<"mfy", 0xE35C, null_frag, GR128, load, 4>;
def MG : BinaryRXY<"mg", 0xE384, null_frag, GR128, load, 8>,
Requires<[FeatureMiscellaneousExtensions2]>;
def ML : BinaryRXY<"ml", 0xE396, null_frag, GR128, load, 4>;
def MLG : BinaryRXY<"mlg", 0xE386, null_frag, GR128, load, 8>;
def : Pat<(z_smul_lohi GR64:$src1, (i64 (load bdxaddr20only:$src2))),
(MG (AEXT128 GR64:$src1), bdxaddr20only:$src2)>;
def : Pat<(z_umul_lohi GR64:$src1, (i64 (load bdxaddr20only:$src2))),
(MLG (AEXT128 GR64:$src1), bdxaddr20only:$src2)>;

Expand Down Expand Up @@ -1765,8 +1802,29 @@ let mayLoad = 1, mayStore = 1, Uses = [R0L, R1D], Defs = [CC] in {
GR128, GR128, GR128>;
def PCC : SideEffectInherentRRE<"pcc", 0xB92C>;
}

let Predicates = [FeatureMessageSecurityAssist5] in
def PPNO : SideEffectBinaryMemMemRRE<"ppno", 0xB93C, GR128, GR128>;
def PPNO : SideEffectBinaryMemMemRRE<"ppno", 0xB93C, GR128, GR128>;
let Predicates = [FeatureMessageSecurityAssist7], isAsmParserOnly = 1 in
def PRNO : SideEffectBinaryMemMemRRE<"prno", 0xB93C, GR128, GR128>;

let Predicates = [FeatureMessageSecurityAssist8] in
def KMA : SideEffectTernaryMemMemMemRRFb<"kma", 0xB929,
GR128, GR128, GR128>;
}

//===----------------------------------------------------------------------===//
// Guarded storage
//===----------------------------------------------------------------------===//

let Predicates = [FeatureGuardedStorage] in {
def LGG : UnaryRXY<"lgg", 0xE34C, null_frag, GR64, 8>;
def LLGFSG : UnaryRXY<"llgfsg", 0xE348, null_frag, GR64, 4>;

let mayLoad = 1 in
def LGSC : SideEffectBinaryRXY<"lgsc", 0xE34D, GR64>;
let mayStore = 1 in
def STGSC : SideEffectBinaryRXY<"stgsc", 0xE349, GR64>;
}

//===----------------------------------------------------------------------===//
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/SystemZ/SystemZInstrSystem.td
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ let hasSideEffects = 1, Defs = [CC] in
let Predicates = [FeatureResetReferenceBitsMultiple], hasSideEffects = 1 in
def RRBM : UnaryRRE<"rrbm", 0xB9AE, null_frag, GR64, GR64>;

// Insert reference bits multiple.
let Predicates = [FeatureInsertReferenceBitsMultiple], hasSideEffects = 1 in
def IRBM : UnaryRRE<"irbm", 0xB9AC, null_frag, GR64, GR64>;

// Perform frame management function.
let hasSideEffects = 1 in
def PFMF : SideEffectBinaryMemRRE<"pfmf", 0xB9AF, GR32, GR64>;
Expand Down
158 changes: 158 additions & 0 deletions llvm/lib/Target/SystemZ/SystemZInstrVector.td
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,11 @@ let Predicates = [FeatureVector] in {
(VLLEZF bdxaddr12only:$addr)>;
def : Pat<(v2f64 (z_vllezf64 bdxaddr12only:$addr)),
(VLLEZG bdxaddr12only:$addr)>;
let Predicates = [FeatureVectorEnhancements1] in {
def VLLEZLF : UnaryVRX<"vllezlf", 0xE704, z_vllezli32, v128f, 4, 6>;
def : Pat<(v4f32 (z_vllezlf32 bdxaddr12only:$addr)),
(VLLEZLF bdxaddr12only:$addr)>;
}

// Load element.
def VLEB : TernaryVRX<"vleb", 0xE700, z_vlei8, v128b, v128b, 1, imm32zx4>;
Expand All @@ -170,6 +175,13 @@ let Predicates = [FeatureVector] in {
def VGEG : TernaryVRV<"vgeg", 0xE712, 8, imm32zx1>;
}

let Predicates = [FeatureVectorPackedDecimal] in {
// Load rightmost with length. The number of loaded bytes is only known
// at run time.
def VLRL : BinaryVSI<"vlrl", 0xE635, int_s390_vlrl, 0>;
def VLRLR : BinaryVRSd<"vlrlr", 0xE637, int_s390_vlrl, 0>;
}

// Use replicating loads if we're inserting a single element into an
// undefined vector. This avoids a false dependency on the previous
// register contents.
Expand Down Expand Up @@ -227,6 +239,13 @@ let Predicates = [FeatureVector] in {
def VSCEG : StoreBinaryVRV<"vsceg", 0xE71A, 8, imm32zx1>;
}

let Predicates = [FeatureVectorPackedDecimal] in {
// Store rightmost with length. The number of stored bytes is only known
// at run time.
def VSTRL : StoreLengthVSI<"vstrl", 0xE63D, int_s390_vstrl, 0>;
def VSTRLR : StoreLengthVRSd<"vstrlr", 0xE63F, int_s390_vstrl, 0>;
}

//===----------------------------------------------------------------------===//
// Selects and permutes
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -256,6 +275,10 @@ let Predicates = [FeatureVector] in {
// Permute doubleword immediate.
def VPDI : TernaryVRRc<"vpdi", 0xE784, z_permute_dwords, v128g, v128g>;

// Bit Permute.
let Predicates = [FeatureVectorEnhancements1] in
def VBPERM : BinaryVRRc<"vbperm", 0xE785, int_s390_vbperm, v128g, v128b>;

// Replicate.
def VREP: BinaryVRIcGeneric<"vrep", 0xE74D>;
def VREPB : BinaryVRIc<"vrepb", 0xE74D, z_splat, v128b, v128b, 0>;
Expand Down Expand Up @@ -424,6 +447,10 @@ let Predicates = [FeatureVector] in {
def VCTZF : UnaryVRRa<"vctzf", 0xE752, cttz, v128f, v128f, 2>;
def VCTZG : UnaryVRRa<"vctzg", 0xE752, cttz, v128g, v128g, 3>;

// Not exclusive or.
let Predicates = [FeatureVectorEnhancements1] in
def VNX : BinaryVRRc<"vnx", 0xE76C, null_frag, v128any, v128any>;

// Exclusive or.
def VX : BinaryVRRc<"vx", 0xE76D, null_frag, v128any, v128any>;

Expand Down Expand Up @@ -567,16 +594,37 @@ let Predicates = [FeatureVector] in {
def VMLOH : BinaryVRRc<"vmloh", 0xE7A5, int_s390_vmloh, v128f, v128h, 1>;
def VMLOF : BinaryVRRc<"vmlof", 0xE7A5, int_s390_vmlof, v128g, v128f, 2>;

// Multiply sum logical.
let Predicates = [FeatureVectorEnhancements1] in {
def VMSL : QuaternaryVRRdGeneric<"vmsl", 0xE7B8>;
def VMSLG : QuaternaryVRRd<"vmslg", 0xE7B8, int_s390_vmslg,
v128q, v128g, v128g, v128q, 3>;
}

// Nand.
let Predicates = [FeatureVectorEnhancements1] in
def VNN : BinaryVRRc<"vnn", 0xE76E, null_frag, v128any, v128any>;

// Nor.
def VNO : BinaryVRRc<"vno", 0xE76B, null_frag, v128any, v128any>;
def : InstAlias<"vnot\t$V1, $V2", (VNO VR128:$V1, VR128:$V2, VR128:$V2), 0>;

// Or.
def VO : BinaryVRRc<"vo", 0xE76A, null_frag, v128any, v128any>;

// Or with complement.
let Predicates = [FeatureVectorEnhancements1] in
def VOC : BinaryVRRc<"voc", 0xE76F, null_frag, v128any, v128any>;

// Population count.
def VPOPCT : UnaryVRRaGeneric<"vpopct", 0xE750>;
def : Pat<(v16i8 (z_popcnt VR128:$x)), (VPOPCT VR128:$x, 0)>;
let Predicates = [FeatureVectorEnhancements1] in {
def VPOPCTB : UnaryVRRa<"vpopctb", 0xE750, ctpop, v128b, v128b, 0>;
def VPOPCTH : UnaryVRRa<"vpopcth", 0xE750, ctpop, v128h, v128h, 1>;
def VPOPCTF : UnaryVRRa<"vpopctf", 0xE750, ctpop, v128f, v128f, 2>;
def VPOPCTG : UnaryVRRa<"vpopctg", 0xE750, ctpop, v128g, v128g, 3>;
}

// Element rotate left logical (with vector shift amount).
def VERLLV : BinaryVRRcGeneric<"verllv", 0xE773>;
Expand Down Expand Up @@ -724,6 +772,14 @@ multiclass BitwiseVectorOps<ValueType type> {
(VNO VR128:$x, VR128:$y)>;
def : Pat<(type (z_vnot VR128:$x)), (VNO VR128:$x, VR128:$x)>;
}
let Predicates = [FeatureVectorEnhancements1] in {
def : Pat<(type (z_vnot (xor VR128:$x, VR128:$y))),
(VNX VR128:$x, VR128:$y)>;
def : Pat<(type (z_vnot (and VR128:$x, VR128:$y))),
(VNN VR128:$x, VR128:$y)>;
def : Pat<(type (or VR128:$x, (z_vnot VR128:$y))),
(VOC VR128:$x, VR128:$y)>;
}
}

defm : BitwiseVectorOps<v16i8>;
Expand Down Expand Up @@ -930,6 +986,36 @@ let Predicates = [FeatureVector] in {
def : Pat<(v4f32 (z_vround (v2f64 VR128:$src))), (VLEDB VR128:$src, 0, 0)>;
def : FPConversion<WLEDB, fpround, v32eb, v64db, 0, 0>;

// Maximum.
multiclass VectorMax<Instruction insn, TypedReg tr> {
def : FPMinMax<insn, fmaxnum, tr, 4>;
def : FPMinMax<insn, fmaxnan, tr, 1>;
}
let Predicates = [FeatureVectorEnhancements1] in {
def VFMAX : TernaryVRRcFloatGeneric<"vfmax", 0xE7EF>;
def VFMAXDB : TernaryVRRcFloat<"vfmaxdb", 0xE7EF, int_s390_vfmaxdb,
v128db, v128db, 3, 0>;
def WFMAXDB : TernaryVRRcFloat<"wfmaxdb", 0xE7EF, null_frag,
v64db, v64db, 3, 8>;
defm : VectorMax<VFMAXDB, v128db>;
defm : VectorMax<WFMAXDB, v64db>;
}

// Minimum.
multiclass VectorMin<Instruction insn, TypedReg tr> {
def : FPMinMax<insn, fminnum, tr, 4>;
def : FPMinMax<insn, fminnan, tr, 1>;
}
let Predicates = [FeatureVectorEnhancements1] in {
def VFMIN : TernaryVRRcFloatGeneric<"vfmin", 0xE7EE>;
def VFMINDB : TernaryVRRcFloat<"vfmindb", 0xE7EE, int_s390_vfmindb,
v128db, v128db, 3, 0>;
def WFMINDB : TernaryVRRcFloat<"wfmindb", 0xE7EE, null_frag,
v64db, v64db, 3, 8>;
defm : VectorMin<VFMINDB, v128db>;
defm : VectorMin<WFMINDB, v64db>;
}

// Multiply.
def VFM : BinaryVRRcFloatGeneric<"vfm", 0xE7E7>;
def VFMDB : BinaryVRRc<"vfmdb", 0xE7E7, fmul, v128db, v128db, 3, 0>;
Expand All @@ -945,6 +1031,20 @@ let Predicates = [FeatureVector] in {
def VFMSDB : TernaryVRRe<"vfmsdb", 0xE78E, fms, v128db, v128db, 0, 3>;
def WFMSDB : TernaryVRRe<"wfmsdb", 0xE78E, fms, v64db, v64db, 8, 3>;

// Negative multiply and add.
let Predicates = [FeatureVectorEnhancements1] in {
def VFNMA : TernaryVRReFloatGeneric<"vfnma", 0xE79F>;
def VFNMADB : TernaryVRRe<"vfnmadb", 0xE79F, fnma, v128db, v128db, 0, 3>;
def WFNMADB : TernaryVRRe<"wfnmadb", 0xE79F, fnma, v64db, v64db, 8, 3>;
}

// Negative multiply and subtract.
let Predicates = [FeatureVectorEnhancements1] in {
def VFNMS : TernaryVRReFloatGeneric<"vfnms", 0xE79E>;
def VFNMSDB : TernaryVRRe<"vfnmsdb", 0xE79E, fnms, v128db, v128db, 0, 3>;
def WFNMSDB : TernaryVRRe<"wfnmsdb", 0xE79E, fnms, v64db, v64db, 8, 3>;
}

// Perform sign operation.
def VFPSO : BinaryVRRaFloatGeneric<"vfpso", 0xE7CC>;
def VFPSODB : BinaryVRRa<"vfpsodb", 0xE7CC, null_frag, v128db, v128db, 3, 0>;
Expand Down Expand Up @@ -1004,19 +1104,43 @@ let Predicates = [FeatureVector] in {
defm WFCEDB : BinaryVRRcSPair<"wfcedb", 0xE7E8, null_frag, null_frag,
v64g, v64db, 3, 8>;

// Compare and signal equal.
let Predicates = [FeatureVectorEnhancements1] in {
defm VFKEDB : BinaryVRRcSPair<"vfkedb", 0xE7E8, null_frag, null_frag,
v128g, v128db, 3, 4>;
defm WFKEDB : BinaryVRRcSPair<"wfkedb", 0xE7E8, null_frag, null_frag,
v64g, v64db, 3, 12>;
}

// Compare high.
def VFCH : BinaryVRRcSPairFloatGeneric<"vfch", 0xE7EB>;
defm VFCHDB : BinaryVRRcSPair<"vfchdb", 0xE7EB, z_vfcmph, z_vfcmphs,
v128g, v128db, 3, 0>;
defm WFCHDB : BinaryVRRcSPair<"wfchdb", 0xE7EB, null_frag, null_frag,
v64g, v64db, 3, 8>;

// Compare and signal high.
let Predicates = [FeatureVectorEnhancements1] in {
defm VFKHDB : BinaryVRRcSPair<"vfkhdb", 0xE7EB, null_frag, null_frag,
v128g, v128db, 3, 4>;
defm WFKHDB : BinaryVRRcSPair<"wfkhdb", 0xE7EB, null_frag, null_frag,
v64g, v64db, 3, 12>;
}

// Compare high or equal.
def VFCHE : BinaryVRRcSPairFloatGeneric<"vfche", 0xE7EA>;
defm VFCHEDB : BinaryVRRcSPair<"vfchedb", 0xE7EA, z_vfcmphe, z_vfcmphes,
v128g, v128db, 3, 0>;
defm WFCHEDB : BinaryVRRcSPair<"wfchedb", 0xE7EA, null_frag, null_frag,
v64g, v64db, 3, 8>;

// Compare and signal high or equal.
let Predicates = [FeatureVectorEnhancements1] in {
defm VFKHEDB : BinaryVRRcSPair<"vfkhedb", 0xE7EA, null_frag, null_frag,
v128g, v128db, 3, 4>;
defm WFKHEDB : BinaryVRRcSPair<"wfkhedb", 0xE7EA, null_frag, null_frag,
v64g, v64db, 3, 12>;
}
}

//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -1202,3 +1326,37 @@ let Predicates = [FeatureVector] in {
defm VSTRCZF : QuaternaryOptVRRdSPair<"vstrczf", 0xE78A, int_s390_vstrczf,
z_vstrcz_cc, v128f, v128f, 2, 2>;
}

//===----------------------------------------------------------------------===//
// Packed-decimal instructions
//===----------------------------------------------------------------------===//

let Predicates = [FeatureVectorPackedDecimal] in {
def VLIP : BinaryVRIh<"vlip", 0xE649>;

def VPKZ : BinaryVSI<"vpkz", 0xE634, null_frag, 0>;
def VUPKZ : StoreLengthVSI<"vupkz", 0xE63C, null_frag, 0>;

let Defs = [CC] in {
def VCVB : BinaryVRRi<"vcvb", 0xE650, GR32>;
def VCVBG : BinaryVRRi<"vcvbg", 0xE652, GR64>;
def VCVD : TernaryVRIi<"vcvd", 0xE658, GR32>;
def VCVDG : TernaryVRIi<"vcvdg", 0xE65A, GR64>;

def VAP : QuaternaryVRIf<"vap", 0xE671>;
def VSP : QuaternaryVRIf<"vsp", 0xE673>;

def VMP : QuaternaryVRIf<"vmp", 0xE678>;
def VMSP : QuaternaryVRIf<"vmsp", 0xE679>;

def VDP : QuaternaryVRIf<"vdp", 0xE67A>;
def VRP : QuaternaryVRIf<"vrp", 0xE67B>;
def VSDP : QuaternaryVRIf<"vsdp", 0xE67E>;

def VSRP : QuaternaryVRIg<"vsrp", 0xE659>;
def VPSOP : QuaternaryVRIg<"vpsop", 0xE65B>;

def VTP : TestVRRg<"vtp", 0xE65F>;
def VCP : CompareVRRh<"vcp", 0xE677>;
}
}
20 changes: 20 additions & 0 deletions llvm/lib/Target/SystemZ/SystemZOperators.td
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ def z_select_ccmask : SDNode<"SystemZISD::SELECT_CCMASK", SDT_ZSelectCCMask,
[SDNPInGlue]>;
def z_adjdynalloc : SDNode<"SystemZISD::ADJDYNALLOC", SDT_ZAdjDynAlloc>;
def z_popcnt : SDNode<"SystemZISD::POPCNT", SDTIntUnaryOp>;
def z_smul_lohi : SDNode<"SystemZISD::SMUL_LOHI", SDT_ZGR128Binary>;
def z_umul_lohi : SDNode<"SystemZISD::UMUL_LOHI", SDT_ZGR128Binary>;
def z_sdivrem : SDNode<"SystemZISD::SDIVREM", SDT_ZGR128Binary>;
def z_udivrem : SDNode<"SystemZISD::UDIVREM", SDT_ZGR128Binary>;
Expand Down Expand Up @@ -549,6 +550,12 @@ def z_fma : PatFrag<(ops node:$src1, node:$src2, node:$src3),
def z_fms : PatFrag<(ops node:$src1, node:$src2, node:$src3),
(fma node:$src2, node:$src3, (fneg node:$src1))>;

// Negative fused multiply-add and multiply-subtract.
def fnma : PatFrag<(ops node:$src1, node:$src2, node:$src3),
(fneg (fma node:$src1, node:$src2, node:$src3))>;
def fnms : PatFrag<(ops node:$src1, node:$src2, node:$src3),
(fneg (fms node:$src1, node:$src2, node:$src3))>;

// Floating-point negative absolute.
def fnabs : PatFrag<(ops node:$ptr), (fneg (fabs node:$ptr))>;

Expand Down Expand Up @@ -624,6 +631,19 @@ def z_vllezf64 : PatFrag<(ops node:$addr),
(scalar_to_vector (f64 (load node:$addr))),
(z_vzero))>;

// Similarly for the high element of a zeroed vector.
def z_vllezli32 : z_vllez<i32, load, 0>;
def z_vllezlf32 : PatFrag<(ops node:$addr),
(bitconvert
(z_merge_high
(v2i64
(bitconvert
(z_merge_high
(v4f32 (scalar_to_vector
(f32 (load node:$addr)))),
(v4f32 (z_vzero))))),
(v2i64 (z_vzero))))>;

// Store one element of a vector.
class z_vste<ValueType scalartype, SDPatternOperator store>
: PatFrag<(ops node:$vec, node:$addr, node:$index),
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Target/SystemZ/SystemZPatterns.td
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,10 @@ class FPConversion<Instruction insn, SDPatternOperator operator, TypedReg tr1,
TypedReg tr2, bits<3> suppress, bits<4> mode>
: Pat<(tr1.vt (operator (tr2.vt tr2.op:$vec))),
(insn tr2.op:$vec, suppress, mode)>;

// Use INSN to perform mininum/maximum operation OPERATOR on type TR.
// FUNCTION is the type of minimum/maximum function to perform.
class FPMinMax<Instruction insn, SDPatternOperator operator, TypedReg tr,
bits<4> function>
: Pat<(tr.vt (operator (tr.vt tr.op:$vec1), (tr.vt tr.op:$vec2))),
(insn tr.op:$vec1, tr.op:$vec2, function)>;
3 changes: 3 additions & 0 deletions llvm/lib/Target/SystemZ/SystemZProcessors.td
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,6 @@ def : ProcessorModel<"zEC12", ZEC12Model, Arch10SupportedFeatures.List>;
def : ProcessorModel<"arch11", Z13Model, Arch11SupportedFeatures.List>;
def : ProcessorModel<"z13", Z13Model, Arch11SupportedFeatures.List>;

def : ProcessorModel<"arch12", Z14Model, Arch12SupportedFeatures.List>;
def : ProcessorModel<"z14", Z14Model, Arch12SupportedFeatures.List>;

3 changes: 2 additions & 1 deletion llvm/lib/Target/SystemZ/SystemZSchedule.td
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def FPU2 : SchedWrite;
def DFU : SchedWrite;
def DFU2 : SchedWrite;

// Vector sub units (z13)
// Vector sub units (z13 and later)
def VecBF : SchedWrite;
def VecBF2 : SchedWrite;
def VecDF : SchedWrite;
Expand All @@ -75,6 +75,7 @@ def VecXsPm : SchedWrite;
def VBU : SchedWrite;


include "SystemZScheduleZ14.td"
include "SystemZScheduleZ13.td"
include "SystemZScheduleZEC12.td"
include "SystemZScheduleZ196.td"
Expand Down
1,573 changes: 1,573 additions & 0 deletions llvm/lib/Target/SystemZ/SystemZScheduleZ14.td

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions llvm/lib/Target/SystemZ/SystemZSubtarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ SystemZSubtarget::SystemZSubtarget(const Triple &TT, const std::string &CPU,
HasVector(false), HasLoadStoreOnCond2(false),
HasLoadAndZeroRightmostByte(false), HasMessageSecurityAssist5(false),
HasDFPPackedConversion(false),
HasMiscellaneousExtensions2(false), HasGuardedStorage(false),
HasMessageSecurityAssist7(false), HasMessageSecurityAssist8(false),
HasVectorEnhancements1(false), HasVectorPackedDecimal(false),
HasInsertReferenceBitsMultiple(false),
TargetTriple(TT), InstrInfo(initializeSubtargetDependencies(CPU, FS)),
TLInfo(TM, *this), TSInfo(), FrameLowering() {}

Expand Down
34 changes: 34 additions & 0 deletions llvm/lib/Target/SystemZ/SystemZSubtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ class SystemZSubtarget : public SystemZGenSubtargetInfo {
bool HasLoadAndZeroRightmostByte;
bool HasMessageSecurityAssist5;
bool HasDFPPackedConversion;
bool HasMiscellaneousExtensions2;
bool HasGuardedStorage;
bool HasMessageSecurityAssist7;
bool HasMessageSecurityAssist8;
bool HasVectorEnhancements1;
bool HasVectorPackedDecimal;
bool HasInsertReferenceBitsMultiple;

private:
Triple TargetTriple;
Expand Down Expand Up @@ -168,6 +175,33 @@ class SystemZSubtarget : public SystemZGenSubtargetInfo {
// Return true if the target has the vector facility.
bool hasVector() const { return HasVector; }

// Return true if the target has the miscellaneous-extensions facility 2.
bool hasMiscellaneousExtensions2() const {
return HasMiscellaneousExtensions2;
}

// Return true if the target has the guarded-storage facility.
bool hasGuardedStorage() const { return HasGuardedStorage; }

// Return true if the target has the message-security-assist
// extension facility 7.
bool hasMessageSecurityAssist7() const { return HasMessageSecurityAssist7; }

// Return true if the target has the message-security-assist
// extension facility 8.
bool hasMessageSecurityAssist8() const { return HasMessageSecurityAssist8; }

// Return true if the target has the vector-enhancements facility 1.
bool hasVectorEnhancements1() const { return HasVectorEnhancements1; }

// Return true if the target has the vector-packed-decimal facility.
bool hasVectorPackedDecimal() const { return HasVectorPackedDecimal; }

// Return true if the target has the insert-reference-bits-multiple facility.
bool hasInsertReferenceBitsMultiple() const {
return HasInsertReferenceBitsMultiple;
}

// Return true if GV can be accessed using LARL for reloc model RM
// and code model CM.
bool isPC32DBLSymbol(const GlobalValue *GV, CodeModel::Model CM) const;
Expand Down
56 changes: 56 additions & 0 deletions llvm/test/CodeGen/SystemZ/branch-11.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
; Test indirect jumps on z14.
;
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 | FileCheck %s

define i32 @f1(i32 %x, i32 %y, i32 %op) {
; CHECK-LABEL: f1:
; CHECK: ahi %r4, -1
; CHECK: clibh %r4, 5, 0(%r14)
; CHECK: llgfr [[OP64:%r[0-5]]], %r4
; CHECK: sllg [[INDEX:%r[1-5]]], [[OP64]], 3
; CHECK: larl [[BASE:%r[1-5]]]
; CHECK: bi 0([[BASE]],[[INDEX]])
entry:
switch i32 %op, label %exit [
i32 1, label %b.add
i32 2, label %b.sub
i32 3, label %b.and
i32 4, label %b.or
i32 5, label %b.xor
i32 6, label %b.mul
]

b.add:
%add = add i32 %x, %y
br label %exit

b.sub:
%sub = sub i32 %x, %y
br label %exit

b.and:
%and = and i32 %x, %y
br label %exit

b.or:
%or = or i32 %x, %y
br label %exit

b.xor:
%xor = xor i32 %x, %y
br label %exit

b.mul:
%mul = mul i32 %x, %y
br label %exit

exit:
%res = phi i32 [ %x, %entry ],
[ %add, %b.add ],
[ %sub, %b.sub ],
[ %and, %b.and ],
[ %or, %b.or ],
[ %xor, %b.xor ],
[ %mul, %b.mul ]
ret i32 %res
}
23 changes: 23 additions & 0 deletions llvm/test/CodeGen/SystemZ/fp-mul-10.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 | FileCheck %s

declare double @llvm.fma.f64(double %f1, double %f2, double %f3)

define double @f1(double %f1, double %f2, double %acc) {
; CHECK-LABEL: f1:
; CHECK: wfnmadb %f0, %f0, %f2, %f4
; CHECK: br %r14
%res = call double @llvm.fma.f64 (double %f1, double %f2, double %acc)
%negres = fsub double -0.0, %res
ret double %negres
}

define double @f2(double %f1, double %f2, double %acc) {
; CHECK-LABEL: f2:
; CHECK: wfnmsdb %f0, %f0, %f2, %f4
; CHECK: br %r14
%negacc = fsub double -0.0, %acc
%res = call double @llvm.fma.f64 (double %f1, double %f2, double %negacc)
%negres = fsub double -0.0, %res
ret double %negres
}

95 changes: 95 additions & 0 deletions llvm/test/CodeGen/SystemZ/int-add-17.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
; Test additions between an i64 and a sign-extended i16 on z14.
;
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 | FileCheck %s

declare i64 @foo()

; Check AGH with no displacement.
define i64 @f1(i64 %a, i16 *%src) {
; CHECK-LABEL: f1:
; CHECK: agh %r2, 0(%r3)
; CHECK: br %r14
%b = load i16, i16 *%src
%bext = sext i16 %b to i64
%add = add i64 %a, %bext
ret i64 %add
}

; Check the high end of the aligned AGH range.
define i64 @f2(i64 %a, i16 *%src) {
; CHECK-LABEL: f2:
; CHECK: agh %r2, 524286(%r3)
; CHECK: br %r14
%ptr = getelementptr i16, i16 *%src, i64 262143
%b = load i16, i16 *%ptr
%bext = sext i16 %b to i64
%add = add i64 %a, %bext
ret i64 %add
}

; Check the next word up, which needs separate address logic.
; Other sequences besides this one would be OK.
define i64 @f3(i64 %a, i16 *%src) {
; CHECK-LABEL: f3:
; CHECK: agfi %r3, 524288
; CHECK: agh %r2, 0(%r3)
; CHECK: br %r14
%ptr = getelementptr i16, i16 *%src, i64 262144
%b = load i16, i16 *%ptr
%bext = sext i16 %b to i64
%add = add i64 %a, %bext
ret i64 %add
}

; Check the high end of the negative aligned AGH range.
define i64 @f4(i64 %a, i16 *%src) {
; CHECK-LABEL: f4:
; CHECK: agh %r2, -2(%r3)
; CHECK: br %r14
%ptr = getelementptr i16, i16 *%src, i64 -1
%b = load i16, i16 *%ptr
%bext = sext i16 %b to i64
%add = add i64 %a, %bext
ret i64 %add
}

; Check the low end of the AGH range.
define i64 @f5(i64 %a, i16 *%src) {
; CHECK-LABEL: f5:
; CHECK: agh %r2, -524288(%r3)
; CHECK: br %r14
%ptr = getelementptr i16, i16 *%src, i64 -262144
%b = load i16, i16 *%ptr
%bext = sext i16 %b to i64
%add = add i64 %a, %bext
ret i64 %add
}

; Check the next word down, which needs separate address logic.
; Other sequences besides this one would be OK.
define i64 @f6(i64 %a, i16 *%src) {
; CHECK-LABEL: f6:
; CHECK: agfi %r3, -524290
; CHECK: agh %r2, 0(%r3)
; CHECK: br %r14
%ptr = getelementptr i16, i16 *%src, i64 -262145
%b = load i16, i16 *%ptr
%bext = sext i16 %b to i64
%add = add i64 %a, %bext
ret i64 %add
}

; Check that AGH allows an index.
define i64 @f7(i64 %a, i64 %src, i64 %index) {
; CHECK-LABEL: f7:
; CHECK: agh %r2, 524284({{%r4,%r3|%r3,%r4}})
; CHECK: br %r14
%add1 = add i64 %src, %index
%add2 = add i64 %add1, 524284
%ptr = inttoptr i64 %add2 to i16 *
%b = load i16, i16 *%ptr
%bext = sext i16 %b to i64
%add = add i64 %a, %bext
ret i64 %add
}

95 changes: 95 additions & 0 deletions llvm/test/CodeGen/SystemZ/int-mul-09.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
; Test multiplications between an i64 and a sign-extended i16 on z14.
;
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 | FileCheck %s

declare i64 @foo()

; Check MGH with no displacement.
define i64 @f1(i64 %a, i16 *%src) {
; CHECK-LABEL: f1:
; CHECK: mgh %r2, 0(%r3)
; CHECK: br %r14
%b = load i16, i16 *%src
%bext = sext i16 %b to i64
%mul = mul i64 %a, %bext
ret i64 %mul
}

; Check the high end of the aligned MGH range.
define i64 @f2(i64 %a, i16 *%src) {
; CHECK-LABEL: f2:
; CHECK: mgh %r2, 524286(%r3)
; CHECK: br %r14
%ptr = getelementptr i16, i16 *%src, i64 262143
%b = load i16, i16 *%ptr
%bext = sext i16 %b to i64
%mul = mul i64 %a, %bext
ret i64 %mul
}

; Check the next word up, which needs separate address logic.
; Other sequences besides this one would be OK.
define i64 @f3(i64 %a, i16 *%src) {
; CHECK-LABEL: f3:
; CHECK: agfi %r3, 524288
; CHECK: mgh %r2, 0(%r3)
; CHECK: br %r14
%ptr = getelementptr i16, i16 *%src, i64 262144
%b = load i16, i16 *%ptr
%bext = sext i16 %b to i64
%mul = mul i64 %a, %bext
ret i64 %mul
}

; Check the high end of the negative aligned MGH range.
define i64 @f4(i64 %a, i16 *%src) {
; CHECK-LABEL: f4:
; CHECK: mgh %r2, -2(%r3)
; CHECK: br %r14
%ptr = getelementptr i16, i16 *%src, i64 -1
%b = load i16, i16 *%ptr
%bext = sext i16 %b to i64
%mul = mul i64 %a, %bext
ret i64 %mul
}

; Check the low end of the MGH range.
define i64 @f5(i64 %a, i16 *%src) {
; CHECK-LABEL: f5:
; CHECK: mgh %r2, -524288(%r3)
; CHECK: br %r14
%ptr = getelementptr i16, i16 *%src, i64 -262144
%b = load i16, i16 *%ptr
%bext = sext i16 %b to i64
%mul = mul i64 %a, %bext
ret i64 %mul
}

; Check the next word down, which needs separate address logic.
; Other sequences besides this one would be OK.
define i64 @f6(i64 %a, i16 *%src) {
; CHECK-LABEL: f6:
; CHECK: agfi %r3, -524290
; CHECK: mgh %r2, 0(%r3)
; CHECK: br %r14
%ptr = getelementptr i16, i16 *%src, i64 -262145
%b = load i16, i16 *%ptr
%bext = sext i16 %b to i64
%mul = mul i64 %a, %bext
ret i64 %mul
}

; Check that MGH allows an index.
define i64 @f7(i64 %a, i64 %src, i64 %index) {
; CHECK-LABEL: f7:
; CHECK: mgh %r2, 524284({{%r4,%r3|%r3,%r4}})
; CHECK: br %r14
%add1 = add i64 %src, %index
%add2 = add i64 %add1, 524284
%ptr = inttoptr i64 %add2 to i16 *
%b = load i16, i16 *%ptr
%bext = sext i16 %b to i64
%mul = mul i64 %a, %bext
ret i64 %mul
}

165 changes: 165 additions & 0 deletions llvm/test/CodeGen/SystemZ/int-mul-10.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
; Test signed high-part i64->i128 multiplications on z14.
;
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 | FileCheck %s

declare i64 @foo()

; Check sign-extended multiplication in which only the high part is used.
define i64 @f1(i64 %dummy, i64 %a, i64 %b) {
; CHECK-LABEL: f1:
; CHECK-NOT: {{%r[234]}}
; CHECK: mgrk %r2, %r3, %r4
; CHECK: br %r14
%ax = sext i64 %a to i128
%bx = sext i64 %b to i128
%mulx = mul i128 %ax, %bx
%highx = lshr i128 %mulx, 64
%high = trunc i128 %highx to i64
ret i64 %high
}

; Check sign-extended multiplication in which only part of the high half
; is used.
define i64 @f2(i64 %dummy, i64 %a, i64 %b) {
; CHECK-LABEL: f2:
; CHECK-NOT: {{%r[234]}}
; CHECK: mgrk [[REG:%r[0-9]+]], %r3, %r4
; CHECK: srlg %r2, [[REG]], 3
; CHECK: br %r14
%ax = sext i64 %a to i128
%bx = sext i64 %b to i128
%mulx = mul i128 %ax, %bx
%highx = lshr i128 %mulx, 67
%high = trunc i128 %highx to i64
ret i64 %high
}

; Check sign-extended multiplication in which the result is split into
; high and low halves.
define i64 @f3(i64 %dummy, i64 %a, i64 %b) {
; CHECK-LABEL: f3:
; CHECK-NOT: {{%r[234]}}
; CHECK: mgrk %r2, %r3, %r4
; CHECK: ogr %r2, %r3
; CHECK: br %r14
%ax = sext i64 %a to i128
%bx = sext i64 %b to i128
%mulx = mul i128 %ax, %bx
%highx = lshr i128 %mulx, 64
%high = trunc i128 %highx to i64
%low = trunc i128 %mulx to i64
%or = or i64 %high, %low
ret i64 %or
}

; Check MG with no displacement.
define i64 @f4(i64 %dummy, i64 %a, i64 *%src) {
; CHECK-LABEL: f4:
; CHECK-NOT: {{%r[234]}}
; CHECK: mg %r2, 0(%r4)
; CHECK: br %r14
%b = load i64 , i64 *%src
%ax = sext i64 %a to i128
%bx = sext i64 %b to i128
%mulx = mul i128 %ax, %bx
%highx = lshr i128 %mulx, 64
%high = trunc i128 %highx to i64
ret i64 %high
}

; Check the high end of the aligned MG range.
define i64 @f5(i64 %dummy, i64 %a, i64 *%src) {
; CHECK-LABEL: f5:
; CHECK: mg %r2, 524280(%r4)
; CHECK: br %r14
%ptr = getelementptr i64, i64 *%src, i64 65535
%b = load i64 , i64 *%ptr
%ax = sext i64 %a to i128
%bx = sext i64 %b to i128
%mulx = mul i128 %ax, %bx
%highx = lshr i128 %mulx, 64
%high = trunc i128 %highx to i64
ret i64 %high
}

; Check the next doubleword up, which requires separate address logic.
; Other sequences besides this one would be OK.
define i64 @f6(i64 %dummy, i64 %a, i64 *%src) {
; CHECK-LABEL: f6:
; CHECK: agfi %r4, 524288
; CHECK: mg %r2, 0(%r4)
; CHECK: br %r14
%ptr = getelementptr i64, i64 *%src, i64 65536
%b = load i64 , i64 *%ptr
%ax = sext i64 %a to i128
%bx = sext i64 %b to i128
%mulx = mul i128 %ax, %bx
%highx = lshr i128 %mulx, 64
%high = trunc i128 %highx to i64
ret i64 %high
}

; Check the high end of the negative aligned MG range.
define i64 @f7(i64 %dummy, i64 %a, i64 *%src) {
; CHECK-LABEL: f7:
; CHECK: mg %r2, -8(%r4)
; CHECK: br %r14
%ptr = getelementptr i64, i64 *%src, i64 -1
%b = load i64 , i64 *%ptr
%ax = sext i64 %a to i128
%bx = sext i64 %b to i128
%mulx = mul i128 %ax, %bx
%highx = lshr i128 %mulx, 64
%high = trunc i128 %highx to i64
ret i64 %high
}

; Check the low end of the MG range.
define i64 @f8(i64 %dummy, i64 %a, i64 *%src) {
; CHECK-LABEL: f8:
; CHECK: mg %r2, -524288(%r4)
; CHECK: br %r14
%ptr = getelementptr i64, i64 *%src, i64 -65536
%b = load i64 , i64 *%ptr
%ax = sext i64 %a to i128
%bx = sext i64 %b to i128
%mulx = mul i128 %ax, %bx
%highx = lshr i128 %mulx, 64
%high = trunc i128 %highx to i64
ret i64 %high
}

; Check the next doubleword down, which needs separate address logic.
; Other sequences besides this one would be OK.
define i64 @f9(i64 *%dest, i64 %a, i64 *%src) {
; CHECK-LABEL: f9:
; CHECK: agfi %r4, -524296
; CHECK: mg %r2, 0(%r4)
; CHECK: br %r14
%ptr = getelementptr i64, i64 *%src, i64 -65537
%b = load i64 , i64 *%ptr
%ax = sext i64 %a to i128
%bx = sext i64 %b to i128
%mulx = mul i128 %ax, %bx
%highx = lshr i128 %mulx, 64
%high = trunc i128 %highx to i64
ret i64 %high
}

; Check that MG allows an index.
define i64 @f10(i64 *%dest, i64 %a, i64 %src, i64 %index) {
; CHECK-LABEL: f10:
; CHECK: mg %r2, 524287(%r5,%r4)
; CHECK: br %r14
%add1 = add i64 %src, %index
%add2 = add i64 %add1, 524287
%ptr = inttoptr i64 %add2 to i64 *
%b = load i64 , i64 *%ptr
%ax = sext i64 %a to i128
%bx = sext i64 %b to i128
%mulx = mul i128 %ax, %bx
%highx = lshr i128 %mulx, 64
%high = trunc i128 %highx to i64
ret i64 %high
}

32 changes: 32 additions & 0 deletions llvm/test/CodeGen/SystemZ/int-mul-11.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
; Test three-operand multiplication instructions on z14.
;
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 | FileCheck %s

; Check MSRKC.
define i32 @f1(i32 %dummy, i32 %a, i32 %b) {
; CHECK-LABEL: f1:
; CHECK: msrkc %r2, %r3, %r4
; CHECK: br %r14
%mul = mul i32 %a, %b
ret i32 %mul
}

; Check MSGRKC.
define i64 @f2(i64 %dummy, i64 %a, i64 %b) {
; CHECK-LABEL: f2:
; CHECK: msgrkc %r2, %r3, %r4
; CHECK: br %r14
%mul = mul i64 %a, %b
ret i64 %mul
}

; Verify that we still use MSGFR for i32->i64 multiplies.
define i64 @f3(i64 %a, i32 %b) {
; CHECK-LABEL: f3:
; CHECK: msgfr %r2, %r3
; CHECK: br %r14
%bext = sext i32 %b to i64
%mul = mul i64 %a, %bext
ret i64 %mul
}

95 changes: 95 additions & 0 deletions llvm/test/CodeGen/SystemZ/int-sub-10.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
; Test subtractions of a sign-extended i16 from an i64 on z14.
;
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 | FileCheck %s

declare i64 @foo()

; Check SGH with no displacement.
define i64 @f1(i64 %a, i16 *%src) {
; CHECK-LABEL: f1:
; CHECK: sgh %r2, 0(%r3)
; CHECK: br %r14
%b = load i16, i16 *%src
%bext = sext i16 %b to i64
%sub = sub i64 %a, %bext
ret i64 %sub
}

; Check the high end of the aligned SGH range.
define i64 @f2(i64 %a, i16 *%src) {
; CHECK-LABEL: f2:
; CHECK: sgh %r2, 524286(%r3)
; CHECK: br %r14
%ptr = getelementptr i16, i16 *%src, i64 262143
%b = load i16, i16 *%ptr
%bext = sext i16 %b to i64
%sub = sub i64 %a, %bext
ret i64 %sub
}

; Check the next word up, which needs separate address logic.
; Other sequences besides this one would be OK.
define i64 @f3(i64 %a, i16 *%src) {
; CHECK-LABEL: f3:
; CHECK: agfi %r3, 524288
; CHECK: sgh %r2, 0(%r3)
; CHECK: br %r14
%ptr = getelementptr i16, i16 *%src, i64 262144
%b = load i16, i16 *%ptr
%bext = sext i16 %b to i64
%sub = sub i64 %a, %bext
ret i64 %sub
}

; Check the high end of the negative aligned SGH range.
define i64 @f4(i64 %a, i16 *%src) {
; CHECK-LABEL: f4:
; CHECK: sgh %r2, -2(%r3)
; CHECK: br %r14
%ptr = getelementptr i16, i16 *%src, i64 -1
%b = load i16, i16 *%ptr
%bext = sext i16 %b to i64
%sub = sub i64 %a, %bext
ret i64 %sub
}

; Check the low end of the SGH range.
define i64 @f5(i64 %a, i16 *%src) {
; CHECK-LABEL: f5:
; CHECK: sgh %r2, -524288(%r3)
; CHECK: br %r14
%ptr = getelementptr i16, i16 *%src, i64 -262144
%b = load i16, i16 *%ptr
%bext = sext i16 %b to i64
%sub = sub i64 %a, %bext
ret i64 %sub
}

; Check the next word down, which needs separate address logic.
; Other sequences besides this one would be OK.
define i64 @f6(i64 %a, i16 *%src) {
; CHECK-LABEL: f6:
; CHECK: agfi %r3, -524290
; CHECK: sgh %r2, 0(%r3)
; CHECK: br %r14
%ptr = getelementptr i16, i16 *%src, i64 -262145
%b = load i16, i16 *%ptr
%bext = sext i16 %b to i64
%sub = sub i64 %a, %bext
ret i64 %sub
}

; Check that SGH allows an index.
define i64 @f7(i64 %a, i64 %src, i64 %index) {
; CHECK-LABEL: f7:
; CHECK: sgh %r2, 524284({{%r4,%r3|%r3,%r4}})
; CHECK: br %r14
%add1 = add i64 %src, %index
%add2 = add i64 %add1, 524284
%ptr = inttoptr i64 %add2 to i16 *
%b = load i16, i16 *%ptr
%bext = sext i16 %b to i64
%sub = sub i64 %a, %bext
ret i64 %sub
}

47 changes: 47 additions & 0 deletions llvm/test/CodeGen/SystemZ/vec-and-04.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
; Test vector NAND on z14.
;
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 | FileCheck %s

; Test a v16i8 NAND.
define <16 x i8> @f1(<16 x i8> %dummy, <16 x i8> %val1, <16 x i8> %val2) {
; CHECK-LABEL: f1:
; CHECK: vnn %v24, %v26, %v28
; CHECK: br %r14
%ret = and <16 x i8> %val1, %val2
%not = xor <16 x i8> %ret, <i8 -1, i8 -1, i8 -1, i8 -1,
i8 -1, i8 -1, i8 -1, i8 -1,
i8 -1, i8 -1, i8 -1, i8 -1,
i8 -1, i8 -1, i8 -1, i8 -1>
ret <16 x i8> %not
}

; Test a v8i16 NAND.
define <8 x i16> @f2(<8 x i16> %dummy, <8 x i16> %val1, <8 x i16> %val2) {
; CHECK-LABEL: f2:
; CHECK: vnn %v24, %v26, %v28
; CHECK: br %r14
%ret = and <8 x i16> %val1, %val2
%not = xor <8 x i16> %ret, <i16 -1, i16 -1, i16 -1, i16 -1,
i16 -1, i16 -1, i16 -1, i16 -1>
ret <8 x i16> %not
}

; Test a v4i32 NAND.
define <4 x i32> @f3(<4 x i32> %dummy, <4 x i32> %val1, <4 x i32> %val2) {
; CHECK-LABEL: f3:
; CHECK: vnn %v24, %v26, %v28
; CHECK: br %r14
%ret = and <4 x i32> %val1, %val2
%not = xor <4 x i32> %ret, <i32 -1, i32 -1, i32 -1, i32 -1>
ret <4 x i32> %not
}

; Test a v2i64 NAND.
define <2 x i64> @f4(<2 x i64> %dummy, <2 x i64> %val1, <2 x i64> %val2) {
; CHECK-LABEL: f4:
; CHECK: vnn %v24, %v26, %v28
; CHECK: br %r14
%ret = and <2 x i64> %val1, %val2
%not = xor <2 x i64> %ret, <i64 -1, i64 -1>
ret <2 x i64> %not
}
45 changes: 45 additions & 0 deletions llvm/test/CodeGen/SystemZ/vec-ctpop-02.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
; Test vector population-count instruction on z14.
;
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 | FileCheck %s

declare <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %a)
declare <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %a)
declare <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %a)
declare <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %a)

define <16 x i8> @f1(<16 x i8> %a) {
; CHECK-LABEL: f1:
; CHECK: vpopctb %v24, %v24
; CHECK: br %r14

%popcnt = call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %a)
ret <16 x i8> %popcnt
}

define <8 x i16> @f2(<8 x i16> %a) {
; CHECK-LABEL: f2:
; CHECK: vpopcth %v24, %v24
; CHECK: br %r14

%popcnt = call <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %a)
ret <8 x i16> %popcnt
}

define <4 x i32> @f3(<4 x i32> %a) {
; CHECK-LABEL: f3:
; CHECK: vpopctf %v24, %v24
; CHECK: br %r14

%popcnt = call <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %a)
ret <4 x i32> %popcnt
}

define <2 x i64> @f4(<2 x i64> %a) {
; CHECK-LABEL: f4:
; CHECK: vpopctg %v24, %v24
; CHECK: br %r14

%popcnt = call <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %a)
ret <2 x i64> %popcnt
}

File renamed without changes.
212 changes: 212 additions & 0 deletions llvm/test/CodeGen/SystemZ/vec-intrinsics-02.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
; Test vector intrinsics added with z14.
;
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 | FileCheck %s

declare <2 x i64> @llvm.s390.vbperm(<16 x i8>, <16 x i8>)
declare <16 x i8> @llvm.s390.vmslg(<2 x i64>, <2 x i64>, <16 x i8>, i32)
declare <16 x i8> @llvm.s390.vlrl(i32, i8 *)
declare void @llvm.s390.vstrl(<16 x i8>, i32, i8 *)
declare <2 x double> @llvm.s390.vfmaxdb(<2 x double>, <2 x double>, i32)
declare <2 x double> @llvm.s390.vfmindb(<2 x double>, <2 x double>, i32)

; VBPERM.
define <2 x i64> @test_vbperm(<16 x i8> %a, <16 x i8> %b) {
; CHECK-LABEL: test_vbperm:
; CHECK: vbperm %v24, %v24, %v26
; CHECK: br %r14
%res = call <2 x i64> @llvm.s390.vbperm(<16 x i8> %a, <16 x i8> %b)
ret <2 x i64> %res
}

; VMSLG with no shifts.
define <16 x i8> @test_vmslg1(<2 x i64> %a, <2 x i64> %b, <16 x i8> %c) {
; CHECK-LABEL: test_vmslg1:
; CHECK: vmslg %v24, %v24, %v26, %v28, 0
; CHECK: br %r14
%res = call <16 x i8> @llvm.s390.vmslg(<2 x i64> %a, <2 x i64> %b, <16 x i8> %c, i32 0)
ret <16 x i8> %res
}

; VMSLG with both shifts.
define <16 x i8> @test_vmslg2(<2 x i64> %a, <2 x i64> %b, <16 x i8> %c) {
; CHECK-LABEL: test_vmslg2:
; CHECK: vmslg %v24, %v24, %v26, %v28, 12
; CHECK: br %r14
%res = call <16 x i8> @llvm.s390.vmslg(<2 x i64> %a, <2 x i64> %b, <16 x i8> %c, i32 12)
ret <16 x i8> %res
}

; VLRLR with the lowest in-range displacement.
define <16 x i8> @test_vlrlr1(i8 *%ptr, i32 %length) {
; CHECK-LABEL: test_vlrlr1:
; CHECK: vlrlr %v24, %r3, 0(%r2)
; CHECK: br %r14
%res = call <16 x i8> @llvm.s390.vlrl(i32 %length, i8 *%ptr)
ret <16 x i8> %res
}

; VLRLR with the highest in-range displacement.
define <16 x i8> @test_vlrlr2(i8 *%base, i32 %length) {
; CHECK-LABEL: test_vlrlr2:
; CHECK: vlrlr %v24, %r3, 4095(%r2)
; CHECK: br %r14
%ptr = getelementptr i8, i8 *%base, i64 4095
%res = call <16 x i8> @llvm.s390.vlrl(i32 %length, i8 *%ptr)
ret <16 x i8> %res
}

; VLRLR with an out-of-range displacement.
define <16 x i8> @test_vlrlr3(i8 *%base, i32 %length) {
; CHECK-LABEL: test_vlrlr3:
; CHECK: vlrlr %v24, %r3, 0({{%r[1-5]}})
; CHECK: br %r14
%ptr = getelementptr i8, i8 *%base, i64 4096
%res = call <16 x i8> @llvm.s390.vlrl(i32 %length, i8 *%ptr)
ret <16 x i8> %res
}

; Check that VLRLR doesn't allow an index.
define <16 x i8> @test_vlrlr4(i8 *%base, i64 %index, i32 %length) {
; CHECK-LABEL: test_vlrlr4:
; CHECK: vlrlr %v24, %r4, 0({{%r[1-5]}})
; CHECK: br %r14
%ptr = getelementptr i8, i8 *%base, i64 %index
%res = call <16 x i8> @llvm.s390.vlrl(i32 %length, i8 *%ptr)
ret <16 x i8> %res
}

; VLRL with the lowest in-range displacement.
define <16 x i8> @test_vlrl1(i8 *%ptr) {
; CHECK-LABEL: test_vlrl1:
; CHECK: vlrl %v24, 0(%r2), 0
; CHECK: br %r14
%res = call <16 x i8> @llvm.s390.vlrl(i32 0, i8 *%ptr)
ret <16 x i8> %res
}

; VLRL with the highest in-range displacement.
define <16 x i8> @test_vlrl2(i8 *%base) {
; CHECK-LABEL: test_vlrl2:
; CHECK: vlrl %v24, 4095(%r2), 0
; CHECK: br %r14
%ptr = getelementptr i8, i8 *%base, i64 4095
%res = call <16 x i8> @llvm.s390.vlrl(i32 0, i8 *%ptr)
ret <16 x i8> %res
}

; VLRL with an out-of-range displacement.
define <16 x i8> @test_vlrl3(i8 *%base) {
; CHECK-LABEL: test_vlrl3:
; CHECK: vlrl %v24, 0({{%r[1-5]}}), 0
; CHECK: br %r14
%ptr = getelementptr i8, i8 *%base, i64 4096
%res = call <16 x i8> @llvm.s390.vlrl(i32 0, i8 *%ptr)
ret <16 x i8> %res
}

; Check that VLRL doesn't allow an index.
define <16 x i8> @test_vlrl4(i8 *%base, i64 %index) {
; CHECK-LABEL: test_vlrl4:
; CHECK: vlrl %v24, 0({{%r[1-5]}}), 0
; CHECK: br %r14
%ptr = getelementptr i8, i8 *%base, i64 %index
%res = call <16 x i8> @llvm.s390.vlrl(i32 0, i8 *%ptr)
ret <16 x i8> %res
}

; VSTRLR with the lowest in-range displacement.
define void @test_vstrlr1(<16 x i8> %vec, i8 *%ptr, i32 %length) {
; CHECK-LABEL: test_vstrlr1:
; CHECK: vstrlr %v24, %r3, 0(%r2)
; CHECK: br %r14
call void @llvm.s390.vstrl(<16 x i8> %vec, i32 %length, i8 *%ptr)
ret void
}

; VSTRLR with the highest in-range displacement.
define void @test_vstrlr2(<16 x i8> %vec, i8 *%base, i32 %length) {
; CHECK-LABEL: test_vstrlr2:
; CHECK: vstrlr %v24, %r3, 4095(%r2)
; CHECK: br %r14
%ptr = getelementptr i8, i8 *%base, i64 4095
call void @llvm.s390.vstrl(<16 x i8> %vec, i32 %length, i8 *%ptr)
ret void
}

; VSTRLR with an out-of-range displacement.
define void @test_vstrlr3(<16 x i8> %vec, i8 *%base, i32 %length) {
; CHECK-LABEL: test_vstrlr3:
; CHECK: vstrlr %v24, %r3, 0({{%r[1-5]}})
; CHECK: br %r14
%ptr = getelementptr i8, i8 *%base, i64 4096
call void @llvm.s390.vstrl(<16 x i8> %vec, i32 %length, i8 *%ptr)
ret void
}

; Check that VSTRLR doesn't allow an index.
define void @test_vstrlr4(<16 x i8> %vec, i8 *%base, i64 %index, i32 %length) {
; CHECK-LABEL: test_vstrlr4:
; CHECK: vstrlr %v24, %r4, 0({{%r[1-5]}})
; CHECK: br %r14
%ptr = getelementptr i8, i8 *%base, i64 %index
call void @llvm.s390.vstrl(<16 x i8> %vec, i32 %length, i8 *%ptr)
ret void
}

; VSTRL with the lowest in-range displacement.
define void @test_vstrl1(<16 x i8> %vec, i8 *%ptr) {
; CHECK-LABEL: test_vstrl1:
; CHECK: vstrl %v24, 0(%r2), 8
; CHECK: br %r14
call void @llvm.s390.vstrl(<16 x i8> %vec, i32 8, i8 *%ptr)
ret void
}

; VSTRL with the highest in-range displacement.
define void @test_vstrl2(<16 x i8> %vec, i8 *%base) {
; CHECK-LABEL: test_vstrl2:
; CHECK: vstrl %v24, 4095(%r2), 8
; CHECK: br %r14
%ptr = getelementptr i8, i8 *%base, i64 4095
call void @llvm.s390.vstrl(<16 x i8> %vec, i32 8, i8 *%ptr)
ret void
}

; VSTRL with an out-of-range displacement.
define void @test_vstrl3(<16 x i8> %vec, i8 *%base) {
; CHECK-LABEL: test_vstrl3:
; CHECK: vstrl %v24, 0({{%r[1-5]}}), 8
; CHECK: br %r14
%ptr = getelementptr i8, i8 *%base, i64 4096
call void @llvm.s390.vstrl(<16 x i8> %vec, i32 8, i8 *%ptr)
ret void
}

; Check that VSTRL doesn't allow an index.
define void @test_vstrl4(<16 x i8> %vec, i8 *%base, i64 %index) {
; CHECK-LABEL: test_vstrl4:
; CHECK: vstrl %v24, 0({{%r[1-5]}}), 8
; CHECK: br %r14
%ptr = getelementptr i8, i8 *%base, i64 %index
call void @llvm.s390.vstrl(<16 x i8> %vec, i32 8, i8 *%ptr)
ret void
}

; VFMAXDB.
define <2 x double> @test_vfmaxdb(<2 x double> %a, <2 x double> %b) {
; CHECK-LABEL: test_vfmaxdb:
; CHECK: vfmaxdb %v24, %v24, %v26, 4
; CHECK: br %r14
%res = call <2 x double> @llvm.s390.vfmaxdb(<2 x double> %a, <2 x double> %b, i32 4)
ret <2 x double> %res
}

; VFMINDB.
define <2 x double> @test_vfmindb(<2 x double> %a, <2 x double> %b) {
; CHECK-LABEL: test_vfmindb:
; CHECK: vfmindb %v24, %v24, %v26, 4
; CHECK: br %r14
%res = call <2 x double> @llvm.s390.vfmindb(<2 x double> %a, <2 x double> %b, i32 4)
ret <2 x double> %res
}

58 changes: 58 additions & 0 deletions llvm/test/CodeGen/SystemZ/vec-max-05.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
; Test vector maximum on z14.
;
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 | FileCheck %s

declare double @fmax(double, double)
declare double @llvm.maxnum.f64(double, double)
declare <2 x double> @llvm.maxnum.v2f64(<2 x double>, <2 x double>)

; Test the fmax library function.
define double @f1(double %dummy, double %val1, double %val2) {
; CHECK-LABEL: f1:
; CHECK: wfmaxdb %f0, %f2, %f4, 4
; CHECK: br %r14
%ret = call double @fmax(double %val1, double %val2) readnone
ret double %ret
}

; Test the f64 maxnum intrinsic.
define double @f2(double %dummy, double %val1, double %val2) {
; CHECK-LABEL: f2:
; CHECK: wfmaxdb %f0, %f2, %f4, 4
; CHECK: br %r14
%ret = call double @llvm.maxnum.f64(double %val1, double %val2)
ret double %ret
}

; Test a f64 constant compare/select resulting in maxnum.
define double @f3(double %dummy, double %val) {
; CHECK-LABEL: f3:
; CHECK: lzdr [[REG:%f[0-9]+]]
; CHECK: wfmaxdb %f0, %f2, [[REG]], 4
; CHECK: br %r14
%cmp = fcmp ogt double %val, 0.0
%ret = select i1 %cmp, double %val, double 0.0
ret double %ret
}

; Test a f64 constant compare/select resulting in maxnan.
define double @f4(double %dummy, double %val) {
; CHECK-LABEL: f4:
; CHECK: lzdr [[REG:%f[0-9]+]]
; CHECK: wfmaxdb %f0, %f2, [[REG]], 1
; CHECK: br %r14
%cmp = fcmp ugt double %val, 0.0
%ret = select i1 %cmp, double %val, double 0.0
ret double %ret
}

; Test the v2f64 maxnum intrinsic.
define <2 x double> @f5(<2 x double> %dummy, <2 x double> %val1,
<2 x double> %val2) {
; CHECK-LABEL: f5:
; CHECK: vfmaxdb %v24, %v26, %v28, 4
; CHECK: br %r14
%ret = call <2 x double> @llvm.maxnum.v2f64(<2 x double> %val1, <2 x double> %val2)
ret <2 x double> %ret
}

58 changes: 58 additions & 0 deletions llvm/test/CodeGen/SystemZ/vec-min-05.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
; Test vector minimum on z14.
;
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 | FileCheck %s

declare double @fmin(double, double)
declare double @llvm.minnum.f64(double, double)
declare <2 x double> @llvm.minnum.v2f64(<2 x double>, <2 x double>)

; Test the fmin library function.
define double @f1(double %dummy, double %val1, double %val2) {
; CHECK-LABEL: f1:
; CHECK: wfmindb %f0, %f2, %f4, 4
; CHECK: br %r14
%ret = call double @fmin(double %val1, double %val2) readnone
ret double %ret
}

; Test the f64 minnum intrinsic.
define double @f2(double %dummy, double %val1, double %val2) {
; CHECK-LABEL: f2:
; CHECK: wfmindb %f0, %f2, %f4, 4
; CHECK: br %r14
%ret = call double @llvm.minnum.f64(double %val1, double %val2)
ret double %ret
}

; Test a f64 constant compare/select resulting in minnum.
define double @f3(double %dummy, double %val) {
; CHECK-LABEL: f3:
; CHECK: lzdr [[REG:%f[0-9]+]]
; CHECK: wfmindb %f0, %f2, [[REG]], 4
; CHECK: br %r14
%cmp = fcmp olt double %val, 0.0
%ret = select i1 %cmp, double %val, double 0.0
ret double %ret
}

; Test a f64 constant compare/select resulting in minnan.
define double @f4(double %dummy, double %val) {
; CHECK-LABEL: f4:
; CHECK: lzdr [[REG:%f[0-9]+]]
; CHECK: wfmindb %f0, %f2, [[REG]], 1
; CHECK: br %r14
%cmp = fcmp ult double %val, 0.0
%ret = select i1 %cmp, double %val, double 0.0
ret double %ret
}

; Test the v2f64 minnum intrinsic.
define <2 x double> @f5(<2 x double> %dummy, <2 x double> %val1,
<2 x double> %val2) {
; CHECK-LABEL: f5:
; CHECK: vfmindb %v24, %v26, %v28, 4
; CHECK: br %r14
%ret = call <2 x double> @llvm.minnum.v2f64(<2 x double> %val1, <2 x double> %val2)
ret <2 x double> %ret
}

24 changes: 24 additions & 0 deletions llvm/test/CodeGen/SystemZ/vec-move-18.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
; Test insertions of memory values into 0 on z14.
;
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 | FileCheck %s

; Test VLLEZLF.
define <4 x i32> @f1(i32 *%ptr) {
; CHECK-LABEL: f1:
; CHECK: vllezlf %v24, 0(%r2)
; CHECK: br %r14
%val = load i32, i32 *%ptr
%ret = insertelement <4 x i32> zeroinitializer, i32 %val, i32 0
ret <4 x i32> %ret
}

; Test VLLEZLF with a float.
define <4 x float> @f2(float *%ptr) {
; CHECK-LABEL: f2:
; CHECK: vllezlf %v24, 0(%r2)
; CHECK: br %r14
%val = load float, float *%ptr
%ret = insertelement <4 x float> zeroinitializer, float %val, i32 0
ret <4 x float> %ret
}

32 changes: 32 additions & 0 deletions llvm/test/CodeGen/SystemZ/vec-mul-05.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
; Test vector negative multiply-and-add on z14.
;
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 | FileCheck %s

declare <2 x double> @llvm.fma.v2f64(<2 x double>, <2 x double>, <2 x double>)

; Test a v2f64 negative multiply-and-add.
define <2 x double> @f1(<2 x double> %dummy, <2 x double> %val1,
<2 x double> %val2, <2 x double> %val3) {
; CHECK-LABEL: f1:
; CHECK: vfnmadb %v24, %v26, %v28, %v30
; CHECK: br %r14
%ret = call <2 x double> @llvm.fma.v2f64 (<2 x double> %val1,
<2 x double> %val2,
<2 x double> %val3)
%negret = fsub <2 x double> <double -0.0, double -0.0>, %ret
ret <2 x double> %negret
}

; Test a v2f64 negative multiply-and-subtract.
define <2 x double> @f2(<2 x double> %dummy, <2 x double> %val1,
<2 x double> %val2, <2 x double> %val3) {
; CHECK-LABEL: f2:
; CHECK: vfnmsdb %v24, %v26, %v28, %v30
; CHECK: br %r14
%negval3 = fsub <2 x double> <double -0.0, double -0.0>, %val3
%ret = call <2 x double> @llvm.fma.v2f64 (<2 x double> %val1,
<2 x double> %val2,
<2 x double> %negval3)
%negret = fsub <2 x double> <double -0.0, double -0.0>, %ret
ret <2 x double> %negret
}
91 changes: 91 additions & 0 deletions llvm/test/CodeGen/SystemZ/vec-or-03.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
; Test vector OR-NOT on z14.
;
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 | FileCheck %s

; Test a v16i8 OR-NOT.
define <16 x i8> @f1(<16 x i8> %dummy, <16 x i8> %val1, <16 x i8> %val2) {
; CHECK-LABEL: f1:
; CHECK: voc %v24, %v26, %v28
; CHECK: br %r14
%not = xor <16 x i8> %val2, <i8 -1, i8 -1, i8 -1, i8 -1,
i8 -1, i8 -1, i8 -1, i8 -1,
i8 -1, i8 -1, i8 -1, i8 -1,
i8 -1, i8 -1, i8 -1, i8 -1>
%ret = or <16 x i8> %val1, %not
ret <16 x i8> %ret
}

; ...and again with the reverse.
define <16 x i8> @f2(<16 x i8> %dummy, <16 x i8> %val1, <16 x i8> %val2) {
; CHECK-LABEL: f2:
; CHECK: voc %v24, %v28, %v26
; CHECK: br %r14
%not = xor <16 x i8> %val1, <i8 -1, i8 -1, i8 -1, i8 -1,
i8 -1, i8 -1, i8 -1, i8 -1,
i8 -1, i8 -1, i8 -1, i8 -1,
i8 -1, i8 -1, i8 -1, i8 -1>
%ret = or <16 x i8> %not, %val2
ret <16 x i8> %ret
}

; Test a v8i16 OR-NOT.
define <8 x i16> @f3(<8 x i16> %dummy, <8 x i16> %val1, <8 x i16> %val2) {
; CHECK-LABEL: f3:
; CHECK: voc %v24, %v26, %v28
; CHECK: br %r14
%not = xor <8 x i16> %val2, <i16 -1, i16 -1, i16 -1, i16 -1,
i16 -1, i16 -1, i16 -1, i16 -1>
%ret = or <8 x i16> %val1, %not
ret <8 x i16> %ret
}

; ...and again with the reverse.
define <8 x i16> @f4(<8 x i16> %dummy, <8 x i16> %val1, <8 x i16> %val2) {
; CHECK-LABEL: f4:
; CHECK: voc %v24, %v28, %v26
; CHECK: br %r14
%not = xor <8 x i16> %val1, <i16 -1, i16 -1, i16 -1, i16 -1,
i16 -1, i16 -1, i16 -1, i16 -1>
%ret = or <8 x i16> %not, %val2
ret <8 x i16> %ret
}

; Test a v4i32 OR-NOT.
define <4 x i32> @f5(<4 x i32> %dummy, <4 x i32> %val1, <4 x i32> %val2) {
; CHECK-LABEL: f5:
; CHECK: voc %v24, %v26, %v28
; CHECK: br %r14
%not = xor <4 x i32> %val2, <i32 -1, i32 -1, i32 -1, i32 -1>
%ret = or <4 x i32> %val1, %not
ret <4 x i32> %ret
}

; ...and again with the reverse.
define <4 x i32> @f6(<4 x i32> %dummy, <4 x i32> %val1, <4 x i32> %val2) {
; CHECK-LABEL: f6:
; CHECK: voc %v24, %v28, %v26
; CHECK: br %r14
%not = xor <4 x i32> %val1, <i32 -1, i32 -1, i32 -1, i32 -1>
%ret = or <4 x i32> %not, %val2
ret <4 x i32> %ret
}

; Test a v2i64 OR-NOT.
define <2 x i64> @f7(<2 x i64> %dummy, <2 x i64> %val1, <2 x i64> %val2) {
; CHECK-LABEL: f7:
; CHECK: voc %v24, %v26, %v28
; CHECK: br %r14
%not = xor <2 x i64> %val2, <i64 -1, i64 -1>
%ret = or <2 x i64> %val1, %not
ret <2 x i64> %ret
}

; ...and again with the reverse.
define <2 x i64> @f8(<2 x i64> %dummy, <2 x i64> %val1, <2 x i64> %val2) {
; CHECK-LABEL: f8:
; CHECK: voc %v24, %v28, %v26
; CHECK: br %r14
%not = xor <2 x i64> %val1, <i64 -1, i64 -1>
%ret = or <2 x i64> %not, %val2
ret <2 x i64> %ret
}
47 changes: 47 additions & 0 deletions llvm/test/CodeGen/SystemZ/vec-xor-02.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
; Test vector NOT-XOR on z14.
;
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 | FileCheck %s

; Test a v16i8 NOT-XOR.
define <16 x i8> @f1(<16 x i8> %dummy, <16 x i8> %val1, <16 x i8> %val2) {
; CHECK-LABEL: f1:
; CHECK: vnx %v24, %v26, %v28
; CHECK: br %r14
%ret = xor <16 x i8> %val1, %val2
%not = xor <16 x i8> %ret, <i8 -1, i8 -1, i8 -1, i8 -1,
i8 -1, i8 -1, i8 -1, i8 -1,
i8 -1, i8 -1, i8 -1, i8 -1,
i8 -1, i8 -1, i8 -1, i8 -1>
ret <16 x i8> %not
}

; Test a v8i16 NOT-XOR.
define <8 x i16> @f2(<8 x i16> %dummy, <8 x i16> %val1, <8 x i16> %val2) {
; CHECK-LABEL: f2:
; CHECK: vnx %v24, %v26, %v28
; CHECK: br %r14
%ret = xor <8 x i16> %val1, %val2
%not = xor <8 x i16> %ret, <i16 -1, i16 -1, i16 -1, i16 -1,
i16 -1, i16 -1, i16 -1, i16 -1>
ret <8 x i16> %not
}

; Test a v4i32 NOT-XOR.
define <4 x i32> @f3(<4 x i32> %dummy, <4 x i32> %val1, <4 x i32> %val2) {
; CHECK-LABEL: f3:
; CHECK: vnx %v24, %v26, %v28
; CHECK: br %r14
%ret = xor <4 x i32> %val1, %val2
%not = xor <4 x i32> %ret, <i32 -1, i32 -1, i32 -1, i32 -1>
ret <4 x i32> %not
}

; Test a v2i64 NOT-XOR.
define <2 x i64> @f4(<2 x i64> %dummy, <2 x i64> %val1, <2 x i64> %val2) {
; CHECK-LABEL: f4:
; CHECK: vnx %v24, %v26, %v28
; CHECK: br %r14
%ret = xor <2 x i64> %val1, %val2
%not = xor <2 x i64> %ret, <i64 -1, i64 -1>
ret <2 x i64> %not
}
1,594 changes: 1,594 additions & 0 deletions llvm/test/MC/Disassembler/SystemZ/insns-z14.txt

Large diffs are not rendered by default.

344 changes: 344 additions & 0 deletions llvm/test/MC/SystemZ/insn-bad-z13.s

Large diffs are not rendered by default.

562 changes: 562 additions & 0 deletions llvm/test/MC/SystemZ/insn-bad-z14.s

Large diffs are not rendered by default.

1,282 changes: 1,282 additions & 0 deletions llvm/test/MC/SystemZ/insn-good-z14.s

Large diffs are not rendered by default.