Files
clang-p2996/llvm/test/Transforms/InstMerge/st_sink_bugfix_22613.ll
Djordje Todorovic 2cdc6f2ca6 Reland "[LICM] Hoist LOAD without sinking the STORE"
When doing load/store promotion within LICM, if we
cannot prove that it is safe to sink the store we won't
hoist the load, even though we can prove the load could
be dereferenced and moved outside the loop. This patch
implements the load promotion by moving it in the loop
preheader by inserting proper PHI in the loop. The store
is kept as is in the loop. By doing this, we avoid doing
the load from a memory location in each iteration.

Please consider this small example:

loop {
  var = *ptr;
  if (var) break;
  *ptr= var + 1;
}
After this patch, it will be:

var0 = *ptr;
loop {
  var1 = phi (var0, var2);
  if (var1) break;
  var2 = var1 + 1;
  *ptr = var2;
}
This addresses some problems from [0].

[0] https://bugs.llvm.org/show_bug.cgi?id=51193

Differential revision: https://reviews.llvm.org/D113289
2021-12-02 03:53:50 -08:00

107 lines
3.3 KiB
LLVM

; ModuleID = 'bug.c'
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; RUN: opt -O2 -S < %s | FileCheck %s
; CHECK-LABEL: main
; CHECK: memset
; CHECK: if.then
; CHECK: store
; CHECK: if.end
; CHECK: store
; CHECK: store
@d = common global i32 0, align 4
@b = common global i32 0, align 4
@f = common global [1 x [3 x i8]] zeroinitializer, align 1
@e = common global i32 0, align 4
@c = common global i32 0, align 4
@a = common global i32 0, align 4
; Function Attrs: nounwind uwtable
define void @fn1() {
entry:
store i32 0, i32* @d, align 4
br label %for.cond
for.cond: ; preds = %for.inc8, %entry
%0 = load i32, i32* @d, align 4
%cmp = icmp slt i32 %0, 2
br i1 %cmp, label %for.body, label %for.end10
for.body: ; preds = %for.cond
%1 = load i32, i32* @d, align 4
%idxprom = sext i32 %1 to i64
%2 = load i32, i32* @b, align 4
%idxprom1 = sext i32 %2 to i64
%arrayidx = getelementptr inbounds [1 x [3 x i8]], [1 x [3 x i8]]* @f, i32 0, i64 %idxprom1
%arrayidx2 = getelementptr inbounds [3 x i8], [3 x i8]* %arrayidx, i32 0, i64 %idxprom
store i8 0, i8* %arrayidx2, align 1
store i32 0, i32* @e, align 4
br label %for.cond3
for.cond3: ; preds = %for.inc, %for.body
%3 = load i32, i32* @e, align 4
%cmp4 = icmp slt i32 %3, 3
br i1 %cmp4, label %for.body5, label %for.end
for.body5: ; preds = %for.cond3
%4 = load i32, i32* @c, align 4
%tobool = icmp ne i32 %4, 0
br i1 %tobool, label %if.then, label %if.end
if.then: ; preds = %for.body5
%5 = load i32, i32* @a, align 4
%dec = add nsw i32 %5, -1
store i32 %dec, i32* @a, align 4
br label %if.end
if.end: ; preds = %if.then, %for.body5
%6 = load i32, i32* @e, align 4
%idxprom6 = sext i32 %6 to i64
%arrayidx7 = getelementptr inbounds [3 x i8], [3 x i8]* getelementptr inbounds ([1 x [3 x i8]], [1 x [3 x i8]]* @f, i32 0, i64 0), i32 0, i64 %idxprom6
store i8 1, i8* %arrayidx7, align 1
br label %for.inc
for.inc: ; preds = %if.end
%7 = load i32, i32* @e, align 4
%inc = add nsw i32 %7, 1
store i32 %inc, i32* @e, align 4
br label %for.cond3
for.end: ; preds = %for.cond3
br label %for.inc8
for.inc8: ; preds = %for.end
%8 = load i32, i32* @d, align 4
%inc9 = add nsw i32 %8, 1
store i32 %inc9, i32* @d, align 4
br label %for.cond
for.end10: ; preds = %for.cond
ret void
}
; Function Attrs: nounwind uwtable
define i32 @main() {
entry:
%retval = alloca i32, align 4
store i32 0, i32* %retval
call void @fn1()
%0 = load i8, i8* getelementptr inbounds ([1 x [3 x i8]], [1 x [3 x i8]]* @f, i32 0, i64 0, i64 1), align 1
%conv = sext i8 %0 to i32
%cmp = icmp ne i32 %conv, 1
br i1 %cmp, label %if.then, label %if.end
if.then: ; preds = %entry
call void @abort()
unreachable
if.end: ; preds = %entry
ret i32 0
}
; Function Attrs: noreturn nounwind
declare void @abort()