
There are a number of backends (specifically AArch64, AMDGPU, Mips, and RISCV) which contain a “TODO: make CombinerHelper methods const” comment. This PR does just that and makes all of the CombinerHelper methods const, removes the TODO comments and makes the associated instances const. This change makes some sense because the CombinerHelper class simply modifies the state of _other_ objects to which it holds pointers or references. Note that AMDGPU contains an identical comment for an instance of AMDGPUCombinerHelper (a subclass of CombinerHelper). I deliberately haven’t modified the methods of that class in order to limit the scope of the change. I’m happy to do so either now or as a follow-up.
143 lines
4.6 KiB
C++
143 lines
4.6 KiB
C++
//===- 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"
|
|
#include <cstdlib>
|
|
|
|
#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;
|
|
}
|