mirror of
https://github.com/intel/llvm.git
synced 2026-01-14 03:50:17 +08:00
This reverts commit f1c1063.
PR #163453 was merged and reverted since it exposed a crash.
After investigation the crash was unrelated and is then fixed in #164628.
This is an attempt to reland #163453.
This commit is contained in:
@@ -4866,6 +4866,89 @@ static Value *simplifySelectWithFCmp(Value *Cond, Value *T, Value *F,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Look for the following pattern and simplify %to_fold to %identicalPhi.
|
||||
/// Here %phi, %to_fold and %phi.next perform the same functionality as
|
||||
/// %identicalPhi and hence the select instruction %to_fold can be folded
|
||||
/// into %identicalPhi.
|
||||
///
|
||||
/// BB1:
|
||||
/// %identicalPhi = phi [ X, %BB0 ], [ %identicalPhi.next, %BB1 ]
|
||||
/// %phi = phi [ X, %BB0 ], [ %phi.next, %BB1 ]
|
||||
/// ...
|
||||
/// %identicalPhi.next = select %cmp, %val, %identicalPhi
|
||||
/// (or select %cmp, %identicalPhi, %val)
|
||||
/// %to_fold = select %cmp2, %identicalPhi, %phi
|
||||
/// %phi.next = select %cmp, %val, %to_fold
|
||||
/// (or select %cmp, %to_fold, %val)
|
||||
///
|
||||
/// Prove that %phi and %identicalPhi are the same by induction:
|
||||
///
|
||||
/// Base case: Both %phi and %identicalPhi are equal on entry to the loop.
|
||||
/// Inductive case:
|
||||
/// Suppose %phi and %identicalPhi are equal at iteration i.
|
||||
/// We look at their values at iteration i+1 which are %phi.next and
|
||||
/// %identicalPhi.next. They would have become different only when %cmp is
|
||||
/// false and the corresponding values %to_fold and %identicalPhi differ
|
||||
/// (similar reason for the other "or" case in the bracket).
|
||||
///
|
||||
/// The only condition when %to_fold and %identicalPh could differ is when %cmp2
|
||||
/// is false and %to_fold is %phi, which contradicts our inductive hypothesis
|
||||
/// that %phi and %identicalPhi are equal. Thus %phi and %identicalPhi are
|
||||
/// always equal at iteration i+1.
|
||||
bool isSelectWithIdenticalPHI(PHINode &PN, PHINode &IdenticalPN) {
|
||||
if (PN.getParent() != IdenticalPN.getParent())
|
||||
return false;
|
||||
if (PN.getNumIncomingValues() != 2)
|
||||
return false;
|
||||
|
||||
// Check that only the backedge incoming value is different.
|
||||
unsigned DiffVals = 0;
|
||||
BasicBlock *DiffValBB = nullptr;
|
||||
for (unsigned i = 0; i < 2; i++) {
|
||||
BasicBlock *PredBB = PN.getIncomingBlock(i);
|
||||
if (PN.getIncomingValue(i) !=
|
||||
IdenticalPN.getIncomingValueForBlock(PredBB)) {
|
||||
DiffVals++;
|
||||
DiffValBB = PredBB;
|
||||
}
|
||||
}
|
||||
if (DiffVals != 1)
|
||||
return false;
|
||||
// Now check that the backedge incoming values are two select
|
||||
// instructions with the same condition. Either their true
|
||||
// values are the same, or their false values are the same.
|
||||
auto *SI = dyn_cast<SelectInst>(PN.getIncomingValueForBlock(DiffValBB));
|
||||
auto *IdenticalSI =
|
||||
dyn_cast<SelectInst>(IdenticalPN.getIncomingValueForBlock(DiffValBB));
|
||||
if (!SI || !IdenticalSI)
|
||||
return false;
|
||||
if (SI->getCondition() != IdenticalSI->getCondition())
|
||||
return false;
|
||||
|
||||
SelectInst *SIOtherVal = nullptr;
|
||||
Value *IdenticalSIOtherVal = nullptr;
|
||||
if (SI->getTrueValue() == IdenticalSI->getTrueValue()) {
|
||||
SIOtherVal = dyn_cast<SelectInst>(SI->getFalseValue());
|
||||
IdenticalSIOtherVal = IdenticalSI->getFalseValue();
|
||||
} else if (SI->getFalseValue() == IdenticalSI->getFalseValue()) {
|
||||
SIOtherVal = dyn_cast<SelectInst>(SI->getTrueValue());
|
||||
IdenticalSIOtherVal = IdenticalSI->getTrueValue();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now check that the other values in select, i.e., %to_fold and
|
||||
// %identicalPhi, are essentially the same value.
|
||||
if (!SIOtherVal || IdenticalSIOtherVal != &IdenticalPN)
|
||||
return false;
|
||||
if (!(SIOtherVal->getTrueValue() == &IdenticalPN &&
|
||||
SIOtherVal->getFalseValue() == &PN) &&
|
||||
!(SIOtherVal->getTrueValue() == &PN &&
|
||||
SIOtherVal->getFalseValue() == &IdenticalPN))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Given operands for a SelectInst, see if we can fold the result.
|
||||
/// If not, this returns null.
|
||||
static Value *simplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
|
||||
@@ -5041,7 +5124,14 @@ static Value *simplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
|
||||
std::optional<bool> Imp = isImpliedByDomCondition(Cond, Q.CxtI, Q.DL);
|
||||
if (Imp)
|
||||
return *Imp ? TrueVal : FalseVal;
|
||||
|
||||
// Look for same PHIs in the true and false values.
|
||||
if (auto *TruePHI = dyn_cast<PHINode>(TrueVal))
|
||||
if (auto *FalsePHI = dyn_cast<PHINode>(FalseVal)) {
|
||||
if (isSelectWithIdenticalPHI(*TruePHI, *FalsePHI))
|
||||
return FalseVal;
|
||||
if (isSelectWithIdenticalPHI(*FalsePHI, *TruePHI))
|
||||
return TrueVal;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
417
llvm/test/Transforms/InstCombine/select_with_identical_phi.ll
Normal file
417
llvm/test/Transforms/InstCombine/select_with_identical_phi.ll
Normal file
@@ -0,0 +1,417 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -S -passes=instcombine | FileCheck %s
|
||||
@A = extern_weak global float, align 4
|
||||
|
||||
; %same.as.v1 is a select with two phis %v1 and %phi.to.remove as the true
|
||||
; and false values, while %v1 and %phi.to.remove are actually the same.
|
||||
; Fold the selection instruction %same.as.v1 to %v1.
|
||||
define void @select_with_identical_phi(ptr %m, ptr %n, i32 %count) {
|
||||
; CHECK-LABEL: @select_with_identical_phi(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
||||
; CHECK: for.body:
|
||||
; CHECK-NEXT: [[V0:%.*]] = phi float [ 0x4415AF1D80000000, [[ENTRY:%.*]] ], [ [[V0_1:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[Q:%.*]] = phi ptr [ [[M:%.*]], [[ENTRY]] ], [ [[Q_NEXT:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[C:%.*]] = phi ptr [ [[N:%.*]], [[ENTRY]] ], [ [[C_NEXT:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[Q_LOAD:%.*]] = load float, ptr [[Q]], align 4
|
||||
; CHECK-NEXT: [[C_LOAD:%.*]] = load float, ptr [[C]], align 4
|
||||
; CHECK-NEXT: [[SUB:%.*]] = fsub float [[Q_LOAD]], [[C_LOAD]]
|
||||
; CHECK-NEXT: [[CMP1:%.*]] = fcmp olt float [[SUB]], [[V0]]
|
||||
; CHECK-NEXT: [[V0_1]] = select i1 [[CMP1]], float [[SUB]], float [[V0]]
|
||||
; CHECK-NEXT: [[CMP2:%.*]] = fcmp ogt float [[SUB]], [[V1]]
|
||||
; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2]], float [[SUB]], float [[V1]]
|
||||
; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1
|
||||
; CHECK-NEXT: [[Q_NEXT]] = getelementptr inbounds nuw i8, ptr [[Q]], i64 4
|
||||
; CHECK-NEXT: [[C_NEXT]] = getelementptr inbounds nuw i8, ptr [[C]], i64 4
|
||||
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], [[COUNT:%.*]]
|
||||
; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]]
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %for.body
|
||||
|
||||
for.body: ; preds = %entry, %for.body
|
||||
%v0 = phi float [ 0x4415AF1D80000000, %entry ], [ %v0.1, %for.body ]
|
||||
%v1 = phi float [ 0xC415AF1D80000000, %entry ], [ %v1.1, %for.body ]
|
||||
%phi.to.remove = phi float [ 0xC415AF1D80000000, %entry ], [ %phi.to.remove.next, %for.body ]
|
||||
%i = phi i32 [ 0, %entry ], [ %inc.i, %for.body ]
|
||||
%q = phi ptr [ %m, %entry ], [ %q.next, %for.body ]
|
||||
%c = phi ptr [ %n, %entry ], [ %c.next, %for.body ]
|
||||
%q.load = load float, ptr %q
|
||||
%c.load = load float, ptr %c
|
||||
%sub = fsub float %q.load, %c.load
|
||||
%cmp1 = fcmp olt float %sub, %v0
|
||||
%v0.1 = select i1 %cmp1, float %sub, float %v0
|
||||
%same.as.v1 = select i1 %cmp1, float %v1, float %phi.to.remove
|
||||
%cmp2 = fcmp ogt float %sub, %same.as.v1
|
||||
%v1.1 = select i1 %cmp2, float %sub, float %v1
|
||||
%phi.to.remove.next = select i1 %cmp2, float %sub, float %same.as.v1
|
||||
%inc.i = add nuw nsw i32 %i, 1
|
||||
%q.next = getelementptr inbounds i8, ptr %q, i64 4
|
||||
%c.next = getelementptr inbounds i8, ptr %c, i64 4
|
||||
%exitcond = icmp eq i32 %inc.i, %count
|
||||
br i1 %exitcond, label %exit, label %for.body
|
||||
|
||||
exit:
|
||||
%vl.1.lcssa = phi float [ %v1.1, %for.body ]
|
||||
store float %vl.1.lcssa, ptr @A
|
||||
ret void
|
||||
}
|
||||
|
||||
; Reduced from select_with_identical_phi().
|
||||
; Check that %same.as.v1 can be folded.
|
||||
define void @select_with_identical_phi_2(i1 %cmp1, i1 %cmp2, float %x) {
|
||||
; CHECK-LABEL: @select_with_identical_phi_2(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
||||
; CHECK: for.body:
|
||||
; CHECK-NEXT: [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY:%.*]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2:%.*]], float [[X:%.*]], float [[V1]]
|
||||
; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1
|
||||
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], 100
|
||||
; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]]
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %for.body
|
||||
|
||||
for.body: ; preds = %entry, %for.body
|
||||
%v1 = phi float [ 0xC415AF1D80000000, %entry ], [ %v1.1, %for.body ]
|
||||
%phi.to.remove = phi float [ 0xC415AF1D80000000, %entry ], [ %phi.to.remove.next, %for.body ]
|
||||
%i = phi i32 [ 0, %entry ], [ %inc.i, %for.body ]
|
||||
%same.as.v1 = select i1 %cmp1, float %v1, float %phi.to.remove
|
||||
%v1.1 = select i1 %cmp2, float %x, float %v1
|
||||
%phi.to.remove.next = select i1 %cmp2, float %x, float %same.as.v1
|
||||
%inc.i = add nuw nsw i32 %i, 1
|
||||
%exitcond = icmp eq i32 %inc.i, 100
|
||||
br i1 %exitcond, label %exit, label %for.body
|
||||
|
||||
exit:
|
||||
%vl.1.lcssa = phi float [ %v1.1, %for.body ]
|
||||
store float %vl.1.lcssa, ptr @A
|
||||
ret void
|
||||
}
|
||||
|
||||
; The difference from select_with_identical_phi_2() is that the true and false values in
|
||||
; %phi.to.remove.next and %v1.1 are swapped.
|
||||
; Check that %same.as.v1 can be folded.
|
||||
define void @select_with_identical_phi_3(i1 %cmp1, i1 %cmp2, float %x) {
|
||||
; CHECK-LABEL: @select_with_identical_phi_3(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
||||
; CHECK: for.body:
|
||||
; CHECK-NEXT: [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY:%.*]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2:%.*]], float [[V1]], float [[X:%.*]]
|
||||
; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1
|
||||
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], 100
|
||||
; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]]
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %for.body
|
||||
|
||||
for.body: ; preds = %entry, %for.body
|
||||
%v1 = phi float [ 0xC415AF1D80000000, %entry ], [ %v1.1, %for.body ]
|
||||
%phi.to.remove = phi float [ 0xC415AF1D80000000, %entry ], [ %phi.to.remove.next, %for.body ]
|
||||
%i = phi i32 [ 0, %entry ], [ %inc.i, %for.body ]
|
||||
%same.as.v1 = select i1 %cmp1, float %v1, float %phi.to.remove
|
||||
%v1.1 = select i1 %cmp2, float %v1, float %x
|
||||
%phi.to.remove.next = select i1 %cmp2, float %same.as.v1, float %x
|
||||
%inc.i = add nuw nsw i32 %i, 1
|
||||
%exitcond = icmp eq i32 %inc.i, 100
|
||||
br i1 %exitcond, label %exit, label %for.body
|
||||
|
||||
exit:
|
||||
%vl.1.lcssa = phi float [ %v1.1, %for.body ]
|
||||
store float %vl.1.lcssa, ptr @A
|
||||
ret void
|
||||
}
|
||||
|
||||
; The difference from select_with_identical_phi_2() is that the true and false values in
|
||||
; same.as.v1 are swapped.
|
||||
; Check that %same.as.v1 can be folded.
|
||||
define void @select_with_identical_phi_4(i1 %cmp1, i1 %cmp2, float %x) {
|
||||
; CHECK-LABEL: @select_with_identical_phi_4(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
||||
; CHECK: for.body:
|
||||
; CHECK-NEXT: [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY:%.*]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2:%.*]], float [[X:%.*]], float [[V1]]
|
||||
; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1
|
||||
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], 100
|
||||
; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]]
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %for.body
|
||||
|
||||
for.body: ; preds = %entry, %for.body
|
||||
%v1 = phi float [ 0xC415AF1D80000000, %entry ], [ %v1.1, %for.body ]
|
||||
%phi.to.remove = phi float [ 0xC415AF1D80000000, %entry ], [ %phi.to.remove.next, %for.body ]
|
||||
%i = phi i32 [ 0, %entry ], [ %inc.i, %for.body ]
|
||||
%same.as.v1 = select i1 %cmp1, float %phi.to.remove, float %v1
|
||||
%v1.1 = select i1 %cmp2, float %x, float %v1
|
||||
%phi.to.remove.next = select i1 %cmp2, float %x, float %same.as.v1
|
||||
%inc.i = add nuw nsw i32 %i, 1
|
||||
%exitcond = icmp eq i32 %inc.i, 100
|
||||
br i1 %exitcond, label %exit, label %for.body
|
||||
|
||||
exit:
|
||||
%vl.1.lcssa = phi float [ %v1.1, %for.body ]
|
||||
store float %vl.1.lcssa, ptr @A
|
||||
ret void
|
||||
}
|
||||
|
||||
; The difference from select_with_identical_phi() is that the true and false values in
|
||||
; %same.as.v1, %phi.to.remove.next and %v1.1 are swapped.
|
||||
; Check that %same.as.v1 can be folded.
|
||||
define void @select_with_identical_phi_5(i1 %cmp1, i1 %cmp2, float %x) {
|
||||
; CHECK-LABEL: @select_with_identical_phi_5(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
||||
; CHECK: for.body:
|
||||
; CHECK-NEXT: [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY:%.*]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2:%.*]], float [[V1]], float [[X:%.*]]
|
||||
; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1
|
||||
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], 100
|
||||
; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]]
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %for.body
|
||||
|
||||
for.body: ; preds = %entry, %for.body
|
||||
%v1 = phi float [ 0xC415AF1D80000000, %entry ], [ %v1.1, %for.body ]
|
||||
%phi.to.remove = phi float [ 0xC415AF1D80000000, %entry ], [ %phi.to.remove.next, %for.body ]
|
||||
%i = phi i32 [ 0, %entry ], [ %inc.i, %for.body ]
|
||||
%same.as.v1 = select i1 %cmp1, float %phi.to.remove, float %v1
|
||||
%v1.1 = select i1 %cmp2, float %v1, float %x
|
||||
%phi.to.remove.next = select i1 %cmp2, float %same.as.v1, float %x
|
||||
%inc.i = add nuw nsw i32 %i, 1
|
||||
%exitcond = icmp eq i32 %inc.i, 100
|
||||
br i1 %exitcond, label %exit, label %for.body
|
||||
|
||||
exit:
|
||||
%vl.1.lcssa = phi float [ %v1.1, %for.body ]
|
||||
store float %vl.1.lcssa, ptr @A
|
||||
ret void
|
||||
}
|
||||
|
||||
; The difference from select_with_identical_phi_2() is that not all phis are sorted with
|
||||
; the same order of incoming BBs.
|
||||
; Check that %same.as.v1 can be folded.
|
||||
define void @select_with_identical_phi_6(i1 %cmp1, i1 %cmp2, float %x) {
|
||||
; CHECK-LABEL: @select_with_identical_phi_6(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
||||
; CHECK: for.body:
|
||||
; CHECK-NEXT: [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY:%.*]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2:%.*]], float [[X:%.*]], float [[V1]]
|
||||
; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1
|
||||
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], 100
|
||||
; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]]
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %for.body
|
||||
|
||||
for.body: ; preds = %entry, %for.body
|
||||
%v1 = phi float [ 0xC415AF1D80000000, %entry ], [ %v1.1, %for.body ]
|
||||
%phi.to.remove = phi float [ %phi.to.remove.next, %for.body ], [ 0xC415AF1D80000000, %entry ]
|
||||
%i = phi i32 [ 0, %entry ], [ %inc.i, %for.body ]
|
||||
%same.as.v1 = select i1 %cmp1, float %v1, float %phi.to.remove
|
||||
%v1.1 = select i1 %cmp2, float %x, float %v1
|
||||
%phi.to.remove.next = select i1 %cmp2, float %x, float %same.as.v1
|
||||
%inc.i = add nuw nsw i32 %i, 1
|
||||
%exitcond = icmp eq i32 %inc.i, 100
|
||||
br i1 %exitcond, label %exit, label %for.body
|
||||
|
||||
exit:
|
||||
%vl.1.lcssa = phi float [ %v1.1, %for.body ]
|
||||
store float %vl.1.lcssa, ptr @A
|
||||
ret void
|
||||
}
|
||||
|
||||
; %v1 and %phi.to.remove do not have the same start value.
|
||||
; Cannot fold %same.as.v1.
|
||||
define void @select_with_identical_phi_negative_1(i1 %cmp1, i1 %cmp2, float %x) {
|
||||
; CHECK-LABEL: @select_with_identical_phi_negative_1(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
||||
; CHECK: for.body:
|
||||
; CHECK-NEXT: [[V1:%.*]] = phi float [ 0x4415AF1D80000000, [[ENTRY:%.*]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[PHI_TO_REMOVE:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY]] ], [ [[PHI_TO_REMOVE_NEXT:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[SAME_AS_V1:%.*]] = select i1 [[CMP1:%.*]], float [[V1]], float [[PHI_TO_REMOVE]]
|
||||
; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2:%.*]], float [[X:%.*]], float [[V1]]
|
||||
; CHECK-NEXT: [[PHI_TO_REMOVE_NEXT]] = select i1 [[CMP2]], float [[X]], float [[SAME_AS_V1]]
|
||||
; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1
|
||||
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], 100
|
||||
; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]]
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %for.body
|
||||
|
||||
for.body: ; preds = %entry, %for.body
|
||||
%v1 = phi float [ 0x4415AF1D80000000, %entry ], [ %v1.1, %for.body ]
|
||||
%phi.to.remove = phi float [ 0xC415AF1D80000000, %entry ], [ %phi.to.remove.next, %for.body ]
|
||||
%i = phi i32 [ 0, %entry ], [ %inc.i, %for.body ]
|
||||
%same.as.v1 = select i1 %cmp1, float %v1, float %phi.to.remove
|
||||
%v1.1 = select i1 %cmp2, float %x, float %v1
|
||||
%phi.to.remove.next = select i1 %cmp2, float %x, float %same.as.v1
|
||||
%inc.i = add nuw nsw i32 %i, 1
|
||||
%exitcond = icmp eq i32 %inc.i, 100
|
||||
br i1 %exitcond, label %exit, label %for.body
|
||||
|
||||
exit:
|
||||
%vl.1.lcssa = phi float [ %v1.1, %for.body ]
|
||||
store float %vl.1.lcssa, ptr @A
|
||||
ret void
|
||||
}
|
||||
|
||||
; %v1 and %phi.to.remove do not act as the same phi since %v1.1 and %phi.to.remove.next do not evolve the same.
|
||||
; Cannot fold %same.as.v1.
|
||||
define void @select_with_identical_phi_negative_2(i1 %cmp1, i1 %cmp2, float %x) {
|
||||
; CHECK-LABEL: @select_with_identical_phi_negative_2(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
||||
; CHECK: for.body:
|
||||
; CHECK-NEXT: [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY:%.*]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[PHI_TO_REMOVE:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY]] ], [ [[PHI_TO_REMOVE_NEXT:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[SAME_AS_V1:%.*]] = select i1 [[CMP1:%.*]], float [[V1]], float [[PHI_TO_REMOVE]]
|
||||
; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2:%.*]], float [[V1]], float [[X:%.*]]
|
||||
; CHECK-NEXT: [[PHI_TO_REMOVE_NEXT]] = select i1 [[CMP2]], float [[X]], float [[SAME_AS_V1]]
|
||||
; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1
|
||||
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], 100
|
||||
; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]]
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %for.body
|
||||
|
||||
for.body: ; preds = %entry, %for.body
|
||||
%v1 = phi float [ 0xC415AF1D80000000, %entry ], [ %v1.1, %for.body ]
|
||||
%phi.to.remove = phi float [ 0xC415AF1D80000000, %entry ], [ %phi.to.remove.next, %for.body ]
|
||||
%i = phi i32 [ 0, %entry ], [ %inc.i, %for.body ]
|
||||
%same.as.v1 = select i1 %cmp1, float %v1, float %phi.to.remove
|
||||
%v1.1 = select i1 %cmp2, float %v1, float %x
|
||||
%phi.to.remove.next = select i1 %cmp2, float %x, float %same.as.v1
|
||||
%inc.i = add nuw nsw i32 %i, 1
|
||||
%exitcond = icmp eq i32 %inc.i, 100
|
||||
br i1 %exitcond, label %exit, label %for.body
|
||||
|
||||
exit:
|
||||
%vl.1.lcssa = phi float [ %v1.1, %for.body ]
|
||||
store float %vl.1.lcssa, ptr @A
|
||||
ret void
|
||||
}
|
||||
|
||||
; %v1 and %phi.to.remove do not act as the same phi since %v1.1 and %phi.to.remove.next do not
|
||||
; have the same condition.
|
||||
; Cannot fold %same.as.v1.
|
||||
define void @select_with_identical_phi_negative_3(i1 %cmp1, i1 %cmp2, i1 %cmp3, float %x) {
|
||||
; CHECK-LABEL: @select_with_identical_phi_negative_3(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
||||
; CHECK: for.body:
|
||||
; CHECK-NEXT: [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY:%.*]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[PHI_TO_REMOVE:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY]] ], [ [[PHI_TO_REMOVE_NEXT:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[SAME_AS_V1:%.*]] = select i1 [[CMP1:%.*]], float [[V1]], float [[PHI_TO_REMOVE]]
|
||||
; CHECK-NEXT: [[V1_1]] = select i1 [[CMP3:%.*]], float [[V1]], float [[X:%.*]]
|
||||
; CHECK-NEXT: [[PHI_TO_REMOVE_NEXT]] = select i1 [[CMP2:%.*]], float [[X]], float [[SAME_AS_V1]]
|
||||
; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1
|
||||
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], 100
|
||||
; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]]
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %for.body
|
||||
|
||||
for.body: ; preds = %entry, %for.body
|
||||
%v1 = phi float [ 0xC415AF1D80000000, %entry ], [ %v1.1, %for.body ]
|
||||
%phi.to.remove = phi float [ 0xC415AF1D80000000, %entry ], [ %phi.to.remove.next, %for.body ]
|
||||
%i = phi i32 [ 0, %entry ], [ %inc.i, %for.body ]
|
||||
%same.as.v1 = select i1 %cmp1, float %v1, float %phi.to.remove
|
||||
%v1.1 = select i1 %cmp3, float %v1, float %x
|
||||
%phi.to.remove.next = select i1 %cmp2, float %x, float %same.as.v1
|
||||
%inc.i = add nuw nsw i32 %i, 1
|
||||
%exitcond = icmp eq i32 %inc.i, 100
|
||||
br i1 %exitcond, label %exit, label %for.body
|
||||
|
||||
exit:
|
||||
%vl.1.lcssa = phi float [ %v1.1, %for.body ]
|
||||
store float %vl.1.lcssa, ptr @A
|
||||
ret void
|
||||
}
|
||||
|
||||
; The true and false values of %same.as.v1 are not really the same phi.
|
||||
; Cannot fold %same.as.v1.
|
||||
define void @select_with_identical_phi_negative_4(i1 %cmp1, i1 %cmp2, float %x) {
|
||||
; CHECK-LABEL: @select_with_identical_phi_negative_4(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
|
||||
; CHECK: for.body:
|
||||
; CHECK-NEXT: [[V0:%.*]] = phi float [ 0x4415AF1D80000000, [[ENTRY:%.*]] ], [ [[V0_1:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[V1:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY]] ], [ [[V1_1:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[PHI_TO_REMOVE:%.*]] = phi float [ 0xC415AF1D80000000, [[ENTRY]] ], [ [[PHI_TO_REMOVE_NEXT:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC_I:%.*]], [[FOR_BODY]] ]
|
||||
; CHECK-NEXT: [[SAME_AS_V1:%.*]] = select i1 [[CMP1:%.*]], float [[V0]], float [[PHI_TO_REMOVE]]
|
||||
; CHECK-NEXT: [[V1_1]] = select i1 [[CMP2:%.*]], float [[X:%.*]], float [[V1]]
|
||||
; CHECK-NEXT: [[PHI_TO_REMOVE_NEXT]] = select i1 [[CMP2]], float [[X]], float [[SAME_AS_V1]]
|
||||
; CHECK-NEXT: [[V0_1]] = fadd float [[V0]], 1.000000e+00
|
||||
; CHECK-NEXT: [[INC_I]] = add nuw nsw i32 [[I]], 1
|
||||
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC_I]], 100
|
||||
; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[FOR_BODY]]
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: store float [[V1_1]], ptr @A, align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
br label %for.body
|
||||
|
||||
for.body: ; preds = %entry, %for.body
|
||||
%v0 = phi float [ 0x4415AF1D80000000, %entry ], [ %v0.1, %for.body ]
|
||||
%v1 = phi float [ 0xC415AF1D80000000, %entry ], [ %v1.1, %for.body ]
|
||||
%phi.to.remove = phi float [ 0xC415AF1D80000000, %entry ], [ %phi.to.remove.next, %for.body ]
|
||||
%i = phi i32 [ 0, %entry ], [ %inc.i, %for.body ]
|
||||
%same.as.v1 = select i1 %cmp1, float %v0, float %phi.to.remove
|
||||
%v1.1 = select i1 %cmp2, float %x, float %v1
|
||||
%phi.to.remove.next = select i1 %cmp2, float %x, float %same.as.v1
|
||||
%v0.1 = fadd float %v0, 1.0
|
||||
%inc.i = add nuw nsw i32 %i, 1
|
||||
%exitcond = icmp eq i32 %inc.i, 100
|
||||
br i1 %exitcond, label %exit, label %for.body
|
||||
|
||||
exit:
|
||||
%vl.1.lcssa = phi float [ %v1.1, %for.body ]
|
||||
store float %vl.1.lcssa, ptr @A
|
||||
ret void
|
||||
}
|
||||
Reference in New Issue
Block a user