mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[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.
This commit is contained in:
parent
efb79ce4ea
commit
c0a69dfec4
@ -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
|
||||
}
|
||||
|
226
test/Transforms/InstCombine/phi-of-insertvalues.ll
Normal file
226
test/Transforms/InstCombine/phi-of-insertvalues.ll
Normal file
@ -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
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user