diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp | 84 | 
1 files changed, 84 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/contrib/llvm-project/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp index 8b15bdb0aca3..fc2793bd7a13 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp @@ -6548,6 +6548,87 @@ bool CombinerHelper::tryFoldBoolSelectToLogic(GSelect *Select,    return false;  } +bool CombinerHelper::tryFoldSelectToIntMinMax(GSelect *Select, +                                              BuildFnTy &MatchInfo) { +  Register DstReg = Select->getReg(0); +  Register Cond = Select->getCondReg(); +  Register True = Select->getTrueReg(); +  Register False = Select->getFalseReg(); +  LLT DstTy = MRI.getType(DstReg); + +  // We need an G_ICMP on the condition register. +  GICmp *Cmp = getOpcodeDef<GICmp>(Cond, MRI); +  if (!Cmp) +    return false; + +  // We want to fold the icmp and replace the select. +  if (!MRI.hasOneNonDBGUse(Cmp->getReg(0))) +    return false; + +  CmpInst::Predicate Pred = Cmp->getCond(); +  // We need a larger or smaller predicate for +  // canonicalization. +  if (CmpInst::isEquality(Pred)) +    return false; + +  Register CmpLHS = Cmp->getLHSReg(); +  Register CmpRHS = Cmp->getRHSReg(); + +  // We can swap CmpLHS and CmpRHS for higher hitrate. +  if (True == CmpRHS && False == CmpLHS) { +    std::swap(CmpLHS, CmpRHS); +    Pred = CmpInst::getSwappedPredicate(Pred); +  } + +  // (icmp X, Y) ? X : Y -> integer minmax. +  // see matchSelectPattern in ValueTracking. +  // Legality between G_SELECT and integer minmax can differ. +  if (True == CmpLHS && False == CmpRHS) { +    switch (Pred) { +    case ICmpInst::ICMP_UGT: +    case ICmpInst::ICMP_UGE: { +      if (!isLegalOrBeforeLegalizer({TargetOpcode::G_UMAX, DstTy})) +        return false; +      MatchInfo = [=](MachineIRBuilder &B) { +        B.buildUMax(DstReg, True, False); +      }; +      return true; +    } +    case ICmpInst::ICMP_SGT: +    case ICmpInst::ICMP_SGE: { +      if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SMAX, DstTy})) +        return false; +      MatchInfo = [=](MachineIRBuilder &B) { +        B.buildSMax(DstReg, True, False); +      }; +      return true; +    } +    case ICmpInst::ICMP_ULT: +    case ICmpInst::ICMP_ULE: { +      if (!isLegalOrBeforeLegalizer({TargetOpcode::G_UMIN, DstTy})) +        return false; +      MatchInfo = [=](MachineIRBuilder &B) { +        B.buildUMin(DstReg, True, False); +      }; +      return true; +    } +    case ICmpInst::ICMP_SLT: +    case ICmpInst::ICMP_SLE: { +      if (!isLegalOrBeforeLegalizer({TargetOpcode::G_SMIN, DstTy})) +        return false; +      MatchInfo = [=](MachineIRBuilder &B) { +        B.buildSMin(DstReg, True, False); +      }; +      return true; +    } +    default: +      return false; +    } +  } + +  return false; +} +  bool CombinerHelper::matchSelect(MachineInstr &MI, BuildFnTy &MatchInfo) {    GSelect *Select = cast<GSelect>(&MI); @@ -6557,5 +6638,8 @@ bool CombinerHelper::matchSelect(MachineInstr &MI, BuildFnTy &MatchInfo) {    if (tryFoldBoolSelectToLogic(Select, MatchInfo))      return true; +  if (tryFoldSelectToIntMinMax(Select, MatchInfo)) +    return true; +    return false;  }  | 
