From 40f1af47601044149102b1597d5f56689661f8a5 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 25 Apr 2022 10:45:48 -0700 Subject: [PATCH] [RISCV] Add isCommutable to ADD/ADDW/MUL/AND/OR/XOR/MIN/MAX/CLMUL Reviewed By: reames Differential Revision: https://reviews.llvm.org/D123970 --- llvm/lib/Target/RISCV/RISCVInstrInfo.td | 46 ++++++++++++------ llvm/lib/Target/RISCV/RISCVInstrInfoM.td | 8 ++-- llvm/lib/Target/RISCV/RISCVInstrInfoZb.td | 14 +++--- llvm/test/CodeGen/RISCV/machine-cse.ll | 78 +++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 26 deletions(-) create mode 100644 llvm/test/CodeGen/RISCV/machine-cse.ll diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td index df603dd..cb28a24 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -513,9 +513,12 @@ class Shift_ri imm11_7, bits<3> funct3, string opcodestr> Sched<[WriteShiftImm, ReadShiftImm]>; let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in -class ALU_rr funct7, bits<3> funct3, string opcodestr> +class ALU_rr funct7, bits<3> funct3, string opcodestr, + bit Commutable = 0> : RVInstR; + opcodestr, "$rd, $rs1, $rs2"> { + let isCommutable = Commutable; +} let hasNoSchedulingInfo = 1, hasSideEffects = 1, mayLoad = 0, mayStore = 0 in @@ -538,9 +541,12 @@ class ShiftW_ri imm11_5, bits<3> funct3, string opcodestr> Sched<[WriteShiftImm32, ReadShiftImm32]>; let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in -class ALUW_rr funct7, bits<3> funct3, string opcodestr> +class ALUW_rr funct7, bits<3> funct3, string opcodestr, + bit Commutable = 0> : RVInstR; + (ins GPR:$rs1, GPR:$rs2), opcodestr, "$rd, $rs1, $rs2"> { + let isCommutable = Commutable; +} let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in class Priv funct7> @@ -613,16 +619,26 @@ def SLLI : Shift_ri<0b00000, 0b001, "slli">; def SRLI : Shift_ri<0b00000, 0b101, "srli">; def SRAI : Shift_ri<0b01000, 0b101, "srai">; -def ADD : ALU_rr<0b0000000, 0b000, "add">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; -def SUB : ALU_rr<0b0100000, 0b000, "sub">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; -def SLL : ALU_rr<0b0000000, 0b001, "sll">, Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; -def SLT : ALU_rr<0b0000000, 0b010, "slt">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; -def SLTU : ALU_rr<0b0000000, 0b011, "sltu">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; -def XOR : ALU_rr<0b0000000, 0b100, "xor">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; -def SRL : ALU_rr<0b0000000, 0b101, "srl">, Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; -def SRA : ALU_rr<0b0100000, 0b101, "sra">, Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; -def OR : ALU_rr<0b0000000, 0b110, "or">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; -def AND : ALU_rr<0b0000000, 0b111, "and">, Sched<[WriteIALU, ReadIALU, ReadIALU]>; +def ADD : ALU_rr<0b0000000, 0b000, "add", /*Commutable*/1>, + Sched<[WriteIALU, ReadIALU, ReadIALU]>; +def SUB : ALU_rr<0b0100000, 0b000, "sub">, + Sched<[WriteIALU, ReadIALU, ReadIALU]>; +def SLL : ALU_rr<0b0000000, 0b001, "sll">, + Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; +def SLT : ALU_rr<0b0000000, 0b010, "slt">, + Sched<[WriteIALU, ReadIALU, ReadIALU]>; +def SLTU : ALU_rr<0b0000000, 0b011, "sltu">, + Sched<[WriteIALU, ReadIALU, ReadIALU]>; +def XOR : ALU_rr<0b0000000, 0b100, "xor", /*Commutable*/1>, + Sched<[WriteIALU, ReadIALU, ReadIALU]>; +def SRL : ALU_rr<0b0000000, 0b101, "srl">, + Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; +def SRA : ALU_rr<0b0100000, 0b101, "sra">, + Sched<[WriteShiftReg, ReadShiftReg, ReadShiftReg]>; +def OR : ALU_rr<0b0000000, 0b110, "or", /*Commutable*/1>, + Sched<[WriteIALU, ReadIALU, ReadIALU]>; +def AND : ALU_rr<0b0000000, 0b111, "and", /*Commutable*/1>, + Sched<[WriteIALU, ReadIALU, ReadIALU]>; let hasSideEffects = 1, mayLoad = 0, mayStore = 0 in { def FENCE : RVInstI<0b000, OPC_MISC_MEM, (outs), @@ -697,7 +713,7 @@ def SLLIW : ShiftW_ri<0b0000000, 0b001, "slliw">; def SRLIW : ShiftW_ri<0b0000000, 0b101, "srliw">; def SRAIW : ShiftW_ri<0b0100000, 0b101, "sraiw">; -def ADDW : ALUW_rr<0b0000000, 0b000, "addw">, +def ADDW : ALUW_rr<0b0000000, 0b000, "addw", /*Commutable*/1>, Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>; def SUBW : ALUW_rr<0b0100000, 0b000, "subw">, Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoM.td b/llvm/lib/Target/RISCV/RISCVInstrInfoM.td index b62e23d..72ba846 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoM.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoM.td @@ -25,13 +25,13 @@ def riscv_remuw : SDNode<"RISCVISD::REMUW", SDT_RISCVIntBinOpW>; //===----------------------------------------------------------------------===// let Predicates = [HasStdExtM] in { -def MUL : ALU_rr<0b0000001, 0b000, "mul">, +def MUL : ALU_rr<0b0000001, 0b000, "mul", /*Commutable*/1>, Sched<[WriteIMul, ReadIMul, ReadIMul]>; -def MULH : ALU_rr<0b0000001, 0b001, "mulh">, +def MULH : ALU_rr<0b0000001, 0b001, "mulh", /*Commutable*/1>, Sched<[WriteIMul, ReadIMul, ReadIMul]>; def MULHSU : ALU_rr<0b0000001, 0b010, "mulhsu">, Sched<[WriteIMul, ReadIMul, ReadIMul]>; -def MULHU : ALU_rr<0b0000001, 0b011, "mulhu">, +def MULHU : ALU_rr<0b0000001, 0b011, "mulhu", /*Commutable*/1>, Sched<[WriteIMul, ReadIMul, ReadIMul]>; def DIV : ALU_rr<0b0000001, 0b100, "div">, Sched<[WriteIDiv, ReadIDiv, ReadIDiv]>; @@ -44,7 +44,7 @@ def REMU : ALU_rr<0b0000001, 0b111, "remu">, } // Predicates = [HasStdExtM] let Predicates = [HasStdExtM, IsRV64] in { -def MULW : ALUW_rr<0b0000001, 0b000, "mulw">, +def MULW : ALUW_rr<0b0000001, 0b000, "mulw", /*Commutable*/1>, Sched<[WriteIMul32, ReadIMul32, ReadIMul32]>; def DIVW : ALUW_rr<0b0000001, 0b100, "divw">, Sched<[WriteIDiv32, ReadIDiv32, ReadIDiv32]>; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td index 247e7d6..88c4a73 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td @@ -525,25 +525,25 @@ def CRC32C_D : RVBUnary<0b0110000, 0b11011, 0b001, OPC_OP_IMM, "crc32c.d">, } // Predicates = [HasStdExtZbr, IsRV64] let Predicates = [HasStdExtZbc] in { -def CLMULR : ALU_rr<0b0000101, 0b010, "clmulr">, +def CLMULR : ALU_rr<0b0000101, 0b010, "clmulr", /*Commutable*/1>, Sched<[WriteCLMUL, ReadCLMUL, ReadCLMUL]>; } // Predicates = [HasStdExtZbc] let Predicates = [HasStdExtZbcOrZbkc] in { -def CLMUL : ALU_rr<0b0000101, 0b001, "clmul">, +def CLMUL : ALU_rr<0b0000101, 0b001, "clmul", /*Commutable*/1>, Sched<[WriteCLMUL, ReadCLMUL, ReadCLMUL]>; -def CLMULH : ALU_rr<0b0000101, 0b011, "clmulh">, +def CLMULH : ALU_rr<0b0000101, 0b011, "clmulh", /*Commutable*/1>, Sched<[WriteCLMUL, ReadCLMUL, ReadCLMUL]>; } // Predicates = [HasStdExtZbcOrZbkc] let Predicates = [HasStdExtZbb] in { -def MIN : ALU_rr<0b0000101, 0b100, "min">, +def MIN : ALU_rr<0b0000101, 0b100, "min", /*Commutable*/1>, Sched<[WriteIALU, ReadIALU, ReadIALU]>; -def MINU : ALU_rr<0b0000101, 0b101, "minu">, +def MINU : ALU_rr<0b0000101, 0b101, "minu", /*Commutable*/1>, Sched<[WriteIALU, ReadIALU, ReadIALU]>; -def MAX : ALU_rr<0b0000101, 0b110, "max">, +def MAX : ALU_rr<0b0000101, 0b110, "max", /*Commutable*/1>, Sched<[WriteIALU, ReadIALU, ReadIALU]>; -def MAXU : ALU_rr<0b0000101, 0b111, "maxu">, +def MAXU : ALU_rr<0b0000101, 0b111, "maxu", /*Commutable*/1>, Sched<[WriteIALU, ReadIALU, ReadIALU]>; } // Predicates = [HasStdExtZbb] diff --git a/llvm/test/CodeGen/RISCV/machine-cse.ll b/llvm/test/CodeGen/RISCV/machine-cse.ll new file mode 100644 index 0000000..3f1cd9d --- /dev/null +++ b/llvm/test/CodeGen/RISCV/machine-cse.ll @@ -0,0 +1,78 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=riscv32 | FileCheck %s --check-prefixes=RV32 +; RUN: llc < %s -mtriple=riscv64 | FileCheck %s --check-prefixes=RV64 + +; Make sure MachineCSE can combine the adds with the operands commuted. + +define void @commute_add_i32(i32 signext %x, i32 signext %y, i32* %p1, i32* %p2, i1 zeroext %cond) { +; RV32-LABEL: commute_add_i32: +; RV32: # %bb.0: +; RV32-NEXT: add a0, a0, a1 +; RV32-NEXT: sw a0, 0(a2) +; RV32-NEXT: beqz a4, .LBB0_2 +; RV32-NEXT: # %bb.1: # %trueblock +; RV32-NEXT: sw a0, 0(a2) +; RV32-NEXT: .LBB0_2: # %falseblock +; RV32-NEXT: ret +; +; RV64-LABEL: commute_add_i32: +; RV64: # %bb.0: +; RV64-NEXT: addw a0, a0, a1 +; RV64-NEXT: sw a0, 0(a2) +; RV64-NEXT: beqz a4, .LBB0_2 +; RV64-NEXT: # %bb.1: # %trueblock +; RV64-NEXT: sw a0, 0(a2) +; RV64-NEXT: .LBB0_2: # %falseblock +; RV64-NEXT: ret + %a = add i32 %x, %y + store i32 %a, i32* %p1 + br i1 %cond, label %trueblock, label %falseblock + +trueblock: + %b = add i32 %y, %x + store i32 %b, i32* %p1 + br label %falseblock + +falseblock: + ret void +} + +define void @commute_add_i64(i64 %x, i64 %y, i64* %p1, i64* %p2, i1 zeroext %cond) { +; RV32-LABEL: commute_add_i64: +; RV32: # %bb.0: +; RV32-NEXT: add a1, a1, a3 +; RV32-NEXT: add a3, a0, a2 +; RV32-NEXT: sltu a0, a3, a0 +; RV32-NEXT: add a0, a1, a0 +; RV32-NEXT: sw a3, 0(a4) +; RV32-NEXT: sw a0, 4(a4) +; RV32-NEXT: beqz a6, .LBB1_2 +; RV32-NEXT: # %bb.1: # %trueblock +; RV32-NEXT: sltu a0, a3, a2 +; RV32-NEXT: add a0, a1, a0 +; RV32-NEXT: sw a3, 0(a4) +; RV32-NEXT: sw a0, 4(a4) +; RV32-NEXT: .LBB1_2: # %falseblock +; RV32-NEXT: ret +; +; RV64-LABEL: commute_add_i64: +; RV64: # %bb.0: +; RV64-NEXT: add a0, a0, a1 +; RV64-NEXT: sd a0, 0(a2) +; RV64-NEXT: beqz a4, .LBB1_2 +; RV64-NEXT: # %bb.1: # %trueblock +; RV64-NEXT: sd a0, 0(a2) +; RV64-NEXT: .LBB1_2: # %falseblock +; RV64-NEXT: ret + %a = add i64 %x, %y + store i64 %a, i64* %p1 + br i1 %cond, label %trueblock, label %falseblock + +trueblock: + %b = add i64 %y, %x + store i64 %b, i64* %p1 + br label %falseblock + +falseblock: + ret void +} -- 2.7.4