aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKrzysztof Parzyszek <kparzysz@codeaurora.org>2016-05-10 16:50:30 +0000
committerKrzysztof Parzyszek <kparzysz@codeaurora.org>2016-05-10 16:50:30 +0000
commita356bb7fa46dc3f62c1136a186dd690f0f0cff6c (patch)
treeb7a1911143f5cdc9696619dfc01b0b89b9152c3b
parentbbac890b532499c8e5b4f5c587ecc7667ddc8293 (diff)
downloadllvm-a356bb7fa46dc3f62c1136a186dd690f0f0cff6c.zip
llvm-a356bb7fa46dc3f62c1136a186dd690f0f0cff6c.tar.gz
llvm-a356bb7fa46dc3f62c1136a186dd690f0f0cff6c.tar.bz2
[ScheduleDAG] Make sure to process all def operands before any use operands
An example from Hexagon where things went wrong: %R0<def> = L2_loadrigp <ga:@fp04> ; load function address J2_callr %R0<kill>, ..., %R0<imp-def> ; call *R0, return value in R0 ScheduleDAGInstrs::buildSchedGraph would visit all instructions going backwards, and in each instruction it would visit all operands in their order on the operand list. In the case of this call, it visited the use of R0 first, then removed it from the set Uses after it visited the def. This caused the DAG to be missing the data dependence edge on R0 between the load and the call. Differential Revision: http://reviews.llvm.org/D20102 llvm-svn: 269076
-rw-r--r--llvm/lib/CodeGen/ScheduleDAGInstrs.cpp33
-rw-r--r--llvm/test/CodeGen/Hexagon/callr-dep-edge.ll20
2 files changed, 45 insertions, 8 deletions
diff --git a/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp b/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp
index 34cebae..282019f 100644
--- a/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp
+++ b/llvm/lib/CodeGen/ScheduleDAGInstrs.cpp
@@ -948,24 +948,41 @@ void ScheduleDAGInstrs::buildSchedGraph(AliasAnalysis *AA,
"Cannot schedule terminators or labels!");
// Add register-based dependencies (data, anti, and output).
+ // For some instructions (calls, returns, inline-asm, etc.) there can
+ // be explicit uses and implicit defs, in which case the use will appear
+ // on the operand list before the def. Do two passes over the operand
+ // list to make sure that defs are processed before any uses.
bool HasVRegDef = false;
for (unsigned j = 0, n = MI->getNumOperands(); j != n; ++j) {
const MachineOperand &MO = MI->getOperand(j);
- if (!MO.isReg()) continue;
+ if (!MO.isReg() || !MO.isDef())
+ continue;
unsigned Reg = MO.getReg();
- if (Reg == 0) continue;
+ if (Reg == 0)
+ continue;
if (TRI->isPhysicalRegister(Reg))
addPhysRegDeps(SU, j);
else {
- if (MO.isDef()) {
- HasVRegDef = true;
- addVRegDefDeps(SU, j);
- }
- else if (MO.readsReg()) // ignore undef operands
- addVRegUseDeps(SU, j);
+ HasVRegDef = true;
+ addVRegDefDeps(SU, j);
}
}
+ // Now process all uses.
+ for (unsigned j = 0, n = MI->getNumOperands(); j != n; ++j) {
+ const MachineOperand &MO = MI->getOperand(j);
+ if (!MO.isReg() || !MO.isUse())
+ continue;
+ unsigned Reg = MO.getReg();
+ if (Reg == 0)
+ continue;
+
+ if (TRI->isPhysicalRegister(Reg))
+ addPhysRegDeps(SU, j);
+ else if (MO.readsReg()) // ignore undef operands
+ addVRegUseDeps(SU, j);
+ }
+
// If we haven't seen any uses in this scheduling region, create a
// dependence edge to ExitSU to model the live-out latency. This is required
// for vreg defs with no in-region use, and prefetches with no vreg def.
diff --git a/llvm/test/CodeGen/Hexagon/callr-dep-edge.ll b/llvm/test/CodeGen/Hexagon/callr-dep-edge.ll
new file mode 100644
index 0000000..d2c6ae4
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/callr-dep-edge.ll
@@ -0,0 +1,20 @@
+; RUN: llc -march=hexagon < %s | FileCheck %s
+; Check that the callr and the load into r0 are not packetized together.
+
+target triple = "hexagon"
+
+@fp = common global i32 (...)* null, align 4
+
+; CHECK: r0 = memw
+; CHECK: {
+; CHECK: callr r0
+
+; Function Attrs: nounwind
+define i32 @foo() #0 {
+entry:
+ %0 = load i32 ()*, i32 ()** bitcast (i32 (...)** @fp to i32 ()**), align 4
+ %call = tail call i32 %0() #0
+ ret i32 %call
+}
+
+attributes #0 = { nounwind }