| //===- CombinerHelperCompares.cpp------------------------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // This file implements CombinerHelper for G_ICMP. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/CodeGen/GlobalISel/CombinerHelper.h" | |
| #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" | |
| #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" | |
| #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" | |
| #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" | |
| #include "llvm/CodeGen/GlobalISel/Utils.h" | |
| #include "llvm/CodeGen/MachineInstr.h" | |
| #include "llvm/CodeGen/MachineOperand.h" | |
| #include "llvm/CodeGen/MachineRegisterInfo.h" | |
| #include "llvm/IR/Instructions.h" | |
| #include "llvm/Support/Casting.h" | |
| #define DEBUG_TYPE "gi-combiner" | |
| using namespace llvm; | |
| bool CombinerHelper::constantFoldICmp(const GICmp &ICmp, | |
| const GIConstant &LHSCst, | |
| const GIConstant &RHSCst, | |
| BuildFnTy &MatchInfo) const { | |
| if (LHSCst.getKind() != GIConstant::GIConstantKind::Scalar) | |
| return false; | |
| Register Dst = ICmp.getReg(0); | |
| LLT DstTy = MRI.getType(Dst); | |
| if (!isConstantLegalOrBeforeLegalizer(DstTy)) | |
| return false; | |
| CmpInst::Predicate Pred = ICmp.getCond(); | |
| APInt LHS = LHSCst.getScalarValue(); | |
| APInt RHS = RHSCst.getScalarValue(); | |
| bool Result = ICmpInst::compare(LHS, RHS, Pred); | |
| MatchInfo = [=](MachineIRBuilder &B) { | |
| if (Result) | |
| B.buildConstant(Dst, getICmpTrueVal(getTargetLowering(), | |
| /*IsVector=*/DstTy.isVector(), | |
| /*IsFP=*/false)); | |
| else | |
| B.buildConstant(Dst, 0); | |
| }; | |
| return true; | |
| } | |
| bool CombinerHelper::constantFoldFCmp(const GFCmp &FCmp, | |
| const GFConstant &LHSCst, | |
| const GFConstant &RHSCst, | |
| BuildFnTy &MatchInfo) const { | |
| if (LHSCst.getKind() != GFConstant::GFConstantKind::Scalar) | |
| return false; | |
| Register Dst = FCmp.getReg(0); | |
| LLT DstTy = MRI.getType(Dst); | |
| if (!isConstantLegalOrBeforeLegalizer(DstTy)) | |
| return false; | |
| CmpInst::Predicate Pred = FCmp.getCond(); | |
| APFloat LHS = LHSCst.getScalarValue(); | |
| APFloat RHS = RHSCst.getScalarValue(); | |
| bool Result = FCmpInst::compare(LHS, RHS, Pred); | |
| MatchInfo = [=](MachineIRBuilder &B) { | |
| if (Result) | |
| B.buildConstant(Dst, getICmpTrueVal(getTargetLowering(), | |
| /*IsVector=*/DstTy.isVector(), | |
| /*IsFP=*/true)); | |
| else | |
| B.buildConstant(Dst, 0); | |
| }; | |
| return true; | |
| } | |
| bool CombinerHelper::matchCanonicalizeICmp(const MachineInstr &MI, | |
| BuildFnTy &MatchInfo) const { | |
| const GICmp *Cmp = cast<GICmp>(&MI); | |
| Register Dst = Cmp->getReg(0); | |
| Register LHS = Cmp->getLHSReg(); | |
| Register RHS = Cmp->getRHSReg(); | |
| CmpInst::Predicate Pred = Cmp->getCond(); | |
| assert(CmpInst::isIntPredicate(Pred) && "Not an integer compare!"); | |
| if (auto CLHS = GIConstant::getConstant(LHS, MRI)) { | |
| if (auto CRHS = GIConstant::getConstant(RHS, MRI)) | |
| return constantFoldICmp(*Cmp, *CLHS, *CRHS, MatchInfo); | |
| // If we have a constant, make sure it is on the RHS. | |
| std::swap(LHS, RHS); | |
| Pred = CmpInst::getSwappedPredicate(Pred); | |
| MatchInfo = [=](MachineIRBuilder &B) { B.buildICmp(Pred, Dst, LHS, RHS); }; | |
| return true; | |
| } | |
| return false; | |
| } | |
| bool CombinerHelper::matchCanonicalizeFCmp(const MachineInstr &MI, | |
| BuildFnTy &MatchInfo) const { | |
| const GFCmp *Cmp = cast<GFCmp>(&MI); | |
| Register Dst = Cmp->getReg(0); | |
| Register LHS = Cmp->getLHSReg(); | |
| Register RHS = Cmp->getRHSReg(); | |
| CmpInst::Predicate Pred = Cmp->getCond(); | |
| assert(CmpInst::isFPPredicate(Pred) && "Not an FP compare!"); | |
| if (auto CLHS = GFConstant::getConstant(LHS, MRI)) { | |
| if (auto CRHS = GFConstant::getConstant(RHS, MRI)) | |
| return constantFoldFCmp(*Cmp, *CLHS, *CRHS, MatchInfo); | |
| // If we have a constant, make sure it is on the RHS. | |
| std::swap(LHS, RHS); | |
| Pred = CmpInst::getSwappedPredicate(Pred); | |
| MatchInfo = [=](MachineIRBuilder &B) { | |
| B.buildFCmp(Pred, Dst, LHS, RHS, Cmp->getFlags()); | |
| }; | |
| return true; | |
| } | |
| return false; | |
| } |