| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt -passes=newgvn -enable-phi-of-ops=true -S -o - %s | FileCheck %s |
| |
| define void @hoisted-load(ptr %p, ptr %q) { |
| ; CHECK-LABEL: @hoisted-load( |
| ; CHECK-NEXT: bb56: |
| ; CHECK-NEXT: [[N60:%.*]] = load i8, ptr [[P:%.*]], align 1 |
| ; CHECK-NEXT: br label [[BB57:%.*]] |
| ; CHECK: bb57: |
| ; CHECK-NEXT: [[PHIOFOPS:%.*]] = phi i1 [ true, [[BB56:%.*]] ], [ [[N62:%.*]], [[BB229:%.*]] ] |
| ; CHECK-NEXT: [[N59:%.*]] = phi i1 [ false, [[BB229]] ], [ true, [[BB56]] ] |
| ; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ 0, [[BB56]] ], [ [[INC:%.*]], [[BB229]] ] |
| ; CHECK-NEXT: [[N62]] = icmp ne i8 [[N60]], 2 |
| ; CHECK-NEXT: br i1 [[PHIOFOPS]], label [[BB229]], label [[BB237:%.*]] |
| ; CHECK: bb229: |
| ; CHECK-NEXT: [[INC]] = add i8 [[IDX]], 1 |
| ; CHECK-NEXT: store i8 [[INC]], ptr [[Q:%.*]], align 1 |
| ; CHECK-NEXT: br label [[BB57]] |
| ; CHECK: bb237: |
| ; CHECK-NEXT: ret void |
| ; |
| bb56: |
| %n60 = load i8, ptr %p |
| br label %bb57 |
| |
| bb57: |
| %n59 = phi i1 [ false, %bb229 ], [ true, %bb56 ] |
| %idx = phi i8 [0, %bb56], [%inc, %bb229] |
| %n62 = icmp ne i8 %n60, 2 |
| %n63 = or i1 %n59, %n62 |
| br i1 %n63, label %bb229, label %bb237 |
| |
| bb229: |
| %inc = add i8 %idx, 1 |
| store i8 %inc, ptr %q |
| br label %bb57 |
| |
| bb237: |
| ret void |
| } |
| |
| define void @store-in-loop(ptr %p, ptr %q) { |
| ; CHECK-LABEL: @store-in-loop( |
| ; CHECK-NEXT: bb56: |
| ; CHECK-NEXT: br label [[BB57:%.*]] |
| ; CHECK: bb57: |
| ; CHECK-NEXT: [[N59:%.*]] = phi i1 [ false, [[BB229:%.*]] ], [ true, [[BB56:%.*]] ] |
| ; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ 0, [[BB56]] ], [ [[INC:%.*]], [[BB229]] ] |
| ; CHECK-NEXT: [[N60:%.*]] = load i8, ptr [[P:%.*]], align 1 |
| ; CHECK-NEXT: [[N62:%.*]] = icmp ne i8 [[N60]], 2 |
| ; CHECK-NEXT: [[N63:%.*]] = or i1 [[N59]], [[N62]] |
| ; CHECK-NEXT: br i1 [[N63]], label [[BB229]], label [[BB237:%.*]] |
| ; CHECK: bb229: |
| ; CHECK-NEXT: [[INC]] = add i8 [[IDX]], 1 |
| ; CHECK-NEXT: store i8 [[INC]], ptr [[Q:%.*]], align 1 |
| ; CHECK-NEXT: br label [[BB57]] |
| ; CHECK: bb237: |
| ; CHECK-NEXT: ret void |
| ; |
| bb56: |
| br label %bb57 |
| |
| bb57: |
| %n59 = phi i1 [ false, %bb229 ], [ true, %bb56 ] |
| %idx = phi i8 [0, %bb56], [%inc, %bb229] |
| %n60 = load i8, ptr %p |
| %n62 = icmp ne i8 %n60, 2 |
| %n63 = or i1 %n59, %n62 |
| br i1 %n63, label %bb229, label %bb237 |
| |
| bb229: |
| %inc = add i8 %idx, 1 |
| store i8 %inc, ptr %q |
| br label %bb57 |
| |
| bb237: |
| ret void |
| } |
| |
| ; TODO: we should support this case |
| define void @no-alias-store-in-loop(ptr noalias %p, ptr noalias %q) { |
| ; CHECK-LABEL: @no-alias-store-in-loop( |
| ; CHECK-NEXT: bb56: |
| ; CHECK-NEXT: br label [[BB57:%.*]] |
| ; CHECK: bb57: |
| ; CHECK-NEXT: [[N59:%.*]] = phi i1 [ false, [[BB229:%.*]] ], [ true, [[BB56:%.*]] ] |
| ; CHECK-NEXT: [[IDX:%.*]] = phi i8 [ 0, [[BB56]] ], [ [[INC:%.*]], [[BB229]] ] |
| ; CHECK-NEXT: [[N60:%.*]] = load i8, ptr [[P:%.*]], align 1 |
| ; CHECK-NEXT: [[N62:%.*]] = icmp ne i8 [[N60]], 2 |
| ; CHECK-NEXT: [[N63:%.*]] = or i1 [[N59]], [[N62]] |
| ; CHECK-NEXT: br i1 [[N63]], label [[BB229]], label [[BB237:%.*]] |
| ; CHECK: bb229: |
| ; CHECK-NEXT: [[INC]] = add i8 [[IDX]], 1 |
| ; CHECK-NEXT: store i8 [[INC]], ptr [[Q:%.*]], align 1 |
| ; CHECK-NEXT: br label [[BB57]] |
| ; CHECK: bb237: |
| ; CHECK-NEXT: ret void |
| ; |
| bb56: |
| br label %bb57 |
| |
| bb57: |
| %n59 = phi i1 [ false, %bb229 ], [ true, %bb56 ] |
| %idx = phi i8 [0, %bb56], [%inc, %bb229] |
| %n60 = load i8, ptr %p |
| %n62 = icmp ne i8 %n60, 2 |
| %n63 = or i1 %n59, %n62 |
| br i1 %n63, label %bb229, label %bb237 |
| |
| bb229: |
| %inc = add i8 %idx, 1 |
| store i8 %inc, ptr %q |
| br label %bb57 |
| |
| bb237: |
| ret void |
| } |
| |
| define void @function-in-loop(ptr %p) { |
| ; CHECK-LABEL: @function-in-loop( |
| ; CHECK-NEXT: bb56: |
| ; CHECK-NEXT: br label [[BB57:%.*]] |
| ; CHECK: bb57: |
| ; CHECK-NEXT: [[N59:%.*]] = phi i1 [ false, [[BB229:%.*]] ], [ true, [[BB56:%.*]] ] |
| ; CHECK-NEXT: [[N60:%.*]] = load i8, ptr [[P:%.*]], align 1 |
| ; CHECK-NEXT: [[N62:%.*]] = icmp ne i8 [[N60]], 2 |
| ; CHECK-NEXT: [[N63:%.*]] = or i1 [[N59]], [[N62]] |
| ; CHECK-NEXT: br i1 [[N63]], label [[BB229]], label [[BB237:%.*]] |
| ; CHECK: bb229: |
| ; CHECK-NEXT: call void @f() |
| ; CHECK-NEXT: br label [[BB57]] |
| ; CHECK: bb237: |
| ; CHECK-NEXT: ret void |
| ; |
| bb56: |
| br label %bb57 |
| |
| bb57: |
| %n59 = phi i1 [ false, %bb229 ], [ true, %bb56 ] |
| %n60 = load i8, ptr %p |
| %n62 = icmp ne i8 %n60, 2 |
| %n63 = or i1 %n59, %n62 |
| br i1 %n63, label %bb229, label %bb237 |
| |
| bb229: |
| call void @f() |
| br label %bb57 |
| |
| bb237: |
| ret void |
| } |
| |
| ; TODO: we should support this case |
| define void @nowrite-function-in-loop(ptr %p) { |
| ; CHECK-LABEL: @nowrite-function-in-loop( |
| ; CHECK-NEXT: bb56: |
| ; CHECK-NEXT: br label [[BB57:%.*]] |
| ; CHECK: bb57: |
| ; CHECK-NEXT: [[N59:%.*]] = phi i1 [ false, [[BB229:%.*]] ], [ true, [[BB56:%.*]] ] |
| ; CHECK-NEXT: [[N60:%.*]] = load i8, ptr [[P:%.*]], align 1 |
| ; CHECK-NEXT: [[N62:%.*]] = icmp ne i8 [[N60]], 2 |
| ; CHECK-NEXT: [[N63:%.*]] = or i1 [[N59]], [[N62]] |
| ; CHECK-NEXT: br i1 [[N63]], label [[BB229]], label [[BB237:%.*]] |
| ; CHECK: bb229: |
| ; CHECK-NEXT: call void @f() #[[ATTR0:[0-9]+]] |
| ; CHECK-NEXT: br label [[BB57]] |
| ; CHECK: bb237: |
| ; CHECK-NEXT: ret void |
| ; |
| bb56: |
| br label %bb57 |
| |
| bb57: |
| %n59 = phi i1 [ false, %bb229 ], [ true, %bb56 ] |
| %n60 = load i8, ptr %p |
| %n62 = icmp ne i8 %n60, 2 |
| %n63 = or i1 %n59, %n62 |
| br i1 %n63, label %bb229, label %bb237 |
| |
| bb229: |
| call void @f() inaccessiblememonly |
| br label %bb57 |
| |
| bb237: |
| ret void |
| } |
| |
| declare void @f() |
| |
| define void @issfeoperand(ptr nocapture readonly %array, i1 %cond1, i1 %cond2, ptr nocapture readonly %p1, ptr nocapture writeonly %p2, ptr nocapture writeonly %p3) local_unnamed_addr #0 { |
| ; CHECK-LABEL: @issfeoperand( |
| ; CHECK-NEXT: for.body: |
| ; CHECK-NEXT: br i1 [[COND1:%.*]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] |
| ; CHECK: cond.true: |
| ; CHECK-NEXT: [[ARRAYIDX31:%.*]] = getelementptr inbounds [3 x [2 x [1 x i8]]], ptr [[ARRAY:%.*]], i64 109, i64 0, i64 0, i64 undef |
| ; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[ARRAYIDX31]], align 1 |
| ; CHECK-NEXT: br label [[COND_FALSE]] |
| ; CHECK: cond.false: |
| ; CHECK-NEXT: [[PHI1:%.*]] = phi i8 [ [[LD1]], [[COND_TRUE]] ], [ 0, [[FOR_BODY:%.*]] ] |
| ; CHECK-NEXT: [[ARRAYIDX42:%.*]] = getelementptr inbounds [3 x [2 x [1 x i8]]], ptr [[ARRAY]], i64 109, i64 0, i64 0, i64 undef |
| ; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[ARRAYIDX42]], align 1 |
| ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8 [[LD2]], [[PHI1]] |
| ; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP1]] to i32 |
| ; CHECK-NEXT: store i32 [[ZEXT]], ptr [[P2:%.*]], align 4 |
| ; CHECK-NEXT: br i1 [[COND2:%.*]], label [[COND_END:%.*]], label [[EXIT:%.*]] |
| ; CHECK: cond.end: |
| ; CHECK-NEXT: [[LD3:%.*]] = load i16, ptr [[P1:%.*]], align 2 |
| ; CHECK-NEXT: [[SEXT:%.*]] = sext i16 [[LD3]] to i32 |
| ; CHECK-NEXT: br label [[EXIT]] |
| ; CHECK: exit: |
| ; CHECK-NEXT: [[PHI2:%.*]] = phi i32 [ [[SEXT]], [[COND_END]] ], [ 0, [[COND_FALSE]] ] |
| ; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[LD2]], 0 |
| ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP2]], i32 [[PHI2]], i32 0 |
| ; CHECK-NEXT: store i32 [[SEL]], ptr [[P3:%.*]], align 4 |
| ; CHECK-NEXT: ret void |
| ; |
| for.body: |
| br i1 %cond1, label %cond.true, label %cond.false |
| |
| cond.true: ; preds = %for.body |
| %arrayidx31 = getelementptr inbounds [3 x [2 x [1 x i8]]], ptr %array, i64 109, i64 0, i64 0, i64 undef |
| %ld1 = load i8, ptr %arrayidx31, align 1 |
| br label %cond.false |
| |
| cond.false: ; preds = %cond.true, %for.body |
| %phi1 = phi i8 [ %ld1, %cond.true ], [ 0, %for.body ] |
| %arrayidx42 = getelementptr inbounds [3 x [2 x [1 x i8]]], ptr %array, i64 109, i64 0, i64 0, i64 undef |
| %ld2 = load i8, ptr %arrayidx42, align 1 |
| %cmp1 = icmp ult i8 %ld2, %phi1 |
| %zext = zext i1 %cmp1 to i32 |
| store i32 %zext, ptr %p2, align 4 |
| br i1 %cond2, label %cond.end, label %exit |
| |
| cond.end: ; preds = %cond.false |
| %ld3 = load i16, ptr %p1, align 2 |
| %sext = sext i16 %ld3 to i32 |
| br label %exit |
| |
| exit: ; preds = %cond.end, %cond.false |
| %phi2 = phi i32 [ %sext, %cond.end ], [ 0, %cond.false ] |
| %cmp2 = icmp eq i8 %ld2, 0 |
| %sel = select i1 %cmp2, i32 %phi2, i32 0 |
| store i32 %sel, ptr %p3, align 4 |
| ret void |
| } |