forked from OSchip/llvm-project
[InstSimplify][EarlyCSE] Try to CSE PHI nodes in the same basic block
Apparently, we don't do this, neither in EarlyCSE, nor in InstSimplify, nor in (old) GVN, but do in NewGVN and SimplifyCFG of all places.. While i could teach EarlyCSE how to hash PHI nodes, we can't really do much (anything?) even if we find two identical PHI nodes in different basic blocks, same-BB case is the interesting one, and if we teach InstSimplify about it (which is what i wanted originally, https://reviews.llvm.org/D86530), we get EarlyCSE support for free. So i would think this is pretty uncontroversial. On vanilla llvm test-suite + RawSpeed, this has the following effects: ``` | statistic name | baseline | proposed | Δ | % | \|%\| | |----------------------------------------------------|-----------|-----------|-------:|---------:|---------:| | instsimplify.NumPHICSE | 0 | 23779 | 23779 | 0.00% | 0.00% | | asm-printer.EmittedInsts | 7942328 | 7942392 | 64 | 0.00% | 0.00% | | assembler.ObjectBytes | 273069192 | 273084704 | 15512 | 0.01% | 0.01% | | correlated-value-propagation.NumPhis | 18412 | 18539 | 127 | 0.69% | 0.69% | | early-cse.NumCSE | 2183283 | 2183227 | -56 | 0.00% | 0.00% | | early-cse.NumSimplify | 550105 | 542090 | -8015 | -1.46% | 1.46% | | instcombine.NumAggregateReconstructionsSimplified | 73 | 4506 | 4433 | 6072.60% | 6072.60% | | instcombine.NumCombined | 3640264 | 3664769 | 24505 | 0.67% | 0.67% | | instcombine.NumDeadInst | 1778193 | 1783183 | 4990 | 0.28% | 0.28% | | instcount.NumCallInst | 1758401 | 1758799 | 398 | 0.02% | 0.02% | | instcount.NumInvokeInst | 59478 | 59502 | 24 | 0.04% | 0.04% | | instcount.NumPHIInst | 330557 | 330533 | -24 | -0.01% | 0.01% | | instcount.TotalInsts | 8831952 | 8832286 | 334 | 0.00% | 0.00% | | simplifycfg.NumInvokes | 4300 | 4410 | 110 | 2.56% | 2.56% | | simplifycfg.NumSimpl | 1019808 | 999607 | -20201 | -1.98% | 1.98% | ``` I.e. it fires ~24k times, causes +110 (+2.56%) more `invoke` -> `call` transforms, and counter-intuitively results in *more* instructions total. That being said, the PHI count doesn't decrease that much, and looking at some examples, it seems at least some of them were previously getting PHI CSE'd in SimplifyCFG of all places.. I'm adjusting `Instruction::isIdenticalToWhenDefined()` at the same time. As a comment in `InstCombinerImpl::visitPHINode()` already stated, there are no guarantees on the ordering of the operands of a PHI node, so if we just naively compare them, we may false-negatively say that the nodes are not equal when the only difference is operand order, which is especially important since the fold is in InstSimplify, so we can't rely on InstCombine sorting them beforehand. Fixing this for the general case is costly (geomean +0.02%), and does not appear to catch anything in test-suite, but for the same-BB case, it's trivial, so let's fix at least that. As per http://llvm-compile-time-tracker.com/compare.php?from=04879086b44348cad600a0a1ccbe1f7776cc3cf9&to=82bdedb888b945df1e9f130dd3ac4dd3c96e2925&stat=instructions this appears to cause geomean +0.03% compile time increase (regression), but geomean -0.01%..-0.04% code size decrease (improvement).
This commit is contained in:
parent
94d3dd8b08
commit
6102310d81
|
@ -4403,6 +4403,19 @@ Value *llvm::SimplifyExtractElementInst(Value *Vec, Value *Idx,
|
|||
|
||||
/// See if we can fold the given phi. If not, returns null.
|
||||
static Value *SimplifyPHINode(PHINode *PN, const SimplifyQuery &Q) {
|
||||
// Is there an identical PHI node before this one in this basic block?
|
||||
for (PHINode &Src : PN->getParent()->phis()) {
|
||||
// Once we've reached the PHI node we've been asked about, stop looking.
|
||||
if (&Src == PN)
|
||||
break;
|
||||
// If the previous PHI is currently trivially dead, ignore it,
|
||||
// it might have been already recorded as being dead.
|
||||
if (Src.use_empty())
|
||||
continue;
|
||||
if (PN->isIdenticalToWhenDefined(&Src))
|
||||
return &Src;
|
||||
}
|
||||
|
||||
// If all of the PHI's incoming values are the same then replace the PHI node
|
||||
// with the common value.
|
||||
Value *CommonValue = nullptr;
|
||||
|
|
|
@ -483,17 +483,33 @@ bool Instruction::isIdenticalToWhenDefined(const Instruction *I) const {
|
|||
if (getNumOperands() == 0 && I->getNumOperands() == 0)
|
||||
return haveSameSpecialState(this, I);
|
||||
|
||||
// PHI nodes are special.
|
||||
if (const PHINode *thisPHI = dyn_cast<PHINode>(this)) {
|
||||
const PHINode *otherPHI = cast<PHINode>(I);
|
||||
// PHI nodes don't nessesairly have their operands in the same order,
|
||||
// so we shouldn't just compare ranges of incoming blocks/values.
|
||||
|
||||
// If both PHI's are in the same basic block, which is the most interesting
|
||||
// case, we know they must have identical predecessor list,
|
||||
// so we only need to check the incoming values.
|
||||
if (thisPHI->getParent() == otherPHI->getParent()) {
|
||||
return all_of(thisPHI->blocks(), [thisPHI, otherPHI](BasicBlock *PredBB) {
|
||||
return thisPHI->getIncomingValueForBlock(PredBB) ==
|
||||
otherPHI->getIncomingValueForBlock(PredBB);
|
||||
});
|
||||
}
|
||||
|
||||
// Otherwise, let's just naively compare operands/blocks.
|
||||
return std::equal(op_begin(), op_end(), I->op_begin()) &&
|
||||
std::equal(thisPHI->block_begin(), thisPHI->block_end(),
|
||||
otherPHI->block_begin());
|
||||
}
|
||||
|
||||
// We have two instructions of identical opcode and #operands. Check to see
|
||||
// if all operands are the same.
|
||||
if (!std::equal(op_begin(), op_end(), I->op_begin()))
|
||||
return false;
|
||||
|
||||
if (const PHINode *thisPHI = dyn_cast<PHINode>(this)) {
|
||||
const PHINode *otherPHI = cast<PHINode>(I);
|
||||
return std::equal(thisPHI->block_begin(), thisPHI->block_end(),
|
||||
otherPHI->block_begin());
|
||||
}
|
||||
|
||||
return haveSameSpecialState(this, I);
|
||||
}
|
||||
|
||||
|
|
|
@ -57,16 +57,15 @@ entry:
|
|||
define <2 x i64 addrspace(1)*> @test3(i1 %cnd, <2 x i64 addrspace(1)*>* %ptr) gc "statepoint-example" {
|
||||
; CHECK-LABEL: test3:
|
||||
; CHECK: # %bb.0: # %entry
|
||||
; CHECK-NEXT: subq $40, %rsp
|
||||
; CHECK-NEXT: .cfi_def_cfa_offset 48
|
||||
; CHECK-NEXT: subq $24, %rsp
|
||||
; CHECK-NEXT: .cfi_def_cfa_offset 32
|
||||
; CHECK-NEXT: testb $1, %dil
|
||||
; CHECK-NEXT: movaps (%rsi), %xmm0
|
||||
; CHECK-NEXT: movaps %xmm0, (%rsp)
|
||||
; CHECK-NEXT: movaps %xmm0, {{[0-9]+}}(%rsp)
|
||||
; CHECK-NEXT: callq do_safepoint
|
||||
; CHECK-NEXT: .Ltmp2:
|
||||
; CHECK-NEXT: movaps (%rsp), %xmm0
|
||||
; CHECK-NEXT: addq $40, %rsp
|
||||
; CHECK-NEXT: addq $24, %rsp
|
||||
; CHECK-NEXT: .cfi_def_cfa_offset 8
|
||||
; CHECK-NEXT: retq
|
||||
entry:
|
||||
|
@ -115,7 +114,7 @@ entry:
|
|||
; Check that we can lower a constant typed as i128 correctly. We don't have
|
||||
; a representation of larger than 64 bit constant in the StackMap format. At
|
||||
; the moment, this simply means spilling them, but there's a potential
|
||||
; optimization for values representable as sext(Con64).
|
||||
; optimization for values representable as sext(Con64).
|
||||
define void @test5() gc "statepoint-example" {
|
||||
; CHECK-LABEL: test5:
|
||||
; CHECK: # %bb.0: # %entry
|
||||
|
@ -172,31 +171,17 @@ entry:
|
|||
; CHECK: .long 0
|
||||
|
||||
; CHECK: .Ltmp2-test3
|
||||
; Check for the four spill slots
|
||||
; Stack Maps: Loc 3: Indirect 7+16 [encoding: .byte 3, .byte 0, .short 16, .short 7, .short 0, .int 16]
|
||||
; Stack Maps: Loc 4: Indirect 7+16 [encoding: .byte 3, .byte 0, .short 16, .short 7, .short 0, .int 16]
|
||||
; Stack Maps: Loc 5: Indirect 7+16 [encoding: .byte 3, .byte 0, .short 16, .short 7, .short 0, .int 16]
|
||||
; Stack Maps: Loc 6: Indirect 7+0 [encoding: .byte 3, .byte 0, .short 16, .short 7, .short 0, .int 0]
|
||||
; Check for the two spill slots
|
||||
; Stack Maps: Loc 3: Indirect 7+0 [encoding: .byte 3, .byte 0, .short 16, .short 7, .short 0, .int 0]
|
||||
; Stack Maps: Loc 4: Indirect 7+0 [encoding: .byte 3, .byte 0, .short 16, .short 7, .short 0, .int 0]
|
||||
; CHECK: .byte 3
|
||||
; CHECK: .byte 0
|
||||
; CHECK: .short 16
|
||||
; CHECK: .short 7
|
||||
; CHECK: .short 0
|
||||
; CHECK: .long 16
|
||||
; CHECK: .long 0
|
||||
; CHECK: .byte 3
|
||||
; CHECK: .byte 0
|
||||
; CHECK: .short 16
|
||||
; CHECK: .short 7
|
||||
; CHECK: .short 0
|
||||
; CHECK: .long 16
|
||||
; CHECK: .byte 3
|
||||
; CHECK: .byte 0
|
||||
; CHECK: .short 16
|
||||
; CHECK: .short 7
|
||||
; CHECK: .short 0
|
||||
; CHECK: .long 16
|
||||
; CHECK: .byte 3
|
||||
; CHECK: .byte 0
|
||||
; CHECK: .byte 0
|
||||
; CHECK: .short 16
|
||||
; CHECK: .short 7
|
||||
; CHECK: .short 0
|
||||
|
|
|
@ -13,9 +13,8 @@ define void @test0(i32 %v0, i32 %v1, i1 %c, i32* %d0, i32* %d1) {
|
|||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
|
||||
; CHECK-NEXT: [[I1:%.*]] = phi i32 [ [[V0]], [[B0]] ], [ [[V1]], [[B1]] ]
|
||||
; CHECK-NEXT: store i32 [[I0]], i32* [[D0:%.*]], align 4
|
||||
; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4
|
||||
; CHECK-NEXT: store i32 [[I0]], i32* [[D1:%.*]], align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
|
@ -46,9 +45,8 @@ define void @test1(i32 %v0, i32 %v1, i1 %c, i32* %d0, i32* %d1) {
|
|||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
|
||||
; CHECK-NEXT: [[I1:%.*]] = phi i32 [ [[V1]], [[B1]] ], [ [[V0]], [[B0]] ]
|
||||
; CHECK-NEXT: store i32 [[I0]], i32* [[D0:%.*]], align 4
|
||||
; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4
|
||||
; CHECK-NEXT: store i32 [[I0]], i32* [[D1:%.*]], align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
|
@ -141,9 +139,8 @@ define void @negative_test4(i32 %v0, i32 %v1, i1 %c, i32* %d0, i32* %d1) {
|
|||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
|
||||
; CHECK-NEXT: [[I1:%.*]] = phi i32 [ [[V1]], [[B1]] ], [ [[V0]], [[B0]] ]
|
||||
; CHECK-NEXT: store i32 [[I0]], i32* [[D0:%.*]], align 4
|
||||
; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4
|
||||
; CHECK-NEXT: store i32 [[I0]], i32* [[D1:%.*]], align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
|
@ -234,9 +231,8 @@ define void @test7(i32 %v0, i32 %v1, i16 %v2, i16 %v3, i1 %c, i32* %d0, i32* %d1
|
|||
; CHECK: end:
|
||||
; CHECK-NEXT: [[IBAD:%.*]] = phi i16 [ [[V2:%.*]], [[B0]] ], [ [[V3:%.*]], [[B1]] ]
|
||||
; CHECK-NEXT: [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
|
||||
; CHECK-NEXT: [[I1:%.*]] = phi i32 [ [[V0]], [[B0]] ], [ [[V1]], [[B1]] ]
|
||||
; CHECK-NEXT: store i32 [[I0]], i32* [[D0:%.*]], align 4
|
||||
; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4
|
||||
; CHECK-NEXT: store i32 [[I0]], i32* [[D1:%.*]], align 4
|
||||
; CHECK-NEXT: store i16 [[IBAD]], i16* [[D2:%.*]], align 2
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
|
@ -269,9 +265,8 @@ define void @test8(i32 %v0, i32 %v1, i16 %v2, i16 %v3, i1 %c, i32* %d0, i32* %d1
|
|||
; CHECK: end:
|
||||
; CHECK-NEXT: [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
|
||||
; CHECK-NEXT: [[IBAD:%.*]] = phi i16 [ [[V2:%.*]], [[B0]] ], [ [[V3:%.*]], [[B1]] ]
|
||||
; CHECK-NEXT: [[I1:%.*]] = phi i32 [ [[V0]], [[B0]] ], [ [[V1]], [[B1]] ]
|
||||
; CHECK-NEXT: store i32 [[I0]], i32* [[D0:%.*]], align 4
|
||||
; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4
|
||||
; CHECK-NEXT: store i32 [[I0]], i32* [[D1:%.*]], align 4
|
||||
; CHECK-NEXT: store i16 [[IBAD]], i16* [[D2:%.*]], align 2
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
|
@ -303,10 +298,9 @@ define void @test9(i32 %v0, i32 %v1, i16 %v2, i16 %v3, i1 %c, i32* %d0, i32* %d1
|
|||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
|
||||
; CHECK-NEXT: [[I1:%.*]] = phi i32 [ [[V0]], [[B0]] ], [ [[V1]], [[B1]] ]
|
||||
; CHECK-NEXT: [[IBAD:%.*]] = phi i16 [ [[V2:%.*]], [[B0]] ], [ [[V3:%.*]], [[B1]] ]
|
||||
; CHECK-NEXT: store i32 [[I0]], i32* [[D0:%.*]], align 4
|
||||
; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4
|
||||
; CHECK-NEXT: store i32 [[I0]], i32* [[D1:%.*]], align 4
|
||||
; CHECK-NEXT: store i16 [[IBAD]], i16* [[D2:%.*]], align 2
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt %s -instcombine -instcombine-infinite-loop-threshold=2 -S | FileCheck %s
|
||||
; RUN: opt %s -instcombine -instcombine-infinite-loop-threshold=3 -S | FileCheck %s
|
||||
|
||||
@var_7 = external global i8, align 1
|
||||
@var_1 = external global i32, align 4
|
||||
|
@ -29,11 +29,10 @@ define void @_Z4testv() {
|
|||
; CHECK-NEXT: br label [[BB12]]
|
||||
; CHECK: bb12:
|
||||
; CHECK-NEXT: [[STOREMERGE1:%.*]] = phi i32 [ [[I11]], [[BB10]] ], [ 1, [[BB9]] ]
|
||||
; CHECK-NEXT: [[STOREMERGE:%.*]] = phi i32 [ [[I11]], [[BB10]] ], [ 1, [[BB9]] ]
|
||||
; CHECK-NEXT: store i32 [[STOREMERGE1]], i32* getelementptr inbounds ([0 x i32], [0 x i32]* @arr_2, i64 0, i64 0), align 4
|
||||
; CHECK-NEXT: store i16 [[I4]], i16* getelementptr inbounds ([0 x i16], [0 x i16]* @arr_4, i64 0, i64 0), align 2
|
||||
; CHECK-NEXT: store i32 [[I8]], i32* getelementptr inbounds ([8 x i32], [8 x i32]* @arr_3, i64 0, i64 0), align 16
|
||||
; CHECK-NEXT: store i32 [[STOREMERGE]], i32* getelementptr inbounds ([0 x i32], [0 x i32]* @arr_2, i64 0, i64 1), align 4
|
||||
; CHECK-NEXT: store i32 [[STOREMERGE1]], i32* getelementptr inbounds ([0 x i32], [0 x i32]* @arr_2, i64 0, i64 1), align 4
|
||||
; CHECK-NEXT: store i16 [[I4]], i16* getelementptr inbounds ([0 x i16], [0 x i16]* @arr_4, i64 0, i64 1), align 2
|
||||
; CHECK-NEXT: store i32 [[I8]], i32* getelementptr inbounds ([8 x i32], [8 x i32]* @arr_3, i64 0, i64 1), align 4
|
||||
; CHECK-NEXT: ret void
|
||||
|
|
|
@ -25,13 +25,8 @@ define { i32, i32 } @test0({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %
|
|||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: [[AGG_LEFT_PN:%.*]] = phi { i32, i32 } [ [[AGG_LEFT:%.*]], [[LEFT]] ], [ [[AGG_RIGHT:%.*]], [[RIGHT]] ]
|
||||
; CHECK-NEXT: [[AGG_LEFT_PN1:%.*]] = phi { i32, i32 } [ [[AGG_LEFT]], [[LEFT]] ], [ [[AGG_RIGHT]], [[RIGHT]] ]
|
||||
; CHECK-NEXT: [[I6:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT_PN1]], 1
|
||||
; CHECK-NEXT: [[I5:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT_PN]], 0
|
||||
; CHECK-NEXT: call void @baz()
|
||||
; CHECK-NEXT: [[I7:%.*]] = insertvalue { i32, i32 } undef, i32 [[I5]], 0
|
||||
; CHECK-NEXT: [[I8:%.*]] = insertvalue { i32, i32 } [[I7]], i32 [[I6]], 1
|
||||
; CHECK-NEXT: ret { i32, i32 } [[I8]]
|
||||
; CHECK-NEXT: ret { i32, i32 } [[AGG_LEFT_PN]]
|
||||
;
|
||||
entry:
|
||||
br i1 %c, label %left, label %right
|
||||
|
@ -162,19 +157,13 @@ define { i32, i32 } @test3({ i32, i32 } %agg_00, { i32, i32 } %agg_01, { i32, i3
|
|||
; CHECK-NEXT: br label [[BB0_MERGE]]
|
||||
; CHECK: bb0.merge:
|
||||
; CHECK-NEXT: [[AGG_00_PN:%.*]] = phi { i32, i32 } [ [[AGG_00:%.*]], [[BB00]] ], [ [[AGG_01:%.*]], [[BB01]] ]
|
||||
; CHECK-NEXT: [[AGG_00_PN1:%.*]] = phi { i32, i32 } [ [[AGG_00]], [[BB00]] ], [ [[AGG_01]], [[BB01]] ]
|
||||
; CHECK-NEXT: br label [[END:%.*]]
|
||||
; CHECK: bb10:
|
||||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: [[AGG_00_PN_PN:%.*]] = phi { i32, i32 } [ [[AGG_00_PN]], [[BB0_MERGE]] ], [ [[AGG_10:%.*]], [[BB10]] ]
|
||||
; CHECK-NEXT: [[AGG_00_PN1_PN:%.*]] = phi { i32, i32 } [ [[AGG_00_PN1]], [[BB0_MERGE]] ], [ [[AGG_10]], [[BB10]] ]
|
||||
; CHECK-NEXT: [[I9:%.*]] = extractvalue { i32, i32 } [[AGG_00_PN1_PN]], 1
|
||||
; CHECK-NEXT: [[I8:%.*]] = extractvalue { i32, i32 } [[AGG_00_PN_PN]], 0
|
||||
; CHECK-NEXT: call void @baz()
|
||||
; CHECK-NEXT: [[I10:%.*]] = insertvalue { i32, i32 } undef, i32 [[I8]], 0
|
||||
; CHECK-NEXT: [[I11:%.*]] = insertvalue { i32, i32 } [[I10]], i32 [[I9]], 1
|
||||
; CHECK-NEXT: ret { i32, i32 } [[I11]]
|
||||
; CHECK-NEXT: ret { i32, i32 } [[AGG_00_PN_PN]]
|
||||
;
|
||||
entry:
|
||||
br i1 %c0, label %bb0.dispatch, label %bb10
|
||||
|
@ -277,17 +266,12 @@ define { i32, i32 } @test5({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %
|
|||
; CHECK-NEXT: call void @bar()
|
||||
; CHECK-NEXT: br label [[MIDDLE]]
|
||||
; CHECK: middle:
|
||||
; CHECK-NEXT: [[AGG_LEFT_PN:%.*]] = phi { i32, i32 } [ [[AGG_LEFT:%.*]], [[LEFT]] ], [ [[AGG_RIGHT:%.*]], [[RIGHT]] ], [ [[I8:%.*]], [[MIDDLE]] ]
|
||||
; CHECK-NEXT: [[AGG_LEFT_PN1:%.*]] = phi { i32, i32 } [ [[AGG_LEFT]], [[LEFT]] ], [ [[AGG_RIGHT]], [[RIGHT]] ], [ [[I8]], [[MIDDLE]] ]
|
||||
; CHECK-NEXT: [[I6:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT_PN1]], 1
|
||||
; CHECK-NEXT: [[I5:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT_PN]], 0
|
||||
; CHECK-NEXT: [[AGG_LEFT_PN:%.*]] = phi { i32, i32 } [ [[AGG_LEFT:%.*]], [[LEFT]] ], [ [[AGG_RIGHT:%.*]], [[RIGHT]] ], [ [[AGG_LEFT_PN]], [[MIDDLE]] ]
|
||||
; CHECK-NEXT: call void @baz()
|
||||
; CHECK-NEXT: [[I7:%.*]] = insertvalue { i32, i32 } undef, i32 [[I5]], 0
|
||||
; CHECK-NEXT: [[I8]] = insertvalue { i32, i32 } [[I7]], i32 [[I6]], 1
|
||||
; CHECK-NEXT: [[C1:%.*]] = call i1 @geni1()
|
||||
; CHECK-NEXT: br i1 [[C1]], label [[END:%.*]], label [[MIDDLE]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: ret { i32, i32 } [[I8]]
|
||||
; CHECK-NEXT: ret { i32, i32 } [[AGG_LEFT_PN]]
|
||||
;
|
||||
entry:
|
||||
br i1 %c0, label %left, label %right
|
||||
|
@ -332,19 +316,14 @@ define { i32, i32 } @test6({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %
|
|||
; CHECK-NEXT: br label [[MERGE]]
|
||||
; CHECK: merge:
|
||||
; CHECK-NEXT: [[AGG_LEFT_PN:%.*]] = phi { i32, i32 } [ [[AGG_LEFT:%.*]], [[LEFT]] ], [ [[AGG_RIGHT:%.*]], [[RIGHT]] ]
|
||||
; CHECK-NEXT: [[AGG_LEFT_PN1:%.*]] = phi { i32, i32 } [ [[AGG_LEFT]], [[LEFT]] ], [ [[AGG_RIGHT]], [[RIGHT]] ]
|
||||
; CHECK-NEXT: call void @baz()
|
||||
; CHECK-NEXT: br i1 [[C1:%.*]], label [[END:%.*]], label [[PASSTHROUGH:%.*]]
|
||||
; CHECK: passthrough:
|
||||
; CHECK-NEXT: call void @qux()
|
||||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: [[I6:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT_PN1]], 1
|
||||
; CHECK-NEXT: [[I5:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT_PN]], 0
|
||||
; CHECK-NEXT: call void @quux()
|
||||
; CHECK-NEXT: [[I7:%.*]] = insertvalue { i32, i32 } undef, i32 [[I5]], 0
|
||||
; CHECK-NEXT: [[I8:%.*]] = insertvalue { i32, i32 } [[I7]], i32 [[I6]], 1
|
||||
; CHECK-NEXT: ret { i32, i32 } [[I8]]
|
||||
; CHECK-NEXT: ret { i32, i32 } [[AGG_LEFT_PN]]
|
||||
;
|
||||
entry:
|
||||
br i1 %c0, label %left, label %right
|
||||
|
@ -451,13 +430,8 @@ define { i32, i32 } @test8({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %
|
|||
; CHECK-NEXT: unreachable
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: [[AGG_LEFT_PN:%.*]] = phi { i32, i32 } [ [[AGG_LEFT:%.*]], [[LEFT]] ], [ [[AGG_LEFT]], [[LEFT]] ], [ [[AGG_RIGHT:%.*]], [[RIGHT]] ], [ [[AGG_RIGHT]], [[RIGHT]] ]
|
||||
; CHECK-NEXT: [[AGG_LEFT_PN1:%.*]] = phi { i32, i32 } [ [[AGG_LEFT]], [[LEFT]] ], [ [[AGG_LEFT]], [[LEFT]] ], [ [[AGG_RIGHT]], [[RIGHT]] ], [ [[AGG_RIGHT]], [[RIGHT]] ]
|
||||
; CHECK-NEXT: [[I6:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT_PN1]], 1
|
||||
; CHECK-NEXT: [[I5:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT_PN]], 0
|
||||
; CHECK-NEXT: call void @baz()
|
||||
; CHECK-NEXT: [[I7:%.*]] = insertvalue { i32, i32 } undef, i32 [[I5]], 0
|
||||
; CHECK-NEXT: [[I8:%.*]] = insertvalue { i32, i32 } [[I7]], i32 [[I6]], 1
|
||||
; CHECK-NEXT: ret { i32, i32 } [[I8]]
|
||||
; CHECK-NEXT: ret { i32, i32 } [[AGG_LEFT_PN]]
|
||||
;
|
||||
entry:
|
||||
br i1 %c, label %left, label %right
|
||||
|
@ -505,13 +479,8 @@ define { i32, i32 } @test9({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %
|
|||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: [[AGG_LEFT_PN:%.*]] = phi { i32, i32 } [ [[AGG_LEFT:%.*]], [[LEFT]] ], [ [[AGG_RIGHT:%.*]], [[RIGHT]] ]
|
||||
; CHECK-NEXT: [[AGG_LEFT_PN1:%.*]] = phi { i32, i32 } [ [[AGG_LEFT]], [[LEFT]] ], [ [[AGG_RIGHT]], [[RIGHT]] ]
|
||||
; CHECK-NEXT: [[I7:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT_PN1]], 1
|
||||
; CHECK-NEXT: [[I0_PN:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT_PN]], 0
|
||||
; CHECK-NEXT: [[I6:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0_PN]], 0
|
||||
; CHECK-NEXT: call void @baz()
|
||||
; CHECK-NEXT: [[I8:%.*]] = insertvalue { i32, i32 } [[I6]], i32 [[I7]], 1
|
||||
; CHECK-NEXT: ret { i32, i32 } [[I8]]
|
||||
; CHECK-NEXT: ret { i32, i32 } [[AGG_LEFT_PN]]
|
||||
;
|
||||
entry:
|
||||
br i1 %c, label %left, label %right
|
||||
|
|
|
@ -15,17 +15,13 @@ define i32 @test_gep_and_bitcast(i1 %cond, i1 %cond2) {
|
|||
; ALL-NEXT: [[OBJ:%.*]] = call i8* @get_ptr.i8()
|
||||
; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
|
||||
; ALL: bb1:
|
||||
; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
|
||||
; ALL-NEXT: [[PTR1_TYPED:%.*]] = bitcast i8* [[PTR1]] to i32*
|
||||
; ALL-NEXT: br label [[EXIT:%.*]]
|
||||
; ALL: bb2:
|
||||
; ALL-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
|
||||
; ALL-NEXT: [[PTR2_TYPED:%.*]] = bitcast i8* [[PTR2]] to i32*
|
||||
; ALL-NEXT: br label [[EXIT]]
|
||||
; ALL: exit:
|
||||
; ALL-NEXT: [[PTR_TYPED:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ]
|
||||
; ALL-NEXT: [[RES_PHI_IN:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ]
|
||||
; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[RES_PHI_IN]], align 4
|
||||
; ALL-NEXT: [[PTR_TYPED_IN:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
|
||||
; ALL-NEXT: [[PTR_TYPED:%.*]] = bitcast i8* [[PTR_TYPED_IN]] to i32*
|
||||
; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[PTR_TYPED]], align 4
|
||||
; ALL-NEXT: store i32 1, i32* [[PTR_TYPED]], align 4
|
||||
; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
|
||||
; ALL-NEXT: ret i32 [[RES]]
|
||||
|
@ -60,17 +56,13 @@ define i32 @test_gep_and_bitcast_arg(i8* %obj, i1 %cond, i1 %cond2) {
|
|||
; ALL-NEXT: entry:
|
||||
; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
|
||||
; ALL: bb1:
|
||||
; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ:%.*]], i64 16
|
||||
; ALL-NEXT: [[PTR1_TYPED:%.*]] = bitcast i8* [[PTR1]] to i32*
|
||||
; ALL-NEXT: br label [[EXIT:%.*]]
|
||||
; ALL: bb2:
|
||||
; ALL-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
|
||||
; ALL-NEXT: [[PTR2_TYPED:%.*]] = bitcast i8* [[PTR2]] to i32*
|
||||
; ALL-NEXT: br label [[EXIT]]
|
||||
; ALL: exit:
|
||||
; ALL-NEXT: [[PTR_TYPED:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ]
|
||||
; ALL-NEXT: [[RES_PHI_IN:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ]
|
||||
; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[RES_PHI_IN]], align 4
|
||||
; ALL-NEXT: [[PTR_TYPED_IN:%.*]] = getelementptr inbounds i8, i8* [[OBJ:%.*]], i64 16
|
||||
; ALL-NEXT: [[PTR_TYPED:%.*]] = bitcast i8* [[PTR_TYPED_IN]] to i32*
|
||||
; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[PTR_TYPED]], align 4
|
||||
; ALL-NEXT: store i32 1, i32* [[PTR_TYPED]], align 4
|
||||
; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
|
||||
; ALL-NEXT: ret i32 [[RES]]
|
||||
|
@ -116,17 +108,13 @@ define i32 @test_gep_and_bitcast_phi(i1 %cond, i1 %cond2, i1 %cond3) {
|
|||
; ALL-NEXT: call void @foo.i8(i8* [[ANOTHER_PHI]])
|
||||
; ALL-NEXT: br i1 [[COND2:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
|
||||
; ALL: bb3:
|
||||
; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
|
||||
; ALL-NEXT: [[PTR1_TYPED:%.*]] = bitcast i8* [[PTR1]] to i32*
|
||||
; ALL-NEXT: br label [[EXIT:%.*]]
|
||||
; ALL: bb4:
|
||||
; ALL-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
|
||||
; ALL-NEXT: [[PTR2_TYPED:%.*]] = bitcast i8* [[PTR2]] to i32*
|
||||
; ALL-NEXT: br label [[EXIT]]
|
||||
; ALL: exit:
|
||||
; ALL-NEXT: [[PTR_TYPED:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB3]] ], [ [[PTR2_TYPED]], [[BB4]] ]
|
||||
; ALL-NEXT: [[RES_PHI_IN:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB3]] ], [ [[PTR2_TYPED]], [[BB4]] ]
|
||||
; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[RES_PHI_IN]], align 4
|
||||
; ALL-NEXT: [[PTR_TYPED_IN:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
|
||||
; ALL-NEXT: [[PTR_TYPED:%.*]] = bitcast i8* [[PTR_TYPED_IN]] to i32*
|
||||
; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[PTR_TYPED]], align 4
|
||||
; ALL-NEXT: store i32 1, i32* [[PTR_TYPED]], align 4
|
||||
; ALL-NEXT: [[RES:%.*]] = select i1 [[COND3:%.*]], i32 [[RES_PHI]], i32 1
|
||||
; ALL-NEXT: ret i32 [[RES]]
|
||||
|
@ -176,15 +164,12 @@ define i32 @test_gep_i32ptr(i1 %cond, i1 %cond2) {
|
|||
; ALL-NEXT: [[OBJ:%.*]] = call i32* @get_ptr.i32()
|
||||
; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
|
||||
; ALL: bb1:
|
||||
; ALL-NEXT: [[PTR1_TYPED:%.*]] = getelementptr inbounds i32, i32* [[OBJ]], i64 16
|
||||
; ALL-NEXT: br label [[EXIT:%.*]]
|
||||
; ALL: bb2:
|
||||
; ALL-NEXT: [[PTR2_TYPED:%.*]] = getelementptr inbounds i32, i32* [[OBJ]], i64 16
|
||||
; ALL-NEXT: br label [[EXIT]]
|
||||
; ALL: exit:
|
||||
; ALL-NEXT: [[PTR_TYPED:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ]
|
||||
; ALL-NEXT: [[RES_PHI_IN:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ]
|
||||
; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[RES_PHI_IN]], align 4
|
||||
; ALL-NEXT: [[PTR_TYPED:%.*]] = getelementptr inbounds i32, i32* [[OBJ]], i64 16
|
||||
; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[PTR_TYPED]], align 4
|
||||
; ALL-NEXT: store i32 1, i32* [[PTR_TYPED]], align 4
|
||||
; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
|
||||
; ALL-NEXT: ret i32 [[RES]]
|
||||
|
@ -218,17 +203,13 @@ define i32 @test_gep_and_bitcast_gep_base_ptr(i1 %cond, i1 %cond2) {
|
|||
; ALL-NEXT: [[OBJ0:%.*]] = call i8* @get_ptr.i8()
|
||||
; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
|
||||
; ALL: bb1:
|
||||
; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ0]], i64 32
|
||||
; ALL-NEXT: [[PTR1_TYPED:%.*]] = bitcast i8* [[PTR1]] to i32*
|
||||
; ALL-NEXT: br label [[EXIT:%.*]]
|
||||
; ALL: bb2:
|
||||
; ALL-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, i8* [[OBJ0]], i64 32
|
||||
; ALL-NEXT: [[PTR2_TYPED:%.*]] = bitcast i8* [[PTR2]] to i32*
|
||||
; ALL-NEXT: br label [[EXIT]]
|
||||
; ALL: exit:
|
||||
; ALL-NEXT: [[PTR_TYPED:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ]
|
||||
; ALL-NEXT: [[RES_PHI_IN:%.*]] = phi i32* [ [[PTR1_TYPED]], [[BB1]] ], [ [[PTR2_TYPED]], [[BB2]] ]
|
||||
; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[RES_PHI_IN]], align 4
|
||||
; ALL-NEXT: [[PTR_TYPED_IN:%.*]] = getelementptr inbounds i8, i8* [[OBJ0]], i64 32
|
||||
; ALL-NEXT: [[PTR_TYPED:%.*]] = bitcast i8* [[PTR_TYPED_IN]] to i32*
|
||||
; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[PTR_TYPED]], align 4
|
||||
; ALL-NEXT: store i32 1, i32* [[PTR_TYPED]], align 4
|
||||
; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
|
||||
; ALL-NEXT: ret i32 [[RES]]
|
||||
|
@ -260,37 +241,19 @@ exit:
|
|||
}
|
||||
|
||||
define i32 @test_gep_and_bitcast_same_bb(i1 %cond, i1 %cond2) {
|
||||
; INSTCOMBINE-LABEL: @test_gep_and_bitcast_same_bb(
|
||||
; INSTCOMBINE-NEXT: entry:
|
||||
; INSTCOMBINE-NEXT: [[OBJ:%.*]] = call i8* @get_ptr.i8()
|
||||
; INSTCOMBINE-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
|
||||
; INSTCOMBINE-NEXT: [[PTR1_TYPED:%.*]] = bitcast i8* [[PTR1]] to i32*
|
||||
; INSTCOMBINE-NEXT: br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[BB2:%.*]]
|
||||
; INSTCOMBINE: bb2:
|
||||
; INSTCOMBINE-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
|
||||
; INSTCOMBINE-NEXT: [[PTR2_TYPED:%.*]] = bitcast i8* [[PTR2]] to i32*
|
||||
; INSTCOMBINE-NEXT: br label [[EXIT]]
|
||||
; INSTCOMBINE: exit:
|
||||
; INSTCOMBINE-NEXT: [[PTR_TYPED:%.*]] = phi i32* [ [[PTR1_TYPED]], [[ENTRY:%.*]] ], [ [[PTR2_TYPED]], [[BB2]] ]
|
||||
; INSTCOMBINE-NEXT: [[RES_PHI_IN:%.*]] = phi i32* [ [[PTR1_TYPED]], [[ENTRY]] ], [ [[PTR2_TYPED]], [[BB2]] ]
|
||||
; INSTCOMBINE-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[RES_PHI_IN]], align 4
|
||||
; INSTCOMBINE-NEXT: store i32 1, i32* [[PTR_TYPED]], align 4
|
||||
; INSTCOMBINE-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
|
||||
; INSTCOMBINE-NEXT: ret i32 [[RES]]
|
||||
;
|
||||
; INSTCOMBINEGVN-LABEL: @test_gep_and_bitcast_same_bb(
|
||||
; INSTCOMBINEGVN-NEXT: entry:
|
||||
; INSTCOMBINEGVN-NEXT: [[OBJ:%.*]] = call i8* @get_ptr.i8()
|
||||
; INSTCOMBINEGVN-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
|
||||
; INSTCOMBINEGVN-NEXT: [[PTR1_TYPED:%.*]] = bitcast i8* [[PTR1]] to i32*
|
||||
; INSTCOMBINEGVN-NEXT: br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[BB2:%.*]]
|
||||
; INSTCOMBINEGVN: bb2:
|
||||
; INSTCOMBINEGVN-NEXT: br label [[EXIT]]
|
||||
; INSTCOMBINEGVN: exit:
|
||||
; INSTCOMBINEGVN-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[PTR1_TYPED]], align 4
|
||||
; INSTCOMBINEGVN-NEXT: store i32 1, i32* [[PTR1_TYPED]], align 4
|
||||
; INSTCOMBINEGVN-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
|
||||
; INSTCOMBINEGVN-NEXT: ret i32 [[RES]]
|
||||
; ALL-LABEL: @test_gep_and_bitcast_same_bb(
|
||||
; ALL-NEXT: entry:
|
||||
; ALL-NEXT: [[OBJ:%.*]] = call i8* @get_ptr.i8()
|
||||
; ALL-NEXT: br i1 [[COND:%.*]], label [[EXIT:%.*]], label [[BB2:%.*]]
|
||||
; ALL: bb2:
|
||||
; ALL-NEXT: br label [[EXIT]]
|
||||
; ALL: exit:
|
||||
; ALL-NEXT: [[PTR_TYPED_IN:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
|
||||
; ALL-NEXT: [[PTR_TYPED:%.*]] = bitcast i8* [[PTR_TYPED_IN]] to i32*
|
||||
; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[PTR_TYPED]], align 4
|
||||
; ALL-NEXT: store i32 1, i32* [[PTR_TYPED]], align 4
|
||||
; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
|
||||
; ALL-NEXT: ret i32 [[RES]]
|
||||
;
|
||||
entry:
|
||||
%obj = call i8* @get_ptr.i8()
|
||||
|
@ -328,8 +291,7 @@ define i32 @test_gep_and_bitcast_same_bb_and_extra_use(i1 %cond, i1 %cond2) {
|
|||
; INSTCOMBINE-NEXT: br label [[EXIT]]
|
||||
; INSTCOMBINE: exit:
|
||||
; INSTCOMBINE-NEXT: [[PTR_TYPED:%.*]] = phi i32* [ [[PTR1_TYPED]], [[ENTRY:%.*]] ], [ [[PTR2_TYPED]], [[BB2]] ]
|
||||
; INSTCOMBINE-NEXT: [[RES_PHI_IN:%.*]] = phi i32* [ [[PTR1_TYPED]], [[ENTRY]] ], [ [[PTR2_TYPED]], [[BB2]] ]
|
||||
; INSTCOMBINE-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[RES_PHI_IN]], align 4
|
||||
; INSTCOMBINE-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[PTR_TYPED]], align 4
|
||||
; INSTCOMBINE-NEXT: store i32 1, i32* [[PTR_TYPED]], align 4
|
||||
; INSTCOMBINE-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
|
||||
; INSTCOMBINE-NEXT: ret i32 [[RES]]
|
||||
|
@ -378,15 +340,12 @@ define i8 @test_gep(i1 %cond, i1 %cond2) {
|
|||
; ALL-NEXT: [[OBJ:%.*]] = call i8* @get_ptr.i8()
|
||||
; ALL-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
|
||||
; ALL: bb1:
|
||||
; ALL-NEXT: [[PTR1:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
|
||||
; ALL-NEXT: br label [[EXIT:%.*]]
|
||||
; ALL: bb2:
|
||||
; ALL-NEXT: [[PTR2:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
|
||||
; ALL-NEXT: br label [[EXIT]]
|
||||
; ALL: exit:
|
||||
; ALL-NEXT: [[PTR_TYPED:%.*]] = phi i8* [ [[PTR1]], [[BB1]] ], [ [[PTR2]], [[BB2]] ]
|
||||
; ALL-NEXT: [[RES_PHI_IN:%.*]] = phi i8* [ [[PTR1]], [[BB1]] ], [ [[PTR2]], [[BB2]] ]
|
||||
; ALL-NEXT: [[RES_PHI:%.*]] = load i8, i8* [[RES_PHI_IN]], align 1
|
||||
; ALL-NEXT: [[PTR_TYPED:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
|
||||
; ALL-NEXT: [[RES_PHI:%.*]] = load i8, i8* [[PTR_TYPED]], align 1
|
||||
; ALL-NEXT: store i8 1, i8* [[PTR_TYPED]], align 1
|
||||
; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i8 [[RES_PHI]], i8 1
|
||||
; ALL-NEXT: ret i8 [[RES]]
|
||||
|
|
|
@ -1926,10 +1926,7 @@ define i32 @select_dominance_chain(i1 %cond, i32 %x, i32 %y) {
|
|||
; CHECK-NEXT: br label [[MERGE_3]]
|
||||
; CHECK: merge.3:
|
||||
; CHECK-NEXT: [[S_3:%.*]] = phi i32 [ [[Y:%.*]], [[IF_FALSE_3]] ], [ [[X:%.*]], [[IF_TRUE_3]] ]
|
||||
; CHECK-NEXT: [[S_2:%.*]] = phi i32 [ [[Y]], [[IF_FALSE_3]] ], [ [[X]], [[IF_TRUE_3]] ]
|
||||
; CHECK-NEXT: [[S_1:%.*]] = phi i32 [ [[Y]], [[IF_FALSE_3]] ], [ [[X]], [[IF_TRUE_3]] ]
|
||||
; CHECK-NEXT: [[SUM_1:%.*]] = add i32 [[S_1]], [[S_2]]
|
||||
; CHECK-NEXT: [[SUM_2:%.*]] = add i32 [[SUM_1]], [[S_3]]
|
||||
; CHECK-NEXT: [[SUM_2:%.*]] = mul i32 [[S_3]], 3
|
||||
; CHECK-NEXT: ret i32 [[SUM_2]]
|
||||
;
|
||||
entry:
|
||||
|
|
|
@ -12,9 +12,8 @@ define void @test0(i32 %v0, i32 %v1, i1 %c, i32* %d0, i32* %d1) {
|
|||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
|
||||
; CHECK-NEXT: [[I1:%.*]] = phi i32 [ [[V0]], [[B0]] ], [ [[V1]], [[B1]] ]
|
||||
; CHECK-NEXT: store i32 [[I0]], i32* [[D0:%.*]], align 4
|
||||
; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4
|
||||
; CHECK-NEXT: store i32 [[I0]], i32* [[D1:%.*]], align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
|
@ -45,9 +44,8 @@ define void @test1(i32 %v0, i32 %v1, i1 %c, i32* %d0, i32* %d1) {
|
|||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
|
||||
; CHECK-NEXT: [[I1:%.*]] = phi i32 [ [[V1]], [[B1]] ], [ [[V0]], [[B0]] ]
|
||||
; CHECK-NEXT: store i32 [[I0]], i32* [[D0:%.*]], align 4
|
||||
; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4
|
||||
; CHECK-NEXT: store i32 [[I0]], i32* [[D1:%.*]], align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
|
@ -140,9 +138,8 @@ define void @negative_test4(i32 %v0, i32 %v1, i1 %c, i32* %d0, i32* %d1) {
|
|||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
|
||||
; CHECK-NEXT: [[I1:%.*]] = phi i32 [ [[V1]], [[B1]] ], [ [[V0]], [[B0]] ]
|
||||
; CHECK-NEXT: store i32 [[I0]], i32* [[D0:%.*]], align 4
|
||||
; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4
|
||||
; CHECK-NEXT: store i32 [[I0]], i32* [[D1:%.*]], align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
|
@ -233,9 +230,8 @@ define void @test7(i32 %v0, i32 %v1, i16 %v2, i16 %v3, i1 %c, i32* %d0, i32* %d1
|
|||
; CHECK: end:
|
||||
; CHECK-NEXT: [[IBAD:%.*]] = phi i16 [ [[V2:%.*]], [[B0]] ], [ [[V3:%.*]], [[B1]] ]
|
||||
; CHECK-NEXT: [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
|
||||
; CHECK-NEXT: [[I1:%.*]] = phi i32 [ [[V0]], [[B0]] ], [ [[V1]], [[B1]] ]
|
||||
; CHECK-NEXT: store i32 [[I0]], i32* [[D0:%.*]], align 4
|
||||
; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4
|
||||
; CHECK-NEXT: store i32 [[I0]], i32* [[D1:%.*]], align 4
|
||||
; CHECK-NEXT: store i16 [[IBAD]], i16* [[D2:%.*]], align 2
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
|
@ -268,9 +264,8 @@ define void @test8(i32 %v0, i32 %v1, i16 %v2, i16 %v3, i1 %c, i32* %d0, i32* %d1
|
|||
; CHECK: end:
|
||||
; CHECK-NEXT: [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
|
||||
; CHECK-NEXT: [[IBAD:%.*]] = phi i16 [ [[V2:%.*]], [[B0]] ], [ [[V3:%.*]], [[B1]] ]
|
||||
; CHECK-NEXT: [[I1:%.*]] = phi i32 [ [[V0]], [[B0]] ], [ [[V1]], [[B1]] ]
|
||||
; CHECK-NEXT: store i32 [[I0]], i32* [[D0:%.*]], align 4
|
||||
; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4
|
||||
; CHECK-NEXT: store i32 [[I0]], i32* [[D1:%.*]], align 4
|
||||
; CHECK-NEXT: store i16 [[IBAD]], i16* [[D2:%.*]], align 2
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
|
@ -302,10 +297,9 @@ define void @test9(i32 %v0, i32 %v1, i16 %v2, i16 %v3, i1 %c, i32* %d0, i32* %d1
|
|||
; CHECK-NEXT: br label [[END]]
|
||||
; CHECK: end:
|
||||
; CHECK-NEXT: [[I0:%.*]] = phi i32 [ [[V0:%.*]], [[B0]] ], [ [[V1:%.*]], [[B1]] ]
|
||||
; CHECK-NEXT: [[I1:%.*]] = phi i32 [ [[V0]], [[B0]] ], [ [[V1]], [[B1]] ]
|
||||
; CHECK-NEXT: [[IBAD:%.*]] = phi i16 [ [[V2:%.*]], [[B0]] ], [ [[V3:%.*]], [[B1]] ]
|
||||
; CHECK-NEXT: store i32 [[I0]], i32* [[D0:%.*]], align 4
|
||||
; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4
|
||||
; CHECK-NEXT: store i32 [[I0]], i32* [[D1:%.*]], align 4
|
||||
; CHECK-NEXT: store i16 [[IBAD]], i16* [[D2:%.*]], align 2
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
; CHECK: latch1:
|
||||
; CHECK-NEXT: %tmp165 = phi i32 [ %tmp163, %body2.thread ], [ %tmp16, %body2 ]
|
||||
; CHECK-NEXT: %tmp154 = phi i32 [ %tmp165, %body2.thread ], [ %tmp15, %body2 ]
|
||||
; CHECK-NEXT: %tmp154 = phi i32 [ %tmp165, %body2.thread ], [ %tmp14, %body2 ]
|
||||
|
||||
define i32 @test(i1 %ARG1, i1 %ARG2, i32 %n) {
|
||||
entry:
|
||||
|
|
|
@ -504,7 +504,6 @@ exit:
|
|||
;CHECK: add <4 x i32>
|
||||
;CHECK: extractelement <4 x i32> %{{.*}}, i32 0
|
||||
;CHECK: %sum.lcssa = phi i32 [ %[[SCALAR:.*]], %.lr.ph ], [ %[[VECTOR:.*]], %middle.block ]
|
||||
;CHECK: %sum.copy = phi i32 [ %[[SCALAR]], %.lr.ph ], [ %[[VECTOR]], %middle.block ]
|
||||
;CHECK: ret i32
|
||||
define i32 @reduction_sum_multiuse(i32 %n, i32* noalias nocapture %A, i32* noalias nocapture %B) {
|
||||
%1 = icmp sgt i32 %n, 0
|
||||
|
|
Loading…
Reference in New Issue