[Mips] Implement hasDivRemOp()

SDIVREM and UDIVREM can be customized lowered in MipsSE.

Fix https://github.com/llvm/llvm-project/issues/54991.

Reviewed By: sdardis

Differential Revision: https://reviews.llvm.org/D124980
This commit is contained in:
Jim Lin 2022-05-16 10:26:32 +08:00
parent 49b0c60542
commit 0a0d6489ef
6 changed files with 91 additions and 51 deletions

View File

@ -61,6 +61,7 @@ add_llvm_target(MipsCodeGen
MipsSubtarget.cpp
MipsTargetMachine.cpp
MipsTargetObjectFile.cpp
MipsTargetTransformInfo.cpp
MicroMipsSizeReduction.cpp
MipsMulMulBugPass.cpp

View File

@ -18,6 +18,7 @@
#include "MipsSEISelDAGToDAG.h"
#include "MipsSubtarget.h"
#include "MipsTargetObjectFile.h"
#include "MipsTargetTransformInfo.h"
#include "TargetInfo/MipsTargetInfo.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
@ -287,7 +288,7 @@ MipsTargetMachine::getTargetTransformInfo(const Function &F) const {
}
LLVM_DEBUG(errs() << "Target Transform Info Pass Added\n");
return TargetTransformInfo(BasicTTIImpl(this, F));
return TargetTransformInfo(MipsTTIImpl(this, F));
}
// Implemented by targets that want to run passes immediately before

View File

@ -0,0 +1,17 @@
//===-- MipsTargetTransformInfo.cpp - Mips specific TTI ----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "MipsTargetTransformInfo.h"
using namespace llvm;
bool MipsTTIImpl::hasDivRemOp(Type *DataType, bool IsSigned) {
EVT VT = TLI->getValueType(DL, DataType);
return TLI->isOperationLegalOrCustom(IsSigned ? ISD::SDIVREM : ISD::UDIVREM,
VT);
}

View File

@ -0,0 +1,40 @@
//===-- MipsTargetTransformInfo.h - Mips specific TTI -----------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_MIPS_MIPSTARGETTRANSFORMINFO_H
#define LLVM_LIB_TARGET_MIPS_MIPSTARGETTRANSFORMINFO_H
#include "MipsTargetMachine.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/CodeGen/BasicTTIImpl.h"
namespace llvm {
class MipsTTIImpl : public BasicTTIImplBase<MipsTTIImpl> {
using BaseT = BasicTTIImplBase<MipsTTIImpl>;
using TTI = TargetTransformInfo;
friend BaseT;
const MipsSubtarget *ST;
const MipsTargetLowering *TLI;
const MipsSubtarget *getST() const { return ST; }
const MipsTargetLowering *getTLI() const { return TLI; }
public:
explicit MipsTTIImpl(const MipsTargetMachine *TM, const Function &F)
: BaseT(TM, F.getParent()->getDataLayout()), ST(TM->getSubtargetImpl(F)),
TLI(ST->getTargetLowering()) {}
bool hasDivRemOp(Type *DataType, bool IsSigned);
};
} // end namespace llvm
#endif

View File

