Index: test/Transforms/InstCombine/phi-sink-load.ll =================================================================== --- /dev/null +++ test/Transforms/InstCombine/phi-sink-load.ll @@ -0,0 +1,110 @@ +; RUN: opt -instcombine -S < %s | FileCheck %s + +;; Tests aiming to add coverage of InstCombinePHI.cpp isSafeAndProfitableToSinkLoad(). + +;; Test for store between load and phi, meaning it is not safe to sink the load +define i32 @test1(i32* %a, i32* %b, i1 %cmp) { +; CHECK-LABEL: @test1 +; CHECK-NEXT: entry +; CHECK-NEXT: load +entry: + %c = load i32, i32* %a, align 4 + store i32 7, i32* %a + br i1 %cmp, label %if.then, label %if.end + +if.then: + %d = load i32, i32* %b, align 4 + br label %if.end + +if.end: + %e = phi i32 [ %d, %if.then ], [ %c, %entry ] + ret i32 %e +} + +;; Test for not address-taken alloca, due to load user. Not profitable to sink load. +define i32 @test2(i32* %a, i1 %cmp) { +; CHECK-LABEL: @test2 +; CHECK-NEXT: entry +; CHECK-NEXT: alloca +; CHECK-NEXT: load +entry: + %b = alloca i32, align 4 + %e = load i32, i32* %b, align 4 + br i1 %cmp, label %if.then, label %if.end + +if.then: + %c = load i32, i32* %a, align 4 + br label %if.end + +if.end: + %d = phi i32 [ %e, %entry ], [ %c, %if.then ] + ret i32 %d +} + +;; Test for not address-taken alloca, due to store user. Not profitable to sink load. +define i32 @test3(i32* %a, i1 %cmp) { +; CHECK-LABEL: @test3 +; CHECK-NEXT: entry +; CHECK-NEXT: alloca +; CHECK-NEXT: store +; CHECK-NEXT: load +entry: + %b = alloca i32, align 4 + store i32 7, i32* %b + %c = load i32, i32* %a, align 4 + br i1 %cmp, label %if.then, label %if.end + +if.then: + %e = load i32, i32* %b, align 4 + br label %if.end + +if.end: + %d = phi i32 [ %e, %if.then ], [ %c, %entry ] + ret i32 %d +} + +;; Test for address-taken alloca, used by store but as operand 0 so the alloca is not stored to, so it is profitable to sink load. +define i32 @test4(i32* %a, i32** %f, i1 %cmp) { +; CHECK-LABEL: @test4 +; CHECK-NEXT: entry +; CHECK-NEXT: alloca +; CHECK-NEXT: store +; CHECK-NEXT: br +entry: + %b = alloca i32, align 4 + store i32* %b, i32** %f + %e = load i32, i32* %b, align 4 + br i1 %cmp, label %if.then, label %if.end + +if.then: + %c = load i32, i32* %a, align 4 + br label %if.end + +if.end: + %d = phi i32 [ %c, %if.then ], [ %e, %entry ] + ret i32 %d +} + +;; Test for address-taken alloca, used by call as well as load so it is profitable to sink load. +define i32 @test5(i32* %a, i1 %cmp) { +; CHECK-LABEL: @test5 +; CHECK-NEXT: entry +; CHECK-NEXT: alloca +; CHECK-NEXT: call +; CHECK-NEXT: br +entry: + %b = alloca i32, align 4 + call void @bar(i32* nonnull %b) + %d = load i32, i32* %b, align 4 + br i1 %cmp, label %if.then, label %if.end + +if.then: + %c = load i32, i32* %a, align 4 + br label %if.end + +if.end: + %e = phi i32 [ %c, %if.then ], [ %d, %entry ] + ret i32 %e +} + +declare void @bar(i32*)