Steve Montgomery
2010-Oct-08 14:51 UTC
[LLVMdev] llvm-gcc: code generated for pre- and post-increment
I'm relatively new to LLVM so apologies in advance if this is a dumb question. I've been experimenting with re-targeting LLVM onto a 16-bit micro which has pre and post increment and decrement addressing modes. I've been using llvm-gcc to generate llvm bitcode and llvm 2.7 to go from here to my target assembly code. I've got the Combine pass to deal with post-increment/decrement modes without any difficulty but I can't seem to get pre-increment/decrement modes to work. If I examine the bitcode for: char c, *p; void func(void) { c = *++p; } then I get (with llvm-gcc 4.2.1): %0 = load i8** @p, align 4 %1 = getelementptr inbounds i8* %0, i32 1 store i8* %1, i8** @p, align 4 %2 = load i8*, %1, align 1 store i* %2m i8* @c, align 1 I think the position of the first store is preventing DAGCombiner::CombineToPreIndexedLoadStore from folding the base pointer (test #3 out of the 4 tests it makes). If I move that store into p to the end of the code then it's happy to fold it. Why does llvm-gcc emit llvm code that seems to preclude the combiner from ever being able to combine a pre-increment/decrement? Given that the order of side-effects between sequence points is unspecified and the behaviour undefined if any object is modified more than once between sequence points it seems to me to be perfectly legal to move that first load to the end. In passing, I note that the clang front-end seems to emit code that will never be a candidate for folding into either pre or post increment/decrement operations. Steve Montgomery
Eli Friedman
2010-Oct-08 22:58 UTC
[LLVMdev] llvm-gcc: code generated for pre- and post-increment
On Fri, Oct 8, 2010 at 7:51 AM, Steve Montgomery <stephen.montgomery3 at btinternet.com> wrote:> I'm relatively new to LLVM so apologies in advance if this is a dumb > question. I've been experimenting with re-targeting LLVM onto a 16-bit > micro which has pre and post increment and decrement addressing modes. > I've been using llvm-gcc to generate llvm bitcode and llvm 2.7 to go > from here to my target assembly code. > > I've got the Combine pass to deal with post-increment/decrement modes > without any difficulty but I can't seem to get pre-increment/decrement > modes to work. If I examine the bitcode for: > > char c, *p; > > void func(void) > { > c = *++p; > } > > then I get (with llvm-gcc 4.2.1): > > %0 = load i8** @p, align 4 > %1 = getelementptr inbounds i8* %0, i32 1 > store i8* %1, i8** @p, align 4 > %2 = load i8*, %1, align 1 > store i* %2m i8* @c, align 1 > > I think the position of the first store is preventing > DAGCombiner::CombineToPreIndexedLoadStore from folding the base > pointer (test #3 out of the 4 tests it makes). If I move that store > into p to the end of the code then it's happy to fold it. > > Why does llvm-gcc emit llvm code that seems to preclude the combiner > from ever being able to combine a pre-increment/decrement? Given that > the order of side-effects between sequence points is unspecified and > the behaviour undefined if any object is modified more than once > between sequence points it seems to me to be perfectly legal to move > that first load to the end.Note that pre-increment is only precluded in cases where you're incrementing something which both can't be eliminated by mem2reg and can't be LICM'ed out of a loop. Yes, it's not ideal, but your testcase isn't representative of many places where pre-increments are used.> In passing, I note that the clang front-end seems to emit code that > will never be a candidate for folding into either pre or post > increment/decrement operations.I don't really know llvm-gcc that well, but the clang code generator is completely naive here: it generates the complete increment, then loads from the address. If you're interested, though, it wouldn't be too hard to change clang to detect constructs like this and shuffle around the generated code. -Eli