summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
authorJessica Paquette <jpaquette@apple.com>2019-05-24 19:35:25 +0000
committerJessica Paquette <jpaquette@apple.com>2019-05-24 19:35:25 +0000
commit56503865ed4d034d46efd84b274c42428fb61d9f (patch)
tree24d8cf694c4461a987e8a135ecb700d0dde02f25 /llvm/lib/Target
parent0cdc5dddca009422ee6a1d72b487fb5c54a654db (diff)
downloadbcm5719-llvm-56503865ed4d034d46efd84b274c42428fb61d9f.tar.gz
bcm5719-llvm-56503865ed4d034d46efd84b274c42428fb61d9f.zip
[GlobalISel][AArch64] Improve register bank mappings for G_SELECT
The fcsel and csel instructions differ in only the register banks they work on. So, they're entirely interchangeable otherwise. With this in mind, this does two things: - Teach AArch64RegisterBankInfo to consider the inputs to G_SELECT as well as the outputs. - Teach it to choose the best register bank mapping based off the constraints of the inputs and outputs. The "best" in this case means the one that requires the smallest number of copies to properly emit a fcsel/csel. For example, if the inputs are all already going to be on FPRs, we should emit a fcsel, even if the output is a GPR. This costs one copy to produce the result, but saves us from copying the inputs into GPRs. Also update the regbank-select.mir to check that we end up with the right select instruction. Differential Revision: https://reviews.llvm.org/D62267 llvm-svn: 361665
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/AArch64/AArch64RegisterBankInfo.cpp55
1 files changed, 49 insertions, 6 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterBankInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterBankInfo.cpp
index 7fdcde44e51..699343614cc 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterBankInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64RegisterBankInfo.cpp
@@ -679,15 +679,58 @@ AArch64RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
// If the destination is FPR, preserve that.
if (OpRegBankIdx[0] != PMI_FirstGPR)
break;
+
+ // If we're taking in vectors, we have no choice but to put everything on
+ // FPRs.
LLT SrcTy = MRI.getType(MI.getOperand(2).getReg());
- if (SrcTy.isVector() ||
- any_of(MRI.use_instructions(MI.getOperand(0).getReg()),
- [&](MachineInstr &MI) { return HasFPConstraints(MI); })) {
- // Set the register bank of every operand to FPR.
- for (unsigned Idx = 0, NumOperands = MI.getNumOperands();
- Idx < NumOperands; ++Idx)
+ if (SrcTy.isVector()) {
+ for (unsigned Idx = 0; Idx < 4; ++Idx)
OpRegBankIdx[Idx] = PMI_FirstFPR;
+ break;
+ }
+
+ // Try to minimize the number of copies. If we have more floating point
+ // constrained values than not, then we'll put everything on FPR. Otherwise,
+ // everything has to be on GPR.
+ unsigned NumFP = 0;
+
+ // Check if the uses of the result always produce floating point values.
+ //
+ // For example:
+ //
+ // %z = G_SELECT %cond %x %y
+ // fpr = G_FOO %z ...
+ if (any_of(MRI.use_instructions(MI.getOperand(0).getReg()),
+ [&](MachineInstr &MI) { return HasFPConstraints(MI); }))
+ ++NumFP;
+
+ // Check if the defs of the source values always produce floating point
+ // values.
+ //
+ // For example:
+ //
+ // %x = G_SOMETHING_ALWAYS_FLOAT %a ...
+ // %z = G_SELECT %cond %x %y
+ //
+ // Also check whether or not the sources have already been decided to be
+ // FPR. Keep track of this.
+ //
+ // This doesn't check the condition, since it's just whatever is in NZCV.
+ // This isn't passed explicitly in a register to fcsel/csel.
+ for (unsigned Idx = 2; Idx < 4; ++Idx) {
+ unsigned VReg = MI.getOperand(Idx).getReg();
+ MachineInstr *DefMI = MRI.getVRegDef(VReg);
+ if (getRegBank(VReg, MRI, TRI) == &AArch64::FPRRegBank ||
+ HasFPConstraints(*DefMI))
+ ++NumFP;
}
+
+ // If we have more FP constraints than not, then move everything over to
+ // FPR.
+ if (NumFP >= 2)
+ for (unsigned Idx = 0; Idx < 4; ++Idx)
+ OpRegBankIdx[Idx] = PMI_FirstFPR;
+
break;
}
case TargetOpcode::G_UNMERGE_VALUES: {
OpenPOWER on IntegriCloud