Skip to content

Commit 0b91b1a

Browse files
committed
[AArch64][GlobalISel] Legalize and Lower Funnel Shift for GlobalISel
Recognise G_FSHR with constant shift amount as a legal instruction. Lowers G_FSHL with constant shift to G_FSHR. If shift amount is non-constant, generic lowering is applied to the instruction. Differential Revision: https://reviews.llvm.org/D155484
1 parent 576b184 commit 0b91b1a

File tree

5 files changed

+1546
-250
lines changed

5 files changed

+1546
-250
lines changed

llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -898,7 +898,9 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
898898
getActionDefinitionsBuilder({G_UADDSAT, G_USUBSAT})
899899
.lowerIf([=](const LegalityQuery &Q) { return Q.Types[0].isScalar(); });
900900

901-
getActionDefinitionsBuilder({G_FSHL, G_FSHR}).lower();
901+
getActionDefinitionsBuilder({G_FSHL, G_FSHR})
902+
.customFor({{s32, s32}, {s32, s64}, {s64, s64}})
903+
.lower();
902904

903905
getActionDefinitionsBuilder(G_ROTR)
904906
.legalFor({{s32, s64}, {s64, s64}})
@@ -1003,6 +1005,9 @@ bool AArch64LegalizerInfo::legalizeCustom(LegalizerHelper &Helper,
10031005
case TargetOpcode::G_SBFX:
10041006
case TargetOpcode::G_UBFX:
10051007
return legalizeBitfieldExtract(MI, MRI, Helper);
1008+
case TargetOpcode::G_FSHL:
1009+
case TargetOpcode::G_FSHR:
1010+
return legalizeFunnelShift(MI, MRI, MIRBuilder, Observer, Helper);
10061011
case TargetOpcode::G_ROTR:
10071012
return legalizeRotate(MI, MRI, Helper);
10081013
case TargetOpcode::G_CTPOP:
@@ -1023,6 +1028,59 @@ bool AArch64LegalizerInfo::legalizeCustom(LegalizerHelper &Helper,
10231028
llvm_unreachable("expected switch to return");
10241029
}
10251030

1031+
bool AArch64LegalizerInfo::legalizeFunnelShift(MachineInstr &MI,
1032+
MachineRegisterInfo &MRI,
1033+
MachineIRBuilder &MIRBuilder,
1034+
GISelChangeObserver &Observer,
1035+
LegalizerHelper &Helper) const {
1036+
assert(MI.getOpcode() == TargetOpcode::G_FSHL ||
1037+
MI.getOpcode() == TargetOpcode::G_FSHR);
1038+
1039+
// Keep as G_FSHR if shift amount is a G_CONSTANT, else use generic
1040+
// lowering
1041+
Register ShiftNo = MI.getOperand(3).getReg();
1042+
LLT ShiftTy = MRI.getType(ShiftNo);
1043+
auto VRegAndVal = getIConstantVRegValWithLookThrough(ShiftNo, MRI);
1044+
1045+
// Adjust shift amount according to Opcode (FSHL/FSHR)
1046+
// Convert FSHL to FSHR
1047+
LLT OperationTy = MRI.getType(MI.getOperand(0).getReg());
1048+
APInt BitWidth(ShiftTy.getSizeInBits(), OperationTy.getSizeInBits(), false);
1049+
1050+
// Lower non-constant shifts and leave zero shifts to the optimizer.
1051+
if (!VRegAndVal || VRegAndVal->Value.urem(BitWidth) == 0)
1052+
return (Helper.lowerFunnelShiftAsShifts(MI) ==
1053+
LegalizerHelper::LegalizeResult::Legalized);
1054+
1055+
APInt Amount = VRegAndVal->Value.urem(BitWidth);
1056+
1057+
Amount = MI.getOpcode() == TargetOpcode::G_FSHL ? BitWidth - Amount : Amount;
1058+
1059+
// If the instruction is G_FSHR, has a 64-bit G_CONSTANT for shift amount
1060+
// in the range of 0 <-> BitWidth, it is legal
1061+
if (ShiftTy.getSizeInBits() == 64 && MI.getOpcode() == TargetOpcode::G_FSHR &&
1062+
VRegAndVal->Value.ult(BitWidth))
1063+
return true;
1064+
1065+
// Cast the ShiftNumber to a 64-bit type
1066+
auto Cast64 = MIRBuilder.buildConstant(LLT::scalar(64), Amount.zext(64));
1067+
1068+
if (MI.getOpcode() == TargetOpcode::G_FSHR) {
1069+
Observer.changingInstr(MI);
1070+
MI.getOperand(3).setReg(Cast64.getReg(0));
1071+
Observer.changedInstr(MI);
1072+
}
1073+
// If Opcode is FSHL, remove the FSHL instruction and create a FSHR
1074+
// instruction
1075+
else if (MI.getOpcode() == TargetOpcode::G_FSHL) {
1076+
MIRBuilder.buildInstr(TargetOpcode::G_FSHR, {MI.getOperand(0).getReg()},
1077+
{MI.getOperand(1).getReg(), MI.getOperand(2).getReg(),
1078+
Cast64.getReg(0)});
1079+
MI.eraseFromParent();
1080+
}
1081+
return true;
1082+
}
1083+
10261084
bool AArch64LegalizerInfo::legalizeRotate(MachineInstr &MI,
10271085
MachineRegisterInfo &MRI,
10281086
LegalizerHelper &Helper) const {

llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ class AArch64LegalizerInfo : public LegalizerInfo {
5151
LegalizerHelper &Helper) const;
5252
bool legalizeRotate(MachineInstr &MI, MachineRegisterInfo &MRI,
5353
LegalizerHelper &Helper) const;
54+
bool legalizeFunnelShift(MachineInstr &MI, MachineRegisterInfo &MRI,
55+
MachineIRBuilder &MIRBuilder,
56+
GISelChangeObserver &Observer,
57+
LegalizerHelper &Helper) const;
5458
bool legalizeCTPOP(MachineInstr &MI, MachineRegisterInfo &MRI,
5559
LegalizerHelper &Helper) const;
5660
bool legalizeAtomicCmpxchg128(MachineInstr &MI, MachineRegisterInfo &MRI,

0 commit comments

Comments
 (0)