diff --git a/llvm/lib/Target/RISCV/RISCV.td b/llvm/lib/Target/RISCV/RISCV.td --- a/llvm/lib/Target/RISCV/RISCV.td +++ b/llvm/lib/Target/RISCV/RISCV.td @@ -92,10 +92,13 @@ // Registers, calling conventions, instruction descriptions. //===----------------------------------------------------------------------===// +include "RISCVSchedule.td" include "RISCVRegisterInfo.td" include "RISCVCallingConv.td" include "RISCVInstrInfo.td" include "RISCVRegisterBanks.td" +include "RISCVSchedRocket32.td" +include "RISCVSchedRocket64.td" //===----------------------------------------------------------------------===// // RISC-V processors supported. @@ -106,6 +109,12 @@ def : ProcessorModel<"generic-rv64", NoSchedModel, [Feature64Bit, FeatureRVCHints]>; +def : ProcessorModel<"rocket-rv32", Rocket32Model, [FeatureRVCHints]>; + +def : ProcessorModel<"rocket-rv64", Rocket64Model, [Feature64Bit, + FeatureRVCHints]>; + + //===----------------------------------------------------------------------===// // Define the RISC-V target. //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -298,7 +298,8 @@ class BranchCC_rri funct3, string opcodestr> : RVInstB { + opcodestr, "$rs1, $rs2, $imm12">, + Sched<[WriteJmp]> { let isBranch = 1; let isTerminator = 1; } @@ -336,13 +337,13 @@ let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in class CSR_ir funct3, string opcodestr> : RVInstI; + opcodestr, "$rd, $imm12, $rs1">, Sched<[WriteCSR]>; let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in class CSR_ii funct3, string opcodestr> : RVInstI; + opcodestr, "$rd, $imm12, $rs1">, Sched<[WriteCSR]>; let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in class ShiftW_ri funct3, string opcodestr> @@ -367,19 +368,19 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { let isReMaterializable = 1, isAsCheapAsAMove = 1 in def LUI : RVInstU; + "lui", "$rd, $imm20">, Sched<[WriteIALU]>; def AUIPC : RVInstU; + "auipc", "$rd, $imm20">, Sched<[WriteIALU]>; let isCall = 1 in def JAL : RVInstJ; + "jal", "$rd, $imm20">, Sched<[WriteJal]>; let isCall = 1 in def JALR : RVInstI<0b000, OPC_JALR, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12), - "jalr", "$rd, ${imm12}(${rs1})">; + "jalr", "$rd, ${imm12}(${rs1})">, Sched<[WriteJalr]>; } // hasSideEffects = 0, mayLoad = 0, mayStore = 0 def BEQ : BranchCC_rri<0b000, "beq">; @@ -389,50 +390,50 @@ def BLTU : BranchCC_rri<0b110, "bltu">; def BGEU : BranchCC_rri<0b111, "bgeu">; -def LB : Load_ri<0b000, "lb">; -def LH : Load_ri<0b001, "lh">; -def LW : Load_ri<0b010, "lw">; -def LBU : Load_ri<0b100, "lbu">; -def LHU : Load_ri<0b101, "lhu">; +def LB : Load_ri<0b000, "lb">, Sched<[WriteLDB]>; +def LH : Load_ri<0b001, "lh">, Sched<[WriteLDH]>; +def LW : Load_ri<0b010, "lw">, Sched<[WriteLDW]>; +def LBU : Load_ri<0b100, "lbu">, Sched<[WriteLDB]>; +def LHU : Load_ri<0b101, "lhu">, Sched<[WriteLDH]>; -def SB : Store_rri<0b000, "sb">; -def SH : Store_rri<0b001, "sh">; -def SW : Store_rri<0b010, "sw">; +def SB : Store_rri<0b000, "sb">, Sched<[WriteSTB]>; +def SH : Store_rri<0b001, "sh">, Sched<[WriteSTH]>; +def SW : Store_rri<0b010, "sw">, Sched<[WriteSTW]>; // ADDI isn't always rematerializable, but isReMaterializable will be used as // a hint which is verified in isReallyTriviallyReMaterializable. let isReMaterializable = 1, isAsCheapAsAMove = 1 in -def ADDI : ALU_ri<0b000, "addi">; +def ADDI : ALU_ri<0b000, "addi">, Sched<[WriteIALU]>; -def SLTI : ALU_ri<0b010, "slti">; -def SLTIU : ALU_ri<0b011, "sltiu">; +def SLTI : ALU_ri<0b010, "slti">, Sched<[WriteIALU]>; +def SLTIU : ALU_ri<0b011, "sltiu">, Sched<[WriteIALU]>; let isReMaterializable = 1, isAsCheapAsAMove = 1 in { -def XORI : ALU_ri<0b100, "xori">; -def ORI : ALU_ri<0b110, "ori">; +def XORI : ALU_ri<0b100, "xori">, Sched<[WriteIALU]>; +def ORI : ALU_ri<0b110, "ori">, Sched<[WriteIALU]>; } -def ANDI : ALU_ri<0b111, "andi">; +def ANDI : ALU_ri<0b111, "andi">, Sched<[WriteIALU]>; -def SLLI : Shift_ri<0, 0b001, "slli">; -def SRLI : Shift_ri<0, 0b101, "srli">; -def SRAI : Shift_ri<1, 0b101, "srai">; +def SLLI : Shift_ri<0, 0b001, "slli">, Sched<[WriteShift]>; +def SRLI : Shift_ri<0, 0b101, "srli">, Sched<[WriteShift]>; +def SRAI : Shift_ri<1, 0b101, "srai">, Sched<[WriteShift]>; -def ADD : ALU_rr<0b0000000, 0b000, "add">; -def SUB : ALU_rr<0b0100000, 0b000, "sub">; -def SLL : ALU_rr<0b0000000, 0b001, "sll">; -def SLT : ALU_rr<0b0000000, 0b010, "slt">; -def SLTU : ALU_rr<0b0000000, 0b011, "sltu">; -def XOR : ALU_rr<0b0000000, 0b100, "xor">; -def SRL : ALU_rr<0b0000000, 0b101, "srl">; -def SRA : ALU_rr<0b0100000, 0b101, "sra">; -def OR : ALU_rr<0b0000000, 0b110, "or">; -def AND : ALU_rr<0b0000000, 0b111, "and">; +def ADD : ALU_rr<0b0000000, 0b000, "add">, Sched<[WriteIALU]>; +def SUB : ALU_rr<0b0100000, 0b000, "sub">, Sched<[WriteIALU]>; +def SLL : ALU_rr<0b0000000, 0b001, "sll">, Sched<[WriteIALU]>; +def SLT : ALU_rr<0b0000000, 0b010, "slt">, Sched<[WriteIALU]>; +def SLTU : ALU_rr<0b0000000, 0b011, "sltu">, Sched<[WriteIALU]>; +def XOR : ALU_rr<0b0000000, 0b100, "xor">, Sched<[WriteIALU]>; +def SRL : ALU_rr<0b0000000, 0b101, "srl">, Sched<[WriteIALU]>; +def SRA : ALU_rr<0b0100000, 0b101, "sra">, Sched<[WriteIALU]>; +def OR : ALU_rr<0b0000000, 0b110, "or">, Sched<[WriteIALU]>; +def AND : ALU_rr<0b0000000, 0b111, "and">, Sched<[WriteIALU]>; let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in { def FENCE : RVInstI<0b000, OPC_MISC_MEM, (outs), (ins fencearg:$pred, fencearg:$succ), - "fence", "$pred, $succ"> { + "fence", "$pred, $succ">, Sched<[]> { bits<4> pred; bits<4> succ; @@ -441,25 +442,28 @@ let imm12 = {0b0000,pred,succ}; } -def FENCE_TSO : RVInstI<0b000, OPC_MISC_MEM, (outs), (ins), "fence.tso", ""> { +def FENCE_TSO : RVInstI<0b000, OPC_MISC_MEM, (outs), (ins), "fence.tso", "">, + Sched<[WriteFence]> { let rs1 = 0; let rd = 0; let imm12 = {0b1000,0b0011,0b0011}; } -def FENCE_I : RVInstI<0b001, OPC_MISC_MEM, (outs), (ins), "fence.i", ""> { +def FENCE_I : RVInstI<0b001, OPC_MISC_MEM, (outs), (ins), "fence.i", "">, + Sched<[WriteFence]> { let rs1 = 0; let rd = 0; let imm12 = 0; } -def ECALL : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ecall", ""> { +def ECALL : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ecall", "">, Sched<[WriteJmp]> { let rs1 = 0; let rd = 0; let imm12 = 0; } -def EBREAK : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ebreak", ""> { +def EBREAK : RVInstI<0b000, OPC_SYSTEM, (outs), (ins), "ebreak", "">, + Sched<[]> { let rs1 = 0; let rd = 0; let imm12 = 1; @@ -468,7 +472,8 @@ // This is a de facto standard (as set by GNU binutils) 32-bit unimplemented // instruction (i.e., it should always trap, if your implementation has invalid // instruction traps). -def UNIMP : RVInstI<0b001, OPC_SYSTEM, (outs), (ins), "unimp", ""> { +def UNIMP : RVInstI<0b001, OPC_SYSTEM, (outs), (ins), "unimp", "">, + Sched<[]> { let rs1 = 0; let rd = 0; let imm12 = 0b110000000000; @@ -486,24 +491,24 @@ /// RV64I instructions let Predicates = [IsRV64] in { -def LWU : Load_ri<0b110, "lwu">; -def LD : Load_ri<0b011, "ld">; -def SD : Store_rri<0b011, "sd">; +def LWU : Load_ri<0b110, "lwu">, Sched<[WriteLDWU]>; +def LD : Load_ri<0b011, "ld">, Sched<[WriteLDD]>; +def SD : Store_rri<0b011, "sd">, Sched<[WriteSTD]>; let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in def ADDIW : RVInstI<0b000, OPC_OP_IMM_32, (outs GPR:$rd), (ins GPR:$rs1, simm12:$imm12), - "addiw", "$rd, $rs1, $imm12">; + "addiw", "$rd, $rs1, $imm12">, Sched<[WriteIALU32]>; -def SLLIW : ShiftW_ri<0, 0b001, "slliw">; -def SRLIW : ShiftW_ri<0, 0b101, "srliw">; -def SRAIW : ShiftW_ri<1, 0b101, "sraiw">; +def SLLIW : ShiftW_ri<0, 0b001, "slliw">, Sched<[WriteShift32]>; +def SRLIW : ShiftW_ri<0, 0b101, "srliw">, Sched<[WriteShift32]>; +def SRAIW : ShiftW_ri<1, 0b101, "sraiw">, Sched<[WriteShift32]>; -def ADDW : ALUW_rr<0b0000000, 0b000, "addw">; -def SUBW : ALUW_rr<0b0100000, 0b000, "subw">; -def SLLW : ALUW_rr<0b0000000, 0b001, "sllw">; -def SRLW : ALUW_rr<0b0000000, 0b101, "srlw">; -def SRAW : ALUW_rr<0b0100000, 0b101, "sraw">; +def ADDW : ALUW_rr<0b0000000, 0b000, "addw">, Sched<[WriteIALU32]>; +def SUBW : ALUW_rr<0b0100000, 0b000, "subw">, Sched<[WriteIALU32]>; +def SLLW : ALUW_rr<0b0000000, 0b001, "sllw">, Sched<[WriteIALU32]>; +def SRLW : ALUW_rr<0b0000000, 0b101, "srlw">, Sched<[WriteIALU32]>; +def SRAW : ALUW_rr<0b0100000, 0b101, "sraw">, Sched<[WriteIALU32]>; } // Predicates = [IsRV64] //===----------------------------------------------------------------------===// @@ -511,26 +516,26 @@ //===----------------------------------------------------------------------===// let isBarrier = 1, isReturn = 1, isTerminator = 1 in { -def URET : Priv<"uret", 0b0000000> { +def URET : Priv<"uret", 0b0000000>, Sched<[WriteTrapRet]> { let rd = 0; let rs1 = 0; let rs2 = 0b00010; } -def SRET : Priv<"sret", 0b0001000> { +def SRET : Priv<"sret", 0b0001000>, Sched<[WriteTrapRet]> { let rd = 0; let rs1 = 0; let rs2 = 0b00010; } -def MRET : Priv<"mret", 0b0011000> { +def MRET : Priv<"mret", 0b0011000>, Sched<[WriteTrapRet]> { let rd = 0; let rs1 = 0; let rs2 = 0b00010; } } // isBarrier = 1, isReturn = 1, isTerminator = 1 -def WFI : Priv<"wfi", 0b0001000> { +def WFI : Priv<"wfi", 0b0001000>, Sched<[]> { let rd = 0; let rs1 = 0; let rs2 = 0b00101; @@ -539,7 +544,7 @@ let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in def SFENCE_VMA : RVInstR<0b0001001, 0b000, OPC_SYSTEM, (outs), (ins GPR:$rs1, GPR:$rs2), - "sfence.vma", "$rs1, $rs2"> { + "sfence.vma", "$rs1, $rs2">, Sched<[WriteFence]> { let rd = 0; } @@ -556,22 +561,22 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 32, isCodeGenOnly = 0, isAsmParserOnly = 1 in def PseudoLI : Pseudo<(outs GPR:$rd), (ins ixlenimm_li:$imm), [], - "li", "$rd, $imm">; + "li", "$rd, $imm">, Sched<[]>; -def PseudoLB : PseudoLoad<"lb">; -def PseudoLBU : PseudoLoad<"lbu">; -def PseudoLH : PseudoLoad<"lh">; -def PseudoLHU : PseudoLoad<"lhu">; -def PseudoLW : PseudoLoad<"lw">; +def PseudoLB : PseudoLoad<"lb">, Sched<[]>; +def PseudoLBU : PseudoLoad<"lbu">, Sched<[]>; +def PseudoLH : PseudoLoad<"lh">, Sched<[]>; +def PseudoLHU : PseudoLoad<"lhu">, Sched<[]>; +def PseudoLW : PseudoLoad<"lw">, Sched<[]>; -def PseudoSB : PseudoStore<"sb">; -def PseudoSH : PseudoStore<"sh">; -def PseudoSW : PseudoStore<"sw">; +def PseudoSB : PseudoStore<"sb">, Sched<[]>; +def PseudoSH : PseudoStore<"sh">, Sched<[]>; +def PseudoSW : PseudoStore<"sw">, Sched<[]>; let Predicates = [IsRV64] in { -def PseudoLWU : PseudoLoad<"lwu">; -def PseudoLD : PseudoLoad<"ld">; -def PseudoSD : PseudoStore<"sd">; +def PseudoLWU : PseudoLoad<"lwu">, Sched<[]>; +def PseudoLD : PseudoLoad<"ld">, Sched<[]>; +def PseudoSD : PseudoStore<"sd">, Sched<[]>; } // Predicates = [IsRV64] def : InstAlias<"mv $rd, $rs", (ADDI GPR:$rd, GPR:$rs, 0)>; @@ -812,7 +817,7 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0 in def PseudoAddTPRel : Pseudo<(outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2, tprel_add_symbol:$src), [], - "add", "$rd, $rs1, $rs2, $src">; + "add", "$rd, $rs1, $rs2, $src">, Sched<[]>; /// FrameIndex calculations @@ -851,7 +856,7 @@ (ins cmpty:$lhs, cmpty:$rhs, ixlenimm:$imm, valty:$truev, valty:$falsev), [(set valty:$dst, (riscv_selectcc cmpty:$lhs, cmpty:$rhs, - (XLenVT imm:$imm), valty:$truev, valty:$falsev))]>; + (XLenVT imm:$imm), valty:$truev, valty:$falsev))]>, Sched<[]>; def Select_GPR_Using_CC_GPR : SelectCC_rrirr; @@ -887,12 +892,12 @@ let isBarrier = 1, isBranch = 1, isTerminator = 1 in def PseudoBR : Pseudo<(outs), (ins simm21_lsb0_jal:$imm20), [(br bb:$imm20)]>, - PseudoInstExpansion<(JAL X0, simm21_lsb0_jal:$imm20)>; + PseudoInstExpansion<(JAL X0, simm21_lsb0_jal:$imm20)>, Sched<[WriteJal]>; let isCall = 1, Defs=[X1] in let isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in def PseudoBRIND : Pseudo<(outs), (ins GPR:$rs1, simm12:$imm12), []>, - PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>; + PseudoInstExpansion<(JALR X0, GPR:$rs1, simm12:$imm12)>, Sched<[WriteJmpReg]>; def : Pat<(brind GPR:$rs1), (PseudoBRIND GPR:$rs1, 0)>; def : Pat<(brind (add GPR:$rs1, simm12:$imm12)), @@ -905,7 +910,7 @@ // Define isCodeGenOnly = 0 to support parsing assembly "call" instruction. let isCall = 1, isBarrier = 1, isCodeGenOnly = 0, hasSideEffects = 0, mayStore = 0, mayLoad = 0 in -def PseudoCALLReg : Pseudo<(outs GPR:$rd), (ins call_symbol:$func), []> { +def PseudoCALLReg : Pseudo<(outs GPR:$rd), (ins call_symbol:$func), []>, Sched<[]> { let AsmString = "call\t$rd, $func"; } @@ -916,7 +921,7 @@ // Define AsmString to print "call" when compile with -S flag. // Define isCodeGenOnly = 0 to support parsing assembly "call" instruction. let isCall = 1, Defs = [X1], isCodeGenOnly = 0 in -def PseudoCALL : Pseudo<(outs), (ins call_symbol:$func), []> { +def PseudoCALL : Pseudo<(outs), (ins call_symbol:$func), []>, Sched<[]> { let AsmString = "call\t$func"; } @@ -930,25 +935,28 @@ let isCall = 1, Defs = [X1] in def PseudoCALLIndirect : Pseudo<(outs), (ins GPR:$rs1), [(riscv_call GPR:$rs1)]>, - PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>; + PseudoInstExpansion<(JALR X1, GPR:$rs1, 0)>, + Sched<[WriteJalr]>; let isBarrier = 1, isReturn = 1, isTerminator = 1 in def PseudoRET : Pseudo<(outs), (ins), [(riscv_ret_flag)]>, - PseudoInstExpansion<(JALR X0, X1, 0)>; + PseudoInstExpansion<(JALR X0, X1, 0)>, + Sched<[WriteJalr]>; // PseudoTAIL is a pseudo instruction similar to PseudoCALL and will eventually // expand to auipc and jalr while encoding. // Define AsmString to print "tail" when compile with -S flag. let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2], isCodeGenOnly = 0 in -def PseudoTAIL : Pseudo<(outs), (ins call_symbol:$dst), []> { +def PseudoTAIL : Pseudo<(outs), (ins call_symbol:$dst), []>, Sched<[]> { let AsmString = "tail\t$dst"; } let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [X2] in def PseudoTAILIndirect : Pseudo<(outs), (ins GPRTC:$rs1), [(riscv_tail GPRTC:$rs1)]>, - PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>; + PseudoInstExpansion<(JALR X0, GPR:$rs1, 0)>, + Sched<[WriteJalr]>; def : Pat<(riscv_tail (iPTR tglobaladdr:$dst)), (PseudoTAIL texternalsym:$dst)>; @@ -958,22 +966,22 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0, isAsmParserOnly = 1 in def PseudoLLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], - "lla", "$dst, $src">; + "lla", "$dst, $src">, Sched<[]>; let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0, isAsmParserOnly = 1 in def PseudoLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], - "la", "$dst, $src">; + "la", "$dst, $src">, Sched<[]>; let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0, isAsmParserOnly = 1 in def PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], - "la.tls.ie", "$dst, $src">; + "la.tls.ie", "$dst, $src">, Sched<[]>; let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0, isAsmParserOnly = 1 in def PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [], - "la.tls.gd", "$dst, $src">; + "la.tls.gd", "$dst, $src">, Sched<[]>; /// Loads @@ -1038,9 +1046,9 @@ // Pessimistically assume the stack pointer will be clobbered let Defs = [X2], Uses = [X2] in { def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), - [(callseq_start timm:$amt1, timm:$amt2)]>; + [(callseq_start timm:$amt1, timm:$amt2)]>, Sched<[]>; def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), - [(callseq_end timm:$amt1, timm:$amt2)]>; + [(callseq_end timm:$amt1, timm:$amt2)]>, Sched<[]>; } // Defs = [X2], Uses = [X2] /// RV64 patterns diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoA.td b/llvm/lib/Target/RISCV/RISCVInstrInfoA.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoA.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoA.td @@ -77,31 +77,31 @@ //===----------------------------------------------------------------------===// let Predicates = [HasStdExtA] in { -defm LR_W : LR_r_aq_rl<0b010, "lr.w">; -defm SC_W : AMO_rr_aq_rl<0b00011, 0b010, "sc.w">; -defm AMOSWAP_W : AMO_rr_aq_rl<0b00001, 0b010, "amoswap.w">; -defm AMOADD_W : AMO_rr_aq_rl<0b00000, 0b010, "amoadd.w">; -defm AMOXOR_W : AMO_rr_aq_rl<0b00100, 0b010, "amoxor.w">; -defm AMOAND_W : AMO_rr_aq_rl<0b01100, 0b010, "amoand.w">; -defm AMOOR_W : AMO_rr_aq_rl<0b01000, 0b010, "amoor.w">; -defm AMOMIN_W : AMO_rr_aq_rl<0b10000, 0b010, "amomin.w">; -defm AMOMAX_W : AMO_rr_aq_rl<0b10100, 0b010, "amomax.w">; -defm AMOMINU_W : AMO_rr_aq_rl<0b11000, 0b010, "amominu.w">; -defm AMOMAXU_W : AMO_rr_aq_rl<0b11100, 0b010, "amomaxu.w">; +defm LR_W : LR_r_aq_rl<0b010, "lr.w">, Sched<[WriteAtomicLDW]>; +defm SC_W : AMO_rr_aq_rl<0b00011, 0b010, "sc.w">, Sched<[WriteAtomicSTW]>; +defm AMOSWAP_W : AMO_rr_aq_rl<0b00001, 0b010, "amoswap.w">, Sched<[WriteAtomicW]>; +defm AMOADD_W : AMO_rr_aq_rl<0b00000, 0b010, "amoadd.w">, Sched<[WriteAtomicW]>; +defm AMOXOR_W : AMO_rr_aq_rl<0b00100, 0b010, "amoxor.w">, Sched<[WriteAtomicW]>; +defm AMOAND_W : AMO_rr_aq_rl<0b01100, 0b010, "amoand.w">, Sched<[WriteAtomicW]>; +defm AMOOR_W : AMO_rr_aq_rl<0b01000, 0b010, "amoor.w">, Sched<[WriteAtomicW]>; +defm AMOMIN_W : AMO_rr_aq_rl<0b10000, 0b010, "amomin.w">, Sched<[WriteAtomicW]>; +defm AMOMAX_W : AMO_rr_aq_rl<0b10100, 0b010, "amomax.w">, Sched<[WriteAtomicW]>; +defm AMOMINU_W : AMO_rr_aq_rl<0b11000, 0b010, "amominu.w">, Sched<[WriteAtomicW]>; +defm AMOMAXU_W : AMO_rr_aq_rl<0b11100, 0b010, "amomaxu.w">, Sched<[WriteAtomicW]>; } // Predicates = [HasStdExtA] let Predicates = [HasStdExtA, IsRV64] in { -defm LR_D : LR_r_aq_rl<0b011, "lr.d">; -defm SC_D : AMO_rr_aq_rl<0b00011, 0b011, "sc.d">; -defm AMOSWAP_D : AMO_rr_aq_rl<0b00001, 0b011, "amoswap.d">; -defm AMOADD_D : AMO_rr_aq_rl<0b00000, 0b011, "amoadd.d">; -defm AMOXOR_D : AMO_rr_aq_rl<0b00100, 0b011, "amoxor.d">; -defm AMOAND_D : AMO_rr_aq_rl<0b01100, 0b011, "amoand.d">; -defm AMOOR_D : AMO_rr_aq_rl<0b01000, 0b011, "amoor.d">; -defm AMOMIN_D : AMO_rr_aq_rl<0b10000, 0b011, "amomin.d">; -defm AMOMAX_D : AMO_rr_aq_rl<0b10100, 0b011, "amomax.d">; -defm AMOMINU_D : AMO_rr_aq_rl<0b11000, 0b011, "amominu.d">; -defm AMOMAXU_D : AMO_rr_aq_rl<0b11100, 0b011, "amomaxu.d">; +defm LR_D : LR_r_aq_rl<0b011, "lr.d">, Sched<[WriteAtomicLDD]>; +defm SC_D : AMO_rr_aq_rl<0b00011, 0b011, "sc.d">, Sched<[WriteAtomicSTD]>; +defm AMOSWAP_D : AMO_rr_aq_rl<0b00001, 0b011, "amoswap.d">, Sched<[WriteAtomicDW]>; +defm AMOADD_D : AMO_rr_aq_rl<0b00000, 0b011, "amoadd.d">, Sched<[WriteAtomicDW]>; +defm AMOXOR_D : AMO_rr_aq_rl<0b00100, 0b011, "amoxor.d">, Sched<[WriteAtomicDW]>; +defm AMOAND_D : AMO_rr_aq_rl<0b01100, 0b011, "amoand.d">, Sched<[WriteAtomicDW]>; +defm AMOOR_D : AMO_rr_aq_rl<0b01000, 0b011, "amoor.d">, Sched<[WriteAtomicDW]>; +defm AMOMIN_D : AMO_rr_aq_rl<0b10000, 0b011, "amomin.d">, Sched<[WriteAtomicDW]>; +defm AMOMAX_D : AMO_rr_aq_rl<0b10100, 0b011, "amomax.d">, Sched<[WriteAtomicDW]>; +defm AMOMINU_D : AMO_rr_aq_rl<0b11000, 0b011, "amominu.d">, Sched<[WriteAtomicDW]>; +defm AMOMAXU_D : AMO_rr_aq_rl<0b11100, 0b011, "amomaxu.d">, Sched<[WriteAtomicDW]>; } // Predicates = [HasStdExtA, IsRV64] //===----------------------------------------------------------------------===// @@ -169,7 +169,7 @@ let hasSideEffects = 0; } -def PseudoAtomicLoadNand32 : PseudoAMO; +def PseudoAtomicLoadNand32 : PseudoAMO, Sched<[]>; // Ordering constants must be kept in sync with the AtomicOrdering enum in // AtomicOrdering.h. def : Pat<(atomic_load_nand_32_monotonic GPR:$addr, GPR:$incr), @@ -223,28 +223,28 @@ (AMOInst GPR:$addr, GPR:$incr, GPR:$mask, GPR:$shiftamt, imm:$ordering)>; -def PseudoMaskedAtomicSwap32 : PseudoMaskedAMO; +def PseudoMaskedAtomicSwap32 : PseudoMaskedAMO, Sched<[]>; def : PseudoMaskedAMOPat; -def PseudoMaskedAtomicLoadAdd32 : PseudoMaskedAMO; +def PseudoMaskedAtomicLoadAdd32 : PseudoMaskedAMO, Sched<[]>; def : PseudoMaskedAMOPat; -def PseudoMaskedAtomicLoadSub32 : PseudoMaskedAMO; +def PseudoMaskedAtomicLoadSub32 : PseudoMaskedAMO, Sched<[]>; def : PseudoMaskedAMOPat; -def PseudoMaskedAtomicLoadNand32 : PseudoMaskedAMO; +def PseudoMaskedAtomicLoadNand32 : PseudoMaskedAMO, Sched<[]>; def : PseudoMaskedAMOPat; -def PseudoMaskedAtomicLoadMax32 : PseudoMaskedAMOMinMax; +def PseudoMaskedAtomicLoadMax32 : PseudoMaskedAMOMinMax, Sched<[]>; def : PseudoMaskedAMOMinMaxPat; -def PseudoMaskedAtomicLoadMin32 : PseudoMaskedAMOMinMax; +def PseudoMaskedAtomicLoadMin32 : PseudoMaskedAMOMinMax, Sched<[]>; def : PseudoMaskedAMOMinMaxPat; -def PseudoMaskedAtomicLoadUMax32 : PseudoMaskedAMOUMinUMax; +def PseudoMaskedAtomicLoadUMax32 : PseudoMaskedAMOUMinUMax, Sched<[]>; def : PseudoMaskedAMOPat; -def PseudoMaskedAtomicLoadUMin32 : PseudoMaskedAMOUMinUMax; +def PseudoMaskedAtomicLoadUMin32 : PseudoMaskedAMOUMinUMax, Sched<[]>; def : PseudoMaskedAMOPat; @@ -274,13 +274,14 @@ (CmpXchgInst GPR:$addr, GPR:$cmp, GPR:$new, 7)>; } -def PseudoCmpXchg32 : PseudoCmpXchg; +def PseudoCmpXchg32 : PseudoCmpXchg, Sched<[]>; defm : PseudoCmpXchgPat<"atomic_cmp_swap_32", PseudoCmpXchg32>; def PseudoMaskedCmpXchg32 : Pseudo<(outs GPR:$res, GPR:$scratch), (ins GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, - ixlenimm:$ordering), []> { + ixlenimm:$ordering), []>, + Sched<[]> { let Constraints = "@earlyclobber $res,@earlyclobber $scratch"; let mayLoad = 1; let mayStore = 1; @@ -328,7 +329,7 @@ /// 64-bit pseudo AMOs -def PseudoAtomicLoadNand64 : PseudoAMO; +def PseudoAtomicLoadNand64 : PseudoAMO, Sched<[]>; // Ordering constants must be kept in sync with the AtomicOrdering enum in // AtomicOrdering.h. def : Pat<(atomic_load_nand_64_monotonic GPR:$addr, GPR:$incr), @@ -361,7 +362,7 @@ /// 64-bit compare and exchange -def PseudoCmpXchg64 : PseudoCmpXchg; +def PseudoCmpXchg64 : PseudoCmpXchg, Sched<[]>; defm : PseudoCmpXchgPat<"atomic_cmp_swap_64", PseudoCmpXchg64>; def : Pat<(int_riscv_masked_cmpxchg_i64 diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoC.td b/llvm/lib/Target/RISCV/RISCVInstrInfoC.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoC.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoC.td @@ -282,7 +282,8 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Uses = [X2] in def C_ADDI4SPN : RVInst16CIW<0b000, 0b00, (outs GPRC:$rd), (ins SP:$rs1, uimm10_lsb00nonzero:$imm), - "c.addi4spn", "$rd, $rs1, $imm"> { + "c.addi4spn", "$rd, $rs1, $imm">, + Sched<[WriteIALU]> { bits<5> rs1; let Inst{12-11} = imm{5-4}; let Inst{10-7} = imm{9-6}; @@ -291,13 +292,15 @@ } let Predicates = [HasStdExtC, HasStdExtD] in -def C_FLD : CLoad_ri<0b001, "c.fld", FPR64C, uimm8_lsb000> { +def C_FLD : CLoad_ri<0b001, "c.fld", FPR64C, uimm8_lsb000>, + Sched<[WriteFLD64]> { bits<8> imm; let Inst{12-10} = imm{5-3}; let Inst{6-5} = imm{7-6}; } -def C_LW : CLoad_ri<0b010, "c.lw", GPRC, uimm7_lsb00> { +def C_LW : CLoad_ri<0b010, "c.lw", GPRC, uimm7_lsb00>, + Sched<[WriteLDW]> { bits<7> imm; let Inst{12-10} = imm{5-3}; let Inst{6} = imm{2}; @@ -306,7 +309,8 @@ let DecoderNamespace = "RISCV32Only_", Predicates = [HasStdExtC, HasStdExtF, IsRV32] in -def C_FLW : CLoad_ri<0b011, "c.flw", FPR32C, uimm7_lsb00> { +def C_FLW : CLoad_ri<0b011, "c.flw", FPR32C, uimm7_lsb00>, + Sched<[WriteFLD32]> { bits<7> imm; let Inst{12-10} = imm{5-3}; let Inst{6} = imm{2}; @@ -314,20 +318,23 @@ } let Predicates = [HasStdExtC, IsRV64] in -def C_LD : CLoad_ri<0b011, "c.ld", GPRC, uimm8_lsb000> { +def C_LD : CLoad_ri<0b011, "c.ld", GPRC, uimm8_lsb000>, + Sched<[WriteLDD]> { bits<8> imm; let Inst{12-10} = imm{5-3}; let Inst{6-5} = imm{7-6}; } let Predicates = [HasStdExtC, HasStdExtD] in -def C_FSD : CStore_rri<0b101, "c.fsd", FPR64C, uimm8_lsb000> { +def C_FSD : CStore_rri<0b101, "c.fsd", FPR64C, uimm8_lsb000>, + Sched<[WriteFST64]> { bits<8> imm; let Inst{12-10} = imm{5-3}; let Inst{6-5} = imm{7-6}; } -def C_SW : CStore_rri<0b110, "c.sw", GPRC, uimm7_lsb00> { +def C_SW : CStore_rri<0b110, "c.sw", GPRC, uimm7_lsb00>, + Sched<[WriteSTW]> { bits<7> imm; let Inst{12-10} = imm{5-3}; let Inst{6} = imm{2}; @@ -336,7 +343,8 @@ let DecoderNamespace = "RISCV32Only_", Predicates = [HasStdExtC, HasStdExtF, IsRV32] in -def C_FSW : CStore_rri<0b111, "c.fsw", FPR32C, uimm7_lsb00> { +def C_FSW : CStore_rri<0b111, "c.fsw", FPR32C, uimm7_lsb00>, + Sched<[WriteFST32]> { bits<7> imm; let Inst{12-10} = imm{5-3}; let Inst{6} = imm{2}; @@ -344,14 +352,16 @@ } let Predicates = [HasStdExtC, IsRV64] in -def C_SD : CStore_rri<0b111, "c.sd", GPRC, uimm8_lsb000> { +def C_SD : CStore_rri<0b111, "c.sd", GPRC, uimm8_lsb000>, + Sched<[WriteSTD]> { bits<8> imm; let Inst{12-10} = imm{5-3}; let Inst{6-5} = imm{7-6}; } let rd = 0, imm = 0, hasSideEffects = 0, mayLoad = 0, mayStore = 0 in -def C_NOP : RVInst16CI<0b000, 0b01, (outs), (ins), "c.nop", ""> +def C_NOP : RVInst16CI<0b000, 0b01, (outs), (ins), "c.nop", "">, + Sched<[WriteNop]> { let Inst{6-2} = 0; } @@ -359,7 +369,8 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in def C_ADDI : RVInst16CI<0b000, 0b01, (outs GPRNoX0:$rd_wb), (ins GPRNoX0:$rd, simm6nonzero:$imm), - "c.addi", "$rd, $imm"> { + "c.addi", "$rd, $imm">, + Sched<[WriteIALU]> { let Constraints = "$rd = $rd_wb"; let Inst{6-2} = imm{4-0}; } @@ -367,7 +378,8 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in def C_ADDI_NOP : RVInst16CI<0b000, 0b01, (outs GPRX0:$rd_wb), (ins GPRX0:$rd, immzero:$imm), - "c.addi", "$rd, $imm"> { + "c.addi", "$rd, $imm">, + Sched<[WriteIALU]> { let Constraints = "$rd = $rd_wb"; let Inst{6-2} = 0; let isAsmParserOnly = 1; @@ -377,27 +389,30 @@ DecoderNamespace = "RISCV32Only_", Defs = [X1], Predicates = [HasStdExtC, IsRV32] in def C_JAL : RVInst16CJ<0b001, 0b01, (outs), (ins simm12_lsb0:$offset), - "c.jal", "$offset">; + "c.jal", "$offset">, Sched<[WriteJal]>; let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Predicates = [HasStdExtC, IsRV64] in def C_ADDIW : RVInst16CI<0b001, 0b01, (outs GPRNoX0:$rd_wb), (ins GPRNoX0:$rd, simm6:$imm), - "c.addiw", "$rd, $imm"> { + "c.addiw", "$rd, $imm">, + Sched<[WriteIALU32]> { let Constraints = "$rd = $rd_wb"; let Inst{6-2} = imm{4-0}; } let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in def C_LI : RVInst16CI<0b010, 0b01, (outs GPRNoX0:$rd), (ins simm6:$imm), - "c.li", "$rd, $imm"> { + "c.li", "$rd, $imm">, + Sched<[WriteIALU]> { let Inst{6-2} = imm{4-0}; } let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in def C_ADDI16SP : RVInst16CI<0b011, 0b01, (outs SP:$rd_wb), (ins SP:$rd, simm10_lsb0000nonzero:$imm), - "c.addi16sp", "$rd, $imm"> { + "c.addi16sp", "$rd, $imm">, + Sched<[WriteIALU]> { let Constraints = "$rd = $rd_wb"; let Inst{12} = imm{9}; let Inst{11-7} = 2; @@ -410,78 +425,87 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in def C_LUI : RVInst16CI<0b011, 0b01, (outs GPRNoX0X2:$rd), (ins c_lui_imm:$imm), - "c.lui", "$rd, $imm"> { + "c.lui", "$rd, $imm">, + Sched<[WriteIALU]> { let Inst{6-2} = imm{4-0}; } -def C_SRLI : Shift_right<0b00, "c.srli", GPRC, uimmlog2xlennonzero>; -def C_SRAI : Shift_right<0b01, "c.srai", GPRC, uimmlog2xlennonzero>; +def C_SRLI : Shift_right<0b00, "c.srli", GPRC, uimmlog2xlennonzero>, + Sched<[WriteShift]>; +def C_SRAI : Shift_right<0b01, "c.srai", GPRC, uimmlog2xlennonzero>, + Sched<[WriteShift]>; let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in def C_ANDI : RVInst16CB<0b100, 0b01, (outs GPRC:$rs1_wb), (ins GPRC:$rs1, simm6:$imm), - "c.andi", "$rs1, $imm"> { + "c.andi", "$rs1, $imm">, + Sched<[WriteIALU]> { let Constraints = "$rs1 = $rs1_wb"; let Inst{12} = imm{5}; let Inst{11-10} = 0b10; let Inst{6-2} = imm{4-0}; } -def C_SUB : CS_ALU<0b100011, 0b00, "c.sub", GPRC>; -def C_XOR : CS_ALU<0b100011, 0b01, "c.xor", GPRC>; -def C_OR : CS_ALU<0b100011, 0b10, "c.or" , GPRC>; -def C_AND : CS_ALU<0b100011, 0b11, "c.and", GPRC>; +def C_SUB : CS_ALU<0b100011, 0b00, "c.sub", GPRC>, Sched<[WriteIALU]>; +def C_XOR : CS_ALU<0b100011, 0b01, "c.xor", GPRC>, Sched<[WriteIALU]>; +def C_OR : CS_ALU<0b100011, 0b10, "c.or" , GPRC>, Sched<[WriteIALU]>; +def C_AND : CS_ALU<0b100011, 0b11, "c.and", GPRC>, Sched<[WriteIALU]>; let Predicates = [HasStdExtC, IsRV64] in { -def C_SUBW : CS_ALU<0b100111, 0b00, "c.subw", GPRC>; -def C_ADDW : CS_ALU<0b100111, 0b01, "c.addw", GPRC>; +def C_SUBW : CS_ALU<0b100111, 0b00, "c.subw", GPRC>, Sched<[WriteIALU32]>; +def C_ADDW : CS_ALU<0b100111, 0b01, "c.addw", GPRC>, Sched<[WriteIALU32]>; } let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in def C_J : RVInst16CJ<0b101, 0b01, (outs), (ins simm12_lsb0:$offset), - "c.j", "$offset"> { + "c.j", "$offset">, Sched<[WriteJmp]> { let isBranch = 1; let isTerminator=1; let isBarrier=1; } -def C_BEQZ : Bcz<0b110, "c.beqz", seteq, GPRC>; -def C_BNEZ : Bcz<0b111, "c.bnez", setne, GPRC>; +def C_BEQZ : Bcz<0b110, "c.beqz", seteq, GPRC>, Sched<[WriteJmp]>; +def C_BNEZ : Bcz<0b111, "c.bnez", setne, GPRC>, Sched<[WriteJmp]>; let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in def C_SLLI : RVInst16CI<0b000, 0b10, (outs GPRNoX0:$rd_wb), (ins GPRNoX0:$rd, uimmlog2xlennonzero:$imm), - "c.slli" ,"$rd, $imm"> { + "c.slli" ,"$rd, $imm">, + Sched<[WriteShift]> { let Constraints = "$rd = $rd_wb"; let Inst{6-2} = imm{4-0}; } let Predicates = [HasStdExtC, HasStdExtD] in -def C_FLDSP : CStackLoad<0b001, "c.fldsp", FPR64, uimm9_lsb000> { +def C_FLDSP : CStackLoad<0b001, "c.fldsp", FPR64, uimm9_lsb000>, + Sched<[WriteFLD64]> { let Inst{6-5} = imm{4-3}; let Inst{4-2} = imm{8-6}; } -def C_LWSP : CStackLoad<0b010, "c.lwsp", GPRNoX0, uimm8_lsb00> { +def C_LWSP : CStackLoad<0b010, "c.lwsp", GPRNoX0, uimm8_lsb00>, + Sched<[WriteLDW]> { let Inst{6-4} = imm{4-2}; let Inst{3-2} = imm{7-6}; } let DecoderNamespace = "RISCV32Only_", Predicates = [HasStdExtC, HasStdExtF, IsRV32] in -def C_FLWSP : CStackLoad<0b011, "c.flwsp", FPR32, uimm8_lsb00> { +def C_FLWSP : CStackLoad<0b011, "c.flwsp", FPR32, uimm8_lsb00>, + Sched<[WriteFLD32]> { let Inst{6-4} = imm{4-2}; let Inst{3-2} = imm{7-6}; } let Predicates = [HasStdExtC, IsRV64] in -def C_LDSP : CStackLoad<0b011, "c.ldsp", GPRNoX0, uimm9_lsb000> { +def C_LDSP : CStackLoad<0b011, "c.ldsp", GPRNoX0, uimm9_lsb000>, + Sched<[WriteLDD]> { let Inst{6-5} = imm{4-3}; let Inst{4-2} = imm{8-6}; } let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in def C_JR : RVInst16CR<0b1000, 0b10, (outs), (ins GPRNoX0:$rs1), - "c.jr", "$rs1"> { + "c.jr", "$rs1">, Sched<[WriteJmpReg]> { let isBranch = 1; let isBarrier = 1; let isTerminator = 1; @@ -491,43 +515,50 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in def C_MV : RVInst16CR<0b1000, 0b10, (outs GPRNoX0:$rs1), (ins GPRNoX0:$rs2), - "c.mv", "$rs1, $rs2">; + "c.mv", "$rs1, $rs2">, + Sched<[WriteIALU]>; let rs1 = 0, rs2 = 0, hasSideEffects = 1, mayLoad = 0, mayStore = 0 in -def C_EBREAK : RVInst16CR<0b1001, 0b10, (outs), (ins), "c.ebreak", "">; +def C_EBREAK : RVInst16CR<0b1001, 0b10, (outs), (ins), "c.ebreak", "">, Sched<[]>; let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCall=1, Defs=[X1], rs2 = 0 in def C_JALR : RVInst16CR<0b1001, 0b10, (outs), (ins GPRNoX0:$rs1), - "c.jalr", "$rs1">; + "c.jalr", "$rs1">, Sched<[WriteJalr]>; let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in def C_ADD : RVInst16CR<0b1001, 0b10, (outs GPRNoX0:$rs1_wb), (ins GPRNoX0:$rs1, GPRNoX0:$rs2), - "c.add", "$rs1, $rs2"> { + "c.add", "$rs1, $rs2">, + Sched<[WriteIALU]> { let Constraints = "$rs1 = $rs1_wb"; } let Predicates = [HasStdExtC, HasStdExtD] in -def C_FSDSP : CStackStore<0b101, "c.fsdsp", FPR64, uimm9_lsb000> { +def C_FSDSP : CStackStore<0b101, "c.fsdsp", FPR64, uimm9_lsb000>, + Sched<[WriteFST64]> { let Inst{12-10} = imm{5-3}; let Inst{9-7} = imm{8-6}; } -def C_SWSP : CStackStore<0b110, "c.swsp", GPR, uimm8_lsb00> { +def C_SWSP : CStackStore<0b110, "c.swsp", GPR, uimm8_lsb00>, + Sched<[WriteSTW]> { let Inst{12-9} = imm{5-2}; let Inst{8-7} = imm{7-6}; } let DecoderNamespace = "RISCV32Only_", Predicates = [HasStdExtC, HasStdExtF, IsRV32] in -def C_FSWSP : CStackStore<0b111, "c.fswsp", FPR32, uimm8_lsb00> { +def C_FSWSP : CStackStore<0b111, "c.fswsp", FPR32, uimm8_lsb00>, + Sched<[WriteFST32]> { let Inst{12-9} = imm{5-2}; let Inst{8-7} = imm{7-6}; + } let Predicates = [HasStdExtC, IsRV64] in -def C_SDSP : CStackStore<0b111, "c.sdsp", GPR, uimm9_lsb000> { +def C_SDSP : CStackStore<0b111, "c.sdsp", GPR, uimm9_lsb000>, + Sched<[WriteSTD]> { let Inst{12-10} = imm{5-3}; let Inst{9-7} = imm{8-6}; } @@ -535,7 +566,8 @@ // The all zeros pattern isn't a valid RISC-V instruction. It's used by GNU // binutils as 16-bit instruction known to be unimplemented (i.e., trapping). let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in -def C_UNIMP : RVInst16<(outs), (ins), "c.unimp", "", [], InstFormatOther> { +def C_UNIMP : RVInst16<(outs), (ins), "c.unimp", "", [], InstFormatOther>, + Sched<[]> { let Inst{15-0} = 0; } @@ -551,7 +583,7 @@ let rd = 0 in def C_NOP_HINT : RVInst16CI<0b000, 0b01, (outs), (ins simm6nonzero:$imm), - "c.nop", "$imm"> { + "c.nop", "$imm">, Sched<[WriteNop]> { let Inst{6-2} = imm{4-0}; let DecoderMethod = "decodeRVCInstrSImm"; } @@ -559,7 +591,8 @@ // Just a different syntax for the c.nop hint: c.addi x0, simm6 vs c.nop simm6. def C_ADDI_HINT_X0 : RVInst16CI<0b000, 0b01, (outs GPRX0:$rd_wb), (ins GPRX0:$rd, simm6nonzero:$imm), - "c.addi", "$rd, $imm"> { + "c.addi", "$rd, $imm">, + Sched<[WriteIALU]> { let Constraints = "$rd = $rd_wb"; let Inst{6-2} = imm{4-0}; let isAsmParserOnly = 1; @@ -567,14 +600,16 @@ def C_ADDI_HINT_IMM_ZERO : RVInst16CI<0b000, 0b01, (outs GPRNoX0:$rd_wb), (ins GPRNoX0:$rd, immzero:$imm), - "c.addi", "$rd, $imm"> { + "c.addi", "$rd, $imm">, + Sched<[WriteIALU]> { let Constraints = "$rd = $rd_wb"; let Inst{6-2} = 0; let isAsmParserOnly = 1; } def C_LI_HINT : RVInst16CI<0b010, 0b01, (outs GPRX0:$rd), (ins simm6:$imm), - "c.li", "$rd, $imm"> { + "c.li", "$rd, $imm">, + Sched<[WriteIALU]> { let Inst{6-2} = imm{4-0}; let Inst{11-7} = 0; let DecoderMethod = "decodeRVCInstrRdSImm"; @@ -582,14 +617,15 @@ def C_LUI_HINT : RVInst16CI<0b011, 0b01, (outs GPRX0:$rd), (ins c_lui_imm:$imm), - "c.lui", "$rd, $imm"> { + "c.lui", "$rd, $imm">, + Sched<[WriteIALU]> { let Inst{6-2} = imm{4-0}; let Inst{11-7} = 0; let DecoderMethod = "decodeRVCInstrRdSImm"; } def C_MV_HINT : RVInst16CR<0b1000, 0b10, (outs GPRX0:$rs1), (ins GPRNoX0:$rs2), - "c.mv", "$rs1, $rs2"> + "c.mv", "$rs1, $rs2">, Sched<[WriteIALU]> { let Inst{11-7} = 0; let DecoderMethod = "decodeRVCInstrRdRs2"; @@ -597,7 +633,8 @@ def C_ADD_HINT : RVInst16CR<0b1001, 0b10, (outs GPRX0:$rs1_wb), (ins GPRX0:$rs1, GPRNoX0:$rs2), - "c.add", "$rs1, $rs2"> { + "c.add", "$rs1, $rs2">, + Sched<[WriteIALU]> { let Constraints = "$rs1 = $rs1_wb"; let Inst{11-7} = 0; let DecoderMethod = "decodeRVCInstrRdRs1Rs2"; @@ -605,7 +642,8 @@ def C_SLLI_HINT : RVInst16CI<0b000, 0b10, (outs GPRX0:$rd_wb), (ins GPRX0:$rd, uimmlog2xlennonzero:$imm), - "c.slli" ,"$rd, $imm"> { + "c.slli" ,"$rd, $imm">, + Sched<[WriteShift]> { let Constraints = "$rd = $rd_wb"; let Inst{6-2} = imm{4-0}; let Inst{11-7} = 0; @@ -613,7 +651,8 @@ } def C_SLLI64_HINT : RVInst16CI<0b000, 0b10, (outs GPR:$rd_wb), (ins GPR:$rd), - "c.slli64" ,"$rd"> { + "c.slli64" ,"$rd">, + Sched<[WriteShift]> { let Constraints = "$rd = $rd_wb"; let Inst{6-2} = 0; let Inst{12} = 0; @@ -621,7 +660,8 @@ def C_SRLI64_HINT : RVInst16CI<0b100, 0b01, (outs GPRC:$rd_wb), (ins GPRC:$rd), - "c.srli64", "$rd"> { + "c.srli64", "$rd">, + Sched<[WriteShift]> { let Constraints = "$rd = $rd_wb"; let Inst{6-2} = 0; let Inst{11-10} = 0; @@ -630,7 +670,8 @@ def C_SRAI64_HINT : RVInst16CI<0b100, 0b01, (outs GPRC:$rd_wb), (ins GPRC:$rd), - "c.srai64", "$rd"> { + "c.srai64", "$rd">, + Sched<[WriteShift]> { let Constraints = "$rd = $rd_wb"; let Inst{6-2} = 0; let Inst{11-10} = 1; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoD.td b/llvm/lib/Target/RISCV/RISCVInstrInfoD.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoD.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoD.td @@ -68,7 +68,7 @@ let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in def FLD : RVInstI<0b011, OPC_LOAD_FP, (outs FPR64:$rd), (ins GPR:$rs1, simm12:$imm12), - "fld", "$rd, ${imm12}(${rs1})">; + "fld", "$rd, ${imm12}(${rs1})">, Sched<[WriteFLD64]>; // Operands for stores are in the order srcreg, base, offset rather than // reflecting the order these fields are specified in the instruction @@ -76,99 +76,113 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in def FSD : RVInstS<0b011, OPC_STORE_FP, (outs), (ins FPR64:$rs2, GPR:$rs1, simm12:$imm12), - "fsd", "$rs2, ${imm12}(${rs1})">; + "fsd", "$rs2, ${imm12}(${rs1})">, Sched<[WriteFST64]>; -def FMADD_D : FPFMAD_rrr_frm; +def FMADD_D : FPFMAD_rrr_frm, Sched<[WriteFMulAdd64]>; def : FPFMADDynFrmAlias; -def FMSUB_D : FPFMAD_rrr_frm; +def FMSUB_D : FPFMAD_rrr_frm, Sched<[WriteFMulSub64]>; def : FPFMADDynFrmAlias; -def FNMSUB_D : FPFMAD_rrr_frm; +def FNMSUB_D : FPFMAD_rrr_frm, Sched<[WriteFMulSub64]>; def : FPFMADDynFrmAlias; -def FNMADD_D : FPFMAD_rrr_frm; +def FNMADD_D : FPFMAD_rrr_frm, Sched<[WriteFMulAdd64]>; def : FPFMADDynFrmAlias; -def FADD_D : FPALUD_rr_frm<0b0000001, "fadd.d">; +def FADD_D : FPALUD_rr_frm<0b0000001, "fadd.d">, Sched<[WriteFALU64]>; def : FPALUDDynFrmAlias; -def FSUB_D : FPALUD_rr_frm<0b0000101, "fsub.d">; +def FSUB_D : FPALUD_rr_frm<0b0000101, "fsub.d">, Sched<[WriteFALU64]>; def : FPALUDDynFrmAlias; -def FMUL_D : FPALUD_rr_frm<0b0001001, "fmul.d">; +def FMUL_D : FPALUD_rr_frm<0b0001001, "fmul.d">, Sched<[WriteFALU64]>; def : FPALUDDynFrmAlias; -def FDIV_D : FPALUD_rr_frm<0b0001101, "fdiv.d">; +def FDIV_D : FPALUD_rr_frm<0b0001101, "fdiv.d">, Sched<[WriteFALU64]>; def : FPALUDDynFrmAlias; -def FSQRT_D : FPUnaryOp_r_frm<0b0101101, FPR64, FPR64, "fsqrt.d"> { +def FSQRT_D : FPUnaryOp_r_frm<0b0101101, FPR64, FPR64, "fsqrt.d">, + Sched<[WriteFSqrt32]> { let rs2 = 0b00000; } def : FPUnaryOpDynFrmAlias; -def FSGNJ_D : FPALUD_rr<0b0010001, 0b000, "fsgnj.d">; -def FSGNJN_D : FPALUD_rr<0b0010001, 0b001, "fsgnjn.d">; -def FSGNJX_D : FPALUD_rr<0b0010001, 0b010, "fsgnjx.d">; -def FMIN_D : FPALUD_rr<0b0010101, 0b000, "fmin.d">; -def FMAX_D : FPALUD_rr<0b0010101, 0b001, "fmax.d">; +def FSGNJ_D : FPALUD_rr<0b0010001, 0b000, "fsgnj.d">, Sched<[WriteFALU64]>; +def FSGNJN_D : FPALUD_rr<0b0010001, 0b001, "fsgnjn.d">, Sched<[WriteFALU64]>; +def FSGNJX_D : FPALUD_rr<0b0010001, 0b010, "fsgnjx.d">, Sched<[WriteFALU64]>; +def FMIN_D : FPALUD_rr<0b0010101, 0b000, "fmin.d">, Sched<[WriteFALU64]>; +def FMAX_D : FPALUD_rr<0b0010101, 0b001, "fmax.d">, Sched<[WriteFALU64]>; -def FCVT_S_D : FPUnaryOp_r_frm<0b0100000, FPR32, FPR64, "fcvt.s.d"> { +def FCVT_S_D : FPUnaryOp_r_frm<0b0100000, FPR32, FPR64, "fcvt.s.d">, + Sched<[WriteFCvtF64ToF32]> { let rs2 = 0b00001; } def : FPUnaryOpDynFrmAlias; -def FCVT_D_S : FPUnaryOp_r<0b0100001, 0b000, FPR64, FPR32, "fcvt.d.s"> { +def FCVT_D_S : FPUnaryOp_r<0b0100001, 0b000, FPR64, FPR32, "fcvt.d.s">, + Sched<[WriteFCvtF32ToF64]> { let rs2 = 0b00000; } -def FEQ_D : FPCmpD_rr<0b010, "feq.d">; -def FLT_D : FPCmpD_rr<0b001, "flt.d">; -def FLE_D : FPCmpD_rr<0b000, "fle.d">; +def FEQ_D : FPCmpD_rr<0b010, "feq.d">, Sched<[WriteFCmp64]>; +def FLT_D : FPCmpD_rr<0b001, "flt.d">, Sched<[WriteFCmp64]>; +def FLE_D : FPCmpD_rr<0b000, "fle.d">, Sched<[WriteFCmp64]>; -def FCLASS_D : FPUnaryOp_r<0b1110001, 0b001, GPR, FPR64, "fclass.d"> { +def FCLASS_D : FPUnaryOp_r<0b1110001, 0b001, GPR, FPR64, "fclass.d">, + Sched<[WriteFClass64]> { let rs2 = 0b00000; } -def FCVT_W_D : FPUnaryOp_r_frm<0b1100001, GPR, FPR64, "fcvt.w.d"> { +def FCVT_W_D : FPUnaryOp_r_frm<0b1100001, GPR, FPR64, "fcvt.w.d">, + Sched<[WriteFCvtF64ToI32]> { let rs2 = 0b00000; } def : FPUnaryOpDynFrmAlias; -def FCVT_WU_D : FPUnaryOp_r_frm<0b1100001, GPR, FPR64, "fcvt.wu.d"> { +def FCVT_WU_D : FPUnaryOp_r_frm<0b1100001, GPR, FPR64, "fcvt.wu.d">, + Sched<[WriteFCvtF64ToI32]> { let rs2 = 0b00001; } def : FPUnaryOpDynFrmAlias; -def FCVT_D_W : FPUnaryOp_r<0b1101001, 0b000, FPR64, GPR, "fcvt.d.w"> { +def FCVT_D_W : FPUnaryOp_r<0b1101001, 0b000, FPR64, GPR, "fcvt.d.w">, + Sched<[WriteFCvtI32ToF64]> { let rs2 = 0b00000; } -def FCVT_D_WU : FPUnaryOp_r<0b1101001, 0b000, FPR64, GPR, "fcvt.d.wu"> { +def FCVT_D_WU : FPUnaryOp_r<0b1101001, 0b000, FPR64, GPR, "fcvt.d.wu">, + Sched<[WriteFCvtI32ToF64]> { let rs2 = 0b00001; } } // Predicates = [HasStdExtD] let Predicates = [HasStdExtD, IsRV64] in { -def FCVT_L_D : FPUnaryOp_r_frm<0b1100001, GPR, FPR64, "fcvt.l.d"> { +def FCVT_L_D : FPUnaryOp_r_frm<0b1100001, GPR, FPR64, "fcvt.l.d">, + Sched<[WriteFCvtF64ToI64]> { let rs2 = 0b00010; } def : FPUnaryOpDynFrmAlias; -def FCVT_LU_D : FPUnaryOp_r_frm<0b1100001, GPR, FPR64, "fcvt.lu.d"> { +def FCVT_LU_D : FPUnaryOp_r_frm<0b1100001, GPR, FPR64, "fcvt.lu.d">, + Sched<[WriteFCvtF64ToI64]> { let rs2 = 0b00011; } def : FPUnaryOpDynFrmAlias; -def FMV_X_D : FPUnaryOp_r<0b1110001, 0b000, GPR, FPR64, "fmv.x.d"> { +def FMV_X_D : FPUnaryOp_r<0b1110001, 0b000, GPR, FPR64, "fmv.x.d">, + Sched<[WriteFMovF64ToI64]> { let rs2 = 0b00000; } -def FCVT_D_L : FPUnaryOp_r_frm<0b1101001, FPR64, GPR, "fcvt.d.l"> { +def FCVT_D_L : FPUnaryOp_r_frm<0b1101001, FPR64, GPR, "fcvt.d.l">, + Sched<[WriteFCvtI64ToF64]> { let rs2 = 0b00010; } def : FPUnaryOpDynFrmAlias; -def FCVT_D_LU : FPUnaryOp_r_frm<0b1101001, FPR64, GPR, "fcvt.d.lu"> { +def FCVT_D_LU : FPUnaryOp_r_frm<0b1101001, FPR64, GPR, "fcvt.d.lu">, + Sched<[WriteFCvtI64ToF64]> { let rs2 = 0b00011; } def : FPUnaryOpDynFrmAlias; -def FMV_D_X : FPUnaryOp_r<0b1111001, 0b000, FPR64, GPR, "fmv.d.x"> { +def FMV_D_X : FPUnaryOp_r<0b1111001, 0b000, FPR64, GPR, "fmv.d.x">, + Sched<[WriteFMovI64ToF64]> { let rs2 = 0b00000; } } // Predicates = [HasStdExtD, IsRV64] @@ -192,8 +206,8 @@ def : InstAlias<"fge.d $rd, $rs, $rt", (FLE_D GPR:$rd, FPR64:$rt, FPR64:$rs), 0>; -def PseudoFLD : PseudoFloatLoad<"fld", FPR64>; -def PseudoFSD : PseudoStore<"fsd", FPR64>; +def PseudoFLD : PseudoFloatLoad<"fld", FPR64>, Sched<[]>; +def PseudoFSD : PseudoStore<"fsd", FPR64>, Sched<[]>; } // Predicates = [HasStdExtD] //===----------------------------------------------------------------------===// @@ -298,13 +312,15 @@ let usesCustomInserter = 1 in def BuildPairF64Pseudo : Pseudo<(outs FPR64:$dst), (ins GPR:$src1, GPR:$src2), - [(set FPR64:$dst, (RISCVBuildPairF64 GPR:$src1, GPR:$src2))]>; + [(set FPR64:$dst, (RISCVBuildPairF64 GPR:$src1, GPR:$src2))]>, + Sched<[]>; // Moves an FPR to two GPRs. let usesCustomInserter = 1 in def SplitF64Pseudo : Pseudo<(outs GPR:$dst1, GPR:$dst2), (ins FPR64:$src), - [(set GPR:$dst1, GPR:$dst2, (RISCVSplitF64 FPR64:$src))]>; + [(set GPR:$dst1, GPR:$dst2, (RISCVSplitF64 FPR64:$src))]>, + Sched<[]>; } // Predicates = [HasStdExtD] diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoF.td b/llvm/lib/Target/RISCV/RISCVInstrInfoF.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoF.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoF.td @@ -103,7 +103,7 @@ let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in def FLW : RVInstI<0b010, OPC_LOAD_FP, (outs FPR32:$rd), (ins GPR:$rs1, simm12:$imm12), - "flw", "$rd, ${imm12}(${rs1})">; + "flw", "$rd, ${imm12}(${rs1})">, Sched<[WriteFLD32]>; // Operands for stores are in the order srcreg, base, offset rather than // reflecting the order these fields are specified in the instruction @@ -111,91 +111,103 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in def FSW : RVInstS<0b010, OPC_STORE_FP, (outs), (ins FPR32:$rs2, GPR:$rs1, simm12:$imm12), - "fsw", "$rs2, ${imm12}(${rs1})">; + "fsw", "$rs2, ${imm12}(${rs1})">, Sched<[WriteFST32]>; -def FMADD_S : FPFMAS_rrr_frm; +def FMADD_S : FPFMAS_rrr_frm, Sched<[WriteFMulAdd32]>; def : FPFMASDynFrmAlias; -def FMSUB_S : FPFMAS_rrr_frm; +def FMSUB_S : FPFMAS_rrr_frm, Sched<[WriteFMulSub32]>; def : FPFMASDynFrmAlias; -def FNMSUB_S : FPFMAS_rrr_frm; +def FNMSUB_S : FPFMAS_rrr_frm, Sched<[WriteFMulSub32]>; def : FPFMASDynFrmAlias; -def FNMADD_S : FPFMAS_rrr_frm; +def FNMADD_S : FPFMAS_rrr_frm, Sched<[WriteFMulAdd32]>; def : FPFMASDynFrmAlias; -def FADD_S : FPALUS_rr_frm<0b0000000, "fadd.s">; +def FADD_S : FPALUS_rr_frm<0b0000000, "fadd.s">, Sched<[WriteFALU32]>; def : FPALUSDynFrmAlias; -def FSUB_S : FPALUS_rr_frm<0b0000100, "fsub.s">; +def FSUB_S : FPALUS_rr_frm<0b0000100, "fsub.s">, Sched<[WriteFALU32]>; def : FPALUSDynFrmAlias; -def FMUL_S : FPALUS_rr_frm<0b0001000, "fmul.s">; +def FMUL_S : FPALUS_rr_frm<0b0001000, "fmul.s">, Sched<[WriteFMul32]>; def : FPALUSDynFrmAlias; -def FDIV_S : FPALUS_rr_frm<0b0001100, "fdiv.s">; +def FDIV_S : FPALUS_rr_frm<0b0001100, "fdiv.s">, Sched<[WriteFDiv32]>; def : FPALUSDynFrmAlias; -def FSQRT_S : FPUnaryOp_r_frm<0b0101100, FPR32, FPR32, "fsqrt.s"> { +def FSQRT_S : FPUnaryOp_r_frm<0b0101100, FPR32, FPR32, "fsqrt.s">, + Sched<[WriteFSqrt32]> { let rs2 = 0b00000; } def : FPUnaryOpDynFrmAlias; -def FSGNJ_S : FPALUS_rr<0b0010000, 0b000, "fsgnj.s">; -def FSGNJN_S : FPALUS_rr<0b0010000, 0b001, "fsgnjn.s">; -def FSGNJX_S : FPALUS_rr<0b0010000, 0b010, "fsgnjx.s">; -def FMIN_S : FPALUS_rr<0b0010100, 0b000, "fmin.s">; -def FMAX_S : FPALUS_rr<0b0010100, 0b001, "fmax.s">; +def FSGNJ_S : FPALUS_rr<0b0010000, 0b000, "fsgnj.s">, Sched<[WriteFALU32]>; +def FSGNJN_S : FPALUS_rr<0b0010000, 0b001, "fsgnjn.s">, Sched<[WriteFALU32]>; +def FSGNJX_S : FPALUS_rr<0b0010000, 0b010, "fsgnjx.s">, Sched<[WriteFALU32]>; +def FMIN_S : FPALUS_rr<0b0010100, 0b000, "fmin.s">, Sched<[WriteFALU32]>; +def FMAX_S : FPALUS_rr<0b0010100, 0b001, "fmax.s">, Sched<[WriteFALU32]>; -def FCVT_W_S : FPUnaryOp_r_frm<0b1100000, GPR, FPR32, "fcvt.w.s"> { +def FCVT_W_S : FPUnaryOp_r_frm<0b1100000, GPR, FPR32, "fcvt.w.s">, + Sched<[WriteFCvtF32ToI32]> { let rs2 = 0b00000; } def : FPUnaryOpDynFrmAlias; -def FCVT_WU_S : FPUnaryOp_r_frm<0b1100000, GPR, FPR32, "fcvt.wu.s"> { +def FCVT_WU_S : FPUnaryOp_r_frm<0b1100000, GPR, FPR32, "fcvt.wu.s">, + Sched<[WriteFCvtF32ToI32]> { let rs2 = 0b00001; } def : FPUnaryOpDynFrmAlias; -def FMV_X_W : FPUnaryOp_r<0b1110000, 0b000, GPR, FPR32, "fmv.x.w"> { +def FMV_X_W : FPUnaryOp_r<0b1110000, 0b000, GPR, FPR32, "fmv.x.w">, + Sched<[WriteFMovF32ToI32]> { let rs2 = 0b00000; } -def FEQ_S : FPCmpS_rr<0b010, "feq.s">; -def FLT_S : FPCmpS_rr<0b001, "flt.s">; -def FLE_S : FPCmpS_rr<0b000, "fle.s">; +def FEQ_S : FPCmpS_rr<0b010, "feq.s">, Sched<[WriteFCmp32]>; +def FLT_S : FPCmpS_rr<0b001, "flt.s">, Sched<[WriteFCmp32]>; +def FLE_S : FPCmpS_rr<0b000, "fle.s">, Sched<[WriteFCmp32]>; -def FCLASS_S : FPUnaryOp_r<0b1110000, 0b001, GPR, FPR32, "fclass.s"> { +def FCLASS_S : FPUnaryOp_r<0b1110000, 0b001, GPR, FPR32, "fclass.s">, + Sched<[WriteFClass32]> { let rs2 = 0b00000; } -def FCVT_S_W : FPUnaryOp_r_frm<0b1101000, FPR32, GPR, "fcvt.s.w"> { +def FCVT_S_W : FPUnaryOp_r_frm<0b1101000, FPR32, GPR, "fcvt.s.w">, + Sched<[WriteFCvtI32ToF32]> { let rs2 = 0b00000; } def : FPUnaryOpDynFrmAlias; -def FCVT_S_WU : FPUnaryOp_r_frm<0b1101000, FPR32, GPR, "fcvt.s.wu"> { +def FCVT_S_WU : FPUnaryOp_r_frm<0b1101000, FPR32, GPR, "fcvt.s.wu">, + Sched<[WriteFCvtI32ToF32]> { let rs2 = 0b00001; } def : FPUnaryOpDynFrmAlias; -def FMV_W_X : FPUnaryOp_r<0b1111000, 0b000, FPR32, GPR, "fmv.w.x"> { +def FMV_W_X : FPUnaryOp_r<0b1111000, 0b000, FPR32, GPR, "fmv.w.x">, + Sched<[WriteFMovI32ToF32]> { let rs2 = 0b00000; } } // Predicates = [HasStdExtF] let Predicates = [HasStdExtF, IsRV64] in { -def FCVT_L_S : FPUnaryOp_r_frm<0b1100000, GPR, FPR32, "fcvt.l.s"> { +def FCVT_L_S : FPUnaryOp_r_frm<0b1100000, GPR, FPR32, "fcvt.l.s">, + Sched<[WriteFCvtF32ToI64]> { let rs2 = 0b00010; } def : FPUnaryOpDynFrmAlias; -def FCVT_LU_S : FPUnaryOp_r_frm<0b1100000, GPR, FPR32, "fcvt.lu.s"> { +def FCVT_LU_S : FPUnaryOp_r_frm<0b1100000, GPR, FPR32, "fcvt.lu.s">, + Sched<[WriteFCvtF32ToI64]> { let rs2 = 0b00011; } def : FPUnaryOpDynFrmAlias; -def FCVT_S_L : FPUnaryOp_r_frm<0b1101000, FPR32, GPR, "fcvt.s.l"> { +def FCVT_S_L : FPUnaryOp_r_frm<0b1101000, FPR32, GPR, "fcvt.s.l">, + Sched<[WriteFCvtI64ToF32]> { let rs2 = 0b00010; } def : FPUnaryOpDynFrmAlias; -def FCVT_S_LU : FPUnaryOp_r_frm<0b1101000, FPR32, GPR, "fcvt.s.lu"> { +def FCVT_S_LU : FPUnaryOp_r_frm<0b1101000, FPR32, GPR, "fcvt.s.lu">, + Sched<[WriteFCvtI64ToF32]> { let rs2 = 0b00011; } def : FPUnaryOpDynFrmAlias; @@ -250,8 +262,8 @@ def : MnemonicAlias<"fmv.s.x", "fmv.w.x">; def : MnemonicAlias<"fmv.x.s", "fmv.x.w">; -def PseudoFLW : PseudoFloatLoad<"flw", FPR32>; -def PseudoFSW : PseudoStore<"fsw", FPR32>; +def PseudoFLW : PseudoFloatLoad<"flw", FPR32>, Sched<[]>; +def PseudoFSW : PseudoStore<"fsw", FPR32>, Sched<[]>; } // Predicates = [HasStdExtF] //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoM.td b/llvm/lib/Target/RISCV/RISCVInstrInfoM.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoM.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoM.td @@ -24,22 +24,22 @@ //===----------------------------------------------------------------------===// let Predicates = [HasStdExtM] in { -def MUL : ALU_rr<0b0000001, 0b000, "mul">; -def MULH : ALU_rr<0b0000001, 0b001, "mulh">; -def MULHSU : ALU_rr<0b0000001, 0b010, "mulhsu">; -def MULHU : ALU_rr<0b0000001, 0b011, "mulhu">; -def DIV : ALU_rr<0b0000001, 0b100, "div">; -def DIVU : ALU_rr<0b0000001, 0b101, "divu">; -def REM : ALU_rr<0b0000001, 0b110, "rem">; -def REMU : ALU_rr<0b0000001, 0b111, "remu">; +def MUL : ALU_rr<0b0000001, 0b000, "mul">, Sched<[WriteIMul]>; +def MULH : ALU_rr<0b0000001, 0b001, "mulh">, Sched<[WriteIMul]>; +def MULHSU : ALU_rr<0b0000001, 0b010, "mulhsu">, Sched<[WriteIMul]>; +def MULHU : ALU_rr<0b0000001, 0b011, "mulhu">, Sched<[WriteIMul]>; +def DIV : ALU_rr<0b0000001, 0b100, "div">, Sched<[WriteIDiv]>; +def DIVU : ALU_rr<0b0000001, 0b101, "divu">, Sched<[WriteIDiv]>; +def REM : ALU_rr<0b0000001, 0b110, "rem">, Sched<[WriteIDiv]>; +def REMU : ALU_rr<0b0000001, 0b111, "remu">, Sched<[WriteIDiv]>; } // Predicates = [HasStdExtM] let Predicates = [HasStdExtM, IsRV64] in { -def MULW : ALUW_rr<0b0000001, 0b000, "mulw">; -def DIVW : ALUW_rr<0b0000001, 0b100, "divw">; -def DIVUW : ALUW_rr<0b0000001, 0b101, "divuw">; -def REMW : ALUW_rr<0b0000001, 0b110, "remw">; -def REMUW : ALUW_rr<0b0000001, 0b111, "remuw">; +def MULW : ALUW_rr<0b0000001, 0b000, "mulw">, Sched<[WriteIMul32]>; +def DIVW : ALUW_rr<0b0000001, 0b100, "divw">, Sched<[WriteIDiv32]>; +def DIVUW : ALUW_rr<0b0000001, 0b101, "divuw">, Sched<[WriteIDiv32]>; +def REMW : ALUW_rr<0b0000001, 0b110, "remw">, Sched<[WriteIDiv32]>; +def REMUW : ALUW_rr<0b0000001, 0b111, "remuw">, Sched<[WriteIDiv32]>; } // Predicates = [HasStdExtM, IsRV64] //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/RISCV/RISCVSchedRocket32.td b/llvm/lib/Target/RISCV/RISCVSchedRocket32.td new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/RISCV/RISCVSchedRocket32.td @@ -0,0 +1,163 @@ +//==- RISCVSchedRocket32.td - Rocket Scheduling Definitions -*- tablegen -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// ===---------------------------------------------------------------------===// +// The following definitions describe the simpler per-operand machine model. +// This works with MachineScheduler. See MCSchedule.h for details. + +// Rocket machine model for scheduling and other instruction cost heuristics. +def Rocket32Model : SchedMachineModel { + let MicroOpBufferSize = 0; // Explicitly set to zero since Rocket is in-order. + let IssueWidth = 1; // 1 micro-ops are dispatched per cycle. + let LoadLatency = 3; + let MispredictPenalty = 3; + let CompleteModel = 1; +} + +//===----------------------------------------------------------------------===// +// Define each kind of processor resource and number available. + +// Modeling each pipeline as a ProcResource using the BufferSize = 0 since +// Rocket is in-order. + +let BufferSize = 0 in { +def Rocket32UnitALU : ProcResource<1>; // Int ALU +def Rocket32UnitIMul : ProcResource<1>; // Int Multiply +def Rocket32UnitMem : ProcResource<1>; // Load/Store +def Rocket32UnitB : ProcResource<1>; // Branch + +def Rocket32UnitFPALU : ProcResource<1>; // FP ALU +} + +let BufferSize = 1 in { +def Rocket32UnitIDiv : ProcResource<1>; // Int Division +def Rocket32UnitFPDivSqrt : ProcResource<1>; // FP Divide/Sqrt' +} + +//===----------------------------------------------------------------------===// +// Subtarget-specific SchedWrite types which both map the ProcResources and +// set the latency. + +let SchedModel = Rocket32Model in { + +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; + +def : WriteRes; + +def : WriteRes; +def : WriteRes; + +// Multiplies on Rocket differ by implementation; placeholder until +// we can determine how to read from command line +def : WriteRes { let Latency = 4; } + +// 32-bit divides have worse case latency of 34 cycle +def : WriteRes { + let Latency = 34; + let ResourceCycles = [34]; +} + +// Memory + +// What is the correct latency to model for fence instructions? +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; + +let Latency = 3 in { +def : WriteRes; +def : WriteRes; +def : WriteRes; +} + +let Latency = 2 in { +def : WriteRes; +def : WriteRes; +def : WriteRes; + +def : WriteRes; +def : WriteRes; +} + +def : WriteRes; + +// Most FP single precision operations are 4 cycles +def : WriteRes { let Latency = 4; } + +// Most FP double precision operations are 6 cycles +def : WriteRes { let Latency = 6; } + +let Latency = 2 in { +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; + +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +} + +let Latency = 5 in { +def : WriteRes; +def : WriteRes; +def : WriteRes; +} + +let Latency = 7 in { +def : WriteRes; +def : WriteRes; +def : WriteRes; +} + +// FP Divide unit on Rocket is not pipelined, so set resource cycles to latency +let Latency = 20, ResourceCycles = [20] in { +def : WriteRes; +def : WriteRes; +} + +// FP Sqrt unit on Rocket is not pipelined, so set resource cycles to latency +def : WriteRes { let Latency = 20; + let ResourceCycles = [20];} +def : WriteRes { let Latency = 25; + let ResourceCycles = [25];} + +def : WriteRes; + +def : InstRW<[WriteIALU], (instrs COPY)>; + +let Unsupported = 1 in { +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +} +} diff --git a/llvm/lib/Target/RISCV/RISCVSchedRocket64.td b/llvm/lib/Target/RISCV/RISCVSchedRocket64.td new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/RISCV/RISCVSchedRocket64.td @@ -0,0 +1,164 @@ +//==- RISCVSchedRocket64.td - Rocket Scheduling Definitions -*- tablegen -*-=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// ===---------------------------------------------------------------------===// +// The following definitions describe the simpler per-operand machine model. +// This works with MachineScheduler. See MCSchedule.h for details. + +// Rocket machine model for scheduling and other instruction cost heuristics. +def Rocket64Model : SchedMachineModel { + let MicroOpBufferSize = 0; // Explicitly set to zero since Rocket is in-order. + let IssueWidth = 1; // 1 micro-ops are dispatched per cycle. + let LoadLatency = 3; + let MispredictPenalty = 3; +} + +//===----------------------------------------------------------------------===// +// Define each kind of processor resource and number available. + +// Modeling each pipeline as a ProcResource using the BufferSize = 0 since +// Rocket is in-order. + +let BufferSize = 0 in { +def Rocket64UnitALU : ProcResource<1>; // Int ALU +def Rocket64UnitIMul : ProcResource<1>; // Int Multiply +def Rocket64UnitMem : ProcResource<1>; // Load/Store +def Rocket64UnitB : ProcResource<1>; // Branch + +def Rocket64UnitFPALU : ProcResource<1>; // FP ALU +} + +let BufferSize = 1 in { +def Rocket64UnitIDiv : ProcResource<1>; // Int Division +def Rocket64UnitFPDivSqrt : ProcResource<1>; // FP Divide/Sqrt +} + +//===----------------------------------------------------------------------===// +// Subtarget-specific SchedWrite types which both map the ProcResources and +// set the latency. + +let SchedModel = Rocket64Model in { + +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; + +def : WriteRes; + +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; + +let Latency = 4 in { +def : WriteRes; +def : WriteRes; +} + +// Integer divide varies based on operand magnitude and sign; worse case latency is 34. +def : WriteRes { + let Latency = 34; + let ResourceCycles = [34]; +} +def : WriteRes { + let Latency = 33; + let ResourceCycles = [33]; +} + +// Memory + +// What is the correct latency to model for fence instructions? +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; + +let Latency = 3 in { +def : WriteRes; +def : WriteRes; +def : WriteRes; +} + +let Latency = 2 in { +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; + +def : WriteRes; +def : WriteRes; + +def : WriteRes; +def : WriteRes; +} + +def : WriteRes; +def : WriteRes; + +// Most FP single precision operations are 4 cycles +def : WriteRes { let Latency = 4; } + +// Most FP double precision operations are 6 cycles +def : WriteRes { let Latency = 6; } + +// Conversion instructions +let Latency = 2 in { +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; + +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +def : WriteRes; +} + +let Latency = 5 in { +def : WriteRes; +def : WriteRes; +def : WriteRes; +} + +let Latency = 7 in { +def : WriteRes; +def : WriteRes; +def : WriteRes; +} + +// FP Divide unit on Rocket is not pipelined, so set resource cycles to latency +let Latency = 20, ResourceCycles = [20] in { +def : WriteRes; +def : WriteRes; +} + +// FP Sqrt unit on Rocket is not pipelined, so set resource cycles to latency +def : WriteRes { let Latency = 20; + let ResourceCycles = [20]; } +def : WriteRes { let Latency = 25; + let ResourceCycles = [25]; } + +def : WriteRes; + +def : InstRW<[WriteIALU], (instrs COPY)>; +} diff --git a/llvm/lib/Target/RISCV/RISCVSchedule.td b/llvm/lib/Target/RISCV/RISCVSchedule.td new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/RISCV/RISCVSchedule.td @@ -0,0 +1,86 @@ +//===-- RISCVSchedule.td - RISCV Scheduling Definitions -------*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +def WriteIALU : SchedWrite; // 32 or 64-bit integer ALU operations +def WriteIALU32 : SchedWrite; // 32-bit integer ALU operations on RV64I +def WriteShift32 : SchedWrite; // 32-bit shift operations on RV64Ix +def WriteShift : SchedWrite; // 32 or 64-bit shift operations +def WriteIDiv : SchedWrite; // 32-bit or 64-bit divide and remainder +def WriteIDiv32 : SchedWrite; // 32-bit divide and remainder on RV64I +def WriteIMul : SchedWrite; // 32-bit or 64-bit multiply +def WriteIMul32 : SchedWrite; // 32-bit multiply on RV64I +def WriteJmp : SchedWrite; // Jump +def WriteJal : SchedWrite; // Jump and link +def WriteJalr : SchedWrite; // Jump and link register +def WriteJmpReg : SchedWrite; // Jump register +def WriteFence : SchedWrite; // Fence instructions +def WriteNop : SchedWrite; +def WriteLDB : SchedWrite; // Load byte +def WriteLDW : SchedWrite; // Load word +def WriteLDWU : SchedWrite; // Load word unsigned +def WriteLDH : SchedWrite; // Load half-word +def WriteLDD : SchedWrite; // Load double-word +def WriteCSR : SchedWrite; // CSR instructions +def WriteSTB : SchedWrite; // Store byte +def WriteSTW : SchedWrite; // Store word +def WriteSTH : SchedWrite; // Store half-word +def WriteSTD : SchedWrite; // Store double-word +def WriteAtomicW : SchedWrite; //Atomic memory operation word size +def WriteAtomicDW : SchedWrite; //Atomic memory operation double word size +def WriteAtomicLDW : SchedWrite; // Atomic load word +def WriteAtomicLDD : SchedWrite; // Atomic load double word +def WriteAtomicSTW : SchedWrite; // Atomic store word +def WriteAtomicSTD : SchedWrite; // Atomic store double word +def WriteTrapRet : SchedWrite; // Trap return instructions +def WriteFALU32 : SchedWrite; // FP 32-bit computation +def WriteFALU64 : SchedWrite; // FP 64-bit computation +def WriteFMul32 : SchedWrite; // 32-bit floating point multiply +def WriteFMulAdd32 : SchedWrite; // 32-bit floating point multiply add +def WriteFMulSub32 : SchedWrite; // 32-bit floating point multiply sub +def WriteFMul64 : SchedWrite; // 64-bit floating point multiply +def WriteFMulAdd64 : SchedWrite; // 64-bit floating point multiply add +def WriteFMulSub64 : SchedWrite; // 64-bit floating point multiply sub +def WriteFDiv32 : SchedWrite; // 32-bit floating point divide +def WriteFDiv64 : SchedWrite; // 64-bit floating point divide +def WriteFSqrt32 : SchedWrite; // 32-bit floating point sqrt +def WriteFSqrt64 : SchedWrite; // 64-bit floating point sqrt + +// Integer to float conversions +def WriteFCvtI32ToF32 : SchedWrite; +def WriteFCvtI32ToF64 : SchedWrite; +def WriteFCvtI64ToF32 : SchedWrite; // RV64I only +def WriteFCvtI64ToF64 : SchedWrite; // RV64I only + +//Float to integer conversions +def WriteFCvtF32ToI32 : SchedWrite; +def WriteFCvtF32ToI64 : SchedWrite; // RV64I only +def WriteFCvtF64ToI32 : SchedWrite; +def WriteFCvtF64ToI64 : SchedWrite; // RV64I only + +// Float to float conversions +def WriteFCvtF32ToF64 : SchedWrite; +def WriteFCvtF64ToF32 : SchedWrite; + +def WriteFConv32 : SchedWrite; // 32-bit floating point convert +def WriteFConv64 : SchedWrite; // 64-bit floating point convert +def WriteFClass32 : SchedWrite; // 32-bit floating point classify +def WriteFClass64 : SchedWrite; // 64-bit floating point classify +def WriteFCmp32 : SchedWrite; // 32-bit floating point compare +def WriteFCmp64 : SchedWrite; // 64-bit floating point compare + +def WriteFMovF32ToI32 : SchedWrite; +def WriteFMovI32ToF32 : SchedWrite; +def WriteFMovF64ToI64 : SchedWrite; // RV64I only +def WriteFMovI64ToF64 : SchedWrite; // RV64I only + +def WriteFMov32 : SchedWrite; // 32-bit floating point move +def WriteFMov64 : SchedWrite; // 64-bit floating point move +def WriteFLD32 : SchedWrite; // Floating point sp load +def WriteFLD64 : SchedWrite; // Floating point dp load +def WriteFST32 : SchedWrite; // Floating point sp store +def WriteFST64 : SchedWrite; // Floating point dp store