serge-sans-paille 50b2a113db
Move "auto-init" instructions to the dominator of their users
As a result of -ftrivial-auto-var-init, clang generates instructions to
set alloca'd memory to a given pattern, right after the allocation site.
In some cases, this (somehow costly) operation could be delayed, leading
to conditional execution in some cases.

This is not an uncommon situation: it happens ~500 times on the cPython
code base, and much more on the LLVM codebase. The benefit greatly
varies on the execution path, but it should not regress on performance.

This is a recommit of cca01008cc31a891d0ec70aff2201b25d05d8f1b with
MemorySSA update fixes.

Differential Revision: https://reviews.llvm.org/D137707
2023-04-04 07:30:03 +02:00

103 lines
4.0 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -S -passes='move-auto-init' -verify-memoryssa | FileCheck %s
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
define void @foo(i32 %x) {
; CHECK-LABEL: @foo(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[BUFFER:%.*]] = alloca [80 x i32], align 16
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[BUFFER]], i8 -86, i64 320, i1 false), !annotation !0
; CHECK-NEXT: br label [[DO_BODY:%.*]]
; CHECK: do.body:
; CHECK-NEXT: [[X_ADDR_0:%.*]] = phi i32 [ [[X:%.*]], [[ENTRY:%.*]] ], [ [[DEC:%.*]], [[DO_COND:%.*]] ]
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [80 x i32], ptr [[BUFFER]], i64 0, i64 0
; CHECK-NEXT: call void @dump(ptr [[ARRAYIDX]])
; CHECK-NEXT: br label [[DO_COND]]
; CHECK: do.cond:
; CHECK-NEXT: [[DEC]] = add nsw i32 [[X_ADDR_0]], -1
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[X_ADDR_0]], 0
; CHECK-NEXT: br i1 [[TOBOOL]], label [[DO_BODY]], label [[DO_END:%.*]]
; CHECK: do.end:
; CHECK-NEXT: ret void
;
entry:
%buffer = alloca [80 x i32], align 16
call void @llvm.memset.p0.i64(ptr align 16 %buffer, i8 -86, i64 320, i1 false), !annotation !0
br label %do.body
do.body: ; preds = %do.cond, %entry
%x.addr.0 = phi i32 [ %x, %entry ], [ %dec, %do.cond ]
%arrayidx = getelementptr inbounds [80 x i32], ptr %buffer, i64 0, i64 0
call void @dump(ptr %arrayidx)
br label %do.cond
do.cond: ; preds = %do.body
%dec = add nsw i32 %x.addr.0, -1
%tobool = icmp ne i32 %x.addr.0, 0
br i1 %tobool, label %do.body, label %do.end
do.end: ; preds = %do.cond
ret void
}
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg)
declare void @dump(ptr )
define void @bar(i32 %x, i32 %y) {
; CHECK-LABEL: @bar(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[BUFFER:%.*]] = alloca [80 x i32], align 16
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[Y:%.*]], 0
; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
; CHECK: if.then:
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[BUFFER]], i8 -86, i64 320, i1 false), !annotation !0
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[X:%.*]], [[Y]]
; CHECK-NEXT: br label [[DO_BODY:%.*]]
; CHECK: do.body:
; CHECK-NEXT: [[X_ADDR_0:%.*]] = phi i32 [ [[ADD]], [[IF_THEN]] ], [ [[DEC:%.*]], [[DO_COND:%.*]] ]
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [80 x i32], ptr [[BUFFER]], i64 0, i64 0
; CHECK-NEXT: call void @dump(ptr [[ARRAYIDX]])
; CHECK-NEXT: br label [[DO_COND]]
; CHECK: do.cond:
; CHECK-NEXT: [[DEC]] = add nsw i32 [[X_ADDR_0]], -1
; CHECK-NEXT: [[TOBOOL1:%.*]] = icmp ne i32 [[X_ADDR_0]], 0
; CHECK-NEXT: br i1 [[TOBOOL1]], label [[DO_BODY]], label [[DO_END:%.*]]
; CHECK: do.end:
; CHECK-NEXT: br label [[IF_END]]
; CHECK: if.end:
; CHECK-NEXT: ret void
;
entry:
%buffer = alloca [80 x i32], align 16
call void @llvm.memset.p0.i64(ptr align 16 %buffer, i8 -86, i64 320, i1 false), !annotation !0
%tobool = icmp ne i32 %y, 0
br i1 %tobool, label %if.then, label %if.end
if.then: ; preds = %entry
%add = add nsw i32 %x, %y
br label %do.body
do.body: ; preds = %do.cond, %if.then
%x.addr.0 = phi i32 [ %add, %if.then ], [ %dec, %do.cond ]
%arrayidx = getelementptr inbounds [80 x i32], ptr %buffer, i64 0, i64 0
call void @dump(ptr %arrayidx)
br label %do.cond
do.cond: ; preds = %do.body
%dec = add nsw i32 %x.addr.0, -1
%tobool1 = icmp ne i32 %x.addr.0, 0
br i1 %tobool1, label %do.body, label %do.end
do.end: ; preds = %do.cond
br label %if.end
if.end: ; preds = %do.end, %entry
ret void
}
!0 = !{!"auto-init"}