[llvm-dev] GEP index canonicalization

Manuel Jacob via llvm-dev llvm-dev at lists.llvm.org
Wed May 25 06:18:49 PDT 2016


*ping*

On 2016-05-19 02:56, Manuel Jacob via llvm-dev wrote:
> Hi,
> 
> InstCombine canonicalizes index operands (unless they are into struct
> types) to pointer size.  The comment says: "If we are using a wider
> index than needed for this platform, shrink it to what we need.  If
> narrower, sign-extend it to what we need.  This explicit cast can make
> subsequent optimizations more obvious.".
> 
> For our architecture, the canonicalization is a bit problematic.  For
> example, our load operation can take any width and will implicitly
> sign-extend or truncate it.  The extra explicit cast however will show
> up as an extra operation in the machine code.  It is of course easy to
> eliminate the cast in a peephole optimization in the backend.
> 
> More interesting is the effect of this canonicalization on subsequent
> transformations.  Which optimizations are more obvious now, as the
> comment says?  I found examples where it enables IndVarSimplify to
> promote an index variable to pointer size.  However that introduces
> truncations, which can't be optimized away by simple peephole
> optimizations in the backend anymore.
> 
> Does it make sense to add a target hook for this?
> 
> -Manuel
> 
> 
> Example:
> 
> define void @foo(i32 %n, i32* %a) {
> entry:
>   %cmp1 = icmp slt i32 0, %n
>   br i1 %cmp1, label %for.body, label %for.end
> 
> for.body:                                         ; preds = %for.body, 
> %entry
>   %i = phi i32 [ %inc, %for.body ], [ 0, %entry ]
>   %ptr = getelementptr inbounds i32, i32* %a, i32 %i
>   store i32 %i, i32* %ptr, align 4
>   %inc = add nsw i32 %i, 1
>   %cmp = icmp slt i32 %inc, %n
>   br i1 %cmp, label %for.body, label %for.end
> 
> for.end:                                          ; preds = %for.body, 
> %entry
>   ret void
> }
> 
> 
> InstCombine introduces a sext instruction:
> 
> define void @foo(i32 %n, i32* %a) {
> entry:
>   %cmp1 = icmp sgt i32 %n, 0
>   br i1 %cmp1, label %for.body, label %for.end
> 
> for.body:                                         ; preds = %for.body, 
> %entry
>   %i = phi i32 [ %inc, %for.body ], [ 0, %entry ]
>   %0 = sext i32 %i to i64
>   %ptr = getelementptr inbounds i32, i32* %a, i64 %0
>   store i32 %i, i32* %ptr, align 4
>   %inc = add nsw i32 %i, 1
>   %cmp = icmp slt i32 %inc, %n
>   br i1 %cmp, label %for.body, label %for.end
> 
> for.end:                                          ; preds = %for.body, 
> %entry
>   ret void
> }
> 
> 
> IndVarSimplify promotes %i to i64, requiring two additional truncs:
> 
> define void @foo(i32 %n, i32* %a) {
> entry:
>   %cmp1 = icmp sgt i32 %n, 0
>   br i1 %cmp1, label %for.body.preheader, label %for.end
> 
> for.body.preheader:                               ; preds = %entry
>   br label %for.body
> 
> for.body:                                         ; preds =
> %for.body.preheader, %for.body
>   %indvars.iv = phi i64 [ 0, %for.body.preheader ], [
> %indvars.iv.next, %for.body ]
>   %ptr = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
>   %0 = trunc i64 %indvars.iv to i32
>   store i32 %0, i32* %ptr, align 4
>   %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
>   %lftr.wideiv = trunc i64 %indvars.iv.next to i32
>   %exitcond = icmp ne i32 %lftr.wideiv, %n
>   br i1 %exitcond, label %for.body, label %for.end.loopexit
> 
> for.end.loopexit:                                 ; preds = %for.body
>   br label %for.end
> 
> for.end:                                          ; preds =
> %for.end.loopexit, %entry
>   ret void
> }
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev


More information about the llvm-dev mailing list