[ConstraintElimination] Generalize AND matching.
Extend more general matching used for chains of ORs to also support chains of ANDs.
This commit is contained in:
parent
5a0722e046
commit
a7ac0dd0cf
|
@ -578,51 +578,51 @@ void State::addInfoFor(BasicBlock &BB) {
|
|||
if (!Br || !Br->isConditional())
|
||||
return;
|
||||
|
||||
// If the condition is a chain of ORs and the false successor only has
|
||||
// the current block as predecessor, queue the negated conditions for the
|
||||
// false successor.
|
||||
Value *Cond = Br->getCondition();
|
||||
|
||||
// If the condition is a chain of ORs/AND and the successor only has the
|
||||
// current block as predecessor, queue conditions for the successor.
|
||||
Value *Op0, *Op1;
|
||||
if (match(Br->getCondition(), m_LogicalOr(m_Value(Op0), m_Value(Op1)))) {
|
||||
BasicBlock *FalseSuccessor = Br->getSuccessor(1);
|
||||
if (canAddSuccessor(BB, FalseSuccessor)) {
|
||||
if (match(Cond, m_LogicalOr(m_Value(Op0), m_Value(Op1))) ||
|
||||
match(Cond, m_LogicalAnd(m_Value(Op0), m_Value(Op1)))) {
|
||||
bool IsOr = match(Cond, m_LogicalOr());
|
||||
bool IsAnd = match(Cond, m_LogicalAnd());
|
||||
// If there's a select that matches both AND and OR, we need to commit to
|
||||
// one of the options. Arbitrarily pick OR.
|
||||
if (IsOr && IsAnd)
|
||||
IsAnd = false;
|
||||
|
||||
BasicBlock *Successor = Br->getSuccessor(IsOr ? 1 : 0);
|
||||
if (canAddSuccessor(BB, Successor)) {
|
||||
SmallVector<Value *> CondWorkList;
|
||||
SmallPtrSet<Value *, 8> SeenCond;
|
||||
auto QueueValue = [&CondWorkList, &SeenCond](Value *V) {
|
||||
if (SeenCond.insert(V).second)
|
||||
CondWorkList.push_back(V);
|
||||
};
|
||||
QueueValue(Op0);
|
||||
QueueValue(Op1);
|
||||
QueueValue(Op0);
|
||||
while (!CondWorkList.empty()) {
|
||||
Value *Cur = CondWorkList.pop_back_val();
|
||||
if (auto *Cmp = dyn_cast<ICmpInst>(Cur)) {
|
||||
WorkList.emplace_back(DT.getNode(FalseSuccessor), Cmp, true);
|
||||
WorkList.emplace_back(DT.getNode(Successor), Cmp, IsOr);
|
||||
continue;
|
||||
}
|
||||
if (match(Cur, m_LogicalOr(m_Value(Op0), m_Value(Op1)))) {
|
||||
QueueValue(Op0);
|
||||
if (IsOr && match(Cur, m_LogicalOr(m_Value(Op0), m_Value(Op1)))) {
|
||||
QueueValue(Op1);
|
||||
QueueValue(Op0);
|
||||
continue;
|
||||
}
|
||||
if (IsAnd && match(Cur, m_LogicalAnd(m_Value(Op0), m_Value(Op1)))) {
|
||||
QueueValue(Op1);
|
||||
QueueValue(Op0);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// If the condition is an AND of 2 compares and the true successor only has
|
||||
// the current block as predecessor, queue both conditions for the true
|
||||
// successor.
|
||||
if (match(Br->getCondition(), m_LogicalAnd(m_Value(Op0), m_Value(Op1))) &&
|
||||
isa<ICmpInst>(Op0) && isa<ICmpInst>(Op1)) {
|
||||
BasicBlock *TrueSuccessor = Br->getSuccessor(0);
|
||||
if (canAddSuccessor(BB, TrueSuccessor)) {
|
||||
WorkList.emplace_back(DT.getNode(TrueSuccessor), cast<ICmpInst>(Op0),
|
||||
false);
|
||||
WorkList.emplace_back(DT.getNode(TrueSuccessor), cast<ICmpInst>(Op1),
|
||||
false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
auto *CmpI = dyn_cast<ICmpInst>(Br->getCondition());
|
||||
if (!CmpI)
|
||||
return;
|
||||
|
|
|
@ -203,13 +203,13 @@ define i1 @test_and_chain_ule_1(i4 %x, i4 %y, i4 %z, i4 %a) {
|
|||
; CHECK: bb1:
|
||||
; CHECK-NEXT: [[T_1:%.*]] = icmp ule i4 [[X]], [[Z]]
|
||||
; CHECK-NEXT: [[T_2:%.*]] = icmp ule i4 [[X]], [[Y]]
|
||||
; CHECK-NEXT: [[R_1:%.*]] = xor i1 [[T_1]], [[T_2]]
|
||||
; CHECK-NEXT: [[R_1:%.*]] = xor i1 true, true
|
||||
; CHECK-NEXT: [[T_3:%.*]] = icmp ule i4 [[Y]], [[Z]]
|
||||
; CHECK-NEXT: [[R_2:%.*]] = xor i1 [[R_1]], [[T_3]]
|
||||
; CHECK-NEXT: [[R_2:%.*]] = xor i1 [[R_1]], true
|
||||
; CHECK-NEXT: [[T_4:%.*]] = icmp ule i4 3, [[X]]
|
||||
; CHECK-NEXT: [[R_3:%.*]] = xor i1 [[R_2]], [[T_4]]
|
||||
; CHECK-NEXT: [[R_3:%.*]] = xor i1 [[R_2]], true
|
||||
; CHECK-NEXT: [[T_5:%.*]] = icmp ule i4 3, [[A]]
|
||||
; CHECK-NEXT: [[R_4:%.*]] = xor i1 [[R_3]], [[T_5]]
|
||||
; CHECK-NEXT: [[R_4:%.*]] = xor i1 [[R_3]], true
|
||||
; CHECK-NEXT: [[C_5:%.*]] = icmp ule i4 [[X]], [[A]]
|
||||
; CHECK-NEXT: [[R_5:%.*]] = xor i1 [[R_4]], [[C_5]]
|
||||
; CHECK-NEXT: ret i1 [[R_5]]
|
||||
|
@ -291,13 +291,13 @@ define i1 @test_and_chain_ule_2(i4 %x, i4 %y, i4 %z, i4 %a) {
|
|||
; CHECK: bb1:
|
||||
; CHECK-NEXT: [[T_1:%.*]] = icmp ule i4 [[X]], [[Z]]
|
||||
; CHECK-NEXT: [[T_2:%.*]] = icmp ule i4 [[X]], [[Y]]
|
||||
; CHECK-NEXT: [[R_1:%.*]] = xor i1 [[T_1]], [[T_2]]
|
||||
; CHECK-NEXT: [[R_1:%.*]] = xor i1 true, true
|
||||
; CHECK-NEXT: [[T_3:%.*]] = icmp ule i4 [[Y]], [[Z]]
|
||||
; CHECK-NEXT: [[R_2:%.*]] = xor i1 [[R_1]], [[T_3]]
|
||||
; CHECK-NEXT: [[R_2:%.*]] = xor i1 [[R_1]], true
|
||||
; CHECK-NEXT: [[T_4:%.*]] = icmp ule i4 3, [[X]]
|
||||
; CHECK-NEXT: [[R_3:%.*]] = xor i1 [[R_2]], [[T_4]]
|
||||
; CHECK-NEXT: [[R_3:%.*]] = xor i1 [[R_2]], true
|
||||
; CHECK-NEXT: [[T_5:%.*]] = icmp ule i4 3, [[A]]
|
||||
; CHECK-NEXT: [[R_4:%.*]] = xor i1 [[R_3]], [[T_5]]
|
||||
; CHECK-NEXT: [[R_4:%.*]] = xor i1 [[R_3]], true
|
||||
; CHECK-NEXT: [[C_5:%.*]] = icmp ule i4 [[X]], [[A]]
|
||||
; CHECK-NEXT: [[R_5:%.*]] = xor i1 [[R_4]], [[C_5]]
|
||||
; CHECK-NEXT: ret i1 [[R_5]]
|
||||
|
@ -380,9 +380,9 @@ define i1 @test_and_chain_with_other_insts_ule(i4 %x, i4 %y, i4 %z, i4 %a, i1 %a
|
|||
; CHECK: bb1:
|
||||
; CHECK-NEXT: [[T_1:%.*]] = icmp ule i4 [[X]], [[Z]]
|
||||
; CHECK-NEXT: [[T_2:%.*]] = icmp ule i4 [[X]], [[Y]]
|
||||
; CHECK-NEXT: [[R_1:%.*]] = xor i1 [[T_1]], [[T_2]]
|
||||
; CHECK-NEXT: [[R_1:%.*]] = xor i1 true, true
|
||||
; CHECK-NEXT: [[T_3:%.*]] = icmp ule i4 [[Y]], [[Z]]
|
||||
; CHECK-NEXT: [[R_2:%.*]] = xor i1 [[R_1]], [[T_3]]
|
||||
; CHECK-NEXT: [[R_2:%.*]] = xor i1 [[R_1]], true
|
||||
; CHECK-NEXT: [[C_4:%.*]] = icmp ule i4 3, [[X]]
|
||||
; CHECK-NEXT: [[R_3:%.*]] = xor i1 [[R_2]], [[C_4]]
|
||||
; CHECK-NEXT: [[C_5:%.*]] = icmp ule i4 3, [[A:%.*]]
|
||||
|
@ -466,13 +466,13 @@ define i1 @test_and_chain_select_ule(i4 %x, i4 %y, i4 %z, i4 %a) {
|
|||
; CHECK: bb1:
|
||||
; CHECK-NEXT: [[T_1:%.*]] = icmp ule i4 [[X]], [[Z]]
|
||||
; CHECK-NEXT: [[T_2:%.*]] = icmp ule i4 [[X]], [[Y]]
|
||||
; CHECK-NEXT: [[R_1:%.*]] = xor i1 [[T_1]], [[T_2]]
|
||||
; CHECK-NEXT: [[R_1:%.*]] = xor i1 [[T_1]], true
|
||||
; CHECK-NEXT: [[T_3:%.*]] = icmp ule i4 [[Y]], [[Z]]
|
||||
; CHECK-NEXT: [[R_2:%.*]] = xor i1 [[R_1]], [[T_3]]
|
||||
; CHECK-NEXT: [[T_4:%.*]] = icmp ule i4 3, [[X]]
|
||||
; CHECK-NEXT: [[R_3:%.*]] = xor i1 [[R_2]], [[T_4]]
|
||||
; CHECK-NEXT: [[R_3:%.*]] = xor i1 [[R_2]], true
|
||||
; CHECK-NEXT: [[T_5:%.*]] = icmp ule i4 3, [[A]]
|
||||
; CHECK-NEXT: [[R_4:%.*]] = xor i1 [[R_3]], [[T_5]]
|
||||
; CHECK-NEXT: [[R_4:%.*]] = xor i1 [[R_3]], true
|
||||
; CHECK-NEXT: [[C_5:%.*]] = icmp ule i4 [[X]], [[A]]
|
||||
; CHECK-NEXT: [[R_5:%.*]] = xor i1 [[R_4]], [[C_5]]
|
||||
; CHECK-NEXT: ret i1 [[R_5]]
|
||||
|
|
Loading…
Reference in New Issue