Wiki Roadmap Timeline Tickets New Ticket Source Search Help / Guide About Trac Login

Ticket #440 (closed defect: fixed)

Opened 13 years ago

Last modified 13 years ago

[PATCH] Bug in SimplifyDRTCalls breaking array appending

Reported by: fawzi Assigned to: lindquist
Priority: blocker Milestone:
Component: backend Version: hg tip
Keywords: Cc:

Description

It seems that some optimization of character functions fail because the type is considered incompatible. For example compiling tango/core/rt/compiler/util/utf.d with any level of optimization (-O for example) fails with

$ ldc -c -I../../tango/tango/core -I../../tango/tango/core/rt/compiler/ldc -I../../tango -I../../tango/tango/core/vendor -O -oftango-core-rt-compiler-util-utf-O3--release--inline.o ../../tango/tango/core/rt/compiler/util/utf.d
ldc: /home/b/becfawzi/d/llvm-28/lib/VMCore/Value.cpp:313: void llvm::Value::replaceAllUsesWith(llvm::Value*): Assertion `New->getType() == getType() && "replaceAllUses of value with new value of different type!"' failed.
0  ldc             0x0000000000e06dff
1  ldc             0x0000000000e08d86
2  libpthread.so.0 0x00002b4f64d2ccb0
3  libc.so.6       0x00002b4f654f2da5 gsignal + 53
4  libc.so.6       0x00002b4f654f41a0 abort + 272
5  libc.so.6       0x00002b4f654ec2e6 __assert_fail + 246
6  ldc             0x0000000000da6de6 llvm::Value::replaceAllUsesWith(llvm::Value*) + 502
7  ldc             0x000000000066940d
8  ldc             0x000000000066a433
9  ldc             0x0000000000d90d2f llvm::FPPassManager::runOnFunction(llvm::Function&) + 623
10 ldc             0x0000000000bcb3b1
11 ldc             0x0000000000bcbc0f
12 ldc             0x0000000000d9088f llvm::MPPassManager::runOnModule(llvm::Module&) + 575
13 ldc             0x0000000000d909f0 llvm::PassManagerImpl::run(llvm::Module&) + 160
14 ldc             0x0000000000667028 ldc_optimize_module(llvm::Module*) + 376
15 ldc             0x0000000000698650 writeModule(llvm::Module*, std::string) + 48
16 ldc             0x000000000065e094 main + 6836
17 libc.so.6       0x00002b4f654e0164 __libc_start_main + 244
18 ldc             0x0000000000580f39 __gxx_personality_v0 + 209
Stack dump:
0.      Running pass 'CallGraph Pass Manager' on module 'rt.compiler.util.utf'.
1.      Running pass 'Simplify calls to D runtime' on function '@_D2rt8compiler4util3utf7toUTF32FAaZAw'
Aborted

using the latest ldc with llvm 2.8

Change History

11/09/10 12:18:08 changed by fawzi

I did all my tests on linux x86_64.

generating a .bc file and optimizing it (as suggested by Deewiant) works (both with and without -inline and -release)

ldc -c -output-bc tango/core/rt/compiler/util/utf.d
if opt -O3 utf.bc > utf2.bc ; then echo 1 ; fi

but the direct optimization

ldc -c -O -output-bc tango/core/rt/compiler/util/utf.d

fails.

As the error is triggered by an assertion of llvm it happens only if one has compiled llvm with --enable-assertions . The release version will ignore this error (rubenbb has no error with this on FreeBSD).

11/10/10 12:53:17 changed by fawzi

disabling the d passes

ldc -c -O  -disable-d-passes tango/core/rt/compiler/util/utf.d

the file compiles, which shows that some of the D specific passes are the culprit here (not llvm).

01/02/11 02:07:51 changed by klickverbot

  • owner changed from ChristianK to lindquist.
  • priority changed from major to blocker.
  • component changed from unspecified to backend.

Raising priority to blocker as the reduced test case shows that this is a very serious issue:

void foo() {
   char[] str;
   str ~= "[";
}

The issue is caused by the SimplifyDRTCalls pass – somehow it manages to produce invalid IR in combination with at least another standard optimization pass, leading to this:

Error: Stored value type does not match pointer operand type!
  store i8 91, i8* (%object.TypeInfo*, i64, i64, i8*)* @_d_arraysetlengthiT, align 1
 i8* (%object.TypeInfo*, i64, i64, i8*)
Broken module found, compilation terminated.

The assert in Value::replaceAllUsesWith is no longer triggered, but I'm fairly confident that this is the same issue (the test-case was actually reduced from tango.text.Regex, because tango/core/rt/compiler/util/utf.d compiled fine for me).

01/02/11 02:10:17 changed by klickverbot

Oh, I didn't mean to change the owner of this ticket, no idea how this happened…

01/02/11 02:18:17 changed by klickverbot

When comparing the IR dumps before and after the pass is run, the problem becomes obvious:

*** IR Dump After Global Value Numbering ***
define fastcc void @_D5regex3fooFZv() {
entry:
  %.gc_mem = tail call i8* @_d_arraysetlengthiT(%object.TypeInfo* @_D11TypeInfo_Aa6__initZ, i64 1, i64 0, i8* null)
  store i8 91, i8* %.gc_mem, align 1
  ret void
}
*** IR Dump After Simplify calls to D runtime ***
define fastcc void @_D5regex3fooFZv() {
entry:
  store i8 91, i8* (%object.TypeInfo*, i64, i64, i8*)* @_d_arraysetlengthiT, align 1
  ret void
}

Oops…

01/02/11 02:49:46 changed by klickverbot

  • summary changed from optimization fails with replaceAllUses of value with new value of different type! to [PATCH] Bug in SimplifyDRTCalls breaking array appending.

Turns out that this (at least) was a rather astonishing off-by-one error:

diff -r d8966356d012 gen/passes/SimplifyDRuntimeCalls.cpp
--- a/gen/passes/SimplifyDRuntimeCalls.cpp	Sat Jan 01 12:00:39 2011 +0000
+++ b/gen/passes/SimplifyDRuntimeCalls.cpp	Sun Jan 02 03:36:07 2011 +0100
@@ -126,9 +126,9 @@
         if (CI->use_empty())
             return CI;
 
-        Value* NewLen = CI->getOperand(2);
+        Value* NewLen = CI->getOperand(1);
         if (Constant* NewCst = dyn_cast<Constant>(NewLen)) {
-            Value* Data = CI->getOperand(4);
+            Value* Data = CI->getOperand(3);
 
             // For now, we just catch the simplest of cases.
             //
@@ -142,7 +142,7 @@
                 return Data;
 
             // If both lengths are constant integers, see if NewLen <= OldLen
-            Value* OldLen = CI->getOperand(3);
+            Value* OldLen = CI->getOperand(2);
             if (ConstantInt* OldInt = dyn_cast<ConstantInt>(OldLen))
                 if (ConstantInt* NewInt = dyn_cast<ConstantInt>(NewCst))
                     if (NewInt->getValue().ule(OldInt->getValue()))

I am not sure how this bug could survive for almost two years (since the very beginning of SimplifyDRTCalls to surface just after the move to LLVM 2.8 – if I had to guess, I'd say that this code path was simplify never taken until some more sophisticated optimizations in LLVM 2.8 started to simplify the IR enough for this pass to become active…

01/02/11 14:02:21 changed by klickverbot

  • status changed from new to closed.
  • resolution set to fixed.

Fixed in changeset 0cb1edbcae87.

Copyright © 2008, LDC Development Team.