diff options
author | Kai Nacke <kai@redstar.de> | 2022-09-10 12:56:41 -0400 |
---|---|---|
committer | Kai Nacke <kai@redstar.de> | 2022-11-13 11:07:58 -0500 |
commit | ba9b5964955e5dd6b28683b93da492950cc6d957 (patch) | |
tree | 55508521a8c11c6de62fec00b8b1c3d449fa83eb | |
parent | b5c97a85ff2bbf6852d8b2a6e3ac6e61d957230f (diff) | |
download | llvm-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.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/Target/M88k/GISel/M88kLegalizerInfo.cpp | 58 | ||||
-rw-r--r-- | llvm/lib/Target/M88k/GISel/M88kRegisterBankInfo.cpp | 4 | ||||
-rw-r--r-- | llvm/test/CodeGen/M88k/select.ll | 30 |
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 +} |