aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKai Nacke <kai@redstar.de>2022-09-08 09:15:12 -0400
committerKai Nacke <kai@redstar.de>2022-11-13 11:07:57 -0500
commitb99c558013e5bd99e91d9b78d732dc9d7bf21b94 (patch)
tree98f57607d6cdcb44fbd3b13c8d555a6279aed230
parentdb0b5cd5909e2e6a35a0d892f54868906be295d0 (diff)
downloadllvm-b99c558013e5bd99e91d9b78d732dc9d7bf21b94.zip
llvm-b99c558013e5bd99e91d9b78d732dc9d7bf21b94.tar.gz
llvm-b99c558013e5bd99e91d9b78d732dc9d7bf21b94.tar.bz2
[m88k] Add another combine pattern.
- Handles call to @llvm.usub.with.overflow.i32() - Turns carry into a bit - Adds some more tests
-rw-r--r--llvm/lib/Target/M88k/GISel/M88kGenRegisterBankInfo.def4
-rw-r--r--llvm/lib/Target/M88k/GISel/M88kLegalizerInfo.cpp5
-rw-r--r--llvm/lib/Target/M88k/GISel/M88kPostLegalizerCombiner.cpp50
-rw-r--r--llvm/lib/Target/M88k/M88kCombine.td15
-rw-r--r--llvm/test/CodeGen/M88k/add.ll27
5 files changed, 91 insertions, 10 deletions
diff --git a/llvm/lib/Target/M88k/GISel/M88kGenRegisterBankInfo.def b/llvm/lib/Target/M88k/GISel/M88kGenRegisterBankInfo.def
index 8cd362a..292981f 100644
--- a/llvm/lib/Target/M88k/GISel/M88kGenRegisterBankInfo.def
+++ b/llvm/lib/Target/M88k/GISel/M88kGenRegisterBankInfo.def
@@ -23,8 +23,8 @@ RegisterBankInfo::PartialMapping M88kGenRegisterBankInfo::PartMappings[]{
{0, 32, M88k::GRRegBank},
// 4: GPR 64-bit value.
{0, 64, M88k::GRRegBank},
- // 5: CR 32-bit value.
- {0, 32, M88k::CRRegBank},
+ // 5: CR 1-bit value.
+ {0, 1, M88k::CRRegBank},
};
// ValueMappings.
diff --git a/llvm/lib/Target/M88k/GISel/M88kLegalizerInfo.cpp b/llvm/lib/Target/M88k/GISel/M88kLegalizerInfo.cpp
index 8533953..d03779e 100644
--- a/llvm/lib/Target/M88k/GISel/M88kLegalizerInfo.cpp
+++ b/llvm/lib/Target/M88k/GISel/M88kLegalizerInfo.cpp
@@ -87,9 +87,10 @@ M88kLegalizerInfo::M88kLegalizerInfo(const M88kSubtarget &ST) {
all(typeInSet(0, {V8S8, V4S16, V2S32}), LegalityPredicate(IsMC88110)))
.clampScalar(0, S32, S32);
getActionDefinitionsBuilder({G_UADDO, G_UADDE, G_USUBO, G_USUBE})
- .legalFor({S32, S32})
+ .legalFor({{S32, S1}})
.clampScalar(0, S32, S32)
- .clampScalar(1, S32, S32);
+ .lower();
+ getActionDefinitionsBuilder({G_SADDO, G_SADDE, G_SSUBO, G_SSUBE}).lower();
getActionDefinitionsBuilder({G_MUL, G_UDIV})
.legalFor({S32})
.customIf(all(typeInSet(0, {S64}), LegalityPredicate(IsMC88110)))
diff --git a/llvm/lib/Target/M88k/GISel/M88kPostLegalizerCombiner.cpp b/llvm/lib/Target/M88k/GISel/M88kPostLegalizerCombiner.cpp
index 79ec7c40..65f6aee 100644
--- a/llvm/lib/Target/M88k/GISel/M88kPostLegalizerCombiner.cpp
+++ b/llvm/lib/Target/M88k/GISel/M88kPostLegalizerCombiner.cpp
@@ -109,9 +109,9 @@ bool applyAddCmpToSubAdd(MachineInstr &MI, MachineRegisterInfo &MRI,
std::tie(SrcRegA, SrcRegB, ZeroReg) = MatchInfo;
MachineIRBuilder B(MI);
- Register Carry = MRI.createGenericVirtualRegister(LLT::scalar(32));
+ Register Carry = MRI.createGenericVirtualRegister(LLT::scalar(1));
Register UnusedReg = MRI.createGenericVirtualRegister(LLT::scalar(32));
- Register UnusedCarry = MRI.createGenericVirtualRegister(LLT::scalar(32));
+ Register UnusedCarry = MRI.createGenericVirtualRegister(LLT::scalar(1));
B.buildInstr(TargetOpcode::G_USUBO, {UnusedReg, Carry}, {ZeroReg, SrcRegB});
B.buildInstr(TargetOpcode::G_UADDE, {DstReg, UnusedCarry},
@@ -158,9 +158,9 @@ bool matchAddCmpToSubAdd2(MachineInstr &MI, MachineOperand &Src1,
return false;
}
- Register Carry = MRI.createGenericVirtualRegister(LLT::scalar(32));
+ Register Carry = MRI.createGenericVirtualRegister(LLT::scalar(1));
Register UnusedReg = MRI.createGenericVirtualRegister(LLT::scalar(32));
- Register UnusedCarry = MRI.createGenericVirtualRegister(LLT::scalar(32));
+ Register UnusedCarry = MRI.createGenericVirtualRegister(LLT::scalar(1));
MatchInfo = [=](MachineIRBuilder &B) {
if (Pred != CmpInst::ICMP_EQ)
@@ -223,9 +223,9 @@ bool matchAddSubFromAddICmp(MachineInstr &MI, MachineRegisterInfo &MRI,
return false;
}
- Register Carry = MRI.createGenericVirtualRegister(LLT::scalar(32));
+ Register Carry = MRI.createGenericVirtualRegister(LLT::scalar(1));
Register UnusedReg = MRI.createGenericVirtualRegister(LLT::scalar(32));
- Register UnusedCarry = MRI.createGenericVirtualRegister(LLT::scalar(32));
+ Register UnusedCarry = MRI.createGenericVirtualRegister(LLT::scalar(1));
MatchInfo = [=](MachineIRBuilder &B) {
if (Pred != CmpInst::ICMP_EQ)
@@ -238,6 +238,44 @@ bool matchAddSubFromAddICmp(MachineInstr &MI, MachineRegisterInfo &MRI,
return true;
}
+// Match
+// Unused, CarryBit = G_USUBU SrcB, SrcC
+// Carry = G_ZEXT CarryBit
+// Dst = G_UADD SrcA, Carry
+// The returned MatchInfo transforms this sequence into
+// Unused, Carry = G_USUBU SrcB, SrcC
+// Dst, UnusedCarry = G_UADDE SrcA, Zero, Carry
+// inserting a zero constant value if necessary.
+bool matchAddSubFromAddSub(MachineInstr &MI, MachineRegisterInfo &MRI,
+ BuildFnTy &MatchInfo) {
+ assert(MI.getOpcode() == TargetOpcode::G_ADD);
+
+ Register DstReg = MI.getOperand(0).getReg();
+ Register SrcRegA;
+ Register Carry;
+ Register ZeroReg = MRI.createGenericVirtualRegister(LLT::scalar(32));
+ MachineInstr *SubMI;
+ if (!mi_match(
+ MI, MRI,
+ m_GAdd(m_Reg(SrcRegA), m_GZExt(m_Reg(Carry)))))
+ return false;
+ SubMI = MRI.getVRegDef(Carry);
+ if (SubMI->getOpcode() != TargetOpcode::G_USUBO)
+ return false;
+ if (SubMI->getOperand(1).getReg() != Carry)
+ return false;
+
+ Register UnusedCarry = MRI.createGenericVirtualRegister(LLT::scalar(1));
+
+ MatchInfo = [=](MachineIRBuilder &B) {
+ B.buildConstant(ZeroReg, 0);
+ B.buildInstr(TargetOpcode::G_UADDE, {DstReg, UnusedCarry},
+ {SrcRegA, ZeroReg, Carry});
+ };
+
+ return true;
+}
+
#define M88KPOSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_DEPS
#include "M88kGenPostLegalizeGICombiner.inc"
#undef M88KPOSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_DEPS
diff --git a/llvm/lib/Target/M88k/M88kCombine.td b/llvm/lib/Target/M88k/M88kCombine.td
index e61e168..63f51fe 100644
--- a/llvm/lib/Target/M88k/M88kCombine.td
+++ b/llvm/lib/Target/M88k/M88kCombine.td
@@ -93,12 +93,27 @@ def addsub_from_addicmp : GICombineRule<
[{ return matchAddSubFromAddICmp(*${root}, MRI, ${matchinfo}); }]),
(apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
+// Combine
+// Unused, CarryBit = G_USUBU SrcB, SrcC
+// Carry = G_ZEXT CarryBit
+// Dst = G_UADD SrcA, Carry
+// into the instruction sequence
+// Unused, Carry = G_USUBU SrcB, SrcC
+// Dst, UnusedCarry = G_UADDE SrcA, Zero, Carry
+// inserting a zero constant value if necessary.
+def addsub_from_addsub : GICombineRule<
+ (defs root:$root, build_fn_matchinfo:$matchinfo),
+ (match (wip_match_opcode G_ADD):$root,
+ [{ return matchAddSubFromAddSub(*${root}, MRI, ${matchinfo}); }]),
+ (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
+
// Post-legalization combines which are primarily optimizations.
def M88kPostLegalizerCombinerHelper: GICombinerHelper<
"M88kGenPostLegalizerCombinerHelper", [
//subadd_from_icmpadd1,
//subadd_from_icmpadd2,
addsub_from_addicmp,
+ addsub_from_addsub,
form_bitfield_extract, // Some rules require legalizer
rotate_out_of_range // Required for left rotates, which produce a negative constant
]> {
diff --git a/llvm/test/CodeGen/M88k/add.ll b/llvm/test/CodeGen/M88k/add.ll
index b570d464..c8d9050 100644
--- a/llvm/test/CodeGen/M88k/add.ll
+++ b/llvm/test/CodeGen/M88k/add.ll
@@ -65,3 +65,30 @@ define i32 @f7(i32 %a, i32 %b) {
%sum = add i32 %conv, %b
ret i32 %sum
}
+
+; Same, but using intrinsic
+define i32 @f8(i32 %a, i32 %b) {
+; CHECK-LABEL: f8:
+; CHECK: subu.co %r2, %r4, %r2
+; CHECK-NEXT: addu.ci %r2, %r3, %r4
+; CHECK-NEXT: jmp %r1
+ %res = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 0, i32 %a)
+ %carrybit = extractvalue { i32, i1 } %res, 1
+ %carry = zext i1 %carrybit to i32
+ %sum = add i32 %carry, %b
+ ret i32 %sum
+}
+
+declare { i32, i1 } @llvm.usub.with.overflow.i32(i32, i32)
+
+; Special case: return (a >= b) + c
+define i32 @f9(i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: f9:
+; CHECK: subu.co %r2, %r3, %r2
+; CHECK-NEXT: addu.ci %r2, %r4, %r5
+; CHECK-NEXT: jmp %r1
+ %cmp = icmp uge i32 %a, %b
+ %conv = zext i1 %cmp to i32
+ %sum = add i32 %conv, %c
+ ret i32 %sum
+}