/// 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?
- if (BasicBlock *BB = PN->getParent()) {
- for (PHINode &Src : BB->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;
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);
}
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 $24, %rsp
-; CHECK-NEXT: .cfi_def_cfa_offset 32
+; CHECK-NEXT: subq $40, %rsp
+; CHECK-NEXT: .cfi_def_cfa_offset 48
; 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 $24, %rsp
+; CHECK-NEXT: addq $40, %rsp
; CHECK-NEXT: .cfi_def_cfa_offset 8
; CHECK-NEXT: retq
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
; CHECK: .long 0
; CHECK: .Ltmp2-test3
-; 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 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: .byte 3
; CHECK: .byte 0
; CHECK: .short 16
; CHECK: .short 7
; CHECK: .short 0
-; CHECK: .long 0
+; CHECK: .long 16
; CHECK: .byte 3
-; CHECK: .byte 0
+; 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: .short 16
; CHECK: .short 7
; CHECK: .short 0
; 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 [[I0]], i32* [[D1:%.*]], align 4
+; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4
; CHECK-NEXT: ret void
;
entry:
; 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 [[I0]], i32* [[D1:%.*]], align 4
+; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4
; CHECK-NEXT: ret void
;
entry:
; 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 [[I0]], i32* [[D1:%.*]], align 4
+; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4
; CHECK-NEXT: ret void
;
entry:
; 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 [[I0]], i32* [[D1:%.*]], align 4
+; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4
; CHECK-NEXT: store i16 [[IBAD]], i16* [[D2:%.*]], align 2
; CHECK-NEXT: ret void
;
; 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 [[I0]], i32* [[D1:%.*]], align 4
+; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4
; CHECK-NEXT: store i16 [[IBAD]], i16* [[D2:%.*]], align 2
; CHECK-NEXT: ret void
;
; 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 [[I0]], i32* [[D1:%.*]], align 4
+; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4
; CHECK-NEXT: store i16 [[IBAD]], i16* [[D2:%.*]], align 2
; CHECK-NEXT: ret void
;
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt %s -instcombine -instcombine-infinite-loop-threshold=3 -S | FileCheck %s
+; RUN: opt %s -instcombine -instcombine-infinite-loop-threshold=2 -S | FileCheck %s
@var_7 = external global i8, align 1
@var_1 = external global i32, align 4
; 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 [[STOREMERGE1]], i32* getelementptr inbounds ([0 x i32], [0 x i32]* @arr_2, i64 0, i64 1), align 4
+; 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 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
; 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: ret { i32, i32 } [[AGG_LEFT_PN]]
+; 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]]
;
entry:
br i1 %c, label %left, label %right
; 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: ret { i32, i32 } [[AGG_00_PN_PN]]
+; 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]]
;
entry:
br i1 %c0, label %bb0.dispatch, label %bb10
; 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]] ], [ [[AGG_LEFT_PN]], [[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: 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 } [[AGG_LEFT_PN]]
+; CHECK-NEXT: ret { i32, i32 } [[I8]]
;
entry:
br i1 %c0, label %left, label %right
; 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: ret { i32, i32 } [[AGG_LEFT_PN]]
+; 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]]
;
entry:
br i1 %c0, label %left, label %right
; 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: ret { i32, i32 } [[AGG_LEFT_PN]]
+; 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]]
;
entry:
br i1 %c, label %left, label %right
; 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: ret { i32, i32 } [[AGG_LEFT_PN]]
+; CHECK-NEXT: [[I8:%.*]] = insertvalue { i32, i32 } [[I6]], i32 [[I7]], 1
+; CHECK-NEXT: ret { i32, i32 } [[I8]]
;
entry:
br i1 %c, label %left, label %right
; 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_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: [[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: store i32 1, i32* [[PTR_TYPED]], align 4
; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
; ALL-NEXT: ret i32 [[RES]]
; 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_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: [[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: store i32 1, i32* [[PTR_TYPED]], align 4
; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
; ALL-NEXT: ret i32 [[RES]]
; 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_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: [[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: store i32 1, i32* [[PTR_TYPED]], align 4
; ALL-NEXT: [[RES:%.*]] = select i1 [[COND3:%.*]], i32 [[RES_PHI]], i32 1
; ALL-NEXT: ret i32 [[RES]]
; 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:%.*]] = getelementptr inbounds i32, i32* [[OBJ]], i64 16
-; ALL-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[PTR_TYPED]], align 4
+; 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: store i32 1, i32* [[PTR_TYPED]], align 4
; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
; ALL-NEXT: ret i32 [[RES]]
; 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_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: [[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: store i32 1, i32* [[PTR_TYPED]], align 4
; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i32 [[RES_PHI]], i32 1
; ALL-NEXT: ret i32 [[RES]]
}
define i32 @test_gep_and_bitcast_same_bb(i1 %cond, i1 %cond2) {
-; 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]]
+; 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]]
;
entry:
%obj = call i8* @get_ptr.i8()
; INSTCOMBINE-NEXT: br label [[EXIT]]
; INSTCOMBINE: exit:
; INSTCOMBINE-NEXT: [[PTR_TYPED:%.*]] = phi i32* [ [[PTR1_TYPED]], [[ENTRY:%.*]] ], [ [[PTR2_TYPED]], [[BB2]] ]
-; INSTCOMBINE-NEXT: [[RES_PHI:%.*]] = load i32, i32* [[PTR_TYPED]], align 4
+; 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]]
; 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:%.*]] = getelementptr inbounds i8, i8* [[OBJ]], i64 16
-; ALL-NEXT: [[RES_PHI:%.*]] = load i8, i8* [[PTR_TYPED]], align 1
+; 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: store i8 1, i8* [[PTR_TYPED]], align 1
; ALL-NEXT: [[RES:%.*]] = select i1 [[COND2:%.*]], i8 [[RES_PHI]], i8 1
; ALL-NEXT: ret i8 [[RES]]
; 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: [[SUM_2:%.*]] = mul i32 [[S_3]], 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: ret i32 [[SUM_2]]
;
entry:
; 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 [[I0]], i32* [[D1:%.*]], align 4
+; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4
; CHECK-NEXT: ret void
;
entry:
; 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 [[I0]], i32* [[D1:%.*]], align 4
+; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4
; CHECK-NEXT: ret void
;
entry:
; 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 [[I0]], i32* [[D1:%.*]], align 4
+; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4
; CHECK-NEXT: ret void
;
entry:
; 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 [[I0]], i32* [[D1:%.*]], align 4
+; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4
; CHECK-NEXT: store i16 [[IBAD]], i16* [[D2:%.*]], align 2
; CHECK-NEXT: ret void
;
; 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 [[I0]], i32* [[D1:%.*]], align 4
+; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4
; CHECK-NEXT: store i16 [[IBAD]], i16* [[D2:%.*]], align 2
; CHECK-NEXT: ret void
;
; 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 [[I0]], i32* [[D1:%.*]], align 4
+; CHECK-NEXT: store i32 [[I1]], i32* [[D1:%.*]], align 4
; CHECK-NEXT: store i16 [[IBAD]], i16* [[D2:%.*]], align 2
; CHECK-NEXT: ret void
;
; CHECK: latch1:
; CHECK-NEXT: %tmp165 = phi i32 [ %tmp163, %body2.thread ], [ %tmp16, %body2 ]
-; CHECK-NEXT: %tmp154 = phi i32 [ %tmp165, %body2.thread ], [ %tmp14, %body2 ]
+; CHECK-NEXT: %tmp154 = phi i32 [ %tmp165, %body2.thread ], [ %tmp15, %body2 ]
define i32 @test(i1 %ARG1, i1 %ARG2, i32 %n) {
entry:
;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