summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/GlobalISel
diff options
context:
space:
mode:
authorQuentin Colombet <quentin.colombet@gmail.com>2019-03-14 01:37:13 +0000
committerQuentin Colombet <quentin.colombet@gmail.com>2019-03-14 01:37:13 +0000
commite77e5f44b871faa775b2cfa289b35f900f9443ab (patch)
tree42c308960e044b69f92972ce4d5f29036b04b6e9 /llvm/lib/CodeGen/GlobalISel
parent591040adc2666006b7242520f8b55e8960b07d71 (diff)
downloadbcm5719-llvm-e77e5f44b871faa775b2cfa289b35f900f9443ab.tar.gz
bcm5719-llvm-e77e5f44b871faa775b2cfa289b35f900f9443ab.zip
[GlobalISel][Utils] Add a getConstantVRegVal variant that looks through instrs
getConstantVRegVal used to only look for G_CONSTANT when looking at unboxing the value of a vreg. However, constants are sometimes not directly used and are hidden behind trunc, s|zext or copy chain of computation. In particular this may be introduced by the legalization process that doesn't want to simplify these patterns because it can lead to infine loop when legalizing a constant. To circumvent that problem, add a new variant of getConstantVRegVal, named getConstantVRegValWithLookThrough, that allow to look through extensions. Differential Revision: https://reviews.llvm.org/D59227 llvm-svn: 356116
Diffstat (limited to 'llvm/lib/CodeGen/GlobalISel')
-rw-r--r--llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp4
-rw-r--r--llvm/lib/CodeGen/GlobalISel/Utils.cpp66
2 files changed, 60 insertions, 10 deletions
diff --git a/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp b/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp
index d8cd71f64b9..a449e9dec41 100644
--- a/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp
@@ -49,8 +49,8 @@ bool InstructionSelector::isOperandImmEqual(
const MachineOperand &MO, int64_t Value,
const MachineRegisterInfo &MRI) const {
if (MO.isReg() && MO.getReg())
- if (auto VRegVal = getConstantVRegVal(MO.getReg(), MRI))
- return *VRegVal == Value;
+ if (auto VRegVal = getConstantVRegValWithLookThrough(MO.getReg(), MRI))
+ return VRegVal->Value == Value;
return false;
}
diff --git a/llvm/lib/CodeGen/GlobalISel/Utils.cpp b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
index 237d892c7f7..d65328be39c 100644
--- a/llvm/lib/CodeGen/GlobalISel/Utils.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
@@ -183,18 +183,68 @@ void llvm::reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC,
Optional<int64_t> llvm::getConstantVRegVal(unsigned VReg,
const MachineRegisterInfo &MRI) {
- MachineInstr *MI = MRI.getVRegDef(VReg);
- if (MI->getOpcode() != TargetOpcode::G_CONSTANT)
+ Optional<ValueAndVReg> ValAndVReg =
+ getConstantVRegValWithLookThrough(VReg, MRI, /*LookThroughInstrs*/ false);
+ assert((!ValAndVReg || ValAndVReg->VReg == VReg) &&
+ "Value found while looking through instrs");
+ if (!ValAndVReg)
+ return None;
+ return ValAndVReg->Value;
+}
+
+Optional<ValueAndVReg> llvm::getConstantVRegValWithLookThrough(
+ unsigned VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs) {
+ SmallVector<std::pair<unsigned, unsigned>, 4> SeenOpcodes;
+ MachineInstr *MI;
+ while ((MI = MRI.getVRegDef(VReg)) &&
+ MI->getOpcode() != TargetOpcode::G_CONSTANT && LookThroughInstrs) {
+ switch (MI->getOpcode()) {
+ case TargetOpcode::G_TRUNC:
+ case TargetOpcode::G_SEXT:
+ case TargetOpcode::G_ZEXT:
+ SeenOpcodes.push_back(std::make_pair(
+ MI->getOpcode(),
+ MRI.getType(MI->getOperand(0).getReg()).getSizeInBits()));
+ VReg = MI->getOperand(1).getReg();
+ break;
+ case TargetOpcode::COPY:
+ VReg = MI->getOperand(1).getReg();
+ if (TargetRegisterInfo::isPhysicalRegister(VReg))
+ return None;
+ break;
+ default:
+ return None;
+ }
+ }
+ if (!MI || MI->getOpcode() != TargetOpcode::G_CONSTANT ||
+ (!MI->getOperand(1).isImm() && !MI->getOperand(1).isCImm()))
return None;
- if (MI->getOperand(1).isImm())
- return MI->getOperand(1).getImm();
+ const MachineOperand &CstVal = MI->getOperand(1);
+ unsigned BitWidth = MRI.getType(MI->getOperand(0).getReg()).getSizeInBits();
+ APInt Val = CstVal.isImm() ? APInt(BitWidth, CstVal.getImm())
+ : CstVal.getCImm()->getValue();
+ assert(Val.getBitWidth() == BitWidth &&
+ "Value bitwidth doesn't match definition type");
+ while (!SeenOpcodes.empty()) {
+ std::pair<unsigned, unsigned> OpcodeAndSize = SeenOpcodes.pop_back_val();
+ switch (OpcodeAndSize.first) {
+ case TargetOpcode::G_TRUNC:
+ Val = Val.trunc(OpcodeAndSize.second);
+ break;
+ case TargetOpcode::G_SEXT:
+ Val = Val.sext(OpcodeAndSize.second);
+ break;
+ case TargetOpcode::G_ZEXT:
+ Val = Val.zext(OpcodeAndSize.second);
+ break;
+ }
+ }
- if (MI->getOperand(1).isCImm() &&
- MI->getOperand(1).getCImm()->getBitWidth() <= 64)
- return MI->getOperand(1).getCImm()->getSExtValue();
+ if (Val.getBitWidth() > 64)
+ return None;
- return None;
+ return ValueAndVReg{Val.getSExtValue(), VReg};
}
const llvm::ConstantFP* llvm::getConstantFPVRegVal(unsigned VReg,
OpenPOWER on IntegriCloud