[patch] mergefunc struct result

Duncan P. N. Exon Smith dexonsmith at apple.com
Fri Apr 18 15:03:24 PDT 2014


Hi Carlo,

Thanks for working on this.  See comments below.

On 2014-Apr-18, at 11:21, Carlo Kok <ck at remobjects.com> wrote:

> When using the merge func pass with two functions that return the same
> kind of struct but with different element types merge func tries to do a
> bitcast of struct to struct and fails with an assert (as you can't bitcast a struct) given the following functions:
> 
> %kv1 = type { i32*, i32* }
> %kv2 = type { i8*, i8* }
> 
> define %kv1 @fn1() ..
> define %kv2 @fn2() ..
> 
> (full file in fail.ir)

This testcase should be part of the commit.  The file extension for LLVM IR is
".ll".  You should find a good place to put this (probably
test/Transforms/MergeFunc/) and give it a descriptive name (maybe
merge-structs.ll?).

There's a good overview of the testing infrastructure here:

http://llvm.org/docs/TestingGuide.html

> 
> The attached patch checks for two struct types & uses insert/extract to
> create the right record.
> 
> To see it fail, fail.ir can be used with opt:
> 
> opt -mergefunc fail.ir -o out.ir

You'll want to add a RUN line something like:

; RUN: opt -mergefunc < %s | FileCheck %s

> after the patch it generates:
> 
> define %kv1 @fn1() {
>  %tmp = alloca %kv1
>  %v1 = getelementptr %kv1* %tmp, i32 0, i32 0
>  store i32* null, i32** %v1
>  %v2 = getelementptr %kv1* %tmp, i32 0, i32 0
>  store i32* null, i32** %v2
>  call void @noop()
>  %v3 = load %kv1* %tmp
>  ret %kv1 %v3
> }
> 
> define %kv2 @fn2() {
>  %1 = tail call %kv1 @fn1()
>  %2 = extractvalue %kv1 %1, 0
>  %3 = bitcast i32* %2 to i8*
>  %4 = insertvalue %kv2 undef, i8* %3, 0
>  %5 = extractvalue %kv1 %1, 1
>  %6 = bitcast i32* %5 to i8*
>  %7 = insertvalue %kv2 %4, i8* %6, 1
>  ret %kv2 %7
> }
> 
> Where fn2 is the merged function.
> 

And then some CHECK lines to confirm that the output is correct.

On the patch itself:

 lib/Transforms/IPO/MergeFunctions.cpp | 10 ++++++++++
 1 file changed, 10 insertions(+)

> diff --git a/lib/Transforms/IPO/MergeFunctions.cpp b/lib/Transforms/IPO/MergeFunctions.cpp
> index 8555d2c..b4a9121 100644
> --- a/lib/Transforms/IPO/MergeFunctions.cpp
> +++ b/lib/Transforms/IPO/MergeFunctions.cpp

Style doesn't match our agreed upon standards [1].  clang-format [2] would fix
a lot of the issues.  Most of my comments below are style nitpicks, so I
encourage you to read the standards.

[1]: http://llvm.org/docs/CodingStandards.html
[2]: http://clang.llvm.org/docs/ClangFormat.html#script-for-patch-reformatting

> @@ -785,6 +785,16 @@ void MergeFunctions::writeThunkOrAlias(Function *F, Function *G) {
>  // but a bit simpler then CastInst::getCastOpcode.
>  static Value* createCast(IRBuilder<false> &Builder, Value *V, Type *DestTy) {
>    Type *SrcTy = V->getType();
> +  if (SrcTy->isStructTy() && DestTy->isStructTy()) {

Should this be asserting:

    assert(DestTy->isStructTy())

rather than checking it?

> +    assert(SrcTy->getStructNumElements() == DestTy->getStructNumElements());
> +    Value* res = UndefValue::get(DestTy);

Should be capitalized and the * is placed wrongly.

    Value *Result = UndefValue::get(DestTy);

> +    for (unsigned int i = 0; i < SrcTy->getStructNumElements(); i++) {

Should be:

    for (unsigned int I = 0, E = SrcTy->getStructNumElements(); I < E; ++I)

Capitilized variables, evaluate the end condition once, pre-increment, and no
need for {} on a single statement.

> +      res = Builder.CreateInsertValue(res, createCast(Builder, 
> +        Builder.CreateExtractValue(V, { i }), 
> +        DestTy->getStructElementType(i)), { i });

I'm not sure MSVC will accept this initializer list.  Regardless, ArrayRef has
a constructor from element type, so you can just leave off the braces.

Also, this line is a little complicated.  Maybe you should split it into
two statements (separate the createCast() from the CreateInsertValue()).

If you leave it as is, the continuation should be double-indented (i.e.,
four spaces), and should probably look more like this:

    Result = Builder.CreateInsertValue(
        Result, createCast(Builder, Builder.CreateExtractValue(V, I), 
                           DestTy->getStructElementType(i)),
        I);

> +    return res;
> +  }
>    if (SrcTy->isIntegerTy() && DestTy->isPointerTy())
>      return Builder.CreateIntToPtr(V, DestTy);
>    else if (SrcTy->isPointerTy() && DestTy->isIntegerTy())




More information about the llvm-commits mailing list