aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKai Nacke <kai@redstar.de>2022-09-10 12:56:41 -0400
committerKai Nacke <kai@redstar.de>2022-11-13 11:07:58 -0500
commitba9b5964955e5dd6b28683b93da492950cc6d957 (patch)
tree55508521a8c11c6de62fec00b8b1c3d449fa83eb
parentb5c97a85ff2bbf6852d8b2a6e3ac6e61d957230f (diff)
downloadllvm-ba9b5964955e5dd6b28683b93da492950cc6d957.zip
llvm-ba9b5964955e5dd6b28683b93da492950cc6d957.tar.gz
llvm-ba9b5964955e5dd6b28683b93da492950cc6d957.tar.bz2
[m88k] Improve handling of G_SELECT
- Adds support for pointer type - Adds a test case It does not fix all problems. If the test case is run with -O1 instead of -O0 then the resulting generic machine instructions trigger a bug in the instruction selector.
-rw-r--r--llvm/lib/Target/M88k/GISel/M88kInstructionSelector.cpp2
-rw-r--r--llvm/lib/Target/M88k/GISel/M88kLegalizerInfo.cpp58
-rw-r--r--llvm/lib/Target/M88k/GISel/M88kRegisterBankInfo.cpp4
-rw-r--r--llvm/test/CodeGen/M88k/select.ll30
4 files changed, 75 insertions, 19 deletions
diff --git a/llvm/lib/Target/M88k/GISel/M88kInstructionSelector.cpp b/llvm/lib/Target/M88k/GISel/M88kInstructionSelector.cpp
index 97a4eb5..2b5de3b 100644
--- a/llvm/lib/Target/M88k/GISel/M88kInstructionSelector.cpp
+++ b/llvm/lib/Target/M88k/GISel/M88kInstructionSelector.cpp
@@ -1190,6 +1190,8 @@ bool M88kInstructionSelector::select(MachineInstr &I) {
return true;
switch (I.getOpcode()) {
+ case TargetOpcode::G_INTTOPTR:
+ case TargetOpcode::G_PTRTOINT:
case TargetOpcode::G_FREEZE:
return selectCopy(I, TII, MRI, TRI, RBI);
case TargetOpcode::G_INTRINSIC:
diff --git a/llvm/lib/Target/M88k/GISel/M88kLegalizerInfo.cpp b/llvm/lib/Target/M88k/GISel/M88kLegalizerInfo.cpp
index d03779e..a3fc93a 100644
--- a/llvm/lib/Target/M88k/GISel/M88kLegalizerInfo.cpp
+++ b/llvm/lib/Target/M88k/GISel/M88kLegalizerInfo.cpp
@@ -46,7 +46,8 @@ M88kLegalizerInfo::M88kLegalizerInfo(const M88kSubtarget &ST) {
getActionDefinitionsBuilder(G_PHI).legalFor({S32, P0});
getActionDefinitionsBuilder(G_SELECT)
- .customForCartesianProduct({S32, S64, P0}, {S1});
+ .customForCartesianProduct({S32, S64, P0}, {S1})
+ .clampScalar(0, S32, S64);
getActionDefinitionsBuilder({G_IMPLICIT_DEF, G_FREEZE})
.legalFor({S32, P0})
.clampScalar(0, S32, S32);
@@ -174,6 +175,7 @@ bool M88kLegalizerInfo::legalizeCustom(LegalizerHelper &Helper,
const LLT S1 = LLT::scalar(1);
const LLT S32 = LLT::scalar(32);
const LLT S64 = LLT::scalar(64);
+ const LLT P0 = LLT::pointer(0, 32);
switch (MI.getOpcode()) {
case G_FCONSTANT: {
@@ -269,7 +271,7 @@ bool M88kLegalizerInfo::legalizeCustom(LegalizerHelper &Helper,
// The instruction
// %4:_(s32) = G_SELECT %1:_(s32), %2:_(s32), %3:_(s32)
// is lowered to:
- // %5:_(s32) = G_SEXT_INREG %1:_(s32), 0
+ // %5:_(s32) = G_SEXT %1:_(s32)
// %6:_(s32) = G_AND %5:_(s32), %2:_(s32)
// %7:_(s32) = G_XOR %5:_(s32), -1
// %8:_(s32) = G_AND %5:_(s32), %3:_(s32)
@@ -277,36 +279,54 @@ bool M88kLegalizerInfo::legalizeCustom(LegalizerHelper &Helper,
//
// If one of the values to select is zero, then the G_AND belonging to that
// value is not generated.
+ // The pointer type require special care.
Register Dst = MI.getOperand(0).getReg();
Register Tst = MI.getOperand(1).getReg();
Register TVal = MI.getOperand(2).getReg();
Register FVal = MI.getOperand(3).getReg();
LLT DstTy = MRI.getType(Dst);
LLT TstTy = MRI.getType(Tst);
- //LLT TValTy = MRI.getType(TVal);
- //LLT FValy = MRI.getType(FVal);
- if (TstTy != S1)
- return false;
- if (DstTy != S32 && DstTy != S64)
- return false;
- int64_t Cst;
- bool MissT = mi_match(TVal, MRI, m_ICst(Cst)) && Cst == 0;
- bool MissF = mi_match(FVal, MRI, m_ICst(Cst)) && Cst == 0;
+
+ // The type used for the calculation. If the instruction operates on
+ // pointers then it is a scalar type of the same size as the pointer.
+ LLT Ty = DstTy.isPointer() ? LLT::scalar(DstTy.getSizeInBits()) : DstTy;
+
+ bool MissT = mi_match(TVal, MRI, m_ZeroInt());
+ bool MissF = mi_match(FVal, MRI, m_ZeroInt());
if (MissT && MissF) {
MIRBuilder.buildConstant(Dst, 0);
} else {
- auto Mask = MIRBuilder.buildSExtInReg(S32, Tst, 0);
+ Register Res = Dst;
+
+ // Convert pointers to integers if necessary.
+ if (DstTy.isPointer()) {
+ Res = MRI.createGenericVirtualRegister(Ty);
+ if (!MissT) {
+ Register Tmp = MRI.createGenericVirtualRegister(Ty);
+ MIRBuilder.buildPtrToInt(Tmp, TVal);
+ TVal = Tmp;
+ }
+ if (!MissF) {
+ Register Tmp = MRI.createGenericVirtualRegister(Ty);
+ MIRBuilder.buildPtrToInt(Tmp, FVal);
+ FVal = Tmp;
+ }
+ }
+
+ auto Mask = MIRBuilder.buildSExt(Ty, Tst);
if (MissF) {
- MIRBuilder.buildAnd(Dst, TVal, Mask);
+ MIRBuilder.buildAnd(Res, TVal, Mask);
} else if (MissT) {
- auto NegMask = MIRBuilder.buildNot(S32, Mask);
- MIRBuilder.buildAnd(Dst, FVal, NegMask);
+ auto NegMask = MIRBuilder.buildNot(Ty, Mask);
+ MIRBuilder.buildAnd(Res, FVal, NegMask);
} else {
- auto MaskT = MIRBuilder.buildAnd(S32, TVal, Mask);
- auto NegMask = MIRBuilder.buildNot(S32, Mask);
- auto MaskF = MIRBuilder.buildAnd(S32, FVal, NegMask);
- MIRBuilder.buildOr(Dst, MaskT, MaskF);
+ auto MaskT = MIRBuilder.buildAnd(Ty, TVal, Mask);
+ auto NegMask = MIRBuilder.buildNot(Ty, Mask);
+ auto MaskF = MIRBuilder.buildAnd(Ty, FVal, NegMask);
+ MIRBuilder.buildOr(Res, MaskT, MaskF);
}
+ if (DstTy.isPointer())
+ MIRBuilder.buildIntToPtr(Dst, Res);
}
MI.eraseFromParent();
break;
diff --git a/llvm/lib/Target/M88k/GISel/M88kRegisterBankInfo.cpp b/llvm/lib/Target/M88k/GISel/M88kRegisterBankInfo.cpp
index 36b2067..916fd11 100644
--- a/llvm/lib/Target/M88k/GISel/M88kRegisterBankInfo.cpp
+++ b/llvm/lib/Target/M88k/GISel/M88kRegisterBankInfo.cpp
@@ -285,6 +285,10 @@ M88kRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
getValueMapping(PMI_GR32),
getValueMapping(PMI_GR32)});
break;
+ case TargetOpcode::G_PTRTOINT:
+ case TargetOpcode::G_INTTOPTR:
+ OperandsMapping = getValueMapping(PMI_GR32);
+ break;
case TargetOpcode::G_SELECT:
// TODO FP not handled.
OperandsMapping = getOperandsMapping({getValueMapping(PMI_GR32),
diff --git a/llvm/test/CodeGen/M88k/select.ll b/llvm/test/CodeGen/M88k/select.ll
new file mode 100644
index 0000000..57c7c57
--- /dev/null
+++ b/llvm/test/CodeGen/M88k/select.ll
@@ -0,0 +1,30 @@
+; Test addition/subtraction.
+;
+; RUN: llc < %s -mtriple=m88k-openbsd -mcpu=mc88100 -O0 -verify-machineinstrs -m88k-enable-delay-slot-filler=false | FileCheck %s
+; RUN: llc < %s -mtriple=m88k-openbsd -mcpu=mc88110 -O0 -verify-machineinstrs -m88k-enable-delay-slot-filler=false | FileCheck %s
+
+define i32 @f1(i32 %a, i32 %b) {
+; CHECK-LABEL: f1:
+; CHECK: cmp %r4, %r2, %r3
+; CHECK-NEXT: ext %r4, %r4, 1<2>
+; CHECK-NEXT: and %r2, %r2, %r4
+; CHECK-NEXT: and.c %r3, %r3, %r4
+; CHECK-NEXT: or %r2, %r2, %r3
+; CHECK-NEXT: jmp %r1
+ %cmp = icmp eq i32 %a, %b
+ %res = select i1 %cmp, i32 %a, i32 %b
+ ret i32 %res
+}
+
+define ptr @f2(ptr %a, ptr %b) {
+; CHECK-LABEL: f2:
+; CHECK: cmp %r4, %r2, %r3
+; CHECK-NEXT: ext %r4, %r4, 1<2>
+; CHECK-NEXT: and %r2, %r2, %r4
+; CHECK-NEXT: and.c %r3, %r3, %r4
+; CHECK-NEXT: or %r2, %r2, %r3
+; CHECK-NEXT: jmp %r1
+ %cmp = icmp eq ptr %a, %b
+ %res = select i1 %cmp, ptr %a, ptr %b
+ ret ptr %res
+}