aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/MachineSink.cpp
diff options
context:
space:
mode:
authorPhilip Reames <preames@rivosinc.com>2024-11-25 18:59:31 -0800
committerGitHub <noreply@github.com>2024-11-25 18:59:31 -0800
commit6657d4bd70523e6852f07f64711fb15bdf7b347a (patch)
treeda532ac21c00d6beeeb76870d4bf7eaf64cedb7c /llvm/lib/CodeGen/MachineSink.cpp
parent6633916ef5ab17bae9b2214a9e3327295ce56b5a (diff)
downloadllvm-6657d4bd70523e6852f07f64711fb15bdf7b347a.zip
llvm-6657d4bd70523e6852f07f64711fb15bdf7b347a.tar.gz
llvm-6657d4bd70523e6852f07f64711fb15bdf7b347a.tar.bz2
[TTI][RISCV] Unconditionally break critical edges to sink ADDI (#108889)
This looks like a rather weird change, so let me explain why this isn't as unreasonable as it looks. Let's start with the problem it's solving. ``` define signext i32 @overlap_live_ranges(ptr %arg, i32 signext %arg1) { bb: %i = icmp eq i32 %arg1, 1 br i1 %i, label %bb2, label %bb5 bb2: ; preds = %bb %i3 = getelementptr inbounds nuw i8, ptr %arg, i64 4 %i4 = load i32, ptr %i3, align 4 br label %bb5 bb5: ; preds = %bb2, %bb %i6 = phi i32 [ %i4, %bb2 ], [ 13, %bb ] ret i32 %i6 } ``` Right now, we codegen this as: ``` li a3, 1 li a2, 13 bne a1, a3, .LBB0_2 lw a2, 4(a0) .LBB0_2: mv a0, a2 ret ``` In this example, we have two values which must be assigned to a0 per the ABI (%arg, and the return value). SelectionDAG ensures that all values used in a successor phi are defined before exit the predecessor block. This creates an ADDI to materialize the immediate in the entry block. Currently, this ADDI is not sunk into the tail block because we'd have to split a critical edges to do so. Note that if our immediate was anything large enough to require two instructions we *would* split this critical edge. Looking at other targets, we notice that they don't seem to have this problem. They perform the sinking, and tail duplication that we don't. Why? Well, it turns out for AArch64 that this is entirely an accident of the existance of the gpr32all register class. The immediate is materialized into the gpr32 class, and then copied into the gpr32all register class. The existance of that copy puts us right back into the two instruction case noted above. This change essentially just bypasses this emergent behavior aspect of the aarch64 behavior, and implements the same "always sink immediates" behavior for RISCV as well.
Diffstat (limited to 'llvm/lib/CodeGen/MachineSink.cpp')
-rw-r--r--llvm/lib/CodeGen/MachineSink.cpp4
1 files changed, 3 insertions, 1 deletions
diff --git a/llvm/lib/CodeGen/MachineSink.cpp b/llvm/lib/CodeGen/MachineSink.cpp
index 0def107..7d0bedab 100644
--- a/llvm/lib/CodeGen/MachineSink.cpp
+++ b/llvm/lib/CodeGen/MachineSink.cpp
@@ -958,7 +958,9 @@ bool MachineSinking::isWorthBreakingCriticalEdge(
}
}
- return false;
+ // Let the target decide if it's worth breaking this
+ // critical edge for a "cheap" instruction.
+ return TII->shouldBreakCriticalEdgeToSink(MI);
}
bool MachineSinking::isLegalToBreakCriticalEdge(MachineInstr &MI,