Index: lib/Target/SystemZ/SystemZ.td =================================================================== --- lib/Target/SystemZ/SystemZ.td +++ lib/Target/SystemZ/SystemZ.td @@ -58,7 +58,7 @@ include "SystemZInstrDFP.td" include "SystemZInstrSystem.td" -def SystemZInstrInfo : InstrInfo {} +def SystemZInstrInfo : InstrInfo { let guessInstructionProperties = 0; } //===----------------------------------------------------------------------===// // Assembly parser Index: lib/Target/SystemZ/SystemZInstrDFP.td =================================================================== --- lib/Target/SystemZ/SystemZInstrDFP.td +++ lib/Target/SystemZ/SystemZInstrDFP.td @@ -15,6 +15,11 @@ // //===----------------------------------------------------------------------===// +// In general, most floating-point instructions (except for simple moves and +// the like) should have the side-effects flag, since they can raise +// exceptions. +let hasSideEffects = 1 in { + //===----------------------------------------------------------------------===// // Move instructions //===----------------------------------------------------------------------===// @@ -229,3 +234,4 @@ def TDGXT : TestRXE<"tdgxt", 0xED59, null_frag, FP128>; } +} // hasSideEffects = 1 Index: lib/Target/SystemZ/SystemZInstrFP.td =================================================================== --- lib/Target/SystemZ/SystemZInstrFP.td +++ lib/Target/SystemZ/SystemZInstrFP.td @@ -29,22 +29,20 @@ //===----------------------------------------------------------------------===// // Load zero. -let hasSideEffects = 0, isAsCheapAsAMove = 1, isMoveImm = 1 in { +let isAsCheapAsAMove = 1, isMoveImm = 1 in { def LZER : InherentRRE<"lzer", 0xB374, FP32, fpimm0>; def LZDR : InherentRRE<"lzdr", 0xB375, FP64, fpimm0>; def LZXR : InherentRRE<"lzxr", 0xB376, FP128, fpimm0>; } // Moves between two floating-point registers. -let hasSideEffects = 0 in { - def LER : UnaryRR <"ler", 0x38, null_frag, FP32, FP32>; - def LDR : UnaryRR <"ldr", 0x28, null_frag, FP64, FP64>; - def LXR : UnaryRRE<"lxr", 0xB365, null_frag, FP128, FP128>; - - // For z13 we prefer LDR over LER to avoid partial register dependencies. - let isCodeGenOnly = 1 in - def LDR32 : UnaryRR<"ldr", 0x28, null_frag, FP32, FP32>; -} +def LER : UnaryRR <"ler", 0x38, null_frag, FP32, FP32>; +def LDR : UnaryRR <"ldr", 0x28, null_frag, FP64, FP64>; +def LXR : UnaryRRE<"lxr", 0xB365, null_frag, FP128, FP128>; + +// For z13 we prefer LDR over LER to avoid partial register dependencies. +let isCodeGenOnly = 1 in + def LDR32 : UnaryRR<"ldr", 0x28, null_frag, FP32, FP32>; // Moves between two floating-point registers that also set the condition // codes. @@ -135,12 +133,12 @@ defm LD : UnaryRXPair<"ld", 0x68, 0xED65, load, FP64, 8>; // For z13 we prefer LDE over LE to avoid partial register dependencies. - let isCodeGenOnly = 1 in + let isCodeGenOnly = 1, hasSideEffects = 1 in def LDE32 : UnaryRXE<"lde", 0xED24, null_frag, FP32, 4>; // These instructions are split after register allocation, so we don't // want a custom inserter. - let Has20BitOffset = 1, HasIndex = 1, Is128Bit = 1 in { + let Has20BitOffset = 1, HasIndex = 1, Is128Bit = 1, mayLoad = 1 in { def LX : Pseudo<(outs FP128:$dst), (ins bdxaddr20only128:$src), [(set FP128:$dst, (load bdxaddr20only128:$src))]>; } @@ -156,7 +154,7 @@ // These instructions are split after register allocation, so we don't // want a custom inserter. - let Has20BitOffset = 1, HasIndex = 1, Is128Bit = 1 in { + let Has20BitOffset = 1, HasIndex = 1, Is128Bit = 1, mayStore = 1 in { def STX : Pseudo<(outs), (ins FP128:$src, bdxaddr20only128:$dst), [(store FP128:$src, bdxaddr20only128:$dst)]>; } @@ -170,15 +168,18 @@ // according to the current mode. The destination of LEXBR and LDXBR // is a 128-bit value, but only the first register of the pair is used. def LEDBR : UnaryRRE<"ledbr", 0xB344, fpround, FP32, FP64>; -def LEXBR : UnaryRRE<"lexbr", 0xB346, null_frag, FP128, FP128>; -def LDXBR : UnaryRRE<"ldxbr", 0xB345, null_frag, FP128, FP128>; -def LEDBRA : TernaryRRFe<"ledbra", 0xB344, FP32, FP64>, - Requires<[FeatureFPExtension]>; -def LEXBRA : TernaryRRFe<"lexbra", 0xB346, FP128, FP128>, - Requires<[FeatureFPExtension]>; -def LDXBRA : TernaryRRFe<"ldxbra", 0xB345, FP128, FP128>, - Requires<[FeatureFPExtension]>; +let hasSideEffects = 1 in { + def LEXBR : UnaryRRE<"lexbr", 0xB346, null_frag, FP128, FP128>; + def LDXBR : UnaryRRE<"ldxbr", 0xB345, null_frag, FP128, FP128>; + + def LEDBRA : TernaryRRFe<"ledbra", 0xB344, FP32, FP64>, + Requires<[FeatureFPExtension]>; + def LEXBRA : TernaryRRFe<"lexbra", 0xB346, FP128, FP128>, + Requires<[FeatureFPExtension]>; + def LDXBRA : TernaryRRFe<"ldxbra", 0xB345, FP128, FP128>, + Requires<[FeatureFPExtension]>; +} let Predicates = [FeatureNoVectorEnhancements1] in { def : Pat<(f32 (fpround FP128:$src)), @@ -218,7 +219,7 @@ // The FP extension feature provides versions of the above that allow // specifying rounding mode and inexact-exception suppression flags. -let Predicates = [FeatureFPExtension] in { +let Predicates = [FeatureFPExtension], hasSideEffects = 1 in { def CEFBRA : TernaryRRFe<"cefbra", 0xB394, FP32, GR32>; def CDFBRA : TernaryRRFe<"cdfbra", 0xB395, FP64, GR32>; def CXFBRA : TernaryRRFe<"cxfbra", 0xB396, FP128, GR32>; @@ -270,7 +271,7 @@ // The FP extension feature provides versions of the above that allow // also specifying the inexact-exception suppression flag. -let Predicates = [FeatureFPExtension], Defs = [CC] in { +let Predicates = [FeatureFPExtension], Defs = [CC], hasSideEffects = 1 in { def CFEBRA : TernaryRRFe<"cfebra", 0xB398, GR32, FP32>; def CFDBRA : TernaryRRFe<"cfdbra", 0xB399, GR32, FP64>; def CFXBRA : TernaryRRFe<"cfxbra", 0xB39A, GR32, FP128>; @@ -316,8 +317,10 @@ // Negation (Load Complement). let Defs = [CC], CCValues = 0xF, CompareZeroCCMask = 0xF in { - def LCEBR : UnaryRRE<"lcebr", 0xB303, null_frag, FP32, FP32>; - def LCDBR : UnaryRRE<"lcdbr", 0xB313, null_frag, FP64, FP64>; + let hasSideEffects = 1 in { + def LCEBR : UnaryRRE<"lcebr", 0xB303, null_frag, FP32, FP32>; + def LCDBR : UnaryRRE<"lcdbr", 0xB313, null_frag, FP64, FP64>; + } def LCXBR : UnaryRRE<"lcxbr", 0xB343, fneg, FP128, FP128>; } // Generic form, which does not set CC. @@ -327,8 +330,10 @@ // Absolute value (Load Positive). let Defs = [CC], CCValues = 0xF, CompareZeroCCMask = 0xF in { - def LPEBR : UnaryRRE<"lpebr", 0xB300, null_frag, FP32, FP32>; - def LPDBR : UnaryRRE<"lpdbr", 0xB310, null_frag, FP64, FP64>; + let hasSideEffects = 1 in { + def LPEBR : UnaryRRE<"lpebr", 0xB300, null_frag, FP32, FP32>; + def LPDBR : UnaryRRE<"lpdbr", 0xB310, null_frag, FP64, FP64>; + } def LPXBR : UnaryRRE<"lpxbr", 0xB340, fabs, FP128, FP128>; } // Generic form, which does not set CC. @@ -338,8 +343,10 @@ // Negative absolute value (Load Negative). let Defs = [CC], CCValues = 0xF, CompareZeroCCMask = 0xF in { - def LNEBR : UnaryRRE<"lnebr", 0xB301, null_frag, FP32, FP32>; - def LNDBR : UnaryRRE<"lndbr", 0xB311, null_frag, FP64, FP64>; + let hasSideEffects = 1 in { + def LNEBR : UnaryRRE<"lnebr", 0xB301, null_frag, FP32, FP32>; + def LNDBR : UnaryRRE<"lndbr", 0xB311, null_frag, FP64, FP64>; + } def LNXBR : UnaryRRE<"lnxbr", 0xB341, fnabs, FP128, FP128>; } // Generic form, which does not set CC. @@ -438,27 +445,31 @@ def MDB : BinaryRXE<"mdb", 0xED1C, fmul, FP64, load, 8>; // f64 multiplication of two FP32 registers. -def MDEBR : BinaryRRE<"mdebr", 0xB30C, null_frag, FP64, FP32>; +let hasSideEffects = 1 in + def MDEBR : BinaryRRE<"mdebr", 0xB30C, null_frag, FP64, FP32>; def : Pat<(fmul (f64 (fpextend FP32:$src1)), (f64 (fpextend FP32:$src2))), (MDEBR (INSERT_SUBREG (f64 (IMPLICIT_DEF)), FP32:$src1, subreg_r32), FP32:$src2)>; // f64 multiplication of an FP32 register and an f32 memory. -def MDEB : BinaryRXE<"mdeb", 0xED0C, null_frag, FP64, load, 4>; +let hasSideEffects = 1 in + def MDEB : BinaryRXE<"mdeb", 0xED0C, null_frag, FP64, load, 4>; def : Pat<(fmul (f64 (fpextend FP32:$src1)), (f64 (extloadf32 bdxaddr12only:$addr))), (MDEB (INSERT_SUBREG (f64 (IMPLICIT_DEF)), FP32:$src1, subreg_r32), bdxaddr12only:$addr)>; // f128 multiplication of two FP64 registers. -def MXDBR : BinaryRRE<"mxdbr", 0xB307, null_frag, FP128, FP64>; +let hasSideEffects = 1 in + def MXDBR : BinaryRRE<"mxdbr", 0xB307, null_frag, FP128, FP64>; let Predicates = [FeatureNoVectorEnhancements1] in def : Pat<(fmul (f128 (fpextend FP64:$src1)), (f128 (fpextend FP64:$src2))), (MXDBR (INSERT_SUBREG (f128 (IMPLICIT_DEF)), FP64:$src1, subreg_h64), FP64:$src2)>; // f128 multiplication of an FP64 register and an f64 memory. -def MXDB : BinaryRXE<"mxdb", 0xED07, null_frag, FP128, load, 8>; +let hasSideEffects = 1 in + def MXDB : BinaryRXE<"mxdb", 0xED07, null_frag, FP128, load, 8>; let Predicates = [FeatureNoVectorEnhancements1] in def : Pat<(fmul (f128 (fpextend FP64:$src1)), (f128 (extloadf64 bdxaddr12only:$addr))), @@ -488,7 +499,7 @@ def DDB : BinaryRXE<"ddb", 0xED1D, fdiv, FP64, load, 8>; // Divide to integer. -let Defs = [CC] in { +let Defs = [CC], hasSideEffects = 1 in { def DIEBR : TernaryRRFb<"diebr", 0xB353, FP32, FP32, FP32>; def DIDBR : TernaryRRFb<"didbr", 0xB35B, FP64, FP64, FP64>; } @@ -505,12 +516,14 @@ def CEB : CompareRXE<"ceb", 0xED09, z_fcmp, FP32, load, 4>; def CDB : CompareRXE<"cdb", 0xED19, z_fcmp, FP64, load, 8>; - def KEBR : CompareRRE<"kebr", 0xB308, null_frag, FP32, FP32>; - def KDBR : CompareRRE<"kdbr", 0xB318, null_frag, FP64, FP64>; - def KXBR : CompareRRE<"kxbr", 0xB348, null_frag, FP128, FP128>; + let hasSideEffects = 1 in { + def KEBR : CompareRRE<"kebr", 0xB308, null_frag, FP32, FP32>; + def KDBR : CompareRRE<"kdbr", 0xB318, null_frag, FP64, FP64>; + def KXBR : CompareRRE<"kxbr", 0xB348, null_frag, FP128, FP128>; - def KEB : CompareRXE<"keb", 0xED08, null_frag, FP32, load, 4>; - def KDB : CompareRXE<"kdb", 0xED18, null_frag, FP64, load, 8>; + def KEB : CompareRXE<"keb", 0xED08, null_frag, FP32, load, 4>; + def KDB : CompareRXE<"kdb", 0xED18, null_frag, FP64, load, 8>; + } } // Test Data Class. @@ -525,11 +538,13 @@ //===----------------------------------------------------------------------===// let hasSideEffects = 1 in { - def EFPC : InherentRRE<"efpc", 0xB38C, GR32, int_s390_efpc>; - def STFPC : StoreInherentS<"stfpc", 0xB29C, storei, 4>; + let mayLoad = 1, mayStore = 1 in { + def EFPC : InherentRRE<"efpc", 0xB38C, GR32, int_s390_efpc>; + def STFPC : StoreInherentS<"stfpc", 0xB29C, storei, 4>; - def SFPC : SideEffectUnaryRRE<"sfpc", 0xB384, GR32, int_s390_sfpc>; - def LFPC : SideEffectUnaryS<"lfpc", 0xB29D, loadu, 4>; + def SFPC : SideEffectUnaryRRE<"sfpc", 0xB384, GR32, int_s390_sfpc>; + def LFPC : SideEffectUnaryS<"lfpc", 0xB29D, loadu, 4>; + } def SFASR : SideEffectUnaryRRE<"sfasr", 0xB385, GR32, null_frag>; def LFAS : SideEffectUnaryS<"lfas", 0xB2BD, null_frag, 4>; Index: lib/Target/SystemZ/SystemZInstrFormats.td =================================================================== --- lib/Target/SystemZ/SystemZInstrFormats.td +++ lib/Target/SystemZ/SystemZInstrFormats.td @@ -21,6 +21,10 @@ let Pattern = pattern; let AsmString = asmstr; + let hasSideEffects = 0; + let mayLoad = 0; + let mayStore = 0; + // Some instructions come in pairs, one having a 12-bit displacement // and the other having a 20-bit displacement. Both instructions in // the pair have the same DispKey and their DispSizes are "12" and "20" @@ -1992,18 +1996,22 @@ } class SideEffectInherentEopcode> - : InstE; + : InstE { + let hasSideEffects = 1; +} class SideEffectInherentS opcode, SDPatternOperator operator> : InstS { let BD2 = 0; + let hasSideEffects = 1; } class SideEffectInherentRRE opcode> : InstRRE { let R1 = 0; let R2 = 0; + let hasSideEffects = 1; } // Allow an optional TLS marker symbol to generate TLS call relocations. @@ -2615,12 +2623,15 @@ class SideEffectUnaryI opcode, Immediate imm> : InstI; + mnemonic#"\t$I1", []> { + let hasSideEffects = 1; +} class SideEffectUnaryRRopcode, RegisterOperand cls> : InstRR { let R2 = 0; + let hasSideEffects = 1; } class SideEffectUnaryRRE opcode, RegisterOperand cls, @@ -2628,6 +2639,7 @@ : InstRRE { let R2 = 0; + let hasSideEffects = 1; } class SideEffectUnaryS opcode, @@ -2637,13 +2649,16 @@ mnemonic#"\t$BD2", [(operator mode:$BD2)]> { let mayLoad = 1; let AccessBytes = bytes; + let hasSideEffects = 1; } class SideEffectAddressS opcode, SDPatternOperator operator, AddressingMode mode = bdaddr12only> : InstS; + mnemonic#"\t$BD2", [(operator mode:$BD2)]> { + let hasSideEffects = 1; +} class LoadAddressRX opcode, SDPatternOperator operator, AddressingMode mode> @@ -2781,7 +2796,8 @@ AddressingMode mode = bdaddr20only> { let isCodeGenOnly = 1 in def "" : CondUnaryRSY; - def Asm : AsmCondUnaryRSY; + let hasSideEffects = 1 in + def Asm : AsmCondUnaryRSY; } @@ -2843,7 +2859,9 @@ class UnaryVRIaGeneric opcode, Immediate imm> : InstVRIa; + mnemonic#"\t$V1, $I2, $M3", []> { + let hasSideEffects = 1; +} class UnaryVRRa opcode, SDPatternOperator operator, TypedReg tr1, TypedReg tr2, bits<4> type = 0, bits<4> m4 = 0, @@ -2862,6 +2880,7 @@ mnemonic#"\t$V1, $V2, $M3", []> { let M4 = m4; let M5 = m5; + let hasSideEffects = 1; } class UnaryVRRaFloatGeneric opcode, bits<4> m5 = 0> @@ -2869,6 +2888,7 @@ (ins VR128:$V2, imm32zx4:$M3, imm32zx4:$M4), mnemonic#"\t$V1, $V2, $M3, $M4", []> { let M5 = m5; + let hasSideEffects = 1; } // Declare a pair of instructions, one which sets CC and one which doesn't. @@ -2893,7 +2913,7 @@ } multiclass UnaryExtraVRRaSPairGeneric opcode> { - let M4 = 0 in + let M4 = 0, hasSideEffects = 1 in def "" : InstVRRa; @@ -2916,17 +2936,22 @@ : InstVRX { let mayLoad = 1; + let hasSideEffects = 1; } class SideEffectBinaryRX opcode, RegisterOperand cls> : InstRXa; + mnemonic##"\t$R1, $XBD2", []> { + let hasSideEffects = 1; +} class SideEffectBinaryRXY opcode, RegisterOperand cls> : InstRXYa; + mnemonic##"\t$R1, $XBD2", []> { + let hasSideEffects = 1; +} class SideEffectBinaryRILPC opcode, RegisterOperand cls> @@ -2936,12 +2961,15 @@ // However, BDXs have two extra operands and are therefore 6 units more // complex. let AddedComplexity = 7; + let hasSideEffects = 1; } class SideEffectBinaryRRE opcode, RegisterOperand cls1, RegisterOperand cls2> : InstRRE; + mnemonic#"\t$R1, $R2", []> { + let hasSideEffects = 1; +} class SideEffectBinaryRRFa opcode, RegisterOperand cls1, RegisterOperand cls2> @@ -2949,6 +2977,7 @@ mnemonic#"\t$R1, $R2", []> { let R3 = 0; let M4 = 0; + let hasSideEffects = 1; } class SideEffectBinaryRRFc opcode, @@ -2956,38 +2985,53 @@ : InstRRFc { let M3 = 0; + let hasSideEffects = 1; } class SideEffectBinaryIE opcode, Immediate imm1, Immediate imm2> : InstIE; + mnemonic#"\t$I1, $I2", []> { + let hasSideEffects = 1; +} class SideEffectBinarySI opcode, Operand imm> : InstSI; + mnemonic#"\t$BD1, $I2", []> { + let hasSideEffects = 1; +} class SideEffectBinarySIL opcode, SDPatternOperator operator, Immediate imm> : InstSIL; + mnemonic#"\t$BD1, $I2", [(operator bdaddr12only:$BD1, imm:$I2)]> { + let hasSideEffects = 1; +} class SideEffectBinarySSa opcode> : InstSSa; + mnemonic##"\t$BDL1, $BD2", []> { + let hasSideEffects = 1; +} class SideEffectBinarySSb opcode> : InstSSb; + mnemonic##"\t$BDL1, $BDL2", []> { + let hasSideEffects = 1; +} class SideEffectBinarySSf opcode> : InstSSf; + mnemonic##"\t$BD1, $BDL2", []> { + let hasSideEffects = 1; +} class SideEffectBinarySSE opcode> : InstSSE; + mnemonic#"\t$BD1, $BD2", []> { + let hasSideEffects = 1; +} class SideEffectBinaryMemMemRR opcode, RegisterOperand cls1, RegisterOperand cls2> @@ -2995,6 +3039,7 @@ mnemonic#"\t$R1, $R2", []> { let Constraints = "$R1 = $R1src, $R2 = $R2src"; let DisableEncoding = "$R1src, $R2src"; + let hasSideEffects = 1; } class SideEffectBinaryMemRRE opcode, @@ -3003,6 +3048,7 @@ mnemonic#"\t$R1, $R2", []> { let Constraints = "$R2 = $R2src"; let DisableEncoding = "$R2src"; + let hasSideEffects = 1; } class SideEffectBinaryMemMemRRE opcode, @@ -3011,6 +3057,7 @@ mnemonic#"\t$R1, $R2", []> { let Constraints = "$R1 = $R1src, $R2 = $R2src"; let DisableEncoding = "$R1src, $R2src"; + let hasSideEffects = 1; } class SideEffectBinaryMemMemRRFc opcode, @@ -3020,6 +3067,7 @@ let Constraints = "$R1 = $R1src, $R2 = $R2src"; let DisableEncoding = "$R1src, $R2src"; let M3 = 0; + let hasSideEffects = 1; } class BinaryRR opcode, SDPatternOperator operator, @@ -3066,7 +3114,7 @@ SDPatternOperator operator, RegisterOperand cls1, RegisterOperand cls2> { let NumOpsKey = mnemonic in { - let NumOpsValue = "3" in + let NumOpsValue = "3", hasSideEffects = 1 in def K : BinaryRRFa, Requires<[FeatureDistinctOps]>; let NumOpsValue = "2", isConvertibleToThreeAddress = 1 in @@ -3078,7 +3126,7 @@ SDPatternOperator operator, RegisterOperand cls1, RegisterOperand cls2> { let NumOpsKey = mnemonic in { - let NumOpsValue = "3" in + let NumOpsValue = "3", hasSideEffects = 1 in def K : BinaryRRFa, Requires<[FeatureDistinctOps]>; let NumOpsValue = "2", isConvertibleToThreeAddress = 1 in @@ -3179,7 +3227,7 @@ SDPatternOperator operator, RegisterOperand cls, Immediate imm> { let NumOpsKey = mnemonic in { - let NumOpsValue = "3" in + let NumOpsValue = "3", hasSideEffects = 1 in def K : BinaryRIE, Requires<[FeatureDistinctOps]>; let NumOpsValue = "2", isConvertibleToThreeAddress = 1 in @@ -3264,6 +3312,17 @@ } } +multiclass BinaryRSAndK_KSideEff opcode1, bits<16> opcode2, + SDPatternOperator operator, RegisterOperand cls> { + let NumOpsKey = mnemonic in { + let NumOpsValue = "3", hasSideEffects = 1 in + def K : BinaryRSY, + Requires<[FeatureDistinctOps]>; + let NumOpsValue = "2", isConvertibleToThreeAddress = 1 in + def "" : BinaryRS; + } +} + class BinaryRSL opcode, RegisterOperand cls> : InstRSLb opcode> : InstVRIb; + mnemonic#"\t$V1, $I2, $I3, $M4", []> { + let hasSideEffects = 1; +} class BinaryVRIc opcode, SDPatternOperator operator, TypedReg tr1, TypedReg tr2, bits<4> type> @@ -3399,7 +3460,9 @@ class BinaryVRIcGeneric opcode> : InstVRIc; + mnemonic#"\t$V1, $V3, $I2, $M4", []> { + let hasSideEffects = 1; +} class BinaryVRIe opcode, SDPatternOperator operator, TypedReg tr1, TypedReg tr2, bits<4> type, bits<4> m5> @@ -3414,7 +3477,9 @@ class BinaryVRIeFloatGeneric opcode> : InstVRIe; + mnemonic#"\t$V1, $V2, $I3, $M4, $M5", []> { + let hasSideEffects = 1; +} class BinaryVRIh opcode> : InstVRIh opcode> : InstVRRa; + mnemonic#"\t$V1, $V2, $M3, $M4, $M5", []> { + let hasSideEffects = 1; +} class BinaryVRRb opcode, SDPatternOperator operator, TypedReg tr1, TypedReg tr2, bits<4> type = 0, @@ -3463,7 +3530,9 @@ class BinaryVRRbSPairGeneric opcode> : InstVRRb; + mnemonic#"\t$V1, $V2, $V3, $M4, $M5", []> { + let hasSideEffects = 1; +} // Declare a pair of instructions, one which sets CC and one which doesn't. // The CC-setting form ends with "S" and sets the low bit of M5. @@ -3487,9 +3556,10 @@ } multiclass BinaryExtraVRRbSPairGeneric opcode> { - def "" : InstVRRb; + let hasSideEffects = 1 in + def "" : InstVRRb; def : InstAlias(NAME) VR128:$V1, VR128:$V2, VR128:$V3, imm32zx4:$M4, 0)>; @@ -3514,6 +3584,7 @@ mnemonic#"\t$V1, $V2, $V3, $M4", []> { let M5 = m5; let M6 = m6; + let hasSideEffects = 1; } class BinaryVRRcFloatGeneric opcode, bits<4> m6 = 0> @@ -3521,6 +3592,7 @@ (ins VR128:$V2, VR128:$V3, imm32zx4:$M4, imm32zx4:$M5), mnemonic#"\t$V1, $V2, $V3, $M4, $M5", []> { let M6 = m6; + let hasSideEffects = 1; } // Declare a pair of instructions, one which sets CC and one which doesn't. @@ -3541,7 +3613,9 @@ : InstVRRc; + mnemonic#"\t$V1, $V2, $V3, $M4, $M5, $M6", []> { + let hasSideEffects = 1; +} class BinaryVRRf opcode, SDPatternOperator operator, TypedReg tr> @@ -3565,7 +3639,9 @@ class BinaryVRSaGeneric opcode> : InstVRSa; + mnemonic#"\t$V1, $V3, $BD2, $M4", []> { + let hasSideEffects = 1; +} class BinaryVRSb opcode, SDPatternOperator operator, bits<5> bytes> @@ -3588,7 +3664,9 @@ class BinaryVRScGeneric opcode> : InstVRSc; + mnemonic#"\t$R1, $V3, $BD2, $M4", []> { + let hasSideEffects = 1; +} class BinaryVRSd opcode, SDPatternOperator operator, bits<5> bytes> @@ -3870,6 +3948,7 @@ let isCompare = 1; let M4 = 0; let M5 = 0; + let hasSideEffects = 1; } class CompareVRRaFloatGeneric opcode> @@ -3878,6 +3957,7 @@ mnemonic#"\t$V1, $V2, $M3, $M4", []> { let isCompare = 1; let M5 = 0; + let hasSideEffects = 1; } class CompareVRRh opcode> @@ -3907,7 +3987,9 @@ class SideEffectTernarySSc opcode> : InstSSc; + mnemonic##"\t$BDL1, $BD2, $I3", []> { + let hasSideEffects = 1; +} class SideEffectTernaryRRFa opcode, RegisterOperand cls1, RegisterOperand cls2, @@ -3915,6 +3997,7 @@ : InstRRFa { let M4 = 0; + let hasSideEffects = 1; } class SideEffectTernaryRRFb opcode, @@ -3923,6 +4006,7 @@ : InstRRFb { let M4 = 0; + let hasSideEffects = 1; } class SideEffectTernaryMemMemMemRRFb opcode, @@ -3935,13 +4019,16 @@ let Constraints = "$R1 = $R1src, $R2 = $R2src, $R3 = $R3src"; let DisableEncoding = "$R1src, $R2src, $R3src"; let M4 = 0; + let hasSideEffects = 1; } class SideEffectTernaryRRFc opcode, RegisterOperand cls1, RegisterOperand cls2, Immediate imm> : InstRRFc; + mnemonic#"\t$R1, $R2, $M3", []> { + let hasSideEffects = 1; +} multiclass SideEffectTernaryRRFcOpt opcode, RegisterOperand cls1, @@ -3958,6 +4045,7 @@ mnemonic#"\t$R1, $R2, $M3", []> { let Constraints = "$R1 = $R1src, $R2 = $R2src"; let DisableEncoding = "$R1src, $R2src"; + let hasSideEffects = 1; } multiclass SideEffectTernaryMemMemRRFcOpt opcode, @@ -3971,7 +4059,9 @@ RegisterOperand cls> : InstSSF; + mnemonic#"\t$BD1, $BD2, $R3", []> { + let hasSideEffects = 1; +} class TernaryRRFa opcode, RegisterOperand cls1, RegisterOperand cls2, @@ -4044,13 +4134,17 @@ RegisterOperand cls1, RegisterOperand cls2> : InstRSa; + mnemonic#"\t$R1, $R3, $BD2", []> { + let hasSideEffects = 1; +} class SideEffectTernaryRSY opcode, RegisterOperand cls1, RegisterOperand cls2> : InstRSYa; + mnemonic#"\t$R1, $R3, $BD2", []> { + let hasSideEffects = 1; +} class SideEffectTernaryMemMemRS opcode, RegisterOperand cls1, RegisterOperand cls2> @@ -4059,6 +4153,7 @@ mnemonic#"\t$R1, $R3, $BD2", []> { let Constraints = "$R1 = $R1src, $R3 = $R3src"; let DisableEncoding = "$R1src, $R3src"; + let hasSideEffects = 1; } class SideEffectTernaryMemMemRSY opcode, @@ -4068,6 +4163,7 @@ mnemonic#"\t$R1, $R3, $BD2", []> { let Constraints = "$R1 = $R1src, $R3 = $R3src"; let DisableEncoding = "$R1src, $R3src"; + let hasSideEffects = 1; } class TernaryRXF opcode, SDPatternOperator operator, @@ -4127,7 +4223,9 @@ class TernaryVRRaFloatGeneric opcode> : InstVRRa; + mnemonic#"\t$V1, $V2, $M3, $M4, $M5", []> { + let hasSideEffects = 1; +} class TernaryVRRb opcode, SDPatternOperator operator, TypedReg tr1, TypedReg tr2, bits<4> type, @@ -4164,9 +4262,10 @@ } multiclass TernaryOptVRRbSPairGeneric opcode> { - def "" : InstVRRb; + let hasSideEffects = 1 in + def "" : InstVRRb; def : InstAlias(NAME) VR128:$V1, VR128:$V2, VR128:$V3, imm32zx4:$M4, 0)>; @@ -4201,7 +4300,9 @@ : InstVRRc; + mnemonic#"\t$V1, $V2, $V3, $M4, $M5, $M6", []> { + let hasSideEffects = 1; +} class TernaryVRRd opcode, SDPatternOperator operator, TypedReg tr1, TypedReg tr2, bits<4> type = 0> @@ -4220,6 +4321,7 @@ (ins VR128:$V2, VR128:$V3, VR128:$V4, imm32zx4:$M5), mnemonic#"\t$V1, $V2, $V3, $V4, $M5", []> { let M6 = 0; + let hasSideEffects = 1; } class TernaryVRRe opcode, SDPatternOperator operator, @@ -4237,7 +4339,9 @@ class TernaryVRReFloatGeneric opcode> : InstVRRe; + mnemonic#"\t$V1, $V2, $V3, $V4, $M5, $M6", []> { + let hasSideEffects = 1; +} class TernaryVRSb opcode, SDPatternOperator operator, TypedReg tr1, TypedReg tr2, RegisterOperand cls, bits<4> type> @@ -4258,6 +4362,7 @@ mnemonic#"\t$V1, $R3, $BD2, $M4", []> { let Constraints = "$V1 = $V1src"; let DisableEncoding = "$V1src"; + let hasSideEffects = 1; } class TernaryVRV opcode, bits<5> bytes, @@ -4306,6 +4411,7 @@ mnemonic#"\t$V1, $V2, $V3, $I4, $M5", []> { let Constraints = "$V1 = $V1src"; let DisableEncoding = "$V1src"; + let hasSideEffects = 1; } class QuaternaryVRIf opcode> @@ -4338,7 +4444,9 @@ class QuaternaryVRRdGeneric opcode> : InstVRRd; + mnemonic#"\t$V1, $V2, $V3, $V4, $M5, $M6", []> { + let hasSideEffects = 1; +} // Declare a pair of instructions, one which sets CC and one which doesn't. // The CC-setting form ends with "S" and sets the low bit of M6. @@ -4364,7 +4472,8 @@ } multiclass QuaternaryOptVRRdSPairGeneric opcode> { - def "" : QuaternaryVRRdGeneric; + let hasSideEffects = 1 in + def "" : QuaternaryVRRdGeneric; def : InstAlias(NAME) VR128:$V1, VR128:$V2, VR128:$V3, VR128:$V4, imm32zx4:$M5, 0)>; @@ -4374,7 +4483,9 @@ RegisterOperand cls1, RegisterOperand cls2, RegisterOperand cls3> : InstRRFa; + mnemonic#"\t$R1, $R2, $R3, $M4", []> { + let hasSideEffects = 1; +} multiclass SideEffectQuaternaryRRFaOptOpt opcode, RegisterOperand cls1, @@ -4389,7 +4500,9 @@ RegisterOperand cls1, RegisterOperand cls2, RegisterOperand cls3> : InstRRFb; + mnemonic#"\t$R1, $R3, $R2, $M4", []> { + let hasSideEffects = 1; +} multiclass SideEffectQuaternaryRRFbOpt opcode, RegisterOperand cls1, @@ -4403,7 +4516,9 @@ RegisterOperand cls> : InstSSe; + mnemonic#"\t$R1, $BD2, $R3, $BD4", []> { + let hasSideEffects = 1; +} class LoadAndOpRSY opcode, SDPatternOperator operator, RegisterOperand cls, AddressingMode mode = bdaddr20only> @@ -4499,7 +4614,8 @@ // clobber the target (vector) register. multiclass LoadAndTestRRE opcode, RegisterOperand cls> { - def "" : UnaryRRE; + let hasSideEffects = 1 in + def "" : UnaryRRE; let isCodeGenOnly = 1, Predicates = [FeatureNoVector] in def Compare : CompareRRE; } @@ -4523,7 +4639,9 @@ // Like SideEffectBinarySIL, but expanded later. class SideEffectBinarySILPseudo : Pseudo<(outs), (ins bdaddr12only:$BD1, imm:$I2), - [(operator bdaddr12only:$BD1, imm:$I2)]>; + [(operator bdaddr12only:$BD1, imm:$I2)]> { + let hasSideEffects = 1; +} // Like UnaryRI, but expanded after RA depending on the choice of register. class UnaryRIPseudo { let NumOpsKey = key in { - let NumOpsValue = "3" in + let NumOpsValue = "3", hasSideEffects = 1 in def K : BinaryRIEPseudo, Requires<[FeatureHighWord, FeatureDistinctOps]>; let NumOpsValue = "2", isConvertibleToThreeAddress = 1 in @@ -4688,7 +4806,8 @@ // Stores $new to $addr if $cc is true ("" case) or false (Inv case). multiclass CondStores { - let Defs = [CC], Uses = [CC], usesCustomInserter = 1 in { + let Defs = [CC], Uses = [CC], usesCustomInserter = 1, + mayLoad = 1, mayStore = 1 in { def "" : Pseudo<(outs), (ins cls:$new, mode:$addr, imm32zx4:$valid, imm32zx4:$cc), [(store (z_select_ccmask cls:$new, (load mode:$addr), Index: lib/Target/SystemZ/SystemZInstrHFP.td =================================================================== --- lib/Target/SystemZ/SystemZInstrHFP.td +++ lib/Target/SystemZ/SystemZInstrHFP.td @@ -14,6 +14,11 @@ // //===----------------------------------------------------------------------===// +// In general, most floating-point instructions (except for simple moves and +// the like) should have the side-effects flag, since they can raise +// exceptions. +let hasSideEffects = 1 in { + //===----------------------------------------------------------------------===// // Move instructions //===----------------------------------------------------------------------===// @@ -238,3 +243,4 @@ def CD : CompareRX<"cd", 0x69, null_frag, FP64, load, 8>; } +} // hasSideEffects = 1 Index: lib/Target/SystemZ/SystemZInstrInfo.td =================================================================== --- lib/Target/SystemZ/SystemZInstrInfo.td +++ lib/Target/SystemZ/SystemZInstrInfo.td @@ -11,37 +11,37 @@ // Stack allocation //===----------------------------------------------------------------------===// -let hasNoSchedulingInfo = 1 in { +let hasNoSchedulingInfo = 1, hasSideEffects = 1 in { def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i64imm:$amt1, i64imm:$amt2), [(callseq_start timm:$amt1, timm:$amt2)]>; def ADJCALLSTACKUP : Pseudo<(outs), (ins i64imm:$amt1, i64imm:$amt2), [(callseq_end timm:$amt1, timm:$amt2)]>; } -let hasSideEffects = 0 in { - // Takes as input the value of the stack pointer after a dynamic allocation - // has been made. Sets the output to the address of the dynamically- - // allocated area itself, skipping the outgoing arguments. - // - // This expands to an LA or LAY instruction. We restrict the offset - // to the range of LA and keep the LAY range in reserve for when - // the size of the outgoing arguments is added. - def ADJDYNALLOC : Pseudo<(outs GR64:$dst), (ins dynalloc12only:$src), - [(set GR64:$dst, dynalloc12only:$src)]>; -} +// Takes as input the value of the stack pointer after a dynamic allocation +// has been made. Sets the output to the address of the dynamically- +// allocated area itself, skipping the outgoing arguments. +// +// This expands to an LA or LAY instruction. We restrict the offset +// to the range of LA and keep the LAY range in reserve for when +// the size of the outgoing arguments is added. +def ADJDYNALLOC : Pseudo<(outs GR64:$dst), (ins dynalloc12only:$src), + [(set GR64:$dst, dynalloc12only:$src)]>; + //===----------------------------------------------------------------------===// // Branch instructions //===----------------------------------------------------------------------===// // Conditional branches. -let isBranch = 1, isTerminator = 1, Uses = [CC] in { +let isBranch = 1, isTerminator = 1, Uses = [CC], hasSideEffects = 1 in { // It's easier for LLVM to handle these branches in their raw BRC/BRCL form // with the condition-code mask being the first operand. It seems friendlier // to use mnemonic forms like JE and JLH when writing out the assembly though. let isCodeGenOnly = 1 in { // An assembler extended mnemonic for BRC. - def BRC : CondBranchRI <"j#", 0xA74, z_br_ccmask>; + let hasSideEffects = 0 in + def BRC : CondBranchRI <"j#", 0xA74, z_br_ccmask>; // An assembler extended mnemonic for BRCL. (The extension is "G" // rather than "L" because "JL" is "Jump if Less".) def BRCL : CondBranchRIL<"jg#", 0xC04>; @@ -73,8 +73,9 @@ let isIndirectBranch = 1 in { def BAsm#V : FixedCondBranchRX , "b#", 0x47>; def BRAsm#V : FixedCondBranchRR , "b#r", 0x07>; - def BIAsm#V : FixedCondBranchRXY, "bi#", 0xe347>, - Requires<[FeatureMiscellaneousExtensions2]>; + let hasSideEffects = 1 in + def BIAsm#V : FixedCondBranchRXY, "bi#", 0xe347>, + Requires<[FeatureMiscellaneousExtensions2]>; } } } @@ -83,12 +84,15 @@ // conditional branches with the condition mask set to "always". let isBranch = 1, isTerminator = 1, isBarrier = 1 in { def J : FixedCondBranchRI ; - def JG : FixedCondBranchRIL; + let hasSideEffects = 1 in + def JG : FixedCondBranchRIL; let isIndirectBranch = 1 in { - def B : FixedCondBranchRX; + let hasSideEffects = 1 in + def B : FixedCondBranchRX; def BR : FixedCondBranchRR; - def BI : FixedCondBranchRXY, - Requires<[FeatureMiscellaneousExtensions2]>; + let mayLoad = 1 in + def BI : FixedCondBranchRXY, + Requires<[FeatureMiscellaneousExtensions2]>; } } @@ -103,7 +107,7 @@ // We nevertheless pretend that the relative compare-and-branch // instructions clobber CC, so that we can lower them to separate // comparisons and BRCLs if the branch ends up being out of range. -let isBranch = 1, isTerminator = 1 in { +let isBranch = 1, isTerminator = 1, hasSideEffects = 1 in { // As for normal branches, we handle these instructions internally in // their raw CRJ-like form, but use assembly macros like CRJE when writing // them out. Using the *Pair multiclasses, we also create the raw forms. @@ -164,7 +168,7 @@ // Decrement a register and branch if it is nonzero. These don't clobber CC, // but we might need to split long relative branches into sequences that do. -let isBranch = 1, isTerminator = 1 in { +let isBranch = 1, isTerminator = 1, hasSideEffects = 1 in { let Defs = [CC] in { def BRCT : BranchUnaryRI<"brct", 0xA76, GR32>; def BRCTG : BranchUnaryRI<"brctg", 0xA77, GR64>; @@ -179,7 +183,7 @@ def BCTGR : BranchUnaryRRE<"bctgr", 0xB946, GR64>; } -let isBranch = 1, isTerminator = 1 in { +let isBranch = 1, isTerminator = 1, hasSideEffects = 1 in { let Defs = [CC] in { def BRXH : BranchBinaryRSI<"brxh", 0x84, GR32>; def BRXLE : BranchBinaryRSI<"brxle", 0x85, GR32>; @@ -197,15 +201,15 @@ //===----------------------------------------------------------------------===// // Unconditional trap. -let hasCtrlDep = 1 in +let hasCtrlDep = 1, hasSideEffects = 1 in def Trap : Alias<4, (outs), (ins), [(trap)]>; // Conditional trap. -let hasCtrlDep = 1, Uses = [CC] in +let hasCtrlDep = 1, Uses = [CC], hasSideEffects = 1 in def CondTrap : Alias<4, (outs), (ins cond4:$valid, cond4:$R1), []>; // Fused compare-and-trap instructions. -let hasCtrlDep = 1 in { +let hasCtrlDep = 1, hasSideEffects = 1 in { // These patterns work the same way as for compare-and-branch. defm CRT : CmpBranchRRFcPair<"crt", 0xB972, GR32>; defm CGRT : CmpBranchRRFcPair<"cgrt", 0xB960, GR64>; @@ -247,7 +251,7 @@ // Define the general form of the call instructions for the asm parser. // These instructions don't hard-code %r14 as the return address register. -let isCall = 1, Defs = [CC] in { +let isCall = 1, Defs = [CC], hasSideEffects = 1 in { def BRAS : CallRI <"bras", 0xA75>; def BRASL : CallRIL<"brasl", 0xC05>; def BAS : CallRX <"bas", 0x4D>; @@ -281,7 +285,8 @@ } // Conditional sibling calls. -let CCMaskFirst = 1, isCall = 1, isTerminator = 1, isReturn = 1 in { +let CCMaskFirst = 1, isCall = 1, isTerminator = 1, isReturn = 1, + hasSideEffects = 1 in { def CallBRCL : Alias<6, (outs), (ins cond4:$valid, cond4:$R1, pcrel32:$I2), []>; let Uses = [R1D] in @@ -289,7 +294,8 @@ } // Fused compare and conditional sibling calls. -let isCall = 1, isTerminator = 1, isReturn = 1, Uses = [R1D] in { +let isCall = 1, isTerminator = 1, isReturn = 1, Uses = [R1D], + hasSideEffects = 1 in { def CRBCall : Alias<6, (outs), (ins GR32:$R1, GR32:$R2, cond4:$M3), []>; def CGRBCall : Alias<6, (outs), (ins GR64:$R1, GR64:$R2, cond4:$M3), []>; def CIBCall : Alias<6, (outs), (ins GR32:$R1, imm32sx8:$I2, cond4:$M3), []>; @@ -305,11 +311,12 @@ def Return : Alias<2, (outs), (ins), [(z_retflag)]>; // A conditional return instruction (bcr , %r14). -let isReturn = 1, isTerminator = 1, hasCtrlDep = 1, CCMaskFirst = 1, Uses = [CC] in +let isReturn = 1, isTerminator = 1, hasCtrlDep = 1, CCMaskFirst = 1, Uses = [CC], + hasSideEffects = 1 in def CondReturn : Alias<2, (outs), (ins cond4:$valid, cond4:$R1), []>; // Fused compare and conditional returns. -let isReturn = 1, isTerminator = 1, hasCtrlDep = 1 in { +let isReturn = 1, isTerminator = 1, hasCtrlDep = 1, hasSideEffects = 1 in { def CRBReturn : Alias<6, (outs), (ins GR32:$R1, GR32:$R2, cond4:$M3), []>; def CGRBReturn : Alias<6, (outs), (ins GR64:$R1, GR64:$R2, cond4:$M3), []>; def CIBReturn : Alias<6, (outs), (ins GR32:$R1, imm32sx8:$I2, cond4:$M3), []>; @@ -360,24 +367,22 @@ //===----------------------------------------------------------------------===// // Register moves. -let hasSideEffects = 0 in { - // Expands to LR, RISBHG or RISBLG, depending on the choice of registers. - def LRMux : UnaryRRPseudo<"lr", null_frag, GRX32, GRX32>, - Requires<[FeatureHighWord]>; - def LR : UnaryRR <"lr", 0x18, null_frag, GR32, GR32>; - def LGR : UnaryRRE<"lgr", 0xB904, null_frag, GR64, GR64>; -} -let Defs = [CC], CCValues = 0xE, CompareZeroCCMask = 0xE in { +// Expands to LR, RISBHG or RISBLG, depending on the choice of registers. +def LRMux : UnaryRRPseudo<"lr", null_frag, GRX32, GRX32>, + Requires<[FeatureHighWord]>; +def LR : UnaryRR <"lr", 0x18, null_frag, GR32, GR32>; +def LGR : UnaryRRE<"lgr", 0xB904, null_frag, GR64, GR64>; + +let Defs = [CC], CCValues = 0xE, CompareZeroCCMask = 0xE, hasSideEffects = 1 in { def LTR : UnaryRR <"ltr", 0x12, null_frag, GR32, GR32>; def LTGR : UnaryRRE<"ltgr", 0xB902, null_frag, GR64, GR64>; } -let usesCustomInserter = 1, hasNoSchedulingInfo = 1 in +let usesCustomInserter = 1, hasNoSchedulingInfo = 1, hasSideEffects = 1 in def PAIR128 : Pseudo<(outs GR128:$dst), (ins GR64:$hi, GR64:$lo), []>; // Immediate moves. -let hasSideEffects = 0, isAsCheapAsAMove = 1, isMoveImm = 1, - isReMaterializable = 1 in { +let isAsCheapAsAMove = 1, isMoveImm = 1, isReMaterializable = 1 in { // 16-bit sign-extended immediates. LHIMux expands to LHI or IIHF, // deopending on the choice of register. def LHIMux : UnaryRIPseudo, @@ -409,7 +414,7 @@ // These instructions are split after register allocation, so we don't // want a custom inserter. - let Has20BitOffset = 1, HasIndex = 1, Is128Bit = 1 in { + let Has20BitOffset = 1, HasIndex = 1, Is128Bit = 1, mayLoad = 1 in { def L128 : Pseudo<(outs GR128:$dst), (ins bdxaddr20only128:$src), [(set GR128:$dst, (load bdxaddr20only128:$src))]>; } @@ -435,7 +440,7 @@ } // Load and trap. -let Predicates = [FeatureLoadAndTrap] in { +let Predicates = [FeatureLoadAndTrap], hasSideEffects = 1 in { def LAT : UnaryRXY<"lat", 0xE39F, null_frag, GR32, 4>; def LFHAT : UnaryRXY<"lfhat", 0xE3C8, null_frag, GRH32, 4>; def LGAT : UnaryRXY<"lgat", 0xE385, null_frag, GR64, 8>; @@ -453,7 +458,7 @@ // These instructions are split after register allocation, so we don't // want a custom inserter. - let Has20BitOffset = 1, HasIndex = 1, Is128Bit = 1 in { + let Has20BitOffset = 1, HasIndex = 1, Is128Bit = 1, mayStore = 1 in { def ST128 : Pseudo<(outs), (ins GR128:$src, bdxaddr20only128:$dst), [(store GR128:$src, bdxaddr20only128:$dst)]>; } @@ -489,17 +494,16 @@ let Predicates = [FeatureLoadStoreOnCond2], Uses = [CC] in { // Load immediate on condition. Matched via DAG pattern and created // by the PeepholeOptimizer via FoldImmediate. - let hasSideEffects = 0 in { - // Expands to LOCHI or LOCHHI, depending on the choice of register. - def LOCHIMux : CondBinaryRIEPseudo; - defm LOCHHI : CondBinaryRIEPair<"lochhi", 0xEC4E, GRH32, imm32sx16>; - defm LOCHI : CondBinaryRIEPair<"lochi", 0xEC42, GR32, imm32sx16>; - defm LOCGHI : CondBinaryRIEPair<"locghi", 0xEC46, GR64, imm64sx16>; - } + + // Expands to LOCHI or LOCHHI, depending on the choice of register. + def LOCHIMux : CondBinaryRIEPseudo; + defm LOCHHI : CondBinaryRIEPair<"lochhi", 0xEC4E, GRH32, imm32sx16>; + defm LOCHI : CondBinaryRIEPair<"lochi", 0xEC42, GR32, imm32sx16>; + defm LOCGHI : CondBinaryRIEPair<"locghi", 0xEC46, GR64, imm64sx16>; // Move register on condition. Expanded from Select* pseudos and // created by early if-conversion. - let hasSideEffects = 0, isCommutable = 1 in { + let isCommutable = 1 in { // Expands to LOCR or LOCFHR or a branch-and-move sequence, // depending on the choice of registers. def LOCRMux : CondBinaryRRFPseudo; @@ -513,28 +517,32 @@ // Store on condition. Expanded from CondStore* pseudos. // Expands to STOC or STOCFH, depending on the choice of register. - def STOCMux : CondStoreRSYPseudo; - defm STOCFH : CondStoreRSYPair<"stocfh", 0xEBE1, GRH32, 4>; + let hasSideEffects = 1 in { + def STOCMux : CondStoreRSYPseudo; + defm STOCFH : CondStoreRSYPair<"stocfh", 0xEBE1, GRH32, 4>; + } - // Define AsmParser extended mnemonics for each general condition-code mask. - foreach V = [ "E", "NE", "H", "NH", "L", "NL", "HE", "NHE", "LE", "NLE", - "Z", "NZ", "P", "NP", "M", "NM", "LH", "NLH", "O", "NO" ] in { - def LOCHIAsm#V : FixedCondBinaryRIE, "lochi", 0xEC42, GR32, - imm32sx16>; - def LOCGHIAsm#V : FixedCondBinaryRIE, "locghi", 0xEC46, GR64, - imm64sx16>; - def LOCHHIAsm#V : FixedCondBinaryRIE, "lochhi", 0xEC4E, GRH32, - imm32sx16>; - def LOCFHRAsm#V : FixedCondBinaryRRF, "locfhr", 0xB9E0, GRH32, GRH32>; - def LOCFHAsm#V : FixedCondUnaryRSY, "locfh", 0xEBE0, GRH32, 4>; - def STOCFHAsm#V : FixedCondStoreRSY, "stocfh", 0xEBE1, GRH32, 4>; + let hasSideEffects = 1 in { + // Define AsmParser extended mnemonics for each general condition-code mask. + foreach V = [ "E", "NE", "H", "NH", "L", "NL", "HE", "NHE", "LE", "NLE", + "Z", "NZ", "P", "NP", "M", "NM", "LH", "NLH", "O", "NO" ] in { + def LOCHIAsm#V : FixedCondBinaryRIE, "lochi", 0xEC42, GR32, + imm32sx16>; + def LOCGHIAsm#V : FixedCondBinaryRIE, "locghi", 0xEC46, GR64, + imm64sx16>; + def LOCHHIAsm#V : FixedCondBinaryRIE, "lochhi", 0xEC4E, GRH32, + imm32sx16>; + def LOCFHRAsm#V : FixedCondBinaryRRF, "locfhr", 0xB9E0, GRH32, GRH32>; + def LOCFHAsm#V : FixedCondUnaryRSY, "locfh", 0xEBE0, GRH32, 4>; + def STOCFHAsm#V : FixedCondStoreRSY, "stocfh", 0xEBE1, GRH32, 4>; + } } } let Predicates = [FeatureLoadStoreOnCond], Uses = [CC] in { // Move register on condition. Expanded from Select* pseudos and // created by early if-conversion. - let hasSideEffects = 0, isCommutable = 1 in { + let isCommutable = 1 in { defm LOCR : CondBinaryRRFPair<"locr", 0xB9F2, GR32, GR32>; defm LOCGR : CondBinaryRRFPair<"locgr", 0xB9E2, GR64, GR64>; } @@ -544,18 +552,22 @@ defm LOCG : CondUnaryRSYPair<"locg", 0xEBE2, nonvolatile_load, GR64, 8>; // Store on condition. Expanded from CondStore* pseudos. - defm STOC : CondStoreRSYPair<"stoc", 0xEBF3, GR32, 4>; - defm STOCG : CondStoreRSYPair<"stocg", 0xEBE3, GR64, 8>; + let hasSideEffects = 1 in { + defm STOC : CondStoreRSYPair<"stoc", 0xEBF3, GR32, 4>; + defm STOCG : CondStoreRSYPair<"stocg", 0xEBE3, GR64, 8>; + } - // Define AsmParser extended mnemonics for each general condition-code mask. - foreach V = [ "E", "NE", "H", "NH", "L", "NL", "HE", "NHE", "LE", "NLE", - "Z", "NZ", "P", "NP", "M", "NM", "LH", "NLH", "O", "NO" ] in { - def LOCRAsm#V : FixedCondBinaryRRF, "locr", 0xB9F2, GR32, GR32>; - def LOCGRAsm#V : FixedCondBinaryRRF, "locgr", 0xB9E2, GR64, GR64>; - def LOCAsm#V : FixedCondUnaryRSY, "loc", 0xEBF2, GR32, 4>; - def LOCGAsm#V : FixedCondUnaryRSY, "locg", 0xEBE2, GR64, 8>; - def STOCAsm#V : FixedCondStoreRSY, "stoc", 0xEBF3, GR32, 4>; - def STOCGAsm#V : FixedCondStoreRSY, "stocg", 0xEBE3, GR64, 8>; + let hasSideEffects = 1 in { + // Define AsmParser extended mnemonics for each general condition-code mask. + foreach V = [ "E", "NE", "H", "NH", "L", "NL", "HE", "NHE", "LE", "NLE", + "Z", "NZ", "P", "NP", "M", "NM", "LH", "NLH", "O", "NO" ] in { + def LOCRAsm#V : FixedCondBinaryRRF, "locr", 0xB9F2, GR32, GR32>; + def LOCGRAsm#V : FixedCondBinaryRRF, "locgr", 0xB9E2, GR64, GR64>; + def LOCAsm#V : FixedCondUnaryRSY, "loc", 0xEBF2, GR32, 4>; + def LOCGAsm#V : FixedCondUnaryRSY, "locg", 0xEBE2, GR64, 8>; + def STOCAsm#V : FixedCondStoreRSY, "stoc", 0xEBF3, GR32, 4>; + def STOCGAsm#V : FixedCondStoreRSY, "stocg", 0xEBE3, GR64, 8>; + } } } //===----------------------------------------------------------------------===// @@ -570,18 +582,15 @@ //===----------------------------------------------------------------------===// // 32-bit extensions from registers. -let hasSideEffects = 0 in { - def LBR : UnaryRRE<"lbr", 0xB926, sext8, GR32, GR32>; - def LHR : UnaryRRE<"lhr", 0xB927, sext16, GR32, GR32>; -} +def LBR : UnaryRRE<"lbr", 0xB926, sext8, GR32, GR32>; +def LHR : UnaryRRE<"lhr", 0xB927, sext16, GR32, GR32>; // 64-bit extensions from registers. -let hasSideEffects = 0 in { - def LGBR : UnaryRRE<"lgbr", 0xB906, sext8, GR64, GR64>; - def LGHR : UnaryRRE<"lghr", 0xB907, sext16, GR64, GR64>; - def LGFR : UnaryRRE<"lgfr", 0xB914, sext32, GR64, GR32>; -} -let Defs = [CC], CCValues = 0xE, CompareZeroCCMask = 0xE in +def LGBR : UnaryRRE<"lgbr", 0xB906, sext8, GR64, GR64>; +def LGHR : UnaryRRE<"lghr", 0xB907, sext16, GR64, GR64>; +def LGFR : UnaryRRE<"lgfr", 0xB914, sext32, GR64, GR32>; + +let Defs = [CC], CCValues = 0xE, CompareZeroCCMask = 0xE, hasSideEffects = 1 in def LTGFR : UnaryRRE<"ltgfr", 0xB912, null_frag, GR64, GR32>; // Match 32-to-64-bit sign extensions in which the source is already @@ -620,23 +629,20 @@ //===----------------------------------------------------------------------===// // 32-bit extensions from registers. -let hasSideEffects = 0 in { - // Expands to LLCR or RISB[LH]G, depending on the choice of registers. - def LLCRMux : UnaryRRPseudo<"llcr", zext8, GRX32, GRX32>, - Requires<[FeatureHighWord]>; - def LLCR : UnaryRRE<"llcr", 0xB994, zext8, GR32, GR32>; - // Expands to LLHR or RISB[LH]G, depending on the choice of registers. - def LLHRMux : UnaryRRPseudo<"llhr", zext16, GRX32, GRX32>, - Requires<[FeatureHighWord]>; - def LLHR : UnaryRRE<"llhr", 0xB995, zext16, GR32, GR32>; -} + +// Expands to LLCR or RISB[LH]G, depending on the choice of registers. +def LLCRMux : UnaryRRPseudo<"llcr", zext8, GRX32, GRX32>, + Requires<[FeatureHighWord]>; +def LLCR : UnaryRRE<"llcr", 0xB994, zext8, GR32, GR32>; +// Expands to LLHR or RISB[LH]G, depending on the choice of registers. +def LLHRMux : UnaryRRPseudo<"llhr", zext16, GRX32, GRX32>, + Requires<[FeatureHighWord]>; +def LLHR : UnaryRRE<"llhr", 0xB995, zext16, GR32, GR32>; // 64-bit extensions from registers. -let hasSideEffects = 0 in { - def LLGCR : UnaryRRE<"llgcr", 0xB984, zext8, GR64, GR64>; - def LLGHR : UnaryRRE<"llghr", 0xB985, zext16, GR64, GR64>; - def LLGFR : UnaryRRE<"llgfr", 0xB916, zext32, GR64, GR32>; -} +def LLGCR : UnaryRRE<"llgcr", 0xB984, zext8, GR64, GR64>; +def LLGHR : UnaryRRE<"llghr", 0xB985, zext16, GR64, GR64>; +def LLGFR : UnaryRRE<"llgfr", 0xB916, zext32, GR64, GR32>; // Match 32-to-64-bit zero extensions in which the source is already // in a 64-bit register. @@ -683,13 +689,13 @@ } // Load and trap. -let Predicates = [FeatureLoadAndTrap] in { +let Predicates = [FeatureLoadAndTrap], hasSideEffects = 1 in { def LLGFAT : UnaryRXY<"llgfat", 0xE39D, null_frag, GR64, 4>; def LLGTAT : UnaryRXY<"llgtat", 0xE39C, null_frag, GR64, 4>; } // Extend GR64s to GR128s. -let usesCustomInserter = 1 in +let usesCustomInserter = 1, hasSideEffects = 1 in def ZEXT128 : Pseudo<(outs GR128:$dst), (ins GR64:$src), []>; //===----------------------------------------------------------------------===// @@ -701,7 +707,7 @@ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$src, subreg_l32)>; // Extend GR64s to GR128s. -let usesCustomInserter = 1 in +let usesCustomInserter = 1, hasSideEffects = 1 in def AEXT128 : Pseudo<(outs GR128:$dst), (ins GR64:$src), []>; //===----------------------------------------------------------------------===// @@ -737,33 +743,35 @@ def : StoreGR64PC; // Store characters under mask -- not (yet) used for codegen. -defm STCM : StoreBinaryRSPair<"stcm", 0xBE, 0xEB2D, GR32, 0>; -def STCMH : StoreBinaryRSY<"stcmh", 0xEB2C, GRH32, 0>; +let hasSideEffects = 1 in { + defm STCM : StoreBinaryRSPair<"stcm", 0xBE, 0xEB2D, GR32, 0>; + def STCMH : StoreBinaryRSY<"stcmh", 0xEB2C, GRH32, 0>; +} //===----------------------------------------------------------------------===// // Multi-register moves //===----------------------------------------------------------------------===// // Multi-register loads. -defm LM : LoadMultipleRSPair<"lm", 0x98, 0xEB98, GR32>; -def LMG : LoadMultipleRSY<"lmg", 0xEB04, GR64>; -def LMH : LoadMultipleRSY<"lmh", 0xEB96, GRH32>; -def LMD : LoadMultipleSSe<"lmd", 0xEF, GR64>; +let hasSideEffects = 1 in { + defm LM : LoadMultipleRSPair<"lm", 0x98, 0xEB98, GR32>; + def LMG : LoadMultipleRSY<"lmg", 0xEB04, GR64>; + def LMH : LoadMultipleRSY<"lmh", 0xEB96, GRH32>; + def LMD : LoadMultipleSSe<"lmd", 0xEF, GR64>; -// Multi-register stores. -defm STM : StoreMultipleRSPair<"stm", 0x90, 0xEB90, GR32>; -def STMG : StoreMultipleRSY<"stmg", 0xEB24, GR64>; -def STMH : StoreMultipleRSY<"stmh", 0xEB26, GRH32>; + // Multi-register stores. + defm STM : StoreMultipleRSPair<"stm", 0x90, 0xEB90, GR32>; + def STMG : StoreMultipleRSY<"stmg", 0xEB24, GR64>; + def STMH : StoreMultipleRSY<"stmh", 0xEB26, GRH32>; +} //===----------------------------------------------------------------------===// // Byte swaps //===----------------------------------------------------------------------===// // Byte-swapping register moves. -let hasSideEffects = 0 in { - def LRVR : UnaryRRE<"lrvr", 0xB91F, bswap, GR32, GR32>; - def LRVGR : UnaryRRE<"lrvgr", 0xB90F, bswap, GR64, GR64>; -} +def LRVR : UnaryRRE<"lrvr", 0xB91F, bswap, GR32, GR32>; +def LRVGR : UnaryRRE<"lrvgr", 0xB90F, bswap, GR64, GR64>; // Byte-swapping loads. Unlike normal loads, these instructions are // allowed to access storage more than once. @@ -785,13 +793,12 @@ //===----------------------------------------------------------------------===// // Load BDX-style addresses. -let hasSideEffects = 0, isAsCheapAsAMove = 1, isReMaterializable = 1 in +let isAsCheapAsAMove = 1, isReMaterializable = 1 in defm LA : LoadAddressRXPair<"la", 0x41, 0xE371, bitconvert>; // Load a PC-relative address. There's no version of this instruction // with a 16-bit offset, so there's no relaxation. -let hasSideEffects = 0, isAsCheapAsAMove = 1, isMoveImm = 1, - isReMaterializable = 1 in +let isAsCheapAsAMove = 1, isMoveImm = 1, isReMaterializable = 1 in def LARL : LoadAddressRIL<"larl", 0xC00, bitconvert>; // Load the Global Offset Table address. This will be lowered into a @@ -855,7 +862,7 @@ defm : InsertMem<"inserti8", ICY, GR64, azextloadi8, bdxaddr20pair>; // Insert characters under mask -- not (yet) used for codegen. -let Defs = [CC] in { +let Defs = [CC], hasSideEffects = 1 in { defm ICM : TernaryRSPair<"icm", 0xBF, 0xEB81, GR32, 0>; def ICMH : TernaryRSY<"icmh", 0xEB80, GRH32, 0>; } @@ -911,10 +918,12 @@ def AGFR : BinaryRRE<"agfr", 0xB918, null_frag, GR64, GR32>; // Addition to a high register. - def AHHHR : BinaryRRFa<"ahhhr", 0xB9C8, null_frag, GRH32, GRH32, GRH32>, - Requires<[FeatureHighWord]>; - def AHHLR : BinaryRRFa<"ahhlr", 0xB9D8, null_frag, GRH32, GRH32, GR32>, - Requires<[FeatureHighWord]>; + let hasSideEffects = 1 in { + def AHHHR : BinaryRRFa<"ahhhr", 0xB9C8, null_frag, GRH32, GRH32, GRH32>, + Requires<[FeatureHighWord]>; + def AHHLR : BinaryRRFa<"ahhlr", 0xB9D8, null_frag, GRH32, GRH32, GR32>, + Requires<[FeatureHighWord]>; + } // Addition of signed 16-bit immediates. defm AHIMux : BinaryRIAndKPseudo<"ahimux", add, GRX32, imm32sx16>; @@ -953,10 +962,12 @@ def ALGFR : BinaryRRE<"algfr", 0xB91A, null_frag, GR64, GR32>; // Addition to a high register. - def ALHHHR : BinaryRRFa<"alhhhr", 0xB9CA, null_frag, GRH32, GRH32, GRH32>, - Requires<[FeatureHighWord]>; - def ALHHLR : BinaryRRFa<"alhhlr", 0xB9DA, null_frag, GRH32, GRH32, GR32>, - Requires<[FeatureHighWord]>; + let hasSideEffects = 1 in { + def ALHHHR : BinaryRRFa<"alhhhr", 0xB9CA, null_frag, GRH32, GRH32, GRH32>, + Requires<[FeatureHighWord]>; + def ALHHLR : BinaryRRFa<"alhhlr", 0xB9DA, null_frag, GRH32, GRH32, GR32>, + Requires<[FeatureHighWord]>; + } // Addition of signed 16-bit immediates. def ALHSIK : BinaryRIE<"alhsik", 0xECDA, addc, GR32, imm32sx16>, @@ -969,8 +980,9 @@ def ALGFI : BinaryRIL<"algfi", 0xC2A, addc, GR64, imm64zx32>; // Addition of signed 32-bit immediates. - def ALSIH : BinaryRIL<"alsih", 0xCCA, null_frag, GRH32, simm32>, - Requires<[FeatureHighWord]>; + let hasSideEffects = 1 in + def ALSIH : BinaryRIL<"alsih", 0xCCA, null_frag, GRH32, simm32>, + Requires<[FeatureHighWord]>; // Addition of memory. defm AL : BinaryRXPair<"al", 0x5E, 0xE35E, addc, GR32, load, 4>; @@ -978,8 +990,10 @@ def ALG : BinaryRXY<"alg", 0xE30A, addc, GR64, load, 8>; // Addition to memory. - def ALSI : BinarySIY<"alsi", 0xEB6E, null_frag, imm32sx8>; - def ALGSI : BinarySIY<"algsi", 0xEB7E, null_frag, imm64sx8>; + let hasSideEffects = 1 in { + def ALSI : BinarySIY<"alsi", 0xEB6E, null_frag, imm32sx8>; + def ALGSI : BinarySIY<"algsi", 0xEB7E, null_frag, imm64sx8>; + } } defm : ZXB; @@ -995,8 +1009,9 @@ } // Addition that does not modify the condition code. -def ALSIHN : BinaryRIL<"alsihn", 0xCCB, null_frag, GRH32, simm32>, - Requires<[FeatureHighWord]>; +let hasSideEffects = 1 in + def ALSIHN : BinaryRIL<"alsihn", 0xCCB, null_frag, GRH32, simm32>, + Requires<[FeatureHighWord]>; //===----------------------------------------------------------------------===// // Subtraction @@ -1011,10 +1026,12 @@ defm SGR : BinaryRREAndK<"sgr", 0xB909, 0xB9E9, sub, GR64, GR64>; // Subtraction from a high register. - def SHHHR : BinaryRRFa<"shhhr", 0xB9C9, null_frag, GRH32, GRH32, GRH32>, - Requires<[FeatureHighWord]>; - def SHHLR : BinaryRRFa<"shhlr", 0xB9D9, null_frag, GRH32, GRH32, GR32>, - Requires<[FeatureHighWord]>; + let hasSideEffects = 1 in { + def SHHHR : BinaryRRFa<"shhhr", 0xB9C9, null_frag, GRH32, GRH32, GRH32>, + Requires<[FeatureHighWord]>; + def SHHLR : BinaryRRFa<"shhlr", 0xB9D9, null_frag, GRH32, GRH32, GR32>, + Requires<[FeatureHighWord]>; + } // Subtraction of memory. defm SH : BinaryRXPair<"sh", 0x4B, 0xE37B, sub, GR32, asextloadi16, 2>; @@ -1034,14 +1051,17 @@ defm SLGR : BinaryRREAndK<"slgr", 0xB90B, 0xB9EB, subc, GR64, GR64>; // Subtraction from a high register. - def SLHHHR : BinaryRRFa<"slhhhr", 0xB9CB, null_frag, GRH32, GRH32, GRH32>, - Requires<[FeatureHighWord]>; - def SLHHLR : BinaryRRFa<"slhhlr", 0xB9DB, null_frag, GRH32, GRH32, GR32>, - Requires<[FeatureHighWord]>; + let hasSideEffects = 1 in { + def SLHHHR : BinaryRRFa<"slhhhr", 0xB9CB, null_frag, GRH32, GRH32, GRH32>, + Requires<[FeatureHighWord]>; + def SLHHLR : BinaryRRFa<"slhhlr", 0xB9DB, null_frag, GRH32, GRH32, GR32>, + Requires<[FeatureHighWord]>; + } // Subtraction of unsigned 32-bit immediates. These don't match // subc because we prefer addc for constants. - def SLFI : BinaryRIL<"slfi", 0xC25, null_frag, GR32, uimm32>; + let hasSideEffects = 1 in + def SLFI : BinaryRIL<"slfi", 0xC25, null_frag, GR32, uimm32>; def SLGFI : BinaryRIL<"slgfi", 0xC24, null_frag, GR64, imm64zx32>; // Subtraction of memory. @@ -1256,29 +1276,35 @@ def MSG : BinaryRXY<"msg", 0xE30C, mul, GR64, load, 8>; // Multiplication of memory, setting the condition code. -let Predicates = [FeatureMiscellaneousExtensions2], Defs = [CC] in { +let Predicates = [FeatureMiscellaneousExtensions2], Defs = [CC], + hasSideEffects = 1 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>; +let hasSideEffects = 1 in + 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>; +let hasSideEffects = 1 in { + 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>; +let hasSideEffects = 1 in { + 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))), @@ -1328,43 +1354,38 @@ //===----------------------------------------------------------------------===// // Logical shift left. -let hasSideEffects = 0 in { - defm SLL : BinaryRSAndK<"sll", 0x89, 0xEBDF, shl, GR32>; - def SLLG : BinaryRSY<"sllg", 0xEB0D, shl, GR64>; - def SLDL : BinaryRS<"sldl", 0x8D, null_frag, GR128>; -} +defm SLL : BinaryRSAndK<"sll", 0x89, 0xEBDF, shl, GR32>; +def SLLG : BinaryRSY<"sllg", 0xEB0D, shl, GR64>; +def SLDL : BinaryRS<"sldl", 0x8D, null_frag, GR128>; // Arithmetic shift left. -let Defs = [CC] in { +let Defs = [CC], hasSideEffects = 1 in { defm SLA : BinaryRSAndK<"sla", 0x8B, 0xEBDD, null_frag, GR32>; def SLAG : BinaryRSY<"slag", 0xEB0B, null_frag, GR64>; def SLDA : BinaryRS<"slda", 0x8F, null_frag, GR128>; } // Logical shift right. -let hasSideEffects = 0 in { - defm SRL : BinaryRSAndK<"srl", 0x88, 0xEBDE, srl, GR32>; - def SRLG : BinaryRSY<"srlg", 0xEB0C, srl, GR64>; - def SRDL : BinaryRS<"srdl", 0x8C, null_frag, GR128>; -} +defm SRL : BinaryRSAndK<"srl", 0x88, 0xEBDE, srl, GR32>; +def SRLG : BinaryRSY<"srlg", 0xEB0C, srl, GR64>; +def SRDL : BinaryRS<"srdl", 0x8C, null_frag, GR128>; // Arithmetic shift right. let Defs = [CC], CCValues = 0xE, CompareZeroCCMask = 0xE in { - defm SRA : BinaryRSAndK<"sra", 0x8A, 0xEBDC, sra, GR32>; + defm SRA : BinaryRSAndK_KSideEff<"sra", 0x8A, 0xEBDC, sra, GR32>; def SRAG : BinaryRSY<"srag", 0xEB0A, sra, GR64>; - def SRDA : BinaryRS<"srda", 0x8E, null_frag, GR128>; + let hasSideEffects = 1 in + def SRDA : BinaryRS<"srda", 0x8E, null_frag, GR128>; } // Rotate left. -let hasSideEffects = 0 in { - def RLL : BinaryRSY<"rll", 0xEB1D, rotl, GR32>; - def RLLG : BinaryRSY<"rllg", 0xEB1C, rotl, GR64>; -} +def RLL : BinaryRSY<"rll", 0xEB1D, rotl, GR32>; +def RLLG : BinaryRSY<"rllg", 0xEB1C, rotl, GR64>; // Rotate second operand left and inserted selected bits into first operand. // These can act like 32-bit operands provided that the constant start and // end bits (operands 2 and 3) are in the range [32, 64). -let Defs = [CC] in { +let Defs = [CC], hasSideEffects = 1 in { let isCodeGenOnly = 1 in def RISBG32 : RotateSelectRIEf<"risbg", 0xEC55, GR32, GR32>; let CCValues = 0xE, CompareZeroCCMask = 0xE in @@ -1372,12 +1393,12 @@ } // On zEC12 we have a variant of RISBG that does not set CC. -let Predicates = [FeatureMiscellaneousExtensions] in +let Predicates = [FeatureMiscellaneousExtensions], hasSideEffects = 1 in def RISBGN : RotateSelectRIEf<"risbgn", 0xEC59, GR64, GR64>; // Forms of RISBG that only affect one word of the destination register. // They do not set CC. -let Predicates = [FeatureHighWord] in { +let Predicates = [FeatureHighWord], hasSideEffects = 1 in { def RISBMux : RotateSelectRIEfPseudo; def RISBLL : RotateSelectAliasRIEf; def RISBLH : RotateSelectAliasRIEf; @@ -1390,7 +1411,7 @@ // Rotate second operand left and perform a logical operation with selected // bits of the first operand. The CC result only describes the selected bits, // so isn't useful for a full comparison against zero. -let Defs = [CC] in { +let Defs = [CC], hasSideEffects = 1 in { def RNSBG : RotateSelectRIEf<"rnsbg", 0xEC54, GR64, GR64>; def ROSBG : RotateSelectRIEf<"rosbg", 0xEC56, GR64, GR64>; def RXSBG : RotateSelectRIEf<"rxsbg", 0xEC57, GR64, GR64>; @@ -1410,10 +1431,12 @@ def CGR : CompareRRE<"cgr", 0xB920, z_scmp, GR64, GR64>; // Comparison with a high register. - def CHHR : CompareRRE<"chhr", 0xB9CD, null_frag, GRH32, GRH32>, - Requires<[FeatureHighWord]>; - def CHLR : CompareRRE<"chlr", 0xB9DD, null_frag, GRH32, GR32>, - Requires<[FeatureHighWord]>; + let hasSideEffects = 1 in { + def CHHR : CompareRRE<"chhr", 0xB9CD, null_frag, GRH32, GRH32>, + Requires<[FeatureHighWord]>; + def CHLR : CompareRRE<"chlr", 0xB9DD, null_frag, GRH32, GR32>, + Requires<[FeatureHighWord]>; + } // Comparison with a signed 16-bit immediate. CHIMux expands to CHI or CIH, // depending on the choice of register. @@ -1462,10 +1485,12 @@ def CLGR : CompareRRE<"clgr", 0xB921, z_ucmp, GR64, GR64>; // Comparison with a high register. - def CLHHR : CompareRRE<"clhhr", 0xB9CF, null_frag, GRH32, GRH32>, - Requires<[FeatureHighWord]>; - def CLHLR : CompareRRE<"clhlr", 0xB9DF, null_frag, GRH32, GR32>, - Requires<[FeatureHighWord]>; + let hasSideEffects = 1 in { + def CLHHR : CompareRRE<"clhhr", 0xB9CF, null_frag, GRH32, GRH32>, + Requires<[FeatureHighWord]>; + def CLHLR : CompareRRE<"clhlr", 0xB9DF, null_frag, GRH32, GR32>, + Requires<[FeatureHighWord]>; + } // Comparison with an unsigned 32-bit immediate. CLFIMux expands to CLFI // or CLIH, depending on the choice of register. @@ -1541,7 +1566,7 @@ def TMH : InstAlias<"tmh\t$R, $I", (TMLH GR32:$R, imm32lh16:$I), 0>; // Compare logical characters under mask -- not (yet) used for codegen. -let Defs = [CC] in { +let Defs = [CC], hasSideEffects = 1 in { defm CLM : CompareRSPair<"clm", 0xBD, 0xEB21, GR32, 0>; def CLMH : CompareRSY<"clmh", 0xEB20, GRH32, 0>; } @@ -1550,10 +1575,12 @@ // Prefetch and execution hint //===----------------------------------------------------------------------===// -def PFD : PrefetchRXY<"pfd", 0xE336, z_prefetch>; -def PFDRL : PrefetchRILPC<"pfdrl", 0xC62, z_prefetch>; +let mayLoad = 1, mayStore = 1 in { + def PFD : PrefetchRXY<"pfd", 0xE336, z_prefetch>; + def PFDRL : PrefetchRILPC<"pfdrl", 0xC62, z_prefetch>; +} -let Predicates = [FeatureExecutionHint] in { +let Predicates = [FeatureExecutionHint], hasSideEffects = 1 in { // Branch Prediction Preload def BPP : BranchPreloadSMI<"bpp", 0xC7>; def BPRP : BranchPreloadMII<"bprp", 0xC5>; @@ -1578,8 +1605,10 @@ let Predicates = [FeatureInterlockedAccess1], Defs = [CC] in { def LAA : LoadAndOpRSY<"laa", 0xEBF8, atomic_load_add_32, GR32>; def LAAG : LoadAndOpRSY<"laag", 0xEBE8, atomic_load_add_64, GR64>; - def LAAL : LoadAndOpRSY<"laal", 0xEBFA, null_frag, GR32>; - def LAALG : LoadAndOpRSY<"laalg", 0xEBEA, null_frag, GR64>; + let hasSideEffects = 1 in { + def LAAL : LoadAndOpRSY<"laal", 0xEBFA, null_frag, GR32>; + def LAALG : LoadAndOpRSY<"laalg", 0xEBEA, null_frag, GR64>; + } def LAN : LoadAndOpRSY<"lan", 0xEBF4, atomic_load_and_32, GR32>; def LANG : LoadAndOpRSY<"lang", 0xEBE4, atomic_load_and_64, GR64>; def LAO : LoadAndOpRSY<"lao", 0xEBF6, atomic_load_or_32, GR32>; @@ -1712,7 +1741,7 @@ } // Test and set. -let mayLoad = 1, Defs = [CC] in +let mayLoad = 1, Defs = [CC], hasSideEffects = 1 in def TS : StoreInherentS<"ts", 0x9300, null_frag, 1>; // Compare and swap. @@ -1723,7 +1752,8 @@ // Compare double and swap. let Defs = [CC] in { - defm CDS : CmpSwapRSPair<"cds", 0xBB, 0xEB31, null_frag, GR128>; + let hasSideEffects = 1 in + defm CDS : CmpSwapRSPair<"cds", 0xBB, 0xEB31, null_frag, GR128>; def CDSG : CmpSwapRSY<"cdsg", 0xEB3E, z_atomic_cmp_swap_128, GR128>; } @@ -1740,7 +1770,7 @@ def STPQ : StoreRXY<"stpq", 0xE38E, z_atomic_store_128, GR128, 16>; // Load pair disjoint. -let Predicates = [FeatureInterlockedAccess1], Defs = [CC] in { +let Predicates = [FeatureInterlockedAccess1], Defs = [CC], hasSideEffects = 1 in { def LPD : BinarySSF<"lpd", 0xC84, GR128>; def LPDG : BinarySSF<"lpdg", 0xC85, GR128>; } @@ -1760,7 +1790,7 @@ let mayLoad = 1, mayStore = 1, Uses = [R0L] in def TRE : SideEffectBinaryMemMemRRE<"tre", 0xB2A5, GR128, GR64>; -let mayLoad = 1, Uses = [R1D], Defs = [CC] in { +let mayLoad = 1, Uses = [R1D], Defs = [CC], hasSideEffects = 1 in { defm TRTE : BinaryMemRRFcOpt<"trte", 0xB9BF, GR128, GR64>; defm TRTRE : BinaryMemRRFcOpt<"trtre", 0xB9BD, GR128, GR64>; } @@ -1821,9 +1851,10 @@ //===----------------------------------------------------------------------===// let Predicates = [FeatureGuardedStorage] in { - def LGG : UnaryRXY<"lgg", 0xE34C, null_frag, GR64, 8>; - def LLGFSG : UnaryRXY<"llgfsg", 0xE348, null_frag, GR64, 4>; - + let hasSideEffects = 1 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 @@ -1834,11 +1865,13 @@ // Decimal arithmetic //===----------------------------------------------------------------------===// -defm CVB : BinaryRXPair<"cvb",0x4F, 0xE306, null_frag, GR32, load, 4>; -def CVBG : BinaryRXY<"cvbg", 0xE30E, null_frag, GR64, load, 8>; +let hasSideEffects = 1 in { + defm CVB : BinaryRXPair<"cvb",0x4F, 0xE306, null_frag, GR32, load, 4>; + def CVBG : BinaryRXY<"cvbg", 0xE30E, null_frag, GR64, load, 8>; -defm CVD : StoreRXPair<"cvd", 0x4E, 0xE326, null_frag, GR32, 4>; -def CVDG : StoreRXY<"cvdg", 0xE32E, null_frag, GR64, 8>; + defm CVD : StoreRXPair<"cvd", 0x4E, 0xE326, null_frag, GR32, 4>; + def CVDG : StoreRXY<"cvdg", 0xE32E, null_frag, GR64, 8>; +} let mayLoad = 1, mayStore = 1 in { def MVN : SideEffectBinarySSa<"mvn", 0xD1>; @@ -1870,7 +1903,7 @@ } } -let Defs = [CC] in { +let Defs = [CC], hasSideEffects = 1 in { def CP : CompareSSb<"cp", 0xF9>; def TP : TestRSL<"tp", 0xEBC0>; } @@ -1882,22 +1915,28 @@ // Read a 32-bit access register into a GR32. As with all GR32 operations, // the upper 32 bits of the enclosing GR64 remain unchanged, which is useful // when a 64-bit address is stored in a pair of access registers. -def EAR : UnaryRRE<"ear", 0xB24F, null_frag, GR32, AR32>; +let hasSideEffects = 1 in + def EAR : UnaryRRE<"ear", 0xB24F, null_frag, GR32, AR32>; // Set access register. -def SAR : UnaryRRE<"sar", 0xB24E, null_frag, AR32, GR32>; +let hasSideEffects = 1 in + def SAR : UnaryRRE<"sar", 0xB24E, null_frag, AR32, GR32>; // Copy access register. -def CPYA : UnaryRRE<"cpya", 0xB24D, null_frag, AR32, AR32>; +let hasSideEffects = 1 in + def CPYA : UnaryRRE<"cpya", 0xB24D, null_frag, AR32, AR32>; // Load address extended. -defm LAE : LoadAddressRXPair<"lae", 0x51, 0xE375, null_frag>; +let hasSideEffects = 1 in + defm LAE : LoadAddressRXPair<"lae", 0x51, 0xE375, null_frag>; // Load access multiple. -defm LAM : LoadMultipleRSPair<"lam", 0x9A, 0xEB9A, AR32>; +let hasSideEffects = 1 in + defm LAM : LoadMultipleRSPair<"lam", 0x9A, 0xEB9A, AR32>; // Load access multiple. -defm STAM : StoreMultipleRSPair<"stam", 0x9B, 0xEB9B, AR32>; +let hasSideEffects = 1 in + defm STAM : StoreMultipleRSPair<"stam", 0x9B, 0xEB9B, AR32>; //===----------------------------------------------------------------------===// // Program mask and addressing mode @@ -1912,7 +1951,7 @@ def SPM : SideEffectUnaryRR<"spm", 0x04, GR32>; // Branch and link - like BAS, but also extracts CC and program mask. -let isCall = 1, Uses = [CC], Defs = [CC] in { +let isCall = 1, Uses = [CC], Defs = [CC], hasSideEffects = 1 in { def BAL : CallRX<"bal", 0x45>; def BALR : CallRR<"balr", 0x05>; } @@ -1929,11 +1968,11 @@ } // Branch and set mode. Not really a call, but also sets an output register. -let isBranch = 1, isTerminator = 1, isBarrier = 1 in +let isBranch = 1, isTerminator = 1, isBarrier = 1, hasSideEffects = 1 in def BSM : CallRR<"bsm", 0x0B>; // Branch and save and set mode. -let isCall = 1, Defs = [CC] in +let isCall = 1, Defs = [CC], hasSideEffects = 1 in def BASSM : CallRR<"bassm", 0x0C>; //===----------------------------------------------------------------------===// @@ -1946,8 +1985,9 @@ def TBEGIN : SideEffectBinarySIL<"tbegin", 0xE560, z_tbegin, imm32zx16>; def TBEGIN_nofloat : SideEffectBinarySILPseudo; - def TBEGINC : SideEffectBinarySIL<"tbeginc", 0xE561, - int_s390_tbeginc, imm32zx16>; + let mayLoad = 1 in + def TBEGINC : SideEffectBinarySIL<"tbeginc", 0xE561, + int_s390_tbeginc, imm32zx16>; } // Transaction End @@ -1955,11 +1995,12 @@ def TEND : SideEffectInherentS<"tend", 0xB2F8, z_tend>; // Transaction Abort - let isTerminator = 1, isBarrier = 1 in + let isTerminator = 1, isBarrier = 1, mayLoad = 1, mayStore = 1 in def TABORT : SideEffectAddressS<"tabort", 0xB2FC, int_s390_tabort>; // Nontransactional Store - def NTSTG : StoreRXY<"ntstg", 0xE325, int_s390_ntstg, GR64, 8>; + let mayLoad = 1, mayStore = 1 in + def NTSTG : StoreRXY<"ntstg", 0xE325, int_s390_ntstg, GR64, 8>; // Extract Transaction Nesting Depth def ETND : InherentRRE<"etnd", 0xB2EC, GR32, int_s390_etnd>; @@ -1985,7 +2026,7 @@ // returns a pair of GR64s, the first giving the number of leading zeros // and the second giving a copy of the source with the leftmost one bit // cleared. We only use the first result here. -let Defs = [CC] in +let Defs = [CC], hasSideEffects = 1 in def FLOGR : UnaryRRE<"flogr", 0xB983, null_frag, GR128, GR64>; def : Pat<(ctlz GR64:$src), (EXTRACT_SUBREG (FLOGR GR64:$src), subreg_h64)>; @@ -2031,7 +2072,7 @@ // .insn directive instructions //===----------------------------------------------------------------------===// -let isCodeGenOnly = 1 in { +let isCodeGenOnly = 1, hasSideEffects = 1 in { def InsnE : DirectiveInsnE<(outs), (ins imm64zx16:$enc), ".insn e,$enc", []>; def InsnRI : DirectiveInsnRI<(outs), (ins imm64zx32:$enc, AnyReg:$R1, imm32sx16:$I2), Index: lib/Target/SystemZ/SystemZInstrSystem.td =================================================================== --- lib/Target/SystemZ/SystemZInstrSystem.td +++ lib/Target/SystemZ/SystemZInstrSystem.td @@ -60,13 +60,15 @@ // Control Register Instructions. //===----------------------------------------------------------------------===// -// Load control. -def LCTL : LoadMultipleRS<"lctl", 0xB7, CR64>; -def LCTLG : LoadMultipleRSY<"lctlg", 0xEB2F, CR64>; +let hasSideEffects = 1 in { + // Load control. + def LCTL : LoadMultipleRS<"lctl", 0xB7, CR64>; + def LCTLG : LoadMultipleRSY<"lctlg", 0xEB2F, CR64>; -// Store control. -def STCTL : StoreMultipleRS<"stctl", 0xB6, CR64>; -def STCTG : StoreMultipleRSY<"stctg", 0xEB25, CR64>; + // Store control. + def STCTL : StoreMultipleRS<"stctl", 0xB6, CR64>; + def STCTG : StoreMultipleRSY<"stctg", 0xEB25, CR64>; +} // Extract primary ASN (and instance). let hasSideEffects = 1 in { @@ -181,10 +183,11 @@ } // Store real address. -def STRAG : StoreSSE<"strag", 0xE502>; +let hasSideEffects = 1 in + def STRAG : StoreSSE<"strag", 0xE502>; // Load using real address. -let mayLoad = 1 in { +let mayLoad = 1, hasSideEffects = 1 in { def LURA : UnaryRRE<"lura", 0xB24B, null_frag, GR32, GR64>; def LURAG : UnaryRRE<"lurag", 0xB905, null_frag, GR64, GR64>; } @@ -204,11 +207,11 @@ //===----------------------------------------------------------------------===// // Move with key. -let mayLoad = 1, mayStore = 1, Defs = [CC] in +let mayLoad = 1, mayStore = 1, Defs = [CC], hasSideEffects = 1 in def MVCK : MemoryBinarySSd<"mvck", 0xD9, GR64>; // Move to primary / secondary. -let mayLoad = 1, mayStore = 1, Defs = [CC] in { +let mayLoad = 1, mayStore = 1, Defs = [CC], hasSideEffects = 1 in { def MVCP : MemoryBinarySSd<"mvcp", 0xDA, GR64>; def MVCS : MemoryBinarySSd<"mvcs", 0xDB, GR64>; } Index: lib/Target/SystemZ/SystemZInstrVector.td =================================================================== --- lib/Target/SystemZ/SystemZInstrVector.td +++ lib/Target/SystemZ/SystemZInstrVector.td @@ -13,15 +13,19 @@ let Predicates = [FeatureVector] in { // Register move. - def VLR : UnaryVRRa<"vlr", 0xE756, null_frag, v128any, v128any>; - def VLR32 : UnaryAliasVRR; - def VLR64 : UnaryAliasVRR; + let hasSideEffects = 1 in { + def VLR : UnaryVRRa<"vlr", 0xE756, null_frag, v128any, v128any>; + def VLR32 : UnaryAliasVRR; + def VLR64 : UnaryAliasVRR; + } // Load GR from VR element. def VLGV : BinaryVRScGeneric<"vlgv", 0xE721>; - def VLGVB : BinaryVRSc<"vlgvb", 0xE721, null_frag, v128b, 0>; - def VLGVH : BinaryVRSc<"vlgvh", 0xE721, null_frag, v128h, 1>; - def VLGVF : BinaryVRSc<"vlgvf", 0xE721, null_frag, v128f, 2>; + let hasSideEffects = 1 in { + def VLGVB : BinaryVRSc<"vlgvb", 0xE721, null_frag, v128b, 0>; + def VLGVH : BinaryVRSc<"vlgvh", 0xE721, null_frag, v128h, 1>; + def VLGVF : BinaryVRSc<"vlgvf", 0xE721, null_frag, v128f, 2>; + } def VLGVG : BinaryVRSc<"vlgvg", 0xE721, z_vector_extract, v128g, 3>; // Load VR element from GR. @@ -37,7 +41,8 @@ // Load VR from GRs disjoint. def VLVGP : BinaryVRRf<"vlvgp", 0xE762, z_join_dwords, v128g>; - def VLVGP32 : BinaryAliasVRRf; + let hasSideEffects = 1 in + def VLVGP32 : BinaryAliasVRRf; } // Extractions always assign to the full GR64, even if the element would @@ -56,8 +61,7 @@ //===----------------------------------------------------------------------===// let Predicates = [FeatureVector] in { - let hasSideEffects = 0, isAsCheapAsAMove = 1, isMoveImm = 1, - isReMaterializable = 1 in { + let isAsCheapAsAMove = 1, isMoveImm = 1, isReMaterializable = 1 in { // Generate byte mask. def VZERO : InherentVRIa<"vzero", 0xE744, 0>; @@ -65,14 +69,16 @@ def VGBM : UnaryVRIa<"vgbm", 0xE744, z_byte_mask, v128b, imm32zx16>; // Generate mask. - def VGM : BinaryVRIbGeneric<"vgm", 0xE746>; + let hasSideEffects = 0 in + def VGM : BinaryVRIbGeneric<"vgm", 0xE746>; def VGMB : BinaryVRIb<"vgmb", 0xE746, z_rotate_mask, v128b, 0>; def VGMH : BinaryVRIb<"vgmh", 0xE746, z_rotate_mask, v128h, 1>; def VGMF : BinaryVRIb<"vgmf", 0xE746, z_rotate_mask, v128f, 2>; def VGMG : BinaryVRIb<"vgmg", 0xE746, z_rotate_mask, v128g, 3>; // Replicate immediate. - def VREPI : UnaryVRIaGeneric<"vrepi", 0xE745, imm32sx16>; + let hasSideEffects = 0 in + def VREPI : UnaryVRIaGeneric<"vrepi", 0xE745, imm32sx16>; def VREPIB : UnaryVRIa<"vrepib", 0xE745, z_replicate, v128b, imm32sx16, 0>; def VREPIH : UnaryVRIa<"vrepih", 0xE745, z_replicate, v128h, imm32sx16, 1>; def VREPIF : UnaryVRIa<"vrepif", 0xE745, z_replicate, v128f, imm32sx16, 2>; @@ -124,7 +130,8 @@ def VLL : BinaryVRSb<"vll", 0xE737, int_s390_vll, 0>; // Load multiple. - def VLM : LoadMultipleVRSa<"vlm", 0xE736>; + let hasSideEffects = 1 in + def VLM : LoadMultipleVRSa<"vlm", 0xE736>; // Load and replicate def VLREP : UnaryVRXGeneric<"vlrep", 0xE705>; @@ -141,8 +148,10 @@ // LEY and LDY offer full 20-bit displacement fields. It's often better // to use those instructions rather than force a 20-bit displacement // into a GPR temporary. - def VL32 : UnaryAliasVRX; - def VL64 : UnaryAliasVRX; + let mayLoad = 1 in { + def VL32 : UnaryAliasVRX; + def VL64 : UnaryAliasVRX; + } // Load logical element and zero. def VLLEZ : UnaryVRXGeneric<"vllez", 0xE704>; @@ -171,8 +180,10 @@ (VLEG VR128:$val, bdxaddr12only:$addr, imm32zx1:$index)>; // Gather element. - def VGEF : TernaryVRV<"vgef", 0xE713, 4, imm32zx2>; - def VGEG : TernaryVRV<"vgeg", 0xE712, 8, imm32zx1>; + let hasSideEffects = 1 in { + def VGEF : TernaryVRV<"vgef", 0xE713, 4, imm32zx2>; + def VGEG : TernaryVRV<"vgeg", 0xE712, 8, imm32zx1>; + } } let Predicates = [FeatureVectorPackedDecimal] in { @@ -210,10 +221,12 @@ def VST : StoreVRX<"vst", 0xE70E, null_frag, v128any, 16>; // Store with length. The number of stored bytes is only known at run time. - def VSTL : StoreLengthVRSb<"vstl", 0xE73F, int_s390_vstl, 0>; + let mayLoad = 1 in + def VSTL : StoreLengthVRSb<"vstl", 0xE73F, int_s390_vstl, 0>; // Store multiple. - def VSTM : StoreMultipleVRSa<"vstm", 0xE73E>; + let hasSideEffects = 1 in + def VSTM : StoreMultipleVRSa<"vstm", 0xE73E>; // Store element. def VSTEB : StoreBinaryVRX<"vsteb", 0xE708, z_vstei8, v128b, 1, imm32zx4>; @@ -231,15 +244,19 @@ // STEY and STDY offer full 20-bit displacement fields. It's often better // to use those instructions rather than force a 20-bit displacement // into a GPR temporary. - def VST32 : StoreAliasVRX; - def VST64 : StoreAliasVRX; + let mayStore = 1 in { + def VST32 : StoreAliasVRX; + def VST64 : StoreAliasVRX; + } // Scatter element. - def VSCEF : StoreBinaryVRV<"vscef", 0xE71B, 4, imm32zx2>; - def VSCEG : StoreBinaryVRV<"vsceg", 0xE71A, 8, imm32zx1>; + let hasSideEffects = 1 in { + def VSCEF : StoreBinaryVRV<"vscef", 0xE71B, 4, imm32zx2>; + def VSCEG : StoreBinaryVRV<"vsceg", 0xE71A, 8, imm32zx1>; + } } -let Predicates = [FeatureVectorPackedDecimal] in { +let Predicates = [FeatureVectorPackedDecimal], mayLoad = 1 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>; @@ -617,7 +634,8 @@ def VOC : BinaryVRRc<"voc", 0xE76F, null_frag, v128any, v128any>; // Population count. - def VPOPCT : UnaryVRRaGeneric<"vpopct", 0xE750>; + let hasSideEffects = 0 in + 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>; @@ -862,19 +880,23 @@ // Element compare. let Defs = [CC] in { def VEC : CompareVRRaGeneric<"vec", 0xE7DB>; - def VECB : CompareVRRa<"vecb", 0xE7DB, null_frag, v128b, 0>; - def VECH : CompareVRRa<"vech", 0xE7DB, null_frag, v128h, 1>; - def VECF : CompareVRRa<"vecf", 0xE7DB, null_frag, v128f, 2>; - def VECG : CompareVRRa<"vecg", 0xE7DB, null_frag, v128g, 3>; + let hasSideEffects = 1 in { + def VECB : CompareVRRa<"vecb", 0xE7DB, null_frag, v128b, 0>; + def VECH : CompareVRRa<"vech", 0xE7DB, null_frag, v128h, 1>; + def VECF : CompareVRRa<"vecf", 0xE7DB, null_frag, v128f, 2>; + def VECG : CompareVRRa<"vecg", 0xE7DB, null_frag, v128g, 3>; + } } // Element compare logical. let Defs = [CC] in { def VECL : CompareVRRaGeneric<"vecl", 0xE7D9>; - def VECLB : CompareVRRa<"veclb", 0xE7D9, null_frag, v128b, 0>; - def VECLH : CompareVRRa<"veclh", 0xE7D9, null_frag, v128h, 1>; - def VECLF : CompareVRRa<"veclf", 0xE7D9, null_frag, v128f, 2>; - def VECLG : CompareVRRa<"veclg", 0xE7D9, null_frag, v128g, 3>; + let hasSideEffects = 1 in { + def VECLB : CompareVRRa<"veclb", 0xE7D9, null_frag, v128b, 0>; + def VECLH : CompareVRRa<"veclh", 0xE7D9, null_frag, v128h, 1>; + def VECLF : CompareVRRa<"veclf", 0xE7D9, null_frag, v128f, 2>; + def VECLG : CompareVRRa<"veclg", 0xE7D9, null_frag, v128g, 3>; + } } // Compare equal. @@ -944,26 +966,30 @@ // Convert from fixed 64-bit. def VCDG : TernaryVRRaFloatGeneric<"vcdg", 0xE7C3>; def VCDGB : TernaryVRRa<"vcdgb", 0xE7C3, null_frag, v128db, v128g, 3, 0>; - def WCDGB : TernaryVRRa<"wcdgb", 0xE7C3, null_frag, v64db, v64g, 3, 8>; + let hasSideEffects = 1 in + def WCDGB : TernaryVRRa<"wcdgb", 0xE7C3, null_frag, v64db, v64g, 3, 8>; def : FPConversion; // Convert from logical 64-bit. def VCDLG : TernaryVRRaFloatGeneric<"vcdlg", 0xE7C1>; def VCDLGB : TernaryVRRa<"vcdlgb", 0xE7C1, null_frag, v128db, v128g, 3, 0>; - def WCDLGB : TernaryVRRa<"wcdlgb", 0xE7C1, null_frag, v64db, v64g, 3, 8>; + let hasSideEffects = 1 in + def WCDLGB : TernaryVRRa<"wcdlgb", 0xE7C1, null_frag, v64db, v64g, 3, 8>; def : FPConversion; // Convert to fixed 64-bit. def VCGD : TernaryVRRaFloatGeneric<"vcgd", 0xE7C2>; def VCGDB : TernaryVRRa<"vcgdb", 0xE7C2, null_frag, v128g, v128db, 3, 0>; - def WCGDB : TernaryVRRa<"wcgdb", 0xE7C2, null_frag, v64g, v64db, 3, 8>; + let hasSideEffects = 1 in + def WCGDB : TernaryVRRa<"wcgdb", 0xE7C2, null_frag, v64g, v64db, 3, 8>; // Rounding mode should agree with SystemZInstrFP.td. def : FPConversion; // Convert to logical 64-bit. def VCLGD : TernaryVRRaFloatGeneric<"vclgd", 0xE7C0>; def VCLGDB : TernaryVRRa<"vclgdb", 0xE7C0, null_frag, v128g, v128db, 3, 0>; - def WCLGDB : TernaryVRRa<"wclgdb", 0xE7C0, null_frag, v64g, v64db, 3, 8>; + let hasSideEffects = 1 in + def WCLGDB : TernaryVRRa<"wclgdb", 0xE7C0, null_frag, v64g, v64db, 3, 8>; // Rounding mode should agree with SystemZInstrFP.td. def : FPConversion; @@ -999,8 +1025,10 @@ let Predicates = [FeatureVectorEnhancements1] in { let isAsmParserOnly = 1 in { def VFLL : UnaryVRRaFloatGeneric<"vfll", 0xE7C4>; - def VFLLS : UnaryVRRa<"vflls", 0xE7C4, null_frag, v128db, v128sb, 2, 0>; - def WFLLS : UnaryVRRa<"wflls", 0xE7C4, null_frag, v64db, v32sb, 2, 8>; + let hasSideEffects = 1 in { + def VFLLS : UnaryVRRa<"vflls", 0xE7C4, null_frag, v128db, v128sb, 2, 0>; + def WFLLS : UnaryVRRa<"wflls", 0xE7C4, null_frag, v64db, v32sb, 2, 8>; + } } def WFLLD : UnaryVRRa<"wflld", 0xE7C4, fpextend, v128xb, v64db, 3, 8>; def : Pat<(f128 (fpextend (f32 VR32:$src))), @@ -1016,8 +1044,10 @@ let Predicates = [FeatureVectorEnhancements1] in { let isAsmParserOnly = 1 in { def VFLR : TernaryVRRaFloatGeneric<"vflr", 0xE7C5>; - def VFLRD : TernaryVRRa<"vflrd", 0xE7C5, null_frag, v128sb, v128db, 3, 0>; - def WFLRD : TernaryVRRa<"wflrd", 0xE7C5, null_frag, v32sb, v64db, 3, 8>; + let hasSideEffects = 1 in { + def VFLRD : TernaryVRRa<"vflrd", 0xE7C5, null_frag, v128sb, v128db, 3, 0>; + def WFLRD : TernaryVRRa<"wflrd", 0xE7C5, null_frag, v32sb, v64db, 3, 8>; + } } def WFLRX : TernaryVRRa<"wflrx", 0xE7C5, null_frag, v64db, v128xb, 4, 8>; def : FPConversion; @@ -1125,12 +1155,14 @@ // Perform sign operation. def VFPSO : BinaryVRRaFloatGeneric<"vfpso", 0xE7CC>; - def VFPSODB : BinaryVRRa<"vfpsodb", 0xE7CC, null_frag, v128db, v128db, 3, 0>; - def WFPSODB : BinaryVRRa<"wfpsodb", 0xE7CC, null_frag, v64db, v64db, 3, 8>; - let Predicates = [FeatureVectorEnhancements1] in { - def VFPSOSB : BinaryVRRa<"vfpsosb", 0xE7CC, null_frag, v128sb, v128sb, 2, 0>; - def WFPSOSB : BinaryVRRa<"wfpsosb", 0xE7CC, null_frag, v32sb, v32sb, 2, 8>; - def WFPSOXB : BinaryVRRa<"wfpsoxb", 0xE7CC, null_frag, v128xb, v128xb, 4, 8>; + let hasSideEffects = 1 in { + def VFPSODB : BinaryVRRa<"vfpsodb", 0xE7CC, null_frag, v128db, v128db, 3, 0>; + def WFPSODB : BinaryVRRa<"wfpsodb", 0xE7CC, null_frag, v64db, v64db, 3, 8>; + let Predicates = [FeatureVectorEnhancements1] in { + def VFPSOSB : BinaryVRRa<"vfpsosb", 0xE7CC, null_frag, v128sb, v128sb, 2, 0>; + def WFPSOSB : BinaryVRRa<"wfpsosb", 0xE7CC, null_frag, v32sb, v32sb, 2, 8>; + def WFPSOXB : BinaryVRRa<"wfpsoxb", 0xE7CC, null_frag, v128xb, v128xb, 4, 8>; + } } // Load complement. @@ -1184,11 +1216,14 @@ let Defs = [CC] in { def VFTCI : BinaryVRIeFloatGeneric<"vftci", 0xE74A>; def VFTCIDB : BinaryVRIe<"vftcidb", 0xE74A, z_vftci, v128g, v128db, 3, 0>; - def WFTCIDB : BinaryVRIe<"wftcidb", 0xE74A, null_frag, v64g, v64db, 3, 8>; + let hasSideEffects = 1 in + def WFTCIDB : BinaryVRIe<"wftcidb", 0xE74A, null_frag, v64g, v64db, 3, 8>; let Predicates = [FeatureVectorEnhancements1] in { def VFTCISB : BinaryVRIe<"vftcisb", 0xE74A, z_vftci, v128f, v128sb, 2, 0>; - def WFTCISB : BinaryVRIe<"wftcisb", 0xE74A, null_frag, v32f, v32sb, 2, 8>; - def WFTCIXB : BinaryVRIe<"wftcixb", 0xE74A, null_frag, v128q, v128xb, 4, 8>; + let hasSideEffects = 1 in { + def WFTCISB : BinaryVRIe<"wftcisb", 0xE74A, null_frag, v32f, v32sb, 2, 8>; + def WFTCIXB : BinaryVRIe<"wftcixb", 0xE74A, null_frag, v128q, v128xb, 4, 8>; + } } } } @@ -1211,10 +1246,12 @@ // Compare and signal scalar. let Defs = [CC] in { def WFK : CompareVRRaFloatGeneric<"wfk", 0xE7CA>; - def WFKDB : CompareVRRa<"wfkdb", 0xE7CA, null_frag, v64db, 3>; - let Predicates = [FeatureVectorEnhancements1] in { - def WFKSB : CompareVRRa<"wfksb", 0xE7CA, null_frag, v32sb, 2>; - def WFKXB : CompareVRRa<"wfkxb", 0xE7CA, null_frag, v128xb, 4>; + let hasSideEffects = 1 in { + def WFKDB : CompareVRRa<"wfkdb", 0xE7CA, null_frag, v64db, 3>; + let Predicates = [FeatureVectorEnhancements1] in { + def WFKSB : CompareVRRa<"wfksb", 0xE7CA, null_frag, v32sb, 2>; + def WFKXB : CompareVRRa<"wfkxb", 0xE7CA, null_frag, v128xb, 4>; + } } } @@ -1222,19 +1259,22 @@ def VFCE : BinaryVRRcSPairFloatGeneric<"vfce", 0xE7E8>; defm VFCEDB : BinaryVRRcSPair<"vfcedb", 0xE7E8, z_vfcmpe, z_vfcmpes, v128g, v128db, 3, 0>; - defm WFCEDB : BinaryVRRcSPair<"wfcedb", 0xE7E8, null_frag, null_frag, - v64g, v64db, 3, 8>; + let hasSideEffects = 1 in + defm WFCEDB : BinaryVRRcSPair<"wfcedb", 0xE7E8, null_frag, null_frag, + v64g, v64db, 3, 8>; let Predicates = [FeatureVectorEnhancements1] in { defm VFCESB : BinaryVRRcSPair<"vfcesb", 0xE7E8, z_vfcmpe, z_vfcmpes, v128f, v128sb, 2, 0>; - defm WFCESB : BinaryVRRcSPair<"wfcesb", 0xE7E8, null_frag, null_frag, - v32f, v32sb, 2, 8>; - defm WFCEXB : BinaryVRRcSPair<"wfcexb", 0xE7E8, null_frag, null_frag, - v128q, v128xb, 4, 8>; + let hasSideEffects = 1 in { + defm WFCESB : BinaryVRRcSPair<"wfcesb", 0xE7E8, null_frag, null_frag, + v32f, v32sb, 2, 8>; + defm WFCEXB : BinaryVRRcSPair<"wfcexb", 0xE7E8, null_frag, null_frag, + v128q, v128xb, 4, 8>; + } } // Compare and signal equal. - let Predicates = [FeatureVectorEnhancements1] in { + let Predicates = [FeatureVectorEnhancements1], hasSideEffects = 1 in { defm VFKEDB : BinaryVRRcSPair<"vfkedb", 0xE7E8, null_frag, null_frag, v128g, v128db, 3, 4>; defm WFKEDB : BinaryVRRcSPair<"wfkedb", 0xE7E8, null_frag, null_frag, @@ -1251,19 +1291,22 @@ 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>; + let hasSideEffects = 1 in + defm WFCHDB : BinaryVRRcSPair<"wfchdb", 0xE7EB, null_frag, null_frag, + v64g, v64db, 3, 8>; let Predicates = [FeatureVectorEnhancements1] in { defm VFCHSB : BinaryVRRcSPair<"vfchsb", 0xE7EB, z_vfcmph, z_vfcmphs, v128f, v128sb, 2, 0>; - defm WFCHSB : BinaryVRRcSPair<"wfchsb", 0xE7EB, null_frag, null_frag, - v32f, v32sb, 2, 8>; - defm WFCHXB : BinaryVRRcSPair<"wfchxb", 0xE7EB, null_frag, null_frag, - v128q, v128xb, 4, 8>; + let hasSideEffects = 1 in { + defm WFCHSB : BinaryVRRcSPair<"wfchsb", 0xE7EB, null_frag, null_frag, + v32f, v32sb, 2, 8>; + defm WFCHXB : BinaryVRRcSPair<"wfchxb", 0xE7EB, null_frag, null_frag, + v128q, v128xb, 4, 8>; + } } // Compare and signal high. - let Predicates = [FeatureVectorEnhancements1] in { + let Predicates = [FeatureVectorEnhancements1], hasSideEffects = 1 in { defm VFKHDB : BinaryVRRcSPair<"vfkhdb", 0xE7EB, null_frag, null_frag, v128g, v128db, 3, 4>; defm WFKHDB : BinaryVRRcSPair<"wfkhdb", 0xE7EB, null_frag, null_frag, @@ -1280,19 +1323,22 @@ 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>; + let hasSideEffects = 1 in + defm WFCHEDB : BinaryVRRcSPair<"wfchedb", 0xE7EA, null_frag, null_frag, + v64g, v64db, 3, 8>; let Predicates = [FeatureVectorEnhancements1] in { defm VFCHESB : BinaryVRRcSPair<"vfchesb", 0xE7EA, z_vfcmphe, z_vfcmphes, v128f, v128sb, 2, 0>; - defm WFCHESB : BinaryVRRcSPair<"wfchesb", 0xE7EA, null_frag, null_frag, - v32f, v32sb, 2, 8>; - defm WFCHEXB : BinaryVRRcSPair<"wfchexb", 0xE7EA, null_frag, null_frag, - v128q, v128xb, 4, 8>; + let hasSideEffects = 1 in { + defm WFCHESB : BinaryVRRcSPair<"wfchesb", 0xE7EA, null_frag, null_frag, + v32f, v32sb, 2, 8>; + defm WFCHEXB : BinaryVRRcSPair<"wfchexb", 0xE7EA, null_frag, null_frag, + v128q, v128xb, 4, 8>; + } } // Compare and signal high or equal. - let Predicates = [FeatureVectorEnhancements1] in { + let Predicates = [FeatureVectorEnhancements1], hasSideEffects = 1 in { defm VFKHEDB : BinaryVRRcSPair<"vfkhedb", 0xE7EA, null_frag, null_frag, v128g, v128db, 3, 4>; defm WFKHEDB : BinaryVRRcSPair<"wfkhedb", 0xE7EA, null_frag, null_frag, @@ -1385,7 +1431,8 @@ // and VLGVF. let Predicates = [FeatureVector] in { def LEFR : UnaryAliasVRS; - def LFER : UnaryAliasVRS; + let hasSideEffects = 1 in + def LFER : UnaryAliasVRS; def : Pat<(f32 (bitconvert (i32 GR32:$src))), (LEFR GR32:$src)>; def : Pat<(i32 (bitconvert (f32 VR32:$src))), (EXTRACT_SUBREG (LFER VR32:$src), subreg_l32)>; @@ -1521,7 +1568,7 @@ // Packed-decimal instructions //===----------------------------------------------------------------------===// -let Predicates = [FeatureVectorPackedDecimal] in { +let Predicates = [FeatureVectorPackedDecimal], hasSideEffects = 1 in { def VLIP : BinaryVRIh<"vlip", 0xE649>; def VPKZ : BinaryVSI<"vpkz", 0xE634, null_frag, 0>;