1211cf8a3SBjorn Pettersson; RUN: opt < %s -passes=sink -S | FileCheck %s 2cee313d2SEric Christopher; RUN: opt < %s -aa-pipeline='basic-aa' -passes='sink' -S | FileCheck %s 3cee313d2SEric Christopher 4cee313d2SEric Christopher@A = external global i32 5cee313d2SEric Christopher@B = external global i32 6cee313d2SEric Christopher 7cee313d2SEric Christopher; Sink should sink the load past the store (which doesn't overlap) into 8cee313d2SEric Christopher; the block that uses it. 9cee313d2SEric Christopher 10cee313d2SEric Christopher; CHECK-LABEL: @foo( 11cee313d2SEric Christopher; CHECK: true: 12*a198d204SMatt Arsenault; CHECK-NEXT: %l = load i32, ptr @A 13cee313d2SEric Christopher; CHECK-NEXT: ret i32 %l 14cee313d2SEric Christopher 15cee313d2SEric Christopherdefine i32 @foo(i1 %z) { 16*a198d204SMatt Arsenault %l = load i32, ptr @A 17*a198d204SMatt Arsenault store i32 0, ptr @B 18cee313d2SEric Christopher br i1 %z, label %true, label %false 19cee313d2SEric Christophertrue: 20cee313d2SEric Christopher ret i32 %l 21cee313d2SEric Christopherfalse: 22cee313d2SEric Christopher ret i32 0 23cee313d2SEric Christopher} 24cee313d2SEric Christopher 25cee313d2SEric Christopher; But don't sink load volatiles... 26cee313d2SEric Christopher 27cee313d2SEric Christopher; CHECK-LABEL: @foo2( 28cee313d2SEric Christopher; CHECK: load volatile 29cee313d2SEric Christopher; CHECK-NEXT: store i32 30cee313d2SEric Christopher 31cee313d2SEric Christopherdefine i32 @foo2(i1 %z) { 32*a198d204SMatt Arsenault %l = load volatile i32, ptr @A 33*a198d204SMatt Arsenault store i32 0, ptr @B 34cee313d2SEric Christopher br i1 %z, label %true, label %false 35cee313d2SEric Christophertrue: 36cee313d2SEric Christopher ret i32 %l 37cee313d2SEric Christopherfalse: 38cee313d2SEric Christopher ret i32 0 39cee313d2SEric Christopher} 40cee313d2SEric Christopher 41cee313d2SEric Christopher; Sink to the nearest post-dominator 42cee313d2SEric Christopher 43cee313d2SEric Christopher; CHECK-LABEL: @diamond( 44cee313d2SEric Christopher; CHECK: X: 45cee313d2SEric Christopher; CHECK-NEXT: phi 46cee313d2SEric Christopher; CHECK-NEXT: mul nsw 47cee313d2SEric Christopher; CHECK-NEXT: sub 48cee313d2SEric Christopher 49cee313d2SEric Christopherdefine i32 @diamond(i32 %a, i32 %b, i32 %c) { 50cee313d2SEric Christopher %1 = mul nsw i32 %c, %b 51cee313d2SEric Christopher %2 = icmp sgt i32 %a, 0 52cee313d2SEric Christopher br i1 %2, label %B0, label %B1 53cee313d2SEric Christopher 54cee313d2SEric ChristopherB0: ; preds = %0 55cee313d2SEric Christopher br label %X 56cee313d2SEric Christopher 57cee313d2SEric ChristopherB1: ; preds = %0 58cee313d2SEric Christopher br label %X 59cee313d2SEric Christopher 60cee313d2SEric ChristopherX: ; preds = %5, %3 61cee313d2SEric Christopher %.01 = phi i32 [ %c, %B0 ], [ %a, %B1 ] 62cee313d2SEric Christopher %R = sub i32 %1, %.01 63cee313d2SEric Christopher ret i32 %R 64cee313d2SEric Christopher} 65cee313d2SEric Christopher 66cee313d2SEric Christopher; We shouldn't sink constant sized allocas from the entry block, since CodeGen 67cee313d2SEric Christopher; interprets allocas outside the entry block as dynamically sized stack objects. 68cee313d2SEric Christopher 69cee313d2SEric Christopher; CHECK-LABEL: @alloca_nosink 70cee313d2SEric Christopher; CHECK: entry: 71cee313d2SEric Christopher; CHECK-NEXT: alloca 72cee313d2SEric Christopherdefine i32 @alloca_nosink(i32 %a, i32 %b) { 73cee313d2SEric Christopherentry: 74cee313d2SEric Christopher %0 = alloca i32 75cee313d2SEric Christopher %1 = icmp ne i32 %a, 0 76cee313d2SEric Christopher br i1 %1, label %if, label %endif 77cee313d2SEric Christopher 78cee313d2SEric Christopherif: 79*a198d204SMatt Arsenault %2 = getelementptr i32, ptr %0, i32 1 80*a198d204SMatt Arsenault store i32 0, ptr %0 81*a198d204SMatt Arsenault store i32 1, ptr %2 82*a198d204SMatt Arsenault %3 = getelementptr i32, ptr %0, i32 %b 83*a198d204SMatt Arsenault %4 = load i32, ptr %3 84cee313d2SEric Christopher ret i32 %4 85cee313d2SEric Christopher 86cee313d2SEric Christopherendif: 87cee313d2SEric Christopher ret i32 0 88cee313d2SEric Christopher} 89cee313d2SEric Christopher 90cee313d2SEric Christopher; Make sure we sink dynamic sized allocas 91cee313d2SEric Christopher 92cee313d2SEric Christopher; CHECK-LABEL: @alloca_sink_dynamic 93cee313d2SEric Christopher; CHECK: entry: 94cee313d2SEric Christopher; CHECK-NOT: alloca 95cee313d2SEric Christopher; CHECK: if: 96cee313d2SEric Christopher; CHECK-NEXT: alloca 97cee313d2SEric Christopherdefine i32 @alloca_sink_dynamic(i32 %a, i32 %b, i32 %size) { 98cee313d2SEric Christopherentry: 99cee313d2SEric Christopher %0 = alloca i32, i32 %size 100cee313d2SEric Christopher %1 = icmp ne i32 %a, 0 101cee313d2SEric Christopher br i1 %1, label %if, label %endif 102cee313d2SEric Christopher 103cee313d2SEric Christopherif: 104*a198d204SMatt Arsenault %2 = getelementptr i32, ptr %0, i32 1 105*a198d204SMatt Arsenault store i32 0, ptr %0 106*a198d204SMatt Arsenault store i32 1, ptr %2 107*a198d204SMatt Arsenault %3 = getelementptr i32, ptr %0, i32 %b 108*a198d204SMatt Arsenault %4 = load i32, ptr %3 109cee313d2SEric Christopher ret i32 %4 110cee313d2SEric Christopher 111cee313d2SEric Christopherendif: 112cee313d2SEric Christopher ret i32 0 113cee313d2SEric Christopher} 114cee313d2SEric Christopher 115cee313d2SEric Christopher; We also want to sink allocas that are not in the entry block. These 116cee313d2SEric Christopher; will already be considered as dynamically sized stack objects, so sinking 117cee313d2SEric Christopher; them does no further damage. 118cee313d2SEric Christopher 119cee313d2SEric Christopher; CHECK-LABEL: @alloca_sink_nonentry 120cee313d2SEric Christopher; CHECK: if0: 121cee313d2SEric Christopher; CHECK-NOT: alloca 122cee313d2SEric Christopher; CHECK: if: 123cee313d2SEric Christopher; CHECK-NEXT: alloca 124cee313d2SEric Christopherdefine i32 @alloca_sink_nonentry(i32 %a, i32 %b, i32 %c) { 125cee313d2SEric Christopherentry: 126cee313d2SEric Christopher %cmp = icmp ne i32 %c, 0 127cee313d2SEric Christopher br i1 %cmp, label %endif, label %if0 128cee313d2SEric Christopher 129cee313d2SEric Christopherif0: 130cee313d2SEric Christopher %0 = alloca i32 131cee313d2SEric Christopher %1 = icmp ne i32 %a, 0 132cee313d2SEric Christopher br i1 %1, label %if, label %endif 133cee313d2SEric Christopher 134cee313d2SEric Christopherif: 135*a198d204SMatt Arsenault %2 = getelementptr i32, ptr %0, i32 1 136*a198d204SMatt Arsenault store i32 0, ptr %0 137*a198d204SMatt Arsenault store i32 1, ptr %2 138*a198d204SMatt Arsenault %3 = getelementptr i32, ptr %0, i32 %b 139*a198d204SMatt Arsenault %4 = load i32, ptr %3 140cee313d2SEric Christopher ret i32 %4 141cee313d2SEric Christopher 142cee313d2SEric Christopherendif: 143cee313d2SEric Christopher ret i32 0 144cee313d2SEric Christopher} 145