-// Helper pattern for normalizing inputs to triginomic instructions for R700+
-// cards.
-class COS_PAT <InstR600 trig> : Pat<
- (fcos f32:$src),
- (trig (MUL_IEEE (MOV_IMM_I32 CONST.TWO_PI_INV), $src))
->;
-
-class SIN_PAT <InstR600 trig> : Pat<
- (fsin f32:$src),
- (trig (MUL_IEEE (MOV_IMM_I32 CONST.TWO_PI_INV), $src))
->;
-
-//===----------------------------------------------------------------------===//
-// R700 Only instructions
-//===----------------------------------------------------------------------===//
-
-let Predicates = [isR700] in {
- def SIN_r700 : SIN_Common<0x6E>;
- def COS_r700 : COS_Common<0x6F>;
-
- // R700 normalizes inputs to SIN/COS the same as EG
- def : SIN_PAT <SIN_r700>;
- def : COS_PAT <COS_r700>;
-}
-
-//===----------------------------------------------------------------------===//
-// Evergreen Only instructions
-//===----------------------------------------------------------------------===//
-
-let Predicates = [isEG] in {
-
-def RECIP_IEEE_eg : RECIP_IEEE_Common<0x86>;
-defm DIV_eg : DIV_Common<RECIP_IEEE_eg>;
-
-def MULLO_INT_eg : MULLO_INT_Common<0x8F>;
-def MULHI_INT_eg : MULHI_INT_Common<0x90>;
-def MULLO_UINT_eg : MULLO_UINT_Common<0x91>;
-def MULHI_UINT_eg : MULHI_UINT_Common<0x92>;
-def RECIP_UINT_eg : RECIP_UINT_Common<0x94>;
-def RECIPSQRT_CLAMPED_eg : RECIPSQRT_CLAMPED_Common<0x87>;
-def EXP_IEEE_eg : EXP_IEEE_Common<0x81>;
-def LOG_IEEE_eg : LOG_IEEE_Common<0x83>;
-def RECIP_CLAMPED_eg : RECIP_CLAMPED_Common<0x84>;
-def RECIPSQRT_IEEE_eg : RECIPSQRT_IEEE_Common<0x89>;
-def SIN_eg : SIN_Common<0x8D>;
-def COS_eg : COS_Common<0x8E>;
-
-def : POW_Common <LOG_IEEE_eg, EXP_IEEE_eg, MUL>;
-def : SIN_PAT <SIN_eg>;
-def : COS_PAT <COS_eg>;
-def : Pat<(fsqrt f32:$src), (MUL $src, (RECIPSQRT_CLAMPED_eg $src))>;
-
-//===----------------------------------------------------------------------===//
-// Memory read/write instructions
-//===----------------------------------------------------------------------===//
-let usesCustomInserter = 1 in {
-
-class RAT_WRITE_CACHELESS_eg <dag ins, bits<4> mask, string name,
- list<dag> pattern>
- : EG_CF_RAT <0x57, 0x2, mask, (outs), ins, name, pattern> {
-}
-
-} // End usesCustomInserter = 1
-
-// 32-bit store
-def RAT_WRITE_CACHELESS_32_eg : RAT_WRITE_CACHELESS_eg <
- (ins R600_TReg32_X:$rw_gpr, R600_TReg32_X:$index_gpr, InstFlag:$eop),
- 0x1, "RAT_WRITE_CACHELESS_32_eg $rw_gpr, $index_gpr, $eop",
- [(global_store i32:$rw_gpr, i32:$index_gpr)]
->;
-
-//128-bit store
-def RAT_WRITE_CACHELESS_128_eg : RAT_WRITE_CACHELESS_eg <
- (ins R600_Reg128:$rw_gpr, R600_TReg32_X:$index_gpr, InstFlag:$eop),
- 0xf, "RAT_WRITE_CACHELESS_128 $rw_gpr.XYZW, $index_gpr, $eop",
- [(global_store v4i32:$rw_gpr, i32:$index_gpr)]
->;
-
-class VTX_READ_eg <string name, bits<8> buffer_id, dag outs, list<dag> pattern>
- : VTX_WORD0_eg, VTX_READ<name, buffer_id, outs, pattern> {
-
- // Static fields
- let VC_INST = 0;
- let FETCH_TYPE = 2;
- let FETCH_WHOLE_QUAD = 0;
- let BUFFER_ID = buffer_id;
- let SRC_REL = 0;
- // XXX: We can infer this field based on the SRC_GPR. This would allow us
- // to store vertex addresses in any channel, not just X.
- let SRC_SEL_X = 0;
-
- let Inst{31-0} = Word0;
-}
-
-class VTX_READ_8_eg <bits<8> buffer_id, list<dag> pattern>
- : VTX_READ_eg <"VTX_READ_8 $dst_gpr, $src_gpr", buffer_id,
- (outs R600_TReg32_X:$dst_gpr), pattern> {
-
- let MEGA_FETCH_COUNT = 1;
- let DST_SEL_X = 0;
- let DST_SEL_Y = 7; // Masked
- let DST_SEL_Z = 7; // Masked
- let DST_SEL_W = 7; // Masked
- let DATA_FORMAT = 1; // FMT_8
-}
-
-class VTX_READ_16_eg <bits<8> buffer_id, list<dag> pattern>
- : VTX_READ_eg <"VTX_READ_16 $dst_gpr, $src_gpr", buffer_id,
- (outs R600_TReg32_X:$dst_gpr), pattern> {
- let MEGA_FETCH_COUNT = 2;
- let DST_SEL_X = 0;
- let DST_SEL_Y = 7; // Masked
- let DST_SEL_Z = 7; // Masked
- let DST_SEL_W = 7; // Masked
- let DATA_FORMAT = 5; // FMT_16
-
-}
-
-class VTX_READ_32_eg <bits<8> buffer_id, list<dag> pattern>
- : VTX_READ_eg <"VTX_READ_32 $dst_gpr, $src_gpr", buffer_id,
- (outs R600_TReg32_X:$dst_gpr), pattern> {
-
- let MEGA_FETCH_COUNT = 4;
- let DST_SEL_X = 0;
- let DST_SEL_Y = 7; // Masked
- let DST_SEL_Z = 7; // Masked
- let DST_SEL_W = 7; // Masked
- let DATA_FORMAT = 0xD; // COLOR_32
-
- // This is not really necessary, but there were some GPU hangs that appeared
- // to be caused by ALU instructions in the next instruction group that wrote
- // to the $src_gpr registers of the VTX_READ.
- // e.g.
- // %T3_X<def> = VTX_READ_PARAM_32_eg %T2_X<kill>, 24
- // %T2_X<def> = MOV %ZERO
- //Adding this constraint prevents this from happening.
- let Constraints = "$src_gpr.ptr = $dst_gpr";
-}
-
-class VTX_READ_128_eg <bits<8> buffer_id, list<dag> pattern>
- : VTX_READ_eg <"VTX_READ_128 $dst_gpr.XYZW, $src_gpr", buffer_id,
- (outs R600_Reg128:$dst_gpr), pattern> {
-
- let MEGA_FETCH_COUNT = 16;
- let DST_SEL_X = 0;
- let DST_SEL_Y = 1;
- let DST_SEL_Z = 2;
- let DST_SEL_W = 3;
- let DATA_FORMAT = 0x22; // COLOR_32_32_32_32
-
- // XXX: Need to force VTX_READ_128 instructions to write to the same register
- // that holds its buffer address to avoid potential hangs. We can't use
- // the same constraint as VTX_READ_32_eg, because the $src_gpr.ptr and $dst
- // registers are different sizes.
-}
-
-//===----------------------------------------------------------------------===//
-// VTX Read from parameter memory space
-//===----------------------------------------------------------------------===//
-
-def VTX_READ_PARAM_8_eg : VTX_READ_8_eg <0,
- [(set i32:$dst_gpr, (load_param_zexti8 ADDRVTX_READ:$src_gpr))]
->;
-
-def VTX_READ_PARAM_16_eg : VTX_READ_16_eg <0,
- [(set i32:$dst_gpr, (load_param_zexti16 ADDRVTX_READ:$src_gpr))]
->;
-
-def VTX_READ_PARAM_32_eg : VTX_READ_32_eg <0,
- [(set i32:$dst_gpr, (load_param ADDRVTX_READ:$src_gpr))]
->;
-
-def VTX_READ_PARAM_128_eg : VTX_READ_128_eg <0,
- [(set v4i32:$dst_gpr, (load_param ADDRVTX_READ:$src_gpr))]
->;
-
-//===----------------------------------------------------------------------===//
-// VTX Read from global memory space
-//===----------------------------------------------------------------------===//
-
-// 8-bit reads
-def VTX_READ_GLOBAL_8_eg : VTX_READ_8_eg <1,
- [(set i32:$dst_gpr, (zextloadi8_global ADDRVTX_READ:$src_gpr))]
->;
-
-// 32-bit reads
-def VTX_READ_GLOBAL_32_eg : VTX_READ_32_eg <1,
- [(set i32:$dst_gpr, (global_load ADDRVTX_READ:$src_gpr))]
->;
-
-// 128-bit reads
-def VTX_READ_GLOBAL_128_eg : VTX_READ_128_eg <1,
- [(set v4i32:$dst_gpr, (global_load ADDRVTX_READ:$src_gpr))]
->;
-
-//===----------------------------------------------------------------------===//
-// Constant Loads
-// XXX: We are currently storing all constants in the global address space.
-//===----------------------------------------------------------------------===//
-
-def CONSTANT_LOAD_eg : VTX_READ_32_eg <1,
- [(set i32:$dst_gpr, (constant_load ADDRVTX_READ:$src_gpr))]
->;
-
-
-} // End Predicates = [isEG]
-
-//===----------------------------------------------------------------------===//
-// Evergreen / Cayman Instructions
-//===----------------------------------------------------------------------===//
-
-let Predicates = [isEGorCayman] in {
-
- // BFE_UINT - bit_extract, an optimization for mask and shift
- // Src0 = Input
- // Src1 = Offset
- // Src2 = Width
- //
- // bit_extract = (Input << (32 - Offset - Width)) >> (32 - Width)
- //
- // Example Usage:
- // (Offset, Width)
- //
- // (0, 8) = (Input << 24) >> 24 = (Input & 0xff) >> 0
- // (8, 8) = (Input << 16) >> 24 = (Input & 0xffff) >> 8
- // (16,8) = (Input << 8) >> 24 = (Input & 0xffffff) >> 16
- // (24,8) = (Input << 0) >> 24 = (Input & 0xffffffff) >> 24
- def BFE_UINT_eg : R600_3OP <0x4, "BFE_UINT",
- [(set i32:$dst, (int_AMDIL_bit_extract_u32 i32:$src0, i32:$src1,
- i32:$src2))],
- VecALU
- >;
- def : BFEPattern <BFE_UINT_eg>;
-
- def BFI_INT_eg : R600_3OP <0x06, "BFI_INT", [], VecALU>;
- defm : BFIPatterns <BFI_INT_eg>;
-
- def BIT_ALIGN_INT_eg : R600_3OP <0xC, "BIT_ALIGN_INT", [], VecALU>;
- def : ROTRPattern <BIT_ALIGN_INT_eg>;
-
- def MULADD_eg : MULADD_Common<0x14>;
- def MULADD_IEEE_eg : MULADD_IEEE_Common<0x18>;
- def ASHR_eg : ASHR_Common<0x15>;
- def LSHR_eg : LSHR_Common<0x16>;
- def LSHL_eg : LSHL_Common<0x17>;
- def CNDE_eg : CNDE_Common<0x19>;
- def CNDGT_eg : CNDGT_Common<0x1A>;
- def CNDGE_eg : CNDGE_Common<0x1B>;
- def MUL_LIT_eg : MUL_LIT_Common<0x1F>;
- def LOG_CLAMPED_eg : LOG_CLAMPED_Common<0x82>;
- def DOT4_eg : DOT4_Common<0xBE>;
- defm CUBE_eg : CUBE_Common<0xC0>;
-
-let hasSideEffects = 1 in {
- def MOVA_INT_eg : R600_1OP <0xCC, "MOVA_INT", []>;
-}
-
- def TGSI_LIT_Z_eg : TGSI_LIT_Z_Common<MUL_LIT_eg, LOG_CLAMPED_eg, EXP_IEEE_eg>;
-
- def FLT_TO_INT_eg : FLT_TO_INT_Common<0x50> {
- let Pattern = [];
- }
-
- def INT_TO_FLT_eg : INT_TO_FLT_Common<0x9B>;
-
- def FLT_TO_UINT_eg : FLT_TO_UINT_Common<0x9A> {
- let Pattern = [];
- }
-
- def UINT_TO_FLT_eg : UINT_TO_FLT_Common<0x9C>;
-
- // TRUNC is used for the FLT_TO_INT instructions to work around a
- // perceived problem where the rounding modes are applied differently
- // depending on the instruction and the slot they are in.
- // See:
- // https://bugs.freedesktop.org/show_bug.cgi?id=50232
- // Mesa commit: a1a0974401c467cb86ef818f22df67c21774a38c
- //
- // XXX: Lowering SELECT_CC will sometimes generate fp_to_[su]int nodes,
- // which do not need to be truncated since the fp values are 0.0f or 1.0f.
- // We should look into handling these cases separately.
- def : Pat<(fp_to_sint f32:$src0), (FLT_TO_INT_eg (TRUNC $src0))>;
-
- def : Pat<(fp_to_uint f32:$src0), (FLT_TO_UINT_eg (TRUNC $src0))>;
-
- // SHA-256 Patterns
- def : SHA256MaPattern <BFI_INT_eg, XOR_INT>;
-
- def EG_ExportSwz : ExportSwzInst {
- let Word1{19-16} = 0; // BURST_COUNT
- let Word1{20} = 1; // VALID_PIXEL_MODE
- let Word1{21} = eop;
- let Word1{29-22} = inst;
- let Word1{30} = 0; // MARK
- let Word1{31} = 1; // BARRIER
- }
- defm : ExportPattern<EG_ExportSwz, 83>;
-
- def EG_ExportBuf : ExportBufInst {
- let Word1{19-16} = 0; // BURST_COUNT
- let Word1{20} = 1; // VALID_PIXEL_MODE
- let Word1{21} = eop;
- let Word1{29-22} = inst;
- let Word1{30} = 0; // MARK
- let Word1{31} = 1; // BARRIER
- }
- defm : SteamOutputExportPattern<EG_ExportBuf, 0x40, 0x41, 0x42, 0x43>;
-
- def CF_TC_EG : CF_CLAUSE_EG<1, (ins i32imm:$ADDR, i32imm:$COUNT),
- "TEX $COUNT @$ADDR"> {
- let POP_COUNT = 0;
- }
- def CF_VC_EG : CF_CLAUSE_EG<2, (ins i32imm:$ADDR, i32imm:$COUNT),
- "VTX $COUNT @$ADDR"> {
- let POP_COUNT = 0;
- }
- def WHILE_LOOP_EG : CF_CLAUSE_EG<6, (ins i32imm:$ADDR),
- "LOOP_START_DX10 @$ADDR"> {
- let POP_COUNT = 0;
- let COUNT = 0;
- }
- def END_LOOP_EG : CF_CLAUSE_EG<5, (ins i32imm:$ADDR), "END_LOOP @$ADDR"> {
- let POP_COUNT = 0;
- let COUNT = 0;
- }
- def LOOP_BREAK_EG : CF_CLAUSE_EG<9, (ins i32imm:$ADDR),
- "LOOP_BREAK @$ADDR"> {
- let POP_COUNT = 0;
- let COUNT = 0;
- }
- def CF_CONTINUE_EG : CF_CLAUSE_EG<8, (ins i32imm:$ADDR),
- "CONTINUE @$ADDR"> {
- let POP_COUNT = 0;
- let COUNT = 0;
- }
- def CF_JUMP_EG : CF_CLAUSE_EG<10, (ins i32imm:$ADDR, i32imm:$POP_COUNT),
- "JUMP @$ADDR POP:$POP_COUNT"> {
- let COUNT = 0;
- }
- def CF_ELSE_EG : CF_CLAUSE_EG<13, (ins i32imm:$ADDR, i32imm:$POP_COUNT),
- "ELSE @$ADDR POP:$POP_COUNT"> {
- let COUNT = 0;
- }
- def CF_CALL_FS_EG : CF_CLAUSE_EG<19, (ins), "CALL_FS"> {
- let ADDR = 0;
- let COUNT = 0;
- let POP_COUNT = 0;
- }
- def POP_EG : CF_CLAUSE_EG<14, (ins i32imm:$ADDR, i32imm:$POP_COUNT),
- "POP @$ADDR POP:$POP_COUNT"> {
- let COUNT = 0;
- }
- def CF_END_EG : CF_CLAUSE_EG<0, (ins), "CF_END"> {
- let COUNT = 0;
- let POP_COUNT = 0;
- let ADDR = 0;
- let END_OF_PROGRAM = 1;
- }
-
-} // End Predicates = [isEGorCayman]