diff --git a/llvm/test/Transforms/Sink/invariant-load.ll b/llvm/test/Transforms/Sink/invariant-load.ll index 1aab4a9696323..c8fb119acd30a 100644 --- a/llvm/test/Transforms/Sink/invariant-load.ll +++ b/llvm/test/Transforms/Sink/invariant-load.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -passes=sink -S < %s | FileCheck %s -; Loads marked invariant can be sunk across critical edges +; Loads marked invariant can be sunk across critical edges. define <4 x float> @invariant_load(ptr %in, i32 %s) { ; CHECK-LABEL: @invariant_load( @@ -12,7 +12,7 @@ define <4 x float> @invariant_load(ptr %in, i32 %s) { ; CHECK-NEXT: [[Z:%.*]] = add i32 [[S]], 1 ; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[V:%.*]] = load <4 x float>, ptr [[IN:%.*]], align 16, !invariant.load !0 +; CHECK-NEXT: [[V:%.*]] = load <4 x float>, ptr [[IN:%.*]], align 16, !invariant.load [[META0:![0-9]+]] ; CHECK-NEXT: ret <4 x float> [[V]] ; main_body: @@ -26,4 +26,67 @@ end: ret <4 x float> %v } +; Loads that aren't marked invariant but used in one branch +; can be sunk to that branch. + +define void @invariant_load_use_in_br(ptr %p, i1 %cond) { +; CHECK-LABEL: @invariant_load_use_in_br( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[COND:%.*]], label [[TRUE_BR:%.*]], label [[FALSE_BR:%.*]] +; CHECK: true.br: +; CHECK-NEXT: call void @fn() +; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK: false.br: +; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[P:%.*]], align 4 +; CHECK-NEXT: call void @fn(i32 [[VAL]]) +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + %val = load i32, ptr %p + br i1 %cond, label %true.br, label %false.br +true.br: + call void @fn() + br label %exit +false.br: + call void @fn(i32 %val) + br label %exit +exit: + ret void +} + +; TODO: Invariant loads marked with metadata can be sunk past calls. + +define void @invariant_load_metadata_call(ptr %p, i1 %cond) { +; CHECK-LABEL: @invariant_load_metadata_call( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[P:%.*]], align 4, !invariant.load [[META0]] +; CHECK-NEXT: call void @fn() +; CHECK-NEXT: br i1 [[COND:%.*]], label [[TRUE_BR:%.*]], label [[FALSE_BR:%.*]] +; CHECK: true.br: +; CHECK-NEXT: call void @fn() +; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK: false.br: +; CHECK-NEXT: call void @fn(i32 [[VAL]]) +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: ret void +; +entry: + %val = load i32, ptr %p, !invariant.load !0 + call void @fn() + br i1 %cond, label %true.br, label %false.br +true.br: + call void @fn() + br label %exit +false.br: + call void @fn(i32 %val) + br label %exit +exit: + ret void +} + +declare void @fn() + !0 = !{}