[llvm] ea2e682 - [NFC][InstCombine] Tests for PHI-of-insertvalue's

Roman Lebedev via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 20 10:16:58 PDT 2020


Author: Roman Lebedev
Date: 2020-08-20T20:16:31+03:00
New Revision: ea2e682cc2f85594fccd7450b5e5e15294e7bf3f

URL: https://github.com/llvm/llvm-project/commit/ea2e682cc2f85594fccd7450b5e5e15294e7bf3f
DIFF: https://github.com/llvm/llvm-project/commit/ea2e682cc2f85594fccd7450b5e5e15294e7bf3f.diff

LOG: [NFC][InstCombine] Tests for PHI-of-insertvalue's

Currently we don't do anything about these,
neither in InstCombine, nor in SimplifyCFG's sinking.
These happen exceedingly rarely, but i've seen them in the cases where
PHI-aware aggregate reconstruction would have fired if not for them.

Added: 
    llvm/test/Transforms/InstCombine/phi-of-insertvalues.ll

Modified: 
    llvm/test/Transforms/InstCombine/phi-aware-aggregate-reconstruction.ll

Removed: 
    


################################################################################
diff  --git a/llvm/test/Transforms/InstCombine/phi-aware-aggregate-reconstruction.ll b/llvm/test/Transforms/InstCombine/phi-aware-aggregate-reconstruction.ll
index d1793343da6c..78c75c346dbc 100644
--- a/llvm/test/Transforms/InstCombine/phi-aware-aggregate-reconstruction.ll
+++ b/llvm/test/Transforms/InstCombine/phi-aware-aggregate-reconstruction.ll
@@ -477,3 +477,52 @@ end:
   %i8 = insertvalue { i32, i32 } %i7, i32 %i6, 1
   ret { i32, i32 } %i8
 }