@ -7,8 +7,8 @@ define void @decompose_illegal_srem_same_block(i32 %a, i32 %b) {
; CHECK-LABEL: @decompose_illegal_srem_same_block(
; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[T0:%.*]] = mul i32 [[DIV]], [[B]]
; CHECK-NEXT: [[REM:%.*]] = sub i32 [[A]], [[T0]]
; CHECK-NEXT: call void @foo(i32 [[REM]], i32 [[DIV]])
; CHECK-NEXT: [[REM_RECOMPOSED:%.*]] = srem i32 [[A]], [[B]]
; CHECK-NEXT: call void @foo(i32 [[REM_RECOMPOSED]], i32 [[DIV]])
; CHECK-NEXT: ret void
;
%div = sdiv i32 %a, %b
@ -22,8 +22,8 @@ define void @decompose_illegal_urem_same_block(i32 %a, i32 %b) {
; CHECK-LABEL: @decompose_illegal_urem_same_block(
; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[T0:%.*]] = mul i32 [[DIV]], [[B]]
; CHECK-NEXT: [[REM:%.*]] = sub i32 [[A]], [[T0]]
; CHECK-NEXT: call void @foo(i32 [[REM]], i32 [[DIV]])
; CHECK-NEXT: [[REM_RECOMPOSED:%.*]] = urem i32 [[A]], [[B]]
; CHECK-NEXT: call void @foo(i32 [[REM_RECOMPOSED]], i32 [[DIV]])
; CHECK-NEXT: ret void
;
%div = udiv i32 %a, %b
@ -100,18 +100,13 @@ end:
define i32 @srem_of_srem_unexpanded(i32 %X, i32 %Y, i32 %Z) {
; CHECK-LABEL: @srem_of_srem_unexpanded(
; CHECK-NEXT: [[T0:%.*]] = mul nsw i32 [[Z:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[X_FROZEN:%.*]] = freeze i32 [[X:%.*]]
; CHECK-NEXT: [[T0_FROZEN:%.*]] = freeze i32 [[T0]]
; CHECK-NEXT: [[T1:%.*]] = sdiv i32 [[X_FROZEN]], [[T0_FROZEN]]
; CHECK-NEXT: [[T1:%.*]] = sdiv i32 [[X:%.*]], [[T0]]
; CHECK-NEXT: [[T2:%.*]] = mul nsw i32 [[T0]], [[T1]]
; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[T1]], [[T0_FROZEN]]
; CHECK-NEXT: [[T3_DECOMPOSED:%.*]] = sub i32 [[X_FROZEN]], [[TMP1]]
; CHECK-NEXT: [[Y_FROZEN:%.*]] = freeze i32 [[Y]]
; CHECK-NEXT: [[T4:%.*]] = sdiv i32 [[T3_DECOMPOSED]], [[Y_FROZEN]]
; CHECK-NEXT: [[T3:%.*]] = srem i32 [[X]], [[T0]]
; CHECK-NEXT: [[T4:%.*]] = sdiv i32 [[T3]], [[Y]]
; CHECK-NEXT: [[T5:%.*]] = mul nsw i32 [[T4]], [[Y]]
; CHECK-NEXT: [[TMP2:%.*]] = mul i32 [[T4]], [[Y_FROZEN]]
; CHECK-NEXT: [[T6_DECOMPOSED:%.*]] = sub i32 [[T3_DECOMPOSED]], [[TMP2]]
; CHECK-NEXT: ret i32 [[T6_DECOMPOSED]]
; CHECK-NEXT: [[T6:%.*]] = srem i32 [[T3]], [[Y]]
; CHECK-NEXT: ret i32 [[T6]]
;
%t0 = mul nsw i32 %Z, %Y
%t1 = sdiv i32 %X, %t0
@ -127,11 +122,11 @@ define i32 @srem_of_srem_expanded(i32 %X, i32 %Y, i32 %Z) {
; CHECK-NEXT: [[T0:%.*]] = mul nsw i32 [[Z:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[T1:%.*]] = sdiv i32 [[X:%.*]], [[T0]]
; CHECK-NEXT: [[T2:%.*]] = mul nsw i32 [[T0]], [[T1]]
; CHECK-NEXT: [[T3:%.*]] = sub nsw i32 [[X]], [[T2]]
; CHECK-NEXT: [[T4:%.*]] = sdiv i32 [[T3]], [[Y]]
; CHECK-NEXT: [[T3_RECOMPOSED:%.*]] = srem i32 [[X]], [[T0]]
; CHECK-NEXT: [[T4:%.*]] = sdiv i32 [[T3_RECOMPOSED]], [[Y]]
; CHECK-NEXT: [[T5:%.*]] = mul nsw i32 [[T4]], [[Y]]
; CHECK-NEXT: [[T6:%.*]] = sub nsw i32 [[T3]], [[T5]]
; CHECK-NEXT: ret i32 [[T6]]
; CHECK-NEXT: [[T6_RECOMPOSED:%.*]] = srem i32 [[T3_RECOMPOSED]], [[Y]]
; CHECK-NEXT: ret i32 [[T6_RECOMPOSED]]
;
%t0 = mul nsw i32 %Z, %Y
%t1 = sdiv i32 %X, %t0

View File

@ -5,12 +5,9 @@ declare void @foo(i32, i32)
define void @decompose_illegal_srem_same_block(i32 %a, i32 %b) {
; CHECK-LABEL: @decompose_illegal_srem_same_block(
; CHECK-NEXT: [[A_FROZEN:%.*]] = freeze i32 [[A:%.*]]
; CHECK-NEXT: [[B_FROZEN:%.*]] = freeze i32 [[B:%.*]]
; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[A_FROZEN]], [[B_FROZEN]]
; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[B_FROZEN]]
; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[A_FROZEN]], [[TMP1]]
; CHECK-NEXT: call void @foo(i32 [[REM_DECOMPOSED]], i32 [[DIV]])
; CHECK-NEXT: [[REM:%.*]] = srem i32 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[A]], [[B]]
; CHECK-NEXT: call void @foo(i32 [[REM]], i32 [[DIV]])
; CHECK-NEXT: ret void
;
%rem = srem i32 %a, %b
@ -21,12 +18,9 @@ define void @decompose_illegal_srem_same_block(i32 %a, i32 %b) {
define void @decompose_illegal_urem_same_block(i32 %a, i32 %b) {
; CHECK-LABEL: @decompose_illegal_urem_same_block(
; CHECK-NEXT: [[A_FROZEN:%.*]] = freeze i32 [[A:%.*]]
; CHECK-NEXT: [[B_FROZEN:%.*]] = freeze i32 [[B:%.*]]
; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[A_FROZEN]], [[B_FROZEN]]
; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[B_FROZEN]]
; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[A_FROZEN]], [[TMP1]]
; CHECK-NEXT: call void @foo(i32 [[REM_DECOMPOSED]], i32 [[DIV]])
; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[REM:%.*]] = urem i32 [[A]], [[B]]
; CHECK-NEXT: call void @foo(i32 [[REM]], i32 [[DIV]])
; CHECK-NEXT: ret void
;
%div = udiv i32 %a, %b
@ -41,12 +35,9 @@ define void @decompose_illegal_urem_same_block(i32 %a, i32 %b) {
define i32 @hoist_sdiv(i32 %a, i32 %b) {
; CHECK-LABEL: @hoist_sdiv(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[A_FROZEN:%.*]] = freeze i32 [[A:%.*]]
; CHECK-NEXT: [[B_FROZEN:%.*]] = freeze i32 [[B:%.*]]
; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[A_FROZEN]], [[B_FROZEN]]
; CHECK-NEXT: [[TMP0:%.*]] = mul i32 [[DIV]], [[B_FROZEN]]
; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[A_FROZEN]], [[TMP0]]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[REM_DECOMPOSED]], 42
; CHECK-NEXT: [[REM:%.*]] = srem i32 [[A:%.*]], [[B:%.*]]
; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[A]], [[B]]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[REM]], 42
; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]]
; CHECK: if:
; CHECK-NEXT: br label [[END]]
@ -169,18 +160,13 @@ end:
define i32 @srem_of_srem_unexpanded(i32 %X, i32 %Y, i32 %Z) {
; CHECK-LABEL: @srem_of_srem_unexpanded(
; CHECK-NEXT: [[T0:%.*]] = mul nsw i32 [[Z:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[X_FROZEN:%.*]] = freeze i32 [[X:%.*]]
; CHECK-NEXT: [[T0_FROZEN:%.*]] = freeze i32 [[T0]]
; CHECK-NEXT: [[T1:%.*]] = sdiv i32 [[X_FROZEN]], [[T0_FROZEN]]
; CHECK-NEXT: [[T1:%.*]] = sdiv i32 [[X:%.*]], [[T0]]
; CHECK-NEXT: [[T2:%.*]] = mul nsw i32 [[T0]], [[T1]]
; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[T1]], [[T0_FROZEN]]
; CHECK-NEXT: [[T3_DECOMPOSED:%.*]] = sub i32 [[X_FROZEN]], [[TMP1]]
; CHECK-NEXT: [[Y_FROZEN:%.*]] = freeze i32 [[Y]]
; CHECK-NEXT: [[T4:%.*]] = sdiv i32 [[T3_DECOMPOSED]], [[Y_FROZEN]]
; CHECK-NEXT: [[T3:%.*]] = srem i32 [[X]], [[T0]]
; CHECK-NEXT: [[T4:%.*]] = sdiv i32 [[T3]], [[Y]]
; CHECK-NEXT: [[T5:%.*]] = mul nsw i32 [[T4]], [[Y]]
; CHECK-NEXT: [[TMP2:%.*]] = mul i32 [[T4]], [[Y_FROZEN]]
; CHECK-NEXT: [[T6_DECOMPOSED:%.*]] = sub i32 [[T3_DECOMPOSED]], [[TMP2]]
; CHECK-NEXT: ret i32 [[T6_DECOMPOSED]]
; CHECK-NEXT: [[T6:%.*]] = srem i32 [[T3]], [[Y]]
; CHECK-NEXT: ret i32 [[T6]]
;
%t0 = mul nsw i32 %Z, %Y
%t1 = sdiv i32 %X, %t0
@ -196,11 +182,11 @@ define i32 @srem_of_srem_expanded(i32 %X, i32 %Y, i32 %Z) {
; CHECK-NEXT: [[T0:%.*]] = mul nsw i32 [[Z:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[T1:%.*]] = sdiv i32 [[X:%.*]], [[T0]]
; CHECK-NEXT: [[T2:%.*]] = mul nsw i32 [[T0]], [[T1]]
; CHECK-NEXT: [[T3:%.*]] = sub nsw i32 [[X]], [[T2]]
; CHECK-NEXT: [[T4:%.*]] = sdiv i32 [[T3]], [[Y]]
; CHECK-NEXT: [[T3_RECOMPOSED:%.*]] = srem i32 [[X]], [[T0]]
; CHECK-NEXT: [[T4:%.*]] = sdiv i32 [[T3_RECOMPOSED]], [[Y]]
; CHECK-NEXT: [[T5:%.*]] = mul nsw i32 [[T4]], [[Y]]
; CHECK-NEXT: [[T6:%.*]] = sub nsw i32 [[T3]], [[T5]]
; CHECK-NEXT: ret i32 [[T6]]
; CHECK-NEXT: [[T6_RECOMPOSED:%.*]] = srem i32 [[T3_RECOMPOSED]], [[Y]]
; CHECK-NEXT: ret i32 [[T6_RECOMPOSED]]
;
%t0 = mul nsw i32 %Z, %Y
%t1 = sdiv i32 %X, %t0