; Basic testcases - these are only tested by inspection, but illustrate the ; basic cases PRE can handle. ; ; RUN: llvm-as < %s | opt -pre -disable-output declare void %use(int) declare int %get() void %test0(int %A, int %B) { ;; Fully redundant %X = add int %A, %B %Y = add int %A, %B call void %use(int %X) call void %use(int %Y) ret void } void %test1(int %cond, int %A, int %B) { switch int %cond, label %Out [ int 1, label %B1 int 2, label %B2 int 3, label %Cont ] B1: %X1 = add int %A, %B call void %use(int %X1) br label %Cont B2: %X2 = add int %A, %B call void %use(int %X2) br label %Cont Cont: br label %Next Next: %X3 = add int %A, %B call void %use(int %X3) br label %Out Out: ret void } void %testloop(bool %cond, int %A, int %B) { br label %Loop Loop: %C = add int %A, %B ; loop invariant call void %use(int %C) %D = add int %C, %B call void %use(int %D) br bool %cond, label %Loop, label %Exit Exit: ret void } void %test3(bool %cond, int %A, int %B) { br bool %cond, label %A, label %B A: %C = add int %A, %B call void %use(int %C) br label %Merge B: %D = add int %A, %B call void %use(int %D) br label %Merge Merge: %E = add int %A, %B call void %use(int %E) ret void } void %test4(bool %cond, int %A, int %B) { br bool %cond, label %A, label %B A: br label %Merge B: %D = add int %A, %B call void %use(int %D) br label %Merge Merge: %E = add int %A, %B call void %use(int %E) ret void } int %test5(bool %cond, int %A, int %B) { br label %Loop Loop: br bool %cond, label %A, label %B A: br label %Merge B: %D = add int %A, %B call void %use(int %D) br label %Merge Merge: br bool %cond, label %Loop, label %Out Out: %E = add int %A, %B ret int %E } void %test6(bool %cond, int %A, int %B) { br bool %cond, label %A1, label %Def A1: br label %Around Def: %C = add int %A, %B call void %use(int %C) br bool %cond, label %F1, label %F2 F1: br label %Around F2: br label %Y Around: br label %Y Y: %D = add int %A, %B call void %use(int %D) ret void } void %testloop-load(bool %cond, int* %P, int* %Q) { br label %Loop Loop: store int 5, int* %Q ;; Q may alias P %D = load int* %P ;; Should not hoist load out of loop call void %use(int %D) br bool %cond, label %Loop, label %Exit Exit: ret void } void %test7(bool %cond) { ;; Test anticipatibility br label %Loop Loop: %A = call int %get() %B = add int %A, %A ; Cannot hoist from loop call void %use(int %B) br bool %cond, label %Loop, label %Exit Exit: ret void } void %test8(bool %cond, int %A, int %B) { ;; Test irreducible loop br bool %cond, label %LoopHead, label %LoopMiddle LoopHead: %C = add int %A, %B ; Should hoist from loop call void %use(int %C) br label %LoopMiddle LoopMiddle: br bool %cond, label %LoopHead, label %Exit Exit: %D = add int %A, %B call void %use(int %D) ret void } void %test9(bool %cond, int %A, int %B) { ;; Test irreducible loop br bool %cond, label %LoopHead, label %LoopMiddle LoopHead: call int %get() ; random function call br label %LoopMiddle LoopMiddle: %C = add int %A, %B ; Should hoist from loop call void %use(int %C) br bool %cond, label %LoopHead, label %Exit Exit: ret void }