FunctionPass *createPseudoProbeInserter();
/// Create IR Type Promotion pass. \see TypePromotion.cpp
- FunctionPass *createTypePromotionPass();
+ FunctionPass *createTypePromotionLegacyPass();
/// Add Flow Sensitive Discriminators. PassNum specifies the
/// sequence number of this pass (starting from 1).
--- /dev/null
+//===- TypePromotion.h ------------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// Defines an IR pass for type promotion.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_TYPEPROMOTION_H
+#define LLVM_CODEGEN_TYPEPROMOTION_H
+
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+
+class Function;
+class TargetMachine;
+
+class TypePromotionPass : public PassInfoMixin<TypePromotionPass> {
+private:
+ const TargetMachine *TM;
+
+public:
+ TypePromotionPass(const TargetMachine *TM): TM(TM) { }
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+};
+
+} // end namespace llvm
+
+#endif // LLVM_CODEGEN_TYPEPROMOTION_H
void initializeTLSVariableHoistLegacyPassPass(PassRegistry &);
void initializeTwoAddressInstructionPassPass(PassRegistry&);
void initializeTypeBasedAAWrapperPassPass(PassRegistry&);
-void initializeTypePromotionPass(PassRegistry&);
+void initializeTypePromotionLegacyPass(PassRegistry&);
void initializeUniformityInfoWrapperPassPass(PassRegistry &);
void initializeUnifyFunctionExitNodesLegacyPassPass(PassRegistry &);
void initializeUnifyLoopExitsLegacyPassPass(PassRegistry &);
TargetRegisterInfo.cpp
TargetSchedule.cpp
TargetSubtargetInfo.cpp
- TypePromotion.cpp
TwoAddressInstructionPass.cpp
+ TypePromotion.cpp
UnreachableBlockElim.cpp
ValueTypes.cpp
VLIWMachineScheduler.cpp
initializeTailDuplicatePass(Registry);
initializeTargetPassConfigPass(Registry);
initializeTwoAddressInstructionPassPass(Registry);
- initializeTypePromotionPass(Registry);
+ initializeTypePromotionLegacyPass(Registry);
initializeUnpackMachineBundlesPass(Registry);
initializeUnreachableBlockElimLegacyPassPass(Registry);
initializeUnreachableMachineBlockElimPass(Registry);
///
//===----------------------------------------------------------------------===//
+#include "llvm/CodeGen/TypePromotion.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/LoopInfo.h"
void Mutate();
};
-class TypePromotion : public FunctionPass {
+class TypePromotionImpl {
unsigned TypeSize = 0;
LLVMContext *Ctx = nullptr;
unsigned RegisterBitWidth = 0;
bool TryToPromote(Value *V, unsigned PromotedWidth, const LoopInfo &LI);
public:
+ bool run(Function &F, const TargetMachine *TM,
+ const TargetTransformInfo &TTI, const LoopInfo &LI);
+};
+
+class TypePromotionLegacy : public FunctionPass {
+public:
static char ID;
- TypePromotion() : FunctionPass(ID) {}
+ TypePromotionLegacy() : FunctionPass(ID) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<LoopInfoWrapperPass>();
Opc == Instruction::SRem || Opc == Instruction::SExt;
}
-bool TypePromotion::EqualTypeSize(Value *V) {
+bool TypePromotionImpl::EqualTypeSize(Value *V) {
return V->getType()->getScalarSizeInBits() == TypeSize;
}
-bool TypePromotion::LessOrEqualTypeSize(Value *V) {
+bool TypePromotionImpl::LessOrEqualTypeSize(Value *V) {
return V->getType()->getScalarSizeInBits() <= TypeSize;
}
-bool TypePromotion::GreaterThanTypeSize(Value *V) {
+bool TypePromotionImpl::GreaterThanTypeSize(Value *V) {
return V->getType()->getScalarSizeInBits() > TypeSize;
}
-bool TypePromotion::LessThanTypeSize(Value *V) {
+bool TypePromotionImpl::LessThanTypeSize(Value *V) {
return V->getType()->getScalarSizeInBits() < TypeSize;
}
/// return values because we only accept ones that guarantee a zeroext ret val.
/// Many arguments will have the zeroext attribute too, so those would be free
/// too.
-bool TypePromotion::isSource(Value *V) {
+bool TypePromotionImpl::isSource(Value *V) {
if (!isa<IntegerType>(V->getType()))
return false;
/// Return true if V will require any promoted values to be truncated for the
/// the IR to remain valid. We can't mutate the value type of these
/// instructions.
-bool TypePromotion::isSink(Value *V) {
+bool TypePromotionImpl::isSink(Value *V) {
// TODO The truncate also isn't actually necessary because we would already
// proved that the data value is kept within the range of the original data
// type. We currently remove any truncs inserted for handling zext sinks.
}
/// Return whether this instruction can safely wrap.
-bool TypePromotion::isSafeWrap(Instruction *I) {
+bool TypePromotionImpl::isSafeWrap(Instruction *I) {
// We can support a potentially wrapping instruction (I) if:
// - It is only used by an unsigned icmp.
// - The icmp uses a constant.
return false;
}
-bool TypePromotion::shouldPromote(Value *V) {
+bool TypePromotionImpl::shouldPromote(Value *V) {
if (!isa<IntegerType>(V->getType()) || isSink(V))
return false;
/// We disallow booleans to make life easier when dealing with icmps but allow
/// any other integer that fits in a scalar register. Void types are accepted
/// so we can handle switches.
-bool TypePromotion::isSupportedType(Value *V) {
+bool TypePromotionImpl::isSupportedType(Value *V) {
Type *Ty = V->getType();
// Allow voids and pointers, these won't be promoted.
/// Disallow casts other than zext and truncs and only allow calls if their
/// return value is zeroext. We don't allow opcodes that can introduce sign
/// bits.
-bool TypePromotion::isSupportedValue(Value *V) {
+bool TypePromotionImpl::isSupportedValue(Value *V) {
if (auto *I = dyn_cast<Instruction>(V)) {
switch (I->getOpcode()) {
default:
/// Check that the type of V would be promoted and that the original type is
/// smaller than the targeted promoted type. Check that we're not trying to
/// promote something larger than our base 'TypeSize' type.
-bool TypePromotion::isLegalToPromote(Value *V) {
+bool TypePromotionImpl::isLegalToPromote(Value *V) {
auto *I = dyn_cast<Instruction>(V);
if (!I)
return true;
return false;
}
-bool TypePromotion::TryToPromote(Value *V, unsigned PromotedWidth,
+bool TypePromotionImpl::TryToPromote(Value *V, unsigned PromotedWidth,
const LoopInfo &LI) {
Type *OrigTy = V->getType();
TypeSize = OrigTy->getPrimitiveSizeInBits().getFixedSize();
return true;
}
-bool TypePromotion::runOnFunction(Function &F) {
- if (skipFunction(F) || DisablePromotion)
+bool TypePromotionImpl::run(Function &F, const TargetMachine *TM,
+ const TargetTransformInfo &TTI,
+ const LoopInfo &LI) {
+ if (DisablePromotion)
return false;
LLVM_DEBUG(dbgs() << "IR Promotion: Running on " << F.getName() << "\n");
- auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
- if (!TPC)
- return false;
-
AllVisited.clear();
SafeToPromote.clear();
SafeWrap.clear();
bool MadeChange = false;
const DataLayout &DL = F.getParent()->getDataLayout();
- const TargetMachine &TM = TPC->getTM<TargetMachine>();
- const TargetSubtargetInfo *SubtargetInfo = TM.getSubtargetImpl(F);
+ const TargetSubtargetInfo *SubtargetInfo = TM->getSubtargetImpl(F);
const TargetLowering *TLI = SubtargetInfo->getTargetLowering();
- const TargetTransformInfo &TII =
- getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
- const LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
RegisterBitWidth =
- TII.getRegisterBitWidth(TargetTransformInfo::RGK_Scalar).getFixedSize();
+ TTI.getRegisterBitWidth(TargetTransformInfo::RGK_Scalar).getFixedSize();
Ctx = &F.getParent()->getContext();
// Return the preferred integer width of the instruction, or zero if we
return MadeChange;
}
-INITIALIZE_PASS_BEGIN(TypePromotion, DEBUG_TYPE, PASS_NAME, false, false)
-INITIALIZE_PASS_END(TypePromotion, DEBUG_TYPE, PASS_NAME, false, false)
+INITIALIZE_PASS_BEGIN(TypePromotionLegacy, DEBUG_TYPE, PASS_NAME, false, false)
+INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
+INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
+INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
+INITIALIZE_PASS_END(TypePromotionLegacy, DEBUG_TYPE, PASS_NAME, false, false)
+
+char TypePromotionLegacy::ID = 0;
-char TypePromotion::ID = 0;
+bool TypePromotionLegacy::runOnFunction(Function &F) {
+ if (skipFunction(F))
+ return false;
-FunctionPass *llvm::createTypePromotionPass() { return new TypePromotion(); }
+ auto *TPC = getAnalysisIfAvailable<TargetPassConfig>();
+ if (!TPC)
+ return false;
+
+ auto *TM = &TPC->getTM<TargetMachine>();
+ auto &TTI = getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
+ auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
+
+ TypePromotionImpl TP;
+ return TP.run(F, TM, TTI, LI);
+}
+
+FunctionPass *llvm::createTypePromotionLegacyPass() {
+ return new TypePromotionLegacy();
+}
+
+PreservedAnalyses TypePromotionPass::run(Function &F,
+ FunctionAnalysisManager &AM) {
+ auto &TTI = AM.getResult<TargetIRAnalysis>(F);
+ auto &LI = AM.getResult<LoopAnalysis>(F);
+ TypePromotionImpl TP;
+
+ bool Changed = TP.run(F, TM, TTI, LI);
+ if (!Changed)
+ return PreservedAnalyses::all();
+
+ PreservedAnalyses PA;
+ PA.preserveSet<CFGAnalyses>();
+ PA.preserve<LoopAnalysis>();
+ return PA;
+}
LINK_COMPONENTS
AggressiveInstCombine
Analysis
+ CodeGen
Core
Coroutines
IPO
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Analysis/TypeBasedAliasAnalysis.h"
#include "llvm/Analysis/UniformityAnalysis.h"
+#include "llvm/CodeGen/TypePromotion.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/PassManager.h"
FUNCTION_PASS("strip-gc-relocates", StripGCRelocates())
FUNCTION_PASS("structurizecfg", StructurizeCFGPass())
FUNCTION_PASS("tailcallelim", TailCallElimPass())
+FUNCTION_PASS("typepromotion", TypePromotionPass(TM))
FUNCTION_PASS("unify-loop-exits", UnifyLoopExitsPass())
FUNCTION_PASS("vector-combine", VectorCombinePass())
FUNCTION_PASS("verify", VerifierPass())
void AArch64PassConfig::addCodeGenPrepare() {
if (getOptLevel() != CodeGenOpt::None)
- addPass(createTypePromotionPass());
+ addPass(createTypePromotionLegacyPass());
TargetPassConfig::addCodeGenPrepare();
}
void ARMPassConfig::addCodeGenPrepare() {
if (getOptLevel() != CodeGenOpt::None)
- addPass(createTypePromotionPass());
+ addPass(createTypePromotionLegacyPass());
TargetPassConfig::addCodeGenPrepare();
}
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: opt -mtriple=aarch64-linux-gnu -type-promotion < %s | llc -mtriple=aarch64-linux-gnu -o - | FileCheck %s
+; RUN: opt -mtriple=aarch64-linux-gnu -passes=typepromotion < %s | llc -mtriple=aarch64-linux-gnu -o - | FileCheck %s
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -mtriple=aarch64 -type-promotion -verify -dce -S %s -o - | FileCheck %s
+; RUN: opt -mtriple=aarch64 -passes=typepromotion,verify,dce -S %s -o - | FileCheck %s
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -mtriple=aarch64 -type-promotion -verify -S %s -o - | FileCheck %s
+; RUN: opt -mtriple=aarch64 -passes=typepromotion,verify -S %s -o - | FileCheck %s
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -mtriple=aarch64 -type-promotion -verify -S %s -o - | FileCheck %s
+; RUN: opt -mtriple=aarch64 -passes=typepromotion,verify -S %s -o - | FileCheck %s
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -mtriple=aarch64 -type-promotion -verify -S %s -o - | FileCheck %s
+; RUN: opt -mtriple=aarch64 -passes=typepromotion,verify -S %s -o - | FileCheck %s
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
; Function Attrs: mustprogress nofree nosync nounwind uwtable
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -type-promotion -mtriple=aarch64 %s -o - | FileCheck %s
+; RUN: opt -S -passes=typepromotion -mtriple=aarch64 %s -o - | FileCheck %s
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64"
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -mtriple=aarch64-linux-gnu -type-promotion -verify -S %s -o - | FileCheck %s
+; RUN: opt -mtriple=aarch64-linux-gnu -passes=typepromotion,verify -S %s -o - | FileCheck %s
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -mtriple=aarch64 -type-promotion -verify -S %s -o - | FileCheck %s
+; RUN: opt -mtriple=aarch64 -passes=typepromotion,verify -S %s -o - | FileCheck %s
define dso_local void @foo(ptr nocapture noundef readonly %a, ptr nocapture noundef readonly %b, ptr nocapture noundef writeonly %c, i64 noundef %n) local_unnamed_addr {
; CHECK-LABEL: @foo(
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -mtriple=arm -type-promotion -verify -disable-type-promotion=false -S %s -o - | FileCheck %s
+; RUN: opt -mtriple=arm -passes=typepromotion,verify -S %s -o - | FileCheck %s
define i8 @call_with_imms(i8* %arg) {
; CHECK-LABEL: @call_with_imms(
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -mtriple=arm -type-promotion -verify -disable-type-promotion=false -S %s -o - | FileCheck %s
+; RUN: opt -mtriple=arm -passes=typepromotion,verify -S %s -o - | FileCheck %s
define i16 @dsp_trunc(i32 %arg0, i32 %arg1, i16* %gep0, i16* %gep1) {
; CHECK-LABEL: @dsp_trunc(
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -mtriple=arm -type-promotion -verify -disable-type-promotion=false -S %s -o - | FileCheck %s
+; RUN: opt -mtriple=arm -passes=typepromotion,verify -S %s -o - | FileCheck %s
define i32 @clear_structures(i8* nocapture readonly %fmt, [1 x i32] %ap.coerce, i8* %out, void (i32, i8*)* nocapture %write) {
; CHECK-LABEL: @clear_structures(
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -mtriple=arm -type-promotion -verify -disable-type-promotion=false -S %s -o - | FileCheck %s
+; RUN: opt -mtriple=arm -passes=typepromotion,verify -S %s -o - | FileCheck %s
define i32 @test_ult_254_inc_imm(i8 zeroext %x) {
; CHECK-LABEL: @test_ult_254_inc_imm(
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -mtriple=thumbv7 -type-promotion -disable-type-promotion=false -S %s -o - | FileCheck %s
+; RUN: opt -mtriple=thumbv7 -passes=typepromotion -S %s -o - | FileCheck %s
define hidden void @dont_promote_large_int(i8* %in, i64* %out) {
; CHECK-LABEL: @dont_promote_large_int(
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -mtriple=arm -type-promotion -verify -S %s -o - | FileCheck %s
+; RUN: opt -mtriple=arm -passes=typepromotion,verify -S %s -o - | FileCheck %s
; Function Attrs: mustprogress nofree nosync nounwind uwtable
define dso_local void @foo(ptr noundef %ptr0, ptr nocapture noundef readonly %ptr1, ptr nocapture noundef %dest) local_unnamed_addr {
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -mtriple=arm -type-promotion -verify -S %s -o - | FileCheck %s
+; RUN: opt -mtriple=arm -passes=typepromotion,verify -S %s -o - | FileCheck %s
; Function Attrs: mustprogress nofree nosync nounwind uwtable
define dso_local void @foo(ptr noundef %ptr0, ptr nocapture noundef readonly %ptr1, ptr nocapture noundef %dest) local_unnamed_addr {
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -mtriple=arm -type-promotion -verify -disable-type-promotion=false -S %s -o - | FileCheck %s
+; RUN: opt -mtriple=arm -passes=typepromotion,verify -S %s -o - | FileCheck %s
; Check that the arguments are extended but then nothing else is.
; This also ensures that the pass can handle loops.
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -mtriple=arm -type-promotion -verify -disable-type-promotion=false -S %s -o - | FileCheck %s
+; RUN: opt -mtriple=arm -passes=typepromotion,verify -S %s -o - | FileCheck %s
define void @phi_pointers(i16* %a, i16* %b, i8 zeroext %M, i8 zeroext %N) {
; CHECK-LABEL: @phi_pointers(
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -mtriple=arm -type-promotion -verify -disable-type-promotion=false -S %s -o - | FileCheck %s
+; RUN: opt -mtriple=arm -passes=typepromotion,verify -S %s -o - | FileCheck %s
define i8 @eq_sgt(i8* %x, i8 *%y, i8 zeroext %z) {
; CHECK-LABEL: @eq_sgt(
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -mtriple=arm -type-promotion -verify -disable-type-promotion=false -S %s -o - | FileCheck %s
+; RUN: opt -mtriple=arm -passes=typepromotion,verify -S %s -o - | FileCheck %s
; Test to check that ARMCodeGenPrepare doesn't optimised away sign extends.
define i16 @test_signed_load(i16* %ptr) {
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -mtriple=arm -type-promotion -verify -disable-type-promotion=false -S %s -o - | FileCheck %s
+; RUN: opt -mtriple=arm -passes=typepromotion,verify -S %s -o - | FileCheck %s
define void @truncate_source_phi_switch(i8* %memblock, i8* %store, i16 %arg) {
; CHECK-LABEL: @truncate_source_phi_switch(
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -mtriple=arm -type-promotion -verify -disable-type-promotion=false -S %s -o - | FileCheck %s
+; RUN: opt -mtriple=arm -passes=typepromotion,verify -S %s -o - | FileCheck %s
define zeroext i16 @overflow_add(i16 zeroext %a, i16 zeroext %b) {
; CHECK-LABEL: @overflow_add(
"atomic-expand",
"expandvp",
"hardware-loops",
- "type-promotion",
"mve-tail-predication",
"interleaved-access",
"global-merge",
initializeWasmEHPreparePass(Registry);
initializeWriteBitcodePassPass(Registry);
initializeHardwareLoopsPass(Registry);
- initializeTypePromotionPass(Registry);
initializeReplaceWithVeclibLegacyPass(Registry);
initializeJMCInstrumenterPass(Registry);