diff --git a/llvm/lib/Target/Mips/CMakeLists.txt b/llvm/lib/Target/Mips/CMakeLists.txt --- a/llvm/lib/Target/Mips/CMakeLists.txt +++ b/llvm/lib/Target/Mips/CMakeLists.txt @@ -61,6 +61,7 @@ MipsSubtarget.cpp MipsTargetMachine.cpp MipsTargetObjectFile.cpp + MipsTargetTransformInfo.cpp MicroMipsSizeReduction.cpp MipsMulMulBugPass.cpp diff --git a/llvm/lib/Target/Mips/MipsTargetMachine.cpp b/llvm/lib/Target/Mips/MipsTargetMachine.cpp --- a/llvm/lib/Target/Mips/MipsTargetMachine.cpp +++ b/llvm/lib/Target/Mips/MipsTargetMachine.cpp @@ -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 @@ } 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 diff --git a/llvm/lib/Target/Mips/MipsTargetTransformInfo.h b/llvm/lib/Target/Mips/MipsTargetTransformInfo.h new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/Mips/MipsTargetTransformInfo.h @@ -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 { + using BaseT = BasicTTIImplBase; + 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 diff --git a/llvm/lib/Target/Mips/MipsTargetTransformInfo.cpp b/llvm/lib/Target/Mips/MipsTargetTransformInfo.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/Mips/MipsTargetTransformInfo.cpp @@ -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); +} diff --git a/llvm/test/Transforms/DivRemPairs/Mips/div-expanded-rem-pair.ll b/llvm/test/Transforms/DivRemPairs/Mips/div-expanded-rem-pair.ll --- a/llvm/test/Transforms/DivRemPairs/Mips/div-expanded-rem-pair.ll +++ b/llvm/test/Transforms/DivRemPairs/Mips/div-expanded-rem-pair.ll @@ -7,8 +7,8 @@ ; 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 @@ ; 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 @@ 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 @@ ; 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 diff --git a/llvm/test/Transforms/DivRemPairs/Mips/div-rem-pairs.ll b/llvm/test/Transforms/DivRemPairs/Mips/div-rem-pairs.ll --- a/llvm/test/Transforms/DivRemPairs/Mips/div-rem-pairs.ll +++ b/llvm/test/Transforms/DivRemPairs/Mips/div-rem-pairs.ll @@ -5,12 +5,9 @@ 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_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 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 @@ 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 @@ ; 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