+
+; The insertion of first element could have been split/hoisted into the predecessors.
+define { i32, i32 } @test9({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %c) {
+; CHECK-LABEL: @test9(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
+; CHECK:       left:
+; CHECK-NEXT:    [[I0:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT:%.*]], 0
+; CHECK-NEXT:    [[I1:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT]], 1
+; CHECK-NEXT:    [[I2:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 0
+; CHECK-NEXT:    call void @foo()
+; CHECK-NEXT:    br label [[END:%.*]]
+; CHECK:       right:
+; CHECK-NEXT:    [[I3:%.*]] = extractvalue { i32, i32 } [[AGG_RIGHT:%.*]], 0
+; CHECK-NEXT:    [[I4:%.*]] = extractvalue { i32, i32 } [[AGG_RIGHT]], 1
+; CHECK-NEXT:    [[I5:%.*]] = insertvalue { i32, i32 } undef, i32 [[I3]], 0
+; CHECK-NEXT:    call void @bar()
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    [[I6:%.*]] = phi { i32, i32 } [ [[I2]], [[LEFT]] ], [ [[I5]], [[RIGHT]] ]
+; CHECK-NEXT:    [[I7:%.*]] = phi i32 [ [[I1]], [[LEFT]] ], [ [[I4]], [[RIGHT]] ]
+; CHECK-NEXT:    call void @baz()
+; CHECK-NEXT:    [[I8:%.*]] = insertvalue { i32, i32 } [[I6]], i32 [[I7]], 1
+; CHECK-NEXT:    ret { i32, i32 } [[I8]]
+;
+entry:
+  br i1 %c, label %left, label %right
+
+left:
+  %i0 = extractvalue { i32, i32 } %agg_left, 0
+  %i1 = extractvalue { i32, i32 } %agg_left, 1
+  %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0
+  call void @foo()
+  br label %end
+
+right:
+  %i3 = extractvalue { i32, i32 } %agg_right, 0
+  %i4 = extractvalue { i32, i32 } %agg_right, 1
+  %i5 = insertvalue { i32, i32 } undef, i32 %i3, 0
+  call void @bar()
+  br label %end
+
+end:
+  %i6 = phi { i32, i32 } [ %i2, %left ], [ %i5, %right ]
+  %i7 = phi i32 [ %i1, %left ], [ %i4, %right ]
+  call void @baz()
+  %i8 = insertvalue { i32, i32 } %i6, i32 %i7, 1
+  ret { i32, i32 } %i8
+}

diff  --git a/llvm/test/Transforms/InstCombine/phi-of-insertvalues.ll b/llvm/test/Transforms/InstCombine/phi-of-insertvalues.ll
new file mode 100644
index 000000000000..dc9c45ca1294
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/phi-of-insertvalues.ll
@@ -0,0 +1,226 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -instcombine < %s | FileCheck %s
+
+declare void @usei32i32agg({ i32, i32 })
+
+; If we have a phi of insertvalues, we can sink it,
+; Here, we only need a PHI for inserted values.
+define { i32, i32 } @test0({ i32, i32 } %agg, i32 %val_left, i32 %val_right, i1 %c) {
+; CHECK-LABEL: @test0(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
+; CHECK:       left:
+; CHECK-NEXT:    [[I0:%.*]] = insertvalue { i32, i32 } [[AGG:%.*]], i32 [[VAL_LEFT:%.*]], 0
+; CHECK-NEXT:    br label [[END:%.*]]
+; CHECK:       right:
+; CHECK-NEXT:    [[I1:%.*]] = insertvalue { i32, i32 } [[AGG]], i32 [[VAL_RIGHT:%.*]], 0
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    [[R:%.*]] = phi { i32, i32 } [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ]
+; CHECK-NEXT:    ret { i32, i32 } [[R]]
+;
+entry:
+  br i1 %c, label %left, label %right
+
+left:
+  %i0 = insertvalue { i32, i32 } %agg, i32 %val_left, 0
+  br label %end
+
+right:
+  %i1 = insertvalue { i32, i32 } %agg, i32 %val_right, 0
+  br label %end
+
+end:
+  %r = phi { i32, i32 } [ %i0, %left ], [ %i1, %right ]
+  ret { i32, i32 } %r
+}
+
+; But only if the insertvalues have no extra uses
+define { i32, i32 } @test1_extrause0({ i32, i32 } %agg, i32 %val_left, i32 %val_right, i1 %c) {
+; CHECK-LABEL: @test1_extrause0(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
+; CHECK:       left:
+; CHECK-NEXT:    [[I0:%.*]] = insertvalue { i32, i32 } [[AGG:%.*]], i32 [[VAL_LEFT:%.*]], 0
+; CHECK-NEXT:    call void @usei32i32agg({ i32, i32 } [[I0]])
+; CHECK-NEXT:    br label [[END:%.*]]
+; CHECK:       right:
+; CHECK-NEXT:    [[I1:%.*]] = insertvalue { i32, i32 } [[AGG]], i32 [[VAL_RIGHT:%.*]], 0
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    [[R:%.*]] = phi { i32, i32 } [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ]
+; CHECK-NEXT:    ret { i32, i32 } [[R]]
+;
+entry:
+  br i1 %c, label %left, label %right
+
+left:
+  %i0 = insertvalue { i32, i32 } %agg, i32 %val_left, 0
+  call void  @usei32i32agg({ i32, i32 } %i0 )
+  br label %end
+
+right:
+  %i1 = insertvalue { i32, i32 } %agg, i32 %val_right, 0
+  br label %end
+
+end:
+  %r = phi { i32, i32 } [ %i0, %left ], [ %i1, %right ]
+  ret { i32, i32 } %r
+}
+define { i32, i32 } @test2_extrause1({ i32, i32 } %agg, i32 %val_left, i32 %val_right, i1 %c) {
+; CHECK-LABEL: @test2_extrause1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
+; CHECK:       left:
+; CHECK-NEXT:    [[I0:%.*]] = insertvalue { i32, i32 } [[AGG:%.*]], i32 [[VAL_LEFT:%.*]], 0
+; CHECK-NEXT:    br label [[END:%.*]]
+; CHECK:       right:
+; CHECK-NEXT:    [[I1:%.*]] = insertvalue { i32, i32 } [[AGG]], i32 [[VAL_RIGHT:%.*]], 0
+; CHECK-NEXT:    call void @usei32i32agg({ i32, i32 } [[I1]])
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    [[R:%.*]] = phi { i32, i32 } [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ]
+; CHECK-NEXT:    ret { i32, i32 } [[R]]
+;
+entry:
+  br i1 %c, label %left, label %right
+
+left:
+  %i0 = insertvalue { i32, i32 } %agg, i32 %val_left, 0
+  br label %end
+
+right:
+  %i1 = insertvalue { i32, i32 } %agg, i32 %val_right, 0
+  call void  @usei32i32agg({ i32, i32 } %i1 )
+  br label %end
+
+end:
+  %r = phi { i32, i32 } [ %i0, %left ], [ %i1, %right ]
+  ret { i32, i32 } %r
+}
+define { i32, i32 } @test3_extrause2({ i32, i32 } %agg, i32 %val_left, i32 %val_right, i1 %c) {
+; CHECK-LABEL: @test3_extrause2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
+; CHECK:       left:
+; CHECK-NEXT:    [[I0:%.*]] = insertvalue { i32, i32 } [[AGG:%.*]], i32 [[VAL_LEFT:%.*]], 0
+; CHECK-NEXT:    call void @usei32i32agg({ i32, i32 } [[I0]])
+; CHECK-NEXT:    br label [[END:%.*]]
+; CHECK:       right:
+; CHECK-NEXT:    [[I1:%.*]] = insertvalue { i32, i32 } [[AGG]], i32 [[VAL_RIGHT:%.*]], 0
+; CHECK-NEXT:    call void @usei32i32agg({ i32, i32 } [[I1]])
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    [[R:%.*]] = phi { i32, i32 } [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ]
+; CHECK-NEXT:    ret { i32, i32 } [[R]]
+;
+entry:
+  br i1 %c, label %left, label %right
+
+left:
+  %i0 = insertvalue { i32, i32 } %agg, i32 %val_left, 0
+  call void  @usei32i32agg({ i32, i32 } %i0 )
+  br label %end
+
+right:
+  %i1 = insertvalue { i32, i32 } %agg, i32 %val_right, 0
+  call void  @usei32i32agg({ i32, i32 } %i1 )
+  br label %end
+
+end:
+  %r = phi { i32, i32 } [ %i0, %left ], [ %i1, %right ]
+  ret { i32, i32 } %r
+}
+
+; Here, we only need a PHI for base aggregate
+define { i32, i32 } @test4({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i32 %val, i1 %c) {
+; CHECK-LABEL: @test4(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
+; CHECK:       left:
+; CHECK-NEXT:    [[I0:%.*]] = insertvalue { i32, i32 } [[AGG_LEFT:%.*]], i32 [[VAL:%.*]], 0
+; CHECK-NEXT:    br label [[END:%.*]]
+; CHECK:       right:
+; CHECK-NEXT:    [[I1:%.*]] = insertvalue { i32, i32 } [[AGG_RIGHT:%.*]], i32 [[VAL]], 0
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    [[R:%.*]] = phi { i32, i32 } [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ]
+; CHECK-NEXT:    ret { i32, i32 } [[R]]
+;
+entry:
+  br i1 %c, label %left, label %right
+
+left:
+  %i0 = insertvalue { i32, i32 } %agg_left, i32 %val, 0
+  br label %end
+
+right:
+  %i1 = insertvalue { i32, i32 } %agg_right, i32 %val, 0
+  br label %end
+
+end:
+  %r = phi { i32, i32 } [ %i0, %left ], [ %i1, %right ]
+  ret { i32, i32 } %r
+}
+
+; Here, we need a PHI for both the base and the inserted value
+define { i32, i32 } @test5({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i32 %val_left, i32 %val_right, i1 %c) {
+; CHECK-LABEL: @test5(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
+; CHECK:       left:
+; CHECK-NEXT:    [[I0:%.*]] = insertvalue { i32, i32 } [[AGG_LEFT:%.*]], i32 [[VAL_LEFT:%.*]], 0
+; CHECK-NEXT:    br label [[END:%.*]]
+; CHECK:       right:
+; CHECK-NEXT:    [[I1:%.*]] = insertvalue { i32, i32 } [[AGG_RIGHT:%.*]], i32 [[VAL_RIGHT:%.*]], 0
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    [[R:%.*]] = phi { i32, i32 } [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ]
+; CHECK-NEXT:    ret { i32, i32 } [[R]]
+;
+entry:
+  br i1 %c, label %left, label %right
+
+left:
+  %i0 = insertvalue { i32, i32 } %agg_left, i32 %val_left, 0
+  br label %end
+
+right:
+  %i1 = insertvalue { i32, i32 } %agg_right, i32 %val_right, 0
+  br label %end
+
+end:
+  %r = phi { i32, i32 } [ %i0, %left ], [ %i1, %right ]
+  ret { i32, i32 } %r
+}
+
+; But the indicies must match
+define { i32, i32 } @test6({ i32, i32 } %agg, i32 %val_left, i32 %val_right, i1 %c) {
+; CHECK-LABEL: @test6(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
+; CHECK:       left:
+; CHECK-NEXT:    [[I0:%.*]] = insertvalue { i32, i32 } [[AGG:%.*]], i32 [[VAL_LEFT:%.*]], 0
+; CHECK-NEXT:    br label [[END:%.*]]
+; CHECK:       right:
+; CHECK-NEXT:    [[I1:%.*]] = insertvalue { i32, i32 } [[AGG]], i32 [[VAL_RIGHT:%.*]], 1
+; CHECK-NEXT:    br label [[END]]
+; CHECK:       end:
+; CHECK-NEXT:    [[R:%.*]] = phi { i32, i32 } [ [[I0]], [[LEFT]] ], [ [[I1]], [[RIGHT]] ]
+; CHECK-NEXT:    ret { i32, i32 } [[R]]
+;
+entry:
+  br i1 %c, label %left, label %right
+
+left:
+  %i0 = insertvalue { i32, i32 } %agg, i32 %val_left, 0
+  br label %end
+
+right:
+  %i1 = insertvalue { i32, i32 } %agg, i32 %val_right, 1
+  br label %end
+
+end:
+  %r = phi { i32, i32 } [ %i0, %left ], [ %i1, %right ]
+  ret { i32, i32 } %r
+}


        


More information about the llvm-commits mailing list