diff --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h --- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h +++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h @@ -375,6 +375,13 @@ return MI.isAsCheapAsAMove(); } + /// Return true if we want to do aggressive MachineCSE. + /// + /// By default, aggressive MachineCSE is enabled when optimizing for size. + virtual bool enableAggressiveMachineCSE(const MachineFunction &MF) const { + return MF.getFunction().hasOptSize(); + } + /// Return true if the instruction should be sunk by MachineSink. /// /// MachineSink determines on its own whether the instruction is safe to sink; diff --git a/llvm/lib/CodeGen/MachineCSE.cpp b/llvm/lib/CodeGen/MachineCSE.cpp --- a/llvm/lib/CodeGen/MachineCSE.cpp +++ b/llvm/lib/CodeGen/MachineCSE.cpp @@ -51,6 +51,10 @@ #define DEBUG_TYPE "machine-cse" +static cl::opt EnableAggressiveMachineCSE( + "enable-aggressive-machine-cse", cl::Hidden, cl::init(false), + cl::desc("Enable aggressive machine CSE on the whole function.")); + STATISTIC(NumCoalesces, "Number of copies coalesced"); STATISTIC(NumCSEs, "Number of common subexpression eliminated"); STATISTIC(NumPREs, "Number of partial redundant expression" @@ -431,6 +435,10 @@ /// defined. bool MachineCSE::isProfitableToCSE(Register CSReg, Register Reg, MachineBasicBlock *CSBB, MachineInstr *MI) { + if (EnableAggressiveMachineCSE || + TII->enableAggressiveMachineCSE(*MI->getMF())) + return true; + // FIXME: Heuristics that works around the lack the live range splitting. // If CSReg is used at all uses of Reg, CSE should not increase register diff --git a/llvm/test/CodeGen/RISCV/enable-agressive-machine-cse.mir b/llvm/test/CodeGen/RISCV/enable-agressive-machine-cse.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/enable-agressive-machine-cse.mir @@ -0,0 +1,92 @@ +# RUN: llc -mtriple=riscv64 -x mir -run-pass=machine-cse --enable-aggressive-machine-cse -simplify-mir -verify-machineinstrs < %s \ +# RUN: | FileCheck %s + +--- | + define i1 @foo(i64 %a, i64 %b) { + entry: + %cmp = icmp slt i64 %a, 2 + br i1 %cmp, label %return, label %if.end + + if.end: + switch i64 %b, label %return [ + i64 3, label %bb3 + i64 2, label %bb2 + ] + + bb2: + br label %return + + bb3: + br label %return + + return: + %ret = phi i1 [ false, %bb2 ], [ false, %bb3 ], [ true, %entry ], [ true, %if.end ] + ret i1 %ret + } + +... +--- +name: foo +tracksRegLiveness: true +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + - { id: 3, class: gpr } + - { id: 4, class: gpr } + - { id: 5, class: gpr } + - { id: 6, class: gpr } + - { id: 7, class: gpr } + - { id: 8, class: gpr } + - { id: 9, class: gpr } + - { id: 10, class: gpr } + - { id: 11, class: gpr } +liveins: + - { reg: '$x10', virtual-reg: '%1' } + - { reg: '$x11', virtual-reg: '%2' } +body: | + bb.0.entry: + liveins: $x10, $x11 + + %2:gpr = COPY $x11 + %1:gpr = COPY $x10 + %3:gpr = ADDI $x0, 1 + %4:gpr = ADDI $x0, 2 + BLT %1, killed %4, %bb.5 + PseudoBR %bb.1 + + bb.1.if.end: + ; CHECK-NOT: %5:gpr = ADDI $x0, 1 + ; CHECK: %6:gpr = ADDI $x0, 3 + ; CHECK: BEQ %2, killed %6, %bb.4 + + %5:gpr = ADDI $x0, 1 + %6:gpr = ADDI $x0, 3 + BEQ %2, killed %6, %bb.4 + PseudoBR %bb.2 + + bb.2.if.end: + ; CHECK-NOT: %7:gpr = ADDI $x0, 2 + ; CHECK: BNE %2, %4, %bb.5 + + %7:gpr = ADDI $x0, 2 + BNE %2, killed %7, %bb.5 + PseudoBR %bb.3 + + bb.3.bb2: + %9:gpr = COPY $x0 + %8:gpr = COPY %9 + PseudoBR %bb.5 + + bb.4.bb3: + %11:gpr = COPY $x0 + %10:gpr = COPY %11 + + bb.5.return: + ; CHECK: %0:gpr = PHI %3, %bb.0, %3, %bb.2, %8, %bb.3, %10, %bb.4 + + %0:gpr = PHI %3, %bb.0, %5, %bb.2, %8, %bb.3, %10, %bb.4 + $x10 = COPY %0 + PseudoRET implicit $x10 + +...