Difference between -mattr=+soft-float and -float-abi=soft

Hi,

I’ve run into a case where `llc -mattr=+soft-float` for
"armv7-unknown-linux-androideabi” segfaults, while
`llc -float-abi=soft` does not. Similarly if the
"target-features"="+soft-float” metadata is embedded,
llc segfaults.

I fear I’m missing something rather subtle here, could
someone help me understand the differences?

Cheers,
Moritz

Hi Moritz,

I’ve run into a case where `llc -mattr=+soft-float` for
"armv7-unknown-linux-androideabi” segfaults, while
`llc -float-abi=soft` does not. Similarly if the
"target-features"="+soft-float” metadata is embedded,
llc segfaults.

The float-abi option specifies which registers should be used to pass
floating-point values during function calls. The +soft-float option
tells Clang that no floating-point instructions or registers should be
used, so LLVM will make calls to software routines instead of using
the FPU.

In theory they should both be reasonably well tested so a segfault is
slightly surprising. The only idea I can come up with (without source)
is that you've ended up in an inconsistent state: maybe LLVM thinks it
needs to use VFP registers (float-abi=hard) but can't use VFP
instructions to get data there (+soft-float). That wouldn't end well.

Cheers.

Tim.

Hi Tim,

Ohh, I completely forgot to attach the source. Running this with:

$ llc -O2 -mcpu=generic HeapStackCheck.ll -mattr=+soft-float -o HeapStackCheck.s

results in

0 llc 0x000000010fea65e6 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 37
1 llc 0x000000010fea5b3a llvm::sys::RunSignalHandlers() + 83
2 llc 0x000000010fea69d6 SignalHandler(int) + 191
3 libsystem_platform.dylib 0x00007fffb45acb3a _sigtramp + 26
4 libsystem_platform.dylib 000000000000000000 _sigtramp + 1269118176
5 llc 0x000000010fe15779 llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) + 1029
6 llc 0x000000010fe14ac7 llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) + 1521
7 llc 0x000000010f1b56d4 (anonymous namespace)::ARMDAGToDAGISel::runOnMachineFunction(llvm::MachineFunction&) + 20
8 llc 0x000000010f9b7914 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) + 114
9 llc 0x000000010fb357e6 llvm::FPPassManager::runOnFunction(llvm::Function&) + 294
10 llc 0x000000010fb359a5 llvm::FPPassManager::runOnModule(llvm::Module&) + 49
11 llc 0x000000010fb35ce1 llvm::legacy::PassManagerImpl::run(llvm::Module&) + 587
12 llc 0x000000010ef4b962 compileModule(char**, llvm::LLVMContext&) + 6646
13 llc 0x000000010ef49bae main + 891
14 libdyld.dylib 0x00007fffb439d235 start + 1
15 libdyld.dylib 0x0000000000000007 start + 1271279059
Stack dump:
0. Program arguments: llc -O2 -mcpu=generic HeapStackCheck.ll -mattr=+soft-float -o HeapStackCheck.s
1. Running pass 'Function Pass Manager' on module 'rts/HeapStackCheck.ll'.
2. Running pass 'ARM Instruction Selection' on function '@stg_gc_f1'
[1] 85435 segmentation fault llc -O2 -mcpu=generic HeapStackCheck.ll -mattr=+soft-float -o

$ llc -O2 -mcpu=generic rts/HeapStackCheck.ll -float-abi=soft -o rts/HeapStackCheck.s

will succeed however.

Given your explanation, this might be due to the fact how the `ghccc` tries to pass
everything is registers. And which is why this falls apart when float registers are
used.

Maybe the lesson here is that a few more adjustments in GHC are needed to not emit
code using float registers if we use soft float.

I still don’t understand why `-float-abi=soft` would compile then. Maybe it simply has
no effect with `ghccc` then?

Cheers,
Moritz

HeapStackCheck.ll (90.1 KB)

That's certainly true. What float-abi does is specify the CC if it's
omitted from the function. If it's explicitly ghccc then it already
has an ABI.

Cheers.

Tim.