Always unfold memory operand

Hi,

I am attempting to modify LLVM to generate code for an architecture which is nearly identical to X86-64, but with a few minor differences.

In particular, “call” must always have a register operand, and cannot have a memory operand. Any ideas on how I can express this rule?

Thanks,

  • David

Just get rid of the pattern for matching the CALL64m instruction, or
make it require a target feature your target doesn't have.

-Eli

Hi Eli,

I have tried this, but the resulting tool-chain was broken.

There are only two references to “CALL64m”: the definition in X86Instr64bit.td, and an entry in X86InstrInfo.cpp.
After commenting both out, compilation of a large application fails with:

llc: ScheduleDAG.cpp:462: void llvm::ScheduleDAGTopologicalSort::InitDAGTopologicalSorting(): Assertion `Node2Index[SU->NodeNum] > Node2Index[I->getSUnit()->NodeNum] && “Wrong topological sorting”’ failed.

bugpoint produced this minimal example which triggers the problem:

define ccc void @ArgsFree() nounwind {
entry:
%0 = load void (i8*)** undef, align 4
call ccc void %0(i8* undef) nounwind
unreachable
}

Any ideas?

  • David

Hi Eli,
I have tried this, but the resulting tool-chain was broken.
There are only two references to "CALL64m": the definition in
X86Instr64bit.td, and an entry in X86InstrInfo.cpp.
After commenting both out, compilation of a large application fails with:
llc: ScheduleDAG.cpp:462: void
llvm::ScheduleDAGTopologicalSort::InitDAGTopologicalSorting(): Assertion
`Node2Index[SU->NodeNum] > Node2Index[I->getSUnit()->NodeNum] && "Wrong
topological sorting"' failed.
bugpoint produced this minimal example which triggers the problem:
define ccc void @ArgsFree() nounwind {
entry:
%0 = load void (i8*)** undef, align 4
call ccc void %0(i8* undef) nounwind
unreachable
}
Any ideas?
- David

I'm not really sure... possibly something is expecting to be able to
fold the load into the call inst, and fails.

-Eli

After removing CALL64m, the resulting DAG has a cycle that cannot be scheduled.

I’ve attached a PDF of the DAG before instruction selection (-view-isel-dags), and after instruction select (-view-sched-dags).

Notice how the flag/chain relationships between MOV64rm and CALL64r make it impossible to schedule.

Here’s the code being compiled:

define ccc void @ArgsFree() nounwind {
entry:
%0 = load void (i8*)** undef, align 4
call ccc void %0(i8* undef) nounwind
unreachable
}

Is this a bug in LLVM, or is there something else I need to do than just remove CALL64m?

  • David

BeforeISEL.pdf (6.02 KB)

AfterISEL.pdf (6.9 KB)

After removing CALL64m, the resulting DAG has a cycle that cannot be
scheduled.
I've attached a PDF of the DAG before instruction selection
(-view-isel-dags), and after instruction select (-view-sched-dags).
Notice how the flag/chain relationships between MOV64rm and CALL64r make it
impossible to schedule.
Here's the code being compiled:
define ccc void @ArgsFree() nounwind {
entry:
%0 = load void (i8*)** undef, align 4
call ccc void %0(i8* undef) nounwind
unreachable
}
Is this a bug in LLVM, or is there something else I need to do than just
remove CALL64m?

Ah... I just looked a bit more, and it looks like
X86DAGToDAGISel::PreprocessISelDAG is performing the invalid
transformation (look at the code starting with the "Also try moving
call address load from outside callseq_start" comment). As far as I
can tell, the issue is impossible to trigger without disabling
CALL64m, though.

-Eli