Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1808,6 +1808,20 @@ bool HexagonInstrInfo::isPredicable(const MachineInstr &MI) const {
return true;
}

bool HexagonInstrInfo::isAssociativeAndCommutative(const MachineInstr &Inst,
bool Invert) const {
if (Invert)
return false;

switch (Inst.getOpcode()) {
// TODO: Add more instructions to be handled by MachineCombiner.
case Hexagon::F2_sfadd:
return Inst.getFlag(MachineInstr::MIFlag::FmReassoc);
default:
return false;
}
}

bool HexagonInstrInfo::isSchedulingBoundary(const MachineInstr &MI,
const MachineBasicBlock *MBB,
const MachineFunction &MF) const {
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/Hexagon/HexagonInstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,9 @@ class HexagonInstrInfo : public HexagonGenInstrInfo {
bool ToBigInstrs = true) const;
void translateInstrsForDup(MachineBasicBlock::instr_iterator MII,
bool ToBigInstrs) const;
bool useMachineCombiner() const override { return true; }
bool isAssociativeAndCommutative(const MachineInstr &Inst,
bool Invert) const override;

// Addressing mode relations.
short changeAddrMode_abs_io(short Opc) const;
Expand Down
11 changes: 11 additions & 0 deletions llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ static cl::opt<bool>
DisableHardwareLoops("disable-hexagon-hwloops", cl::Hidden,
cl::desc("Disable Hardware Loops for Hexagon target"));

static cl::opt<bool> EnableMCR("hexagon-mcr", cl::Hidden, cl::init(true),
cl::desc("Enable the machine combiner pass"));

static cl::opt<bool>
DisableAModeOpt("disable-hexagon-amodeopt", cl::Hidden,
cl::desc("Disable Hexagon Addressing Mode Optimization"));
Expand Down Expand Up @@ -309,6 +312,7 @@ class HexagonPassConfig : public TargetPassConfig {

void addIRPasses() override;
bool addInstSelector() override;
bool addILPOpts() override;
void addPreRegAlloc() override;
void addPostRegAlloc() override;
void addPreSched2() override;
Expand Down Expand Up @@ -393,6 +397,13 @@ bool HexagonPassConfig::addInstSelector() {
return false;
}

bool HexagonPassConfig::addILPOpts() {
if (EnableMCR)
addPass(&MachineCombinerID);

return true;
}

void HexagonPassConfig::addPreRegAlloc() {
if (getOptLevel() != CodeGenOptLevel::None) {
if (EnableCExtOpt)
Expand Down
65 changes: 65 additions & 0 deletions llvm/test/CodeGen/Hexagon/machine-combiner-reassoc.mir
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
# RUN: llc -mtriple=hexagon -hexagon-mcr=true -run-pass=machine-combiner\
# RUN: %s -o - | FileCheck %s --check-prefix=ENABLED
# RUN: llc -mtriple=hexagon -hexagon-mcr=false -run-pass=machine-combiner\
# RUN: %s -o - | FileCheck %s --check-prefix=DISABLED

# Test that demonstrates the machine-combiner pass performing reassociation
# to improve instruction-level parallelism (ILP) by breaking dependency chains.

--- |
define float @test_reassoc_chain(float* nocapture readonly %a) {
ret float 0.0
}
...

---
# Test a longer chain: ((A + B) + C) + D
# Should reassociate to optimize the critical path
# Verify we still have 3 F2_sfadd instructions but in optimized order
# Original chain should be preserved

name: test_reassoc_chain
tracksRegLiveness: true
body: |
bb.0:
liveins: $r0

; ENABLED-LABEL: name: test_reassoc_chain
; ENABLED: liveins: $r0
; ENABLED-NEXT: {{ $}}
; ENABLED-NEXT: [[COPY:%[0-9]+]]:intregs = COPY $r0
; ENABLED-NEXT: [[L2_loadri_io:%[0-9]+]]:intregs = L2_loadri_io [[COPY]], 0
; ENABLED-NEXT: [[L2_loadri_io1:%[0-9]+]]:intregs = L2_loadri_io [[COPY]], 4
; ENABLED-NEXT: [[F2_sfadd:%[0-9]+]]:intregs = nnan ninf nsz arcp contract afn reassoc F2_sfadd killed [[L2_loadri_io1]], killed [[L2_loadri_io]], implicit $usr
; ENABLED-NEXT: [[L2_loadri_io2:%[0-9]+]]:intregs = L2_loadri_io [[COPY]], 8
; ENABLED-NEXT: [[L2_loadri_io3:%[0-9]+]]:intregs = L2_loadri_io [[COPY]], 12
; ENABLED-NEXT: [[F2_sfadd1:%[0-9]+]]:intregs = nnan ninf nsz arcp contract afn reassoc F2_sfadd killed [[L2_loadri_io2]], killed [[L2_loadri_io3]], implicit $usr
; ENABLED-NEXT: [[F2_sfadd2:%[0-9]+]]:intregs = nnan ninf nsz arcp contract afn reassoc F2_sfadd killed [[F2_sfadd]], killed [[F2_sfadd1]], implicit $usr
; ENABLED-NEXT: $r0 = COPY [[F2_sfadd2]]
; ENABLED-NEXT: PS_jmpret $r31, implicit-def dead $pc, implicit $r0
;
; DISABLED-LABEL: name: test_reassoc_chain
; DISABLED: liveins: $r0
; DISABLED-NEXT: {{ $}}
; DISABLED-NEXT: [[COPY:%[0-9]+]]:intregs = COPY $r0
; DISABLED-NEXT: [[L2_loadri_io:%[0-9]+]]:intregs = L2_loadri_io [[COPY]], 0
; DISABLED-NEXT: [[L2_loadri_io1:%[0-9]+]]:intregs = L2_loadri_io [[COPY]], 4
; DISABLED-NEXT: [[F2_sfadd:%[0-9]+]]:intregs = nnan ninf nsz arcp contract afn reassoc F2_sfadd killed [[L2_loadri_io1]], killed [[L2_loadri_io]], implicit $usr
; DISABLED-NEXT: [[L2_loadri_io2:%[0-9]+]]:intregs = L2_loadri_io [[COPY]], 8
; DISABLED-NEXT: [[L2_loadri_io3:%[0-9]+]]:intregs = L2_loadri_io [[COPY]], 12
; DISABLED-NEXT: [[F2_sfadd1:%[0-9]+]]:intregs = nnan ninf nsz arcp contract afn reassoc F2_sfadd killed [[L2_loadri_io2]], killed [[L2_loadri_io3]], implicit $usr
; DISABLED-NEXT: [[F2_sfadd2:%[0-9]+]]:intregs = nnan ninf nsz arcp contract afn reassoc F2_sfadd killed [[F2_sfadd]], killed [[F2_sfadd1]], implicit $usr
; DISABLED-NEXT: $r0 = COPY [[F2_sfadd2]]
; DISABLED-NEXT: PS_jmpret $r31, implicit-def dead $pc, implicit $r0
%0:intregs = COPY $r0
%1:intregs = L2_loadri_io %0:intregs, 0
%2:intregs = L2_loadri_io %0:intregs, 4
%3:intregs = nnan ninf nsz arcp contract afn reassoc F2_sfadd killed %2:intregs, killed %1:intregs, implicit $usr
%4:intregs = L2_loadri_io %0:intregs, 8
%5:intregs = nnan ninf nsz arcp contract afn reassoc F2_sfadd killed %3:intregs, killed %4:intregs, implicit $usr
%6:intregs = L2_loadri_io %0:intregs, 12
%7:intregs = nnan ninf nsz arcp contract afn reassoc F2_sfadd killed %5:intregs, killed %6:intregs, implicit $usr
$r0 = COPY %7:intregs
PS_jmpret $r31, implicit-def dead $pc, implicit $r0
...