1 //===- CombinerHelperCompares.cpp------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements CombinerHelper for G_ICMP. 10 // 11 //===----------------------------------------------------------------------===// 12 #include "llvm/CodeGen/GlobalISel/CombinerHelper.h" 13 #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h" 14 #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" 15 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" 16 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" 17 #include "llvm/CodeGen/GlobalISel/Utils.h" 18 #include "llvm/CodeGen/MachineInstr.h" 19 #include "llvm/CodeGen/MachineOperand.h" 20 #include "llvm/CodeGen/MachineRegisterInfo.h" 21 #include "llvm/IR/Instructions.h" 22 #include "llvm/Support/Casting.h" 23 #include <cstdlib> 24 25 #define DEBUG_TYPE "gi-combiner" 26 27 using namespace llvm; 28 29 bool CombinerHelper::constantFoldICmp(const GICmp &ICmp, 30 const GIConstant &LHSCst, 31 const GIConstant &RHSCst, 32 BuildFnTy &MatchInfo) const { 33 if (LHSCst.getKind() != GIConstant::GIConstantKind::Scalar) 34 return false; 35 36 Register Dst = ICmp.getReg(0); 37 LLT DstTy = MRI.getType(Dst); 38 39 if (!isConstantLegalOrBeforeLegalizer(DstTy)) 40 return false; 41 42 CmpInst::Predicate Pred = ICmp.getCond(); 43 APInt LHS = LHSCst.getScalarValue(); 44 APInt RHS = RHSCst.getScalarValue(); 45 46 bool Result = ICmpInst::compare(LHS, RHS, Pred); 47 48 MatchInfo = [=](MachineIRBuilder &B) { 49 if (Result) 50 B.buildConstant(Dst, getICmpTrueVal(getTargetLowering(), 51 /*IsVector=*/DstTy.isVector(), 52 /*IsFP=*/false)); 53 else 54 B.buildConstant(Dst, 0); 55 }; 56 57 return true; 58 } 59 60 bool CombinerHelper::constantFoldFCmp(const GFCmp &FCmp, 61 const GFConstant &LHSCst, 62 const GFConstant &RHSCst, 63 BuildFnTy &MatchInfo) const { 64 if (LHSCst.getKind() != GFConstant::GFConstantKind::Scalar) 65 return false; 66 67 Register Dst = FCmp.getReg(0); 68 LLT DstTy = MRI.getType(Dst); 69 70 if (!isConstantLegalOrBeforeLegalizer(DstTy)) 71 return false; 72 73 CmpInst::Predicate Pred = FCmp.getCond(); 74 APFloat LHS = LHSCst.getScalarValue(); 75 APFloat RHS = RHSCst.getScalarValue(); 76 77 bool Result = FCmpInst::compare(LHS, RHS, Pred); 78 79 MatchInfo = [=](MachineIRBuilder &B) { 80 if (Result) 81 B.buildConstant(Dst, getICmpTrueVal(getTargetLowering(), 82 /*IsVector=*/DstTy.isVector(), 83 /*IsFP=*/true)); 84 else 85 B.buildConstant(Dst, 0); 86 }; 87 88 return true; 89 } 90 91 bool CombinerHelper::matchCanonicalizeICmp(const MachineInstr &MI, 92 BuildFnTy &MatchInfo) const { 93 const GICmp *Cmp = cast<GICmp>(&MI); 94 95 Register Dst = Cmp->getReg(0); 96 Register LHS = Cmp->getLHSReg(); 97 Register RHS = Cmp->getRHSReg(); 98 99 CmpInst::Predicate Pred = Cmp->getCond(); 100 assert(CmpInst::isIntPredicate(Pred) && "Not an integer compare!"); 101 if (auto CLHS = GIConstant::getConstant(LHS, MRI)) { 102 if (auto CRHS = GIConstant::getConstant(RHS, MRI)) 103 return constantFoldICmp(*Cmp, *CLHS, *CRHS, MatchInfo); 104 105 // If we have a constant, make sure it is on the RHS. 106 std::swap(LHS, RHS); 107 Pred = CmpInst::getSwappedPredicate(Pred); 108 109 MatchInfo = [=](MachineIRBuilder &B) { B.buildICmp(Pred, Dst, LHS, RHS); }; 110 return true; 111 } 112 113 return false; 114 } 115 116 bool CombinerHelper::matchCanonicalizeFCmp(const MachineInstr &MI, 117 BuildFnTy &MatchInfo) const { 118 const GFCmp *Cmp = cast<GFCmp>(&MI); 119 120 Register Dst = Cmp->getReg(0); 121 Register LHS = Cmp->getLHSReg(); 122 Register RHS = Cmp->getRHSReg(); 123 124 CmpInst::Predicate Pred = Cmp->getCond(); 125 assert(CmpInst::isFPPredicate(Pred) && "Not an FP compare!"); 126 127 if (auto CLHS = GFConstant::getConstant(LHS, MRI)) { 128 if (auto CRHS = GFConstant::getConstant(RHS, MRI)) 129 return constantFoldFCmp(*Cmp, *CLHS, *CRHS, MatchInfo); 130 131 // If we have a constant, make sure it is on the RHS. 132 std::swap(LHS, RHS); 133 Pred = CmpInst::getSwappedPredicate(Pred); 134 135 MatchInfo = [=](MachineIRBuilder &B) { 136 B.buildFCmp(Pred, Dst, LHS, RHS, Cmp->getFlags()); 137 }; 138 return true; 139 } 140 141 return false; 142 } 143