[PATCH] [InstructionMerge - GVN] hoisting and sinking of equivalent memory instructions in diamonds

Gerolf Hoflehner ghoflehner at apple.com
Fri May 2 14:08:09 PDT 2014


ping …

On Apr 29, 2014, at 12:31 PM, Gerolf Hoflehner <ghoflehner at apple.com> wrote:

> Hi,
> 
> the attached patch iteratively hoists two loads to the same address out of a diamond (hammock) and merges them
> into a single load in the header. Similar it sinks and merges two stores to the tail block. The algorithm
> iterates over the instructions of one side of the diamond and attempts to find a matching load/store on
> the other side. It hoists / sinks when it thinks it safe to do so. It runs as part of GVN in the GVN preparation
> loop.  I tailored the code as conservative as possible to catch the initial cases we are interested in, which 
> keeps code size and complexity in check. The optimization helps hiding load latencies and triggering if-conversion.
> 
> The optimization gives gains on some internal benchmarks and about ~2% on SPEC mcf.
> 
> I have not measured a sizable compiler-time impact.
> 
> Cheers
> Gerolf
> 
> <instruction_merge.patch>
> 
> 
> Example for the optimization from 181.mcf, refresh_potential():
> 
> IR before opt 
> while.body6:                                      ; preds = %while.body6.lr.ph, %if.end
>   %checksum.152 = phi i64 [ %checksum.057, %while.body6.lr.ph ], [ %checksum.2, %if.end ]
>   %node.251 = phi %struct.node* [ %node.155, %while.body6.lr.ph ], [ %12, %if.end ]
>   %orientation = getelementptr inbounds %struct.node* %node.251, i64 0, i32 7
>   %3 = load i64* %orientation, align 8, !tbaa !13
>   %cmp7 = icmp eq i64 %3, 1
>   br i1 %cmp7, label %if.then, label %if.else
> 
> if.then:                                          ; preds = %while.body6
>   %basic_arc = getelementptr inbounds %struct.node* %node.251, i64 0, i32 8
>   %4 = load %struct.arc** %basic_arc, align 8, !tbaa !14
>   %cost = getelementptr inbounds %struct.arc* %4, i64 0, i32 4
>   %5 = load i64* %cost, align 8, !tbaa !15
>   %pred = getelementptr inbounds %struct.node* %node.251, i64 0, i32 2
>   %6 = load %struct.node** %pred, align 8, !tbaa !17
>   %potential8 = getelementptr inbounds %struct.node* %6, i64 0, i32 11
>   %7 = load i64* %potential8, align 8, !tbaa !11
>   %add = add nsw i64 %7, %5
>   %potential9 = getelementptr inbounds %struct.node* %node.251, i64 0, i32 11
>   store i64 %add, i64* %potential9, align 8, !tbaa !11
>   br label %if.end
> 
> if.else:                                          ; preds = %while.body6
>   %pred10 = getelementptr inbounds %struct.node* %node.251, i64 0, i32 2
>   %8 = load %struct.node** %pred10, align 8, !tbaa !17
>   %potential11 = getelementptr inbounds %struct.node* %8, i64 0, i32 11
>   %9 = load i64* %potential11, align 8, !tbaa !11
>   %basic_arc12 = getelementptr inbounds %struct.node* %node.251, i64 0, i32 8
>   %10 = load %struct.arc** %basic_arc12, align 8, !tbaa !14
>   %cost13 = getelementptr inbounds %struct.arc* %10, i64 0, i32 4
>   %11 = load i64* %cost13, align 8, !tbaa !15
>   %sub = sub nsw i64 %9, %11
>   %potential14 = getelementptr inbounds %struct.node* %node.251, i64 0, i32 11
>   store i64 %sub, i64* %potential14, align 8, !tbaa !11
>   %inc = add nsw i64 %checksum.152, 1
>   br label %if.end
> 
> if.end:                                           ; preds = %if.else, %if.then
>   %checksum.2 = phi i64 [ %checksum.152, %if.then ], [ %inc, %if.else ]
>   %child15 = getelementptr inbounds %struct.node* %node.251, i64 0, i32 3
>   %12 = load %struct.node** %child15, align 8, !tbaa !12
>   %tobool = icmp eq %struct.node* %12, null
>   br i1 %tobool, label %while.cond5.while.cond16.preheader_crit_edge, label %while.body6
> 
> IR after:
> while.body6:                                      ; preds = %while.body6.lr.ph, %if.end
>   %checksum.152 = phi i64 [ %checksum.057, %while.body6.lr.ph ], [ %checksum.2, %if.end ]
>   %node.251 = phi %struct.node* [ %node.155, %while.body6.lr.ph ], [ %13, %if.end ]
>   %orientation = getelementptr inbounds %struct.node* %node.251, i64 0, i32 7
>   %3 = load i64* %orientation, align 8, !tbaa !13
>   %cmp7 = icmp eq i64 %3, 1
>   %4 = getelementptr inbounds %struct.node* %node.251, i64 0, i32 8
>   %5 = load %struct.arc** %4, align 8, !tbaa !14
>   %6 = getelementptr inbounds %struct.arc* %5, i64 0, i32 4
>   %7 = load i64* %6, align 8, !tbaa !15
>   %8 = getelementptr inbounds %struct.node* %node.251, i64 0, i32 2
>   %9 = load %struct.node** %8, align 8, !tbaa !17
>   %10 = getelementptr inbounds %struct.node* %9, i64 0, i32 11
>   %11 = load i64* %10, align 8, !tbaa !11
>   br i1 %cmp7, label %if.then, label %if.else
> 
> if.then:                                          ; preds = %while.body6
>   %add = add nsw i64 %11, %7
>   br label %if.end
> 
> if.else:                                          ; preds = %while.body6
>   %sub = sub nsw i64 %11, %7
>   %inc = add nsw i64 %checksum.152, 1
>   br label %if.end
> 
> if.end:                                           ; preds = %if.else, %if.then
>   %add.sink = phi i64 [ %sub, %if.else ], [ %add, %if.then ]
>   %checksum.2 = phi i64 [ %checksum.152, %if.then ], [ %inc, %if.else ]
>   %12 = getelementptr inbounds %struct.node* %node.251, i64 0, i32 11
>   store i64 %add.sink, i64* %12, align 8, !tbaa !11
>   %child15 = getelementptr inbounds %struct.node* %node.251, i64 0, i32 3
>   %13 = load %struct.node** %child15, align 8, !tbaa !12
>   %tobool = icmp eq %struct.node* %13, null
>   br i1 %tobool, label %while.cond5.while.cond16.preheader_crit_edge, label %while.body6

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140502/aeca6222/attachment.html>


More information about the llvm-commits mailing list