Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

__float128 crashes the compiler / optimizer #9489

Open Quuxplusone opened 13 years ago

Quuxplusone commented 13 years ago
Bugzilla Link PR9126
Status NEW
Importance P normal
Reported by larrybartholdi@yahoo.com
Reported on 2011-02-02 13:29:42 -0800
Last modified on 2011-09-26 08:03:49 -0700
Version trunk
Hardware PC Linux
CC anton@korobeynikov.info, efriedma@quicinc.com, llvm-bugs@lists.llvm.org, scott+llvm+bugzilla@pakin.org
Fixed by commit(s)
Attachments dl.diff (1482 bytes, text/plain)
Blocks
Blocked by
See also
I've heard about llvm only 10 minutes ago, and tried something on the website's
"online compiler" 5 minutes ago:

#include <stdio.h>
#include <stdlib.h>

__float128 factorial(__float128 X) {
  if (X == 0.0) return 1.0;
  return X*factorial(X-1);
}

int main(int argc, char **argv) {
  printf("%LLg\n", factorial(atoi(argv[1])));
}

(I had initially tried float128 and _float128 types, which don't seem to be
recognized at all).

This crashes the compiler / optimizer:

/tmp/webcompile/_22203_0.c: In function 'factorial':
/tmp/webcompile/_22203_0.c:4: internal compiler error: Segmentation fault
Quuxplusone commented 13 years ago
I have to confess I already knew about it.  The main reason I never added
support
for this (besides not needing it myself) is I couldn't find a description of the
__float128 type.  Is it the standard IEEE quad precision type?
Quuxplusone commented 13 years ago
(In reply to comment #1)
> I have to confess I already knew about it.  The main reason I never added
> support
> for this (besides not needing it myself) is I couldn't find a description of
> the
> __float128 type.  Is it the standard IEEE quad precision type?
As it seems for me - yes. Note that currently LLVM is not pretty good in
supporting fp128 at the codegen level. I believe I had some patches for this
while reviewing systemz backend, but probably I committed them all, I'll check.
Quuxplusone commented 13 years ago
On x86 (including x86_64) the compiler quickly barfs on fp128 because its
alignment is not known: nothing is specified in the data layout string...
Quuxplusone commented 13 years ago

Attached dl.diff (1482 bytes, text/plain): data layout patch

Quuxplusone commented 13 years ago
This is fixed in the sense that dragonegg now happily outputs IR for the
testcase (see below).  However codegen falls over at once:
llvm/include/llvm/Target/TargetLowering.h:171: virtual
llvm::TargetRegisterClass* llvm::TargetLowering::getRegClassFor(llvm::EVT)
const: Assertion `RC && "This value type is not natively supported!"' failed.
Stack dump:
0.  Running pass 'X86 DAG->DAG Instruction Selection' on function '@factorial'

Anton, maybe you can comment on this?

target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-f128:128:128-n8:16:32:64"
target triple = "x86_64-unknown-linux-gnu"

module asm "\09.ident\09\22GCC: (GNU) 4.5.3 20110304 (prerelease) LLVM:
126934:127093M\22"

@.str = private constant [6 x i8] c"%LLg\0A\00", align 1

define fp128 @factorial(fp128 %X) nounwind readnone {
entry:
  %0 = fcmp oeq fp128 %X, 0xL00000000000000000000000000000000
  br i1 %0, label %"5", label %"4"

"4":                                              ; preds = %entry
  %1 = fadd fp128 %X, 0xL0000000000000000BFFF000000000000
  %2 = tail call fp128 @factorial(fp128 %1) nounwind
  %3 = fmul fp128 %2, %X
  ret fp128 %3

"5":                                              ; preds = %entry
  ret fp128 0xL00000000000000003FFF000000000000
}

define i32 @main(i32 %argc, i8** nocapture %argv) nounwind {
entry:
  %0 = getelementptr inbounds i8** %argv, i64 1
  %1 = load i8** %0, align 8
  %2 = tail call i64 @strtol(i8* noalias nocapture %1, i8** noalias null, i32 10) nounwind
  %3 = trunc i64 %2 to i32
  %4 = sitofp i32 %3 to fp128
  %5 = tail call fp128 @factorial(fp128 %4) nounwind
  %6 = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([6 x i8]* @.str, i64 0, i64 0), fp128 %5) nounwind
  ret i32 undef
}

declare i64 @strtol(i8* noalias, i8** noalias nocapture, i32) nounwind

declare i32 @printf(i8* nocapture, ...) nounwind
Quuxplusone commented 13 years ago
We have practically nothing in terms of __float128 support; APFloat works
(AFAIK), but not much else.  The following patch is enough to get a little
further, but we then fail in type legalization because we don't know how to
generate fp128 libcalls.

Index: SelectionDAG/TargetLowering.cpp
===================================================================
--- SelectionDAG/TargetLowering.cpp (revision 127954)
+++ SelectionDAG/TargetLowering.cpp (working copy)
@@ -762,6 +762,15 @@

   // Decide how to handle f64. If the target does not have native f64 support,
   // expand it to i64 and we will be generating soft float library calls.
+  if (!isTypeLegal(MVT::f128)) {
+    NumRegistersForVT[MVT::f128] = NumRegistersForVT[MVT::i128];
+    RegisterTypeForVT[MVT::f128] = RegisterTypeForVT[MVT::i128];
+    TransformToType[MVT::f128] = MVT::i128;
+    ValueTypeActions.setTypeAction(MVT::f128, Expand);
+  }
+
+  // Decide how to handle f64. If the target does not have native f64 support,
+  // expand it to i64 and we will be generating soft float library calls.
   if (!isTypeLegal(MVT::f64)) {
     NumRegistersForVT[MVT::f64] = NumRegistersForVT[MVT::i64];
     RegisterTypeForVT[MVT::f64] = RegisterTypeForVT[MVT::i64];
Quuxplusone commented 12 years ago

_Bug 10980 has been marked as a duplicate of this bug._