diff --git a/llvm/test/Transforms/GVNSink/gvn-awareness.ll b/llvm/test/Transforms/GVNSink/gvn-awareness.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/GVNSink/gvn-awareness.ll @@ -0,0 +1,90 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 +; Test to show a sinking operation that would have been impossible without +; GVN-awareness. +; RUN: opt -passes=gvn-sink -S < %s | FileCheck %s + +define void @gvn_awareness(ptr %a, i32 %beam) { +; CHECK-LABEL: define void @gvn_awareness +; CHECK-SAME: (ptr [[A:%.*]], i32 [[BEAM:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +; CHECK-NEXT: [[BEAM_ADDR:%.*]] = alloca i32, align 4 +; CHECK-NEXT: [[I:%.*]] = alloca i32, align 4 +; CHECK-NEXT: store ptr [[A]], ptr [[A_ADDR]], align 8 +; CHECK-NEXT: store i32 [[BEAM]], ptr [[BEAM_ADDR]], align 4 +; CHECK-NEXT: br label [[FOR_COND:%.*]] +; CHECK: for.cond: +; CHECK-NEXT: [[DOTSINK:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[IF_END:%.*]] ] +; CHECK-NEXT: [[TMP0:%.*]] = phi ptr [ [[TMP3:%.*]], [[IF_END]] ], [ [[A]], [[ENTRY]] ] +; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[INC]], [[IF_END]] ], [ 0, [[ENTRY]] ] +; CHECK-NEXT: store i32 [[DOTSINK]], ptr [[I]], align 4 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP1]], 10000 +; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: ret void +; CHECK: for.body: +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[TMP1]], [[BEAM]] +; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 2, [[BEAM]] +; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[MUL]] to i64 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IDXPROM]] +; CHECK-NEXT: store i32 0, ptr [[ARRAYIDX]], align 4 +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.else: +; CHECK-NEXT: [[MUL2:%.*]] = mul nsw i32 2, [[TMP1]] +; CHECK-NEXT: [[IDXPROM3:%.*]] = sext i32 [[MUL2]] to i64 +; CHECK-NEXT: [[ARRAYIDX4:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 [[IDXPROM3]] +; CHECK-NEXT: store i32 1, ptr [[ARRAYIDX4]], align 4 +; CHECK-NEXT: [[DOTPRE:%.*]] = load i32, ptr [[I]], align 4 +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[TMP2:%.*]] = phi i32 [ [[DOTPRE]], [[IF_ELSE]] ], [ [[BEAM]], [[IF_THEN]] ] +; CHECK-NEXT: [[TMP3]] = phi ptr [ [[TMP0]], [[IF_ELSE]] ], [ [[A]], [[IF_THEN]] ] +; CHECK-NEXT: [[INC]] = add nsw i32 [[TMP2]], 1 +; CHECK-NEXT: br label [[FOR_COND]] +; +entry: + %a.addr = alloca ptr, align 8 + %beam.addr = alloca i32, align 4 + %i = alloca i32, align 4 + store ptr %a, ptr %a.addr, align 8 + store i32 %beam, ptr %beam.addr, align 4 + store i32 0, ptr %i, align 4 + br label %for.cond + +for.cond: ; preds = %if.end, %entry + %0 = phi ptr [ %3, %if.end ], [ %a, %entry ] + %1 = phi i32 [ %inc, %if.end ], [ 0, %entry ] + %cmp = icmp slt i32 %1, 10000 + br i1 %cmp, label %for.body, label %for.cond.cleanup + +for.cond.cleanup: ; preds = %for.cond + ret void + +for.body: ; preds = %for.cond + %cmp1 = icmp eq i32 %1, %beam + br i1 %cmp1, label %if.then, label %if.else + +if.then: ; preds = %for.body + %mul = mul nsw i32 2, %beam + %idxprom = sext i32 %mul to i64 + %arrayidx = getelementptr inbounds i32, ptr %a, i64 %idxprom + store i32 0, ptr %arrayidx, align 4 + br label %if.end + +if.else: ; preds = %for.body + %mul2 = mul nsw i32 2, %1 + %idxprom3 = sext i32 %mul2 to i64 + %arrayidx4 = getelementptr inbounds i32, ptr %0, i64 %idxprom3 + store i32 1, ptr %arrayidx4, align 4 + %.pre = load i32, ptr %i, align 4 + br label %if.end + +if.end: ; preds = %if.else, %if.then + %2 = phi i32 [ %.pre, %if.else ], [ %beam, %if.then ] + %3 = phi ptr [ %0, %if.else ], [ %a, %if.then ] + %inc = add nsw i32 %2, 1 + store i32 %inc, ptr %i, align 4 + br label %for.cond +}